/* ============================================================
   On-Device-Voice-Agent — the AI-coach component kit + presentations
   Consumes tokens.css only: no colour literal lives here (washes
   are color-mix() over token roles), and type and spacing ride the
   --fs-* / --sp-* scales. Panels carry the elevation bundles;
   chrome text rides the micro/body scale — 12 px floor.
   Motion happens only on a state change; prefers-reduced-motion
   zeroes every duration through the tokens (tokens.css) and the
   animation kill-switch at the bottom of this file.
   spec.html is the authority for every surface below.

   Layout map (one DOM, see app.js's presentation manager):
     grid areas  top · hero · coach · tl · metrics   (console, tablet
                 landscape) — tablet portrait and phone flatten the
                 coach column (display: contents) into
                 head · conv · sug · bar so the orb can dock over the
                 hero (tablet portrait) or ride its own row (phone).
     hooks       .hero (3D) · aside.coach (orb + caption + conversation +
                 chips + text bar) · .timeline (profile strip) ·
                 .metrics (tiles + STOP). Later work styles INSIDE
                 these; the PRESENTATIONS section owns where they sit.
   ============================================================ */

* { margin: 0; padding: 0; box-sizing: border-box; }
html, body { height: 100%; }
body {
  background: var(--bg-abyss);
  color: var(--ink);
  font-family: var(--font-body);
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}
button, input { font: inherit; color: inherit; }
button { cursor: pointer; border: 0; background: none; }
[hidden] { display: none !important; }
:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }

/* ---------- atmosphere: the two voices as washes ---------- */
.atmosphere {
  position: fixed; inset: 0; pointer-events: none; z-index: 0;
  background:
    radial-gradient(1100px 760px at 30% 40%, color-mix(in srgb, var(--cyan) 7%, transparent), transparent 62%),
    radial-gradient(900px 700px at 88% 30%, color-mix(in srgb, var(--coach) 6%, transparent), transparent 60%),
    var(--bg-base);
}

/* ---------- scaled stage (fixed design px, fit to window) ---------- */
.stage-viewport { position: fixed; inset: 0; z-index: 1; }
.stage {
  position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%);   /* fitStage appends scale() */
  transform-origin: center center;
  overflow: hidden;
  background: var(--bg-base);
}
.notch, .frame-caption { display: none; }

/* ---------- micro label ---------- */
.microlabel {
  font-size: var(--fs-micro);
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-label);
}

/* ============================================================
   THE APP GRID — the booth composition (console.html, 1920x1080
   design px). Fluid presentations re-declare the template below.
   ============================================================ */
.app {
  --pad-x: var(--sp-7);
  --gap-x: 22px;
  --coach-w: 600px;
  position: absolute; inset: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--coach-w);
  grid-template-rows: 76px minmax(0, 1fr) auto auto;
  grid-template-areas:
    "top     top"
    "hero    coach"
    "tl      coach"
    "metrics coach";
  gap: 18px var(--gap-x);
  padding: 18px var(--pad-x) 26px;
}
.topbar  { grid-area: top; }
.hero    { grid-area: hero; }
.timeline { grid-area: tl; }
.metrics { grid-area: metrics; }
aside.coach { grid-area: coach; }   /* the COLUMN — a bubble is .msg.coach */

/* the live screen hides while the start screen owns the stage */
.stage[data-screen="start"] .app { visibility: hidden; }

/* ---------- HR zone colour: ONE mapping, read as --zc by the HR tile,
   the segment label, the zone strip and the next-segment card ---------- */
:where(.stat.hr, .tl-seg, .tl-seg-bar) { --zc: var(--z3); }
:where(.tl-next) { --zc: var(--ink-faint); }
[data-zone="1"] { --zc: var(--z1); }
[data-zone="2"] { --zc: var(--z2); }
[data-zone="3"] { --zc: var(--z3); }
[data-zone="4"] { --zc: var(--z4); }
[data-zone="5"] { --zc: var(--z5); }

/* ---------- panel ---------- */
.hero, aside.coach, .timeline, .metrics {
  border-radius: var(--r-lg);
  background: var(--panel);
  box-shadow: var(--elev-2);
}

/* ============================================================
   TOP BAR — brand · status lights · on-device · latency · clock · lang
   ============================================================ */
.topbar {
  display: flex; align-items: center; gap: 18px;
  padding: 0 6px;
  min-width: 0;
}
.brand { display: flex; align-items: center; gap: var(--sp-3); flex: none; padding: 0; text-align: left; border-radius: var(--r-md); }
/* Home: the brand is a button (≥44 px target) on the live screen only —
   inert on the start screen, where .app is hidden and sv-brand shows */
.brand:focus-visible { outline: 2px solid var(--cyan); outline-offset: 3px; }
.brand .mark {
  width: 44px; height: 44px; border-radius: 13px;
  display: grid; place-items: center;
  color: var(--coach);
  background: var(--coach-wash);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--coach) 35%, transparent);
}
.brand .mark svg { width: 28px; height: 28px; }
.brand .names { display: flex; flex-direction: column; line-height: var(--lh-tight); }
.brand .name {
  font-family: var(--font-display); font-size: var(--fs-xl); letter-spacing: 0.06em;
}
.brand .sub {
  font-size: var(--fs-micro); font-weight: 600; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--coach);
}

.lights {
  display: flex; align-items: center; gap: var(--sp-1);
  margin-left: 18px; padding: 5px;
  border-radius: var(--r-pill);
  background: var(--panel);
  box-shadow: var(--elev-1);
  min-width: 0;
}
.light {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  height: 32px; padding: 0 14px 0 var(--sp-3);
  border-radius: var(--r-pill);
  font-size: var(--fs-xs); font-weight: 600; color: var(--ink-dim);
  white-space: nowrap;
}
.light i {
  width: 8px; height: 8px; border-radius: 50%; flex: none;
  background: var(--ink-faint);
  transition: background var(--t-med), box-shadow var(--t-med);
}
.light[data-state="ready"] i { background: var(--cyan); box-shadow: 0 0 10px var(--cyan-glow); }
.light[data-state="loading"] i { background: var(--amber); animation: blink 1.1s steps(2, jump-none) infinite; }
.light[data-state="error"] i { background: var(--danger); box-shadow: 0 0 10px var(--danger-wash); }
.light[data-state="error"] { color: var(--danger); }
.light[data-state="off"] { opacity: 0.55; }
@keyframes blink { 50% { opacity: 0.25; } }

.device-badge, .offline-badge, .lat-chip {
  display: inline-flex; align-items: center; gap: 7px;
  height: 32px; padding: 0 var(--sp-3);
  border-radius: var(--r-pill);
  font-size: var(--fs-xs); font-weight: 600; white-space: nowrap;
}
.device-badge svg, .offline-badge svg, .lat-chip svg { width: 16px; height: 16px; flex: none; }
.device-badge { color: var(--ok); background: var(--ok-wash); }
.offline-badge { color: var(--ink-dim); background: var(--panel); box-shadow: var(--elev-1); }
.offline-badge[aria-hidden="true"] { display: none; }
.spacer { flex: 1; }
.lat-chip {
  font-family: var(--font-mono); font-size: var(--fs-xs);
  color: var(--ink); background: var(--panel); box-shadow: var(--elev-1);
}
.lat-chip svg { color: var(--coach); }
.lat-chip .lat-lbl { font-family: var(--font-body); color: var(--ink-faint); font-weight: 500; }
.lat-chip.bump { animation: bump var(--t-med) var(--ease-out); }
@keyframes bump { 40% { box-shadow: var(--elev-1), 0 0 0 3px var(--coach-glow); } }
.clock {
  font-family: var(--font-mono); font-size: var(--fs-reply); font-weight: 500;
  color: var(--ink-dim); letter-spacing: 0.04em; font-variant-numeric: tabular-nums;
}

.lang-toggle {
  display: inline-flex; padding: 3px; gap: 2px; flex: none;
  border-radius: var(--r-pill);
  background: var(--panel); box-shadow: var(--elev-1);
}
.lang-toggle button {
  height: 34px; min-width: 46px; padding: 0 var(--sp-3);
  border-radius: var(--r-pill);
  font-size: var(--fs-xs); font-weight: 700; letter-spacing: 0.08em;
  color: var(--ink-faint);
  transition: background var(--t-fast), color var(--t-fast);
}
.lang-toggle button.on { background: var(--ink); color: var(--bg-abyss); }

/* the header folds as it narrows (a size container, so every presentation
   and language gets the same rule): badges go icon-only, then the status
   lights go dots-only, then the latency label and the wordmark leave */
.topbar { container: topbar / inline-size; }
@container topbar (max-width: 1320px) {
  .device-badge span, .offline-badge span { display: none; }
  .device-badge, .offline-badge { padding: 0 var(--sp-2); }
}
@container topbar (max-width: 1120px) {
  .light { padding: 0 var(--sp-2); gap: 0; }
  .light span { display: none; }
}
@container topbar (max-width: 700px) {
  .lat-chip .lat-lbl, .brand .names { display: none; }
}

/* ============================================================
   HERO — the 3D machine, unobstructed
   ============================================================ */
.hero { position: relative; overflow: hidden; min-height: 0;
  background:
    radial-gradient(80% 70% at 50% 60%, color-mix(in srgb, var(--cyan) 6%, transparent), transparent 70%),
    var(--panel);
}
.machine3d { position: absolute; inset: 0; width: 100%; height: 100%; display: block; touch-action: none; }
.mode-chip {
  position: absolute; left: var(--sp-5); top: 18px; z-index: 1;
  display: inline-flex; align-items: center; gap: 9px;
  height: 34px; padding: 0 14px;
  border-radius: var(--r-pill);
  font-size: var(--fs-xs); font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--ink-dim);
  background: var(--scrim-soft);
  box-shadow: var(--elev-1);
  pointer-events: none;
}
.mode-chip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--ink-faint); }
.mode-chip[data-mode="running"] .dot, .mode-chip[data-mode="warmup"] .dot { background: var(--ok); box-shadow: 0 0 10px var(--ok); }
.mode-chip[data-mode="running"], .mode-chip[data-mode="warmup"] { color: var(--ink); }
.mode-chip[data-mode="paused"] .dot { background: var(--amber); }
.mode-chip[data-mode="keyout"] .dot { background: var(--danger); }

