/* ==========================================================================
   Christ the Healer International Missions Movement
   Shared design system. Palette derived from the ministry's own logo.
   Fourth Ground Consulting, July 2026.
   ========================================================================== */

/* --- 1. Tokens ----------------------------------------------------------- */
:root {
  /* Blues, sampled from the globe in the CTHIMM mark */
  --blue:        #0C6CB4;
  --blue-mid:    #1E7ABF;
  --blue-deep:   #0A5292;
  --indigo:      #243C78;
  --sky:         #A8C4E3;

  /* Dark grounds */
  --navy:        #0A2138;
  --navy-soft:   #123050;
  --ink:         #071829;
  /* One step below the footer, for the maintainer credit plate under it. */
  --ink-deep:    #040F1B;

  /* Gold, sampled from the cross and the Bible edge. Used as light, never as surface. */
  --gold:        #F09018;
  --gold-bright: #FBBA60;
  --ember:       #F05424;

  /* Warm grounds. Never pure white. */
  --parchment:   #FBF8F2;
  --parchment-2: #F5F0E6;
  --parchment-3: #EFE8DA;

  /* Text. Never pure black. */
  --text:        #1A1F26;
  --text-soft:   #3D4653;
  --text-muted:  #5A6472;
  --on-dark:     #F3F1EA;
  --on-dark-mut: rgba(243, 241, 234, .68);

  /* Lines */
  --rule:        rgba(26, 31, 38, .10);
  --rule-soft:   rgba(26, 31, 38, .06);
  --rule-dark:   rgba(243, 241, 234, .14);

  /* Type */
  /* EB Garamond is a revival of a sixteenth century type, chosen for the
     ecclesiastical weight it carries without costume drama. It is also the
     natural setting for scripture and for the Hebrew feast names. Public Sans
     underneath is a plain civic sans, deliberately opinion-free. */
  --display: "EB Garamond", "Iowan Old Style", Georgia, serif;
  --body:    "Public Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;

  /* Motion */
  --enter: cubic-bezier(.16, 1, .3, 1);
  --react: cubic-bezier(.23, 1, .32, 1);

  /* Rhythm */
  --pad:   clamp(1.25rem, 5vw, 3rem);
  --band:  clamp(4.5rem, 10vw, 8.5rem);
  --max:   1240px;
  --measure: 62ch;
}

/* --- 2. Reset ------------------------------------------------------------ */
*, *::before, *::after { box-sizing: border-box; }
/* scroll-padding-top, not a per-element scroll-margin. The header is fixed and up
   to 82px tall, so every in-page anchor on this site was landing underneath it:
   #schedule, #locations, #leadership, the ministry cards, the pastor cards. One
   rule on the scroll container covers all of them, including hash navigation from
   another page. */
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; scroll-padding-top: clamp(84px, 11vw, 112px); }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--parchment);
  color: var(--text);
  font-family: var(--body);
  font-weight: 400;
  font-size: clamp(1rem, .28vw + .95rem, 1.075rem);
  line-height: 1.75;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

img, svg, video { display: block; max-width: 100%; height: auto; }
button { font: inherit; color: inherit; cursor: pointer; }
::selection { background: rgba(12, 108, 180, .18); }

h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 600;
  line-height: 1.14;
  /* Garamond is already tight and has a small x-height. Fraunces wanted -.015em
     to stop its wide forms drifting apart; the same value here closes the
     counters up and the headline starts to look crowded. */
  letter-spacing: -.005em;
  margin: 0 0 .6em;
  text-wrap: balance;
}
p { margin: 0 0 1.15em; }
p:last-child { margin-bottom: 0; }

a { color: var(--blue); text-decoration-color: rgba(12,108,180,.32); text-underline-offset: .18em; }
a:hover { color: var(--blue-deep); text-decoration-color: currentColor; }

:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 3px;
  border-radius: 3px;
}

