/* ============================================================================
   Infinite · design language «BLACK» (ui v5)                         read me
   ----------------------------------------------------------------------------
   DIRECTION
   Vercel-grade black-on-black. The page is a dark room; the only light comes
   from the music. Chrome is almost invisible: hairlines, graphite surfaces,
   white / soft-grey text, ONE warm accent (amber) used sparingly — active
   state, playhead, like, "live" dots. No cards-for-the-sake-of-cards, no
   explanatory paragraphs, no admin-panel look. Dense but calm; every screen
   should be something you leave on a second monitor.
     surfaces   #000 page · #050505 / #0a0a0a / #111 / #171717 graphite
     lines      rgba(255,255,255,.06 / .10 / .16) hairlines, never solid grey
     text       #ededed primary · #a1a1a1 secondary · #7a7a7a tertiary (4.9:1 on
                #000, the smallest text-safe grey) · #3d3d3d ghost (separators only)
     accent     amber #ffa133 (hi #ffc27a, lo #b86416) — never for large fills
     data       chords / lanes / sections have their own restrained tokens
                (below). Read them on canvas via api.colors / api.chordColor().
   TYPE
     --font-sans  Geist (Google Fonts, Latin + Cyrillic) → system-ui fallback
     --font-mono  Geist Mono → ui-monospace fallback: labels, numbers, keys.
     Labels: mono, 10–11 px, UPPERCASE, tracking .06em, --text-3.
     Numbers: tabular everywhere (set on body).
   SHAPE     radii 6 / 10 / 999 (pills). Hairline borders + faint inner top
             highlight (inset 0 1px 0 rgba(255,255,255,.04)). Glow only on
             accent things and on the music.
   MOTION    subtle, purposeful: --dur-1 120 ms (hover), --dur-2 200 ms (mode
             crossfade, toasts), --dur-3 420 ms (overlays); --ease-out.
             prefers-reduced-motion zeroes every --dur-*; canvas code must
             check api.prefersReducedMotion(). Flash safety: no full-area
             luminance change faster than 3/s; fast detail (hats) only on
             small areas.
   LAYERS    --z-* only. Modes live in #stage (below --z-chrome).
   NIGHT     :root[data-vibe='sleep'] (the SLEEP vibe, «Night Tide») redefines the
             tokens warm-only for a dark bedroom: text #cdb89f / #a38e76 / #8a7560,
             amber hairlines at low alpha, graphite play / start buttons with a
             1 px amber-lo ring and an amber icon (no white fills, no glow), warm
             chord / lane / section tokens (blue ≤ 0.55 × red), a static dim net
             dot. PLAY auto-hides the controls after 8 s (data-chrome='hidden';
             the first tap / key only reveals them; the timer sheet closes itself
             after 12 s). Canvas ink follows --ink-rgb / --hair-rgb (warm text-1
             at night). Nothing is white at night.
   LAYOUT    top bar --topbar-h (alias --header-h). PLAY is full-bleed under a
             transparent top bar with a floating transport pill. DSP / STUDIO:
             the transport sits inside the top bar (≥ 900 px) or in a bottom
             dock (< 900 px; #stage gets padding-bottom: var(--stage-pad-bottom)).
             Full-height mode: min-height: calc(100dvh - var(--topbar-h) - var(--stage-pad-bottom)).
             Works at 375 / 800 / ≥ 1440 px; no horizontal scroll.
   ========================================================================== */

:root {
  color-scheme: dark;

  /* surfaces */
  --bg: #000;
  --bg-1: #050505;
  --surface-1: #0a0a0a;
  --surface-2: #111111;
  --surface-3: #171717;
  --surface-4: #1f1f1f;

  /* hairlines */
  --line-1: rgba(255, 255, 255, 0.06);
  --line-2: rgba(255, 255, 255, 0.10);
  --line-3: rgba(255, 255, 255, 0.16);
  --highlight: inset 0 1px 0 rgba(255, 255, 255, 0.04);

  /* text */
  --text-1: #ededed;
  --text-2: #a1a1a1;
  --text-3: #7a7a7a;          /* text-safe tertiary: 4.9:1 on #000 (WCAG AA for 10–11 px labels) */
  --text-4: #3d3d3d;
  /* canvas ink as an "r, g, b" triplet for rgba(): ink = data strokes / fills (text-1), hair = grid hairlines */
  --ink-rgb: 237, 237, 237;
  --hair-rgb: 255, 255, 255;

  /* the one accent */
  --accent: #ffa133;
  --accent-hi: #ffc27a;
  --accent-lo: #b86416;
  --accent-glow: rgba(255, 161, 51, 0.35);
  --accent-ink: #1a0f02;

  /* status */
  --ok: #45d483;
  --warn: #ffa133;
  --bad: #ff5c5c;

  /* data: lanes (Studio / DSP) */
  --lane-kick: #f5f5f5;
  --lane-bass: #9a9a9a;
  --lane-hat: #8be3c3;
  --lane-chord: #a594ff;
  --lane-fx: #ff7ab6;
  /* sleep lanes (session.lanes of the sleep style; redefined warm under data-vibe='sleep') */
  --lane-pad: #a594ff;
  --lane-keys: #d2b6ff;
  --lane-sub: #9a9a9a;
  --lane-bell: #8be3c3;
  --lane-tide: #6f7c8f;

  /* data: chords — known ids; unknown ids get hsl(--chord-hue-from + h % span, 90%, 62–83%) */
  --chord-gm9: #8f7dff;
  --chord-gm9-hi: #d2b6ff;
  --chord-cm9: #4f8dff;
  --chord-dm7: #33d1be;
  --chord-ebmaj7: #b07dff;
  --chord-bbmaj9: #7dbbff;
  --chord-fadd9: #5fd1a0;
  --chord-dm11: #57c7e6;
  --chord-hue-from: 188;
  --chord-hue-span: 9;
  --chord-fallback-l: 62 69 76 83;

  /* data: section kinds — lightness follows density */
  --sec-intro: #6e6e6e;
  --sec-drop-light: #b9b9b9;
  --sec-drop-full: #ffffff;
  --sec-break: #7aa2ff;
  --sec-stripped: #8f9bab;
  --sec-transition: #ffd49a;
  --sec-outro: #474747;
  --sec-unknown: #8a8a8a;
  --sec-drift: #6e6e6e;
  --sec-tide: #b9b9b9;
  --sec-deep: #474747;
  --sec-glimmer: #ffd49a;
  --sec-wind-down: #3a3a3a;

  --mark-like: var(--accent);

  /* type */
  --font-sans: 'Geist', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --font-mono: 'Geist Mono', ui-monospace, 'SF Mono', SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospace;
  --fs-label: 10.5px;
  --fs-small: 12px;
  --fs-body: 13px;
  --track-label: 0.06em;

  /* shape */
  --r-1: 6px;
  --r-2: 10px;
  --r-3: 14px;
  --r-pill: 999px;

  /* layout */
  --topbar-h: 52px;
  --header-h: var(--topbar-h);
  --dock-h: 0px;
  --stage-pad-bottom: var(--dock-h);
  --gutter: 16px;

  /* motion */
  --ease-out: cubic-bezier(0.2, 0.8, 0.2, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --dur-1: 120ms;
  --dur-2: 200ms;
  --dur-3: 420ms;
  --dur-mode: var(--dur-2);
  --toast-ms: 2400;

  /* layers */
  --z-stage: 0;
  --z-chrome: 10;
  --z-overlay: 20;
  --z-toast: 30;
  --z-start: 40;
  --z-help: 50;
}

@media (prefers-reduced-motion: reduce) {
  :root { --dur-1: 0ms; --dur-2: 0ms; --dur-3: 0ms; }
}

/* ---------- NIGHT: the SLEEP vibe (warm-only, dim; see the header) ---------- */
:root[data-vibe='sleep'] {
  --bg: #000;
  --bg-1: #050302;
  --surface-1: #0a0705;
  --surface-2: #110c08;
  --surface-3: #18110b;
  --surface-4: #20170f;
  --line-1: rgba(255, 161, 51, 0.07);
  --line-2: rgba(255, 161, 51, 0.11);
  --line-3: rgba(255, 161, 51, 0.17);
  --highlight: inset 0 1px 0 rgba(255, 190, 120, 0.03);
  --text-1: #cdb89f;
  --text-2: #a38e76;
  --text-3: #8a7560;          /* ≈ 4.8:1 on #000 */
  --text-4: #3a2e24;
  --ink-rgb: 205, 184, 159;   /* canvas strokes / hairlines follow text-1: nothing is white at night (DSP, STUDIO) */
  --hair-rgb: 205, 184, 159;
  --accent: #e0913a;
  --accent-hi: #f0b070;
  --accent-lo: #8f561d;
  --accent-glow: rgba(224, 145, 58, 0.14);
  --accent-ink: #140b03;
  --ok: #8c7a4c;
  --warn: #e0913a;
  --bad: #c8603f;
  --lane-kick: #cdb89f;
  --lane-bass: #8a7560;
  --lane-hat: #b8925a;
  --lane-chord: #d9774a;
  --lane-fx: #c65a6a;
  --lane-pad: #d49a4f;
  --lane-keys: #e0ad6c;
  --lane-sub: #a8643f;
  --lane-bell: #f0c48a;
  --lane-tide: #8f6a4f;
  --chord-gm9: #d9774a;
  --chord-gm9-hi: #e59866;
  --chord-cm9: #c65a6a;
  --chord-dm7: #d49a4f;
  --chord-ebmaj7: #b86f55;
  --chord-bbmaj9: #e0ad6c;
  --chord-fadd9: #a95a48;
  --chord-dm11: #c98c4c;
  --chord-hue-from: 18;       /* unknown ids: an ember band, never sky-cyan at night */
  --chord-hue-span: 14;
  --chord-fallback-l: 46 52 58 64;
  --sec-intro: #6e5a48;
  --sec-drop-light: #a08462;
  --sec-drop-full: #cdb89f;
  --sec-break: #b86f55;
  --sec-stripped: #8a7560;
  --sec-transition: #d49a4f;
  --sec-outro: #47382c;
  --sec-unknown: #8a7560;
  --sec-drift: #8a6448;
  --sec-tide: #c98c4c;
  --sec-deep: #5e4230;
  --sec-glimmer: #e0ad6c;
  --sec-wind-down: #4a3629;
  --toast-ms: 1800;
}

/* ---------- base ---------- */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; height: 100%; background: var(--bg); }
body {
  color: var(--text-1);
  font: 400 var(--fs-body)/1.45 var(--font-sans);
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-x: clip;            /* clip, not hidden: hidden would turn body into a scroll container (stray scrollbar gutter) */
}
button, input { font: inherit; color: inherit; }
button { cursor: pointer; }
svg { display: block; }
kbd {
  display: inline-grid; place-items: center; min-width: 20px; height: 20px; padding: 0 5px;
  font: 500 10.5px/1 var(--font-mono); color: var(--text-2);
  background: var(--surface-2); border: 1px solid var(--line-2); border-radius: 5px;
  box-shadow: inset 0 -1px 0 rgba(255, 255, 255, 0.04);
}
.num, .mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.label {
  font: 500 var(--fs-label)/1.2 var(--font-mono); letter-spacing: var(--track-label);
  text-transform: uppercase; color: var(--text-3);
}
.sr-only {
  position: absolute !important; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
:focus { outline: none; }
:focus-visible { outline: 2px solid rgba(237, 237, 237, 0.85); outline-offset: 2px; border-radius: var(--r-1); }   /* white: amber is a state colour, never focus */
::selection { background: rgba(255, 161, 51, 0.3); }
[hidden] { display: none !important; }

/* ---------- app frame ---------- */
.app {
  position: relative;
  min-height: 100dvh;
  display: grid;
  grid-template-rows: var(--topbar-h) 1fr;
}
.stage {
  position: relative;
  display: grid;
  grid-template: 1fr / minmax(0, 1fr);
  min-width: 0;
  padding-bottom: var(--stage-pad-bottom);
}
.stage > .mode {
  grid-area: 1 / 1;
  min-width: 0;
  opacity: 1;
  transition: opacity var(--dur-mode) var(--ease-out);
}
.stage > .mode.mode--enter, .stage > .mode.mode--leave { opacity: 0; }
.stage > .mode.mode--leave { pointer-events: none; position: absolute; inset: 0; overflow: hidden; }   /* never grows the page mid-fade */

/* PLAY is full-bleed: the stage covers the viewport, the bar floats over it */
.app[data-mode='play'] .stage { position: fixed; inset: 0; padding: 0; z-index: var(--z-stage); }

/* ---------- top bar ---------- */
.topbar {
  position: sticky; top: 0; z-index: var(--z-chrome);
  display: flex; align-items: center; gap: 12px;
  height: var(--topbar-h); padding: 0 var(--gutter);
  background: rgba(0, 0, 0, 0.82);
  border-bottom: 1px solid var(--line-1);
}
/* backdrop-filter only where the transport inside the bar is NOT position:fixed (it would become its containing block) */
@supports (backdrop-filter: blur(1px)) {
  @media (min-width: 900px) {
    .app:not([data-mode='play']) .topbar { background: rgba(0, 0, 0, 0.66); backdrop-filter: blur(14px) saturate(140%); }
  }
}
/* PLAY: no backdrop-filter / transform on the bar — the transport inside it is position:fixed */
.app[data-mode='play'] .topbar {
  position: fixed; inset: 0 0 auto 0;
  background: transparent;
  border-bottom-color: transparent;
}
.app[data-mode='play'] .topbar::before {
  content: ''; position: absolute; inset: 0 0 auto 0; height: 120px; z-index: -1; pointer-events: none;
  background: linear-gradient(to bottom, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.22) 40%, rgba(0, 0, 0, 0.06) 75%, rgba(0, 0, 0, 0) 100%);
}

