/* ══════════════════════════════════════════════════════════════════════════
   bwui-tokens.css — THE ONLY FILE IN THE COMPANY THAT MAY DEFINE A CUSTOM
   PROPERTY. Load order: tokens → base → components → (docs | portal) → thin
   per-property sheet.

   WHAT THIS FILE IS
     Every design token of the BankWriter UI library: grounds, ink, rules,
     brand, semantic channels, on-ink ramp, data wells, elevation, families,
     radius ladder, grid, type ladder, space ladder. Both themes.

   WHAT THIS FILE MUST NEVER CONTAIN
     · A selector that styles anything. No element rules, no component rules,
       no layout. It declares values; it paints nothing.
     · A theme-aware component. Dark is handled HERE, at token level, only.
       No file downstream may reference a theme, a media query for colour
       scheme, or a data-theme attribute.
     · A fifth radius, a ninth space step, or a colour used as both a fill
       and as type. A colour is one or the other, never both (§2.2).

   AUTHORITY
     All values come from SPEC.md §2 (Tokens) and §3 (Ladders). Where SPEC.md
     and judgement disagree, SPEC.md wins. Every ratio in a comment is the
     WCAG 2.1 relative-luminance figure against the exact hex pair named, as
     computed in SPEC.md §2.4 — not estimated, not inherited from an older
     document. contrast_test.py re-derives them from this file.
   ══════════════════════════════════════════════════════════════════════════ */

