/* =====================================================================
   Aleph design tokens — THE ONE SOURCE (Stage B, B3 "tokens first";
   Surface-Drift-Audit §5). Every Aleph web surface links this file before
   its own stylesheet and never redefines a token declared here. Layout
   measurements that belong to one surface (sidebar widths, page width)
   stay in that surface's own :root. Product Design owns the values.
   ===================================================================== */
:root {
    /* Brand (logo-derived) */
    --bg-dark: #000000;                       /* the logo's central void */
    --bg-panel: rgba(12, 14, 16, 0.62);       /* subtle glass over black */
    --brand-blue: #6dacc8;
    --brand-blue-soft: #a4cfd9;
    --brand-orange: #fb9126;
    --brand-warm: #e5deb3;
    --brand-amber: #f6b755;                    /* progress / emphasis gradient stop (was used undeclared — the audit's drift) */

    /* Type */
    /* Consolas is here for a reason (PD, 2026-09-10). The --font-mono sweep folds 38 sites onto
       this stack, and they did NOT all start from the same place — FOUR spellings, THREE
       behaviours:
           34  'JetBrains Mono', monospace
            1  "JetBrains Mono", monospace          same behaviour, different quotes
            2  'JetBrains Mono'                     no fallback at all
            1  'JetBrains Mono', ui-monospace, SFMono-Regular, Consolas, monospace
       Without Consolas that last site is the sweep's ONLY regression — Menlo is macOS, Consolas is
       Windows, so a Windows reader whose webfont failed would fall FURTHER than before. With it, no
       site renders worse than it did, on any platform, webfont or not. That is a stronger property
       than "invisible", and it is what let the sweep ride a bundle rather than wait for its own.
       (38, not 37: my first count used a single-quote pattern and could not see the double-quoted
       one. The instrument matched what it could see rather than what the question was about — while
       I was checking whether the sweep was a pure tokenisation. The COO caught it.)
       DO NOT trim this stack to look tidy: each entry is one platform's answer. */
    --font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

    /* Semantic roles */
    --primary: var(--brand-blue);
    --accent: var(--brand-orange);
    --danger: var(--brand-orange);
    --warning: var(--brand-orange);
    --info: var(--brand-blue);

    /* Text */
    --text-main: #f8fafc;
    --text-muted: #94a3b8;

    /* Composer surfaces. Phase 1a tokenised these at the literals they replaced; PHASE 2f now
       retunes them, and this is the payoff of having tokenised: three values, one line each,
       visible and revertible, with no hunt through 6000 lines of stylesheet.
       2f: the composer is ONE layer. .chat-input-area and #chat-input are both transparent and
       the field is defined by its border alone; what shows through is .chat-section's own
       --bg-panel surface, exactly like a record card. Do NOT "fix" a field that looks flat by
       assigning --bg-panel here — that is the three-layer composer the spec exists to undo. */
    --composer-bg: transparent;
    --input-bg: transparent;
    --input-line: rgba(109, 172, 200, 0.28);

    /* 2b: the hairline COLOUR. The spec asks for `1px var(--line)`, and --line does not exist —
       the WebUI has --border, which is a SHORTHAND (1px solid rgba(...)), not a colour. Writing
       `1px solid var(--border)` would expand to two widths and two styles and be dropped
       silently: the same trap as --border-strong on the Switch. So --line is the colour, defined
       once, and --border keeps its shorthand meaning. */
    --line: rgba(109, 172, 200, 0.14);

    /* 2e: the lattice level, now a token rather than a literal at style.css:45. */
    --lattice-opacity: 0.45;

    /* Surface fills (Phase 1a), again at PARITY with the literals they replace. Named -bg because
       they are backgrounds: the identical rgba(255,255,255,.05) also appears on 15 BORDERS, and a
       fill token standing in for a hairline would encode a meaning that breaks at the next retune.
       Those borders need their own name from PD. */
    /* TONAL, not semantic (PD §1e). A generic value gets a tonal name: these are steps in a
       neutral fill ramp, exactly as --text-muted is a step in the text ramp, and many unrelated
       roles legitimately share them. They were first named --chip-bg / --trace-bg after the FIRST
       selector anyone looked at, and then applied to every site sharing the value — a specific
       name on a generic value, which is how a chip token ended up on a button and a "trace" token
       on four things that are not traces.
       NO ALIASES back to the old names: an alias carries no information, is one more thing to
       keep in sync, and quietly invites the divergence this is cleaning up. If a chip later needs
       its own fill, mint --chip-bg THEN, with its own value. */
    /* RECESSES (PD, 2026-09-10, on the Chairman's "grey backgrounds are not feeling well").
       An inset fill was written as literal DARKNESS — rgba(0,0,0,.2-.62) and rgba(4,10,15,.42).
       On black that reads as a recess; on paper it paints a DIRTY GREY BLOCK, which is what he
       saw on the CONTEXTS dock, the record search box and the Settings body.
       A recess is a RELATION ("inset from its panel"), not a colour, so it needs a token that can
       mean the relation in both grounds. NOT a parity tokenisation: the light values are CHOSEN
       (paper takes far less darkening than black takes lightening), and the dark side collapses
       eight alphas onto two steps, so dark shifts slightly at several sites. Declared, not claimed
       invisible.
       SCRIMS AND MEDIA GROUNDS DO NOT TAKE THESE and stay literal: a backdrop's job is to dim the
       page, and a photo or a graph scene is shown on dark in both themes. */
    /* A CARD rises from its panel — in BOTH themes. Phase 4a's premise ("panels rise instead of
       receding") applied one level in. NOT a recess: an artifact tile, a message card and a
       choice card sit ON their panel, they are not cut into it. Dark keeps the near-black the
       tiles had; light lifts toward paper-white. */
    --fill-card: rgba(255, 255, 255, 0.04);
    --fill-recess: rgba(0, 0, 0, 0.28);
    --fill-recess-strong: rgba(0, 0, 0, 0.50);
    --fill-faint: rgba(255, 255, 255, 0.05);
    --fill-faintest: rgba(255, 255, 255, 0.02);

    /* The brand hue at its faintest. TONAL, in the brand hue — distinct from --glow-blue, which
       is SEMANTIC and means a glow. They share a value today and must be free to diverge:
       brightening the nebula must never move a message bubble. */
    --tint-brand: rgba(109, 172, 200, 0.08);

    /* SEMANTIC: part of a panel's gradient recipe, not a tint that happens to sit on a panel. */
    --panel-wash: rgba(109, 172, 200, 0.08);

    /* Completes the code family with --code-surface and --code-gutter-text. A code block is not
       a control, so it does not take --control-line. */
    --code-line: #222;

    /* Phase 1d (Product Design, 2026-09-09). Names follow ROLES read from the selectors, not hex
       values: where one value serves two meanings it gets two names, identical today and free to
       diverge. All adopted at the CURRENT literal — Phase 2 retunes. */

    /* Text ramp. --text-bright is the INTERACTION PEAK (hover/focus), not "whiter text". */
    --text-bright: #ffffff;
    --text-secondary: #e2e8f0;
    --text-faint: #64748b;
    --text-on-accent: #000;

    /* Status MESSAGES — the pale forms only. A danger button is an action, not a state. */
    --status-soft-error: #fecdd3;
    --status-soft-success: #dcfce7;
    --status-soft-info: #dbeafe;
    --status-soft-warning: #fed7aa;

    /* Tinted-control states (PD re-split, 2026-09-09). NOT status messages: all three tint a
       control the same way — border-color at ~.42-.55, background at ~.12-.18, text the pale form
       of the SAME hue. Sharing --status-soft-* with them would mean retuning a message colour
       silently retints every toggle. --status-soft-* is now exactly what it says: the text of a
       status MESSAGE. */
    --control-on-text: #dcfce7;
    --control-confirming-text: #fed7aa;
    /* The BLUE member of the tinted-control family (PD, 2026-09-10, overturning their own
       morning ruling on SD-20260909-19). Minted rather than reused, on measurement:
       --brand-blue-soft is #3f8fa8 in light and gives 3.17:1 on the mask button's own tint,
       where the bar is 4.5:1 because that button inherits body text. The same value had
       ALREADY been measured at 3.58:1 and rejected by 4e for --state-done, twenty lines
       below — and was then shipped here anyway, because the second time it arrived as a NAME
       and not a number. A token is a claim about ROLE and carries no memory of what its VALUE
       has already failed.
       NOT --state-done, though its light value is the same: that would couple a CONTROL's
       legibility to a STATUS token's future retuning, which is precisely what 4e de-aliased
       away from. Same mistake pointed the other way. */
    --control-on-text-blue: #a4cfd9;

    /* Destructive ACTIONS, deliberately outside --state-*. */
    --action-danger: #ef4444;
    --action-danger-hover: #dc2626;

    /* File types: their own family. Some share a value with a status token TODAY; separate names
       are the point, so neither drags the other when one is retuned. */
    --filetype-pdf: #ef4444;
    --filetype-doc: #60a5fa;
    --filetype-sheet: #22c55e;
    --filetype-slides: #f97316;
    --filetype-archive: #facc15;
    --filetype-generic: #cbd5e1;

    /* Surfaces and chrome. --scroll-thumb and --control-line are both #222 on purpose. */
    --scroll-thumb: #222;
    --control-line: #222;
    --code-surface: #071019;
    --code-gutter-text: #52657a;
    --embed-surface: #05070a;

    /* Edges, depth, focus */
    --border: 1px solid rgba(109, 172, 200, 0.14);
    --border-strong: 1px solid rgba(109, 172, 200, 0.28);
    --glass-shadow: 0 10px 36px rgba(0, 0, 0, 0.82);
    --focus-ring: 0 0 0 3px rgba(109, 172, 200, 0.22);
    --glow-blue: rgba(109, 172, 200, 0.08);
    --glow-orange: rgba(251, 145, 38, 0.08);

    /* The four-state status vocabulary (one meaning per state, every surface).
       PD 4e (2026-09-10): these carry their OWN values and no longer alias the brand tokens.
       Aliasing couples a DECORATIVE value to one that must be READ — different jobs under
       different constraints — and is how a future brand tweak silently breaks state contrast.
       Dark is exactly today's numbers written out: no visual change. */
    --state-running: #6dacc8;                 /* something is happening now */
    --state-waiting: #fb9126;                 /* waits for the person (approval, consent, answer) */
    --state-done: #a4cfd9;                    /* finished, ready */
    --state-failed: #f87171;                  /* failed — said plainly */
}