.brand {
  display: inline-flex; align-items: center; gap: 9px; height: 32px; padding: 0 4px 0 2px;
  color: var(--text-1); text-decoration: none; flex: none;
}
.brand-mark { width: 26px; height: 13px; }
.brand-mark path { fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linejoin: round; }
.brand-word { font: 600 15px/1 var(--font-sans); letter-spacing: -0.02em; }

/* segmented tabs */
.tabs {
  display: inline-flex; align-items: center; gap: 2px; padding: 3px; flex: none;
  background: rgba(10, 10, 10, 0.6); border: 1px solid var(--line-1); border-radius: var(--r-pill);
}
.mode-tab {
  position: relative; display: inline-flex; align-items: center; gap: 7px;
  height: 28px; padding: 0 13px; border: 0; border-radius: var(--r-pill); background: transparent;
  font: 500 11px/1 var(--font-mono); letter-spacing: 0.08em; color: var(--text-3);
  transition: color var(--dur-1) var(--ease-out), background-color var(--dur-1) var(--ease-out);
}
.mode-tab:hover { color: var(--text-1); }
.mode-tab[aria-selected='true'] { color: var(--text-1); background: var(--surface-3); box-shadow: var(--highlight), 0 0 0 1px var(--line-1); }
.mode-tab::before {
  content: ''; width: 4px; height: 4px; border-radius: 50%; background: currentColor; opacity: 0;
  transition: opacity var(--dur-1) var(--ease-out);
}
.mode-tab[aria-selected='true']::before { opacity: 1; background: var(--accent); box-shadow: 0 0 8px var(--accent-glow); }
.app[data-mode='play'] .tabs { position: absolute; left: 50%; transform: translateX(-50%); }

/* right cluster: tags, net dot, help */
.status { display: inline-flex; align-items: center; gap: 8px; flex: none; margin-left: auto; }
.tag {
  display: inline-flex; align-items: center; gap: 5px; height: 22px; padding: 0 8px;
  font: 500 10px/1 var(--font-mono); letter-spacing: var(--track-label); text-transform: uppercase;
  color: var(--text-3); border: 1px solid var(--line-1); border-radius: var(--r-pill); background: rgba(10, 10, 10, 0.5);
  white-space: nowrap;
}
.tag svg { width: 12px; height: 12px; }

/* sound source: a tiny two-state pill, SAMPLE (slices of the reference) | SYNTH (procedural) — every mode, key S.
   Selected = graphite chip; while the chosen source is not heard yet (it lands at the next bar the engine
   fetches) the chip is only outlined. Compact widths keep the selected half only (a toggle). */
.src-seg {
  display: inline-flex; align-items: center; gap: 2px; height: 22px; padding: 2px; flex: none;
  border: 1px solid var(--line-1); border-radius: var(--r-pill); background: rgba(10, 10, 10, 0.5);
}
.src-seg button {
  height: 16px; padding: 0 7px; border: 0; border-radius: var(--r-pill); background: transparent;
  font: 500 9.5px/1 var(--font-mono); letter-spacing: 0.06em; color: var(--text-3); white-space: nowrap;
  transition: color var(--dur-1) var(--ease-out), background-color var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out);
}
.src-seg button:hover:not(:disabled) { color: var(--text-1); }
.src-seg button[aria-pressed='true'] { color: var(--text-1); background: var(--surface-3); box-shadow: var(--highlight), 0 0 0 1px var(--line-1); }
.src-seg[data-armed='true'] button[aria-pressed='true'] { color: var(--text-2); background: transparent; box-shadow: inset 0 0 0 1px var(--line-3); }
.src-seg button:disabled { cursor: default; color: var(--text-4); }
.src-seg[aria-disabled='true'] button { color: var(--text-4); }
.net-dot {
  width: 7px; height: 7px; border-radius: 50%; background: var(--text-4); flex: none;
  transition: background-color var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out);
}
.net-dot[data-state='ok'] { background: var(--ok); box-shadow: 0 0 8px rgba(69, 212, 131, 0.45); }
.net-dot[data-state='buffering'], .net-dot[data-state='connecting'] { background: var(--accent); box-shadow: 0 0 8px var(--accent-glow); animation: pulse-dot 1.2s var(--ease-in-out) infinite; }
.net-dot[data-state='reconnecting'] { background: var(--bad); animation: pulse-dot 1.2s var(--ease-in-out) infinite; }
@keyframes pulse-dot { 50% { opacity: 0.35; } }
@media (prefers-reduced-motion: reduce) { .net-dot { animation: none !important; } }

