/* ============================================================
   HOLDBACK — styles.css
   Independent Automotive Advisory · Toronto, Ontario
   ============================================================

   TABLE OF CONTENTS  (search for "§N" to jump)

   §1   RESET + :root design tokens (ink/surface/accent/spacing/
        radius/shadow/motion/section-rhythm/transitions)        ~L10
   §2   Base typography + html/body                              ~L390
   §3   Utility classes (text-center, sr-only, num-tabular)      ~L400
   §4   Button system (.btn, .btn-primary, .btn-outline, .btn-lg) ~L430
   §5   Editorial: drop-cap + emphasis + brand-def + manifesto   ~L600
   §6   Hero + page-header + chapter-numeral system              ~L640
   §7   Mobile typography overrides                              ~L655
   §8   Breadcrumb removed (see comment)                         ~L780
   §9   Tool narrative system (.tool-hero-argument et al)        ~L790
   §10  Stats bar + count-up + reveal-up animations              ~L900
   §11  Disabled states + form invalid                           ~L930
   §12  Cards + pricing tier + comparison table                  ~L1050
   §13  Editorial figures + pull-quotes + callouts               ~L2700
   §14  Editorial divider + closing manifesto                    ~L3050
   §15  Hero numeral watermark (page-header + guide-hero)        ~L3070
   §16  Loading / sending button states                          ~L3760
   §17  Input + select + textarea base                           ~L3140
   §18  Footer (3-zone: nav + newsletter + legal)                ~L3260
   §19  Section-rhythm collapse rule (data-bg sibling)           ~L380
   §20  Mobile nav + responsive (640/768/960 breakpoints)        ~L4040
   §21  prefers-reduced-motion overrides                         ~L4200
   §22  Mobile CTA bar bottom positioning                        ~L4290

   Line numbers are approximate — drift with edits. Use as
   discovery hints, not authoritative. For the canonical
   structure, see /design-system in the live site.
   ============================================================ */

/* ----------------------------------------------------------
   §1. RESET + :root DESIGN TOKENS
   ---------------------------------------------------------- */

*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  top: -60px;
  left: 0;
  background: var(--orange);
  color: var(--slate);
  /* WCAG 2.5.5 — ensure focused skip link is 44px+ tall on focus. */
  padding: var(--sp-3) 20px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  z-index: var(--z-skip);
  font-weight: 600;
  transition: top var(--duration-fast) var(--ease-out);
}

/* ============================================================
   DESIGN TOKEN SYSTEM — single source of truth

   Naming convention: role-based, not hue-based.
     --ink-*      text on light surface
     --surface-* backgrounds
     --accent-*  primary brand orange + variants
     --on-dark-* alpha-white text roles on slate backgrounds
     --border-*  dividers and outlines
     --fs-*      font-size scale (9 steps + 2 clamped display)
     --lh-*      line-height tokens
     --ls-*      letter-spacing tokens
     --fw-*      font-weight tokens
     --sp-*      4pt spacing grid (0 / 4 / 8 / 12 / 16 / 24 / 32 / 48 / 64 / 96 / 128)
     --radius-*  border radius (xs → pill → circle)
     --shadow-*  elevation (0–5 + focus + accent)
     --duration-*, --ease-* motion primitives
     --transition-* pre-composed transitions for common cases
     --z-*       stacking contexts

   Legacy aliases live at the bottom of :root — those are maintained
   for backward compatibility while existing rules continue to refer
   to the older naming. Do not introduce new usages of the legacy
   tokens in new rules. Migrate references incrementally.
   ============================================================ */

