/* ============================================================
   Wojtek Staszczyk — Design Tokens (single source of truth)
   Extracted from colors_and_type.css on 2026-07-13 (RUI-04).
   EVERY page links this file FIRST, before any inline <style>.
   Element styles for case studies live in colors_and_type.css.
   Rules: see personal site/CLAUDE.md → "Design system rules".
   ============================================================ */

/* ============================================================
   DARK MODE IS LIVE from here down.

   Authored with light-dark() + color-scheme rather than a
   [data-theme] attribute, on purpose. A [data-theme] approach has to
   state every dark value TWICE - once under :root[data-theme="dark"]
   and once under @media (prefers-color-scheme: dark) for the
   no-preference case - because CSS cannot OR a media query with a
   selector. Two copies of ~60 tokens that must never drift is the
   likeliest place for a silent bug. light-dark() states each once.

   Every themed token is declared TWICE on purpose:
       --x: <light>;
       --x: light-dark(<light>, <dark>);
   An engine that cannot parse light-dark() drops the second
   declaration at parse time and keeps the first, so a pre-2024
   browser renders today's light site byte for byte. That is a
   stronger guarantee than [data-theme] gives.

   HARD RULE: never set color-scheme on anything but :root.
   light-dark() resolves against the USING element's computed
   color-scheme, so a per-element value would flip every inherited
   token inside it.
   ============================================================ */

:root {
  /* No stored preference = follow the OS. This alone gives correct
     light/dark with zero JavaScript, and it is what makes the OS's
     own sunset schedule (macOS Auto, iOS Sunset to Sunrise, Android)
     reach the site - which is why there is no sunset code here. */
  color-scheme: light dark;
}
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"]  { color-scheme: dark;  }

@media print {
  /* A dark page prints as a wall of ink, or white-on-white. */
  :root { color-scheme: light !important; }
}