/* ============================================================
   METRICS BAR — Anton numerals; speed/incline carry the target.
   A size container: numerals scale with the bar (cqi), so the
   same rules serve the booth, a laptop and a tablet.
   ============================================================ */
.metrics {
  container: metrics / inline-size;
  display: grid;
  /* cols 5+6 are wider: HR's label is the longest, and HR moves into col 5
     when the narrow-bar rule below drops pace */
  grid-template-columns: 1.3fr 1fr 0.95fr 1fr 1.2fr 1.2fr 0.95fr auto;
  align-items: stretch;
  padding: 0;
  overflow: hidden;
}
/* top-aligned, never centred: tiles hold different rows (speed/incline an .alt row, HR its band and
   hint), and centring each one put the labels at 3 heights across the strip */
.stat {
  position: relative;
  display: flex; flex-direction: column; justify-content: flex-start; gap: var(--sp-1);
  --stat-px: 18px;                       /* the tile's side padding: the target chip aligns to it */
  padding: 18px var(--stat-px);
  min-width: 0;
}
.metrics .microlabel { letter-spacing: 0.16em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.stat + .stat { box-shadow: inset 1px 0 0 var(--panel-edge); }
.stat .num, .stat .value-row {
  display: flex; align-items: baseline; gap: 6px;
  font-family: var(--font-display);
  font-size: clamp(var(--fs-num-sm), 3.4cqi, var(--fs-num)); line-height: 1;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.stat small {
  font-family: var(--font-body); font-size: var(--fs-xs); font-weight: 600;
  color: var(--ink-faint); letter-spacing: 0.04em;
}
.stat .alt { font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--ink-faint); white-space: nowrap; }
.stat .alt { transition: opacity var(--t-med); }
.stat[data-armed="1"] .alt { opacity: 0; }
.stat-speed .value-row, .stat-incline .value-row { font-size: clamp(var(--fs-num), 5.8cqi, var(--fs-num-lg)); }
.stat-speed .value { color: var(--ink); }
.stat-speed[data-armed="1"] .value, .stat-incline[data-armed="1"] .value { color: var(--ink-dim); }
/* a narrow bar (laptop console) drops pace — time + distance carry it */
@container metrics (max-width: 1000px) {
  .metrics .stat-pace { display: none; }
}


/* the commanded value rides beside the numeral while the belt ramps */
/* Where it sits: a tile with an .alt row (console, tablet landscape) is too narrow
   for label + chip on one line ("SPE"), so the chip takes the alt row's place at the
   tile's foot and the alt row steps aside while armed. Tiles without that row
   (tablet portrait, phone: .alt is display:none) keep the chip beside the label. */
.target-marker {
  position: absolute; bottom: var(--sp-3); left: var(--stat-px); right: auto;
  padding: var(--sp-1) 10px;
  border-radius: var(--r-pill);
  font-family: var(--font-body); font-size: var(--fs-sm); font-weight: 700;
  color: var(--bg-abyss); background: var(--target);
  font-variant-numeric: tabular-nums;
  opacity: 0; transform: translateX(-8px) scale(0.8);
  pointer-events: none;
}
.target-marker::before { content: '→ '; }
.target-marker.show { animation: marker-in var(--t-card) var(--ease-spring) forwards; }
.target-marker.merge { animation: marker-merge var(--t-med) var(--ease-out) forwards; }
@keyframes marker-in { from { opacity: 0; transform: translateX(-8px) scale(0.8); } to { opacity: 1; transform: none; } }
@keyframes marker-merge { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateX(-16px) scale(0.7); } }

/* a changed value rolls up into place (app.js rollText: transform/opacity only) */
.stat .roll { display: inline-block; }

/* HR: muted until a source is live; then tinted by the target zone, with
   a five-zone band (target lit) and the number coloured by in/below/above */
.stat.hr { transition: background-color var(--t-med); }
.stat.hr .num { color: var(--ink-faint); }
.stat.hr.live { background: linear-gradient(180deg, transparent 20%, color-mix(in srgb, var(--zc) 16%, transparent)); }
.stat.hr.live .num { color: var(--ink); }
.stat.hr.live[data-rel="below"] .num span { color: var(--z1); }
.stat.hr.live[data-rel="above"] .num span { color: var(--z5); }
.stat.hr .microlabel::before { content: '♥ '; color: var(--danger); opacity: 0.4; }
.stat.hr.live .microlabel::before { opacity: 1; }
.zone-band { display: flex; gap: 3px; height: 4px; margin-top: 2px; max-width: 120px; }
.zone-band i { flex: 1; border-radius: 2px; background: var(--hairline); transition: background-color var(--t-med), transform var(--t-med); }
.stat.hr[data-zone="1"] .zone-band i[data-z="1"],
.stat.hr[data-zone="2"] .zone-band i[data-z="2"],
.stat.hr[data-zone="3"] .zone-band i[data-z="3"],
.stat.hr[data-zone="4"] .zone-band i[data-z="4"],
.stat.hr[data-zone="5"] .zone-band i[data-z="5"] { background: var(--zc); transform: scaleY(1.5); }
.stat.hr:not(.live) .zone-band { opacity: 0.5; }

.stop-btn {
  margin: 14px 14px 14px 6px;
  min-width: 104px; min-height: var(--tap-lg);
  border-radius: var(--r-md);
  font-family: var(--font-display); font-size: var(--fs-xl); letter-spacing: 0.08em;
  color: var(--ink);
  background: var(--danger);
  box-shadow: 0 6px 22px var(--danger-wash), inset 0 -3px 0 color-mix(in srgb, var(--bg-abyss) 30%, transparent);
  transition: transform var(--t-fast);
}
.stop-btn:active { transform: scale(0.96); }

/* ============================================================
   WORKOUT PROFILE — the signature strip (grid area "tl").
   Head: plan · segment · target/HR · countdown. Body: the canvas
   profile (zone columns, done part lit, you-are-here) over the
   #tlSegs zone strip, and the next-segment card. With no plan the
   strip is the free-run state: a speed sparkline and the hint.
   ============================================================ */
.timeline {
  --tl-h: clamp(60px, 8.4vh, 96px);
  padding: 14px 20px 16px; min-width: 0;
  position: relative; overflow: hidden;
}
.tl-head { display: flex; align-items: center; gap: var(--sp-4); margin-bottom: 10px; min-width: 0; }
.tl-name {
  font-size: var(--fs-micro); font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--ink-label); white-space: nowrap;
}
.tl-seg {
  display: inline-flex; align-items: baseline; gap: var(--sp-2);
  font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--ink-faint); white-space: nowrap;
}
.tl-seg b {
  font-family: var(--font-body); font-weight: 800; font-size: var(--fs-lg); letter-spacing: 0.01em;
  color: var(--zc);
}
.tl-zone {
  display: inline-flex; align-items: center; gap: var(--sp-3); min-width: 0;
  font-size: var(--fs-sm); color: var(--ink-faint); white-space: nowrap;
}
.tl-target { font-family: var(--font-mono); font-size: var(--fs-xs); }
.tl-target:not(:empty)::after { content: ' bpm'; }
.tl-hr {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 10px 3px 8px; border-radius: var(--r-pill);
  font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--ink-faint);
  box-shadow: inset 0 0 0 1px var(--hairline);
}
.tl-hr b { font-weight: 700; }
.tl-hr svg { width: 13px; height: 13px; color: var(--ink-faint); }
.tl-hr[data-rel="in"] { --rc: var(--ok); }
.tl-hr[data-rel="below"] { --rc: var(--z1); }
.tl-hr[data-rel="above"] { --rc: var(--z5); }
.tl-hr[data-rel]:not([data-rel="none"]) { color: var(--rc); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--rc) 45%, transparent); }
.tl-hr[data-rel]:not([data-rel="none"]) svg { color: var(--danger); }
.tl-count { margin-left: auto; display: inline-flex; align-items: baseline; gap: 6px; white-space: nowrap; }
.tl-count b {
  font-family: var(--font-display); font-weight: 400; font-size: var(--fs-2xl); line-height: 1;
  font-variant-numeric: tabular-nums; color: var(--ink);
}
.tl-count small { font-size: var(--fs-xs); font-weight: 600; color: var(--ink-faint); letter-spacing: 0.04em; }

.tl-body {
  display: grid; grid-template-columns: minmax(0, 1fr) clamp(150px, 15%, 230px);
  gap: var(--sp-4); align-items: stretch;
}
.tl-chart { position: relative; display: flex; flex-direction: column; min-width: 0; height: var(--tl-h); }
.tl-chart canvas { display: block; width: 100%; flex: 1 1 auto; min-height: 0; }
/* the zone strip under the columns — one bar per segment (the suites read it) */
.tl-segs { display: flex; gap: 2px; height: 5px; margin-top: 5px; flex: none; }
.tl-seg-bar {
  flex: 1 1 0; min-width: 2px; border-radius: 3px;
  background: var(--zc); opacity: 0.4;
  transition: opacity var(--t-med);
}
.tl-seg-bar.past { opacity: 0.85; }
.tl-seg-bar.now { opacity: 1; animation: seg-now 1.6s var(--ease-out) infinite alternate; }
@keyframes seg-now { from { opacity: 1; } to { opacity: 0.55; } }

