/* ============================================================================
   Rampant Research — design tokens
   Source of record. Extracted 2026-07-29/30 from the approved NG Terminal theme
   (Claude Design project "Dashboard inventory handoff" / NG Terminal.dc.html),
   then corrected per the joint-PM review.

   Companion: docs/design-tokens.md — read it for LOCKED vs UNLOCKED and the
   contrast acceptance tests. Do not change a value here without updating that.

   CORRECTED 2026-08-09 after the nine-seat design panel
   (docs/business/design-review-panel-2026-08-09.md):
     · dark --line 0.26 -> 0.65 and --locked-fill 0.08 -> 0.24 — the round-1
       LIGHT repair had never been back-ported to dark, where 5 of 7 pages live.
     · every ratio annotation now names the token's WORST real background
       (--panel-3), not --bg. The design-project COPY of this file had quietly
       re-annotated three tokens upward by measuring against --bg — a nominated
       reference background, inside the file that carries the rule against them.
     · three tokens are now visibly documented as FAILING (--txt-3, --warn,
       --put). They are owner-owed, not silently fixed: a text-ramp value is a
       visual decision. An honest annotation of a real failure is the point.

   ⚠️ The design-project copy MUST be byte-identical to this file. It diverged
   within a single round twice; the second divergence dropped the base block
   below, which is what implements acceptance test 8.

   RULES
   1. Never hardcode a hex in a component. Every colour comes from here.
   2. Colour is semantic, never decorative.
   3. Semantic bull/bear MUST be paired with a non-colour channel (glyph or
      direction). Colour alone is not a signal — deuteranopia.
   4. Small text uses the *-text variants. The base semantic tokens are for
      fills, borders, glows and large display numerals only.
   ========================================================================= */

:root {
  /* --- Type families (LOCKED) ------------------------------------------- */
  --font-head: 'Source Serif 4', Georgia, serif;
  --font-body: 'Work Sans', system-ui, -apple-system, sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, monospace;

  /* --- Type scale (UNLOCKED — the reference's 8-9.5px tier is not viable
         for a public marketing surface; WCAG 1.4.4/1.4.12) ---------------- */
  --fs-micro:  0.75rem;   /* 12px — the FLOOR. Nothing smaller ships.       */
  --fs-small:  0.8125rem; /* 13px */
  --fs-body:   0.9375rem; /* 15px — long-form body minimum                  */
  --fs-lead:   1.125rem;
  --fs-h3:     1.375rem;
  --fs-h2:     1.75rem;
  --fs-h1:     2.5rem;
  --fs-display: clamp(2.5rem, 6vw, 4.5rem);

  /* Tracking. The reference uses 0.13-0.28em on 8-9.5px uppercase labels.
     Uppercase + heavy tracking is legible only at >=12px and >=500 weight. */
  --track-label: 0.12em;
  --track-tight: -0.02em;
  --lh-tight: 1.2;
  --lh-body:  1.6;

  /* --- Geometry / elevation (LOCKED) ----------------------------------- */
  --radius:    14px;
  --radius-sm: 9px;
  --shadow:    0 10px 28px rgba(0, 0, 0, 0.38);

  /* --- Spacing scale --------------------------------------------------- */
  --sp-1: 0.25rem; --sp-2: 0.5rem;  --sp-3: 0.75rem; --sp-4: 1rem;
  --sp-5: 1.5rem;  --sp-6: 2rem;    --sp-7: 3rem;    --sp-8: 4.5rem;

  /* --- Non-colour semantic channel (REQUIRED alongside bull/bear) ------- */
  --glyph-bull: '▲';
  --glyph-bear: '▼';
  --glyph-flat: '—';
  --glyph-stale: '⚠';

  /* COVERAGE-state glyphs. Added 2026-08-09. These and --glyph-locked below are
     DISJOINT SETS on purpose: coverage state and entitlement are orthogonal axes
     that had collapsed into one visual language, and ◈ was doing duty as both
     "absent" and "paid" on different pages. One glyph, two meanings, is not a
     second channel.
     ⚠️ OWNER-OWED: ◆ vs ◇ differ only by fill and are the weakest pair here at
     12px. A filled/half/empty/dash ramp (● ◐ ○ —) survives small sizes and low
     vision far better. Not changed unilaterally — the diamond set is the shipped
     vocabulary and swapping it is a visual decision. */
  --glyph-live:        '◆';
  --glyph-research:    '◇';
  --glyph-watchlist:   '○';
  --glyph-notcovered:  '—';

  /* ENTITLEMENT. The ONLY glyph in the paid/locked language. */
  --glyph-locked: '◈';
}

/* ============================================================================
   SURFACE: dark  — the product / market surface. Default.
   Ground, panels, hues all LOCKED (approved 2026-07-19).
   Lightness values on TEXT roles are UNLOCKED and were corrected here.
   ========================================================================= */