:root{
  color-scheme: light dark;

  /* ── grounds ──────────────────────────────────────────────────────────────
     --bw-outer is the band BEHIND the sheet. It is NOT a text ground:
     --bw-green-deep on it is 4.38:1 and FAILS. Nothing readable sits on
     --bw-outer except --bw-ink (15.60:1) and --bw-ink2 (14.34:1).           */
  --bw-outer:#E7E5DC;
  --bw-paper:#F5F4EE;
  --bw-surface:#FFFFFF;
  --bw-sunk:#FCFBF6;          /* table header band, code wells, staff messages */

  /* ── ink (TEXT) ───────────────────────────────────────────────────────────
     ratios, in order: outer / paper / surface / sunk                        */
  --bw-ink:#0B0B0B;           /* TEXT 15.60 / 17.86 / 19.68 / 19.00 — headings   */
  --bw-ink2:#161616;          /* TEXT 14.34 / 16.42 / 18.10 / 17.47 — body       */
  --bw-muted:#3E523F;         /* TEXT  6.70 /  7.67 /  8.46 /  8.16 — secondary  */
  --bw-faint:#8E938A;         /* NOT TEXT 2.49 / 2.85 / 3.14 / 3.03 — DECORATION
                                 ONLY. Legal use, exhaustively: the dotted leader
                                 (.bwui-lead). That is the whole list. It was a
                                 spent pagination control too until 2026-07-26,
                                 which was 2.85:1 TYPE on --bw-paper; that use is
                                 now --bw-muted. Never a word a person reads.    */

  /* ── rules ────────────────────────────────────────────────────────────────
     --bw-line is the hairline between rows. --bw-line-strong is section rules
     and BOTH strokes of the double rule.                                    */
  --bw-line:#E5E2D7;
  --bw-line-strong:#D6D2C5;

  /* ── brand ────────────────────────────────────────────────────────────────
     --bw-green is a SHAPE token. Complete legal job list, and this list names
     only uses that EXIST as a var(--bw-green) reference in the library:
       1. the 2px current-item underline in the site header
          (bwui-components.css §4.9) — 2.63:1 on --bw-paper, the band it
          actually sits in;
       2. the four bars of .bwui-mark (bwui-components.css §4.13).
     The focus glow is a LITERAL rgba(106,165,117,.22) derived from this hex,
     not a var() use of it (see --bw-glow). Never type on a light ground. It IS
     legal as type on --bw-ink-panel (6.80:1) — that case is --bw-on-ink-green. */
  --bw-green:#6AA575;         /* NOT TEXT on any light ground — 2.63 on
                                 --bw-paper (the header band, its only light
                                 job) / 2.90 on --bw-surface                     */
  --bw-green-deep:#49724D;    /* TEXT 5.53 surface / 5.02 paper / 5.34 sunk /
                                 4.98 on --bw-tip-fill. 4.38 on --bw-outer FAILS
                                 and is not a legal ground; 4.51 on --bw-mint
                                 clears AA by 0.008 and is excluded by RULE.     */
  --bw-on-green:#FFFFFF;      /* TEXT on a --bw-green-deep FILL = 5.53           */
  --bw-mint:#D9EDDE;          /* ORNAMENT FILL ONLY — no type of any colour is
                                 PERMITTED on it except --bw-ink (16.04) /
                                 --bw-ink2 (14.75). --bw-green-deep measures
                                 4.51 — it clears AA by 0.008 and is excluded by
                                 rule, not by measurement. Two jobs, exhaustively:
                                 the chapter-chip hover and ::selection.         */

  /* ── semantic channels ────────────────────────────────────────────────────
     fill / line / ink. The ink is measured against ITS OWN fill, never against
     the window. Body copy inside any callout is --bw-ink2, ≥15:1 on all four. */
  /* 2026-10-14, owner ruling (keep the current look): the lines, the amber
     fill and the red ink are the approved portal's values again.          */
  --bw-note-fill:#E4EEF2; --bw-note-line:#C6DCE6;
  --bw-note-ink:#185FA5;      /* TEXT 5.53 on --bw-note-fill · 6.52 on surface   */
  --bw-tip-fill:#EDF5EF;  --bw-tip-line:#BFE0C9;
  --bw-tip-ink:#49724D;       /* TEXT 4.98 on --bw-tip-fill · 5.53 on surface    */
  --bw-caut-fill:#F6EEDC; --bw-caut-line:#E8D9B5;
  --bw-caut-ink:#8A5A13;      /* TEXT 5.12 on --bw-caut-fill · 5.91 on surface   */
  --bw-warn-fill:#F7E8E4; --bw-warn-line:#E7C9C3;
  --bw-warn-ink:#9E3B2C;      /* TEXT 5.65 on --bw-warn-fill · 6.74 on surface   */
  /* v4's flag red survives ONLY as a fill (--bw-on-green white on it = 4.99).
     As TYPE on --bw-warn-fill it is 4.19 and fails — which is why
     --bw-warn-ink exists. Same story as v4's amber #9A7B2E (3.62).          */
  --bw-flag:#BC4B3B;          /* NOT TEXT — fill only                            */

  /* ── on --bw-ink-panel (footer, CTA band, sign-in brand panel) ────────────
     The panel is #0B0B0B in BOTH themes — it is the constant the customer
     recognises — so this ramp is identical in both. Ratios vs #0B0B0B.      */
  --bw-ink-panel:#0B0B0B;     /* explicit, so the panel never follows the theme  */
  --bw-on-ink:#FFFFFF;        /* TEXT 19.68 on --bw-ink-panel                    */
  --bw-on-ink-2:#CFCFC8;      /* TEXT 12.57 on --bw-ink-panel — body and links   */
  --bw-on-ink-3:#A8A89F;      /* TEXT  8.22 on --bw-ink-panel — meta and labels  */
  --bw-on-ink-green:#6AA575;  /* TEXT  6.80 on --bw-ink-panel — the ONE case
                                 where the fill green is legal as type.          */
  /* The three hairlines and the one wash that may be drawn ON the ink panel.
     They were raw rgba() literals in bwui-components.css until 2026-07-26;
     they are values, so they live here. Not type — no ratio applies.        */
  --bw-on-ink-line:rgba(255,255,255,.28);       /* ghost-button border on ink   */
  --bw-on-ink-line-soft:rgba(255,255,255,.14);  /* the footer's base rule       */
  --bw-on-ink-wash:rgba(255,255,255,.08);       /* ghost-button hover ground    */

  /* ── data wells ───────────────────────────────────────────────────────── */
  --bw-key-fill:#F0EEE7;      /* --bw-ink2 on this fill = 15.59 (TEXT ok)        */
  --bw-key-line:#D6D2C5;
  --bw-field-bg:#FFFFFF;      /* --bw-ink2 on this fill = 18.10 (TEXT ok)        */
  --bw-field-line:#95917F;    /* 3.17:1 on --bw-field-bg, 3.05:1 on --bw-sunk: an
                                 input border is the only thing that makes an
                                 empty field findable, so it clears WCAG 1.4.11's
                                 3:1 on EVERY ground a control sits on. Was
                                 #989483, which is 2.93:1 on --bw-sunk (the card
                                 ground the sales forms sit on); the portal's
                                 measured value took over on 2026-10-14.         */

  /* ── portal additions (2026-10-14, the stylesheet convergence) ────────────
     portal.css carried these as its own tokens; they moved here so a colour
     lives in exactly one file. Dark values are in both dark blocks below.   */
  --bw-meta:#5C5F58;          /* TEXT 5.90 outer / 6.50 surface / 6.16 sunk ,
                                 mono metadata: ids, dates, column labels      */
  --bw-green-on-ground:#476F4B; /* TEXT 4.60 on --bw-outer, 4.70 on --bw-mint,
                                 5.70 surface: the green WORDS on the page
                                 ground (page head, kicker, endnote) and on a
                                 mint pill, where --bw-green-deep measures 4.38
                                 and 4.51. Kickers take this everywhere.        */
  --bw-pane:#161616;          /* the sign-in ink pane (approved 2026-07-26). NOT
                                 --bw-ink-panel: the pane warms in dark.        */
  --bw-pane-edge:transparent; /* its hairline; a rule only in dark             */
  --bw-on-dark:#FFFFFF;       /* TEXT 17.4 on --bw-pane                        */
  --bw-on-dark-2:#C9C7BE;     /* TEXT 10.6 on --bw-pane: the pane's copy      */
  --bw-on-dark-3:#8F8D84;     /* TEXT  5.4 on --bw-pane: the privacy line     */
  --bw-on-dark-green:#9CC7A4; /* TEXT  8.5 on --bw-pane: the italic word      */
  --bw-scrim:rgba(11,11,11,.45);           /* behind a dialog                 */
  --bw-sh-menu:0 12px 28px rgba(0,0,0,.16);/* the staff menu, an overlay      */
  --bw-chip-wash:rgba(255,255,255,.18);    /* a count tag on an inked chip
                                              (2026-10-14, as approved); the
                                              tag's words are the chip's own */
  --bw-gutter:2rem;           /* 32px: the portal's one side padding; 20px at
                                 a tablet and below (media block under this)   */
  /* the select arrow (appearance:none removes the native one). A data: URI in
     a CSS background is img-src, not style-src, so it is not inline style.
     The stroke is --bw-meta in each theme.                                   */
  --bw-select-arrow:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%235C5F58' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='M5 9l7 7 7-7'/%3E%3C/svg%3E");
  /* the order form (order_form.css) is PAPER in both themes: it is what gets
     printed, so these never follow the theme. Values unchanged from the
     document sheet; measured there (doc-ink on paper 16.9, doc-muted on paper
     5.7 and on tint 5.3, on-band on band 16.9, on-band on doc-green 6.2,
     doc-note-ink on --bw-caut-fill 7.9).                                     */
  --bw-doc-paper:#FFFFFF; --bw-doc-ink:#1A1A18; --bw-doc-muted:#6B6B64;
  --bw-doc-line:#E0DED6; --bw-doc-tint:#F5F4F0;
  --bw-doc-band:#1A1A18; --bw-doc-on-band:#FFFFFF; --bw-doc-green:#3B6D11;
  --bw-doc-note-ink:#5D4415;
  --bw-doc-note-fill:#F6EEDC; --bw-doc-note-line:#E8D9B5;  /* the desk note's
                                 own fill, fixed: the themed caution fill goes
                                 near-black in dark and the ink is constant */
  --bw-doc-shadow:0 2px 6px rgba(0,0,0,.06), 0 26px 60px -28px rgba(0,0,0,.35);

  /* ── elevation. 2026-10-14, owner ruling (keep the current look): the
        portal's sheets and cards rest on --bw-sh in light, as approved; the
        dark ramp sets all three to none, so dark is flat.                  */
  --bw-sh-sm:0 1px 2px rgba(11,11,11,.05), 0 4px 14px -8px rgba(11,11,11,.14);
  --bw-sh:0 1px 2px rgba(11,11,11,.04), 0 14px 36px -16px rgba(11,11,11,.20);
  --bw-sh-lg:0 2px 6px rgba(11,11,11,.05), 0 30px 60px -24px rgba(11,11,11,.28);
  --bw-glow:0 0 0 3px rgba(106,165,117,.22);      /* focus — v4's real green */
  --bw-glow-err:0 0 0 3px rgba(163,55,38,.14);    /* the error ring — the light
                                 ramp's --bw-warn-ink at 14%. It is a VALUE, so
                                 it lives here: hardcoding it in the component
                                 left a maroon glow on a dark field.        */
  --bw-btn-lift:0 12px 24px -12px rgba(73,114,77,.7);

  /* ── families ─────────────────────────────────────────────────────────── */
  /* "Fraunces Fallback" is Georgia width-matched to Fraunces 500 (the
     @font-face is in bwui-base.css), so a heading that paints in the fallback
     first does not reflow when the web font lands. 2026-10-14. */
  --bw-serif:"Fraunces", "Fraunces Fallback", Georgia, "Times New Roman", serif;
  --bw-sans:"Manrope", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --bw-mono:"JetBrains Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  /* ── radius ladder — 4 steps. Neighbouring values are banned (lint R1).  */
  --bw-r-xs:6px;              /* tags, key wells, the chapter reference chip */
  --bw-r-btn:11px;            /* every button, every input                   */
  --bw-r:14px;                /* cards, callouts, figure frames              */
  --bw-r-lg:18px;             /* outermost frames only — modal, sign-in card */
  /* 2026-10-14, owner ruling (keep the current look): the two shapes the
     approved portal had that the four steps cannot draw. --bw-r-sm is the
     small well (the key group, a seat icon, a file chip, a row input);
     --bw-r-pill is the fully round status pill, chip and theme pair.      */
  --bw-r-sm:8px;
  --bw-r-pill:999px;

  /* ── grid. ONE gutter for header, body and footer, so the page has exactly
        ONE left edge. justify-content:start, never center. Centring an inner
        grid inside --bw-wrap is what produced four left edges (112/200/336/472
        at 1280px) on the current site. Arithmetic at 1280px: wrap 1120 centred
        → x=80; pad 40 → content starts x=120, ends x=1160. Tracks
        240 + 40 + 608 = 888. Slack 112px after the SECOND gutter (1040 − 240 −
        40 − 608 − 40 = 112), ragged right. The slack track holds NOTHING;
        figures may break out across tracks 2+3 (.bwui-fig--wide).           */
  --bw-wrap:70rem;                        /* 1120px */
  --bw-pad:clamp(1.25rem, 4vw, 2.5rem);   /*   20 → 40px */
  --bw-stub:15rem;                        /*  240px — the reference margin */
  --bw-measure:38rem;                     /*  608px — ~70ch */
  --bw-measure-sm:34rem;                  /*  544px — captions, empty states */
  --bw-gut:2.5rem;                        /*   40px */
  --bw-lead-min:7.5rem;                   /*  120px — the HARD dot-leader run.
       One number, two consumers (.bwui-lrow--fig and .bwui-kv__row); it was
       typed twice and drifted-in-waiting.                                    */
  --bw-head-h:4.3125rem;                  /*   69px (2026-10-14, owner ruling: the
       portal's approved header, 68 plus its hairline). Sticky offset. THE HEADER
       IS THIS TALL, not "about" this tall: .bwui-head__in carries
       min-height:var(--bw-head-h), and .bwui-stub, thead th and
       scroll-padding-top all offset by it. If the header can wrap taller than
       the token, the sticky navigation hides UNDER it. See the ≤46rem override
       below.                                                                 */
  --bw-app:65rem;                         /* 1040px — portal shell width (2026-10-14,
       owner ruling: the approved main column; the convergence had 1080) */

  /* ── type ladder. Everything is rem off a 100% root, so a reader who raises
        their browser font size gets a larger site (lint F1 fails on any px
        font-size in the library). Invariant, lint F2: every step is ≥1.12×
        the step below, and the smallest HEADING role (--bw-t-h4, 18px)
        outranks body copy (16px) by size AND weight AND colour. There is no
        heading role anywhere in the system below 18px — anything smaller is a
        LABEL, is set in mono, and is never marked up as h1–h6.
        Rank check at 1280px: 40 / 30 / 22 / 19 lede / 18 / 16.             */
  --bw-t-display:clamp(2.25rem, 1.65rem + 2.6vw, 3rem);  /* 36 → 48px — hero only */
  --bw-t-h1:clamp(2rem, 1.6rem + 1.7vw, 2.5rem);         /* 32 → 40px */
  --bw-t-h2:clamp(1.5rem, 1.2rem + 1.3vw, 1.875rem);     /* 24 → 30px */
  --bw-t-h3:1.375rem;                                    /*      22px */
  --bw-t-h4:1.125rem;                                    /*      18px — heading FLOOR */
  --bw-t-lede:1.1875rem;                                 /*      19px */
  --bw-t-body:1rem;                                      /*      16px */
  --bw-t-small:0.9375rem;                                /*      15px — UI rows */
  --bw-t-fig:0.9375rem;                                  /*      15px — mono amounts */
  --bw-t-micro:0.8125rem;                                /*      13px — helper, caption */
  --bw-t-mono:0.75rem;                                   /*      12px — ids, dates */
  --bw-t-label:0.6875rem;                                /*      11px — FLOOR. Kickers,
       row references, table column labels. Nothing in the system is smaller.
       v4 bottoms out at 9.5px, which is the wrong floor for this audience.  */
  /* 2026-10-14, owner ruling (keep the current look): the approved portal's
     own steps, each the exact pixel size it was set at, so the restored
     pages measure what they measured before the convergence. The 11px
     floor above still holds (its 9.5, 10 and 10.5px labels stay at 11). */
  --bw-t-meta:0.71875rem;                                /*    11.5px — mono sub-lines */
  --bw-t-mono-l:0.78125rem;                              /*    12.5px — mono cells, fine print */
  --bw-t-note:0.84375rem;                                /*    13.5px — notes, help, compact buttons */
  --bw-t-ui:0.875rem;                                    /*      14px — the key, quiet buttons */
  --bw-t-row:0.90625rem;                                 /*    14.5px — nav, labels, row names */
  --bw-t-row-l:0.96875rem;                               /*    15.5px — a person, a stacked subject */
  --bw-t-subj:1.03125rem;                                /*    16.5px — a ticket subject, the pane copy */
  --bw-t-read:1.0625rem;                                 /*      17px — the portal's body, card heads */
  --bw-t-sec:1.3125rem;                                  /*      21px — the section heading */
  --bw-t-net:1.5rem;                                     /*      24px — the net figure */
  --bw-t-modal:1.5625rem;                                /*      25px — the dialog title */
  --bw-t-thread:1.625rem;                                /*      26px — the thread title */
  --bw-t-auth:1.8125rem;                                 /*      29px — the sign-in card title */
  --bw-t-empty:1.875rem;                                 /*      30px — the empty state title */
  --bw-t-page:clamp(1.75rem, 3.4vw, 2.25rem);            /* 28 → 36px — the page display */
  --bw-t-pane:clamp(1.875rem, 3.2vw, 2.5rem);            /* 30 → 40px — the sign-in pane */

  --bw-lh-tight:1.12;         /* display / h1 / h2            */
  --bw-lh-head:1.28;          /* h3 / h4                      */
  --bw-lh-body:1.75;          /* running text at a 70ch measure */
  --bw-lh-ui:1.45;            /* rows, labels, buttons, code wells, textareas */
  --bw-lh-print:1.5;          /* PRINT BODY ONLY — a fifth step, declared
       deliberately rather than typed as a literal in bwui-base.css's print
       block. 1.75 wastes a sheet; 1.45 is tight for halftoned body copy.    */
  /* 2026-10-14, owner ruling (keep the current look): the approved portal's
     reading and display leading. */
  --bw-lh-read:1.65;          /* the portal's body, a message, a note       */
  --bw-lh-display:1.06;       /* the page display                           */
  --bw-lh-fig:1.1;            /* a tally figure, the net figure             */
  --bw-lh-sec:1.2;            /* the section heading                        */
  --bw-lh-flow:1.3;           /* a sequence step's name                     */
  --bw-lh-side:1.35;          /* the quick navigation in the margin         */
  --bw-lh-subj:1.4;           /* a ticket subject                           */
  --bw-lh-sub:1.5;            /* a sub-line under a figure                  */
  --bw-lh-note:1.55;          /* a card lede, a cell note, the dialog note  */
  --bw-lh-lede:1.6;           /* the lede, the sign-in sub-line, card notes */
  --bw-lh-fact:1.7;           /* a card foot, a fact line                   */

  --bw-w-body:400; --bw-w-med:500; --bw-w-semi:600; --bw-w-bold:700;
  --bw-w-xbold:800;           /* the net figure only (2026-10-14, owner ruling) */

  /* ── tracking. TWO values, so "how many things carry the kicker treatment"
        is a grep and not a judgement call (lint S1 counts --bw-track-kicker
        uses; at most three selectors outside .bwui-kicker itself).          */
  --bw-track-kicker:.13em;    /* .bwui-kicker, .bwui-callout__k, .bwui-foot__k */
  --bw-track-label:.06em;     /* every other mono label — table column heads,
                                 tags, keys, directions, section labels      */

  /* ── space ladder. Eight values and no others; lint P1 fails on any margin
        or padding length in the library that is not 0, a --bw-s* token, or
        one of the three named exceptions (.bwui-btn, .bwui-field, .bwui-tag).
        Rhythm rule: the space ABOVE a heading is 3–4× the space below it, so
        a heading binds downward to what it introduces.                      */
  --bw-s0:0.125rem;  /*  2px — the gap inside the double rule, tag padding */
  --bw-s1:0.25rem;   /*  4px */
  --bw-s2:0.5rem;    /*  8px */
  --bw-s3:0.75rem;   /* 12px */
  --bw-s4:1rem;      /* 16px */
  --bw-s5:1.5rem;    /* 24px */
  --bw-s6:2rem;      /* 32px */
  --bw-s7:3rem;      /* 48px */
  --bw-s8:4.5rem;    /* 72px */
}

