/* Sectioned stylesheet, scoped by class name (no global element selectors). */

/* 1. Tokens & reset */

:root {
  --bg: #0e0f12;
  --bg-soft: #15171c;
  --bg-elev: #1c1f26;
  --bg-elev-hover: #232730;
  --border: #2a2f3a;
  --border-strong: #3a4150;
  --text: #f4f5f7;
  --text-soft: #b8bdc7;
  --text-muted: #7d8390;
  --accent: #ff9500;
  --accent-soft: rgba(255, 149, 0, 0.18);
  --danger: #ff6a75;
  --success: #34d399;
  --warn: #f59e0b;

  --radius-sm: 8px;
  --radius: 14px;
  --radius-lg: 22px;

  --shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.35);
  --shadow-lg: 0 16px 48px rgba(0, 0, 0, 0.45);

  --font-stack: -apple-system, BlinkMacSystemFont, "Segoe UI", "SF Pro Text",
    "Inter", system-ui, sans-serif;

  --transition-fast: 0.18s ease;
  --transition: 0.25s ease;
}

/* ?theme= (set by the desktop app) overrides the OS preference below. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) {
    --bg: #f6f7fa;
    --bg-soft: #eceff5;
    --bg-elev: #ffffff;
    --bg-elev-hover: #f0f3fa;
    --border: #d8dde6;
    --border-strong: #b9c0cd;
    --text: #1c2028;
    --text-soft: #4a525f;
    --text-muted: #7e8695;
    --shadow-sm: 0 2px 8px rgba(20, 25, 40, 0.08);
    --shadow-lg: 0 16px 48px rgba(20, 25, 40, 0.18);
  }
}

:root[data-theme="light"] {
  --bg: #f6f7fa;
  --bg-soft: #eceff5;
  --bg-elev: #ffffff;
  --bg-elev-hover: #f0f3fa;
  --border: #d8dde6;
  --border-strong: #b9c0cd;
  --text: #1c2028;
  --text-soft: #4a525f;
  --text-muted: #7e8695;
  --shadow-sm: 0 2px 8px rgba(20, 25, 40, 0.08);
  --shadow-lg: 0 16px 48px rgba(20, 25, 40, 0.18);
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-stack);
  font-size: 16px;
  line-height: 1.5;
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  display: flex;
  flex-direction: column;
}

a {
  color: inherit;
}

button {
  font-family: inherit;
}

/* 2. App shell */

.app-shell__header {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 24px;
  background: color-mix(in srgb, var(--bg) 85%, transparent);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border-bottom: 1px solid var(--border);
}

.app-shell__brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  color: var(--text);
  font-weight: 600;
  letter-spacing: 0.2px;
  border-radius: var(--radius-sm);
  padding: 4px 6px;
  transition: background var(--transition-fast);
}

.app-shell__brand:hover {
  background: var(--bg-elev);
}

/* SVG offset upward so the head sits centered in the disc, not the body. */
.app-shell__brand-mark {
  position: relative;
  display: inline-block;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--bg-soft);
  overflow: visible;
  flex-shrink: 0;
}

.app-shell__brand-mark img {
  position: absolute;
  width: 140%;
  height: auto;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -57%);
  pointer-events: none;
  user-select: none;
  -webkit-user-drag: none;
  display: block;
}

.app-shell__brand-text {
  font-size: 0.95rem;
}

/* Lets the Back button toggle via `hidden` without shifting the brand. */
.app-shell__lead {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

/* Fixed below the topbar, outside the header, so the lead/gear layout
   stays untouched. Borderless so it reads as a label, not a control. */
.app-shell__personality {
  position: fixed;
  top: 90px;
  left: 32px;
  z-index: 9;
  display: inline-flex;
  align-items: center;
  gap: 16px;
  padding: 8px 12px;
  margin: -8px -12px;
  background: transparent;
  border: 0;
  border-radius: 16px;
  min-width: 0;
  max-width: 320px;
  font: inherit;
  color: inherit;
  cursor: pointer;
  appearance: none;
  transition: background 0.15s ease;
}

.app-shell__personality:hover {
  background: var(--bg-soft);
}

.app-shell__personality:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.app-shell__personality[hidden] {
  display: none;
}

.app-shell__personality-text {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  min-width: 0;
  line-height: 1.2;
}

.app-shell__personality-label {
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.app-shell__personality-name {
  font-size: 1.35rem;
  font-weight: 700;
  color: var(--text);
  letter-spacing: -0.3px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 260px;
}

/* Larger than the brand mark for presence outside the topbar. */
.app-shell__personality-avatar {
  position: relative;
  display: inline-block;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: var(--bg-soft);
  overflow: visible;
  flex-shrink: 0;
}

.app-shell__personality-avatar img {
  position: absolute;
  width: 140%;
  height: auto;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -57%);
  pointer-events: none;
  user-select: none;
  -webkit-user-drag: none;
  display: block;
}

/* Shared by the Back and gear buttons so both read as the same control. */
.app-shell__icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border: 1px solid var(--border);
  background: var(--bg-elev);
  color: var(--text-soft);
  border-radius: 50%;
  cursor: pointer;
  padding: 0;
  transition: color var(--transition-fast), background var(--transition-fast),
    border-color var(--transition-fast), transform var(--transition-fast);
}

.app-shell__icon-btn[hidden] {
  display: none;
}

.app-shell__icon-btn svg {
  width: 18px;
  height: 18px;
}

.app-shell__icon-btn:hover {
  color: var(--text);
  background: var(--bg-elev-hover);
  border-color: var(--border-strong);
}

.app-shell__icon-btn:active {
  transform: scale(0.96);
}

.app-shell__icon-btn:focus-visible,
.app-shell__brand:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Accent tint + rotation signal the gear also closes Settings when active. */
.app-shell__gear.is-active {
  color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 60%, transparent);
  background: color-mix(in srgb, var(--accent) 14%, var(--bg-elev));
}

.app-shell__gear.is-active svg {
  transform: rotate(60deg);
  transition: transform var(--transition);
}

.app-shell__outlet {
  flex: 1 1 auto;
  width: 100%;
  max-width: 1080px;
  margin: 0 auto;
  padding: 32px 24px 64px;
  /* Flex column so the Talk view can claim full height via flex:1 and
     center vertically; other views just sit at the top. */
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* 3. Generic primitives */

.view-header {
  margin-bottom: 28px;
}

.view-title {
  margin: 0 0 6px;
  font-size: 1.6rem;
  font-weight: 600;
  letter-spacing: -0.01em;
}

.view-subtitle {
  margin: 0;
  color: var(--text-soft);
}

.view-status {
  margin-top: 18px;
  color: var(--text-muted);
  font-size: 0.9rem;
}

.view-status.is-warning {
  color: var(--warn);
}

.view-status.is-error {
  color: var(--danger);
}

.view-error {
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius);
  padding: 16px;
  background: var(--bg-elev);
}

