/* ==========================================================================
   base-v3.css - OWNED BY CALL INSIGHTS V3. Nothing else loads this file.

   A full copy of base.css taken at the 8/21 fork, not an override layer.

   Brees, 8/21: "every version should have its own CSS because one of those
   versions is going to be the main." That is the whole rationale: the version
   that wins gets shipped as DE's real page, and a page that ships should not
   be wired into two pages that were rejected. V3 can therefore be edited
   freely - there is no shared selector to break, and no pin to keep complete.

   Scope: tokens, global type, the focus ring.

   RED FLAG - THIS IS THE COPY DECISION THIS PROJECT ONCE REVERSED. V2 was
   first built as a 3,600-line duplicate of direction-d.css and that duplicate
   was DELETED, because two copies mean a fix to one page silently misses the
   other. The risk did not go away; it was accepted on purpose, and it is
   bounded because two of these three pages get deleted. What replaces the old
   protection is scripts/css-divergence.js: it records the parent's hash at
   fork time and tells you when base.css has changed since, so a shared fix that
   missed V3 is visible instead of silent. RUN IT BEFORE ANY RELEASE.
   ========================================================================== */

/* ==========================================================================
   Vet Call Insights — base.css
   Shared foundation ONLY: tokens, reset, font declarations, typography
   primitives, focus states, reduced-motion handling, screen-reader utilities.

   This file deliberately contains NO page layout. Section composition,
   grid structure, and colour weighting live in the per-direction stylesheets.
   If you find yourself adding a .section or .hero rule here, it belongs in
   direction-a/b/c.css instead.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. TOKENS
   Every colour, size, space, radius and motion value used anywhere on the
   page is declared here. No hardcoded hex or px spacing below this block.
   -------------------------------------------------------------------------- */

