/* =================================================================
   Zealous Website — shared styles
   Source of truth: Figma "Smart Justice / Homepage - 1720px"
   Colors and key sizes below are pulled directly from the Figma
   design variables so every page stays consistent.
   ================================================================= */

/* ---------- Web fonts (all licensed) ----------
   Founders Grotesk (self-hosted woff2): Medium 500 + Semibold 600. No Bold (700)
   face — nothing renders Founders bold (the nav/footer wordmarks are now SVG).
   PP Editorial New 400 (self-hosted woff2).
   Neue Haas Grotesk: Adobe Fonts (Typekit kit dnq5kwg), loaded via the <link>
   in index.html's <head>; see --font-body. */
@font-face {
  font-family: 'Founders Grotesk';
  src: url('../fonts/FoundersGrotesk-Medium.woff2') format('woff2');
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Founders Grotesk';
  src: url('../fonts/FoundersGrotesk-Semibold.woff2') format('woff2');
  font-weight: 600; font-style: normal; font-display: swap;
}
/* Neue Haas Grotesk is now served by Adobe Fonts (Typekit kit dnq5kwg) — the
   <link> is in index.html's <head>. Its family is "neue-haas-grotesk-text"
   (see --font-body below). No self-hosted @font-face / woff2 needed. */
@font-face {
  font-family: 'PP Editorial New';
  src: url('../fonts/PPEditorialNew-Regular.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}

/* ---------- Design tokens (from Figma variables) ---------- */
:root {
  /* Colors — exact values from the Figma file */
  --white:          #ffffff;
  --coral:          #fc9b6e;
  --light-coral:    #ffdece;
  --black:          #1a1a1a;
  --green:          #a2ecbc;
  --yellow:         #eee881;
  --light-blue:     #daf5ff;
  --light-green:    #f3fef7;
  --highlight-blue: #94e1ff;
  --light-yellow:   #fffdd8;
  --blue:           #2966c3;
  --background-blue: #c3e1ef;

  /* Fonts — the real licensed typefaces from the Figma file.
     Founders Grotesk  -> big display headlines (self-hosted woff2)
     Neue Haas Grotesk -> body text (Adobe Fonts/Typekit: "neue-haas-grotesk-text")
     PP Editorial New  -> serif accents (self-hosted woff2) */
  --font-display: 'Founders Grotesk', 'Helvetica Neue', Arial, sans-serif;
  --font-body:    'neue-haas-grotesk-text', 'Helvetica Neue', Arial, sans-serif;
  --font-serif:   'PP Editorial New', Georgia, 'Times New Roman', serif;

  /* Layout — Figma frame is 1720px wide with 75px side padding
     and 125px top/bottom padding. We keep those as the maximum and
     scale them down fluidly on smaller screens. */
  --max-width: 1720px;
  --pad-x: clamp(20px, calc(11.96vw - 24.85px), 75px);  /* 20 @375 · 75 @835+ (Figma mobile gutter) */
  --pad-y: clamp(40px, calc(7.98vw + 10px), 125px);     /* 40 @375 · 75 @835 · 125 @1440 */

  /* Fluid type scale — single formulas that hit the Figma size at every
     breakpoint (375 / 835 / 1440) and interpolate smoothly between. */
  --fs-quote:      clamp(50px, calc(8.26vw + 6px), 125px);    /* 50 @375 · 75 @835 · 125 @1440 */
  --fs-display:    clamp(50px, calc(5.43vw + 29.6px), 100px); /* 50 @375 · 75 @835 · 100 @1440 */
  --fs-display-lg: clamp(50px, calc(10.87vw + 9.2px), 100px); /* 50 @375 · 100 @835+ (California, Join Us) */
  --fs-card:       clamp(45px, calc(6.52vw + 20.55px), 75px); /* 45 @375 · 75 @835 (Figma card title) */
  --fs-myth:       clamp(28px, calc(1.5vw + 22.4px), 32px);   /* 28 @375 · 32 @835 */
  --fs-serif-l:    clamp(20px, calc(0.87vw + 16.7px), 24px);  /* 20 @375 · 24 @835 */
  --fs-serif-m:    20px;                                       /* 20px everywhere */
  --fs-body:       18px;                                       /* 18px everywhere */
  --fs-small:      16px;

  /* Motion — ease-in-out curve matching Figma's "Ease In And Out"
     (same as the CSS ease-in-out keyword). Used for hover/transitions. */
  --ease-io: cubic-bezier(0.42, 0, 0.58, 1);
  /* Softer ease-in-out (easeInOutCubic) — gentler start/settle for the
     more "liquid" card-hover motion. */
  --ease-soft: cubic-bezier(0.65, 0, 0.35, 1);
}

/* ---------- Reset / base ---------- */
*,
*::before,
*::after { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  overflow-x: hidden;
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.4;
  color: var(--black);
  background: var(--light-yellow);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

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

a { color: inherit; }

h1, h2, h3, p, blockquote, dl, dd, dt, figure { margin: 0; }

ul { margin: 0; padding: 0; list-style: none; }

/* ---------- Reusable display heading ---------- */
.display {
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: -0.02em;
  line-height: 0.9;
}

.section__title {
  font-size: var(--fs-display);
}
/* Per-section headline line-heights, matching the Figma values */
.moment .section__title,
.california .section__title { line-height: 0.8; }
.facts .section__title { line-height: 0.85; }
/* California and Join Us keep their 100px headline at tablet (others drop to 75) */
.california .section__title { font-size: var(--fs-display-lg); }

/* ---------- Body copy ---------- */
.body-copy { font-size: var(--fs-body); line-height: 1.4; }
.body-copy p + p { margin-top: 1em; }

/* Serif accent line that sits under body copy (underlined statement) */
.lead-accent {
  width: fit-content;        /* highlight hugs the text, not the whole column */
  max-width: 100%;
  padding: 0.1em 0.22em;
  font-family: var(--font-serif);
  font-size: var(--fs-serif-m);
  line-height: 1.15;
  letter-spacing: -0.02em;
}
.lead-accent--green { --hl: var(--green); }            /* #a2ecbc */
.lead-accent--blue  { --hl: var(--highlight-blue); }   /* #94e1ff */
/* Block line that holds an inline highlight span. The marker sits on the
   INLINE span (not this block), so box-decoration-break:clone hugs each
   wrapped line instead of forming one full-width box when it wraps on mobile. */
.lead-accent-line { width: 100%; }

/* Small serif eyebrow label (e.g. "The Moment") */
.eyebrow-serif {
  font-family: var(--font-serif);
  font-size: var(--fs-serif-l);
  letter-spacing: -0.02em;
}

/* ---------- Pills (highlighted text chips) ---------- */
.pill {
  display: inline-block;
  padding: 8px 10px;
  font-family: var(--font-serif);
  font-size: var(--fs-serif-l);
  line-height: 1.1;
  letter-spacing: -0.02em;
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
}
.pill--coral      { background: var(--coral);      color: var(--white); }
.pill--light-blue { background: var(--light-blue); color: var(--black); }

/* ---------- Buttons ---------- */
.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  width: 150px;
  padding: 12px;
  border-radius: 100px;
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.25;
  text-decoration: none;
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
  transition: transform 0.15s var(--ease-io);   /* press feedback only */
}
/* Hover (mouse) / keyboard focus → Hover variant: the arrow slides right.
   Driven by transform (GPU-accelerated, no reflow), the full 300ms on an
   ease-in-out curve matching Figma's smart-animate. */
.btn__arrow {
  width: 13px;
  height: 10px;
  flex: none;
  transition: transform 0.3s var(--ease-io);
}
.btn:hover .btn__arrow,
.btn:focus-visible .btn__arrow,
.btn.is-hover .btn__arrow { transform: translateX(12px); }
/* "Back to Top" reuses the shared arrow, rotated -90deg to point UP. On hover it
   slides up (translateX along its now-rotated axis). The extra .btn class keeps
   these more specific than the generic .btn:hover .btn__arrow rule above. */
.nav__back-top .btn__arrow { transform: rotate(-90deg); }
.btn.nav__back-top:hover .btn__arrow,
.btn.nav__back-top:focus-visible .btn__arrow,
.btn.nav__back-top.is-hover .btn__arrow { transform: rotate(-90deg) translateX(12px); }
.btn:active { transform: translateY(1px); }
.btn:focus-visible { outline: 2px solid var(--black); outline-offset: 2px; }

@media (prefers-reduced-motion: reduce) {
  .btn,
  .btn::after { transition: none; }
}

.btn--coral          { background: var(--coral);          color: var(--white); }
.btn--black          { background: var(--black);          color: var(--white); }
.btn--light-blue     { background: var(--light-blue);     color: var(--black); }
.btn--highlight-blue { background: var(--highlight-blue); color: var(--black); }
.btn--blue           { background: var(--blue);           color: var(--light-blue); }

/* ---------- Generic section wrapper ---------- */
/* Full-bleed sections: the background runs edge-to-edge at ANY width, while
   content stays centred and exactly as wide as before (the 1720 frame minus its
   gutters). Below 1720 the padding is just --pad-x (unchanged); past 1720 it
   grows by (viewport - 1720)/2 so the extra width becomes margin, not content. */
.section {
  width: 100%;
  padding: var(--pad-y) max(var(--pad-x), calc((100% - var(--max-width)) / 2 + var(--pad-x)));
}

/* =================================================================
   NAVIGATION
   ================================================================= */
/* =================================================================
   COMPONENT — Navigation
   Desktop (>835): full bar (links · wordmark · Get Involved), transparent
   over the hero. Fixed; after scrolling past the hero it collapses to a
   light-blue hamburger (top-right) that opens a dropdown menu.
   Mobile (≤835): wordmark left + hamburger right at all times.
   ================================================================= */
.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 50;
  transition: background-color 0.35s var(--ease-soft);  /* dark bar fades in on scroll */
}
.nav {
  position: relative;
  max-width: var(--max-width);
  margin-inline: auto;
  padding: 25px var(--pad-x);
  /* Three equal-weight columns so the wordmark is truly CENTERED regardless of
     the links/CTA widths: links (left) · wordmark (centre) · Get Involved
     (right). */
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 24px;
}
.nav__links {
  justify-self: start;
  display: flex;
  gap: clamp(20px, 3vw, 50px);
  font-size: var(--fs-small);
  color: var(--light-blue);
}
.nav__cta { justify-self: end; color: #030303; }   /* Figma nav CTA text #030303 */
.nav__links a { text-decoration: none; }
.nav__brand {
  justify-self: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-small);
  line-height: 1;             /* Figma leading-none (2-line mobile logo) */
  text-transform: uppercase;
  text-decoration: none;
  color: var(--light-blue);
  text-align: center;
  white-space: nowrap;         /* one line on desktop/iPad (wraps on mobile) */
}
.nav__brand .amp { text-transform: uppercase; }
/* SVG wordmark logo (replaces the text). 1-line lockup sized to the same ~199px
   width the text logo occupied; vertically centred in the nav row. */
.nav__brand-logo { display: block; width: 199px; height: auto; }

/* Hamburger toggle — light-blue CIRCLE (Figma scrolled/mobile nav), pinned top-right */
.nav__toggle {
  display: none;
  position: absolute;
  top: 22px;
  right: var(--pad-x);
  width: 45px;
  height: 45px;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  border-radius: 50%;             /* circle, per the new Figma nav */
  background: var(--light-blue);  /* #daf5ff */
  color: var(--black);
  cursor: pointer;
  z-index: 2;
}
/* Both icons stacked (centred, overlapping) so the hamburger ⇄ × swap can DRAW
   back and forth via stroke-dasharray / stroke-dashoffset (pathLength=1) — like the
   line-draws elsewhere on the site. Centred with margins (not transform) so it
   doesn't fight the rotate/flip, which targets only the hamburger (--open) icon —
   that keeps the × a TRUE × (never rotated into a +). */
.nav__toggle-icon {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 24px;
  height: 24px;
  margin: -12px 0 0 -12px;
  transform-origin: center;
}
.nav__toggle-icon path { stroke-dasharray: 1; transition: stroke-dashoffset 0.4s var(--ease-soft); }
.nav__toggle-icon--open  path { stroke-dashoffset: 0; }   /* hamburger drawn at rest */
.nav__toggle-icon--close path { stroke-dashoffset: 1; }   /* × retracted at rest */
/* On open: the hamburger draws OUT and the × draws IN (reversed on close). */
.nav__toggle[aria-expanded="true"] .nav__toggle-icon--open  path { stroke-dashoffset: 1; }
.nav__toggle[aria-expanded="true"] .nav__toggle-icon--close path { stroke-dashoffset: 0; }
.nav__toggle:focus-visible { outline: 2px solid var(--light-blue); outline-offset: 2px; }
/* Reduced motion: instant swap between hamburger and × — no draw. */
@media (prefers-reduced-motion: reduce) {
  .nav__toggle-icon path { transition: none; }
}

/* Dropdown menu panel */
.nav__menu {
  position: absolute;
  top: calc(100% + 10px);
  right: var(--pad-x);
  width: 200px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 30px;
  padding: 24px 50px;
  border-radius: 10px;
  background: var(--background-blue);
}
.nav__menu[hidden] { display: none; }
.nav__menu a:not(.btn) {
  font-size: var(--fs-small);
  color: var(--black);
  text-decoration: none;
}

/* ----- Nav link hover/focus highlight -----
   No underline. On hover OR keyboard focus a Highlight-Blue (#94E1FF) marker
   wipes in left-to-right BEHIND the text (the text colour is untouched).
   Implemented with a ::before that scaleX(0→1) — GPU-friendly (transform), so
   it adds no layout shift and stays on the global liquid ease. Covers both the
   desktop bar (.nav__links) and the hamburger menu (.nav__menu), every
   breakpoint. */
.nav__links a,
.nav__menu a:not(.btn) {
  position: relative;
  isolation: isolate;            /* keep the negative-z marker scoped to the link */
}
.nav__links a::before,
.nav__menu a:not(.btn)::before {
  content: "";
  position: absolute;
  inset: -0.12em -0.3em;         /* marker sits slightly proud of the text */
  z-index: -1;                   /* behind the link text */
  background: var(--highlight-blue);   /* #94E1FF */
  transform: scaleX(0);
  transform-origin: left center; /* wipe grows from the left */
  transition: transform 0.55s var(--ease-soft);
}
/* Full desktop menu only: hover highlight is BLUE (#2966C3). The hamburger
   menu (.nav__menu) keeps #94E1FF — .nav__links is hidden once collapsed. */
.nav__links a::before { background: var(--blue); }
.nav__links a:hover::before,
.nav__links a:focus-visible::before,
.nav__menu a:not(.btn):hover::before,
.nav__menu a:not(.btn):focus-visible::before {
  transform: scaleX(1);
}
@media (prefers-reduced-motion: reduce) {
  /* highlight still appears on hover/focus, just with no wipe animation */
  .nav__links a::before,
  .nav__menu a:not(.btn)::before { transition: none; }
}

/* Desktop & iPad (≥835): full bar at top, collapses to the hamburger on scroll.
   SCROLLED STATE: background stays TRANSPARENT (no bar) — just the circular
   hamburger floats top-right. The top (unscrolled) state is unchanged. */
@media (min-width: 835px) {
  .site-header.is-scrolled { background: transparent; }
  /* flex + in-flow hamburger so the collapsed nav keeps its full height (py-25 + 45) */
  .site-header.is-scrolled .nav { display: flex; justify-content: flex-end; align-items: center; }
  .site-header.is-scrolled .nav__links,
  .site-header.is-scrolled .nav__brand,
  .site-header.is-scrolled .nav__cta { display: none; }
  .site-header.is-scrolled .nav__toggle {
    display: inline-flex;
    position: relative;          /* positioning context for the stacked icons */
  }
  .site-header.is-scrolled .nav__toggle .nav__toggle-icon--open {
    transition: transform 0.6s var(--ease-soft);   /* smooth, eased flip */
  }
  /* Timed flip: 0.5s after the bar fully collapses to the hamburger, nav.js adds
     .is-flipped — the HAMBURGER icon ROTATES from horizontal (start, node 10454-1279)
     to the diagonal scrolled state (end, node 10473-1661 — a 45° turn) and HOLDS
     there. On the hamburger icon only, so the × (close) is never rotated. Reverts
     when the bar re-expands. */
  .site-header.is-scrolled .nav__toggle.is-flipped .nav__toggle-icon--open {
    transform: rotate(45deg);
  }
}
/* Reduced motion: no flip animation — show the static END state (diagonal) as soon
   as it's collapsed (nav.js skips the timer here; this shows the end state). */
@media (prefers-reduced-motion: reduce) and (min-width: 835px) {
  .site-header.is-scrolled .nav__toggle .nav__toggle-icon--open { transition: none; transform: rotate(45deg); }
}

/* Mobile (≤834): a TRANSPARENT bar — wordmark (logo) left, circular hamburger
   right. The LOGO scrolls away normally with the page (the header is absolute, not
   pinned, so it leaves the top with the content). The HAMBURGER is STICKY
   (position:fixed, pinned to the top-right corner) and, on scroll, ROTATES IN PLACE
   to the Figma slant angle — it does NOT travel down the page. */
@media (max-width: 834px) {
  .site-header { position: absolute; }   /* logo scrolls away with the page */
  .nav {
    max-width: none;
    margin: 0;
    width: 100%;
    padding: 25px 40px;            /* Figma mobile nav px-40 py-25 */
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
  .nav__links, .nav__cta { display: none; }
  /* The LOGO — scrolls away normally with the page (it's in the absolute header,
     no transform, not pinned), like normal content. */
  .nav__brand {
    width: 120px;                  /* Figma mobile wordmark = 120px (2 tight lines) */
    font-size: 18px;               /* Figma mobile wordmark = 18px */
    text-align: left;
    white-space: normal;
  }
  /* The 1-line SVG wordmark doesn't wrap like the old text; let the cell size to it
     and keep it compact on mobile. */
  .nav__brand { width: auto; }
  .nav__brand-logo { width: 160px; }
  .nav__toggle {
    display: inline-flex;
    position: fixed;               /* STICKY — pinned to the top-right corner, stays visible */
    top: 25px; right: 40px;        /* same spot as in the bar → no jump at the top */
    width: 40px; height: 40px;     /* Figma mobile menu = 40px */
  }
  .nav__toggle .nav__toggle-icon--open {
    transition: transform 0.45s var(--ease-soft);   /* smooth in-place rotation */
  }
  .nav__menu { position: fixed; top: 79px; right: 40px; }
  /* ON SCROLL: the HAMBURGER icon ROTATES IN PLACE to the Figma mobile-scrolled slant
     (rotate(-135deg) scaleY(-1), node 10454-1296). On the hamburger icon only, so the
     × (close) stays a true ×; no button transform means no reset-on-open is needed. */
  .site-header.is-scrolled .nav__toggle .nav__toggle-icon--open {
    transform: rotate(-135deg) scaleY(-1);
  }
}
/* Reduced motion: no slant — hamburger icon stays upright in its normal spot. */
@media (max-width: 834px) and (prefers-reduced-motion: reduce) {
  .nav__toggle .nav__toggle-icon--open { transition: none; transform: none; }
}

/* =================================================================
   HERO
   ================================================================= */
.hero {
  position: relative;
  min-height: 800px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: calc(var(--pad-y) + 40px) var(--pad-x) var(--pad-y);
  /* Art-directed photo: phone crop by default, swapped at each breakpoint.
     Anchored LEFT (not center) so the person stays flush to the block's left
     edge like Figma — when the photo is wider than the block (e.g. the 1720px
     image at the 1440 breakpoint), cover then crops only the empty light-blue
     on the right instead of slicing into the subject on the left. */
  background: var(--light-blue) url('../images/hero-375.jpg') left center / cover no-repeat;
}
.hero__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 50px;
  text-align: center;
  max-width: 1060px;   /* matches the Figma headline width */
}
.hero__eyebrow {
  text-align: center;
  white-space: normal;
}
/* Hero eyebrow uses the SAME marker-highlight wipe as the rest of the page
   (.hl: coral gradient grows 0%→100%, box-decoration-break:clone so each
   wrapped line wipes L→R in parallel, ease-in-out). It's above the fold, so
   it is triggered on load (data-fx-onload in fx.js) rather than on scroll.
   Kept inline so box-decoration-break gives a per-line marker box. */
/* Scoped under .hero__eyebrow so the white text wins over `.hl { color:
   inherit }`, which is defined later in the file with equal specificity. */
.hero__eyebrow .hero__eyebrow-mark {
  --hl: var(--coral);
  display: inline;
  padding: 0.18em 0.34em;
  font-family: var(--font-serif);
  font-size: var(--fs-serif-m);   /* 20px — Figma hero eyebrow */
  line-height: 1.35;            /* room so stacked per-line markers don't collide */
  letter-spacing: -0.02em;
  color: var(--white);
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
}
.hero__title {
  font-size: var(--fs-display);
  line-height: 0.8;
  color: var(--light-coral);
}
.hero__buttons {
  display: flex;
  gap: 25px;
  flex-wrap: wrap;
  justify-content: center;
}

/* =================================================================
   MENTAL HEALTH DIVERSION
   ================================================================= */
.diversion {
  position: relative;          /* containing block for the bg pattern */
  background: var(--light-green);
  display: flex;
  flex-direction: column;
  gap: 75px;
  overflow: hidden;            /* clip the pattern's bleed (like .facts) */
}
/* Background zig-zag pattern — the green chevron from Figma "Pattern 1". The art
   is the ACTUAL Figma pattern asset (41 visible lines from 38 paths), not the
   reused Facts chevron. Figma uses a DIFFERENT per-width composition, so we ship
   two: the wide one (viewBox 1440×1884, full block) for ≥641px, and the mobile
   one (viewBox 375×716, a top band) for ≤640px — each pre-proportioned for its
   width so neither is distorted. Both FILL their box (preserveAspectRatio="none")
   and scrub-draw via the shared [data-fx-scrub] system (fx.js drives --draw from
   the wrapper; both SVGs' .fx-line read it). Behind everything (z-index 0,
   pointer-events none) so cards/text stay on top. */
.diversion__pattern {
  position: absolute;
  inset: 0;                    /* full block (wide composition) */
  pointer-events: none;
  z-index: 0;
}
.diversion__pattern .fx-draw { display: block; width: 100%; height: 100%; }
.diversion__pattern .dpat--sm { display: none; }   /* mobile variant hidden by default */
/* Mobile (≤640): swap to the 375×716 composition, placed as a TOP BAND (Figma
   shows the pattern only across the top of the tall stacked-content block). */
@media (max-width: 640px) {
  .diversion__pattern {
    inset: auto;
    top: 0;
    left: 0;
    width: 100%;
    aspect-ratio: 375 / 716;   /* top band, matches the Figma 375 pattern box */
  }
  .diversion__pattern .dpat--lg { display: none; }
  .diversion__pattern .dpat--sm { display: block; }
}
/* Lift all real content above the background pattern. */
.diversion__header,
.diversion__row,
.diversion .steps { position: relative; z-index: 1; }
/* "Content Header" group (Figma): the new section tag sits directly above the
   heading, grouped so the tag→heading spacing is tight (18px) while the group as
   a whole keeps the section's 75px rhythm to the row below — so nothing else in
   the About block moves except being pushed down by the tag. The tag reuses the
   site's section-tag treatment (.eyebrow-serif: serif, --fs-serif-l, -0.02em). */
.diversion__header {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 18px;                /* tag → heading (1720 / 1440 frames) */
  width: 100%;
}
.diversion__tag { line-height: 2; }   /* Figma tag leading: 2 */
@media (max-width: 1024px) { .diversion__header { gap: 8px; } }   /* 835 frame */
@media (max-width: 600px)  { .diversion__header { gap: 0; } }     /* 375 frame */
.diversion__row {
  display: flex;
  gap: clamp(40px, 8vw, 123px);
  align-items: flex-start;
}
.diversion__content {
  flex: 0 1 644px;          /* Figma content column = 644px */
  display: flex;
  flex-direction: column;
  gap: 50px;
  align-items: flex-start;
}
.diversion__media {
  flex: 1 1 0;
  min-width: 0;
  display: block;
}
.diversion__media img {
  width: 100%;
  height: 489px;           /* Figma keeps this slot 489px tall, cropping width */
  display: block;
  object-fit: cover;
  border-radius: 10px;
}

/* ----- Steps cards -----
   CSS Grid (not flex) so the row's track height sizes to the TALLEST card's
   content and every card stretches to match it — equal height that GROWS as
   content reveals/wraps, with no clipping. (A stretched flex item holding the
   reveal's `grid 1fr` doesn't reliably grow its track, which clipped the
   revealed text and pushed the title off the top around 1024–1280px.) */
.steps {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 24px;
  align-items: stretch;
}
/* =================================================================
   COMPONENT — Card ("Card System" / Steps)
   Variants: --green · --yellow · --blue (default background colour).
   State: on hover/focus the card turns coral, a diamond pattern fades
   in, and the description expands. Title is always visible.
   Sizes (desktop row / tablet · mobile stacked) are handled by the
   .steps container + the responsive blocks below.
   ================================================================= */
.card {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  /* No hardcoded height: fx.js measures the tallest card's full (title + body)
     content at the current width and sets --card-reserve, so all cards match
     responsively and the resting title can move up as the body reveals. */
  min-height: var(--card-reserve, 0px);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  /* ≥50px top & bottom always (breathing room so the revealed title/body never
     crowd or clip the edges); sides per Figma (32). */
  padding: 50px 32px;
  border: 1px solid var(--black);
  border-radius: 10px;
  overflow: hidden;
  background: var(--card-bg, var(--green));
  transition: background-color 0.55s var(--ease-soft);
}
.card--green { --card-bg: var(--green); }
.card--yellow { --card-bg: var(--yellow); }
.card--blue  { --card-bg: var(--background-blue); }

/* Each card now carries its OWN decorative pattern, revealed on hover (desktop/
   iPad) and tap/active (mobile). All three reuse the shared .fx-line draw-on
   system, so they sketch on at the SAME duration/easing/stagger — only the path
   shape and sweep DIRECTION differ per pattern. Stretched to a per-card box
   (preserveAspectRatio="none"); the card's overflow:hidden clips the bleed.
     • green  (Actual Care)   — Arch:    fan of curved arcs, top-RIGHT
     • yellow (Public Safety) — Diamond: sunburst, full-width, focal near top
     • blue   (Follow-Through)— Fan:     bent lines, full-width, mirrored */
.card__pattern {
  position: absolute;
  pointer-events: none;
  z-index: 0;
}
.card__pattern .fx-draw { display: block; width: 100%; height: 100%; }
/* Actual Care — Arch, anchored top-right; arcs draw bottom→top, swept L→R. */
.card--green  .card__pattern { top: 0; right: 0; width: 82%; aspect-ratio: 416 / 327; }
/* Public Safety — Diamond sunburst, full width, focal near the top. Its paths
   run edge→centre, so a -1 starting dashoffset reveals from the CENTRE end first
   → the rays draw OUTWARD from the focal point (timing-neutral; same transition). */
.card--yellow .card__pattern { top: 0; left: 0; width: 100%; aspect-ratio: 504.661 / 305; }
.card--yellow .fx-line { stroke-dashoffset: -1; }
/* Cohesion: normalise the per-card stagger by (n−1) so all three patterns —
   despite different path counts (33 / 58 / 14) — span the EXACT same window and
   finish together. Duration (0.275s) and easing stay from the shared .fx-line,
   so the three draw on at identical speed; only shape & direction differ. */
.card .fx-line { transition-delay: calc(var(--i) / (var(--n) - 1) * 0.2s); }
/* INTRO (hover / focus / tap-active) sweeps on its OWN order, --j, while the
   OUTRO (return to rest, above) keeps --i — a CSS transition alone can't differ
   per direction, so the end-state rule supplies the intro stagger. Duration and
   easing are unchanged, so all three still draw at one identical speed.
     • Actual Care (green):  --j = reverse of --i → intro is the exact reverse of
       its outro (so hover draws it in the way un-hover draws it out).
     • Public Safety (yellow): --j = --i → unchanged.
     • Follow-Through (blue):  --j orders the lines right→left on intro; the outro
       (--i) is left exactly as it was. */
.card:hover .fx-line,
.card:focus-within .fx-line,
.card.is-active .fx-line { transition-delay: calc(var(--j) / (var(--n) - 1) * 0.2s); }
/* Follow-Through — Fan of bent lines, full width, mirrored to match Figma; lines
   draw along their length, swept top→bottom. */
.card--blue   .card__pattern { top: 0; left: 0; width: 100%; aspect-ratio: 505 / 428; transform: scaleX(-1); transform-origin: center; }
/* Patterns re-sized to the stacked card box per the mobile (375) frame. */
@media (max-width: 600px) {
  .card--green  .card__pattern { width: 85.4%; aspect-ratio: 416 / 327; }
  .card--yellow .card__pattern { aspect-ratio: 333 / 299; }
  .card--blue   .card__pattern { aspect-ratio: 333 / 358; }
}
/* prefers-reduced-motion: the pattern is shown in its final (fully-drawn) state
   on hover/active with NO sketching animation. (At rest it stays hidden, as the
   pattern is a hover/active decoration.) */
@media (prefers-reduced-motion: reduce) {
  .card .fx-line { transition: none !important; }
}
/* Title + body share one group pinned to the card's bottom (the card is a
   flex column with justify-content:flex-end). The body is COLLAPSED at rest
   so the group is exactly as tall as the title and the title sits on Figma's
   resting baseline — nothing is reserved. On hover the body opens; because
   the group is bottom-anchored, that extra height grows UPWARD, lifting the
   title to reveal the body below it.

   Two implementations:
   • Base (below) collapses the body with max-height — animates in EVERY
     browser, including pre-2022 ones. max-height can only ease toward a fixed
     ceiling, so the timing is a touch less exact, but the motion is smooth.
   • @supports block further down upgrades modern browsers to an exact grid
     0fr→1fr reveal that eases to the body's real height (the liquid default). */
.card__content {
  position: relative;
  z-index: 1;
}
.card__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-card);
  line-height: 0.9;
  letter-spacing: -0.02em;
  color: var(--black);
  /* Safety net: never let a long title overflow its (now column-capped) card —
     break it rather than clip. The clean per-title break is authored in the
     markup (e.g. "Follow-<wbr>Through"); this only catches anything narrower. */
  overflow-wrap: break-word;
}
/* The title is pinned at its 75px maximum from 835px up, but in the 3-up band
   (≥1025px) the three columns keep narrowing toward the 1024px stack point. The
   longest title wraps to two lines ("Follow-" / "Through") by design, but its
   longest WORD ("Through" ≈ 263px @75px) stops fitting the column below ~1200px
   and would break mid-word. So scale the title down across the 3-up band just
   enough that every word fits cleanly, ramping back to the full 75px by ~1230px
   where the cards are wide enough — matching the Figma 1440 cards. Stacked
   widths (≤1024) keep the normal --fs-card (the full-width card fits 75px). */