.muted {
  color: var(--text-muted);
}

.muted.small {
  font-size: 0.85rem;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: 1px solid transparent;
  background: var(--bg-elev);
  color: var(--text);
  font-size: 0.95rem;
  font-weight: 500;
  padding: 10px 16px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background var(--transition-fast), border-color var(--transition-fast),
    transform var(--transition-fast);
}

.btn:hover:not(:disabled) {
  background: var(--bg-elev-hover);
}

.btn:active:not(:disabled) {
  transform: scale(0.98);
}

.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.btn--primary {
  background: var(--accent);
  color: #1a0f00;
  font-weight: 600;
}

.btn--primary:hover:not(:disabled) {
  background: color-mix(in srgb, var(--accent) 90%, white);
}

.btn--ghost {
  background: transparent;
  border-color: var(--border);
  color: var(--text-soft);
}

.btn--ghost:hover:not(:disabled) {
  border-color: var(--border-strong);
  color: var(--text);
}

.route-error {
  margin: 32px;
  padding: 16px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--danger);
  background: color-mix(in srgb, var(--danger) 12%, transparent);
  color: var(--text);
}

/* 4. Home view - personality grid */

.view--home .personality-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 18px;
}

/* Slot wraps a card button + its (optional) edit button so the edit control
   is a sibling, never a <button> nested inside the card button. */
.personality-card-slot {
  position: relative;
  display: flex;
}

.personality-card-slot .personality-card {
  flex: 1;
  width: 100%;
}

.personality-card__edit {
  position: absolute;
  top: 8px;
  right: 8px;
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--bg-soft);
  color: var(--text-muted);
  box-shadow: inset 0 0 0 1px var(--border);
  cursor: pointer;
  opacity: 0.55;
  transition: opacity var(--transition-fast), background var(--transition-fast),
    color var(--transition-fast);
}

.personality-card-slot:hover .personality-card__edit,
.personality-card__edit:focus-visible {
  opacity: 1;
}

.personality-card__edit:hover {
  background: var(--bg-elev-hover);
  color: var(--text);
}

.personality-card__edit svg {
  width: 15px;
  height: 15px;
}

.personality-card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  gap: 12px;
  min-height: 196px;
  padding: 20px 16px 18px;
  background: var(--bg-elev);
  border: 0;
  border-radius: var(--radius);
  /* Hairline border via inset shadow stays crisp where 1px CSS borders
     anti-alias, especially at non-integer device pixel ratios. */
  box-shadow: inset 0 0 0 1px var(--border);
  cursor: pointer;
  color: inherit;
  text-align: center;
  font: inherit;
  transition: background var(--transition-fast), box-shadow var(--transition-fast),
    transform 0.1s ease;
  -webkit-tap-highlight-color: transparent;
}

.personality-card:hover:not(:disabled) {
  background: var(--bg-elev-hover);
}

.personality-card:active:not(:disabled) {
  transform: scale(0.97);
}

.personality-card:focus-visible {
  box-shadow:
    inset 0 0 0 2px var(--accent),
    0 0 0 3px color-mix(in srgb, var(--accent) 30%, transparent);
  outline: none;
}

.personality-card.is-active {
  background: color-mix(in srgb, var(--accent) 8%, var(--bg-elev));
  box-shadow: inset 0 0 0 2px var(--accent);
}

.personality-card.is-active:hover:not(:disabled) {
  background: color-mix(in srgb, var(--accent) 12%, var(--bg-elev));
}

.personality-card.is-disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* overflow: visible - avatars are full-body illustrations anchored on the
   head; antennas/hats spill above the disc rim. */
.personality-card__avatar {
  position: relative;
  width: 110px;
  height: 110px;
  border-radius: 50%;
  background: var(--bg-soft);
  overflow: visible;
  flex-shrink: 0;
}

.personality-card__avatar img {
  position: absolute;
  width: 140%;
  height: auto;
  left: 50%;
  top: 50%;
  /* Slight upward bias so the SVG's "head" lands at disc center while
     the antennas escape above. */
  transform: translate(-50%, -57%);
  pointer-events: none;
  user-select: none;
  -webkit-user-drag: none;
  display: block;
}

.personality-card__avatar img.personality-card__avatar--fallback {
  opacity: 0.7;
}

.personality-card__name {
  font-weight: 600;
  font-size: 0.95rem;
  line-height: 1.2;
  color: var(--text);
  width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.personality-card.is-active .personality-card__name {
  color: var(--accent);
}

/* Outlined, not filled - the wash + ring + tinted name already signal
   "selected". */
.personality-card__badge {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 22px;
  height: 22px;
  padding: 0;
  border-radius: 50%;
  background: var(--bg-elev);
  color: var(--accent);
  display: grid;
  place-items: center;
  box-shadow: inset 0 0 0 2px var(--accent);
}

.personality-card__badge svg {
  width: 12px;
  height: 12px;
}

.personality-card--custom {
  background: transparent;
  box-shadow: inset 0 0 0 1px transparent;
  /* Dashed insets aren't a thing, so use a real border to override the shadow. */
  border: 1px dashed var(--border-strong);
}

.personality-card--custom:hover:not(:disabled) {
  background: var(--bg-elev);
  border-color: var(--accent);
}

.personality-card__plus {
  width: 110px;
  height: 110px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 2.6rem;
  font-weight: 300;
  color: var(--text-soft);
  background: var(--bg-soft);
}

.personality-card__hint {
  color: var(--text-muted);
  font-size: 0.78rem;
}

/* 5. Talk view - history sidebar + conversation pane */

/* Two-pane: history sidebar on the left, conversation on the right.
   flex: 1 claims the outlet's remaining height so the panes can scroll. */
/* App-shell layout for the conversation: the page itself never scrolls, the
   transcript scrolls inside its own pane, so the composer and mic stay put. */
body:has(.view--talk) {
  height: 100vh;
  overflow: hidden;
}

/* Column: a slim mode bar on top, then the sidebar and conversation side by side. */
.view--talk {
  display: flex;
  flex: 1;
  flex-direction: column;
  min-height: 0;
  height: 100%;
}

.talk__panes {
  display: flex;
  flex: 1;
  flex-direction: row;
  align-items: stretch;
  gap: 20px;
  min-height: 0;
}

/* Free conversation is not a lesson, so it gets its own bar. */
.talk__topbar {
  flex: none;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 16px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-soft);
}

