/* ==========================================================================
   GAVP Microsite — Design System
   ========================================================================== */

@font-face{
  font-family:'Ubuntu';
  font-style:normal;
  font-weight:600;
  font-display:swap;
  src:url('../assets/fonts/ubuntu-600.woff2') format('woff2');
}
@font-face{
  font-family:'Ubuntu';
  font-style:normal;
  font-weight:700;
  font-display:swap;
  src:url('../assets/fonts/ubuntu-700.woff2') format('woff2');
}
@font-face{
  /* Ubuntu has no extra-bold cut — reuse Bold for the rare 800-weight usage
     (e.g. big stat numerals) rather than leaving it missing/faux-bolded. */
  font-family:'Ubuntu';
  font-style:normal;
  font-weight:800;
  font-display:swap;
  src:url('../assets/fonts/ubuntu-700.woff2') format('woff2');
}
@font-face{
  font-family:'Open Sans';
  font-style:normal;
  font-weight:400;
  font-display:swap;
  src:url('../assets/fonts/opensans-400.woff2') format('woff2');
}
@font-face{
  /* Open Sans' TTF set has no Medium cut — 500-weight body text renders as Regular. */
  font-family:'Open Sans';
  font-style:normal;
  font-weight:500;
  font-display:swap;
  src:url('../assets/fonts/opensans-400.woff2') format('woff2');
}
@font-face{
  font-family:'Open Sans';
  font-style:normal;
  font-weight:600;
  font-display:swap;
  src:url('../assets/fonts/opensans-600.woff2') format('woff2');
}
@font-face{
  /* covers the handful of body-text <strong> tags (e.g. .state-mini) that ask for 700 —
     without this the browser would fall back to the 600 cut for them. */
  font-family:'Open Sans';
  font-style:normal;
  font-weight:700;
  font-display:swap;
  src:url('../assets/fonts/opensans-700.woff2') format('woff2');
}

:root{
  /* colour */
  --blue-950:#072C5A; /* deepen-on-hover/focus shade for the Challenge-page map states */
  --blue-900:#0A3D7C;
  --blue-700:#12509E;
  --blue-600:#1B62B8;
  /* Was #E8F2FC — reported directly as too close to white to read clearly during the
     page-backdrop crossfade on some screens. Nudged slightly more saturated/darker, not a big
     jump (contrast with --ink-900 body text is still 12.87:1, comfortably above the 14.07:1 it
     was before — nowhere close to the 4.5:1 AA floor either way). This is a single shared
     token, so every .section-tint background, and everything else that reads --blue-100
     (icon-tile fills, chip backgrounds, etc.), picks up the change together. */
  --blue-100:#D2E6FB;
  --blue-50:#F4F9FE;

  --orange-600:#F07D1C;
  --orange-500:#F5922E;
  --orange-100:#FDE9D4;
  /* --orange-600 on white is only 2.74:1 — fine for white-on-orange buttons/fills/dividers,
     but fails WCAG AA for orange text on white. Use --orange-text (4.65:1) for inline/heading
     text highlights instead; never use --orange-600 for text set directly on a white ground. */
  --orange-text:#C1531A;

  --ink-900:#152238;
  --ink-600:#5B6472;
  --white:#FFFFFF;

  /* type */
  --font-head:'Ubuntu', 'Segoe UI', sans-serif;
  --font-body:'Open Sans', 'Segoe UI', sans-serif;

  /* layout */
  --container:1240px;
  --gutter:clamp(20px, 5vw, 96px);
  /* Shared vertical section spacing. How GAVP Works uses its own
     `--how-block-gap` so its three content groups share one equal responsive rhythm. */
  --section-y:clamp(44px, 6vw, 84px);

  /* motion — shared across the premium scroll/chapter system (see CLAUDE.md
     "Premium scroll chapters & motion system"). Reused rather than one-off
     values per component, so the page reads as one composed system. */
  --ease-premium:cubic-bezier(.22,1,.36,1);
  --ease-smooth:cubic-bezier(.65,0,.35,1);
  --duration-fast:280ms;
  --duration-medium:650ms;
  --duration-slow:1000ms;
}

*, *::before, *::after{ box-sizing:border-box; }
html{ scroll-behavior:smooth; }
body{
  margin:0;
  font-family:var(--font-body);
  color:var(--ink-900);
  background:var(--white);
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
  /* the full-bleed logo patch uses the 100vw/-50vw breakout trick, which can introduce a
     hairline horizontal scrollbar on some browsers when a vertical scrollbar is present
     (100vw includes its width). This is the standard, low-risk guard for that trick. */
  overflow-x:hidden;
}
/* Horizontal clipping guard for full-bleed 100vw components. `clip` is deliberate here:
   unlike `hidden`, it does not create a scroll container, so viewport-sticky descendants
   (notably the How GAVP Works transition panel) keep their intended sticky containing block. */
main{ overflow-x:clip; }

/* Single full-page colour backdrop — fixed behind everything, one flat colour across the
   whole viewport at any given scroll position. initPageBackdrop() in js/main.js sets
   data-active-theme ("white" / "tint" / "dark") on this element based on which themed
   section ([data-bg-theme]) currently crosses the vertical centre of the viewport (same
   IntersectionObserver + centre-band rootMargin technique the old per-section fade used).
   z-index:-1 (not a positive z-index moved via DOM order) so it never needs touching every
   section's own stacking — it just sits below the normal (auto/0+) stacking of everything
   else in the document by definition. */
.page-backdrop{
  position:fixed;
  inset:0;
  z-index:-1;
  background-color:var(--white);
  transition:background-color 1.1s ease;
}
.page-backdrop[data-active-theme="tint"]{ background-color:var(--blue-100); }
.page-backdrop[data-active-theme="dark"]{ background-color:var(--blue-900); }
@media (prefers-reduced-motion: reduce){
  .page-backdrop{ transition:none; }
}
html.no-js .page-backdrop{ display:none; } /* no-js falls back to each section painting its
  own resting colour again — see .section-tint/.section-dark no-js rules above */

/* Swipe-up reveal — used on the heading of every section that follows a dark chapter
   (How GAVP Works after Challenge, Resources after Partners). A ONE-SHOT reveal, exactly
   like .reveal (added to the same initScrollReveal() observer, gets .in-view once), just
   with a clip-path wipe instead of opacity+translateY: the heading is masked off from below
   and unmasks upward as it scrolls into view. No extra scroll distance required — this is
   NOT the position:sticky "pin the heading, hold it, then release" version tried earlier.
   That version needed a tall .pin-wrap "runway" purely to give the sticky hold something to
   consume, and that runway rendered as a large, empty, dead-scroll gap before the rest of
   the section's content — exactly the complaint that got it removed. This has no runway: it
   plays once, over a fraction of a second, the moment the heading enters view. */
.reveal--swipe{
  opacity:0;
  clip-path:inset(100% 0 0 0);
  transition:opacity var(--duration-medium) var(--ease-premium),
             clip-path var(--duration-medium) var(--ease-premium);
}
.reveal--swipe.in-view{ opacity:1; clip-path:inset(0 0 0 0); }
@media (prefers-reduced-motion: reduce){
  .reveal--swipe{ transition:none !important; opacity:1 !important; clip-path:none !important; }
}

/* ==========================================================================
   Challenge → How GAVP Works transition
   ========================================================================== */
/* The outgoing dark panel is sticky while the real How GAVP Works section scrolls over it.
   There is no pinned incoming 100vh panel and no ScrollTrigger spacer: the incoming chapter
   is ordinary document flow, so its content height is determined by content, not viewport. */
.curtain-transition{
  position:relative;
}
.curtain-current{
  position:sticky;
  top:0;
  z-index:1;
  min-height:100vh;
  min-height:100svh;
  display:flex;
  align-items:center;
  padding:clamp(72px, 8vw, 112px) 0;
  background-color:var(--blue-900);
}
.curtain-current > .container{ width:100%; }

/* The actual How GAVP Works chapter paints an opaque tint because it physically passes over
   the sticky dark panel. Once it reaches the viewport it becomes the visible surface. */
.how-gavp{
  --how-block-gap:clamp(72px, 7vw, 112px);
  position:relative;
  z-index:2;
  min-height:auto;
  align-items:stretch;
  padding:var(--how-block-gap) 0;
  background-color:var(--blue-100);
  scroll-margin-top:88px;
}
.how-gavp-flow{
  display:flex;
  flex-direction:column;
  gap:var(--how-block-gap);
}
.how-gavp-intro{
  max-width:760px;
  margin:0 auto;
  text-align:center;
}
.how-gavp-block{ min-width:0; }
.how-gavp .gcw-row{ margin-bottom:0; }
.how-gavp .stat-banner{ margin-bottom:0; }

@media (max-width:820px){
  .how-gavp{ --how-block-gap:clamp(52px, 9vw, 72px); }
  .curtain-current{ padding:64px 0; }
}

@media (prefers-reduced-motion: reduce){
  .curtain-current{ position:relative; min-height:auto; }
}
html.no-js .curtain-current{ position:relative; min-height:auto; }

img{ max-width:100%; display:block; }
a{ color:inherit; text-decoration:none; }
ul{ margin:0; padding:0; list-style:none; }
button{ font-family:inherit; cursor:pointer; }
h1,h2,h3,h4{
  font-family:var(--font-head);
  color:var(--blue-700);
  margin:0;
  line-height:1.15;
  text-wrap:balance;
  font-weight:700;
}
p{ margin:0; }

.container{
  max-width:var(--container);
  margin:0 auto;
  padding:0 var(--gutter);
  position:relative;
  z-index:2; /* explicit — keeps real content above .line-ornament (z-index:1) in any
                section that has one */
}

.visually-hidden{
  position:absolute; width:1px; height:1px; overflow:hidden;
  clip:rect(0 0 0 0); white-space:nowrap;
}

/* focus visibility */
a:focus-visible, button:focus-visible{
  outline:2px solid var(--orange-600);
  outline-offset:3px;
  border-radius:4px;
}

@media (prefers-reduced-motion: reduce){
  *{ animation-duration:0.001ms !important; animation-iteration-count:1 !important; transition-duration:0.001ms !important; scroll-behavior:auto !important; }
}

/* ==========================================================================
   Type helpers
   ========================================================================== */

.eyebrow{
  display:inline-flex;
  align-items:center;
  gap:8px;
  font-family:var(--font-body);
  font-weight:600;
  font-size:16px; /* bumped up per direct client feedback (first 12.5px->13.5px, then asked to
    increase further) — was 12.5px originally */
  letter-spacing:0.08em;
  text-transform:uppercase;
  color:var(--orange-text); /* AA-safe on white/pale grounds — see --orange-text note */
  margin-bottom:14px;
}
.eyebrow.blue{ color:var(--blue-600); }
/* on a dark blue surface, keep the label itself high-contrast white and let the leading
   rule (decorative, not text) carry the orange accent instead */
.eyebrow.on-dark{ color:rgba(255,255,255,.88); }
/* The small leading dash/rule before every eyebrow label — removed site-wide per direct
   feedback ("remove the dash before section headers. It looks very AI"). display:none rather
   than deleting the rule outright, so the colour/sizing is still here to just flip back on if
   ever wanted again — same "leave dead code, keep the history" convention as elsewhere in this
   file, just via a one-line toggle instead of a whole unused block. */
.eyebrow::before{
  content:"";
  width:22px; height:2px;
  background:var(--orange-600);
  border-radius:2px;
  display:none;
}
.eyebrow.blue::before{ background:var(--blue-600); }

.section-head{ max-width:640px; }
.section-head h2{ font-size:clamp(28px, 3.2vw, 40px); margin-bottom:16px; }
.lede{ font-size:16px; color:var(--ink-600); max-width:56ch; }

/* ==========================================================================
   Buttons
   ========================================================================== */

.btn{
  display:inline-flex;
  align-items:center;
  gap:10px;
  font-family:var(--font-body);
  font-weight:600;
  font-size:15px;
  padding:13px 26px;
  border-radius:999px;
  border:1.5px solid transparent;
  transition:transform .15s ease, box-shadow .15s ease, background .15s ease, color .15s ease;
  white-space:nowrap;
}
.btn:hover{ transform:translateY(-1px); }

.btn-primary{
  background:var(--orange-600);
  color:var(--white);
  box-shadow:0 6px 18px -8px rgba(240,125,28,.6);
}
.btn-primary:hover{ background:var(--orange-500); }

.btn-secondary{
  background:var(--white);
  border-color:var(--blue-600);
  color:var(--blue-600);
}
.btn-secondary:hover{
  background:var(--orange-100);
  border-color:var(--orange-600);
  color:var(--orange-600);
}
.btn-secondary:hover .btn-play-dot svg polygon{ fill:var(--orange-600); }

.btn-on-dark{
  background:transparent;
  border-color:rgba(255,255,255,.7);
  color:var(--white);
}
.btn-on-dark:hover{
  background:rgba(240,125,28,.16);
  border-color:var(--orange-600);
  color:var(--orange-500);
}

.btn-play-dot{
  width:22px; height:22px; border-radius:50%;
  background:rgba(255,255,255,.25);
  display:inline-flex; align-items:center; justify-content:center;
  flex:none;
}
.btn-play-dot svg{ width:9px; height:9px; margin-left:1px; }

/* ==========================================================================
   Nav
   ========================================================================== */

.site-header{
  position:sticky; top:0; z-index:50;
  background:rgba(255,255,255,.92);
  backdrop-filter:blur(8px);
  border-bottom:1px solid rgba(18,80,158,.08);
  transition:background-color var(--duration-medium) ease, border-color var(--duration-medium) ease;
}
/* Keep the sticky GAVP navbar below the WordPress admin toolbar
   while viewing the site as a logged-in administrator. */
body.admin-bar .site-header{
  top:32px;
}

@media screen and (max-width:782px){
  body.admin-bar .site-header{
    top:46px;
  }
}
/* Toggled by initHeaderTheme() in js/main.js — an IntersectionObserver watches every
   .section-dark chapter and flips this on while one sits under the sticky header, so
   nav/logo colour inverts in sync with the chapter it's currently over instead of
   staying fixed. */
.site-header.on-dark{
  background:rgba(10,61,124,.88);
  border-bottom-color:rgba(255,255,255,.14);
}
.site-header.on-dark .logo{ color:var(--white); }
.site-header.on-dark .logo span{ color:var(--orange-500); }
.site-header.on-dark .nav-links a{ color:rgba(255,255,255,.85); }
.site-header.on-dark .nav-links a:hover,
.site-header.on-dark .nav-links a.active{ border-color:var(--orange-500); }
.site-header.on-dark .nav-toggle span,
.site-header.on-dark .nav-toggle::before,
.site-header.on-dark .nav-toggle::after{ background:var(--white); }
.nav{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:24px;
  padding:18px var(--gutter);
  max-width:var(--container);
  margin:0 auto;
  border-radius:999px;
  transition:max-width var(--duration-medium) var(--ease-premium),
             padding var(--duration-medium) var(--ease-premium),
             background-color var(--duration-medium) ease,
             box-shadow var(--duration-medium) ease,
             border-color var(--duration-medium) ease;
}
/* Floating pill navbar once the page is scrolled — toggled by initHeaderScrollShrink()
   in js/main.js (a simple scrollY > 24px threshold). At rest, .site-header is the plain
   full-width bar it always was (background/blur/border live there); once scrolled, that
   full-width chrome goes transparent and the "bar" look moves onto .nav itself, which
   shrinks to a centred, rounded pill with its own background/shadow/border so it reads as
   a distinct floating control rather than a shrunken version of the same bar. */
.site-header.is-scrolled{
  background:transparent;
  border-bottom-color:transparent;
  backdrop-filter:none;
  padding-top:10px;
}
.site-header.is-scrolled .nav{
  max-width:1080px;
  padding:10px 14px 10px 26px;
  gap:18px;
  background:rgba(255,255,255,.92);
  backdrop-filter:blur(10px);
  box-shadow:0 10px 30px rgba(10,61,124,.16);
  border:1px solid rgba(18,80,158,.10);
}
.site-header.is-scrolled .nav-links{ gap:20px; white-space:nowrap; }
.site-header.on-dark.is-scrolled .nav{
  background:rgba(10,61,124,.92);
  box-shadow:0 10px 30px rgba(0,0,0,.28);
  border-color:rgba(255,255,255,.14);
}
@media (max-width:900px){
  .site-header.is-scrolled .nav{ max-width:calc(100% - 32px); padding:8px 10px; }
}
.logo{
  font-family:var(--font-head);
  font-weight:800;
  font-size:22px;
  letter-spacing:.01em;
  color:var(--blue-700);
  white-space:nowrap;
  flex-shrink:0;
}
/* Dead code — .logo used to end in an orange "." (<span>.</span>), removed site-wide per direct
   feedback ("remove the dot after GAVP wherever applicable"). Left in place, unused, same
   dead-code convention as elsewhere in this file. */
.logo span{ color:var(--orange-600); }

.nav-links{
  display:flex;
  align-items:center;
  gap:30px;
  white-space:nowrap;
}
.nav-links a{
  font-size:14.5px;
  font-weight:600;
  color:var(--blue-700);
  padding:6px 2px;
  border-bottom:2px solid transparent;
  border-radius:999px;
  transition:border-color .15s ease, color var(--duration-medium) ease,
             background-color .2s ease, padding .2s ease;
}
.nav-links a:hover{ border-color:var(--orange-600); }
.nav-mobile-contact{ display:none; }
/* Scrollspy-driven active state (initNavScrollSpy() in js/main.js) — a solid dark-blue pill,
   per direct feedback ("highlight the section we're in, maybe with a dark blue background... it
   is both functional and aesthetic"). Was just an orange border-bottom (a leftover, never
   actually wired to anything — no JS toggled .active before this). Extra horizontal padding
   only applies to the active link itself, so the pill shape doesn't need a fixed width. */
.nav-links a.active{
  background:var(--blue-700); color:var(--white);
  border-color:transparent;
  padding:6px 14px;
}
.site-header.on-dark .nav-links a.active{ background:var(--orange-500); color:var(--white); border-color:transparent; }

.nav-cta{ display:flex; align-items:center; gap:14px; }

.nav-toggle{
  display:none;
  background:none; border:none;
  width:38px; height:38px;
  align-items:center; justify-content:center;
}
.nav-toggle span, .nav-toggle::before, .nav-toggle::after{
  content:"";
  display:block;
  width:20px; height:2px;
  background:var(--blue-700);
  border-radius:2px;
}
.nav-toggle span{ margin:5px 0; }


/* Sangam Collaborative navbar fit
   --------------------------------
   The longer wordmark needs more horizontal room than the previous GAVB label.
   On desktop, keep the wordmark on one line and allow the floating/scrolled pill
   to use almost the full viewport width so the Contact Us CTA stays inside it. */
@media (min-width:901px){
  .site-header .logo{
    font-size:18px;
  }

  .site-header.is-scrolled .nav{
    width:calc(100% - 24px);
    max-width:1240px;
    padding-left:20px;
    padding-right:14px;
    gap:14px;
  }

  .site-header.is-scrolled .nav-links{
    gap:16px;
  }

  .site-header.is-scrolled .nav-cta{
    flex-shrink:0;
  }

  .site-header.is-scrolled .nav-cta .btn{
    padding:11px 20px;
    font-size:14px;
  }
}

/* Extra breathing room on smaller desktop/laptop widths while still preserving
   the full desktop navigation instead of prematurely switching to the mobile menu. */
@media (min-width:901px) and (max-width:1180px){
  .nav{
    gap:14px;
  }

  .nav-links{
    gap:16px;
  }

  .nav-links a{
    font-size:13.5px;
  }

  .site-header .logo{
    font-size:17px;
  }

  .nav-cta .btn{
    padding:11px 18px;
    font-size:13.5px;
  }
}

@media (max-width:900px){
  .nav{
    display:grid;
    grid-template-columns:1fr auto 1fr;
    align-items:center;
  }
  .logo{ grid-column:2; justify-self:center; }
  .nav-cta{ grid-column:3; justify-self:end; margin-left:0; }
  .nav-cta .btn{ display:none; }
  .nav-links{
    position:absolute; top:100%; left:0; right:0;
    background:var(--white);
    flex-direction:column;
    align-items:flex-start;
    gap:4px;
    padding:14px var(--gutter) 20px;
    border-bottom:1px solid rgba(18,80,158,.08);
    transform:translateY(-8px);
    opacity:0;
    visibility:hidden;
    transition:opacity .18s ease, transform .18s ease, visibility .18s ease;
  }
  .nav-links a{ padding:10px 0; width:100%; }
  .nav-links .nav-mobile-contact{ display:block; }
  .nav-links.open{ opacity:1; transform:translateY(0); visibility:visible; }
  .nav-toggle{ display:inline-flex; flex-direction:column; }
  .site-header.on-dark .nav-links{ background:var(--blue-900); border-bottom-color:rgba(255,255,255,.14); }
}

/* ==========================================================================
   Decorative line ornament (hand-authored, reused across sections)
   ========================================================================== */

.line-ornament{
  position:absolute;
  inset:0;
  width:100%; height:100%;
  overflow:visible;
  pointer-events:none;
  z-index:0;
}
.line-ornament path{ fill:none; will-change:transform; }

/* gentle ambient "flowing" drift — three staggered rhythms so lines don't move in lockstep.
   transform-box is set explicitly: SVG child elements don't reliably pick up CSS transform
   animation in every browser without it, which is the most common reason this silently no-ops. */
.line-ornament path{ transform-box:fill-box; transform-origin:center; }
.line-ornament .flow-a{ animation:lineFlowA 8s ease-in-out infinite alternate; }
.line-ornament .flow-b{ animation:lineFlowB 10s ease-in-out infinite alternate; animation-delay:-2s; }
.line-ornament .flow-c{ animation:lineFlowC 13s ease-in-out infinite alternate; animation-delay:-5s; }

@keyframes lineFlowA{
  from{ transform:translate(-24px,-8px); }
  to{ transform:translate(24px,10px); }
}
@keyframes lineFlowB{
  from{ transform:translate(20px,10px); }
  to{ transform:translate(-20px,-12px); }
}
@keyframes lineFlowC{
  from{ transform:translate(-16px,12px); }
  to{ transform:translate(26px,-8px); }
}

/* ==========================================================================
   Photo frames — asymmetric curved corners
   ========================================================================== */

