/* ============================================================================
   DUBE MINISTRIES — black & gold
   ============================================================================
   The ground is a WARM near-black (a trace of red and yellow in it), not the
   blue-black of the sibling wedding build. The scene film is lit with a warm
   stage wash, and a blue-black page under warm footage reads as two different
   images bolted together.
   ========================================================================== */

:root{
  /* warm black field — every one of these has more red than blue */
  --ink-950:#050403;
  --ink-900:#0B0906;
  --ink-850:#100C07;
  --ink-800:#171108;
  --ink-700:#20180C;

  /* gold */
  --gold:#C9A24B;
  --gold-hi:#E8CC86;
  --gold-pale:#F3E2B6;
  --gold-deep:#8A6524;
  --gold-line:rgba(201,162,75,.32);
  --gold-line-soft:rgba(201,162,75,.17);

  /* the amber of the stage wash — the accent, used sparingly */
  --amber:#E0A64A;
  --amber-soft:rgba(224,166,74,.14);

  /* ink on the black */
  --paper:#F4EDE0;
  --paper-soft:rgba(244,237,224,.76);
  --paper-mute:rgba(244,237,224,.52);
  --paper-faint:rgba(244,237,224,.30);

  --warn:#E8B45C;

  --ease:cubic-bezier(.22,1,.36,1);
  --serif:'Cormorant Garamond',Georgia,serif;
  --sans:'Jost',-apple-system,'Segoe UI',sans-serif;

  --maxw:560px;
  --maxw-wide:640px;

  /* Keep in step with films.dissolveMs in config.js — the fade must still be
     running while the scene film plays underneath it. */
  --dissolve:1400ms;
}

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

/* The `hidden` attribute is applied by the UA stylesheet as `display:none`,
   which ANY author `display` declaration silently overrides. Several things
   here are flex or grid containers that are ALSO toggled with `hidden` — the
   lightbox, the hero type, the scroll hint, the RSVP confirmation, the whole
   gallery section, the partner card. The lightbox is `position:fixed;
   inset:0; z-index:90`, so without this rule it sits invisibly over the entire
   page and swallows every click on the site, "Tap To Open" included. This rule
   has to beat all of them. */
[hidden]{ display:none !important }

html,body{margin:0;padding:0}
html{-webkit-text-size-adjust:100%; scroll-behavior:auto}

body{
  background:var(--ink-900);
  color:var(--paper);
  font-family:var(--serif);
  font-weight:300;
  line-height:1.6;
  overflow-x:hidden;
  -webkit-font-smoothing:antialiased;
}
img{max-width:100%; display:block}
button{font:inherit; color:inherit; cursor:pointer; border:0; background:none}
a{color:var(--gold-hi); text-decoration:none}

/* The shared <symbol> sheet. NOT display:none — that breaks <use> references
   in Safari. Collapsed to zero instead. */
.svg-defs{ position:absolute; width:0; height:0; overflow:hidden }

html.intro-lock, html.intro-lock body{
  overflow:hidden !important; height:100%;
  touch-action:none; overscroll-behavior:none;
}

/* ── type primitives ─────────────────────────────────────────────────────── */
.eyebrow{
  font-family:var(--sans); font-weight:200;
  font-size:clamp(.6rem,2.4vw,.68rem);
  letter-spacing:.42em; text-indent:.42em; text-transform:uppercase;
  color:var(--gold-hi); opacity:.9; margin:0;
}
.micro{
  font-family:var(--sans); font-weight:200;
  font-size:clamp(.6rem,2.3vw,.66rem);
  letter-spacing:.24em; text-indent:.24em; text-transform:uppercase;
  color:var(--paper-mute); margin:0;
}
.body{
  font-size:clamp(.95rem,3.7vw,1.02rem); line-height:1.78;
  color:var(--paper-soft); margin:0; font-weight:300;
}
.lede{
  font-size:clamp(1rem,3.9vw,1.1rem); line-height:1.75;
  color:var(--paper-soft); font-style:italic; margin:0; max-width:48ch;
}

/* The display face. The card artwork sets "WORSHIP" in an engraved Trajan-
   style capital; light Cormorant in wide-tracked caps is the nearest thing
   available offline, and it keeps the page to a single serif.

   line-height and padding are NOT cosmetic here: `background-clip:text` only
   paints inside the element's box, so any ink that overshoots renders
   transparent rather than clipped. Caps overshoot less than a script face, but
   the tracking pushes the last letter's right sidebearing out, and a tight
   line-height still eats the cap-height on the foil. */
.display{
  font-family:var(--serif); font-weight:300;
  font-size:clamp(1.9rem,8vw,2.7rem);
  line-height:1.22;
  letter-spacing:.14em; text-indent:.14em; text-transform:uppercase;
  padding:.14em .12em .16em;
  margin:0;
}
.display.xl{ font-size:clamp(2.2rem,9.5vw,3.4rem) }

/* Foil for dark grounds: luminous end to end, so the sweep shifts WARMTH
   rather than brightness and contrast can never drop out mid-cycle. Deep
   bronze stops go muddy on black; a near-white highlight blows out.

   NO `filter` on foil text, ever. A filter promotes the element to its own
   composited layer, which Chrome rasterises once and then rescales — on type
   already painted through background-clip, that is permanently soft
   letterforms. The glow is not worth blurring every heading for. */
