/* ==========================================================================
   ICCH — Iglesia Cristiana Comunidad Hispana
   Design system: refined teal · Inter · full-bleed photo hero
   ========================================================================== */

/* ---------- fonts (self-hosted, no third-party request) ---------- */

/* Two families:
   - Manrope for body, UI, meta, and interior headings (h3, h4). Warm humanist
     sans — rounder terminals than Inter, less "product page" feel, still
     professional. Variable weight woff2 keeps it small (~25 KB latin).
   - Fraunces for display: hero title, page-head title, section h2, pull-quotes.
     Editorial serif — variable-weight/opsz axis renders soft at large sizes.
   All self-hosted, subset to latin + latin-ext. */
@font-face {
  font-family: 'Manrope';
  src: url('../fonts/manrope-latin.woff2') format('woff2-variations');
  font-weight: 300 800;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
                 U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Manrope';
  src: url('../fonts/manrope-latin-ext.woff2') format('woff2-variations');
  font-weight: 300 800;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
                 U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF,
                 U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* Newsreader — variable serif designed for editorial reading. Lower stroke
   contrast than Fraunces, warmer terminals, opsz + wght axes. Site default
   serif; reads clearly at long titles where Fraunces got fragile. */
@font-face {
  font-family: 'Newsreader';
  src: url('../fonts/newsreader-latin.woff2') format('woff2-variations');
  font-weight: 200 800;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
                 U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Newsreader';
  src: url('../fonts/newsreader-latin-ext.woff2') format('woff2-variations');
  font-weight: 200 800;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
                 U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF,
                 U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* Fraunces — kept only for the hero H1. High-contrast display serif; the
   thin strokes that made it hard to read at longer titles are a feature here,
   because the hero is a single confident line meant to feel editorial. */
@font-face {
  font-family: 'Fraunces';
  src: url('../fonts/fraunces-latin.woff2') format('woff2-variations');
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
                 U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Fraunces';
  src: url('../fonts/fraunces-latin-ext.woff2') format('woff2-variations');
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
                 U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF,
                 U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ---------- tokens ---------- */

:root {
  /* brand */
  --teal-900: #072F37;
  --teal-800: #0B424C;
  --teal-700: #0F5560;   /* primary */
  --teal-600: #16697A;
  --teal-100: #D9E8EB;
  --teal-50:  #EDF4F5;

  /* neutrals */
  --ink:      #101A1D;
  --ink-2:    #33454A;   /* body copy */
  --ink-3:    #5A6C72;   /* meta — 5.35:1 on --bg, 4.88:1 on --sand (AA) */
  --sand:     #F5F1EA;
  --sand-2:   #EBE5DA;
  --bg:       #FCFCFB;
  --line:     #E2DDD3;
  --line-2:   #D3CCBF;

  /* accent — used sparingly */
  --brass:    #9A6A28;

  /* type — Manrope for body/UI (warm humanist sans), Fraunces for display and
     pull-quotes. Variable fonts on both axes; opsz on Fraunces renders soft
     at display sizes. */
  --sans:    'Manrope', 'Segoe UI', -apple-system, system-ui, Roboto, sans-serif;
  --serif:   'Newsreader', 'Iowan Old Style', 'Palatino Linotype', 'Book Antiqua',
             Palatino, ui-serif, Georgia, serif;
  --display: var(--serif);

  /* spacing scale (4/8 rhythm) */
  --sp-1: .25rem;  --sp-2: .5rem;   --sp-3: .75rem;  --sp-4: 1rem;
  --sp-5: 1.5rem;  --sp-6: 2rem;    --sp-7: 3rem;    --sp-8: 4rem;
  --sp-9: 6rem;

  --wrap: 1200px;
  --wrap-narrow: 760px;
  --gutter: clamp(1.25rem, 5vw, 3rem);
  --section: clamp(3rem, 6.5vw, 6rem);
  --header-h: 76px;

  --r-sm: 6px;
  --r-md: 12px;
  --r-lg: 20px;

  /* Elevation ladder — layered, physically plausible shadows. Each rung pairs
     a tight contact shadow (ambient) with a softer diffuse one (directional). */
  --shadow-xs: 0 1px 2px rgba(16,26,29,.04);
  --shadow-sm: 0 1px 2px rgba(16,26,29,.05), 0 2px 8px rgba(16,26,29,.04);
  --shadow-md: 0 1px 3px rgba(16,26,29,.06), 0 8px 24px rgba(16,26,29,.08);
  --shadow-lg: 0 2px 4px rgba(16,26,29,.06), 0 16px 40px rgba(16,26,29,.11);
  --shadow-xl: 0 4px 8px rgba(16,26,29,.06), 0 28px 64px rgba(16,26,29,.14);
  /* Inner highlight — the subtle top-edge sheen used on premium cards. */
  --highlight-inner: inset 0 1px 0 rgba(255,255,255,.7);

  --ease: cubic-bezier(.22, 1, .36, 1);
  --dur: 240ms;

  /* z-scale */
  --z-header: 100;
  --z-drawer: 200;
  --z-skip:   300;
}

/* ---------- reset ---------- */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 6rem;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink-2);
  font-family: var(--sans);
  font-size: 1.0625rem;          /* 17px */
  line-height: 1.7;
  font-synthesis: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
  /* Kill the default gray tap-highlight iOS Safari draws on every touch — a
   custom :active/:focus already covers feedback and it clashes with the
   subtle-teal aesthetic. */
  -webkit-tap-highlight-color: transparent;
}

/* Safe-area top inset for notched phones — pushes the header down under
   the notch/dynamic island. Requires `viewport-fit=cover` in the meta
   viewport tag, which every page already has. Left/right insets are handled
   on .wrap so every content column adapts too. */
.header__inner { padding-top: env(safe-area-inset-top); }

img, picture, svg { display: block; max-width: 100%; }
img { height: auto; }
svg { flex: none; }

button, input, textarea, select { font: inherit; color: inherit; }

h1, h2, h3, h4 {
  margin: 0;
  color: var(--ink);
  font-family: var(--sans);
  font-weight: 700;
  line-height: 1.12;
  letter-spacing: -.025em;
  text-wrap: balance;
}
/* Editorial serif reserved for display sizes only. H3/H4 stay Manrope so card
   titles, form labels and interior headings keep their tight, functional feel.
   Newsreader has lower stroke contrast than Fraunces — needs slightly more
   weight (600 → 550 range) to feel confident without turning bold. */
h1, h2, .display, .h2, .pagehead .display {
  font-family: var(--display);
  font-weight: 550;
  font-optical-sizing: auto;
  font-variation-settings: 'opsz' 60;
  letter-spacing: -.015em;
}

p { margin: 0; text-wrap: pretty; }

a { color: inherit; }

::selection { background: var(--teal-100); color: var(--teal-900); }

:focus-visible {
  outline: 3px solid var(--teal-600);
  outline-offset: 3px;
  border-radius: 2px;
}

/* ---------- layout primitives ---------- */

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  /* max() with env() covers notched iPhones in landscape — safe-area insets
     kick in when the notch is on the side and eat into the normal gutter. */
  padding-left: max(var(--gutter), env(safe-area-inset-left));
  padding-right: max(var(--gutter), env(safe-area-inset-right));
}
.wrap--narrow { max-width: var(--wrap-narrow); }

