/* Innate — control-room design system. One stylesheet, every page.
   Instrument-panel restraint: hairlines, typography, and a single signal
   amber doing all the work. No gradients-as-decoration, no drop shadows. */

html,
body {
  /* App UI, not a document: no pinch/double-tap zoom (iOS ignores the
     viewport flag; canvas elements set their own touch-action). */
  touch-action: pan-x pan-y;
}

:root {
  --bg: #0a0a0c;
  --panel: #111114;
  --hairline: rgb(255 255 255 / 8%);
  --hairline-strong: rgb(255 255 255 / 16%);
  --text: #e7e7ea;
  --muted: #8a8a93;
  --accent: #e8a33d;            /* signal amber — live/active states only */
  --accent-dim: rgb(232 163 61 / 40%);
  --accent-faint: rgb(232 163 61 / 12%);
  --ok: #56c28c;                /* connected dot */
  --danger: #d96a5a;
  --blue: #401ffb;              /* Innate brand blue — logo backdrop */
  --type-learned: #5fb8a3;      /* skill-type dot: trained ACT policy */
  --type-replay: #6b93d6;       /* skill-type dot: recorded trajectory */
  --type-digital: #a389d4;      /* skill-type dot: code/SDK skill */
  --eval: #b58ce6;              /* evaluation identity — policy rollouts, never training data */
  --eval-dim: rgb(181 140 230 / 40%);
  --eval-faint: rgb(181 140 230 / 12%);
  --glass: rgb(0 0 0 / 40%);

  /* ---- controls over a live backdrop ------------------------------------
     Every button that floats over the camera feed or the map faces the same
     problem: the backdrop is whatever the robot is looking at, from a dark room
     to a blown-out white wall. A control that only *tints* that backdrop — the
     12% accent fill this app used to reach for — borrows contrast it may not
     have, and amber-on-white is the worst case of it.
     So a control carries its own dark base, and the accent lives in the text
     and the hairline where it stays legible at any backdrop brightness. Still
     translucent (the feed moves under it), but lit from within, not behind.
     Raised = buttons; recessed = text fields; off = disabled/inert. */
  --ctl-glass: rgb(8 8 10 / 72%);
  --ctl-glass-hover: rgb(8 8 10 / 84%);
  --ctl-field: rgb(8 8 10 / 52%);
  --ctl-sheen: inset 0 1px 0 rgb(255 255 255 / 12%);
  /* --accent / --danger lifted until they read on that base; plain --muted
     grey washes out over a bright feed, so neutral control text is brighter. */
  --ctl-accent: #f7c274;
  --ctl-accent-hover: #ffd79a;
  --ctl-danger: #f7a595;
  --ctl-text: rgb(231 231 234 / 78%);
  --ctl-text-off: rgb(231 231 234 / 42%);
  --ctl-edge-accent: rgb(232 163 61 / 45%);
  --ctl-edge-accent-hover: rgb(232 163 61 / 72%);
  --ctl-edge-danger: rgb(217 106 90 / 50%);
  --agent-purple: #e0dcff;
  --agent-purple-fill: rgb(64 31 251 / 32%);
  --agent-purple-edge: rgb(151 135 255 / 68%);

  --font-ui: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, "SF Mono", "Cascadia Code", Menlo, Consolas, monospace;
}

* {
  box-sizing: border-box;
}

/* The `hidden` attribute must win over any element that also sets `display`
   (grid/flex/block author rules otherwise override the UA [hidden] rule). */
[hidden] {
  display: none !important;
}

html,
body {
  height: 100%;
  margin: 0;
}

body {
  display: grid;
  grid-template-columns: 64px 1fr;
  overflow: hidden;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-ui);
  font-size: 13px;
  line-height: 1.45;
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
}

.mono {
  font-family: var(--font-mono);
}

.microlabel {
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0;
}

::selection {
  background: var(--accent-dim);
}

:focus-visible {
  outline: 1px solid var(--accent);
  outline-offset: 2px;
}

button {
  font: inherit;
  color: inherit;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
}

/* Native select chevron cannot be inset reliably.
   30px end padding = 10px inset + 10px icon + 10px text gap. */
.log-select,
.modal-select,
.prof-select,
.record-skill,
.set-ctl select.set-text,
select.episodes-tool,
select.skill-input {
  -webkit-appearance: none;
  appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path d='M1 1l4 4 4-4' fill='none' stroke='%238a8a93' stroke-width='1.4'/></svg>");
  background-repeat: no-repeat;
  background-position: right 10px center;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* ---- icon rail ---------------------------------------------------------- */

.rail {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  padding: 14px 0 12px;
  border-right: 1px solid var(--hairline);
  background: var(--bg);
  user-select: none;
  -webkit-user-select: none;
  /* Overlay-expand on hover: the body grid reserves 64px; the rail widens on top
     of the content (no reflow) and fades in text labels. */
  position: relative;
  z-index: 40;
  width: 64px;
  overflow: hidden;
  transition: width 160ms ease;
}
.rail:hover {
  width: 200px;
  box-shadow: 2px 0 18px rgb(0 0 0 / 45%);
}

.rail-mark {
  display: grid;
  place-items: center;
  width: 64px;             /* full rail width */
  height: 52px;
  margin: -14px 0 18px;    /* negate rail's top padding so the block reaches the top edge */
  background: var(--blue);
  color: #fff;
}

.rail-nav {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.rail-link {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  height: 38px;
  margin: 0 8px;           /* 48px content + 2×8 = the 64px collapsed rail, icon stays centered */
  border-radius: 9px;
  color: var(--muted);
  text-decoration: none;   /* it's an <a> — no link underline under the label */
  transition: color 120ms ease;
}

.rail-link:hover {
  color: var(--text);
}

.rail-link.active {
  color: var(--text);
}

.rail-ico {
  flex: none;
  width: 48px;             /* centers the icon within the 64px collapsed rail */
  display: grid;
  place-items: center;
}

.rail-label {
  white-space: nowrap;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: 11px;
  opacity: 0;
  transition: opacity 120ms ease;
}
.rail:hover .rail-label {
  opacity: 1;
}

/* Keycap hint: the number key that jumps to this section. A small digit pinned
   to the top-right corner of the icon, always visible even when collapsed. */
.rail-key {
  position: absolute;
  top: 3px;
  left: 33px;              /* top-right corner of the 48px icon box */
  font-size: 9px;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  opacity: 0.7;
  pointer-events: none;
}

.rail-link.active::before {
  content: "";
  position: absolute;
  left: -13px;
  top: 10px;
  width: 2px;
  height: 18px;
  border-radius: 1px;
  background: var(--accent);
}

/* Group boundaries in the rail. Collapsed, a hairline tick under the icon
   column marks the break; on hover-expand, labeled dividers trade the tick
   for the group's header — label plus a hairline running to the right edge
   (unlabeled ones keep the tick). */
.rail-div {
  position: relative;
  flex: none;
  height: 17px;
  margin: 4px 0 1px;
}

.rail-div::before {
  content: "";
  position: absolute;
  left: 22px;             /* 20px tick centered under the icon column (x = 32) */
  top: 50%;
  width: 20px;
  height: 1px;
  background: var(--hairline);
  transition: opacity 120ms ease;
}

.rail:hover .rail-div.has-label::before {
  opacity: 0;
}

.rail-div-label {
  position: absolute;
  left: 13px;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  gap: 9px;
  white-space: nowrap;
  text-transform: uppercase;
  letter-spacing: 0.15em;
  font-size: 10.5px;
  font-weight: 650;
  color: var(--text);
  opacity: 0;
  transition: opacity 120ms ease;
}

.rail-div-label::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--hairline);
}

.rail:hover .rail-div-label {
  opacity: 0.85;
}

/* Bottom-pinned utility links (Settings), at the rail's very bottom. */
.rail-foot {
  margin-top: auto;
  padding-top: 12px;
}

/* ---- boot splash -------------------------------------------------------- */

/* Covers the stage area from first paint until router.js mounts the first page
   (see index.html). Fixed, offset past the 64px rail column so the nav shows
   through the moment initShell builds it (which happens well before the first
   page mounts) — only the main stage waits behind the splash. */
.boot-splash {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 64px; /* = body grid's rail column (grid-template-columns: 64px 1fr) */
  z-index: 1000;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 20px;
  background: var(--bg);
  opacity: 1;
  /* Short: the page mounts in ~0.4s on robot WiFi, so a 0.4s fade was half the
     perceived load. Long enough to not flash. */
  transition: opacity 0.2s ease;
}

/* .is-leaving is set by router.js to fade out; then the element is removed. */
.boot-splash.is-leaving {
  opacity: 0;
  pointer-events: none;
}

.boot-splash__mark {
  font-size: 15px;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--muted);
}

/* Indeterminate bar: no byte progress yet at boot (the JS itself is still
   downloading), so a looping sweep rather than a filled fraction. */
.boot-splash__bar {
  width: min(220px, 50vw);
  height: 3px;
  border-radius: 999px;
  background: var(--hairline);
  overflow: hidden;
}

.boot-splash__bar span {
  display: block;
  width: 40%;
  height: 100%;
  border-radius: 999px;
  background: var(--accent);
  animation: boot-sweep 1.1s ease-in-out infinite;
}

@keyframes boot-sweep {
  0% {
    transform: translateX(-100%);
  }
  100% {
    transform: translateX(350%);
  }
}

@media (prefers-reduced-motion: reduce) {
  .boot-splash__bar span {
    animation: boot-pulse 1.4s ease-in-out infinite;
    width: 100%;
    transform: none;
  }
  @keyframes boot-pulse {
    0%,
    100% {
      opacity: 0.25;
    }
    50% {
      opacity: 0.8;
    }
  }
}

/* ---- stage -------------------------------------------------------------- */

.stage {
  position: relative;
  overflow: hidden;
}

.connect-layer,
.cockpit,
.map-view {
  position: absolute;
  inset: 0;
}

.map-canvas {
  display: block;
  width: 100%;
  height: 100%;
  /* Drags pan the map (or place goals); never scroll the page. */
  touch-action: none;
}

.map-controls {
  position: absolute;
  /* Top-left corner; top-right belongs to the camera strip. */
  top: 14px;
  left: 14px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
}

.map-controls-row {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  min-width: 210px;
}

/* Icon + label cards with a hint slot (mobile-app style). */
.map-btn {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 12px 6px 8px;
  border: 1px solid var(--hairline-strong);
  border-radius: 10px;
  background: var(--ctl-glass);
  box-shadow: var(--ctl-sheen);
  backdrop-filter: blur(6px);
  color: var(--text);
  text-align: left;
  transition: border-color 150ms ease, color 150ms ease, background 150ms ease;
}

.map-btn:hover:not(:disabled) {
  border-color: var(--ctl-edge-accent);
  background: var(--ctl-glass-hover);
}

.map-btn:active:not(:disabled) {
  transform: translateY(1px);
}

.map-btn:disabled {
  color: var(--ctl-text-off);
  cursor: progress;
}

.map-btn.is-active {
  border-color: var(--ctl-edge-accent-hover);
  color: var(--ctl-accent);
}

.map-btn-icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 24px;
  height: 24px;
  border: 1px solid var(--hairline-strong);
  border-radius: 50%;
  transition: border-color 150ms ease, background 150ms ease;
}

.map-btn:hover:not(:disabled) .map-btn-icon {
  border-color: var(--ctl-edge-accent);
}

.map-btn.is-active .map-btn-icon {
  border-color: var(--ctl-edge-accent-hover);
  background: var(--accent-faint);
}

.map-btn-icon svg {
  width: 13px;
  height: 13px;
}

.map-btn-label {
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.map-btn-hint {
  margin-left: auto;
  padding-left: 10px;
  border-left: 1px solid var(--hairline);
  max-width: 120px;
  font-size: 10px;
  line-height: 1.3;
  color: var(--muted);
}

.map-btn-hint:empty {
  display: none;
}

/* Icon-only (Back): don't stretch to the card width. */
.map-btn-compact {
  align-self: flex-start;
}

/* Outcome line for the widget's own navigation goals. */
.map-status {
  max-width: 340px;
  padding: 4px 10px;
  border: 1px solid var(--hairline);
  border-radius: 8px;
  background: var(--ctl-glass);
  backdrop-filter: blur(6px);
  font-size: 12px;
  line-height: 1.4;
  color: var(--muted);
}

.map-status[data-kind="ok"] {
  color: var(--ok);
}

.map-status[data-kind="fail"] {
  color: var(--danger);
}


.connect-layer {
  display: grid;
  place-items: center;
}

/* ---- connect card ------------------------------------------------------- */

.connect-card {
  width: 320px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 28px;
  background: var(--panel);
  border: 1px solid var(--hairline);
  border-radius: 12px;
}

.connect-input {
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--hairline-strong);
  border-radius: 0;
  padding: 6px 1px;
  font-size: 14px;
  color: var(--text);
  transition: border-color 150ms ease;
}

.connect-input:focus {
  outline: none;
  border-bottom-color: var(--accent);
}

.connect-input::placeholder {
  color: rgb(255 255 255 / 22%);
}

.connect-button {
  border: 1px solid var(--hairline-strong);
  border-radius: 8px;
  padding: 9px 0;
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text);
  transition: border-color 150ms ease, color 150ms ease;
}

.connect-button:hover:not(:disabled) {
  border-color: var(--accent-dim);
  color: var(--accent);
}

.connect-button:disabled {
  color: var(--muted);
  cursor: progress;
}

.connect-error {
  margin: 0;
  font-size: 12px;
  color: var(--danger);
}

.connect-hint {
  letter-spacing: 0.1em;
}

/* ---- video stage -------------------------------------------------------- */

.video-stage {
  position: absolute;
  inset: 0;
  background: #000;
}

.video-stage video {
  width: 100%;
  height: 100%;
  object-fit: contain; /* never crop the operator's view */
}

.video-stage.degraded video {
  filter: saturate(0.55) brightness(0.75);
}

/* Cold-start warmup: hide the frozen first frame so the "loading video stream"
   overlay shows over black, not a stale frame that looks live. */
.video-stage.buffering video {
  visibility: hidden;
}

.video-status {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 14px;
}

.video-status-text {
  letter-spacing: 0.22em;
}

.video-status.waiting .video-status-text {
  animation: breathe 2.2s ease-in-out infinite;
}

@keyframes breathe {
  0%, 100% { opacity: 0.35; }
  50% { opacity: 0.9; }
}

.video-retry {
  border: 1px solid var(--hairline-strong);
  border-radius: 8px;
  padding: 7px 16px;
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text);
}

.video-retry:hover {
  border-color: var(--accent-dim);
  color: var(--accent);
}

/* ---- glass overlays ------------------------------------------------------ */

.overlay {
  position: absolute;
  background: var(--glass);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid var(--hairline);
  border-radius: 11px;
  user-select: none;
  -webkit-user-select: none;
}

.overlay-top-left {
  top: 14px;
  left: 14px;
}

.overlay-right {
  right: 14px;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  padding: 10px 7px;
}

.overlay-bottom-left {
  left: 14px;
  bottom: 14px;
  padding: 10px 12px;
}

/* Top-left overlay column on the Agent page. */
.overlay-stack-top-left {
  position: absolute;
  top: 14px;
  left: 14px;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  width: max-content;
  gap: 10px;
  z-index: 6;
}

.overlay-stack-top-left > .overlay {
  position: static;
  /* The sim's 3D scene behind these cards is often bright wall/floor, where
     the default 40% glass washes the text out -- use the darker glass the
     sim debug stack (.overlay-sim) settled on. */
  background: rgb(0 0 0 / 66%);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
}

/* ---- challenge panel (sim only, see agent/challengePanel.js) ------------- */
.agent-challenge-dock {
  position: absolute;
  bottom: 14px;
  left: 80px;
  z-index: 13;
  width: 56px;
  height: 56px;
}

.challenge-panel {
  position: absolute;
  bottom: 66px;
  left: -66px;
  display: grid;
  width: min(360px, calc(100vw - 150px));
  max-height: min(520px, calc(100vh - 110px));
  padding: 13px;
  gap: 10px;
  overflow-y: auto;
  background: rgb(8 8 10 / 42%);
  backdrop-filter: blur(30px) saturate(1.1) brightness(0.82);
  -webkit-backdrop-filter: blur(30px) saturate(1.1) brightness(0.82);
  border: 1px solid rgb(255 255 255 / 14%);
  border-radius: 18px;
  box-shadow: 0 14px 44px rgb(0 0 0 / 48%);
  transform-origin: bottom left;
  will-change: transform, opacity;
  transition:
    opacity 220ms cubic-bezier(0.23, 1, 0.32, 1),
    transform 240ms cubic-bezier(0.23, 1, 0.32, 1),
    visibility 0s;
}

.agent-challenge-dock:not(.open) .challenge-panel {
  visibility: hidden;
  opacity: 0;
  pointer-events: none;
  transform: translate(-4px, 10px) scale(0.96);
  transition:
    opacity 130ms cubic-bezier(0.25, 0.46, 0.45, 0.94),
    transform 160ms cubic-bezier(0.25, 0.46, 0.45, 0.94),
    visibility 0s linear 160ms;
}

.challenge-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 24px;
  padding-bottom: 10px;
  border-bottom: 1px solid rgb(255 255 255 / 9%);
}

.agent-challenge-toggle {
  display: grid;
  width: 56px;
  height: 56px;
  padding: 0;
  color: rgb(255 255 255 / 82%);
  background: rgb(8 8 10 / 76%);
  backdrop-filter: blur(20px) saturate(1.1);
  -webkit-backdrop-filter: blur(20px) saturate(1.1);
  border: 1px solid rgb(255 255 255 / 18%);
  border-radius: 50%;
  box-shadow: 0 10px 28px rgb(0 0 0 / 38%);
  cursor: pointer;
  place-items: center;
  transition:
    color 150ms ease,
    background-color 150ms ease,
    border-color 150ms ease,
    transform 120ms cubic-bezier(0.215, 0.61, 0.355, 1);
}

.agent-challenge-toggle-icon {
  grid-area: 1 / 1;
  width: 24px;
  height: 24px;
  transition:
    opacity 160ms cubic-bezier(0.23, 1, 0.32, 1),
    transform 180ms cubic-bezier(0.23, 1, 0.32, 1);
}

.agent-challenge-toggle-flag {
  background: currentColor;
  -webkit-mask: url("/js/agent/icons/finish-flag.svg") center / contain no-repeat;
  mask: url("/js/agent/icons/finish-flag.svg") center / contain no-repeat;
}

.agent-challenge-toggle-close {
  opacity: 0;
  pointer-events: none;
  transform: rotate(-10deg) scale(0.82);
}

.agent-challenge-dock.open .agent-challenge-toggle-flag {
  opacity: 0;
  transform: rotate(10deg) scale(0.82);
}

.agent-challenge-dock.open .agent-challenge-toggle-close {
  opacity: 1;
  transform: rotate(0) scale(1);
}

.agent-challenge-toggle:active {
  transform: scale(0.96);
}

.agent-challenge-toggle:focus-visible {
  outline: 2px solid var(--ctl-accent);
  outline-offset: 3px;
}

.agent-challenge-dock.active .agent-challenge-toggle {
  color: var(--ctl-accent);
  border-color: var(--ctl-edge-accent);
}

@media (hover: hover) and (pointer: fine) {
  .agent-challenge-toggle:hover {
    color: #fff;
    background: rgb(14 14 18 / 88%);
    border-color: rgb(255 255 255 / 30%);
  }
}

.challenge-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.challenge-empty {
  font-size: 12px;
  color: var(--muted);
}

.challenge-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 9px 11px;
  background: rgb(8 8 10 / 46%);
  border: 1px solid rgb(255 255 255 / 14%);
  border-radius: 8px;
  color: var(--text);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.challenge-item:hover {
  background: rgb(8 8 10 / 62%);
  border-color: rgb(255 255 255 / 24%);
}

.challenge-dot {
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  border: 1px solid var(--muted);
}

.challenge-dot.passed {
  background: var(--ok);
  border-color: var(--ok);
}

.challenge-item-text {
  display: grid;
  flex: 1;
  gap: 2px;
  min-width: 0;
}

.challenge-item-title {
  font-size: 13px;
  line-height: 1.25;
}

.challenge-item-meta {
  font-size: 11px;
  line-height: 1.3;
  color: rgb(231 231 234 / 68%);
}

.challenge-play {
  display: flex;
  color: var(--muted);
  opacity: 0.5;
}

.challenge-item:hover .challenge-play {
  color: var(--accent);
  opacity: 1;
}

.challenge-active {
  display: flex;
  flex-direction: column;
  gap: 8px;
  /* Let the brief/goals be selected so the challenge instructions can be
     copied into the agent chat (the .overlay default is user-select: none). */
  user-select: text;
  -webkit-user-select: text;
}

.challenge-title-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}

.challenge-timer {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--accent);
}

.challenge-timer.final {
  color: var(--muted);
}

.challenge-brief {
  font-size: 12px;
  line-height: 1.35;
  color: var(--muted);
}

.challenge-goals {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.challenge-goals li {
  position: relative;
  padding-left: 20px;
  font-size: 12px;
  color: var(--muted);
}

.challenge-goals li::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 3px;
  width: 9px;
  height: 9px;
  border: 1px solid var(--muted);
  border-radius: 3px;
}

.challenge-goals li.done {
  color: var(--text);
}

.challenge-goals li.done::before {
  content: "✓";
  border-color: var(--ok);
  background: rgb(86 194 140 / 18%);
  color: var(--ok);
  font-size: 9px;
  line-height: 9px;
  text-align: center;
}

.challenge-banner {
  padding: 7px 9px;
  border-radius: 8px;
  font-size: 12px;
}

.challenge-banner.passed {
  background: rgb(86 194 140 / 14%);
  border: 1px solid rgb(86 194 140 / 45%);
  color: var(--ok);
}

.challenge-banner.failed {
  background: rgb(217 106 90 / 12%);
  border: 1px solid rgb(217 106 90 / 45%);
  color: var(--danger);
}

.challenge-actions {
  display: flex;
  gap: 6px;
}

.challenge-action {
  flex: 1;
  padding: 6px 0;
  background: rgb(255 255 255 / 5%);
  border: 1px solid var(--hairline-strong);
  border-radius: 8px;
  color: var(--text);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
}

.challenge-action:hover {
  background: rgb(255 255 255 / 10%);
}

/* Standing hint in the panel head — reopens the first-run intro dialog. */
.challenge-tutorial-link {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgb(231 231 234 / 72%);
  transition: color 150ms ease;
}

.challenge-tutorial-link:hover {
  color: var(--accent);
}

/* Circled "?" — marks the hint as a clickable help control. Inherits
   currentColor so the hover amber tints icon and text together. */
.challenge-tutorial-q {
  display: inline-grid;
  place-items: center;
  width: 13px;
  height: 13px;
  border: 1px solid currentColor;
  border-radius: 50%;
  font-size: 8px;
  letter-spacing: 0;
  line-height: 1;
}

/* ---- challenge first-run intro (challengeIntro.js) ----------------------- */
/* One-time interstitial over everything (like the app promo, z 100): what
   challenges are, and the tutorial that builds the skill they expect. */

.challenge-intro-backdrop {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  padding: 24px;
  background: rgb(0 0 0 / 62%);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

.challenge-intro {
  position: relative;
  width: 430px;
  max-width: 100%;
  max-height: 100%;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 24px 26px 20px;
  background: var(--panel);
  border: 1px solid var(--hairline-strong);
  border-radius: 14px;
}

.challenge-intro-close {
  position: absolute;
  top: 12px;
  right: 14px;
  font-size: 14px;
  color: var(--muted);
}

.challenge-intro-close:hover {
  color: var(--text);
}

.challenge-intro-title {
  margin: 0 0 2px;
  font-size: 18px;
  font-weight: 600;
}

.challenge-intro-blurb {
  margin: 0;
  font-size: 13px;
  line-height: 1.55;
  color: var(--muted);
}

.challenge-intro-figure {
  display: block;
  position: relative;
  margin-top: 6px;
  border: 1px solid var(--hairline-strong);
  border-radius: 10px;
  overflow: hidden;
  transition: border-color 150ms ease;
}

.challenge-intro-figure img {
  display: block;
  width: 100%;
  height: auto;
}

.challenge-intro-figure:hover {
  border-color: var(--accent-dim);
}

.challenge-intro-chip {
  position: absolute;
  right: 8px;
  bottom: 8px;
  padding: 3px 8px;
  background: rgb(0 0 0 / 70%);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  border: 1px solid var(--hairline-strong);
  border-radius: 6px;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--muted);
  transition: color 150ms ease;
}

.challenge-intro-figure:hover .challenge-intro-chip {
  color: var(--accent);
}

.challenge-intro-caption {
  margin: 0;
  font-size: 11px;
  line-height: 1.5;
  color: var(--muted);
}

.challenge-intro-cta {
  margin-top: 8px;
  padding: 11px 0;
  border: 1px solid var(--accent-dim);
  border-radius: 9px;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-align: center;
  color: var(--accent);
  text-decoration: none;
  transition: background 150ms ease;
}

.challenge-intro-cta:hover {
  background: var(--accent-faint);
}

.challenge-intro-skip {
  padding: 6px 0 2px;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  transition: color 150ms ease;
}

.challenge-intro-skip:hover {
  color: var(--text);
}

/* Sim-only debug controls — stacks just under the telemetry card (top-left). */
.overlay-sim {
  left: 14px;
  top: 92px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px 12px;
  background: rgb(0 0 0 / 66%);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
}

.sim-button {
  border: 1px solid var(--hairline-strong);
  border-radius: 8px;
  padding: 6px 10px;
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ctl-text);
  background: var(--ctl-glass);
  box-shadow: var(--ctl-sheen);
  transition: border-color 150ms ease, color 150ms ease, background 150ms ease;
}

.sim-button:hover:not(:disabled) {
  border-color: var(--ctl-edge-accent);
  background: var(--ctl-glass-hover);
  color: var(--ctl-accent);
}

.sim-button:disabled {
  color: var(--ctl-text-off);
  background: var(--ctl-field);
  box-shadow: none;
  cursor: progress;
}

.sim-metrics {
  margin: 0;
  font-size: 11px;
  color: var(--muted);
}

.overlay-joystick {
  --joystick-throw: 0;
  --joystick-strafe: 0;
  --joystick-forward: 0;
  --joystick-forward-strength: abs(var(--joystick-forward));
  --joystick-hit-size: 264px;
  --joystick-pad-size: 184px;
  left: 50%;
  bottom: 84px;
  transform: translateX(-50%);
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border: none;
}

