/* =========================================================
   Focus on Relationships — prototype stylesheet
   Vanguard Marriage and Family Advocates
   ========================================================= */

:root {
  /* Brand */
  --c-brand: #176fe9;
  --c-brand-deep: #0f4fa8;
  --c-brand-soft: #e6efff;

  /* Neutrals */
  --c-ink: #0a0a0a;
  --c-paper: #ffffff;
  --c-mute: #555;
  --c-line: #e5e7eb;
  --c-shade: #f5f6f8;

  /* Type */
  --f-display: "Plus Jakarta Sans", "Geist", system-ui, sans-serif;
  --f-body: "Geist", system-ui, sans-serif;
  --f-mono: "Geist Mono", ui-monospace, monospace;

  /* Spacing */
  --s-1: 8px;
  --s-2: 16px;
  --s-3: 24px;
  --s-4: 40px;
  --s-5: 64px;
  --s-6: 96px;
  --s-7: 140px;

  /* Container */
  --container: 1320px;
  --gutter: 48px;

  /* Motion */
  --ease: cubic-bezier(0.4, 0, 0.2, 1);
  --d-sm: 200ms;
  --d-md: 300ms;
  --d-lg: 500ms;
}

/* Tablet-down: pull the gutter in so giant clamp() heads aren't hugging
   the viewport edge. Sections that hard-code their padding-inline at
   600/380px breakpoints still win — this is the global default. The
   1023px ceiling keeps desktop layout (sticky flow kicks in at 1024px)
   on the original 48px gutter. */
@media (max-width: 1023px) {
  :root { --gutter: 32px; }
}
@media (max-width: 600px) {
  :root { --gutter: 24px; --s-7: 96px; --s-6: 72px; }
}
@media (max-width: 380px) {
  :root { --gutter: 16px; }
}

* { box-sizing: border-box; }
/* When Lenis is active, it controls smoothness — the native CSS smooth
   behavior fights it on anchor jumps. Lenis adds .lenis-smooth to <html>;
   we disable native scroll-behavior in that case only. */
html { scroll-behavior: smooth; }
html.lenis, html.lenis body { height: auto; }
html.lenis-smooth { scroll-behavior: auto; }
body {
  margin: 0;
  font-family: var(--f-body);
  font-size: 20px;
  line-height: 1.55;
  color: var(--c-ink);
  background: var(--c-paper);
  -webkit-font-smoothing: antialiased;
}
img, video { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; }
strong { font-weight: 600; }
em { font-style: italic; }
.muted { color: var(--c-mute); font-weight: 400; }

/* ---------- Nav ---------- */
.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 50;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 22px var(--gutter);
  background: transparent;
  border-bottom: 1px solid transparent;
  color: #fff;
  font-family: var(--f-mono);
  font-size: 14px;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  transition: background var(--d-md) var(--ease),
              border-color var(--d-md) var(--ease),
              color var(--d-md) var(--ease),
              backdrop-filter var(--d-md) var(--ease),
              padding var(--d-md) var(--ease);
}
.nav.is-scrolled {
  background: rgba(255,255,255,0.94);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom-color: var(--c-line);
  color: var(--c-ink);
  padding-block: 14px;
}
.nav__brand {
  display: flex;
  align-items: center;
  gap: 12px;
}
.nav__mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  background: var(--c-brand);
  color: #fff;
  font-weight: 800;
  letter-spacing: 0;
}
.nav__name { font-weight: 500; }
.nav__links {
  display: flex;
  gap: 24px;
  align-items: center;
}
.nav__links a {
  position: relative;
  padding: 4px 0;
  color: inherit;
  transition: color var(--d-sm) var(--ease);
}
.nav__links a:hover { color: var(--c-brand); }
.nav__cta {
  background: var(--c-brand) !important;
  color: #fff !important;
  padding: 12px 18px !important;
  /* Touch target: ensure CTA stays ≥44px tall on every device. */
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}
.nav__cta:hover { background: var(--c-brand-deep) !important; }

/* ---------- Hamburger toggle (hidden on desktop) ---------- */
.nav__toggle {
  display: none;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  min-width: 44px;
  min-height: 44px;
  background: transparent;
  border: 1px solid currentColor;
  color: inherit;
  cursor: pointer;
  font-family: var(--f-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.nav__toggle-bars {
  display: inline-flex;
  flex-direction: column;
  justify-content: space-between;
  width: 18px;
  height: 12px;
}
.nav__toggle-bars span {
  display: block;
  height: 2px;
  background: currentColor;
  transition: transform var(--d-sm) var(--ease), opacity var(--d-sm) var(--ease);
}
.nav__toggle[aria-expanded="true"] .nav__toggle-bars span:nth-child(1) {
  transform: translateY(5px) rotate(45deg);
}
.nav__toggle[aria-expanded="true"] .nav__toggle-bars span:nth-child(2) {
  opacity: 0;
}
.nav__toggle[aria-expanded="true"] .nav__toggle-bars span:nth-child(3) {
  transform: translateY(-5px) rotate(-45deg);
}
.nav__toggle:focus-visible {
  outline: 2px solid var(--c-brand);
  outline-offset: 2px;
}

@media (max-width: 860px) {
  .nav { padding: 16px 24px; }
  .nav.is-scrolled { padding-block: 12px; }
  .nav__name { display: none; }
  .nav__toggle { display: inline-flex; }

  /* Mobile drawer. The .nav__links list, when open, drops down from the
     nav as a full-width panel with stacked links sized for tap (≥52px
     each). Position: absolute against the fixed .nav parent so the drawer
     sits flush below the bar at any scroll state. */
  .nav__links {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 8px 24px 24px;
    background: rgba(255,255,255,0.98);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border-bottom: 1px solid var(--c-line);
    color: var(--c-ink);
    max-height: calc(100vh - 64px);
    overflow-y: auto;
    transform: translateY(-8px);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: transform var(--d-md) var(--ease),
                opacity var(--d-md) var(--ease),
                visibility 0s linear var(--d-md);
    /* iOS safe-area inset for landscape phones with home indicator. */
    padding-bottom: max(24px, env(safe-area-inset-bottom));
  }
  .nav__links.is-open {
    transform: none;
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transition: transform var(--d-md) var(--ease),
                opacity var(--d-md) var(--ease),
                visibility 0s linear 0s;
  }
  .nav__links a {
    display: flex;
    align-items: center;
    min-height: 52px;
    padding: 12px 0;
    font-size: 15px;
    border-bottom: 1px solid var(--c-line);
    color: var(--c-ink);
  }
  .nav__links a:last-child { border-bottom: 0; }
  .nav__links .nav__cta {
    margin-top: 12px;
    justify-content: center;
    border-bottom: 0 !important;
  }
}

/* When the drawer is open, lock body scroll and force the nav bar into
   its scrolled (opaque) styling so the bar and panel read as one chrome. */
body.nav-open { overflow: hidden; }
body.nav-open .nav {
  background: rgba(255,255,255,0.98);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom-color: var(--c-line);
  color: var(--c-ink);
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 16px 24px;
  font-family: var(--f-mono);
  font-size: 14px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border: 1px solid transparent;
  transition: all var(--d-sm) var(--ease);
  cursor: pointer;
}
.btn--primary {
  background: var(--c-brand);
  color: #fff;
}
.btn--primary:hover { background: var(--c-brand-deep); }
.btn--ghost {
  border-color: var(--c-ink);
  color: var(--c-ink);
}
.btn--ghost:hover { background: var(--c-ink); color: #fff; }
.btn--xl { padding: 22px 32px; font-size: 15px; }

/* ---------- Shared bits ---------- */
.dot {
  display: inline-block;
  width: 10px; height: 10px;
  background: var(--c-brand);
  margin-right: 10px;
  vertical-align: middle;
}
.kicker, .display__kicker {
  font-family: var(--f-mono);
  font-size: 14px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--c-mute);
  margin: 0 0 var(--s-2);
}
.kicker--light { color: rgba(255,255,255,0.65); }

/* =========================================================
   HERO
   ========================================================= */
.hero {
  position: relative;
  min-height: 100vh;
  padding: 130px var(--gutter) 90px;
  color: #fff;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  overflow: hidden;
  /* softer brand on dark backgrounds */
  --c-brand: #5fa1ff;
  --c-brand-deep: #2f85f5;
}
.hero__video {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  z-index: 0;
  /* Hero parallax: JS writes transform on scroll. transform-origin keeps
     the scale anchored to the visual center so the slow zoom feels rooted. */
  transform-origin: 50% 50%;
  will-change: transform;
}
.hero__veil {
  position: absolute; inset: 0;
  background:
    linear-gradient(180deg, rgba(10,10,10,0.35) 0%, rgba(10,10,10,0.50) 60%, rgba(10,10,10,0.85) 100%),
    linear-gradient(120deg, rgba(23,111,233,0.18), transparent 60%);
  z-index: 1;
}

.hero__anchor {
  position: relative;
  z-index: 2;
  text-align: right;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--s-3);
  width: 100%;
  margin-left: auto;
}
.hero__display {
  margin: 0;
  font-family: var(--f-display);
  font-weight: 700;
  font-size: clamp(52px, 10vw, 168px);
  line-height: 0.96;
  letter-spacing: -0.03em;
  word-break: keep-all;
  hyphens: none;
  white-space: normal;
  width: 100%;
}
.hero__line { display: block; }
.hero__cycle {
  position: relative;
  display: inline-block;
  vertical-align: baseline;
  color: var(--c-brand);
  /* Hold the line stable. The longest cycled word is "Transform" (9
     chars). A ghost span (.hero__cycle-ghost) renders the longest word
     invisibly to lock width — a `min-width: 9ch` would only approximate
     this since the display face is proportional, not monospaced. */
  white-space: nowrap;
}
/* Hidden word nodes — kept in DOM only for the aria-live announcement
   that fires when each word finishes typing. The visible surface is
   .hero__cycle-text; the original .hero__word spans never paint. */
.hero__word {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  pointer-events: none;
  opacity: 0;
}
/* Ghost holds the longest word's intrinsic width so the surrounding
   line ("Don't toss it, ___ it.") never reflows as words type/erase.
   Padding-bottom + matching negative margin gives descenders (g in
   "Reignite") room to paint without nudging the line baseline. The
   .hero__display line-height of 0.96 otherwise crops them. Same trick
   the global [data-split] line-mask uses. */
.hero__cycle-ghost {
  display: inline-block;
  visibility: hidden;
  pointer-events: none;
  white-space: nowrap;
  padding-bottom: 0.12em;
  margin-bottom: -0.12em;
}
/* Visible typed surface, painted on top of the ghost.
   Right-aligned to the ghost so the visible word stays flush against
   the trailing " it." — when the typed word is shorter than the
   longest ("Transform"), unused ghost-width sits on the LEFT of the
   word rather than between the word and " it.". The cursor is a
   pseudo-element at the end of this surface, so it travels with the
   right edge of the visible text automatically. */
.hero__cycle-text {
  position: absolute;
  right: 0;
  top: 0;
  white-space: nowrap;
  /* Match the ghost's descender padding so the background-clip:text
     surface has room to paint the "g" in "Reignite". Absolute element,
     so this adds no layout cost. */
  padding-bottom: 0.12em;
  /* Cool blue gradient on the cycling word. Darker brand blue at the
     edges, light pale blue glow through the center. Clips to text
     shape. The cursor ::after has its own solid background and is
     unaffected. */
  background-image: linear-gradient(90deg, #176fe9 0%, #cdebff 50%, #176fe9 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  /* Compositor-only: opacity is what we touch in the reduced-motion
     fallback. Typing itself is a textContent swap on a small node. */
  will-change: opacity;
}
/* Cursor — pseudo-element on the text container so it floats at the
   end of whatever's currently typed, with no extra DOM node and no
   space character glitches. Brand-blue on this dark hero. */
.hero__cycle-text::after {
  content: "";
  display: inline-block;
  width: 0.08em;
  height: 0.92em;
  margin-left: 0.06em;
  vertical-align: -0.08em;
  background: #5fa1ff;
  /* Solid by default — JS toggles .is-blinking during the read beat. */
  opacity: 1;
  transform: translateZ(0);
}
.hero__cycle-text.is-blinking::after {
  animation: heroCursorBlink 530ms steps(1, end) infinite;
}
@keyframes heroCursorBlink {
  0%, 50%   { opacity: 1; }
  50.01%, 100% { opacity: 0; }
}
/* Reduced-motion fallback: cross-fade only. No cursor (would just sit
   blinking with nothing to type). */
.hero__cycle-text.no-cursor::after { display: none; }
.hero__cycle-text.is-fading {
  opacity: 0;
  transition: opacity 220ms linear;
}
.hero__it { color: #fff; }
.hero__teaser {
  margin: 0;
  font-family: var(--f-mono);
  font-size: clamp(13px, 1vw, 16px);
  letter-spacing: 0.03em;
  line-height: 1.55;
  color: rgba(255,255,255,0.85);
  max-width: 720px;
}
.hero__cta { align-self: flex-end; }

.hero__scroll {
  position: absolute;
  left: 50%; bottom: 28px;
  transform: translateX(-50%);
  z-index: 2;
  display: flex; align-items: center; gap: 10px;
  font-family: var(--f-mono);
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.85);
}
.hero__scroll-arrow {
  display: inline-block;
  font-size: 18px;
  animation: bob 1.6s var(--ease) infinite;
}
@keyframes bob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(6px); }
}

