/* style.css — layout, overlays, safe-area, type scale (UX Spec §7), Midnight Pressing
   surfaces (Art Direction: channel-strip cards, cream label islands, warm dark). */

:root {
  --lacquer: #191310; --lacquer-deep: #0D0A07; --groove: #2B2119;
  --bone: #EDE6D6; --cream: #F5EEDF; --ink: #2B2119;
  --plum: #9B6BFF; --verdigris: #2EC4A9; --magenta: #F45B9E;
  --danger: #FF3B2F; --gold: #FFD75E;
  /* U8 F32: recording-tally red — warmer, deeper than the field's Signal Red; chrome
     only (title/end-card chip), never on the play field (§4.3 red-semantics ruling) */
  --tally-red: #D6402E;
  --sat: env(safe-area-inset-top, 0px);
  --sab: env(safe-area-inset-bottom, 0px);
  --sans: -apple-system, "SF Pro Rounded", "Segoe UI", sans-serif;
  --mono: ui-monospace, "SF Mono", Menlo, monospace;
}

* { margin: 0; padding: 0; box-sizing: border-box;
    -webkit-tap-highlight-color: transparent;
    -webkit-touch-callout: none;
    -webkit-user-select: none; user-select: none; }

html, body {
  height: 100%; overflow: hidden;
  background: var(--lacquer-deep);
  color: var(--bone);
  font-family: var(--sans);
  overscroll-behavior: none;
  position: fixed; inset: 0; width: 100%;
}

#safe-probe { position: absolute; top: 0; height: var(--sat); width: 1px; visibility: hidden; }

#stage {
  position: absolute; inset: 0; width: 100%; height: 100%;
  touch-action: none; display: block;
}

#file-notice {
  position: absolute; top: 40%; left: 50%; transform: translateX(-50%);
  max-width: 320px; padding: 16px; background: var(--cream); color: var(--ink);
  border-radius: 12px; font-size: 15px; text-align: center; z-index: 99;
}

/* ---------- layers: transparent to the canvas except interactive children ---------- */
/* pointer-events:none is load-bearing: #stage (the canvas) is a SIBLING below #ui and
   owns every gameplay tap — the container must never be the hit target. */
#ui { position: absolute; inset: 0; pointer-events: none; }
#ui .hidden { display: none !important; }
.layer { position: absolute; inset: 0; pointer-events: none; }
.layer.hidden { display: none; }
.layer button, .layer .draft-card, .layer .set-row, .layer .loop-row,
.layer .resume-card, .layer .kit-card { pointer-events: auto; }
.layer-library, .layer-settings { background: rgba(13, 10, 7, 0.88); pointer-events: auto; }
.layer-resume { background: rgba(13, 10, 7, 0.55); }

button {
  font-family: var(--sans); border: none; background: none; color: inherit;
  font-size: 17px; cursor: pointer;
  transition: transform 90ms ease-out;   /* press-state <=100ms, no hover states */
}
button:active { transform: scale(0.96); }

/* ---------- attract (title = the game) ---------- */
.attract-top {
  position: absolute; top: calc(var(--sat) + 14px); left: 0; right: 0;
  display: flex; flex-direction: column; align-items: center; gap: 8px;
}
.chip {
  font-size: 13px; font-weight: 600; color: var(--bone);
  background: rgba(0,0,0,0.4); border-radius: 999px; padding: 6px 14px;
}
.today-line {
  width: min(calc(100% - 32px), 430px); text-align: center;
  font-size: 15px; line-height: 1.3; opacity: 0.85; overflow-wrap: anywhere;
}
@media (max-width: 340px) { .today-line { font-size: 13px; } }
.big-tap {
  position: absolute; left: 0; right: 0; top: 62%;
  text-align: center; font-size: 28px; font-weight: 600; color: var(--cream);
  animation: breathe 2.4s ease-in-out infinite;
}
@keyframes breathe { 0%, 100% { opacity: 0.9; } 50% { opacity: 0.55; } }
.corner {
  position: absolute; bottom: calc(var(--sab) + 16px);
  width: 64px; height: 64px; border-radius: 16px;
  background: rgba(43, 33, 25, 0.85); border: 1px solid var(--groove);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
}
.corner-l { left: 16px; } .corner-r { right: 16px; }
.corner-icon { font-size: 20px; } .corner-label { font-size: 12px; opacity: 0.8; }
.corner.hidden { display: none; }
/* U3 F13: attract idle hint — post-FTUE only, static, no animation (kill idle pulsing) */
.idle-hint {
  position: absolute; left: 0; right: 0; top: calc(62% + 44px);
  text-align: center; font-size: 14px; color: var(--bone); opacity: 0.6;
}
.idle-hint.hidden { display: none; }
.big-tap.shared { display: none; }
.shared-hear-btn, .shared-make-btn {
  position: absolute; left: 50%; top: calc(62% + 56px); transform: translateX(-50%);
  width: min(240px, calc(100% - 64px)); min-height: 44px;
  border: 1px solid var(--groove); border-radius: 999px;
  background: rgba(43, 33, 25, 0.82); color: var(--bone); opacity: 0.85;
}
.shared-hear-btn { top: 62%; color: var(--cream); opacity: 1; }
.shared-hear-btn:active, .shared-make-btn:active { transform: translateX(-50%) scale(0.96); }