/* Bottom-center bar: holds the speak pill + the Skills menu as separate pills.
   Transparent itself — each child carries its own glass (see .tts-bar). */
.overlay-tts {
  left: 50%;
  bottom: 18px;
  transform: translateX(-50%);
  display: flex;
  align-items: stretch;
  gap: 10px;
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border: none;
}

/* ---- profiling panel (Teleop) ------------------------------------------- */

/* Discrete toggle: a small glass pulse button, top-right corner. */
.profiling-toggle {
  position: absolute;
  top: 14px;
  right: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  background: var(--ctl-glass);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid var(--hairline-strong);
  border-radius: 9px;
  box-shadow: var(--ctl-sheen);
  color: var(--ctl-text);
  cursor: pointer;
  transition: color 150ms ease, border-color 150ms ease, background 150ms ease;
}

.profiling-toggle:hover {
  color: var(--text);
  background: var(--ctl-glass-hover);
  border-color: rgb(255 255 255 / 26%);
}

.profiling-toggle.active {
  color: var(--ctl-accent);
  border-color: var(--ctl-edge-accent);
}

/* Link failed/erroring — make the toggle unmistakably red even while closed. */
.profiling-toggle.failed {
  color: var(--ctl-danger);
  border-color: var(--ctl-edge-danger);
}

.profiling-value.bad {
  color: var(--danger);
}

.cam-strip {
  --pip-w: 113px;
  --pip-h: 113px;
  --pip-gap: 8px;
  --pip-inset: 20px;
  --pip-top: 14px;
  position: absolute;
  right: var(--pip-inset);
  top: var(--pip-top);
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: var(--pip-gap);
}

/* Teleop keeps a profiling toggle in the top-right corner; on that page only,
   start the strip left of it so the tiles can still sit flush with the top
   without colliding. The Agent page has no toggle (and sets its own offset). */
.cockpit:not(.agent-cockpit) .cam-strip {
  right: 54px;
}

.cam-tile {
  position: relative;
  width: var(--pip-w);
  filter: saturate(0.22);
  background: rgb(8 8 10 / 34%);
  backdrop-filter: blur(10px) saturate(1.08);
  -webkit-backdrop-filter: blur(10px) saturate(1.08);
  border: 1px solid rgb(255 255 255 / 28%);
  border-radius: 16px;
  box-shadow:
    inset 0 1px 0 rgb(255 255 255 / 16%),
    0 10px 28px rgb(0 0 0 / 22%);
  cursor: pointer;
  overflow: hidden;
  transform-origin: center;
  -webkit-tap-highlight-color: transparent;
  transition:
    filter 180ms ease,
    transform 160ms cubic-bezier(0.455, 0.03, 0.515, 0.955),
    border-color 150ms ease;
}

@media (hover: hover) and (pointer: fine) {
  .cam-tile:hover {
    z-index: 1;
    filter: saturate(1);
    border-color: rgb(255 255 255 / 48%);
    transform: translateY(-3px);
  }

  .cam-tile:hover .cam-tile-label {
    color: #fff;
    background-color: rgb(18 18 21 / 62%);
  }
}

.cam-tile:active {
  transform: translateY(0) scale(0.985);
}

.cam-tile:focus-visible {
  filter: saturate(1);
  outline: 2px solid rgb(255 255 255 / 72%);
  outline-offset: 3px;
}

/* Off: a compact dim pill showing just the camera name. */
.cam-tile.off {
  padding: 7px 12px;
  color: var(--muted);
  font-size: 12px;
  letter-spacing: 0.02em;
  text-transform: lowercase;
}

.cam-tile.off:hover {
  color: var(--text);
}

/* Live: a thumbnail of the feed. */
.cam-tile.live {
  display: grid;
  /* Explicit column: with only rows declared the column is content-sized, so a
     child that arrives oversized (the map canvas keeps its big-stage width
     until it is re-fitted) inflates the track, `width: 100%` resolves to the
     inflated track, and re-measuring just confirms it — a stable wrong size
     that overflow only hides. minmax(0, 1fr) pins the track to the tile. */
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: var(--pip-h) 25px;
  height: auto;
  background: rgb(8 8 10 / 48%);
}

.cam-tile.live > video,
.cam-tile.live > canvas,
.cam-tile.live > .cam-map-host {
  grid-row: 1;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Feed requested but not flowing yet — dim the tile so it reads as warming up. */
.cam-tile.connecting video {
  opacity: 0.25;
}

.cam-tile-label {
  position: static;
  grid-row: 2;
  display: flex;
  align-items: center;
  height: 25px;
  padding: 0 9px;
  background: rgb(18 18 21 / 42%);
  backdrop-filter: blur(12px) saturate(1.08);
  -webkit-backdrop-filter: blur(12px) saturate(1.08);
  border-top: 1px solid rgb(255 255 255 / 18%);
  color: rgb(255 255 255 / 82%);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  pointer-events: none;
  transition: color 150ms ease, background-color 150ms ease;
}

/* Map view — same ladder as a camera. As a thumbnail it's a tile-sized canvas host. */
.cam-tile-map {
  height: auto;
  background: #000;
}

.cam-map-host {
  position: relative; /* the memory cards anchor to the map, not the tile */
  width: 100%;
  height: 100%;
}

.cam-map-host .map-canvas {
  display: block;
}

/* The map's Locate / Go To controls only make sense at full size. */
.cam-map-host:not(.big) .map-controls {
  display: none;
}

/* Same for the memory cards: in the PiP thumbnail they would outsize and
   clip against the tile's overflow — the pulsing marks alone tell the story. */
.cam-map-host:not(.big) .mem-card,
.cam-map-host:not(.big) .mem-search-card {
  display: none;
}

/* On the cockpit stage the telemetry card owns the very corner (it paints
   over the map) — start the controls just below it. */
.cam-map-host.big .map-controls {
  top: 72px;
}

/* Map promoted to the big stage: full-bleed under the control overlays. Inserted as the stage's first
   child, so DOM order keeps the overlays (and the strip) painting on top; the video stage hides. */
.cam-map-host.big {
  position: absolute;
  inset: 0;
  background: #000;
}

.cam-map-primary .video-stage {
  display: none;
}

/* The sim's feed frame is opaque and paints after the map host (which is the
   cockpit's first child, so the overlays win on DOM order), which left a
   promoted map hidden behind it. Give the map the frame's own box and lift it
   over the frame; the overlays sit at z-index >= 5 and still paint on top. */
.agent-cockpit.agent-sim .cam-map-host.big {
  z-index: 1;
}

@media (min-width: 1401px) {
  /* Inset by the frame's 1px border rather than drawing a second one, so the
     map sits in the frame the same way the feed does and the hairline stays
     whatever the frame says it is. 17px radius is the frame's 18px less that
     border, matching the video. */
  .agent-cockpit.agent-sim .cam-map-host.big {
    top: calc(var(--agent-dock-gutter) + 1px);
    right: auto;
    bottom: auto;
    left: calc(var(--agent-dock-gutter) + 1px);
    width: calc(var(--agent-frame-width) - 2px);
    height: auto;
    aspect-ratio: 4 / 3;
    overflow: hidden;
    border-radius: 17px;
  }
}

/* Panel sits just below the toggle; denser glass since it's over the feed. */
.profiling {
  position: absolute;
  top: 54px;
  right: 14px;
  z-index: 2; /* paint above the camera PiP strip */
  width: 232px;
  padding: 11px 14px;
  background: rgb(0 0 0 / 66%);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border: 1px solid var(--hairline);
  border-radius: 11px;
  user-select: none;
  -webkit-user-select: none;
}

.profiling-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}

.profiling-hint {
  font-size: 10px;
  color: var(--muted);
  border: 1px solid var(--hairline-strong);
  border-radius: 4px;
  padding: 0 5px;
  line-height: 1.5;
}

.profiling-grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 11px 10px;
}

.profiling-item {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.profiling-row {
  display: flex;
  align-items: baseline;
  gap: 3px;
}

.profiling-value {
  font-size: 14px;
  color: var(--text);
}

.profiling-unit {
  font-size: 10px;
  color: var(--muted);
}

/* The jitter buffer delay is the headline metric — span the row and accent it. */
.profiling-item.headline {
  grid-column: 1 / -1;
}

.profiling-item.headline .profiling-value {
  font-size: 20px;
  color: var(--accent);
}

/* ---- record HUD (Collect page) ------------------------------------------ */

.overlay-record {
  top: 14px;
  left: 50%;
  transform: translateX(-50%);
  padding: 11px 14px;
}

.record-panel {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 10px;
  min-width: 320px;
}

.record-top {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 10px;
}

.record-skill {
  flex: 1;
  min-width: 0;
  /* Transparent so the overlay's own glass blur shows through — the dark-grey
     fill read as a heavy block against the rest of the HUD. The open dropdown
     popup is OS-rendered dark via the page's color-scheme: dark. */
  background-color: transparent;
  border: 1px solid var(--hairline-strong);
  border-radius: 8px;
  padding: 6px 30px 6px 10px;
  font: inherit;
  font-size: 12px;
  color: var(--text);
  transition: border-color 150ms ease;
}

.record-skill:hover:not(:disabled) {
  border-color: var(--accent-dim);
}

.record-skill:focus {
  outline: none;
  border-color: var(--accent);
}

.record-skill:disabled {
  color: var(--muted);
  border-color: var(--hairline);
  cursor: default;
}

/* Keep the closed control's selected label legible on the glass while the
   popup list stays dark (Firefox needs the explicit option background). */
.record-skill option {
  background: var(--panel);
  color: var(--text);
}

.record-count {
  font-size: 12px;
  color: var(--text);
  white-space: nowrap;
}

.record-link {
  font-size: 11px;
  color: var(--text);
  text-decoration: none;
  white-space: nowrap;
  transition: color 150ms ease;
}

.record-link:hover {
  color: var(--accent);
}

.record-controls {
  display: flex;
  justify-content: center;
  gap: 10px;
  margin-bottom: 10px;
}

.record-btn {
  flex: 1;
  border: 1px solid var(--hairline-strong);
  border-radius: 8px;
  padding: 9px 14px;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ctl-text);
  background: var(--ctl-glass);
  box-shadow: var(--ctl-sheen);
  white-space: nowrap;
  transition: border-color 150ms ease, color 150ms ease, background 150ms ease;
}

.record-btn:disabled {
  color: var(--ctl-text-off);
  background: var(--ctl-field);
  border-color: var(--hairline);
  box-shadow: none;
  cursor: default;
}

/* Record: danger-tinted outline; muted when the arm/dataset gate is unmet. */
.record-start:not(:disabled) {
  border-color: var(--ctl-edge-danger);
  color: var(--ctl-danger);
}

.record-start:not(:disabled):hover {
  background: var(--ctl-glass-hover);
  border-color: rgb(217 106 90 / 78%);
}

/* Stop: reads as live — danger edge + the running timer. */
.record-stop {
  border-color: rgb(217 106 90 / 78%);
  color: var(--ctl-danger);
  font-variant-numeric: tabular-nums;
}

.record-save:not(:disabled) {
  border-color: rgb(86 194 140 / 50%);
  color: #8fdcb4;
}

.record-save:not(:disabled):hover {
  background: var(--ctl-glass-hover);
  border-color: rgb(86 194 140 / 78%);
}

.record-discard:not(:disabled):hover {
  border-color: var(--ctl-edge-accent);
  background: var(--ctl-glass-hover);
  color: var(--ctl-accent);
}

.record-hint {
  margin: 0;
  text-align: center;
  letter-spacing: 0.08em;
  color: var(--text);
}

/* Green confirmation flash after a recorded movement is saved. */
.record-hint.ok {
  color: var(--ok);
}

/* Orphaned-recording recovery banner — an episode left open on the robot
   (e.g. one that survived a dropped connection). Danger-tinted to draw the eye. */
.record-orphan {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
  padding: 8px 12px;
  border: 1px solid rgb(217 106 90 / 50%);
  border-radius: 10px;
  background: rgb(217 106 90 / 14%);
}

.record-orphan-msg {
  flex: 1;
  color: var(--danger);
  letter-spacing: 0.04em;
}

.record-orphan-discard:not(:disabled) {
  border-color: rgb(217 106 90 / 50%);
  color: var(--danger);
}

.record-orphan-discard:not(:disabled):hover {
  background: rgb(217 106 90 / 14%);
}

.record-orphan-dismiss {
  padding: 4px 8px;
}

/* recorded-movement wizard (replaces the picker while a draft is recording) */
.record-wizard {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 320px;
}

.record-wizard-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.record-wizard-name {
  font-size: 13px;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.record-wizard-cancel {
  font-size: 11px;
  color: var(--muted);
  white-space: nowrap;
  transition: color 150ms ease;
}

.record-wizard-cancel:hover:not(:disabled) {
  color: var(--danger);
}

/* new-skill type chooser (mobile: AddSkillScreen cards) */
.collect-choice {
  display: flex;
  flex-direction: column;
  gap: 5px;
  text-align: left;
  padding: 14px 16px;
  background: var(--bg);
  border: 1px solid var(--hairline-strong);
  border-radius: 10px;
  transition: border-color 150ms ease, background 150ms ease;
}

.collect-choice:hover:not(:disabled) {
  border-color: var(--accent-dim);
  background: var(--accent-faint);
}

.collect-choice:disabled {
  opacity: 0.5;
  cursor: default;
}

.collect-choice-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
}

.collect-choice-desc {
  font-size: 12px;
  line-height: 1.5;
  color: var(--muted);
}

/* multiline guidelines field + the chooser's back link, reusing modal styling */
.modal-textarea {
  min-height: 64px;
  resize: vertical;
  line-height: 1.5;
}

.modal-back {
  align-self: flex-start;
  font-size: 11px;
  color: var(--muted);
  transition: color 150ms ease;
}

.modal-back:hover {
  color: var(--text);
}

/* ---- telemetry strip ----------------------------------------------------- */

.telemetry-overlay {
  z-index: 12;
  width: 360px;
  box-sizing: border-box;
  background: linear-gradient(135deg, rgb(18 18 21 / 72%), rgb(8 8 10 / 62%));
  border-color: rgb(255 255 255 / 14%);
  border-radius: 16px;
  box-shadow: 0 10px 28px rgb(0 0 0 / 24%);
}

.telemetry {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  column-gap: 0;
  row-gap: 9px;
  padding: 12px 14px;
}

.telemetry-item {
  min-width: 0;
  padding: 0 10px;
}

.telemetry-status-dot,
.telemetry-meta {
  display: none;
}

.telemetry-item-robot {
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  column-gap: 12px;
  padding-right: 0;
  padding-bottom: 9px;
  padding-left: 0;
  border-bottom: 1px solid rgb(255 255 255 / 10%);
}

.telemetry-item-robot .microlabel {
  display: none;
}

.telemetry-item-battery,
.telemetry-item-link,
.telemetry-item-agent {
  grid-column: span 2;
}

.telemetry-item-battery {
  align-items: flex-start;
  gap: 3px;
}

.telemetry-item-link,
.telemetry-item-agent {
  display: grid;
  grid-template-columns: 6px minmax(0, 1fr);
  grid-template-rows: auto auto;
  align-items: center;
  column-gap: 7px;
  row-gap: 3px;
}

.telemetry-item-link .microlabel,
.telemetry-item-agent .microlabel {
  grid-column: 1 / -1;
  grid-row: 1;
}

.telemetry-item-agent,
.telemetry-item-link {
  border-left: 1px solid rgb(255 255 255 / 10%);
}

.telemetry-item-battery {
  padding-left: 0;
}

.telemetry-item-agent {
  padding-right: 0;
}

.telemetry-item-link .telemetry-status-dot,
.telemetry-item-agent .telemetry-status-dot {
  display: block;
  grid-column: 1;
  grid-row: 2;
  width: 6px;
  height: 6px;
  background: rgb(231 231 234 / 24%);
  border-radius: 50%;
}

.telemetry-item-link .telemetry-value,
.telemetry-item-agent .telemetry-value {
  grid-column: 2;
  grid-row: 2;
}

.telemetry-item.live .telemetry-status-dot {
  background: var(--ok);
  box-shadow: 0 0 5px rgb(86 194 140 / 58%);
}

.telemetry-item.warn .telemetry-status-dot {
  background: var(--danger);
  box-shadow: 0 0 5px rgb(255 105 97 / 52%);
}

.telemetry .microlabel {
  color: rgb(231 231 234 / 58%);
  font-size: 8px;
  letter-spacing: 0.14em;
}

.telemetry-value {
  display: block;
  flex: 1;
  min-width: 0;
  overflow: hidden;
  color: var(--text);
  font-size: 11.5px;
  white-space: nowrap;
}

.telemetry-item-robot .telemetry-value {
  color: #fff;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.02em;
}

.telemetry-item-robot .telemetry-meta {
  display: block;
  color: rgb(231 231 234 / 52%);
  font-size: 9px;
}

.telemetry-item.live .telemetry-value {
  color: var(--text);
}

.telemetry-item.warn .telemetry-value {
  color: var(--danger);
}

.telemetry-value-track {
  display: inline-flex;
  width: max-content;
  transform: translateX(0);
}

.telemetry-value-duplicate {
  display: none;
}

.telemetry-value.overflowing .telemetry-value-track {
  gap: 24px;
  will-change: transform;
  animation: telemetry-marquee var(--telemetry-duration) linear infinite;
}

.telemetry-value.overflowing .telemetry-value-duplicate {
  display: inline;
}

/* ---- joystick ------------------------------------------------------------ */

.joystick-hit-target {
  display: grid;
  grid-template-rows: 1fr var(--joystick-pad-size);
  justify-items: center;
  width: var(--joystick-hit-size);
  height: var(--joystick-hit-size);
  touch-action: none;
  cursor: default;
}

.joystick-hit-target.engaged,
.joystick-hit-target.engaged .joystick-pad {
  cursor: grabbing;
}

.joystick-hit-target > * {
  grid-area: 2 / 1;
  place-self: center;
}

.joystick-pad {
  position: relative;
  width: var(--joystick-pad-size);
  height: var(--joystick-pad-size);
  border-radius: 50%;
  cursor: grab;
  background:
    radial-gradient(
      circle at 50% calc(50% - var(--joystick-forward) * 58%),
      rgb(255 255 255 / calc(var(--joystick-forward-strength) * 0.88)) 0%,
      rgb(255 255 255 / calc(var(--joystick-forward-strength) * 0.56)) 22%,
      rgb(255 255 255 / calc(var(--joystick-forward-strength) * 0.3)) 40%,
      rgb(255 255 255 / calc(var(--joystick-forward-strength) * 0.12)) 55%,
      rgb(255 255 255 / 0%) 72%
    ),
    rgb(8 8 10 / 38%);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  border: 1.25px solid
    rgb(255 255 255 / calc(0.28 + var(--joystick-forward-strength) * 0.5));
}

.joystick-direction {
  position: absolute;
  width: 14px;
  height: 14px;
  color: rgb(255 255 255 / calc(0.38 + var(--joystick-direction-strength) * 0.52));
  opacity: calc(0.35 + var(--joystick-direction-strength) * 0.65);
}

.joystick-direction::before {
  content: "";
  position: absolute;
  inset: 3px;
  border-left: 1.5px solid currentColor;
  border-top: 1.5px solid currentColor;
  transform: rotate(45deg);
}

.joystick-direction-forward {
  --joystick-direction-strength: max(0, var(--joystick-forward));
  top: 10%;
  left: 50%;
  transform: translate(-50%, 0);
}

.joystick-direction-backward {
  --joystick-direction-strength: max(0, calc(-1 * var(--joystick-forward)));
  bottom: 10%;
  left: 50%;
  transform: translate(-50%, 0) rotate(180deg);
}

.joystick-direction-right {
  --joystick-direction-strength: max(0, var(--joystick-strafe));
  right: 10%;
  top: 50%;
  transform: translate(0, -50%) rotate(90deg);
}

.joystick-direction-left {
  --joystick-direction-strength: max(0, calc(-1 * var(--joystick-strafe)));
  left: 10%;
  top: 50%;
  transform: translate(0, -50%) rotate(-90deg);
}

.joystick-knob {
  width: calc(var(--joystick-pad-size) * 34 / 92);
  height: calc(var(--joystick-pad-size) * 34 / 92);
  border-radius: 50%;
  box-sizing: content-box;
  pointer-events: none;
  background: rgb(245 245 248 / 28%);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-style: solid;
  border-color: color-mix(
    in srgb,
    rgb(255 255 255 / 48%) calc((1 - var(--joystick-forward-strength)) * 100%),
    #eead55 calc(var(--joystick-forward-strength) * 100%)
  );
  border-width:
    calc(1.5px + var(--joystick-throw) * 3.5px + var(--joystick-forward-strength) * 1.25px);
  transition: transform 130ms cubic-bezier(0.215, 0.61, 0.355, 1);
}

.overlay-joystick:has(.joystick-hit-target.engaged) .joystick-knob,
.overlay-joystick:has(.joystick-hit-target.mirroring) .joystick-knob {
  transition: none;
}

/* ---- WASD chips ----------------------------------------------------------- */

.wasd {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.wasd-row {
  display: flex;
  gap: 4px;
}

.wasd-row:first-child {
  padding-left: 30px; /* center W above S */
}

.wasd-chip {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border: 1px solid var(--hairline-strong);
  border-radius: 6px;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ctl-text);
  background: var(--ctl-field);
  transition: color 100ms ease, border-color 100ms ease, background 100ms ease;
}

.wasd-chip.held {
  color: var(--ctl-accent);
  border-color: var(--ctl-edge-accent);
  background: var(--ctl-glass);
}

.wasd-hint {
  margin-top: 7px;
  font-size: 9px;
}

/* ---- speed modes ----------------------------------------------------------- */

.speed-modes {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

.sm-label {
  font-size: 9px;
  letter-spacing: 0.08em;
  color: var(--ctl-text);
}

.sm-group {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid var(--hairline-strong);
  border-radius: 9px;
  /* The group is the control here — one base behind the whole segmented stack,
     so the buttons stay hairline-separated rather than each carrying its own. */
  background: var(--ctl-glass);
  box-shadow: var(--ctl-sheen);
}

.sm-btn {
  padding: 6px 9px;
  border: 0;
  border-bottom: 1px solid var(--hairline-strong);
  background: transparent;
  color: var(--ctl-text);
  font: inherit;
  font-size: 10px;
  cursor: pointer;
  transition: background 150ms ease, color 150ms ease;
}

.sm-btn:last-child {
  border-bottom: 0;
}

.sm-btn:hover {
  color: var(--text);
  background: rgb(255 255 255 / 6%);
}

.sm-btn.on {
  background: rgb(232 163 61 / 14%);
  color: var(--ctl-accent);
}

/* ---- head tilt ------------------------------------------------------------ */

.head-tilt {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}

.ht-label {
  font-size: 9px;
  /* Same rail as the speed picker, same problem: plain grey washes out over a
     bright camera view. Kept in step so the rail reads as one control group. */
  color: var(--ctl-text);
}

.ht-track {
  position: relative;
  width: 26px;
  height: 190px;
  touch-action: none;
  cursor: ns-resize;
}

.ht-rail {
  position: absolute;
  left: 50%;
  top: 0;
  bottom: 0;
  width: 1px;
  margin-left: -0.5px;
  background: var(--hairline-strong);
}

.ht-zero {
  position: absolute;
  left: 50%;
  width: 9px;
  height: 1px;
  transform: translate(-50%, -50%);
  background: var(--hairline-strong);
}

.ht-actual {
  position: absolute;
  left: 50%;
  width: 15px;
  height: 1px;
  transform: translate(-50%, -50%);
  background: var(--accent-dim);
  transition: top 300ms ease;
}

.ht-thumb {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  background: #b9b9c1;
  transition: background 150ms ease;
}

.head-tilt.engaged .ht-thumb {
  background: var(--accent);
}

.ht-readout {
  font-size: 10px;
  color: var(--muted);
  min-height: 14px;
}

.head-tilt.engaged .ht-readout {
  color: var(--accent);
}

/* ---- audio toggle ---------------------------------------------------------- */

.icon-toggle {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border: 1px solid var(--hairline-strong);
  border-radius: 9px;
  color: var(--ctl-text);
  background: var(--ctl-glass);
  box-shadow: var(--ctl-sheen);
  transition: color 150ms ease, border-color 150ms ease, background 150ms ease;
}

.icon-toggle:hover {
  color: var(--text);
  background: var(--ctl-glass-hover);
}

.icon-toggle.active {
  color: var(--ctl-accent);
  border-color: var(--ctl-edge-accent);
}

.audio-toggle:not(.active) .wave {
  opacity: 0.2;
}

/* ---- TTS bar ---------------------------------------------------------------- */

.tts-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  width: min(440px, 56vw);
  padding: 5px 16px 5px 18px;
  background: var(--ctl-glass);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-radius: 999px;
  border: 1px solid var(--hairline-strong);
  box-shadow: var(--ctl-sheen);
  transition: border-color 200ms ease;
}

.tts-bar.sent {
  border-color: var(--ctl-edge-accent);
}

.tts-input {
  flex: 1;
  min-width: 0;
  background: transparent;
  border: none;
  padding: 7px 0;
  font: inherit;
  color: var(--text);
}

.tts-input:focus {
  outline: none;
}

.tts-input::placeholder {
  color: rgb(255 255 255 / 25%);
}

/* Text affordance inside the pill, not a pill of its own — the bar already
   carries the base, so this only needs the colour lift. */
.tts-hint {
  font: inherit;
  font-size: 11px;
  color: var(--ctl-text);
  background: none;
  border: 0;
  padding: 4px 8px;
  cursor: pointer;
  transition: color 150ms ease;
}

.tts-hint:hover {
  color: var(--ctl-accent);
}

.tts-bar.sent .tts-hint {
  color: var(--ctl-accent);
}

/* ---- leader arm panel -------------------------------------------------------- */

.overlay-arm {
  right: 14px;
  bottom: 14px;
  /* This panel sits over the live camera feed, so the default 40% glass left
     the labels washed out. Denser backdrop + more blur for legibility. */
  background: rgb(0 0 0 / 66%);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
}

.arm-panel {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px 14px;
  width: 168px;
}

/* Collapse toggle — hidden on desktop (panel is always open); shown only on
   the mobile layout below, where the panel starts collapsed. */
.arm-header {
  display: none;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  color: rgb(255 255 255 / 62%);
}

.arm-caret {
  transition: transform 150ms ease;
}

.arm-panel:not(.collapsed) .arm-caret {
  transform: rotate(90deg);
}

.arm-panel .microlabel {
  color: rgb(255 255 255 / 62%);
}

.arm-hint {
  margin: 0;
  font-size: 11px;
  line-height: 1.5;
  color: rgb(255 255 255 / 58%);
}

