/* ============================================================
   FABBRUCCIO: TOKENS (layer 1 of 3)

   SOURCE OF TRUTH
   ---------------
   Every value in section 2 is copied from the FINALIZED design language:
     /home/lb/skills/webdesign/brands/fabbruccio/design-language/tokens.css
   which was itself extracted from the approved build at
     /home/lb/fixSites/fabbruccio-beta2/site.css
   The token NAMES here match that contract exactly, so CSS ports across
   from the static site with no renaming. Do not invent a token: if a value
   is missing, add it to the contract AND here, together.

   LOAD ORDER
   ----------
     1. fab-tokens.css   <- this file. Values only. Paints nothing.
     2. fab-base.css     <- reset, base type, shared primitives
     3. fab-<section>    <- one file per section, conditionally enqueued

   The whole chain depends on the parent handle `instawhew`, which is a
   FILE-LESS ALIAS (instawhew/functions.php:288-290) whose own deps are
   iw-tokens, iw-layout, iw-header, iw-footer, iw-ds and iw-util. Depending
   on the alias rather than on iw-tokens is what puts us after utilities.css,
   the parent's self-described "wins cascade" layer. Depending on iw-tokens
   alone (which this file used to do) put us BEFORE it.

   Never edit the parent (instawhew) for the brand.
   ============================================================ */

/* ============================================================
   ROOT FONT SIZE: RECLAIM IT FROM Automatic.css
   ============================================================
   Automatic.css (the utility framework left over from the Bricks build)
   ships `html { font-size: var(--root-font-size) !important; }` with
   `--root-font-size: 62.5%`, i.e. a 10px root, which is that framework's
   convention for making 1rem equal 10px.

   This theme is authored against a 16px root, so on any site where ACSS
   is active EVERY rem-based size renders at 62.5% of its intended value.
   Measured on www after the cutover: h2 was 17.5px against 28px on
   staging, exactly 28 x 0.625. Body text looked normal only because it is
   set in px, which is what disguised it.

   Fixed by redefining ACSS's OWN variable rather than fighting its
   `!important` with more `!important`. This file loads after ACSS, so the
   later definition wins and ACSS's own declaration then resolves to 100%.

   Do not "simplify" this away while automatic-css is still an active
   plugin. The durable cleanup is to deactivate that plugin, since nothing
   in this theme uses its utilities, but that is a separate decision.
   ------------------------------------------------------------ */
:root {
  --root-font-size: 100%;
}


/* 1. SELF-HOSTED FONTS ---------------------------------------

   THE FAMILY IS A PLACEHOLDER. Hanken Grotesk is the self-hostable
   stand-in for the licensed Suisse Int'l / Basic Commercial class
   neo-grotesque. NOT Inter. NEVER a serif display face. Swapping it
   touches --fab-font-sans below, the `sans` entry in theme.json, and the
   two woff2 files. Nothing else.

   `font-weight: 100 900` is the file's TRUE variable wght axis, verified
   with fontTools against both woff2 binaries (min 100, default 400,
   max 900). Declaring a narrower range is what MANUFACTURES SYNTHETIC
   BOLD: a request outside the declared range still matches this face,
   the axis clamps to the declared maximum, and the browser then fakes
   the remaining weight by smearing the glyphs. Declaring the true range
   removes that mechanism entirely.

   Brand weight is enforced where it belongs instead: theme.json pins all
   six heading levels to 500, and the components below use 400 and 500
   only. There is no 600, no 700 and no 800 anywhere in this system.

   theme.json declares the same two faces with the same range for the
   editor. The two declarations must stay in sync or the browser may pick
   either one. Paths here are relative to this file
   (assets/css/sections/ -> ../../fonts/). */
