/* ==========================================================================
   Editorial Command Centre — token contract
   Implements docs/design-system.md §7, re-hued for SAHE per §4.6.

   This project has no Tailwind and no build step, so §7 ships here as the
   plain custom-property contract §2 describes, plus the §7 `@layer utilities`
   classes under the same names and the same values.

   Load order: tokens.css FIRST, then theme.css. The two no longer share any
   token name — the four colliding legacy tokens (--surface, --radius-sm/md/
   lg/xl) were renamed --legacy-* so `--radius-md` unambiguously means 6px.

   PHASE 1 SCOPE: tokens, fonts and utilities only. Nothing here restyles an
   existing component; the app renders exactly as before apart from the font.
   The base-layer rules that would change appearance are parked at the foot of
   this file, commented, for Phase 2.
   ========================================================================== */

/* ── Fonts (§5.1) — self-hosted variable, latin subset, no CDN request ───── */

/* Outfit is the one interface family: page titles, figures, labels and body
   all sit on it, at weights 300-700. Inter and Newsreader are gone — two
   families were doing a job the ramp no longer needs, and a serif heading
   beside an Outfit label read as two products. */

@font-face {
    font-family: 'Outfit';
    font-style: normal;
    font-weight: 300 700;
    font-display: swap;
    src: url('../fonts/Outfit-normal-300_700-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
        U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
        U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Outfit';
    font-style: normal;
    font-weight: 300 700;
    font-display: swap;
    src: url('../fonts/Outfit-normal-300_700-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
        U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F,
        U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F,
        U+A720-A7FF;
}

@font-face {
    font-family: 'JetBrains Mono';
    font-style: normal;
    font-weight: 400 500;
    font-display: swap;
    src: url('../fonts/JetBrainsMono-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
        U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
        U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ── Light theme (§4.2, re-hued §4.6) ───────────────────────────────────────
   Brand inputs: navy #00346f → --ink/--chrome/shadow tint · primary #e36036
   → coral slot · success #006e25 → teal slot. royal/amber/crimson/plum/slate
   are left at their §4.2 values: they are status colours, not brand colours.
   Every ratio below was measured, not assumed — see the Phase 1 report.      */

:root {
    color-scheme: light;

    /* Ink — the navy text ramp */
    --ink: #00346f;         /* 11.70:1 on paper */
    --ink-soft: #345d8c;    /*  6.80:1 on surface */
    --ink-mute: #4a6f99;    /*  5.00:1 on paper — carries every caps label */
    --ink-faint: #829cb9;   /*  placeholders, disabled glyphs, separator dots */
    /* --ink-faint is right for separator dots and disabled glyphs, but it is
       only 2.84:1 on --surface and placeholders are TEXT people have to read.
       Placeholders get their own step: below the field label, above the
       border, and over 4.5:1 on every surface it lands on. */
    --placeholder: var(--ink-mute);
    --ink-line: #c8d4e0;

    /* Brand */
    --coral: #e36036;
    --coral-strong: #b64d2b;
    --coral-hover: #a24526;
    --coral-soft: #f9efea;
    --coral-line: #f5d4c8;

    --teal: #006e25;
    --teal-strong: #006e25;
    --teal-hover: #006221;
    --teal-soft: #e9f0e9;
    --teal-line: #bcd7c3;

    /* Status — unchanged from §4.2 */
    --royal: #123a85;
    --royal-strong: #123a85;
    --royal-hover: #0e2f6e;
    --royal-soft: #e8eefa;
    --royal-line: #bfd0ee;

    --amber: #b77a21;
    --amber-strong: #8f5e14;
    --amber-hover: #744c0f;
    --amber-soft: #fbf1de;
    --amber-line: #ecd5a6;

    --crimson: #b4331f;
    --crimson-strong: #b4331f;
    --crimson-hover: #962917;
    --crimson-soft: #fceeeb;
    --crimson-line: #f2c4ba;

    --plum: #6b3fa0;
    --plum-strong: #5b2f92;
    --plum-hover: #4b2680;
    --plum-soft: #f2ecfb;
    --plum-line: #d6c3ee;

    --slate: #5b6b84;
    --slate-strong: #4c5a70;
    --slate-hover: #3f4b5e;
    --slate-soft: #eef1f5;
    --slate-line: #d4dbe5;

    /* Surfaces — warm, never pure grey */
    --paper: #fbfaf8;
    --surface: #ffffff;
    --surface-alt: #f5f3ef;
    --surface-sunken: #f0eee9;
    --rule: #e6e3dd;
    --rule-strong: #d3cfc6;

    /* Chrome — one scale, theme-invariant. The rail is the same navy in light
       and dark: it is the product's fixed frame, and a frame that changes
       colour with the canvas stops reading as a frame. Defined here only; the
       dark block deliberately does not override it. */
    --chrome: #071733;
    --chrome-alt: #12294a;
    --chrome-rule: #1c3a61;
    --chrome-text: #c0cfe1;
    --chrome-text-mute: #8298b8;
    --chrome-text-strong: #ffffff;

    /* Effects — navy at low alpha, never black (§4.2) */
    --shadow-raise: 0 1px 2px rgb(0 52 111 / 0.04), 0 4px 16px rgb(0 52 111 / 0.06);
    --shadow-float: 0 2px 4px rgb(0 52 111 / 0.05), 0 12px 32px rgb(0 52 111 / 0.11);
    --shadow-drawer: -12px 0 48px rgb(0 52 111 / 0.14);
    --focus-ring: 0 0 0 2px var(--surface), 0 0 0 4px var(--royal);

    /* Fonts (§5.1) */
    /* One family. --font-serif is kept as a token name because the display
       ramp (page titles, KPI figures) is written against it across the
       product; it now resolves to Outfit like everything else, so those
       places keep their size and weight and simply stop changing typeface. */
    --font-sans: 'Outfit', ui-sans-serif, system-ui, -apple-system, sans-serif;
    --font-serif: var(--font-sans);
    --font-mono: 'JetBrains Mono', ui-monospace, 'SFMono-Regular', monospace;

    /* Type scale (§5.2) — nine steps */
    --text-display: 2.5rem;
    --text-display-lh: 1.1;
    --text-display-ls: -0.022em;
    --text-figure: 2.125rem;
    --text-figure-lh: 1;
    --text-figure-ls: -0.02em;
    --text-h1: 1.875rem;
    --text-h1-lh: 1.2;
    --text-h1-ls: -0.018em;
    --text-h2: 1.25rem;
    --text-h2-lh: 1.4;
    --text-h2-ls: -0.012em;
    --text-h3: 0.9375rem;
    --text-h3-lh: 1.45;
    --text-h3-ls: -0.004em;
    --text-body: 0.875rem;
    --text-body-lh: 1.55;
    --text-sm: 0.8125rem;
    --text-sm-lh: 1.5;
    --text-xs: 0.75rem;
    --text-xs-lh: 1.45;
    --text-label: 0.625rem;
    --text-label-lh: 1.4;
    --text-label-ls: 0.09em;

    /* Radius (§6.2) — one per role */
    --radius-sm: 4px;
    --radius-md: 6px;
    --radius-lg: 10px;
    --radius-xl: 14px;

    /* Motion (§11) — one curve for the entire product */
    --ease-out-editorial: cubic-bezier(0.2, 0, 0, 1);
}

/* ── Dark theme (§4.3), derived by inversion per §4.6 step 6 ────────────────
   -strong LIGHTENS here instead of darkening, which is what lets components
   carry one class list across both themes with no JS branching.             */

:root[data-theme="dark"] {
    color-scheme: dark;

    --ink: #eef2f9;
    --ink-soft: #a9bad6;
    --ink-mute: #8ba0c0;
    --ink-faint: #6b80a4;
    --placeholder: var(--ink-mute);
    --ink-line: #26497e;

    --coral: #e36036;
    --coral-strong: #e6704a;
    --coral-hover: #e98362;
    --coral-soft: #2c1811;
    --coral-line: #6b3524;

    --teal: #298548;
    --teal-strong: #5aa172;
    --teal-hover: #6fad84;
    --teal-soft: #0d3019;
    --teal-line: #187738;

    --royal: #4c82e0;
    --royal-strong: #7aa6ee;
    --royal-hover: #96baf3;
    --royal-soft: #11244a;
    --royal-line: #2a4d8f;

    --amber: #d99a3c;
    --amber-strong: #e8b464;
    --amber-hover: #f0c684;
    --amber-soft: #2b2010;
    --amber-line: #57411d;

    --crimson: #e0553c;
    --crimson-strong: #ef7a63;
    --crimson-hover: #f59583;
    --crimson-soft: #2d1512;
    --crimson-line: #5a2a22;

    --plum: #a97ce8;
    --plum-strong: #bb99f0;
    --plum-hover: #ccb0f5;
    --plum-soft: #1e1a33;
    --plum-line: #3a3160;

    --slate: #8496ae;
    --slate-strong: #a2b1c5;
    --slate-hover: #b8c4d4;
    --slate-soft: #172a4a;
    --slate-line: #2a3f61;

    /* The dark canvas is navy, not grey or black — one family throughout. */
    --paper: #061b33;
    --surface: #0d2c50;
    --surface-alt: #12335c;
    --surface-sunken: #08223f;
    --rule: #1d4470;
    --rule-strong: #2a5688;

    /* No --chrome-* here on purpose: the rail carries the same navy in both
       themes (see the light block). */

    /* Black at high alpha — a navy shadow on a navy ground is invisible. */
    --shadow-raise: 0 1px 2px rgb(0 0 0 / 0.3), 0 4px 16px rgb(0 0 0 / 0.35);
    --shadow-float: 0 2px 4px rgb(0 0 0 / 0.35), 0 12px 32px rgb(0 0 0 / 0.5);
    --shadow-drawer: -12px 0 48px rgb(0 0 0 / 0.5);
    --focus-ring: 0 0 0 2px var(--surface), 0 0 0 4px var(--royal);
}

/* ── Utilities (§7 `@layer utilities`) ───────────────────────────────────── */

/* The system's signature: the 10px caps label (§5.3). */
.label {
    font-size: var(--text-label);
    line-height: var(--text-label-lh);
    letter-spacing: var(--text-label-ls);
    text-transform: uppercase;
    font-weight: 600;
}

/* Any number that sits above or beside another number (§5.4). */
.tabular {
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
}

/* A vertical hairline for dividing stat columns (§6.4). */
.rule-y {
    border-inline-start: 1px solid var(--rule);
}

/* The hairline that fades out — closes every section header (§6.4). */
.rule-fade {
    background: linear-gradient(90deg, var(--rule) 0%, transparent 100%);
    height: 1px;
}

/* Texture for the navy sign-in panel, at ~40% opacity. One place only (§6.5). */
.grain {
    background-image: radial-gradient(circle at 1px 1px,
        color-mix(in srgb, var(--ink) 6%, transparent) 1px, transparent 0);
    background-size: 4px 4px;
}

/* The rail's own scrollbar — a paper thumb inside navy looks like a bug (§7). */
.scroll-chrome::-webkit-scrollbar-thumb {
    background: var(--chrome-rule);
    border-color: var(--chrome);
}

/* ── Tone utilities (§4.4) ──────────────────────────────────────────────────
   The four TONE_* maps in core/design.py name these classes. With Tailwind
   they would be generated; here they are written out once. Unused until the
   primitives land in Phase 2 — defining them changes nothing on screen.    */

/* TONE_TEXT — small text always takes the -strong variant (§4.1). */
.text-coral-strong { color: var(--coral-strong); }
.text-teal-strong { color: var(--teal-strong); }
.text-royal-strong { color: var(--royal-strong); }
.text-amber-strong { color: var(--amber-strong); }
.text-crimson-strong { color: var(--crimson-strong); }
.text-plum-strong { color: var(--plum-strong); }
.text-slate-strong { color: var(--slate-strong); }
.text-ink { color: var(--ink); }

/* TONE_SOFT — tint grounds. */
.bg-coral-soft { background-color: var(--coral-soft); }
.bg-teal-soft { background-color: var(--teal-soft); }
.bg-royal-soft { background-color: var(--royal-soft); }
.bg-amber-soft { background-color: var(--amber-soft); }
.bg-crimson-soft { background-color: var(--crimson-soft); }
.bg-plum-soft { background-color: var(--plum-soft); }
.bg-slate-soft { background-color: var(--slate-soft); }
.bg-surface-alt { background-color: var(--surface-alt); }

/* TONE_LINE — always paired with the matching -soft. */
.border-coral-line { border-color: var(--coral-line); }
.border-teal-line { border-color: var(--teal-line); }
.border-royal-line { border-color: var(--royal-line); }
.border-amber-line { border-color: var(--amber-line); }
.border-crimson-line { border-color: var(--crimson-line); }
.border-plum-line { border-color: var(--plum-line); }
.border-slate-line { border-color: var(--slate-line); }
.border-ink-line { border-color: var(--ink-line); }

/* TONE_FILL — graphics take the base tone, not -strong (§4.1). */
.bg-coral { background-color: var(--coral); }
.bg-teal { background-color: var(--teal); }
.bg-royal { background-color: var(--royal); }
.bg-amber { background-color: var(--amber); }
.bg-crimson { background-color: var(--crimson); }
.bg-plum { background-color: var(--plum); }
.bg-slate { background-color: var(--slate); }
.bg-ink { background-color: var(--ink); }

/* ── Keyframes (§7) ──────────────────────────────────────────────────────── */

@keyframes rise {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: none; }
}

@keyframes fade {
    from { opacity: 0; }
    to   { opacity: 1; }
}

@keyframes slide-in {
    from { transform: translateX(100%); }
    to   { transform: none; }
}

@keyframes shimmer {
    from { background-position: -200% 0; }
    to   { background-position:  200% 0; }
}

/* ── Reduced motion (§11) ────────────────────────────────────────────────── */

@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;
    }
}

/* ── Theme toggle (§16) ─────────────────────────────────────────────────────
   The one component Phase 1 ships, because the phase mandates the control.
   Everything else waits for Phase 2.                                        */

.theme-toggle {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 2px;
    border: 1px solid var(--rule);
    border-radius: var(--radius-md);
    background-color: var(--surface-alt);
}

.theme-toggle__option {
    display: grid;
    place-items: center;
    width: 24px;
    height: 24px;
    padding: 0;
    border: 0;
    border-radius: 4px;
    background: transparent;
    color: var(--ink-mute);
    cursor: pointer;
    transition: background-color 150ms var(--ease-out-editorial),
                color 150ms var(--ease-out-editorial),
                box-shadow 150ms var(--ease-out-editorial);
}

.theme-toggle__option:hover { color: var(--ink); }

.theme-toggle__option[aria-checked="true"] {
    background-color: var(--surface);
    color: var(--ink);
    box-shadow: var(--shadow-raise);
}

.theme-toggle__option svg { width: 14px; height: 14px; }

/* ── Legacy bridge, dark theme only ─────────────────────────────────────────
   theme.css still paints the whole app through the old Material 3 token
   names, none of which had a dark value — so without this block the mandated
   theme toggle would be a control that does nothing.

   Every entry points at a new token, so the two cannot drift. The LIGHT theme
   is deliberately untouched: theme.css keeps its own values there and the app
   renders byte-identically to before.

   DELETE THIS BLOCK as Phase 2 migrates each component off the old names.   */

/* NOTE: the `:root` prefix is load-bearing, not decoration. theme.css is
   linked AFTER tokens.css and declares all of these names again in a plain
   `:root` block. A bare `[data-theme="dark"]` selector has the SAME
   specificity (0,1,0) as `:root`, so source order decided it and theme.css's
   light values won — every legacy token below silently kept its light value
   in dark mode. `:root[data-theme="dark"]` is (0,2,0) and wins outright.
   Keep the prefix on any dark block that redeclares a theme.css name.       */
:root[data-theme="dark"] {
    --primary: var(--royal);
    --primary-container: var(--royal-soft);
    --on-primary: #ffffff;
    --on-primary-container: var(--royal-strong);
    --primary-fixed: var(--royal-soft);
    --primary-fixed-dim: var(--royal-line);

    --secondary: var(--teal);
    --secondary-container: var(--teal-soft);
    --on-secondary: #ffffff;
    --on-secondary-container: var(--teal-strong);
    --secondary-fixed: var(--teal-soft);
    --secondary-fixed-dim: var(--teal-line);

    --tertiary: var(--amber);
    --tertiary-container: var(--amber-soft);
    --on-tertiary: #ffffff;
    --on-tertiary-container: var(--amber-strong);
    --tertiary-fixed: var(--amber-soft);
    --tertiary-fixed-dim: var(--amber-line);

    --error: var(--crimson);
    --error-container: var(--crimson-soft);
    --on-error: #ffffff;
    --on-error-container: var(--crimson-strong);

    --legacy-surface: var(--paper);
    --background: var(--paper);
    --surface-dim: var(--surface-sunken);
    --surface-bright: var(--surface-alt);
    --surface-container-lowest: var(--surface);
    --surface-container-low: var(--surface);
    --surface-container: var(--surface-alt);
    --surface-container-high: var(--surface-alt);
    --surface-container-highest: var(--rule);
    --surface-variant: var(--surface-alt);

    --on-surface: var(--ink);
    --on-surface-variant: var(--ink-soft);
    --on-background: var(--ink);

    --outline: var(--ink-mute);
    --outline-variant: var(--rule);

    --inverse-surface: var(--ink);
    --inverse-on-surface: var(--paper);
    --inverse-primary: var(--royal-strong);
    --surface-tint: var(--royal);

    --shadow-sm: 0 1px 3px rgb(0 0 0 / 0.30);
    --shadow-md: 0 4px 16px rgb(0 0 0 / 0.35);
    --shadow-lg: 0 16px 32px rgb(0 0 0 / 0.40);
    --shadow-xl: 0 24px 48px rgb(0 0 0 / 0.50);
}

/* ── Base layer ─────────────────────────────────────────────────────────────
   The §7 base-layer rules (border-color, body, text-wrap, :focus-visible,
   ::selection and the scrollbar) were parked here during Phase 1 because they
   change how every page looks. They are now live in components.css, which
   loads after theme.css so the spec's base wins over the legacy one.
   ------------------------------------------------------------------------- */