/* ---------- Jam toggle chip (Update 1 §2.2): bottom-center above the corners,
   >=56pt target; states distinguished by glyph + label, never color alone ---------- */
.jam-chip {
  position: absolute; bottom: calc(var(--sab) + 96px); left: 0; right: 0;
  margin: 0 auto; width: max-content; min-height: 56px; padding: 0 24px;
  border-radius: 999px; background: rgba(43, 33, 25, 0.85);
  border: 1px solid var(--groove);
  font-size: 15px; font-weight: 600; color: var(--bone);
}
.jam-chip.jam { border-color: var(--verdigris); color: var(--cream); } /* hue is redundancy, not the signal */
.jam-chip.hidden { display: none; }
/* U8 F32 — the breathing REC recording light: sinusoidal opacity breathe, period
   3200ms (0.31Hz — ambient, an order of magnitude under any alert cadence), alpha
   0.45 -> 1.0. Opacity ONLY: no size change, no glow. Pure CSS on the DOM chip —
   zero canvas/frame cost. The pulse is never load-bearing: every state it accompanies
   is also carried by the label text (§4.2 attention-budget ruling). */
.rec-dot {
  color: var(--tally-red);
  display: inline-block;
  animation: rec-breathe 3200ms ease-in-out infinite;
}
@keyframes rec-breathe { 0%, 100% { opacity: 0.45; } 50% { opacity: 1; } }
/* flashReduce / prefers-reduced-motion: STATIC solid red dot at full alpha — never
   white (his explicit instruction), never animated. Both the in-game settings flag
   (html.flash-reduce, set by main.js) and the OS media query are honored. */
html.flash-reduce .rec-dot { animation: none; opacity: 1; }

/* ---------- run ---------- */
.pause-btn {
  position: absolute; top: calc(var(--sat) + 10px); right: 12px;
  width: 44px; height: 44px; border-radius: 12px;
  background: rgba(0,0,0,0.4); color: var(--bone); font-size: 18px;
}
/* U8 F31 §3.1 — the Press chip: quiet to the eye (12pt label, alpha 0.55, static),
   generous to the thumb (44pt padded target). Top-left field edge beneath the score
   cluster; outside the verb band; clear of the pause button (top-right). Never in the
   verb band, never a toast, never modal. */
.press-chip {
  position: absolute; top: calc(var(--sat) + 54px); left: 8px;
  min-width: 44px; min-height: 44px; padding: 4px 12px;
  border: none; border-radius: 999px; background: transparent;
  font-size: 12px; font-weight: 600; color: var(--bone); opacity: 0.55;
  text-align: left;
}
.press-chip .press-dot { color: var(--gold); }
.press-chip.pressed { opacity: 0.9; }
.press-chip.hidden { display: none; }
.active-effect {
  position: absolute; top: calc(var(--sat) + 58px); left: 50%; transform: translateX(-50%);
  max-width: min(62vw, 230px); min-height: 32px; padding: 7px 12px;
  border: 1px solid var(--groove); border-radius: 999px;
  background: rgba(25,19,16,0.88); color: var(--cream);
  font-size: clamp(12px, 3.7vw, 14px); line-height: 1.25; text-align: center;
}
.active-effect.hidden { display: none; }
/* fresh-side accent: brightens once, riding the pressing shimmer beat (WAX_STEP_MS),
   then settles back to idle — no self-animation at rest, ever */