:root {
  /* ─── 1. INK (text on light surfaces) ─────────────────────── */
  /* Warm-biased grays — neutrals live in the same thermal family as the orange. */
  --ink:               #1A2332;   /* primary — headlines, body */
  --ink-2:             #58544F;   /* secondary body, muted UI — warm (AAA 7.5:1) */
  --ink-3:             #8A8578;   /* tertiary — captions — warm (AA Large 3.67:1) */
  --ink-disabled:      #C4C8CD;
  --body-text:         #524E47;   /* long-form body, softer than --ink — warm (AAA 8.3:1) */

  /* ─── 2. SURFACE (backgrounds) ────────────────────────────── */
  --surface:              #FFFFFF;
  --surface-raised:       #F2EFE8;   /* cream — warmed for editorial read (+4pts warmth) */
  --surface-sunk:         #ECE6DB;   /* cream-hover — interactive lift (adjusted to match new cream) */
  --surface-inverse:      #1A2332;   /* slate */
  --surface-inverse-deep: #0F1828;   /* deeper slate — night-sky indigo, not void */

  /* ─── 3. ACCENT (brand orange — context-aware) ───────────── */
  --accent:            #E8762B;   /* primary — CTAs, highlights (on slate: 5.18:1) */
  --accent-large:      #DF701B;   /* large text on white — H1/H2/stat (AA Large 3.25:1) */
  --accent-hover:      #C05D1A;   /* hover on light bg */
  --accent-active:     #A83D00;   /* pressed / active / body text on white (AA small 5.98:1) */
  --accent-deepest:    #7A2900;   /* deep fill for tinted cells */
  --accent-on-dark:    #F39455;   /* text variant for slate bg (AA 6.9:1) */
  --accent-tint:       #FFF5EF;   /* lightest — highlight-cell bg */
  --accent-tint-2:     #FDEDD8;   /* stronger tint */

  /* ─── 4. SEMANTIC (status) ────────────────────────────────── */
  --ok:                #10B981;
  --ok-deep:           #059669;
  --warn:              #F59E0B;
  --warn-tint:         #FEF3C7;
  --warn-ink:          #92400E;
  --danger:            #DC3545;   /* warmed — rust-red, lives in warm family (AA Large 4.41:1) */
  --danger-deep:       #C02D36;   /* warmed body-text red (AA small 5.63:1) */
  --ok-text:           #047857;   /* success as TEXT on white/cream — AA small 5.14:1 (was --ok #10B981 failing at 2.54:1) */
  /* Semantic tint tokens — added in BDCA closeout (audit 2026-05-06).
     Migrate scattered light-tint hex literals (#DCFCE7, #FEE2E2, #E0F2FE,
     #F0FDF4, #BBF7D0, #7F1D1D, #0C4A6E) to a single source of truth. */
  --ok-tint:           #DCFCE7;   /* light green badge/cell bg */
  --ok-tint-soft:      #F0FDF4;   /* lightest green callout bg */
  --ok-border:         #BBF7D0;   /* green callout border */
  --danger-tint:       #FEE2E2;   /* light red badge/cell bg */
  --danger-deepest:    #7F1D1D;   /* deepest red text on tint */
  --ok-deepest:        #064E3B;   /* deepest green text on green tint —
                                     pairs with --ok-alpha-10 / --ok-tint
                                     for ~10:1 reading contrast. Was a
                                     gap in the token set: --danger-
                                     deepest existed but --ok-deepest
                                     did not, so green tinted cards used
                                     --ok-text (#047857) at borderline
                                     ~3.6:1 (audit 2026-05-08). */
  --info-tint:         #E0F2FE;   /* light blue callout bg */
  --info-deep:         #0C4A6E;   /* deep blue callout text */

  /* Chart category palette — used by cost-of-ownership.html legend
     swatches. Was a free-floating flat-UI hex set; tokenized for
     consistency and to enable future re-skinning. */
  --chart-depreciation: #E67E22;
  --chart-financing:    #3498DB;
  --chart-insurance:    #9B59B6;
  --chart-fuel:         #2ECC71;
  --chart-maintenance:  #E74C3C;
  --chart-fees:         #95A5A6;

  /* Editorial signal tokens — foundation for "industry-insider" voice.
     Color-design audit 2026-05-07 found Holdback's positioning ("ex-
     dealer telling you what they don't want you to know") has zero
     color-system expression beyond CTAs. These four tokens map specific
     editorial roles to brand-coherent ink colors. Components that
     consume them (insider-note, regulatory-citation, verified-claim,
     anonymous-source) ship in next iteration; tokens land first so
     pages can adopt incrementally without breaking existing styles.

     All four are AAA on white (>7:1) and AA Large on cream (>4.5:1). */
  --ink-insider:       #4A2E0F;   /* dark amber — "from the dealer side" notes */
  --ink-regulatory:    #1E3A5F;   /* deep slate-blue — OMVIC/MVDA citations */
  --ink-verified:      #1B4D2E;   /* deep forest — verified-independence claims */
  --ink-anonymous:     #2D2D2D;   /* near-black — anonymous-source quotes */

  /* Audit round-4 2026-05-08: editorial ink expansion. */
  --ink-marginalia:    #5C4A2E;   /* warm-paper-on-paper — sidenotes / pull-quotes */
  --ink-footnote:      #7A6E5C;   /* faded — footnote refs and small secondary text */

  /* Surface palette expansion — beyond cream/white/slate. The audit
     identified the 3-color trio as too narrow; paper/fog/ember fill
     in the warmth gradient between them. */
  --surface-paper:     #FAF6EE;   /* warmer than cream — for callouts on white */
  --surface-fog:       #E8E4DC;   /* divider rule shading, between cream and border */
  --surface-ember:     #382418;   /* deepest editorial — pillar-guide cliffhangers */

  /* Status-icon glyphs — audit round-2 2026-05-07 A7. Color-blind
     readers (protanopia / deuteranopia) cannot distinguish the orange
     accent from the danger-red on small UI surfaces. Pairing every
     status indicator with a SHAPE-distinct glyph makes the semantic
     meaning legible without relying on color (WCAG 1.4.1). Components
     that consume these (.status-pill, .badge with status modifier)
     emit ::before content automatically. */
  --status-ok-icon:      "\2713";   /* ✓ check — success / verified */
  --status-warn-icon:    "\0021";   /* ! exclamation — warning / attention */
  --status-danger-icon:  "\2715";   /* ✕ x — error / blocked */
  --status-info-icon:    "\2139";   /* ℹ info circle — neutral guidance */

  /* ─── 5. BORDERS & DIVIDERS ───────────────────────────────── */
  --border:             #E0DDD8;
  --border-subtle:      rgba(26, 35, 50, 0.06);
  --border-on-dark:     rgba(255, 255, 255, 0.10);
  --border-on-dark-sub: var(--surface-on-dark-2);

  /* ─── 6. TEXT ON DARK (alpha-white roles) ─────────────────── */
  /* Elevated to editorial reading-ergonomics standard (NYT, Atlantic,
     Apple on dark). Prior values were AA-compliant but perceptually
     dim for sustained reading. All new values remain AAA on slate. */
  --on-dark:            rgba(255, 255, 255, 0.92);  /* primary body on slate — hero decks, long-form */
  --on-dark-default:    rgba(255, 255, 255, 0.85);  /* secondary body — sidebar cards, CTA descriptors */
  --on-dark-muted:      rgba(255, 255, 255, 0.75);  /* captions, meta labels */
  --on-dark-dim:        rgba(255, 255, 255, 0.68);  /* tertiary — footer legal, fine-print */

  /* Low-alpha fills for cards / strips on slate backgrounds */
  --surface-on-dark-1:  rgba(255, 255, 255, 0.04);
  --surface-on-dark-2:  rgba(255, 255, 255, 0.06);
  --surface-on-dark-3:  rgba(255, 255, 255, 0.08);
  --surface-on-dark-4:  rgba(255, 255, 255, 0.12);

  /* ─── 7. ACCENT ALPHAS (tint backgrounds) ─────────────────── */
  --accent-alpha-5:     rgba(232, 118, 43, 0.05);   /* whisper tint */
  --accent-alpha-8:     rgba(232, 118, 43, 0.08);
  --accent-alpha-10:    rgba(232, 118, 43, 0.10);
  --accent-alpha-12:    rgba(232, 118, 43, 0.12);
  --accent-alpha-20:    rgba(232, 118, 43, 0.20);   /* declared 2026-05-08 — was referenced in --shadow-warm-xl + .status-pill but never declared, silently breaking those rules until now */
  --accent-alpha-25:    rgba(232, 118, 43, 0.25);
  --accent-alpha-35:    rgba(232, 118, 43, 0.35);
  --accent-alpha-40:    rgba(232, 118, 43, 0.40);   /* CTA glow */
  --accent-alpha-50:    rgba(232, 118, 43, 0.50);   /* heavy hover/halo */

  /* Status-color alpha pairs for success / danger / warn badges */
  --ok-alpha-10:        rgba(16, 185, 129, 0.10); /* emerald — matches --ok #10B981 */
  --ok-alpha-25:        rgba(16, 185, 129, 0.25);
  --danger-alpha-10:    rgba(220, 53, 69, 0.10);  /* matches warmed --danger var(--danger) */
  --danger-alpha-25:    rgba(220, 53, 69, 0.25);
  --warn-alpha-10:      rgba(245, 158, 11, 0.10); /* matches --warn #F59E0B */
  --warn-alpha-25:      rgba(245, 158, 11, 0.25);

  /* Tinted-slate alpha — for elevation effects on light-bg cards
     (mirrors the --surface-on-dark-* family but slate-on-light) */
  --surface-tinted-04:  rgba(26, 35, 50, 0.04);  /* faintest — tooltip/disclaimer */
  --surface-tinted-06:  rgba(26, 35, 50, 0.06);  /* faint — neutral badge bg */
  --surface-tinted-08:  rgba(26, 35, 50, 0.08);  /* card lift */

  /* Shadow-dark tint (for hovering CTA on slate) */
  --shadow-slate-12:    rgba(26, 35, 50, 0.12);
  --shadow-slate-25:    rgba(26, 35, 50, 0.25);
  --shadow-slate-30:    rgba(26, 35, 50, 0.30);
  --shadow-slate-deep-40: rgba(15, 24, 40, 0.40);
  --shadow-pure-25:     rgba(0, 0, 0, 0.25);

  /* Edge-case orange alphas (used in gradient glows / focus rings) */
  --accent-alpha-7-grad: rgba(232, 118, 43, 0.07);   /* hero radial glow */
  --accent-alpha-15:    rgba(232, 118, 43, 0.15);    /* focus-ring on orange */
  --accent-alpha-30:    rgba(232, 118, 43, 0.30);    /* thankyou badge glow */

  /* Top-mobile-CTA dark shadow (inverted direction) */
  --shadow-mobile-cta:  0 -4px 20px rgba(26, 35, 50, 0.25);

  /* Divider on slate — warm peach beat mark (carries brand DNA into dark sections) */
  --divider-on-dark:    rgba(243, 148, 85, 0.35);

  /* In-between alpha white — CTA descriptor copy on slate */
  --on-dark-soft:       rgba(255, 255, 255, 0.80);   /* elevated from 0.68 for reading ergonomics */

  /* ─── 8. TYPOGRAPHY — families ────────────────────────────── */
  --font-heading: 'DM Serif Display', Georgia, serif;
  --font-body:    'DM Sans', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;

  /* ─── 9. TYPOGRAPHY — size scale ──────────────────────────── */
  --fs-2xs:        0.6875rem;  /* 11px — legal / fine print */
  --fs-xs:         0.75rem;    /* 12px — eyebrows, badges, micro UI */
  --fs-sm:         0.875rem;   /* 14px — secondary body, UI labels */
  --fs-sm-plus:    0.95rem;    /* 15.2px — body copy "just under base" */
  --fs-base:       1rem;       /* 16px — default body */
  --fs-md:         1.125rem;   /* 18px — lead paragraph, subtitles */
  --fs-lg:         1.375rem;   /* 22px — small section headings (h4) */
  --fs-xl:         1.75rem;    /* 28px — h3, card titles */
  --fs-2xl:        2.25rem;    /* 36px — h2 static (page intros) */
  --fs-2xl-fluid:  clamp(1.6rem, 3vw, 2.25rem);   /* h2 responsive (section titles) */
  --fs-3xl:        clamp(2rem,   4vw, 3rem);      /* h1 (tool / article / guide pages) */
  --fs-display:    clamp(2.75rem, 4vw + 1rem, 4.25rem);  /* hero h1 (homepage display) */
  /* Hero figure — ONE dramatic number per page (e.g., "$3,100", "2.5%").
     Larger than display, for the single "wow" stat moment. Used sparingly. */
  --fs-hero-figure: clamp(3.5rem, 6vw + 1rem, 5.5rem);

  /* ─── 10. TYPOGRAPHY — line heights ───────────────────────── */
  --lh-display: 1.05;   /* display heroes */
  --lh-tight:   1.15;   /* large headings */
  --lh-snug:    1.3;    /* small headings */
  --lh-base:    1.55;   /* body */
  --lh-relaxed: 1.7;    /* relaxed prose — ~50 hardcoded `1.7` literals across blog/guide pages migrated to this token (audit 2026-05-06) */
  --lh-loose:   1.75;   /* long-form prose */

  /* ─── 11. TYPOGRAPHY — tracking ───────────────────────────── */
  --ls-tight:    -0.02em;   /* display */
  --ls-snug:     -0.01em;   /* headings */
  --ls-normal:    0;
  --ls-wide:      0.06em;   /* small caps */
  --ls-widest:    0.12em;   /* eyebrow labels */

  /* ─── 12. TYPOGRAPHY — weights ────────────────────────────── */
  --fw-regular:  400;
  --fw-medium:   500;
  --fw-semibold: 600;
  --fw-bold:     700;

  /* ─── 13. SPACING — 4pt grid + half-step ──────────────────── */
  --sp-0:   0;
  --sp-1:   4px;
  --sp-1half: 6px;     /* half-step — tight inline gaps (badge icon-text, status pills, micro-rows). 50+ usages */
  --sp-2:   8px;
  --sp-3:   12px;
  --sp-3half: 14px;    /* half-step — table cells, button vertical padding (audit round-2 2026-05-07 #4b: 14px literal had ~20+ usages) */
  --sp-4:   16px;
  --sp-5:   24px;
  --sp-5half: 28px;    /* half-step — card padding tier between sp-5 and sp-6 (audit round-2 2026-05-07 #4b: 28px literal had ~25+ usages including .cbc-quote-box, deal-analyzer.css, payment-calculator.css) */
  --sp-6:   32px;
  --sp-7:   48px;
  --sp-7half: 56px;    /* half-step — section-row gap on long pages (audit round-2 2026-05-07 #4b: 56px literal in homepage.css + guides.css gap) */
  --sp-8:   64px;
  --sp-9:   96px;

  /* Audit round-3 2026-05-07 #2c: was 23 hardcoded `min-height: 44px`
     and 5 hardcoded `scroll-margin-top: 88px` across files. Tokens
     centralize the discipline so WCAG 2.5.5 compliance and nav-clearance
     have a single source of truth. */
  --touch-target-min:        44px;
  --scroll-margin-section:   88px;

  /* Card-padding tokens — the layout audit (2026-05-06) found 16+ card
     components (callout, callout-box, callout-dark, script-box, warning-box,
     fee-card, product-card, range-card, scope-card, fi-product-card,
     path-card, bos-section, sidebar-card, sidebar-cta-card, author-box,
     sidebar-stat-card, etc.) with five different paddings: 20px, 24px,
     28px, 32px, 36px. Two of those (20, 28) are off-grid. Standardising
     to these two tokens (24 = base body card, 32 = hero/result card)
     closes ~40 findings. */
  --card-pad:    var(--sp-5);   /* 24 — body cards, callouts, script-boxes */
  --card-pad-lg: var(--sp-6);   /* 32 — hero/result/featured cards */

  /* Card-hover canonical pattern — the design-consistency audit
     (2026-05-07) found 14 distinct card-hover signatures across the
     site (lift values -1/-2/-3/-4px; shadow tokens --shadow-md / -3 /
     -4 / -lg / -xl / none). Standardising on these two tokens makes
     every interactive card feel like one family. -2px lift + shadow-lg
     is the most common existing pattern; -3px + shadow-xl is reserved
     for premium / hero cards (pillar guide cards, blog featured). */
  --card-hover-lift:     -2px;
  --card-hover-lift-lg:  -3px;
  /* Audit round-4 2026-05-08: prior card-hover shadows were cool gray
     (--shadow-lg / --shadow-xl), reading "spec sheet" rather than
     "premium brand." Now layered: brand-warm orange-tinted glow
     UNDER the gray depth shadow, so every card hover carries brand
     in its lift. Closes the "flat and cold" feedback. */
  --card-hover-shadow:    0 12px 28px var(--accent-alpha-12), 0 4px 12px rgba(26, 35, 50, 0.10);
  --card-hover-shadow-lg: 0 20px 48px var(--accent-alpha-15), 0 8px 20px rgba(26, 35, 50, 0.14);
  --sp-10: 128px;

  /* ─── 14. SECTION RHYTHM ──────────────────────────────────── */
  --section-pad:     80px 0;   /* default — desktop (industry standard: Stripe/Linear/Vercel ~80px) */
  --section-pad-md:  64px 0;   /* tablet */
  --section-pad-sm:  40px 0;   /* mobile / dense */

  /* Section-rhythm contract: each <section> declares its background colour
     via data-bg="cream|white|slate". The collapse rule below uses that to
     remove the second section's top padding when two same-colour sections
     are stacked, so the visible gap = one --section-pad worth (80px) of
     breathing, not two (160px). Bg colour itself is still set by each
     section's own class rule — data-bg is metadata for the rhythm system. */

  /* ─── 15. RADIUS ──────────────────────────────────────────── */
  --radius-2xs:     2px;     /* micro elements — tab indicators, tiny chart bars */
  --radius-xs:      4px;
  --radius-sm:      6px;
  --radius-md:     10px;
  --radius-lg:     16px;
  --radius-xl:     24px;
  --radius-pill:  100px;
  --radius-circle: 50%;

  /* ─── 16. SHADOW — elevation scale ────────────────────────── */
  /* Round 9 audit 2026-05-08: bumped opacities across the card-tier
     scale (-2 / -3 / -4) by ~25-50% relative. Original scale was
     calibrated for cards on cream sections; against pure white sections
     the 4-8% layers were near-invisible at small zoom levels and on
     high-density displays, so cards with bg=white sitting on data-bg=
     "white" were reading as "white on white." The new opacities still
     stay below the threshold where shadows feel heavy/UI-toolkit, but
     give the lift cards need to read as elevated surfaces. */
  --shadow-0:       none;
  --shadow-1:       0 1px 2px rgba(26,35,50,0.05);   /* was 0.04 */
  --shadow-2:       0 2px 8px rgba(26,35,50,0.08);   /* was 0.06 */
  --shadow-3:       0 8px 24px rgba(26,35,50,0.12);  /* was 0.08 */
  --shadow-4:       0 16px 40px rgba(26,35,50,0.16); /* was 0.12 */
  --shadow-5:       0 24px 60px rgba(26,35,50,0.22); /* was 0.18 */
  --shadow-focus:   0 0 0 4px var(--accent-alpha-15);
  --shadow-focus-sm: 0 0 0 3px var(--accent-alpha-12); /* alias for input focus rings */
  --shadow-accent:  0 6px 20px var(--accent-alpha-35);
  --shadow-card:    0 4px 24px rgba(26, 35, 50, 0.08); /* soft elevation, used on 14 page-specific cards */
  --shadow-dark:    0 2px 20px rgba(15, 24, 40,0.40);   /* on slate */
  --shadow-warm:    0 8px 24px var(--accent-alpha-10), 0 2px 8px rgba(26, 35, 50, 0.06); /* warm elevation — brand in depth system */
  /* Audit round-4 2026-05-08: companion lg + xl variants for hero
     cards / pricing-tier featured / pillar-guide feature cards.
     The warmth ratio scales with elevation so larger cards feel
     literally "lit from below" with brand orange. */
  --shadow-warm-lg: 0 16px 40px var(--accent-alpha-15), 0 4px 16px rgba(26, 35, 50, 0.10);
  --shadow-warm-xl: 0 28px 64px var(--accent-alpha-20), 0 8px 24px rgba(26, 35, 50, 0.14);
  /* Soft ambient glow — for behind-element luminance (e.g., behind
     a hero h1, behind a featured pricing card). Not a drop shadow —
     a luminous halo that suggests light emanating from the surface. */
  --shadow-accent-glow:    0 0 60px rgba(232, 118, 43, 0.18);
  --shadow-accent-glow-lg: 0 0 100px rgba(232, 118, 43, 0.22);

  /* ─── 16a. SURFACE TEXTURE — procedural film grain ─────────
     Inline SVG noise via feTurbulence. No external asset needed.
     Applied at low opacity on dark surfaces (.hero, .cta-section,
     .footer) to add tactile "material" quality. Premium precedent:
     Linear 2023, Vercel 2024, Figma. Imperceptible individually,
     cumulatively signals "not flat color." */
  --grad-noise: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' seed='2'/><feColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.05 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");

  /* ─── 16b. GRADIENTS — sanctioned warm glows ──────────────── */
  /* Hero/slate section ambient glow — restores warmth to dark surfaces.
     Applied from the upper-right. Low alpha so type stays the hero. */
  --grad-hero-glow: radial-gradient(ellipse 1100px 700px at 85% 15%,
                      rgba(232, 118, 43, 0.14) 0%,
                      rgba(232, 118, 43, 0.06) 35%,
                      transparent 65%);
  /* Softer version for secondary slate sections (CTAs further down the page) */
  --grad-slate-glow-soft: radial-gradient(ellipse 900px 500px at 15% 90%,
                            var(--accent-alpha-10) 0%,
                            transparent 55%);
  /* CTA button inner gradient — adds the "button is lit" quality without extra DOM */
  --grad-cta-inner: linear-gradient(180deg,
                      rgba(255, 255, 255, 0.10) 0%,
                      rgba(0, 0, 0, 0.06) 100%);
  /* Section bridge — white→cream fade, white→slate fade (used in large sections) */
  --grad-section-bridge-cream: linear-gradient(180deg, var(--surface) 0%, var(--surface-raised) 100%);

  /* Audit round-4 2026-05-08: warmth-budget enrichment.
     The site previously had cream / white / slate as flat fills,
     reading "documentation" rather than "premium publication." These
     gradients add subtle vertical luminance — the eye registers warmth
     and depth without conscious notice (Stripe + Linear use the same
     trick). Use sparingly: hero cards, featured pricing tier, pillar-
     guide aside cards. Not on every surface. */
  --grad-cream-warm:  linear-gradient(180deg,
                        #F5F1E8 0%,
                        var(--surface-raised) 60%,
                        #EFEBE2 100%);
  --grad-white-soft:  linear-gradient(180deg,
                        #FFFFFF 0%,
                        #FAF8F5 100%);
  --grad-orange-wash: linear-gradient(180deg,
                        rgba(232, 118, 43, 0.04) 0%,
                        rgba(232, 118, 43, 0.00) 100%);
  --grad-ember-glow:  radial-gradient(ellipse 600px 320px at 50% 0%,
                        rgba(232, 118, 43, 0.10),
                        transparent 70%);

  /* ─── 17. MOTION ──────────────────────────────────────────── */
  --ease-out:         cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in-out:      cubic-bezier(0.65, 0, 0.35, 1);
  --ease-out-expo:    cubic-bezier(0.19, 1, 0.22, 1);  /* premium button hover, card lift */
  --ease-spring:      cubic-bezier(0.34, 1.56, 0.64, 1);  /* subtle overshoot for reveals */
  --ease-standard:    ease;                          /* fallback */
  --duration-fast:    150ms;   /* interactive feedback */
  --duration-base:    250ms;   /* most UI changes */
  --duration-slow:    400ms;   /* layout shifts, reveals */
  --duration-reveal:  600ms;   /* scroll reveals (stagger-friendly) */
  /* Audit round-4 2026-05-08 #9: idle CTA breathe duration. */
  --duration-cta-breathe: 4500ms;
  /* Page-load progressive reveal stagger — H1 → subtitle → CTAs → secondary. */
  --duration-stage-h1:        80ms;
  --duration-stage-subtitle:  200ms;
  --duration-stage-cta:       320ms;
  --duration-stage-secondary: 440ms;

  /* Pre-composed transitions for the common cases */
  --transition-color:     color var(--duration-fast) var(--ease-out);
  --transition-bg:        background-color var(--duration-fast) var(--ease-out);
  --transition-border:    border-color var(--duration-fast) var(--ease-out),
                          box-shadow  var(--duration-fast) var(--ease-out);
  --transition-transform: transform var(--duration-base) var(--ease-out);
  --transition-reveal:    opacity  var(--duration-slow) var(--ease-out),
                          transform var(--duration-slow) var(--ease-out);

  /* ─── 18. LAYOUT ──────────────────────────────────────────── */
  --container:       1140px;
  --container-tight: 880px;
  --container-wide:  1280px;
  /* Prose containers — added 2026-05-04 to replace 30+ hardcoded
     max-width values (520, 540, 620, 640, 720, 760, 800, 920) scattered
     across page CSS. Use these for any single-column reading container. */
  --container-prose-sm: 540px;   /* tight prose: alerts, single-column lists */
  --container-prose:    720px;   /* standard reading column (~65ch at 16px) */
  --container-prose-md: 760px;   /* legacy guide column — used by 5 Tier-2 guides; closes the audit's prose-width drift finding without forcing a visual change */
  --container-prose-lg: 920px;   /* wider prose: long-form articles */

  /* ─── 19. Z-INDEX ─────────────────────────────────────────── */
  --z-base:        1;
  --z-dropdown:    100;
  --z-sticky:      500;
  --z-mobile-cta:  999;
  --z-nav:         1000;
  --z-mobile-nav:  1001;
  --z-nav-toggle:  1002;
  --z-modal:       5000;
  --z-progress:    9999;
  --z-skip:        10000;

  /* ──────────────────────────────────────────────────────────
     LEGACY ALIASES — preserved so existing rules keep rendering
     unchanged during incremental migration. DO NOT introduce new
     usages of these. New rules should use the role tokens above.
     ────────────────────────────────────────────────────────── */
  --slate:           var(--ink);
  --dark:            var(--surface-inverse-deep);
  --orange:          var(--accent);
  --orange-text:     var(--accent-active); /* WCAG AA 5.98:1 on white (was --accent-hover 4.23:1 FAIL) */
  --orange-dark:     var(--accent-active);
  --orange-darkest:  var(--accent-deepest);
  --orange-on-dark:  var(--accent-on-dark);
  --orange-tint:     var(--accent-tint);
  --cream:           var(--surface-raised);
  --cream-hover:     var(--surface-sunk);
  --white:           var(--surface);
  --stone:           var(--ink-2);
  /* --muted / --muted-dark removed — zero usage across all CSS + HTML files.
     Use --ink-2 or --ink-3 directly for any future muted-text needs. */

  /* Hero padding — larger than a standard section because the hero sits
     below fixed nav (64px) and needs extra breathing above headline. 160
     top absorbs nav clearance, 100 bottom leads into stats-bar hairline. */
  --hero-pad:        160px 0 100px;
  --hero-pad-md:     120px 0 80px;
  --hero-pad-sm:     100px 0 var(--sp-7);
  --success:         var(--ok);
  --success-dark:    var(--ok-deep);
  --warning-bg:      var(--warn-tint);
  --warning-border:  var(--warn);
  --warning-text:    var(--warn-ink);

  /* Old shadow alias names (old CSS still uses these) */
  --shadow-sm:  var(--shadow-2);
  --shadow-md:  var(--shadow-3);
  --shadow-lg:  var(--shadow-4);
  --shadow-xl:  var(--shadow-5);

  /* Legacy generic transition — new rules should use the
     property-specific --transition-* tokens instead. Preserved
     because ~13 rules currently reference it. Explicit property
     list avoids the `transition: all` repaint-storm anti-pattern
     while covering every visual state currently in use. */
  --transition: color var(--duration-fast) var(--ease-out),
                background-color var(--duration-fast) var(--ease-out),
                border-color var(--duration-fast) var(--ease-out),
                box-shadow var(--duration-fast) var(--ease-out),
                opacity var(--duration-fast) var(--ease-out),
                transform var(--duration-base) var(--ease-out);
}

html {
  scroll-behavior: smooth;
  font-size: 16px;
  /* Audit round-3 2026-05-07 #10d: macOS users with "Show scroll bars:
     Always" see scrollbars take layout space; default-mode users see
     them overlay. scrollbar-gutter: stable reserves the space in both
     modes so layout doesn't shift between scrollbar-on/off states or
     when the scrollbar appears mid-page. */
  scrollbar-gutter: stable;
  /* Tell the browser this site is light-themed so UA dark-mode
     auto-inversion of inputs/scrollbars doesn't break our colour
     story. (Once a real dark-mode lands, change to "light dark"
     and the rest of the css adapts via the prefers-color-scheme
     media query.) */
  color-scheme: light;
}

/* ============================================================
   ::SELECTION — brand-orange highlight on every copy event
   ============================================================
   Default OS blue is a brand break every time a buyer copies a
   stat or a script. Tinted alpha-25 (light surfaces) and alpha-40
   (dark surfaces) so selected text stays readable across the
   cream/white/slate triad. Color-design audit 2026-05-07. */
::selection {
  background-color: var(--accent-alpha-25);
  color: var(--ink);
}
[data-bg="slate"] ::selection,
[data-bg="dark"] ::selection,
.guide-hero ::selection,
.article-hero ::selection,
.page-header ::selection,
.cta-section ::selection {
  background-color: var(--accent-alpha-40);
  color: var(--white);
}
::-moz-selection { /* Older Firefox fallback */
  background-color: var(--accent-alpha-25);
  color: var(--ink);
}

/* Section-rhythm collapse — see token block §14 for the contract.
   When two adjacent <section>s share data-bg, the second's top padding
   falls away so the visible seam is one --section-pad worth, not two. */
section[data-bg="cream"] + section[data-bg="cream"],
section[data-bg="white"] + section[data-bg="white"],
section[data-bg="slate"] + section[data-bg="slate"] {
  padding-block-start: 0;
}

/* Global "+ HST" suffix used alongside displayed prices. Moved here from
   services.css so homepage and booking can use the same visual pattern. */
.price-hst {
  font-size: 0.4em;
  font-weight: 400;
  color: var(--ink-2);
  letter-spacing: 0;
  margin-left: var(--sp-1);
  vertical-align: middle;
}

/* ============================================================
   NUMERIC TYPOGRAPHY — tabular lining figures
   ============================================================
   Financial-grade digit treatment. Tabular-nums: every digit
   occupies the same width, so $43,500 aligns vertically with
   $41,500 in math tables. Lining-nums: numerals align with
   cap-height (vs oldstyle-figures). Used on every .stat, .price,
   .amount, .value selector across the site.
   ============================================================ */
.num-tabular,
.stat-number, .stat-value,
.sidebar-stat-number,
.pricing-tier-price, .pricing-price,
.hero-card-price, .hero-card-price strong,
.problem-card-number,
.booking-card-price,
.means-number,
.stats-bar-value, .stats-bar-value-green,
.math-line .value, .math-line .label,
.price-hst,
.pr-stat-value, .pr-stat-value.warn,
.ti-stat-value, .ti-stat-value.ti-good, .ti-stat-value.ti-warn,
.payment-big-amount,
.compare-savings-amount,
.savings-callout-amount,
.savings-banner-amount,
.window-card .window-saving,
.score-gauge .num,
.figure-money,
.ev-context-row-value,
.profit-stack-total .ps-value,
/* F49 expansion: every data-bearing context gets tabular numerals */
table th, table td,
input[type="number"],
input[type="text"][inputmode="decimal"],
/* .chart-* selectors removed (audit round-3 2026-05-07 #7 — entire
   chart vocabulary was unused dead code). When chart components
   return, re-add their value-rendering selectors here. */
.count-up, .count-up-target,
.math-block .value, .article-compare-table td,
.holdback-table td, .pr-term-table td,
.pricing-tier-desc em {
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: "tnum" 1, "lnum" 1;
}

/* ============================================================
   .figure-hero — THE dramatic number per page
   ============================================================
   Use for the single "wow" number that anchors a page's argument:
     $3,100 hidden profit · 2.5% holdback · $4,000 saved on a deal.
   One per page only. Combines --fs-hero-figure scale + accent color
   + figure-money's tabular numerals.

   Pair with an eyebrow above and description below for the full
   editorial pattern:
     <div class="figure-hero-wrap">
       <p class="eyebrow">Hidden dealer profit</p>
       <p class="figure-hero"><span class="figure-money-currency">$</span>3,100</p>
       <p class="figure-hero-caption">Avoidable by reviewing every layer.</p>
     </div>
   ============================================================ */
.figure-hero {
  font-family: var(--font-heading);
  font-size: var(--fs-hero-figure);
  line-height: 0.9;
  color: var(--accent-large);
  letter-spacing: var(--ls-tight);
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: "tnum" 1, "lnum" 1;
  margin: 0;
  display: inline-flex;
  align-items: baseline;
  gap: 0.05em;
}
/* On dark heroes, swap to on-dark orange. .founder-hero added to match
   the other dark-bg hero variants — without it, a .figure-hero placed
   inside the about hero would render in --accent (light-bg color) and
   read visibly different from the same component on every other page. */
.hero .figure-hero,
.page-header .figure-hero,
.cta-section .figure-hero,
.article-cta-block .figure-hero,
.booking-hero .figure-hero,
.article-hero .figure-hero,
.guide-hero .figure-hero,
.founder-hero .figure-hero {
  color: var(--accent-on-dark);
}
.figure-hero .figure-money-currency {
  /* Bumped from 0.48em → 0.55em + opacity 0.72 → 0.86 so the "$" reads
     as part of the priced unit rather than a detached token next to a
     bigger number. Editorial-pricing precedent (Apple, Stripe) typically
     pairs "$" at ~50–60% of the figure height. */
  font-size: 0.55em;
  font-weight: 500;
  opacity: 0.86;
  transform: translateY(-0.22em);
  line-height: 1;
}
.figure-hero-wrap {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}
.figure-hero-wrap .eyebrow {
  margin: 0;
}
.figure-hero-caption {
  font-size: var(--fs-sm-plus);
  color: var(--body-text);
  line-height: 1.6;
  max-width: 40ch;
  margin: 0;
  font-style: italic;
}
.hero .figure-hero-caption,
.page-header .figure-hero-caption,
.cta-section .figure-hero-caption,
.article-cta-block .figure-hero-caption,
.booking-hero .figure-hero-caption,
.article-hero .figure-hero-caption,
.guide-hero .figure-hero-caption,
.founder-hero .figure-hero-caption {
  color: var(--on-dark);
}

/* ============================================================
   .figure-money — editorial-grade monetary display
   ============================================================
   One number per page moment. Use on THE stat ($3,100 hidden
   profit, 2.5% holdback, $499 fee). Not for inline body prices.

   Anatomy:
     <span class="figure-money">
       <span class="figure-money-currency">$</span>3,100
     </span>

   The currency glyph is de-emphasized so the number carries
   the visual weight — Bloomberg/WSJ editorial convention.
   ============================================================ */
.figure-money {
  font-family: var(--font-heading);
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: "tnum" 1, "lnum" 1;
  letter-spacing: var(--ls-tight);
  line-height: 1;
  display: inline-flex;
  align-items: baseline;
  gap: 0.05em;
}
.figure-money-currency {
  font-size: 0.55em;
  font-weight: 400;
  opacity: 0.72;
  transform: translateY(-0.15em);
  line-height: 1;
}
.figure-money-unit {
  font-size: 0.4em;
  font-weight: 400;
  margin-left: 0.25em;
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  opacity: 0.72;
  align-self: center;
}

body {
  font-family: var(--font-body);
  color: var(--slate);
  background: var(--cream);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* F50: opt into variable-font optical sizing (auto-adjust kerning per size);
     F52: enable standard ligatures (ff, fl, fi glyph pairs) site-wide. */
  font-optical-sizing: auto;
  font-feature-settings: "kern" 1, "liga" 1, "calt" 1;
}

h1, h2, h3 {
  font-family: var(--font-heading);
  line-height: 1.2;
  color: var(--slate);
}

/* ============================================================
   HEADING FAMILY VARIANTS — .heading-sans / .heading-condensed
   ============================================================
   Default headings use DM Serif Display. For specific editorial
   moments — stat displays, data sections, section callouts — a
   tighter DM Sans bold reads differently than serif and breaks
   visual monotony.

   Usage:
     <h2 class="heading-sans">Your pricing, in plain numbers</h2>
     <h3 class="heading-sans heading-condensed">Data Findings</h3>

   Apply sparingly — every 3-4 sections max. The system works
   because the serif-sans contrast is noticeable, which requires
   restraint to stay noticeable.
   ============================================================ */
.heading-sans {
  font-family: var(--font-body);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-tight);
}
.heading-condensed {
  font-stretch: 85%;        /* DM Sans variable-axis, where supported */
  letter-spacing: -0.015em;
}
.heading-uppercase {
  text-transform: uppercase;
  letter-spacing: var(--ls-wide);
  font-weight: var(--fw-bold);
}

/* ============================================================
   EDITORIAL HEADING EMPHASIS — <em> within headings
   ============================================================
   Italic phrases within display headings are THE editorial signature
   of long-form publishing (NYT Magazine, Atlantic, New Yorker). Gives
   a one-line rhythm break within a headline. Strategic — not every
   H1 should use it, but reserved for key emphasis phrases.

   Base treatment: warm accent color + italic serif. On dark heroes,
   --orange-on-dark for AAA contrast; on light bg, --accent-active.
   ============================================================ */
h1 em, h2 em, h3 em,
h1 i, h2 i, h3 i,
.hero h1 em,
.page-header h1 em,
.booking-hero h1 em,
.guide-hero h1 em {
  font-style: italic;
  font-weight: inherit;
  color: var(--accent-active);    /* light-bg default; on-dark heroes override below */
  letter-spacing: inherit;
}
/* On dark heroes, elevate to on-dark orange for AAA contrast.
   Every dark-band hero on the site goes here. The .founder-hero
   (about page) was missing — it fell through to the light-bg base
   color (--accent-active #A83D00, deep red-orange) instead of the
   peach --accent-on-dark, making the about italic visibly darker
   than every other page's italic on the same slate background.

   Extended (2026-04-30) to cover any h1/h2/h3 em inside ANY
   [data-bg="slate"] / [data-bg="dark"] section, not just heroes —
   the CTA-section h2 italic on extended-warranty-canada.html was
   landing at 2.5:1 (FAIL) because it sits in a slate CTA band that
   isn't a hero. The selector now closes that gap. */
.hero h1 em,
.page-header h1 em,
.booking-hero h1 em,
.guide-hero h1 em,
.article-hero h1 em,
.founder-hero h1 em,
[data-bg="slate"] h1 em,
[data-bg="slate"] h2 em,
[data-bg="slate"] h3 em,
[data-bg="dark"] h1 em,
[data-bg="dark"] h2 em,
[data-bg="dark"] h3 em {
  color: var(--accent-on-dark);    /* #F39455, 6.9:1 AAA on slate */
}

h4, h5, h6 {
  font-family: var(--font-body);
  font-weight: 600;
  color: var(--slate);
}

/* ============================================================
   <abbr> — semantic acronym styling
   ============================================================
   177 acronyms wrapped across 30 pages (OMVIC, PIPEDA, CASL,
   MSRP, F&I, etc.). Styled with dotted underline + help cursor
   so users see the expansion on hover. Editorial signal +
   accessibility win for screen readers.
   ============================================================ */
abbr[title] {
  /* Dotted underline signals "hover for expansion" — W3C convention.
     text-underline-offset keeps the dots from crowding the cap glyphs. */
  text-decoration: underline dotted 1.5px;
  text-decoration-color: var(--accent-alpha-40);
  text-underline-offset: 3px;
  text-decoration-skip-ink: none;
  cursor: help;
  letter-spacing: 0.02em;           /* slight tracking for all-cap acronyms */
}

/* ============================================================
   F59: MOBILE HERO TYPOGRAPHY
   ============================================================
   At narrow viewports, the display serif can overwhelm.
   Cap sizes more aggressively on mobile. */
@media (max-width: 640px) {
  .hero h1 { font-size: clamp(2rem, 8vw, 2.5rem); line-height: 1.1; }
  .page-header h1,
  .article-hero h1,
  .booking-hero h1,
  .guide-hero h1,
  .founder-hero h1 { font-size: clamp(1.75rem, 7vw, 2.25rem); }
  .hero-subtitle,
  .article-hero-deck,
  .founder-hero-subtitle { font-size: var(--fs-base); }
}

/* ============================================================
   F62: MOBILE NAV SLIDE-IN ANIMATION
   ============================================================
   Mobile nav was toggling open/closed instantly. Adding a
   smooth slide-in from the right with ease-out-expo curve.

   Class-name fix (2026-05-02): JS toggles `.open` on .mobile-nav
   and `.active` on .nav-toggle separately. The previous rules used
   .mobile-nav:not(.active)/.active — never matched, so the closed
   transform stuck while displayed and the drawer was permanently
   offset 24px right (visible page-content sliver on the left edge,
   plus the bottom mobile-cta-bar bled through that same strip).
   Renamed to `.open` so the slide-in works as designed. */
@media (max-width: 960px) {
  .mobile-nav {
    transition: transform 320ms var(--ease-out-expo),
                opacity 240ms ease-out;
  }
  .mobile-nav:not(.open) {
    transform: translateX(24px);
  }
  .mobile-nav.open {
    transform: translateX(0);
  }
  /* Cookie banner (z=9999) would otherwise float above the open drawer.
     Hide it whenever the drawer is up — the user can manage cookies
     after closing the menu. */
  body:has(.mobile-nav.open) .cookie-banner {
    display: none !important;
  }
  /* Drawer slides UNDER the .nav header. The header stays at its normal
     z-index, fully styled (glass-blur or solid-slate, whichever the page
     state has). The drawer never tries to replace or recolour it, so
     opening/closing the menu produces zero header repaint — the brand,
     toggle, and bottom-of-header divider stay pixel-stable. */
  body:has(.mobile-nav.open) .nav {
    z-index: var(--z-nav-toggle);   /* lift above drawer so toggle stays clickable */
  }
}
@media (prefers-reduced-motion: reduce) {
  .mobile-nav { transition: none; transform: none !important; }
}

/* ============================================================
   F63a: ACCESSIBILITY-BEYOND-AA — system preferences
   ============================================================
   Color-design audit 2026-05-07 found zero support for any of:
   forced-colors, prefers-contrast, prefers-reduced-transparency.
   This block ships explicit support for all three.

   forced-colors (Windows High Contrast mode):
   - Anything painted via background-image / box-shadow / outline
     is dropped by the OS in this mode. CTAs that use orange-fill
     backgrounds become invisible. Rebind to system colors.

   prefers-contrast: more:
   - Users who explicitly request higher contrast get tighter
     ink + thicker borders + un-aliased focus rings.

   prefers-reduced-transparency:
   - Users who request reduced transparency get solid replacements
     for alpha-based glassmorphism, hero glows, and frosted layers.
   ============================================================ */

/* --- forced-colors (Windows High Contrast / macOS Increase Contrast) --- */
@media (forced-colors: active) {
  /* Buttons: rebind to system colours so they survive HC mode.
     ButtonFace/ButtonText/Highlight are the canonical bindings. */
  .btn,
  .btn-primary,
  .btn-outline,
  .btn-outline-white,
  .btn-slate {
    forced-color-adjust: none;
    background-color: ButtonFace;
    color: ButtonText;
    border: 1px solid ButtonText;
  }
  .btn-primary:hover,
  .btn:hover {
    background-color: Highlight;
    color: HighlightText;
  }
  /* Cards: ensure articulation when background colors are stripped */
  .blog-card-link,
  .guide-feature-card,
  .why-card,
  .deliverable-card,
  .calc-card,
  .results-panel,
  .booking-card,
  .ask-card,
  .term-card,
  .month-card,
  .path-card {
    border: 1px solid CanvasText;
  }
  /* Focus ring rebinds to system Highlight colour */
  :focus-visible {
    outline: 2px solid Highlight;
    box-shadow: none;
  }
  /* Decorative gradient backgrounds — drop entirely so text is readable */
  .article-hero,
  .guide-hero,
  .page-header,
  .hero {
    background-image: none;
  }
  /* Drop drop-cap orange tint — first letter becomes plain text */
  .article-body.has-dropcap > p:first-of-type::first-letter,
  .guide-content.has-dropcap > p:first-of-type::first-letter,
  p.has-dropcap::first-letter {
    color: CanvasText;
  }
}

/* --- prefers-contrast: more --- */
@media (prefers-contrast: more) {
  :root {
    /* Push body + secondary inks to maximum-contrast variants */
    --body-text:        #1A1A1A;          /* was #524E47 (8.3:1 → 16:1) */
    --ink-2:            #2B2B2B;          /* was #58544F */
    --ink-3:            #3A3A3A;          /* was muted gray */
    --on-dark-default:  rgba(255, 255, 255, 0.96);  /* was 0.85 */
    --on-dark-muted:    rgba(255, 255, 255, 0.88);  /* was 0.75 */
    --border:           #ABA59B;          /* darken hairlines so they're visible */
  }
  /* Buttons get thicker ring + bolder weight */
  .btn { border-width: 2px; font-weight: 700; }
  /* Focus ring grows */
  :focus-visible {
    outline-width: 3px;
    outline-offset: 4px;
  }
}

/* --- prefers-reduced-transparency --- */
@media (prefers-reduced-transparency: reduce) {
  /* Replace alpha tints with solid surrogates that hit similar
     visual weight at full opacity. Hero glows and frosted layers
     drop to flat fills. */
  :root {
    --accent-alpha-5:    #FFF5EF;   /* solid version of rgba(232,118,43,.05) */
    --accent-alpha-7-grad: transparent; /* hero glow disabled */
    --accent-alpha-8:    #FFEEE2;
    --accent-alpha-10:   #FFE6D4;
    --accent-alpha-12:   #FFDFC8;
    --accent-alpha-15:   #FFD4B5;
    --accent-alpha-25:   #FBB791;
    --accent-alpha-30:   #FAA77B;
    --accent-alpha-35:   #F9A06F;
    --accent-alpha-40:   #F89863;
    --on-dark:           #FFFFFF;
    --on-dark-default:   #E8E5DF;
    --on-dark-muted:     #BCB7AB;
    --on-dark-dim:       #A8A398;
  }
  /* Hero radial-glow background-images become flat colors */
  .hero,
  .article-hero,
  .guide-hero,
  .page-header,
  .booking-hero,
  .founder-hero {
    background-image: none;
  }
  /* Frosted nav becomes solid */
  .nav.nav-solid,
  .nav.scrolled {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
}

/* ============================================================
   F63: EMPTY STATE SYSTEM
   ============================================================
   Components for "no results," "nothing here yet" moments. */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-4);
  text-align: center;
  padding: var(--sp-7) var(--sp-5);
  max-width: 48ch;
  margin: 0 auto;
}
.empty-state .illustration { max-width: 140px; }
.empty-state h3 {
  font-family: var(--font-heading);
  font-size: var(--fs-lg);
  margin: 0;
  color: var(--ink);
}
.empty-state p {
  font-size: var(--fs-sm-plus);
  color: var(--body-text);
  margin: 0;
  line-height: var(--lh-base);
}

/* ============================================================
   F66: SCROLL-TO-TOP SYSTEM
   ============================================================
   Audit round-2 2026-05-07 Top-10 #6: was inline-only on glossary
   at bottom: 80px (4px above the 76px mobile-cta-bar AND covered by
   the 84px cookie banner). Promoted to system component so every
   long-form page (pillar guides, blog posts) can adopt it via single
   <button class="scroll-top"> markup. Auto-init in js/main.js. */
.scroll-top {
  position: fixed;
  /* Respects iOS safe-area + mobile-cta-bar offset.
     calc with env() returns the larger value automatically when the
     bar is present — no class-flip needed. */
  bottom: calc(20px + env(safe-area-inset-bottom));
  right: 20px;
  z-index: var(--z-floating, 90);
  width: 44px;
  height: 44px;
  border-radius: var(--radius-circle);
  background: var(--slate);
  color: var(--white);
  border: 0;
  cursor: pointer;
  display: none;
  align-items: center;
  justify-content: center;
  box-shadow: var(--shadow-lg);
  transition: opacity var(--duration-fast) var(--ease-out),
              transform var(--duration-fast) var(--ease-out);
  opacity: 0;
}
.scroll-top.is-visible {
  display: flex;
  opacity: 1;
}
.scroll-top:hover {
  background: var(--slate-deep, #0F1820);
  transform: translateY(-2px);
}
.scroll-top svg {
  width: 20px;
  height: 20px;
}
/* When the mobile-cta-bar is present (sticky-cta band, ~76px tall on
   mobile), lift the scroll-top button so it doesn't overlap the bar.
   The body padding-bottom that already exists for the bar handles
   content offset; this rule moves only the floating button. */
body.has-mobile-cta-bar .scroll-top {
  bottom: calc(96px + env(safe-area-inset-bottom));
}
@media (prefers-reduced-motion: reduce) {
  .scroll-top { transition: none; }
}

/* ============================================================
   F66g: TRUST-SIGNAL COMPONENTS — content-agnostic scaffolding
   ============================================================
   Build-ahead infrastructure (2026-05-08): Holdback charges $147+
   per consultation but ships zero testimonials, case studies, or
   third-party trust signals. The barrier to deploying real social
   proof is "no CSS for it yet" — this block removes that barrier.

   When real testimonials arrive, deployment is HTML-only. The CSS
   is intentionally restrained so a single 4-star review reads as
   trustworthy rather than "design-perfect-because-fabricated."

   Components:
     .testimonial-card     — quoted prose + attribution + role
     .testimonial-grid     — 2/3-up gallery for multiple testimonials
     .case-sketch          — anonymized result sketch ("A Toronto buyer
                              avoided $4,800 in markup") — clearly
                              labeled "case sketch" not "testimonial"
     .credentials-strip    — band of factual credentials (ACC cert,
                              dealer-side experience, OMVIC-aware,
                              years in industry, consultations advised)
     .results-stat-strip   — aggregate stats from real consultations
                              ($X saved · N consultations · Y% closed
                              with better terms) */

.testimonial-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--sp-5);
  margin-top: var(--sp-7);
}