.skip {
  position: absolute; left: .75rem; top: -3rem; z-index: 200;
  background: var(--navy); color: var(--on-dark);
  padding: .6rem 1rem; border-radius: .6rem; font-size: .85rem;
  transition: transform .25s var(--react);
}
.skip:focus { top: .75rem; }
.vh {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* --- 3. Layout ----------------------------------------------------------- */
.wrap { width: 100%; max-width: var(--max); margin-inline: auto; padding-inline: var(--pad); }
.wrap--tight { max-width: 880px; }
.band { padding-block: var(--band); }
.band--half { padding-block: calc(var(--band) * .62); }
.measure { max-width: var(--measure); }

.band--dark { background: var(--navy); color: var(--on-dark); }
.band--dark h1, .band--dark h2, .band--dark h3 { color: var(--on-dark); }
.band--dark p { color: var(--on-dark-mut); }
.band--dark a { color: var(--gold-bright); }
/* `.band--dark a` (0,1,1) outranks `.btn` (0,1,0), which would paint a gold pill's
   label gold on gold. Buttons keep their own foreground token. */
.band--dark a.btn, .band--ink a.btn { color: var(--btn-fg); }
.band--ink  { background: var(--ink); color: var(--on-dark); }
.band--warm { background: var(--parchment-2); }

/* --- 4. Type utilities --------------------------------------------------- */
.overline {
  display: flex; align-items: center; gap: .7rem;
  font-family: var(--body);
  font-size: clamp(.62rem, .18vw + .58rem, .7rem);
  font-weight: 700; letter-spacing: .3em; text-transform: uppercase;
  color: var(--gold); margin: 0 0 1.4rem;
}
.overline::after {
  content: ""; flex: 0 0 clamp(28px, 6vw, 56px); height: 1px;
  background: linear-gradient(90deg, var(--gold), transparent);
}
.overline--center { justify-content: center; }
.overline--center::before {
  content: ""; flex: 0 0 clamp(28px, 6vw, 56px); height: 1px;
  background: linear-gradient(270deg, var(--gold), transparent);
}
.band--dark .overline { color: var(--gold-bright); }

h1.hero-title { font-size: clamp(2.5rem, 6.4vw, 5.2rem); font-weight: 500; line-height: 1.05; letter-spacing: -.005em; }
.h2 { font-size: clamp(1.85rem, 3.6vw, 3.05rem); }
.h3 { font-size: clamp(1.3rem, 1.8vw, 1.6rem); }
.lede {
  font-size: clamp(1.08rem, .55vw + .98rem, 1.3rem);
  line-height: 1.68; color: var(--text-soft); font-weight: 400;
}
.band--dark .lede { color: var(--on-dark-mut); }
.italic-accent { font-family: var(--display); font-style: italic; font-weight: 400; }
.center { text-align: center; }
.center .overline { justify-content: center; }

/* --- 5. Meridian arc motif ---------------------------------------------- */
/* A single line of longitude, lifted from the globe in their mark. */
.arc {
  width: clamp(90px, 16vw, 160px); height: 20px; margin: 0 0 1.6rem;
  overflow: visible;
}
.arc path { fill: none; stroke: var(--gold); stroke-width: 1.4; stroke-linecap: round; }
.arc--center { margin-inline: auto; }
.band--dark .arc path { stroke: var(--gold-bright); }

.rule-arc {
  display: block; width: 100%; height: 34px; margin: 0; overflow: visible;
}
.rule-arc path { fill: none; stroke: var(--rule); stroke-width: 1; }

/* --- 6. Buttons --------------------------------------------------------- */
.btn {
  --btn-bg: var(--blue);
  --btn-fg: #fff;
  display: inline-flex; align-items: center; gap: .62rem;
  background: var(--btn-bg); color: var(--btn-fg);
  font-family: var(--body); font-size: clamp(.68rem, .14vw + .65rem, .74rem);
  font-weight: 700; letter-spacing: .2em; text-transform: uppercase;
  padding: 1.02rem 2.1rem; border: 0; border-radius: 999px;
  text-decoration: none; text-align: center; max-width: 100%;
  box-shadow: 0 8px 26px rgba(12, 108, 180, .22);
  transition: transform .4s var(--react), box-shadow .4s var(--react), background-color .3s var(--react);
}
.btn:hover {
  color: var(--btn-fg); background: var(--blue-deep);
  transform: translateY(-2px);
  box-shadow: 0 14px 34px rgba(12, 108, 180, .3);
}
.btn:active { transform: translateY(0); }
.btn svg { flex: 0 0 auto; transition: transform .4s var(--react); }
.btn:hover svg { transform: translateX(4px); }

.btn--ghost {
  --btn-bg: transparent; --btn-fg: var(--text);
  border: 1.4px solid var(--rule); box-shadow: none;
}
.btn--ghost:hover {
  --btn-fg: var(--blue); background: transparent;
  border-color: rgba(12,108,180,.4); box-shadow: 0 10px 26px rgba(12,108,180,.08);
}
.btn--onDark {
  --btn-bg: transparent; --btn-fg: var(--on-dark);
  border: 1.4px solid var(--rule-dark); box-shadow: none;
}
.btn--onDark:hover {
  --btn-fg: var(--ink); background: var(--on-dark); border-color: var(--on-dark);
}
.btn--gold { --btn-bg: var(--gold); --btn-fg: var(--ink); box-shadow: 0 8px 26px rgba(240,144,24,.26); }
.btn--gold:hover { background: var(--gold-bright); box-shadow: 0 14px 34px rgba(240,144,24,.34); }

.cta-row { display: flex; flex-wrap: wrap; gap: .85rem; align-items: center; }
.trust {
  font-size: .8rem; line-height: 1.6; color: var(--text-muted); margin: 1.15rem 0 0;
}
.band--dark .trust { color: rgba(243,241,234,.5); }

/* --- 7. Header ---------------------------------------------------------- */
.hdr {
  position: fixed; inset: 0 0 auto; z-index: 100;
  background: rgba(251, 248, 242, .9);
  backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
  border-bottom: 1px solid var(--rule-soft);
  transition: box-shadow .4s var(--react), background-color .4s var(--react);
}
.hdr.is-scrolled { box-shadow: 0 2px 24px rgba(10, 33, 56, .06); }

/* Over a dark hero the header rides transparent, then settles into parchment on scroll. */
body.dark-hero .hdr:not(.is-scrolled):not(.is-open) {
  background: linear-gradient(180deg, rgba(7,24,41,.5), transparent);
  backdrop-filter: none; -webkit-backdrop-filter: none;
  border-bottom-color: transparent;
}
body.dark-hero .hdr:not(.is-scrolled):not(.is-open) .brand__a { color: #fff; }
body.dark-hero .hdr:not(.is-scrolled):not(.is-open) .brand__b { color: rgba(255,255,255,.62); }
body.dark-hero .hdr:not(.is-scrolled):not(.is-open) .nav > a { color: rgba(255,255,255,.82); }
body.dark-hero .hdr:not(.is-scrolled):not(.is-open) .nav > a:hover,
body.dark-hero .hdr:not(.is-scrolled):not(.is-open) .nav > a[aria-current="page"] { color: #fff; }
body.dark-hero .hdr:not(.is-scrolled):not(.is-open) .burger { border-color: rgba(255,255,255,.34); }
body.dark-hero .hdr:not(.is-scrolled):not(.is-open) .burger span,
body.dark-hero .hdr:not(.is-scrolled):not(.is-open) .burger span::before,
body.dark-hero .hdr:not(.is-scrolled):not(.is-open) .burger span::after { background: #fff; }
.hdr__in {
  display: flex; align-items: center; gap: 1rem;
  min-height: clamp(62px, 7vw, 82px);
  width: 100%; max-width: var(--max); margin-inline: auto; padding-inline: var(--pad);
}
.brand { display: flex; align-items: center; gap: .7rem; text-decoration: none; margin-right: auto; min-width: 0; }
/* Sized by height, not width. A landscape mark set to a fixed width sits short
   next to a two-line wordmark and the baselines stop agreeing. */
.brand img { height: clamp(29px, 3.5vw, 39px); width: auto; }
.brand__txt { display: flex; flex-direction: column; line-height: 1.14; }
.brand__a {
  font-family: var(--display); font-weight: 700;
  font-size: clamp(.8rem, .5vw + .72rem, 1.05rem);
  text-transform: uppercase; letter-spacing: .06em;
  color: var(--navy); white-space: nowrap;
}
.brand__b {
  font-size: clamp(.44rem, .2vw + .4rem, .58rem); font-weight: 600;
  letter-spacing: clamp(.07em, .045vw, .16em); text-transform: uppercase; color: var(--text-muted);
  white-space: nowrap;
}

.nav { display: flex; align-items: center; gap: clamp(.6rem, 1.4vw, 1.55rem); }
.nav a {
  font-size: .84rem; font-weight: 500; color: var(--text-soft);
  text-decoration: none; padding: .3rem 0; position: relative;
  transition: color .3s var(--react);
}
.nav a::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -2px; height: 1.5px;
  background: var(--gold); transform: scaleX(0); transform-origin: left;
  transition: transform .4s var(--enter);
}
.nav a:hover { color: var(--navy); }
.nav a:hover::after, .nav a[aria-current="page"]::after { transform: scaleX(1); }
.nav a[aria-current="page"] { color: var(--navy); font-weight: 600; }
.hdr .btn { padding: .78rem 1.5rem; box-shadow: 0 6px 18px rgba(12,108,180,.2); }

.burger {
  display: none; width: 42px; height: 42px; border: 1px solid var(--rule);
  border-radius: 50%; background: transparent; align-items: center; justify-content: center;
}
.burger span {
  display: block; width: 17px; height: 1.5px; background: var(--navy); position: relative;
  transition: transform .35s var(--react);
}
.burger span::before, .burger span::after {
  content: ""; position: absolute; left: 0; width: 17px; height: 1.5px; background: var(--navy);
  transition: transform .35s var(--react);
}
.burger span::before { top: -5.5px; } .burger span::after { top: 5.5px; }
.burger[aria-expanded="true"] span { transform: rotate(45deg); }
.burger[aria-expanded="true"] span::before { transform: translateY(5.5px) rotate(-90deg); }
.burger[aria-expanded="true"] span::after { transform: scaleX(0); }

@media (max-width: 940px) {
  .burger { display: flex; }
  .nav {
    position: fixed; inset: clamp(62px,7vw,82px) 0 auto; flex-direction: column;
    align-items: stretch; gap: 0; padding: .6rem var(--pad) 1.6rem;
    background: rgba(251,248,242,.98);
    backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
    border-bottom: 1px solid var(--rule);
    transform: translateY(-8px); opacity: 0; pointer-events: none;
    transition: transform .4s var(--enter), opacity .3s var(--enter);
    max-height: calc(100vh - 62px); overflow-y: auto;
  }
  .nav.is-open { transform: translateY(0); opacity: 1; pointer-events: auto; }
  .nav a { padding: .95rem 0; border-bottom: 1px solid var(--rule-soft); font-size: .98rem; }
  .nav a::after { display: none; }
  .nav .btn { margin-top: 1.1rem; justify-content: center; }
}

/* --- 8. Hero ------------------------------------------------------------ */
.hero {
  position: relative; isolation: isolate;
  min-height: min(92svh, 880px);
  display: flex; align-items: flex-end;
  padding: calc(clamp(62px,7vw,82px) + clamp(3rem,9vw,7rem)) 0 clamp(3rem, 7vw, 5.5rem);
  background: var(--ink); color: var(--on-dark); overflow: hidden;
}
.hero__media { position: absolute; inset: 0; z-index: -2; }
.hero__media img, .hero__media video {
  width: 100%; height: 100%; object-fit: cover; object-position: center 58%;
}
.hero__media video { opacity: 0; transition: opacity 1.4s var(--enter); }
.hero__media video.is-ready { opacity: 1; }
/* Text is never unprotected over imagery. */
.hero__scrim {
  position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(180deg, rgba(7,24,41,.62) 0%, rgba(7,24,41,.14) 30%, rgba(7,24,41,.52) 74%, rgba(7,24,41,.8) 100%),
    linear-gradient(96deg, rgba(7,24,41,.86) 0%, rgba(7,24,41,.4) 52%, rgba(7,24,41,.06) 100%);
}
.hero__in { position: relative; width: 100%; }

/* --- 8b. Centred, logo-led hero ---------------------------------------- */
/* The emblem is the anchor of the fold. Everything else stacks on its axis. */
.hero--center {
  align-items: center; text-align: center;
  min-height: min(100svh, 940px);
  padding-block: calc(clamp(62px, 7vw, 82px) + clamp(2.2rem, 5vw, 4rem)) clamp(2.4rem, 5vw, 4rem);
}
.hero--center .hero__scrim {
  background:
    radial-gradient(ellipse 80% 66% at 50% 48%, rgba(7,24,41,.64) 0%, rgba(7,24,41,.44) 48%, rgba(7,24,41,.22) 80%, transparent 100%),
    linear-gradient(180deg, rgba(7,24,41,.66) 0%, rgba(7,24,41,.2) 26%, rgba(7,24,41,.2) 62%, rgba(7,24,41,.82) 100%);
}
.hero--center .hero__in { display: flex; flex-direction: column; align-items: center; }

.lockup { display: flex; flex-direction: column; align-items: center; margin: 0; }
/* The ministry's own logo is landscape (1.23:1), so it is sized by width and
   given its aspect up front to hold the fold still while it loads. The wrapper
   carries the sizing because a <picture> is inline and would not take it. */
/* Height matters as much as width here. On a short laptop a mark sized off vw
   alone grows tall enough to push the two calls to action past the fold, so it
   also yields to available height. */
.lockup__pic {
  display: block;
  width: clamp(196px, min(24vw, 31svh), 318px);
  margin-bottom: clamp(1rem, 2vw, 1.7rem);
}
.lockup__mark {
  display: block; width: 100%; height: auto;
  aspect-ratio: 864 / 702;
  filter: drop-shadow(0 10px 34px rgba(0,0,0,.42));
}
.lockup__a {
  display: block;
  font-family: var(--display); font-weight: 700; font-style: normal;
  font-size: clamp(1.62rem, 4.4vw, 3.35rem); line-height: 1.04;
  /* Set as capitals, the way the ministry writes its own name. Caps need tracking
     opened up, not closed: the negative value that suits lowercase Garamond jams
     capitals into each other, because there are no descenders or x-height curves
     to hold them apart. */
  text-transform: uppercase; letter-spacing: .045em; color: #fff;
  text-shadow: 0 2px 22px rgba(7,24,41,.55);
}
.lockup__b {
  display: block; margin-top: clamp(.5rem, 1vw, .8rem);
  font-family: var(--body); font-weight: 700;
  font-size: clamp(.52rem, .55vw + .42rem, .76rem);
  letter-spacing: clamp(.2em, .5vw, .42em); text-transform: uppercase;
  color: var(--gold-bright);
  text-shadow: 0 1px 12px rgba(7,24,41,.6);
}
.lockup__rule {
  width: clamp(120px, 22vw, 240px); height: 18px;
  margin: clamp(1.2rem, 2.3vw, 1.8rem) auto clamp(1.1rem, 2.1vw, 1.6rem);
  overflow: visible;
}
.lockup__rule path { fill: none; stroke: rgba(251,186,96,.78); stroke-width: 1.5; stroke-linecap: round; }
.lockup__rule circle { fill: var(--gold-bright); }

.hero__line {
  font-family: var(--display); font-style: italic; font-weight: 400;
  font-size: clamp(1.28rem, 2.5vw, 2.05rem); line-height: 1.34;
  color: #fff; max-width: 24ch; margin: 0 auto;
  text-shadow: 0 2px 20px rgba(7,24,41,.6);
}

/* The ministry's own tagline, set the way their own site sets it: uppercase, with the
   second half in gold. Their treatment, our typeface. */
.hero__tag {
  font-family: var(--display); font-weight: 600;
  font-size: clamp(1.14rem, 2.35vw, 2.05rem); line-height: 1.28;
  letter-spacing: .055em; text-transform: uppercase;
  color: #fff; max-width: 36ch; margin: 0 auto;
  text-shadow: 0 2px 22px rgba(7,24,41,.62);
}
.hero__tag em {
  font-style: normal; font-weight: 600;
  color: var(--gold-bright);
  display: block;
}
@media (max-width: 560px) { .hero__tag { letter-spacing: .035em; max-width: 20ch; } }
.hero--center .lede {
  max-width: 56ch; margin: clamp(1.1rem, 2.2vw, 1.6rem) auto 0;
  color: rgba(255,255,255,.8); text-wrap: balance;
}
.cta-row--center { justify-content: center; }
.hero--center .cta-row { margin-top: clamp(1.7rem, 3.2vw, 2.5rem); }
.hero--center .scrollcue { justify-content: center; flex-direction: column; gap: .7rem; }
.hero--center .scrollcue i { width: 1px; height: 30px; }

/* The logo-led fold stacks eight layers: mark, wordmark, sub-wordmark, rule,
   tagline, lede, two buttons, scroll cue. A laptop gives about 800px of usable
   height, which is not enough for all of it at full size, and a half-cut button
   reads worse than either a whole one or none. So on a short desktop viewport
   the rhythm tightens instead of the invitation falling off the fold. */
@media (min-width: 817px) and (max-height: 900px) {
  .hero--center .lockup__a  { font-size: clamp(1.62rem, 3.5vw, 2.55rem); }
  .hero--center .hero__tag  { font-size: clamp(1.14rem, 2vw, 1.62rem); }
  .hero--center .lede       { font-size: .96rem; margin-top: 1rem; max-width: 58ch; }
  .hero--center .lockup__pic { margin-bottom: .75rem; }
  .hero--center .lockup__rule { margin-top: .85rem; margin-bottom: .85rem; }
  .hero--center .cta-row    { margin-top: 1.5rem; }
}

/* Shorter still. 1366x768 and 1280x800 are the two most common Windows laptop
   viewports here, and the scroll cue was landing 46px and 18px below the fold on
   them. Cutting one wrapped line out of the tagline and one out of the lede
   recovered 91px of that; this tier finds the rest in the gaps, so the fold ends
   where the page ends. Measured against the cue's bottom edge, not by eye. */
@media (min-width: 817px) and (max-height: 820px) {
  .hero--center { padding-bottom: clamp(1.3rem, 2.6vw, 2rem); }
  .hero--center .lockup__pic  { margin-bottom: .5rem; }
  .hero--center .lockup__rule { margin-top: .6rem; margin-bottom: .6rem; }
  .hero--center .cta-row      { margin-top: 1.15rem; }
  .hero--center .scrollcue    { margin-top: 1.3rem; gap: .5rem; }
  .hero--center .scrollcue i  { height: 22px; }
}

/* Over a logo-led hero the header brand is redundant, so it waits for the scroll. */
body.hero-lockup .hdr:not(.is-scrolled):not(.is-open) .brand {
  opacity: 0; transform: translateY(-6px); pointer-events: none;
}
.hdr .brand { transition: opacity .5s var(--enter), transform .5s var(--enter); }

/* --- 8c. Axial section intro ------------------------------------------- */
.intro { max-width: 660px; margin-inline: auto; text-align: center; }
.intro--wide { max-width: 820px; }
.intro .overline { justify-content: center; }
.intro .overline::before {
  content: ""; flex: 0 0 clamp(28px, 6vw, 56px); height: 1px;
  background: linear-gradient(270deg, var(--gold), transparent);
}
.band--dark .intro .overline::before { background: linear-gradient(270deg, var(--gold-bright), transparent); }
.intro .arc { margin-inline: auto; }
.intro .lede { margin-inline: auto; }
.after-intro { margin-top: clamp(2.4rem, 5vw, 3.8rem); }

/* Stats sitting on the same axis as the hero lockup. */

/* Two columns of left-aligned prose under a centred heading. Reads far better
   than long centred lines, and still holds the axis. */
/* One paragraph per column, deliberately, so the two blocks stay the same visual
   weight. CSS `columns` would reflow them into a lopsided pair. */
.prose-axial {
  max-width: 900px; margin-inline: auto;
  display: grid; grid-template-columns: 1fr 1fr; gap: clamp(1.6rem, 4vw, 3.2rem);
  color: var(--text-soft); text-align: left;
}
.prose-axial p { margin: 0; }
@media (max-width: 760px) { .prose-axial { grid-template-columns: 1fr; max-width: 60ch; } }

/* Where a gift goes: four items on one axis. */
.uses {
  list-style: none; margin: 0 auto; padding: 0; max-width: 1040px;
  display: grid; gap: clamp(1.6rem, 3vw, 2.4rem);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 210px), 1fr));
  text-align: center;
}
.uses li { display: flex; flex-direction: column; align-items: center; gap: .85rem; font-size: .96rem; line-height: 1.6; }
.uses svg {
  width: 38px; height: 38px; padding: 10px; border-radius: 50%;
  background: rgba(251,186,96,.1);
  fill: none; stroke: var(--gold-bright); stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round;
}
.uses span { max-width: 22ch; color: var(--on-dark-mut); }