.arm-status {
  margin: 0;
  font-size: 12px;
  color: var(--text);
}

.arm-status.warn {
  color: var(--danger);
  font-size: 11px;
}

.arm-joints {
  display: flex;
  gap: 14px;
  height: 30px;
  padding: 0 2px;
}

.arm-joint {
  position: relative;
  width: 1px;
  background: var(--hairline-strong);
}

.arm-joint-dot {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  background: #b9b9c1;
}

.arm-panel:has(.arm-engage.active) .arm-joint-dot {
  background: var(--accent);
}

.arm-button {
  border: 1px solid var(--hairline-strong);
  border-radius: 8px;
  padding: 7px 0;
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ctl-text);
  background: var(--ctl-glass);
  box-shadow: var(--ctl-sheen);
  transition: border-color 150ms ease, color 150ms ease, background 150ms ease;
}

.arm-button:hover:not(:disabled) {
  border-color: var(--ctl-edge-accent);
  background: var(--ctl-glass-hover);
  color: var(--ctl-accent);
}

.arm-button:disabled {
  color: var(--ctl-text-off);
  background: var(--ctl-field);
  box-shadow: none;
  cursor: progress;
}

.arm-engage.active {
  border-color: var(--ctl-edge-accent);
  color: var(--ctl-accent);
}

/* Engage sits next to a small icon button that copies the joint ticks. */
.arm-engage-row {
  display: flex;
  gap: 8px;
}

.arm-engage-row .arm-engage {
  flex: 1;
}

.arm-copy {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 7px 9px;
  color: var(--muted);
}

.arm-copy.copied {
  border-color: var(--ok);
  color: var(--ok);
}

.arm-note {
  font-size: 9px;
}

.arm-note.warn {
  color: var(--danger);
}

.arm-divider {
  height: 1px;
  background: var(--hairline);
  margin: 2px 0;
}

.arm-services {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.arm-actions {
  display: flex;
  gap: 8px;
}

.arm-actions .arm-button {
  flex: 1;
  padding: 6px 2px;
}

/* Torque toggle: small cap over a green ON / red OFF state, like the app. */
.arm-torque {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
}

.arm-torque-cap {
  font-size: 8px;
  letter-spacing: 0.1em;
  color: var(--muted);
}

.arm-torque-state {
  font-size: 11px;
  letter-spacing: 0.08em;
  color: var(--muted);
}

.arm-torque.on {
  border-color: rgb(86 194 140 / 50%);
}

.arm-torque.on .arm-torque-state {
  color: var(--ok);
}

.arm-torque.off {
  border-color: rgb(217 106 90 / 50%);
}

.arm-torque.off .arm-torque-state {
  color: var(--danger);
}

/* Keep the semantic colour on hover instead of the generic amber. */
.arm-torque.on:hover:not(:disabled) {
  border-color: var(--ok);
  color: inherit;
}

.arm-torque.off:hover:not(:disabled) {
  border-color: var(--danger);
  color: inherit;
}


/* ---- logging page --------------------------------------------------------- */

.logging {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.log-grid {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: 1fr 360px; /* log | log-sources panel */
  grid-template-rows: minmax(0, 1fr); /* bound the row so inner lists can scroll */
}

/* shared page header (Logs / Datasets / Training) */
.page-head {
  flex: none;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 16px 20px;
  border-bottom: 1px solid var(--hairline);
}

.page-title {
  margin: 0;
  font-size: 19px;
  font-weight: 600;
}

/* Title with a leading identity glyph (Nav wears the mobile app's map pin). */
.page-title-iconed {
  display: flex;
  align-items: center;
  gap: 7px;
}

.page-title-iconed svg {
  flex: none;
  width: 19px;
  height: 19px;
  color: var(--muted);
}

.log-main {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
}

.log-side {
  border-left: 1px solid var(--hairline);
  overflow-y: auto;
  min-height: 0;
}

/* Phones: sources pane as a toggleable slide-over (button lives in .page-head). */
.sources-toggle {
  display: none;
  margin-left: auto;
  padding: 6px 14px;
  font: inherit;
  font-size: 13px;
  color: var(--text);
  background: var(--glass);
  border: 1px solid var(--hairline);
  border-radius: 999px;
  cursor: pointer;
}

.sources-backdrop {
  display: none;
}

@media (max-width: 700px) {
  .log-grid {
    grid-template-columns: 1fr;
  }

  .sources-toggle {
    display: inline-flex;
  }

  .log-side {
    display: none;
  }

  .log-grid.sources-open .log-side {
    display: block;
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: 60; /* above the rail (40) */
    width: min(85vw, 360px);
    background: var(--bg);
    box-shadow: -16px 0 48px rgb(0 0 0 / 55%);
  }

  /* Tap anywhere off the drawer to close it. */
  .log-grid.sources-open .sources-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 55;
    background: rgb(0 0 0 / 45%);
  }

  /* Fixed columns leave the message a few characters wide on a phone:
     meta on one line, the message full-width beneath it. */
  .log-cols {
    display: none;
  }

  .log-row {
    grid-template-columns: auto auto 1fr;
    grid-template-areas:
      "time level source"
      "msg msg msg";
    align-items: center;
    row-gap: 0;
    column-gap: 10px;
    padding: 3px 16px;
  }

  .log-row .col-time {
    grid-area: time;
  }

  .log-row .col-level {
    grid-area: level;
  }

  .log-row .col-source {
    grid-area: source;
  }

  .log-row .col-msg {
    grid-area: msg;
  }
}

/* "LOGS" headline above the toolbar */
.logs-title {
  padding: 14px 16px 0;
}

/* toolbar */
.log-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px 12px;
  border-bottom: 1px solid var(--hairline);
}

/* breadcrumb pill: "Source: launch › node   N errors" */
.logs-crumb {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 6px 11px;
  border: 1px solid var(--hairline-strong);
  border-radius: 8px;
  max-width: 46%;
}

.logs-errbadge {
  flex: none;
  padding: 2px 7px;
  border-radius: 5px;
  font-size: 10.5px;
  color: var(--danger);
  background: rgb(217 106 90 / 14%);
}

.log-bar-spacer {
  flex: 1;
}

.log-seg {
  display: flex;
  border: 1px solid var(--hairline-strong);
  border-radius: 7px;
  overflow: hidden;
}

.log-seg-btn {
  padding: 5px 11px;
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}

.log-seg-btn.active {
  background: var(--accent-faint);
  color: var(--accent);
}

.log-select {
  background-color: transparent;
  border: 1px solid var(--hairline-strong);
  border-radius: 7px;
  padding: 5px 30px 5px 10px;
  font: inherit;
  font-size: 11px;
  color: var(--text);
}

.log-select:disabled {
  opacity: 0.4;
}

.log-pickers {
  display: inline-flex;
  gap: 8px;
}

.log-search {
  flex: 0 1 220px;
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--hairline-strong);
  padding: 5px 2px;
  font-size: 12px;
  color: var(--text);
}

.log-search:focus {
  outline: none;
  border-bottom-color: var(--accent);
}

.log-count {
  white-space: nowrap;
}

.log-btn {
  border: 1px solid var(--hairline-strong);
  border-radius: 7px;
  padding: 5px 10px;
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}

.log-btn:hover {
  color: var(--text);
  border-color: var(--accent-dim);
}

.log-btn.active {
  color: var(--ok);
  border-color: rgb(86 194 140 / 50%);
}

.log-btn.log-icon-btn {
  line-height: 0;
}

/* log list */
/* columns shared by the header and each log row */
.log-cols,
.log-row {
  display: grid;
  grid-template-columns: 104px 60px 172px 1fr;
  gap: 14px;
  align-items: baseline;
  padding: 2px 16px;
}

.log-cols {
  padding-top: 8px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--hairline);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
}

.log-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 6px 0;
  font-size: 12px;
  line-height: 1.55;
}

.log-row:hover {
  background: rgb(255 255 255 / 4%);
}

.col-time {
  color: var(--muted);
  opacity: 0.7;
  white-space: nowrap;
}

/* level badge */
.col-level {
  justify-self: start;
  padding: 1px 6px;
  border-radius: 4px;
  font-size: 10px;
  letter-spacing: 0.06em;
}

.lvl-debug { color: var(--muted); background: rgb(255 255 255 / 6%); }
.lvl-info { color: var(--ok); background: rgb(86 194 140 / 12%); }
.lvl-warn { color: var(--accent); background: rgb(232 163 61 / 14%); }
.lvl-error { color: var(--danger); background: rgb(217 106 90 / 14%); }

.col-source {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  cursor: pointer;
}

.col-source:hover {
  text-decoration: underline;
}

.col-msg {
  min-width: 0;
  color: var(--text);
  white-space: pre-wrap;
  word-break: break-word;
}

.log-row.sev-warn .col-msg {
  color: var(--accent);
}

.log-row.sev-error .col-msg {
  color: var(--danger);
}

.log-row.sev-debug .col-msg {
  color: var(--muted);
}

/* current-scope breadcrumb text inside .logs-crumb */
.log-scope {
  flex: 1;
  min-width: 0;
  font-size: 12px;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---- log sources panel (launch / process / node-logger) ------------------ */

.sources-head {
  padding: 12px 14px 10px;
  border-bottom: 1px solid var(--hairline);
}

.sources-modes {
  display: flex;
  gap: 4px;
  margin-top: 10px;
  border: 1px solid var(--hairline-strong);
  border-radius: 8px;
  padding: 3px;
}

.sources-mode {
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 7px 4px;
  border-radius: 6px;
  font-size: 11.5px;
  letter-spacing: 0.02em;
  color: var(--muted);
}

.sources-mode svg {
  flex: none;
  opacity: 0.8;
}

.sources-mode.active {
  background: var(--accent-faint);
  color: var(--accent);
}

.sources-filter {
  width: 100%;
  margin-top: 10px;
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--hairline-strong);
  padding: 6px 2px;
  font-size: 13px;
  color: var(--text);
}

.sources-filter:focus {
  outline: none;
  border-bottom-color: var(--accent);
}

.sources-filter::placeholder {
  color: rgb(255 255 255 / 25%);
}

.sources-list {
  display: flex;
  flex-direction: column;
  padding: 6px 0 8px;
}

.src-row {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 12px 8px 0;
  color: var(--text);
  cursor: pointer;
}

.src-row:hover {
  background: rgb(255 255 255 / 5%);
}

.src-row.selected {
  background: var(--accent-faint);
}

.src-row.selected .src-name {
  color: var(--accent);
}

.src-caret {
  flex: none;
  display: grid;
  place-items: center;
  width: 16px;
  height: 16px;
  color: var(--muted);
  transition: color 120ms ease;
}

.src-caret svg {
  transition: transform 120ms ease;
}

.src-caret.open svg {
  transform: rotate(90deg);
}

.src-row:hover .src-caret {
  color: var(--text);
}

.src-caret.leaf {
  visibility: hidden;
}

/* type icon, tinted by worst severity in the subtree */
.src-icon {
  flex: none;
  display: grid;
  place-items: center;
  color: var(--muted);
}

.src-icon.sev-ok {
  color: #7d8aa0;
}

.src-icon.sev-warn {
  color: var(--accent);
}

.src-icon.sev-error {
  color: var(--danger);
}

.src-name {
  flex: 1;
  min-width: 0;
  font-size: 13.5px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.src-sub {
  margin-left: 8px;
  font-size: 11px;
  color: var(--muted);
}

.src-count {
  flex: none;
  margin-right: 12px;
  font-size: 11.5px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.src-count.c-warn {
  color: var(--accent);
}

.src-count.c-error {
  color: var(--danger);
}

/* worded top-level badge ("11 errors" / "3 warnings") */
.src-count.badge {
  padding: 2px 8px;
  border-radius: 5px;
  font-size: 10.5px;
}

.src-count.badge.c-error {
  background: rgb(217 106 90 / 14%);
}

.src-count.badge.c-warn {
  background: rgb(232 163 61 / 14%);
}

/* ---- datasets page -------------------------------------------------------- */

.datasets {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.datasets-grid {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: 232px 1fr;
  grid-template-rows: minmax(0, 1fr);
  gap: 12px;
  padding: 0px 16px 16px;
}

/* Skills sidebar and the main episode area are each a rounded panel. */
.datasets-page-head {
  flex: none;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 16px 20px;
}

.datasets-side {
  border: 1px solid var(--hairline);
  border-radius: 12px;
  background: var(--panel);
  overflow-y: auto;
  min-height: 0;
}

.datasets-main {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  border: 1px solid var(--hairline);
  border-radius: 12px;
  background: var(--panel);
  overflow: hidden; /* clip the episode list/player to the rounded corners */
}

.datasets-empty {
  padding: 14px;
  color: var(--muted);
  font-size: 12px;
}

/* skill roster */
.skillpanel-head {
  padding: 18px 16px 12px;
}

.skillpanel-count {
  display: block;
  margin-top: 3px;
  font-size: 11px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* Section headers: "Training data" (operator demos) vs "Evaluation runs"
   (policy rollouts). Two different kinds of episodes — the icons + the eval
   tint keep them from ever reading as one flat list. */
.skillpanel-group {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 12px 16px 6px;
  color: var(--muted);
}
.skillpanel-group svg {
  flex: none;
  opacity: 0.8;
}
.skillpanel-group.eval {
  margin-top: 8px;
  border-top: 1px solid var(--hairline);
  padding-top: 14px;
  color: var(--eval);
}

.skillpanel-hint {
  margin: 0;
  padding: 4px 16px 10px;
  font-size: 11px;
  line-height: 1.5;
  color: var(--muted);
}

/* Evaluation dataset rows carry the eval accent instead of signal amber. */
.skill-row.eval .skill-count {
  color: var(--eval);
  opacity: 0.85;
}
.skill-row.eval.active {
  background: var(--eval-faint);
  box-shadow: inset 2px 0 0 var(--eval);
}
.skill-row.eval.active .skill-name {
  color: var(--eval);
}

.skill-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 9px;
  width: 100%;
  padding: 8px 16px;
  text-align: left;
  color: var(--text);
}

.skill-row:hover {
  background: rgb(255 255 255 / 3%);
}

/* selected skill — same highlight as the training page's selected run */
.skill-row.active {
  background: var(--accent-faint);
  box-shadow: inset 2px 0 0 var(--accent);
}

.skill-row.active .skill-name {
  color: var(--accent);
}

.skill-name {
  font-size: 13px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.skill-count {
  flex: none;
  font-size: 10px;
  color: var(--muted);
}

/* episode detail */
.episodes {
  /* shared grid template so the column header and rows line up */
  --ep-grid: minmax(0, 1.6fr) 1fr 0.7fr 0.95fr 56px;
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}

.episodes-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  padding: 18px 20px 14px;
}

.episodes-title {
  margin: 0;
  font-size: 19px;
  font-weight: 600;
}

.episodes-sub {
  margin: 5px 0 0;
  font-size: 12px;
  color: var(--muted);
}

.episodes-ready {
  color: var(--ok);
}

.episodes-preparing {
  color: var(--accent);
}

.episodes-tools {
  display: flex;
  align-items: center;
  gap: 8px;
}

.episodes-search {
  width: 180px;
  background: var(--panel);
  border: 1px solid var(--hairline);
  border-radius: 8px;
  padding: 7px 11px;
  font-size: 12px;
  color: var(--text);
}

.episodes-search:focus {
  outline: none;
  border-color: var(--accent-dim);
}

.episodes-tool {
  height: 32px;
  padding: 0 12px;
  background-color: var(--panel);
  border: 1px solid var(--hairline);
  border-radius: 8px;
  font-size: 12px;
  color: var(--muted);
}

/* .episodes-tool is also used on buttons — only selects need chevron clearance. */
select.episodes-tool {
  padding: 0 30px 0 10px;
}

.episodes-tool:hover {
  color: var(--text);
  border-color: var(--accent-dim);
}

/* "+ Collect" is an <a> jumping to the Collect page — match the tool height
   and tint it as the primary action on the episode list. */
.episodes-collect {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  color: var(--accent);
  border-color: var(--accent-dim);
}

.episodes-collect:hover {
  color: var(--accent);
  background: var(--accent-faint);
}

.episodes-colhead {
  display: grid;
  grid-template-columns: var(--ep-grid);
  align-items: center;
  gap: 16px;
  padding: 10px 20px;
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
}

.episodes-colhead .col {
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
}

.episodes-rows {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 6px 0;
}

.episode-row {
  display: grid;
  grid-template-columns: var(--ep-grid);
  align-items: center;
  gap: 16px;
  padding: 9px 20px;
}

.episode-row:hover {
  background: rgb(255 255 255 / 3%);
}

.episode-row.clickable {
  cursor: pointer;
}

/* hovered episode — same highlight as the training page's selected run */
.episode-row.clickable:hover {
  background: var(--accent-faint);
  box-shadow: inset 2px 0 0 var(--accent);
}

.ep-cell {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}

.ep-dot {
  flex: none;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #5a5a63;
}

.episode-ready .ep-dot {
  background: var(--ok);
}

.episode-preparing .ep-dot {
  background: var(--accent);
}

.ep-thumb {
  flex: none;
  width: 84px;
  height: 48px;
  border-radius: 7px;
  overflow: hidden;
  background: #000;
  border: 1px solid var(--hairline);
}

.ep-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.ep-id {
  font-size: 14px;
  color: var(--text);
}

.ep-recorded {
  font-size: 13px;
  color: var(--muted);
}

.ep-duration {
  font-size: 13px;
  color: var(--muted);
}

/* label dropdown (shared by the list column and the player header) */
.ep-label {
  display: flex;
  align-items: center;
}

.ep-label-select {
  -webkit-appearance: none;
  appearance: none;
  background: var(--panel)
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path d='M1 1l4 4 4-4' fill='none' stroke='%238a8a93' stroke-width='1.4'/></svg>")
    no-repeat right 9px center;
  border: 1px solid var(--hairline);
  border-radius: 8px;
  padding: 5px 26px 5px 11px;
  font: inherit;
  font-size: 12px;
  cursor: pointer;
}

.ep-label-select:focus {
  outline: none;
  border-color: var(--accent-dim);
}

.ep-label-select.is-success {
  color: var(--ok);
}

.ep-label-select.is-fail {
  color: var(--danger);
}

.ep-label-select option {
  color: var(--text);
  background: var(--panel);
}

/* row actions (prepare / delete) */
.ep-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 4px;
}

.ep-action-btn {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 7px;
  color: var(--muted);
  opacity: 0.75;
}

.ep-action-btn:hover {
  opacity: 1;
  background: rgb(255 255 255 / 6%);
}

.ep-action-btn.ep-delete:hover {
  color: var(--danger);
}

.episodes-foot {
  flex: none;
  margin: 0;
  padding: 12px;
  text-align: center;
  font-size: 11px;
  color: var(--muted);
}

.episode-prepare {
  border: 1px solid var(--hairline-strong);
  border-radius: 7px;
  padding: 5px 11px;
  font-size: 11px;
  color: var(--text);
}

.episode-prepare:hover:not(:disabled) {
  border-color: var(--accent-dim);
  color: var(--accent);
}

.episode-prepare:disabled {
  color: var(--muted);
  cursor: progress;
}

/* ---- evaluation view (skill.type == "eval") --------------------------------
   Judged policy rollouts, not training data: a sixth Policy column, a Result
   column with an explicit Unlabeled state + failure tags, per-policy filter
   chips, and the eval violet replacing signal amber throughout. */
.episodes--eval {
  --ep-grid: minmax(0, 1.35fr) minmax(0, 0.9fr) 0.95fr 0.6fr 1.15fr 84px;
}

.episodes-titlerow {
  display: flex;
  align-items: center;
  gap: 10px;
}

.episodes-kind {
  padding: 3px 8px;
  border: 1px solid var(--eval-dim);
  border-radius: 999px;
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--eval);
  background: var(--eval-faint);
}

.episodes-fail {
  color: var(--danger);
}

.episodes--eval .episode-row.clickable:hover {
  background: var(--eval-faint);
  box-shadow: inset 2px 0 0 var(--eval);
}

.episodes--eval .episodes-collect {
  color: var(--eval);
  border-color: var(--eval-dim);
}
.episodes--eval .episodes-collect:hover {
  background: var(--eval-faint);
}

/* per-policy filter chips (shown once ≥2 policies have runs here) */
.policy-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 0 20px 12px;
}

.policy-chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  max-width: 240px;
  padding: 4px 10px;
  border: 1px solid var(--hairline-strong);
  border-radius: 999px;
  font-size: 11px;
  color: var(--muted);
}
.policy-chip:hover {
  color: var(--text);
  border-color: var(--eval-dim);
}
.policy-chip.active {
  color: var(--eval);
  border-color: var(--eval-dim);
  background: var(--eval-faint);
}
.policy-chip-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.policy-chip-tally {
  flex: none;
  font-size: 10px;
  opacity: 0.85;
}

.ep-policy {
  font-size: 12px;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* provenance badge on training episodes that weren't teleop demonstrations */
.ep-src {
  flex: none;
  padding: 2px 7px;
  border-radius: 999px;
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.ep-src-rollout {
  color: var(--eval);
  background: var(--eval-faint);
  border: 1px solid var(--eval-dim);
}
.ep-src-replay {
  color: var(--type-replay);
  background: rgb(107 147 214 / 12%);
  border: 1px solid rgb(107 147 214 / 40%);
}

/* result cell: outcome select + failure-mode tags */
.ep-result {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}

.ep-label-select.is-unlabeled {
  color: var(--muted);
}

.ep-tags {
  display: flex;
  gap: 4px;
  min-width: 0;
  overflow: hidden;
}

.ep-tag {
  flex: none;
  padding: 2px 7px;
  border-radius: 999px;
  border: 1px solid var(--hairline-strong);
  font-size: 10px;
  color: var(--muted);
  white-space: nowrap;
}
.ep-tag.more {
  border-style: dashed;
}

/* ---- episode context menu + promote flow ---------------------------------- */
.ctx-menu {
  position: fixed;
  z-index: 60;
  min-width: 210px;
  max-width: 280px;
  padding: 5px;
  border: 1px solid var(--hairline-strong);
  border-radius: 10px;
  background: var(--panel);
  box-shadow: 0 8px 28px rgb(0 0 0 / 55%);
}

.ctx-head {
  padding: 7px 10px 3px;
  color: var(--eval);
}

.ctx-item {
  display: block;
  width: 100%;
  padding: 7px 10px;
  border-radius: 7px;
  text-align: left;
  font-size: 12px;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ctx-item:hover {
  background: rgb(255 255 255 / 6%);
}
.ctx-item.danger:hover {
  color: var(--danger);
}

.ctx-sep {
  margin: 5px 6px;
  border-top: 1px solid var(--hairline);
}

.ctx-empty {
  margin: 0;
  padding: 4px 10px 8px;
  font-size: 11px;
  color: var(--muted);
}

.ep-toast {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 70;
  max-width: 360px;
  padding: 10px 14px;
  border: 1px solid var(--hairline-strong);
  border-radius: 10px;
  background: var(--panel);
  box-shadow: 0 8px 28px rgb(0 0 0 / 55%);
  font-size: 12px;
  color: var(--text);
}
.ep-toast.ok {
  border-color: var(--ok);
}
.ep-toast.fail {
  border-color: var(--danger);
}

/* provenance chips in the player header */
.prov-chip {
  flex: none;
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid var(--hairline-strong);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}
.prov-chip.rollout {
  color: var(--eval);
  border-color: var(--eval-dim);
  background: var(--eval-faint);
}
.prov-chip.policy {
  text-transform: none;
  letter-spacing: 0;
  max-width: 200px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.player-add {
  height: 32px;
  padding: 0 12px;
  border: 1px solid var(--eval-dim);
  border-radius: 8px;
  font-size: 12px;
  color: var(--eval);
}
.player-add:hover {
  background: var(--eval-faint);
}

/* episode player (MP4 replay) */
.datasets-pane {
  display: flex;
  flex-direction: column;
  min-height: 0;
  flex: 1;
}

.episode-player {
  display: flex;
  flex-direction: column;
  min-height: 0;
  flex: 1;
  gap: 16px;
  padding: 16px 20px 18px;
  overflow-y: auto;
}

/* breadcrumb header */
.player-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 14px;
}

.player-headinfo {
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 0;
}

/* skill title — same look as the episode-list title; clickable to go back */
.player-title {
  text-align: left;
  color: var(--text);
}

.player-title:hover {
  color: var(--accent);
}

.player-subrow {
  display: flex;
  align-items: center;
  flex-wrap: wrap; /* provenance chips (policy rollout · policy · tags) may overflow */
  gap: 8px 10px;
}

.player-nav {
  display: flex;
  gap: 4px;
}

.player-navbtn {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border: 1px solid var(--hairline-strong);
  border-radius: 7px;
  font-size: 15px;
  line-height: 1;
  color: var(--text);
}

.player-navbtn:hover:not(:disabled) {
  border-color: var(--accent-dim);
  color: var(--accent);
}

.player-navbtn:disabled {
  opacity: 0.35;
  cursor: default;
}

.player-actions {
  display: flex;
  align-items: center;
  gap: 10px;
}

.player-delete {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  border: 1px solid var(--hairline-strong);
  border-radius: 8px;
  padding: 6px 13px;
  font-size: 12px;
  color: var(--muted);
}

.player-delete:hover:not(:disabled) {
  border-color: var(--danger);
  color: var(--danger);
}

.player-delete:disabled {
  opacity: 0.5;
  cursor: progress;
}


/* video pair */
.video-pair {
  display: flex;
  gap: 12px;
  /* Size to the videos' own height (each cell follows its frame's aspect),
     rather than absorbing leftover vertical space and clamping the videos to
     whatever fits the screen. The player scrolls if the frames are tall. */
  align-items: flex-start;
}

.video-cell {
  position: relative;
  flex: 1; /* equal half-widths */
  min-width: 0;
  background: #000;
  border: 1px solid var(--hairline);
  border-radius: 10px;
  overflow: hidden;
}

.video-cell video {
  display: block;
  width: 100%;
  height: auto; /* height follows the frame's aspect — scales with width, never clamped */
}

.video-cell-label {
  position: absolute;
  top: 10px;
  left: 12px;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 7px;
  color: var(--text);
  text-shadow: 0 1px 3px rgb(0 0 0 / 70%);
}

.video-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #5a5a63;
}

.video-dot.live {
  background: var(--ok);
}

/* transport pill */
.episode-transport {
  flex: none;
  align-self: center;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 7px 10px;
  background: var(--panel);
  border: 1px solid var(--hairline);
  border-radius: 999px;
}

.transport-btn {
  flex: none;
  height: 30px;
  min-width: 34px;
  padding: 0 8px;
  border-radius: 999px;
  color: var(--muted);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  transition: color 120ms ease, background 120ms ease;
}

.transport-btn:hover {
  color: var(--text);
  background: rgb(255 255 255 / 5%);
}

.transport-play {
  width: 40px;
  height: 40px;
  margin: 0 2px;
  border: 1.5px solid var(--accent);
  color: var(--accent);
  font-size: 13px;
}

.transport-play:hover {
  background: var(--accent-faint);
  color: var(--accent);
}

.transport-speed {
  color: var(--text);
}

.transport-time {
  flex: none;
  margin-left: 6px;
  padding-left: 12px;
  border-left: 1px solid var(--hairline);
  font-size: 12px;
  color: var(--muted);
}

/* scrubber — custom track: amber fill up to --pct, hairline beyond */
.transport-scrub {
  -webkit-appearance: none;
  appearance: none;
  flex: none;
  width: 100%;
  height: 16px;
  background: transparent;
  cursor: pointer;
}

.transport-scrub::-webkit-slider-runnable-track {
  height: 3px;
  border-radius: 2px;
  background: linear-gradient(
    to right,
    var(--accent) var(--pct, 0%),
    var(--hairline-strong) var(--pct, 0%)
  );
}

.transport-scrub::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 12px;
  height: 12px;
  margin-top: -4.5px;
  border-radius: 50%;
  background: var(--accent);
  border: none;
  transition: box-shadow 120ms ease;
}

.transport-scrub:hover::-webkit-slider-thumb {
  box-shadow: 0 0 0 5px var(--accent-faint);
}

.transport-scrub::-moz-range-track {
  height: 3px;
  border-radius: 2px;
  background: var(--hairline-strong);
}

.transport-scrub::-moz-range-progress {
  height: 3px;
  border-radius: 2px;
  background: var(--accent);
}

.transport-scrub::-moz-range-thumb {
  width: 12px;
  height: 12px;
  border: none;
  border-radius: 50%;
  background: var(--accent);
}

/* telemetry panel (datasets episode player — distinct from the Teleop
   .telemetry strip; same name previously collided and stacked the Teleop bar) */
.player-telemetry {
  flex: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px 16px 14px;
  background: var(--panel);
  border: 1px solid var(--hairline);
  border-radius: 10px;
}

.telemetry-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.telemetry-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

.legend-item {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}

.legend-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
}

