/* ============================================================================
   VENUE VIBE ENGINE — vve.css?v=13
   Loads AFTER ../css/tokens.css. Implements the ENTIRE component inventory
   (docs/VVE-COMPONENTS.md C1–C19 + §0 tokens + §2 state matrix + §4 utilities).
   Screen builders write ZERO css — anything missing routes back through
   VVE-COMPONENTS.md, never into a screen file.

   LEGALITY LAWS (dossier §1.6 — binding):
   1. Raw crimson #9E1B32 on black = decorative/FILL only. Never text, never a
      meaning-carrying stroke. bg crimson + ivory text = THE legal treatment.
   2. Meaningful crimson strokes/icons/tracks -> --crimson-line (3.69:1).
      Crimson body text/links -> --crimson-text (4.59:1). Smoke-on-crimson banned.
   3. State never color-only: selected = crimson fill + ivory ✓ + TEXT label.
   4. Focus = 2px ivory ring, offset 2px, everywhere on dark ground.
   5. Reduced motion: single global gate (media query + [data-reduced-motion]).
   ========================================================================== */

/* ============================================================================
   0. TOKENS (VVE-COMPONENTS §0 — the ONLY additions to the site token set)
   ========================================================================== */
:root {
  /* Minted palette-law tokens (DECISIONS "Palette law" — system-wide) */
  --crimson-text: #D14A63;   /* 4.59:1 on black — normal text + links in crimson */
  --crimson-line: #C4324E;   /* 3.69:1 on black — large text, icons, strokes,
                                slider tracks, meaningful borders */

  /* Target + rhythm tokens */
  --vve-target:      44px;   /* house mobile minimum hit area */
  --vve-target-min:  24px;   /* absolute floor — remove buttons, dense controls */
  --vve-chip-h:      44px;   /* chip min-height mobile; 40px permitted >=768px */
  --vve-gap-card:    10px;   /* card/chip grid gap; 8px absolute floor */
  --vve-accent-bar:  3px;    /* song-card genre-family accent bar width */
  --vve-ring-w:      2px;    /* focus ring width */
  --vve-ring-off:    2px;    /* focus ring offset */

  /* Sticky chrome heights (drive scroll-padding, SC 2.4.11).
     --vve-header-h is the TOTAL fixed top chrome: booking bar + progress
     header. app.js re-measures both on load/resize and overwrites these two
     with real pixel values; the rem values below are the pre-JS reservation. */
  --vve-topbar-h: 2.75rem;   /* 44px booking bar — logo + Request Availability */
  --vve-header-h: 8.25rem;   /* booking bar + progress header (row + rail) */
  --vve-footer-h: 4.5rem;    /* 72px sticky CTA footer */

  /* Motion pipeline — every VVE transition/animation runs through these so the
     reduced-motion gate can neutralize ALL motion in one place. */
  --vve-dur-1: var(--dur-1);
  --vve-dur-2: var(--dur-2);
  --vve-dur-3: var(--dur-3);
  --vve-dur-fill: 0.7s;      /* meter fill (D25) */
  --vve-shift: 8px;          /* max reveal transform distance */
}

/* Tabbed-to controls must never hide under sticky bars (SC 2.4.11) */
html {
  scroll-padding-top:    calc(var(--vve-header-h) + 0.5rem);
  scroll-padding-bottom: calc(var(--vve-footer-h) + 0.5rem);
}

/* ============================================================================
   REDUCED MOTION — single global gate (§0 law 5). Two mirrored blocks:
   the OS media query AND the dev-strip toggle [data-reduced-motion="true"].
   Crossfade <=150ms or instant; no transforms > 8px; nothing auto-animates.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  :root { --vve-dur-1: 0.001s; --vve-dur-2: 0.001s; --vve-dur-3: 0.001s;
          --vve-dur-fill: 0.001s; --vve-shift: 0px; }
  .vve *, .vve *::before, .vve *::after {
    animation-duration: 0.001s !important;
    animation-delay: 0s !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001s !important;
    scroll-behavior: auto !important;
  }
}
html[data-reduced-motion="true"] { --vve-dur-1: 0.001s; --vve-dur-2: 0.001s;
  --vve-dur-3: 0.001s; --vve-dur-fill: 0.001s; --vve-shift: 0px; }
html[data-reduced-motion="true"] .vve *,
html[data-reduced-motion="true"] .vve *::before,
html[data-reduced-motion="true"] .vve *::after {
  animation-duration: 0.001s !important;
  animation-delay: 0s !important;
  animation-iteration-count: 1 !important;
  transition-duration: 0.001s !important;
  scroll-behavior: auto !important;
}

/* ============================================================================
   BASE — page ground, type, focus law
   ========================================================================== */
* { box-sizing: border-box; }

/* [hidden] must always win over component display rules */
.vve [hidden], [hidden].vve-cta, [hidden].vve-devstrip { display: none !important; }

body.vve {
  margin: 0;
  background: var(--bg);
  color: var(--ivory);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  min-height: 100dvh;
  -webkit-font-smoothing: antialiased;
}

/* Focus law (§0 law 4): ivory ring on dark ground, everywhere. Never removed
   without replacement. Ivory-surface contexts (print/brief) flip the ring. */
.vve :focus-visible {
  outline: var(--vve-ring-w) solid var(--ivory);
  outline-offset: var(--vve-ring-off);
  border-radius: var(--r-xs);
}
.vve .vve-on-ivory :focus-visible { outline-color: var(--crimson-line); }

/* Element resets at ZERO specificity (:where) so every component class wins */
:where(.vve) :where(button) {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}
:where(.vve) :where(fieldset) { border: 0; margin: 0; padding: 0; min-inline-size: 0; }
:where(.vve) :where(legend) { padding: 0; }
:where(.vve) :where(h1, h2, h3, h4) { margin: 0; line-height: var(--lh-tight); }
:where(.vve) :where(p) { margin: 0 0 var(--sp-4); }
:where(.vve) :where(ol, ul) { margin: 0; padding: 0; list-style: none; }
:where(.vve) :where(img, svg) { max-width: 100%; display: block; }
:where(.vve) :where(a) { color: var(--crimson-text); transition: color var(--vve-dur-1) var(--ease); }
:where(.vve) :where(a):hover { color: var(--ivory); text-decoration-thickness: 1px; text-underline-offset: 3px; }

/* ============================================================================
   SHARED UTILITIES (VVE-COMPONENTS §4)
   ========================================================================== */
.vve-visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.vve-skip {
  position: fixed;
  top: -100%;
  left: var(--sp-4);
  z-index: var(--z-skip);
  background: var(--ivory);
  color: var(--bg);
  font-family: var(--font-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  text-decoration: none;
  padding: var(--sp-3) var(--sp-5);
  border-radius: var(--r-sm);
  transition: top var(--vve-dur-1) var(--ease);
}
.vve-skip:focus-visible { top: var(--sp-4); outline-color: var(--crimson-line); }

/* Shared ivory ✓ glyph — always aria-hidden, always beside a text label */
.vve-check {
  width: 14px; height: 14px;
  flex: 0 0 auto;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Roadmap microlabel — names a not-yet-live side effect in plain language */
.vve-simnote {
  color: var(--smoke);
  font-size: var(--fs-micro);
  font-family: var(--font-label);
  letter-spacing: var(--ls-label);
}

/* Screen wrapper — owns the focus-target <h2> */
.vve-screen {
  min-height: calc(100dvh - var(--vve-header-h) - var(--vve-footer-h));
  padding: var(--sp-6) 0 var(--sp-8);
}
.vve-screen > h2, .vve-screen .vve-screen__title { outline: none; }

.vve-screen__eyebrow {
  font-family: var(--font-label);
  font-size: var(--fs-micro);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--smoke);
  margin: 0 0 var(--sp-2);
}
.vve-screen__title {
  font-family: var(--font-display);
  font-size: var(--fs-title);
  text-transform: uppercase;
  letter-spacing: 0.01em;
  color: var(--ivory);
  text-wrap: balance;
  margin: 0 0 var(--sp-3);
}
.vve-screen__lead { color: var(--ivory-80); max-width: var(--w-copy); }
/* Centered-frame lead (F2/F3/savedscreen/reveal confirm) — no inline styles */
.vve-screen__lead--center { margin-inline: auto; text-align: center; }
.vve-screen__hint { color: var(--smoke); font-size: var(--fs-small); }
.vve-screen__group { margin-top: var(--sp-6); }
/* Breathing room under frame-screen confirm rows (F3 microlabel etc.) */
.vve-frame-note { margin-top: var(--sp-4); }

/* Group label / legend rendering (question line above a control group) */
.vve-legend, .vve-cardgrid__legend, .vve-chipset__legend {
  display: block;
  font-family: var(--font-label);
  font-size: var(--fs-h4);
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--ivory);
  margin-bottom: var(--sp-3);
}
.vve-legend--hidden { position: absolute; clip-path: inset(50%); }

/* Optional open-text + generic text/time inputs (R4/C2/G3 notes, B2 fine-tune) */
.vve-field { margin-top: var(--sp-5); }
.vve-field__label {
  display: block;
  font-family: var(--font-label);
  font-size: var(--fs-small);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--ivory-80);
  margin-bottom: var(--sp-2);
}
.vve-field__optional { color: var(--smoke); text-transform: none; letter-spacing: 0; }
.vve-input, .vve-textarea {
  width: 100%;
  min-height: 48px;
  background: var(--panel);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  color: var(--ivory);
  font: inherit;
  padding: var(--sp-3) var(--sp-4);
}
.vve-textarea { min-height: 96px; resize: vertical; }
.vve-input::placeholder, .vve-textarea::placeholder { color: var(--smoke); }
.vve-input[type="time"] { color-scheme: dark; width: auto; }

/* Error rendering (ivory text + icon, never crimson-only) */
.vve-error {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  color: var(--ivory);
  font-size: var(--fs-small);
  margin-top: var(--sp-2);
}
.vve-error::before { content: "!"; flex: 0 0 auto; display: grid; place-items: center;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--crimson); color: var(--ivory);
  font-family: var(--font-logo); font-size: 13px; }
.vve [aria-invalid="true"] { border-color: var(--crimson-line); }

/* Two-column responsive layout helper (DNA rail on >=980px) */
.vve-layout { display: block; }

/* ============================================================================
   SHELL — header / stage / footer geometry
   ========================================================================== */
/* Booking bar — the site's primary conversion path, pinned above the wizard's
   own chrome so "Request Availability" is one tap from all 22 screens. */
.vve-topbar {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: calc(var(--z-sticky) + 1);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  min-height: var(--vve-topbar-h);
  padding: 0 var(--gutter);
  background: var(--bg);
  border-bottom: 1px solid var(--line);
}
/* ---- IDENTITY LOCKUP: mark + product name + presenter credit -------------
   The mark inherits currentColor from the anchor, so hover/focus recolours the
   whole lockup as one object. The crimson spindle pin is fixed inside the SVG —
   it is a filled shape, never a hairline (#9E1B32 on black is 2.50:1). */
/* Container is no longer the link — the mark opens the wizard, the presenter
   credit routes to the main site. Two links, never nested. */
.vve-lockup {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  min-width: 0;
}
.vve-lockup__home {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  text-decoration: none;
  color: var(--ivory);
}
.vve-lockup__byname {
  color: var(--crimson-text);
  font-weight: 600;
  text-decoration: none;
}
.vve-lockup__byname:hover,
.vve-lockup__byname:focus-visible { color: var(--ivory); }
.vve-lockup__mark {
  width: 30px; height: 30px;
  flex: none;
  display: block;
}
.vve-lockup__name {
  font-family: var(--font-display);
  font-size: var(--fs-small);
  line-height: 1;
  letter-spacing: 0.075em;
  text-transform: uppercase;
  white-space: nowrap;
}
.vve-lockup__tm {
  font-size: 0.5em;
  vertical-align: super;
  letter-spacing: 0;
  opacity: 0.75;
}
.vve-lockup__by {
  font-family: var(--font-label);
  font-size: 0.62rem;
  line-height: 1;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--smoke);
  white-space: nowrap;
}

/* Narrow phones: the presenter credit is the first thing to go — the mark and
   product name must never wrap or shrink below legibility. */
@media (max-width: 400px) {
  .vve-lockup__mark { width: 26px; height: 26px; }
  .vve-lockup__by { font-size: 0.56rem; letter-spacing: 0.08em; }
}
@media (max-width: 340px) {
  .vve-lockup__by { display: none; }
}
.vve-topbar__cta {
  display: inline-flex;
  align-items: center;
  min-height: 34px;
  padding: var(--sp-2) var(--sp-4);
  border-radius: var(--r-pill);
  background: var(--crimson);
  color: var(--ivory);
  font-family: var(--font-label);
  font-size: var(--fs-micro);
  font-weight: 600;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  transition: background var(--vve-dur-1) var(--ease);
}
.vve-topbar__cta:hover  { background: var(--crimson-hot); }
.vve-topbar__cta:active { background: var(--crimson-deep); }

.vve-header {
  position: fixed;
  inset: var(--vve-topbar-h) 0 auto 0;
  z-index: var(--z-sticky);
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line);
}
.vve-header__row {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: 3.25rem;
  padding: 0 var(--gutter);
  max-width: var(--w-max);
  margin: 0 auto;
}