.icon-btn {
  display: inline-grid; place-items: center; width: 32px; height: 32px; padding: 0;
  border: 1px solid var(--line-1); border-radius: var(--r-pill); background: rgba(10, 10, 10, 0.5);
  color: var(--text-2); font: 500 12px/1 var(--font-mono);
  transition: color var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out), background-color var(--dur-1) var(--ease-out);
}
.icon-btn:hover { color: var(--text-1); border-color: var(--line-3); background: var(--surface-2); }

/* ---------- transport ---------- */
.transport { display: flex; align-items: center; gap: 2px; flex: none; transition: opacity var(--dur-3) var(--ease-out); }
.tb {
  position: relative; display: inline-grid; place-items: center;
  width: 36px; height: 36px; padding: 0; border: 0; border-radius: var(--r-pill);
  background: transparent; color: var(--text-2);
  transition: color var(--dur-1) var(--ease-out), background-color var(--dur-1) var(--ease-out), transform var(--dur-1) var(--ease-out);
}
.tb svg { width: 18px; height: 18px; }
.tb:hover { color: var(--text-1); background: rgba(255, 255, 255, 0.06); }
.tb:active { transform: scale(0.94); }
.tb[aria-disabled='true'] { opacity: 0.32; cursor: default; }
.tb[aria-disabled='true']:hover { background: transparent; color: var(--text-2); }

.tb-play { width: 40px; height: 40px; background: var(--text-1); color: #000; margin: 0 4px; box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.1), 0 6px 24px -8px rgba(255, 255, 255, 0.35); }
.tb-play:hover { background: #fff; color: #000; }
.tb-play svg { width: 16px; height: 16px; }
.tb-play .i-pause { display: none; }
.app[data-wanted='true'] .tb-play .i-play { display: none; }
.app[data-wanted='true'] .tb-play .i-pause { display: block; }
.app[data-buffering='true'] .tb-play::after {
  content: ''; position: absolute; inset: -3px; border-radius: 50%;
  border: 1.5px solid transparent; border-top-color: var(--accent);
  animation: spin 0.9s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .app[data-buffering='true'] .tb-play::after { animation: none; border-color: var(--accent-lo); } }

.tb-like .i-heart-fill { display: none; }
.tb-like[aria-pressed='true'] { color: var(--accent); }
.tb-like[aria-pressed='true'] .i-heart { display: none; }
.tb-like[aria-pressed='true'] .i-heart-fill { display: block; filter: drop-shadow(0 0 6px var(--accent-glow)); }
.tb.pop { animation: pop 420ms var(--ease-out); }
.tb.kick { animation: nudge 360ms var(--ease-out); }
@keyframes pop { 30% { transform: scale(1.22); } 100% { transform: scale(1); } }
@keyframes nudge { 30% { transform: translateX(3px); } 100% { transform: translateX(0); } }

.tsep { width: 1px; height: 18px; background: var(--line-2); margin: 0 6px; flex: none; }

/* volume */
.vol { display: inline-flex; align-items: center; gap: 2px; }
.tb-mute .i-vol-off { display: none; }
.tb-mute[aria-pressed='true'] { color: var(--text-3); }
.tb-mute[aria-pressed='true'] .i-vol-on { display: none; }
.tb-mute[aria-pressed='true'] .i-vol-off { display: block; }

/* thin range slider (volume, energy) */
.range {
  --p: 50%;
  -webkit-appearance: none; appearance: none; width: 72px; height: 24px; margin: 0; padding: 0;
  background: transparent; cursor: pointer;
}
.range::-webkit-slider-runnable-track {
  height: 2px; border-radius: 2px;
  background: linear-gradient(to right, var(--text-2) var(--p), var(--line-3) var(--p));
}
.range::-moz-range-track { height: 2px; border-radius: 2px; background: var(--line-3); }
.range::-moz-range-progress { height: 2px; border-radius: 2px; background: var(--text-2); }
.range::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; width: 10px; height: 10px; margin-top: -4px; border-radius: 50%;
  background: var(--text-1); border: 0; box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.6);
  transition: transform var(--dur-1) var(--ease-out);
}
.range::-moz-range-thumb { width: 10px; height: 10px; border-radius: 50%; background: var(--text-1); border: 0; }
.range:hover::-webkit-slider-thumb, .range:focus-visible::-webkit-slider-thumb { transform: scale(1.25); }
.range:focus-visible { outline-offset: 0; }
.vol .range[data-muted='true']::-webkit-slider-runnable-track { background: var(--line-3); }

/* energy control */
.energy { display: inline-flex; align-items: center; gap: 8px; padding: 0 4px 0 6px; }
.energy-label { font: 500 10px/1 var(--font-mono); letter-spacing: 0.08em; color: var(--text-3); }
.energy-track { position: relative; display: inline-flex; align-items: center; }
.energy-track .range { width: 84px; }
.energy-level {
  position: absolute; left: 0; top: 50%; height: 2px; margin-top: -1px; width: var(--lvl, 0%); border-radius: 2px;
  background: rgba(255, 255, 255, 0.55); pointer-events: none;
  transition: width 300ms var(--ease-out);
}
.energy-track::before { content: ''; position: absolute; left: 0; right: 0; top: 50%; height: 2px; margin-top: -1px; border-radius: 2px; background: var(--line-3); pointer-events: none; }
.energy .range { position: relative; z-index: 1; }
.energy .range::-webkit-slider-runnable-track { background: transparent; }
.energy .range::-moz-range-track, .energy .range::-moz-range-progress { background: transparent; }
.energy[data-auto='true'] .range::-webkit-slider-thumb { background: var(--text-3); box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.6); }
.energy[data-auto='true'] .range::-moz-range-thumb { background: var(--text-3); }
.chip-auto {
  height: 22px; padding: 0 8px; border-radius: var(--r-pill);
  font: 500 10px/1 var(--font-mono); letter-spacing: 0.08em;
  color: var(--text-3); background: transparent; border: 1px solid var(--line-2);
  transition: color var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out), background-color var(--dur-1) var(--ease-out);
}
.chip-auto:hover { color: var(--text-1); border-color: var(--line-3); }
.chip-auto[aria-pressed='true'] { color: var(--accent); border-color: rgba(255, 161, 51, 0.35); background: rgba(255, 161, 51, 0.08); }
.energy-val { font: 500 10.5px/1 var(--font-mono); color: var(--text-2); min-width: 2ch; text-align: right; }

/* PLAY: the transport is a floating glass pill */
.app[data-mode='play'] .transport {
  position: fixed; left: 50%; bottom: max(22px, env(safe-area-inset-bottom));
  transform: translateX(-50%);
  z-index: var(--z-chrome);
  padding: 5px 6px; gap: 2px;
  background: rgba(12, 12, 12, 0.55);
  border: 1px solid var(--line-2);
  border-radius: var(--r-pill);
  box-shadow: var(--highlight), 0 24px 60px -24px rgba(0, 0, 0, 0.9);
}
@supports (backdrop-filter: blur(1px)) {
  .app[data-mode='play'] .transport { background: rgba(14, 14, 14, 0.42); backdrop-filter: blur(22px) saturate(150%); }
}
.app[data-mode='play'] .tb { width: 40px; height: 40px; }
.app[data-mode='play'] .tb-play { width: 46px; height: 46px; }
.app[data-mode='play'] .tb-play svg { width: 18px; height: 18px; }
.app[data-started='false'] .transport { opacity: 0; pointer-events: none; }