:root {
  /* -- Colour ------------------------------------------------------------ */
  --ink: #2f2f35;
  --oat: #f3eee8;
  --petal: #ffaeda;
  --lime: #d2db75;
  --sky: #c6e2ee;
  --indigo: #4c4e68;
  --clay: #e16126;
  --marigold: #ff8c1a;
  --white: #ffffff;

  /* Brand tints — the soft end of each hue, lifted verbatim from the DE
     design-system bundle's own token file (`--de-*-soft` / `--de-oat-deep`).
     These are not invented: they are the values the brand's homepage uses for
     large quiet fields, which is exactly what the colour variants need when
     a full-strength petal or lime section would shout.

     They live here rather than in a variant stylesheet because verify.js
     requires every colour to be a token — a hex literal in a direction file
     is a stray-hex failure, and rightly so. Declaring them centrally does NOT
     make them shared design: which variant uses which, and where, is still
     entirely a per-variant decision. */
  --petal-soft: #ffe1f1;
  --lime-soft: #edf0ce;
  --sky-soft: #e4f1f7;

  /* --marigold-soft — ADDED 8/14. The palette had soft tints for petal, lime
     and sky but never for marigold or clay.

     🔴 IT IS NOT MIXED AT THE SAME RATIO AS THE OTHERS, ON PURPOSE. The
     existing tints are ~52–63% toward white. This one is 45%, tuned to
     LUMINANCE rather than to the family's mix ratio:

         sky  0.550  ·  lime  0.655  ·  marigold (full) 0.400  ·  THIS 0.595

     Full-strength marigold is not merely louder than sky and lime, it is
     markedly DARKER, so a card using it never sits in the same family as the
     other two however the hues are arranged. At 0.595 it lands between them
     and the three read as one set by weight.

     Ink on it is 8.30:1, so it carries body copy comfortably.

     ⚠️ Adding a token is safe — nothing else references it — but this is
     base.css, shared by twelve directions. Do not retune an EXISTING token
     here to solve a one-page problem. */
  --marigold-soft: #ffc081;
  --oat-deep: #e7dfd4;

  /* --- DEEP TIER — the brand accents as TEXT ------------------------------
     The brand's accents are pastels. They are beautiful as fills and as
     decorative dots, and they are unusable as text: measured on white, petal
     is 1.70:1, lime 1.49:1, marigold 2.33:1, sky 1.35:1. The floor for large
     text is 3:1.

     The DE homepage mockup ships exactly this defect — its 01/02/03 numerals
     are set in raw petal/lime/marigold on white. `_mockup-reference/devices.md`
     records it as a defect to fix on the way in, not a pattern to inherit.

     These are the same hues at the same saturation, dropped in lightness only,
     until each clears 3:1 on BOTH grounds the page uses (white and oat). So
     the "each number is a different colour" effect survives intact — it is the
     same pink, green and orange, one step richer.

         petal-deep     3.47 on white   3.01 on oat
         lime-deep      3.48            3.02
         marigold-deep  3.52            3.05
         sky-deep       3.47            3.00
         clay-deep      3.51            3.04

     🔴 These are for text at >= 24px ONLY. Below that the floor is 4.5:1 and
     none of them clear it. Small coloured text needs --ink-muted instead.
     Decorative dots and fills keep the ORIGINAL pastels — a dot beside a text
     label carries no information on its own and has no contrast burden. */
  --petal-deep: #ff299d;
  --lime-deep: #869025;

  /* --lime-ink — ADDED 9/17 for the Perspectives broadsheet. The *-deep tier above is tuned as a MARK colour:
     --lime-deep measures 3.02 on oat, which clears the 3:1 graphic floor and the large-text floor, and fails
     ordinary text. The broadsheet sets its kickers and dates in the lime family at 11-12px, so it needs a tier
     that clears 4.5:1 as body text:
         --lime-ink   5.59 on oat   6.45 on white   — same hue family, darkened until small type passes
     Use it ONLY for small type in the lime family on a light ground. Fields, underline bands and duotone
     grounds stay --lime; marks at display size may stay --lime-deep. */
  --lime-ink: #5c631b;

  /* --sky-ink / --petal-ink / --marigold-ink — ADDED 9/17, the same job as --lime-ink for the other three hues.
     Perspectives colours each category, and a category label is 11–15px type: the pastels are 1.35–2.33 on white
     and the *-deep tier is ~3.5, so neither can carry small text. These are darkened until small type passes on
     the darker of the two grounds this site uses:
         --sky-ink       6.09 on oat   7.02 on white
         --petal-ink     6.13 on oat   7.08 on white
         --marigold-ink  5.94 on oat   6.86 on white
     Small type in that hue family only. Fields, dots, duotone grounds and underline bands stay on the pastels. */
  --sky-ink: #1f5f7d;
  --petal-ink: #a32069;
  --marigold-ink: #8a4a06;

  /* 🔴 A SECOND, QUIETER PINK, ADDED 8/31 FOR LARGE DISPLAY FIGURES.
     The *-deep set above exists to make the pastels legible, and it does —
     but --petal-deep is tuned as a DOT and border colour, and at 36px it
     reads neon. Brees, on seeing the Google Ads ROI ratio in it: "i dont
     think that was the right pink."
     This is petal's own hue (327deg) with saturation pulled back to 48%:
         --petal      1.70 on white   invisible as text
         --petal-deep 3.47            legible, large-text only, reads neon
         --petal-muted 6.33           clears the 4.5 BODY floor
     ⚠️ IT DOES NOT REPLACE --petal-deep. That token is still correct for the
     dots and borders it already colours; this one is for type. */
  --petal-muted: #ab2b72;

  /* 🔴 A SECOND, QUIETER PINK, ADDED 8/31 FOR LARGE DISPLAY FIGURES.
     The *-deep set above exists to make the pastels legible, and it does —
     but --petal-deep is tuned as a DOT and border colour, and at 36px it
     reads neon. Brees, on seeing the Google Ads ROI ratio in it: "i dont
     think that was the right pink."
     This is petal's own hue (327deg) with saturation pulled back to 48%:
         --petal      1.70 on white   invisible as text
         --petal-deep 3.47            legible, large-text only, reads neon
         --petal-muted 6.33           clears the 4.5 BODY floor
     ⚠️ IT DOES NOT REPLACE --petal-deep. That token is still correct for the
     dots and borders it already colours; this one is for type. */
  --petal-muted: #ab2b72;

  /* 🔴 A SECOND, QUIETER PINK, ADDED 8/31 FOR LARGE DISPLAY FIGURES.
     The *-deep set above exists to make the pastels legible, and it does —
     but --petal-deep is tuned as a DOT and border colour, and at 36px it
     reads neon. Brees, on seeing the Google Ads ROI ratio in it: "i dont
     think that was the right pink."
     This is petal's own hue (327deg) with saturation pulled back to 48%:
         --petal      1.70 on white   invisible as text
         --petal-deep 3.47            legible, large-text only, reads neon
         --petal-muted 6.33           clears the 4.5 BODY floor
     ⚠️ IT DOES NOT REPLACE --petal-deep. That token is still correct for the
     dots and borders it already colours; this one is for type. */
  --petal-muted: #ab2b72;
  --marigold-deep: #d66b00;
  --sky-deep: #3893bb;
  --clay-deep: #e16228;

  /* Derived alphas. Declared once so no rule invents its own rgba().
     The three low values are hairlines and borders — never text. */
  --ink-08: rgba(47, 47, 53, 0.08);
  --ink-10: rgba(47, 47, 53, 0.1);
  --ink-12: rgba(47, 47, 53, 0.12);

  /* --- secondary text -----------------------------------------------------
     ONE muted value, not two, and it is 72% rather than the brief's 55%.

     The brief specifies "ink at 55%" for eyebrows and used 65% for other
     secondary copy. Measured against the real backgrounds, 55% lands at
     3.18:1 and 65% at 4.15:1 — both below the 4.5:1 AA floor for normal
     text, and a rendered sweep found 114 failing elements across the three
     directions because of these two tokens alone.

     72% measures 5.05:1 on oat and 5.4:1 on white, so it clears AA with
     margin at every size we use it.

     There is no second, lighter tier: any value light enough to read as
     distinct from this one fails. Secondary text earns its hierarchy from
     size, weight, letter-spacing and uppercasing instead — which is the
     house position anyway, that emphasis comes from type rather than from
     washing contrast out. */
  --ink-muted: rgba(47, 47, 53, 0.72);

  /* Oat on the dark fills, all verified: 7.2:1 on ink, 4.8:1 on indigo,
     and 5.2:1 for the 60% footer bottom bar on ink. */
  --oat-14: rgba(243, 238, 232, 0.14);
  --oat-60: rgba(243, 238, 232, 0.6);
  --oat-75: rgba(243, 238, 232, 0.75);

  /* THE FAKE TEMPLATE — homepage hero card only (home-hero.css .sh__tpl*, 9/15).
     Deliberately OFF-brand: flat greys and a stock blue, so the generic
     "theme #04" site the card wipes away reads as a template, not as DE. They
     live here, in the token sheet, because verify.js rightly fails any hex in a
     page sheet — the hero CSS moved into assets/ when it became the homepage.
     Greys were darkened from Brees' comp so the template's words still measure
     AA on white. Never use these anywhere else. */
  --tpl-url: #5d5d63;
  --tpl-text: #56606b;
  --tpl-link: #626b75;
  --tpl-btn: #46699c;
  --tpl-mark: #c6ccd3;
  --tpl-line: #e6e8eb;
  --tpl-fill: #edeff2;
  --tpl-fill-2: #dde1e6;
  --tpl-dot: #8a8a90;   /* the caption pill's "template" dot; home-hero.js swaps it for lime-deep */

  /* The routing line, taken from the brand guide's Infographic and Line
     Pattern assets. The line itself is a quiet warm neutral — in the real
     artwork ALL of the colour lives in the dots sitting on it, never in the
     stroke. Getting this backwards is what made the first connector read
     louder than the brand actually is. */
  /* The connector's and the linework's shared stroke. Added 8/19 when V2's
     timeline spine needed it: the value already lived in THREE places
     (direction-d.js, linework-a.svg, linework-b.svg) and nowhere as a token,
     so a fourth literal would have been the point it drifted. Measured 1.40:1
     on petal, 2.07:1 on oat, 5.56:1 on indigo - over the 1.35 decorative
     floor on every ground the line crosses. */
  /* V3 SECTION 2-3 TRACK. The one line changes colour where the ground does:
     light over the indigo problem section, ink over the oat how section. Both
     are the brand tokens at an alpha, not new colours - Brees, 8/21, chose
     "snap to brand tokens" over adopting the canvas mock's softened palette,
     so nothing here introduces a hue the system did not already have.

     rgba() rather than hex so the stray-hex rule reads them as what they are:
     an opacity on an existing token, not a twenty-second colour. */
  --v3-track-on-indigo: rgba(243, 238, 232, 0.45);
  --v3-track-on-oat: rgba(47, 47, 53, 0.28);

  /* -- The PRODUCT's own UI palette ---------------------------------------
     🔴 THESE ARE NOT BRAND COLOURS AND MUST NEVER BE USED AS ONE. They exist
     so the render of a Vet Call Insights card can look like the product a
     client will actually receive — Brees, 8/24: "I want it to be exactly like
     the screenshot. Clients need to see what they'll actually see." Sampled
     from three product screenshots in Alie's Drive folder. Nothing outside
     `.callback--real` may reference them.

     ⚠️ FOUR OF THE SIX ARE ONE STEP DARKER THAN THE PRODUCT SHIPS, AND THAT
     IS NOT A TASTE EDIT. Measured against the product's own values:

         white on green-500  #22C55E   2.28:1   the primary button
         white on indigo-500 #6366F1   4.47:1   the secondary button
         red-500  #EF4444 on the card  3.50:1   the flag line
         indigo-500 on the card        4.16:1   phone number and links

     All four are under the 4.5 floor, so reproducing them literally would put
     four known WCAG failures on DE's own marketing site. Each moved to the
     nearest passing shade of the SAME hue — green-700, indigo-600, red-700 —
     which reads as the same design at a glance and measures 5.02, 6.29, 6.02
     and 5.85. The two that already passed (the muted label, the declined
     button) are the product's values untouched.
     📌 This is worth knowing about the PRODUCT, not just the page: those four
     pairs fail in the real emails too. */
  /* 🔁 9/16 (later) — THE RENDERS WEAR DE'S COLOURS. Brees: "Without changing the layout, content or format of the VCI
     renders - can we change the color to match the DE branding", brand colours for the red and green too. Every
     value below is a brand token or its nearest AA-passing shade (measured, ink/indigo/oat family):
         purple -> indigo #4c4e68 (white on it 8.09)   near-black -> ink #2f2f35      greys -> oat #f3eee8
         red "missed/hung up" -> deep petal #b8175f (6.31 on white, 5.47 on oat)   green deltas -> dark lime #5c6318 (6.46)
         green money -> indigo (8.09)   mint pill -> lime-soft #edf0ce (dark lime on it 5.52)   amber -> dark marigold (5.62)
         green "I Called Back" button -> lime with INK text (8.95; renders-v3.css flips the label colour)
     The history below records the product's original values and why they were darkened on 8/xx. */
  --vci-card: #faf8f5;
  --vci-panel: #ffffff;
  --vci-ink: #2f2f35;
  --vci-label: #5f5f66;
  --vci-indigo: #4c4e68;
  --vci-green: #d2db75;
  --vci-red: #b8175f;
  --vci-grey: #f3eee8;
  --vci-grey-ink: #5f5f66;
  --vci-band: #f3eee8;
  --vci-head: #2f2f35;
  --vci-muted: #66666d;
  /* green-700, where the recap ships green-500 (#22C55E): the "+8 vs last
     week" deltas are 11px, and green-500 on white measures 2.22:1. Same hue,
     5.02:1. The recap's red small text is the same story — 3.76:1 at red-500,
     6.47:1 at the --vci-red already declared above. */
  --vci-pos: #5c6318;

  /* The MONTHLY statement's own palette — a different template again: navy
     masthead, green money, an amber "worth a double-check" flag, a mint pill.
     Measured against the PDF, three pairs miss the 4.5 floor:

         green  #0D9E6E money rows on white      3.42:1
         green  #0D9E6E on the mint pill         2.84:1
         indigo #817CCB section labels on white  3.67:1

     Same treatment as the other two renders: nearest passing shade of the
     same hue — emerald-700 for the money (5.48 on white, 4.55 on mint) and
     --vci-indigo for the labels (5.85). The amber already passes at 5.02 and
     is the PDF's own value.
     📌 The BIG total would have passed at the product's green — 3.42 clears
     the 3:1 large-text threshold at 44px. It takes the darker green anyway,
     because two different greens in one statement reads as a mistake. */
  --vci-navy: #4c4e68;
  --vci-money: #4c4e68;
  --vci-mint: #edf0ce;
  --vci-amber: #a64f00;
  --font-vci: system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;

  --line-deep: #b2a695;
  --line: #d9d3ca;
  --line-ring: #c9c2b8;

  /* --line-ink — ADDED 8/24 for the closing block's hairlines. The three
     rules above are WARM (they are oat's own greys) and go muddy on a colour
     ground; on --sky they read as a beige smudge rather than a line. This is
     ink at 16%, i.e. the same hairline the mock draws — sampled off it at
     rgb(177,201,211) on sky, which is ink at ~14-18%.
     rgba() rather than a hex for the same reason as the track tokens above:
     it is an opacity on an existing token, not a new colour. */
  --line-ink: rgba(47, 47, 53, 0.16);

  /* The one permitted elevation. Nothing heavier anywhere. */
  --shadow-card: 0 2px 24px rgba(47, 47, 53, 0.06);

  /* -- Type -------------------------------------------------------------- */
  --font-display: "All Round Gothic", "Century Gothic", ui-rounded, system-ui,
    sans-serif;
  --font-body: "Altivo", system-ui, -apple-system, sans-serif;

  /* Decorative accent — ANDORA MODERN SERIF, per Brand Guide p.13, which names
     exactly three faces: All Round Gothic and Altivo for "Headers & Paragraph",
     and Andora Modern Serif for "Decorative".

     🔴 This was briefly changed to Prata and is now changed back. The mockup
     bundle's token file asserts Andora is print-only with no web licence; that
     was true for its author but not here. Brees licensed Andora on 2026-08-10
     (Creative Market order 148062510) — Regular and Italic, each with a
     Webfont licence, shipping .woff/.woff2. Prata is not in the brand guide at
     all and has been removed entirely.

     ⚠️ The webfont licence is capped at 10,000 pageviews/month per style. Fine
     for a prototype; must be upgraded before this serves a public DE page.

     Andora has Regular and Italic, no bold — 600/700 would be a synthesised
     fake, so the decorative face is never emboldened.

     Playfair Display and Poppins are gone from every stack. They were the
     stand-ins while the real faces were missing, and they were arriving from
     Google Fonts on every page. Those link tags are removed; the site now
     loads no external fonts at all. */
  --font-accent: "Andora Modern Serif", "Bodoni Moda", Didot, serif;

  --fs-display: clamp(2.5rem, 5.5vw, 4.5rem);
  --fs-h2: clamp(1.875rem, 3.6vw, 3rem);
  --fs-h3: clamp(1.1875rem, 1.9vw, 1.5rem);
  --fs-lead: clamp(1.0625rem, 1.5vw, 1.3125rem);
  --fs-body: 1.0625rem;
  --fs-small: 0.9375rem;
  --fs-eyebrow: 0.8125rem;

  --lh-display: 1.06;
  --lh-body: 1.65;
  --ls-display: -0.02em;
  --ls-eyebrow: 0.14em;
  --measure: 64ch;

  /* -- Space (8px base, these values only) -------------------------------- */
  --s-1: 8px;
  --s-2: 16px;
  --s-3: 24px;
  --s-4: 40px;
  --s-5: 64px;
  --s-6: 96px;
  --s-7: 144px;

  --section-pad: clamp(4rem, 8vw, 8rem);
  --container-max: 1240px;
  --container-pad: clamp(1.25rem, 5vw, 4rem);
  --grid-gap: 24px;

  /* -- Radius ------------------------------------------------------------- */
  --r-card: 24px;
  --r-render: 16px;
  --r-bleed: 0;
  --r-pill: 999px;

  /* -- Motion ------------------------------------------------------------- */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --d-micro: 150ms;
  --d-nav: 180ms;
  --d-marker: 200ms;
  --d-accordion: 240ms;
  --d-highlight: 300ms;
  /* 400 -> 750. Brees, 8/18: "I do see some animation but it happens so fast,
     maybe we slow it a bit so it's more intentional."
     ⚠️ THIS IS THE ONE LEVER FOR THE WHOLE `.reveal` SYSTEM - 32 elements,
     plus `.connector` and its node dots, which consume the same token.
     🔴 ONE THING DOES **NOT** FOLLOW IT: the hero's `--d-hero` (700ms).

     ⏹ The pricing rules' clip-path draw USED to be the other exception,
     hardcoded at 620ms / 700ms. Brought onto this token 8/19 at Brees'
     request, so the whole `.reveal` system now moves at one speed. Its
     460ms delay on `::before` is deliberately KEPT — that offset is the
     two-stage draw, not a duration, and folding it in would collapse the
     sequence into a single simultaneous reveal.
     ⚠️ The old note pointed at direction-d.css:1410/:1415. Those line
     numbers were already stale by ~57 lines when this was written; the
     rules are near :1467. Search for `.pricing__rule.reveal.is-visible`
     rather than trusting a line number. */
  --d-reveal: 750ms;
  --d-hero: 700ms;

  /* -- SPOTLIGHT SUB-BRAND ------------------------------------------------
     Spotlight (the product Alie's copy calls Smart Intake) has its OWN logo,
     palette and typefaces. Brees, 9/3: "the page from the hero to the last
     section should be spotlight branding but the header and the footer, those
     aren't going to change." So these tokens skin ONE page's <main>; the DE
     palette above still dresses the chrome around it.

     🔴 WHY THEY LIVE HERE AND NOT IN spotlight.css. verify.js allows a raw hex
     only in a sheet that OWNS :root — the rule is expressed as a role, not a
     filename, precisely so a fork does not get a hand-written exemption. This
     sheet owns :root, so this is where a new palette is declared, and
     spotlight.css references var(--sl-*) like every other sheet.

     Values are verbatim from "Logo Style Guide.pdf" in the Spotlight brand
     folder (Drive), 2025-08-22.

     🔴 CHARCOAL IS THE ONLY TEXT COLOUR IN THIS PALETTE. Measured, all pairs:
        charcoal on off-white 14.60 · on white 16.30 · on cream 13.06
                  on blue      7.87 · on gold  9.32
        gold / blue / cream on ANY light ground: 1.12–2.07 — every one fails
        both the 4.5 body floor and the 3.0 large-text floor.
     Gold, blue and cream are FILL colours. They become text ONLY reversed on
     charcoal (9.32 / 7.87 / 13.06). The brand's own button is charcoal-on-gold
     at 9.32, so this is Spotlight's own rule, not one imposed on it.
     ⚠️ Spotlight's app uses white-on-blue for its CONTINUE button — 2.07:1.
     That is inside their product screenshots and stays there. Do NOT copy it
     onto this page as a button style. */
  --sl-charcoal: #231F20;
  --sl-gold: #DAC52A;
  --sl-cream: #F0E8AA;
  --sl-blue: #75BEDB;
  --sl-offwhite: #F4F2F0;

  /* ⏳ THE REAL FACES ARE NAMED FIRST AND ARE NOT LOADED YET. Co Headline Bold
     (Dalton Maag) and Chennai Bold (Insigne) are Adobe Fonts. They are cleared
     for web use through an Adobe web project, and self-hosting them needs
     separate foundry licences — so there are no .woff2 files for these and
     there must not be. That is the Avenir rule this studio already learned.

     Naming them first means the day the kit <link> lands, every heading and
     every paragraph on this page changes face with NO other edit. Until then
     the DE faces stand in, which is why the page reads slightly wrong today.
     ⏳ OWED: an Adobe Fonts kit id authorised for localhost, the Vercel
     preview and digitalempathyvet.com. */
  --sl-font-head: "co-headline", "Co Headline", "All Round Gothic", system-ui, sans-serif;
  --sl-font-body: "chennai", "Chennai", "Altivo", system-ui, sans-serif;
}