.talk__topbar-item {
  padding: 6px 14px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--bg-elev);
  color: var(--text-soft);
  font-family: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast),
    border-color var(--transition-fast);
}

.talk__topbar-item:hover {
  background: var(--bg-elev-hover);
  color: var(--text);
}

.talk__topbar-item.is-active {
  background: var(--accent-soft);
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
  color: var(--text);
}

.talk__topbar-item[hidden] {
  display: none;
}

.talk__reconnect {
  padding: 6px 14px;
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--danger) 55%, transparent);
  background: color-mix(in srgb, var(--danger) 14%, transparent);
  color: var(--text);
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: 600;
  cursor: pointer;
}

.talk__reconnect:hover:not(:disabled) {
  background: color-mix(in srgb, var(--danger) 22%, transparent);
}

.talk__reconnect:disabled {
  opacity: 0.7;
  cursor: default;
}

.talk__reconnect[hidden] {
  display: none;
}

.talk__topbar-spacer {
  flex: 1;
}

.talk__whoami {
  color: var(--text-muted);
  font-size: 0.8rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 40%;
}

.talk__signout {
  border: 0;
  background: transparent;
  color: var(--text-muted);
  font-family: inherit;
  font-size: 0.8rem;
  cursor: pointer;
  padding: 4px 6px;
  border-radius: var(--radius-sm);
}

.talk__signout:hover {
  color: var(--text);
  background: var(--bg-elev);
}

/* Landing page: sign in and pick a robot. */
.view--login {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 1;
  padding: 24px;
}

.login__card {
  width: min(420px, 100%);
  padding: 30px 30px 26px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}

.login__title {
  margin: 0 0 4px;
  font-size: 1.6rem;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.login__subtitle {
  margin: 0 0 20px;
  color: var(--text-soft);
}

.login__status {
  margin: 0;
  min-height: 1.2em;
  font-size: 0.85rem;
  color: var(--warn);
}

.login__proceed {
  width: 100%;
  padding: 12px;
  font-size: 1rem;
}

/* The landing page stands alone, without the app chrome. */
body.is-login .app-shell__trail,
body.is-login .app-shell__back {
  display: none;
}

/* Sidebar: persona header + new-chat button + saved chat history */
.talk__sidebar {
  display: flex;
  flex-direction: column;
  width: 244px;
  flex-shrink: 0;
  gap: 14px;
  padding: 16px;
  background: var(--bg-soft);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  min-height: 0;
  height: 100%;
  overflow-y: auto;
}

/* Study control condition: hide the embodiment cues, keep the transcript. */
.view--talk.is-text-only .talk__camera-wrap,
.view--talk.is-text-only .talk__mic {
  display: none;
}

.talk__mode {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  padding: 10px 0 12px;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  user-select: none;
}

.talk__mode input {
  margin-top: 2px;
  accent-color: var(--accent);
  cursor: pointer;
  flex-shrink: 0;
}

.talk__mode-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.talk__mode-title {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text);
}

.talk__mode-hint {
  font-size: 0.74rem;
  line-height: 1.3;
  color: var(--text-muted);
}

.talk__persona {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--border);
}

.talk__persona-avatar {
  position: relative;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: var(--bg-elev);
  overflow: visible;
  flex-shrink: 0;
}

.talk__persona-avatar img {
  position: absolute;
  width: 140%;
  height: auto;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -57%);
  pointer-events: none;
  user-select: none;
  -webkit-user-drag: none;
  display: block;
}

.talk__persona-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
  line-height: 1.2;
}

.talk__persona-label {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.talk__persona-name {
  font-size: 1.08rem;
  font-weight: 700;
  color: var(--text);
  letter-spacing: -0.2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Learning scenario selector */
.talk__scenario {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border);
}

.talk__scenario-label {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.talk__scenario-select {
  width: 100%;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--bg-elev);
  color: var(--text);
  font-family: inherit;
  font-size: 0.88rem;
  cursor: pointer;
}

.talk__scenario-select:focus {
  outline: none;
  border-color: var(--accent);
}

.talk__scenario-note {
  margin: 0;
  font-size: 0.78rem;
  line-height: 1.35;
  color: var(--text-muted);
}

/* Curriculum list: one clickable row per task, in lesson order. */
.talk__curriculum {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 0 -4px;
}

.talk__task {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 7px 8px;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-soft);
  font-family: inherit;
  font-size: 0.85rem;
  text-align: left;
  cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast);
}

.talk__task:hover {
  background: var(--bg-elev);
  color: var(--text);
}

.talk__task.is-active {
  background: var(--accent-soft);
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
  color: var(--text);
  font-weight: 600;
}

.talk__task-num {
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--bg-elev);
  color: var(--text-muted);
  font-size: 0.72rem;
  font-weight: 700;
}

.talk__task.is-active .talk__task-num {
  background: var(--accent);
  color: #1a0f00;
}

.talk__task-title {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Tool buttons stay neutral: the accent tint is reserved for the active task,
   otherwise a permanent highlight here reads as "currently selected". */
.talk__session-btn {
  width: 100%;
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong);
  background: var(--bg-elev);
  color: var(--text-soft);
  font-family: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast);
}

.talk__session-btn:hover {
  background: var(--bg-elev-hover);
  color: var(--text);
}

.talk__control-btn {
  width: 100%;
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong);
  background: var(--bg-elev);
  color: var(--text-soft);
  font-family: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast);
}

.talk__control-btn:hover {
  background: var(--bg-elev-hover);
  color: var(--text);
}

/* Header: power icon sits beside the gear */
.app-shell__trail {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

/* Help page */
.view--help {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.help__steps {
  margin: 0;
  padding-left: 22px;
}

.help__steps li {
  margin-bottom: 6px;
  line-height: 1.45;
}

.help__rows {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.help__row {
  display: grid;
  grid-template-columns: 220px 1fr;
  gap: 14px;
  align-items: start;
  line-height: 1.45;
}

.help__row-label {
  font-weight: 600;
  color: var(--text-soft);
}

@media (max-width: 620px) {
  .help__row {
    grid-template-columns: 1fr;
    gap: 2px;
  }
}

/* Robot panel: power, network, sound */
.robot__power-state {
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 0 0 6px;
  font-weight: 600;
}

.robot__dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--text-muted);
  flex-shrink: 0;
}

.robot__dot.is-on {
  background: var(--success);
  box-shadow: 0 0 8px color-mix(in srgb, var(--success) 60%, transparent);
}

.robot__networks {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 8px 0;
}

.robot__known,
.robot__network {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 11px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--bg-soft);
  color: var(--text-soft);
  font-size: 0.85rem;
  font-family: inherit;
  cursor: pointer;
}