.telemetry-plot {
  position: relative;
  /* Fixed, compact height so the joint graph doesn't hog vertical space — the
     video pair (flex: 1) takes the rest and the frames can show in full. */
  height: 190px;
  flex: none;
}

.telemetry-svg {
  width: 100%;
  height: 100%;
  display: block;
}

.telemetry-playhead {
  stroke: var(--accent);
  stroke-width: 1;
  opacity: 0.8;
}

.telemetry-dot {
  position: absolute;
  width: 9px;
  height: 9px;
  margin: -4.5px 0 0 -4.5px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-faint);
  pointer-events: none;
}

/* hover guide + value tooltip */
.telemetry-hoverline {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--hairline-strong);
  pointer-events: none;
}

.telemetry-tip {
  position: absolute;
  top: 6px;
  z-index: 2;
  min-width: 92px;
  padding: 7px 9px;
  background: rgb(8 8 10 / 92%);
  border: 1px solid var(--hairline-strong);
  border-radius: 8px;
  transform: translateX(10px);
  pointer-events: none;
}

.telemetry-tip.flip {
  transform: translateX(calc(-100% - 10px));
}

/* y-axis tick labels for an absolutely-scaled trace series (profile chart) */
.trace-ytick {
  position: absolute;
  left: 4px;
  transform: translateY(-50%);
  font-size: 9px;
  line-height: 1;
  opacity: 0.8;
  pointer-events: none;
}

.tip-time {
  margin-bottom: 5px;
  padding-bottom: 5px;
  border-bottom: 1px solid var(--hairline);
  font-size: 10px;
  color: var(--muted);
}

.tip-row {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  line-height: 1.6;
}

.tip-label {
  color: var(--muted);
  min-width: 18px;
}

.tip-val {
  margin-left: auto;
  color: var(--text);
}

/* ---- training page -------------------------------------------------------- */

.training {
  position: absolute;
  inset: 0;
  overflow: hidden;
  display: flex; /* dashboard | run detail pane */
}

.training-dash,
.training-wrap {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
}

.training-dash {
  flex: 1;
  min-width: 0;
}

.training-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  padding: 18px 20px 14px;
}

.training-title {
  margin: 0;
  font-size: 19px;
  font-weight: 600;
}

.training-sub {
  margin: 5px 0 0;
  font-size: 12px;
  color: var(--muted);
}

.training-tools {
  display: flex;
  align-items: center;
  gap: 8px;
}

.training-train-btn {
  height: 32px;
  padding: 0 14px;
  border: 1px solid var(--accent-dim);
  border-radius: 8px;
  font-size: 12px;
  color: var(--accent);
}

.training-train-btn:hover {
  background: var(--accent-faint);
}

.training-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 4px 16px 24px;
}

.training-hero-host {
  padding: 0 16px;
}

/* "Running now" hero card */
.run-hero {
  display: flex;
  flex-direction: column;
  gap: 8px;
  border: 1px solid var(--hairline-strong);
  border-radius: 12px;
  background: var(--panel);
  padding: 16px 20px;
  margin: 10px 0 6px;
}

.hero-eyebrow {
  font-size: 10px;
  letter-spacing: 0.08em;
  color: var(--ok);
}

.hero-title {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 17px;
  font-weight: 600;
  text-align: left;
}

.hero-title:hover {
  color: var(--accent);
}

.hero-badge {
  font-size: 10px;
  letter-spacing: 0.04em;
  color: #5a8dee;
  background: rgb(90 141 238 / 14%);
  border-radius: 999px;
  padding: 2px 8px;
}

.hero-meta {
  font-size: 12px;
  color: var(--muted);
}

.hero-step {
  font-size: 13px;
  margin-top: 2px;
}

.hero-actions {
  display: flex;
  gap: 8px;
  margin-top: 6px;
}

/* run detail pane (right column) */
.training-detail {
  flex: none;
  width: 384px;
  height: 100%;
  overflow-y: auto;
  border-left: 1px solid var(--hairline);
  background: var(--panel);
}

/* Collapse the pane entirely when nothing is selected. */
.training-detail:has(.run-detail.is-empty) {
  display: none;
}

.run-detail {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 20px;
}

.rd-empty {
  color: var(--muted);
  font-size: 13px;
  padding: 8px 0;
}

.rd-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}

.rd-title {
  font-size: 16px;
  font-weight: 600;
  margin-top: 2px;
}

.rd-close {
  color: var(--muted);
  font-size: 14px;
  line-height: 1;
  padding: 2px 4px;
}

.rd-close:hover {
  color: var(--text);
}

.rd-statusrow {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
}

.rd-section {
  margin: 8px 0 -4px;
}

.rd-progress-line {
  font-size: 12px;
  color: var(--muted);
}

.rd-row {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  font-size: 13px;
  padding: 3px 0;
  border-bottom: 1px solid var(--hairline);
}

.rd-k {
  color: var(--muted);
}

.rd-v {
  text-align: right;
  word-break: break-word;
}

.rd-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 4px;
}

/* skill group */
.skill-group {
  border: 1px solid var(--hairline);
  border-radius: 12px;
  background: var(--panel);
  margin-bottom: 12px;
  padding-bottom: 6px;
  overflow: hidden; /* clip row hover/selected highlight to the rounded corners */
}

.skill-group-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 10px 20px 8px;
}

.skill-group-name {
  font-size: 14px;
  font-weight: 500;
}

.skill-group-meta {
  flex: 1;
  font-size: 11px;
  color: var(--muted);
}

.skill-group-train {
  flex: none;
  font-size: 12px;
  color: var(--accent);
}

.skill-group-train:hover {
  color: var(--text);
}

.skill-group-empty {
  padding: 4px 20px 6px;
  font-size: 12px;
  color: var(--muted);
}

/* dataset sync row */
.skill-group-dataset {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 2px 20px 10px;
}

.skill-group-dataset .tbar {
  flex: 1;
  max-width: 520px;
}

/* run outcome chip */
.run-outcome {
  font-size: 10px;
  letter-spacing: 0.04em;
  padding: 2px 8px;
  border-radius: 999px;
}

.oc-checking {
  color: var(--muted);
  background: rgb(255 255 255 / 6%);
}

.oc-ok {
  color: var(--ok);
  background: rgb(86 194 140 / 12%);
}

.oc-fail {
  color: var(--danger);
  background: rgb(217 106 90 / 14%);
}

/* logs modal */
.modal.modal-lg {
  width: 860px;
  height: 80%;
  max-height: 100%;
}

.logs-head-tools {
  display: flex;
  align-items: center;
  gap: 10px;
}

.logs-filesel {
  max-width: 360px;
}

.logs-copy-btn {
  display: inline-flex;
  color: var(--muted);
}

.logs-copy-btn:hover {
  color: var(--text);
}

.logs-copy-btn.copied {
  color: var(--ok);
}

.logs-live-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ok);
  animation: logs-live-pulse 1.6s ease-in-out infinite;
}

@keyframes logs-live-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.45; }
}

.logs-view {
  flex: 1;
  min-height: 0;
  overflow: auto;
  padding: 12px 16px;
  background: var(--bg);
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.5;
}

.log-line {
  white-space: pre-wrap;
  word-break: break-word;
  color: var(--text);
}

.log-line.is-stderr {
  color: var(--muted);
}

.log-line.is-err {
  color: var(--danger);
}

/* run row */
.run-row {
  display: grid;
  /* Fixed-width actions track (not `auto`): each row is its own grid, so an
     `auto` track would size to that row's buttons and the fr columns would
     reflow — making the meta line shift left on rows that have buttons.
     Reserving a constant width keeps the left/meta columns aligned across rows. */
  grid-template-columns: minmax(220px, 1.1fr) minmax(0, 2fr) 240px;
  /* Baseline-align so the label, instance/meta line, and buttons sit on one
     line even when the middle column is taller (progress bar / error below). */
  align-items: baseline;
  gap: 16px;
  padding: 10px 20px;
  cursor: pointer;
}

.run-row:hover {
  background: rgb(255 255 255 / 3%);
}

.run-row.is-selected {
  background: var(--accent-faint);
  box-shadow: inset 2px 0 0 var(--accent);
}

.run-left {
  display: flex;
  align-items: center;
  gap: 9px;
  min-width: 0;
}

.run-id {
  font-size: 13px;
  color: var(--muted);
}

.run-dot {
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #5a5a63;
}

.run-dot.s-1 { background: var(--accent); }
.run-dot.s-2,
.run-dot.s-4 { background: #5bc0de; }
.run-dot.s-5 { background: #5a8dee; }
.run-dot.s-6,
.run-dot.s-7 { background: var(--ok); }
.run-dot.s-3 { background: var(--danger); }
.run-dot.s-8 { background: #5a5a63; }
/* Derived state: terminal run whose results hold no checkpoint (training failed). */
.run-dot.s-failed { background: var(--danger); }

.run-btn.run-cancel:hover:not(:disabled) {
  border-color: var(--danger);
  color: var(--danger);
}

.run-label {
  font-size: 13px;
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
}

.run-daemon {
  font-size: 11px;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.run-mid {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.run-meta {
  font-size: 11px;
  color: var(--muted);
}

.run-error {
  font-size: 11px;
  color: var(--danger);
}

.run-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
}

.run-btn {
  border: 1px solid var(--hairline-strong);
  border-radius: 7px;
  padding: 5px 12px;
  font-size: 11px;
  color: var(--text);
}

.run-btn:hover:not(:disabled) {
  border-color: var(--accent-dim);
  color: var(--accent);
}

.run-btn:disabled {
  color: var(--muted);
  opacity: 0.6;
  cursor: default;
}

/* transfer / running progress bar */
.tbar {
  position: relative;
  height: 16px;
  border-radius: 5px;
  background: rgb(255 255 255 / 6%);
  overflow: hidden;
}

.tbar-fill {
  height: 100%;
  background: var(--accent-dim);
  transition: width 200ms ease;
}

.tbar-label {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  padding: 0 8px;
  font-size: 10px;
  color: var(--text);
}

.tbar-indeterminate .tbar-fill {
  width: 35%;
  animation: tbar-slide 1.4s ease-in-out infinite;
}

@keyframes tbar-slide {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(330%); }
}

/* configure modal */
.modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgb(0 0 0 / 55%);
  display: grid;
  place-items: center;
  padding: 24px;
  z-index: 5;
}

.modal {
  width: 420px;
  max-width: 100%;
  max-height: 100%;
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border: 1px solid var(--hairline-strong);
  border-radius: 12px;
  overflow: hidden;
}

.modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 18px;
  border-bottom: 1px solid var(--hairline);
}

.modal-title {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
}

.modal-close {
  font-size: 14px;
  color: var(--muted);
}

.modal-close:hover:not(:disabled) {
  color: var(--text);
}

.modal-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 18px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.modal-field {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.modal-field-label {
  font-size: 12px;
  color: var(--muted);
}

.modal-hint {
  font-size: 10px;
  color: var(--muted);
  opacity: 0.7;
}

.modal-select,
.modal-input {
  background-color: var(--bg);
  border: 1px solid var(--hairline-strong);
  border-radius: 8px;
  padding: 8px 10px;
  font: inherit;
  font-size: 13px;
  color: var(--text);
}

.modal-select {
  padding: 8px 30px 8px 10px;
}

.modal-select:focus,
.modal-input:focus {
  outline: none;
  border-color: var(--accent-dim);
}

.modal-epline {
  margin: -4px 0 0;
  font-size: 12px;
  color: var(--muted);
}

.modal-hyper {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding-top: 6px;
  border-top: 1px solid var(--hairline);
}

.modal-check {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 13px;
  color: var(--text);
  cursor: pointer;
}

.modal-check input {
  accent-color: var(--accent);
  width: 15px;
  height: 15px;
}

.modal-warn {
  margin: 0;
  font-size: 12px;
  color: var(--accent);
  min-height: 1em;
}

.modal-status {
  margin: 0;
  font-size: 12px;
  color: var(--muted);
  min-height: 1em;
}

.modal-start {
  margin-top: 4px;
  border: 1px solid var(--accent-dim);
  border-radius: 8px;
  padding: 11px 0;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
}

.modal-start:hover:not(:disabled) {
  background: var(--accent-faint);
}

.modal-start:disabled {
  color: var(--muted);
  border-color: var(--hairline-strong);
  cursor: default;
}

/* training empty state (no local runs) */
.training-empty {
  min-height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  text-align: center;
}

.training-empty p {
  margin: 0;
  max-width: 320px;
  color: var(--muted);
}

.training-empty-btn {
  border: 1px solid var(--accent-dim);
  border-radius: 9px;
  padding: 11px 22px;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
}

.training-empty-btn:hover {
  background: var(--accent-faint);
}

/* ---- motion --------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
  }
}

/* ---- profiling page ----------------------------------------------------- */
/* Record-and-graph view for ACT inference timing. Inherits .page-head /
   .page-title from the shared header. Note: the class is .profiling-page, not
   .profiling — the latter is the teleop overlay panel (absolute, 232px, pinned
   top-right), and sharing it would leak that positioning onto this full page. */

.profiling-page {
  display: flex;
  flex-direction: column;
  min-height: 0;
  height: 100%;
}

.prof-sub {
  align-self: center;
}

.prof-live {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  color: var(--muted);
}
.prof-live-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--muted);
}
.prof-live[data-state="live"] .prof-live-dot {
  background: var(--ok);
}
.prof-live[data-state="rec"] .prof-live-dot {
  background: var(--danger);
  animation: prof-pulse 1.2s ease-in-out infinite;
}
@keyframes prof-pulse {
  50% { opacity: 0.25; }
}

.prof-btn {
  padding: 7px 14px;
  border: 1px solid var(--hairline-strong);
  border-radius: 8px;
  color: var(--text);
  background: var(--panel);
  font-size: 12px;
}
.prof-btn:hover {
  border-color: var(--accent-dim);
}
.prof-btn-rec.active {
  border-color: var(--danger);
  color: var(--danger);
}
.prof-select {
  background-color: transparent;
  border: 1px solid var(--hairline-strong);
  border-radius: 8px;
  padding: 6px 30px 6px 10px;
  font: inherit;
  font-size: 12px;
  color: var(--text);
}
.prof-select:disabled {
  opacity: 0.4;
}

.prof-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 18px 20px 28px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.prof-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 10px;
}
.prof-stat {
  border: 1px solid var(--hairline);
  border-radius: 10px;
  padding: 12px 14px;
  background: var(--panel);
}
.prof-stat.warn {
  border-color: var(--danger);
}
.prof-stat-label {
  margin-bottom: 6px;
}
.prof-stat-value {
  font-size: 22px;
  font-weight: 600;
  line-height: 1.1;
}
.prof-stat.warn .prof-stat-value {
  color: var(--danger);
}
.prof-stat-foot {
  margin-top: 4px;
  font-size: 11px;
  color: var(--muted);
}

.prof-charts {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}
.prof-chart-card {
  border: 1px solid var(--hairline);
  border-radius: 12px;
  padding: 14px 16px 16px;
  background: var(--panel);
  min-width: 0;
}
.prof-chart-card:first-child {
  grid-column: 1 / -1;
}
.prof-chart-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 12px;
}
.prof-chart-title {
  font-size: 13px;
  font-weight: 600;
}
.prof-chart-body {
  min-height: 120px;
}

.prof-svg {
  width: 100%;
  height: 200px;
  display: block;
  border-bottom: 1px solid var(--hairline);
}
/* Plot area: a fixed-width y-axis tick column beside the stretched svg. */
.prof-plot {
  display: flex;
  gap: 8px;
  align-items: stretch;
}
.prof-plot-svg {
  position: relative; /* hover guide + value tip overlay anchor */
  flex: 1;
  min-width: 0;
}
.prof-yaxis {
  flex: 0 0 auto;
  width: 46px;
  height: 200px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: flex-end;
  font-size: 10px;
  line-height: 1;
  color: var(--muted);
  font-family: var(--font-mono);
}
.prof-axis {
  display: flex;
  justify-content: space-between;
  margin-top: 6px;
  font-size: 10px;
  color: var(--muted);
  font-family: var(--font-mono);
}
.prof-legend {
  display: flex;
  gap: 16px;
  margin-top: 8px;
  font-size: 11px;
  color: var(--muted);
}
.prof-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.prof-legend-swatch {
  width: 10px;
  height: 10px;
  border-radius: 2px;
  display: inline-block;
}

.prof-bar-row {
  display: grid;
  grid-template-columns: 120px 1fr 70px;
  align-items: center;
  gap: 12px;
  margin: 10px 0;
}
.prof-bar-name {
  font-size: 12px;
  color: var(--text);
}
.prof-bar-track {
  height: 14px;
  border-radius: 4px;
  background: var(--hairline);
  overflow: hidden;
}
.prof-bar-fill {
  height: 100%;
  border-radius: 4px;
  transition: width 0.2s ease;
}
.prof-bar-val {
  text-align: right;
  font-size: 12px;
  color: var(--muted);
}

.prof-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 120px;
  color: var(--muted);
}
.prof-hint {
  text-align: center;
}

/* Unified rollout control: skill picker + Run rollout / Profile only. */
.prof-rollout {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.prof-btn-quiet {
  color: var(--muted);
}
/* Arm recovery — an accent outline sets it apart from the run/utility buttons. */
.prof-btn-reboot {
  border-color: var(--accent-dim);
}
.prof-btn-reboot:disabled {
  opacity: 0.4;
}
.prof-btn-ok {
  border-color: var(--ok);
  color: var(--ok);
}
.prof-btn-fail {
  border-color: var(--danger);
  color: var(--danger);
}
.prof-auto {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--muted);
  cursor: pointer;
}

/* Rollout failure line: the actual error message, kept up until the next run. */
.prof-error {
  border: 1px solid var(--danger);
  border-radius: 10px;
  padding: 8px 14px;
  background: var(--panel);
  color: var(--danger);
  font-size: 12px;
  font-family: var(--font-mono);
}

/* Review bar: shown between run end and ✓/✗/Discard. */
.prof-review {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  border: 1px solid var(--accent-dim);
  border-radius: 10px;
  padding: 10px 14px;
  background: var(--panel);
}
.prof-review-text {
  font-size: 12px;
}
.prof-tags {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-left: auto;
}
.prof-tag {
  padding: 3px 9px;
  border: 1px solid var(--hairline-strong);
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  font-size: 11px;
}
.prof-tag.active {
  border-color: var(--danger);
  color: var(--danger);
}

/* Eval-session tally + per-rollout ribbon. */
.prof-session {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
}
.prof-session-ribbon {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 6px;
}
.prof-chip {
  padding: 3px 9px;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  font-size: 11px;
  color: var(--muted);
}
.prof-chip.ok {
  border-color: var(--ok);
  color: var(--ok);
}
.prof-chip.fail {
  border-color: var(--danger);
  color: var(--danger);
}

@media (max-width: 720px) {
  .prof-charts {
    grid-template-columns: 1fr;
  }
}

/* ---- skills menu (Teleop): collapsible launcher next to the speak bar --- */
/* A "Skills ▾" pill in the bottom bar opens a popover of skill rows above it. A
   parameter-less skill runs on click; a parameterized one expands inline to a
   small form (reusing the .skill-* form styles below) with a Run button. */

.skills-menu {
  position: relative;
  flex: 0 0 auto;
}

.skills-menu-btn {
  display: flex;
  align-items: center;
  gap: 9px;
  height: 100%;
  min-height: 40px;
  min-width: 230px;
  padding: 0 16px;
  font: inherit;
  color: var(--text);
  background: var(--ctl-glass);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid var(--hairline-strong);
  border-radius: 999px;
  box-shadow: var(--ctl-sheen);
  cursor: pointer;
  transition: border-color 150ms ease, background 150ms ease;
}

.skills-menu-btn:hover {
  background: var(--ctl-glass-hover);
}

.skills-menu.open .skills-menu-btn {
  border-color: var(--ctl-edge-accent);
}

/* Status dot: grey when idle, green (pulsing) while a skill runs. */
.skills-menu-dot {
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--muted);
  opacity: 0.5;
  transition: background 150ms ease, opacity 150ms ease;
}

.skills-menu-dot.on {
  background: var(--ok);
  opacity: 1;
  box-shadow: 0 0 9px var(--ok);
  animation: breathe 2.2s ease-in-out infinite;
}

.skills-menu-label {
  flex: 0 0 auto;
}

/* Active-skill name (or "None active"), filling the widened button and
   truncating if long. The chevron is pushed to the far edge. */
.skills-menu-active {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding-left: 9px;
  border-left: 1px solid var(--hairline);
  font-size: 12px;
  /* Brighter than --muted: the pill floats over the live camera feed, where
     plain grey washes out on light backgrounds. */
  color: var(--ctl-text);
  text-align: left;
}

.skills-menu-active.on {
  color: var(--text);
}

.skills-menu-chevron {
  flex: 0 0 auto;
  font-size: 11px;
  color: var(--muted);
  transition: transform 150ms ease;
}

.skills-menu.open .skills-menu-chevron {
  transform: rotate(180deg);
}

/* Popover above the button. Hidden until open. A column: the legend is a fixed
   (non-scrolling) header row, only the list body below it scrolls — using
   position: sticky for the header instead let trackpad overscroll bounce drag
   it along with the list on some browsers. */
.skills-pop {
  position: absolute;
  bottom: calc(100% + 10px);
  right: 0;
  width: 280px;
  max-height: min(52vh, 460px);
  display: none;
  flex-direction: column;
  overflow: hidden;
  background: rgb(8 8 11 / 58%);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border: 1px solid var(--hairline-strong);
  border-radius: 14px;
  box-shadow: 0 18px 48px rgb(0 0 0 / 45%);
}

.skills-menu.open .skills-pop {
  display: flex;
}

.skills-pop-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: 6px;
}

.skills-pop-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* Key for the type dots — a fixed header above the scrollable list, slightly
   less transparent than the popover body so it reads as a distinct bar. */
.skills-pop-legend {
  flex: 0 0 auto;
  display: flex;
  gap: 12px;
  padding: 8px 12px;
  background: rgb(8 8 11 / 54%);
  border-bottom: 1px solid var(--hairline);
}

.skills-pop-legend-item {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  color: var(--muted);
}

.skills-pop-empty {
  margin: 0;
  padding: 16px 12px;
  font-size: 12px;
  color: var(--muted);
  text-align: center;
}

.skills-pop-row {
  display: flex;
  flex-direction: column;
}

/* Folder section header (SkillInfo.group): a full-width toggle row, visually
   quieter than skill rows so sections read as structure, not entries. */
.skills-pop-group {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  margin-top: 6px;
  padding: 6px 12px;
  text-align: left;
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
  background: transparent;
  border: none;
  border-top: 1px solid var(--hairline);
  border-radius: 0;
  cursor: pointer;
  transition: background 150ms ease;
}

.skills-pop-group:hover {
  background: rgb(255 255 255 / 5%);
}

.skills-pop-group-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.skills-pop-row.expanded {
  background: rgb(255 255 255 / 4%);
  border-radius: 10px;
}

.skills-pop-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  padding: 10px 12px;
  text-align: left;
  color: var(--text);
  background: transparent;
  border: none;
  border-radius: 10px;
  cursor: pointer;
  transition: background 150ms ease;
}

.skills-pop-item:hover:not(:disabled) {
  background: rgb(255 255 255 / 7%);
}

.skills-pop-item:disabled {
  color: var(--muted);
  cursor: not-allowed;
}

.skills-pop-name {
  font-size: 13px;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Skill-type indicator: learned (trained policy) / replay (recorded trajectory) /
   digital (code skill). Color-only + a tooltip, no label text — keeps rows compact. */
.skills-pop-type-dot {
  flex: 0 0 auto;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--hairline-strong);
}

.skills-pop-type-dot.learned {
  background: var(--type-learned);
}

.skills-pop-type-dot.replay {
  background: var(--type-replay);
}

.skills-pop-type-dot.digital {
  background: var(--type-digital);
}

/* A skill file that failed to load — row is disabled, error shown inline. */
.skills-pop-type-dot.broken {
  background: var(--danger);
}

.skills-pop-tail {
  flex: 0 0 auto;
  font-size: 13px;
  color: var(--muted);
}

.skills-pop-status {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 0 12px 10px;
  font-size: 11px;
  line-height: 1.35;
  color: var(--muted);
  word-break: break-word;
}

