/* ============================================================
   Yashika & Vidur — Main Invite
   Intro (wax-sealed envelope) · Hero (garden courtyard) ·
   Scratch the date · Invitation
   House rules: border-radius 0 everywhere, no plates behind marks.
   ============================================================ */

/* The couple's names — Anastasia Script, as on prerna-weds-krishna: a
   copperplate with huge flourished capitals over a small x-height (278
   against a 730 cap), so it reads as a signature. Names only; every
   other script line stays on Great Vibes. Subset woff2 (Latin + quotes),
   the source TTF is not shipped. */
@font-face {
  font-family: "Anastasia Script";
  src: url("assets/font/anastasia_script.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

:root {
  /* the site's wine — sampled off the first (wine) envelope film; the
     seal on the ivory one carries the same red family */
  --wine: #6e1a2e;
  --wine-deep: #4c0f1f;
  /* the rose of the names on the family's printed card */
  --rose: #a62a5a;
  /* the names: a deep berry-wine, the envelope's own wine lifted a
     touch towards rose — reads on the pastel sky and on the card's
     ivory alike, where the old #a62a5a magenta went candy-pink */
  --name-ink: #7e1c40;
  --rose-soft: #c45d82;
  /* the card's olive for the request lines and parents */
  --olive: #4f5934;
  --gold: #b8904f;
  --gold-deep: #8a6431;
  --gold-light: #e7cf9c;
  --ivory: #fffaf3;
  --blush: #f7e6df;
  --paper: #f3eadd;

  --font-script: 'Great Vibes', 'Pinyon Script', cursive;
  --font-name: 'Anastasia Script', 'Great Vibes', cursive;
  --font-date: 'Bodoni Moda', 'Didot', Georgia, serif;
  --font-caps: 'Cinzel', 'Times New Roman', serif;
  --font-body: 'Cormorant Garamond', Georgia, serif;

  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-soft: cubic-bezier(0.45, 0, 0.2, 1);
}

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

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  /* NOT scroll-behavior:smooth — every scroll here that should glide asks
     for it itself, and a global smooth turns script scrolls into steps */
}

html, body {
  margin: 0;
  padding: 0;
  background: var(--blush);
  overflow-x: hidden;
}

body {
  font-family: var(--font-body);
  color: var(--wine);
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
}

img, video, canvas { display: block; }
img { -webkit-user-drag: none; user-select: none; }

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

p { margin: 0; }
h1, h2 { margin: 0; font-weight: 400; }

/* date ordinals (15th, 22nd): raised by position, not vertical-align,
   so a superscript never pushes its line taller than its neighbours */
sup {
  position: relative;
  top: -0.62em;
  margin-left: 0.04em;
  font-size: 0.55em;
  line-height: 0;
  letter-spacing: 0.02em;
  vertical-align: baseline;
}


/* ============================================================
   SECTION 1 — INTRO
   ============================================================ */
.intro-screen {
  position: fixed;
  inset: 0;
  z-index: 50;
  /* the ivory envelope's own paper (sampled off intro.mp4) under the poster */
  background: #e6dcd2 url('assets/intro/intro.webp') center / cover no-repeat;
  cursor: pointer;
  overflow: hidden;
  outline: none;
  touch-action: manipulation;
}

.intro-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  pointer-events: none;
}

/* the prompt — type straight on the film, no plate behind it. The
   envelope is IVORY (the 2026-10-05 film), so the ink is wine with an
   ivory halo to lift it off the embossed paper. */
.begin-button {
  position: absolute;
  left: 50%;
  bottom: calc(11% + env(safe-area-inset-bottom, 0px));
  transform: translateX(-50%);
  width: max-content;
  max-width: calc(100% - 32px);
  padding: 14px 18px;
  text-align: center;
  font-family: var(--font-caps);
  font-size: clamp(0.84rem, 4.1vw, 1.02rem);
  font-weight: 600;
  letter-spacing: 0.3em;
  text-indent: 0.3em;
  text-transform: uppercase;
  color: var(--wine);
  text-shadow:
    0 0 1px rgba(255, 250, 243, 0.95),
    0 0 8px rgba(255, 250, 243, 0.9),
    0 0 18px rgba(255, 250, 243, 0.7);
  transition: opacity 400ms var(--ease-soft);
}
.begin-button .begin-main {
  display: inline-block;
  animation: beginPulse 2400ms ease-in-out infinite;
}
.begin-button::after {
  content: '';
  display: block;
  width: 64%;
  height: 1px;
  margin: 11px auto 0;
  background: linear-gradient(90deg, transparent, var(--gold-deep), transparent);
  opacity: 0.9;
}

.begin-button.is-loading { opacity: 0.55; }
.begin-button.is-loading .begin-main { animation: none; }
.begin-button.is-hidden { opacity: 0; pointer-events: none; }

@keyframes beginPulse {
  0%, 100% { opacity: 0.74; }
  50%      { opacity: 1; }
}

.intro-screen.is-fading {
  opacity: 0;
  transition: opacity 500ms linear;
}

/* blush veil between envelope and garden — up over the envelope first,
   the envelope removed behind it, then down onto the hero */
.blush-veil {
  position: fixed;
  inset: 0;
  z-index: 51;
  pointer-events: none;
  opacity: 0;
  background:
    radial-gradient(ellipse at 50% 45%, #fffaf4 0%, #fbeee6 45%, #f3d9d0 100%);
}
.blush-veil.is-active { animation: veilPass 1700ms var(--ease-soft) forwards; }

@keyframes veilPass {
  0%   { opacity: 0; }
  30%  { opacity: 1; }
  48%  { opacity: 1; }
  100% { opacity: 0; }
}


/* ============================================================
   SECTION 2 — HERO
   ============================================================ */
.hero-screen {
  position: relative;
  container-type: inline-size;
  min-height: 100vh;
  min-height: 100svh;
  overflow: hidden;
  background: #f4dfd6;
  isolation: isolate;
}

.hero-film {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.hero-bg {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
}

/* The boughs are full-canvas cut-outs (941x1672, real alpha), but their
   ink is not the same size: the left one fills 593x453 from the top-left
   corner, the right one 539x840 from the top-right, so at one shared scale
   the right garlands hung twice as far. Each is scaled on its OWN so both
   drop exactly --bough-drop, anchored to its corner:
     width = drop x 941 / ink height  (453 left, 840 right)
   pointer-events:none — mostly transparent, must not swallow a swipe. */
.hero-screen { --bough-drop: 33cqw; }
.hero-bough {
  position: absolute;
  top: 0;
  z-index: 2;
  height: auto;
  pointer-events: none;
  opacity: 0;
  transform: translateY(-22%);
  will-change: transform;
}
.hero-bough--left  { left: 0;  width: calc(var(--bough-drop) * 941 / 453); transform-origin: 8% 0; }
.hero-bough--right { right: 0; width: calc(var(--bough-drop) * 941 / 840); transform-origin: 92% 0; }

.hero-screen.is-animated .hero-bough {
  animation:
    boughDrop 1800ms var(--ease-out) 500ms forwards,
    boughSwayL 7.5s ease-in-out 2300ms infinite;
}
.hero-screen.is-animated .hero-bough--right {
  animation:
    boughDrop 1800ms var(--ease-out) 700ms forwards,
    boughSwayR 8.6s ease-in-out 2500ms infinite;
}

@keyframes boughDrop {
  from { opacity: 0; transform: translateY(-22%); }
  to   { opacity: 1; transform: none; }
}
@keyframes boughSwayL {
  0%, 100% { opacity: 1; transform: rotate(0deg); }
  50%      { opacity: 1; transform: rotate(1.1deg); }
}
@keyframes boughSwayR {
  0%, 100% { opacity: 1; transform: rotate(0deg); }
  50%      { opacity: 1; transform: rotate(-1deg); }
}

/* The names stand in the open sky between the boughs. Sized in cqw off
   the hero's own width so the block keeps its place against the boughs,
   which also scale with the width. */
.hero-content {
  position: absolute;
  z-index: 3;
  left: 0;
  right: 0;
  /* positioned in the center blank space of the portrait hero background */
  top: 46cqw;
  padding: 0 6cqw;
  text-align: center;
  color: var(--wine);
}

.hero-eyebrow {
  font-family: var(--font-caps);
  font-size: clamp(0.66rem, 3.1cqw, 0.9rem);
  font-weight: 600;
  letter-spacing: 0.3em;
  text-indent: 0.3em;
  text-transform: uppercase;
  color: var(--wine);
  text-shadow: 0 0 10px rgba(255, 250, 243, 0.95), 0 0 2px rgba(255, 250, 243, 0.9);
  opacity: 0;
}

.hero-names {
  margin-top: 1.4cqw;
  font-family: var(--font-name);
  color: var(--name-ink);
  line-height: 0.95;
}
.hn-line,
.hn-amp {
  display: block;
  opacity: 0;
  text-shadow:
    0 0 18px rgba(255, 250, 243, 0.95),
    0 0 6px rgba(255, 250, 243, 0.85);
}
.hn-line { font-size: 15.4cqw; line-height: 1.0; padding: 0 0.2em; }
/* Centred by INK, not by advance: Anastasia's capitals swing far out
   to the left while the words end on a short tail, so a box-centred
   name sits right of the axis (measured with canvas actualBoundingBox:
   Yashika +0.17em, Vidur +0.22em). `left` rather than a transform,
   which the write-on animations own. Same offsets on the card below. */
.hn-line--bride,
.inv-name--bride { position: relative; left: -0.17em; }
/* Vidur goes a further 0.1em left of its ink centre (2026-10-08, client
   said "off center"): the V's entry hook is a hairline, so the eye centres
   on the heavy "idur", which sat ~10px right of the axis. */
.hn-line--groom,
.inv-name--groom { position: relative; left: -0.32em; }
.hn-amp {
  /* Cormorant's italic ampersand, in gold: a script one between two
     script names turns the three into one tangle */
  font-family: var(--font-body);
  font-style: italic;
  font-weight: 500;
  font-size: 8cqw;
  line-height: 1;
  margin: 0.2cqw 0;
  color: var(--gold-deep);
}

.hero-place {
  margin-top: 3cqw;
  font-family: var(--font-caps);
  font-size: clamp(0.78rem, 3.9cqw, 1.05rem);
  font-weight: 600;
  letter-spacing: 0.28em;
  text-indent: 0.28em;
  text-transform: uppercase;
  color: var(--wine);
  text-shadow: 0 0 10px rgba(255, 250, 243, 0.95), 0 0 2px rgba(255, 250, 243, 0.9);
  opacity: 0;
}

/* the arrival — timed from the veil starting to lift */
.hero-screen.is-animated .hero-eyebrow { animation: heroRise 1100ms var(--ease-out) 900ms forwards; }
.hero-screen.is-animated .hn-line--bride { animation: heroName 1500ms var(--ease-out) 1150ms forwards; }
.hero-screen.is-animated .hn-amp { animation: heroRise 1100ms var(--ease-out) 1650ms forwards; }
.hero-screen.is-animated .hn-line--groom { animation: heroName 1500ms var(--ease-out) 1900ms forwards; }
.hero-screen.is-animated .hero-place { animation: heroRise 1100ms var(--ease-out) 2550ms forwards; }

@keyframes heroRise {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}
@keyframes heroName {
  from { opacity: 0; transform: translateY(14px) scale(0.96); filter: blur(4px); }
  to   { opacity: 1; transform: none; filter: blur(0); }
}

/* scroll cue — wine type on the mist the floor dissolves into (see
   SEAMS); an ivory halo, no plate */
.scroll-cue {
  position: absolute;
  z-index: 4;
  left: 50%;
  bottom: calc(18px + env(safe-area-inset-bottom, 0px));
  transform: translateX(-50%) translateY(8px);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 900ms var(--ease-soft), transform 900ms var(--ease-out);
}
.hero-screen.is-cue .scroll-cue { opacity: 1; transform: translateX(-50%); }
.scroll-cue-label {
  font-family: var(--font-caps);
  font-size: 0.86rem;
  font-weight: 700;
  letter-spacing: 0.3em;
  text-indent: 0.3em;
  text-transform: uppercase;
  color: var(--wine);
  text-shadow: 0 0 8px rgba(255, 250, 243, 0.95), 0 0 2px rgba(255, 250, 243, 0.9);
}
.scroll-arrows {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.scroll-arrows i {
  display: block;
  width: 13px;
  height: 13px;
  margin-top: -4px;
  border-right: 2px solid var(--wine);
  border-bottom: 2px solid var(--wine);
  transform: rotate(45deg);
  filter: drop-shadow(0 0 3px rgba(255, 250, 243, 0.95));
  opacity: 0.25;
  animation: cueArrow 1800ms ease-in-out infinite;
}
.scroll-arrows i:nth-child(2) { animation-delay: 200ms; }
.scroll-arrows i:nth-child(3) { animation-delay: 400ms; }

@keyframes cueArrow {
  0%, 100% { opacity: 0.2; }
  40%      { opacity: 1; }
}


/* ============================================================
   SECTION 3 — SCRATCH THE DATE
   ============================================================ */
.scratch-section {
  position: relative;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  isolation: isolate;
  background: #f8e7de;
}

.scratch-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  background: url('assets/scratch/scratch_date_bg.webp') center / cover no-repeat;
}

.petal-canvas {
  position: absolute;
  inset: 0;
  z-index: 5;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* the 941x1672 canvas every layer of this card is drawn on */
.scratch-stage {
  position: relative;
  z-index: 2;
  container-type: inline-size;
  width: 100%;
  aspect-ratio: 941 / 1672;
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 1000ms var(--ease-soft), transform 1200ms var(--ease-out);
}
.scratch-section.is-in .scratch-stage { opacity: 1; transform: none; }

.scratch-heading {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 66.5%;
  padding: 0 16px;
  text-align: center;
}
.sh-eyebrow {
  font-family: var(--font-script);
  font-size: 13cqw;
  line-height: 1.05;
  color: var(--name-ink);
  text-shadow: 0 0 14px rgba(255, 250, 243, 0.9);
}
.sh-ornament {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin: 2.4cqw 0 3cqw;
}
.sh-rule {
  width: 16cqw;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--gold-deep));
}
.sh-rule:last-child { background: linear-gradient(90deg, var(--gold-deep), transparent); }
.sh-diamond {
  width: 6px;
  height: 6px;
  background: var(--gold-deep);
  transform: rotate(45deg);
}
.sh-cta {
  font-family: var(--font-caps);
  font-size: clamp(0.66rem, 3.2cqw, 0.88rem);
  font-weight: 600;
  letter-spacing: 0.22em;
  text-indent: 0.22em;
  text-transform: uppercase;
  color: var(--wine);
  text-shadow: 0 0 10px rgba(255, 250, 243, 0.95);
  transition: opacity 700ms var(--ease-soft);
}
.sh-cta.is-swapping { opacity: 0; }

.scratch-frame-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  filter: drop-shadow(0 6px 14px rgba(110, 26, 46, 0.18));
}