.vve-stage {
  display: block;
  max-width: 640px;
  margin: 0 auto;
  padding: calc(var(--vve-header-h) + var(--sp-2)) var(--gutter) calc(var(--vve-footer-h) + var(--sp-6));
  outline: none;
}
/* Footer hidden (frame screens) — reclaim its padding */
.vve-stage--no-cta { padding-bottom: var(--sp-8); }
/* Step mount fade — opacity/transform only, ~180ms, never delays interactivity.
   reduced-motion zeroes animation-duration via the global .vve * gate above. */
.vve-stage--in { animation: vve-stage-in 180ms var(--ease) both; }
@keyframes vve-stage-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}
/* Screens carrying the fixed DNA strip (<980px): reserve the strip's collapsed
   height too, so the scroll floor clears strip + footer (C11 stacks above C14) */
.vve-stage:has(.vve-dna) {
  padding-bottom: calc(var(--vve-footer-h) + var(--vve-chip-h) + var(--sp-6));
}

/* ============================================================================
   C1 — PROGRESS RAIL  .vve-progress
   ========================================================================== */
.vve-progress {
  padding: 0 var(--gutter) var(--sp-2);
  max-width: var(--w-max);
  margin: 0 auto;
}
.vve-progress__label {
  display: flex;
  align-items: baseline;
  gap: var(--sp-3);
  flex: 1 1 auto;
  min-width: 0;
  justify-content: center;
}
.vve-progress__stage {
  font-family: var(--font-label);
  font-size: var(--fs-micro);
  font-weight: 600;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--ivory);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.vve-progress__count {
  font-family: var(--font-label);
  font-size: var(--fs-micro);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--smoke);           /* 5.09:1 — legal */
  white-space: nowrap;
}
.vve-progress__track {
  position: relative;
  height: 4px;
  border-radius: var(--r-pill);
  background: rgba(242, 239, 228, 0.10);
  overflow: hidden;
}
.vve-progress__fill {
  height: 100%;
  width: 0%;
  background: var(--crimson);    /* raw crimson — legal as decorative fill */
  border-radius: inherit;
  transition: width var(--vve-dur-3) var(--ease);
}
.vve-progress__dots {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: var(--sp-2);
  padding: 0 2px;
}
.vve-progress__dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--smoke);              /* upcoming */
  position: relative;
  transition: background-color var(--vve-dur-2) var(--ease),
              box-shadow var(--vve-dur-2) var(--ease);
}
.vve-progress__dot--done { background: var(--ivory); }          /* completed */
.vve-progress__dot[aria-current="step"] {
  background: var(--crimson);            /* current: crimson dot + ivory ring */
  box-shadow: 0 0 0 2px var(--ivory);    /* the ring carries state contrast */
}
.vve-progress__note {
  margin: var(--sp-2) 0 0;
  font-family: var(--font-label);
  font-size: var(--fs-micro);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--smoke);
  text-align: center;
}
/* --complete: Review/Reveal header state — no counter, no "Stage 7" */
.vve-progress__complete {
  margin: var(--sp-1) 0 0;
  text-align: center;
  font-family: var(--font-logo);
  font-size: var(--fs-small);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--ivory);
}
.vve-progress--complete .vve-progress__dots,
.vve-progress--complete .vve-progress__note { display: none; }

/* ============================================================================
   C15 — BACK CONTROL  .vve-back
   ========================================================================== */
.vve-back {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--vve-target);
  min-width: 70px;
  padding: 0 var(--sp-3) 0 var(--sp-1);
  font-family: var(--font-label);
  font-size: var(--fs-small);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--ivory-80);
  flex: 0 0 auto;
  transition: color var(--vve-dur-1) var(--ease);
}
.vve-back:hover { color: var(--ivory); }

/* ============================================================================
   C17 — SAVED TICK  .vve-saved
   ========================================================================== */
.vve-saved {
  flex: 0 0 auto;
  min-width: 70px;
  text-align: right;
}
.vve-saved__visual {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  font-family: var(--font-label);
  font-size: var(--fs-micro);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--smoke);           /* 5.09:1 */
  opacity: 0;
  transition: opacity var(--vve-dur-1) var(--ease);
}
.vve-saved__visual.is-on   { opacity: 1; }
.vve-saved__visual.is-held { opacity: 0.4; }   /* fades to 40%, stays legible */

/* ============================================================================
   C14 — STICKY CTA FOOTER  .vve-cta
   ========================================================================== */
.vve-cta {
  position: fixed;
  inset: auto 0 0 0;
  z-index: var(--z-sticky);
  min-height: var(--vve-footer-h);
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-top: 1px solid var(--line);
  padding-bottom: env(safe-area-inset-bottom, 0);
}
.vve-cta__inner {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  max-width: 640px;
  margin: 0 auto;
  padding: var(--sp-3) var(--gutter);
}
.vve-cta__note {
  margin: 0;
  font-size: var(--fs-micro);
  font-family: var(--font-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--smoke);
  text-align: center;
}
.vve-cta__primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  width: 100%;
  min-height: 48px;
  padding: var(--sp-2) var(--sp-6);
  border-radius: var(--r-sm);
  background: var(--crimson);            /* THE legal primary: crimson fill */
  color: var(--ivory);                   /* 6.87:1 */
  font-family: var(--font-label);
  font-size: var(--fs-body);
  font-weight: 600;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  transition: background var(--vve-dur-1) var(--ease);
}
.vve-cta__primary:hover  { background: var(--crimson-hot); }
.vve-cta__primary:active { background: var(--crimson-deep); }
/* Floor not yet met: enabled + focusable, never disabled (§2 matrix) */
.vve-cta__primary--waiting {
  background: var(--panel-2);
  color: var(--ivory-80);
  border: 1px solid var(--line-strong);
}
.vve-cta__primary--waiting:hover  { background: var(--panel-2); }
.vve-cta__primary--waiting:active { background: var(--panel); }
.vve-cta__secondary { display: flex; justify-content: center; }

/* ============================================================================
   C16 — SAVE & FINISH LATER  .vve-savelater
   ========================================================================== */
.vve-savelater {
  display: inline-flex;
  align-items: center;
  min-height: var(--vve-target);
  padding: 0 var(--sp-3);
  color: var(--ivory-80);
  font-size: var(--fs-small);
  font-family: var(--font-label);
  letter-spacing: 0.06em;
  transition: color var(--vve-dur-1) var(--ease);
}
.vve-savelater:hover, .vve-savelater:focus-visible {
  color: var(--ivory);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.vve-savelater--prominent {
  border: 1px solid var(--line-strong);
  border-radius: var(--r-pill);
  padding: 0 var(--sp-5);
}
/* Save-later confirmation body state (rendered into the stage by app.js) */
.vve-savedscreen { text-align: center; padding-top: var(--sp-9); }
.vve-savedscreen .vve-check { width: 28px; height: 28px; margin: 0 auto var(--sp-4); color: var(--ivory); }

/* ============================================================================
   C2 — SINGLE-SELECT CARD GRID  .vve-cardgrid / .vve-card
   (hidden native radio + label-card; selected = crimson fill + ivory ✓ + text)
   ========================================================================== */
.vve-cardgrid__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));   /* 2-across mobile, D7 */
  gap: var(--vve-gap-card);
}
.vve-cardgrid__grid--stack { grid-template-columns: minmax(0, 1fr); }
/* Presentational category heading inside the one radio grid (event-type picker).
   role=presentation — the fieldset/legend stays the accessible group. */
.vve-cardgrid__group {
  font-family: var(--font-label);
  font-size: var(--fs-micro);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--smoke);
  margin: var(--sp-4) 0 var(--sp-2);
}
.vve-cardgrid__group:first-child { margin-top: 0; }
.vve-card {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--sp-1);
  min-height: 72px;
  padding: var(--sp-4);
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  cursor: pointer;
  transition: background var(--vve-dur-1) var(--ease),
              border-color var(--vve-dur-1) var(--ease),
              box-shadow var(--vve-dur-1) var(--ease),
              transform var(--vve-dur-1) var(--ease);
}
@media (hover: hover) {
  .vve-card:hover { background: var(--panel-2); border-color: var(--line-strong); box-shadow: var(--shadow-1); transform: translateY(-1px); }
}
.vve-card__title {
  font-family: var(--font-label);
  font-size: var(--fs-body);
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--ivory);
}
.vve-card__meta { font-size: var(--fs-micro); color: var(--smoke); transition: color var(--vve-dur-1) var(--ease); }
.vve-card__state {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  font-family: var(--font-label);
  font-size: var(--fs-micro);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--ivory);
  visibility: hidden;              /* visibility, not display — no reflow */
  min-height: 1em;
}
/* Selected: crimson FILL + ivory text + ✓ + label (never color alone) */
.vve input:checked + .vve-card,
.vve input:checked + * .vve-card {
  background: var(--crimson);
  border-color: var(--crimson-line);
}
.vve input:checked + .vve-card .vve-card__title { color: var(--ivory); }
.vve input:checked + .vve-card .vve-card__meta  { color: var(--ivory-80); } /* never smoke-on-crimson */
.vve input:checked + .vve-card .vve-card__state { visibility: visible; }
.vve input:focus-visible + .vve-card {
  outline: var(--vve-ring-w) solid var(--ivory);
  outline-offset: var(--vve-ring-off);
}
/* --tile: M1-style cinematic gradient (decorative), text stays on the dark end */
.vve-card--tile {
  min-height: 96px;
  justify-content: flex-end;
  background: linear-gradient(160deg, var(--panel) 0%, var(--haze) 130%);
}
.vve input:checked + .vve-card--tile { background: var(--crimson); }
/* --compact: chip-height confirm rows */
.vve-card--compact { min-height: var(--vve-target); flex-direction: row; align-items: center; gap: var(--sp-3); }

/* --budget (B3): the money-sign comfort-band card. Reuses the C2 radio-group
   anatomy + selected-state contract; adds the sign scale + typical-range line.
   Crimson is FILL/ACCENT only — range text is --crimson-text (legal 4.59:1) or
   ivory when the card is filled, never a hairline. */
.vve-card--budget {
  align-items: flex-start;
  justify-content: flex-start;
  gap: var(--sp-2);
  min-height: 96px;
  text-align: left;
}
.vve-tier__signs {
  font-family: var(--font-display);
  font-size: 1.5rem;
  line-height: 1;
  letter-spacing: 0.12em;
}
.vve-tier__signs .on  { color: var(--crimson-text); transition: color var(--vve-dur-1) var(--ease); }          /* filled = crimson accent */
.vve-tier__signs .off { color: var(--smoke); opacity: 0.6; transition: color var(--vve-dur-1) var(--ease), opacity var(--vve-dur-1) var(--ease); }   /* remainder of the scale */
.vve-tier__name { display: flex; align-items: baseline; gap: var(--sp-2); flex-wrap: wrap; }
.vve-tier__sub {
  font-family: var(--font-label);
  font-size: var(--fs-micro);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: color-mix(in srgb, var(--crimson-text) 80%, var(--ivory));
}
.vve-tier__range {
  font-family: var(--font-label);
  font-size: var(--fs-small);
  font-weight: 500;
  color: var(--ivory-80);
  transition: color var(--vve-dur-1) var(--ease);
}
.vve-tier__range--real { color: var(--ivory); }                /* the one confirmed number */
.vve-tier__range-tag {
  font-weight: 400;
  font-size: var(--fs-micro);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--smoke);
}
.vve-tier__note {
  font-size: var(--fs-micro);
  color: var(--ivory-80);
  border-top: 1px solid var(--line);
  padding-top: var(--sp-2);
  margin-top: var(--sp-1);
}
.vve-card--budget-unsure { min-height: var(--vve-target); }
/* Selected fill: every accent flips to ivory so nothing rides crimson-on-crimson */
.vve input:checked + .vve-card--budget .vve-tier__signs .on  { color: var(--ivory); }
.vve input:checked + .vve-card--budget .vve-tier__signs .off { color: var(--ivory); opacity: 0.4; }
.vve input:checked + .vve-card--budget .vve-tier__sub,
.vve input:checked + .vve-card--budget .vve-tier__range { color: var(--ivory); }
.vve input:checked + .vve-card--budget .vve-tier__range-tag { color: var(--ivory-80); }
.vve input:checked + .vve-card--budget .vve-tier__note { color: var(--ivory-80); border-top-color: var(--crimson-line); }

/* B3 orientation hint (text-only, never an auto-select) + persistent caveat */
.vve-budget__hint {
  font-size: var(--fs-small);
  color: var(--ivory-80);
  margin-bottom: var(--sp-3);
}
.vve-budget__caveat {
  font-size: var(--fs-small);
  color: var(--smoke);
  margin-top: var(--sp-4);
  line-height: 1.5;
}
.vve-budget__more { margin-top: var(--sp-3); }
.vve-budget__more > summary {
  font-family: var(--font-label);
  font-size: var(--fs-small);
  letter-spacing: var(--ls-label);
  color: var(--crimson-text);
  cursor: pointer;
}
.vve-budget__more > summary:focus-visible { outline: var(--vve-ring-w) solid var(--ivory); outline-offset: var(--vve-ring-off); }
.vve-budget__more > p { font-size: var(--fs-small); color: var(--ivory-80); margin-top: var(--sp-2); line-height: 1.55; }