.press-chip.accent { animation: press-accent 1000ms ease-out; }
@keyframes press-accent { 0% { opacity: 1; } 100% { opacity: 0.55; } }
.ftue-text {
  position: absolute; left: 0; right: 0; top: 57%;
  text-align: center; font-size: clamp(18px, 5.64vw, 22px); font-weight: 500; color: var(--cream);
  text-shadow: 0 1px 8px rgba(0,0,0,0.8);
  white-space: pre-line; text-wrap: balance; line-height: 1.25; padding: 0 16px;
  transition: opacity 300ms ease-in;
}
.crack-label {
  /* 51%: below the canvas HUD strip (~45–49% height) — the two must never collide
     at the attribution moment (UX Spec §7 readability) */
  position: absolute; left: 0; right: 0; top: 51%;
  text-align: center; font-size: 17px; font-weight: 600; color: var(--cream);
  text-shadow: 0 1px 6px rgba(0,0,0,0.9);
}
.ftue-text.hidden, .crack-label.hidden { display: none; }
/* U3 F10: B4/B4b copy anchors directly adjacent to the pip row (~47% canvas height) —
   Gestalt proximity: one glance parses text + object as one chunk */
.ftue-text.at-pips { top: calc(47% + 28px); font-size: clamp(17px, 4.87vw, 19px); }

/* U15 comprehension holds: the record keeps spinning and sounding, while two
   critical models (return + crack) get a single explicit, non-canvas-dismissable
   card. It is compact enough for 320x568 and its only action clears the 56pt floor. */
.teach-card {
  position: absolute; z-index: 4; left: 16px; right: 16px;
  bottom: calc(var(--sab) + 18px); padding: 18px;
  border: 1px solid var(--groove); border-radius: 18px;
  background: rgba(25,19,16,0.96); box-shadow: 0 10px 32px rgba(0,0,0,0.45);
  text-align: center;
}
.teach-card.hidden { display: none; }
.teach-card-title { color: var(--gold); font-size: 16px; font-weight: 700; letter-spacing: 0.08em; }
.teach-card-body { margin: 10px 0 14px; color: var(--cream); font-size: 16px; line-height: 1.45; white-space: pre-line; }
.teach-card-continue {
  width: 100%; min-height: 56px; border: 0; border-radius: 14px;
  background: var(--cream); color: var(--ink); font-size: 17px; font-weight: 700;
}
.teach-card-continue:disabled { opacity: 0.48; }

/* ---------- draft: channel-strip cards in the verb band, no timer ---------- */
.draft-title {
  position: absolute; top: 38%; left: 0; right: 0; text-align: center;
  font-size: 15px; opacity: 0.85; text-shadow: 0 1px 6px rgba(0,0,0,0.9);
}
.draft-cap {  /* coach line C1: caption type, once ever */
  position: absolute; top: calc(38% + 24px); left: 0; right: 0; text-align: center;
  font-size: 13px; opacity: 0.7; text-shadow: 0 1px 6px rgba(0,0,0,0.9);
}
.draft-cap.hidden { display: none; }
.draft-stack {
  position: absolute; top: 45%; left: 16px; right: 16px;
  display: flex; flex-direction: column; gap: 16px;
}
.draft-card {
  min-height: 88px; border-radius: 14px; background: var(--cream); color: var(--ink);
  border-left: 10px solid var(--stripe, var(--plum));
  padding: 14px 16px; display: flex; flex-direction: column; justify-content: center; gap: 4px;
  transition: transform 90ms ease-out;
  /* staggered eased entrance — cards deal in one by one, overshoot arrival */
  animation: card-in 250ms cubic-bezier(0.34, 1.56, 0.64, 1) backwards;
  animation-delay: calc(var(--i, 0) * 70ms);
}
@keyframes card-in { from { opacity: 0; transform: translateY(14px) scale(0.97); } }
.draft-card:active { transform: scale(0.97); }
.draft-card.inspect { transform: scale(1.02); }  /* hold-to-inspect (UX Spec §2.3) */
.card-name { font-size: 17px; font-weight: 600; }
.card-blurb { font-size: 15px; opacity: 0.75; }

/* ---------- run end: thumb-first stack, Retry dominant and lowest ----------
   U6 F25 §3.1 — the SLOT SYSTEM: the whole card is one flex column in document flow;
   no two text elements can ever share an absolute position again. SLOT A (.end-top:
   stamp row, then cause line), SLOT B (.end-mid: score band, centered by auto
   margins — it compresses when SLOT C needs the room), SLOT C (.end-stack: bottom
   group; the gap is the only spacing authority). Priority law: cause line > buttons >
   deposit > trio/pointer > stamp — the compact media query below shrinks in that
   reverse order; the cause line and primary buttons never compress. */
.layer-end {
  display: flex; flex-direction: column;
  padding: calc(var(--sat) + 58px) 16px calc(var(--sab) + 16px);
}
.end-done {
  position: absolute; top: calc(var(--sat) + 10px); left: 12px;
  height: 44px; padding: 0 14px; border-radius: 12px;
  background: rgba(0,0,0,0.4); font-size: 15px; z-index: 2;
}
/* SLOT A — stamp row and cause line are separate flex rows: overlap is impossible
   by construction; padding bounds the -4° rotation overhang out of A2's line box */