.robot__network:hover {
  border-color: var(--accent);
  color: var(--text);
}

.robot__known.is-current {
  border-color: color-mix(in srgb, var(--success) 55%, transparent);
  background: color-mix(in srgb, var(--success) 12%, var(--bg-soft));
  color: var(--text);
  cursor: default;
}

.robot__forget {
  border: 0;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  font-size: 1rem;
  line-height: 1;
  padding: 0 2px;
}

.robot__forget:hover {
  color: var(--danger);
}

.robot__slider-row {
  display: grid;
  grid-template-columns: 110px 1fr 52px;
  align-items: center;
  gap: 12px;
  margin-bottom: 10px;
}

.robot__slider-label {
  color: var(--text-soft);
  font-size: 0.9rem;
}

.robot__slider {
  width: 100%;
  accent-color: var(--accent);
  cursor: pointer;
}

.robot__level {
  text-align: right;
  color: var(--text-muted);
  font-size: 0.85rem;
}

@media (max-width: 620px) {
  .robot__slider-row {
    grid-template-columns: 1fr;
    gap: 4px;
  }
}

/* Control panel (Task 3) */
.view--control {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.control__actions {
  display: flex;
  gap: 8px;
}

.control__status {
  margin: 0;
  min-height: 1.3em;
  color: var(--text-soft);
  font-size: 0.9rem;
}

.control__body {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.control__meter {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}

.control__meter-label {
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 700;
  color: #1a0f00;
  background: var(--danger);
}

.control__meter-label.is-score-2 {
  background: var(--warn);
}

.control__meter-label.is-score-3,
.control__meter-label.is-score-4 {
  background: var(--success);
}

.control__moves {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.control__moves .btn {
  text-transform: capitalize;
}

.control__log {
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-height: 40vh;
  overflow-y: auto;
}

.control__attempt {
  display: grid;
  grid-template-columns: 170px 90px 1fr;
  gap: 10px;
  padding: 6px 8px;
  border-radius: var(--radius-sm);
  font-size: 0.88rem;
}

.control__attempt.is-ok {
  background: color-mix(in srgb, var(--success) 12%, transparent);
}

.control__attempt.is-fail {
  background: color-mix(in srgb, var(--danger) 10%, transparent);
}

.control__attempt-result {
  font-weight: 600;
  text-transform: capitalize;
}

@media (max-width: 620px) {
  .control__attempt {
    grid-template-columns: 1fr;
    gap: 2px;
  }
}

/* Session view: reveal panel + transcript */
.view--session {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.session__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.session__heading {
  margin: 12px 0 0;
  font-size: 1.1rem;
  font-weight: 600;
}

.session__banner {
  padding: 14px 16px;
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--warn) 14%, var(--bg-elev));
  border: 1px solid color-mix(in srgb, var(--warn) 45%, transparent);
  margin-bottom: 12px;
  line-height: 1.45;
}

.session__insights {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.session__finding {
  display: grid;
  grid-template-columns: 170px 1fr;
  gap: 14px;
  padding: 12px 14px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

.session__finding-label {
  font-weight: 600;
  color: var(--text-soft);
  font-size: 0.9rem;
}

.session__finding-disclosed {
  font-size: 1rem;
  color: var(--text);
  margin-bottom: 4px;
}

.session__finding-question {
  margin-top: 8px;
  font-size: 0.9rem;
  color: var(--text);
}

.session__finding-tag {
  display: inline-block;
  margin-right: 8px;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--accent);
  color: #1a0f00;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.session__transcript {
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-height: 46vh;
  overflow-y: auto;
  padding: 12px 14px;
  background: var(--bg-soft);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

.session__turn {
  display: grid;
  grid-template-columns: 74px 84px 1fr;
  gap: 10px;
  padding: 5px 0;
  border-bottom: 1px solid color-mix(in srgb, var(--border) 60%, transparent);
  font-size: 0.9rem;
  line-height: 1.4;
}

.session__turn-role {
  font-weight: 600;
  color: var(--text-muted);
  text-transform: capitalize;
}

.session__turn--user .session__turn-role {
  color: var(--accent);
}

.session__turn--camera .session__turn-role {
  color: var(--success);
}

.session__turn-content {
  word-break: break-word;
}

@media (max-width: 620px) {
  .session__finding,
  .session__turn {
    grid-template-columns: 1fr;
    gap: 4px;
  }
}

.talk__newchat {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  padding: 10px 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong);
  background: var(--bg-elev);
  color: var(--text);
  font-weight: 600;
  font-size: 0.92rem;
  cursor: pointer;
  transition: background var(--transition-fast), border-color var(--transition-fast),
    transform var(--transition-fast);
}

.talk__newchat:hover {
  background: var(--bg-elev-hover);
  border-color: var(--accent);
}

.talk__newchat:active {
  transform: scale(0.98);
}

.talk__history {
  display: flex;
  flex-direction: column;
  gap: 4px;
  overflow-y: auto;
  min-height: 0;
  margin: 0 -6px;
  padding: 0 6px;
}

.talk__history-empty {
  color: var(--text-muted);
  font-size: 0.82rem;
  padding: 6px;
}

.talk__chat-item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  text-align: left;
  padding: 9px 11px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  background: transparent;
  color: var(--text-soft);
  cursor: pointer;
  font-size: 0.88rem;
  font-family: inherit;
  transition: background var(--transition-fast), color var(--transition-fast);
}

.talk__chat-item:hover {
  background: var(--bg-elev);
  color: var(--text);
}

.talk__chat-item.is-active {
  background: var(--accent-soft);
  color: var(--text);
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
}

.talk__chat-item-title {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  cursor: pointer;
}

.talk__chat-delete {
  flex-shrink: 0;
  border: 0;
  background: transparent;
  color: var(--text-muted);
  font-size: 1rem;
  line-height: 1;
  padding: 0 2px;
  cursor: pointer;
  opacity: 0;
  transition: opacity var(--transition-fast), color var(--transition-fast);
}

.talk__chat-item:hover .talk__chat-delete,
.talk__chat-delete:focus-visible {
  opacity: 1;
}

.talk__chat-delete:hover {
  color: var(--danger);
}

.talk__chat-item-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
  flex-shrink: 0;
}

/* Conversation pane: camera pinned on top, transcript scrolls, composer pinned. */
.talk__main {
  flex: 1;
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 14px 20px 16px;
}

/* Live "Reachy's view" camera panel */
.talk__camera-wrap {
  position: relative;
  flex: none;
  width: 100%;
  max-width: 340px;
  margin: 0 auto 6px;
  aspect-ratio: 16 / 9;
  background: #0a0a0c;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow-sm), inset 0 0 0 1px rgba(255, 255, 255, 0.04);
}

.talk__camera {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.talk__camera-label {
  position: absolute;
  top: 8px;
  left: 10px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 9px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.5);
  color: #fff;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.talk__camera-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #ff4d4d;
  box-shadow: 0 0 6px #ff4d4d;
  animation: talk-camera-pulse 1.6s ease-in-out infinite;
}

@keyframes talk-camera-pulse {
  0%, 100% { opacity: 1; box-shadow: 0 0 7px #ff4d4d; }
  50% { opacity: 0.45; box-shadow: 0 0 2px #ff4d4d; }
}

.talk__camera-status {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: rgba(255, 255, 255, 0.75);
  font-size: 0.85rem;
  letter-spacing: 0.01em;
  pointer-events: none;
}

/* Compact orb so the transcript is the focus in this chat layout. */
.view--talk .convo-orb {
  width: clamp(150px, 20vw, 208px);
}

.talk__orb-wrap {
  display: grid;
  place-items: center;
  margin-top: 4px;
}

.talk__caption {
  margin: 0 0 6px 4px;
  color: var(--text-soft);
  font-size: 0.85rem;
  text-align: left;
  min-height: 1.3em;
}

.talk__log {
  flex: 1 1 auto;
  width: 100%;
  max-width: 660px;
  min-height: 0;
  max-height: none;
  margin: 10px auto;
  overflow-y: auto;
  overscroll-behavior: contain;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 6px 4px;
}

/* Pinned below the transcript so the mic never scrolls out of reach. */
.talk__composer {
  flex: none;
  width: 100%;
  max-width: 660px;
  margin: 0 auto;
}

.view--talk .convo-orb.talk__mic {
  width: 56px;
  height: 56px;
  flex: none;
}

.talk__mic .convo-orb__glow {
  filter: blur(10px);
}

.talk__mic .convo-orb__core {
  border-width: 1.5px;
}

/* The icon size is a chain of percentages tuned for the large orb, which lands
   at about ten pixels once the orb is this small. Pin the indicator to the exact
   centre of the circle and give it a fixed, readable size instead. */
.talk__mic .convo-orb__indicator {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 24px;
  height: 24px;
}

.talk__mic .convo-orb__indicator > .ind > svg {
  width: 22px;
  height: 22px;
}

/* The listening bars and thinking dots are also sized for the large orb and
   would sit wider than this circle, so they are scaled to stay inside it. */
.talk__mic .ind-thinking {
  gap: 4px;
}

.talk__mic .ind-thinking .dot {
  width: 5px;
  height: 5px;
}

.talk__mic .ind-bars {
  gap: 2px;
  height: 60%;
}

.talk__mic .ind-bars .bar {
  width: 2px;
  min-height: 2px;
}

.talk__log-empty {
  margin: auto;
  color: var(--text-muted);
  font-size: 0.92rem;
  text-align: center;
}

.talk__msg {
  max-width: 84%;
  padding: 9px 13px;
  border-radius: var(--radius);
  font-size: 0.95rem;
  line-height: 1.4;
  white-space: pre-wrap;
  word-break: break-word;
  box-shadow: var(--shadow-sm);
}

.talk__msg--assistant {
  align-self: flex-start;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  color: var(--text);
  border-bottom-left-radius: 6px;
}

.talk__msg--user {
  align-self: flex-end;
  background: var(--accent);
  color: #1a0f00;
  border-bottom-right-radius: 6px;
}

.talk__text-form {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  margin: 0;
}

.talk__text-input {
  flex: 1;
  min-width: 0;
  padding: 12px 14px;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--bg-elev);
  color: var(--text);
  font-family: inherit;
  font-size: 0.98rem;
  transition: border-color var(--transition-fast), background var(--transition-fast);
}

.talk__text-input:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--bg-soft);
}