/* Reveal budget echo (D6: comfort band, never a quote) */
.vve-reveal__budget { display: flex; align-items: baseline; gap: var(--sp-3); flex-wrap: wrap; }
.vve-reveal__budget-signs {
  font-family: var(--font-display);
  font-size: 1.75rem;
  line-height: 1;
  letter-spacing: 0.12em;
  color: var(--crimson-text);
}
.vve-reveal__budget-line { display: flex; align-items: baseline; gap: var(--sp-2); flex-wrap: wrap; }
.vve-reveal__budget-name { font-family: var(--font-display); font-size: var(--fs-h3, 1.25rem); color: var(--ivory); letter-spacing: 0.02em; }
.vve-reveal__budget-range { font-family: var(--font-label); font-size: var(--fs-small); color: var(--crimson-text); }
.vve-reveal__budget-note { color: var(--ivory-80); margin-top: var(--sp-2); }

/* ============================================================================
   C3 — MULTI-SELECT CHIP SET  .vve-chipset / .vve-chip
   (hidden native checkbox build OR [aria-pressed] button build — same skin)
   ========================================================================== */
.vve-chipset__row {
  display: flex;
  flex-wrap: wrap;                 /* wrapping row — never horizontal-scroll-only */
  gap: 8px;
}
.vve-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--vve-chip-h);
  padding: 0 var(--sp-4);
  border-radius: var(--r-pill);
  background: var(--panel);
  border: 1px solid var(--line);
  font-family: var(--font-label);
  font-size: var(--fs-small);
  font-weight: 500;
  letter-spacing: 0.05em;
  color: var(--ivory);
  cursor: pointer;
  transition: background var(--vve-dur-1) var(--ease),
              border-color var(--vve-dur-1) var(--ease);
}
@media (hover: hover) {
  .vve-chip:hover { background: var(--panel-2); border-color: var(--line-strong); }
}
.vve-chip .vve-check { visibility: hidden; width: 0; transition: none; } /* zero width until selected */
/* Selected chip — checkbox build */
.vve input:checked + .vve-chip {
  background: var(--crimson);
  border-color: var(--crimson-line);
  color: var(--ivory);
}
.vve input:checked + .vve-chip .vve-check { visibility: visible; width: 14px; }
.vve input:focus-visible + .vve-chip {
  outline: var(--vve-ring-w) solid var(--ivory);
  outline-offset: var(--vve-ring-off);
}
/* Selected chip — button build */
.vve-chip[aria-pressed="true"] {
  background: var(--crimson);
  border-color: var(--crimson-line);
  color: var(--ivory);
}
.vve-chip[aria-pressed="true"] .vve-check { visibility: visible; width: 14px; }
/* Quiet suggestion chip (pre-suggested, not pre-selected — BR2 G1) */
.vve-chip--suggested { border-style: dashed; border-color: var(--line-strong); }
.vve-chip--suggested::after {
  content: "Suggested";
  font-size: var(--fs-micro);
  color: var(--smoke);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
}

/* ============================================================================
   C4 — TRI-STATE AFFINITY CARD  .vve-tricard
   (fieldset per card; visible 3-chip radio row is the accessible baseline;
    card-face tap-to-cycle is a pointer enhancement, aria-hidden)
   ========================================================================== */
.vve-tricard-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--vve-gap-card);
}
.vve-tricard {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: var(--sp-4);
  transition: background var(--vve-dur-1) var(--ease),
              border-color var(--vve-dur-1) var(--ease),
              opacity var(--vve-dur-1) var(--ease),
              transform var(--vve-dur-1) var(--ease);
}
/* "Not us" swipe-away: the card fades and lifts, a fresh name takes its slot.
   JS only adds these when motion is allowed; --vve-dur-1 also zeroes under the
   global reduced-motion gate, so the swap is instant there. */
.vve-tricard--leaving { opacity: 0; transform: translateY(-8px) scale(0.98); pointer-events: none; }
.vve-tricard--entering { opacity: 0; transform: translateY(8px); }
.vve-tricard__face {
  display: block;
  width: 100%;
  min-height: 56px;
  text-align: left;
  cursor: pointer;
  margin-bottom: var(--sp-3);
}
.vve-tricard__name {
  font-family: var(--font-display);       /* the typography IS the artwork (D9) */
  font-size: var(--fs-h3);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--ivory);
  transition: color var(--vve-dur-1) var(--ease);
}
.vve-tricard__meta { font-size: var(--fs-micro); color: var(--smoke); margin-top: 2px; transition: color var(--vve-dur-1) var(--ease); }
.vve-tricard__chips { display: flex; flex-wrap: wrap; gap: 8px; }
/* The three states — the LABEL TEXT carries the distinction, never color alone */
.vve-tricard--feels { background: var(--crimson); border-color: var(--crimson-line); }
.vve-tricard--feels .vve-tricard__name { color: var(--ivory); }
.vve-tricard--feels .vve-tricard__meta { color: var(--ivory-80); }
.vve-tricard--maybe { background: var(--panel-2); border-color: var(--line-strong); }
.vve-tricard--notus { border-color: var(--smoke); }
.vve-tricard--notus .vve-tricard__name { color: var(--ivory-60); }
/* Chip skins inside a crimson-filled card need a legal ground */
.vve-tricard--feels .vve-chip { background: color-mix(in srgb, var(--bg) 35%, var(--crimson)); border-color: rgba(242,239,228,0.35); }
.vve-tricard--feels input:checked + .vve-chip { background: var(--bg); border-color: var(--ivory); }
/* "Maybe" selected chip: panel-2 fill + ✓ + label (per spec) */
.vve-tricard--maybe input:checked + .vve-chip { background: var(--panel-2); border-color: var(--ivory-60); }
/* --chip modifier (M4): tri-state collapses to a plain chip-row — card face omitted */
.vve-tricard--chip { padding: var(--sp-3); }
.vve-tricard--chip .vve-tricard__face { display: none; }
.vve-tricard--chip .vve-tricard__name { font-family: var(--font-label); font-size: var(--fs-body); text-transform: none; }

/* ============================================================================
   C5 — SLIDER (native-first)  .vve-slider
   Track smoke, filled range --crimson-line, thumb ivory. JS syncs the fill via
   --vve-slider-fill (0–100) and mirrors aria-valuetext into __value.
   ========================================================================== */
.vve-slider { margin-top: var(--sp-4); }
.vve-slider__label {
  display: block;
  font-family: var(--font-label);
  font-size: var(--fs-h4);
  font-weight: 600;
  color: var(--ivory);
  margin-bottom: var(--sp-3);
}
.vve-slider__input {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: var(--vve-target);       /* padded 44px hit area */
  background: transparent;
  cursor: pointer;
  margin: 0;
}
.vve-slider__input::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: var(--r-pill);
  background: linear-gradient(to right,
    var(--crimson-line) 0%,
    var(--crimson-line) calc(var(--vve-slider-fill, 0) * 1%),
    var(--smoke)        calc(var(--vve-slider-fill, 0) * 1%),
    var(--smoke)        100%);
}
.vve-slider__input::-moz-range-track {
  height: 4px; border-radius: var(--r-pill); background: var(--smoke);
}
.vve-slider__input::-moz-range-progress {
  height: 4px; border-radius: var(--r-pill); background: var(--crimson-line);
}
.vve-slider__input::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 24px; height: 24px;
  margin-top: -10px;
  border-radius: 50%;
  background: var(--ivory);
  border: 0;
  box-shadow: var(--shadow-1);
  transition: box-shadow var(--vve-dur-1) var(--ease), transform var(--vve-dur-1) var(--ease);
}
.vve-slider__input::-moz-range-thumb {
  width: 24px; height: 24px;
  border-radius: 50%;
  background: var(--ivory);
  border: 0;
  box-shadow: var(--shadow-1);
  transition: box-shadow var(--vve-dur-1) var(--ease), transform var(--vve-dur-1) var(--ease);
}
@media (hover: hover) {
  .vve-slider__input:hover::-webkit-slider-thumb { box-shadow: var(--glow-crimson-soft); }
}
.vve-slider__input:active::-webkit-slider-thumb { transform: scale(1.08); }
.vve-slider__input:active::-moz-range-thumb { transform: scale(1.08); }
.vve-slider__input:focus-visible { outline: none; }
.vve-slider__input:focus-visible::-webkit-slider-thumb {
  box-shadow: 0 0 0 var(--vve-ring-w) var(--bg), 0 0 0 calc(var(--vve-ring-w) * 2) var(--ivory);
}
.vve-slider__input:focus-visible::-moz-range-thumb {
  box-shadow: 0 0 0 var(--vve-ring-w) var(--bg), 0 0 0 calc(var(--vve-ring-w) * 2) var(--ivory);
}
.vve-slider__value {
  margin-top: var(--sp-2);
  color: var(--ivory);
  font-size: var(--fs-small);
  min-height: 1.4em;               /* value line never reflows */
}
.vve-slider__ends {
  display: flex;
  justify-content: space-between;
  font-size: var(--fs-micro);
  color: var(--smoke);
  margin-top: 2px;
}
.vve-slider__ticks {
  display: flex;
  justify-content: space-between;
  padding: 0 10px;
  margin-top: -14px;
  pointer-events: none;
}
.vve-slider__tick { width: 4px; height: 4px; border-radius: 50%; background: var(--smoke); }

/* ============================================================================
   C6 — ENERGY-ARC SEGMENT LIST  .vve-arc
   ========================================================================== */
.vve-arc { display: flex; flex-direction: column; gap: var(--vve-gap-card); }
.vve-arc__segment {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: var(--sp-4);
}
.vve-arc__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-bottom: var(--sp-3);
}
.vve-arc__name {
  font-family: var(--font-label);
  font-size: var(--fs-h4);
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ivory);
}
.vve-arc__time { font-size: var(--fs-micro); color: var(--smoke); }
/* Intensity stepper: discrete step blocks + the label as TEXT */
.vve-arc__stepper { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; }
.vve-arc__steps { display: flex; gap: 4px; }
.vve-arc__step {
  width: var(--vve-target-min);
  height: var(--vve-target-min);
  min-width: var(--vve-target-min);
  border-radius: var(--r-xs);
  background: var(--panel-2);
  border: 1px solid var(--line);
  cursor: pointer;
  transition: background var(--vve-dur-1) var(--ease);
}
.vve-arc__step--on { background: var(--crimson); border-color: var(--crimson-line); } /* fill = legal */
.vve input:checked + .vve-arc__step { background: var(--crimson); border-color: var(--crimson-line); }
.vve input:focus-visible + .vve-arc__step {
  outline: var(--vve-ring-w) solid var(--ivory);
  outline-offset: var(--vve-ring-off);
}
.vve-arc__level {
  font-family: var(--font-label);
  font-size: var(--fs-small);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--ivory);              /* "Building" — the text carries the state */
  min-width: 8ch;
}
.vve-arc__controls { display: flex; gap: 8px; margin-top: var(--sp-3); flex-wrap: wrap; }
.vve-arc__move, .vve-arc__add, .vve-arc__remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--vve-target);
  padding: 0 var(--sp-4);
  border-radius: var(--r-pill);
  border: 1px solid var(--line-strong);
  background: var(--panel);
  color: var(--ivory);
  font-family: var(--font-label);
  font-size: var(--fs-small);
  letter-spacing: 0.06em;
  transition: background var(--vve-dur-1) var(--ease);
}
@media (hover: hover) {
  .vve-arc__move:hover, .vve-arc__add:hover, .vve-arc__remove:hover { background: var(--panel-2); }
}
.vve-arc__remove { color: var(--ivory-80); min-width: var(--vve-target); }
.vve-arc__add { align-self: flex-start; }
/* Curve preview — decorative; data table is the accessible rendering */
.vve-arc__curve { margin: var(--sp-4) 0; }
.vve-arc__curve svg { width: 100%; height: auto; }
.vve-arc__curve path { fill: none; stroke: var(--crimson-line); stroke-width: 2; }
.vve-arc__table { width: 100%; border-collapse: collapse; margin-top: var(--sp-4); }
.vve-arc__table caption { text-align: left; color: var(--smoke); font-size: var(--fs-micro);
  letter-spacing: var(--ls-label); text-transform: uppercase; padding-bottom: var(--sp-2); }
.vve-arc__table th, .vve-arc__table td {
  text-align: left;
  padding: var(--sp-2) var(--sp-3);
  border-bottom: 1px solid var(--line);
  font-size: var(--fs-small);
}
.vve-arc__table th { color: var(--smoke); font-family: var(--font-label);
  letter-spacing: var(--ls-label); text-transform: uppercase; font-weight: 500; }
.vve-arc__table td { color: var(--ivory); }

/* ============================================================================
   C7 — SONG CARD  .vve-song  (library + manual + blocked + readonly variants)
   Text-based cards are THE design (D9) — no artwork slot exists.
   ========================================================================== */