/* the oval window, 4px inside the frame's cream (see index.html) */
.scratch-aperture {
  position: absolute;
  left: 10.1%;
  top: 40.73%;
  width: 80.13%;
  height: 18.84%;
  clip-path: ellipse(50% 50% at 50% 50%);
}

.scratch-reveal {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  color: var(--wine);
  background: radial-gradient(ellipse at 50% 50%, #fffdf8 0%, #fbf3e6 70%, #f5e7d4 100%);
}
/* One face, one ink — Bodoni Moda, a high-contrast Didone, all in the
   wine. The date is set big in the italic (its hairlines and ball
   terminals are the flourish); the weekday and the year are its small
   letterspaced roman either side, the weekday between two gold
   hairlines. Lining figures by default. */
.sd-weekday,
.sd-date,
.sd-year {
  font-family: var(--font-date);
  font-optical-sizing: auto;
  font-variant-numeric: lining-nums;
  color: var(--wine);
  line-height: 1.05;
}
.sd-weekday {
  display: flex;
  align-items: center;
  gap: 2.4cqw;
  font-size: 3.3cqw;
  font-weight: 500;
  letter-spacing: 0.34em;
  text-indent: 0.34em;
  text-transform: uppercase;
}
.sd-weekday::before,
.sd-weekday::after {
  content: '';
  width: 7cqw;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--gold));
}
.sd-weekday::after { background: linear-gradient(90deg, var(--gold), transparent); }
.sd-date {
  margin: 1.4cqw 0 1.6cqw;
  font-size: 8.4cqw;
  font-style: italic;
  font-weight: 400;
  letter-spacing: 0.01em;
}
.sd-year {
  font-size: 3.4cqw;
  font-weight: 600;
  letter-spacing: 0.5em;
  text-indent: 0.5em;
}
.sd-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* the dates are struck once the foil is off */
.scratch-reveal > p { transform: scale(0.98); transition: transform 900ms var(--ease-out); }
.scratch-aperture.is-revealed .scratch-reveal > p { transform: none; }

.scratch-canvas,
.sand-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.scratch-canvas {
  z-index: 2;
  touch-action: none;
  cursor: grab;
  outline: none;
}
.sand-canvas { z-index: 3; pointer-events: none; }

/* a sheen crossing the foil so it reads as something to touch */
.scratch-glint {
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  overflow: hidden;
  transition: opacity 500ms;
}
.scratch-glint::before {
  content: '';
  position: absolute;
  top: -20%;
  bottom: -20%;
  width: 30%;
  left: -40%;
  background: linear-gradient(100deg, transparent, rgba(255, 248, 230, 0.55), transparent);
  transform: skewX(-18deg);
  animation: glint 3600ms ease-in-out 1200ms infinite;
}
.scratch-aperture.is-scratching .scratch-glint,
.scratch-aperture.is-revealed .scratch-glint { opacity: 0; }

@keyframes glint {
  0%   { left: -40%; }
  55%  { left: 120%; }
  100% { left: 120%; }
}

.scratch-hint {
  position: absolute;
  inset: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  font-family: var(--font-caps);
  font-size: 3.9cqw;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-indent: 0.2em;
  text-transform: uppercase;
  /* struck INTO the foil: the envelope's wine, with a light lip under
     each letter — white on the pale rose-gold all but vanished */
  color: #5e1427;
  text-shadow:
    0 1px 0 rgba(255, 240, 214, 0.75),
    0 0 10px rgba(255, 238, 210, 0.55);
  animation: beginPulse 2400ms ease-in-out infinite;
}

.scratch-glow {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 6;
  width: 64px;
  height: 64px;
  margin: -32px 0 0 -32px;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(circle, rgba(255, 246, 222, 0.7) 0%, rgba(255, 236, 200, 0) 70%);
  transition: opacity 250ms;
}
.scratch-glow.is-active { opacity: 1; }

/* note + plate, below the frame's lower rim (frame ends at 64.4%) */
.scratch-after {
  position: absolute;
  left: 0;
  right: 0;
  top: 67%;
  display: grid;
  place-items: center;
  padding: 0 16px;
}
/* the cue and the plate share one cell */
.scratch-after > * { grid-area: 1 / 1; }
.scratch-after .sh-cta {
  text-align: center;
  white-space: nowrap;
  font-size: clamp(0.68rem, 3.3cqw, 0.88rem);
  letter-spacing: 0.16em;
  text-indent: 0.16em;
  text-shadow:
    0 0 2px rgba(255, 250, 243, 0.95),
    0 0 10px rgba(255, 250, 243, 0.95),
    0 0 22px rgba(255, 250, 243, 0.8);
}
.scratch-after .sh-cta::before,
.scratch-after .sh-cta::after {
  content: '';
  display: block;
  width: 9cqw;
  height: 1px;
  margin: 0 auto;
  background: linear-gradient(90deg, transparent, var(--gold-deep), transparent);
}
.scratch-after .sh-cta::before { margin-bottom: 2.6cqw; }
.scratch-after .sh-cta::after { margin-top: 2.6cqw; }
.sh-cta.is-swapping { pointer-events: none; }

/* A foil-stamped plate: chamfered (cut, never rounded), in the rose-gold
   of the scratch foil, an engraved rule struck inside it. */
.date-cta {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: min(78cqw, 330px);
  padding: 17px 30px;
  opacity: 0;
  visibility: hidden;
  touch-action: manipulation;
}
/* it pops — a quick overshoot up from a little below its size — then
   breathes, and a sheen crosses the plate every few seconds */