.end-top { display: flex; flex-direction: column; gap: 8px; }
.stamp-row { display: flex; justify-content: flex-end; padding: 4px 4px 2px 0; }
.end-cause {
  text-align: center; font-size: 17px; color: var(--bone); opacity: 0.9;
  overflow-wrap: break-word;               /* wraps (<=2 lines by copy), NEVER truncates */
  /* U6 F25 R2 (M1): fade-in DELAYED past the full 250ms stamp-slam — backwards fill
     holds opacity 0 while the slam's 1.6x overshoot bbox transits this line's box,
     so stamp and cause line are never visible in the same frame (entry-transit
     counts; the slam bytes stay update3-certified). Both animations start on the
     same style flush (ui.end sets text + .slam in one task). Contract asserted in
     qa/update6-check.mjs: static delay >= slam duration + rAF transit-frame probe. */
  animation: fade-in 300ms ease-out 300ms backwards;
}
/* end screen enters, never pops: score pops in with overshoot, stack rises after */
@keyframes fade-in { from { opacity: 0; } }
@keyframes pop-in  { from { opacity: 0; transform: scale(0.6); } }
@keyframes rise-in { from { opacity: 0; transform: translateY(16px); } }
.end-cause.wax { color: var(--gold); font-size: 22px; font-weight: 600; }
/* SLOT B — score band: flow siblings; long fill lines push down, never under.
   min-height keeps the one-line score alive when SLOT C wins the space (§3.1). */
.end-mid {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  margin: auto 0; min-height: 44px; overflow: hidden;
}
.end-score {
  text-align: center;
  font-family: var(--mono); font-size: 40px; font-weight: 700; color: var(--cream);
  text-shadow: 0 1px 10px rgba(0,0,0,0.8);
  animation: pop-in 350ms cubic-bezier(0.34, 1.56, 0.64, 1) backwards;
}
.end-delta {
  text-align: center; font-size: 15px; opacity: 0.8;
  animation: fade-in 300ms ease-out 120ms backwards;
}
/* U3 F13: fill-percent progress line — a trend line under the delta, quiet type */
.end-fill {
  text-align: center; font-size: 13px; opacity: 0.65;
  animation: fade-in 300ms ease-out 160ms backwards;
}
.end-fill.hidden { display: none; }
/* U8 F35 §7.3: the collector's-detail secondary stat — smallest stat type */
.end-stat {
  text-align: center; font-size: 11px; opacity: 0.5; font-family: var(--mono);
  animation: fade-in 300ms ease-out 200ms backwards;
}
.end-stat.hidden { display: none; }
.end-trio {
  text-align: center; font-size: 13px; color: var(--gold); opacity: 0.95;
  padding: 0 8px;
}
.end-trio.hidden { display: none; }
/* U6 F26 §4.3: the suppression caption — a static text row in the Share slot */
.share-cap {
  text-align: center; font-size: 13px; opacity: 0.8; line-height: 1.45;
}
.share-cap.hidden { display: none; }
/* U3 F16: the streak stamp — the only cream element outside label/cards; passport
   corner FEEL kept by right alignment + rotation (U6 F25: in flow, its own row) */
.streak-stamp {
  background: var(--cream); color: var(--ink);
  border: 1px solid var(--ink); border-radius: 999px;
  padding: 8px 16px; transform: rotate(-4deg);
  font-family: var(--mono); font-weight: 700; font-size: 14px; text-align: center;
  text-transform: uppercase;               /* visual transform only — vocabulary stays "Day N 🔥" */
  pointer-events: none;
}
.streak-stamp.milestone { box-shadow: inset 0 0 0 3px var(--cream), inset 0 0 0 4px var(--ink); }
.streak-stamp .stamp-flakes { font-size: 11px; opacity: 0.7; letter-spacing: 0.4px; }
.streak-stamp .stamp-flakes.hidden { display: none; }
.streak-stamp.hidden { display: none; }
.streak-stamp.slam { animation: stamp-slam 250ms cubic-bezier(0.34, 1.56, 0.64, 1) backwards; }
@keyframes stamp-slam {
  from { transform: scale(1.6) rotate(-12deg); opacity: 0.85; }
  to   { transform: scale(1) rotate(-4deg); opacity: 1; }
}
/* U3 F12: low-emphasis Library entry below Retry */
.end-lib-btn {
  opacity: 0.75; min-height: 46px; height: 46px; flex: 0 0 46px;
}
.end-stack {
  display: flex; flex-direction: column; gap: 16px;
  margin-top: 12px; flex-shrink: 0;        /* SLOT C wins: B compresses, C never clips */
  animation: rise-in 300ms ease-out 80ms backwards;
}
/* (U6 F25: the priority-law compression tiers live at the END of this file — they must
   follow every base rule they soften, or equal-specificity base rules would win) */