.vve-songlist {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--vve-gap-card);
}
.vve-song {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: stretch;
  background: var(--panel);
  border: 1px solid var(--line-strong);
  border-left: var(--vve-accent-bar) solid var(--family-accent, var(--crimson-line));
  border-radius: var(--r-sm);
  min-height: 88px;
  transition: background var(--vve-dur-1) var(--ease),
              border-color var(--vve-dur-1) var(--ease);
}
@media (hover: hover) { .vve-song:hover { background: var(--panel-2); } }
.vve-song__body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
  padding: var(--sp-3) var(--sp-4);
  cursor: pointer;
  min-width: 0;
}
.vve-song__title {
  font-family: var(--font-display);        /* typography IS the artwork */
  font-size: var(--fs-h4);
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--ivory);
  overflow-wrap: anywhere;
}
.vve-song__artist { color: var(--smoke); font-size: var(--fs-small); }
.vve-song__tags { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: 2px; }
.vve-song__family, .vve-song__decade {
  font-family: var(--font-label);
  font-size: var(--fs-micro);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--smoke);                     /* family name as TEXT — never color-only */
}
.vve-song__state {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  font-family: var(--font-label);
  font-size: var(--fs-micro);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--ivory);
  visibility: hidden;
  min-height: 1em;
  margin-top: 2px;
}
.vve-song__actions {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  padding: var(--sp-2);
  border-left: 1px solid var(--line);
}
.vve-song__reject, .vve-song__expand, .vve-song__remove, .vve-song__unblock {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--vve-target);
  min-width: var(--vve-target);
  padding: 0 var(--sp-3);
  border-radius: var(--r-sm);
  color: var(--ivory-80);
  font-family: var(--font-label);
  font-size: var(--fs-micro);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  transition: background var(--vve-dur-1) var(--ease), color var(--vve-dur-1) var(--ease);
}
@media (hover: hover) {
  .vve-song__reject:hover, .vve-song__expand:hover,
  .vve-song__remove:hover, .vve-song__unblock:hover { background: var(--panel-2); color: var(--ivory); }
}
/* Selected: crimson-line border + ✓ + "Selected" TEXT (D9: border, not full fill) */
.vve input:checked ~ .vve-song__body .vve-song__state,
.vve-song--is-selected .vve-song__state { visibility: visible; }
.vve input:checked ~ .vve-song__body .vve-song__state { color: var(--ivory); }
.vve-song:has(input:checked), .vve-song--is-selected {
  border-color: var(--crimson-line);
  border-left-color: var(--crimson-line);
}
.vve-song input:focus-visible ~ .vve-song__body {
  outline: var(--vve-ring-w) solid var(--ivory);
  outline-offset: calc(-1 * var(--vve-ring-w));
  border-radius: var(--r-sm);
}
/* --manual: visually identical; family name matches non-manual (--smoke) for AA contrast */
.vve-song--manual .vve-song__family { color: var(--smoke); }
/* --is-blocked (G2 hard-no): smoke border + strike + "Blocked" TEXT label */
.vve-song--is-blocked { border-color: var(--smoke); border-left-color: var(--smoke); }
.vve-song--is-blocked .vve-song__title {
  color: var(--ivory-60);
  text-decoration: line-through;
  text-decoration-thickness: 2px;
}
.vve-song--is-blocked .vve-song__state { visibility: visible; color: var(--ivory-80); }
/* --readonly (V3): no inputs; must-play pin = crimson-line dot + TEXT tag */
.vve-song--readonly { grid-template-columns: minmax(0, 1fr); }
.vve-song--readonly .vve-song__body { cursor: default; }
.vve-song__pin {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-family: var(--font-label);
  font-size: var(--fs-micro);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--ivory);
}
.vve-song__pin::before {
  content: "";
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--crimson-line);
}
.vve-song__quote {
  margin: var(--sp-2) 0 0;
  padding-left: var(--sp-3);
  border-left: 2px solid var(--line-strong);
  color: var(--ivory-80);
  font-style: italic;
  font-size: var(--fs-small);
}
/* Detail expansion — inline disclosure, never a modal */
.vve-song__detail {
  grid-column: 1 / -1;
  border-top: 1px solid var(--line);
  padding: var(--sp-4);
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
}
.vve-song__detail[hidden] { display: none; }

/* ============================================================================
   CURATION / THE FINAL CUT — crate groups + compact "more like this" links
   (reuses the C-song card for crate records; links are lighter pill rows)
   ========================================================================== */
.vve-curation__crate { display: flex; flex-direction: column; gap: var(--sp-5); }
.vve-curation__group { display: flex; flex-direction: column; gap: var(--sp-3); }
/* Add-to-crate — the crate's own path into the library. Outline, never crimson
   fill: the crimson primary is reserved for "Lock the crate" in the footer, so
   this reads as a secondary action, not a second CTA competing with it. */
.vve-curation__addrow { display: flex; }
.vve-curation__add {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  min-height: var(--vve-target); padding: 0 var(--sp-4);
  background: transparent; border: 1px solid var(--line-strong); border-radius: var(--r-pill);
  color: var(--ivory); cursor: pointer;
  font-family: var(--font-label); font-size: var(--fs-micro);
  letter-spacing: var(--ls-label); text-transform: uppercase;
  transition: background var(--vve-dur-1) var(--ease), border-color var(--vve-dur-1) var(--ease);
}
.vve-curation__add-icon { font-size: 18px; line-height: 1; color: var(--ivory-80); }
@media (hover: hover) { .vve-curation__add:hover { border-color: var(--ivory-60); background: var(--panel-2); } }
.vve-curation__add:focus-visible { outline: 2px solid var(--ivory); outline-offset: 2px; }
/* hero — the empty state's primary action, where it is the ONLY way forward */
.vve-curation__add--hero {
  width: 100%; min-height: calc(var(--vve-target) + var(--sp-2));
  margin-top: var(--sp-3); border-style: dashed; border-color: var(--ivory-60); color: var(--ivory);
}
.vve-curation__linkhint {
  font-family: var(--font-label); font-size: var(--fs-micro);
  letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--smoke);
}
.vve-curation__links {
  display: flex; flex-wrap: wrap; gap: var(--sp-2);
  margin: 0; padding: 0; list-style: none;
}
.vve-curation__link { position: relative; }
.vve-curation__link-body {
  display: inline-flex; flex-direction: column; justify-content: center; gap: 1px;
  min-height: var(--vve-target);            /* 44px — primary tap-to-add control */
  padding: 6px var(--sp-3); cursor: pointer;
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: var(--r-pill);
  transition: background var(--vve-dur-1) var(--ease), border-color var(--vve-dur-1) var(--ease);
}
@media (hover: hover) { .vve-curation__link-body:hover { border-color: var(--ivory-60); } }
.vve-curation__link-title {
  font-family: var(--font-label); font-size: var(--fs-small);
  letter-spacing: 0.01em; color: var(--ivory);
}
.vve-curation__link-meta { font-size: var(--fs-micro); color: var(--smoke); }
.vve-curation__link .vve-song__state { margin-top: 0; }
.vve input:checked + .vve-curation__link-body { background: var(--crimson); border-color: var(--crimson-line); }
.vve input:checked + .vve-curation__link-body .vve-curation__link-title,
.vve input:checked + .vve-curation__link-body .vve-curation__link-meta { color: var(--ivory); }
.vve input:checked + .vve-curation__link-body .vve-song__state { visibility: visible; color: var(--ivory); }
.vve-curation__link input:focus-visible + .vve-curation__link-body {
  outline: 2px solid var(--ivory); outline-offset: 2px;
}

/* ============================================================================
   RUN OF SHOW — moment timeline + event-needs extras
   ========================================================================== */
.vve-ros__legend { margin-top: var(--sp-6); }
.vve-ros__flowcard {
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-sm);
  padding: var(--sp-4); margin-top: var(--sp-4);
}
.vve-ros__flowlist {
  list-style: none; margin: var(--sp-3) 0 0; padding: 0;
  display: flex; flex-direction: column; gap: var(--sp-2);
}
.vve-ros__flowlist li {
  position: relative; padding-left: var(--sp-4); color: var(--ivory-80); font-size: var(--fs-small);
}
.vve-ros__flowlist li::before {
  content: ""; position: absolute; left: 0; top: 0.55em;
  width: 5px; height: 5px; border-radius: 50%; background: var(--crimson);
}
.vve-ros__flownote { margin-top: var(--sp-3); color: var(--smoke); font-size: var(--fs-micro); }

.vve-ros__timeline { display: flex; flex-direction: column; gap: var(--vve-gap-card); margin-top: var(--sp-3); }
.vve-ros__moment {
  position: relative; background: var(--panel); border: 1px solid var(--line-strong);
  border-left: var(--vve-accent-bar) solid var(--crimson-line);
  border-radius: var(--r-sm); padding: var(--sp-3) var(--sp-4);
}
.vve-ros__moment-head { display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-2); }
.vve-ros__moment-title {
  font-family: var(--font-display); font-size: var(--fs-h4); letter-spacing: 0.03em;
  text-transform: uppercase; color: var(--ivory); flex: 1 1 auto; min-width: 0;
}
.vve-ros__yours, .vve-ros__varies {
  font-family: var(--font-label); font-size: var(--fs-micro); letter-spacing: var(--ls-label);
  text-transform: uppercase; padding: 2px 8px; border-radius: var(--r-pill);
}
.vve-ros__yours { color: var(--ivory-80); border: 1px solid var(--line); }
.vve-ros__varies { color: var(--smoke); border: 1px dashed rgba(242,239,228,0.24); }
.vve-ros__flag { color: var(--smoke); font-size: var(--fs-micro); margin: var(--sp-2) 0 0; }
.vve-ros__moment-body { display: flex; flex-direction: column; gap: var(--sp-2); margin-top: var(--sp-3); }
.vve-ros__mic {
  display: inline-flex; align-items: center; gap: var(--sp-2); align-self: flex-start;
  min-height: var(--vve-target); padding: 4px 12px; cursor: pointer;
  border: 1px solid var(--line); border-radius: var(--r-pill);
  font-family: var(--font-label); font-size: var(--fs-micro); letter-spacing: var(--ls-label);
  text-transform: uppercase; color: var(--smoke);
}
.vve input:checked + .vve-ros__mic { background: var(--crimson); border-color: var(--crimson-line); color: var(--ivory); }
.vve-ros__mic .vve-check { visibility: hidden; width: 0; transition: width .12s var(--ease); }
.vve input:checked + .vve-ros__mic .vve-check { visibility: visible; width: 14px; }
.vve input:focus-visible + .vve-ros__mic { outline: 2px solid var(--ivory); outline-offset: 2px; }
.vve-ros__note { width: 100%; min-height: 3em; }
.vve-ros__moment-tools { display: flex; gap: var(--sp-2); margin-top: var(--sp-3); }
.vve-ros__tool {
  min-height: var(--vve-target); min-width: var(--vve-target); padding: 0 12px;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; border: 1px solid var(--line); border-radius: var(--r-sm);
  color: var(--ivory-80); font-family: var(--font-label); font-size: var(--fs-micro);
  letter-spacing: var(--ls-label); text-transform: uppercase; cursor: pointer;
}
.vve-ros__tool[disabled] { opacity: 0.35; cursor: default; }
.vve-ros__tool--remove { margin-left: auto; }
@media (hover: hover) { .vve-ros__tool:not([disabled]):hover { border-color: var(--ivory-60); } }

.vve-ros__add-row { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-3); }
.vve-ros__add-row .vve-input { flex: 1 1 12rem; }
.vve-ros__kind { flex: 0 0 auto; width: auto; }

.vve-ros__extras { margin-top: var(--sp-6); }
.vve-ros__extra { padding: var(--sp-4) 0; border-top: 1px solid var(--line); }
.vve-ros__extra-label { font-family: var(--font-label); font-size: var(--fs-small); letter-spacing: 0.02em; color: var(--ivory); text-transform: uppercase; }
.vve-ros__extra-caption { color: var(--smoke); font-size: var(--fs-small); margin: var(--sp-2) 0 var(--sp-3); max-width: var(--w-copy); }
.vve-ros__extra-choice { display: flex; flex-wrap: wrap; gap: var(--sp-2); }

/* ============================================================================
   C8 — SEARCH BAR + SUGGESTION GRID  .vve-search
   ========================================================================== */
/* Elevated above the sticky CTA footer (--z-sticky) so the typeahead dropdown
   clears it — the bar itself never overlaps the footer (top- vs bottom-sticky). */