.date-cta.is-in {
  visibility: visible;
  animation:
    ctaPop 900ms cubic-bezier(0.34, 1.56, 0.64, 1) forwards,
    ctaBreathe 2800ms ease-in-out 1400ms infinite;
}
@keyframes ctaPop {
  0%   { opacity: 0; transform: translateY(14px) scale(0.72); }
  60%  { opacity: 1; }
  100% { opacity: 1; transform: none; }
}
@keyframes ctaBreathe {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 1; transform: scale(1.045); }
}
.dc-plate {
  position: absolute;
  inset: 0;
  background: linear-gradient(110deg, #7a1f38 0%, #9b3150 45%, #7a1f38 100%);
  clip-path: polygon(12px 0, calc(100% - 12px) 0, 100% 50%, calc(100% - 12px) 100%, 12px 100%, 0 50%);
  filter: drop-shadow(0 6px 12px rgba(80, 14, 32, 0.3));
}
.dc-plate::before {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: -45%;
  width: 34%;
  background: linear-gradient(100deg, transparent, rgba(255, 238, 204, 0.5), transparent);
  transform: skewX(-20deg);
}
.date-cta.is-in .dc-plate::before { animation: ctaSheen 3400ms ease-in-out 900ms infinite; }
@keyframes ctaSheen {
  0%   { left: -45%; }
  40%  { left: 120%; }
  100% { left: 120%; }
}
.dc-plate::after {
  content: '';
  position: absolute;
  inset: 4px;
  clip-path: polygon(10px 0, calc(100% - 10px) 0, 100% 50%, calc(100% - 10px) 100%, 10px 100%, 0 50%);
  box-shadow: inset 0 0 0 1px rgba(231, 207, 156, 0.85);
  background:
    linear-gradient(90deg, rgba(231, 207, 156, 0.85), rgba(231, 207, 156, 0.85)) top / 100% 1px no-repeat,
    linear-gradient(90deg, rgba(231, 207, 156, 0.85), rgba(231, 207, 156, 0.85)) bottom / 100% 1px no-repeat;
}
.dc-inner {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
.dc-label {
  font-family: var(--font-caps);
  font-size: clamp(0.78rem, 3.8cqw, 1rem);
  font-weight: 600;
  letter-spacing: 0.2em;
  text-indent: 0.2em;
  text-transform: uppercase;
  color: #f6e4bd;
  white-space: nowrap;
}
.dc-ornament {
  width: 5px;
  height: 5px;
  background: var(--gold-light);
  transform: rotate(45deg);
}

/* THE WAY ON, HELD SHUT — added by script.js only, so a page whose
   script never ran is simply the whole invitation */
body.is-sealed .invite-screen { display: none; }


/* ============================================================
   SECTION 4 — THE INVITATION
   ============================================================ */
.invite-screen {
  position: relative;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 28px 0;
  overflow: hidden;
  isolation: isolate;
  background: var(--paper) url('assets/invite/invite_bg.webp') center / cover no-repeat;
}

.inv-card {
  position: relative;
  container-type: inline-size;
  /* the PNG carries ~5% clear margin and a pink under-sheet each side,
     so 110% of the column puts the ivory leaf at ~88% of the screen;
     the under-sheet's outer edge just meets the screen edge */
  width: min(110%, calc((100svh - 40px) * 0.6671));
  min-width: min(100%, 300px);
  aspect-ratio: 1024 / 1535;
  margin: auto 0;
  filter: drop-shadow(0 10px 22px rgba(110, 26, 46, 0.16));
}
.inv-card__paper {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* the inner gold rule runs 14.6%-86.1% across and 9.8%-86.5% down
   (measured off invite_card.webp); the text is held inside it, clear of
   the corner sprigs and of the bottom rule */
.invite-content {
  position: absolute;
  left: 17.2%;
  right: 16.4%;
  top: 11%;
  bottom: 15.4%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
}
.invite-content > * { flex-shrink: 0; }

/* lord_Ganesha.webp is 1254 square with its ink at x 273-980, y 162-1025.
   Sized by the INK (9cqi wide): the image is 1254/707 of that, and
   negative margins trim the empty rows above and below the drawing. */
.inv-mark {
  width: 14cqi;
  height: 14cqi;
  margin: 0 0 1.2cqi 0;
  filter: drop-shadow(0 2px 6px rgba(110, 26, 46, 0.22));
}

.inv-sacred {
  font-family: var(--font-body);
  font-style: italic;
  font-weight: 600;
  font-size: 2.8cqi;
  line-height: 1.35;
  letter-spacing: 0.04em;
  color: var(--wine);
  margin-bottom: 0.8cqi;
  max-width: 95%;
}

/* The blessing is ONE block, as on the printed card: the head and each
   grandparents' line set alike, every couple on its own single line
   (nowrap — a couple split across two lines read as a ragged list),
   held tight so the four lines read together. */
.inv-sacred + .inv-sacred { margin-top: 0.5cqi; }
.inv-blessing-head,
.inv-blessing {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 2.56cqi;
  line-height: 1.36;
  letter-spacing: 0.015em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--wine);
}
.inv-blessing-head { margin-top: 3.6cqi; }
.inv-blessing--amp {
  font-size: 2.4cqi;
  line-height: 1.2;
  color: var(--gold-deep);
}

/* two lines, broken where the printed card breaks them (the <br>) */
.inv-request {
  margin-top: 2.2cqi;
  margin-bottom: 2.2cqi;
  font-family: var(--font-body);
  font-style: italic;
  font-weight: 600;
  font-size: 2.85cqi;
  line-height: 1.38;
  white-space: normal;
  text-wrap: balance;
  max-width: 95%;
  color: var(--olive);
}

.inv-name {
  font-family: var(--font-name);
  font-size: 12.2cqi;
  line-height: 1.03;
  color: var(--name-ink);
  padding: 0 0.12em;
}
.inv-name--bride { margin-top: 1.8cqi; }

.inv-parents {
  margin-top: 0.6cqi;
  font-family: var(--font-body);
  font-style: italic;
  font-weight: 700;
  /* small caps in brackets, as printed. Kept clear of the bottom corner
     sprigs (they fill 79-87% down, 14.6-24% in from each side): the
     whole stack is short enough that this line ends above them */
  font-size: 2.6cqi;
  line-height: 1.3;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--olive);
}

.inv-amp {
  margin: 1cqi 0 -0.4cqi;
  font-family: var(--font-body);
  font-style: italic;
  font-weight: 500;
  font-size: 6.6cqi;
  line-height: 1;
  color: var(--gold-deep);
}

/* ── the reveal, staged down the leaf ──
   ONE motion for every line, so nothing on the card jumps: the leaf
   settles first, then each line breathes up out of a soft blur, top to
   bottom, on a long ease. No letter-spacing tracks (a line that widens
   re-wraps mid-animation and snaps), no letter splits, no rotation —
   only the names are written on, slowly, as the hero's are.
   Hidden only under .js-gate, which the script adds — script-off is
   simply the whole card. */
.invite-screen.js-gate .inv-card { opacity: 0; transform: translateY(26px) scale(0.985); }
.invite-screen.js-gate .invite-content > *,
.invite-screen.js-gate .inv-word { opacity: 0; }
.invite-screen.js-gate .inv-request { opacity: 1; }

.invite-screen.is-revealed .inv-card {
  animation: invLeaf 1600ms var(--ease-out) forwards;
}
.invite-screen.is-revealed .invite-content > * {
  animation: invRise 1500ms var(--ease-out) var(--d, 0ms) forwards;
}
.invite-screen.is-revealed .inv-request { animation: none; }
.invite-screen.is-revealed .inv-word {
  animation: invRise 1300ms var(--ease-out) calc(var(--d, 0ms) + var(--wi) * 70ms) forwards;
}
.inv-word { display: inline-block; }

/* children, in order: mark, sacred x2, head, blessing, &, blessing,
   request, bride, her parents, &, groom, his parents */
.invite-content > :nth-child(1)  { --d: 450ms; }
.invite-content > :nth-child(2)  { --d: 800ms; }
.invite-content > :nth-child(3)  { --d: 980ms; }
.invite-content > :nth-child(4)  { --d: 1250ms; }
.invite-content > :nth-child(5)  { --d: 1430ms; }
.invite-content > :nth-child(6)  { --d: 1580ms; }
.invite-content > :nth-child(7)  { --d: 1730ms; }
.invite-content > :nth-child(8)  { --d: 2050ms; }
.invite-content > :nth-child(9)  { --d: 3000ms; }
.invite-content > :nth-child(10) { --d: 4000ms; }
.invite-content > :nth-child(11) { --d: 4350ms; }
.invite-content > :nth-child(12) { --d: 4650ms; }
.invite-content > :nth-child(13) { --d: 5600ms; }

.invite-screen.is-revealed .inv-mark { animation-name: invMark; animation-duration: 1800ms; }
.invite-screen.is-revealed .inv-amp  { animation-name: invAmp; animation-duration: 1400ms; }

@keyframes invLeaf {
  to { opacity: 1; transform: none; }
}
@keyframes invRise {
  from { opacity: 0; transform: translateY(14px); filter: blur(5px); }
  60%  { filter: blur(0); }
  to   { opacity: 1; transform: none; filter: blur(0); }
}
@keyframes invMark {
  from { opacity: 0; transform: scale(0.9); filter: blur(5px); }
  to   { opacity: 1; transform: none; filter: blur(0); }
}
@keyframes invAmp {
  from { opacity: 0; transform: scale(0.8); filter: blur(4px); }
  to   { opacity: 1; transform: none; filter: blur(0); }
}

/* ============================================================
   SECTION 5 — THE CELEBRATIONS
   One full-screen card per event. Everything is sized in cqw off
   .events, so a card keeps its composition on every phone and inside
   the 480px desktop column.
   ============================================================ */
.events {
  position: relative;
  container-type: inline-size;
  --ev-wine: #3a0b19;
  background: var(--ev-wine);
}

/* ── each card's own dusk ──
   The film's floor goes down into a deep tone drawn from that film's
   own palette (one flat wine read as a foreign weight on the pastel
   scenes): --ev-deep is where the card ENDS, --ev-mid tints the way
   down, and --ev-from is the card above's --ev-deep, which this card's
   top band starts from — so every join is one colour meeting itself. */
#ev-wedding   { --ev-deep: 58, 11, 25;  --ev-mid: 168, 64, 64;  --ev-from: 251, 222, 208; }
#ev-reception { --ev-deep: 21, 29, 61;  --ev-mid: 66, 80, 136;  --ev-from: 58, 11, 25; }

/* THE WAY ON stays shut for these too */
body.is-sealed .events,
body.is-sealed .site-footer { display: none; }


/* ── the event cards ── */
.ev-card {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100svh;
  background: rgb(var(--ev-deep));
}

/* The film is shown WHOLE, at full width and its own 4:7 (768x1344),
   never cover-cropped: the couple stand low in these paintings, and a
   venue block laid over a full-screen crop sat on their knees. The
   venue lives on the wine below instead, overlapping only the floor. */
.ev-film {
  position: relative;
  z-index: 0;
  flex: 0 0 auto;
  width: 100%;
  aspect-ratio: 768 / 1344;
  overflow: hidden;
}
.ev-bg {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* A short fade that is ALWAYS there, so the film never meets the
   card's flat colour on a hard edge — even before the card is visited. */
.ev-film::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -2px;
  height: calc(9% + 2px);
  pointer-events: none;
  background:
    linear-gradient(180deg, rgba(var(--ev-deep), 0) 0%, rgb(var(--ev-deep)) 100%);
}

/* The dusk proper, over the lower part of the film: it rises from the
   floor, through the film's own mid-tone, into the deep — and only when
   the guest arrives at the card (.is-lit, toggled by script.js, so it
   gathers again on every visit). Its last rows are solid --ev-deep. */
.ev-shade {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(175cqw * 0.54);
  height: calc(175cqw * 0.46 + 4px);
  z-index: 1;
  pointer-events: none;
  transform-origin: 50% 100%;
  background:
    linear-gradient(180deg,
      rgba(var(--ev-mid), 0) 0%,
      rgba(var(--ev-mid), 0.16) 26%,
      rgba(var(--ev-deep), 0.42) 48%,
      rgba(var(--ev-deep), 0.78) 68%,
      rgba(var(--ev-deep), 0.95) 86%,
      rgb(var(--ev-deep)) calc(100% - 4px));
}
.events.js-ev .ev-shade {
  opacity: 0;
  transform: translateY(14%) scaleY(0.6);
  transition:
    opacity 1500ms var(--ease-soft),
    transform 2000ms var(--ease-out);
}
.events.js-ev .ev-card.is-lit .ev-shade { opacity: 1; transform: none; }

/* a low warm light under the venue, breathing in after the dusk */
.ev-foot::before {
  content: '';
  position: absolute;
  z-index: -1;
  left: 0;
  right: 0;
  top: -6cqw;
  bottom: 0;
  pointer-events: none;
  background: radial-gradient(ellipse 62% 46% at 50% 44%,
    rgba(var(--ev-mid), 0.5) 0%,
    rgba(var(--ev-mid), 0.18) 48%,
    rgba(var(--ev-mid), 0) 76%);
}
.events.js-ev .ev-foot::before {
  opacity: 0;
  transition: opacity 1800ms var(--ease-soft) 700ms;
}
.events.js-ev .ev-card.is-lit .ev-foot::before { opacity: 1; }

/* the sky block — name and date, high in the painting */
.ev-top {
  position: absolute;
  z-index: 2;
  left: 0;
  right: 0;
  top: calc(175cqw * 0.095);
  padding: 0 9cqw;
  text-align: center;
  color: var(--wine);
}
/* a feathered breath of ivory behind it, so the wine ink holds on the
   lanterns and garlands — no edge, nothing that reads as a plate */
.ev-top::before {
  content: '';
  position: absolute;
  z-index: -1;
  left: -10cqw;
  right: -10cqw;
  top: -14cqw;
  bottom: -12cqw;
  background: radial-gradient(ellipse 54% 52% at 50% 50%,
    rgba(255, 250, 243, 0.86) 0%,
    rgba(255, 250, 243, 0.66) 40%,
    rgba(255, 250, 243, 0.28) 62%,
    rgba(255, 250, 243, 0) 80%);
}

.ev-name {
  display: block;
  /* padded out and pulled back by the same amount: the write-on mask
     clips to the box, and Great Vibes swings well outside its own */
  margin: 0 -8cqw;
  padding: 1.5cqw 8cqw 2.5cqw;
  font-family: var(--font-script);
  font-weight: 400;
  font-size: 11cqw;
  line-height: 1.08;
  color: var(--name-ink);
  /* a tight ivory core holds the hairlines where they cross a lantern
     or a garland, the wider washes lift the whole word off the art */
  text-shadow:
    0 0 1px rgba(255, 250, 243, 0.95),
    0 0 4px rgba(255, 250, 243, 0.9),
    0 0 12px rgba(255, 250, 243, 0.9),
    0 0 26px rgba(255, 250, 243, 0.75);
}
.ev-kicker {
  display: block;
  /* Great Vibes' M swings up past the cap line — held clear of it */
  margin-bottom: 1.8cqw;
  font-family: var(--font-caps);
  font-size: 3.6cqw;
  font-weight: 600;
  letter-spacing: 0.42em;
  text-indent: 0.42em;
  text-transform: uppercase;
  line-height: 1.4;
  color: var(--wine);
}

.ev-date {
  margin-top: 0.4cqw;
  font-family: var(--font-date);
  font-optical-sizing: auto;
  font-variant-numeric: lining-nums;
  font-style: italic;
  font-size: 5.4cqw;
  font-weight: 500;
  color: var(--wine);
  text-shadow:
    0 0 1px rgba(255, 250, 243, 0.95),
    0 0 4px rgba(255, 250, 243, 0.92),
    0 0 14px rgba(255, 250, 243, 0.9);
}

/* OPEN-SKY films (the Chowki's bare shrine wall, the Sagan's night sky):
   the painting leaves its top ~45% empty — wall 10-44%, sky 8-43% of
   the film, measured off the posters — and a one-line title at the top
   left a tall blank between the date and the scene, which a big phone
   only made taller. The title is set LARGE on two lines and dropped to
   the middle of that open band, so the type fills it as the subject. */
.ev-card--open .ev-top { top: calc(175cqw * var(--ev-top-at, 0.14)); }
#ev-wedding   { --ev-top-at: 0.16; }
#ev-reception { --ev-top-at: 0.13; }
.ev-card--open .ev-name { font-size: 15.5cqw; line-height: 1; }
.ev-card--open .ev-date { margin-top: 1.6cqw; font-size: 6.2cqw; }
.ev-card--open .ev-top::before { top: -10cqw; bottom: -10cqw; }

/* night films (the wedding's starlit sky) and the Chowki's lamp-light:
   ivory and gold on the dark, a dusk shadow in place of the ivory breath */
.ev-card--night .ev-top { color: #fff4e2; }
.ev-card--night .ev-top::before {
  background: radial-gradient(ellipse 50% 50% at 50% 50%,
    rgba(16, 20, 52, 0.42) 0%,
    rgba(16, 20, 52, 0.2) 45%,
    rgba(16, 20, 52, 0) 72%);
}
.ev-card--night .ev-name {
  color: #fff1dc;
  text-shadow: 0 0 22px rgba(255, 214, 160, 0.45), 0 2px 10px rgba(10, 8, 30, 0.55);
}
.ev-card--night .ev-kicker,
.ev-card--night .ev-date {
  color: #fbe9cf;
  text-shadow: 0 1px 10px rgba(10, 8, 30, 0.7);
}

/* the Sagan's emerald ballroom: the shadow behind its ivory type is the
   film's own night green, not the wedding's midnight blue */
#ev-reception.ev-card--night .ev-top::before {
  background: radial-gradient(ellipse 50% 50% at 50% 50%,
    rgba(6, 22, 19, 0.5) 0%,
    rgba(6, 22, 19, 0.24) 45%,
    rgba(6, 22, 19, 0) 72%);
}
#ev-reception.ev-card--night .ev-name {
  text-shadow: 0 0 22px rgba(255, 214, 150, 0.4), 0 2px 10px rgba(4, 16, 13, 0.6);
}