/* --------------------------------------------------------------------------
   2. BRAND FONT DECLARATIONS — MOVED

   The real files landed 2026-08-11, extracted from the brand-guide homepage
   mockup bundle. All 18 cuts now live in assets/fonts/ and are declared in
   assets/css/fonts.css, which every page loads BEFORE this file.

   What used to be here was a block of @font-face rules pointing at filenames
   that were never delivered (allroundgothic-demi.otf, altivo-light.otf, and
   so on). Every one of them 404'd, which is why all six directions had been
   rendering in the Poppins fallback. They are deleted rather than left in
   place: a declaration that always fails is indistinguishable from one that
   is about to start working, and it hid the fact that the fonts were missing.

   The Andora Modern Serif declaration is deleted and NOT replaced. See the
   note on --font-accent above.
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   3. RESET
   -------------------------------------------------------------------------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body,
h1,
h2,
h3,
h4,
p,
figure,
blockquote,
dl,
dd,
ul,
ol {
  margin: 0;
}

ul,
ol {
  padding: 0;
  list-style: none;
}

body {
  min-height: 100vh;
  font-family: var(--font-body);
  font-size: var(--fs-body);
  font-weight: 400;
  line-height: var(--lh-body);
  color: var(--ink);
  background-color: var(--oat);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

img,
picture,
video,
canvas,
svg {
  display: block;
  max-width: 100%;
}

input,
button,
textarea,
select {
  font: inherit;
  color: inherit;
}

button {
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  text-align: inherit;
}

a {
  color: inherit;
}

table {
  border-collapse: collapse;
  width: 100%;
}

/* --------------------------------------------------------------------------
   4. TYPOGRAPHY PRIMITIVES
   Scale and weight only. Colour and placement belong to the directions.
   -------------------------------------------------------------------------- */

