/* ═══════════════════════════════════════════════════════════════════════════
   BASE — the vocabulary every template shares.
   Names no colour, names no layout. A template = base.css + one theme file
   (colour + type) + one layout file (structure).

   Every number here came out of the research in docs/research/, not taste:
   · 4px base / 8px step, 12 columns, 1200-1280px container, 680px prose (66ch)
     — verified against ONS, GOV.UK and Tailwind v4 design systems
   · type scale clamps all satisfy max/min <= 2.5, because vw does not scale
     under zoom and a wider ratio fails WCAG 1.4.4 at 500%
   · 44px tap targets — WCAG 2.2 AA asks 24x24 (2.5.8); a thumb asks more
   · no dark-mode toggle: a toggle costs a cookie or a script, and the
     no-cookie property is what keeps compliance cheap fleet-wide. So
     prefers-color-scheme only, and only where a theme opts in.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── self-hosted, SIL OFL. No third-party request, by construction. ────────
   Fontshare families (Satoshi, General Sans, Switzer, Cabinet Grotesk) are
   FORBIDDEN here: ITF FFL v2.0 forbids subsetting, format conversion, passing
   files to third parties, and serving through a template editor — which is
   exactly what we are. Verified by reading the shipped FFL.txt. */
@font-face{font-family:Inter;src:url(/fonts/inter-var.woff2)format('woff2');
  font-weight:100 900;font-display:swap;font-style:normal}
@font-face{font-family:Fraunces;src:url(/fonts/fraunces-var.woff2)format('woff2');
  font-weight:100 900;font-display:swap;font-style:normal}
@font-face{font-family:Archivo;src:url(/fonts/archivo-var.woff2)format('woff2');
  font-weight:100 900;font-display:swap;font-style:normal}
@font-face{font-family:'Archivo Narrow';src:url(/fonts/archivo-narrow-var.woff2)format('woff2');
  font-weight:100 900;font-display:swap;font-style:normal}
@font-face{font-family:'IBM Plex Sans';src:url(/fonts/ibm-plex-sans-var.woff2)format('woff2');
  font-weight:100 700;font-display:swap;font-style:normal}
@font-face{font-family:'IBM Plex Mono';src:url(/fonts/ibm-plex-mono-400.woff2)format('woff2');
  font-weight:400;font-display:swap;font-style:normal}
@font-face{font-family:'IBM Plex Mono';src:url(/fonts/ibm-plex-mono-600.woff2)format('woff2');
  font-weight:600;font-display:swap;font-style:normal}