.deposit { background: rgba(43,33,25,0.8); border-radius: 12px; padding: 12px 14px; }
/* B10 Jam callout + DDA-moment pointer: caption type, an offer, never a lecture */
.end-jam-note {
  font-size: 13px; color: var(--gold); text-align: center; white-space: pre-line;
  line-height: 1.5; opacity: 0.95;
}
.end-jam-note.hidden { display: none; }
/* U2 F3: the SAME jam chip component, in the end-card stack flow (>=56pt target) */
.end-jam-chip { position: static; margin: 0 auto; }
.end-jam-cap {
  font-size: 12px; text-align: center; opacity: 0.7; margin-top: -6px;
}
.end-jam-cap.hidden { display: none; }
.deposit-pointer { font-size: 12px; margin-top: 6px; opacity: 0.7; }
.deposit-pointer.hidden { display: none; }
.end-intent {
  border: 1px solid var(--groove); border-radius: 12px; padding: 11px 14px;
  font-size: 14px; line-height: 1.35; text-align: center; color: var(--cream);
}
.end-intent.hidden, .recovery-btn.hidden { display: none; }
.recovery-btn { min-height: 56px; height: auto; padding: 10px 14px; line-height: 1.3; }
/* graduation nudge (§2.3): equal-weight buttons, never blocks Retry */
.nudge-card { background: rgba(43,33,25,0.9); border: 1px solid var(--groove); border-radius: 12px; padding: 12px 14px; }
.nudge-card.hidden { display: none; }
.nudge-text { font-size: 14px; text-align: center; margin-bottom: 10px; }
.nudge-row { display: flex; gap: 10px; }
.nudge-btn {
  flex: 1; height: 48px; border-radius: 12px; background: rgba(0,0,0,0.35);
  border: 1px solid var(--groove); color: var(--bone); font-size: 14px; font-weight: 600;
}
.deposit-bar { height: 6px; border-radius: 3px; background: rgba(0,0,0,0.5); overflow: hidden; }
.deposit-fill {
  height: 100%; background: var(--gold); border-radius: 3px;
  transition: width 600ms cubic-bezier(0.34, 1.56, 0.64, 1);   /* fills with overshoot */
}
.deposit-text { font-size: 13px; margin-top: 8px; opacity: 0.85; }
.share-btn {
  height: 52px; border-radius: 14px; background: rgba(43,33,25,0.9);
  border: 1px solid var(--groove); color: var(--bone); font-size: 17px;
}
/* U8 F31 §3.3 — the Jam end-card press slot: SLOT C's primary; declining is its own
   explicit button, never a default dismissal */
.press-slot { display: flex; flex-direction: column; gap: 10px; }
.press-slot.hidden { display: none; }
.press-session-btn {
  height: 56px; border-radius: 14px; background: var(--gold); color: var(--ink);
  font-size: 17px; font-weight: 600;
}
.press-session-btn.hidden { display: none; }
.pressed-line { text-align: center; font-size: 15px; color: var(--gold); }
.pressed-line.hidden { display: none; }
.done-press-btn { opacity: 0.8; }
.retry-btn {
  height: 64px; border-radius: 16px; background: var(--cream); color: var(--ink);
  font-size: 20px; font-weight: 600;
}
.share-btn.hidden { display: none; }

/* U14 competency graduation: short enough to scan cold, with a clear default path.
   REC is the core game; Jam is a visible, lower-emphasis no-stakes alternative. */