.skills-pop-status.error {
  color: var(--danger);
}

/* The expanded form sits inside the row, indented to match the item padding. */
.skills-pop-row .skill-form {
  padding: 0 12px 12px;
}

/* ---- skill params form (shared: skills menu) --------------------------- */

.skill-form {
  display: grid;
  gap: 10px;
  padding-top: 2px;
}

.skill-param-note {
  margin: 0;
  font-size: 11px;
  color: var(--muted);
}

.skill-param {
  display: grid;
  gap: 5px;
}

.skill-param-label {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 6px;
  font-size: 11px;
  color: var(--text);
}

.skill-param-type {
  font-size: 10px;
  color: var(--muted);
}

.skill-input {
  width: 100%;
  min-height: 32px;
  padding: 0 9px;
  font-size: 12px;
  color: var(--text);
  background-color: rgb(0 0 0 / 45%);
  border: 1px solid var(--hairline-strong);
  border-radius: 7px;
  transition: border-color 150ms ease;
}

/* .skill-input is also used on text fields — only selects need chevron clearance. */
select.skill-input {
  padding: 0 30px 0 10px;
}

.skill-input:focus {
  outline: none;
  border-color: var(--accent-dim);
}

.skill-textarea {
  min-height: 64px;
  padding: 8px 9px;
  resize: vertical;
}

.skill-bool {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}

.skill-bool-opt {
  min-height: 32px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  background: rgb(0 0 0 / 45%);
  border: 1px solid var(--hairline-strong);
  border-radius: 7px;
  transition: border-color 150ms ease, color 150ms ease, background 150ms ease;
}

.skill-bool-opt:hover {
  color: var(--text);
}

.skill-bool-opt.on {
  color: var(--accent);
  border-color: var(--accent-dim);
  background: var(--accent-faint);
}

.skill-form-footer {
  display: flex;
  align-items: center;
  gap: 10px;
  justify-content: space-between;
  margin-top: 2px;
}

.skill-status {
  margin: 0;
  flex: 1;
  font-size: 11px;
  line-height: 1.35;
  color: var(--muted);
  word-break: break-word;
}

.skill-status.error {
  color: var(--danger);
}

.skill-confirm {
  flex: 0 0 auto;
  min-height: 34px;
  padding: 0 16px;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #d7d2ff;
  background: rgb(64 31 251 / 30%);
  border: 1px solid rgb(64 31 251 / 60%);
  border-radius: 8px;
  transition: opacity 150ms ease, background 150ms ease, border-color 150ms ease;
}

.skill-confirm:hover:not(:disabled) {
  background: rgb(64 31 251 / 48%);
  border-color: var(--blue);
}

.skill-confirm:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.skill-confirm.stop {
  color: var(--danger);
  background: transparent;
  border-color: var(--danger);
}

.skill-confirm.stop:hover:not(:disabled) {
  background: rgb(217 106 90 / 14%);
}

/* ---- chat pane (Teleop dock) -------------------------------------------- */

.chat-agentbar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--hairline);
}

.chat-agent-label {
  flex: 0 0 auto;
  color: var(--muted);
}

.chat-agent-select {
  flex: 1;
  min-width: 0;
  min-height: 30px;
  padding: 0 8px;
  font-size: 12px;
  color: var(--text);
  background: rgb(0 0 0 / 45%);
  border: 1px solid var(--hairline-strong);
  border-radius: 7px;
}

.chat-agent-select:focus {
  outline: none;
  border-color: rgb(64 31 251 / 60%);
}

/* Spins while a directive change is in flight (waiting on the brain). */
.chat-agent-spinner {
  flex: 0 0 auto;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 2px solid var(--accent-dim);
  border-top-color: var(--accent);
  animation: spin360 0.7s linear infinite;
}

@keyframes spin360 {
  to {
    transform: rotate(360deg);
  }
}

.chat-reset-brain {
  flex: 0 0 auto;
  min-height: 30px;
  padding: 0 10px;
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  background: rgb(255 255 255 / 4%);
  border: 1px solid var(--hairline-strong);
  border-radius: 7px;
  transition: color 150ms ease, border-color 150ms ease, background 150ms ease;
}

.chat-reset-brain:hover {
  color: var(--danger);
  border-color: var(--danger);
  background: rgb(217 106 90 / 12%);
}

.chat-messages {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px 14px;
}

.chat-msg {
  display: flex;
  flex-direction: column;
  max-width: 85%;
}

.chat-msg.user {
  align-self: flex-end;
  align-items: flex-end;
}

.chat-msg.robot,
.chat-msg.system {
  align-self: flex-start;
  align-items: flex-start;
}

.chat-bubble {
  padding: 7px 10px;
  border-radius: 10px;
  font-size: 12px;
  line-height: 1.4;
  white-space: pre-wrap;
  word-break: break-word;
}

.chat-msg.user .chat-bubble {
  color: #fff;
  background: rgb(64 31 251 / 38%);
  border: 1px solid rgb(64 31 251 / 60%);
}

.chat-msg.robot .chat-bubble {
  color: var(--text);
  background: rgb(255 255 255 / 6%);
  border: 1px solid var(--hairline-strong);
}

.chat-msg.system .chat-bubble {
  color: var(--muted);
  background: transparent;
  border: 1px dashed var(--hairline-strong);
  font-size: 11px;
}

.chat-sender {
  margin-bottom: 3px;
  font-size: 9px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}

/* Collapsed "Thoughts" block — grouped agent reasoning, expandable. */
.chat-thoughts {
  align-self: flex-start;
  max-width: 90%;
  display: flex;
  flex-direction: column;
}

.chat-thoughts-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  text-align: left;
  color: var(--muted);
  background: rgb(255 255 255 / 4%);
  border: 1px solid var(--hairline);
  border-radius: 9px;
  transition: background 150ms ease, color 150ms ease;
}

.chat-thoughts-toggle:hover {
  color: var(--text);
  background: rgb(255 255 255 / 7%);
}

.chat-thoughts-label {
  font-size: 9px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.chat-thoughts-status {
  flex: 1;
  font-size: 11px;
}

.chat-thoughts.active .chat-thoughts-status::after {
  content: "";
  display: inline-block;
  width: 5px;
  height: 5px;
  margin-left: 6px;
  border-radius: 50%;
  background: var(--blue);
  animation: chat-think-pulse 1.4s infinite ease-in-out;
}

@keyframes chat-think-pulse {
  0%, 100% { opacity: 0.4; }
  50% { opacity: 1; }
}

.chat-thoughts-arrow {
  font-size: 9px;
  opacity: 0.6;
}

/* Two states by construction: collapsed shows only the latest thought (the
   list's last item, clamped), open shows them all. One element owns the
   content, so no class combination can hide everything. */
.chat-thoughts-list {
  margin-top: 6px;
}

.chat-thoughts:not(.open) .chat-thought-item:not(:last-child) {
  display: none;
}

.chat-thoughts:not(.open) .chat-thought-item:last-child {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.chat-thoughts.open .chat-thoughts-list {
  max-height: 360px;
  overflow-y: auto;
}

.chat-thought-item {
  position: relative;
  padding: 4px 0 4px 14px;
  font-size: 12px;
  line-height: 1.4;
  color: var(--muted);
}

.chat-thought-item::before {
  content: "•";
  position: absolute;
  left: 2px;
  opacity: 0.5;
}

.chat-skill,
.chat-skill-group {
  align-self: stretch;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--hairline-strong);
  border-radius: 12px;
  background: rgb(10 10 14 / 28%);
  overflow: hidden;
}

.chat-skill-head {
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr) auto 14px;
  width: 100%;
  gap: 10px;
  align-items: center;
  padding: 12px;
  color: inherit;
  background: transparent;
  border: 0;
  font: inherit;
  text-align: left;
}

.chat-skill.has-detail .chat-skill-head {
  cursor: pointer;
}

.chat-skill:not(.has-detail) .chat-skill-head {
  cursor: default;
}

.chat-skill-icon {
  display: grid;
  width: 24px;
  height: 24px;
  color: var(--muted);
  border: 1px solid currentColor;
  border-radius: 50%;
  font-size: 10px;
  font-weight: 700;
  place-items: center;
}

.chat-skill-icon::before {
  content: "■";
  font-size: 8px;
}

.chat-skill-copy {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: 1px;
}

.chat-skill-name-row {
  display: flex;
  min-width: 0;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
}

.chat-skill-name-row .chat-skill-name {
  min-width: 0;
}

.chat-skill-name {
  color: #fff;
  font-size: 14px;
  font-weight: 560;
  line-height: 1.3;
  overflow-wrap: anywhere;
}

.chat-skill-count {
  flex: none;
  padding: 3px 7px;
  color: rgb(231 231 234 / 76%);
  background: rgb(255 255 255 / 7%);
  border: 1px solid rgb(255 255 255 / 16%);
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.05em;
  line-height: 1;
  text-transform: uppercase;
}