.vve-search { position: sticky; top: var(--vve-header-h); z-index: calc(var(--z-sticky, 200) + 2);
  background: color-mix(in srgb, var(--bg) 94%, transparent);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  padding: var(--sp-2) 0;
  margin-bottom: var(--sp-4);
}
.vve-search--static { position: static; background: none; backdrop-filter: none; padding: 0; }
.vve-search__label {
  display: block;
  font-family: var(--font-label);
  font-size: var(--fs-small);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--ivory-80);
  margin-bottom: var(--sp-2);
}
.vve-search__box { position: relative; }
.vve-search__input {
  width: 100%;
  height: 48px;
  background: var(--panel);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  color: var(--ivory);
  font: inherit;
  padding: 0 var(--vve-target) 0 var(--sp-4);
}
.vve-search__input::placeholder { color: var(--smoke); }
.vve-search__input::-webkit-search-cancel-button { display: none; }
.vve-search__clear {
  position: absolute;
  right: 4px;
  top: 50%;
  transform: translateY(-50%);
  min-width: var(--vve-target-min);
  min-height: var(--vve-target-min);
  width: 40px; height: 40px;
  display: grid;
  place-items: center;
  border-radius: var(--r-sm);
  color: var(--ivory-80);
  font-size: 18px;
  line-height: 1;
}
.vve-search__clear[hidden] { display: none; }
.vve-search__status {
  margin-top: var(--sp-2);
  font-size: var(--fs-micro);
  font-family: var(--font-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--smoke);
  min-height: 1.2em;
}
/* Typeahead dropdown — floats right under the input (combobox listbox). */
.vve-search__drop {
  position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 30;
  margin: 0; padding: 4px; list-style: none;
  background: var(--panel); border: 1px solid var(--line-strong); border-radius: var(--r-sm);
  box-shadow: 0 14px 36px rgba(0, 0, 0, 0.55);
  max-height: 46vh; overflow-y: auto; -webkit-overflow-scrolling: touch;
}
.vve-search__drop[hidden] { display: none; }
.vve-search__opt {
  display: flex; align-items: center; gap: var(--sp-3);
  min-height: var(--vve-target); padding: 6px var(--sp-3);
  border-radius: var(--r-sm); cursor: pointer;
}
.vve-search__opt:hover, .vve-search__opt.is-active { background: var(--panel-2); }
.vve-search__opt.is-active { outline: 1px solid var(--ivory-60); outline-offset: -1px; }
.vve-search__opt-body { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1 1 auto; }
.vve-search__opt-title {
  font-family: var(--font-label); font-size: var(--fs-small); color: var(--ivory);
  letter-spacing: 0.01em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.vve-search__opt-meta {
  font-size: var(--fs-micro); color: var(--smoke);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.vve-search__opt-add {
  flex: 0 0 auto; font-family: var(--font-label); font-size: var(--fs-micro);
  letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--crimson-text, var(--crimson));
}
.vve-search__opt--manual .vve-search__opt-title { color: var(--ivory-80); font-style: italic; }

/* Set-aside recovery — the "Not this" records, one tap to bring back. */
.vve-setaside__list { list-style: none; margin: var(--sp-2) 0 0; padding: 0; display: flex; flex-direction: column; gap: var(--sp-2); }
.vve-setaside__item {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: 6px var(--sp-3); border: 1px dashed var(--line); border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--panel) 60%, transparent);
}
.vve-setaside__body { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1 1 auto; }
.vve-setaside__title { font-family: var(--font-label); font-size: var(--fs-small); color: var(--ivory-80); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vve-setaside__artist { font-size: var(--fs-micro); color: var(--smoke); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vve-setaside__back {
  flex: 0 0 auto; min-height: var(--vve-target); padding: 0 var(--sp-3);
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; border: 1px solid var(--line-strong); border-radius: var(--r-pill);
  color: var(--ivory); font-family: var(--font-label); font-size: var(--fs-micro);
  letter-spacing: var(--ls-label); text-transform: uppercase; cursor: pointer;
}
@media (hover: hover) { .vve-setaside__back:hover { border-color: var(--ivory-60); background: var(--panel-2); } }
.vve-setaside__back:focus-visible { outline: 2px solid var(--ivory); outline-offset: 2px; }
/* The bloom: refreshed suggestion cards crossfade <=150ms (JS adds/removes) */
.vve-search__grid .vve-song--incoming { animation: vve-bloom-in 0.15s var(--ease) both; }
@keyframes vve-bloom-in { from { opacity: 0; } to { opacity: 1; } }

/* ============================================================================
   C9 — ROLE-CHIP ROW  .vve-rolechips  (chip skin from C3; radio semantics)
   ========================================================================== */
.vve-rolechips { display: flex; flex-wrap: wrap; gap: 8px; }
.vve-rolechips .vve-chip { font-size: var(--fs-micro); letter-spacing: var(--ls-label); text-transform: uppercase; }

/* ============================================================================
   C10 — COUNTER / STATUS CHIP  .vve-counter
   ========================================================================== */
.vve-counter {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  padding: var(--sp-2) var(--sp-4);
  color: var(--smoke);
  font-size: var(--fs-small);
}
.vve-counter__num {
  font-family: var(--font-logo);
  font-size: var(--fs-lead);
  color: var(--ivory);
  letter-spacing: 0.04em;
}
.vve-counter--milestone {
  display: flex;
  justify-content: center;
  padding: var(--sp-3) var(--sp-5);
  margin: var(--sp-4) 0;
}
.vve-counter--inline { padding: var(--sp-1) var(--sp-3); font-size: var(--fs-micro); }
/* Milestone pulse — once, <=300ms, border only (the permitted micro-dopamine) */
.vve-counter--pulse { animation: vve-counter-pulse 0.3s var(--ease) 1; }
@keyframes vve-counter-pulse {
  0%, 100% { border-color: var(--line); }
  50%      { border-color: var(--crimson-line); }
}

/* ============================================================================
   C11 — LIVE MUSIC DNA PANEL  .vve-dna
   Mobile: collapsed sticky strip above the CTA footer. >=980px: side rail.
   ========================================================================== */
.vve-dna {
  position: fixed;
  left: 0; right: 0;
  bottom: var(--vve-footer-h);
  z-index: calc(var(--z-sticky) - 1);
  background: color-mix(in srgb, var(--panel) 90%, transparent);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-top: 1px solid var(--line);
}
.vve-dna__toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  width: 100%;
  min-height: var(--vve-target);
  padding: var(--sp-2) var(--gutter);
  text-align: left;
}
.vve-dna__toggle::after {
  content: "";
  width: 8px; height: 8px;
  border-right: 2px solid var(--ivory-80);
  border-top: 2px solid var(--ivory-80);
  transform: rotate(-45deg);
  transition: transform var(--vve-dur-1) var(--ease);
  flex: 0 0 auto;
}
.vve-dna__toggle[aria-expanded="true"]::after { transform: rotate(135deg); }
.vve-dna__summary {
  color: var(--ivory);
  font-size: var(--fs-small);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.vve-dna__body { padding: var(--sp-2) var(--gutter) var(--sp-4); }
.vve-dna__body[hidden] { display: none; }
.vve-dna__tags { display: flex; flex-wrap: wrap; gap: 8px; margin-top: var(--sp-3); }
.vve-dna__tag {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  padding: var(--sp-1) var(--sp-3);
  font-family: var(--font-label);
  font-size: var(--fs-micro);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--ivory-80);
}
/* Sealed state (V1 Review): label withheld + seal glyph */
.vve-dna--sealed .vve-dna__seal {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  color: var(--ivory);
  font-size: var(--fs-small);
}
.vve-dna--sealed .vve-dna__seal::before {
  content: "";
  width: 10px; height: 10px;
  border: 2px solid var(--crimson-line);
  border-radius: 50%;
}

/* ============================================================================
   C12 — REVIEW EDIT-CARD  .vve-editcard  (GOV.UK check-answers pattern)
   ========================================================================== */
.vve-editcard {
  position: relative;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: var(--sp-5);
  margin-bottom: var(--sp-4);
}
.vve-editcard__title {
  font-family: var(--font-label);
  font-size: var(--fs-h4);
  font-weight: 600;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--ivory);
  margin: 0 0 var(--sp-3);
  padding-right: 5rem;
}
.vve-editcard__edit {
  position: absolute;
  top: var(--sp-3);
  right: var(--sp-3);
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  min-height: var(--vve-target);
  padding: 0 var(--sp-3);
  color: var(--crimson-text);            /* 4.59:1 — legal link color */
  font-family: var(--font-label);
  font-size: var(--fs-small);
  letter-spacing: 0.06em;
  text-decoration: none;
}
.vve-editcard__edit:hover, .vve-editcard__edit:focus-visible { text-decoration: underline; text-underline-offset: 3px; }
/* Confirm values wrap UNDER the absolutely-positioned Edit/Adjust control,
   never through it — mirrors the title guard */
.vve-editcard__value { padding-right: 4.5rem; }
.vve-editcard__list { margin: 0; }
.vve-editcard__list > div {
  display: grid;
  grid-template-columns: minmax(0, 40%) minmax(0, 1fr);
  gap: var(--sp-3);
  padding: var(--sp-2) 0;
  border-bottom: 1px solid var(--line);
}
.vve-editcard__list > div:last-child { border-bottom: 0; }
.vve-editcard__list dt { color: var(--smoke); font-size: var(--fs-small); }
.vve-editcard__list dd { margin: 0; color: var(--ivory); font-size: var(--fs-small); }
.vve-editcard__assumed {
  font-family: var(--font-label);
  font-size: var(--fs-micro);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--smoke);
}
/* --confirm (B1): one pre-filled value + Edit — the endowed-progress payoff */
.vve-editcard--confirm { padding: var(--sp-4) var(--sp-5); }
.vve-editcard--confirm .vve-editcard__title { font-size: var(--fs-micro); color: var(--smoke); margin-bottom: var(--sp-1); }
.vve-editcard--confirm .vve-editcard__value { color: var(--ivory); font-size: var(--fs-lead); }

/* ============================================================================
   C13 — DNA METER  .vve-meter
   ========================================================================== */
.vve-meter { margin-bottom: var(--sp-5); }
.vve-meter__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--sp-3);
  margin-bottom: var(--sp-2);
}
.vve-meter__label {
  font-family: var(--font-label);
  font-size: var(--fs-body);
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ivory);
}
.vve-meter__value {
  font-family: var(--font-logo);
  font-size: var(--fs-h3);
  color: var(--ivory);
  letter-spacing: 0.03em;
}
.vve-meter__bar {
  height: 6px;
  border-radius: var(--r-pill);
  background: rgba(242, 239, 228, 0.10);
  overflow: hidden;
}
.vve-meter__fill {
  height: 100%;
  width: 0%;
  border-radius: inherit;
  background: var(--crimson);                       /* decorative fill — legal */
  box-shadow: inset 0 1px 0 var(--crimson-line);    /* 1px top edge for definition */
  transition: width var(--vve-dur-fill) var(--ease);
}
.vve-meter--filled .vve-meter__fill { width: var(--meter-value, 0%); }
.vve-meter__receipt { margin: var(--sp-2) 0 0; color: var(--smoke); font-size: var(--fs-small); }
/* --mini (C11 embed): 4px track, no receipt, no count-up */
.vve-meter--mini { margin-bottom: var(--sp-3); }
.vve-meter--mini .vve-meter__bar { height: 4px; }
.vve-meter--mini .vve-meter__label { font-size: var(--fs-micro); letter-spacing: var(--ls-label); }
.vve-meter--mini .vve-meter__value { font-size: var(--fs-body); }
.vve-meter--mini .vve-meter__fill { transition-duration: var(--vve-dur-2); }

/* ============================================================================
   C18 — CALIBRATION BEAT  .vve-beat  (V2 transient overlay)
   ========================================================================== */
.vve-beat {
  position: fixed;
  inset: 0;
  z-index: var(--z-header);
  background: var(--bg);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-6);
  padding: var(--gutter);
}
.vve-beat__wave { width: min(420px, 80vw); }
.vve-beat__wave path {
  fill: none;
  stroke: var(--crimson);                /* decorative — legal */
  stroke-width: 2;
  stroke-dasharray: 600;
  stroke-dashoffset: 600;
  animation: vve-beat-draw 2.2s var(--ease) forwards;
}
@keyframes vve-beat-draw { to { stroke-dashoffset: 0; } }
.vve-beat__line {
  font-family: var(--font-label);
  font-size: var(--fs-lead);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--ivory);
  text-align: center;
  min-height: 1.5em;
}
.vve-beat__skip {
  position: absolute;
  top: var(--sp-4);
  right: var(--sp-4);
  min-height: var(--vve-target);
  min-width: var(--vve-target);
  padding: 0 var(--sp-4);
  color: var(--ivory-80);
  font-family: var(--font-label);
  font-size: var(--fs-small);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
}
.vve-beat__skip:hover { color: var(--ivory); }

/* ============================================================================
   C19 — RESUME / EXPIRED FRAME SCREENS  .vve-resume / .vve-expired
   ========================================================================== */
.vve-resume, .vve-expired { text-align: center; padding-top: var(--sp-8); }
.vve-resume .vve-screen__title, .vve-expired .vve-screen__title { margin-bottom: var(--sp-4); }
.vve-resume__note, .vve-expired__safe {
  color: var(--smoke);
  font-size: var(--fs-small);
  margin-top: var(--sp-6);
}
.vve-expired__safe { color: var(--ivory-80); }
.vve-frame-actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-3);
  margin-top: var(--sp-6);
}
/* Centered non-sticky primary (F3 / F2 / F1 welcome body button style) */
.vve-btn-primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: var(--sp-2) var(--sp-7);
  border-radius: var(--r-sm);
  background: var(--crimson);
  color: var(--ivory);
  font-family: var(--font-label);
  font-size: var(--fs-body);
  font-weight: 600;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  text-decoration: none;          /* also used as an <a> (reveal → book.html) */
  transition: background var(--vve-dur-1) var(--ease);
}
.vve-btn-primary:hover  { background: var(--crimson-hot); }
.vve-btn-primary:active { background: var(--crimson-deep); }
.vve-btn-secondary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--vve-target);
  padding: 0 var(--sp-5);
  border-radius: var(--r-pill);
  border: 1px solid var(--line-strong);
  color: var(--ivory);
  font-family: var(--font-label);
  font-size: var(--fs-small);
  letter-spacing: 0.06em;
  transition: background var(--vve-dur-1) var(--ease);
}
.vve-btn-secondary:hover { background: var(--panel-2); }
/* ghost — lowest-emphasis action (e.g. "start a fresh profile" on the reveal) */
.vve-btn-ghost {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--vve-target);
  padding: 0 var(--sp-5);
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  background: transparent;
  color: var(--smoke);
  font-family: var(--font-label);
  font-size: var(--fs-small);
  letter-spacing: 0.06em;
  cursor: pointer;
  transition: color var(--vve-dur-1) var(--ease), border-color var(--vve-dur-1) var(--ease);
}
.vve-btn-ghost:hover { color: var(--ivory); border-color: var(--line-strong); }
.vve-btn-ghost:focus-visible { outline: 2px solid var(--crimson-line); outline-offset: 2px; }
.vve-expired--sent .vve-expired__action { display: none; }
.vve-expired__confirm {
  display: none;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  color: var(--ivory);
}
.vve-expired--sent .vve-expired__confirm { display: flex; }