.tl-next {
  display: flex; flex-direction: column; justify-content: center; gap: 2px; min-width: 0;
  padding: var(--sp-2) var(--sp-3) var(--sp-2) 14px;
  border-radius: var(--r-md);
  background: color-mix(in srgb, var(--zc) 9%, transparent);
  box-shadow: inset 3px 0 0 var(--zc), var(--elev-1);
}
.tl-next .microlabel { letter-spacing: 0.16em; }
.tl-next b { font-size: var(--fs-md); font-weight: 800; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tl-next[data-last="1"] b { font-size: var(--fs-sm); white-space: normal; line-height: var(--lh-snug); }
.tl-next span:not(.microlabel) { font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--ink-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* free run */
.tl-idle { display: flex; align-items: center; gap: var(--sp-4); min-height: 40px; min-width: 0; }
.tl-free { display: none; align-items: baseline; gap: var(--sp-3); white-space: nowrap; }
.tl-free b { font-family: var(--font-display); font-weight: 400; font-size: var(--fs-xl); line-height: 1; font-variant-numeric: tabular-nums; }
.tl-free span:not(.microlabel) { font-family: var(--font-mono); font-size: var(--fs-sm); color: var(--ink-dim); }
.tl-spark { display: none; flex: 1 1 auto; min-width: 60px; height: 40px; }
.tl-hint { font-size: var(--fs-body); color: var(--ink-faint); display: flex; align-items: center; gap: 10px; min-width: 0; }
.tl-hint::before { content: ''; width: 34px; height: 6px; border-radius: 3px; flex: none;
  background: var(--grad-energy); opacity: 0.6; }
.tl-idle[data-moving="1"] .tl-free { display: inline-flex; }
.tl-idle[data-moving="1"] .tl-spark { display: block; }
.tl-idle[data-moving="1"] .tl-hint { flex: none; font-size: var(--fs-sm); }
.timeline[data-live="0"] .tl-head, .timeline[data-live="0"] .tl-body { display: none; }
.timeline[data-live="1"] .tl-idle { display: none; }

/* ============================================================
   COACH COLUMN — orb · live caption · conversation · suggestions
   ============================================================ */
aside.coach {
  display: flex; flex-direction: column;
  min-height: 0; min-width: 0; overflow: hidden;
  background:
    radial-gradient(90% 40% at 50% 0%, var(--coach-wash), transparent 70%),
    var(--panel);
}
.coach-head {
  display: flex; flex-direction: column; align-items: center;
  padding: 6px var(--sp-7) 14px;
  text-align: center;
}
.orb-shell { position: relative; display: grid; place-items: center; flex: none; }
.orb-shell canvas { display: block; }
.coach-live { width: 100%; min-width: 0; }
.orb-status {
  margin-top: 2px;
  font-size: var(--fs-xs); font-weight: 700; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--ink-faint);
  transition: color var(--t-med);
}
.orb-status[data-state="listening"] { color: var(--cyan); }
.orb-status[data-state="thinking"] { color: var(--ink); }
.orb-status[data-state="speaking"] { color: var(--coach); }
.orb-status[data-state="awaiting_confirmation"] { color: var(--amber); }
.orb-status[data-state="barge_in"] { color: var(--danger); }

.orb-status[data-paused="1"] { color: var(--ink-dim); letter-spacing: 0.12em; }

/* the live caption — a ROLLING window, not a clamp: lines wrap at word
   boundaries and the box is bottom-anchored, so the newest words of a
   long reply stay in view and older lines leave at the top (whole lines:
   the height is an exact multiple of the line box). Never mid-word. */
.transcript { margin-top: 10px; min-height: 84px; }
.heard, .reply {
  display: flex; flex-direction: column; justify-content: flex-end;
  max-height: calc(var(--lines) * var(--lh) * 1em);
  overflow: hidden; overflow-wrap: break-word;
  transition: opacity var(--t-med) var(--ease-out);
}
.heard {
  --lines: 2; --lh: var(--lh-snug);
  font-size: var(--fs-lg); font-weight: 500; line-height: var(--lh);
  color: var(--cyan);
}
.transcript.idle .heard { color: var(--ink-faint); font-weight: 400; }
.heard .cursor { display: inline-block; width: 2px; height: 1em; margin-left: 3px; vertical-align: -2px;
  background: var(--cyan); animation: blink 0.9s steps(2, jump-none) infinite; }
.reply {
  --lines: 3; --lh: 1.45;
  margin-top: 6px;
  font-size: var(--fs-reply); line-height: var(--lh); color: var(--ink);
}
/* phases (app.js): the previous turn's lines step aside while the rider
   talks; the heard line dims under the reply; a coach line nobody asked
   for shows no heard line; a rested turn collapses to the state line */
.transcript[data-phase="listening"] :is(.heard, .reply),
.transcript[data-phase="hearing"] .reply,
.transcript[data-phase="settled"] :is(.heard, .reply) { opacity: 0; }
.transcript[data-phase="reply"] .heard { opacity: 0.62; }
.transcript[data-solo="1"] .heard { display: none; }
.transcript[data-solo="1"] .reply { margin-top: 0; }
/* a pending confirmation carries a safety question: show it whole — the
   rolling window (--lines) would scroll its first words away on a narrow
   coach column. .stage raises the weight over every presentation's own --lines */
.stage .transcript[data-confirm="1"] .reply { --lines: 5; }

/* ---------- conversation ---------- */
.conv-wrap {
  flex: 1; min-height: 0;
  display: flex; flex-direction: column;
  border-top: 1px solid var(--panel-edge);
}
.sheet-handle { display: none; }        /* phone only (bottom sheet) */
.conv-title { padding: 14px var(--sp-6) 6px; }
.conv {
  list-style: none; flex: 1; min-height: 0; overflow-y: auto;
  overscroll-behavior: contain;
  padding: 6px var(--sp-5) 14px;
  display: flex; flex-direction: column; gap: var(--sp-3);
  scrollbar-width: thin; scrollbar-color: var(--panel-edge) transparent;
  mask-image: linear-gradient(to bottom, transparent 0, var(--ink) 36px);
}
.conv-empty { margin: auto; max-width: 340px; text-align: center; color: var(--ink-faint); font-size: var(--fs-body); line-height: var(--lh-body); }
.turn { display: flex; flex-direction: column; gap: 6px; animation: rise var(--t-card) var(--ease-card); }
@keyframes rise { from { opacity: 0; transform: translateY(8px); } }
.msg {
  max-width: 88%;
  padding: 10px 14px 11px;
  border-radius: var(--sp-4);
  font-size: var(--fs-body); line-height: 1.45;
  overflow-wrap: anywhere;
}
.msg .who {
  display: block; margin-bottom: 2px;
  font-size: var(--fs-micro); font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase;
}
.msg.you {
  align-self: flex-end;
  background: var(--user-wash);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--cyan) 22%, transparent);
  border-bottom-right-radius: var(--r-xs);
}
.msg.you .who { color: var(--cyan); }
.msg.coach {
  align-self: flex-start;
  background: var(--coach-wash);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--coach) 22%, transparent);
  border-bottom-left-radius: var(--r-xs);
}
.msg.coach .who { color: var(--coach); }
.msg.coach.filler .txt { color: var(--ink-faint); font-style: italic; }
.msg.interrupted .txt::after { content: '…'; color: var(--ink-faint); }
.int-tag {
  display: inline-block; margin-left: var(--sp-2);
  padding: 1px var(--sp-2); border-radius: var(--r-pill);
  font-size: var(--fs-micro); font-weight: 600;
  color: var(--danger); background: var(--danger-wash);
}
.turn-coach .msg.coach { max-width: 92%; }
.coach.sheet-open .msg.coach {
  background: color-mix(in srgb, var(--coach) 15%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--coach) 34%, transparent);
}
.coach.sheet-open .msg.you { background: color-mix(in srgb, var(--cyan) 13%, transparent); }

