/* ════════════════════════════════════════════════════════════════════════════
   COSIGNA — canonical design token set (web surfaces)
   WP1: token target definition. NOT YET WIRED INTO PAGES.
   Migration target for WP2 (web) and build input for WP3 (PDF/offline-verifier).

   Authored: 2026-06-12 · Service v0.121.3
   Source: UX/theme/tokens.inventory.json (generated by scripts/scan_brand_tokens.py)

   READING GUIDE
   ─────────────
   This file is divided into two @layer blocks:

   1. @layer protected — colours that encode INTEGRITY VERDICTS.
      A skin MUST NOT override these. The pickup tool (WP9) refuses to export them.
      Overriding --verdict-ok / --verdict-danger can make a BROKEN proof look OK.

   2. :root (global) — the full palette + semantic skin tokens.
      A white-label skin may override any of these in its own :root or
      [data-theme="..."] block.

   EXISTING `:root` VARIABLE MAPPING (for WP2 find-and-replace reference)
   ───────────────────────────────────────────────────────────────────────
   The per-file :root blocks that exist today will be REPLACED by a single
   <link> to this file during WP2. Mapping of existing vars → canonical names:

   File: UX/verifier/verifier.css (lines 7-51)
     --ink           → --brand-ink
     --paper         → --surface-paper
     --ivory         → --surface-ivory
     --gold          → --brand-gold
     --success       → --verdict-ok            ← PROTECTED
     --danger        → --verdict-danger         ← PROTECTED
     --muted         → --text-muted
     --ag-success    → --verdict-ok             ← PROTECTED (alias)
     --ag-danger     → --verdict-danger         ← PROTECTED (alias)
     --ag-warning    → --state-warning
     --ag-white      → --color-white
     --ag-gray-50    → --surface-bg-tint
     --ag-gray-100   → --surface-ivory
     --ag-gray-200   → --border-default
     --ag-gray-400   → --text-gray-400
     --ag-gray-500   → --text-muted
     --ag-gray-900   → --brand-ink
     --bg            → --bg
     --surface       → --surface-paper
     --surface-2     → --surface-ivory
     --text          → --brand-ink
     --text-muted    → --text-muted
     --border        → --border-default
     --field         → --field
     --accent        → --brand-gold
     --grad          → --gradient-header
     (verifier.css:13-14, 62-63: --success/--danger marked PROTECTED ✓ WP0 done)

   File: UX/desktop-initiator/initiator.css (lines 7-28) — same mapping as verifier.css
   File: UX/mobile-signer/signer.css (lines 7-52) — same mapping + --ag-gray-700 → --text-gray
   File: UX/account/account.css (lines 7-27) — same mapping
   File: UX/admin/admin.css (lines 5-48) — same mapping + status vars below:
     --st-open       → --state-open (maps to --brand-ink)
     --st-closed     → --state-closed (maps to --verdict-ok)    ← PROTECTED source
     --st-aborted    → --state-abort
     --st-expired    → --state-expired
     --sev-error     → --state-abort (maps to --verdict-danger)  ← PROTECTED source
     --sev-warn      → --state-expired

   File: UX/landing/index.html inline :root (line 42) — similar, but uses
     --cream / --green / --red as aliases; WP2b normalises to canonical names.

   ════════════════════════════════════════════════════════════════════════════ */


/* ┌─────────────────────────────────────────────────────────────────────────┐
   │  @layer protected — SKINS MUST NOT OVERRIDE                            │
   │                                                                         │
   │  These colours carry INTEGRITY meaning. A skin that overrides them can  │
   │  make a cryptographically-BROKEN proof render as green/OK.              │
   │                                                                         │
   │  The WP9 pickup tool reads this block and REFUSES to let a tenant theme │
   │  export any token listed here (the property values are locked in the    │
   │  export logic; the names are the gate key).                             │
   │                                                                         │
   │  WP0 already wired verifier.css and certificate.py to these values;    │
   │  they are frozen here as the single source of truth.                   │
   │                                                                         │
   │  DARK-MODE NOTE: the dark-mode adjustments of --verdict-ok /           │
   │  --verdict-danger (#5bbf8e / #e8736b) are included here. They appear   │
   │  in verifier.css [data-theme="dark"] and signer.css. A white-label     │
   │  skin may brighten/dim them if the NON-COLOUR WP0 cues remain intact   │
   │  (glyph + border-style), but the TOKEN NAMES must map to the same      │
   │  semantic verdict slot. FLAGGED FOR OPUS: confirm whether the dark-mode │
   │  variants should be hard-locked or skin-adjustable.                    │
   └─────────────────────────────────────────────────────────────────────────┘ */