.tutorial-choice {
  display: flex; flex-direction: column; gap: 12px;
  background: rgba(43,33,25,0.9); border: 1px solid var(--groove);
  border-radius: 16px; padding: 16px;
}
.tutorial-choice.hidden { display: none; }
.tutorial-choice-title { text-align: center; font-size: 15px; opacity: 0.82; }
.tutorial-mode-btn {
  min-height: 68px; border-radius: 14px; padding: 10px 14px;
  display: flex; flex-direction: column; justify-content: center; gap: 3px;
  text-align: left;
}
.tutorial-mode-btn.rec { border: 0; background: var(--cream); color: var(--ink); }
.tutorial-mode-btn.jam { border: 1px solid var(--groove); background: rgba(0,0,0,0.22); color: var(--bone); }
.tutorial-mode-title { font-size: 17px; font-weight: 700; }
.tutorial-mode-caption { font-size: 12px; font-weight: 500; opacity: 0.75; }
.layer-end.tutorial-graduation .end-done,
.layer-end.tutorial-graduation .stamp-row,
.layer-end.tutorial-graduation .end-mid,
.layer-end.tutorial-graduation .end-trio,
.layer-end.tutorial-graduation .end-jam-note,
.layer-end.tutorial-graduation .end-jam-chip,
.layer-end.tutorial-graduation .end-jam-cap,
.layer-end.tutorial-graduation .press-slot,
.layer-end.tutorial-graduation .nudge-card,
.layer-end.tutorial-graduation .deposit,
.layer-end.tutorial-graduation .deposit-pointer,
.layer-end.tutorial-graduation .share-btn,
.layer-end.tutorial-graduation .share-cap { display: none; }
.layer-end.tutorial-graduation .end-top { padding-top: calc(var(--sat) + 40px); }
.layer-end.tutorial-graduation .end-cause { color: var(--gold); letter-spacing: 0.06em; }
.layer-end.tutorial-graduation .end-stack { width: min(100%, 400px); margin-top: 14px; }

/* ---------- library / settings ---------- */
.screen-top {
  position: absolute; top: calc(var(--sat) + 10px); left: 12px; right: 12px;
  display: flex; align-items: center; gap: 12px; z-index: 2;
}
.back-btn { width: 44px; height: 44px; border-radius: 12px; background: rgba(0,0,0,0.4); font-size: 18px; }
.screen-title { font-size: 20px; font-weight: 600; flex: 1; }
/* U13: a single safe-area-aware vertical flow owns Library layout. Card copy is
   content-sized; normal flow keeps every following section below it. */
.library-body {
  position: absolute; top: calc(var(--sat) + 64px); bottom: calc(var(--sab) + 8px);
  left: 0; right: 0; overflow-y: auto; overscroll-behavior: contain;
  padding: 4px 0 16px;
}
/* U3 F12 §3.3: sections named for what they are */
.shelf-header {
  position: relative; margin: 0 16px 4px;
  font-size: 12px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase;
  opacity: 0.6; line-height: 1.35;
}
.kit-shelf {
  position: relative; display: flex; align-items: stretch; gap: 10px;
  overflow-x: auto; overflow-y: hidden; padding: 8px 16px 14px;
}
/* U3 F11 §4.2/§3.3: owned cards keep the cream interactive affordance because they ARE
   interactive; locked cards restyle to a flat Groove-tone collection badge — different
   shape and value, not color alone (grayscale-safe) */
.kit-card {
  position: relative; min-width: 108px; border-radius: 12px; padding: 10px 12px;
  background: var(--cream); color: var(--ink);
  transition: transform 90ms ease-out;
}
.kit-card:active { transform: scale(0.96); }
.kit-card.locked {
  background: var(--groove); color: var(--bone); opacity: 0.85;
  border-radius: 6px; border: 1px dashed rgba(237, 230, 214, 0.35);
}
.kit-name { font-size: 15px; font-weight: 600; }
.kit-sub { font-size: 12px; opacity: 0.7; margin-top: 2px; }
/* U4 F21: the rotation line — caption type under the kit label; the return trigger
   ("Hear it tomorrow.") said out loud, persistently, on owned non-today cards */
.kit-rot { font-size: 11px; opacity: 0.6; margin-top: 4px; line-height: 1.3; }
/* U3 F11: today's live pick — shape + label tag, never color alone */
.today-tag {
  position: absolute; top: -6px; right: -4px;
  background: var(--ink); color: var(--cream);
  font-size: 9px; font-weight: 700; letter-spacing: 0.08em;
  padding: 3px 7px; border-radius: 6px; border: 1px solid var(--cream);
}
.kit-bar { height: 4px; border-radius: 2px; background: rgba(0,0,0,0.5); margin-top: 8px; }
.kit-bar-fill { height: 100%; border-radius: 2px; background: var(--gold); }
/* U6 F24 §2.1/§2.2 — the Neon Groove card: full copy + the player-owned record-style
   control live ON the card (the card is the theme's home, not a Settings burial) */