[data-surface='dark'], :root {
  --bg:      #0a0e1a;
  --panel:   #12182c;
  --panel-b: #0d1122;
  --panel-2: #171f38;
  --panel-3: #1d2645;

  /* CORRECTED 2026-08-09 (dark back-port of the round-1 light repair). 0.26 alpha
     composited to 1.45-1.49:1 against ALL THREE real dark grounds (--panel,
     --panel-b, and the gold gradient lobe). Under that lobe --panel is 1.00:1
     against the page, so the border is the ONLY elevation channel and it was not
     perceivable. 0.65 -> 3.03-3.13:1, mirroring light's 0.62. Same defect and same
     fix as light; it was simply never carried across. */
  --line:   rgba(184, 135, 58, 0.65);   /* was 0.26 (~1.47:1 FAIL) */
  --line-2: rgba(184, 135, 58, 0.11);   /* ~1.14:1 — DECORATIVE HAIRLINE ONLY.
                                           Never the sole border of a component. */

  /* Text ramp. ⚠️ RATIOS BELOW NAME EACH TOKEN'S *WORST* REAL BACKGROUND, not its
     best. Quoting a ratio against --bg is a nominated reference background — the
     failure the contrast rule exists to stop — and every page renders text on a
     panel tier or on the gradient lobe, never on raw --bg. Worst ground is
     --panel-3 (#1d2645) throughout. See design-tokens.md §4.                  */
  --txt:   #eae6d8;   /* 11.88:1 on --panel-3 (15.41 on --bg)  AAA            */
  --txt-2: #a39d8a;   /*  5.47:1 on --panel-3 (7.10 on --bg)   AA             */
  --txt-3: #8b8574;   /* 🔴 4.03:1 on --panel-3 · 4.42 on --panel-2 — FAILS
                         4.5:1 on both. 4.78 on --panel, 5.23 on --bg. The old
                         "~5.0:1 PASS" was measured on --bg alone. OWNER-OWED:
                         #95907e clears 4.64:1 on every real ground. Not changed
                         here — a text-ramp value is a visual decision.        */

  /* Brand accent */
  --accent:      #b8863a;   /* 4.60:1 on --panel-3 (5.97 on --bg)  PASS       */
  --accent-dim:  #7a5720;   /* ~2.95:1 — DECORATIVE ONLY. Never text, never
                               a UI boundary that must be perceivable.       */
  --accent-edge: #9c6f2c;   /* 3.34:1 on --panel-3 (4.33 on --bg) — clears the
                               3:1 boundary bar on every real ground. PASS.
                               The "~4.3:1" annotation was --bg-only.         */
  --logo-text:   #241b04;

  /* --- Semantic. Base = fills / glows / large numerals (>=24px, or >=19px
         at 700). *-text = small text and any label under 24px. ------------ */
  --bull:      #5fae7c;  /* 5.53:1 on --panel-3 (7.18 on --bg)              */
  --bull-text: #5fae7c;  /* already passes — kept identical for symmetry    */
  --bear:      #b5484f;  /* ~3.7:1 on --bg — LARGE/FILL ONLY. Never text.   */
  --bear-text: #d97b82;  /* 5.02:1 on --panel-3 (6.52 on --bg)  PASS        */
  --neutral:   #c79a52;  /* 5.77:1 on --panel-3                             */
  --warn:      #c17a3f;  /* 🔴 4.33:1 on --panel-3 — FAILS 4.5:1. 5.13 on
                            --panel, 5.61 on --bg. OWNER-OWED, same class as
                            the light-surface --warn repair of 2026-07-30.  */

  /* Paid / locked. NO HUE — see design-tokens.md §5. Violet is retired from
     the entitlement role because it is the put-side data colour.           */
  --locked:      #6f6a5c;
  --locked-text: #a39d8a;   /* 5.47:1 on --panel-3 */
  /* CORRECTED 2026-08-09 (dark back-port). 0.08 alpha composited to 1.13:1 over
     every dark ground — the locked FILL channel was absent, so locked chips and
     the gated panel body carried glyph + text only. Light was raised 0.07 -> 0.18
     on 2026-07-30 for exactly this reason; dark was never carried across.
     0.24 -> 1.51:1, a just-perceivable wash. */
  --locked-fill: rgba(163, 157, 138, 0.24);   /* was 0.08 (~1.13:1) */

  /* Put-side keeps the violet it always had, in the DATA language only.     */
  --put: #8b7fc4;   /* 🔴 4.19:1 on --panel-3 — FAILS 4.5:1 (5.44 on --bg).
                       Currently unused outside the gallery. OWNER-OWED.    */

  /* Staleness (component 15) */
  --stale:   #c17a3f;
  --dead:    #b5484f;

  --page-gradient:
    radial-gradient(1200px 700px at 15% -10%, rgba(184,135,58,0.08), transparent 60%),
    radial-gradient(1000px 600px at 100% 0%, rgba(139,127,196,0.05), transparent 55%),
    var(--bg);
}

