/* ==========================================================================
   Becoming The Wandobires — Brian & Angella
   Design system: black canvas, bone white type, green as the ritual accent.
   ========================================================================== */

/* ---------- 1. Tokens ---------- */

:root {
  /* Ink — near-black with a faint green undertone so it sits with the greens */
  --ink:        #050C08;
  --ink-1:      #0A140E;
  --ink-2:      #0F1D15;
  --ink-3:      #16291D;
  --ink-line:   #1E3527;

  /* Bone — warm off-white, never pure #fff for large fields */
  --bone:       #F4F2EA;
  --bone-2:     #E4E1D5;
  --bone-3:     #C9C5B6;
  --paper:      #FBFAF6;

  /* Green — the accent runs from deep forest to a living, tropical light */
  --green-900:  #04301B;
  --green-800:  #063F24;
  --green-700:  #0A5A33;
  --green-600:  #0E7241;
  --green-500:  #12894C;
  --green-400:  #1FB365;
  --green-300:  #4BD98C;
  --green-200:  #8CEDB8;
  --green-glow: #6BF2A6;

  /* Semantic */
  --bg:            var(--ink);
  --fg:            var(--bone);
  --fg-muted:      #9AA79F;
  --fg-faint:      #6B7A72;
  --accent:        var(--green-400);
  --accent-strong: var(--green-300);
  --rule:          rgba(244, 242, 234, 0.14);

  /* Type */
  --display: "Cormorant Garamond", "Hoefler Text", Garamond, "Times New Roman", serif;
  --sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;

  --step--1: clamp(0.78rem, 0.75rem + 0.15vw, 0.86rem);
  --step-0:  clamp(0.95rem, 0.9rem + 0.25vw, 1.06rem);
  --step-1:  clamp(1.15rem, 1.05rem + 0.5vw, 1.35rem);
  --step-2:  clamp(1.5rem, 1.25rem + 1.2vw, 2.1rem);
  --step-3:  clamp(2rem, 1.5rem + 2.4vw, 3.4rem);
  --step-4:  clamp(2.6rem, 1.6rem + 4.6vw, 5.6rem);
  --step-5:  clamp(3.2rem, 1.4rem + 8vw, 9rem);

  /* Space */
  --gutter: clamp(1.25rem, 4vw, 4rem);
  --section-y: clamp(4.5rem, 11vw, 10rem);
  --measure: 62ch;

  /* Motion */
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);

  --radius: 2px;
  --radius-lg: 4px;

  --shadow-lift: 0 30px 80px -30px rgba(0, 0, 0, 0.85);
}

/* ---------- 2. Reset ---------- */

*, *::before, *::after { box-sizing: border-box; }

/* Any author `display` rule beats the UA stylesheet's [hidden] { display:none },
   which would otherwise leave hidden grid/flex containers on screen. Several
   things here toggle visibility via the hidden attribute, so make it stick. */
[hidden] { display: none !important; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--sans);
  font-size: var(--step-0);
  line-height: 1.65;
  font-weight: 300;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

body.is-locked { overflow: hidden; }

h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 300;
  line-height: 1.06;
  letter-spacing: -0.015em;
  margin: 0;
  text-wrap: balance;
}

p { margin: 0 0 1.1em; text-wrap: pretty; }
p:last-child { margin-bottom: 0; }

img, picture, svg, video { display: block; max-width: 100%; }
img { height: auto; }

a { color: inherit; text-decoration: none; }

button, input, select, textarea { font: inherit; color: inherit; }

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

::selection { background: var(--green-400); color: var(--ink); }

/* Film grain — barely there, but it stops the black from looking flat */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 900;
  pointer-events: none;
  opacity: 0.04;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ---------- 3. Layout primitives ---------- */

.shell {
  width: min(100% - (var(--gutter) * 2), 1280px);
  margin-inline: auto;
}
.shell--narrow { width: min(100% - (var(--gutter) * 2), 860px); }
.shell--wide   { width: min(100% - (var(--gutter) * 2), 1560px); }

.section { padding-block: var(--section-y); position: relative; }
.section--tight { padding-block: clamp(3rem, 7vw, 6rem); }

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 1000;
  background: var(--green-400);
  color: var(--ink);
  padding: 0.75rem 1.25rem;
  font-weight: 500;
}
.skip-link:focus { left: 1rem; top: 1rem; }

/* ---------- 4. Typographic details ---------- */

.eyebrow {
  font-family: var(--sans);
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 1.25rem;
  display: flex;
  align-items: center;
  gap: 0.9rem;
}
.eyebrow::before {
  content: "";
  width: clamp(1.5rem, 4vw, 3rem);
  height: 1px;
  background: currentColor;
  opacity: 0.6;
  flex: none;
}
.eyebrow--center { justify-content: center; }
.eyebrow--center::after {
  content: "";
  width: clamp(1.5rem, 4vw, 3rem);
  height: 1px;
  background: currentColor;
  opacity: 0.6;
  flex: none;
}

.display  { font-size: var(--step-3); }
.display-lg { font-size: var(--step-4); }
.lede {
  font-size: var(--step-1);
  color: var(--fg-muted);
  max-width: var(--measure);
  font-weight: 300;
}
.prose { max-width: var(--measure); color: var(--fg-muted); }
.prose strong { color: var(--fg); font-weight: 400; }

.serif-italic { font-family: var(--display); font-style: italic; font-weight: 300; }