.section { padding-block: var(--section); }
.section--sand { background: var(--sand); }
.section--tight { padding-block: clamp(2.25rem, 4.5vw, 3.75rem); }

.stack > * + * { margin-top: var(--sp-4); }
.stack-lg > * + * { margin-top: var(--sp-6); }

/* ---------- type utilities ---------- */

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: .6em;
  font-family: var(--sans);
  font-size: .75rem;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--teal-700);
  margin: 0 0 var(--sp-4);
}
/* Small hairline mark flanking the eyebrow — a subtle editorial cue that
   reads 'section' without shouting. Left-aligned eyebrows show only the
   leading rule; centered eyebrows (hero, centered blocks) mirror it on the
   right so the wordmark sits symmetric between two hairlines. */
.eyebrow::before,
.hero .eyebrow::after,
[style*="text-align:center"] .eyebrow::after {
  content: '';
  width: 1.75em;
  height: 1px;
  background: currentColor;
  opacity: .5;
}
.hero .eyebrow,
[style*="text-align:center"] .eyebrow { justify-content: center; }
.section--teal .eyebrow,
.hero--teal .eyebrow { color: var(--teal-100); }

.display {
  font-size: clamp(1.95rem, 5.6vw, 4.15rem);
  line-height: 1.05;
  letter-spacing: -.022em;
  overflow-wrap: break-word;              /* long Spanish words like
                                             "encontrado" shouldn't punch
                                             past the container on 375px */
}
.h2 {
  font-size: clamp(1.55rem, 3.1vw, 2.5rem);
  line-height: 1.15;
  letter-spacing: -.02em;
  overflow-wrap: break-word;
}
/* H3/H4 stay Inter — tight, functional, for card titles and interior headings */
.h3 { font-family: var(--sans); font-size: clamp(1.1rem, 1.5vw, 1.3rem);
  line-height: 1.3; letter-spacing: -.018em; font-weight: 650; }

.lead {
  font-size: clamp(1.075rem, 1.5vw, 1.3rem);
  line-height: 1.6;
  color: var(--ink-2);
  max-width: 60ch;
}
.prose { max-width: 68ch; }
.prose p + p { margin-top: var(--sp-4); }
.prose ol, .prose ul { max-width: 66ch; padding-left: 1.25em; margin: var(--sp-4) 0; }
.prose li + li { margin-top: .35em; }
.muted { color: var(--ink-3); }
.small { font-size: .9375rem; }

.verse {
  position: relative;
  isolation: isolate;
  margin: var(--sp-6) 0;
  padding: var(--sp-2) 0 var(--sp-2) var(--sp-5);
  border-left: 2px solid var(--teal-600);
  font-family: var(--serif);
  font-optical-sizing: auto;
  font-variation-settings: 'opsz' 36;
  font-style: italic;
  font-size: clamp(1.15rem, 1.9vw, 1.5rem);
  line-height: 1.5;
  font-weight: 450;
  letter-spacing: -.005em;
  color: var(--ink);
  transition: border-left-color 800ms cubic-bezier(.4, 0, .5, 1);
}
/* Localized warm-yellow bloom sitting to the LEFT of the bar. The pseudo's
   right edge is flush with the bar and its width sits entirely outside the
   verse box, so nothing bleeds into the text area on the right.

   Uses a LINEAR gradient (horizontal fade only) so the brightness is even
   along the entire bar height — as if the bar were a uniform light strip,
   not a point-source glow. A vertical mask softens the top/bottom edges so
   nothing terminates in a hard rectangle. */
.verse::before {
  content: '';
  position: absolute;
  z-index: -1;
  top: -24px;
  bottom: -24px;
  left: -110px;
  width: 110px;
  background: linear-gradient(
    to left,
    rgba(255, 240, 160, .55) 0%,
    rgba(255, 230, 130, .35) 25%,
    rgba(255, 220, 110, .16) 55%,
    rgba(255, 215, 100, .05) 80%,
    transparent 100%
  );
  -webkit-mask-image: linear-gradient(
    to bottom,
    transparent 0%,
    black 25%,
    black 75%,
    transparent 100%
  );
          mask-image: linear-gradient(
    to bottom,
    transparent 0%,
    black 25%,
    black 75%,
    transparent 100%
  );
  opacity: 0;
  pointer-events: none;
  transition: opacity 1200ms cubic-bezier(.4, 0, .5, 1);
}
.verse:hover { border-left-color: #EFC847; }
.verse:hover::before { opacity: 1; }

/* A .verse with data-reveal picks up the reveal-on transitions (opacity /
   transform / filter) which override our transition property. Restate the
   full list here so border-left-color can also animate on hover. Selector
   includes .reveal-on to raise specificity above .reveal-on [data-reveal]. */
.reveal-on .verse[data-reveal],
.verse[data-reveal] {
  transition:
    opacity 900ms cubic-bezier(.22, 1, .36, 1),
    transform 900ms cubic-bezier(.22, 1, .36, 1),
    filter 900ms cubic-bezier(.22, 1, .36, 1),
    border-left-color 800ms cubic-bezier(.4, 0, .5, 1);
}
/* Inside .verse-block the card owns the glow — don't stack two halos. */
.verse-block .verse,
.verse-block .verse:hover { border-left-color: var(--teal-600); }
.verse-block .verse::before { display: none; }
.verse cite { display: block; margin-top: var(--sp-3); font-family: var(--sans);
  font-size: .875rem; font-style: normal; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-3); }

/* ---------- buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: .55em;
  min-height: 48px;
  padding: .75rem 1.6rem;
  border: 1px solid transparent;
  border-radius: 999px;
  /* Serif CTAs — matches the display headings, gives buttons a
     distinctive editorial voice instead of the default modern-sans look.
     Small opsz keeps stroke contrast low at button sizes. */
  font-family: var(--serif);
  font-optical-sizing: auto;
  font-variation-settings: 'opsz' 8;
  font-size: 1rem;
  font-weight: 550;
  letter-spacing: -.005em;
  text-decoration: none;
  white-space: nowrap;                 /* never break a CTA across lines */
  cursor: pointer;
  transition: background-color var(--dur) var(--ease),
              color var(--dur) var(--ease),
              border-color var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}
.btn svg { width: 1.05em; height: 1.05em; transition: transform var(--dur) var(--ease); }
.btn:hover svg { transform: translateX(3px); }
.btn:active { transform: translateY(1px); }

