@charset "UTF-8";

/* Google Fonts used by the landing page (Oswald for the HEARTS·HANDS·CLT
   wordmark, Fraunces for serif headlines, Inter for body/UI). Loaded here
   instead of in <head> so this stylesheet is self-sufficient — header_base.php
   does not need to know which fonts the landing page wants. Other pages
   harmlessly receive the same fonts (cached by the browser thereafter). */
@import url('https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@400;500;600;700&family=Fraunces:opsz,wght@9..144,300;9..144,400;9..144,500;9..144,600;9..144,700;9..144,900&family=Inter:wght@300;400;500;600;700&family=Oswald:wght@200;300;400;500;600;700&display=swap');

/* Font smoothing — critical on dark backgrounds and large screens/projectors.
   antialiased renders thinner, crisper strokes vs the default subpixel mode. */
html {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  background: #111c34; /* site's dark navy — prevents white flash if CSS or JS is slow */
  /* Reserve the vertical scrollbar's gutter for the entire page lifecycle. <html>
     is the viewport scroller (document.scrollingElement), so this holds the
     layout width constant even while the landing page toggles body overflow from
     hidden (closed doors) to auto (doors open). Without it, on classic-scrollbar
     desktops/TVs the scrollbar appeared at door-open and narrowed the viewport
     ~11px; since the tagline hero is centered, that re-centered the flying-in
     halves a few px right as the words populated — a fast horizontal shake just
     before the cross drew. Unlike overflow-x, scrollbar-gutter does NOT create a
     scroll container, so the sticky header is unaffected (verified). No-op for
     overlay scrollbars (mobile/trackpad), which never occupied layout space. */
  scrollbar-gutter: stable;
}

/* ==========================================================================
   Hearts to Hands CLT — Main-Site Stylesheet
   --------------------------------------------------------------------------
   Public marketing site styles only (home, about, contact, privacy, terms).
   Layered on top of styles-base.css (which provides typography, glass cards,
   portal-header, hero-sub, etc.). Anything section-specific lives HERE.
   ========================================================================== */

/* ── Policy pages (privacy, terms) ───────────────────────────────────────── */