@media (min-width: 1025px) {
  .card__title { font-size: clamp(56px, calc(9.27vw - 39px), 75px); }
}
.card__body {
  max-height: 0;               /* collapsed at rest — fallback reveal mechanism */
  overflow: hidden;            /* clip the body (and its top gap) while collapsed */
  padding-top: 48px;           /* gap above the body — clipped at rest (border-box) */
  opacity: 0;
  transform: translateY(14px);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.4;
  color: var(--black);
  max-width: 427px;
  /* soft fade/slide + max-height open, same 0.55s curve */
  transition: max-height 0.55s var(--ease-soft), opacity 0.55s var(--ease-soft), transform 0.55s var(--ease-soft);
}

/* Hover / keyboard-focus / .is-active (showcase) reveal the coral state.
   Everything (background, pattern draw, body) animates over 0.55s on the
   same soft ease-in-out curve, so it reads as one fluid motion. */
.card:hover,
.card:focus-within,
.card.is-active { background: var(--coral); }
.card:hover .card__body,
.card:focus-within .card__body,
.card.is-active .card__body {
  max-height: 24em;           /* generous ceiling — exceeds the longest body */
  opacity: 1;
  transform: translateY(0);
}

/* Modern upgrade (post-2022 browsers). subgrid support implies the browser
   can also animate grid track sizes, so we swap the body's max-height reveal
   for an exact grid 0fr→1fr open that eases to its true height. This is the
   default, liquid version; the max-height rules above are the fallback. */