.chat-skill-summary {
  min-width: 0;
  color: rgb(231 231 234 / 72%);
  font-family: var(--font-mono);
  font-size: 10.5px;
  line-height: 1.45;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chat-skill-summary:empty {
  display: none;
}

.chat-skill-chevron {
  display: grid;
  color: rgb(231 231 234 / 58%);
  transform: rotate(0deg);
  transform-origin: center;
  transition: transform 180ms ease;
  place-items: center;
}

.chat-skill-chevron svg {
  width: 14px;
  height: 14px;
}

:is(.chat-skill, .chat-skill-group).open > .chat-skill-head .chat-skill-chevron {
  transform: rotate(90deg);
}

.chat-skill:not(.has-detail) .chat-skill-chevron {
  visibility: hidden;
}

.chat-skill-detail {
  display: none;
  grid-template-columns: minmax(0, 1fr);
  gap: 12px;
  max-height: 320px;
  overflow-y: auto;
  padding: 12px 13px 14px;
  color: rgb(231 231 234 / 84%);
  border-top: 1px solid var(--hairline);
}

.chat-skill.open .chat-skill-detail {
  display: grid;
}

@media (prefers-reduced-motion: reduce) {
  .chat-skill-chevron {
    transition: none;
  }
}

.chat-skill-parameters:empty,
.chat-skill-failure:empty {
  display: none;
}

.chat-skill-detail-label {
  margin: 0 0 9px;
  color: rgb(231 231 234 / 58%);
  font-size: 9px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.chat-skill-parameters dl {
  display: grid;
  grid-template-rows: auto auto;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: 2px 12px;
  margin: 0;
  font-size: 11px;
  line-height: 1.3;
}

.chat-skill-parameters dt {
  color: rgb(231 231 234 / 58%);
  font-size: 9px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.chat-skill-parameters dd {
  margin: 0;
  color: #fff;
  font-family: var(--font-mono);
  overflow-wrap: anywhere;
}

.chat-skill-failure {
  padding-top: 11px;
  border-top: 1px solid var(--hairline);
}

.chat-skill-parameters:empty + .chat-skill-failure {
  padding-top: 0;
  border-top: 0;
}

.chat-skill-failure-message {
  margin: 0;
  color: #ffd6cb;
  font-size: 11px;
  line-height: 1.45;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.chat-skill-status {
  padding: 5px 8px;
  color: rgb(231 231 234 / 76%);
  background: rgb(255 255 255 / 6%);
  border: 1px solid rgb(255 255 255 / 10%);
  border-radius: 999px;
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
}

:is(.chat-skill, .chat-skill-group).running {
  border-color: rgb(112 91 255 / 72%);
  background: rgb(64 31 251 / 16%);
}

:is(.chat-skill, .chat-skill-group).running > .chat-skill-head .chat-skill-icon,
:is(.chat-skill, .chat-skill-group).running > .chat-skill-head .chat-skill-status {
  color: #c0b8ff;
  border-color: rgb(151 135 255 / 48%);
}

:is(.chat-skill, .chat-skill-group).running > .chat-skill-head .chat-skill-icon::before {
  content: "";
  width: 8px;
  height: 8px;
  background: currentColor;
  border-radius: 50%;
  animation: chat-think-pulse 1.4s infinite ease-in-out;
}

:is(.chat-skill, .chat-skill-group).completed {
  border-color: var(--ok);
}

:is(.chat-skill, .chat-skill-group).completed > .chat-skill-head .chat-skill-icon,
:is(.chat-skill, .chat-skill-group).completed > .chat-skill-head .chat-skill-status {
  color: var(--ok);
}

:is(.chat-skill, .chat-skill-group).completed > .chat-skill-head .chat-skill-icon::before,
:is(.chat-skill, .chat-skill-group).failed > .chat-skill-head .chat-skill-icon::before {
  content: "";
  width: 14px;
  height: 14px;
  background: currentColor;
}

:is(.chat-skill, .chat-skill-group).completed > .chat-skill-head .chat-skill-icon,
:is(.chat-skill, .chat-skill-group).failed > .chat-skill-head .chat-skill-icon {
  border-width: 1.5px;
}

:is(.chat-skill, .chat-skill-group).completed > .chat-skill-head .chat-skill-icon::before {
  mask: url("/js/agent/icons/check.svg") center / contain no-repeat;
  -webkit-mask: url("/js/agent/icons/check.svg") center / contain no-repeat;
}

:is(.chat-skill, .chat-skill-group).failed {
  --chat-skill-failed-accent: #ffaaa1;
  --chat-skill-failed-edge: rgb(237 108 91 / 46%);
  background: var(--ctl-field);
  border-color: rgb(237 108 91 / 72%);
  box-shadow: var(--ctl-sheen);
}

:is(.chat-skill, .chat-skill-group).failed > .chat-skill-head .chat-skill-icon {
  color: var(--chat-skill-failed-accent);
  border-color: var(--chat-skill-failed-edge);
}

:is(.chat-skill, .chat-skill-group).failed > .chat-skill-head .chat-skill-status {
  color: var(--chat-skill-failed-accent);
  background: rgb(217 106 90 / 16%);
  border-color: var(--chat-skill-failed-edge);
}

:is(.chat-skill, .chat-skill-group).failed > .chat-skill-head .chat-skill-summary {
  color: rgb(255 255 255 / 78%);
}

:is(.chat-skill, .chat-skill-group).failed > .chat-skill-head .chat-skill-icon::before {
  mask: url("/js/agent/icons/failed.svg") center / contain no-repeat;
  -webkit-mask: url("/js/agent/icons/failed.svg") center / contain no-repeat;
}

:is(.chat-skill, .chat-skill-group).interrupted > .chat-skill-head .chat-skill-icon::before {
  content: "■";
  font-size: 8px;
}

.chat-skill-group > .chat-skill-head {
  cursor: pointer;
}

.chat-skill-group-list {
  display: none;
  flex-direction: column;
  max-height: 176px;
  overflow-y: auto;
  overscroll-behavior: contain;
  border-top: 1px solid var(--hairline);
  scrollbar-color: rgb(255 255 255 / 22%) transparent;
  scrollbar-width: thin;
}

.chat-skill-group.open > .chat-skill-group-list {
  display: flex;
}

.chat-skill-group-list::-webkit-scrollbar {
  width: 6px;
}

.chat-skill-group-list::-webkit-scrollbar-thumb {
  background: rgb(255 255 255 / 22%);
  border: 1px solid transparent;
  border-radius: 999px;
  background-clip: padding-box;
}

.chat-skill-group-list .chat-skill {
  flex: none;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
}

.chat-skill-group-list .chat-skill + .chat-skill {
  border-top: 1px solid var(--hairline);
}

.chat-skill-group-list .chat-skill-head {
  grid-template-columns: 18px minmax(0, 1fr) auto 12px;
  gap: 8px;
  min-height: 38px;
  padding: 6px 10px;
}

.chat-skill-group-list .chat-skill-icon {
  width: 18px;
  height: 18px;
}

.chat-skill-group-list .chat-skill-icon::before {
  width: 11px;
  height: 11px;
}

.chat-skill-group-list .chat-skill:has(.chat-skill-summary:not(:empty)) .chat-skill-name {
  display: none;
}

.chat-skill-group-list .chat-skill-summary {
  color: rgb(231 231 234 / 72%);
  font-size: 9.5px;
  line-height: 1.35;
}

.chat-skill-group-list .chat-skill-status {
  padding: 3px 6px;
  font-size: 8px;
}

.chat-skill-group-list .chat-skill-chevron svg {
  width: 12px;
  height: 12px;
}

.chat-skill-group-list .chat-skill.running {
  background: rgb(64 31 251 / 12%);
}

.chat-skill-group-list .chat-skill.failed {
  background: rgb(217 106 90 / 10%);
}

.chat-skill-head:focus-visible {
  outline: 2px solid var(--ctl-accent);
  outline-offset: -3px;
  border-radius: 10px;
}

.chat-input-row {
  display: flex;
  gap: 8px;
  padding: 10px 12px;
  border-top: 1px solid var(--hairline);
}

.chat-input {
  flex: 1;
  min-height: 34px;
  max-height: 120px;
  padding: 8px 10px;
  resize: none;
  font-size: 12px;
  color: var(--text);
  background: rgb(0 0 0 / 45%);
  border: 1px solid var(--hairline-strong);
  border-radius: 7px;
}

.chat-input:focus {
  outline: none;
  border-color: rgb(64 31 251 / 60%);
}

.chat-send {
  flex: 0 0 auto;
  align-self: flex-end;
  min-height: 34px;
  padding: 0 14px;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #d7d2ff;
  background: rgb(64 31 251 / 30%);
  border: 1px solid rgb(64 31 251 / 60%);
  border-radius: 8px;
  transition: background 150ms ease, border-color 150ms ease;
}

.chat-send:hover {
  background: rgb(64 31 251 / 48%);
  border-color: var(--blue);
}

/* ---- Agent page --------------------------------------------------------- */
.agent-cockpit {
  --agent-dock-width: 360px;
  --agent-dock-gutter: 18px;
  /* Inset of every floating control from the feed frame's edge. The camera
     strip set the precedent; the rest match it. */
  --agent-overlay-inset: 14px;
  --agent-telemetry-height: 56px;
}

.agent-cockpit .agent-feed-frame {
  display: contents;
}

.agent-width-guard {
  display: none;
}

.agent-cockpit .video-stage {
  background: transparent;
}

.agent-cockpit .cam-strip {
  position: relative;
  top: auto;
  right: auto;
  left: auto;
  width: max-content;
}

.agent-cockpit .agent-telemetry-overlay {
  width: var(--agent-dock-width);
  height: var(--agent-telemetry-height);
  border-radius: 14px;
}

.agent-cockpit .agent-telemetry-overlay .telemetry {
  display: flex;
  height: 100%;
  align-items: center;
  gap: 0;
  padding: 8px 12px;
}

.agent-cockpit .agent-telemetry-overlay .telemetry-item {
  flex: 1 1 0;
  padding: 0 10px;
}

.agent-cockpit .agent-telemetry-overlay .telemetry-item-robot {
  display: grid;
  flex-grow: 1.65;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto auto;
  align-content: center;
  gap: 2px;
  padding: 0 12px 0 0;
  border-bottom: 0;
}

.agent-cockpit
  .agent-telemetry-overlay
  .telemetry-item-robot
  .telemetry-value {
  line-height: 1.2;
}

.agent-cockpit
  .agent-telemetry-overlay
  .telemetry-item-robot
  .telemetry-meta {
  line-height: 1.3;
}

.agent-cockpit .agent-telemetry-overlay .telemetry-item-battery {
  display: grid;
  grid-template-rows: auto auto;
  align-content: center;
  gap: 2px;
}

.agent-cockpit
  .agent-telemetry-overlay
  .telemetry-item:not(.telemetry-item-robot) {
  border-left: 1px solid rgb(255 255 255 / 10%);
}

@keyframes telemetry-marquee {
  to {
    transform: translateX(calc(-50% - 12px));
  }
}

@media (prefers-reduced-motion: reduce) {
  .telemetry-value-duplicate {
    display: none;
  }
}

.sim-debug-stack {
  position: absolute;
  bottom: 132px;
  left: 14px;
  z-index: 5;
  display: flex;
  flex-direction: column;
  width: min(360px, calc(100% - 28px));
  gap: 8px;
  color: rgb(255 255 255 / 92%);
}

.sim-scene-setup {
  position: relative;
  width: 56px;
  height: 56px;
}

.sim-scene-panel {
  position: absolute;
  bottom: 66px;
  left: 0;
  display: grid;
  width: min(360px, calc(100vw - 92px));
  padding: 0 13px 13px;
  gap: 14px;
  overflow: hidden;
  background: rgb(8 8 10 / 42%);
  backdrop-filter: blur(30px) saturate(1.1) brightness(0.82);
  -webkit-backdrop-filter: blur(30px) saturate(1.1) brightness(0.82);
  border: 1px solid rgb(255 255 255 / 14%);
  border-radius: 18px;
  box-shadow: 0 14px 44px rgb(0 0 0 / 48%);
  transform-origin: bottom left;
  will-change: transform, opacity;
  transition:
    opacity 220ms cubic-bezier(0.23, 1, 0.32, 1),
    transform 240ms cubic-bezier(0.23, 1, 0.32, 1),
    visibility 0s;
}

.sim-scene-setup:not(.open) .sim-scene-panel {
  visibility: hidden;
  opacity: 0;
  pointer-events: none;
  transform: translate(-4px, 10px) scale(0.96);
  transition:
    opacity 130ms cubic-bezier(0.25, 0.46, 0.45, 0.94),
    transform 160ms cubic-bezier(0.25, 0.46, 0.45, 0.94),
    visibility 0s linear 160ms;
}

.sim-scene-header {
  display: grid;
  padding: 13px 1px 12px;
  gap: 2px;
  border-bottom: 1px solid rgb(255 255 255 / 9%);
}

.sim-scene-header strong {
  font-size: 12px;
  font-weight: 620;
  line-height: 1.2;
}

.sim-scene-header small {
  font-size: 10px;
  line-height: 1.25;
  color: rgb(255 255 255 / 50%);
}

.sim-scene-toggle {
  display: grid;
  width: 56px;
  height: 56px;
  padding: 0;
  color: rgb(255 255 255 / 82%);
  background: rgb(8 8 10 / 76%);
  backdrop-filter: blur(20px) saturate(1.1);
  -webkit-backdrop-filter: blur(20px) saturate(1.1);
  border: 1px solid rgb(255 255 255 / 18%);
  border-radius: 14px;
  box-shadow:
    inset 0 1px 0 rgb(255 255 255 / 10%),
    0 10px 28px rgb(0 0 0 / 38%);
  cursor: pointer;
  place-items: center;
  transition:
    color 150ms ease,
    background-color 150ms ease,
    border-color 150ms ease,
    transform 120ms cubic-bezier(0.215, 0.61, 0.355, 1);
}

.sim-scene-toggle-icon {
  grid-area: 1 / 1;
  width: 24px;
  height: 24px;
  transition:
    opacity 160ms cubic-bezier(0.23, 1, 0.32, 1),
    transform 180ms cubic-bezier(0.23, 1, 0.32, 1);
}

.sim-scene-toggle-shapes {
  background: currentColor;
  -webkit-mask: url("/js/agent/icons/shapes.svg") center / contain no-repeat;
  mask: url("/js/agent/icons/shapes.svg") center / contain no-repeat;
}

.sim-scene-toggle-close {
  opacity: 0;
  pointer-events: none;
  transform: rotate(-10deg) scale(0.82);
}

.sim-scene-setup.open .sim-scene-toggle-shapes {
  opacity: 0;
  transform: rotate(10deg) scale(0.82);
}

.sim-scene-setup.open .sim-scene-toggle-close {
  opacity: 1;
  transform: rotate(0) scale(1);
}

.sim-scene-toggle:active {
  transform: scale(0.96);
}

.sim-scene-toggle:focus-visible {
  outline: 2px solid var(--ctl-accent);
  outline-offset: 3px;
}

.sim-scene-button:focus-visible {
  outline: 2px solid var(--agent-purple);
  outline-offset: -2px;
}

@media (hover: hover) and (pointer: fine) {
  .sim-scene-toggle:hover {
    color: #fff;
    background: rgb(14 14 18 / 88%);
    border-color: rgb(255 255 255 / 30%);
  }
}

.sim-scene-section {
  display: grid;
  min-width: 0;
  gap: 12px;
}

.sim-scene-section-header {
  display: flex;
  min-height: 30px;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.sim-scene-section h3 {
  margin: 0;
  font-size: 10px;
  font-weight: 650;
  line-height: 1;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgb(255 255 255 / 64%);
}

.sim-view-aids > span {
  font-size: 9px;
  font-weight: 620;
  line-height: 1;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgb(255 255 255 / 42%);
}

.sim-prop-grid {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 7px;
}

.sim-scene-button,
.sim-placement-switch button {
  appearance: none;
  margin: 0;
  font-family: system-ui, sans-serif;
  color: rgb(255 255 255 / 72%);
  background: rgb(255 255 255 / 6%);
  border: 1px solid rgb(255 255 255 / 11%);
  cursor: pointer;
}

.sim-scene-button {
  min-height: 30px;
  padding: 6px 10px;
  font-size: 10px;
  font-weight: 570;
  line-height: 1;
  border-radius: 9px;
  transition: color 140ms ease, background-color 140ms ease, border-color 140ms ease;
}

.sim-scene-button:hover {
  color: #fff;
  background: rgb(255 255 255 / 10%);
  border-color: rgb(255 255 255 / 20%);
}

.sim-scene-button.is-active {
  color: var(--agent-purple);
  background: rgb(64 31 251 / 20%);
  border-color: rgb(151 135 255 / 48%);
}

.sim-prop-button {
  display: grid;
  min-width: 0;
  height: 56px;
  padding: 6px 3px 5px;
  place-items: center;
  align-content: center;
  gap: 4px;
}

.sim-prop-icon {
  font-size: 18px;
  line-height: 1;
}

.sim-prop-name {
  display: block;
  width: 100%;
  overflow: hidden;
  font-size: 9px;
  line-height: 1.1;
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sim-add-all {
  min-height: 56px;
  padding: 6px 3px 5px;
  color: rgb(255 255 255 / 58%);
  border-style: dashed;
}

.sim-prop-add-icon {
  font-size: 20px;
  font-weight: 300;
  line-height: 1;
}

.sim-placement-section {
  padding-top: 12px;
  border-top: 1px solid rgb(255 255 255 / 8%);
}

.sim-placement-switch {
  position: relative;
  isolation: isolate;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2px;
  padding: 3px;
  background: var(--ctl-field);
  border: 1px solid var(--hairline-strong);
  border-radius: 11px;
}

.sim-placement-switch::before {
  position: absolute;
  z-index: 0;
  top: 3px;
  bottom: 3px;
  left: 3px;
  width: calc((100% - 8px) / 2);
  background: rgb(4 4 6 / 88%);
  border-radius: 8px;
  box-shadow:
    inset 0 0 0 1px rgb(255 255 255 / 14%),
    0 2px 6px rgb(0 0 0 / 24%);
  content: "";
  transition: transform 180ms cubic-bezier(0.645, 0.045, 0.355, 1);
}

.sim-placement-switch.spot-selected::before {
  transform: translateX(calc(100% + 2px));
}

.sim-placement-switch button {
  position: relative;
  z-index: 1;
  padding: 7px 14px;
  font: inherit;
  font-size: 10px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ctl-text-off);
  background: transparent;
  border-color: transparent;
  border-radius: 8px;
  transition: color 180ms cubic-bezier(0.645, 0.045, 0.355, 1);
}

.sim-placement-switch button.is-active {
  color: #fff;
}

.sim-placement-switch button:focus-visible {
  outline: 2px solid var(--ctl-accent);
  outline-offset: 1px;
}

.sim-placement-hint {
  min-height: 14px;
  margin: 0;
  font-size: 10px;
  line-height: 1.4;
  color: rgb(255 255 255 / 48%);
}

.sim-scene-utilities {
  grid-template-columns: 1fr;
  padding-top: 12px;
  gap: 9px;
  border-top: 1px solid rgb(255 255 255 / 8%);
}

.sim-clear-props {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 28px;
  padding: 6px 10px;
  font-size: 11px;
  font-weight: 600;
  color: rgb(255 255 255 / 56%);
}

.sim-clear-props-icon {
  width: 13px;
  height: 13px;
  background: currentColor;
  -webkit-mask: url("/js/agent/icons/trash.svg") center / contain no-repeat;
  mask: url("/js/agent/icons/trash.svg") center / contain no-repeat;
}

.sim-view-aids {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  min-width: 0;
  align-items: center;
  gap: 6px;
}

.sim-camera-modes {
  grid-template-columns: minmax(0, 1fr) repeat(3, auto);
}

.sim-view-aids > span {
  white-space: nowrap;
}

/* The agent page re-parents this stack out of the feed frame onto the cockpit
   (see agent/main.js), so its offsets have to clear the gutter to reach the
   frame's edge — same as the challenge dock and Inspect Brain. Hidden below
   641px, so the gutter always applies here. */
.agent-cockpit .sim-debug-stack {
  bottom: calc(
    var(--agent-dock-gutter) + var(--agent-overlay-inset)
  ) !important;
  left: calc(var(--agent-dock-gutter) + var(--agent-overlay-inset));
}

/* Agent page keeps every camera live (no off pill), so any off tile here is the
   optional map — give it the same square footprint as the live feeds. */
.agent-cockpit .cam-tile.off {
  display: flex;
  align-items: center;
  justify-content: center;
  height: var(--pip-h);
  padding: 0;
}

.agent-mic-control {
  --agent-mic-level: 0;
  position: relative;
  z-index: 2;
  display: flex;
  width: 42px;
  height: 42px;
  align-items: center;
  justify-content: center;
}

.agent-mic-button {
  --agent-mic-inner-wave-scale: 1.38;
  position: relative;
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  padding: 0;
  color: rgb(255 255 255 / 88%);
  background:
    radial-gradient(
      circle,
      rgb(255 255 255 / calc(8% + var(--agent-mic-level) * 28%)) 0 12%,
      rgb(255 255 255 / calc(var(--agent-mic-level) * 16%)) 28%,
      transparent 58%
    ),
    rgb(8 8 10 / 48%);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  border: 1.25px solid rgb(255 255 255 / 28%);
  border-radius: 50%;
  box-shadow:
    inset 0 1px 0 rgb(255 255 255 / 10%),
    0 14px 38px rgb(0 0 0 / 24%);
  cursor: pointer;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
  transition:
    transform 150ms cubic-bezier(0.645, 0.045, 0.355, 1),
    color 150ms ease,
    border-color 150ms ease;
}

.agent-mic-button::before {
  content: "";
  position: absolute;
  z-index: 1;
  width: 30px;
  height: 30px;
  border: 1px solid rgb(255 255 255 / 48%);
  border-radius: 50%;
  background: rgb(245 245 248 / 38%);
  box-shadow:
    inset 0 1px 0 rgb(255 255 255 / 24%),
    0 8px 28px rgb(0 0 0 / 28%);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  transition:
    transform 150ms ease,
    border-color 150ms ease,
    background-color 150ms ease,
    box-shadow 150ms ease;
}

.agent-mic-button::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: 50%;
  background: radial-gradient(
    circle,
    rgb(255 255 255 / 12%) 0,
    rgb(255 255 255 / 4%) 38%,
    transparent 68%
  );
  box-shadow:
    inset 0 0 30px rgb(255 255 255 / 6%),
    0 0 36px rgb(255 255 255 / 10%);
  opacity: 0;
  pointer-events: none;
  transition: opacity 150ms ease;
}

.agent-mic-outer-waves,
.agent-mic-inner-waves {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.agent-mic-outer-waves {
  inset: 0;
  transition: opacity 100ms cubic-bezier(0.215, 0.61, 0.355, 1);
}

.agent-mic-outer-wave,
.agent-mic-inner-wave {
  position: absolute;
  border-radius: 50%;
  opacity: 0;
  will-change: transform, opacity;
}

.agent-mic-outer-wave {
  inset: 0;
  background: radial-gradient(
    circle closest-side,
    transparent 0 78%,
    rgb(255 255 255 / 64%) 83%,
    rgb(255 255 255 / 30%) 91%,
    rgb(255 255 255 / 8%) 97%,
    transparent 100%
  );
}

.agent-mic-icon {
  position: relative;
  z-index: 2;
  width: 16px;
  height: 16px;
  background: currentColor;
  mask: url("/js/agent/icons/mic.svg") center / contain no-repeat;
  -webkit-mask: url("/js/agent/icons/mic.svg") center / contain no-repeat;
  opacity: 0.84;
  pointer-events: none;
  transition:
    opacity 150ms ease,
    transform 150ms ease;
}

.agent-mic-inner-waves {
  inset: 1px;
  z-index: 1;
  border-radius: 50%;
  overflow: hidden;
  transition: opacity 160ms ease;
}

.agent-mic-inner-wave {
  top: 50%;
  left: 50%;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: radial-gradient(
    circle closest-side,
    transparent 0 72%,
    rgb(255 255 255 / 38%) 80%,
    rgb(224 220 255 / 20%) 89%,
    transparent 100%
  );
  transform: translate(-50%, -50%);
}

.agent-mic-hover-glow {
  position: absolute;
  z-index: 1;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: radial-gradient(circle, rgb(255 255 255 / 34%), rgb(255 255 255 / 12%) 54%, transparent 76%);
  opacity: 0;
  pointer-events: none;
  transform: scale(0.96);
  transition:
    opacity 150ms ease,
    transform 150ms ease;
  will-change: transform, opacity;
}

.agent-mic-waveform {
  position: absolute;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 17px;
  gap: 1.5px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 100ms ease;
}

.agent-mic-waveform-bar {
  width: 2px;
  height: 15px;
  border-radius: 2px;
  background: currentColor;
  transform: scaleY(var(--agent-wave, 0.12));
  transition: transform 70ms cubic-bezier(0.215, 0.61, 0.355, 1);
}

.agent-mic-label {
  position: absolute;
  left: 50%;
  bottom: calc(100% + 8px);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  white-space: nowrap;
  color: rgb(255 255 255 / 72%);
  opacity: 0;
  text-shadow: 0 1px 8px rgb(0 0 0 / 70%);
  transform: translateX(-50%);
  pointer-events: none;
  transition: opacity 120ms ease;
}

.agent-mic-control:is(.listening, .waiting) .agent-mic-label {
  opacity: 1;
}

.agent-mic-message {
  --agent-mic-hint-bg: rgb(26 26 29);
  --agent-mic-hint-border: rgb(138 138 147 / 42%);
  position: absolute;
  right: 0;
  bottom: calc(100% + 8px);
  z-index: 3;
  width: max-content;
  max-width: calc(100vw - 32px);
  padding: 10px 14px;
  font-size: 13px;
  line-height: 1.35;
  letter-spacing: 0;
  text-transform: none;
  white-space: normal;
  color: rgb(231 231 234 / 78%);
  background: var(--agent-mic-hint-bg);
  border: 1px solid var(--agent-mic-hint-border);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgb(0 0 0 / 30%);
  opacity: 0;
  text-shadow: none;
  pointer-events: none;
  transition: opacity 120ms cubic-bezier(0.215, 0.61, 0.355, 1);
  will-change: opacity;
}

.agent-mic-control:is(.show-hold-hint, .show-unavailable-message) .agent-mic-message {
  opacity: 1;
  transition-duration: 180ms;
}

.agent-mic-message::after {
  content: "";
  position: absolute;
  right: 17px;
  bottom: -4px;
  width: 8px;
  height: 8px;
  background: var(--agent-mic-hint-bg);
  border-right: 1px solid var(--agent-mic-hint-border);
  border-bottom: 1px solid var(--agent-mic-hint-border);
  transform: rotate(45deg);
}

@media (hover: hover) and (pointer: fine) {
  .agent-mic-control.unavailable:hover .agent-mic-message {
    opacity: 1;
    transition-duration: 180ms;
  }

  .agent-mic-control:not(.listening):not(.waiting):not(.unavailable) .agent-mic-button:hover {
    color: #fff;
    border-color: rgb(255 255 255 / 48%);
  }

  .agent-mic-control:not(.listening):not(.waiting):not(.unavailable) .agent-mic-button:hover::before {
    transform: scale(1.07);
  }

  .agent-mic-control:not(.listening):not(.waiting):not(.unavailable) .agent-mic-button:hover::after {
    opacity: 0.62;
  }

  .agent-mic-control:not(.listening):not(.waiting):not(.unavailable) .agent-mic-button:hover .agent-mic-icon {
    opacity: 1;
    transform: scale(1.08);
  }

  .agent-mic-control:not(.listening):not(.waiting):not(.unavailable) .agent-mic-button:hover .agent-mic-hover-glow {
    opacity: 1;
    transform: scale(1.07);
  }

  .agent-mic-control:not(.listening):not(.waiting):not(.unavailable):has(.agent-mic-button:hover)
    .agent-mic-outer-waves {
    opacity: 0;
  }

  .agent-mic-control:not(.listening):not(.waiting):not(.unavailable):has(.agent-mic-button:hover)
    .agent-mic-outer-wave {
    animation-play-state: paused;
  }
}

.agent-mic-control:not(.listening):not(.waiting):not(.unavailable) .agent-mic-outer-waves {
  opacity: 1;
}

.agent-mic-control:not(.listening):not(.waiting):not(.unavailable) .agent-mic-outer-wave {
  animation: agent-mic-outer-wave 1.8s cubic-bezier(0.215, 0.61, 0.355, 1) infinite;
}

.agent-mic-control.waiting .agent-mic-button {
  color: rgb(255 255 255 / 54%);
  background: rgb(8 8 10 / 34%);
  border-color: rgb(255 255 255 / 16%);
  cursor: wait;
  transform: scale(0.96);
}

.agent-mic-control.waiting .agent-mic-button::before {
  background: rgb(190 190 198 / 20%);
  border-color: rgb(255 255 255 / 28%);
  box-shadow:
    inset 0 1px 0 rgb(255 255 255 / 10%),
    0 6px 20px rgb(0 0 0 / 20%);
}

.agent-mic-control.waiting .agent-mic-button::after {
  opacity: 0.2;
}

.agent-mic-control.waiting .agent-mic-icon {
  opacity: 0.58;
  transform: scale(0.94);
}

.agent-mic-control.waiting .agent-mic-label {
  color: rgb(255 255 255 / 56%);
}

.agent-mic-control.unavailable .agent-mic-button {
  color: rgb(255 255 255 / 40%);
  background: rgb(8 8 10 / 26%);
  border-color: rgb(255 255 255 / 12%);
  cursor: not-allowed;
}

.agent-mic-control.unavailable .agent-mic-button::before {
  background: rgb(190 190 198 / 14%);
  border: 1px solid rgb(255 255 255 / 22%);
  box-shadow:
    inset 0 0 0 1px rgb(255 255 255 / 4%),
    0 6px 20px rgb(0 0 0 / 16%);
}

.agent-mic-control.unavailable .agent-mic-button::after {
  opacity: 0.12;
}

.agent-mic-control.unavailable .agent-mic-icon {
  mask: url("/js/agent/icons/mic-disabled.svg") center / contain no-repeat;
  -webkit-mask: url("/js/agent/icons/mic-disabled.svg") center / contain no-repeat;
}

.agent-mic-control.unavailable .agent-mic-message {
  --agent-mic-hint-bg: rgb(34 27 18);
  --agent-mic-hint-border: var(--ctl-edge-accent);
  color: var(--ctl-accent);
}

.agent-mic-control.listening .agent-mic-button {
  color: var(--agent-purple);
  border-color: rgb(255 255 255 / 16%);
  transform: scale(0.9);
  transition:
    transform 130ms cubic-bezier(0.215, 0.61, 0.355, 1),
    color 150ms ease,
    border-color 150ms ease;
}

.agent-mic-control.listening .agent-mic-button::after {
  opacity: 1;
  transition-duration: 120ms;
  transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
}

.agent-mic-control.listening .agent-mic-button::before {
  background: var(--agent-purple-fill);
  border-color: var(--agent-purple-edge);
  transform: scale(1.08);
  transition:
    transform 130ms cubic-bezier(0.215, 0.61, 0.355, 1),
    border-color 150ms ease,
    background-color 150ms ease,
    box-shadow 150ms ease;
}

.agent-mic-control.listening .agent-mic-icon {
  opacity: 0;
  transform: scale(0.8);
}

.agent-mic-control.listening .agent-mic-waveform {
  opacity: 1;
}

.agent-mic-control.listening .agent-mic-inner-waves {
  opacity: 1;
}

.agent-mic-control.listening .agent-mic-inner-wave {
  animation: agent-mic-inner-wave 2.7s cubic-bezier(0.215, 0.61, 0.355, 1) infinite;
}

.agent-mic-outer-wave:nth-child(2) {
  animation-delay: -0.6s;
}

.agent-mic-outer-wave:nth-child(3) {
  animation-delay: -1.2s;
}

.agent-mic-inner-wave:nth-child(2) {
  animation-delay: -0.9s;
}

.agent-mic-inner-wave:nth-child(3) {
  animation-delay: -1.8s;
}

@keyframes agent-mic-outer-wave {
  0% {
    opacity: 0;
    transform: scale(0.94);
  }
  14% {
    opacity: 0.5;
  }
  65% {
    opacity: 0.18;
  }
  100% {
    opacity: 0;
    transform: scale(1.2);
  }
}

@keyframes agent-mic-inner-wave {
  0% {
    opacity: 0;
    transform: translate(-50%, -50%) scale(1);
  }
  14% {
    opacity: 0.42;
  }
  72% {
    opacity: 0.14;
  }
  100% {
    opacity: 0;
    transform: translate(-50%, -50%) scale(var(--agent-mic-inner-wave-scale));
  }
}

.agent-mic-button:focus-visible {
  outline: 2px solid var(--ctl-accent);
  outline-offset: 2px;
}

.agent-cockpit.brain-open .agent-mic-control {
  display: none;
}

.agent-panel {
  position: absolute;
  top: var(--agent-dock-gutter);
  right: var(--agent-dock-gutter);
  bottom: var(--agent-dock-gutter);
  width: var(--agent-dock-width);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 10px;
  max-height: calc(100% - var(--agent-dock-gutter) - var(--agent-dock-gutter));
  padding: 0;
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border: 0;
  pointer-events: none;
}

.agent-control-panel,
.agent-thoughts-panel {
  backdrop-filter: blur(30px) saturate(1.1) brightness(0.82);
  -webkit-backdrop-filter: blur(30px) saturate(1.1) brightness(0.82);
  border-radius: 18px;
  box-shadow: 0 14px 44px rgb(0 0 0 / 48%);
  pointer-events: auto;
}

.agent-control-panel {
  position: relative;
  z-index: 2;
  display: flex;
  flex: 0 0 auto;
  flex-direction: column;
  gap: 10px;
  padding: 14px;
  background: rgb(8 8 10 / 42%);
  border: 1px solid rgb(255 255 255 / 14%);
}

.agent-thoughts-panel {
  display: flex;
  flex: 1 1 auto;
  width: 100%;
  flex-direction: column;
  gap: 12px;
  min-height: 280px;
  max-height: none;
  padding: 16px;
  background: linear-gradient(180deg, rgb(10 10 12 / 14%), rgb(6 6 9 / 38%));
  border: 1px solid rgb(255 255 255 / 12%);
}

.challenge-panel .microlabel {
  color: rgb(231 231 234 / 72%);
}

@media (min-width: 641px) {
  .agent-cockpit {
    --agent-dock-width: 388px;
  }

  .agent-cockpit .overlay-stack-top-left {
    top: calc(var(--agent-dock-gutter) + 18px);
    right: calc(
      var(--agent-dock-width) + var(--agent-dock-gutter) + var(--agent-dock-gutter) + 18px
    );
    bottom: auto;
    left: auto;
  }

  .agent-cockpit .video-stage {
    top: var(--agent-dock-gutter);
    bottom: var(--agent-dock-gutter);
    left: var(--agent-dock-gutter);
    right: calc(
      var(--agent-dock-width) + var(--agent-dock-gutter) + var(--agent-dock-gutter)
    );
  }

  .agent-cockpit .video-stage video {
    display: block;
    height: auto;
    max-height: 100%;
    border: 1px solid transparent;
    border-radius: 18px;
    object-position: left top;
  }

  .agent-cockpit .video-stage.video-ready video {
    border-color: color-mix(in srgb, var(--text) 34%, var(--bg));
  }

  .agent-cockpit .agent-telemetry-overlay {
    top: auto;
    right: auto;
    bottom: var(--agent-dock-gutter);
    left: var(--agent-dock-gutter);
  }

  .agent-cockpit .agent-stage-view-toggle {
    right: calc(
      var(--agent-dock-width) + var(--agent-dock-gutter) + var(--agent-dock-gutter)
    );
    bottom: var(--agent-dock-gutter);
    left: auto;
  }
}

.agent-head {
  display: flex;
  align-items: center;
  width: 100%;
  min-height: 32px;
  gap: 12px;
  padding: 0;
  color: inherit;
  background: transparent;
  border: 0;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.agent-control-panel.collapsed .agent-controls,
.agent-control-panel.collapsed .agent-status-row {
  display: none;
}

.agent-head-copy {
  display: flex;
  flex: 1;
  min-width: 0;
  flex-direction: column;
  gap: 2px;
}

.agent-head-label {
  color: rgb(231 231 234 / 58%);
  font-size: 9px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.agent-head-agent-name {
  min-width: 0;
  color: #fff;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.25;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.agent-head-chev {
  display: flex;
  margin-left: auto;
  color: var(--muted);
  opacity: 0.62;
  transform: rotate(90deg);
  transition: transform 180ms cubic-bezier(0.645, 0.045, 0.355, 1), color 150ms ease, opacity 150ms ease;
}

.agent-control-panel.collapsed .agent-head-chev {
  transform: rotate(0);
}

.agent-head:focus-visible {
  outline: 2px solid var(--ctl-accent);
  outline-offset: 4px;
  border-radius: 6px;
}

@media (hover: hover) and (pointer: fine) {
  .agent-head:hover .agent-head-chev {
    color: var(--text);
    opacity: 1;
  }
}

@media (max-width: 640px) {
  .agent-cockpit .overlay-stack-top-left {
    right: 14px;
    width: auto;
  }

  .agent-cockpit .agent-telemetry-overlay {
    top: 14px;
    right: 14px;
    bottom: auto;
    left: 14px;
    width: auto;
  }

  /* The 360px right dock doesn't fit a phone: dock as a bottom sheet
     instead, expandable to full height via its disclosure header. */
  .agent-panel {
    top: auto;
    left: 14px;
    right: 14px;
    bottom: 80px;
    width: auto;
    height: 44vh;
    max-height: none;
  }

  .agent-control-panel,
  .agent-thoughts-panel {
    padding: 12px;
  }

  .agent-thoughts-panel {
    min-height: 0;
    max-height: none;
  }

  .agent-cockpit .cam-strip {
    right: auto;
  }

  /* The agent bottom sheet owns the lower half; the sim debug chips would
     float over it (they live on Teleop/Collect anyway). */
  .agent-cockpit .sim-debug-stack {
    display: none !important; /* the stage sets display inline */
  }

  .agent-challenge-dock {
    left: 14px;
  }

  .agent-stage-view-toggle {
    left: 80px;
  }

  .challenge-panel {
    left: 0;
    width: min(360px, calc(100vw - 28px));
  }

}

.agent-title {
  display: inline-flex;
  flex: none;
  align-items: center;
}

.agent-title-icon {
  width: 22px;
  height: 22px;
  color: #fff;
  filter: drop-shadow(0 0 6px rgb(255 255 255 / 62%));
}

.agent-panel.active .agent-title-icon {
  color: #ffd08a;
  filter: drop-shadow(0 0 4px rgb(255 181 94)) drop-shadow(0 0 12px rgb(242 145 48 / 90%));
  transform-origin: center;
  will-change: transform, opacity;
  animation: agent-title-active-pulse 2s cubic-bezier(0.455, 0.03, 0.515, 0.955) infinite;
}

@keyframes agent-title-active-pulse {
  0%,
  100% {
    opacity: 0.74;
    transform: scale(0.97);
  }

  50% {
    opacity: 1;
    transform: scale(1.12);
  }
}

.agent-stage-view-toggle {
  position: absolute;
  bottom: 14px;
  z-index: 13;
  display: inline-flex;
  align-items: center;
  height: 56px;
  gap: 10px;
  padding: 0 16px;
  color: rgb(255 255 255 / 76%);
  background: rgb(8 8 10 / 76%);
  backdrop-filter: blur(20px) saturate(1.1);
  -webkit-backdrop-filter: blur(20px) saturate(1.1);
  border: 1px solid rgb(255 255 255 / 18%);
  border-radius: 28px;
  box-shadow: 0 10px 28px rgb(0 0 0 / 38%);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
  transition:
    color 150ms ease,
    background-color 150ms ease,
    border-color 150ms ease,
    transform 120ms cubic-bezier(0.215, 0.61, 0.355, 1);
}

.agent-stage-view-icon {
  width: 20px;
  height: 20px;
  flex: none;
  background: currentColor;
  -webkit-mask: url("/js/agent/icons/brain-full.svg") center / contain no-repeat;
  mask: url("/js/agent/icons/brain-full.svg") center / contain no-repeat;
}

.agent-stage-view-label {
  line-height: 1.45;
  text-align: left;
  white-space: pre-line;
}

.agent-stage-view-toggle.active .agent-stage-view-icon {
  -webkit-mask-image: url("/js/agent/icons/live.svg");
  mask-image: url("/js/agent/icons/live.svg");
}

.agent-stage-view-toggle.active {
  color: var(--ctl-accent);
  background: rgb(8 8 10 / 84%);
  border-color: var(--ctl-edge-accent);
}

.agent-stage-view-toggle:active {
  transform: scale(0.97);
}

.agent-stage-view-toggle:focus-visible {
  outline: 2px solid var(--ctl-accent);
  outline-offset: 2px;
}

@media (hover: hover) and (pointer: fine) {
  .agent-stage-view-toggle:hover {
    color: #fff;
    background: rgb(14 14 18 / 84%);
    border-color: rgb(255 255 255 / 28%);
  }
}

/* The Brain monitor layer: an opaque stage that flips in over the camera view
   (video keeps streaming beneath — closing it is instant). Sits above the
   stage overlays but below the panel, which stays docked in both views; the
   monitor's own layout (incl. clearing the panel) lives in brain.css. */
.agent-brain {
  position: absolute;
  inset: 0;
  z-index: 10;
  background: var(--bg);
  animation: brain-in 220ms ease-out;
}

/* The turn inspector is a fixed full-viewport modal, but this layer's z-index
   traps it in a stacking context below the docked panel (z 12). While it's
   open, lift the whole layer to the inspector's own level so the modal truly
   covers the page — panel and rail included. */
.agent-brain:has(.br-inspect:not([hidden])) {
  z-index: 60;
}

.agent-cockpit .agent-panel {
  z-index: 12; /* above the brain layer; overlays sit at ≤8 */
}

@keyframes brain-in {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* The monitor owns the stage: the camera overlays and the sim debug chips
   stand down while it's open (the panel carries the running state; the
   monitor shows pose and frames). */
.agent-cockpit.brain-open .overlay-stack-top-left,
.agent-cockpit.brain-open .cam-strip,
.agent-cockpit.brain-open .agent-telemetry-overlay {
  display: none;
}

.agent-cockpit.brain-open .sim-debug-stack {
  display: none !important; /* the sim stage sets its display inline */
}

.agent-cockpit.brain-open .agent-challenge-dock {
  display: none;
}

.agent-controls {
  display: flex;
  height: 36px;
  gap: 8px;
  align-items: stretch;
}

.agent-directive-picker {
  position: relative;
  flex: 1;
  min-width: 0;
}

.agent-directive {
  display: flex;
  width: 100%;
  height: 36px;
  min-width: 0;
  align-items: center;
  gap: 10px;
  padding: 0 11px;
  font-size: 12px;
  text-align: left;
  color: var(--text);
  background: var(--ctl-field);
  border: 1px solid var(--hairline-strong);
  border-radius: 9px;
  cursor: pointer;
  transition: background 150ms ease, border-color 150ms ease;
}

.agent-directive-value {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.agent-directive-chevron {
  display: grid;
  flex: 0 0 16px;
  width: 16px;
  height: 16px;
  color: var(--muted);
  place-items: center;
  transform-origin: center;
  transition: color 150ms ease, transform 180ms cubic-bezier(0.645, 0.045, 0.355, 1);
}

.agent-directive-chevron svg {
  display: block;
  width: 12px;
  height: 12px;
}

.agent-directive-picker.open .agent-directive-chevron {
  color: var(--text);
  transform: rotate(90deg);
}

.agent-directive-picker.open .agent-directive {
  background: var(--ctl-glass);
  border-color: rgb(255 255 255 / 28%);
}

.agent-directive:focus-visible {
  outline: 2px solid var(--ctl-accent);
  outline-offset: 2px;
}

@media (hover: hover) and (pointer: fine) {
  .agent-directive:hover:not(:disabled) {
    background: var(--ctl-glass);
    border-color: rgb(255 255 255 / 24%);
  }
}

.agent-directive:disabled {
  color: var(--muted);
  opacity: 0.65;
  cursor: not-allowed;
}

.agent-directive-list {
  position: absolute;
  top: calc(100% + 7px);
  left: 0;
  z-index: 4;
  display: none;
  width: max(100%, 280px);
  max-height: min(42vh, 320px);
  padding: 5px;
  overflow-y: auto;
  color: var(--text);
  background: #0c0c0f;
  border: 1px solid var(--hairline-strong);
  border-radius: 11px;
  box-shadow: 0 16px 40px rgb(0 0 0 / 44%);
}

.agent-directive-picker.open .agent-directive-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
  animation: agent-directive-in 140ms cubic-bezier(0.215, 0.61, 0.355, 1);
}

@keyframes agent-directive-in {
  from {
    opacity: 0;
  }
}

.agent-directive-option {
  display: flex;
  width: 100%;
  min-height: 36px;
  align-items: center;
  gap: 9px;
  padding: 7px 9px;
  color: var(--ctl-text);
  border-radius: 7px;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.agent-directive-option:hover,
.agent-directive-option:focus-visible {
  color: #fff;
  background: rgb(255 255 255 / 9%);
  outline: none;
}

.agent-directive-option[aria-selected="true"] {
  color: #fff;
  background: rgb(255 255 255 / 7%);
}

.agent-directive-check {
  display: flex;
  flex: 0 0 14px;
  width: 14px;
  color: var(--agent-purple);
  opacity: 0;
}

.agent-directive-check svg {
  width: 14px;
  height: 11px;
}

.agent-directive-option[aria-selected="true"] .agent-directive-check {
  opacity: 1;
}

.agent-directive-option-name,
.agent-directive-option-error {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.agent-directive-option-copy {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: 1px;
}

.agent-directive-option-error {
  color: var(--muted);
  font-size: 10px;
}

.agent-directive-option.broken {
  min-height: 46px;
  margin-top: 3px;
  padding-top: 6px;
  border-top: 1px solid var(--hairline);
  border-radius: 0 0 7px 7px;
}

.agent-directive-warning {
  display: grid;
  flex: 0 0 15px;
  width: 15px;
  height: 15px;
  color: var(--danger);
  border: 1px solid currentColor;
  border-radius: 50%;
  font-size: 10px;
  font-weight: 700;
  place-items: center;
}

.agent-directive-empty {
  padding: 9px;
  color: var(--muted);
  font-size: 11px;
}

.agent-toggle {
  position: relative;
  display: inline-flex;
  flex: 0 0 82px;
  align-items: center;
  justify-content: center;
  padding: 0 13px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ctl-accent);
  background: rgb(232 163 61 / 13%);
  border: 1px solid var(--ctl-edge-accent);
  border-radius: 9px;
  box-shadow: var(--ctl-sheen);
  transition:
    color 150ms ease,
    background-color 150ms ease,
    border-color 150ms ease,
    transform 120ms cubic-bezier(0.215, 0.61, 0.355, 1);
}

.agent-toggle::after {
  content: "";
  position: absolute;
  inset: -2px;
  border: 1px solid rgb(255 181 94 / 86%);
  border-radius: 10px;
  box-shadow:
    0 0 5px rgb(255 181 94 / 72%),
    0 0 14px rgb(242 145 48 / 48%);
  opacity: 0;
  pointer-events: none;
}

.agent-toggle:not(.stop):not(:disabled)::after {
  opacity: 0.4;
  animation: agent-start-border-pulse 2s cubic-bezier(0.455, 0.03, 0.515, 0.955) infinite;
}

@keyframes agent-start-border-pulse {
  50% {
    opacity: 1;
  }
}

@media (hover: hover) and (pointer: fine) {
  .agent-toggle:hover:not(:disabled) {
    color: var(--ctl-accent-hover);
    background: rgb(232 163 61 / 20%);
    border-color: var(--ctl-edge-accent-hover);
  }
}

.agent-toggle.stop {
  color: var(--ctl-danger);
  background: rgb(217 106 90 / 12%);
  border-color: var(--ctl-edge-danger);
}

@media (hover: hover) and (pointer: fine) {
  .agent-toggle.stop:hover:not(:disabled) {
    color: #ffd6cb;
    background: rgb(217 106 90 / 19%);
    border-color: rgb(217 106 90 / 78%);
  }
}

.agent-toggle:active:not(:disabled) {
  transform: scale(0.97);
}

.agent-toggle:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}

.agent-toggle[aria-busy="true"] {
  cursor: wait;
}

.agent-toggle:disabled:not([aria-busy="true"]) {
  color: var(--ctl-text-off);
  background: var(--ctl-field);
  border-color: var(--hairline-strong);
  box-shadow: none;
  cursor: not-allowed;
}

@media (prefers-reduced-motion: reduce) {
  .agent-toggle:not(.stop):not(:disabled)::after {
    opacity: 0.7;
  }
}

.agent-reset {
  flex: 0 0 36px;
  display: inline-grid;
  width: 36px;
  padding: 0;
  /* Secondary action: same material as the toggle, neutral instead of accent —
     the colour is the only thing separating them. */
  color: var(--ctl-text);
  background: var(--ctl-glass);
  border: 1px solid var(--hairline-strong);
  border-radius: 9px;
  box-shadow: var(--ctl-sheen);
  transition: color 150ms ease, border-color 150ms ease, background 150ms ease;
  place-items: center;
}

.agent-reset-icon {
  display: block;
  width: 16px;
  height: 16px;
  background: currentColor;
  mask: url("/js/agent/icons/trash.svg") center / contain no-repeat;
  -webkit-mask: url("/js/agent/icons/trash.svg") center / contain no-repeat;
}

.agent-reset:hover:not(:disabled) {
  color: var(--text);
  background: var(--ctl-glass-hover);
  border-color: rgb(255 255 255 / 26%);
}

.agent-reset:disabled {
  color: var(--ctl-text-off);
  background: var(--ctl-field);
  border-color: var(--hairline);
  box-shadow: none;
  cursor: not-allowed;
}

.agent-status-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.agent-activeskill {
  display: flex;
  grid-column: 1;
  align-items: center;
  height: 34px;
  min-width: 0;
  gap: 8px;
  padding: 0 10px;
  background: var(--ctl-field);
  border: 1px solid var(--hairline);
  border-radius: 9px;
  transition: background 200ms ease, border-color 200ms ease;
}

.agent-activeskill .microlabel {
  flex: 0 0 auto;
}

.agent-activeskill-name {
  flex: 1;
  min-width: 0;
  font-size: 12px;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.agent-activeskill.on {
  background: var(--ctl-glass);
  border-color: var(--ctl-edge-accent);
}

.agent-activeskill.on .agent-activeskill-name {
  color: var(--ctl-accent);
}

.agent-stream-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.agent-stream-label {
  margin: 0 2px;
}

.agent-stream-mode {
  position: relative;
  isolation: isolate;
  display: inline-grid;
  grid-template-columns: repeat(2, 1fr);
  min-width: 148px;
  gap: 2px;
  padding: 3px;
  background: var(--ctl-field);
  border: 1px solid var(--hairline-strong);
  border-radius: 11px;
}

.agent-stream-mode::before {
  position: absolute;
  z-index: 0;
  top: 3px;
  bottom: 3px;
  left: 3px;
  width: calc((100% - 8px) / 2);
  background: rgb(4 4 6 / 88%);
  border-radius: 8px;
  box-shadow:
    inset 0 0 0 1px rgb(255 255 255 / 14%),
    0 2px 6px rgb(0 0 0 / 24%);
  content: "";
  transition: transform 180ms cubic-bezier(0.645, 0.045, 0.355, 1);
}

.agent-stream-mode.detailed-selected::before {
  transform: translateX(calc(100% + 2px));
}

.agent-stream-mode-btn {
  position: relative;
  z-index: 1;
  padding: 7px 14px;
  color: var(--ctl-text-off);
  background: transparent;
  border: 0;
  border-radius: 8px;
  font: inherit;
  font-size: 10px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  cursor: pointer;
  transition: color 180ms cubic-bezier(0.645, 0.045, 0.355, 1);
}

.agent-stream-mode-btn.active {
  color: #fff;
}

@media (hover: hover) and (pointer: fine) {
  .agent-stream-mode-btn:hover:not(.active) {
    color: var(--ctl-text);
  }
}

.agent-stream-mode-btn:focus-visible {
  outline: 2px solid var(--ctl-accent);
  outline-offset: 1px;
}

/* Over translucent glass the app's --muted grey reads too dim, so the agent
   panel brightens its secondary text (thoughts, previews, status, system lines)
   to a near-white. Scoped to .agent-panel so teleop's chat is untouched. */
.agent-panel .chat-thought-item,
.agent-panel .chat-thoughts-status,

.agent-panel .chat-thoughts-label,
.agent-panel .agent-stream-label,
.agent-panel .agent-activeskill .microlabel {
  color: rgb(231 231 234 / 65%);
}

.agent-panel .chat-msg.system .chat-bubble {
  color: rgb(231 231 234 / 78%);
}

.agent-panel .chat-msg:not(.system) .chat-bubble {
  padding: 11px 14px;
  border-radius: 20px;
  font-size: 15px;
  line-height: 1.45;
}

.agent-panel .chat-msg.user .chat-bubble {
  background: rgb(12 12 16 / 56%);
  border-color: rgb(255 255 255 / 16%);
}

.agent-panel .chat-msg.robot {
  max-width: 100%;
}

.agent-panel .agent-stream > .chat-msg {
  margin-block: 6px;
}

.agent-panel .chat-msg.robot .chat-bubble {
  color: #fff;
  padding: 4px 2px;
  background: transparent;
  border: 0;
  border-radius: 0;
}

.agent-panel .agent-stream > :is(.chat-skill, .chat-skill-group) {
  margin-block: 6px;
}

.agent-stream-wrap {
  position: relative;
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  min-height: 0;
}

.agent-stream-wrap.can-scroll-up {
  padding-top: 50px;
}

.agent-stream {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-right: -12px;
  padding: 4px 12px 4px 2px;
  scrollbar-width: thin;
  scrollbar-color: rgb(255 255 255 / 22%) transparent;
}

.agent-stream > * {
  flex-shrink: 0;
}

.agent-stream-compact-spacer {
  pointer-events: none;
}

.agent-stream::-webkit-scrollbar {
  width: 7px;
}

.agent-stream::-webkit-scrollbar-track {
  background: transparent;
}

.agent-stream::-webkit-scrollbar-thumb {
  background: rgb(255 255 255 / 18%);
  background-clip: padding-box;
  border: 2px solid transparent;
  border-radius: 999px;
}

.agent-stream::-webkit-scrollbar-thumb:hover {
  background: rgb(255 255 255 / 30%);
  background-clip: padding-box;
}

.agent-stream.compact > .chat-thoughts,
.agent-stream.compact > .skill-output {
  display: none;
}

.agent-stream.compact > .compact-entering {
  animation: compact-message-in 180ms cubic-bezier(0.215, 0.61, 0.355, 1);
}

.agent-stream.compact.replaying > * {
  animation: none;
}

.agent-stream.compact .chat-sender {
  display: none;
}

.agent-stream.compact .chat-msg {
  max-width: 100%;
}

.agent-stream-earlier {
  position: absolute;
  z-index: 2;
  top: 9px;
  left: 2px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  color: rgb(231 231 234 / 78%);
  background: rgb(8 8 10 / 94%);
  border: 1px solid rgb(255 255 255 / 16%);
  border-radius: 999px;
  box-shadow: 0 6px 16px rgb(0 0 0 / 28%);
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transform: translateY(-4px);
  transition:
    opacity 150ms cubic-bezier(0.215, 0.61, 0.355, 1),
    transform 150ms cubic-bezier(0.215, 0.61, 0.355, 1),
    color 150ms ease,
    background 150ms ease,
    border-color 150ms ease;
}

.agent-stream-earlier svg {
  width: 16px;
  height: 16px;
}

.agent-stream-wrap.can-scroll-up .agent-stream-earlier {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}

.agent-stream-wrap.can-scroll-up::before {
  position: absolute;
  z-index: 1;
  top: 25px;
  right: 0;
  left: 46px;
  height: 1px;
  background: rgb(255 255 255 / 10%);
  pointer-events: none;
  content: "";
}

@media (hover: hover) and (pointer: fine) {
  .agent-stream-earlier:hover {
    color: #fff;
    background: rgb(12 12 16 / 86%);
    border-color: rgb(255 255 255 / 24%);
  }
}

.agent-stream-earlier:focus-visible {
  outline: 2px solid var(--ctl-accent);
  outline-offset: 1px;
}

@keyframes compact-message-in {
  from {
    opacity: 0;
    transform: translateY(4px);
  }
}

/* Reading surfaces are copy-paste material — chat history (discussion,
   thoughts, skill runs) and skill status/error text — so they override the
   overlays' drag-friendly `user-select: none`. */
.agent-stream,
.skills-pop-status {
  user-select: text;
  -webkit-user-select: text;
}

.agent-compose {
  position: relative;
  display: flex;
  gap: 4px;
  align-items: flex-end;
  padding: 6px 10px 6px 6px;
  background: var(--ctl-field);
  border: 1px solid var(--hairline-strong);
  border-radius: 15px;
  transition: background-color 150ms ease, border-color 150ms ease, box-shadow 150ms ease;
}

.agent-compose:focus-within {
  background: rgb(8 8 10 / 78%);
  border-color: var(--agent-purple-edge);
  box-shadow: 0 0 0 2px rgb(64 31 251 / 10%);
}

.agent-cockpit.agent-sim .agent-compose:has(.agent-mic-control:is(.waiting, .listening)) {
  flex: 0 0 auto;
  overflow: hidden;
  background: rgb(10 9 15 / 96%);
  border-color: rgb(151 135 255 / 42%);
  box-shadow:
    inset 0 1px 0 rgb(255 255 255 / 12%),
    0 8px 24px rgb(0 0 0 / 36%);
}

.agent-cockpit.agent-sim
  .agent-compose:has(.agent-mic-control:is(.waiting, .listening))
  :is(.agent-compose-input, .agent-compose-placeholder) {
  opacity: 0;
  pointer-events: none;
  transition: opacity 120ms cubic-bezier(0.215, 0.61, 0.355, 1);
}

.agent-cockpit.agent-sim
  .agent-compose:has(.agent-mic-control:is(.waiting, .listening))
  .agent-compose-mic {
  position: absolute;
  inset: 0;
  display: grid;
  width: auto;
  height: auto;
  margin: 0;
  place-items: center;
}

.agent-cockpit.agent-sim
  .agent-compose:has(.agent-mic-control:is(.waiting, .listening))
  :is(.agent-mic-control, .agent-mic-button) {
  width: 100%;
  height: 100%;
}

.agent-cockpit.agent-sim
  .agent-compose:has(.agent-mic-control:is(.waiting, .listening))
  .agent-mic-button {
  background: transparent;
  border: 0;
  border-radius: 14px;
  box-shadow: none;
  transform: none;
}

.agent-cockpit.agent-sim
  .agent-compose:has(.agent-mic-control:is(.waiting, .listening))
  .agent-mic-button::before,
.agent-cockpit.agent-sim
  .agent-compose:has(.agent-mic-control:is(.waiting, .listening))
  .agent-mic-button::after,
.agent-cockpit.agent-sim
  .agent-compose:has(.agent-mic-control:is(.waiting, .listening))
  :is(.agent-mic-inner-waves, .agent-mic-outer-waves) {
  display: none;
}

.agent-cockpit.agent-sim
  .agent-compose:has(.agent-mic-control:is(.waiting, .listening))
  .agent-mic-label {
  top: 50%;
  bottom: auto;
  left: 18px;
  color: rgb(231 231 234 / 68%);
  font-size: 10px;
  letter-spacing: 0.08em;
  transform: translateY(-50%);
}

.agent-cockpit.agent-sim
  .agent-compose:has(.agent-mic-control.listening)
  .agent-mic-waveform {
  width: 52px;
  height: 30px;
  gap: 3px;
  transform-origin: center;
  animation: agent-sim-waveform-in 180ms cubic-bezier(0.215, 0.61, 0.355, 1) 80ms both;
}

.agent-cockpit.agent-sim
  .agent-compose:has(.agent-mic-control.listening)
  .agent-mic-waveform-bar {
  height: 26px;
  background: linear-gradient(180deg, rgb(255 255 255 / 96%), var(--agent-purple));
}

.agent-cockpit.agent-sim
  .agent-compose:has(.agent-mic-control.listening)
  .agent-mic-waveform-bar:is(:first-child, :last-child) {
  opacity: 0.48;
}

.agent-cockpit.agent-sim
  .agent-compose:has(.agent-mic-control.listening)
  .agent-mic-waveform-bar:is(:nth-child(2), :nth-last-child(2)) {
  opacity: 0.68;
}

@keyframes agent-sim-waveform-in {
  from {
    opacity: 0;
    transform: scale(0.86);
  }

  to {
    opacity: 1;
    transform: scale(1);
  }
}

.agent-compose-input {
  position: relative;
  z-index: 1;
  flex: 1;
  min-width: 0;
  min-height: 52px;
  max-height: 120px;
  padding: 15px 12px;
  resize: none;
  font: inherit;
  font-size: 15px;
  line-height: 22px;
  color: var(--text);
  background: transparent;
  border: 0;
}

.agent-compose-placeholder {
  position: absolute;
  z-index: 1;
  top: 21px;
  right: 64px;
  left: 18px;
  overflow: hidden;
  color: rgb(255 255 255 / 32%);
  font-size: 15px;
  line-height: 22px;
  text-overflow: ellipsis;
  white-space: nowrap;
  pointer-events: none;
  user-select: none;
  transition: opacity 500ms cubic-bezier(0.455, 0.03, 0.515, 0.955), transform 500ms cubic-bezier(0.455, 0.03, 0.515, 0.955);
}

.agent-compose-placeholder.exiting {
  opacity: 0;
  transform: translateY(-1px);
}

.agent-compose-placeholder.entering {
  opacity: 0;
  transform: translateY(1px);
  transition: none;
}

.agent-compose-placeholder.hidden {
  opacity: 0;
  transform: none;
  transition-duration: 100ms;
}

.agent-compose-input:focus {
  outline: none;
}

.agent-compose-mic {
  position: relative;
  z-index: 2;
  display: flex;
  flex: 0 0 42px;
  width: 42px;
  height: 42px;
  margin-bottom: 4px;
}

.agent-compose-send {
  position: relative;
  flex: 0 0 42px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  margin-bottom: 4px;
  padding: 0;
  color: var(--agent-purple);
  background: var(--agent-purple-fill);
  border: 1px solid var(--agent-purple-edge);
  border-radius: 50%;
  box-shadow: var(--ctl-sheen), 0 4px 14px rgb(64 31 251 / 18%);
  transition: transform 120ms ease-out, background-color 150ms ease, border-color 150ms ease, color 150ms ease, opacity 150ms ease;
}

.agent-compose-send::before {
  position: absolute;
  inset: -8px;
  content: "";
}

.agent-compose-send-icon {
  width: 16px;
  height: 16px;
  background: currentColor;
  -webkit-mask: url("/js/agent/icons/arrow.svg") center / contain no-repeat;
  mask: url("/js/agent/icons/arrow.svg") center / contain no-repeat;
}

.agent-compose-send:disabled {
  color: rgb(255 255 255 / 24%);
  background: rgb(255 255 255 / 5%);
  border-color: rgb(255 255 255 / 8%);
  box-shadow: none;
  opacity: 0.72;
  cursor: default;
}

.agent-compose-send:active:not(:disabled) {
  transform: scale(0.96);
}

@media (hover: hover) and (pointer: fine) {
  .agent-compose-send:hover:not(:disabled) {
    color: #fff;
    background: rgb(64 31 251 / 44%);
    border-color: rgb(151 135 255 / 84%);
  }
}

@media (prefers-reduced-motion: reduce) {
  .agent-compose-send:active:not(:disabled) {
    transform: none;
  }
}

.agent-compose-send:focus-visible {
  outline: 2px solid var(--agent-purple);
  outline-offset: 2px;
}

@media (min-width: 641px) {
  .agent-cockpit .agent-stage-view-toggle {
    width: 136px;
    justify-content: center;
  }
}

@media (min-width: 641px) {
  .agent-cockpit.agent-sim .agent-feed-frame {
    position: absolute;
    display: block;
    top: var(--agent-dock-gutter);
    right: auto;
    bottom: auto;
    left: var(--agent-dock-gutter);
    width: calc(
      100% - var(--agent-dock-width) - var(--agent-dock-gutter) -
        var(--agent-dock-gutter) - var(--agent-dock-gutter)
    );
    height: auto;
    aspect-ratio: 4 / 3;
    overflow: hidden;
    background: #000;
    border: 1px solid color-mix(in srgb, var(--text) 34%, var(--bg));
    border-radius: 18px;
  }

  .agent-cockpit.agent-sim .agent-feed-frame > .video-stage {
    position: absolute !important;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 100%;
    aspect-ratio: 4 / 3;
    transform: none;
  }

  .agent-cockpit.agent-sim .video-stage > :is(canvas, video) {
    width: 100%;
    height: 100%;
    border: 0;
    border-radius: 17px;
    object-fit: cover;
  }

  .agent-cockpit.agent-sim .overlay-stack-top-left {
    top: 32px;
    right: calc(
      var(--agent-dock-width) + var(--agent-dock-gutter) + var(--agent-dock-gutter) +
        14px
    );
  }

  .agent-cockpit.agent-sim .cam-strip {
    --pip-gap: 12px;
  }

}

@media (min-width: 641px) and (max-width: 1400px) {
  .agent-cockpit .video-stage {
    position: absolute !important;
    inset: 0;
    width: auto;
    height: auto;
  }

  .agent-cockpit .video-stage video {
    width: 100%;
    height: 100%;
    max-height: none;
    border: 0;
    border-radius: 0;
    object-position: center;
    object-fit: cover;
  }

  .agent-cockpit.agent-sim .agent-feed-frame {
    inset: 0;
    width: 100%;
    height: 100%;
    aspect-ratio: auto;
    border: 0;
    border-radius: 0;
  }

  .agent-cockpit.agent-sim .agent-feed-frame > .video-stage {
    width: 100%;
    height: 100%;
    aspect-ratio: auto;
  }

  .agent-cockpit.agent-sim .video-stage > :is(canvas, video) {
    border-radius: 0;
  }
}

/* Wide-but-short screens: the 4:3 frame is derived from whatever width the dock
   leaves over, so past a certain aspect ratio it is taller than the stage and
   its bottom corners get cropped. Invert the dependency — size the frame from
   the available height, then define the dock as the width left over. Every rule
   that already anchors to --agent-dock-width (the panel, the camera strip, the
   Inspect Brain toggle) then follows the frame's edge for free. Below this the
   dock's own width still binds, so the two agree at the boundary. */
@media (min-width: 1401px) {
  .agent-cockpit.agent-sim {
    /* Fixed dock width, kept as its own name so --agent-dock-width can be
       derived below without a circular reference. */
    --agent-dock-base: 388px;
    --agent-frame-fit: calc((100dvh - 2 * var(--agent-dock-gutter)) * 4 / 3);
    --agent-frame-max: calc(
      100% - var(--agent-dock-base) - 3 * var(--agent-dock-gutter)
    );
    --agent-frame-width: min(var(--agent-frame-fit), var(--agent-frame-max));
    --agent-dock-width: calc(
      100% - var(--agent-frame-width) - 3 * var(--agent-dock-gutter)
    );
  }
}

/* Floating controls all sit --agent-overlay-inset inside the frame's edge.
   They live in two different containing blocks — the scene-setup stack is a
   child of the stage, while the challenge dock and Inspect Brain hang off the
   cockpit — so the cockpit-anchored pair add the gutter to reach the same edge
   the stage-anchored ones start from. */
@media (min-width: 641px) {
  .agent-cockpit.agent-sim .overlay-stack-top-left {
    top: calc(var(--agent-dock-gutter) + var(--agent-overlay-inset));
    right: calc(
      var(--agent-dock-width) + 2 * var(--agent-dock-gutter) +
        var(--agent-overlay-inset)
    );
  }

  .agent-cockpit .agent-stage-view-toggle {
    right: calc(
      var(--agent-dock-width) + 2 * var(--agent-dock-gutter) +
        var(--agent-overlay-inset)
    );
    bottom: calc(var(--agent-dock-gutter) + var(--agent-overlay-inset));
  }

  /* Sits to the right of the scene-setup button, which is 56px wide and starts
     one inset in from the frame's left edge. */
  .agent-cockpit .agent-challenge-dock {
    bottom: calc(var(--agent-dock-gutter) + var(--agent-overlay-inset));
    left: calc(
      var(--agent-dock-gutter) + var(--agent-overlay-inset) + 56px + 10px
    );
  }
}

@media (max-width: 1280px) {
  .agent-width-guard {
    position: fixed;
    z-index: 1000;
    inset: 0;
    isolation: isolate;
    display: grid;
    padding: clamp(20px, 4vw, 36px);
    place-items: center;
    color: var(--text);
    background: rgb(4 4 7 / 58%);
    backdrop-filter: blur(42px) saturate(0.72) brightness(0.5);
    -webkit-backdrop-filter: blur(42px) saturate(0.72) brightness(0.5);
  }

  .agent-width-guard-card {
    position: relative;
    z-index: 1;
    display: grid;
    box-sizing: border-box;
    width: min(420px, 100%);
    padding: 34px clamp(24px, 6vw, 42px);
    gap: 6px;
    text-align: center;
    background: rgb(10 10 14 / 62%);
    border: 1px solid rgb(255 255 255 / 16%);
    border-radius: 20px;
    box-shadow:
      inset 0 1px 0 rgb(255 255 255 / 10%),
      0 24px 80px rgb(0 0 0 / 52%);
  }

  .agent-width-guard-title {
    margin: 0;
    font-size: 17px;
    font-weight: 620;
    line-height: 1.3;
    letter-spacing: -0.01em;
    text-wrap: balance;
  }

  .agent-width-guard-message {
    max-width: 300px;
    margin: 0;
    justify-self: center;
    color: rgb(231 231 234 / 62%);
    font-size: 12px;
    line-height: 1.6;
    text-wrap: balance;
  }

  .agent-width-meter {
    display: grid;
    margin-top: 18px;
    gap: 11px;
    text-align: left;
  }

  .agent-width-meter-labels {
    display: flex;
    align-items: end;
    justify-content: space-between;
    gap: 16px;
  }

  .agent-width-meter-labels > span {
    display: grid;
    gap: 5px;
    color: rgb(231 231 234 / 42%);
    font-size: 8px;
    line-height: 1;
    letter-spacing: 0.14em;
    text-transform: uppercase;
  }

  .agent-width-meter-labels output {
    color: rgb(231 231 234 / 88%);
    font-family: var(--font-mono);
    font-size: 12px;
    font-weight: 540;
    letter-spacing: 0;
    text-transform: none;
  }

  .agent-width-meter-track {
    position: relative;
    height: 20px;
    overflow: hidden;
    background:
      repeating-linear-gradient(
        90deg,
        transparent 0 39px,
        rgb(255 255 255 / 7%) 39px 40px
      ),
      rgb(255 255 255 / 5%);
    border: 1px solid rgb(255 255 255 / 14%);
    border-radius: 6px;
    box-shadow: inset 0 2px 8px rgb(0 0 0 / 38%);
  }

  .agent-width-meter-track > span {
    position: absolute;
    inset: 3px;
    background: rgb(151 135 255 / 42%);
    border-radius: 3px;
    box-shadow:
      inset -3px 0 0 rgb(236 232 255 / 92%),
      0 0 18px rgb(111 88 255 / 34%);
    transform: scaleX(var(--agent-width-progress));
    transform-origin: left center;
    transition: transform 180ms cubic-bezier(0.645, 0.045, 0.355, 1);
  }

  .agent-width-meter-track::after {
    position: absolute;
    top: 5px;
    right: 5px;
    bottom: 5px;
    width: 2px;
    background: rgb(255 255 255 / 68%);
    content: "";
  }
}

/* Top-center "<agent> is running" pill — shown on non-Agent pages while the
   brain runs. Clickable: jumps to the Agent page. Glass + full pill match the
   speak bar (same translucency, even rounder edges). */
.agent-indicator {
  position: fixed;
  top: 14px;
  /* Centered over the stage, not the viewport: the 64px rail shifts the content
     area right, so half the rail (32px) keeps the pill aligned with the
     stage-centered joystick / speak bar below it. */
  left: calc(50% + 32px);
  transform: translateX(-50%);
  z-index: 40;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 7px 6px 16px;
  background: var(--ctl-glass);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid var(--hairline-strong);
  border-radius: 999px;
  box-shadow: var(--ctl-sheen);
  color: var(--text);
  font-size: 13px;
  text-decoration: none;
  transition: border-color 150ms ease, background 150ms ease;
}

.agent-indicator:hover {
  border-color: rgb(255 255 255 / 26%);
  background: var(--ctl-glass-hover);
}

.agent-indicator-dot {
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--ok);
  box-shadow: 0 0 9px var(--ok);
  animation: breathe 2.2s ease-in-out infinite;
}

.agent-indicator-label {
  white-space: nowrap;
}

.agent-indicator-stop {
  flex: 0 0 auto;
  padding: 4px 13px;
  font: inherit;
  font-size: 12px;
  color: var(--ctl-danger);
  background: var(--ctl-glass);
  border: 1px solid var(--ctl-edge-danger);
  border-radius: 999px;
  cursor: pointer;
  transition: background 150ms ease, color 150ms ease;
}

.agent-indicator-stop:hover {
  background: var(--danger);
  color: #fff;
}

.agent-indicator-stop:disabled {
  opacity: 0.5;
  cursor: default;
}

/* ---- arm protection alert ------------------------------------------------ */
/* Discrete amber card pinned top-right on every page while a servo sits in
   latched (overcurrent) protection; carries the reboot remedy. */

.arm-alert {
  position: fixed;
  top: 14px;
  right: 14px;
  z-index: 40;
  width: 216px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px 12px;
  background: var(--glass);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid var(--accent-dim);
  border-radius: 11px;
}

.arm-alert-head {
  display: flex;
  align-items: center;
  gap: 7px;
}

.arm-alert-head .microlabel {
  flex: 1;
  color: var(--accent);
}

.arm-alert-dot {
  flex: 0 0 auto;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 9px var(--accent);
}

.arm-alert-dismiss {
  flex: 0 0 auto;
  padding: 0 3px;
  font-size: 14px;
  line-height: 1;
  color: var(--muted);
}

.arm-alert-dismiss:hover {
  color: var(--text);
}

.arm-alert-text {
  margin: 0;
  font-size: 11px;
  line-height: 1.5;
  color: var(--text);
}

.arm-alert-text.warn {
  color: var(--danger);
}

/* ---- mobile teleop layout ------------------------------------------------- */
/* On a phone the centered joystick and the bottom-right arm panel collide, and
   the keyboard-only WASD chips are dead weight (and overlap the speech bar).
   Lift the arm controls out of the joystick's way — up to the left, under the
   telemetry strip, and narrower so they read as secondary — and drop WASD. */

@media (max-width: 640px) {
  /* Keyboard drive has no place on a touch screen. */
  .overlay-bottom-left {
    display: none;
  }

  /* Phones can't drive the leader arm (no WebSerial) -- drop the panel. */
  .overlay-arm {
    display: none;
  }

  /* The Robot/Link/Agent telemetry card costs too much of a small feed.
     Agent keeps its status card, but drops the camera tiles beneath it. */
  .overlay-top-left {
    display: none;
  }

  .agent-cockpit .cam-strip {
    display: none;
  }

  /* Speak bar above the Skills launcher instead of side by side: the bar
     spans the width, the Skills pill centers beneath it. */
  .overlay-tts {
    left: 14px;
    right: 14px;
    transform: none;
    flex-direction: column;
    align-items: center;
  }

  .overlay-tts .tts-bar {
    align-self: center;
    width: min(440px, 100%);
  }

  /* Full-size joystick swallows half a phone screen. */
  .overlay-joystick {
    --joystick-hit-size: 150px;
    --joystick-pad-size: 120px;
  }

  .skills-menu-btn {
    min-width: 0;
  }

  /* Camera tiles shrink to share the width (3 tiles + gaps + insets), and
     no page keeps a top-right toggle on phones -- use the full width. */
  .cam-strip,
  .cockpit:not(.agent-cockpit) .cam-strip {
    --pip-w: min(92px, 21vw);
    --pip-h: min(92px, 21vw);
    --pip-gap: 6px;
    padding: 6px;
    right: 14px;
  }

  /* The joystick sits above the stacked speak bar + Skills launcher. */
  .overlay-joystick {
    bottom: 150px;
  }

  /* Scene setup sits under the camera tiles on phones. */
  .sim-debug-stack {
    bottom: auto !important;
    top: calc(24px + min(120px, 24vw)) !important;
    left: 14px !important;
  }

  .sim-scene-panel {
    top: 66px;
    bottom: auto;
    transform-origin: top left;
  }

  .sim-scene-setup:not(.open) .sim-scene-panel {
    transform: translate(-4px, -10px) scale(0.96);
  }

  /* The camera strip spans the whole top on phones -- start below the tiles
     (the .big selector outranks the desktop cockpit offset). */
  .map-controls,
  .cam-map-host.big .map-controls {
    top: calc(26px + min(120px, 24vw));
    left: 14px;
  }
}

/* ---- mobile app promo ----------------------------------------------------- */
/* Shown only on phones/tablets (appPromo.js). Fixed over everything, including
   the rail (z 40), so it reads as a true interstitial. */

.app-promo-backdrop {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  padding: 24px;
  background: rgb(0 0 0 / 62%);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

.app-promo {
  position: relative;
  width: 320px;
  max-width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 14px;
  padding: 30px 26px 24px;
  background: var(--panel);
  border: 1px solid var(--hairline-strong);
  border-radius: 14px;
}

.app-promo-close {
  position: absolute;
  top: 12px;
  right: 14px;
  font-size: 14px;
  color: var(--muted);
}

.app-promo-close:hover {
  color: var(--text);
}

.app-promo-logo {
  height: 40px;
  width: auto;
}

.app-promo-title {
  margin: 0;
  font-size: 17px;
  font-weight: 600;
}

.app-promo-blurb {
  margin: 0;
  font-size: 13px;
  line-height: 1.55;
  color: var(--muted);
}

.app-promo-cta {
  width: 100%;
  margin-top: 4px;
  padding: 12px 0;
  border: 1px solid var(--accent-dim);
  border-radius: 9px;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  text-decoration: none;
  transition: background 150ms ease;
}

.app-promo-cta:hover {
  background: var(--accent-faint);
}

.app-promo-stay {
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  transition: color 150ms ease;
}

.app-promo-stay:hover {
  color: var(--text);
}

/* ---- Nav page (Foxglove-style sensor view) ------------------------------- */

.nav-page {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.nav-grid {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: 1fr 360px; /* scene | telemetry panels + plots */
  grid-template-rows: minmax(0, 1fr);
}

.nav-scene {
  position: relative;
  min-width: 0;
  min-height: 0;
}

.nav-side {
  border-left: 1px solid var(--hairline);
  overflow-y: auto;
  min-height: 0;
}

/* Scene-corner legend for the map's marks (bottom-right; the map controls
   own the top-left, the mapping drive kit the other corners). */
.map-legend {
  position: absolute;
  right: 12px;
  bottom: 12px;
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 9px 12px;
  font-size: 11px;
  color: var(--muted);
  background: var(--ctl-glass);
  backdrop-filter: blur(6px);
  border: 1px solid var(--hairline);
  border-radius: 10px;
  pointer-events: none;
}

/* Current-map pill (bottom-left) — the mobile app's map-name pill, same
   glyph; the pin lights amber only while a map is actually loaded. */
.map-name-pill {
  position: absolute;
  left: 12px;
  bottom: 12px;
  display: flex;
  align-items: center;
  gap: 6px;
  max-width: min(46%, 260px);
  padding: 5px 12px 5px 10px;
  font-size: 11px;
  color: var(--ctl-text);
  background: var(--ctl-glass);
  box-shadow: var(--ctl-sheen);
  backdrop-filter: blur(6px);
  border: 1px solid var(--hairline-strong);
  border-radius: 999px;
  pointer-events: none;
}

.map-name-pill svg {
  flex: none;
  width: 13px;
  height: 13px;
  color: var(--ctl-accent);
}

.map-name-pill span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.map-name-pill.is-empty {
  color: var(--ctl-text-off);
}

.map-name-pill.is-empty svg {
  color: var(--ctl-text-off);
}

.legend-row {
  display: flex;
  align-items: center;
  gap: 8px;
  /* The legend box passes pointer events through to the map; re-enable them
     per row so its topic tooltip (title) can show on hover. */
  pointer-events: auto;
}

.legend-swatch {
  flex: none;
}

.legend-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
}

.legend-line {
  width: 14px;
  height: 3px;
  border-radius: 2px;
}

/* Mirrors the costmap colormap: inflation blue → inscribed amber → lethal red. */
.legend-cost {
  width: 26px;
  height: 6px;
  border-radius: 3px;
  background: linear-gradient(to right, rgb(77 124 254 / 45%), #e8a33d, #d96a5a);
}

.nav-panel {
  padding: 14px 16px;
  border-bottom: 1px solid var(--hairline);
}

.nav-panel .microlabel {
  margin-bottom: 8px;
}

.nav-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  padding: 2px 0;
}

.nav-row-label {
  color: var(--muted);
}

.nav-row-value {
  font-size: 12px;
  text-align: right;
  overflow-wrap: anywhere;
}

/* Severity accents for status rows (localization). */
.nav-row-value.ok {
  color: var(--ok);
}

.nav-row-value.warn {
  color: var(--accent);
}

.nav-row-value.fail {
  color: var(--danger);
}

/* Live strip charts. Overrides .telemetry-plot's 190px (sized for the episode
   player's joint graph) — three stacked plots share the sidebar here. */
.nav-plot {
  height: 84px;
  margin-top: 8px;
}

.nav-plot-canvas {
  display: block;
  width: 100%;
  height: 100%;
}

/* Maps panel: roster rows + a recording banner over the scene. */
.maps-new {
  padding: 4px 10px;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
  border: 1px solid var(--accent-dim);
  border-radius: 999px;
  transition: background 150ms ease, border-color 150ms ease;
}

.maps-new:hover:not(:disabled) {
  background: var(--accent-faint);
}

.maps-new:disabled {
  color: var(--muted);
  border-color: var(--hairline);
}

.maps-list {
  margin-top: 8px;
}

.maps-row {
  display: flex;
  align-items: center;
  gap: 6px;
}

.maps-pick {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 6px;
  border-radius: 6px;
  text-align: left;
  transition: background 120ms ease;
}

.maps-pick:hover:not(:disabled) {
  background: var(--accent-faint);
}

.maps-dot {
  flex: none;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  border: 1px solid var(--hairline-strong);
}

.maps-row.is-active .maps-dot {
  background: var(--accent);
  border-color: var(--accent);
}

.maps-name {
  font-size: 12px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.maps-row.is-active .maps-name {
  color: var(--accent);
}

/* Floating map preview beside a hovered roster row (fixed — the JS positions
   it left of the sidebar so no ancestor overflow can clip it). */
.maps-preview {
  position: fixed;
  z-index: 30;
  width: 220px;
  padding: 6px;
  font-size: 11px;
  color: var(--muted);
  text-align: center;
  background: rgb(10 10 12 / 92%);
  backdrop-filter: blur(6px);
  border: 1px solid var(--hairline-strong);
  border-radius: 10px;
  pointer-events: none;
}

.maps-preview img {
  display: block;
  width: 100%;
  border-radius: 4px;
}

.maps-delete {
  flex: none;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 6px;
  color: var(--muted);
}

.maps-delete:hover:not(:disabled) {
  color: var(--danger);
  background: rgb(217 106 90 / 12%);
}

.maps-delete:disabled {
  opacity: 0.35;
  cursor: default;
}

.maps-empty,
.maps-status {
  margin-top: 8px;
  font-size: 11px;
  color: var(--muted);
}

.maps-status[data-kind="fail"] {
  color: var(--danger);
}

.maps-status[data-kind="ok"] {
  color: var(--ok);
}

.maps-mapfree {
  margin-top: 10px;
  cursor: pointer;
}

.maps-mapfree input {
  accent-color: var(--accent);
  width: 14px;
  height: 14px;
}

/* Busy veil: mode/map changes bring Nav2 lifecycle stacks up and down (up to
   a minute) — block the scene and say what's happening instead of going dead. */
.nav-veil {
  position: absolute;
  inset: 0;
  z-index: 8; /* above the banner (5) and PiP (4) */
  display: grid;
  place-items: center;
  background: rgb(10 10 12 / 55%);
  backdrop-filter: blur(2px);
}

.nav-veil-text {
  padding: 8px 16px;
  font-size: 12px;
  color: var(--accent);
  border: 1px solid var(--accent-dim);
  border-radius: 999px;
  background: var(--glass);
}

/* Map-free notice pinned over the scene (same slot as the mapping banner —
   the two modes are mutually exclusive, so they never coexist). */
.nav-scene-note {
  position: absolute;
  top: 12px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 5;
  max-width: calc(100% - 24px);
  padding: 6px 12px;
  font-size: 11px;
  color: var(--muted);
  border: 1px solid var(--hairline-strong);
  border-radius: 999px;
  background: var(--glass);
  backdrop-filter: blur(6px);
}

/* Confirm dialog body (shares the app's .modal-* frame). */
.confirm-body {
  margin: 0 0 16px;
  color: var(--muted);
  line-height: 1.5;
}

.confirm-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}

.confirm-btn {
  padding: 7px 16px;
  font-size: 12px;
  color: var(--text);
  border: 1px solid var(--hairline-strong);
  border-radius: 8px;
}

.confirm-btn:hover {
  border-color: var(--accent-dim);
}

.confirm-primary {
  color: var(--accent);
  border-color: var(--accent-dim);
  background: var(--accent-faint);
}

.confirm-primary.danger {
  color: var(--danger);
  border-color: var(--danger);
  background: rgb(217 106 90 / 12%);
}

/* Shift key cap inline in the recording line — the .wasd-chip key-cap
   language, sized to sit in a sentence and tinted to the banner's amber. */
.mapping-kbd {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 1px 5px;
  margin: 0 1px;
  vertical-align: baseline;
  border: 1px solid var(--accent-dim);
  border-radius: 5px;
  background: var(--accent-faint);
  font-family: var(--font-mono);
  font-size: 10px;
  line-height: 1.5;
}

/* Inline validity hint next to the map-name field. */
.mapping-hint {
  font-size: 10px;
  color: var(--muted);
}

.mapping-hint:empty {
  display: none;
}

/* Main-camera PiP while mapping (the drive kit's video tile). The teleop
   .video-stage inside fills it (position:absolute; inset:0). */
.nav-cam-pip {
  position: absolute;
  right: 12px;
  bottom: 12px;
  /* No z-index: driveKit appends this before the control overlays, so DOM
     order alone keeps the joystick / WASD chips / head tilt painting on top
     (same trick as .cam-map-host.big). An explicit z-index here would let the
     opaque video cover the controls. */
  /* Grow to 360px; on narrow scenes, stop at the centred 264px joystick hit target. */
  width: min(360px, calc(50% - 144px));
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border: 1px solid var(--hairline-strong);
  border-radius: 10px;
  background: #000;
}

/* Recording banner pinned over the scene while the robot is in mapping mode. */
.mapping-banner {
  position: absolute;
  top: 12px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 10px;
  max-width: calc(100% - 24px);
  padding: 8px 12px;
  border: 1px solid var(--ctl-edge-accent);
  border-radius: 10px;
  background: var(--ctl-glass);
  box-shadow: var(--ctl-sheen);
  backdrop-filter: blur(6px);
}

.mapping-banner-text {
  font-size: 12px;
  color: var(--ctl-accent);
}

.mapping-name {
  width: 130px;
  padding: 4px 8px;
  font-size: 12px;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--hairline-strong);
  border-radius: 6px;
}

.mapping-btn {
  flex: none;
  padding: 5px 12px;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text);
  border: 1px solid var(--hairline-strong);
  border-radius: 999px;
}

.mapping-btn:hover:not(:disabled) {
  border-color: var(--accent-dim);
  color: var(--accent);
}

.mapping-btn.danger:hover:not(:disabled) {
  border-color: var(--danger);
  color: var(--danger);
}

.mapping-btn:disabled {
  color: var(--muted);
}

/* Layer toggle chips in the page header. */
.layer-chips {
  display: flex;
  gap: 8px;
  margin-left: auto;
}

.layer-chip {
  padding: 5px 12px;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ctl-text);
  background: var(--ctl-glass);
  border: 1px solid var(--hairline-strong);
  border-radius: 999px;
  box-shadow: var(--ctl-sheen);
  transition: color 150ms ease, border-color 150ms ease, background 150ms ease;
}

.layer-chip:not(.is-on):hover:not(:disabled) {
  color: var(--text);
  border-color: rgb(255 255 255 / 26%);
}

.layer-chip.is-on {
  color: var(--ctl-accent);
  border-color: var(--ctl-edge-accent);
  background: linear-gradient(var(--accent-faint), var(--accent-faint)), var(--ctl-glass);
}

/* Momentary action chip (never .is-on) — reads as a button, not a toggle. */
.layer-chip-action:hover:not(:disabled) {
  color: var(--text);
  background: var(--ctl-glass-hover);
  border-color: rgb(255 255 255 / 26%);
}

.layer-chip-action:disabled {
  opacity: 0.45;
}

/* ---- Spatial memory (map layer cards + sidebar reel) ----------------------
   The layer's violet (#b48cff) is deliberately distinct from every other map
   mark; the cards share the scene's glass language (legend, status). */

.mem-card {
  position: absolute;
  z-index: 5;
  padding: 6px;
  background: rgb(10 10 12 / 88%);
  border: 1px solid var(--hairline-strong);
  border-radius: 10px;
  box-shadow: 0 6px 24px rgb(0 0 0 / 45%);
}

/* The hover thumbnail is read-only — it must never steal the canvas's cursor. */
.mem-card-hover {
  pointer-events: none;
}

.mem-card-img {
  display: block;
  width: 180px;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 6px;
  background: rgb(255 255 255 / 4%);
}

.mem-card-img-lg {
  width: 248px;
}

.mem-card-meta {
  padding-top: 6px;
  font-size: 11px;
  color: var(--muted);
  /* Never wider than the thumbnail: a long meta line otherwise stretches the
     card past the image and leaves a dead bar beside it — wrap instead. */
  width: 0;
  min-width: 100%;
}

.mem-card-popup .mem-card-img {
  cursor: zoom-in;
}

/* Full-screen viewer for a remembered image (the popup's photo opens it). */
.mem-lightbox {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: center;
  align-content: center;
  gap: 10px;
  background: rgb(10 10 12 / 82%);
  backdrop-filter: blur(6px);
}

.mem-lightbox-img {
  max-width: min(90vw, 1400px);
  max-height: 80vh;
  border: 1px solid var(--hairline-strong);
  border-radius: 12px;
  background: rgb(255 255 255 / 4%);
}

.mem-lightbox-cap {
  font-size: 12px;
  color: var(--muted);
}

.mem-lightbox-close {
  position: fixed;
  top: 14px;
  right: 18px;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  font-size: 15px;
  color: var(--muted);
  border: 1px solid var(--hairline-strong);
  border-radius: 50%;
  background: var(--ctl-glass);
}

.mem-lightbox-close:hover {
  color: var(--text);
  border-color: rgb(255 255 255 / 30%);
}

.mem-card-actions {
  display: flex;
  gap: 8px;
  margin-top: 8px;
}

.mem-card-btn {
  flex: 1;
  padding: 6px 12px;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ctl-text);
  background: var(--ctl-glass);
  border: 1px solid var(--hairline-strong);
  border-radius: 7px;
  transition: color 150ms ease, border-color 150ms ease;
}

.mem-card-btn:hover {
  color: var(--text);
  border-color: rgb(255 255 255 / 30%);
}

.mem-card-btn-go {
  color: #cbaefc;
  border-color: rgb(180 140 255 / 45%);
}

.mem-card-btn-go:hover {
  color: #e2d2ff;
  border-color: rgb(180 140 255 / 80%);
}

.mem-card-btn-forget:hover:not(:disabled) {
  color: var(--danger);
  border-color: rgb(217 106 90 / 60%);
}

.mem-card-btn-forget:disabled {
  opacity: 0.5;
  cursor: default;
}

/* The recall verdict — floats in from the top of the scene, dismisses itself. */
.mem-search-card {
  position: absolute;
  top: 12px;
  left: 50%;
  z-index: 6;
  width: min(430px, calc(100% - 24px));
  padding: 10px 12px;
  background: rgb(10 10 12 / 90%);
  border: 1px solid var(--hairline-strong);
  border-radius: 12px;
  box-shadow: 0 8px 30px rgb(0 0 0 / 50%);
  opacity: 0;
  transform: translate(-50%, -10px);
  transition: opacity 260ms ease, transform 260ms ease;
}

.mem-search-card.is-in {
  opacity: 1;
  transform: translate(-50%, 0);
}

.mem-search-card.is-found {
  border-color: rgb(180 140 255 / 45%);
  box-shadow: 0 8px 30px rgb(0 0 0 / 50%), 0 0 26px rgb(180 140 255 / 14%);
}

.mem-search-head {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.mem-search-head .microlabel {
  margin: 0;
  flex: none;
  color: #cbaefc;
}

.mem-search-query {
  min-width: 0;
  overflow: hidden;
  font-size: 13px;
  color: var(--text);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.mem-search-chip {
  flex: none;
  padding: 2px 8px;
  font-size: 10px;
  color: #cbaefc;
  background: rgb(180 140 255 / 12%);
  border: 1px solid rgb(180 140 255 / 35%);
  border-radius: 999px;
}

.mem-search-close {
  flex: none;
  margin-left: auto;
  padding: 0 4px;
  font-size: 16px;
  line-height: 1;
  color: var(--muted);
  background: none;
  border: none;
}

.mem-search-close:hover {
  color: var(--text);
}

.mem-search-body {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  margin-top: 8px;
}

.mem-search-img {
  flex: none;
  width: 132px;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 6px;
  background: rgb(255 255 255 / 4%);
}

.mem-search-text {
  font-size: 12px;
  line-height: 1.45;
  color: var(--text);
}

/* Sidebar panel: count + cache chip + the reel of remembered views. */
.mem-panel-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.mem-panel-head .microlabel {
  margin-bottom: 8px;
}

.mem-panel-count {
  font-size: 11px;
  color: var(--muted);
}

.mem-panel-chip {
  margin-left: auto;
  padding: 2px 8px;
  font-size: 10px;
  border: 1px solid var(--hairline-strong);
  border-radius: 999px;
  color: var(--muted);
}

.mem-panel-chip[data-kind="ok"] {
  color: var(--ok);
  border-color: rgb(86 194 140 / 40%);
}

.mem-panel-chip[data-kind="warn"] {
  color: var(--ctl-accent);
  border-color: rgb(232 163 61 / 40%);
}

.mem-panel-clear {
  padding: 2px 8px;
  font-size: 10px;
  color: var(--muted);
  cursor: pointer;
  background: none;
  border: 1px solid var(--hairline-strong);
  border-radius: 999px;
  transition: color 150ms ease, border-color 150ms ease;
}

.mem-panel-clear:hover:not(:disabled) {
  color: var(--danger);
  border-color: rgb(217 106 90 / 45%);
}

.mem-panel-clear:disabled {
  opacity: 0.5;
  cursor: default;
}

.mem-panel-empty {
  font-size: 12px;
  line-height: 1.5;
  color: var(--muted);
}

.mem-reel {
  display: flex;
  gap: 8px;
  padding-bottom: 4px;
  overflow-x: auto;
  scrollbar-width: thin;
}

.mem-thumb {
  position: relative;
  flex: none;
  padding: 0;
  overflow: hidden;
  background: none;
  border: 1px solid var(--hairline-strong);
  border-radius: 8px;
  transition: border-color 150ms ease, transform 150ms ease;
}

.mem-thumb:hover {
  border-color: rgb(180 140 255 / 70%);
  transform: translateY(-1px);
}

.mem-thumb-img {
  display: block;
  width: 96px;
  height: 72px;
  object-fit: cover;
}

.mem-thumb-age {
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  padding: 2px 5px;
  font-size: 9px;
  color: #ddd;
  text-align: left;
  background: linear-gradient(transparent, rgb(0 0 0 / 78%));
}

.mem-panel-search {
  margin-top: 8px;
  overflow: hidden;
  font-size: 10px;
  color: var(--muted);
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Phones: scene on top, telemetry scrolling beneath it. */
@media (max-width: 700px) {
  .nav-grid {
    grid-template-columns: 1fr;
    grid-template-rows: 55vh minmax(0, 1fr);
  }

  .nav-side {
    border-left: none;
    border-top: 1px solid var(--hairline);
  }
}
