/* ============================================================================
   FREDRIKA & HOSEA — second draft

   A deliberately different register from the first. Draft one was romantic
   stationery: script foil on every heading, damask pressed into every ground,
   ornaments, gradients, bordered cards, a gold line threading the whole
   scroll. The client didn't want it.

   The rules this one holds to:

     · ONE flat paper. No gradients, no damask, no vignettes. Two tones that
       alternate — the paper and a single tint band.
     · Type carries everything. A light serif at large sizes for headings, a
       very small and very wide-tracked sans for labels. Hairlines instead of
       rules with diamonds on them.
     · Gold is an ACCENT, not a surface: the monogram, the wax seal, a hairline
       under a heading. No gold headings anywhere.
     · Script appears TWICE on the whole page — the couple's names in the hero,
       and "See You There" at the end. Script everywhere is what made draft one
       read as stationery.
     · Nothing is boxed. Cards become rows separated by hairlines.
     · Content is left-aligned. Centring everything is the most stationery-like
       thing a layout can do.
     · Space does the work decoration used to.

   What survives from draft one, because it was mechanics rather than style:
   the tap-to-open gate, the cross-dissolve, the flip clock, the reveal sweep,
   the form fields, and the wax seal.
   ========================================================================== */

:root{
  /* The whole palette. These were originally within 3% of the paper, and the
     page read as one flat white sheet — "premium" turned into "blank". They
     are now far enough apart that a section change is a change you can SEE,
     which is what carries a design with no ornament on it. Every one is warm;
     a cold tint next to gold reads as concrete. */
  --paper:#FDFBF9;
  --tint:#EFE6DE;    /* warm sand   — story, gifts */
  --grey:#DFDBD3;    /* dove grey   — Day One */
  --blush:#EBD1C6;   /* real blush  — Day Two, finale */
  /* Both are TEXT colours, and both are set at small letterspaced cap sizes
     where there is no weight to fall back on. Measured against the darkest
     ground on the page (blush): grey-mid 4.4:1, blush-ink 4.5:1. The lighter
     values these started at measured 2.5:1 once the grounds were deepened —
     legible on paper, not legible on blush. */
  --blush-ink:#94493D;
  --grey-mid:#655E55;

  /* Gold is an ACCENT ONLY here — a hairline, the seal, the monogram. It is
     2.5:1 on the blush ground, so it is never used to set type except at the
     display size of the finale script, where 2.5:1 is fine. */
  --gold:#A9812F;
  --gold-soft:rgba(169,129,47,.42);

  /* ink — warm near-black, never pure */
  --ink:#241F1B;
  --ink-soft:rgba(36,31,27,.74);
  --ink-mute:rgba(36,31,27,.54);
  --line:rgba(36,31,27,.18);
  --line-soft:rgba(36,31,27,.11);

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

  --maxw:38rem;

  /* keep in step with films.dissolveMs in js/config.js */
  --dissolve:1600ms;
}

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

/* The gold keyline. The ivory card in the film carries a fine gold rule inset
   from its edge, and on a printed invitation that rule is most of what says
   "invitation" rather than "web page". One fixed element, drawn over
   everything, never in the way of a click. */
.keyline{
  position:fixed; inset:clamp(8px,2.2vw,18px);
  border:1px solid var(--gold-soft);
  pointer-events:none; z-index:70;
}
/* Off during the opening: the film has its own keyline, and two of them
   nested reads as a mistake. */
html.intro-lock .keyline{ opacity:0 }
.keyline{ transition:opacity .8s var(--ease) }

/* The `hidden` attribute is applied by the UA stylesheet as `display:none`,
   which ANY author `display` declaration silently overrides. Several things
   here are flex containers that are ALSO toggled with `hidden` — the
   countdown, the banking sheet, the RSVP confirmation, the scroll hint, the
   hero name line. Without this rule they stay in the layout, and a full-bleed
   one sits invisibly over the page swallowing every click, "Tap To Open"
   included. This 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(--paper);
  color:var(--ink);
  font-family:var(--serif);
  font-weight:300;
  line-height:1.65;
  overflow-x:hidden;
  -webkit-font-smoothing:antialiased;
  /* Cormorant ships OLDSTYLE figures: "11:00" reads as "I I:oo" and "27" drops
     below the baseline. Unusable on a page whose whole job is dates. */
  font-variant-numeric:lining-nums;
  font-feature-settings:"lnum" 1;
}
img{ max-width:100%; display:block }
button{ font:inherit; color:inherit; cursor:pointer; border:0; background:none }
a{ color:var(--ink); text-decoration:none }
main{ position:relative }

html.intro-lock, html.intro-lock body{
  overflow:hidden !important; height:100%;
  touch-action:none; overscroll-behavior:none;
}
::selection{ background:rgba(169,129,47,.20); color:var(--ink) }

