/* ==========================================================================
   TELL — theme.css · Harbor Noir tokens
   ==========================================================================
   NO LIGHT THEME, BY DESIGN. This game commits to nocturne: Corvin Bay is a
   harbor city at night, the premise is rain-on-glass, and the palette is the
   art direction (design/30-assets.md, "Harbor Noir"). Golden hour is banned;
   the one warm exception is The Meridian (brass), applied via a body class
   (`body.interlude`) so the devil's room can be the coziest room in the game.

   Color law (design pillars):
   - The Gift renders in desaturated silver monochrome (--hn-silver). Meaning
     would be color; the Gift never supplies it.
   - NO red / NO green anywhere in the cue or choice grammar — polarity and
     option kinds are encoded by SHAPE + LABEL, never by stoplight colors.
   - "Insufficient evidence" owns its own calibration color (--hn-calibration):
     first-class, never a coward grey.
   ========================================================================== */

:root {
  /* --- ground -------------------------------------------------------- */
  --hn-ink: #0a1418;            /* harbor night — UI ground (shell agrees)  */
  --hn-ink-deep: #070e12;       /* deepest shadow mass                      */
  --hn-deep: #0e1c22;           /* raised surfaces / panel ground           */
  --hn-teal: #16323b;           /* structural teal — borders, plates        */
  --hn-teal-bright: #1e4e56;    /* Corvin Teal — rain, glass, water         */
  --hn-slate: #5c6b78;          /* Slate Rain — overcast midtone            */
  --hn-rain: #8fa7ad;           /* rain-grey secondary text                 */

  /* --- signal -------------------------------------------------------- */
  --hn-silver: #c9d2d4;         /* Gift Silver — primary text, cue render   */
  --hn-white: #f4f7f9;          /* Signal White — highlights only           */
  --hn-gold: #b9a67c;           /* desaturated gold — cue pulse, focus ring */

  /* --- points (accents only, never washes) ---------------------------- */
  --hn-sodium: #d97a32;         /* streetlight points                       */
  --hn-rose: #c9438a;           /* drowned neon (NOT #FF00FF — reserved)    */

  /* --- the exception -------------------------------------------------- */
  --hn-brass: #c9973f;          /* Meridian Brass — interlude scenes only   */
  --hn-oxblood: #5a2a2e;        /* Meridian oxblood                         */

  /* --- A10 The Mask (v1.9 §23.1) --------------------------------------- */
  /* LEAF BRASS. The gilt of a picture frame in a municipal building, borrowed
     from the apartment lobby's mailbox bank and ruled low-chroma — and it is
     explicitly NOT --hn-brass above (ruling R2: Meridian Brass is the interlude
     hue and belongs to Aster's rooms). It is drawn as a DOUBLE RULE in dull ink
     on card stock: no sheen, no gradient, no glow, no animation. A gilt frame is
     a MOUNT, never a verdict — it says "this one has been mounted", and the
     instant it says "this one is false" the ability is a lie detector. */
  --hn-leaf: #8e7a4a;           /* Leaf Brass — the gilt frame, and only that */

  /* --- calibration ---------------------------------------------------- */
  --hn-calibration: #7d93b2;    /* "insufficient evidence" — its own color  */

  /* --- semantic aliases (what components actually consume) ------------ */
  --accent: var(--hn-gold);          /* interactive accent / focus          */
  --plate-edge: var(--hn-teal);      /* speaker plate + panel edges         */
  --surface: rgba(14, 28, 34, 0.92); /* dialogue / menu surfaces            */
  --surface-line: rgba(30, 78, 86, 0.55);
  --text: var(--hn-silver);
  --text-dim: var(--hn-rain);

  /* --- type ------------------------------------------------------------ */
  --font-prose: Georgia, 'Times New Roman', serif;          /* narration/dialogue */
  --font-ui: 'Segoe UI', system-ui, -apple-system, sans-serif; /* chips, labels  */
  --fs-line: clamp(1.02rem, 1.6vw, 1.22rem);
  --fs-ui: 0.72rem;
  --track-ui: 0.22em;

  /* --- motion ---------------------------------------------------------- */
  --t-cut: 0ms;
  --t-fade: 240ms;
  --t-xfade: 520ms;   /* the A/B dissolve: the board's own rhythm, and the cue itself */
  --t-slow: 1200ms;
  --t-ui: 180ms;

  /* --- live scene atmosphere (JS-driven) ------------------------------- */
  --tension: 0;                 /* 0..1 — scene pressure, set by the HUD    */
}

/* --------------------------------------------------------------------------
   Interlude override — The Meridian's brass warmth, via body class only.
   Everything that consumes the aliases warms; nothing else changes.
   -------------------------------------------------------------------------- */
body.interlude {
  --accent: var(--hn-brass);
  --plate-edge: #4a3a22;
  --surface: rgba(28, 21, 13, 0.93);
  --surface-line: rgba(201, 151, 63, 0.30);
  --text-dim: #a89578;
}

/* --------------------------------------------------------------------------
   Base
   -------------------------------------------------------------------------- */
html {
  color-scheme: dark; /* commit — there is no light theme to fall back to */
}

body {
  background: var(--hn-ink);
  color: var(--text);
  font-family: var(--font-prose);
  -webkit-font-smoothing: antialiased;
}

::selection {
  background: rgba(185, 166, 124, 0.30);
  color: var(--hn-white);
}

/* Quiet noir scrollbars (codex drawer, ledger strip) */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--hn-teal) transparent;
}
*::-webkit-scrollbar { width: 8px; height: 8px; }
*::-webkit-scrollbar-thumb { background: var(--hn-teal); border-radius: 4px; }
*::-webkit-scrollbar-track { background: transparent; }

/* --------------------------------------------------------------------------
   Accessibility primitives
   -------------------------------------------------------------------------- */

/* Keyboard focus is always visible, in the accent (gold / brass) — never
   suppressed. Pointer users don't see it (focus-visible). */
:focus { outline: none; }
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 2px;
}

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip: rect(0 0 0 0); clip-path: inset(50%);
  overflow: hidden; white-space: nowrap;
}

/* Small-caps UI label idiom, used by chips/tags game-wide */
.ui-label {
  font-family: var(--font-ui);
  font-size: var(--fs-ui);
  letter-spacing: var(--track-ui);
  text-transform: uppercase;
  color: var(--text-dim);
}

/* --------------------------------------------------------------------------
   Reduced motion — global stance. Component animations also guard
   individually in stage.css/ui.css; this is the safety net.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  /* Looping/long animation is the real vestibular risk, so it stays clamped hard.
     TRANSITIONS are not clamped with !important any more: this blanket rule was
     overriding every tailored reduced-motion rule in stage.css AND every
     deliberate short fade — the establishing card's 420ms opacity fade simply
     never ran for anyone whose OS has reduce-motion on, which is how it was
     found. Component rules now win by specificity, and each animated element in
     stage.css already declares what it does under reduce-motion. Anything that
     forgot to still falls back to the near-instant default below. */
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
  }
  *, *::before, *::after { transition-duration: 0.01ms; }
}