@supports (grid-template-rows: subgrid) {
  .card__content {
    display: grid;
    grid-template-rows: auto 0fr;
    /* One column, capped at the card's width (minmax floor 0, not the title's
       max-content). Without this the implicit grid column is `auto` and sizes to
       the widest title's MAX-CONTENT — so "Follow-Through" stayed one 263px line
       and overflowed (clipped) when the 3-up track got narrow (~1025–1180px).
       Capping the column lets the title wrap to the card, like the block fallback. */
    grid-template-columns: minmax(0, 1fr);
    transition: grid-template-rows 0.55s var(--ease-soft);
  }
  .card__body {
    max-height: none;         /* the grid row governs height now, not max-height */
    min-height: 0;            /* let the row collapse fully at rest */
    transition: opacity 0.55s var(--ease-soft), transform 0.55s var(--ease-soft);
  }
  .card:hover .card__content,
  .card:focus-within .card__content,
  .card.is-active .card__content { grid-template-rows: auto 1fr; }
}
/* (card pattern lines now inherit the shared liquid .fx-line timing below) */

/* Desktop AND iPad (≥835): (a) cards 50px TALLER than their content-sized height —
   added to --card-reserve, no hardcoded px, equal heights preserved. (b) Body stays
   BELOW the title — ORIGINAL hover layout (headline above, text below). The resting
   title sits flush at the bottom 50px. We collapse the body with max-height here
   rather than the grid 0fr reveal: grid 0fr could NOT shrink the body past its 48px
   top-gap, so the resting title got pushed ~48px up; max-height:0 clips that gap
   fully (resting title at 50px) while the body's scrollHeight STILL counts it — so
   fx.js's --card-reserve (and therefore the card size) is unchanged. Scoped ≥835
   (desktop + iPad); mobile (≤834) untouched. */