.photo-frame{
  position:relative;
  overflow:hidden;
  background:linear-gradient(135deg, var(--blue-100), #dce9f7);
  border:1px solid rgba(18,80,158,.08);
}
.photo-frame img{ width:100%; height:100%; object-fit:cover; }
.photo-frame .frame-tag{
  position:absolute; left:14px; bottom:14px;
  background:rgba(21,34,56,.72);
  color:#fff;
  font-size:11px;
  padding:5px 10px;
  border-radius:6px;
  font-family:var(--font-body);
  letter-spacing:.02em;
  z-index:2;
}

.frame-hero{ border-radius:32px 140px 32px 32px; aspect-ratio:6/7; }
.frame-blob-b{ border-radius:32px 32px 140px 32px; }
.frame-blob-tr{ border-radius:32px 140px 32px 32px; }
.frame-blob-tl{ border-radius:140px 32px 32px 32px; }
.frame-video{ border-radius:32px 100px 32px 32px; aspect-ratio:16/10; }

/* ==========================================================================
   Hero
   ========================================================================== */

.hero{
  position:relative;
  overflow:hidden;
}
.hero-grid{
  display:grid;
  grid-template-columns:1.05fr 0.95fr;
  gap:56px;
  align-items:center;
  position:relative;
  z-index:2;
}
.hero h1{
  font-size:clamp(34px, 4.6vw, 56px);
  margin-bottom:18px;
}
.hero .lede{ margin-bottom:28px; font-size:17px; }

.hero-ctas{ display:flex; gap:14px; flex-wrap:wrap; margin-bottom:34px; }

/* Text-plus-arrow hero links — replaces the old solid-pill CTAs, modelled directly on the
   ClimateWorks Foundation reference (plain bold white text + a diagonal arrow, no button
   chrome). Kept deliberately minimal/editorial to match that reference exactly. */
.hero-cta-links{ display:flex; gap:40px; flex-wrap:wrap; margin-bottom:34px; }
.hero-cta-link{
  display:inline-flex; align-items:center; gap:10px;
  color:var(--white); font-family:var(--font-body); font-weight:700; font-size:15.5px;
}
.hero-cta-arrow{
  width:26px; height:26px; border-radius:50%;
  border:1px solid rgba(255,255,255,.6);
  display:inline-flex; align-items:center; justify-content:center; flex:none;
  transition:transform .25s ease, background-color .25s ease, border-color .25s ease;
}
.hero-cta-arrow svg{ width:13px; height:13px; }
.hero-cta-link:hover .hero-cta-arrow{
  background:var(--orange-500); border-color:var(--orange-500);
  transform:translate(2px,-2px);
}
@media (max-width:480px){ .hero-cta-links{ gap:24px; } .hero-cta-link{ font-size:14px; } }

.stat-bar{
  display:flex; flex-wrap:wrap;
  align-items:center;
  gap:10px;
  font-family:var(--font-head);
  font-weight:700;
  font-size:14px;
  color:var(--blue-700);
  letter-spacing:.02em;
  padding-top:22px;
  border-top:1px solid rgba(18,80,158,.14);
  margin-bottom:14px;
}
.stat-bar .dot{ color:var(--orange-600); font-weight:700; }

.state-list{
  font-size:13.5px;
  color:var(--ink-600);
  display:flex; flex-wrap:wrap; gap:8px;
}
.state-list .dot{ color:var(--orange-600); }

/* ==========================================================================
   Hero — full-bleed autoplay video background
   ========================================================================== */

/* Height reduced (was clamp(560px,82vh,800px)) — per direct feedback that the hero "seems bit
   large... the lack of text in it makes it look very empty," referencing the ClimateWorks
   site's own shorter hero. A shorter box makes the same headline+2 links read as intentional
   rather than lost in empty space, without needing to invent extra copy just to fill height. */
.hero--video{
  min-height:clamp(440px, 58vh, 620px);
  display:flex;
  align-items:center;
  /* deliberately NO padding on this element — it's what the video (inset:0, a sibling,
     not a descendant of .container) uses as its box, so any padding here would only
     shrink the space the video is positioned within on some engines' box-model edge
     cases. All breathing room instead lives on .hero-copy below, which can't affect the
     video's coverage since it's a cousin, not a sibling, of the video element. */
  padding:0;
}
/* .hero--video is a flex container, so its .container child is a flex item — without an
   explicit width, a flex item's basis defaults to its own content's shrink-to-fit size,
   not 100% of the row, and .container's own margin:0 auto then centred that *smaller* box
   within the flex row instead of spanning full width and left-padding its content. That's
   what was pushing the hero heading well right of the nav logo above it (the nav isn't
   nested in a flex parent, so it never hit this). width:100% puts .container back to
   spanning the full row, at which point its max-width/margin/padding centre+pad exactly
   like every other section's .container does, and the heading lines up with the nav logo. */
.hero--video > .container{ width:100%; }
.hero-video{
  position:absolute;
  top:0; left:0;
  width:100%; height:100%;
  min-width:100%; min-height:100%;
  object-fit:cover;
  object-position:center;
  z-index:0;
  display:block;
}
/* strong blue on the left where the text sits, fading out so the footage reads clearly
   on the right — same left-to-right overlay language used elsewhere on the page */
/* Was a strong blue-900 gradient (up to 93% opacity near the text) — replaced with a much
   lighter plain-black gradient per direct client feedback ("remove the blue overlay... to make
   the visuals clearer and less distracting... just have like 10% black gradient just to have
   the text visible"). Kept as a gradient rather than a single flat ~10% wash, not a flat tint
   uniform across the whole frame — the H1/CTAs sit on the left, so darkening only needs to be
   real there for contrast; a flat 10% over the entire video would either be too weak on the
   left (text) or needlessly dim the right (pure footage, no text) at the same time. 45% at the
   very left edge, fading to fully transparent by just past halfway, is the judgement call for
   "enough to keep text visible" — tune down further toward a flatter/lighter value if it still
   reads as too dark once reviewed against the real client footage. */
.hero-video-overlay{
  position:absolute;
  top:0; left:0; right:0; bottom:0;
  z-index:1;
  background:linear-gradient(90deg,
    rgba(0,0,0,.45) 0%,
    rgba(0,0,0,.18) 32%,
    rgba(0,0,0,0) 58%);
}
.hero-grid--video{ grid-template-columns:1fr; justify-content:start; }
.hero-grid--video .hero-copy{
  max-width:620px;
  margin-left:0; margin-right:auto; /* pin to the left, regardless of the grid column's own width */
  padding:108px 0 44px; /* clears the sticky header at the top, breathing room at the bottom —
                            lives here instead of on .hero--video, see note above. Trimmed down
                            from 132px/60px alongside the shorter .hero--video min-height. */
}

.hero--video h1{ color:var(--white); }
.hero--video .lede{ color:rgba(255,255,255,.88); }

.stat-bar--on-video{
  color:var(--white);
  border-top-color:rgba(255,255,255,.28);
}
.state-list--on-video{ color:rgba(255,255,255,.75); }

/* Hero data boxes — UNUSED now, per direct client feedback ("remove the three statistics
   cards... move the impact statistics below the hero/video section as a separate content
   block"). Left in place, unused, same "leave dead code, keep the history" convention as
   elsewhere in this file — the 3 numbers themselves moved to #hero-metrics below (a new
   section, un-boxed there per the client's own follow-up wording: "we don't need to put them
   in boxes, they can be normally placed"), not deleted, just relocated and restyled. */
.hero-stat-boxes{
  display:flex; flex-wrap:wrap; gap:14px;
}
.hero-stat-box{
  background:rgba(255,255,255,.08);
  border:1px solid rgba(255,255,255,.22);
  border-radius:16px;
  padding:16px 22px;
  min-width:120px;
  backdrop-filter:blur(6px);
}
.hero-stat-box .num{
  font-family:var(--font-head); font-weight:800;
  font-size:clamp(26px, 2.6vw, 34px); color:var(--white);
  font-variant-numeric:tabular-nums;
  line-height:1.05;
}
.hero-stat-box .lbl{
  font-size:12.5px; color:rgba(255,255,255,.75);
  margin-top:4px;
}

@media (max-width:640px){
  .hero--video{ min-height:auto; }
  .hero-grid--video .hero-copy{ padding:112px 0 48px; }
  .hero-stat-box{ padding:14px 18px; min-width:104px; }
}

/* ==========================================================================
   Hero metrics — small horizontal section between Home and About GAVP
   ========================================================================== */
/* New section per direct client feedback — see the HTML comment on #hero-metrics for the full
   brief. "Small horizontal section" means short, not the base .section's min-height:100vh
   floor (same min-height:auto treatment, and the same .section#id{...} override pattern for
   reliably beating the base .section rule at equal class-selector specificity, as
   #challenge/#resources elsewhere in this file). */
/* Padding tightened (was clamp(56px,8vw,96px)) — per direct feedback that this whole section
   "has become too long and big," alongside the font-size reductions and the graphic swap below. */
.section#hero-metrics{ min-height:auto; padding:clamp(36px, 5vw, 60px) 0; }
/* Static/own background, deliberately taken OUT of the page-wide crossfade system — per direct
   feedback, this early run of sections (hero video → hero-metrics → About) was fading through
   too many colour changes in too short a scroll distance (white → light-blue → white → dark, all
   within the first couple of screens). #hero-metrics now paints its own opaque colour directly
   (same "own opaque background, no data-bg-theme" pattern #impact-stories uses further down the
   page) instead of asking the shared .page-backdrop to crossfade to "tint" and back to "white"
   for About right after it — see the removed data-bg-theme="tint" attribute in index.html. The
   .page-backdrop itself never leaves "white" until #challenge, so About is white from the very
   first frame, with no fade-in required to get there. */
.section#hero-metrics{ background-color:var(--blue-100); position:relative; overflow:hidden; }
/* Rebuilt per a direct ClimateWorks Foundation reference: statement + tagline + stat row all
   stacked in one left column, a decorative shape composition on the right — "design on one
   side and the text and the numbers on the other side." Was a single side-by-side row
   (statement left, numbers right) before that — see CLAUDE.md "Hero metrics section" for the
   full history of this section's layout. */
.hero-metrics-layout{
  display:flex; align-items:center; justify-content:space-between;
  gap:clamp(36px, 6vw, 72px);
  flex-wrap:wrap;
}
.hero-metrics-content{ flex:1 1 420px; max-width:600px; }
/* Font sizes trimmed down a step (statement: 22-32px → 18-25px; tagline margin halved; numbers:
   28-38px → 22-30px) — per direct feedback the section "has become too long and big," so its
   text now takes noticeably less vertical room without dropping any content. */
.hero-metrics-statement{
  font-family:var(--font-head); font-weight:700;
  font-size:clamp(18px, 2vw, 25px); line-height:1.35;
  color:var(--blue-900);
  text-align:left;
  margin:0 0 12px;
}
.hero-metrics-tagline{
  font-size:14px; color:var(--ink-600); margin:0 0 20px;
}
/* Small round separators between the four concepts — was plain "|" pipe characters, replaced
   per direct feedback for a softer, more deliberate-looking divider. */
.hero-metrics-tagline .dot{ color:var(--orange-text); opacity:.8; margin:0 2px; font-size:11px; vertical-align:middle; }
.hero-metrics-row{
  display:flex; flex-wrap:wrap;
  gap:clamp(24px, 3.5vw, 40px);
  text-align:left;
}
/* Clean vertical-line separators between the three stats, per direct feedback ("replace the
   small dots between the hero statistics with clean separator lines") — matches the sitewide
   "no dotted separators, use plain lines" direction (see "Dotted separators removed sitewide"
   in CLAUDE.md). A thin line rather than a dot/bullet glyph; skipped on the first item since
   there's nothing to its left to separate from. */
.hero-metric:not(:first-child){
  padding-left:clamp(20px, 2.6vw, 32px);
  border-left:1px solid rgba(10, 61, 124, .16);
}
.hero-metric .num{
  font-family:var(--font-head); font-weight:800;
  font-size:clamp(25px, 2.8vw, 34px); color:var(--blue-900);
  font-variant-numeric:tabular-nums;
  line-height:1.05;
}
.hero-metric .lbl{ font-size:13px; color:var(--ink-600); margin-top:6px; }

/* Full-bleed decorative wave — replaced the earlier boxed rounded-corner gradient panel
   entirely, per direct reference image, rather than iterating on the box further. A direct
   child of .section (see the HTML comment on #hero-metrics) so right:0 anchors to the actual
   browser edge, not the 1240px-capped .container — that's what keeps this pinned to the right
   side of the screen at any monitor width, wide or narrow, instead of centring inward or
   stretching oddly on an ultra-wide display. Reuses the exact same `#flow-lines-seg` symbol
   every other `.line-ornament` instance on the page draws from (see "Per-section decorative
   line art" below) — just cropped to a taller/wider window, rendered at its natural blue
   gradient colour (no hue-shift filter, no low-opacity fade — the reference wants it vivid,
   not a faint background texture), and given real width so it reads as the section's own
   design element rather than a subtle accent. `.hero-metrics-graphic-logo` (a dead-code
   wordmark experiment from the old boxed-panel era) is removed outright along with the panel
   it belonged to — a short-lived, fully-superseded attempt, not worth preserving as history
   the way longer-lived components are elsewhere in this file. */
.hero-metrics-graphic{
  position:absolute;
  top:0; right:0; bottom:0;
  width:min(58vw, 1040px);
  z-index:0;
  pointer-events:none;
  /* Nudges the whole wave down and further right within its own box, per direct feedback —
     a plain transform (rather than touching top/right, which would also reshape the
     preserveAspectRatio "slice" crop) so the wave itself just shifts position without
     changing which portion of the source art is framed. */
  transform:translate(6%, 16%);
}
.hero-metrics-wave{
  width:100%; height:100%;
  display:block;
  /* Fades in from the left edge so it blends into the plain section background behind the
     text column rather than cutting off hard — the reference shows the lines emerging out of
     nothing on the left, not a rectangular clip. */
  -webkit-mask-image:linear-gradient(to right, transparent 0%, black 24%);
  mask-image:linear-gradient(to right, transparent 0%, black 24%);
}
.hero-metrics-content{ position:relative; z-index:1; }
@media (max-width:900px){ .hero-metrics-graphic{ width:80vw; opacity:.5; } }
@media (max-width:640px){ .hero-metrics-graphic{ display:none; } }

@media (max-width:760px){
  .hero-metrics-row{ width:100%; justify-content:space-between; gap:20px; }
}

/* ==========================================================================
   Decorative line art — per-section, not page-spanning.
   Client-supplied "bg lines" vector (assets/bg lines.ai, a PDF-compatible AI export),
   converted once via pymupdf into 42 gradient-coloured paths on a 4000×2000 canvas.
   A representative subset (11 paths) lives once as a <symbol id="flow-lines-seg"> right
   after <body>; each section below just <use>s it with a different viewBox "crop" window
   and CSS position, so the same source art reads a little differently each time it
   appears instead of looking like one repeated sticker.
   ========================================================================== */

.line-ornament{
  position:absolute;
  width:70%;
  height:60%;
  z-index:1; /* above the section's own background-color, below .container (z-index:2) */
  overflow:hidden;
  pointer-events:none;
  opacity:.1; /* low on purpose — this sits behind real content, including headline text,
                 in a couple of sections, and must never compete with it for attention */
  /* mostly horizontal, leaning gently left-to-right-and-down, per direction */
  transform:rotate(7deg);
  /* blue by default; shifts toward orange as the page is scrolled — see initLineHueShift()
     in js/main.js, which drives --line-hue on the root element */
  filter:hue-rotate(var(--line-hue, 0deg));
  transition:filter .2s linear;
}
.line-ornament use{ width:100%; height:100%; }

.line-ornament--upper{ top:-6%; right:-6%; }
.line-ornament--lower{ bottom:-8%; left:-6%; transform:rotate(5deg); }

@media (max-width:760px){
  .line-ornament{ width:95%; height:42%; opacity:.08; }
}

@media (prefers-reduced-motion: reduce){
  .line-ornament{ transition:none; }
}

/* ==========================================================================
   Generic section spacing
   ========================================================================== */

.section{
  padding:var(--section-y) 0;
  position:relative;
  /* clip-path, not overflow:hidden — overflow:hidden establishes a "scroll container" for
     CSS purposes even though this section never actually scrolls independently, which breaks
     position:sticky for any descendant (any non-visible overflow on an ancestor becomes a
     sticky element's containing block for stickiness purposes). Nothing currently inside
     .section relies on sticky, but this bit us once already during development, so keep using
     clip-path — it clips overflowing decorative children (.line-ornament, .chapter-orb)
     identically to overflow:hidden without that trap, in case a future sticky child is added. */
  clip-path:inset(0);
  background-color:var(--white);
  transition:background-color 1.1s ease, color 1.1s ease;
  /* near-full-screen sections — each colour gets to properly fill the viewport before the
     next one fades in, which is what makes the hand-off actually read as dramatic rather
     than a quick flash. min-height (not height) so content-heavy sections (Challenge,
     Partners) are still free to grow taller than the viewport. */
  min-height:100vh;
  display:flex;
  align-items:center;
}
.section > .container{ width:100%; }
@media (max-width:640px){
  /* full-screen sections feel like padding on tall mobile content — ease off there */
  .section{ min-height:auto; }
}
/* #resources (heading + brochure card, merged into one plain section once its curtain-lift
   into Partners was removed — see CLAUDE.md "Current status") was left at the base .section's
   min-height:100vh + align-items:center, which vertically centred its fairly short content
   (one heading, one card) inside a full-viewport box — reported directly as "a lot of gap"
   after the "Explore the GAVP vision" heading. Not a chapter that needs to fill a screen the
   way Challenge does, so it drops the vh floor entirely and just takes its natural content
   height plus normal section padding — same fix, same reasoning as #challenge below. */
.section#resources{ min-height:auto; }
/* How GAVP Works now uses `.how-gavp` above as one naturally-tall chapter; the previous
   split-section stitching rules were removed with the old architecture. */

/* About, Partners, Case Studies and Contact all get the same min-height:auto treatment already
   established for #resources/#challenge/#hero-metrics above — per direct
   feedback about large-monitor gaps, called out specifically at the About→Goal, Partners→Case
   Studies and Resources→Contact boundaries. Each of these sections' content is comfortably
   shorter than 100vh on a large/tall monitor, so the base .section's min-height:100vh floor +
   align-items:center was centring that content inside a mostly-empty full-viewport box — on
   top of the section-to-section padding, that's what read as "very far apart." Harmless where
   a section's own content already exceeds 100vh (Partners, most of the time) — min-height:auto
   only removes the floor, it doesn't shrink real content. */
.section#about, .section#partners, .section#case-studies, .section#contact{ min-height:auto; }
/* #challenge specifically (not .section-dark generally — Partners still wants the full-vh
   floor, its content comfortably fills it): with the state-mini-list removed in favour of
   the on-demand hover .state-detail-panel, Challenge's own content (heading, statement, map)
   got noticeably shorter, so the base .section's min-height:100vh + align-items:center left
   real dead space centered above AND below it before the Health/Nutrition/Education row even
   began (that row is a separate pinned curtain-lift screen after this one — see "Curtain-lift
   transition" — so two stacked forced-full-viewport screens compounded into one large visible
   gap). Dropping the vh floor here lets the section hug its actual content instead, so the
   icon row (now top-aligned itself — see .curtain-current) follows the map closely. */
.section#challenge{ min-height:auto; padding-bottom:clamp(28px, 4vw, 48px); }
/* Its own padding-bottom is trimmed too (from the base .section's shared var(--section-y),
   64–120px) — that stacked directly on top of .curtain-current's padding-top, and after
   tightening the latter the section's own trailing padding was still enough on its own to
   read as a leftover gap. Left with enough breathing room to not butt the map straight
   against the icon row with zero seam, just no longer a full section-y's worth. */
/* Sections themselves are transparent — the coloured surface is a single fixed full-page
   backdrop (.page-backdrop, defined with the rest of the top-level layout below) that sits
   behind everything and changes colour as the user scrolls, via initPageBackdrop() in
   js/main.js. This replaces two earlier per-section approaches (a .bg-active fade on
   .section-tint, and a scroll-scrubbed color-mix() dissolve on .section-dark) — both were
   real, working effects, but both were still fundamentally a *box* changing colour, so the
   boundary between one section's box and the next was always a visible edge. A single
   page-wide backdrop has no such edge: the whole viewport is always one colour, and text
   just sits on top of whatever that colour currently is. See CLAUDE.md. */
.section-white{ background-color:transparent; }
.section-tint{ background-color:transparent; }
html.no-js .section-tint{ background-color:var(--blue-100); } /* no JS → no backdrop colour
  detection at all, so each section must paint its own resting colour again */
@media (prefers-reduced-motion: reduce){
  .section-tint{ background-color:var(--blue-100); }
}

.section-dark{
  background-color:transparent;
  color:var(--white);
}

/* ==========================================================================
   Challenge → How GAVP transition surfaces

   Normal sections use the shared fixed page backdrop and are transparent.
   These two overlapping transition sections must instead paint their own
   opaque surfaces so the outgoing panel cannot show through the incoming
   How GAVP Works chapter.
   ========================================================================== */

.curtain-transition > .curtain-current{
  background-color:var(--blue-900);
}

.curtain-transition > .how-gavp{
  background-color:var(--blue-100);
}

html.no-js .section-dark{ background-color:var(--blue-900); }
@media (prefers-reduced-motion: reduce){
  .section-dark{ background-color:var(--blue-900); }
}
.section-dark h2{ color:var(--white); }
.section-dark .lede{ color:rgba(255,255,255,.82); }
.section-dark .eyebrow{ color:var(--orange-500); } /* verified 4.58:1 on blue-900 */
.section-dark .form-field span{ color:rgba(255,255,255,.85); }
.section-dark .form-field input, .section-dark .form-field textarea{
  background:rgba(255,255,255,.08);
  border-color:rgba(255,255,255,.28);
  color:var(--white);
}
.section-dark .form-field input::placeholder, .section-dark .form-field textarea::placeholder{
  color:rgba(255,255,255,.65); /* verified ~4.5:1 against the input's own translucent fill */
}
.section-dark .form-field input:focus-visible, .section-dark .form-field textarea:focus-visible{
  outline-color:var(--orange-500); border-color:var(--orange-500);
}
.section-dark .form-check{ color:rgba(255,255,255,.75); }

/* ==========================================================================
   .section-dark — extended component coverage.
   Challenge and Partners were converted from .section-white to .section-dark
   as part of the premium scroll/chapter brief (three dark-navy chapters:
   Challenge, Partners, Contact — see CLAUDE.md). Every component that appears
   inside those two sections needs its light-surface colours inverted here;
   components that only ever appear on light sections are untouched.
   ========================================================================== */
.section-dark h3, .section-dark h4{ color:var(--white); }
.section-dark .eyebrow.blue{ color:var(--orange-500); }
.section-dark .hl{ color:var(--orange-500); }
.section-dark .partner-name{ color:var(--white); }

.section-dark .icon-card{ background:rgba(255,255,255,.06); border-color:rgba(255,255,255,.14); }
.section-dark .icon-tile{ background:rgba(255,255,255,.14); }
.section-dark .icon-tile svg{ stroke:var(--white); }
.section-dark .icon-card h3{ color:var(--white); } /* higher specificity than .icon-card h3's own
  color:var(--ink-900) — without this, source order made the component rule win and the heading
  rendered dark-navy-on-navy, functionally invisible */
.section-dark .icon-card p{ color:rgba(255,255,255,.7); }

.section-dark .stat-trio .num,
.section-dark .stat-row .stat .num,
.section-dark .mdp-stat-grid .num{ color:var(--white); } /* .stat-row .stat .num matched, at equal
  specificity to the plain .stat-row .num guess, so the extra .stat class here is deliberate —
  it must out-specify the component's own color:var(--blue-900) rule regardless of source order,
  or the numerals render navy-on-navy and disappear (this happened once already, see verify pass) */
/* Per direct client feedback ("see if we can make the numbers pop a bit — both the numbers
   and the text are the same colour") — overrides the plain-white rule above specifically for
   the MDP grid's numerals with the brand's own "orange highlights statistics" rule (verified
   4.58:1 on --blue-900, same safe shade used for .eyebrow/.hl elsewhere in dark sections), so
   the big numbers now read as a distinct accent colour rather than blending into the labels. */
.section-dark .mdp-stat-grid .num{ color:var(--orange-500); }
.section-dark .stat-trio .lbl,
.section-dark .stat-row .lbl,
.section-dark .mdp-stat-grid .lbl{ color:rgba(255,255,255,.65); }
.section-dark .stat-trio .stat-item + .stat-item{ border-left-color:var(--orange-500); }

.section-dark .case-mini{ background:rgba(255,255,255,.06); }
.section-dark .case-mini p{ color:rgba(255,255,255,.72); }
.section-dark .case-mini .eyebrow{ color:var(--orange-500); }

.section-dark .logo-tile{ background:rgba(255,255,255,.08); border-color:rgba(255,255,255,.28); color:rgba(255,255,255,.8); }
.section-dark .eco-chip{ background:rgba(255,255,255,.08); border-color:rgba(255,255,255,.22); color:var(--white); }

/* the shared "bg lines" ornament reads as near-invisible dark-on-dark at its normal
   authored colours (a blue/navy gradient) — lift it with brightness so it still reads
   as a faint pale line on the navy surface, same hue-shift-on-scroll behaviour as elsewhere */
.section-dark .line-ornament{ opacity:.16; filter:brightness(2.4) hue-rotate(var(--line-hue, 0deg)); }
@media (max-width:760px){ .section-dark .line-ornament{ opacity:.12; } }

/* Challenge map, on the now-dark surface: the base outline becomes a faint ghost, the
   5 focus states become pale (rather than brand-blue-on-navy, which was too low-contrast),
   and labels/leader-lines invert to stay legible. */
.section-dark .challenge-map-svg .cls-1{ fill:rgba(255,255,255,.12); }
.section-dark .challenge-map-svg #INAS, .section-dark .challenge-map-svg #INBR,
.section-dark .challenge-map-svg #INCT, .section-dark .challenge-map-svg #INJH,
.section-dark .challenge-map-svg #INOR{ fill:var(--blue-100); }
.section-dark .challenge-map-svg #INAS:hover, .section-dark .challenge-map-svg #INAS:focus-visible,
.section-dark .challenge-map-svg #INBR:hover, .section-dark .challenge-map-svg #INBR:focus-visible,
.section-dark .challenge-map-svg #INCT:hover, .section-dark .challenge-map-svg #INCT:focus-visible,
.section-dark .challenge-map-svg #INJH:hover, .section-dark .challenge-map-svg #INJH:focus-visible,
.section-dark .challenge-map-svg #INOR:hover, .section-dark .challenge-map-svg #INOR:focus-visible{ fill:var(--orange-500); }
.section-dark .state-detail{ color:rgba(255,255,255,.75); border-left-color:var(--orange-500); }
.section-dark .state-detail strong{ color:var(--white); }
.section-dark .state-detail--default{ color:rgba(255,255,255,.5); }

/* ==========================================================================
   Sync dark-chapter TEXT colour to the same signal that drives the shared backdrop.
   Every rule above is unconditional — .section-dark's headings/eyebrows/etc are always
   white/orange, completely independent of how far the scroll-driven backdrop has actually
   progressed. That's a real structural gap, not just a timing tweak: text and background are
   two separate systems and can drift apart no matter how well the trigger point is tuned —
   reported directly as headings already white while the backdrop underneath was still light
   blue. initPageBackdrop() in js/main.js mirrors the active backdrop
   theme onto html.theme-dark, and every selector below counters one rule above back to
   its ordinary light-surface colour until that class appears — so text and background flip on
   the literal same line of code, not just similar timing. Deliberately excludes no-js and
   reduced-motion (via requiring html.js, already the no-js→js swap marker) — both skip the
   scroll-linked reveal entirely and must keep showing the correct settled (dark) colours
   immediately, per the .section-dark fallback rules already above. Scoped to the elements
   that actually appear early enough in a dark chapter to matter (heading/eyebrow/lede and the
   components right below them) — the India map and Contact's form fields sit far enough into
   their sections that the backdrop reliably catches up before they're on screen, so they're
   intentionally left on the unconditional dark styling above rather than duplicated here.

   Wrapped in `(prefers-reduced-motion: no-preference)` — NOT applied to reduced-motion users.
   `html.theme-dark` is set by the scroll-position-driven initPageBackdrop() controller, so a reduced-motion user who hasn't scrolled yet would
   otherwise see these light-fallback colours applied to content that's already sitting on a
   dark background (nothing scroll-linked ever ran to flip .theme-dark on) — exactly the low-
   contrast "washed out" look this whole block exists to prevent in the first place. Reduced-
   motion should show the correct, final, settled state immediately with no scroll dependency
   at all, same principle as every other reveal in this file — so for those users the plain,
   always-on .section-dark rules above are the only ones that should ever apply. */
@media (prefers-reduced-motion: no-preference){
html.js:not(.theme-dark) .section-dark h2,
html.js:not(.theme-dark) .section-dark h3,
html.js:not(.theme-dark) .section-dark h4,
html.js:not(.theme-dark) .section-dark .partner-name{ color:var(--blue-700); }
html.js:not(.theme-dark) .section-dark .lede{ color:var(--ink-600); }
html.js:not(.theme-dark) .section-dark .eyebrow{ color:var(--orange-text); }
html.js:not(.theme-dark) .section-dark .eyebrow.blue{ color:var(--blue-600); }
html.js:not(.theme-dark) .section-dark .hl{ color:var(--orange-text); }
html.js:not(.theme-dark) .section-dark .icon-card{ background:var(--white); border-color:rgba(18,80,158,.1); }
html.js:not(.theme-dark) .section-dark .icon-tile{ background:var(--blue-100); }
html.js:not(.theme-dark) .section-dark .icon-tile svg{ stroke:var(--blue-700); }
html.js:not(.theme-dark) .section-dark .icon-card h3{ color:var(--ink-900); }
html.js:not(.theme-dark) .section-dark .icon-card p{ color:var(--ink-600); }
html.js:not(.theme-dark) .section-dark .state-detail{ color:var(--ink-600); border-left-color:var(--orange-600); }
html.js:not(.theme-dark) .section-dark .state-detail strong{ color:var(--blue-700); }
html.js:not(.theme-dark) .section-dark .stat-trio .num,
html.js:not(.theme-dark) .section-dark .stat-row .stat .num,
html.js:not(.theme-dark) .section-dark .mdp-stat-grid .num{ color:var(--blue-900); }
html.js:not(.theme-dark) .section-dark .stat-trio .lbl,
html.js:not(.theme-dark) .section-dark .stat-row .lbl,
html.js:not(.theme-dark) .section-dark .mdp-stat-grid .lbl{ color:var(--ink-600); }
html.js:not(.theme-dark) .section-dark .stat-trio .stat-item + .stat-item{ border-left-color:var(--orange-600); }
html.js:not(.theme-dark) .section-dark .case-mini{ background:var(--blue-50); }
html.js:not(.theme-dark) .section-dark .case-mini p{ color:var(--ink-600); }
html.js:not(.theme-dark) .section-dark .case-mini .eyebrow{ color:var(--orange-text); }
html.js:not(.theme-dark) .section-dark .logo-tile{ background:var(--blue-50); border-color:rgba(18,80,158,.25); color:var(--ink-600); }
html.js:not(.theme-dark) .section-dark .eco-chip{ background:var(--white); border-color:rgba(18,80,158,.15); color:var(--blue-700); }
html.js:not(.theme-dark) .section-dark .form-field span{ color:var(--blue-700); }
html.js:not(.theme-dark) .section-dark .form-field input,
html.js:not(.theme-dark) .section-dark .form-field textarea{ background:var(--white); border-color:rgba(18,80,158,.18); color:var(--ink-900); }
html.js:not(.theme-dark) .section-dark .form-check{ color:var(--ink-600); }
/* every colour swap above fades rather than snaps */
html.js .section-dark h2, html.js .section-dark h3, html.js .section-dark h4,
html.js .section-dark .partner-name, html.js .section-dark .lede, html.js .section-dark .eyebrow,
html.js .section-dark .hl, html.js .section-dark .icon-card h3, html.js .section-dark .icon-card p,
html.js .section-dark .state-detail, html.js .section-dark .state-detail strong,
html.js .section-dark .stat-trio .num, html.js .section-dark .stat-row .stat .num,
html.js .section-dark .stat-trio .lbl, html.js .section-dark .stat-row .lbl,
html.js .section-dark .mdp-stat-grid .num, html.js .section-dark .mdp-stat-grid .lbl,
html.js .section-dark .case-mini p, html.js .section-dark .case-mini .eyebrow,
html.js .section-dark .logo-tile, html.js .section-dark .eco-chip,
html.js .section-dark .form-field span, html.js .section-dark .form-check{
  transition:color .4s ease;
}
} /* end @media (prefers-reduced-motion: no-preference) */

/* ==========================================================================
   Chapter orbs — restrained decorative circular outlines that give each dark
   chapter a bit of depth/composition, echoing the reference video's oversized
   transition shapes without literally recreating a growing-circle mask (kept
   deliberately simple: a one-shot scale+opacity reveal via the existing
   .reveal machinery, not a continuous scroll-scrubbed transform). Composition
   (which corner, how many) varies per chapter so the three dark sections
   don't read as identical — see index.html.
   ========================================================================== */
.chapter-orb{
  position:absolute;
  border-radius:50%;
  pointer-events:none;
  z-index:0;
  opacity:0;
  transform:scale(.9);
  border:1px solid rgba(255,255,255,.16);
  transition:opacity var(--duration-slow) var(--ease-premium), transform var(--duration-slow) var(--ease-premium);
}
.chapter-orb.in-view{ opacity:1; transform:scale(1); }
.chapter-orb--a{ width:min(52vw,640px); height:min(52vw,640px); top:-16%; right:-14%; }
.chapter-orb--b{ width:min(30vw,380px); height:min(30vw,380px); bottom:-10%; left:-8%; }
.chapter-orb--c{ width:min(20vw,240px); height:min(20vw,240px); bottom:10%; right:8%; }
@media (max-width:760px){ .chapter-orb{ display:none; } }

/* ==========================================================================
   Signature sentence reveal — "The Challenge" opening statement.
   First line establishes immediately in white; the second line's words start
   faint/muted and resolve one by one into the accent colour as the section
   scrolls past — an opacity/colour reveal driven by initSystemicReveal() in
   js/main.js (NOT a typewriter effect: every word is already in the DOM,
   already readable, only its opacity/colour animates). The full sentence is
   exposed to assistive tech via aria-label on the wrapper; both inner <p>s
   are aria-hidden to avoid double-reading it.
   ========================================================================== */
.systemic-statement{
  max-width:900px; margin:0 auto 44px; text-align:center;
  position:relative; z-index:2;
}
.systemic-statement__context{
  font-family:var(--font-head); font-weight:700;
  font-size:clamp(21px,2.6vw,30px);
  color:var(--white);
  margin-bottom:10px;
  line-height:1.3;
  transition:color .4s ease;
}
/* Same theme-dark sync as the rest of .section-dark's text (see the block further down) —
   this element isn't itself inside a .section-dark selector (it's its own dedicated class),
   so it was missed the first time and kept rendering white before the backdrop caught up:
   reported directly as "Health, nutrition and education are deeply connected." staying white
   on the still-light background. */
@media (prefers-reduced-motion: no-preference){
  html.js:not(.theme-dark) .systemic-statement__context{ color:var(--blue-700); }
}
.systemic-statement__reveal{
  font-family:var(--font-head); font-weight:700;
  font-size:clamp(21px,2.6vw,30px);
  line-height:1.3;
}
.systemic-statement__reveal span{
  display:inline-block;
  opacity:.16;
  color:rgba(255,255,255,.4);
  transform:translateY(0);
  transition:opacity var(--duration-medium) var(--ease-premium),
             color var(--duration-medium) var(--ease-premium),
             transform var(--duration-medium) var(--ease-premium);
}
.systemic-statement__reveal span.is-lit{
  opacity:1;
  color:var(--orange-500);
  transform:translateY(-3px);
}
/* same reasoning as .systemic-statement__context above — the muted "not yet lit" colour is
   white-ish, which is invisible-to-illegible on the still-light background before the theme
   flips. Only the muted (not-lit) state needs the swap; .is-lit's orange stays legible on
   either light or dark surfaces already, so it's untouched. */
@media (prefers-reduced-motion: no-preference){
  html.js:not(.theme-dark) .systemic-statement__reveal span{ color:rgba(18,80,158,.35); }
}
@media (prefers-reduced-motion: reduce){
  .systemic-statement__reveal span{
    opacity:1 !important; color:var(--orange-500) !important; transform:none !important;
  }
}

.split{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:64px;
  align-items:center;
  position:relative;
  z-index:2;
}
.split.reverse .split-media{ order:-1; }
/* Anchor-partner instance (Partners section): with align-items:center, the count-up stats in
   the left column change width digit-by-digit as they animate (0 -> 18/5,000/27/143M), which
   can nudge .stat-row's wrapped height by a line and re-center the whole grid row — reported
   as the photo on the right "moving a little" while the numbers count up. Top-aligning this
   instance removes the dependency on left-column height entirely, so the image never shifts
   regardless of how the counters reflow. */
.split.split--top{ align-items:flex-start; }

@media (max-width:920px){
  .hero-grid{ grid-template-columns:1fr; }
  .hero-media{ order:-1; }
  .split{ grid-template-columns:1fr; gap:36px; }
  .split.reverse .split-media{ order:0; }
}

/* video block */
.video-frame{ position:relative; }
.play-button{
  position:absolute; top:50%; left:50%;
  transform:translate(-50%,-50%);
  width:74px; height:74px;
  border-radius:50%;
  background:rgba(255,255,255,.94);
  border:2px solid var(--orange-600);
  display:flex; align-items:center; justify-content:center;
  box-shadow:0 12px 30px -10px rgba(10,61,124,.45);
  transition:transform .18s ease;
  z-index:3;
}
.play-button:hover{ transform:translate(-50%,-50%) scale(1.06); }
.play-button svg{ width:22px; height:22px; margin-left:3px; }

/* ==========================================================================
   Ambition / map section
   ========================================================================== */

.ambition-grid{
  display:grid;
  grid-template-columns:1.1fr 0.9fr;
  gap:56px;
  align-items:start;
  position:relative; z-index:2;
}
@media (max-width:920px){ .ambition-grid{ grid-template-columns:1fr; } }

.map-wrap{
  position:relative;
  background:var(--white);
  border-radius:32px;
  padding:20px;
  border:1px solid rgba(18,80,158,.1);
}
.map-link{ display:block; }
.map-svg{ width:100%; height:auto; display:block; }

/* base India outline — matches --blue-100 already via the source file's own .cls-1 rule;
   we only need a thin separating stroke between states for legibility. */
.map-svg path{ stroke:#fff; stroke-width:1.3; stroke-linejoin:round; }

/* the 5 GAVP focus states, highlighted in the deep brand blue at rest, orange on individual
   hover. transform-box/-origin let the scale-up read as a smooth "swipe" rather than a snap. */
.map-svg #INAS, .map-svg #INBR, .map-svg #INCT, .map-svg #INJH, .map-svg #INOR{
  fill:var(--blue-900);
  transform-box:fill-box;
  transform-origin:center;
  transition:fill .35s ease, transform .35s ease, opacity .35s ease;
  cursor:pointer;
}
.map-svg #INAS:hover, .map-svg #INBR:hover, .map-svg #INCT:hover,
.map-svg #INJH:hover, .map-svg #INOR:hover{
  fill:var(--orange-600);
  transform:scale(1.02);
}