.testimonial-card {
  background: var(--surface-paper);
  background-image: var(--grad-cream-warm);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--card-pad-lg);
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  box-shadow: var(--shadow-warm);
}
.testimonial-card::before {
  content: "\201C";  /* opening curly double-quote */
  position: absolute;
  top: var(--sp-3);
  right: var(--sp-5);
  font-family: var(--font-heading);
  font-size: 4rem;
  color: var(--accent-alpha-25);
  line-height: 1;
  pointer-events: none;
}
.testimonial-quote {
  font-family: var(--font-heading);
  font-size: var(--fs-lg);
  font-style: italic;
  color: var(--ink);
  line-height: 1.45;
  margin: 0;
  position: relative;
  z-index: 1;
}
.testimonial-attribution {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--border);
  font-size: var(--fs-sm);
}
.testimonial-name {
  font-weight: var(--fw-semibold);
  color: var(--slate);
}
.testimonial-role {
  color: var(--ink-2);
}

/* Case sketch — anonymized aggregate or composite. Visually
   distinct from .testimonial-card so readers understand the
   distinction. Use .case-sketch when the content is not a real
   individual quote. */
.case-sketch {
  background: var(--white);
  background-image: var(--grad-white-soft);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent-active);
  border-radius: 0 var(--radius-lg) var(--radius-lg) 0;
  padding: var(--card-pad-lg);
  margin: var(--sp-5) 0;
}
.case-sketch-label {
  display: inline-block;
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: var(--ls-widest);
  color: var(--ink-2);
  margin-bottom: var(--sp-3);
  padding: 2px var(--sp-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--cream);
}
.case-sketch h3 {
  font-family: var(--font-heading);
  font-size: var(--fs-lg);
  margin: 0 0 var(--sp-3);
  color: var(--slate);
}
.case-sketch p {
  font-size: var(--fs-sm-plus);
  line-height: var(--lh-relaxed);
  color: var(--body-text);
  margin: 0;
}
.case-sketch p + p {
  margin-top: var(--sp-3);
}
.case-sketch-result {
  display: flex;
  align-items: baseline;
  gap: var(--sp-3);
  padding-top: var(--sp-4);
  margin-top: var(--sp-4);
  border-top: 1px dashed var(--border);
}
.case-sketch-result-figure {
  font-family: var(--font-heading);
  font-size: var(--fs-2xl);
  color: var(--accent-active);
  line-height: 1;
}
.case-sketch-result-label {
  font-size: var(--fs-sm);
  color: var(--ink-2);
}

/* Credentials strip — surfaces real factual credentials. Replaces
   the "trust me bro" gap with: ACC certification, Georgian College
   training, dealer-side franchise experience, years in industry,
   consultations advised. Use sparingly — once on homepage and
   once on services. */
.credentials-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--sp-5);
  padding: var(--sp-6) var(--sp-5);
  background: var(--cream);
  background-image: var(--grad-cream-warm);
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  margin: var(--sp-6) 0;
}
.credential-item {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  text-align: center;
  padding: 0 var(--sp-3);
  border-right: 1px solid var(--border);
}
.credential-item:last-child {
  border-right: 0;
}
.credential-figure {
  font-family: var(--font-heading);
  font-size: var(--fs-xl);
  color: var(--slate);
  line-height: 1;
  margin-bottom: var(--sp-1);
}
.credential-figure em {
  color: var(--accent-active);
  font-style: italic;
}
.credential-label {
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: var(--ls-widest);
  color: var(--ink-2);
}
.credential-detail {
  font-size: var(--fs-sm);
  color: var(--body-text);
  line-height: var(--lh-snug);
  margin-top: var(--sp-2);
}
@media (max-width: 768px) {
  .credential-item {
    border-right: 0;
    border-bottom: 1px solid var(--border);
    padding-bottom: var(--sp-4);
  }
  .credential-item:last-child {
    border-bottom: 0;
    padding-bottom: 0;
  }
}

/* Results stat strip — aggregate from real consultations.
   $X average savings · N consultations · Y% close-with-better-terms.
   Use only when the underlying numbers are real; do not fabricate. */
.results-stat-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--sp-4);
  padding: var(--sp-5);
  background: var(--slate);
  background-image: var(--grad-noise), var(--grad-slate-glow-soft);
  border-radius: var(--radius-lg);
  margin: var(--sp-7) 0;
  color: var(--white);
  position: relative;
  overflow: hidden;
}
.results-stat-item {
  text-align: center;
  padding: 0 var(--sp-3);
}
.results-stat-figure {
  font-family: var(--font-heading);
  font-size: var(--fs-2xl);
  color: var(--orange-on-dark);
  line-height: 1;
  margin-bottom: var(--sp-1);
}
.results-stat-label {
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: var(--ls-widest);
  color: var(--on-dark-muted);
}
.results-stat-detail {
  font-size: var(--fs-sm);
  color: var(--on-dark-default);
  line-height: var(--lh-snug);
  margin-top: var(--sp-2);
}

/* ============================================================
   F66j: BOOKING REASSURANCE BAND
   ============================================================
   Audit round-5 2026-05-08 #11: the practice ships "all sales
   final" by deliberate policy. The band reframes the three real
   risk-reducers (free reschedule, remote+private, written brief)
   instead of a refund pitch. Sits between the tier grid and the
   pricing note, three icons + headings + supporting copy. */
.booking-reassurance {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--sp-5);
  margin: var(--sp-7) 0 var(--sp-6);
  padding: var(--sp-6);
  background: var(--cream);
  background-image: var(--grad-cream-warm);
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-warm);
}
.booking-reassurance-item {
  display: flex;
  gap: var(--sp-3);
  align-items: flex-start;
}
.booking-reassurance-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-circle);
  background: var(--white);
  border: 1.5px solid var(--orange);
  color: var(--orange-text);
  font-size: var(--fs-lg);
  font-family: var(--font-heading);
  line-height: 1;
}
.booking-reassurance-content {
  flex: 1;
  min-width: 0;
}
.booking-reassurance-heading {
  font-family: var(--font-heading);
  font-size: var(--fs-md);
  color: var(--slate);
  margin-bottom: var(--sp-1);
  line-height: var(--lh-snug);
}
.booking-reassurance-desc {
  font-size: var(--fs-sm);
  color: var(--body-text);
  margin: 0;
  line-height: var(--lh-base);
}
@media (max-width: 768px) {
  .booking-reassurance {
    grid-template-columns: 1fr;
    gap: var(--sp-4);
  }
}

/* ============================================================
   F66h: BOOKING FLOW STEPS — "Step 2 of 3" reframing
   ============================================================
   Audit round-5 2026-05-08 #6: cal.com handoff felt like an exit.
   The 3-step indicator above the tier grid frames the booking
   moment as continuation, not departure. Visible 1→2→3 progress
   with the current step highlighted (Stripe checkout pattern). */
.booking-flow-steps {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-3);
  flex-wrap: wrap;
  margin-bottom: var(--sp-6);
  padding: var(--sp-4) var(--sp-5);
  background: var(--cream);
  background-image: var(--grad-cream-warm);
  border-radius: var(--radius-pill);
  border: 1px solid var(--border);
  font-size: var(--fs-sm);
}
.booking-flow-step {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  color: var(--ink-2);
  white-space: nowrap;
}
.booking-flow-step.is-current {
  color: var(--slate);
  font-weight: var(--fw-semibold);
}
.booking-flow-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: var(--radius-circle);
  background: var(--white);
  border: 1.5px solid var(--border);
  color: var(--ink-2);
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  font-family: var(--font-heading);
}
.booking-flow-step.is-current .booking-flow-num {
  background: var(--orange);
  border-color: var(--orange);
  color: var(--slate);
  box-shadow: 0 2px 8px var(--accent-alpha-25);
}
.booking-flow-divider {
  width: 24px;
  height: 1px;
  background: var(--border);
}
@media (max-width: 640px) {
  .booking-flow-steps {
    border-radius: var(--radius-lg);
    padding: var(--sp-3) var(--sp-4);
    gap: var(--sp-2);
  }
  .booking-flow-divider { width: 12px; }
  .booking-flow-label { font-size: var(--fs-xs); }
}

/* ============================================================
   F66i: CALCULATOR RESULTS CTA — post-result conversion ladder
   ============================================================
   Audit round-5 2026-05-08 #12: 13 of 16 calculators have no CTA
   after the result panel. Calc → booking is the highest-intent
   path on the site. This component sits at the bottom of every
   results panel: "Want this deal reviewed? Book a Deal Review".
   Single partial, 16 deployments, ~5 lines of HTML each. */
.calc-results-cta {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-5) var(--card-pad-lg);
  background: var(--cream);
  background-image: var(--grad-cream-warm);
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  border-left: 3px solid var(--orange);
  margin-top: var(--sp-6);
  flex-wrap: wrap;
  box-shadow: var(--shadow-warm);
}
.calc-results-cta-content {
  flex: 1;
  min-width: 240px;
}
.calc-results-cta-eyebrow {
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: var(--ls-widest);
  color: var(--accent-active);
  margin-bottom: var(--sp-2);
}
.calc-results-cta-heading {
  font-family: var(--font-heading);
  font-size: var(--fs-md);
  color: var(--slate);
  margin: 0 0 var(--sp-2);
  line-height: var(--lh-snug);
}
.calc-results-cta-desc {
  font-size: var(--fs-sm);
  color: var(--body-text);
  margin: 0;
  line-height: var(--lh-base);
}
.calc-results-cta .btn {
  flex-shrink: 0;
}
@media (max-width: 640px) {
  .calc-results-cta { flex-direction: column; align-items: stretch; }
  .calc-results-cta .btn { text-align: center; }
}

/* ============================================================
   F66k: BOOKING-CARD CTA — mobile sticky-to-card-bottom
   ============================================================
   Audit round-5 2026-05-08 #4b: on mobile, the booking-card CTA
   sits ~2,200px down from the hero. By the time the user reads
   the tier card, the CTA can be off-screen if they scrolled to
   read the feature list mid-card. Sticking the CTA to the
   bottom of the card (within the card's own scroll context) on
   mobile keeps the CTA in thumb-zone while reading the card. */
@media (max-width: 768px) {
  .booking-card {
    display: flex;
    flex-direction: column;
  }
  .booking-card-features {
    margin-bottom: var(--sp-4);
  }
  .booking-card-btn {
    margin-top: auto;
    width: 100%;
    text-align: center;
    /* Subtle ramp from card-bg to CTA prominence */
    box-shadow: 0 -8px 16px -8px rgba(232, 118, 43, 0.20);
  }
}

/* ============================================================
   F66f: BOOKING TIER 3-UP GRID
   ============================================================
   Audit round-4 2026-05-08 #2: tier cards previously stacked
   vertically inside .booking-tiers-wrap (max-width 760px). On
   1440px displays the user saw ONE tier per scroll-screen,
   losing side-by-side comparison. Stripe/Linear pricing pattern
   restored: 3-up grid at desktop, single column ≤900px. */
.booking-tiers-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--sp-5);
  align-items: stretch;
  margin-bottom: var(--sp-5);
}
@media (max-width: 900px) {
  .booking-tiers-grid {
    grid-template-columns: 1fr;
    max-width: var(--container-prose-md);
    margin-left: auto;
    margin-right: auto;
  }
}
/* booking.html overrides .booking-tiers-wrap to be full container
   width (was 760px); the wrapper still constrains the big-stat
   above the grid, but the grid itself spans wider. */
.booking-tiers-wrap:has(.booking-tiers-grid) {
  max-width: var(--container);
}

/* ============================================================
   F66e: UNIVERSAL CARD HOVER — warm-shadow + lift system-wide
   ============================================================
   Audit round-4 2026-05-08 Top-12 #1: prior state shipped 14 card
   variants with asymmetric hover treatments — 6 had no hover at all,
   8 had a hover but only ONE consumed --card-hover-lift. The
   --shadow-warm-lg / -xl / --shadow-accent-glow tokens were defined
   but referenced in zero rules. This single block activates the
   warm-shadow vocabulary across every elevated card on every page.

   Closes: pricing-tier flat (homepage), booking-card flat, problem-
   card flat, featured-reading missing lift, deliverable-card no
   hover, tool-card hover-only-no-lift, and 8+ other variants.

   Featured tiers (homepage --featured + booking --featured) layer
   in --shadow-accent-glow for the "winner" treatment. Stripe +
   Linear pricing precedent. */
.service-card,
.featured-reading-card,
.pricing-tier,
.pricing-card,
.booking-card,
.problem-card,
.tool-card,
.deliverable-card,
.bottom-nav-card,
.guide-feature-card,
.fi-product-card {
  transition: transform 240ms var(--ease-out-expo),
              box-shadow 280ms var(--ease-out),
              border-color 180ms ease-out;
}
.service-card:hover,
.featured-reading-card:hover,
.pricing-tier:hover,
.pricing-card:hover,
.booking-card:hover,
.problem-card:hover,
.tool-card:hover,
.deliverable-card:hover,
.bottom-nav-card:hover,
.guide-feature-card:hover,
.fi-product-card:hover,
.featured-reading-card:focus-visible,
.bottom-nav-card:focus-visible,
.guide-feature-card:focus-visible {
  transform: translateY(var(--card-hover-lift));
  box-shadow: var(--shadow-warm-lg);
  border-color: var(--accent-alpha-25);
}
/* Featured/winner treatment — additional warm-glow halo */
.pricing-tier-featured:hover,
.booking-card-featured:hover,
.pricing-card.featured:hover {
  transform: translateY(var(--card-hover-lift)) scale(1.02);
  box-shadow: var(--shadow-warm-xl), var(--shadow-accent-glow);
}

/* ============================================================
   F66d: READING PROGRESS BAR — site-wide
   ============================================================
   Promoted from blog.css 2026-05-08 so every page can ship the
   bar consistently. JS auto-init in main.js targets any page
   with #readingProgress; safely no-ops on pages without the
   markup. 4px orange line at viewport top, fills as the user
   scrolls toward the document end. */
.reading-progress {
  position: fixed;
  top: 0;
  left: 0;
  height: 4px;
  background: var(--orange);
  z-index: var(--z-progress);
  transition: width 0.1s linear;
  width: 0%;
  box-shadow: 0 1px 6px var(--accent-alpha-40);
}

/* ============================================================
   F66c: MAILTO COPY BUTTON
   ============================================================
   Audit round-2 2026-05-07 #12c. JS in main.js auto-injects
   <button class="mailto-copy">Copy</button> next to every mailto:
   link. Visual is restrained — small, tertiary — so the email
   address itself remains the primary affordance and the Copy is
   a secondary helper for desktop-without-mail-client users. */
.mailto-copy {
  margin-left: var(--sp-2);
  padding: 2px var(--sp-2);
  border: 1px solid var(--border);
  background: transparent;
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: var(--fs-2xs);
  font-weight: 600;
  color: var(--ink-2);
  text-transform: uppercase;
  letter-spacing: var(--ls-wide);
  cursor: pointer;
  transition: var(--transition);
  vertical-align: middle;
  line-height: 1.4;
}
.mailto-copy:hover {
  color: var(--orange-text);
  border-color: var(--orange);
}
.mailto-copy.is-copied {
  background: var(--ok-tint, rgba(16,185,129,0.10));
  color: var(--ok-text);
  border-color: var(--ok-text);
}
/* Footer dark-bg variant */
.footer .mailto-copy,
.cta-section .mailto-copy {
  color: var(--on-dark-default);
  border-color: var(--surface-on-dark-3);
}
.footer .mailto-copy:hover,
.cta-section .mailto-copy:hover {
  color: var(--orange-on-dark);
  border-color: var(--orange-on-dark);
}

/* ============================================================
   F66b: STATUS PILL — color-blind-safe status indicator
   ============================================================
   Audit round-2 2026-05-07 A7: small color-only status indicators
   fail WCAG 1.4.1 AND fail protanopia/deuteranopia distinction
   between --accent (orange) and --danger (rust-red). The pill
   ALWAYS emits a shape-distinct glyph (✓ ! ✕ ℹ) via ::before so
   the meaning is legible without color. Authors use:
     <span class="status-pill status-pill--ok">Verified</span>
     <span class="status-pill status-pill--warn">Caution</span>
     <span class="status-pill status-pill--danger">Avoid</span>
     <span class="status-pill status-pill--info">Note</span>     */
.status-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1half);
  padding: 3px var(--sp-2);
  border-radius: var(--radius-pill, 100px);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: var(--ls-wide);
  line-height: 1.4;
  white-space: nowrap;
}
.status-pill::before {
  font-weight: var(--fw-bold);
  font-size: 0.95em;
  line-height: 1;
  display: inline-flex;
}
.status-pill--ok {
  background: var(--ok-tint, rgba(16, 185, 129, 0.10));
  color: var(--ok-text);
}
.status-pill--ok::before { content: var(--status-ok-icon); }
.status-pill--warn {
  background: var(--warn-tint, rgba(245, 158, 11, 0.12));
  color: var(--warn-text, #92400E);
}
.status-pill--warn::before { content: var(--status-warn-icon); }
.status-pill--danger {
  background: var(--danger-tint, rgba(220, 53, 69, 0.10));
  color: var(--danger-deep);
}
.status-pill--danger::before { content: var(--status-danger-icon); }
.status-pill--info {
  background: var(--accent-alpha-10);
  color: var(--accent-active);
}
.status-pill--info::before { content: var(--status-info-icon); }

/* ============================================================
   F67: STATS BAR ELEVATION — editorial stat moments
   ============================================================
   Upgrades the homepage .stats-bar from understated sans to
   an editorial stat display. Use .stats-bar-editorial variant. */
.stats-bar-editorial {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--sp-6);
  padding: var(--sp-6);
  background: var(--surface-raised);
  border-radius: var(--radius-lg);
  text-align: center;
}
.stats-bar-editorial .stat-value {
  font-family: var(--font-heading);
  font-size: clamp(2rem, 4vw, 2.75rem);
  line-height: 1;
  /* Was --accent-large (2.83:1 on cream FAILS AA Large). Now --accent-active AAA. */
  color: var(--accent-active);
  margin: 0 0 var(--sp-2);
}
.stats-bar-editorial .stat-label {
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: var(--ls-widest);
  color: var(--ink-2);
  margin: 0;
}

/* ============================================================
   F76: FRESHNESS BADGE — "recently updated" indicator
   ============================================================
   Small green pill for posts updated within 30 days. Signals
   active maintenance without shouting. */
.freshness-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1half);
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: var(--ls-wide);
  padding: var(--sp-1) 10px;
  border-radius: var(--radius-pill);
  background: var(--ok-alpha-10);
  color: var(--ok-text);
  line-height: 1;
}
.freshness-badge::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  animation: soft-breathe 2s infinite ease-in-out;
}
@media (prefers-reduced-motion: reduce) {
  .freshness-badge::before { animation: none; }
}