@media (max-width: 800px) {
  .hero__anchor { text-align: left; align-items: flex-start; }
  .hero__cta { align-self: stretch; justify-content: center; }
  /* Hide the "Scroll" cue on tablets/phones — touch users already know
     how to scroll, and on iOS the bottom address bar covers it anyway. */
  .hero__scroll { display: none; }
}
@media (max-width: 600px) {
  .hero { padding: 100px 24px 80px; }
  .hero__display { font-size: clamp(40px, 9vw, 64px); }
  .hero__teaser { font-size: 14px; }
  /* Touch target floor on the primary hero CTA. */
  .hero__cta { min-height: 52px; padding: 18px 24px; }
}
@media (max-width: 380px) {
  .hero { padding: 96px 16px 72px; }
  .hero__display { font-size: clamp(32px, 8vw, 48px); }
}

/* =========================================================
   MARQUEE
   ========================================================= */
.strip {
  background: var(--c-ink);
  color: #5fa1ff;
  font-family: var(--f-display);
  font-weight: 700;
  font-size: clamp(22px, 2.8vw, 36px);
  letter-spacing: -0.005em;
  padding: 22px 0;
  overflow: hidden;
  border-block: 1px solid var(--c-ink);
}
.strip__track {
  display: flex;
  white-space: nowrap;
  gap: 32px;
  animation: marquee 60s linear infinite;
  width: max-content;
}
@keyframes marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

/* =========================================================
   ABOUT / DISPLAY
   ========================================================= */
.display {
  max-width: var(--container);
  margin: 0 auto;
  padding: var(--s-7) var(--gutter) var(--s-6);
}
.display__headline {
  font-family: var(--f-display);
  font-weight: 700;
  font-size: clamp(52px, 10vw, 168px);
  line-height: 0.96;
  letter-spacing: -0.03em;
  margin: 0 0 var(--s-4);
  word-break: keep-all;
}
.display__line { display: block; }
.display__body { max-width: 900px; }
.display__lede {
  font-size: clamp(22px, 2vw, 30px);
  line-height: 1.4;
  margin: 0 0 var(--s-2);
}
.display__lede strong { font-weight: 600; color: var(--c-ink); }
.display__lede em { color: var(--c-brand); font-style: normal; font-weight: 600; }

.display__sub {
  font-size: clamp(18px, 1.4vw, 22px);
  line-height: 1.55;
  color: var(--c-mute);
  margin: var(--s-3) 0 0;
}
.display__sub em { color: var(--c-brand); font-style: normal; font-weight: 600; }
.display__sub:last-child { margin-bottom: 0; }

@media (max-width: 600px) {
  .display { padding-inline: 24px; }
  .display__headline { font-size: clamp(40px, 9vw, 64px); }
}
@media (max-width: 380px) {
  .display { padding-inline: 16px; }
  .display__headline { font-size: clamp(32px, 8vw, 48px); }
}

/* =========================================================
   HUGE
   ========================================================= */
.huge {
  background: var(--c-ink);
  color: #fff;
  padding: var(--s-7) var(--gutter);
  text-align: left;
  overflow: hidden;
  --c-brand: #5fa1ff;
}
.huge__h {
  margin: 0 auto;
  max-width: var(--container);
  width: 100%;
}
.huge__line {
  display: block;
  font-family: var(--f-display);
  font-weight: 700;
  font-size: clamp(52px, 10vw, 168px);
  line-height: 0.96;
  letter-spacing: -0.03em;
  word-break: keep-all;
  hyphens: none;
}
.huge__line--accent { color: var(--c-brand); }

/* Bottom row: proof on left, photo on right */
.huge__bottom {
  margin: var(--s-7) auto 0;
  max-width: var(--container);
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: var(--s-5);
  align-items: start;
}
.huge__proof {
  position: relative;
  padding: var(--s-3) 0 var(--s-3) var(--s-3);
  border-left: 2px solid var(--c-brand);
}
.huge__proof-mark {
  position: absolute;
  left: -2px; top: 0;
  width: 2px; height: 72px;
  background: var(--c-brand);
  box-shadow: 0 0 28px rgba(95,161,255,0.6);
}
.huge__proof-lede {
  font-size: clamp(24px, 2.4vw, 34px);
  line-height: 1.45;
  color: rgba(255,255,255,0.94);
  margin: 0 0 var(--s-3);
  font-weight: 400;
}
.huge__proof-lede em {
  color: var(--c-brand);
  font-style: normal;
  font-weight: 600;
}
.huge__proof-sub {
  font-size: clamp(18px, 1.55vw, 23px);
  line-height: 1.55;
  color: rgba(255,255,255,0.62);
  margin: 0;
}

/* Photo placeholder — swap background-image for a real photo */
.huge__photo {
  position: relative;
  aspect-ratio: 1 / 1;
  background:
    linear-gradient(180deg, rgba(0,0,0,0) 55%, rgba(0,0,0,0.45) 100%),
    url("outcomes.png");
  background-size: cover;
  background-position: center;
  overflow: hidden;
}

@media (max-width: 800px) {
  .huge__bottom { grid-template-columns: 1fr; }
  .huge__photo { aspect-ratio: 16 / 10; max-height: 360px; }
}

