/* ==========================================================================
   Dr Kamsiah Dental Clinic — Grand Opening invitation
   Uses tokens from /css/tokens.css (linked first). No imports.

   Modes (set on <html> by /js/boot.js):
   - no class      : no JavaScript — static, fully readable page (default styles)
   - .js           : JS present — curtain gate, preloader and dock exist
   - .motion       : cinematic mode — pinned (sticky) scenes + initial hidden states
   - .reduced-motion: JS, but everything static; gate is a simple fade
   ========================================================================== */

:root {
  --dock-h: 64px;
  --dock-space: calc(var(--dock-h) + 22px + env(safe-area-inset-bottom, 0px));
  --gutter: clamp(16px, 5vw, 40px);
  --measure: 60ch;
  /* Button fill: its lightest stop (#9a6b22) keeps cream label text ≥ 4.5:1. */
  --btn-gold: linear-gradient(110deg, #6f460f 0%, #86591b 30%, #9a6b22 50%, #86591b 70%, #6f460f 100%);
  /* Gradient for gold display text on cream: its lightest stop (#a8782c, 3.6:1) keeps
     even thin italic strokes above 3:1. The bright --gold-gradient is kept for dark
     surfaces (finale) and decoration. */
  --gold-text: linear-gradient(110deg, #7a5015 0%, #946622 26%, #a8782c 50%, #946622 74%, #7a5015 100%);
  --night: #461b1b; /* poster maroon, deep */
  --night-2: #5c2626; /* poster maroon */
  --glow: 241, 214, 140;
}

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

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  background: var(--bg);
  color: var(--ink);
  overflow-x: clip;
}
/* Keyboard focus scrolling keeps fields clear of the fixed dock. */
html.js { scroll-padding-top: 16px; scroll-padding-bottom: calc(var(--dock-space) + 8px); }
.nowrap { white-space: nowrap; }

body {
  margin: 0;
  min-height: 100vh;
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 1rem;
  line-height: 1.6;
  background: var(--bg);
  color: var(--ink);
  overflow-x: clip;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  -webkit-tap-highlight-color: transparent;
}

html.is-locked, html.is-locked body { overflow: hidden; }
html.is-dusk { background: var(--night); }

img, svg, canvas { display: block; max-width: 100%; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }
a { color: var(--gold-700); text-underline-offset: 0.18em; text-decoration-thickness: 1px; }
p { margin: 0; }
h1, h2, h3 { margin: 0; font-weight: 500; }
ul { margin: 0; padding: 0; }
[hidden] { display: none !important; }

:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; border-radius: 6px; }
.poster__title:focus, .section-title:focus, .sheet__title:focus, .closed__title:focus, .pass:focus, .thanks:focus { outline: none; }

.sr-only {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}

.skip-link {
  position: fixed; left: 12px; top: -120px; z-index: 100;
  padding: 10px 16px; border-radius: 999px;
  background: var(--cream-50); color: var(--ink); font-weight: 500; text-decoration: none;
  box-shadow: var(--shadow-lift);
  transition: top 0.3s var(--ease-out);
}
.skip-link:focus-visible { top: 12px; }

.icon {
  width: 20px; height: 20px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round;
}

/* Paper grain — fixed, very subtle, same over every section so joins stay invisible */
.paper {
  position: fixed; inset: 0; z-index: 40; pointer-events: none;
  opacity: 0.55;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .29 0 0 0 0 .17 0 0 0 0 .11 0 0 0 .07 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 180px 180px;
}

/* --------------------------------------------------------------------------
   Typography helpers
   -------------------------------------------------------------------------- */
.container { width: min(100% - 2 * var(--gutter), 1100px); margin-inline: auto; }
.container--narrow { width: min(100% - 2 * var(--gutter), 720px); }

.eyebrow, .caption__eyebrow, .beat__label, .action-group__label, .countdown__label {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.75rem;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--gold-700);
}

.section-head { text-align: center; max-width: 40rem; margin: 0 auto clamp(28px, 6vw, 56px); }
.section-head .eyebrow { margin-bottom: 14px; display: inline-flex; align-items: center; gap: 12px; }
.section-head .eyebrow::before, .section-head .eyebrow::after {
  content: ""; width: 28px; height: 1px; background: linear-gradient(90deg, transparent, var(--gold-500));
  transform-origin: 100% 50%;
  transition: transform 1.2s var(--ease-out) 0.25s;
}
.section-head .eyebrow::after { background: linear-gradient(270deg, transparent, var(--gold-500)); transform-origin: 0 50%; }
.motion .section-head:not(.is-in) .eyebrow::before, .motion .section-head:not(.is-in) .eyebrow::after { transform: scaleX(0); }

.section-title {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(2.2rem, 8.4vw, 3.8rem);
  line-height: 1.04;
  letter-spacing: -0.005em;
  color: var(--brown-800);
  text-wrap: balance;
}
.section-title em, .finale__title em {
  font-style: italic;
  font-weight: 500;
  background: var(--gold-text);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  padding: 0 0.06em;
  margin: 0 -0.06em;
}
.finale__title em { background-image: var(--gold-gradient); }
/* A lone hairline ampersand is too thin for a gradient: solid deep gold. */
.wishes .section-title em { background: none; color: var(--gold-700); -webkit-text-fill-color: currentColor; }
.section-lede {
  margin: 16px auto 0;
  max-width: 34rem;
  color: var(--ink-soft);
  font-size: clamp(1rem, 3.6vw, 1.1rem);
  font-weight: 400;
  text-wrap: pretty;
}

.gold-text {
  background: var(--gold-gradient);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* --------------------------------------------------------------------------
   Buttons
   -------------------------------------------------------------------------- */
.btn {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  min-height: 50px;
  padding: 12px 24px;
  border-radius: 999px;
  border: 1px solid transparent;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 1rem;
  line-height: 1.2;
  letter-spacing: 0.02em;
  text-decoration: none;
  text-align: center;
  cursor: pointer;
  transition: translate 0.35s var(--ease-out), scale 0.35s var(--ease-out), box-shadow 0.35s var(--ease-out), background-color 0.35s, border-color 0.35s, color 0.35s;
  -webkit-user-select: none; user-select: none;
}
.btn .icon { width: 19px; height: 19px; }
.btn:active { scale: 0.98; }

.btn--gold {
  color: #fffdf8;
  font-weight: 600;
  background: var(--btn-gold);
  background-size: 220% 100%;
  background-position: 0% 0;
  border-color: rgba(122, 82, 22, 0.35);
  text-shadow: 0 1px 1px rgba(70, 40, 8, 0.45);
  box-shadow: 0 10px 24px -8px rgba(138, 95, 31, 0.55), inset 0 1px 0 rgba(255, 245, 214, 0.45);
  transition: translate 0.35s var(--ease-out), scale 0.35s var(--ease-out), box-shadow 0.35s var(--ease-out), background-position 0.9s var(--ease-out);
}
@media (hover: hover) {
  .btn--gold:hover { background-position: 100% 0; box-shadow: 0 14px 30px -10px rgba(138, 95, 31, 0.7), inset 0 1px 0 rgba(255, 245, 214, 0.5); }
  .btn--line:hover { background: var(--cream-50); border-color: var(--gold-600); }
  .btn--ghost:hover { background: rgba(198, 154, 67, 0.1); }
}
.btn--line {
  color: var(--brown-700);
  background: rgba(255, 253, 248, 0.55);
  border-color: rgba(198, 154, 67, 0.75);
}
.btn--line .icon { color: var(--gold-600); }
.btn--ghost { color: var(--brown-700); background: transparent; border-color: var(--line); }
.btn--line-light {
  color: var(--cream-100);
  background: rgba(255, 240, 210, 0.04);
  border-color: rgba(227, 191, 104, 0.7);
}
.btn--line-light .icon { color: var(--gold-400); }
@media (hover: hover) { .btn--line-light:hover { background: rgba(227, 191, 104, 0.12); } }
.btn--block { width: 100%; }

.link {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px;
  background: none; border: 0; padding: 10px 8px;
  font-family: var(--font-body); font-weight: 500; font-size: 0.95rem;
  color: var(--gold-700);
  text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.25em;
  cursor: pointer;
}

/* --------------------------------------------------------------------------
   Scene 0 — Preloader
   -------------------------------------------------------------------------- */
.preloader { display: none; }
.js .preloader {
  display: grid; place-items: center;
  position: fixed; inset: 0; z-index: 90;
}
.preloader__bg {
  position: absolute; inset: 0;
  background:
    radial-gradient(circle at 50% 46%, rgba(var(--glow), 0.14), rgba(var(--glow), 0) 42%),
    radial-gradient(150% 105% at 50% 48%, rgba(30, 8, 8, 0) 50%, rgba(30, 8, 8, 0.5) 100%),
    var(--maroon-700);
}
.preloader__inner { position: relative; display: grid; justify-items: center; gap: 26px; }
.preloader__mark { width: 86px; height: auto; overflow: visible; will-change: transform; }
.preloader__mark path {
  fill: var(--gold-400);
  fill-opacity: 1;
  stroke: var(--gold-400);
  stroke-width: 9;
  stroke-opacity: 0;
}
.motion .preloader__mark path {
  fill-opacity: 0;
  stroke-opacity: 1;
  stroke-dasharray: 1 1;
  stroke-dashoffset: 1;
  animation: pl-draw 1.6s var(--ease-in-out) 0.1s forwards, pl-fill 0.7s ease 1.35s forwards;
}
@keyframes pl-draw { to { stroke-dashoffset: 0; } }
@keyframes pl-fill { to { fill-opacity: 1; stroke-opacity: 0; } }
.preloader__bar {
  width: 120px; height: 1px; overflow: hidden;
  background: rgba(227, 191, 104, 0.2);
}
.preloader__fill {
  display: block; height: 100%; width: 100%;
  background: var(--gold-gradient-soft);
  transform-origin: 0 50%;
  transform: scaleX(0.06);
  transition: transform 0.6s var(--ease-out);
}
/* If the script never arrives, the preloader bows out by itself. */
.boot-failed .preloader { display: none; }

/* --------------------------------------------------------------------------
   Poster world (SPEC §5A) — the maroon stage, tied-back velvet curtains and the
   gold glitter canopy. Shared by the gate, the poster (#home) and the finale.

   Curtain geometry: the drapes run the full scene height; their natural width
   is 198/1280 of it. Narrow phones squeeze them to ≤ 25vw and tuck up to 16% of
   their width off-canvas, which keeps the gold bows visible.
   -------------------------------------------------------------------------- */
.poster__stage, .finale__stage {
  --sh: max(600px, 100svh);
  --cw-n: calc(var(--sh) * 0.1547);
  --cw: min(var(--cw-n), max(78px, 25vw));
  --co: clamp(0px, calc((var(--cw-n) - 25vw) * 0.5), calc(var(--cw) * 0.16));
}

/* Maroon stage: watercolour mottling + a soft vignette (no images). */
.maroon-stage {
  background-color: var(--maroon-700);
  background-image:
    radial-gradient(115% 75% at 50% 40%, rgba(122, 52, 50, 0.05), rgba(92, 38, 38, 0) 62%),
    radial-gradient(150% 110% at 50% 46%, rgba(30, 8, 8, 0) 58%, rgba(30, 8, 8, 0.3) 100%),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='600' height='600'%3E%3Cfilter id='w' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.012 .016' numOctaves='4' seed='11'/%3E%3CfeColorMatrix values='0 0 0 0 .62 0 0 0 0 .3 0 0 0 0 .28 0 0 0 .11 -.09'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23w)'/%3E%3C/svg%3E"),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='600' height='600'%3E%3Cfilter id='d' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.02 .013' numOctaves='3' seed='4'/%3E%3CfeColorMatrix values='0 0 0 0 .16 0 0 0 0 .05 0 0 0 0 .05 0 0 0 .42 -.18'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23d)'/%3E%3C/svg%3E");
  background-size: 100% 100%, 100% 100%, cover, cover;
  background-position: center;
  background-repeat: no-repeat;
}