/* ── type ────────────────────────────────────────────────────────────────── */
.eyebrow{
  font-family:var(--sans); font-weight:300;
  font-size:.6rem; letter-spacing:.5em; text-indent:.5em; text-transform:uppercase;
  color:var(--grey-mid); margin:0;
}
.micro{
  font-family:var(--sans); font-weight:300;
  font-size:.6rem; letter-spacing:.26em; text-indent:.26em; text-transform:uppercase;
  color:var(--ink-mute); margin:0;
}
/* The workhorse heading: serif, light, large, tight — NOT script, NOT gold.
   This single change is most of the difference between the two drafts. */
/* Bigger than draft two had it. At 3.1rem the headings sat politely in the
   middle of a lot of white and the page read as unfinished; the size is what
   makes space read as deliberate rather than empty. */
.display{
  font-family:var(--serif); font-weight:300;
  font-size:clamp(2.7rem,11.5vw,4.2rem);
  line-height:1.05; letter-spacing:-.02em;
  color:var(--ink); margin:1.1rem 0 0;
}
/* Script survives in exactly two places. Script faces draw ink outside their
   line box, so they need the padding whatever the design. */
.script{
  font-family:var(--script); font-weight:400;
  font-size:clamp(2.6rem,11vw,3.8rem);
  line-height:1.2; padding:.14em .1em .18em; margin:0;
  color:var(--gold);
}
.body{
  font-size:clamp(1rem,3.8vw,1.08rem); line-height:1.85;
  color:var(--ink-soft); margin:.9rem 0 0; font-weight:300; max-width:34ch;
}
/* A hairline. No diamond, no gradient, no glow — but gold, and long enough to
   register. */
.hair{
  display:block; width:4rem; height:1px; background:var(--gold);
  margin:1.6rem 0 0; opacity:.55;
}

/* ── stages ──────────────────────────────────────────────────────────────── */
/* Flat colour, so a section hugs its content without the ground stopping
   short. Left-aligned and asymmetric. */
.stage{
  position:relative; width:100%;
  display:flex; flex-direction:column; align-items:center;
  padding:clamp(5.5rem,15vh,9rem) clamp(1.6rem,7vw,4rem);
  background:var(--paper);
}
.stage--tint{ background:var(--tint) }

/* Real paper grain, lifted from a CLEAN area of the ivory card in the film —
   no gold ornament in the crop, or the card's fleuron tiles across the page
   behind the text, which is exactly what happened the first time. The patch
   spans eight levels of grey and weighs 1 KB: it is the difference between a
   flat colour swatch and a sheet of something, and nothing more. */
.stage::before,.day-scene::before,.finale-scene::before{
  content:""; position:absolute; inset:0; z-index:0; pointer-events:none;
  background-image:url("../assets/tex-paper.jpg");
  background-size:420px auto; background-repeat:repeat;
  opacity:.7; mix-blend-mode:multiply;
}
.stage>.inner,.day-inner,.finale-type{ position:relative; z-index:2 }

/* The blush sections get a vector ogee damask. This started as a still cropped
   from the film, but that still is only 600 px wide and `cover` stretched it
   across the viewport, so it pixelated on a phone and disintegrated on a
   desktop. Vector tiles instead of stretching: sharp at any size, and the
   motif keeps the same physical size on every screen. */
.day-warm::before,.finale-scene::before{
  background-image:url("../assets/pat-damask.svg");
  background-size:64px 85px; background-repeat:repeat;
  /* Enough to read as printed stock, not so much that the pattern competes
     with the type sitting on it. */
  opacity:.5;
}
.stage>.inner{
  width:100%; max-width:var(--maxw);
  display:flex; flex-direction:column; align-items:flex-start; text-align:left;
}

/* ── reveals ─────────────────────────────────────────────────────────────── */
.reveal{
  opacity:0; transform:translateY(14px);
  transition:opacity 1.2s var(--ease), transform 1.4s var(--ease);
  will-change:opacity,transform;
}
.reveal.in{ opacity:1; transform:none; will-change:auto }

/* ══════════════════ 1 · OPENING ══════════════════ */
.opening-scene{
  position:relative; height:100svh; height:100dvh; overflow:hidden;
  background:#F2E8E2; cursor:pointer; z-index:3;
}
.opening-sticky{ position:absolute; inset:0; overflow:hidden }

/* The film is 16:9 and there is no 9:16 cut. Cropping it to a phone loses the
   left and right thirds — exactly where "YOU ARE" and "Invited" sit — so on a
   portrait screen it is CONTAINED, and this carries a blurred copy of its own
   poster behind it. The letterbox then reads as depth of field rather than as
   empty bars. */
.film-fill{
  position:absolute; inset:0; z-index:2; pointer-events:none;
  background-size:cover; background-position:center;
  transform:scale(1.25); filter:blur(38px) saturate(1.05);
  opacity:0;
  transition:opacity var(--dissolve) cubic-bezier(.42,0,.35,1);
}
.opening-scene.film-contain .film-fill{ opacity:1 }
/* This has to out-rank the rule above it, or the blurred fill survives the
   dissolve and sits over the hero as a smear. `.film-fill.faded` alone is one
   class short of `.opening-scene.film-contain .film-fill`. */
.opening-scene .film-fill.faded{ opacity:0 }