/* 🔴 THE TYPE RULE, 9/10 — HEADING LEVEL DECIDES THE FACE.

   Brees: "All H1s and H2s, unless I specified otherwise, should be All Round
   Gothic Medium. Everything else (H3s, H4s, etc.) should be the font Spring or
   the Altivo." Piloted on Call Insights 9/10, approved, rolled out here.

   So `.t-h3` LEAVES this group. H1 and H2 keep the display face at 500 —
   which they already were; that half of the rule needed no change at all.

   ⏹ "Spring" is not used: no such face exists in this repo or in the brand
   guide, which names exactly three (All Round Gothic and Altivo for Headers &
   Paragraph, Andora Modern Serif for Decorative). Brees chose Altivo for now,
   9/10, with Spring to be swapped in later if it materialises — one token. */
.t-display,
.t-h2 {
  font-family: var(--font-display);
  font-weight: 500;
  line-height: var(--lh-display);
  letter-spacing: var(--ls-display);
  text-wrap: balance;
}

.t-display {
  font-size: var(--fs-display);
}

.t-h2 {
  font-size: var(--fs-h2);
}

/* ⚠️ ALTIVO HAS NO 600 CUT (300/400/400i/500/700). Carrying the old
   `font-weight: 600` across would have silently resolved to the 700 face — a
   heavier jump than intended — so the weight is stated, not inherited.
   📌 500 matches `.faq__q`, which was ALREADY Altivo before this rule existed
   and is therefore the precedent rather than a new invention.
   ⚠️ `text-wrap: balance` is restated here because leaving the group above
   dropped it. */
