/* ============================================================================
   base.css — the one place the site's design tokens live.

   Written 2026-09-05, as step one of the rebrand. Before this, 90 of 91 pages
   declared their own copy of these values and ~3,470 references pointed at
   names like --black and --white, which cannot describe a light theme. See
   docs/design-tokens.md for the contract and the reasoning.

   Every value here is the value the site already rendered. This file changed
   no pixels; it only stopped the same numbers being written ninety times.

   TWO HALVES:
     1. the semantic contract — the vocabulary new work is written in
     2. legacy aliases — every old name pointing at its new home, so existing
        rules keep working while they are migrated a component at a time

   The aliases are scaffolding. They come out when the last reference does, and
   check-pages will fail the build if a raw colour or font stack reappears in a
   component rule.

   THEME: everything sits on :root and every page is still pinned
   <html data-theme="dark">. When the light palette is authored it takes :root
   and these values move into :root[data-theme="dark"] plus the
   prefers-color-scheme block. Structuring it that way is why the contract
   forbids a component from ever defining a colour inside a theme block.
   ============================================================================ */

/* ── Schibsted Grotesk, self-hosted ───────────────────────────────────────
   Served from our own origin instead of fonts.gstatic.com. Loading it from Google costs four
   SEQUENTIAL steps before a glyph can paint -- DNS + TLS to fonts.googleapis.com, the CSS,
   then DNS + TLS to fonts.gstatic.com, then the font -- and the CSS is only discovered after
   the HTML parser reaches it. Same-origin, preloaded in <head>, it is one request that starts
   at parse time on a connection the browser has already opened.

   font-display:optional is what removes the twitch, and self-hosting is what makes it cheap.
   swap paints a fallback and then swaps to the real face, and Schibsted Grotesk is 6.8% wider
   than system-ui (603.9px against 565.6px measured over the real nav labels) -- so every swap
   shoved the nav 64px sideways. optional gives the font a 100ms block window and NO swap window
   afterwards: either it arrives in time and is used, or this one page view renders in the
   fallback. Both outcomes shift nothing. Same-origin and preloaded, it wins that 100ms on any
   normal connection, and the immutable cache header in vercel.json means every later visit has
   it already.

   The tradeoff is deliberate: a first-time visitor on a slow link sees system-ui for one page
   view. That is a smaller cost than the whole layout jumping on every load.

   A size-adjust fallback keyed to local('Arial') was tried first and REMOVED: local() resolved
   "loaded" while actually handing back system-ui (293.18px where real Arial is 312.59px), so
   the adjustment scaled the wrong font and measured WORSE than no fallback at all -- 40.3px of
   drift against 38.3px. Do not reintroduce it without checking what local() actually returns.

   The files are Schibsted Grotesk v7, SIL Open Font License, which permits self-hosting.
   To refresh: fetch the css2 URL with a Chrome UA, download the woff2 it names, keep the
   unicode-range blocks below in step with it. */