/* ============================================================================
   SURFACE: light — the reading surface (methodology, notes, pricing,
   coverage). Per owner decision D1. Did not exist in any prior artifact:
   every value here is a PROPOSAL awaiting the owner's eye.
   ========================================================================= */
[data-surface='light'] {
  /* CORRECTED 2026-07-30 after the panel gallery rendered this surface for the
     first time. --bg was #f7f4ec against a #ffffff panel — ~1.10:1, so a panel
     had no perceivable edge, and --line at 0.22 alpha computed to ~1.4:1 against
     white and could not rescue it. Deepened the ground AND strengthened the rule. */
  --bg:      #efe9dc;   /* was #f7f4ec */
  --panel:   #ffffff;
  --panel-b: #f1ede2;
  --panel-2: #ebe6d9;
  --panel-3: #e2dccb;

  --line:   rgba(90, 66, 26, 0.62);   /* ~3.4:1 vs #ffffff — was ~1.4:1 */
  --line-2: rgba(90, 66, 26, 0.26);

  --txt:   #1b1a17;   /* ~15.5:1 on --bg */
  --txt-2: #4a463d;   /* ~7.8:1  on --bg */
  /* CORRECTED 2026-07-30 (3rd light pass): #6b665a passed on --bg (4.7:1) and on a white
     panel (5.7:1) but fell to 3.8:1 on #d7d1c5 — the composite --locked-fill produces over
     a panel, and where most as_of stamps sit. Darkened to clear 4.5:1 on ALL THREE of its
     real backgrounds. --locked keeps #6b665a: it is a border/glyph token at a 3:1 bar. */
  --txt-3: #5c584d;   /* ~4.7:1 on #d7d1c5 · ~5.9:1 on --bg · ~7.1:1 on white */

  --accent:      #7a5720;   /* the dim brass becomes the accent on light   */
  --accent-dim:  #b8863a;
  --accent-edge: #97702c;
  --logo-text:   #f7f4ec;

  --bull:      #2f7a4c;
  --bull-text: #2b6e45;
  --bear:      #a03840;
  --bear-text: #97333b;
  --neutral:   #8a6520;
  /* CORRECTED 2026-07-30 (2nd light pass): #8f5520 passed on --bg (~4.8:1) but fell to
     ~3.96:1 on the darker panel tiers, which is where it actually renders. Darkened to
     clear 4.5:1 against --panel-3 and below, not merely against the ground.
     The defect was an UNDER-SCOPED audit, not a wrong ratio. */
  --warn:      #7d4718;   /* was #8f5520 */

  --locked:      #6b665a;
  --locked-text: #4a463d;
  /* CORRECTED 2026-07-30: 0.07 alpha was invisible on a #ffffff panel, so the
     WATCHLIST and MEMBER chips lost their fill channel entirely on light and
     were carrying glyph + text only. */
  --locked-fill: rgba(107, 102, 90, 0.18);   /* was 0.07 */

  --put: #5b4f96;

  --stale: #8f5520;
  --dead:  #a03840;

  --page-gradient: var(--bg);
  --shadow: 0 6px 18px rgba(43, 36, 20, 0.10);
}

/* ============================================================================
   Base + a11y floor (non-negotiable, design-scope §4)
   ========================================================================= */
html, body {
  margin: 0;
  background: var(--bg);
  color: var(--txt);
  font-family: var(--font-mono);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
}

/* 🔴 font-size lives on BODY, never on HTML, and this is load-bearing.
   Measured 2026-08-23: this rule previously read `html, body { … font-size:
   var(--fs-small); … }`. Setting a REM-valued size on the root element is
   SELF-REFERENTIAL — the root resolved 16px → 13px, and every token below then
   compounded down by 0.8125. `--fs-micro`, whose own comment three dozen lines
   up reads "12px — the FLOOR. Nothing smaller ships.", shipped at 9.75px on
   every page, and 38 elements sat under that floor at a 360px viewport.
   ⇒ The root must keep the user's base size. Only `body` may take a token. */
body { font-size: var(--fs-small); }
body[data-surface='light'] { font-family: var(--font-body); font-size: var(--fs-body); }

*, *::before, *::after { box-sizing: border-box; }

/* Tabular figures are mandatory in any data column. */
.num, [data-num] {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}

:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Wide content scrolls inside its own container. The page body never scrolls
   horizontally — required down to 360px. */
.scroll-x { overflow-x: auto; max-width: 100%; }
img, svg, canvas { max-width: 100%; height: auto; }