.kit-card.theme-card { min-width: 224px; max-width: 248px; }
.theme-body { font-size: 11px; opacity: 0.78; margin-top: 6px; line-height: 1.4; }
.theme-toggle { display: flex; align-items: center; gap: 8px; margin-top: 8px; }
.theme-toggle-label { font-size: 11px; font-weight: 600; opacity: 0.7; }
.theme-opt {
  min-height: 44px; padding: 0 14px; border-radius: 999px;
  border: 1px solid var(--ink); font-size: 13px; font-weight: 600; color: var(--ink);
}
.theme-opt.sel { background: var(--ink); color: var(--cream); }
/* U8 F33 §5.3 — the standard-rotation shelf slots between the collection and the
   pressings; the loop list yields the row (tape/glass are owned-by-everyone cards,
   never a revoked unlock) */
.std-header { margin-top: 4px; }
.std-shelf { margin-bottom: 4px; }
.loops-header {
  position: relative; margin: 4px 16px 8px;
  font-size: 12px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase;
  opacity: 0.6;
}
.loop-list {
  position: relative; margin: 0 12px;
  display: flex; flex-direction: column; gap: 8px;
}
.lib-empty { font-size: 15px; opacity: 0.6; text-align: center; margin-top: 40px; padding: 0 24px; line-height: 1.5; }
.loop-row {
  min-height: 64px; border-radius: 12px; background: rgba(43,33,25,0.8);
  display: flex; align-items: center; padding: 8px 8px 8px 14px; gap: 8px;
}
.loop-info { flex: 1; min-width: 0; }
.loop-day { font-size: 15px; font-weight: 600; }
.loop-sub { font-size: 13px; opacity: 0.7; margin-top: 2px; overflow-wrap: anywhere; }
.loop-playing { color: var(--gold); font-size: 14px; }
.icon-btn { width: 44px; height: 44px; flex: 0 0 44px; border-radius: 10px; background: rgba(0,0,0,0.35); font-size: 18px; }
.confirm-del {
  height: 44px; padding: 0 12px; margin-left: 16px; border-radius: 10px;
  background: var(--danger); color: var(--cream); font-size: 14px; font-weight: 600;
}
.confirm-del.hidden { display: none; }
.pressing-detail {
  margin: -4px 4px 8px; padding: 12px; border: 1px solid var(--groove);
  border-radius: 12px; background: rgba(25,19,16,0.92);
  display: flex; flex-direction: column; gap: 10px;
}
.detail-copy { font-size: 14px; line-height: 1.4; opacity: 0.82; }
.detail-btn {
  width: 100%; min-height: 48px; padding: 9px 12px; border-radius: 12px;
  background: rgba(43,33,25,0.95); border: 1px solid var(--groove);
  color: var(--cream); font-size: 15px; line-height: 1.25;
}
.detail-btn.primary { min-height: 56px; background: var(--cream); color: var(--ink); font-weight: 700; }
.detail-btn.danger { color: var(--danger); }
.detail-btn:disabled { opacity: 0.45; }
.settings-list {
  position: absolute; top: calc(var(--sat) + 70px); left: 12px; right: 12px;
  bottom: calc(var(--sab) + 12px); overflow-y: auto;
  display: flex; flex-direction: column; gap: 8px;
}
.set-row {
  min-height: 56px; border-radius: 12px; background: rgba(43,33,25,0.8);
  display: flex; align-items: center; justify-content: space-between; padding: 0 16px;
}
.set-label { font-size: 17px; }
.set-value { font-family: var(--mono); font-size: 15px; opacity: 0.8; }
.danger-row .set-label { color: var(--danger); }
.toggle {
  width: 52px; height: 30px; border-radius: 999px; background: rgba(0,0,0,0.5);
  position: relative; transition: background 150ms ease-out;
}
.toggle.on { background: var(--verdigris); }
.knob {
  position: absolute; top: 3px; left: 3px; width: 24px; height: 24px; border-radius: 50%;
  background: var(--cream); transition: transform 150ms ease-out;
}
.toggle.on .knob { transform: translateX(22px); }

/* ---------- resume / pause / calibration card ---------- */
.resume-card {
  position: absolute; left: 16px; right: 16px; bottom: calc(var(--sab) + 24px);
  background: var(--cream); color: var(--ink); border-radius: 18px; padding: 20px 18px;
  display: flex; flex-direction: column; gap: 14px;
}
.resume-title { font-size: 20px; font-weight: 600; }
.resume-recap { font-size: 15px; opacity: 0.8; white-space: pre-line; }
.resume-card .retry-btn { background: var(--ink); color: var(--cream); }
.quiet-btn { height: 44px; font-size: 15px; opacity: 0.65; }
.quiet-btn.hidden { display: none; }

/* ---------- toasts / banner / debug ---------- */
/* U4 F18 opacity hierarchy: --msg-alpha is the per-layer knob the arbiter drives.
   P0 banner and P1/P2 text hold 1.0; the P5 toast recedes (0.72) while any P1/P2
   text is live — the secondary voice visibly recedes instead of competing. */