.amp {
  font-family: var(--display);
  font-style: italic;
  color: var(--accent);
  font-weight: 400;
}

/* ---------- 5. Monogram ---------- */

.monogram {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-family: var(--display);
  font-size: 1.15rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--fg);
  white-space: nowrap;
}
.monogram__ring {
  width: 30px; height: 30px;
  border: 1px solid var(--accent);
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 0.72rem;
  letter-spacing: 0;
  color: var(--accent);
  flex: none;
  transition: background 0.4s var(--ease), color 0.4s var(--ease);
}
a.monogram:hover .monogram__ring { background: var(--accent); color: var(--ink); }

/* The wordmark spells out the whole site title, and it may not wrap — so on a
   phone it has to shrink rather than shoulder the menu button off the screen. */
@media (max-width: 640px) {
  .monogram { font-size: 0.8rem; letter-spacing: 0.1em; gap: 0.45rem; }
  .monogram__ring { width: 26px; height: 26px; font-size: 0.62rem; }
}
/* Small, older handsets are still common here, and 320px leaves the title and
   the menu button fighting over about 280px of usable width. Kept below the
   common 375px phone, which has room for the size above. */
@media (max-width: 340px) {
  .monogram { font-size: 0.68rem; letter-spacing: 0.06em; gap: 0.35rem; }
  .monogram__ring { width: 23px; height: 23px; font-size: 0.55rem; }
}

/* ---------- 6. Buttons ---------- */

.btn {
  --btn-bg: transparent;
  --btn-fg: var(--fg);
  --btn-bd: var(--rule);
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.7rem;
  padding: 0.95rem 1.9rem;
  font-family: var(--sans);
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--btn-fg);
  background: var(--btn-bg);
  border: 1px solid var(--btn-bd);
  border-radius: var(--radius);
  cursor: pointer;
  overflow: hidden;
  transition: color 0.45s var(--ease), border-color 0.45s var(--ease), background 0.45s var(--ease), transform 0.2s var(--ease);
  isolation: isolate;
}
.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--green-400);
  transform: scaleY(0);
  transform-origin: bottom;
  transition: transform 0.45s var(--ease);
}
.btn:hover::before, .btn:focus-visible::before { transform: scaleY(1); }
.btn:hover, .btn:focus-visible { color: var(--ink); border-color: var(--green-400); }
.btn:active { transform: translateY(1px); }

.btn--solid { --btn-bg: var(--green-400); --btn-fg: var(--ink); --btn-bd: var(--green-400); }
.btn--solid::before { background: var(--green-200); }

.btn--ghost { --btn-bd: rgba(244,242,234,0.28); }

.btn--onlight { --btn-fg: var(--ink); --btn-bd: rgba(5,12,8,0.22); }
.btn--onlight:hover, .btn--onlight:focus-visible { color: var(--ink); }
.btn--onlight::before { background: var(--green-300); }

.btn--block { width: 100%; }
.btn--lg { padding: 1.15rem 2.4rem; }

.btn[disabled], .btn[aria-busy="true"] { opacity: 0.55; pointer-events: none; }

.btn__spinner {
  width: 15px; height: 15px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
  display: none;
}
.btn[aria-busy="true"] .btn__spinner { display: block; }
@keyframes spin { to { transform: rotate(360deg); } }

.link-underline {
  position: relative;
  color: var(--accent);
  padding-bottom: 2px;
}
.link-underline::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 0.4s var(--ease);
}
.link-underline:hover::after, .link-underline:focus-visible::after {
  transform: scaleX(1);
  transform-origin: left;
}

/* ---------- 7. Navigation ---------- */

.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 800;
  padding-block: clamp(1rem, 2.2vw, 1.6rem);
  transition: padding 0.5s var(--ease), border-color 0.5s var(--ease);
  border-bottom: 1px solid transparent;
}

/* The solid bar lives on a pseudo-element rather than on .nav itself, and that
   is load-bearing: a backdrop-filter makes an element the containing block for
   any position:fixed descendant, which would shrink the full-screen mobile menu
   inside it down to the height of the bar. On ::before it blurs just the same
   and the menu stays anchored to the viewport. */
.nav::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: rgba(5, 12, 8, 0.82);
  backdrop-filter: blur(16px) saturate(140%);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
  opacity: 0;
  transition: opacity 0.5s var(--ease);
}
.nav.is-stuck::before { opacity: 1; }
.nav.is-stuck {
  border-bottom-color: var(--ink-line);
  padding-block: 0.85rem;
}

/* With the menu open the bar has nothing to sit on top of — the panel covers
   the screen — so it drops back to the bare state it has at the top of the
   homepage, rather than laying a line and a second pane of glass over it. */
.nav.is-menu-open::before { opacity: 0; }
.nav.is-menu-open { border-bottom-color: transparent; }
.nav__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
}
.nav__links {
  display: flex;
  align-items: center;
  gap: clamp(1.2rem, 2.6vw, 2.4rem);
  list-style: none;
  margin: 0;
  padding: 0;
}
.nav__link {
  font-size: var(--step--1);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-weight: 400;
  color: var(--fg-muted);
  position: relative;
  padding-block: 0.35rem;
  transition: color 0.35s var(--ease);
}
.nav__link::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  height: 1px; width: 100%;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 0.4s var(--ease);
}
.nav__link:hover, .nav__link:focus-visible, .nav__link[aria-current="page"] { color: var(--fg); }
.nav__link:hover::after, .nav__link:focus-visible::after, .nav__link[aria-current="page"]::after {
  transform: scaleX(1);
  transform-origin: left;
}
.nav__cta { display: none; }
/* Only once the wordmark, the links and the button can all sit on one line.
   Below this the Pledge link in the nav carries it, as it does on a phone. */