/* ============================================================
   F75: BREADCRUMB COMPONENT — REMOVED
   ============================================================
   The generic .breadcrumb rules (and .breadcrumb-sep) were never
   referenced by any HTML on the site. Blog posts use the more
   specific .article-breadcrumb (defined in blog.css). Removed
   here to keep styles.css honest. If a non-blog breadcrumb is
   ever needed, recreate from .article-breadcrumb as a starting
   point.
   ============================================================ */

/* ============================================================
   F42/F43/F44: TOOL NARRATIVE SYSTEM
   ============================================================
   Calculators/tools historically read as "fields and results."
   This adds editorial narrative scaffolding:

   .tool-hero-argument   — why this tool exists (above the form)
   .tool-result-hero     — the dramatic primary number after calc
   .tool-result-narrative — "what this means for you" editorial
                             footer after results

   Usage on any tool page with existing .page-header:
     <div class="tool-hero-argument">
       <p class="tool-argument-statement">
         Monthly payments are the dealer's preferred unit of deception.
       </p>
       <p class="tool-argument-preview">
         You'll see: true APR, total interest, per-month breakdown.
       </p>
     </div>
   ============================================================ */
.tool-hero-argument {
  max-width: var(--container-prose-md);
  margin: var(--sp-5) auto var(--sp-7);
  padding: var(--sp-5) var(--sp-6);
  background: var(--surface-raised);
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
}
.tool-argument-statement {
  font-family: var(--font-heading);
  font-size: var(--fs-md);
  line-height: 1.4;
  color: var(--ink);
  font-style: italic;
  margin: 0 0 var(--sp-3);
  letter-spacing: -0.01em;
}
.tool-argument-preview {
  font-size: var(--fs-sm);
  color: var(--body-text);
  line-height: var(--lh-base);
  margin: 0;
}
.tool-argument-preview::before {
  content: "You'll see: ";
  font-weight: var(--fw-bold);
  color: var(--accent-active);
  text-transform: uppercase;
  letter-spacing: var(--ls-wide);
  font-size: 0.85em;
  margin-right: var(--sp-1);
}

/* Result hero — one big number, editorial treatment */
.tool-result-hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: var(--sp-7) var(--sp-5);
  background: var(--surface-raised);
  border-radius: var(--radius-lg);
  margin: var(--sp-5) 0;
  border: 1px solid var(--border);
  box-shadow: var(--shadow-warm), var(--shadow-2);
}
.tool-result-hero .eyebrow {
  margin-bottom: var(--sp-3);
  color: var(--accent-active);
}
.tool-result-hero .figure-hero {
  margin-bottom: var(--sp-3);
}
.tool-result-hero-caption {
  font-size: var(--fs-sm-plus);
  color: var(--body-text);
  line-height: var(--lh-base);
  max-width: 48ch;
  margin: 0;
  font-style: italic;
}

/* Post-result narrative — the "what this means" editorial block */
.tool-result-narrative {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--sp-5);
  padding: var(--sp-6);
  background: var(--surface-inverse);
  color: var(--on-dark);
  border-radius: var(--radius-lg);
  margin: var(--sp-6) 0 0;
  align-items: center;
  background-image: var(--grad-noise), var(--grad-slate-glow-soft);
}
.tool-result-narrative h3 {
  font-family: var(--font-heading);
  font-size: var(--fs-lg);
  color: var(--white);
  margin: 0 0 var(--sp-3);
  line-height: var(--lh-snug);
  letter-spacing: var(--ls-snug);
}
.tool-result-narrative h3 em {
  color: var(--accent-on-dark);
  font-style: italic;
}
.tool-result-narrative p {
  font-size: var(--fs-sm-plus);
  color: var(--on-dark);
  line-height: 1.65;
  margin: 0;
  max-width: 54ch;
}
.tool-result-narrative .btn {
  flex-shrink: 0;
}
@media (max-width: 768px) {
  .tool-result-narrative { grid-template-columns: 1fr; }
  .tool-result-narrative .btn { width: 100%; text-align: center; justify-content: center; }
}

/* ============================================================
   F48: COUNT-UP ANIMATION — scroll-triggered number reveal
   ============================================================
   Elements with .count-up get animated from 0 → data-target
   when they enter the viewport. Works alongside the scroll
   reveal system. Respects prefers-reduced-motion (shows final
   number immediately, no count).
   ============================================================ */
.count-up {
  display: inline-block;
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: "tnum" 1, "lnum" 1;
}

/* ============================================================
   F41: DISABLED STATES — canonical treatment for all controls
   ============================================================
   Covers buttons, inputs, selects, textareas, and aria-disabled
   elements. Consistent across the system instead of relying on
   browser defaults (which vary and look like bugs).
   ============================================================ */
button:disabled,
.btn:disabled,
.btn[aria-disabled="true"],
[aria-disabled="true"].btn,
input:disabled,
select:disabled,
textarea:disabled {
  opacity: 0.55;
  cursor: not-allowed;
  pointer-events: none;
  filter: saturate(0.65);
  box-shadow: none;
}
.btn:disabled,
.btn[aria-disabled="true"] {
  transform: none !important;
  filter: saturate(0.65) brightness(0.95);
}
input:disabled,
select:disabled,
textarea:disabled {
  background-color: var(--surface-sunk);
  color: var(--ink-3);
  border-color: var(--border);
}

/* ============================================================
   F51: <mark>, <q>, <kbd> — editorial semantic HTML
   ============================================================
   <mark> highlights a phrase without interrupting flow.
   <q>    inline quote with typographic marks.
   <kbd>  keyboard shortcut (reserved for future use).
   ============================================================ */
mark {
  background: linear-gradient(180deg, transparent 50%, var(--accent-alpha-25) 50%);
  color: inherit;
  padding: 0 2px;
  border-radius: 1px;
}
q {
  quotes: "\201C" "\201D" "\2018" "\2019";
  font-style: italic;
  color: var(--ink);
}
q::before { content: open-quote; color: var(--accent); margin-right: 0.05em; }
q::after  { content: close-quote; color: var(--accent); margin-left: 0.05em; }
kbd {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.9em;
  background: var(--surface-sunk);
  color: var(--ink);
  padding: 2px var(--sp-1half);
  border-radius: var(--radius-2xs);
  border: 1px solid var(--border);
  box-shadow: 0 1px 0 var(--surface-tinted-08);
}

/* ============================================================
   F53: .smallcaps — editorial small-caps utility
   ============================================================
   Used for figure attributions, legal fine-print eyebrows, and
   editorial metadata. Falls back to synthesized small-caps in
   browsers without native glyph support.
   ============================================================ */
.smallcaps {
  font-variant-caps: all-small-caps;
  font-feature-settings: "c2sc" 1, "smcp" 1;
  letter-spacing: 0.06em;
  font-weight: 500;
}

/* ============================================================
   F78: SKELETON LOADING STATES
   ============================================================
   Placeholder "ghost" blocks that breathe while async content
   loads. Uses the existing soft-breathe keyframe plus a warm
   gradient that sweeps across (F9 shimmer reuse).
   ============================================================ */
.skeleton {
  background: linear-gradient(
    90deg,
    var(--surface-raised) 0%,
    var(--surface-sunk) 50%,
    var(--surface-raised) 100%
  );
  background-size: 200% 100%;
  border-radius: var(--radius-sm);
  color: transparent !important;
  user-select: none;
  animation: btn-shimmer 1.8s linear infinite;
  min-height: 1em;
  display: inline-block;
}
.skeleton--line { width: 100%; height: 0.9em; margin: var(--sp-1) 0; }
.skeleton--title { height: 1.5em; width: 60%; }
.skeleton--block { height: 80px; width: 100%; }

@media (prefers-reduced-motion: reduce) {
  .skeleton { animation: none; background: var(--surface-sunk); }
}

/* ============================================================
   F84: RESPONSIVE TABLE — universal scroll-wrap component
   ============================================================
   Wraps any <table> wider than the mobile viewport in a
   horizontal-scroll container so the table never expands the
   page width. Apply to articles, calculators, comparison
   tables — anywhere a table appears.

   Usage:  <div class="responsive-table"><table>...</table></div>

   Aliases the established scroll-wrappers .table-wrapper,
   .table-scroll-wrapper, .holdback-table-wrap so the codebase
   has one canonical responsive-table pattern. .compare-table-wrap
   and .tco-table-card are NOT aliased — they are visual cards
   (border-radius + box-shadow + overflow:hidden) and would lose
   the radius-clip if scroll-x were forced on them.

   Defensive fallback (mobile only): any naked <table> inside an
   article-body / guide-content / .container container becomes
   block + overflow-x: auto so a missed wrapper still doesn't
   blow up the layout.
   ============================================================ */
.responsive-table,
.table-wrapper,
.table-scroll-wrapper,
.holdback-table-wrap {
  overflow-x: auto;  margin: var(--sp-4) 0 var(--sp-5);
  /* Subtle scroll-hint shadows: visible only when content overflows */
  background:
    linear-gradient(to right, var(--white) 30%, rgba(255, 255, 255, 0)) left center / 40px 100% no-repeat local,
    linear-gradient(to left,  var(--white) 30%, rgba(255, 255, 255, 0)) right center / 40px 100% no-repeat local,
    radial-gradient(farthest-side at 0    50%, rgba(0, 0, 0, 0.06), transparent) left  center / 14px 100% no-repeat scroll,
    radial-gradient(farthest-side at 100% 50%, rgba(0, 0, 0, 0.06), transparent) right center / 14px 100% no-repeat scroll;
}
.responsive-table > table,
.table-wrapper > table,
.table-scroll-wrapper > table,
.holdback-table-wrap > table {
  margin-block: 0;
}

/* Defensive fallback for naked tables that escaped the wrapper sweep.
   Mobile-only so desktop layouts (where wide tables fit) are untouched. */
@media (max-width: 768px) {
  .article-body > table,
  .guide-content > table,
  .container > table {
    display: block;
    overflow-x: auto;    max-width: 100%;
  }
}

/* ============================================================
   F85: CODE WORD-BREAK — long unbreakable strings (CSS values,
   URLs, hashes) stop forcing horizontal scroll on mobile.
   ============================================================
   Inline <code> wraps aggressively. Block <pre> still scrolls
   horizontally so formatting is preserved.
   ============================================================ */
:not(pre) > code {
  word-break: break-word;
  overflow-wrap: anywhere;
}
pre {
  overflow-x: auto;  max-width: 100%;
}
pre > code {
  word-break: normal;
  overflow-wrap: normal;
  white-space: pre;
}

/* ============================================================
   F86: NUMBER-INPUT GUARD — type=number inputs reserve space
   for spinner controls. On mobile, the reserved width can push
   the input past its container even with box-sizing: border-box.
   Reset appearance so the input honours its computed width.
   ============================================================ */
input[type="number"] {
  appearance: textfield;
  -moz-appearance: textfield;
  -webkit-appearance: textfield;
  max-width: 100%;
}
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* ============================================================
   F87: EDITORIAL DIVIDER — section punctuation
   ============================================================
   A small horizontal accent line with optional centred glyph,
   used to break up long-form copy between major sections without
   the heavy "next section starts" feel of a full-bleed band.

   Three variants:
     .editorial-divider              — plain hairline + centre dot
     .editorial-divider--accent      — orange centre glyph (§)
     .editorial-divider--double      — double rule with breathing

   Used inside <article>, .guide-content, .article-body, between
   logical chapters. Replaces the empty space between H2-blocks
   that was reading flat without illustrations. */
.editorial-divider {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-3);
  margin: var(--sp-7) 0;
  color: var(--ink-3);
}
.editorial-divider::before,
.editorial-divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border);
  max-width: 160px;
}
.editorial-divider .editorial-divider-glyph {
  font-family: var(--font-heading);
  font-size: var(--fs-md);
  color: var(--ink-3);
  line-height: 1;
  display: inline-block;
}
.editorial-divider--accent .editorial-divider-glyph {
  color: var(--accent-active);
  font-style: italic;
}
.editorial-divider--double::before,
.editorial-divider--double::after {
  background: linear-gradient(to right, transparent, var(--border) 40%, var(--border) 60%, transparent);
  height: 3px;
  background-clip: padding-box;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  background: transparent;
}
@media (max-width: 768px) {
  .editorial-divider { margin: var(--sp-6) 0; }
  .editorial-divider::before,
  .editorial-divider::after { max-width: 80px; }
}

/* ============================================================
   F88: BIG-STAT CALLOUT — the credibility punctuation
   ============================================================
   Holdback's brand sells through specific numbers — "$3,000-
   $6,000 in avoidable cost," "16× return on one session,"
   "2% Honda holdback." This component renders a single number
   at display weight + a short descriptor + an optional source
   pointer. Used to break long copy with a verifiable claim.

   Three variants:
     .big-stat                  — default cream-tinted box on white
     .big-stat--inline          — full-bleed band, slate background
     .big-stat--accent          — orange-tinted, max emphasis

   Anatomy:
     <aside class="big-stat">
       <div class="big-stat-num">$2,400</div>
       <div class="big-stat-label">Typical F&I markup per deal</div>
       <div class="big-stat-source">Based on Ontario dealer data, 2026</div>
     </aside>
   ============================================================ */
.big-stat {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-1);
  padding: var(--sp-6) var(--sp-7);
  margin: var(--sp-7) 0;
  background: var(--cream);
  border-radius: var(--radius-lg);
  border-left: 4px solid var(--accent-active);
  position: relative;
}
.big-stat-num {
  font-family: var(--font-heading);
  font-size: clamp(2.5rem, 4.5vw + 1rem, 4.25rem);
  line-height: 1;
  letter-spacing: var(--ls-tight);
  color: var(--ink);
  font-weight: 700;
}
.big-stat-num em {
  color: var(--accent-active);
  font-style: italic;
  font-weight: inherit;
}
.big-stat-label {
  font-family: var(--font-body);
  font-size: var(--fs-md);
  color: var(--body-text);
  line-height: 1.45;
  max-width: 50ch;
  margin-top: var(--sp-2);
}
.big-stat-source {
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--ls-widest);
  color: var(--ink-3);
  margin-top: var(--sp-3);
}

/* Slate-backed full-bleed variant — for "stop and notice this" moments */
.big-stat--inline {
  background: var(--slate);
  border-left-color: var(--accent);
}
.big-stat--inline .big-stat-num { color: var(--white); }
.big-stat--inline .big-stat-num em { color: var(--accent-on-dark); }
.big-stat--inline .big-stat-label { color: var(--on-dark); }
.big-stat--inline .big-stat-source { color: var(--on-dark-muted); }

/* Orange-tinted variant — peak emphasis (use sparingly, max one per page) */
.big-stat--accent {
  background: var(--accent-tint);
  border-left-color: var(--accent);
}
.big-stat--accent .big-stat-num { color: var(--accent-active); }
.big-stat--accent .big-stat-label { color: var(--accent-deepest); }

@media (max-width: 768px) {
  .big-stat { padding: var(--sp-5) var(--sp-5); margin: var(--sp-6) 0; }
}

/* ============================================================
   F90: TL;DR / KEY TAKEAWAYS — AI Overview + reader-scan device
   ============================================================
   Three jobs:
   (1) Reader value: surfaces the 3-5 highest-leverage takeaways at
       the top of every long-form page so readers who skim get the
       core value in 30 seconds.
   (2) AI Overview / LLM citation lift: paired with Article.abstract
       in JSON-LD and speakable.cssSelector targeting `.tldr`, the
       block becomes the canonical citation surface for ChatGPT
       Browse, Perplexity, Google AI Overview, and Claude.
   (3) Voice-search optimization: speakable schema makes the block
       eligible for Google Assistant / voice-surfaces. Was missing
       site-wide before this device shipped.

   Intended placement: directly after the hero, above the article body.
   Use the `<aside class="tldr">` semantic shape so screen readers
   announce it as complementary content. */
.tldr {
  /* Audit round-4 2026-05-08: was flat cream with a 4px orange rule —
     read "callout box," not "editorial moment." Now layered: warm
     cream gradient + subtle warm shadow + soft accent-glow so the
     summary feels like the curtain opening on the article. The
     orange rule remains as the editorial seal. */
  background: var(--grad-cream-warm, var(--cream));
  border-left: 4px solid var(--accent-active);
  border-radius: 0 var(--radius-lg) var(--radius-lg) 0;
  padding: var(--card-pad-lg);
  margin: 0 0 var(--sp-7);
  max-width: var(--container-prose-md);
  box-shadow: var(--shadow-warm);
}
.tldr-label {
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--accent-active);
  margin-bottom: var(--sp-3);
}
.tldr-summary {
  font-family: var(--font-heading);
  /* Audit round-2 2026-05-07 #8d: was --fs-md (18px), identical to
     .guide-content h3. Visually indistinguishable from a sub-section
     heading even though .tldr-summary is the article's lead summary.
     Bumped to --fs-lg (22px) so it reads as a higher tier than h3. */
  font-size: var(--fs-lg);
  line-height: var(--lh-snug);
  color: var(--slate);
  margin: 0 0 var(--sp-4);
}
.tldr ul {
  list-style: none;
  padding: 0;
  margin: 0;
}
.tldr li {
  position: relative;
  padding: 6px 0 6px 24px;
  font-size: var(--fs-sm-plus);
  line-height: var(--lh-relaxed);
  color: var(--ink-2);
}
.tldr li::before {
  content: '\2192';
  position: absolute;
  left: 0;
  top: 6px;
  color: var(--accent-active);
  font-weight: 700;
}
.tldr li strong { color: var(--slate); font-weight: 600; }
@media (max-width: 768px) {
  .tldr { padding: var(--sp-5); margin: 0 0 var(--sp-6); }
  .tldr-summary { font-size: var(--fs-sm-plus); }
}

/* ============================================================
   F89: SCRIPT BOX — "what to say" dialogue device
   ============================================================
   Promoted from blog.css (where it was first authored) into the
   universal sheet so pillar guides + calculator pages can use it
   without depending on the blog stylesheet. Used to render an
   exact line of buyer-side language ("I see a $599 admin fee on
   the bill of sale...") in italic on a slate background. The
   accent border on the left signals "speak this verbatim".
   ============================================================ */
.script-box {
  background: var(--dark);
  border-left: 3px solid var(--orange);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
  padding: 20px var(--sp-5);
  margin: var(--sp-7) 0;
}
.script-box-label {
  margin-bottom: var(--sp-2);
}
.script-box p {
  margin: 0;
  font-size: var(--fs-base);
  color: var(--on-dark);
  line-height: 1.65;
  font-style: italic;
}
/* Was: bold weight + on-dark color (same as body), which produced
   jarring upright-looking bold text mid-quote, breaking the "single
   verbatim line" feel of the script-box. Designer review (2026-05-07
   from rendered finance-office-guide screenshot) showed the bold
   clause reading as a different voice. Fix: keep emphasis but make
   it subtle — same weight as surrounding italic, slightly brighter
   colour, hairline underline. The script now reads as one continuous
   spoken line with a marked emphasis clause. */
.script-box p strong {
  color: var(--white);
  font-weight: inherit;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  text-decoration-color: var(--accent-on-dark);
}

/* ============================================================
   F90: MATH BLOCK — show-the-work component
   ============================================================
   Slate-backed step-by-step calculation. Promoted from blog.css
   so pillar guides + calculator hero copy can show the math
   instead of asserting it. Uses .math-line (label + value rows)
   and .math-total (final total with top-rule). Color variants
   on .value: .orange, .green, .red.
   ============================================================ */
.math-block {
  background: var(--slate);
  border-radius: var(--radius-lg);
  padding: var(--sp-6) var(--sp-6);
  margin: var(--sp-7) 0;
  color: var(--white);
}
.math-block-label {
  margin-bottom: var(--sp-4);
}
.math-line {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--sp-2) 0;
  border-bottom: 1px solid var(--surface-on-dark-2);
  font-size: var(--fs-base);
}
.math-line:last-child { border-bottom: none; }
.math-block strong { color: var(--on-dark); }
.math-line .label { color: var(--on-dark-default); }
.math-line .value { font-weight: 700; color: var(--white); }
.math-line .value.orange { color: var(--accent-on-dark); }
.math-line .value.green { color: var(--on-dark); }
.math-line .value.red { color: var(--danger); }
.math-total {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--sp-3) 0 0;
  border-top: 2px solid var(--surface-on-dark-4);
  margin-top: var(--sp-1);
  font-size: var(--fs-base);
}
.math-total .label { color: var(--white); font-weight: 600; }
.math-total .value { font-weight: 700; color: var(--white); font-size: var(--fs-md); }
.math-total .value.red { color: var(--danger); }

/* ============================================================
   F91: PULL QUOTE — editorial punctuation for long-form
   ============================================================
   Promoted from blog.css so pillar guides + about + landing
   pages can use it. Large italic serif on slate ink with an
   orange left rule. 36px margin top/bottom for breathing.
   ============================================================ */
.pull-quote {
  border-left: 3px solid var(--orange);
  padding: var(--sp-1) 0 var(--sp-1) var(--sp-5);
  margin: var(--sp-7) 0;
  hanging-punctuation: first last;
}
.pull-quote p {
  font-family: var(--font-heading);
  font-size: var(--fs-lg);
  font-style: italic;
  color: var(--slate);
  line-height: 1.4;
  margin: 0 0 var(--sp-3);
}
.pull-quote cite {
  font-size: var(--fs-sm);
  color: var(--ink-2);
  font-style: normal;
}

/* ============================================================
   F64: BRANDED LOADER — three-dot pulse in brand palette
   ============================================================
   Replaces generic Material spinner. Uses the dot-pulse
   keyframe with staggered delays for each of 3 dots.
   ============================================================ */
.loader-brand {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  padding: var(--sp-3);
}
.loader-brand span {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--accent);
  animation: dot-pulse 1.4s infinite ease-in-out both;
}
.loader-brand span:nth-child(1) { animation-delay: -0.32s; }
.loader-brand span:nth-child(2) { animation-delay: -0.16s; }
.loader-brand span:nth-child(3) { animation-delay: 0s; }
.loader-brand--on-dark span { background: var(--accent-on-dark); }

@media (prefers-reduced-motion: reduce) {
  .loader-brand span { animation: none; opacity: 0.6; }
}

/* ============================================================
   CHART VOCABULARY — DELETED (audit round-3 2026-05-07 #7)
   ============================================================
   This block (~240 lines, 22 selectors: .chart, .chart-bar-*,
   .chart-donut-*, .chart-stat-*, .chart-legend-*) was designed but
   never deployed in any HTML or JS template. Calculator pages each
   re-implement their own scoped chart styles (.ti-chart-*,
   .severity-bar-*, etc.) so a centralized vocabulary would have been
   useful — but it was never adopted, then removed.

   When a calculator needs a shared chart vocabulary, re-introduce
   here as a token block + scoped class names that reflect actual
   usage, not a speculative design system. */


/* SECTION TRANSITION BLEEDS — DELETED (audit round-4 2026-05-08)
   .section-bleed-from-cream / -white / -slate / -cream-sunk shipped
   as a 4-class system but were used in 0 HTML files. The visual goal
   (softer section seams) is now achieved at the section level via
   --grad-cream-warm / --grad-white-soft gradient fills. */

/* EDITORIAL CARD VARIANT — DELETED (audit round-4 2026-05-08)
   .surface-card--editorial + .card--editorial shipped as asymmetric-
   radius modifiers but were used in 0 HTML files. If a featured
   editorial card pattern is needed, re-introduce as a per-page
   override at deployment time. */

/* ============================================================
   UNIT ABBREVIATION — inline trailing units
   ============================================================
   For appending units to figures: "$3,100 HST+" or "60 MPH".
   Smaller, uppercase, tracked, muted. Consistent across all
   price, stat, and data-display contexts.
   ============================================================ */
.unit {
  font-size: 0.55em;
  font-weight: 500;
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--ink-2);
  margin-left: 0.4em;
  vertical-align: 0.12em;
  font-variant-numeric: normal;
}
/* On dark, shift to on-dark */
.hero .unit, .page-header .unit, .article-hero .unit,
.booking-hero .unit, .guide-hero .unit,
.founder-hero .unit,
.cta-section .unit, .article-cta-block .unit,
.footer .unit {
  color: var(--on-dark-muted);
}