/* the venue block, on the dusk below the film — it rides up over the
   faded floor, and takes whatever the screen has left, centred */
.ev-foot {
  position: relative;
  z-index: 2;
  isolation: isolate;
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  margin-top: -16cqw;
  padding: 0 10cqw calc(9cqw + env(safe-area-inset-bottom, 0px));
  text-align: center;
  color: #fff4e6;
}
.ev-time {
  font-family: var(--font-caps);
  font-size: 3.9cqw;
  font-weight: 600;
  letter-spacing: 0.26em;
  text-indent: 0.26em;
  text-transform: uppercase;
  color: var(--gold-light);
}
.ev-time-note {
  margin-top: 1.2cqw;
  font-family: var(--font-body);
  font-style: italic;
  font-weight: 500;
  font-size: 4.3cqw;
  font-variant-numeric: lining-nums;
  color: #f6e2c8;
}
.ev-foot-rule {
  display: block;
  width: 22cqw;
  height: 1px;
  margin: 3.6cqw auto 3.2cqw;
  background: linear-gradient(90deg, transparent, var(--gold-light), transparent);
}
.ev-venue {
  font-family: var(--font-body);
  font-style: italic;
  font-weight: 600;
  font-size: 7.4cqw;
  line-height: 1.12;
  text-wrap: balance;
  color: #fff6ea;
}
.ev-addr {
  /* held in from the edges: the music and menu marks are pinned in the
     bottom-right corner, and an address line ran under them (left edge
     of the marks = width - 70px, i.e. 82% at 390px, 81% at 360px) */
  max-width: 62cqw;
  margin-top: 1.6cqw;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 4.2cqw;
  line-height: 1.35;
  font-variant-numeric: lining-nums;
  text-wrap: balance;
  color: rgba(255, 240, 222, 0.86);
}
.ev-map {
  display: inline-block;
  margin-top: 4.4cqw;
  padding: 1.6cqw 1cqw;
  font-family: var(--font-caps);
  font-size: 3cqw;
  font-weight: 600;
  letter-spacing: 0.26em;
  text-indent: 0.26em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--gold-light);
  background:
    linear-gradient(90deg, var(--gold-light), var(--gold-light)) 50% 100% / 100% 1px no-repeat;
  touch-action: manipulation;
}


/* ── the text animations ──
   Every hidden state lives under .js-ev, which the script adds — a page
   whose script never ran is simply every card, set. Each card plays once,
   the first time it is well into view. */

/* split letters and words (script.js) */
.ev-w { display: inline-block; white-space: nowrap; }
.ev-c { display: inline-block; }