@media (min-width: 1060px) { .nav__cta { display: inline-flex; } }

.nav__toggle {
  display: grid;
  place-items: center;
  width: 44px; height: 44px;
  background: none;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  cursor: pointer;
}
.nav__toggle span {
  display: block;
  width: 18px; height: 1px;
  background: var(--fg);
  position: relative;
  transition: background 0.3s var(--ease);
}
.nav__toggle span::before, .nav__toggle span::after {
  content: "";
  position: absolute;
  left: 0;
  width: 18px; height: 1px;
  background: var(--fg);
  transition: transform 0.4s var(--ease);
}
.nav__toggle span::before { top: -6px; }
.nav__toggle span::after  { top: 6px; }
.nav__toggle[aria-expanded="true"] span { background: transparent; }
.nav__toggle[aria-expanded="true"] span::before { transform: translateY(6px) rotate(45deg); }
.nav__toggle[aria-expanded="true"] span::after  { transform: translateY(-6px) rotate(-45deg); }

@media (min-width: 860px) { .nav__toggle { display: none; } }

@media (max-width: 859px) {
  .nav__links {
    position: fixed;
    inset: 0;
    flex-direction: column;
    justify-content: center;
    gap: 2rem;
    /* Same veil as the photo viewer: dark enough to read against, sheer
       enough that the blurred page still shows through it. */
    background: rgba(3, 8, 5, 0.72);
    backdrop-filter: blur(18px) saturate(115%);
    -webkit-backdrop-filter: blur(18px) saturate(115%);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-1.5rem);
    transition: opacity 0.5s var(--ease), transform 0.5s var(--ease), visibility 0.5s;
  }
  .nav__links.is-open { opacity: 1; visibility: visible; transform: none; }
  .nav__link { font-size: var(--step-1); letter-spacing: 0.2em; }
}

/* ---------- 8. Hero ---------- */

.hero {
  position: relative;
  min-height: 100svh;
  display: grid;
  align-items: end;
  overflow: hidden;
  isolation: isolate;
}
.hero__media {
  position: absolute;
  inset: 0;
  z-index: -2;
}
.hero__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Anchored low so the couple rides in the upper half of the frame and the
     names land on the grass below them rather than across their faces. */
  object-position: 50% 68%;
  animation: kenburns 26s var(--ease-in-out) infinite alternate;
}
@keyframes kenburns {
  from { transform: scale(1.06) translate3d(0, 0, 0); }
  to   { transform: scale(1.16) translate3d(-1.5%, -1.5%, 0); }
}
.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  /* Heavy at the foot so the type always wins, lighter across the couple. */
  background:
    linear-gradient(to top,
      var(--ink) 0%,
      rgba(5,12,8,0.94) 18%,
      rgba(5,12,8,0.78) 34%,
      rgba(5,12,8,0.34) 58%,
      rgba(5,12,8,0.30) 78%,
      rgba(5,12,8,0.62) 100%),
    radial-gradient(130% 70% at 50% 100%, rgba(4,48,27,0.6), transparent 62%);
}
.hero__inner {
  padding-block: clamp(6rem, 14vh, 9rem) clamp(4.5rem, 11vh, 7rem);
  text-align: center;
  display: grid;
  justify-items: center;
  gap: clamp(1.25rem, 3vw, 2rem);
}

/* On the photograph, the accent green disappears into the foliage. */
.hero .eyebrow {
  color: var(--bone);
  text-shadow: 0 2px 24px rgba(0,0,0,0.8);
}
.hero .eyebrow::before, .hero .eyebrow::after { opacity: 0.45; }
.hero__names {
  font-size: var(--step-5);
  line-height: 0.92;
  letter-spacing: -0.02em;
  text-shadow: 0 6px 60px rgba(0,0,0,0.55);
}
.hero__names .amp {
  display: block;
  font-size: 0.42em;
  margin-block: 0.06em;
  color: var(--green-300);
}
.hero__meta {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: clamp(0.75rem, 2.5vw, 1.75rem);
  font-size: var(--step--1);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--bone-2);
}
.hero__meta .dot { width: 4px; height: 4px; border-radius: 50%; background: var(--accent); flex: none; }
.hero__actions { display: flex; flex-wrap: wrap; gap: 0.85rem; justify-content: center; }

/* Wrapping the meta line leaves separator dots dangling at the end of a row,
   so below this width it becomes a clean stack instead. */
@media (max-width: 640px) {
  .hero__meta { flex-direction: column; gap: 0.5rem; }
  .hero__meta .dot { display: none; }
  .hero__actions { width: 100%; flex-direction: column; }
  .hero__actions .btn { width: 100%; }
}