/* ---------- tool chips ---------- */
.chips { display: flex; flex-wrap: wrap; gap: 6px; align-self: flex-start; max-width: 100%; }
.tool-chip {
  --p: 0%;
  position: relative; overflow: hidden;
  display: inline-flex; align-items: center; gap: var(--sp-2);
  height: 30px; padding: 0 var(--sp-3) 0 10px; max-width: 100%;
  border-radius: var(--r-pill);
  font-size: var(--fs-xs); font-weight: 600;
  color: var(--ink);
  background: var(--panel);
  box-shadow: var(--elev-1);
}
.tc-lbl { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tc-icon { width: 14px; height: 14px; border-radius: 50%; flex: none; position: relative; }
.tool-chip[data-state="running"] .tc-icon {
  border: 2px solid var(--panel-edge); border-top-color: var(--coach);
  animation: spin 0.8s linear infinite;
}
.tool-chip[data-state="done"] .tc-icon { background: var(--ok); }
.tool-chip[data-state="done"] .tc-icon::after {
  content: ''; position: absolute; left: 4px; top: 2px; width: 3px; height: 6px;
  border: solid var(--bg-abyss); border-width: 0 2px 2px 0; transform: rotate(45deg);
}
.tool-chip[data-state="failed"] .tc-icon { background: var(--ink-faint); }
.tool-chip[data-state="failed"] { color: var(--ink-faint); }
.tool-chip[data-state="failed"] .tc-lbl { text-decoration: line-through; }
.tool-chip[data-state="replaced"] { color: var(--ink-faint); }
.tool-chip[data-state="replaced"] .tc-icon { background: var(--ink-faint); }
.tc-state { font-weight: 500; color: var(--ink-faint); font-size: var(--fs-micro); flex: none; font-variant-numeric: tabular-nums; }
.tc-bar { position: absolute; left: 0; right: 0; bottom: 0; height: 2px; }
.tc-bar i { display: block; height: 100%; width: var(--p); background: var(--coach); transition: width 120ms linear; }
.tool-chip[data-state="done"] .tc-bar i { background: var(--ok); }
@keyframes spin { to { transform: rotate(360deg); } }
/* a workout plan is ONE long job: "started" with a live dot, no bar
   (its progress is the profile chart's), "done" when the workout ends */
.tool-chip[data-kind="plan"] .tc-bar { display: none; }
.tool-chip[data-kind="plan"][data-state="running"] .tc-icon {
  border: 0; background: var(--coach); transform: scale(0.64);
}
/* the pulse is a halo on a pseudo-element: transform + opacity only */
.tool-chip[data-kind="plan"][data-state="running"] .tc-icon::before {
  content: ''; position: absolute; inset: 0; border-radius: 50%;
  box-shadow: 0 0 0 4px var(--coach-wash);
  animation: plan-dot 1.6s var(--ease-out) infinite;
}
.tool-chip[data-kind="plan"][data-state="running"] .tc-state { color: var(--coach); }
@keyframes plan-dot { 50% { transform: scale(1.45); opacity: 0; } }

/* ---------- suggestions + typed bar ---------- */
.suggest {
  display: flex; flex-wrap: wrap; gap: var(--sp-2);
  padding: 0 var(--sp-5) var(--sp-3);
  transition: opacity var(--t-med);
  min-width: 0;
}
.suggest[data-show="0"] { opacity: 0.35; }
.sug-chip {
  height: 38px; padding: 0 var(--sp-4);
  border-radius: var(--r-pill);
  font-size: var(--fs-sm); font-weight: 600; color: var(--ink);
  white-space: nowrap;
  background: var(--panel);
  box-shadow: inset 0 0 0 1px var(--hairline);
  transition: background var(--t-fast), box-shadow var(--t-fast);
}
.sug-chip:hover { background: var(--user-wash); box-shadow: inset 0 0 0 1px var(--cyan-dim); }
.sug-chip:active { transform: scale(0.97); }
/* confirm scope: the chips ARE the yes/no (the card stays authoritative) */
.sug-chip[data-tone="yes"] { color: var(--bg-abyss); background: var(--amber); box-shadow: none; }
.sug-chip[data-tone="no"] { box-shadow: inset 0 0 0 1px var(--ink-faint); }
.suggest[data-ctx="paused"] .sug-chip[data-key="sugResume"] { box-shadow: inset 0 0 0 1px var(--cyan-dim); color: var(--cyan); }
.text-bar {
  display: flex; gap: var(--sp-2); align-items: center;
  margin: 0 var(--sp-5) var(--sp-5); padding: 5px 5px 5px var(--sp-4);
  border-radius: var(--r-pill);
  background: var(--bg-abyss);
  box-shadow: inset 0 0 0 1px var(--panel-edge);
  min-width: 0;
}
.text-bar:focus-within { box-shadow: inset 0 0 0 1px var(--cyan-dim); }
.text-bar input {
  flex: 1; min-width: 0; height: 36px;
  border: 0; outline: 0; background: transparent;
  font-size: var(--fs-body); color: var(--ink);
}
.text-bar input::placeholder { color: var(--ink-faint); }
.text-bar button {
  width: 36px; height: 36px; border-radius: 50%; flex: none;
  display: grid; place-items: center;
  color: var(--bg-abyss); background: var(--cyan);
}
.text-bar button svg { width: 18px; height: 18px; }

/* ============================================================
   SAFETY SURFACES — colours unchanged from v1 (spec.html §safety)
   The confirm card centres over the hero column: --card-w and the
   app's --pad-x / --gap-x / --coach-w (on .stage) place it.
   ============================================================ */
.stage { --pad-x: var(--sp-7); --gap-x: 22px; --coach-w: 600px; }
.confirm-card {
  --card-w: min(560px, calc(100% - 2 * var(--sp-4)));
  position: absolute; z-index: 40;
  left: calc(var(--pad-x) + (100% - 2 * var(--pad-x) - var(--gap-x) - var(--coach-w)) / 2);
  bottom: 300px; width: var(--card-w);
  margin-left: calc(var(--card-w) / -2);
  padding: 22px var(--sp-6) 18px;
  border-radius: var(--r-lg);
  background: var(--bg-lift);
  box-shadow: var(--elev-3), 0 0 0 2px var(--amber), var(--glow-amber);
  opacity: 0; transform: translateY(16px) scale(0.98); pointer-events: none;
  transition: opacity var(--t-card) var(--ease-card), transform var(--t-card) var(--ease-card);
}
.confirm-card.show { opacity: 1; transform: none; pointer-events: auto; }
.confirm-card .head { display: flex; align-items: center; gap: 14px; }
.confirm-card .badge {
  width: 40px; height: 40px; border-radius: 50%; flex: none;
  display: grid; place-items: center;
  font-family: var(--font-display); font-size: var(--fs-num-sm);
  color: var(--bg-abyss); background: var(--amber);
}
.confirm-card .title { font-size: var(--fs-xl); font-weight: 700; line-height: 1.2; }
.confirm-card .title b { color: var(--amber); }
.confirm-card .hint { margin-top: var(--sp-2); font-size: var(--fs-body); color: var(--ink-dim); }
.confirm-card .actions { display: flex; gap: 10px; margin-top: var(--sp-4); }
.confirm-card .actions button {
  flex: 1; height: 50px; min-height: var(--tap-lg); border-radius: var(--r-md);
  font-size: var(--fs-md); font-weight: 700;
}
.confirm-card .yes { color: var(--bg-abyss); background: var(--amber); }
.confirm-card .no { color: var(--ink); background: var(--panel); box-shadow: inset 0 0 0 1px var(--hairline); }
.confirm-card .timeout { margin-top: 14px; height: 3px; border-radius: 2px; background: var(--panel-edge); overflow: hidden; }
.confirm-card .timeout i { display: block; height: 100%; background: var(--amber); transform-origin: left; }
@keyframes timeout-shrink { from { transform: scaleX(1); } to { transform: scaleX(0); } }

.limit-banner {
  position: absolute; z-index: 41; left: 50%; top: 96px;
  max-width: calc(100% - 2 * var(--sp-4));
  transform: translate(-50%, -12px);
  padding: var(--sp-3) 22px;
  border-radius: var(--r-pill);
  font-size: var(--fs-body); font-weight: 600; text-align: center;
  color: var(--ink); background: var(--bg-lift);
  box-shadow: var(--elev-3), 0 0 0 1.5px var(--danger);
  opacity: 0; pointer-events: none;
  transition: opacity var(--t-med), transform var(--t-med) var(--ease-out);
}
.limit-banner.show { opacity: 1; transform: translate(-50%, 0); }

.flash-red {
  position: absolute; inset: 0; z-index: 42; pointer-events: none;
  box-shadow: inset 0 0 0 6px var(--danger), inset 0 0 160px var(--danger-wash);
  opacity: 0;
}
.flash-red.fire { animation: flash-red 900ms var(--ease-out); }
@keyframes flash-red { 0% { opacity: 1; } 100% { opacity: 0; } }

.keyout {
  position: absolute; inset: 0; z-index: 60;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--sp-5);
  text-align: center; padding: var(--sp-8);
  background: color-mix(in srgb, var(--bg-abyss) 94%, var(--danger));
  opacity: 0; visibility: hidden;
  transition: opacity var(--t-med), visibility 0s linear var(--t-med);
}
.keyout.show { opacity: 1; visibility: visible; transition: opacity var(--t-med); }
.keyout .icon {
  width: 120px; height: 120px; border-radius: 50%;
  display: grid; place-items: center;
  color: var(--danger); background: var(--danger-wash);
  box-shadow: 0 0 0 2px var(--danger), var(--glow-red);
}
.keyout .icon svg { width: 60px; height: 60px; }
.keyout h1 { font-family: var(--font-display); font-size: var(--fs-display); letter-spacing: 0.04em; color: var(--danger); font-weight: 400; line-height: 1.1; }
.keyout p { max-width: 620px; font-size: var(--fs-lg); line-height: var(--lh-body); color: var(--ink-dim); }
.keyout button {
  margin-top: var(--sp-2); height: 56px; padding: 0 30px;
  border-radius: var(--r-pill);
  font-size: var(--fs-md); font-weight: 700;
  color: var(--ink); background: var(--panel); box-shadow: inset 0 0 0 1.5px var(--hairline);
}

/* ============================================================
   PRESENTATIONS
   body[data-presentation] = console | tablet | phone (what sits where)
   body[data-fit]          = console | fluid | phone-flow | phone-frame
                             (how the stage meets the window)
   body[data-orient]       = landscape | portrait
   ============================================================ */

/* ---------- console (booth canvas + fluid desktop): the coach head is a
   ROW — a compact orb (app.js › orbSize) beside the state line and the live
   caption — so the conversation owns the column: the audience reads what the
   agent HEARD next to the coach's reply, two exchanges in view. The caption
   is two lines heard + two lines reply at a FIXED height (min-height = both
   windows full), so the list never jumps while a reply streams; a confirm
   question still shows whole (.stage … [data-confirm] raises --lines). ---------- */
body[data-presentation="console"] .coach-head {
  flex-direction: row; align-items: center; gap: var(--sp-4);
  padding: var(--sp-3) var(--sp-6) var(--sp-3) var(--sp-4);
  text-align: left;
}
body[data-presentation="console"] .orb-status { margin-top: 0; }
body[data-presentation="console"] .transcript {
  margin-top: var(--sp-1);
  min-height: calc(2 * var(--lh-snug) * var(--fs-lg) + 6px + 2 * 1.45 * var(--fs-reply));
}
body[data-presentation="console"] .reply { --lines: 2; }
/* the title and the "What I remember" toggle share ONE row (the panel
   opens full width under them), so a fact on file costs the list no row */