.carousel__nav--center { justify-content: center; }

/* --- 20. Worship service schedule -------------------------------------- */
.sched__when {
  font-family: var(--body); font-size: clamp(.66rem, .2vw + .6rem, .76rem);
  font-weight: 700; letter-spacing: .2em; text-transform: uppercase;
  line-height: 2; color: var(--on-dark); margin: .4rem 0 0;
}
.sched__when time { color: var(--gold-bright); font-style: normal; }
/* Its own block, so the address can balance across two lines instead of dropping a
   single word onto the second. It was leaving "CITY" alone on a phone. The block is
   what makes the `<br>` unnecessary, which is why the markup no longer has one. */
.sched__when span {
  display: block; text-wrap: balance;
  color: var(--on-dark-mut); letter-spacing: .14em; font-weight: 600;
}

.sched {
  display: grid; gap: clamp(1.1rem, 2vw, 1.6rem);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 268px), 1fr));
}
/* Four cards need explicit columns. `auto-fit` fits three across from about 900px
   and strands the fourth alone on a second row, which reads as an afterthought
   rather than as the fourth service. Two by two through the middle range, capped so
   the cards do not stretch into letterboxes, then four across once there is room. */
@media (min-width: 620px) {
  .sched--four { grid-template-columns: repeat(2, minmax(0, 400px)); justify-content: center; }
}
@media (min-width: 1240px) {
  .sched--four { grid-template-columns: repeat(4, 1fr); justify-content: stretch; }
  /* The time stops growing with the viewport here, because the card does not. The
     base size is 1.5vw, but `.wrap` caps at 1240px, so above about 1336px the
     window keeps widening while the card stays at roughly 200px of content and the
     type runs out of room: measured, "11:05 AM to 12:20 PM" needed 250px inside 200
     at 1600 and wrapped, dropping that one card's Junior Church panel and roster
     half a line below the other three. Fixed at 1.2rem the longest line needs about
     170px, which also survives the font swap, where the Georgia fallback sets about
     8 per cent wider than EB Garamond and would otherwise wrap and then unwrap. */
  .sched--four .sched__time { font-size: 1.2rem; }
}
.sched__card {
  position: relative; overflow: hidden;
  background: rgba(255,255,255,.04);
  border: 1px solid var(--rule-dark);
  border-radius: 1.25rem;
  padding: clamp(1.5rem, 2.4vw, 2.1rem);
  text-align: center;
  transition: transform .55s var(--enter), border-color .45s var(--enter), background-color .45s var(--enter);
}
.sched__card::before {
  content: ""; position: absolute; inset: 0 0 auto; height: 2.5px;
  background: linear-gradient(90deg, var(--blue-mid), var(--gold));
  transform: scaleX(0); transform-origin: center;
  transition: transform .6s var(--enter);
}
.sched__card:hover { transform: translateY(-5px); border-color: rgba(251,186,96,.3); background: rgba(255,255,255,.06); }
.sched__card:hover::before { transform: scaleX(1); }

.sched__no {
  font-size: .64rem; font-weight: 700; letter-spacing: .26em; text-transform: uppercase;
  color: var(--gold-bright); margin: 0 0 1rem;
}
.sched__time {
  font-family: var(--display); font-weight: 500;
  font-size: clamp(1.18rem, 1.5vw, 1.5rem); line-height: 1.15;
  color: var(--on-dark); margin: 0 0 .3rem;
}
.sched__big { font-size: 1.5em; font-weight: 500; letter-spacing: 0; }
/* The end of the range never splits. "11:05 AM to 12:20 PM" is the one that has to
   wrap in a narrow card, and it should break after the start time, not mid-range. */
.sched__tail { white-space: nowrap; }
.sched__label {
  font-size: .7rem; font-weight: 600; letter-spacing: .18em; text-transform: uppercase;
  color: var(--on-dark-mut); margin: 0;
}
.sched__jr {
  margin: 1.3rem 0; padding: .9rem 1rem;
  border-radius: .75rem; background: rgba(12,108,180,.16);
  border: 1px solid rgba(143,190,230,.16);
}
.sched__jr-h {
  font-size: .6rem; font-weight: 700; letter-spacing: .22em; text-transform: uppercase;
  color: #8CBEE6; margin: 0 0 .25rem;
}
.sched__jr-t { font-size: .92rem; font-weight: 500; color: var(--on-dark); margin: 0; }
.sched__jr-a { font-size: .68rem; color: rgba(243,241,234,.5); margin: .28rem 0 0; }