/* a card */
.events.js-ev .ev-card .ev-bg { transform: scale(1.12); }
.events.js-ev .ev-card .ev-top::before { opacity: 0; }
.events.js-ev .ev-name {
  -webkit-mask-image: linear-gradient(90deg, #000 40%, transparent 60%);
          mask-image: linear-gradient(90deg, #000 40%, transparent 60%);
  -webkit-mask-size: 250% 100%;
          mask-size: 250% 100%;
  -webkit-mask-position: 100% 0;
          mask-position: 100% 0;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
}
.events.js-ev .ev-kicker { opacity: 0; letter-spacing: 0.9em; }
.events.js-ev .ev-card .ev-date .ev-c,
.events.js-ev .ev-card .ev-time .ev-c { opacity: 0; transform: translateY(0.45em); filter: blur(3px); }
.events.js-ev .ev-foot-rule { transform: scaleX(0); }
.events.js-ev .ev-time-note,
.events.js-ev .ev-venue,
.events.js-ev .ev-addr,
.events.js-ev .ev-map { opacity: 0; transform: translateY(12px); }
.events.js-ev .ev-map { background-size: 0 1px; }

.ev-card .ev-bg { transition: transform 3200ms var(--ease-out); }
.ev-card.is-in .ev-bg { transform: none; }

.ev-card.is-in .ev-top::before { animation: evFade 1200ms var(--ease-soft) 100ms forwards; }
.ev-card.is-in .ev-kicker { animation: evTrackWide 1300ms var(--ease-out) 450ms forwards; }
.ev-card.is-in .ev-name { animation: evWrite 2000ms var(--ease-soft) 600ms forwards; }
.ev-card.is-in .ev-date .ev-c {
  animation: evChar 650ms var(--ease-out) calc(1500ms + var(--ci) * 32ms) forwards;
}
.ev-card.is-in .ev-time .ev-c {
  animation: evChar 600ms var(--ease-out) calc(2100ms + var(--ci) * 40ms) forwards;
}
.ev-card.is-in .ev-time-note { animation: evRise 900ms var(--ease-out) 2500ms forwards; }
.ev-card.is-in .ev-foot-rule { animation: evDraw 1100ms var(--ease-out) 2550ms forwards; }
.ev-card.is-in .ev-venue { animation: evRise 1000ms var(--ease-out) 2700ms forwards; }
.ev-card.is-in .ev-addr { animation: evRise 1000ms var(--ease-out) 2950ms forwards; }
.ev-card.is-in .ev-map {
  animation:
    evRise 900ms var(--ease-out) 3250ms forwards,
    evUnderline 900ms var(--ease-out) 3700ms forwards;
}

/* the script names are written on, left to right, by a feathered mask */
@keyframes evWrite {
  from { -webkit-mask-position: 100% 0; mask-position: 100% 0; }
  to   { -webkit-mask-position: 0 0;    mask-position: 0 0; }
}
@keyframes evChar {
  to { opacity: 1; transform: none; filter: blur(0); }
}
@keyframes evRise {
  to { opacity: 1; transform: none; }
}
@keyframes evFade {
  to { opacity: 1; }
}
@keyframes evDraw {
  to { transform: scaleX(1); }
}
@keyframes evTrackWide {
  to { opacity: 1; letter-spacing: 0.42em; }
}
@keyframes evUnderline {
  to { background-size: 100% 1px; }
}


/* ============================================================
   SECTION 6 — WITH WARM REGARDS  ·  SECTION 7 — THE COUNTDOWN
   Two watercolour papers. Each film is cover-fit into a box ONE SCREEN
   tall at the top of its section, so where the painting lands is known
   in CSS on any phone:
     --fh    the painting's drawn height = max(175cqw, 100svh)  (4:7 film)
     --fw    its drawn width             = --fh x 4/7
     --ftop  the painting's top          = (100svh - --fh) / 2
   and the type is placed and sized in THOSE units, against the clear
   paper measured off the posters (strong-edge mask, % of the film):
     blessing   sprig left to x21% (y16-40), sprig right from x77% (y44-64),
                swing branch + swing to x34% (y60-88): an open centre
                column x23-77% from the top down to y59%
     countdown  lamp + sprig left to x32% (y4-28), x21% (y28-48);
                right wash from x84-94% (y4-36): one centred line needs
                y >= 28%, within x22-78%
   Edge colours sampled off the posters (centre 80%, 8 rows):
     blessing     top #f7eae4  bottom #fcf2ea
     countdown    top #fcf1e5 (unlit) / #d1b8b4 (lit)  bottom #f0d6c4 (lit)
   ============================================================ */
.bl-screen,
.cd-screen {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  container-type: inline-size;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100svh;
  text-align: center;
}
.bl-screen,
.cd-screen {
  --fh: max(175cqw, 100svh);
  --fw: calc(var(--fh) * 0.5714);
  --ftop: calc((100svh - var(--fh)) / 2);
}
.bl-screen { background: #fbefe7; }
.cd-screen { background: #f3dfd0; }

body.is-sealed .bl-screen,
body.is-sealed .cd-screen,
body.is-sealed .rsvp-section { display: none; }

.bl-film,
.cd-film {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 100vh;
  height: 100svh;
  z-index: 0;
}
.bl-bg,
.cd-bg {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* the wedding card ends in midnight: it dissolves down into the paper
   (two stacked ramps of one colour, run past the edge — see SEAMS) */
.bl-screen::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: -4px;
  z-index: 1;
  height: calc(clamp(90px, 14svh, 150px) + 4px);
  pointer-events: none;
  background:
    linear-gradient(180deg, rgb(21, 29, 61) 0%, rgba(21, 29, 61, 0) 46%),
    linear-gradient(180deg, rgb(21, 29, 61) 0%, rgba(21, 29, 61, 0) 100%);
}
/* blessing paper into the countdown paper — the same ivory either side
   until the lamp lights, then a mist off the paper above */
.cd-screen::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: -4px;
  z-index: 1;
  height: calc(clamp(60px, 9svh, 96px) + 4px);
  pointer-events: none;
  background:
    linear-gradient(180deg, #fcf2ea 0%, rgba(252, 242, 234, 0) 44%),
    linear-gradient(180deg, #fcf2ea 0%, rgba(252, 242, 234, 0) 100%);
}

/* ── with warm regards ──
   Set like the family's printed closing card: the two headings in a
   bold italic serif (each on ONE line), the families in italic caps, a
   rule, then the special invitation. The block runs film y~13-61%
   (centre 37%), five family lines one under another; its last line ends above
   the swing's branch (ink to x23% at y61-64%, x33% from y64%), and no
   line is wider than 52% of the painting (x24-76%), so nothing crosses
   a sprig, the branch or the swing on any phone. */
.bl-content {
  position: absolute;
  inset: 0;
  z-index: 2;
  color: var(--wine);
}
.bl-main {
  position: absolute;
  left: 50%;
  top: calc(var(--ftop) + var(--fh) * 0.37);
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
}
.bl-head {
  font-family: var(--font-body);
  font-style: italic;
  font-weight: 600;
  font-size: calc(var(--fw) * 0.07);
  line-height: 1.12;
  white-space: nowrap;
  color: var(--name-ink);
  text-shadow: 0 0 10px rgba(255, 250, 243, 0.95);
}
.bl-head--second { margin-top: 0; font-size: calc(var(--fw) * 0.062); }
/* one family per line, set like the couples' names below (client,
   2026-10-08: the small caps read pale, and the page had dead space) */
.bl-families {
  margin-top: calc(var(--fw) * 0.035);
  font-family: var(--font-body);
  font-style: italic;
  font-size: calc(var(--fw) * 0.052);
  font-weight: 600;
  line-height: 1.3;
  white-space: nowrap;
  color: var(--olive);
  text-shadow: 0 0 8px rgba(255, 250, 243, 0.95);
}
.bl-families + .bl-families { margin-top: 0; }
.bl-ornament {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: calc(var(--fw) * 0.026);
  padding: calc(var(--fh) * 0.028) 0;
}
.bl-rule {
  width: calc(var(--fw) * 0.15);
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--gold));
}
.bl-rule:last-child { background: linear-gradient(90deg, var(--gold), transparent); }
.bl-diamond {
  width: calc(var(--fw) * 0.016);
  height: calc(var(--fw) * 0.016);
  background: var(--gold);
  transform: rotate(45deg);
}
.bl-name {
  margin-top: calc(var(--fw) * 0.004);
  font-family: var(--font-body);
  font-style: italic;
  font-weight: 600;
  font-size: calc(var(--fw) * 0.054);
  line-height: 1.35;
  white-space: nowrap;
  color: var(--olive);
  text-shadow: 0 0 8px rgba(255, 250, 243, 0.95);
}
.bl-head--second + .bl-name { margin-top: calc(var(--fw) * 0.045); }
.bl-name + .bl-name { margin-top: calc(var(--fw) * 0.012); }

/* ── the countdown ──
   Heading, clock and calendar button from just below the lamp (film
   y28.5%, see the top of this block); the couple's sign-off at the
   foot, narrow enough to stand beside the music and menu marks. On
   a short phone the page grows rather than letting them meet: the
   painting's box stays one screen tall and the paper runs on below. */
.cd-content {
  position: relative;
  z-index: 2;
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  /* the sign-off is kept narrow enough (centred, <= W - 2x70px) to sit
     BESIDE the music and menu marks, so no band is held for them */
  padding: calc(var(--ftop) + var(--fh) * 0.285) 0 calc(clamp(18px, 3svh, 30px) + env(safe-area-inset-bottom, 0px));
  color: var(--wine);
}
.cd-main {
  display: flex;
  flex-direction: column;
  align-items: center;
}
/* the same bold italic serif as the warm-regards headings, one line,
   no wider than 54% of the painting (clear of the lamp's sprig) */
.cd-head {
  font-family: var(--font-body);
  font-style: italic;
  font-weight: 600;
  font-size: calc(var(--fw) * 0.068);
  line-height: 1.12;
  white-space: nowrap;
  color: var(--name-ink);
  text-shadow: 0 0 12px rgba(255, 250, 243, 0.95);
}
/* below the painting's box (a short phone only) the paper runs on in
   the section's own colour, the film fading into it */
.cd-film::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 48px;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(243, 223, 208, 0), #f3dfd0);
}

/* the garland: the full width, the doves at its ends. Each cell is laid
   over its pendant's cream interior (x/y/w/h in % of the art); the
   number sits a little above the middle, where the pendant is widest. */
.cd-garland {
  position: relative;
  width: 100cqw;
  margin-top: clamp(14px, 2.6svh, 26px);
  /* room under the drops for the unit names */
  margin-bottom: 7cqw;
  aspect-ratio: 2120 / 742;
}
.cd-garland__art,
.cd-dove {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.cd-garland__art { filter: drop-shadow(0 4px 8px rgba(110, 26, 46, 0.12)); }
/* each dove is a full-canvas layer, so it pivots on its own beak (the
   point that holds the ribbon) and the bow never parts from it: a slow
   bob, the two out of step */
.cd-dove { filter: drop-shadow(0 4px 6px rgba(110, 26, 46, 0.14)); }
.cd-dove--l { transform-origin: 15.7% 21.4%; animation: cdDoveL 3400ms ease-in-out infinite; }
.cd-dove--r { transform-origin: 84.5% 21%;   animation: cdDoveR 3900ms ease-in-out -1200ms infinite; }
@keyframes cdDoveL {
  0%, 100% { transform: rotate(0deg) translateY(0); }
  30%      { transform: rotate(-3.2deg) translateY(-0.6%); }
  62%      { transform: rotate(1.6deg) translateY(0.5%); }
}
@keyframes cdDoveR {
  0%, 100% { transform: rotate(0deg) translateY(0); }
  34%      { transform: rotate(3deg) translateY(-0.6%); }
  66%      { transform: rotate(-1.5deg) translateY(0.5%); }
}
.cd-cell {
  position: absolute;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
.cd-cell--1 { left: 19.6%; top: 39.6%; width: 11.6%; height: 39.4%; }
.cd-cell--2 { left: 34.5%; top: 44.6%; width: 11.9%; height: 39.6%; }
.cd-cell--3 { left: 52.1%; top: 45.1%; width: 12.1%; height: 39.4%; }
.cd-cell--4 { left: 68.7%; top: 39.6%; width: 11.7%; height: 39%; }
/* only the number inside the pendant (the client's ask) */
.cd-num {
  font-family: var(--font-date);
  font-weight: 500;
  font-size: 7.6cqw;
  line-height: 1;
  font-variant-numeric: lining-nums tabular-nums;
  color: var(--wine);
}
/* the unit names hang OUTSIDE, under each pendant's crystal drop
   (the drops end ~16% of the art below the cells) */
.cd-lbl {
  position: absolute;
  left: 50%;
  top: calc(100% + 6.4cqw);
  transform: translateX(-50%);
  font-family: var(--font-caps);
  font-weight: 600;
  font-size: 2.6cqw;
  line-height: 1;
  letter-spacing: 0.14em;
  text-indent: 0.14em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--wine);
  text-shadow: 0 0 6px rgba(255, 250, 243, 0.95);
}
.cd-done {
  margin-top: 3cqw;
  font-family: var(--font-body);
  font-style: italic;
  font-weight: 600;
  font-size: 7cqw;
  color: var(--name-ink);
}

/* Add to Google Calendar: a wine plate with a gold rule struck inside
   it — square cut, as every edge on this site */
.cd-cal {
  position: relative;
  display: inline-block;
  margin-top: clamp(18px, 4.2svh, 38px);
  padding: 3.4cqw 5.4cqw;
  font-family: var(--font-caps);
  font-size: 3cqw;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-indent: 0.2em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  color: #fbecd6;
  background: linear-gradient(180deg, #7e1f38 0%, var(--wine) 55%, var(--wine-deep) 100%);
  box-shadow: 0 6px 16px rgba(76, 15, 31, 0.28);
  touch-action: manipulation;
  overflow: hidden;
}
.cd-cal::before {
  content: '';
  position: absolute;
  inset: 4px;
  border: 1px solid rgba(231, 207, 156, 0.75);
  pointer-events: none;
}
/* a sheen crosses it now and then, so it reads as something to press */
.cd-cal::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: -40%;
  width: 26%;
  background: linear-gradient(100deg, transparent, rgba(255, 236, 200, 0.32), transparent);
  transform: skewX(-18deg);
  animation: cdSheen 5200ms var(--ease-soft) 2000ms infinite;
  pointer-events: none;
}
@keyframes cdSheen {
  0%   { left: -40%; }
  32%  { left: 130%; }
  100% { left: 130%; }
}
.cd-cal:active { transform: translateY(1px); box-shadow: 0 3px 8px rgba(76, 15, 31, 0.3); }
.cd-cal:focus-visible { outline: 1px solid var(--gold-deep); outline-offset: 3px; }

/* the sign-off at the very end of the countdown: the couple's names in
   their own hand (Anastasia, as in the hero and on the card), a gold
   ampersand, the date between rules */
.cp-sign {
  margin-top: auto;
  padding-top: clamp(24px, 4svh, 44px);
  display: flex;
  flex-direction: column;
  align-items: center;
}
.cp-couple {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 2.4cqw;
  white-space: nowrap;
}
.cp-couple__n {
  font-family: var(--font-name);
  font-size: 9.4cqw;
  line-height: 1.25;
  color: var(--name-ink);
  text-shadow: 0 0 12px rgba(255, 250, 243, 0.95);
}
.cp-couple__amp {
  font-family: var(--font-body);
  font-style: italic;
  font-weight: 500;
  font-size: 5.8cqw;
  /* Anastasia's final swash runs right of its box — held off it */
  margin: 0 0.6cqw 0 2.4cqw;
  color: var(--gold-deep);
}
.cp-sign-date {
  display: flex;
  align-items: center;
  gap: 3cqw;
  margin-top: 0.6cqw;
  font-family: var(--font-date);
  font-style: italic;
  font-weight: 500;
  font-size: 4.3cqw;
  font-variant-numeric: lining-nums;
  white-space: nowrap;
  color: var(--wine);
  text-shadow: 0 0 8px rgba(255, 250, 243, 0.95);
}
.cp-sign-rule {
  width: 5cqw;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--gold));
}
.cp-sign-rule:last-child { background: linear-gradient(90deg, var(--gold), transparent); }
/* the YV monogram (800x553, ink 14-787 x 13-540): gold, under the date,
   with a soft ivory lift so it holds on the warmed paper */
.cp-mark {
  width: 18cqw;
  height: auto;
  margin-top: clamp(10px, 2.2svh, 20px);
  filter:
    drop-shadow(0 0 6px rgba(255, 250, 243, 0.85))
    drop-shadow(0 2px 4px rgba(110, 26, 46, 0.18));
}

/* ── their arrival ── (hidden states only under .js-cl, set by script.js;
   .is-in once, the first time a section is well into view) */
.js-cl .bl-head,
.js-cl .cp-couple__n,
.js-cl .cp-couple__amp,
.js-cl .cp-mark { opacity: 0; transform: translateY(12px); filter: blur(3px); }
.js-cl .cd-head { opacity: 0; transform: translateY(12px); filter: blur(3px); }
.js-cl .bl-families .ev-c { opacity: 0; }
.js-cl .bl-rule { transform: scaleX(0); transform-origin: 100% 50%; }
.js-cl .bl-rule:last-child { transform-origin: 0 50%; }
.js-cl .bl-diamond { opacity: 0; }
.js-cl .bl-name,
.js-cl .cp-sign-date,
.js-cl .cd-cal { opacity: 0; transform: translateY(12px); }
/* the garland is let down from the doves' ribbon, swinging to rest */
.js-cl .cd-garland { opacity: 0; transform: translateY(-14px) rotate(-1.6deg); transform-origin: 50% 0; }

.bl-screen.is-in .bl-head            { animation: blRise 1300ms var(--ease-out) 400ms forwards; }
.bl-screen.is-in .bl-families .ev-c  { animation: txChar 600ms var(--ease-out) calc(1300ms + var(--li, 0) * 320ms + var(--ci) * 30ms) forwards; }
.bl-screen.is-in .bl-diamond         { animation: txPop 700ms var(--ease-out) 3100ms forwards; }
.bl-screen.is-in .bl-rule            { animation: txDraw 1000ms var(--ease-out) 3200ms forwards; }
.bl-screen.is-in .bl-head--second    { animation-delay: 3600ms; }
@keyframes blRise { to { opacity: 1; transform: none; filter: blur(0); } }
.bl-screen.is-in .bl-name            { animation: evRise 1000ms var(--ease-out) 4700ms forwards; }
.bl-screen.is-in .bl-name + .bl-name { animation-delay: 5000ms; }
.cd-screen.is-in .cp-couple__n--bride { animation: blRise 1500ms var(--ease-out) 3300ms forwards; }
.cd-screen.is-in .cp-couple__amp { animation: blRise 1100ms var(--ease-out) 3800ms forwards; }
.cd-screen.is-in .cp-couple__n--groom { animation: blRise 1500ms var(--ease-out) 4100ms forwards; }
.cd-screen.is-in .cp-sign-date { animation: evRise 1000ms var(--ease-out) 4800ms forwards; }
.cd-screen.is-in .cp-mark { animation: blRise 1600ms var(--ease-out) 5300ms forwards; }

.cd-screen.is-in .cd-head          { animation: blRise 1400ms var(--ease-out) 500ms forwards; }
.cd-screen.is-in .cd-garland       { animation: cdHang 2200ms var(--ease-out) 1300ms forwards; }
.cd-screen.is-in .cd-cal           { animation: evRise 1000ms var(--ease-out) 2800ms forwards; }
@keyframes cdHang {
  0%   { opacity: 0; transform: translateY(-14px) rotate(-1.6deg); }
  35%  { opacity: 1; }
  55%  { transform: translateY(2px) rotate(0.9deg); }
  78%  { transform: translateY(0) rotate(-0.35deg); }
  100% { opacity: 1; transform: none; }
}
/* a changing number settles in from above */
.cd-num.is-tick { animation: cdTick 520ms var(--ease-out); }
@keyframes cdTick {
  from { opacity: 0.2; transform: translateY(-0.18em); filter: blur(1.5px); }
  to   { opacity: 1; transform: none; filter: blur(0); }
}


/* ── the close ── */
.site-footer {
  position: relative;
  /* the countdown paper's lit floor, which it ends on */
  background: #f0d6c4;
}
.site-credit {
  position: relative;
  z-index: 2;
  padding: 10px 16px calc(22px + env(safe-area-inset-bottom, 0px));
  text-align: center;
  font-family: var(--font-caps);
  font-size: 0.55rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-indent: 0.18em;
  text-transform: uppercase;
  color: rgba(110, 26, 46, 0.72);
}
.site-credit a {
  color: var(--wine);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}


/* ============================================================
   SEAMS — no hard cuts between paintings
   Each join gets a soft band on both sides, two stacked ramps of one
   colour (an ease-out, not a flat wash), run a few px PAST the edge so
   the boundary row sits inside the band's solid end. Colours sampled
   off the rendered edges (centre 80%, ~1% of rows):
     hero floor (last frame)  #827150   scratch sky   #e7e0dc
     scratch floor            #e0c2a9   invite sky    #f8e7df
   The hero's floor is hard, dark detail (chairs, foliage), and the
   midpoint of those two would be a muddy beige across a pastel sky — so
   that join does not meet in the middle: the garden dissolves upward
   into the scratch sky's own blush, like mist off the lawn.
   ============================================================ */
.hero-screen { --seam-bot: #ece3de; }
.scratch-section { --seam-top: #ece3de; --seam-bot: #ecd5c4; }
.invite-screen { --seam-top: #ecd5c4; --seam-bot: #fbded0; }


.hero-screen::after,
.scratch-section::before,
.scratch-section::after,
.invite-screen::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  pointer-events: none;
}

.hero-screen::after {
  z-index: 3;
  bottom: -4px;
  height: calc(clamp(150px, 26svh, 240px) + 4px);
  background:
    linear-gradient(0deg, var(--seam-bot) 0%, transparent 46%),
    linear-gradient(0deg, var(--seam-bot) 0%, transparent 100%);
}

.scratch-section::before {
  z-index: 1;
  top: -4px;
  height: calc(clamp(64px, 10svh, 110px) + 4px);
  background:
    linear-gradient(180deg, var(--seam-top) 0%, transparent 44%),
    linear-gradient(180deg, var(--seam-top) 0%, transparent 100%);
}
.scratch-section::after {
  z-index: 1;
  bottom: -4px;
  height: calc(clamp(74px, 12svh, 138px) + 4px);
  background:
    linear-gradient(0deg, var(--seam-bot) 0%, transparent 44%),
    linear-gradient(0deg, var(--seam-bot) 0%, transparent 100%);
  transition: opacity 900ms var(--ease-soft);
}
/* while sealed the card IS the end of the page — no band leading on to
   a section that is not there yet */
body.is-sealed .scratch-section::after { opacity: 0; }

.invite-screen::before {
  z-index: 0;
  top: -4px;
  height: calc(clamp(74px, 12svh, 138px) + 4px);
  background:
    linear-gradient(180deg, var(--seam-top) 0%, transparent 44%),
    linear-gradient(180deg, var(--seam-top) 0%, transparent 100%);
}
.inv-card { z-index: 1; }

.invite-screen::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  z-index: 0;
  bottom: -4px;
  height: calc(clamp(64px, 10svh, 110px) + 4px);
  pointer-events: none;
  background:
    linear-gradient(0deg, var(--seam-bot) 0%, transparent 44%),
    linear-gradient(0deg, var(--seam-bot) 0%, transparent 100%);
}
.ev-card::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  z-index: 1;
  top: -4px;
  height: calc(clamp(60px, 9svh, 96px) + 4px);
  pointer-events: none;
  background:
    linear-gradient(180deg, rgb(var(--ev-from)) 0%, rgba(var(--ev-from), 0) 44%),
    linear-gradient(180deg, rgb(var(--ev-from)) 0%, rgba(var(--ev-from), 0) 100%);
}

/* ── the hand-off as the page moves ──
   script.js writes --out (0 → 1) as each section scrolls away above the
   fold, and the outgoing painting settles back while its type lifts and
   fades — the next section arrives over a scene already receding rather
   than butting into a still one. */
.hero-content {
  opacity: calc(1 - var(--out, 0) * 1.25);
  translate: 0 calc(var(--out, 0) * -36px);
}
.hero-film {
  scale: calc(1 + var(--out, 0) * 0.06);
  transform-origin: 50% 100%;
}
.scratch-stage {
  translate: 0 calc(var(--out, 0) * -28px);
}


/* ============================================================
   TEXT ANIMATIONS — hero, save the date, invitation
   The same vocabulary as the celebrations: script names WRITTEN ON by a
   feathered mask travelling left to right, small caps arriving letter by
   letter (split by script.js into .ev-c), spaced caps TRACKING IN, rules
   DRAWN out from the centre. Every hidden state sits under html.tx,
   which the script adds — no script, every line simply set.
   The scratched date itself is left alone: hiding its letters would have
   a guest scratching onto a blank card.
   ============================================================ */

/* the write-on mask, shared */
html.tx .hn-line,
html.tx .sh-eyebrow,
html.tx .inv-name {
  -webkit-mask-image: linear-gradient(90deg, #000 40%, transparent 60%);
          mask-image: linear-gradient(90deg, #000 40%, transparent 60%);
  -webkit-mask-size: 250% 100%;
          mask-size: 250% 100%;
  -webkit-mask-position: 100% 0;
          mask-position: 100% 0;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
}
@keyframes txWrite {
  from { opacity: 1; -webkit-mask-position: 100% 0; mask-position: 100% 0; }
  to   { opacity: 1; -webkit-mask-position: 0 0;    mask-position: 0 0; transform: none; }
}
@keyframes txChar {
  from { opacity: 0; transform: translateY(0.5em); filter: blur(3px); }
  to   { opacity: 1; transform: none; filter: blur(0); }
}
@keyframes txDraw {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}
@keyframes txPop {
  from { opacity: 0; transform: rotate(45deg) scale(0.2); }
  to   { opacity: 1; transform: rotate(45deg) scale(1); }
}
@keyframes txAmp {
  from { opacity: 0; transform: scale(0.55) rotate(-10deg); filter: blur(3px); }
  to   { opacity: 1; transform: none; filter: blur(0); }
}

/* ── HERO ──
   Anastasia's capitals swing far outside the line box, and the mask
   clips to that box: pad it out and pull it back by the same amount,
   so the layer grows and the layout does not move (the old padding was
   0 0.2em; 0.45 - 0.25 keeps it). */
.hn-line { padding: 0.28em 0.45em 0.32em; margin: -0.28em -0.25em -0.32em; }

/* "The wedding of": letter by letter, the container itself held up */
html.tx .hero-eyebrow.tx-split { opacity: 1; }
html.tx .hero-eyebrow.tx-split .ev-c { opacity: 0; }
.hero-screen.is-animated .hero-eyebrow.tx-split { animation: none; }
.hero-screen.is-animated .hero-eyebrow .ev-c {
  animation: txChar 700ms var(--ease-out) calc(900ms + var(--ci) * 42ms) forwards;
}
/* the names, written on in turn */
.hero-screen.is-animated .hn-line--bride { animation: txWrite 2100ms var(--ease-soft) 1300ms forwards; }
.hero-screen.is-animated .hn-amp         { animation: txAmp 1000ms var(--ease-out) 2700ms forwards; }
.hero-screen.is-animated .hn-line--groom { animation: txWrite 1900ms var(--ease-soft) 2950ms forwards; }
/* "New Delhi" tracks in from wide */
.hero-screen.is-animated .hero-place { animation: txTrackPlace 1500ms var(--ease-out) 4300ms forwards; }
@keyframes txTrackPlace {
  from { opacity: 0; letter-spacing: 0.9em; text-indent: 0.9em; filter: blur(2px); }
  to   { opacity: 1; letter-spacing: 0.28em; text-indent: 0.28em; filter: blur(0); }
}

/* ── SAVE THE DATE ── staged as the card arrives */
.sh-eyebrow { padding: 0.12em 0.3em 0.22em; margin: -0.12em -0.3em -0.22em; }
html.tx .sh-eyebrow { opacity: 0; }
html.tx .sh-rule { transform: scaleX(0); transform-origin: 100% 50%; }
html.tx .sh-rule:last-child { transform-origin: 0 50%; }
html.tx .sh-diamond { opacity: 0; }
html.tx .sh-cta.tx-split .ev-c { opacity: 0; }
.scratch-section.is-in .sh-eyebrow { animation: txWrite 1900ms var(--ease-soft) 350ms forwards; }
.scratch-section.is-in .sh-rule { animation: txDraw 1000ms var(--ease-out) 1300ms forwards; }
.scratch-section.is-in .sh-diamond { animation: txPop 700ms var(--ease-out) 1200ms forwards; }
.scratch-section.is-in .sh-cta .ev-c {
  animation: txChar 600ms var(--ease-out) calc(1600ms + var(--ci) * 28ms) forwards;
}
/* once struck, the date settles with a breath of gold light across it */
.scratch-reveal::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: -40%;
  width: 30%;
  pointer-events: none;
  background: linear-gradient(100deg, transparent, rgba(231, 207, 156, 0.55), transparent);
  transform: skewX(-18deg);
  opacity: 0;
}
.scratch-aperture.is-revealed .scratch-reveal::after {
  animation: txDateSheen 1500ms var(--ease-soft) 650ms 1 forwards;
}
@keyframes txDateSheen {
  0%   { left: -40%; opacity: 1; }
  100% { left: 120%; opacity: 1; }
}

/* ── THE INVITATION ── the names are written on, slowly (the rest of
   the card's reveal is in SECTION 4) */
.inv-name { padding: 0.18em 0.4em 0.26em; margin-left: -0.28em; margin-right: -0.28em; }
.inv-name--bride { margin-top: calc(2.4cqi - 0.18em); margin-bottom: -0.26em; }
.inv-name--groom { margin-top: -0.18em; margin-bottom: -0.26em; }
html.tx .invite-screen.js-gate .inv-name { opacity: 1; }
.invite-screen.is-revealed .inv-name--bride { animation: txWrite 2600ms var(--ease-soft) var(--d) forwards; }
.invite-screen.is-revealed .inv-name--groom { animation: txWrite 2400ms var(--ease-soft) var(--d) forwards; }


/* ============================================================
   MUSIC + NAVIGATION
   Two painted marks, pinned bottom-right — the gramophone plays/pauses,
   the compass opens the menu. The art IS the button: no plate, a drop
   shadow off the ink only. They sit under the intro (z 45 < 50) and
   arrive with the hero (.is-on).
   ============================================================ */
.site-controls {
  position: fixed;
  z-index: 45;
  bottom: calc(10px + env(safe-area-inset-bottom, 0px));
  right: 8px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  opacity: 0;
  transform: translateY(12px);
  pointer-events: none;
  transition: opacity 900ms var(--ease-soft), transform 900ms var(--ease-out);
}
.site-controls.is-on { opacity: 1; transform: none; pointer-events: auto; }

.ctl-btn {
  position: relative;
  width: 62px;
  height: 62px;
  display: flex;
  align-items: center;
  justify-content: center;
  touch-action: manipulation;
}
/* an ivory halo off the ink itself, then a shadow under it — enough to
   lift the marks off the boughs and garlands they cross, with no plate */
.ctl-btn img {
  width: 54px;
  height: 54px;
  object-fit: contain;
  filter:
    drop-shadow(0 0 5px rgba(255, 249, 238, 0.95))
    drop-shadow(0 3px 6px rgba(46, 8, 20, 0.42));
  transition: filter 500ms var(--ease-soft), opacity 500ms var(--ease-soft), transform 600ms var(--ease-out);
}
.ctl-btn:active img { transform: scale(0.9); }
.ctl-btn:focus-visible { outline: 1px solid var(--gold-deep); outline-offset: -2px; }

/* playing: the gramophone rocks on its feet and gold motes rise off the
   horn (its mouth is up and right of the icon's centre) */
.ctl-music.is-playing img {
  transform-origin: 50% 92%;
  animation: gramoRock 2600ms ease-in-out infinite;
}
@keyframes gramoRock {
  0%, 100% { transform: rotate(-3deg); }
  50%      { transform: rotate(3deg); }
}
.ctl-notes {
  position: absolute;
  left: 58%;
  top: 4px;
  width: 20px;
  height: 26px;
  pointer-events: none;
}
.ctl-notes i {
  position: absolute;
  bottom: 0;
  left: 6px;
  width: 4px;
  height: 4px;
  background: var(--gold);
  box-shadow: 0 0 4px rgba(255, 236, 190, 0.9);
  transform: rotate(45deg);
  opacity: 0;
}
.ctl-music.is-playing .ctl-notes i { animation: noteRise 2400ms ease-out infinite; }
.ctl-music.is-playing .ctl-notes i:nth-child(2) { left: 13px; animation-delay: 800ms; }
.ctl-music.is-playing .ctl-notes i:nth-child(3) { left: 2px;  animation-delay: 1600ms; }
@keyframes noteRise {
  0%   { opacity: 0; transform: translate(0, 0) rotate(45deg) scale(0.6); }
  20%  { opacity: 1; }
  100% { opacity: 0; transform: translate(6px, -22px) rotate(45deg) scale(1.1); }
}
/* paused: the colour drains a little and a fine wine stroke crosses it */
.ctl-music:not(.is-playing) img {
  filter:
    drop-shadow(0 0 5px rgba(255, 249, 238, 0.95))
    drop-shadow(0 3px 6px rgba(46, 8, 20, 0.42))
    saturate(0.7);
}
.ctl-music:not(.is-playing)::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: 46px;
  height: 2px;
  margin: -1px 0 0 -23px;
  background: var(--wine);
  box-shadow: 0 0 0 1px rgba(255, 246, 232, 0.85);
  transform: rotate(-45deg);
  pointer-events: none;
}

/* the compass turns a quarter as the menu opens */
.ctl-nav[aria-expanded="true"] img { transform: rotate(90deg); }

/* ── the menu ── */
.nav-menu {
  position: fixed;
  inset: 0;
  z-index: 60;
  visibility: hidden;
  pointer-events: none;
  transition: visibility 0s linear 700ms;
}
.nav-menu.is-open {
  visibility: visible;
  pointer-events: auto;
  transition: visibility 0s;
}
.nav-scrim {
  position: absolute;
  inset: 0;
  background: rgba(36, 6, 16, 0.5);
  -webkit-backdrop-filter: blur(3px);
          backdrop-filter: blur(3px);
  opacity: 0;
  transition: opacity 600ms var(--ease-soft);
}
.nav-menu.is-open .nav-scrim { opacity: 1; }

.nav-sheet {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: min(86%, 350px);
  overflow-y: auto;
  padding: calc(64px + env(safe-area-inset-top, 0px)) 32px calc(30px + env(safe-area-inset-bottom, 0px));
  background:
    radial-gradient(ellipse 90% 60% at 100% 0%, rgba(247, 214, 214, 0.55), transparent 70%),
    linear-gradient(180deg, #fdf7ef 0%, #f7eadf 100%);
  box-shadow: -14px 0 30px rgba(46, 8, 20, 0.28);
  transform: translateX(104%);
  transition: transform 700ms var(--ease-out);
}
/* a gold rule struck inside the sheet's edge */
.nav-sheet::before {
  content: '';
  position: absolute;
  inset: 12px;
  border: 1px solid rgba(184, 144, 79, 0.55);
  pointer-events: none;
}
.nav-menu.is-open .nav-sheet { transform: none; }

.nav-close {
  position: absolute;
  top: calc(20px + env(safe-area-inset-top, 0px));
  right: 20px;
  width: 44px;
  height: 44px;
}
.nav-close i {
  position: absolute;
  left: 11px;
  top: 21px;
  width: 22px;
  height: 1.5px;
  background: var(--wine);
  transform: rotate(45deg);
}
.nav-close i + i { transform: rotate(-45deg); }
.nav-close:focus { outline: none; }
.nav-close:focus-visible,
.nav-list a:focus-visible { outline: 1px solid var(--gold-deep); outline-offset: 2px; }

.nav-eyebrow {
  font-family: var(--font-caps);
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--gold-deep);
}
.nav-list {
  list-style: none;
  margin: 18px 0 0;
  padding: 0;
}
.nav-list li + li { border-top: 1px solid rgba(184, 144, 79, 0.28); }
.nav-list a {
  display: flex;
  align-items: baseline;
  gap: 14px;
  padding: 12px 2px;
  font-family: var(--font-body);
  font-style: italic;
  font-weight: 600;
  font-size: 1.45rem;
  line-height: 1.15;
  color: var(--wine);
  text-decoration: none;
  touch-action: manipulation;
}
.nav-head {
  margin-top: 26px;
  font-family: var(--font-script);
  font-size: 2.1rem;
  line-height: 1.1;
  color: var(--name-ink);
}
.nav-list--events { margin-top: 6px; }
.nav-list--events a { font-size: 1.22rem; padding: 10px 2px; }
.nav-day {
  flex: 0 0 56px;
  font-family: var(--font-date);
  font-style: italic;
  font-weight: 400;
  font-size: 1.5rem;
  font-variant-numeric: lining-nums;
  color: var(--gold-deep);
}
.nav-sealed-note {
  display: none;
  margin-top: 22px;
  font-family: var(--font-body);
  font-style: italic;
  font-size: 1.02rem;
  color: var(--olive);
}
/* the way on is shut until the date is struck — so is the menu's */
body.is-sealed .nav-locked { display: none; }
body.is-sealed .nav-sealed-note { display: block; }

/* the lines arrive one after another as the sheet comes in
   (--ni is numbered by script.js) */
.nav-sheet .nav-eyebrow,
.nav-sheet .nav-list li,
.nav-sheet .nav-head,
.nav-sheet .nav-sealed-note {
  opacity: 0;
  transform: translateX(18px);
  transition: opacity 500ms var(--ease-soft), transform 700ms var(--ease-out);
}
.nav-menu.is-open .nav-sheet .nav-eyebrow,
.nav-menu.is-open .nav-sheet .nav-list li,
.nav-menu.is-open .nav-sheet .nav-head,
.nav-menu.is-open .nav-sheet .nav-sealed-note {
  opacity: 1;
  transform: none;
  transition-delay: calc(180ms + var(--ni, 0) * 55ms);
}


/* ============================================================
   REDUCED MOTION
   Everything still arrives, it simply arrives at once. The intro stays
   a tap — that gate is the guest's own gesture, not motion — and the
   scratch stays interactive.
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  .begin-button .begin-main,
  .scratch-hint,
  .scratch-glint::before,
  .scroll-arrows i { animation: none; }
  .scroll-arrows i { opacity: 0.8; }

  .hero-screen.is-animated .hero-bough,
  .hero-screen.is-animated .hero-bough--right { animation: none; opacity: 1; transform: none; }
  .hero-screen.is-animated .hero-eyebrow,
  .hero-screen.is-animated .hn-line,
  .hero-screen.is-animated .hn-amp,
  .hero-screen.is-animated .hero-place { animation: none; opacity: 1; }

  .date-cta.is-in { animation: none; opacity: 1; }
  .date-cta.is-in .dc-plate::before { animation: none; }
  .hero-content, .hero-film, .scratch-stage { translate: none; scale: none; }
  .hero-content { opacity: 1; }

  .invite-screen.is-revealed .invite-content > *,
  .invite-screen.is-revealed .inv-word { animation: none; opacity: 1; transform: none; }
  .invite-screen.js-gate .inv-card { animation: none; opacity: 1; transform: none; }

  /* the celebrations: every line simply set, the films still loop (a
     held camera, like the hero) but without the settling push */
  .events.js-ev .ev-c,
  .events.js-ev .ev-card .ev-top::before,
  .events.js-ev .ev-kicker,
  .events.js-ev .ev-foot-rule,
  .events.js-ev .ev-time-note,
  .events.js-ev .ev-venue,
  .events.js-ev .ev-addr,
  .events.js-ev .ev-map,
  .events.js-ev .ev-card .ev-bg { animation: none !important; transition: none; opacity: 1; transform: none; filter: none; }
  .events.js-ev .ev-kicker { letter-spacing: 0.42em; }
  .ctl-music.is-playing img,
  .ctl-music.is-playing .ctl-notes i { animation: none; }
  .nav-sheet, .nav-scrim, .nav-sheet .nav-eyebrow, .nav-sheet .nav-list li,
  .nav-sheet .nav-head, .nav-sheet .nav-sealed-note { transition: none !important; }
  html.tx .ev-c { opacity: 1 !important; animation: none !important; transform: none; filter: none; }
  html.tx .hn-line,
  html.tx .sh-eyebrow,
  html.tx .inv-name { -webkit-mask-image: none; mask-image: none; }
  html.tx .sh-eyebrow,
  html.tx .sh-diamond { opacity: 1; animation: none; }
  html.tx .sh-rule { transform: none; animation: none; }
  .scratch-aperture.is-revealed .scratch-reveal::after { animation: none; }
  .hero-screen.is-animated .hero-place { letter-spacing: 0.28em; text-indent: 0.28em; }
  .events.js-ev .ev-shade,
  .events.js-ev .ev-foot::before { transition: none; opacity: 1; transform: none; }
  .events.js-ev .ev-map { background-size: 100% 1px; }
  .events.js-ev .ev-name { animation: none !important; -webkit-mask-image: none; mask-image: none; }
  /* the closing pages: set at once; the lamp is shown already lit */
  .js-cl .bl-head, .js-cl .cd-head, .js-cl .cp-couple__n, .js-cl .cp-couple__amp, .js-cl .cp-sign-date, .js-cl .cp-mark,
  .js-cl .bl-diamond, .js-cl .bl-rule, .js-cl .bl-name,
  .js-cl .cd-cal, .js-cl .cd-garland {
    animation: none !important; opacity: 1; transform: none;
    -webkit-mask-image: none; mask-image: none; filter: none;
  }
  .cd-num.is-tick,
  .cd-dove,
  .cd-cal::after { animation: none; }
}