/* ---------- Chart (placeholder) ---------- */
.chart {
  margin: var(--s-7) auto 0;
  max-width: var(--container);
}
.chart__intro {
  font-family: var(--f-display);
  font-weight: 600;
  font-size: clamp(20px, 1.8vw, 26px);
  line-height: 1.4;
  color: rgba(255,255,255,0.94);
  margin: 0 0 var(--s-4);
  max-width: 760px;
}
.chart__stats {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--s-3);
}
.chart__stat {
  border: 1px solid rgba(255,255,255,0.18);
  background: rgba(255,255,255,0.025);
  padding: var(--s-3);
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  position: relative;
  min-height: 280px;
  transition: background var(--d-md) var(--ease), border-color var(--d-md) var(--ease);
}
.chart__stat:hover {
  background: rgba(95,161,255,0.08);
  border-color: var(--c-brand);
}
.chart__stat-head {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-family: var(--f-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.chart__stat-num {
  color: rgba(255,255,255,0.55);
}
.chart__stat-title {
  color: rgba(255,255,255,0.88);
}
.chart__big {
  display: inline-block;
  align-self: center;
  font-family: var(--f-display);
  font-weight: 800;
  font-size: clamp(64px, 6.4vw, 104px);
  line-height: 1;
  letter-spacing: -0.035em;
  color: var(--c-brand);
  font-variant-numeric: tabular-nums;
  min-width: 2.5ch;
  text-align: center;
  margin-block: var(--s-2);
}
.chart__label {
  font-size: 16px;
  line-height: 1.45;
  color: rgba(255,255,255,0.85);
  margin: 0;
  flex: 1;
}
.chart__caveat {
  margin: var(--s-4) 0 0;
  font-family: var(--f-mono);
  font-size: 13px;
  line-height: 1.6;
  color: rgba(255,255,255,0.55);
  max-width: 760px;
}
.chart__view-sources {
  display: inline-block;
  margin-top: var(--s-3);
  font-family: var(--f-mono);
  font-size: 12px;
  color: rgba(255,255,255,0.55);
  text-decoration: none;
  border-bottom: 1px solid currentColor;
  padding: 12px 0 4px;
  min-height: 44px;
  line-height: 1.4;
  transition: color var(--d-sm) var(--ease);
}
.chart__view-sources:hover { color: #fff; }

.chart__cta {
  margin: var(--s-7) auto 0;
  max-width: var(--container);
  padding: var(--s-5) 0 0;
  border-top: 1px solid rgba(255,255,255,0.12);
}
.chart__cta-h {
  font-family: var(--f-display);
  font-weight: 700;
  font-size: clamp(36px, 4.5vw, 72px);
  letter-spacing: -0.02em;
  color: var(--c-brand);
  line-height: 1.05;
  margin: 0 0 var(--s-3);
  max-width: 18ch;
}
.chart__cta-body {
  font-family: var(--f-display);
  font-weight: 500;
  font-size: clamp(18px, 1.6vw, 22px);
  color: rgba(255,255,255,0.88);
  line-height: 1.5;
  max-width: 56ch;
  margin: 0;
}

@media (max-width: 1100px) {
  .chart__stats { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 600px) {
  .chart__stats { grid-template-columns: 1fr; }
}

@media (max-width: 600px) {
  .huge { padding: var(--s-5) 24px; }
  .huge__line { font-size: clamp(40px, 9vw, 64px); }
}
@media (max-width: 380px) {
  .huge { padding: var(--s-5) 16px; }
  .huge__line { font-size: clamp(32px, 8vw, 48px); }
}

/* =========================================================
   STORIES
   ========================================================= */
.stories {
  max-width: var(--container);
  margin: 0 auto;
  padding: var(--s-7) var(--gutter);
}
.stories__head { margin-bottom: var(--s-5); }
.stories__h2 {
  font-family: var(--f-display);
  font-weight: 700;
  font-size: clamp(36px, 4.5vw, 72px);
  line-height: 1.05;
  letter-spacing: -0.02em;
  margin: 0;
  color: var(--c-ink);
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.stories__line { display: block; }
.stories__h2 .accent,
.display__headline .accent,
.included__h2 .accent {
  color: var(--c-brand);
  font-style: normal;
  font-weight: inherit;
}

/* ---------- Display: "Pause" — looping breath ----------
   The word breathes slowly and forever: a single slow blur+opacity
   dip and back, then a longer rest before the next breath. Rest is
   longer than the breath itself so the section never feels twitchy
   — the eye reads stillness, then a single gesture, then stillness
   again. Compositor-only (filter + opacity), no layout writes.

   Cycle: 7300ms total.
     0%      — at rest
     0-19%   — inhale/exhale (1400ms in, 1400ms out = 2800ms breath)
     19-100% — rest (4500ms before the next breath)

   Why pure CSS infinite (no JS observer/timeout): cheap, never
   forgets, and the animation pauses naturally when the tab is
   backgrounded (browsers throttle keyframes off-screen). The old
   one-shot JS rig is removed.

   inline-block keeps the filter from leaking to neighboring text and
   keeps the baseline stable so "before" doesn't shift horizontally. */
.display__headline .accent {
  display: inline-block;
  /* Stable baseline — filter on inline boxes can drift in some
     engines; inline-block locks it. */
  vertical-align: baseline;
  animation: display-pause-breath 7300ms cubic-bezier(0.4, 0, 0.4, 1) infinite both;
  will-change: filter, opacity;
}
@keyframes display-pause-breath {
  0%    { filter: blur(0px);   opacity: 1;    }
  9.5%  { filter: blur(2.4px); opacity: 0.55; }
  19%   { filter: blur(0px);   opacity: 1;    }
  100%  { filter: blur(0px);   opacity: 1;    }
}

/* ---------- Stories: looping per-letter "transformation" dissolve ----------
   Each letter of the word "transformation." breathes between full opacity
   and 0.42 on a 6.6s cycle, with phase offset by --char-phase (0..1) so
   the ripple travels left-to-right and never lands on a moment where the
   whole word dims at once. Pure opacity = compositor-only.
   The animation runs forever. Reduced-motion path further down kills it. */
.stories__h2 .stories__char {
  display: inline-block;
  animation: stories-letter-pulse 6600ms cubic-bezier(0.5, 0, 0.5, 1) infinite;
  animation-delay: calc(var(--char-phase, 0) * -6600ms);
  will-change: opacity;
}
@keyframes stories-letter-pulse {
  0%   { opacity: 1; }
  35%  { opacity: 0.42; }
  70%  { opacity: 1; }
  100% { opacity: 1; }
}

.stories__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-3);
}
.card {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--c-line);
  background: var(--c-paper);
  padding: var(--s-2);
  transition: transform var(--d-md) var(--ease), background var(--d-md) var(--ease), color var(--d-md) var(--ease);
}
.card:hover {
  transform: translateY(-4px);
  background: var(--c-ink);
  color: #fff;
}
.card:hover .card__meta { color: rgba(255,255,255,0.6); }
.card:hover .card__excerpt { color: rgba(255,255,255,0.8); }
.card:hover .card__cta { color: var(--c-brand); }
.card__meta {
  display: flex;
  justify-content: space-between;
  font-family: var(--f-mono);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--c-mute);
  margin-bottom: var(--s-2);
}
.card__art {
  aspect-ratio: 16 / 11;
  margin-bottom: var(--s-2);
  background-size: cover;
  background-position: center;
  background-color: var(--c-shade);
}
.card__art--1 { background-image: linear-gradient(135deg, #176fe9 0%, #0a3a85 100%); }
.card__art--2 { background-image: linear-gradient(135deg, #1d2b3a 0%, #176fe9 120%); }
.card__art--3 { background-image: linear-gradient(135deg, #0a0a0a 0%, #176fe9 100%); }
.card__title {
  font-family: var(--f-display);
  font-weight: 600;
  font-size: 24px;
  line-height: 1.2;
  letter-spacing: -0.01em;
  margin: 0 0 var(--s-1);
}
.card__excerpt {
  font-size: 17px;
  line-height: 1.5;
  color: var(--c-mute);
  margin: 0 0 var(--s-2);
  flex: 1;
}
.card__cta {
  font-family: var(--f-mono);
  font-size: 13px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--c-brand);
}

@media (max-width: 900px) {
  .stories__grid { grid-template-columns: 1fr; }
}
@media (max-width: 600px) {
  .stories { padding-inline: 24px; }
  .stories__h2 { font-size: clamp(30px, 8.5vw, 48px); }
}
/* The "transformation." word is a row of inline-block letter spans —
   without this, narrow viewports can break the word mid-letter. The
   parent .accent stays inline so the line still wraps as a whole token. */
.stories__h2 .accent { white-space: nowrap; }

/* =========================================================
   FLOW (program flow)
   ========================================================= */
.flow {
  background: var(--c-ink);
  color: #fff;
  padding: var(--s-7) var(--gutter) var(--s-7);
  --c-brand: #5fa1ff;
}
.flow__grid {
  max-width: var(--container);
  margin-inline: auto;
  /* Mobile/tablet: single column. Headline scrolls with the rest of the
     section. Two-column sticky layout kicks in at >=1024px (see below). */
  display: block;
}
.flow__intro { margin: 0 0 var(--s-6); }
.flow__title {
  font-family: var(--f-display);
  font-weight: 700;
  font-size: clamp(52px, 10vw, 168px);
  line-height: 0.96;
  letter-spacing: -0.03em;
  margin: 0 0 var(--s-3);
  word-break: keep-all;
}
.flow__line { display: block; }
.flow__line--accent { color: var(--c-brand); }
.flow__sub {
  font-size: clamp(18px, 1.5vw, 22px);
  line-height: 1.5;
  color: rgba(255,255,255,0.7);
  max-width: 720px;
  margin: 0;
}

.flow__stations {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--s-5);
}
.station {
  display: grid;
  grid-template-columns: 220px 1fr;
  gap: var(--s-4);
  align-items: start;
  padding: var(--s-4) 0;
  border-top: 1px solid rgba(255,255,255,0.15);
}
.station__num {
  font-family: var(--f-display);
  font-weight: 700;
  font-size: clamp(56px, 6vw, 104px);
  line-height: 1;
  color: var(--c-brand);
  letter-spacing: -0.03em;
}

/* ---------- Two-column sticky layout (>=1024px) ---------- */
/* BKKDW pattern: headline pins to top-left while stations scroll up the
   right column. position: sticky on the headline column means it parks
   itself at the top of the viewport for the duration of .flow's scroll
   length, then releases naturally at the section boundary. The stations
   column has no special positioning — natural document flow. */
@media (min-width: 1024px) {
  .flow__grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
    gap: var(--s-6);
    align-items: start;
  }
  .flow__intro {
    position: sticky;
    /* 12vh clears the nav with breathing room. Tuned so the H2 lands in
       the upper third of the viewport while stations cycle past. */
    top: 12vh;
    margin: 0;
    /* Cap height so the sticky column never asks for more than the
       viewport (would defeat sticky on short windows). */
    max-height: calc(100vh - 12vh);
  }
  .flow__title {
    /* Slightly tighter at the sticky size — the column is now ~50% of
       container width, so the giant clamp upper bound was overshooting. */
    font-size: clamp(52px, 7.5vw, 128px);
  }
}
.station__title {
  font-family: var(--f-display);
  font-weight: 700;
  font-size: clamp(28px, 3vw, 44px);
  line-height: 1.1;
  letter-spacing: -0.015em;
  margin: 0 0 var(--s-2);
}
.station__lede {
  font-size: clamp(18px, 1.4vw, 22px);
  line-height: 1.5;
  margin: 0 0 var(--s-2);
  max-width: 760px;
}
.station__lede em { color: var(--c-brand); font-style: normal; font-weight: 600; }
.station__detail {
  font-family: var(--f-mono);
  font-size: 14px;
  line-height: 1.6;
  color: rgba(255,255,255,0.65);
  margin: 0;
}
.station__detail strong { color: #fff; font-weight: 600; }

/* ---------- Reveal: stations fade + lift as they enter ---------- */
/* Override the global [data-reveal] travel (24px) with the proposal-spec
   32px so the lift reads more clearly against the giant numerals.
   Compositor-only: opacity + translate3d. */
.station[data-reveal] {
  opacity: 0;
  transform: translate3d(0, 32px, 0);
  transition: opacity 700ms var(--ease), transform 700ms var(--ease);
  will-change: opacity, transform;
}
.station[data-reveal].is-visible {
  opacity: 1;
  transform: translate3d(0, 0, 0);
}

@media (max-width: 800px) {
  .station { grid-template-columns: 1fr; gap: var(--s-2); }
  .station__num { font-size: 40px; }
}
@media (max-width: 600px) {
  .flow { padding-inline: 24px; }
  .flow__title { font-size: clamp(40px, 9vw, 64px); }
}

/* =========================================================
   INCLUDED (incentives)
   ========================================================= */
.included {
  max-width: var(--container);
  margin: 0 auto;
  padding: var(--s-7) var(--gutter);
}
.included__head { margin-bottom: var(--s-5); max-width: 900px; }
.included__h2 {
  font-family: var(--f-display);
  font-weight: 700;
  font-size: clamp(36px, 4.5vw, 72px);
  line-height: 1.05;
  letter-spacing: -0.02em;
  margin: 0 0 var(--s-2);
}
.included__sub {
  font-size: clamp(18px, 1.4vw, 22px);
  line-height: 1.5;
  color: var(--c-mute);
  margin: 0;
}
.included__grid {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-3);
}
.incentive {
  border: 1px solid var(--c-line);
  background: var(--c-paper);
  padding: var(--s-3);
  transition: background var(--d-md) var(--ease), color var(--d-md) var(--ease), transform var(--d-md) var(--ease);
}
.incentive:hover {
  background: var(--c-brand-soft);
  transform: translateY(-3px);
}
.incentive__icon {
  display: inline-block;
  width: 40px; height: 40px;
  line-height: 40px;
  text-align: center;
  background: var(--c-brand);
  color: #fff;
  font-weight: 800;
  margin-bottom: var(--s-2);
  font-size: 20px;
}
.incentive h3 {
  font-family: var(--f-display);
  font-weight: 600;
  font-size: 24px;
  line-height: 1.2;
  letter-spacing: -0.01em;
  margin: 0 0 6px;
}
.incentive p {
  margin: 0;
  font-size: 17px;
  color: var(--c-mute);
}

@media (max-width: 900px) {
  .included__grid { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 600px) {
  .included { padding-inline: 24px; }
  .included__grid { grid-template-columns: 1fr; }
}

/* =========================================================
   PROGRAMS / CURRICULUM
   ========================================================= */
.programs {
  background: var(--c-shade);
  padding: var(--s-7) var(--gutter);
}
.programs__head, .programs__list, .programs__note {
  max-width: var(--container);
  margin-inline: auto;
}
.programs__head { margin-bottom: var(--s-5); max-width: 960px; }
.programs__head h2 {
  font-family: var(--f-display);
  font-weight: 700;
  font-size: clamp(36px, 4.5vw, 72px);
  line-height: 1.05;
  letter-spacing: -0.02em;
  margin: 0 0 var(--s-2);
}
.programs__intro {
  font-size: clamp(18px, 1.5vw, 22px);
  line-height: 1.5;
  color: var(--c-mute);
  margin: 0;
}
.programs__list {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-3);
}
.program {
  background: var(--c-paper);
  padding: var(--s-3);
  border: 1px solid var(--c-line);
}
.program__tag {
  display: inline-block;
  background: var(--c-brand);
  color: #fff;
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 8px 12px;
  margin-bottom: var(--s-2);
}
.program h3 {
  font-family: var(--f-display);
  font-weight: 600;
  font-size: 24px;
  line-height: 1.2;
  letter-spacing: -0.01em;
  margin: 0 0 var(--s-1);
}
.program p { margin: 0; color: var(--c-mute); font-size: 17px; line-height: 1.55; }
.program p em { color: var(--c-brand); font-style: normal; font-weight: 600; }

.programs__note {
  margin-top: var(--s-5);
  font-size: 18px;
  line-height: 1.55;
  color: var(--c-mute);
  max-width: 1000px;
}
.programs__note strong { color: var(--c-ink); font-weight: 700; }

@media (max-width: 900px) {
  .programs__list { grid-template-columns: 1fr; }
}
@media (max-width: 600px) {
  .programs { padding-inline: 24px; }
}

/* =========================================================
   ENROLL
   ========================================================= */
.enroll {
  max-width: var(--container);
  margin: 0 auto;
  padding: var(--s-7) var(--gutter);
}
.enroll__head { margin-bottom: var(--s-5); max-width: 960px; }
.enroll__line {
  font-family: var(--f-display);
  font-weight: 700;
  font-size: clamp(44px, 7.5vw, 120px);
  line-height: 0.98;
  letter-spacing: -0.025em;
  margin: 0;
  word-break: keep-all;
  hyphens: none;
}
.enroll__line--accent { color: var(--c-brand); }
.enroll__sub {
  font-size: clamp(18px, 1.5vw, 22px);
  line-height: 1.5;
  color: var(--c-mute);
  margin: var(--s-3) 0 0;
  max-width: 720px;
}

.enroll__grid {
  display: grid;
  grid-template-columns: 1fr 1.5fr;
  gap: var(--s-5);
  align-items: start;
}

@media (max-width: 900px) {
  .enroll__grid { grid-template-columns: 1fr; }
}
@media (max-width: 600px) {
  .enroll { padding-inline: 24px; }
  .enroll__line { font-size: clamp(36px, 8vw, 56px); }
}

/* Eligibility callout */
.qualify {
  position: sticky;
  top: 100px;
  background: var(--c-ink);
  color: #fff;
  padding: var(--s-3);
  border: 1px solid var(--c-ink);
  --c-brand: #5fa1ff;
}
.qualify .kicker { color: var(--c-brand); margin-bottom: var(--s-1); }
.qualify .dot { background: var(--c-brand); }
.qualify__title {
  font-family: var(--f-display);
  font-weight: 600;
  font-size: 24px;
  line-height: 1.2;
  letter-spacing: -0.01em;
  margin: 0 0 var(--s-2);
}
.qualify__list {
  list-style: none;
  padding: 0;
  margin: 0 0 var(--s-3);
}
.qualify__list li {
  position: relative;
  padding: 10px 0 10px 28px;
  font-size: 17px;
  line-height: 1.5;
  border-top: 1px solid rgba(255,255,255,0.15);
}
.qualify__list li:first-child { border-top: 0; }
.qualify__list li span {
  position: absolute;
  left: 0; top: 12px;
  color: var(--c-brand);
  font-weight: 700;
}
.qualify__list em { color: var(--c-brand); font-style: normal; font-weight: 600; }
.qualify__note {
  margin: 0;
  font-family: var(--f-mono);
  font-size: 13px;
  letter-spacing: 0.04em;
  color: rgba(255,255,255,0.65);
}
@media (max-width: 900px) {
  .qualify { position: static; }
}

/* Form */
.enroll-form {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
}
.enroll-form__group {
  border: 1px solid var(--c-line);
  padding: var(--s-3);
  margin: 0;
}
.enroll-form__group legend {
  font-family: var(--f-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--c-brand);
  padding: 0 8px;
  margin-left: -8px;
}
.enroll-form label {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-family: var(--f-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--c-mute);
  margin-bottom: var(--s-2);
}
.enroll-form__group label:last-child { margin-bottom: 0; }
.enroll-form__row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-2);
}
.enroll-form input[type="text"],
.enroll-form input[type="email"],
.enroll-form input[type="tel"],
.enroll-form select,
.enroll-form textarea {
  font-family: var(--f-body);
  font-size: 18px;
  letter-spacing: normal;
  text-transform: none;
  padding: 12px 14px;
  border: 1px solid var(--c-line);
  background: #fff;
  color: var(--c-ink);
  border-radius: 0;
}
.enroll-form input:focus,
.enroll-form select:focus,
.enroll-form textarea:focus {
  outline: 2px solid var(--c-brand);
  outline-offset: 0;
  border-color: var(--c-brand);
}
.enroll-form__label {
  font-family: var(--f-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--c-mute);
  margin: 0 0 var(--s-1);
}
.enroll-form__checks {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 20px;
}
.enroll-form__checks label {
  flex-direction: row;
  align-items: center;
  gap: 10px;
  font-family: var(--f-body);
  font-size: 16px;
  letter-spacing: normal;
  text-transform: none;
  color: var(--c-ink);
  margin: 0;
  /* Tap target: each option fills a 44px row of its own on phone. */
  min-height: 44px;
  padding: 6px 0;
}
.enroll-form__checks input[type="checkbox"],
.enroll-form__consent input[type="checkbox"] {
  width: 20px;
  height: 20px;
  flex: 0 0 20px;
}
.enroll-form__message {
  font-family: var(--f-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--c-mute);
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.enroll-form__consent {
  display: flex !important;
  flex-direction: row !important;
  align-items: flex-start !important;
  gap: 12px;
  font-family: var(--f-body) !important;
  font-size: 16px !important;
  letter-spacing: normal !important;
  text-transform: none !important;
  color: var(--c-ink);
}
.enroll-form__consent input { margin-top: 4px; }
.enroll-form__submit { align-self: flex-start; }
.enroll-form__privacy {
  font-family: var(--f-mono);
  font-size: 13px;
  line-height: 1.55;
  color: var(--c-mute);
  margin: 0;
}

.enroll-form__success {
  border: 1px solid var(--c-brand);
  padding: var(--s-4);
  background: var(--c-brand-soft);
}
.enroll-form__success h3 {
  font-family: var(--f-display);
  font-weight: 700;
  font-size: 32px;
  line-height: 1.1;
  letter-spacing: -0.015em;
  margin: 0 0 var(--s-2);
}
.enroll-form__success p { margin: 0 0 var(--s-2); font-size: 18px; }
.enroll-form__success p:last-child { margin-bottom: 0; }

@media (max-width: 600px) {
  .enroll-form__row { grid-template-columns: 1fr; }
  /* Tighter group padding so inputs aren't squeezed. */
  .enroll-form__group { padding: var(--s-2); }
  /* Full-width submit + roomy tap area for one-handed use. */
  .enroll-form__submit {
    align-self: stretch;
    justify-content: center;
    min-height: 56px;
  }
}

/* =========================================================
   FOOTER
   ========================================================= */
.footer {
  background: var(--c-ink);
  color: #fff;
  padding: var(--s-5) var(--gutter) var(--s-3);
  --c-brand: #5fa1ff;
}
.footer__top {
  display: flex;
  justify-content: space-between;
  align-items: end;
  flex-wrap: wrap;
  gap: var(--s-3);
  border-bottom: 1px solid rgba(255,255,255,0.15);
  padding-bottom: var(--s-4);
  margin-bottom: var(--s-4);
}
.footer__brand {
  font-family: var(--f-display);
  font-weight: 600;
  font-size: clamp(24px, 3vw, 36px);
  line-height: 1.2;
  letter-spacing: -0.01em;
  margin: 0;
  max-width: 520px;
}
.footer__tag {
  margin: 0;
  font-family: var(--f-display);
  font-weight: 700;
  font-size: clamp(28px, 4.5vw, 64px);
  line-height: 1.05;
  letter-spacing: -0.02em;
  text-transform: none;
  color: var(--c-brand);
  text-align: right;
}
@media (max-width: 700px) {
  .footer__tag { text-align: left; }
}
.footer__cols {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-4);
  margin-bottom: var(--s-4);
}
.footer__cols a {
  display: block;
  padding: 5px 0;
  color: rgba(255,255,255,0.78);
  font-size: 17px;
  transition: color var(--d-sm) var(--ease);
}
.footer__cols a:hover { color: var(--c-brand); }
.footer__h {
  font-family: var(--f-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.5);
  margin: 0 0 var(--s-2);
}
.footer__sources {
  border-top: 1px solid rgba(255,255,255,0.15);
  padding-top: var(--s-3);
  margin-bottom: var(--s-3);
  max-width: 720px;
}
.footer__sources-text {
  font-size: 14px;
  line-height: 1.55;
  color: rgba(255,255,255,0.7);
  margin: 0 0 var(--s-1);
}
.footer__sources-link {
  display: inline-block;
  font-family: var(--f-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--c-brand);
  border-bottom: 1px solid var(--c-brand);
  padding-bottom: 2px;
}
.footer__sources-link:hover { opacity: 0.75; }

.footer__address, .footer__service {
  margin: 6px 0;
  font-size: 14px;
  line-height: 1.55;
  color: rgba(255,255,255,0.6);
}
.footer__service strong { color: #fff; font-weight: 600; }
.footer__legal {
  margin: var(--s-2) 0 0;
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  color: rgba(255,255,255,0.4);
}

@media (max-width: 700px) {
  .footer__cols { grid-template-columns: 1fr 1fr; gap: var(--s-3); }
  /* Bigger tap targets in the footer link list on touch devices. */
  .footer__cols a { padding: 10px 0; min-height: 44px; display: flex; align-items: center; }
}
@media (max-width: 600px) {
  .footer { padding-inline: 24px; }
}
@media (max-width: 480px) {
  .footer__cols { grid-template-columns: 1fr; gap: var(--s-2); }
}

/* =========================================================
   REVEALS
   ========================================================= */
/* ---------- Back to top button ---------- */
.back-top {
  position: fixed;
  right: 24px;
  bottom: 24px;
  z-index: 40;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 16px;
  background: var(--c-ink);
  color: #fff;
  border: 1px solid rgba(255,255,255,0.2);
  font-family: var(--f-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
  opacity: 0;
  transform: translateY(20px);
  transition: opacity var(--d-md) var(--ease),
              transform var(--d-md) var(--ease),
              background var(--d-sm) var(--ease),
              border-color var(--d-sm) var(--ease);
  pointer-events: none;
}
.back-top.is-visible {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}
.back-top:hover {
  background: #176fe9;
  border-color: #176fe9;
}
.back-top__label { font-size: 11px; }
@media (max-width: 600px) {
  /* Touch target ≥44×44; respect iOS safe-area at the bottom edge. */
  .back-top {
    right: 16px;
    bottom: max(16px, env(safe-area-inset-bottom));
    padding: 0;
    width: 48px;
    height: 48px;
    justify-content: center;
    font-size: 16px;
  }
  .back-top__label { display: none; }
}

[data-reveal] {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 700ms var(--ease), transform 700ms var(--ease);
}
[data-reveal].is-visible {
  opacity: 1;
  transform: none;
}
/* ---------- Line mask reveal ---------- */
/* Each [data-split] becomes a clipped wrapper; its inner text (wrapped
   by JS into .reveal-inner) translates from translateY(100%) to 0 on
   intersection. One curve, one duration, one beat per line.

   Clipper notes:
     • The line classes (.huge__line, .flow__line, .display__line,
       .enroll__line) are already display:block — overflow:hidden lands
       cleanly on them. .station__title is the h3 itself; same story.
     • A small padding-bottom keeps descenders (g, p, y, comma tails)
       from being clipped by the tight display line-heights. Matched
       negative margin keeps layout neutral.
     • Stagger is driven by --line-index (set by JS only for siblings
       with multiple [data-split] children). Lone lines stay at 0. */
[data-split] {
  display: block;
  overflow: hidden;
  padding-bottom: 0.12em;
  margin-bottom: -0.12em;
}
[data-split] .reveal-inner {
  display: block;
  transform: translateY(100%);
  transition: transform 600ms cubic-bezier(0.22, 1, 0.36, 1);
  transition-delay: calc(var(--line-index, 0) * 90ms);
  will-change: transform;
}
[data-split].is-visible .reveal-inner {
  transform: translateY(0);
}

/* ---------- Scroll progress indicator ---------- */
/* Thin brand-blue line at top of viewport — JS writes scaleX(0..1).
   Sits above nav (z-index 60) so it's always visible. Pure transform =
   GPU-cheap; no layout writes. Reduced-motion safe (still updates but
   without animation); we also clip it inside that media query. */
.scroll-progress {
  position: fixed;
  top: 0; left: 0;
  width: 100%;
  height: 3px;
  background: var(--c-brand);
  transform-origin: 0 50%;
  transform: scaleX(0);
  z-index: 60;
  pointer-events: none;
  will-change: transform;
  box-shadow: 0 0 12px rgba(23,111,233,0.45);
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
  [data-reveal] { opacity: 1; transform: none; }
  /* Line-mask reveal collapses to a 200ms opacity fade. No translate —
     the inner span sits in place and the clip is invisible because the
     content never moves. */
  [data-split] {
    overflow: visible;
    padding-bottom: 0;
    margin-bottom: 0;
  }
  [data-split] .reveal-inner {
    transform: none !important;
    opacity: 0;
    transition: opacity 200ms linear !important;
    transition-delay: 0ms !important;
  }
  [data-split].is-visible .reveal-inner {
    opacity: 1;
  }
  /* Stations: render at their final state instantly. Sticky positioning
     on .flow__intro stays — sticky is layout, not animated transition,
     and is fine in reduced-motion contexts. We override our own
     .station[data-reveal] rule (more specific than the global reset). */
  .station[data-reveal],
  .station[data-reveal].is-visible {
    opacity: 1;
    transform: none;
  }
  .hero__video { transform: none !important; }
  .scroll-progress { display: none; }
  /* Pause beat — render static. The animation now runs on .accent
     itself (not gated by an .is-pausing class), so the guard targets
     the same selector. No filter/opacity flicker. */
  .display__headline .accent {
    animation: none !important;
    filter: none !important;
    opacity: 1 !important;
  }
  /* Stories: kill the looping letter-pulse; render statically. */
  .stories__h2 .stories__char {
    animation: none !important;
    opacity: 1 !important;
  }
  /* Hero typewriter: cursor stays hidden, fade is short and linear. */
  .hero__cycle-text::after { display: none !important; }
  .hero__cycle-text.is-fading {
    transition: opacity 200ms linear !important;
  }
}

/* =========================================================
   SOURCES PAGE
   ========================================================= */
.sources-body { background: var(--c-paper); }
.sources-body .nav--simple {
  background: rgba(255,255,255,0.94);
  backdrop-filter: blur(12px);
  border-bottom-color: var(--c-line);
  color: var(--c-ink);
}
.sources-page {
  max-width: 920px;
  margin: 0 auto;
  padding: 140px var(--gutter) var(--s-7);
}
.sources-page__head { margin-bottom: var(--s-6); }
.sources-page__h1 {
  font-family: var(--f-display);
  font-weight: 700;
  font-size: clamp(48px, 7vw, 96px);
  line-height: 1;
  letter-spacing: -0.025em;
  margin: 0 0 var(--s-3);
}
.sources-page__lede {
  font-size: clamp(18px, 1.5vw, 22px);
  line-height: 1.5;
  margin: 0 0 var(--s-3);
}
.sources-page__caveat {
  font-family: var(--f-mono);
  font-size: 13px;
  line-height: 1.65;
  color: var(--c-mute);
  background: var(--c-shade);
  padding: var(--s-3);
  border-left: 2px solid var(--c-brand);
  margin: 0;
}
.sources-list {
  list-style: none;
  padding: 0;
  margin: 0 0 var(--s-7);
}
.source {
  border-top: 1px solid var(--c-line);
  padding: var(--s-4) 0;
  display: grid;
  grid-template-columns: 80px 1fr;
  gap: var(--s-3);
}
.source:last-child { border-bottom: 1px solid var(--c-line); }
.source__num {
  font-family: var(--f-display);
  font-weight: 800;
  font-size: 36px;
  line-height: 1;
  color: var(--c-brand);
  letter-spacing: -0.02em;
  margin: 0;
}
.source__title {
  font-family: var(--f-display);
  font-weight: 700;
  font-size: 24px;
  line-height: 1.2;
  letter-spacing: -0.01em;
  margin: 0 0 var(--s-2);
}
.source__claim {
  font-size: 18px;
  line-height: 1.5;
  margin: 0 0 var(--s-2);
}
.source__cite {
  font-size: 16px;
  line-height: 1.5;
  color: var(--c-mute);
  margin: 0 0 var(--s-1);
}
.source__cite strong { color: var(--c-ink); font-weight: 600; }
.source__link {
  font-family: var(--f-mono);
  font-size: 13px;
  letter-spacing: 0.02em;
  margin: 0;
  word-break: break-all;
}
.source__link a { color: var(--c-brand); border-bottom: 1px solid var(--c-brand); padding-bottom: 1px; }
.source__link a:hover { opacity: 0.75; }

.sources-additional {
  margin-bottom: var(--s-7);
}
.sources-additional__h2 {
  font-family: var(--f-display);
  font-weight: 700;
  font-size: 28px;
  line-height: 1.2;
  letter-spacing: -0.01em;
  margin: 0 0 var(--s-3);
}
.sources-additional__list {
  list-style: none;
  padding: 0;
  margin: 0;
}
.sources-additional__list li {
  padding: var(--s-2) 0;
  border-top: 1px solid var(--c-line);
  font-size: 16px;
  line-height: 1.55;
  color: var(--c-mute);
}
.sources-additional__list li:last-child { border-bottom: 1px solid var(--c-line); }

.sources-page__back { margin-top: var(--s-5); }

@media (max-width: 700px) {
  .sources-page { padding: 110px 24px var(--s-6); }
  .source { grid-template-columns: 1fr; gap: var(--s-1); }
  .source__num { font-size: 28px; }
}

/* ============ CHART V2 (new design for review) ============ */
.chart-v2 {
  margin: 0 auto;
  max-width: 1100px;
  list-style: none;
  padding: 0;
}
.chart-v2__intro {
  font-family: var(--f-display);
  font-weight: 600;
  font-size: clamp(20px, 1.8vw, 26px);
  line-height: 1.4;
  color: rgba(255,255,255,0.94);
  margin: 0 0 var(--s-5);
  max-width: 60ch;
}
.chart-v2__rows {
  list-style: none;
  margin: 0;
  padding: 0;
}
.chart-v2-row {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.4fr) minmax(0, 1fr);
  gap: var(--s-4);
  align-items: start;
  padding: var(--s-5) 0;
  border-top: 1px solid rgba(255,255,255,0.12);
}
.chart-v2-row:last-child {
  border-bottom: 1px solid rgba(255,255,255,0.12);
}
.chart-v2-row__head {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-family: var(--f-mono);
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.chart-v2-row__num {
  color: rgba(255,255,255,0.55);
}
.chart-v2-row__title {
  color: rgba(255,255,255,0.88);
}
.chart-v2-row__big {
  font-family: var(--f-display);
  font-weight: 800;
  font-size: clamp(64px, 7vw, 112px);
  line-height: 0.95;
  letter-spacing: -0.03em;
  color: var(--c-brand);
  margin: 0 0 var(--s-2);
}
.chart-v2-row__label {
  font-size: 17px;
  line-height: 1.45;
  color: rgba(255,255,255,0.82);
  margin: 0;
  max-width: 44ch;
}
.chart-v2-row__viz {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}
.bar {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.bar__cap {
  font-family: var(--f-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  color: rgba(255,255,255,0.7);
}
.bar__track {
  display: block;
  height: 6px;
  background: rgba(255,255,255,0.10);
}
.bar__fill {
  display: block;
  height: 100%;
  width: calc(var(--pct) * 1%);
}
.bar__fill--good { background: var(--c-brand); }
.bar__fill--bad { background: rgba(255,255,255,0.35); }

.chart-v2__cta {
  margin-top: var(--s-6);
  max-width: 50ch;
}
.chart-v2__cta-h {
  font-family: var(--f-display);
  font-weight: 800;
  font-size: clamp(28px, 3.5vw, 44px);
  color: #fff;
  line-height: 1.05;
  margin: 0 0 var(--s-2);
}
.chart-v2__cta-body {
  font-family: var(--f-display);
  font-weight: 500;
  font-size: 18px;
  color: rgba(255,255,255,0.88);
  line-height: 1.5;
  max-width: 50ch;
  margin: 0;
}
.chart-v2__caveat {
  margin: var(--s-4) 0 0;
  font-family: var(--f-mono);
  font-size: 13px;
  line-height: 1.6;
  color: rgba(255,255,255,0.55);
  max-width: 760px;
}
.chart-v2__sources {
  display: inline-block;
  margin-top: var(--s-3);
  font-family: var(--f-mono);
  font-size: 12px;
  color: rgba(255,255,255,0.55);
  text-decoration: none;
  border-bottom: 1px solid currentColor;
  padding-bottom: 2px;
  transition: color var(--d-sm) var(--ease);
}
.chart-v2__sources:hover { color: #fff; }

@media (max-width: 900px) {
  .chart-v2-row {
    grid-template-columns: 1fr;
    gap: var(--s-3);
  }
}

/* =========================================================
   CHART V2 — LIGHT VARIANT (sources page)
   ---------------------------------------------------------
   The original .chart-v2 above is keyed for a dark background.
   The sources page sits on paper, so we re-tone every text
   color and rule to ink. Layout stays identical: head | body |
   viz, with a citation block under the row spanning full width.

   Citation block layout choice: full-width below the 3-column
   grid. Reasons:
     • Source titles and citations run long (especially Stat 04
       which carries a 100-word citation). Reading width matters.
     • Visual hierarchy reads as data first, source second —
       which is what Kate asked for in the motion brief.
     • Indenting under the body column would sit awkwardly
       beside the viz on stat 04, and crowd the bars.

   Implemented with grid-template-areas so the citation can
   span all three columns cleanly without nested divs.
   ========================================================= */
.chart-v2--light {
  list-style: none;
  margin: 0 0 var(--s-7);
  padding: 0;
}
.chart-v2--light .chart-v2-row {
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.4fr) minmax(0, 1fr);
  grid-template-areas:
    "head body viz"
    "cite cite cite";
  border-top-color: var(--c-line);
  padding: var(--s-5) 0;
  gap: var(--s-4) var(--s-4);
}
.chart-v2--light .chart-v2-row:last-child {
  border-bottom-color: var(--c-line);
}
.chart-v2--light .chart-v2-row__head { grid-area: head; }
.chart-v2--light .chart-v2-row__body { grid-area: body; }
.chart-v2--light .chart-v2-row__viz  { grid-area: viz; }
.chart-v2--light .chart-v2-row__cite { grid-area: cite; }

.chart-v2--light .chart-v2-row__num   { color: var(--c-mute); }
.chart-v2--light .chart-v2-row__title { color: var(--c-ink); }
.chart-v2--light .chart-v2-row__big   { color: var(--c-brand); }
.chart-v2--light .chart-v2-row__label { color: var(--c-ink); }

.chart-v2--light .bar__cap   { color: var(--c-mute); }
.chart-v2--light .bar__track { background: var(--c-line); }
.chart-v2--light .bar__fill--good { background: var(--c-brand); }
/* Comparison bar uses ink at AA-safe contrast (#1f2937-ish via 70% ink)
   instead of the dark-variant's translucent white. */
.chart-v2--light .bar__fill--bad  { background: #1f2937; }

/* Citation block — quiet block under the data row. */
.chart-v2-row__cite {
  padding: var(--s-3) 0 0;
  border-top: 1px dashed var(--c-line);
  margin-top: var(--s-2);
  max-width: 78ch;
}
.cite__title {
  font-family: var(--f-display);
  font-weight: 700;
  font-size: 18px;
  line-height: 1.25;
  letter-spacing: -0.01em;
  margin: 0 0 var(--s-1);
  color: var(--c-ink);
}
.cite__claim {
  font-size: 16px;
  line-height: 1.55;
  color: var(--c-ink);
  margin: 0 0 var(--s-2);
}
.cite__source {
  font-size: 14px;
  line-height: 1.5;
  color: var(--c-mute);
  margin: 0 0 6px;
}
.cite__source strong { color: var(--c-ink); font-weight: 600; }
.cite__link {
  font-family: var(--f-mono);
  font-size: 12px;
  letter-spacing: 0.02em;
  margin: 0;
  word-break: break-all;
}
.cite__link a {
  color: var(--c-brand);
  border-bottom: 1px solid var(--c-brand);
  padding-bottom: 1px;
  transition: opacity var(--d-sm) var(--ease);
}
.cite__link a:hover { opacity: 0.7; }

@media (max-width: 900px) {
  .chart-v2--light .chart-v2-row {
    grid-template-columns: 1fr;
    grid-template-areas:
      "head"
      "body"
      "viz"
      "cite";
    gap: var(--s-3);
  }
}

/* =========================================================
   CHART V2 — REVEAL + BAR-FILL CHOREOGRAPHY (sources page)
   ---------------------------------------------------------
   Motion contract:
     • Whole row rises 16px + fades on intersection.
     • Rows stagger by 120ms via --row-index from JS.
     • Bars fill with scaleX from the left (compositor-only;
       width is set statically via --pct, transform animates).
       Within a row: good fills first, bad fills 150ms later.
     • Big number gets a count-up via JS (parseFromText).
     • Citation slides in 12px + fades, after the bars finish.

   Why scaleX, not width: width animation triggers layout on
   every frame. scaleX is GPU-composited. We pre-set the final
   width via the inline --pct style, then transform-scale from
   0 to 1 along the X axis, transform-origin: 0 50%.

   Reduced-motion: every state collapses to final, no transitions.
   ========================================================= */
.sources-chart .chart-v2-row {
  opacity: 0;
  transform: translateY(16px);
  transition:
    opacity 700ms var(--ease),
    transform 800ms var(--ease);
  transition-delay: calc(var(--row-index, 0) * 120ms);
}
.sources-chart .chart-v2-row.is-visible {
  opacity: 1;
  transform: none;
}

/* Bar fills — set final width via --pct, animate scaleX from 0 to 1.
   The track keeps its fixed height/background; only the fill scales. */
.sources-chart .bar__fill {
  transform-origin: 0 50%;
  transform: scaleX(0);
  transition: transform 900ms cubic-bezier(0.22, 1, 0.36, 1);
  /* Will-change scoped to the active state to avoid permanent layer
     promotion on idle pages. */
}
.sources-chart .chart-v2-row.is-visible .bar__fill { transform: scaleX(1); }
/* Good bar fires first, bad bar trails by 150ms — comparison reads
   as a sequence (baseline established, then the gap shows up). The
   row-stagger delay carries through so bars in row 4 wait their turn. */
.sources-chart .chart-v2-row .bar[data-bar="good"] .bar__fill {
  transition-delay: calc(var(--row-index, 0) * 120ms + 200ms);
}
.sources-chart .chart-v2-row .bar[data-bar="bad"] .bar__fill {
  transition-delay: calc(var(--row-index, 0) * 120ms + 350ms);
}

/* Big-number reveal pairing — slight lift while the count-up runs. */
.sources-chart .chart-v2-row__big {
  opacity: 0;
  transform: translateY(8px);
  transition:
    opacity 600ms var(--ease),
    transform 700ms var(--ease);
  transition-delay: calc(var(--row-index, 0) * 120ms + 100ms);
}
.sources-chart .chart-v2-row.is-visible .chart-v2-row__big {
  opacity: 1;
  transform: none;
}
.sources-chart .chart-v2-row__label {
  opacity: 0;
  transform: translateY(8px);
  transition:
    opacity 600ms var(--ease),
    transform 700ms var(--ease);
  transition-delay: calc(var(--row-index, 0) * 120ms + 250ms);
}
.sources-chart .chart-v2-row.is-visible .chart-v2-row__label {
  opacity: 1;
  transform: none;
}

/* Citation block — delayed entry so the data lands first.
   Total cushion = row stagger + 1100ms (bars finish) + 50ms breathing room. */
.sources-chart .chart-v2-row__cite {
  opacity: 0;
  transform: translateY(12px);
  transition:
    opacity 700ms var(--ease),
    transform 800ms var(--ease);
  transition-delay: calc(var(--row-index, 0) * 120ms + 1150ms);
}
.sources-chart .chart-v2-row.is-visible .chart-v2-row__cite {
  opacity: 1;
  transform: none;
}

/* Fifth treatment — a thin brand hairline that scales in along the
   row's top border on reveal. Same scaleX-from-left pattern as the
   index page chart__cta hairline; quiet, structural, doesn't compete
   with the data. The static border-top stays as the resting rule
   (paper-grey); the hairline overlays in brand blue. */
.sources-chart .chart-v2-row {
  position: relative;
}
.sources-chart .chart-v2-row::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--c-brand);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform 900ms var(--ease);
  transition-delay: calc(var(--row-index, 0) * 120ms);
  pointer-events: none;
}
.sources-chart .chart-v2-row.is-visible::before { transform: scaleX(1); }

@media (prefers-reduced-motion: reduce) {
  .sources-chart .chart-v2-row,
  .sources-chart .chart-v2-row.is-visible,
  .sources-chart .chart-v2-row__big,
  .sources-chart .chart-v2-row__label,
  .sources-chart .chart-v2-row__cite {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .sources-chart .bar__fill {
    transform: scaleX(1) !important;
    transition: none !important;
  }
  .sources-chart .chart-v2-row::before {
    transform: scaleX(1) !important;
    transition: none !important;
  }
}

/* =========================================================
   FAMILY SECTION MOTION (#family)
   ---------------------------------------------------------
   Layered reveal choreography for the emotional centerpiece.
   Beats:
     1. Stat cards stagger in one after another (index-driven delay),
        smaller translate than the global data-reveal so they feel
        deliberate, not floaty.
     2. Big numbers (.chart__big) count up via JS — see script.js.
        We zero them out here so SSR'd text doesn't flash.
     3. Proof mark glow — one slow pulse on intersection. No loop.
     4. CTA reveal is distinct from the cards: a hairline rule scales
        in first (scaleX 0 -> 1), then the headline drops, then body.
   All effects are reduced-motion safe (block at the bottom of file
   already neutralizes transitions; we add explicit fallbacks).
   ========================================================= */

/* 1. Stat-card stagger — overrides the default data-reveal travel */
.chart__stat[data-reveal] {
  transform: translateY(10px);
  transition:
    opacity 600ms var(--ease),
    transform 700ms var(--ease);
  transition-delay: calc(var(--reveal-delay, 0) * 1ms);
}
.chart__stat[data-reveal].is-visible {
  transform: none;
}

/* 2. Big numbers — keep the slot reserved while JS counts up.
      We don't blank the text (a11y / no-JS read still works); we just
      mark the ones the counter is going to take over so it can
      cleanly own the value. */
.chart__big[data-counted] {
  /* tabular-nums is already on; nothing else needed visually */
}

/* 3. Proof-mark pulse — the brand-blue hairline beside the lede gets
      one slow brightening on reveal. We trigger by adding .is-pulsing
      from JS when the .huge__proof block enters view. */
.huge__proof-mark {
  /* base box-shadow is already defined upstream */
  transition: box-shadow 1200ms var(--ease);
}
.huge__proof-mark.is-pulsing {
  animation: proof-mark-pulse 1800ms var(--ease) 1 both;
}
@keyframes proof-mark-pulse {
  0%   { box-shadow: 0 0 28px rgba(95,161,255,0.6); }
  45%  { box-shadow: 0 0 56px rgba(95,161,255,1);   }
  100% { box-shadow: 0 0 28px rgba(95,161,255,0.6); }
}

/* 4. CTA distinct reveal — hairline rule draws first, then content.
      We replace the parent border-top with a pseudo-element we can
      animate (scaleX 0 -> 1). Children fade up after, lightly delayed. */
.chart__cta[data-reveal] {
  position: relative;
  border-top-color: transparent; /* hide the static rule; pseudo takes over */
  transform: translateY(28px);
  transition:
    opacity 800ms var(--ease),
    transform 900ms var(--ease);
  transition-delay: 120ms;
}
.chart__cta[data-reveal]::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  right: 0;
  height: 1px;
  background: rgba(255,255,255,0.18);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform 900ms var(--ease);
}
.chart__cta[data-reveal].is-visible::before {
  transform: scaleX(1);
}
.chart__cta[data-reveal] .chart__cta-h,
.chart__cta[data-reveal] .chart__cta-body {
  opacity: 0;
  transform: translateY(14px);
  transition:
    opacity 700ms var(--ease),
    transform 700ms var(--ease);
}
.chart__cta[data-reveal] .chart__cta-h     { transition-delay: 380ms; }
.chart__cta[data-reveal] .chart__cta-body  { transition-delay: 540ms; }
.chart__cta[data-reveal].is-visible .chart__cta-h,
.chart__cta[data-reveal].is-visible .chart__cta-body {
  opacity: 1;
  transform: none;
}

/* Reduced-motion: hard fallbacks so users who opt out land on the
   final visual state immediately. The global block at the bottom of
   the file zeroes durations; these rules guarantee no element is
   stuck mid-transform. */
@media (prefers-reduced-motion: reduce) {
  .chart__stat[data-reveal],
  .chart__cta[data-reveal] {
    transform: none !important;
    opacity: 1 !important;
  }
  .chart__cta[data-reveal] {
    border-top-color: rgba(255,255,255,0.12) !important;
  }
  .chart__cta[data-reveal]::before { display: none; }
  .chart__cta[data-reveal] .chart__cta-h,
  .chart__cta[data-reveal] .chart__cta-body {
    opacity: 1 !important;
    transform: none !important;
  }
  .huge__proof-mark.is-pulsing { animation: none !important; }
}

/* ============ STORIES HOVER ============ */
/* Coordinated 3-element hover choreography on .card. Existing rules
   already lift the card and invert color; we layer on:
     a) a brand-blue corner accent that grows (top-left to bottom-right
        diagonal) as a quiet "you can click this" signal
     b) the artwork scales up gently (1 -> 1.04) inside its frame so the
        tile feels alive without the whole card moving more
     c) the read-story CTA arrow slides 6px right
   Pure CSS, no JS. Compositor-friendly transforms only.
   Reduced-motion safe: existing global block neutralizes durations,
   and we add explicit static-state fallbacks at the bottom. */
.card { position: relative; overflow: hidden; isolation: isolate; }
.card__art {
  overflow: hidden;
  position: relative;
}
.card__art::before {
  /* The actual gradient lives on .card__art via background-image; we
     re-project it onto a ::before so we can scale it without scaling
     the frame itself. */
  content: "";
  position: absolute;
  inset: 0;
  background: inherit;
  background-image: inherit;
  background-size: cover;
  background-position: center;
  transform: scale(1);
  transition: transform 600ms var(--ease);
  will-change: transform;
}
.card:hover .card__art::before { transform: scale(1.04); }
.card__cta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  position: relative;
  transition: gap 300ms var(--ease), color var(--d-md) var(--ease);
}
.card:hover .card__cta { gap: 14px; }
.card::after {
  /* Diagonal corner accent — a thin brand line that scales from the
     top-left corner outward on hover. Lives behind text via z-index. */
  content: "";
  position: absolute;
  top: 0; left: 0;
  width: 24px;
  height: 2px;
  background: var(--c-brand);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform 380ms var(--ease);
  z-index: 0;
  pointer-events: none;
}
.card:hover::after { transform: scaleX(1); }
@media (prefers-reduced-motion: reduce) {
  .card__art::before,
  .card:hover .card__art::before { transform: none !important; }
  .card::after,
  .card:hover::after { transform: none !important; }
  .card:hover .card__cta { gap: 6px; }
}

/* ============ INCLUDED MAGNETIC HOVER ============ */
/* Cursor-toward-icon magnetic pull. The icon translates a maximum of
   6px in the cursor's direction with a 320ms ease-out on release. JS
   writes --mx / --my custom properties; CSS turns them into transforms.
   Pointer-only — JS guards with (hover: hover) and (pointer: fine).
   Performance: only one element per card moves, transform-only. */
.incentive { position: relative; }
.incentive__icon {
  --mx: 0;
  --my: 0;
  transform: translate3d(calc(var(--mx) * 1px), calc(var(--my) * 1px), 0);
  transition: transform 320ms cubic-bezier(0.22, 1, 0.36, 1),
              background var(--d-sm) var(--ease);
  will-change: transform;
}
.incentive.is-magnetic .incentive__icon {
  /* While the cursor is actively over the card, we want the move to
     follow quickly — short duration, snappy ease. The 320ms above
     applies on exit (when JS strips this class and resets to 0). */
  transition: transform 120ms linear, background var(--d-sm) var(--ease);
}
@media (prefers-reduced-motion: reduce) {
  .incentive__icon {
    transform: none !important;
    transition: background var(--d-sm) var(--ease);
  }
}

/* ============ ENROLL FORM FOCUS + SUBMIT ============ */
/* Animated focus ring: a brand-blue underline that draws across the
   bottom of the field on focus, on top of the existing 2px outline so
   AA contrast and the 2px effective width are never lost during the
   draw. We do NOT replace the outline — we layer.
   Submit press: depth on :active using translateY(1px) + inset shadow.
   Layered onto the existing .btn--primary hover, no conflict. */
.enroll-form input[type="text"],
.enroll-form input[type="email"],
.enroll-form input[type="tel"],
.enroll-form select,
.enroll-form textarea {
  position: relative;
  transition: border-color 220ms var(--ease),
              box-shadow 260ms var(--ease),
              background-color 220ms var(--ease);
}
.enroll-form input:focus,
.enroll-form select:focus,
.enroll-form textarea:focus {
  /* Keep the 2px outline (AA) AND draw a brand-blue inset underline
     via box-shadow that animates in from 0 to 3px. The outline stays
     full-strength the entire time — no contrast drop during the draw. */
  outline: 2px solid var(--c-brand);
  outline-offset: 0;
  border-color: var(--c-brand);
  box-shadow: inset 0 -3px 0 0 var(--c-brand-deep),
              0 0 0 4px rgba(23,111,233,0.12);
  background-color: #fafcff;
}
/* Submit press depth — layered onto existing .btn--primary:hover. */
.enroll-form__submit {
  position: relative;
  transition: background var(--d-sm) var(--ease),
              transform 140ms var(--ease),
              box-shadow 200ms var(--ease);
  box-shadow: 0 1px 0 0 rgba(0,0,0,0.10);
}
.enroll-form__submit:active {
  transform: translateY(1px);
  box-shadow: inset 0 2px 6px rgba(0,0,0,0.25),
              0 0 0 0 rgba(0,0,0,0.0);
}
.enroll-form__submit:focus-visible {
  outline: 2px solid #fff;
  outline-offset: -5px;
  box-shadow: 0 0 0 4px var(--c-brand-deep);
}
@media (prefers-reduced-motion: reduce) {
  .enroll-form input,
  .enroll-form select,
  .enroll-form textarea,
  .enroll-form__submit {
    transition: none !important;
  }
  .enroll-form__submit:active { transform: none !important; }
}

/* ============ PROGRAMS COUNTER ============ */
/* Tabular numerals so the digit width doesn't jitter as the value
   ticks up. Visually identical to the static rendering at rest. */
.count-up {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
}

/* (Flow progress rail removed per Kate's feedback — stacked-card layout
   makes a separate progress indicator redundant. The accumulating cards
   themselves are the progress visualization.) */

/* =========================================================
   ============ INDEX2 — COHESION SANDBOX ============
   ========================================================= */
/* Scoped under .v2 only. index.html (no .v2 class) is unaffected.
   Five v2-only motion treatments (May 10 update):
     1) Cohesion tokens — one curve, one duration for v2 reveals.
     2) Trafficwatch-style line-by-line word reveal in body copy.
     3) Stat-pop boost on chart big numbers + program counters.
     4) Right-gutter page-navigation slider (dots + section labels).
     5) CTA boost on the family-section CTA — bigger + glow pulse.
     6) Single-image parallax on the family photo (preserved from v1).

   The light/dark body-background handshake was removed on May 10 —
   Kate found the flash distracting. The data-v2-mode attributes stay
   on each section in case we want to reuse them. */

/* ---- Cohesion tokens ---- */
.v2 {
  /* One curve, one duration. Tweaks downstream are layered, not replaced. */
  --d-reveal: 700ms;
  --v2-side-color: #176fe9; /* brand blue */
}

/* Cohesion ingredient: the [data-split] mask reveal in the base sheet uses
   cubic-bezier(0.22, 1, 0.36, 1). On v2 we standardize on var(--ease) so
   every reveal speaks the same easing language as nav, hero veil, hover,
   chart-stat, and form transitions. Duration pinned to --d-reveal (700ms),
   matching [data-reveal] elsewhere on the page. */
.v2 [data-split] .reveal-inner {
  transition: transform var(--d-reveal) var(--ease);
}
.v2 [data-reveal] {
  transition: opacity var(--d-reveal) var(--ease),
              transform var(--d-reveal) var(--ease);
}

/* ---- Side-gutter rotated section label (legacy) ---- */
/* The rotated label is now superseded by the right-gutter page nav
   (see "v2 page nav" below). We keep the markup but hide it on v2 to
   avoid a double cluster on the right edge. */
.v2-side-label {
  display: none;
}

/* ---- Job 2: Trafficwatch line-by-line word reveal ---- */
/* Each targeted body-copy paragraph has its words wrapped in
   .v2-tw-word spans by JS. Each word carries --line-index (its
   visual line, computed by JS via offsetTop). Words on the same
   line share an index, so they reveal as a group; lines stagger
   by 70ms — enough beat to feel typed-in-batches without dragging.
   Compositor-only (opacity + 8px translateY).

   Why words (not characters): trafficwatch's pacing reads as
   "each line of prose appears one after the other." Per-character
   would feel typewriter-y; we already have a typewriter on the
   hero. Per-line is the right grain. */
.v2 .v2-tw-word {
  display: inline-block;
  opacity: 0;
  transform: translateY(8px);
  transition:
    opacity 520ms var(--ease),
    transform 520ms var(--ease);
  transition-delay: calc(var(--line-index, 0) * 70ms);
  will-change: opacity, transform;
}
.v2 .is-tw-revealed .v2-tw-word {
  opacity: 1;
  transform: none;
}
/* Instant variant: applied to blocks already in view at script init
   so the user never sees an opacity-0 frame for visible text. */
.v2 .is-tw-instant .v2-tw-word {
  opacity: 1;
  transform: none;
  transition: none !important;
  transition-delay: 0ms !important;
}
/* Preserve any inline emphasis inside the wrapped text. The wrapper
   walks text nodes only, so <em>/<strong> tags stay in place around
   their now-wrapped words. */
.v2 .v2-tw-word em,
.v2 .v2-tw-word strong {
  font: inherit;
  color: inherit;
}

/* ---- Job 3: Stat-pop on chart big numbers + program counters ---- */
/* Two of four techniques applied:
     - Longer count-up duration (handled in JS: 1600ms chart, 1200ms programs).
     - Scale-pop on land: the .is-popped class is added at duration-200ms,
       and the number scales from 0.92 to 1 over the final 200ms. The
       resting state is scale 1; the pop is anchored at the same end-state.

   Rejected:
     - Bigger entrance translateY — global data-reveal already supplies
       24px lift; doubling competes with the line-reveal in Job 2.
     - Brand-blue glow halo — reserved exclusively for the CTA (Job 5)
       so glow stays the page's loudest signal. */
.v2 .v2-statpop {
  display: inline-block;
  transform: scale(0.92);
  transform-origin: 50% 60%;
  transition: transform 200ms var(--ease);
  will-change: transform;
}
.v2 .v2-statpop.is-popped {
  transform: scale(1);
}

/* ---- Job 4: Right-gutter page-navigation slider ---- */
/* Hidden below 1024px (mobile uses the hamburger drawer). Pinned to the
   right edge. Each item is a 6px brand-blue dot with the section label
   appearing on hover; the ACTIVE item shows its label always and gets
   a 12px filled brand-blue dot. */
.v2-page-nav {
  display: none;
}
@media (min-width: 1024px) {
  body.v2 .v2-page-nav {
    display: block;
    position: fixed;
    top: 50%;
    right: 22px;
    z-index: 45;
    transform: translateY(-50%);
    pointer-events: auto;
  }
  body.v2 .v2-page-nav__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 14px;
    align-items: flex-end;
  }
  body.v2 .v2-page-nav__item { margin: 0; }
  body.v2 .v2-page-nav__link {
    display: flex;
    align-items: center;
    gap: 12px;
    text-decoration: none;
    font-family: var(--f-mono);
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--v2-side-color);
    /* Reserve enough room for the longest label so hover doesn't push
       the dot column horizontally. */
    min-height: 16px;
    padding: 4px 0;
    line-height: 1;
    cursor: pointer;
    transition:
      color 280ms var(--ease),
      opacity 280ms var(--ease);
    opacity: 0.55;
  }
  body.v2 .v2-page-nav__link:hover { opacity: 1; }
  body.v2 .v2-page-nav__label {
    display: inline-block;
    opacity: 0;
    transform: translateX(6px);
    transition:
      opacity 240ms var(--ease),
      transform 240ms var(--ease);
    /* Right-aligned because the nav is on the right gutter; reads
       toward the dot rather than away from it. */
    text-align: right;
    white-space: nowrap;
  }
  body.v2 .v2-page-nav__link:hover .v2-page-nav__label,
  body.v2 .v2-page-nav__item.is-active .v2-page-nav__label {
    opacity: 1;
    transform: none;
  }
  body.v2 .v2-page-nav__dot {
    display: inline-block;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: transparent;
    border: 1.5px solid var(--v2-side-color);
    transition:
      transform 280ms var(--ease),
      background 280ms var(--ease),
      border-color 280ms var(--ease),
      box-shadow 280ms var(--ease);
    flex-shrink: 0;
  }
  body.v2 .v2-page-nav__item.is-active .v2-page-nav__link {
    opacity: 1;
    color: var(--v2-side-color);
  }
  body.v2 .v2-page-nav__item.is-active .v2-page-nav__dot {
    background: var(--v2-side-color);
    transform: scale(1.6);
    box-shadow: 0 0 0 4px rgba(23, 111, 233, 0.12);
  }
}

/* ---- Job 5: CTA boost on .chart__cta-h ---- */
/* Two enhancements applied:
     1. Larger size — clamp(48px, 6vw, 96px), up from clamp(36, 4.5vw, 72).
     2. Brand-blue glow that pulses on reveal then settles to a subtle
        resting state. Driven by an animation on .is-visible so the
        pulse runs once, in time with the existing CTA reveal cascade.
   Rejected: hairline draw across full page width (the CTA's existing
   ::before scaleX rule already handles this from 0..100% within the
   container — extending it edge-to-edge would crash through the chart
   grid above). Letter-by-letter reveal on the headline (would conflict
   with Job 2's word reveal happening throughout the page). */
body.v2 #family .chart__cta-h {
  font-size: clamp(48px, 6vw, 96px);
  /* Resting glow — soft, just enough to feel held. */
  text-shadow: 0 0 28px rgba(95, 161, 255, 0.18);
}
body.v2 #family .chart__cta[data-reveal].is-visible .chart__cta-h {
  animation: v2-cta-pulse 1500ms var(--ease) 380ms 1 both;
}
@keyframes v2-cta-pulse {
  0%   { text-shadow: 0 0 28px rgba(95, 161, 255, 0.18); }
  35%  { text-shadow: 0 0 64px rgba(95, 161, 255, 0.85); }
  100% { text-shadow: 0 0 28px rgba(95, 161, 255, 0.28); }
}