/* ============================================================
   CHECKMARK VARIANTS — .check, .check--outlined, .check--bloom
   ============================================================
   Canonical checkmark system for trust-signal lists, feature
   bullets, commitment markers. Three variants:
     .check           standard filled orange circle (default)
     .check--outlined outlined ring — softer, sidebar contexts
     .check--bloom    filled with subtle orange halo — hero moments
   ============================================================ */
.check {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: var(--radius-circle);
  background: var(--accent);
  color: var(--slate);
  font-size: var(--fs-2xs);
  font-weight: 700;
  flex-shrink: 0;
}
.check--outlined {
  background: transparent;
  border: 1.5px solid var(--accent);
  color: var(--accent-active);
}
.check--bloom {
  background: var(--accent);
  color: var(--slate);
  box-shadow: 0 0 0 3px var(--accent-alpha-25),
              0 0 0 6px var(--accent-alpha-10);
}

/* ============================================================
   ORNAMENTAL DIVIDERS — .rule-*
   ============================================================
   Editorial typography furniture. Replaces plain <hr> or empty
   gap patterns with character-based separators. Used between
   section eyebrows, chapter breaks in long-form, and anywhere
   a "visual beat" is warranted.

   Usage patterns:
     <div class="rule-em-dash"></div>        — centered em-dash mark
     <div class="rule-star"></div>            ✦ brand flourish
     <div class="rule-dot"></div>             • subtle mark
     <div class="rule-slash"></div>           / minimal separator
     <div class="rule-three-star"></div>      ✦  ✦  ✦  chapter break
   ============================================================ */
.rule-em-dash,
.rule-star,
.rule-dot,
.rule-slash,
.rule-three-star {
  display: flex;
  align-items: center;
  justify-content: center;
  margin: var(--sp-6) auto;
  color: var(--accent);
  text-align: center;
  font-family: var(--font-heading);
  font-size: var(--fs-md);
  line-height: 1;
  letter-spacing: 0.4em;
  user-select: none;
}
.rule-em-dash::before { content: "—"; font-size: var(--fs-xl); letter-spacing: 0; }
.rule-star::before    { content: "✦"; font-size: var(--fs-base); }
.rule-dot::before     { content: "•"; font-size: var(--fs-md); }
.rule-slash::before   { content: "/"; font-size: var(--fs-md); opacity: 0.5; }
.rule-three-star::before { content: "✦  ✦  ✦"; font-size: var(--fs-sm-plus); }

/* Dark-bg variants */
.hero .rule-em-dash, .hero .rule-star,
.hero .rule-dot, .hero .rule-slash, .hero .rule-three-star,
.cta-section [class^="rule-"],
.footer [class^="rule-"],
.page-header [class^="rule-"],
.article-hero [class^="rule-"],
.article-cta-block [class^="rule-"],
.guide-hero [class^="rule-"],
.booking-hero [class^="rule-"],
.founder-hero [class^="rule-"] {
  color: var(--accent-on-dark);
}

/* Inline variants — for use mid-paragraph or mid-metadata */
.rule-inline {
  display: inline-block;
  margin: 0 0.5em;
  color: var(--accent);
  opacity: 0.45;
  user-select: none;
}
.rule-inline-em::before { content: "—"; }
.rule-inline-dot::before { content: "•"; }
.rule-inline-slash::before { content: "/"; }
/* On dark: lighten the underline */
.hero abbr[title], .page-header abbr[title],
.booking-hero abbr[title], .guide-hero abbr[title],
.article-hero abbr[title], .footer abbr[title],
.founder-hero abbr[title],
.cta-section abbr[title],
.callout-dark abbr[title], .article-cta-block abbr[title],
.sidebar-cta-card abbr[title] {
  text-decoration-color: rgba(243, 148, 85, 0.55);
}

p {
  color: var(--body-text);
  line-height: var(--lh-loose);
}

a {
  color: inherit;
  text-decoration: none;
  transition: var(--transition);
}

/* ============================================================
   F54: GLOBAL :focus-visible — modern dual-ring (Stripe/Linear/
   GitHub pattern). Inner halo at the surface colour, outer ring
   at the brand accent. This:
   - Gives the focus ring readable separation on any surface
   - Adds brand expression (orange ring is recognizable)
   - Stays WCAG 2.4.7 + 2.4.11 compliant
   - Is implemented via box-shadow (cheaper to animate than outline)
   The outline declaration is preserved as a fallback for browsers
   that don't honour :focus-visible (very rare in 2026).
   ============================================================ */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: var(--radius-xs);
  /* Dual-ring: 0 0 0 3px white-halo, 0 0 0 5px brand-orange */
  box-shadow: 0 0 0 3px var(--white), 0 0 0 5px var(--accent);
  transition: outline-offset var(--duration-fast) var(--ease-out),
              box-shadow var(--duration-fast) var(--ease-out);
}
/* On dark backgrounds, swap white halo for slate, accent for peach.
   Maintains the dual-ring depth on any surface. */
.hero :focus-visible,
.page-header :focus-visible,
.article-hero :focus-visible,
.booking-hero :focus-visible,
.guide-hero :focus-visible,
.cta-section :focus-visible,
.article-cta-block :focus-visible,
.callout-dark :focus-visible,
.footer :focus-visible,
.mobile-nav :focus-visible {
  outline-color: var(--accent-on-dark);
  box-shadow: 0 0 0 3px var(--slate), 0 0 0 5px var(--accent-on-dark);
}

a:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 2px;
  border-radius: var(--radius-2xs);
}

img {
  max-width: 100%;
  display: block;
}

ul {
  list-style: none;
}

/* ----------------------------------------------------------
   2. UTILITY CLASSES
   ---------------------------------------------------------- */

.container {
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 var(--sp-5);
}

.section-label {
  display: inline-block;
  margin-bottom: 14px;
}

.section-title {
  font-family: var(--font-heading);
  font-size: var(--fs-2xl-fluid);
  color: var(--slate);
  margin-bottom: var(--sp-4);
  line-height: var(--lh-snug);
  letter-spacing: var(--ls-snug);
}

.section-subtitle {
  font-size: var(--fs-md);
  color: var(--ink-2);
  max-width: 640px;
  line-height: var(--lh-loose);
}

.text-center {
  text-align: center;
}

.text-center .section-subtitle {
  margin: 0 auto;
}


.bg-white {
  background: var(--white);
}

/* ----------------------------------------------------------
   3. BUTTONS
   ---------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  /* WCAG 2.5.5 — 44px minimum touch target. 12px padding + 20px text = ~44px.
     Standardized to --sp-3 --sp-5 (12/24) from prior 14/28 off-grid values. */
  padding: var(--sp-3) var(--sp-5);
  min-height: 44px;
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: var(--fs-base);
  font-weight: 600;
  line-height: 1.2;
  cursor: pointer;
  border: 2px solid transparent;
  transition: var(--transition);
  text-decoration: none;
  white-space: nowrap;
  /* Hard-cap the button at the available container width so a long label
     (e.g. "Why Most Car Services Have a Conflict") cannot push the layout
     viewport on iPhone-mini-class screens (375px). Below 480px we let the
     label wrap onto a second line — still 44+px tall, still tappable. */
  max-width: 100%;
}
@media (max-width: 480px) {
  .btn {
    white-space: normal;
    line-height: 1.3;
  }
}

/* Primary CTA: dark slate text on orange for WCAG AA 5.34:1 contrast.
   Hover uses shadow + lift (not bg change) to preserve contrast at all states. */
.btn-primary {
  background-color: var(--orange);
  background-image: var(--grad-cta-inner);   /* subtle top-highlight/bottom-shade — button is "lit" */
  color: var(--slate);
  border-color: var(--orange);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.15) inset, 0 1px 2px var(--surface-tinted-08);
  /* Compound transition for premium hover — transform, filter, and shadow
     animate with distinct curves so the motion feels layered. */
  transition: transform 220ms var(--ease-out-expo),
    box-shadow 280ms var(--ease-out),
    filter 180ms ease-out,
    background-color var(--duration-fast) var(--ease-out);
}

.btn-primary:hover {
  background-color: var(--orange);
  background-image: var(--grad-cta-inner);
  border-color: var(--orange);
  color: var(--slate);
  /* Compound hover: lift 2px, brighten 5%, stack warm shadow.
     This is the "button is lit and lifting" premium interaction. */
  transform: translateY(var(--card-hover-lift));
  filter: brightness(1.05);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.24) inset,
    0 10px 28px var(--accent-alpha-35),
    0 2px 6px rgba(26, 35, 50, 0.10);
}

.btn-primary:active {
  /* F61: tactile mobile active — subtle scale + brightness.
     Feels like a physical press. 80ms snap-back. */
  transform: translateY(0) scale(0.98);
  filter: brightness(0.94);
  transition-duration: 80ms;
}

.btn-primary:focus-visible {
  outline: 2px solid var(--slate);
  outline-offset: 2px;
}

.btn-slate {
  background: var(--slate);
  color: var(--white);
  border-color: var(--slate);
}

.btn-slate:hover {
  background: var(--dark);
  border-color: var(--dark);
  transform: translateY(-1px);
  box-shadow: 0 6px 20px var(--shadow-slate-30);
}

.btn-outline {
  background: transparent;
  color: var(--slate);
  border-color: var(--border);
}

.btn-outline:hover {
  background: var(--slate);
  color: var(--white);
  border-color: var(--slate);
  transform: translateY(-1px);
}

/* Outline on dark — consolidated. .btn-outline-dark is an alias. */
.btn-outline-white,
.btn-outline-dark {
  background: transparent;
  color: var(--white);
  border-color: var(--on-dark-muted);
}

.btn-outline-white:hover,
.btn-outline-dark:hover {
  background: var(--surface-on-dark-4);
  border-color: var(--on-dark-default);
}

.btn:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 2px;
}

.btn-outline-white:focus-visible,
.btn-outline-dark:focus-visible {
  outline: 2px solid var(--white);
  outline-offset: 2px;
}

.btn:active {
  transform: scale(0.97);
  transition-duration: 0.05s;
}

/* (duplicate .btn-primary:active merged above into the compound hover block) */

.btn-lg {
  /* Standardized to --sp-4 --sp-7 (16/48). Was 17×36 (both off-grid).
     Retains 44px+ min-height from .btn base. */
  padding: var(--sp-4) var(--sp-7);
  font-size: var(--fs-base);
  min-height: 48px;
}

.btn-sm {
  padding: var(--sp-3) 20px;
  font-size: var(--fs-sm);
  border-radius: var(--radius-sm);
  min-height: 44px; /* WCAG 2.5.5 touch target */
  line-height: 1.25;
}

.btn-block {
  width: 100%;
  text-align: center;
  justify-content: center;
}


/* ----------------------------------------------------------
   4. NAVIGATION
   ---------------------------------------------------------- */

.nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: var(--z-nav);
  padding: var(--sp-5) 0;
  transition: background var(--duration-base) ease, backdrop-filter var(--duration-base) ease, box-shadow var(--duration-base) ease, padding var(--duration-base) ease;
}

/* Glass-blur scrolled state — semi-transparent slate with backdrop filter.
   Premium precedent: Apple, Linear, Vercel. Falls back to solid slate on
   browsers without backdrop-filter support (via the feature query below). */
.nav.scrolled {
  background: rgba(26, 35, 50, 0.78);
  -webkit-backdrop-filter: blur(16px) saturate(180%);
  backdrop-filter: blur(16px) saturate(180%);
  padding: 14px 0;
  box-shadow: 0 2px 20px var(--shadow-slate-deep-40);
}

/* Fallback: solid slate if backdrop-filter unsupported (rare on 2026 browsers) */
@supports not (backdrop-filter: blur(16px)) {
  .nav.scrolled {
    background: var(--slate);
  }
}

/* nav-solid: always solid — no transparent phase, no JS dependency */
.nav.nav-solid {
  background: var(--slate);
  padding: 14px 0;
  box-shadow: 0 2px 20px var(--shadow-slate-deep-40);
}

.nav-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 var(--sp-5);
}

.nav-logo,
.nav-brand {
  font-family: var(--font-heading);
  font-size: var(--fs-lg);
  font-weight: 400;
  color: var(--white);
  letter-spacing: -0.01em;
  text-decoration: none;
  line-height: 1;
  /* WCAG 2.5.5 — brand logo is a primary navigation link; needs 44px target. */
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  padding: 0 var(--sp-1);
}

.nav-logo span,
.nav-brand span {
  color: var(--orange);
}

.nav-links {
  display: flex;
  align-items: center;
  gap: var(--sp-6);
}

.nav-links a {
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--on-dark);
  text-decoration: none;
  transition: var(--transition-color);
  letter-spacing: 0.01em;
  /* WCAG 2.5.5 touch target (44px min). Padding gives tap zone without
     visually inflating the link row — padding is inside the existing
     nav-links gap, not on top of it. */
  padding: var(--sp-3) var(--sp-1);
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}

.nav-links a:hover {
  color: var(--white);
}

.nav-links a.active {
  color: var(--orange-on-dark);
}

.nav-cta .btn {
  /* Was 12×26 (26 off-grid). Now --sp-3 --sp-5 (12/24) matching .btn base. */
  padding: var(--sp-3) var(--sp-5);
  font-size: var(--fs-sm);
}
.nav-cta .btn:hover {
  box-shadow: 0 4px 16px var(--accent-alpha-35);
}

.nav-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: var(--sp-1half);
  cursor: pointer;
  /* WCAG 2.5.5 (44×44 minimum tap target). Was 32×26 — failed.
     Padding gives the tap zone without enlarging the visual icon. */
  min-width: 44px;
  min-height: 44px;
  padding: 10px;
  background: none;
  border: none;
  position: relative;
  z-index: var(--z-nav-toggle);
}

.nav-toggle span {
  display: block;
  width: 24px;
  height: 2px;
  background: var(--white);
  border-radius: var(--radius-2xs);
  transition: var(--transition);
}

.nav-toggle.active span:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
}

.nav-toggle.active span:nth-child(2) {
  opacity: 0;
}

.nav-toggle.active span:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
}

.mobile-nav {
  display: none;
  position: fixed;
  /* Drawer slides UNDER the existing .nav header — never replaces it.
     The .nav stays the single source of truth for the brand row + logo
     + hamburger/X toggle, so the visible header looks identical whether
     the menu is open or closed (no glass-blur vs solid-slate jump,
     no duplicate-brand-row jitter, no border-bottom appearing on open). */
  top: var(--nav-height-mobile, 72px);
  left: 0;
  right: 0;
  bottom: 0;
  background: var(--slate);
  z-index: var(--z-mobile-nav);
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-start;
  gap: 0;
  overflow-y: auto;
}

.mobile-nav.open {
  display: flex;
}

/* Drawer's own brand row is now redundant — .nav carries the brand always. */
.mobile-nav-brand {
  display: none !important;
}

.mobile-nav-brand span {
  color: var(--orange-on-dark);
}

/* Scope to non-button anchors. Without `:not(.btn)`, this rule's higher
   specificity (1,1) was beating .btn-primary's (1,0) and dragging the
   drawer's "Book My Consultation" button into white-92 instead of the
   slate-on-orange treatment used everywhere else on the site. */
.mobile-nav a:not(.btn) {
  font-family: var(--font-body);
  font-size: var(--fs-base);
  font-weight: 500;
  color: var(--on-dark);
  text-decoration: none;
  padding: 17px var(--sp-5);
  /* Was --surface-on-dark-2 (0.06 alpha), the brand row above uses
     --border-on-dark (0.10 alpha). Unify to --border-on-dark so every
     drawer separator has the same weight. */
  border-bottom: 1px solid var(--border-on-dark);
  display: block;
  transition: var(--transition-color), var(--transition-bg);
  letter-spacing: 0.01em;
}

.mobile-nav a:not(.btn):hover {
  color: var(--white);
  background: var(--surface-on-dark-1);
}

/* Nav dropdown */
.nav-dropdown > a {
  cursor: default;
}

/* Audit round-3 2026-05-07 #5: was an unreachable selector chain
   `.nav-dropdown:hover .nav-dropdown:focus-within ...` — descendant
   combinator between two `.nav-dropdown` selectors required nested
   .nav-dropdown elements. Author meant a comma. Both pseudo-classes
   now properly union, and the chain matches `.nav-dropdown-menu` as
   a descendant — the actual intended structure. */
.nav-dropdown:hover .nav-dropdown-menu a,
.nav-dropdown:focus-within .nav-dropdown-menu a {
  display: block;
  padding: 10px 20px;
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--on-dark-default);
  text-decoration: none;
  transition: var(--transition-bg), var(--transition-color);
  white-space: nowrap;
}

.nav-dropdown-menu a:hover {
  background: var(--surface-on-dark-2);
  color: var(--white);
}

.nav-dropdown-menu a.nav-deal-analyzer-link {
  color: var(--orange-on-dark) !important;
  font-weight: 600;
}

.mobile-nav a.mobile-nav-deal-analyzer {
  color: var(--orange-on-dark) !important;
  font-weight: 700 !important;
}

.mobile-nav .mobile-nav-cta {
  margin-top: auto;
  padding: var(--sp-5);
  border-top: 1px solid var(--surface-on-dark-3);
}

.mobile-nav .mobile-nav-cta .btn {
  width: 100%;
  text-align: center;
  justify-content: center;
}


/* ----------------------------------------------------------
   5. HERO SECTION
   ---------------------------------------------------------- */

.hero {
  background-color: var(--slate);
  /* Layered: noise texture (topmost) + warm radial glow + solid slate base.
     The noise adds film-grain material quality to the dark hero. */
  background-image: var(--grad-noise), var(--grad-hero-glow);
  color: var(--white);
  padding: var(--hero-pad);
  position: relative;
  overflow: hidden;
}

/* Hero carries an ambient warm glow from the upper-right — brand DNA in
   the depth system. Low alpha (peaks at 14%) keeps type as the hero and
   the composition serious, but the surface now reads as lit rather than
   flat. Editorial precedent: NYT Magazine feature heroes, The Atlantic
   longform spreads, New Yorker digital covers. */

.hero-inner {
  display: grid;
  grid-template-columns: 1fr 400px;
  gap: var(--sp-8);
  align-items: center;
  position: relative;
  z-index: var(--z-base);
}

.hero h1 {
  font-family: var(--font-heading);
  font-size: var(--fs-display);
  color: var(--white);
  line-height: var(--lh-display);
  margin-bottom: var(--sp-5);
  letter-spacing: var(--ls-tight);
}

.hero-subtitle {
  font-size: var(--fs-md);
  color: var(--on-dark-default);
  line-height: var(--lh-loose);
  max-width: 540px;
  /* Was 44px (off-grid). Now --sp-7 (48px) — lands on 4pt grid. */
  margin-bottom: var(--sp-7);
}

.hero-cta-group {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  flex-wrap: wrap;
  margin-bottom: var(--sp-7);
}

.hero-social-proof::before {
  content: '';
  display: block;
  width: 32px;
  height: 1px;
  background: var(--divider-on-dark);
  flex-shrink: 0;
}

@media (max-width: 768px) {
  .hero-social-proof::before {
    display: none;
  }
}

/* Hero Card — warm elevation: brand DNA lives in the depth system,
   not just the accent color. Orange-tinted shadow at 10% alpha creates
   the "this card is of the scene, not pasted onto it" read. */
.hero-card {
  background: var(--white);
  border-radius: var(--radius-lg);
  padding: var(--sp-6);
  box-shadow: var(--shadow-warm), var(--shadow-xl);
  color: var(--slate); border: 1px solid var(--border); /* round 9 — safety hairline so card stays visible on white sections */ }

.hero-card-title {
  font-family: var(--font-heading);
  font-size: var(--fs-md);
  color: var(--slate);
  margin-bottom: var(--sp-5);
  padding-bottom: var(--sp-4);
  border-bottom: 1px solid var(--border);
}

.hero-card-list {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  margin-bottom: var(--sp-5);
}

/* Was display:flex with gap:10px. Flex split text + inline children
   (potential <abbr>, <strong>) into separate flex items, creating
   10px gaps mid-sentence. Block layout + absolute-positioned bullet
   keeps the checkmark icon while letting text flow inline naturally. */
.hero-card-list li {
  position: relative;
  padding-left: 26px;
  font-size: var(--fs-sm);
  color: var(--slate);
  line-height: 1.5;
}

.hero-card-list li::before {
  content: '\2713';
  position: absolute;
  left: 0;
  top: 0.1em;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  background: var(--orange);
  color: var(--slate);
  border-radius: var(--radius-circle);
  font-size: var(--fs-2xs);
  font-weight: 700;
  flex-shrink: 0;
  margin-top: 1px;
}

.hero-card-price {
  /* Simplified — was a cream rectangle inside a white card (redundant
     visual layering). Now just a spacing wrapper; the button carries all
     visual weight on its own. Pulls user focus to the button, not the box. */
  text-align: center;
  padding-top: var(--sp-5);
  margin-top: var(--sp-2);
  border-top: 1px solid var(--border);
}

.hero-card-price strong {
  color: var(--slate);
}

/* ----------------------------------------------------------
   7. HOW IT WORKS / STEPS
   ---------------------------------------------------------- */

.steps-section {
  padding: var(--section-pad);
  background-color: var(--white);
  background-image: var(--grad-white-soft);
}

/* minmax(0, 1fr) instead of bare 1fr — `1fr` resolves to `minmax(auto, 1fr)`
   which expands tracks to fit child content (a wide <table>, <pre>, or
   <img>), pushing the layout beyond viewport on narrow screens. The 0
   minimum lets cards shrink to the viewport regardless of overflow content.
   Mirrors .guide-layout/.article-grid which already use this defensive form. */
.steps-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--sp-5);
  margin-top: var(--sp-7);
}

.step-card {
  position: relative;
}

/* ── Canonical numbered-step circle (audit 2026-05-06) ──
   Two variants. The whole site uses these. Six legacy variants
   (.step-number 40px, .booking-preflight-num 36px, .booking-how-num 28px
   filled, .ty-step-num 28px, .step-num cream-with-completion-state) were
   consolidated into the two below. About's .timeline-step-circle stays
   separate — it's a range-label pattern, not a step indicator. */
.step-circle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  /* Audit round-4 2026-05-08: was flat --orange — read "filled
     circle." Now gradient-filled with inner highlight + warm-glow
     shadow so the circle reads "lit ember" against the page surface.
     Inner highlight = top 35% lighter brand orange; outer glow =
     soft accent-alpha emanation. Editorial precedent: Stripe/Apple
     numbered-step indicators on pricing pages. */
  background:
    linear-gradient(180deg,
      #F39156 0%,
      var(--orange) 50%,
      #DA6A1A 100%);
  color: var(--slate);
  border-radius: var(--radius-circle);
  font-family: var(--font-heading);
  font-size: var(--fs-md);
  font-weight: 700;
  line-height: 1;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.30),
    0 4px 12px var(--accent-alpha-25),
    0 1px 2px rgba(26, 35, 50, 0.08);
}

/* Subtle variant — checklist / in-tool sequences (private-sale-guide,
   thankyou). Cream fill so the orange anchors stay scarce. */
.step-circle--subtle {
  width: 28px;
  height: 28px;
  background: var(--cream);
  color: var(--ink-2);
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  font-weight: 700;
  border: 1px solid var(--border);
}

/* Completion state — used by private-sale-guide checklist. */
.step-item.completed .step-circle--subtle,
.step-circle--subtle.is-completed {
  background: rgba(16, 185, 129, 0.1);
  color: var(--ok-text);
  border-color: rgba(16, 185, 129, 0.3);
}

/* Marketing/process variant context (steps-grid, referral, index)
   needs a bottom-margin to space the circle above its caption. */
.step-card .step-circle,
.referral-step .step-circle,
.steps-grid .step-circle {
  margin-bottom: var(--sp-5);
  box-shadow: var(--shadow-focus);
}

.step-card h3 {
  font-size: var(--fs-md);
  margin-bottom: 10px;
  color: var(--slate);
}

.step-card p {
  font-size: var(--fs-sm);
  color: var(--ink-2);
  line-height: 1.65;
}

.step-connector {
  position: absolute;
  top: var(--sp-5);
  right: -16px;
  width: 32px;
  height: 1px;
  background: var(--border);
}

.step-card:last-child .step-connector {
  display: none;
}

/* ----------------------------------------------------------
   8. SERVICES GRID / CARDS
   ---------------------------------------------------------- */