.opening-video{
  position:absolute; inset:0; width:100%; height:100%;
  object-fit:cover; pointer-events:none; background:transparent;
  z-index:3;
  transition:opacity var(--dissolve) cubic-bezier(.42,0,.35,1);
}
.opening-scene.film-contain .opening-video{ object-fit:contain }
.opening-video.faded{ opacity:0 }

/* Three states: WAITING near-opaque so the only thing on screen is the seal;
   READY a half-scrim so the envelope appears with the prompt brightest on it;
   PLAYING gone. Two tones, because the cut declares its own — see config. */
.film-scrim{
  position:absolute; inset:0; z-index:4; pointer-events:none;
  background:rgba(8,7,7,.92);
  opacity:1;
  transition:opacity 1.1s var(--ease);
}
.opening-scene.film-light .film-scrim{ background:rgba(250,244,240,.93) }
.opening-scene.is-ready   .film-scrim{ opacity:.55 }
/* On the LIGHT cut, .93 x .55 meant the guest met the film through 51% white:
   the blush damask went grey-pink, the gold seal went beige, the grey envelope
   went white — the artwork arrived washed out. The prompt below is an opaque
   pill with its own outline and shadow, so it does not need the picture dimmed
   behind it to be found. This only takes the edge off. */
.opening-scene.film-light.is-ready .film-scrim{ opacity:.14 }
.opening-scene.is-playing .film-scrim{ opacity:0 }

/* What the film dissolves INTO. The film ends on ivory and blush; this is the
   same paper, so the hand-over is a fade rather than a cut. */
/* The one wash on the page. The film ends on an ivory card with blush at its
   edges; a flat white plate behind it made the dissolve land on nothing. This
   is not draft one's layered gradient ground — it is one soft blush base, so
   the hand-over has somewhere to land. */
.hero-plate{
  position:absolute; inset:0; z-index:1;
  display:flex; align-items:center; justify-content:center;
  background:
    radial-gradient(120% 70% at 50% 118%, var(--blush) 0%, rgba(235,209,198,0) 62%),
    var(--paper);
  overflow:hidden;
}
.hero-type{
  position:relative; z-index:2;
  display:flex; flex-direction:column; align-items:center;
  text-align:center; gap:0;
  padding:clamp(1.2rem,4vh,2rem) clamp(1.4rem,7vw,2rem);
  max-width:min(46rem,92vw);
}
/* Opacity and transform only — no blur. A filter forces a composited layer
   that Chrome rasterises once and rescales, and the type goes permanently
   soft. */
.hero-type [data-r]{
  opacity:0; transform:translateY(14px);
  transition:opacity 1.1s var(--ease), transform 1.3s var(--ease);
}
.hero-mono{
  display:block; width:clamp(58px,15vw,84px); height:auto;
  margin:0 auto clamp(1.6rem,5vh,2.4rem);
}
.hero-name{
  margin:0 0 .5rem; font-family:var(--sans); font-weight:300;
  font-size:.62rem; letter-spacing:.42em; text-indent:.42em; text-transform:uppercase;
  color:var(--blush-ink);
}
.hero-lead{
  margin:0 0 1.1rem; font-family:var(--sans); font-weight:300;
  font-size:.6rem; letter-spacing:.42em; text-indent:.42em; text-transform:uppercase;
  color:var(--grey-mid);
  text-wrap:balance; line-height:2;
}
/* One of the two places script appears. */
.hero-names{
  margin:0; display:flex; flex-direction:column; align-items:center; gap:0;
  font-weight:400;
}
.hero-names .hn-one,.hero-names .hn-two{
  font-family:var(--script); font-weight:400;
  font-size:clamp(2.9rem,14vw,5rem); line-height:1.16;
  padding:.12em .1em .16em; display:block; color:var(--ink);
}
.hero-names .hn-amp{
  font-family:var(--serif); font-style:italic; font-weight:300;
  font-size:clamp(1rem,4vw,1.4rem); line-height:1;
  color:var(--gold); margin:-.3em 0 -.15em;
}
@media (min-width:600px){
  .hero-names{ flex-direction:row; align-items:baseline; gap:clamp(.6rem,2.2vw,1.2rem) }
  .hero-names .hn-amp{ margin:0 }
}
.hero-type .hair{ margin:1.6rem auto 1.4rem }
.hero-dates{
  margin:0; font-family:var(--sans); font-weight:300;
  font-size:clamp(.62rem,2.7vw,.72rem);
  letter-spacing:.38em; text-indent:.38em; text-transform:uppercase;
  color:var(--ink);
}
.hero-place{
  margin:.6rem 0 0; font-family:var(--sans); font-weight:300;
  font-size:.56rem; letter-spacing:.32em; text-indent:.32em; text-transform:uppercase;
  color:var(--grey-mid);
}

/* ── the gate ─────────────────────────────────────────────────────────────
   The prompt is withheld until the film is wholly in memory, so a tap can
   never land on an unbuffered file — play() on an empty element sticks at
   currentTime 0 forever, which reads as a dead button. Strict is only safe
   because readiness CANNOT HANG: see initOpening() for the fetch-error
   fallback, the 30s stall detector, the 5s post-download watchdog and the
   absolute ceiling. */