.policy-section { margin-bottom: 2.5rem; }
.policy-section h2 {
  font-size: 1.1rem; font-weight: 700;
  color: var(--h2h-gold, #D8A85A);
  border-bottom: 1px solid rgba(216,168,90,.20);
  padding-bottom: .5rem; margin-bottom: 1rem;
}
.policy-section p,
.policy-section li {
  font-size: .92rem; line-height: 1.75;
  color: rgba(233,238,247,.80);
}
.policy-section ul { padding-left: 1.25rem; }
.policy-section li { margin-bottom: .35rem; }

.policy-intro {
  background: rgba(216,168,90,.06);
  border: 1px solid rgba(216,168,90,.18);
  border-radius: 10px;
  padding: 1.25rem 1.5rem;
  margin-bottom: 2rem;
  font-size: .88rem; line-height: 1.7;
  color: rgba(233,238,247,.75);
}

.policy-meta {
  font-size: .78rem;
  color: rgba(233,238,247,.40);
  border-top: 1px solid rgba(255,255,255,.14);
  padding-top: 1.5rem; margin-top: 2.5rem;
}

.section-main .policy-section a,
.section-main .policy-intro a,
.section-main .policy-meta a { color: var(--h2h-gold, #D8A85A); }
.section-main .policy-section a:hover,
.section-main .policy-intro a:hover,
.section-main .policy-meta a:hover { color: #f5dfa0; }

/* ── Quill-generated DB content (admin-editable docs) ────────────────────── */

.ql-db-content { color: rgba(233,238,247,.82); font-size: .92rem; line-height: 1.75; }
.ql-db-content h2 {
  font-size: 1.05rem; font-weight: 700;
  color: var(--h2h-gold, #D8A85A);
  border-bottom: 1px solid rgba(216,168,90,.20);
  padding-bottom: .5rem; margin: 2rem 0 1rem;
}
.ql-db-content h3 {
  font-size: .95rem; font-weight: 700;
  color: rgba(233,238,247,.90);
  margin: 1.5rem 0 .75rem;
}
.ql-db-content p { margin-bottom: .85rem; }
.ql-db-content ul,
.ql-db-content ol { padding-left: 1.35rem; margin-bottom: .85rem; }
.ql-db-content li { margin-bottom: .3rem; }
.ql-db-content a { color: var(--h2h-gold, #D8A85A); }
.ql-db-content strong { color: rgba(233,238,247,.95); }

/* ── Terms-specific: SMS box + keyword pills ─────────────────────────────── */

.sms-box {
  background: rgba(31,166,222,.06);
  border: 1px solid rgba(31,166,222,.22);
  border-radius: 10px;
  padding: 1.25rem 1.5rem;
  margin: 1.25rem 0;
}
.sms-box p,
.sms-box li {
  font-size: .88rem; line-height: 1.75;
  color: rgba(233,238,247,.80);
}
.sms-box ul { padding-left: 1.25rem; margin-bottom: 0; }

.keyword {
  display: inline-block;
  background: rgba(255,255,255,.10);
  border: 1px solid rgba(255,255,255,.20);
  border-radius: 6px;
  padding: 2px 10px;
  font-weight: 800;
  font-family: monospace;
  font-size: 1rem;
  color: #fff;
  letter-spacing: .04em;
}

/* ── Main-site footer ──────────────────────────────────────────────────────
   Footer styles moved to styles-base.css so the shared site footer
   (partials/footer_base.php) renders identically across main, fundraiser, and
   portal. See the ".main-footer" section in styles-base.css. */

/* ── Policy page heading (used in privacy/terms — consolidates the inline style) ── */

.policy-page-title {
  font-size: 1.5rem; font-weight: 800;
  color: #fff;
  margin-bottom: .35rem;
}
.policy-page-meta {
  font-size: .8rem;
  color: rgba(233,238,247,.40);
  margin-bottom: 2rem;
}
.policy-intro strong { color: var(--h2h-gold, #D8A85A); }

/* ── Reveal-on-scroll (fade + lift) ───────────────────────────────────── */
.reveal-on-scroll {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity .8s cubic-bezier(.22,.61,.36,1), transform .8s cubic-bezier(.22,.61,.36,1);
  will-change: opacity, transform;
}
.reveal-on-scroll.is-visible {
  opacity: 1;
  transform: translateY(0);
  /* Release the compositor layer once revealed — a lingering will-change:transform
     keeps the element on a GPU layer and renders its text slightly blurry on
     hi-dpi/large screens. */
  will-change: auto;
}
@media (prefers-reduced-motion: reduce) {
  .reveal-on-scroll { opacity: 1; transform: none; transition: none; }
}

/* ── Section: Home Hero (#home) ─────────────────────────────────────────── */
/* Tagline hero + supporting split panels + bible verse book rotator.
   No landing-wrap — panels bleed edge-to-edge. */
/* #home selector beats the alternating section-background rule (which uses the
   background shorthand and would otherwise wipe out this photo). */
#home.home-hero {
  padding: 0;
  position: relative;
  overflow: hidden;                 /* clip the slowly drifting skyline layer */
  /* Fill the viewport below the sticky header on first load. svh keeps it honest
     on phones (accounts for the browser address bar); the vh line is a fallback. */
  min-height: calc(100vh - 6rem);
  min-height: calc(100svh - 6rem);
  display: flex;
  flex-direction: column;
  background-color: #070b14;
}
/* Skyline + scrims on their own layer so the whole hero can drift (Ken Burns)
   indefinitely after the intro, without moving the text. The scrims keep the
   tagline legible; the slow scale/translate keeps the night skyline feeling alive. */
.home-hero-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  background-image:
    radial-gradient(120% 75% at 50% 16%, rgba(216,168,90,.08), transparent 60%),
    linear-gradient(180deg, rgba(7,11,20,.8) 0%, rgba(7,11,20,.56) 55%, rgba(7,11,20,.42) 100%),
    url('../images/main/charlotte-skyline-night-gray.jpg');
  background-repeat: no-repeat;
  background-position: center top, center, center bottom;
  background-size: cover, cover, cover;
  transform-origin: 50% 65%;
  animation: heroDrift 30s ease-in-out infinite alternate;
  will-change: transform;
}
/* Noticeable but calm: a slow zoom + vertical pan you can actually see over a few
   seconds. Base scale is generous so there's ample bleed for BOTH the drift swing
   AND the scroll-parallax offset (--hero-py) to move the image without ever
   exposing an edge. (Verified: ~120px top overhang covers parallax up to MAX.) */
@keyframes heroDrift {
  from { transform: scale(1.12) translateY(calc(1.6% + var(--hero-py, 0px))); }
  to   { transform: scale(1.21) translateY(calc(-2.0% + var(--hero-py, 0px))); }
}
/* Faint ambient "city lights" — a few tiny warm glints over the downtown towers
   that breathe slowly, so the skyline feels alive without disturbing the calm.
   Rides the same drift as the photo (it's a child of .home-hero-bg). */
.home-hero-bg::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    radial-gradient(circle 1.6px at 53% 29%, rgba(255,226,170,.95), transparent 100%),
    radial-gradient(circle 1.2px at 58% 25%, rgba(255,220,160,.9),  transparent 100%),
    radial-gradient(circle 1px   at 47% 33%, rgba(255,230,185,.9),  transparent 100%),
    radial-gradient(circle 1.4px at 62% 31%, rgba(255,224,168,.9),  transparent 100%),
    radial-gradient(circle 1px   at 50% 23%, rgba(255,228,178,.9),  transparent 100%);
  opacity: .14;
  animation: heroTwinkle 5.5s ease-in-out infinite;
}
@keyframes heroTwinkle { 0%, 100% { opacity: .12; } 50% { opacity: .46; } }
@media (prefers-reduced-motion: reduce) {
  .home-hero-bg::after { animation: none; opacity: .16; }
}
/* Content + the section accent line sit above the drifting skyline. */
#home.home-hero > .home-tagline-hero,
#home.home-hero > .home-lower { position: relative; z-index: 1; }
#home.home-hero::before { z-index: 2; }
@media (prefers-reduced-motion: reduce) {
  .home-hero-bg { animation: none; transform: none; }
}

/* ── Tagline hero: split-origin staggered reveal ─────────────────────────── */
.home-tagline-hero {
  text-align: center;
  /* Asymmetric vertical padding biases the centered block slightly DOWN toward
     optical center — dead-center left a heavy void of skyline above the cue and
     read top-heavy. The extra top padding settles the tagline+Why/How lower. */
  padding: clamp(4rem, 11vh, 8rem) 2rem 2rem;
  overflow: hidden;
  /* Take the available height and center the tagline + Why/How vertically so the
     hero reads as a full, balanced screen. */
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.home-tagline-row {
  /* Symmetric halves so the gap between the phrases lands dead-center on the
     spine (a centered flex row drifts off because the phrases differ in width). */
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: center;
}
.home-tl-left  { justify-self: end;   text-align: right; padding-right: clamp(1rem, 3vw, 2rem); }
.home-tl-right { justify-self: start; text-align: left;  padding-left:  clamp(1rem, 3vw, 2rem); }
@media (max-width: 760px) {
  .home-tagline-row { grid-template-columns: 1fr; }
  .home-tl-left, .home-tl-right { justify-self: center; text-align: center; padding: 0; }
}

/* "Hearts to Love." — flies in from the left */
.home-tl-left {
  font-family: 'Oswald', sans-serif;
  font-size: clamp(2.4rem, 6vw, 4.25rem);
  font-weight: 600;
  letter-spacing: .02em;
  color: rgba(255,255,255,.92);
  white-space: nowrap;
  opacity: 0;
  transform: translateX(-115px) scale(.94);
  will-change: transform, opacity, filter;
}

/* "Hands to Serve." — flies in from the right */
.home-tl-right {
  font-family: 'Oswald', sans-serif;
  font-size: clamp(2.4rem, 6vw, 4.25rem);
  font-weight: 600;
  letter-spacing: .02em;
  color: rgba(255,255,255,.92);
  white-space: nowrap;
  opacity: 0;
  transform: translateX(115px) scale(.94);
  will-change: transform, opacity, filter;
}

/* Cross = a tall gold SPINE dividing the hero into Hearts/Why (left) and
   Hands/How (right), crossed by a red→gold→blue ARM in the gap above Why/How.
   The spine lives in .home-tl-inner (content height: sentence-top → Why/How
   bottom) and draws itself from the center outward. */
.home-tl-inner { position: relative; width: 100%; max-width: 62.5rem; margin: 0 auto; }   /* 62.5rem = 1000px at the 16px base root: unchanged on phones/laptops/monitors, but grows with the site's large-screen root-size zoom (19px @2200px, 23px @3000px) so the two nowrap halves don't overflow their columns and collide at the spine on TV/4K. */
.home-tl-inner > .home-tagline-row,
.home-tl-inner > .home-why { position: relative; z-index: 1; } /* text above the spine */

.home-tl-spine {
  /* Top at the letter caps; bottom extends ~6rem below Why/How so the lower arm
     is ~2x the upper — a Latin cross, not a plus (measured: 2.1:1, ~90px above
     the scroll cue). Desktop only (hidden on mobile). */
  position: absolute; left: 50%; top: 1.4rem; bottom: -6rem;
  width: 3px;
  transform: translateX(-50%) scaleY(0);
  transform-origin: center;
  background: linear-gradient(to bottom,
    rgba(216,168,90,.95), rgba(216,168,90,1) 50%, rgba(216,168,90,.6));
  box-shadow: 0 0 18px rgba(216,168,90,.45), 0 0 6px rgba(216,168,90,.6);
  border-radius: 2px;
  z-index: 0;
}
/* Horizontal cross-arm — in the gap above Why/How, crossing the spine. */
.home-tl-cross {
  position: relative; z-index: 1;
  height: 2px;
  margin: 1.7rem auto 1.5rem;
  pointer-events: none;
}
.home-tl-cross-glow {
  position: absolute; left: 50%; top: 50%;
  width: 180px; height: 180px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle, rgba(216,168,90,.45), transparent 62%);
  opacity: 0;
}
.home-tl-cross-h {
  position: absolute; left: 50%; top: 50%;
  width: 200px; height: 3px;
  transform: translate(-50%, -50%) scaleX(0);
  transform-origin: center;
  border-radius: 2px;
  background: linear-gradient(90deg,
    rgba(206,17,38,0), #CE1126 16%, #D8A85A 50%, #1FA6DE 84%, rgba(31,166,222,0));
  box-shadow: 0 0 14px rgba(216,168,90,.35);
}

/* Reveal (a beat after doors open / on a skipped load): halves glide in slowly
   and meet, the union sparks, the spine draws from center, the arm crosses,
   then Why/How fade up. Slower so the welcome can't be missed. */
.home-tagline-hero.is-revealed .home-tl-left  { animation: htlLeft  1.2s cubic-bezier(.16,.84,.34,1) both; }
.home-tagline-hero.is-revealed .home-tl-right { animation: htlRight 1.2s cubic-bezier(.16,.84,.34,1) both; }
.home-tagline-hero.is-revealed .hs-red  { animation: htlSparkRed  1.3s ease 1.0s both; }
.home-tagline-hero.is-revealed .hs-blue { animation: htlSparkBlue 1.3s ease 1.0s both; }
.home-tagline-hero.is-revealed .home-tl-spine      { animation: htlSpine  .85s cubic-bezier(.22,.61,.36,1) 1.4s both; }
.home-tagline-hero.is-revealed .home-tl-cross-glow { animation: htlGlow 1.1s ease 1.55s both, glowBreath 7s ease-in-out 3s infinite; }
.home-tagline-hero.is-revealed .home-tl-cross-h    { animation: htlCrossH 1.3s cubic-bezier(.33,0,.2,1) 1.9s both; }
@keyframes htlSpine  { to { transform: translateX(-50%) scaleY(1); } }
@keyframes htlGlow   { 0% { opacity: 0; } 45% { opacity: 1; } 100% { opacity: 0; } }
/* After the intro flash fades, the cross glow breathes gently — the faith symbol
   quietly alive at the heart of the hero, indefinitely. */
@keyframes glowBreath { 0%, 100% { opacity: .12; } 50% { opacity: .42; } }
@keyframes htlCrossH { to { transform: translate(-50%, -50%) scaleX(1); } }
/* Reduced motion: show the finished hero immediately — no fly-in, no cross draw,
   no spark/glow. Visible regardless of .is-revealed so there's no blank wait. */
@media (prefers-reduced-motion: reduce) {
  .home-tl-left, .home-tl-right { animation: none !important; opacity: 1 !important; transform: none !important; }
  .home-tl-spine   { animation: none !important; transform: translateX(-50%) scaleY(1) !important; }
  .home-tl-cross-h { animation: none !important; transform: translate(-50%, -50%) scaleX(1) !important; }
  .home-tl-cross-glow { animation: none !important; opacity: 0 !important; }
  .home-why        { animation: none !important; opacity: 1 !important; transform: none !important; }
  .home-scroll-down { animation: none !important; opacity: 1 !important; transform: none !important; }
  .hs-red, .hs-blue { animation: none !important; }
}
/* Mobile: tagline + Why/How stack, so a central divider makes no sense — hide
   the spine and let the arm read as a simple horizontal divider. */
@media (max-width: 760px) {
  .home-tl-spine { display: none; }
  .home-tl-cross { margin: 1.3rem auto; }
  /* With the vertical spine gone on mobile, the arm is the ONLY brand mark left in
     the gap — so make it an intentional divider, not a faint hairline. A short,
     centered red→gold→blue rule with a soft gold glow, clearly deliberate. */
  .home-tl-cross-h {
    width: 132px; height: 3px;
    box-shadow: 0 0 12px rgba(216,168,90,.5);
    background: linear-gradient(90deg,
      var(--h2h-red, #CE1126) 0%, var(--h2h-gold, #D8A85A) 50%, var(--h2h-blue, #1FA6DE) 100%);
  }
  /* Portrait fix: the desktop bottom-anchor showed the dark foreground (no lit
     buildings) and the 90%-opaque top scrim crushed the upper skyline. So on
     phones: (1) anchor to the lit skyscraper band, (2) lift the scrim so the
     lights actually show while keeping text legible, (3) speed the drift a bit
     so the movement reads on the now-detailed area. */
  .home-hero-bg {
    background-image:
      radial-gradient(120% 70% at 50% 12%, rgba(216,168,90,.09), transparent 60%),
      linear-gradient(180deg, rgba(7,11,20,.64) 0%, rgba(7,11,20,.48) 48%, rgba(7,11,20,.82) 100%),
      url('../images/main/charlotte-skyline-night-gray.jpg');
    background-position: center top, center, center 26%;
    animation-duration: 22s;
  }
}

/* Hero why/how block + CTA pair — fade up just after the rule draws in.
   The two columns sit under the tagline halves: Why under "Hearts to Love",
   How under "Hands to Serve". */
.home-why { margin-top: 3rem; opacity: 0; position: relative; }   /* drop Why/How clear of the cross arm (≈64px gap, measured); opacity:0 so it doesn't flash visible on first paint before the reveal runs — matches .home-tl-left/right. Restored by .is-revealed animation and the reduced-motion override below. */
/* A soft localized scrim directly behind the Why/How copy so it never sinks into
   the lit skyscraper band of the skyline — two side pools (left/right column) that
   leave the center clear so the gold spine still reads, feathered to no box edge. */
.home-why::before {
  content: '';
  position: absolute;
  inset: -1.6rem -2rem;
  z-index: 0;
  background:
    radial-gradient(46% 92% at 24% 50%, rgba(7,11,20,.6), transparent 76%),
    radial-gradient(46% 92% at 76% 50%, rgba(7,11,20,.6), transparent 76%);
  pointer-events: none;
}
.home-why .ia-intro-col { position: relative; z-index: 1; }
.home-why .ia-intro-body { font-size: 1.05rem; color: rgba(240,244,250,.9); text-shadow: 0 1px 10px rgba(7,11,20,.95), 0 0 5px rgba(7,11,20,.7); }
/* Desktop legibility over the (now brighter) skyline + a tight dark halo that
   sharpens the red word's edges — pure red blooms on dark backgrounds (an optical
   effect more than the hex). The mobile block further below keeps its own
   stronger shadows. */
.home-tl-left, .home-tl-right { text-shadow: 0 2px 16px rgba(7,11,20,.5), 0 0 2px rgba(7,11,20,.5); }
.home-why .ia-intro-eyebrow { text-shadow: 0 1px 8px rgba(7,11,20,.7); }

/* Scroll cue hidden until the hero reveal finishes (body.hero-revealed), so it
   lands LAST instead of floating on an empty hero the instant the doors open. */
.home-scroll-down { opacity: 0; }
/* Ticks above Why/How removed — the growing red/blue line above carries the
   brand split. The eyebrows mirror the headline: WHY = Hearts-red (love), HOW =
   Hands-blue (serve), so the two columns read as the two halves of the brand idea
   instead of two identical gold labels. A touch more weight + tracking makes them
   feel intentional rather than a default eyebrow. */
.home-why .ia-intro-col { padding-top: 0; }
.home-why .ia-intro-col::before { display: none; }
.home-why .ia-intro-eyebrow { font-weight: 800; letter-spacing: .24em; }
.home-why .ia-intro-col--red  .ia-intro-eyebrow { color: var(--h2h-red, #CE1126); text-shadow: 0 0 14px rgba(0,0,0,.85), 0 1px 4px rgba(0,0,0,.8); }
.home-why .ia-intro-col--blue .ia-intro-eyebrow { color: var(--h2h-blue, #1FA6DE); }
.home-tagline-hero.is-revealed .home-why { animation: htlFadeUp .8s ease .3s both; }
body.hero-revealed .home-scroll-down { animation: htlFadeUp .8s ease .7s both; }
@keyframes htlFadeUp { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .home-tagline-hero.is-revealed .home-why { animation: none; }
}

/* Focus-in slide: each half flies in from its side, sharpening from a soft blur
   and settling from a slight scale — cinematic, not a flat slide. */
@keyframes htlLeft  {
  from { opacity: 0; transform: translateX(-115px) scale(.94); filter: blur(8px); }
  to   { opacity: 1; transform: translateX(0) scale(1);        filter: blur(0); }
}
@keyframes htlRight {
  from { opacity: 0; transform: translateX(115px) scale(.94);  filter: blur(8px); }
  to   { opacity: 1; transform: translateX(0) scale(1);        filter: blur(0); }
}
@keyframes htlSparkRed  { 0% { text-shadow: none; } 45% { text-shadow: 0 0 26px rgba(206,17,38,.8); }  100% { text-shadow: 0 0 0 rgba(206,17,38,0); } }
@keyframes htlSparkBlue { 0% { text-shadow: none; } 45% { text-shadow: 0 0 26px rgba(31,166,222,.8); } 100% { text-shadow: 0 0 0 rgba(31,166,222,0); } }

/* Brand red is #CE1126 (the --h2h-red token): a crisp "true" red chosen because
   the previous magenta-leaning red (#EF0037) bloomed on dark backgrounds and read
   hazy next to the blue. The hero just references the token. */
/* Keep the TRUE brand red on the hero; it sinks into the skyline only because the
   photo is busy, not because of the hue. A strong dark halo lifts it off the
   skyline so it reads on par with the blue — no pink/coral hue shift. */
.hs-red  { color: var(--h2h-red, #CE1126); text-shadow: 0 0 24px rgba(0,0,0,.9), 0 2px 7px rgba(0,0,0,.85), 0 0 3px rgba(0,0,0,.8); }
.hs-blue { color: var(--h2h-blue, #1FA6DE); }

/* ── Home lower (book rotator + ring CTA) ────────────────────────────────── */
.home-lower {
  max-width: 1100px;
  margin: 0 auto;
  padding: 2.5rem 2rem 4rem;
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* Homepage section sequence is carried by DOM order in index.php (hero → about →
   in-action → impact-band → mosaic → his-word → events → recaps → donate →
   contact → join). An earlier flex `order:` layer duplicated that sequence on a
   flex-column wrapper; it was redundant (DOM order already matched) and has been
   removed, so the DOM is the single source of truth for section order. */
/* Kill any horizontal scroll from full-bleed (100vw) sections interacting with
   the scrollbar — overflow-x:clip prevents the scroll WITHOUT establishing a new
   scroll container or forcing overflow-y (unlike `hidden`), so sticky + vertical
   scroll are unaffected. Also protects mobile from 100vw-bleed overflow.
   NOTE: do NOT add overflow-x to <html>. Doing so makes <html> a second scroll
   container that steals scrolling away from <body>; the sticky header then anchors
   to a body that no longer scrolls and slides off-screen for good. Mobile bleed
   overflow is contained at the source instead (see .partner-marquee). */
body.section-main { overflow-x: clip; }


/* ══ His Word, Our Call — ambient scripture frame ══════════════════════════
   The verse + photo pairings cross-fade slowly on their own, like a framed
   picture on a wall that quietly changes — no card outline, no dots, no arrows.
   A thin gold progress hairline is the only hint of motion. Sits on its own
   distinctly-dark contemplative band so it reads as a quiet pause. */
.verse-eyebrow {
  text-align: center;
  font-family: 'Oswald', sans-serif;
  font-size: .95rem; font-weight: 500;
  letter-spacing: .22em; text-transform: uppercase;
  color: rgba(216,168,90,.7);
  margin-bottom: clamp(1.5rem, 3vw, 2.5rem);
}
/* A quiet reflective pause — deliberately more compact than the proof sections
   around it (slightly tighter band padding + a smaller frame) so it reads as a
   breath, not a centerpiece. */
body.page-main-home #his-word {
  padding-block: clamp(2rem, 3.6vw, 3.4rem);   /* lighter than the proof sections — a breath, not a centerpiece */
  background:
    radial-gradient(125% 65% at 50% 0%, rgba(216,168,90,.13), transparent 55%),
    #0f1a33;   /* lighter panel + gold top-glow — part of the chapter system */
}

.verse-show { position: relative; max-width: 56rem; margin: 0 auto; }
.verse-stage {
  position: relative;
  height: clamp(240px, 27vw, 320px);
}
.vs-slide {
  position: absolute; inset: 0;
  display: grid; grid-template-columns: 1.05fr 1fr;
  gap: clamp(1.75rem, 4vw, 3.25rem); align-items: center;
  opacity: 0; transition: opacity 1.1s ease; pointer-events: none;
}
.vs-slide.is-active { opacity: 1; pointer-events: auto; }
.vs-photo {
  margin: 0; height: 100%; border-radius: 14px; overflow: hidden;
  box-shadow: 0 24px 56px rgba(0,0,0,.45);
}
.vs-photo img {
  width: 100%; height: 100%;
  object-fit: cover; object-position: center 32%; display: block;
  transform: scale(1.03);
  transition: transform 9s ease-out;
}
.vs-slide.is-active .vs-photo img { transform: scale(1.09); }  /* gentle ken-burns */
.vs-verse { text-align: center; padding: 0 clamp(1.4rem, 4vw, 2.6rem); position: relative; }
/* Paired oversized quotation marks framing the verse — open mark hugging the
   top-left, close mark the bottom-right — in faint white, like a pull-quote.
   Purely decorative; they sit behind the text. */
.vs-verse::before,
.vs-verse::after {
  position: absolute; font-family: Georgia, serif; line-height: 1;
  font-size: clamp(4rem, 9vw, 6.5rem);
  color: rgba(255,255,255,.10); z-index: 0; pointer-events: none;
}
.vs-verse::before { content: "\201C"; top: -.42em; left: -.06em; }
.vs-verse::after  { content: "\201D"; bottom: -.66em; right: -.04em; }
.vs-text, .vs-ref { position: relative; z-index: 1; }
.vs-text {
  font-family: 'Fraunces', Georgia, serif;
  font-style: italic; font-weight: 400;
  font-size: clamp(1.15rem, 1.85vw, 1.6rem);
  line-height: 1.5; color: #eef2f8; margin: 0 0 1rem;
}
.vs-ref {
  font-family: 'Oswald', sans-serif;
  font-style: normal; letter-spacing: .2em; text-transform: uppercase;
  color: #D8A85A; font-size: .85rem;
}
/* Toned down: a small centred tick that quietly fills, instead of a full-width
   bar sweeping across the section — keeps the ambient "time passing" cue without
   pulling focus from the verse. */
.verse-progress {
  max-width: 84px; margin: clamp(1.2rem, 2.6vw, 1.8rem) auto 0;
  height: 2px; border-radius: 2px; opacity: .8;
  background: rgba(216,168,90,.14); overflow: hidden;
}
.verse-progress span {
  display: block; height: 100%; width: 0;
  background: var(--h2h-gold, #D8A85A);
  animation: vsProgress 8000ms linear forwards;
}
.verse-show.is-paused .verse-progress span { animation-play-state: paused; }
@keyframes vsProgress { from { width: 0; } to { width: 100%; } }

@media (max-width: 720px) {
  .vs-slide { grid-template-columns: 1fr; grid-template-rows: 168px auto; gap: 1.1rem; align-content: center; }
  .verse-stage { height: auto; min-height: 330px; }
  .vs-text { font-size: clamp(1.15rem, 4.6vw, 1.45rem); }
}
@media (prefers-reduced-motion: reduce) {
  .vs-slide { transition: none; }
  .vs-photo img, .vs-slide.is-active .vs-photo img { transition: none; transform: none; }
  .verse-progress { display: none; }
}

/* ── "Our Story" ring button — pulsing, echoes the Enter door button ─────── */
.home-scroll-down { margin-top: 2.75rem; text-align: center; }

.home-enter-btn {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: .65rem;
  text-decoration: none;
}

.home-enter-label {
  font-size: .84rem;
  font-weight: 800;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: #D8A85A;
  transition: color .25s, text-shadow .25s;
  text-shadow: 0 0 14px rgba(216,168,90,.5), 0 1px 8px rgba(7,11,20,.8);
}

.home-enter-btn:hover .home-enter-label {
  color: #fff;
  text-shadow: 0 0 18px rgba(216,168,90,.8);
}

.home-enter-ring {
  width: 56px; height: 56px;
  border-radius: 50%;
  border: 2px solid var(--h2h-gold, #D8A85A);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #D8A85A;
  font-size: 1.05rem;
  position: relative;
  transition: border-color .25s, color .25s, box-shadow .25s, transform .25s;
  background: linear-gradient(135deg, rgba(216,168,90,.22), rgba(216,168,90,.08));
  backdrop-filter: blur(6px);
  box-shadow: 0 0 18px rgba(216,168,90,.45), inset 0 0 12px rgba(216,168,90,.16);
  animation: ringPulse 2.8s ease-in-out infinite;
}
@keyframes ringPulse {
  0%, 100% { box-shadow: 0 0 18px rgba(216,168,90,.45), inset 0 0 12px rgba(216,168,90,.16); }
  50%       { box-shadow: 0 0 32px rgba(216,168,90,.68), inset 0 0 16px rgba(216,168,90,.20); }
}
@media (prefers-reduced-motion: reduce) { .home-enter-ring, .home-enter-ring .ph { animation: none; } }

.home-enter-btn:hover .home-enter-ring {
  border-color: rgba(216,168,90,1);
  color: #fff;
  box-shadow: 0 0 36px rgba(216,168,90,.6), inset 0 0 18px rgba(216,168,90,.2);
  transform: scale(1.06);
}

/* Radar expanding rings removed — the persistent scroll cue reads calmer as a
   single glow-breathe. (The radar sweep suits the one-time Skip Intro beacon,
   which even stops after 30s; a cue that sits on screen the whole time at the
   hero shouldn't sweep continuously.) */

.home-enter-ring .ph {
  animation: homeChevBounce 1.8s ease-in-out infinite;
}

@keyframes homeChevBounce {
  0%, 100% { transform: translateY(0); }
  50%       { transform: translateY(3px); }
}

/* Responsive */

@media (max-width: 600px) {
  /* Tagline stacks; halves slide down/up instead of left/right. (Only `gap`
     does anything here — .home-tagline-row is display:grid at every width, so
     a `flex-direction: column` that used to sit on this line was dead: from an
     earlier iteration where this container was flex, before the 760px rule
     above switched it to a single grid column. Removed — the actual stacking
     comes from that grid-template-columns:1fr rule, not from this breakpoint.) */
  .home-tagline-row { gap: .85rem; }
  .home-tl-left  { transform: translateY(-22px); }
  .home-tl-right { transform: translateY( 22px); }
  .home-tagline-hero.is-revealed .home-tl-left  { animation-name: htlDown; }
  .home-tagline-hero.is-revealed .home-tl-right { animation-name: htlUp; }
  @keyframes htlDown { from { opacity: 0; transform: translateY(-22px); } to { opacity: 1; transform: none; } }
  @keyframes htlUp   { from { opacity: 0; transform: translateY( 22px); } to { opacity: 1; transform: none; } }
  .home-lower { padding: 3rem 1.25rem 4rem; }
}

/* Mobile hero fit: stacked content runs tall, so compress it (smaller tagline +
   Why/How text, tighter spacing) so the "See Us in Action" cue stays above the
   fold. Verified at 390x800 — cue ~61px above the fold, no horizontal overflow. */
@media (max-width: 760px) {
  .home-tl-left, .home-tl-right { font-size: 2rem; }
  .home-tagline-row { row-gap: .35rem; }             /* the two tagline lines sit tighter as one unit (~5px) */
  .home-tl-cross { margin: 1.5rem auto; }            /* symmetric — line sits equidistant between the tagline and the Why/How blurb */
  .home-tl-cross-glow { display: none; }             /* no cross on mobile → hide the stray glow pulse */
  /* generous space above the tagline (off the header) + reclaim elsewhere so the
     scroll cue still clears the phone's bottom address bar — verified 375→430px */
  .home-tagline-hero { padding-top: 2.2rem; padding-bottom: .5rem; }
  .home-scroll-down { margin-top: 1rem; }
  .home-why { margin-top: 0; gap: 1rem; }   /* gap below the divider now comes from .home-tl-cross only, keeping it equidistant */
  /* Lifting the hero scrim to show the skyline lights also reduced contrast
     behind the Why/How text — a dark text-shadow keeps it legible over the now
     brighter buildings without re-darkening the skyline. */
  .home-why .ia-intro-body { font-size: 1rem; line-height: 1.45; text-shadow: 0 1px 8px rgba(7,11,20,.98), 0 0 4px rgba(7,11,20,.98); }
  .home-why .ia-intro-eyebrow { text-shadow: 0 1px 6px rgba(7,11,20,.95); }
  .home-lower { padding: .5rem 1.25rem 1.4rem; }     /* cue clears (~25px at 393w, ~19px at 375w) */
  /* hero fills the visible viewport exactly (6rem ≈ the header above it) so the
     next section doesn't peek through below the cue */
  #home.home-hero { min-height: calc(100vh - 6rem); min-height: calc(100svh - 6rem); }
}

/* ── Section: About Us (#about) ────────────────────────────────────────── */
/* Section kicker — small, letter-spaced, sits under the rule. Contrasts with
   the big condensed title. (Reusable: .section-kicker on any section.) */
.section-kicker {
  font-family: 'DM Sans', sans-serif;
  font-weight: 700;
  font-size: .85rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  margin: 0 0 1.1rem;
}

/* Calm the per-section kickers to a single gold label — overrides the inline
   tri-color spans in the markup so every section header reads consistently. */
.section-kicker { color: var(--h2h-gold, #D8A85A); }
.section-kicker span { color: var(--h2h-gold, #D8A85A) !important; }

/* ── Our Story (origin) — single editorial column: intro → the Facebook post →
   the days that followed → the proof photo → the leap + coda + CTA. Reuses the
   shared .main-section-header--editorial and .story-leap components. Dark-stage
   section, so text colors are hardcoded light-on-dark (matching the rest of the
   dark landing sections), with brand tokens for the accents. ── */
/* Header sits BARE, directly in .landing-wrap — same grammar as In Action's
   header: no override, no wrapper. It gets the default centered editorial
   column width and is its own independent .reveal-on-scroll trigger, exactly
   like every other section. (Do NOT nest the header inside .about-body or
   any content column — a past regression shrank the header to a sidebar's
   width instead of the full editorial column every other section uses.
   Full-width header is non-negotiable.) */

/* Body — matches the standard editorial column width (same as In Action,
   Contact) via the shared .ed-col utility above, so the section's right edge
   lines up with the rest of the page. Reading text (intro/post/days) is
   capped narrower within it for line length — normal editorial practice, not
   dead space. The photo + leap stats + bookend are composed as a genuine
   two-column payoff (see .origin-payoff below) that uses the full width, so
   nothing is left empty. */
.about-body {
  position: relative;
  display: flex;
  flex-direction: column;
}

/* Post + days — now a real two-column pairing. With the post trimmed to 4
   comments, its rendered height (~408px) closely matches the days narrative
   (~374px), so this reads as an intentional composition rather than the
   mismatched pairing that was tried (and reverted) with the standfirst. */
.origin-story {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(1.75rem, 3.5vw, 3rem);
  align-items: start;
}
@media (max-width: 900px) {
  .origin-story { grid-template-columns: 1fr; }
}

.origin-post,
.origin-days { max-width: 44rem; margin-left: 0; margin-right: auto; }
@media (max-width: 960px) {
  .about-body { gap: 0; }
}

/* Intro standfirst — full width (the section's one lede statement before the
   layout narrows into the post/days columns below); brighter and a touch
   larger, opening clause reads as tracked caps in the brand gradient, echoing
   the section kicker bar. */
.origin-intro {
  margin: 0 0 2rem 0;
  text-align: left;
  color: rgba(233,238,247,.9);
  font-size: clamp(1.08rem, 1.35vw, 1.2rem);
  line-height: 1.65;
}
.origin-intro em { font-style: normal; color: var(--gold); }
.origin-lead-open {
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  font-size: 1.04em;
  background: linear-gradient(90deg, #CE1126 0%, #D8A85A 50%, #1FA6DE 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* The Facebook post — authentic structure tuned to the navy/gold stage rather
   than literal FB chrome. Rises in on scroll (replayed via .is-visible). */
.origin-post {
  max-width: 44rem;
  margin: 0 auto 0 0;   /* flush left with the rest of the reading column, not centered */
  background: rgba(17,28,52,.62);
  border: 1px solid rgba(216,168,90,.20);
  border-radius: 14px;
  box-shadow: 0 24px 60px rgba(0,0,0,.42);
  padding: 1.15rem 1.3rem;
  opacity: 0;
  transform: translateY(20px);
  transition: opacity .9s ease, transform .9s cubic-bezier(.22,.61,.36,1);
}
.about-body.is-visible .origin-post { opacity: 1; transform: none; }
.origin-post-head { display: flex; align-items: center; gap: .75rem; }
.origin-post-avatar {
  width: 46px; height: 46px;
  border-radius: 50%;
  overflow: hidden;
  flex: none;
  position: relative;
  box-shadow: 0 2px 10px rgba(0,0,0,.35);
  border: 1px solid rgba(255,255,255,.12);
}
.origin-post-avatar img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  /* The 2018 source crops Kendra's hairline at the top edge; a slight zoom toward
     the face lifts that flat cut just out of the circle and re-centers her — the
     honest fix, versus red padding that only stacked space above the cut. */
  transform: scale(1.12);
  transform-origin: 50% 42%;
}
.origin-post-avatar.is-mono {
  display: grid;
  place-items: center;
  background: linear-gradient(135deg, var(--red), var(--gold) 55%, var(--blue));
}
.origin-post-avatar.is-mono::after {
  content: attr(data-mono);
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 700; font-size: 1.15rem; color: #fff; letter-spacing: .02em;
}
.origin-post-who { min-width: 0; display: flex; flex-direction: column; }
.origin-post-name { font-weight: 700; color: #fff; font-size: 1rem; line-height: 1.25; }
.origin-post-tag { font-weight: 400; color: rgba(233,238,247,.66); }
.origin-post-tag b { font-weight: 700; color: #fff; }
.origin-post-meta { display: flex; align-items: center; gap: .4rem; font-size: .78rem; color: rgba(233,238,247,.42); margin-top: .1rem; }
.origin-post-body { margin: 1rem 0 .55rem; font-size: 1.04rem; line-height: 1.62; color: rgba(233,238,247,.94); }
.origin-heart { color: var(--red); }

.origin-eng {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  margin-top: 1.1rem; padding-top: .9rem;
  border-top: 1px solid rgba(233,238,247,.07);
  font-size: .9rem; color: rgba(233,238,247,.66);
}
.origin-eng-react { display: flex; align-items: center; gap: .5rem; }
.origin-rx { display: inline-flex; }
.origin-rx > span {
  width: 22px; height: 22px; border-radius: 50%;
  display: grid; place-items: center; font-size: .72rem;
  margin-left: -6px; border: 2px solid rgba(17,28,52,.9); color: #fff;
}
.origin-rx > span:first-child { margin-left: 0; }
.origin-rx-like { background: #1f6feb; }
.origin-rx-love { background: #e0245e; }
/* Spring-pop on the reaction pills each time support surges (JS toggles
   .is-bump as the count advances with the comment stream). Matches the pip
   spring so the whole post shares one "pop" language. */
.origin-rx { transform-origin: left center; }
.origin-rx.is-bump { animation: originRxBump .5s cubic-bezier(.3, 1.5, .5, 1); }
@keyframes originRxBump {
  0%   { transform: scale(1); }
  38%  { transform: scale(1.28); }
  100% { transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .origin-rx.is-bump { animation: none; }
}
.origin-eng-count b { color: rgba(233,238,247,.94); font-weight: 600; }

.origin-bar {
  display: flex;
  border-top: 1px solid rgba(233,238,247,.08);
  border-bottom: 1px solid rgba(233,238,247,.08);
  margin: .55rem -1.3rem 0;
}
.origin-bar span {
  flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  padding: .7rem .4rem; color: rgba(233,238,247,.66);
  font-weight: 600; font-size: .9rem;
}
.origin-bar i { font-size: 1.15rem; }

/* Comments — stream in one at a time (scripts-main.js), each with a heart pip
   and a collapsed "replied" indicator; a typing bubble sits between arrivals. */
.origin-cmts { padding: 1.1rem 0 0; }
.origin-cmt {
  display: flex; gap: .6rem; margin-top: .95rem;
  opacity: 0; filter: blur(3px); transform: translateY(10px);
  transition: opacity .6s ease, filter .6s ease, transform .6s cubic-bezier(.19,.68,.32,1);
}
.origin-cmt.is-in { opacity: 1; filter: blur(0); transform: none; }
.origin-cmt-av {
  width: 34px; height: 34px; border-radius: 50%; flex: none;
  display: grid; place-items: center;
  font-family: 'Barlow Condensed', sans-serif; font-weight: 600; font-size: .82rem;
  color: #fff; background: rgba(233,238,247,.14);
}
.origin-cmt-b { min-width: 0; display: flex; flex-direction: column; }
.origin-bubble { background: rgba(233,238,247,.05); border-radius: 2px 14px 14px 14px; padding: .55rem .85rem; align-self: flex-start; }
.origin-cmt-name { font-weight: 700; color: #fff; font-size: .86rem; display: block; }
.origin-cmt-q { font-size: .95rem; color: rgba(233,238,247,.94); line-height: 1.45; margin-top: .1rem; display: block; }
.origin-cmt-meta { display: flex; align-items: center; gap: 1rem; margin: .3rem 0 0 .85rem; font-size: .72rem; font-weight: 600; color: rgba(233,238,247,.42); }
.origin-cmt-rx {
  display: inline-flex; align-items: center; gap: .22rem;
  padding: .05rem .45rem .05rem .35rem; border-radius: 10px;
  background: rgba(224,36,94,.16); color: #ff86a6; font-weight: 700;
  opacity: 0; transform: scale(.4);
  transition: opacity .3s ease, transform .4s cubic-bezier(.3,1.5,.5,1);
}
.origin-cmt-rx.is-pop { opacity: 1; transform: scale(1); }
.origin-cmt-rx .origin-heart { font-size: .7rem; }
.origin-cmt-replies {
  display: flex; align-items: center; gap: .35rem;
  margin: .5rem 0 0 .85rem; font-size: .74rem; color: rgba(233,238,247,.42);
  opacity: 0; transform: translateY(-3px);
  transition: opacity .4s ease, transform .4s ease;
}
.origin-cmt-replies.is-pop { opacity: 1; transform: none; }
.origin-cmt-replies i { font-size: .9rem; color: rgba(216,168,90,.6); }
.origin-cmt-replies b { color: rgba(233,238,247,.66); font-weight: 600; }
.origin-typing {
  display: flex; gap: .6rem; margin-top: .95rem;
  opacity: 0; height: 0; overflow: hidden; transition: opacity .25s ease;
}
.origin-typing.is-on { opacity: 1; height: auto; }
.origin-bubble--typing { display: inline-flex; gap: 5px; align-items: center; padding: .7rem .95rem; }
.origin-bubble--typing span { width: 6px; height: 6px; border-radius: 50%; background: rgba(233,238,247,.42); animation: originBlink 1.3s infinite; }
.origin-bubble--typing span:nth-child(2) { animation-delay: .2s; }
.origin-bubble--typing span:nth-child(3) { animation-delay: .4s; }
@keyframes originBlink { 0%,60%,100% { opacity: .25; transform: translateY(0); } 30% { opacity: .9; transform: translateY(-3px); } }

/* The days that followed — sits beside the post in .origin-story now, so it
   starts flush with the top of that row (no top margin — the row itself
   already has proper spacing above it from the seam/post block before it). */
.origin-days { max-width: 42rem; margin: 0; }
.origin-days-eyebrow { display: flex; align-items: center; gap: 1.1rem; margin: 0 0 1.6rem; }
.origin-days-eyebrow::before, .origin-days-eyebrow::after { content: ""; height: 1px; flex: 1; background: linear-gradient(90deg, transparent, rgba(216,168,90,.28), transparent); }
.origin-days-eyebrow span { font-family: 'Oswald', sans-serif; font-size: .75rem; letter-spacing: .16em; text-transform: uppercase; color: rgba(233,238,247,.52); white-space: nowrap; }
.origin-days p { font-size: 1.04rem; line-height: 1.7; color: rgba(233,238,247,.78); margin: 0 0 1.1rem; }
.origin-days p b { color: rgba(233,238,247,.94); font-weight: 600; }
.origin-em { color: var(--gold); }
.origin-aside { font-family: 'Fraunces', Georgia, serif; font-style: italic; font-weight: 400; color: rgba(244,239,228,.82); }

/* Payoff — photo + leap stats + bookend as a genuine two-column composition,
   using the section's full width instead of stacking full-width blocks with
   dead space around centered text. Photo takes the wider column; the stats
   + bookend + CTA sit alongside it, left-aligned like the rest of the story
   (this is the next beat in the same reading column, not a floating
   pull-quote). */
.origin-payoff {
  display: grid;
  grid-template-columns: 1.3fr 1fr;
  gap: clamp(1.75rem, 3.5vw, 3rem);
  align-items: center;
  margin-top: 3rem;
}
.origin-payoff-side {
  display: flex;
  flex-direction: column;
}
@media (max-width: 900px) {
  .origin-payoff { grid-template-columns: 1fr; }
}

/* Proof — the first-mission group photo: the payoff. Grayscale develops into
   color on reveal (echoing the intro motif), with a smoked-glass caption bar
   the photo bleeds through. */
.origin-proof {
  max-width: 100%;
  margin: 0;
  position: relative;
  overflow: hidden;
  border-radius: 14px;
  border-top: 2px solid var(--gold);
  box-shadow: 0 24px 60px rgba(0,0,0,.42);
}
.origin-proof img {
  display: block; width: 100%; height: clamp(240px, 34vw, 440px); object-fit: cover; object-position: center 30%;
  filter: grayscale(1); transform: scale(1.05);
  transition: filter 3.6s ease .15s, transform 3.8s cubic-bezier(.22,.61,.36,1) .15s;
}
.origin-proof.is-developed img { filter: grayscale(0); transform: scale(1); }
.origin-proof.no-photo { display: none; }
.origin-proof-cap {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; align-items: center; gap: .5rem;
  padding: .85rem 1.2rem; margin: 0;
  color: rgba(244,239,228,.94);
  font-family: 'Oswald', sans-serif; font-size: .66rem; letter-spacing: .16em; text-transform: uppercase;
  background: linear-gradient(0deg, rgba(11,17,32,.66), rgba(11,17,32,.12) 72%, transparent);
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
}
.origin-proof-cap i { font-size: .85rem; color: var(--gold); }

/* Resolution — the bookend thesis, the reused .story-leap, the coda, the CTA. */
.origin-resolution { text-align: left; margin: 0; }   /* left-aligned in the payoff's side column — the next beat, not a floating pull-quote */
.origin-book {
  font-family: 'Fraunces', Georgia, serif; font-style: italic; font-weight: 400;
  font-size: clamp(1.3rem, 2.6vw, 1.7rem); line-height: 1.35; color: #fff; margin: 0 0 1.8rem;
}
.origin-book .origin-g { color: var(--gold); }
.origin-leap {
  margin-top: 0;
  justify-content: flex-start;
  padding-top: 1.5rem;
  border-top: 2px solid transparent;
  border-image: linear-gradient(90deg, #CE1126 0%, #D8A85A 50%, #1FA6DE 100%) 1;
}
.origin-coda {
  margin: 2rem 0 0;
  font-family: 'Fraunces', Georgia, serif; font-style: italic; font-weight: 300;
  font-size: clamp(1.16rem, 2.3vw, 1.44rem); line-height: 1.4; color: #f4f0e7; max-width: 28rem;
}
.origin-coda-cite {
  display: block; margin-top: .8rem;
  font-family: 'Oswald', sans-serif; font-style: normal; font-size: .74rem;
  letter-spacing: .12em; text-transform: uppercase; color: rgba(233,238,247,.52);
}
/* Dual close: the section has to sell BOTH doors — serving and giving — not
   just one. "Serve with us" stays the single gold pill (site rule: one primary
   .btn-gold, no second pill); "Prefer to give?" is a quiet underlined text
   link on the same line, opening the existing year-round donate modal in
   place (no navigation away from the story). */
.origin-cta-row { display: flex; align-items: center; gap: .55rem 1.4rem; flex-wrap: wrap; margin-top: 2.2rem; }
.origin-resolution .btn-gold { margin-top: 0; }
.origin-cta-alt {
  background: none; border: none; padding: 0 0 .15rem; cursor: pointer;
  display: inline-flex; align-items: center; gap: .35rem;
  font-family: 'Inter', sans-serif; font-size: .9rem; font-weight: 600;
  color: rgba(233,238,247,.68);
  border-bottom: 1px solid rgba(216,168,90,.35);
  transition: color .25s ease, border-color .25s ease;
}
.origin-cta-alt i { font-size: .85rem; transition: transform .25s ease; }
.origin-cta-alt:hover { color: var(--gold); border-color: var(--gold); }
.origin-cta-alt:hover i { transform: translateX(2px); }

@media (prefers-reduced-motion: reduce) {
  .origin-post, .origin-cmt { opacity: 1; filter: none; transform: none; transition: none; }
  .origin-proof img { filter: none; transform: none; transition: none; }
}
@media (max-width: 640px) {
  .origin-post { padding: 1rem 1.05rem; }
  .origin-bar { margin-left: -1.05rem; margin-right: -1.05rem; }
}

/* Founding-day "leap" — three bold stat blocks showing how that first mission
   grew (12 planned → 88 meals, 2 friends → 12 hearts, all in 3 days). The result
   numbers count up ONCE when scrolled into view (scripts-main.js, [data-leap]) and
   never reset, then settle into a gentle gold breath. This is the "took on a life
   of its own" moment, given real visual weight. */
.story-leap {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  justify-content: flex-start;
  gap: clamp(.85rem, 2vw, 1.5rem);
  margin: 0;   /* spacing handled by .origin-payoff-side's flow */
}
.story-leap-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .3rem;
  min-width: 0;
}
.story-leap-pair {
  display: inline-flex;
  align-items: baseline;
  justify-content: center;
  gap: .55rem;
}
.story-leap-from {
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 600;
  font-size: clamp(1.6rem, 3vw, 2.35rem);
  line-height: .95;
  color: rgba(233,238,247,.48);
  font-variant-numeric: tabular-nums;
}
.story-leap-arrow {
  align-self: center;
  font-size: clamp(1rem, 1.8vw, 1.35rem);
  color: rgba(216,168,90,.85);
}
.story-leap-num {
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 600;
  font-size: clamp(2rem, 3.6vw, 2.9rem);   /* smaller than the cumulative band — this is the spark, not the scoreboard */
  line-height: .95;
  color: var(--gold);
  font-variant-numeric: tabular-nums;
}
.story-leap-num.counted { animation: statGlow 4.5s ease-in-out 1s infinite; }
.story-leap-label {
  font-family: 'Oswald', sans-serif;
  text-transform: uppercase;
  letter-spacing: .1em;
  font-size: .82rem;
  font-weight: 500;
  color: rgba(233,238,247,.72);
}
.story-leap-div {
  align-self: center;
  width: 1px;
  height: 52px;
  background: linear-gradient(180deg, transparent, rgba(216,168,90,.4), transparent);
}
@keyframes statGlow {
  0%, 100% { text-shadow: 0 0 2px rgba(216,168,90,.15); }
  50%      { text-shadow: 0 0 16px rgba(216,168,90,.6); }
}
@media (prefers-reduced-motion: reduce) {
  .story-leap-num.counted { animation: none; }
}
@media (max-width: 600px) {
  .story-leap-div { display: none; }
  /* Equal 3-up grid instead of flex-wrap. flex-wrap let the third stat (the
     naturally widest "Days, start to finish" block) drop alone onto its own
     row while the first two paired up — an unbalanced 2+1 layout on every
     phone width. A grid with three equal columns keeps all three stats on
     one row always; a label wraps to a second line within its own column
     instead of the whole block reflowing. */
  .story-leap {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: .4rem .5rem;
    justify-items: center;
  }
  .story-leap-item { width: 100%; }
  .story-leap-pair { flex-wrap: wrap; justify-content: center; }
}

/* Partners — floating, no container, matches stats treatment */
/* Helping Hands — set apart from the story/stats as its own full-width band
   (subtle tint + top hairline spanning the viewport), so it reads as a distinct
   "our partners" strip rather than part of the About column. */
.partners-strip {
  position: relative;
  z-index: 0;
  margin-top: clamp(1.75rem, 3.5vw, 2.75rem);
  padding: clamp(1.25rem, 2.4vw, 1.85rem) 0;   /* slim "trusted by" strip, not a thick band */
  text-align: center;
}
.partners-strip::before {
  content: "";
  position: absolute;
  z-index: -1;
  top: 0;
  bottom: 0;
  left: calc(50% - 50vw);
  width: 100vw;
  /* A real tonal break: a flat lighter "shelf" across the whole band (not a
     gradient that fades to nothing at the edges) plus hairlines bright enough to
     actually see, and a thin inner highlight at the top for a polished edge. So
     it clearly reads as its own "our partners" strip, not part of About. */
  background: rgba(255,255,255,.06);
  border-top: 1px solid rgba(216,168,90,.22);
  border-bottom: 1px solid rgba(216,168,90,.22);
  /* Restrained warm glow on the top/bottom edges — a soft halo that ties into
     the site's glow motif without competing with the hero/impact focal points. */
  box-shadow: inset 0 1px 0 rgba(255,255,255,.06),
              0 0 26px rgba(216,168,90,.08);
}
.partners-strip-label {
  font-size: .76rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .2em;
  color: rgba(216,168,90,.7);
  margin-bottom: 1rem;
}
/* Partner count BELOW the strip — small, quiet. */
.partners-strip-count {
  margin-top: .9rem;
  font-size: .82rem;
  line-height: 1.5;
  letter-spacing: .03em;
  color: rgba(233,238,247,.5);
  font-variant-numeric: tabular-nums;
}
/* Draggable scroll carousel — auto-scrolls (JS), pauses on hover, and can be
   grabbed/flicked left or right. Native horizontal scroll, scrollbar hidden. */
.partner-marquee {
  position: relative;
  /* Full-bleed: the logo track fills the whole band edge-to-edge. The body's
     overflow-x:clip guard absorbs the 100vw so this never adds a scrollbar. */
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
  overflow-x: auto;
  overflow-y: hidden;
  /* Vertical padding gives logos clearance above and below for the hover lift.
     Without it the marquee clips at exactly logo-height and any translateY cuts off. */
  padding-top: 6px;
  padding-bottom: 6px;
  cursor: grab;
  touch-action: pan-y;
  scrollbar-width: none;
  -ms-overflow-style: none;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 4%, #000 96%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 4%, #000 96%, transparent);
}
.partner-marquee::-webkit-scrollbar { display: none; }   /* WebKit */
.partner-marquee.is-dragging { cursor: grabbing; }
.partner-track {
  display: flex;
  align-items: center;
  width: max-content;
  user-select: none;
}
/* No tile background. Each logo sits in a fixed, INVISIBLE box (so they stay
   evenly sized) and is recoloured to solid white at rest, then shows its full
   colour on hover. Upload BASIC transparent-background logos. */
/* Logos display in their natural colours on a clean white "chip" so mixed
   logos (white-background, transparent, or full-colour) look uniform and stay
   legible on the dark band. */
/* Each uploaded logo is already a finished, uniform white tile (logo centered
   on a white rounded-square background). So the carousel adds NO background and
   NO padding — it just shows the tile itself at a fixed height. Because every
   tile shares the same dimensions, they all render identically (works whether
   they're square or 300x180). */
.partner-marquee .partner-logo {
  flex: 0 0 auto;
  margin-right: 2.1rem;
  display: flex;
  align-items: center;
  background: transparent;
  padding: 0;
}
/* Anchor logos link to the partner's site; stop native image-drag from
   hijacking the carousel grab gesture. */
a.partner-logo { text-decoration: none; -webkit-user-drag: none; }

/* ── Partner logo treatment — transparent PNGs ──────────────────────────────
   brightness(0) invert(1) collapses every mark to a pure white silhouette so
   the strip reads as one unified force rather than 70 competing brand palettes.
   At rest: muted white, half-opacity. Hover: colour lifts fully in — the
   partner's real brand colours bloom out of the white, which feels like a
   reveal rather than just a colour change. */
.partner-marquee .partner-logo img {
  height: 46px;
  width: auto;
  max-width: 160px;   /* cap very wide logos so no single mark dominates the strip */
  display: block;
  /* grayscale strips colour for a unified at-rest look; brightness(1.8) lifts
     all marks to be visible on the dark section background regardless of
     whether the source logo uses light marks (Barker, Audi) or coloured marks
     (760 Craft Works). Light marks stay white; mid-range colour marks become
     readable silver tones. Hover removes the filter entirely to reveal the
     logo's real brand colours. */
  filter: grayscale(1) brightness(1.8);
  opacity: .65;
  transition: opacity .3s ease, filter .3s ease;
  -webkit-user-drag: none;
  user-select: none;
  pointer-events: none;
}
/* While the strip is hovered, non-active logos step back */
.partner-marquee:hover .partner-logo img { opacity: .25; filter: grayscale(1) brightness(1.4); }
/* Hovered logo: brightness lift so dark elements in dark-bg logos become readable.
   Can't do filter:none here — logos designed for light backgrounds have dark marks
   that vanish on the dark page. A brightness+saturation lift keeps hues recognisable
   while making everything visible. Once all logos are proper dark-bg assets, revert
   hover to filter:none for full colour reveal. */
.partner-marquee .partner-logo:hover img {
  filter: brightness(1.6) saturate(1.15);
  opacity: 1;
}

/* ── Fallback for any remaining white-background logos ───────────────────────
   If a logo file hasn't been replaced with a transparent PNG yet, add class
   partner-logo--legacy to that tile's wrapper. The grayscale+invert+screen
   chain makes the white background disappear on the dark page so it still
   reads as a white silhouette (slightly less sharp than a true transparent PNG
   but invisible difference at display height). Remove the class once the file
   is replaced. */
.partner-logo--legacy img {
  filter: grayscale(1) invert(1) brightness(1.05) !important;
  mix-blend-mode: screen;
}
.partner-marquee .partner-logo--legacy:hover img {
  filter: none !important;
  mix-blend-mode: normal;
}

.hero-wordmark {
  font-family: 'Bebas Neue', sans-serif;
  font-size: clamp(2.2rem, 7vw, 4rem);
  letter-spacing: .04em;
  background: linear-gradient(135deg, #D8A85A 0%, #f5dfa0 50%, #D8A85A 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  line-height: 1;
  margin-bottom: .75rem;
  text-shadow: 0 0 60px rgba(216,168,90,.30);
}
.hero-tagline {
  font-size: clamp(.95rem, 2vw, 1.15rem);
  color: rgba(233,238,247,.70);
  font-style: italic;
  margin-bottom: 2.25rem;
}
.hero-tagline strong { color: #CE1126; font-style: normal; }
.hero-tagline em { color: #1FA6DE; font-style: normal; }
.hero-cta {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  padding: .85rem 1.75rem;
  border-radius: 999px;
  font-weight: 700;
  font-size: .92rem;
  text-decoration: none;
  letter-spacing: .02em;
  transition: transform .15s ease, box-shadow .15s ease, background .15s ease;
  border: 1.5px solid;
  white-space: nowrap;
}
.hero-cta-primary {
  background: var(--h2h-gold, #D8A85A);
  color: #070b14;
  border-color: var(--h2h-gold, #D8A85A);
}
.hero-cta-primary:hover {
  background: #f5dfa0; border-color: #f5dfa0;
  transform: translateY(-2px);
  box-shadow: 0 8px 22px rgba(216,168,90,.30);
  color: #070b14;
}

/* Smaller on phones. */
@media (max-width: 600px) {
  .partner-marquee .partner-logo { margin-right: 1.5rem; }
  .partner-marquee .partner-logo img { height: 36px; max-width: 130px; }
}

/* ── Section: Donate (#donate) — three cards ──────────────────────────── */
/* ── Donate — three editorial rows, no card chrome ──────────────────────── */
/* Uses --ed-col-indent (the shared bar+gap token) so it tracks the header's title
   column at every viewport width instead of a hardcoded value. */
.donate-ways {
  display: grid;
  grid-template-columns: repeat(3, 1fr);   /* three EQUAL columns — Give gets no more room */
  gap: clamp(1rem, 3vw, 2.5rem);
  align-items: stretch;
  max-width: 60rem;                          /* centered action row */
  /* Positioned ABSOLUTE at a fixed % down the section so it scales identically
     at every viewport width (verified 76% clears the interaction at 1440 + 2560).
     RIGHT-aligned to the wrap's edge (matching the header's own left margin,
     verified 120px on both sides at 1440) so "Fuel the Mission" — the primary
     CTA — lands under the photo's emotional focal point (the hands + sandwich),
     giving the section a deliberate title→moment→action diagonal instead of a
     dead-centered row. Positioning does NOT use transform: this element also
     carries .reveal-on-scroll, whose .is-visible state sets
     `transform: translateY(0)` on scroll-reveal — transform is a single CSS
     property, so that unconditionally REPLACED (not merged with) an earlier
     translateX(-50%) centering trick, silently shoving the row to the right
     edge with zero margin. left:auto/right:0 + width:fit-content avoids
     transform entirely so the two animations can't collide. */
  position: absolute;
  left: auto;
  right: 0;
  top: 76%;                                   /* verified: gives the row real bottom breathing room (was only 35px to the section edge at 78%/52vw) while still clearing the interaction */
  /* NOT width:fit-content — verified broken here: CSS Grid intrinsic sizing
     treats 1fr tracks as wanting to expand toward any max-width cap during a
     fit-content/max-content calculation, so the row measured 944px (nearly the
     full 60rem max-width) instead of hugging the three buttons' actual content
     (measured 560px at 1440). Computed explicitly instead, mirroring the exact
     gap formula so it's correct at every viewport, not just the one it was
     eyeballed at: 3 buttons at their fixed 10rem min-width + 2 gaps. */
  width: calc(3 * 10rem + 2 * clamp(1rem, 3vw, 2.5rem));
  margin: 0;
}
/* Soft dark shelf tied to the button ROW (not the photo gradient) so labels +
   notes stay legible at ANY section height, while the photo above stays vivid.
   Radial fade on all edges = depth, not a hard-edged card. */
.donate-ways::before {
  content: "";
  position: absolute;
  inset: -1.5rem -2rem -2rem;
  z-index: -1;
  background: radial-gradient(120% 130% at 50% 55%, rgba(6,10,18,.72) 0%, rgba(6,10,18,.55) 45%, rgba(6,10,18,.2) 78%, rgba(6,10,18,0) 100%);
  pointer-events: none;
}
/* Full-bleed photo poster in NORMAL document flow. Anchored to the TOP of the
   photo so both heads (which sit near the top of the frame) are never cropped.
   Height tracks WIDTH (56.4vw) so the visible slice always runs from the caps
   down to the volunteer's knee — identical framing at desktop and large-TV
   widths (verified 1440 + 2560). background-size:100% auto sizes the image to
   the band width so that vertical slice is exact. Mobile overrides below switch
   to content-driven height + cover (a vw-height would collapse too short for the
   stacked buttons on a narrow screen). */
.donate--photo {
  position: relative; isolation: isolate; overflow: hidden;
  height: 56vw;                              /* slightly taller than the tightest crop — gives the button row real breathing room before the section ends, verified against the interaction staying clear */
}
/* The sitewide "chapter seam" (.landing-bleed::before, a center-growing accent
   line marking every section break) has z-index:auto, which normally paints
   fine over a flat background. Donate's photo layer is the first section with
   its own opaque z-index:0 background, and it happens to come later in DOM
   order at the same stacking level — so it was silently painting over the
   seam, hiding it. Lift the seam above the photo + wrap explicitly. */
.donate--photo::before { z-index: 2; }
.donate--photo > .landing-wrap { position: relative; z-index: 1; height: 100%; }  /* height:100% so .donate-ways's top:% resolves against the SECTION, not just the header's own content height */
.donate-photo-bg {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-size: 100% auto;
  background-position: center 6%;           /* small top margin above the caps; band height crops the bottom around the sandwich + blanket */
  background-repeat: no-repeat;
  opacity: .82;   /* same recipe as the join band (the reference) so the three photo bands read at a consistent brightness */
  filter: brightness(.62) saturate(1.02) contrast(1.02);
}
/* Directional scrim built to keep the CENTER-RIGHT interaction vivid: a vignette
   whose clear window sits over the faces + sandwich, a top band for the header,
   a bottom band for the button row, and a soft left veil. Re-tuned for the
   shorter 52vw crop (verified: sandwich + blanket now clear of the old dark
   ramp, which used to start at section-63% — right over the sandwich at this
   height). This is what makes the photo read as THE moment. */
.donate-photo-bg::after {
  content: ""; position: absolute; inset: 0;
  /* Lightened to match the join band's minimal scrim — the old heavy radial +
     .86/.9 vertical bands made this read much darker than join. Now just a light
     top band (header + tax line), a soft bottom band (button row), and a faint
     left veil; the photo stays vivid. */
  background:
    linear-gradient(180deg, rgba(6,10,18,.55) 0%, rgba(6,10,18,.18) 18%, rgba(6,10,18,0) 34%, rgba(6,10,18,0) 66%, rgba(6,10,18,.30) 82%, rgba(6,10,18,.55) 100%),
    linear-gradient(90deg, rgba(6,10,18,.28) 0%, rgba(6,10,18,.06) 30%, rgba(6,10,18,0) 55%);
}
/* Three uniform action buttons — centered content, equal columns. Typography
   (font, uppercase, weight, letter-spacing, radius) and transitions come from
   the SHARED button system (body.section-main :is(...) rules), same as every
   other CTA on the site — only layout mechanics + color/fill (the tier) are
   set here. Show Up + Meet a Need mirror the sitewide secondary gold-outline
   (.btn-gold); Give Now is the solid green primary. */
.donate-way {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: .55rem;
}
.donate-way-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  /* size matches the shared medium tier (.btn-gold / .cf-submit /
     .donate-way-cta--give already get this from body.section-main :is(...));
     added explicitly since plain .donate-way-cta isn't in that size list. */
  padding: .55rem 1.2rem;
  font-size: .84rem;
  min-height: 42px;
  min-width: 10rem;   /* uniform width across all three — measured to fit "Fuel the Mission" (the longest label) comfortably, so button size no longer varies with text length */
  /* secondary tier: same transparent gold-outline treatment as .btn-gold
     sitewide (body.section-main .btn-gold:not(.cf-submit)) — no bespoke fill. */
  background: transparent;
  color: var(--h2h-gold, #D8A85A);
  border: 1px solid rgba(216,168,90,.55);
}
.donate-way-cta:hover {
  background: rgba(216,168,90,.15);
  border-color: rgba(216,168,90,.75);
  color: var(--h2h-gold, #D8A85A);
}
.donate-way-cta--give {
  background: var(--h2h-green, #10B981);
  color: #062610;
  border: 1px solid var(--h2h-green, #10B981);
}
.donate-way-cta--give:hover {
  /* Brighten the green + keep the dark text (mirrors the gold primaries). */
  background: #34D399;
  border-color: #34D399;
  color: #062610;
}
/* Real substance under each button — one short factual line, quiet and small,
   so the row reads as three meaningful options rather than bare labels. */
.donate-way-note {
  margin: .1rem 0 0;
  font-size: .82rem;
  line-height: 1.4;
  color: rgba(233,238,247,.68);
  max-width: 18rem;
}
/* The dollar figure earns real presence — bold + green, same emphasis convention
   as the 100% in the promise line above, so it reads as a genuine stat, not
   just part of a quiet caption. */
.donate-way-note-stat {
  font-weight: 700;
  color: var(--h2h-green, #10B981);
  font-size: 1.05em;
}
@media (max-width: 720px) {
  /* Mobile: content drives height (the vw-height collapses too short here), and
     the photo covers behind. Both heads + the interaction still read at the top;
     buttons stack full-width below. Verified at 390px. */
  .donate--photo { height: auto; padding-top: 2rem; padding-bottom: 2.5rem; }
  .donate--photo .donate-photo-bg { background-size: cover; }
  /* Portrait crop puts the stacked buttons directly over the bright focal zone,
     so drop the vignette here — use a darker filter + a simpler, stronger
     vertical scrim that protects the whole stacked column while the photo reads. */
  .donate--photo .donate-photo-bg { filter: brightness(.62) saturate(1.02) contrast(1.02); }
  .donate--photo .donate-photo-bg::after {
    background: linear-gradient(180deg, rgba(6,10,18,.5) 0%, rgba(6,10,18,.22) 22%, rgba(6,10,18,.28) 45%, rgba(6,10,18,.5) 70%, rgba(6,10,18,.7) 100%);
  }
  /* Mobile is content-height, so the low desktop top-margin would leave a huge gap — reset it. */
  .donate-ways { position: static; left: auto; right: auto; width: auto; transform: none; grid-template-columns: 1fr; gap: 1.5rem; margin: clamp(1.5rem, 6vw, 2.5rem) auto 0; max-width: 22rem; }
  .donate-way-cta { width: 100%; }
}

.mission-list .date {
  font-size: .8rem;
  color: rgba(233,238,247,.50);
  white-space: nowrap;
}

/* ── Section: Contact (#contact) — info + form ───────────────────────── */
.contact-grid {
  display: grid;
  grid-template-columns: 1fr 1.4fr;
  gap: 2.5rem;
  max-width: 980px;
  margin: 0 auto;
}
@media (max-width: 768px) {
  .contact-grid { grid-template-columns: 1fr; gap: 2rem; }
}

/* ── Sticky header on scroll (main site) ──────────────────────────────── */
/* Contain the full-bleed header bar (the ::before below uses 100vw). 'clip'
   prevents a horizontal scrollbar WITHOUT turning the body into a scroll
   container — so it doesn't break position:sticky (unlike overflow:hidden). */
body.section-main { overflow-x: clip; }

/* Main site header sticky/frost/glide now lives in styles-base.css (.portal-header)
   as the shared, site-wide standard. Only homepage-specific nav bits remain below. */
/* Header content spine: the .h2h-shell wrapper (base CSS: full-width gutter band)
   plus the .portal-header row capped at --container and centered — so the logo's
   left edge and the nav/Give right edge land on the SAME vertical lines as every
   section's content and the footer. One unbroken spine. */
.h2h-shell--header { padding-block: 1.5rem; }   /* replaces Bootstrap .py-4; read by fitHeroBleed() */
.section-main .portal-header {
  max-width: var(--container);
  width: 100%;
  margin-inline: auto;
  box-sizing: border-box;
}
/* (transparent bar + scrolled-state frost/backdrop now in styles-base.css) */

/* ==========================================================================
   Landing Page — Door Experience + Site (index.php)
   --------------------------------------------------------------------------
   Cinematic intro with sliding doors over photo collages, then the main
   site is revealed underneath. Brand palette: red #CE1126, blue #1FA6DE,
   gold #D8A85A, black #444655.

   Scoping: post-door selectors that could collide with Bootstrap (.btn,
   .nav, etc.) or with global element styles (section) are prefixed with
   `body.page-landing` so they only apply on this page. Inner wrappers use
   `.landing-wrap` (not `.container`) to avoid colliding with any outer page
   wrapper. The door experience
   itself uses uniquely-named selectors (.door-*, .door-experience) so it
   needs no scoping.
   ========================================================================== */

:root {
  /* Official Hearts to Hands CLT brand palette */
  --red: #CE1126;
  --red-deep: #C8002E;
  --blue: #1FA6DE;
  --blue-deep: #0089BD;
  --gold: #D8A85A;
  --gold-warm: #C99860;
  --black: #444655;
  --black-deep: #2D2E38;

  --cream: #F7F2EA;
  --paper: #FBF8F2;
  --ink: #444655;
  --ink-soft: #5E6070;
  --ink-mute: #9094A1;
  --line: rgba(68,70,85,0.1);
}

* { margin: 0; padding: 0; box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  background:
    radial-gradient(ellipse 60% 50% at 0%   0%,   rgba(206,17,38,.07),  transparent),
    radial-gradient(ellipse 60% 50% at 100% 100%, rgba(31,166,222,.07), transparent),
    linear-gradient(180deg, #070b14, #0b1220);
  color: var(--text, #c8d0df);
  font-family: 'Inter', 'Plus Jakarta Sans', sans-serif;
  line-height: 1.6;
  /* overflow-x intentionally NOT redeclared here — base sets `overflow-x: clip`
     on body specifically so position:sticky on .portal-header keeps working.
     `hidden` used to live here and silently override that (same specificity,
     later in cascade), which is what broke the sticky nav on index.php. */
}

/* ========================================================
   THE DOOR EXPERIENCE
   Full-viewport intro that "opens" to reveal the site.
   ======================================================== */
.door-experience {
  position: fixed;
  inset: 0;
  z-index: 1025; /* above sticky nav (z-index:1020 from .section-main .portal-header) */
  overflow: hidden;
  background: #0F1015;
  /* Doors glide in and settle smoothly — no shudder/slam. */
}

/* When user enters, this class triggers the door-opening sequence */
.door-experience.opened {
  pointer-events: none;
  /* Drop the opaque backdrop the instant the doors start parting so the hero
     shows THROUGH the widening gap (doors opening onto the city) rather than
     the panels sliding off a dark void. The hero is painted and opacity:1
     behind by open time, so nothing flashes. */
  background: transparent;
}

.door-experience.gone {
  display: none;
}

/* The two doors */
.door {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 50%;
  overflow: hidden;
  /* No transform transition here. We previously had:
       transition: transform 1.4s cubic-bezier(.76,0,.24,1);
     but it conflicts with the slide-in animation's `forwards` fill —
     when control hands off from the animation to the held value,
     some WebKit builds briefly fire the transition, which reads as
     the doors bouncing back open a crack after they meet. The
     animation handles all the motion we need on its own. */
  will-change: transform;
}

.door-left {
  left: 0;
  width: calc(50% + 1px); /* overlap the seam by 1px so no dark gap shows once the gold seam fades */
  animation: doorSlideInLeft 1.0s cubic-bezier(0.45, 0, 0.55, 1) .1s both;
  /* Outer drop shadow + inner shadow (panel depth, like light catching a real
     surface) + a faint top edge highlight. */
  box-shadow:
    30px 0 80px rgba(0,0,0,0.5),
    inset 0 0 90px rgba(0,0,0,0.32),
    inset 0 2px 0 rgba(255,255,255,0.06);
  /* Brand red gradient — dark at outer edge, peaks mid-way, then dark
     again at the seam (right edge) so no bright red bleeds through
     sub-pixel gaps between the two door panels. */
  background:
    radial-gradient(ellipse 70% 45% at 85% 20%, rgba(255,150,150,0.24) 0%, transparent 65%),
    linear-gradient(to right, #2D0008 0%, #8B001C 35%, #CE1126 65%, #2D0008 100%);
}

.door-right {
  right: 0;
  animation: doorSlideInRight 1.0s cubic-bezier(0.45, 0, 0.55, 1) .1s both;
  box-shadow:
    -30px 0 80px rgba(0,0,0,0.5),
    inset 0 0 90px rgba(0,0,0,0.32),
    inset 0 2px 0 rgba(255,255,255,0.06);
  /* Brand blue gradient — dark at outer edge, peaks mid-way, then dark
     again at the seam (left edge, since gradient is to-left) so no
     bright blue bleeds through at the center join. */
  background:
    radial-gradient(ellipse 70% 45% at 15% 20%, rgba(140,225,255,0.24) 0%, transparent 65%),
    linear-gradient(to left, #001524 0%, #003D5C 35%, #1FA6DE 65%, #001524 100%);
}

@keyframes doorSlideInLeft {
  0% {
    transform: translateX(-110%);
    filter: brightness(0.7);
  }
  100% {
    transform: translateX(0);
    filter: brightness(1);
  }
}

@keyframes doorSlideInRight {
  0% {
    transform: translateX(110%);
    filter: brightness(0.7);
  }
  100% {
    transform: translateX(0);
    filter: brightness(1);
  }
}

/* When doors open - exact reverse of entrance */
.door-experience.opened .door-left {
  animation: doorSlideOutLeft 1.4s cubic-bezier(.64,0,.78,0) forwards;
}

.door-experience.opened .door-right {
  animation: doorSlideOutRight 1.4s cubic-bezier(.64,0,.78,0) forwards;
}

@keyframes doorSlideOutLeft {
  0% {
    transform: translateX(0);
    filter: brightness(1);
  }
  100% {
    transform: translateX(-110%);
    filter: brightness(0.7);
  }
}

@keyframes doorSlideOutRight {
  0% {
    transform: translateX(0);
    filter: brightness(1);
  }
  100% {
    transform: translateX(110%);
    filter: brightness(0.7);
  }
}

/* ── Photo mosaic grid ───────────────────────────────────────────────
   Red/blue collage photos fill each door in a tight grid.
   JS fitDoorGrid() sets grid-template-columns/rows so cells are
   exact square px units that fill the panel with no gaps.
   Photos start grayscale; revealDoorColors() adds .cell-revealed
   per column, sweeping from the center seam outward, synced with
   the wordmark trace animations.                                    */
.door-image {
  /* display: none guarantees photos are never painted during the door
     slide-in animation, even on cache hits. JS (runPhotoWave) switches this to
     display: grid when the photo wave starts — timed off the wordmark settling,
     not a fixed delay — then each photo fades in individually via its own
     h2hWavePop animation (see the wave rules below), not a container-level fade. */
  display: none;
  position: absolute;
  inset: 0;
  z-index: 1;
  /* grid-template-columns and grid-template-rows set by JS */
  overflow: hidden;
  opacity: 0;
  transition: opacity 0.8s ease;
  /* Near-black background so any sub-pixel gaps between grid cells bleed
     dark rather than the red/blue door gradient behind the grid. */
  background: #0d0d0d;
}

.door-image img {
  /* Explicit width/height set by JS (cellSize×cellSize). min-width/height:0
     prevents replaced elements from overflowing their grid cells. */
  min-width: 0;
  min-height: 0;
  object-fit: cover;
  object-position: center;
  display: block;
  filter: grayscale(1) brightness(0.60) blur(1px);
  transition: none; /* all transitions managed inline by JS */
  will-change: transform; /* parallax via JS mousemove */
  outline: none; /* belt-and-suspenders: prevents any browser UA default outline */
  /* No border at load — brand-colored border is added by JS only after a
     cell has been revealed via bloom (see doSwap in scripts-main.js). */
}

.door-image img.cell-revealed {
  filter: grayscale(1) brightness(0.9); /* dignified B&W — color is saved for the reveal when doors open */
  box-shadow: none;
  /* Stay above unrevealed photos so a new bloom next to a revealed
     photo doesn't slide underneath it. */
  position: relative;
  z-index: 2;
}

/* ── Photo wave ──────────────────────────────────────────────────────────
   Color photos pop in over the city. Driven by per-cell CSS animation-delay
   (--cellDelay, set by JS) and GPU-cheap props only (opacity + transform), so
   it stays smooth across a dense grid. Each lands with its red/blue outline. */
.door-experience.wave .door-image      { display: grid; opacity: 1; background: transparent; gap: 0; } /* tight mosaic — no gaps between photos */
/* On open, keep the photos so the doors carry them out cleanly (no black flash). */
.door-experience.wave.opened .door-image { opacity: 1; transition: none; }
/* Keep the photos fully visible as the doors slide open — they ride out ON the
   doors (no revert to the bare skyline). The shared .opened rule sets
   animation:none, which would otherwise drop these back to their pre-animation
   opacity:0, so we pin opacity/transform/border here. */
.door-experience.wave.opened .door-image img {
  opacity: 1;
  transform: none;
  outline-color: var(--bc);
}
.door-experience.wave .door-image img  {
  filter: grayscale(1) brightness(0.95);   /* dignified B&W faces — color is saved for the reveal */
  transition: none;
  opacity: 0;
  outline: 1px solid transparent; outline-offset: -1px;  /* thin border, set to brand color on settle */
  will-change: transform, opacity;
  /* Animation runs as soon as .wave is added; each photo is offset by its own
     --cellDelay (set inline by JS) for the staggered wave. No paused state and
     no rAF trigger — robust even if the tab isn't focused. */
  animation: h2hWavePop var(--pop, .6s) cubic-bezier(.22, .61, .36, 1) var(--cellDelay, 0s) both;
}
.door-left  .door-image img { --bc: rgba(206,17,38,.38); }  /* subtle red edge, doesn't overpower */
.door-right .door-image img { --bc: rgba(31,166,222,.38); } /* subtle blue edge */
/* Each photo ARRIVES rather than just switching on: a small scale lift (92%->100%)
   paired with the existing opacity fade. Transform + opacity only — no filter/blur
   animation added here, since that would reintroduce repaint cost across a dense
   grid (up to ~170 cells on TV); this keeps the same GPU-cheap, compositor-only
   profile the wave was built on, so it stays smooth at every grid size. The scale
   is small on purpose — a felt lift, not a bounce or a pop. */
@keyframes h2hWavePop {
  0%   { opacity: 0; transform: scale(.92); }
  70%  { outline-color: transparent; }
  100% { opacity: 1; transform: scale(1); outline-color: var(--bc); }
}

/* Blooming clone is taken position:absolute by JS. Transform:scale and
   transform-origin are managed entirely by JS inline (inverse-scale technique).
   This class is kept for z-index; scale is NOT driven by CSS. */
.door-image img.cell-bloom {
  position: absolute;
  z-index: 5;
}

/* Brand border is set inline by JS as `outline` because CSS
   `box-shadow: inset` is buried behind the image content on <img>
   elements — object-fit:cover fills the entire box and covers it.
   Outline renders above image content and is not hidden by the image. */

/* Photo grid exits with its door */
.door-experience.opened .door-image {
  opacity: 0;
  transition: opacity 0.35s ease;
}

/* Scrim gives the wordmark trace good contrast against the photos. */
.door::after {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.30);
  z-index: 2;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .door-image { display: grid; opacity: 1; }
  .door-image img { filter: grayscale(0) brightness(1); box-shadow: none; transition: none; }
}

/* The wordmark sits center over both doors */
.door-wordmark {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 5;
  /* rem-relative cap (68.75rem = 1100px at the 16px base root): identical on
     phones/laptops/monitors, but grows on large presentation screens via the
     site's root-size zoom (19px @2200px, 23px @3000px) so the wordmark doesn't
     sit small in a 4K frame the way a fixed 1100px would. */
  width: min(94vw, 68.75rem);
  text-align: center;
  transition: opacity 0.8s ease, transform 1.2s cubic-bezier(.76,0,.24,1);
}

/* Scrim removed — the door panel's own dark background provides consistent
   contrast behind the wordmark throughout the entire intro. No fade-in needed. */

.door-experience.opened .door-wordmark {
  opacity: 0;
  transform: translate(-50%, -50%) scale(1.2);
  transition: opacity 0.6s ease, transform 1s cubic-bezier(.7,0,.84,0);
}

/* Instant skip — the whole overlay is click-to-enter, so show a pointer cursor
   over it (except the Enter button, which already shows its own). */
.door-experience.enterable { cursor: pointer; }

.wordmark-svg {
  width: 100%;
  overflow: visible;
  display: block;
  /* Tight shadow only — no large blurry halo which softens letter edges */
  filter:
    drop-shadow(0 1px 3px rgba(0, 0, 0, 0.95))
    drop-shadow(0 3px 10px rgba(0, 0, 0, 0.7));
  transition: filter 0.8s ease;
}

/* SVG trace + fill animation */
.trace {
  fill: none;
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  /* stroke-dasharray must be >= the word's full outline length, so the dash is a
     SINGLE run that draws on — not a repeating pattern. The real outline length of
     HEARTS/HANDS at font-size 175 is ~655 units (measured on dev). The old 650 sat
     just under that, so the pattern repeated and bridged the gap between two letter
     contours as a straight line — a stray diagonal slash through the H (worst on
     HANDS). 720 clears the true length with ~10% headroom for font-render variance:
     past the length so nothing bridges, yet close enough that the draw still fills
     the full 0.7s with no start-of-draw stall. */
  stroke-dasharray: 720;
  stroke-dashoffset: 720;
}

/* All wordmark animations start PAUSED. JS adds .seq-started to #doorExp
   when fonts.ready fires — that's when delays begin counting. This ensures
   animations never run against invisible (not-yet-loaded) font glyphs,
   regardless of whether fonts come from cache or network. */
.trace-red,
.trace-blue,
.hearts-fill,
.hands-fill,
.connector-fill,
.clt-fill,
.rule-left,
.rule-right { animation-play-state: paused; }

.door-experience.seq-started .trace-red,
.door-experience.seq-started .trace-blue,
.door-experience.seq-started .hearts-fill,
.door-experience.seq-started .hands-fill,
.door-experience.seq-started .connector-fill,
.door-experience.seq-started .clt-fill,
.door-experience.seq-started .rule-left,
.door-experience.seq-started .rule-right { animation-play-state: running; }

.trace-red {
  stroke: var(--red);
  /* Single glow (was two stacked drop-shadows). Because the draw animates
     stroke-dashoffset on the main thread, every glow is recomputed each frame —
     halving them noticeably smooths the trace. */
  filter: drop-shadow(0 0 8px var(--red));
  /* Draw the outline on, then fade it out as the fill lands (traceFade starts
     when the draw ends at 1.3s, finishes with the fill at 1.75s). The 2.5u
     stroke is CENTERED on the glyph edge, so it sits ~1.25u OUTSIDE the fill;
     scaled up on large screens that leftover ring reads as a mismatched
     outline. Fading the trace once the fill is solid leaves a crisp fill at
     every size while keeping the draw-then-fill choreography. */
  animation: traceReveal 0.7s cubic-bezier(.65,0,.35,1) 0.6s forwards,
             traceFade 0.45s ease 1.3s forwards;
}

.trace-blue {
  stroke: var(--blue);
  filter: drop-shadow(0 0 8px var(--blue));
  /* Same draw-then-fade: draw ends 2.0s, fill ends 2.4s, so the trace fades
     across that window and the settled HANDS is a clean fill. */
  animation: traceReveal 0.7s cubic-bezier(.65,0,.35,1) 1.3s forwards,
             traceFade 0.4s ease 2.0s forwards;
}

@keyframes traceReveal { to { stroke-dashoffset: 0; } }
@keyframes traceFade { to { opacity: 0; } }

.word-fill {
  font-family: 'Oswald', sans-serif;
  /* Bumped from 400 to 500 for slightly fatter HEARTS/HANDS strokes
     while still feeling skinny relative to the original 700.
     IMPORTANT: this CSS rule has higher specificity than the SVG
     font-weight attribute, so it controls the actual rendered weight
     of the fill text. The trace and fill MUST use the same weight
     or they visually misalign — keep this value in sync with the
     SVG font-weight="..." attribute on the trace and fill elements. */
  font-weight: 500;
  opacity: 0;
}

.hearts-fill {
  fill: #B0002B;
  /* fillReveal fades the solid word in OVER the finished outline — you read it
     as "outline draws then fills," not a muddy overlap. Starts as the red
     outline completes (0.6s delay + 0.7s draw = 1.3s). */
  animation: fillReveal .5s ease 1.25s forwards;
}

.hands-fill {
  fill: var(--blue);
  /* Same: the blue fill starts as the HANDS outline finishes
     (1.3s delay + 0.7s draw = 2.0s) — draw, then fill. Ends ~2.4s, well inside
     the open-sequence fallback. */
  animation: fillReveal .5s ease 1.9s forwards;
}

/* Tall skinny white center text - TO between words, CLT in caption */
.center-text {
  fill: rgba(255,255,255,0.95);
  font-family: 'Oswald', sans-serif;
  font-weight: 200;
  letter-spacing: .06em;
  opacity: 0;
  filter: drop-shadow(0 1px 3px rgba(0,0,0,0.8));
}

.connector-fill {
  /* Override the white fill from .center-text — TO is gold to match
     the gold caption rules flanking CLT, tying the supporting elements
     together visually. CLT stays white via .clt-fill below. Also
     overrides the .center-text default letter-spacing (.06em) with
     -.02em — slight negative tracking that pulls TO's two letters
     closer together for visual compactness. */
  fill: var(--gold);
  letter-spacing: -.02em;
  animation: fillIn .3s ease 0.9s forwards;
}

.clt-fill {
  letter-spacing: .35em;
  font-weight: 400;
  animation: fillIn .3s ease 2.0s forwards;
}

/* Gold caption rules flanking CLT */
.caption-rule {
  opacity: 0;
  transform-origin: center;
  filter: drop-shadow(0 0 4px rgba(216,168,90,0.4));
}

.rule-left {
  transform: scaleX(0);
  transform-origin: right center;
  animation: ruleGrow .3s cubic-bezier(.22,1,.36,1) 2.75s forwards;
  /* Brand-gold glow renders BEFORE the parent .wordmark-svg's dark
     halo, so the final look is: bright gold line → soft gold radiance
     → dark separation halo. Same depth treatment as the wordmark
     letters, but warm-toned to match the rule's color. */
  filter:
    drop-shadow(0 0 3px rgba(216, 168, 90, 0.8))
    drop-shadow(0 0 10px rgba(216, 168, 90, 0.4));
}

.rule-right {
  transform: scaleX(0);
  transform-origin: left center;
  animation: ruleGrow .3s cubic-bezier(.22,1,.36,1) 2.75s forwards;
  filter:
    drop-shadow(0 0 3px rgba(216, 168, 90, 0.8))
    drop-shadow(0 0 10px rgba(216, 168, 90, 0.4));
}

@keyframes ruleGrow {
  to {
    opacity: 1;
    transform: scaleX(1);
  }
}

@keyframes fillIn {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

/* Pure opacity fade for HEARTS/HANDS fills — no translate, so the colored
   letters stay exactly co-aligned with the trace outline they overlay.
   (The trace has no transform, so any translate on the fill would offset
   them relative to each other during/after the animation.) */
@keyframes fillReveal {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* Enter prompt */
.door-enter {
  position: absolute;
  bottom: 4.5rem;
  left: 50%;
  transform: translateX(-50%);
  z-index: 6;
  display: none;
  cursor: pointer;
  background: none;
  border: none;
  color: white;
  font-family: 'Inter', sans-serif;
  text-align: center;
  padding: .5rem 1rem;
}

.door-enter.active {
  display: block;
}

/* Label matches the hero "See Us in Action" cue exactly (.home-enter-label):
   same size/tracking/weight + gold glow, no frosted pill. */
.door-enter-label {
  display: inline-block;
  font-size: .82rem;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--gold);
  margin-bottom: .65rem;
  font-weight: 700;
  /* gold glow (matches hero cue) + a soft dark shadow for legibility over the
     bright doors, since the frosted pill is gone */
  text-shadow: 0 0 12px rgba(216,168,90,.5), 0 1px 6px rgba(7,11,20,.85);
  transition: color .25s, text-shadow .25s;
}
.door-enter:hover .door-enter-label {
  color: #fff;
  text-shadow: 0 0 18px rgba(216,168,90,.8);
}

/* Gold ring in the same family as the hero cue (.home-enter-ring), but with its
   OWN soft dark backing + faint gold glow. The hero cue borrows contrast from the
   dark skyline behind it; the skip ring sits over the bright doors, so it needs a
   subtle radial halo (fades out, not a hard pill) to stay legible without becoming
   the main feature. */
.door-enter-button {
  position: relative;
  width: 56px;
  height: 56px;
  border: 2px solid var(--gold);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto;
  color: var(--gold);
  background: radial-gradient(circle, rgba(7,11,20,.55) 0%, rgba(7,11,20,.32) 55%, rgba(7,11,20,0) 78%);
  box-shadow: 0 0 22px 6px rgba(7,11,20,.5), 0 0 16px rgba(216,168,90,.32);
  transition: border-color .25s, color .25s, box-shadow .25s, transform .25s;
}

/* Radar rings — matched to the hero cue (.home-enter-ring::before/::after):
   inset -2px, 2px ring, staggered 1.2s, 2.4s cycle. Stay paused until the
   button appears (.door-enter.active), then fade out with the whole button
   once the photo wave finishes covering the city (.door-enter.intro-done,
   set by runPhotoWave — see below). Not a fixed timer: it tracks however long
   the wave actually takes on that screen/grid size. */
.door-enter-button::before {
  content: '';
  position: absolute;
  inset: -2px;
  border: 2px solid rgba(216, 168, 90, 0.7);
  border-radius: 50%;
  animation: pulseRing 2.4s cubic-bezier(0.16, 1, 0.3, 1) infinite;
  animation-play-state: paused;
}

.door-enter-button::after {
  content: '';
  position: absolute;
  inset: -2px;
  border: 2px solid rgba(216, 168, 90, 0.7);
  border-radius: 50%;
  animation: pulseRing 2.4s cubic-bezier(0.16, 1, 0.3, 1) infinite 1.2s;
  animation-play-state: paused;
}

/* Start pulses only after button has appeared */
.door-enter.active .door-enter-button::before,
.door-enter.active .door-enter-button::after {
  animation-play-state: running;
}

@keyframes pulseRing {
  0% {
    transform: scale(1);
    opacity: 1;
  }
  100% {
    /* Reaches 1.75x — nearly double the button's size — so the ring
       sweeps well into the surrounding dark halo, making it
       unmistakably visible. Fades to 0 at the same time, so the
       next ring (or this one's next cycle) starts fresh at scale 1. */
    transform: scale(1.75);
    opacity: 0;
  }
}

/* One-time nudge pulse triggered by JS after ~5 photos bloom */
@keyframes enterNudgePulse {
  0%   { box-shadow: 0 0 0 0 rgba(212,175,55,0.9), 0 0 30px 0 rgba(212,175,55,0.3); }
  60%  { box-shadow: 0 0 0 22px rgba(212,175,55,0), 0 0 30px 8px rgba(212,175,55,0.5); }
  100% { box-shadow: 0 0 0 22px rgba(212,175,55,0), 0 0 30px 0 rgba(212,175,55,0); }
}
.door-enter.enter-nudge .door-enter-button {
  animation: enterNudgePulse 1.1s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}

.door-enter:hover .door-enter-button {
  border-color: rgba(216, 168, 90, 1);
  color: #fff;
  transform: scale(1.06);
  box-shadow: 0 0 22px 6px rgba(7,11,20,.5), 0 0 40px rgba(216, 168, 90, 0.65), inset 0 0 18px rgba(216, 168, 90, 0.2);
}

.door-enter-arrows {
  width: 24px;
  height: 11px;
  stroke: var(--gold); /* gold to match the hero cue's gold chevron; overridden to dark in drain state below */
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  fill: none;
  overflow: visible; /* allow chevrons to translate outside the viewBox on hover */
}

/* Subtle outward translation on the chevrons when the button is hovered —
   left chevron drifts left, right chevron drifts right, mirroring the
   actual door-open motion that's about to happen. The transition runs in
   both directions, so chevrons ease back smoothly when hover ends. */
.door-enter-arrows { transition: stroke .25s ease; }
.door-enter:hover .door-enter-arrows { stroke: #fff; }
.door-enter-arrows polyline {
  transition: transform 0.3s cubic-bezier(.65,0,.35,1);
}
.door-enter:hover .door-enter-arrows polyline:first-child {
  transform: translateX(-4px);
}
.door-enter:hover .door-enter-arrows polyline:last-child {
  transform: translateX(4px);
}

.door-experience.opened .door-enter {
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.4s ease;
}

/* Skip control fades out as the photo wave finishes covering the city —
   set by runPhotoWave just before auto-open. Nothing left to skip. */
.door-enter.intro-done {
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.6s ease;
}

/* ── Post-open memory cleanup ───────────────────────────────────────────────
   Once the user enters, the intro is gone. Release compositor layers and stop
   continuous animations so the browser can reclaim GPU memory for the page. */
.door-experience.opened .door-image,
.door-experience.opened .door-image img {
  will-change: auto;   /* frees the composited layer held for parallax */
  animation: none;
}
.door-experience.opened .hearts-fill,
.door-experience.opened .hands-fill {
  animation: none;     /* stop the fill repaint loop as the doors open */
  opacity: 1;          /* but HOLD the filled state — clearing the forwards
                          animation would otherwise drop these back to their
                          base opacity:0, snapping the wordmark to its outline */
}
.door-experience.opened .door-enter-button::before,
.door-experience.opened .door-enter-button::after {
  animation: none;     /* stops pulseRing */
}

/* ==========================================================================
   Main Site Sections — Dark Glass Aesthetic
   Matches the portal and fundraiser pages: dark bg, glass cards,
   brand palette (red #CE1126, blue #1FA6DE, gold #D8A85A).
   All sections use .landing-bleed to span full viewport width;
   .landing-wrap re-constrains content to max-width: 1100px.
   ========================================================================== */

.landing-wrap { max-width: var(--container); margin: 0 auto; }

/* NOTE: the single source of truth for shared section vertical rhythm is the
   `body.page-landing section` rule further down (search "SECTIONS — fluid
   vertical rhythm"). An earlier duplicate here was silently overridden by it
   and has been removed so there is one authoritative value. */

/* ── Section bands ──────────────────────────────────────────────────────────
   Clear separation: alternating panel tone (raised vs. base), a soft brand
   glow at the top, and a short brand-coloured accent bar that marks where each
   section begins. */
body.page-landing section.landing-bleed { --band-accent: rgba(255,255,255,.4); }

/* Accent-bar colour cycles by section POSITION — red → gold → blue, repeating —
   so inserting or reordering .landing-bleed sections recolours them all
   automatically. New sections just need class="landing-bleed". */
/* Seam colour cycles red → gold → blue starting at the FIRST VISIBLE seam, which
   is About (the 2nd section — the hero's own seam is hidden). So About = red,
   In Action = gold, Impact band = blue, then the cycle repeats down the page. */
body.page-landing section.landing-bleed:nth-of-type(3n+2) { --band-accent: var(--h2h-red,  #CE1126); }
body.page-landing section.landing-bleed:nth-of-type(3n)   { --band-accent: var(--h2h-gold, #D8A85A); }
body.page-landing section.landing-bleed:nth-of-type(3n+1) { --band-accent: var(--h2h-blue, #1FA6DE); }

body.page-landing section.landing-bleed::before {
  content: "";
  position: absolute; top: 0; left: 0; right: 0;
  height: 2px;
  /* A full-width seam that grows in from the centre on scroll, marking each
     chapter break. Colour cycles red → gold → blue by section position
     (--band-accent); single-colour per seam so it never competes with the
     hero cross's tricolour. */
  background: linear-gradient(90deg, transparent, var(--band-accent) 18%, var(--band-accent) 82%, transparent);
  opacity: .8;
  transform: scaleX(0);
  transform-origin: center;
  transition: transform 1.1s cubic-bezier(.22,.61,.36,1);
}
body.page-landing section.landing-bleed.in-view::before {
  transform: scaleX(1);
}
@media (prefers-reduced-motion: reduce) {
  body.page-landing section.landing-bleed::before { transform: scaleX(1); transition: none; }
}
/* The hero is the first chapter, so its top seam lands right under the nav and
   doubles up with the tri-colour scroll-progress line above the fold. Suppress it
   on the hero only — the progress bar is the lone line wanted up top; the seams
   between every later section stay. */
body.page-landing section.landing-bleed.home-hero::before { display: none; }

/* ── Homepage chapter surfaces ───────────────────────────────────────────────
   Each chapter gets either the DEEP base (#070b14) or a clearly lighter PANEL
   (#0f1a33), assigned by VISUAL (flex) order so adjacent chapters always
   contrast and read as distinct — the old nth-of-type alternation keyed off DOM
   order, which didn't match the display order. A soft brand-tinted glow sits at
   each chapter's top edge (layered into the background, always behind content)
   to give each one its own character and lift it off the one before. */
/* The rhythm is LIGHTNESS: PANEL (#1a2c50, lighter) and DEEP (#070b14) alternate
   by visual order, so adjacent chapters read distinct on tone alone. Colour is a
   FAINT hint at the very top edge only (~.09) — a whisper of character, never a
   wash that competes with the content. See DESIGN_STANDARDS.md. */
body.page-main-home #about     { background: radial-gradient(120% 55% at 50% 0%, rgba(216,168,90,.09), transparent 55%), #1a2c50; }  /* PANEL */
body.page-main-home #in-action { background: radial-gradient(120% 55% at 50% 0%, rgba(31,166,222,.09),  transparent 55%), #070b14; }  /* DEEP · blue — follows About panel; video on dark reads cinematic */
body.page-main-home #impact-band { background: radial-gradient(120% 55% at 50% 0%, rgba(216,168,90,.07), transparent 55%), #1a2c50; }  /* PANEL · gold — sits between In Action deep + Mosaic deep; photo bg overrides via .impact-band-bg */
body.page-main-home #events    { background: radial-gradient(120% 55% at 50% 0%, rgba(206,17,38,.09),   transparent 55%), #1a2c50; }  /* PANEL · red  */
body.page-main-home #impact    { background: radial-gradient(120% 55% at 50% 0%, rgba(31,166,222,.09),  transparent 55%), #070b14; }  /* DEEP · blue (recaps) */
body.page-main-home #donate    { background: #070b14;   /* DEEP · the full-bleed street photo (.donate-photo-bg) provides the surface; keep a dark base so the fade-out at the section seam lands on solid color */
                                  padding-bottom: clamp(1.5rem, 2.5vw, 2.25rem); }
body.page-main-home #contact   { background: radial-gradient(120% 55% at 50% 0%, rgba(216,168,90,.09),  transparent 55%), #070b14; }  /* DEEP · gold */
body.page-main-home #join      { background: radial-gradient(120% 55% at 50% 0%, rgba(216,168,90,.09),  transparent 55%), #1a2c50; }  /* PANEL · gold (send-off, keeps Contact→Join from doubling dark) */

/* Footer connects flush to the last section (the old 4rem gap read as a second
   divider after Contact). */
body.page-landing .main-footer { margin-top: 0; }

/* Keep page content above the parallax glow layer (glows are body-level, z:0). */
body.section-main .container { position: relative; z-index: 1; }

/* ── Shared section header ─────────────────────────────────────────────── */
.main-section-header {
  text-align: center;
  margin-bottom: 2.5rem;
}
/* Section heading system — used by every section (About, Donate, Events, …):
   a bold condensed gold title (echoes the HEARTS TO HANDS wordmark) + a
   brand-gradient underline that draws in when the section reveals + a small
   colored kicker. Lives on .main-section-header (a .reveal-on-scroll block). */
.main-section-title {
  font-family: 'Bebas Neue', 'Barlow Condensed', sans-serif;
  font-size: clamp(2.8rem, 8vw, 5rem);
  font-weight: 400;
  color: var(--h2h-gold, #D8A85A);
  line-height: .95;
  margin: .25rem 0 0;
  letter-spacing: .03em;
  text-transform: uppercase;
  text-shadow: 0 2px 16px rgba(0, 0, 0, .4);
}
.main-section-rule {
  width: 88px;
  height: 3px;
  border-radius: 3px;
  margin: 16px auto 18px;
  background: linear-gradient(90deg, var(--h2h-red, #CE1126), var(--h2h-gold, #D8A85A), var(--h2h-blue, #1FA6DE));
  transform: scaleX(0);
  transform-origin: center;
  transition: transform 1s cubic-bezier(.22, .61, .36, 1) .2s;
}
.main-section-header.is-visible .main-section-rule { transform: scaleX(1); }
@media (prefers-reduced-motion: reduce) {
  .main-section-rule { transform: scaleX(1); transition: none; }
}
.main-section-sub {
  font-size: .98rem;
  color: rgba(200,208,223,.55);
  margin-top: .4rem;
}
.main-section-sub--center { text-align: center; }

/* ── Editorial section header (modernization POC) ──────────────────────────
   Variant of .main-section-header: left-aligned, oversized faded index number,
   a kicker with a short rule (no centered growing underline), and a mixed-case
   Barlow Condensed headline. Applied to one section first as a proof-of-concept;
   if approved, this replaces the centered pattern across all sections. */
/* Shared editorial content column. The header AND every section's content block
   align to this column so nothing stretches wider or further left than the heading.
   To align a section's content: max-width: var(--ed-col-max); margin: auto;
   padding-left: var(--ed-col-indent);  (indent = accent bar 4px + the header gap). */
:root {
  /* Layout tokens — rem-based so they scale with the big-screen root bump below.
     --container = overall content max; text still caps at the narrower --ed-col-max. */
  --container: 82rem;                       /* 1312px @16px — widened spine (was 75rem); text still caps at the narrower --ed-col-max */
  --gutter: clamp(1.25rem, 4vw, 1.75rem);    /* fluid side gutter: 20px → 28px (tightened from 40px — matches base) */
  --ed-col-max: 62.5rem;                    /* editorial reading column (1000px @16px) */
  --ed-gap: clamp(1.1rem, 3vw, 1.75rem);
  --ed-bar: 6px;                            /* section accent-bar width; feeds the indent so content stays aligned if it changes */
  --ed-col-indent: calc(var(--ed-bar) + var(--ed-gap));
  /* Editorial two-column spread (media/portrait left, content right) — shared by
     About and Contact so their column split stays identical. */
  --editorial-spread-cols: minmax(0, clamp(340px, 44vw, 520px)) minmax(0, 1fr);
  --editorial-spread-gap: clamp(1.75rem, 4vw, 3.5rem);
}

/* ── Breakpoint reference (documentation only — defines no rules) ─────────────
   This site does NOT use a single global breakpoint scale; most media queries
   are tuned to the width at which a SPECIFIC element's content breaks, which is
   deliberate and should be left alone. This note is the map so future edits
   reach for an existing threshold instead of inventing a new nearby one.

   CANONICAL layout stops — prefer these when a NEW rule needs a breakpoint:
     600px   phone / small-tablet boundary (the workhorse — most stacking here)
     720px   tablet: two-column → single-column (In Action, Events, verse, donate)
     860px   About spread stacks (header → photo → story)
     900px   general wide-tablet adjustments
     1900px  ultra-wide: --container starts tracking the viewport (see below)
     2200px / 3000px  TV/4K root-font zoom tiers (see above)

   INTENTIONAL one-offs — each tuned to one element; do NOT fold into the above:
     360px  hide the next-bar CTA label so the button doesn't overflow
     420px  donate amount buttons go 2-up
     460px  join actions stack to one column
     480px  (assorted small-phone type/spacing)
     520px  (assorted small-phone adjustments)
     560px  impact-band-heart-stage width cap (min(300px, 80vw))
     760px  hero tagline/Why-How stacking (its own tuned value, near 720)
     767/768px  hero + contact-grid + next-bar — 767(max)/768(min) are CORRECT
                complementary pairs (no overlap, no gap); do not "align" them
     599/600px  .impact-strip — 600(min):nowrap + 599(max):max-content is a
                CORRECT complementary split on the same element; do not merge
                (snapping 599→600 would make both fire at 600px = a real conflict)
   ──────────────────────────────────────────────────────────────────────────── */
/* Scale the whole layout UP on very large presentation screens (TVs / 4K). Every
   rem-based value — type, spacing, --container, --ed-col-max — grows together;
   full-bleed bands already span 100vw. Gated high (≥2200px) so phones, tablets,
   laptops and normal monitors (≤1920px) are completely untouched at 16px. */
@media (min-width: 2200px) { html { font-size: 19px; } }
@media (min-width: 3000px) { html { font-size: 23px; } }

/* Ultra-wide void reduction (homepage only). The rem-based scale above zooms the
   whole design up on big screens, but because it grows type AND --container in
   lockstep, the wrap stays ~1425px at 2560px while the viewport nearly doubles —
   leaving ~520px of dead navy on each side of the wrap-contained sections
   (About, In Action, Events, Recaps, Contact). Here we let --container track the
   VIEWPORT instead (86vw, capped at 105rem so it never gets absurd on 4K/8K), so
   the two-column sections (In Action, Events, Recaps) fill the screen and each
   void drops to ~280px. Gated at 1900px so laptops/monitors (≤1920px) are
   untouched; the font-size zoom above still layers on at 2200px+.
   EXCEPTION: About's story and the Contact form are text/entry-forward — a wider
   column would push the reading measure past ~75 chars / make form fields
   uncomfortably long. So those two cap at the base 75rem and CENTER within the
   wider wrap, keeping their approved proportions while everything around them
   uses the reclaimed width. */
@media (min-width: 1900px) {
  body.page-main-home { --container: min(86vw, 105rem); }
  body.page-main-home #contact .contact-grid { max-width: 75rem; margin-inline: auto; }
  /* Ultra-wide hero: let the tagline + Why/How block grow so it commands the
     screen instead of sitting small in a sea of skyline. Block width and type
     are both rem-based, so their fit ratio holds constant across the root-size
     steps at 2200px (19px) and 3000px (23px) — no clipping at any TV width. */
  body.page-main-home .home-tl-inner { max-width: 80rem; }
  body.page-main-home .home-tl-left,
  body.page-main-home .home-tl-right { font-size: 5.4rem; }
  body.page-main-home .home-why .ia-intro-body { font-size: 1.15rem; }
}

/* Align a section's content block to the editorial header's TEXT column, so the
   block's left/right edges match the heading and nothing spills left of it.
   Box-based (not padding) so cards with their own background line up too. The
   max() keeps it safe on mobile, where it falls back to just the bar+gap indent.
   Add `ed-col` to any new section content block to line it up automatically.
   NOT applied to intentionally full-bleed bands (partners strip, impact stats,
   donate cards) or to narrower centered blocks that already sit right of the head. */
.ed-col,
#in-action .in-action-layout,
#about .about-body,
#contact .contact-grid {
  max-width: calc(var(--ed-col-max) - var(--ed-col-indent));
  margin-left: calc(var(--ed-col-indent) + max(0px, (100% - var(--ed-col-max)) / 2));
  margin-right: auto;
}
.main-section-header--editorial {
  text-align: left;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: var(--ed-gap);
  align-items: stretch;
  /* Hard-left on the content spine (full --container width), so every section
     header lines up with the nav logo. Full-width section headers are the
     locked default -- do NOT reintroduce a centered/reading-column indent. */
  max-width: 100%;
  margin: 0 0 2.75rem;
}
/* Slim brand accent bar — quietly carries "Hearts to Love (red), Hands to
   Serve (blue)". Brand color used with intent, not decoration. */
.main-section-header--editorial .mse-bar {
  width: var(--ed-bar);
  align-self: stretch;
  min-height: 96px;
  border-radius: 3px;
  background: linear-gradient(#CE1126 0%, #D8A85A 50%, #1FA6DE 100%);
  box-shadow: 0 0 18px -3px rgba(216,168,90,.55);   /* warm halo so the bar reads boldly against the dark sections */
  /* Draws downward (red → gold → blue) with a glowing leading edge when the
     section scrolls in. clip-path (not scaleY) keeps the bar full-width and the
     glow crisp as it grows, so the motion actually registers. */
  clip-path: inset(0 0 100% 0 round 3px);
  transition: clip-path 1.4s cubic-bezier(.22, .61, .36, 1) .15s;
}
.main-section-header--editorial.is-visible .mse-bar { clip-path: inset(0 0 0 0 round 3px); }
@media (prefers-reduced-motion: reduce) {
  .main-section-header--editorial .mse-bar { clip-path: none; transition: none; }
}
/* Kicker row: kicker on the left, optional stat chip on the right. */
.main-section-header--editorial .mse-kickrow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: .85rem;
}
.main-section-header--editorial .mse-kicker {
  font-family: 'Oswald', sans-serif;
  display: flex;
  align-items: center;
  gap: .8rem;
  font-size: .82rem;
  font-weight: 500;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--h2h-gold, #D8A85A);
}
.main-section-header--editorial .mse-kicker::after {
  content: "";
  height: 1px;
  width: 54px;
  background: rgba(216,168,90,.5);
}
/* Stacked: kicker → headline → description, top to bottom. Clear reading order;
   horizontal interest comes from the bar + the headline's offset, not from
   splitting the copy. Description sits at a readable measure beneath. */
.main-section-header--editorial .mse-row {
  display: block;
  margin-top: .35rem;
}
.main-section-header--editorial .mse-title {
  font-family: 'Barlow Condensed', 'Bebas Neue', sans-serif;
  font-size: clamp(2.1rem, 4.4vw, 3.35rem);   /* capped — the 4.3rem max read as oversized on large screens */
  font-weight: 600;
  line-height: 1.02;
  letter-spacing: .005em;
  color: #f4efe4;
  margin: 0;
}
.main-section-header--editorial .mse-title em {
  font-style: normal;
  color: var(--h2h-gold, #D8A85A);
}
.main-section-header--editorial .mse-sub {
  font-size: 1.02rem;
  color: rgba(206,214,228,.80);
  max-width: 54ch;
  margin: .95rem 0 0;
  line-height: 1.65;
}
@media (max-width: 760px) {
  /* Keep the thin accent bar on the left; tighten the gap. */
  .main-section-header--editorial { column-gap: 1rem; }
  .main-section-header--editorial .mse-sub { max-width: 100%; }
}
/* Stat cards row — reuse .stat-cards from styles-base.css */
.main-hero .stat-cards { margin-top: 0; max-width: 600px; margin-left: auto; margin-right: auto; }

/* ── Responsive ────────────────────────────────────────────────────────── */
@media (max-width: 900px) {
  body.page-landing section { padding: 3.5rem 1.5rem; }
  .main-hero .stat-cards { grid-template-columns: repeat(3,1fr); }
  /* Door experience tablet adjustments */
  .door-wordmark { width: min(96vw, 1100px); }
  .door-enter { bottom: 2rem; }
  .door-enter-button { width: 50px; height: 50px; }
}
@media (max-width: 600px) {
  .main-hero .stat-cards { grid-template-columns: 1fr; }
}

/* LEGACY HERO (post-door) — replaced, keeping selector as dead stub */
body.page-landing .hero {
  position: relative;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background: linear-gradient(to bottom, #FBF8F2 0%, #F2EBDE 100%);
}

body.page-landing .hero-collage {
  position: absolute;
  inset: 0;
  background-image: url('/assets/images/main/collage-red.jpg');
  background-size: cover;
  background-position: center;
  filter: grayscale(1) contrast(1.05);
  opacity: 0.18;
}

body.page-landing .hero-content {
  position: relative;
  z-index: 5;
  text-align: center;
  padding: 2rem;
  max-width: 1000px;
}

body.page-landing .hero-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: .6rem;
  font-size: .85rem;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--ink-mute);
  font-weight: 500;
  margin-bottom: 2rem;
}

body.page-landing .hero-eyebrow::before,
body.page-landing .hero-eyebrow::after {
  content: '';
  width: 24px;
  height: 1px;
  background: var(--gold-warm);
}

body.page-landing .hero-headline {
  font-family: 'Fraunces', serif;
  font-weight: 400;
  font-size: clamp(2.5rem, 6vw, 4.8rem);
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--ink);
  margin-bottom: 1.5rem;
}

body.page-landing .hero-headline em {
  font-style: italic;
  color: var(--red);
  font-weight: 500;
}

body.page-landing .hero-headline .blue-accent {
  color: var(--blue);
  font-style: italic;
  font-weight: 500;
}

body.page-landing .hero-sub {
  font-size: 1.2rem;
  color: var(--ink-soft);
  max-width: 580px;
  margin: 0 auto 2.5rem;
  line-height: 1.65;
}

body.page-landing .hero-actions {
  display: flex;
  gap: 1rem;
  justify-content: center;
  flex-wrap: wrap;
}

body.page-landing .btn {
  padding: 1rem 1.8rem;
  border-radius: 999px;
  text-decoration: none;
  font-size: .85rem;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  transition: all .25s ease;
  display: inline-flex;
  align-items: center;
  gap: .6rem;
}

body.page-landing .btn-primary {
  background: var(--red);
  color: white;
  box-shadow: 0 6px 24px rgba(206,17,38,0.25);
}

body.page-landing .btn-primary:hover {
  background: var(--red-deep);
  transform: translateY(-2px);
  box-shadow: 0 10px 30px rgba(206,17,38,0.4);
}

body.page-landing .btn-secondary {
  background: transparent;
  color: var(--ink);
  border: 1.5px solid var(--ink);
}

body.page-landing .btn-secondary:hover {
  background: var(--ink);
  color: var(--paper);
  transform: translateY(-2px);
}

body.page-landing .btn-arrow { transition: transform .25s ease; }
body.page-landing .btn:hover .btn-arrow { transform: translateX(3px); }

/* SECTIONS — fluid vertical rhythm + gutter; max-width via shared token.
   Uniform top/bottom base for every editorial section: 48px → 80px. Sections
   that intentionally deviate (in-action/mosaic tight pair, donate photo poster,
   impact-band full-bleed band) override this locally and are the only exceptions. */
body.page-landing section { padding: clamp(3rem, 5.5vw, 5rem) var(--gutter); position: relative; }
.landing-wrap { max-width: var(--container); margin: 0 auto; }

body.page-landing .eyebrow {
  display: inline-block;
  font-size: .78rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--red);
  font-weight: 600;
  margin-bottom: 1rem;
}

body.page-landing .section-title {
  font-family: 'Fraunces', serif;
  font-weight: 500;
  font-size: clamp(2rem, 4.5vw, 3.5rem);
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--ink);
  margin-bottom: 1.5rem;
}

body.page-landing .section-title em {
  font-style: italic;
  color: var(--red);
  font-weight: 400;
}

body.page-landing .section-lead {
  font-size: 1.15rem;
  color: var(--ink-soft);
  max-width: 640px;
  line-height: 1.7;
}

body.page-landing .reveal {
  opacity: 0;
  transform: translateY(30px);
  transition: opacity .8s ease, transform .8s ease;
}

body.page-landing .reveal.visible { opacity: 1; transform: translateY(0); }

/* MISSION */
body.page-landing .mission { background: var(--paper); }

body.page-landing .mission-grid {
  display: grid;
  grid-template-columns: 1fr 1.2fr;
  gap: 5rem;
  align-items: center;
}

body.page-landing .mission-statement {
  font-family: 'Fraunces', serif;
  font-weight: 400;
  font-size: clamp(1.5rem, 2.5vw, 2.1rem);
  line-height: 1.4;
  color: var(--ink);
  letter-spacing: -0.01em;
}

body.page-landing .mission-statement .highlight {
  background: linear-gradient(120deg, transparent 0%, transparent 5%, rgba(216,168,90,0.45) 5%, rgba(216,168,90,0.45) 95%, transparent 95%);
  padding: 0 .2em;
}

body.page-landing .mission-statement em {
  font-style: italic;
  color: var(--red);
}

/* IMPACT */
body.page-landing .impact {
  background: var(--black-deep);
  color: var(--paper);
  position: relative;
  overflow: hidden;
}

body.page-landing .impact-collage {
  position: absolute;
  inset: 0;
  background-image: url('/assets/images/main/collage-blue.jpg');
  background-size: cover;
  background-position: center;
  filter: grayscale(1);
  opacity: 0.18;
  mix-blend-mode: luminosity;
}

body.page-landing .impact::before {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse at 20% 0%, rgba(206,17,38,0.18), transparent 50%),
    radial-gradient(ellipse at 80% 100%, rgba(31,166,222,0.15), transparent 50%);
  pointer-events: none;
}

body.page-landing .impact .landing-wrap { position: relative; z-index: 2; }
body.page-landing .impact .eyebrow { color: var(--gold); }
body.page-landing .impact .section-title { color: var(--paper); }
body.page-landing .impact .section-title em { color: var(--gold); }

body.page-landing .stats-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 2rem;
  margin-top: 4rem;
}

body.page-landing .stat { position: relative; padding: 2rem 0; }

body.page-landing .stat:not(:last-child)::after {
  content: '';
  position: absolute;
  right: -1rem;
  top: 20%;
  bottom: 20%;
  width: 1px;
  background: rgba(216,168,90,0.2);
}

body.page-landing .stat-number {
  font-family: 'Fraunces', serif;
  font-weight: 500;
  font-size: clamp(2.8rem, 5vw, 4rem);
  line-height: 1;
  color: var(--gold);
  margin-bottom: .8rem;
  letter-spacing: -0.02em;
}

body.page-landing .stat-number sup {
  font-size: .5em;
  color: var(--gold-warm);
  margin-left: 2px;
}

body.page-landing .stat-label {
  font-size: .85rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: rgba(247,242,234,0.7);
  font-weight: 500;
}

/* PROGRAMS */
body.page-landing .programs { background: var(--cream); }

body.page-landing .programs-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2rem;
  margin-top: 4rem;
}

body.page-landing .program-card {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 2.5rem;
  transition: all .35s ease;
  position: relative;
  overflow: hidden;
}

body.page-landing .program-card::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  background: var(--red);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .4s ease;
}

body.page-landing .program-card:hover {
  transform: translateY(-6px);
  box-shadow: 0 20px 50px rgba(68,70,85,0.12);
  border-color: transparent;
}

body.page-landing .program-card:hover::before { transform: scaleX(1); }
body.page-landing .program-card:nth-child(2)::before { background: var(--blue); }
body.page-landing .program-card:nth-child(3)::before { background: var(--gold-warm); }

body.page-landing .program-icon {
  width: 56px;
  height: 56px;
  border-radius: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 1.5rem;
  background: rgba(206,17,38,0.08);
  color: var(--red);
}

body.page-landing .program-card:nth-child(2) .program-icon {
  background: rgba(31,166,222,0.10);
  color: var(--blue);
}

body.page-landing .program-card:nth-child(3) .program-icon {
  background: rgba(216,168,90,0.18);
  color: var(--gold-warm);
}

body.page-landing .program-title {
  font-family: 'Fraunces', serif;
  font-weight: 600;
  font-size: 1.4rem;
  margin-bottom: .8rem;
  color: var(--ink);
}

body.page-landing .program-text {
  color: var(--ink-soft);
  font-size: .98rem;
  line-height: 1.65;
  margin-bottom: 1.2rem;
}

body.page-landing .program-list { list-style: none; padding: 0; }

body.page-landing .program-list li {
  font-size: .88rem;
  color: var(--ink-mute);
  padding: .4rem 0;
  border-top: 1px solid var(--line);
  display: flex;
  align-items: center;
  gap: .6rem;
}

body.page-landing .program-list li::before {
  content: '';
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--gold-warm);
}

/* GET INVOLVED */
body.page-landing .involved {
  background: linear-gradient(135deg, #FAF5EC 0%, #F2E8D5 100%);
  position: relative;
}

body.page-landing .involved-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2rem;
  margin-top: 4rem;
}

body.page-landing .involved-card {
  padding: 3rem;
  border-radius: 24px;
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  min-height: 380px;
  transition: transform .35s ease;
}

body.page-landing .involved-card:hover { transform: translateY(-6px); }

body.page-landing .involved-card.volunteer {
  background: var(--red);
  color: white;
}

body.page-landing .involved-card.donate {
  background: var(--black-deep);
  color: var(--paper);
}

body.page-landing .involved-card::before {
  content: '';
  position: absolute;
  top: -50%; right: -20%;
  width: 60%; height: 200%;
  background: radial-gradient(circle, rgba(255,255,255,0.08), transparent 60%);
  pointer-events: none;
}

body.page-landing .involved-tag {
  font-size: .75rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  opacity: 0.7;
  margin-bottom: 1rem;
  font-weight: 500;
}

body.page-landing .involved-title {
  font-family: 'Fraunces', serif;
  font-weight: 500;
  font-size: clamp(1.8rem, 3vw, 2.4rem);
  line-height: 1.15;
  margin-bottom: 1rem;
  letter-spacing: -0.01em;
}

body.page-landing .involved-text {
  font-size: 1rem;
  line-height: 1.65;
  opacity: 0.85;
  margin-bottom: 2rem;
  flex-grow: 1;
}

body.page-landing .involved-btn {
  align-self: flex-start;
  background: white;
  color: var(--ink);
  padding: 1rem 1.6rem;
  border-radius: 999px;
  text-decoration: none;
  font-size: .85rem;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  display: inline-flex;
  align-items: center;
  gap: .6rem;
  transition: all .25s ease;
}

body.page-landing .involved-card.donate .involved-btn {
  background: var(--gold);
  color: var(--ink);
}

body.page-landing .involved-btn:hover {
  transform: translateX(4px);
  box-shadow: 0 8px 24px rgba(0,0,0,0.15);
}
/* RESPONSIVE */
@media (max-width: 900px) {
  body.page-landing section { padding: 5rem 1.5rem; }

  body.page-landing .mission-grid,
  body.page-landing .involved-grid {
    grid-template-columns: 1fr;
    gap: 3rem;
  }

  body.page-landing .stats-grid {
    grid-template-columns: repeat(2, 1fr);
    gap: 1.5rem;
  }

  body.page-landing .stat:not(:last-child)::after { display: none; }

  body.page-landing .programs-grid { grid-template-columns: 1fr; }

  body.page-landing .hero-actions { flex-direction: column; max-width: 280px; margin: 0 auto; }
  body.page-landing .btn { justify-content: center; }

  /* Door experience adjustments for tablets/small screens */
  .door-wordmark { width: min(96vw, 1100px); }
  .door-enter { bottom: 2rem; }
  .door-enter-button { width: 50px; height: 50px; }
}

/* Very narrow viewports */
@media (max-width: 480px) {
  .door-wordmark { width: 98vw; }
  .door-enter-button { width: 48px; height: 48px; }
  .door-enter-label { font-size: .75rem; letter-spacing: .25em; }
}

/* REDUCED MOTION */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ============================================================
   Landing page integration with header_main.php / footer_main.php
   ============================================================ */

/* Lock body scroll until the user enters the site.
   REGRESSION FIX (2026-07-18): this used to toggle overflow directly on <body>
   (`body.page-landing{overflow:hidden}` then `body.page-landing.doors-opened
   {overflow-y:auto; overflow-x:clip}`). Mixing overflow-y:auto with
   overflow-x:clip on the SAME element forces the browser to downgrade that
   clip to a used value of hidden (per the CSS Overflow spec's axis-mixing
   rule: a non-{visible,clip} value on one axis forces the other off its
   visible/clip exemption). That silently turned <body> into a real scroll
   container competing with <html> (the actual document.scrollingElement) for
   position:sticky's containing-block lookup — since body's own scrollTop
   never moves, the sticky header anchored to a container that never scrolls
   and slid off-screen with the page. This is exactly the failure mode the
   base html{} rule's neighboring comments warn about, just triggered from
   the body side instead.
   Fix: control <html>'s own overflow-y directly via :has(), reacting to the
   same JS-toggled body classes with zero JS changes. <body> now never
   declares anything but the sitewide `body.section-main{overflow-x:clip}` —
   clip paired with the default visible on y, which is exempt from the
   axis-mixing downgrade, so body can never re-acquire scroll-container status. */
html:has(body.page-landing:not(.doors-opened)) { overflow-y: hidden; }
html:has(body.page-landing.doors-opened)        { overflow-y: auto; }

/* Hide the chrome (skip link, main-footer) until the doors open.
   No transition — content snaps to full opacity the instant the doors start
   sliding, so it's revealed naturally by the door motion rather than fading
   in simultaneously as a separate animation. */
body.page-landing > .skip-to-content,
body.page-landing > .main-footer {
  opacity: 0;
  pointer-events: none;
}

body.page-landing.doors-opened > .skip-to-content,
body.page-landing.doors-opened > .main-footer {
  opacity: 1;
  pointer-events: auto;
}
/* (A pair of rules used to sit here targeting `body.page-landing > .container
   > *:not(.door-experience)`, meant to hide the rest of the page until the
   doors opened. Removed — confirmed dead: header_main.php has never wrapped
   the landing sections in a `.container` div — sections are direct children
   of <body> — so that selector never matched anything. It also wasn't doing
   any real job: .door-experience is `position:fixed; inset:0` with an opaque
   background at z-index:1025, so it already fully covers and blocks clicks to
   everything behind it while closed, with or without this rule.) */

/* Sections are direct children of <body> (no wrapping .container in
   header_main.php — see the note above), but body itself has no padding or
   max-width, so they'd already run full-width by default. This breakout
   (width:100vw; left:50%; margin:-50vw) is kept anyway so each section is an
   explicit, self-contained full-bleed unit regardless of its parent — photo
   backgrounds and dark/cream section colors fill the true viewport edge. The
   inner .landing-wrap then re-constrains the content. */
body.page-landing section.landing-bleed {
  width: 100vw;
  position: relative;
  left: 50%;
  margin-left: -50vw;
  margin-right: -50vw;
  /* Offset anchor-link jumps so the section lands flush against the BOTTOM of the
     opaque scrolled nav bar. The scrolled nav measures 54px tall (verified on
     desktop render); park the section top 1px under it so no strip of the previous
     section (e.g. the bright hero, when the cue jumps to #about/#in-action) peeks
     through the semi-transparent bar. The section's own top padding provides the
     breathing room below the nav. */
  scroll-margin-top: 53px;
}
/* The hero is the first section and fills the viewport from the very top, so the
   Home link must land at scrollY 0 — a 62px offset would push the hero down and
   leave a gap below the skyline. A large margin clamps the anchor jump to the top. */
body.page-landing section#home.landing-bleed { scroll-margin-top: 100vh; }

/* ======================================================================
   MAIN SITE NAV — desktop inline links + mobile overlay
   ====================================================================== */

/* Outer portal-nav row */
.section-main .portal-nav { align-items: center; gap: .5rem; }

/* Desktop inline links — base styles now in styles-base.css */

/* ======================================================================
   HEADER DONATE BUTTON — solid gold pill
   ====================================================================== */
@keyframes h2h-give-heartbeat {
  0%, 100% { transform: scale(1); }
  14%      { transform: scale(1.35); }
  28%      { transform: scale(1); }
  42%      { transform: scale(1.2); }
  56%      { transform: scale(1); }
}
@keyframes h2h-give-glow {
  0%, 100% { box-shadow: 0 2px 8px rgba(16,185,129,.15); }
  50%      { box-shadow: 0 4px 28px rgba(16,185,129,.75), 0 0 0 5px rgba(16,185,129,.22), 0 0 48px rgba(16,185,129,.30); }
}

.header-donate-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  height: 42px;                    /* match the hamburger height */
  padding: 0 1.2rem;
  border-radius: 10px;             /* unified button radius */
  background: var(--h2h-green, #10B981);
  border: 1px solid rgba(16,185,129,.85);
  color: #082a14;                  /* deep green-dark for contrast */
  font-weight: 700;
  font-size: .8rem;
  letter-spacing: .09em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  position: relative;
  overflow: hidden;
  animation: h2h-give-glow 2.4s ease-in-out infinite;
  transition: background .18s ease, border-color .18s ease, transform .18s ease;
}
.header-donate-btn::after {
  content: '';
  position: absolute;
  top: 0; left: -100%; width: 60%; height: 100%;
  background: linear-gradient(120deg, transparent 0%, rgba(255,255,255,.35) 50%, transparent 100%);
  transition: left .45s ease;
  pointer-events: none;
}
.header-donate-btn:hover::after { left: 160%; }
.header-donate-btn i {
  font-size: .95em;
  display: inline-block;
  animation: h2h-give-heartbeat 2s ease-in-out infinite;
}
.header-donate-btn:hover,
.header-donate-btn:focus-visible {
  background: #34d96a;             /* a touch lighter for lift */
  border-color: var(--h2h-green, #10B981);
  transform: translateY(-1px);
  color: #082a14;
  animation: none;
  box-shadow: 0 5px 16px rgba(16,185,129,.38);
}
.header-donate-btn:hover i,
.header-donate-btn:focus-visible i { animation: none; transform: scale(1.15); }
/* Scrollspy active state — lit with a soft ring when the Donate section is in
   view, so the nav reflects "you're here" instead of leaving Recaps highlighted. */
.header-donate-btn--active {
  box-shadow: 0 0 0 3px rgba(16,185,129,.32), 0 6px 18px rgba(16,185,129,.42);
}
.header-donate-btn:active {
  transform: translateY(0);
  box-shadow: 0 2px 8px rgba(16,185,129,.20);
}

/* ════ Modern nav — skyline-bleed hero · scroll-frosted floating bar · glide ════ */

/* Hero bleeds up under the transparent header so the skyline reads edge to edge.
   The pull equals the header's occupied height; content is padded back down so
   the tagline never sits under the nav. */
body.page-main-home #home { margin-top: -94px; padding-top: 94px; box-sizing: border-box; }
@media (max-width: 767px) { body.page-main-home #home { margin-top: -76px; padding-top: 76px; } }
/* Because the hero is pulled up under the header, it must be a FULL viewport tall
   (not 100vh − header) or it would end short of the fold. svh keeps it honest on
   phones; vh is the fallback. */
body.page-main-home #home.home-hero { min-height: 100vh; min-height: 100svh; }
@media (max-width: 767px) { body.page-main-home #home.home-hero { min-height: 100vh; min-height: 100svh; } }

/* Header is transparent over the hero, then a full-width frosted bar (via ::before)
   once you scroll into the content — keeps the links legible + reads editorial. */
.section-main .portal-header {
  /* Pill styling removed — the scrolled treatment is the full-bleed ::before bar.
     Keep only the transition for the frost fade-in. */
  transition: background .25s ease;
}
.section-main .portal-header.is-scrolled {
  /* Strips the old rounded floating-pill geometry (radius, inset padding, element
     background, shadow) so the header content sits flush on the --container spine.
     The frosted-glass look itself — backdrop-blur + tint + edges — is applied by the
     .header-scrolled frost rules above; deliberately NOT overriding backdrop-filter
     here (an earlier `none` here silently cancelled the frost). */
  background: transparent;
  border-color: transparent;
  box-shadow: none;
  padding: .6rem 0;
  border-radius: 0;
}

/* (nav glide + inline-link hover now in styles-base.css, shared site-wide) */
@media (max-width: 480px) {
  .header-donate-btn {
    height: 38px;
    padding: 0 .95rem;
    font-size: .74rem;
    letter-spacing: .07em;
  }
}

/* ════════ Mobile menu (main site) — engaging full-screen nav ════════
   Rebuilt as a conversion moment, not just a link list: icon rows, a lit
   active item, prominent Serve + Give actions, and quick contact. Scoped to
   .section-main so the portal/fundraiser/admin overlays are untouched. */
.section-main .snav-fs { padding: 0; display: block; }
.section-main .snav-fs-inner {
  position: relative; z-index: 1;
  min-height: 100%;
  width: 100%; max-width: 540px; margin: 0 auto;
  display: flex; flex-direction: column;
  padding: clamp(1rem, 4.5vw, 1.6rem) clamp(1.4rem, 7vw, 2.4rem) clamp(1.5rem, 6vw, 2.2rem);
  box-sizing: border-box;
}
.section-main .snav-fs-top {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: clamp(.4rem, 3vw, 1rem);
}
/* Real H2H logo anchors the top of the menu — echoes the collapsed bar so the
   overlay reads as a continuation of the header, and it's automatically on-brand
   (no risk of hand-colored text drifting from the actual mark). */
.section-main .snav-fs-logolink { display: inline-flex; align-items: center; text-decoration: none; }
.section-main .snav-fs-logo { height: 40px; width: auto; display: block; }
/* the × button is already styled in styles-base; unpin it from absolute so it
   sits in the top row beside the logo */
.section-main .snav-fs .snav-fs-close { position: static; top: auto; right: auto; }

/* link list — vertically centered in the space between header and CTAs */
.section-main .snav-fs-links {
  flex: 1 1 auto; display: flex; flex-direction: column; justify-content: center;
  gap: 0;
  padding: clamp(.2rem, 1.5vw, .5rem) 0;
}
/* Editorial link: typography does the work — no icon, no caret. Big Barlow
   Condensed with a hairline between rows (echoes the section hairlines). */
.section-main .snav-fs .snav-fs-link {
  display: block;
  font-family: 'Barlow Condensed','Bebas Neue',sans-serif;
  font-weight: 600; letter-spacing: .005em; line-height: 1;
  font-size: clamp(1.6rem, 7vw, 2.2rem);
  color: rgba(233,238,247,.82);
  padding: clamp(.35rem, 2.1vw, .62rem) 0;
  border-bottom: 1px solid rgba(255,255,255,.08);
}
.section-main .snav-fs-links .snav-fs-link--home { border-top: 1px solid rgba(255,255,255,.08); }
/* Home = icon only, sitting on the same baseline as the words below it */
.section-main .snav-fs .snav-fs-ico--home {
  display: inline-block; font-size: .95em; opacity: 1;
  color: rgba(233,238,247,.82);
  transition: color .2s ease;
}
/* Active = gold text (and gold home glyph), nothing else — one gold item, ration kept */
.section-main .snav-fs .snav-fs-link--active { color: var(--h2h-gold, #D8A85A); }
.section-main .snav-fs .snav-fs-link--active .snav-fs-ico--home { color: var(--h2h-gold, #D8A85A); }

/* Serve + Give — the actions that get people involved */
.section-main .snav-fs-actions {
  display: flex; flex-direction: column; gap: .7rem;
  margin-top: clamp(.7rem, 4vw, 1.3rem);
}
.section-main .snav-fs-cta {
  display: flex; align-items: center; justify-content: center; gap: .6rem;
  height: 56px; border-radius: 15px; text-decoration: none;
  font-family: 'Oswald', system-ui, sans-serif; text-transform: uppercase;
  letter-spacing: .07em; font-weight: 600; font-size: 1.06rem;
  transition: transform .12s ease, box-shadow .2s ease, filter .2s ease;
}
.section-main .snav-fs-cta i { font-size: 1.25em; }
.section-main .snav-fs-cta--serve {
  background: linear-gradient(120deg, #E2BD70, #D8A85A);
  color: #1c1404; box-shadow: 0 12px 28px rgba(216,168,90,.30);
}
.section-main .snav-fs-cta--give {
  background: var(--h2h-green, #10B981);
  color: #04230f; box-shadow: 0 12px 28px rgba(16,185,129,.28);
}
.section-main .snav-fs-cta:active { transform: translateY(1px); filter: brightness(1.05); }

/* quick contact row */
.section-main .snav-fs-foot {
  display: flex; gap: .7rem; justify-content: center;
  margin-top: clamp(.9rem, 5vw, 1.6rem);
}
.section-main .snav-fs-foot a {
  width: 46px; height: 46px; border-radius: 13px;
  display: flex; align-items: center; justify-content: center;
  color: rgba(233,238,247,.72); font-size: 1.3rem; text-decoration: none;
  background: rgba(255,255,255,.05); border: 1px solid rgba(255,255,255,.1);
  transition: color .2s ease, border-color .2s ease, background .2s ease;
}
.section-main .snav-fs-foot a:active {
  background: rgba(216,168,90,.14); border-color: rgba(216,168,90,.4); color: #fff;
}

/* entrance: CTAs + contact row cascade in with the links (delays set in JS) */
.section-main .snav-fs-cta,
.section-main .snav-fs-foot {
  opacity: 0; transform: translateY(20px);
  transition: opacity .3s ease, transform .3s ease,
              box-shadow .2s ease, filter .2s ease;
}
.section-main .snav-fs.is-open .snav-fs-cta,
.section-main .snav-fs.is-open .snav-fs-foot { opacity: 1; transform: translateY(0); }
@media (prefers-reduced-motion: reduce) {
  .section-main .snav-fs-cta,
  .section-main .snav-fs-foot { opacity: 1; transform: none; transition: none; }
}

/* ════════ Smart "next mission" action bar ════════
   Follows the reader past the hero so signing up for the next open event is
   always a tap away; slides away over Events/Donate/Join. Mobile = bottom bar,
   desktop = compact corner pill. */
/* Screen-reader-only utility — visually hidden but announced by assistive tech.
   Used for the hero's top-level <h1> so the page has a proper heading spine
   without altering the animated visual tagline. */
body.page-main-home .sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}
body.page-main-home .next-bar {
  position: fixed; z-index: 1015;
  left: 12px; right: 12px; bottom: 12px;
  transform: translateY(170%); opacity: 0; pointer-events: none;
  transition: transform .42s cubic-bezier(.22,.61,.36,1), opacity .3s ease;
}
body.page-main-home .next-bar.is-visible { transform: none; opacity: 1; pointer-events: auto; }
body.page-main-home .next-bar-inner {
  display: flex; align-items: center; gap: .55rem;
  padding: .4rem .5rem .4rem .68rem;
  border-radius: 13px;
  background: rgba(13,20,34,.88);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  border: 1px solid rgba(255,255,255,.1);
  box-shadow: 0 10px 30px rgba(0,0,0,.45);
}
body.page-main-home .next-bar-ico {
  flex: 0 0 auto; width: 30px; height: 30px; border-radius: 9px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(255,255,255,.12); color: #fff; font-size: 1rem;
}
body.page-main-home .next-bar-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; line-height: 1.16; }
body.page-main-home .next-bar-event {
  font-weight: 700; color: #f3f6fb; font-size: .86rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
body.page-main-home .next-bar-when {
  font-family: 'Oswald', system-ui, sans-serif; text-transform: uppercase;
  letter-spacing: .07em; font-size: .63rem; font-weight: 600; color: var(--h2h-gold,#D8A85A);
}
body.page-main-home .next-bar-cta {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: .35rem;
  /* Gold to match the Events "Sign Up" (same action → same colour). No resting
     glow — the gold glow arrives on hover, like the other primaries. */
  background: var(--h2h-gold,#D8A85A); color: #1a1206; text-decoration: none;
  font-family: 'Oswald', system-ui, sans-serif; text-transform: uppercase;
  letter-spacing: .04em; font-weight: 600; font-size: .77rem;
  padding: .45rem .8rem; border-radius: 9px;
  transition: transform var(--btn-ease, 160ms ease), box-shadow var(--btn-ease, 160ms ease), filter .2s ease;
}
body.page-main-home .next-bar-cta:hover { transform: translateY(-1px); box-shadow: 0 6px 18px rgba(216,168,90,.30); }
body.page-main-home .next-bar-cta:active { transform: translateY(1px); filter: brightness(1.05); box-shadow: 0 2px 8px rgba(216,168,90,.22); }
body.page-main-home .next-bar-x {
  flex: 0 0 auto; width: 26px; height: 26px; border: 0; background: transparent;
  color: rgba(233,238,247,.5); font-size: 1.25rem; line-height: 1; cursor: pointer; border-radius: 8px;
  transition: color .2s ease, background .2s ease;
}
body.page-main-home .next-bar-x:hover { color: #fff; background: rgba(255,255,255,.08); }
/* very small phones: collapse the CTA label to just the arrow */
@media (max-width: 360px) {
  body.page-main-home .next-bar-cta span { display: none; }
  body.page-main-home .next-bar-cta { padding: .45rem .62rem; }
}
/* desktop: compact corner pill, bottom-right */
@media (min-width: 768px) {
  body.page-main-home .next-bar { left: auto; right: 24px; bottom: 24px; max-width: 430px; }
}
@media (prefers-reduced-motion: reduce) {
  body.page-main-home .next-bar { transition: opacity .3s ease; }
  body.page-main-home .next-bar.is-visible { transform: none; }
}

/* ════════ Moments mosaic — a living band of real faces ════════
   Two rows of recap photos drift in opposite directions (paused on hover); the
   pool is rendered server-side and grows as staff upload, so it's always real
   and current. Edges fade out via a mask so tiles enter/leave gracefully. */
/* Married to In Action above it: SAME deep background, NO divider line, and a
   tight top so the mosaic reads as the closing movement of the same chapter
   ("what showing up looks like" → "the faces behind it"), not a new section. */
body.page-main-home #mosaic { background: #070b14; padding-block: clamp(2rem, 4vw, 3.25rem) clamp(2.4rem, 5vw, 4.25rem); overflow: hidden; }  /* DEEP — a wall of faces, gallery-style on near-black; its own beat after In Action's panel */
body.page-main-home #mosaic::before { content: none; }   /* drop the section divider line */
body.page-main-home #in-action { padding-bottom: clamp(2rem, 4vw, 3.5rem); }  /* match the Impact Band's own top padding (clamp(2rem,4vw,3.5rem)) so the band sits symmetrically between In Action above and Mosaic below — the old 1.6–2.5rem "tight pair with mosaic" value predated the Impact Band being inserted between them, which left the gap above the band visibly shorter than the gap below it. */
.mosaic-head { text-align: center; max-width: 60rem; margin: 0 auto clamp(1.4rem, 3vw, 2.4rem); padding: 0 1.25rem; }
.mosaic-head .section-kicker { margin-bottom: .55rem; }
.mosaic-title {
  font-family: 'Barlow Condensed', 'Bebas Neue', sans-serif;
  font-size: clamp(2rem, 4.2vw, 3.2rem); font-weight: 600; line-height: 1.02;
  letter-spacing: .005em; color: #f4efe4; margin: 0;
}
.mosaic-title em { font-style: normal; color: var(--h2h-gold, #D8A85A); }
/* Break out of the section's side padding to bleed full-viewport-width — a river
   of faces streaming off both edges (the section clips overflow, so no h-scroll).
   The row mask keeps them dissolving softly at the margins, not hard-cut. */
.mosaic-marquee {
  display: flex; flex-direction: column; gap: clamp(.55rem, 1.4vw, 1rem);
  width: 100vw; max-width: 100vw; margin-left: calc(50% - 50vw);
}
.mosaic-row {
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}
/* Spacing lives on each tile (margin), NOT flex gap: with gap, 2N tiles have
   2N−1 gaps, so translateX(-50%) lands half a gap short of a whole tile period
   and the loop hitches. Per-tile margin makes the period exact = seamless. */
.mosaic-track { display: flex; width: max-content; }
.mosaic-track--a { animation: mosaicScroll 64s linear infinite; }
.mosaic-track--b { animation: mosaicScroll 64s linear infinite reverse; }
.mosaic-marquee:hover .mosaic-track,
.mosaic-marquee:focus-within .mosaic-track { animation-play-state: paused; }
@keyframes mosaicScroll { from { transform: translate3d(0,0,0); } to { transform: translate3d(-50%,0,0); } }
/* Fixed HEIGHT, auto width — each photo shows at its own aspect ratio, so nothing
   gets cropped (the old fixed 4:3 + object-fit:cover was cutting faces). Tiles end
   up varying widths; the images load eager (see index.php) so their widths are
   known up front and the marquee period can't shift mid-scroll. */
.mosaic-tile {
  flex: 0 0 auto; height: clamp(116px, 17vw, 184px); width: auto;
  margin-right: clamp(.55rem, 1.4vw, 1rem);   /* tile owns its trailing gap → seamless loop */
  border-radius: 12px; overflow: hidden;
  border: 1px solid rgba(255,255,255,.06); box-shadow: 0 10px 26px rgba(0,0,0,.4);
}
.mosaic-tile img { height: 100%; width: auto; display: block; transition: filter .35s ease; }
/* Hover bloom: marquee pauses + hovered tile warms up, others dim slightly */
.mosaic-marquee:hover .mosaic-tile img { filter: brightness(.82) saturate(.8); }
.mosaic-tile:hover img { filter: brightness(1.14) saturate(1.18) !important; }
.mosaic-cta { text-align: center; margin-top: clamp(.85rem, 1.8vw, 1.3rem); padding-bottom: clamp(.5rem, 1.5vw, 1rem); }
.mosaic-cta-line {
  font-family: 'Barlow Condensed', 'Oswald', sans-serif;
  font-size: clamp(1.05rem, 2.2vw, 1.35rem);
  font-weight: 500;
  letter-spacing: .01em;
  color: rgba(233,238,247,.72);
  margin: 0 0 clamp(.9rem, 2vw, 1.4rem);
  font-style: italic;
}
/* Mosaic "Serve with us" is the same secondary invitation as the In Action one,
   so it is styled entirely by the shared button system — no bespoke size, resting
   glow, or hover lift (that asymmetry made the two look like different tiers). */
@media (prefers-reduced-motion: reduce) {
  .mosaic-track--a, .mosaic-track--b { animation: none; }
  .mosaic-row { overflow-x: auto; }
}

/* ======================================================================
   DONATE MODAL (.dm-*) — year-round Stripe giving overlay
   ====================================================================== */
.dm-overlay {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: none;
  align-items: flex-start;
  justify-content: center;
  padding: 4vh 1rem;
  overflow-y: auto;
}
.dm-overlay.is-open { display: flex; }
body.dm-locked { overflow: hidden; }

.dm-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(6, 10, 18, .72);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}

.dm-dialog {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 460px;
  background: #0e1420;
  border: 1px solid rgba(255,255,255,.14);
  border-radius: 18px;
  box-shadow: 0 30px 80px rgba(0,0,0,.55);
  padding: 1.75rem 1.6rem 1.6rem;
  color: #e9eef7;
  transform: translateY(14px);
  opacity: 0;
  transition: transform .28s ease, opacity .28s ease;
}
.dm-overlay.is-open .dm-dialog { transform: translateY(0); opacity: 1; }

.dm-close {
  position: absolute;
  top: .85rem; right: .9rem;
  width: 34px; height: 34px;
  border-radius: 10px;
  border: 1px solid rgba(255,255,255,.14);
  background: rgba(255,255,255,.05);
  color: rgba(233,238,247,.75);
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer;
  transition: background .15s ease, color .15s ease;
}
.dm-close:hover { background: rgba(255,255,255,.10); color: #fff; }

.dm-head { margin-bottom: 1.1rem; }
.dm-title {
  font-family: 'Bebas Neue', sans-serif;
  font-size: 2rem;
  letter-spacing: .02em;
  color: var(--h2h-gold, #D8A85A);
  line-height: 1;
}
.dm-progress { display: flex; gap: .4rem; margin-top: .7rem; }
.dm-dot {
  width: 26px; height: 4px; border-radius: 999px;
  background: rgba(255,255,255,.14);
  transition: background .25s ease;
}
.dm-dot.is-active { background: var(--h2h-gold, #D8A85A); }

/* Steps: only the active one shows */
.dm-step { display: none; }
.dm-step.is-active { display: block; animation: dmFade .25s ease; }
@keyframes dmFade { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

.dm-step-h {
  font-size: 1.05rem;
  font-weight: 700;
  color: #fff;
  margin-bottom: .5rem;
}
.dm-sub, .dm-trust {
  font-size: .82rem;
  line-height: 1.55;
  color: rgba(233,238,247,.6);
  margin-bottom: 1rem;
}
.dm-amt-echo { color: var(--h2h-gold, #D8A85A); font-weight: 700; }

/* Amount grid */
.dm-amounts {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: .6rem;
  margin-bottom: 1rem;
}
.dm-amt {
  padding: .8rem .4rem;
  border-radius: 12px;
  border: 1px solid rgba(255,255,255,.16);
  background: rgba(255,255,255,.06);
  color: #e9eef7;
  font-weight: 700;
  font-size: 1rem;
  cursor: pointer;
  transition: border-color .15s ease, background .15s ease, color .15s ease;
}
.dm-amt:hover { border-color: rgba(216,168,90,.55); }
.dm-amt.selected {
  border-color: var(--h2h-gold, #D8A85A);
  background: rgba(216,168,90,.14);
  color: #f5dfa0;
}

.dm-custom { margin-bottom: 1rem; }
.dm-custom label, .dm-field label {
  display: block;
  font-size: .76rem;
  font-weight: 600;
  letter-spacing: .02em;
  color: rgba(233,238,247,.7);
  margin-bottom: .3rem;
}
.dm-optional { color: rgba(233,238,247,.4); font-weight: 400; }
.dm-custom-field { position: relative; }
.dm-custom-dollar {
  position: absolute; left: .8rem; top: 50%; transform: translateY(-50%);
  color: rgba(233,238,247,.5); font-weight: 700;
}
.dm-custom-field input { padding-left: 1.7rem !important; }

.dm-field { margin-bottom: .8rem; }
.dm-grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: .7rem; }
.dm-step input[type="text"],
.dm-step input[type="email"],
.dm-step input[type="tel"],
.dm-step input[type="number"] {
  width: 100%;
  padding: .7rem .8rem;
  border-radius: 10px;
  border: 1px solid rgba(255,255,255,.16);
  background: rgba(255,255,255,.05);
  color: #e9eef7;
  font-size: .95rem;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.dm-step input:focus {
  outline: none;
  border-color: rgba(216,168,90,.6);
  box-shadow: 0 0 0 3px rgba(216,168,90,.14);
}
.dm-step input.is-invalid { border-color: var(--h2h-red, #CE1126); }

#dm-payment-element { margin: .25rem 0 1rem; min-height: 40px; }

.dm-err {
  background: rgba(206,17,38,.12);
  border: 1px solid rgba(206,17,38,.4);
  color: #ff9bb0;
  border-radius: 10px;
  padding: .6rem .8rem;
  font-size: .82rem;
  margin-bottom: .9rem;
}

.dm-actions { display: flex; gap: .6rem; margin-top: .4rem; }
.dm-btn {
  flex: 1;
  padding: .8rem 1rem;
  border-radius: 999px;
  border: 1px solid transparent;
  font-weight: 700;
  font-size: .9rem;
  cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  transition: filter .15s ease, background .15s ease, border-color .15s ease, opacity .15s ease;
}
.dm-next {
  background: var(--h2h-gold, #D8A85A);
  color: #1a1206;
}
.dm-next:hover { filter: brightness(1.07); }
.dm-next:disabled { opacity: .45; cursor: not-allowed; }
.dm-ghost {
  flex: 0 0 auto;
  background: transparent;
  border-color: rgba(255,255,255,.2);
  color: rgba(233,238,247,.8);
}
.dm-ghost:hover { background: rgba(255,255,255,.06); }

.dm-secure {
  text-align: center;
  margin-top: .9rem;
  font-size: .68rem;
  color: rgba(233,238,247,.32);
}

.dm-spin {
  display: inline-block;
  width: 1em; height: 1em;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  vertical-align: -.15em;
  animation: dmSpin .7s linear infinite;
}
@keyframes dmSpin { to { transform: rotate(360deg); } }

@media (max-width: 420px) {
  .dm-amounts { grid-template-columns: repeat(2, 1fr); }
}

/* ======================================================================
   DONATION THANK-YOU PAGE (/donation_success.php)
   ====================================================================== */
.donate-thanks {
  max-width: 640px;
  margin: 3rem auto;
  text-align: center;
}
.donate-thanks-title {
  font-family: 'Bebas Neue', sans-serif;
  font-size: clamp(3rem, 9vw, 5rem);
  color: var(--h2h-gold, #D8A85A);
  line-height: 1;
}
.donate-thanks-amount {
  font-size: 2.4rem;
  font-weight: 800;
  color: #fff;
  margin: .4rem 0 1rem;
}
.donate-thanks-sub {
  font-size: 1.02rem;
  line-height: 1.6;
  color: rgba(233,238,247,.78);
}
.donate-thanks-note {
  margin-top: 1rem;
  font-size: .82rem;
  color: rgba(233,238,247,.45);
}
.donate-thanks-actions {
  margin-top: 2rem;
  display: flex;
  gap: .8rem;
  justify-content: center;
  flex-wrap: wrap;
}
.donate-thanks-card {
  margin-top: 2.5rem;
  background: rgba(255,255,255,.06);
  border: 1px solid rgba(255,255,255,.14);
  border-radius: 16px;
  padding: 1.6rem;
}
.donate-thanks-error {
  max-width: 520px;
  margin: 3rem auto;
  text-align: center;
  background: rgba(255,255,255,.06);
  border: 1px solid rgba(255,255,255,.14);
  border-radius: 16px;
  padding: 2rem;
}

/* ======================================================================
   CONTACT SECTION (#contact)
   ====================================================================== */
#contact .contact-grid {
  display: grid;
  grid-template-columns: var(--editorial-spread-cols);
  gap: 3rem;
  column-gap: var(--editorial-spread-gap);
  align-items: start;   /* founders/reach panel and form top-align; form sizes to content */
  /* Content sits BELOW the full-width header and aligns under its title text
     (indented past the accent bar), matching every other section. */
  max-width: calc(var(--ed-col-max) - var(--ed-col-indent));
  margin-left: var(--ed-col-indent);
  margin-right: auto;
}
@media (max-width: 820px) {
  #contact .contact-grid { grid-template-columns: 1fr; gap: 2rem; margin-left: 0; max-width: none; }
}
.contact-left { display: flex; flex-direction: column; gap: 1.75rem; }
/* ── Contact — editorial reach list replaces icon-badge cards ──────────── */
.contact-reach {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  align-items: start;
  gap: 1rem;
  margin-top: 2.75rem;
  padding-top: 2.25rem;
  border-top: 1px solid rgba(233,238,247,.10);
}
/* Each channel: gold-ringed icon above a two-line stack (label + value), all
   centered. Centering the whole column (not the inline content) makes a phone
   number and the word "Facebook" align identically across all four — fixes the
   old ragged spacing where different content widths floated at different spots. */
.contact-reach-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: .6rem;
  padding: .5rem;
  text-decoration: none;
  transition: transform .2s ease;
}
.contact-reach-ring {
  display: inline-flex; align-items: center; justify-content: center;
  width: 52px; height: 52px;
  border-radius: 50%;
  background: rgba(216,168,90,.08);
  border: 1px solid rgba(216,168,90,.35);
  color: var(--h2h-gold, #D8A85A);
  transition: background .2s ease, border-color .2s ease, transform .2s ease;
}
.contact-reach-ring i { font-size: 1.35rem; }
.contact-reach-label {
  font-family: 'Oswald', sans-serif; font-size: .66rem; font-weight: 500;
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--label-muted, rgba(210,200,182,.7));
}
.contact-reach-value {
  font-size: .95rem; color: rgba(233,238,247,.82);
  line-height: 1.3; word-break: break-word;
}
.contact-reach-item:hover { transform: translateY(-3px); }
.contact-reach-item:hover .contact-reach-ring {
  background: rgba(216,168,90,.16);
  border-color: rgba(216,168,90,.7);
  transform: scale(1.06);
}
.contact-reach-item:hover .contact-reach-value { color: #fff; }
@media (prefers-reduced-motion: reduce) {
  .contact-reach-item, .contact-reach-ring { transition: none; }
  .contact-reach-item:hover { transform: none; }
  .contact-reach-item:hover .contact-reach-ring { transform: none; }
}
@media (max-width: 820px) {
  /* Mobile: 4-across is too cramped — wrap to a comfortable 2×2 grid. The
     stacked-column design already centers cleanly, so no divider rework needed. */
  .contact-reach { grid-template-columns: 1fr 1fr; gap: 1.75rem 1rem; margin-top: 2.25rem; padding-top: 1.75rem; }
}

/* Form — no card wrapper; fields sit directly on the page */
.contact-form-wrap {
  position: relative;
  display: flex;
  flex-direction: column;
  /* Fields cap at a comfortable interaction width so they don't stretch to the
     full editorial column on ultra-wide (the column itself stays unified with
     About). Fixed px, not rem — a form field's comfortable width is absolute, not
     a type-scaled reading measure. No effect at ≤1440 (column is already ~624px). */
  max-width: 660px;
  /* Left padding makes room for the gold spine hairline (below) so fields don't
     butt against it. */
  padding-left: clamp(1.5rem, 3vw, 2.5rem);
}
/* Gold hairline spine on the form's left edge — carries the hero's gold
   cross-spine motif down into Contact, so the form reads as a continuation of the
   founders' invitation across the row, not a separate widget. Typography + one
   hairline; no card chrome. Drawn as a soft-capped gradient line (brightest at
   center, fading at both ends) so it feels lit, not ruled. Two-column layout only
   — removed on the mobile stack where a left edge line would be arbitrary. */
.contact-form-wrap::before {
  content: "";
  position: absolute; left: 0; top: .25rem; bottom: .25rem;
  width: 2px;
  border-radius: 2px;
  background: linear-gradient(to bottom,
    rgba(216,168,90,.05), rgba(216,168,90,.7) 50%, rgba(216,168,90,.05));
  box-shadow: 0 0 12px rgba(216,168,90,.28);
  pointer-events: none;
}
.contact-form {
  display: flex;
  flex-direction: column;
}
.contact-form .cf-float:has(textarea) {
  display: flex; flex-direction: column;
}
.contact-form textarea.cf-input {
  min-height: 120px; height: 120px; resize: vertical;
}
/* Founders photo in Contact (moved here from About) */
.contact-founders-feature { margin: 0 0 1.75rem; }
.contact-founders-feature img {
  width: 100%;
  max-width: 460px;
  height: auto;
  border-radius: 16px;
  display: block;
}
/* "FOUNDED BY …" caption — same treatment as the About group-photo caption
   (.origin-proof-cap): a gold-accented gradient bar overlaid on the photo, Oswald
   uppercase, letter-spaced. Anchored inside .contact-founders-stage (position:
   relative). The founders photo fills its image box down to the bottom edge (the
   subjects extend to the base of the frame), so the caption sits flush at
   bottom:0 — the true bottom edge of the photo, exactly like the About group
   photo. The image's bottom mask-fade is gentle enough that the caption text
   remains crisp there (verified on dev). */
.contact-founders-feature-cap {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; align-items: center; justify-content: center; gap: .5rem;
  padding: .7rem 1.2rem; margin: 0;
  z-index: 2;
  text-align: center;
  color: rgba(244,239,228,.94);
  font-family: 'Oswald', sans-serif;
  font-size: .66rem; font-weight: 500;
  letter-spacing: .16em; text-transform: uppercase;
  background: linear-gradient(0deg, rgba(11,17,32,.66), rgba(11,17,32,.12) 72%, transparent);
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
  pointer-events: none;
}
/* Founders' voice — now the emotional ANCHOR of the section: centered below the
   photo and enlarged so the invitation, not the form, is what the eye lands on.
   Same Fraunces italic signature as the Ansel quote, taken up a tier. Closing
   phrase lifts to gold so the invitation carries warmth without needing a button. */
.contact-founders-voice {
  margin: 1.1rem 0 0;
  text-align: center;
  font-family: 'Fraunces', Georgia, serif;
  font-style: italic;
  font-weight: 300;
  font-size: clamp(1.5rem, 2.4vw, 2rem);
  line-height: 1.35;
  color: rgba(233,238,247,.94);
}
.contact-founders-voice .cfv-invite { color: rgba(216,168,90,.9); }

/* ── Contact form fields ───────────────────────────────────── */
.contact-form .cf-float { position: relative; margin-bottom: 1.1rem; }
.contact-form .cf-float > .cf-input {
  display: block; width: 100%;
  height: 54px; min-height: 54px;
  padding: .95rem 1rem;
  font-size: .98rem; font-family: inherit;
  background: rgba(255,255,255,.04);
  border: 1.5px solid rgba(255,255,255,.14);
  border-radius: 12px;
  color: #f4f6fb;
  transition: background .2s ease, border-color .2s ease, box-shadow .2s ease;
}
.contact-form .cf-float > textarea.cf-input {
  height: 130px; min-height: 130px; padding: 1rem;
  line-height: 1.5; resize: vertical;
}
.contact-form .cf-float > .cf-input::placeholder { color: transparent; }   /* the label is the placeholder; hide the real one */
.contact-form .cf-float > .cf-input:focus {
  outline: none;
  background: rgba(255,255,255,.06);
  border-color: var(--h2h-gold, #D8A85A);
  box-shadow: 0 0 0 4px rgba(216,168,90,.14);
  color: #fff;
}
/* Floating label — sits as the placeholder at rest, then LIFTS to straddle the
   top border on focus/fill (Material-style notched label). The little pill of
   navy background behind the lifted label masks the border line so the label
   reads as "cut into" the outline, not floating over it. */
.contact-form .cf-float > label {
  position: absolute; top: 50%; left: 1rem;
  transform: translateY(-50%);
  padding: 0 .35rem;
  font-size: .98rem;
  color: rgba(233,238,247,.55);
  pointer-events: none;
  transform-origin: 0 50%;
  transition: top .18s ease, transform .18s ease, color .2s ease;
}
/* textarea label anchors to the top rather than vertical-center */
.contact-form .cf-float:has(textarea) > label { top: 1.05rem; transform: none; }
.contact-form .cf-float > .cf-input:focus ~ label,
.contact-form .cf-float > .cf-input:not(:placeholder-shown) ~ label {
  top: 0;
  transform: translateY(-50%) scale(.82);
  color: var(--h2h-gold, #D8A85A);
  /* Backing for the lifted label: a THIN horizontal strip (transparent above/below,
     opaque only across the ~26% band where the border line sits) rather than a
     full pill. A full pill read as a visible dark patch because the section has a
     gold radial overlay here, so no flat color matches the tinted background. The
     strip only masks the 1.5px border stroke, so the label reads as notched into
     the outline with no patch. rgb(26,25,26) = the gold overlay composited over
     the section bg, so the tiny visible sliver blends. */
  background: linear-gradient(to bottom,
    transparent 0%, transparent 40%,
    rgb(26,25,26) 40%, rgb(26,25,26) 66%,
    transparent 66%, transparent 100%);
  border-radius: 0;
}
/* Icon-bearing fields: label + input clear the icon at rest; on lift the label
   snaps back to the border-notch position (icon no longer relevant up there). */
.contact-form .cf-float.cf-has-icon > .cf-input { padding-left: 2.9rem; }
.contact-form .cf-float.cf-has-icon > label { left: 2.9rem; }
.contact-form .cf-float.cf-has-icon > .cf-input:focus ~ label,
.contact-form .cf-float.cf-has-icon > .cf-input:not(:placeholder-shown) ~ label {
  left: 1rem;
}
.contact-form .cf-field-icon {
  position: absolute;
  left: 1.05rem; top: 27px;
  transform: translateY(-50%);
  font-size: 1.1rem;
  color: rgba(233,238,247,.35);
  pointer-events: none;
  z-index: 3;
  transition: color .2s ease;
}
.contact-form .cf-float:focus-within .cf-field-icon { color: var(--h2h-gold, #D8A85A); }
@media (prefers-reduced-motion: reduce) {
  .contact-form .cf-float > label { transition: none; }
}

.cf-field { margin-bottom: 1rem; }
.cf-toggle-label {
  display: block;
  font-size: .76rem;
  font-weight: 600;
  letter-spacing: .02em;
  color: rgba(233,238,247,.7);
  margin-bottom: .5rem;
}

.cf-toggle {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  width: fit-content;
  min-width: 230px;
  padding: 3px;
  border: 1px solid rgba(255,255,255,.14);
  border-radius: 999px;
  background: rgba(255,255,255,.04);
}
.cf-toggle::before {
  content: '';
  position: absolute;
  top: 3px; bottom: 3px; left: 3px;
  width: calc(50% - 3px);
  border-radius: 999px;
  background: linear-gradient(135deg, #e4b96e, var(--h2h-gold, #D8A85A));
  box-shadow: 0 2px 12px rgba(216,168,90,.4);
  transition: transform .32s cubic-bezier(.22, .61, .36, 1);
  z-index: 0;
}
.cf-toggle:has(.cf-toggle-btn[data-method="phone"].is-active)::before {
  transform: translateX(100%);
}
.cf-toggle-btn {
  position: relative;
  z-index: 1;
  padding: .55rem 1.1rem;
  background: transparent;
  border: 0;
  border-radius: 999px;
  color: rgba(233,238,247,.62);
  font-weight: 700;
  font-size: .85rem;
  cursor: pointer;
  transition: color .25s ease;
}
.cf-toggle-btn.is-active { color: #1a1206; }
@supports not selector(:has(a)) {
  /* Fallback for browsers without :has() — JS still toggles .is-active, so
     the active option stays legible via a plain background tint. */
  .cf-toggle-btn.is-active { background: rgba(216,168,90,.22); }
}

/* Honeypot — keep in the DOM but out of sight and off the tab order */
.cf-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.cf-status {
  border-radius: 10px;
  padding: .6rem .8rem;
  font-size: .85rem;
  margin-bottom: .9rem;
}
.cf-status.is-ok    { background: rgba(16,185,129,.12);  border: 1px solid rgba(16,185,129,.4);  color: #6EE7B7; }
.cf-status.is-error { background: rgba(206,17,38,.12);   border: 1px solid rgba(206,17,38,.4);   color: #ff9bb0; }

/* Submit: make it a SOLID gold primary CTA (the shared .btn-gold is a ghost,
   which reads too weak for the form's main action). Matches "Give Now". */
.contact-form .cf-submit {
  width: auto;
  align-self: flex-start;
  margin-top: .5rem;
  background: var(--h2h-gold, #D8A85A) !important;
  color: #1a1206 !important;
  border: 1px solid var(--h2h-gold, #D8A85A) !important;
  font-weight: 800;
  padding: .8rem 1.5rem;
}
/* No resting glow — the 1px lift + gold glow come from the shared primary-hover
   rule, so Send Message behaves exactly like the Events "Sign Up" button. */
.contact-form .cf-submit:hover {
  background: #e4b96e !important;
  border-color: #e4b96e !important;
}
/* Under-form reassurance line — fills the tall-screen right-column void and
   warms up the ask. Muted neutral so it stays quiet beneath the CTA. */
.contact-form-note {
  display: flex;
  align-items: flex-start;
  gap: .55rem;
  margin: 1.5rem 0 0;
  padding-top: 1.25rem;
  border-top: 1px solid rgba(233,238,247,.1);
  font-size: .9rem;
  line-height: 1.55;
  color: rgba(233,238,247,.6);
}
.contact-form-note i {
  color: rgba(216,168,90,.8);
  font-size: 1.05rem;
  line-height: 1.4;
  flex-shrink: 0;
}

/* ======================================================================
   UNIFIED BUTTON SYSTEM (main site)
   One shared shape + type language for every CTA — Oswald, uppercase,
   weight 600, .06em tracking, a single 8px radius — ending the
   6/8/10/11/12/15px radius scatter and the mixed Inter / 500 / 700 weights
   (the always-visible header Give button was Inter/700/.09em; .btn-gold was
   `capitalize`). Each button's colour, size, and animation stay in its own
   component rule below; this layer only unifies shape + type. The
   body.section-main prefix keeps specificity high enough to win cleanly over
   the component rules WITHOUT !important, and scopes it to the public main
   site (portal / fundraiser / admin untouched).
   Colour logic: GOLD = serve/engage, GREEN = give money. Documented
   exception: the next-bar "Save my spot" is blue (the Hands sign-up action —
   green stays reserved for Give). Size still scales per context. */
body.section-main :is(
  .btn-gold, .cf-submit,
  .header-donate-btn, .snav-fs-cta,
  .join-btn, .next-bar-cta,
  .donate-way-cta,
  .recap-see-all, .recap-all-close
) {
  font-family: 'Oswald', system-ui, sans-serif;
  text-transform: uppercase;
  font-weight: 600;
  letter-spacing: .06em;
  border-radius: 8px;
}

/* Colour logic fix: the Join band's "Give" was a neutral white ghost with a
   red heart while every other Give reads green. Bring it onto the green
   "give money" language — kept as the lighter secondary so "Serve With Us"
   stays the dominant ask. */
body.section-main .join-btn--give {
  background: rgba(16,185,129,.08);
  border-color: rgba(16,185,129,.45);
  color: #d6f5e6;
}
body.section-main .join-btn--give:hover {
  background: rgba(16,185,129,.16);
  border-color: rgba(16,185,129,.75);
  color: #fff;
}
body.section-main .join-btn--give i { color: var(--h2h-green, #10B981); }

/* ── Size scale + state model ─────────────────────────────────────
   Three deliberate sizes (was ~10 ad-hoc paddings) and ONE state behaviour per
   tier, so both size and elevation carry meaning:
     • lg — closing / hero CTAs (Join)
     • md — standard section CTAs (serve, Save My Spot, Send, Give Now)
     • sm — inline / low-stakes (Remind Me, calendar, See all)
   PRIMARY (solid) lifts 1px with a single-blur shadow in its own colour;
   SECONDARY (outline) + TERTIARY (text) shift tonally with NO lift — so a lift
   always signals "this is the main action" (replaces the old 3–42px random
   glows). Header Give, mobile-nav CTAs and the toast keep their context-fixed
   sizes on purpose. */
:root { --btn-ease: 160ms cubic-bezier(.2,.6,.35,1); }

body.section-main :is(
  .btn-gold, .cf-submit, .join-btn,
  .donate-way-cta,
  .recap-see-all, .recap-all-close
) {
  transition: color var(--btn-ease), background var(--btn-ease),
              border-color var(--btn-ease), box-shadow var(--btn-ease),
              transform var(--btn-ease);
}

/* size — lg / md / sm (pure-text buttons take no box) */
body.section-main .join-btn { padding: .9rem 2.1rem; font-size: 1rem; min-height: 52px; }
body.section-main :is(.btn-gold, .cf-submit, .donate-way-cta--give) {
  padding: .55rem 1.2rem; font-size: .84rem; min-height: 42px;
}
body.section-main .recap-see-all {
  padding: .4rem .9rem; font-size: .78rem; min-height: 36px;
}

/* PRIMARY lift — gold */
body.section-main :is(.cf-submit, .join-btn--serve):hover {
  transform: translateY(-1px); box-shadow: 0 6px 18px rgba(216,168,90,.30);
}
body.section-main :is(.cf-submit, .join-btn--serve):active {
  transform: translateY(0); box-shadow: 0 2px 8px rgba(216,168,90,.22);
}
/* PRIMARY lift — green */
body.section-main .donate-way-cta--give:hover {
  transform: translateY(-1px); box-shadow: 0 6px 18px rgba(16,185,129,.30);
}
body.section-main .donate-way-cta--give:active {
  transform: translateY(0); box-shadow: 0 2px 8px rgba(16,185,129,.22);
}
/* SECONDARY = tonal shift only, no lift */
body.section-main .join-btn--give:hover { transform: none; }
/* "Serve With Us" is the evergreen invitation → SECONDARY gold outline, leaving
   the solid "Sign Up" as the page's one clear primary. Base .btn-gold already
   gives gold text + border + tonal hover; dropping it from the lift group above
   removes the primary-style hover lift, and this crisps it to a clean outline.
   (:not(.cf-submit) so the gold Send Message primary is unaffected.) */
body.section-main .btn-gold:not(.cf-submit) {
  background: transparent;
  border-color: rgba(216,168,90,.55);
}
body.section-main .btn-gold:not(.cf-submit):hover { box-shadow: none; }

/* Universal keyboard focus ring + disabled + reduced-motion */
body.section-main :is(
  .btn-gold, .cf-submit, .join-btn,
  .donate-way-cta,
  .recap-see-all, .recap-all-close
):focus-visible {
  outline: 2px solid rgba(216,168,90,.75); outline-offset: 2px;
}
body.section-main :is(.btn-gold, .cf-submit, .join-btn, .recap-see-all):disabled {
  opacity: .5; cursor: not-allowed; transform: none; box-shadow: none;
}
@media (prefers-reduced-motion: reduce) {
  body.section-main :is(.btn-gold, .cf-submit, .join-btn, .donate-way-cta--give):hover { transform: none; }
}

/* ── Gold discipline — reserve gold for action + deliberate accent ────────
   Gold was carrying kickers, eyebrows AND captions on top of buttons and title
   accents, so it had stopped meaning anything. Drop the incidental labels to a
   warm muted neutral; gold now reads as "action" (buttons) or a deliberate
   editorial accent (the title <em> words, the impact stats). One token — tune
   --label-muted to taste. */
:root { --label-muted: rgba(210,200,182,.78); }
body.section-main :is(
  .mse-kicker, .event-eyebrow, .impact-band-kicker,
  .contact-founders-feature-cap, .about-founders-feature-cap,
  .recap-tile-eyebrow, .recap-more-eb, .recap-all-eb,
  .recap-ledger-count,
  .evt-cd-pr-label, .recap-lb-eyebrow
) {
  color: var(--label-muted);
}

/* ======================================================================
   EVENTS SECTION (#events)
   ====================================================================== */
#events .landing-wrap { max-width: var(--container); }
.event-eyebrow {
  font-family: 'DM Sans', sans-serif;
  font-weight: 700; font-size: .82rem; letter-spacing: .12em; text-transform: uppercase;
  color: var(--h2h-gold, #D8A85A);
  margin-bottom: .5rem;
}
/* Live countdown to the next open event — urgency + momentum, ticks via JS. */
.evt-countdown {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .3rem 1rem;
  margin: .2rem 0 1.1rem;
  font-family: 'Barlow Condensed', sans-serif;
}
.evt-cd-label {
  align-self: center;
  margin-right: .15rem;
  font-family: 'Oswald', sans-serif;
  text-transform: uppercase;
  letter-spacing: .12em;
  font-size: .92rem;
  color: rgba(233,238,247,.62);
}
.evt-cd-unit { display: inline-flex; align-items: baseline; gap: .3rem; }
.evt-cd-unit b {
  font-weight: 700;
  font-size: 1.65rem;
  line-height: 1;
  color: var(--h2h-gold, #D8A85A);
  font-variant-numeric: tabular-nums;
}
.evt-cd-unit > span {
  font-family: 'Oswald', sans-serif;
  text-transform: uppercase;
  letter-spacing: .08em;
  font-size: .85rem;
  color: rgba(233,238,247,.5);
}
/* Partner spotlight row — sits below the countdown digits */
.evt-cd-partner-row {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1.1rem;
  padding-top: .7rem;
  margin-top: .1rem;
  border-top: 1px solid rgba(233,238,247,.13);
}
.evt-cd-pr-label {
  font-family: 'Oswald', sans-serif;
  font-size: .85rem;
  font-weight: 400;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: rgba(233,238,247,.5);
  white-space: nowrap;
}
.evt-cd-pr-wrap {
  position: relative;
  height: 52px;
  min-width: 140px;
  flex-shrink: 0;
}
/* Logos anchor to the wrap's LEFT edge (not centered) so the gap between the
   "Made possible by" label and the logo stays constant regardless of how
   wide or narrow each partner's logo is — narrow logos no longer float far
   from the text, and wide logos no longer crowd against it. */
.evt-cd-pr-img {
  position: absolute;
  top: 50%; left: 0;
  transform: translateY(-50%);
  height: 44px;
  width: auto;
  max-width: 160px;
  object-fit: contain;
  display: block;
  transition: opacity .5s ease;
  filter: brightness(1.15);
}
/* Reserved caption line beneath the spotlight, for the rare partner who gets
   a one-line callout (currently just our very first partner). Stays present
   and empty for everyone else in the rotation so nothing shifts layout when
   it fades in and out; text + visibility are set per-partner in JS. */
.evt-cd-pr-note {
  width: 100%;
  text-align: center;
  margin-top: .35rem;
  min-height: 1.1em;
  font-family: 'Oswald', sans-serif;
  font-size: .72rem;
  font-weight: 400;
  letter-spacing: .04em;
  color: rgba(216,168,90,.75);
  opacity: 0;
  transition: opacity .5s ease;
}
.evt-cd-pr-note.is-visible { opacity: 1; }
/* ── Open for Sign-Up — strip the old "glass" card chrome and pill badge so this
   list reads in the same editorial language as About / In Action / Recaps.
   Scoped to #events so these win without needing to touch the older,
   now-unused .glass/.evt-open-card/.evt-open-badge rules elsewhere. ──────── */
#events .evt-open-kicker {
  display: flex;
  align-items: center;
  gap: .4rem;
  font-family: 'Oswald', sans-serif;
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--h2h-green, #10B981);
  margin: 0 0 1rem;
}
#events .evt-open-kicker i { font-size: .95rem; }

/* Hero — portrait poster floated left; text wraps naturally beside and below */
.evt-open-hero {
  float: left;
  width: 110px;
  height: auto;
  border-radius: 8px;
  overflow: hidden;
  margin: 0 1.1rem .5rem 0;
}
.evt-open-hero img {
  width: 100%;
  height: auto;
  display: block;
}
/* Placeholder poster — branded cover shown when an open event has no artwork
   yet. Same 110px footprint as a real poster; reads as intentional, not missing. */
.evt-open-hero--ph {
  background: #0b1120;
  /* No border on the placeholder. The white matte on real posters is baked into
     specific hero PNGs, not a universal frame — some real heroes won't have one,
     so forcing a matte on the placeholder would make it LESS consistent, not more.
     The placeholder reads as intentional on its own: gold top-edge, dot-grid, and
     centered logo. box-sizing kept so the 110px footprint matches a real hero. */
  box-sizing: border-box;
}
.evt-ph {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .45rem;
  background: linear-gradient(158deg, #17233f 0%, #0b1120 100%);
  overflow: hidden;
}
.evt-ph > * { position: relative; z-index: 1; }
/* faint gold dot-grid + a slow diagonal sheen so it feels alive */
.evt-ph::before {
  content: ""; position: absolute; inset: 0; z-index: 0;
  background:
    radial-gradient(rgba(216,168,90,.10) 1px, transparent 1.5px) 0 0 / 11px 11px,
    linear-gradient(115deg, transparent 42%, rgba(233,238,247,.07) 50%, transparent 58%);
  background-size: 11px 11px, 260% 100%;
  animation: evtPhSheen 6.5s ease-in-out infinite;
}
/* brand-gradient top edge */
.evt-ph::after {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 3px; z-index: 2;
  background: linear-gradient(90deg, #CE1126 0%, #D8A85A 50%, #1FA6DE 100%);
}
@keyframes evtPhSheen { 0%, 100% { background-position: 0 0, 130% 0; } 50% { background-position: 0 0, -30% 0; } }
.evt-ph-logo {
  width: 64%;
  max-width: 74px;
  height: auto;
  filter: drop-shadow(0 2px 8px rgba(0,0,0,.35));
}
.evt-ph-cat {
  display: inline-flex; align-items: center; gap: .3rem;
  font-family: 'Oswald', sans-serif; font-size: .56rem; font-weight: 500;
  letter-spacing: .13em; text-transform: uppercase; color: rgba(216,168,90,.92);
}
.evt-ph-cat i { font-size: .82rem; }
@media (prefers-reduced-motion: reduce) { .evt-ph::before { animation: none; } }

/* Sheen sweep on REAL event hero art — the same diagonal light pass as the
   placeholder poster (Kendra's request). The container already clips it. */
.evt-open-hero:not(.evt-open-hero--ph) { position: relative; }
.evt-open-hero:not(.evt-open-hero--ph)::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(115deg, transparent 42%, rgba(255,255,255,.16) 50%, transparent 58%);
  background-size: 260% 100%;
  animation: evtHeroSweep 6.5s ease-in-out infinite;
  /* Per-hero phase offset (set inline in the events loop) so 2+ posters shimmer
     staggered, not in lockstep — a synchronized sweep reads mechanical. */
  animation-delay: var(--sweep-delay, 0s);
}
@keyframes evtHeroSweep { 0%, 100% { background-position: 130% 0; } 50% { background-position: -30% 0; } }
@media (prefers-reduced-motion: reduce) { .evt-open-hero:not(.evt-open-hero--ph)::after { animation: none; } }
/* Sheen sweep on the PLACEHOLDER hero too, so the event row reads as one cohesive
   set (a real poster beside a placeholder both shimmer). Separate rule, not a
   merged selector, because the placeholder sits on a DARK navy tile: the real
   hero's .16 white pass is nearly invisible here, so this peak is brighter (.28)
   with a warm gold trailing edge to read on navy the way the white pass reads on a
   light poster. Reuses the same evtHeroSweep keyframes + --sweep-delay stagger.
   z-index 3 rides above the placeholder's dot-grid (.evt-ph::before z0) and gold
   top-edge (.evt-ph::after z2); the container's overflow:hidden clips it. */
.evt-open-hero--ph { position: relative; }
.evt-open-hero--ph::after {
  content: ""; position: absolute; inset: 0; z-index: 3; pointer-events: none;
  background: linear-gradient(115deg,
    transparent 40%,
    rgba(255,255,255,.28) 49%,
    rgba(216,168,90,.22) 51%,
    transparent 60%);
  background-size: 260% 100%;
  animation: evtHeroSweep 6.5s ease-in-out infinite;
  animation-delay: var(--sweep-delay, 0s);
}
@media (prefers-reduced-motion: reduce) { .evt-open-hero--ph::after { animation: none; } }
.impact-strip {
  display: flex;
  flex-direction: row;
  gap: .6rem;
}
/* Desktop: fill full spotlight width */
@media (min-width: 600px) { .impact-strip { flex-wrap: nowrap; } }
/* Mobile: natural width so outer wrapper can scroll it */
@media (max-width: 599px) { .impact-strip { width: max-content; } }

/* "See All" tile — photo mosaic + pulsing gold border */
@keyframes h2h-seeall-pulse {
  0%, 100% { border-color: rgba(216,168,90,.32); box-shadow: 0 0 0 0 rgba(216,168,90,0); }
  50%       { border-color: rgba(216,168,90,.72); box-shadow: 0 0 16px 4px rgba(216,168,90,.16); }
}

/* ── Events Portfolio (portfolio.php) ──────────────────────────────── */

/* Filter bar */
.port-filters {
  display: flex;
  flex-direction: column;
  gap: .75rem;
  margin-bottom: 2rem;
}
.port-filter-group {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .45rem;
}
.port-filter-label {
  font-size: .7rem; font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase;
  color: rgba(233,238,247,.35);
  margin-right: .2rem;
  flex-shrink: 0;
}
.port-filter-btn {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .42rem 1rem;
  background: rgba(255,255,255,.05);
  border: 1px solid rgba(255,255,255,.12);
  border-radius: 999px;
  font-size: .82rem; font-weight: 600;
  color: rgba(233,238,247,.65);
  cursor: pointer;
  transition: background .18s ease, border-color .18s ease, color .18s ease;
}
.port-filter-btn:hover {
  background: rgba(216,168,90,.1);
  border-color: rgba(216,168,90,.35);
  color: rgba(233,238,247,.9);
}
.port-filter-btn--active {
  background: rgba(216,168,90,.15) !important;
  border-color: rgba(216,168,90,.55) !important;
  color: var(--h2h-gold, #D8A85A) !important;
}
.port-filter-count {
  font-size: .72rem; font-weight: 700;
  color: rgba(233,238,247,.4);
}
.port-filter-btn--active .port-filter-count { color: rgba(216,168,90,.7); }

/* Year band */
.port-year-band { margin-bottom: 2.5rem; }
.port-year-band--hidden { display: none; }
.port-year-header {
  display: flex; align-items: center; gap: .85rem;
  margin-bottom: 1rem;
}
.port-year-label {
  font-family: 'Bebas Neue', sans-serif;
  font-size: 2rem; line-height: 1;
  color: var(--h2h-gold, #D8A85A);
  letter-spacing: .04em;
  flex-shrink: 0;
}
.port-year-count {
  font-size: .75rem; font-weight: 600;
  color: rgba(233,238,247,.35);
  flex-shrink: 0;
}
.port-year-rule {
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, rgba(216,168,90,.3), transparent);
}

/* Compact card grid — 4 col desktop, 3 tablet, 2 mobile */
.port-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: .85rem;
}
@media (max-width: 900px) { .port-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 600px) { .port-grid { grid-template-columns: repeat(2, 1fr); gap: .6rem; } }

/* Card */
.port-card {
  display: flex; flex-direction: column;
  background: rgba(255,255,255,.06);
  border: 1px solid rgba(255,255,255,.14);
  border-radius: 12px; overflow: hidden;
  text-decoration: none; color: inherit;
  transition: transform .22s ease, border-color .22s ease, box-shadow .22s ease;
}
.port-card:hover {
  transform: translateY(-5px);
  border-color: rgba(216,168,90,.45);
  box-shadow: 0 12px 32px rgba(0,0,0,.35);
}
.port-card--hidden { display: none; }

/* Square hero */
.port-card-media {
  width: 100%;
  aspect-ratio: 1 / 1;
  background: #0a0e18 center/cover no-repeat;
  position: relative;
  overflow: hidden;
  display: flex; align-items: center; justify-content: center;
}
.port-card--has-recap .port-card-media::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(0,0,0,.45) 0%, transparent 55%);
}
.port-card-icon {
  font-size: 2rem;
  color: rgba(233,238,247,.15);
}
/* Event number badge — top-left */
.port-card-num {
  position: absolute; top: .5rem; left: .5rem;
  font-size: .65rem; font-weight: 800; letter-spacing: .04em;
  background: rgba(0,0,0,.6);
  border: 1px solid rgba(216,168,90,.35);
  color: var(--h2h-gold, #D8A85A);
  padding: .15rem .42rem;
  border-radius: 999px;
  backdrop-filter: blur(4px);
  z-index: 1;
}
/* Recap play badge — bottom-right */
.port-card-recap-badge {
  position: absolute; bottom: .5rem; right: .5rem;
  font-size: 1.15rem;
  color: rgba(255,255,255,.9);
  z-index: 1;
  filter: drop-shadow(0 1px 4px rgba(0,0,0,.6));
}

/* Card body */
.port-card-body {
  padding: .6rem .75rem .7rem;
  display: flex; flex-direction: column;
  gap: .18rem;
  flex-grow: 1;
}
.port-card-cat {
  font-size: .6rem; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--h2h-gold, #D8A85A);
}
.port-card-title {
  font-size: .82rem; font-weight: 700;
  color: rgba(233,238,247,.9);
  line-height: 1.3;
  display: -webkit-box; -webkit-line-clamp: 2;
  -webkit-box-orient: vertical; overflow: hidden;
}
.port-card-date {
  font-size: .68rem; font-weight: 500;
  color: rgba(233,238,247,.45);
  margin-top: .1rem;
}
.port-card-stat {
  font-size: .68rem; font-weight: 500;
  color: rgba(233,238,247,.45);
}
.port-card-stat i { color: #CE1126; font-size: .6rem; }

/* ── Event recap page ───────────────────────────────────────────────── */
.recap-back-link {
  display: inline-flex; align-items: center; gap: .4rem;
  font-size: .85rem; font-weight: 600;
  color: rgba(233,238,247,.55);
  text-decoration: none;
  margin-bottom: 1.75rem;
  transition: color .2s ease;
}
.recap-back-link:hover { color: rgba(233,238,247,.85); }
.recap-header { margin-bottom: 1.75rem; }
.recap-eyebrow {
  font-size: .75rem; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--h2h-gold, #D8A85A);
  margin-bottom: .4rem;
}
.recap-title {
  font-size: clamp(1.8rem, 5vw, 2.8rem);
  font-weight: 800; color: #fff; line-height: 1.1; margin-bottom: .5rem;
}
.recap-date { font-size: .9rem; color: rgba(233,238,247,.6); }
.recap-date i { color: var(--h2h-gold, #D8A85A); margin-right: .3rem; }
.recap-video-wrap { border-radius: 16px; overflow: hidden; margin-bottom: 2rem; background: #000; }
.recap-video { width: 100%; display: block; aspect-ratio: 16/9; }
.recap-hero {
  border-radius: 16px; aspect-ratio: 16/9;
  background: center/cover no-repeat #0a0e18;
  margin-bottom: 2rem;
}
.recap-description {
  font-size: 1rem; line-height: 1.75;
  color: rgba(233,238,247,.82);
  margin-bottom: 2rem;
  padding: 1.5rem;
  background: rgba(255,255,255,.06);
  border: 1px solid rgba(255,255,255,.14);
  border-radius: 14px;
}
.recap-description p { margin: 0; }
.recap-stats-row {
  display: flex; gap: 2rem; flex-wrap: wrap;
  margin-bottom: 2.5rem;
}
.recap-stat { display: flex; flex-direction: column; gap: .15rem; }
.recap-stat-num { font-size: 2rem; font-weight: 800; color: #fff; line-height: 1; }
.recap-stat-label { font-size: .78rem; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--h2h-gold, #D8A85A); }
.recap-section { margin-bottom: 2.5rem; }
.recap-section-title {
  font-size: 1rem; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: rgba(233,238,247,.55);
  margin-bottom: 1rem; display: flex; align-items: center; gap: .5rem;
}
.recap-section-title i { color: var(--h2h-gold, #D8A85A); }
.recap-names-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: .5rem;
}
.recap-name {
  background: rgba(255,255,255,.05);
  border: 1px solid rgba(255,255,255,.14);
  border-radius: 8px;
  padding: .45rem .75rem;
  font-size: .88rem;
  color: rgba(233,238,247,.82);
}
.recap-partners-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 1rem;
}
.recap-partner-card {
  background: rgba(255,255,255,.05);
  border: 1px solid rgba(255,255,255,.14);
  border-radius: 12px;
  padding: 1rem;
  display: flex; flex-direction: column; align-items: center; gap: .6rem;
  text-align: center;
}
.recap-partner-card img { max-height: 48px; width: auto; max-width: 100%; object-fit: contain; opacity: .85; }
.recap-partner-placeholder { height: 48px; width: 48px; border-radius: 8px; background: rgba(255,255,255,.08); display: flex; align-items: center; justify-content: center; color: rgba(233,238,247,.3); font-size: 1.3rem; }
.recap-partner-name { font-size: .78rem; color: rgba(233,238,247,.65); line-height: 1.3; }

/* "Want to see more?" → Events Portfolio call-out */
/* ── Recap spotlight + "more" strip ──────────────────────────────────────────
   The most recent event is featured large (poster-forward, info overlaid so it
   never strands text in a void); the other recent recaps sit in a compact grid
   beside it. Both open the in-place lightbox; full history is in the portfolio. */
/* Recap stage — most-recent spotlight (left) beside the browse grid (right).
   Spotlight leads at ~1.5fr; the grid fills the rest. Stacks on mobile. */
.recap-stage {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
  gap: clamp(1rem, 2.4vw, 2rem);
  align-items: stretch;
  max-width: var(--container);
  margin: 0 auto;
}
@media (max-width: 860px) {
  .recap-stage { grid-template-columns: 1fr; }
  .recap-more { height: auto; grid-template-rows: auto; }
  .recap-more-tile img { aspect-ratio: 1 / 1; height: auto; }
}

.recap-spotlight {
  display: block; position: relative;
  width: 100%; margin: 0;
  align-self: start;
  border-radius: 16px; overflow: hidden;
  border: 1px solid rgba(255,255,255,.12);
  box-shadow: 0 24px 60px rgba(0,0,0,.5);
  transition: transform .3s cubic-bezier(.22,.61,.36,1), border-color .3s ease, box-shadow .3s ease, opacity .18s ease;
}
.recap-spotlight:hover, .recap-spotlight:focus-visible {
  transform: translateY(-4px); border-color: rgba(216,168,90,.5); outline: none;
  box-shadow: 0 32px 72px rgba(0,0,0,.6);
}
/* Category accent bar at the top of the spotlight image */
.recap-spotlight[data-category="mission"]::before    { content:''; position:absolute; top:0; left:0; right:0; height:4px; background:var(--h2h-red,#CE1126); z-index:4; }
.recap-spotlight[data-category="fundraiser"]::before { content:''; position:absolute; top:0; left:0; right:0; height:4px; background:var(--h2h-gold,#D8A85A); z-index:4; }
.recap-spotlight[data-category="outreach"]::before   { content:''; position:absolute; top:0; left:0; right:0; height:4px; background:var(--h2h-blue,#1FA6DE); z-index:4; }
.recap-spotlight-img { display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: cover; object-position: center top; transition: filter .4s ease; }
.recap-spotlight:hover .recap-spotlight-img { filter: brightness(1.06) saturate(1.05); }
.recap-spotlight-badge {
  position: absolute; top: 14px; left: 14px; z-index: 3;
  display: inline-flex; align-items: center; gap: .35rem;
  font-family: 'Oswald', sans-serif; font-size: .68rem; font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase;
  color: #1a1205; background: var(--h2h-gold, #D8A85A);
  padding: .35rem .7rem; border-radius: 7px;
}
.recap-spotlight-play {
  position: absolute; top: 42%; left: 50%; transform: translate(-50%,-50%); z-index: 3;
  width: 64px; height: 64px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: rgba(6,9,15,.5); border: 2px solid rgba(255,255,255,.7); color: #fff;
  font-size: 1.5rem; -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
}
.recap-spotlight-info {
  position: absolute; inset: 0; z-index: 2;
  display: flex; flex-direction: column; justify-content: flex-end;
  padding: 1.5rem 1.4rem 1.3rem;
  background: linear-gradient(
    to top,
    rgba(6,9,15,.97) 0%,
    rgba(6,9,15,.78) 28%,
    rgba(6,9,15,.40) 55%,
    transparent 80%
  );
}
.recap-spotlight-title {
  font-family: 'Bebas Neue', 'Barlow Condensed', sans-serif;
  font-size: clamp(1.8rem, 3vw, 2.4rem); line-height: 1; color: #fff;
  margin: .25rem 0 .35rem; letter-spacing: .01em;
}
.recap-spotlight-meta { font-family: 'Barlow', sans-serif; font-size: .9rem; color: rgba(233,238,247,.85); }
.recap-spotlight-cta {
  font-family: 'Oswald', sans-serif; font-size: .78rem; font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase; color: var(--h2h-gold, #D8A85A);
  margin-top: .65rem; display: inline-flex; align-items: center; gap: .35rem;
}
.recap-spotlight-cta i { transition: transform .2s ease; }
.recap-spotlight:hover .recap-spotlight-cta i { transform: translateX(4px); }

/* Recap ledger: aligned with the title text, not the accent bar */
.recap-ledger {
  margin-top: 1.4rem;
  margin-bottom: clamp(1.75rem, 3.5vw, 2.75rem);
  padding-top: 1.2rem;
  border-top: 1px solid rgba(255,255,255,.1);
  margin-left: var(--ed-col-indent);
}
.recap-ledger-count {
  font-size: .9rem;
  color: rgba(233,238,247,.6);
  display: block;
  margin-bottom: .6rem;
}
/* Editorial category labels — replace Bootstrap pill badges */
.recap-cats { display: flex; align-items: center; gap: 1.5rem; flex-wrap: wrap; }
.recap-cat {
  font-family: 'Oswald', sans-serif;
  font-size: .72rem;
  font-weight: 500;
  letter-spacing: .12em;
  text-transform: uppercase;
  display: inline-flex;
  align-items: center;
  gap: .35rem;
}
.recap-cat--mission   { color: var(--h2h-red,  #CE1126); }
.recap-cat--fundraiser { color: var(--h2h-gold, #D8A85A); }
.recap-cat--outreach  { color: var(--h2h-blue, #1FA6DE); }

/* Ledger as a slim full-width strip under the header (count left, legend right,
   bracketed by hairlines) — replaces the old half-width column beside the spotlight. */
.recap-ledger--strip {
  max-width: var(--container);
  margin: 0 auto clamp(1.4rem, 3vw, 2.25rem);
  padding: .85rem 0;
  border-top: 1px solid rgba(255,255,255,.1);
  border-bottom: 1px solid rgba(255,255,255,.1);
  display: flex; align-items: center; justify-content: space-between;
  gap: .75rem 1.5rem; flex-wrap: wrap;
}
.recap-ledger--strip .recap-ledger-count { margin: 0; }

/* Active tile — the one currently displayed in the stage */
.recap-more-tile--active {
  border-color: rgba(216,168,90,.7) !important;
  box-shadow: 0 0 0 2px rgba(216,168,90,.35) !important;
  transform: translateY(-2px);
}

.recap-more {
  display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; gap: 12px;
  width: 100%; height: 100%; margin: 0;   /* fills the stage's right column, matching the spotlight height */
}
/* Tiles share the row width so the strip always fits the window — no sideways
   scrolling. Only as many as fit cleanly are shown (caps below); the full
   history lives on the portfolio page. */
.recap-more-tile {
  min-width: 0; position: relative;
  border-radius: 10px; overflow: hidden;
  border: 1px solid rgba(255,255,255,.10);
  box-shadow: 0 8px 22px rgba(0,0,0,.35);
  transition: transform .25s ease, border-color .25s ease, box-shadow .25s ease;
}
.recap-more-tile:nth-child(n+5) { display: none; }                          /* stage grid: 2×2 (4 tiles) */
@media (max-width: 600px) { .recap-more-tile:nth-child(n+3) { display: none; } }  /* 2 on phones */
.recap-more-tile:hover, .recap-more-tile:focus-visible {
  transform: translateY(-5px) scale(1.015); border-color: rgba(216,168,90,.5); outline: none;
  box-shadow: 0 16px 36px rgba(0,0,0,.5);
}
.recap-more-tile img {
  display: block; width: 100%; height: 100%; object-fit: cover;
  transition: filter .35s ease;
}
.recap-more-tile:hover img { filter: brightness(1.1) saturate(1.08); }
/* Category accent bar */
.recap-more-tile[data-category="mission"]::before    { content:''; position:absolute; top:0; left:0; right:0; height:3px; background:var(--h2h-red,#CE1126); z-index:3; }
.recap-more-tile[data-category="fundraiser"]::before { content:''; position:absolute; top:0; left:0; right:0; height:3px; background:var(--h2h-gold,#D8A85A); z-index:3; }
.recap-more-tile[data-category="outreach"]::before   { content:''; position:absolute; top:0; left:0; right:0; height:3px; background:var(--h2h-blue,#1FA6DE); z-index:3; }
.recap-more-play {
  position: absolute; top: 8px; right: 8px; z-index: 2;
  width: 26px; height: 26px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: rgba(206,17,38,.92); color: #fff; font-size: .7rem;
}
.recap-more-cap {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 1;
  padding: 2.5rem .65rem .55rem;
  background: linear-gradient(to top, rgba(6,9,15,.97) 0%, rgba(6,9,15,.75) 45%, transparent 100%);
  display: flex; flex-direction: column; gap: .18rem;
}
.recap-more-eb {
  font-family: 'Oswald', sans-serif; font-size: .58rem; font-weight: 600;
  letter-spacing: .15em; text-transform: uppercase; color: var(--h2h-gold, #D8A85A);
  line-height: 1;
}
.recap-more-title {
  font-family: 'Oswald', sans-serif; font-size: .72rem; font-weight: 600;
  letter-spacing: .04em; text-transform: uppercase; color: #fff; line-height: 1.2;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}

/* shared bits kept from the old poster wall */
.recap-tile-empty {
  width: 100%; aspect-ratio: 1 / 1;
  display: flex; align-items: center; justify-content: center;
  font-size: 2.4rem; color: rgba(233,238,247,.16); background: #131c30;
}
.recap-tile-eyebrow {
  font-family: 'Oswald', sans-serif; font-size: .65rem; font-weight: 600;
  letter-spacing: .18em; text-transform: uppercase; color: var(--h2h-gold, #D8A85A);
}

/* ── Recap lightbox — a recap opens in place over the page ───────────────────
   Poster (or inline video) on top, recap details below; the dedicated page
   stays the deep view behind "See who served". Full-screen sheet on mobile. */
.recap-lb {
  position: fixed; inset: 0; z-index: 4000;
  display: flex; align-items: center; justify-content: center;
  padding: clamp(1rem, 4vw, 3rem);
}
.recap-lb[hidden] { display: none; }
.recap-lb-backdrop {
  position: absolute; inset: 0;
  background: rgba(4,7,12,.78);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  opacity: 0; transition: opacity .28s ease;
}
.recap-lb.is-open .recap-lb-backdrop { opacity: 1; }
.recap-lb-dialog {
  position: relative; z-index: 1;
  width: min(720px, 100%); max-height: 90vh; overflow-y: auto;
  display: flex; flex-direction: column;
  background: #0d1626; border: 1px solid rgba(255,255,255,.12);
  border-radius: 18px; box-shadow: 0 40px 100px rgba(0,0,0,.6);
  transform: scale(.92) translateY(14px); opacity: 0;
  transition: transform .3s cubic-bezier(.22,.61,.36,1), opacity .3s ease;
}
.recap-lb.is-open .recap-lb-dialog { transform: none; opacity: 1; }
.recap-lb-close {
  position: absolute; top: 12px; right: 12px; z-index: 3;
  width: 38px; height: 38px; border-radius: 50%; border: none; cursor: pointer;
  background: rgba(6,9,15,.6); color: #fff; font-size: 1.1rem;
  display: flex; align-items: center; justify-content: center;
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
  transition: background .2s ease;
}
.recap-lb-close:hover { background: rgba(206,17,38,.92); }
.recap-lb-media { width: 100%; background: #060a12; }
.recap-lb-poster { display: block; width: 100%; max-height: 52vh; object-fit: contain; margin: 0 auto; }
.recap-lb-video { width: 100%; aspect-ratio: 16 / 9; }
.recap-lb-video iframe { width: 100%; height: 100%; display: block; border: 0; }
.recap-lb-body { padding: clamp(1.5rem, 3vw, 2.25rem); }
.recap-lb-eyebrow { font-family:'Oswald',sans-serif; font-size:.7rem; font-weight:600; letter-spacing:.2em; text-transform:uppercase; color: var(--h2h-gold,#D8A85A); }
.recap-lb-title { font-family:'Bebas Neue','Barlow Condensed',sans-serif; font-size: clamp(1.8rem,4vw,2.6rem); line-height:1; color:#fff; margin:.35rem 0 .5rem; letter-spacing:.01em; }
.recap-lb-date { font-family:'Barlow',sans-serif; font-size:.9rem; color: rgba(233,238,247,.72); display:flex; align-items:center; gap:.4rem; margin-bottom:.9rem; }
.recap-lb-date i { color: var(--h2h-gold,#D8A85A); }
.recap-lb-stats { display:flex; gap:1.75rem; margin-bottom:1.1rem; }
.recap-lb-stat { font-family:'Barlow',sans-serif; font-size:.82rem; color: rgba(233,238,247,.7); }
.recap-lb-stat b { display:block; font-family:'Bebas Neue','Barlow Condensed',sans-serif; font-size:1.7rem; color:#fff; line-height:1; margin-bottom:.1rem; }
.recap-lb-desc { font-size:.98rem; line-height:1.6; color: rgba(233,238,247,.82); margin:0 0 1.25rem; }
.recap-lb-watch { display:inline-flex; align-items:center; gap:.4rem; margin:0 0 1rem; color: var(--h2h-gold,#D8A85A); font-weight:600; }
.recap-lb-full { display:inline-flex; align-items:center; gap:.4rem; font-family:'Oswald',sans-serif; font-size:.8rem; font-weight:600; letter-spacing:.06em; text-transform:uppercase; color: var(--h2h-gold,#D8A85A); }
.recap-lb-full i { transition: transform .2s ease; }
.recap-lb-full:hover i { transform: translateX(4px); }
@media (max-width: 720px) {
  .recap-lb { padding: 0; align-items: flex-end; }
  .recap-lb-dialog { width: 100%; max-height: 94vh; border-radius: 18px 18px 0 0; transform: translateY(100%); }
  .recap-lb.is-open .recap-lb-dialog { transform: none; }
  .recap-lb-poster { max-height: 38vh; }
}
@media (prefers-reduced-motion: reduce) {
  .recap-lb-backdrop, .recap-lb-dialog { transition: opacity .15s ease; transform: none; }
}

/* ── "See all events" expand trigger ────────────────────────────────────── */
.recap-see-all-wrap {
  text-align: center;
  margin-top: 1.5rem;
}
.recap-see-all {
  display: inline-flex; align-items: center; gap: .5rem;
  font-family: 'Oswald', sans-serif; font-size: .9rem; font-weight: 600;
  letter-spacing: .06em; text-transform: uppercase;
  color: rgba(233,238,247,.7);
  background: rgba(255,255,255,.05);
  border: 1px solid rgba(255,255,255,.18);
  border-radius: 10px; padding: .6rem 1.25rem; cursor: pointer;
  transition: color .2s ease, border-color .2s ease, background .2s ease;
}
.recap-see-all:hover {
  color: var(--h2h-gold, #D8A85A);
  border-color: rgba(216,168,90,.5);
  background: rgba(216,168,90,.08);
}
.recap-see-all-caret { transition: transform .3s ease; font-size: .8rem; }
.recap-see-all[aria-expanded="true"] .recap-see-all-caret { transform: rotate(180deg); }

/* ── Expandable full archive grid ────────────────────────────────────────── */
.recap-all {
  overflow: hidden;
  height: 0;
  transition: height .45s cubic-bezier(.22,.61,.36,1);
}
.recap-all-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
  gap: .55rem;
  padding-top: 1.5rem;
}
.recap-all-tile {
  position: relative;
  display: block;
  border-radius: 10px; overflow: hidden;
  aspect-ratio: 1 / 1;
  border: 1px solid rgba(255,255,255,.1);
  box-shadow: 0 6px 18px rgba(0,0,0,.32);
  transition: transform .22s ease, border-color .22s ease, box-shadow .22s ease;
  text-decoration: none;
}
.recap-all-tile:hover, .recap-all-tile:focus-visible {
  transform: translateY(-4px) scale(1.03);
  border-color: rgba(216,168,90,.55);
  box-shadow: 0 14px 30px rgba(0,0,0,.46);
  outline: none;
}
.recap-all-tile img {
  display: block; width: 100%; height: 100%;
  object-fit: cover;
  transition: filter .25s ease;
}
.recap-all-tile:hover img { filter: brightness(1.08) saturate(1.06); }
.recap-all-play {
  position: absolute; top: 6px; right: 6px; z-index: 2;
  width: 22px; height: 22px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: rgba(206,17,38,.9); color: #fff; font-size: .62rem;
}
.recap-all-cap {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 1;
  padding: 1.6rem .5rem .45rem;
  background: linear-gradient(to top, rgba(6,9,15,.97) 0%, rgba(6,9,15,.7) 50%, transparent 100%);
  display: flex; flex-direction: column; gap: .14rem;
}
.recap-all-eb {
  font-family: 'Oswald', sans-serif; font-size: .54rem; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--h2h-gold, #D8A85A); line-height: 1;
}
.recap-all-title {
  font-family: 'Oswald', sans-serif; font-size: .66rem; font-weight: 600;
  letter-spacing: .03em; text-transform: uppercase; color: #fff; line-height: 1.2;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.recap-all-footer {
  text-align: center;
  padding: 1.25rem 0 .25rem;
}
.recap-all-close {
  display: inline-flex; align-items: center; gap: .35rem;
  font-family: 'Oswald', sans-serif; font-size: .82rem; font-weight: 600;
  letter-spacing: .06em; text-transform: uppercase;
  color: rgba(233,238,247,.55); background: none; border: none;
  cursor: pointer; transition: color .2s ease;
}
.recap-all-close:hover { color: rgba(233,238,247,.9); }
@media (max-width: 600px) {
  .recap-all-grid { grid-template-columns: repeat(auto-fill, minmax(90px, 1fr)); }
}

/* Keep legacy impact-cta styles for any other page that might reference them */
.impact-cta {
  margin: 2.5rem auto 0;
  max-width: 720px;
  text-align: center;
  background: linear-gradient(160deg, rgba(216,168,90,.10), rgba(255,255,255,.05));
  border: 1px solid rgba(216,168,90,.30);
  border-radius: 18px;
  padding: 2rem 1.75rem;
}
.impact-cta-head {
  font-family: 'Bebas Neue', sans-serif;
  font-size: clamp(1.6rem, 4vw, 2.2rem);
  letter-spacing: .02em;
  color: var(--h2h-gold, #D8A85A);
  line-height: 1;
}
.impact-cta-text {
  font-size: .94rem;
  line-height: 1.65;
  color: rgba(233,238,247,.78);
  margin: .8rem auto 1.4rem;
  max-width: 600px;
}
.impact-cta-btn { font-size: .95rem; padding: .6rem 1.4rem; }

.std-video-wrap {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: 14px;
  overflow: hidden;
  background: #000;
  border: 1px solid rgba(255,255,255,.14);
}

/* Self-hosted video player (See Us in Action) — poster + branded gold play cue,
   click to load/play (preload=none → the video isn't fetched until played, and
   no third-party tracking before then). The play overlay hides once playing,
   revealing the native controls. */
.ia-video-el {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: #000;
  display: block;
  z-index: 0;
}
/* Ambient muted loop — sits above the (paused) main video, below the play cue,
   so the section reads as alive until the visitor clicks to watch with sound. */
.ia-video-ambient {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: #000;
  display: block;
  z-index: 1;
  pointer-events: none;
}
.ia-video-wrap.is-playing .ia-video-ambient { display: none; }
/* After the one ambient play finishes, fade it out to reveal the curated poster. */
.ia-video-wrap.ambient-done .ia-video-ambient { opacity: 0; transition: opacity .6s ease; pointer-events: none; }
.ia-video-play {
  position: absolute;
  inset: 0;
  z-index: 2;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .7rem;
  border: 0;
  cursor: pointer;
  color: #fff;
  background: radial-gradient(circle at center, rgba(7,11,20,.22), rgba(7,11,20,.58));
  transition: opacity .3s ease, visibility .3s ease;
}
.ia-video-play-ring {
  width: 66px;
  height: 66px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid var(--h2h-gold, #D8A85A);
  background: rgba(7,11,20,.42);
  color: var(--h2h-gold, #D8A85A);
  font-size: 1.55rem;
  box-shadow: 0 6px 26px rgba(0,0,0,.45), 0 0 18px rgba(216,168,90,.3);
  transition: transform .25s ease, background .25s ease, color .25s ease, box-shadow .25s ease;
}
/* Inline SVG triangle — path is pre-centred in its viewBox (x-centre 13.5 of 24,
   a built-in optical nudge), so flex-centring the box centres the triangle. No
   font-glyph guesswork. */
.ia-video-play-tri {
  width: 26px;
  height: 26px;
  display: block;
  fill: var(--h2h-gold, #D8A85A);
}
.ia-video-play:hover .ia-video-play-tri,
.ia-video-play:focus-visible .ia-video-play-tri { fill: #fff; }
.ia-video-play-label {
  font-size: .8rem;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  text-shadow: 0 1px 6px rgba(7,11,20,.85);
}
.ia-video-play-time {
  font-size: .72rem;
  letter-spacing: .1em;
  color: rgba(255,255,255,.7);
  text-shadow: 0 1px 6px rgba(7,11,20,.85);
  margin-top: .15rem;
}
.ia-video-play:hover .ia-video-play-ring,
.ia-video-play:focus-visible .ia-video-play-ring {
  transform: scale(1.08);
  background: rgba(216,168,90,.22);
  color: #fff;
  box-shadow: 0 6px 30px rgba(0,0,0,.5), 0 0 30px rgba(216,168,90,.55);
}
.ia-video-wrap.is-playing .ia-video-play {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
  .ia-video-play, .ia-video-play-ring { transition: none; }
}

/* ── "See Us in Action" — video + featured testimonial + supporting voices ── */
/* How / Why we serve — two light, accented columns leading the section
   (relocated from the hero; no heavy red/blue blocks, just a small top rule) */
.ia-intro {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2.75rem;
  max-width: 980px;
  margin: 0 auto;
}
.ia-intro-col {
  position: relative;
  padding-top: 1.1rem;
  text-align: center;
}
.ia-intro-col::before {
  content: '';
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 42px;
  height: 3px;
  border-radius: 2px;
}
.ia-intro-col--red::before  { background: #CE1126; }
.ia-intro-col--blue::before { background: #1FA6DE; }
.ia-intro-eyebrow {
  font-family: 'Oswald', sans-serif;
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--h2h-gold, #D8A85A);
  margin: 0 0 .7rem;
}
.ia-intro-body {
  font-size: 1rem;
  line-height: 1.7;
  color: rgba(233,238,247,.72);
  max-width: 30rem;
  margin: 0 auto;
}
@media (max-width: 720px) {
  .ia-intro { grid-template-columns: 1fr; gap: 1.9rem; }
}

/* Match the editorial section-header box (max-width 1000) and indent to its text
   column (past the 4px accent bar + column gap) so the video/quote/photos line up
   under "Hearts at Work" instead of stretching further left than the heading. */
/* This section is media + a split layout (not body text), so it can use the full
   container width instead of the narrow reading column — fills large laptops/desktops
   and shrinks the side margins. Header + content both widen together (still aligned),
   and the video stays crisp because it never exceeds ~half this width. */
#in-action { --ed-col-max: var(--container); }
#about   { --ed-col-max: var(--container); }
/* Match the widened sections (In Action, About) so the left edge lines up. */
#events  { --ed-col-max: var(--container); }
/* Events header row: the countdown sits BESIDE the header — filling the right of
   the title/blurb instead of stacking below it (was a big empty right half).
   Only goes 2-column when a countdown exists; stacks under on narrow screens. */
/* Head-row wrappers: constrain to the container and auto-center (matching the
   about-spread pattern) so the editorial header inside aligns flush-left at the
   same x as About and In Action, with no centering indent. The header's own
   max-width is overridden to 100% so it fills the wrapper column rather than
   re-centering itself at 62.5rem inside the already-constrained wrapper. */
.evt-head-row, .recap-head-row, .donate-head-row {
  max-width: var(--container);
  margin-left: auto;
  margin-right: auto;
}

.evt-head-row { display: grid; grid-template-columns: 1fr; gap: clamp(1rem, 2.5vw, 1.75rem); align-items: center; margin-bottom: clamp(1.75rem, 3.5vw, 2.75rem); }
/* Header always leads: the countdown banner stacks BELOW the full-width header
   rather than beside it, matching every other section's header-first grammar. */
.evt-head-row.has-aside { grid-template-columns: 1fr; justify-items: start; }
.evt-head-row > .main-section-header--editorial { margin-bottom: 0; }
/* Recaps header row: full-width editorial header. The archive-ledger strip and
   the recap stage (spotlight + browse grid) sit below it, each full-width. */
.recap-head-row { display: grid; grid-template-columns: 1fr; gap: clamp(1.25rem, 3vw, 2.25rem); align-items: start; margin-bottom: clamp(1.75rem, 3.5vw, 2.75rem); }
/* Header now spans the full width on top; the ledger strip and recap stage below
   it own their own layout (see .recap-ledger--strip and .recap-stage). */
.recap-head-row > .main-section-header--editorial { margin-bottom: 0; }
/* Donate header: standard editorial header, same column + margin as every
   other section. The "100%" promise sits under the title/sub as a fused stat. */
.donate-head-row { display: block; margin-bottom: 0; }
.donate-promise {
  display: inline-flex; align-items: baseline; gap: .5rem;
  margin-top: .9rem;
  padding: 0;
  background: none;
  border: none;
}
.donate-promise-pct { font-family: 'Barlow Condensed','Oswald',sans-serif; font-weight: 700; font-size: clamp(1.9rem, 3vw, 2.4rem); line-height: 1; color: var(--h2h-green, #10B981); }
.donate-promise-mark { font-size: .5em; vertical-align: .55em; margin-left: .04em; }
.donate-promise-lead { font-family: 'Inter', sans-serif; font-weight: 400; font-size: 1.02rem; color: rgba(206,214,228,.80); line-height: 1.65; }  /* matches the standard .mse-sub subtitle used in every other section — only the 100% stat beside it is an accent */
#impact  { --ed-col-max: var(--container); }
#donate  { --ed-col-max: var(--container); }
#contact { --ed-col-max: var(--container); }

/* ── In Action atmosphere — a heavily blurred, dimmed outreach still behind the
   content, so the section reads as its own "place" rather than another identical
   dark panel. Subtle by design (tune via opacity). ── */
#in-action::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  /* A clean, faint warm wash (no photo) so the section feels its own without any
     murk competing with the video, photos, and quote. */
  background: radial-gradient(85% 60% at 50% 28%, rgba(216,168,90,.06), transparent 70%);
  pointer-events: none;
}
#in-action::before { z-index: 2; }              /* keep the accent line above the atmosphere */
#in-action > .landing-wrap { position: relative; z-index: 1; }

.in-action-layout { margin-top: 2.25rem; }   /* column alignment handled by the .ed-col rule */
/* Side by side again, but tuned: video alone in the wider column (nothing
   crowds it, so it gets full attention even without being full-bleed), Ansel's
   testimony narrower in the second column, with the invitation below the quote
   box — watch, feel, then act. */
.ia-split {
  display: grid;
  grid-template-columns: 1.3fr .7fr;
  align-items: start;
  gap: clamp(1.5rem, 3vw, 2.5rem);
}
/* Capped, not full-bleed — this footage is from an older phone; stretching it
   wider would make the softness/compression more visible, not less. Revisit
   once better footage exists. */
.ia-media { display: flex; flex-direction: column; gap: .9rem; max-width: 900px; }
.ia-words { display: flex; flex-direction: column; justify-content: flex-start; gap: .85rem; }
/* Button + reassurance on one line so the invitation is compact, not 4 stacked lines. */
.ia-cta-row { display: flex; align-items: center; gap: .55rem 1rem; flex-wrap: wrap; }

/* A "Joy + Dignity" three-tile photo gallery (.ia-photoset > .ia-moment,
   with Ken Burns drift via @keyframes iaKenBurns, and .ia-moment-cap labels)
   used to sit here, full-width below the video + testimony. Confirmed dead and
   removed: the current markup has no .ia-photoset anywhere — the section ends
   after the video/quote split. Checked beyond just this page too (fundraiser
   and portal pages have no plausible reuse for an outreach-photo gallery named
   ia-*) before removing. If the gallery comes back, it lived right here. */

/* ── Cinematic impact band ───────────────────────────────────────────────
   Full-bleed kinetic numbers over a darkened outreach photo. Breaks the
   all-dark centered rhythm; the page's second "wow" beat. The four figures
   carry the Hearts-red / Hands-blue / gold / green color system on a dark
   stage, and count up on reveal. */
#impact-band.impact-band {
  position: relative;
  overflow: hidden;
  padding: clamp(2rem, 4vw, 3.5rem) 0;
  background: #06090f;
  isolation: isolate;
}
.impact-band-bg {
  position: absolute; inset: 0;
  background: center/cover no-repeat;
  opacity: .82;   /* same recipe as the join band (the reference): dim via opacity + filter, with only a light text-zone scrim — keeps the three photo bands consistent */
  filter: brightness(0.62) saturate(1.02) contrast(1.02);
  transform: scale(1.08);
  animation: bandDrift 22s ease-in-out infinite alternate;
  z-index: 0;
}
.impact-band::after {
  content: ""; position: absolute; inset: 0; z-index: 1;
  /* Light text-zone-only scrim (top for the header, bottom for the footer line) —
     matches the join band's minimal approach so the photo stays vivid and the
     three bands read at a consistent brightness. The heavy radial pool was what
     made this band look darker than join. */
  background:
    linear-gradient(180deg, rgba(6,9,15,.20) 0%, rgba(6,9,15,.05) 40%, rgba(6,9,15,.05) 60%, rgba(6,9,15,.22) 100%);
}
.impact-band-inner {
  position: relative; z-index: 2;
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 clamp(1.25rem, 4vw, 2rem);
  text-align: center;
}
.impact-band-kicker {
  font-family: 'Oswald', sans-serif;
  text-transform: uppercase; letter-spacing: .28em;
  font-size: .82rem; font-weight: 500;
  color: var(--h2h-gold, #D8A85A);
  margin: 0 0 .65rem;
}
.impact-band-lead {
  font-family: 'Barlow Condensed', 'Oswald', sans-serif;
  font-weight: 700;
  /* One line at every viewport — vw-driven so it scales down with the screen
     instead of wrapping. Verified no-overflow at 500/1440/2560px. */
  font-size: clamp(1.05rem, 5.6vw, 3rem);
  white-space: nowrap;
  line-height: 1.04;
  color: #fff;
  margin: 0 auto clamp(2.25rem, 4vw, 3.25rem);
}
.impact-band-lead em { font-style: normal; color: var(--h2h-gold, #D8A85A); }
.impact-band-stats {
  display: block;
  max-width: 46ch;
  margin: 0 auto;
}
/* Punchline: two of the four numbers woven into one narrative sentence —
   Missions + Serving Hearts, the emotional pair. No day/time claim (missions
   run on regular but varied days), just the echo of "showed up". */
.impact-band-punch {
  font-family: 'Barlow Condensed', 'Oswald', sans-serif;
  font-weight: 600;
  font-size: clamp(1.4rem, 3vw, 2.1rem);
  line-height: 1.32;
  color: #fff;
  margin: 0 0 .4rem;
}
/* Decorative dot-field canvas (impactHeartCanvas in scripts-main.js) — 893
   individual dots, one per volunteer, scatter then coalesce into a heart every
   time the band scrolls into view (replays each pass, matching the site's
   reveal-on-scroll convention). Internal resolution is fixed (480×380); display
   size scales responsively via CSS, so it stays crisp at every viewport.
   The stage wrapper gives it a dark radial backdrop — same technique as the
   Contact founders photo's gold glow, just dark — so the red dots stay legible
   regardless of what's in the mission photo behind them (the tent canopy is
   red/blue and was camouflaging the dots before this). */
.impact-band-heart-stage {
  position: relative;
  width: min(380px, 74vw);
  margin: .35rem auto .2rem;
  isolation: isolate;
}
.impact-band-heart-stage::before {
  content: '';
  position: absolute; inset: -10%;
  background: radial-gradient(ellipse 60% 60% at 50% 50%, rgba(6,9,15,.72), rgba(6,9,15,.4) 55%, transparent 76%);
  filter: blur(2px);
  pointer-events: none;
  z-index: 0;
}
.impact-band-heart {
  position: relative; z-index: 1;
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 480 / 380;
}
/* Partners + dollars are already self-explanatory as raw numbers — a plain
   supporting line, not dramatized the way the punchline above is. */
.impact-band-facts {
  font-family: 'Inter', sans-serif;
  font-size: 1.02rem;
  color: rgba(233,238,247,.78);
  margin: .35rem 0 0;
}
.impact-band-num {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  /* The mission photo has red/blue tent canopies running right through this
     text; brand-colored digits (red especially) were color-camouflaging
     against them at every viewport. A dark rim + soft ambient shadow keeps
     each number legible regardless of what hue sits behind it — same idea as
     the dot-heart's dark stage, applied to glyphs instead of a canvas. */
  text-shadow: 0 1px 2px rgba(0,0,0,.55), 0 0 12px rgba(0,0,0,.4);
}
/* True brand colors so each figure still reads with its own identity, even
   inline within a sentence instead of as a standalone giant digit. */
.impact-band-num--gold { color: var(--h2h-gold, #D8A85A); }
.impact-band-num--red   { color: var(--h2h-red, #CE1126); }
.impact-band-num--blue  { color: var(--h2h-blue, #1FA6DE); }
.impact-band-num--green { color: var(--h2h-green, #10B981); }
/* Currency + unit as small raised affixes so the figure itself is the hero. */
.impact-band-num .num-cur {
  font-size: .78em; font-weight: 600; vertical-align: .12em;
  margin-right: .03em; opacity: .9;
}
.impact-band-num .num-unit {
  font-size: .78em; font-weight: 600; vertical-align: 0;
  margin-left: .03em; opacity: .9;
}

@keyframes bandDrift {
  from { transform: scale(1.08) translate3d(-1.2%, -1%, 0); }
  to   { transform: scale(1.16) translate3d(1.5%, 1.2%, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .impact-band-bg { animation: none; transform: scale(1.08); }
  .join-bg { animation: none; transform: scale(1.04); }
}
@media (max-width: 560px) {
  .impact-band-heart-stage { width: min(300px, 80vw); }
}

/* The invitation sits directly below Ansel's quote box (moved out of the figure) —
   testimony, who said it, then the ask. The box sizes to its content and the
   box + invitation group is spread top-to-bottom across the column (justify-content:space-between),
   which the ResizeObserver still matches to the video's height. */
.ia-words > .ia-cta-block { align-self: flex-start; margin: 0; }
.ia-cta-line {
  font-family: 'Barlow Condensed', 'Bebas Neue', sans-serif;
  font-weight: 600;
  font-size: 1.5rem;
  line-height: 1.1;
  color: #f4efe4;
  margin: 0 0 .4rem;
}
/* (Removed the old .ia-cta fat override — the invitation button now uses the one
   standard .btn-gold like every other gold CTA.)
   Two more rules used to sit here — .ia-cta-note (a reassurance line under the
   button, like "No experience needed") and .ia-cta-block--wide (a centered
   variant for when the invitation closed the section under the now-removed
   photo gallery above). Confirmed dead and removed: the current markup's
   .ia-cta-block only has .ia-cta-line + .ia-cta-row, no reassurance line and
   no --wide modifier anywhere. */

/* Quote cards — dark glass, gold accent, brand voice */
.ia-quote {
  position: relative;
  margin: 0;
  padding: 1.6rem 1.6rem 1.5rem;
  background: rgba(255,255,255,.06);
  border: 1px solid rgba(255,255,255,.14);
  border-radius: 16px;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  overflow: hidden;
}
.ia-quote blockquote {
  position: relative;
  z-index: 1;
  margin: 0 0 1rem;
  font-family: 'Fraunces', Georgia, serif;
  font-style: italic;
  font-weight: 300;
  color: rgba(233,238,247,.86);
  line-height: 1.6;
  font-size: 1rem;
}
.ia-quote figcaption { position: relative; z-index: 1; display: flex; flex-direction: row; align-items: center; gap: .8rem; }
.ia-quote-cap-text { display: flex; flex-direction: column; gap: .12rem; }
/* Ansel's portrait beside his testimony — circular, gold-ringed. Hides itself
   gracefully (onerror) until the cropped photo is dropped in, so the caption
   still reads clean with just the name in the meantime. */
.ia-quote-avatar {
  flex: 0 0 auto;
  width: 84px; height: 84px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid rgba(216,168,90,.55);
  box-shadow: 0 4px 16px rgba(0,0,0,.45);
}
.ia-quote-name { font-weight: 700; color: #f4efe4; font-size: 1rem; }
.ia-quote-role { font-size: .85rem; color: rgba(233,238,247,.45); letter-spacing: .04em; }

/* Featured quote (Ansel) — the marks are back (Kendra liked them) but small and
   quiet this time: one static mark, modest size, low opacity — not the animated
   7.5rem pair that used to out-weigh the video beside it. Opening and closing
   marks now match — same large gold glyph — bracketing the testimony. The
   invitation sits below the whole box (see .ia-words > .ia-cta-block); the box
   sizes to its content and the box + invitation group is centered in the column,
   which is locked to the video's actual rendered height via a small ResizeObserver
   script (see scripts-main.js, ia-media/.ia-words sync) rather than tuned
   padding — the video's height is aspect-ratio-locked and the text's isn't, so
   no static CSS values could guarantee an exact match at every viewport width;
   several attempts at manually tuning spacing per-breakpoint kept drifting out
   of sync at widths that weren't specifically tested. The padding below is just
   the visual baseline; the JS is what actually guarantees the match. */
.ia-quote--featured {
  position: relative;
  flex: 1 1 auto;   /* grow to fill the column (locked to the video height) so the quote box
                       matches the video and the CTA sits directly beneath it — no dead gap.
                       Contents are spread via justify-content:space-between below so the
                       extra height reads as breathing room, not a hollow band. */
  min-height: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;   /* keep mark → quote → caption as a tight group and center it in the
                                grown box, so the surplus becomes even breathing room top and
                                bottom — NOT a gap between the quote text and Ansel's photo
                                (which space-between produced). */
  border-left: 2px solid rgba(216,168,90,.5);
  background: rgba(216,168,90,.045);
  padding: 1rem 1.3rem .85rem 1.5rem;
}
.ia-quote-mark {
  /* In-flow (NOT absolute): the box grows to the video's height and the content
     group is vertically centered, so an absolutely-positioned mark pinned to the
     top drifted away from the centered text, leaving a dead band beneath the
     glyph. In flow with a short line-box + negative bottom margin, the glyph
     sits tucked right above the first line of the quote, the way a pull-quote
     mark should — and it travels WITH the text at any box height. */
  display: block;
  height: 1.4rem;
  margin: 0 0 -0.9rem;
  font-family: Georgia, 'Fraunces', serif;
  font-size: 2.6rem;
  line-height: 0.5;
  color: rgba(216,168,90,.35);
  pointer-events: none;
}
/* A little breathing room between the end of the testimony and Ansel's
   photo/name so the attribution doesn't jam against the last line. */
.ia-quote--featured .ia-quote-cap { margin-top: 1.1rem; }
/* Closing mark mirrors the opening one — same large gold serif glyph, positioned
   at the quote's bottom-right so the two marks bracket the testimony (attribution
   sits below, outside the brackets). Absolute within the position:relative blockquote. */
.ia-quote-mark-close {
  position: absolute;
  right: -.65rem;
  bottom: -.7rem;
  font-family: Georgia, 'Fraunces', serif;
  font-size: 2.6rem;
  line-height: 1;
  color: rgba(216,168,90,.35);
  margin: 0;
  pointer-events: none;
}
.ia-quote--featured blockquote { position: relative; z-index: 1; font-size: 1.02rem; line-height: 1.6; color: rgba(233,238,247,.9); padding-left: .55rem; margin-bottom: .45rem; }
/* Ansel's words are two reflections from two moments — woven into one quote but
   clearly separated by a full-width gold rule that fades at both ends. */
.ia-quote--featured blockquote p { margin: 0; }
.ia-quote--featured blockquote p + p { margin-top: .65rem; }
.ia-quote--featured blockquote p + p::before {
  content: "";
  display: block;
  width: 100%;
  height: 1px;
  margin-bottom: .65rem;
  background: linear-gradient(90deg, transparent, rgba(216,168,90,.5) 15%, rgba(216,168,90,.5) 85%, transparent);
}

/* 820px was too low a threshold — measured the actual height mismatch between
   the video and Ansel's column across the full desktop range and found it's fine
   at 1280px+ (27px diff) but balloons badly in the 900–1200px zone (55–236px),
   a completely realistic laptop-browser-window range that went untested before.
   Stack single-column through that zone instead of forcing a cramped 2-up split. */
@media (max-width: 1279px) {
  .ia-split { grid-template-columns: 1fr; gap: 1.75rem; }
  /* The 900px cap exists to stop the video stretching thin on true widescreen
     (see .ia-media comment above) — but once stacked single-column here, that
     same cap left the video narrower than its own full-width column, showing
     as a large empty gap beside it. Full width in the stack, same as mobile. */
  .ia-media { max-width: none; }
}


/* Scroll progress bar — thin tri-colour line at the very top that fills as the
   visitor scrolls. A subtle, modern "alive" cue. */
.scroll-progress {
  position: fixed; top: 0; left: 0;
  width: 100%; height: 3px;
  z-index: 3000; pointer-events: none; background: transparent;
}
.scroll-progress-fill {
  display: block; height: 100%; width: 0;
  background: linear-gradient(90deg, var(--h2h-red, #CE1126), var(--h2h-gold, #D8A85A), var(--h2h-blue, #1FA6DE));
}

#mainNavDrawer .pnav-item--active .pnav-item-pip { display: block; }

/* ── Staggered card reveals ─────────────────────────────────────────────────
   A grid tagged .stagger (alongside .reveal-on-scroll) fades its children in
   one-by-one when the grid scrolls into view, instead of all at once. */
.reveal-on-scroll.stagger { opacity: 1; transform: none; transition: none; }
.stagger > * {
  opacity: 0; transform: translateY(18px);
  transition: opacity .55s cubic-bezier(.22,.61,.36,1), transform .55s cubic-bezier(.22,.61,.36,1);
  will-change: opacity, transform;
}
.stagger.is-visible > * { opacity: 1; transform: none; will-change: auto; }
.stagger.is-visible > *:nth-child(1) { transition-delay: .04s; }
.stagger.is-visible > *:nth-child(2) { transition-delay: .11s; }
.stagger.is-visible > *:nth-child(3) { transition-delay: .18s; }
.stagger.is-visible > *:nth-child(4) { transition-delay: .25s; }
.stagger.is-visible > *:nth-child(5) { transition-delay: .32s; }
.stagger.is-visible > *:nth-child(6) { transition-delay: .39s; }
@media (prefers-reduced-motion: reduce) { .stagger > * { opacity: 1; transform: none; transition: none; } }

/* ── Gentle float on the spotlight media frame ──────────────────────────── */
@keyframes h2hFloat { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-7px); } }

/* ==========================================================================
   HOMEPAGE TYPE FLOOR — nothing renders smaller than .85rem (the size used for
   the Ansel quote role, ".ia-quote-role"). These small eyebrows, kickers, badges,
   captions, and labels were all below that floor; this raises them to it so the
   page has a consistent minimum readable size. Kept in one block (vs. editing 26
   scattered rules) so the floor is obvious and easy to adjust. Scoped to the
   homepage so the portal/fundraiser keep their own scale.
   ========================================================================== */
body.page-main-home .mse-kicker,
body.page-main-home .impact-band-kicker,
body.page-main-home .event-eyebrow,
body.page-main-home .event-subhead,
body.page-main-home .story-leap-label,
body.page-main-home .cf-toggle-label,
body.page-main-home .about-founders-cap,
body.page-main-home .ia-video-play-label,
body.page-main-home .ia-video-play-time,
body.page-main-home .vs-ref,
body.page-main-home .header-donate-btn,
body.page-main-home .home-enter-label,
body.page-main-home .main-footer-heading {
  font-size: .85rem !important;
}

/* ==========================================================================
   EVENTS — "next mission" cinematic flow (replaces the old two-column grid).
   A conversion surface: one dramatized hero (countdown-led), then slim rails.
   Scoped under body.page-main-home so it never leaks to the portal event list.
   ========================================================================== */
body.page-main-home .evt-flow {
  /* Align the flow's left edge with the section TITLE (not the accent bar):
     the editorial header indents its title by the bar width + column gap, and
     --ed-col-indent (= 6px + --ed-gap) is the shared token that expresses exactly
     that offset. Same token donate/contact use, so all sections line up and it
     tracks the header responsively. max-width shrinks by the indent so the right
     edge still lands at the container edge. */
  max-width: calc(var(--container) - var(--ed-col-indent));
  margin: clamp(1.5rem, 3vw, 2.25rem) 0 0 var(--ed-col-indent);
  display: flex;
  flex-direction: column;
  gap: clamp(1.75rem, 3.5vw, 2.75rem);
}

/* ── LEAD BAND ───────────────────────────────────────────────────────────────
   The primary hero and its optional "also open" companion aside share one row:
   hero takes the flexible main column, the companion aside a fixed-ish right
   rail. align-items:stretch makes the aside match the hero's height (no dead
   space, no stranded short column). When there's no companion, .evt-lead--solo
   collapses to a single column so the hero fills the row exactly as before. */
body.page-main-home .evt-lead {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(260px, 340px);
  gap: clamp(1.5rem, 3vw, 2.5rem);
  align-items: start;
}
body.page-main-home .evt-lead--solo { grid-template-columns: minmax(0, 1fr); }

/* ── HERO ──────────────────────────────────────────────────────────────────
   Editorial, not a boxed card: no fill, border, or radius on the hero frame —
   the poster and the type carry it, with whitespace as the container. The body
   column STRETCHES to the poster's height (align-items:stretch) so the shift
   agenda and the Sign Up row fill the frame instead of floating mid-column. */
body.page-main-home .evt-hero {
  display: grid;
  grid-template-columns: minmax(0, clamp(260px, 32%, 360px)) minmax(0, 1fr);
  gap: clamp(1.25rem, 3vw, 2.25rem);
  align-items: stretch;
}
body.page-main-home .evt-hero-media { position: relative; min-height: 0; }
/* The poster keeps its .evt-open-hero sheen-sweep + .evt-ph placeholder styling;
   here we only override the old 110px-float sizing so it becomes the SQUARE hero
   slot. Event posters are 500×500 — a 1:1 box shows them WHOLE (object-fit
   contain, never cropped/skewed). Capped smaller than before (was 460px) so the
   hero no longer dominates the viewport. Top-aligned in its column so any surplus
   height from a taller body sits below it as intentional breathing room. */
body.page-main-home .evt-hero-poster {
  float: none;
  width: 100%;
  max-width: 360px;
  aspect-ratio: 1 / 1;
  height: auto;
  margin: 0;
  align-self: start;
  border-radius: 12px;
  overflow: hidden;
  background: #0b1120;
}
body.page-main-home .evt-hero-poster > img {
  width: 100%; height: 100%;
  object-fit: contain;
  display: block;
}
/* Placeholder branch: .evt-ph already fills a 1:1 box, so let it fill the square. */
body.page-main-home .evt-hero-poster.evt-open-hero--ph .evt-ph { height: 100%; }
body.page-main-home .evt-hero-body {
  display: flex;
  flex-direction: column;
  gap: .7rem;
  min-width: 0;
  padding: .35rem .25rem;
}
body.page-main-home .evt-hero-body .evt-open-kicker { margin: 0; }

/* Countdown — the emotional anchor, leading the pitch. Sized to its content
   (not the full column width) so it reads as a self-contained beat, not a form
   field spanning the text block. */
body.page-main-home .evt-hero-countdown {
  align-self: start;
  width: fit-content;
  max-width: 100%;
  margin: .1rem 0 .5rem;
  padding: .85rem 1.15rem;
  border: 1px solid rgba(216,168,90,.28);
  border-radius: 12px;
  background: linear-gradient(180deg, rgba(216,168,90,.10), rgba(216,168,90,.04));
}
body.page-main-home .evt-hero-countdown .evt-cd-label {
  display: block;
  font-family: 'Barlow Condensed', sans-serif;
  text-transform: uppercase;
  letter-spacing: .12em;
  font-size: .9rem;
  color: rgba(233,238,247,.78);
  margin-bottom: .5rem;
}
body.page-main-home .evt-cd-clock { display: flex; gap: clamp(.6rem, 2vw, 1.2rem); }
body.page-main-home .evt-hero-countdown .evt-cd-unit {
  display: flex; flex-direction: column; align-items: center;
  line-height: 1;
}
body.page-main-home .evt-hero-countdown .evt-cd-unit b {
  font-family: 'Oswald', sans-serif;
  font-weight: 600;
  font-size: clamp(1.6rem, 4vw, 2.3rem);
  color: var(--h2h-gold, #D8A85A);
  font-variant-numeric: tabular-nums;
}
body.page-main-home .evt-hero-countdown .evt-cd-unit span {
  margin-top: .25rem;
  font-family: 'Barlow Condensed', sans-serif;
  text-transform: uppercase;
  letter-spacing: .1em;
  font-size: .62rem;
  color: rgba(233,238,247,.55);
}
/* Heartbeat pulse on the seconds digit — a subtle tick that makes the countdown
   feel alive rather than static. Honors reduced-motion below. */
@keyframes evtCdSecPulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.14); } }
body.page-main-home .evt-hero-countdown .evt-cd-unit--sec b {
  display: inline-block;
  animation: evtCdSecPulse 1s ease-in-out infinite;
  transform-origin: center;
}
/* Urgent state (JS adds .is-urgent within 48h) — warms the whole countdown toward
   red so the last push reads as "now or never," and lifts the border/label. */
body.page-main-home .evt-hero-countdown.is-urgent {
  border-color: rgba(206,17,38,.45);
  background: linear-gradient(180deg, rgba(206,17,38,.14), rgba(206,17,38,.05));
}
body.page-main-home .evt-hero-countdown.is-urgent .evt-cd-unit b { color: #ff5a6a; }
body.page-main-home .evt-hero-countdown.is-urgent .evt-cd-label { color: rgba(255,138,148,.95); }
@media (prefers-reduced-motion: reduce) {
  body.page-main-home .evt-hero-countdown .evt-cd-unit--sec b { animation: none; }
}

body.page-main-home .evt-hero-title {
  font-family: 'Barlow Condensed', 'Oswald', sans-serif;
  font-weight: 600;
  font-size: clamp(1.6rem, 3.4vw, 2.35rem);
  line-height: 1.05;
  color: #fff;
  margin: 0;
}

/* Meta chips — date + venue as clean pills, not run-on text */
body.page-main-home .evt-hero-meta { display: flex; flex-wrap: wrap; gap: .5rem; }
body.page-main-home .evt-chip {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .32rem .7rem;
  border: 1px solid rgba(255,255,255,.14);
  border-radius: 999px;
  font-size: .82rem;
  color: rgba(233,238,247,.85);
  text-decoration: none;
}
body.page-main-home .evt-chip i { color: var(--h2h-gold, #D8A85A); font-size: .95rem; }

/* Condensed shifts — time · role · spots pill, hairline-separated rows */
body.page-main-home .evt-hero-shifts {
  display: flex; flex-direction: column;
  margin: .15rem 0 .1rem;
  border-top: 1px solid rgba(255,255,255,.08);
}
body.page-main-home .evt-sh {
  display: grid;
  /* time → detail (flexes to fill) → spots pill. Detail is minmax(0,1fr) so it
     absorbs the row's slack itself and the spots pill trails at exactly one gap
     after the text — no empty spacer column stranding the pill at the far right.
     (The old `auto max-content 1fr auto` pushed the pill to the frame edge in a
     wide body; this keeps time · detail · pill reading as one tight line.) */
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas: 'time detail spots';
  gap: .5rem 1.25rem;
  align-items: center;
  padding: .6rem 0;
  border-bottom: 1px solid rgba(255,255,255,.08);
}
body.page-main-home .evt-sh-time {
  grid-area: time;
  display: inline-flex; align-items: baseline; gap: .45rem;
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 600;
  letter-spacing: .02em;
  color: #fff;
  white-space: nowrap;
}
body.page-main-home .evt-sh-ico {
  color: var(--h2h-gold, #D8A85A);
  font-size: .95rem;
  position: relative; top: .12em;
}
/* Stacked detail block: role (line 1) over location (line 2). */
body.page-main-home .evt-sh-detail {
  grid-area: detail;
  display: flex; flex-direction: column; gap: .15rem;
  min-width: 0;
}
body.page-main-home .evt-sh-role {
  font-size: .92rem;
  color: rgba(233,238,247,.92);
  line-height: 1.2;
}
/* Location line — quiet, gold, tappable to Maps; shown on every shift. */
body.page-main-home .evt-sh-loc {
  align-self: flex-start;
  display: inline-flex; align-items: center; gap: .3rem;
  font-size: .8rem;
  color: rgba(216,168,90,.8);
  text-decoration: none;
  white-space: nowrap;
  max-width: 100%;
}
body.page-main-home .evt-sh-loc i { font-size: .95em; flex-shrink: 0; }
body.page-main-home .evt-sh-loc span,
body.page-main-home .evt-sh-loc { overflow: hidden; text-overflow: ellipsis; }
body.page-main-home .evt-sh-loc:hover { color: #fff; }
body.page-main-home .evt-sh-spots {
  grid-area: spots;
  justify-self: end;
  padding: .18rem .55rem;
  border-radius: 999px;
  font-family: 'Barlow Condensed', sans-serif;
  font-size: .74rem;
  letter-spacing: .04em;
  text-transform: uppercase;
  white-space: nowrap;
  color: #10B981;
  background: rgba(16,185,129,.12);
  border: 1px solid rgba(16,185,129,.3);
}
/* Low availability (<10) — an amber nudge that a shift is filling up. */
body.page-main-home .evt-sh-spots.is-low {
  color: #D8A85A;
  background: rgba(216,168,90,.12);
  border-color: rgba(216,168,90,.4);
}
body.page-main-home .evt-sh-spots.is-full {
  color: rgba(233,238,247,.55);
  background: rgba(255,255,255,.05);
  border-color: rgba(255,255,255,.14);
}
body.page-main-home .evt-sh.is-full .evt-sh-time,
body.page-main-home .evt-sh.is-full .evt-sh-role { opacity: .55; }

body.page-main-home .evt-hero-actions {
  display: flex; flex-wrap: wrap; align-items: center; gap: .8rem 1.1rem;
  margin-top: auto;
  padding-top: .5rem;
}
body.page-main-home .evt-hero-actions .evt-cd-pr-note { width: 100%; margin: 0; }

/* ── SAVE THE DATE — full-width horizontal rail ─────────────────────── */
body.page-main-home .evt-upcoming { display: flex; flex-direction: column; gap: 1rem; }
body.page-main-home .evt-upcoming-head {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: .5rem 1rem;
  border-top: 1px solid rgba(255,255,255,.08);
  padding-top: 1rem;
}
body.page-main-home .evt-upcoming-head .event-subhead { margin: 0; }
/* Base label styling — restored here after being mistakenly swept up in an
   Events dead-code cleanup pass; still live (the "Save the Date" label above
   the upcoming-events rail). The margin override just above zeroes this rule's
   own margin for that specific placement. */
.event-subhead {
  font-family: 'DM Sans', sans-serif;
  font-weight: 700; font-size: .82rem; letter-spacing: .14em; text-transform: uppercase;
  color: rgba(233,238,247,.5);
  margin: 1.75rem 0 1rem;
}
/* Quiet clarifier that replaced the old "Add all events" button in the head. */
body.page-main-home .evt-upcoming-note {
  font-family: 'Barlow Condensed', sans-serif;
  text-transform: uppercase;
  letter-spacing: .08em;
  font-size: .78rem;
  color: rgba(233,238,247,.5);
}
/* Flex-wrap (not a fixed grid): the future-events count is dynamic — 1, 2, 3, or
   more — so cards flow and wrap naturally, each keeping a sensible min/max width
   rather than stretching to fill a hardcoded column count. */
body.page-main-home .evt-upcoming-rail {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}
@media (max-width: 720px) { body.page-main-home .evt-up-card { flex-basis: 100%; max-width: none; } }
body.page-main-home .evt-up-card {
  flex: 1 1 240px;
  max-width: 420px;
  display: flex; flex-direction: column; gap: .3rem;
  padding: .2rem 0 .2rem 1rem;
  border-left: 2px solid rgba(216,168,90,.35);
}
body.page-main-home .evt-up-date { display: flex; align-items: baseline; gap: .4rem; margin-bottom: .15rem; }
body.page-main-home .evt-up-mon {
  font-family: 'Barlow Condensed', sans-serif;
  text-transform: uppercase;
  letter-spacing: .1em;
  font-size: .8rem;
  color: var(--h2h-gold, #D8A85A);
}
body.page-main-home .evt-up-day {
  font-family: 'Oswald', sans-serif;
  font-weight: 600;
  font-size: 1.5rem;
  color: #fff;
  line-height: 1;
}
body.page-main-home .evt-up-title {
  font-family: 'Barlow Condensed', sans-serif;
  font-weight: 600;
  font-size: 1.1rem;
  color: #fff;
  line-height: 1.15;
}
body.page-main-home .evt-up-opens { font-size: .8rem; color: rgba(233,238,247,.55); }
/* Two-pill action row on each save-the-date card (Remind me + Add to calendar). */
body.page-main-home .evt-up-actions {
  display: flex; flex-wrap: wrap; gap: .5rem;
  margin-top: .45rem;
}
body.page-main-home .evt-up-pill {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .35rem .8rem;
  border: 1px solid rgba(255,255,255,.16);
  border-radius: 999px;
  background: transparent;
  color: rgba(233,238,247,.8);
  font-family: 'Barlow Condensed', sans-serif;
  text-transform: uppercase;
  letter-spacing: .05em;
  font-size: .74rem;
  cursor: pointer;
  transition: border-color .18s ease, color .18s ease, background .18s ease;
}
body.page-main-home .evt-up-pill:hover { border-color: rgba(216,168,90,.5); color: #fff; }
body.page-main-home .evt-up-pill i { font-size: .95em; }
/* Quiet overflow line under the save-the-date rail ("+ N more later this year"). */
body.page-main-home .evt-up-more {
  margin: .25rem 0 0;
  font-family: 'Barlow Condensed', sans-serif;
  text-transform: uppercase;
  letter-spacing: .1em;
  font-size: .82rem;
  color: rgba(233,238,247,.5);
}

/* ── Community partners — section-level standing strip (rotating spotlight) ──
   Sits at the very end of the flow: a general "made possible by our community
   partners" acknowledgment, deliberately NOT inside any event so it reads as
   year-round support, not event sponsorship. The rotator JS swaps #evtPrImg
   through all active partners. */
body.page-main-home .evt-partners {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .5rem;
  border-top: 1px solid rgba(255,255,255,.08);
  padding-top: clamp(1.25rem, 3vw, 2rem);
  text-align: center;
}
body.page-main-home .evt-partners .evt-cd-partner-row {
  display: flex; flex-direction: column; align-items: center; gap: .6rem;
  width: auto; margin: 0;
}
body.page-main-home .evt-partners .evt-cd-pr-label {
  font-family: 'Barlow Condensed', sans-serif;
  text-transform: uppercase;
  letter-spacing: .14em;
  font-size: .75rem;
  color: rgba(233,238,247,.6);
}
body.page-main-home .evt-partners .evt-cd-pr-note { margin: 0; }

/* ── Header 45-day clarifier line (under the subtitle) ───────────────── */
body.page-main-home .mse-note {
  display: flex; align-items: center; gap: .4rem;
  margin: .5rem 0 0;
  font-family: 'Barlow Condensed', sans-serif;
  font-size: .85rem;
  letter-spacing: .02em;
  color: rgba(233,238,247,.55);
}
body.page-main-home .mse-note i { color: var(--h2h-gold, #D8A85A); font-size: 1em; }

/* ── MORE OPEN — compact "also open" rows for secondary open events ───────
   Deliberately lighter than the hero so a 2nd open event reads as "also
   available," never a co-headliner: small thumbnail, title, date, shift count,
   Sign Up. Hairline-separated rows; editorial, not filled cards. */
body.page-main-home .evt-more {
  /* Companion aside beside the hero. A soft filled panel (unlike the borderless
     hero) so it reads as a distinct "also available" surface without competing;
     stretches to the hero's height via the .evt-lead grid. Three-part vertical
     rhythm so it never looks half-empty next to a tall hero: label pinned top,
     the card(s) centered in the free space, a quiet "all shifts" link anchoring
     the bottom edge. */
  align-self: stretch;
  display: flex; flex-direction: column;
  padding: clamp(1rem, 2vw, 1.4rem);
  border: 1px solid rgba(255,255,255,.08);
  border-radius: 14px;
  background: linear-gradient(180deg, rgba(255,255,255,.035), rgba(255,255,255,.015));
}
body.page-main-home .evt-more-label {
  margin: 0 0 1rem;
  font-family: 'Barlow Condensed', sans-serif;
  text-transform: uppercase;
  letter-spacing: .14em;
  font-size: .78rem;
  color: rgba(233,238,247,.6);
}
/* The card stack takes the free vertical space and centers within it, so a lone
   companion sits in the optical middle of the panel rather than clinging to the
   top. With two companions the stack simply fills and this is a no-op. */
body.page-main-home .evt-more-cards {
  flex: 1 1 auto;
  display: flex; flex-direction: column; gap: 1rem;
  justify-content: center;
}
/* Quiet footer link anchoring the panel's bottom edge. */
body.page-main-home .evt-more-foot {
  margin-top: 1rem;
  padding-top: .9rem;
  border-top: 1px solid rgba(255,255,255,.08);
}
body.page-main-home .evt-more-all {
  display: inline-flex; align-items: center; gap: .4rem;
  font-family: 'Barlow Condensed', sans-serif;
  text-transform: uppercase;
  letter-spacing: .08em;
  font-size: .8rem;
  color: rgba(233,238,247,.7);
  text-decoration: none;
  transition: color .18s ease, gap .18s ease;
}
body.page-main-home .evt-more-all i { color: var(--h2h-gold, #D8A85A); transition: transform .18s ease; }
body.page-main-home .evt-more-all:hover { color: #fff; gap: .6rem; }
/* Each companion event: thumbnail on top, identity + meta + CTA stacked below.
   Vertical (not a wide row) because the aside column is narrow — this keeps the
   Sign Up button directly under the text it belongs to, never flung to a far edge. */
body.page-main-home .evt-mo {
  display: flex; flex-direction: column; gap: .7rem;
}
body.page-main-home .evt-mo + .evt-mo {
  padding-top: 1rem;
  border-top: 1px solid rgba(255,255,255,.08);
}
body.page-main-home .evt-mo-thumb {
  width: 100%; aspect-ratio: 1 / 1;
  border-radius: 10px;
  overflow: hidden;
  background: #0b1120;
  display: flex; align-items: center; justify-content: center;
}
body.page-main-home .evt-mo-thumb img { width: 100%; height: 100%; object-fit: contain; }
/* Branded mini-placeholder: reuse the hero's .evt-ph identity (logo + category)
   scaled into the 1:1 thumbnail. .evt-ph itself is styled once with the hero;
   this only sizes it to fill the thumb so a companion with no artwork still
   reads as H2H. */
body.page-main-home .evt-mo-thumb-ph.evt-ph {
  width: 100%; height: 100%;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: .4rem;
}
body.page-main-home .evt-mo-thumb-ph.evt-ph .evt-ph-logo { width: clamp(38px, 22%, 56px); height: auto; }
body.page-main-home .evt-mo-body { min-width: 0; display: flex; flex-direction: column; gap: .35rem; }
body.page-main-home .evt-mo-title {
  margin: 0;
  font-family: 'Oswald', sans-serif;
  font-weight: 600;
  font-size: 1.05rem;
  color: #fff;
  line-height: 1.15;
}
body.page-main-home .evt-mo-meta {
  display: flex; flex-wrap: wrap; gap: .3rem 1rem;
  font-family: 'Barlow Condensed', sans-serif;
  font-size: .85rem;
  color: rgba(233,238,247,.6);
}
body.page-main-home .evt-mo-meta span { display: inline-flex; align-items: center; gap: .35rem; }
body.page-main-home .evt-mo-meta i { color: var(--h2h-gold, #D8A85A); font-size: .95em; }
body.page-main-home .evt-mo-cta { align-self: start; white-space: nowrap; margin-top: .15rem; }

/* ── Responsive: stack the lead band + hero on narrow screens ─────────── */
@media (max-width: 960px) {
  /* Lead band collapses first: the companion aside drops below the hero as a
     full-width block rather than fighting for a 260px rail on a mid-width screen. */
  body.page-main-home .evt-lead { grid-template-columns: 1fr; }
  /* With the aside now full-width, the companion card's "vertical because the
     rail is narrow" rationale inverts: go horizontal so the branded thumbnail
     stays a compact square instead of ballooning to the full column width. */
  body.page-main-home .evt-mo { flex-direction: row; align-items: center; gap: 1.1rem; }
  body.page-main-home .evt-mo-thumb { width: clamp(104px, 20%, 140px); flex: 0 0 auto; }
  body.page-main-home .evt-mo-body { flex: 1 1 auto; }
}
@media (max-width: 860px) {
  body.page-main-home .evt-hero {
    grid-template-columns: 1fr;
  }
  /* Stacked: cap the square poster so it doesn't dominate the card on narrow screens. */
  body.page-main-home .evt-hero-poster { max-width: 320px; justify-self: start; }
}
@media (max-width: 560px) {
  body.page-main-home .evt-sh {
    grid-template-columns: 1fr auto;
    grid-template-areas: 'time spots' 'detail detail';
    row-gap: .3rem;
  }
}

/* ── Closing call — the two doors (Serve + Give) ─────────────────────────────
   The page's send-off: one warm line and the two ways to show up, side by side.
   Sits last (order:10), so it closes the story instead of crowding the hero. */
.join-band {
  position: relative;
  background: #070b14;
  text-align: center;
  overflow: hidden;
}
/* The mission photo — faint enough to read as atmosphere, strong enough to feel */
.join-bg {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center 0;   /* top-aligned so no one's head is cropped in the short, wide band (the group's heads sit near the top of the frame) */
  background-repeat: no-repeat;
  opacity: .82;   /* was .78; nudged up slightly since the dimming now comes from brightness, not opacity washing into the navy */
  filter: brightness(0.62) saturate(1.02) contrast(1.02);   /* the reference recipe: dim via opacity(.82) + this filter, with only a light text-zone scrim. impact + donate now match this. */
  transform: scale(1.04);   /* slight overscale guards against edge flicker */
  animation: joinDrift 21s ease-in-out infinite alternate;   /* slow ambient breath, same motion language as the impact band */
}
/* Top-biased so the group's heads (near the top of the frame) stay in view across
   the whole cycle; both extremes keep the band fully covered (verified). */
@keyframes joinDrift {
  from { transform: scale(1.06) translate3d(-0.8%, 0.4%, 0); }
  to   { transform: scale(1.12) translate3d(1.0%, -0.6%, 0); }
}
/* Scrim: a clean full-width darkening, NOT a soft radial pool. The old radial
   ellipse floated a blurry dark blob in the middle of the bright photo — its soft
   circular edge read as fuzz/smudge with no structure. Instead: an even overall
   dim (so no visible edge anywhere) plus a horizontal band that deepens through
   the middle third where the headline + subtitle sit. A horizontal band has no
   circular edge to perceive, so it reads as intentional lighting, not haze. The
   photo still shows through bright at the very top/bottom. */
.join-band::before {
  content: '';
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to bottom,
      rgba(7,11,20,.34) 0%,
      rgba(7,11,20,.72) 34%,
      rgba(7,11,20,.78) 58%,
      rgba(7,11,20,.52) 82%,
      rgba(7,11,20,.40) 100%);
  z-index: 1;
  pointer-events: none;
}
/* Full-bleed closing band: photo spans edge-to-edge (no side gutter); content stays
   centered via .join-inner max-width. Vertical rhythm is uniform on top (matches the
   editorial base) with a tighter bottom so the send-off reads punchy, not sparse
   (the old full base left ~90px dead below the buttons). */
body.page-landing #join { padding-left: 0; padding-right: 0; }
body.page-main-home #join.join-band { padding-top: clamp(3rem, 5.5vw, 5rem); padding-bottom: clamp(2.5rem, 4vw, 3.5rem); }
.join-inner { position: relative; z-index: 2; max-width: 640px; margin: 0 auto; }
.join-eyebrow {
  font-family: 'Oswald', sans-serif; font-size: .95rem; font-weight: 500;
  letter-spacing: .24em; text-transform: uppercase; color: rgba(216,168,90,.7);
  margin-bottom: .85rem;
}
.join-title {
  font-family: 'Bebas Neue', 'Barlow Condensed', sans-serif;
  font-size: clamp(2.4rem, 6vw, 3.8rem); line-height: .98; letter-spacing: .01em;
  color: #fff; margin: 0 0 .9rem;
  font-weight: 400;   /* Bebas Neue ships ONLY weight 400 — an inherited 700 forced the browser to synthesize bold, fattening the strokes into a heavy, almost-3D look. 400 is the font's true weight (also honors the display-font max-600 rule). */
  text-shadow: 0 1px 3px rgba(7,11,20,.45);   /* tight edge-definition only — the horizontal band scrim does the legibility work, so this stays small to avoid the fuzzy halo a large blur produced */
}
.join-title em { font-style: normal; color: var(--h2h-gold, #D8A85A); }
.join-sub {
  font-size: clamp(1rem, 1.6vw, 1.15rem); line-height: 1.6;
  color: rgba(255,255,255,.96); margin: 0 auto 2rem; max-width: 30rem;
  text-shadow: 0 1px 10px rgba(7,11,20,.75);   /* full-opacity white + shadow so the subtitle stops getting lost in the photo */
}
.join-actions { display: flex; gap: 1rem; justify-content: center; flex-wrap: wrap; align-items: center; }
.join-btn {
  display: inline-flex; align-items: center; gap: .5rem;
  font-family: 'Oswald', sans-serif; font-weight: 600;
  letter-spacing: .04em; text-transform: uppercase;
  border-radius: 12px; cursor: pointer;
  text-decoration: none; border: 1.5px solid transparent;
  transition: transform .2s ease, background .2s ease, border-color .2s ease, box-shadow .2s ease;
}
.join-btn i { font-size: 1.1rem; }
.join-btn--serve {
  font-size: 1.08rem; padding: 1rem 2.35rem;
  background: var(--h2h-gold, #D8A85A); color: #1a1205;
  box-shadow: 0 10px 28px rgba(216,168,90,.28);
}
.join-btn--serve:hover { transform: translateY(-3px); box-shadow: 0 18px 42px rgba(216,168,90,.38); }
.join-btn--give {
  font-size: .9rem; padding: .75rem 1.65rem;
  background: rgba(255,255,255,.04); color: rgba(233,238,247,.75);
  border-color: rgba(255,255,255,.22);
}
.join-btn--give:hover {
  transform: translateY(-2px);
  color: #fff; border-color: rgba(255,255,255,.5);
  background: rgba(255,255,255,.1);
}
.join-btn--give i { color: var(--h2h-red, #CE1126); }
@media (max-width: 460px) {
  .join-actions { flex-direction: column; }
  .join-btn { justify-content: center; width: 100%; max-width: 280px; margin: 0 auto; }
}
@media (prefers-reduced-motion: reduce) {
  .join-btn:hover { transform: none; }
}

/* ── Section content left-alignment — title column (after bar+gap indent) ──
   Targets content blocks that were sitting at the bar's x (105px) instead of
   the title's x (137px). Direct rules placed last in the cascade so they win
   over any conflicting margin resets above. --ed-col-indent = 4px + --ed-gap. */

/* The founders figure is the left panel's content; zero its own bottom margin so
   spacing comes from .contact-left's flex gap. (Reach-us methods used to sit here
   too but now live in a full-width strip below the grid — see .contact-reach.) */
.contact-left .contact-founders-feature { margin-bottom: 0; }

/* ── Contact founders — transparent cut-out portrait ─────────────────────────
   The founders are a cut-out on a transparent background: they emerge from a
   warm gold glow, and the mid-torso crop dissolves into the navy (no framed
   photo box). The portrait now lives inside the left panel (.contact-left),
   under the header and above the form's right column. On mobile the grid
   becomes a flex column: header, then founders, then form. */
.contact-founders-stage {
  position: relative;
  display: block;
  padding-top: 1.25rem;
  margin-bottom: .9rem;
  isolation: isolate;
}
/* Warm spotlight behind them — they step out of the light. Breathes slowly so
   the section feels alive without flickering. */
.contact-founders-stage::before {
  content: '';
  position: absolute; z-index: 0;
  left: 50%; top: 6%;
  width: 86%; height: 96%;
  transform: translateX(-50%);
  background: radial-gradient(ellipse 58% 60% at 50% 42%,
              rgba(216,168,90,.30), rgba(216,168,90,.12) 46%, transparent 72%);
  filter: blur(4px);
  pointer-events: none;
  animation: foundersGlow 10s ease-in-out infinite;
}
#contact .contact-founders-stage img {
  position: relative; z-index: 1;
  display: block;
  width: 84%;
  max-width: 430px;
  height: auto;            /* preserve true proportions — no stretch */
  object-fit: contain;
  border-radius: 0;
  margin: 0 auto;
  /* bottom fade — the mid-torso crop dissolves into the navy */
  -webkit-mask-image: linear-gradient(to bottom, #000 74%, transparent 99%);
          mask-image: linear-gradient(to bottom, #000 74%, transparent 99%);
  filter: drop-shadow(0 16px 26px rgba(0,0,0,.40));
}
@keyframes foundersGlow { 0%, 100% { opacity: .82; } 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .contact-founders-stage::before { animation: none; }
}

/* Mobile: the grid becomes a flex column. DOM order already gives the right
   sequence — the left panel (header, then founders) stacks first, then the form. */
@media (max-width: 820px) {
  #contact .contact-grid { display: flex; flex-direction: column; }
  #contact .contact-founders-stage img { width: 78%; }
  /* Stacked layout: drop the form's left spine + its padding — a left-edge
     hairline only makes sense beside the founders column in the two-column row. */
  .contact-form-wrap { padding-left: 0; }
  .contact-form-wrap::before { display: none; }
}