@media (min-width: 835px) {
  .card { min-height: calc(var(--card-reserve, 0px) + 50px); }
  @supports (grid-template-rows: subgrid) {
    .card__content { display: block; }   /* block + max-height reveal, not grid 0fr */
    .card__body {
      max-height: 0;
      min-height: 0;
      padding-top: 0;        /* gap moves to ::before so the body can collapse fully (padding is a hard floor max-height can't clip) */
      transition: max-height 0.55s var(--ease-soft), opacity 0.55s var(--ease-soft), transform 0.55s var(--ease-soft);
    }
    /* The 48px title↔text gap as CLIPPABLE content: counted in scrollHeight (so
       fx.js keeps --card-reserve correct → size unchanged) but clipped by
       overflow+max-height at rest (so the resting title lands at the 50px padding). */
    .card__body::before { content: ''; display: block; height: 48px; }
    .card:hover .card__body,
    .card:focus-within .card__body,
    .card.is-active .card__body { max-height: 24em; }
  }
}

/* Touch cards use a real <button> that fills the card as the tap target (mobile
   adds a click→.is-active toggle in fx.js). On DESKTOP the button does NOT
   intercept pointer events — pointer-events:none lets hover and text-selection
   work exactly as before — but it stays keyboard-focusable, so tabbing to it
   still triggers the card's :focus-within reveal. The mobile block flips
   pointer-events:auto so it becomes the tap target there. */
.card__toggle {
  position: absolute;
  inset: 0;
  z-index: 2;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  pointer-events: none;                 /* desktop: pass clicks/hover through */
  -webkit-tap-highlight-color: transparent;
}
.card__toggle:focus-visible { outline: 2px solid var(--black); outline-offset: -4px; }

/* =================================================================
   SHARED — Draw-on line effect (stroke-dasharray / stroke-dashoffset)
   Lines are undrawn by default; they "draw on" when triggered:
   - cards: on hover / keyboard focus (left-to-right)
   - facts (.is-drawn, set by IntersectionObserver): left-to-right
   - join us (.is-drawn): right-to-left (its strokes start on the right,
     so the same technique draws them the opposite way)
   pathLength="1" on every path lets one dash value cover any line length.
   --i = stroke order (sorted by x); --n = stroke count → staggered sweep.
   ================================================================= */