/* ============================================================
   DESKTOP / TABLET FRAME
   Designed for a portrait phone only. On wider screens the same layout
   is locked to a centred 480px column with plain gutters. Every
   position:fixed element is re-pinned onto the column. Kept LAST so the
   base rules above cannot out-source it.
   ============================================================ */
#device-frame { width: 100%; }

@media (min-width: 600px) {
  html, body { background: #2a0a14; }

  #device-frame {
    position: relative;
    width: 480px;
    max-width: 100%;
    margin: 0 auto;
    background: var(--blush);
  }

  .intro-screen,
  .blush-veil,
  .nav-menu {
    left: 50%;
    right: auto;
    width: 480px;
    margin-left: -240px;
  }
  .site-controls { right: calc(50% - 240px + 8px); }
}

/* ── RSVP Contact Styling ── */
.bl-rsvp-box {
  margin-top: calc(var(--fw) * 0.035);
  display: flex;
  flex-direction: column;
  gap: calc(var(--fw) * 0.02);
  align-items: center;
}
.bl-contact-link {
  color: var(--wine);
  text-decoration: none;
  font-weight: 700;
  letter-spacing: 0.03em;
  border-bottom: 1.5px dotted var(--gold-deep);
  padding-bottom: 2px;
  transition: all 0.2s ease;
}
.bl-contact-link:hover,
.bl-contact-link:focus {
  color: var(--gold-deep);
  border-bottom-style: solid;
}