.btn--primary { background: var(--teal-700); color: #fff; }
.btn--primary:hover { background: var(--teal-800); }

.btn--ghost { background: transparent; color: var(--ink); border-color: var(--line-2); }
.btn--ghost:hover { border-color: var(--ink); background: rgba(16,26,29,.03); }

.btn--light { background: #fff; color: var(--teal-900); }
.btn--light:hover { background: var(--teal-50); }

/* .65 not .45 — the border is a UI boundary and needs 3:1 against the hero
   photo behind it (WCAG 1.4.11). At .45 it measured 2.72:1. */
.btn--outline-light { background: transparent; color: #fff; border-color: rgba(255,255,255,.65); }
.btn--outline-light:hover { border-color: #fff; background: rgba(255,255,255,.1); }

/* Hero button hover glow — soft warm halo, no tight rim, gradual fade so it
   reads as a bloom rather than a state flip. Longer duration than the base
   button transition to make the glow the last thing to arrive. */
.hero .btn {
  transition: background-color var(--dur) var(--ease),
              color var(--dur) var(--ease),
              border-color var(--dur) var(--ease),
              transform var(--dur) var(--ease),
              box-shadow 1000ms cubic-bezier(.4, 0, .5, 1);
}
.hero .btn:hover {
  box-shadow:
    0 10px 40px rgba(255, 205, 150, .13),
    0 0 70px rgba(255, 240, 220, .16);
}

.btn-row { display: flex; flex-wrap: wrap; gap: var(--sp-3); }

/* text link with animated underline */
.link {
  display: inline-flex;
  align-items: center;
  gap: .4em;
  color: var(--teal-700);
  font-weight: 600;
  text-decoration: none;
  background-image: linear-gradient(currentColor, currentColor);
  background-size: 0% 1.5px;
  background-position: 0 100%;
  background-repeat: no-repeat;
  transition: background-size var(--dur) var(--ease);
  padding-bottom: 2px;
}
.link:hover, .link:focus-visible { background-size: 100% 1.5px; }
.link svg { width: 1em; height: 1em; }

/* Standalone links get a full 44px touch target. Links sitting inline inside a
   sentence keep their natural height — enlarging those would break the text
   baseline, and WCAG 2.5.8 exempts inline links for exactly that reason. */
.timecard .link, .card__foot .link { min-height: 44px; }
.give a { display: inline-flex; align-items: center; min-height: 44px; }

/* ---------- header ---------- */

.header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  background: rgba(252,252,251,.72);
  backdrop-filter: saturate(180%) blur(18px);
  -webkit-backdrop-filter: saturate(180%) blur(18px);
  border-bottom: 1px solid transparent;
  transition: border-color 320ms var(--ease), background-color 320ms var(--ease);
}
/* Once scrolled past the fold, the header condenses: tighter row, smaller mark,
   solid line under it. Animated via CSS custom properties so a single class
   toggle drives every dimension. */
.header.is-stuck {
  border-bottom-color: var(--line);
  background: rgba(252,252,251,.94);
  --header-h: 62px;
}
.header.is-stuck .brand img { width: 32px; height: 32px; }
.header.is-stuck .brand__sub { opacity: .7; }

.header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-5);
  min-height: var(--header-h);
  transition: min-height 320ms var(--ease);
}

.brand { display: flex; align-items: center; gap: .7rem; text-decoration: none; min-height: 44px; }
.brand img { width: 40px; height: 40px; object-fit: contain;
  transition: width 320ms var(--ease), height 320ms var(--ease); }
.brand__sub { transition: opacity 320ms var(--ease); }
.brand__text { display: flex; flex-direction: column; line-height: 1.1; }
/* Newsreader (site serif) at header-brand size — matches the section H2s
   and gives the wordmark editorial character instead of the default sans.
   Uppercase-only glyphs sit in the top half of their line box, so flex
   centering makes them read as too high next to the logo. Nudge down with
   translateY to align the optical center of the letters with the mark. */
.brand__name {
  font-family: var(--serif);
  font-variation-settings: 'opsz' 20;
  font-weight: 600;
  font-size: 1.2rem;
  line-height: 1;
  color: var(--ink);
  letter-spacing: -.005em;
  transform: translateY(3px);
}
.brand__sub { font-size: .6875rem; letter-spacing: .13em; text-transform: uppercase;
  color: var(--ink-3); }

.nav { display: flex; align-items: center; gap: var(--sp-1); }
.nav a {
  position: relative;
  padding: .55rem .7rem;
  font-size: .9375rem;
  font-weight: 500;
  color: var(--ink-2);
  text-decoration: none;
  border-radius: var(--r-sm);
  white-space: nowrap;                 /* two-word links must stay on one line */
  transition: color var(--dur) var(--ease);
}
.nav a::after {
  content: '';
  position: absolute;
  left: .7rem; right: .7rem; bottom: .28rem;
  height: 1.5px;
  background: var(--teal-700);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur) var(--ease);
}
.nav a:hover { color: var(--ink); }
.nav a:hover::after { transform: scaleX(1); }
.nav a[aria-current="page"] { color: var(--teal-700); font-weight: 600; }
.nav a[aria-current="page"]::after { transform: scaleX(1); }

/* The header CTA is a compact version of the site's primary button. It sits
   inside the sticky bar, so it uses less padding + a smaller type size than
   in-content buttons — otherwise it dominates the row and crowds the edge. */
.header__cta {
  margin-left: var(--sp-3);
  min-height: 40px;
  /* Uneven top/bottom padding compensates for serif letters sitting high in
     their line-box (cap-height + ascenders own the top of the em, descenders
     are unused in "Planifica tu visita"). Total vertical padding stays the
     same so the button height doesn't change. */
  padding: .65rem 1.1rem .35rem;
  font-size: .875rem;
  line-height: 1;
  font-variation-settings: 'opsz' 8;
}
/* the CTA inside .nav is for the mobile drawer only — on desktop .header__cta
   is the one shown, so hide this copy to avoid a duplicate button */
.nav > .btn { display: none; }

.burger {
  display: none;
  align-items: center;
  justify-content: center;
  width: 48px; height: 48px;
  margin-right: -.5rem;
  background: none;
  border: 0;
  border-radius: var(--r-sm);
  cursor: pointer;
  color: var(--ink);
}
.burger svg { width: 24px; height: 24px; }
.burger .icon-close { display: none; }
.burger[aria-expanded="true"] .icon-open { display: none; }
.burger[aria-expanded="true"] .icon-close { display: block; }

/* Mobile drawer. Breakpoint is 1100px because the full desktop nav (8 links +
   CTA) measures ~1052px of content — below that it would overflow the viewport. */
