/* ==========================================================================
   Tanvi & Niral: one column (a phone's width, at most 480px), one full-screen
   scene per page. --u is one PDF point at the column's width (the PDF page
   is 595pt wide), so artwork keeps the designer's proportions.
   ========================================================================== */

:root {
  --col: min(100vw, 480px);
  --serif: 'Caladea', Cambria, Georgia, serif;
  --display: 'Gloock', 'Playfair Display', Georgia, serif;
  --gujarati: 'Hind Vadodara', 'Noto Sans Gujarati', sans-serif;
  --ease-out: cubic-bezier(.2, .7, .2, 1);
}

*, *::before, *::after { box-sizing: border-box; }
/* The page itself never scrolls: main.js moves the scenes on a one-screen
   stage, so there is no scroll position to restore, snap or resize */
html, body { height: 100%; overflow: hidden; overscroll-behavior: none; }
html { -webkit-text-size-adjust: 100%; }
html.is-booting body { visibility: hidden; }
body {
  margin: 0;
  background: #1e1214;
  font-family: var(--serif);
  -webkit-font-smoothing: antialiased;
}
p { margin: 0; }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
.noscript { color: #f3e6cc; text-align: center; padding: 40vh 24px; }

/* ---------- Column and scenes ---------- */

.invite {
  position: relative;
  width: var(--col);
  height: 100vh;
  height: 100dvh;                 /* the screen as it is: nothing scrolls, so it holds still */
  margin: 0 auto;
  overflow: hidden;
  touch-action: none;             /* swipes are the pager's, not the browser's */
  container-type: inline-size;
  box-shadow: 0 0 80px rgba(0, 0, 0, .5);
  opacity: 0;
  transition: opacity .9s ease;
}
.invite.is-open { opacity: 1; }

.scene {
  --u: calc(100cqw / 595);
  /* stacked on the stage; main.js places each one with a transform */
  position: absolute;
  top: 0; left: 0; right: 0;
  isolation: isolate;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  /* exactly one screen (the stage, measured by main.js): the artwork at
     the top and bottom edges always shows whole */
  height: var(--stage-h, 100vh);
  padding: calc(88 * var(--u) * var(--k, 1)) 0 calc(96 * var(--u) * var(--k, 1));
  will-change: transform;
}

/* The arrow at the bottom of every page (main.js): next page, or from the
   last page, back to the start. A soft disc keeps it legible on any art. */
.cue {
  position: fixed; z-index: 30;
  left: 50%; bottom: max(14px, env(safe-area-inset-bottom));
  translate: -50% 0;
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border-radius: 50%;
  color: #3a1d22;
  background: rgba(255, 249, 236, .72);
  box-shadow: 0 2px 10px rgba(0, 0, 0, .25);
  opacity: 0; pointer-events: none;
  transition: opacity .8s ease .6s;
  -webkit-tap-highlight-color: transparent;
}
.invite.is-open ~ .cue { opacity: 1; pointer-events: auto; }
.cue[hidden] { display: none; }
.cue svg { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; animation: nudge 2s ease-in-out infinite; transition: rotate .4s ease; }
.cue.is-back svg { rotate: 180deg; animation-name: nudge-up; }
@keyframes nudge-up { 50% { translate: 0 -6px; } }

/* Page dots on the column's right edge: where you are, and a way to jump */
.dots {
  position: fixed; z-index: 30;
  right: calc((100vw - var(--col)) / 2 + 6px);
  top: 50%; translate: 0 -50%;
  display: flex; flex-direction: column; align-items: center;
  opacity: 0; pointer-events: none;
  transition: opacity .8s ease .6s;
}
.invite.is-open ~ .dots { opacity: 1; pointer-events: auto; }
.dots button { width: 22px; height: 20px; display: grid; place-items: center; }
.dots button::before {
  content: ''; width: 6px; height: 6px; border-radius: 3px;
  background: rgba(255, 250, 238, .6);
  box-shadow: 0 0 0 1px rgba(40, 18, 22, .35), 0 1px 4px rgba(0, 0, 0, .3);
  transition: height .4s var(--ease-out), background-color .4s;
}
.dots button[aria-current='page']::before { height: 16px; background: #fffaee; }

/* Stacked cards (main.js slides each scene up over the last, and sets the
   covered one's scale and shade) */
.scene + .scene { box-shadow: 0 -18px 40px rgba(0, 0, 0, .35); }
.scene__shade {
  position: absolute; inset: 0; z-index: 20;
  background: #120a0c;
  opacity: 0;
  pointer-events: none;
}

.bg { position: absolute; inset: 0; z-index: -1; }
.bg--cover { background: center / cover no-repeat; }

/* Artwork, placed in page points and pinned to the top or bottom edge.
   On a short screen main.js shrinks it (--k below 1) towards the edges it
   hugs (scenes.js side()), so the text gets more room. */
.layer {
  position: absolute;
  z-index: 1;
  left: calc((297.5 + (var(--x) - 297.5) * var(--k, 1)) * var(--u));
  width: calc(var(--w) * var(--u) * var(--k, 1));
  height: calc(var(--h) * var(--u) * var(--k, 1));
  pointer-events: none;
}
.layer--l { left: calc(var(--x) * var(--u)); }
.layer--r { left: auto; right: calc((595 - var(--x) - var(--w)) * var(--u) * var(--k, 1)); }
.layer--full { --k: 1; }
.layer--top { top: calc(var(--y) * var(--u) * var(--k, 1)); }
.layer--bottom { bottom: calc((842 - var(--y) - var(--h)) * var(--u) * var(--k, 1)); }
.layer img { display: block; width: 100%; height: 100%; }
.layer.is-mirrored { scale: -1 1; }

/* The text card: fills the space between the margins, text centred.
   --clear-top / --clear-bottom (page points from that edge) mark how far
   the scene's artwork reaches: the text stays out of those bands, and on a
   short screen the scene grows taller rather than run text over the art. */
.panel {
  flex: 1;
  width: 84%;
  margin-inline: auto;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  padding: 28px 16px;
  padding-top: max(28px, calc((var(--clear-top, 0) - 88) * var(--u) * var(--k, 1) + 14px));
  padding-bottom: max(28px, calc((var(--clear-bottom, 0) - 96) * var(--u) * var(--k, 1) + 14px));
  min-height: 0;                  /* may be squeezed: main.js then scales the text (--fit) */
  font-size: calc(clamp(14.5px, calc(var(--u) * 22), 17px) * var(--fit, 1));
  line-height: 1.38;
  text-wrap: balance;
}
.line { position: relative; z-index: 2; }
.rule { width: 42px; height: 1px; margin: 1.1em auto; background: currentColor; opacity: .45; }

/* ---------- Arrivals: each scene animates in once, as it settles on screen ---------- */

/* Lines rise into place one after another, once the page has settled
   (only opacity and movement: a blur would cost the phone a redraw a frame) */
.line {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 1s ease, transform 1.2s var(--ease-out);
  transition-delay: calc(var(--i, 0) * 85ms + 60ms);
}
.is-in .line { opacity: 1; transform: none; }
/* Names and titles are written in: a wipe from left to right */
.t-name, .t-title, .t-names {
  clip-path: inset(-20% 100% -20% 0);
  transition-property: opacity, transform, clip-path;
  transition-duration: 1s, 1.2s, 1.5s;
  transition-timing-function: ease, var(--ease-out), cubic-bezier(.65, 0, .35, 1);
}
.is-in .t-name, .is-in .t-title, .is-in .t-names { clip-path: inset(-20% -6% -20% -6%); }
.rule.line { transform: scaleX(0); transition-duration: .9s, 1.4s; }
.is-in .rule.line { transform: none; }

.layer[class*='enter-'] { transition: transform 1.8s var(--ease-out), opacity 1.3s ease; }
.scene:not(.is-near) .enter-fade { opacity: 0; }
.scene:not(.is-near) .enter-rise { opacity: 0; transform: translateY(14%); }
.scene:not(.is-near) .enter-drop { opacity: 0; transform: translateY(-24%); }
.scene:not(.is-near) .enter-walk-l { opacity: 0; transform: translateX(-55%); }
.scene:not(.is-near) .enter-walk-r { opacity: 0; transform: translateX(45%); }
.enter-walk-l, .enter-walk-r { transition-duration: 2.8s, 1.4s !important; }
.walk-late { transition-delay: .6s; }

/* ---------- Idle movement: two rhythms each, so nothing settles into a metronome ---------- */

/* Plants and florals: a slow sway, plus a quicker flutter in the leaves */
.idle-sway { transform-origin: 50% 100%; animation: sway 6s ease-in-out infinite alternate, flutter 3.4s ease-in-out infinite alternate; }
.sway-late .idle-sway { animation-delay: -3.5s, -1.2s; }
@keyframes sway { from { rotate: -1.6deg; } to { rotate: 1.8deg; } }
@keyframes flutter { from { transform: skewX(-1.2deg) scaleY(1); } to { transform: skewX(1deg) scaleY(1.014); } }

/* The leafy garland: drifts and ripples from where it hangs */
.idle-sway-t { transform-origin: 50% 0; animation: drift 5s ease-in-out infinite alternate, flutter 3.8s ease-in-out infinite alternate; }
@keyframes drift { from { translate: 0 0; } to { translate: 0 5px; } }

/* Chandeliers and lanterns: a pendulum from the top of the chain */
.idle-swing { transform-origin: 50% 0; animation: swing 4.2s ease-in-out infinite alternate; }
.swing-slow .idle-swing { animation-duration: 5.4s; animation-delay: -2s; }
@keyframes swing { from { rotate: -3deg; } to { rotate: 3deg; } }

@keyframes bob { from { translate: 0 0; } to { translate: 0 -1.8%; } }

/* The lady: breathing, leaning a little towards the couple */
.idle-breathe { transform-origin: 50% 100%; animation: breathe 3.6s ease-in-out infinite alternate, lean 7s ease-in-out infinite alternate; }
@keyframes breathe { from { scale: 1; } to { scale: 1.02; } }
@keyframes lean { from { rotate: -.6deg; } to { rotate: .9deg; } }

/* The elephant's heavy, swaying walk on the spot */
.idle-lumber { transform-origin: 50% 100%; animation: bob 1.6s ease-in-out infinite alternate, lumber 3.2s ease-in-out infinite alternate; }
@keyframes lumber { from { rotate: -1.3deg; } to { rotate: 1.3deg; } }

/* Deer: a regular dip of the head, as if nibbling */
.idle-graze { transform-origin: 30% 100%; animation: graze 6.5s ease-in-out infinite; }
.graze-late .idle-graze { animation-delay: -3.4s; animation-duration: 7.6s; }
@keyframes graze { 0%, 50%, 100% { rotate: 0deg; } 64% { rotate: -2.6deg; } 78% { rotate: -2.2deg; } 88% { rotate: .4deg; } }

/* Particles (scenes.js motes()) */
.motes { position: absolute; inset: 0; z-index: 1; overflow: hidden; pointer-events: none; }
.motes i { position: absolute; left: var(--x); display: block; }
.motes--dust i {
  top: 100%;
  width: calc(4px * var(--size)); aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 238, 180, .95), rgba(214, 170, 70, .55) 45%, transparent 70%);
  animation: rise var(--dur) linear var(--delay) infinite;
}
@keyframes rise {
  0% { translate: 0 0; opacity: 0; }
  12% { opacity: .85; }
  80% { opacity: .5; }
  100% { translate: var(--drift) -105svh; opacity: 0; }
}
.motes--petals i {
  top: -16px;
  width: calc(9px * var(--size)); height: calc(6px * var(--size));
  border-radius: 80% 0 80% 0;
  background: linear-gradient(135deg, #f6b3c1, #d4607c);
  animation: fall var(--dur) linear var(--delay) infinite;
}
.motes--petals i:nth-child(even) { background: linear-gradient(135deg, #ffcf6e, #ec8a22); }
@keyframes fall {
  0% { translate: 0 0; rotate: 0deg; opacity: 0; }
  8% { opacity: .7; }
  50% { translate: var(--drift) 52svh; rotate: 190deg; }
  90% { opacity: .65; }
  100% { translate: calc(var(--drift) * -.6) 105svh; rotate: 380deg; opacity: 0; }
}
.motes--glow i {
  top: var(--y);
  width: calc(8px * var(--size)); aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 242, 220, .9), rgba(255, 205, 150, .3) 45%, transparent 70%);
  animation: wander var(--dur) ease-in-out var(--delay) infinite alternate;
}
@keyframes wander {
  0% { translate: 0 0; opacity: .1; }
  50% { opacity: .7; }
  100% { translate: calc(var(--drift) * 3) calc(var(--drift) * -1); opacity: .15; }
}

/* String lights: two blurred copies pulse out of step (only opacity
   animates, so the phone's graphics chip does the work) */
.lights__glow {
  position: absolute; inset: 0;
  filter: blur(3px) brightness(2.2);
  mix-blend-mode: screen;
  animation: glow 2.3s ease-in-out infinite alternate;
}
.lights__glow--b { filter: blur(7px) brightness(2.6); animation: glow-b 3.7s ease-in-out infinite alternate; }
@keyframes glow { 0% { opacity: .2; } 35% { opacity: .75; } 50% { opacity: .4; } 100% { opacity: .9; } }
@keyframes glow-b { 0% { opacity: 0; } 60% { opacity: .55; } 100% { opacity: .15; } }

/* Glints on crystal and mirror balls */
.sparkle {
  position: absolute;
  z-index: 1;
  left: calc((297.5 + (var(--x) - 297.5) * var(--k, 1)) * var(--u));
  width: calc(var(--s) * var(--u) * 1.6 * var(--k, 1));
  aspect-ratio: 1;
  translate: -50% -50%;
  background: radial-gradient(circle, #fff 0 18%, rgba(255, 248, 225, .9) 30%, transparent 70%);
  clip-path: polygon(50% 0, 58% 42%, 100% 50%, 58% 58%, 50% 100%, 42% 58%, 0 50%, 42% 42%);
  animation: glint 3.1s ease-in-out infinite;
  animation-delay: var(--d);
  pointer-events: none;
}
.sparkle--top { top: calc(var(--y) * var(--u) * var(--k, 1)); }
.sparkle--bottom { bottom: calc((842 - var(--y)) * var(--u) * var(--k, 1)); translate: -50% 50%; }
@keyframes glint {
  0%, 70%, 100% { opacity: 0; scale: .2; rotate: 0deg; }
  82% { opacity: 1; scale: 1; rotate: 45deg; }
}

/* ---------- Patchwork scenes: cover, invitation, closing ---------- */

.scene--patchwork { --clear-bottom: 262; background: #6a9f86; color: #721b32; }   /* florals */
.scene--patchwork .panel { background: rgba(236, 217, 185, .94); }

.panel--cover { position: relative; }
/* The monogram floats, and every few seconds a band of light crosses it */
.monogram { position: relative; width: 76%; }
.monogram img { display: block; width: 100%; height: auto; }
.is-in .monogram { animation: float 5s ease-in-out infinite alternate; }
@keyframes float { from { translate: 0 0; } to { translate: 0 -7px; } }
.monogram__shine {
  position: absolute; inset: 0;
  overflow: hidden;
  -webkit-mask: url(../assets/patchwork/monogram.webp) center / 100% 100% no-repeat;
  mask: url(../assets/patchwork/monogram.webp) center / 100% 100% no-repeat;
}
.monogram__shine::before {
  content: ''; position: absolute; top: -10%; bottom: -10%; left: 0; width: 45%;
  background: linear-gradient(100deg, transparent, rgba(255, 246, 214, .75) 50%, transparent);
  translate: -120% 0;
  rotate: 12deg;
}
.is-in .monogram__shine::before { animation: shine 6.5s ease-in-out 2.4s infinite; }
@keyframes shine { 0% { translate: -120% 0; } 40%, 100% { translate: 320% 0; } }
.monogram--small { width: 34%; margin-bottom: .6em; }

@keyframes nudge { 50% { translate: 0 6px; } }

.t-invocation { font-family: var(--gujarati); color: #105e47; font-size: .9em; }
.t-blessing { margin-top: 1.4em; }
.t-host { color: #105e47; font-weight: 700; font-size: 1.25em; margin-top: .15em; }
.t-lead { margin-top: .5em; }
.t-name { font-family: var(--display); color: #105e47; font-size: 2.45em; line-height: 1.05; margin-top: .55em; }
.t-parents { color: #105e47; }
.t-with { margin: .7em 0 0; }
.t-elders-lead { font-style: italic; font-size: .9em; margin-top: 1.5em; }
.t-elders { font-size: .9em; line-height: 1.5; margin-top: .3em; }

/* ---------- Sangeet ---------- */

/* chandeliers reach 270pt down; the mirror balls rise 240pt */
.scene--sangeet { --clear-top: 274; --clear-bottom: 250; background: #3d131f; color: #e8e0de; }
.scene--sangeet .panel { width: 72%; }
.scene--sangeet .t-lead { font-size: 1.12em; margin-top: 0; }
.t-title { font-family: var(--display); font-size: 2.65em; line-height: 1.08; margin-top: .55em; }
.scene--sangeet .t-title {
  color: #fab04c;
  background: linear-gradient(100deg, #fab04c 42%, #ffe4ad 50%, #fab04c 58%) 100% 0 / 260% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: title-sheen 7s ease-in-out 2s infinite;
}
@keyframes title-sheen { 0% { background-position: 100% 0; } 55%, 100% { background-position: 0 0; } }
.t-date { font-weight: 700; font-size: 1.15em; margin-top: 1em; }
.t-time { font-size: .95em; }
.t-venue { font-weight: 700; font-size: 1.15em; margin-top: 1em; }
.t-address { font-size: .95em; }
.t-closing { font-style: italic; font-size: 1.1em; }
.scene--sangeet .t-closing { color: #fff; }

/* Disco light: three soft beams sweep slowly from the mirror balls */
.beams { position: absolute; inset: 0; z-index: 0; overflow: hidden; pointer-events: none; mix-blend-mode: screen; }
.beams i {
  position: absolute;
  left: 18%; bottom: 14%;
  width: 150%; height: 34px;
  transform-origin: 0 50%;
  background: linear-gradient(90deg, rgba(255, 226, 170, .32), rgba(255, 226, 170, .1) 45%, transparent 75%);
  filter: blur(6px);
  animation: beam 9s ease-in-out infinite alternate;
}
.beams i:nth-child(2) { animation-duration: 12s; animation-delay: -4s; background: linear-gradient(90deg, rgba(250, 176, 76, .3), rgba(250, 176, 76, .08) 45%, transparent 75%); }
.beams i:nth-child(3) { animation-duration: 10.5s; animation-delay: -7s; height: 22px; }
@keyframes beam { from { rotate: -78deg; } to { rotate: -22deg; } }
.scene:not(.is-in) .beams { opacity: 0; }
.beams { transition: opacity 2s ease 1s; }

/* ---------- Event links: add to calendar, directions ---------- */

.actions {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 10px;
  margin-top: 1.5em;
}
.action {
  display: inline-flex; align-items: center; gap: .45em;
  min-height: 40px;
  padding: .45em 1.05em .45em .85em;
  border: 1px solid var(--action-line);
  border-radius: 999px;
  background: var(--action-fill);
  color: var(--action-ink);
  font-size: .8em;
  letter-spacing: .05em;
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
  transition: background-color .25s ease, scale .2s ease;
}
.action:active { scale: .96; background: var(--action-press); }
.action svg { width: 1.25em; height: 1.25em; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.scene--sangeet { --action-ink: #fab04c; --action-line: rgba(250, 176, 76, .55); --action-fill: rgba(250, 176, 76, .06); --action-press: rgba(250, 176, 76, .18); }
.scene--milaap { --action-ink: #2a4502; --action-line: rgba(42, 69, 2, .4); --action-fill: rgba(255, 255, 255, .35); --action-press: rgba(42, 69, 2, .1); }

/* ---------- Hasta Milaap: the gold frame stretches by repeating its side panels ---------- */

/* the palanquin's flag reaches 276pt up from the bottom */
.scene--milaap { --clear-bottom: 282; background: #efe1c2; color: #2a4502; }
.frame {
  border-style: solid;
  border-color: transparent;
  border-width: calc(460 * var(--u)) calc(122.5 * var(--u)) calc(184.5 * var(--u));
  border-image: url(../assets/milaap/frame.webp) 920 245 369 fill / 1 / 0 round;
}
.sheen { overflow: hidden; mix-blend-mode: soft-light; }
.sheen::before {
  content: ''; position: absolute; top: -20%; bottom: -20%; left: 0; width: 40%;
  background: linear-gradient(100deg, transparent, rgba(255, 238, 196, .8) 50%, transparent);
  rotate: 10deg;
  animation: sheen 9s ease-in-out infinite;
}
@keyframes sheen { 0% { translate: -110% 0; } 55%, 100% { translate: 280% 0; } }

/* Petals tipping off the lady's plate (inside her layer, so they walk in with her) */
.spill { position: absolute; left: 4%; top: 31%; width: 30%; height: 10%; }
.spill i {
  position: absolute; left: 0; top: 0;
  width: 7px; height: 5px;
  border-radius: 80% 0 80% 0;
  background: linear-gradient(135deg, #f6b3c1, #c94b6b);
  opacity: 0;
  animation: spill 8.5s ease-in infinite;
  animation-delay: var(--d);
}
.spill i:nth-child(3n) { background: linear-gradient(135deg, #ffcf6e, #ec8a22); }
@keyframes spill {
  0%, 4% { opacity: 0; translate: 0 0; rotate: 0deg; }
  8% { opacity: .9; }
  60% { opacity: .8; }
  70%, 100% { opacity: 0; translate: var(--dx) 520%; rotate: 260deg; }
}
.scene--milaap .panel { width: 76%; background: rgba(239, 225, 194, .92); }
.t-shloka { font-family: var(--gujarati); font-size: .88em; line-height: 1.6; }
.scene--milaap .t-lead { margin-top: 1em; }
.scene--milaap .t-title { color: #892524; }
.t-wishes-lead { font-style: italic; font-size: .9em; }
.t-wishes { font-weight: 700; font-size: 1.15em; }

/* ---------- Closing: countdown ---------- */

.t-names { font-family: var(--display); color: #105e47; font-size: 2.2em; line-height: 1.1; }
.scene--closing .t-date { color: #105e47; margin-top: .4em; }
.countdown {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
  width: 100%;
  max-width: 300px;
  margin-top: 1.4em;
}
.countdown__unit {
  display: flex; flex-direction: column; align-items: center;
  padding: .55em 0 .45em;
  border: 1px solid rgba(114, 27, 50, .3);
  border-radius: 4px;
}
.countdown__n { font-family: var(--display); color: #105e47; font-size: 1.75em; line-height: 1; font-variant-numeric: tabular-nums; }
.countdown__n.is-ticking { animation: tick .45s var(--ease-out); }
@keyframes tick { from { opacity: .2; translate: 0 -30%; } }
.countdown__label { font-size: .68em; letter-spacing: .12em; text-transform: uppercase; margin-top: .35em; }
.t-countdown-label { font-style: italic; font-size: .9em; margin-top: .8em; }

/* ---------- Envelope ---------- */

.envelope-screen {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 34px;
  overflow: hidden;
  touch-action: none;             /* a swipe on the envelope scrolls nothing */
  overscroll-behavior: none;
  transition: opacity .7s ease;
}
.envelope-screen[hidden] { display: none; }
.envelope-screen__bg {
  position: absolute; inset: -20px; z-index: -1;
  background: url(../assets/patchwork/bg.webp) center / cover;
  filter: brightness(.5) saturate(1.05) blur(1.5px);
  animation: slow-zoom 24s ease-in-out infinite alternate;
}
@keyframes slow-zoom { to { scale: 1.08; } }
.envelope-screen.is-leaving { opacity: 0; }

.envelope {
  position: relative;
  width: min(84vw, 380px);
  aspect-ratio: 1.42;
  perspective: 1400px;
  animation: arrive 1.1s var(--ease-out) both, float 4.5s ease-in-out 1.1s infinite alternate;
}
.is-opening .envelope { animation: none; }
@keyframes arrive { from { opacity: 0; translate: 0 30px; } }
.envelope__back {
  position: absolute; inset: 0;
  background: #cdb38a;
  border-radius: 6px;
  box-shadow: 0 30px 60px rgba(0, 0, 0, .5);
}
.envelope__letter {
  position: absolute; left: 6%; right: 6%; top: 5%; height: 90%;
  z-index: 1;
  display: grid; place-items: center;
  background: #efe0c2;
  border-radius: 3px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, .2);
  transition: transform 1.2s var(--ease-out) .55s;
}
.envelope__letter img { width: 40%; }
.envelope__pocket {
  position: absolute; inset: 0;
  z-index: 2;
  display: flex; align-items: flex-end; justify-content: center;
  padding-bottom: 8%;
  background: linear-gradient(170deg, #ecd9b9, #e0c79e);
  clip-path: polygon(0 0, 50% 54%, 100% 0, 100% 100%, 0 100%);
  border-radius: 6px;
}
.envelope__names { font-family: var(--display); color: #105e47; font-size: clamp(19px, 5.6vw, 24px); }
.envelope__flap {
  position: absolute; left: 0; right: 0; top: 0; height: 58%;
  z-index: 3;
  background: linear-gradient(#e5cfa7, #d4ba8f);
  clip-path: polygon(0 0, 100% 0, 50% 100%);
  transform-origin: 50% 0;
  transition: transform .9s cubic-bezier(.4, .1, .3, 1);
}
.is-opening .envelope__flap { transform: rotateX(180deg); }
.is-flap-back .envelope__flap { z-index: 0; }
.is-opening .envelope__letter { transform: translateY(-58%); }
.is-leaving .envelope__letter { transform: translateY(-58%) scale(1.08); }

.seal {
  position: absolute; left: 50%; top: 58%;
  z-index: 4;
  width: clamp(76px, 22vw, 92px);
  aspect-ratio: 1;
  translate: -50% -50%;
  border-radius: 48% 52% 50% 50% / 51% 49% 52% 48%;
  background: radial-gradient(circle at 35% 30%, #94304b, #5c1226 60%, #3f0a19);
  box-shadow: 0 6px 16px rgba(0, 0, 0, .45), inset 0 -3px 6px rgba(0, 0, 0, .35), inset 0 2px 3px rgba(255, 255, 255, .18);
  animation: seal-breathe 2.4s ease-in-out infinite;
  transition: scale .45s ease, opacity .45s ease;
}
.seal::after {
  content: ''; position: absolute; inset: -10px; border-radius: 50%;
  border: 1.5px solid rgba(243, 230, 204, .7);
  animation: ripple 2.4s ease-out infinite;
}
.seal__wax {
  position: absolute; inset: 13%;
  display: grid; place-items: center;
  border-radius: 50%;
  background: #efe0c2;
  box-shadow: inset 0 2px 5px rgba(0, 0, 0, .4), 0 0 0 2px #c9a24a;
}
.seal__wax img { width: 82%; }
@keyframes seal-breathe { 50% { scale: 1.05; } }
@keyframes ripple { from { opacity: .9; scale: .85; } to { opacity: 0; scale: 1.35; } }
.is-opening .seal { animation: none; scale: .5; opacity: 0; pointer-events: none; }
.is-opening .seal::after { display: none; }

.envelope__hint {
  color: #f3e6cc;
  font-style: italic;
  font-size: 16px;
  letter-spacing: .03em;
  animation: hint 2.4s ease-in-out infinite;
}
@keyframes hint { 50% { opacity: .55; } }
.is-opening .envelope__hint { opacity: 0; animation: none; transition: opacity .4s; }

/* ---------- Music button ---------- */

.music {
  position: fixed;
  z-index: 60;                    /* above the envelope too */
  top: max(14px, env(safe-area-inset-top));
  right: calc((100vw - var(--col)) / 2 + 14px);
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border-radius: 50%;
  color: #f6e7c8;
  background: rgba(30, 14, 18, .72);
  box-shadow: 0 2px 10px rgba(0, 0, 0, .3);
}
.music[hidden] { display: none; }
.music__note { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.music__bars { display: none; gap: 3px; align-items: flex-end; height: 16px; }
.music__bars i { width: 3px; height: 100%; background: currentColor; border-radius: 1px; animation: bar 1s ease-in-out infinite alternate; }
.music__bars i:nth-child(2) { animation-delay: -.4s; }
.music__bars i:nth-child(3) { animation-delay: -.7s; }
@keyframes bar { from { scale: 1 .3; } to { scale: 1 1; } }
.music.is-playing .music__note { display: none; }
.music.is-playing .music__bars { display: flex; }
.music__bars i { transform-origin: 50% 100%; }

/* ---------- Less motion ---------- */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .line, .layer { opacity: 1 !important; transform: none !important; filter: none !important; clip-path: none !important; }
  .scene__shade, .beams, .spill { display: none; }
}