/* ---------- connection pill ---------- */
.netstate {
  position: fixed; left: 50%; top: calc(var(--topbar-h) + 10px); transform: translateX(-50%);
  z-index: var(--z-overlay);
  display: inline-flex; align-items: center; gap: 8px; height: 26px; padding: 0 12px 0 10px;
  font: 500 10.5px/1 var(--font-mono); letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-2);
  background: rgba(12, 12, 12, 0.8); border: 1px solid var(--line-2); border-radius: var(--r-pill);
  box-shadow: var(--highlight);
  animation: fade-in var(--dur-3) var(--ease-out);
  white-space: nowrap;
}
.netstate i { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 8px var(--accent-glow); animation: pulse-dot 1.2s var(--ease-in-out) infinite; }
.netstate[data-state='reconnecting'] i { background: var(--bad); box-shadow: 0 0 8px rgba(255, 92, 92, 0.5); }
@keyframes fade-in { from { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .netstate, .netstate i { animation: none; } }

/* ---------- toasts ---------- */
.toasts {
  position: fixed; left: 50%; bottom: 96px; transform: translateX(-50%);
  z-index: var(--z-toast);
  display: flex; flex-direction: column; align-items: center; gap: 6px; pointer-events: none;
  width: max-content; max-width: calc(100vw - 32px);
}
.app:not([data-mode='play']) ~ .toasts { bottom: calc(24px + var(--stage-pad-bottom)); }
/* PLAY: system messages drop from under the bar (where the netstate pill lives), so they never meet the
   section caption / status line at the bottom; pushed down while the netstate pill shows */
.app[data-mode='play'] ~ .toasts { top: calc(var(--topbar-h) + 10px); bottom: auto; }
.app[data-mode='play'] ~ .netstate:not([hidden]) ~ .toasts { top: calc(var(--topbar-h) + 44px); }
.app[data-mode='play'] ~ .toasts .toast { animation-name: toast-in-top; }
.app[data-mode='play'] ~ .toasts .toast.toast--out { transform: translateY(-4px); }
@keyframes toast-in-top { from { opacity: 0; transform: translateY(-6px); } }
.toast {
  display: inline-flex; align-items: center; gap: 8px; height: 30px; padding: 0 13px 0 11px; max-width: 100%;
  font: 500 11px/1 var(--font-mono); letter-spacing: 0.04em; color: var(--text-1);
  background: rgba(14, 14, 14, 0.9); border: 1px solid var(--line-2); border-radius: var(--r-pill);
  box-shadow: var(--highlight), 0 12px 32px -12px rgba(0, 0, 0, 0.9);
  animation: toast-in var(--dur-2) var(--ease-out);
  transition: opacity var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.toast-text { overflow: hidden; text-overflow: ellipsis; }
.toast-glyph { display: inline-grid; place-items: center; width: 12px; height: 12px; color: var(--text-3); flex: none; }
.toast-glyph svg { width: 12px; height: 12px; }
.toast[data-kind='like'] .toast-glyph { color: var(--accent); }
.toast[data-kind='error'] .toast-glyph { color: var(--bad); }
.toast.toast--out { opacity: 0; transform: translateY(4px); }
@keyframes toast-in { from { opacity: 0; transform: translateY(6px); } }

/* ---------- start overlay ---------- */
.start {
  position: fixed; inset: 0; z-index: var(--z-start);
  display: grid; place-items: center; padding: 24px var(--gutter);
  background: radial-gradient(ellipse 70% 60% at 50% 50%, rgba(0, 0, 0, 0.1) 0%, rgba(0, 0, 0, 0.45) 60%, rgba(0, 0, 0, 0.85) 100%);
  transition: opacity 700ms var(--ease-out), visibility 0s linear 700ms;
}
.app:not([data-mode='play']) ~ .start { background: rgba(0, 0, 0, 0.94); }
.start[data-state='gone'] { opacity: 0; visibility: hidden; pointer-events: none; }
.start-inner { position: relative; isolation: isolate; display: flex; flex-direction: column; align-items: center; text-align: center; }
.start-inner::before {                       /* soft scrim: the text never sits on the brightest dots of the orb */
  content: ''; position: absolute; z-index: -1; left: 50%; top: 50%; width: 560px; height: 420px; max-width: 150vw;
  transform: translate(-50%, -50%); pointer-events: none;
  background: radial-gradient(closest-side, rgba(0, 0, 0, 0.62), rgba(0, 0, 0, 0.35) 55%, rgba(0, 0, 0, 0));
}
.start-mark { width: 64px; height: 32px; color: var(--text-1); margin-bottom: 22px; }
.start-mark path { fill: none; stroke: currentColor; stroke-width: 1.1; stroke-linejoin: round; }
.start-title { margin: 0; font: 500 44px/1 var(--font-sans); letter-spacing: -0.045em; color: var(--text-1); }
.start-sub { margin: 14px 0 0; font: 500 11px/1 var(--font-mono); letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-2); }
.start-sub span + span::before { content: '·'; margin: 0 10px; color: var(--text-4); }
.start-btn {
  margin-top: 34px; display: inline-flex; align-items: center; gap: 10px; height: 44px; padding: 0 16px 0 18px;
  border: 0; border-radius: var(--r-pill); background: var(--text-1); color: #000;
  font: 500 14px/1 var(--font-sans); letter-spacing: -0.01em;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.12), 0 10px 40px -10px rgba(255, 255, 255, 0.4);
  transition: transform var(--dur-1) var(--ease-out), background-color var(--dur-1) var(--ease-out);
}
.start-btn:hover { background: #fff; }
.start-btn:active { transform: scale(0.97); }
.start-btn:disabled { opacity: 0.6; cursor: progress; }
.start-btn svg { width: 13px; height: 13px; }
.start-btn kbd { background: rgba(0, 0, 0, 0.07); border-color: rgba(0, 0, 0, 0.12); color: rgba(0, 0, 0, 0.5); box-shadow: none; margin-left: 2px; }
.start-tags { display: flex; gap: 6px; justify-content: center; margin-top: 22px; min-height: 22px; }
.start-error { margin: 16px 0 0; max-width: 46ch; font: 500 11.5px/1.5 var(--font-mono); color: var(--bad); }

/* ---------- help ---------- */
.help {
  width: min(360px, calc(100vw - 32px)); padding: 16px 18px 12px; margin: auto;
  color: var(--text-1); background: rgba(12, 12, 12, 0.96);
  border: 1px solid var(--line-2); border-radius: var(--r-3);
  box-shadow: var(--highlight), 0 30px 80px -20px rgba(0, 0, 0, 0.95);
}
.help::backdrop { background: rgba(0, 0, 0, 0.55); }
.help[open] { animation: help-in var(--dur-2) var(--ease-out); }
@keyframes help-in { from { opacity: 0; transform: translateY(6px) scale(0.98); } }
.help-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.help h2 { margin: 0; font: 500 var(--fs-label)/1 var(--font-mono); letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-3); }
.help dl { display: grid; grid-template-columns: auto 1fr; margin: 0; }
.help dt, .help dd { margin: 0; padding: 7px 0; border-top: 1px solid var(--line-1); display: flex; align-items: center; }
.help dt { gap: 4px; padding-right: 18px; }
.help dd { color: var(--text-2); font-size: 12.5px; }
.help-close { width: 26px; height: 26px; font-size: 14px; }

/* ---------- shared components (api.ui) ---------- */
.sec-chip { display: inline-flex; align-items: center; gap: 7px; font: 500 11px/1 var(--font-mono); letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-1); white-space: nowrap; }
.sec-chip::before { content: ''; width: 7px; height: 7px; border-radius: 2px; background: var(--k, var(--sec-unknown)); flex: none; }
.sec-pos { color: var(--text-3); }