.film-loader{
  position:absolute; left:50%; top:50%;
  transform:translate(-50%,-50%); z-index:7;
  display:flex; flex-direction:column; align-items:center; gap:1.2rem;
  pointer-events:none;
  transition:opacity .6s var(--ease), transform .6s var(--ease);
}
.film-loader.gone{ opacity:0; transform:translate(-50%,-50%) scale(.96) }
.film-loader .wax-seal{ width:clamp(84px,20vw,116px); height:clamp(84px,20vw,116px) }
.loader-label{
  font-family:var(--sans); font-weight:300;
  font-size:.55rem; letter-spacing:.42em; text-indent:.42em; text-transform:uppercase;
  color:rgba(241,232,220,.6);
}
.opening-scene.film-light .loader-label{ color:var(--grey-mid) }

/* A flat ink slab. Draft one's prompt breathed and pulsed; this one just sits
   there and is obviously a button. */
.tap-cue{
  position:absolute; left:50%; top:50%; z-index:8;
  transform:translate(-50%,calc(-50% + clamp(76px,14vh,110px)));
  opacity:0; pointer-events:none;
  transition:opacity .8s var(--ease) .35s;
}
.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; white-space:nowrap;
  font-family:var(--sans); font-weight:400;
  font-size:.6rem; letter-spacing:.36em; text-indent:.36em; text-transform:uppercase;
  color:var(--paper); background:var(--ink);
  padding:1rem clamp(1.5rem,6vw,2.2rem); border-radius:0;
}
@media (max-width:360px){ .tap-cue .label{ font-size:.55rem; letter-spacing:.24em; text-indent:.24em } }
.opening-scene.is-playing .film-cue{
  opacity:0; pointer-events:none;
  transform:translate(-50%,calc(-50% + clamp(76px,14vh,110px))) scale(.96);
}

.scroll-hint{
  position:absolute; left:50%; bottom:1.6rem; transform:translateX(-50%);
  z-index:7; display:flex; flex-direction:column; align-items:center; gap:.5rem;
  opacity:0; transition:opacity 1.2s var(--ease);
  font-family:var(--sans); font-weight:300; font-size:.54rem;
  letter-spacing:.36em; text-indent:.36em; text-transform:uppercase;
  color:var(--grey-mid);
}
.scroll-hint.in{ opacity:1 }
.scroll-hint i{ width:1px; height:30px; display:block; background:var(--line) }

/* ── the wax seal ─────────────────────────────────────────────────────────
   The one piece of ornament that stays, because it is the wedding's mark and
   it is in the film. Poured wax rather than a coin: uneven radii, an
   off-centre highlight, a rim that catches light above and shadow below. */