@font-face{
  font-family:'Schibsted Grotesk';
  font-style:normal;
  font-weight:400 800;
  font-display:optional;
  src:url('/assets/fonts/schibsted-grotesk-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:'Schibsted Grotesk';
  font-style:normal;
  font-weight:400 800;
  font-display:optional;
  src:url('/assets/fonts/schibsted-grotesk-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;
}

:root {

  /* ── surfaces ──────────────────────────────────────────────────────────
     Three levels. Every extra step is one more decision per component and one
     more thing to get wrong in the second theme.

     NOTE: --bg is the one genuine clash between the Lab and the rest of the
     site. The Lab renders #0A0A0A, the other 90 pages render #0A0A0A.
     Both are preserved: this is the site value, and pro.css overrides it for
     the Lab. Resolving that is now a one-line decision instead of a hunt. */
  --bg:               #0A0A0A;
  --surface:          #111110;
  --surface-raised:   #161614;
  --surface-sunken:   #1C1C19;

  /* ── ink ───────────────────────────────────────────────────────────────── */
  --text:             #FAFAFA;
  --text-muted:       rgba(245,244,240,0.62);
  --text-faint:       rgba(245,244,240,0.38);

  /* ── division ──────────────────────────────────────────────────────────
     Currently a white alpha, which is dark-only by construction. It becomes a
     real theme-aware colour when light is authored. */
  --border:           rgba(255,255,255,0.07);
  --border-strong:    rgba(255,255,255,0.16);

  /* ── meaning ───────────────────────────────────────────────────────────
     The accent is a ROLE, not a hue. Naming it --gold is how you end up with
     384 edits to change it. */
  --accent:           #C9A84C;
  --accent-ink:       #1A1508;
  --accent-soft:      rgba(201,168,76,0.11);

  /* Status is separate from the accent. --green-light currently does both jobs
     -- brand green AND "better than average" -- which is why it appears 897
     times; these two names split it. */
  --positive:         #5BBF85;
  --positive-soft:    rgba(91,191,133,0.11);
  --negative:         #D94848;
  --negative-soft:    rgba(217,72,72,0.11);
  --warning:          #C9A84C;
  --warning-soft:     rgba(201,168,76,0.09);
  --accent-alt:       #5A8FA8;

  /* ── type ──────────────────────────────────────────────────────────────
     --font-mono is for FIGURES THAT MUST ALIGN IN A COLUMN. It is currently on
     443 selectors of which 85 are numeric; the rest is prose in a data costume
     and is the single biggest reason the site reads as templated. */
  --font-display:     'Cormorant Garamond',Georgia,serif;
  --font-body:        'DM Sans','Helvetica Neue',sans-serif;
  --font-mono:        'Azeret Mono','Courier New',monospace;

  --text-xs:          10px;
  --text-sm:          12px;
  --text-md:          14px;
  --text-lg:          16px;
  --text-xl:          clamp(20px,2.2vw,28px);
  --text-2xl:         clamp(32px,4vw,52px);

  /* ── space, shape, depth, motion ───────────────────────────────────────── */
  --space-1:          4px;
  --space-2:          8px;
  --space-3:          12px;
  --space-4:          16px;
  --space-5:          24px;
  --space-6:          32px;
  --space-7:          48px;
  --space-8:          64px;

  --radius-sm:        6px;
  --radius-md:        10px;
  --radius-lg:        16px;
  --radius-full:      999px;

  --shadow-sm:        0 1px 3px rgba(0,0,0,0.35),0 2px 8px rgba(0,0,0,0.2);
  --shadow-md:        0 4px 16px rgba(0,0,0,0.4),0 1px 3px rgba(0,0,0,0.3);
  --shadow-lg:        0 12px 40px rgba(0,0,0,0.5),0 4px 12px rgba(0,0,0,0.3);

  --ease-out:         cubic-bezier(0.22,1,0.36,1);
  --ease-in-out:      cubic-bezier(0.4,0,0.2,1);
  --dur-fast:         140ms;
  --dur-slow:         320ms;

  /* ── layout ────────────────────────────────────────────────────────────── */
  --nav-h:            64px;
  /* Chrome you look past wants a denser mix than a content surface, and it must stay
     translucent -- --surface is opaque. This is the value the nav already rendered. */
  --nav-bg:           rgba(10,10,10,0.7);
  --sidebar-w:        224px;
  --measure:          68ch;
  --container:        1200px;

  /* ══ LEGACY ALIASES ══════════════════════════════════════════════════════
     Scaffolding. Every name the site currently references, pointing at its new
     home so nothing breaks while rules migrate. Delete each one as its last
     reference goes; the file is done when this block is empty. */

  --black:            var(--bg);
  --black-mid:        var(--surface);
  --black-card:       var(--surface-raised);
  --black-card2:      var(--surface-sunken);
  --white:            var(--text);
  --gold:             var(--accent);
  --green-light:      var(--positive);
  --red:              var(--negative);
  --blue-mid:         var(--accent-alt);
  /* The last alias still holding a retired literal. Every other name here points at a v2
     token; this one kept shipping the old brand green wherever it was used. */
  --green:            var(--accent);

  --display:          var(--font-display);
  --body:             var(--font-body);
  --mono:             var(--font-mono);
  --num:              var(--font-mono);

  --text-micro:       var(--text-xs);
  --text-small:       var(--text-sm);
  --text-body:        var(--text-md);
  --text-h3:          var(--text-lg);
  --text-h2:          var(--text-xl);
  --text-hero:        var(--text-2xl);

  /* Marketing-page names with no equivalent in the Lab palette. They stay as
     literals until the design phase decides whether they survive at all. */
  --graphite:         var(--text-muted);
  --steel:            var(--text-muted);
  --blue:             var(--accent);
  --warm-gray:        var(--surface-sunken);
}

/* ============================================================================
   BRAND v2 — the rebrand system. NOT ON YET.

   Nothing carries data-brand="v2" in production, so this file still renders the
   site exactly as it did. Add the attribute to one page to try it:

       <html data-brand="v2">                 system preference decides the theme
       <html data-brand="v2" data-theme="light">
       <html data-brand="v2" data-theme="dark">

   THEME IS THREE STATES, NOT TWO. An explicit choice stamps data-theme; the
   default "system" setting stamps nothing and is separated only by
   prefers-color-scheme. A colour whose only definition sits inside a
   [data-theme] block never applies in the unstamped state — that is the classic
   unreadable-page bug, and it is why light is defined on the bare selector.

   ACCENT IS A PRESET. Slate is the default; Navy and Azure are one attribute
   away (data-accent="navy"). Switching later is this file, not 3,000 call sites.
   ============================================================================ */

/* ── light: the designed default ─────────────────────────────────────────── */
[data-brand="v2"] {
  --bg:#F5F7F9;  --surface:#FFFFFF;  --surface-raised:#FFFFFF;  --surface-sunken:#EAEEF2;
  --text:#0B1017;  --text-muted:#495260;  --text-faint:#616A79;
  --border:#DFE4EA;  --border-strong:#C2CAD5;

  --accent:#3A5673;  --accent-hi:#54748F;  --accent-ink:#FFFFFF;  --accent-soft:#EAEEF3;
  --nav-bg:rgba(255,255,255,.66);
  /* Glass is its own small palette: a pane needs an edge, a lit top and a shaded underside. */
  --glass:rgba(255,255,255,.34); --glass-edge:rgba(15,25,40,.12);
  --glass-top:rgba(255,255,255,.85); --glass-bot:rgba(15,25,40,.05);
  /* One hue in four steps for the SG categories, and a track that is a division rather than
     a surface -- see the note where the bars are rendered. */
  --cat-1:#2E4C6B; --cat-2:#4E7396; --cat-3:#7BA0C0; --cat-4:#A8BFD6;
  --track:rgba(15,25,40,.10);
  --ink-display:#161D27;
  --positive:#0E6B45;  --positive-soft:#E1F0E9;
  --negative:#A02D23;  --negative-soft:#FAE7E5;
  --warning:#8A5A12;   --warning-soft:#F7EEDF;

  --shadow-sm:0 1px 2px rgba(11,16,23,.04),0 10px 30px -14px rgba(11,16,23,.16);
  --shadow-md:0 1px 3px rgba(11,16,23,.05),0 20px 46px -22px rgba(11,16,23,.22);
  --shadow-lg:0 2px 6px rgba(11,16,23,.05),0 40px 80px -36px rgba(11,16,23,.30);
  --contour:rgba(11,16,23,.26);

  /* Figures are the body face with tabular figures, not a monospace. Mono reads as
     code editor; Stripe and Apple both set numerals this way. */
  --font-display:'Schibsted Grotesk',system-ui,-apple-system,sans-serif;
  --font-body:'Schibsted Grotesk',system-ui,-apple-system,sans-serif;
  --font-fig:'Schibsted Grotesk',system-ui,-apple-system,sans-serif;
  --font-mono:'Schibsted Grotesk',system-ui,-apple-system,sans-serif;
  --fig-track:-.045em;
}

/* ── dark: the same tokens, restated ─────────────────────────────────────── */
@media (prefers-color-scheme: dark) {
  [data-brand="v2"]:not([data-theme="light"]) {
    --bg:#03060A;  --surface:#080D13;  --surface-raised:#0C121A;  --surface-sunken:#010305;
    --text:#EEF2F7;  --text-muted:#8894A3;  --text-faint:#7A8492;
    --border:#141B24;  --border-strong:#232D39;
    --accent:#93AFCC;  --accent-hi:#B4C9DE;  --accent-ink:#0A1119;  --accent-soft:#101821;
    --nav-bg:rgba(9,14,21,.72);
    --glass:rgba(12,18,27,.34); --glass-edge:rgba(160,195,235,.15);
    --glass-top:rgba(190,220,255,.11); --glass-bot:rgba(0,0,0,.30);
    --cat-1:#BCD4EC; --cat-2:#8FB2D4; --cat-3:#6389AE; --cat-4:#456E92;
    --track:rgba(160,195,235,.13);
    --ink-display:#EEF2F7;
    --positive:#3FBE85;  --positive-soft:#082016;
    --negative:#E0796A;  --negative-soft:#23120F;
    --warning:#D7A54B;   --warning-soft:#211A0B;
    --shadow-sm:0 1px 2px rgba(0,0,0,.6),0 12px 34px -16px rgba(0,0,0,.8);
    --shadow-md:0 1px 4px rgba(0,0,0,.6),0 26px 58px -26px rgba(0,0,0,.85);
    --shadow-lg:0 2px 8px rgba(0,0,0,.6),0 50px 100px -44px rgba(0,0,0,.9);
    --contour:rgba(190,215,240,.20);
  }
}
/* Stated again so an explicit choice beats the OS in BOTH directions. */
[data-brand="v2"][data-theme="dark"] {
  --bg:#03060A;  --surface:#080D13;  --surface-raised:#0C121A;  --surface-sunken:#010305;
  --text:#EEF2F7;  --text-muted:#8894A3;  --text-faint:#7A8492;
  --border:#141B24;  --border-strong:#232D39;
  --accent:#93AFCC;  --accent-hi:#B4C9DE;  --accent-ink:#0A1119;  --accent-soft:#101821;
  --nav-bg:rgba(9,14,21,.72);
  --glass:rgba(12,18,27,.34); --glass-edge:rgba(160,195,235,.15);
  --glass-top:rgba(190,220,255,.11); --glass-bot:rgba(0,0,0,.30);
  --cat-1:#BCD4EC; --cat-2:#8FB2D4; --cat-3:#6389AE; --cat-4:#456E92;
  --track:rgba(160,195,235,.13);
  --ink-display:#EEF2F7;
  --positive:#3FBE85;  --positive-soft:#082016;
  --negative:#E0796A;  --negative-soft:#23120F;
  --warning:#D7A54B;   --warning-soft:#211A0B;
  --shadow-sm:0 1px 2px rgba(0,0,0,.6),0 12px 34px -16px rgba(0,0,0,.8);
  --shadow-md:0 1px 4px rgba(0,0,0,.6),0 26px 58px -26px rgba(0,0,0,.85);
  --shadow-lg:0 2px 8px rgba(0,0,0,.6),0 50px 100px -44px rgba(0,0,0,.9);
  --contour:rgba(190,215,240,.20);
}

/* ── the accent, swappable ───────────────────────────────────────────────
   Slate is the default above. These two are the reserved alternatives; each is
   a full set, because the ink that sits on a hue and its fill strength are not
   derivable from the hue. */
[data-brand="v2"][data-accent="navy"]{--accent:#123A6B;--accent-hi:#1F5697;--accent-ink:#FFFFFF;--accent-soft:#E6ECF5;}
[data-brand="v2"][data-accent="azure"]{--accent:#12558C;--accent-hi:#2E80C4;--accent-ink:#FFFFFF;--accent-soft:#E7EFF7;}
@media (prefers-color-scheme: dark) {
  [data-brand="v2"][data-accent="navy"]:not([data-theme="light"]){--accent:#7FB2EA;--accent-hi:#A6CBF4;--accent-ink:#04101E;--accent-soft:#091622;}
  [data-brand="v2"][data-accent="azure"]:not([data-theme="light"]){--accent:#63A9E6;--accent-hi:#8FC4F2;--accent-ink:#04121E;--accent-soft:#0A1926;}
}
[data-brand="v2"][data-accent="navy"][data-theme="dark"]{--accent:#7FB2EA;--accent-hi:#A6CBF4;--accent-ink:#04101E;--accent-soft:#091622;}
[data-brand="v2"][data-accent="azure"][data-theme="dark"]{--accent:#63A9E6;--accent-hi:#8FC4F2;--accent-ink:#04121E;--accent-soft:#0A1926;}

/* FIGURES ARE TWO SETTINGS, NOT ONE.

   Tracking makes numerals feel set rather than typed, and belongs on every figure.
   Tabular is narrower than that: it fixes each digit to one width so decimals line
   up in a column — and in doing so it also selects the tabular COMMA and PERIOD,
   which are as wide as a digit. In a column that is the point. In a headline it
   renders as "126 , 270" and "+0 . 94", which reads as a typo.

   So .fig carries the tracking and .tnum carries the alignment. Reach for .tnum on
   table cells and stacked stat columns; leave it off display numerals and anything
   sitting in a sentence. Applying it on body was the original bug — every comma in
   every paragraph gained a space in front of it. */
[data-brand="v2"] .fig,
[data-brand="v2"] [data-fig] { letter-spacing: var(--fig-track); }
[data-brand="v2"] .tnum,
[data-brand="v2"] [data-tnum] { font-variant-numeric: tabular-nums; }

/* ==== SYNCED FOOTER — canonical chrome, see scripts/sync-chrome.js ==== */
footer{background:var(--black);
  border-top:1px solid var(--border);
  padding:64px 56px 36px;}
.footer-grid{max-width:1120px; margin:0 auto;
  display:grid;
  grid-template-columns:1.5fr 1fr 1fr 1fr;
  gap:44px;}
.f-brand .f-logo{display:flex; align-items:center; gap:10px; margin-bottom:14px;}
.f-brand .f-logo svg{width:20px; height:20px;}
.f-brand .f-logo-text{font-weight:600; font-size:13px; letter-spacing:.1em; color:var(--white);}
.f-brand .f-logo-text span{font-weight:300; opacity:.5;}
.f-brand p{font-size:13px; color:var(--text-muted); line-height:1.65; max-width:240px;}
.f-col h5{font-size:10px; font-weight:600; letter-spacing:.2em;
  text-transform:uppercase; color:var(--text-muted);
  margin-bottom:18px;}
.f-col a{display:block; font-size:13px; color:var(--text-muted); margin-bottom:11px; transition:color .2s;}
.f-col a:hover{color:var(--white);}
.footer-bottom{max-width:1120px; margin:44px auto 0;
  padding-top:24px;
  border-top:1px solid var(--border);
  display:flex; justify-content:space-between;
  font-size:12px; color:var(--text-muted);}
@media(max-width:900px){.footer-grid{grid-template-columns:1fr 1fr;}}
@media(max-width:600px){.footer-grid{grid-template-columns:1fr; gap:28px;}}
.footer-bottom .footer-end{display:flex;align-items:center;gap:22px;}
.theme-toggle{display:inline-flex;align-items:center;gap:9px;background:none;border:0;padding:0;
  cursor:pointer;font:inherit;font-size:12.5px;color:var(--text-faint);
  transition:color .18s;-webkit-tap-highlight-color:transparent;}
.theme-toggle:hover{color:var(--text-muted);}
.theme-toggle:focus-visible{outline:2px solid var(--accent);outline-offset:4px;border-radius:4px;}
.theme-toggle .tt-track{position:relative;width:34px;height:19px;border-radius:99px;
  background:var(--track,var(--border));border:1px solid var(--border-strong);
  transition:background .22s;flex-shrink:0;}
.theme-toggle .tt-knob{position:absolute;top:2px;left:2px;width:13px;height:13px;border-radius:50%;
  background:var(--text-muted);
  /* Composited: the knob slides, the track only changes colour. */
  transition:transform .28s cubic-bezier(.2,.8,.2,1),background .22s;}
.theme-toggle .tt-label{min-width:34px;text-align:left;}
/* ==== /SYNCED FOOTER ==== */

/* ============================================================================
   THE CAPTURE BLOCK — one email surface, used wherever a reader finishes
   something: a research study, an article, a course profile.

   It is deliberately NOT a card with a border on every side. A bordered box at
   the end of a page reads as an advert bolted on; a rule above it and a wash
   behind it reads as the last section of the piece, which is what it is.

   Every colour is a token, so it inverts with the theme and cannot drift.
   ============================================================================ */
.dl-capture{position:relative;margin:56px 0 8px;padding:34px clamp(20px,4vw,38px) 32px;
  border-top:1px solid var(--border-strong);
  background:linear-gradient(168deg,color-mix(in srgb,var(--accent) 6%,transparent) 0%,transparent 62%);}
.dl-cap-eyebrow{display:flex;align-items:center;gap:11px;font-family:var(--mono);font-size:9.5px;
  font-weight:600;letter-spacing:.17em;text-transform:uppercase;color:var(--text-faint);margin:0 0 14px;}
.dl-cap-eyebrow::before{content:"";width:22px;height:1px;background:var(--border-strong);flex-shrink:0;}
.dl-cap-title{margin:0 0 10px;font-family:var(--body);font-size:clamp(22px,2.6vw,29px);font-weight:700;
  line-height:1.12;letter-spacing:-.03em;color:var(--ink-display);text-wrap:balance;}
.dl-cap-sub{margin:0 0 22px;max-width:56ch;font-size:15px;line-height:1.66;color:var(--text-muted);}

.dl-capture form{display:flex;gap:10px;max-width:460px;flex-wrap:wrap;}
/* Hiding the form after a successful signup: an element carrying its own display value
   ignores [hidden] entirely, so this has to be stated. */
.dl-capture form[hidden]{display:none;}
.dl-capture input[type="email"]{flex:1 1 220px;min-width:0;
  background:color-mix(in srgb,var(--text) 6%,transparent);
  border:1px solid var(--border-strong);border-radius:7px;padding:13px 16px;
  font-family:var(--body);font-size:14.5px;color:var(--text);outline:none;
  transition:border-color .2s,background .2s;}
.dl-capture input[type="email"]::placeholder{color:var(--text-faint);}
.dl-capture input[type="email"]:focus{border-color:var(--accent);
  background:color-mix(in srgb,var(--text) 9%,transparent);}
.dl-capture button{background:var(--accent);color:var(--accent-ink);border:0;border-radius:7px;
  padding:13px 24px;font-family:var(--body);font-size:14.5px;font-weight:650;cursor:pointer;
  white-space:nowrap;transition:background .2s,transform .15s;}
.dl-capture button:hover:not(:disabled){background:var(--accent-hi);transform:translateY(-1px);}
.dl-capture button:disabled{opacity:.6;cursor:default;}
.dl-capture button:focus-visible{outline:2px solid var(--accent);outline-offset:3px;}

.dl-cap-note{margin:12px 0 0;font-size:12.5px;color:var(--text-faint);}

/* The status line carries every message, so no page invents its own wording. */
.dl-cap-status{margin:0;min-height:0;font-size:14px;line-height:1.6;color:var(--text-muted);}
.dl-cap-status[data-state="err"]{color:var(--negative);}
.dl-cap-done{margin:0 0 8px;font-size:15.5px;font-weight:650;color:var(--ink-display);}
.dl-cap-more{margin:0 0 18px;max-width:54ch;font-size:14.5px;line-height:1.62;color:var(--text-muted);}
.dl-cap-cta{display:inline-block;background:var(--accent);color:var(--accent-ink);
  border-radius:7px;padding:12px 22px;font-size:14.5px;font-weight:650;text-decoration:none;
  transition:background .2s,transform .15s;}
.dl-cap-cta:hover{background:var(--accent-hi);transform:translateY(-1px);}
.dl-cap-cta:focus-visible{outline:2px solid var(--accent);outline-offset:3px;}

@media (max-width:600px){
  .dl-capture{margin-top:40px;padding:28px 18px 26px;}
  .dl-capture form{flex-direction:column;}
  /* flex-basis becomes a HEIGHT once the row turns into a column, so the 220px basis that
     sizes the field on desktop made it 220px TALL on a phone. */
  .dl-capture input[type="email"]{flex:0 0 auto;width:100%;}
  .dl-capture button{width:100%;}
}

/* ══════════════════════════════════════════════════════════════════════════
   BROWSER CHROME — the details that read as "unfinished" when left alone
   ──────────────────────────────────────────────────────────────────────────
   Ship test rule 7 asks whether selection, caret, focus ring and scrollbar are
   themed or still browser defaults. Audited 2026-09-18: the Lab had themed
   scrollbars and nothing else did, and NOTHING on the site themed selection,
   the caret, or accent-color.

   These are the cheapest possible upgrades and the most visible: a person who
   drags to highlight a sentence on a warm near-black page and gets Chrome's
   default blue has just been told the page was not finished. Everything here
   is token-driven, so it follows the theme rather than pinning a colour.
   ══════════════════════════════════════════════════════════════════════════ */

/* Selection. Accent at low alpha rather than a solid fill: a solid accent
   forces a second ink colour to stay legible on top of it, and the point is to
   mark the text, not to repaint it. */
::selection{ background:color-mix(in srgb, var(--accent) 26%, transparent); color:var(--text); }

/* The caret is a brand surface people stare directly at while typing. */
input, textarea, select, [contenteditable]{ caret-color:var(--accent); }

/* Native controls: checkbox, radio, range and progress all render in the
   browser's own blue unless told otherwise, which is jarring next to gold. */
:root{ accent-color:var(--accent); }

/* iOS Safari inflates text when a phone is rotated unless this is set, which
   silently breaks any layout tuned at a breakpoint. */
/* Hold the scrollbar's space open whether or not there is a scrollbar.
   A vertical scrollbar is ~10px, so centred content sits ~5px further right without one --
   measured on the live homepage, .nav-links left 860.94 -> 866.14 when overflow-y was forced
   hidden. A page that carries a scrollbar early in load and loses it once content settles
   therefore slides visibly rightwards.

   This does NOT show up in CLS: Chrome treats a scrollbar appearing as a viewport change, not
   a layout shift, so the metric reads clean while the page visibly moves. Do not take a good
   CLS number as proof that nothing shifted sideways.

   It was already set in pro.css, which only lab.html and pro.html load. Here it covers all 95
   pages. The cost is a permanently reserved ~10px strip on pages short enough not to scroll,
   which is the accepted trade and what the Lab has been doing all along. */
html{ scrollbar-gutter:stable; }
html{ -webkit-text-size-adjust:100%; text-size-adjust:100%; }

/* Scrollbars, site-wide. pro.css already styled the Lab's; every other page
   was still showing the OS default, so the two halves of the site did not
   match. Firefox takes the standard properties, Chromium the -webkit ones. */
* {
  scrollbar-width:thin;
  scrollbar-color:var(--border-strong) transparent;
}
::-webkit-scrollbar{ width:10px; height:10px; }
::-webkit-scrollbar-track{ background:transparent; }
::-webkit-scrollbar-thumb{
  background:var(--border-strong); border-radius:99px;
  border:3px solid transparent; background-clip:content-box;
}
::-webkit-scrollbar-thumb:hover{ background:var(--text-faint); background-clip:content-box; }
::-webkit-scrollbar-corner{ background:transparent; }

/* List markers inherit body colour by default, which makes a bullet as loud as
   the sentence it introduces. It is punctuation; it should be quieter. */
li::marker{ color:var(--text-faint); }

/* One focus ring, everywhere, and only for keyboard users. A mouse click that
   leaves a ring behind reads as a stuck state. */
:where(a, button, input, select, textarea, [tabindex]):focus-visible{
  outline:2px solid var(--accent);
  outline-offset:2px;
  border-radius:3px;
}

/* Safari renders search inputs as rounded pills with a native clear button
   that cannot be themed; this returns them to ordinary text fields. */
input[type="search"]{ -webkit-appearance:none; appearance:none; }
input[type="search"]::-webkit-search-decoration,
input[type="search"]::-webkit-search-cancel-button{ -webkit-appearance:none; appearance:none; }

/* Chrome paints autofilled inputs a hard pastel yellow that no stylesheet can
   override directly. An inset shadow the size of the field is the only way to
   repaint it, and the long transition stops it flashing through on load. */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus{
  -webkit-text-fill-color:var(--text);
  -webkit-box-shadow:0 0 0 1000px var(--surface-sunken) inset;
  transition:background-color 9999s ease-in-out 0s;
  caret-color:var(--accent);
}

/* A tap on mobile flashes a translucent black box over the element. It is not
   a design decision anyone made, and every control here already has a :active
   or :hover state doing that job properly. */
a, button, [role="button"], .psb-nav-item, .bnav-item{ -webkit-tap-highlight-color:transparent; }

/* Disabled controls should read as unavailable rather than merely faded: a
   greyed button that still shows a pointer invites a click that does nothing. */
button[disabled], input[disabled], select[disabled], textarea[disabled]{ cursor:not-allowed; }

/* Numerals line up everywhere they are compared. Running prose keeps
   proportional figures -- tabular spacing in a sentence puts a full digit width
   around every comma and full stop, which is how a headline ends up reading
   "Drought : Is This". */
/* Only where digits are actually COMPARED, and never on a container that also
   holds sentences: tabular spacing in running text puts a full digit width
   around every comma and full stop. That is how a headline once rendered as
   "Drought : Is This", and applying this to .fx-wrap reproduced it exactly. */
table, [class*="-table"]{ font-variant-numeric:tabular-nums; }