:root{
  /* Space: 4px base, 8px step. Section rhythm deliberately has SIX values,
     because uniform section heights are the loudest "this is a template" tell
     in the whole layout research. */
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:24px; --s6:32px;
  --s7:48px; --s8:64px; --s9:96px; --s10:128px; --s11:160px;

  /* Fluid type. Every clamp below has max/min <= 2.5 — checked, not assumed. */
  --step--1:clamp(0.83rem,0.80rem + 0.15vw,0.94rem);
  --step-0: clamp(1.00rem,0.96rem + 0.20vw,1.13rem);
  --step-1: clamp(1.20rem,1.13rem + 0.35vw,1.44rem);
  --step-2: clamp(1.44rem,1.31rem + 0.65vw,1.84rem);
  --step-3: clamp(1.73rem,1.50rem + 1.15vw,2.36rem);
  --step-4: clamp(2.07rem,1.68rem + 1.95vw,3.01rem);
  --step-5: clamp(2.49rem,1.85rem + 3.20vw,3.85rem);
  --step-6: clamp(2.99rem,1.97rem + 5.10vw,4.93rem);

  --measure:66ch;          /* GOV.UK caps line length at 75 chars; 66 is the target */
  --container:1240px;
  --prose:680px;
  --lead:1.6; --head-lead:1.15; --head-weight:700;
  --radius:10px; --btn-radius:8px;
  --ring:2px;              /* focus ring width — never removed, see below */
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body{margin:0;background:var(--bg);color:var(--body);
  font:400 var(--step-0)/var(--lead) var(--font-body);
  font-synthesis-weight:none;text-rendering:optimizeLegibility}

h1,h2,h3,h4{font-family:var(--font-head);color:var(--ink);margin:0 0 var(--s4);
  line-height:var(--head-lead);font-weight:var(--head-weight);
  letter-spacing:var(--head-track,-0.01em);text-wrap:balance}
p{margin:0 0 var(--s5);max-width:var(--measure)}
a{color:var(--accent-dark)}
img,svg,video{max-width:100%;display:block}
ul,ol{padding-left:1.2em}

/* 67% of the web removes focus outlines, +14 points year on year (Web Almanac
   2025, 17M sites). We do the opposite, visibly, everywhere. */
:focus-visible{outline:var(--ring) solid var(--accent-dark);outline-offset:3px;border-radius:2px}

/* WCAG 2.2 AA 2.5.8 asks 24x24. A thumb asks more, and trades traffic is
   overwhelmingly phones, so every target a finger aims at gets 44px. Links
   inside running prose are exempt on purpose: a 44px line box inside a
   paragraph wrecks the leading for a target nobody taps. */
.btn,nav a,.brand,.tap,
footer a,.util a,li > a{display:inline-flex;align-items:center;min-height:44px}
.btn{justify-content:center;gap:var(--s2);padding:0 var(--s5);
  border-radius:var(--btn-radius);border:1px solid var(--accent);
  background:var(--accent);color:var(--on-accent);text-decoration:none;
  font-weight:600;font-family:var(--font-body);cursor:pointer;
  transition:background .18s ease,border-color .18s ease}
.btn:hover{background:var(--accent-dark);border-color:var(--accent-dark)}
.btn--ghost{background:transparent;color:var(--accent-dark)}
.btn--ghost:hover{background:var(--accent);color:var(--on-accent)}
.btn--lg{min-height:54px;padding:0 var(--s6);font-size:var(--step-1)}

/* The skip link is hidden by CLIPPING, not by being pushed off-screen.
   `left:-9999px` was here until 2026-09-05, and on the first right-to-left page
   we built it created nine thousand pixels of scrollable area: dir="rtl" flips
   which side is "outside", so the element that was safely off the left edge in
   English became a horizontal scrollbar in Arabic. Measured, not guessed —
   documentElement.scrollWidth was 11264 against a 1265px viewport.
   Clipping takes no space in either direction. */
.skip{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);
  white-space:nowrap}
.skip:focus{position:fixed;width:auto;height:auto;overflow:visible;clip-path:none;
  inset-inline-start:var(--s2);top:var(--s2);z-index:99;background:var(--card);
  color:var(--ink);padding:var(--s3) var(--s4);border:var(--ring) solid var(--accent-dark);
  display:inline-flex;align-items:center;min-height:44px}

.wrap{max-width:var(--container);margin-inline:auto;padding-inline:var(--s5)}
.prose{max-width:var(--prose)}
.eyebrow{font-size:var(--step--1);text-transform:uppercase;letter-spacing:.14em;
  color:var(--accent-dark);font-weight:600;margin:0 0 var(--s3)}

/* Wide content scrolls inside its own box; the page body never scrolls
   sideways. A table given a tabindex is reachable by keyboard, which is the
   half most implementations forget. */
.scroller{overflow-x:auto;-webkit-overflow-scrolling:touch}
.scroller:focus-visible{outline:var(--ring) solid var(--accent-dark)}

/* Grain. ~1KB of inline SVG turbulence, and the cheapest premium signal
   available — it is also the visual opposite of AI output, which matters
   because 31% of consumers trust a brand LESS on seeing AI marketing. */
.grain::after{content:'';position:absolute;inset:0;pointer-events:none;opacity:.055;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)'/%3E%3C/svg%3E")}

/* WCAG 2.3.3. Parallax is named in the criterion's own intent as a vestibular
   trigger, so it is banned outright rather than reduced here. */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important;scroll-behavior:auto!important}
}