.glyph rect.g-cell { fill: rgba(255, 255, 255, 0.06); }
.glyph rect.g-beat { fill: rgba(255, 255, 255, 0.14); }
.glyph rect.g-odd { stroke: #fff; stroke-width: 1; stroke-dasharray: 2 1; }

.gauge { display: grid; gap: 6px; min-width: 0; }
.gauge-head { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.gauge-label { font: 500 var(--fs-label)/1 var(--font-mono); letter-spacing: var(--track-label); text-transform: uppercase; color: var(--text-3); }
.gauge-value { font: 500 12px/1 var(--font-mono); color: var(--text-1); }
.gauge[data-out='true'] .gauge-value { color: var(--warn); }
.gauge-track { position: relative; height: 4px; border-radius: 2px; background: var(--surface-3); }
.gauge-band { position: absolute; top: 0; bottom: 0; background: rgba(255, 255, 255, 0.07); }
.gauge-fill { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 2px; background: var(--text-1); transition: width 300ms var(--ease-out); }
.gauge-edges { position: absolute; top: -3px; bottom: -3px; border-left: 1px solid var(--text-3); border-right: 1px solid var(--text-3); pointer-events: none; }
.gauge-hint { font-size: 11px; color: var(--text-3); }

.spark { width: 100%; overflow: visible; }
.spark .s-band { fill: rgba(255, 255, 255, 0.04); }
.spark .s-edge { stroke: var(--line-3); stroke-dasharray: 2 3; stroke-width: 1; vector-effect: non-scaling-stroke; }
.spark .s-area { fill: rgba(255, 255, 255, 0.05); }
.spark .s-line { fill: none; stroke: var(--text-1); stroke-width: 1.25; vector-effect: non-scaling-stroke; }
.spark .s-dot { fill: var(--accent); }

/* ---------- PLAY ---------- */
.play { position: relative; width: 100%; height: 100dvh; overflow: hidden; background: #000; isolation: isolate; }
.play-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }

.play-hud {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  height: 92px; padding: 0 22px env(safe-area-inset-bottom);
  pointer-events: none;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
}
.play-hud { transition: opacity var(--dur-3) var(--ease-out); }
.app[data-started='false'] .play-hud { opacity: 0; }
.play-status, .play-meta {
  display: inline-flex; align-items: center; min-width: 0; overflow: hidden;
  font: 500 10.5px/1 var(--font-mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-3);
  white-space: nowrap;
}
.play-status > span + span::before, .play-meta > span + span::before { content: '·'; margin: 0 9px; color: var(--text-4); }
.play-status .hi { color: var(--text-2); }
.play-status { pointer-events: auto; cursor: default; }     /* hover → seed tooltip */
.live-dot {
  display: inline-block; width: 5px; height: 5px; border-radius: 50%; background: var(--accent);
  margin-right: 9px; box-shadow: 0 0 6px var(--accent-glow); opacity: 0.25; transition: opacity 180ms linear; flex: none;
}
.play[data-playing='true'] .live-dot { opacity: 1; }

.play-caption {
  position: absolute; left: 50%; bottom: 132px; z-index: 2;
  display: flex; flex-direction: column; align-items: center; gap: 9px; pointer-events: none;
  opacity: 0; transform: translate(-50%, 6px);
  transition: opacity 900ms var(--ease-out), transform 900ms var(--ease-out);
}
.play-caption[data-show='true'] { opacity: 1; transform: translate(-50%, 0); }
.cap-kicker { font: 500 10px/1 var(--font-mono); letter-spacing: 0.2em; color: var(--text-2); text-transform: uppercase; }
.cap-name { font: 300 28px/1 var(--font-sans); letter-spacing: -0.025em; color: var(--text-1); text-shadow: 0 0 30px rgba(0, 0, 0, 0.8); white-space: nowrap; }

/* ---------- DSP / STUDIO placeholders ---------- */
.ph {
  min-height: calc(100dvh - var(--topbar-h) - var(--stage-pad-bottom));
  display: grid; grid-template-rows: auto 1fr auto;
  padding: 14px var(--gutter) 16px;
}
.ph-head { display: flex; align-items: center; justify-content: space-between; gap: 12px 24px; padding-bottom: 12px; border-bottom: 1px solid var(--line-1); flex-wrap: wrap; }
.ph-title { display: flex; align-items: center; gap: 12px; }
.ph-title h1 { margin: 0; font: 500 12px/1 var(--font-mono); letter-spacing: 0.14em; color: var(--text-1); }
.ph-readouts { display: flex; flex-wrap: wrap; row-gap: 10px; }
.ph-ro { display: grid; gap: 6px; padding: 0 16px; border-left: 1px solid var(--line-1); min-width: 64px; }
.ph-ro:first-child { border-left: 0; padding-left: 0; }
.ph-ro b { font: 500 15px/1 var(--font-mono); color: var(--text-1); letter-spacing: -0.01em; font-weight: 500; }
.ph-body { position: relative; min-height: 240px; margin-top: 12px; border: 1px solid var(--line-1); border-radius: var(--r-2); background: var(--bg-1); overflow: hidden; }
.ph-body canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.ph-foot { display: flex; justify-content: space-between; gap: 12px; padding-top: 10px; flex-wrap: wrap; }

/* ---------- responsive ---------- */
/* DSP / STUDIO: transport in the bar on wide screens, docked at the bottom below 900 px */
@media (max-width: 899px) {
  .app:not([data-mode='play']) { --dock-h: 72px; --stage-pad-bottom: 72px; }
  .app:not([data-mode='play']) ~ .toasts { bottom: 96px; }
  .app:not([data-mode='play']) .transport {
    position: fixed; left: 50%; bottom: max(12px, env(safe-area-inset-bottom)); transform: translateX(-50%);
    z-index: var(--z-chrome); padding: 5px 6px;
    background: rgba(14, 14, 14, 0.92); border: 1px solid var(--line-2); border-radius: var(--r-pill);
    box-shadow: var(--highlight), 0 20px 50px -20px rgba(0, 0, 0, 0.9);
  }
}
@media (max-width: 1100px) {
  .vol .range { display: none; }
}
/* DSP / STUDIO keep the transport in the bar from 900 px: there the dev tags give way (no horizontal scroll) */
@media (min-width: 900px) and (max-width: 1024px) {
  .app:not([data-mode='play']) .tag-dev { display: none; }
  .app:not([data-mode='play']) .brand-word { display: none; }
  .app:not([data-mode='play']) .tag-silent span { display: none; }
}
/* PLAY centres the tabs over the bar: up to 1024 px the dev tags collapse (DEV hidden, SILENT as its icon) and the
   source pill keeps its selected half, so the right cluster never slides under the tabs (layout probe:
   __infisound.topbarCheck()) */
@media (max-width: 1024px) {
  .app[data-mode='play'] .tag-dev { display: none; }
  .app[data-mode='play'] .tag-silent span { display: none; }
  .app[data-mode='play'] .status:has(.tag:not([hidden])) .src-seg button[aria-pressed='false'] { display: none; }
  .app[data-mode='play'] .status:has(.tag:not([hidden])) .src-seg[aria-disabled='true'] { display: none; }
}
/* … and the source pill keeps only its selected half (a toggle) up to 1180 px */
@media (min-width: 900px) and (max-width: 1180px) {
  .app:not([data-mode='play']) .src-seg button[aria-pressed='false'] { display: none; }
  .app:not([data-mode='play']) .src-seg[aria-disabled='true'] { display: none; }   /* no selected half to show */
}
@media (max-width: 1180px) {
  /* not enough room beside the pill: the status line sits centred above it, on a soft bottom scrim */
  .play-hud { height: auto; padding: 0 16px; bottom: 92px; background: none; justify-content: center; }
  .play::after {
    content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 170px; z-index: 1; pointer-events: none;
    background: linear-gradient(to top, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.3) 45%, rgba(0, 0, 0, 0));
  }
  .play-meta { display: none; }
  .play-caption { bottom: 142px; }
}
@media (max-width: 760px) {
  .brand-word { display: none; }
  .src-seg button[aria-pressed='false'] { display: none; }     /* the source pill becomes a toggle */
  .src-seg[aria-disabled='true'] { display: none; }             /* … with nothing selected (no source info): hidden */
  .tag-silent span { display: none; }
}
@media (max-width: 600px) {
  :root { --topbar-h: 48px; --gutter: 12px; }
  .energy-label, .energy-val { display: none; }
  .energy-track .range { width: 64px; }
  .tag-dev { display: none; }
  .mode-tab { padding: 0 10px; letter-spacing: 0.06em; }
  .app[data-mode='play'] .tabs { position: static; transform: none; margin: 0 auto; }
  .start-title { font-size: 36px; }
  .ph-ro { padding: 0 10px; min-width: 0; }
}
@media (max-width: 420px) {
  .app[data-mode='play'] .tb { width: 38px; height: 38px; }
  .tsep { margin: 0 2px; }
  .energy { padding: 0 2px; gap: 4px; }
  .energy-track .range { width: 52px; }
  .tag-silent span { display: none; }
}
/* phones: the bar holds brand · tabs · source toggle · silent · dot · ? without horizontal scroll (375: 0 px spare) */
@media (max-width: 480px) {
  .topbar { gap: 8px; }
  .status { gap: 6px; }
  .mode-tab { padding: 0 7px; }
  .tag-silent { padding: 0; border: 0; background: none; }
  .src-seg { padding: 0; border: 0; background: none; }
}
@media (pointer: coarse) {
  .tb, .app[data-mode='play'] .tb { min-width: 44px; min-height: 44px; }
  .mode-tab { height: 34px; }
  .src-seg { height: auto; }
  .src-seg button { height: 30px; min-width: 44px; }
}
@media (prefers-reduced-motion: reduce) {
  .play-caption, .start, .transport, .toast { transition: none; animation: none; }
}

/* ============================================================================
   DSP (ui v5) — the audio laboratory. One instrument surface: panels share
   hairlines (1px gaps over --line-1), no cards, no prose. Canvases fill their
   .dsp-cvbox; numbers are DOM (mono, tabular). modes/dsp.js + dsp/*.js
   ========================================================================== */
.dsp {
  min-height: calc(100dvh - var(--topbar-h) - var(--stage-pad-bottom));
  display: grid; grid-template-rows: auto minmax(0, 1fr); gap: 10px;
  padding: 10px var(--gutter) 14px;
}

/* readout strip */
.dsp-strip { display: flex; flex-wrap: wrap; align-items: center; row-gap: 10px; min-width: 0; padding-top: 2px; }
.dsp-ro { display: grid; gap: 6px; padding: 0 16px; border-left: 1px solid var(--line-1); min-width: 0; }
.dsp-ro:first-child { padding-left: 2px; border-left: 0; }
.dsp-ro b {
  display: inline-flex; align-items: center; gap: 7px; min-height: 15px;
  font: 500 15px/1 var(--font-mono); color: var(--text-1); letter-spacing: -0.01em; white-space: nowrap;
}
.dsp-ro-live { margin-left: auto; }
.dsp-dim { color: var(--text-3); font-size: 12px; margin-left: -3px; }
.dsp-sw { width: 8px; height: 8px; border-radius: 2px; background: var(--text-4); flex: none; }
.dsp-sw-ch[data-odd='true'] { outline: 1px dashed rgba(255, 255, 255, 0.9); outline-offset: 1px; }
.dsp-live { width: 6px; height: 6px; border-radius: 50%; background: var(--text-4); flex: none; transition: background-color var(--dur-2) var(--ease-out); }
.dsp-live[data-on='true'] { background: var(--accent); box-shadow: 0 0 8px var(--accent-glow); }

/* the surface */
.dsp-grid {
  display: grid; gap: 1px; min-height: 0; min-width: 0;
  background: var(--line-1); border: 1px solid var(--line-1); border-radius: var(--r-2); overflow: hidden;
  grid-template-columns: minmax(0, 1fr) minmax(220px, 300px) minmax(300px, 344px);
  grid-template-rows: auto minmax(236px, 1fr) clamp(208px, 24vh, 300px);
  grid-template-areas: 'hero hero loud' 'hero hero scope' 'spec low eng';
}
.dsp-p { position: relative; display: flex; flex-direction: column; min-width: 0; min-height: 0; background: var(--bg-1); }
.dsp-hero { grid-area: hero; }
.dsp-loud { grid-area: loud; }
.dsp-scope { grid-area: scope; }
.dsp-spec { grid-area: spec; }
.dsp-low { grid-area: low; }
.dsp-eng { grid-area: eng; }

.dsp-ph { display: flex; align-items: center; gap: 10px; height: 32px; padding: 0 12px; flex: none; min-width: 0; }
.dsp-ph h2 { margin: 0; color: var(--text-2); white-space: nowrap; }
.dsp-ph h2[title] { cursor: help; }
.dsp-fill { flex: 1 1 auto; }
.dsp-cbar { display: inline-block; flex: none; width: 56px; height: 4px; border-radius: 2px; box-shadow: 0 0 0 1px var(--line-1); }
.dsp-tag { font: 500 10px/1 var(--font-mono); letter-spacing: 0.06em; color: var(--warn); white-space: nowrap; }

.dsp-btn {
  height: 22px; padding: 0 9px; flex: none;
  border: 1px solid var(--line-2); border-radius: var(--r-pill); background: transparent;
  font: 500 10px/1 var(--font-mono); letter-spacing: 0.08em; color: var(--text-3);
  transition: color var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out);
}
.dsp-btn:hover { color: var(--text-1); border-color: var(--line-3); }
.dsp-seg { display: inline-flex; align-items: center; gap: 2px; padding: 2px; flex: none; border: 1px solid var(--line-1); border-radius: var(--r-pill); }
.dsp-seg button {
  min-width: 24px; height: 20px; padding: 0 6px; border: 0; border-radius: var(--r-pill); background: transparent;
  font: 500 10.5px/1 var(--font-mono); color: var(--text-3);
  transition: color var(--dur-1) var(--ease-out), background-color var(--dur-1) var(--ease-out);
}
.dsp-seg button:hover { color: var(--text-1); }
.dsp-seg button[aria-pressed='true'] { color: var(--text-1); background: var(--surface-3); box-shadow: var(--highlight), 0 0 0 1px var(--line-1); }
.dsp-seg .label { padding: 0 6px 0 3px; font-size: 9.5px; }