.services-section {
  padding: var(--section-pad);
  background: var(--cream);
}

.services-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--sp-5);
  margin-top: var(--sp-7);
}

.service-card {
  background: var(--white);
  border-radius: var(--radius-md);
  padding: var(--sp-6) 28px;
  border: 1px solid var(--border);
  /* Base elevation — cards have presence even at rest (was flat). */
  box-shadow: var(--shadow-1);
  transition: transform 240ms var(--ease-out-expo),
    box-shadow 280ms var(--ease-out),
    border-color 180ms ease-out;
}

.service-card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-4);
  border-color: var(--accent-alpha-25);
}

.service-icon {
  font-size: var(--fs-xl);
  margin-bottom: var(--sp-4);
  width: 56px;
  height: 56px;
  background: var(--slate);
  border-radius: var(--radius-md);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--white);
  flex-shrink: 0;
  box-shadow: 0 2px 8px var(--shadow-slate-12);
}
.service-icon svg {
  width: 26px;
  height: 26px;
}

.service-card h3 {
  font-size: var(--fs-md);
  margin-bottom: 10px;
  color: var(--slate);
}

.service-card p {
  font-size: var(--fs-sm);
  color: var(--ink-2);
  line-height: 1.65;
}

.services-cta {
  text-align: center;
  margin-top: 44px;
}

/* Service Detail Cards (services.html) */
.service-detail-card {
  background: var(--white);
  border-radius: var(--radius-lg);
  padding: 40px;
  border: 1px solid var(--border);
  margin-bottom: var(--card-pad-lg);
  transition: var(--transition);
}

.service-detail-card:hover {
  box-shadow: var(--shadow-md);
}

.service-detail-header {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-5);
  margin-bottom: var(--sp-5);
}

.service-detail-header-text h3 {
  font-size: var(--fs-lg);
  color: var(--slate);
  margin-bottom: var(--sp-2);
}

.service-detail-header-text p {
  font-size: var(--fs-base);
  color: var(--ink-2);
  line-height: 1.65;
}

.service-detail-list {
  margin-top: var(--sp-5);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* Was display:flex with gap:10px. The 12 <abbr> usages on services.html
   inside this list got flex-itemized, creating gaps mid-sentence. */
.service-detail-list li {
  position: relative;
  padding-left: 18px;
  font-size: var(--fs-sm);
  color: var(--ink-2);
  line-height: var(--lh-base);
}

.service-detail-list li::before {
  content: '\2192';
  position: absolute;
  left: 0;
  top: 0;
  color: var(--orange);
  font-weight: 700;
}

/* ----------------------------------------------------------
   9. ABOUT SECTION
   ---------------------------------------------------------- */

.about-content p {
  font-size: var(--fs-base);
  color: var(--ink-2);
  line-height: 1.8;
  margin-bottom: var(--sp-5);
}

/* Was display:flex with gap:10px. Same anti-pattern as service-detail-
   list — inline children would be flex-itemized. Block + absolute
   keeps the architecture safe for future content. */
.about-highlights li {
  position: relative;
  padding-left: 22px;
  font-size: var(--fs-sm);
  color: var(--ink-2);
  line-height: var(--lh-base);
}

.about-highlights li::before {
  content: '\2713';
  position: absolute;
  left: 0;
  top: 1px;
  color: var(--orange);
  font-weight: 700;
  font-size: var(--fs-sm);
}

.about-quote p {
  font-family: var(--font-heading);
  font-style: italic;
  font-size: var(--fs-md);
  color: var(--slate);
  line-height: 1.6;
  margin: 0;
}

.stat-card {
  background: var(--cream);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--card-pad-lg) var(--sp-5);
  text-align: center;
}

.stat-number {
  font-family: var(--font-heading);
  font-size: var(--fs-2xl);
  color: var(--slate);
  line-height: 1;
  margin-bottom: var(--sp-2);
}

.stat-label {
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--ink-2);
  line-height: 1.4;
}

/* ----------------------------------------------------------
   11. FAQ ACCORDION
   ---------------------------------------------------------- */

.faq-section {
  padding: var(--section-pad);
  background-color: var(--white);
  background-image: var(--grad-white-soft);
}
/* Audit 2026-05-08: cream variant lets pages route faq differently when
   sandwiched between whites (e.g., best-time-to-buy mid-body-cta above). */
.faq-section.faq-section--cream {
  background-color: var(--cream);
  background-image: var(--grad-cream-warm);
}

.faq-container {
  max-width: var(--container-prose-md);
  margin: var(--sp-7) auto 0;
}

.faq-item {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
  margin-bottom: var(--sp-3);
  transition: var(--transition);
}

.faq-item.active {
  border-color: var(--accent-alpha-35);
  box-shadow: 0 2px 12px var(--accent-alpha-8);
}

.faq-question {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 20px var(--sp-5);
  cursor: pointer;
  background: var(--white);
  transition: var(--transition-bg);
  gap: var(--sp-4);
  user-select: none;
  /* Button-element normalizers (faq-question is now a native <button>) */
  width: 100%;
  border: 0;
  margin: 0;
  text-align: left;
  font: inherit;
  color: inherit;
}
.faq-question:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: -2px;
  background: var(--cream);
}

.faq-question:hover {
  background: var(--cream);
}

/* Wrapper heading — strips default h3 spacing/sizing so the trigger
   button controls layout. Heading semantics are preserved for AT. */
.faq-question-heading {
  margin: 0;
  font: inherit;
  color: inherit;
}

.faq-question-text {
  font-family: var(--font-body);
  font-size: var(--fs-base);
  font-weight: 600;
  color: var(--slate);
  line-height: 1.45;
}

.faq-icon {
  width: 28px;
  height: 28px;
  border-radius: var(--radius-circle);
  background: var(--cream);
  border: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: var(--transition);
  color: var(--ink-2);
  font-size: var(--fs-md);
  line-height: 1;
}

.faq-item.active .faq-icon {
  background: var(--orange);
  border-color: var(--orange);
  color: var(--slate);
  transform: rotate(45deg);
}

.faq-answer {
  max-height: 0;
  overflow: hidden;
  padding: 0 var(--sp-5);
  background: var(--white);
  transition: max-height var(--duration-base) ease, padding var(--duration-base) ease;
}

.faq-answer p {
  font-size: var(--fs-sm);
  color: var(--ink-2);
  line-height: var(--lh-loose);
}

.faq-item.active .faq-answer {
  max-height: 600px;
  padding: 0 var(--sp-5) 20px;
}

/* ----------------------------------------------------------
   12. CTA BANNER
   ---------------------------------------------------------- */

.cta-section {
  background-color: var(--slate);
  /* Noise + lower-left warm glow for secondary dark zones */
  background-image: var(--grad-noise), var(--grad-slate-glow-soft);
  padding: var(--section-pad);
  position: relative;
  overflow: hidden;
}

/* CTA section carries the softer slate glow (from lower-left) — keeps
   continuity with hero warmth without echoing the same composition. */

.cta-inner {
  max-width: 700px;
  margin: 0 auto;
  text-align: center;
  position: relative;
  z-index: var(--z-base);
}

.cta-inner h2 {
  font-family: var(--font-heading);
  font-size: var(--fs-2xl-fluid);
  color: var(--white);
  margin-bottom: var(--sp-4);
  line-height: var(--lh-snug);
  letter-spacing: var(--ls-snug);
}

.cta-inner p {
  color: var(--on-dark-soft);
  font-size: var(--fs-base);
  margin-bottom: 36px;
  line-height: var(--lh-loose);
}

.cta-buttons {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-4);
  flex-wrap: wrap;
}

/* ----------------------------------------------------------
   13. PRICING
   ---------------------------------------------------------- */

.pricing-section {
  padding: var(--section-pad);
  /* Was cream — but preceded by 2 cream sections (deliverables + compare)
     creating a 4,453px continuous cream run with invisible section breaks.
     White breaks the rhythm: cream → cream → WHITE → slate (bootcamp). */
  background: var(--white);
}

.pricing-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--sp-5);
  align-items: start;
}

.pricing-card {
  background: var(--white);
  border-radius: var(--radius-lg);
  /* Was 36×32 (36 off-grid). Normalized to --sp-6 (32) both axes. */
  padding: var(--sp-6);
  border: 2px solid var(--border);
  position: relative;
  transition: var(--transition);
}

.pricing-card:hover {
  box-shadow: var(--shadow-lg);
}

.pricing-card.featured {
  border-color: var(--orange);
  transform: scale(1.03);
  box-shadow: var(--shadow-xl);
}

/* Pricing card "Most Popular" badge — confident ribbon with downward notch.
   Same editorial treatment as homepage's .pricing-tier-badge. */
.pricing-badge {
  position: absolute;
  top: -16px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--slate);
  color: var(--white);
  font-size: var(--fs-xs);
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: var(--sp-2) 22px;
  border-radius: var(--radius-pill);
  white-space: nowrap;
}
.pricing-badge::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  width: 0;
  height: 0;
  border-left: 8px solid transparent;
  border-right: 8px solid transparent;
  border-top: 7px solid var(--slate);
}

.pricing-card.featured .pricing-badge {
  background: var(--orange);
  box-shadow: 0 4px 14px var(--accent-alpha-35);
}
.pricing-card.featured .pricing-badge::after {
  border-top-color: var(--orange);
}

.pricing-tier-label {
  margin-bottom: var(--sp-2);
}

.pricing-card h3 {
  font-family: var(--font-heading);
  font-size: var(--fs-lg);
  color: var(--slate);
  margin-bottom: var(--sp-1half);
}

.pricing-price {
  font-family: var(--font-heading);
  font-size: var(--fs-3xl);
  color: var(--slate);
  line-height: 1;
  margin: var(--sp-4) 0 var(--sp-1);
}

.pricing-price sup {
  font-size: var(--fs-md);
  vertical-align: super;
  font-family: var(--font-body);
  font-weight: 600;
}

.pricing-duration {
  font-size: var(--fs-sm);
  color: var(--ink-2);
  margin-bottom: var(--sp-4);
}

.pricing-desc {
  font-size: var(--fs-sm);
  color: var(--ink-2);
  line-height: 1.65;
  padding-bottom: var(--sp-5);
  border-bottom: 1px solid var(--border);
  margin-bottom: var(--sp-5);
}

.pricing-features {
  display: flex;
  flex-direction: column;
  /* Was 10px gap / 28px bottom (both off-grid). Tightened to --sp-2 (8px)
     gap and --sp-6 (32px) bottom — snaps to grid AND reduces card height by
     ~14-28px per card (more space-efficient for 7-10 feature lists). */
  gap: var(--sp-2);
  margin-bottom: var(--sp-6);
}

.pricing-features li {
  /* Hanging-indent layout: text flows as a single block so inline <a>
     tags stay inline and wrap naturally. The checkmark icon is absolutely
     positioned in the left padding, outside the text flow — so it can't
     be pushed around by anchors or get misplaced mid-wrap. */
  position: relative;
  padding-left: var(--sp-5);
  font-size: var(--fs-sm);
  color: var(--ink-2);
  line-height: 1.5;
}

.pricing-features li.included {
  color: var(--slate);
}

.pricing-features li .feat-icon {
  position: absolute;
  left: 0;
  top: 0;
  font-size: var(--fs-sm);
  line-height: 1.5;
}

.pricing-features li.included .feat-icon {
  color: var(--success);
}

.pricing-features li.excluded {
  /* "Not included" signalled via strikethrough, not opacity, so text remains
     WCAG AA readable. --stone on white gives ~7:1 contrast. */
  color: var(--ink-2);
  text-decoration: line-through;
  text-decoration-color: var(--ink-2);
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}

.pricing-features li.excluded .feat-icon {
  color: var(--ink-2);
  text-decoration: none;
}

/* Shared trust-badge checkmark — used across homepage hero, CTA sections,
   and every tool/advisory page. Bumped weight + size so it reads at a glance
   on dark backgrounds (was thin and easy to miss in the trust row). */
.trust-check {
  color: var(--success);
  font-weight: 800;
  font-size: 1.05em;
  display: inline-block;
  margin-right: 2px;
}

/* Shared CTA trust-badge row — used at the bottom of every page's final CTA
   section. Canonical name is .cta-trust-row. Every page loads styles.css,
   so these rules render correctly site-wide. */
.cta-trust-row {
  display: flex;
  gap: var(--sp-5);
  flex-wrap: wrap;
  justify-content: center;
  margin-top: var(--sp-4);
}
/* Was inline-flex with gap. Defensive refactor: badge sits as natural
   inline content; the ✓ icon carries its own margin-right. Prevents
   any future <abbr> in the badge text from being flex-itemized. */
.cta-trust-badge {
  display: inline-block;
  font-size: var(--fs-sm);
  color: var(--on-dark-dim);
}
.cta-trust-badge .trust-check {
  margin-right: var(--sp-1half);
}

/* CTA contact-note — "Questions? Email ..." line at bottom of every final CTA.
   Canonical definition lives here so every page that uses this pattern renders
   correctly. Link uses --orange-on-dark (var(--orange-on-dark), WCAG AA 6.9:1 on slate) for
   clear clickability, matching nav-active/analyzer-link convention elsewhere. */
.cta-contact-note {
  font-size: var(--fs-sm);
  color: var(--on-dark-default);
  margin-top: var(--sp-5);
  margin-bottom: 0;
}

/* Closing manifesto — italic orange line that replaces "Questions? Email..."
   as the LAST visible content above the footer. Editorial sign-off that
   restates the brand thesis instead of a customer-service line. */
.closing-manifesto {
  font-family: var(--font-heading);
  font-style: italic;
  font-size: var(--fs-md);
  color: var(--orange-on-dark);
  text-align: center;
  margin: var(--sp-6) auto 0;
  max-width: 38ch;
  line-height: 1.45;
  letter-spacing: var(--ls-snug);
}
.closing-manifesto-byline {
  display: block;
  margin-top: 10px;
  font-style: normal;
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--on-dark-dim);
}
.cta-contact-link {
  color: var(--orange-on-dark);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  transition: color var(--duration-fast) ease;
}
.cta-contact-link:hover,
.cta-contact-link:focus-visible {
  color: var(--white);
}
.cta-contact-link:focus-visible {
  /* Visible focus ring on slate — WCAG 2.4.7. Was color-only (invisible state change). */
  outline: 2px solid var(--accent-on-dark);
  outline-offset: 3px;
  border-radius: var(--radius-2xs);
}

/* Add-ons */
.addon-card h3 {
  font-size: var(--fs-base);
  margin-bottom: var(--sp-1half);
  color: var(--slate);
}

.addon-price {
  font-family: var(--font-heading);
  font-size: var(--fs-lg);
  color: var(--orange-text);
  margin-bottom: 10px;
}

.addon-card p {
  font-size: var(--fs-sm);
  color: var(--ink-2);
  line-height: 1.65;
}



/* ----------------------------------------------------------
   14. PAGE HEADER (inner pages)
   ---------------------------------------------------------- */

.page-header {
  background-color: var(--slate);
  /* Audit round-4 2026-05-08 #5: --grad-hero-glow alone is anchored
     at 85% 15% with a 1100x700 ellipse — fine on full heroes (homepage,
     pillar guides), but on .page-header (~280px tall, calculator pages)
     the ellipse is mostly clipped above the viewport so the hero
     reads as a flat slate strip. Adding --grad-ember-glow (anchored
     top-center, 600x320 ellipse) creates a vertical light source
     visible on short heroes. The two-layer glow adds depth without
     overwhelming the noise pattern. */
  background-image:
    var(--grad-noise),
    var(--grad-hero-glow),
    var(--grad-ember-glow);
  padding: 120px 0 var(--sp-8);
  color: var(--white);
  position: relative;
  overflow: hidden;
}
/* Inner-page heroes (services, tools, deal-analyzer, payment-calculator,
   booking, blog index, guides index, etc.) — center the headline block so
   the layout is a balanced editorial overture instead of a left-column
   with empty right-column negative space.

   Applies to .page-header AND .booking-hero (which uses its own wrapper
   class but mirrors the same content tree). h1 + p get a max-width to
   keep the line-length editorial. */
.page-header > .container > .section-label,
.page-header > .container > h1,
.page-header > .container > p,
.page-header > .container > .micro-label,
.booking-hero > .container > .section-label,
.booking-hero > .container > h1,
.booking-hero > .container > p,
.booking-hero > .container > .micro-label {
  text-align: center;
  margin-left: auto;
  margin-right: auto;
}
.page-header > .container > h1,
.booking-hero > .container > h1 {
  max-width: 24ch;
}
.page-header > .container > p,
.booking-hero > .container > p {
  max-width: 60ch;
}

/* ============================================================
   IMAGE INFRASTRUCTURE — editorial <figure> + <picture> patterns
   ============================================================
   Ready for when commissioned photography lands. Handles:
     - aspect-ratio containers (prevents CLS on image load)
     - AVIF → WebP → JPEG fallback via <picture> element
     - lazy-loading (loading="lazy" + decoding="async")
     - figcaption semantic pairing
     - rounded corners + warm shadow elevation

   Usage:
     <figure class="editorial-figure">
       <picture>
         <source type="image/avif" srcset="/images/hero.avif">
         <source type="image/webp" srcset="/images/hero.webp">
         <img src="/images/hero.jpg" alt="..." loading="lazy" decoding="async">
       </picture>
       <figcaption>Photograph caption here.</figcaption>
     </figure>
   ============================================================ */
.editorial-figure {
  margin: var(--sp-6) 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}
.editorial-figure picture,
.editorial-figure > img {
  display: block;
  width: 100%;
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-3);
}
.editorial-figure img {
  width: 100%;
  height: auto;
  display: block;
  border-radius: var(--radius-lg);
}
.editorial-figure figcaption {
  font-size: var(--fs-sm);
  color: var(--ink-2);
  font-style: italic;
  line-height: var(--lh-base);
  max-width: 65ch;
  padding: 0 var(--sp-3);
}
.editorial-figure figcaption cite {
  font-style: normal;
  /* Was var(--ink-3) = 3.67:1 on white — AA Large only, but this is fs-xs (12px) text.
     Upgraded to var(--ink-2) = 7.5:1 AAA for compliant citation reading. */
  color: var(--ink-2);
  font-size: var(--fs-xs);
  display: block;
  margin-top: var(--sp-1);
  text-transform: uppercase;
  letter-spacing: var(--ls-wide);
}

/* Aspect-ratio variants — prevent layout shift while image loads */
.editorial-figure--16x9 picture,
.editorial-figure--16x9 > img { aspect-ratio: 16 / 9; object-fit: cover; }
.editorial-figure--4x3 picture,
.editorial-figure--4x3 > img  { aspect-ratio: 4 / 3;  object-fit: cover; }
.editorial-figure--3x4 picture,
.editorial-figure--3x4 > img  { aspect-ratio: 3 / 4;  object-fit: cover; }
.editorial-figure--1x1 picture,
.editorial-figure--1x1 > img  { aspect-ratio: 1 / 1;  object-fit: cover; }

/* Full-bleed variant — stretches to container edge for hero moments */
.editorial-figure--full-bleed {
  margin-left: calc(var(--sp-6) * -1);
  margin-right: calc(var(--sp-6) * -1);
}
.editorial-figure--full-bleed picture,
.editorial-figure--full-bleed > img {
  border-radius: 0;
}
@media (max-width: 768px) {
  .editorial-figure--full-bleed {
    margin-left: calc(var(--sp-5) * -1);
    margin-right: calc(var(--sp-5) * -1);
  }
}

/* Warm color-graded overlay — applies consistent brand grading to any image.
   Opt-in via .editorial-figure--warm; uses multiply blend + warm tint. */
.editorial-figure--warm picture,
.editorial-figure--warm > img {
  filter: saturate(1.05) contrast(1.02);
}

/* ============================================================
   ILLUSTRATION SYSTEM — .illust
   ============================================================
   SVG illustrations use currentColor so CSS can drive palette.
   Data attributes split the illustration into role-based paths:
     data-ill-role="outline"       — body lines (inherits currentColor)
     data-ill-role="accent"        — accent-colored pop moments
     data-ill-role="accent-halo"   — subtle accent-tinted halos

   Parent containers control the illustration's base color and
   accent hue via CSS custom properties. This makes a single SVG
   file render in any brand context — cream bg, slate bg, with or
   without dark mode — by changing parent classes only.
   ============================================================ */
.illustration {
  display: block;
  color: var(--ink);                    /* base outline color */
  --illust-accent: var(--accent);       /* accent hue */
  max-width: 100%;
  height: auto;
}
.illustration svg {
  width: 100%;
  height: auto;
  display: block;
}
/* Accent-role paths use the --illust-accent variable */
.illustration svg [data-ill-role="accent"] {
  color: var(--illust-accent);
}
.illustration svg [data-ill-role="accent"][fill="currentColor"] {
  fill: var(--illust-accent);
}
.illustration svg [data-ill-role="accent"][stroke="currentColor"] {
  stroke: var(--illust-accent);
}
.illustration svg [data-ill-role="accent-halo"] {
  color: var(--illust-accent);
}
.illustration svg [data-ill-role="accent-halo"][fill="currentColor"] {
  fill: var(--illust-accent);
}

/* On dark backgrounds, illustration flips: outlines white, accent peach */
.illustration--on-dark,
.hero .illustration,
.page-header .illustration,
.article-hero .illustration,
.booking-hero .illustration,
.guide-hero .illustration,
.founder-hero .illustration,
.article-cta-block .illustration,
.cta-section .illustration {
  color: var(--on-dark);
  --illust-accent: var(--accent-on-dark);
}

/* ────────────────────────────────────────────────────────────
   Size variants — content-type-driven, NOT aesthetic preference

   Each illustration earns its size based on the information density
   it carries. This rule is the single source of truth; future
   contributors pick the size class by asking "what does this
   illustration TELL the reader?", not "what looks good here?"

     --sm  (160px) → SYMBOLIC. Decorative or icon-style illustrations
                     that signal a concept without conveying new
                     information. Examples: clock (means "time/fast"),
                     magnifier ("search"), shield (brand mark),
                     decorative map (no geographic data).

     --md  (280px) → CONCEPTUAL. Illustrations that represent a
                     deliverable, process, moment, or metaphor that
                     reinforces the body content. Examples: receipt
                     (the deliverable), advisory session (scene),
                     key handoff (conversion moment), balance scale
                     (process metaphor).

     --lg  (420px) → DATA. Illustrations that convey actual
                     information the body text doesn't repeat.
                     Examples: Ontario map showing service coverage
                     (geographic data), invoice + calculator showing
                     a financial calculation as artifact.

     --xl  (560px) → HERO-ONLY. Reserved for top-of-page hero moments
                     where the illustration IS the page's primary
                     visual. Use sparingly.

   Margin is uniform across all tiers (centralized below in
   .illustration-figure) — size encodes meaning, breathing room
   does not. This prevents per-instance margin drift.
   ──────────────────────────────────────────────────────────── */
.illustration--sm { max-width: 160px; }
.illustration--md { max-width: 280px; }
.illustration--lg { max-width: 420px; }
.illustration--xl { max-width: 560px; }

/* Figure wrapper — semantic pairing with <figcaption>
   Canonical margin lives here (was previously inline per-figure,
   causing arbitrary 28/20/32/12 drift across pages). One source
   of truth. */
.illustration-figure {
  margin: var(--sp-5) auto var(--sp-3);
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  align-items: center;
}
.illustration-figure figcaption {
  font-size: var(--fs-sm);
  color: var(--ink-2);
  font-style: italic;
  line-height: 1.5;
  text-align: center;
  max-width: 40ch;
}

/* HERO NUMERAL device removed (audit 2026-05-07).
   The numbers (01–22, plus DS) were arbitrary editorial IDs assigned
   per page with no incoming reference, no index/catalog, no navigation
   anchor — pure decorative texture that raised "what does 17 mean?"
   confusion on every guide page. Editorial precedent (Monocle/NYRB)
   only works when the issue numbers ARE the navigation; here they
   weren't. Removed sitewide; the hero compositions read cleaner without
   them. The .container z-index lift below is still useful for any
   other absolutely-positioned hero decoration. */
.page-header > .container,
.guide-hero > .container { position: relative; z-index: var(--z-base); }