/* ============================================================================
   V3 REVEAL — screen-level styles (D22–D25; module builder composes these)
   ========================================================================== */
.vve-reveal__hero { position: relative; padding: var(--sp-8) 0 var(--sp-7); }
.vve-reveal__hero::before {
  content: "";
  position: absolute;
  inset: -2.5rem -25% auto -25%;
  height: 22rem;
  background: radial-gradient(60% 100% at 32% 0%, var(--haze), transparent 70%);
  pointer-events: none;
  z-index: -1;
}
/* The -25% horizontal bleed is a desktop ambient effect; below ~1024px the hero
   fills most of the viewport and that bleed spills past the edge → horizontal
   scroll (caught in Stage-6 render matrix at 360 & 768). Contain the haze to the
   hero at narrow widths — the glow stays, the sideways scroll goes. */
@media (max-width: 1024px) {
  .vve-reveal__hero::before { inset: -2.5rem 0 auto 0; }
}
.vve-reveal__eyebrow {
  font-family: var(--font-label);
  font-size: var(--fs-micro);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--smoke);
  margin-bottom: var(--sp-3);
}
.vve-reveal__label {
  font-family: var(--font-display);
  font-size: var(--fs-display);
  text-transform: uppercase;
  line-height: var(--lh-tight);
  color: var(--ivory);
  text-wrap: balance;
  opacity: 0;
  transform: translateY(var(--vve-shift));
  animation: vve-label-rise 0.4s var(--ease) forwards;   /* D25: 400ms */
}
@keyframes vve-label-rise { to { opacity: 1; transform: none; } }
.vve-reveal__underline {
  height: 3px;
  width: 0;
  background: var(--crimson);              /* decorative fill */
  margin: var(--sp-3) 0 var(--sp-4);
  animation: vve-underline-draw 0.6s var(--ease) 0.35s forwards;  /* D25: 600ms */
}
@keyframes vve-underline-draw { to { width: min(240px, 60%); } }
.vve-reveal__because { color: var(--ivory-80); max-width: var(--w-copy); font-size: var(--fs-lead); }
.vve-reveal__decisionlist {
  list-style: none; margin: var(--sp-4) 0 0; padding: 0;
  max-width: var(--w-copy); display: flex; flex-direction: column; gap: var(--sp-3);
}
.vve-reveal__decisionlist li {
  position: relative; padding-left: var(--sp-4); color: var(--ivory-80); font-size: var(--fs-body);
}
.vve-reveal__decisionlist li::before {
  content: ""; position: absolute; left: 0; top: 0.6em;
  width: 5px; height: 5px; border-radius: 50%; background: var(--crimson);
}
.vve-reveal__tags { display: flex; flex-wrap: wrap; gap: 8px; margin-top: var(--sp-4); }
.vve-reveal__section { padding: var(--sp-7) 0; border-top: 1px solid var(--line); }
.vve-reveal__section:last-child { padding-top: var(--sp-8); padding-bottom: var(--sp-9); border-top: 0; }
.vve-reveal__section-title {
  font-family: var(--font-label);
  font-size: var(--fs-h4);
  font-weight: 600;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--ivory);
  margin-bottom: var(--sp-5);
}
.vve-reveal__rolegroup { margin-bottom: var(--sp-5); }
.vve-reveal__rolegroup-title {
  font-family: var(--font-label);
  font-size: var(--fs-micro);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--smoke);
  margin-bottom: var(--sp-3);
}
.vve-reveal__steps { counter-reset: vve-step; }
.vve-reveal__step {
  counter-increment: vve-step;
  display: flex;
  gap: var(--sp-4);
  padding: var(--sp-3) 0;
  color: var(--ivory-80);
}
.vve-reveal__step::before {
  content: counter(vve-step);
  font-family: var(--font-logo);
  font-size: var(--fs-h3);
  color: var(--crimson-text);              /* legal crimson text */
  line-height: 1;
  min-width: 1.5ch;
}
.vve-reveal__privacy { color: var(--smoke); font-size: var(--fs-small); margin-top: var(--sp-5); }

/* ============================================================================
   DEV STRIP — internal only
   ========================================================================== */
/* Anchors above BOTH the sticky CTA footer and any bottom-docked panel
   (the songs screen's live Music DNA drawer sits in the same corner) —
   --vve-dock-h is published by whichever screen docks a panel, 0 otherwise. */
.vve-devstrip {
  position: fixed;
  left: var(--sp-3);
  bottom: calc(var(--vve-footer-h) + var(--vve-dock-h, 0px) + var(--sp-3));
  z-index: var(--z-menu);
  max-width: min(340px, calc(100vw - 2 * var(--sp-3)));
  background: var(--bg-2);
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-sm);
  font-family: var(--font-label);
  font-size: var(--fs-micro);
  color: var(--smoke);
  /* Recedes so it never fights the content it floats over (the reveal is one
     long scroll with no CTA footer to sit above); full opacity on interaction. */
  opacity: 0.42;
  transition: opacity var(--vve-dur-1, 0.2s) ease;
}
.vve-devstrip:hover,
.vve-devstrip:focus-within,
.vve-devstrip[open] { opacity: 1; }
.vve-devstrip__summary {
  cursor: pointer;
  padding: var(--sp-2) var(--sp-3);
  letter-spacing: var(--ls-label);
  list-style: none;
  user-select: none;
}
.vve-devstrip__summary::-webkit-details-marker { display: none; }
.vve-devstrip__body { padding: 0 var(--sp-3) var(--sp-3); display: flex; flex-direction: column; gap: var(--sp-2); }
.vve-devstrip__group { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }
.vve-devstrip__label { letter-spacing: var(--ls-label); display: inline-flex; align-items: center; gap: var(--sp-1); }
.vve-devstrip__btn {
  border: 1px solid var(--line-strong);
  border-radius: var(--r-xs);
  padding: var(--sp-1) var(--sp-2);
  color: var(--ivory-80);
  min-height: var(--vve-target-min);
}
.vve-devstrip__btn:hover { background: var(--panel-2); color: var(--ivory); }
.vve-devstrip__btn--danger { border-color: var(--crimson-line); color: var(--crimson-text); }
.vve-devstrip__btn.is-active { background: var(--crimson); color: var(--ivory); border-color: var(--crimson-line); }

/* Shell placeholder for unregistered modules (pre-integration state) */
.vve-placeholder {
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-md);
  padding: var(--sp-6);
  color: var(--smoke);
  text-align: center;
}
.vve-placeholder code { color: var(--ivory-80); font-size: var(--fs-small); }

/* ============================================================================
   BREAKPOINTS — mobile-first, 390px reference. 768 / 980 / 1280.
   ========================================================================== */
@media (min-width: 768px) {
  :root { --vve-chip-h: 40px; }            /* 40px permitted >=768px */
  .vve-cta__inner { flex-direction: row; align-items: center; justify-content: flex-end; gap: var(--sp-4); }
  .vve-cta__note { order: -1; margin-right: auto; text-align: left; }
  .vve-cta__primary { width: auto; min-width: 220px; }
  .vve-cta__secondary { order: -1; }
  .vve-tricard-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .vve-songlist--2col, .vve-search__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .vve-song__detail { grid-column: 1 / -1; }
  .vve-rolechips .vve-chip { min-height: 40px; }   /* dense detail panel allowance */
}

@media (min-width: 980px) {
  .vve-stage { max-width: 720px; }
  /* DNA panel becomes a persistent side rail inside .vve-layout screens */
  .vve-layout { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: var(--sp-6); align-items: start; }
  .vve-layout .vve-dna {
    position: sticky;
    top: calc(var(--vve-header-h) + var(--sp-4));
    bottom: auto; left: auto; right: auto;
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    background: color-mix(in srgb, var(--panel) 90%, transparent);
  }
  .vve-layout .vve-dna__toggle { display: none; }
  .vve-layout .vve-dna__body { display: block; padding: var(--sp-4); }
  .vve-layout .vve-dna__body[hidden] { display: block !important; }  /* rail is always open */
  .vve-layout ~ * { max-width: none; }
  .vve-stage--wide { max-width: 1060px; }   /* screens that opt into the rail layout */
  /* Side-rail case: the DNA lives in the sticky rail, not a fixed strip —
     restore the default pad (Review's strip keeps the taller pad) */
  .vve-stage--wide:has(.vve-layout .vve-dna) {
    padding-bottom: calc(var(--vve-footer-h) + var(--sp-6));
  }
}

/* ============================================================================
   MISSING-ANSWER FLASH  .vve-missing
   Set by app.js flashMissing() when Continue is blocked. The group is scrolled
   clear of the sticky chrome first, then jumps so the eye lands on it.

   Crimson here is a GLOW and a RING — both are filled/haloed shapes, not a
   hairline, so they survive the 2.50:1 problem (#9E1B32 on #0A0A0A). The ring
   uses --crimson-line (3.69:1) which is legal as a non-text indicator, and the
   footer note still carries the words — this never communicates by colour alone.
   ========================================================================== */
.vve-missing {
  position: relative;
  border-radius: var(--r-md, 10px);
  animation: vve-jump 320ms var(--ease) both;
}
.vve-missing::after {
  content: "";
  position: absolute;
  inset: -10px -12px;
  border: 2px solid var(--crimson-line);
  border-radius: inherit;
  pointer-events: none;
  animation: vve-ring 1600ms ease-out both;
}

@keyframes vve-jump {
  0%   { transform: translateY(-6px); }
  100% { transform: translateY(0); }
}
@keyframes vve-ring {
  0%   { opacity: 0; box-shadow: 0 0 0 0 rgba(196, 50, 78, .45); }
  12%  { opacity: 1; box-shadow: 0 0 22px 4px rgba(196, 50, 78, .40); }
  70%  { opacity: 1; box-shadow: 0 0 14px 2px rgba(196, 50, 78, .22); }
  100% { opacity: 0; box-shadow: 0 0 0 0 rgba(196, 50, 78, 0); }
}

/* Reduced motion: same information, no movement. The ring holds longer and
   fades rather than pulsing, so it is still unmistakable. */
@media (prefers-reduced-motion: reduce) {
  .vve-missing { animation: none; }
  .vve-missing::after { animation: vve-ring-still 1600ms ease-out both; }
}
html[data-reduced-motion="true"] .vve-missing { animation: none; }
html[data-reduced-motion="true"] .vve-missing::after { animation: vve-ring-still 1600ms ease-out both; }

@keyframes vve-ring-still {
  0%, 78% { opacity: 1; }
  100%    { opacity: 0; }
}

/* ============================================================================
 * C-IMPORT — "Bring your playlist" overlay (screenshot/paste → review → add)
 *   Lives above wizard chrome (z 1100 > --z-skip). Crimson is FILL-only; amber
 *   #D9A441 = review-warn (8.3:1 on panel). Respects reduced-motion via --noanim.
 * ==========================================================================*/
.vve-imp__scrim {
  position: fixed; inset: 0; z-index: 1100;
  display: flex; align-items: center; justify-content: center;
  padding: var(--sp-4);
  background: rgba(6, 6, 7, 0.72);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  animation: vve-imp-fade 0.22s var(--ease, ease) both;
}
.vve-imp {
  width: 100%; max-width: 560px; max-height: 90vh; overflow-y: auto;
  background: var(--panel); color: var(--ivory);
  border: 1px solid rgba(242, 239, 228, 0.10);
  border-radius: var(--r-lg); box-shadow: var(--shadow-2);
  animation: vve-imp-rise 0.26s var(--ease-io, ease) both;
}
.vve-imp--noanim, .vve-imp--noanim .vve-imp__scrim { animation: none; }
.vve-imp__scrim:has(.vve-imp--noanim) { animation: none; }
@keyframes vve-imp-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes vve-imp-rise { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .vve-imp, .vve-imp__scrim { animation: none !important; }
}

.vve-imp__head {
  position: sticky; top: 0; z-index: 1;
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-3); padding: var(--sp-5) var(--sp-5) var(--sp-3);
  background: linear-gradient(var(--panel), var(--panel) 72%, transparent);
}
.vve-imp__title { font-family: var(--font-display); font-size: var(--fs-title); margin: 0; letter-spacing: 0.01em; }
.vve-imp__x {
  flex: none; width: 40px; height: 40px; border-radius: var(--r-pill);
  background: transparent; border: 1px solid rgba(242,239,228,0.16); color: var(--ivory-80);
  font-size: 22px; line-height: 1; cursor: pointer;
}
.vve-imp__x:hover { background: var(--panel-2); color: var(--ivory); }
.vve-imp__body { padding: 0 var(--sp-5) var(--sp-5); }
.vve-imp__intro, .vve-imp__proc-sub { color: var(--ivory-80); font-size: var(--fs-small); margin: 0 0 var(--sp-4); }