/* ---- Single-image parallax: family photo ---- */
/* The base .huge__photo paints its background-image directly on the box.
   To translate the photo without translating the layout box, we move the
   image to a ::before pseudo, oversize it (height 130%, top -15%), then
   JS writes translate3d(0, Y, 0) on it. Compositor-only. */
@media (min-width: 800px) {
  body.v2 .huge__photo {
    background-image: none; /* repainted in ::before below */
  }
  body.v2 .huge__photo::before {
    content: "";
    position: absolute;
    inset: -15% 0;
    background:
      linear-gradient(180deg, rgba(0,0,0,0) 55%, rgba(0,0,0,0.45) 100%),
      url("outcomes.png");
    background-size: cover;
    background-position: center;
    will-change: transform;
    transform: translate3d(0, 0, 0);
  }
}

/* ---- Job 6: Circle hero stat (v2-only, family section) ---- */
/* Layout: two-column hero stat above the existing 4-card grid.
     left column = ring (~40%), right column = caption + attribution.
     Stacks to single column under 800px (ring on top).
   Visual:
     - SVG ring uses pathLength="100" so stroke-dasharray/offset map
       to a 0..100 percent regardless of the actual circumference.
       Resting state: dashoffset 100 (empty). Filled state: 0 (full).
     - Track ring at low-opacity white so the brand-blue arc reads
       cleanly on the dark slab.
     - Center number sits absolutely centered inside the ring; type
       size pushes past the supporting cards' .chart__big so it
       reads as the section hero (ring + number > four below).
     - Halo: a soft brand-blue radial behind the ring; idle at low
       opacity, pulses brighter once the ring fill completes (JS
       toggles .is-haloed). Reuses the CTA glow color signature
       (rgba(95, 161, 255, 0.x)) but lives behind the SVG, not in
       text-shadow, so the two glows never compete on the same node.
   Motion contract (JS owns sequencing — see script.js v2 IIFE):
     - On intersection: stroke-dashoffset animates 100 -> 0 over
       1400ms ease-out (CSS transition, JS sets the inline style).
     - 200ms after the ring kicks, the center number count-up runs
       0 -> 10 over 1400ms (custom easing — easeOutCubic).
     - At ring-fill completion: halo .is-haloed turns on; CSS
       handles a 400ms fade-in / 600ms fade-out via animation.
   Reduced motion: the stylesheet's @media block at the bottom
     short-circuits dashoffset to 0 and halo to idle opacity;
     JS's prefersReduced check skips the count-up entirely. */