.talk__text-input::placeholder {
  color: var(--text-muted);
}

.talk__send {
  padding: 12px 20px;
  border-radius: var(--radius);
  border: none;
  background: var(--accent);
  color: #1a0f00;
  font-weight: 600;
  font-size: 0.95rem;
  cursor: pointer;
  transition: background var(--transition-fast), transform var(--transition-fast);
}

.talk__send:hover:not(:disabled) {
  background: color-mix(in srgb, var(--accent) 90%, white);
}

.talk__send:active:not(:disabled) {
  transform: scale(0.97);
}

.talk__send:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* ChatGPT-style full-bleed: the Talk view spans the full window width with the
   sidebar flush to the left edge. Overrides the outlet's centered, max-width,
   padded layout that the other views use. */
.app-shell__outlet:has(.view--talk) {
  max-width: none;
  padding: 0;
}

.talk__panes {
  gap: 0;
}

.talk__sidebar {
  border-radius: 0;
  border-width: 0 1px 0 0;
}

.talk__main {
  padding: 18px 24px 24px;
}

/* Stack the sidebar above the conversation on narrow screens. */
@media (max-width: 720px) {
  .talk__panes {
    flex-direction: column;
  }
  .talk__sidebar {
    width: 100%;
    max-height: 38vh;
    border-width: 0 0 1px 0;
  }
}

/* 6. Settings view */

.view--settings {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.settings-section {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px 22px;
}

.settings-section-title {
  margin: 0 0 14px;
  font-size: 1.05rem;
  font-weight: 600;
  letter-spacing: -0.005em;
}

.settings-form {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.settings-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.settings-field-row {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(120px, 1fr);
  gap: 12px;
}

.settings-label {
  font-size: 0.85rem;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 600;
}

.settings-input,
.settings-select {
  width: 100%;
  background: var(--bg-soft);
  border: 1px solid var(--border);
  color: var(--text);
  font-size: 0.95rem;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  transition: border-color var(--transition-fast), background var(--transition-fast);
}

.settings-input:focus,
.settings-select:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--bg-elev);
}

.settings-hint {
  margin: 0;
  font-size: 0.85rem;
  color: var(--text-muted);
}

.settings-actions {
  display: flex;
  gap: 10px;
}