body[data-presentation="console"] .conv-wrap {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-rows: auto auto minmax(0, 1fr);
}
body[data-presentation="console"] .conv-title { grid-area: 1 / 1; align-self: center; padding: var(--sp-3) var(--sp-3) var(--sp-2) var(--sp-6); }
body[data-presentation="console"] .mem:not([hidden]) { display: contents; }
body[data-presentation="console"] .mem-toggle { grid-area: 1 / 2; justify-self: end; align-self: center; margin: var(--sp-2) var(--sp-5) var(--sp-1) 0; }
body[data-presentation="console"] .mem-panel { grid-area: 2 / 1 / 3 / -1; margin: 0; padding: 0 var(--sp-5) var(--sp-2); }
body[data-presentation="console"] .conv { grid-area: 3 / 1 / 4 / -1; }

/* ---------- fluid: the stage IS the viewport (no transform) ---------- */
body[data-fit="fluid"] .stage-viewport,
body[data-fit="phone-flow"] .stage-viewport { height: 100vh; height: 100dvh; bottom: auto; }
body[data-fit="fluid"] .stage {
  left: 0; top: 0; width: 100%; height: 100%;
  transform: none;
}
body[data-fit="fluid"] .stage,
body[data-fit="fluid"] .app {
  --pad-x: clamp(var(--sp-4), 1.6vw, var(--sp-7));
  --gap-x: clamp(var(--sp-3), 1.2vw, 22px);
}
body[data-fit="fluid"] .app {
  padding:
    max(env(safe-area-inset-top, 0px), clamp(var(--sp-3), 1.4vh, 18px))
    max(env(safe-area-inset-right, 0px), var(--pad-x))
    max(env(safe-area-inset-bottom, 0px), clamp(var(--sp-3), 2vh, 26px))
    max(env(safe-area-inset-left, 0px), var(--pad-x));
  row-gap: clamp(var(--sp-3), 1.6vh, 18px);
}

/* fluid console: hero + coach column; the coach takes ~a third */
body[data-fit="fluid"][data-presentation="console"] .stage,
body[data-fit="fluid"][data-presentation="console"] .app { --coach-w: clamp(360px, 31vw, 600px); }
body[data-fit="fluid"][data-presentation="console"] .app {
  grid-template-rows: clamp(56px, 7vh, 76px) minmax(0, 1fr) auto auto;
}
body[data-fit="fluid"][data-presentation="console"] .confirm-card { bottom: clamp(200px, 30vh, 300px); }
body[data-fit="fluid"][data-presentation="console"] .metrics .microlabel { letter-spacing: 0.12em; }
@container metrics (max-width: 860px) {   /* the 1280 laptop: "HEART RATE" still fits */
  body[data-fit="fluid"][data-presentation="console"] .metrics .stat.hr .microlabel { letter-spacing: 0.04em; }
}
body[data-fit="fluid"] .limit-banner { top: calc(env(safe-area-inset-top, 0px) + 84px); }
@media (max-height: 820px) {
  body[data-fit="fluid"][data-presentation="console"] .stat { --stat-px: var(--sp-4); padding: var(--sp-3) var(--stat-px); }
  body[data-fit="fluid"][data-presentation="console"] .timeline { padding: var(--sp-3) var(--sp-5) 14px; }
  body[data-fit="fluid"][data-presentation="console"] .tl-head { margin-bottom: var(--sp-2); }
  body[data-fit="fluid"][data-presentation="console"] .transcript {
    min-height: calc(2 * var(--lh-snug) * var(--fs-md) + 6px + 2 * 1.45 * var(--fs-md));
  }
  body[data-fit="fluid"][data-presentation="console"] :is(.heard, .reply) { font-size: var(--fs-md); }
}
/* a desktop up to 900 px tall: the suggestions keep ONE row (scrolls
   sideways, as on the tablet) so two exchanges stay in the conversation */
@media (max-height: 900px) {
  body[data-fit="fluid"][data-presentation="console"] .suggest {
    flex-wrap: nowrap; overflow-x: auto; overscroll-behavior-x: contain;
    scrollbar-width: thin; scrollbar-color: var(--panel-edge) transparent;
  }
  body[data-fit="fluid"][data-presentation="console"] .sug-chip { flex: none; }
}

/* ---------- touch presentations: every target ≥ --tap ---------- */
body[data-presentation="tablet"],
body[data-presentation="phone"] { touch-action: manipulation; }
body:is([data-presentation="tablet"], [data-presentation="phone"]) .lang-toggle button { height: var(--tap); min-width: var(--tap); }
body:is([data-presentation="tablet"], [data-presentation="phone"]) .sug-chip { height: var(--tap); padding: 0 18px; }
body:is([data-presentation="tablet"], [data-presentation="phone"]) .text-bar { padding: var(--sp-1) var(--sp-1) var(--sp-1) 18px; }
body:is([data-presentation="tablet"], [data-presentation="phone"]) .text-bar input { height: var(--tap); font-size: var(--fs-md); }
body:is([data-presentation="tablet"], [data-presentation="phone"]) .text-bar button { width: var(--tap); height: var(--tap); }
body:is([data-presentation="tablet"], [data-presentation="phone"]) .stop-btn { min-height: var(--tap-lg); min-width: 96px; }
body:is([data-presentation="tablet"], [data-presentation="phone"]) .confirm-card .actions button { height: 56px; }
body:is([data-presentation="tablet"], [data-presentation="phone"]) .sug-chip:hover { background: var(--panel); box-shadow: inset 0 0 0 1px var(--hairline); }

/* ---------- stacked layouts (phone + tablet portrait): the coach COLUMN
   flattens into the app grid (head · conv · sug · bar) — aside.coach,
   never the .msg.coach bubble. :where() keeps these at plain-class
   weight so each presentation's own rules below refine them. ---------- */
:where(body[data-presentation="phone"], body[data-presentation="tablet"][data-orient="portrait"]) aside.coach { display: contents; }
:where(body[data-presentation="phone"], body[data-presentation="tablet"][data-orient="portrait"]) .orb-status { margin-top: 0; font-size: var(--fs-micro); }
:where(body[data-presentation="phone"], body[data-presentation="tablet"][data-orient="portrait"]) .transcript { min-height: 0; }
:where(body[data-presentation="phone"], body[data-presentation="tablet"][data-orient="portrait"]) .heard { --lines: 1; }
:where(body[data-presentation="phone"], body[data-presentation="tablet"][data-orient="portrait"]) .reply { --lines: 2; margin-top: 2px; }
:where(body[data-presentation="phone"], body[data-presentation="tablet"][data-orient="portrait"]) .conv-wrap {
  grid-area: conv;
  border-top: 0;
  background: var(--panel); box-shadow: var(--elev-2);
  overflow: hidden;
}
:where(body[data-presentation="phone"], body[data-presentation="tablet"][data-orient="portrait"]) .suggest { grid-area: sug; flex-wrap: nowrap; overflow-x: auto; }
:where(body[data-presentation="phone"], body[data-presentation="tablet"][data-orient="portrait"]) .text-bar { grid-area: bar; margin: 0; }

/* ============================================================
   TABLET (iPad-class: short side 600–1100)
   ============================================================ */
body[data-presentation="tablet"] .topbar { gap: var(--sp-3); padding: 0; }
body[data-presentation="tablet"] .lights { margin-left: var(--sp-2); }
body[data-presentation="tablet"] .clock,
body[data-presentation="tablet"] .brand .sub { display: none; }

/* metrics as big separate tiles + STOP (shared by both orientations) */
body[data-presentation="tablet"] .metrics {
  background: none; box-shadow: none; border-radius: 0; overflow: visible;
  gap: var(--sp-3);
}
body[data-presentation="tablet"] .stat {
  border-radius: var(--r-lg);
  background: var(--panel);
  box-shadow: var(--elev-2);
  --stat-px: var(--sp-5);
  padding: var(--sp-4) var(--stat-px);
}
body[data-presentation="tablet"] .stat + .stat { box-shadow: var(--elev-2); }
body[data-presentation="tablet"] .stop-btn { margin: 0; border-radius: var(--r-lg); font-size: var(--fs-2xl); }
body[data-presentation="tablet"][data-orient="portrait"] .target-marker { top: var(--sp-3); bottom: auto; left: auto; right: var(--sp-3); }

/* -- tablet landscape: hero 60 % | coach 40 %, strip + tiles full width -- */
body[data-presentation="tablet"][data-orient="landscape"] .stage,
body[data-presentation="tablet"][data-orient="landscape"] .app { --coach-w: 40%; }
body[data-presentation="tablet"][data-orient="landscape"] .app {
  grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
  grid-template-rows: auto minmax(0, 1fr) auto auto;
  grid-template-areas:
    "top     top"
    "hero    coach"
    "tl      tl"
    "metrics metrics";
}
body[data-presentation="tablet"][data-orient="landscape"] .metrics {
  grid-template-columns: 1.35fr 1.1fr 1fr 1fr minmax(120px, 0.8fr);
}
body[data-presentation="tablet"][data-orient="landscape"] .stat-dist,
body[data-presentation="tablet"][data-orient="landscape"] .stat-pace,
body[data-presentation="tablet"][data-orient="landscape"] .stat-kcal { display: none; }
body[data-presentation="tablet"][data-orient="landscape"] .stat .num { font-size: clamp(32px, 4.4cqi, 52px); }
body[data-presentation="tablet"][data-orient="landscape"] .stat-speed .value-row,
body[data-presentation="tablet"][data-orient="landscape"] .stat-incline .value-row { font-size: clamp(var(--fs-num), 6cqi, var(--fs-num-lg)); }
body[data-presentation="tablet"][data-orient="landscape"] .coach-head {
  flex-direction: row; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-5) var(--sp-3) var(--sp-3); text-align: left;
}
body[data-presentation="tablet"][data-orient="landscape"] .orb-status { margin-top: 0; }
body[data-presentation="tablet"][data-orient="landscape"] .transcript { min-height: 0; margin-top: var(--sp-1); }
body[data-presentation="tablet"][data-orient="landscape"] .heard { font-size: var(--fs-md); }
body[data-presentation="tablet"][data-orient="landscape"] .reply { font-size: var(--fs-md); --lines: 2; }
body[data-presentation="tablet"][data-orient="landscape"] .conv-title { padding: var(--sp-3) var(--sp-5) var(--sp-1); }
body[data-presentation="tablet"][data-orient="landscape"] .suggest { flex-wrap: nowrap; overflow-x: auto; }
body[data-presentation="tablet"][data-orient="landscape"] .confirm-card { bottom: auto; top: 22%; }