body.v2 .chart-hero {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 0.75fr) minmax(0, 1fr);
  gap: var(--s-5);
  align-items: center;
  margin: 0 auto var(--s-6);
  max-width: var(--container);
  padding: var(--s-5) 0 var(--s-6);
  border-bottom: 1px solid rgba(255,255,255,0.12);
}
body.v2 .chart-hero__ring {
  position: relative;
  width: clamp(240px, 28vw, 380px);
  aspect-ratio: 1 / 1;
  margin: 0 auto;
  /* Promote to its own layer; the SVG stroke transition + halo
     animation share the box. */
  isolation: isolate;
}
body.v2 .chart-hero__halo {
  position: absolute;
  inset: -8%;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(95, 161, 255, 0.32), rgba(95, 161, 255, 0) 72%);
  opacity: 0;
  pointer-events: none;
  z-index: 0;
  filter: blur(2px);
  will-change: opacity;
}
body.v2 .chart-hero__ring.is-haloed .chart-hero__halo {
  animation: v2-halo-pulse 1000ms var(--ease) 1 both;
}
@keyframes v2-halo-pulse {
  0%   { opacity: 0; }
  40%  { opacity: 1; }
  100% { opacity: 0; }
}
body.v2 .chart-hero__svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* Start the arc at 12 o'clock, sweep clockwise — same as trafficwatch
     and the universal data-viz convention for a part-of-whole reveal. */
  transform: rotate(-90deg);
  z-index: 1;
}
body.v2 .chart-hero__track {
  fill: none;
  stroke: rgba(255, 255, 255, 0.14);
  stroke-width: 7;
}
body.v2 .chart-hero__fill {
  fill: none;
  stroke: var(--c-brand);
  stroke-width: 7;
  stroke-linecap: round;
  /* pathLength="100" on the element normalizes dasharray to 0..100. */
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  transition: stroke-dashoffset 1400ms cubic-bezier(0.22, 1, 0.36, 1);
  will-change: stroke-dashoffset;
}
body.v2 .chart-hero[data-chart-hero].is-filled .chart-hero__fill {
  stroke-dashoffset: 0;
}
body.v2 .chart-hero__big {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--f-display);
  font-weight: 800;
  font-size: clamp(96px, 9vw, 156px);
  line-height: 1;
  letter-spacing: -0.04em;
  color: var(--c-brand);
  font-variant-numeric: tabular-nums;
  z-index: 2;
  pointer-events: none;
}
body.v2 .chart-hero__copy {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  max-width: 50ch;
}
body.v2 .chart-hero__kicker {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  font-family: var(--f-mono);
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.62);
}
body.v2 .chart-hero__bullet {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--c-brand);
  display: inline-block;
}
body.v2 .chart-hero__caption {
  margin: 0;
  font-family: var(--f-display);
  font-weight: 500;
  font-size: clamp(20px, 1.8vw, 26px);
  line-height: 1.4;
  color: rgba(255,255,255,0.92);
}
body.v2 .chart-hero__source {
  margin: var(--s-1) 0 0;
  font-family: var(--f-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  color: rgba(255,255,255,0.55);
  line-height: 1.6;
}
body.v2 .chart-hero__view-source {
  color: rgba(255,255,255,0.78);
  text-decoration: none;
  border-bottom: 1px solid rgba(255,255,255,0.32);
  padding-bottom: 1px;
  margin-left: 6px;
  transition: color var(--d-sm) var(--ease), border-color var(--d-sm) var(--ease);
}
body.v2 .chart-hero__view-source:hover {
  color: #fff;
  border-bottom-color: #fff;
}

@media (max-width: 800px) {
  body.v2 .chart-hero {
    grid-template-columns: 1fr;
    gap: var(--s-4);
    text-align: center;
  }
  body.v2 .chart-hero__copy {
    margin: 0 auto;
    align-items: center;
  }
  body.v2 .chart-hero__caption { text-wrap: balance; }
}

/* ---- Reduced motion ---- */
@media (prefers-reduced-motion: reduce) {
  body.v2 .huge__photo::before {
    transform: none !important;
  }
  .v2 [data-split] .reveal-inner,
  .v2 [data-reveal] {
    transition: none !important;
  }
  /* Job 2: words land at full opacity, no stagger. */
  .v2 .v2-tw-word {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  /* Job 3: numbers settle to rest state immediately. */
  .v2 .v2-statpop {
    transform: none !important;
    transition: none !important;
  }
  /* Job 4: page nav still works; just no transition flourish. */
  body.v2 .v2-page-nav__link,
  body.v2 .v2-page-nav__label,
  body.v2 .v2-page-nav__dot {
    transition: none !important;
  }
  /* Job 5: CTA pulse disabled. */
  body.v2 #family .chart__cta[data-reveal].is-visible .chart__cta-h {
    animation: none !important;
  }
  /* Job 6: hero ring renders fully filled, no transition; halo idle off. */
  body.v2 .chart-hero__fill {
    stroke-dashoffset: 0 !important;
    transition: none !important;
  }
  body.v2 .chart-hero__ring.is-haloed .chart-hero__halo {
    animation: none !important;
    opacity: 0 !important;
  }
}