/* dim the other four focus states while one is hovered, so attention stays on it */
.map-svg:has(#INBR:hover, #INCT:hover, #INJH:hover, #INOR:hover) #INAS{ opacity:.45; }
.map-svg:has(#INAS:hover, #INCT:hover, #INJH:hover, #INOR:hover) #INBR{ opacity:.45; }
.map-svg:has(#INAS:hover, #INBR:hover, #INJH:hover, #INOR:hover) #INCT{ opacity:.45; }
.map-svg:has(#INAS:hover, #INBR:hover, #INCT:hover, #INOR:hover) #INJH{ opacity:.45; }
.map-svg:has(#INAS:hover, #INBR:hover, #INCT:hover, #INJH:hover) #INOR{ opacity:.45; }

/* the source file's own marker groups — not needed on top of our leader-line overlay */
.map-svg #points, .map-svg #label_points{ display:none; }

/* leader-line + label per state — hidden until that state is hovered, for a clean rest state */
.map-leader-group{
  opacity:0;
  transform:translateY(6px);
  transition:opacity .25s ease, transform .25s ease;
  pointer-events:none;
}
.map-svg:has(#INAS:hover) #leader-INAS,
.map-svg:has(#INBR:hover) #leader-INBR,
.map-svg:has(#INCT:hover) #leader-INCT,
.map-svg:has(#INJH:hover) #leader-INJH,
.map-svg:has(#INOR:hover) #leader-INOR{
  opacity:1;
  transform:translateY(0);
}

.map-leader{ stroke:var(--orange-600); stroke-width:2.6; }
.map-dot{ fill:var(--orange-600); stroke:#fff; stroke-width:1.5; }
.map-label{
  font-family:var(--font-body);
  font-weight:600;
  font-size:25px;
  fill:var(--blue-900);
}

.map-hint{
  margin:14px 0 0;
  text-align:center;
  font-size:12.5px;
  color:var(--ink-600);
}

.icon-cards{ display:flex; flex-direction:column; gap:18px; }
.icon-card{
  display:flex; gap:16px; align-items:flex-start;
  background:var(--white);
  border:1px solid rgba(18,80,158,.1);
  border-radius:18px;
  padding:18px 20px;
}
/* Heading-level icon — deliberately bigger and more solid (filled tile, no border needed to
   read as "primary") than .step-icon below, which is the supporting/item-level treatment.
   The two were previously close enough in size (46px vs .step-icon's 52px) that .step-icon,
   used for the smaller sub-items underneath a .icon-tile heading, actually rendered LARGER
   than the heading icon above it — an inverted, confusing hierarchy, flagged directly
   ("heading icons and supporting-item icons should have different visual treatments so their
   hierarchy is clear"). Sized up here and .step-icon sized down below, so the heading icon is
   now unambiguously the larger, bolder one wherever the two appear together (e.g. .gcw-card-head
   vs .gcw-item, or .systems-card-icon vs the .systems-item icons within the same card). */
.icon-tile{
  width:50px; height:50px; border-radius:50%;
  background:var(--blue-100);
  display:flex; align-items:center; justify-content:center;
  flex:none;
}
/* `color:` added alongside the existing `stroke:` — the client-supplied replacement icons
   (Government/Community headings, etc.) are solid-fill outline glyphs using
   `fill="currentColor"` rather than the original hand-drawn `stroke`-based line icons, so they
   need `color` set explicitly wherever they land; `stroke` is left in place, untouched, for
   any icon that's still the original stroke-based style. */
.icon-tile svg{ width:30px; height:30px; stroke:var(--blue-700); color:var(--blue-700); }
.icon-card h3{ font-size:15.5px; margin-bottom:3px; color:var(--ink-900); }
.icon-card p{ font-size:13.5px; color:var(--ink-600); }

.ambition-stat{
  margin-top:26px;
  display:flex; align-items:baseline; gap:12px;
  flex-wrap:wrap;
}
.ambition-stat .num{
  font-family:var(--font-head); font-weight:800;
  font-size:30px; color:var(--blue-900);
}
.ambition-stat .lbl{ font-size:13.5px; color:var(--ink-600); }

/* ==========================================================================
   Logo grid
   ========================================================================== */

/* Small label + subtext directly above the logo marquee — sentence-case with a colon, not the
   uppercase .eyebrow treatment used elsewhere, since it reads as a plain label rather than a
   section kicker. */
.partners-logos-head{ text-align:center; max-width:640px; margin:0 auto; }
.partners-logos-head h3{ font-size:19px; margin-bottom:6px; }
/* .lede has its own max-width:56ch with no margin:auto, so without this override the
   paragraph's own box hugs the left edge of this already-centered wrapper instead of
   actually centering on the page — the text-align:center on the wrapper only centers text
   within that (left-anchored) box, not the box itself. */
.partners-logos-head .lede{ font-size:14.5px; margin-left:auto; margin-right:auto; }

.logo-tile{
  height:76px;
  width:170px;
  flex:0 0 auto;
  border-radius:14px;
  background:var(--blue-50);
  border:1px solid rgba(18,80,158,.14);
  display:flex; align-items:center; justify-content:center;
  padding:14px 20px;
  font-size:11px; font-weight:600; letter-spacing:.06em;
  color:var(--ink-600);
  text-transform:uppercase;
}
/* Real logo files (see the .logo-marquee HTML comment) — object-fit:contain so each logo's own
   aspect ratio is respected inside the fixed tile rather than being cropped or stretched. */
.logo-tile img{ max-width:100%; max-height:100%; width:auto; height:auto; object-fit:contain; }
.logo-tile--on-dark{
  background:rgba(255,255,255,.08);
  border-color:rgba(255,255,255,.28);
  color:rgba(255,255,255,.8);
}

/* Continuously-scrolling logo strip. The track holds the logo set twice back to back;
   animating exactly -50% loops it seamlessly (viewers never see a seam or reset jump). */
.logo-marquee{
  position:relative; z-index:2;
  overflow:hidden;
  margin:32px 0 30px;
  /* soft fade at both edges instead of an abrupt cut */
  -webkit-mask-image:linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  mask-image:linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.logo-marquee-track{
  display:flex;
  gap:16px;
  width:max-content;
  animation:logoMarquee 28s linear infinite;
}
.logo-marquee:hover .logo-marquee-track{ animation-play-state:paused; }
@keyframes logoMarquee{
  from{ transform:translateX(0); }
  to{ transform:translateX(calc(-50% - 8px)); } /* half the track (one set) + half the gap */
}

.logo-marquee--patch{
  /* breaks out of .container to the full viewport width, regardless of nesting —
     standard "full-bleed inside a centred layout" trick */
  width:100vw;
  position:relative;
  left:50%; right:50%;
  margin-left:-50vw; margin-right:-50vw;
  background:var(--blue-900);
  border-radius:0;
  padding:26px 0;
  /* edge-to-edge means there's no edge to soften — no fade here, unlike the base marquee */
  -webkit-mask-image:none;
  mask-image:none;
}
.logo-marquee--patch .logo-marquee-track{ padding:0 24px; }

@media (prefers-reduced-motion: reduce){
  .logo-marquee-track{ animation:none !important; transform:none !important; }
}

/* ==========================================================================
   Closing CTA
   ========================================================================== */

.closing{
  position:relative;
  overflow:hidden;
  /* placeholder photo reused from the "introducing the alliance" asset until a dedicated
     closing-CTA shot is supplied — see CLAUDE.md asset list. */
  background:var(--blue-900) url("assets/images/introducing-alliance.png") center/cover no-repeat;
  padding:80px var(--gutter) 92px;
  color:var(--white);
  isolation:isolate;
}
.closing::before{
  content:"";
  position:absolute; inset:0;
  background:linear-gradient(100deg, rgba(10,61,124,.96) 34%, rgba(10,61,124,.6) 78%);
  z-index:0;
}
.closing-inner{
  position:relative; z-index:2;
  max-width:640px;
}
.closing h2{ color:var(--white); font-size:clamp(28px,3.6vw,42px); margin-bottom:16px; }
.closing p{ color:rgba(255,255,255,.86); font-size:16px; margin-bottom:30px; max-width:52ch; }
.closing-ctas{ display:flex; gap:14px; flex-wrap:wrap; }

/* ==========================================================================
   Closing CTA card — Contact section. A boxed, rounded variant of the .closing pattern
   above (same copy, same .closing-ctas class for the button row) rather than the original's
   full-bleed background-image treatment: a contained dark-navy card with its own asymmetric
   corner radius, sitting on the page's ordinary light background, photo as a genuine side
   panel rather than a CSS background-image. See CLAUDE.md "Closing CTA card" for why this
   replaced the full-bleed dark chapter + enquiry form this section carried before.
   ========================================================================== */
.closing-card{
  background:var(--blue-900);
  /* Uniform on all 4 corners, per direct feedback — was 28px 56px 28px 28px (one blown-out
     top-right corner, matching the site's usual asymmetric-corner shape language elsewhere),
     but reported directly as reading like a mismatch/mistake on this specific card rather than
     a deliberate accent. .closing-card-media img carries no border-radius of its own (see the
     comment there) — it's masked entirely by this card's own overflow:hidden clip, so a single
     value here is all that's needed to keep the photo's corners in sync with the card's. */
  border-radius:28px;
  overflow:hidden;
  display:grid;
  grid-template-columns:1.1fr 1fr;
  align-items:stretch;
}
.closing-card-copy{
  padding:clamp(32px,4.5vw,56px);
  display:flex; flex-direction:column;
}
.closing-card-copy h2{
  color:var(--white); font-size:clamp(26px,3.2vw,38px);
  margin:14px 0 16px;
}
.closing-card-copy p{
  color:rgba(255,255,255,.85); font-size:15.5px; line-height:1.6;
  margin-bottom:28px; max-width:46ch;
}
/* aspect-ratio (not just min-height) is what actually controls this column's height — without
   it, a portrait source image (object-fit:cover, width/height:100%) has no definite height to
   fill, so the grid falls back to the image's own intrinsic aspect ratio to size the row, and
   the whole card ends up as tall as the photo "wants" to be regardless of how short the copy
   column's real content is. That's what made the card read as "very long" — reported directly
   — even though min-height:320px was already a comparatively modest floor. 3/2 (landscape,
   roughly half the height a 1200×1680 portrait crop would otherwise force at the same width)
   is what actually fixes it. */
.closing-card-media{ position:relative; aspect-ratio:3/2; min-height:240px; }
/* No border-radius on the img itself — .closing-card's own overflow:hidden already clips
   everything inside it (including this image) to the card's real per-corner shape
   (28px 56px 28px 28px). A separate, hand-matched radius here previously used 56px on the
   bottom-right corner (to echo the card's 56px top-right) but the card's own bottom-right is
   only 28px — the mismatch let the card's blue background show through as a small crescent
   at that one corner, reported directly as "a blue thing coming out" of the photo. Letting the
   parent's clip do the rounding removes the chance of the two ever drifting out of sync again. */
.closing-card-media img{
  width:100%; height:100%; object-fit:cover;
}
@media (max-width:760px){
  .closing-card{ grid-template-columns:1fr; border-radius:24px; }
  .closing-card-media{ order:-1; aspect-ratio:3/2; min-height:200px; }
}

/* Contact's own variant — copy (with a small image inset, not the full-column photo the
   base .closing-card uses) + a real form panel, per direct instruction. See the HTML comment
   on #contact for the full reasoning. */
.closing-card--form{ grid-template-columns:1fr 1fr; }
@media (max-width:760px){ .closing-card--form{ grid-template-columns:1fr; } }

.contact-info{
  margin-bottom:24px; padding-left:16px;
  border-left:2px solid var(--orange-500);
}
.contact-info p{ margin:0 0 4px; font-size:14px; color:rgba(255,255,255,.85); }
.contact-info a{ color:var(--white); text-decoration:none; }
.contact-info a:hover{ text-decoration:underline; }

/* Started as a small 220px-wide inset thumbnail, then briefly grew to fill the entire rest of
   the left column via flex:1 (stretching to match whatever height the form panel happened to
   need) — reported as too tall once the form column was this much shorter in comparison.
   Switched to aspect-ratio:1/1 instead: height is now set from the thumb's own (stable) width,
   about 20% shorter than the old flex-fill height at this column width, and it no longer
   depends on the sibling form column's height at all. The form panel's own rhythm (padding/
   gap/field size/textarea rows, below) was tightened to match, so the two columns land at
   close to the same total height instead of the copy column being visibly shorter. */
.closing-card-thumb{
  width:100%;
  aspect-ratio:1/1;
  border-radius:16px 16px 16px 40px;
  overflow:hidden;
}
.closing-card-thumb img{ width:100%; height:100%; object-fit:cover; display:block; }

.closing-card-form-panel{
  background:rgba(255,255,255,.04);
  border-left:1px solid rgba(255,255,255,.08);
  padding:clamp(20px, 3vw, 28px);
  display:flex; flex-direction:column; gap:10px;
}
@media (max-width:760px){ .closing-card-form-panel{ border-left:none; border-top:1px solid rgba(255,255,255,.08); } }
.closing-card-form-panel input,
.closing-card-form-panel select,
.closing-card-form-panel textarea{
  font-family:var(--font-body); font-size:14.5px;
  width:100%;
  background:rgba(255,255,255,.08);
  border:1px solid rgba(255,255,255,.22);
  border-radius:10px;
  padding:10px 14px;
  color:var(--white);
}
.closing-card-form-panel input::placeholder,
.closing-card-form-panel textarea::placeholder{ color:rgba(255,255,255,.55); }
.closing-card-form-panel select{ color:rgba(255,255,255,.75); }
.closing-card-form-panel select option{ color:var(--ink-900); }
.closing-card-form-panel textarea{ resize:vertical; }
.closing-card-form-panel input:focus-visible,
.closing-card-form-panel select:focus-visible,
.closing-card-form-panel textarea:focus-visible{
  outline:2px solid var(--orange-500); outline-offset:1px; border-color:var(--orange-500);
}
.closing-card-form-panel button{ margin-top:4px; align-self:flex-start; }

/* ==========================================================================
   Footer
   ========================================================================== */

.site-footer{
  background:var(--white);
  padding:40px var(--gutter) 30px;
  border-top:1px solid rgba(18,80,158,.08);
}
.footer-inner{
  max-width:var(--container);
  margin:0 auto;
  display:flex; justify-content:space-between; align-items:center;
  flex-wrap:wrap; gap:16px;
}
.footer-links{ display:flex; gap:20px; flex-wrap:wrap; }
.footer-links a{ font-size:13.5px; color:var(--ink-600); }
.footer-links a:hover{ color:var(--blue-700); }
.footer-copy{ font-size:12.5px; color:var(--ink-600); }

/* ==========================================================================
   Scroll reveal — headings and card groups fade/rise into place once, the
   first time they cross into view. Deliberately restrained: opacity + a
   modest 20px rise, not a slide-in-from-the-side flourish. .reveal-2/-3/-4
   add a stagger for elements meant to arrive as a related group (e.g. a row
   of cards) — put them on the individual items, not the row wrapper.
   ========================================================================== */

/* .reveal-2/-3/-4/-5's transition-delay is a real trap on any element that ALSO defines its own
   hover transitions (border-color/background-color/box-shadow/transform etc — see .engage-item,
   .case-stat, .pillar-card): `.reveal-N.in-view{ transition-delay:.1s }` is a bare longhand with
   higher specificity (two classes) than a single-class `.engage-item{ transition:... }` rule, so
   it wins and applies to EVERY transitioned property on that element, not just this rule's own
   opacity/transform — permanently, since .in-view is never removed once added. That silently
   made every reveal-3/-4/-5 card's hover feel laggy (.2s/.3s/.4s of dead air before anything
   visibly moved) while un-staggered siblings felt instant — reported directly on the "Six ways
   to engage" cards (3, 4, 5 laggy vs 1, 2, 6 fast). Fixed by not combining a numbered stagger
   class with a component that has its own hover transitions — see .engage-item/.case-stat/
   .pillar-card in index.html, none of which use reveal-2/-3/-4/-5 any more, only plain
   reveal--pop, so their scroll-in now arrives together rather than staggered — that's an
   acceptable trade for hover no longer being slowed down by leftover entrance-animation delay. */
.reveal{
  opacity:0; transform:translateY(20px);
  transition:opacity .65s cubic-bezier(.2,.7,.3,1), transform .65s cubic-bezier(.2,.7,.3,1);
}
.reveal.in-view{ opacity:1; transform:translateY(0); }
.reveal-2.in-view{ transition-delay:.1s; }
.reveal-3.in-view{ transition-delay:.2s; }
.reveal-4.in-view{ transition-delay:.3s; }
.reveal-5.in-view{ transition-delay:.4s; }

/* a livelier entrance for icon-led cards (e.g. the 4 capability steps) — rises AND grows
   into place with a slight overshoot, rather than the plain fade/rise used elsewhere */
.reveal--pop{
  opacity:0; transform:translateY(26px) scale(.88);
  transition:opacity .55s ease, transform .6s cubic-bezier(.34,1.56,.64,1);
}
.reveal--pop.in-view{ opacity:1; transform:translateY(0) scale(1); }

/* ==========================================================================
   Shared inline highlight (used inside headings/paragraphs across inner pages)
   ========================================================================== */

.hl{ color:var(--orange-text); }
h1 .hl, h2 .hl, h3 .hl{ color:var(--orange-text); }
p .hl, p .hl-blue{ font-weight:600; }
.hl-blue{ color:var(--blue-600); }

/* ==========================================================================
   About — hero: broad photo field with an overlapping white panel
   ========================================================================== */

.about-hero{ position:relative; overflow:hidden; }

.about-hero-media{
  position:relative;
  height:clamp(360px, 46vw, 540px);
  overflow:hidden;
}
.about-hero-media img{
  width:100%; height:100%; object-fit:cover;
  object-position:center 28%; /* keeps faces in the upper portion of the frame visible */
  display:block;
}
/* restrained blue wash top/left, stronger fade bottom/right, per the reference */
.about-hero-overlay{
  position:absolute; inset:0;
  background:
    linear-gradient(200deg, rgba(10,61,124,.5) 0%, rgba(10,61,124,.14) 40%, transparent 62%),
    linear-gradient(325deg, rgba(10,61,124,.72) 0%, transparent 48%);
}

.about-hero-panel{
  position:relative;
  z-index:2;
  margin-top:clamp(-220px,-24vw,-120px);
  margin-bottom:40px;
  max-width:640px;
  background:var(--white);
  border-radius:40px 120px 40px 40px; /* one prominent corner: upper-right */
  padding:clamp(28px,4vw,52px);
}

@media (max-width:820px){
  .about-hero-media{ height:clamp(220px,50vw,320px); }
  .about-hero-panel{ margin-top:-40px; max-width:none; border-radius:32px 64px 32px 32px; }
}

/* decorative lines bleeding up from the section below into the hero — see .bleed-top */
.bleed-top{ overflow:visible; }
.about-bridge-lines{ position:absolute; top:-140px; left:0; height:300px; }
.about-bridge-lines.at-bottom{ top:auto; bottom:-140px; }
@media (max-width:820px){ .about-bridge-lines{ display:none; } }

/* ==========================================================================
   About — Vision & Mission, one connected composition
   ========================================================================== */

.vm-head{ text-align:center; max-width:600px; margin:0 auto 40px; position:relative; z-index:2; }

/* one continuous photographic strip — three adjacent, equal-height panels, not separate cards */
.vm-photo{
  display:grid; grid-template-columns:1fr 1fr 1fr; gap:3px;
  border-radius:36px; overflow:hidden;
  margin-bottom:-64px; position:relative; z-index:1;
}
.vm-photo img{ width:100%; height:100%; object-fit:cover; display:block; aspect-ratio:4/5; }

.vm-row{ display:flex; align-items:stretch; position:relative; z-index:2; }
.vm-panel{ flex:1; padding:clamp(30px,4vw,52px) clamp(28px,4vw,48px); position:relative; }
.vm-panel-vision{
  background:var(--blue-100);
  color:var(--ink-900);
  border-radius:120px 32px 120px 32px; /* prominent upper-left + lower-right */
  margin-right:-48px;
  padding-right:96px;
  z-index:1;
}
.vm-panel-mission{
  background:var(--blue-900);
  color:var(--white);
  border-radius:120px 32px 32px 32px; /* prominent upper-left, nesting against Vision's curve */
  padding-left:96px;
  z-index:0;
}
.vm-icon{
  width:52px; height:52px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  margin-bottom:18px;
}
.vm-panel-vision .vm-icon{ background:rgba(18,80,158,.1); }
.vm-panel-vision .vm-icon svg{ stroke:var(--blue-700); }
.vm-panel-mission .vm-icon{ background:rgba(255,255,255,.14); }
.vm-panel-mission .vm-icon svg{ stroke:#fff; }
.vm-icon svg{ width:24px; height:24px; }

.vm-statement{
  font-family:var(--font-head); font-weight:700;
  font-size:clamp(18px,1.9vw,22px);
  line-height:1.4;
  margin-bottom:14px;
  text-wrap:balance;
}
.vm-panel-mission .vm-statement{ color:var(--white); }
.vm-note{ font-size:13.5px; line-height:1.65; }
.vm-panel-vision .vm-note{ color:var(--ink-600); }
.vm-panel-mission .vm-note{ color:rgba(255,255,255,.82); }

@media (max-width:820px){
  .vm-row{ flex-direction:column; }
  .vm-panel-vision, .vm-panel-mission{
    border-radius:36px; margin-right:0; padding-left:clamp(28px,4vw,48px); padding-right:clamp(28px,4vw,48px);
  }
  .vm-panel-vision{ margin-bottom:14px; }
  .vm-photo{ margin-bottom:14px; }
}

/* ==========================================================================
   About — Why Now
   ========================================================================== */

.why-grid{
  display:grid;
  grid-template-columns:0.85fr 1.15fr;
  gap:48px;
  align-items:start;
}
.why-grid p{ font-size:15.5px; color:var(--ink-600); line-height:1.7; }
.why-grid p + p{ margin-top:14px; }
@media (max-width:820px){ .why-grid{ grid-template-columns:1fr; } }

.split-photo{
  display:grid; grid-template-columns:1fr 1fr; gap:4px;
  border-radius:30px; overflow:hidden;
  margin:38px 0 34px;
}
.split-photo .photo-frame{ border-radius:0; aspect-ratio:16/11; }

.stat-trio{
  display:flex; justify-content:center; flex-wrap:wrap;
  text-align:center; margin:0 0 26px;
}
.stat-trio .stat-item{ padding:0 clamp(18px,4vw,40px); }
.stat-trio .stat-item + .stat-item{ border-left:2px solid var(--orange-600); }
.stat-trio .num{
  font-family:var(--font-head); font-weight:800;
  font-size:clamp(40px,6vw,68px); color:var(--blue-900);
  font-variant-numeric:tabular-nums;
  line-height:1.05;
  letter-spacing:-.01em;
}
.stat-trio .lbl{ font-size:13.5px; color:var(--ink-600); margin-top:8px; }

@media (max-width:640px){
  .stat-trio{ flex-direction:column; align-items:center; gap:18px; }
  .stat-trio .stat-item{ padding:0; }
  .stat-trio .stat-item + .stat-item{
    border-left:none;
    border-top:2px solid var(--orange-600);
    padding-top:18px;
    width:160px;
  }
}

.why-caption{ text-align:center; max-width:58ch; margin:0 auto; font-size:15px; color:var(--ink-600); }
.why-note{ text-align:center; max-width:64ch; margin:14px auto 0; font-size:13px; color:var(--ink-faint,var(--ink-600)); }

/* ==========================================================================
   The Goal — MDP stat grid (5 big count-up numbers)
   ========================================================================== */
/* Unlike .stat-trio (3 items, short 1-3 word labels, side-by-side with dividers), these 5
   labels are full sentences ("of recent mothers received fewer than 4 antenatal visits..."),
   so a divided single row would either wrap badly or force the row absurdly wide. A wrapping
   grid with generous per-item width instead, no divider lines (the numerals themselves,
   several in different colours-by-position, carry the "data" feel here). Reuses the same
   .num/.lbl + data-count-to counter convention as .stat-trio/.stat-row (initCountUp() in
   js/main.js) — this is a new layout, not a new counter mechanism. */
/* Fixed 5 columns (not auto-fit(minmax(200px,1fr))) — auto-fit's 200px floor meant a 5th
   column never quite fit at typical desktop container widths (~198px available), silently
   wrapping the last stat onto its own row-of-one, which read as broken/off-balance rather than
   the intended one clean row of 5 — reported directly. Fixed at the columns count instead of
   a minimum width, since 5 items at this container width fit comfortably once not fighting an
   arbitrary 200px floor. Narrower breakpoints below still explicitly step down to fewer
   columns rather than relying on auto-fit at all. */
.mdp-stat-grid{
  display:grid;
  grid-template-columns:repeat(5, 1fr);
  gap:32px 24px;
  margin-top:44px;
}
@media (max-width:900px){
  .mdp-stat-grid{ grid-template-columns:repeat(3, 1fr); }
}
.mdp-stat{ text-align:left; }
.mdp-stat .num{
  font-family:var(--font-head); font-weight:800;
  font-size:clamp(34px, 3.6vw, 50px); color:var(--blue-900);
  font-variant-numeric:tabular-nums;
  line-height:1.05;
  letter-spacing:-.01em;
  margin-bottom:8px;
}
.mdp-stat .lbl{ font-size:13.5px; line-height:1.55; color:var(--ink-600); max-width:26ch; }

@media (max-width:640px){
  .mdp-stat-grid{ grid-template-columns:1fr 1fr; gap:26px 20px; }
}
@media (max-width:420px){
  .mdp-stat-grid{ grid-template-columns:1fr; }
}

/* ==========================================================================
   About — The Alliance Concept
   ========================================================================== */

.alliance-banner{
  position:relative;
  height:clamp(320px, 40vw, 460px);
  overflow:hidden;
}
.alliance-banner img{
  width:100%; height:100%; object-fit:cover;
  object-position:center 35%;
  display:block;
}
/* white-to-transparent scrim so the overlaid heading stays readable against the photo */
.alliance-banner-scrim{
  position:absolute; inset:0;
  background:linear-gradient(100deg, rgba(255,255,255,.97) 0%, rgba(255,255,255,.86) 32%, rgba(255,255,255,.2) 64%, transparent 80%);
}
.alliance-banner .container{
  position:relative; z-index:2;
  height:100%; display:flex; align-items:center;
}
.alliance-banner-copy{ max-width:600px; }
.alliance-banner-copy h2{ font-size:clamp(26px,3vw,36px); margin-bottom:16px; }

@media (max-width:760px){
  /* photo stays a clean, fixed-height banner; copy drops below it in normal flow
     rather than overlaying faces */
  .alliance-banner{ height:auto; overflow:visible; }
  .alliance-banner img{ height:220px; }
  .alliance-banner-scrim{ display:none; }
  .alliance-banner .container{
    position:static; height:auto; display:block;
    background:var(--white); padding-top:28px; padding-bottom:6px;
  }
}

.steps-card{
  position:relative; z-index:2;
  background:var(--blue-100);
  border-radius:36px;
  padding:clamp(28px,4vw,44px);
  /* was -64px, inherited from a different page's layout where this card overlapped a photo
     banner above it — here it just sits under a plain heading, so a negative margin cropped
     the heading's second line. Normal positive spacing instead. */
  margin-top:8px;
}
@media (max-width:760px){ .steps-card{ margin-top:0; } }
.steps-row{
  display:grid; grid-template-columns:repeat(4, 1fr); gap:24px;
  position:relative;
}
/* one thin solid orange line travelling behind the four icons — a single connected model,
   not four bordered cards */
.steps-row::before{
  content:"";
  position:absolute; top:26px; left:9%; right:9%; height:2px;
  background:var(--orange-600); opacity:.55;
}
.step-item{ position:relative; }
/* Supporting/item-level icon — smaller and lighter (thin outline, white fill) than the
   heading-level .icon-tile/.systems-card-icon it sits under, so the two read as clearly
   different tiers rather than near-identical circles at different spots. See .icon-tile's
   own comment above for the "was inverted" history. */
.step-icon{
  width:40px; height:40px; border-radius:50%;
  background:var(--white); border:1px solid rgba(18,80,158,.12);
  display:flex; align-items:center; justify-content:center;
  margin-bottom:14px;
  transition:transform .25s ease, border-color .25s ease, box-shadow .25s ease;
}
/* `color:` added for the same reason as `.icon-tile svg` above — several `.step-icon`
   instances (Leadership/Digitisation/Decentralisation/Inclusion, the 8 Systems Strengthening
   items) now use the client-supplied `fill="currentColor"` icons instead of the original
   `stroke`-based ones. */
.step-icon svg{ width:24px; height:24px; stroke:var(--blue-700); color:var(--blue-700); transition:stroke .25s ease, color .25s ease; }
.step-item:hover .step-icon{
  transform:scale(1.1);
  border-color:var(--orange-600);
  box-shadow:0 8px 18px -10px rgba(240,125,28,.5);
}
.step-item:hover .step-icon svg{ stroke:var(--orange-600); }
.step-item h3{
  font-size:12.5px; text-transform:uppercase; letter-spacing:.05em;
  color:var(--blue-700); margin-bottom:6px; font-weight:700;
}
.step-item p{ font-size:13px; color:var(--ink-600); }

.steps-note{ margin-top:26px; font-size:14.5px; color:var(--ink-600); max-width:82ch; line-height:1.7; }

@media (max-width:760px){
  .steps-row{ grid-template-columns:1fr 1fr; }
  .steps-row::before{ display:none; }
}

@media (max-width:480px){
  /* the connecting line rotates into a vertical path behind the stacked items */
  .steps-row{ grid-template-columns:1fr; gap:26px; }
  .steps-row::before{
    display:block;
    top:0; bottom:0; left:26px; right:auto; width:2px; height:auto; background:var(--orange-600);
  }
}

/* ==========================================================================
   About — Outcomes panel
   ========================================================================== */

.outcomes-panel{
  position:relative;
  display:grid;
  grid-template-columns:1.15fr 0.85fr;
  overflow:hidden;
  border-radius:64px 20px 20px 20px; /* one or two prominent corners on the outer section only */
  background:var(--blue-900);
}
.outcomes-inner{
  padding:clamp(36px,5vw,60px);
}
.outcomes-panel h2{ color:var(--white); font-size:clamp(24px,3vw,32px); margin-bottom:26px; }
.checklist{ display:flex; flex-direction:column; gap:13px; margin-bottom:32px; }
.check-item{
  display:flex; align-items:center; gap:12px;
  font-size:14.5px; color:rgba(255,255,255,.92);
}
.check-item svg{ width:22px; height:22px; flex:none; }

.outcomes-media{ position:relative; }
.outcomes-media img{ width:100%; height:100%; object-fit:cover; display:block; }
/* soft blue fade where the photo meets the content column, rather than a hard seam */
.outcomes-seam{
  position:absolute; inset:0 auto 0 0;
  width:36%;
  background:linear-gradient(90deg, var(--blue-900) 0%, rgba(10,61,124,.0) 100%);
}

@media (max-width:820px){
  .outcomes-panel{ grid-template-columns:1fr; border-radius:40px 40px 20px 20px; }
  .outcomes-media{ order:-1; height:220px; }
  .outcomes-seam{ inset:auto 0 0 0; width:auto; height:40%; background:linear-gradient(0deg, var(--blue-900) 0%, rgba(10,61,124,0) 100%); }
}

/* ==========================================================================
   The Challenge — page intro
   ========================================================================== */

.challenge-hero{ position:relative; padding:56px 0 0; overflow:hidden; }
.challenge-hero-grid{
  display:grid; grid-template-columns:1.05fr 0.95fr; gap:48px; align-items:center;
  position:relative; z-index:2; padding-bottom:36px;
}
.challenge-hero h1{ font-size:clamp(32px,4.2vw,50px); margin-bottom:16px; }
.challenge-hero h1 .ink{ color:var(--blue-700); }
.challenge-hero-photo{ aspect-ratio:5/6; }
.challenge-hero-photo img{ object-position:center 22%; }
@media (max-width:860px){
  .challenge-hero-grid{ grid-template-columns:1fr; }
  .challenge-hero-media{ order:-1; }
}

/* ==========================================================================
   Seema's story — deep-blue banner + controlled rounded transition
   ========================================================================== */

.seema-banner{ position:relative; background:var(--blue-900); overflow:hidden; }
.seema-banner-grid{
  position:relative; z-index:2;
  display:grid; grid-template-columns:1fr 1fr; align-items:center; gap:40px;
  min-height:380px; padding:64px 0 120px;
}
.seema-banner-copy h2{ font-size:clamp(28px,4vw,44px); line-height:1.25; }
.on-white{ color:var(--white); }
.on-white-soft{ color:rgba(255,255,255,.88); font-weight:600; }
.on-orange{ color:var(--orange-500); } /* orange-500, not -600: 4.58:1 on blue-900, verified AA-safe */

.seema-banner-media{ position:absolute; inset:0 0 0 42%; z-index:0; }
.seema-banner-media img{ width:100%; height:100%; object-fit:cover; object-position:center 20%; display:block; }
.seema-banner-media::after{
  content:"";
  position:absolute; inset:0;
  background:linear-gradient(90deg, var(--blue-900) 0%, rgba(10,61,124,.55) 32%, rgba(10,61,124,.12) 62%, transparent 88%);
}

@media (max-width:820px){
  .seema-banner-grid{ grid-template-columns:1fr; min-height:0; padding:44px 0 70px; }
  .seema-banner-media{ position:relative; inset:auto; height:220px; margin-top:20px; order:2; }
  .seema-banner-media::after{ background:linear-gradient(0deg, var(--blue-900) 0%, rgba(10,61,124,.25) 40%, transparent 70%); }
}

/* the rounded white panel pulls up over the banner's bottom edge — a controlled rectangle,
   not an organic blob */
.cycle-section{
  position:relative; z-index:2;
  background:var(--white);
  border-radius:56px 56px 0 0;
  margin-top:-72px;
  padding-top:calc(var(--section-y) + 26px);
}
@media (max-width:820px){ .cycle-section{ border-radius:40px 40px 0 0; margin-top:-40px; } }

/* ==========================================================================
   The intergenerational cycle diagram
   ========================================================================== */

.cycle-wrap{
  position:relative;
  max-width:620px;
  aspect-ratio:1/1; /* forced square at every width the circular layout renders at — this,
                        combined with the true-circular-arc paths below, is what keeps the
                        diagram an exact circle rather than an ellipse. */
  margin:8px auto 0;
}
.cycle-connectors{ position:absolute; inset:0; width:100%; height:100%; overflow:visible; }
.cycle-arc{
  fill:none; stroke:var(--orange-600); stroke-width:2; stroke-linecap:round;
  stroke-dasharray:300; stroke-dashoffset:300;
  transition:stroke-dashoffset .6s ease;
}
.cycle-wrap.in-view .cycle-arc{ stroke-dashoffset:0; }
.cycle-wrap.in-view .cycle-arc[data-arc="1"]{ transition-delay:.05s; }
.cycle-wrap.in-view .cycle-arc[data-arc="2"]{ transition-delay:.25s; }
.cycle-wrap.in-view .cycle-arc[data-arc="3"]{ transition-delay:.45s; }
.cycle-wrap.in-view .cycle-arc[data-arc="4"]{ transition-delay:.65s; }
.cycle-wrap.in-view .cycle-arc[data-arc="5"]{ transition-delay:.85s; }
.cycle-wrap.in-view .cycle-arc[data-arc="6"]{ transition-delay:1.05s; }

/* Icon and caption are positioned independently from the same anchor point (rather than
   stacked in one flex box) so the caption can sit OUTSIDE the ring, in the direction that
   points away from the circle, instead of overlapping the arc that passes right by the icon. */
.cycle-node{
  position:absolute;
  left:var(--x); top:var(--y);
  width:0; height:0;
  opacity:0; transition:opacity .5s ease;
}
.cycle-wrap.in-view .cycle-node{ opacity:1; }
.cycle-wrap.in-view .cycle-node[data-node="1"]{ transition-delay:0s; }
.cycle-wrap.in-view .cycle-node[data-node="2"]{ transition-delay:.2s; }
.cycle-wrap.in-view .cycle-node[data-node="3"]{ transition-delay:.4s; }
.cycle-wrap.in-view .cycle-node[data-node="4"]{ transition-delay:.6s; }
.cycle-wrap.in-view .cycle-node[data-node="5"]{ transition-delay:.8s; }
.cycle-wrap.in-view .cycle-node[data-node="6"]{ transition-delay:1s; }

/* node centers sit on a true circle, R=38% of the (always-square) wrap, at 60°/9° insets
   matching the arc math above */
.cycle-node[data-node="1"]{ --x:50%; --y:12%; }
.cycle-node[data-node="2"]{ --x:82.9%; --y:31%; }
.cycle-node[data-node="3"]{ --x:82.9%; --y:69%; }
.cycle-node[data-node="4"]{ --x:50%; --y:88%; }
.cycle-node[data-node="5"]{ --x:17.1%; --y:69%; }
.cycle-node[data-node="6"]{ --x:17.1%; --y:31%; }

.cycle-icon{
  position:absolute; left:0; top:0; transform:translate(-50%,-50%);
  width:60px; height:60px; border-radius:50%;
  background:var(--white); border:2px solid var(--blue-600);
  display:flex; align-items:center; justify-content:center;
}
.cycle-icon::after{
  content:"";
  position:absolute; inset:-7px;
  border-radius:50%;
  border:1.5px dashed rgba(18,80,158,.35);
}
.cycle-icon svg{ width:24px; height:24px; stroke:var(--blue-700); }

.cycle-caption{
  position:absolute;
  width:132px;
  font-size:12px; line-height:1.55; color:var(--ink-600);
}
.cycle-caption strong{ color:var(--ink-900); font-weight:700; }

/* top (1) / bottom (4): caption centred directly below the icon+ring */
.cycle-node[data-node="1"] .cycle-caption,
.cycle-node[data-node="4"] .cycle-caption{
  left:0; top:42px; transform:translateX(-50%); text-align:center;
}
/* right side (2, 3): caption sits to the right, pointing away from the circle */
.cycle-node[data-node="2"] .cycle-caption,
.cycle-node[data-node="3"] .cycle-caption{
  left:40px; top:0; transform:translateY(-50%); text-align:left;
}
/* left side (5, 6): caption sits to the left, pointing away from the circle */
.cycle-node[data-node="5"] .cycle-caption,
.cycle-node[data-node="6"] .cycle-caption{
  left:-40px; top:0; transform:translate(-100%,-50%); text-align:right;
}

.cycle-summary{ text-align:center; margin-top:44px; }
.cycle-summary p{ font-family:var(--font-head); font-weight:700; font-size:clamp(20px,2.4vw,28px); line-height:1.4; }
.ink-strong{ color:var(--blue-700); }

@media (max-width:900px){
  /* the circle collapses into a vertical looping timeline rather than a squeezed circle.
     900px (not the site's usual ~760px breakpoint) is deliberate here: below that width a
     620px-capped circle doesn't leave enough side margin for the 132px outward captions
     without risking horizontal overflow — verified against the geometry above. */
  .cycle-wrap{ aspect-ratio:auto; max-width:420px; }
  .cycle-connectors{ display:none; }
  .cycle-node{
    position:relative; left:auto; top:auto; width:auto; height:auto;
    display:flex; flex-direction:row; align-items:center; text-align:left; gap:16px;
    padding:16px 0; border-left:2px dashed rgba(18,80,158,.3); padding-left:20px; margin-left:22px;
  }
  .cycle-icon{ position:relative; left:auto; top:auto; transform:none; flex:none; }
  .cycle-caption{ position:relative; left:auto; top:auto; transform:none; text-align:left; width:auto; }
  .cycle-node[data-node="6"]{ border-left-color:var(--orange-600); }
  .cycle-node[data-node="6"] .cycle-icon{ border-color:var(--orange-600); }
}

/* ==========================================================================
   National data overview
   ========================================================================== */

.rule-blue{
  border:none; height:1px;
  background:rgba(18,80,158,.15);
  max-width:520px; margin:8px auto 22px;
}

/* ==========================================================================
   Geography of the challenge
   ========================================================================== */

/* align-items was :center — dropped (defaults to :stretch) per direct instruction: the
   right-hand column (.geo-aside) needs to stretch to the map's full height so its own content
   can be anchored to the top (.map-context) and bottom (.mdp-compare-card) of that height,
   rather than being vertically centred as one block the way it was before. */
.geo-grid{
  display:grid; grid-template-columns:1.5fr 0.7fr; gap:40px;
}
@media (max-width:900px){ .geo-grid{ grid-template-columns:1fr; } }

/* .geo-aside wraps .map-context + .mdp-compare-card — stretched to the map's height by the
   grid above, then this flex column splits that height between them: text pinned to the top,
   the compare card pushed to the bottom via margin-top:auto, with whatever space is left
   between them (rather than a fixed gap) — exactly "anchor to the top" / "anchor to the
   bottom" as asked, not just "put some space between them." */
.geo-aside{ display:flex; flex-direction:column; height:100%; }
.geo-aside .mdp-compare-card{ margin-top:auto; }
@media (max-width:900px){
  /* the map's own height no longer constrains anything once the grid drops to 1 column, so
     stretching/anchoring has nothing to measure against — fall back to normal stacked flow
     with an explicit gap instead. */
  .geo-aside{ height:auto; gap:28px; }
  .geo-aside .mdp-compare-card{ margin-top:0; }
}

.geo-compare{ text-align:left; }
.geo-compare-figure{
  font-family:var(--font-head); font-weight:800; color:var(--blue-900);
  font-size:clamp(40px,5vw,56px); line-height:1;
}
.geo-compare-figure span{ color:var(--orange-text); }
.geo-compare-label{ font-size:13.5px; color:var(--ink-600); margin-top:8px; max-width:32ch; }

.geo-bars{ display:flex; gap:28px; margin-top:26px; align-items:flex-end; }
.geo-bar-item{ display:flex; flex-direction:column; align-items:center; gap:8px; width:88px; }
/* the value sits above the bar rather than inside its fill — at 12% the filled area is only
   ~17px tall, nowhere near enough to hold its own label legibly */
.geo-bar-value{
  font-family:var(--font-head); font-weight:800; font-size:17px; color:var(--blue-900);
  font-variant-numeric:tabular-nums;
}
/* No enclosing background/border on the track — that would visually read as a fixed 0–100%
   scale behind the fill, which is misleading once the fill height stopped being a literal
   percentage (see .mdp-compare-card .geo-bar-track below for the specific fix). Just a thin
   baseline so the bars still read as sitting on a shared ground line. */
.geo-bar-track{
  width:44px; height:140px;
  display:flex; align-items:flex-end;
  border-bottom:2px solid rgba(18, 80, 158, .15);
}
.geo-bar-fill{
  width:100%; height:var(--pct);
  background:var(--blue-700);
  border-radius:10px 10px 0 0;
  transition:height .8s ease;
}
.geo-bar-fill--muted{ background:var(--blue-100); }
.geo-bar-lbl{ font-size:12px; color:var(--ink-600); text-align:center; margin-top:2px; }

/* ==========================================================================
   The Goal — MDP compare card (map-context diagram)
   ========================================================================== */
/* Sits inside the dark "Goal" chapter, well past the map — deep enough into the section that,
   same reasoning as the map's own colours and Contact's form fields (see CLAUDE.md
   "`html.theme-dark` must only apply when motion is actually on"), the scroll-driven dark
   backdrop has reliably already caught up by the time this is on screen. Styled directly for
   a dark surface (unconditional white/translucent colours) rather than run through the
   gated light/dark sync machinery that Really-early dark-chapter content needs. */
/* Card + reused .geo-bar-* sizing were both scaled down a notch (from an original
   padding:24px 26px / gap:28px / track 44×140px / multiplier clamp(30–40px)) after direct
   follow-up feedback that the section felt crowded once the diagram was in place — smaller
   footprint here, plus .map-context picking up its own top margin below, together give the
   whole .geo-aside column more breathing room without changing the anchor-top/anchor-bottom
   layout itself. */
.mdp-compare-card{
  display:flex; flex-wrap:wrap; align-items:center; gap:20px;
  background:rgba(255,255,255,.06);
  border:1px solid rgba(255,255,255,.16);
  border-radius:18px;
  padding:18px 20px;
}
.mdp-compare-copy{ flex:1 1 130px; min-width:120px; }
.mdp-compare-multiplier{
  font-family:var(--font-head); font-weight:800;
  font-size:clamp(24px, 2.4vw, 32px); color:var(--white);
  line-height:1; margin-bottom:6px;
  font-variant-numeric:tabular-nums;
}
.mdp-compare-copy p{ font-size:12.5px; line-height:1.5; color:rgba(255,255,255,.7); max-width:22ch; }

/* Dark-surface overrides for the reused .geo-bar-* component (authored above for a light
   section) — scoped to this card so the shared component's own light-mode defaults are
   untouched for any future light-section use. Track/item sizing shrunk here too, alongside
   the card padding above. */
.mdp-compare-card .geo-bars{ margin-top:0; gap:20px; }
.mdp-compare-card .geo-bar-item{ width:70px; }
.mdp-compare-card .geo-bar-value{ color:var(--white); font-size:15px; }
.mdp-compare-card .geo-bar-track{ width:36px; height:104px; border-bottom-color:rgba(255,255,255,.22); }
.mdp-compare-card .geo-bar-fill{ background:linear-gradient(180deg, #FDE9A8 0%, var(--orange-500) 100%); }
.mdp-compare-card .geo-bar-fill--muted{ background:rgba(255,255,255,.35); }
.mdp-compare-card .geo-bar-lbl{ color:rgba(255,255,255,.65); font-size:11.5px; }

/* Bar grow-in: collapsed to height:0 until .reveal--bars (the outer .mdp-compare-card) gets
   .in-view from initScrollReveal() (js/main.js) — same IntersectionObserver-driven mechanism
   every other .reveal variant on the page uses, just animating a bar height instead of an
   opacity/transform. The reduced-motion floor (transition-duration:.001ms, set globally near
   the top of this file) already neutralises this the same way it does every other .reveal
   transition, so no separate reduced-motion rule is needed here. */
.reveal--bars .geo-bar-fill{ height:0; }
.reveal--bars.in-view .geo-bar-fill{ height:var(--pct); }
.reveal--bars.in-view .geo-bar-item:last-child .geo-bar-fill{ transition-delay:.15s; }

@media (max-width:480px){
  .mdp-compare-card{ padding:16px; gap:16px; }
  .mdp-compare-card .geo-bar-item{ width:64px; }
  .mdp-compare-card .geo-bar-track{ width:32px; height:92px; }
}

/* Challenge-page map: labels stay visible; hover/keyboard-focus deepens the state's blue
   (distinct treatment from the homepage's orange-swap map — see the injected HTML comment). */
.challenge-map-wrap{
  position:relative;
  /* no card/box — the map sits directly on the section background, and gets to be bigger
     for it (the padding+border were eating real width). */
}
.challenge-map-svg{ width:100%; height:auto; display:block; }
.challenge-map-svg path{ stroke:#fff; stroke-width:1.3; stroke-linejoin:round; }
/* Single-phase reveal, once, on scroll-into-view: the whole map (focus states + the rest of
   India) fades in together as one piece — see .challenge-map-wrap.in-view below and the
   extended initScrollReveal() target list in js/main.js. Was previously a staggered two-phase
   reveal (5 focus states first, then the rest of India ~0.5s later) — per direct feedback that
   the stagger no longer read as neat, both phases now share the same transition with no delay. */
.challenge-map-svg path{ opacity:0; transition:opacity .6s ease, fill .2s ease; }
.challenge-map-wrap.in-view .challenge-map-svg path{ opacity:1; }

.challenge-map-svg #INAS, .challenge-map-svg #INBR, .challenge-map-svg #INCT,
.challenge-map-svg #INJH, .challenge-map-svg #INOR{
  fill:var(--blue-700);
  transition:fill .2s ease, opacity .6s ease;
  cursor:pointer;
}
.challenge-map-svg #INAS:hover, .challenge-map-svg #INAS:focus-visible,
.challenge-map-svg #INBR:hover, .challenge-map-svg #INBR:focus-visible,
.challenge-map-svg #INCT:hover, .challenge-map-svg #INCT:focus-visible,
.challenge-map-svg #INJH:hover, .challenge-map-svg #INJH:focus-visible,
.challenge-map-svg #INOR:hover, .challenge-map-svg #INOR:focus-visible{
  fill:var(--blue-950);
}
/* real, visible focus ring for keyboard users — never suppress outline without a replacement */
.challenge-map-svg #INAS:focus-visible, .challenge-map-svg #INBR:focus-visible,
.challenge-map-svg #INCT:focus-visible, .challenge-map-svg #INJH:focus-visible,
.challenge-map-svg #INOR:focus-visible{
  outline:2.5px solid var(--orange-600);
  outline-offset:2px;
}
.challenge-map-svg #points, .challenge-map-svg #label_points{ display:none; }
/* State name labels — hover/focus-only, per direct feedback ("when we hover over them you can
   have the name come up like previously we had, and not always displayed"). Sits directly on
   each focus state's own shape, which is always a pale --blue-100 fill in this dark chapter
   (unconditionally, see the map's own colour rules just above — not gated by html.theme-dark),
   so the label needs a dark, not light, fill to read clearly against it. Text-anchor:middle
   centres each label on its state's own label-point anchor (reused from the source Illustrator
   file's #label_points group, not guessed coordinates). pointer-events:none keeps the label
   from ever intercepting the hover/focus/click target that belongs to the state path
   underneath it. */
.map-state-label{
  font-family:var(--font-body); font-weight:700; font-size:22px;
  fill:var(--blue-900);
  text-anchor:middle;
  pointer-events:none;
  paint-order:stroke;
  stroke:rgba(255,255,255,.55); stroke-width:3px;
  opacity:0;
  transition:opacity .2s ease;
}
/* Hover/focus reveal — same :has() technique the old .state-detail-panel used (see "State
   detail panel" in CLAUDE.md): the state path and its label are siblings in different SVG
   groups, so there's no plain CSS sibling selector connecting them; :has() on their shared
   .challenge-map-svg ancestor is what makes "hovering state X reveals label X" possible. */
.challenge-map-svg:has(#INAS:hover, #INAS:focus-visible) .map-state-label[data-for="INAS"],
.challenge-map-svg:has(#INBR:hover, #INBR:focus-visible) .map-state-label[data-for="INBR"],
.challenge-map-svg:has(#INCT:hover, #INCT:focus-visible) .map-state-label[data-for="INCT"],
.challenge-map-svg:has(#INJH:hover, #INJH:focus-visible) .map-state-label[data-for="INJH"],
.challenge-map-svg:has(#INOR:hover, #INOR:focus-visible) .map-state-label[data-for="INOR"]{
  opacity:1;
}

/* ==========================================================================
   State detail panel — replaces the old always-visible 5-line .state-mini-list AND the
   map's own permanent leader-line labels (both removed). Hovering/focusing one of the 5
   highlighted states shows its name + one line of description here instead; nothing else on
   the map changes except the existing hover-fill colour (already handled by the #INxx:hover
   rules above/below — this only controls the text panel). Pure CSS, via the same :has()
   technique the map's own hover-dim effect already uses below — no JS needed.
   ========================================================================== */
/* .map-context replaces .state-detail-panel in the markup (see index.html) — fixed copy
   establishing GAVP's five focus states and the MDP-rate comparison, per the new brief,
   instead of the old hover-triggered per-state description. .state-detail-panel/.state-detail
   and their :has() hover rules below are unused now but left in place — same "leave dead
   code, keep the history" convention as elsewhere in this file — in case the interactive
   version comes back. */
/* margin-top nudges the text down from the map's very top edge. First tried at 12px — reported
   directly as not visibly doing anything ("the text hasn't gone down"), i.e. too subtle to
   read as an intentional shift. Increased substantially. The diagram stays put (still
   bottom-anchored via .mdp-compare-card's margin-top:auto on the shared .geo-aside parent) —
   only the text moves, per direct instruction ("the diagram stays where it is, the text above
   it comes down"). clamp()'d so the shift doesn't eat too much of the available column height
   on shorter viewports where the map itself is shorter. */
.map-context{ display:flex; flex-direction:column; gap:16px; margin-top:clamp(40px, 7vw, 84px); }
.map-context .lede{ font-size:15px; line-height:1.65; }
/* Footnote treatment for the 26%/12% comparison line — per direct feedback ("this is not a
   paragraph line... add it like a footnote. Italics and smaller font"), pulled out of the shared
   `.lede` styling (16px, upright) into its own smaller/italic/muted rule. Doesn't set its own
   colour, same reasoning as .map-context-source below — it inherits from the parent, whose
   colour is already synced to the dark/light theme-dark signal. */
.map-context-footnote{
  font-size:13px; font-style:italic; line-height:1.6;
  opacity:.72;
}
/* Dead code — the inline source citation this paragraph used to end in
   ("[Source: Press Release (GAVP launch)]"), removed per direct feedback ("remove the source
   line. That is just for internal understanding"). Left in place, unused, same dead-code
   convention as elsewhere in this file. */
.map-context-source{
  display:inline-block;
  font-size:11.5px; font-weight:400;
  opacity:.7; /* inherits colour from the parent .lede rather than setting its own — that
    rule is already synced to the dark/light theme-dark signal (see CLAUDE.md), a hardcoded
    colour here would just be wrong (or invisible) in one of the two states */
  margin-left:4px;
}
.state-detail-panel{ position:relative; min-height:96px; display:flex; align-items:center; }
.state-detail{
  display:none;
  font-size:14px; line-height:1.6; color:var(--ink-600);
  border-left:2px solid var(--orange-600); padding-left:14px;
}
.state-detail strong{ display:block; color:var(--blue-700); font-weight:700; margin-bottom:2px; }
.state-detail--default{
  display:block;
  border-left-color:rgba(18,80,158,.2);
  font-style:italic;
}
.geo-grid:has(
  #INAS:hover, #INAS:focus-visible, #INBR:hover, #INBR:focus-visible,
  #INCT:hover, #INCT:focus-visible, #INJH:hover, #INJH:focus-visible,
  #INOR:hover, #INOR:focus-visible
) .state-detail--default{ display:none; }
.geo-grid:has(#INAS:hover, #INAS:focus-visible) .state-detail[data-for="INAS"]{ display:block; }
.geo-grid:has(#INBR:hover, #INBR:focus-visible) .state-detail[data-for="INBR"]{ display:block; }
.geo-grid:has(#INCT:hover, #INCT:focus-visible) .state-detail[data-for="INCT"]{ display:block; }
.geo-grid:has(#INJH:hover, #INJH:focus-visible) .state-detail[data-for="INJH"]{ display:block; }
.geo-grid:has(#INOR:hover, #INOR:focus-visible) .state-detail[data-for="INOR"]{ display:block; }

/* ==========================================================================
   State realities — accessible tabs
   ========================================================================== */

.state-tabs-panel{
  background:var(--blue-100);
  border-radius:36px;
  padding:clamp(22px,3vw,32px);
}
.state-tablist-wrap{ overflow-x:auto; -webkit-overflow-scrolling:touch; margin-bottom:22px; }
.state-tablist{ display:flex; gap:6px; min-width:max-content; border-bottom:1px solid rgba(18,80,158,.18); }
.state-tab{
  background:none; border:none;
  padding:12px 18px; min-height:44px;
  font-family:var(--font-body); font-weight:600; font-size:14.5px;
  color:var(--ink-600);
  border-bottom:2px solid transparent;
  white-space:nowrap;
}
.state-tab:hover{ color:var(--blue-700); }
.state-tab.is-active{ color:var(--blue-900); border-bottom-color:var(--orange-600); }

.state-panels{ display:grid; }
/* All 5 panels stay in the same grid cell at all times (grid-row/column:1), which is what
   keeps the panel's overall height stable across switches — the row auto-sizes to the
   tallest panel, visible or not. Native `hidden`/`display:none` would remove a panel from
   that height calculation entirely, so visibility is used instead, with a transition-delay
   that keeps it "visible" for the full fade-out (only flipping to hidden once opacity hits 0)
   so inactive panels are excluded from the tab order without an abrupt cut. */
.state-panel{
  grid-row:1; grid-column:1;
  display:grid; grid-template-columns:1fr 1fr; gap:32px; align-items:center;
  opacity:0; visibility:hidden; pointer-events:none;
  transform:translateX(10px);
  transition:opacity .3s ease, transform .3s ease, visibility 0s linear .3s;
}
.state-panel.is-active{
  opacity:1; visibility:visible; pointer-events:auto; transform:translateX(0);
  transition:opacity .3s ease, transform .3s ease, visibility 0s linear 0s;
}
.state-panel-copy h3{ font-size:clamp(20px,2.4vw,26px); margin-bottom:12px; }
.state-panel-copy p{ font-size:15px; color:var(--ink-600); line-height:1.7; }
.state-indicator-note{ margin-top:14px; font-size:12.5px; font-style:italic; color:var(--ink-faint,var(--ink-600)); }
.state-panel-media{ border-radius:28px; overflow:hidden; aspect-ratio:4/3; }
.state-panel-media img{ width:100%; height:100%; object-fit:cover; display:block; }

@media (max-width:760px){
  .state-panel{ grid-template-columns:1fr; }
  .state-panel-media{ order:-1; }
}

/* ==========================================================================
   Interconnected deprivations — Health / Nutrition / Education
   ========================================================================== */

.hne-wrap{
  position:relative;
  max-width:600px;
  aspect-ratio:500/460;
  margin:36px auto 0;
}
.hne-connectors{ position:absolute; inset:0; width:100%; height:100%; overflow:visible; }
.hne-line{
  fill:none; stroke-width:1.6;
  stroke-dasharray:400; stroke-dashoffset:400;
  transition:stroke-dashoffset .8s ease;
  opacity:.7;
}
.hne-wrap.in-view .hne-line{ stroke-dashoffset:0; }

.hne-node{
  position:absolute; left:var(--x); top:var(--y);
  transform:translate(-50%,-50%);
  width:180px; text-align:center;
  opacity:0; transition:opacity .5s ease;
}
.hne-wrap.in-view .hne-node{ opacity:1; }
/* these --x/--y assignments were accidentally dropped when the inline styles were removed —
   without them every node defaulted to the same position and rendered stacked on top of
   each other. Position values must live here, not just the transition-delay. */
.hne-node[data-node="health"]{ --x:50%; --y:8%; transition-delay:.1s; }
.hne-node[data-node="nutrition"]{ --x:15%; --y:82%; transition-delay:.3s; }
.hne-node[data-node="education"]{ --x:85%; --y:82%; transition-delay:.5s; }

.hne-icon{
  width:58px; height:58px; border-radius:50%;
  background:var(--blue-100);
  display:inline-flex; align-items:center; justify-content:center;
  margin-bottom:10px;
}
.hne-icon svg{ width:26px; height:26px; stroke:var(--blue-700); }
.hne-node h4{ font-size:14.5px; margin-bottom:6px; color:var(--blue-700); }
.hne-node ul{ font-size:12.5px; color:var(--ink-600); line-height:1.7; }

.hne-center{
  position:absolute; left:50%; top:56%; transform:translate(-50%,-50%);
  max-width:150px; text-align:center;
  font-family:var(--font-head); font-weight:700; font-size:14px; color:var(--blue-900);
  line-height:1.4;
}

@media (max-width:640px){
  .hne-wrap{ aspect-ratio:auto; height:auto; }
  .hne-connectors, .hne-center{ display:none; }
  .hne-wrap{ display:flex; flex-direction:column; gap:24px; align-items:center; }
  .hne-node{ position:relative; left:auto; top:auto; transform:none; }
}

/* ==========================================================================
   Closing systemic-response CTA
   ========================================================================== */

.systemic-cta{
  position:relative;
  display:grid; grid-template-columns:1.15fr 0.85fr;
  overflow:hidden;
  border-radius:20px 64px 20px 20px;
  background:var(--blue-900);
}
.systemic-cta-inner{ padding:clamp(36px,5vw,60px); position:relative; z-index:2; }
.systemic-cta-inner .eyebrow{ margin-bottom:14px; }
.systemic-cta-inner h2{ color:var(--white); font-size:clamp(26px,3.2vw,36px); margin-bottom:16px; }
.systemic-cta-inner p{ color:rgba(255,255,255,.85); font-size:15.5px; line-height:1.7; margin-bottom:28px; max-width:52ch; }

.systemic-cta-media{ position:relative; }
.systemic-cta-media img{ width:100%; height:100%; object-fit:cover; display:block; }
.systemic-cta-seam{
  position:absolute; inset:0 auto 0 0; width:36%;
  background:linear-gradient(90deg, var(--blue-900) 0%, rgba(10,61,124,0) 100%);
}

.btn-arrow{ transition:transform .18s ease; }
.btn:hover .btn-arrow{ transform:translateX(3px); }

@media (max-width:820px){
  .systemic-cta{ grid-template-columns:1fr; border-radius:20px 40px 20px 20px; }
  .systemic-cta-media{ order:-1; height:220px; }
  .systemic-cta-seam{ inset:auto 0 0 0; width:auto; height:40%; background:linear-gradient(0deg, var(--blue-900) 0%, rgba(10,61,124,0) 100%); }
}

/* ==========================================================================
   Single-page microsite — compact section components
   (added when the project pivoted from 7 full pages to one compressed scroll;
   everything above this point is still shared with the archived multi-page build)
   ========================================================================== */

.home-extras{ padding-top:36px; padding-bottom:36px; }
.home-video-row{
  display:grid; grid-template-columns:1.1fr 0.9fr; gap:36px; align-items:center;
  margin-bottom:36px;
}
/* Widened taller (16/10 -> 5/4) to better match the now considerably taller 3-paragraph copy
   column beside it — per direct instruction ("adjust the video ratio accordingly"). 4/5 (full
   portrait) was tried first and overshot badly (733px tall vs. the copy's 448px at a 1400px
   capture); 5/4 lands close (469px vs 448px). */
.home-video .frame-video{ aspect-ratio:5/4; }
.home-video-copy .lede + .lede{ margin-top:14px; }
@media (max-width:820px){ .home-video-row{ grid-template-columns:1fr; } }

.logo-strip{ border-top:1px solid rgba(18,80,158,.08); padding-top:28px; }

/* About — compact Vision/Mission pair (flat cards, not the full interlocking panels
   used on the archived About page — this section is meant to read in seconds) */
.vm-mini-row{ display:grid; grid-template-columns:1fr 1fr; gap:20px; margin-bottom:36px; }
.vm-mini{ border-radius:24px; padding:26px 28px; }
.vm-mini--light{ background:var(--blue-100); }
.vm-mini--light p{ color:var(--ink-900); font-size:15px; line-height:1.6; }
.vm-mini--dark{ background:var(--blue-900); }
.vm-mini--dark p{ color:rgba(255,255,255,.9); font-size:15px; line-height:1.6; }
@media (max-width:700px){ .vm-mini-row{ grid-template-columns:1fr; } }

.why-now-mini{ margin-bottom:32px; }
.alliance-tagline{ text-align:center; }

/* ==========================================================================
   How GAVP Works (continued) — Government/Community, Systems columns,
   stat banner, Four Pillars
   ========================================================================== */

/* Government / Community — light-card/dark-card pairing, same visual logic as
   .vm-mini--light/--dark in About (two sides of one system), reused rather than inventing a
   second two-tone pattern. */
.gcw-row{ display:grid; grid-template-columns:1fr 1fr; gap:28px; margin:8px 0 0; position:relative; }
@media (max-width:820px){ .gcw-row{ grid-template-columns:1fr; } }

.gcw-card{ border-radius:28px; padding:clamp(28px, 4vw, 40px); }
.gcw-card--light{ background:var(--blue-50); border:1px solid rgba(18,80,158,.1); }
.gcw-card--dark{ background:var(--blue-900); }

/* The "GAVP is the bridge" connector — simplified to a plain vertical bar + centred circular
   "GAVP" badge, per direct feedback. Was an hourglass-shaped SVG panel spanning the full card
   height with a double-headed arrow either side, built to match a client reference image as
   closely as possible — but the organic shape's deliberate overlap into each card's padding
   (see the superseded comment this replaces) still read as covering the cards' own text, and
   the shape itself was flagged as "not working." .gcw-bridge-shape/.gcw-bridge-arrow's CSS is
   left in place below, unused, same dead-code convention as elsewhere in this file. Absolutely
   positioned (not a grid child) so it overlays the gap between the two cards without adding its
   own row/height — `.gcw-row` is a grid, so both cards already stretch to the same height by
   default, which `.gcw-bridge{ top:0; bottom:0 }` then exactly matches. */
.gcw-bridge{
  position:absolute; top:0; bottom:0; left:50%; transform:translateX(-50%);
  width:72px;
  z-index:3; pointer-events:none;
}
.gcw-bridge-line{
  position:absolute; top:0; bottom:0; left:50%; transform:translateX(-50%);
  width:3px; border-radius:2px;
  background:linear-gradient(180deg, var(--blue-700), var(--blue-900));
}
.gcw-bridge-badge{
  position:absolute; top:50%; left:50%; transform:translate(-50%,-50%);
  display:flex; align-items:center; justify-content:center;
  width:72px; height:72px; border-radius:50%;
  background:var(--white); border:3px solid var(--orange-500);
  color:var(--blue-900);
  font-family:var(--font-head); font-weight:800; font-size:13.5px; letter-spacing:.02em;
  box-shadow:0 14px 30px -12px rgba(7,44,90,.55), inset 0 0 0 6px rgba(18,80,158,.06);
}
@media (max-width:820px){ .gcw-bridge{ display:none; } }
/* Dead code — the hourglass shape + arrows this connector used to be, kept for history only. */
.gcw-bridge-shape{ position:absolute; inset:0; width:100%; height:100%; display:block; }
.gcw-bridge-arrow{
  position:absolute; top:50%; color:var(--orange-500);
  width:18px; height:11px;
}
.gcw-bridge-arrow svg{ width:100%; height:100%; }
.gcw-bridge-arrow--left{ right:calc(50% + 22px); transform:translateY(-50%); }
.gcw-bridge-arrow--right{ left:calc(50% + 22px); transform:translateY(-50%); }

/* Caption moved back out of the bridge shape entirely (an inline version was tried first,
   positioned inside the shape's lower half to match the reference exactly — but the shape is
   only ~148px wide, and at any width wide enough to hold readable text there, it collided with
   the cards' own real body copy, which runs considerably longer than the reference mockup's.
   A single always-visible caption below the row is less literal but reliably readable
   regardless of how long the surrounding card content gets. */
.gcw-bridge-caption{
  text-align:center; font-size:13.5px; font-style:italic; color:var(--ink-600);
  margin:14px 0 56px;
}

.gcw-card-head{ display:flex; align-items:center; gap:14px; margin-bottom:26px; }
.gcw-card-head h3{ font-size:22px; }
.gcw-card--dark .gcw-card-head h3{ color:var(--white); }
/* Community's heading icon now matches Government's light-blue-circle/dark-blue-icon
   treatment exactly, per direct feedback — was a translucent-white circle with a white icon
   (matching the rest of the dark card), now the same var(--blue-100) background + blue-700
   icon as the light "Government" card, so only this one heading icon breaks from the card's
   otherwise-dark styling. Everything else in the dark Community card (items, stats, text)
   is untouched. */
.gcw-card--dark .gcw-card-head .icon-tile{ background:var(--blue-100); }
.gcw-card--dark .gcw-card-head .icon-tile svg{ stroke:var(--blue-700); color:var(--blue-700); }

/* Reuses .step-icon (the same circular icon treatment the old 4-step row used) but in a
   vertical mini-list, 2 per card, instead of a horizontal row of 4. */
.gcw-items{ display:flex; flex-direction:column; gap:20px; margin-bottom:26px; }
.gcw-item{ display:flex; gap:14px; align-items:flex-start; }
.gcw-item .step-icon{ flex:none; margin-bottom:0; }
.gcw-item h4{ font-size:14px; font-weight:700; color:var(--blue-700); margin-bottom:4px; }
.gcw-item p{ font-size:13.5px; line-height:1.55; color:var(--ink-600); }
.gcw-card--dark .gcw-item h4{ color:var(--white); }
.gcw-card--dark .gcw-item p{ color:rgba(255,255,255,.72); }
.gcw-card--dark .gcw-item .step-icon{ background:rgba(255,255,255,.1); border-color:rgba(255,255,255,.24); }
.gcw-card--dark .gcw-item .step-icon svg{ stroke:var(--white); color:var(--white); }

.gcw-lede{
  font-family:var(--font-head); font-weight:700; font-size:14.5px;
  color:var(--blue-700);
  padding-top:20px; border-top:1px solid rgba(18,80,158,.14);
  margin-bottom:18px;
}
.gcw-card--dark .gcw-lede{ color:var(--white); border-top-color:rgba(255,255,255,.2); }

/* The 3 highlighted-number lines per card — per direct instruction ("the numbers part has to
   be highlighted and numbers to be bold and in counter fashion like we do"). .num reuses the
   site's existing data-count-to counter convention; .num-static is for the one line per card
   that isn't a clean countable number ("Thousands of...") — same precedent as "1 in 7" in the
   MDP stat grid elsewhere, still styled to match, just not animated. */
.gcw-stats{ display:flex; flex-direction:column; gap:10px; }
.gcw-stat{ font-size:14px; line-height:1.5; color:var(--ink-600); }
.gcw-card--dark .gcw-stat{ color:rgba(255,255,255,.85); }
.gcw-stat .num,
.gcw-stat .num-static{
  font-family:var(--font-head); font-weight:800; font-size:19px;
  color:var(--blue-900); font-variant-numeric:tabular-nums;
}
.gcw-card--dark .gcw-stat .num,
.gcw-card--dark .gcw-stat .num-static{ color:var(--orange-500); }

/* Strengthen Education Systems / Strengthen Health Systems — was a plain bulleted list (a
   dot marker + running text); per direct client feedback ("paragraphs look very plain...
   bullet points can be replaced with relevant icons, boxes can be added") rebuilt into boxed
   .systems-item cards, reusing the exact .step-icon treatment (icon + h4 + p) the
   Government/Community items above already use, so the two blocks read as one consistent
   visual language rather than two different list styles back to back. */
.systems-row{ display:grid; grid-template-columns:1fr 1fr; gap:44px; margin:0 0 56px; position:relative; }
@media (max-width:760px){ .systems-row{ grid-template-columns:1fr; gap:32px; } }

/* Per direct client reference image: each column is now a bordered card with a solid-blue
   header bar (icon + white title), not a plain heading sitting directly above the list. */
.systems-card{
  background:var(--white); border:1px solid rgba(18,80,158,.1);
  border-radius:20px; overflow:hidden;
}
.systems-card-head{
  display:flex; align-items:center; gap:12px;
  background:var(--blue-700); padding:18px 22px;
}
/* Education vs Health made visually distinct, per direct feedback that the two cards "appear
   too similar" — restrained, colour-only differences (no new elements/icons/badges added, to
   avoid the clutter the same feedback explicitly warned against). Went through three rounds:
   Health's header bar was first just a deeper navy (--blue-900 instead of Education's
   --blue-700), which read as too close to Education's own blue at a glance; then switched to
   solid orange (--orange-600) per direct feedback ("make Strengthen Health Systems fully
   orange like how it's blue on the left side, so they look visually distinct"); **then tuned
   to a specific client-supplied hex pair** — header bar + item icons/headings `#f88512`, item
   boxes `#f6dec4`; **then the header/icon/heading orange was swapped again to `#e17300`** (a
   deeper, less yellow orange), per a further direct follow-up, while `#f6dec4` (the light
   peachy item-box tint) stayed unchanged. All hex values are **hardcoded, not CSS custom
   properties** and **scoped only to `.systems-card--health`** — a deliberate one-off request
   for this specific card, not a sitewide palette change; the shared `--orange-*` tokens
   (buttons, CTAs, highlights elsewhere) are untouched throughout all these rounds. This is a
   deliberate, scoped exception to "orange is a scarce accent, not a second primary colour"
   (see "Colour" above), confined to this one card. A separate earlier attempt at
   differentiation (a 5px border-left stripe in each card's own header colour) was tried and
   reverted per direct feedback that it "wasn't working" — border-left doesn't follow a
   border-radius curve the way a background fill does (overflow:hidden only clips a child's
   *content*, not the element's own border rendering), so the straight vertical stripe visibly
   broke the card's rounded top/bottom-left corners instead of tracing them. */
.systems-card--health{ background:var(--blue-50); }
.systems-card--health .systems-card-head{ background:#e17300; }
.systems-card--health .systems-items .systems-item{ background:#f6dec4; border-color:rgba(225,115,0,.22); }
/* Sized up (was 38px, smaller than the 40px .step-icon items sitting right below it in the
   same card — the same inverted-hierarchy issue fixed sitewide, see .icon-tile's comment) so
   this heading icon is unambiguously the larger, more prominent one in the card. */
.systems-card-icon{
  width:46px; height:46px; border-radius:50%; flex:none;
  border:1.5px solid rgba(255,255,255,.6);
  display:flex; align-items:center; justify-content:center;
  color:var(--white);
}
.systems-card-icon svg{ width:29px; height:29px; }
.systems-card-head h3{ font-size:17px; color:var(--white); margin:0; }
.systems-items{ display:flex; flex-direction:column; gap:14px; padding:22px; }

/* Dotted vertical connector between the two cards — removed entirely per direct feedback
   (a later round explicitly asked to remove the orange dotted divider in this area, on top
   of the earlier request to drop its node-dot markers — see CLAUDE.md "How GAVP Works — full
   rebuild"). .systems-connector/.systems-connector-dot's CSS is left in place, unused, same
   dead-code convention as elsewhere in this file — nothing in current index.html references
   either class any more. */
.systems-connector{
  position:absolute; top:0; bottom:0; left:50%; transform:translateX(-50%);
  width:2px;
  border-left:2px dotted var(--orange-500);
}
.systems-connector-dot{
  width:10px; height:10px; border-radius:50%;
  background:var(--white); border:2px solid var(--orange-500);
  margin-left:-6px;
}
@media (max-width:760px){ .systems-connector{ display:none; } }
.systems-item{
  display:flex; gap:14px; align-items:flex-start;
  background:var(--blue-50); border:1px solid rgba(18,80,158,.1);
  border-radius:16px; padding:16px 18px;
  transition:border-color .25s ease, box-shadow .25s ease, transform .25s ease;
}
.systems-item:hover{
  border-color:var(--orange-500);
  box-shadow:0 14px 28px -18px rgba(10,61,124,.3);
  transform:translateY(-2px);
}
.systems-item .step-icon{ flex:none; margin-bottom:0; }
.systems-item h4{ font-size:14.5px; font-weight:700; color:var(--blue-700); margin-bottom:4px; }
.systems-item p{ font-size:13.5px; line-height:1.55; color:var(--ink-600); }
/* Health card's item icons/headings recoloured from the shared blue-700 to the same #f88512
   used on its header bar — per direct follow-up instruction, so the icon + heading text inside
   each Health item box reads as part of the same orange system as the header, not left blue
   like Education's. Body copy (.systems-item p) stays the neutral ink-600 grey in both cards —
   only what was explicitly blue changed. */
.systems-card--health .systems-item h4{ color:#e17300; }
.systems-card--health .systems-item .step-icon svg{ stroke:#e17300; color:#e17300; }

/* Stat callout banner — full-bleed, edge-to-edge, per direct instruction ("scales all the way
   from end to end"). Same 100vw/-50vw breakout trick as .logo-marquee--patch (now removed from
   About, but the technique/its safety guard — main{overflow-x:hidden} — are both still very
   much in play), not a new one invented for this. "UP TO 10X" is static text (.hl, reusing the
   site's existing inline-highlight class), not run through the count-up mechanism — see the
   HTML comment for why. */
.stat-banner{
  position:relative;
  width:100vw; left:50%; right:50%; margin-left:-50vw; margin-right:-50vw;
  background:var(--blue-900);
  padding:clamp(32px, 5vw, 52px) var(--gutter);
  margin-top:0; margin-bottom:56px;
  text-align:center;
}
.stat-banner p{
  font-family:var(--font-head); font-weight:700;
  font-size:clamp(20px, 2.8vw, 32px); color:var(--white);
  max-width:900px; margin:0 auto;
  line-height:1.4;
}
.stat-banner .hl{ color:var(--orange-500); font-weight:800; }
/* Two-line h3+p variant — reused as-is for Partners' closing CTA band ("Join the Global
   Alliance..." / "Turn philanthropic capital...") rather than building a second full-bleed
   banner component. When h3 is present, it carries the bold headline weight and p drops to a
   lighter secondary line underneath, instead of p alone carrying the single-line statement. */
.stat-banner h3{
  font-family:var(--font-head); font-weight:700;
  font-size:clamp(22px, 3vw, 34px); color:var(--white);
  max-width:820px; margin:0 auto 10px;
  line-height:1.3;
}
.stat-banner h3 + p{
  font-family:var(--font-body); font-weight:400;
  font-size:clamp(14.5px, 1.6vw, 17px); color:rgba(255,255,255,.8);
}

/* Four Pillars — redesigned again per a direct client reference image ("make it exactly like
   this"): 4 standalone cards, no shared outer wrapper, alternating white/dark-blue background,
   each with a white icon circle + a large faint index number on top, a heading, and a
   description. Replaces the previous "one shared card, individual .pillar-item boxes inside"
   version entirely — .pillars-card/.pillar-item/.pillar-badge's old CSS is left in place,
   unused, same dead-code convention as elsewhere. */
.pillars-row{ display:grid; grid-template-columns:repeat(4, 1fr); gap:20px; }
@media (max-width:900px){ .pillars-row{ grid-template-columns:1fr 1fr; } }
@media (max-width:520px){ .pillars-row{ grid-template-columns:1fr; } }

.pillar-card{
  position:relative; overflow:hidden;
  background:var(--white); border:1px solid rgba(18,80,158,.1);
  border-radius:20px 20px 20px 64px;
  padding:26px 22px;
  transition:transform .25s ease, box-shadow .25s ease;
}
.pillar-card:nth-child(2n){ border-radius:20px 64px 20px 20px; }
.pillar-card:hover{ transform:translateY(-3px); box-shadow:0 18px 34px -20px rgba(10,61,124,.35); }
.pillar-card--dark{ background:var(--blue-900); border-color:var(--blue-900); }

.pillar-card-top{ display:flex; align-items:flex-start; justify-content:space-between; margin-bottom:34px; }
.pillar-icon{
  width:52px; height:52px; border-radius:50%; flex:none;
  background:var(--white); border:1px solid rgba(18,80,158,.14);
  display:flex; align-items:center; justify-content:center;
  color:var(--blue-700);
  box-shadow:0 8px 18px -12px rgba(10,61,124,.3);
}
.pillar-icon svg{ width:31px; height:31px; stroke:var(--blue-700); }
.pillar-num{
  font-family:var(--font-head); font-weight:800; font-size:clamp(38px,4vw,50px);
  color:rgba(18,80,158,.14); line-height:1;
}
.pillar-card--dark .pillar-num{ color:rgba(255,255,255,.16); }

.pillar-card h3{ font-size:17px; color:var(--blue-700); margin-bottom:10px; }
.pillar-card p{ font-size:14px; line-height:1.6; color:var(--ink-600); }
.pillar-card--dark h3{ color:var(--white); }
.pillar-card--dark p{ color:rgba(255,255,255,.75); }

/* ==========================================================================
   Partners — Six Ways to Engage (3-column, 2-row grid)
   ========================================================================== */
/* Redesigned again per a direct client reference image ("make it exactly like this"): light-
   blue-fill cards with a darker blue outline and a white icon circle, inverting to a dark-blue
   fill only on hover/focus. History: was a dark blue-900 fill + white text; then bordered
   WHITE cards + a "+" expand affordance in the bottom-right corner (see the two superseded
   comment blocks that used to live here). Per a later, more specific reference image + direct
   feedback: base fill is now light blue (not white), border is a visibly darker blue (not a
   faint tint), and the "+" affordance was removed outright — "there is no functionality" behind
   it, so it was just a false affordance. .engage-expand's CSS below is left in place, unused,
   same dead-code convention as elsewhere in this file — the HTML no longer references it. */
.engage-grid{
  display:grid; grid-template-columns:repeat(3, 1fr); gap:22px;
}
@media (max-width:900px){ .engage-grid{ grid-template-columns:1fr 1fr; } }
@media (max-width:560px){ .engage-grid{ grid-template-columns:1fr; } }

/* All hover-state properties below share the exact same duration+easing (.18s ease) and have
   no property-specific delays, so the background/border/icon/text changes land in the same
   frame instead of visibly sequencing. Was .25s ease with the properties spread across several
   separate transition declarations (still same duration/easing on paper, but reported directly
   as looking like a two-step glitch — box turning white, then only afterward turning dark blue)
   — consolidated and shortened for a snappier, more obviously-simultaneous flip. */
.engage-item{
  position:relative;
  display:block;
  padding:24px 22px 26px;
  border-radius:18px;
  background:var(--blue-50);
  border:1.5px solid var(--blue-600);
  transition:border-color .18s ease, box-shadow .18s ease, transform .18s ease, background-color .18s ease;
}
.engage-item:hover{
  border-color:var(--blue-900);
  box-shadow:0 18px 36px -18px rgba(10,61,124,.35);
  transform:translateY(-3px);
  background:var(--blue-900);
}
.engage-item-top{ display:flex; align-items:flex-start; justify-content:space-between; margin-bottom:18px; }
.engage-item .icon-tile{
  background:var(--white);
  transition:transform .18s ease, background-color .18s ease;
}
.engage-item .icon-tile svg{ stroke:var(--blue-700); color:var(--blue-700); transition:stroke .18s ease, color .18s ease; }
.engage-item:hover .icon-tile{ background:rgba(255,255,255,.14); transform:scale(1.08); }
.engage-item:hover .icon-tile svg{ stroke:var(--white); color:var(--white); }
.engage-num{
  font-family:var(--font-head); font-weight:800; font-size:14px; color:var(--blue-700);
  transition:color .18s ease;
}
.engage-item:hover .engage-num{ color:var(--orange-500); }
.engage-item h4{ font-size:16px; margin-bottom:6px; color:var(--ink-900); transition:color .18s ease; }
.engage-item p{ font-size:13.5px; line-height:1.55; color:var(--ink-600); transition:color .18s ease; }
.engage-item:hover h4{ color:var(--white); }
.engage-item:hover p{ color:rgba(255,255,255,.78); }
.engage-expand{
  position:absolute; right:20px; bottom:20px;
  width:32px; height:32px; border-radius:50%;
  border:1px solid rgba(18,80,158,.3);
  display:flex; align-items:center; justify-content:center;
  color:var(--blue-700);
  transition:transform .18s ease, background-color .18s ease, border-color .18s ease, color .18s ease;
}
.engage-expand svg{ width:15px; height:15px; }
.engage-item:hover .engage-expand{
  border-color:var(--orange-500); background:var(--orange-500); color:var(--white);
  transform:rotate(90deg);
}

/* ==========================================================================
   Case Studies — Bihar 8-stat grid
   ========================================================================== */
.case-study-grid{
  display:grid; grid-template-columns:repeat(4, 1fr); gap:24px;
}
@media (max-width:900px){ .case-study-grid{ grid-template-columns:1fr 1fr; } }
@media (max-width:480px){ .case-study-grid{ grid-template-columns:1fr; } }

.case-stat{
  position:relative;
  background:var(--white);
  border:1px solid rgba(18,80,158,.1);
  border-radius:20px;
  padding:30px 22px 24px;
  overflow:hidden;
  transition:transform .35s var(--ease-premium), box-shadow .35s var(--ease-premium), border-color .35s ease;
}
/* The "slide" — a two-tone bar that grows in from the left edge on hover, not a fade. Literal
   scaleX so it reads as motion, matching the "when we hover the sections slide" request. */
.case-stat::before{
  content:"";
  position:absolute; top:0; left:0; right:0; height:4px;
  background:linear-gradient(90deg, var(--orange-600), var(--blue-700));
  transform:scaleX(0); transform-origin:left;
  transition:transform .5s var(--ease-premium);
}
.case-stat:hover{
  transform:translateY(-6px);
  box-shadow:0 24px 44px -22px rgba(10,61,124,.35);
  border-color:transparent;
}
.case-stat:hover::before{ transform:scaleX(1); }
.case-stat-index{
  position:absolute; top:18px; right:20px;
  font-family:var(--font-head); font-weight:800; font-size:13px;
  color:rgba(18,80,158,.14);
  transition:color .35s ease;
}
.case-stat:hover .case-stat-index{ color:rgba(240,125,28,.4); }
.case-stat .num, .case-stat .num-static{
  display:block;
  font-family:var(--font-head); font-weight:800;
  font-size:clamp(26px, 2.6vw, 36px); color:var(--blue-900);
  font-variant-numeric:tabular-nums;
  line-height:1.1;
  transition:color .35s ease;
}
.case-stat:hover .num, .case-stat:hover .num-static{ color:var(--orange-text); }
.case-stat p{ font-size:13.5px; line-height:1.55; color:var(--ink-600); margin-top:10px; }
/* Icon added above the index number, per the reference image — every stat card now leads with
   a circular outlined icon (same treatment as .step-icon elsewhere) rather than jumping straight
   to the number. Compound, non-single-number stats (e.g. "70% / 19%→81%", "64 / 222") use a
   smaller font size than a clean single number so they don't wrap awkwardly inside the card. */
.case-stat-icon{
  display:flex; align-items:center; justify-content:center;
  width:40px; height:40px; border-radius:50%; flex:none;
  background:var(--blue-100); border:1px solid rgba(18,80,158,.12);
  color:var(--blue-700);
  margin-bottom:14px;
  transition:background-color .35s ease, color .35s ease;
}
.case-stat-icon svg{ width:19px; height:19px; stroke:var(--blue-700); transition:stroke .35s ease; }
.case-stat:hover .case-stat-icon{ background:var(--orange-100); color:var(--orange-600); }
.case-stat:hover .case-stat-icon svg{ stroke:var(--orange-600); }
.case-stat .num-static{ font-size:clamp(18px, 1.7vw, 23px); }

/* ==========================================================================
   Case Studies — section header + tab nav, per-state hero cards, closing bars
   ========================================================================== */
.case-studies-head{
  display:flex; align-items:flex-end; justify-content:space-between; flex-wrap:wrap;
  gap:20px; margin-bottom:48px;
}
.case-tabs{ display:flex; gap:28px; }
.case-tab{
  font-family:var(--font-head); font-weight:800; font-size:14.5px; letter-spacing:.01em;
  color:var(--blue-600); padding-bottom:6px; border-bottom:2px solid transparent;
  transition:color .2s ease, border-color .2s ease;
}
.case-tab:hover{ color:var(--blue-900); }
.case-tab--active{ color:var(--orange-text); border-bottom-color:var(--orange-600); }

.case-block{ margin-bottom:56px; scroll-margin-top:100px;}
.case-block:last-child{ margin-bottom:0; }

.case-hero{
  display:grid; grid-template-columns:1fr 1fr;
  border-radius:28px 84px 28px 28px;
  overflow:hidden;
  margin-bottom:40px;
}
.case-hero--dark{ background:var(--blue-900); }
.case-hero--light{ background:var(--blue-50); border:1px solid rgba(18,80,158,.1); border-radius:28px 28px 84px 28px; }
@media (max-width:820px){ .case-hero{ grid-template-columns:1fr; } }

.case-hero-copy{
  padding:clamp(32px, 4vw, 56px);
  display:flex; flex-direction:column; justify-content:center; gap:16px;
}
.case-hero-tag{
  font-family:var(--font-body); font-weight:700; font-size:12.5px; letter-spacing:.06em; text-transform:uppercase;
}
.case-hero--dark .case-hero-tag{ color:var(--orange-500); }
.case-hero-tag--standalone{ color:var(--orange-text); text-align:center; margin-bottom:18px; }
.case-hero-tag .dot{ opacity:.6; margin:0 2px; }
/* Visual hierarchy swapped per direct feedback (item 28 of the AlignX content-changes doc):
   the location/domain label used to be the small uppercase .case-hero-tag while the tagline
   was the large heading — reversed so the label reads as the primary/larger text and the
   tagline as smaller, secondary text. Both are dedicated classes now (not a bare `h3` tag
   selector, which would fight with class-based overrides at equal/higher specificity) so
   either can be applied to whichever element without a selector conflict. */
.case-hero-tag--label{
  font-family:var(--font-head); font-weight:800;
  font-size:clamp(24px, 2.8vw, 34px); line-height:1.18; letter-spacing:0; text-transform:none;
}
.case-hero--dark .case-hero-tag--label{ color:var(--white); }
.case-hero--light .case-hero-tag--label{ color:var(--blue-700); }
.case-hero-tag--label .dot{ margin:0 8px; color:var(--orange-500); opacity:1; }
.case-hero-tag--standalone.case-hero-tag--label{ color:var(--blue-900); }

.case-hero-tagline{
  font-family:var(--font-body); font-weight:700; font-size:13px; letter-spacing:.06em; text-transform:uppercase; line-height:1.4;
}
.case-hero--dark .case-hero-tagline{ color:var(--orange-500); }
.case-hero--light .case-hero-tagline{ color:var(--orange-text); }
.case-hero-copy p{ font-size:15px; line-height:1.65; }
.case-hero--dark .case-hero-copy p{ color:rgba(255,255,255,.75); }
.case-hero--light .case-hero-copy p{ color:var(--ink-600); }

.case-hero-media{ position:relative; min-height:280px; }
.case-hero-media img{ width:100%; height:100%; object-fit:cover; display:block; }

/* The "38 Districts" badge — a small pill sitting under the copy, echoing the map-pin/count-up
   language used elsewhere on the page (.mdp-stat-grid, .gcw-stats) rather than inventing a new
   stat-display pattern for one badge. */
.case-hero-badge{
  display:inline-flex; align-items:center; gap:12px; align-self:flex-start;
  background:rgba(255,255,255,.08); border:1px solid rgba(255,255,255,.18);
  border-radius:16px; padding:12px 18px; margin-top:6px;
}
.case-hero-badge-icon{
  display:flex; align-items:center; justify-content:center;
  width:36px; height:36px; border-radius:50%; flex:none;
  background:rgba(255,255,255,.12); color:var(--orange-500);
}
.case-hero-badge-icon svg{ width:18px; height:18px; stroke:var(--orange-500); }
.case-hero-badge .num{ display:block; font-family:var(--font-head); font-weight:800; font-size:22px; color:var(--white); line-height:1.1; }
.case-hero-badge .lbl{ display:block; font-size:11px; letter-spacing:.06em; text-transform:uppercase; color:rgba(255,255,255,.65); }

/* Rajasthan's "Since 2008" / "From 100 schools" pair — same visual language as the badge above,
   but two plain inline items rather than one boxed pill (the reference shows them unboxed on
   the light hero). */
.case-hero-facts{ display:flex; gap:28px; margin-top:6px; }
.case-hero-fact{ display:flex; align-items:center; gap:12px; }
.case-hero-fact-icon{
  display:flex; align-items:center; justify-content:center;
  width:38px; height:38px; border-radius:50%; flex:none;
  background:var(--blue-100); color:var(--blue-700);
}
.case-hero-fact-icon svg{ width:18px; height:18px; stroke:var(--blue-700); }
.case-hero-fact strong{ display:block; font-family:var(--font-head); font-weight:800; font-size:16px; color:var(--blue-900); line-height:1.2; }

.case-subhead{
  font-size:clamp(20px, 2vw, 25px); color:var(--blue-900); margin-bottom:24px;
}

/* Closing statement bar — a contained, rounded dark-navy pill (not the edge-to-edge .stat-banner
   breakout used elsewhere), matching the reference's "capsule" shape. Just a centred statement
   now, no arrow/CTA — per direct feedback ("they are just statements so we dont need the bottom
   right arrow or 'explore the proof'... make the statements centre aligned"), both were removed
   (`.case-closing-arrow` was a quiet in-page link to Rajasthan, `.case-closing--cta` held an
   actual `.btn-primary`; their CSS is left in place below, unused, same dead-code convention as
   elsewhere in this file). `margin-top` matches `.case-study-grid`'s own `gap` (24px) so the bar
   sits equidistant from the stat cards above it, rather than flush against them — also flagged
   directly ("the closing lines are very attached to the data boxes"). */
.case-closing{
  margin-top:24px;
  display:flex; align-items:center; justify-content:center;
  background:var(--blue-900); border-radius:20px;
  padding:clamp(24px, 3vw, 34px) clamp(28px, 4vw, 40px);
}
.case-closing p{ color:var(--white); font-weight:700; font-size:clamp(16px, 1.6vw, 19px); line-height:1.4; max-width:64ch; margin:0; text-align:center; }
/* Dead code — the arrow-in-a-circle (Bihar) and the .btn-primary CTA variant (Rajasthan,
   .case-closing--cta) this bar used to end in, kept for history only. */
.case-closing-arrow{
  display:flex; align-items:center; justify-content:center; flex:none;
  width:48px; height:48px; border-radius:50%;
  background:var(--orange-600); color:var(--white);
  transition:background-color .2s ease, transform .2s ease;
}
.case-closing-arrow svg{ width:20px; height:20px; }
.case-closing-arrow:hover{ background:var(--orange-500); transform:translateX(3px); }
.case-closing--cta .btn-primary{ flex:none; }

/* Short connector between the two case-study blocks — just enough to read as "next case
   study," not a full section divider/rule. Was a dotted line (echoing .systems-connector's
   now-removed language elsewhere on the page) — switched to the site's plain solid-line
   convention instead, per direct feedback to remove dotted separators sitewide in favour of
   clean lines. */
.case-divider{
  position:relative;
  display:flex; justify-content:center;
  height:40px; margin:0 0 8px;
}
.case-divider::before{
  content:""; height:100%; border-left:2px solid var(--orange-500);
}
.case-divider-dot{
  position:absolute; bottom:-4px; left:50%; transform:translateX(-50%);
  width:8px; height:8px; border-radius:50%;
  background:var(--orange-500);
}

.icon-cards--row{ flex-direction:row; margin-top:8px; }
@media (max-width:820px){ .icon-cards--row{ flex-direction:column; } }

/* ==========================================================================
   The Goal — "Why public systems" (replaces the old Health/Nutrition/Education
   icon-card row in .curtain-current — see index.html)
   ========================================================================== */
/* Sits inside the dark sticky transition layer between The Gap and How GAVP Works. It uses
   direct dark-surface styling because `.curtain-current` is always blue-900 by construction. */
/* Centred to match the rest of The Goal chapter (heading, systemic-statement, MDP stat grid
   above are all centred) — a left-aligned block here read as visually disconnected from
   everything around it. */
.why-systems{ max-width:820px; margin:0 auto; text-align:center; }
.why-systems > .eyebrow{ color:var(--orange-500); margin-bottom:22px; }
/* The single $200B+ figure, pulled out of a bullet-list item into a real stat — reuses the
   same big-number-plus-caption language as .mdp-stat-grid/.hero-metric elsewhere on the page,
   rather than a lone <li> with a disc marker (which read as an unfinished list, not a
   statistic). */
.why-systems-stat .num{
  font-family:var(--font-head); font-weight:800;
  font-size:clamp(42px, 5.5vw, 64px); color:var(--white);
  font-variant-numeric:tabular-nums;
  line-height:1;
}
.why-systems-caption{
  font-size:15px; line-height:1.65; color:rgba(255,255,255,.75);
  max-width:640px; margin:12px auto 0;
}
/* A short orange accent bar instead of a full-width hairline — "orange punctuates" per the
   brand's own colour rule, and reads as a deliberate divider rather than a leftover rule line. */
.why-systems-divider{
  display:block; width:56px; height:3px;
  background:var(--orange-500); border-radius:2px;
  margin:30px auto;
}
/* The part called out to "highlight... like a title/bold font" — larger and bolder than the
   stat above it, not just an inline emphasis, so it reads as the section's takeaway line.
   Per a later, explicitly flagged-as-important round of feedback ("this line needs to pop...
   right now it looks plain"), wrapped in its own bordered/tinted pull-quote card — a subtle
   translucent panel with an orange left accent (the "white panels layered over blue" shape
   language, not a glow/gradient effect) — and bumped up another size step, so it reads as a
   distinct callout rather than a fourth paragraph in a row of similar-looking text. */
.why-systems-highlight-card{
  background:rgba(255,255,255,.07);
  border:1px solid rgba(255,255,255,.16);
  border-left:4px solid var(--orange-500);
  border-radius:4px 20px 20px 4px;
  padding:clamp(22px,3vw,32px) clamp(24px,3.4vw,40px);
  max-width:780px; margin:0 auto;
}
.why-systems-highlight{
  font-family:var(--font-head); font-weight:700;
  font-size:clamp(22px, 2.6vw, 30px); line-height:1.4;
  color:var(--white);
}
/* Scoped colour (not the shared .hl, which is tuned for light backgrounds) — verified 4.58:1
   on --blue-900, same safe shade used for .eyebrow/.mdp-stat-grid .num elsewhere on dark. */
.why-systems-highlight .pop{ color:var(--orange-500); }

/* How GAVP Works — ecosystem, shown as a simple tag row since the brief lists names only */
.ecosystem-row{
  display:flex; flex-wrap:wrap; justify-content:center; gap:10px;
  margin-top:28px;
}
.eco-chip{
  background:var(--white); border:1px solid rgba(18,80,158,.15);
  border-radius:999px; padding:8px 18px;
  font-size:13.5px; font-weight:600; color:var(--blue-700);
}

/* Partners — anchor-partner name (was an inline style; pulled into a class so
   .section-dark can override its colour now that Partners is a dark chapter) */
.partner-name{
  font-size:clamp(20px,2.4vw,26px); margin-bottom:12px; color:var(--blue-700);
  font-family:var(--font-head); font-weight:700;
}

/* Partners — Piramal Foundation's 4-stat row (stat-trio is built for exactly 3 dividered
   items; this is a simpler wrapping row for 4) */
.stat-row{ display:flex; flex-wrap:wrap; gap:32px; margin-top:10px; }
.stat-row .stat{ min-width:96px; }
.stat-row .stat .num{
  font-family:var(--font-head); font-weight:800;
  font-size:clamp(30px,3.6vw,42px); color:var(--blue-900);
  font-variant-numeric:tabular-nums;
  line-height:1.05;
}
.stat-row .stat .lbl{ font-size:12.5px; color:var(--ink-600); margin-top:6px; }

/* Partners — compact case-study pair */
.case-mini-row{ display:grid; grid-template-columns:1fr 1fr; gap:20px; margin-top:36px; }
.case-mini{ background:var(--blue-50); border-radius:20px; padding:22px 24px; }
.case-mini h4{ font-size:16px; margin-bottom:8px; }
.case-mini p{ font-size:13.5px; color:var(--ink-600); line-height:1.6; }
@media (max-width:700px){ .case-mini-row{ grid-template-columns:1fr; } }

/* Resources — single brochure card */
.resource-card{
  display:grid; grid-template-columns:0.9fr 1.1fr; gap:32px; align-items:center;
  max-width:880px; margin:0 auto;
  background:var(--white); border-radius:28px; padding:22px;
  border:1px solid rgba(18,80,158,.1);
}
.resource-card-media{ aspect-ratio:16/10; }
.resource-card-copy h3{ font-size:19px; margin-bottom:10px; }
.resource-card-copy p{ font-size:14px; color:var(--ink-600); line-height:1.6; margin-bottom:18px; }
.btn[aria-disabled="true"]{ opacity:.6; cursor:not-allowed; }

/* Resource links grid — down to 2 boxes (GAVP Overview, Press & Outreach) per the AlignX
   content-changes doc (see the comment on #resources in index.html); was 4. Styled as
   interactive link-cards (hover lift/border-glow), same language as .engage-item/.case-stat
   elsewhere, not a plain static list. */
.resource-links{
  display:grid; grid-template-columns:repeat(2, 1fr); gap:20px;
  max-width:760px; margin:32px auto 0;
}
@media (max-width:600px){ .resource-links{ grid-template-columns:1fr; } }
.resource-link-card{
  display:block;
  background:var(--white);
  border:1px solid rgba(18,80,158,.12);
  border-radius:18px;
  padding:22px 20px;
  transition:border-color .25s ease, box-shadow .25s ease, transform .25s ease;
}
.resource-link-card:hover{
  border-color:var(--orange-600);
  box-shadow:0 16px 32px -20px rgba(10,61,124,.3);
  transform:translateY(-3px);
}
.resource-link-card[aria-disabled="true"]{ cursor:not-allowed; }
.resource-link-card h4{ font-size:15.5px; color:var(--blue-700); margin-bottom:6px; }
.resource-link-card p{ font-size:13px; line-height:1.5; color:var(--ink-600); }

/* GAVP Overview card — the one box with a download button next to its text, so it's a plain
   div (not the whole-card <a> the other resource-link-cards use — a link can't nest inside a
   link) laid out as a row instead of the default block/hover-only card. */
.resource-link-card--overview{
  display:flex; align-items:center; justify-content:space-between; gap:16px;
}
.resource-link-card-btn{ padding:10px 20px; font-size:13.5px; flex-shrink:0; }
@media (max-width:480px){
  .resource-link-card--overview{ flex-direction:column; align-items:flex-start; }
}

/* ==========================================================================
   Impact Stories — 5 vertical panels, one expands on hover/focus/tap.
   Deliberately not `.section-dark`/`data-bg-theme` — see the HTML comment on
   #impact-stories for why: this section's own opaque background makes it
   "statically dark blue" regardless of scroll position, per direct
   instruction, with none of the theme-dark sync machinery built for the
   scroll-crossfaded chapters (for example The Gap) — that machinery has
   nothing to key off here since this section never toggles it.
   ========================================================================== */
/* min-height:auto for the same reason #hero-metrics/#resources/#challenge/.how-gavp
   already override it (see CLAUDE.md "Section background rhythm") — on the stacked mobile
   layout this section's content is shorter than 100vh, and the base .section's forced-100vh +
   align-items:center floor would centre it inside a mostly-empty box instead. */
.section#impact-stories{ background:var(--blue-900); min-height:auto; padding:clamp(56px,8vw,100px) 0; }
.impact-stories .impact-stories-intro .eyebrow{ color:var(--orange-500); } /* verified 4.58:1 on blue-900, same as .section-dark .eyebrow elsewhere */
.impact-stories .impact-stories-intro h2{ color:var(--white); font-size:clamp(26px,3vw,36px); margin:14px 0 16px; }
.impact-stories .impact-stories-intro .lede{ color:rgba(255,255,255,.72); }

.impact-stories-layout{
  display:flex; align-items:stretch; gap:clamp(28px,4vw,56px);
}
.impact-stories-intro{ flex:0 0 clamp(220px,22vw,300px); padding-top:6px; }

.impact-panels{
  display:flex; gap:14px; flex:1; min-width:0;
}
.impact-panel{
  position:relative;
  flex:1 1 0; min-width:0;
  display:flex; flex-direction:column;
  height:clamp(380px,42vw,560px);
  border-radius:22px;
  overflow:hidden;
  background:var(--blue-950);
  text-decoration:none;
  box-shadow:0 0 0 0 rgba(7,44,90,0);
  transition:flex-grow .55s cubic-bezier(.22,.61,.36,1), background-color .45s ease, box-shadow .35s ease;
  cursor:pointer;
}
.impact-panel-media{ position:relative; flex:0 0 60%; overflow:hidden; }
.impact-panel-media img{
  width:100%; height:100%; object-fit:cover; display:block;
  transition:transform .6s cubic-bezier(.22,.61,.36,1);
}
/* Two stacked fade layers, crossfaded via opacity, instead of one layer whose `background`
   (gradient) value used to swap navy->white directly. A `background`/gradient value is NOT
   smoothly interpolable by a CSS transition — the browser can only hard-swap it the instant
   the rule changes, which is exactly the "box forming"/hard-edged flash reported over the
   image on hover. `opacity` IS smoothly interpolable, so crossfading two pre-drawn gradients
   (one navy-to-transparent, one white-to-transparent) reads as one continuous, seamless dissolve. */
.impact-panel-fade{
  position:absolute; inset:auto 0 0 0; height:65%;
  pointer-events:none;
  transition:opacity .5s ease;
}
.impact-panel-fade--dark{ background:linear-gradient(to top, var(--blue-950) 0%, rgba(7,44,90,0) 100%); opacity:1; }
.impact-panel-fade--light{ background:linear-gradient(to top, var(--white) 0%, rgba(255,255,255,0) 100%); opacity:0; }

.impact-panel-body{ position:relative; flex:1; }
/* Two independent text blocks crossfaded via opacity, rather than one heading whose container
   keeps reflowing live as the panel's own width animates (flex-grow triggers real layout on
   every frame, so a single shared heading visibly rewraps/jumps between line-breaks mid-
   transition — reported as the text "glitching as it rearranges"). Each copy fades out FAST
   with no delay the instant the hover state changes (gone before its own reflow becomes
   visible) and the incoming copy fades in only after a delay long enough for the .55s
   flex-grow transition to have mostly settled — so neither piece of text is ever visibly
   mid-reflow, in either direction. */
.impact-panel-heading-collapsed,
.impact-panel-content-expanded{
  position:absolute; left:16px; right:16px; bottom:18px;
}
.impact-panel-heading-collapsed{
  color:var(--white); font-size:clamp(12.5px,1.15vw,14.5px); line-height:1.32;
  font-family:var(--font-head); font-weight:700;
  opacity:1;
  transition:opacity .22s ease .3s; /* fading back IN (leaving hover) — delayed so it only
    appears once the panel has mostly finished shrinking back to its narrow resting width */
}
.impact-panel-content-expanded{
  opacity:0;
  transition:opacity .28s ease; /* fading OUT (leaving hover) — no delay, gone quickly as the
    panel starts shrinking, before its text would visibly reflow narrower */
}
.impact-panel-content-expanded h3{
  color:var(--blue-900); font-size:clamp(13px,1.15vw,15px); line-height:1.3;
  font-family:var(--font-head); font-weight:700;
}
.impact-panel-content-expanded p{ font-size:12.5px; line-height:1.55; color:var(--ink-600); margin:8px 0 12px; }
.impact-panel-cta{
  display:inline-flex; align-items:center; gap:6px;
  font-size:12.5px; font-weight:700; color:var(--blue-700);
  cursor:pointer;
}
.impact-panel-cta svg{ width:15px; height:15px; transition:transform .3s ease; }

.impact-panel:hover,
.impact-panel:focus-visible,
.impact-panel.is-active{
  flex-grow:3.4;
  background:var(--white);
  box-shadow:0 24px 48px -20px rgba(7,44,90,.4);
}
.impact-panel:hover .impact-panel-fade--dark,
.impact-panel:focus-visible .impact-panel-fade--dark,
.impact-panel.is-active .impact-panel-fade--dark{ opacity:0; }
.impact-panel:hover .impact-panel-fade--light,
.impact-panel:focus-visible .impact-panel-fade--light,
.impact-panel.is-active .impact-panel-fade--light{ opacity:1; }
.impact-panel:hover .impact-panel-media img,
.impact-panel:focus-visible .impact-panel-media img,
.impact-panel.is-active .impact-panel-media img{ transform:scale(1.06); }
.impact-panel:hover .impact-panel-heading-collapsed,
.impact-panel:focus-visible .impact-panel-heading-collapsed,
.impact-panel.is-active .impact-panel-heading-collapsed{
  opacity:0; transition:opacity .28s ease; /* fading OUT (entering hover) — no delay, gone
    quickly before it would visibly reflow wider */
}
.impact-panel:hover .impact-panel-content-expanded,
.impact-panel:focus-visible .impact-panel-content-expanded,
.impact-panel.is-active .impact-panel-content-expanded{
  opacity:1; transition:opacity .25s ease .3s; /* fading IN (entering hover) — delayed to land
    right as the .55s flex-grow transition finishes, so it appears already-settled */
}

@media (max-width:900px){
  .impact-stories-layout{ flex-direction:column; gap:28px; }
  .impact-stories-intro{ flex:none; max-width:60ch; }
  .impact-panel{ height:clamp(320px,58vw,420px); }
}
@media (max-width:560px){
  .impact-panels{ gap:8px; }
  .impact-panel{ border-radius:16px; height:340px; }
  .impact-panel-body{ padding:12px 10px; }
  .impact-panel-heading-collapsed,
  .impact-panel-content-expanded{ left:10px; right:10px; bottom:12px; }
  .impact-panel-content-expanded p{ font-size:11.5px; margin:6px 0 10px; }
}

/* Contact — simple static form shell (no backend wired yet) */
.contact-form{ max-width:640px; margin:0 auto; }
.form-field{ display:flex; flex-direction:column; gap:6px; }
.form-field span{ font-size:13px; font-weight:600; color:var(--blue-700); }
.form-field input, .form-field textarea{
  font-family:var(--font-body); font-size:14.5px;
  border:1px solid rgba(18,80,158,.25); border-radius:10px;
  padding:11px 14px; background:var(--white); color:var(--ink-900);
  resize:vertical;
}
.form-field input:focus-visible, .form-field textarea:focus-visible{
  outline:2px solid var(--orange-600); outline-offset:1px; border-color:var(--orange-600);
}
.form-check{
  display:flex; align-items:flex-start; gap:10px;
  margin:16px 0 22px; font-size:13px; color:var(--ink-600);
}
.form-check input{ margin-top:3px; flex:none; width:16px; height:16px; }

/* ==========================================================================
   Reduced motion — disable count-up / draw-in / stagger, show everything immediately
   ========================================================================== */

@media (prefers-reduced-motion: reduce){
  .cycle-arc, .hne-line{ transition:none !important; stroke-dashoffset:0 !important; }
  .cycle-node, .hne-node{ transition:none !important; opacity:1 !important; }
  .geo-bar-fill{ transition:none !important; }
  .state-panel{ transition:none !important; }
  .reveal, .reveal--pop{ transition:none !important; opacity:1 !important; transform:none !important; }
  .chapter-orb{ transition:none !important; opacity:1 !important; transform:none !important; }
  .challenge-map-svg path{ transition:none !important; opacity:1 !important; }
  .step-icon, .step-item:hover .step-icon{ transition:none !important; transform:none !important; }
}

/* Breathing room before Public Systems Strengthening */
#how-it-works .section-head.reveal{
  margin-top:32px !important;
}

/* Tighten Resources → Contact handoff */
@media (min-width:761px){
  #resources{
    padding-bottom:42px;
  }

  #contact{
    padding-top:42px;
  }
}

/* ==========================================================================
   MOBILE SYSTEM — Batch 1
   Reference widths: 390px primary / 412px secondary
   Fluid safety range: ~360px–430px
   ========================================================================== */

   /* Mobile-only controls for Education / Health carousel */
.systems-mobile-nav{
  display:none;
}
@media (max-width: 767px) {

  /* ------------------------------------------------------------------------
     Mobile navbar
     ------------------------------------------------------------------------ */

  .nav{
    padding:12px 18px;
    gap:12px;
  }

  .logo{
    font-size:22px;
    flex:none;
  }

  .nav-cta{
    margin-left:0;
    gap:8px;
  }

  .nav-toggle{
    width:42px;
    height:42px;
    flex:none;
  }

  .nav-toggle span,
  .nav-toggle::before,
  .nav-toggle::after{
    width:22px;
  }

  /* Keep the floating/scrolled navbar compact on phones. */
  .site-header.is-scrolled{
    padding-top:8px;
  }

  .site-header.is-scrolled .nav{
    max-width:calc(100% - 24px);
    padding:8px 10px;
    gap:8px;
  }

  /* Dropdown aligns with the compact mobile header. */
  .nav-links{
    padding:12px 20px 18px;
  }

  .nav-links a{
    font-size:14px;
  }
    /* ------------------------------------------------------------------------
     Hero metrics
     Three equal compact cells instead of a wrapping desktop flex row.
     ------------------------------------------------------------------------ */

  .section#hero-metrics{
    padding:36px 0 40px;
  }

  .hero-metrics-content{
    flex-basis:auto;
    max-width:none;
    width:100%;
  }

  .hero-metrics-layout{
    display:block;
  }

  .hero-metrics-statement{
    font-size:clamp(21px, 6.2vw, 25px);
    line-height:1.38;
    margin-bottom:18px;
  }

  .hero-metrics-tagline{
    font-size:13px;
    line-height:1.7;
    margin-bottom:28px;
  }

  .hero-metrics-row{
    display:grid;
    grid-template-columns:repeat(3, minmax(0, 1fr));
    gap:0;
    width:100%;
    align-items:start;
    text-align:center;
  }

  .hero-metric{
    min-width:0;
    padding:2px 10px;
  }

  /* Reset the desktop separator implementation first. */
  .hero-metric:not(:first-child){
    padding-left:10px;
    border-left:1px solid rgba(10,61,124,.18);
  }

  .hero-metric .num{
    display:block;
    font-size:clamp(28px, 8.5vw, 34px);
    line-height:1;
  }

  .hero-metric .lbl{
    display:block;
    margin-top:8px;
    font-size:11.5px;
    line-height:1.35;
  }

  /*
   * The decorative ribbon competes with the content on narrow screens.
   * The statement + metrics are the important information, so remove only
   * the decoration in mobile mode.
   */
  .hero-metrics-graphic{
    display:none;
  }

    /* ------------------------------------------------------------------------
     Hero video
     ------------------------------------------------------------------------ */

  .hero--video h1{
    font-size:clamp(38px, 11vw, 46px);
    line-height:1.05;
  }

  .hero-grid--video .hero-copy{
    padding:72px 0 38px;
  }

  .hero-cta-links{
    display:flex;
    flex-direction:column;
    align-items:flex-start;
    gap:20px;
    margin-bottom:0;
  }

  .hero-cta-link{
    font-size:14px;
  }

  /* ------------------------------------------------------------------------
   THE GAP — mobile typography
   ------------------------------------------------------------------------ */

#challenge{
  padding-top:96px;
  padding-bottom:64px;
}

#challenge .section-head{
  margin-bottom:22px !important;
}

#challenge .section-head h2{
  font-size:clamp(30px, 8vw, 34px);
  line-height:1.08;
}

#challenge .section-head .lede{
  font-size:15px;
  line-height:1.6;
  margin-top:12px !important;
}

/* The signature MDP statement should remain prominent without behaving
   like another full-screen headline on a phone. */
#challenge .systemic-statement{
  margin-top:34px;
  margin-bottom:32px;
}

#challenge .systemic-statement__context,
#challenge .systemic-statement__reveal{
  font-size:clamp(23px, 6.5vw, 28px);
  line-height:1.28;
}
/* ------------------------------------------------------------------------
   THE GAP — compact mobile statistic grid
   ------------------------------------------------------------------------ */

#challenge .mdp-stat-grid{
  display:grid;
  grid-template-columns:repeat(2, minmax(0, 1fr));
  gap:12px;
  margin-top:30px;
}

/* Override the old <=420px rule that forced every stat onto its own row. */
#challenge .mdp-stat{
  min-width:0;
  padding:16px 14px;

  background:rgba(255,255,255,.06);
  border:1px solid rgba(255,255,255,.12);
  border-radius:16px;

  text-align:left;
}

/* Last statistic uses the complete row instead of leaving an awkward
   empty sixth cell. */
#challenge .mdp-stat:last-child{
  grid-column:1 / -1;

  display:grid;
  grid-template-columns:auto 1fr;
  align-items:center;
  column-gap:16px;
}

#challenge .mdp-stat .num{
  font-size:clamp(28px, 8vw, 34px);
  line-height:1;
  margin-bottom:8px;
}

#challenge .mdp-stat .lbl{
  font-size:12px;
  line-height:1.45;
  max-width:none;
}

#challenge .mdp-stat:last-child .num{
  margin-bottom:0;
}

/* ------------------------------------------------------------------------
   THE GAP — mobile focus-state map

   Touchscreens don't have a useful hover state. Show all five GAVP focus
   states and their labels immediately instead.
   ------------------------------------------------------------------------ */

#challenge .challenge-map-wrap{
  margin-top:10px;
}

#challenge .challenge-map-svg{
  width:100%;
  max-width:390px;
  margin-inline:auto;
}

/* All five focus states are simultaneously highlighted on mobile. */
#challenge .challenge-map-svg #INAS,
#challenge .challenge-map-svg #INBR,
#challenge .challenge-map-svg #INCT,
#challenge .challenge-map-svg #INJH,
#challenge .challenge-map-svg #INOR{
  fill:var(--orange-500);
  cursor:default;
}

/* State names already exist in front-page.php.
   Make them permanently visible on mobile instead of hover-only. */
#challenge .map-state-label{
  opacity:1;
  fill:var(--white);

  font-size:24px;
  font-weight:700;

  stroke:rgba(10,61,124,.8);
  stroke-width:4px;
}
/* ------------------------------------------------------------------------
   THE GAP — map context and comparison
   ------------------------------------------------------------------------ */

#challenge .geo-grid{
  gap:22px;
  margin-top:36px;
}

#challenge .geo-aside{
  gap:18px;
}

#challenge .map-context{
  margin-top:0;
}

#challenge .map-context .lede{
  font-size:14px;
  line-height:1.55;
}

#challenge .map-context .lede + .lede{
  margin-top:12px;
}

#challenge .mdp-compare-card{
  padding:16px;
  gap:14px;
  border-radius:16px;
}