.settings-status {
  margin: 0;
  font-size: 0.85rem;
  color: var(--text-muted);
  min-height: 1em;
}

.settings-status.is-error {
  color: var(--danger);
}

.settings-status-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 8px;
  margin: 0;
}

.settings-status-row {
  display: grid;
  grid-template-columns: 180px 1fr;
  gap: 12px;
  padding: 8px 12px;
  border-radius: var(--radius-sm);
  background: var(--bg-soft);
}

.settings-status-row.is-warn {
  background: color-mix(in srgb, var(--warn) 12%, var(--bg-soft));
}

.settings-status-row.is-ok {
  background: color-mix(in srgb, var(--success) 10%, var(--bg-soft));
}

.settings-status-label {
  margin: 0;
  font-size: 0.85rem;
  color: var(--text-muted);
}

.settings-status-value {
  margin: 0;
  font-weight: 500;
}

@media (max-width: 620px) {
  .settings-field-row,
  .settings-status-row {
    grid-template-columns: 1fr;
  }
}

/* 7. Modal (profile-modal) */

.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: rgba(0, 0, 0, 0.55);
  display: grid;
  place-items: center;
  padding: 24px;
  animation: modal-fade-in 0.18s ease;
}

@keyframes modal-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.modal {
  width: min(560px, 100%);
  max-height: 90vh;
  overflow-y: auto;
  background: var(--bg-elev);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: 24px 26px 22px;
  animation: modal-pop-in 0.22s ease;
}

@keyframes modal-pop-in {
  from { transform: translateY(8px) scale(0.98); opacity: 0; }
  to   { transform: translateY(0)   scale(1);    opacity: 1; }
}

.modal__title {
  margin: 0 0 4px;
  font-size: 1.15rem;
  font-weight: 600;
}

.modal__subtitle {
  margin: 0 0 16px;
  color: var(--text-muted);
  font-size: 0.9rem;
}

.modal__form {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.modal__field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.modal__label {
  font-size: 0.85rem;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 600;
}

.modal__input,
.modal__textarea {
  background: var(--bg-soft);
  border: 1px solid var(--border);
  color: var(--text);
  font-family: inherit;
  font-size: 0.95rem;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  resize: vertical;
}

.modal__input:focus,
.modal__textarea:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--bg-elev);
}

.modal__input.is-readonly {
  opacity: 0.7;
  cursor: not-allowed;
}

.modal__error {
  margin: 0;
  min-height: 1em;
  font-size: 0.85rem;
  color: var(--danger);
  visibility: hidden;
}

.modal__error.is-visible {
  visibility: visible;
}

.modal__actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 4px;
}

/* Tool checklist (personality creation/editing) */
.modal__tools {
  border: none;
  margin: 0;
  padding: 0;
  min-width: 0; /* let the grid shrink inside the flex form */
}

.modal__tools-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px 16px;
  margin-top: 6px;
  max-height: 220px;
  overflow-y: auto;
  padding: 10px 12px;
  background: var(--bg-soft);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

.modal__tool {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.9rem;
  color: var(--text);
  cursor: pointer;
}

.modal__tool input {
  accent-color: var(--accent);
}

/* 8. Conversation orb
 * Indicators are mounted statically (orb.js) and switched via [data-state]
 * + the inline --glow colour; Python drives the state, not audio. */

.convo-orb {
  --glow: #34d399;

  position: relative;
  width: clamp(220px, 38vw, 320px);
  aspect-ratio: 1 / 1;
  border-radius: 50%;
  border: none;
  background: transparent;
  padding: 0;
  display: grid;
  place-items: center;
  color: var(--glow);
  /* The orb is the mic toggle button (see talk.js). */
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.18s ease, filter 0.18s ease;
}

.convo-orb:active {
  transform: scale(0.97);
}

.convo-orb:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 6px;
}

.convo-orb__glow {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: radial-gradient(circle at center, var(--glow) 0%, transparent 65%);
  filter: blur(28px);
  opacity: 0.5;
  pointer-events: none;
  transition: opacity 0.25s, background 0.25s, transform 1.4s ease-in-out;
}

.convo-orb__ring,
.convo-orb__ring-outer {
  position: absolute;
  top: 50%;
  left: 50%;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  pointer-events: none;
  transition: opacity 0.4s ease, border-color 0.4s ease, transform 0.3s ease;
}

.convo-orb__ring {
  width: 82%;
  height: 82%;
  border: 1.5px solid color-mix(in srgb, var(--glow) 35%, transparent);
  opacity: 0.35;
}

.convo-orb__ring-outer {
  width: 94%;
  height: 94%;
  border: 1px solid color-mix(in srgb, var(--glow) 22%, transparent);
  opacity: 0;
}

.convo-orb__core {
  position: relative;
  width: 72%;
  height: 72%;
  border-radius: 50%;
  background: radial-gradient(
    circle at 35% 28%,
    color-mix(in srgb, var(--glow) 28%, transparent),
    color-mix(in srgb, var(--glow) 10%, transparent) 55%,
    color-mix(in srgb, var(--glow) 5%, transparent)
  );
  border: 2px solid color-mix(in srgb, var(--glow) 40%, transparent);
  box-shadow:
    0 0 32px color-mix(in srgb, var(--glow) 22%, transparent),
    inset 0 0 28px color-mix(in srgb, var(--glow) 18%, transparent);
  display: grid;
  place-items: center;
  color: var(--glow);
  transition: background 0.4s ease, border-color 0.4s ease, box-shadow 0.4s ease, transform 0.4s ease;
}

/* Every .ind child stacks in this grid cell; opacity rules below pick
   the visible one, so the subtree never needs rebuilding. */
.convo-orb__indicator {
  position: relative;
  width: 44%;
  height: 44%;
  display: grid;
  place-items: center;
  color: var(--glow);
}

/* Without this, <span> defaults to display: inline and the SVG inside
   sizes against an undefined-width container, rendering off-center. */
.convo-orb__indicator > .ind {
  grid-area: 1 / 1;
  width: 100%;
  height: 100%;
  display: grid;
  place-items: center;
  opacity: 0;
  transform: scale(0.85);
  transition: opacity 0.25s ease, transform 0.25s ease;
  pointer-events: none;
}

/* display: block strips the inline baseline gap that would otherwise
   nudge the icon off-center vertically. */
.convo-orb__indicator > .ind > svg {
  width: 60%;
  height: 60%;
  display: block;
}

/* Keyframes carry both scale(1) and the rotation so the browser doesn't
   interpolate between two different transform functions. */