:root {
  /* ---------- COLOR: WARM NEUTRAL FOUNDATION ------------- */
  --linen-50:  #FAF7F0;  /* paper / page bg */
  --linen-100: #F5F1EA;  /* primary cream bg (matches --cream) */
  --linen-200: #EDE6D8;  /* secondary / card bg (matches --cream-2) */
  --linen-300: #D9D1C0;  /* border / hairline (matches --line) */
  --linen-400: #9A8471;  /* lighter muted — decorative/15px+ only (3.15:1 on cream) */
  --linen-500: #6B6357;  /* muted text / meta (matches --muted, 5.26:1 on cream) */

  --ink-900: #1A1815;    /* primary text (matches --ink) */
  --ink-800: #3A352E;    /* soft ink (matches --ink-soft) */
  --ink-700: #4A3D34;
  --ink-600: #5C4E45;

  /* ---------- COLOR: ACCENT (the "20%") ------------------- */
  /* V3: dark amber — audit batch-1 (brand differentiation, 2026-05-27) */
  --copper-50:  #F5EDD6;  /* very light amber */
  --copper-100: #E8D5A8;  /* light amber */
  --copper-300: #C4915C;  /* mid amber — used for borders, sub-accents (6.4:1 on ink) */
  --copper-500: #7a4a0a;  /* PRIMARY ACCENT — matches --accent (6.6:1 on cream) */
  --copper-600: #5a3508;  /* hover (matches --accent-2, 9.6:1 on cream) */
  --copper-700: #4A2C06;  /* dark amber — used for labels, small text */
  --copper-900: #2A1804;  /* very dark amber */

  /* terra-* aliases REMOVED 2026-08-31 - the case studies now use the
     same semantic roles as the rest of the site. */

  /* Aliases: short-name tokens (main pages) → semantic tokens */
  --cream:    var(--linen-100);   /* #f5f1ea */
  --cream-2:  var(--linen-200);   /* #ede6d8 */
  --paper:    var(--linen-50);    /* #faf7f0 */
  --ink:      var(--ink-900);     /* #1a1815 */
  --ink-soft: var(--ink-800);     /* #3a352e */
  --muted:    var(--linen-500);   /* #6b6357 */
  --line:     var(--linen-300);   /* #d9d1c0 */
  --accent:   var(--copper-500);  /* primary accent */
  --accent-2: var(--copper-600);  /* pressed / hover */

  /* ---------- COLOR: ON-DARK TEXT — REMOVED 2026-08-31 ----
     --fg-on-dark-1/2/3, --accent-on-dark and --line-on-dark are gone.
     Their names described the LIGHT theme's inverted bands, which
     stopped being coherent once dark mode existed ("on dark"
     relative to what?). Use the band scope at the bottom of this
     file instead: inside a band, --fg-1/2/3, --fg-accent and --rule
     already resolve to the band's own ladder.
     The rule they carried survives and still applies:
     NEVER rgba(cream, opacity) for text on a band - it fails
     contrast and reads washed out (Refactoring UI pp. 36-38, 142). */

  /* ---------- COLOR: SEMANTIC ---------------------------- */
  --success: #5A7A3E;
  --success:  light-dark(#5A7A3E, #8FB06B);
  --warning: #C28A2C;
  --warning:  light-dark(#C28A2C, #E0AC5B);
  --danger:  #B8412E;
  --danger:   light-dark(#B8412E, #E08270);
  --info:    #5C6B7A;
  --info:     light-dark(#5C6B7A, #9BAAB9);

  /* ---------- FG / BG / BORDER -------------------------- */
  --bg-canvas:   var(--linen-100);   /* #f5f1ea — main cream */
  --bg-canvas:    light-dark(var(--linen-100), var(--umber-900));
  --bg-surface:  var(--linen-50);    /* #faf7f0 — paper/cards */
  --bg-surface:   light-dark(var(--linen-50), var(--umber-800));
  --bg-muted:    var(--linen-200);   /* #ede6d8 — recessed */
  --bg-muted:     light-dark(var(--linen-200), var(--umber-950));

  --fg-1: var(--ink-900);
  --fg-1:  light-dark(var(--ink-900), var(--sand-50));
  /* The real text ladder has FOUR rungs, not three: page CSS used
     --ink-soft (#3A352E, 10.79:1 on cream) 73 times for body copy
     that is softer than a heading but louder than meta. --fg-2 is a
     different value, so folding them together would have changed the
     page. Dark value sits between --fg-1 (15.19:1) and --fg-2
     (9.15:1) at 11.87:1, preserving the same three-way separation. */
  --fg-body: var(--ink-800);
  --fg-body: light-dark(var(--ink-800), #D5CEC2);
  --fg-2: var(--linen-500);
  --fg-2:  light-dark(var(--linen-500), var(--sand-200));
  --fg-3: var(--linen-400);
  --fg-3:  light-dark(var(--linen-400), var(--sand-400));
  --fg-accent: var(--copper-500);
  --fg-accent:  light-dark(var(--copper-500), var(--copper-200));
  --fg-on-accent: var(--linen-50);
  --fg-on-accent:  light-dark(var(--linen-50), #241A0C);
  /* Secondary text on an accent fill. Solid, not an alpha of the primary:
     DESIGN.md 0.4 forbids opacity-based text, and it breaks hardest exactly
     here - the fill inverts between themes, so a fixed alpha that reads at
     62% over dark amber vanishes over light amber. 5.20:1 / 5.03:1. */
  --fg-on-accent-2: #E2D6C0;
  --fg-on-accent-2: light-dark(#E2D6C0, #4A3418);

  --border-hairline: var(--linen-300);
  --border-hairline:  light-dark(var(--linen-300), var(--umber-600));
  --border-strong:   var(--linen-400);
  --border-strong:    light-dark(var(--linen-400), var(--umber-400));


  /* ============================================================
     DARK MODE — ARCHITECTURE (phase 1)
     Added 2026-08-31. LIGHT VALUES ONLY at this stage: every token
     below resolves to exactly what the site renders today, so this
     block is a pure addition with no visual effect. Phase 5 converts
     the semantic layer to light-dark() and the second theme turns on.

     THE THREE LAYERS — and the one rule that matters:

       Layer 1  palette ramps (--linen/--ink/--copper/--umber/--sand)
                Raw hex. NEVER referenced by component CSS.
       Layer 2  legacy aliases (--cream/--ink/--accent/--terra-*)
                FROZEN TO LIGHT. They do not theme-flip, by design:
                that is what lets un-migrated CSS keep rendering
                correctly while the migration runs page by page.
       Layer 3  semantic roles (--fg-*, --bg-*, --rule, --band-*)
                The ONLY layer component CSS may touch.

     Why roles and not colours: --cream used to mean both "the page
     background" AND "text on a dark band", and --ink meant both
     "body text" AND "the dark band's background". One token, two
     opposite jobs — so no value could be correct in both themes.
     Components now ask for a role relative to the surface they sit
     on, and a band rebinds those roles to its own ladder (bottom of
     this file). --fg-1 is "the primary text colour HERE", whatever
     "here" happens to be.
     ============================================================ */

  /* ---------- L1: DARK SURFACES (warm umber, hue ~35deg) --------
     Not pure black, deliberately: #000 maximises halation for
     readers with astigmatism and cannot show a shadow. Warm rather
     than grey so the dark theme still reads as paper-and-ink. */
  --umber-950: #0F0E0D;  /* sunken wells, code blocks              */
  --umber-900: #15130F;  /* DARK PAGE CANVAS                       */
  --umber-800: #1D1A15;  /* card on canvas          (1.07:1 lift)  */
  --umber-700: #2E2921;  /* BAND — the lift         (1.29:1 lift)  */
  --umber-600: #3A3329;  /* band card / hover / rule               */
  --umber-500: #423B31;  /* rule on band                           */
  --umber-400: #574E42;  /* rule-strong                            */

  /* ---------- L1: FOREGROUNDS FOR DARK SURFACES (warm sand) ----- */
  --sand-50:  #EDE8DE;   /* fg-1 on dark canvas   15.2:1           */
  --sand-100: #DCD4C6;   /* SLAB FILL on dark — deliberately softer
                            than --sand-50. A slab is a large flooded
                            area, not small strokes, so it needs less
                            luminance than body text to read as loud.
                            Chosen over the full #EDE8DE 2026-08-31.  */
  --sand-200: #BFB5A4;   /* fg-2 on dark canvas    9.2:1           */
  --sand-300: #D4CBBA;   /* fg-2 on lifted band    9.8:1           */
  --sand-350: #B0A08C;   /* fg-3 on lifted band    5.8:1           */
  --sand-400: #A2988A;   /* fg-3 on dark canvas    6.5:1           */

  /* ---------- L1: ACCENT STEPS FOR DARK GROUNDS -----------------
     The accent cannot survive the flip unchanged: --copper-500
     #7a4a0a is a DARK amber that works because the ground is light,
     and it is near-invisible on #15130F. Material's tone mapping
     (primary tone 40 -> 80) says lighten AND desaturate; #D4A06A is
     92% -> 54% saturation on the same hue. That value already
     existed here as --accent-on-dark, so the call is proven. */
  --copper-150: #E3B98C; /* accent hover on dark canvas            */
  --copper-200: #D4A06A; /* accent on dark canvas  (was on-dark)   */
  --copper-250: #E0AE7C; /* accent on the lifted band              */

  /* ---------- L3: SEMANTIC — SURFACES -------------------------- */
  --bg-sunken: var(--linen-200);  /* recessed wells; inverts in dark */
  --bg-sunken:  light-dark(var(--linen-200), var(--umber-950));

  /* ---------- L3: SEMANTIC — RULES ----------------------------- */
  /* Same values as --border-hairline/--border-strong, shorter names,
     and unlike those they get rebound inside a band. */
  --rule:        var(--linen-300);
  --rule:         light-dark(var(--linen-300), var(--umber-600));
  --rule-strong: var(--linen-400);
  --rule-strong:  light-dark(var(--linen-400), var(--umber-400));

  /* ---------- L3: SEMANTIC — ACCENT ---------------------------- */
  /* Hover REVERSES direction between themes: darker on light,
     lighter on dark. Only a named role can carry that. */
  --fg-accent-hover: var(--copper-600);
  --fg-accent-hover:  light-dark(var(--copper-600), var(--copper-150));


  /* ---------- L3: THE AMBER SUB-FAMILY ------------------------
     Page CSS reached past the semantic layer for these because no
     role existed. They are the accent used at four different jobs,
     and each needs its own dark counterpart - a single --fg-accent
     cannot serve a hairline, a label, a callout fill and a border.
     Light values are exactly what they replace. ---------------- */
  --accent-soft:    var(--copper-300); /* sub-accent: marks, rules, borders */
  --accent-soft:     light-dark(var(--copper-300), #B8894F);
  --accent-strong:  var(--copper-600); /* pressed / heavier accent          */
  --accent-strong:   light-dark(var(--copper-600), var(--copper-150));
  --accent-label:   var(--copper-700); /* small caps labels on light        */
  /* A FILLED accent surface - a button or badge whose background is the
     accent. Distinct from --fg-accent because the band scope rebinds that
     one: inside a band --fg-accent is the lighter on-band amber, which is
     right for text but leaves a filled button with no contrast against the
     band it sits on. This one is never rebound, so a filled accent control
     reads the same way on the page and inside a band. */
  --accent-fill:    var(--copper-500);
  --accent-fill:    light-dark(var(--copper-500), var(--copper-200));
  --accent-label:    light-dark(var(--copper-700), #E0BC91);
  --surface-accent: var(--copper-50);  /* callout / highlight fill          */
  --surface-accent:  light-dark(var(--copper-50), #241E14);
  --border-accent:  var(--copper-100); /* callout border                    */
  --border-accent:   light-dark(var(--copper-100), #4A3E28);

  /* ---------- L3: SEMANTIC — THE BAND -------------------------- */
  /* A "band" is the full-bleed emphasis section: the footer, the
     #contact CTA, .cta-band on posts, .sd and .cs-footer-contact on
     case studies. Today it is DARKER than the page. In dark mode it
     LIFTS — becomes lighter than the canvas — which preserves the
     meaning ("this section is emphasised") while inverting the
     mechanism, exactly as elevation works in a dark UI. DESIGN.md
     §9's "one full-bleed dark region per page" becomes "one lifted
     region per page" and stays enforceable. */
  /* DARK VALUE SETTLED 2026-08-31: --umber-700 #2E2921, a 1.29:1 lift
     above the dark canvas. Reviewed against #26221C (1.17:1) and
     #332D24 (1.36:1) in _dev/palette.html; all three clear AA for band
     meta text, so the call was aesthetic, not a contrast constraint. */
  --band-bg:               var(--ink-900);
  --band-bg:                light-dark(var(--ink-900), var(--umber-700));
  --band-bg-2:             #221F1A;   /* nested card inside a band  */
  --band-bg-2:              light-dark(#221F1A, var(--umber-600));
  --band-fg-1:             var(--linen-100);
  --band-fg-1:              light-dark(var(--linen-100), var(--linen-100));
  --band-fg-2:             var(--linen-300);
  --band-fg-2:              light-dark(var(--linen-300), var(--sand-300));
  --band-fg-3:             var(--linen-400);
  --band-fg-3:              light-dark(var(--linen-400), var(--sand-350));
  --band-fg-accent:        var(--copper-200);
  --band-fg-accent:         light-dark(var(--copper-200), var(--copper-250));
  --band-fg-accent-hover:  var(--copper-150);
  --band-fg-accent-hover:   light-dark(var(--copper-150), #EFCBA4);
  --band-rule:             rgba(245, 241, 234, .15);
  --band-rule:              light-dark(rgba(245, 241, 234, .15), rgba(245, 241, 234, .10));
  --band-rule-strong:      var(--ink-700);
  --band-rule-strong:       light-dark(var(--ink-700), var(--umber-400));

  /* ---------- L3: SEMANTIC — MAX-CONTRAST SLABS ----------------
     .nav-cv, .btn-p, .skip-link:focus, .form-submit, a.btn. These
     are NOT bands. A band is a surface you read ON; a slab is a
     control that must stand OUT. In dark mode a band lifts a little,
     but a slab has to inverAt all the way or it disappears. Same
     token name, opposite direction — which is why they must not
     share one. Inside a band the scope below re-points these so the
     slab inverts against the band, in either theme, for free. */
  /* DARK VALUE SETTLED 2026-08-31: --sand-100 #DCD4C6 (not --sand-50). */
  --btn-primary-bg:        var(--ink-900);
  --btn-primary-bg:         light-dark(var(--ink-900), var(--sand-100));
  --btn-primary-fg:        var(--linen-100);
  --btn-primary-fg:         light-dark(var(--linen-100), var(--umber-900));
  --btn-primary-bg-hover:  var(--copper-500);
  --btn-primary-bg-hover:   light-dark(var(--copper-500), var(--copper-200));
  --btn-primary-fg-hover:  var(--linen-100);
  --btn-primary-fg-hover:   light-dark(var(--linen-100), #241A0C);


  /* ---------- L3: TRANSLUCENCY -------------------------------
     rgba() cannot consume a hex custom property, so every scrim,
     sticky bar and tint on this site was a hardcoded literal that
     no theme could reach. That is why they must become tokens.

     NOT rgb-triplet tokens (--ink-rgb: 26,24,21). Triplets force the
     SAME alpha in both themes, which is wrong for nearly every case
     here: rgb(26 24 21 / .55) is a correct scrim over cream, but the
     same alpha over a near-black canvas is far too weak. A colour
     with alpha IS a <color>, so light-dark() takes it whole in
     phase 5 and each theme gets its own hand-tuned alpha.

     Light values only at this stage - identical to the literals they
     replace. ------------------------------------------------- */
  --bar-bg:        rgba(245, 241, 234, 0.85); /* sticky header       */
  --bar-bg:         light-dark(rgba(245, 241, 234, 0.85), rgba(21, 19, 15, 0.86));
  --bar-bg-solid:  rgba(245, 241, 234, 0.96); /* header, opaque var  */
  --bar-bg-solid:   light-dark(rgba(245, 241, 234, 0.96), rgba(21, 19, 15, 0.94));
  --float-bg:      rgba(250, 247, 240, .96);  /* case-study float nav*/
  --float-bg:       light-dark(rgba(250, 247, 240, .96), rgba(29, 26, 21, .94));
  --scrim:         rgba(26, 24, 21, .55);     /* drawer overlay      */
  --scrim:          light-dark(rgba(26, 24, 21, .55), rgba(8, 7, 6, .72));
  --scrim-strong:  rgba(26, 24, 21, .82);     /* modal overlay       */
  --scrim-strong:   light-dark(rgba(26, 24, 21, .82), rgba(8, 7, 6, .88));

  /* surface tints - hover / pressed / stronger, on a light ground */
  --tint-1:        rgba(26, 24, 21, .06);
  --tint-1:         light-dark(rgba(26, 24, 21, .06), rgba(237, 232, 222, .07));
  --tint-2:        rgba(26, 24, 21, .08);
  --tint-2:         light-dark(rgba(26, 24, 21, .08), rgba(237, 232, 222, .10));
  --tint-3:        rgba(26, 24, 21, .1);
  --tint-3:         light-dark(rgba(26, 24, 21, .1), rgba(237, 232, 222, .14));
  --band-tint-1:   rgba(245, 241, 234, .06);  /* tint INSIDE a band  */
  --band-tint-1:    light-dark(rgba(245, 241, 234, .06), rgba(245, 241, 234, .07));

  /* accent tints - portrait FX, callouts */
  --accent-tint-1: rgba(122, 74, 10, 0.08);
  --accent-tint-1:  light-dark(rgba(122, 74, 10, 0.08), rgba(212, 160, 106, 0.12));
  --accent-tint-2: rgba(122, 74, 10, .12);
  --accent-tint-2:  light-dark(rgba(122, 74, 10, .12), rgba(212, 160, 106, .18));
  --accent-tint-3: rgba(122, 74, 10, 0.3);
  --accent-tint-3:  light-dark(rgba(122, 74, 10, 0.3), rgba(212, 160, 106, 0.40));
  --accent-veil:   rgba(122, 74, 10, .92);
  --accent-veil:    light-dark(rgba(122, 74, 10, .92), rgba(212, 160, 106, .92));

  /* over media - these sit on photographs, not on a themed surface,
     so they stay near-black in BOTH themes */
  --overlay-media: rgba(0, 0, 0, .45);
  --overlay-deep:  rgba(0, 0, 0, .35);

  /* shadow colours. Dark mode needs a MUCH higher alpha to be
     visible at all against a near-black ground - a straight port of
     .04 is invisible - hence separate tokens rather than reusing
     --tint-*. */
  --shadow-a:      rgba(26, 24, 21, 0.04);
  --shadow-a:       light-dark(rgba(26, 24, 21, 0.04), rgba(0, 0, 0, 0.40));
  --shadow-b:      rgba(26, 24, 21, 0.06);
  --shadow-b:       light-dark(rgba(26, 24, 21, 0.06), rgba(0, 0, 0, 0.46));
  --shadow-c:      rgba(26, 24, 21, .18);     /* drawer              */
  --shadow-c:       light-dark(rgba(26, 24, 21, .18), rgba(0, 0, 0, .58));
  --shadow-d:      rgba(26, 24, 21, 0.03);
  --shadow-d:       light-dark(rgba(26, 24, 21, 0.03), rgba(0, 0, 0, 0.30));
  --shadow-e:      rgba(26, 24, 21, 0.08);
  --shadow-e:       light-dark(rgba(26, 24, 21, 0.08), rgba(0, 0, 0, 0.50));
  --focus-ring:    rgba(122, 74, 10, 0.18);   /* :focus-visible ring */

  /* Edge for light-background imagery. Transparent in light - those images
     already sit on cream and need no help - and a visible hairline in dark,
     where an unframed white screenshot reads as a hole punched in the page
     rather than an object. NOT a dimming filter: these are screenshots of
     light product UIs, they are SUPPOSED to be bright, and dimming meaningful
     content hurts exactly the light-sensitive readers dark mode is for. */
  --img-edge: transparent;
  --img-edge: light-dark(transparent, var(--rule-strong));
  --focus-ring:     light-dark(rgba(122, 74, 10, 0.18), rgba(212, 160, 106, 0.32));


  /* STILL LITERAL after phase 4 - 15 one-off rgba() values that had no
     exact token. Each needs a dark value CHOSEN, not derived, so they
     are phase 5 work rather than a mechanical swap:

       .zbar / .zhint / .img-zoom-badge (4th-case-study-fa)
         paper at .90 / .94 / .95 - floating UI over images. Three
         near-identical alphas that should collapse into one token;
         that is a deliberate 1-2% change, so it needs a decision.
       .ofl-in .ofl-n / .ofl-d (4th-case-study-fa)
         color:rgba(250,247,240,.62) and .82 - opacity-based TEXT on a
         dark ground. This already violates DESIGN.md 0.4 and 9 today
         ("never rgba(cream, opacity) for text on dark"). Should become
         --fg-2 / --fg-3, which is a real (small) contrast change.
       .fx-* portrait easter-egg tints (index.html)
         accent at 0, .1, .14, .35 - decorative gradient stops.
       .preview-btn:hover .pv-count
         rgba(255,255,255,.18) - a white veil over an accent fill;
         correct in both themes as-is.
  */

  /* ---------- TYPE: FAMILIES ----------------------------- */
  --font-serif: 'Chivo', Georgia, serif;
  --font-sans:  'Inter', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Arial, sans-serif;
  --font-mono:  'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;

  /* ---------- TYPE: SCALE --------------------------------
     The only text sizes. 12px (.75rem) is the floor.
     .75 / .875 / 1 / 1.125 / 1.25 / 1.375 / 1.5 / 1.75 rem
     + display clamps below. (Refactoring UI pp. 88-93)      */
  --fs-display-xl: clamp(3.5rem, 7vw, 6rem);
  --fs-display-lg: clamp(2.5rem, 5vw, 4.5rem);
  --fs-display-md: clamp(2rem, 3.5vw, 3rem);
  --fs-h1: 2.25rem;
  --fs-h2: 1.75rem;
  --fs-h3: 1.375rem;
  --fs-h4: 1.125rem;
  --fs-body-lg: 1.1875rem;
  --fs-body:    1rem;
  --fs-small:   0.875rem;
  --fs-caption: 0.75rem;

  /* ---------- TYPE: WEIGHTS ------------------------------ */
  --fw-light:    300;
  --fw-regular:  400;
  --fw-medium:   500;
  --fw-semibold: 600;
  --fw-bold:     700;

  /* ---------- TYPE: LEADING / TRACKING ------------------- */
  --lh-tight: 1.05;
  --lh-snug: 1.2;
  --lh-normal: 1.5;
  --lh-relaxed: 1.65;

  --tracking-tight: -0.025em;
  --tracking-normal: 0;
  --tracking-wide: 0.08em;

  /* ---------- SPACING (8px base) ------------------------- */
  --space-1:  4px;
  --space-2:  8px;
  --space-3:  12px;
  --space-4:  16px;
  --space-5:  24px;
  --space-6:  32px;
  --space-7:  48px;
  --space-8:  64px;
  --space-9:  96px;
  --space-10: 128px;
  --space-11: 192px;

  /* ---------- LAYOUT: 80/20 RATIO GRID ------------------- */
  --col-wide: 80fr;
  --col-narrow: 20fr;
  --content-max: 72rem;
  --prose-max: 40rem;

  /* ---------- RADII (the only four; two-tier) -------------
     flat stamps (tags/badges/chips): --radius-1 (2px)
     controls (buttons/nav-cv/fields)
       + cards + content imagery:     --radius-2 (6px)
     modals + hero imagery:           --radius-3 (10px)
     dots / pills:                    --radius-pill          */
  --radius-0: 0px;
  --radius-1: 2px;
  --radius-2: 6px;
  --radius-3: 10px;
  --radius-4: 16px;
  --radius-pill: 999px;

  /* ---------- SHADOWS (warm-tinted) ---------------------- */
  /* Geometry stays fixed; only the COLOUR is themed, via the
     --shadow-* tokens above. box-shadow is not a <color>, so
     light-dark() cannot hold the whole shorthand - it has to sit on
     the colour inside it. */
  --shadow-0: none;
  --shadow-1: 0 1px 2px var(--shadow-a), 0 1px 1px var(--shadow-d);
  --shadow-2: 0 2px 8px var(--shadow-b), 0 1px 2px var(--shadow-a);
  --shadow-3: 0 8px 24px var(--shadow-e), 0 2px 4px var(--shadow-a);
  --shadow-focus: 0 0 0 3px var(--focus-ring); /* amber — was terracotta (RUI-06) */

  /* ---------- MOTION ------------------------------------- */
  --ease-standard: cubic-bezier(0.2, 0.6, 0.2, 1);
  --ease-entry:    cubic-bezier(0, 0, 0.2, 1);
  --ease-exit:     cubic-bezier(0.4, 0, 1, 1);
  --dur-fast: 120ms;
  --dur-med:  220ms;
  --dur-slow: 420ms;
}

/* ============================================================
   THE BAND SCOPE  (dark mode, phase 1)

   Every full-bleed emphasis section on the site. Listing them here
   rather than on each page is the point: a band is a SURFACE, and a
   surface owns its own foreground ladder. Anything inside one that
   asks for --fg-1 gets the band's primary text colour, not the
   page's — in either theme, with no conditional and no second rule.

   That is what makes `color: var(--cream)` (which meant "light text,
   because I happen to know this section is dark") collapse into
   `color: var(--fg-1)` ("the primary text colour here").

   Membership was derived mechanically, not guessed: every rule in
   the codebase setting background to --ink / --bg-inverse, minus the
   max-contrast slabs (.nav-cv, .btn-p, .btn-s:hover, .skip-link:focus,
   .form-submit, a.btn), which invert the OTHER way and take the
   --btn-primary-* tokens instead.

   NOTE — this block deliberately sets no `color` and no `background`.
   The page CSS still does that, and will keep doing it until phase 3
   re-points those declarations at --band-bg / --fg-1. Declaring them
   here now would change the computed colour of band CONTAINERS that
   have no visible text of their own, which is diff noise with no
   rendering benefit.
   ============================================================ */

.band,
footer,
#contact,
.cta-band,
.sd,
.cs-footer-contact {
  --fg-1:            var(--band-fg-1);
  --fg-2:            var(--band-fg-2);
  --fg-3:            var(--band-fg-3);
  --fg-accent:       var(--band-fg-accent);
  --fg-accent-hover: var(--band-fg-accent-hover);
  --rule:            var(--band-rule);
  --rule-strong:     var(--band-rule-strong);
  --bg-surface:      var(--band-bg-2);

  /* A slab inside a band inverts against the BAND, not the page. */
  --btn-primary-bg:  var(--band-fg-1);
  --btn-primary-fg:  var(--band-bg);
}

/* ============================================================
   NON-COLOUR THEME VALUES  (phase 7)

   light-dark() accepts <color> ONLY - not <image>, despite the name
   (CSS.supports('content','light-dark(url(a),url(b))') is false).
   So anything that is not a colour lives here instead. Keeping
   this block SHORT is the point - duplicating the whole palette
   under [data-theme] is exactly what light-dark() avoids.

   The line-art illustrations are NOT re-tinted in dark mode. They
   are referenced as <img src="...svg">, which makes each one an
   isolated document: currentColor resolves against its own initial
   `color: black`, not the host page, so the usual "make the SVG
   inherit" trick is inert. An invert() filter on the <img> was the
   obvious answer and it was tried and dropped - it turns faces and
   hands black, because in this art a face is not a shape, it is the
   page showing through between the hair and an open contour stroke.

   The three page heroes are handled instead by swapping in a
   generated monoline twin - see chrome.css. The nine principle
   drawings on About keep the cream they already sit on in light
   mode, frozen below.
   ============================================================ */
:root {
  /* The ground under the nine principle drawings on About. Deliberately
     NOT themed, and the only surface token in the file that is not: in
     dark mode those drawings keep the exact cream they have in light, so
     the artwork reads identically in both. Themed, it would go near-black
     (--bg-sunken inverts) and take the black strokes with it. */
  --illo-ground: var(--linen-200);
}