.fx-draw { overflow: visible; }
.fx-line {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  /* One liquid feel for every background pattern: the soft ease-in-out curve
     (gentle start, gentle settle). Duration halved to ~275ms for a snappier
     draw/un-draw; same curve, same per-stroke stagger preserving each
     pattern's sweep direction. */
  transition: stroke-dashoffset 0.275s var(--ease-soft);
  transition-delay: calc(var(--i, 0) / var(--n, 1) * 0.2s);
}
[data-fx-scroll].is-drawn .fx-line,
.card:hover .fx-line,
.card:focus-within .fx-line,
.card.is-active .fx-line { stroke-dashoffset: 0; }

@media (prefers-reduced-motion: reduce) {
  /* Only the scroll-in entrance patterns (Facts, Join Us) show fully drawn.
     The card diamond is a HOVER state, so it stays hidden until hover. */
  [data-fx-scroll] .fx-line { stroke-dashoffset: 0 !important; transition: none !important; }
}

/* ----- Scroll-synced scrub (Facts pattern) -----
   Instead of a fixed-duration play, the draw is tied to scroll position via
   --draw (0→1), which fx.js sets from the block's position in the viewport:
   0 when the block's TOP enters view, 1 when its BOTTOM enters view. There's
   no transition — scroll position IS the timeline, so it scrubs forward on the
   way down and reverses on the way up. Each line still draws left-to-right:
   line i animates over its own slice of the progress (a --stagger-wide window
   offset by i/n), so lower-i (left) strokes complete first. */
[data-fx-scrub] .fx-line {
  --p: var(--draw, 0);
  --stagger: 0.3;
  --order: var(--i, 0);   /* stagger sequence position (default: as authored) */
  /* --lp = this line's local progress 0→1 (its slice of the scroll progress) */
  --lp: clamp(0, (var(--p) - var(--order) / var(--n, 1) * var(--stagger)) / (1 - var(--stagger)), 1);
  transition: none;
  stroke-dashoffset: calc(1 - var(--lp));   /* draw from the path's start */
}
/* Facts: reverse the DRAW DIRECTION of each stroke (not the stagger order). The
   zig-zag strokes are authored apex-first (M = the far end, L = the shared apex
   at y≈384), so the default start→end draw makes every stroke grow TOWARD that
   apex — reading as all lines converging on a flat horizontal. Flipping the dash
   anchor (-1→0 instead of 1→0) draws each stroke from the apex OUTWARD along its
   own diagonal: "\" downward, "/" upward, tracing the zig-zag. Scoped to Facts
   (the scrub pattern without the Join's data-fx-rtl flag). */
[data-fx-scrub]:not([data-fx-rtl]) .fx-line {
  stroke-dashoffset: calc(var(--lp) - 1);   /* draw from the path's end */
}
/* Reverse the stagger SEQUENCE (which line draws first) — NOT each line's own
   draw direction. The Join fan's lines are authored top-to-bottom, so by
   default they sweep top-first on scroll down; flipping --order to (n-1-i)
   makes the sweep run the other way to follow the scroll. Scoped to the Join
   pattern via its data-fx-rtl flag; Facts (no flag) keeps the authored order. */
[data-fx-scrub][data-fx-rtl] .fx-line {
  --order: calc(var(--n, 1) - 1 - var(--i, 0));
}
/* (No prefers-reduced-motion override for the scrub patterns: they're intentionally
   animated for everyone — see the matching note in fx.js. The reveal is a gentle
   scroll-tied draw, not autonomous motion.) */

/* =================================================================
   THE MOMENT
   ================================================================= */
.moment {
  position: relative;          /* containing block for the bg pattern */
  background: var(--light-blue);
  display: flex;
  flex-direction: column;
  gap: 75px;
  overflow: hidden;            /* clip the pattern's bleed */
}
/* Background line pattern (— / —): top-LEFT, full width, in the upper area, behind
   the content. Reuses the shared scrub-draw system; data-fx-scrub-enter ties the
   draw to the pattern's own top→bottom entering the viewport (see fx.js). The art
   is stretched to its Figma box per breakpoint (preserveAspectRatio="none"), so
   the horizontals stay level while the diagonal fan adapts. z-index 0 +
   pointer-events:none → content stays on top, legible, and clickable. */
.moment__pattern {
  position: absolute;
  top: var(--pad-y);           /* starts at the content top (Figma top ≈ pad-y) */
  left: 0;
  width: 100%;
  aspect-ratio: 1440 / 1008;   /* desktop natural proportions */
  pointer-events: none;
  z-index: 0;
}
@media (max-width: 1024px) { .moment__pattern { aspect-ratio: 835 / 1013; } }  /* 835 frame */
@media (max-width: 600px)  {
  /* ROOT-CAUSE FIX for the mobile skew. On desktop the element is forced to the
     375/866 box and preserveAspectRatio="none" stretches the 1440×1008 viewBox
     ≈3.3× more vertically than horizontally → the diagonal fan skews near-vertical.
     Instead, give the element the viewBox's OWN aspect (1440/1008) and let it fill
     the section height; now "none" scales UNIFORMLY (no distortion), so the diagonals
     keep their true Figma angle (~50°). The art is wider than 375 and bleeds off the
     sides (.moment clips it) exactly as the Figma mobile frame shows. We anchor with
     left:50% + a translateX in % of the element's own width so the fold's vertical
     edge lands at ≈60% of the viewport — matching the Figma mobile composition —
     and stays put across the 375–600 range. The scrub-draw is unaffected: fx.js
     reads the element box (height-filled here), not the inner SVG. */
  .moment__pattern {
    top: 0;
    bottom: 0;
    left: 50%;
    width: auto;
    height: auto;
    aspect-ratio: 1440 / 1008;
    transform: translateX(-24.4%);
  }
  .moment__pattern .fx-draw { transform: none; }
}
.moment__pattern .fx-draw { display: block; width: 100%; height: 100%; }
.moment__content,
.moment__photos { position: relative; z-index: 1; }
.moment__content {
  display: flex;
  gap: clamp(40px, 8vw, 125px);
  align-items: flex-start;
  justify-content: flex-end;
}
.moment__text {
  flex: 0 1 889px;          /* Figma right content block = 889px */
  display: flex;
  flex-direction: column;
  gap: 50px;
}
.moment__text .section__title { line-height: 0.8; }
.moment__photos {
  display: flex;
  align-items: center;
  justify-content: flex-end;
}
.moment__photo {
  flex: 1 1 0;
  min-width: 0;
  object-fit: cover;
  border-radius: 10px;
}
.moment__photo--right { height: 728px; margin-right: -45px; }     /* overlap, per Figma */
.moment__photo--left  { height: 462px; border: 3px solid var(--light-blue); }
/* Desktop ONLY: the photo pair is NOT full-bleed. Per the Figma desktop frames the
   "Photos" block is a fixed width — 1136px @1440, 1245px @1720 — right-aligned so its
   LEFT edge lines up with "The Moment". Width interpolates linearly between the two
   frames; heights stay 728/462 (base). Scoped to ≥1025 so the 835 + 375 layouts
   (which size the photos by aspect-ratio) are completely untouched. */
@media (min-width: 1025px) {
  .moment__photos {
    width: clamp(1136px, calc(38.93vw + 575px), 1245px);
    align-self: flex-end;     /* right-align the block → left edge meets the tag */
  }
}

/* =================================================================
   QUOTE
   ================================================================= */
.quote {
  position: relative;
  min-height: 800px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--pad-y) var(--pad-x);
  /* Art-directed photo: phone crop by default, swapped at each breakpoint */
  background: var(--black) url('../images/quote-mobile.jpg') center/cover no-repeat;
}
.quote__text {
  max-width: 968px;
  text-align: center;
  font-size: var(--fs-quote);
  line-height: 0.9;
  letter-spacing: -0.02em;
  color: var(--light-yellow);
}

/* =================================================================
   FACTS
   ================================================================= */
.facts {
  /* Full-bleed like the other .section blocks (it is class="section facts"): the
     light-yellow background AND the zig-zag pattern run edge-to-edge at ANY width,
     while the grid content (photo column + myths) stays capped at --max-width and
     centred by the shared .section full-bleed padding. (Previously this was capped
     at 1720 + centred; past 1720 the background relied on matching the page colour
     and the pattern stopped short of the screen edges.) */
  position: relative;
  background: var(--light-yellow);
  display: grid;
  /* Photo column flexes narrow; the myth text column holds ~860px wide,
     so it stays readable from 1440 up to 1720 (matches Figma's reflow). */
  grid-template-columns: minmax(0, 1fr) minmax(0, 860px);
  gap: clamp(40px, 6vw, 75px);
  align-items: stretch;
  overflow: hidden;
}
/* Zig-zag line texture (inline SVG, yellow) — draws on when scrolled into view.
   Placement matches Figma's "Pattern" frame on the Facts block: flush to the
   LEFT (x=0), spanning the full block width and bleeding off the right
   (1720 wide in a 1440 block = 119.44%), with the art bleeding 87px ABOVE the
   block top. The earlier rule pinned it left:-12% at only 70% width, which
   shifted it off-left and cropped the right half of the chevron, and offset it
   17px DOWN instead of up. aspect-ratio keeps the art's native proportions and
   translateY expresses the -87px top bleed as a share of the pattern's own
   height (-87/1528), so it scales correctly at every width. */