/* ── THE NARROW HEADER (≤46rem). Not a style — a MEASUREMENT, which is why it
      is here and not in the component sheet.

      At ≤46rem .bwui-head__in wraps (bwui-components.css §4.9) and the header
      is no longer 72px, so every consumer of --bw-head-h — the sticky stub at
      bwui-doc.css §5, the sticky <thead>, html{scroll-padding-top} — was
      offsetting by a number that stopped being true. The stub sits at z-index
      10 under a z-index-30 header: too small a token hides the primary mobile
      navigation the moment the page scrolls.

      The component sheet CAPS the narrow header at exactly three rows so this
      number cannot drift: [brand + theme control] / [nav, one line] /
      [compact search]. Measured at a 320–480px viewport:
          padding-block  12 + 12                            =  24
          row 1  .bwui-iconbtn 2.75rem                      =  44
          gap    --bw-s3                                    =  12
          row 2  nav link 15px × 1.45 + 2 × --bw-s2         =  38
          gap    --bw-s3                                    =  12
          row 3  .bwui-search--compact field min-height     =  36
                                                       total = 166px
      168px (10.5rem) is that, rounded up onto the 8px grid. Because
      .bwui-head__in sets min-height:var(--bw-head-h), rounding UP is the safe
      direction: the header becomes exactly the token and every offset still
      matches. Rounding DOWN hides navigation.

      BUDGET: the nav row holds five short labels at 320px (5 × ~60px + 4 ×
      16px gap = 364 … re-measure at four if the labels are long). Add a sixth
      item, or a two-word label, and the nav wraps to a fourth row — re-measure
      this token before you ship it.                                          */