/* -- tablet portrait: hero on top with the orb docked over it, strip,
      3x2 tiles + STOP, conversation fills the rest -- */
body[data-presentation="tablet"][data-orient="portrait"] .app {
  grid-template-columns: minmax(0, 1fr);
  /* the conversation keeps ~2 bubbles (140 px) — the hero gives way first */
  grid-template-rows: auto minmax(220px, 38dvh) auto auto minmax(140px, 1fr) auto auto;
  grid-template-areas: "top" "hero" "tl" "metrics" "conv" "sug" "bar";
}
body[data-presentation="tablet"][data-orient="portrait"] .coach-head {
  grid-area: hero; align-self: end; justify-self: end;
  position: relative; z-index: 2;
  flex-direction: row-reverse; align-items: center; gap: var(--sp-3);
  width: min(560px, calc(100% - 2 * var(--sp-4)));
  margin: 0 var(--sp-3) var(--sp-3) 0;
  padding: var(--sp-2) var(--sp-2) var(--sp-2) var(--sp-5);
  text-align: left;
  border-radius: var(--r-xl);
  /* a solid scrim, not a live blur over the 3D canvas (touch GPUs) */
  background: color-mix(in srgb, var(--bg-base) 90%, transparent);
  box-shadow: var(--elev-2);
}
body[data-presentation="tablet"][data-orient="portrait"] .transcript { margin-top: var(--sp-1); }
body[data-presentation="tablet"][data-orient="portrait"] .heard { font-size: var(--fs-md); }
body[data-presentation="tablet"][data-orient="portrait"] .reply { font-size: var(--fs-body); }
body[data-presentation="tablet"][data-orient="portrait"] .conv-wrap { border-radius: var(--r-lg); }
body[data-presentation="tablet"][data-orient="portrait"] .conv-title { padding: var(--sp-3) var(--sp-5) var(--sp-1); }
body[data-presentation="tablet"][data-orient="portrait"] .suggest { padding: 0; }
body[data-presentation="tablet"][data-orient="portrait"] .metrics {
  grid-template-columns: repeat(3, minmax(0, 1fr)) minmax(112px, 0.7fr);
  grid-template-rows: auto auto;
}
body[data-presentation="tablet"][data-orient="portrait"] .stat-speed { grid-column: 1; grid-row: 1; }
body[data-presentation="tablet"][data-orient="portrait"] .stat-incline { grid-column: 2; grid-row: 1; }
body[data-presentation="tablet"][data-orient="portrait"] .stat-time { grid-column: 3; grid-row: 1; }
body[data-presentation="tablet"][data-orient="portrait"] .stat-dist { grid-column: 1; grid-row: 2; }
body[data-presentation="tablet"][data-orient="portrait"] .stat.hr { grid-column: 2; grid-row: 2; }
body[data-presentation="tablet"][data-orient="portrait"] .stat-kcal { grid-column: 3; grid-row: 2; }
body[data-presentation="tablet"][data-orient="portrait"] .stat-pace { display: none; }
body[data-presentation="tablet"][data-orient="portrait"] .stop-btn { grid-column: 4; grid-row: 1 / span 2; }
body[data-presentation="tablet"][data-orient="portrait"] .stat { padding: var(--sp-3) var(--sp-4); }
body[data-presentation="tablet"][data-orient="portrait"] .stat .num { font-size: clamp(30px, 5cqi, var(--fs-num)); }
body[data-presentation="tablet"][data-orient="portrait"] .stat-speed .value-row,
body[data-presentation="tablet"][data-orient="portrait"] .stat-incline .value-row { font-size: clamp(var(--fs-num), 7cqi, 60px); }
body[data-presentation="tablet"][data-orient="portrait"] .stat .alt { display: none; }
body[data-presentation="tablet"][data-orient="portrait"] .confirm-card {
  left: var(--sp-6); right: var(--sp-6); width: auto; margin-left: 0;
  bottom: auto; top: 22%;
}

/* ============================================================
   PHONE (short side < 600; 390x844 design px in the desktop bezel)
   ============================================================ */
body[data-presentation="phone"] .stage-viewport {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 18px;
}
body[data-presentation="phone"] .frame-caption {
  display: block;
  font-size: var(--fs-micro); font-weight: 600; letter-spacing: var(--track-label); text-transform: uppercase;
  color: var(--ink-faint);
}
body[data-presentation="phone"] .phone-frame {
  position: relative;
  width: var(--stage-w, 390px); height: var(--stage-h, 844px);
  border: 10px solid var(--bg-abyss);
  border-radius: 54px;
  overflow: hidden;
  box-shadow: var(--glow-cyan), var(--elev-3);
  box-sizing: content-box;
}
body[data-presentation="phone"] .phone-frame::before {
  content: ''; position: absolute; inset: 0; border-radius: 44px;
  box-shadow: inset 0 0 0 1px var(--hairline);
  pointer-events: none; z-index: 94;
}
body[data-presentation="phone"] .notch {
  display: block;
  position: absolute; top: var(--sp-3); left: 50%; transform: translateX(-50%);
  width: 104px; height: 30px; border-radius: var(--r-pill);
  background: var(--bg-abyss);
  z-index: 95; pointer-events: none;
}
body[data-presentation="phone"] .phone-frame > .stage { left: 50%; top: 50%; }

/* phone-flow (a phone-sized viewport): edge to edge, no bezel, NO transform */
body[data-fit="phone-flow"] .stage-viewport { display: block; }
body[data-fit="phone-flow"] .phone-frame {
  width: 100%; height: 100%;
  border: 0; border-radius: 0; box-shadow: none; overflow: visible;
}
body[data-fit="phone-flow"] .phone-frame > .stage {
  left: 0; top: 0; right: 0; bottom: 0;
  width: auto; height: auto; transform: none;
}
body[data-fit="phone-flow"] .phone-frame::before,
body[data-fit="phone-flow"] .notch,
body[data-fit="phone-flow"] .frame-caption { display: none; }

/* the phone grid: top · hero · orb row · tiles · strip · conversation
   sheet · chips · text bar (the coach column is flattened into it) */
body[data-presentation="phone"] .stage,
body[data-presentation="phone"] .app {
  --pad-x: var(--sp-3);
  --dock-h: calc(var(--tap) + var(--sp-2) + var(--tap) + 2 * var(--sp-1) + var(--sp-2));
}
body[data-presentation="phone"] .app {
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto minmax(104px, 1.15fr) auto auto auto minmax(96px, 1fr) auto auto;
  grid-template-areas: "top" "hero" "head" "metrics" "tl" "conv" "sug" "bar";
  gap: var(--sp-2);
  padding: calc(env(safe-area-inset-top, 0px) + 44px) var(--pad-x) calc(min(env(safe-area-inset-bottom, 0px), 34px) + var(--sp-2));
}
body[data-fit="phone-flow"][data-presentation="phone"] .app {
  padding:
    calc(env(safe-area-inset-top, 0px) + var(--sp-2))
    calc(env(safe-area-inset-right, 0px) + var(--pad-x))
    calc(env(safe-area-inset-bottom, 0px) + var(--sp-2))
    calc(env(safe-area-inset-left, 0px) + var(--pad-x));
}
body[data-presentation="phone"] .topbar { height: var(--tap); gap: var(--sp-2); padding: 0; }
body[data-presentation="phone"] .brand .mark { width: 36px; height: 36px; border-radius: 11px; }
/* the 36 px mark keeps its footprint; the button's hit area is the full 44 px */
body[data-presentation="phone"] .brand { min-width: var(--tap); min-height: var(--tap); justify-content: center; margin-inline: -4px; }
body[data-presentation="phone"] .brand .mark svg { width: 22px; height: 22px; }
body[data-presentation="phone"] .brand .names { display: none; }
body[data-presentation="phone"] .device-badge,
body[data-presentation="phone"] .offline-badge,
body[data-presentation="phone"] .clock { display: none; }
body[data-presentation="phone"] .lights { margin-left: auto; padding: 3px; gap: 0; order: 2; }
body[data-presentation="phone"] .light { height: 26px; padding: 0 6px; font-size: 0; gap: 0; }
body[data-presentation="phone"] .light span { display: none; }
body[data-presentation="phone"] .spacer { display: none; }
body[data-presentation="phone"] .lat-chip { height: 28px; padding: 0 var(--sp-2); font-size: var(--fs-micro); order: 1; margin-left: auto; }
body[data-presentation="phone"] .lat-chip .lat-lbl { display: none; }
body[data-presentation="phone"] .lang-toggle { order: 3; }
body[data-presentation="phone"] .lang-toggle button { padding: 0 var(--sp-2); font-size: var(--fs-micro); }