/* ===========================================================================================
   PHASE 4a — LIGHT MODE. It is NOT an inversion.
   The identity is a void with a luminous lattice, and light breaks its premises: adding light to
   white yields nothing, so the lattice stops GLOWING and becomes DRAWN, panels RISE instead of
   receding, and both brand hues DEEPEN. Measured on the paper ground below: --brand-blue #2d7691
   is 4.57:1 (AA for body text), --text-main 15.80:1, --text-muted 4.94:1. The dark palette is
   excellent ON BLACK — 8:1 to 12:1 — and has nowhere to go on white, which is why the values
   change rather than flip.
   Dark stays the default in bare :root. Light is this single override, and it NEVER follows the
   OS (Chairman, 2026-09-09): it is an explicit Settings choice, so prefers-color-scheme is not
   consulted anywhere.
   =========================================================================================== */
:root[data-theme="light"] {
    color-scheme: light;

    --bg-dark: #eef3f5;                       /* cool paper, faint cyan bias — not pure white */
    --bg-panel: rgba(255, 255, 255, 0.74);    /* panels rise; still translucent so the lattice shows through */

    --brand-blue: #2d7691;
    --brand-blue-soft: #3f8fa8;
    --brand-orange: #c2660a;
    --brand-warm: #8a7440;
    --brand-amber: #b07d18;

    --text-main: #0e1a21;
    --text-muted: #5a6b76;
    /* The rest of the text ramp, derived to keep its ORDER on paper: bright is the interaction
       peak (darkest here, since contrast runs the other way), faint the most recessive. */
    /* Paper needs a fraction of the darkening black needs of light. */
    --fill-card: rgba(255, 255, 255, 0.72);
    --fill-recess: rgba(14, 26, 33, 0.05);
    --fill-recess-strong: rgba(14, 26, 33, 0.10);
    --text-bright: #040b0f;
    --text-secondary: #26333c;
    --text-faint: #7d8b95;
    --text-on-accent: #ffffff;                /* on a deepened brand fill, white is the legible one */

    --border: 1px solid rgba(16, 40, 55, 0.13);
    --border-strong: 1px solid rgba(16, 40, 55, 0.24);
    --line: rgba(16, 40, 55, 0.13);
    --glass-shadow: 0 8px 28px rgba(16, 40, 55, 0.10);
    --focus-ring: 0 0 0 3px rgba(45, 118, 145, 0.30);
    /* PD 4e (2026-09-10). .state-pill is the FIRST site of these four, so light was the first
       time they were asked to carry TEXT — and two failed, measured on the composited card
       ground #fbfcfc at 11px semibold where the bar is 4.5:1.
       --state-done needed more than a deepening: the obvious #356f83 (5.44:1) sits 17 units from
       running, so the two would read as ONE colour on paper. In dark they are 67 apart because
       done is LIGHTER than running — and lighter fails on paper, so THE RELATIONSHIP INVERTS.
       #1f5c6b is DEEPER than running, 48 away, and still reads as "settled". Same meaning,
       opposite direction, because the ground is opposite. */
    --state-running: #2d7691;                 /* 4.97:1 — unchanged, it already passed */
    --state-waiting: #a85408;                 /* was #c2660a, 3.93:1 — now 5.19:1 */
    --state-done: #1f5c6b;                    /* was #3f8fa8, 3.58:1 — now 7.29:1 */
    --state-failed: #b3261e;                  /* 6.36:1 — unchanged */

    /* The neutral fill ramp inverts: faint WHITE on black becomes faint INK on paper. */
    --fill-faint: rgba(16, 40, 55, 0.05);
    --fill-faintest: rgba(16, 40, 55, 0.035);

    --tint-brand: rgba(45, 118, 145, 0.10);
    --panel-wash: rgba(45, 118, 145, 0.10);
    --glow-blue: rgba(45, 118, 145, 0.10);
    --scroll-thumb: rgba(16, 40, 55, 0.22);

    --control-line: rgba(16, 40, 55, 0.24);
    --code-surface: #e4ebee;
    --code-gutter-text: #7d8b95;
    --code-line: rgba(16, 40, 55, 0.13);
    --embed-surface: #e8eef0;

    /* The status ramp's pale forms are pale against BLACK; on paper they need to darken to stay
       readable as text. */
    --status-soft-error: #8c2f2a;
    --status-soft-success: #2b6b41;
    --status-soft-info: #2d5f8c;
    --status-soft-warning: #8a5a12;
    --control-on-text: #2b6b41;
    --control-confirming-text: #8a5a12;
    --control-on-text-blue: #1f5c6b;          /* 6.47:1 on the tinted control; #3f8fa8 was 3.17 */

    --action-danger: #b3261e;
    --action-danger-hover: #8c1d17;

    --filetype-pdf: #b3261e;
    --filetype-doc: #2d5f8c;
    --filetype-sheet: #2b6b41;
    --filetype-slides: #a2540c;
    --filetype-archive: #8a5a12;
    --filetype-generic: #5a6b76;

    /* 0.5 rather than 0.45: drawn ink on paper needs slightly more presence than a glow in a void. */
    --lattice-opacity: 0.5;

    /* --composer-bg and --input-bg stay TRANSPARENT in both themes. The composer is one layer;
       giving the field its own fill here is the three-layer composer Phase 2f undid. */
}