@media (max-width: 1100px) {
  .burger { display: flex; }
  .header__cta { display: none; }
  .nav > .btn { display: inline-flex; }
  .nav {
    position: fixed;
    /* Anchor to the bottom of the actual header (which grows by safe-area on
       notched phones and shrinks to 62px when scrolled). Hardcoded 76px left
       a visible gap between the header row and the drawer's first item. */
    top: calc(var(--header-h) + env(safe-area-inset-top));
    right: 0;
    left: 0;
    z-index: var(--z-drawer);
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: var(--sp-4) var(--gutter) var(--sp-7);
    background: var(--bg);
    border-bottom: 1px solid var(--line);
    box-shadow: var(--shadow-md);
    transform: translateY(-12px);
    opacity: 0;
    visibility: hidden;
    transition: transform var(--dur) var(--ease), opacity var(--dur) var(--ease),
                visibility var(--dur), top var(--dur) var(--ease);
    max-height: calc(100dvh - var(--header-h) - env(safe-area-inset-top));
    overflow-y: auto;
    overscroll-behavior: contain;
  }
  .nav.is-open { transform: translateY(0); opacity: 1; visibility: visible; }
  .nav a { padding: .9rem .25rem; font-size: 1.0625rem; border-bottom: 1px solid var(--line); }
  .nav a::after { display: none; }
  /* CTA inside the drawer — the base .nav a rule sets color: var(--ink-2)
     with specificity 0,1,1 which was beating .btn--primary's color:#fff.
     Re-declare white here with matching specificity so it wins by source
     order. Also drop the border-bottom that .nav a picks up. */
  .nav .btn {
    margin-top: var(--sp-5);
    justify-content: center;
    border-bottom: 0;
  }
  .nav a.btn--primary { color: #fff; }
  .nav a.btn--primary:hover { color: #fff; }
}

/* ---------- hero (full-bleed blurred photo) ---------- */

.hero {
  position: relative;
  display: grid;
  align-items: center;
  overflow: hidden;
  text-align: center;
  color: #fff;
  padding-block: clamp(3.5rem, 9vw, 6rem);
  /* fill what's left of the viewport under the sticky header.
     svh keeps mobile browser chrome from causing a jump; vh is the fallback. */
  min-height: calc(100vh - var(--header-h));
  min-height: calc(100svh - var(--header-h));
}
.hero__bg { position: absolute; inset: 0; isolation: isolate; }
/* <picture> is inline by default and auto-sizes to its image, so the img
   inside couldn't resolve height:100% — it was rendering at natural size
   (only ~40% of the hero on mobile). Positioning picture to fill hero__bg
   gives it explicit dimensions so the img fills the rest. */
.hero__bg > picture {
  position: absolute;
  inset: 0;
  display: block;
}
/* Ken Burns: 32s ease-in-out drift, alternating. Starts slightly zoomed so the
   scale-up doesn't reveal cropped edges. GPU-only transform, no layout thrash. */
.hero__bg img {
  width: 100%; height: 100%; object-fit: cover;
  transform: scale(1.06);
  animation: kenburns 32s ease-in-out infinite alternate;
  will-change: transform;
}
@keyframes kenburns {
  from { transform: scale(1.06) translate3d(-1%, -0.5%, 0); }
  to   { transform: scale(1.14) translate3d( 1.5%, 0.8%, 0); }
}
/* Two-layer scrim: gradient for legibility + fine grain for filmic warmth.
   Grain is an inline SVG data URI (~1KB), no request. Blend-mode 'overlay'
   gives the photo texture without darkening it further. */
.hero__bg::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 0.35 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)' opacity='0.9'/></svg>");
  background-size: 200px 200px;
  mix-blend-mode: overlay;
  opacity: .22;
  pointer-events: none;
  z-index: 1;
}
.hero__bg::after {
  content: '';
  position: absolute;
  inset: 0;
  /* Two layers: a punchy linear scrim for legibility across the whole hero,
     then a subtle radial darkening at the edges for vignette. */
  background:
    linear-gradient(180deg, rgba(6,38,45,.55) 0%, rgba(6,38,45,.65) 45%, rgba(6,38,45,.82) 100%),
    radial-gradient(ellipse at 50% 50%, transparent 40%, rgba(6,38,45,.35) 100%);
  z-index: 2;
}
.hero__content { position: relative; z-index: 1; }
.hero h1 { color: #fff; }
.hero .eyebrow { color: rgba(255,255,255,.82); }
.hero .lead { color: rgba(255,255,255,.9); margin-inline: auto; max-width: 46ch; }
.hero .display { margin-bottom: var(--sp-5); }
.hero .lead + .btn-row { margin-top: var(--sp-6); }
.hero .btn-row { justify-content: center; }
/* Hero owns its own display scale — larger than the interior page-head display
   because it's the front-door moment. Spacing between title and buttons is
   set explicitly here so the layout works with or without a lead paragraph.
   Uses Fraunces (not the site-wide Newsreader) — the extra stroke contrast
   feels right on a single confident line, even if it's too much at page H2s. */
.hero .display {
  font-family: 'Fraunces', var(--serif);
  font-variation-settings: 'opsz' 96, 'SOFT' 30;
  font-weight: 600;
  /* Mobile floor is 2rem (32px) so five-word titles wrap to 2–3 lines instead
     of dominating the whole screen on 375px. Scales up smoothly to the
     original 5.25rem on desktop. */
  font-size: clamp(2rem, 6.5vw, 5.25rem);
  letter-spacing: -.025em;
  overflow-wrap: break-word;
  margin-bottom: 0;
  /* Two matched shadow layers — both states declare the same count and blur
     radii, only opacities change. That's what lets the browser interpolate
     smoothly instead of snapping (text-shadows with different layer counts
     can't animate between each other). No tight core, so the light diffuses
     into a soft cloud instead of tracing each letter. Hover triggers on the
     title itself, not the whole hero. */
  text-shadow:
    0 0 70px rgba(255, 240, 220, .09),
    0 0 130px rgba(255, 205, 150, 0);
  transition: text-shadow 1400ms cubic-bezier(.4, 0, .5, 1);
}
.hero .display:hover {
  text-shadow:
    0 0 70px rgba(255, 240, 220, .22),
    0 0 130px rgba(255, 205, 150, .14);
}
.hero .display + .btn-row { margin-top: var(--sp-7); }
.hero .eyebrow { margin-bottom: var(--sp-5); }

/* interior page header — a tinted band, so pages don't open on empty white */
.pagehead {
  background: var(--sand);
  border-bottom: 1px solid var(--sand-2);
  padding-block: clamp(2rem, 4vw, 3.25rem);
}
.pagehead .display { font-size: clamp(2rem, 4.4vw, 3.1rem); }
.pagehead .lead { margin-top: var(--sp-4); }

/* ---------- service times strip ---------- */

.times {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  gap: var(--sp-5);
}
.timecard {
  position: relative;
  padding: var(--sp-6);
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-xs), var(--highlight-inner);
  transition: border-color 360ms var(--ease), box-shadow 360ms var(--ease),
              transform 360ms var(--ease);
}
/* Accent bar at the top of each card — brass hairline that keeps the sand
   background from washing them out. Draws in on hover. */