/* Section-label inside dark-bg page heroes. Was --orange (5.18:1 on
   slate, AA only). Upgraded to --accent-on-dark (6.9:1 AAA on slate)
   to match the other dark-context eyebrows (.script-box-label,
   .math-block-label, .founder-hero-label). */
.page-header .section-label,
.booking-hero .section-label {
  color: var(--accent-on-dark);
}

.page-header h1 {
  font-family: var(--font-heading);
  font-size: var(--fs-3xl);
  color: var(--white);
  margin-bottom: var(--sp-4);
  line-height: var(--lh-tight);
}

.page-header p {
  font-size: var(--fs-md);
  color: var(--on-dark-soft);
  max-width: 580px;
  line-height: var(--lh-loose);
}

.footer-social {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: var(--sp-5);
}
.footer-social a {
  color: var(--on-dark-default);
  transition: var(--transition-color);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
}
.footer-social a:hover {
  color: var(--orange-on-dark);
}


/* ----------------------------------------------------------
   16. DELIVERABLES
   ---------------------------------------------------------- */

.deliverables-section {
  padding: var(--section-pad);
  background-color: var(--cream);
  background-image: var(--grad-cream-warm);
}
/* Audit 2026-05-08: white variant restores rhythm when sandwiched
   between two cream sections (specialty-coverage above, compare below). */
.deliverables-section.deliverables-section--white {
  background-color: var(--white);
  background-image: var(--grad-white-soft);
}

.deliverables-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-5);
  margin-top: var(--sp-7);
}

.deliverable-card {
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--card-pad-lg);
  display: flex;
  align-items: flex-start;
  gap: var(--sp-4);
  transition: var(--transition);
}

.deliverable-card:hover {
  box-shadow: var(--shadow-md);
  border-color: var(--accent-alpha-25);
}


.deliverable-card h3 {
  font-size: var(--fs-base);
  margin-bottom: var(--sp-2);
  color: var(--slate);
}

.deliverable-card p {
  font-size: var(--fs-sm);
  color: var(--ink-2);
  line-height: 1.65;
}

/* ----------------------------------------------------------
   17. FORMS
   ---------------------------------------------------------- */


label {
  display: block;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--slate);
  margin-bottom: var(--sp-1half);
}

/* Required-field indicator. Audit round-2 2026-05-07: the prior
   pattern (orange asterisk inside label) failed WCAG 1.4.1 (color is
   the only signal) AND failed contrast (~2.6:1 on white). The orange
   asterisk is kept as visual anchor but paired with screen-reader
   text "(required)" so AT users hear the requirement. Authors use:
     <label>Name <span class="required" aria-hidden="true">*</span>
       <span class="sr-only"> (required)</span>
     </label>
   plus the input gets aria-required="true". */
label .required {
  color: var(--orange-text);  /* AA-conformant 5.98:1 (was --orange 2.6:1) */
  margin-left: 2px;
  font-weight: 700;           /* shape weight as a non-color cue */
}
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

input[type="text"],
input[type="email"],
input[type="tel"],
input[type="number"],
input[type="search"],
input[type="url"],
select,
textarea {
  width: 100%;
  padding: var(--sp-3) var(--sp-4);
  /* Audit round-2 2026-05-07: WCAG 2.5.5 minimum touch-target = 44×44.
     Prior implicit height (padding + line-height) computed to ~41-42px
     across every form on the site (calculators + booking + newsletter).
     Single rule fixes the gate everywhere. */
  min-height: 44px;
  border: 1.5px solid var(--border);
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  color: var(--slate);
  background: var(--white);
  transition: var(--transition-border);
  appearance: none;
  -webkit-appearance: none;
}

input[type="text"]:focus,
input[type="email"]:focus,
input[type="tel"]:focus,
input[type="number"]:focus,
input[type="search"]:focus,
input[type="url"]:focus,
select:focus,
textarea:focus {
  outline: none;
  border-color: var(--orange);
  box-shadow: var(--shadow-focus-sm);
}

/* Audit round-2 2026-05-07: error state was JS-driven only (.error
   class). [aria-invalid="true"] selectors were absent, so a JS path
   that flipped aria-invalid without also adding .error painted no
   visual indicator while still announcing the error to AT. Now both
   selectors share the same treatment — either path is sufficient. */
input.error, select.error, textarea.error,
input[aria-invalid="true"],
select[aria-invalid="true"],
textarea[aria-invalid="true"] {
  border-color: var(--danger-deep);
  box-shadow: 0 0 0 3px var(--danger-alpha-10);
}

/* Placeholder color — global default. Per-component overrides exist
   in deal-analyzer.css but this base ensures a readable contrast
   (--ink-2 = AA Normal on white). */
input::placeholder, textarea::placeholder {
  color: var(--ink-2);
  opacity: 1;
}


textarea {
  min-height: 120px;
  resize: vertical;
}

select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236B7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6,9 12,15 18,9'%3E%3C/polyline%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  padding-right: 40px;
  cursor: pointer;
}


/* ----------------------------------------------------------
   18. FOOTER
   ---------------------------------------------------------- */

/* ============================================================
   FOOTER — editorial 3-zone layout

   Zone 1: Nav grid          — slate, brand + link columns
   Zone 2: Newsletter band   — cream, full-width, reuses .blog-email-capture
   Zone 3: Legal bar         — deeper slate, copyright + non-affiliation

   Visual rhythm: slate → cream → deeper slate. The cream interruption
   creates a clear editorial moment (NYT Sunday Magazine precedent) and
   isolates the conversion ask from the navigation noise.
   ============================================================ */
.footer {
  background-color: var(--surface-inverse);  /* slate — Zone 1 bg */
  background-image: var(--grad-noise);        /* film grain — consistency with hero */
  /* Reduced from 64px → 40px. Stacked padding above (cta-section bottom 80px
     + footer top 40px) = 120px breathing room without feeling cavernous.
     The decorative hairline below replaces the previous featureless slate-
     on-slate transition with an editorial divider rule. */
  padding: 40px 0 0;
  color: var(--on-dark-muted);
  border-top: 1px solid var(--surface-on-dark-2);
  position: relative;
}
/* Orange hairline rule above the footer — editorial transition signal
   that visually punctuates the end of page narrative and the start of
   the footer chrome. Newspaper precedent: section-break rules on NYT,
   The Atlantic. 60% width, centered, 1px, accent. */
.footer::before {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: min(60%, 480px);
  height: 1px;
  background: linear-gradient(
    to right,
    transparent 0%,
    var(--orange) 50%,
    transparent 100%
  );
  opacity: 0.7;
}

.footer-inner {
  display: grid;
  /* Tools and Resources carry the long lists; they flow into 2 internal
     sub-columns (see rule below) to cut footer height ~40%. Brand gets
     1.3fr (logo + tagline + address + 5 social icons); Explore gets 0.6fr
     (only 3 items — doesn't need full-width). Tools & Resources get
     1.75fr each so their sub-columns have ~150px apiece. */
  grid-template-columns: 1.3fr 0.6fr 1.75fr 1.75fr;
  gap: var(--sp-7);
  padding-bottom: var(--sp-7);
  border-bottom: 1px solid var(--surface-on-dark-3);
}

/* ────────────────────────────────────────────────────────────
   Long-list compaction — "Free Tools" (11 items) and "Resources"
   (9 items) flow into 2 internal sub-columns.

   Forced `column-count: 2` (not `columns: 150px 2`) so behavior is
   deterministic regardless of exact container width. Longer items
   like "Finance Office Guide" may wrap to 2 lines in the tightest
   case — that's an acceptable trade for a 40% footer-height reduction.

   At ≤480px the override in the mobile media query reverts to 1 col
   for touch-target clarity.
   ──────────────────────────────────────────────────────────── */
.footer-inner > .footer-col:nth-child(3) ul,
.footer-inner > .footer-col:nth-child(4) ul {
  display: block;              /* override .footer-col ul flex */
  column-count: 2;
  column-gap: var(--sp-4);     /* 16px between sub-cols (tighter, gives more link width) */
  column-fill: balance;
}
.footer-inner > .footer-col:nth-child(3) ul li,
.footer-inner > .footer-col:nth-child(4) ul li {
  margin-bottom: 10px;         /* restore the flex-gap */
  break-inside: avoid;         /* never split a link across sub-columns */
}
.footer-inner > .footer-col:nth-child(3) ul li:last-child,
.footer-inner > .footer-col:nth-child(4) ul li:last-child {
  margin-bottom: 0;
}

.footer-brand .footer-logo {
  font-family: var(--font-heading);
  font-size: var(--fs-lg);
  color: var(--white);
  margin-bottom: var(--sp-3);
  display: block;
}

.footer-brand .footer-logo span {
  color: var(--orange);
}

/* .footer-tagline removed — was zero-usage dead CSS. The
   .footer-positioning rule below is the active brand line in
   the footer brand column. */

/* Stronger brand positioning paragraph — editorial one-liner about who
   Holdback is and who it serves. Replaces the lighter tagline in the
   redesigned footer brand column. */
.footer-positioning {
  font-size: var(--fs-sm-plus);         /* 15.2px — reads as "statement" not caption */
  color: var(--on-dark-default);         /* 75% white — stronger than muted */
  line-height: 1.65;
  margin-bottom: var(--sp-5);
  max-width: 280px;
}

.footer-contact-item {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-sm);
  color: var(--on-dark-dim);
  margin-bottom: var(--sp-2);
}

.footer-contact-item a {
  color: var(--on-dark-default);
  text-decoration: none;
  transition: var(--transition-color);
}

.footer-contact-item a:hover {
  color: var(--orange-on-dark);
}

.footer-col h2,
.footer-col h3 {
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--on-dark);
  margin-bottom: var(--sp-4);
  font-family: var(--font-body);
}

.footer-col ul {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.footer-col ul li a {
  font-size: var(--fs-sm);
  color: var(--on-dark-dim);
  text-decoration: none;
  transition: var(--transition-color);
}

.footer-col ul li a:hover {
  color: var(--white);
}

/* ────────────────────────────────────────────────────────────
   Zone 2: Newsletter band — cream interruption between nav and
   legal. Reuses .blog-email-capture for the form itself (see blog.css).
   This zone gives conversion one clear moment, lifted from the
   nav noise and the legal compliance.
   ──────────────────────────────────────────────────────────── */
.footer-newsletter-band {
  background: var(--surface-raised);       /* warm cream #F2EFE8 */
  padding: 56px 0;                          /* own breathing — no extra margin */
  color: var(--ink);
  /* The .footer-inner's border-bottom provides the slate/cream hairline. */
}

.footer-newsletter-inner {
  display: grid;
  grid-template-columns: 1.1fr 1fr;         /* text left, form right */
  gap: var(--sp-8);
  align-items: center;
  max-width: 960px;                          /* tighter than container — editorial feel */
  margin: 0 auto;
}

.footer-newsletter-text {
  /* Editorial text block */
}

.footer-newsletter-eyebrow {
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: var(--ls-widest);
  color: var(--accent-active);               /* muted orange — AA body compliant */
  margin: 0 0 var(--sp-3) 0;
}

.footer-newsletter-heading {
  font-family: var(--font-heading);
  font-size: clamp(1.5rem, 2.2vw + 0.5rem, 2rem);
  color: var(--ink);
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-tight);
  margin: 0 0 var(--sp-3) 0;
}

.footer-newsletter-subtext {
  font-size: var(--fs-sm-plus);
  color: var(--body-text);
  line-height: 1.65;
  margin: 0;
  max-width: 40ch;
}

/* The form container reuses .blog-email-capture but strips the card
   chrome (background, border, padding, margin) since the band itself
   carries the cream surface. */
.footer-newsletter-band .blog-email-capture {
  background: transparent;
  border-left: none;
  border-radius: 0;
  padding: 0;
  margin: 0;
}

@media (max-width: 768px) {
  .footer-newsletter-band {
    padding: 40px 0;
  }
  .footer-newsletter-inner {
    grid-template-columns: 1fr;
    gap: var(--sp-5);
  }
  .footer-newsletter-subtext {
    max-width: none;
  }
}

/* ============================================================
   EMAIL CAPTURE — reusable lead-magnet form block
   Originally a blog-only pattern (.blog-email-capture); promoted
   to a sitewide component so the footer newsletter band on every
   page receives the same form/button styling. Lives here in
   styles.css (loaded on every page) instead of blog.css (only
   loaded on /blog/* routes).
   ============================================================ */
.blog-email-capture {
  background: var(--cream);
  border-left: 4px solid var(--accent);
  border-radius: var(--radius-lg);
  padding: var(--card-pad-lg) var(--sp-6);
  margin: 40px 0;
}
.blog-email-capture-text h3 {
  font-family: var(--font-heading);
  font-size: var(--fs-md);
  color: var(--slate);
  margin: 0 0 var(--sp-2);
  line-height: 1.3;
  letter-spacing: 0;
}
.blog-email-capture-text p {
  font-size: var(--fs-sm-plus);
  color: var(--body-text);
  line-height: var(--lh-base);
  margin: 0 0 var(--sp-4);
}
.blog-email-capture-form {
  display: flex;
  gap: var(--sp-2);
  align-items: stretch;
  margin-bottom: 10px;
  flex-wrap: wrap;
  position: relative;
}
.blog-email-capture-form input[type="email"] {
  flex: 1 1 260px;
  padding: var(--sp-3) 14px;
  border: 1.5px solid var(--border);
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: var(--fs-sm-plus);
  background: var(--white);
  color: var(--slate);
  min-height: 44px;
  box-sizing: border-box;
  transition: border-color 0.15s;
}
.blog-email-capture-form input[type="email"]:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: var(--shadow-focus-sm);
}
.blog-email-capture-form button[type="submit"] {
  padding: var(--sp-3) 22px;
  background: var(--accent);
  color: var(--slate);
  border: none;
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: var(--fs-sm-plus);
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  min-height: 44px;
  transition: transform var(--duration-fast), box-shadow var(--duration-fast);
}
.blog-email-capture-form button[type="submit"]:hover {
  background: var(--accent);
  color: var(--slate);
  transform: translateY(-1px);
  box-shadow: var(--shadow-accent);
}
.blog-email-capture-form button[type="submit"]:disabled {
  opacity: 0.6;
  cursor: default;
  transform: none;
  box-shadow: none;
}
.blog-email-capture-form button[type="submit"]:focus-visible {
  outline: 2px solid var(--slate);
  outline-offset: 2px;
}
.blog-email-capture-consent {
  font-size: var(--fs-xs);
  color: var(--ink-2);
  line-height: 1.5;
  margin: 0;
}
.blog-email-capture-consent a {
  color: var(--accent-active);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.blog-email-capture-consent a:hover {
  color: var(--slate);
}
.blog-email-capture-success {
  display: none;
  color: var(--ok-text);
  font-weight: 600;
  font-size: var(--fs-sm-plus);
  padding: var(--sp-1) 0;
}
.blog-email-capture-success.visible {
  display: block;
}
.blog-email-capture-form.hidden,
.blog-email-capture-consent.hidden {
  display: none;
}

@media (max-width: 640px) {
  .blog-email-capture {
    padding: 22px 20px;
    margin: var(--sp-6) 0;
  }
  .blog-email-capture-text h3 {
    font-size: var(--fs-md);
  }
  .blog-email-capture-form button[type="submit"] {
    width: 100%;
  }
}

/* ────────────────────────────────────────────────────────────
   Zone 3: Legal bar — deeper slate, non-affiliation disclosure
   ──────────────────────────────────────────────────────────── */
.footer-legal-bar {
  background-color: var(--surface-inverse-deep);  /* warmed #0F1828 */
  background-image: var(--grad-noise);
  border-top: 1px solid var(--surface-on-dark-2);
}

.footer-bottom {
  padding: 22px 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--sp-3);
}

.footer-copy {
  font-size: var(--fs-sm);
  color: var(--on-dark-muted);
  margin: 0;
  line-height: 1.6;
}

/* Non-affiliation disclosure — sits next to copyright. Typographically
   equal weight but separated visually with the divider character. */
.footer-disclosure {
  color: var(--on-dark-dim);
}

.footer-legal {
  display: flex;
  gap: var(--sp-5);
}

.footer-legal a {
  font-size: var(--fs-sm);
  color: var(--on-dark-muted);
  text-decoration: none;
  transition: var(--transition-color);
}

.footer-legal a:hover {
  color: var(--on-dark-muted);
}

/* ----------------------------------------------------------
   19. FADE-IN ANIMATION
   ---------------------------------------------------------- */

/* ============================================================
   SCROLL REVEAL SYSTEM — .reveal-up
   ============================================================
   Pattern: content is visible by default (no-JS safe, SEO-safe).
   JavaScript adds .is-hidden on page load, then observes; when
   scrolled into view, .is-revealed triggers the transition.

   This guarantees:
     - Non-JS users see all content immediately
     - Reduced-motion users see all content (JS skips hiding)
     - Old browsers (no IntersectionObserver) see all content
     - Crawlers/SEO see all content
     - Modern browsers with JS + full motion get the choreography

   Stagger supported via data-reveal-delay attribute (0-500ms). */
.reveal-up {
  /* No declarations by default — content is visible. */
}
.reveal-up.is-hidden {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity var(--duration-reveal) var(--ease-out-expo),
    transform var(--duration-reveal) var(--ease-out-expo);
  transition-delay: var(--reveal-delay, 0ms);
  will-change: opacity, transform;
}
.reveal-up.is-hidden.is-revealed {
  opacity: 1;
  transform: translateY(0);
}
/* Stagger helpers — apply via data-reveal-delay attribute (F47: 60ms base, capped 300ms) */
.reveal-up[data-reveal-delay="60"]  { --reveal-delay: 60ms; }
.reveal-up[data-reveal-delay="120"] { --reveal-delay: 120ms; }
.reveal-up[data-reveal-delay="180"] { --reveal-delay: 180ms; }
.reveal-up[data-reveal-delay="240"] { --reveal-delay: 240ms; }
.reveal-up[data-reveal-delay="300"] { --reveal-delay: 300ms; }
/* Backward-compat for any hardcoded old values */
.reveal-up[data-reveal-delay="80"]  { --reveal-delay: 80ms; }
.reveal-up[data-reveal-delay="160"] { --reveal-delay: 160ms; }
.reveal-up[data-reveal-delay="320"] { --reveal-delay: 320ms; }
.reveal-up[data-reveal-delay="400"] { --reveal-delay: 400ms; }

/* ============================================================
   NAMED KEYFRAME LIBRARY — reusable motion primitives
   ============================================================
   Each keyframe is (a) short (<2s), (b) respects reduced motion
   via the global catch-all at the bottom of this file, (c) used
   in one or more documented components.
   ============================================================ */

/* Dot-pulse — for loading/pending states on form submits */
@keyframes dot-pulse {
  0%, 80%, 100% { opacity: 0.25; transform: scale(0.85); }
  40%            { opacity: 1.00; transform: scale(1.10); }
}

/* Button shimmer — subtle highlight sweep on primary CTA */
@keyframes btn-shimmer {
  0%   { background-position: -180% 0; }
  100% { background-position:  280% 0; }
}

/* Number count-up — scroll-triggered stat reveal */
@keyframes number-fade-up {
  0%   { opacity: 0; transform: translateY(12px); }
  100% { opacity: 1; transform: translateY(0); }
}

/* Underline draw — hover state on links (alt to background-size animation) */
@keyframes underline-draw {
  0%   { transform: scaleX(0); transform-origin: left; }
  100% { transform: scaleX(1); transform-origin: left; }
}

/* Subtle breathing — for "live" badges (e.g., "Live now", "Available") */
@keyframes soft-breathe {
  0%, 100% { opacity: 1.0; }
  50%      { opacity: 0.5; }
}

/* Audit round-4 2026-05-08 #9: idle btn-breathe on the primary CTA in
   hero / cta-section / booking-card-featured — the button gently
   pulses its warm shadow so the page feels alive at rest. Apple,
   Linear, Stripe pattern. Stops on prefers-reduced-motion. */
@keyframes btn-breathe {
  0%, 100% {
    box-shadow:
      0 1px 0 rgba(255,255,255,0.16) inset,
      0 1px 2px var(--surface-tinted-08);
  }
  50% {
    box-shadow:
      0 1px 0 rgba(255,255,255,0.20) inset,
      0 4px 16px var(--accent-alpha-25);
  }
}
.hero .btn-primary,
.cta-section .btn-primary,
.booking-card-featured .btn-primary {
  animation: btn-breathe var(--duration-cta-breathe, 4500ms) var(--ease-in-out) infinite;
}
.hero .btn-primary:hover,
.cta-section .btn-primary:hover,
.booking-card-featured .btn-primary:hover {
  /* Stop breathing on hover — the rich hover treatment takes over. */
  animation: none;
}
@media (prefers-reduced-motion: reduce) {
  .hero .btn-primary,
  .cta-section .btn-primary,
  .booking-card-featured .btn-primary {
    animation: none;
  }
}

/* Audit round-4 2026-05-08 #11: --ease-spring deployed on the
   handful of micro-interactions where a gentle overshoot reads as
   premium polish. faq-icon rotate (+ → ×), mailto-copy copied
   feedback, scroll-top hover lift. */
.faq-icon {
  transition: transform 320ms var(--ease-spring),
              background-color 200ms ease;
}
.mailto-copy {
  transition: color var(--duration-fast) var(--ease-out),
              border-color var(--duration-fast) var(--ease-out),
              background-color 220ms var(--ease-spring);
}
.scroll-top:hover {
  transition: background var(--duration-fast) var(--ease-out),
              transform 280ms var(--ease-spring);
}

/* ============================================================
   LOADING STATES — .btn.is-loading, .is-sending
   ============================================================
   When a form submit or async action is in-flight, swap the
   button label with a dot-pulse animation. Respects reduced
   motion (dots still visible, no pulse). */
/* Audit round-2 2026-05-07: [aria-busy="true"] mirror added so any
   call site that flips the standard ARIA attribute (instead of adding
   .is-loading/.is-sending classes) gets identical visual treatment.
   AT users get a "busy" announcement automatically when aria-busy is
   set; visual users now get the same dot-pulse without authors having
   to remember the .is-loading class. */
.btn.is-loading,
.btn.is-sending,
.btn[aria-busy="true"] {
  color: transparent !important;
  position: relative;
  pointer-events: none;
}
.btn.is-loading::after,
.btn.is-sending::after,
.btn[aria-busy="true"]::after {
  content: "";
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--slate);
  /* font-size here is a LAYOUT dimension (controls inline-flex line-height
     for the dot row), NOT a typography choice. Don't tokenize. */
  font-size: 20px;
  letter-spacing: 0.2em;
  background-image: radial-gradient(circle, currentColor 40%, transparent 42%);
  background-size: 8px 8px;
  background-position: 30% 50%, 50% 50%, 70% 50%;
  background-repeat: no-repeat;
  /* Three dots: use pseudo-content with inline flex */
}

/* Simpler, more robust: use three span children with CSS animation */
.btn-loading-dots {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-1half);
  position: absolute;
  inset: 0;
}
.btn-loading-dots span {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--slate);
  animation: dot-pulse 1.4s infinite ease-in-out both;
}
.btn-primary .btn-loading-dots span { background: var(--slate); }
.btn-slate .btn-loading-dots span    { background: var(--white); }
.btn-loading-dots span:nth-child(1) { animation-delay: -0.32s; }
.btn-loading-dots span:nth-child(2) { animation-delay: -0.16s; }
.btn-loading-dots span:nth-child(3) { animation-delay: 0s; }

.fade-in {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.6s ease, transform 0.6s ease;
}

.fade-in.visible {
  opacity: 1;
  transform: translateY(0);
}

.fade-in-delay-1 { transition-delay: 0.1s; }
.fade-in-delay-2 { transition-delay: var(--duration-fast); }
.fade-in-delay-3 { transition-delay: var(--duration-base); }

/* ----------------------------------------------------------
   20. PRICING FAQ
   ---------------------------------------------------------- */

/* .pricing-faq-section removed — not used anywhere in HTML (dead CSS) */

/* ----------------------------------------------------------
   21. BOOKING PAGE
   ---------------------------------------------------------- */

.booking-hero {
  background-color: var(--slate);
  background-image: var(--grad-noise), var(--grad-hero-glow);
  padding: 120px 0 var(--sp-8);
  color: var(--white);
  position: relative;
  overflow: hidden;
}