@media (max-width:46rem){
  :root{ --bw-head-h:10.5rem; }          /* 168px — three rows, see above */
}

/* ── THE PORTAL HEADER (2026-10-14). The portal does not use .bwui-head: its
      header is .site-head in portal.css, 72px on a desktop and TWO rows from
      1023px down (the nav takes a row of its own). Measured at 390 and 768:
      padding 12 + 12, row one 44 (the 44px controls), gap 12, row two 44,
      plus the hairline = 125; 132px (8.25rem) is that on the 4px grid, and
      it wins over the 46rem block above because it comes later. The one
      consumer is .split, the sign-in half-split, which fills what is left.
      The side padding is the same story: 32px on a desktop, 20px from a
      tablet (820px) down, so nothing overhangs at any width.               */
@media (max-width:63.9375rem){
  :root{ --bw-head-h:8.1875rem; }        /* 131px: two rows (2026-10-14, the
                                            approved portal's measure) */
}
@media (max-width:51.25rem){
  :root{ --bw-gutter:1.25rem; }          /* 20px: a tablet and a phone */
}

/* ══════════════════════════════════════════════════════════════════════════
   DARK. Both properties ship it, and it is handled HERE ONLY — a component
   never knows which theme it is in.

   TWO SIGNALS, and the explicit attribute wins in BOTH directions:
     1. @media (prefers-color-scheme: dark) applies to :root:not([data-theme="light"]),
        so a reader who has explicitly chosen LIGHT keeps light on a dark OS.
     2. :root[data-theme="dark"] is declared after it and carries higher
        specificity, so an explicit DARK choice wins on a light OS.
   The portal's FOUC-free initialiser stamps data-theme before first paint;
   :root[data-theme="light"] below re-asserts the light ramp for the case where
   the attribute is stamped light while the OS says dark.

   Warm near-black axis (the portal's — the only worked dark ramp the company
   has), not blue-slate. Ratios are against --bw-paper #121110 unless stated.
   ══════════════════════════════════════════════════════════════════════════ */