/* Parked in the corner so it never collides with the centred buttons. */
.hero__scroll {
  position: absolute;
  left: var(--gutter);
  bottom: clamp(1.25rem, 3vh, 2.25rem);
  display: grid;
  justify-items: start;
  gap: 0.6rem;
  font-size: 0.62rem;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--fg-faint);
  z-index: 2;
}
.hero__scroll i {
  display: block;
  width: 1px; height: 46px;
  background: linear-gradient(to bottom, var(--accent), transparent);
  animation: drip 2.4s var(--ease-in-out) infinite;
  transform-origin: top;
}
/* No room for it beside stacked buttons, or on a short viewport. */
@media (max-width: 640px), (max-height: 640px) {
  .hero__scroll { display: none; }
}
@keyframes drip {
  0%   { transform: scaleY(0); opacity: 0; }
  35%  { transform: scaleY(1); opacity: 1; }
  100% { transform: scaleY(1) translateY(46px); opacity: 0; }
}

/* ---------- 9. Countdown ---------- */

.countdown {
  border-block: 1px solid var(--ink-line);
  background: linear-gradient(180deg, var(--ink-1), var(--ink));
}
.countdown__inner {
  display: grid;
  gap: clamp(1.5rem, 4vw, 3rem);
  padding-block: clamp(2.25rem, 5vw, 3.5rem);
  align-items: center;
  text-align: center;
}
@media (min-width: 880px) {
  .countdown__inner { grid-template-columns: auto 1fr; text-align: left; }
}
.countdown__label {
  font-size: var(--step--1);
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--fg-faint);
}
.countdown__label b {
  display: block;
  font-family: var(--display);
  font-size: var(--step-2);
  font-weight: 300;
  letter-spacing: 0.02em;
  text-transform: none;
  color: var(--fg);
  margin-top: 0.4rem;
}
.countdown__units {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(0.5rem, 2vw, 1.5rem);
}
.cd-unit {
  padding: clamp(0.75rem, 2vw, 1.25rem) 0.5rem;
  border: 1px solid var(--ink-line);
  border-radius: var(--radius);
  background: rgba(18, 137, 76, 0.05);
}
.cd-unit__n {
  display: block;
  font-family: var(--display);
  font-size: clamp(1.9rem, 5vw, 3.2rem);
  line-height: 1;
  font-weight: 300;
  color: var(--green-300);
  font-variant-numeric: tabular-nums;
}
.cd-unit__l {
  display: block;
  margin-top: 0.5rem;
  font-size: 0.62rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--fg-faint);
}
.countdown.is-past .cd-unit__n { color: var(--bone-3); }

/* ---------- 10. Story ---------- */

.story { display: grid; gap: clamp(4.5rem, 12vw, 10rem); }

.beat {
  display: grid;
  gap: clamp(1.75rem, 5vw, 4.5rem);
  align-items: center;
}
@media (min-width: 900px) {
  .beat { grid-template-columns: 1fr 1fr; }
  .beat--flip .beat__media { order: 2; }
  .beat--wide { grid-template-columns: 1.15fr 0.85fr; }
}

.beat__media {
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--ink-2);
  box-shadow: var(--shadow-lift);
}
.beat__media::after {
  content: "";
  position: absolute;
  inset: 0;
  box-shadow: inset 0 0 0 1px rgba(244,242,234,0.08);
  pointer-events: none;
  border-radius: inherit;
}
.beat__media img {
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  transition: transform 1.2s var(--ease), filter 1.2s var(--ease);
  filter: saturate(0.94);
}
.beat__media:hover img { transform: scale(1.035); filter: saturate(1.05); }

/* A photograph that failed twice (see initImageFallback in ui.js). Better a
   quiet framed panel than the browser's broken-image glyph. */
.beat__media.is-broken,
.gallery__item.is-broken {
  background:
    repeating-linear-gradient(135deg, var(--ink-2) 0 12px, var(--ink-3) 12px 24px);
}
.is-broken img { opacity: 0; }

.beat__num {
  font-family: var(--display);
  font-size: var(--step--1);
  letter-spacing: 0.3em;
  color: var(--accent);
  display: block;
  margin-bottom: 0.9rem;
}
.beat__title { font-size: var(--step-3); margin-bottom: 1.25rem; }
.beat__title em { font-style: italic; color: var(--green-300); }
.beat__body { color: var(--fg-muted); max-width: 46ch; }
.beat__caption {
  margin-top: 1.5rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--rule);
  font-size: var(--step--1);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fg-faint);
}

/* A stacked pair of smaller frames for the "ordinary days" beat.
   `align-items: start` matters: the second frame is deliberately dropped down
   the page, and without it the grid would stretch the first frame to match the
   taller row — leaving a strip of empty background below its photograph and
   making the two look like different sizes. Hugging the content keeps both
   images exactly the same height. */
.beat__stack {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(0.75rem, 2vw, 1.25rem);
  align-items: start;
}
.beat__stack .beat__media:nth-child(2) { margin-top: clamp(1.5rem, 5vw, 3.5rem); }
.beat__stack .beat__media img { aspect-ratio: 3 / 4; }

/* Pull quote between beats */
.quote {
  text-align: center;
  padding-block: clamp(3rem, 8vw, 6rem);
}
.quote blockquote {
  margin: 0;
  font-family: var(--display);
  font-size: var(--step-3);
  font-style: italic;
  font-weight: 300;
  line-height: 1.24;
  max-width: 22ch;
  margin-inline: auto;
  color: var(--fg);
}
.quote cite {
  display: block;
  margin-top: 1.75rem;
  font-family: var(--sans);
  font-style: normal;
  font-size: var(--step--1);
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--accent);
}

/* ---------- 11. Gallery ---------- */