.sched__serving {
  font-size: .58rem; font-weight: 700; letter-spacing: .26em; text-transform: uppercase;
  color: rgba(243,241,234,.45); margin: 0 0 .8rem;
  padding-top: 1.1rem; border-top: 1px solid var(--rule-dark);
}
.sched__pastors {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; justify-content: center; gap: .4rem .5rem;
}
.sched__pastors li {
  font-size: .82rem; line-height: 1.5; color: var(--on-dark-mut);
  padding: .18rem .6rem; border-radius: 999px;
  background: rgba(255,255,255,.05);
}
/* The roster is a weekly rota, so it carries the Sunday it belongs to. Without the
   date the page states one week's list as though it were permanent, and it is wrong
   by the following Sunday with nothing on the page to say so. */
.sched__roster {
  max-width: 62ch; margin: clamp(1.8rem,3.5vw,2.4rem) auto 0;
  text-align: center; font-size: .8rem; line-height: 1.7;
  color: rgba(243,241,234,.42);
}
/* Scoped to the left-aligned hero variant. `.hero h1 em` at (0,1,2) was outranking
   `.hero__tag em` at (0,1,1) and forcing the gold half of the tagline into italic. */
.hero:not(.hero--center) h1 { color: #fff; margin-bottom: .5em; max-width: 19ch; }
.hero:not(.hero--center) h1 em {
  font-style: italic; font-weight: 400;
  color: var(--gold-bright);
}
/* Colour only. The measure belongs to the variants, `.hero--center .lede` and
   `.hero--page .lede`, and both of those are declared elsewhere in this file.
   A `max-width` here sat at equal specificity but later in source order, so it
   quietly beat the centred hero's own 52ch and pinned it to 48ch. Two rules were
   dead because of it, including the short-desktop 58ch. Nothing looked broken,
   which is why it survived. */
.hero .lede { color: rgba(255,255,255,.82); }
.hero .overline { color: var(--gold-bright); }
.hero .cta-row { margin-top: clamp(1.6rem, 3vw, 2.4rem); }

.scrollcue {
  display: flex; align-items: center; gap: .55rem; margin-top: clamp(2.2rem, 4vw, 3.4rem);
  font-size: .62rem; font-weight: 700; letter-spacing: .28em; text-transform: uppercase;
  color: rgba(255,255,255,.62);
}
.scrollcue i {
  display: block; width: 1px; height: 34px;
  background: linear-gradient(180deg, var(--gold-bright), transparent);
  transform-origin: top; animation: cue 2.4s var(--enter) infinite;
}
@keyframes cue { 0%,100% { transform: scaleY(.4); opacity: .5 } 50% { transform: scaleY(1); opacity: 1 } }

/* --- 9. Stats ----------------------------------------------------------- */
.stats {
  display: grid; gap: clamp(2rem, 4vw, 3.4rem);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 190px), 1fr));
}

.stats--axial { text-align: center; }
.stats--axial .stat__l { max-width: 24ch; margin-inline: auto; }

/* Five figures, not four. `auto-fit` would fit as many as the width allows and then
   strand the remainder in a left-aligned row of one, which reads as a mistake.
   Flex with an explicit basis per band always leaves a centred final row: five, then
   three and two, then two two and one, then one. */
.stats--five {
  display: flex; flex-wrap: wrap; justify-content: center;
  column-gap: clamp(1.4rem, 3vw, 2.6rem); row-gap: clamp(2.2rem, 4vw, 3.2rem);
}
.stats--five > * { flex: 0 1 100%; }
@media (min-width: 480px)  { .stats--five > * { flex-basis: 44%; } }
@media (min-width: 760px)  { .stats--five > * { flex-basis: 29%; } }
@media (min-width: 1140px) { .stats--five > * { flex-basis: 16.5%; } }
/* "10,000" is six glyphs where "25" was two. At the four-up size a flex item's
   min-content is about 220px, wider than its 16.5% basis, and since flex items do
   not shrink below min-content the row silently broke 4+1 with the orphan hard left.
   The figure is sized down for this variant rather than the grid being fought. */
.stats--five .stat__n { font-size: clamp(2.15rem, 3.6vw, 3.4rem); }
.stats--five .stat__l { max-width: 22ch; }

/* The closing statement. Display italic for the mission line so it reads as the
   church speaking, plain body underneath so the claim is not dressed up. */
.stats__coda {
  /* Wide enough for the closing sentence to hold one line. It is 51.6ch set, and at
     46ch it broke across two, which halved the weight of the last thing on the
     section. Stated in ch rather than pixels so it keeps wrapping on a phone, where
     one line was never possible. The rule above the coda widens with it, which is
     right: it should be as wide as the widest line under it. */
  text-align: center; max-width: 58ch;
  margin: clamp(2.8rem, 6vw, 4.4rem) auto 0;
  padding-top: clamp(2rem, 4vw, 2.8rem);
  border-top: 1px solid var(--rule);
}
.band--dark .stats__coda, .band--ink .stats__coda { border-top-color: var(--rule-dark); }
.stats__mission {
  font-family: var(--display); font-style: italic; font-weight: 500;
  font-size: clamp(1.4rem, 2.6vw, 2.1rem); line-height: 1.3;
  color: var(--navy); margin: 0 0 .7rem;
}
.stats__line {
  font-size: clamp(1rem, .4vw + .92rem, 1.12rem);
  line-height: 1.65; color: var(--text-muted); margin: 0;
}

/* A qualifier, not a digit. Smaller, raised, and quieter than the figure, so the
   number still reads as the number and the plus reads as "at least". It sits in its
   own span so the count-up never has to parse around it. */
.stat__plus {
  font-size: .48em; vertical-align: .62em; margin-left: .04em;
  opacity: .5; letter-spacing: 0;
}
.stat__n {
  font-family: var(--display); font-weight: 500;
  font-size: clamp(2.9rem, 5.4vw, 4.6rem); line-height: 1;
  letter-spacing: -.004em; color: var(--navy); margin: 0 0 .35rem;
  font-variant-numeric: tabular-nums; font-feature-settings: "tnum" 1;
}
.band--dark .stat__n { color: var(--gold-bright); }
.stat__l {
  font-size: .95rem; line-height: 1.5; color: var(--text-muted); margin: 0;
  max-width: 22ch;
}
.band--dark .stat__l { color: var(--on-dark-mut); }
.stat__src { display: block; font-size: .74rem; color: var(--text-muted); opacity: .72; margin-top: .4rem; }

/* --- 10. Cards ---------------------------------------------------------- */
.grid { display: grid; gap: clamp(1.1rem, 2vw, 1.6rem); }
.grid--3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr)); }
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 360px), 1fr)); }

.card {
  position: relative; isolation: isolate; overflow: hidden;
  background: #fff; border: 1px solid var(--rule-soft);
  border-radius: 1.25rem; padding: clamp(1.5rem, 2.4vw, 2.1rem);
  text-decoration: none; color: inherit;
  transition: transform .55s var(--enter), box-shadow .55s var(--enter), border-color .45s var(--enter);
}
.card::before {
  content: ""; position: absolute; inset: 0 0 auto; height: 2.5px;
  background: linear-gradient(90deg, var(--blue), var(--gold));
  transform: scaleX(0); transform-origin: left;
  transition: transform .6s var(--enter);
}
a.card:hover, .card--lift:hover {
  transform: translateY(-5px);
  box-shadow: 0 24px 56px rgba(10, 33, 56, .09);
  border-color: rgba(12, 108, 180, .14);
}
a.card:hover::before, .card--lift:hover::before { transform: scaleX(1); }
.card h3 { font-size: clamp(1.14rem, 1.1vw, 1.32rem); margin-bottom: .5rem; color: var(--navy); }
.card p { font-size: .95rem; line-height: 1.68; color: var(--text-muted); }
.card__tag {
  display: inline-block; font-size: .62rem; font-weight: 700; letter-spacing: .2em;
  text-transform: uppercase; color: var(--blue); margin-bottom: .9rem;
}
.card__more {
  display: inline-flex; align-items: center; gap: .45rem; margin-top: 1.1rem;
  font-size: .68rem; font-weight: 700; letter-spacing: .2em; text-transform: uppercase;
  color: var(--blue);
}
.card__more svg { transition: transform .4s var(--react); }
a.card:hover .card__more svg { transform: translateX(4px); }
.band--dark .card {
  background: rgba(255,255,255,.035); border-color: var(--rule-dark);
}
.band--dark .card h3 { color: var(--on-dark); }
.band--dark .card p { color: var(--on-dark-mut); }
.band--dark .card__tag, .band--dark .card__more { color: var(--gold-bright); }
.band--dark a.card:hover { box-shadow: 0 24px 56px rgba(0,0,0,.28); border-color: rgba(251,186,96,.28); }