@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    color-scheme: dark;

    --bw-outer:#0C0B0A; --bw-paper:#121110; --bw-surface:#1C1B17; --bw-sunk:#211F1A;

    /* 2026-10-14, owner ruling (keep the current look): ink2, muted, the two
       lines, the four channels and the flat cards are the approved portal's
       dark values again; every pair is re-measured by the smoke guard. */
    --bw-ink:#F5F3EC;   /* TEXT 17.71 outer / 16.99 paper / 15.52 surface / 14.83 sunk */
    --bw-ink2:#E4E3DA;  /* TEXT 15.26 outer / 13.38 surface / 12.78 sunk */
    --bw-muted:#B9BDB3; /* TEXT 10.29 outer /  9.02 surface /  8.62 sunk */
    --bw-faint:#6C6A61; /* NOT TEXT 3.63 / 3.48 / 3.18 / 3.04 — decoration only.
                           Light and dark keep --bw-faint and --bw-muted DISTINCT. */

    --bw-line:#2E2C26;
    --bw-line-strong:#3C3A32;

    --bw-green:#6AA575;      /* 6.51 on paper — still a SHAPE token; the role is
                                fixed by rule, not by ratio. */
    --bw-green-deep:#B4D98C; /* TEXT 12.40 outer / 11.90 paper / 10.87 surface /
                                10.38 sunk. #49724D is 3.4:1 here and is never
                                used in dark. */
    --bw-on-green:#121110;   /* TEXT on a --bw-green-deep fill = 11.90 */
    --bw-mint:#243024;       /* ORNAMENT FILL ONLY */

    --bw-note-fill:#18242C; --bw-note-line:#2C3F4C;
    --bw-note-ink:#9CC6E4;   /* TEXT 8.75 on --bw-note-fill */
    --bw-tip-fill:#20281F;  --bw-tip-line:#33472F;
    --bw-tip-ink:#B4D98C;    /* TEXT 9.56 on --bw-tip-fill */
    --bw-caut-fill:#2B2416; --bw-caut-line:#4A3D22;
    --bw-caut-ink:#E5B567;   /* TEXT 8.15 on --bw-caut-fill */
    --bw-warn-fill:#331B17; --bw-warn-line:#523028;
    --bw-warn-ink:#ED9A8C;   /* TEXT 7.33 on --bw-warn-fill */
    --bw-flag:#C4574A;       /* NOT TEXT — fill only */

    /* An --bw-ink panel stays #0B0B0B in dark, so the on-ink ramp is UNCHANGED
       except for --bw-on-ink, which warms to match the dark paper family.   */
    --bw-ink-panel:#0B0B0B;
    --bw-on-ink:#F5F3EC;       /* TEXT 17.73 on --bw-ink-panel */
    --bw-on-ink-2:#CFCFC8;     /* TEXT 12.57 on --bw-ink-panel */
    --bw-on-ink-3:#A8A89F;     /* TEXT  8.22 on --bw-ink-panel */
    --bw-on-ink-green:#6AA575; /* TEXT  6.80 on --bw-ink-panel */
    /* The panel is constant, so its hairlines are too. */
    --bw-on-ink-line:rgba(255,255,255,.28);
    --bw-on-ink-line-soft:rgba(255,255,255,.14);
    --bw-on-ink-wash:rgba(255,255,255,.08);

    --bw-key-fill:#2C2920;     /* --bw-ink2 on this fill = 9.98 (TEXT ok) */
    --bw-key-line:rgba(255,255,255,.20);
    --bw-field-bg:#211F1A;     /* --bw-ink2 on this fill = 11.30 (TEXT ok) */
    --bw-field-line:#7A776D;   /* 3.85:1 on --bw-surface, 3.67:1 on --bw-sunk ,
                                 a SOLID value (2026-10-14), so the ratio is the
                                 same on every ground; the .34 white composite
                                 was 3.09 on the field and under 3 on a card. */

    /* flat in dark: a shadow on a near-black ground reads as a smudge
       (the approved portal's dark set, 2026-10-14) */
    --bw-sh-sm:none;
    --bw-sh:none;
    --bw-sh-lg:none;
    --bw-glow:0 0 0 3px rgba(180,217,140,.22);
    --bw-glow-err:0 0 0 3px rgba(236,154,154,.20);  /* the dark --bw-warn-ink */
    --bw-btn-lift:0 12px 24px -12px rgba(180,217,140,.35);

    /* portal additions, dark (2026-10-14) */
    --bw-meta:#A8ACA1;         /* TEXT 7.1 paper / 6.5 surface / 6.1 sunk */
    --bw-green-on-ground:#B4D98C; /* TEXT 12.4 on the dark ground */
    --bw-pane:#211F1A; --bw-pane-edge:var(--bw-line);
    --bw-scrim:rgba(0,0,0,.62);
    --bw-sh-menu:0 12px 28px rgba(0,0,0,.55);
    --bw-chip-wash:rgba(0,0,0,.10);
    --bw-select-arrow:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23A8ACA1' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='M5 9l7 7 7-7'/%3E%3C/svg%3E");
  }
}