.wax-seal{
  position:relative; display:grid; place-items:center; flex:0 0 auto;
  width:clamp(72px,17vw,104px); height:clamp(72px,17vw,104px);
  border-radius:47% 53% 52% 48% / 51% 47% 53% 49%;
  background:
    radial-gradient(circle at 34% 28%, rgba(255,238,196,.6) 0%, rgba(255,238,196,0) 46%),
    radial-gradient(circle at 62% 74%, rgba(60,38,10,.5) 0%, rgba(60,38,10,0) 52%),
    linear-gradient(150deg,#D8B063 0%,#BE944A 34%,#96702F 66%,#6E5121 100%);
  box-shadow:
    inset 0 2px 4px rgba(255,242,208,.42),
    inset 0 -3px 7px rgba(38,24,6,.5),
    0 10px 22px -12px rgba(122,88,48,.5);
}
.wax-seal::before{
  content:""; position:absolute; inset:9%; border-radius:inherit;
  box-shadow:
    inset 0 2px 3px rgba(40,26,8,.5),
    inset 0 -2px 2px rgba(255,240,200,.26);
}
.wax-seal .ws-mark{
  position:relative; z-index:2; display:block; width:64%; height:auto;
}
.wax-seal.small{ width:60px; height:60px }
@keyframes sealBreathe{
  0%,100%{ transform:scale(1) }
  50%    { transform:scale(1.03) }
}
.wax-seal.breathing{ animation:sealBreathe 3.6s ease-in-out infinite }

/* ══════════════════ 2 · COUNTDOWN ══════════════════
   The flip clock stays — it was the client's own request. Restyled flat: no
   drop shadows, hairline seams, ink digits rather than gold. */
.countdown{
  display:flex; justify-content:flex-start; align-items:flex-start;
  gap:clamp(.5rem,2.6vw,1.2rem);
  margin:clamp(1.8rem,5vh,2.6rem) 0 0;
  max-width:100%; flex-wrap:nowrap;
}
.fc-unit{ display:flex; flex-direction:column; align-items:center; gap:.8rem }
.fc-digits{ display:flex; gap:2px }
.fc-label{
  font-family:var(--sans); font-weight:300;
  font-size:.5rem; letter-spacing:.26em; text-indent:.26em; text-transform:uppercase;
  color:var(--grey-mid);
}
.fc-digit{
  --fh:clamp(38px,11.5vw,64px);
  position:relative; width:calc(var(--fh) * .72); height:var(--fh);
  perspective:340px;
  font-family:var(--serif); font-weight:300;
  font-size:calc(var(--fh) * .56); line-height:1;
  font-variant-numeric:lining-nums tabular-nums;
}
/* The tiles must be OPAQUE. A translucent leaf lets the incoming number show
   through the outgoing one mid-fall, which reads as the old digit lingering
   behind the flip rather than being replaced by it. */
.fc-half,.fc-flap{
  position:absolute; left:0; width:100%; height:50%; overflow:hidden;
  background-color:#FFFFFF;
  color:var(--ink);
  box-shadow:inset 0 0 0 1px var(--line-soft), 0 1px 2px rgba(36,31,27,.06);
}
.fc-top,.fc-flap-top{ top:0 }
.fc-bot,.fc-flap-bot{ bottom:0 }
/* The glyph is a full-height absolutely-placed block clipped by the half —
   deterministic, unlike relying on flex alignment of an oversized item. */
.fc-half i,.fc-flap i{
  position:absolute; left:0; right:0; text-align:center;
  height:var(--fh); line-height:var(--fh); font-style:normal;
}
.fc-top i,.fc-flap-top i{ top:0 }
.fc-bot i,.fc-flap-bot i{ top:calc(var(--fh) / -2) }
.fc-hinge{
  position:absolute; left:0; right:0; top:50%; height:1px; z-index:4;
  background:var(--line); pointer-events:none;
}
.fc-flap{ z-index:3; display:none; backface-visibility:hidden }
.fc-digit.flipping .fc-flap{ display:block }
.fc-digit.flipping .fc-flap-top{
  transform-origin:50% 100%;
  animation:fcTop .3s cubic-bezier(.4,0,.8,.3) forwards;
}
.fc-digit.flipping .fc-flap-bot{
  transform-origin:50% 0%; transform:rotateX(90deg);
  animation:fcBot .3s cubic-bezier(.2,.8,.4,1) .3s forwards;
}
@keyframes fcTop{ from{ transform:rotateX(0) }     to{ transform:rotateX(-90deg) } }
@keyframes fcBot{ from{ transform:rotateX(90deg) } to{ transform:rotateX(0) } }
/* A leaf turning away from the light darkens as it goes — this is most of what
   makes the flip read as a card rather than a CSS rotation. */
.fc-flap::after{
  content:""; position:absolute; inset:0; background:#000;
  opacity:0; pointer-events:none;
}
.fc-digit.flipping .fc-flap-top::after{ animation:fcShadeOut .3s linear forwards }
.fc-digit.flipping .fc-flap-bot::after{ animation:fcShadeIn  .3s linear .3s forwards }
@keyframes fcShadeOut{ from{ opacity:0 }   to{ opacity:.24 } }
@keyframes fcShadeIn { from{ opacity:.24 } to{ opacity:0 } }

/* The longest .micro line on the page — "Until Day One · 27 August 2027 ·
   Namibian time". At .26em tracking it stranded "TIME" on a line of its own. */
[data-cd-note]{ margin-top:1.6rem; letter-spacing:.16em; text-indent:.16em }
.cd-also{
  margin:.5rem 0 0; font-family:var(--serif); font-style:italic; font-weight:300;
  font-size:clamp(.95rem,3.7vw,1.05rem); color:var(--ink-mute);
}

/* ══════════════════ 3 · OUR STORY ══════════════════ */
.chapters{ width:100%; display:flex; flex-direction:column; gap:2.5rem }
.chapter{ display:block; max-width:34ch }
.ch-no{
  margin:0 0 .5rem; font-family:var(--serif); font-style:italic; font-weight:300;
  font-size:1.2rem; color:var(--gold-soft);
}
.ch-title{
  margin:0 0 .6rem; font-family:var(--sans); font-weight:300;
  font-size:.6rem; letter-spacing:.34em; text-indent:.34em; text-transform:uppercase;
  color:var(--grey-mid);
}
.ch-text{
  margin:0; font-size:clamp(1.02rem,3.9vw,1.12rem); line-height:1.9;
  color:var(--ink-soft); font-weight:300;
}
.chapters--one{ margin-top:1.6rem }

/* ══════════════════ 4 & 5 · THE TWO DAYS ══════════════════
   Two flat grounds, one grey and one blush. The days were two temperatures in
   draft one and still are; the difference is now simply which colour the page
   is, with nothing layered over it. */
.day-scene{
  position:relative; width:100%;
  display:flex; flex-direction:column; align-items:center;
  padding:clamp(5.5rem,15vh,9rem) clamp(1.6rem,7vw,4rem);
}
.day-cool{ background:var(--grey) }
.day-warm{ background:var(--blush) }
.day-inner{
  width:100%; max-width:var(--maxw);
  display:flex; flex-direction:column; align-items:flex-start; text-align:left;
}
.day-tag{
  margin:0; font-family:var(--sans); font-weight:300;
  font-size:.6rem; letter-spacing:.5em; text-indent:.5em; text-transform:uppercase;
  color:var(--grey-mid);
}
.day-warm .day-tag{ color:var(--blush-ink) }
.day-inner .hair{ margin:1.1rem 0 0 }

/* The date, set as the largest thing in the section. Editorial, not ornate. */
.day-date{
  margin:1.6rem 0 0; display:flex; align-items:baseline; gap:.7rem;
  font-family:var(--serif); font-weight:300; color:var(--ink);
}
.day-date b{
  font-weight:300; font-size:clamp(5rem,26vw,8.5rem); line-height:.86;
  letter-spacing:-.03em;
}
.day-date span{
  display:flex; flex-direction:column; align-items:flex-start; gap:.2rem;
  font-family:var(--sans); font-weight:300;
  font-size:.62rem; letter-spacing:.28em; text-transform:uppercase;
  color:var(--ink-mute);
}
.day-date span i{ font-style:normal; display:block }

.day-title{
  margin:1.5rem 0 0; font-family:var(--serif); font-weight:300;
  font-size:clamp(2.4rem,10vw,3.4rem); line-height:1.08; letter-spacing:-.018em;
  color:var(--ink);
}
.day-lede{
  margin:.5rem 0 0; font-family:var(--serif); font-style:italic; font-weight:300;
  font-size:clamp(1.02rem,4vw,1.14rem); color:var(--ink-mute);
}
.day-when{
  margin:1.3rem 0 0; font-family:var(--sans); font-weight:300;
  font-size:.66rem; letter-spacing:.28em; text-transform:uppercase; color:var(--ink);
}
.day-arrive{
  margin:.4rem 0 0; font-family:var(--serif); font-style:italic; font-weight:300;
  font-size:1rem; color:var(--ink-mute); text-transform:none; letter-spacing:0;
}

/* The programme, when config has one. A hairline-ruled list, no nodes. */
.programme{
  list-style:none; margin:2rem 0 0; padding:0; width:100%;
  display:flex; flex-direction:column;
}
.pr-step{
  display:grid; grid-template-columns:4.5rem 1fr; gap:0 1.2rem;
  padding:.85rem 0; border-top:1px solid var(--line-soft);
  opacity:0; transform:translateY(10px);
  transition:opacity 1s var(--ease), transform 1.1s var(--ease);
}
.pr-step.in{ opacity:1; transform:none }
.pr-time{
  margin:0; font-family:var(--sans); font-weight:300;
  font-size:.66rem; letter-spacing:.16em; color:var(--grey-mid);
  padding-top:.28rem; font-variant-numeric:tabular-nums;
}
.pr-what{
  margin:0; font-size:clamp(1rem,3.9vw,1.08rem); line-height:1.5; color:var(--ink);
}

/* Venue and dress: hairline-separated rows, not bordered cards. */
.day-facts{
  width:100%; margin-top:clamp(2.4rem,7vh,3.4rem);
  display:flex; flex-direction:column;
}
.fact{
  padding:1.5rem 0; border-top:1px solid var(--line);
  opacity:0; transform:translateY(12px);
  transition:opacity 1.1s var(--ease), transform 1.2s var(--ease);
}
.fact.in{ opacity:1; transform:none }
.fact-label{
  margin:0; font-family:var(--sans); font-weight:300;
  font-size:.55rem; letter-spacing:.36em; text-indent:.36em; text-transform:uppercase;
  color:var(--grey-mid);
}
.day-warm .fact-label{ color:var(--blush-ink) }
.fact-main{
  margin:.6rem 0 0; font-family:var(--serif); font-weight:300;
  font-size:clamp(1.3rem,5vw,1.6rem); line-height:1.25; color:var(--ink);
}
.fact-sub{ margin:.3rem 0 0; font-size:1rem; color:var(--ink-soft); line-height:1.6 }
.fact-note{ margin:.5rem 0 0; font-size:.94rem; color:var(--ink-mute); font-style:italic }
.fact-link{
  display:inline-block; margin-top:.9rem;
  font-family:var(--sans); font-weight:300;
  font-size:.58rem; letter-spacing:.28em; text-transform:uppercase;
  color:var(--ink); border-bottom:1px solid var(--gold-soft); padding-bottom:3px;
  transition:border-color .4s var(--ease);
}
.fact-link:hover{ border-bottom-color:var(--gold) }

/* A full-bleed band of the card itself — ivory, the gold keyline, the grey
   envelope and the damask, straight out of the film. One image, once, between
   the last day and the reply. It is the only picture on the page and it does
   the work that a photograph would if the couple had supplied one. */
.band{
  position:relative; width:100%;
  height:clamp(160px,32vh,300px);
  background-image:url("../assets/tex-corner.jpg");
  background-size:cover; background-position:center;
}

/* ── buttons ─────────────────────────────────────────────────────────────── */
.btn{
  display:inline-block; margin-top:2rem;
  font-family:var(--sans); font-weight:400;
  font-size:.6rem; letter-spacing:.34em; text-indent:.34em; text-transform:uppercase;
  color:var(--paper); background:var(--ink);
  padding:1.05rem clamp(1.6rem,6vw,2.4rem);
  border-radius:0; text-align:center;
  transition:background .4s var(--ease), color .4s var(--ease);
}
.btn:hover{ background:var(--gold) }
.btn:focus-visible{ outline:2px solid var(--gold); outline-offset:3px }
.btn--quiet{
  color:var(--ink); background:transparent;
  box-shadow:inset 0 0 0 1px var(--line);
}
.btn--quiet:hover{ background:var(--ink); color:var(--paper) }
.btn.done{ background:transparent; color:var(--grey-mid); box-shadow:inset 0 0 0 1px var(--line-soft) }
.cal-btn{ align-self:flex-start }

/* ── the sheet: RSVP and banking ─────────────────────────────────────────── */
/* Not a card. A sheet of the same paper with a hairline at the top, so it
   reads as a continuation of the page rather than an object dropped onto it. */
/* A sheet of card laid on the page. Draft two made this a bare hairline and
   it disappeared into the ground; this is paper again — but one flat tone and
   a soft shadow, not draft one's bordered, cornered, gradient-filled box. */
.sheet{
  position:relative; width:100%; margin-top:2.4rem;
  padding:clamp(1.8rem,6vw,2.6rem);
  background:#FFFDFB; border-top:2px solid var(--gold-soft);
  box-shadow:0 18px 40px -28px rgba(60,44,34,.45);
  text-align:left;
  display:flex; flex-direction:column;
}

/* ══════════════════ 6 · RSVP ══════════════════ */
.invited-chip{
  margin:0 0 1.6rem; font-family:var(--sans); font-weight:300;
  font-size:.58rem; letter-spacing:.3em; text-transform:uppercase;
  color:var(--blush-ink);
}
.rsvp-perday{
  margin:0 0 1.6rem; font-family:var(--serif); font-style:italic; font-weight:300;
  font-size:1rem; color:var(--ink-mute);
}
.rsvp-days{ display:flex; flex-direction:column; margin-bottom:2rem }
.rsvp-day{
  display:flex; flex-direction:column; gap:1rem;
  padding:1.6rem 0; border-top:1px solid var(--line-soft);
}
.rd-head{ display:flex; flex-direction:column; gap:.25rem }
.rd-tag{
  margin:0; font-family:var(--sans); font-weight:300;
  font-size:.55rem; letter-spacing:.34em; text-indent:.34em; text-transform:uppercase;
  color:var(--grey-mid);
}
.rsvp-day.is-two .rd-tag{ color:var(--blush-ink) }
.rd-when{
  margin:0; font-family:var(--serif); font-weight:300;
  font-size:clamp(1.15rem,4.6vw,1.35rem); color:var(--ink);
}
.rd-when em{ font-style:italic; color:var(--ink-mute); font-size:.88em }

.seg-row{ display:grid; grid-template-columns:1fr 1fr; gap:.5rem }
.seg{
  padding:.85rem .6rem; border-radius:0;
  background:transparent; box-shadow:inset 0 0 0 1px var(--line);
  font-family:var(--sans); font-weight:300; font-size:.58rem;
  letter-spacing:.24em; text-indent:.24em; text-transform:uppercase;
  color:var(--ink-mute);
  transition:box-shadow .35s var(--ease), color .35s var(--ease), background .35s var(--ease);
}
.seg:hover{ box-shadow:inset 0 0 0 1px var(--ink-mute); color:var(--ink) }
.seg.on{ background:var(--ink); color:var(--paper); box-shadow:none }
.seg.on.seg-no{ background:var(--grey-mid); color:var(--paper) }
.seg:focus-visible{ outline:2px solid var(--gold); outline-offset:2px }

.rd-count{ display:none }
.rsvp-day.attending .rd-count{ display:block }

.field{ position:relative; margin-top:.4rem }
.field input,.field textarea,.field select{
  width:100%; padding:1.4rem 0 .6rem; border:0;
  border-bottom:1px solid var(--line);
  background:transparent; color:var(--ink);
  font-family:var(--serif); font-weight:400; font-size:1.05rem; line-height:1.4;
  border-radius:0; outline:none; resize:none;
  transition:border-color .4s var(--ease);
}
.field select{ appearance:none; -webkit-appearance:none; cursor:pointer }
.field select option{ background:#FFFFFF; color:var(--ink) }
.field-select::after{
  content:""; position:absolute; right:.2rem; bottom:1.1rem; width:6px; height:6px;
  border-right:1px solid var(--grey-mid); border-bottom:1px solid var(--grey-mid);
  transform:rotate(45deg); pointer-events:none;
}
.field label{
  position:absolute; left:0; top:1.35rem; pointer-events:none;
  font-family:var(--sans); font-weight:300; font-size:.62rem;
  letter-spacing:.24em; text-transform:uppercase; color:var(--grey-mid);
  transition:transform .4s var(--ease), color .4s 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.15rem) scale(.86); color:var(--ink-mute);
}
.field input:focus,.field textarea:focus,.field select:focus{ border-bottom-color:var(--ink) }
.field.invalid input,.field.invalid textarea,.field.invalid select{ border-bottom-color:#A8453E }

.sheet .btn{ align-self:flex-start }
.form-error{
  margin:1rem 0 0; font-family:var(--sans); font-weight:300; font-size:.62rem;
  letter-spacing:.16em; color:#A8453E;
}

.rsvp-done{
  width:100%; margin-top:2.4rem; padding-top:2.4rem; border-top:1px solid var(--line);
  display:flex; flex-direction:column; align-items:flex-start; text-align:left;
}
.rsvp-done .wax-seal{ margin-bottom:1.4rem }
.rsvp-recap{
  list-style:none; margin:1.6rem 0 0; padding:0;
  display:flex; flex-direction:column; width:100%; max-width:22rem;
}
.rsvp-recap li{
  display:flex; justify-content:space-between; align-items:baseline; gap:1rem;
  padding:.8rem 0; border-top:1px solid var(--line-soft);
  font-family:var(--sans); font-weight:300; font-size:.56rem;
  letter-spacing:.24em; text-transform:uppercase; color:var(--grey-mid);
}
.rsvp-recap li b{
  font-family:var(--serif); font-weight:400; font-size:1.05rem;
  letter-spacing:0; text-transform:none; color:var(--ink);
}

/* ══════════════════ 7 · GIFTS ══════════════════ */
.bank-card.sealed{ opacity:0; transform:translateY(-6px) }
.bank-card.unsealed{
  opacity:1; transform:none;
  transition:opacity .6s var(--ease), transform .7s var(--ease);
}
.bank-rows{ margin:0; display:flex; flex-direction:column; width:100% }
.bank-row{
  display:flex; align-items:baseline; justify-content:space-between; gap:1rem;
  padding:.9rem 0; border-top:1px solid var(--line-soft);
}
.bank-row dt{
  font-family:var(--sans); font-weight:300;
  font-size:.55rem; letter-spacing:.28em; text-transform:uppercase; color:var(--grey-mid);
}
.bank-row dd{
  margin:0; font-family:var(--serif); font-weight:400;
  font-size:1.05rem; color:var(--ink); text-align:right;
}
/* A value the couple have not supplied — obviously unfinished, never invented */
.bank-row dd.pending{
  font-style:italic; font-size:.94rem; color:var(--grey-mid);
}
.bank-foot{ margin-top:1.4rem }

/* ══════════════════ 8 · FINALE ══════════════════ */
.finale-scene{
  position:relative; width:100%; min-height:88svh;
  display:flex; align-items:center; justify-content:center;
  /* The page ends on the strongest colour it has. */
  background:var(--blush);
}
.finale-type{
  position:relative; width:100%; max-width:var(--maxw);
  display:flex; flex-direction:column; align-items:center;
  text-align:center; padding:clamp(4rem,12vh,6rem) clamp(1.6rem,7vw,4rem);
}
.finale-seal{
  width:clamp(96px,24vw,136px); height:clamp(96px,24vw,136px);
  margin-bottom:2.4rem;
  opacity:0; transform:translateY(14px);
  transition:opacity 1.2s var(--ease), transform 1.4s var(--ease);
}
.finale-seal.in{ opacity:1; transform:none }
.finale-type .hair{ margin:1.6rem auto }
.fin-sub{
  margin:.8rem 0 0; font-family:var(--serif); font-style:italic; font-weight:300;
  font-size:clamp(1.05rem,4vw,1.18rem); color:var(--ink-soft);
}
.hashtag{
  margin:1.8rem 0 0; font-family:var(--sans); font-weight:300;
  font-size:.58rem; letter-spacing:.3em; text-indent:.3em; text-transform:uppercase;
  color:var(--grey-mid);
}

/* ══════════════════ scroll progress ══════════════════ */
.progress-rail{
  position:fixed; left:0; right:0; top:0; height:1px; z-index:60;
  background:transparent; pointer-events:none;
}
.progress-rail i{ display:block; height:100%; width:0; background:var(--gold-soft) }

/* ══════════════════ reduced motion ══════════════════ */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{
    animation-duration:.001ms !important; animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
  }
  .reveal,.hero-type [data-r],.chapter,.pr-step,.fact,.finale-seal{
    opacity:1 !important; transform:none !important;
  }
}

/* ══════════════════ STYLE PICKER ══════════════════
   Only rendered with ?pick=1 in the URL, so a guest never sees it. Remove this
   block, the markup and the head script once a direction is chosen. */
.style-pick{
  position:fixed; left:50%; bottom:14px; transform:translateX(-50%);
  z-index:90; display:flex; gap:1px;
  background:rgba(36,31,27,.9); padding:1px; border-radius:2px;
  font-family:var(--sans); font-weight:300;
}
.style-pick a{
  padding:.6rem .9rem; cursor:pointer; white-space:nowrap;
  font-size:.56rem; letter-spacing:.18em; text-transform:uppercase;
  color:rgba(255,255,255,.72); background:rgba(36,31,27,.9);
}
.style-pick a:hover{ color:#fff }
.style-pick a.on{ background:#fff; color:#241F1B }