.timecard::before {
  content: '';
  position: absolute;
  top: 0; left: var(--r-lg); right: var(--r-lg);
  height: 2px;
  background: linear-gradient(90deg, var(--teal-700), var(--teal-600));
  border-radius: 0 0 2px 2px;
  transform: scaleX(.2);
  transform-origin: left;
  transition: transform 500ms var(--ease);
}
.timecard:hover {
  border-color: var(--teal-100);
  box-shadow: var(--shadow-lg), var(--highlight-inner);
  transform: translateY(-4px);
}
.timecard:hover::before { transform: scaleX(1); }
.section--sand .timecard { background: #fff; border-color: var(--sand-2); }
.timecard__label { display: flex; align-items: center; gap: .5rem; margin-bottom: var(--sp-3);
  font-size: .75rem; font-weight: 600; letter-spacing: .14em; text-transform: uppercase;
  color: var(--teal-700); }
.timecard__label svg { width: 15px; height: 15px; }
.timecard h3 { margin-bottom: var(--sp-2); }
.timecard__time { font-family: var(--sans); font-size: 1.4rem; font-weight: 650;
  letter-spacing: -.02em; color: var(--ink); margin-bottom: var(--sp-3);
  font-variant-numeric: tabular-nums; }
.timecard address { font-style: normal; color: var(--ink-3); font-size: .9375rem;
  margin-bottom: var(--sp-4); }

/* ---------- photo strip ---------- */

.strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  gap: var(--sp-4);
}
.strip figure { position: relative; margin: 0; overflow: hidden;
  border-radius: var(--r-lg); background: var(--sand-2);
  box-shadow: var(--shadow-sm);
  transition: transform 500ms var(--ease), box-shadow 500ms var(--ease); }
.strip img { width: 100%; aspect-ratio: 4/5; object-fit: cover;
  transition: transform 1200ms var(--ease); }
/* Gradient wash for depth — invisible until hover, then rises from the bottom. */
.strip figure::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(180deg, transparent 55%, rgba(7,47,55,.45) 100%);
  opacity: 0;
  transition: opacity 500ms var(--ease);
  pointer-events: none;
}
.strip figure:hover { transform: translateY(-6px); box-shadow: var(--shadow-lg); }
.strip figure:hover img { transform: scale(1.06); }
.strip figure:hover::after { opacity: 1; }
.strip figure:nth-child(2) img { aspect-ratio: 4/5; }

@media (min-width: 900px) {
  .strip { grid-template-columns: 1.1fr .9fr 1.1fr; align-items: end; }
  .strip figure:nth-child(2) img { aspect-ratio: 3/4; }
}

/* ---------- split rows ---------- */

.split {
  display: grid;
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: center;
}
@media (min-width: 900px) {
  .split { grid-template-columns: 1fr 1fr; }
  .split--wide-text { grid-template-columns: 1.15fr .85fr; }
  .split--flip > *:first-child { order: 2; }
}
.split figure {
  margin: 0; overflow: hidden;
  border-radius: var(--r-lg); background: var(--sand-2);
  box-shadow: var(--shadow-md);
  transition: transform 500ms var(--ease), box-shadow 500ms var(--ease);
}
.split figure img { width: 100%; aspect-ratio: 4/5; object-fit: cover;
  transition: transform 1200ms var(--ease); }
.split figure:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); }
.split figure:hover img { transform: scale(1.04); }

/* ---------- cards ---------- */

.grid {
  display: grid;
  gap: var(--sp-5);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
}
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 380px), 1fr)); }
.grid--4 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr)); }

.card {
  display: flex;
  flex-direction: column;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  text-decoration: none;
  box-shadow: var(--shadow-xs);
  transition: border-color 360ms var(--ease), box-shadow 360ms var(--ease),
              transform 360ms var(--ease);
}
.section--sand .card { border-color: var(--sand-2); }
.card:hover {
  border-color: var(--teal-100);
  box-shadow: var(--shadow-lg);
  transform: translateY(-4px);
}

.card__media { overflow: hidden; background: var(--sand-2); }
.card__media img { width: 100%; aspect-ratio: 3/2; object-fit: cover;
  transition: transform 900ms var(--ease); }
.card:hover .card__media img { transform: scale(1.06); }

.card__body { padding: var(--sp-5); display: flex; flex-direction: column; gap: var(--sp-3); flex: 1; }
.card__body h3 { color: var(--ink); }
.card__body p { color: var(--ink-2); font-size: .9688rem; line-height: 1.65; }
.card__foot { margin-top: auto; padding-top: var(--sp-2); }

/* value cards (sembrar/crecer/servir) */
.value { text-align: left; }
.value__media img { aspect-ratio: 1/1; object-fit: contain; background: var(--sand); padding: var(--sp-5); }

/* people */
.person .card__media img { aspect-ratio: 1/1; object-position: top center; }
.person__role { font-size: .75rem; font-weight: 600; letter-spacing: .13em;
  text-transform: uppercase; color: var(--teal-700); }
.person__contact { display: flex; flex-direction: column; gap: .35rem; margin-top: auto;
  padding-top: var(--sp-4); border-top: 1px solid var(--line); font-size: .875rem; }
.person__contact a { display: inline-flex; align-items: center; gap: .5rem;
  color: var(--ink-3); text-decoration: none; word-break: break-word;
  transition: color var(--dur) var(--ease); min-height: 44px; }
.person__contact a:hover { color: var(--teal-700); }
.person__contact svg { width: 15px; height: 15px; flex: none; }

/* featured pastor block */
.featured { display: grid; gap: clamp(1.5rem, 4vw, 3rem); align-items: center; }
@media (min-width: 800px) { .featured { grid-template-columns: minmax(0, 320px) 1fr; } }
.featured figure { margin: 0; border-radius: var(--r-md); overflow: hidden; background: var(--sand-2); }
.featured figure img { width: 100%; aspect-ratio: 4/5; object-fit: cover; object-position: top center; }

/* ---------- accordion ---------- */

.acc { border-top: 1px solid var(--line); }
.acc details { border-bottom: 1px solid var(--line); }
.acc summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: var(--sp-5) 0;
  min-height: 56px;
  cursor: pointer;
  list-style: none;
  font-family: var(--serif);
  font-optical-sizing: auto;
  font-variation-settings: 'opsz' 24;
  font-size: clamp(1.15rem, 1.6vw, 1.35rem);
  font-weight: 550;
  letter-spacing: -.01em;
  color: var(--ink);
  transition: color var(--dur) var(--ease);
}
.acc summary::-webkit-details-marker { display: none; }
.acc summary:hover { color: var(--teal-700); }
.acc__icon { flex: none; width: 22px; height: 22px; color: var(--teal-700);
  transition: transform var(--dur) var(--ease); }
.acc details[open] .acc__icon { transform: rotate(45deg); }
.acc__body { padding-bottom: var(--sp-6); max-width: 70ch; }
.acc__body p { color: var(--ink-2); }
.acc__body p + p { margin-top: var(--sp-4); }

/* ---------- schedule ----------
   Rows read like a curated table on desktop and stack into card blocks on
   mobile. A soft hover highlight (teal wash + brass accent) turns the whole
   thing into a scannable weekly rhythm without new markup. */

.sched { border-top: 1px solid var(--line); }
/* Day grouping — each group opens with a serif day heading anchored by a
   short brass rule. Rows inside drop their leftmost day cell to breathe. */