/* ============================================================
   SECTION — SEPARATE RSVP WITH OPTIONS & DYNAMIC DECLINE HIDING
   ============================================================ */
.rsvp-section {
  position: relative;
  isolation: isolate;
  background: linear-gradient(180deg, #fbefe7 0%, #f9e9df 35%, #f4dcd0 100%);
  padding: clamp(48px, 8svh, 80px) clamp(16px, 4cqw, 28px);
  color: var(--wine);
  text-align: center;
  border-top: 1px solid rgba(190, 147, 76, 0.22);
}

.rsvp-container {
  width: 100%;
  max-width: 440px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.rsvp-eyebrow {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(11px, 2.8cqw, 13px);
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--gold-deep);
  margin-bottom: 6px;
}

.rsvp-title {
  font-family: var(--font-body);
  font-style: italic;
  font-weight: 600;
  font-size: clamp(36px, 8.5cqw, 44px);
  line-height: 1.08;
  color: var(--name-ink);
  letter-spacing: 0.04em;
  text-shadow: 0 0 10px rgba(255, 250, 243, 0.95);
}

.rsvp-subtitle {
  font-family: var(--font-body);
  font-style: italic;
  font-size: clamp(14.5px, 3.4cqw, 16px);
  line-height: 1.45;
  color: var(--olive);
  max-width: 360px;
  margin: 12px auto 26px;
}

/* ── Both Numbers Contact Cards ── */
.rsvp-contacts {
  width: 100%;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin-bottom: 24px;
}

.rsvp-contact-card {
  background: rgba(255, 255, 255, 0.85);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid rgba(190, 147, 76, 0.38);
  border-radius: 14px;
  padding: 16px 10px 14px;
  display: flex;
  flex-direction: column;
  align-items: center;
  box-shadow: 0 6px 18px rgba(110, 26, 46, 0.08);
  transition: transform 0.22s ease, box-shadow 0.22s ease, border-color 0.22s ease;
}
.rsvp-contact-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 24px rgba(110, 26, 46, 0.14);
  border-color: var(--gold-deep);
}