/* Icon wrap for stroke-based SVG icons */
.icon-wrap {
  width: 52px; height: 52px; border-radius: 50%;
  display: grid; place-items: center; margin-bottom: 1.15rem;
  background: rgba(12, 108, 180, .07);
}
.icon-wrap svg { width: 24px; height: 24px; fill: none; stroke: var(--blue); stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.icon-wrap--gold { background: rgba(240, 144, 24, .09); }
.icon-wrap--gold svg { stroke: var(--gold); }
.band--dark .icon-wrap { background: rgba(251,186,96,.1); }
.band--dark .icon-wrap svg { stroke: var(--gold-bright); }

/* --- 11. Figures and photography --------------------------------------- */
/* Consistent treatment: settled grayscale that warms to full colour. */
.photo { position: relative; overflow: hidden; border-radius: 1.25rem; background: var(--parchment-3); }
.photo img {
  width: 100%; height: 100%; object-fit: cover;
  filter: grayscale(.86) contrast(1.04) brightness(.98);
  transition: filter 1s var(--enter), transform 1.1s var(--enter);
}
.photo:hover img, .photo.is-live img { filter: grayscale(0) contrast(1.02); }
.photo--zoom:hover img { transform: scale(1.03); }
/* Edge-to-edge photographic band, used as a breath between sections. */
.photo-bleed { position: relative; overflow: hidden; margin: 0; }
.photo-bleed img {
  width: 100%; height: clamp(240px, 40vw, 540px); object-fit: cover;
  filter: grayscale(.82) contrast(1.05) brightness(.99);
  transition: filter 1.2s var(--enter), transform 1.4s var(--enter);
}
.photo-bleed:hover img, .photo-bleed.is-live img { filter: grayscale(0) contrast(1.02); }
.photo-bleed figcaption {
  position: absolute; inset: auto 0 0; padding: clamp(1.1rem, 3vw, 2.2rem);
  color: rgba(255,255,255,.86); font-size: clamp(.76rem, .3vw + .7rem, .88rem);
  background: linear-gradient(0deg, rgba(7,24,41,.84) 0%, rgba(7,24,41,.34) 55%, transparent 100%);
  text-align: center;
}
html.shot .photo-bleed img { filter: grayscale(.24) contrast(1.03); }

.photo--tall { aspect-ratio: 4 / 5; }
.photo--tall img { height: 100%; }
@media (max-width: 860px) { .photo--tall { aspect-ratio: 4 / 3; } }
.photo figcaption {
  font-size: .78rem; line-height: 1.6; color: var(--text-muted);
  padding: .75rem .1rem 0; margin: 0;
}
/* Any text sitting on a photo gets a gradient shield. */
.photo--captioned::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(0deg, rgba(7,24,41,.86) 0%, rgba(7,24,41,.34) 42%, transparent 76%);
}
.photo__over {
  position: absolute; inset: auto 0 0; z-index: 2;
  padding: clamp(1.1rem, 2.4vw, 1.9rem); color: #fff;
}
.photo__over h3 { color: #fff; margin-bottom: .3rem; }
.photo__over p { color: rgba(255,255,255,.78); font-size: .92rem; margin: 0; }

.split {
  display: grid; gap: clamp(2rem, 5vw, 4.5rem); align-items: center;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr));
}
.split--wide-l { grid-template-columns: 1.15fr 1fr; }
.split--wide-r { grid-template-columns: 1fr 1.15fr; }
@media (max-width: 860px) {
  .split--wide-l, .split--wide-r { grid-template-columns: 1fr; }
  .split--flip > *:first-child { order: 2; }
}

/* --- 12. Parallax portrait --------------------------------------------- */
.portrait {
  position: relative; overflow: hidden; border-radius: 1.4rem;
  aspect-ratio: 4 / 5; background: var(--navy);
}
.portrait img {
  width: 100%; height: 118%; object-fit: cover; object-position: center 30%;
  filter: grayscale(.6) contrast(1.06);
  will-change: transform;
}
.pquote {
  font-family: var(--display); font-style: italic; font-weight: 400;
  font-size: clamp(1.25rem, 2.1vw, 1.85rem); line-height: 1.5;
  color: var(--navy); margin: 0 0 1.2rem;
}
.band--dark .pquote { color: var(--on-dark); }
.pquote__by {
  font-size: .72rem; font-weight: 700; letter-spacing: .22em; text-transform: uppercase;
  color: var(--gold); margin: 0;
}