.sched__group + .sched__group { margin-top: var(--sp-6); }
.sched__group-title {
  display: flex;
  align-items: baseline;
  gap: var(--sp-4);
  padding: var(--sp-5) 0 var(--sp-3);
  font-family: var(--serif);
  font-optical-sizing: auto;
  font-variation-settings: 'opsz' 36;
  font-size: clamp(1.6rem, 2.4vw, 2rem);
  font-weight: 550;
  letter-spacing: -.015em;
  color: var(--ink);
}
.sched__group-title::after {
  content: '';
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, var(--line-2), transparent);
  align-self: center;
}
/* Rows inside a group don't need the day cell — the heading owns it. */
.sched__group .sched__row { grid-template-columns: 1fr; }
@media (min-width: 720px) {
  .sched__group .sched__row { grid-template-columns: 9rem 1fr auto; }
}

/* Optional intro note under a day heading — used when several events in the
   group share the same qualifier (e.g. "all around 6-7pm, contact to confirm"). */
.sched__group-note {
  margin: 0 0 var(--sp-3);
  padding: var(--sp-2) 0;
  max-width: 60ch;
  font-size: .95rem;
  color: var(--ink-3);
  font-style: italic;
}

/* Links inside a where-cell — inherit the muted meta color, gain a subtle
   teal underline instead of the default browser blue. Padding on Y extends
   the tap target beyond the 24px line-box (WCAG 2.5.8 exempts inline links,
   but a bit more room on mobile still helps mis-taps). */
.sched__where a {
  color: inherit;
  text-decoration: none;
  background-image: linear-gradient(var(--teal-600), var(--teal-600));
  background-size: 100% 1px;
  background-position: 0 100%;
  background-repeat: no-repeat;
  padding: 6px 0 3px;
  transition: color var(--dur) var(--ease), background-size var(--dur) var(--ease);
}
.sched__where a:hover {
  color: var(--teal-700);
  background-size: 100% 1.5px;
}
.sched__row {
  position: relative;
  display: grid;
  gap: var(--sp-1) var(--sp-5);
  grid-template-columns: 1fr;
  padding: var(--sp-5) var(--sp-4);
  margin-inline: calc(var(--sp-4) * -1);
  border-bottom: 1px solid var(--line);
  border-radius: var(--r-md);
  transition: background-color 260ms var(--ease);
}
.sched__row::before {
  content: '';
  position: absolute;
  left: 0; top: 25%; bottom: 25%;
  width: 2px;
  background: var(--teal-700);
  border-radius: 0 2px 2px 0;
  transform: scaleY(0);
  transform-origin: center;
  transition: transform 320ms var(--ease);
}
.sched__row:hover { background: rgba(15,85,96,.035); }
.sched__row:hover::before { transform: scaleY(1); }
@media (min-width: 720px) {
  .sched__row { grid-template-columns: 8.5rem 9rem 1fr auto; align-items: baseline; }
}
.sched__day {
  font-family: var(--sans);
  font-weight: 700;
  color: var(--ink);
  font-size: .95rem;
  letter-spacing: .01em;
}
.sched__time {
  color: var(--teal-700);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  font-feature-settings: 'ss01';
}
.sched__what { color: var(--ink); font-weight: 500; }
.sched__where {
  color: var(--ink-3);
  font-size: .85rem;
  display: inline-flex;
  align-items: center;
  gap: .35em;
}
.sched__where::before {
  content: '';
  width: 4px; height: 4px;
  border-radius: 50%;
  background: var(--teal-600);
  opacity: .6;
}

/* ---------- values triptych ----------
   Editorial numbered rows for a set of three (or four) core values. Reads
   like a magazine spread: big Fraunces Roman numeral in brass, Fraunces
   headline, Manrope description. Brass hairline between rows animates
   from left on scroll into view. No images — the type does the work. */

.values-list {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--sand-2);
}
.section--sand .values-list { border-top-color: var(--line-2); }

.value-row {
  position: relative;
  display: grid;
  gap: var(--sp-5) var(--sp-7);
  grid-template-columns: 1fr;
  padding-block: var(--sp-7);
  border-bottom: 1px solid var(--sand-2);
  transition: background-color 360ms var(--ease);
}
.section--sand .value-row { border-bottom-color: var(--line-2); }

@media (min-width: 720px) {
  .value-row {
    grid-template-columns: minmax(120px, 180px) 1fr minmax(128px, 160px);
    align-items: center;
    padding-block: var(--sp-8);
  }
}

/* Brass accent bar that draws across from left when the row scrolls in. */
.value-row::before {
  content: '';
  position: absolute;
  left: 0; top: 0;
  width: 100%;
  max-width: 80px;
  height: 2px;
  background: linear-gradient(90deg, var(--brass), rgba(154,106,40,.15));
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 800ms var(--ease) 200ms, max-width 800ms var(--ease);
}
.reveal-on .value-row.is-in::before,
.value-row:hover::before { transform: scaleX(1); }
.value-row:hover::before { max-width: 100%; }
.value-row:hover { background: rgba(154,106,40,.03); }

.value-row__num {
  font-family: var(--serif);
  font-optical-sizing: auto;
  font-variation-settings: 'opsz' 72;
  /* Numeral floor is 3.2rem (~51px) so it stays visually strong on 375px
     without dwarfing the actual title/description beside it. */
  font-size: clamp(3.2rem, 9vw, 7.5rem);
  line-height: .85;
  font-weight: 450;
  letter-spacing: -.03em;
  color: var(--brass);
  opacity: .9;
}

.value-row__body { max-width: 52ch; }
.value-row__title {
  font-family: var(--serif);
  font-optical-sizing: auto;
  font-variation-settings: 'opsz' 48;
  font-size: clamp(1.65rem, 3.6vw, 2.75rem);
  line-height: 1.1;
  font-weight: 550;
  letter-spacing: -.015em;
  color: var(--ink);
  margin: 0 0 var(--sp-3);
}
.value-row__desc {
  font-size: clamp(1rem, 1.35vw, 1.15rem);
  line-height: 1.6;
  color: var(--ink-2);
  margin: 0;
}
.value-row__icon {
  width: 36px;
  height: 36px;
  color: var(--teal-700);
  opacity: .7;
  transition: opacity 360ms var(--ease), transform 500ms var(--ease);
}
.value-row:hover .value-row__icon { opacity: 1; transform: translateX(4px); }
@media (max-width: 719px) {
  .value-row__icon { display: none; }
}

/* Poster thumbnail — the church's own SEMBRANDO/Creciendo/SIRVIENDO
   illustrations, framed as a small vertical card so their loud typography
   sits inside the row's rhythm rather than fighting the editorial layout. */
.value-row__poster {
  width: 128px;
  aspect-ratio: 3/4;
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--bg);
  box-shadow: var(--shadow-sm);
  border: 1px solid var(--sand-2);
  transition: transform 500ms var(--ease), box-shadow 500ms var(--ease);
}
.value-row__poster img { width: 100%; height: 100%; object-fit: cover;
  object-position: top center; transition: transform 800ms var(--ease); }