body[data-presentation="phone"] .hero { border-radius: var(--r-md); }
body[data-presentation="phone"] .mode-chip { left: 10px; top: 10px; height: 26px; padding: 0 10px; font-size: var(--fs-micro); }

/* orb + live caption row */
body[data-presentation="phone"] .coach-head {
  grid-area: head;
  flex-direction: row; align-items: center; gap: var(--sp-2);
  padding: 2px var(--sp-3) 2px 2px; text-align: left;
  min-height: 64px;
  border-radius: var(--r-md);
  background:
    radial-gradient(60% 120% at 0% 50%, var(--coach-wash), transparent 70%),
    var(--panel);
  box-shadow: var(--elev-2);
}
body[data-presentation="phone"] .orb-status { letter-spacing: 0.14em; }
body[data-presentation="phone"] .transcript { margin-top: 2px; }
body[data-presentation="phone"] .heard { font-size: var(--fs-body); }
body[data-presentation="phone"] .reply { font-size: var(--fs-sm); --lh: var(--lh-snug); }

/* tiles 2x2 + STOP */
body[data-presentation="phone"] .metrics {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(84px, 0.62fr);
  grid-template-rows: auto auto;
  border-radius: var(--r-md);
}
body[data-presentation="phone"] .stat { padding: var(--sp-2) 10px; gap: 2px; }
body[data-presentation="phone"] .stat .num { font-size: var(--fs-num-sm); gap: 3px; }
body[data-presentation="phone"] .stat small { font-size: var(--fs-micro); }
body[data-presentation="phone"] .stat .microlabel { font-size: var(--fs-micro); letter-spacing: 0.04em; text-transform: none; }
body[data-presentation="phone"] .stat-speed .value-row,
body[data-presentation="phone"] .stat-incline .value-row { font-size: 34px; }
body[data-presentation="phone"] .stat .alt { display: none; }
body[data-presentation="phone"] .stat-pace,
body[data-presentation="phone"] .stat-dist,
body[data-presentation="phone"] .stat-kcal { display: none; }
body[data-presentation="phone"] .stat + .stat { box-shadow: none; }
body[data-presentation="phone"] .stat-speed { grid-column: 1; grid-row: 1; }
body[data-presentation="phone"] .stat-incline { grid-column: 2; grid-row: 1; box-shadow: inset 1px 0 0 var(--panel-edge); }
body[data-presentation="phone"] .stat-time { grid-column: 1; grid-row: 2; box-shadow: inset 0 1px 0 var(--panel-edge); }
body[data-presentation="phone"] .stat.hr { grid-column: 2; grid-row: 2; box-shadow: inset 1px 1px 0 var(--panel-edge); }
body[data-presentation="phone"] .stop-btn { grid-column: 3; grid-row: 1 / span 2; margin: var(--sp-2) var(--sp-2) var(--sp-2) 0; min-width: 0; font-size: var(--fs-xl); }
body[data-presentation="phone"] .stat.hr .microlabel::before { content: none; }
body[data-presentation="phone"] .target-marker .tm-unit { display: none; }
body[data-presentation="phone"] .target-marker { right: 6px; top: 6px; bottom: auto; left: auto; font-size: var(--fs-micro); padding: 2px 7px; }

body[data-presentation="phone"] .timeline { --tl-h: 46px; padding: 10px var(--sp-3) 10px; border-radius: var(--r-md); }
body[data-presentation="phone"] .tl-head { gap: var(--sp-2); margin-bottom: 6px; flex-wrap: wrap; row-gap: 2px; }
body[data-presentation="phone"] .tl-name { display: none; }
body[data-presentation="phone"] .tl-seg b { font-size: var(--fs-body); }
body[data-presentation="phone"] .tl-count b { font-size: var(--fs-num-sm); }
body[data-presentation="phone"] .tl-zone { gap: var(--sp-2); width: 100%; order: 5; }
body[data-presentation="phone"] .tl-hr { padding: 1px 8px 1px 6px; }
body[data-presentation="phone"] .tl-body { grid-template-columns: minmax(0, 1fr); gap: 6px; }
body[data-presentation="phone"] .tl-next {
  flex-direction: row; align-items: baseline; gap: var(--sp-2);
  padding: 4px 10px; border-radius: var(--r-sm);
}
body[data-presentation="phone"] .tl-next b { font-size: var(--fs-sm); }
body[data-presentation="phone"] .tl-next .microlabel { letter-spacing: 0.08em; }
body[data-presentation="phone"] .tl-next[data-last="1"] b { white-space: nowrap; }
body[data-presentation="phone"] .tl-idle { gap: var(--sp-3); min-height: 30px; }
body[data-presentation="phone"] .tl-hint { font-size: var(--fs-xs); }
body[data-presentation="phone"] .tl-spark { height: 30px; }
body[data-presentation="phone"] .tl-free b { font-size: var(--fs-md); font-family: var(--font-mono); font-weight: 700; }
body[data-presentation="phone"] .tl-idle[data-moving="1"] .tl-hint { display: none; }

/* the conversation: a peek in the grid; the handle lifts it into a sheet */
body[data-presentation="phone"] .conv-wrap { border-radius: var(--r-md); transition: box-shadow var(--t-med); }
body[data-presentation="phone"] .sheet-handle {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px;
  flex: none; width: 100%; height: var(--tap);
}
body[data-presentation="phone"] .sheet-handle i {
  width: 36px; height: 4px; border-radius: 2px; background: var(--hairline);
}
body[data-presentation="phone"] .sheet-handle .microlabel { font-size: var(--fs-micro); line-height: 1; }
body[data-presentation="phone"] .conv-title { display: none; }
body[data-presentation="phone"] .conv { padding: 0 10px var(--sp-2); gap: var(--sp-2); mask-image: linear-gradient(to bottom, transparent 0, var(--ink) 20px); }
body[data-presentation="phone"] .msg { font-size: var(--fs-sm); padding: 7px 11px var(--sp-2); }
body[data-presentation="phone"] .conv-empty { font-size: var(--fs-xs); }
body[data-presentation="phone"] .coach.sheet-open .conv-wrap {
  position: absolute; z-index: 30;
  grid-area: auto;                     /* abspos in a grid: auto = the padding box, not the "conv" cell */
  left: var(--pad-x); right: var(--pad-x);
  top: calc(env(safe-area-inset-top, 0px) + var(--tap) + var(--sp-4));
  bottom: calc(env(safe-area-inset-bottom, 0px) + var(--dock-h) + var(--sp-2));
  background: var(--bg-lift);
  box-shadow: var(--elev-3), 0 -20px 60px var(--scrim);
  animation: sheet-up var(--t-card) var(--ease-card);
}
body[data-presentation="phone"][data-fit="phone-frame"] .coach.sheet-open .conv-wrap { top: 92px; }
body[data-presentation="phone"] .coach.sheet-open .sheet-handle i { background: var(--ink-dim); }
@keyframes sheet-up { from { transform: translateY(24px); opacity: 0.6; } }

/* chips: one scrolling row with edge fades */
body[data-presentation="phone"] .suggest {
  padding: 0 var(--sp-4);
  margin: 0 calc(-1 * var(--pad-x));
  scrollbar-width: none; scroll-snap-type: x proximity;
  scroll-padding-inline: var(--sp-4);
  mask-image: linear-gradient(to right, transparent 0, var(--ink) var(--sp-4), var(--ink) calc(100% - var(--sp-6)), transparent 100%);
}
body[data-presentation="phone"] .suggest::-webkit-scrollbar { display: none; }
body[data-presentation="phone"] .sug-chip { font-size: var(--fs-xs); flex: none; scroll-snap-align: start; }
body:is([data-presentation="tablet"]) .suggest {
  scrollbar-width: none;
  mask-image: linear-gradient(to right, var(--ink) calc(100% - var(--sp-8)), transparent 100%);
}

body[data-presentation="phone"] .confirm-card {
  left: var(--sp-3); right: var(--sp-3); width: auto; margin-left: 0;
  bottom: calc(env(safe-area-inset-bottom, 0px) + var(--dock-h) + var(--sp-4)); padding: var(--sp-4);
}
body[data-presentation="phone"] .confirm-card .title { font-size: var(--fs-lg); }
body[data-presentation="phone"] .confirm-card .badge { width: 32px; height: 32px; font-size: var(--fs-reply); }
body[data-presentation="phone"] .limit-banner { top: calc(env(safe-area-inset-top, 0px) + 60px); width: calc(100% - var(--sp-6)); font-size: var(--fs-sm); border-radius: var(--r-md); }
body[data-presentation="phone"] .keyout h1 { font-size: var(--fs-3xl); }
body[data-presentation="phone"] .keyout p { font-size: var(--fs-body); }
body[data-presentation="phone"] .keyout .icon { width: 90px; height: 90px; }

/* ---------- reduced motion: no loops, no transitions ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0ms !important; animation-iteration-count: 1 !important;
    transition-duration: 0ms !important;
  }
}

/* an application with no machine telemetry (app.js paintGeneric): the
   belt widgets step aside, the hero carries the app's own two lines */
.stage[data-app-panel="generic"] .machine3d,
.stage[data-app-panel="generic"] .metrics > *,
.stage[data-app-panel="generic"] .timeline > * { visibility: hidden; }
.app-panel {
  position: absolute; inset: 0; pointer-events: none;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px;
}
.app-panel-title {
  font: 600 13px/1 var(--font-body); letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-label);
}
.app-panel-display {
  font: 400 clamp(48px, 9vw, 112px)/1 var(--font-display); color: var(--ink); font-variant-numeric: tabular-nums;
}

/* ============================================================
   MIC MUTE — the customer's mic toggle (beside the typed input,
   inside the .text-bar pill) and the muted strip.
   Muted, the safety-word KWS and STT are both off: the strip states a
   safety fact, so it takes the danger role (spec.html). The pressed
   button itself stays neutral — the strip carries the warning.
   ============================================================ */