@font-face {
  font-family: 'Hanken Grotesk';
  src: url('../../fonts/hanken-grotesk-latin.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
                 U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122, U+2191,
                 U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Hanken Grotesk';
  src: url('../../fonts/hanken-grotesk-latin-ext.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
                 U+02DD-02FF, U+1E00-1E9F, U+2020, U+20A0-20AB,
                 U+2C60-2C7F, U+A720-A7FF;
}

/* ============================================================
   2. THE BRAND TOKENS. Contract-exact.
   ============================================================ */

:root {

  /* ---------------------------------------------------------------------
     COLOR. A colorless warm-neutral system. The LEATHER carries the color.
     All chroma comes from full-grain leather photography plus the one
     accent, the boot's own cherry-red lining, used as a MARK only.
     NO GOLD. EVER. See design-language/rules.md, the one-accent-mark rule.
     --------------------------------------------------------------------- */

  /* core palette, mirrors theme.json settings.color.palette 1:1 */
  --fab-ground:            #F6F4EF;  /* warm paper, the page ground            */
  --fab-ground-panel:      #FFFFFF;  /* the only lifted surface, review cards  */
  --fab-stage-grey:        #EDEBE6;  /* the product stage and editorial bands  */
  --fab-ink:               #1C1B1A;  /* warm near-black, all primary type      */
  --fab-ink-secondary:     #8A857D;  /* warm grey, all secondary type          */
  --fab-hairline:          #DEDAD2;  /* 1px rules, the ONLY divider            */
  --fab-accent-oxblood:    #7A1F2B;  /* the brand field accent, MARK ONLY      */
  --fab-accent-cherry:     #9A2233;  /* the literal lining color, swatch only  */

  /* derived accent states, extracted from .cta in the build */
  --fab-accent-pressed:    #68101C;  /* .cta:hover background and border       */
  --fab-accent-ink:        #F6F1EA;  /* type ON the oxblood button. Warmer
                                        than --fab-ground on purpose.          */

  /* photographic and chrome colors. Not palette entries, not for type. */
  --fab-hero-letterbox:    #3B2E25;                /* leather brown behind hero */
  --fab-veil-nav:          rgba(246,244,239,.86);  /* nav once solidified       */
  --fab-veil-buybar:       rgba(246,244,239,.92);  /* docked sticky buy-bar     */
  --fab-veil-hint:         rgba(246,244,239,.70);  /* on-image hint chip        */
  --fab-veil-modal:        rgba(20,17,16,.50);     /* size-guide scrim          */
  --fab-scrim-top:         rgba(24,18,14,.46);     /* hero top gradient stop    */
  --fab-scrim-bottom:      rgba(24,18,14,0);       /* hero bottom gradient stop */
  --fab-swatch-ring:       rgba(0,0,0,.12);        /* inset ring on the swatch  */

  /* ---------------------------------------------------------------------
     TYPE. ONE neo-grotesque for everything: nav, headings, body, price,
     legal. Minimal hierarchy. Emphasis comes from position and whitespace,
     not from scale or weight. Weights 400 and 500 only.
     --------------------------------------------------------------------- */

  --fab-font-sans: "Hanken Grotesk", system-ui, -apple-system, "Segoe UI",
                   Roboto, Helvetica, Arial, sans-serif;
  --fab-weight-regular: 400;
  --fab-weight-medium:  500;   /* the only emphasis weight. No 600, no 700. */

  /* size scale. Tiny working sizes. Fixed rem for UI, clamp for headings. */
  --fab-size-micro:     .62rem;   /* on-image hint chip                     */
  --fab-size-label:     .66rem;   /* eyebrow, option row, footer heads      */
  --fab-size-caption:   .72rem;   /* breadcrumb, more-link, count, filters  */
  --fab-size-small:     .78rem;   /* nav links, figcaption, buy-bar size    */
  --fab-size-detail:    .82rem;   /* card meta, lining, returns, tables     */
  --fab-size-compact:   .86rem;   /* spec body, size buttons, CTA, inputs   */
  --fab-size-body:      .9375rem; /* body as built. 15px at the 16px root.
                                     WAS LITERALLY 15px. Identical here, but
                                     px does not participate in the desktop
                                     tier at the foot of this file, and body
                                     copy sitting still while everything
                                     around it grew was the one thing that
                                     tier could not afford. Keep it in rem. */
  --fab-size-lede:      .95rem;   /* section intro paragraphs               */
  --fab-size-prose:     .98rem;   /* long-form storytelling paragraphs      */
  --fab-size-quote:     1.06rem;  /* review pull quote                      */
  --fab-size-product:   1.32rem;  /* product NAME and PRICE, same size      */
  --fab-size-heading-s: clamp(1.3rem,2.3vw,1.75rem);   /* section h2        */
  --fab-size-heading-m: clamp(1.4rem,2.6vw,1.9rem);    /* spread h2         */
  --fab-size-heading-l: clamp(1.5rem,2.9vw,2.05rem);   /* page h1           */
  --fab-size-statement: clamp(1.55rem,3vw,2.15rem);    /* the thesis line,
                                                          largest in system */

  /* leading */
  --fab-leading-body:      1.62;
  --fab-leading-prose:     1.72;
  --fab-leading-editorial: 1.65;
  --fab-leading-spec:      1.60;
  --fab-leading-compact:   1.50;
  --fab-leading-lining:    1.45;
  --fab-leading-assure:    1.35;
  --fab-leading-heading:   1.14;
  --fab-leading-product:   1.10;

  /* tracking. Negative on headings, open on the uppercase micro-labels. */
  --fab-track-body:            .005em;
  --fab-track-nav:             .01em;
  --fab-track-cta:             .02em;
  --fab-track-caption:         .05em;
  --fab-track-link-underline:  .06em;
  --fab-track-upper-tight:     .1em;   /* table head                        */
  --fab-track-upper-news:      .12em;  /* newsletter submit                 */
  --fab-track-upper:           .14em;  /* the default uppercase tracking    */
  --fab-track-upper-wide:      .16em;  /* footer heads, review attribution  */
  --fab-track-eyebrow:         .2em;   /* the eyebrow, the widest           */
  --fab-track-heading-s:      -.01em;
  --fab-track-heading-m:      -.015em;
  --fab-track-heading-l:      -.018em;

  /* measure. Text columns are capped in ch, never in px. */
  --fab-measure-tight:  30ch;  /* footer newsletter blurb                   */
  --fab-measure-prose:  40ch;  /* spread body, editorial caption line       */
  --fab-measure-hero:   44ch;  /* hero footer line                          */
  --fab-measure-intro:  46ch;  /* section intro, spec accordion body        */
  --fab-measure-wide:   52ch;  /* page header intro, newsletter, size note  */

  /* ---------------------------------------------------------------------
     SPACE. Airy and unhurried. Fixed px inside components, fluid clamps
     for the section rhythm. The pacing device is whitespace and one
     photograph at a time, never a band of color.
     --------------------------------------------------------------------- */

  --fab-space-xxs:  2px;    /* hairline nudge under a meta line             */
  --fab-space-xs:   8px;    /* inline gap, table cell padding               */
  --fab-space-sm:  12px;    /* gallery gap, swatch gap, size grid           */
  --fab-space-md:  16px;    /* block gap, heading to body                   */
  --fab-space-lg:  20px;    /* component padding, group top padding         */
  --fab-space-xl:  26px;    /* group separation, nav link gap               */
  --fab-space-xxl: 32px;    /* footer column gap                            */

  --fab-gutter:   clamp(20px,5vw,68px);   /* the page gutter                */
  --fab-band-sm:  clamp(38px,5vw,62px);   /* quiet band, newsletter         */
  --fab-band-md:  clamp(56px,8vw,104px);  /* the default section band       */
  --fab-band-lg:  clamp(64px,10vw,132px); /* storytelling band              */

  /* ---------------------------------------------------------------------
     LAYOUT
     --------------------------------------------------------------------- */

  --fab-wrap:        1360px;  /* the one container in the built system      */
  --fab-wrap-narrow: 1040px;  /* the reviews grid, the only narrower one    */
  --fab-nav-height:  62px;
  --fab-stage-aspect: 4 / 3;  /* product stage. Matches the source shots.   */
  --fab-portrait-max: 560px;  /* editorial portrait cap on the grey stage   */

  /* ---------------------------------------------------------------------
     SURFACE. Frameless. No elevation, no drop shadow, no card chrome.
     Hairline rules are the only dividers. Sharp corners everywhere.
     --------------------------------------------------------------------- */

  --fab-radius:        0;      /* everything is square    */
  --fab-radius-round:  50%;    /* the lining swatch ONLY  */
  --fab-shadow:        none;   /* there is no shadow      */
  --fab-hairline-width: 1px;
  --fab-rule:          1px solid var(--fab-hairline);
  --fab-rule-ink:      1px solid var(--fab-ink);   /* active or focused edge */

  /* ---------------------------------------------------------------------
     MOTION. Constants only. The techniques live in
     library/animations/catalog.json and are REFERENCED, never bound into
     a template or a block. See design-language/motion.md.
     --------------------------------------------------------------------- */

  --fab-ease:                  cubic-bezier(0,0,.2,1); /* the house curve   */
  --fab-reveal-distance:       22px;
  --fab-reveal-duration:       .6s;
  --fab-reveal-stagger:        70ms;
  --fab-nav-solidify-duration: .4s;
  --fab-swap-duration:         .5s;   /* PDP gallery hero cell              */
  --fab-swap-duration-card:    .45s;  /* product card                       */
  --fab-buybar-duration:       .35s;
  --fab-hover-duration:        .25s;  /* opacity and color hovers           */
  --fab-press-duration:        .35s;  /* press logo greyscale to color      */
  --fab-blur-chrome:  blur(14px) saturate(1.1);
  --fab-blur-chip:    blur(4px);
  --fab-blur-modal:   blur(3px);
}

/* =========================================================================
   REDUCED MOTION. Global, as built. Any section that adds motion inherits
   this and must not re-enable itself inside the query. The hard cut-off
   selectors live in fab-base.css; this only collapses the constants.
   ========================================================================= */
@media (prefers-reduced-motion: reduce) {
  :root {
    --fab-reveal-duration: .001ms;
    --fab-reveal-stagger: 0ms;
    --fab-nav-solidify-duration: .001ms;
    --fab-swap-duration: .001ms;
    --fab-swap-duration-card: .001ms;
    --fab-buybar-duration: .001ms;
  }
}

/* ============================================================
   3. LEGACY TOKEN ALIASES

   The pre-beta2 visual layer named its tokens differently and had a very
   different palette: a gold accent, a Playfair serif display face, a
   1440px measure, dark "island" bands. Those names are still referenced
   by the section files this pass does NOT own (cart, contact, search,
   404, minicart, calf, ticker, campaign, compare).

   Deleting the names would leave those routes painting with invalid
   colours. So each one is re-pointed at its nearest contract token here.
   That is deliberately more than a compatibility shim: it is how the two
   banned design decisions are killed EVERYWHERE at once rather than only
   on the three routes this pass rebuilt.

     --fab-gold* / --fab-gold-lift  ->  ink-secondary and hairline.
                                        NO GOLD. It is the AI-luxury tell
                                        this brand was built against, and
                                        an alias is the only way to remove
                                        it from files this pass does not
                                        rewrite.
     --fab-serif                    ->  the sans stack. There is no serif
                                        display face in this system.
     --fab-display-weight           ->  500. Was 500 already; restated so
                                        an alias cannot resurrect 700.

   When a section is rebuilt to beta2 it should stop reading these and use
   the contract names. When the last consumer is gone, delete this block.
   ============================================================ */
:root {
  /* surfaces */
  --fab-bg:        var(--fab-ground);
  --fab-bg-2:      var(--fab-stage-grey);
  --fab-bg-3:      var(--fab-hairline);
  --fab-ink-2:     var(--fab-ink-secondary);
  --fab-ink-3:     var(--fab-ink-secondary);

  /* the banned accents, neutralised */
  --fab-gold:      var(--fab-ink-secondary);
  --fab-gold-2:    var(--fab-ink-secondary);
  --fab-gold-lift: var(--fab-hairline);

  /* wine was the old name for the oxblood mark */
  --fab-wine:      var(--fab-accent-oxblood);
  --fab-wine-2:    var(--fab-accent-cherry);

  /* the old dark island. There are no dark bands in the beta2 system;
     these resolve to ink-on-paper so an unrebuilt band stays legible. */
  --fab-dark:      var(--fab-ink);
  --fab-on-dark:   var(--fab-ground);
  --fab-on-dark-2: var(--fab-hairline);

  /* rules */
  --fab-line:      var(--fab-hairline);
  --fab-line-2:    var(--fab-hairline);

  /* measure + gutter. The old names, the new values. */
  --fab-gut:       var(--fab-gutter);

  /* type stacks. The serif is gone; both aliases are the one sans. */
  --fab-serif:     var(--fab-font-sans);
  --fab-sans:      var(--fab-font-sans);

  /* motion */
  --fab-speed:     var(--fab-hover-duration);

  /* the old fluid display scale, snapped onto the contract scale. The
     old --fab-display-1 was clamp(3rem,7.4vw,7.4rem): a 118px headline
     in a system whose largest type is 34px. It is aliased DOWN. */
  --fab-display-1: var(--fab-size-statement);
  --fab-display-2: var(--fab-size-heading-s);
  --fab-display-weight:     var(--fab-weight-medium);
  --fab-tracking-display:   var(--fab-track-heading-l);
  --fab-tracking-display-2: var(--fab-track-heading-m);
  --fab-leading-display:    var(--fab-leading-heading);
  --fab-leading-display-2:  var(--fab-leading-heading);

  /* eyebrow */
  --fab-eyebrow-size:     var(--fab-size-label);
  --fab-eyebrow-tracking: var(--fab-track-eyebrow);
  --fab-eyebrow-weight:   var(--fab-weight-medium);

  /* button */
  --fab-btn-size:     var(--fab-size-compact);
  --fab-btn-tracking: var(--fab-track-cta);
  --fab-btn-pad-y:    17px;
  --fab-btn-pad-x:    17px;
  --fab-btn-radius:   var(--fab-radius);
  --fab-btn-gap:      var(--fab-space-xs);

  /* section rhythm */
  --fab-sec-pad:  var(--fab-band-md);
  --fab-sec-gap:  var(--fab-band-sm);

  /* nav height. fab-pdp.css and fab-minicart.css read --fab-nav-h; the
     contract name is --fab-nav-height. Aliased so the two cannot drift. */
  --fab-nav-h:    var(--fab-nav-height);
}

/* ============================================================
   4. SEMANTIC PARENT-TOKEN OVERRIDES

   instawhew paints from its own neutral semantic tokens
   (instawhew/assets/css/tokens.css). Re-point those at the Fabbruccio
   palette so any inherited parent chrome picks up the brand without us
   restyling it component by component. Token NAMES must match the
   parent's exactly; the VALUES are ours.

   Fabbruccio is light-first and has no dark mode, so :root and
   [data-theme=light] carry the same values, and [data-theme=dark] is
   deliberately given the same values too: the parent ships a no-flash
   script (instawhew/functions.php:405) that will set data-theme=dark from
   a stale localStorage key or an OS preference, and there is no dark
   Fabbruccio to switch to. Without the third selector a returning visitor
   with that key set would get instawhew's dark surfaces under our type.
   ============================================================ */
:root,
[data-theme="light"],
[data-theme="dark"] {
  --page-bg:     var(--fab-ground);
  --surface:     var(--fab-ground-panel);
  --surface-2:   var(--fab-stage-grey);
  --surface-3:   var(--fab-hairline);
  --text-1:      var(--fab-ink);
  --text-2:      var(--fab-ink-secondary);
  --text-3:      var(--fab-ink-secondary);
  --line:        var(--fab-hairline);
  --line-subtle: var(--fab-hairline);

  /* Type stacks the parent's base rules read. Both point at the one sans:
     the parent's --font-heading used to be the Playfair serif. */
  --font:         var(--fab-font-sans);
  --font-heading: var(--fab-font-sans);

  /* Frameless. The parent aliases theme.json's shadow presets into these;
     the presets are already `none`, and this is the belt to that braces. */
  --shadow-xs: none;
  --shadow-sm: none;
  --shadow-md: none;
  --shadow-lg: none;
  --shadow-xl: none;

  /* Radius 0 everywhere. The lining swatch is the single exception and it
     sets border-radius directly, not through a token. */
  --radius-sm:   0;
  --radius-md:   0;
  --radius-lg:   0;
  --radius-xl:   0;
  --radius-2xl:  0;
  --radius-full: 9999px;  /* left round: the parent uses it for pills we
                             do not render, and zeroing it would make any
                             future round affordance impossible to spot. */

  /* THE SITE GUTTER. This is the one parent token whose value is
     load-bearing for us, because instawhew/assets/css/layout.css:65 pays
     it to .wp-site-blocks as padding-inline, and --fab-chrome-bleed
     (section 5) is valued FROM it. Setting it to the brand gutter is what
     makes the bleed exact: a band escapes precisely the padding that is
     really there, at every viewport width. */
  --gutter: var(--fab-gutter);
}

/* ============================================================
   5. CHROME BLEED

   The full-bleed escape hatch: how much a band must pull back by to reach
   the real page edge.

   Scoped to .wp-site-blocks on purpose, and this is the whole trick: the
   bleed is switched on ONLY inside the wrapper that actually pays the
   gutter back as padding, and it is valued FROM that same token.

     FSE path      inside .wp-site-blocks -> bleed = var(--gutter)
                   -> a band escapes exactly the padding that is there
     classic path  no .wp-site-blocks     -> the var() fallback (0px)
                   -> no escape, because there is nothing to escape

   instawhew is a HYBRID theme. Classic PHP templates (our front-page.php,
   page-contact.php, search.php) render chrome straight into <body> with no
   .wp-site-blocks wrapper at all, while FSE routes (/shop/, the PDP, cart,
   404) get the wrapper from wp-includes/template-canvas.php. An
   UNCONDITIONAL negative margin is what put the footer at left:-32 /
   right:1472 on a 1440 viewport. Consumers must always read this with the
   0px fallback: var(--fab-chrome-bleed, 0px).

   It is deliberately NOT 100vw. 100vw includes the scrollbar's width, so
   a 100vw band overflows by ~15px on any desktop with a visible scrollbar,
   and that overflow is then silently swallowed by the parent's
   body{overflow-x:hidden}. 100vw IS BANNED in this theme.

   Custom properties inherit, so a consumer picks this up at any depth
   inside the wrapper. Definition, not decoration, so it lives in layer 1.
   ============================================================ */
.wp-site-blocks { --fab-chrome-bleed: var(--gutter, 0px); }


/* ============================================================
   LAYER 1b. THE DESKTOP TYPE TIER (>= 1024px)
   ============================================================
   THE PROBLEM. The built scale is a phone scale wearing a desktop layout.
   Measured on live at 1440: body 15px, section h2 28px, the largest thing
   on the front page 34.4px, nav links 12.48px. Those are not a regression,
   they are beta2's own numbers to the decimal, verified by rendering
   fabbruccio-beta2/ side by side with www and comparing the character
   weighted size distribution: same root, same body, same largest headline,
   means within 0.6px. The agreed design was simply never given a desktop
   step, so a 1440 viewport reads a 390 type scale across a 1360px wrap.

   WHY THIS IS DONE AT THE ROOT AND NOT TOKEN BY TOKEN. Only 101 of the 207
   font-size declarations in this theme read a --fab-size-* token. The other
   106 are literal rem values in fab-cart, fab-minicart, fab-compare,
   fab-footer and friends. Redefining the tokens alone would have stepped up
   slightly under half the type on the site and left the rest where it was,
   which is worse than not doing it: a half-scaled page is a broken page,
   where an evenly small one is merely small.

   Raising the root scales every rem in the theme, both kinds, with one
   declaration and no per-component edits.

   WHAT MAKES THAT SAFE HERE, AND IT WOULD NOT BE SAFE IN MOST THEMES:
   THIS THEME'S TYPE IS ALL rem AND ITS SPACE IS ALL px. Checked before
   writing this: 0 padding/margin/gap declarations use rem, 299 use px, and
   every layout token is px (--fab-wrap 1360px, --fab-nav-height 62px, the
   whole --fab-space-* ladder, --fab-gutter's clamp). So the root moves type
   and ONLY type. The wrap does not widen, the gutters do not open up, the
   nav does not get taller, nothing reflows except the text itself. That
   separation is what earns the shortcut, so if space ever moves to rem this
   block has to be revisited on the same day.

   IT GOES THROUGH --root-font-size ON PURPOSE. See the note at the head of
   this file: Automatic.css owns `html { font-size: var(--root-font-size)
   !important; }`, so redefining its variable is the only way to move the
   root without an !important war. The `html` rule below is the same value
   for the day ACSS is finally deactivated and its !important declaration
   goes with it. Two paths, one number, so they cannot disagree.

   1024px, not 900px, and not a fluid ramp: 900 is where the mobile nav
   hands over, and stepping type at exactly that breakpoint would have made
   one change look like two. Everything below 1024 is untouched, which keeps
   the 390 half of the 07-31 audit valid.

   THE HEADINGS GET MORE THAN THE 10%. Body needed a nudge and the display
   line needed a promotion, so the four heading clamps have their MAX raised
   past what the root alone would give. Their vw terms are unchanged except
   on --fab-size-statement, where 3vw could not reach the new cap at 1440
   and would have quietly held the headline 0.8px short of it.

   Resulting sizes at 1440, root 17.6px:

     body         15    -> 16.5    section h2   28   -> 32
     lede         15.2  -> 16.7    spread h2    30.4 -> 35.2
     prose        15.68 -> 17.2    page h1      32.8 -> 40
     product      21.12 -> 24      statement    34.4 -> 44
     nav links    12.48 -> 13.7    footer links 14.4 -> 15.8
   ------------------------------------------------------------ */
@media (min-width: 1024px) {

  :root {
    --root-font-size: 110%;

    /* Past the uniform 10%, for heading weight the root cannot give. */
    --fab-size-product:   1.3636rem;                      /* 24    */
    --fab-size-heading-s: clamp(1.3rem,2.3vw,1.8182rem);  /* 32    */
    --fab-size-heading-m: clamp(1.4rem,2.6vw,2rem);       /* 35.2  */
    --fab-size-heading-l: clamp(1.5rem,2.9vw,2.2727rem);  /* 40    */
    --fab-size-statement: clamp(1.55rem,3.2vw,2.5rem);    /* 44    */
  }

  /* Not a duplicate of ACSS's rule, a replacement for the day it is gone.
     While ACSS is active its !important wins and reads the same variable,
     so the computed root is 110% either way. */
  html { font-size: var(--root-font-size); }
}