.gallery {
  columns: 2;
  column-gap: clamp(0.6rem, 1.6vw, 1.1rem);
}
@media (min-width: 720px)  { .gallery { columns: 3; } }
@media (min-width: 1180px) { .gallery { columns: 4; } }

.gallery__item {
  break-inside: avoid;
  margin-bottom: clamp(0.6rem, 1.6vw, 1.1rem);
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: var(--ink-2);
  border-radius: var(--radius);
  overflow: hidden;
  cursor: zoom-in;
  position: relative;
}
.gallery__item img {
  width: 100%;
  transition: transform 0.9s var(--ease), opacity 0.6s var(--ease);
  filter: saturate(0.92);
}
.gallery__item::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(4,48,27,0.55), transparent 55%);
  opacity: 0;
  transition: opacity 0.5s var(--ease);
}
.gallery__item:hover img, .gallery__item:focus-visible img { transform: scale(1.05); filter: saturate(1.05); }
.gallery__item:hover::after, .gallery__item:focus-visible::after { opacity: 1; }

/* Lightbox
 *
 * The controls each own a row or a column of the grid rather than floating on
 * top of the photograph: close in the corner of the SCREEN, prev and next
 * against the edges, caption underneath. Whatever is left in the middle is
 * the photograph's, so it opens as large as it can without being covered.
 */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 950;

  /* A <dialog> is sized to its contents by the browser and centred with an
     auto margin. These five undo that, so the viewer is the whole viewport. */
  width: auto;
  height: auto;
  max-width: none;
  max-height: none;
  margin: 0;

  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-rows: auto minmax(0, 1fr) auto;
  align-items: center;
  justify-items: center;
  gap: clamp(0.5rem, 1.5vw, 1rem);
  padding: clamp(0.75rem, 2vw, 1.5rem);

  /* Only a thin veil of its own; the blur behind does the darkening. */
  background: rgba(3, 8, 5, 0.35);
  border: 0;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.4s var(--ease), visibility 0.4s;
}
.lightbox.is-open { opacity: 1; visibility: visible; }

/* The page behind, while a photo is open. Without backdrop-filter support this
   still darkens to roughly the same place — it just doesn't blur. */
.lightbox::backdrop {
  background: rgba(3, 8, 5, 0.72);
  backdrop-filter: blur(18px) saturate(115%);
  -webkit-backdrop-filter: blur(18px) saturate(115%);
}

.lightbox img {
  /* Spans the close button's row as well: that row only holds something in the
     third column, so the photograph can use its height without ever meeting
     it — which is worth about 90px of picture on a laptop screen. */
  grid-column: 2;
  grid-row: 1 / span 2;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  border-radius: var(--radius);
  box-shadow: var(--shadow-lift);
  transform: scale(0.96);
  transition: transform 0.45s var(--ease);
}
.lightbox.is-open img { transform: scale(1); }

.lightbox__caption {
  grid-column: 1 / -1;
  grid-row: 3;
  margin: 0;
  max-width: 60ch;
  font-size: var(--step--1);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--fg-muted);
  text-align: center;
}

.lightbox__btn {
  width: 52px; height: 52px;
  display: grid; place-items: center;
  background: rgba(244,242,234,0.06);
  border: 1px solid var(--rule);
  border-radius: 50%;
  color: var(--fg);
  cursor: pointer;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  transition: background 0.3s var(--ease), border-color 0.3s var(--ease);
}
.lightbox__btn:hover { background: var(--green-400); border-color: var(--green-400); color: var(--ink); }
.lightbox__close     { grid-column: 3; grid-row: 1; justify-self: end; align-self: start; }
/* Centred on the picture, not on the leftover row below it. */
.lightbox__btn--prev { grid-column: 1; grid-row: 1 / span 2; justify-self: start; align-self: center; }
.lightbox__btn--next { grid-column: 3; grid-row: 1 / span 2; justify-self: end; align-self: center; }

/* On a phone a column each side would cost the photograph a third of the
   screen, so the two arrows drop to the bottom corners — nearer a thumb, and
   still clear of the picture. */
@media (max-width: 640px) {
  .lightbox {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr) auto auto;
  }
  .lightbox__close     { grid-column: 1; grid-row: 1; }
  /* Here the close button has the whole first row, so the picture keeps to
     the second one. */
  .lightbox img        { grid-column: 1; grid-row: 2; }
  .lightbox__caption   { grid-column: 1; grid-row: 3; }
  .lightbox__btn--prev { grid-column: 1; grid-row: 4; justify-self: start; align-self: center; }
  .lightbox__btn--next { grid-column: 1; grid-row: 4; justify-self: end; align-self: center; }
}

/* ---------- 12. Events ---------- */

.events {
  display: grid;
  gap: clamp(1.25rem, 3vw, 2rem);
}
@media (min-width: 860px) { .events { grid-template-columns: 1fr 1fr; } }