.facts__pattern {
  position: absolute;
  /* The bowtie/ray pattern is SYMMETRIC: its convergence spine runs down the
     CENTRE of the asset, with lines fanning to all four corners. The SVG viewBox
     is now LANDSCAPE (1721.56 × 1615.9) so its aspect matches the desktop block —
     the element is the WHOLE block (inset:0) and the art FILLS it
     (preserveAspectRatio="none") with no skew, both fans fully visible, nothing
     clipped. (Previously the viewBox was PORTRAIT (1615.9 × 1721.56) holding the
     same lines rotated 90°, so stretching it into the landscape block rotated the
     whole pattern the wrong way — the fan ran left↔right instead of top↔bottom.)
     The scrub-draw re-anchors automatically — fx.js drives --draw from THIS
     element's box. */
  inset: 0;
  pointer-events: none;
  z-index: 0;
  overflow: hidden;     /* clip the cover panel (and any art bleed) to the block */
}
/* TOP→BOTTOM reveal: a solid light-yellow cover panel (::after) sits over the fan and
   retracts toward the bottom (scaleY 1→0, origin bottom) — uncovering the pattern from
   the top down. It's a plain `transform` TRANSITION (not a scroll-scrub), so:
     • at rest the pattern is FULLY drawn, filling the whole block (cover scaled to 0);
     • when the block scrolls into view fx.js adds .is-revealed → the wipe plays once
       (~1.4s); it replays if you leave and return.
   transform transitions repaint reliably in every browser (this is what finally fixed
   the "won't animate in Safari/Chrome" problem — clip-path and scrubbed inline styles
   did not). Default (no JS / not yet in view) = fully covered; JS reveals it. */
.facts__pattern::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--light-yellow);
  transform-origin: bottom;
  transform: scaleY(1);                 /* fully covers the fan (hidden) */
  transition: transform 1.4s var(--ease-soft);
  pointer-events: none;
  z-index: 1;           /* above the SVG art, below .facts__content (z-index:1, sibling) */
}
.facts__pattern.is-revealed::after { transform: scaleY(0); }   /* retract → reveal top→bottom */
/* TABLET + MOBILE (≤1024 — the single-column range where .facts__media is hidden):
   the block is narrow + tall, so preserveAspectRatio="none" stretched the landscape
   viewBox NON-UNIFORMLY into the portrait block → the fan skewed/distorted. Instead,
   give the element the viewBox's OWN aspect ratio and fill the HEIGHT (centred; the
   extra width bleeds off the sides and is clipped by .facts overflow:hidden). Now
   "none" scales UNIFORMLY (no skew): we see an OFF-CENTRE CROP of the fan at its
   natural proportions — exactly how Figma frames it (it positions the full-size art
   larger than the block and clips, rather than re-fitting it). Matches the Figma
   835 frame (Facts Block 10319-822 → Pattern 3 10473-2183) and the 375 frame
   (10325-1069 → 10473-2511). The scrub-draw re-anchors automatically (fx.js reads
   this box, whose vertical extent is unchanged). */
@media (max-width: 1024px) {
  .facts__pattern {
    inset: auto;
    top: 0;
    bottom: 0;
    left: 50%;
    width: auto;
    aspect-ratio: 1721.56 / 1615.9;
    transform: translateX(-50%);
  }
}
/* (>1720 keeps the same focal-at-31% placement as the base — the percentage
   width/left scale with the full-bleed block, so no override is needed.) */
.facts__pattern .fx-draw {
  display: block;
  width: 100%;
  /* Bleed the art a hair PAST the block's bottom and let .facts overflow:hidden
     clip it. The block's height is fractional (e.g. 1542.94px), so at dpr 1 the
     art's bottom edge lands on a sub-pixel boundary and the last device-px row
     rounded to the bare background → a ~1px gap. Over-scanning the bottom makes
     the fill always reach the edge cleanly at EVERY width/DPR (no per-width nudge);
     the extra is clipped, so nothing bleeds into the next section. */
  height: calc(100% + 2px);
}
/* Lines are always solid (the clip-path does the reveal, not stroke-dashoffset).
   Scoped to Facts so the other scrub patterns (diversion, moment, join) keep their
   own per-line draw. Specificity ties the shared [data-fx-scrub] rule and wins on
   source order (this block comes later). */
.facts__pattern[data-fx-scrub] .fx-line {
  stroke-dasharray: none;
  stroke-dashoffset: 0;
  transition: none;
}
.facts__content, .facts__media { position: relative; z-index: 1; }
/* "The Facts" section tag (Figma "Content Header"). Reuses .eyebrow-serif.
   Desktop (≥1025): sits at the block's top-LEFT corner, level with the heading
   (which stays in the right text column). Placed OUT OF FLOW (absolute, anchored
   to the section's own padding box) so the photo|text grid, the scrub-draw
   pattern and the myth layout are all untouched — it just fills the empty
   top-left corner above the photos. Tablet/Mobile (≤1024): the photo column is
   hidden and the block is a single column, so the tag drops in as the first
   in-flow item, stacking directly above the heading. */
.facts__tag {
  position: absolute;
  top: var(--pad-y);
  left: max(var(--pad-x), calc((100% - var(--max-width)) / 2 + var(--pad-x)));
  z-index: 1;
  line-height: 2;                 /* Figma tag leading */
  white-space: nowrap;
}
/* ≤1024 (835 frame): in flow as the first single-column grid item. The grid
   row-gap is 40px; pull up to the Figma 8px tag→heading gap. */
@media (max-width: 1024px) {
  .facts__tag { position: static; margin-bottom: -32px; }
}
/* ≤600 (375 frame): 0px tag→heading gap. */
@media (max-width: 600px) {
  .facts__tag { margin-bottom: -40px; }
}
/* Decorative left images (overlapping pair) */
.facts__media {
  position: relative;
  align-self: stretch;
}
.facts__img {
  position: absolute;
  object-fit: cover;
  border-radius: 10px;
}
.facts__img--top {
  top: 16%;
  right: 0;                /* Figma: SMALLER top photo, upper-RIGHT, behind */
  width: 72%;              /* matches Figma 257px @1440; capped so it doesn't over-grow @1720 */
  max-width: 368px;        /* Figma 1720 top photo width */
  aspect-ratio: 368 / 376; /* Figma top photo (no crop) */
}
.facts__img--bottom {
  top: 40%;
  left: 0;                 /* Figma: LARGER bottom photo, lower-LEFT, in front, overlapping */
  width: 92%;             /* matches Figma 328px @1440 */
  max-width: 481px;       /* Figma 1720 bottom photo width */
  aspect-ratio: 481 / 486; /* Figma bottom photo (was 328/362 → too tall) */
  border: 3px solid var(--light-yellow);
}
.facts__content {
  display: flex;
  flex-direction: column;
  gap: 75px;
}
/* Myths list */
.myths {
  display: flex;
  flex-direction: column;
  gap: 56px;
}
.myth {
  display: flex;
  gap: clamp(24px, 5vw, 75px);
  align-items: flex-start;
}
.myth__claim {
  flex: 0 0 clamp(160px, 20vw, 260px);
  font-family: var(--font-body);
  font-style: italic;
  font-size: var(--fs-body);
  line-height: 1.4;
}
.myth__truth {
  flex: 1 1 0;
  min-width: 0;
  max-width: 537px;
  font-family: var(--font-serif);
  font-size: var(--fs-myth);
  line-height: 1.1;
  letter-spacing: -0.02em;
}
/* Footnote at the bottom of the Facts section (Figma: Neue Haas / body font,
   italic, 18px — smaller than the 28–32px serif answers). Left-aligned to the
   content edge, capped to the myth-row width. */