@layer protected {
  :root {
    /*
     * ── Integrity / verdict tokens ──────────────────────────────────────── *
     * These are the ONLY colours that may appear on .verdict--ok and
     * .verdict--broken / .verdict--doc-mismatch elements, and on the
     * certificate.py confirmed/failed pill.
     */

    /* Confirmed / anchored state (teal — the loop is closed) */
    --verdict-ok:          #0F766E;  /* = --success in verifier.css:13 (WP0) */
    --verdict-ok-dark:     #5bbf8e;  /* dark-mode override (verifier.css:62) */

    /* Failure / tampered state (danger red) */
    --verdict-danger:      #B91C1C;  /* = --danger in verifier.css:14 (WP0) */
    --verdict-danger-dark: #e8736b;  /* dark-mode override (verifier.css:63) */

    /* v0.200 P0-5: Pending / not-yet-closed state (amber — distinct from ok-teal AND danger-red) */
    /* PROTECTED: a hostile skin that makes this green would turn an unanchored/pending proof look OK. */
    --verdict-pending:      #92520A;  /* deep amber — MUST NOT equal --verdict-ok; brand_palette guards this */
    --verdict-pending-dark: #d97706;  /* dark-mode variant (Tailwind amber-600, legible on dark bg) */

    /* v0.409.1: Anchor completion state — PROTECTED (dedicated tokens so a tenant
     * cannot spoof the anchor-dot state via --gold/--green overrides). */
    --anchor-complete:      #2E7D5B;  /* anchor confirmed (green — distinct from verdict-ok teal) */
    --anchor-pending:       #C3A14B;  /* anchor pending (gold/amber — matches the existing --gold) */

    /*
     * ── Brand soul / seal geometry ──────────────────────────────────────── *
     * These two colours define the COSigna SEAL (the closing arc of the ring
     * and the navy background of the brand lockup). They are protected because
     * the seal IS the integrity signal — a skin that changes the seal geometry
     * colour can break the visual chain-of-trust signal.
     *
     * WP2 SPLIT NOTE: --brand-ink and --brand-gold are ALSO used for ordinary
     * chrome (headers, borders, button backgrounds). During WP2 migration, the
     * seal-specific uses must be split into --seal-ink / --seal-gold references
     * so the chrome uses can be freed for skinning while the seal remains locked.
     * FLAGGED FOR OPUS: confirm this split strategy before WP2 begins.
     */

    /* Primary navy — brand lockup, seal geometry, all integrity-adjacent ink */
    --brand-ink:     #14253D;  /* = --ink / --text / --grad start in all CSS files */
    --seal-ink:      #14253D;  /* WP2 target alias for seal-only uses (same value, separate token) */

    /* Seal gold ring — the closing arc of the COSigna ring */
    --brand-gold:    #C3A14B;  /* = --gold / --accent in all CSS files */
    --seal-gold:     #C3A14B;  /* WP2 target alias for seal/ring arc uses */
  }

  /*
   * v0.501.0 Stream A fold 1b — COBRAND CONTAINER GEOMETRY PIN
   * A tenant CSS rule targeting .cobrand / #cobrand-logo CANNOT use position/inset/transform
   * (blocked at upload by skin_validate.py _cobrand_block_declarations_safe).  These !important
   * pins are a defence-in-depth backstop: even if a bug in the validator ever lets a position
   * or overflow-breaking rule through, the protected-layer geometry pins ensure the cobrand slot
   * stays in-flow and bounded.  Overflow:hidden prevents child elements from leaking outside the
   * allocated slot and covering the wordmark / verdict banner above.
   * NOTE: recap/index.html also carries equivalent inline pins because recap loads NO tokens.css.
   */
  .cobrand {
    position: static !important;
    max-height: 120px !important;
    overflow: hidden !important;
  }
  #cobrand-logo {
    position: static !important;
    max-width: 200px !important;
    max-height: 80px !important;
    overflow: hidden !important;
  }
}


/* ┌─────────────────────────────────────────────────────────────────────────┐
   │  :root — full skin palette (theme-overridable)                          │
   └─────────────────────────────────────────────────────────────────────────┘ */