.booking-hero .step-label {
  display: inline-block;
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--orange);
  background: var(--accent-alpha-12);
  border: 1px solid var(--accent-alpha-25);
  padding: var(--sp-1half) 14px;
  border-radius: var(--radius-pill);
  margin-bottom: var(--sp-4);
}

.booking-hero h1 {
  font-family: var(--font-heading);
  font-size: var(--fs-3xl);
  color: var(--white);
  margin-bottom: var(--sp-3);
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-snug);
}

.booking-hero p {
  font-size: var(--fs-base);
  color: var(--on-dark-muted);
  max-width: 540px;
  line-height: var(--lh-loose);
}


.booking-sidebar-card h3 {
  font-size: var(--fs-base);
  color: var(--slate);
  margin-bottom: 14px;
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}


/* ----------------------------------------------------------
   22. THANK YOU PAGE
   ---------------------------------------------------------- */


.ty-main {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 80px var(--sp-5);
}

.ty-card {
  background: var(--white);
  border-radius: var(--radius-xl);
  padding: 56px var(--sp-7);
  max-width: 640px;
  width: 100%;
  text-align: center;
  box-shadow: var(--shadow-xl);
  border: 1px solid var(--border);
}

.ty-icon {
  width: 72px;
  height: 72px;
  background: var(--orange);
  border-radius: var(--radius-circle);
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto 28px;
  color: var(--slate);
  font-size: var(--fs-xl);
  box-shadow: 0 8px 24px var(--accent-alpha-30);
}

.ty-card h1 {
  font-size: var(--fs-2xl);
  color: var(--slate);
  margin-bottom: var(--sp-3);
}

.ty-card .ty-subtitle {
  font-size: var(--fs-base);
  color: var(--ink-2);
  line-height: var(--lh-loose);
  margin-bottom: 40px;
  max-width: 440px;
  margin-left: auto;
  margin-right: auto;
}

.ty-steps {
  text-align: left;
  margin-bottom: 36px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
}

.ty-step {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-4);
  padding: var(--sp-4) 20px;
  border-bottom: 1px solid var(--border);
}

.ty-step:last-child {
  border-bottom: none;
}

/* .ty-step-num removed — migrated to .step-circle--subtle (audit 2026-05-06) */

.ty-step-content h4 {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--slate);
  margin-bottom: 3px;
}

.ty-step-content p {
  font-size: var(--fs-sm);
  color: var(--ink-2);
  line-height: var(--lh-base);
  margin: 0;
}

.ty-cta-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  margin-bottom: var(--sp-6);
  flex-wrap: wrap;
}

.ty-social {
  border-top: 1px solid var(--border);
  padding-top: var(--sp-5);
}

.ty-social p {
  font-size: var(--fs-sm);
  color: var(--ink-2);
  margin-bottom: 14px;
}

.ty-social-links {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-4);
}

.ty-social-links a {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--slate);
  text-decoration: none;
  padding: var(--sp-2) var(--sp-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  transition: var(--transition);
}

.ty-social-links a:hover {
  background: var(--cream);
  border-color: var(--ink-2);
}

/* ----------------------------------------------------------
   23. RESPONSIVE BREAKPOINTS
   ---------------------------------------------------------- */

@media (max-width: 960px) {
  .hero-inner {
    grid-template-columns: 1fr;
    gap: var(--sp-7);
  }

  .hero-card {
    max-width: 480px;
  }

  .footer-inner {
    grid-template-columns: 1fr 1fr;
    gap: 36px;
  }


}

@media (max-width: 768px) {
  :root {
    --section-pad: 64px 0;
  }

  .nav-links,
  .nav-cta {
    display: none;
  }

  .nav-toggle {
    display: flex;
  }

  .hero {
    padding: 110px 0 60px;
  }

  .steps-grid {
    grid-template-columns: 1fr 1fr;
    gap: var(--card-pad-lg);
  }

  .step-connector {
    display: none;
  }

  .services-grid {
    grid-template-columns: 1fr 1fr;
    gap: var(--sp-4);
  }

  .pricing-grid {
    grid-template-columns: 1fr;
    gap: var(--sp-5);
  }

  .pricing-card.featured {
    transform: none;
  }

  .footer-inner {
    grid-template-columns: 1fr 1fr;
    gap: var(--card-pad-lg);
  }

  .deliverables-grid {
    grid-template-columns: 1fr;
  }

  .service-detail-header {
    flex-direction: column;
    gap: var(--sp-3);
  }

  .stat-card {
    padding: 20px 14px;
  }

  /* .cta-section padding handled by --section-pad token globally (no override needed) */

  .cta-buttons {
    flex-direction: column;
    align-items: stretch;
  }

  .cta-buttons .btn {
    text-align: center;
    justify-content: center;
  }

  .hero-cta-group {
    flex-direction: column;
    align-items: stretch;
  }

  .hero-cta-group .btn {
    text-align: center;
    justify-content: center;
  }

  .about-content > .btn {
    display: block;
    width: 100%;
    text-align: center;
  }

  /* Touch targets — 44px minimum (WCAG 2.5.5).
     Was 10px padding only (~34px tap height = FAIL).
     min-height 44 + flex-align makes the link area satisfy WCAG 2.2 AA
     Target Size with no visual change to typography or spacing. */
  .footer-col ul li a {
    display: flex;
    align-items: center;
    padding: 10px 0;
    min-height: 44px;
  }

  .footer-col ul {
    gap: 0;
  }

  .footer-legal a {
    display: inline-flex;
    align-items: center;
    padding: 10px 0;
    min-height: 44px;
  }
}

@media (max-width: 640px) {
  .steps-grid {
    grid-template-columns: 1fr;
  }

  .services-grid {
    grid-template-columns: 1fr;
  }

  .footer-inner {
    grid-template-columns: 1fr;
  }

  /* Narrow phones: revert 2-column link flow to single column so each
     link has the full row width (better touch targets, no cramped text). */
  .footer-inner > .footer-col:nth-child(3) ul,
  .footer-inner > .footer-col:nth-child(4) ul {
    column-count: 1;
  }

  .ty-card {
    padding: 36px var(--sp-5);
  }


  .footer-bottom {
    flex-direction: column;
    text-align: center;
    align-items: center;
  }
  /* Audit round-2 2026-05-07 #12b: on stacked-mobile the legal links
     and copyright text were the same size + color and sat on adjacent
     lines, reading as one block. A subtle hairline separator + extra
     gap makes the legal-link row visually distinct from copy. */
  .footer-bottom .footer-legal {
    margin-top: var(--sp-3);
    padding-top: var(--sp-3);
    border-top: 1px solid var(--surface-on-dark-3);
    width: 100%;
    justify-content: center;
    flex-wrap: wrap;
    gap: var(--sp-4);
  }
}

@media (max-width: 768px) {
  .table-scroll-hint {
    display: block !important;
  }
}

/* ----------------------------------------------------------
   REDUCED MOTION
   ---------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  /* Global catch-all — disable all motion for users who prefer reduced motion.
     WCAG 2.1 Success Criterion 2.3.3 (Animation from Interactions). */
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  /* Keep explicit fade-in elements visible */
  .fade-in {
    opacity: 1;
    transform: none;
  }
  /* Disable specific transform/translate hovers */
  .btn:hover,
  .btn:active,
  .service-card:hover,
  .pricing-card.featured {
    transform: none;
  }
}

/* ----------------------------------------------------------
   PRINT STYLES
   ----------------------------------------------------------
   Audit round-3 2026-05-07 #5: print stylesheet had three real
   bugs and several missing affordances:

   - .faq-section was hidden globally → faq.html printed as just
     the page-header (the FAQ entries ARE the page body). Now
     hidden only inside .article-body context.
   - .footer hidden globally meant print users lost mailto +
     legal links. Replaced with a print-specific minimal footer
     (mailto + privacy/terms text only).
   - URL appendage scoped only to .article-body a — pillar
     guides, FAQ, glossary printed without URL annotations.
     Selector broadened to all long-form contexts.
   - No @page rule → wasted page real estate at default UA margins.
   - No widows/orphans → ugly single-line page breaks.
   - No break-inside protection on editorial blocks → callouts,
     pull-quotes, tables split mid-content.
   - Heroes printed in slate-on-slate (illegible at low toner) —
     inverted to white background for print legibility. */

@page {
  size: letter;
  margin: 0.6in 0.7in;
}
@page :first {
  margin-top: 0.4in;
}

@media print {
  .nav, .mobile-nav, .mobile-cta-bar,
  .reading-progress, #siteBanner, .sidebar-cta-card,
  .article-cta-block, .cta-section,
  .scroll-top, .mailto-copy,
  .btn, .nav-toggle { display: none !important; }

  /* Hide FAQ accordion only when used as a sidebar/closing block
     inside an article body — never on faq.html where it IS the
     main content. */
  .article-body .faq-section { display: none !important; }

  body {
    padding-bottom: 0;
    background: white;
    color: black;
    font-size: 11pt;
  }

  /* Heroes: invert to dark-on-white. Was printing as slate-on-slate
     with print-color-adjust: exact (low-toner illegibility). */
  .hero, .page-header, .article-hero, .guide-hero,
  .booking-hero, .founder-hero {
    background: white !important;
    color: black !important;
  }
  .hero h1, .page-header h1, .article-hero h1,
  .guide-hero h1, .booking-hero h1, .founder-hero h1,
  .hero h1 em, .page-header h1 em { color: black !important; }
  .hero p, .page-header p, .article-hero p,
  .guide-hero p, .article-hero-deck, .guide-hero-intro { color: #333 !important; }

  /* URL appendage broadened to every long-form prose surface. */
  .article-body a, .guide-content a, .guide-detail a,
  .glossary-content a, .faq-section a {
    color: inherit;
    text-decoration: underline;
  }
  .article-body a[href^="http"]::after,
  .guide-content a[href^="http"]::after,
  .guide-detail a[href^="http"]::after,
  .glossary-content a[href^="http"]::after,
  .faq-section a[href^="http"]::after {
    content: " (" attr(href) ")";
    font-size: 0.85em;
    color: #555;
    word-break: break-all;
  }
  /* Skip URL annotation on internal anchor links — they print as
     "(#section-id)" which is noise on paper. */
  .article-body a[href^="#"]::after,
  .guide-content a[href^="#"]::after,
  .guide-detail a[href^="#"]::after,
  .faq-section a[href^="#"]::after { content: ""; }

  .article-grid, .guide-layout { grid-template-columns: 1fr; }
  .article-sidebar { position: static; display: none; }

  /* Page-break discipline. */
  h1, h2, h3, h4 { break-after: avoid; page-break-after: avoid; }
  p, blockquote, li {
    widows: 3;
    orphans: 3;
  }
  .callout, .callout-box, .callout-dark, .big-stat,
  .pull-quote, .script-box, .math-block, .tldr,
  .fi-product-card, .product-card, .editorial-divider,
  figure, table, dl, blockquote, pre {
    break-inside: avoid;
    page-break-inside: avoid;
  }

  /* Print footer — restores mailto + legal lost when .footer was
     hidden. Authors don't need to add HTML; this generated content
     prints automatically at the end of the document. */
  body::after {
    content: "Holdback · Toronto, Ontario · hello@holdback.ca · holdback.ca/privacy · holdback.ca/terms";
    display: block;
    margin-top: 24pt;
    padding-top: 8pt;
    border-top: 0.5pt solid #999;
    font-size: 9pt;
    color: #555;
    text-align: center;
  }
}

/* ----------------------------------------------------------
   STICKY MOBILE CTA BAR
   ---------------------------------------------------------- */

.mobile-cta-bar {
  display: none;
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: var(--z-mobile-cta);
  background: var(--slate);
  /* iOS safe-area inset — clears iPhone home indicator */
  padding: var(--sp-3) 20px calc(12px + env(safe-area-inset-bottom, 0px)) 20px;
  box-shadow: 0 -4px 20px var(--shadow-slate-25);
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
}

.mobile-cta-bar-text {
  font-size: var(--fs-sm);
  color: var(--on-dark);
  line-height: 1.3;
}

.mobile-cta-bar-text strong {
  display: block;
  color: var(--white);
  font-size: var(--fs-sm);
}

.mobile-cta-bar .btn {
  flex-shrink: 0;
  padding: var(--sp-3) 20px;
  font-size: var(--fs-sm);
  min-height: 48px;
}

@media (max-width: 768px) {
  .mobile-cta-bar {
    display: flex;
  }

  /* Add padding to body so content isn't hidden behind bar */
  body {
    padding-bottom: 76px;
  }

  /* Push cookie banner above mobile CTA bar */
  #siteBanner {
    bottom: 84px !important;
  }

  /* Hide on booking page — already on the form */
  body.booking-page-wrap .mobile-cta-bar {
    display: none;
  }

  body.booking-page-wrap #siteBanner {
    bottom: 20px !important;
  }

  body.booking-page-wrap {
    padding-bottom: 0;
  }

  .flex-center-mobile {
    justify-content: center;
    text-align: center;
  }
}

/* ============================================================
   COOKIE CONSENT BANNER — tokenized styling
   Rendered dynamically by js/main.js. Token-based so any future brand
   change picks up automatically. Uses --z-progress so it sits above
   the cookie overlay but below the skip-link.
   ============================================================ */
.cookie-banner {
  position: fixed;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  max-width: 640px;
  width: calc(100% - 40px);
  background: var(--surface-inverse);
  color: var(--on-dark);
  padding: 20px var(--sp-5);
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  font-size: var(--fs-sm);
  z-index: var(--z-progress);
  box-shadow: var(--shadow-4);
  border-radius: var(--radius-lg);
  line-height: 1.5;
}
.cookie-banner-text {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1half);
}
.cookie-banner-text strong {
  color: var(--white);
  font-weight: var(--fw-semibold);
  font-size: var(--fs-base);
}
.cookie-banner-text span {
  color: var(--on-dark-default);
}
.cookie-banner a {
  color: var(--accent-on-dark);
  text-decoration: underline;
  text-underline-offset: 3px;
  font-weight: var(--fw-semibold);
  width: fit-content;
}
.cookie-banner a:hover {
  color: var(--white);
}
.cookie-banner-actions {
  display: flex;
  gap: var(--sp-2);
  justify-content: flex-end;
  flex-wrap: wrap;
  margin-top: var(--sp-1);
}
.cookie-banner-btn {
  padding: 10px 22px;
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  cursor: pointer;
  white-space: nowrap;
  transition: var(--transition-bg);
  border: 1.5px solid transparent;
  min-height: 44px;
}
.cookie-banner-btn-primary {
  background: var(--accent);
  color: var(--slate);
  border-color: var(--accent);
}
.cookie-banner-btn-primary:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--slate);
  box-shadow: var(--shadow-accent);
}
.cookie-banner-btn-secondary {
  background: transparent;
  color: var(--on-dark);
  border-color: rgba(255,255,255,0.35);
}
.cookie-banner-btn-secondary:hover {
  background: var(--surface-on-dark-3);
  color: var(--white);
  border-color: var(--white);
}
.cookie-banner-btn:focus-visible {
  outline: 2px solid var(--accent-on-dark);
  outline-offset: 2px;
}
@media (max-width: 640px) {
  /* Audit round-2 2026-05-07 #1g: was bottom: 12px which sat BELOW
     the 76px mobile-cta-bar (covered by it). Anchored above the bar
     using calc + safe-area-inset so the banner is always reachable.
     max-height + overflow-y handles the iPhone-SE-landscape edge case
     where the banner could otherwise grow past the visible viewport. */
  .cookie-banner {
    bottom: calc(84px + env(safe-area-inset-bottom));
    padding: var(--sp-4) var(--sp-4);
    max-height: calc(100vh - 100px);
    overflow-y: auto;
  }
  .cookie-banner-actions { flex-direction: column; align-items: stretch; }
  .cookie-banner-btn { width: 100%; }
}

/* Footer "Cookie Settings" link — matches .footer-legal a exactly.
   Explicit values (not `inherit`) because the button inherits from the
   parent div, which doesn't carry the anchor's size/color. */
.footer-cookie-link {
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  font-family: inherit;
  font-size: var(--fs-sm);              /* match .footer-legal a */
  font-weight: inherit;
  line-height: inherit;
  color: var(--on-dark-muted);           /* match .footer-legal a */
  text-decoration: none;
  cursor: pointer;
  transition: var(--transition-color);
  /* Display: inline matches <a> siblings. Inside .footer-legal's flex
     container, all children become flex items regardless of this value —
     but the inline default is correct for any non-flex parent (e.g.
     future use in a paragraph). */
  display: inline;
  vertical-align: baseline;
}
.footer-cookie-link:hover {
  color: var(--on-dark-muted);
  text-decoration: underline;
}
.footer-cookie-link:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-2xs);
}

/* Mobile padding parity with .footer-legal a (line 2154) */
@media (max-width: 768px) {
  .footer-cookie-link {
    display: inline-block;
    padding: 10px 0;
  }
}

/* ============================================================
   EYEBROW — canonical uppercase-label component

   Replaces 20+ scattered label classes with a unified system.
   Old class names are kept as comma-grouped aliases so existing
   HTML renders identically without modification.

   Canonical:
     <span class="eyebrow">The Real Math</span>
     <span class="eyebrow eyebrow--on-dark">What It Covers</span>

   Variants:
     .eyebrow            orange on light (default)
     .eyebrow--on-dark   orange on slate
     .eyebrow--muted     stone — use on cream / white for neutral labels
     .eyebrow--muted-dark muted white — brand positioning hints on slate
     .eyebrow--white     solid white on slate — headings, table columns
     .eyebrow--tight     narrower tracking (0.07em) — pill badges

   New code should use .eyebrow. Old classes are preserved for
   backward compatibility during incremental HTML migration.
   ============================================================ */

/* Base — canonical typography shared by every eyebrow-style element. */
.eyebrow,
.micro-label,
.stat-box-label,
.bootcamp-covers-label,
.section-label,
.toc-title,
.more-guides-label,
.pricing-coming-soon-label,
.callout-label,
.sidebar-stat-label,
.fleet-pricing-label,
.fleet-who-heading,
.article-category,
.script-box-label,
.math-block-label,
.stats-bar-label,
.pricing-tier-label,
.bottom-nav-dir,
.hero-brand-pos,
.cbc-source-label {
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: var(--ls-widest);
  /* Was --accent-hover (#C05D1A) — 3.8:1 on cream / 4.4:1 on white (FAIL AA).
     --accent-active is the body-text-grade orange (5.98:1 on white per token
     comment) and clears 4.5:1 on cream too. Single change fixes the eyebrow
     contrast on every page using these classes. Dark-context overrides
     directly below still win for slate-bg sections. */
  color: var(--accent-active);
}

/* Orange-on-light is the default (no override needed for most). */

/* Orange-on-dark variant — slate backgrounds, inside dark sections. */
.script-box-label,
.math-block-label {
  color: var(--accent-on-dark);
}

/* Some of the "orange-on-light" group uses the brighter --accent instead of --accent-hover
   (for slightly more visual weight on cream backgrounds). Preserve those. */
.fleet-pricing-label,
.fleet-who-heading,
.article-category {
  color: var(--accent);
}

/* Muted variant — stone on cream / white. Slightly tighter tracking. */
.stats-bar-label,
.pricing-tier-label,
.bottom-nav-dir {
  color: var(--ink-2);
  letter-spacing: 0.1em;
}

/* Muted-dark variant — muted white on slate. For brand positioning hints. */
.hero-brand-pos,
.cbc-source-label {
  color: var(--on-dark-default);
  letter-spacing: 0.1em;
}

/* The bottom-nav-header uses slightly tighter tracking than --ls-widest. */
.bottom-nav-header,
.bottom-nav-heading {
  letter-spacing: 0.1em;
}

/* .hero-brand-pos has font-weight normal (brand treatment — not bold). */
.hero-brand-pos {
  font-weight: var(--fw-regular);
}


/* ============================================================
   MID-BODY CTA — soft-commit touchpoint mid-page
   Inserted before the FAQ or bottom CTA section on long pages.
   Routes to the Deal Analyzer (low-commit mid-funnel destination).
   Track 4 audit fix: closes the top-CTA → bottom-CTA gap.
   ============================================================ */
.mid-body-cta {
  padding: var(--section-pad-sm);
  background: var(--cream);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}
/* Audit 2026-05-08: white variant for pages where the surrounding
   sections are both cream (e.g., hst-calculator info above + faq below). */
.mid-body-cta.mid-body-cta--white {
  background-color: var(--white);
  background-image: var(--grad-white-soft);
}
.mid-body-cta-inner {
  max-width: 860px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-6);
  flex-wrap: wrap;
}
.mid-body-cta-text {
  flex: 1 1 360px;
}
.mid-body-cta-text h3 {
  font-family: var(--font-heading);
  font-size: var(--fs-lg);
  color: var(--slate);
  margin: 0 0 var(--sp-2);
  line-height: 1.3;
}
.mid-body-cta-text p {
  font-size: var(--fs-base);
  color: var(--ink-2);
  line-height: var(--lh-base);
  margin: 0;
}
.mid-body-cta .btn {
  flex-shrink: 0;
}
@media (max-width: 640px) {
  .mid-body-cta-inner { flex-direction: column; align-items: flex-start; gap: var(--sp-4); }
  .mid-body-cta .btn { width: 100%; justify-content: center; }
}

/* Calculator email-capture wrap — section container for reusable .blog-email-capture card */
.mid-email-capture {
  padding: var(--sp-7) 0;
  background: var(--white);
}
/* Audit 2026-05-08: cream variant lets calculator pages alternate
   their rhythm when the calc-section above is also white. */
.mid-email-capture.mid-email-capture--cream {
  background-color: var(--cream);
  background-image: var(--grad-cream-warm);
}

/* ============================================================
   SURFACE CARD — shared base for content cards
   Use as foundation for .step-card, .pricing-card, .feature-card,
   .sidebar-card, etc. Page-specific cards extend with modifiers.
   Single canonical shadow token replaces 14× duplicate raw value.
   ============================================================ */
.surface-card {
  background: var(--white);
  border-radius: var(--radius-lg);
  padding: var(--sp-6);
  box-shadow: var(--shadow-md); border: 1px solid var(--border); /* round 9 — safety hairline so card stays visible on white sections */ }
.surface-card--elevated { box-shadow: var(--shadow-lg); }
.surface-card--flat     { box-shadow: none; border: 1px solid var(--border); }
.surface-card--cream    { background: var(--cream); }
.surface-card--slate    { background: var(--slate); color: var(--on-dark); }
.surface-card--slate h1,
.surface-card--slate h2,
.surface-card--slate h3 { color: var(--white); }
.surface-card--accent-border { border-left: 4px solid var(--accent); }

/* ============================================================
   PEOPLE ALSO ASK (PAA) — long-tail Q&A section for AI/SGE citation
   ============================================================
   Plain h3/p pairs (no expand/collapse) — every question and answer
   is fully visible to the reader and to AI Overview extractors.
   Lives at the bottom of pillar guides, before the CTA section.
   Research-backed: question H3s + concise 2–3 sentence answers
   align with how Google AI Overviews extract passages for citation.
   ============================================================ */
.paa-section {
  padding: var(--section-pad);
  background: var(--cream);
}
/* Audit 2026-05-08: white variant lets pages route paa differently when
   the prior section is also cream (e.g., best-time-to-buy faq above). */
.paa-section.paa-section--white {
  background-color: var(--white);
  background-image: var(--grad-white-soft);
}
.paa-section .container {
  max-width: var(--container-prose-md);
}
.paa-section .section-label {
  margin-bottom: var(--sp-3);
}
.paa-section h2 {
  font-family: var(--font-heading);
  font-size: var(--fs-2xl-fluid);
  color: var(--slate);
  letter-spacing: var(--ls-snug);
  line-height: var(--lh-tight);
  margin: 0 0 var(--sp-7);
}
.paa-list {
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
}
.paa-item {
  border-block-start: 1px solid var(--border);
  padding-block-start: var(--sp-5);
}
.paa-item:first-child {
  border-block-start: none;
  padding-block-start: 0;
}
.paa-item h3 {
  font-family: var(--font-heading);
  font-size: var(--fs-md);
  color: var(--slate);
  line-height: 1.45;
  margin: 0 0 var(--sp-3);
}
.paa-item p {
  font-size: var(--fs-base);
  color: var(--body-text);
  line-height: var(--lh-relaxed);
  margin: 0;
  max-width: 65ch;
}