#challenge .mdp-compare-multiplier{
  font-size:26px;
}

#challenge .mdp-compare-copy p{
  font-size:11.5px;
  line-height:1.45;
}

#challenge .mdp-compare-card .geo-bar-track{
  height:78px;
  width:28px;
}

#challenge .mdp-compare-card .geo-bar-item{
  width:54px;
}

#challenge .mdp-compare-card .geo-bars{
  gap:14px;
}

/* ------------------------------------------------------------------------
   HOW GAVP WORKS — Government → GAVP → Community mobile bridge
   ------------------------------------------------------------------------ */

#how-it-works .gcw-row{
  display:grid;
  grid-template-columns:1fr;
  gap:0;
  overflow:visible;
}

/* Reorder the existing three children on mobile:
   Government → Bridge → Community */
#how-it-works .gcw-card--light{
  order:1;
}

#how-it-works .gcw-bridge{
  display:block;
  order:2;

  position:relative;
  inset:auto;
  top:auto;
  right:auto;
  bottom:auto;
  left:auto;
  transform:none;

  width:100%;
  height:94px;
  z-index:1;
  pointer-events:none;
}

#how-it-works .gcw-card--dark{
  order:3;
}

/* Vertical connection between the two sides of the system */
#how-it-works .gcw-bridge-line{
  top:-10px;
  bottom:-10px;
  left:50%;
  width:3px;
  transform:translateX(-50%);

  background:var(--orange-500);
}