.event-card {
  position: relative;
  padding: clamp(1.75rem, 4vw, 3rem);
  border: 1px solid var(--ink-line);
  border-radius: var(--radius-lg);
  background:
    linear-gradient(160deg, rgba(18,137,76,0.10), rgba(5,12,8,0) 55%),
    var(--ink-1);
  display: grid;
  align-content: start;
  gap: 1.4rem;
  overflow: hidden;
  transition: border-color 0.5s var(--ease), transform 0.5s var(--ease);
}
.event-card:hover { border-color: rgba(31,179,101,0.45); transform: translateY(-4px); }
.event-card__tag {
  justify-self: start;
  font-size: 0.64rem;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  padding: 0.45rem 0.9rem;
  border: 1px solid var(--green-700);
  border-radius: 100px;
  color: var(--green-300);
  background: rgba(4,48,27,0.5);
}
.event-card__tag--muted { border-color: var(--ink-line); color: var(--fg-faint); background: transparent; }
.event-card__title { font-size: var(--step-2); }
.event-card__rows { display: grid; gap: 0.9rem; margin: 0; }
.event-row {
  display: grid;
  grid-template-columns: 7.5rem 1fr;
  gap: 1rem;
  align-items: baseline;
  padding-bottom: 0.9rem;
  border-bottom: 1px solid var(--rule);
}
.event-row:last-child { border-bottom: 0; padding-bottom: 0; }
.event-row dt {
  font-size: 0.66rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--fg-faint);
}
.event-row dd { margin: 0; color: var(--fg); font-weight: 400; }
.event-row dd small { display: block; color: var(--fg-muted); font-weight: 300; margin-top: 0.15rem; }

/* ---------- 13. Forms ---------- */

