/* Layout: one phone-width column (the invitation) centred on a night-blue backdrop; each block is a full-bleed band
   with its own inner gutter. One deliberate look — the blue toile envelope, then old paper, gold paint and wine or
   gold ink — in any theme. Headings are deep wine lit like silk, small captions gold, body text wine. */
:root {
  --col: 480px;
  --paper: #F3EADA;
  --paper-2: #EADFC9;
  --card: #FBF6EC;
  --line: #DDCDB2;
  --ink: #5A1E28;
  --title: #6E1E2E;
  --ink-soft: #A57C6E;
  --muted: #7B5B52;
  --gold: #A47D3B;
  --gold-2: #C9A55E;
  --gold-text: linear-gradient(100deg, #8E6624 0%, #BC913D 28%, #D6B05C 46%, #AF822E 64%, #85601F 100%);
  --champagne: #F1D9A6;
  --night: #1C2048;
  --ivory: #FFF8EA;
  --glow: rgba(255, 214, 150, .42);
  --f-display: "Cormorant Garamond", "Times New Roman", serif;
  --f-body: "Commissioner", "Helvetica Neue", Arial, sans-serif;
  --f-script: "Great Vibes", "Snell Roundhand", cursive;
  --grain: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%27240%27 height=%27240%27%3E%3Cfilter id=%27n%27%3E%3CfeTurbulence type=%27fractalNoise%27 baseFrequency=%27.85%27 numOctaves=%273%27 stitchTiles=%27stitch%27/%3E%3CfeColorMatrix values=%270 0 0 0 .38  0 0 0 0 .3  0 0 0 0 .18  0 0 0 .11 0%27/%3E%3C/filter%3E%3Crect width=%27100%25%27 height=%27100%25%27 filter=%27url%28%23n%29%27/%3E%3C/svg%3E");
  --mottle: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%27640%27 height=%27640%27%3E%3Cfilter id=%27m%27 x=%270%27 y=%270%27 width=%27100%25%27 height=%27100%25%27%3E%3CfeTurbulence type=%27fractalNoise%27 baseFrequency=%27.0055%27 numOctaves=%274%27 seed=%2711%27 stitchTiles=%27stitch%27/%3E%3CfeColorMatrix values=%270 0 0 0 .6  0 0 0 0 .44  0 0 0 0 .24  .8 0 0 0 -.35%27/%3E%3C/filter%3E%3Crect width=%27100%25%27 height=%27100%25%27 filter=%27url%28%23m%29%27/%3E%3C/svg%3E");
  /* Old paper: fine grain, soft watercolour mottling, edges browned by time. Tiles vertically without seams. */
  --paper-bg:
    var(--grain) 0 0 / 240px 240px,
    var(--mottle) 0 0 / 640px 640px,
    linear-gradient(90deg, rgba(146, 106, 58, .13), rgba(146, 106, 58, 0) 15%, rgba(146, 106, 58, 0) 85%, rgba(146, 106, 58, .13)),
    var(--paper);
  --vignette: radial-gradient(135% 88% at 50% 46%, rgba(146, 106, 58, 0) 60%, rgba(146, 106, 58, .15));
  --gl: max(54px, env(safe-area-inset-left, 0px));
  --gr: max(54px, env(safe-area-inset-right, 0px));  /* room for the peonies down both edges */
}
.title, .greet-title, .cal-head .script, .menv-paper b, .menv-label b, .sent h3 { color: var(--title); }
/* Wine headings with a soft sheen: the gradient is clipped to the letters; padding keeps the script swashes inside the painted box. */
:is(.title, .greet-title, .cal-head .script, .menv-paper b, .menv-label b, .sent h3) {
  background: linear-gradient(100deg, #4A1020 0%, #7A2034 30%, #A4465A 47%, #77203A 63%, #47101E 100%); -webkit-background-clip: text; background-clip: text; color: transparent; -webkit-text-fill-color: transparent;
}
/* ---------- Draft papers (data-paper on <html>): 1 cream, made in CSS above; 2–7 photographed old letters and book pages.
   Every page is its own sheet of the chosen paper, each a little different (another part of it, mirrored, a touch warmer or paler,
   set per page in site.js), with a soft wash of paper colour in the middle so the faded writing stays behind the words. ---------- */
html.img-paper {
  /* a clean band down the middle of every sheet, where the words and pictures sit; the old writing shows only along the edges */
  --calm-bg: linear-gradient(90deg, rgb(var(--calm) / 0) 0%, rgb(var(--calm) / var(--calm-a)) 17%, rgb(var(--calm) / var(--calm-a)) 83%, rgb(var(--calm) / 0) 100%);
  --paper-bg: var(--calm-bg), var(--paper-img) 50% 30% / cover no-repeat, var(--paper);
  --vignette: radial-gradient(135% 90% at 50% 46%, rgba(120, 80, 40, 0) 64%, rgba(120, 80, 40, .14));
}
html.img-paper .site { background: var(--paper); }
html.img-paper .sec { isolation: isolate; box-shadow: 0 -16px 24px -18px rgba(70, 45, 20, .55); }
html.img-paper .sec::before, .sheet-ghost { content: ""; position: absolute; inset: 0; z-index: -1; transform: scaleX(var(--pf, 1));
  background: linear-gradient(var(--pt, transparent), var(--pt, transparent)), var(--calm-bg), var(--paper-img) var(--pp, 50% 30%) / var(--ps, cover) no-repeat, var(--paper); }
/* The sheet of the page just left, dissolving over the new one (site.js sheetGhost). On the finale it lies over the night picture. */
.sheet-ghost { display: block; pointer-events: none; will-change: opacity; }
.sheet-ghost.plain { transform: none; background: var(--vignette), var(--paper-bg); }
.finale > .sheet-ghost { z-index: 1; }
html[data-paper="2"] { --paper-img: url("../img/paper-1.webp"); --paper: #E7D5B3; --calm: 240 228 204; --calm-a: .84; }
html[data-paper="3"] { --paper-img: url("../img/paper-2.webp"); --paper: #E9ECEE; --calm: 244 244 240; --calm-a: .88; }
html[data-paper="4"] { --paper-img: url("../img/paper-3.webp"); --paper: #E2CBA2; --calm: 240 226 200; --calm-a: .8; }
html[data-paper="5"] { --paper-img: url("../img/paper-4.webp"); --paper: #ECE1C9; --calm: 244 236 220; --calm-a: .8; }
html[data-paper="6"] { --paper-img: url("../img/paper-5.webp"); --paper: #EEE5D4; --calm: 246 240 228; --calm-a: .8; }
html[data-paper="7"] { --paper-img: url("../img/paper-6.webp"); --paper: #ECDABA; --calm: 244 232 210; --calm-a: .8; }
.paper { background: var(--paper-bg); }
html { background: #12152E; }
body {
  margin: 0;
  background: #12152E;
  color: var(--ink);
  font-family: var(--f-body);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}
html.locked, html.locked body { overflow: hidden; }
img { display: block; max-width: 100%; }
.defs { position: absolute; width: 0; height: 0; overflow: hidden; }

.backdrop { position: fixed; inset: 0; background: radial-gradient(120% 80% at 50% 30%, #2A3160 0%, #151935 60%, #0E1027 100%); }
.backdrop::after { content: ""; position: absolute; inset: 0; background: url("../img/liner.webp") center / 520px auto; opacity: .05; mix-blend-mode: screen; }
.site { position: relative; max-width: var(--col); margin: 0 auto; background: var(--paper-bg); box-shadow: 0 0 90px rgba(0, 0, 0, .5); overflow-x: clip; }

/* ---------- Shared type ---------- */
/* Every page is exactly one screen of the phone it is opened on, its content centred; if a small phone cannot hold it,
   site.js scales that page's content down to fit (fitPages). --vu is 1% of that screen, measured once by site.js with the
   browser bars showing and kept while the bars hide on scroll or the keyboard comes up, so nothing changes size mid-way. */
.sec { position: relative; box-sizing: border-box; height: calc(var(--vu, 1svh) * 100); min-height: 540px; overflow: hidden; display: flex; flex-direction: column; justify-content: center;
  padding: calc(30px + env(safe-area-inset-top, 0px)) 0 calc(30px + env(safe-area-inset-bottom, 0px)); }
.sec > .inner { flex: none; transform-origin: 50% 50%; }
/* A page arrives like the opening words: rising from below, words pouring in after it, pictures blooming out of the paper
   from the middle. The rise and the fit-to-screen scale (--fit) live in one transform: phones that split them into separate
   properties dropped one of them while the other animated, and the page jumped in size afterwards. */
.sec > .inner { transform: translate3d(0, calc(var(--vu, 1svh) * 9), 0) scale(var(--fit, 1)); opacity: 0;
  transition: transform 2.6s cubic-bezier(.16, 1, .3, 1), opacity 1.5s ease; }
.sec.here > .inner { transform: translate3d(0, 0, 0) scale(var(--fit, 1)); opacity: 1; }
/* First the words drift up, then the picture blooms out of the paper, evenly, one after the other. */
.sec .flow { --d0: .5s; }
.bloom { opacity: 0; transform: scale(.94); clip-path: ellipse(18% 16% at 50% 54%);
  transition: clip-path 2.6s cubic-bezier(.3, .6, .3, 1) var(--bd, 1.7s), opacity 1.4s ease var(--bd, 1.7s), transform 2.8s cubic-bezier(.2, .7, .2, 1) var(--bd, 1.7s); }
.sec.here .bloom { opacity: 1; transform: none; clip-path: ellipse(90% 90% at 50% 54%); }
.looks-sec .bloom { --bd: .7s; }   /* «Образы вечера»: the pictures come with the words, as asked */
/* (the format picture blooms through a wrapper: its own scale is the slow zoom) */
.fmt-bloom { display: block; width: 100%; height: 100%; }
/* «Образы вечера»: both pictures bloom together with the words of the page, not after them. */
/* Pages with less on them start higher, so the empty space is not all at the top. */
.program, .rsvp { justify-content: flex-start; padding-top: calc(calc(var(--vu, 1svh) * 9) + env(safe-area-inset-top, 0px)); }
.program > .inner, .rsvp > .inner { transform-origin: 50% 0; }
.inner { padding-left: var(--gl); padding-right: var(--gr); }
.sec > .inner { position: relative; z-index: 1; }   /* above the peonies */
.kicker {
  display: flex; align-items: center; justify-content: center; gap: 12px; margin: 0 0 14px;
  font: 600 12.5px var(--f-display); letter-spacing: .32em; text-transform: uppercase; color: var(--gold);
}
.kicker::before, .kicker::after { content: ""; width: 26px; height: 1px; background: currentColor; opacity: .55; }
.sec .kicker::before, .sec .kicker::after { transform: scaleX(0); transition: transform 1.4s cubic-bezier(.2, .7, .2, 1) .3s; }
.sec .kicker::before { transform-origin: 100% 50%; }
.sec .kicker::after { transform-origin: 0 50%; }
.sec .kicker.in::before, .sec .kicker.in::after { transform: none; }
.title { margin: 0 0 12px; text-align: center; font: 500 clamp(28px, 7.6vw, 36px)/1.12 var(--f-display); color: var(--ink); text-wrap: balance; }
.text { margin: 0 auto; max-width: 30ch; text-align: center; font: 400 19px/1.45 var(--f-display); color: var(--ink); text-wrap: pretty; }
.text.muted { color: var(--muted); font-style: italic; font-size: 17px; margin-top: 18px; }
.script { font-family: var(--f-script); font-weight: 400; }
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px; padding: 13px 24px; border: 0; border-radius: 999px; cursor: pointer;
  font: 500 14.5px var(--f-body); color: var(--ivory); background: var(--ink); text-decoration: none;
  box-shadow: 0 10px 20px -12px rgba(44, 66, 107, .7);
}
.btn:focus-visible, .link-btn:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }
.flourish { display: block; width: 150px; margin: 0 auto 30px; overflow: visible; }
.flourish path { fill: none; stroke: var(--gold-2); stroke-width: 1; stroke-linecap: round; stroke-dasharray: 1; stroke-dashoffset: 0; }

/* Words drift up one after another, so a paragraph pours in instead of popping. */
.flow .w { display: inline-block; opacity: 0; transform: translateY(1.1em);
  transition: opacity 1.2s ease, transform 1.6s cubic-bezier(.16, 1, .3, 1); transition-delay: calc(var(--d0, 0s) + var(--i, 0) * 45ms); }
.flow.in .w { opacity: 1; transform: none; }
.flow .cap { font-weight: inherit; font-size: 1.16em; line-height: 0; color: var(--gold); }
/* Headings are written in with a sweep of the pen. */
.title.wr { padding: .14em .3em; margin-left: -.3em; margin-right: -.3em;
  -webkit-mask: linear-gradient(90deg, #000 42%, transparent 58%) 100% 0 / 260% 100% no-repeat;
  mask: linear-gradient(90deg, #000 42%, transparent 58%) 100% 0 / 260% 100% no-repeat; }
.title.wr.in { animation: write 2.2s cubic-bezier(.5, .1, .3, 1) both; }

/* ---------- Peony garlands with gold scrolls down both edges of every page, half tucked behind the edge.
   The top half hangs from the page top, the bottom half rises from its bottom; on a tall page they meet in a soft fade. ---------- */
.pe-set { position: absolute; inset: 0; z-index: 0; overflow: hidden; pointer-events: none; }
.story-pin .pe-set { top: env(safe-area-inset-top, 0px); bottom: env(safe-area-inset-bottom, 0px); }
.pe { position: absolute; width: 200px; height: 50%; background: url("../img/side-1.webp") no-repeat; background-size: 100% auto; opacity: 0;
  transition: opacity 1.6s ease, transform 2.4s cubic-bezier(.2, .7, .2, 1); }
.pe.tl, .pe.tr { top: 0; background-position: 0 0; -webkit-mask: linear-gradient(#000 76%, transparent); mask: linear-gradient(#000 76%, transparent); }
.pe.bl, .pe.br { bottom: 0; background-position: 0 100%; -webkit-mask: linear-gradient(transparent, #000 24%); mask: linear-gradient(transparent, #000 24%); }
.pe.tl, .pe.bl { left: 0; transform: translateX(-76%); }
.pe.tr, .pe.br { right: 0; transform: scaleX(-1) translateX(-76%); }
.pe-set.in .pe { opacity: 1; }
.pe-set.still .pe { transition: none; }
.pe-set.in .pe.tl, .pe-set.in .pe.bl { transform: translateX(-71%); }
.pe-set.in .pe.tr, .pe-set.in .pe.br { transform: scaleX(-1) translateX(-71%); }

/* ---------- Hero: envelope → day → night ---------- */
.hero {
  position: relative; height: calc(var(--vu, 1svh) * 100); min-height: 560px; overflow: hidden;
  background: var(--night); container-type: inline-size; perspective: 1400px;
  -webkit-tap-highlight-color: transparent;
}
.rig { position: absolute; inset: 0; transform-style: preserve-3d; transform-origin: 50% 45%; pointer-events: none; }
.card { position: absolute; inset: 0; overflow: hidden; transform: translateZ(-2px) scale(1.06); }
.card .layer { position: absolute; inset: 0; width: 100%; height: 100%; }
.card img { width: 100%; height: 100%; object-fit: cover; }
/* Night comes down from the top with a soft edge. The edge is a fixed mask on a sheet that slides down, while the
   picture inside slides up by the same amount and stays put: two transforms the GPU plays, no repainting. */
.card .night { inset: 0 0 auto 0; height: 145%; overflow: hidden; transform: translateY(-100%);
  -webkit-mask: linear-gradient(#000 69%, transparent); mask: linear-gradient(#000 69%, transparent);
  transition: transform 2.8s cubic-bezier(.45, 0, .25, 1); will-change: transform; }
.night-in { position: absolute; left: 0; right: 0; top: 0; height: 68.966%; transform: translateY(145%);
  transition: transform 2.8s cubic-bezier(.45, 0, .25, 1); will-change: transform; }
.hero[data-time="night"] .card .night, .hero[data-time="night"] .night-in { transform: none; }
.hero-stars { position: absolute; inset: 0; width: 100%; height: 100%; }
.dim { position: absolute; inset: 0; background: #1A1626; opacity: .72; }

.title-block { position: absolute; left: 4%; right: 4%; top: 13%; }
.title-block .w {
  padding: 2cqw 5cqw; margin: -2cqw -5cqw;
  -webkit-mask: linear-gradient(90deg, #000 42%, transparent 58%) 100% 0 / 260% 100% no-repeat;
  mask: linear-gradient(90deg, #000 42%, transparent 58%) 100% 0 / 260% 100% no-repeat;
}
.title-block .r { opacity: 0; }
.title-block.in .w { animation: write 2.6s cubic-bezier(.5, .1, .3, 1) var(--d, 0s) both; }
.title-block.in .r { animation: rise 1.4s ease var(--d, 0s) both; }
@keyframes write { from { -webkit-mask-position: 100% 0; mask-position: 100% 0; } to { -webkit-mask-position: 0 0; mask-position: 0 0; } }
@keyframes rise { from { opacity: 0; transform: translateY(1.6cqw); } to { opacity: 1; transform: none; } }
.t { display: grid; justify-items: center; gap: 1.4cqw; text-align: center; color: var(--ivory); line-height: 1.05;
  text-shadow: 0 0 2.4cqw var(--glow), 0 .3cqw .8cqw rgba(10, 12, 40, .35);
  transition: color 1.6s ease, text-shadow 1.6s ease; }
.t > span { display: block; }
.t .eyebrow { font: 500 3.5cqw var(--f-display); letter-spacing: .42em; padding-left: .42em; text-transform: uppercase; }
.t .names { font-family: var(--f-script); font-size: 13cqw; }
.t .date { font: 500 3.7cqw var(--f-display); letter-spacing: .36em; padding-left: .36em; text-transform: uppercase; }
.hero[data-time="day"] .t { color: var(--ink); text-shadow: 0 0 2.4cqw rgba(255, 252, 245, .95); }

.part { position: absolute; inset: 0; transform-style: preserve-3d; }
.flap { position: absolute; left: 0; top: 0; transform-style: preserve-3d; transform-origin: 50% 0; }
.face { position: absolute; inset: 0; -webkit-backface-visibility: hidden; backface-visibility: hidden; }
.front { background: url("../img/env-c.webp") no-repeat; }
/* Safari ignores backface-visibility inside this 3D rig, so the lining stays switched off until the flap turns over. */
.back { background: #F5EFE4 url("../img/liner.webp") 0 0 repeat; transform: rotateX(180deg); opacity: 0; }
.hero:is([data-state="closed"], [data-state="opening"]) :is(.flap, .card) { will-change: transform; }
.hero:is([data-state="closed"], [data-state="opening"]) :is(.face, .seal, .dim, .fshadow) { will-change: opacity, transform; }
.shade { position: absolute; inset: 0; opacity: 0; background: #161A34; }
.fshadow { position: absolute; left: 0; top: 0; transform-origin: 50% 0; filter: blur(6px); opacity: 0; }
.fshadow i { position: absolute; inset: 0; background: rgba(18, 22, 46, .8); }
.body-wrap { position: absolute; inset: 0; filter: drop-shadow(0 -.5cqw 1.2cqw rgba(30, 25, 20, .35)); }
.body { position: absolute; inset: 0; background: url("../img/env-c.webp") no-repeat; }

/* The seal is there from the first frame and "blinks" every few seconds: a warm glow behind it, a heart-shaped echo
   and a glint across the wax. All of it is opacity and transform, so it never costs a repaint. */
.seal {
  --sw: min(44cqw, 210px);
  position: absolute; left: 50%; top: 100%;
  width: var(--sw); aspect-ratio: 760 / 731; margin: calc(var(--sw) * -731 / 1520) 0 0 calc(var(--sw) / -2); padding: 0; border: 0; background: none; -webkit-appearance: none; appearance: none; line-height: 0; cursor: pointer; pointer-events: auto;
  transform: translateZ(.6px);
  -webkit-backface-visibility: hidden; backface-visibility: hidden;
  -webkit-tap-highlight-color: transparent;
}
.seal img { position: relative; width: 100%; height: auto; filter: drop-shadow(0 1.6cqw 2.2cqw rgba(60, 40, 10, .38)); }
.seal .echo { position: absolute; left: 0; top: 0; filter: none; opacity: 0; }
.seal .halo {
  position: absolute; inset: -38%; border-radius: 50%; opacity: 0;
  background: radial-gradient(circle, rgba(255, 232, 175, .95), rgba(255, 214, 140, .4) 38%, rgba(255, 214, 140, 0) 66%);
}
.seal .glint { position: absolute; inset: 0; overflow: hidden; pointer-events: none;
  -webkit-mask: url("../img/seal-b.webp") center / 100% 100% no-repeat; mask: url("../img/seal-b.webp") center / 100% 100% no-repeat; }
.seal .glint b { position: absolute; top: -10%; bottom: -10%; left: 0; width: 46%; transform: translateX(-110%);
  background: linear-gradient(100deg, rgba(255, 250, 232, 0) 10%, rgba(255, 250, 232, .8) 50%, rgba(255, 250, 232, 0) 90%); }
.hero.ready .seal { animation: breathe 3.6s ease-in-out infinite; }
.hero.ready .seal .halo { animation: glow 3.6s ease-in-out .9s infinite; }
.hero.ready .seal .echo { animation: echo 3.6s cubic-bezier(.2, .6, .3, 1) .9s infinite; }
.hero.ready .seal .glint b { animation: glint 3.6s ease-in-out .9s infinite; }
.seal:focus-visible { outline: 2px solid var(--gold); outline-offset: 6px; border-radius: 50%; }
.seal.pressed, .hero.ready .seal.pressed :is(.echo, .glint b) { animation: none; pointer-events: none; }
.seal.pressed .halo { animation: none !important; }
.seal.pressed :is(.echo, .glint) { opacity: 0; }
/* The seal is centred on the tip of the flap by margins from its known size (760×731), not by translate(-50%): Safari worked
   the percentage out once, when the animation started and the picture had no height yet, and the seal sat low until it was
   touched. The breathing (a scale only) starts once the picture is decoded. */
@keyframes breathe { 0%, 100% { transform: translateZ(.6px); } 50% { transform: translateZ(.6px) scale(1.025); } }
@keyframes glow { 0%, 52%, 100% { opacity: 0; transform: scale(.8); } 68% { opacity: .9; transform: scale(1); } 86% { opacity: 0; transform: scale(1.12); } }
@keyframes echo { 0%, 58% { opacity: 0; transform: scale(1); } 62% { opacity: .55; } 100% { opacity: 0; transform: scale(1.42); } }
@keyframes glint { 0%, 60% { transform: translateX(-110%); } 88%, 100% { transform: translateX(240%); } }
@keyframes pulse { 50% { opacity: .55; } }

/* "Нажмите на печать": small, at the bottom, on a cloud of cream so it reads over the engraving. */
.hint { position: absolute; left: 0; right: 0; bottom: calc(calc(var(--vu, 1svh) * 7) + env(safe-area-inset-bottom, 0px)); z-index: 3; margin: 0; text-align: center; pointer-events: none;
  opacity: 0; transition: opacity 1.2s ease .5s; }
.hint span { display: inline-flex; align-items: center; gap: 10px; padding: 10px 24px 11px; border-radius: 999px;
  font: italic 500 min(5.2cqw, 22px) var(--f-display); letter-spacing: .04em; color: var(--ink);
  background: rgba(251, 246, 236, .93); box-shadow: 0 0 0 1px rgba(201, 165, 94, .55), 0 0 0 4px rgba(251, 246, 236, .5), 0 8px 22px -8px rgba(40, 50, 90, .35); }
.hint span::before, .hint span::after { content: ""; width: 5px; height: 5px; border-radius: 50%; background: var(--gold-2); }
.hero.ready .hint { opacity: 1; }
.hero.ready .hint span { animation: hintPing 3.6s ease-in-out .9s infinite; }
@keyframes hintPing { 0%, 55%, 100% { box-shadow: 0 0 0 1px rgba(201, 165, 94, .55), 0 0 0 4px rgba(251, 246, 236, .5), 0 8px 22px -8px rgba(40, 50, 90, .35); }
  70% { box-shadow: 0 0 0 1px rgba(201, 165, 94, .95), 0 0 0 7px rgba(241, 217, 166, .45), 0 8px 26px -6px rgba(164, 125, 59, .55); } }
.hero:not([data-state="closed"]) .hint { opacity: 0; transition-delay: 0s; transition-duration: .5s; }

/* Night-blue veil until the envelope and the seal are decoded, so they appear together. */
.veil { position: absolute; inset: 0; z-index: 9; display: grid; place-items: center; background: var(--night); transition: opacity 1.1s ease, visibility 0s 1.1s; }
.veil i { width: 9px; height: 9px; border-radius: 50%; background: var(--champagne); box-shadow: 0 0 18px 6px rgba(241, 217, 166, .45); animation: pulse 1.6s ease-in-out infinite; }
.hero.ready .veil { opacity: 0; visibility: hidden; }

.rose { position: absolute; bottom: -4%; width: 74%; z-index: 4; pointer-events: none; opacity: 0; }
.rose-l { left: -10%; }
.rose-r { right: -10%; }
.wipe { position: absolute; inset: 0; z-index: 7; background: var(--vignette), var(--paper-bg); transform: translateY(101%); pointer-events: none;
  -webkit-mask: var(--deckle-up) top / 100% 40px no-repeat, linear-gradient(#000, #000) 0 39px / 100% calc(100% - 39px) no-repeat;
  mask: var(--deckle-up) top / 100% 40px no-repeat, linear-gradient(#000, #000) 0 39px / 100% calc(100% - 39px) no-repeat; }

.dn {
  position: absolute; top: max(4.5cqw, calc(env(safe-area-inset-top, 0px) + 10px)); right: max(4.5cqw, calc(env(safe-area-inset-right, 0px) + 10px)); z-index: 6;
  display: flex; gap: 1cqw; padding: 1.2cqw; border-radius: 99px; cursor: pointer;
  background: rgba(255, 255, 255, .2); border: 1px solid rgba(255, 255, 255, .4);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  opacity: 0; pointer-events: none; transition: opacity .8s ease;
}
.hero[data-state="night"] .dn { opacity: 1; pointer-events: auto; }
.dn span { display: grid; place-items: center; width: min(8cqw, 38px); height: min(8cqw, 38px); border-radius: 50%; color: var(--ivory); transition: background .5s, color .5s; }
.dn svg { width: 55%; height: 55%; }
.hero[data-time="day"] .dn { border-color: rgba(44, 66, 107, .25); }
.hero[data-time="day"] .dn span { color: var(--ink); }
.hero[data-time="day"] .dn .sun, .hero[data-time="night"] .dn .moon { background: var(--ivory); color: var(--night); }
.dn:focus-visible { outline: 2px solid var(--ivory); outline-offset: 2px; }

.cue { position: absolute; left: 0; right: 0; bottom: calc(20px + env(safe-area-inset-bottom, 0px)); z-index: 5; display: grid; justify-items: center; gap: 8px;
  opacity: 0; transition: opacity 1s ease; pointer-events: none; }
.cue span { font: 600 11px var(--f-display); letter-spacing: .42em; padding-left: .42em; text-transform: uppercase; color: var(--ink); }
.cue i { position: relative; width: 1px; height: 36px; background: linear-gradient(var(--ink-soft), transparent); overflow: visible; }
.cue i::after { content: ""; position: absolute; left: -2px; top: -4px; width: 5px; height: 5px; border-radius: 50%; background: var(--gold); animation: drip 1.9s ease-in infinite; }
@keyframes drip { 0% { transform: translateY(0); opacity: 1; } 100% { transform: translateY(40px); opacity: 0; } }

.hero.no-trans, .hero.no-trans * { transition: none !important; }
.hero.no-trans .title-block * { animation-delay: 0s !important; animation-duration: .001s !important; }

/* ---------- Epigraph, the opening words, the two of us ---------- */
@property --r { syntax: "<percentage>"; inherits: false; initial-value: 0%; }
.story-pin { position: absolute; inset: 0; z-index: 8; overflow: hidden; opacity: 0; visibility: hidden; transition: opacity 1.4s ease, visibility 0s 1.4s;
  background: var(--vignette), var(--paper-bg); }
.story-pin.on { opacity: 1; visibility: visible; transition: opacity 1.4s ease, visibility 0s; }

/* Letters turn over one by one like pages of a score, word by word on the beat, flashing gold as they land. */
/* Centred by flex, so the two of us can sit under the quote without a transform. */
.epigraph { position: absolute; inset: 0 0 2% 0; z-index: 1; margin: 0; display: flex; flex-direction: column; justify-content: center; align-items: center;
  padding-left: max(34px, var(--gl)); padding-right: max(34px, var(--gr)); text-align: center; }
.epi-text { margin: 0 auto; max-width: 13.5em; font: italic 500 clamp(28px, 7.4vw, 34px)/1.4 var(--f-display); color: var(--ink); }
.epi-text .wd { display: inline-block; white-space: nowrap; }
.epi-text .ch { display: inline-block; opacity: 0; transform-origin: 0 70%; }
/* Written as if by an unseen pen: each letter is drawn in from left to right, the ink glinting gold and drying to wine. */
.epi-text .ch.on { animation: chWrite .24s linear both, chGold 1.7s ease both; }
@keyframes chWrite { 0% { opacity: 1; clip-path: inset(-40% 100% -40% -14%); } 100% { opacity: 1; clip-path: inset(-40% -40% -40% -40%); } }
.epi-text .ch.off { transform-origin: 100% 70%; animation: chOut .95s cubic-bezier(.5, 0, .75, .4) both, chGoldOut .95s ease both; }
}
@keyframes chGold { 0% { color: #CDA552; } 100% { color: var(--ink); } }
@keyframes chOut {
  0% { opacity: 1; transform: perspective(520px) rotateY(0deg); }
  100% { opacity: 0; transform: perspective(520px) rotateY(105deg) translateY(-.18em); }
}
@keyframes chGoldOut { 0% { color: var(--ink); } 45% { color: #C39A48; } 100% { color: #E2C27A; } }
.epi-author { display: inline-flex; align-items: center; gap: 12px; margin-top: 22px; font: 600 12.5px var(--f-display); letter-spacing: .32em; padding-left: .32em; text-transform: uppercase; color: var(--gold);
  opacity: 0; transform: translateY(8px); transition: opacity 1.4s ease, transform 1.4s ease; }
.epi-author::before, .epi-author::after { content: ""; width: 26px; height: 1px; background: currentColor; opacity: .55; }
.epigraph.signed .epi-author { opacity: 1; transform: none; }
.epigraph.gone .epi-author { opacity: 0; transform: translateY(-14px); }
/* The two of us appear under the quote once it is signed, and leave with it. */
.epigraph .couple { margin: 26px 0 0; display: grid; justify-items: center; pointer-events: none; }
.epigraph.gone .figurine { opacity: 0; transform: translateY(-16px) scale(.97); transition: opacity 1.3s ease, transform 1.6s ease; }

/* The opening words rise from below and settle at the top, clear of the corner flourishes. */
.greeting { position: absolute; left: 0; right: 0; top: calc(max(calc(var(--vu, 1svh) * 18), 124px) + env(safe-area-inset-top, 0px)); z-index: 1; text-align: center;
  padding-left: max(34px, var(--gl)); padding-right: max(34px, var(--gr)); opacity: 0; transform: translateY(calc(var(--vu, 1svh) * 30)); }
.greeting.in { opacity: 1; transform: none; transition: transform 2.8s cubic-bezier(.16, 1, .3, 1), opacity 1.6s ease; }
.greet-title { margin: 0 -.3em; padding: .12em .3em; font: 400 clamp(40px, 11vw, 50px)/1.1 var(--f-script); }
.greet-flourish { display: block; width: 124px; margin: 8px auto 16px; overflow: visible; }
.greet-flourish path { fill: none; stroke: var(--gold-2); stroke-width: 1.1; stroke-linecap: round; stroke-dasharray: 1 1; stroke-dashoffset: 1; transition: stroke-dashoffset 1.8s ease .8s; }
.greeting.in .greet-flourish path { stroke-dashoffset: 0; }
/* The first letter: a tall gold script initial, the same gold as the rings below. Padding keeps its swashes inside the
   painted box; negative margins keep it from pushing the first line down. */
.greet-text .cap { display: inline-block; padding: .14em .16em .04em; margin: -.62em -.16em -.34em -.16em; vertical-align: -.1em;
  font: 400 2.75em/1 var(--f-script); background: linear-gradient(160deg, #8E6624 8%, #D9B666 38%, #F1DA9E 50%, #B98B37 66%, #85601F 96%);
  -webkit-background-clip: text; background-clip: text; color: transparent; -webkit-text-fill-color: transparent; }
.greet-text { --d0: 1.1s; margin: 0 auto; max-width: 16.5em; font: italic 500 clamp(21px, 5.8vw, 24px)/1.52 var(--f-display); color: var(--ink); text-wrap: pretty; }
.figurine { height: min(calc(var(--vu, 1svh) * 36), 320px); width: auto; max-width: 78%; object-fit: contain;
  opacity: 0; transform: translateY(10px) scale(.94);
  -webkit-mask: radial-gradient(ellipse 62% 56% at 50% 55%, #000 var(--r), transparent calc(var(--r) + 24%));
  mask: radial-gradient(ellipse 62% 56% at 50% 55%, #000 var(--r), transparent calc(var(--r) + 24%));
  transition: --r 2.6s cubic-bezier(.3, .6, .3, 1), opacity 1.3s ease, transform 2.6s cubic-bezier(.2, .7, .2, 1); }
.figurine.in { --r: 140%; opacity: 1; transform: none; }
/* The rings: a small watercolour of peonies that blooms out of the paper right under the opening words, then floats. */
.rings { margin: 18px 0 0; display: grid; justify-items: center; pointer-events: none; }
.ring-img { width: min(68%, 290px); height: min(calc(var(--vu, 1svh) * 27), 240px); object-fit: contain;
  opacity: 0; transform: translateY(10px) scale(.94);
  -webkit-mask: radial-gradient(ellipse 62% 58% at 50% 52%, #000 var(--r), transparent calc(var(--r) + 24%));
  mask: radial-gradient(ellipse 62% 58% at 50% 52%, #000 var(--r), transparent calc(var(--r) + 24%));
  transition: --r 2.6s cubic-bezier(.3, .6, .3, 1), opacity 1.3s ease, transform 2.6s cubic-bezier(.2, .7, .2, 1); }
.ring-img.in { --r: 140%; opacity: 1; transform: none; }
.rings.in { animation: ringsFloat 6s ease-in-out 2.8s infinite; }
@keyframes ringsFloat { 50% { transform: translateY(-5px) rotate(-1deg); } }
.story-dust { position: absolute; inset: 0; z-index: 2; width: 100%; height: 100%; pointer-events: none; }
.story-dust.page-dust { position: fixed; z-index: 34; left: max(0px, calc((100vw - var(--col)) / 2)); width: min(100vw, var(--col)); }

/* The music switch that stays with the guest down the whole page (hidden for now via the hidden attribute). */
.music-tg[hidden] { display: none; }
.music-tg { position: fixed; z-index: 45; top: calc(22px + env(safe-area-inset-top, 0px)); left: calc(50% - 20px);
  display: flex; align-items: center; justify-content: center; gap: 3px; width: 40px; height: 40px; padding: 0; border: 0; border-radius: 50%; cursor: pointer;
  background: rgba(255, 252, 246, .92); box-shadow: 0 0 0 1px rgba(201, 165, 94, .6), 0 6px 16px -6px rgba(60, 40, 20, .4);
  opacity: 0; pointer-events: none; transform: scale(.6); transition: opacity .8s ease, transform .8s cubic-bezier(.3, 1.5, .5, 1); -webkit-tap-highlight-color: transparent; }
html.sound-chosen .music-tg { opacity: 1; pointer-events: auto; transform: none; }
.music-tg i { width: 2.5px; height: 16px; border-radius: 2px; background: var(--gold); transform-origin: 50% 100%; transform: scaleY(.25); transition: transform .4s ease; }
.music-tg[aria-pressed="true"] i { animation: eq 1.1s ease-in-out infinite; }
.music-tg[aria-pressed="true"] i:nth-child(2) { animation-delay: -.45s; }
.music-tg[aria-pressed="true"] i:nth-child(3) { animation-delay: -.8s; }
.music-tg[aria-pressed="true"] i:nth-child(4) { animation-delay: -.2s; }
.music-tg::after { content: ""; position: absolute; width: 24px; height: 1.5px; border-radius: 1px; background: var(--ink-soft); transform: rotate(-45deg); transition: opacity .3s; }
.music-tg[aria-pressed="true"]::after { opacity: 0; }
.music-tg:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }
@keyframes eq { 0%, 100% { transform: scaleY(.3); } 50% { transform: scaleY(1); } }

/* ---------- Page changes during the film (#tourVeil, played from site.js) ---------- */
.tour-veil { position: fixed; z-index: 35; top: 0; bottom: 0; left: max(0px, calc((100vw - var(--col)) / 2)); width: min(100vw, var(--col)); pointer-events: none;
  transform: translateY(102%); background: var(--vignette), var(--paper-bg), #F3EADA; box-shadow: 0 -18px 40px -14px rgba(70, 45, 20, .35);
  -webkit-mask: var(--deckle-up) top / 100% 40px no-repeat, linear-gradient(#000, #000) 0 39px / 100% calc(100% - 39px) no-repeat;
  mask: var(--deckle-up) top / 100% 40px no-repeat, linear-gradient(#000, #000) 0 39px / 100% calc(100% - 39px) no-repeat; }
.tour-veil[data-kind="3"] { transform: none; opacity: 0; box-shadow: none; -webkit-mask: none; mask: none;
  background: radial-gradient(circle at 50% 50%, #FFF8E6 0%, rgba(250, 230, 180, .96) 30%, rgba(236, 204, 140, .7) 55%, rgba(236, 204, 140, 0) 75%); }
.tour-veil[data-kind="4"] { transform: none; opacity: 0; background: none; box-shadow: none; -webkit-mask: none; mask: none; }
.tour-veil .leaf { position: absolute; inset: 0; height: 100%; transform-origin: 0 50%; box-shadow: 0 0 40px rgba(60, 40, 20, .35); }

/* ---------- After the film: the epigraph and the opening words as ordinary pages under the title ---------- */
.epi-static { margin: 0; text-align: center; }
.epi-static .epi-text .ch { opacity: 1; }
.epi-static .epi-author { opacity: 1; transform: none; }
.epi-static .couple { margin: calc(var(--vu, 1svh) * 3.4) 0 0; display: grid; justify-items: center; }
.greet-page .greeting { position: static; opacity: 1; transform: none; padding-left: 0; padding-right: 0; }

/* ---------- Format of the day ---------- */
.format .text { max-width: 20.5em; font-size: 20.5px; line-height: 1.5; }
.fmt-pic { position: relative; width: min(80%, 320px, calc(var(--vu, 1svh) * 36)); aspect-ratio: 4 / 5; margin: calc(var(--vu, 1svh) * 3) auto 0;
  opacity: 0; transform: translateY(26px); transition: opacity 1.4s ease, transform 1.8s cubic-bezier(.2, .7, .2, 1); }
.fmt-pic::before { content: ""; position: absolute; inset: -9px; border: 1px solid var(--gold-2); border-radius: 999px 999px 16px 16px; opacity: .85; }
.fmt-pic img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 30%; border-radius: 999px 999px 10px 10px;
  transform: scale(1.14); transition: transform 3.2s cubic-bezier(.2, .7, .2, 1), opacity .4s ease; }
.fmt-pic.in { opacity: 1; transform: none; }
.fmt-pic.in img { transform: none; }

/* ---------- Draft-only: the variants panel ---------- */
.drafts { position: fixed; z-index: 50; right: calc(max(0px, (100vw - var(--col)) / 2) + 10px); bottom: calc(10px + env(safe-area-inset-bottom, 0px));
  display: grid; justify-items: end; gap: 8px; opacity: 0; pointer-events: none; transition: opacity .8s ease; }
html.unlocked .drafts { opacity: 1; pointer-events: auto; }
.drafts-toggle { padding: 9px 15px; border: 1px solid rgba(164, 125, 59, .5); border-radius: 999px; cursor: pointer;
  background: rgba(255, 252, 246, .95); box-shadow: 0 4px 14px rgba(60, 40, 20, .18);
  font: 600 11px var(--f-display); letter-spacing: .18em; text-transform: uppercase; color: #6C5340; }
.drafts-card { order: -1; box-sizing: border-box; width: min(326px, calc(100vw - 20px)); max-height: calc(var(--vu, 1svh) * 72); overflow: auto; padding: 14px 14px 4px;
  border-radius: 14px; background: rgba(255, 252, 246, .97); box-shadow: 0 16px 44px rgba(50, 30, 10, .28); }
.drafts-card[hidden], .drafts[hidden] { display: none; }
.drafts-h { margin: 0 0 12px; font: italic 500 16px var(--f-display); color: #4A3528; }
.drow { margin-bottom: 12px; }
.drow > span { display: block; margin-bottom: 6px; font: 600 10.5px var(--f-display); letter-spacing: .2em; text-transform: uppercase; color: #A47D3B; }
.dopts { display: flex; flex-wrap: wrap; gap: 6px; }
.dopts button { display: inline-flex; align-items: center; gap: 7px; min-width: 38px; height: 34px; padding: 0 11px; justify-content: center;
  border: 1px solid #DDCDB2; border-radius: 999px; background: transparent; cursor: pointer; font: 500 15.5px var(--f-display); color: #3A2A20; }
.dopts button[aria-pressed="true"] { border-color: #A47D3B; background: rgba(201, 165, 94, .2); }
.dopts i { width: 14px; height: 14px; border-radius: 50%; background: var(--s); }
.drafts button:focus-visible { outline: 2px solid #A47D3B; outline-offset: 2px; }

/* ---------- Date: calendar, swans, countdown ---------- */
.cal { position: relative; max-width: 330px; margin: 0 auto; padding: 24px 16px 16px; background: var(--card); border-radius: 3px;
  box-shadow: 0 26px 44px -30px rgba(60, 48, 28, .45), 0 0 0 1px rgba(170, 150, 110, .2); }
.cal-head { text-align: center; margin-bottom: 12px; }
/* inline-block with room round the letters: the wine paint is clipped to the text box, and the swash of «И» reaches out past it */
.cal-head .script { display: inline-block; padding: .16em .4em .1em; margin: -.16em 0 -.1em; font-size: 46px; line-height: 1; color: var(--ink); }
.cal-head .year { display: block; margin-top: 4px; font: 600 12.5px var(--f-display); letter-spacing: .42em; padding-left: .42em; color: var(--gold); }
.cal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); row-gap: 2px; text-align: center; font-variant-numeric: tabular-nums; }
.cal-grid .wd { padding-bottom: 6px; font: 600 11px var(--f-display); letter-spacing: .12em; text-transform: uppercase; color: var(--ink-soft); }
.cal-grid .d { font: 500 18px/38px var(--f-display); color: var(--ink); transition: color .8s ease, transform .8s ease; }
.cal-grid .d.we { color: var(--ink-soft); }
.cal-grid .d.mark { font-weight: 600; }
.cal-grid .d.mark { transition: color 1.6s ease, transform 1.6s cubic-bezier(.3, .7, .3, 1); }
.cal-grid .d.mark.on { color: var(--gold); transform: scale(1.15); }
.cal-heart { position: absolute; left: 0; top: 0; width: 80px; height: 74px; overflow: visible; pointer-events: none; }
/* Drawn round the 13th like a pen circling it. No non-scaling-stroke here: with it browsers measure the dash in screen
   pixels instead of the path's length of 1, and the whole heart showed at once instead of being drawn. */
.cal-heart { filter: drop-shadow(0 0 3px rgba(241, 217, 166, .7)); }
.cal-heart path { fill: none; stroke: var(--gold); stroke-width: 3.4; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 1; stroke-dashoffset: 1; }
.swans { position: relative; margin: 22px -6px 0; aspect-ratio: 1400 / 596; }
.swan { position: absolute; inset: 0; }
.swan img { width: 100%; height: 100%; animation: bob 4.5s ease-in-out infinite; }
.swan.l img { clip-path: inset(0 49.93% 0 0); }
.swan.r img { clip-path: inset(0 0 0 50.07%); animation-delay: -2.2s; }
@keyframes bob { 50% { transform: translateY(-1.5%); } }
.date-line { margin: 4px 0 0; text-align: center; font: 600 13px var(--f-display); letter-spacing: .34em; padding-left: .34em; text-transform: uppercase; color: var(--ink); }
.countdown { margin-top: 40px; text-align: center; }
.countdown .kicker { margin-bottom: 12px; }
.cd-row { display: flex; justify-content: center; align-items: flex-start; gap: 4px; }
.cd-u { display: grid; gap: 4px; min-width: 62px; }
.cd-u b { display: inline-flex; justify-content: center; height: 1.12em; overflow: hidden; font: 500 42px/1.1 var(--f-display); color: var(--ink); font-variant-numeric: tabular-nums; }
.cd-u b span { display: inline-block; }
.cd-u b span.roll { animation: roll .6s cubic-bezier(.3, .7, .2, 1); }
@keyframes roll { from { transform: translateY(75%); opacity: 0; filter: blur(2px); } to { transform: none; opacity: 1; filter: none; } }
.cd-u i { font: italic 400 14.5px var(--f-display); color: var(--muted); }
.cd-sep { font: 400 30px/1.4 var(--f-display); color: var(--gold-2); }

/* ---------- Program: the whole day at a glance, times floating in one after another ---------- */
.plan { position: relative; max-width: 380px; margin: 30px auto 0; padding: 0; list-style: none; }
.plan::before { content: ""; position: absolute; left: 99px; top: 34px; bottom: 34px; width: 1px; transform-origin: 50% 0; transform: scaleY(0);
  background: linear-gradient(var(--gold-2), rgba(201, 165, 94, .35)); transition: transform 3s cubic-bezier(.45, .05, .3, 1) .5s; }
.plan li { position: relative; display: grid; grid-template-columns: 64px 70px 1fr; align-items: center; min-height: 92px;
  opacity: 0; transform: translateY(34px); transition: opacity 1.1s ease, transform 1.5s cubic-bezier(.16, 1, .3, 1); transition-delay: calc(.6s + var(--k) * .6s); }
.plan time { justify-self: end; font: 500 29px/1 var(--f-display); letter-spacing: .02em; color: var(--gold); font-variant-numeric: lining-nums; }
.plan-dot { justify-self: center; display: grid; place-items: center; width: 58px; height: 58px; border-radius: 50%; background: var(--card);
  box-shadow: 0 0 0 1px rgba(201, 165, 94, .7), 0 0 0 4px var(--paper), 0 0 0 5px rgba(201, 165, 94, .35), 0 8px 16px -10px rgba(60, 40, 20, .5);
  transform: scale(.3); transition: transform 1.1s cubic-bezier(.3, 1.6, .5, 1); transition-delay: calc(.75s + var(--k) * .6s); }
.plan-dot img { width: 44px; height: 44px; object-fit: contain; }
.plan-txt { display: grid; gap: 2px; }
.plan p { margin: 0; font: 500 21px/1.25 var(--f-display); color: var(--ink); text-wrap: pretty; }
.plan small { font: italic 400 16px/1.3 var(--f-display); color: var(--muted); }
/* Starts with the page (.here), not with the scroll: under the turning sheet nothing would be seen. */
.sec.here .plan::before { transform: none; }
.sec.here .plan li { opacity: 1; transform: none; }
.sec.here .plan .plan-dot { transform: none; }

/* Under the timeline (draft data-clock on <html>): 1 a gold pocket watch at 15:00 among peonies, 2 the swans, 3 a gold flourish. */
.plan-pic { margin: calc(var(--vu, 1svh) * 2.6) auto 0; display: grid; justify-items: center; }
.plan-pic > * { grid-area: 1 / 1; }
.pp-watch { width: min(128%, 460px); max-height: calc(var(--vu, 1svh) * 31); margin: 0 -14%; object-fit: contain; opacity: 0; transform: translateY(14px) scale(.96);
  transition: opacity 1.6s  ease 3s, transform 2.2s cubic-bezier(.2, .7, .2, 1) 3s; }
.pp-swans { position: relative; width: min(100%, 320px); aspect-ratio: 1400 / 596; max-height: calc(var(--vu, 1svh) * 17); display: none; }
.pp-swans .swan { opacity: 0; transition: opacity 1.4s  ease 3s, transform 2.4s cubic-bezier(.2, .7, .2, 1) 3s; }
.pp-swans .swan.l { transform: translateX(-30%); }
.pp-swans .swan.r { transform: translateX(30%); }
.pp-curl { display: none; width: min(80%, 280px); overflow: visible; }
.pp-curl path { fill: none; stroke: var(--gold-2); stroke-width: 1.2; stroke-linecap: round; stroke-dasharray: 1 1; stroke-dashoffset: 1; transition: stroke-dashoffset 2.4s ease 3s; }
.sec.here .plan-pic .pp-watch { opacity: 1; transform: none; }
.sec.here .plan-pic .swan { opacity: 1; transform: none; }
.sec.here .plan-pic .pp-curl path { stroke-dashoffset: 0; }
html[data-clock="2"] .pp-watch, html[data-clock="3"] .pp-watch { display: none; }
html[data-clock="2"] .pp-swans { display: block; }
html[data-clock="3"] .pp-curl { display: block; }

/* Draft layouts of the timeline (data-plan on <html>): 1 medallions on a gold line (above), 2 a gold thread down the middle,
   3 little cards that slide in from alternate sides, 4 a zigzag either side of the line. Each step still arrives after the last. */
html[data-plan="2"] .plan::before { display: none; }
html[data-plan="2"] .plan li { grid-template-columns: 1fr; justify-items: center; gap: 6px; min-height: 0; padding: 4px 0 50px; text-align: center; }
html[data-plan="2"] .plan li:last-child { padding-bottom: 0; }
html[data-plan="2"] .plan time { justify-self: center; order: -1; font-size: 34px; }
html[data-plan="2"] .plan li::after { content: ""; position: absolute; left: 50%; bottom: 8px; width: 1px; height: 34px; transform: scaleY(0); transform-origin: 50% 0;
  background: linear-gradient(var(--gold-2), rgba(201, 165, 94, .2)); transition: transform .9s ease; transition-delay: calc(1.1s + var(--k) * .6s); }
html[data-plan="2"] .plan li:last-child::after { display: none; }
html[data-plan="2"] .sec.here .plan li::after { transform: none; }

html[data-plan="3"] .plan::before { display: none; }
html[data-plan="3"] .plan li { grid-template-columns: 74px 1fr 50px; gap: 10px; min-height: 0; margin: 0 0 14px; padding: 14px 14px 14px 10px; border-radius: 3px;
  background: var(--card); box-shadow: 0 0 0 1px rgba(201, 165, 94, .55), 0 0 0 4px var(--card), 0 0 0 5px rgba(201, 165, 94, .28), 0 14px 22px -16px rgba(60, 40, 20, .5);
  transform: translateX(var(--from, -46px)); }
html[data-plan="3"] .plan li:nth-child(even) { --from: 46px; }
html[data-plan="3"] .plan time { justify-self: center; font: 400 34px/1 var(--f-script); }
html[data-plan="3"] .plan-dot { order: 3; width: 46px; height: 46px; box-shadow: none; background: none; }
html[data-plan="3"] .plan-dot img { width: 42px; height: 42px; }

html[data-plan="4"] .plan::before { left: 50%; }
html[data-plan="4"] .plan li { grid-template-columns: 1fr 66px 1fr; grid-template-areas: "t d ." "x d ."; column-gap: 12px; min-height: 0; padding: 10px 0; text-align: right; }
html[data-plan="4"] .plan li:nth-child(even) { grid-template-areas: ". d t" ". d x"; text-align: left; }
html[data-plan="4"] .plan time { grid-area: t; justify-self: stretch; align-self: end; font-size: 27px; }
html[data-plan="4"] .plan-dot { grid-area: d; align-self: center; }
html[data-plan="4"] .plan-txt { grid-area: x; align-self: start; }
html[data-plan="4"] .plan p { font-size: 19px; }
html[data-plan="4"] .plan small { font-size: 15px; }
html[data-plan="4"] .plan li { transform: translateX(var(--from, -30px)); }
html[data-plan="4"] .plan li:nth-child(even) { --from: 30px; }

/* ---------- Place: folded map ---------- */
.sub { margin: 0 auto; max-width: 30ch; text-align: center; font: italic 400 17px/1.4 var(--f-display); color: var(--muted); }
.fold { --w: 33.3334%; position: relative; width: min(100%, 360px, calc(var(--vu, 1svh) * 42)); aspect-ratio: 3 / 4; margin: calc(var(--vu, 1svh) * 3) auto calc(var(--vu, 1svh) * 3); perspective: 1600px; }
.fold::before { content: ""; position: absolute; top: 3%; bottom: -2%; left: calc(50% - var(--w) / 2); width: var(--w); background: rgba(60, 48, 28, .32); filter: blur(14px); }
.fold-track { position: absolute; inset: 0; transform-style: preserve-3d; }
.panel { position: absolute; top: 0; width: 33.3334%; height: 100%; transform-style: preserve-3d; }
.panel .panel { left: 100%; width: 100%; transform-origin: 0 50%; }
.pf, .pb { position: absolute; inset: 0; -webkit-backface-visibility: hidden; backface-visibility: hidden; }
.pf { background: url("../img/map.webp") no-repeat; background-size: 300% 100%; }
.pb { background: #EDE3D0 url("../img/liner.webp") center / 220px auto; transform: rotateY(180deg); }
/* Safari shows back faces anyway: the backs that never turn towards us are switched off, the middle panel is swapped in JS. */
.p1 > .pb, .p3 > .pb { visibility: hidden; }
.pshade { position: absolute; inset: 0; background: #1D1A26; opacity: 0; }
.pin-wrap { position: absolute; left: 57.5%; top: 8%; z-index: 5; width: 15%; transform: translate(-50%, -50%); opacity: 0; pointer-events: none; }
.pin-wrap img { width: 100%; filter: drop-shadow(0 4px 4px rgba(60, 40, 10, .4)); }
.pin-wrap.dropped { animation: drop .75s cubic-bezier(.3, .8, .4, 1) forwards; }
.pin-wrap.dropped::after { content: ""; position: absolute; inset: -20%; border-radius: 50%; border: 1.5px solid var(--gold-2); animation: ring 1s ease-out .4s both; }
@keyframes drop {
  0% { opacity: 0; transform: translate(-50%, -170%) scale(2.3); }
  55% { opacity: 1; transform: translate(-50%, -50%) scale(.9); }
  78% { transform: translate(-50%, -50%) scale(1.06); }
  100% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}
@keyframes ring { from { transform: scale(.4); opacity: .9; } to { transform: scale(2.3); opacity: 0; } }
.actions { display: flex; justify-content: center; }

/* ---------- Dress code: watercolour palette ---------- */
.pantones { position: relative; display: grid; gap: 4px; margin: calc(var(--vu, 1svh) * 2.4) 0 4px; }
/* Each family of colours on its own line, four to a line, always fitting the screen. */
.pt-row { display: grid; gap: 6px; }
.pt-cap { margin: 0; text-align: center; font: italic 500 16px/1.2 var(--f-display); color: var(--ink); }
.pt-line { display: flex; justify-content: center; gap: 8px; padding: 6px 0 10px; }
.pt { flex: 1 1 0; min-width: 0; max-width: 70px; box-sizing: border-box; }
.pt { position: relative; display: grid; grid-template-columns: minmax(0, 1fr); align-content: start; padding: 6px 6px 8px; border: 0; border-radius: 2px; text-align: left;
  background: #FFFDF8; color: #2E2724; box-shadow: 0 1px 2px rgba(60, 40, 20, .14), 0 12px 18px -12px rgba(60, 40, 20, .5);
  transform: rotate(var(--tilt, -1deg)); }
.pt:nth-child(3n+2) { --tilt: .8deg; }
.pt:nth-child(3n) { --tilt: -.4deg; }
.pt:nth-child(4n) { --tilt: 1.3deg; }
/* The paint is brushed on inside a clean square: the watercolour edge is drawn larger and clipped, so it never spills over the card's white frame. */
.pt-wash { position: relative; display: block; aspect-ratio: 1; border-radius: 1px; overflow: hidden; }
.pt-wash::before { content: ""; position: absolute; inset: -10px; filter: url(#wc);
  background: radial-gradient(120% 95% at 38% 32%, color-mix(in srgb, var(--c) 62%, #fff) 0%, var(--c) 52%, color-mix(in srgb, var(--c) 84%, #3A2A20) 100%), var(--grain), var(--c); }
.pt-label { display: grid; gap: 1px; padding: 7px 2px 0; }
.pt-label b { font: 700 10.5px/1 var(--f-body); letter-spacing: .01em; }
.pt-label b sup { font-size: .6em; }
.pt-label i { font: normal 500 8.5px/1.25 var(--f-body); color: #5E5450; }
.pt-label span { font: italic 500 13px/1.15 var(--f-display); color: var(--ink); hyphens: auto; overflow-wrap: anywhere; }
/* 2 — a swatch fan opened from one corner; the names run up the uncovered edge of each strip. */
html[data-pal8="2"] .pantones { display: block; height: 330px; max-width: none; margin: 28px -10px 34px; }
html[data-pal8="2"] :is(.pt-row, .pt-line) { display: contents; }
html[data-pal8="2"] .pt-cap { display: none; }
html[data-pal8="2"] .pt { position: absolute; left: 50%; bottom: 0; width: 64px; height: 250px; margin-left: -32px; padding: 5px; z-index: var(--k);
  transform-origin: 50% 94%; transform: rotate(calc((var(--k) - 5.5) * 6.6deg)); }
html[data-pal8="2"] .pt { display: block; }
html[data-pal8="2"] .pt-wash { position: absolute; inset: 5px; aspect-ratio: auto; }
html[data-pal8="2"] .pt-label { position: absolute; left: 8px; top: 12px; padding: 5px 2px; writing-mode: vertical-rl; transform: rotate(180deg); background: rgba(255, 253, 248, .92); border-radius: 1px; }
html[data-pal8="2"] .pt-label span { font-size: 12px; }
html[data-pal8="2"] .pt-label i, html[data-pal8="2"] .pt-label b { display: none; }
/* 3 — loose drops of paint with the name beneath. */
html[data-pal8="3"] .pt-line { gap: 6px; }
html[data-pal8="3"] .pt { padding: 0; background: none; box-shadow: none; transform: none; justify-items: center; text-align: center; }
html[data-pal8="3"] .pt-wash { overflow: visible; filter: url(#wc); }
html[data-pal8="3"] .pt-wash::before { inset: 0; filter: none; border-radius: inherit; }
html[data-pal8="3"] .pt-wash { width: min(100%, 66px); border-radius: 47% 53% 44% 56% / 52% 45% 55% 48%; }
html[data-pal8="3"] .pt:nth-child(3n+2) .pt-wash { border-radius: 55% 45% 50% 50% / 46% 56% 44% 54%; }
html[data-pal8="3"] .pt:nth-child(3n) .pt-wash { border-radius: 44% 56% 58% 42% / 50% 48% 52% 50%; }
html[data-pal8="3"] .pt-label b, html[data-pal8="3"] .pt-label i { display: none; }

/* The looks: watercolour figures for the ladies and the gentlemen; a touch opens one large. */
.looks { display: grid; gap: calc(var(--vu, 1svh) * 1.6); margin: calc(var(--vu, 1svh) * 2) 0 4px; }
.look { margin: 0; display: grid; justify-items: center; gap: 10px; }
.look-pic { display: block; width: calc(100% + 24px); margin: 0 -12px; padding: 0; border: 0; background: none; cursor: zoom-in; -webkit-tap-highlight-color: transparent; }
.look-pic img { width: 100%; height: auto; max-height: calc(var(--vu, 1svh) * 27); object-fit: contain; }
.look-note { max-width: 19em; margin: 2px auto 0; text-align: center; font: italic 500 18px/1.45 var(--f-display); color: var(--ink); text-wrap: balance; }
.lightbox { position: fixed; inset: 0; z-index: 60; display: grid; place-items: center; padding: 16px; background: rgba(40, 28, 20, .82); cursor: zoom-out; }
.lightbox[hidden] { display: none; }
.lightbox img { max-width: 100%; max-height: 100%; object-fit: contain; border-radius: 3px; background: #FBF6EC; box-shadow: 0 20px 60px rgba(0, 0, 0, .5); }

/* ---------- Little envelopes ---------- */
.menvs { display: grid; gap: calc(var(--vu, 1svh) * 2); margin-top: calc(var(--vu, 1svh) * 2.6); }
.menv-wrap { padding-top: 0; transition: padding-top .8s cubic-bezier(.3, .7, .2, 1); }
/* The letter rises over the envelope above instead of pushing the page longer: a page stays one screen. */
.menv-wrap { position: relative; }
.menv-wrap.open { z-index: 6; }
.menv { position: relative; display: block; width: 100%; max-width: min(300px, calc(var(--vu, 1svh) * 32)); aspect-ratio: 8 / 5; margin: 0 auto; padding: 0; border: 0; background: none; cursor: pointer;
  perspective: 900px; font: inherit; color: inherit; text-align: center; -webkit-tap-highlight-color: transparent; }
.menv:focus-visible { outline: 2px solid var(--gold); outline-offset: 4px; }
.menv-back { position: absolute; inset: 0; border-radius: 3px; background: #E4D9C4; box-shadow: 0 18px 30px -18px rgba(60, 48, 28, .55); }
.menv-paper { position: absolute; left: 6%; right: 6%; top: 5%; height: 90%; z-index: 2; box-sizing: border-box; padding: 14px 14px; display: grid; align-content: start; gap: 4px;
  background: #FFFDF8; border-radius: 2px; box-shadow: 0 1px 4px rgba(60, 48, 28, .15);
  transition: transform .75s cubic-bezier(.3, .7, .2, 1) 0s; }
.menv-paper b { justify-self: center; padding: .12em .3em .06em; margin: -.12em 0 -.06em; font: 400 27px/1 var(--f-script); color: var(--ink); }
.menv-paper > span { font: italic 500 14.5px/1.34 var(--f-display); color: #4A1622; }
/* The guest-chat button inside the letter: only reachable once the letter is out of its envelope. */
.menv-go { justify-self: center; margin-top: 4px; padding: 6px 16px; border-radius: 999px; background: var(--title); color: var(--ivory);
  font: 500 12.5px/1 var(--f-body); text-decoration: none; letter-spacing: .02em; pointer-events: none; box-shadow: 0 4px 10px -6px rgba(60, 20, 30, .6); }
.menv-wrap.open .menv-go { pointer-events: auto; }
.menv-go:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.menv-wrap.open .menv-paper { animation: letterOut 1.3s cubic-bezier(.3, .7, .2, 1) .35s both; }
/* The letter slides up out of its pocket, then comes forward and lies on top of its own envelope, slightly raised, so it never
   covers the heading above. */
@keyframes letterOut {
  0% { transform: none; z-index: 2; }
  48% { transform: translateY(-62%); z-index: 2; }
  52% { transform: translateY(-60%) scale(1.02); z-index: 8; box-shadow: 0 14px 26px -12px rgba(60, 40, 20, .5); }
  100% { transform: translateY(-6%) scale(1.03); z-index: 8; box-shadow: 0 16px 30px -12px rgba(60, 40, 20, .55); }
}
/* «Письма для Вас»: the envelopes stay small so three fit one screen, but a letter is as wide as the column and as tall as its
   words, so nothing is cut. It starts small inside its envelope, rises out and opens to full size (transform only), and lies
   centred on its envelope; site.js (fitLetter) gives the row room above and below and sets --ly, where it settles. */
#notes .menvs { container-type: inline-size; }
#notes .menv-wrap { transition: padding .9s cubic-bezier(.3, .7, .2, 1); }
#notes .menv-paper { left: 50%; right: auto; width: min(300px, 100cqw); margin-left: calc(min(300px, 100cqw) / -2); height: auto; min-height: 90%;
  padding: 12px 16px 14px; opacity: 0; }
#notes .menv-wrap.open .menv-paper { animation: letterWide 1.5s cubic-bezier(.3, .7, .2, 1) .35s both; }
@keyframes letterWide {
  0% { opacity: 0; transform: translateY(0) scale(.7); z-index: 2; }
  18% { opacity: 1; }
  46% { opacity: 1; transform: translateY(-30%) scale(.72); z-index: 2; }
  52% { transform: translateY(-28%) scale(.75); z-index: 8; box-shadow: 0 14px 26px -12px rgba(60, 40, 20, .5); }
  100% { opacity: 1; transform: translateY(var(--ly, -6%)) scale(1); z-index: 8; box-shadow: 0 16px 30px -12px rgba(60, 40, 20, .55); }
}
.menv-pocket { position: absolute; inset: 0; z-index: 3; border-radius: 3px;
  clip-path: polygon(0 0, 50% 56%, 100% 0, 100% 100%, 0 100%);
  background:
    linear-gradient(to top right, transparent 49.4%, rgba(130, 110, 80, .24) 50%, transparent 50.6%) left bottom / 50% 66% no-repeat,
    linear-gradient(to top left, transparent 49.4%, rgba(130, 110, 80, .24) 50%, transparent 50.6%) right bottom / 50% 66% no-repeat,
    linear-gradient(to bottom left, transparent 49.6%, rgba(90, 62, 30, .2) 50.2%, transparent 54%) left top / 50% 56% no-repeat,
    linear-gradient(to bottom right, transparent 49.6%, rgba(90, 62, 30, .2) 50.2%, transparent 54%) right top / 50% 56% no-repeat,
    var(--env, none) 50% 50% / var(--env-size, 100% 100%) no-repeat, #F7F0E3; }
/* Draft envelopes (data-env on <html>): 1 watercolour peonies, each envelope its own sheet (the flap shows the top of it);
   2 the blue toile of the main envelope; 3 plain cream; 4 an old tea-stained letter. */
html[data-env="1"] .menvs > .menv-wrap:nth-child(1) .menv { --env: url("../img/envelope-1.webp"); }
html[data-env="1"] .menvs > .menv-wrap:nth-child(2) .menv { --env: url("../img/envelope-2.webp"); }
html[data-env="1"] .menvs > .menv-wrap:nth-child(3) .menv { --env: url("../img/envelope-3.webp"); }
html[data-env="1"] .sent .menv { --env: url("../img/envelope-4.webp"); }
html[data-env="2"] .menv { --env: url("../img/env-c.webp"); --env-size: cover; --flap-size: cover; }
html[data-env="4"] .menv { --env: url("../img/paper-3.webp"); --env-size: cover; --flap-size: cover; }
/* The name sits on a small ivory plate with a gold rule, so it reads on any envelope paper. */
.menv-label { position: absolute; left: 50%; bottom: 6%; z-index: 4; transform: translateX(-50%); padding: 7px 18px 5px; white-space: nowrap; pointer-events: none;
  background: rgba(255, 251, 243, .95); border: 1px solid rgba(190, 152, 84, .75); border-radius: 2px;
  box-shadow: 0 0 0 3px rgba(255, 251, 243, .7), 0 6px 14px -8px rgba(60, 40, 20, .45); }
.menv-label b { display: block; padding: .08em .2em; font: 400 29px/1 var(--f-script); }
.menv-flap { position: absolute; left: 0; right: 0; top: 0; height: 58%; z-index: 5; transform-origin: 50% 0; transform-style: preserve-3d;
  transition: transform .7s cubic-bezier(.5, .05, .3, 1) .45s, z-index 0s .78s; }
.menv-wrap.open .menv-flap { transform: rotateX(180deg); z-index: 1; transition: transform .7s cubic-bezier(.5, .05, .3, 1) 0s, z-index 0s .33s; }
.flap-f, .flap-b { position: absolute; inset: 0; -webkit-backface-visibility: hidden; backface-visibility: hidden; }
.flap-f { clip-path: polygon(0 0, 100% 0, 50% 100%); background: linear-gradient(to bottom, rgba(255, 252, 244, .25), rgba(120, 90, 50, .1)), var(--env, none) 50% 0 / var(--flap-size, 100% 172.4%) no-repeat, #F4EBDB; }
.flap-b { clip-path: polygon(0 100%, 100% 100%, 50% 0); background: #E9DFCB url("../img/liner.webp") center / 200px auto; transform: rotateX(180deg); }
/* Faces swap when the flap is edge-on (≈0.29 s into its turn), because Safari ignores backface-visibility here. */
.flap-f, .menv-flap img { visibility: visible; transition: visibility 0s .74s; }
.flap-b { visibility: hidden; transition: visibility 0s .74s; }
.menv-wrap.open .flap-f, .menv-wrap.open .menv-flap img { visibility: hidden; transition: visibility 0s .29s; }
.menv-wrap.open .flap-b { visibility: visible; transition: visibility 0s .29s; }
/* Once open, the raised flap melts away, so it never stands over the heading above. */
#notes .menv-wrap.open .flap-b { animation: flapAway .7s ease .75s both; }
@keyframes flapAway { to { opacity: 0; } }
.menv-flap img { position: absolute; left: 50%; top: 100%; width: 17%; transform: translate(-50%, -50%) translateZ(1px);
  -webkit-backface-visibility: hidden; backface-visibility: hidden; filter: drop-shadow(0 3px 3px rgba(60, 40, 10, .35)); }

/* ---------- RSVP ---------- */
/* Once the film is over: a quiet note that the whole invitation can now be leafed through by hand. */
.after-note { max-width: 19em; margin: calc(var(--vu, 1svh) * 3) auto 0; text-align: center; font: italic 500 16.5px/1.45 var(--f-display); color: var(--muted); text-wrap: balance;
  opacity: 0; transform: translateY(12px); transition: opacity 1.6s ease .6s, transform 1.8s cubic-bezier(.16, 1, .3, 1) .6s; }
html.unlocked .after-note { opacity: 1; transform: none; }
.an-arrows { display: block; width: 14px; height: 30px; margin: 0 auto 8px; background:
  linear-gradient(var(--gold-2), var(--gold-2)) 50% 50% / 1px 22px no-repeat,
  conic-gradient(from 135deg at 50% 0, transparent 0 90deg, transparent 0) ; position: relative; }
.an-arrows::before, .an-arrows::after { content: ""; position: absolute; left: 3px; width: 7px; height: 7px; border: solid var(--gold-2); border-width: 1px 1px 0 0; }
.an-arrows::before { top: 1px; transform: rotate(-45deg); }
.an-arrows::after { bottom: 1px; transform: rotate(135deg); }
html.unlocked .an-arrows { animation: anFloat 3.2s ease-in-out 2s infinite; }
@keyframes anFloat { 50% { transform: translateY(-4px); } }
.rsvp-card { position: relative; max-width: 360px; margin: 28px auto 0; padding: 30px 22px 26px; box-sizing: border-box; background: var(--card); border-radius: 3px;
  box-shadow: 0 30px 50px -30px rgba(60, 48, 28, .45), 0 0 0 1px rgba(170, 150, 110, .2);
  transform-origin: 50% 100%; transition: transform .8s cubic-bezier(.5, 0, .3, 1), opacity .6s ease; }
.rsvp-card.away { transform: perspective(900px) rotateX(55deg) translateY(30%) scale(.55); opacity: 0; }
.rsvp-card.shake { animation: shake .45s; }
@keyframes shake { 20%, 60% { transform: translateX(-6px); } 40%, 80% { transform: translateX(6px); } }
.field { display: grid; gap: 4px; margin: 0 0 20px; min-width: 0; padding: 0; border: 0; text-align: left; }
.field > label, .field > legend { padding: 0; font: 600 12px var(--f-display); letter-spacing: .22em; text-transform: uppercase; color: var(--gold); }
.field input[type="text"], .field textarea {
  width: 100%; box-sizing: border-box; padding: 6px 2px; border: 0; border-bottom: 1px solid var(--line); border-radius: 0; outline: none;
  background: transparent; font: 400 19px/1.35 var(--f-display); color: var(--ink); resize: none; transition: border-color .3s;
}
.field input[type="text"]:focus, .field textarea:focus { border-bottom-color: var(--gold); }
.field ::placeholder { color: #A39C8D; font-style: italic; }
.choices { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 6px; }
.chip { position: relative; }
.chip input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.chip span { display: inline-block; padding: 8px 14px; border: 1px solid var(--line); border-radius: 999px; cursor: pointer;
  font: italic 400 16.5px var(--f-display); color: var(--ink); transition: background .25s, border-color .25s, color .25s; }
.chip input:checked + span { background: var(--ink); border-color: var(--ink); color: var(--ivory); font-style: normal; }
.chip input:focus-visible + span { outline: 2px solid var(--gold); outline-offset: 2px; }
.err { margin: -10px 0 14px; min-height: 1em; font-size: 13px; color: #9B3B3B; }
.submit { width: 100%; margin-top: 4px; background: linear-gradient(180deg, #B8904A, #96712F); color: var(--ivory); }
.submit img { width: 22px; height: auto; filter: drop-shadow(0 1px 1px rgba(0, 0, 0, .3)); }
.deadline { margin: 14px 0 0; text-align: center; font: italic 400 15px var(--f-display); color: var(--muted); }
.sent { display: grid; justify-items: center; gap: 14px; margin-top: 30px; text-align: center; }
.sent[hidden] { display: none; }
.sent .menv-wrap { width: 100%; }
.sent .menv { cursor: default; animation: float 4.5s ease-in-out infinite; }
.sent .menv-flap img { opacity: 0; transform: translate(-50%, -50%) translateZ(1px) scale(2.4); transition: opacity .25s, transform .45s cubic-bezier(.3, 1.5, .5, 1); }
.sent.stamped .menv-flap img { opacity: 1; transform: translate(-50%, -50%) translateZ(1px) scale(1); }
.sent.stamped .menv-back { animation: thud .45s .12s; }
.sent.no-trans * { transition: none !important; }
@keyframes thud { 35% { transform: translateY(3px) scale(.985); } }
@keyframes float { 50% { transform: translateY(-6px) rotate(-.6deg); } }
.sent-text { display: grid; gap: 6px; opacity: 0; transform: translateY(8px); transition: opacity .8s ease, transform .8s ease; }
.sent.thanked .sent-text { opacity: 1; transform: none; }
.sent h3 { display: inline-block; margin: -.12em 0 0; padding: .12em .3em .06em; font: 400 48px/1 var(--f-script); color: var(--ink); }
.sent p { margin: 0 auto; max-width: 28ch; font: italic 400 18px/1.4 var(--f-display); color: var(--muted); }
.link-btn { margin-top: 6px; padding: 4px; border: 0; background: none; cursor: pointer; font: italic 400 16px var(--f-display); color: var(--ink-soft); text-decoration: underline; text-underline-offset: 3px; }

/* ---------- Finale: night again ---------- */
.finale { position: relative; min-height: calc(var(--vu, 1svh) * 100); overflow: hidden; background: var(--night); color: var(--ivory); text-align: center; -webkit-tap-highlight-color: transparent; }
.finale-bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 50% 0; }
.finale::before { content: ""; position: absolute; top: -1px; left: 0; right: 0; height: 44px; z-index: 2; background: var(--paper-bg);
  -webkit-mask: var(--deckle-down) bottom / 100% 44px no-repeat; mask: var(--deckle-down) bottom / 100% 44px no-repeat; }
.sky { position: absolute; inset: 0; z-index: 1; width: 100%; height: 100%; }
.finale-inner { position: relative; z-index: 3; display: grid; justify-items: center; gap: 8px; padding-top: calc(var(--vu, 1svh) * 15); pointer-events: none; }
.finale-inner a, .finale-inner button { pointer-events: auto; }
.finale .kicker { color: var(--champagne); }
.finale h2 { margin: 0; font: 400 66px/1 var(--f-script); text-shadow: 0 0 18px var(--glow), 0 2px 10px rgba(10, 12, 40, .5); }
.finale .when { margin: 4px 0 0; font: 600 13px var(--f-display); letter-spacing: .34em; padding-left: .34em; text-transform: uppercase; text-shadow: 0 1px 8px rgba(10, 12, 40, .6); }
.finale .sign { margin: 14px 0 0; font: italic 400 20px var(--f-display); text-shadow: 0 1px 8px rgba(10, 12, 40, .6); }
/* On a phone the picture is as tall as the screen and the palace begins little more than a third of the way down: the words
   sit higher, each line stays one line, and a soft night shade behind them keeps them readable over the pink clouds. */
@media (max-width: 600px) {
  .finale-inner { padding-top: max(58px, calc(var(--vu, 1svh) * 8)); gap: 6px; }
  .finale h2 { font-size: min(66px, 15.5vw); white-space: nowrap; }
  .finale .when { font-size: clamp(10.5px, 3vw, 13px); letter-spacing: .24em; padding-left: .24em; white-space: nowrap; }
  .finale .sign { margin-top: 8px; font-size: 18px; }
  .finale::after { content: ""; position: absolute; left: 0; right: 0; top: 40px; height: 58%; z-index: 2; pointer-events: none;
    background: radial-gradient(120% 60% at 50% 22%, rgba(16, 18, 52, .5), rgba(16, 18, 52, .22) 55%, rgba(16, 18, 52, 0) 78%); }
}
.foot-mark { position: absolute; left: 0; right: 0; bottom: calc(18px + env(safe-area-inset-bottom, 0px)); z-index: 3; margin: 0; font: 400 30px/1 var(--f-script); color: var(--ink); pointer-events: none; }
.foot-mark small { display: block; margin-top: 6px; font: 600 11px var(--f-display); letter-spacing: .4em; padding-left: .4em; color: var(--gold); }

/* ---------- Overlays ---------- */
.progress { position: fixed; z-index: 30; top: 30vh; height: 40vh; width: 14px; right: calc(max(0px, (100vw - var(--col)) / 2) + 6px);
  opacity: 0; transition: opacity .6s ease; pointer-events: none; }
.progress.on { opacity: 1; }
.progress i { position: absolute; left: 50%; top: 0; bottom: 0; width: 1px; background: linear-gradient(var(--gold-2), rgba(201, 165, 94, .15)); }
.progress img { position: absolute; left: 50%; top: 0; width: 18px; transform: translate(-50%, -50%); filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .3)); }
.sparkles { position: fixed; inset: 0; z-index: 40; width: 100%; height: 100%; pointer-events: none; }

@media (prefers-reduced-motion: reduce) {
  .seal, .hint span, .swan img, .sent .menv, .cue i::after, .hero.ready .seal :is(.halo, .echo, .glint b), .music-tg i { animation: none !important; }
  .plan li, .plan-dot, .plan::before { transform: none; opacity: 1; transition: none; }
  .epi-text .ch { opacity: 1; }
  .flow .w { opacity: 1; transform: none; transition: none; }
  .title.wr { -webkit-mask: none; mask: none; }
  .sec .kicker::before, .sec .kicker::after { transform: none; }
}