.dsp-cvbox { position: relative; flex: 1 1 auto; min-height: 0; }
.dsp-cvbox canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.dsp-cvbox-hero { min-height: 260px; }
.dsp-cvbox-hero canvas[data-c='heroS'] { pointer-events: none; }
.dsp-cvbox-hero canvas[data-c='hero'], .dsp-spec canvas { cursor: crosshair; }
.dsp-cvbox-loud { flex: 0 0 132px; margin: 0 12px; }
.dsp-cvbox-scope { min-height: 150px; }
.dsp-cvbox-corr { flex: 0 0 24px; margin: 0 10px; }

.dsp-big { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); padding: 2px 12px 10px; flex: none; }
.dsp-big > div { display: grid; gap: 6px; padding-left: 10px; border-left: 1px solid var(--line-1); min-width: 0; }
.dsp-big > div:first-child { padding-left: 0; border-left: 0; }
.dsp-big b { font: 500 20px/1 var(--font-mono); color: var(--text-1); letter-spacing: -0.02em; white-space: nowrap; }
.dsp-foot { display: flex; align-items: center; gap: 16px; height: 30px; padding: 0 12px; flex: none; min-width: 0; overflow: hidden; }
.dsp-foot > span { display: inline-flex; align-items: baseline; gap: 6px; white-space: nowrap; }
.dsp-foot b, .dsp-hr b { font: 500 12px/1 var(--font-mono); color: var(--text-1); }
.dsp-foot b[data-over='true'], .dsp-foot b[data-neg='true'] { color: var(--bad); }
.dsp-hr { display: inline-flex; align-items: baseline; gap: 6px; white-space: nowrap; }
.dsp-note { display: inline-flex; align-items: baseline; gap: 8px; font: 500 11px/1 var(--font-mono); color: var(--text-2); white-space: nowrap; }
.dsp-note b { font: 500 18px/1 var(--font-mono); color: var(--text-1); letter-spacing: -0.01em; }
.dsp-note [data-v='GRIT'] { color: var(--bad); }             /* SLEEP · SUB PURITY: the sub has grit (H3 > −40 dB) */

.dsp-eng-grid { flex: 1 1 auto; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); align-content: start; column-gap: 16px; padding: 0 12px 8px; min-height: 0; }
.dsp-cell { display: grid; grid-template-columns: minmax(0, 1fr); align-content: start; row-gap: 5px; padding: 8px 0 7px; border-top: 1px solid var(--line-1); min-width: 0; }
.dsp-cell b { display: block; font: 500 13px/1.1 var(--font-mono); color: var(--text-1); letter-spacing: -0.01em; white-space: nowrap; overflow: hidden; min-width: 0; }
.dsp-cell .dsp-dim { margin-left: 0; font-size: 11px; }
.dsp-cell [data-bad='true'] { color: var(--bad); }
.dsp-gauge { position: relative; display: block; height: 3px; margin-top: 3px; border-radius: 2px; background: var(--line-1); }
.dsp-gauge > i { position: absolute; top: 0; bottom: 0; left: 0; display: block; }
.dsp-gauge > i[data-r='bufBar'] { width: 0; border-radius: 2px; background: rgba(237, 237, 237, 0.7); transition: width var(--dur-2) var(--ease-out); }
.dsp-gauge > i[data-r='bufTick'] { top: -3px; bottom: -3px; width: 1px; background: var(--text-2); }
.dsp-spark { display: block; width: 100%; height: 16px; opacity: 0.8; }
.dsp-spark svg { display: block; width: 100%; height: 16px; }

/* second monitor: the side column and the bottom row grow with the screen, numbers readable across a room */
@media (min-width: 1600px) {
  .dsp-grid {
    grid-template-columns: minmax(0, 1fr) minmax(240px, 18vw) minmax(320px, 22vw);
    grid-template-rows: auto minmax(236px, 1fr) clamp(200px, 24vh, 300px);
  }
  .dsp-big b { font-size: clamp(20px, 1.4vw, 28px); }
  .dsp-cvbox-loud { flex-basis: clamp(132px, 15vh, 200px); }
  .dsp-cell b { font-size: 14px; }
}
@media (max-width: 1320px) {
  .dsp-grid { grid-template-columns: minmax(0, 1fr) minmax(200px, 250px) minmax(290px, 316px); }
}
@media (max-width: 1180px) {
  .dsp-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-template-rows: minmax(360px, 58vh) auto 220px 210px;
    grid-template-areas: 'hero hero' 'loud scope' 'spec spec' 'low eng';
  }
  .dsp-cvbox-scope { min-height: 170px; }
  .dsp-ro-live { margin-left: 0; }
}
@media (max-width: 899px) {
  .dsp-ro-live { display: none; }                  /* the top bar's net dot carries the state here */
  .dsp-ro { padding: 0 13px; }
}
@media (max-width: 760px) {
  .dsp-ro { padding: 0 12px; }
  .dsp-ro b { font-size: 14px; }
}
@media (max-width: 640px) {
  .dsp-grid {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: none; grid-auto-rows: auto;
    grid-template-areas: 'hero' 'loud' 'scope' 'spec' 'low' 'eng';
  }
  .dsp-cvbox-hero { min-height: 300px; }
  .dsp-cvbox-scope { min-height: 240px; }
  .dsp-spec .dsp-cvbox, .dsp-low .dsp-cvbox { min-height: 160px; }
  .dsp-hero .dsp-ph h2, .dsp-cbar { display: none; }
  .dsp-big b { font-size: 17px; }
  .dsp-ro { padding: 0 10px; }
  .dsp-ro b { font-size: 13px; }
  .dsp-dim { font-size: 11px; }
}
@media (pointer: coarse) {
  .dsp-btn, .dsp-seg button { min-height: 44px; min-width: 44px; }
  .dsp-ph { height: auto; min-height: 48px; }
}