.convo-orb__indicator > .ind-spinner {
  display: block;
  place-self: center;
  width: 32%;
  height: 32%;
  border: 3px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
}

@keyframes orb-spin {
  from { transform: scale(1) rotate(0deg); }
  to   { transform: scale(1) rotate(360deg); }
}

/* Per-dot animation, staggered ~160ms, so it composes cleanly with the
   parent's show/hide scale(.85 -> 1). */
.convo-orb__indicator > .ind-thinking {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}
.ind-thinking .dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.3;
}
.ind-thinking .dot:nth-child(1) { animation: orb-thinking-dot 1.25s ease-in-out infinite; animation-delay: 0s; }
.ind-thinking .dot:nth-child(2) { animation: orb-thinking-dot 1.25s ease-in-out infinite; animation-delay: 0.16s; }
.ind-thinking .dot:nth-child(3) { animation: orb-thinking-dot 1.25s ease-in-out infinite; animation-delay: 0.32s; }

@keyframes orb-thinking-dot {
  0%, 60%, 100% { transform: scale(0.7); opacity: 0.3; }
  30%           { transform: scale(1.15); opacity: 1; }
}

/* Height capped at 42% so bars animating up to 100% of this container
   never overflow into the core's inner edge. */
.convo-orb__indicator > .ind-bars {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  height: 42%;
}
.ind-bars .bar {
  width: 4px;
  min-height: 4px;
  height: 35%;
  border-radius: 3px;
  background: currentColor;
  opacity: 0.7;
}
.convo-orb[data-state="listening"] .ind-bars .bar {
  animation: orb-bar 0.9s ease-in-out infinite;
}
.ind-bars .bar:nth-child(1) { animation-delay: -0.2s; }
.ind-bars .bar:nth-child(2) { animation-delay: -0.05s; }
.ind-bars .bar:nth-child(3) { animation-delay: -0.35s; }
.ind-bars .bar:nth-child(4) { animation-delay: -0.1s; }
.ind-bars .bar:nth-child(5) { animation-delay: -0.25s; }

@keyframes orb-bar {
  0%, 100% { height: 35%; opacity: 0.7; }
  50%      { height: 100%; opacity: 1; }
}

.ind-voice .wave {
  transform-origin: 50% 50%;
  opacity: 0;
}
.convo-orb[data-state="speaking"] .ind-voice .wave {
  animation: orb-voice-wave 1.35s ease-out infinite;
}
.ind-voice .wave-1 { animation-delay: 0s; }
.ind-voice .wave-2 { animation-delay: 0.35s; }

@keyframes orb-voice-wave {
  0%   { opacity: 0; transform: scale(0.7); }
  30%  { opacity: 1; transform: scale(1); }
  70%  { opacity: 0.2; transform: scale(1.12); }
  100% { opacity: 0; transform: scale(0.7); }
}

/* Per-state visibility & ambient animations */

/* .ind-mic (idle) is never set to opacity:1 explicitly, so any
   [data-state] rule below wins via cascade. */
.convo-orb[data-state="idle"] .ind-mic,
.convo-orb[data-state="muted"] .ind-mic-off,
.convo-orb[data-state="connecting"] .ind-spinner,
.convo-orb[data-state="listening"] .ind-bars,
.convo-orb[data-state="thinking"] .ind-thinking,
.convo-orb[data-state="speaking"] .ind-voice,
.convo-orb[data-state="error"] .ind-error {
  opacity: 1;
  transform: scale(1);
}

/* !important: without it, the show/hide scale(1) rule above would fight
   the spinner's own rotation keyframes. */
.convo-orb[data-state="connecting"] .ind-spinner {
  opacity: 1 !important;
  animation: orb-spin 0.9s linear infinite;
}

/* Idle: gentle breath on the inner ring; off in connecting/error. */
.convo-orb[data-state="idle"] .convo-orb__ring {
  animation: orb-breathe 2.4s ease-in-out infinite;
}

/* Listening: brighter rings, both visible. */
.convo-orb[data-state="listening"] .convo-orb__ring {
  opacity: 0.85;
  animation: orb-breathe 2s ease-in-out infinite;
}
.convo-orb[data-state="listening"] .convo-orb__ring-outer {
  opacity: 0.45;
}

/* Thinking: dimmer than speaking so the 3-dot indicator stays the focus. */
.convo-orb[data-state="thinking"] .convo-orb__core {
  animation: orb-thinking-throb 1.4s ease-in-out infinite;
}

/* Speaking: outer ring fades in to convey audio radiating out. */
.convo-orb[data-state="speaking"] .convo-orb__core {
  animation: orb-speak 1.6s ease-in-out infinite;
}
.convo-orb[data-state="speaking"] .convo-orb__ring-outer {
  opacity: 0.4;
  animation: orb-ring-out 1.8s ease-out infinite;
}

/* Muted: perfectly still and dimmed so "paused" reads at a glance. */
.convo-orb[data-state="muted"] .convo-orb__glow {
  opacity: 0.25;
}

/* Error: no animation, just a stronger edge to read as a stop signal. */
.convo-orb[data-state="error"] .convo-orb__core {
  border-color: var(--glow);
}

/* Keyframes */

@keyframes orb-breathe {
  0%, 100% { transform: translate(-50%, -50%) scale(1);    opacity: 0.35; }
  50%      { transform: translate(-50%, -50%) scale(1.06); opacity: 0.7; }
}

@keyframes orb-ring-out {
  0%   { transform: translate(-50%, -50%) scale(1);    opacity: 0.4; }
  100% { transform: translate(-50%, -50%) scale(1.18); opacity: 0; }
}

@keyframes orb-thinking-throb {
  0%, 100% { transform: scale(1);    box-shadow: 0 0 32px color-mix(in srgb, var(--glow) 18%, transparent),
                                                inset 0 0 28px color-mix(in srgb, var(--glow) 14%, transparent); }
  50%      { transform: scale(0.97); box-shadow: 0 0 26px color-mix(in srgb, var(--glow) 12%, transparent),
                                                inset 0 0 22px color-mix(in srgb, var(--glow) 8%, transparent); }
}

@keyframes orb-speak {
  0%, 100% { transform: scale(1);    box-shadow: 0 0 32px color-mix(in srgb, var(--glow) 22%, transparent),
                                                inset 0 0 28px color-mix(in srgb, var(--glow) 18%, transparent); }
  50%      { transform: scale(1.04); box-shadow: 0 0 44px color-mix(in srgb, var(--glow) 35%, transparent),
                                                inset 0 0 36px color-mix(in srgb, var(--glow) 30%, transparent); }
}