/* Explicit DARK — wins on a light OS. Same values; duplicated verbatim because
   there is no preprocessor and a custom property cannot alias a whole block.
   If you edit one ramp you MUST edit the other; contrast_test.py resolves both
   and will fail on a drift. */
:root[data-theme="dark"]{
  color-scheme: dark;

  --bw-outer:#0C0B0A; --bw-paper:#121110; --bw-surface:#1C1B17; --bw-sunk:#211F1A;

  /* 2026-10-14, owner ruling: identical to the media block above */
  --bw-ink:#F5F3EC;   /* TEXT 17.71 outer / 16.99 paper / 15.52 surface / 14.83 sunk */
  --bw-ink2:#E4E3DA;  /* TEXT 15.26 outer / 13.38 surface / 12.78 sunk */
  --bw-muted:#B9BDB3; /* TEXT 10.29 outer /  9.02 surface /  8.62 sunk */
  --bw-faint:#6C6A61; /* NOT TEXT 3.63 / 3.48 / 3.18 / 3.04 — decoration only */

  --bw-line:#2E2C26;
  --bw-line-strong:#3C3A32;

  --bw-green:#6AA575;      /* SHAPE token — 6.51 on paper, role fixed by rule */
  --bw-green-deep:#B4D98C; /* TEXT 12.40 outer / 11.90 paper / 10.87 surface / 10.38 sunk */
  --bw-on-green:#121110;   /* TEXT on a --bw-green-deep fill = 11.90 */
  --bw-mint:#243024;       /* ORNAMENT FILL ONLY */

  --bw-note-fill:#18242C; --bw-note-line:#2C3F4C;
  --bw-note-ink:#9CC6E4;   /* TEXT 8.75 on --bw-note-fill */
  --bw-tip-fill:#20281F;  --bw-tip-line:#33472F;
  --bw-tip-ink:#B4D98C;    /* TEXT 9.56 on --bw-tip-fill */
  --bw-caut-fill:#2B2416; --bw-caut-line:#4A3D22;
  --bw-caut-ink:#E5B567;   /* TEXT 8.15 on --bw-caut-fill */
  --bw-warn-fill:#331B17; --bw-warn-line:#523028;
  --bw-warn-ink:#ED9A8C;   /* TEXT 7.33 on --bw-warn-fill */
  --bw-flag:#C4574A;       /* NOT TEXT — fill only */

  --bw-ink-panel:#0B0B0B;
  --bw-on-ink:#F5F3EC;       /* TEXT 17.73 on --bw-ink-panel */
  --bw-on-ink-2:#CFCFC8;     /* TEXT 12.57 on --bw-ink-panel */
  --bw-on-ink-3:#A8A89F;     /* TEXT  8.22 on --bw-ink-panel */
  --bw-on-ink-green:#6AA575; /* TEXT  6.80 on --bw-ink-panel */
  --bw-on-ink-line:rgba(255,255,255,.28);
  --bw-on-ink-line-soft:rgba(255,255,255,.14);
  --bw-on-ink-wash:rgba(255,255,255,.08);

  --bw-key-fill:#2C2920;     /* --bw-ink2 on this fill = 9.98 (TEXT ok) */
  --bw-key-line:rgba(255,255,255,.20);
  --bw-field-bg:#211F1A;     /* --bw-ink2 on this fill = 11.30 (TEXT ok) */
  --bw-field-line:#7A776D;   /* 3.85:1 surface / 3.67:1 sunk (2026-10-14) */

  --bw-sh-sm:none;
  --bw-sh:none;
  --bw-sh-lg:none;
  --bw-glow:0 0 0 3px rgba(180,217,140,.22);
  --bw-glow-err:0 0 0 3px rgba(236,154,154,.20);
  --bw-btn-lift:0 12px 24px -12px rgba(180,217,140,.35);

  /* portal additions, dark (2026-10-14): identical to the media block */
  --bw-meta:#A8ACA1;
  --bw-green-on-ground:#B4D98C;
  --bw-pane:#211F1A; --bw-pane-edge:var(--bw-line);
  --bw-scrim:rgba(0,0,0,.62);
  --bw-sh-menu:0 12px 28px rgba(0,0,0,.55);
  --bw-chip-wash:rgba(0,0,0,.10);
  --bw-select-arrow:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23A8ACA1' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='M5 9l7 7 7-7'/%3E%3C/svg%3E");
}

