/* ═════════════════════════════════════════════════════════════════════
   EthosOne 2.0 — canonical design tokens
   The single source for the website and for Storybook. The prototype
   links this file; .storybook/preview.ts imports it. Nothing else
   defines a colour, a size, a radius, a shadow or a duration.

   Merged 8 September 2026 from two systems that had drifted apart:
     · ethosone-storybook/src/tokens/index.css — the Figma-generated
       primitives (space, radius, shadow, the 25→950 ramps, semantics)
     · prototypes/v4.3-merged.html :root — the fluid display ladder,
       the section rhythm, the domain accents and the motion set

   Two rulings are load-bearing here:
     1. Inter, at 400/500/600. Not Barlow.
     2. --h1 is the ceiling. Nothing that is not an H1 renders larger.
   ═════════════════════════════════════════════════════════════════════ */

:root {

  /* ═══ TYPEFACE ═══════════════════════════════════════════════════ */

  --font-sans: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI",
               Roboto, Helvetica, Arial, sans-serif;
  --font-mono: ui-monospace, Menlo, "SF Mono", "Fira Code", Consolas, monospace;
  --font-features: "cv11", "ss01";

  --fw-regular:  400;
  --fw-medium:   500;   /* the workhorse: 64 of 89 weighted declarations */
  --fw-semibold: 600;


  /* ═══ TYPE RAMP ══════════════════════════════════════════════════
     Strictly descending from --h1. The hero H1 is the largest type on
     any page in the site; every step below it is smaller at every
     viewport. Adding a size above --h1 is a defect, not a style.

     39 hardcoded sizes collapsed into these 13 steps.               */

  /* fluid, viewport-responsive — headings only */
  --h1:            clamp(29px, 2.8vw, 42px);   /* THE CEILING. Hero, once per page */
  --h1-ls:         -.03em;
  --h1-lh:         1.1;

  --display-lg:    clamp(26px, 2.5vw, 38px);   /* was max 54px, and was outgrowing --h1 */
  --display-lg-ls: -.036em;
  --display-lg-lh: 1.1;

  --h2:            clamp(23px, 2.2vw, 34px);   /* was max 37px */
  --h2-ls:         -.028em;

  --display:       clamp(22px, 2.0vw, 30px);   /* was max 38px; 2.2vw tied it to --h2 */
  --display-ls:    -.03em;
  --display-lh:    1.12;

  --casc:          clamp(17px, 1.35vw, 21px);  /* the R cascade */

  /* The four large steps shrink with the viewport, because a stat or a
     sub-head that stays at 26px while --display drops to 22px on a phone
     outranks the heading above it. The four small steps now step down too,
     tablet then mobile, at the same 900/560 breakpoints --pad already uses
     — see the RESPONSIVE block below. 16px is the desktop/laptop reference,
     not a floor: a paragraph reads narrower on a small screen, so it does
     not need to hold the same absolute size as it does on a wide one. */
  --fs-3xl: clamp(21px,   1.9vw, 26px);
  --fs-2xl: clamp(19px,   1.7vw, 22px);   /* absorbs 25 */
  --fs-xl:  clamp(17.5px, 1.5vw, 20px);   /* absorbs 19.5, 21 — the old --h3 */
  --fs-lg:  clamp(16.5px, 1.3vw, 18px);   /* absorbs 17.5, 18, 18.5 */

  --fs-3xs: 11px;   /* micro: ring labels, table tags, the 9.5-11.5px cluster */

  --fs-md:  16px;   /* body; absorbs 16, 16.5 */
  --fs-sm:  14px;   /* absorbs 13.5, 14.2, 14.5 — interactive text */
  --fs-xs:  13px;   /* absorbs 12.5, 12.6, 13, 13.4 — static meta */
  --fs-2xs: 12px;   /* absorbs 12, 12.2 — captions, legal */

  /* 24 line-heights → 5 */
  --lh-tight:   1.1;    /* display */
  --lh-snug:    1.25;   /* headings */
  --lh-normal:  1.45;   /* dense UI */
  --lh-relaxed: 1.55;   /* body */
  --lh-loose:   1.7;    /* long prose */

  /* 23 letter-spacings → 5 */
  --ls-display: -.034em;
  --ls-tight:   -.02em;
  --ls-normal:  -.01em;
  --ls-none:    0;
  --ls-caps:    .08em;  /* uppercase labels only */


  /* ═══ SPACE — 4px grid ═══════════════════════════════════════════ */

  --space-0-5: 2px;   --space-1:   4px;   --space-1-5: 6px;
  --space-2:   8px;   --space-2-5: 10px;  --space-3:   12px;
  --space-3-5: 14px;  --space-4:   16px;  --space-5:   20px;
  --space-6:   24px;  --space-7:   28px;  --space-8:   32px;
  --space-9:   36px;  --space-10:  40px;  --space-11:  44px;
  --space-12:  48px;  --space-14:  56px;  --space-16:  64px;
  --space-20:  80px;  --space-24:  96px;


  /* ═══ LAYOUT ═════════════════════════════════════════════════════
     --w and --pad scale continuously above 1400px rather than through
     five discrete tiers at 1600/1920/2400/3200/4600.                */

  --w:     min(1392px, 92vw);
  --pad:   58px;
  --nav:   66px;
  --ask-w: 580px;

  /* section rhythm — tightened one step to cut scroll depth */
  --sec:       80px;   /* was 96 */
  --sec-tight: 56px;   /* was 66 */
  --sec-sm:    44px;   /* was 52 */
  --sec-lead:  36px;   /* was 44 */

  --gap-card: var(--space-7);   /* 28px, between floating cards */
  --gap-list: var(--space-4);   /* 16px, within a list */
  /* the three near-identical fluid gaps the file had grown, as one token */
  --gap-fluid: clamp(30px, 5vw, 80px);


  /* ═══ RADIUS ═════════════════════════════════════════════════════
     27 distinct radii collapsed to these.                           */

  --radius-none: 0;
  --radius-xs:   2px;
  --radius-sm:   4px;
  --radius-md:   6px;
  --radius-lg:   8px;
  --radius-xl:   12px;
  --radius-2xl:  16px;
  --radius-3xl:  24px;
  --radius-full: 9999px;

  /* the chat bubble: an iMessage corner, with the tail corner tightened */
  --radius-bubble:      20px;
  --radius-bubble-tail: 6px;


  /* ═══ SHADOW ═════════════════════════════════════════════════════
     32 one-off shadow strings collapsed to these.                   */

  --shadow-xs:  0 1px 2px rgba(16,24,40,.05);
  --shadow-sm:  0 1px 2px rgba(16,24,40,.06), 0 1px 3px rgba(16,24,40,.10);
  --shadow-md:  0 2px 4px rgba(16,24,40,.06), 0 4px 8px rgba(16,24,40,.10);
  --shadow-lg:  0 4px 6px rgba(16,24,40,.05), 0 10px 15px rgba(16,24,40,.10);
  --shadow-xl:  0 8px 10px rgba(16,24,40,.04), 0 20px 25px rgba(16,24,40,.10);
  --shadow-2xl: 0 24px 48px rgba(16,24,40,.18);
  /* The site's own idiom: a navy-tinted lift with negative spread, so the
     shadow reads as depth under a floating surface rather than as a blur
     around it. Thirty-two one-off strings resolved to these four steps. */
  --lift-sm: 0 10px 24px -18px rgba(47,60,86,.36);
  --lift-md: 0 18px 40px -24px rgba(47,60,86,.40);
  --lift-lg: 0 30px 62px -30px rgba(47,60,86,.34);
  --lift-xl: 0 40px 90px -30px rgba(47,60,86,.45), 0 12px 30px -14px rgba(47,60,86,.24);

  /* the same, over dark bands and photography */
  --lift-dark-sm: 0 8px 20px -12px rgba(0,0,0,.42);
  --lift-dark:    0 14px 30px -13px rgba(0,0,0,.52);
  --lift-dark-lg: 0 34px 64px -36px rgba(0,0,0,.6);
  --inset-top:    inset 0 1px 0 rgba(255,255,255,.35);

  /* gold does not cast a shadow, it glows */
  --glow-gold:    0 14px 34px -14px rgba(237,196,153,.55);
  --glow-gold-lg: 0 20px 44px -16px rgba(237,196,153,.65);

  /* selection and focus rings */
  --ring-gold:    0 0 0 3px rgba(217,167,106,.18);
  --ring-pai:     0 0 0 3px rgba(217,70,239,.18);
  --ring-success: 0 0 0 3px rgba(20,107,58,.16);
  --shadow-focus:       0 0 0 4px rgba(47,60,86,.24), 0 1px 2px rgba(16,24,40,.05);
  --shadow-focus-brand: 0 0 0 4px rgba(255,255,255,.12), 0 1px 2px rgba(16,24,40,.05);


  /* ═══ COLOUR — primitives ════════════════════════════════════════ */

  --color-base-white: #ffffff;
  --color-base-black: #000000;

  /* brand */
  --color-ethos-luminousSand: #EDC499;
  --color-ethos-dawnGlow:     #F6E2C2;
  --color-ethos-busOrange:    #FA9819;
  --color-ethos-oceanBlue:    #0089D4;   /* EthosOne bright blue */
  --color-ethos-boardGrey:    #F1F2F3;
  --color-ethos-etherealMist: #F4F6FC;
  --color-ethos-chalkWhite:   #FCFCFC;
  --color-ethos-borderGrey:   #CBCBCB;

  /* navy */
  --color-primary-25:  #f7f8fa;  --color-primary-50:  #f0f2f5;
  --color-primary-100: #e4e8ee;  --color-primary-200: #d2d9e3;
  --color-primary-300: #b8c4d4;  --color-primary-400: #7d90a8;
  --color-primary-500: #526480;  --color-primary-600: #2f3c56;
  --color-primary-700: #243044;  --color-primary-800: #192333;
  --color-primary-900: #101722;  --color-primary-950: #0a0f17;

  /* gray, light mode */
  --color-gray-lm-25:  #fdfdfd;  --color-gray-lm-50:  #fafafa;
  --color-gray-lm-100: #f5f5f5;  --color-gray-lm-200: #f4f6fc;
  --color-gray-lm-300: #d5d7da;  --color-gray-lm-400: #a4a7ae;
  --color-gray-lm-500: #717680;  --color-gray-lm-600: #535862;
  --color-gray-lm-700: #414651;  --color-gray-lm-800: #252b37;
  --color-gray-lm-900: #181d27;  --color-gray-lm-950: #0a0d12;

  /* gray, dark mode */
  --color-gray-dm-25:  #fafafa;  --color-gray-dm-50:  #f7f7f7;
  --color-gray-dm-100: #f0f0f1;  --color-gray-dm-200: #f4f6fc;
  --color-gray-dm-300: #cecfd2;  --color-gray-dm-400: #94979c;
  --color-gray-dm-500: #85888e;  --color-gray-dm-600: #61656c;
  --color-gray-dm-700: #373a41;  --color-gray-dm-800: #22262f;
  --color-gray-dm-900: #13161b;  --color-gray-dm-950: #0c0e12;

  /* status */
  --color-error-25:  #fffbfa;  --color-error-50:  #fef3f2;
  --color-error-100: #ffe4e4;  --color-error-200: #ffcbc9;
  --color-error-300: #ff9a95;  --color-error-400: #f97066;
  --color-error-500: #ff6259;  --color-error-600: #ff3b30;
  --color-error-700: #cc2f26;  --color-error-800: #a3261e;
  --color-error-900: #681813;  --color-error-950: #55160c;

  --color-warning-25:  #fffcf5;  --color-warning-50:  #fffaeb;
  --color-warning-100: #ffedd5;  --color-warning-200: #ffe4bd;
  --color-warning-300: #ffd497;  --color-warning-400: #ffbb5c;
  --color-warning-500: #f79009;  --color-warning-600: #dc6803;
  --color-warning-700: #b54708;  --color-warning-800: #93370d;
  --color-warning-900: #7a2e0e;  --color-warning-950: #4e1d09;

  --color-success-25:  #f6fef9;  --color-success-50:  #ecfdf3;
  --color-success-100: #dcfae6;  --color-success-200: #abefc4;
  --color-success-300: #75e0a7;  --color-success-400: #47cd89;
  --color-success-500: #17b26a;  --color-success-600: #079455;
  --color-success-700: #067647;  --color-success-800: #085d3a;
  --color-success-900: #074d31;  --color-success-950: #053321;


  /* ═══ COLOUR — semantic aliases ══════════════════════════════════ */

  --color-text-primary:     var(--color-primary-600);
  --color-text-secondary:   var(--color-gray-lm-700);
  --color-text-tertiary:    var(--color-gray-lm-600);
  --color-text-quaternary:  var(--color-gray-lm-500);
  --color-text-white:       var(--color-base-white);
  --color-text-placeholder: var(--color-gray-lm-500);
  --color-text-error:       var(--color-error-700);
  --color-text-warning:     var(--color-warning-600);
  --color-text-success:     var(--color-success-700);

  --color-border-primary:   var(--color-gray-lm-300);
  --color-border-secondary: var(--color-gray-lm-200);
  --color-border-brand:     var(--color-primary-500);

  --color-bg-primary:   var(--color-base-white);
  --color-bg-secondary: var(--color-primary-25);
  --color-bg-tertiary:  var(--color-primary-50);
  --color-bg-brand:     var(--color-primary-600);
  --color-bg-error:     var(--color-error-50);
  --color-bg-warning:   var(--color-warning-50);
  --color-bg-success:   var(--color-success-50);


  /* ═══ COLOUR — the site's working surface names ══════════════════
     Short aliases the page CSS actually writes. They resolve to the
     ramps above, so there is still one source per value.           */

  --bg:    #ffffff;
  --bg-2:  #F7F8FB;
  --bg-3:  #EDF0F6;
  --panel: #F4F5F9;              /* was repeated raw in five places */
  --fg:    var(--color-primary-600);
  --fg-2:  #5A6378;
  --fg-3:  #656C7D;
  --line:  #E4E7EF;
  --line-2:#D3D8E4;

  /* the dark ramp, anchored on ethosone.io's navy rather than near-black */
  --dk:      #202B42;  --dk-2:      #26324B;
  --dk-3:    #2F3C56;  --dk-4:      #3B4A68;
  --dk-hover:#3A496A;
  --dk-fg:   #F3F5FB;  --dk-fg-2:   #C7CFE0;  --dk-fg-3: #98A3BC;
  --dk-line: #364360;  --dk-line-2: #46577A;
  --dk-rgb:  32,43,66;
  --mist: #f3f5fb;               /* ethereal mist: proof band, card hover, callout cards */
  --card-pad: var(--space-6);
  --card-radius: var(--radius-2xl);
  --blue-lt: #8fb4ff;

  --gold:    var(--color-ethos-luminousSand);
  --gold-2:  #D9A76A;
  --gold-lt: #F5E1C1;
  --gold-ink:#8F5729;
  /* --gold-ink is 5.89:1 on white and 5.27:1 on --gold-bg, so it reads
     everywhere it is used as text on a light panel. On the gold fill itself
     it is 3.64:1, and the gold button carries a 14px label, so the primary
     call to action was the one place on the site failing AA. Same hue, taken
     far enough down to clear 4.5:1 on --gold. Fill labels only.
     (Visual pass, 21 September 2026.) */
  --gold-ink-deep:#7A4A21;
  --gold-bg: #FAF1E5;

  /* ── PolicyAI, the machine's colour ─────────────────────────────────
     The three stops are the app's (src/components/ai/tokens.ts) and 1.0's
     hero-visual. The gradient means "a machine produced this": it wears the
     PolicyAI wordmark and the product's own surfaces, and it appears on the
     rest of the site only as a strip, a hairline, a bloom or an orb. Never a
     button fill, never body text, never chrome. Ruling §9, 12 September 2026. */
  --pai-1: #7C3AED;  --pai-2: #D946EF;  --pai-3: #F97316;
  --pai-strip:      linear-gradient(90deg, var(--pai-1), var(--pai-2), var(--pai-3));
  --pai-icon:       linear-gradient(135deg, var(--pai-1) 0%, var(--pai-2) 100%);
  --pai-icon-ready: linear-gradient(135deg, rgba(124,58,237,.10) 0%, rgba(249,115,22,.10) 100%);
  --pai-text:       linear-gradient(90deg, var(--pai-1) 0%, var(--pai-2) 50%, var(--pai-3) 100%);
  --pai-aurora:     radial-gradient(120% 80% at 0% 0%, rgba(124,58,237,.15) 0%, transparent 55%), radial-gradient(120% 80% at 100% 100%, rgba(249,115,22,.13) 0%, transparent 55%);
  --pai-bloom:      radial-gradient(ellipse 70% 60% at 50% 45%, rgba(124,58,237,.35) 0%, rgba(217,70,239,.20) 40%, transparent 72%);
  --pai-tint:       linear-gradient(180deg, #faf5ff 0%, #ffffff 60%);
  --pai-line:       rgba(124,58,237,.18);
  /* The one deliberate departure from the ruling above (14 September 2026):
     the mega menu's PolicyAI tile carries the gradient as a chrome fill, so
     the machine-made module reads as such at a glance rather than as one
     more outlined card. The display stops cannot carry it: white text scores
     3.46:1 on --pai-2 and 2.80:1 on --pai-3, both failures. These are the
     deep end of the same violet -> fuchsia -> orange ramp, picked so white
     clears 4.5:1 on every stop and every point between them. Fill only;
     the ruling still holds everywhere else. */
  --pai-1-deep: #5B21B6;  --pai-2-deep: #A21CAF;  --pai-3-deep: #9A3412;
  /* The mirror of the deep stops. --pai-1-deep and friends exist so white
     can sit ON the ramp; these exist so the ramp can sit on the navy, which
     is the other way a brand colour meets a dark surface and fails.

     Measured against --dk: --pai-1 is 2.48:1, --pai-2 4.09:1, --pai-3
     5.04:1. So a gradient drawn through text on the navy is legible at its
     orange end and close to invisible at its violet one, which is what the
     homepage's PolicyAI stat numerals were doing at 22px. These three are
     the light end of the same violet -> fuchsia -> orange ramp, each one
     over 5:1 on --dk. Text and pills on dark only; --pai-strip is still the
     ramp everywhere it is a strip, a hairline or a fill.
     (Visual pass, 22 September 2026. --pai-2-lt dates from the 21st, for
     the pills, and is unchanged.) */
  --pai-1-lt: #A78BFA;  --pai-2-lt: #E879F9;  --pai-3-lt: #FB923C;
  --pai-text-lt: linear-gradient(90deg, var(--pai-1-lt) 0%, var(--pai-2-lt) 50%, var(--pai-3-lt) 100%);
  --pai-fill:       linear-gradient(100deg, var(--pai-1-deep) 0%, var(--pai-2-deep) 52%, var(--pai-3-deep) 100%);
  --pai-fill-hover: linear-gradient(100deg,
                      color-mix(in srgb, var(--pai-1-deep) 88%, #fff) 0%,
                      color-mix(in srgb, var(--pai-2-deep) 88%, #fff) 52%,
                      color-mix(in srgb, var(--pai-3-deep) 88%, #fff) 100%);
  /* The mirror of the ramp above, for text ON a dark ground (22 September
     2026). --pai-text starts at #7C3AED, which is 2.53:1 on the navy and
     unreadable at small sizes; these are the light end of the same violet ->
     fuchsia -> orange ramp, each stop clearing 4.5:1 on --dk so the whole
     sweep passes AA. Text on dark only. */
  --pai-1-lift: #A78BFA;  --pai-2-lift: #E879F9;  --pai-3-lift: #FB923C;
  --pai-text-dk:    linear-gradient(90deg, var(--pai-1-lift) 0%, var(--pai-2-lift) 50%, var(--pai-3-lift) 100%);
  --glow-pai:       0 0 0 6px rgba(124,58,237,.18), 0 12px 28px -8px rgba(217,70,239,.35);
  --glow-pai-warm:  0 0 0 5px rgba(249,115,22,.12), 0 10px 24px -10px rgba(167,139,250,.40);
  --glow-orb:       0 0 40px 12px rgba(124,58,237,.28), 0 0 90px 30px rgba(217,70,239,.12);
  --lift-pai:       0 24px 48px -28px rgba(124,58,237,.35), 0 8px 24px -12px rgba(47,60,86,.12);
  --t-bloom: 1.2s;  --t-wash: .9s;  --t-settle: .6s;  --t-march: 2.4s;  --t-breathe: 7s;
  --ease-breath: cubic-bezier(.45, 0, .55, 1);
  /* AI Governance is a school subject, not a machine: navy and gold carry it,
     with one restrained gradient accent per band. */
  --aig-hairline: linear-gradient(90deg, transparent, rgba(124,58,237,.55), rgba(249,115,22,.55), transparent);
  /* third-party marks, used only on the monogram tiles of the connectivity band */
  --mark-word: #185ABD; --mark-outlook: #0F6CBD; --mark-google: #34A853; --mark-sso: #6264A7;
  --mark-tass: #C8102E; --mark-seqta: #00A6A6; --mark-xero: #13B5EA; --mark-pdf: #B30B00;
  --blue:  var(--color-ethos-oceanBlue);
  /* Ocean blue is the brand's, and it is a fill and a focus ring: 3.80:1 on
     white, which clears the 3:1 a control needs and fails the 4.5:1 a
     sentence needs. Every inline link on the site was wearing it. This is
     the same hue taken to the ink end, 5.85:1 on white and 5.37:1 on
     --mist, and it is what text uses; --blue keeps the chrome. It is the
     value --d-data-ink already resolved to, so the ramp is unchanged.
     (Visual pass, 21 September 2026.) */
  --blue-ink: #0069A8;
  --cloud: #F3F5FB;  --stone: #D8D5CA;  --orange: #FFB067;

  /* answer domains: the rail and tag colour of a turn, by what it is about.
     -ink values are all >=4.8:1 on white and on their own 9% tint. */
  --d-risk:   #F97316;  --d-risk-ink:   #A64B12;
  --d-policy: #7C3AED;  --d-policy-ink: #6D28D9;
  --d-price:  #D9A76A;
  --d-data:   #0089D4;  --d-data-ink:   #0069A8;
  --d-assure: #6E9B7A;  --d-assure-ink: #2F6B52;
  --d-core:   #8B93A6;  --d-core-ink:   #5A6378;
  --ph: #6E7689;

  /* status chips, which had been living outside the palette */
  --chip-bad-bg:  #fdecec;  --chip-bad-fg:  #a32b1f;
  --chip-good-bg: #e7f6ee;  --chip-good-fg: #146b3a;
  --chip-warn-bg: #fff3e0;  --chip-warn-fg: #8a5a12;

  /* the agent terminal panel in the hero */
  --term-bg:    #1A2233;  --term-inset: #131A28;
  --term-line:  #38445F;  --term-fg:    #C3CBDA;

  /* macOS window chrome, used by the fake app shells */
  --mac-red: #ff5f57;  --mac-amber: #febc2e;  --mac-green: #28c840;

  /* the product's own ground, sampled from the real captures. The build
     spec names #f7f8fa; the app actually renders this warm family. */
  --app-bg:    #F4F3EE;  --app-inset: #EEECE4;
  --app-inset-2:#ECE9E0; --app-line:  #E5E2DA;

  /* semantic label ink: reassigned once per theme, so every eyebrow,
     column heading and caption follows the surface it sits on */
  --label-fg: var(--fg-2);


  /* ═══ MOTION ═════════════════════════════════════════════════════ */

  --ease:     cubic-bezier(.22, 1, .36, 1);
  --t-fast:   .2s;
  --t:        .35s;
  --t-slow:   .55s;
  --t-reveal: .8s;
}


/* ═══ RESPONSIVE ═══════════════════════════════════════════════════
   Four numeric breakpoints, down from 25. Everything above 1400px is
   continuous rather than tiered, so a 5K display is interpolated
   rather than jumped to.                                            */

@media (max-width: 900px) {
  :root {
    --pad: 24px;
    /* body text steps down a half-tier on tablet, so a paragraph set at a
       narrower measure doesn't hold the same absolute size as it does on
       a wide desktop line. */
    --fs-md:  15px;
    --fs-sm:  13.5px;
    --fs-xs:  12.5px;
    --fs-2xs: 11.5px;
    --fs-3xs: 10.5px;
  }
}
/* the gutter keeps shrinking below 560 rather than stepping again at 400:
   16px on a 360px phone, 20px by 560px, with nothing in between to tune */
@media (max-width: 560px) {
  :root {
    --pad: clamp(16px, 4.5vw, 20px);
    --sec: 56px; --sec-tight: 40px;
    /* and a second, smaller step on the phone */
    --fs-md:  14.5px;
    --fs-sm:  13px;
    --fs-xs:  12px;
    /* The bottom two rungs come up half a step each. 10px was the phone's
       floor and the footer's ASBA disclaimer sat on it on all 163 pages, as
       did the capture captions, the kickers and the resource dates: on a
       390px screen that is a squint rather than a size. Both move together
       so the ladder keeps its rung, and --fs-xs above is unchanged, so the
       descent the ceiling gate checks is the same shape it was.
       (Visual pass, 21 September 2026.) */
    --fs-2xs: 11.5px;
    --fs-3xs: 11px;
  }
}

@media (min-width: 1400px) {
  :root {
    --w:      clamp(1392px, 74vw, 3100px);
    --pad:    clamp(58px, 3.1vw, 120px);
    --nav:    clamp(66px, 2.4vw, 104px);
    /* 20vw doesn't clear its own 580px floor until ~2900px and hits its
       760px ceiling by ~3800px, so the homepage's search field (the
       prototype's .ask, prototypes/v4.3-merged.html) sat flat across the
       whole 1440p-6K range while the hero column around it (.hero .center,
       clamp(760px,33vw,1360px)) kept growing — the field visibly stopped
       filling its own column. Raised rate and cap so it keeps growing
       through the same range, staying comfortably inside the hero column
       at every width (614px in an 845px column at 2560, 922px in a 1267px
       column at 3840, capping at 1160px against the column's 1360px cap
       at 6016). */
    --ask-w:  clamp(580px, 24vw, 1160px);

    /* The ladder keeps its rate and only raises its cap, so the step from
       the base range into this one is continuous — no jump at 1400px —
       and the descent from --h1 holds at every width up to 5K.
       Ordering at 2720px, where most caps bind:
         h1 76 · display-lg 68 · h2 60 · display 54 · casc 37 · 3xl 25   */
    --h1:         clamp(39.2px, 2.8vw, 76px);
    --display-lg: clamp(35px,   2.5vw, 68px);
    --h2:         clamp(30.8px, 2.2vw, 60px);
    --display:    clamp(28px,   2.0vw, 54px);
    --casc:       clamp(18.9px, 1.35vw, 38px);

    /* A plain vw rate cannot grow these: the floor holds until rate*vw
       overtakes it, so 16px body text would sit flat until about 2900px
       while the H1 climbed past 70. Interpolating from the breakpoint
       itself makes every step start moving at 1400 and land on its cap
       at ~5150, which is what keeps the page in proportion on a 5K panel. */
    --fs-3xl: clamp(26px, calc(26px + (100vw - 1400px) * 0.004267), 42px);
    --fs-2xl: clamp(22px, calc(22px + (100vw - 1400px) * 0.003733), 36px);
    --fs-xl:  clamp(20px, calc(20px + (100vw - 1400px) * 0.0032),   32px);
    --fs-lg:  clamp(18px, calc(18px + (100vw - 1400px) * 0.002667), 28px);
    --fs-md:  clamp(16px, calc(16px + (100vw - 1400px) * 0.0024),   25px);
    --fs-sm:  clamp(14px, calc(14px + (100vw - 1400px) * 0.001867), 21px);
    --fs-xs:  clamp(13px, calc(13px + (100vw - 1400px) * 0.0016),   19px);
    --fs-2xs: clamp(12px, calc(12px + (100vw - 1400px) * 0.001333), 17px);
    --fs-3xs: clamp(11px, calc(11px + (100vw - 1400px) * 0.001067), 15px);
  }
}