.toasts {
  --msg-alpha: 1;
  position: absolute; top: calc(var(--sat) + 60px); left: 0; right: 0;
  display: flex; flex-direction: column; align-items: center; gap: 8px; pointer-events: none;
}
.toast {
  background: var(--cream); color: var(--ink); font-size: 14px; font-weight: 600;
  border-radius: 18px; padding: 10px 18px; opacity: 0; transform: translateY(-8px);
  white-space: pre-line; text-align: center; line-height: 1.45;  /* U4 F21: two-line unlock toast */
  transition: opacity 250ms ease-out, transform 250ms ease-out;
}
.toast.in { opacity: var(--msg-alpha, 1); transform: none; }
/* F18 R9 occlusion fix: the end card's cause line and streak stamp both live in the
   --sat+64px band; released toasts (guaranteed onto the end card by R9) drop below
   that band so the stamp never clips the F21 unlock copy and the toast never paints
   over the cause line. 128px clears the tallest stamp (day + flakes lines + -4° tilt). */
.toasts.on-end { top: calc(var(--sat) + 128px); }
/* U3 F12: tappable toasts (unlock -> library) re-enable pointer events on themselves */
.toast.tappable { pointer-events: auto; cursor: pointer; }
.banner {
  position: absolute; bottom: calc(var(--sab) + 96px); left: 16px; right: 16px;
  background: rgba(43,33,25,0.95); border: 1px solid var(--groove);
  border-radius: 10px; padding: 10px 14px; font-size: 13px; text-align: center;
  pointer-events: none; z-index: 50;
}
.banner.hidden { display: none; }
.debug-overlay {
  position: absolute; bottom: calc(var(--sab) + 4px); left: 8px;
  font-family: var(--mono); font-size: 11px; color: var(--verdigris);
  background: rgba(0,0,0,0.6); padding: 4px 8px; border-radius: 6px; pointer-events: none; z-index: 60;
}
.debug-juice {
  position: absolute; bottom: calc(var(--sab) + 28px); left: 8px;
  font-size: 11px; color: var(--bone); background: rgba(0,0,0,0.6);
  padding: 4px 8px; border-radius: 6px; z-index: 60;
}

@media (prefers-reduced-motion: reduce) {
  .big-tap, .draft-card, .end-score, .end-stack, .end-cause, .end-delta,
  .end-fill, .streak-stamp, .press-chip { animation: none; }
  .toast, .toggle, .knob, .deposit-fill, button { transition: none; }
  .rec-dot { animation: none; opacity: 1; }   /* U8 F32: static solid red, never white */
}

/* U6 F25 §3.1 priority-law compression for short viewports: lower-priority elements
   shrink first (stamp, trio/pointer, deposit chrome, then SLOT B); the cause line and
   the primary buttons never compress below their floors (every control stays >=44pt).
   These tiers must stay LAST in the file — they override equal-specificity base rules. */
@media (max-height: 700px) {
  .layer-end { padding-top: calc(var(--sat) + 56px); }   /* always clears the ← Title band */
  .end-stack { gap: 10px; margin-top: 8px; }
  .end-score { font-size: 32px; }
  .streak-stamp { padding: 5px 12px; font-size: 12px; }
  .stamp-row { padding-top: 0; }
  .end-trio, .deposit-text, .share-cap { font-size: 12px; }
  .deposit { padding: 8px 12px; }
  .nudge-text { margin-bottom: 6px; }
  .nudge-btn { height: 44px; }
  .share-btn { height: 44px; }
  .retry-btn { height: 56px; }
}
@media (max-height: 600px) {
  .layer-end { padding-top: calc(var(--sat) + 56px); padding-bottom: calc(var(--sab) + 12px); }
  .end-stack { gap: 6px; margin-top: 4px; }
  .end-mid { gap: 2px; min-height: 36px; }
  .end-score { font-size: 28px; }
  .end-delta { font-size: 13px; }
  .end-fill { font-size: 11px; }
  .streak-stamp { padding: 4px 10px; font-size: 11px; }
  .streak-stamp .stamp-flakes { font-size: 9px; }
  .end-trio, .deposit-text, .share-cap { font-size: 11px; line-height: 1.3; }
  .deposit { padding: 6px 10px; }
  .deposit-text { margin-top: 5px; }
  .nudge-card { padding: 8px 10px; }
  .nudge-text { font-size: 13px; margin-bottom: 4px; }
  .retry-btn { height: 52px; font-size: 18px; }
  .quiet-btn { height: 44px; }
}