.t-h3 {
  font-family: var(--font-body);
  font-size: var(--fs-h3);
  font-weight: 500;
  line-height: 1.25;
  letter-spacing: 0;
  text-wrap: balance;
}

.t-lead {
  font-size: var(--fs-lead);
  line-height: 1.5;
  max-width: var(--measure);
}

.t-body {
  font-size: var(--fs-body);
  max-width: var(--measure);
}

.t-small {
  font-size: var(--fs-small);
}

.t-eyebrow {
  font-family: var(--font-body);
  font-size: var(--fs-eyebrow);
  font-weight: 600;
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--ink-muted);
}

/* The decorative accent, used on ONE emphasis word inline mid-sentence —
   never on a whole line. (Brand guide; confirmed by the homepage mockup,
   which sets exactly one word per headline in it.)

   UPRIGHT, not italic — Brees' call, 8/11, and the guide-faithful reading.
   The Brand Guide's own Andora specimen (p.13) is upright, and the brand
   homepage mockup sets every decorative word upright too. The accent then
   reads as a change of texture inside the sentence rather than a flourish.

   This project originally set it italic, but that decision was made while the
   decorative face was actually Playfair Display standing in for an unavailable
   Andora — an aesthetic choice about a placeholder, not about this typeface.

   The Andora Italic IS licensed and IS declared in fonts.css. It is simply not
   used here. It stays declared because it is bought and drawn artwork we may
   want later; `font-display: swap` means an unused face is never downloaded.

   Weight stays 400 — Andora ships no bold, and a heavier value would be
   faux-bolded by the browser. */