.rcc-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: linear-gradient(135deg, #dfb76c, #9a6e2e);
  color: #fff;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 17px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 8px;
  box-shadow: 0 3px 10px rgba(154, 110, 46, 0.35);
}

.rcc-name {
  font-family: var(--font-display);
  font-size: 14.5px;
  font-weight: 600;
  color: var(--wine);
  letter-spacing: 0.06em;
  margin-bottom: 3px;
}

.rcc-phone {
  font-family: var(--font-body);
  font-size: 13.5px;
  font-weight: 700;
  color: var(--olive);
  text-decoration: none;
  margin-bottom: 12px;
  white-space: nowrap;
}

.rcc-actions {
  display: flex;
  gap: 6px;
  width: 100%;
}

.rcc-btn {
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 7px 4px;
  border-radius: 7px;
  font-family: var(--font-display);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-decoration: none;
  transition: all 0.2s ease;
}

.rcc-btn--call {
  background: rgba(88, 22, 34, 0.08);
  color: var(--wine);
  border: 1px solid rgba(88, 22, 34, 0.22);
}
.rcc-btn--call:hover {
  background: var(--wine);
  color: #fff;
}

.rcc-btn--wa {
  background: rgba(37, 211, 102, 0.12);
  color: #128c7e;
  border: 1px solid rgba(37, 211, 102, 0.35);
}
.rcc-btn--wa:hover {
  background: #25d366;
  color: #fff;
}

/* ── Interactive RSVP Form with Options ── */
.rsvp-form {
  width: 100%;
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid rgba(190, 147, 76, 0.42);
  border-radius: 18px;
  padding: 24px 20px;
  text-align: left;
  box-shadow: 0 10px 30px rgba(110, 26, 46, 0.1);
}

.rf-group {
  margin-bottom: 20px;
}

/* Animated collapse/expand for Number of Guests */
#rfGuestsGroup {
  max-height: 180px;
  opacity: 1;
  overflow: hidden;
  transition: max-height 0.35s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.25s ease, margin 0.3s ease;
}

#rfGuestsGroup.is-hidden {
  max-height: 0;
  opacity: 0;
  margin-top: 0;
  margin-bottom: 0;
  pointer-events: none;
}

.rf-label {
  display: block;
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--wine);
  margin-bottom: 9px;
}

.rf-pills {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.rf-pills--guests {
  flex-direction: row;
  gap: 6px;
}
.rf-pills--guests .rf-pill {
  flex: 1;
  text-align: center;
  justify-content: center;
  padding: 10px 4px;
}

.rf-pill {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  border-radius: 10px;
  background: #faf7f2;
  border: 1px solid rgba(190, 147, 76, 0.28);
  cursor: pointer;
  transition: all 0.22s ease;
  user-select: none;
}
.rf-pill input[type="radio"] {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.rf-pill-badge {
  font-size: 18px;
  line-height: 1;
  flex-shrink: 0;
}

.rf-pill-content {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.rf-pill-title {
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 600;
  color: #3b2a26;
  line-height: 1.25;
}

.rf-pill-desc {
  font-family: var(--font-body);
  font-size: 12px;
  font-style: italic;
  color: #7d6b65;
  line-height: 1.2;
}

.rf-pill-dot {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1.5px solid var(--gold-deep);
  flex-shrink: 0;
  position: relative;
  transition: all 0.2s ease;
}
.rf-pill.is-active .rf-pill-dot {
  background: var(--wine);
  border-color: var(--wine);
  box-shadow: inset 0 0 0 2.5px #fff;
}

.rf-pill-text {
  font-family: var(--font-body);
  font-size: 14.5px;
  font-weight: 600;
  color: #3b2a26;
}

.rf-pill:hover {
  border-color: var(--gold-deep);
  background: #fff;
  transform: translateY(-1px);
}

.rf-pill.is-active {
  background: #fff;
  border-color: var(--wine);
  box-shadow: 0 3px 12px rgba(88, 22, 34, 0.12), inset 0 0 0 1px var(--wine);
}
.rf-pill.is-active .rf-pill-title,
.rf-pill.is-active .rf-pill-text {
  color: var(--wine);
  font-weight: 700;
}
.rf-pill.is-active .rf-pill-desc {
  color: var(--gold-deep);
  font-weight: 500;
}

/* Subtle gentle styling when decline is active */
.rf-pill--decline.is-active {
  border-color: #8c7873;
  box-shadow: 0 3px 12px rgba(70, 60, 58, 0.1), inset 0 0 0 1px #8c7873;
}
.rf-pill--decline.is-active .rf-pill-title {
  color: #554440;
}
.rf-pill--decline.is-active .rf-pill-desc {
  color: #8c7873;
}

.rf-input {
  width: 100%;
  padding: 12px 14px;
  border-radius: 9px;
  border: 1px solid rgba(190, 147, 76, 0.38);
  background: #fff;
  font-family: var(--font-body);
  font-size: 15px;
  color: #2b1f1d;
  box-sizing: border-box;
  outline: none;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.rf-input:focus {
  border-color: var(--wine);
  box-shadow: 0 0 0 3px rgba(88, 22, 34, 0.12);
}
.rf-input::placeholder {
  color: #a89a94;
  font-style: italic;
}

.rf-submit-btn {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  padding: 14px 20px;
  border-radius: 999px;
  border: none;
  background: linear-gradient(135deg, #25d366 0%, #128c7e 100%);
  color: #fff;
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
  box-shadow: 0 4px 16px rgba(18, 140, 126, 0.35);
  transition: all 0.25s ease;
  margin-top: 12px;
}
.rf-submit-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 22px rgba(18, 140, 126, 0.5);
}
.rf-submit-btn:active {
  transform: translateY(0);
}

.rf-note {
  margin-top: 12px;
  font-family: var(--font-body);
  font-style: italic;
  font-size: 12.5px;
  line-height: 1.4;
  color: #8c7873;
  text-align: center;
}