/* ============================================================================
   STUDIO (ui v5) — the self-writing DAW. A readout strip over one timeline
   canvas on a hairline surface (no cards). Canvas: modes/studio.js +
   studio/timeline.js. Prefix .stu-.
   ========================================================================== */
.stu {
  height: calc(100dvh - var(--topbar-h) - var(--stage-pad-bottom));
  min-height: 420px;
  display: grid; grid-template-rows: auto minmax(0, 1fr); gap: 10px;
  padding: 10px var(--gutter) 14px;
  min-width: 0;
}
/* one line from 800 px whatever the readouts say, so the canvas height never jumps: the theme glyph is the one
   thing that gives way (it narrows, down to 40 px); below 800 px two fixed rows (a forced break after THEME) */
.stu-strip { display: flex; flex-wrap: nowrap; align-items: center; row-gap: 10px; min-width: 0; padding-top: 2px; }
.stu-ro { display: grid; gap: 6px; padding: 0 16px; border-left: 1px solid var(--line-1); min-width: 0; flex: none; }
.stu-ro-theme { flex: 0 1 auto; grid-template-columns: minmax(0, 1fr); }
.stu-ro-theme b { display: flex; min-width: 0; }
.stu-br { display: none; }
.stu-ro:first-child { padding-left: 2px; border-left: 0; }
.stu-ro[title] { cursor: default; }
.stu-ro b {
  display: inline-flex; align-items: center; gap: 7px; min-height: 15px;
  font: 500 15px/1 var(--font-mono); color: var(--text-1); letter-spacing: -0.01em; white-space: nowrap;
}
.stu-ro [data-r='pos'] { display: inline-block; min-width: 4.5ch; }
.stu-dim { color: var(--text-3); font-size: 12px; margin-left: -3px; }
.stu-sw { width: 8px; height: 8px; border-radius: 2px; background: var(--text-4); flex: none; }
.stu-sw-ch[data-odd='true'] { outline: 1px dashed rgba(255, 255, 255, 0.9); outline-offset: 1px; }
.stu-glyph { display: flex; align-items: center; flex: 0 1 auto; min-width: 40px; }
.stu-glyph .glyph { display: block; width: 162px; max-width: 100%; height: 12px; }
.stu-heart { display: inline-grid; place-items: center; width: 12px; height: 12px; color: var(--accent); margin-left: -2px; }
.stu-heart svg { width: 12px; height: 12px; filter: drop-shadow(0 0 5px var(--accent-glow)); }
.stu-fill { flex: 1 1 auto; }
.stu-seg { display: inline-flex; align-items: center; gap: 2px; padding: 2px; flex: none; border: 1px solid var(--line-1); border-radius: var(--r-pill); }
.stu-seg button {
  min-width: 24px; height: 20px; padding: 0 6px; border: 0; border-radius: var(--r-pill); background: transparent;
  font: 500 10.5px/1 var(--font-mono); color: var(--text-3);
  transition: color var(--dur-1) var(--ease-out), background-color var(--dur-1) var(--ease-out);
}
.stu-seg button:hover { color: var(--text-1); }
.stu-seg button[aria-pressed='true'] { color: var(--text-1); background: var(--surface-3); box-shadow: var(--highlight), 0 0 0 1px var(--line-1); }
.stu-seg .label { padding: 0 6px 0 3px; font-size: 9.5px; }

.stu-surface {
  position: relative; min-height: 0; min-width: 0;
  border: 1px solid var(--line-1); border-radius: var(--r-2); background: var(--bg-1); overflow: hidden;
}
.stu-surface canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }

/* the strip follows DSP's strip (paddings, sizes, breakpoints); what only STUDIO has gives way first:
   ≤ 1024 AHEAD, the BARS label and the theme state go; < 800 two fixed rows */
@media (max-width: 1024px) {
  .stu-ro-ahead, .stu-seg .label, .stu-ro-theme [data-r='themeSt'] { display: none; }
  .stu-glyph .glyph { width: 112px; height: 10px; }
}
@media (max-width: 899px) {
  .stu-ro { padding: 0 13px; }
}
@media (max-width: 799px) {
  .stu-strip { flex-wrap: wrap; }
  .stu-br { display: block; flex: 0 0 100%; height: 0; }
  .stu-br + .stu-ro { padding-left: 2px; border-left: 0; }
}
@media (max-width: 760px) {
  .stu-ro { padding: 0 12px; }
  .stu-ro b { font-size: 14px; }
}
@media (max-width: 640px) {
  .stu-ro { padding: 0 10px; }
  .stu-ro b { font-size: 13px; }
  .stu-dim { font-size: 11px; }
  .stu-ro-theme .stu-glyph { display: none; }
}
@media (max-width: 600px) {
  .stu { min-height: 460px; gap: 8px; padding-top: 8px; }
}
@media (pointer: coarse) {
  .stu-seg button { min-height: 44px; min-width: 44px; }
}

/* ============================================================================
   SLEEP (the night vibe) — components. Tokens: top of this file.
   ========================================================================== */
/* vibe button (moon in chill → sleep, sun in sleep → chill); on touch screens it takes the ? slot */
.vibe-btn svg { width: 16px; height: 16px; }
.vibe-btn .i-sun { display: none; }
:root[data-vibe='sleep'] .vibe-btn .i-moon { display: none; }
:root[data-vibe='sleep'] .vibe-btn .i-sun { display: block; }
@media (pointer: coarse) {
  .app[data-vibe-offer='true'] #btnHelp { display: none; }
  .vibe-btn { width: 44px; height: 44px; }
}
@media (max-width: 480px) {
  .app[data-vibe-offer='true'] #btnHelp { display: none; }
}

/* timer chip (transport, sleep only): moon ring with a thin amber arc of the time left + minutes */
.tb-timer { display: none; }
.tsep-timer { display: none; }
:root[data-vibe='sleep'] .tb-timer { display: inline-flex; align-items: center; gap: 6px; width: auto; padding: 0 11px 0 9px; }
:root[data-vibe='sleep'] .tsep-timer { display: block; }
.app[data-mode='play'] .tb-timer { width: auto; }
.timer-ring { display: inline-grid; place-items: center; width: 20px; height: 20px; flex: none; }
.timer-ring svg { width: 20px; height: 20px; transform: rotate(-90deg); }
.timer-ring circle { fill: none; stroke-width: 1.4; }
.timer-ring .ta-bg { stroke: var(--line-3); }
.timer-ring .ta-fg { stroke: var(--accent); stroke-linecap: round; stroke-dasharray: var(--arc, 0) 100; }
.tb-timer[data-armed='false'] .ta-fg { stroke-dasharray: 0 100; }
.timer-ring .ta-moon { fill: var(--text-3); transform: rotate(90deg); transform-origin: 10px 10px; }
.tb-timer[data-armed='true'] .ta-moon { fill: var(--accent); }
.timer-txt { font: 500 12px/1 var(--font-mono); letter-spacing: 0.02em; color: var(--text-2); white-space: nowrap; }
/* DSP / STUDIO keep the transport in the bar from 900 px: at night the timer chip needs its room there — the energy
   control drops its ENERGY label and number up to 1180 px (no horizontal scroll; the slider and AUTO stay) */
@media (min-width: 900px) and (max-width: 1180px) {
  :root[data-vibe='sleep'] .app:not([data-mode='play']) .energy-label,
  :root[data-vibe='sleep'] .app:not([data-mode='play']) .energy-val { display: none; }
}
@media (max-width: 599px) {
  :root[data-vibe='sleep'] .energy-slot, :root[data-vibe='sleep'] .tsep-timer { display: none; }
}