/* Explicit LIGHT — wins on a dark OS. Only the values the dark ramp changes
   need re-asserting; everything else was never overridden. */
:root[data-theme="light"]{
  color-scheme: light;

  --bw-outer:#E7E5DC; --bw-paper:#F5F4EE; --bw-surface:#FFFFFF; --bw-sunk:#FCFBF6;

  --bw-ink:#0B0B0B;   /* TEXT 15.60 / 17.86 / 19.68 / 19.00 */
  --bw-ink2:#161616;  /* TEXT 14.34 / 16.42 / 18.10 / 17.47 */
  --bw-muted:#3E523F; /* TEXT  6.70 /  7.67 /  8.46 /  8.16 */
  --bw-faint:#8E938A; /* NOT TEXT 2.49 / 2.85 / 3.14 / 3.03 — decoration only */

  --bw-line:#E5E2D7;
  --bw-line-strong:#D6D2C5;

  --bw-green:#6AA575;      /* NOT TEXT on a light ground — 2.90 on surface */
  --bw-green-deep:#49724D; /* TEXT 5.53 surface / 5.02 paper / 5.34 sunk */
  --bw-on-green:#FFFFFF;   /* TEXT on a --bw-green-deep fill = 5.53 */
  --bw-mint:#D9EDDE;       /* ORNAMENT FILL ONLY */

  --bw-note-fill:#E4EEF2; --bw-note-line:#C6DCE6;
  --bw-note-ink:#185FA5;   /* TEXT 5.53 on --bw-note-fill */
  --bw-tip-fill:#EDF5EF;  --bw-tip-line:#BFE0C9;
  --bw-tip-ink:#49724D;    /* TEXT 4.98 on --bw-tip-fill */
  --bw-caut-fill:#F6EEDC; --bw-caut-line:#E8D9B5;
  --bw-caut-ink:#8A5A13;   /* TEXT 5.12 on --bw-caut-fill */
  --bw-warn-fill:#F7E8E4; --bw-warn-line:#E7C9C3;
  --bw-warn-ink:#9E3B2C;   /* TEXT 5.65 on --bw-warn-fill */
  --bw-flag:#BC4B3B;       /* NOT TEXT — fill only */

  --bw-ink-panel:#0B0B0B;
  --bw-on-ink:#FFFFFF;       /* TEXT 19.68 on --bw-ink-panel */
  --bw-on-ink-2:#CFCFC8;     /* TEXT 12.57 on --bw-ink-panel */
  --bw-on-ink-3:#A8A89F;     /* TEXT  8.22 on --bw-ink-panel */
  --bw-on-ink-green:#6AA575; /* TEXT  6.80 on --bw-ink-panel */
  --bw-on-ink-line:rgba(255,255,255,.28);
  --bw-on-ink-line-soft:rgba(255,255,255,.14);
  --bw-on-ink-wash:rgba(255,255,255,.08);

  --bw-key-fill:#F0EEE7;   --bw-key-line:#D6D2C5;
  --bw-field-bg:#FFFFFF;   --bw-field-line:#95917F;   /* 3.17:1 on #FFFFFF */

  --bw-sh-sm:0 1px 2px rgba(11,11,11,.05), 0 4px 14px -8px rgba(11,11,11,.14);
  --bw-sh:0 1px 2px rgba(11,11,11,.04), 0 14px 36px -16px rgba(11,11,11,.20);
  --bw-sh-lg:0 2px 6px rgba(11,11,11,.05), 0 30px 60px -24px rgba(11,11,11,.28);
  --bw-glow:0 0 0 3px rgba(106,165,117,.22);
  --bw-glow-err:0 0 0 3px rgba(163,55,38,.14);
  --bw-btn-lift:0 12px 24px -12px rgba(73,114,77,.7);

  /* portal additions, light re-asserted (2026-10-14) */
  --bw-meta:#5C5F58;
  --bw-green-on-ground:#476F4B;
  --bw-pane:#161616; --bw-pane-edge:transparent;
  --bw-scrim:rgba(11,11,11,.45);
  --bw-sh-menu:0 12px 28px rgba(0,0,0,.16);
  --bw-chip-wash:rgba(255,255,255,.18);
  --bw-select-arrow:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%235C5F58' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='M5 9l7 7 7-7'/%3E%3C/svg%3E");
}