.facts__footnote {
  max-width: 860px;
  font-family: var(--font-body);
  font-style: italic;
  font-size: var(--fs-body);   /* 18px at every breakpoint */
  line-height: 1.4;
  color: var(--black);
}
/* Highlighted phrases inside a myth — colour is set per myth via --hl */
.hl { color: inherit; }
.myth--green  .hl { --hl: var(--green); }
.myth--yellow .hl { --hl: var(--yellow); }
.myth--blue   .hl { --hl: var(--highlight-blue); }   /* #94E1FF — Figma */
.myth--coral  .hl { --hl: var(--coral); }
.myth--white  .hl { --hl: #ffffff; }                 /* Figma solid white */

/* =================================================================
   MARKER HIGHLIGHT WIPE (Option B)
   The highlight colour fills in left-to-right when the phrase scrolls into
   view (.is-drawn, toggled by the IntersectionObserver) and un-fills — the
   wipe reverses back to no highlight — when it scrolls out, re-filling on the
   way back in. box-decoration-break: clone gives each wrapped line its own
   marker box, so every line wipes L→R (in parallel). Real selectable text.
   Same soft ease-in-out curve as the background patterns (var(--ease-soft)).
   ================================================================= */
.hl,
.lead-accent {
  /* clear the <mark> user-agent default (yellow) so the resting state is
     plain text — the colour comes only from the animated gradient below */
  background-color: transparent;
  background-image: linear-gradient(var(--hl, transparent), var(--hl, transparent));
  background-repeat: no-repeat;
  background-position: 0 0;            /* fill grows from the left */
  background-size: 0% 100%;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
  transition: background-size 0.275s var(--ease-soft);
}
.hl.is-drawn,
.lead-accent.is-drawn { background-size: 100% 100%; }
@media (prefers-reduced-motion: reduce) {
  .hl, .lead-accent { background-size: 100% 100% !important; }
}

/* =================================================================
   CALIFORNIA BUILT
   ================================================================= */
.california {
  background: var(--light-coral);
  display: flex;
  gap: clamp(40px, 6vw, 75px);
  align-items: center;
}
.california__content {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 50px;
  align-items: flex-start;
}
/* "What's at Stake?" section tag (Figma "Header Content"): grouped with the
   heading so the tag→heading spacing is tight while the group keeps the content
   column's rhythm (50px desktop / 25px below) to the body. The tag reuses the
   site's section-tag treatment (.eyebrow-serif). Only the tag is new — the
   heading, body copy and coral highlight are untouched. */
.california__header {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 18px;                /* tag → heading (1720 / 1440 frames) */
  width: 100%;
}
.california__tag { line-height: 2; }   /* Figma tag leading: 2 */
@media (max-width: 1024px) { .california__header { gap: 8px; } }   /* 835 frame */
@media (max-width: 600px)  { .california__header { gap: 0; } }     /* 375 frame */
.california__highlight { color: var(--black); font-size: var(--fs-serif-m); }
/* On mobile this coral chip wraps; make it an inline per-line marker (clone)
   with tighter padding so each line hugs its words instead of forming one box.
   Desktop (single-line chip) is untouched. */
@media (max-width: 834px) {
  .california__highlight {
    display: inline;
    box-decoration-break: clone;
    -webkit-box-decoration-break: clone;
    padding: 0.15em 0.3em;
    line-height: 1.5;
  }
}
.california__media {
  flex: 1 1 0;
  min-width: 0;
  display: block;
}
.california__media img {
  width: 100%;
  height: 453px;           /* Figma keeps this slot 453px tall, cropping width */
  display: block;
  object-fit: cover;
  border-radius: 10px;     /* no stroke — Figma image has none */
}

/* =================================================================
   JOIN US
   ================================================================= */
.join {
  position: relative;
  background: var(--blue);
  padding: var(--pad-y) var(--pad-x);
  overflow: hidden;
}
/* Fan pattern (inline SVG, light-blue) — draws on right-to-left when in view.
   inset:0 makes the pattern box the FULL block (top→bottom), like
   .facts__pattern. The SVG's preserveAspectRatio="...slice" then covers that
   box at any size, so the fan fills the whole block with no bottom gap. The
   earlier aspect-ratio sized the height off the WIDTH, so it only matched the
   block height at ~1720 and left a growing gap at narrower widths. */
.join__pattern {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
}
.join__pattern .fx-draw { display: block; width: 100%; height: 100%; }
.join__inner {
  position: relative;
  z-index: 1;
  max-width: var(--max-width);
  margin-inline: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 25px;
}
.join__eyebrow { color: var(--black); }
/* "Join Us" reuses the EXACT Facts text-colour animation: the shared .hl
   marker wipe (light-blue grows 0%→100% on the same 0.5s ease-in-out curve),
   triggered by data-fx-scroll when the block scrolls into view — no separate
   animation. This rule only supplies the chip's box/typography; the colour
   inherits black from .join__eyebrow via `.hl { color: inherit }`. */
.join__eyebrow .join__eyebrow-mark {
  --hl: var(--light-blue);
  display: inline;
  padding: 8px 10px;
  font-family: var(--font-serif);
  font-size: var(--fs-serif-l);
  line-height: 1.1;
  letter-spacing: -0.02em;
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
}
.join__title {
  font-size: var(--fs-display-lg);
  line-height: 0.8;
  color: var(--light-blue);
}
.join__sub {
  font-size: var(--fs-body);
  color: var(--light-blue);
}

/* =================================================================
   FOOTER
   ================================================================= */
/* =================================================================
   COMPONENT — Footer
   Desktop / iPad: logo+tagline left, links right, legal centered.
   Mobile: everything centered and stacked.
   ================================================================= */
/* =================================================================
   COMPONENT — Footer (Figma "Footer" — Desktop/iPad/Mobile)
   Desktop: uppercase wordmark + highlighted serif tagline (left), nav links
   with arrows + Get Involved CTA in a row (right), legal bottom-right.
   iPad (≤1439): nav links stack & right-align, legal centered.
   Mobile (≤834): everything centered and stacked.
   ================================================================= */
/* Full-bleed black background at ANY width (incl. ultra-wide > 1720) — the
   max-width cap lives on the inner wrapper, not the background. */
/* =================================================================
   COMPONENT — Footer (Figma redesign — Desktop/iPad/Mobile)
   Full-bleed BLACK background at ANY width (incl. ultra-wide > 1720). The
   content stays within --max-width and centres via .site-footer__inner.
   Top row: campaign quote (left) + nav/CTA (right). Divider. Bottom row:
   wordmark + tagline (left) + legal (right).
   ================================================================= */
.site-footer {
  background: var(--black);
  color: var(--light-blue);
}
/* Only the background runs edge-to-edge; this caps + centres the content. */
.site-footer__inner {
  max-width: var(--max-width);
  margin-inline: auto;
  padding: 50px var(--pad-x);
  display: flex;
  flex-direction: column;
  gap: clamp(64px, 9.4vw, 135px);
}
.site-footer__top {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 40px;
}
/* Campaign quote — large display type, light-blue */
.site-footer__quote {
  max-width: 600px;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(36px, 5.5vw, 75px);
  line-height: 0.9;
  letter-spacing: -0.02em;
  color: var(--light-blue);
}
.site-footer__nav {
  display: flex;
  align-items: center;
  gap: 75px;                /* Figma desktop footer links gap (iPad/mobile override below) */
}
/* About / Facts / Impact — text only. On hover/focus a #2966C3 pill wipes in
   behind the text — the same scaleX marker technique used elsewhere (GPU-
   friendly, link text colour unchanged), shaped to a rounded pill. */
.site-footer__link {
  position: relative;
  isolation: isolate;            /* scope the negative-z marker to the link */
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.25;
  color: var(--light-blue);
  text-decoration: none;
}
.site-footer__link::before {
  content: "";
  position: absolute;
  inset: -0.25em -0.5em;         /* marker hugs the text */
  z-index: -1;                   /* rectangular corners — matches the nav highlight */
  background: var(--blue);       /* #2966C3 */
  transform: scaleX(0);
  transform-origin: left center; /* wipe grows from the left */
  transition: transform 0.55s var(--ease-soft);
}
.site-footer__link:hover::before,
.site-footer__link:focus-visible::before { transform: scaleX(1); }
.site-footer__link:focus-visible { outline: 2px solid var(--light-blue); outline-offset: 2px; }
/* Get Involved reuses the shared .btn / .btn--light-blue; make the focus ring
   visible against the dark footer (default is black). */
.site-footer .btn:focus-visible { outline-color: var(--light-blue); }

/* Bottom row — divider + wordmark/tagline (left) + legal (right) */
.site-footer__bottom {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 40px;
  border-top: 1px solid var(--light-blue);
  padding-top: 30px;
}
.site-footer__brand {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 18px;
}
.site-footer__logo {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 20px;
  line-height: 1;
  text-transform: uppercase;
  color: var(--light-blue);
}
/* SVG wordmark logo — same ~248.7px width the text logo occupied (all breakpoints). */
.site-footer__logo-img { display: block; width: 248.7px; height: auto; }
/* Tagline: serif phrase on a Highlight-Blue marker that WIPES in left-to-right
   on scroll-into-view — reuses the shared .hl wipe (background-size 0→100% on
   the soft ease, toggled by the IntersectionObserver). The marker is on an
   inline span (box-decoration-break hugs each line); colour inherits black. */
.site-footer__tagline { color: var(--black); }
.site-footer__tagline .site-footer__tagline-mark {
  --hl: var(--highlight-blue);   /* #94E1FF — per Figma */
  font-family: var(--font-serif);
  font-size: 20px;
  line-height: 1.1;
  letter-spacing: -0.02em;
  padding: 0.1em 0.22em;
}
.site-footer__legal {
  text-align: right;
  font-size: 13px;
  color: var(--light-blue);
}
.site-footer__legal a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
  transition: color 0.2s ease-in-out;
}
.site-footer__legal a:hover { color: var(--white); }
.site-footer__legal a:focus-visible { outline: 2px solid var(--light-blue); outline-offset: 2px; }

/* iPad (≤1439): nav links stack & right-align (CTA below); bottom row stays */
@media (max-width: 1439px) {
  .site-footer__nav { flex-direction: column; align-items: flex-end; gap: 40px; }
}
/* Mobile (≤834): everything centred and stacked */
@media (max-width: 834px) {
  .site-footer__top { flex-direction: column; align-items: center; gap: 40px; }
  .site-footer__quote { max-width: none; text-align: center; }
  .site-footer__nav { align-items: center; gap: 25px; }
  .site-footer__bottom { flex-direction: column; align-items: center; gap: 24px; }
  .site-footer__brand { align-items: center; text-align: center; }
  .site-footer__legal { text-align: center; }
}
@media (prefers-reduced-motion: reduce) {
  .site-footer__link::before { transition: none; }
}