/* timer sheet: 15 · 30 · 45 · 60 · 90 · ∞, +15, keep the tide; placed next to the chip (app.js) */
.sheet {
  position: fixed; z-index: var(--z-overlay); left: 50%; top: 50%;
  width: min(300px, calc(100vw - 24px)); padding: 12px 12px 10px;
  background: rgba(10, 7, 5, 0.96); border: 1px solid var(--line-2); border-radius: var(--r-3);
  box-shadow: var(--highlight), 0 24px 60px -24px rgba(0, 0, 0, 0.95);
}
.sheet-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; padding: 0 2px 10px; }
.sheet-end { font: 500 11px/1 var(--font-mono); color: var(--text-2); letter-spacing: 0.04em; }
.sheet-opts { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 4px; }
.sheet-opts button, .sheet-btn {
  height: 36px; min-width: 0; padding: 0; border: 1px solid var(--line-1); border-radius: var(--r-2); background: transparent;
  font: 500 13px/1 var(--font-mono); color: var(--text-2);
  transition: color var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out), background-color var(--dur-1) var(--ease-out);
}
.sheet-opts button:hover, .sheet-btn:hover:not(:disabled) { color: var(--text-1); border-color: var(--line-3); }
.sheet-opts button[aria-checked='true'] { color: var(--accent); border-color: var(--accent-lo); background: var(--surface-3); }
.sheet-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 8px; }
.sheet-btn { padding: 0 14px; }
.sheet-btn:disabled { opacity: 0.4; cursor: default; }
.sheet-tog { display: inline-flex; align-items: center; gap: 8px; font: 500 11px/1 var(--font-mono); letter-spacing: 0.04em; color: var(--text-2); cursor: pointer; }
.sheet-tog input { width: 16px; height: 16px; margin: 0; accent-color: var(--accent-lo); }
@media (pointer: coarse) {
  .sheet-opts button, .sheet-btn { height: 44px; }
  .sheet-tog { min-height: 44px; }
}

/* start screen: the vibe choice above Start, styled in the chosen vibe */
.start-vibe {
  display: inline-flex; align-items: center; gap: 3px; margin-top: 26px; padding: 3px;
  border: 1px solid var(--line-2); border-radius: var(--r-pill); background: rgba(10, 10, 10, 0.6);
}
.start-vibe button {
  display: inline-flex; align-items: center; gap: 6px; height: 34px; padding: 0 14px; border: 0; border-radius: var(--r-pill);
  background: transparent; font: 500 11px/1 var(--font-mono); letter-spacing: 0.06em; color: var(--text-3); white-space: nowrap;
  transition: color var(--dur-1) var(--ease-out), background-color var(--dur-1) var(--ease-out);
}
.start-vibe button b { font-weight: 600; letter-spacing: 0.1em; color: inherit; }
.start-vibe button:hover { color: var(--text-1); }
.start-vibe button[aria-checked='true'] { color: var(--text-1); background: var(--surface-3); box-shadow: var(--highlight), 0 0 0 1px var(--line-2); }
.start-vibe + .start-btn { margin-top: 18px; }
@media (max-width: 420px) {
  .start-vibe button { padding: 0 10px; font-size: 10.5px; }
}
@media (pointer: coarse) { .start-vibe button { height: 44px; } }

/* night overrides of the chill components */
:root[data-vibe='sleep'] :focus-visible { outline-color: rgba(205, 184, 159, 0.8); }
:root[data-vibe='sleep'] .tb:hover { background: rgba(255, 161, 51, 0.06); }
:root[data-vibe='sleep'] .tb-play,
:root[data-vibe='sleep'] .tb-play:hover { background: var(--surface-3); color: var(--accent); box-shadow: 0 0 0 1px var(--accent-lo); }
:root[data-vibe='sleep'] .tb-play:hover { background: var(--surface-4); color: var(--accent-hi); }
:root[data-vibe='sleep'] .start { background: radial-gradient(ellipse 70% 60% at 50% 50%, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.8) 60%, rgba(0, 0, 0, 0.95) 100%); }
:root[data-vibe='sleep'] .start-btn,
:root[data-vibe='sleep'] .start-btn:hover { background: var(--surface-3); color: var(--accent); box-shadow: 0 0 0 1px var(--accent-lo); }
:root[data-vibe='sleep'] .start-btn:hover { background: var(--surface-4); }
:root[data-vibe='sleep'] .start-btn kbd { background: transparent; border-color: var(--line-2); color: var(--text-3); }
:root[data-vibe='sleep'] .start-mark, :root[data-vibe='sleep'] .start-title { color: var(--text-1); }
:root[data-vibe='sleep'] .start-vibe { background: rgba(10, 7, 5, 0.6); }
:root[data-vibe='sleep'] .start-vibe button[aria-checked='true'] { color: var(--accent); box-shadow: 0 0 0 1px var(--accent-lo); }
:root[data-vibe='sleep'] .mode-tab[aria-selected='true']::before { box-shadow: none; }
:root[data-vibe='sleep'] .tabs { background: rgba(10, 7, 5, 0.6); }
:root[data-vibe='sleep'] .src-seg { display: none; }                     /* sleep is synth-only */
:root[data-vibe='sleep'] .net-dot { animation: none !important; box-shadow: none !important; opacity: 0.6; }
:root[data-vibe='sleep'] .net-dot[data-state='ok'] { background: var(--ok); }
:root[data-vibe='sleep'] .net-dot[data-state='buffering'], :root[data-vibe='sleep'] .net-dot[data-state='connecting'] { background: var(--accent-lo); }
:root[data-vibe='sleep'] .netstate { background: rgba(10, 7, 5, 0.85); color: var(--text-3); animation: none; }
:root[data-vibe='sleep'] .netstate i { animation: none; box-shadow: none; background: var(--accent-lo); }
:root[data-vibe='sleep'] .toast { color: var(--text-3); background: rgba(10, 7, 5, 0.9); }
:root[data-vibe='sleep'] .tb-like[aria-pressed='true'] .i-heart-fill { filter: none; }
:root[data-vibe='sleep'] .energy-level { background: rgba(205, 184, 159, 0.45); }
:root[data-vibe='sleep'] .chip-auto[aria-pressed='true'] { background: rgba(224, 145, 58, 0.06); border-color: var(--accent-lo); }
:root[data-vibe='sleep'] .glyph rect.g-odd { stroke: var(--text-1); }
:root[data-vibe='sleep'] .help { background: rgba(10, 7, 5, 0.96); }
:root[data-vibe='sleep'] .app[data-mode='play'] .transport { background: rgba(10, 7, 5, 0.5); }
:root[data-vibe='sleep'] .live-dot { box-shadow: none; opacity: 0.35; }
:root[data-vibe='sleep'] .play[data-playing='true'] .live-dot { opacity: 0.6; }
:root[data-vibe='sleep'] .play-caption,
:root[data-vibe='sleep'] .play-meta { display: none; }                  /* no captions, no counters at night */

/* auto-hidden controls (SLEEP · PLAY): out over 1.5 s, back at the night level over 0.4 s */
:root[data-vibe='sleep'] .app[data-mode='play'] .topbar,
:root[data-vibe='sleep'] .app[data-mode='play'] .transport,
:root[data-vibe='sleep'] .play-hud { transition: opacity 400ms var(--ease-out); }
.app[data-chrome='hidden'][data-mode='play'] .topbar,
.app[data-chrome='hidden'][data-mode='play'] .transport,
.app[data-chrome='hidden'] .play-hud,
.app[data-chrome='hidden'] .play-stopped { opacity: 0; pointer-events: none; transition: opacity 1.5s var(--ease-in-out); }
.app[data-chrome='hidden'] ~ .netstate { display: none; }

/* after the timer: nothing streams — like / next / energy are off until Play (app.js sleepEnded) */
.app[data-sleep-ended='true'] .tb-like, .app[data-sleep-ended='true'] .tb-next, .app[data-sleep-ended='true'] .energy-slot { opacity: 0.35; }
.app[data-sleep-ended='true'] .energy-slot { pointer-events: none; }
/* after the timer: a dim line on black, shown with the controls */
.play-stopped {
  position: absolute; left: 0; right: 0; top: 42%; z-index: 2; text-align: center; pointer-events: none;
  font: 500 11px/1 var(--font-mono); letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-3);
  transition: opacity 400ms var(--ease-out);
}
@media (prefers-reduced-motion: reduce) {
  .app[data-chrome='hidden'][data-mode='play'] .topbar, .app[data-chrome='hidden'][data-mode='play'] .transport,
  .app[data-chrome='hidden'] .play-hud { transition: none; }
}

/* Full style choice stays accessible during playback and fits narrow screens. */
.style-select { max-width: 155px; min-height: 36px; padding: 0 10px; border: 1px solid var(--line-2); border-radius: var(--r-pill); background: var(--surface-2); color: var(--text-1); font: 11px var(--font-mono); }
.style-select:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.start-vibe { flex-wrap: wrap; justify-content: center; max-width: min(620px, calc(100vw - 32px)); border-radius: 20px; }
@media (max-width: 600px) { .style-select { max-width: 115px; font-size: 10px; } .vibe-btn { display: none; } .start-vibe button { flex-direction: column; justify-content: center; gap: 5px; height: 52px; } }

/* NIGHTSHIFT: acid green and violet, with the existing motion/accessibility rules. */
:root[data-vibe='phonk'] {
  --accent: #c7ff52;
  --accent-hi: #e0ff9f;
  --accent-lo: #719a23;
  --lane-bass: #c7ff52;
  --lane-chord: #bd90ff;
  --lane-hat: #87dcd1;
  --lane-fx: #ff79c2;
}