/* 9. Block coding view (Blockly workspace + activities panel) */

.app-shell__outlet:has(.view--blocks) {
  max-width: none;
  padding: 20px 24px 24px;
}

.view--blocks {
  display: flex;
  flex-direction: column;
  gap: 12px;
  flex: 1 1 auto;
  min-height: 0;
}

.blocks__header {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px 24px;
}

.blocks__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.blocks__stop {
  background: var(--danger);
  border-color: var(--danger);
  color: #fff;
}

.blocks__status {
  margin: 0;
  color: var(--text-soft);
}

.blocks__status.is-error {
  color: var(--danger);
}

.blocks__main {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: 12px;
  flex: 1 1 auto;
  min-height: 560px;
}

.blocks__workspace {
  position: relative;
  min-height: 560px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}

.view--blocks.is-running .blocks__workspace {
  border-color: var(--success);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--success) 35%, transparent);
}

.blocks__side {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-height: 0;
  max-height: calc(100vh - 170px);
  padding: 14px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow-y: auto;
}

.blocks__side-title {
  margin: 6px 0 0;
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.blocks__card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 0.9rem;
  color: var(--text-soft);
}

.blocks__card-title {
  margin: 6px 0 0;
  font-size: 0.85rem;
  color: var(--text);
}

.blocks__adapt {
  margin: 0;
}

.blocks__question {
  margin: 0;
  padding: 10px 12px;
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm);
  background: var(--accent-soft);
  color: var(--text);
  font-weight: 600;
}

.blocks__question-label {
  display: block;
  margin-bottom: 2px;
  font-size: 0.7rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--accent);
}

.blocks__list {
  margin: 0;
  padding-left: 1.2em;
}

.blocks__list li + li {
  margin-top: 4px;
}

.blocks__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 4px 0 0;
}

.blocks__tag {
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 0.75rem;
  font-weight: 600;
}

.blocks__card-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 6px;
}

.blocks__card-actions .btn {
  text-decoration: none;
}

.blocks__log {
  margin: 0;
  padding: 8px 10px 8px 2em;
  min-height: 90px;
  max-height: 220px;
  overflow-y: auto;
  background: var(--bg-soft);
  border-radius: var(--radius-sm);
  font-family: ui-monospace, "SF Mono", Consolas, monospace;
  font-size: 0.8rem;
}

.blocks__log li {
  padding: 2px 0;
  overflow-wrap: anywhere;
}

.blocks__log li.is-info { color: var(--success); }
.blocks__log li.is-warn { color: var(--warn); }
.blocks__log li.is-error { color: var(--danger); }

@media (max-width: 860px) {
  .blocks__main {
    grid-template-columns: 1fr;
  }

  .blocks__side {
    max-height: none;
  }
}

.blocks__eye {
  width: 100%;
  aspect-ratio: 4 / 3;
  background: var(--bg-soft);
  border-radius: var(--radius-sm);
  image-rendering: pixelated;
}

/* 10. Threat model board (adversarial model-based inquiry) */

.app-shell__outlet:has(.view--model) {
  max-width: 1320px;
}

.view--model {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.tm-header {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px 24px;
}

.tm-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.tm-cycle {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.tm-cycle li {
  display: grid;
  gap: 2px;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-elev);
  font-size: 0.8rem;
  color: var(--text-soft);
}

.tm-cycle li strong {
  color: var(--text);
  font-size: 0.85rem;
}

.tm-cycle li.is-active {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.tm-board {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 12px;
  align-items: start;
}

.tm-column {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-soft);
}

.tm-column-title {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  margin: 0;
  font-size: 0.95rem;
  font-weight: 600;
}

.tm-count {
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
}

.tm-cards {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.tm-card {
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-left: 3px solid var(--text-muted);
  border-radius: var(--radius-sm);
  background: var(--bg-elev);
}

.tm-card.is-supported {
  border-left-color: var(--success);
}

.tm-card.is-refuted {
  border-left-color: var(--danger);
}

.tm-card-body {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.tm-card p {
  margin: 0;
  font-size: 0.88rem;
  color: var(--text-soft);
  overflow-wrap: anywhere;
}

.tm-card .tm-claim {
  color: var(--text);
  font-weight: 600;
}

.tm-card.is-refuted .tm-claim {
  text-decoration: line-through;
  text-decoration-color: var(--danger);
}

.tm-status {
  align-self: flex-start;
  padding: 1px 8px;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 600;
  background: var(--bg-soft);
  color: var(--text-soft);
}

.tm-status.is-supported {
  background: color-mix(in srgb, var(--success) 18%, transparent);
  color: var(--success);
}

.tm-status.is-refuted {
  background: color-mix(in srgb, var(--danger) 18%, transparent);
  color: var(--danger);
}

.tm-actions,
.tm-form-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.tm-small {
  padding: 3px 10px;
  font-size: 0.78rem;
}

.tm-form {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.tm-add .tm-form {
  max-width: 640px;
  padding: 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-elev);
}

.tm-text {
  resize: vertical;
  font-family: inherit;
}

.tm-message {
  margin: 0;
  min-height: 1.2em;
  font-size: 0.85rem;
  color: var(--danger);
}

.tm-history {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 4px 0 0;
  padding-left: 1.1em;
  font-size: 0.8rem;
  color: var(--text-soft);
}

.tm-history li {
  display: flex;
  flex-direction: column;
}

.blocks__model {
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-size: 0.88rem;
}

.blocks__model-lead {
  margin: 0;
  color: var(--text-soft);
}

.blocks__model-claims {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.blocks__board-link {
  align-self: flex-start;
  text-decoration: none;
}

.blocks__log li {
  cursor: pointer;
}

.blocks__log li:hover {
  background: var(--bg-elev-hover);
}

@media (max-width: 960px) {
  .tm-board {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 560px) {
  .tm-board {
    grid-template-columns: 1fr;
  }
}

/* Virtual Senti (Block coding without a robot) */
.blocks__virtual { display: grid; gap: 8px; }
.blocks__virtual[hidden] { display: none; }
.blocks__stage { width: 100%; aspect-ratio: 4 / 3; overflow: hidden; border-radius: var(--radius-sm); background: #1b2b4d; }
.blocks__stage canvas { display: block; }
.blocks__virtual-actions { display: flex; flex-wrap: wrap; gap: 6px; }
.blocks__wave { flex: 1; min-width: 0; }
.blocks__note { padding: 8px 10px; border-radius: var(--radius-sm); background: var(--bg-soft); border-left: 3px solid var(--accent); font-size: 0.9em; }