/* GAVP becomes the literal bridge between the cards */
#how-it-works .gcw-bridge-badge{
  top:50%;
  left:50%;
  transform:translate(-50%,-50%);

  width:66px;
  height:66px;

  font-size:13px;

  border-width:3px;
  box-shadow:
    0 10px 24px -10px rgba(7,44,90,.45),
    inset 0 0 0 5px rgba(18,80,158,.06);
}

/* Government / Community cards — reduce mobile scroll length */

#how-it-works .gcw-card{
  padding:22px 20px;
  border-radius:22px;
}

#how-it-works .gcw-items{
  gap:14px;
  margin-bottom:18px;
}

#how-it-works .gcw-item{
  gap:11px;
}

#how-it-works .gcw-item .step-icon{
  width:36px;
  height:36px;
}

#how-it-works .gcw-item h4{
  font-size:13.5px;
  margin-bottom:3px;
}

#how-it-works .gcw-item p{
  font-size:12.5px;
  line-height:1.48;
}

#how-it-works .gcw-lede{
  font-size:13.5px;
  line-height:1.5;
  padding-top:16px;
  margin-bottom:14px;
}

#how-it-works .gcw-stats{
  gap:7px;
}

#how-it-works .gcw-stat{
  font-size:12.5px;
  line-height:1.45;
}