/* .text-bar button paints the send button cyan; the mute button opts out */
.text-bar button.mic-toggle {
  border-radius: 50%;
  color: var(--ink-dim); background: transparent;
  transition: background var(--t-fast), color var(--t-fast);
}
.text-bar button.mic-toggle[aria-pressed="true"] {
  color: var(--ink); background: var(--panel-edge);
}
.mic-toggle svg { width: 20px; height: 20px; flex: none; }
.mic-toggle .mic-slash { display: none; }
.mic-toggle[aria-pressed="true"] .mic-slash { display: inline; }
.text-bar button.mic-toggle:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
body:is([data-presentation="tablet"], [data-presentation="phone"]) .text-bar button.mic-toggle { width: var(--tap); height: var(--tap); }

.mute-strip {
  display: flex; align-items: center;
  margin-top: var(--sp-2); padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-sm);
  font-size: var(--fs-sm); font-weight: 600; line-height: var(--lh-snug); color: var(--ink);
  background: var(--danger-wash);
  box-shadow: inset 3px 0 0 var(--danger), inset 0 0 0 1px color-mix(in srgb, var(--danger) 40%, transparent);
}
.stage[data-mic="off"] .orb-status { cursor: pointer; }
body[data-presentation="phone"] .mute-strip { margin-top: var(--sp-1); padding: 6px var(--sp-2); font-size: var(--fs-xs); }

/* ============================================================
   CUSTOMER MESSAGING — the idle "Try saying" panel, the per-turn
   proof badge, the latency chip's visible path label
   ============================================================ */
/* the panel sits inside .conv-empty (gone with the first user turn) */
.conv-empty { max-width: min(420px, 100%); min-width: 0; }
/* phone: the Try row says it — the sentence would only crowd the sheet's peek */
body[data-presentation="phone"] .conv-empty > p { display: none; }
.try-panel {
  display: flex; flex-direction: column; gap: var(--sp-3);
  margin-top: var(--sp-4); text-align: left;
}
.try-title { color: var(--cyan); }
.try-group { display: flex; flex-direction: column; gap: 6px; }
.try-label {
  font-size: var(--fs-micro); font-weight: 600; letter-spacing: var(--track-label);
  text-transform: uppercase; color: var(--ink-faint);
}
.try-chips { display: flex; flex-wrap: wrap; gap: var(--sp-2); min-width: 0; }
.conv-empty .try-panel .sug-chip {
  height: auto; min-height: var(--tap); max-width: 100%;
  padding: 6px var(--sp-4);
  white-space: normal; text-align: left; line-height: var(--lh-snug);
}
/* phone: the sheet's peek is short — one scrolling row of chips, no group labels */
body[data-presentation="phone"] .try-panel {
  flex-direction: row; align-items: center; gap: var(--sp-2); margin-top: var(--sp-2);
  overflow-x: auto; scrollbar-width: none;
}
body[data-presentation="phone"] .try-panel::-webkit-scrollbar { display: none; }
body[data-presentation="phone"] .try-group,
body[data-presentation="phone"] .try-chips { display: contents; }
body[data-presentation="phone"] .try-label { display: none; }
body[data-presentation="phone"] .try-title { flex: none; }
body[data-presentation="phone"] .conv-empty .try-panel .sug-chip { flex: none; white-space: nowrap; }
body[data-presentation="phone"] .conv-empty .try-panel .sug-chip { font-size: var(--fs-xs); }

/* the badge on a coach reply: which brain answered + the measured reply time */
.turn-badge {
  display: flex; width: fit-content;
  margin-top: 6px; padding: 2px var(--sp-2);
  border-radius: var(--r-pill);
  font-family: var(--font-mono); font-size: var(--fs-micro); font-weight: 600;
  line-height: var(--lh-snug); white-space: nowrap;
  color: var(--ink-dim); background: var(--panel);
  box-shadow: inset 0 0 0 1px var(--hairline);
}
.turn-badge[data-path="1"] { color: var(--ok); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ok) 45%, transparent); }
.turn-badge[data-path="2"] { color: var(--coach); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--coach) 45%, transparent); }
/* what answered (app.js answerSource): the library is a neutral source, safety is the safety role */
.turn-badge[data-src="kb"] { color: var(--ink-dim); box-shadow: inset 0 0 0 1px var(--hairline); }
.turn-badge[data-src="safety"] {
  color: var(--danger); background: var(--danger-wash);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--danger) 55%, transparent);
}

/* the chip's path label is TEXT (touch has no hover): it replaces the
   generic label once a turn is measured; a narrow header folds it away
   and a tap (focus) brings it back */
.lat-chip .lat-path { font-family: var(--font-body); font-weight: 600; color: var(--coach); }
.lat-chip .lat-path:empty { display: none; }
.lat-chip:has(.lat-path:not(:empty)) .lat-lbl { display: none; }
.lat-chip:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
@container topbar (max-width: 700px) {
  .lat-chip .lat-path { display: none; }
  .lat-chip:focus .lat-path:not(:empty) { display: inline; }
}

/* half-duplex route: voice stop is deaf while the coach talks — said on the page, safety role, until the mic stops */
.hd-strip {
  position: fixed; left: 50%; top: calc(8px + env(safe-area-inset-top, 0px)); transform: translateX(-50%); z-index: 90;
  max-width: min(92vw, 640px); padding: 6px 14px; border-radius: var(--r-pill, 999px);
  border: 1px solid var(--danger); background: var(--danger-wash); color: var(--text, #fff);
  font: 600 var(--fs-micro, 12px)/1.4 var(--font-ui, system-ui, sans-serif); text-align: center;
}
.hd-strip[hidden] { display: none; }

/* ============================================================
   HEART-RATE HINT + WHAT THE COACH REMEMBERS
   ============================================================ */
/* no fresh source: the tile says how to give the coach one (hidden while a reading is live) */
.stat.hr .hr-hint {
  font-size: var(--fs-micro); line-height: var(--lh-snug); color: var(--ink-faint);
  min-width: 0; overflow: hidden;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2;
}
.stat.hr[data-src="live"] .hr-hint { display: none; }
/* nothing to show in the zone band without a reading or a plan: the hint takes its room */
.stat.hr[data-src="none"][data-zone=""] .zone-band { display: none; }

/* a collapsible list under the conversation title; the phone shows it inside the open sheet only */
.mem { flex: none; min-width: 0; padding: 0 var(--sp-5) var(--sp-2); }
.mem[hidden], .mem-panel[hidden] { display: none; }
.mem-toggle {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  max-width: 100%; min-height: 32px; padding: 0 var(--sp-3);
  border-radius: var(--r-pill);
  font-size: var(--fs-xs); font-weight: 600; color: var(--ink-dim);
  background: var(--panel); box-shadow: inset 0 0 0 1px var(--hairline);
  transition: background var(--t-fast), box-shadow var(--t-fast);
}
.mem-toggle:hover { background: var(--user-wash); box-shadow: inset 0 0 0 1px var(--cyan-dim); }
.mem-toggle:focus-visible, .mem-x:focus-visible, .mem-all:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
.mem-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mem-count { font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--cyan); }
.mem-count:empty { display: none; }
.mem-caret {
  flex: none; width: 7px; height: 7px; margin-top: -3px;
  border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: rotate(45deg); transition: transform var(--t-fast);
}
.mem-toggle[aria-expanded="true"] .mem-caret { margin-top: 3px; transform: rotate(-135deg); }
.mem-panel {
  display: flex; flex-direction: column; align-items: flex-start; gap: var(--sp-2);
  margin-top: var(--sp-2); max-height: min(34vh, 220px); overflow-y: auto; overscroll-behavior: contain;
  scrollbar-width: thin; scrollbar-color: var(--panel-edge) transparent;
}
.mem-chips { list-style: none; display: flex; flex-wrap: wrap; gap: var(--sp-2); min-width: 0; max-width: 100%; margin: 0; padding: 0; }
.mem-chip {
  display: inline-flex; align-items: center; max-width: 100%; min-height: 32px;
  padding: 0 0 0 var(--sp-3);
  border-radius: var(--r-pill);
  font-size: var(--fs-xs); font-weight: 600; color: var(--ink);
  background: var(--panel); box-shadow: inset 0 0 0 1px var(--hairline);
}
.mem-chip[data-info="1"] { padding-right: var(--sp-3); color: var(--ink-dim); }
.mem-txt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mem-x {
  flex: none; display: grid; place-items: center; width: 32px; height: 32px;
  border-radius: var(--r-pill); color: var(--ink-faint);
}
.mem-x svg { width: 14px; height: 14px; }
.mem-x:hover { color: var(--ink); background: var(--user-wash); }
.mem-all {
  min-height: 32px; padding: 0 var(--sp-1);
  font-size: var(--fs-xs); font-weight: 600; color: var(--ink-faint); text-decoration: underline;
}
.mem-all:hover { color: var(--ink); }
.mem-empty { margin: 0; font-size: var(--fs-xs); line-height: var(--lh-body); color: var(--ink-faint); }
body:is([data-presentation="tablet"], [data-presentation="phone"]) .mem-toggle,
body:is([data-presentation="tablet"], [data-presentation="phone"]) .mem-chip,
body:is([data-presentation="tablet"], [data-presentation="phone"]) .mem-all { min-height: var(--tap); }
body:is([data-presentation="tablet"], [data-presentation="phone"]) .mem-x { width: var(--tap); height: var(--tap); }
body[data-presentation="phone"] .mem { padding: 0 var(--sp-3) var(--sp-2); }
body[data-presentation="phone"] .coach:not(.sheet-open) .mem { display: none; }