.accent-serif {
  font-family: var(--font-accent);
  font-weight: 400;
  font-style: normal;
  letter-spacing: 0;
}

/* Numerals that need to line up in a column (proof figures, invoice tables). */
.t-tabular {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* --------------------------------------------------------------------------
   5. FOCUS
   Visible on every interactive element. Never removed without replacement.
   -------------------------------------------------------------------------- */

:focus {
  outline: 3px solid var(--petal);
  outline-offset: 2px;
}

:focus:not(:focus-visible) {
  outline: none;
}

/* 🔴 DUAL-TONE FOCUS RING — do not collapse this back to one colour.

   This was a single 3px petal outline. Measured against every ground this
   brand actually uses, it FAILED WCAG 2.4.11 / 1.4.11 (>= 3:1 for a focus
   indicator) on nine of eleven:

       oat 1.48  ·  white 1.70  ·  petal 1.00  ·  lime 1.15  ·  sky 1.26
       oat-deep 1.29  ·  sky-soft 1.48  ·  petal-soft 1.40  ·  lime-soft 1.46
       ink 7.80 PASS  ·  indigo 4.74 PASS

   Petal on a petal section is 1.00:1 — the ring was not merely weak there,
   it was invisible. The old note anticipated trouble "on the ink and indigo
   sections where the petal ring has the least room to read". It was exactly
   backwards: ink and indigo were the only two grounds it passed on.

   The fix is a two-band indicator rather than a better single colour, because
   no single hue clears 3:1 against both oat and ink. An ink outline sits
   outside a white band, so whichever ground the element is on, one of the two
   bands contrasts against it:

       oat 11.53  ·  white 13.30  ·  petal 7.80  ·  lime 8.95  ·  sky 9.83
       ink 13.30  ·  indigo 8.09  ·  oat-deep 10.07  ·  tints 10.95-11.54

   The white band is the same idea as the halo on Design Explorer's ring,
   which is recorded there as "never delete". Same reasoning here: remove
   either band and the indicator disappears on half the palette. */
:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 2px;
  /* Fills the 2px offset gap, so the pair is always adjacent with no ground
     showing between them. */
  box-shadow: 0 0 0 2px var(--white);
  border-radius: 2px;
}