#how-it-works .gcw-stat .num,
#how-it-works .gcw-stat .num-static{
  font-size:17px;
}

/* ------------------------------------------------------------------------
   SYSTEMS STRENGTHENING — mobile Education / Health switcher
   ------------------------------------------------------------------------ */

#how-it-works .systems-mobile-nav{
  display:grid;
  grid-template-columns:1fr 1fr;

  padding:4px;
  margin:0 0 8px;

  background:rgba(18,80,158,.08);
  border:1px solid rgba(18,80,158,.10);
  border-radius:999px;
}

#how-it-works .systems-mobile-tab{
  appearance:none;
  border:0;
  background:transparent;

  min-height:42px;
  padding:9px 12px;
  border-radius:999px;

  font-family:var(--font-body);
  font-size:13px;
  font-weight:700;
  color:var(--blue-700);

  transition:
    background-color .2s ease,
    color .2s ease,
    box-shadow .2s ease;
}

#how-it-works .systems-mobile-tab.is-active{
  background:var(--blue-700);
  color:var(--white);
  box-shadow:0 5px 14px -8px rgba(10,61,124,.6);
}

/* Health uses the orange visual language already established by its card. */
#how-it-works
.systems-mobile-tab[data-system-target="health"].is-active{
  background:#e17300;
}