:root {
  /* ── Core brand colours (skin copies; protected layer holds the originals) */
  --brand-ink:       #14253D;  /* PROTECTED — also defined in @layer protected */
  --brand-gold:      #C3A14B;  /* PROTECTED — also defined in @layer protected */
  --verdict-ok:      #0F766E !important;  /* PROTECTED — also defined in @layer protected; !important = unlayered cascade lock (beats a tenant :root override) */
  --verdict-danger:  #B91C1C !important;  /* PROTECTED — also defined in @layer protected; !important = unlayered cascade lock (beats a tenant :root override) */
  --verdict-pending: #92520A !important;  /* v0.200 P0-5: PROTECTED — 3rd integrity state (amber); !important = unlayered cascade lock */
  --anchor-complete: #2E7D5B !important;  /* v0.409.1: PROTECTED — anchor confirmed state; !important = unlayered cascade lock */
  --anchor-pending:  #C3A14B !important;  /* v0.409.1: PROTECTED — anchor pending state; !important = unlayered cascade lock */

  /* ── Paper / background surface tokens ──────────────────────────────────── */
  --surface-paper:   #FAF8F3;  /* --paper / --surface / body bg (warm near-white) */
  --surface-ivory:   #F3EFE6;  /* --ivory / --surface-2 (slightly warmer panel fill) */
  --surface-bg:      #EDE8DD;  /* --bg (light-mode outer background, slightly darker) */
  --surface-warm:    #fffdf8;  /* warm near-white (landing, recap page surfaces) */
  --field:           #ffffff;  /* form field background (--field in CSS files) */

  /* v0.301.3 — Always-dark brand-chrome foreground. The topbar / verifier header is ALWAYS
     navy in BOTH colour schemes (brand chrome, never skin-themed), so its text + lockup must
     be a FIXED light colour. Header foregrounds MUST bind to --on-ink, NEVER to
     --paper / --surface-paper (those correctly flip to dark in dark mode → dark-on-dark
     header = the bug). INVARIANT: --on-ink is declared ONLY here and is NEVER redefined in
     any dark-mode block. Enforced by tests/test_css_dark_mode_guard.py. */
  --on-ink:          #FAF8F3;  /* paper-on-navy chrome text (scheme-independent) */

  /* ── Typography tokens ───────────────────────────────────────────────────── */
  --text-ink:        #14253D;  /* = --brand-ink; alias for body text / --text */
  --text-muted:      #5e6571;  /* v0.532.0 D-5b WP5: #6B7280→#5e6571 — AA margin for muted body text over the aurora (landing 4.36→5.30). Only deepens light-mode muted; dark override (#8f9dae) untouched. */
  --text-warm-muted: #8a7d5f;  /* version / sub-header muted on cream (server.py) */
  --text-secondary:  #3b4a5e;  /* secondary body text (mailer body copy) */
  --text-gray:       #374151;  /* Tailwind gray-700 / --ag-gray-700 (signer.css) */
  --text-gray-400:   #9ca3af;  /* --ag-gray-400 */

  /* ── Border tokens ───────────────────────────────────────────────────────── */
  --border-default:  #E3DCCC;  /* --border (light mode warm-beige border) */
  --border-warm:     #e3ddd0;  /* warm border variant (landing, nav menus) */
  --border-soft:     #e2dccc;  /* slightly softer warm border (recap, legal) */
  --border-subtle:   #d9d2c2;  /* very subtle border (story inline CSS) */

  /* ── Brand gold derivatives ──────────────────────────────────────────────── */
  --brand-gold-dark: #7e6314;  /* v0.532.0 D-5b WP5: #8a6d1f→#7e6314 — AA margin for gold links over the aurora (landing 4.42→5.15). Darkened gold for AA link contrast on cream. */
                               /* AMBIGUOUS: could be derived as a hsl() step — see scanner */
  --brand-gold-muted:#9a7b2e;  /* muted gold (admin/navmenu footer link) */

  /* ── Gradient ─────────────────────────────────────────────────────────────── */
  --gradient-header: linear-gradient(135deg, #14253D, #1d3147);
                     /* --grad in all CSS files; end stop is skin-overridable */
  --gradient-end:    #1d3147;  /* --surface-ink-raised / gradient end / --surface-2 dark */

  /* ── Semantic state tokens (non-integrity; skin layer) ───────────────────── */
  /* WARNING: not-closed / open ring / pending states */
  --state-warning:   #B26A00;  /* amber warning (verifier.css .verdict--not-closed) */
  --state-warning-alt: #8a6d1d;/* amber warning alt (initiator.js timeout banner) */
  --state-expired:   #9a8030;  /* admin.css --st-expired / --sev-warn */
  --state-attestation: #7a4400;/* verifier.css .verdict--attestation */
  --state-pending:   #f59e0b;  /* Tailwind amber-500 / signer.css --ag-warning */

  /* ABORT / UI error states (NOT integrity verdicts — skin layer) */
  --state-abort:     #B3261E;  /* initiator.js abort banner (Material-You error red) */
                               /* AMBIGUOUS: close to --verdict-danger but distinct hex */
                               /* Opus to rule: collapse to --verdict-danger or keep separate? */

  /* OK/confirmed state variants used in signer (gesture fill, account banner) */
  --state-ok-fallback: #16a34a; /* JS var(--success,#16a34a) fallback in ceremony-gesture.js */
                                /* AMBIGUOUS: should normalise to var(--verdict-ok)? */
  --state-ok-muted:    #2e7d5b; /* recap page green (lighter than verdict-ok) */
  --state-ok-bright:   #46b385; /* light ok tint (recap dark mode --green) */

  /* Verdict danger border (darker variant for dashed border on --broken) */
  --verdict-danger-border: #8c1d18; /* verifier.css .verdict--broken dashed border */

  /* Focus ring (keyboard accessibility) */
  --focus-ring: #2563eb;  /* ceremony-gesture.js focus-visible outline fallback */

  /* ── Dark-mode semantic state surface colours ─────────────────────────────── */
  --state-ok-dark-container: #14532d;  /* signer.css dark .verify-status--ok bg */
  --state-ok-vivid: #4ade80;           /* signer.css dark ok text */
  --state-ok-bright-alt: #86efac;      /* signer.css dark ok border */

  /* ── Skin surface tints (used in server.py f-strings, legal pages, landing) */
  --surface-gold-tint:   #fbf3df;  /* legal banner bg (golden-tint) */
  --surface-warn-tint:   #faf0ec;  /* legal disclaimer bg (warm-tint) */
  --surface-green-tint:  #eef3ee;  /* legal callout bg (green-tint) */
  --surface-bg-tint:     #f9fafb;  /* --ag-gray-50 equivalent */

  /* ── Typography ──────────────────────────────────────────────────────────── */
  --font: 'Outfit', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  --font-mono: ui-monospace, 'Cascadia Code', 'Source Code Pro', monospace;

  /* ── Spacing (8pt grid — carried from verifier.css; not colour tokens but
        part of the canonical design system) ──────────────────────────────── */
  --s1: 4px;  --s2: 8px;   --s3: 12px;  --s4: 16px;
  --s5: 20px; --s6: 24px;  --s8: 32px;  --s12: 48px;

  /* ── Border-radius ────────────────────────────────────────────────────────── */
  --radius-sm: 4px;   --radius-md: 8px;
  --radius-lg: 12px;  --radius-xl: 16px;
  --radius-full: 9999px;

  /* ── Shadow ──────────────────────────────────────────────────────────────── */
  --shadow: 0 1px 2px rgba(20,37,61,.06), 0 12px 30px -12px rgba(20,37,61,.18);
}


/* ┌─────────────────────────────────────────────────────────────────────────┐
   │  MATERIAL SYSTEM — "liquid glass" (v0.532.0 D-5b, UX Revamp Phase 2)    │
   │  Source of truth: docs/MOCKUP_ux_revamp_extended_2026-07-19.html —      │
   │  founder-validated 2026-07-19 ("Looks nice" + the liquid-glass ruling). │
   │  Every stop / blur radius / rim shadow below is copied VERBATIM from    │
   │  that mockup; do not re-derive or "improve" a value — the mockup's own │
   │  inline comments carry the measured WCAG ratios that justify each one.  │
   │                                                                         │
   │  LIGHT values are the default (below). DARK overrides live in BOTH      │
   │  dark-mode blocks further down (@media prefers-color-scheme AND         │
   │  [data-theme="dark"]) — kept in sync; that split is load-bearing.       │
   │                                                                         │
   │  THE TWO GOLDS — resolved, not duplicated: the mockup's 4-stop gold     │
   │  ramp does not introduce a parallel palette. It SLOTS the two golds     │
   │  this file already had into a named family: --brand-gold-dark          │
   │  (#8a6d1f, above) = the ramp's "deep" stop; --brand-gold's own          │
   │  dark-mode override (#d8b864, below — = register.yaml's documented     │
   │  "gold_dark") = the ramp's "bright" stop; --brand-gold light (#C3A14B) │
   │  = the ramp's base stop. Only ONE value is genuinely new —              │
   │  --gold-brightest — the ramp's top stop, not previously in canon.       │
   │                                                                         │
   │  VERDICT CARVE-OUT: none of these tokens may be consumed by .verdict /  │
   │  .verdict-banner — that surface stays flat/opaque per @layer protected  │
   │  above and PLAN_ux_revamp_phase2_aesthetic §WP2. Enforced by e2e        │
   │  spec 44 (verdict-lock) + spec 60 (skin-integrity-guard).                │
   └─────────────────────────────────────────────────────────────────────────┘ */

:root {
  /* the 4th gold rung — the other three already exist as canonical tokens,
     see "THE TWO GOLDS" above (--brand-gold-dark / --brand-gold / its dark override) */
  --gold-brightest: #F5CC6B;

  /* ── Aurora underlay — brand-hue blooms behind chrome+body; LIGHT default;
        dark override in both dark-mode blocks below (mockup :107-116) ────── */
  --material-aurora:
    radial-gradient(58% 44% at 10% 4%,  rgba(245,204,107,.34), transparent 70%),
    radial-gradient(52% 40% at 94% 26%, rgba(53,80,122,.22),  transparent 72%),
    radial-gradient(60% 46% at 72% 99%, rgba(195,161,75,.26), transparent 70%);

  /* ── Chrome (topbar) material — the SAME in both registers on purpose: the
        "dark-vault" chrome is theme-independent brand chrome, never skin-
        themed (mockup :118-132, comment "BOTH modes") ─────────────────────── */
  --material-chrome-bg:
    linear-gradient(180deg, rgba(255,255,255,.20), rgba(255,255,255,.05) 38%, rgba(255,255,255,0) 62%),
    linear-gradient(135deg,#223a5e 0%,#16294a 46%,#0d1a2c 100%);
  --material-chrome-fg: #FAF8F3;
  --material-chrome-sub-fg: #e8eef7; /* explicit tone, NOT opacity — .72 alpha measured 3.59:1 */
  --material-chrome-blur: blur(18px) saturate(1.5);
  --material-chrome-rim: inset 0 1px 0 rgba(255,255,255,.34), inset 0 -1px 0 rgba(0,0,0,.42);

  /* ── Body — translucent warm-paper (LIGHT); vault override below (mockup :134-139) ── */
  --material-body-bg: linear-gradient(180deg, rgba(250,248,243,.80), rgba(243,239,230,.62));
  --material-body-blur: blur(22px) saturate(1.25);

  /* ── Title shades — 3-stop DIAGONAL gradient-clip for hero <h1> text
        (mockup :151-158). Applied via .span-navy / .span-gold below. ─────── */
  --shade-navy: linear-gradient(115deg,#0d1a2c 0%,var(--brand-ink,#14253D) 38%,#43629a 100%);
  --shade-gold: linear-gradient(115deg,#FFE3A0 0%,var(--gold-brightest) 34%,var(--brand-gold,#C3A14B) 100%);

  /* ── CTA primary — gold 3-stop ramp + sheen + specular rim + soft bloom.
        LIGHT default; dark override below (mockup :164-177). Light bottom
        stop #b08e3a measures 4.98:1 against ink — widest ramp that clears AA. ── */
  --material-cta-primary-bg:
    linear-gradient(180deg, rgba(255,255,255,.55), rgba(255,255,255,.10) 44%, rgba(255,255,255,0) 62%),
    linear-gradient(180deg,#F5CC6B 0%,#d8b864 46%,#b08e3a 100%);
  --material-cta-primary-fg: var(--brand-ink, #14253D);
  --material-cta-primary-rim:
    inset 0 1px 0 rgba(255,255,255,.85), inset 0 -1.5px 0 rgba(101,77,20,.42),
    0 6px 18px -6px rgba(176,142,58,.55);

  /* ── CTA secondary — the glass tier: translucent pane, blurred, rim-lit,
        no fill of its own. LIGHT default; dark override below (mockup :178-186) ── */
  --material-cta-ghost-bg: linear-gradient(180deg, rgba(255,255,255,.62), rgba(255,255,255,.28));
  --material-cta-ghost-border: rgba(20,37,61,.28);
  --material-cta-ghost-fg: var(--brand-ink, #14253D);
  --material-cta-ghost-blur: blur(12px) saturate(1.4);
  --material-cta-ghost-rim: inset 0 1px 0 rgba(255,255,255,.9), 0 4px 14px -8px rgba(20,37,61,.35);

  /* ── Cards / rows — LIGHT default; the dark override below is SMOKED, not
        frosted (mockup :191-209 — see the WP3 note on the dark block below) ── */
  --material-card-bg: linear-gradient(180deg, rgba(255,255,255,.86), rgba(255,255,255,.52));
  --material-card-border: rgba(255,255,255,.72);
  --material-card-blur: blur(16px) saturate(1.45);
  --material-card-rim: inset 0 1px 0 rgba(255,255,255,.95), 0 8px 22px -12px rgba(20,37,61,.30);
  --material-card-radius: 14px;
}

/* ── Title-shade utility classes — apply to a hero <h1> (or a <span> inside
      one). a11y trap: background-clip:text + color:transparent shows NOTHING
      if the clip doesn't render (forced-colours, some AT, ancient engines) —
      so a real, opaque `color:` fallback is set FIRST and the clip only
      engages behind an @supports gate; forced-colors gets an explicit reset
      too. This is progressive enhancement, matching PLAN_ux_revamp_phase2's
      WP1 a11y note verbatim. ─────────────────────────────────────────────── */
.span-navy,
.span-gold {
  /* solid fallback colour — always visible even where the clip is unsupported */
  color: var(--brand-ink, #14253D);
}
.span-gold { color: var(--gold-brightest, #F5CC6B); }

@supports (background-clip: text) or (-webkit-background-clip: text) {
  .span-navy {
    background: var(--shade-navy);
    -webkit-background-clip: text; background-clip: text;
    -webkit-text-fill-color: transparent; color: transparent;
  }
  .span-gold {
    background: var(--shade-gold);
    -webkit-background-clip: text; background-clip: text;
    -webkit-text-fill-color: transparent; color: transparent;
  }
}
@media (forced-colors: active) {
  /* forced-colours can honour @supports yet still ignore the visual clip result —
     fall back explicitly to plain system text rather than risk invisible text. */
  .span-navy, .span-gold {
    background: none; -webkit-text-fill-color: currentColor; color: CanvasText;
  }
}


/* ┌─────────────────────────────────────────────────────────────────────────┐
   │  Dark-mode overrides (skin layer — overridable)                         │
   │  The PROTECTED integrity token overrides (--verdict-ok-dark etc.) are   │
   │  listed here too for completeness; they are also in @layer protected.   │
   └─────────────────────────────────────────────────────────────────────────┘ */

/* v0.301.3 ROOT-CAUSE FIX (founder: "colour issues solved once and for all").
   This block previously opened `[data-theme="dark"], @media (prefers-color-scheme: dark) {`
   — an @media at-rule used as a member of a SELECTOR LIST, which is INVALID CSS. Every
   engine DROPS the entire block, so the canonical prefers-color-scheme dark overrides NEVER
   applied: --surface-paper / --text-ink / --field stayed at their LIGHT values on a device
   in OS dark mode. Per-file CSS then half-compensated with its own literals → the
   "Frankenstein half-dark" state the founder photographed (cream topbar + dark-on-dark
   inputs). This is the SAME bug class initiator.css fixed in v0.77.0 — but the canonical
   SOURCE here was missed, which is why the colour issues kept recurring. Split into a
   PROPER standalone @media at-rule; the [data-theme="dark"] selector form has its own
   valid block below. Guarded fleet-wide by tests/test_css_dark_mode_guard.py + e2e spec 45. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    /* ── Surface ─────────── */
    --bg:             #0c1726;
    --surface-paper:  #16273f;
    --surface-ivory:  #1d3147;
    --surface-bg:     #0c1726;  /* v0.301.3: was MISSING in BOTH dark blocks → any var(--surface-bg) (e.g. the account/initiator topbar dark override) resolved to the LIGHT cream #EDE8DD → cream topbar. */
    --field:          #0f2034;

    /* ── Typography ──────── */
    --text-ink:       #FAF8F3;
    --text-muted:     #8f9dae;  /* v0.529.1 D-5b/A: was #8896a8, which measured 4.41:1 on the
                                   RAISED card (--surface-ivory #1d3147) = FAILS AA. It passed at
                                   5.0 on flat paper, which is why it hid for so long: the defect
                                   only appears one elevation up. Now 5.14 card / 5.45 paper /
                                   6.52 bg. Smallest departure from the shipped token that clears
                                   AA on every dark surface. */

    /* ── Borders ─────────── */
    --border-default: #27405e;

    /* ── Accent ──────────── */
    --brand-gold:     #d8b864;  /* brightened for dark-mode contrast */

    /* ── Material (dark register) — mockup dark values. Chrome + title-shades are
          theme-independent (no dark override, defined once in :root). WP3: the card
          is SMOKED (#1a2c40 = rgba 26,44,64), which clears the protected #e8736b
          danger badge at 4.80:1 (shipped #1d3147 = 4.48 FAIL); on dark the 1px inset
          rim carries the specular ALONE — no white field-sheen (a 7% sheen re-broke
          the badge to 3.95). Mockup :112-209. KEEP IN SYNC with the [data-theme="dark"]
          block below (the split is load-bearing). ─────────────────────────────── */
    --material-aurora:
      radial-gradient(58% 44% at 10% 4%,  rgba(245,204,107,.20), transparent 70%),
      radial-gradient(52% 40% at 94% 26%, rgba(90,132,200,.22),  transparent 72%),
      radial-gradient(60% 46% at 72% 99%, rgba(216,184,100,.16), transparent 70%);
    --material-body-bg: linear-gradient(180deg, rgba(22,39,63,.90), rgba(12,23,38,.80));
    --material-cta-primary-bg:
      linear-gradient(180deg, rgba(255,255,255,.52), rgba(255,255,255,.08) 44%, rgba(255,255,255,0) 62%),
      linear-gradient(180deg,#FFDD8F 0%,#F5CC6B 46%,#C3A14B 100%);
    --material-cta-primary-fg: var(--surface-bg, #0c1726);
    --material-cta-primary-rim:
      inset 0 1px 0 rgba(255,255,255,.9), inset 0 -1.5px 0 rgba(101,77,20,.5),
      0 6px 22px -6px rgba(245,204,107,.42);
    --material-cta-ghost-bg: linear-gradient(180deg, rgba(255,255,255,.16), rgba(255,255,255,.05));
    --material-cta-ghost-border: rgba(250,248,243,.3);
    --material-cta-ghost-fg: var(--text-ink, #FAF8F3);
    --material-cta-ghost-rim: inset 0 1px 0 rgba(255,255,255,.24), 0 4px 14px -8px rgba(0,0,0,.55);
    --material-card-bg: linear-gradient(180deg, rgba(26,44,64,.94), rgba(18,31,47,.88));
    --material-card-border: rgba(255,255,255,.14);
    --material-card-rim: inset 0 1px 0 rgba(255,255,255,.20), 0 8px 22px -12px rgba(0,0,0,.65);

    /* ── Protected integrity (dark) ─────────────────────────────────────── */
    /* Listed here so a skin importing only this :root block gets dark values,
       but the @layer protected block is the authoritative gate. */
    --verdict-ok:      #5bbf8e !important;  /* = --verdict-ok-dark; !important keeps dark consistent with light's lock (else light !important would beat dark) */
    --verdict-danger:  #e8736b !important;  /* = --verdict-danger-dark; !important keeps dark consistent with light's lock */
    --verdict-pending: #d97706 !important;  /* v0.200 P0-5: PROTECTED dark variant; !important lock matches light */
  }
}

[data-theme="dark"] {
  --bg:             #0c1726;
  --surface-paper:  #16273f;
  --surface-ivory:  #1d3147;
  --surface-bg:     #0c1726;  /* v0.301.3: keep in sync with the @media dark block above */
  --field:          #0f2034;
  --text-ink:       #FAF8F3;
  --text-muted:     #8f9dae;  /* v0.529.1 D-5b/A — keep in sync with the @media dark block above */
  --border-default: #27405e;
  --brand-gold:     #d8b864;
  /* ── Material (dark register) — KEEP IN SYNC with the @media dark block above (WP3
        smoked #1a2c40 card; no dark override for chrome/title-shades). Mockup :112-209. */
  --material-aurora:
    radial-gradient(58% 44% at 10% 4%,  rgba(245,204,107,.20), transparent 70%),
    radial-gradient(52% 40% at 94% 26%, rgba(90,132,200,.22),  transparent 72%),
    radial-gradient(60% 46% at 72% 99%, rgba(216,184,100,.16), transparent 70%);
  --material-body-bg: linear-gradient(180deg, rgba(22,39,63,.90), rgba(12,23,38,.80));
  --material-cta-primary-bg:
    linear-gradient(180deg, rgba(255,255,255,.52), rgba(255,255,255,.08) 44%, rgba(255,255,255,0) 62%),
    linear-gradient(180deg,#FFDD8F 0%,#F5CC6B 46%,#C3A14B 100%);
  --material-cta-primary-fg: var(--surface-bg, #0c1726);
  --material-cta-primary-rim:
    inset 0 1px 0 rgba(255,255,255,.9), inset 0 -1.5px 0 rgba(101,77,20,.5),
    0 6px 22px -6px rgba(245,204,107,.42);
  --material-cta-ghost-bg: linear-gradient(180deg, rgba(255,255,255,.16), rgba(255,255,255,.05));
  --material-cta-ghost-border: rgba(250,248,243,.3);
  --material-cta-ghost-fg: var(--text-ink, #FAF8F3);
  --material-cta-ghost-rim: inset 0 1px 0 rgba(255,255,255,.24), 0 4px 14px -8px rgba(0,0,0,.55);
  --material-card-bg: linear-gradient(180deg, rgba(26,44,64,.94), rgba(18,31,47,.88));
  --material-card-border: rgba(255,255,255,.14);
  --material-card-rim: inset 0 1px 0 rgba(255,255,255,.20), 0 8px 22px -12px rgba(0,0,0,.65);
  --verdict-ok:      #5bbf8e !important;  /* dark lock (consistent with light) */
  --verdict-danger:  #e8736b !important;  /* dark lock (consistent with light) */
  --verdict-pending: #d97706 !important;  /* v0.200 P0-5: PROTECTED dark lock */
}


/* ════════════════════════════════════════════════════════════════════════════
   LEGACY ALIAS BLOCK — backwards-compatibility aliases for existing per-file
   :root vars that reference the old names. These keep existing CSS that uses
   var(--ink) / var(--paper) / var(--accent) etc. working until WP2 completes
   the find-and-replace.

   Remove this block after WP2 completes.
   ════════════════════════════════════════════════════════════════════════════ */
:root {
  /* Canonical names → legacy aliases used across all CSS files today */
  --ink:            var(--brand-ink);
  --paper:          var(--surface-paper);
  --ivory:          var(--surface-ivory);
  --gold:           var(--brand-gold);
  --success:        var(--verdict-ok);      /* PROTECTED mapping */
  --danger:         var(--verdict-danger);  /* PROTECTED mapping */
  --muted:          var(--text-muted);
  --bg:             var(--surface-bg);
  --surface:        var(--surface-paper);
  --surface-2:      var(--surface-ivory);
  --text:           var(--text-ink);
  --border:         var(--border-default);
  --accent:         var(--brand-gold);
  --grad:           var(--gradient-header);

  /* Legacy ag-* aliases used in chain-walk / badge selectors */
  --ag-success:     var(--verdict-ok);      /* PROTECTED mapping */
  --ag-danger:      var(--verdict-danger);  /* PROTECTED mapping */
  --ag-warning:     var(--state-warning);
  --ag-white:       #ffffff;
  --ag-gray-50:     var(--surface-bg-tint);
  --ag-gray-100:    var(--surface-ivory);
  --ag-gray-200:    var(--border-default);
  --ag-gray-400:    var(--text-gray-400);
  --ag-gray-500:    var(--text-muted);
  --ag-gray-700:    var(--text-gray);
  --ag-gray-900:    var(--brand-ink);

  /* Legacy radius/shadow aliases */
  --ag-radius-md:   var(--radius-md);
  --ag-radius-lg:   var(--radius-lg);
  --ag-radius-xl:   var(--radius-xl);
  --ag-radius-full: var(--radius-full);
}