/* Tied-back curtains (the poster's own drapes, cut from the approved artwork). */
.curtain {
  position: absolute; top: 0; bottom: 0; z-index: 3;
  width: var(--cw);
  pointer-events: none;
}
.curtain--l { left: calc(-1 * var(--co)); }
.curtain--r { right: calc(-1 * var(--co)); }
.curtain__drape { position: absolute; inset: 0; }
/* Pivots on the outer top corner: the sway only ever swings outward, never opening a gap at the edge. */
.curtain--l .curtain__drape { transform-origin: 0 0; }
.curtain--r .curtain__drape { transform-origin: 100% 0; }
.curtain__drape img {
  width: 100%; height: 100%; max-width: none;
  object-fit: fill;
  filter: brightness(var(--lit, 1)) drop-shadow(0 0 18px rgba(24, 6, 6, 0.45));
}
/* A tiny four-point sparkle that glints on each gold bow now and then. */
.sparkle {
  position: absolute; width: 26px; height: 26px; margin: -13px 0 0 -13px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 251, 232, 1) 0 7%, rgba(255, 226, 150, 0.55) 20%, rgba(255, 226, 150, 0) 48%);
  opacity: 0;
  pointer-events: none;
}
.sparkle::before, .sparkle::after {
  content: ""; position: absolute; left: 0; top: 50%; width: 100%; height: 2px; margin-top: -1px;
  border-radius: 2px;
  background: radial-gradient(closest-side, #fffbe9, rgba(255, 232, 160, 0.85) 45%, rgba(255, 232, 160, 0));
}
.sparkle::after { transform: rotate(90deg); }
.curtain--l .sparkle { left: 23%; top: 66.6%; }
.curtain--r .sparkle { left: 77%; top: 66.6%; }

/* Static glitter canopy (no JS / reduced motion). With motion a canvas twinkles instead. */
.canopy { display: none; }
html:not(.motion) .canopy {
  display: block;
  position: absolute; left: 0; right: 0; top: 0; z-index: 1;
  height: max(90px, calc(var(--sh) * 0.16));
  /* a scatter of gold flecks (pre-generated, like the poster's canopy), repeated across */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='360' height='150'%3E%3Cg fill='%23f6d682'%3E%3Ccircle cx='130' cy='75' r='0.9' fill-opacity='0.49'/%3E%3Ccircle cx='189' cy='25' r='1.4' fill-opacity='0.57'/%3E%3Ccircle cx='151' cy='4' r='1.3' fill-opacity='0.75'/%3E%3Ccircle cx='343' cy='25' r='1.3' fill-opacity='0.70'/%3E%3Ccircle cx='248' cy='13' r='1.4' fill-opacity='0.63'/%3E%3Ccircle cx='173' cy='54' r='1.2' fill-opacity='0.39'/%3E%3Ccircle cx='341' cy='3' r='1.3' fill-opacity='0.87'/%3E%3Ccircle cx='275' cy='21' r='1.0' fill-opacity='0.81'/%3E%3Ccircle cx='200' cy='38' r='1.0' fill-opacity='0.61'/%3E%3Ccircle cx='331' cy='5' r='1.2' fill-opacity='0.57'/%3E%3Ccircle cx='66' cy='48' r='1.4' fill-opacity='0.40'/%3E%3Ccircle cx='358' cy='0' r='1.0' fill-opacity='0.83'/%3E%3Ccircle cx='249' cy='27' r='0.7' fill-opacity='0.56'/%3E%3Ccircle cx='226' cy='24' r='1.2' fill-opacity='0.66'/%3E%3Ccircle cx='139' cy='135' r='1.4' fill-opacity='0.18'/%3E%3Ccircle cx='115' cy='24' r='1.0' fill-opacity='0.55'/%3E%3Ccircle cx='255' cy='1' r='1.4' fill-opacity='0.81'/%3E%3Ccircle cx='280' cy='3' r='0.7' fill-opacity='0.79'/%3E%3Ccircle cx='109' cy='31' r='0.8' fill-opacity='0.68'/%3E%3Ccircle cx='143' cy='13' r='0.7' fill-opacity='0.85'/%3E%3Ccircle cx='328' cy='20' r='0.7' fill-opacity='0.85'/%3E%3Ccircle cx='355' cy='54' r='1.1' fill-opacity='0.39'/%3E%3Ccircle cx='331' cy='14' r='0.9' fill-opacity='0.87'/%3E%3Ccircle cx='107' cy='76' r='1.3' fill-opacity='0.49'/%3E%3Ccircle cx='329' cy='46' r='1.4' fill-opacity='0.56'/%3E%3Ccircle cx='321' cy='18' r='0.9' fill-opacity='0.80'/%3E%3Ccircle cx='23' cy='6' r='0.9' fill-opacity='0.76'/%3E%3Ccircle cx='27' cy='6' r='1.1' fill-opacity='0.79'/%3E%3Ccircle cx='360' cy='1' r='0.7' fill-opacity='0.95'/%3E%3Ccircle cx='147' cy='51' r='1.0' fill-opacity='0.41'/%3E%3Ccircle cx='290' cy='20' r='1.5' fill-opacity='0.53'/%3E%3Ccircle cx='202' cy='1' r='1.7' fill-opacity='0.92'/%3E%3Ccircle cx='153' cy='26' r='1.2' fill-opacity='0.63'/%3E%3Ccircle cx='159' cy='3' r='1.4' fill-opacity='0.82'/%3E%3Ccircle cx='282' cy='31' r='0.9' fill-opacity='0.67'/%3E%3Ccircle cx='130' cy='26' r='1.3' fill-opacity='0.53'/%3E%3Ccircle cx='322' cy='21' r='0.8' fill-opacity='0.73'/%3E%3Ccircle cx='11' cy='36' r='0.8' fill-opacity='0.45'/%3E%3Ccircle cx='24' cy='65' r='1.4' fill-opacity='0.59'/%3E%3Ccircle cx='73' cy='8' r='0.7' fill-opacity='0.91'/%3E%3Ccircle cx='121' cy='10' r='0.9' fill-opacity='0.91'/%3E%3Ccircle cx='61' cy='51' r='0.7' fill-opacity='0.62'/%3E%3Ccircle cx='46' cy='84' r='1.2' fill-opacity='0.40'/%3E%3Ccircle cx='245' cy='57' r='1.2' fill-opacity='0.45'/%3E%3Ccircle cx='118' cy='66' r='0.7' fill-opacity='0.57'/%3E%3Ccircle cx='305' cy='13' r='1.1' fill-opacity='0.70'/%3E%3Ccircle cx='124' cy='23' r='1.2' fill-opacity='0.56'/%3E%3Ccircle cx='249' cy='7' r='1.1' fill-opacity='0.72'/%3E%3Ccircle cx='95' cy='24' r='0.9' fill-opacity='0.66'/%3E%3Ccircle cx='314' cy='116' r='1.0' fill-opacity='0.23'/%3E%3Ccircle cx='114' cy='12' r='0.9' fill-opacity='0.77'/%3E%3Ccircle cx='200' cy='15' r='1.0' fill-opacity='0.66'/%3E%3Ccircle cx='65' cy='3' r='0.7' fill-opacity='0.94'/%3E%3Ccircle cx='12' cy='6' r='0.7' fill-opacity='0.78'/%3E%3Ccircle cx='154' cy='29' r='0.7' fill-opacity='0.82'/%3E%3Ccircle cx='285' cy='41' r='1.4' fill-opacity='0.68'/%3E%3Ccircle cx='203' cy='13' r='1.0' fill-opacity='0.57'/%3E%3Ccircle cx='178' cy='75' r='1.4' fill-opacity='0.41'/%3E%3Ccircle cx='215' cy='5' r='1.0' fill-opacity='0.54'/%3E%3C/g%3E%3Cg fill='%23ecc262'%3E%3Ccircle cx='327' cy='26' r='1.1' fill-opacity='0.62'/%3E%3Ccircle cx='208' cy='86' r='1.0' fill-opacity='0.27'/%3E%3Ccircle cx='52' cy='10' r='0.8' fill-opacity='0.86'/%3E%3Ccircle cx='139' cy='10' r='1.6' fill-opacity='0.71'/%3E%3Ccircle cx='314' cy='15' r='0.8' fill-opacity='0.73'/%3E%3Ccircle cx='37' cy='15' r='1.6' fill-opacity='0.53'/%3E%3Ccircle cx='131' cy='3' r='0.7' fill-opacity='0.81'/%3E%3Ccircle cx='181' cy='23' r='1.2' fill-opacity='0.78'/%3E%3Ccircle cx='61' cy='38' r='0.8' fill-opacity='0.73'/%3E%3Ccircle cx='5' cy='4' r='1.5' fill-opacity='0.77'/%3E%3Ccircle cx='87' cy='2' r='0.8' fill-opacity='0.89'/%3E%3Ccircle cx='343' cy='7' r='1.0' fill-opacity='0.95'/%3E%3Ccircle cx='225' cy='12' r='1.4' fill-opacity='0.92'/%3E%3Ccircle cx='86' cy='22' r='0.8' fill-opacity='0.50'/%3E%3Ccircle cx='226' cy='79' r='1.1' fill-opacity='0.39'/%3E%3Ccircle cx='197' cy='32' r='1.4' fill-opacity='0.56'/%3E%3Ccircle cx='66' cy='7' r='1.3' fill-opacity='0.65'/%3E%3Ccircle cx='293' cy='25' r='0.7' fill-opacity='0.77'/%3E%3Ccircle cx='265' cy='2' r='1.2' fill-opacity='0.66'/%3E%3Ccircle cx='1' cy='1' r='1.1' fill-opacity='0.68'/%3E%3Ccircle cx='308' cy='42' r='1.2' fill-opacity='0.63'/%3E%3Ccircle cx='29' cy='7' r='1.4' fill-opacity='0.79'/%3E%3Ccircle cx='108' cy='32' r='1.1' fill-opacity='0.51'/%3E%3Ccircle cx='155' cy='31' r='0.9' fill-opacity='0.80'/%3E%3Ccircle cx='193' cy='0' r='1.5' fill-opacity='0.69'/%3E%3Ccircle cx='70' cy='2' r='1.4' fill-opacity='0.58'/%3E%3Ccircle cx='349' cy='7' r='0.9' fill-opacity='0.63'/%3E%3Ccircle cx='320' cy='9' r='0.8' fill-opacity='0.78'/%3E%3Ccircle cx='256' cy='18' r='1.0' fill-opacity='0.52'/%3E%3Ccircle cx='111' cy='43' r='1.7' fill-opacity='0.64'/%3E%3Ccircle cx='154' cy='5' r='1.0' fill-opacity='0.80'/%3E%3Ccircle cx='215' cy='3' r='1.2' fill-opacity='0.70'/%3E%3Ccircle cx='131' cy='26' r='1.3' fill-opacity='0.48'/%3E%3Ccircle cx='129' cy='5' r='0.8' fill-opacity='0.89'/%3E%3Ccircle cx='353' cy='6' r='1.1' fill-opacity='0.92'/%3E%3Ccircle cx='212' cy='26' r='0.9' fill-opacity='0.64'/%3E%3Ccircle cx='289' cy='0' r='1.3' fill-opacity='0.58'/%3E%3Ccircle cx='325' cy='9' r='0.7' fill-opacity='0.69'/%3E%3Ccircle cx='328' cy='5' r='0.8' fill-opacity='0.82'/%3E%3Ccircle cx='302' cy='19' r='1.3' fill-opacity='0.66'/%3E%3Ccircle cx='111' cy='25' r='0.9' fill-opacity='0.50'/%3E%3Ccircle cx='10' cy='5' r='0.8' fill-opacity='0.69'/%3E%3Ccircle cx='227' cy='52' r='1.2' fill-opacity='0.41'/%3E%3Ccircle cx='345' cy='27' r='1.1' fill-opacity='0.52'/%3E%3Ccircle cx='95' cy='7' r='1.4' fill-opacity='0.69'/%3E%3Ccircle cx='56' cy='5' r='0.9' fill-opacity='0.76'/%3E%3Ccircle cx='344' cy='8' r='0.9' fill-opacity='0.95'/%3E%3Ccircle cx='7' cy='20' r='1.4' fill-opacity='0.75'/%3E%3Ccircle cx='298' cy='30' r='1.1' fill-opacity='0.80'/%3E%3Ccircle cx='59' cy='18' r='1.9' fill-opacity='0.81'/%3E%3Ccircle cx='83' cy='45' r='1.3' fill-opacity='0.72'/%3E%3Ccircle cx='21' cy='57' r='1.4' fill-opacity='0.59'/%3E%3Ccircle cx='34' cy='49' r='1.1' fill-opacity='0.43'/%3E%3Ccircle cx='30' cy='62' r='0.7' fill-opacity='0.52'/%3E%3Ccircle cx='5' cy='18' r='1.0' fill-opacity='0.87'/%3E%3Ccircle cx='148' cy='19' r='0.8' fill-opacity='0.57'/%3E%3Ccircle cx='67' cy='39' r='0.7' fill-opacity='0.66'/%3E%3Ccircle cx='114' cy='28' r='1.5' fill-opacity='0.63'/%3E%3Ccircle cx='320' cy='17' r='1.0' fill-opacity='0.74'/%3E%3Ccircle cx='31' cy='13' r='1.1' fill-opacity='0.59'/%3E%3C/g%3E%3Cg fill='%23e2b24c'%3E%3Ccircle cx='54' cy='12' r='1.6' fill-opacity='0.74'/%3E%3Ccircle cx='28' cy='95' r='1.1' fill-opacity='0.39'/%3E%3Ccircle cx='214' cy='35' r='1.2' fill-opacity='0.73'/%3E%3Ccircle cx='168' cy='133' r='1.4' fill-opacity='0.18'/%3E%3Ccircle cx='295' cy='49' r='1.3' fill-opacity='0.55'/%3E%3Ccircle cx='161' cy='91' r='1.4' fill-opacity='0.44'/%3E%3Ccircle cx='282' cy='71' r='1.3' fill-opacity='0.36'/%3E%3Ccircle cx='314' cy='17' r='1.4' fill-opacity='0.60'/%3E%3Ccircle cx='73' cy='66' r='1.1' fill-opacity='0.44'/%3E%3Ccircle cx='155' cy='5' r='1.1' fill-opacity='0.62'/%3E%3Ccircle cx='38' cy='102' r='1.2' fill-opacity='0.34'/%3E%3Ccircle cx='353' cy='125' r='1.8' fill-opacity='0.25'/%3E%3Ccircle cx='20' cy='17' r='1.2' fill-opacity='0.70'/%3E%3Ccircle cx='346' cy='9' r='1.5' fill-opacity='0.62'/%3E%3Ccircle cx='56' cy='57' r='1.4' fill-opacity='0.54'/%3E%3Ccircle cx='234' cy='8' r='1.1' fill-opacity='0.56'/%3E%3Ccircle cx='222' cy='43' r='1.6' fill-opacity='0.45'/%3E%3Ccircle cx='168' cy='10' r='1.3' fill-opacity='0.75'/%3E%3Ccircle cx='135' cy='16' r='0.8' fill-opacity='0.63'/%3E%3Ccircle cx='43' cy='54' r='1.4' fill-opacity='0.64'/%3E%3Ccircle cx='180' cy='2' r='1.3' fill-opacity='0.74'/%3E%3Ccircle cx='162' cy='143' r='0.8' fill-opacity='0.18'/%3E%3Ccircle cx='149' cy='41' r='1.0' fill-opacity='0.54'/%3E%3Ccircle cx='85' cy='19' r='0.9' fill-opacity='0.77'/%3E%3Ccircle cx='344' cy='13' r='0.8' fill-opacity='0.59'/%3E%3Ccircle cx='331' cy='2' r='0.9' fill-opacity='0.94'/%3E%3Ccircle cx='121' cy='13' r='1.9' fill-opacity='0.81'/%3E%3Ccircle cx='266' cy='48' r='1.4' fill-opacity='0.58'/%3E%3Ccircle cx='89' cy='41' r='1.0' fill-opacity='0.60'/%3E%3Ccircle cx='106' cy='45' r='0.9' fill-opacity='0.48'/%3E%3Ccircle cx='192' cy='5' r='1.2' fill-opacity='0.65'/%3E%3Ccircle cx='164' cy='15' r='1.4' fill-opacity='0.77'/%3E%3Ccircle cx='292' cy='54' r='1.3' fill-opacity='0.48'/%3E%3Ccircle cx='260' cy='34' r='0.9' fill-opacity='0.65'/%3E%3Ccircle cx='173' cy='96' r='1.2' fill-opacity='0.27'/%3E%3Ccircle cx='283' cy='6' r='0.8' fill-opacity='0.81'/%3E%3Ccircle cx='163' cy='98' r='1.1' fill-opacity='0.39'/%3E%3Ccircle cx='227' cy='133' r='1.0' fill-opacity='0.20'/%3E%3Ccircle cx='186' cy='10' r='0.9' fill-opacity='0.88'/%3E%3Ccircle cx='359' cy='6' r='0.9' fill-opacity='0.58'/%3E%3Ccircle cx='94' cy='0' r='0.9' fill-opacity='0.97'/%3E%3Ccircle cx='132' cy='37' r='1.0' fill-opacity='0.60'/%3E%3Ccircle cx='11' cy='29' r='1.0' fill-opacity='0.74'/%3E%3Ccircle cx='321' cy='77' r='1.3' fill-opacity='0.45'/%3E%3Ccircle cx='118' cy='13' r='0.8' fill-opacity='0.78'/%3E%3Ccircle cx='37' cy='95' r='1.0' fill-opacity='0.39'/%3E%3Ccircle cx='5' cy='19' r='1.4' fill-opacity='0.58'/%3E%3Ccircle cx='226' cy='73' r='1.2' fill-opacity='0.34'/%3E%3Ccircle cx='106' cy='19' r='1.1' fill-opacity='0.82'/%3E%3Ccircle cx='290' cy='20' r='1.3' fill-opacity='0.74'/%3E%3Ccircle cx='154' cy='19' r='1.2' fill-opacity='0.63'/%3E%3Ccircle cx='33' cy='108' r='1.4' fill-opacity='0.29'/%3E%3Ccircle cx='2' cy='59' r='1.4' fill-opacity='0.52'/%3E%3Ccircle cx='135' cy='54' r='1.0' fill-opacity='0.39'/%3E%3Ccircle cx='10' cy='30' r='1.2' fill-opacity='0.79'/%3E%3Ccircle cx='199' cy='45' r='1.4' fill-opacity='0.51'/%3E%3Ccircle cx='296' cy='14' r='1.3' fill-opacity='0.61'/%3E%3Ccircle cx='30' cy='39' r='1.2' fill-opacity='0.58'/%3E%3Ccircle cx='280' cy='19' r='1.1' fill-opacity='0.79'/%3E%3Ccircle cx='22' cy='10' r='1.5' fill-opacity='0.86'/%3E%3Ccircle cx='73' cy='21' r='1.1' fill-opacity='0.80'/%3E%3Ccircle cx='313' cy='7' r='1.2' fill-opacity='0.62'/%3E%3Ccircle cx='341' cy='17' r='1.3' fill-opacity='0.88'/%3E%3C/g%3E%3Cg fill='%23d4a03c'%3E%3Ccircle cx='239' cy='19' r='0.7' fill-opacity='0.74'/%3E%3Ccircle cx='178' cy='28' r='0.9' fill-opacity='0.73'/%3E%3Ccircle cx='311' cy='51' r='0.9' fill-opacity='0.49'/%3E%3Ccircle cx='54' cy='92' r='0.8' fill-opacity='0.29'/%3E%3Ccircle cx='314' cy='18' r='1.5' fill-opacity='0.71'/%3E%3Ccircle cx='344' cy='30' r='1.2' fill-opacity='0.49'/%3E%3Ccircle cx='127' cy='71' r='1.1' fill-opacity='0.55'/%3E%3Ccircle cx='316' cy='52' r='0.8' fill-opacity='0.53'/%3E%3Ccircle cx='20' cy='63' r='1.1' fill-opacity='0.37'/%3E%3Ccircle cx='232' cy='82' r='1.0' fill-opacity='0.31'/%3E%3Ccircle cx='132' cy='3' r='1.0' fill-opacity='0.85'/%3E%3Ccircle cx='295' cy='42' r='1.4' fill-opacity='0.73'/%3E%3Ccircle cx='30' cy='48' r='1.8' fill-opacity='0.67'/%3E%3Ccircle cx='68' cy='24' r='1.1' fill-opacity='0.51'/%3E%3Ccircle cx='123' cy='114' r='1.4' fill-opacity='0.26'/%3E%3Ccircle cx='15' cy='3' r='1.2' fill-opacity='0.71'/%3E%3Ccircle cx='249' cy='31' r='1.2' fill-opacity='0.62'/%3E%3Ccircle cx='337' cy='109' r='0.7' fill-opacity='0.31'/%3E%3Ccircle cx='41' cy='10' r='1.0' fill-opacity='0.89'/%3E%3Ccircle cx='23' cy='9' r='1.0' fill-opacity='0.55'/%3E%3Ccircle cx='96' cy='9' r='1.1' fill-opacity='0.68'/%3E%3Ccircle cx='103' cy='31' r='0.7' fill-opacity='0.49'/%3E%3Ccircle cx='101' cy='16' r='0.9' fill-opacity='0.76'/%3E%3Ccircle cx='311' cy='30' r='0.9' fill-opacity='0.54'/%3E%3Ccircle cx='335' cy='2' r='1.4' fill-opacity='0.75'/%3E%3Ccircle cx='39' cy='9' r='0.8' fill-opacity='0.81'/%3E%3Ccircle cx='333' cy='33' r='1.1' fill-opacity='0.56'/%3E%3Ccircle cx='351' cy='7' r='1.1' fill-opacity='0.55'/%3E%3Ccircle cx='67' cy='12' r='1.4' fill-opacity='0.52'/%3E%3Ccircle cx='89' cy='30' r='1.2' fill-opacity='0.59'/%3E%3Ccircle cx='84' cy='1' r='1.1' fill-opacity='0.97'/%3E%3Ccircle cx='166' cy='58' r='1.3' fill-opacity='0.50'/%3E%3Ccircle cx='179' cy='3' r='1.3' fill-opacity='0.64'/%3E%3Ccircle cx='357' cy='31' r='0.8' fill-opacity='0.74'/%3E%3Ccircle cx='150' cy='33' r='0.7' fill-opacity='0.76'/%3E%3Ccircle cx='311' cy='16' r='1.5' fill-opacity='0.58'/%3E%3Ccircle cx='2' cy='7' r='1.4' fill-opacity='0.88'/%3E%3Ccircle cx='125' cy='6' r='0.8' fill-opacity='0.56'/%3E%3Ccircle cx='355' cy='0' r='1.1' fill-opacity='0.83'/%3E%3Ccircle cx='113' cy='75' r='1.7' fill-opacity='0.49'/%3E%3Ccircle cx='66' cy='1' r='0.8' fill-opacity='0.85'/%3E%3Ccircle cx='269' cy='39' r='0.9' fill-opacity='0.63'/%3E%3Ccircle cx='204' cy='2' r='0.9' fill-opacity='0.78'/%3E%3Ccircle cx='214' cy='66' r='1.2' fill-opacity='0.47'/%3E%3Ccircle cx='111' cy='6' r='1.2' fill-opacity='0.92'/%3E%3Ccircle cx='2' cy='37' r='1.4' fill-opacity='0.59'/%3E%3Ccircle cx='177' cy='0' r='1.1' fill-opacity='0.63'/%3E%3Ccircle cx='83' cy='81' r='0.8' fill-opacity='0.45'/%3E%3Ccircle cx='251' cy='46' r='1.3' fill-opacity='0.51'/%3E%3Ccircle cx='158' cy='6' r='1.3' fill-opacity='0.59'/%3E%3Ccircle cx='71' cy='17' r='1.2' fill-opacity='0.58'/%3E%3Ccircle cx='51' cy='19' r='1.2' fill-opacity='0.78'/%3E%3Ccircle cx='87' cy='66' r='1.0' fill-opacity='0.37'/%3E%3Ccircle cx='20' cy='13' r='0.9' fill-opacity='0.51'/%3E%3Ccircle cx='338' cy='40' r='1.1' fill-opacity='0.69'/%3E%3Ccircle cx='202' cy='19' r='0.9' fill-opacity='0.63'/%3E%3Ccircle cx='90' cy='32' r='0.8' fill-opacity='0.53'/%3E%3Ccircle cx='225' cy='38' r='1.0' fill-opacity='0.55'/%3E%3Ccircle cx='188' cy='21' r='1.4' fill-opacity='0.65'/%3E%3Ccircle cx='44' cy='7' r='1.1' fill-opacity='0.77'/%3E%3Ccircle cx='112' cy='2' r='1.3' fill-opacity='0.92'/%3E%3Ccircle cx='287' cy='5' r='1.0' fill-opacity='0.81'/%3E%3Ccircle cx='351' cy='5' r='1.3' fill-opacity='0.87'/%3E%3Ccircle cx='209' cy='8' r='1.4' fill-opacity='0.75'/%3E%3C/g%3E%3Cg fill='%23fcecb8'%3E%3Ccircle cx='153' cy='3' r='1.4' fill-opacity='0.64'/%3E%3Ccircle cx='206' cy='3' r='1.1' fill-opacity='0.85'/%3E%3Ccircle cx='74' cy='2' r='1.2' fill-opacity='0.68'/%3E%3Ccircle cx='66' cy='53' r='0.9' fill-opacity='0.54'/%3E%3Ccircle cx='40' cy='17' r='1.2' fill-opacity='0.72'/%3E%3Ccircle cx='172' cy='40' r='1.3' fill-opacity='0.49'/%3E%3Ccircle cx='94' cy='35' r='1.0' fill-opacity='0.70'/%3E%3Ccircle cx='356' cy='39' r='1.3' fill-opacity='0.49'/%3E%3Ccircle cx='37' cy='3' r='1.1' fill-opacity='0.76'/%3E%3Ccircle cx='215' cy='28' r='1.1' fill-opacity='0.51'/%3E%3Ccircle cx='219' cy='44' r='1.3' fill-opacity='0.45'/%3E%3Ccircle cx='274' cy='25' r='1.4' fill-opacity='0.70'/%3E%3Ccircle cx='72' cy='28' r='0.9' fill-opacity='0.76'/%3E%3Ccircle cx='252' cy='83' r='1.4' fill-opacity='0.33'/%3E%3Ccircle cx='289' cy='9' r='1.9' fill-opacity='0.53'/%3E%3Ccircle cx='279' cy='9' r='0.8' fill-opacity='0.58'/%3E%3Ccircle cx='8' cy='1' r='0.9' fill-opacity='0.81'/%3E%3Ccircle cx='178' cy='38' r='0.9' fill-opacity='0.47'/%3E%3Ccircle cx='264' cy='29' r='1.3' fill-opacity='0.65'/%3E%3Ccircle cx='25' cy='18' r='1.4' fill-opacity='0.53'/%3E%3Ccircle cx='242' cy='9' r='1.3' fill-opacity='0.64'/%3E%3Ccircle cx='189' cy='5' r='1.5' fill-opacity='0.89'/%3E%3Ccircle cx='292' cy='64' r='1.2' fill-opacity='0.60'/%3E%3Ccircle cx='179' cy='41' r='1.2' fill-opacity='0.64'/%3E%3Ccircle cx='108' cy='3' r='1.5' fill-opacity='0.65'/%3E%3Ccircle cx='89' cy='7' r='0.9' fill-opacity='0.91'/%3E%3Ccircle cx='15' cy='72' r='0.9' fill-opacity='0.36'/%3E%3Ccircle cx='197' cy='47' r='0.8' fill-opacity='0.52'/%3E%3Ccircle cx='328' cy='30' r='0.8' fill-opacity='0.58'/%3E%3Ccircle cx='174' cy='106' r='0.7' fill-opacity='0.26'/%3E%3Ccircle cx='321' cy='35' r='1.2' fill-opacity='0.66'/%3E%3Ccircle cx='299' cy='55' r='0.8' fill-opacity='0.48'/%3E%3Ccircle cx='323' cy='5' r='0.9' fill-opacity='0.60'/%3E%3Ccircle cx='282' cy='61' r='1.0' fill-opacity='0.35'/%3E%3Ccircle cx='72' cy='5' r='1.2' fill-opacity='0.82'/%3E%3Ccircle cx='96' cy='37' r='1.1' fill-opacity='0.70'/%3E%3Ccircle cx='106' cy='102' r='1.4' fill-opacity='0.22'/%3E%3Ccircle cx='140' cy='6' r='1.2' fill-opacity='0.90'/%3E%3Ccircle cx='24' cy='40' r='1.2' fill-opacity='0.70'/%3E%3Ccircle cx='17' cy='19' r='1.2' fill-opacity='0.82'/%3E%3Ccircle cx='251' cy='31' r='1.1' fill-opacity='0.72'/%3E%3Ccircle cx='211' cy='36' r='1.2' fill-opacity='0.67'/%3E%3Ccircle cx='196' cy='1' r='0.8' fill-opacity='0.97'/%3E%3Ccircle cx='66' cy='127' r='1.1' fill-opacity='0.26'/%3E%3Ccircle cx='55' cy='13' r='1.4' fill-opacity='0.58'/%3E%3Ccircle cx='326' cy='20' r='1.3' fill-opacity='0.55'/%3E%3Ccircle cx='298' cy='24' r='0.9' fill-opacity='0.63'/%3E%3Ccircle cx='68' cy='0' r='1.4' fill-opacity='0.85'/%3E%3Ccircle cx='220' cy='71' r='1.2' fill-opacity='0.49'/%3E%3Ccircle cx='19' cy='72' r='0.9' fill-opacity='0.53'/%3E%3Ccircle cx='261' cy='60' r='0.7' fill-opacity='0.59'/%3E%3Ccircle cx='102' cy='49' r='0.7' fill-opacity='0.52'/%3E%3Ccircle cx='275' cy='74' r='1.3' fill-opacity='0.34'/%3E%3Ccircle cx='21' cy='11' r='1.0' fill-opacity='0.90'/%3E%3C/g%3E%3C/svg%3E");
  background-size: 360px 150px;
  background-repeat: repeat-x;
  background-position: 0 0;
  -webkit-mask: linear-gradient(180deg, #000 0%, rgba(0, 0, 0, 0.8) 30%, rgba(0, 0, 0, 0.28) 65%, rgba(0, 0, 0, 0) 100%);
  mask: linear-gradient(180deg, #000 0%, rgba(0, 0, 0, 0.8) 30%, rgba(0, 0, 0, 0.28) 65%, rgba(0, 0, 0, 0) 100%);
}

/* --------------------------------------------------------------------------
   Scene 1 — The Gate: closed velvet curtains + the medallion on the seam
   -------------------------------------------------------------------------- */
.gate { display: none; }
.js .gate {
  display: block;
  position: fixed; inset: 0; z-index: 60;
  overflow: hidden;
  touch-action: none;
  overscroll-behavior: contain;
  cursor: pointer;
  --medal: min(58vw, 252px, 34svh);
  --medal-y: 56%;
}
.no-gate .gate, .boot-failed .gate { display: none !important; }

/* Closed velvet curtains — the gate here, and the finale's curtain-fall (gate.js
   velvetPair). The seam belongs to the fabric, never a separate line: each panel
   runs a feather's width past the middle and fades out over it toward the seam
   (--fe: the feather's current softness, set by gate.js), so the two panels
   cross-fade instead of meeting in an edge; and each panel paints its own seam
   shadow, which sinks into the stage maroon, so it always travels with the fabric
   and a parting gap never shows as a light or dark line. */
.gate, .finale__fall { --feather: max(30px, 5vw); }
.vpanel {
  position: absolute; top: 0; height: 100%;
  width: calc(50% + var(--feather));
  overflow: hidden;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  --fe: var(--feather);
}
.motion .vpanel { will-change: transform; }
.vpanel--l {
  left: 0; transform-origin: 0 0;
  -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - var(--feather) / 2 - var(--fe) / 2), rgba(0, 0, 0, 0) calc(100% - var(--feather) / 2 + var(--fe) / 2));
  mask-image: linear-gradient(90deg, #000 calc(100% - var(--feather) / 2 - var(--fe) / 2), rgba(0, 0, 0, 0) calc(100% - var(--feather) / 2 + var(--fe) / 2));
}
.vpanel--r {
  right: 0; transform-origin: 100% 0;
  -webkit-mask-image: linear-gradient(270deg, #000 calc(100% - var(--feather) / 2 - var(--fe) / 2), rgba(0, 0, 0, 0) calc(100% - var(--feather) / 2 + var(--fe) / 2));
  mask-image: linear-gradient(270deg, #000 calc(100% - var(--feather) / 2 - var(--fe) / 2), rgba(0, 0, 0, 0) calc(100% - var(--feather) / 2 + var(--fe) / 2));
}
.vpanel > span { position: absolute; inset: 0; }
.vpanel--r > span { transform: scaleX(-1); }
/* Velvet: the straightened poster fabric, repeated across, aligned at the seam. */
.vpanel__velvet {
  background: var(--copper-500) url("/assets/img/poster/velvet-tile.webp") repeat-x right var(--feather) top 0;
  background-size: auto 124%; /* the tile's shadowed foot stays below the hem */
}
/* Shading: the top and the hem, the outer edge, one soft highlight — and the seam.
   --seam: 1 = closed (the two leading pleats touch over a fine crease), 0 = parting
   (the seam valley deepens into the stage's own maroon over the last ~90px, so the
   opening gap never reads as a line). The panels stand still while it changes:
   the gate eases it at the tap, the finale scrubs it once the panels have met. */
.vpanel { --seam: 1; }
.vpanel__shade {
  background:
    linear-gradient(180deg, rgba(36, 9, 5, 0.6) 0%, rgba(36, 9, 5, 0.12) 13%, rgba(36, 9, 5, 0) 24%, rgba(36, 9, 5, 0) 78%, rgba(36, 9, 5, 0.5) 100%),
    linear-gradient(90deg, rgba(36, 9, 5, 0.18) 0%, rgba(36, 9, 5, 0) 16%),
    radial-gradient(55% 42% at 34% 40%, rgba(255, 196, 150, 0.14), rgba(255, 196, 150, 0) 72%);
}
.vpanel__shade::before, .vpanel__shade::after { content: ""; position: absolute; inset: 0; pointer-events: none; }
.vpanel__shade::before {
  background: linear-gradient(90deg, rgba(52, 16, 12, 0) calc(100% - var(--feather) - 150px), rgba(64, 22, 18, 0.42) calc(100% - var(--feather) - 70px), rgba(86, 33, 28, 0.8) calc(100% - var(--feather) - 22px), rgba(89, 35, 30, 0.86) calc(100% - var(--feather)), rgba(89, 35, 30, 0.86) 100%);
  opacity: calc(1 - 0.84 * var(--seam));
}
/* The crease where the closed panels meet: velvet shadow, not stage maroon. */
.vpanel__shade::after {
  background: linear-gradient(90deg, rgba(58, 24, 10, 0) calc(100% - var(--feather) - 14px), rgba(58, 24, 10, 0.34) calc(100% - var(--feather) - 6px), rgba(40, 15, 6, 0.72) calc(100% - var(--feather)), rgba(58, 24, 10, 0.34) calc(100% - var(--feather) + 6px), rgba(58, 24, 10, 0) calc(100% - var(--feather) + 14px));
  opacity: var(--seam);
}
.gate .vpanel__shade::before, .gate .vpanel__shade::after { transition: opacity 0.34s ease-in-out; }
.gate.is-opening .vpanel { --seam: 0; }
/* Extra fold shadows that appear as the fabric gathers. */
.vpanel__gather {
  opacity: 0;
  background: repeating-linear-gradient(90deg,
    rgba(30, 8, 4, 0) 0, rgba(30, 8, 4, 0.34) 13px, rgba(30, 8, 4, 0) 26px,
    rgba(255, 190, 140, 0.1) 33px, rgba(30, 8, 4, 0) 40px);
}
/* The warm light behind the curtains: a soft, wide glow that blooms from the gap
   as the panels part (no core, no edge — it only ever brightens gently). */
.gate__glow {
  position: absolute; z-index: 1; left: 50%; top: -6%; bottom: -6%;
  width: max(260px, 40vw); margin-left: calc(max(260px, 40vw) / -2);
  background: radial-gradient(closest-side,
    rgba(255, 214, 160, 0.4) 0%, rgba(255, 214, 160, 0.37) 16%, rgba(255, 214, 160, 0.3) 32%,
    rgba(255, 214, 160, 0.2) 48%, rgba(255, 214, 160, 0.1) 64%, rgba(255, 214, 160, 0.035) 80%, rgba(255, 214, 160, 0) 100%);
  filter: blur(22px);
  mix-blend-mode: screen;
  opacity: 0;
  pointer-events: none;
  will-change: transform, opacity;
}
html:not(.motion) .gate__canopy { height: max(90px, 15%); z-index: 2; }
.gate__glitter {
  position: absolute; left: 0; top: 0; z-index: 2;
  width: 100%; height: max(96px, 17%);
  pointer-events: none;
}

.gate__top {
  position: absolute; left: 0; right: 0; z-index: 2;
  top: max(84px, 15%);
  bottom: calc(100% - var(--medal-y) + var(--medal) / 2 + 14px);
  display: flex; flex-direction: column; align-items: center; justify-content: safe center;
  gap: 8px;
  padding: 0 24px;
  text-align: center;
  color: var(--paper-cream);
  pointer-events: none;
  isolation: isolate;
}
.gate__top::before {
  content: ""; position: absolute; left: 50%; top: 50%; z-index: -1;
  width: min(118vw, 640px); height: 150%;
  transform: translate(-50%, -50%);
  background: radial-gradient(closest-side, rgba(40, 10, 8, 0.62), rgba(40, 10, 8, 0.3) 55%, rgba(40, 10, 8, 0));
}
.gate__dear {
  font-family: var(--font-script);
  font-size: min(clamp(1.8rem, 8.6vw, 2.8rem), 6.8svh);
  line-height: 1.08;
  color: var(--gold-300);
  max-width: min(100%, 34rem);
  padding: 0.1em 0.25em 0.16em;
  overflow-wrap: anywhere;
  text-shadow: 0 2px 14px rgba(30, 8, 6, 0.7);
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}
.gate__dear.is-long { font-size: min(clamp(1.4rem, 6.6vw, 2.1rem), 5.6svh); }
.gate__name { white-space: normal; }
.gate__clinic {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: clamp(0.72rem, 3.2vw, 0.86rem);
  letter-spacing: 0.32em;
  padding-left: 0.32em;
  text-transform: uppercase;
  text-shadow: 0 1px 10px rgba(30, 8, 6, 0.8);
}
.gate__since {
  display: flex; align-items: center; gap: 10px;
  font-family: var(--font-poster-serif);
  font-style: italic;
  font-size: 0.95rem;
  color: rgba(246, 238, 227, 0.9);
  text-shadow: 0 1px 10px rgba(30, 8, 6, 0.8);
}
.gate__since::before, .gate__since::after { content: ""; width: 24px; height: 1px; background: var(--gold-400); }

/* The medallion (the real <button>): maroon disc, gold + copper rings, the tooth
   mark and the poster's own "Grand Opening" lettering. */
.medal {
  position: absolute; left: 50%; top: var(--medal-y); z-index: 3;
  width: var(--medal); height: var(--medal);
  margin: calc(var(--medal) / -2) 0 0 calc(var(--medal) / -2);
  padding: 0; border: 0; border-radius: 50%;
  background: none;
  color: var(--paper-cream);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.medal__halo {
  position: absolute; inset: -1px; border-radius: 50%;
  box-shadow: 0 0 0 1px rgba(227, 191, 104, 0.75), 0 0 28px 5px rgba(var(--glow), 0.5);
  opacity: 0; pointer-events: none;
}
.gate.is-ready:not(.is-opening) .medal__halo { animation: medal-pulse 2.8s var(--ease-out) infinite; }
@keyframes medal-pulse { 0% { opacity: 0.95; transform: scale(1); } 100% { opacity: 0; transform: scale(1.16); } }
.medal__disc {
  position: absolute; inset: 0;
  border-radius: 50%;
  display: grid; justify-items: center; align-content: center;
  gap: calc(var(--medal) * 0.028);
  background: radial-gradient(circle at 50% 30%, #7d3634 0%, var(--maroon-700) 46%, var(--maroon-800) 82%, var(--maroon-900) 100%);
  box-shadow: 0 26px 50px -18px rgba(16, 4, 4, 0.85), 0 6px 16px rgba(16, 4, 4, 0.4), inset 0 2px 0 rgba(255, 222, 186, 0.14);
  transition: scale 0.55s var(--ease-out), box-shadow 0.55s var(--ease-out);
}
.medal__rings { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.medal__ring { fill: none; }
.medal__ring--outer { stroke: var(--gold-400); stroke-width: 1.6; }
.medal__ring--copper { stroke: #a4552a; stroke-width: 3.2; stroke-opacity: 0.85; }
.medal__ring--inner { stroke: var(--gold-500); stroke-width: 0.8; }
.medal__mark {
  width: 17%; aspect-ratio: 856 / 880;
  background: var(--gold-gradient-soft);
  -webkit-mask: url("/assets/img/mark.svg") center / contain no-repeat;
  mask: url("/assets/img/mark.svg") center / contain no-repeat;
}
.medal__script {
  width: 66%; aspect-ratio: 2574 / 1578;
  translate: -3% 0;
  background: linear-gradient(115deg, #e6c983 0%, #f8e9bf 42%, #d8b56c 68%, #c69a43 100%);
  -webkit-mask: url("/assets/img/poster/grand-opening-script.svg") center / contain no-repeat;
  mask: url("/assets/img/poster/grand-opening-script.svg") center / contain no-repeat;
}
.medal__cta {
  margin-top: 1%;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: max(10.5px, calc(var(--medal) * 0.044));
  line-height: 1;
  letter-spacing: 0.3em;
  padding-left: 0.3em;
  text-transform: uppercase;
  color: rgba(246, 238, 227, 0.92);
}
.gate.is-ready:not(.is-opening) .medal__cta { animation: cta-breathe 2.8s ease-in-out infinite; }
@keyframes cta-breathe { 0%, 100% { opacity: 0.92; } 50% { opacity: 0.6; } }
.medal:focus-visible { outline: 2px solid var(--gold-300); outline-offset: 7px; border-radius: 50%; }
@media (hover: hover) {
  .motion .medal:hover .medal__disc { scale: 1.035; box-shadow: 0 30px 56px -18px rgba(16, 4, 4, 0.9), 0 8px 20px rgba(16, 4, 4, 0.4), inset 0 2px 0 rgba(255, 222, 186, 0.2); }
}
.motion .medal:active .medal__disc { scale: 0.97; transition-duration: 0.15s; }
.gate.is-opening .medal { pointer-events: none; }

/* Short landscape screens: medallion a little lower, header tighter. */
@media (max-height: 520px) and (orientation: landscape) {
  .js .gate { --medal: min(64vw, 240px, 44svh); --medal-y: 62%; }
  .gate__top { top: 56px; gap: 3px; }
  .gate__clinic { font-size: 0.72rem; }
}

/* --------------------------------------------------------------------------
   Scene 2 — The Poster (#home)
   One viewport, every size. Sizes are "poster pixels" (the 1024 × 1280 artwork)
   times --pu, a height-based unit, and each element is also capped by the free
   width between the curtains at its height (--in-*: how far a drape reaches in).
   -------------------------------------------------------------------------- */
.poster { position: relative; background: var(--maroon-700); color: var(--paper-cream); }
.motion .poster { height: calc(max(600px, 100svh) + 125svh); background: transparent; }
.poster__stage {
  position: relative;
  height: var(--sh);
  overflow: hidden;
  overflow: clip;
  --pt: max(40px, calc(var(--sh) * 0.078));
  --pb: calc(var(--dock-space) + 42px);
  --pu: calc((var(--sh) - var(--pt) - var(--pb)) / 1090);
  --gx: 12px;
  --in-top: calc(var(--cw) * 0.95 - var(--co) + var(--gx));
  --in-script: calc(var(--cw) * 0.9 - var(--co) + var(--gx));
  --in-mid: calc(var(--cw) * 0.75 - var(--co) + var(--gx));
  --in-low: calc(var(--cw) * 0.6 - var(--co) + var(--gx));
}
.motion .poster__stage { height: var(--sh); }
html:not(.js) .poster__stage { --pb: 44px; }
.poster__bg, .poster__spot, .poster__amber, .poster__house { position: absolute; inset: 0; pointer-events: none; }
.poster__spot {
  z-index: 1;
  inset: -16% -20% 8%;
  background: radial-gradient(40% 46% at 50% 44%, rgba(255, 210, 156, 0.12), rgba(255, 210, 156, 0.045) 55%, rgba(255, 210, 156, 0) 76%);
}
.poster__glitter {
  position: absolute; left: 0; top: 0; z-index: 1;
  width: 100%; height: max(96px, calc(var(--pt) * 2.1));
  pointer-events: none;
}
.poster__content {
  position: absolute; left: 0; right: 0; z-index: 2;
  top: var(--pt); bottom: var(--pb);
  container-type: inline-size;
  display: flex; flex-direction: column; align-items: center; justify-content: space-between;
  text-align: center;
  will-change: transform;
}
.poster__eyebrow {
  font-family: var(--font-poster-serif);
  font-style: italic;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.01em;
  line-height: 1.32;
  font-size: max(12.5px, min(calc(29.5 * var(--pu)), calc((100vw - 2 * var(--in-top)) / 18.2)));
  font-size: max(12.5px, min(calc(29.5 * var(--pu)), calc((100cqi - 2 * var(--in-top)) / 18.2)));
  max-width: calc(100cqi - 2 * var(--in-top));
  text-wrap: balance;
}
.poster__title {
  flex: none;
  margin: 0;
  line-height: 0;
  width: min(calc(429 * var(--pu)), calc((100cqi - 2 * var(--in-script)) / 1.1));
  color: var(--paper-cream);
}
.poster__title:focus { outline: none; }
.script { display: block; width: 100%; height: auto; overflow: visible; translate: -5% 0; }
.script__shimmer { color: #f6dc97; }
.poster__art {
  position: relative; flex: none;
  width: min(calc(600 * var(--pu)), calc(100cqi - 2 * var(--in-mid)));
  aspect-ratio: 1293 / 931;
}
/* The image (the owner's 1312 × 1199 sketch) carries transparent margins: size it so
   its drawing (x 10–1303, y 147–1078) fills the box exactly. No filters. */
.poster__store {
  position: absolute;
  left: -0.773%; top: -15.79%;
  width: 101.47%; height: 128.79%;
  max-width: none;
}
.poster__store.is-drawing {
  -webkit-mask-image: linear-gradient(180deg, #000 calc(var(--wipe, 0%) - 7%), rgba(0, 0, 0, 0) var(--wipe, 0%));
  mask-image: linear-gradient(180deg, #000 calc(var(--wipe, 0%) - 7%), rgba(0, 0, 0, 0) var(--wipe, 0%));
}
.poster__pen {
  position: absolute; left: -3%; right: -3%; top: 0; height: 100%;
  pointer-events: none; opacity: 0;
}
.poster__pen::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 2px; margin-top: -1px;
  border-radius: 2px;
  background: linear-gradient(90deg, rgba(255, 240, 205, 0), rgba(255, 240, 205, 0.9) 18%, #fffaf0 50%, rgba(255, 240, 205, 0.9) 82%, rgba(255, 240, 205, 0));
  box-shadow: 0 0 14px 3px rgba(var(--glow), 0.5);
}
/* Tiny warm glows on the five ceiling lights (landmarks in % of the drawing box). */
.downlight {
  position: absolute; top: 28.25%;
  width: 3.4%; aspect-ratio: 1; margin: -1.7% 0 0 -1.7%;
  border-radius: 50%;
  background: radial-gradient(circle, #fffdf2 0 12%, rgba(255, 234, 176, 0.75) 24%, rgba(245, 200, 116, 0.22) 48%, rgba(245, 200, 116, 0) 70%);
  opacity: 0.7;
  pointer-events: none;
}
.downlight--1 { left: 13.61%; }
.downlight--2 { left: 29%; }
.downlight--3 { left: 48.8%; }
.downlight--4 { left: 64.5%; }
.downlight--5 { left: 86.47%; }

/* The gold ribbon with notched ends. White text sits on the deeper gold band (≥ 3:1). */
.ribbon {
  /* never wider than ~94% of the drawing (as on the poster) */
  --rw: min(calc(522 * var(--pu)), calc(100cqi - 2 * var(--in-low)), calc((100cqi - 2 * var(--in-mid)) * 0.94));
  position: relative; flex: none;
  display: flex; align-items: stretch;
  width: var(--rw);
  height: calc(var(--rw) * 0.1475);
  margin: 0;
  perspective: 700px;
}
.ribbon__body {
  position: relative; flex: 1;
  display: grid; place-items: center;
  margin: 0 -1px;
  overflow: hidden;
  background: linear-gradient(180deg, #d4a756 0%, var(--ribbon-gold) 20%, var(--ribbon-gold) 80%, #b8883b 100%);
}
.ribbon__band {
  position: absolute; left: 2%; right: 2%; top: 0; bottom: 0;
  background: linear-gradient(90deg, rgba(169, 122, 44, 0), rgba(169, 122, 44, 0.85) 6%, var(--ribbon-gold-deep) 11%, var(--ribbon-gold-deep) 89%, rgba(169, 122, 44, 0.85) 94%, rgba(169, 122, 44, 0));
}
.ribbon__text {
  position: relative;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: calc(var(--rw) * 0.058);
  line-height: 1;
  letter-spacing: 0.16em;
  padding-left: 0.16em;
  text-transform: uppercase;
  white-space: nowrap;
  color: #fff;
  text-shadow: 0 1px 1px rgba(92, 58, 10, 0.4);
}
.ribbon__text .char { display: inline-block; }
.ribbon__end {
  position: relative; flex: none;
  width: calc(var(--rw) * 0.072);
  background: linear-gradient(180deg, #cf9f4c 0%, var(--ribbon-gold) 24%, var(--ribbon-gold) 76%, #b3843a 100%);
}
.ribbon__end--l { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%, 58% 50%); transform-origin: 100% 50%; }
.ribbon__end--r { clip-path: polygon(0 0, 100% 0, 42% 50%, 100% 100%, 0 100%); transform-origin: 0 50%; }
.ribbon__shine {
  position: absolute; top: 0; bottom: 0; left: 0; width: 42%;
  background: linear-gradient(105deg, rgba(255, 249, 226, 0) 0%, rgba(255, 249, 226, 0.5) 50%, rgba(255, 249, 226, 0) 100%);
  transform: translateX(-120%);
  pointer-events: none;
}

.poster__info { display: grid; gap: 0.12em; }
.poster__venue, .poster__time {
  font-family: var(--font-poster-serif);
  font-style: italic;
  font-size: max(13px, min(calc(31 * var(--pu)), calc((100cqi - 2 * var(--in-low)) / 16.8)));
  line-height: 1.18;
  color: var(--paper-cream);
}
.poster__time { font-variant-numeric: lining-nums; }
.poster__rule {
  flex: none; display: block;
  width: max(64px, calc(172 * var(--pu)));
  height: max(1px, calc(2 * var(--pu)));
  background: rgba(246, 238, 227, 0.88);
}
.poster__see {
  font-family: var(--font-poster-serif);
  font-style: italic;
  font-size: max(12px, calc(20 * var(--pu)));
  letter-spacing: 0.05em;
  line-height: 1.2;
  color: rgba(246, 238, 227, 0.95);
}

/* Sits just under the content box (inside it, so it fades with the poster). */
.poster__cue {
  position: absolute; left: 0; right: 0; z-index: 4;
  top: calc(100% + 2px);
  width: max-content; margin: 0 auto;
  display: grid; justify-items: center; gap: 5px;
  padding: 3px 16px;
  color: rgba(246, 238, 227, 0.78);
  font-family: var(--font-body);
  font-size: 0.62rem; font-weight: 500;
  letter-spacing: 0.32em; padding-left: calc(16px + 0.32em);
  text-transform: uppercase;
  text-decoration: none;
  transition: color 0.35s;
}
.poster__cue-line { position: relative; width: 1px; height: 16px; overflow: hidden; background: rgba(246, 238, 227, 0.22); }
.poster__cue-line::after {
  content: ""; position: absolute; left: 0; top: 0; width: 1px; height: 50%;
  background: var(--gold-300);
  animation: cue-drop 2.2s var(--ease-in-out) infinite;
}
@keyframes cue-drop { 0% { transform: translateY(-100%); } 100% { transform: translateY(220%); } }
@media (hover: hover) { .poster__cue:hover { color: var(--gold-300); } }
html:not(.js) .poster__cue { display: none; }
/* The shortest phones (320×568): the poster stack uses every pixel down to "See You
   There!" and the cue would sit on that line — the dock already invites the scroll. */
@media (orientation: portrait) and (max-height: 600px) { .poster__cue { display: none; } }

.poster__amber {
  z-index: 5; opacity: 0;
  background:
    radial-gradient(85% 65% at 50% 40%, rgba(236, 200, 140, 0.9), rgba(236, 200, 140, 0) 75%),
    linear-gradient(180deg, #c4916a 0%, #b9835a 100%);
}
.poster__house { z-index: 6; opacity: 0; background: var(--bg); }

/* Wide desktop screens: the dock waits below the fold until the guest scrolls
   (html.dock-top, poster.js), so the poster gets that margin back and grows. */
/* Tablets and desktops: the poster ends on "See You There!" with open space below it,
   so the cue keeps its distance as one compact line in the stage's foot. */
@media (min-width: 601px), (orientation: landscape) {
  .poster__cue { top: calc(100% + 18px); grid-auto-flow: column; align-items: center; gap: 9px; padding-block: 2px; }
  .poster__cue-line { height: 14px; }
}
@media (min-width: 1024px) and (min-aspect-ratio: 4/3) {
  .motion .poster__stage { --pb: 54px; }
  html.js.motion.dock-top .dock { transform: translateY(calc(100% + 24px)); opacity: 0; }
  html.js.motion.dock-top .dock:focus-within { transform: none; opacity: 1; }
}

/* Portrait phones: the drawing is limited by the width, so the poster block keeps
   its own (slightly relaxed) rhythm — poster pixels × --pw, the width-based unit,
   never more than the height-based gap, so it always fits — and the spare height
   goes above it (under the canopy) and below it (above the cue). */
@media (max-width: 600px) and (orientation: portrait) {
  .poster__content {
    --pw: calc(min(calc(600 * var(--pu)), calc(100cqi - 2 * var(--in-mid))) / 600);
    justify-content: flex-start;
  }
  .poster__content::before, .poster__content::after { content: ""; flex: 3 1 0; min-height: 0; }
  .poster__content::after { flex-grow: 2; }
  .poster__title { margin-top: min(calc(34 * var(--pw) * 1.5), calc(34 * var(--pu))); }
  .poster__art { margin-top: min(calc(22 * var(--pw) * 1.5), calc(22 * var(--pu))); }
  .ribbon { margin-top: min(calc(26 * var(--pw) * 1.5), calc(26 * var(--pu))); }
  .poster__info { margin-top: min(calc(34 * var(--pw) * 1.5), calc(34 * var(--pu))); }
  .poster__rule { margin-top: min(calc(40 * var(--pw) * 1.5), calc(40 * var(--pu))); }
  .poster__see { margin-top: min(calc(30 * var(--pw) * 1.5), calc(30 * var(--pu))); }
}
/* The eyebrow keeps the poster's single line on common phones. */
/* (The line is 18.24em wide; at its height the drapes reach ~0.9 of their width.) */
@media (max-width: 440px) {
  .poster__eyebrow {
    --in-eyebrow: calc(var(--cw) * 0.9 - var(--co) + 3px);
    letter-spacing: 0;
    font-size: max(12px, min(calc(29.5 * var(--pu)), calc((100cqi - 2 * var(--in-eyebrow)) / 18.6)));
    max-width: calc(100cqi - 2 * var(--in-eyebrow) + 2px);
  }
}

/* Motion: everything waits for the curtains (poster.js plays the reveal). */
.motion .poster__spot, .motion .poster__glitter { opacity: 0; }
.motion .poster__curtain .curtain__drape { opacity: 0; }
.motion .poster__content > *, .motion .poster__cue { opacity: 0; }
.motion .poster__title { opacity: 1; }
.motion .downlight { opacity: 0; }

/* Short landscape phones: two columns so the poster still fits one screen. */
@media (max-height: 520px) and (orientation: landscape) {
  .poster__stage, .finale__stage { --sh: 100svh; }
  .poster__stage { --pt: 22px; --pb: calc(var(--dock-space) + 4px); --pu: calc((var(--sh) - var(--pt) - var(--pb)) / 560); }
  .motion .poster { height: 225svh; }
  .motion .poster + .story { margin-top: -100svh; }
  .poster__content {
    display: grid; grid-template-columns: auto auto; grid-auto-flow: column; grid-template-rows: repeat(6, auto);
    justify-content: center; align-content: center; justify-items: center; column-gap: 5vw; row-gap: 6px;
  }
  .poster__art { grid-column: 2; grid-row: 1 / -1; width: min(calc(600 * var(--pu)), 42vw); }
  .poster__cue { display: none; }
}

/* --------------------------------------------------------------------------
   Sticky "pinned" stages (motion only). Static layout is the default.
   -------------------------------------------------------------------------- */
.stage { position: relative; }
.motion .stage {
  position: sticky; top: 0;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
  overflow: clip;
}

/* --------------------------------------------------------------------------
   Scene 3 — Since 1996
   -------------------------------------------------------------------------- */
.story { position: relative; background: transparent; }
.motion .story { height: 320vh; height: 320svh; }
/* The story rises over the poster's last screen while its house lights come up:
   maroon → amber → cream, with the first chapter already arriving (no blank gap). */
.motion .poster + .story { margin-top: calc(-1 * max(600px, 100svh)); }
.story__stage {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: clamp(18px, 3.4svh, 34px);
  padding: clamp(72px, 10svh, 110px) var(--gutter) calc(var(--dock-space) + 28px);
  text-align: center;
}
.story__year {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(5.6rem, 31vw, 15rem);
  line-height: 0.82;
  letter-spacing: -0.02em;
  font-variant-numeric: lining-nums tabular-nums;
  font-feature-settings: "lnum" 1, "tnum" 1;
  padding: 0.04em 0.06em 0.08em;
}
.story__year-num {
  background: var(--gold-text);
  background-size: 100% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: var(--gold-600);
}

.timeline { position: relative; width: min(82vw, 520px); height: 46px; }
.timeline__track {
  position: absolute; left: 6px; right: 6px; top: 8px; height: 1px;
  background: rgba(198, 154, 67, 0.25);
}
.timeline__fill {
  position: absolute; inset: 0;
  background: linear-gradient(90deg, var(--gold-600), var(--gold-400), var(--gold-600));
  transform-origin: 0 50%;
}
.timeline__runner { position: absolute; inset: 0; will-change: transform; }
.timeline__spark {
  position: absolute; left: 0; top: -4px; width: 9px; height: 9px; margin-left: -4.5px;
  border-radius: 50%;
  background: #fff6dc;
  box-shadow: 0 0 0 1px var(--gold-500), 0 0 14px 4px rgba(var(--glow), 0.9);
  opacity: 0;
}
.timeline__dot {
  position: absolute; top: 4px; width: 9px; height: 9px; border-radius: 50%;
  background: var(--cream-50);
  box-shadow: inset 0 0 0 1.5px var(--gold-500);
}
.timeline__dot--start { left: 2px; background: var(--gold-500); }
.timeline__dot--end { right: 2px; background: var(--gold-500); }
.timeline__label {
  position: absolute; top: 22px;
  font-size: 0.78rem; font-weight: 500; letter-spacing: 0.18em;
  color: var(--gold-700);
}
.timeline__label--start { left: 0; }
.timeline__label--end { right: 0; }
.timeline__label--mid {
  left: 50%; transform: translateX(-50%);
  font-family: var(--font-display); font-style: italic; font-weight: 500;
  font-size: 1rem; letter-spacing: 0.02em; color: var(--ink-soft); top: 18px;
  white-space: nowrap;
  font-variant-numeric: lining-nums; font-feature-settings: "lnum" 1;
}

.story__beats { display: grid; gap: 40px; width: min(100%, 36rem); }
.beat { display: grid; gap: 14px; justify-items: center; }
.beat__label { font-size: 0.74rem; }
.beat__text {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(1.4rem, 5.4vw, 2.05rem);
  line-height: 1.32;
  color: var(--brown-800);
  text-wrap: balance;
}
/* The tagline closes the second chapter: a short gold rule, then three phrases
   in tracked caps that wrap between phrases, never inside one. */
.beat__tagline {
  position: relative;
  display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 0.95em;
  margin-top: 4px; padding-top: 18px;
  font-family: var(--font-body); font-weight: 500;
  font-size: 0.74rem; line-height: 1.5; letter-spacing: 0.24em; text-transform: uppercase;
  color: var(--gold-700);
  text-wrap: balance;
}
.beat__tagline::before {
  content: ""; position: absolute; top: 0; left: 50%;
  width: 46px; height: 1px; margin-left: -23px;
  background: linear-gradient(90deg, rgba(198, 154, 67, 0), var(--gold-500), rgba(198, 154, 67, 0));
  transform: scaleX(var(--rule, 1));
}
.beat__tagline-part { white-space: nowrap; }
.motion .story__beats { gap: 0; }
.motion .beat { grid-area: 1 / 1; }
.motion .beat--2 { opacity: 0; }
.motion .timeline__fill { transform: scaleX(0); }
.motion .timeline__label--mid { opacity: 0; }

/* --------------------------------------------------------------------------
   Storefront drawing (shared by #clinic and #finale): the owner's sketch,
   1312×1199 (same geometry as the SPEC §1 landmarks, verified on the new
   images). No filters. Landmarks in % of the drawing; % margins are relative
   to width, which keeps round glows
   centred on their landmark at every size.
   -------------------------------------------------------------------------- */
.storefront {
  position: relative;
  aspect-ratio: 1312 / 1199;
  width: 100%;
}
.storefront > * { position: absolute; }
.storefront > img { inset: 0; width: 100%; height: 100%; object-fit: contain; }
.storefront__sign { clip-path: inset(20% 20.4% 69% 20.4%); }
.storefront__sign-glow {
  left: 14%; top: 13%; width: 72%; height: 25%;
  background: radial-gradient(closest-side, rgba(var(--glow), 0.55), rgba(var(--glow), 0.18) 60%, rgba(var(--glow), 0));
}
.lamp {
  top: 34.1%;
  width: 18%; height: 0;
  margin-left: -9%;
}
.lamp--1 { left: 14.2%; }
.lamp--2 { left: 29.3%; }
.lamp--3 { left: 48.8%; }
.lamp--4 { left: 64.3%; }
.lamp--5 { left: 85.8%; }
.lamp > span { position: absolute; left: 0; width: 100%; }
.lamp__core {
  left: 41% !important; width: 18% !important; aspect-ratio: 1; top: 0;
  margin-top: -9%;
  border-radius: 50%;
  background: radial-gradient(circle, #fffdf3 0%, #fff1c9 35%, rgba(var(--glow), 0.7) 60%, rgba(var(--glow), 0) 72%);
}
.lamp__halo {
  aspect-ratio: 1; top: 0; margin-top: -50%;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 236, 190, 0.75) 0%, rgba(var(--glow), 0.35) 30%, rgba(var(--glow), 0) 68%);
}
.lamp__cone {
  top: 0;
  height: 0; padding-bottom: 230%;
  background: linear-gradient(180deg, rgba(255, 230, 170, 0.5) 0%, rgba(255, 230, 170, 0.2) 45%, rgba(255, 230, 170, 0) 88%);
  clip-path: polygon(45% 0, 55% 0, 100% 100%, 0 100%);
}
.storefront__door {
  left: 25.1%; top: 40%; width: 19.8%; height: 47.8%;
  border-radius: 50% 50% 1% 1% / 22.6% 22.6% 1% 1%;
  background:
    radial-gradient(120% 85% at 50% 72%, #fffef8 0%, #fff7e2 38%, rgba(247, 228, 180, 0.9) 70%, rgba(236, 212, 154, 0.55) 100%);
  box-shadow: 0 0 40px 12px rgba(var(--glow), 0.5);
  opacity: 0;
}
.storefront__pencil { inset: 0; pointer-events: none; opacity: 0; will-change: transform; }
.storefront__pencil-line {
  position: absolute; left: -3%; right: -3%; top: 0; height: 2px; margin-top: -1px;
  background: linear-gradient(90deg, rgba(var(--glow), 0) 0%, var(--gold-400) 12%, #fff4d2 50%, var(--gold-400) 88%, rgba(var(--glow), 0) 100%);
  box-shadow: 0 0 14px 3px rgba(var(--glow), 0.75), 0 0 2px rgba(168, 120, 44, 0.8);
  border-radius: 2px;
}
.storefront__glow, .storefront__flood {
  left: 35%; top: 63.9%;
  aspect-ratio: 1;
  border-radius: 50%;
  pointer-events: none;
  opacity: 0;
  will-change: transform, opacity;
}
.storefront__glow {
  width: 44%; margin: -22% 0 0 -22%;
  background: radial-gradient(closest-side, #fffef8 0%, rgba(255, 248, 228, 0.95) 40%, rgba(var(--glow), 0.45) 72%, rgba(var(--glow), 0) 100%);
}
.storefront__flood {
  width: 36%; margin: -18% 0 0 -18%;
  background: radial-gradient(closest-side, var(--bg) 0%, var(--bg) 72%, rgba(251, 246, 236, 0) 100%);
}

/* --------------------------------------------------------------------------
   Scene 4 — Our New Home
   -------------------------------------------------------------------------- */
.clinic { position: relative; }
.motion .clinic { height: 460vh; height: 460svh; }
.clinic__stage {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: clamp(14px, 3svh, 30px);
  padding: clamp(40px, 7svh, 80px) var(--gutter) calc(var(--dock-space) + 20px);
}
.clinic__frame {
  width: min(100%, 1000px);
  transform-origin: 35% 63.9%;
}
.motion .clinic__frame {
  flex: none;
  width: min(calc(100vw - 10px), 1000px, calc((100svh - var(--dock-space) - 230px) * 1.0944));
  will-change: transform;
}
.clinic .storefront__sign-glow, .clinic .lamp { opacity: 0.9; }
.clinic__captions {
  display: grid; gap: 10px; justify-items: center; text-align: center;
  width: min(100%, 34rem);
}
.caption__eyebrow { margin-bottom: 8px; }
.caption { text-wrap: balance; }
.caption__text {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 500;
  font-size: clamp(1.6rem, 6.4vw, 2.6rem);
  line-height: 1.12;
  color: var(--brown-800);
  text-wrap: balance;
}
.caption--2 .caption__text, .caption--3 .caption__text { font-size: clamp(1.4rem, 5.2vw, 2.2rem); color: var(--brown-700); }
.clinic__whiteout { position: absolute; inset: 0; background: var(--bg); opacity: 0; pointer-events: none; }
.motion .clinic__captions { min-height: 6.6rem; gap: 0; }
.motion .clinic__captions .caption { grid-area: 1 / 1; opacity: 0; }
/* Portrait: the chapter title enters first, above the drawing. */
@media (max-aspect-ratio: 1/1) {
  .motion .clinic__captions { order: -1; align-content: end; }
}
/* Wide screens: drawing and captions side by side, so the drawing can be large. */
@media (min-width: 1000px) and (min-aspect-ratio: 5/4) {
  .motion .clinic__stage { flex-direction: row; gap: clamp(40px, 4.5vw, 72px); }
  .motion .clinic__frame { width: min(60vw, 900px, calc((100svh - var(--dock-space) - 80px) * 1.0944)); }
  .motion .clinic__captions { width: min(26vw, 22rem); justify-items: start; text-align: left; }
}
.motion .clinic .storefront__lines { clip-path: inset(0% 0% 100% 0%); }
.motion .clinic .storefront__sign { clip-path: inset(20% 79.6% 69% 20.4%); }
.motion .clinic .storefront__sign-glow,
.motion .clinic .lamp { opacity: 0; }

/* --------------------------------------------------------------------------
   Scene 5 — The Celebration
   -------------------------------------------------------------------------- */
.details {
  position: relative;
  padding: clamp(72px, 14vw, 140px) 0 clamp(64px, 12vw, 120px);
}
.cards {
  list-style: none;
  display: grid; gap: 16px;
  grid-template-columns: 1fr;
}
@media (min-width: 700px) { .cards { grid-template-columns: repeat(3, 1fr); gap: clamp(14px, 2vw, 22px); } }
.card {
  position: relative;
  display: grid; justify-items: center; align-content: center; gap: 6px;
  padding: 30px 22px 28px;
  text-align: center;
  background: linear-gradient(180deg, rgba(255, 253, 248, 0.95), rgba(255, 253, 248, 0.7));
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-soft);
}
.card::before {
  content: ""; position: absolute; inset: 6px; border-radius: calc(var(--radius-lg) - 5px);
  border: 1px solid rgba(198, 154, 67, 0.22); pointer-events: none;
}
.card__icon {
  width: 46px; height: 46px; margin-bottom: 10px;
  fill: none; stroke: var(--gold-600); stroke-width: 1.3; stroke-linecap: round; stroke-linejoin: round;
}
.card__label {
  font-family: var(--font-body); font-weight: 500; font-size: 0.74rem;
  letter-spacing: 0.26em; text-transform: uppercase; color: var(--gold-700);
}
.card__value {
  font-family: var(--font-display); font-weight: 500;
  font-variant-numeric: lining-nums; font-feature-settings: "lnum" 1;
  font-size: clamp(1.45rem, 5.4vw, 1.75rem); line-height: 1.2;
  color: var(--brown-800);
}
.card__sub { color: var(--ink-soft); font-size: 0.95rem; max-width: 26ch; text-wrap: pretty; }
/* The ceremony note under the time: the ceremony leads, the open house follows. */
.card__note {
  display: grid; justify-items: center; gap: 1px;
  max-width: 30ch; margin-top: 6px; padding-top: 10px;
  position: relative; line-height: 1.4; text-wrap: balance;
  font-variant-numeric: lining-nums; font-feature-settings: "lnum" 1;
}
.card__note::before {
  content: ""; position: absolute; top: 0; left: 50%; width: 28px; height: 1px; margin-left: -14px;
  background: linear-gradient(90deg, rgba(198, 154, 67, 0), var(--gold-500), rgba(198, 154, 67, 0));
}
.card__note .note__lead { color: var(--ink); font-weight: 500; }
.card__note .note__rest::before { content: none; }
/* No JS: the note stays one raw string. A width between "…10:00 AM ·" (14.4em) and
   "…AM · Open" (17.1em) makes a plain wrap break after the ceremony time, never
   between "10:00" and "AM" (which is where balance would put it). */
html:not(.js) .card__note { max-width: 15.6em; text-wrap: wrap; }

.countdown {
  margin: clamp(40px, 8vw, 72px) auto 0;
  display: grid; justify-items: center; gap: 18px;
  text-align: center;
}
.countdown__grid { display: flex; align-items: flex-start; justify-content: center; gap: clamp(8px, 3vw, 26px); }
.countdown__unit { display: grid; justify-items: center; gap: 6px; min-width: clamp(58px, 17vw, 96px); }
.countdown__num {
  display: block;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(2.6rem, 12.5vw, 4.6rem);
  line-height: 1;
  font-variant-numeric: lining-nums tabular-nums;
  font-feature-settings: "lnum" 1, "tnum" 1;
  color: var(--brown-800);
}
.countdown__name { font-size: 0.7rem; font-weight: 500; letter-spacing: 0.2em; text-transform: uppercase; color: var(--ink-muted); }
.countdown__sep {
  align-self: center; margin-top: -1.3em;
  width: 4px; height: 4px; border-radius: 50%; background: var(--gold-500);
}
.countdown__state {
  font-family: var(--font-display); font-style: italic; font-weight: 500;
  font-size: clamp(1.8rem, 7vw, 2.6rem); color: var(--brown-800);
}
/* "Happening now" / "Thank you for celebrating with us" ease in when they take over. */
.motion .countdown__state.is-shown { animation: state-in 1.1s var(--ease-out) both; }
@keyframes state-in { from { opacity: 0; transform: translateY(14px) scale(0.98); } to { opacity: 1; transform: none; } }

.details__actions {
  margin-top: clamp(40px, 8vw, 64px);
  display: grid; gap: 26px;
  justify-content: center;
}
@media (min-width: 860px) { .details__actions { grid-template-columns: auto auto; gap: 56px; } }
.action-group { display: grid; justify-items: center; gap: 12px; }
.action-group__row { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; }

/* --------------------------------------------------------------------------
   Scene 6 — RSVP
   -------------------------------------------------------------------------- */
.rsvp { position: relative; padding: clamp(64px, 12vw, 120px) 0 clamp(72px, 12vw, 120px); }
.rsvp__panel {
  position: relative;
  padding: clamp(22px, 5.5vw, 48px);
  background: linear-gradient(180deg, rgba(255, 253, 248, 0.98), rgba(255, 252, 245, 0.92));
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lift);
}
.rsvp__panel::before {
  content: ""; position: absolute; inset: 7px; border-radius: calc(var(--radius-lg) - 6px);
  border: 1px solid rgba(198, 154, 67, 0.28); pointer-events: none;
}
/* The Guest Pass carries its own gold frame: drop the panel chrome around it. */
.rsvp__panel.is-pass { background: none; border-color: transparent; box-shadow: none; padding-inline: 0; }
.rsvp__panel.is-pass::before { display: none; }
.notice { color: var(--ink); text-align: center; }
.rsvp__form { position: relative; display: grid; gap: 22px; }
.rsvp__form[hidden] { display: none; }
.rsvp__saved { text-align: center; margin-bottom: -6px; }

.field { display: grid; gap: 8px; min-width: 0; border: 0; padding: 0; margin: 0; }
.field-row { display: grid; gap: 22px; }
@media (min-width: 620px) { .field-row { grid-template-columns: 1fr 1fr; gap: 18px; } }
.field__label {
  padding: 0;
  font-weight: 500; font-size: 0.95rem; color: var(--brown-800);
}
.req { color: var(--gold-700); }
.opt { color: var(--ink-muted); font-weight: 400; }
.field__hint { display: flex; justify-content: space-between; gap: 12px; font-size: 0.86rem; color: var(--ink-muted); }
.field__hint:empty { display: none; }
.field__count { font-variant-numeric: tabular-nums; white-space: nowrap; }
.field__error {
  display: none;
  font-size: 0.88rem; font-weight: 500; color: var(--danger);
}
.field__error.is-visible { display: flex; gap: 6px; align-items: flex-start; }
.field__error.is-visible::before {
  content: "!"; flex: none; display: grid; place-items: center;
  width: 16px; height: 16px; margin-top: 2px; border-radius: 50%;
  background: var(--danger); color: #fff; font-size: 0.7rem; font-weight: 600;
}
.field__error a { color: var(--danger); font-weight: 600; }

.input {
  width: 100%;
  min-height: 52px;
  padding: 13px 16px;
  font-size: 1rem;
  font-family: var(--font-body);
  color: var(--ink);
  background: #fffefb;
  border: 1px solid var(--line-strong);
  border-radius: 14px;
  box-shadow: inset 0 1px 2px rgba(74, 44, 29, 0.05);
  transition: border-color 0.25s, box-shadow 0.25s, background-color 0.25s;
  -webkit-appearance: none; appearance: none;
}
.input::placeholder { color: #9c8878; }
textarea.input { min-height: 4.6em; max-height: 16em; resize: none; line-height: 1.5; field-sizing: content; }
#f-wish { min-height: 6.1em; }
.input:hover { border-color: var(--sand-500); }
.input:focus { outline: none; border-color: var(--gold-600); box-shadow: 0 0 0 3px rgba(198, 154, 67, 0.22); background: #fff; }
.input:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.input[aria-invalid="true"] { border-color: var(--danger); box-shadow: 0 0 0 3px rgba(164, 69, 47, 0.12); }
.select { position: relative; }
.select::after {
  content: ""; position: absolute; right: 18px; top: 50%; width: 8px; height: 8px; margin-top: -6px;
  border-right: 1.5px solid var(--gold-600); border-bottom: 1.5px solid var(--gold-600);
  transform: rotate(45deg); pointer-events: none;
}
.select .input { padding-right: 44px; }

/* The lucky-draw promise under the RSVP lede */
.rsvp__lucky {
  display: inline-flex; align-items: center; gap: 10px;
  margin-top: 14px; padding: 7px 16px 7px 12px;
  border-radius: 999px;
  border: 1px solid rgba(198, 154, 67, 0.55);
  background: linear-gradient(180deg, rgba(255, 253, 248, 0.9), rgba(251, 243, 227, 0.9));
  font-size: 0.9rem; font-weight: 500; color: var(--brown-700);
  text-wrap: balance;
}
.rsvp__lucky-star {
  flex: none; width: 12px; height: 12px;
  background: var(--gold-gradient-soft);
  clip-path: polygon(50% 0, 62% 38%, 100% 50%, 62% 62%, 50% 100%, 38% 62%, 0 50%, 38% 38%);
}

/* Arrival windows (cards) */
.slots { display: grid; gap: 10px; }
@media (min-width: 560px) { .slots { grid-template-columns: 1fr 1fr; } }
.slots__loading, .slots__error { grid-column: 1 / -1; color: var(--ink-muted); font-size: 0.95rem; padding: 14px 4px; }
.slots__error { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; color: var(--ink-soft); }
.slot { position: relative; display: grid; cursor: pointer; }
.slot__input { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; pointer-events: none; }
.slot__body {
  position: relative;
  display: flex; flex-direction: column; gap: 10px;
  padding: 16px 18px 16px;
  border-radius: 16px;
  background: #fffefb;
  border: 1px solid var(--line-strong);
  transition: border-color 0.3s, box-shadow 0.3s, background-color 0.3s, translate 0.35s var(--ease-out), scale 0.35s var(--ease-out);
}
@media (hover: hover) { .slot:hover .slot__body { border-color: var(--gold-500); } }
.slot__top { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.slot__time {
  font-family: var(--font-display); font-weight: 600;
  font-variant-numeric: lining-nums tabular-nums; font-feature-settings: "lnum" 1, "tnum" 1;
  font-size: clamp(1.1rem, 5.2vw, 1.28rem); line-height: 1.15; color: var(--brown-800);
}
.slot__check {
  flex: none; width: 22px; height: 22px; border-radius: 50%;
  border: 1px solid var(--line-strong); background: var(--cream-50);
  display: grid; place-items: center;
  transition: background 0.3s, border-color 0.3s;
}
.slot__check::after {
  content: ""; width: 9px; height: 5px; margin-top: -2px;
  border-left: 1.6px solid #fff; border-bottom: 1.6px solid #fff;
  transform: rotate(-45deg) scale(0); transition: transform 0.35s var(--ease-out);
}
.slot__note {
  margin-top: -4px;
  font-family: var(--font-display); font-style: italic; font-weight: 500;
  font-size: 1rem; line-height: 1.3;
  color: var(--ink-soft);
  text-wrap: pretty;
}
.slot.is-full .slot__note { color: var(--ink-muted); }
.slot__bar { position: relative; flex: none; height: 4px; margin-top: auto; border-radius: 4px; background: var(--cream-200); overflow: hidden; }
.slot__fill {
  position: absolute; inset: 0; border-radius: 4px;
  background: linear-gradient(90deg, var(--gold-600), var(--gold-400));
  transform-origin: 0 50%;
  transform: scaleX(0);
}
.slot__meta { display: flex; justify-content: space-between; gap: 10px; font-size: 0.86rem; color: var(--ink-muted); }
.slot__left { display: inline-flex; align-items: center; gap: 6px; font-weight: 500; color: var(--gold-700); }
.slot__left.is-low { color: var(--brown-600); font-weight: 600; }
.slot__left.is-low::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: var(--gold-500); box-shadow: 0 0 0 3px rgba(198, 154, 67, 0.18); }
.slot__input:checked + .slot__body {
  border-color: var(--gold-600);
  background: linear-gradient(180deg, #fffaf0, #fff6e4);
  box-shadow: 0 0 0 1px var(--gold-600), 0 12px 26px -14px rgba(138, 95, 31, 0.55);
}
.slot__input:checked + .slot__body .slot__check { background: var(--gold-600); border-color: var(--gold-600); }
.slot__input:checked + .slot__body .slot__check::after { transform: rotate(-45deg) scale(1); }
.slot__input:focus-visible + .slot__body { outline: 2px solid var(--focus); outline-offset: 3px; }
.slot.is-full { cursor: not-allowed; }
.slot.is-full .slot__body { background: var(--cream-100); border-style: dashed; }
.slot.is-full .slot__time { color: var(--ink-muted); text-decoration: line-through; text-decoration-thickness: 1px; text-decoration-color: rgba(118, 96, 79, 0.5); }
.slot.is-full .slot__left { color: var(--ink-muted); }
.slot.is-full .slot__fill { background: var(--sand-500); }
.field--slots[aria-invalid="true"] .slot__body { border-color: rgba(164, 69, 47, 0.55); }

.hp { position: absolute !important; left: -10000px; top: auto; width: 1px; height: 1px; overflow: hidden; }

.rsvp__status { min-height: 1.4em; text-align: center; font-size: 0.95rem; color: var(--ink-soft); }
.rsvp__status:empty { min-height: 0; margin-top: -22px; }
.rsvp__status.is-error { color: var(--danger); font-weight: 500; }
.rsvp__status.is-error a { color: var(--danger); font-weight: 600; }
/* Live messages (status, the pax hint, the windows' load error) ease in whenever they change. */
.motion .rsvp__status.is-new:not(:empty), .motion #hint-pax.is-new:not(:empty), .motion .slots__error { animation: error-in 0.45s var(--ease-out) both; }

.rsvp__submit { min-height: 56px; font-size: 1.05rem; }
.btn__spinner {
  display: none;
  width: 18px; height: 18px; border-radius: 50%;
  border: 2px solid rgba(255, 253, 248, 0.45); border-top-color: #fffdf8;
  animation: spin 0.8s linear infinite;
}
.rsvp__submit.is-loading .btn__spinner { display: inline-block; }
.rsvp__submit.is-loading { cursor: progress; }
.rsvp__submit[aria-disabled="true"] { opacity: 0.85; }
@keyframes spin { to { transform: rotate(360deg); } }

/* Closed notice */
.closed { display: grid; justify-items: center; gap: 14px; text-align: center; padding: 10px 0; }
.closed__mark {
  width: 46px; aspect-ratio: 856 / 880;
  background: var(--gold-gradient-soft);
  -webkit-mask: url("/assets/img/mark.svg") center / contain no-repeat;
  mask: url("/assets/img/mark.svg") center / contain no-repeat;
}
.closed__title {
  font-family: var(--font-display); font-weight: 500; font-size: clamp(1.8rem, 7vw, 2.4rem); line-height: 1.1; color: var(--brown-800);
}
.closed__text { color: var(--ink-soft); max-width: 34ch; text-wrap: pretty; }

/* Result: the number reveal, then the golden ticket and its save actions (css/ticket.css) */
.rsvp__result { display: grid; justify-items: center; gap: 18px; }

/* --------------------------------------------------------------------------
   Scene 7 — Wishes
   -------------------------------------------------------------------------- */
.wishes { position: relative; padding: clamp(56px, 10vw, 110px) 0 clamp(48px, 8vw, 96px); }
.wishes__stat {
  margin-top: 16px;
  font-family: var(--font-display); font-style: italic; font-size: clamp(1.15rem, 4.4vw, 1.35rem); color: var(--ink-soft);
}
.wishes__stat strong { font-style: normal; font-weight: 600; color: var(--gold-700); font-variant-numeric: lining-nums; font-feature-settings: "lnum" 1; }
.wishes__list {
  list-style: none;
  display: flex; flex-wrap: wrap; justify-content: center; align-items: flex-start;
  gap: 18px;
}
.wish {
  flex: 1 1 290px;
  max-width: 380px;
  margin: 0;
  padding: 26px 24px 22px;
  background: rgba(255, 253, 248, 0.9);
  border: 1px solid var(--line);
  border-radius: 20px;
  box-shadow: 0 8px 24px -16px rgba(74, 44, 29, 0.3);
  position: relative;
}
.wish::before {
  content: "\201C";
  position: absolute; top: 4px; left: 18px;
  font-family: var(--font-display); font-size: 3.6rem; line-height: 1;
  color: var(--gold-400);
}
.wish__text {
  position: relative;
  padding-top: 14px;
  font-family: var(--font-display); font-style: italic; font-weight: 500;
  font-size: 1.24rem; line-height: 1.4; color: var(--brown-800);
  white-space: pre-line; overflow-wrap: anywhere;
}
.wish__name {
  margin-top: 14px;
  font-size: 0.8rem; font-weight: 500; letter-spacing: 0.18em; text-transform: uppercase; color: var(--gold-700);
  overflow-wrap: anywhere;
}
.wish.is-new { box-shadow: 0 0 0 1px var(--gold-500), 0 14px 30px -16px rgba(138, 95, 31, 0.5); }
.motion .wish.pre { opacity: 0; transform: translateY(26px); }
.motion .wish { transition: opacity 0.9s var(--ease-out), transform 1.1s var(--ease-out), translate 0.5s var(--ease-out), box-shadow 0.5s var(--ease-out), border-color 0.4s; }
.wishes__empty { display: grid; justify-items: center; gap: 16px; text-align: center; }
.wishes__empty-text { font-family: var(--font-display); font-style: italic; font-size: 1.35rem; color: var(--ink-soft); text-align: center; }
/* The one soft line #programme / #wishes show while /api/event is unavailable. */
.section-soft { max-width: 30ch; margin: 0 auto; font-size: 1.2rem; text-wrap: balance; }
.section-soft[hidden] { display: none; }
.wishes__more-wrap { display: flex; justify-content: center; margin-top: 12px; }

/* --------------------------------------------------------------------------
   Scene 8 — Finale (dusk)
   -------------------------------------------------------------------------- */
.finale { position: relative; overflow: clip; background: var(--night); color: var(--cream-100); }
/* Scrubbed: dusk → the closing message → the farewell (curtains return) → hold →
   the curtains close → the end card (finale.js). */
.motion .finale { height: 480vh; height: 480svh; background: transparent; }
.finale__stage {
  display: flex; flex-direction: column; justify-content: center;
  /* the curtains frame the farewell: content stays clear of the drapes */
  --in-finale: max(var(--gutter), calc(var(--cw) * 0.74 - var(--co) + 12px));
  --foot-h: 44px;
  padding: clamp(44px, 8svh, 80px) var(--in-finale) calc(var(--dock-space) + 8px);
}
.motion .finale__stage { padding-bottom: calc(var(--dock-space) + var(--foot-h)); }
/* The glitter canopy stays above everything, closed curtains included. */
.finale__glitter {
  position: absolute; left: 0; top: 0; z-index: 5;
  width: 100%; height: max(96px, 17svh);
  pointer-events: none;
}
.finale__canopy { height: max(90px, 16svh); }
.finale__inner { z-index: 2; }
.finale__footer { z-index: 6; }
.motion .finale__glitter { opacity: 0; }
.finale__dusk {
  position: absolute; left: 0; right: 0; top: 0;
  height: 100%;
}
.motion .finale__dusk { height: 100vh; height: 100lvh; opacity: 0; }
/* Golden hour: a warm amber wash comes first, so cream → amber → deep brown
   never passes through a flat grey. */
.finale__amber { display: none; }
.motion .finale__amber {
  display: block;
  position: absolute; left: 0; right: 0; top: 0;
  height: 100vh; height: 100lvh;
  opacity: 0;
  background:
    radial-gradient(95% 62% at 50% 32%, rgba(255, 232, 178, 0.95), rgba(255, 232, 178, 0) 72%),
    linear-gradient(180deg, #efd2a0 0%, #dcad74 52%, #b98150 100%);
}
.finale__inner {
  position: relative;
  display: grid; grid-template-columns: minmax(0, 1fr); justify-items: center; align-items: center;
  gap: clamp(18px, 3.2svh, 34px);
  width: min(100%, 1100px); margin: 0 auto;
}
.finale__art { width: min(100%, 560px, calc(100vw - 2 * (var(--cw) * 0.95 - var(--co) + 10px))); }
/* Height budget: the screen minus paddings, the farewell copy (≈ 275px + 23vw below
   the title's max size), the footer and the dock — so the stack always fits. */
.motion .finale__art { width: min(100%, 560px, max(96px, calc((88.8svh - 448px - 23vw) * 1.0944)), calc(100vw - 2 * (var(--cw) * 0.95 - var(--co) + 10px))); }
.storefront--night .storefront__day { opacity: 0; }
.storefront--night .storefront__night { opacity: 1; }
.storefront--night .lamp > span, .storefront--night .storefront__sign-glow { mix-blend-mode: screen; }
.storefront--night .storefront__sign-glow { background: radial-gradient(closest-side, rgba(var(--glow), 0.5), rgba(var(--glow), 0.12) 60%, rgba(var(--glow), 0)); }
.storefront--night .lamp__cone { background: linear-gradient(180deg, rgba(255, 222, 150, 0.55) 0%, rgba(255, 222, 150, 0.2) 45%, rgba(255, 222, 150, 0) 88%); }
.storefront--night .storefront__door {
  opacity: 0.55;
  background: radial-gradient(120% 85% at 50% 72%, rgba(255, 240, 200, 0.75) 0%, rgba(241, 214, 140, 0.4) 55%, rgba(241, 214, 140, 0.12) 100%);
  box-shadow: 0 0 50px 10px rgba(var(--glow), 0.25);
  mix-blend-mode: screen;
}
.motion .storefront--night .storefront__day { opacity: 1; }
.motion .storefront--night .storefront__night,
.motion .storefront--night .lamp,
.motion .storefront--night .storefront__sign-glow,
.motion .storefront--night .storefront__door { opacity: 0; }

/* Two beats: the closing message, then the farewell. Static: one after the other;
   motion: they share one place and hand over (finale.js). */
.finale__text { width: 100%; display: grid; grid-template-columns: minmax(0, 1fr); justify-items: center; gap: clamp(44px, 8svh, 72px); }
.motion .finale__text { gap: 0; }
.motion .finale__beat { grid-area: 1 / 1; align-self: center; }
.finale__message { display: grid; grid-template-columns: minmax(0, 1fr); justify-items: center; gap: 12px; max-width: 36rem; text-align: center; }
.finale__lede { max-width: 31em; }
/* Single column: the message arrives before the curtains come back, so it may use
   the width between the gutters. */
.motion .finale__message { justify-self: stretch; max-width: none; margin-inline: calc(var(--gutter) - var(--in-finale)); }
.finale__ornament {
  display: block; width: 72px; height: 1px; margin-bottom: 6px;
  background: linear-gradient(90deg, rgba(227, 191, 104, 0), var(--gold-400), rgba(227, 191, 104, 0));
}
.finale__lede {
  font-family: var(--font-display); font-style: italic; font-weight: 400;
  font-size: clamp(1.2rem, 4.5vw, 1.62rem); line-height: 1.34;
  color: var(--cream-100);
  text-wrap: pretty;
}
.finale__tagline {
  margin-top: 10px;
  font-family: var(--font-body); font-weight: 500;
  font-size: clamp(0.72rem, 2.9vw, 0.84rem); line-height: 1.8;
  letter-spacing: 0.24em; padding-left: 0.24em;
  text-transform: uppercase;
  color: var(--gold-300);
  text-wrap: balance;
}
.finale__copy { display: grid; grid-template-columns: minmax(0, 1fr); justify-items: center; gap: 10px; text-align: center; }
.finale__logo {
  width: clamp(92px, 14svh, 150px); aspect-ratio: 2100 / 1566;
  background: var(--gold-gradient-soft);
  -webkit-mask: url("/assets/img/logo.svg") center / contain no-repeat;
  mask: url("/assets/img/logo.svg") center / contain no-repeat;
  margin-bottom: 4px;
}
.finale__title {
  font-family: var(--font-display); font-weight: 500;
  font-size: clamp(2.1rem, 8.8vw, 3.8rem); line-height: 1.04;
  color: var(--cream-100);
  text-wrap: balance;
}
.finale__date { font-size: clamp(1rem, 4vw, 1.15rem); letter-spacing: 0.34em; padding-left: 0.34em; color: var(--gold-300); margin-top: 6px; }
.finale__time { font-size: 0.95rem; color: var(--beige-300); }
.finale__rule { display: block; width: 72px; height: 1px; margin-top: 6px; background: rgba(246, 238, 227, 0.7); transform-origin: 50% 50%; }
.finale__see {
  font-family: var(--font-poster-serif); font-style: italic;
  font-size: clamp(0.95rem, 3.8vw, 1.1rem); letter-spacing: 0.05em;
  color: var(--paper-cream);
}
/* The scrub moves the wrapper, so the button keeps its own hover lift and press. */
/* (A flex row centres the one-line button even where it is wider than the column:
   low on the stage the drapes leave it more room than the column assumes.) */
.finale__cta-wrap { justify-self: stretch; display: flex; justify-content: center; margin-top: 10px; }
.finale__cta {
  flex: none;
  white-space: nowrap;
  font-size: clamp(0.86rem, 3.9vw, 1rem);
  padding-inline: clamp(14px, 4vw, 24px);
}
.finale__footer {
  position: relative;
  margin-top: clamp(18px, 3svh, 32px);
  text-align: center;
  font-size: 0.68rem; font-weight: 500; letter-spacing: 0.24em; text-transform: uppercase;
  line-height: 1.9;
  color: var(--beige-400);
  text-shadow: 0 1px 8px rgba(24, 6, 5, 0.85);
}
/* Motion: the signature sits just above the dock, over the stage and, at the very
   end, over the closed curtains. */
.motion .finale__footer {
  position: absolute; left: 0; right: 0; bottom: calc(var(--dock-space) + 2px);
  margin: 0; padding: 0 var(--gutter);
}

/* The curtain-fall (SPEC §10.3): the velvet panels (see .vpanel) close from the tied-
   back drapes and the medallion returns on the seam as an end card. Static (reduced
   motion / no JS): a closed-curtain end card after the farewell. */
.finale__fall {
  position: relative; z-index: 4;
  height: clamp(480px, 88svh, 760px);
  margin: clamp(48px, 9svh, 88px) calc(-1 * var(--in-finale)) 0;
  overflow: hidden;
  --medal: min(58vw, 240px, 36svh);
}
.motion .finale__fall {
  position: absolute; inset: 0; margin: 0; height: auto;
  pointer-events: none;
  --medal: min(56vw, 244px, 32svh);
}
.motion .finale__fall .vpanel { opacity: 0; }
.endcard {
  position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: 2;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: clamp(16px, 3svh, 26px);
  padding: 24px var(--gutter);
  text-align: center;
}
.motion .endcard {
  top: clamp(44px, 8svh, 80px); bottom: calc(var(--dock-space) + var(--foot-h));
  padding: 0 var(--gutter);
  visibility: hidden; opacity: 0;
}
.endcard__medal {
  position: relative; flex: none;
  width: var(--medal); height: var(--medal);
  border-radius: 50%;
  display: grid; justify-items: center; align-content: center;
  gap: calc(var(--medal) * 0.022);
  padding-bottom: calc(var(--medal) * 0.07); /* the stack sits a touch high: a wider chord for the date line */
  background: radial-gradient(circle at 50% 30%, #7d3634 0%, var(--maroon-700) 46%, var(--maroon-800) 82%, var(--maroon-900) 100%);
  box-shadow: 0 26px 50px -18px rgba(16, 4, 4, 0.85), 0 6px 16px rgba(16, 4, 4, 0.4), inset 0 2px 0 rgba(255, 222, 186, 0.14);
  color: var(--paper-cream);
}
.endcard__rings { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.endcard__ring { fill: none; }
.endcard__mark {
  width: 15%; aspect-ratio: 856 / 880;
  background: var(--gold-gradient-soft);
  -webkit-mask: url("/assets/img/mark.svg") center / contain no-repeat;
  mask: url("/assets/img/mark.svg") center / contain no-repeat;
}
.endcard__thanks {
  font-family: var(--font-script);
  font-size: calc(var(--medal) * 0.172);
  line-height: 1.12;
  padding: 0 0.12em;
  background: linear-gradient(115deg, #e6c983 0%, #f8e9bf 42%, #d8b56c 68%, #c69a43 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.endcard__see {
  display: grid; justify-items: center; gap: 3px;
  font-family: var(--font-poster-serif); font-style: italic;
  font-size: max(13px, calc(var(--medal) * 0.058));
  line-height: 1.3;
  color: rgba(246, 238, 227, 0.92);
}
.endcard__date {
  font-family: var(--font-body); font-style: normal; font-weight: 600;
  font-size: max(13px, calc(var(--medal) * 0.062));
  letter-spacing: 0.16em; padding-left: 0.16em;
  color: var(--gold-300);
  font-variant-numeric: lining-nums;
}
.endcard__top {
  pointer-events: auto;
  min-height: 46px;
  padding: 10px 22px;
  font-size: 0.92rem;
  background: rgba(47, 18, 18, 0.55);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}
.endcard__arrow { display: inline-block; transition: transform 0.5s var(--ease-out); }
@media (hover: hover) { .motion .endcard__top:hover .endcard__arrow { transform: translateY(-3px); } }
/* Narrow screens: two deliberate lines instead of a dangling separator. */
@media (max-width: 640px), (max-width: 760px) and (orientation: portrait) {
  .finale__sep { display: block; height: 0; overflow: hidden; }
  .finale__footer { letter-spacing: 0.2em; }
}
@media (max-width: 360px) { .finale__footer { letter-spacing: 0.15em; } }
@media (max-width: 340px) { .finale__cta { font-size: 0.8rem; gap: 7px; padding-inline: 12px; } }
.motion .finale__copy > *, .motion .finale__message > *, .motion .finale__footer { opacity: 0; }
/* Short phones: the farewell drops the logo so the stack still clears the dock. */
@media (max-height: 640px) {
  .motion .finale__logo { display: none; }
  .motion .finale__title { font-size: clamp(1.8rem, 8vw, 2.4rem); }
  .motion .finale__lede { font-size: clamp(1.1rem, 4.2vw, 1.3rem); }
}

@media (min-width: 1000px) and (min-aspect-ratio: 5/4) {
  .finale__inner { grid-template-columns: 1.15fr 1fr; justify-items: stretch; gap: 64px; }
  .finale__art { justify-self: end; }
  .motion .finale__art { width: min(100%, 620px, calc((100svh - var(--dock-space) - 190px) * 1.0944)); }
  .finale__copy, .finale__message { justify-items: start; text-align: left; }
  .finale__cta-wrap { justify-content: flex-start; }
  .finale__text { justify-items: start; }
  .motion .finale__message { margin-inline: 0; }
  .finale__ornament { background: linear-gradient(90deg, var(--gold-400), rgba(227, 191, 104, 0)); }
}

/* --------------------------------------------------------------------------
   Persistent UI — progress, dock, sheets, toast
   -------------------------------------------------------------------------- */
.progress { display: none; }
.js .progress {
  display: block;
  position: fixed; left: 0; right: 0; top: 0; height: 2px; z-index: 75;
  pointer-events: none;
  opacity: 0; transition: opacity 0.6s;
}
.gate-done .progress, .no-gate .progress, .reduced-motion .progress { opacity: 1; }
.progress__bar {
  display: block; height: 100%;
  background: var(--gold-gradient-soft);
  transform-origin: 0 50%;
  transform: scaleX(0);
  box-shadow: 0 0 8px rgba(var(--glow), 0.8);
}

.dock { display: none; }
.js .dock {
  position: fixed; z-index: 70;
  left: 0; right: 0; margin: 0 auto;
  bottom: calc(12px + env(safe-area-inset-bottom, 0px));
  width: max-content; max-width: calc(100% - 16px);
  display: flex; align-items: center; gap: 2px;
  padding: 5px;
  border-radius: 999px;
  background: rgba(255, 252, 245, 0.78);
  -webkit-backdrop-filter: blur(16px) saturate(1.4);
  backdrop-filter: blur(16px) saturate(1.4);
  border: 1px solid rgba(198, 154, 67, 0.38);
  box-shadow: 0 14px 34px -12px rgba(46, 26, 16, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.6);
  transform: translateY(160%);
  opacity: 0;
  transition: transform 0.9s var(--ease-out), opacity 0.6s, background-color 0.6s, border-color 0.6s;
}
/* dock-in: added by dock.js introDock() once the poster reveal is done (or the
   guest scrolls). Reduced motion / the static fallback: shown once the gate is gone. */
.js.dock-in .dock, .js.reduced-motion.gate-done .dock, .js .dock:focus-within { transform: none; opacity: 1; }
/* Reduced motion: the dock fades, it never slides. */
.reduced-motion .dock { transition-property: opacity, background-color, border-color; }
/* Slides away while a primary action (submit, pass actions) sits in its band. */
html.js.dock-avoid .dock { transform: translateY(calc(100% + 24px)); opacity: 0; }
/* Reduced motion: it fades out where it stands and lets taps through to the action
   beneath (this outranks the .reduced-motion.gate-done rule above). */
html.js.reduced-motion.dock-avoid .dock { transform: none; opacity: 0; pointer-events: none; }
html.js.dock-avoid .dock:focus-within { transform: none; opacity: 1; pointer-events: auto; }
/* Maroon glass dock over the poster stage and the finale */
.is-dusk .dock {
  background: rgba(47, 18, 18, 0.66);
  border-color: rgba(227, 191, 104, 0.45);
  box-shadow: 0 14px 34px -12px rgba(0, 0, 0, 0.55), inset 0 1px 0 rgba(255, 240, 210, 0.08);
}
.is-dusk .dock__btn { color: var(--cream-100); }
.is-dusk .dock__btn .icon { color: var(--gold-400); }
.is-dusk .bars span { background: var(--gold-400); }
.is-dusk .dock__btn--primary .icon { color: #fffdf8; }
.dock__btn {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  width: clamp(54px, 15.5vw, 68px); height: 54px;
  padding: 0;
  border: 0; border-radius: 999px;
  background: transparent;
  color: var(--brown-700);
  text-decoration: none;
  transition: background-color 0.3s, color 0.3s, scale 0.3s var(--ease-out);
}
.dock__btn .icon { width: 21px; height: 21px; color: var(--gold-600); }
.dock__label { font-size: 0.66rem; font-weight: 500; letter-spacing: 0.06em; line-height: 1; }
.motion .dock__btn:active { scale: 0.94; }
.reduced-motion .dock__btn, .reduced-motion .dock__btn:focus-visible { transition-property: background-color, color; }
@media (hover: hover) { .dock__btn:hover { background: rgba(198, 154, 67, 0.12); } }
.dock__btn--primary {
  color: #fffdf8;
  background: var(--btn-gold);
  box-shadow: 0 8px 18px -8px rgba(138, 95, 31, 0.7), inset 0 1px 0 rgba(255, 245, 214, 0.45);
}
.dock__btn--primary .icon { color: #fffdf8; }
.dock__btn--primary .dock__label { text-shadow: 0 1px 1px rgba(70, 40, 8, 0.4); }
@media (hover: hover) { .dock__btn--primary:hover { background: var(--btn-gold); filter: brightness(1.06); } }
.dock__btn:focus-visible { outline-offset: 1px; border-radius: 999px; }

.bars { display: flex; align-items: flex-end; gap: 2.5px; height: 18px; margin-bottom: 2px; }
.bars span {
  width: 2.5px; height: 100%; border-radius: 2px;
  background: var(--gold-600);
  transform-origin: 50% 100%;
  transform: scaleY(0.3);
}
.dock__music[aria-pressed="true"] .bars span { animation: bars 1s ease-in-out infinite; }
.dock__music[aria-pressed="true"] .bars span:nth-child(2) { animation-delay: -0.3s; animation-duration: 0.8s; }
.dock__music[aria-pressed="true"] .bars span:nth-child(3) { animation-delay: -0.6s; animation-duration: 1.2s; }
.dock__music[aria-pressed="true"] .bars span:nth-child(4) { animation-delay: -0.15s; animation-duration: 0.9s; }
@keyframes bars { 0%, 100% { transform: scaleY(0.3); } 50% { transform: scaleY(1); } }

.sheet {
  margin: 0; padding: 0; border: 0;
  width: 100%; height: 100%; max-width: none; max-height: none;
  background: transparent;
  color: var(--ink);
  overflow: hidden;
}
.sheet[open] { display: grid; place-items: end center; }
.sheet::backdrop { background: rgba(46, 26, 16, 0.38); }
.sheet.is-closing::backdrop { background: rgba(46, 26, 16, 0); }
/* The scrim fades in with the panel and out with it (motion only). */
.motion .sheet::backdrop { transition: background-color 0.4s var(--ease-out); }
.motion .sheet.is-closing::backdrop { transition-duration: 0.32s; }
@starting-style { .motion .sheet[open]::backdrop { background: rgba(46, 26, 16, 0); } }
.sheet__panel {
  position: relative;
  width: min(100%, 460px);
  max-height: 88vh;
  overflow: auto;
  padding: 14px 24px calc(26px + env(safe-area-inset-bottom, 0px));
  display: grid; gap: 10px;
  background: linear-gradient(180deg, var(--cream-50), var(--cream-100));
  border-radius: 26px 26px 0 0;
  border: 1px solid rgba(198, 154, 67, 0.4);
  border-bottom: 0;
  box-shadow: 0 -20px 50px -20px rgba(46, 26, 16, 0.4);
}
@media (min-width: 640px) {
  .sheet[open] { place-items: center; }
  .sheet__panel { border-radius: 26px; border-bottom: 1px solid rgba(198, 154, 67, 0.4); padding-bottom: 28px; }
}
.sheet__grip { justify-self: center; width: 40px; height: 4px; border-radius: 4px; background: var(--beige-400); margin-bottom: 8px; }
.sheet__title { font-family: var(--font-display); font-weight: 500; font-size: 1.9rem; line-height: 1.1; color: var(--brown-800); padding-right: 40px; }
.sheet__strong { font-weight: 500; color: var(--brown-800); }
.sheet__text { color: var(--ink-soft); }
.sheet__actions { display: grid; gap: 10px; margin-top: 12px; }
.sheet__close {
  position: absolute; right: 14px; top: 16px;
  width: 44px; height: 44px; border-radius: 50%;
  display: grid; place-items: center;
  border: 1px solid var(--line); background: var(--cream-50); color: var(--brown-700);
}
.sheet__close .icon { width: 18px; height: 18px; }

.toast {
  position: fixed; z-index: 85; left: 0; right: 0; margin: 0 auto;
  bottom: calc(var(--dock-space) + 12px);
  width: max-content; max-width: calc(100% - 32px);
  padding: 11px 18px;
  border-radius: 999px;
  background: var(--brown-800); color: var(--cream-100);
  font-size: 0.92rem; font-weight: 500;
  box-shadow: var(--shadow-lift);
  opacity: 0; transform: translateY(12px);
  transition: opacity 0.35s, transform 0.45s var(--ease-out);
  pointer-events: none;
}
.toast:empty { display: none; }
.toast.is-visible { opacity: 1; transform: none; }
/* Inside an open sheet (dock.js moves it there): at the top, clear of the panel. */
dialog .toast { position: absolute; top: calc(16px + env(safe-area-inset-top, 0px)); bottom: auto; transform: translateY(-12px); }
dialog .toast.is-visible { transform: none; }
.reduced-motion .toast { transition-property: opacity; transform: none; }
/* Copy address: the icon ticks once the address is on the clipboard. */
.btn.is-done .icon { color: var(--success); }

/* --------------------------------------------------------------------------
   Micro-interactions — one vocabulary for everything you can touch:
   lift on hover, a light sweep on buttons, a soft press, an easing focus ring.
   They use the individual translate/scale/rotate properties, so they never fight
   the GSAP entrances (which own `transform`). Movement only in cinematic mode;
   reduced motion keeps the colour changes.
   -------------------------------------------------------------------------- */
:focus-visible { transition: outline-offset 0.3s var(--ease-out); }
.btn { isolation: isolate; overflow: hidden; }
.btn::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  border-radius: inherit;
  background: linear-gradient(105deg, rgba(255, 250, 235, 0) 30%, rgba(255, 250, 235, 0.38) 50%, rgba(255, 250, 235, 0) 70%);
  transform: translateX(-130%);
  pointer-events: none;
}
.btn--line::after, .btn--ghost::after { background: linear-gradient(105deg, rgba(227, 191, 104, 0) 30%, rgba(227, 191, 104, 0.22) 50%, rgba(227, 191, 104, 0) 70%); }
.btn--line-light::after { background: linear-gradient(105deg, rgba(241, 214, 140, 0) 30%, rgba(241, 214, 140, 0.2) 50%, rgba(241, 214, 140, 0) 70%); }
@media (hover: hover) {
  .motion .btn:hover { translate: 0 -2px; }
  .motion .btn--line:hover, .motion .btn--ghost:hover { box-shadow: 0 12px 26px -16px rgba(138, 95, 31, 0.55); }
  .motion .btn:hover::after { transform: translateX(130%); transition: transform 0.95s var(--ease-out); }
  .motion .btn:hover .icon { transform: translateY(-1px) scale(1.06); }
}
.btn .icon { transition: transform 0.45s var(--ease-out); }
.motion .btn:active { translate: 0 0; scale: 0.975; transition-duration: 0.12s; }
.btn:focus-visible { outline-offset: 4px; }

.link { transition: color 0.3s, text-underline-offset 0.35s var(--ease-out), text-decoration-color 0.3s; text-decoration-color: rgba(138, 95, 31, 0.5); }
@media (hover: hover) { .link:hover { color: var(--brown-700); text-decoration-color: currentColor; text-underline-offset: 0.36em; } }
.link { transition-property: color, text-underline-offset, text-decoration-color, scale; }
.motion .link:active { scale: 0.97; }

/* Detail cards lift and their line icons brighten. */
.card { transition: translate 0.6s var(--ease-out), box-shadow 0.6s var(--ease-out), border-color 0.6s; }
.card__icon { transition: transform 0.6s var(--ease-out), stroke 0.4s; }
@media (hover: hover) {
  .card:hover { border-color: rgba(198, 154, 67, 0.6); }
  .motion .card:hover { translate: 0 -4px; box-shadow: var(--shadow-lift); }
  .motion .card:hover .card__icon { transform: translateY(-2px) scale(1.06); stroke: var(--gold-700); }
}

/* Countdown numerals catch the light when hovered. */
.countdown__num { transition: color 0.4s; }
@media (hover: hover) { .countdown__unit:hover .countdown__num { color: var(--gold-700); } }

/* Slot cards: lift, press, and the check mark springs in (below). */
@media (hover: hover) { .motion .slot:not(.is-full):hover .slot__body { translate: 0 -2px; box-shadow: 0 12px 24px -16px rgba(138, 95, 31, 0.5); } }
.motion .slot:not(.is-full):active .slot__body { scale: 0.985; transition-duration: 0.12s; }
.motion .slot__check::after { transition: transform 0.45s cubic-bezier(0.34, 1.56, 0.64, 1); }
html:not(.motion) .slot__check::after { transition: none; }

/* Fields: the label turns gold while you type; errors ease in. */
.field__label { transition: color 0.3s; }
.field:focus-within > .field__label, .field:focus-within > legend.field__label { color: var(--gold-700); }
.motion .select::after { transition: transform 0.35s var(--ease-out); }
.select:focus-within::after { transform: translateY(2px) rotate(45deg); }
.motion .field__error.is-visible { animation: error-in 0.45s var(--ease-out) both; }
@keyframes error-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
.motion .rsvp__status.is-error { animation: error-in 0.45s var(--ease-out) both; }

/* Wishes: cards lift gently. */
@media (hover: hover) {
  .wish:hover { border-color: rgba(198, 154, 67, 0.55); }
  .motion .wish:not(.pre):hover { translate: 0 -3px; box-shadow: 0 16px 32px -18px rgba(74, 44, 29, 0.4); }
}

/* Dock: icons rise on hover, everything presses softly. */
.dock__btn .icon, .dock__btn .bars { transition: transform 0.45s var(--ease-out); }
@media (hover: hover) { .motion .dock__btn:hover .icon, .motion .dock__btn:hover .bars { transform: translateY(-2px); } }

/* Sheets: the close button turns, options are .btn. */
.sheet__close { transition: rotate 0.45s var(--ease-out), scale 0.3s var(--ease-out), background-color 0.3s, border-color 0.3s; }
@media (hover: hover) { .sheet__close:hover { background: var(--cream-100); border-color: var(--gold-500); } .motion .sheet__close:hover { rotate: 90deg; } }
.motion .sheet__close:active { rotate: 90deg; scale: 0.92; }

/* --------------------------------------------------------------------------
   Reduced motion & no-JS: static, complete, readable
   -------------------------------------------------------------------------- */
.reduced-motion .medal__halo, .reduced-motion .medal__cta, .reduced-motion .poster__cue-line::after { animation: none; }
html:not(.motion) .clinic .storefront__door { opacity: 0.35; }
html:not(.motion) .clinic__captions .caption { opacity: 1; }
html:not(.motion) .clinic__captions { gap: 14px; }
html:not(.motion) .clinic { padding-block: clamp(40px, 8vw, 90px); }
html:not(.motion) .story { padding-block: clamp(56px, 10vw, 100px); }
html:not(.motion) .finale { padding-block: clamp(56px, 10vw, 100px) calc(var(--dock-space) + 30px); }
html:not(.motion) .finale__stage { position: static; }
html:not(.motion) .finale__inner, html:not(.motion) .finale__footer { position: relative; }
/* The tied-back drapes frame every screen of the farewell: each drape is one scene tall
   (the poster's own proportions) and sticks to the screen edges while the message scrolls
   between them, down the whole finale. The end card's closed curtains (z-index 4) then
   rise over them — the curtain falls. No crop mid-scene, no bare band. Pure CSS: works
   without JS too. */
html:not(.motion) .finale__curtain { bottom: 0; height: auto; }
html:not(.motion) .finale__curtain .curtain__drape { position: sticky; inset: auto; top: 0; width: 100%; height: var(--sh); }
/* The closed curtains are the page's last full screen, glitter above them and the
   signature at their foot (over the velvet, clear of the dock). */
html:not(.motion) .finale, html:not(.motion) .finale__stage { padding-bottom: 0; }
html:not(.motion) .finale__fall { height: auto; min-height: 100vh; min-height: 100svh; }
html:not(.motion) .endcard { top: max(64px, calc(var(--sh) * 0.1)); bottom: calc(var(--dock-space) + 40px); padding-block: 0; }
html:not(.motion) .finale__footer {
  position: absolute; left: 0; right: 0; z-index: 6;
  bottom: calc(var(--dock-space) + 6px);
  margin: 0; padding: 0 var(--gutter);
}
html:not(.js) .endcard { bottom: 60px; }
html:not(.js) .finale__footer { bottom: 20px; }
html:not(.js) .rsvp__form, html:not(.js) .rsvp__saved, html:not(.js) [data-countdown] > :not(.sr-only) { display: none; }
html:not(.motion) .poster__content { will-change: auto; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { scroll-behavior: auto !important; }
  .medal__halo, .medal__cta, .poster__cue-line::after, .dock__music[aria-pressed="true"] .bars span { animation: none !important; }
}

/* Small phones: keep everything inside 320px */
@media (max-width: 360px) {
  .countdown__unit { min-width: 52px; }
  .countdown__grid { gap: 6px; }
  .btn { padding-inline: 18px; }
  .gate__clinic { letter-spacing: 0.24em; }
  .dock__label { font-size: 0.62rem; }
}

.wish__quote { margin: 0; }

/* Short landscape screens (phones held sideways): side-by-side compositions */
@media (max-height: 520px) and (orientation: landscape) {
  .story__stage { gap: 10px; padding-top: 24px; }
  .story__year { font-size: clamp(4rem, 24svh, 7rem); }
  .beat__text { font-size: 1.2rem; }
  .motion .clinic__stage {
    flex-direction: row; gap: 28px;
    padding: 14px var(--gutter) calc(var(--dock-space) + 4px);
  }
  .motion .clinic__frame { width: min(56vw, calc((100svh - var(--dock-space) - 24px) * 1.0944)); }
  .clinic__captions { width: min(38vw, 22rem); }
  .finale__inner { grid-template-columns: auto 1fr; justify-items: stretch; gap: 28px; }
  .finale__art, .motion .finale__art { width: min(46vw, calc((100svh - var(--dock-space) - 36px) * 1.0944)); }
  .finale__copy { justify-items: start; text-align: left; }
  .finale__cta-wrap { justify-content: flex-start; }
  .finale__title { font-size: clamp(1.6rem, 4vw, 2.1rem); }
  .finale__copy { gap: 6px; }
  .finale__logo { width: 52px; margin-bottom: 0; }
  .finale__footer { margin-top: 8px; }
  .motion .finale__stage { padding-top: 16px; --foot-h: 26px; }
  .finale__text { justify-items: start; }
  .finale__message { justify-items: start; text-align: left; gap: 6px; }
  .motion .finale__message { margin-inline: 0; }
  .finale__lede { font-size: clamp(1rem, 2.6vw, 1.2rem); }
  .finale__ornament { display: none; }
  .finale__sep { display: inline; height: auto; }
  .motion .finale__fall { --medal: min(44svh, 200px); }
  .motion .endcard { flex-direction: row; top: 16px; }
}