.card-light {
  background: var(--paper);
  color: var(--ink);
  border-radius: var(--radius-lg);
  padding: clamp(1.75rem, 5vw, 4rem);
  box-shadow: var(--shadow-lift);
  position: relative;
  overflow: hidden;
}
.card-light::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 3px;
  background: linear-gradient(90deg, var(--green-700), var(--green-300), var(--green-700));
}
.card-light h2, .card-light h3 { color: var(--ink); }
.card-light .eyebrow { color: var(--green-600); }
.card-light .prose, .card-light .lede { color: #4A554E; }

.form { display: grid; gap: clamp(1.1rem, 2.5vw, 1.6rem); }
.form__grid { display: grid; gap: inherit; }
@media (min-width: 680px) { .form__grid--2 { grid-template-columns: 1fr 1fr; } }

/* align-content:start stops a field's rows from stretching to match a taller
   neighbour in the same grid row — otherwise the currency <select> grows to
   cover the height of the amount field's hint line beside it. */
.field { display: grid; gap: 0.5rem; align-content: start; }

/* Fieldsets carry UA border/padding and an intrinsic min-width that can force
   overflow, so reset them here rather than inline on every element. */
fieldset.field { border: 0; padding: 0; margin: 0; min-inline-size: 0; }

/* A rendered <legend> is laid out outside the fieldset's content box, so the
   grid `gap` never reaches it. It needs its own spacing. */
fieldset.field > legend.field__label { padding: 0; margin-bottom: 0.85rem; float: none; }

.field__label {
  font-size: 0.68rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  font-weight: 600;
  color: #3A443E;
}
.field__label .req { color: var(--green-600); }
.field__hint { font-size: var(--step--1); color: #6B756E; }

.input, .select, .textarea {
  width: 100%;
  padding: 0.9rem 1rem;
  background: #FFFFFF;
  border: 1px solid #D5D2C6;
  border-radius: var(--radius);
  color: var(--ink);
  font-weight: 400;
  transition: border-color 0.3s var(--ease), box-shadow 0.3s var(--ease);
  appearance: none;
}
.input::placeholder, .textarea::placeholder { color: #9AA29C; }
.input:hover, .select:hover, .textarea:hover { border-color: #A9B0A6; }
.input:focus, .select:focus, .textarea:focus {
  outline: none;
  border-color: var(--green-500);
  box-shadow: 0 0 0 3px rgba(31,179,101,0.18);
}
.textarea { min-height: 7.5rem; resize: vertical; line-height: 1.6; }
.select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23566' stroke-width='1.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1rem center;
  padding-right: 2.5rem;
}
.input[aria-invalid="true"], .select[aria-invalid="true"], .textarea[aria-invalid="true"] {
  border-color: #C0392B;
  box-shadow: 0 0 0 3px rgba(192,57,43,0.14);
}
.field__error {
  font-size: var(--step--1);
  color: #A5281B;
  display: none;
}
.field__error.is-shown { display: block; }

/* Segmented choices, rendered as pills */
.choices { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.choice { position: relative; }
.choice input {
  position: absolute;
  opacity: 0;
  width: 100%; height: 100%;
  margin: 0;
  cursor: pointer;
}
.choice span {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.75rem 1.15rem;
  border: 1px solid #D5D2C6;
  border-radius: 100px;
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: 0.04em;
  color: #4A554E;
  background: #fff;
  transition: all 0.3s var(--ease);
  cursor: pointer;
  user-select: none;
}
.choice input:hover + span { border-color: #A9B0A6; }
.choice input:checked + span {
  background: var(--green-700);
  border-color: var(--green-700);
  color: var(--bone);
  box-shadow: 0 6px 18px -8px rgba(10,90,51,0.8);
}
.choice input:focus-visible + span {
  outline: 2px solid var(--green-500);
  outline-offset: 2px;
}
.choice__dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.35;
  flex: none;
}
.choice input:checked + span .choice__dot { opacity: 1; background: var(--green-200); }

.honeypot {
  position: absolute !important;
  left: -9999px !important;
  width: 1px; height: 1px;
  opacity: 0;
  pointer-events: none;
}

.form__footer {
  display: grid;
  gap: 1rem;
  padding-top: 0.5rem;
}
@media (min-width: 680px) {
  .form__footer { grid-template-columns: 1fr auto; align-items: center; }
}
.form__note { font-size: var(--step--1); color: #6B756E; margin: 0; }

.form-status {
  padding: 1rem 1.15rem;
  border-radius: var(--radius);
  font-size: var(--step--1);
  border: 1px solid transparent;
  display: none;
}
.form-status.is-shown { display: block; }
.form-status--error { background: #FDECEA; border-color: #F1B0A8; color: #8A2318; }
.form-status--ok    { background: #E7F7EE; border-color: #A5DFC0; color: #0A5A33; }

/* Success panel that replaces the form */
.result {
  display: none;
  text-align: center;
  padding: clamp(1rem, 4vw, 2rem) 0;
}
.result.is-shown { display: block; }
.result__seal {
  width: 76px; height: 76px;
  margin: 0 auto 1.75rem;
  border-radius: 50%;
  border: 1px solid var(--green-500);
  display: grid;
  place-items: center;
  color: var(--green-600);
  animation: pop 0.6s var(--ease) both;
}
@keyframes pop {
  from { transform: scale(0.6); opacity: 0; }
  to   { transform: scale(1); opacity: 1; }
}
.result__ref {
  display: inline-block;
  margin-top: 1.5rem;
  padding: 0.7rem 1.4rem;
  border: 1px dashed var(--green-500);
  border-radius: var(--radius);
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: var(--step-1);
  letter-spacing: 0.14em;
  color: var(--green-700);
  background: #F1FAF5;
}

/* ---------- 14. Pledge page specifics ---------- */

.page-hero {
  position: relative;
  padding-block: clamp(8rem, 18vh, 12rem) clamp(3rem, 8vw, 5rem);
  overflow: hidden;
  isolation: isolate;
  text-align: center;
}
.page-hero__media { position: absolute; inset: 0; z-index: -2; }
.page-hero__media img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 32%; }
.page-hero__scrim {
  position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(to bottom, rgba(5,12,8,0.86), rgba(5,12,8,0.92) 55%, var(--ink));
}

.methods { display: grid; gap: clamp(1rem, 2.5vw, 1.5rem); }
@media (min-width: 780px) { .methods { grid-template-columns: repeat(3, 1fr); } }

.method {
  border: 1px solid var(--ink-line);
  border-radius: var(--radius-lg);
  padding: clamp(1.4rem, 3vw, 2rem);
  background: var(--ink-1);
  display: grid;
  gap: 1rem;
  align-content: start;
  transition: border-color 0.4s var(--ease), background 0.4s var(--ease);
}
.method:hover { border-color: rgba(31,179,101,0.4); }
.method__head { display: flex; align-items: center; gap: 0.9rem; }
.method__logo {
  width: 66px;
  height: 40px;
  flex: none;
  border-radius: 9px;
  display: block;
  box-shadow: 0 2px 10px -4px rgba(0, 0, 0, 0.6);
}
.method__name { font-family: var(--display); font-size: var(--step-1); }
.method__rows { display: grid; gap: 0.7rem; margin: 0; }
.method__row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  padding-bottom: 0.65rem;
  border-bottom: 1px solid var(--rule);
  font-size: var(--step--1);
}
.method__row:last-child { border-bottom: 0; padding-bottom: 0; }
.method__row dt { color: var(--fg-faint); letter-spacing: 0.08em; text-transform: uppercase; font-size: 0.64rem; }
.method__row dd { margin: 0; text-align: right; font-weight: 400; color: var(--fg); }
.method__row dd.mono { font-family: ui-monospace, "SF Mono", Menlo, monospace; letter-spacing: 0.04em; }

.copy-btn {
  background: none;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 0.3rem 0.6rem;
  font-size: 0.62rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--fg-muted);
  cursor: pointer;
  transition: all 0.3s var(--ease);
  margin-left: 0.5rem;
  vertical-align: middle;
}
.copy-btn:hover { border-color: var(--green-400); color: var(--green-300); }
.copy-btn.is-done { background: var(--green-400); border-color: var(--green-400); color: var(--ink); }

.steps { counter-reset: step; display: grid; gap: 1.5rem; list-style: none; padding: 0; margin: 0; }
@media (min-width: 860px) {
  .steps--row { grid-template-columns: repeat(3, 1fr); gap: clamp(1.5rem, 4vw, 3rem); }
}
.steps li {
  counter-increment: step;
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 1.15rem;
  align-items: start;
}
.steps li::before {
  content: counter(step, decimal-leading-zero);
  font-family: var(--display);
  font-size: var(--step-1);
  color: var(--accent);
  line-height: 1;
  padding-top: 0.15rem;
}
.steps b { display: block; font-weight: 500; color: var(--fg); margin-bottom: 0.25rem; }
.steps span { color: var(--fg-muted); font-size: var(--step--1); }

/* Payment details rendered on a light card (inside the pledge form + receipt) */
.pay-inline {
  border: 1px solid #D8E5DD;
  border-left: 3px solid var(--green-500);
  border-radius: var(--radius);
  background: #F1FAF5;
  padding: clamp(1.1rem, 3vw, 1.6rem);
  display: grid;
  gap: 1rem;
  text-align: left;
}
.pay-inline__title {
  margin: 0;
  font-size: 0.68rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--green-700);
  display: flex;
  align-items: center;
  gap: 0.6rem;
}
.pay-inline__logo {
  width: 44px; height: 27px;
  border-radius: 6px;
  flex: none;
  display: block;
}
.pay-inline__rows { display: grid; gap: 0.65rem; margin: 0; }
.pay-inline__row {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.5rem 1rem;
  padding-bottom: 0.6rem;
  border-bottom: 1px solid #DCE9E2;
}
.pay-inline__row:last-child { border-bottom: 0; padding-bottom: 0; }
.pay-inline__row dt {
  font-size: 0.64rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: #5C6B63;
}
.pay-inline__row dd {
  margin: 0;
  color: var(--ink);
  font-weight: 500;
  text-align: right;
  display: flex;
  align-items: center;
  gap: 0.25rem;
}
.pay-inline__row dd.mono { font-family: ui-monospace, "SF Mono", Menlo, monospace; letter-spacing: 0.02em; }
.pay-inline__note { margin: 0; font-size: var(--step--1); color: #4A554E; line-height: 1.6; }
.pay-inline__note strong { color: var(--green-700); }

.copy-btn--light { border-color: #C2D4CA; color: #5C6B63; }
.copy-btn--light:hover { border-color: var(--green-500); color: var(--green-700); }
.copy-btn--light.is-done { background: var(--green-500); border-color: var(--green-500); color: #fff; }

/* ---------- 15. Invitation card ---------- */

.invite {
  display: grid;
  gap: clamp(1.75rem, 5vw, 4rem);
  align-items: center;
}
@media (min-width: 900px) { .invite { grid-template-columns: 0.85fr 1.15fr; } }
.invite__frame {
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-lift);
  border: 1px solid var(--ink-line);
}

/* ---------- 16. Footer ---------- */

.footer {
  border-top: 1px solid var(--ink-line);
  background: linear-gradient(180deg, var(--ink), #030805);
  padding-block: clamp(3rem, 7vw, 5rem) clamp(2rem, 4vw, 3rem);
}
.footer__grid {
  display: grid;
  gap: clamp(2rem, 5vw, 3.5rem);
  padding-bottom: clamp(2rem, 5vw, 3.5rem);
  border-bottom: 1px solid var(--rule);
}
@media (min-width: 780px) { .footer__grid { grid-template-columns: 1.4fr 1fr 1fr; } }
.footer__names {
  font-family: var(--display);
  font-size: var(--step-2);
  line-height: 1.1;
}
.footer__col h4 {
  font-family: var(--sans);
  font-size: 0.64rem;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--fg-faint);
  margin-bottom: 1.1rem;
  font-weight: 600;
}
.footer__col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.65rem; }
.footer__col a { color: var(--fg-muted); font-size: var(--step--1); transition: color 0.3s var(--ease); }
.footer__col a:hover { color: var(--green-300); }
.footer__bottom {
  padding-top: 1.75rem;
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  justify-content: space-between;
  align-items: center;
  font-size: 0.68rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--fg-faint);
}

/* ---------- 17. Scroll reveal ---------- */

/* Reveal-on-scroll is opt-in, gated behind the .js class that ui.js sets as
   soon as it runs. If the script is blocked, fails, or never arrives on a bad
   connection, none of these rules apply and the content — the whole Our Story
   section included — simply renders visible instead of staying clipped away. */
.js .reveal {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 1s var(--ease), transform 1s var(--ease);
  transition-delay: var(--reveal-delay, 0ms);
  will-change: opacity, transform;
}
.js .reveal.is-in { opacity: 1; transform: none; }

.js .reveal-clip {
  clip-path: inset(0 0 100% 0);
  transition: clip-path 1.2s var(--ease);
  transition-delay: var(--reveal-delay, 0ms);
}
.js .reveal-clip.is-in { clip-path: inset(0 0 0 0); }

@media (prefers-reduced-motion: reduce) {
  .js .reveal, .js .reveal-clip { opacity: 1; transform: none; clip-path: none; }
  .hero__media img { animation: none; transform: scale(1.06); }
  .hero__scroll i { animation: none; }
}

/* ---------- 18. Utilities ---------- */

.center { text-align: center; }
.center .lede, .center .prose { margin-inline: auto; }
.stack-sm { display: grid; gap: 0.75rem; }
.stack    { display: grid; gap: 1.5rem; }
.stack-lg { display: grid; gap: clamp(2rem, 5vw, 3.5rem); }
.mt-lg { margin-top: clamp(2rem, 5vw, 3.5rem); }
.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
.rule { height: 1px; background: var(--rule); border: 0; margin: 0; }
.no-js-only { display: none; }

/* ---------- 19. Print ---------- */
/* Guests print the pledge receipt, so make that one thing come out cleanly. */

@media print {
  :root { --shadow-lift: none; }
  body { background: #fff; color: #000; }
  body::after { display: none; }
  .nav, .footer, .hero__scroll, .lightbox, .page-hero__media, .page-hero__scrim,
  .section#methods, .btn, .copy-btn, .skip-link { display: none !important; }
  .section { padding-block: 0; background: none !important; }
  .card-light { box-shadow: none; padding: 0; }
  .card-light::before { display: none; }
  .page-hero { padding-block: 0 1rem; color: #000; }
  .page-hero .lede, .page-hero .eyebrow { color: #333; }
  .result { display: block !important; }
  .result__ref { border-color: #000; color: #000; background: none; }
  .pay-inline { background: none; border-color: #999; border-left-color: #000; break-inside: avoid; }
  a[href]::after { content: ""; }
}