.foil{
  background-image:linear-gradient(100deg,
    #B98F3C 0%, #D6B166 14%, #EFD79E 30%,
    #FFF6DC 46%, #EFD79E 62%, #D0A957 80%, #B98F3C 100%);
  background-size:260% 100%;
  -webkit-background-clip:text; background-clip:text;
  -webkit-text-fill-color:transparent; color:transparent;
  animation:foilSweep 11s ease-in-out infinite;
  text-rendering:geometricPrecision;
}
@keyframes foilSweep{
  0%,100%{background-position:0% 50%}
  50%{background-position:100% 50%}
}

.rule{
  display:block; width:min(230px,62%); height:1px; position:relative;
  background:linear-gradient(90deg,transparent,var(--gold-line),transparent);
  margin:.2rem 0 .3rem;
}
.rule::after{
  content:""; position:absolute; left:50%; top:50%;
  width:5px; height:5px; transform:translate(-50%,-50%) rotate(45deg);
  background:var(--gold); box-shadow:0 0 8px rgba(201,162,75,.6);
}

/* the dove, wherever it appears */
.dove-mark svg,
.ec-seal svg,.done-seal svg,.fin-seal svg,.cd-past-seal svg{
  width:100%; height:100%; display:block;
  fill:url(#goldFace);
}
.dove-eye{ fill:var(--ink-900) }

/* ── stages ──────────────────────────────────────────────────────────────── */
.stage{
  position:relative; width:100%;
  min-height:62svh;                /* gradient grounds may hug their content */
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  text-align:center; overflow:hidden;
  padding:clamp(3.4rem,9vh,5rem) clamp(1.4rem,6vw,4rem);
}
.stage>.inner{
  max-width:var(--maxw); width:100%; position:relative; z-index:2;
  display:flex; flex-direction:column; align-items:center;
  gap:clamp(.5rem,1.5vh,.85rem);
}
.stage>.inner.wide{ max-width:var(--maxw-wide) }

/* Three-pass warm-black grounds. Every bloom is amber, never blue: a cool
   highlight on this palette reads as a colour cast rather than as stage light.
   Backgrounds are gradients ON the section, so the sections may hug their
   content — that is what keeps dead space off the page. */
.bg-ink{
  background:
    radial-gradient(92% 58% at 50% 0%,    rgba(224,166,74,.13) 0%, rgba(224,166,74,0) 62%),
    radial-gradient(120% 78% at 14% 100%, rgba(201,162,75,.10) 0%, rgba(201,162,75,0) 58%),
    linear-gradient(180deg,#0D0A06 0%,#120D07 48%,#080604 100%);
}
.bg-ink-deep{
  background:
    radial-gradient(88% 54% at 50% 4%,    rgba(224,166,74,.10) 0%, rgba(224,166,74,0) 60%),
    radial-gradient(130% 84% at 88% 100%, rgba(201,162,75,.075) 0%, rgba(201,162,75,0) 58%),
    linear-gradient(180deg,#080604 0%,#0C0906 52%,#050403 100%);
}
.bg-warm{
  background:
    radial-gradient(96% 62% at 50% 2%,    rgba(240,185,92,.17) 0%, rgba(240,185,92,0) 64%),
    radial-gradient(122% 80% at 20% 96%,  rgba(201,162,75,.14) 0%, rgba(201,162,75,0) 56%),
    linear-gradient(180deg,#0E0A06 0%,#191106 50%,#0A0705 100%);
}

/* a woven tooth you feel more than see */
.stage::before{
  content:""; position:absolute; inset:0; z-index:0; pointer-events:none;
  opacity:.55;
  background-image:
    repeating-linear-gradient(90deg,rgba(255,240,214,.015) 0 1px,transparent 1px 3px),
    repeating-linear-gradient(0deg, rgba(0,0,0,.055)       0 1px,transparent 1px 3px);
}
/* feathered seam so neighbouring scenes melt instead of banding */
.stage::after{
  content:""; position:absolute; left:0; right:0; bottom:0;
  height:clamp(52px,10vh,110px); z-index:0; pointer-events:none;
  background:linear-gradient(180deg,rgba(5,4,3,0),rgba(5,4,3,.55));
}

/* ── reveals ─────────────────────────────────────────────────────────────── */
.reveal{
  opacity:0; transform:translateY(18px); filter:blur(4px);
  transition:opacity 1.4s var(--ease), transform 1.7s var(--ease), filter 1.4s var(--ease);
  will-change:opacity,transform;
}
/* `filter:none`, NOT `blur(0)`. A zero-radius blur is still an ACTIVE filter,
   so the element keeps its composited layer and every gold foil heading stays
   permanently soft. `none` drops the layer and the type snaps back sharp. */
.reveal.in{ opacity:1; transform:none; filter:none; will-change:auto }

/* ══════════════════ 1 · OPENING ══════════════════ */
.opening-scene{
  position:relative; height:100svh; height:100dvh; overflow:hidden;
  background:var(--ink-950); cursor:pointer;
}
.opening-sticky{ position:absolute; inset:0; display:flex; align-items:center; justify-content:center; overflow:hidden }
.opening-video{
  position:absolute; inset:0; width:100%; height:100%;
  object-fit:cover; pointer-events:none; background:var(--ink-950);
}
#sceneVideo{ z-index:1 }                                  /* second film, beneath */
#cardVideo.card-video{ z-index:2; transition:opacity var(--dissolve) cubic-bezier(.42,0,.35,1) }
#cardVideo.card-video.faded{ opacity:0 }                  /* the cross-dissolve */

/* ── the scrim ────────────────────────────────────────────────────────────
   A genuine graded scrim on the film, NOT a box behind the words. A dark
   panel would bleed visibly against the warm footage; grading the frame reads
   as the stage falling into shadow.

   Both variants are built against measured luminance of the final frame
   (mean Y, 0–255, by band):

     LANDSCAPE  face 20–40% = 128–137     bottom 70–100% centre = 17–18
     PORTRAIT   face 10–40% =  86–117     bottom 60–100%        = 15–22

   So both stay near-transparent across the face band and ramp hard below it,
   where the type lives. */
.hero-scrim{
  position:absolute; inset:0; z-index:3; pointer-events:none;
  background:
    radial-gradient(118% 74% at 50% 38%, rgba(0,0,0,0) 44%, rgba(8,5,3,.48) 100%),
    linear-gradient(180deg,
      rgba(8,5,3,.52) 0%, rgba(8,5,3,.12) 14%, rgba(8,5,3,0) 34%,
      rgba(8,5,3,.30) 54%, rgba(8,5,3,.74) 74%, rgba(8,5,3,.94) 100%);
}
/* Portrait: the face sits higher in the frame and the dark suit fills the
   lower two-thirds, so the ramp starts a little earlier and finishes deeper. */
html:not(.is-wide) .hero-scrim{
  background:
    radial-gradient(120% 68% at 50% 30%, rgba(0,0,0,0) 46%, rgba(8,5,3,.42) 100%),
    linear-gradient(180deg,
      rgba(8,5,3,.44) 0%, rgba(8,5,3,.08) 16%, rgba(8,5,3,0) 36%,
      rgba(8,5,3,.28) 52%, rgba(8,5,3,.70) 70%, rgba(8,5,3,.95) 100%);
}

/* ── buffering gate ──────────────────────────────────────────────────────
   The prompt is withheld until BOTH films are wholly in memory. Tapping into
   an unbuffered film gives a dead button — play() on an empty element sticks
   at currentTime 0 and never recovers. This is safe to make strict only
   because readiness cannot hang: a fetch that fails or stalls for 30s falls
   back to streaming and opens the gate anyway (see initOpening). */
.film-loader{
  position:absolute; left:50%; bottom:clamp(126px,22vh,190px);
  transform:translateX(-50%); z-index:7;
  display:flex; flex-direction:column; align-items:center; gap:.7rem;
  pointer-events:none;                     /* never swallows a tap */
  transition:opacity .7s var(--ease), transform .7s var(--ease);
}
.film-loader.gone{ opacity:0; transform:translateX(-50%) translateY(6px) }
.loader-ring{ width:clamp(46px,11vw,58px); height:clamp(46px,11vw,58px); overflow:visible }
.lr-track{ fill:none; stroke:rgba(232,204,134,.16); stroke-width:2.4 }
/* NOTE: the −90° start lives in the SVG transform ATTRIBUTE, never in CSS.
   A CSS transform-origin would stack on top of it and skew the arc. */
.lr-arc{
  fill:none; stroke:var(--gold-hi); stroke-width:2.4; stroke-linecap:round;
  transition:stroke-dashoffset .45s linear;
}
.loader-pct{
  font-family:var(--serif); font-weight:300; font-size:.98rem;
  letter-spacing:.06em; color:#FBF5E9;
  text-shadow:0 2px 12px rgba(0,0,0,.9);
}
.loader-label{
  font-family:var(--sans); font-weight:200;
  font-size:.56rem; letter-spacing:.34em; text-indent:.34em; text-transform:uppercase;
  color:var(--paper-mute); text-shadow:0 2px 10px rgba(0,0,0,.9);
  text-align:center; padding:0 1rem;
}

/* The card artwork is dark and busy, so a bare light label vanishes into it.
   The prompt needs its own contrasting surface. */
.tap-cue{
  position:absolute; left:50%; bottom:clamp(58px,12vh,104px);
  transform:translateX(-50%); z-index:8;
  opacity:0; pointer-events:none;
  transition:opacity .8s var(--ease);
}
.opening-scene.is-ready .tap-cue{ opacity:1; pointer-events:auto }
.film-cue{ transition:opacity .9s var(--ease), transform .9s var(--ease) }
.tap-cue .label{
  display:inline-block;
  font-family:var(--sans); font-weight:200;
  font-size:.66rem; letter-spacing:.38em; text-indent:.38em; text-transform:uppercase;
  color:#FCF4E4; padding:.85rem 1.7rem; border-radius:999px;
  background:linear-gradient(180deg,rgba(36,25,12,.88),rgba(11,9,6,.92));
  border:1px solid rgba(232,204,134,.55);
  backdrop-filter:blur(3px);
  animation:tapBreathe 3s ease-in-out infinite;
}
@keyframes tapBreathe{
  0%,100%{ box-shadow:0 12px 34px -14px rgba(0,0,0,.85), 0 0 0 6px rgba(232,204,134,.10) }
  50%    { box-shadow:0 12px 34px -14px rgba(0,0,0,.85), 0 0 0 16px rgba(232,204,134,0) }
}
.opening-scene.is-playing .film-cue{ opacity:0; transform:translateX(-50%) scale(.94) }

/* ── hero type ────────────────────────────────────────────────────────────
   NOT the wedding's flanking columns. That footage had clean negative space
   either side of the couple; this footage has none — congregation fills both
   sides in landscape, and a dark suit fills the centre in portrait. There is
   nothing to flank into.

   So: ONE stack, anchored LOW, in a column narrow enough to stay inside the
   dark centre of the landscape frame. At 1280px the column is 520px = 40.6%
   of the frame, centred — x 29.7% to 70.3% — which is exactly the band
   measured at mean luma 17–18. On wider screens the fixed cap narrows it
   further, so it only gets safer. Nothing crosses the face in either
   orientation. */
.hero-type{
  position:absolute; inset:0; z-index:5; pointer-events:none;
  display:flex; align-items:flex-end; justify-content:center;
  text-align:center;
  padding:0 1.3rem clamp(2.1rem,6.5vh,3.6rem);
}
.ht-stack{
  display:flex; flex-direction:column; align-items:center;
  gap:clamp(.26rem,1vh,.5rem);
  width:100%; max-width:min(520px,92vw);
}
/* Opacity and transform only — no blur. A filter on foil type leaves it
   permanently soft (see .foil above and revealText() in main.js). */
.hero-type [data-r]{
  opacity:0; transform:translateY(16px);
  transition:opacity 1.15s var(--ease), transform 1.4s var(--ease);
}
.ht-eyebrow,.ht-kind,.ht-with,.ht-date,.ht-welcome,.ht-pillars{
  font-family:var(--sans); font-weight:200; margin:0;
  text-transform:uppercase; color:#F2E9D8;
  text-shadow:0 2px 14px rgba(0,0,0,.9), 0 1px 3px rgba(0,0,0,.7);
}
.ht-eyebrow{ font-size:clamp(.55rem,2.3vw,.63rem); letter-spacing:.44em; text-indent:.44em; color:var(--gold-hi) }
.ht-kind   { font-size:clamp(.62rem,2.7vw,.74rem); letter-spacing:.34em; text-indent:.34em }
.ht-title{
  font-family:var(--serif); font-weight:300;
  font-size:clamp(2.6rem,13vw,3.9rem);
  line-height:1.16; letter-spacing:.15em; text-indent:.15em; text-transform:uppercase;
  padding:.12em .1em .14em;
}
.ht-pillars{
  font-size:clamp(.5rem,2.1vw,.58rem); letter-spacing:.26em; text-indent:.26em;
  color:var(--gold-hi); opacity:.92;
}
.ht-with{
  font-family:var(--serif); font-weight:300; text-transform:none;
  font-size:clamp(1.05rem,4.4vw,1.3rem); letter-spacing:.05em;
  color:#FBF5E9;
}
.ht-date   { font-size:clamp(.56rem,2.4vw,.64rem); letter-spacing:.3em; text-indent:.3em; color:var(--paper-soft) }
.ht-welcome{
  font-size:clamp(.55rem,2.3vw,.62rem); letter-spacing:.36em; text-indent:.36em;
  color:var(--gold-hi);
  padding-top:.5rem; margin-top:.15rem;
  border-top:1px solid var(--gold-line-soft);
}
.ht-orn{ display:block; width:120px; height:9px; position:relative; margin:.15rem 0 }
.ht-orn::before,.ht-orn::after{
  content:""; position:absolute; top:50%; width:44px; height:1px;
  background:linear-gradient(90deg,transparent,rgba(232,204,134,.72));
}
.ht-orn::before{ left:0 }
.ht-orn::after{ right:0; transform:scaleX(-1) }
.ht-orn i{
  position:absolute; left:50%; top:50%; width:6px; height:6px;
  transform:translate(-50%,-50%) rotate(45deg);
  background:var(--gold-hi); box-shadow:0 0 10px rgba(232,204,134,.8);
}

.scroll-hint{
  position:absolute; left:50%; bottom:1.4rem; transform:translateX(-50%);
  z-index:7; display:flex; flex-direction:column; align-items:center; gap:.45rem;
  opacity:0; transition:opacity 1.2s var(--ease);
  font-family:var(--sans); font-weight:200; font-size:.56rem;
  letter-spacing:.36em; text-indent:.36em; text-transform:uppercase; color:var(--paper-mute);
}
.scroll-hint.in{ opacity:1 }
.scroll-hint i{
  width:1px; height:30px; display:block;
  background:linear-gradient(180deg,transparent,rgba(232,204,134,.85));
  animation:hintDrop 2.4s ease-in-out infinite;
}
@keyframes hintDrop{ 0%,100%{transform:scaleY(.5); opacity:.4} 50%{transform:scaleY(1); opacity:1} }

/* ══════════════════ 2 · COUNTDOWN ══════════════════ */
.clock{ width:100% }

/* ── the flip clock ──────────────────────────────────────────────────────
   Four split-flap leaves. Each unit stacks four layers:

     .f-upper       top half of the NEW value   (revealed as the leaf falls)
     .f-lower       bottom half of the OLD value (covered as the leaf rises)
     .f-fold-upper  top half of the OLD value    rotates  0 → -90°
     .f-fold-lower  bottom half of the NEW value rotates 90° →  0°

   Every layer clips a FULL-height glyph — `.f-upper` shows its top half,
   `.f-lower` its bottom half — so the halves meet on the seam the way a real
   split-flap does, instead of being two separate pieces of type.

   The folds are visibility:hidden unless mid-flip. That is not tidiness: in a
   backgrounded tab CSS animations do not run at all, and a fold left visible
   in its resting state would sit there showing a stale value forever. */
.clock-flip{
  display:grid; grid-template-columns:repeat(4,1fr);
  gap:clamp(.4rem,2.2vw,1rem);
  margin-top:clamp(1rem,3.5vh,1.8rem);
  --fh:clamp(56px,16vw,88px);
}
.flip-unit{ display:flex; flex-direction:column; align-items:center; gap:.6rem; min-width:0 }

.flip{
  position:relative; width:100%; height:var(--fh);
  perspective:340px; perspective-origin:50% 50%;
  border-radius:5px;
  font-family:var(--serif); font-weight:300;
  font-size:calc(var(--fh) * .62); letter-spacing:.02em;
  box-shadow:0 18px 34px -22px rgba(0,0,0,.95), 0 0 0 1px var(--gold-line-soft);
}
.f-half{
  position:absolute; left:0; right:0; height:50%; overflow:hidden;
  backface-visibility:hidden; -webkit-backface-visibility:hidden;
}
.f-half > i{
  position:absolute; left:0; right:0;
  height:var(--fh); line-height:var(--fh);
  font-style:normal; text-align:center;
  color:#FCF6E8; text-shadow:0 2px 14px rgba(0,0,0,.55);
}
/* upper leaves: lighter, lit from above */
.f-upper,.f-fold-upper{
  top:0; border-radius:5px 5px 0 0;
  background:linear-gradient(180deg,#241a0D 0%,#191207 100%);
}
.f-upper > i,.f-fold-upper > i{ top:0 }
/* lower leaves: darker, in the shadow of the fold */
.f-lower,.f-fold-lower{
  bottom:0; border-radius:0 0 5px 5px;
  background:linear-gradient(180deg,#120C06 0%,#1B1309 100%);
}
.f-lower > i,.f-fold-lower > i{ bottom:0 }

/* the hinge line where the two leaves meet */
.f-upper::after,.f-fold-upper::after{
  content:""; position:absolute; left:0; right:0; bottom:0; height:1px;
  background:rgba(0,0,0,.75); box-shadow:0 1px 0 rgba(232,204,134,.10);
}

.f-fold{ visibility:hidden; z-index:2 }
.f-fold-upper{ transform-origin:50% 100%; transform:rotateX(0deg) }
.f-fold-lower{ transform-origin:50% 0%;   transform:rotateX(90deg) }
.flip.go .f-fold{ visibility:visible }
.flip.go .f-fold-upper{ animation:leafDown .3s cubic-bezier(.36,0,.66,1) forwards }
.flip.go .f-fold-lower{ animation:leafUp   .3s cubic-bezier(.34,0,.64,1) .3s both }
@keyframes leafDown{ from{ transform:rotateX(0deg) }   to{ transform:rotateX(-90deg) } }
@keyframes leafUp  { from{ transform:rotateX(90deg) }  to{ transform:rotateX(0deg) } }

.flip-label{
  font-family:var(--sans); font-weight:200;
  font-size:clamp(.48rem,2vw,.58rem);
  letter-spacing:.28em; text-indent:.28em; text-transform:uppercase; color:var(--paper-mute);
}

/* ── the engraved dial clock (countdown.style: "dial") ─────────────────── */
.dials{
  display:grid; grid-template-columns:repeat(4,1fr);
  gap:clamp(.4rem,2.4vw,1.1rem);
  width:100%; margin-top:clamp(.8rem,3vh,1.6rem);
}
.dial{ position:relative; display:flex; flex-direction:column; align-items:center; gap:.5rem }
.dial-ring{ position:relative; width:100%; aspect-ratio:1; max-width:126px }
.dial-ring svg{ width:100%; height:100%; transform:rotate(-90deg); overflow:visible }
.dial-ring .track{ fill:none; stroke:rgba(201,162,75,.15); stroke-width:1.6 }
.dial-ring .arc{
  fill:none; stroke:url(#goldArc); stroke-width:2.2; stroke-linecap:round;
  filter:drop-shadow(0 0 5px rgba(201,162,75,.5));
  transition:stroke-dashoffset .55s var(--ease);
}
.dial-ring .ticks line{ stroke:rgba(201,162,75,.3); stroke-width:1 }
.dial-ring .ticks line.major{ stroke:rgba(232,204,134,.62); stroke-width:1.4 }

/* The travelling marker on the seconds dial. It rides INSIDE the rim rather
   than reaching from the centre, so it orbits the numeral instead of striking
   through it. The pivot lives in the SVG rotate() attribute ONLY — declaring a
   transform-origin in CSS as well stacks both and swings the hand off the
   dial entirely. */
.dial-ring .hand{
  stroke:var(--gold-hi); stroke-width:2.2; stroke-linecap:round;
  transition:transform .3s var(--ease);
}
.dial-ring .pin{ fill:rgba(232,204,134,.5) }

.dial-num{
  position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
  font-family:var(--serif); font-weight:300; letter-spacing:.02em;
  font-size:clamp(1.5rem,6.6vw,2.05rem); line-height:1;
  color:#FCF6E8; text-shadow:0 2px 16px rgba(0,0,0,.6);
}
.dial-num.tick{ animation:numTick .5s var(--ease) }
@keyframes numTick{
  0%{ opacity:.25; transform:translateY(-5px) }
  100%{ opacity:1; transform:none }
}
.dial-label{
  font-family:var(--sans); font-weight:200;
  font-size:clamp(.5rem,2.1vw,.6rem);
  letter-spacing:.28em; text-indent:.28em; text-transform:uppercase; color:var(--paper-mute);
}

/* The after-the-event state. Shown INSTEAD of the dials once the date has
   passed — never a row of zeroes, never a negative number. */
.cd-past{
  display:flex; flex-direction:column; align-items:center; gap:.9rem;
  margin-top:clamp(1rem,3.5vh,1.8rem); max-width:40ch;
}
.cd-past-seal{
  width:54px; height:54px; display:block; opacity:.9;
  filter:drop-shadow(0 6px 18px rgba(0,0,0,.7));
}
.cd-past-text{
  margin:0; font-size:clamp(.92rem,3.6vw,1rem); line-height:1.75;
  color:var(--paper-soft); font-style:italic;
}

/* ══════════════════ 3 · THE MINISTRY ══════════════════ */
.min-portrait{
  margin:clamp(1.2rem,4vh,1.8rem) 0 0; width:100%; max-width:340px;
  position:relative; border-radius:4px; overflow:hidden;
  border:1px solid var(--gold-line);
  box-shadow:0 30px 60px -42px rgba(0,0,0,.95);
}
.min-portrait img{ width:100%; height:auto; display:block }
.min-portrait figcaption{
  padding:.7rem .8rem; text-align:center;
  font-family:var(--sans); font-weight:200; font-size:.54rem;
  letter-spacing:.24em; text-indent:.24em; text-transform:uppercase;
  color:var(--paper-mute); background:rgba(8,6,4,.6);
}

.movements{
  width:100%; display:flex; flex-direction:column;
  gap:clamp(.8rem,2.6vw,1.1rem); margin-top:clamp(1.3rem,4.5vh,2rem);
}
.movement{
  position:relative; text-align:left;
  display:flex; flex-direction:column;
  opacity:0; transform:translateY(16px);
  transition:opacity 1.1s var(--ease), transform 1.3s var(--ease);
  overflow:hidden;                 /* so the photograph honours the card radius */
}
.movement.in{ opacity:1; transform:none }
.movement .mv-copy{
  padding:clamp(1.3rem,5vw,1.7rem) clamp(1.2rem,4.5vw,1.6rem);
  display:flex; flex-direction:column; gap:.45rem;
}
/* The photograph sits above the copy and is graded into the page rather than
   pasted onto it: a warm scrim at its foot melts it into the card, so a stock
   image reads as part of the design instead of a panel dropped in. */
.mv-photo{
  margin:0; position:relative; overflow:hidden;
  aspect-ratio:3/2; background:var(--ink-850);
  border-bottom:1px solid var(--gold-line-soft);
}
.mv-photo img{
  width:100%; height:100%; object-fit:cover; display:block;
  filter:saturate(.92) contrast(1.02);
}
.mv-photo::after{
  content:""; position:absolute; inset:0; pointer-events:none;
  background:
    linear-gradient(180deg, rgba(11,9,6,.30) 0%, rgba(11,9,6,0) 34%, rgba(11,9,6,.55) 100%),
    linear-gradient(90deg, rgba(224,166,74,.07), rgba(224,166,74,0) 60%);
}
.mv-head{ display:flex; align-items:baseline; gap:.75rem }
.mv-no{
  font-family:var(--sans); font-weight:200; font-size:.56rem;
  letter-spacing:.34em; color:var(--gold); flex:0 0 auto;
}
.mv-title{
  margin:0; font-family:var(--serif); font-weight:300;
  font-size:clamp(1.1rem,4.4vw,1.32rem); line-height:1.26;
  color:#FBF5E9; letter-spacing:.03em;
}
.mv-text{ margin:0; font-size:clamp(.84rem,3.3vw,.91rem); line-height:1.74; color:var(--paper-soft) }

/* ══════════════════ shared engraved card surface ══════════════════ */
.event-card,.venue-card,.gift-card,.rsvp-card,.movement,.expect-card{
  position:relative;
  background:linear-gradient(168deg, rgba(46,33,15,.58), rgba(13,10,6,.74));
  border:1px solid var(--gold-line);
  border-radius:4px;
  box-shadow:
    0 1px 0 rgba(255,246,220,.07) inset,
    0 30px 60px -40px rgba(0,0,0,.95),
    0 4px 14px -10px rgba(0,0,0,.6);
  backdrop-filter:blur(2px);
}
/* engraved inner keyline */
.event-card::after,.venue-card::after,.gift-card::after,.rsvp-card::after{
  content:""; position:absolute; inset:6px; border-radius:2px;
  border:1px solid var(--gold-line-soft); pointer-events:none;
}
/* corner ticks — stationery detail */
.ec-corner{ position:absolute; width:13px; height:13px; pointer-events:none; z-index:3 }
.ec-corner::before,.ec-corner::after{ content:""; position:absolute; background:var(--gold); opacity:.62 }
.ec-corner::before{ width:100%; height:1px }
.ec-corner::after { width:1px; height:100% }
.ec-corner.tl{ left:12px; top:12px }
.ec-corner.tr{ right:12px; top:12px } .ec-corner.tr::after{ right:0 }
.ec-corner.bl{ left:12px; bottom:12px } .ec-corner.bl::before{ bottom:0 }
.ec-corner.br{ right:12px; bottom:12px } .ec-corner.br::before{ bottom:0 } .ec-corner.br::after{ right:0 }

/* ══════════════════ 4 · THE EVENING ══════════════════ */
.event-card{
  width:100%; margin-top:clamp(1rem,3.5vh,1.6rem);
  padding:clamp(1.7rem,6vw,2.6rem) clamp(1.2rem,5vw,2.2rem);
  text-align:left;
}
.ec-head{ display:flex; flex-direction:column; align-items:center; gap:.6rem; margin-bottom:clamp(1.1rem,4vh,1.7rem) }
.ec-seal{ width:38px; height:38px; display:block; opacity:.95 }
.ec-line{ display:block; width:74%; height:1px; background:linear-gradient(90deg,transparent,var(--gold-line),transparent) }
.ec-date{
  font-family:var(--sans); font-weight:200; margin:0;
  font-size:clamp(.56rem,2.3vw,.63rem);
  letter-spacing:.3em; text-indent:.3em; text-transform:uppercase; color:var(--paper-mute);
}
.ec-list{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column }
.ec-item{
  display:grid; grid-template-columns:auto 22px 1fr; align-items:start;
  gap:0 clamp(.5rem,2.5vw,.9rem);
  padding:clamp(.6rem,2.2vh,.85rem) 0;
  opacity:0; transform:translateY(12px);
  transition:opacity 1s var(--ease), transform 1.15s var(--ease);
}
.ec-item.in{ opacity:1; transform:none }
.ec-time{
  font-family:var(--serif); font-weight:400; font-size:clamp(.95rem,3.8vw,1.08rem);
  color:var(--gold-hi); line-height:1.35; letter-spacing:.03em; white-space:nowrap;
  padding-top:.06rem;
}
.ec-node{ position:relative; height:100%; display:flex; justify-content:center }
.ec-node i{
  width:6px; height:6px; margin-top:.52rem; transform:rotate(45deg);
  background:var(--gold); box-shadow:0 0 8px rgba(201,162,75,.55); z-index:2;
}
.ec-node::before{
  content:""; position:absolute; left:50%; top:0; bottom:0; width:1px;
  transform:translateX(-50%); background:rgba(201,162,75,.28);
}
.ec-item:first-child .ec-node::before{ top:.55rem }
.ec-item:last-child  .ec-node::before{ bottom:calc(100% - .95rem) }
.ec-body h3{
  margin:0; font-family:var(--serif); font-weight:400;
  font-size:clamp(1rem,4vw,1.14rem); line-height:1.3; color:#FBF5E9; letter-spacing:.02em;
}
.ec-body p{
  margin:.16rem 0 0; font-size:clamp(.8rem,3.1vw,.87rem);
  line-height:1.62; color:var(--paper-mute);
}
.ec-foot{ margin-top:clamp(1rem,3.5vh,1.5rem); padding-top:1rem; border-top:1px solid var(--gold-line-soft); text-align:center }
.ec-foot p{
  margin:0; font-family:var(--sans); font-weight:200;
  font-size:clamp(.56rem,2.3vw,.62rem);
  letter-spacing:.22em; text-indent:.22em; text-transform:uppercase; color:var(--paper-mute);
}

/* ══════════════════ 5 · WHERE ══════════════════ */
.venue-card{
  width:100%; margin-top:clamp(1rem,3.5vh,1.5rem);
  padding:clamp(1.6rem,5.5vw,2.1rem) clamp(1.2rem,5vw,1.8rem);
  display:flex; flex-direction:column; align-items:center; gap:.4rem; text-align:center;
}
.vc-name{
  font-family:var(--serif); font-weight:300; margin:.1rem 0 0;
  font-size:clamp(1.25rem,5.2vw,1.55rem); line-height:1.24; color:#FBF5E9; letter-spacing:.02em;
}
.vc-address{ margin:0; font-size:clamp(.86rem,3.4vw,.94rem); line-height:1.62; color:var(--paper-soft) }
.vc-time{
  font-family:var(--serif); font-style:italic; margin:.3rem 0 0;
  font-size:clamp(.98rem,3.8vw,1.08rem); color:var(--gold-hi);
}
.vc-facts{
  width:100%; margin:.9rem 0 0; padding:.9rem 0 0;
  border-top:1px solid var(--gold-line-soft);
  display:flex; flex-direction:column; gap:.6rem; text-align:left;
}
.vc-fact{ display:flex; gap:.7rem; align-items:flex-start }
.vc-fact-icon{ width:16px; height:16px; flex:0 0 auto; margin-top:.18rem }
.vc-fact-icon svg{
  width:100%; height:100%; fill:none; stroke:var(--gold);
  stroke-width:1.4; stroke-linecap:round; stroke-linejoin:round;
}
.vc-fact-copy{ min-width:0 }
.vc-fact-copy b{
  display:block; font-family:var(--sans); font-weight:200; font-size:.53rem;
  letter-spacing:.26em; text-indent:.26em; text-transform:uppercase; color:var(--gold-hi);
  margin-bottom:.15rem;
}
.vc-fact-copy span{ font-size:clamp(.8rem,3.1vw,.87rem); line-height:1.6; color:var(--paper-soft) }
.vc-dir{
  margin-top:.9rem; font-family:var(--sans); font-weight:200;
  font-size:.58rem; letter-spacing:.26em; text-indent:.26em; text-transform:uppercase;
  color:var(--gold-hi); border-bottom:1px solid var(--gold-line); padding-bottom:.22rem;
}
/* Unconfirmed content is marked in the page, not just in a comment — an
   address that has not been verified must not read like a verified one. */
.is-placeholder{ color:var(--warn) !important; font-style:italic }

.map-frame{
  position:relative; width:100%; margin-top:clamp(1rem,3.5vh,1.5rem);
  aspect-ratio:16/11; border-radius:4px; overflow:hidden;
  border:1px solid var(--gold-line);
  box-shadow:0 30px 60px -42px rgba(0,0,0,.95);
}
/* Google's embed only ships a light tile set, so it is inverted into a night
   map. invert + hue-rotate alone leaves greens and water a muddy khaki, so
   saturation is pulled back and contrast lifted after — that is what turns it
   warm black rather than brown. */
.map-frame iframe{
  width:100%; height:100%; border:0;
  filter:invert(.93) hue-rotate(180deg) saturate(.42) brightness(.94) contrast(1.1) sepia(.18);
}
.map-veil{
  position:absolute; inset:0; pointer-events:none;
  mix-blend-mode:multiply;
  background:linear-gradient(180deg,rgba(58,40,16,.46),rgba(30,22,10,.3) 40%,rgba(58,40,16,.46));
  box-shadow:inset 0 0 70px rgba(6,4,2,.72);
}

/* ── buttons ──────────────────────────────────────────────────────────────
   Ink is deep warm black on rich champagne. At #100B04 on #E4C578 this clears
   9:1, which is where thin uppercase type usually fails. A paler gold fill
   washes the lettering out — do not lighten it. */
.btn-gold{
  position:relative; margin-top:clamp(1.1rem,4vh,1.7rem);
  padding:1.05rem 2.2rem; border-radius:999px;
  font-family:var(--sans); font-weight:400;
  font-size:.66rem; letter-spacing:.3em; text-indent:.3em; text-transform:uppercase;
  color:#100B04;
  background:linear-gradient(100deg,#B68A35 0%,#D4AD5E 30%,#E9D093 50%,#D2AC5C 70%,#B68A35 100%);
  background-size:200% 100%;
  box-shadow:0 16px 36px -20px rgba(0,0,0,.9), 0 0 0 1px rgba(255,246,220,.34);
  transition:background-position .9s var(--ease), transform .5s var(--ease), box-shadow .5s var(--ease);
  overflow:hidden; text-align:center;
}
.btn-gold:hover{ background-position:100% 50%; transform:translateY(-1px) }
.btn-gold:active{ transform:translateY(0) scale(.985) }
.btn-gold:focus-visible{ outline:2px solid var(--gold-hi); outline-offset:3px }

.btn-ghost{
  position:relative; padding:1.02rem 1.9rem; border-radius:999px;
  font-family:var(--sans); font-weight:300;
  font-size:.62rem; letter-spacing:.28em; text-indent:.28em; text-transform:uppercase;
  color:var(--gold-hi); text-align:center;
  background:linear-gradient(180deg,rgba(40,28,13,.62),rgba(12,9,6,.72));
  border:1px solid var(--gold-line);
  transition:border-color .5s var(--ease), color .5s var(--ease), background .5s var(--ease), transform .4s var(--ease);
}
.btn-ghost:hover{ border-color:var(--gold-hi); transform:translateY(-1px) }
.btn-ghost:active{ transform:translateY(0) scale(.985) }
.btn-ghost:focus-visible{ outline:2px solid var(--gold-hi); outline-offset:3px }

.cal-btn{ display:inline-flex; align-items:center; justify-content:center; min-width:238px; min-height:47px }
.cal-btn .cal-ring{
  position:absolute; inset:-3px; width:calc(100% + 6px); height:calc(100% + 6px);
  opacity:0; pointer-events:none; overflow:visible;
}
.cal-btn .cal-ring circle{
  fill:none; stroke:var(--gold-hi); stroke-width:2.4; stroke-linecap:round;
  stroke-dasharray:296; stroke-dashoffset:296; transform-origin:50% 50%; transform:rotate(-90deg);
}
.cal-btn .cal-tick{
  position:absolute; left:50%; top:50%; width:22px; height:22px;
  transform:translate(-50%,-50%) scale(.7); opacity:0; pointer-events:none;
}
.cal-btn .cal-tick path{
  fill:none; stroke:#100B04; stroke-width:2.6; stroke-linecap:round; stroke-linejoin:round;
  stroke-dasharray:26; stroke-dashoffset:26;
}
.cal-btn span{ transition:opacity .4s var(--ease), transform .5s var(--ease) }
.cal-btn.saving .cal-ring{ opacity:1 }
.cal-btn.saving .cal-ring circle{ animation:ringDraw 1s var(--ease) forwards }
@keyframes ringDraw{ to{ stroke-dashoffset:0 } }
.cal-btn.saving span{ opacity:0; transform:translateY(-6px) }
.cal-btn.saved .cal-tick{ opacity:1; transform:translate(-50%,-50%) scale(1) }
.cal-btn.saved .cal-tick path{ animation:tickDraw .55s var(--ease) forwards }
@keyframes tickDraw{ to{ stroke-dashoffset:0 } }
.cal-btn.done span{ opacity:1; transform:none }
.cal-btn.done .cal-tick{ opacity:0; transform:translate(-50%,-50%) scale(.6) }
.cal-btn.done .cal-ring{ opacity:0 }

/* ══════════════════ 6 · WHAT TO EXPECT ══════════════════ */
.expect-grid{
  width:100%; display:grid; grid-template-columns:1fr;
  gap:clamp(.7rem,2.5vw,1rem); margin-top:clamp(1.2rem,4vh,1.8rem);
}
.expect-card{
  padding:clamp(1.15rem,4.5vw,1.45rem) clamp(1.05rem,4vw,1.35rem);
  text-align:left; display:flex; flex-direction:column; gap:.4rem;
  opacity:0; transform:translateY(14px);
  transition:opacity 1.1s var(--ease), transform 1.3s var(--ease);
}
.expect-card.in{ opacity:1; transform:none }
.expect-card h4{
  margin:0; font-family:var(--serif); font-weight:400;
  font-size:clamp(.98rem,3.9vw,1.08rem); line-height:1.32;
  color:var(--gold-hi); letter-spacing:.02em;
}
.expect-card p{ margin:0; font-size:clamp(.82rem,3.2vw,.88rem); line-height:1.7; color:var(--paper-soft) }

/* ══════════════════ 7 · GALLERY ══════════════════ */
.gallery-stage{ padding-left:0; padding-right:0; min-height:auto }
.gallery-stage>.inner{ padding:0 clamp(1.4rem,6vw,4rem) }

.gallery-rail{
  position:relative; z-index:2; width:100%;
  margin-top:clamp(1.4rem,5vh,2.4rem);
  overflow-x:auto; overflow-y:hidden;
  -webkit-overflow-scrolling:touch;
  scrollbar-width:none; cursor:grab;
  overscroll-behavior-x:contain;         /* never hand a flick to the page */
}
.gallery-rail::-webkit-scrollbar{ display:none }
.gallery-rail.dragging{ cursor:grabbing }
.gallery-rail.dragging .gl-shot{ pointer-events:none }

.gallery-track{
  display:flex; align-items:center;
  gap:clamp(.6rem,2vw,1.1rem);
  padding:0 clamp(1.4rem,6vw,4rem);
  width:max-content;
}
.gl-shot{
  position:relative; flex:0 0 auto; overflow:hidden; border-radius:3px;
  height:clamp(230px,42vh,420px);
  background:var(--ink-850);
  box-shadow:0 0 0 1px var(--gold-line-soft), 0 24px 44px -34px rgba(0,0,0,.95);
  opacity:0; transform:translateX(38px);
  transition:opacity 1.1s var(--ease), transform 1.4s var(--ease), box-shadow .55s var(--ease);
  border:0; padding:0; margin:0; cursor:pointer;
}
.gl-shot.in{ opacity:1; transform:none }
.gl-shot img{ height:100%; width:auto; display:block; filter:saturate(.98) }
.gl-shot::after{
  content:""; position:absolute; inset:0; pointer-events:none;
  background:linear-gradient(180deg,rgba(8,6,4,.12),rgba(8,6,4,0) 36%,rgba(8,6,4,.32));
  transition:opacity .5s var(--ease);
}
.gl-shot:hover{ box-shadow:0 0 0 1px var(--gold-line), 0 26px 50px -30px rgba(0,0,0,.95) }
.gl-shot:hover::after{ opacity:.4 }

.rail-fade{ position:absolute; top:0; bottom:0; width:clamp(28px,7vw,90px); pointer-events:none; z-index:3 }
.rail-fade.left { left:0;  background:linear-gradient(90deg,#080604,rgba(8,6,4,0)) }
.rail-fade.right{ right:0; background:linear-gradient(270deg,#080604,rgba(8,6,4,0)) }

.gallery-hint,.gallery-note{ position:relative; z-index:2; text-align:center; padding:0 clamp(1.4rem,6vw,4rem) }
.gallery-hint{ margin-top:clamp(1rem,3.5vh,1.5rem); color:var(--gold-hi); opacity:.75 }
.gallery-note{ margin-top:.55rem }

/* ── lightbox ─────────────────────────────────────────────────────────── */
.lightbox{
  position:fixed; inset:0; z-index:90;
  display:flex; align-items:center; justify-content:center;
  background:rgba(5,4,3,.95); backdrop-filter:blur(10px);
  opacity:0; transition:opacity .45s var(--ease);
}
.lightbox.in{ opacity:1 }
.lb-stage{ margin:0; max-width:88vw; max-height:82svh; display:flex }
.lb-stage img{
  max-width:88vw; max-height:82svh; width:auto; height:auto; object-fit:contain;
  border-radius:3px; box-shadow:0 0 0 1px var(--gold-line), 0 40px 90px -40px #000;
  transform:scale(.97); opacity:0;
  transition:transform .6s var(--ease), opacity .5s var(--ease);
}
.lightbox.in .lb-stage img{ transform:none; opacity:1 }
.lb-close{
  position:absolute; top:clamp(.8rem,3vh,1.8rem); right:clamp(.8rem,3vw,1.8rem);
  width:44px; height:44px; border-radius:50%; z-index:2;
  font-size:1.7rem; line-height:1; color:var(--paper);
  border:1px solid var(--gold-line); background:rgba(20,14,8,.75);
}
.lb-nav{
  position:absolute; top:50%; transform:translateY(-50%); z-index:2;
  width:48px; height:48px; border-radius:50%;
  font-size:2rem; line-height:1; color:var(--gold-hi);
  border:1px solid var(--gold-line); background:rgba(20,14,8,.75);
  transition:background .4s var(--ease), border-color .4s var(--ease);
}
.lb-nav:hover{ background:rgba(40,28,14,.9); border-color:var(--gold-hi) }
.lb-nav.prev{ left:clamp(.5rem,2.5vw,2rem) }
.lb-nav.next{ right:clamp(.5rem,2.5vw,2rem) }
.lb-count{
  position:absolute; bottom:clamp(1rem,4vh,2.2rem); left:50%; transform:translateX(-50%);
  margin:0; font-family:var(--sans); font-weight:200; font-size:.6rem;
  letter-spacing:.3em; text-indent:.3em; color:var(--paper-mute);
}

/* ══════════════════ 8 · RESERVE YOUR SEAT ══════════════════ */
.rsvp-card{
  width:100%; margin-top:clamp(1rem,3.5vh,1.6rem);
  padding:clamp(1.8rem,6vw,2.4rem) clamp(1.2rem,5vw,1.9rem);
  display:flex; flex-direction:column; gap:clamp(.95rem,3vh,1.2rem); text-align:left;
}
.field{ position:relative }
.field input,.field textarea,.field select{
  width:100%; padding:1.1rem .1rem .45rem; border:0; border-bottom:1px solid var(--gold-line);
  background:transparent; color:var(--paper);
  font-family:var(--serif); font-weight:300; font-size:1rem; line-height:1.4;
  border-radius:0; outline:none; resize:none;
  transition:border-color .5s var(--ease);
}
.field select{ appearance:none; -webkit-appearance:none; cursor:pointer }
.field select option{ background:#140E07; color:var(--paper) }
.field-guests::after{
  content:""; position:absolute; right:.3rem; bottom:1rem; width:7px; height:7px;
  border-right:1px solid var(--gold); border-bottom:1px solid var(--gold);
  transform:rotate(45deg); pointer-events:none;
}
.field label{
  position:absolute; left:.1rem; top:1.05rem; pointer-events:none;
  font-family:var(--sans); font-weight:200; font-size:.78rem;
  letter-spacing:.16em; text-transform:uppercase; color:var(--paper-mute);
  transition:transform .45s var(--ease), font-size .45s var(--ease), color .45s var(--ease);
  transform-origin:left top;
}
.field input:focus~label,.field textarea:focus~label,
.field input:not(:placeholder-shown)~label,.field textarea:not(:placeholder-shown)~label,
.field select~label{ transform:translateY(-1.05rem) scale(.78); color:var(--gold-hi) }
.field input:focus,.field textarea:focus,.field select:focus{ border-bottom-color:var(--gold-hi) }
.field.invalid input,.field.invalid textarea{ border-bottom-color:#C86A6A }

/* the first-time checkbox — the one that lets the host team welcome someone
   properly, so it is given real weight rather than a bare tickbox */
.check{
  display:flex; align-items:flex-start; gap:.8rem; cursor:pointer;
  padding:.85rem .9rem; border-radius:3px;
  border:1px solid var(--gold-line-soft); background:rgba(224,166,74,.05);
  transition:border-color .45s var(--ease), background .45s var(--ease);
}
.check:hover{ border-color:var(--gold-line) }
.check input{ position:absolute; opacity:0; width:0; height:0 }
.check-box{
  flex:0 0 auto; width:20px; height:20px; margin-top:.1rem; border-radius:3px;
  border:1px solid var(--gold-line); display:grid; place-items:center;
  background:rgba(8,6,4,.5);
  transition:background .35s var(--ease), border-color .35s var(--ease);
}
.check-box svg{ width:13px; height:13px; overflow:visible }
.check-box svg path{
  fill:none; stroke:#100B04; stroke-width:3; stroke-linecap:round; stroke-linejoin:round;
  stroke-dasharray:26; stroke-dashoffset:26; transition:stroke-dashoffset .4s var(--ease);
}
.check input:checked~.check-box{
  background:linear-gradient(100deg,#B98F3C,#E9D29A 46%,#D6B166); border-color:var(--gold-hi);
}
.check input:checked~.check-box svg path{ stroke-dashoffset:0 }
.check input:focus-visible~.check-box{ outline:2px solid var(--gold-hi); outline-offset:2px }
.check-copy{ min-width:0 }
.check-copy b{
  display:block; font-family:var(--sans); font-weight:300; font-size:.7rem;
  letter-spacing:.18em; text-transform:uppercase; color:var(--paper);
}
.check-copy em{
  display:block; margin-top:.22rem; font-style:normal;
  font-family:var(--serif); font-size:.84rem; line-height:1.55; color:var(--paper-mute);
}
.check input:checked~.check-copy b{ color:var(--gold-hi) }

.rsvp-card .btn-gold{ margin-top:.3rem; width:100% }
.rsvp-card .micro{ text-align:center }
.rsvp-error{
  margin:0; text-align:center; color:#E8A08F;
  font-family:var(--sans); font-weight:200; font-size:.6rem;
  letter-spacing:.2em; text-transform:uppercase;
}
.rsvp-done{
  width:100%; margin-top:clamp(1rem,3.5vh,1.6rem);
  display:flex; flex-direction:column; align-items:center; gap:.5rem;
  padding:clamp(2rem,7vw,2.8rem) 1.2rem;
}
.done-seal{ width:56px; height:56px; display:block; margin-bottom:.6rem }
.rsvp-done .display{ font-size:clamp(1.6rem,7vw,2.2rem) }
.rsvp-done .body{ text-align:center; max-width:42ch }

/* ══════════════════ 9 · PARTNER WITH US ══════════════════ */
.gift-card{
  width:100%; margin-top:clamp(1rem,3.5vh,1.5rem);
  padding:clamp(1.7rem,6vw,2.2rem) clamp(1.2rem,5vw,1.8rem); text-align:left;
}
/* the card unseals rather than appearing — details are private until asked for */
.gift-card.sealed{ opacity:0; transform:translateY(-8px) }
.gift-card.unsealed{ opacity:1; transform:none; transition:opacity .7s var(--ease), transform .8s var(--ease) }
.gift-warning{
  margin:0 0 1rem; text-align:center;
  font-family:var(--sans); font-weight:300; font-size:.56rem;
  letter-spacing:.24em; text-indent:.24em; text-transform:uppercase;
  color:var(--warn);
  padding:.55rem .7rem; border:1px dashed rgba(232,180,92,.45); border-radius:3px;
}
.gift-rows{ margin:0; display:flex; flex-direction:column; gap:.1rem }
.gift-row{
  display:flex; align-items:baseline; justify-content:space-between; gap:1rem;
  padding:.62rem 0; border-bottom:1px solid var(--gold-line-soft);
}
.gift-row:last-child{ border-bottom:0 }
.gift-row dt{
  font-family:var(--sans); font-weight:200; font-size:.55rem;
  letter-spacing:.24em; text-indent:.24em; text-transform:uppercase;
  color:var(--paper-mute); flex:0 0 auto;
}
.gift-row dd{
  margin:0; font-family:var(--serif); font-weight:300;
  font-size:clamp(.92rem,3.6vw,1rem); color:#FBF5E9;
  text-align:right; letter-spacing:.03em; word-break:break-word;
}

/* ══════════════════ 10 · INVITE SOMEONE ══════════════════
   Deliberately the loudest block on the page after the opening. For a ministry
   event this is the conversion that matters most. */
.invite-stage .inner{ max-width:var(--maxw) }
.share-actions{
  width:100%; display:flex; flex-direction:column;
  gap:.65rem; margin-top:clamp(1.2rem,4vh,1.8rem);
}
.share-actions .btn-gold,.share-actions .btn-ghost{
  margin-top:0; width:100%;
  display:inline-flex; align-items:center; justify-content:center; gap:.7rem;
  text-decoration:none;
}
.share-wa{ padding-block:1.15rem }
.wa-mark{ width:19px; height:19px; flex:0 0 auto }
.wa-mark path{ fill:#100B04 }
.wa-mark .wa-hook{ fill:#E9D093 }
.copy-mark{ width:17px; height:17px; flex:0 0 auto; overflow:visible }
.copy-mark .ic-copy{
  fill:none; stroke:currentColor; stroke-width:1.5; stroke-linecap:round; stroke-linejoin:round;
  transition:opacity .3s var(--ease);
}
.copy-mark .ic-tick{
  fill:none; stroke:currentColor; stroke-width:2.4; stroke-linecap:round; stroke-linejoin:round;
  stroke-dasharray:26; stroke-dashoffset:26; opacity:0;
}
.share-copy.copied{ border-color:var(--gold-hi); background:linear-gradient(180deg,rgba(72,52,20,.7),rgba(24,17,9,.8)) }
.share-copy.copied .ic-copy{ opacity:0 }
.share-copy.copied .ic-tick{ opacity:1; animation:tickDraw .5s var(--ease) forwards }
.share-url{
  margin-top:clamp(1rem,3vh,1.4rem); word-break:break-all;
  text-transform:none; letter-spacing:.08em; text-indent:0;
  font-family:var(--serif); font-size:.8rem; color:var(--paper-faint);
}

/* ══════════════════ 11 · FINALE ══════════════════ */
.finale-scene{
  position:relative; width:100%; min-height:100svh;
  display:flex; align-items:flex-end; justify-content:center; overflow:hidden;
  background:var(--ink-950);
}
/* Background is an IMAGE, so this section must be full-screen — an image
   cannot cover a box taller than itself, and a short section here is what
   makes the page background show through halfway down. */
.finale-img{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; object-position:50% 38% }
.finale-scrim{
  position:absolute; inset:0; pointer-events:none;
  background:
    radial-gradient(120% 76% at 50% 32%, rgba(8,5,3,0) 34%, rgba(8,5,3,.5) 100%),
    linear-gradient(180deg, rgba(8,5,3,.5) 0%, rgba(8,5,3,.1) 24%, rgba(8,5,3,.74) 64%, rgba(8,5,3,.97) 100%);
}
.finale-type{
  position:relative; z-index:2; width:100%; max-width:var(--maxw);
  display:flex; flex-direction:column; align-items:center; gap:.55rem;
  text-align:center; padding:0 1.4rem clamp(3.2rem,10vh,5.2rem);
}
.fin-seal{ width:46px; height:46px; display:block; margin-bottom:.4rem; opacity:.95 }
.fin-sub{
  margin:0; font-family:var(--serif); font-style:italic;
  font-size:clamp(1.02rem,4.2vw,1.22rem); color:var(--paper-soft);
}
.fin-tag{ color:var(--gold); opacity:.85 }

/* ══════════════════ chrome ══════════════════ */
.progress-rail{
  position:fixed; left:0; right:0; bottom:0; height:2px; z-index:60;
  background:rgba(255,246,220,.05); pointer-events:none;
}
.progress-rail i{
  display:block; height:100%; width:0;
  background:linear-gradient(90deg,#8A6524,#C9A24B 40%,#F3E2B6 70%,#C9A24B);
  box-shadow:0 0 12px rgba(201,162,75,.7);
}

/* ══════════════════ desktop tier ══════════════════ */
@media (min-width:900px){
  :root{ --maxw:700px; --maxw-wide:1020px }
  .stage{ min-height:78svh; padding:clamp(5rem,11vh,7.5rem) 2.5rem }

  .dials{ gap:clamp(1rem,2.6vw,1.8rem) }
  .dial-ring{ max-width:150px }
  .dial-num{ font-size:2.5rem }

  .movements{ grid-template-columns:repeat(3,1fr); display:grid; gap:clamp(.9rem,2vw,1.2rem) }
  .min-portrait{ max-width:300px }

  .event-card{ max-width:720px }
  .ec-item{ grid-template-columns:auto 26px 1fr; padding:.95rem 0 }

  .venue-card{ max-width:720px }
  .vc-facts{ flex-direction:row; gap:2rem }
  .vc-fact{ flex:1 }
  .map-frame{ aspect-ratio:21/8 }

  .expect-grid{ grid-template-columns:1fr 1fr }

  .gl-shot{ height:clamp(300px,52vh,480px) }

  .rsvp-card{ max-width:620px }
  .gift-card{ max-width:620px }
  .share-actions{ flex-direction:row; flex-wrap:wrap; max-width:620px }
  .share-actions .share-wa{ flex:1 1 100% }
  .share-actions .share-copy,.share-actions .share-sms{ flex:1 1 0 }
  .finale-type{ max-width:760px }
}
@media (min-width:1400px){
  :root{ --maxw:780px; --maxw-wide:1120px }
}

/* ══════════════════ LANDSCAPE OPENING ══════════════════
   The type stays a single low stack — there is nothing to flank into in this
   footage. It is simply held to a narrower column so it cannot stray out of
   the dark centre of the frame, and given a little more bottom room. */
@media (min-aspect-ratio: 1/1){
  .hero-type{ padding-bottom:clamp(2.4rem,8vh,4.4rem) }
  .ht-stack{ max-width:min(520px,44vw); gap:clamp(.24rem,.9vh,.46rem) }
  .ht-title{ font-size:clamp(2.4rem,5.2vw,3.6rem) }
  .ht-with{ font-size:clamp(1.05rem,2vw,1.35rem) }
}

/* landscape phones — short and wide, so tighten before anything clips */
@media (max-height:520px) and (orientation:landscape){
  .hero-type{ padding-bottom:1rem }
  .ht-stack{ max-width:min(520px,54vw); gap:.16rem }
  .ht-title{ font-size:1.9rem }
  .ht-with{ font-size:.95rem }
  .ht-orn{ display:none }
  .ht-pillars{ display:none }
  .film-loader{ bottom:clamp(96px,26vh,150px) }
}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.01ms !important; animation-iteration-count:1 !important;
    transition-duration:.01ms !important;
  }
  .reveal{ opacity:1; transform:none; filter:none }
}