.value-row:hover .value-row__poster { transform: translateY(-3px); box-shadow: var(--shadow-md); }
.value-row:hover .value-row__poster img { transform: scale(1.04); }
@media (max-width: 719px) {
  .value-row__poster { width: 88px; align-self: start; }
}

/* ---------- video facade ----------
   Lazy YouTube embed. First paint is a static thumbnail with a play button;
   only when the visitor clicks does the JS swap in the iframe. Keeps the
   site free of third-party requests until interaction — and out of every
   visitor's YouTube tracking footprint. */

.video-facade {
  position: relative;
  aspect-ratio: 16 / 9;
  width: 100%;
  max-width: 960px;
  margin: 0 auto;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: #0a1a1e;
  box-shadow: var(--shadow-md);
  cursor: pointer;
  transition: transform 500ms var(--ease), box-shadow 500ms var(--ease);
}
.video-facade:hover { transform: translateY(-3px); box-shadow: var(--shadow-lg); }
.video-facade img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform 900ms var(--ease), filter 500ms var(--ease);
}
.video-facade:hover img { transform: scale(1.03); filter: brightness(.85); }

/* Play button — glassy pill in warm-white centered on the thumb.
   Uses backdrop-filter so it picks up the image behind it. */
.video-facade__play {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  display: grid;
  place-items: center;
  width: clamp(64px, 8vw, 92px);
  aspect-ratio: 1 / 1;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, .92);
  color: var(--teal-900);
  box-shadow: 0 8px 24px rgba(0,0,0,.25), 0 0 0 8px rgba(255,255,255,.12);
  cursor: pointer;
  transition: transform 500ms var(--ease),
              background-color 300ms var(--ease),
              box-shadow 500ms var(--ease);
}
.video-facade__play svg {
  width: 40%; height: 40%;
  margin-left: 8%;                    /* nudge the play triangle visually centered */
}
.video-facade:hover .video-facade__play {
  transform: translate(-50%, -50%) scale(1.08);
  box-shadow: 0 12px 32px rgba(0,0,0,.3),
              0 0 0 14px rgba(255,255,255,.18),
              0 0 60px rgba(255, 220, 130, .35);
}

/* Once activated, JS swaps in an iframe that fills the same box. */
.video-facade iframe {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  border: 0;
}

/* ---------- verse callout ----------
   Pull-quote panel used on the home page. Full-width band, editorial layout.
   Serif italic already inherited from .verse — this positions and dresses it. */

.verse-block {
  position: relative;
  padding: clamp(var(--sp-6), 8vw, var(--sp-8)) clamp(var(--sp-5), 6vw, var(--sp-6));
  text-align: center;
  background: var(--sand);
  border-radius: var(--r-lg);
  overflow: hidden;
  /* Baseline matches hover shape so the transition can interpolate. Layers
     invisible until hover; alpha and vertical offset animate. */
  box-shadow:
    0 12px 0 rgba(210, 140, 60, 0),
    0 0 80px rgba(240, 170, 80, 0),
    0 0 160px rgba(220, 150, 70, 0);
  transition: box-shadow 1200ms cubic-bezier(.4, 0, .5, 1),
              transform 700ms cubic-bezier(.4, 0, .5, 1);
}
/* Warm brass-amber bloom on hover — warmer and more present than the hero
   glow. Three-layer halo: a close directional drop (adds lift), a mid
   amber ring, and a wide diffuse spread that washes the surrounding white
   with warmth. Gradual 1.2s ease keeps it from feeling like a light-switch. */
.verse-block:hover {
  transform: translateY(-3px);
  box-shadow:
    0 18px 40px rgba(210, 140, 60, .22),
    0 0 90px rgba(240, 170, 80, .38),
    0 0 180px rgba(220, 150, 70, .22);
}
.verse-block::before {
  content: '“';
  position: absolute;
  top: -.35em; left: 50%;
  transform: translateX(-50%);
  font-family: var(--serif);
  font-size: clamp(9rem, 18vw, 15rem);
  line-height: 1;
  color: var(--teal-700);
  opacity: .08;
  pointer-events: none;
  user-select: none;
}
.verse-block .verse {
  position: relative;
  margin: 0 auto;
  padding: 0;
  border: 0;
  max-width: 44ch;
  font-size: clamp(1.35rem, 2.4vw, 1.85rem);
  line-height: 1.4;
}
.verse-block .verse cite {
  margin-top: var(--sp-5);
  color: var(--teal-700);
  font-weight: 600;
  letter-spacing: .12em;
}

/* ---------- giving ---------- */

.give {
  padding: var(--sp-6);
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-xs);
  display: flex; flex-direction: column; gap: var(--sp-3);
  transition: border-color 360ms var(--ease), box-shadow 360ms var(--ease),
              transform 360ms var(--ease);
}
.section--sand .give { border-color: var(--sand-2); }
.give:hover { border-color: var(--teal-100); box-shadow: var(--shadow-md); transform: translateY(-2px); }
.give__icon { width: 40px; height: 40px; display: grid; place-items: center;
  border-radius: 50%; background: var(--teal-50); color: var(--teal-700);
  margin-bottom: var(--sp-2); }
.give__icon svg { width: 20px; height: 20px; }
.give a { color: var(--teal-700); text-decoration: none; font-weight: 500; }
.give a:hover { text-decoration: underline; }

/* ---------- form ---------- */