/* ------------------------------------------------------------------------
   Horizontal native scroll-snap carousel
   ------------------------------------------------------------------------ */

#how-it-works .systems-row{
  display:flex;
  grid-template-columns:none;

  gap:14px;

  overflow-x:auto;
  overflow-y:hidden;

  scroll-snap-type:x mandatory;
  scroll-behavior:smooth;

  -webkit-overflow-scrolling:touch;
  overscroll-behavior-x:contain;

  scrollbar-width:none;

  padding:0 1px 6px;
  margin:0 0 32px;
}

#how-it-works .systems-row::-webkit-scrollbar{
  display:none;
}

#how-it-works .systems-card{
  flex:0 0 100%;
  min-width:100%;

  scroll-snap-align:start;
  scroll-snap-stop:always;

  border-radius:18px;
}


/* ------------------------------------------------------------------------
   Compact card internals
   ------------------------------------------------------------------------ */

#how-it-works .systems-card-head{
  padding:14px 16px;
  gap:10px;
}

#how-it-works .systems-card-icon{
  width:38px;
  height:38px;
}

#how-it-works .systems-card-icon svg{
  width:23px;
  height:23px;
}

#how-it-works .systems-card-head h3{
  font-size:15.5px;
}

#how-it-works .systems-items{
  padding:14px;
  gap:10px;
}

#how-it-works .systems-item{
  padding:13px 14px;
  gap:11px;
  border-radius:13px;
}

#how-it-works .systems-item .step-icon{
  width:35px;
  height:35px;
}

#how-it-works .systems-item h4{
  font-size:13.5px;
  line-height:1.3;
  margin-bottom:3px;
}

#how-it-works .systems-item p{
  font-size:12.25px;
  line-height:1.48;
}
/* How GAVP section-level mobile typography */

#how-it-works .how-gavp-intro h2{
  font-size:clamp(28px, 7.8vw, 32px);
  line-height:1.12;
}

#how-it-works .how-gavp-block > .section-head h2{
  font-size:clamp(25px, 7vw, 29px);
  line-height:1.15;
}

#how-it-works .how-gavp-block > .section-head .lede{
  font-size:14px;
  line-height:1.55;
}

#how-it-works .how-gavp-block > .section-head{
  margin-bottom:22px !important;
}

/* ------------------------------------------------------------------------
   CASE STUDIES — mobile tabbed case-study switcher
   ------------------------------------------------------------------------ */

#case-studies{
  padding-top:64px;
  padding-bottom:64px;
}

#case-studies .case-studies-head{
  display:block;
  margin-bottom:24px;
}

#case-studies .section-head{
  max-width:none !important;
}

#case-studies .section-head h2{
  font-size:clamp(29px, 8vw, 34px);
  line-height:1.12;
}

#case-studies .section-head .lede{
  font-size:15px;
  line-height:1.55;
  margin-top:12px;
}


/* ------------------------------------------------------------------------
   Health / Education controls
   ------------------------------------------------------------------------ */

#case-studies .case-tabs{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:4px;

  margin-top:24px;
  padding:4px;

  background:rgba(18,80,158,.08);
  border:1px solid rgba(18,80,158,.10);
  border-radius:999px;
}

#case-studies .case-tab{
  display:flex;
  align-items:center;
  justify-content:center;

  min-height:44px;
  padding:10px 12px;

  border:0;
  border-radius:999px;

  font-size:13px;
  line-height:1;
  text-align:center;

  color:var(--blue-700);
}

#case-studies .case-tab--active{
  background:var(--blue-700);
  color:var(--white);
  border-bottom-color:transparent;

  box-shadow:0 6px 16px -10px rgba(10,61,124,.6);
}

/* Give Education an orange selected state so sector identity remains obvious. */
#case-studies .case-tab[href="#case-rajasthan"].case-tab--active{
  background:#e17300;
}


/* ------------------------------------------------------------------------
   Only one case study occupies the mobile slot
   ------------------------------------------------------------------------ */

#case-studies .case-block{
  display:none;
  margin-bottom:0;
}

#case-studies .case-block.is-mobile-active{
  display:block;
}

/* Desktop connector between Bihar and Rajasthan has no purpose when only
   one case exists in the mobile slot. */
#case-studies .case-divider{
  display:none;
}

/* ------------------------------------------------------------------------
   Case-study hero — compact mobile treatment
   ------------------------------------------------------------------------ */

#case-studies .case-hero{
  grid-template-columns:1fr;

  margin-bottom:26px;

  border-radius:22px;
}

/* Remove asymmetric desktop corner treatment on mobile. */
#case-studies .case-hero--dark,
#case-studies .case-hero--light{
  border-radius:22px;
}

#case-studies .case-hero-copy{
  padding:22px 20px;
  gap:12px;
}

#case-studies .case-hero-tag--label{
  font-size:clamp(22px, 6.5vw, 26px);
  line-height:1.15;
}

#case-studies .case-hero-tagline{
  font-size:11.5px;
  line-height:1.45;
}

#case-studies .case-hero-copy p{
  font-size:13.5px;
  line-height:1.55;
}

#case-studies .case-hero-media{
  min-height:0;
  height:210px;
}

#case-studies .case-hero-media img{
  width:100%;
  height:100%;
  object-fit:cover;
}


/* Bihar badge */
#case-studies .case-hero-badge{
  padding:9px 12px;
  gap:9px;
  border-radius:13px;
}

#case-studies .case-hero-badge-icon{
  width:31px;
  height:31px;
}

#case-studies .case-hero-badge .num{
  font-size:18px;
}

#case-studies .case-hero-badge .lbl{
  font-size:9.5px;
}


/* Rajasthan inline facts */
#case-studies .case-hero-facts{
  gap:16px;
  flex-wrap:wrap;
}

#case-studies .case-hero-fact{
  gap:8px;
}

#case-studies .case-hero-fact-icon{
  width:32px;
  height:32px;
}

#case-studies .case-hero-fact strong{
  font-size:14px;
}

/* ------------------------------------------------------------------------
   Evidence cards
   ------------------------------------------------------------------------ */

#case-studies .case-subhead{
  font-size:20px;
  line-height:1.25;
  margin-bottom:16px;
}

#case-studies .case-study-grid{
  grid-template-columns:1fr;
  gap:12px;
}

#case-studies .case-stat{
  padding:18px 16px 17px;
  border-radius:16px;
}

#case-studies .case-stat-icon{
  width:34px;
  height:34px;
  margin-bottom:10px;
}

#case-studies .case-stat-icon svg{
  width:17px;
  height:17px;
}

#case-studies .case-stat-index{
  top:14px;
  right:15px;
  font-size:11px;
}

#case-studies .case-stat .num{
  font-size:26px;
}

#case-studies .case-stat .num-static{
  font-size:18px;
}

#case-studies .case-stat p{
  margin-top:7px;
  font-size:12.5px;
  line-height:1.48;
}

#case-studies .case-closing{
  margin-top:14px;

  padding:18px 16px;
  border-radius:16px;
}

#case-studies .case-closing p{
  font-size:13.5px;
  line-height:1.45;
}

/* ------------------------------------------------------------------------
   IMPACT STORIES — vertical mobile accordion
   ------------------------------------------------------------------------ */

#impact-stories{
  padding:64px 0;
}

#impact-stories .impact-stories-layout{
  display:block;
}

#impact-stories .impact-stories-intro{
  max-width:none;
  padding-top:0;
  margin-bottom:28px;
}

#impact-stories .impact-stories-intro h2{
  font-size:clamp(29px, 8vw, 34px);
  line-height:1.12;
  margin:12px 0 14px;
}

#impact-stories .impact-stories-intro .lede{
  font-size:14px;
  line-height:1.55;
}


/* ------------------------------------------------------------------------
   Stories become one vertical column
   ------------------------------------------------------------------------ */

#impact-stories .impact-panels{
  display:flex;
  flex-direction:column;

  width:100%;
  gap:14px;
}

#impact-stories .impact-panel{
  flex:none;
  width:100%;
  min-width:0;

  height:auto;
  min-height:0;

  display:block;

  border-radius:18px;
  overflow:hidden;

  background:var(--blue-950);

  transition:
    background-color .3s ease,
    box-shadow .3s ease;
}


/* ------------------------------------------------------------------------
   Story image
   ------------------------------------------------------------------------ */

#impact-stories .impact-panel-media{
  flex:none;
  height:150px;

  transition:height .35s var(--ease-premium);
}

#impact-stories .impact-panel.is-active .impact-panel-media{
  height:190px;
}

#impact-stories .impact-panel-media img{
  width:100%;
  height:100%;
  object-fit:cover;
}


/* ------------------------------------------------------------------------
   Story body
   ------------------------------------------------------------------------ */

#impact-stories .impact-panel-body{
  position:relative;
  flex:none;

  min-height:0;

  padding:16px 18px;
}


/* The title stays visible in both collapsed and expanded states. */
#impact-stories .impact-panel-heading-collapsed{
  position:static;

  opacity:1;

  padding-right:38px;

  font-size:17px;
  line-height:1.3;

  color:var(--white);

  transition:color .25s ease;
}

#impact-stories .impact-panel.is-active
.impact-panel-heading-collapsed{
  opacity:1;
  color:var(--blue-900);
}


/* The desktop expanded version contains the title again.
   On mobile the existing collapsed title remains visible, so don't duplicate it. */