/* --- 13. Carousel ------------------------------------------------------ */
.carousel { position: relative; }
.carousel__track {
  display: flex; gap: clamp(.9rem, 1.8vw, 1.4rem);
  overflow-x: auto; scroll-snap-type: x mandatory;
  scrollbar-width: none; -ms-overflow-style: none;
  padding-bottom: .35rem;
}
.carousel__track::-webkit-scrollbar { display: none; }
.carousel__item {
  flex: 0 0 clamp(250px, 74vw, 400px); scroll-snap-align: start;
}
.carousel__nav { display: flex; gap: .55rem; margin-top: 1.6rem; }
.cbtn {
  width: 44px; height: 44px; border-radius: 50%; background: transparent;
  border: 1.4px solid var(--rule); display: grid; place-items: center;
  transition: transform .35s var(--react), border-color .35s var(--react), opacity .3s;
}
.cbtn svg { width: 17px; height: 17px; fill: none; stroke: var(--navy); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.cbtn:hover { transform: translateY(-2px); border-color: rgba(12,108,180,.4); }
.cbtn[disabled] { opacity: .3; pointer-events: none; }
.band--dark .cbtn { border-color: var(--rule-dark); }
.band--dark .cbtn svg { stroke: var(--on-dark); }

/* --- 14. Video lightbox ------------------------------------------------ */
.playbtn {
  position: absolute; inset: 0; z-index: 3; display: grid; place-items: center;
  background: transparent; border: 0; width: 100%; height: 100%;
}
.playbtn i {
  width: clamp(58px, 7vw, 76px); aspect-ratio: 1; border-radius: 50%;
  background: rgba(255,255,255,.94); display: grid; place-items: center;
  box-shadow: 0 12px 34px rgba(7,24,41,.3);
  transition: transform .45s var(--react), background-color .35s var(--react);
}
.playbtn i::after {
  content: ""; width: 0; height: 0; margin-left: 4px;
  border-left: 15px solid var(--navy);
  border-top: 9.5px solid transparent; border-bottom: 9.5px solid transparent;
  transition: border-left-color .35s var(--react);
}
.playbtn:hover i { transform: scale(1.07); background: var(--gold-bright); }

.lbox {
  position: fixed; inset: 0; z-index: 300; display: grid; place-items: center;
  padding: var(--pad); background: rgba(7, 24, 41, .95);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  opacity: 0; pointer-events: none;
  transition: opacity .4s var(--enter);
}
.lbox[open], .lbox.is-open { opacity: 1; pointer-events: auto; }
.lbox__frame { width: min(100%, 1060px); }
.lbox video { width: 100%; border-radius: .9rem; background: #000; box-shadow: 0 30px 90px rgba(0,0,0,.6); }
.lbox__cap { color: var(--on-dark-mut); font-size: .84rem; margin: .9rem 0 0; }
.lbox__x {
  position: absolute; top: clamp(1rem, 3vw, 2rem); right: clamp(1rem, 3vw, 2rem);
  width: 46px; height: 46px; border-radius: 50%; background: rgba(255,255,255,.1);
  border: 1px solid rgba(255,255,255,.2); display: grid; place-items: center;
  transition: transform .35s var(--react), background-color .3s;
}
.lbox__x svg { width: 18px; height: 18px; fill: none; stroke: #fff; stroke-width: 1.9; stroke-linecap: round; }
.lbox__x:hover { transform: rotate(90deg); background: rgba(255,255,255,.2); }

/* --- 15. Lists --------------------------------------------------------- */
.ticks { list-style: none; margin: 0; padding: 0; display: grid; gap: .8rem; }
.ticks li { display: grid; grid-template-columns: 18px 1fr; gap: .8rem; align-items: start; font-size: .98rem; }
.ticks svg { width: 18px; height: 18px; margin-top: .38em; fill: none; stroke: var(--gold); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.band--dark .ticks svg { stroke: var(--gold-bright); }

.deflist { display: grid; gap: 0; margin: 0; }
.deflist > div {
  display: grid; gap: .3rem 1.6rem; padding: 1.15rem 0;
  border-bottom: 1px solid var(--rule);
  grid-template-columns: minmax(140px, 26%) 1fr;
}
.deflist > div:first-child { border-top: 1px solid var(--rule); }
.deflist dt { font-weight: 600; color: var(--navy); font-size: .96rem; }
.deflist dd { margin: 0; color: var(--text-muted); font-size: .96rem; }
.band--dark .deflist > div { border-color: var(--rule-dark); }
.band--dark .deflist dt { color: var(--on-dark); }
.band--dark .deflist dd { color: var(--on-dark-mut); }
@media (max-width: 620px) { .deflist > div { grid-template-columns: 1fr; } }

/* --- 16. Accordion / FAQ ----------------------------------------------- */
.faq { border-top: 1px solid var(--rule); }
.faq details { border-bottom: 1px solid var(--rule); }
.faq summary {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 1.2rem;
  padding: 1.35rem 0; cursor: pointer; list-style: none;
  font-family: var(--display); font-weight: 500;
  font-size: clamp(1.02rem, .8vw + .88rem, 1.22rem); color: var(--navy);
  transition: color .3s var(--react);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary:hover { color: var(--blue); }
.faq summary i {
  flex: 0 0 20px; height: 20px; position: relative; margin-top: .25em;
}
.faq summary i::before, .faq summary i::after {
  content: ""; position: absolute; inset: 50% 0 auto; height: 1.6px;
  background: var(--gold); transition: transform .4s var(--enter);
}
.faq summary i::after { transform: rotate(90deg); }
.faq details[open] summary i::after { transform: rotate(0deg); }
.faq__a { padding: 0 0 1.5rem; max-width: 68ch; }
.faq__a p { color: var(--text-muted); font-size: .98rem; }

/* --- 17. Footer -------------------------------------------------------- */
/* No bottom padding. The credit plate below has to reach the bottom of the page,
   and footer padding would sit underneath it as a strip of the lighter ink. The
   space the padding used to give the copyright line now belongs to that line. */
.ftr { background: var(--ink); color: var(--on-dark-mut); padding-block: clamp(3.4rem, 7vw, 5.4rem) 0; }
.ftr__top {
  display: grid; gap: clamp(2.2rem, 4vw, 3.4rem);
  grid-template-columns: minmax(min(100%, 260px), 1.5fr) repeat(auto-fit, minmax(min(100%, 140px), 1fr));
}
.ftr__brand { display: flex; align-items: center; gap: .8rem; margin-bottom: 1.2rem; text-decoration: none; }
.ftr__brand img { width: 46px; }
.ftr__brand .brand__a { color: var(--on-dark); }
.ftr__brand .brand__b { color: rgba(243,241,234,.5); }
.ftr p { font-size: .93rem; line-height: 1.75; }
.ftr h4 {
  font-family: var(--body); font-size: .64rem; font-weight: 700;
  letter-spacing: .24em; text-transform: uppercase; color: var(--gold-bright);
  margin: 0 0 1.15rem;
}
.ftr ul { list-style: none; margin: 0; padding: 0; display: grid; gap: .68rem; }
.ftr ul a, .ftr address a {
  color: var(--on-dark-mut); text-decoration: none; font-size: .93rem;
  transition: color .3s var(--react);
}
.ftr ul a:hover, .ftr address a:hover { color: var(--gold-bright); }
.ftr address { font-style: normal; font-size: .93rem; line-height: 1.8; }
.ftr__social { display: flex; gap: .5rem; margin-top: 1.4rem; }
.ftr__social a {
  width: 40px; height: 40px; border-radius: 50%; border: 1px solid var(--rule-dark);
  display: grid; place-items: center; text-decoration: none;
  font-size: .64rem; font-weight: 700; letter-spacing: .06em; color: var(--on-dark-mut);
  transition: transform .35s var(--react), border-color .3s, color .3s;
}
.ftr__social a:hover { transform: translateY(-2px); border-color: var(--gold-bright); color: var(--gold-bright); }

.ftr__btm {
  margin-top: clamp(2.6rem, 5vw, 4rem); padding-block: 1.7rem 2rem;
  border-top: 1px solid var(--rule-dark);
  display: flex; flex-wrap: wrap; gap: 1rem 1.6rem; align-items: center; justify-content: space-between;
}
.ftr__btm p { font-size: .82rem; margin: 0; color: rgba(243,241,234,.46); }

/* The maintainer credit, on its own plate under the footer. Same treatment as the
   International Teams Philippines site: one centred row of label, emblem, name and
   line, on a ground a step darker than the footer so it reads as a signature on the
   page rather than another footer column. */
.signoff { background: var(--ink-deep); border-top: 1px solid rgba(243, 241, 234, .10); }
.signoff__in {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: clamp(.9rem, 2.4vw, 2rem); padding-block: 1.75rem;
}
.signoff__pre {
  font-family: var(--body); font-size: .72rem; font-weight: 400;
  letter-spacing: .16em; text-transform: uppercase; color: rgba(243, 241, 234, .48);
}
.signoff__mark { display: inline-flex; }
.signoff__mark img {
  height: 46px; width: auto; opacity: .95;
  transition: transform .4s var(--react), opacity .3s var(--react);
}
.signoff__mark:hover img { transform: scale(1.06); opacity: 1; }
.signoff__name {
  font-family: var(--body); font-size: .92rem; font-weight: 800;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--gold-bright); text-decoration: none;
  border-bottom: 1px solid rgba(251, 186, 96, .45);
  transition: color .25s var(--react), border-color .25s var(--react);
}
.signoff__name:hover { color: var(--on-dark); border-color: rgba(243, 241, 234, .6); }
.signoff__sub { font-size: .78rem; letter-spacing: .03em; color: rgba(243, 241, 234, .46); }

/* The emblem gleam. A highlight travels around the mark, like light moving across
   metal. Same treatment as the International Teams Philippines footer, so the two
   ministries we look after are signed the same way in motion as well as in layout.

   Three things worth knowing.

   The mask path is `../img/`, not the bare filename the ITP stylesheet uses. URLs in
   a stylesheet resolve against the stylesheet, and this one sits in assets/css/ while
   the emblem sits in assets/img/. Getting this wrong gives a 404, and a failed mask
   is transparent rather than loud: the emblem still renders and the gleam simply does
   not appear.

   `@property` is what makes it sweep. A plain custom property cannot be interpolated,
   so the conic gradient would jump between keyframes instead of turning. Registering
   the angle makes it animatable.

   The angle animates, not the element. Rotating the pseudo element with `transform`
   would rotate its mask with it, so the highlight would sit still while the whole
   mark appeared to spin.

   Masks are origin restricted. Over file:// this renders nothing; use the preview
   server. The bucket serves over HTTPS, so production is unaffected. */
@property --fg-gleam { syntax: "<angle>"; inherits: false; initial-value: 0deg; }

.signoff__mark { position: relative; }
.signoff__mark::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  /* Brightens the gold rather than painting over it, so it reads as reflected light
     instead of a white overlay. */
  mix-blend-mode: screen;
  -webkit-mask: url(../img/4g-emblem.png) center/100% 100% no-repeat;
          mask: url(../img/4g-emblem.png) center/100% 100% no-repeat;
  background: conic-gradient(from var(--fg-gleam),
    rgba(255, 246, 220, 0)    0deg,
    rgba(255, 246, 220, 0)   52deg,
    rgba(255, 246, 220, .92) 78deg,
    rgba(255, 246, 220, 0)  106deg,
    rgba(255, 246, 220, 0)  360deg);
  /* One full turn. Slow enough to read as a finish rather than a spinner. */
  animation: fg-gleam-spin 4.6s linear infinite;
}
@keyframes fg-gleam-spin { to { --fg-gleam: 360deg } }

/* The hover scale on the img is left alone and does not carry the gleam with it. Six
   per cent is not perceptible at 46px, and scaling the pseudo element would drag its
   mask out of alignment with the mark underneath. */

@media (prefers-reduced-motion: reduce) {
  .signoff__mark::after { display: none; }
}

/* One row above 760px, tagline last, which is the arrangement the ministry chose
   after seeing both. The two-row version centred every row on the page axis; this
   one centres the run of text instead, which leaves the emblem and the name sitting
   about 68px left of the middle. That is the trade, and it is the same trade the
   reference site makes. The phone layout below is a centred stack either way. */

/* One column on a phone, and the emblem grows because it is the only thing on its
   own line and can carry the weight there. */
@media (max-width: 760px) {
  .signoff__in { flex-direction: column; text-align: center; gap: .72rem; padding-block: 2.6rem; }
  .signoff__mark img { height: 64px; }
}

/* --- 18. Scroll entrance ----------------------------------------------- */
/* Only transform and opacity are animated, with one deliberate exception: the
   maintainer emblem in the footer sweeps a registered angle property. That is a
   paint on a 46px box and touches no layout, but it is not transform or opacity, so
   it is named here rather than left to contradict this line. */
[data-rise] {
  opacity: 0; transform: translateY(30px);
  transition: opacity .9s var(--enter), transform .9s var(--enter);
  transition-delay: var(--d, 0ms);
}
[data-rise].is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  [data-rise] { opacity: 1 !important; transform: none !important; transition: none !important; }
  .scrollcue i { animation: none; }
  .portrait img { transform: none !important; }
}
/* Screenshot mode: reveal every entrance and unpin the hero for full-page capture. */
html.shot [data-rise] { opacity: 1 !important; transform: none !important; transition: none !important; }
/* Track the emulated viewport rather than a fixed height. Pinning these made
   fold checks untruthful: a 900px hero clipped into an 820px shot looked like a
   layout fault that did not exist. vh instead of svh because headless has no
   retracting browser UI for svh to account for. */
/* Screenshots get a full-height fold so the capture matches what a visitor sees.
   The figure hero is exempt: its whole point is a ratio, and overriding the
   height here would make every verification screenshot a lie. */
html.shot .hero:not(.hero--figure) { min-height: min(100vh, 940px); }
html.shot .hero--center { min-height: min(100vh, 940px); }
html.shot .scrollcue i { animation: none; }
html.shot .photo img { filter: grayscale(.28) contrast(1.03); }

/* --- 19. Narrow-viewport guards ---------------------------------------- */
@media (max-width: 520px) {
  .btn { padding: .95rem 1.5rem; letter-spacing: .14em; }
  .cta-row { gap: .7rem; }
  .cta-row > .btn { width: 100%; justify-content: center; }
  .stats { grid-template-columns: 1fr 1fr; gap: 2rem 1.4rem; }
  .ftr__top { grid-template-columns: 1fr 1fr; }
  .ftr__top > *:first-child { grid-column: 1 / -1; }
  .carousel__item { flex-basis: 82vw; }
}
@media (max-width: 380px) {
  .brand__b { display: none; }
  .ftr__top { grid-template-columns: 1fr; }
}

/* --- 21. Inner-page hero ------------------------------------------------ */
/* Shorter than the home fold. An inner page has to start delivering inside the
   first screen, so the hero states where you are and gets out of the way. */
.hero--page {
  min-height: min(62svh, 560px);
  padding: calc(clamp(62px,7vw,82px) + clamp(2.6rem,6vw,4.4rem)) 0 clamp(2.6rem, 5vw, 4rem);
}
.hero--page h1 {
  font-family: var(--display); font-weight: 400; font-style: italic;
  font-size: clamp(2.1rem, 5.2vw, 4.1rem); line-height: 1.04;
  letter-spacing: -.005em; color: #fff; max-width: 22ch;
  text-shadow: 0 2px 24px rgba(7,24,41,.55);
}
.hero--page .lede { color: rgba(255,255,255,.82); max-width: 54ch; margin-top: 1.2rem; }
.hero--page .overline { color: var(--gold-bright); }

/* --- 21b. Hero built around a standing figure --------------------------- */
/* One photograph cannot survive `cover` across every box shape. A 560px band on a
   2560px display is a 4.6:1 letterbox: it throws away 59% of a 1.88:1 frame and
   decapitates anyone standing in it. Nudging `object-position` only moves which
   part gets lost, and it moves differently at every viewport height, because
   `62svh` makes the box ratio depend on the window as well as the width.
   So the box stops guessing. `--hero-ar` pins it to a known ratio per band, and
   there is a hand-framed crop of the photograph at each of those exact ratios,
   so `cover` has nothing left to cut and the composition is the same everywhere:
   raised hand at roughly 6% from the top, face in the upper third, words below.
   `min-height` rather than `aspect-ratio` on purpose. If the headline ever wraps
   long enough to outgrow the ratio, the box grows and the crop tightens from the
   sides instead of overflowing, which is the harmless direction to fail. */
.hero--figure {
  --hero-ar: .625;
  min-height: calc(100vw / var(--hero-ar));
}
.hero--figure .hero__media img { object-position: center center; }
@media (min-width:  600px) { .hero--figure { --hero-ar: 1.2;  } }
@media (min-width:  900px) { .hero--figure { --hero-ar: 1.75; } }
@media (min-width: 1280px) { .hero--figure { --hero-ar: 2.6;  } }
@media (min-width: 2200px) { .hero--figure { --hero-ar: 3.7;  } }
/* A phone held sideways, or a short docked window. Last, so it wins. Here the
   headline needs more height than any ratio would give it, so the box ends up
   near 2.3:1 whatever we ask for. 2.6 is the closest crop, which leaves an 11%
   trim off the sides instead of the 39% the ultrawide crop was costing. */
@media (orientation: landscape) and (max-height: 560px) {
  .hero--figure { --hero-ar: 2.6; }
}

/* A page opener with no photograph behind it. Parchment, not ink. */
.pagehead {
  padding: calc(clamp(62px,7vw,82px) + clamp(2.8rem,7vw,5rem)) 0 clamp(2rem, 4vw, 3.2rem);
  background: var(--parchment-2);
  border-bottom: 1px solid var(--rule-soft);
}
.pagehead h1 {
  font-family: var(--display); font-weight: 400; font-style: italic;
  font-size: clamp(2.1rem, 5vw, 3.9rem); line-height: 1.06;
  letter-spacing: -.005em; color: var(--navy); max-width: 24ch;
}
.pagehead .lede { max-width: 58ch; margin-top: 1.1rem; }
.pagehead--center { text-align: center; }
.pagehead--center h1, .pagehead--center .lede { margin-inline: auto; }

/* --- 24. Senior pastors, on the schedule's navy ------------------------- */
/* The section above this one is `band--dark`. Holding the same navy here means
   there is no seam between them and the two read as one passage rather than two
   stacked cards. The photograph is a navy duotone already, so it needs a scrim
   that shapes legibility rather than one that darkens the whole frame. */
.leaders {
  position: relative; isolation: isolate; overflow: hidden;
  /* Derived from width, not from `svh`. With a viewport-height min-height the media
     box ratio changed with the window, so `cover` cropped a different axis on every
     screen and the couple wandered. At 1/1.9 the media box is 1.70:1 at every width
     below the cap, comfortably wider than the photograph's 1.5:1, so nothing is
     trimmed horizontally and they stay where they actually stand in the frame. */
  min-height: min(calc(100vw / 1.9), 880px);
  /* Tighter than `.band`. The section's height is set by the text column, not by
     the min-height, and every extra pixel of padding makes the media box taller,
     narrower in ratio, and therefore more zoomed, which walks the couple to the
     right and into the words. The photograph supplies the breathing room that the
     padding would otherwise have to. */
  padding-block: clamp(3rem, 6vw, 5.5rem);
  display: grid; align-content: center;
}
/* Overscanned top and bottom. The parallax translates the image, and without the
   overscan the travel would drag a hard edge into view at the top of the section. */
/* 6% is enough. The parallax travels about 16px at this speed, so the old 12%
   was buying overscan nothing needed and making the media box taller, which is
   what forced the horizontal crop in the first place. */
.leaders__media { position: absolute; inset: -6% 0; z-index: -2; }
.leaders__media picture { display: block; width: 100%; height: 100%; }
.leaders__media img {
  width: 100%; height: 100%; object-fit: cover;
  /* Hold the couple. They stand in the left third of the frame, and the crop
     tightens on a different axis at each end of the range: at 1024 the box is
     taller than the photograph so it trims the sides and Ruth is the one at risk,
     while at 2560 it is wider so it trims top and bottom and their heads are.
     16% protects her, 46% keeps the heads clear of the top edge. */
  object-position: 16% 46%;
  will-change: transform;
}
.leaders__scrim {
  position: absolute; inset: 0; z-index: -1;
  background:
    /* Vertical: fully navy at both edges so the joins above and below disappear. */
    linear-gradient(180deg,
      var(--navy) 0%, rgba(10,33,56,.30) 13%,
      rgba(10,33,56,.24) 74%, rgba(10,33,56,.94) 97%, var(--navy) 100%),
    /* Horizontal: light over the couple, solid ground under the words. */
    linear-gradient(90deg,
      rgba(10,33,56,.06) 0%, rgba(10,33,56,.14) 26%,
      rgba(10,33,56,.72) 48%, rgba(10,33,56,.93) 62%, rgba(10,33,56,.96) 100%);
}
.leaders__in { position: relative; }
.leaders__col { max-width: 48ch; margin-left: auto; }
.leaders .pquote { color: #fff; }
.leaders .pquote__by { color: var(--gold-bright); }
.leaders .measure { max-width: 46ch; }
.leaders__head .pquote { margin-top: 1.4rem; }
.leaders__body { margin-top: 1.7rem; }
.leaders__body .cta-row { margin-top: 1.7rem; }

/* Under 1024px the photograph stops being a background and takes its own band.
   Forced behind a narrow column, `cover` can only show about 30% of a 1.5:1 frame,
   which crops Mrs. Bishop Ruth off the left edge entirely and lands the headline on
   Bishop Rod's face. A band at the ministry's own aspect keeps both of them in
   shot, and the words then sit on solid navy where nothing competes with them. */
/* Under 1280px the name and the greeting move up beside them, into the empty half
   of the photograph, and only the biography stays below. That is the arrangement the
   ministry asked for, and it is also the only one that works: forced behind a full
   width column, `cover` can show about 30% of a 1.5:1 frame, which crops Mrs. Bishop
   Ruth off the left edge and lands the headline on Bishop Rod's face.

   The geometry is the whole trick. `--band` is the photograph's height, derived from
   the viewport width so it never depends on window height. `--overscan` is how much
   taller the picture is than that band, which is the parallax travel room, and it is
   also what decides the crop: the image box ratio is `--band-ar / --overscan`, and
   the couple only leave the right half of the frame free while that stays close to
   the photograph's own 1.5. Hence 1.5 and 1.06, not 4/3 and 1.18. */
@media (max-width: 1279px) {
  .leaders {
    --band-ar: 1.5;
    --overscan: 1.06;
    --band: calc(100vw / var(--band-ar));
    /* The strip the centred label sits in, above the photograph. Declared as a
       variable because the media and the scrim have to begin exactly where it
       ends: they are positioned against the section, so section padding cannot
       move them and a hard-coded second number would drift out of step. */
    --strip: clamp(3rem, 9vw, 4.2rem);
    display: block; min-height: 0; position: relative;
    padding-block: 0 clamp(3rem, 8vw, 4.6rem);
  }
  /* Centred above everything, on solid navy, at the site's ordinary overline size
     rather than the shrunken one the 47% column needed. This is the same placement
     and the same rules-both-sides treatment as "Worship Service" over "SCHEDULE".
     The height is fixed rather than intrinsic because the photograph's top edge is
     pinned to the same number, so the strip has to stay taller than the label at
     every width. Measured: one line down to 320px, two lines at 280px at 35px
     total, still inside the 48px floor. A longer label would need --strip raised. */
  .leaders__eyebrow {
    justify-content: center; text-align: center;
    height: var(--strip); margin: 0;
    font-size: clamp(.62rem, .18vw + .58rem, .7rem); letter-spacing: .3em;
  }
  .leaders__eyebrow::before {
    content: ""; flex: 0 0 clamp(28px, 6vw, 56px); height: 1px;
    background: linear-gradient(270deg, var(--gold-bright), transparent);
  }
  .leaders__media {
    position: absolute; inset: var(--strip) 0 auto 0; height: var(--band);
    z-index: -2; overflow: hidden;
  }
  .leaders__media picture {
    position: relative; display: block;
    height: calc(var(--overscan) * 100%);
    top: calc((1 - var(--overscan)) * 50%);
  }
  /* Left edge, so the couple stand at their true 6% to 48% of the frame and the
     right half stays clear for the words. */
  .leaders__media img { object-position: 0% 46%; }
  .leaders__scrim {
    display: block; inset: var(--strip) 0 auto 0; height: var(--band);
    background:
      linear-gradient(180deg, var(--navy) 0%, rgba(10,33,56,.06) 14%,
        rgba(10,33,56,.10) 62%, rgba(10,33,56,.74) 90%, var(--navy) 100%),
      linear-gradient(90deg, rgba(10,33,56,0) 0%, rgba(10,33,56,.05) 38%,
        rgba(10,33,56,.62) 52%, rgba(10,33,56,.88) 64%, rgba(10,33,56,.92) 100%);
  }
  .leaders__col { max-width: none; margin-left: 0; }

  /* Reserve exactly the band, and sit the words in the clear half of it. */
  .leaders__head {
    min-height: var(--band);
    display: grid; align-content: center;
  }
  .leaders__head > * { max-width: 47%; margin-left: auto; margin-right: 0; }
  /* Stepped down because the column is now 47% of a phone. The full scale returns
     at 1280 where there is room for it. */
  .leaders__head .h2 {
    font-size: clamp(1.12rem, 4.6vw, 1.66rem); line-height: 1.14; margin-bottom: 0;
  }
  .leaders__head .pquote {
    font-size: clamp(.86rem, 3.2vw, 1.18rem); line-height: 1.42;
    margin-top: .8rem; margin-bottom: .55rem;
  }
  .leaders__head .pquote__by { font-size: clamp(.56rem, 2vw, .68rem); letter-spacing: .16em; }

  .leaders__body { margin-top: clamp(1.9rem, 5vw, 2.8rem); }
}

/* On a narrow phone the words may need more height than the photograph has. That is
   handled by `min-height` rather than by hiding anything: the block simply grows, and
   the overflow lands on plain navy under a band that already fades to navy, so the
   join does not show. Nothing is dropped and nothing is duplicated, which is the
   whole reason not to solve this with `display: none`. */
@media (max-width: 419px) {
  .leaders__head > * { max-width: 50%; }
}

/* A word set as capitals needs the tracking opened up. Applied as a transform so
   the accessible name stays "Schedule" rather than shouting in the tree. */
.h2--caps { text-transform: uppercase; letter-spacing: .05em; }

/* A heading meant to hold one line. `.intro` caps at 660px and this one sets wider
   than that at full size, so it broke after "again" and the sentence lost its beat.
   Paired with `.intro--wide` in the markup, which gives it 820px. `balance` is the
   safety net for the phone, where one line is not possible: it splits the two lines
   evenly instead of leaving "Sunday." alone. */
.h2--hold { text-wrap: balance; }
/* One line on a phone too, which needs the type a step down: measured, the sentence
   sets 406px at the normal 1.85rem floor and a 390px screen offers 350px of column.
   At 1.5rem it holds one line down to about 375px, which covers the iPhone SE, the
   12 through 15, and the common Android widths. Below that `balance` takes over and
   splits it evenly rather than dropping "Sunday." on its own. */
@media (max-width: 460px) { .h2--hold { font-size: 1.5rem; } }

/* Two sentences, one per line, split with a <br> rather than by luck. On a narrow
   phone each half wraps again, which is the right failure: the break the ministry
   asked for still lands where they asked for it. */
.lede--split { max-width: none; text-wrap: pretty; }

/* --- 21b. Pastoral team ------------------------------------------------- */
/* Every name in a Sunday schedule links here, to that pastor's own card. */
.sched__pastors li a {
  color: inherit; text-decoration: none;
  transition: color .3s var(--react), background-color .3s var(--react);
}
.sched__pastors li:hover { background: rgba(251, 186, 96, .14); }
.sched__pastors li:hover a { color: var(--gold-bright); }
.sched__pastors li:focus-within { outline: 2px solid var(--gold-bright); outline-offset: 2px; }

.pastors__svc {
  font-family: var(--body); font-size: .66rem; font-weight: 700;
  letter-spacing: .26em; text-transform: uppercase; color: var(--blue);
  margin: clamp(2.4rem, 5vw, 3.4rem) 0 1.2rem;
  display: flex; align-items: baseline; flex-wrap: wrap; gap: .3rem .8rem;
}
.pastors__svc:first-child { margin-top: 0; }
.pastors__svc span {
  font-family: var(--display); font-size: 1.34rem; font-weight: 500;
  letter-spacing: 0; text-transform: none; color: var(--navy);
}
.pastor__svc {
  font-size: .78rem; letter-spacing: .04em; color: var(--text-muted); margin: 0;
}
/* Answers "which one did I click?" after the jump. It persists rather than fading,
   because that question is still worth answering a minute later. */
.pastor:target {
  border-color: rgba(251, 186, 96, .55);
  box-shadow: 0 0 0 3px rgba(251, 186, 96, .14);
}
.pastor:target::before { transform: scaleX(1); }
.pastor:target .h3 { color: var(--blue-deep); }
/* Four across, not three. Until the introductions arrive most cards carry a name
   and one line, and at the 280px column the grid stretches them into large empty
   rectangles. A tighter column fits four and the row reads as a list of people
   rather than a set of blanks. When the copy lands, raise this back to 280px. */
.pastors .grid--3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 232px), 1fr)); }
.pastors .pastor { padding: clamp(1.15rem, 1.8vw, 1.5rem); }
/* Two up on a phone. Twenty-five single-column cards is about 3,200px of scrolling
   for a name and one line each; paired, it halves and the page can still be read at
   arm's length. */