/* --------------------------------------------------------------------------
   6. SCREEN-READER UTILITIES
   -------------------------------------------------------------------------- */

.visually-hidden {
  position: absolute !important;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Skip link — first focusable element on every direction. */
.skip-link {
  position: absolute;
  top: var(--s-1);
  left: var(--s-1);
  z-index: 999;
  padding: var(--s-1) var(--s-2);
  background-color: var(--ink);
  color: var(--oat);
  font-size: var(--fs-small);
  font-weight: 500;
  border-radius: var(--r-pill);
  transform: translateY(-200%);
  transition: transform var(--d-nav) var(--ease-out);
}

.skip-link:focus {
  transform: translateY(0);
}

/* --------------------------------------------------------------------------
   7. SHARED BEHAVIOUR PRIMITIVES
   The collapse mechanic used by both the Problem cards and the FAQ.
   Text stays in the DOM at all times — height:0 + overflow:hidden, never
   display:none — so it is indexable and readable by assistive tech, and so
   the FAQPage schema mirrors visible text exactly.
   -------------------------------------------------------------------------- */

.collapse {
  height: 0;
  overflow: hidden;
  transition: height var(--d-accordion) var(--ease-out);
}

.collapse[data-open="true"] {
  height: auto;
}

/* Without JS every panel is open and the page is complete. The script sets
   data-js="on" on <html> at parse time, which is what arms the collapse. */
html:not([data-js="on"]) .collapse {
  height: auto;
}

/* Section entrance. Elements start displaced only once JS confirms it can
   restore them; without JS they are simply visible. */
html[data-js="on"] .reveal {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity var(--d-reveal) var(--ease-out),
    transform var(--d-reveal) var(--ease-out);
}

html[data-js="on"] .reveal.is-visible {
  opacity: 1;
  transform: none;
}

/* --------------------------------------------------------------------------
   8. REDUCED MOTION
   Produces a completely still page with all content in its final state.
   Signature elements additionally handle this in their own logic — a
   duration override alone is not sufficient for them.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }

  html[data-js="on"] .reveal {
    opacity: 1;
    transform: none;
  }
}
