/* Samantha & Steven — November 2026
   Tokens and layout per design handoff (design_handoff_wedding_site/README.md). */

@font-face { font-family: "TokyoDreams"; src: url("../assets/TokyoDreams.otf") format("opentype"); font-display: swap; }
@font-face { font-family: "AvenirMedium"; src: url("../assets/AvenirMedium.ttf") format("truetype"); font-display: swap; }
@font-face { font-family: "ESScript"; src: url("../assets/ESScript-ThinScript.ttf") format("truetype"); font-display: swap; }

:root {
  --plum: #553D58;
  --plum-mid: #6E5772;
  --lilac: #9C85A0;
  --lilac-light: #D0BADA;
  --mauve: #CBB8D0;
  --ground: #E6DFEA;
  --sky: #EDE7F0;
  --rule-plum: rgba(230, 223, 234, .38);
}

*, *::before, *::after { box-sizing: border-box; }
html { background: var(--ground); }
body {
  margin: 0;
  background: var(--ground);
  color: var(--plum);
  font-family: "AvenirMedium", "Helvetica Neue", Helvetica, sans-serif;
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3, p, fieldset, figure { margin: 0; font-weight: 400; font-size: inherit; }
fieldset { padding: 0; border: 0; min-width: 0; }
img { max-width: 100%; }
a { color: var(--plum); text-decoration: none; border-bottom: 1px solid rgba(85, 61, 88, .35); }
a:hover { color: var(--lilac); border-bottom-color: var(--lilac); }
.scene--plum a { color: var(--ground); border-bottom-color: rgba(230, 223, 234, .5); }
.scene--plum a:hover { color: var(--lilac-light); border-bottom-color: var(--lilac-light); }
::selection { background: var(--lilac-light); color: var(--plum); }

[hidden] { display: none !important; }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
body.locked { overflow: hidden; }

/* ============ Password gate ============ */
.gate {
  position: fixed; inset: 0; z-index: 100;
  background: var(--plum); color: var(--ground);
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  transition: opacity 700ms ease;
}
.gate.gate-out { opacity: 0; pointer-events: none; }
.gate-panel { display: flex; flex-direction: column; align-items: center; gap: 18px; text-align: center; width: 100%; max-width: 340px; }
.gate-monogram { width: clamp(58px, 6vw, 92px); height: auto; opacity: .9; }
.gate-word { font-size: 9px; letter-spacing: .3em; text-transform: uppercase; color: var(--ground); }
.gate-script { font-family: "ESScript", cursive; font-size: clamp(30px, 3vw, 46px); color: var(--lilac-light); line-height: 1; }
.gate-line { font-size: 11px; letter-spacing: .16em; text-transform: uppercase; color: var(--mauve); line-height: 1.9; white-space: nowrap; }
@media (max-width: 420px) { .gate-line { font-size: 9px; } }
.gate-input {
  width: 100%; background: transparent; border: 1px solid var(--rule-plum);
  color: var(--ground); padding: 12px 14px; font-family: inherit;
  font-size: 12px; letter-spacing: .12em; text-align: center;
}
.gate-input:focus { outline: none; border-color: var(--lilac-light); }
.gate-btn {
  width: 100%; background: var(--ground); color: var(--plum); border: 0; cursor: pointer;
  padding: 13px 14px; font-family: inherit; font-size: 10px; letter-spacing: .3em; text-transform: uppercase;
}
.gate-error { font-size: 11px; letter-spacing: .08em; color: var(--mauve); }

/* ============ Background layers ============
   Absolute inside the sticky camera in camera mode (mirrors the prototype's
   structure); fixed to the viewport in flow mode. */
.bg-sky { position: fixed; inset: 0; background: var(--sky); z-index: 0; }
.bg-stripes {
  position: fixed; top: -140vh; bottom: -140vh; left: -140vw; right: -140vw;
  background: url("../assets/striped-bg.jpg") left top / auto 100% repeat-x;
  opacity: .45; will-change: transform; z-index: 0;
}
.bg-skyline {
  position: fixed; bottom: 0; right: -2vw; z-index: 0;
  display: flex; align-items: flex-end; justify-content: flex-end;
  opacity: .14; pointer-events: none;
}
.bg-skyline img { height: 94vh; max-height: 94vh; width: auto; max-width: none; }
body.cam .bg-sky, body.cam .bg-stripes, body.cam .bg-skyline { position: absolute; }

/* ============ Chrome overlays ============ */
.topbar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 60;
  display: flex; align-items: center; justify-content: space-between;
  padding: 26px 34px; pointer-events: none;
  mix-blend-mode: difference;
}
.topbar-mark { display: flex; align-items: center; gap: 13px; opacity: 0; transition: opacity 700ms ease; }
.topbar-mark.show { opacity: 1; }
.topbar-mark img { height: 24px; width: auto; filter: brightness(0) invert(1); opacity: .62; }
.topbar-word { font-size: 9px; letter-spacing: .3em; text-transform: uppercase; color: #E6DFEA; }

/* Section sidebar (desktop) — collapsed to tick marks; hovering the rail
   (or keyboard focus) reveals the section names. Blends like the top bar
   so it reads on every ground. */
.sidenav {
  position: fixed; right: 30px; top: 50%; transform: translateY(-50%); z-index: 60;
  display: flex; flex-direction: column; align-items: flex-end; gap: 13px;
  padding: 14px 0 14px 40px;
  mix-blend-mode: difference;
}
.sidenav button {
  appearance: none; border: 0; padding: 0; background: none; cursor: pointer;
  display: flex; align-items: center; justify-content: flex-end; gap: 10px;
  font-family: inherit; font-size: 9px; letter-spacing: .3em; text-transform: uppercase;
  color: rgba(230, 223, 234, .45); text-align: right;
  transition: color 400ms ease;
}
.sidenav button:hover { color: rgba(230, 223, 234, .85); }
.sidenav button[aria-current="true"] { color: #E6DFEA; }
.sidenav .tick { display: block; width: 16px; height: 1px; background: currentColor; transition: width 400ms ease; }
.sidenav button[aria-current="true"] .tick { width: 28px; }
.sidenav .lbl {
  opacity: 0; transform: translateX(8px);
  transition: opacity 350ms ease, transform 350ms cubic-bezier(.22, 1, .36, 1);
  pointer-events: none; white-space: nowrap;
}
.sidenav:hover .lbl, .sidenav:focus-within .lbl { opacity: 1; transform: translateX(0); }

/* Menu (mobile) */
.menu-btn {
  position: fixed; top: 20px; right: 22px; z-index: 62;
  appearance: none; border: 0; background: none; cursor: pointer; padding: 6px 0 6px 12px;
  font-family: inherit; font-size: 9px; letter-spacing: .3em; text-transform: uppercase;
  color: #E6DFEA; mix-blend-mode: difference;
}
.menu {
  position: fixed; inset: 0; z-index: 90;
  background: var(--plum); color: var(--ground);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 26px;
  padding: 24px;
}
.menu-close {
  position: absolute; top: 20px; right: 22px;
  appearance: none; border: 0; background: none; cursor: pointer; padding: 6px 0 6px 12px;
  font-family: inherit; font-size: 9px; letter-spacing: .3em; text-transform: uppercase;
  color: var(--lilac-light);
}
.menu-monogram { width: 54px; height: auto; opacity: .9; }
.menu-list { display: flex; flex-direction: column; align-items: center; gap: 16px; max-height: 70vh; overflow-y: auto; }
.menu-list button {
  appearance: none; border: 0; background: none; cursor: pointer; padding: 2px 4px;
  font-family: inherit; font-size: 12px; letter-spacing: .3em; text-transform: uppercase;
  color: var(--mauve);
}
.menu-list button[aria-current="true"] { color: var(--ground); }

.progress { position: fixed; bottom: 0; left: 0; right: 0; height: 2px; background: rgba(85, 61, 88, .14); z-index: 60; }
.progress-fill { height: 100%; width: 0%; background: var(--plum); }
body.cam .topbar, body.cam .sidenav, body.cam .menu-btn, body.cam .menu, body.cam .progress { position: absolute; }

/* ============ Stage / camera / scenes ============ */
.stage { position: relative; z-index: 1; width: 100%; }

/* Default (flow) layout: normal vertical document. Camera mode is opted into via body.cam. */
.camera { position: relative; }
.track { position: relative; }
.scene {
  position: relative; width: 100%; min-height: 100svh; overflow: hidden;
  display: flex; flex-direction: column;
}
.scene--plum { background: var(--plum); color: var(--ground); }
.scene--plum .eyebrow { color: var(--lilac-light); }

body.cam { overflow: hidden; height: 100vh; } /* camera mode is gesture-driven — no document scroll */
body.cam .camera { position: sticky; top: 0; left: 0; width: 100%; height: 100vh; overflow: hidden; }
body.cam .track { position: absolute; top: 0; left: 0; height: 100%; will-change: transform; }
/* Each scene on its own compositor layer so content rasterizes up front, not
   mid-glide (the first glide otherwise stutters while the invitation paints).
   renderAt hides scenes beyond distance 1.6, so only ~3 layers live at once. */
body.cam .scene { will-change: transform; }
body.cam .scene { position: absolute; width: 100vw; height: 100vh; min-height: 0; }

/* ============ Reveals ============ */
html.js .rv {
  opacity: 0;
  transform: translateY(var(--rv-y, 24px));
  transition: opacity var(--rv-d, 1200ms) ease, transform var(--rv-d, 1200ms) var(--rv-e, cubic-bezier(.22, 1, .36, 1));
}
html.js .rv.on { opacity: 1; transform: translateY(0); }
html.js .rv-draw {
  clip-path: inset(0 0 100% 0);
  transition: clip-path var(--rv-d, 2400ms) var(--rv-e, cubic-bezier(.22, 1, .36, 1));
}
html.js .rv-draw.on { clip-path: inset(0 0 0 0); }
html.js .rv-draw-up {
  clip-path: inset(100% 0 0 0);
  transition: clip-path var(--rv-d, 2600ms) var(--rv-e, cubic-bezier(.33, 1, .4, 1));
}
html.js .rv-draw-up.on { clip-path: inset(0 0 0 0); }

/* ============ Shared bits ============ */
.eyebrow { font-size: 9px; letter-spacing: .34em; text-transform: uppercase; color: var(--lilac); }
.tbc { color: var(--lilac); }
.scene--plum .tbc { color: var(--lilac-light); }
.card-light { display: flex; flex-direction: column; border-top: 1px solid var(--lilac-light); }

.strip {
  flex: 1 1 auto; min-height: 0;
  display: flex; align-items: stretch; gap: 20px;
  overflow-x: auto; overflow-y: hidden;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scrollbar-color: rgba(230, 223, 234, .4) transparent;
}

/* ============ Scene 1 — Home ============ */
.s1 { align-items: center; justify-content: center; gap: 2.4vh; padding: 4vh 8vw 12vh; }
.s1-monogram { width: clamp(62px, 7vw, 120px); height: auto; max-height: 13vh; object-fit: contain; }
.s1-names { width: clamp(240px, 36vw, 560px); height: auto; max-height: 34vh; object-fit: contain; }
.s1-dates { display: flex; flex-direction: column; align-items: center; gap: 12px; }
.s1-date { font-size: clamp(10px, .95vw, 13px); letter-spacing: .34em; text-transform: uppercase; }
.s1-city { font-family: "ESScript", cursive; font-size: clamp(28px, 2.6vw, 44px); color: var(--lilac); line-height: 1; }
.s1-scroll { position: absolute; bottom: 4vh; display: flex; flex-direction: column; align-items: center; gap: 12px; }
.s1-scroll i { display: block; width: 1px; height: 44px; background: linear-gradient(180deg, #9C85A0, rgba(156, 133, 160, 0)); animation: cue 2.6s ease-in-out infinite; }
@keyframes cue { 0%, 100% { opacity: .35; transform: scaleY(.7); transform-origin: top; } 50% { opacity: 1; transform: scaleY(1); } }

/* ============ Scene 2 — Invitation ============ */
.s2 { align-items: center; justify-content: center; padding: clamp(24px, 7vh, 76px) 8vw; }
.s2-card { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 18px; max-width: 640px; }
/* The invitation, recreated as live text matching the printed invite's
   geometry. All positions/sizes are in cqw (1% of card width) converted from
   pixel measurements of the 1429×2000 source artwork, so the layout scales
   with the card at the artwork's exact proportions. */
.invite {
  position: relative;
  width: min(88vw, calc(min(80vh, 900px) * 0.7145));
  aspect-ratio: 1429 / 2000;
  container-type: inline-size;
  text-align: center;
}
.invite > * { position: absolute; left: 0; right: 0; margin: 0; }
.inv-bh { left: auto; right: 6.2cqw; top: 5cqw; font-size: 2.6cqw; letter-spacing: .08em; color: #908692; }
.inv-monogram { left: 50%; right: auto; transform: translateX(-50%); top: 17.5cqw; height: 16.9cqw; width: auto; }
.inv-parents, .inv-when, .inv-addr, .inv-foot {
  font-size: 2.33cqw; line-height: 4.01cqw; letter-spacing: .112em;
  text-transform: uppercase; color: #8d8090;
}
.inv-parents { top: 40.58cqw; }
.inv-name { font-family: "ESScript", cursive; font-size: 8cqw; line-height: 1; color: #452F47; }
.inv-name-1 { top: 62.91cqw; }
.inv-and { top: 72.6cqw; font-family: "ESScript", cursive; font-size: 3.65cqw; line-height: 1; color: #452F47; }
.inv-name-2 { top: 76.77cqw; }
.inv-when { top: 93.24cqw; }
.inv-venue { top: 110.09cqw; font-family: "TokyoDreams", "Didot", serif; font-size: 4cqw; line-height: 1; letter-spacing: .064em; text-transform: uppercase; color: #423642; font-weight: 400; }
.inv-addr { top: 115.24cqw; color: #8a828c; }
.inv-foot { top: 131.11cqw; display: flex; justify-content: space-between; padding: 0 5.9cqw; font-size: 1.84cqw; color: #908692; }
.s2-rsvp { border-bottom: none; font-family: "ESScript", cursive; font-size: clamp(26px, 2.4vw, 38px); color: var(--plum); line-height: 1; }

/* ============ Scene 4 — The wedding ============ */
.s4 { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, .85fr); grid-template-rows: minmax(0, 1fr); align-items: center; }
.s4-photo { position: relative; grid-column: 2; grid-row: 1; height: 100%; overflow: hidden; }
.s4-photo img { position: absolute; top: -6%; left: 0; width: 112%; height: 112%; max-width: none; object-fit: cover; opacity: .95; }
.s4-copy { position: relative; grid-column: 1; grid-row: 1; display: flex; flex-direction: column; gap: 16px; padding: 0 6vw 0 9vw; }
.s4-script { font-family: "ESScript", cursive; font-size: clamp(28px, 2.6vw, 42px); color: var(--lilac); line-height: 1; }
.s4-title { font-family: "TokyoDreams", "Didot", serif; font-size: clamp(28px, 3.2vw, 52px); letter-spacing: .06em; line-height: 1; }
.s4-meta { font-size: 11px; letter-spacing: .16em; text-transform: uppercase; line-height: 1.9; }
.s4-body { font-size: 14px; line-height: 2; color: var(--plum-mid); max-width: 46ch; }

/* ============ Scene 5 — The morning after ============ */
/* Sibling of the wedding scene, so it borrows that scene's type scale; the rule above the
   copy is the shared .card-light border-top. */
.s5 { justify-content: center; padding: clamp(30px, 10vh, 96px) 9vw; }
.s5-copy { display: flex; flex-direction: column; gap: 14px; max-width: 700px; }
.s5-card { gap: 16px; padding-top: 22px; }
.s5-script { font-family: "ESScript", cursive; font-size: clamp(28px, 2.6vw, 42px); color: var(--lilac); line-height: 1; }
.s5-title { font-family: "TokyoDreams", "Didot", serif; font-size: clamp(28px, 3.2vw, 52px); letter-spacing: .06em; line-height: 1.1; }
/* Qualifier under the title — same metrics as the meta block but lilac, matching the
   .rsvp-note treatment the site already uses for "read this caveat" lines. */
.s5-note { font-size: 11px; letter-spacing: .16em; text-transform: uppercase; line-height: 1.9; color: var(--lilac); }
.s5-meta { font-size: 11px; letter-spacing: .16em; text-transform: uppercase; line-height: 1.9; }
.s5-body { font-size: 14px; line-height: 2; color: var(--plum-mid); }

/* ============ Scene 6 — Where to stay ============ */
.s6 { justify-content: center; gap: 2.4vh; padding: clamp(26px, 8vh, 76px) 9vw; }
.s6-title { font-family: "TokyoDreams", "Didot", serif; font-size: clamp(22px, 2.4vw, 38px); letter-spacing: .05em; line-height: 1.1; }
.s6-head { display: flex; align-items: baseline; justify-content: space-between; gap: 3vw; flex-wrap: wrap; position: relative; }
.s6-contact { font-size: 11px; letter-spacing: .1em; color: var(--mauve); }
.s6-strip { margin-right: -9vw; padding-right: 9vw; padding-bottom: 12px; position: relative; }
/* Cards never scroll: in cam mode the global wheel handler preventDefaults before native
   scroll can run, so a card scroller is unusable by wheel and just eats the page gesture.
   Content is made to FIT instead — see the max-height ladder below. */
.hotel {
  flex: 0 0 clamp(230px, 26vw, 330px); scroll-snap-align: start;
  display: flex; flex-direction: column; gap: 10px;
  border: 1px solid var(--rule-plum); padding: 16px;
}
.hotel--featured { border-color: rgba(230, 223, 234, .6); }
.hotel-photo { border: 1px solid rgba(230, 223, 234, .45); padding: 7px; }
.hotel-photo img { display: block; width: 100%; aspect-ratio: 3 / 2; object-fit: cover; filter: grayscale(1); }
.hotel-name a { color: inherit; border-bottom: none; }
.hotel-name a:hover { color: var(--lilac-light); }
.hotel-name { font-family: "TokyoDreams", "Didot", serif; font-size: clamp(17px, 1.6vw, 24px); letter-spacing: .05em; line-height: 1.2; }
.hotel-addr { font-size: 12px; line-height: 1.75; color: var(--mauve); }
.hotel-note { font-size: 12px; line-height: 1.75; color: var(--mauve); }
.hotel-hl { font-size: 12px; line-height: 1.75; color: var(--ground); }
.hotel-book { align-self: flex-start; font-size: 10px; letter-spacing: .26em; text-transform: uppercase; border: 1px solid rgba(230, 223, 234, .5); border-bottom: 1px solid rgba(230, 223, 234, .5); padding: 8px 12px; margin-top: 2px; }
.hotel-book:hover { border-color: var(--lilac-light); }

/* Short-viewport ladder. The card is fixed-width, so its content height is essentially
   constant while the available height tracks the viewport — hence max-height, not width.
   Each step buys back enough px to keep every card overflow-free; see DEVLOG for the
   measured budget. */
@media (max-height: 960px) {
  .s6 { padding: clamp(22px, 5vh, 48px) 9vw; gap: 2vh; }
  .hotel { gap: 9px; padding: 15px; }
  .hotel-photo img { aspect-ratio: 16 / 9; }
  .hotel-addr, .hotel-note, .hotel-hl { line-height: 1.7; }
}
@media (max-height: 820px) {
  .s6 { padding: clamp(18px, 4.6vh, 44px) 9vw; gap: 1.6vh; }
  .hotel { gap: 8px; padding: 14px; }
  .hotel-photo { padding: 5px; }
  .hotel-photo img { aspect-ratio: 2 / 1; }
  .hotel-name { font-size: clamp(15px, 1.4vw, 20px); }
  .hotel-addr, .hotel-note, .hotel-hl { font-size: 11px; line-height: 1.7; }
  .hotel-book { padding: 7px 10px; }
}

/* Below ~900px the card hits its 230px floor, so the copy wraps into more lines and grows
   taller again — trim the leading once more for that narrow-carousel band. */
@media (max-width: 900px) {
  .hotel { gap: 8px; }
  .hotel-addr, .hotel-note, .hotel-hl { line-height: 1.6; }
}

/* ============ Scene 7 — Travel and transport ============ */
.s7 { justify-content: center; gap: 3.4vh; padding: clamp(30px, 10vh, 96px) 9vw; }
.s7-head { display: flex; flex-direction: column; gap: 10px; }
.s7-script { font-family: "ESScript", cursive; font-size: clamp(30px, 3vw, 50px); color: var(--plum); line-height: 1; }
.s7-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 4vh 4vw; max-width: 1060px; }
.s7-card { gap: 12px; padding-top: 18px; }
.s7-title { font-size: 11px; letter-spacing: .18em; text-transform: uppercase; line-height: 1.7; }
.s7-body { font-size: 13px; line-height: 1.95; color: var(--plum-mid); }

/* ============ Scene 8 — What to wear ============ */
.s8 { justify-content: center; gap: 3vh; padding: clamp(30px, 10vh, 96px) 9vw; }
.s8-block { display: flex; flex-direction: column; gap: 22px; max-width: 58ch; }
.s8-body { font-size: 14px; line-height: 2; color: var(--plum-mid); }
.s8-title { font-family: "TokyoDreams", "Didot", serif; font-size: clamp(26px, 3.4vw, 56px); letter-spacing: .07em; line-height: 1.05; white-space: nowrap; }
.s8-note { font-size: 13px; line-height: 1.95; }
/* Attire images arrive with transparent backgrounds — no frame, no fill. */
.s8-boards { display: grid; grid-template-columns: 1fr 1fr; gap: 0; width: 100%; max-width: 900px; align-items: center; }
.s8-board { display: block; width: 100%; height: auto; }
/* The tux artwork carries wide transparent side margins — pull it toward the gowns. */
.s8-board:last-child { margin-left: -8%; }

/* ============ Scene 9 — Eat and drink ============ */
.s9 { justify-content: center; gap: 3.4vh; padding: clamp(30px, 10vh, 96px) 9vw; }
.s9-head { flex: 0 0 auto; display: flex; align-items: flex-end; justify-content: space-between; gap: 4vw; position: relative; }
.s9-copy { display: flex; flex-direction: column; gap: 12px; max-width: 42ch; }
.s9-title { font-family: "TokyoDreams", "Didot", serif; font-size: clamp(26px, 3.2vw, 50px); letter-spacing: .05em; line-height: 1.1; }
.s9-script { font-family: "ESScript", cursive; font-size: clamp(24px, 2.2vw, 36px); color: var(--lilac-light); line-height: 1; }
/* Full-height skyline anchored bottom-right on every plum scene, mirroring the light
   scenes' .bg-skyline (plum scenes cover the fixed background one, so each carries
   its own inverted copy). */
.plum-skyline {
  position: absolute; bottom: 0; right: -2vw;
  height: 94vh; max-height: 94vh; width: auto; max-width: none;
  filter: brightness(0) invert(1); opacity: .14; pointer-events: none;
}
.s9-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 4vh 5vw; max-width: 940px; position: relative; }
.eat-col { display: flex; flex-direction: column; gap: 14px; border-top: 1px solid var(--rule-plum); padding-top: 18px; }
.eat-script { font-family: "ESScript", cursive; font-size: clamp(26px, 2.4vw, 38px); color: var(--lilac-light); line-height: 1; }
.eat-list { font-size: 14px; line-height: 2.1; color: var(--mauve); }

/* ============ Scene 10 — Experiences and tours ============ */
.s10 { justify-content: center; gap: 3.4vh; padding: clamp(30px, 10vh, 96px) 9vw; }
.s10-head { display: flex; flex-direction: column; gap: 10px; }
.s10-title { font-family: "TokyoDreams", "Didot", serif; font-size: clamp(26px, 3.2vw, 50px); letter-spacing: .05em; line-height: 1.1; }
.s10-note { font-size: 13px; line-height: 1.95; max-width: 60ch; }
.s10-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 4vh 5vw; max-width: 900px; }
.s10-card { gap: 14px; padding-top: 18px; }
.s10-script { font-family: "ESScript", cursive; font-size: clamp(26px, 2.4vw, 38px); color: var(--lilac); line-height: 1; }
.s10-list { font-size: 13px; line-height: 2.15; color: var(--plum-mid); }

/* ============ Scene 11 — Registry ============ */
.s11 { align-items: center; justify-content: center; gap: 24px; padding: clamp(30px, 10vh, 96px) 9vw; text-align: center; }
.s11-monogram { width: clamp(58px, 5.5vw, 90px); height: auto; opacity: .85; }
.s11-block { display: flex; flex-direction: column; align-items: center; gap: 20px; }
.s11-title { font-family: "TokyoDreams", "Didot", serif; font-size: clamp(22px, 2.4vw, 38px); letter-spacing: .06em; line-height: 1.2; }
.s11-link { font-size: 10px; letter-spacing: .28em; text-transform: uppercase; }
.s11-script { font-family: "ESScript", cursive; font-size: clamp(28px, 2.8vw, 44px); color: var(--lilac); line-height: 1.25; }

/* ============ Scene 12 — FAQ ============ */
.s12 { justify-content: center; gap: 4vh; padding: clamp(30px, 10vh, 96px) 9vw; }
.s12-title { font-family: "TokyoDreams", "Didot", serif; font-size: clamp(22px, 2.4vw, 38px); letter-spacing: .05em; line-height: 1.1; }
.s12-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 4vh 5vw; max-width: 940px; }
.s12-card { display: flex; flex-direction: column; gap: 12px; border-top: 1px solid var(--rule-plum); padding-top: 18px; }
.s12-q { font-family: "TokyoDreams", "Didot", serif; font-size: clamp(15px, 1.4vw, 21px); letter-spacing: .06em; text-transform: uppercase; line-height: 1.5; }
.s12-a { font-size: 13px; line-height: 2.15; color: var(--mauve); }

/* ============ Scene 13 — RSVP ============ */
.s13 { align-items: center; justify-content: center; padding: clamp(24px, 7vh, 72px) 9vw; }
.s13::before {
  content: ""; position: absolute; inset: -6vh -4vw; pointer-events: none;
  background: radial-gradient(58% 55% at 50% 50%,
    var(--sky) 0%, rgba(237, 231, 240, .82) 55%, rgba(237, 231, 240, 0) 82%);
}
.rsvp-panel {
  position: relative;
  display: flex; flex-direction: column; align-items: center; text-align: center; gap: 14px;
  padding: clamp(22px, 4vh, 46px) 5vw;
  width: 100%; max-width: 660px; max-height: 100%; min-height: 0;
  overflow-y: auto;
  scrollbar-width: none;
}
.rsvp-panel::-webkit-scrollbar { display: none; }
/* Clipped content melts out at the edges instead of being cut. The 22px fade
   never exceeds the panel's minimum vertical padding, so nothing visible dims
   when the panel rests at either end. Cam mode only — flow mode doesn't scroll. */
body.cam .rsvp-panel {
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 22px, #000 calc(100% - 22px), transparent 100%);
  mask-image: linear-gradient(180deg, transparent 0, #000 22px, #000 calc(100% - 22px), transparent 100%);
}
.rsvp-title { font-family: "TokyoDreams", "Didot", serif; font-size: clamp(24px, 2.7vw, 42px); letter-spacing: .06em; line-height: 1.2; }
.rsvp-lede { font-size: 13px; line-height: 2; color: var(--plum-mid); }
.rsvp-note { font-size: 11px; letter-spacing: .16em; text-transform: uppercase; color: var(--lilac); }
.rsvp-form { display: flex; flex-direction: column; gap: 14px; width: 100%; max-width: 400px; text-align: left; }
#attending-fields { display: flex; flex-direction: column; gap: 14px; }
.f-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.f-field { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.f-label { font-size: 10px; letter-spacing: .12em; text-transform: uppercase; color: var(--lilac); }
.f-input {
  width: 100%; border: 0; border-bottom: 1px solid var(--lilac-light); background: transparent;
  padding: 8px 2px; font-family: inherit; font-size: 12px; letter-spacing: .04em; color: var(--plum);
  border-radius: 0;
}
.f-input:focus { outline: none; border-bottom-color: var(--plum); }
.f-input:-webkit-autofill { -webkit-box-shadow: 0 0 0 1000px var(--sky) inset; -webkit-text-fill-color: var(--plum); }
select.f-input {
  appearance: none;
  background: transparent url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23553D58'/%3E%3C/svg%3E") right 2px center / 10px 6px no-repeat;
  padding-right: 18px;
}
.f-set { display: flex; flex-direction: column; gap: 8px; border: 0; padding: 10px 0 2px; }
.f-set legend { padding: 0; float: left; margin-bottom: 8px; }
.f-set legend + * { clear: both; }
.fest-sub { margin-top: 6px; }
.opt { display: flex; align-items: center; gap: 9px; font-size: 10px; letter-spacing: .12em; text-transform: uppercase; color: var(--plum-mid); cursor: pointer; }
.opt input { accent-color: var(--plum); margin: 0; }
/* Sub-hint under a checkbox; indented to line up with the option label, not the box. */
.opt-hint { margin: -3px 0 0 22px; font-size: 9px; letter-spacing: .12em; text-transform: uppercase; color: var(--lilac); }
#guests { display: flex; flex-direction: column; gap: 14px; }
.guest-block { display: flex; flex-direction: column; gap: 10px; border-top: 1px solid var(--lilac-light); padding-top: 14px; margin-top: 4px; }
.guest-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.guest-heading { color: var(--plum-mid); }
.guest-remove {
  background: none; border: 0; cursor: pointer; padding: 0; font-family: inherit;
  font-size: 9px; letter-spacing: .18em; text-transform: uppercase; color: var(--lilac);
  border-bottom: 1px solid var(--lilac-light);
}
.guest-remove:hover, .guest-remove:focus-visible { color: var(--plum); border-bottom-color: var(--plum); outline: none; }
.rsvp-add {
  align-self: flex-start; background: none; border: 0; cursor: pointer; padding: 6px 0; font-family: inherit;
  font-size: 10px; letter-spacing: .18em; text-transform: uppercase; color: var(--plum-mid);
  border-bottom: 1px solid var(--lilac-light);
}
.rsvp-add:hover, .rsvp-add:focus-visible { color: var(--plum); border-bottom-color: var(--plum); outline: none; }
.rsvp-error { font-size: 11px; letter-spacing: .08em; line-height: 1.8; color: var(--plum-mid); }
.rsvp-submit {
  background: var(--plum); color: var(--ground); border: 0; cursor: pointer;
  padding: 13px 14px; font-family: inherit; font-size: 10px; letter-spacing: .3em; text-transform: uppercase; text-align: center;
}
.rsvp-submit:disabled { opacity: .6; cursor: default; }
.rsvp-done { display: flex; flex-direction: column; align-items: center; gap: 16px; }
.rsvp-done-script { font-family: "ESScript", cursive; font-size: clamp(28px, 2.8vw, 44px); color: var(--lilac); line-height: 1; }

/* ============ Scene 14 — See you in Toronto ============ */
.s14 { background: var(--sky); align-items: center; justify-content: flex-start; padding: 9vh 8vw 0; }
.s14-title { position: relative; z-index: 4; font-family: "ESScript", cursive; font-size: clamp(34px, 4vw, 62px); color: var(--plum); line-height: 1; }
.s14-art {
  position: absolute; left: 0; right: 0; top: 19vh; bottom: 11vh;
  display: flex; align-items: flex-end; justify-content: center; overflow: hidden;
}
.s14-frame { position: relative; height: 100%; aspect-ratio: 1000 / 1300; max-width: 72vw; overflow: hidden; }
/* The stage is the illustration's own 1000x1400 canvas mapped onto the 1300-unit frame:
   the frame's top edge is image y=90, so height = 1400/1300 and top = -90/1300. Every layer
   is then placed by its natural offset on that canvas — clouds and skyline are 1000x667
   sitting at y=85 (85/1400 and 667/1400), the car already fills the full 1400. */
.s14-stage { position: absolute; left: 0; right: 0; top: -6.9231%; height: 107.6923%; }
.s14-stage img { position: absolute; left: 0; width: 100%; max-width: none; }
.s14-clouds, .s14-skyline { top: 6.0714%; height: 47.6429%; }
.s14-car { top: 0; height: 100%; transform-origin: 50% 88%; }
/* Arrival: three timed beats — clouds gather, the city rises, then the car pulls away up
   the road. Driven by the shared [data-anim]/.on reveal (data-delay staggers them), NOT by
   scroll position: scrubbing tied the whole sequence to the scroll-in, so it finished before
   the scene had even filled the screen and you always arrived at a static picture.
   The skyline reuses .rv-draw-up; these two carry the motions that class doesn't cover.
   JS-only, so with JS off the finale still renders assembled. */
html.js .s14-fade {
  opacity: 0; transform: translateX(-3%);
  transition: opacity var(--rv-d, 1400ms) ease, transform var(--rv-d, 1400ms) var(--rv-e, cubic-bezier(.22, 1, .36, 1));
}
html.js .s14-fade.on { opacity: 1; transform: none; }
html.js .s14-drive {
  opacity: 0; transform: scale(1.5) translateY(4%);
  transition: opacity calc(var(--rv-d, 1700ms) * .45) ease, transform var(--rv-d, 1700ms) var(--rv-e, cubic-bezier(.33, 1, .4, 1));
}
html.js .s14-drive.on { opacity: 1; transform: scale(1) translateY(0); }
.s14-date {
  position: absolute; bottom: 4.5vh; left: 0; right: 0; z-index: 4; text-align: center;
  font-size: 9px; letter-spacing: .34em; text-transform: uppercase; color: var(--lilac);
}

/* ============ Flow mode (mobile / reduced motion / no-JS) ============ */
body.flow .rsvp-panel { max-height: none; overflow-y: visible; }
body.flow .s14 { min-height: 100svh; }

@media (max-width: 767px) {
  .bg-skyline { display: none; }
  .bg-stripes { top: -40vh; bottom: -40vh; left: -20vw; right: -20vw; }
  .topbar { padding: 20px 22px; }
  .s4 { display: flex; flex-direction: column; align-items: stretch; gap: 4vh; padding: 0 0 8vh; }
  .s4-photo { height: 44svh; width: 100%; }
  .s4-copy { padding: 0 8vw; }
  .s6-strip { margin-right: -8vw; padding-right: 8vw; }
  .s5, .s6, .s7, .s8, .s9, .s10, .s12 { padding-left: 8vw; padding-right: 8vw; }
  .sidenav { display: none; }
  .f-row { grid-template-columns: 1fr; }
  .s8-title { white-space: normal; }
  .s8-boards { grid-template-columns: 1fr; }
}

@media (min-width: 768px) {
  .menu-btn, .menu { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  html.js .rv, html.js .rv-draw, html.js .rv-draw-up {
    opacity: 1; transform: none; clip-path: none; transition: none;
  }
  html.js .s14-fade, html.js .s14-drive {
    opacity: 1 !important; transform: none !important; transition: none !important;
  }
  .topbar-mark { transition: none; }
  .s1-scroll i { animation: none; }
  .sidenav .lbl, .sidenav .tick { transition: none; }
}