/* =================================================================
   ART DIRECTION — swap the full-bleed photo crops at each breakpoint
   (375 phone · 835 tablet · 1440 desktop · 1720 wide desktop)
   Each hero crop is rendered at its Figma frame's exact size from the one
   source photo, so the subject stays anchored left and the sky fills the
   right; background-size:cover + left-anchor (set on .hero) keeps the same
   art direction at in-between widths and full-bleed past 1720 (Strategy A).
   ================================================================= */
@media (min-width: 835px) {
  .hero  { background-image: url('../images/hero-835.jpg'); }
  .quote { background-image: url('../images/quote-ipad.jpg'); }
}
/* Quote photo at the tablet range only (835–1439): Figma anchors this crop to
   the TOP of the block (top: -0.06%, full height), but the base rule centres it.
   The 835-wide tablet image has to scale UP to cover wider tablet viewports,
   which overflows vertically — centring then crops the subject's head top/bottom.
   Anchoring to the top matches Figma. (Horizontal is irrelevant here: the image
   always fills the width exactly. 375 / 1440 / 1720 keep the base centre.) */
@media (min-width: 835px) and (max-width: 1439px) {
  .quote { background-position: center top; }
  /* Tablet (835 Figma frame) specifics. Font sizes already match — body 18px,
     buttons 14px/12px, nav links 16px — but the build's body line-height and nav
     gutter were carrying desktop values; the 835 frame uses 1.2 leading and a
     50px nav gutter (vs the 75px section gutter). */
  .body-copy { line-height: 1.2; }
  .nav { padding-inline: 50px; }
}
@media (min-width: 1440px) {
  .hero  { background-image: url('../images/hero-1440.jpg'); }
  .quote { background-image: url('../images/quote-desktop.jpg'); }
}
/* Wide desktop: the dedicated 1720 frame crop. From here up the background
   bleeds edge-to-edge (cover) while the content stays capped/centred. */
@media (min-width: 1720px) {
  .hero  { background-image: url('../images/hero-1720.jpg'); }
}

/* =================================================================
   RESPONSIVE — stack the two-column layouts below the tablet width
   Refined per the 1720 / 1440 / 835 / 375 Figma frames.
   ================================================================= */
/* ---- TABLET (matches the 835px frame) ---- */
@media (max-width: 1024px) {
  /* Diversion: the row stacks — photo full-width above the copy (Figma 835
     shows it between the heading and the body), then cards stack below. */
  .diversion__row { display: flex; flex-direction: column; gap: 50px; }
  /* width:100% (not the base flex sizing) so the photo matches the card column
     exactly — same left/right edges as the cards, not the image's intrinsic px. */
  .diversion__media { display: block; order: -1; flex: none; width: 100%; }
  .diversion__media img { height: 300px; }
  /* flex:none is the real fix for the empty gap below the button. The base
     `.diversion__content { flex: 0 1 644px }` means 644px COLUMN WIDTH in the
     desktop row — but here the row is flex-direction:column, so that 644px
     leaks onto the MAIN axis (height), forcing the text column 644px tall and
     stranding the button ~390px above the row's bottom. flex:none → the column
     sizes to its own content height, so the button sits at the bottom and the
     cards follow 75px later. No fixed height anywhere. */
  .diversion__content { width: 100%; gap: 25px; flex: none; }
  /* 75px section rhythm per the 835 frame: heading→image and button→card. */
  .diversion { gap: 75px; }
  .steps { grid-template-columns: 1fr; gap: 22px; }   /* stack; 22px between cards */
  /* Cards inherit the base flex-end (title hugs the bottom) and the content-
     driven --card-reserve height (set by fx.js to the tallest card's full
     revealed content) — equal heights with NO hardcoded px, and room for the
     title to move UP as the body reveals on hover. */
  .card__body { min-height: 0; }
  /* Cards are landscape when stacked — give the fan a portrait box matching its
     own proportions (so preserveAspectRatio="none" doesn't squash it), anchored
     to the top and clipped by the card. */
  /* Patterns re-sized to the stacked (landscape) card box per the iPad frame. */
  .card--green  .card__pattern { width: 60.7%; aspect-ratio: 416 / 327; }
  .card--yellow .card__pattern { aspect-ratio: 684 / 304; }
  .card--blue   .card__pattern { aspect-ratio: 682 / 348; }

  /* Moment: "The Moment" label moves above the headline; photos shrink */
  .moment__content { flex-direction: column; gap: 25px; }
  .moment__text { flex-basis: auto; width: 100%; gap: 25px; }
  .moment__photo--right { height: auto; aspect-ratio: 365 / 538; }
  .moment__photo--left  { height: auto; aspect-ratio: 365 / 298; }

  /* Facts: single column, decorative photos dropped, myth claim stacks above truth */
  .facts { grid-template-columns: 1fr; gap: 40px; }
  .facts__media { display: none; }
  .facts__content { gap: 40px; }
  .myths { gap: 40px; }
  .myth { flex-direction: column; gap: 25px; align-items: flex-start; }
  .myth__claim { flex: none; }
  .myth__truth { max-width: none; }
  /* Footnote tucks closer to the last myth than the inter-myth gap when
     stacked: Figma is 15px @375 and 25px @835. The facts__content gap is
     40px @375 / 50px @835, so a -25px pull lands both values. */
  .facts__footnote { margin-top: -25px; }

  /* California: stacks, image full width below the text */
  .california { flex-direction: column; align-items: stretch; gap: 40px; }
  .california__content { gap: 25px; }
  .california__media img { height: auto; aspect-ratio: 685 / 400; }
}

/* iPad (601–1024): the Facts pattern uses the SAME focal-at-31%, full-height
   placement as desktop/mobile (the old bottom-anchored override was for the
   previous chevron art and put the sunburst's focal on the wrong side). */
@media (min-width: 601px) and (max-width: 1024px) {
  /* Facts spacing per the 835 frame: header→myths and myth→myth are 50px
     (the shared tablet rule used 40). Scoped to 835 so 375 is unchanged. */
  .facts__content { gap: 50px; }
  .myths { gap: 50px; }
  /* California stacks with a 75px gap between the copy and the image at 835
     (the shared tablet rule used 40). */
  .california { gap: 75px; }
}

/* ---- MOBILE (matches the 375px frame) ---- */
@media (max-width: 600px) {
  /* Hero / Quote heights shrink */
  .hero { min-height: 600px; }
  .hero__inner { gap: 40px; }
  .quote { min-height: 0; }

  /* Diversion: the photo returns, stacked above the text.
     gap = the button→first-card spacing (Impact button is the last item in the
     row, then the .steps). 50px on mobile (iPad uses 75px in the tablet block). */
  .diversion { gap: 50px; }
  .diversion__row { display: flex; flex-direction: column; gap: 50px; }
  /* width:100% so the photo lines up with the card column (see tablet note). */
  .diversion__media { display: block; order: -1; flex: none; width: 100%; }
  .diversion__media img { height: 300px; }
  /* Cards become TAP-to-activate (touch has no hover). Matching the Figma mobile
     (375) frame: the body is ALWAYS shown, tap (.is-active) turns the card coral
     and draws the line pattern. Layout per the frame: content bottom-anchored
     (justify-end, inherited), 50px top/bottom · 24px side padding, 18px title↔body
     gap; equal heights still come from --card-reserve (no fixed height). */
  .card { padding: 50px 24px; }
  .card__toggle { pointer-events: auto; }              /* the tap target on touch */
  /* Body always visible (override the hover-collapse, both grid + fallback) */
  .card__content { grid-template-rows: auto auto; }
  .card__body {
    max-height: none;
    opacity: 1;
    transform: none;
    padding-top: 18px;                                 /* title↔body gap (Figma 18) */
  }
  /* Tap/active turns the card CORAL (matches the Figma mobile active state),
     same coral used elsewhere on the site. Hover/focus keep the native colour
     (touch has no hover; focus alone must not flip it). */
  .card:hover,
  .card:focus-within { background: var(--card-bg); }
  .card.is-active { background: var(--coral); }
  /* The pattern draws ONLY when tapped (.is-active), never on hover/focus, so the
     on/off toggle reads cleanly (focus alone must not leave it drawn). */
  .card:hover .fx-line,
  .card:focus-within .fx-line { stroke-dashoffset: 1; }
  .card.is-active .fx-line { stroke-dashoffset: 0; }

  /* Moment: photos shrink to the mobile crop ratios */
  .moment { gap: 40px; }
  .moment__photo--right { aspect-ratio: 190 / 256; }
  .moment__photo--left  { aspect-ratio: 190 / 166; }

  /* Facts: tighter spacing between the claim and its statement */
  .myth { gap: 15px; }

  /* California: portrait image on mobile */
  .california { gap: 30px; }
  .california__media img { aspect-ratio: 335 / 400; }
}

/* Respect users who prefer reduced motion — site-wide: no animation/
   transition, final states shown instantly. (Specific draw/hover states
   above also force their final values for this case.) */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *,
  *::before,
  *::after {
    transition-duration: 0.001ms !important;
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
  }
}