.form { max-width: 640px; }
.form__row { display: grid; gap: var(--sp-4); grid-template-columns: 1fr 1fr; }
@media (max-width: 600px) { .form__row { grid-template-columns: 1fr; } }
.field { display: flex; flex-direction: column; gap: .4rem; margin-bottom: var(--sp-4); }
.field label { font-size: .875rem; font-weight: 600; color: var(--ink); }
.field .req { color: var(--brass); }
.field input, .field textarea {
  width: 100%;
  min-height: 48px;
  padding: .8rem 1rem;
  font-size: 1rem;                 /* >=16px: prevents iOS zoom-on-focus */
  color: var(--ink);
  background: #fff;
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.field textarea { min-height: 140px; resize: vertical; line-height: 1.6; }
.field input:hover, .field textarea:hover { border-color: var(--ink-3); }
.field input:focus, .field textarea:focus {
  outline: none;
  border-color: var(--teal-700);
  box-shadow: 0 0 0 3px rgba(15,85,96,.14);
}
.field input[aria-invalid="true"], .field textarea[aria-invalid="true"] { border-color: #A32017; }
.field__error { font-size: .8125rem; color: #A32017; min-height: 1.2em; }
.form__status { margin-top: var(--sp-4); font-size: .9375rem; display: flex;
  align-items: flex-start; gap: .5rem; }
.form__status svg { width: 18px; height: 18px; margin-top: .2em; }
.form__status.is-ok  { color: #14624A; }
.form__status.is-err { color: #A32017; }

/* ---------- CTA band ---------- */

.cta-band { background: var(--teal-800); color: rgba(255,255,255,.82); }
.cta-band h2 { color: #fff; }
.cta-band .lead { color: rgba(255,255,255,.8); }

/* ---------- footer ---------- */

.footer { background: var(--teal-900); color: rgba(255,255,255,.72); padding-block: var(--sp-8) var(--sp-6); }
/* styled as a small label, but an <h2> so the heading order never skips a level */
.footer__h { color: #fff; font-family: var(--sans); font-size: .75rem; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase; margin-bottom: var(--sp-4);
  line-height: 1.4; }
.footer__cols { display: grid; gap: var(--sp-7);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); }
.footer__brand { display: flex; align-items: center; gap: .8rem; margin-bottom: var(--sp-4); }
.footer__brand img { width: 44px; height: 44px; object-fit: contain;
  background: #fff; border-radius: 8px; padding: 4px; }
/* Two-line brand text: ICCH mark + tagline, stacked with tight rhythm.
   Previous markup wrapped both in nested <span>s with default line-height,
   which left a visible vertical gap between the lines. */
.footer__brand-text { display: flex; flex-direction: column; line-height: 1.2; }
.footer__brand-text strong { color: #fff; font-family: var(--serif);
  font-variation-settings: 'opsz' 20; font-size: 1.1rem; font-weight: 600;
  letter-spacing: -.005em; }
.footer__brand-text span { color: rgba(255,255,255,.72); font-size: .78rem;
  letter-spacing: .04em; margin-top: 2px; }
.footer ul { list-style: none; margin: 0; padding: 0; }
.footer li + li { margin-top: .2rem; }
.footer a { color: rgba(255,255,255,.78); text-decoration: none;
  transition: color var(--dur) var(--ease); }
/* standalone footer links get a full touch target */
.footer li > a { display: inline-flex; align-items: center; min-height: 44px; }
.footer a:hover { color: #fff; }
.footer address { font-style: normal; }
.footer__social { display: flex; gap: var(--sp-3); }
.footer__social a { display: grid; place-items: center; width: 44px; height: 44px;
  border: 1px solid rgba(255,255,255,.2); border-radius: 50%;
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease); }
.footer__social a:hover { background: rgba(255,255,255,.1); border-color: rgba(255,255,255,.45); }
.footer__social svg { width: 19px; height: 19px; }
.footer__legal { margin-top: var(--sp-8); padding-top: var(--sp-5);
  border-top: 1px solid rgba(255,255,255,.14); font-size: .8125rem;
  display: flex; flex-wrap: wrap; gap: var(--sp-4); justify-content: space-between;
  color: rgba(255,255,255,.6); }

/* ---------- skip link ---------- */

.skip {
  position: fixed; top: 0; left: 0; z-index: var(--z-skip);
  padding: .85rem 1.35rem; background: var(--teal-800); color: #fff;
  font-weight: 600; text-decoration: none;
  transform: translateY(-120%);
  transition: transform 180ms var(--ease);
}
.skip:focus { transform: translateY(0); }

/* visually hidden, still announced — used for section headings the design
   doesn't show but the heading outline needs */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---------- scroll reveal ----------
   Fail-safe by design: content is visible by default. The hidden state only
   exists while <html> carries .reveal-on, which JS adds *after* confirming
   IntersectionObserver support — and removes again if reveals stop working.
   If CSS loads but JS dies, nothing is ever stuck invisible. */

.reveal-on [data-reveal] {
  opacity: 0;
  transform: translate3d(0, 22px, 0) scale(.985);
  transition: opacity 900ms var(--ease), transform 900ms var(--ease),
              filter 900ms var(--ease);
  transition-delay: var(--reveal-delay, 0ms);
  will-change: opacity, transform;
  filter: blur(2px);
}
.reveal-on [data-reveal].is-in {
  opacity: 1;
  transform: none;
  filter: blur(0);
}
/* Mobile: drop the blur layer. Filter animation on 10+ elements per screen
   drains frame rate on lower-end phone GPUs; the fade+translate reveal still
   reads clearly without it. */
@media (max-width: 720px) {
  .reveal-on [data-reveal] { filter: none; }
}
/* Hero word-by-word stagger. JS splits the hero h1 into <span class="word">;
   the parent h1 skips the shell reveal (opacity/transform/filter go direct to
   their end state) but keeps its text-shadow transition alive for the hover
   glow — a blanket transition:none here was killing that.

   Perf notes:
   - Force the h1 into a single compositing layer with translateZ(0) so the
     text-shadow bloom doesn't have to be recomputed against 5+ per-word
     layers every animation frame.
   - Drop `will-change` from the words themselves — one layer per word plus
     a parent shadow layer was the choppiness. The h1 owns one layer now.
   - Smaller translate distance (18% not 40%) and slightly shorter duration
     mean less repaint area per frame and a tighter overall timing window. */
.reveal-on .hero .display[data-reveal] {
  opacity: 1;
  transform: translateZ(0);
  filter: none;
  transition: text-shadow 1400ms cubic-bezier(.4, 0, .5, 1);
}
.reveal-on .hero .display .word {
  display: inline-block;
  opacity: 0;
  transform: translate3d(0, 18%, 0);
  transition: opacity 550ms cubic-bezier(.22, 1, .36, 1),
              transform 550ms cubic-bezier(.22, 1, .36, 1);
  transition-delay: calc(var(--word-i, 0) * 45ms + var(--reveal-delay, 0ms));
}
.reveal-on .hero .display.is-in .word { opacity: 1; transform: none; }
/* keep a space between spans so word wraps behave naturally */
.hero .display .word + .word { margin-left: .28em; }

/* ---------- cross-document view transitions ----------
   Progressive enhancement: browsers that support cross-document view
   transitions (Chrome 126+) do a soft cross-fade between pages instead of
   flashing white. Everything else ignores this block. */

@view-transition { navigation: auto; }

::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 300ms;
  animation-timing-function: cubic-bezier(.22, 1, .36, 1);
}
::view-transition-old(root) { animation-name: vt-fade-out; }
::view-transition-new(root) { animation-name: vt-fade-in; }
@keyframes vt-fade-out { to { opacity: 0; transform: translateY(-6px); } }
@keyframes vt-fade-in  { from { opacity: 0; transform: translateY(6px); } }

/* Persist and cross-fade the header + footer across navigations. */
.header { view-transition-name: site-header; }
.footer { view-transition-name: site-footer; }

@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
}

/* ---------- reduced motion ---------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  .reveal-on [data-reveal],
  .reveal-on .hero .display .word {
    opacity: 1 !important; transform: none !important; filter: none !important;
  }
  .hero__bg img { animation: none !important; transform: scale(1.06) !important; }
  .strip img, .card__media img { transition: none !important; }
  .strip figure:hover img, .card:hover .card__media img { transform: none !important; }
}

/* ---------- print ---------- */

@media print {
  .header, .footer, .skip, .cta-band { display: none; }
  body { color: #000; background: #fff; }
  .reveal-on [data-reveal] { opacity: 1 !important; transform: none !important; }
}