/* intake -------------------------------------------------------------- */
.vve-imp__drop {
  display: flex; flex-direction: column; align-items: center; gap: var(--sp-2);
  padding: var(--sp-7) var(--sp-4); text-align: center; cursor: pointer;
  border: 1.5px dashed rgba(242,239,228,0.22); border-radius: var(--r-md);
  background: rgba(242,239,228,0.02); transition: border-color 0.18s, background 0.18s;
}
.vve-imp__drop:hover, .vve-imp__drop:focus-visible, .vve-imp__drop.is-over {
  border-color: var(--crimson-line); background: rgba(196,50,78,0.06); outline: none;
}
.vve-imp__drop-ico { color: var(--crimson-text); }
.vve-imp__drop-lead { font-family: var(--font-label); font-size: var(--fs-lead); color: var(--ivory); }
.vve-imp__drop-sub { font-size: var(--fs-micro); color: var(--smoke); }
.vve-imp__or { display: flex; align-items: center; gap: var(--sp-3); margin: var(--sp-4) 0; color: var(--smoke); font-size: var(--fs-micro); }
.vve-imp__or::before, .vve-imp__or::after { content: ""; flex: 1; height: 1px; background: rgba(242,239,228,0.10); }
.vve-imp__pastewrap { display: flex; flex-direction: column; gap: var(--sp-2); }
.vve-imp__paste {
  width: 100%; resize: vertical; padding: var(--sp-3); font: inherit; font-size: var(--fs-small);
  color: var(--ivory); background: var(--panel-2); border: 1px solid rgba(242,239,228,0.14); border-radius: var(--r-sm);
}
.vve-imp__paste:focus-visible { outline: 2px solid var(--crimson-line); outline-offset: 1px; }
.vve-imp__note { color: var(--crimson-text); font-size: var(--fs-micro); min-height: 1.2em; margin: var(--sp-3) 0 0; }

/* processing ---------------------------------------------------------- */
.vve-imp__proc { display: flex; flex-direction: column; align-items: center; gap: var(--sp-3); padding: var(--sp-7) var(--sp-3); text-align: center; }
.vve-imp__spin {
  width: 34px; height: 34px; border-radius: 50%;
  border: 3px solid rgba(242,239,228,0.14); border-top-color: var(--crimson-text);
  animation: vve-imp-spin 0.8s linear infinite;
}
@media (prefers-reduced-motion: reduce) { .vve-imp__spin { animation-duration: 2s; } }
@keyframes vve-imp-spin { to { transform: rotate(360deg); } }
.vve-imp__proc-status { font-family: var(--font-label); font-size: var(--fs-lead); margin: 0; }
.vve-imp__bar { width: 100%; max-width: 320px; height: 6px; border-radius: var(--r-pill); background: rgba(242,239,228,0.10); overflow: hidden; }
.vve-imp__bar-fill { display: block; height: 100%; width: 0; background: var(--crimson); transition: width 0.2s var(--ease, ease); }

/* review -------------------------------------------------------------- */
.vve-imp__rev-head { margin-bottom: var(--sp-3); }
.vve-imp__rev-count { font-family: var(--font-label); font-size: var(--fs-lead); margin: 0 0 2px; }
.vve-imp__rev-count strong { color: var(--ivory); }
.vve-imp__rev-need { color: #D9A441; }
.vve-imp__rev-sub { color: var(--ivory-80); font-size: var(--fs-micro); margin: 0; }
.vve-imp__rows { display: flex; flex-direction: column; gap: var(--sp-2); margin-bottom: var(--sp-3); }
.vve-imp__row {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-3); border-radius: var(--r-sm);
  background: var(--panel-2); border: 1px solid transparent;
}
.vve-imp__row.is-warn { border-color: rgba(217,164,65,0.45); }
.vve-imp__row-fields { flex: 1; display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.vve-imp__in {
  width: 100%; padding: 6px 8px; font: inherit; color: var(--ivory);
  background: rgba(10,10,10,0.4); border: 1px solid rgba(242,239,228,0.12); border-radius: var(--r-xs);
}
.vve-imp__in--title { font-size: var(--fs-small); font-weight: 600; }
.vve-imp__in--artist { font-size: var(--fs-micro); color: var(--ivory-80); }
.vve-imp__in:focus-visible { outline: 2px solid var(--crimson-line); outline-offset: 1px; }
.vve-imp__row-meta { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
.vve-imp__badge { font-size: 10px; letter-spacing: 0.04em; text-transform: uppercase; padding: 2px 7px; border-radius: var(--r-pill); white-space: nowrap; }
.vve-imp__badge.is-ok { color: var(--smoke); border: 1px solid rgba(125,130,133,0.4); }
.vve-imp__badge.is-warn { color: #D9A441; border: 1px solid rgba(217,164,65,0.5); }
.vve-imp__badge.is-lib { color: var(--crimson-text); border: 1px solid var(--crimson-line); }
.vve-imp__del {
  width: 28px; height: 28px; border-radius: var(--r-pill); font-size: 18px; line-height: 1; cursor: pointer;
  background: transparent; border: 1px solid rgba(242,239,228,0.14); color: var(--smoke);
}
.vve-imp__del:hover { color: var(--crimson-text); border-color: var(--crimson-line); }

/* buttons ------------------------------------------------------------- */
.vve-imp__actions { display: flex; gap: var(--sp-3); margin-top: var(--sp-4); }
.vve-imp__primary, .vve-imp__ghost {
  font-family: var(--font-label); font-size: var(--fs-small); letter-spacing: 0.02em;
  padding: var(--sp-3) var(--sp-5); border-radius: var(--r-pill); cursor: pointer; border: 1px solid transparent;
}
.vve-imp__primary { flex: 1; background: var(--crimson); color: var(--ivory); border-color: var(--crimson); }
.vve-imp__primary:hover:not(:disabled) { background: var(--crimson-hot, var(--crimson)); }
.vve-imp__primary:disabled { opacity: 0.5; cursor: not-allowed; }
.vve-imp__ghost { background: transparent; color: var(--ivory-80); border-color: rgba(242,239,228,0.2); }
.vve-imp__ghost:hover { color: var(--ivory); border-color: var(--ivory-60); }
.vve-imp__ghost--sm { font-size: var(--fs-micro); padding: var(--sp-2) var(--sp-3); margin-top: var(--sp-2); }
.vve-imp__primary:focus-visible, .vve-imp__ghost:focus-visible, .vve-imp__x:focus-visible, .vve-imp__del:focus-visible {
  outline: 2px solid var(--crimson-line); outline-offset: 2px;
}

/* Import entry point on the songs screen — invites the screenshot import. */
.vve-songimport-cta {
  display: inline-flex; align-items: center; gap: var(--sp-2); margin-top: var(--sp-3);
  padding: var(--sp-2) var(--sp-4); font-family: var(--font-label); font-size: var(--fs-micro);
  letter-spacing: 0.02em; color: var(--ivory-80); cursor: pointer;
  background: rgba(196,50,78,0.06); border: 1px solid var(--crimson-line); border-radius: var(--r-pill);
  transition: background 0.18s, color 0.18s;
}
.vve-songimport-cta::before { content: "📸"; font-size: 1em; filter: grayscale(0.2); }
.vve-songimport-cta:hover { background: rgba(196,50,78,0.12); color: var(--ivory); }
.vve-songimport-cta:focus-visible { outline: 2px solid var(--crimson-line); outline-offset: 2px; }

/* Genre-preference selector on the pick-songs screen (front-rotation control). */
.vve-genrepick__row { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-2); }
.vve-genrepick__chip {
  display: inline-flex; align-items: center; min-height: var(--vve-chip-h, 44px);
  padding: 6px 14px; border-radius: var(--r-pill); cursor: pointer;
  font-family: var(--font-label); font-size: var(--fs-micro); letter-spacing: 0.02em;
  color: var(--smoke); background: transparent; border: 1px solid rgba(242,239,228,0.16);
  transition: color .16s var(--ease), border-color .16s var(--ease), background .16s var(--ease);
}
@media (min-width: 768px) { .vve-genrepick__chip { min-height: 40px; } }
.vve-genrepick__chip:hover { color: var(--ivory); border-color: var(--ivory-60); }
.vve-genrepick__chip.is-on {
  color: var(--ivory); background: rgba(196,50,78,0.12); border-color: var(--crimson-line);
}
.vve-genrepick__chip.is-on::before { content: "✓ "; color: var(--crimson-text); }
.vve-genrepick__chip:focus-visible { outline: 2px solid var(--crimson-line); outline-offset: 2px; }

/* Start-over — low-emphasis reset reachable from the footer of any working page. */
.vve-cta__secondary { display: flex; gap: var(--sp-3); align-items: center; justify-content: center; flex-wrap: wrap; }
.vve-startover {
  background: transparent; border: none; cursor: pointer;
  color: var(--smoke); font-family: var(--font-label); font-size: var(--fs-micro);
  letter-spacing: 0.04em; text-decoration: underline; text-underline-offset: 3px;
  padding: var(--sp-2);
}
.vve-startover:hover { color: var(--crimson-text); }
.vve-startover:focus-visible { outline: 2px solid var(--crimson-line); outline-offset: 2px; border-radius: var(--r-xs); }

/* Separate the "favorites" confirmation from the "room" read in the genre panel. */
.vve-genrepick__legend2 { margin-top: var(--sp-4); padding-top: var(--sp-3); border-top: 1px solid rgba(242,239,228,0.08); }

/* ---- ONE-AT-A-TIME GENRE STEPPER  .vve-genrestep -------------------------
   The room read, surfaced one lane at a time so it reads as a decision instead
   of a chip wall. The full chip list still lives under .vve-genrepick__alltoggle.
   No keyframes: the only motion rides --vve-dur-1, which the global
   reduced-motion gate zeroes. */
.vve-genrestep { display: flex; flex-direction: column; gap: var(--sp-2); margin-top: var(--sp-3); }
.vve-genrestep__progress {
  margin: 0; font-family: var(--font-label); font-size: var(--fs-micro);
  letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--smoke);
}
.vve-genrestep__card {
  display: flex; flex-direction: column; gap: 2px;
  padding: var(--sp-4); background: var(--panel);
  border: 1px solid var(--line); border-radius: var(--r-md);
  transition: background var(--vve-dur-1) var(--ease), border-color var(--vve-dur-1) var(--ease);
}
.vve-genrestep__card.is-on { background: var(--crimson); border-color: var(--crimson-line); }
.vve-genrestep__name {
  font-family: var(--font-display); font-size: var(--fs-h3);
  text-transform: uppercase; letter-spacing: 0.02em; color: var(--ivory);
}
.vve-genrestep__signal { font-size: var(--fs-micro); color: var(--smoke); }
.vve-genrestep__card.is-on .vve-genrestep__signal { color: var(--ivory-80); }
/* state is never colour-only — tick + words */
.vve-genrestep__state {
  display: inline-flex; align-items: center; gap: 6px; margin-top: var(--sp-2);
  font-family: var(--font-label); font-size: var(--fs-micro);
  letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--ivory);
}
.vve-genrestep__actions { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.vve-genrestep__btn {
  flex: 1 1 auto; min-height: var(--vve-target); padding: 0 var(--sp-4);
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; border: 1px solid var(--line-strong); border-radius: var(--r-pill);
  color: var(--ivory); cursor: pointer;
  font-family: var(--font-label); font-size: var(--fs-micro);
  letter-spacing: var(--ls-label); text-transform: uppercase;
  transition: background var(--vve-dur-1) var(--ease), border-color var(--vve-dur-1) var(--ease);
}
/* crimson FILL only — never crimson text or a crimson hairline as the signal */
.vve-genrestep__btn--primary { background: var(--crimson); border-color: var(--crimson-line); }
.vve-genrestep__btn--primary.is-on { background: transparent; border-color: var(--ivory-60); }
@media (hover: hover) { .vve-genrestep__btn:hover { border-color: var(--ivory-60); background: var(--panel-2); }
  .vve-genrestep__btn--primary:hover { background: var(--crimson); border-color: var(--ivory-60); } }
.vve-genrestep__btn:focus-visible { outline: 2px solid var(--ivory); outline-offset: 2px; }
.vve-genrestep__nav { display: flex; }
.vve-genrestep__back {
  min-height: var(--vve-target); padding: 0 var(--sp-2);
  display: inline-flex; align-items: center;
  background: transparent; border: none; cursor: pointer;
  color: var(--smoke); font-family: var(--font-label); font-size: var(--fs-micro);
  letter-spacing: var(--ls-label); text-transform: uppercase;
}
@media (hover: hover) { .vve-genrestep__back:hover { color: var(--ivory); } }
.vve-genrestep__back:focus-visible { outline: 2px solid var(--ivory); outline-offset: 2px; border-radius: var(--r-xs); }
.vve-genrestep__done { margin: 0 0 var(--sp-2); font-size: var(--fs-micro); color: var(--smoke); }
/* the full list, still reachable so more favourites can be added */
.vve-genrepick__alltoggle {
  align-self: flex-start; min-height: var(--vve-target); padding: 0;
  margin-top: var(--sp-3);
  display: inline-flex; align-items: center;
  background: transparent; border: none; cursor: pointer;
  color: var(--ivory); font-family: var(--font-label); font-size: var(--fs-micro);
  letter-spacing: var(--ls-label); text-transform: uppercase;
  text-decoration: underline; text-underline-offset: 3px;
}
@media (hover: hover) { .vve-genrepick__alltoggle:hover { color: var(--crimson-text); } }
.vve-genrepick__alltoggle:focus-visible { outline: 2px solid var(--ivory); outline-offset: 2px; border-radius: var(--r-xs); }

/* ============================================================================
   C21 — LIBRARY BROWSER  .vve-library
   Curation V2. APPEND-ONLY block: it adds selectors, it edits none. Deleting
   everything from this banner to EOF reverts the browser's styling completely.
   Spec: docs/GERONIMO-CURATION-LIBRARY.md §11.5 / §11.10 (+ Thor T-01).
   No @keyframes and no scripted motion anywhere in this block — reduced motion
   is satisfied structurally; the two transitions below run through --vve-dur-1,
   which the global gate at the top of this file already zeroes.
   ========================================================================== */
.vve-library {
  margin-top: var(--sp-6);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--line);
}
.vve-library__toggle {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3);
  width: 100%; min-height: var(--vve-target); padding: var(--sp-2) 0;
  background: transparent; border: none; cursor: pointer; text-align: left;
  color: var(--ivory); font-family: var(--font-label); font-size: var(--fs-small);
  letter-spacing: var(--ls-label); text-transform: uppercase;
}
.vve-library__toggle::after {
  content: "+"; flex: 0 0 auto; color: var(--ivory-80); font-size: 18px; line-height: 1;
  width: 1em; text-align: center;        /* the en-dash is narrower — stops the right edge jittering on toggle */
}
/* the disclosure is wrapped in an h3 purely for heading navigation — it must not
   introduce any heading typography or spacing of its own. */