@media (max-width: 619px) {
  .pastors .grid--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .75rem; }
  .pastors .pastor { padding: 1rem .95rem; }
  .pastors .pastor .h3 { font-size: 1rem; line-height: 1.25; }
  .pastors .pastor__svc { font-size: .72rem; }
}
/* `.sched__roster` is written for the navy band and its colour is near white. This
   line sits on parchment, so it needs its own. */
.pastors__ask { max-width: 62ch; color: var(--text-muted); }

/* --- 22. The Appointed Times wheel ------------------------------------- */
.wheel-wrap {
  display: grid; gap: clamp(2rem, 4vw, 3.4rem);
  grid-template-columns: minmax(min(100%, 300px), 420px) 1fr;
  align-items: center;
}
@media (max-width: 900px) { .wheel-wrap { grid-template-columns: 1fr; } }

.wheel { width: 100%; height: auto; overflow: visible; }
.wheel__ring { fill: none; stroke: rgba(243,241,234,.16); stroke-width: 1; }
.wheel__arc {
  fill: none; stroke: rgba(251,186,96,.34); stroke-width: 1.4;
  stroke-linecap: round; stroke-dasharray: 2 7;
}
.wheel__node { cursor: pointer; }
.wheel__node circle {
  fill: rgba(12,108,180,.34); stroke: rgba(168,196,227,.5); stroke-width: 1.2;
  transition: fill .45s var(--react), stroke .45s var(--react), r .45s var(--react);
}
.wheel__node text {
  font-family: var(--body); font-size: 9px; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase;
  fill: rgba(243,241,234,.5); transition: fill .45s var(--react);
}
.wheel__node:hover circle, .wheel__node:focus-visible circle { fill: rgba(12,108,180,.6); }
.wheel__node.is-on circle { fill: var(--gold); stroke: var(--gold-bright); }
.wheel__node.is-on text { fill: var(--gold-bright); }
.wheel__node:focus-visible { outline: none; }
.wheel__node:focus-visible circle { stroke: #fff; stroke-width: 2; }
.wheel__hub {
  font-family: var(--display); font-style: italic; font-size: 15px;
  fill: rgba(243,241,234,.42); text-anchor: middle;
}

.feast { min-height: 15rem; }
.feast__no {
  font-family: var(--body); font-weight: 800; font-size: .62rem;
  letter-spacing: .42em; text-transform: uppercase; color: var(--gold-bright);
}
.feast__h {
  font-family: var(--display); font-weight: 500;
  font-size: clamp(1.6rem, 3vw, 2.5rem); line-height: 1.1;
  color: #fff; margin: .5rem 0 .1rem;
}
.feast__heb {
  font-family: var(--display); font-style: italic;
  font-size: 1.02rem; color: rgba(168,196,227,.9);
}
.feast__when {
  margin-top: 1rem; font-size: .78rem; font-weight: 700;
  letter-spacing: .2em; text-transform: uppercase; color: rgba(243,241,234,.5);
}
.feast__body { margin-top: 1.1rem; max-width: 52ch; color: var(--on-dark-mut); }
.feast__points {
  margin-top: 1.3rem; padding-top: 1.1rem; border-top: 1px solid var(--rule-dark);
  max-width: 52ch;
}
.feast__points span {
  display: block; font-size: .64rem; font-weight: 800; letter-spacing: .3em;
  text-transform: uppercase; color: rgba(251,186,96,.66); margin-bottom: .45rem;
}
.feast__points p { color: #fff; font-size: 1.02rem; margin: 0; }

/* --- 23. Notices, locations, giving ------------------------------------ */
/* Used where the ministry has not yet supplied a detail. Saying so plainly is
   better than shipping a plausible-looking placeholder that gets mistaken for
   real information. */
.notice {
  display: grid; grid-template-columns: 20px 1fr; gap: .9rem;
  padding: 1.1rem 1.3rem; border-radius: .9rem;
  background: rgba(240,144,24,.07); border: 1px solid rgba(240,144,24,.22);
  font-size: .93rem; color: var(--text-soft);
}
.notice svg { width: 20px; height: 20px; margin-top: .18em; fill: none; stroke: var(--gold); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.band--dark .notice, .band--ink .notice {
  background: rgba(251,186,96,.09); border-color: rgba(251,186,96,.24); color: var(--on-dark-mut);
}
.band--dark .notice svg, .band--ink .notice svg { stroke: var(--gold-bright); }

.loc { display: grid; gap: .35rem; padding: 1.25rem 0; border-bottom: 1px solid var(--rule); }
/* The global paragraph margin fights the grid gap here and makes every row sit
   about 20px taller than it should, which reads as a list nobody finished. */
.loc p { margin: 0; }
.loc:first-child { border-top: 1px solid var(--rule); }
.loc__n { font-family: var(--display); font-weight: 500; font-size: 1.2rem; color: var(--navy); }
.loc__m { font-size: .92rem; color: var(--text-muted); }
.loc__l { font-size: .8rem; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--blue); }
.loc--main { background: var(--parchment-2); border-radius: 1.25rem; border: 0; padding: clamp(1.5rem, 3vw, 2.2rem); }
.loc--main + .loc { border-top: 1px solid var(--rule); }

.qr {
  display: grid; gap: 1rem; justify-items: center; text-align: center;
  padding: clamp(1.8rem, 4vw, 2.6rem);
  border-radius: 1.25rem; background: rgba(255,255,255,.05);
  border: 1px dashed rgba(243,241,234,.26);
}
.qr__box {
  width: clamp(150px, 34vw, 200px); aspect-ratio: 1;
  display: grid; place-items: center; border-radius: .9rem;
  background: rgba(243,241,234,.05); border: 1px dashed rgba(243,241,234,.3);
  font-size: .68rem; font-weight: 800; letter-spacing: .24em;
  text-transform: uppercase; color: rgba(243,241,234,.42); text-align: center;
  padding: 1rem;
}

/* Progressive enhancement: all seven appointed times are in the HTML and all
   seven are visible by default. The script adds `is-live` once the wheel is
   wired up, and only then do they collapse to one at a time. With JavaScript
   off the page is a plain readable list rather than six hidden panels. */
.feasts { display: grid; gap: clamp(2.4rem, 5vw, 3.4rem); }
.feasts.is-live { display: block; }
.feasts.is-live .feast { display: none; }
.feasts.is-live .feast.is-on { display: block; animation: feastIn .55s var(--enter) both; }
@keyframes feastIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .feasts.is-live .feast.is-on { animation: none; }
}
.feast__nav {
  display: flex; gap: .6rem; align-items: center;
  margin-top: 1.6rem; padding-top: 1.3rem; border-top: 1px solid var(--rule-dark);
}
.feasts:not(.is-live) .feast__nav { display: none; }
.feast__nav p {
  margin: 0 0 0 auto; font-size: .72rem; font-weight: 700;
  letter-spacing: .2em; text-transform: uppercase; color: rgba(243,241,234,.44);
}