/* ── PRINT. Paper is paper. The light ramp is re-asserted here so a reader who
      prints while in dark mode does not get near-white ink on a page the
      printer renders as white. Elevation is removed outright: a shadow costs
      toner and buys nothing. Layout for print lives in bwui-base.css; only
      VALUES live here.                                                      */
@media print{
  :root, :root[data-theme="dark"], :root[data-theme="light"]{
    color-scheme: light;
    --bw-outer:#FFFFFF; --bw-paper:#FFFFFF; --bw-surface:#FFFFFF; --bw-sunk:#FFFFFF;
    --bw-ink:#000000;   /* TEXT 21.00 on white */
    --bw-ink2:#161616;  /* TEXT 18.10 on white */
    --bw-muted:#3E523F; /* TEXT  8.46 on white */
    --bw-faint:#767B72; /* NOT TEXT — decoration only; darkened from #8E938A
                           because print halftones lose the lightest greys.   */
    --bw-line:#C9C5B6;
    --bw-line-strong:#8E938A;
    --bw-green-deep:#49724D; /* TEXT 5.53 on white */
    --bw-ink-panel:#FFFFFF;
    --bw-on-ink:#000000;     /* TEXT 21.00 on white */
    --bw-on-ink-2:#161616;   /* TEXT 18.10 on white */
    --bw-on-ink-3:#3E523F;   /* TEXT  8.46 on white */
    --bw-on-ink-green:#49724D;/* TEXT 5.53 on white — the fill green is 2.90
                                 here and would be unreadable.               */
    /* The panel is WHITE in print, so a white-on-white hairline would vanish;
       the on-ink rules take the paper hairlines instead.                    */
    --bw-on-ink-line:#8E938A;
    --bw-on-ink-line-soft:#C9C5B6;
    --bw-on-ink-wash:transparent;
    --bw-key-fill:#FFFFFF;   --bw-key-line:#C9C5B6;
    --bw-field-bg:#FFFFFF;   --bw-field-line:#8E938A;
    --bw-sh-sm:none; --bw-sh:none; --bw-sh-lg:none;
    --bw-glow:none;  --bw-glow-err:none;  --bw-btn-lift:none;
    /* portal additions in print (2026-10-14): readable on white, no overlay */
    --bw-meta:#3E523F;       /* TEXT 8.46 on white */
    --bw-green-on-ground:#476F4B;
    --bw-pane:#FFFFFF; --bw-pane-edge:#C9C5B6;
    --bw-on-dark:#000000; --bw-on-dark-2:#161616; --bw-on-dark-3:#3E523F;
    --bw-on-dark-green:#49724D;
    --bw-scrim:transparent; --bw-sh-menu:none;
  }
}