.vve-library__heading { margin: 0; font: inherit; letter-spacing: inherit; }
/* crate progress, on the row the client is looking at while they browse */
.vve-library__togglecount {
  margin-inline-start: auto; color: var(--smoke);
  font-size: var(--fs-micro); letter-spacing: 0.02em; text-transform: none;
}
.vve-library__toggle[aria-expanded="true"]::after { content: "–"; }
.vve-library__toggle:focus-visible { outline: 2px solid var(--ivory); outline-offset: 2px; border-radius: var(--r-xs); }
@media (hover: hover) { .vve-library__toggle:hover { color: var(--crimson-text); } }
/* The three tiers here are filter / browse / results. They were reading as one
   undifferentiated stack because .vve-search and .vve-genrepick__row each carry
   a margin from their HOME screens on top of this gap — measured 40 / 16 / 16,
   a 2.5x step where the eye expects one scale. Neutralised locally; the shared
   rules those components use elsewhere are untouched. */
.vve-library__body { display: flex; flex-direction: column; gap: var(--sp-5); padding-top: var(--sp-3); }
.vve-library__body > .vve-search { margin-bottom: calc(var(--sp-3) - var(--sp-5)); }
.vve-library__body > .vve-genrepick__row { margin-top: 0; }
/* the shared clear button is a fixed 40x40 (its min-* use --vve-target-min, the
   24px floor, which is NOT a tap target). A mis-tap here costs the query. */
.vve-library .vve-search__clear { width: var(--vve-target); height: var(--vve-target); }

/* -- breadcrumb + Back: a mobile drill control. Hidden >=980px, where both
      panes are visible at once and there is nothing to go "back" to — EXCEPT
      while a search is running, which --search keeps visible at every width. */
.vve-library__crumb { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; }
.vve-library__crumb-text {
  font-family: var(--font-label); font-size: var(--fs-micro); letter-spacing: var(--ls-label);
  text-transform: uppercase; color: var(--smoke); min-width: 0; overflow-wrap: anywhere;
}

/* -- browser panes: Genre | Artist. One DOM at every width; data-level is read
      only below 980px. Hidden panes are display:none so a screen-reader user on
      a phone hears exactly ONE browser column (D-03). */
.vve-library__panes { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp-4); }
.vve-library__pane {
  display: flex; flex-direction: column; gap: var(--sp-2); min-width: 0;
  overflow-x: clip;                     /* never `hidden` — it kills position:sticky ancestors */
}
/* The internal scroll cap belongs at EVERY width, not just desktop. Uncapped
   below 980px the artist pane ran 1,186px tall (24 rows) and pushed the record
   list to y2,132 on a 375px screen — the client picks a lane and the records
   they asked for are two screens below a wall of nav buttons. The height is
   also cut to a whole number of rows PLUS the gap: at the old 320px the cut
   landed 32px into a 48px row pitch, straight through the descenders of row 7. */
.vve-library__list {
  list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--sp-1);
  max-height: calc(6 * (var(--vve-target) + var(--sp-1)) + var(--sp-3));   /* 300px = 6 rows + a 12px peek */
  overflow-y: auto; overscroll-behavior: contain;
  padding-inline-end: 2px;
  padding-block: 2px; margin-block: -2px;          /* clip box for the row focus ring */
}
.vve-library__row {
  display: flex; align-items: center; gap: var(--sp-2);
  width: 100%; min-height: var(--vve-target); padding: var(--sp-1) var(--sp-3);
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-sm);
  color: var(--ivory-80); cursor: pointer; text-align: left;
  font-family: var(--font-label); font-size: var(--fs-small); letter-spacing: 0.02em;
  transition: background var(--vve-dur-1) var(--ease), border-color var(--vve-dur-1) var(--ease);
}
@media (hover: hover) { .vve-library__row:hover { background: var(--panel-2); color: var(--ivory); } }
.vve-library__row:focus-visible { outline: 2px solid var(--ivory); outline-offset: 2px; }
/* current lane/artist: crimson FILL (never crimson text, never a crimson
   hairline as the only signal) + a visible tick + the count, all as text. */
.vve-library__row.is-on {
  background: var(--crimson); border-color: var(--crimson-line); color: var(--ivory);
}
/* The "All records" / "All artists" row is always the FIRST li, and it is `is-on`
   before the client has decided anything. Left as crimson it made the null state
   the loudest surface on the screen — three crimson slabs at rest, none of them a
   choice. Neutral here, so crimson arrives exactly once: on the lane they picked.
   aria-current and the ✓ glyph are untouched, so state is never colour-only. */
.vve-library__list > li:first-child > .vve-library__row.is-on {
  background: var(--panel-2); border-color: var(--ivory-60); color: var(--ivory);
}
.vve-library__list > li:first-child > .vve-library__row.is-on .vve-library__n { color: var(--ivory-80); }
/* same reasoning for "Any era" — it is the no-filter default, so it should not
   wear the accent. Scoped to the library; m4's own genre picker is untouched. */
.vve-library__body .vve-genrepick__chip[data-era=""].is-on {
  background: var(--panel-2); border-color: var(--ivory-60); color: var(--ivory);
}
.vve-library__body .vve-genrepick__chip[data-era=""].is-on::before { color: var(--ivory); }
.vve-library__tick { flex: 0 0 auto; width: 1em; color: var(--ivory); }
.vve-library__rowlabel { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.vve-library__n { flex: 0 0 auto; font-size: var(--fs-micro); color: var(--smoke); }
.vve-library__row.is-on .vve-library__n { color: var(--ivory); }
.vve-library__note { font-size: var(--fs-micro); color: var(--smoke); margin: var(--sp-2) 0 0; }

/* -- records: full width, below the panes, at every size. */
.vve-library__records { display: flex; flex-direction: column; gap: var(--sp-3); }
/* .vve-song falls back to a crimson left border when no --family-accent is set,
   which reads fine across ~12 crate cards and becomes 48–60 identical crimson
   bars in one scroll here. Worse, it is the SAME crimson as the "in the crate"
   outline, so the accent carried no information and diluted the selected state.
   Both :not()s are load-bearing: `.vve-library__records .vve-song` (0,2,0) would
   otherwise outrank `.vve-song--is-selected` (0,1,0) and strip the real signal. */
.vve-library__records .vve-song:not(.vve-song--is-selected):not(:has(input:checked)) {
  border-left-color: var(--line-strong);
}
.vve-library__count { font-family: var(--font-label); font-size: var(--fs-micro);
  letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--smoke); margin: 0; }
/* orientation line — the browser used to open with no instruction at all */
.vve-library__hint { font-size: var(--fs-micro); color: var(--smoke); margin: 0; }
/* the 30-cap message, spliced into the record list under the row that was
   tapped. Ivory, not smoke: it answers a tap that just did nothing, so it has
   to read as feedback rather than fine print. */
li.vve-library__cap {
  /* .vve-songlist is a grid, so an un-spanned item stretches to whatever record
     card shares its row (measured 236px for one line of text). */
  grid-column: 1 / -1; align-self: start;
  list-style: none; display: block; margin: 0; padding: var(--sp-2) var(--sp-3);
  background: var(--panel); border: 1px solid var(--line-strong); border-radius: var(--r-sm);
  color: var(--ivory); font-size: var(--fs-micro); line-height: 1.4;
}
/* the add/remove control inside .vve-song__actions — same skin as the crate's
   own row buttons, declared here rather than joined to that selector list so
   this block stays a pure addition. */
.vve-library__act {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--vve-target);
  /* wide enough for "Remove" (70px), so the action column does not step 23px in
     and out down a 48-row list — and so tapping Add never re-flows the title
     column and changes row height under the finger that just lifted. */
  min-width: calc(var(--vve-target) + var(--sp-6));
  padding: 0 var(--sp-3);
  background: transparent; border: none; border-radius: var(--r-sm); cursor: pointer;
  color: var(--ivory-80); font-family: var(--font-label); font-size: var(--fs-micro);
  letter-spacing: var(--ls-label); text-transform: uppercase;
  transition: background var(--vve-dur-1) var(--ease), color var(--vve-dur-1) var(--ease);
}
@media (hover: hover) { .vve-library__act:hover { background: var(--panel-2); color: var(--ivory); } }
.vve-library__act:focus-visible { outline: 2px solid var(--ivory); outline-offset: -2px; }

.vve-library__pager { display: flex; justify-content: center; }
.vve-library__more {
  min-height: var(--vve-target); padding: 0 var(--sp-4);
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; border: 1px solid var(--line-strong); border-radius: var(--r-pill);
  color: var(--ivory); font-family: var(--font-label); font-size: var(--fs-micro);
  letter-spacing: var(--ls-label); text-transform: uppercase; cursor: pointer;
}
@media (hover: hover) { .vve-library__more:hover { border-color: var(--ivory-60); background: var(--panel-2); } }
.vve-library__more:focus-visible { outline: 2px solid var(--ivory); outline-offset: 2px; }
/* spill control — a longer label than "Show more"; let it breathe instead of
   overflowing the pill on a narrow phone. */
.vve-library__more--spill { padding: var(--sp-2) var(--sp-4); max-width: 100%; white-space: normal; text-align: center; line-height: 1.35; }
/* the genre→library seam, spliced into the records <ol> (a grid). A non-record
   row: centred label with a hairline either side, spanning the full width. */
li.vve-library__seam {
  grid-column: 1 / -1; list-style: none;
  display: flex; align-items: center; gap: var(--sp-3); margin: var(--sp-2) 0;
  color: var(--smoke); font-family: var(--font-label); font-size: var(--fs-micro);
  letter-spacing: var(--ls-label); text-transform: uppercase;
}
li.vve-library__seam::before, li.vve-library__seam::after {
  content: ""; flex: 1 1 auto; height: 1px; background: var(--line);
}
.vve-library__pagernote { font-size: var(--fs-micro); color: var(--smoke); margin: 0; }
.vve-library__pagernote:focus-visible { outline: 2px solid var(--ivory); outline-offset: 2px; }

/* -- the honesty footnote: what is held back here, and why. */
.vve-library__held { font-size: var(--fs-micro); color: var(--smoke); margin: 0; }
.vve-library__rulelink {
  /* was 98x21 — the only control in this block under the 44px house minimum */
  display: inline-flex; align-items: center; min-height: var(--vve-target);
  background: transparent; border: none; padding: 0; cursor: pointer;
  color: var(--crimson-text); font: inherit;
  text-decoration: underline; text-underline-offset: 3px;
}
@media (hover: hover) { .vve-library__rulelink:hover { color: var(--ivory); } }
.vve-library__rulelink:focus-visible { outline: 2px solid var(--ivory); outline-offset: 2px; border-radius: var(--r-xs); }

/* -- MOBILE: one browser pane at a time. data-level is read ONLY here. */
@media (max-width: 979.98px) {
  .vve-library[data-level="genre"]  .vve-library__pane[data-pane="artist"] { display: none; }
  .vve-library[data-level="artist"] .vve-library__pane[data-pane="genre"]  { display: none; }
  /* Once a lane is picked, the records ARE the answer — D-01 promises they
     refill immediately. Below 980px the artist column drops BELOW them and
     becomes an opt-in narrowing, the way the iOS Music app orders it, instead
     of an alphabetical wall the client must thumb past to reach what they
     asked for. .vve-library__body is already a flex column, so this is order
     only: no DOM move, so focus order and the SR reading order still match. */
  .vve-library[data-level="artist"] .vve-library__panes { order: 3; }
}

/* -- DESKTOP: the iTunes browser pane — Genre | Artist side by side, each
      scrolling internally, above a full-width record list. The stage is NOT
      widened (M-01): no .vve-stage rule is touched, so V1's crate cards keep
      the exact width they have today. */
@media (min-width: 980px) {
  .vve-library__panes { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .vve-library__crumb { display: none; }
  .vve-library__crumb--search { display: flex; }
}