#impact-stories .impact-panel-content-expanded h3{
  display:none;
}


/* ------------------------------------------------------------------------
   Expandable story information
   ------------------------------------------------------------------------ */

#impact-stories .impact-panel-content-expanded{
  position:static;

  max-height:0;
  overflow:hidden;

  opacity:0;
  transform:translateY(-4px);

  pointer-events:none;

  transition:
    max-height .38s var(--ease-premium),
    opacity .22s ease,
    transform .3s ease;

  color:var(--ink-900);
}

#impact-stories .impact-panel.is-active
.impact-panel-content-expanded{
  max-height:240px;

  opacity:1;
  transform:translateY(0);

  pointer-events:auto;
}

#impact-stories .impact-panel-content-expanded p{
  margin:12px 0 16px;

  font-size:13.5px;
  line-height:1.55;

  color:var(--ink-600);
}


/* ------------------------------------------------------------------------
   Read More becomes an obvious secondary action.
   The whole card no longer behaves as the external-link trigger on mobile.
   ------------------------------------------------------------------------ */

#impact-stories .impact-panel-cta{
  display:inline-flex;
  align-items:center;
  gap:7px;

  padding:9px 13px;

  border-radius:999px;

  background:var(--blue-700);
  color:var(--white);

  font-size:12.5px;
  font-weight:700;
}

#impact-stories .impact-panel-cta svg{
  width:14px;
  height:14px;
}


/* ------------------------------------------------------------------------
   + / − affordance
   Makes it obvious that the story card can be expanded.
   ------------------------------------------------------------------------ */

#impact-stories .impact-panel-body::after{
  content:'+';

  position:absolute;
  top:11px;
  right:17px;

  font-family:var(--font-body);
  font-size:26px;
  font-weight:400;
  line-height:1;

  color:var(--white);

  transition:
    color .25s ease,
    transform .3s ease;
}

#impact-stories .impact-panel.is-active
.impact-panel-body::after{
  content:'−';
  color:var(--blue-700);
}


/* ------------------------------------------------------------------------
   Expanded card
   ------------------------------------------------------------------------ */

#impact-stories .impact-panel.is-active{
  background:var(--white);

  box-shadow:
    0 18px 36px -20px rgba(7,44,90,.55);
}


/* Override the desktop crossfade timing for the mobile accordion. */
#impact-stories .impact-panel.is-active
.impact-panel-heading-collapsed{
  transition:color .25s ease;
}

/* ------------------------------------------------------------------------
   CONTACT — robust full-width mobile image

   The desktop image uses aspect-ratio, but on mobile we explicitly size the
   media row so Safari/in-app browsers cannot resolve it narrower than the card.
   ------------------------------------------------------------------------ */

#contact .closing-card{
  grid-template-columns:minmax(0, 1fr);
  width:100%;
}

#contact .closing-card-media{
  order:-1;

  width:100%;
  min-width:0;
  max-width:none;
  justify-self:stretch;

  /* Use a definite responsive height rather than aspect-ratio on phones. */
  height:clamp(200px, 56vw, 280px);
  min-height:0;
  aspect-ratio:auto;

  position:relative;
  overflow:hidden;
}

#contact .closing-card-media img{
  position:absolute;
  inset:0;

  width:100%;
  height:100%;
  max-width:none;

  display:block;
  object-fit:cover;
  object-position:center;
}

}

/* ==========================================================================
   IMPACT STORY MODAL
   Concept A — in-page long-form story reader

   Desktop:
   - centred editorial modal
   - image on the left
   - long-form story on the right

   Mobile:
   - near/full-screen story reader
   - single-column image + narrative
   ========================================================================== */


/* --------------------------------------------------------------------------
   Modal shell
   -------------------------------------------------------------------------- */

.impact-modal[hidden]{
  display:none !important;
}

.impact-modal{
  position:fixed;
  inset:0;

  z-index:100000;

  display:flex;
  align-items:center;
  justify-content:center;

  padding:24px;

  opacity:0;
  visibility:hidden;
  pointer-events:none;

  transition:
    opacity .28s ease,
    visibility .28s ease;
}


/*
 * Added by JS in Sprint D.
 * Keeping visibility state separate from `hidden` lets us animate the
 * modal open/closed rather than making it appear abruptly.
 */
.impact-modal.is-open{
  opacity:1;
  visibility:visible;
  pointer-events:auto;
}


/* --------------------------------------------------------------------------
   Backdrop
   -------------------------------------------------------------------------- */

.impact-modal-backdrop{
  position:absolute;
  inset:0;

  background:rgba(7,44,90,.80);

  -webkit-backdrop-filter:blur(8px);
  backdrop-filter:blur(8px);

  opacity:0;

  transition:opacity .32s ease;
}

.impact-modal.is-open .impact-modal-backdrop{
  opacity:1;
}


/* --------------------------------------------------------------------------
   Desktop dialog
   -------------------------------------------------------------------------- */

.impact-modal-dialog{
  position:relative;
  z-index:1;

  width:min(1120px, 100%);
  max-height:min(760px, calc(100dvh - 48px));

  overflow:hidden;

  background:var(--white);

  border:1px solid rgba(18,80,158,.12);
  border-radius:28px;

  box-shadow:
    0 34px 90px rgba(7,44,90,.32),
    0 8px 28px rgba(7,44,90,.16);

  opacity:0;
  transform:translateY(20px) scale(.985);

  transition:
    opacity .34s ease,
    transform .45s var(--ease-premium);
}

.impact-modal.is-open .impact-modal-dialog{
  opacity:1;
  transform:translateY(0) scale(1);
}


/* --------------------------------------------------------------------------
   Close button
   -------------------------------------------------------------------------- */

.impact-modal-close{
  position:absolute;
  top:18px;
  right:18px;

  z-index:4;

  width:44px;
  height:44px;

  display:inline-flex;
  align-items:center;
  justify-content:center;

  padding:0;

  border:1px solid rgba(18,80,158,.12);
  border-radius:50%;

  background:rgba(255,255,255,.94);
  color:var(--blue-900);

  font-size:27px;
  font-weight:400;
  line-height:1;

  box-shadow:0 8px 24px rgba(7,44,90,.12);

  transition:
    background-color .2s ease,
    color .2s ease,
    transform .2s ease;
}

.impact-modal-close:hover{
  background:var(--blue-900);
  color:var(--white);

  transform:rotate(4deg);
}


/* --------------------------------------------------------------------------
   Two-column editorial layout
   -------------------------------------------------------------------------- */

.impact-modal-layout{
  display:grid;
  grid-template-columns:minmax(320px, .9fr) minmax(0, 1.1fr);

  min-height:560px;
  max-height:min(760px, calc(100dvh - 48px));
}


/* --------------------------------------------------------------------------
   Story image
   -------------------------------------------------------------------------- */

.impact-modal-media{
  position:relative;

  min-width:0;
  min-height:0;

  overflow:hidden;

  background:var(--blue-100);
}

.impact-modal-media::after{
  content:"";

  position:absolute;
  inset:0;

  pointer-events:none;

  background:
    linear-gradient(
      180deg,
      rgba(7,44,90,0) 55%,
      rgba(7,44,90,.16) 100%
    );
}

.impact-modal-media img{
  width:100%;
  height:100%;

  min-height:560px;

  display:block;

  object-fit:cover;
  object-position:center;
}


/* --------------------------------------------------------------------------
   Story copy
   -------------------------------------------------------------------------- */

.impact-modal-copy{
  min-width:0;

  display:flex;
  flex-direction:column;

  overflow-y:auto;
  overscroll-behavior:contain;

  padding:
    clamp(46px, 5vw, 68px)
    clamp(34px, 5vw, 64px)
    34px;
}


/* Small editorial label above title */
.impact-modal-eyebrow{
  margin-bottom:12px;

  font-family:var(--font-body);
  font-size:12px;
  font-weight:700;

  letter-spacing:.10em;
  text-transform:uppercase;

  color:var(--orange-text);
}


.impact-modal-copy h2{
  max-width:16ch;

  margin:0 0 24px;

  font-size:clamp(28px, 3vw, 40px);
  line-height:1.12;

  color:var(--blue-900);
}


/* --------------------------------------------------------------------------
   WYSIWYG story content
   -------------------------------------------------------------------------- */

.impact-modal-content{
  max-width:62ch;

  color:var(--ink-900);

  font-size:15px;
  line-height:1.75;
}

.impact-modal-content p{
  margin:0 0 18px;
}

.impact-modal-content p:last-child{
  margin-bottom:0;
}


/* Give future WYSIWYG headings a sensible hierarchy */
.impact-modal-content h3,
.impact-modal-content h4{
  margin:28px 0 12px;

  color:var(--blue-900);
}

.impact-modal-content h3{
  font-size:21px;
}

.impact-modal-content h4{
  font-size:17px;
}


/*
 * Global site CSS removes list bullets, so explicitly restore them
 * inside long-form editorial content.
 */
.impact-modal-content ul{
  margin:16px 0 20px;
  padding-left:22px;

  list-style:disc;
}

.impact-modal-content ol{
  margin:16px 0 20px;
  padding-left:22px;

  list-style:decimal;
}

.impact-modal-content li{
  margin-bottom:8px;
}


/* Links that might be added through the WYSIWYG editor */
.impact-modal-content a{
  color:var(--blue-700);

  text-decoration:underline;
  text-decoration-thickness:1px;
  text-underline-offset:3px;
}


/* Optional quote styling if client content uses blockquotes later */
.impact-modal-content blockquote{
  margin:26px 0;

  padding:4px 0 4px 18px;

  border-left:3px solid var(--orange-600);

  color:var(--blue-900);

  font-family:var(--font-head);
  font-size:18px;
  line-height:1.5;
}


/* --------------------------------------------------------------------------
   Previous / Next navigation
   -------------------------------------------------------------------------- */

.impact-modal-navigation{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:16px;

  margin-top:auto;
  padding-top:32px;
}


.impact-modal-nav{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  gap:9px;

  min-height:42px;

  padding:10px 15px;

  border:1px solid rgba(18,80,158,.20);
  border-radius:999px;

  background:transparent;
  color:var(--blue-700);

  font-size:13px;
  font-weight:700;

  transition:
    background-color .2s ease,
    border-color .2s ease,
    color .2s ease,
    transform .2s ease;
}


.impact-modal-nav:hover{
  background:var(--blue-700);
  border-color:var(--blue-700);

  color:var(--white);
}


.impact-modal-prev:hover{
  transform:translateX(-2px);
}

.impact-modal-next:hover{
  transform:translateX(2px);
}


/* --------------------------------------------------------------------------
   Scroll lock
   Added / removed by JS in Sprint D.
   -------------------------------------------------------------------------- */

body.impact-modal-open{
  overflow:hidden;
}


/* ==========================================================================
   IMPACT STORY MODAL — MOBILE
   ========================================================================== */

@media (max-width:767px){

  .impact-modal{
    align-items:stretch;

    padding:0;
  }


  /*
   * On phones this becomes a full-screen story reader rather than a small
   * floating popup. This gives longer stories enough room to breathe.
   */
  .impact-modal-dialog{
    width:100%;
    height:100vh;
    height:100dvh;

    max-height:none;

    overflow-y:auto;
    overscroll-behavior:contain;

    border:0;
    border-radius:0;

    box-shadow:none;

    transform:translateY(24px);
  }

  .impact-modal.is-open .impact-modal-dialog{
    transform:translateY(0);
  }


  .impact-modal-layout{
    display:block;

    min-height:100%;
    max-height:none;
  }


  /* ---------------------------------------------------------------
     Mobile close button

     Sticky means the close control stays reachable even after the
     reader has scrolled deep into a long story.
     --------------------------------------------------------------- */

  .impact-modal-close{
    position:sticky;

    top:12px;

    margin:
      12px
      12px
      -56px
      auto;

    width:42px;
    height:42px;

    display:flex;

    background:rgba(255,255,255,.94);
  }


  /* ---------------------------------------------------------------
     Mobile story image
     --------------------------------------------------------------- */

  .impact-modal-media{
    width:100%;
    height:clamp(230px, 68vw, 330px);

    min-height:0;
  }

  .impact-modal-media img{
    width:100%;
    height:100%;

    min-height:0;

    object-fit:cover;
  }


  /* ---------------------------------------------------------------
     Mobile copy
     --------------------------------------------------------------- */

  .impact-modal-copy{
    display:block;

    overflow:visible;

    padding:
      28px
      20px
      calc(28px + env(safe-area-inset-bottom));
  }


  .impact-modal-eyebrow{
    margin-bottom:10px;

    font-size:11px;
  }


  .impact-modal-copy h2{
    max-width:none;

    margin-bottom:20px;

    padding-right:10px;

    font-size:clamp(26px, 7.4vw, 32px);
    line-height:1.15;
  }


  .impact-modal-content{
    max-width:none;

    font-size:14.5px;
    line-height:1.7;
  }


  .impact-modal-content p{
    margin-bottom:17px;
  }


  .impact-modal-content blockquote{
    margin:22px 0;

    font-size:17px;
  }


  /* ---------------------------------------------------------------
     Mobile Previous / Next
     --------------------------------------------------------------- */

  .impact-modal-navigation{
    gap:10px;

    margin-top:30px;
    padding-top:22px;

    border-top:1px solid rgba(18,80,158,.12);
  }


  .impact-modal-nav{
    flex:1;

    min-width:0;

    padding:11px 12px;

    font-size:12px;
  }

}


/* ==========================================================================
   IMPACT STORY MODAL — SMALL PHONE SAFETY
   ========================================================================== */

@media (max-width:380px){

  .impact-modal-copy{
    padding-left:17px;
    padding-right:17px;
  }

  .impact-modal-navigation{
    flex-direction:column;
  }

  .impact-modal-nav{
    width:100%;
  }

}


/* ==========================================================================
   IMPACT STORY MODAL — REDUCED MOTION
   ========================================================================== */

@media (prefers-reduced-motion:reduce){

  .impact-modal,
  .impact-modal-backdrop,
  .impact-modal-dialog,
  .impact-modal-close,
  .impact-modal-nav{
    transition:none !important;
  }

}

/* ==========================================================================
   IMPACT STORY MODAL — DESKTOP REFINEMENT

   Desktop-only override.
   Mobile <= 767px remains completely untouched.

   Goals:
   - show the complete story image rather than aggressively cropping it
   - give long-form copy more horizontal room
   - allow longer stories to scroll gracefully
   - keep Previous / Next navigation permanently accessible
   ========================================================================== */

@media (min-width:1024px){

  /* ------------------------------------------------------------------------
     Use more of the available desktop viewport
     ------------------------------------------------------------------------ */

  .impact-modal{
    padding:24px;
  }

  .impact-modal-dialog{
    width:min(1320px, calc(100vw - 48px));

    /*
     * Use almost the full available screen height rather than imposing
     * the previous 760px ceiling.
     */
    height:min(820px, calc(100dvh - 48px));
    max-height:calc(100dvh - 48px);

    overflow:hidden;
  }


  /* ------------------------------------------------------------------------
     More balanced editorial split

     46% gives photographs enough room to retain their composition,
     while 54% gives the narrative considerably more line length.
     ------------------------------------------------------------------------ */

  .impact-modal-layout{
    grid-template-columns:
      minmax(0, 46%)
      minmax(0, 54%);

    width:100%;
    height:100%;

    min-height:0;
    max-height:none;
  }


  /* ------------------------------------------------------------------------
     IMAGE — preserve the complete photograph
     ------------------------------------------------------------------------ */

  .impact-modal-media{
    min-width:0;
    min-height:0;

    display:flex;
    align-items:center;
    justify-content:center;

    /*
     * Intentional frame around photographs whose proportions do not
     * exactly match the modal column.
     */
    padding:24px;

    background:var(--blue-950);

    overflow:hidden;
  }


  /*
   * The previous dark fade was useful with edge-to-edge cropped imagery.
   * It isn't necessary once the image is intentionally framed.
   */
  .impact-modal-media::after{
    display:none;
  }


  .impact-modal-media img{
    width:100%;
    height:100%;

    min-height:0;
    max-height:100%;

    display:block;

    /*
     * Critical change:
     * never sacrifice parts of the photograph just to fill the column.
     */
    object-fit:contain;

    /*
     * JS currently carries the card crop position into the modal.
     * That was useful with object-fit:cover, but in the full-image reader
     * we want the complete photograph centred.
     */
    object-position:center !important;

    border-radius:18px;
  }


  /* ------------------------------------------------------------------------
     STORY COLUMN
     ------------------------------------------------------------------------ */

  .impact-modal-copy{
    min-width:0;
    min-height:0;

    height:100%;

    /*
     * This is now the ONLY independently scrolling region on desktop.
     */
    overflow-y:auto;
    overscroll-behavior:contain;

    scrollbar-gutter:stable;

    padding:
      42px
      clamp(42px, 4vw, 58px)
      0;
  }


  /*
   * Wider copy means the title no longer needs to wrap into three or
   * four short lines as often.
   */
  .impact-modal-copy h2{
    max-width:none;

    margin-bottom:20px;

    padding-right:42px;

    font-size:clamp(30px, 2.5vw, 38px);
    line-height:1.12;
  }


  .impact-modal-eyebrow{
    margin-bottom:10px;
  }


  /* ------------------------------------------------------------------------
     LONG-FORM STORY CONTENT
     ------------------------------------------------------------------------ */

  .impact-modal-content{
    max-width:72ch;

    font-size:14.5px;
    line-height:1.65;
  }


  .impact-modal-content p{
    margin-bottom:16px;
  }


  .impact-modal-content h3{
    margin:22px 0 10px;

    font-size:19px;
    line-height:1.3;
  }


  .impact-modal-content h4{
    margin:20px 0 9px;
  }


  .impact-modal-content blockquote{
    margin:20px 0;

    font-size:16px;
    line-height:1.55;
  }


  /* ------------------------------------------------------------------------
     NAVIGATION — permanently accessible

     If a future story is genuinely long, the narrative can scroll,
     but users never lose access to Previous / Next.
     ------------------------------------------------------------------------ */

  .impact-modal-navigation{
    position:sticky;
    bottom:0;
    z-index:3;

    margin-top:28px;

    padding:
      18px
      0
      24px;

    background:var(--white);

    border-top:1px solid rgba(18,80,158,.10);
  }


  /* Slightly stronger visual affordance on desktop */
  .impact-modal-nav{
    min-height:42px;

    padding:10px 16px;
  }


  /* ------------------------------------------------------------------------
     Make desktop overflow visually understandable.

     A subtle scrollbar is better than making content appear mysteriously
     clipped when a particularly long story exceeds the available viewport.
     ------------------------------------------------------------------------ */

  .impact-modal-copy{
    scrollbar-width:thin;
    scrollbar-color:
      rgba(18,80,158,.30)
      transparent;
  }

  .impact-modal-copy::-webkit-scrollbar{
    width:6px;
  }

  .impact-modal-copy::-webkit-scrollbar-track{
    background:transparent;
  }

  .impact-modal-copy::-webkit-scrollbar-thumb{
    background:rgba(18,80,158,.26);

    border-radius:999px;
  }

}

/* ==========================================================================
   IMPACT STORY MODAL — DESKTOP IMAGE MODE TESTING

   Switch between the two treatments by changing ONE class on .impact-modal:

   impact-modal--framed  = 4:3 editorial crop
   impact-modal--fill    = image fills entire left panel

   Mobile <= 767px is untouched.
   ========================================================================== */

@media (min-width:1024px){

  /* ------------------------------------------------------------------------
     Shared desktop image-column foundation
     ------------------------------------------------------------------------ */

  .impact-modal-media{
    min-width:0;
    min-height:0;

    overflow:hidden;

    background:var(--blue-950);
  }

  .impact-modal-media::after{
    display:none;
  }


  /* ========================================================================
     MODE A — 4:3 FRAMED IMAGE

     Gives every story a consistent editorial image shape.
     ======================================================================== */

  .impact-modal--framed .impact-modal-media{
    display:flex;
    align-items:center;
    justify-content:center;

    padding:clamp(24px, 2.5vw, 38px);
  }

  .impact-modal--framed .impact-modal-media img{
    width:100%;
    height:auto;

    max-width:620px;

    aspect-ratio:4 / 3;

    object-fit:cover;

    /*
     * Do NOT use !important here.
     * JS already carries each card's focal point into the modal.
     */
    object-position:center;

    border-radius:18px;

    box-shadow:0 18px 44px rgba(0,0,0,.18);
  }


  /* ========================================================================
     MODE B — FULL LEFT-PANEL IMAGE

     Image completely occupies the navy/image side.
     Cropping is intentional and controlled through object-position.
     ======================================================================== */

  .impact-modal--fill .impact-modal-media{
    display:block;

    padding:0;
  }

  .impact-modal--fill .impact-modal-media img{
    width:100%;
    height:100%;

    min-height:0;
    max-height:none;

    display:block;

    object-fit:cover;

    /*
     * JS-provided focal position can override this for individual stories.
     */
    object-position:center;

    border-radius:0;
    box-shadow:none;
  }

}

/* ==========================================================================
   UTILITY MODALS
   Shared shell for:
   - About GAVP video
   - Press & Outreach

   Kept completely separate from the Impact Story modal.
   ========================================================================== */


/* --------------------------------------------------------------------------
   Disabled states
   -------------------------------------------------------------------------- */

.play-button:disabled{
  opacity:.55;
  cursor:not-allowed;
}

.resource-link-card--press{
  width:100%;

  font:inherit;
  text-align:left;

  cursor:pointer;
}

.resource-link-card--press:disabled{
  opacity:.62;
  cursor:default;
}

.resource-link-card--press:disabled:hover{
  transform:none;

  border-color:rgba(18,80,158,.12);
  box-shadow:none;
}


/* Single resource card rather than old 2-column grid */
.resource-links--single{
  grid-template-columns:1fr;

  max-width:560px;
}


/* ==========================================================================
   Utility modal shell
   ========================================================================== */

.utility-modal[hidden]{
  display:none !important;
}

.utility-modal{
  position:fixed;
  inset:0;

  z-index:100010;

  display:flex;
  align-items:center;
  justify-content:center;

  padding:24px;

  opacity:0;
  visibility:hidden;
  pointer-events:none;

  transition:
    opacity .26s ease,
    visibility .26s ease;
}

.utility-modal.is-open{
  opacity:1;
  visibility:visible;
  pointer-events:auto;
}


.utility-modal-backdrop{
  position:absolute;
  inset:0;

  background:rgba(7,44,90,.84);

  -webkit-backdrop-filter:blur(8px);
  backdrop-filter:blur(8px);

  opacity:0;

  transition:opacity .28s ease;
}

.utility-modal.is-open .utility-modal-backdrop{
  opacity:1;
}


/* --------------------------------------------------------------------------
   Shared dialog
   -------------------------------------------------------------------------- */

.utility-modal-dialog{
  position:relative;
  z-index:1;

  width:min(880px, 100%);
  max-height:calc(100dvh - 48px);

  overflow:hidden;

  background:var(--white);

  border:1px solid rgba(18,80,158,.12);
  border-radius:26px;

  box-shadow:0 32px 90px rgba(7,44,90,.34);

  opacity:0;
  transform:translateY(18px) scale(.985);

  transition:
    opacity .32s ease,
    transform .42s var(--ease-premium);
}

.utility-modal.is-open .utility-modal-dialog{
  opacity:1;
  transform:translateY(0) scale(1);
}


/* --------------------------------------------------------------------------
   Close
   -------------------------------------------------------------------------- */

.utility-modal-close{
  position:absolute;

  top:16px;
  right:16px;

  z-index:4;

  width:44px;
  height:44px;

  display:flex;
  align-items:center;
  justify-content:center;

  padding:0;

  border:1px solid rgba(18,80,158,.14);
  border-radius:50%;

  background:rgba(255,255,255,.95);
  color:var(--blue-900);

  font-size:27px;
  line-height:1;

  box-shadow:0 8px 24px rgba(7,44,90,.12);
}

.utility-modal-close:hover{
  background:var(--blue-900);
  color:var(--white);
}


/* ==========================================================================
   VIDEO MODAL
   ========================================================================== */

.utility-modal-dialog--video{
  width:min(1080px, 100%);

  background:#000;
}

.utility-video-wrap{
  width:100%;

  aspect-ratio:16 / 9;

  background:#000;
}

.utility-video{
  width:100%;
  height:100%;

  display:block;

  object-fit:contain;
}


/* ==========================================================================
   PRESS MODAL
   ========================================================================== */

.utility-modal-dialog--press{
  width:min(760px, 100%);

  max-height:min(760px, calc(100dvh - 48px));

  overflow-y:auto;
}

.press-modal-copy{
  padding:
    clamp(42px, 5vw, 58px)
    clamp(28px, 5vw, 52px)
    38px;
}

.utility-modal-eyebrow{
  margin-bottom:9px;

  font-size:12px;
  font-weight:700;

  letter-spacing:.1em;
  text-transform:uppercase;

  color:var(--orange-text);
}

.press-modal-copy h2{
  margin:0 48px 28px 0;

  font-size:clamp(28px, 3vw, 38px);

  color:var(--blue-900);
}


/* --------------------------------------------------------------------------
   Press list
   -------------------------------------------------------------------------- */

.press-list{
  display:flex;
  flex-direction:column;

  border-top:1px solid rgba(18,80,158,.12);
}

.press-list-item{
  display:flex;
  align-items:center;
  justify-content:space-between;

  gap:24px;

  padding:19px 2px;

  border-bottom:1px solid rgba(18,80,158,.12);

  transition:
    color .2s ease,
    padding-left .2s ease;
}

.press-list-item:hover{
  padding-left:7px;
}

.press-list-item-title{
  color:var(--ink-900);

  font-size:14.5px;
  font-weight:600;
  line-height:1.45;
}

.press-list-item-action{
  display:inline-flex;
  align-items:center;

  gap:7px;

  flex:none;

  color:var(--blue-700);

  font-size:12.5px;
  font-weight:700;
}

.press-list-item-action svg{
  width:15px;
  height:15px;
}


/* ==========================================================================
   Utility modals — MOBILE
   ========================================================================== */

@media (max-width:767px){

  .utility-modal{
    padding:12px;
  }


  .utility-modal-dialog{
    max-height:calc(100dvh - 24px);

    border-radius:20px;
  }


  /* Video remains landscape within available phone width */
  .utility-modal-dialog--video{
    width:100%;
  }


  .utility-modal-close{
    width:40px;
    height:40px;

    top:10px;
    right:10px;

    font-size:24px;
  }


  .press-modal-copy{
    padding:
      48px
      20px
      calc(26px + env(safe-area-inset-bottom));
  }


  .press-modal-copy h2{
    margin-right:36px;

    font-size:28px;
  }


  .press-list-item{
    align-items:flex-start;

    gap:14px;

    padding:17px 0;
  }


  .press-list-item-title{
    font-size:13.5px;
  }


  .press-list-item-action{
    font-size:11.5px;
  }

}


/* --------------------------------------------------------------------------
   Body scroll lock
   -------------------------------------------------------------------------- */

body.utility-modal-open{
  overflow:hidden;
}


/* --------------------------------------------------------------------------
   Reduced motion
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion:reduce){

  .utility-modal,
  .utility-modal-backdrop,
  .utility-modal-dialog,
  .press-list-item{
    transition:none !important;
  }

}
/* Hero CTA anchor destinations — clear the sticky navbar */
#challenge,
#impact-stories{
  scroll-margin-top:100px;
}

/* Bridge PNG inside centre badge */
.gcw-bridge-badge--image {
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  padding: 0;
}

.gcw-bridge-badge--image img {
  display: block;
  width: 76%;
  height: auto;
  object-fit: contain;
}