:root {
  --night: #120c1e;
  --night-deep: #0a0715;
  --candle: #f3c26b;
  --candle-soft: #f9dfa6;
  --rose: #e3a1b0;
  --paper: #f4e9db;
  --ink: #2b1f38;
  --text: #efe5ee;
  --muted: #b4a5c4;

  --display: "Bodoni Moda", "Didot", Georgia, serif;
  --body: "Hanken Grotesk", system-ui, sans-serif;
  --hand: "Nothing You Could Do", "Segoe Print", cursive;
  --script: "Pinyon Script", "Bodoni Moda", cursive;
  --typed: "Special Elite", "Courier New", monospace;
  --oldbook: "IM Fell English", Georgia, serif;

  --ease-out: cubic-bezier(.2, .7, .2, 1);
  --glow: 0 0 24px rgba(10, 7, 21, .95), 0 0 6px rgba(10, 7, 21, .9);
  --room: radial-gradient(70% 55% at 50% 50%, #3a2440 0%, #1c1229 58%, #0b0714 100%);
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  height: 100svh;
  overflow: hidden;
  background: var(--night-deep);
  color: var(--text);
  font-family: var(--body);
  font-size: 1.0625rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overscroll-behavior: none;
  -webkit-tap-highlight-color: transparent;
  touch-action: none;
}
button { font: inherit; color: inherit; }
/* Text can be highlighted and copied; only the things she drags or taps can't. */
::selection { background: rgba(243, 194, 107, .4); color: #fff; }
.clock, .final, .countdown__zero, .gate__candle, .cake, .match, .sound-btn, .turn-hint, .tap-hint, canvas { user-select: none; -webkit-user-select: none; }
:focus-visible { outline: 2px solid var(--candle); outline-offset: 4px; border-radius: 4px; }
[hidden] { display: none !important; }

/* Each part is a full-screen layer that fades in with .is-on */
.gate, .act {
  position: fixed;
  inset: 0;
  opacity: 0;
  visibility: hidden;
  transition: opacity 1s ease, visibility 0s linear 1s;
}
.gate.is-on, .act.is-on { opacity: 1; visibility: visible; transition: opacity 1s ease, visibility 0s; }


.narration {
  position: fixed;
  left: 0; right: 0;
  bottom: max(30px, 5.5svh);
  z-index: 8;
  margin: 0;
  padding: 0 24px;
  text-align: center;
  font-family: var(--display);
  font-style: italic;
  font-size: clamp(1.1rem, 3.3vw, 1.55rem);
  line-height: 1.3;
  color: var(--candle-soft);
  text-shadow: var(--glow);
  text-wrap: balance;
  opacity: 0;
  filter: blur(6px);
  transform: translateY(6px);
  transition: opacity .9s ease, filter .9s ease, transform .9s var(--ease-out);
  pointer-events: none;
}
.narration.is-on { opacity: 1; filter: none; transform: none; }

.tap-hint {
  position: absolute;
  left: 16px; right: 16px;
  bottom: max(28px, 5svh);
  margin: 0;
  text-align: center;
  color: var(--muted);
  font-size: .95rem;
  opacity: 0;
  transition: opacity 1.2s ease;
  pointer-events: none;
}
.tap-hint.is-on { opacity: 1; animation: breathe 3s ease-in-out 1.2s infinite; }
@keyframes breathe { 50% { opacity: .45; } }

.w { opacity: 0; filter: blur(4px); transition: opacity .6s ease, filter .8s ease; }
.w.is-on { opacity: 1; filter: none; }

/* ---------- Gate ---------- */
.gate {
  z-index: 9;
  display: grid;
  place-items: center;
  padding: 24px 16px;
  background: radial-gradient(60% 50% at 50% 40%, #2a1d3d 0%, var(--night) 70%, var(--night-deep) 100%);
}
.gate.is-leaving { opacity: 0; transition: opacity 1.1s ease; }
.countdown, .begin {
  grid-area: 1 / 1;
  width: 100%;
  max-width: 30rem;
  text-align: center;
  opacity: 0;
  visibility: hidden;
  transition: opacity .8s ease, visibility 0s linear .8s;
}
.countdown.is-on, .begin.is-on { opacity: 1; visibility: visible; transition: opacity .8s ease, visibility 0s; }
.begin { cursor: pointer; }
.begin__text { margin: 0; color: var(--muted); font-size: 1rem; animation: breathe 3s ease-in-out infinite; }
.gate__flame { position: relative; width: 14px; height: 34px; margin: 0 auto 2.2rem; }
.gate__flame::before {
  content: "";
  position: absolute;
  left: 50%; top: 50%;
  width: 180px; height: 180px;
  transform: translate(-50%, -50%);
  background: radial-gradient(circle, rgba(255, 196, 110, .28), transparent 60%);
}
.gate__flame span {
  position: absolute;
  inset: 0;
  border-radius: 50% 50% 45% 45% / 70% 70% 30% 30%;
  background: radial-gradient(ellipse at 50% 78%, #fff 0 18%, #ffe08a 38%, #ffa23c 66%, rgba(255, 110, 30, 0) 80%);
  filter: blur(.6px);
  transform-origin: 50% 100%;
  animation: flicker 2.4s ease-in-out infinite;
}
@keyframes flicker {
  0%, 100% { transform: scale(1, 1) skewX(0); }
  25% { transform: scale(.96, 1.06) skewX(-2deg); }
  50% { transform: scale(1.03, .95) skewX(1.5deg); }
  75% { transform: scale(.98, 1.04) skewX(-1deg); }
}

/* The countdown: rolling digits, then a heartbeat, then midnight */
.gate { --heat: 0; isolation: isolate; }
.gate::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(55% 45% at 50% 46%, rgba(255, 170, 90, .34), rgba(190, 80, 90, .12) 55%, transparent 80%);
  opacity: var(--heat);
  transition: opacity 1s ease;
}
.countdown { display: grid; justify-items: center; max-width: 48rem; }
.countdown > * { grid-column: 1; }
.clock { grid-row: 2; display: flex; justify-content: center; gap: clamp(.45rem, 2.2vw, 1.3rem); }
/* Each unit is a small lit card; the line along its bottom drains as that unit runs down. */
.clock__unit {
  --left: 1;
  position: relative;
  display: grid;
  justify-items: center;
  gap: .35rem;
  padding: clamp(.55rem, 2vw, 1rem) clamp(.5rem, 2.4vw, 1.3rem) clamp(.6rem, 2vw, 1rem);
  border: 1px solid rgba(243, 194, 107, .16);
  border-radius: 16px;
  background: linear-gradient(180deg, rgba(255, 236, 205, .07), rgba(255, 236, 205, .015) 60%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .07), 0 24px 40px -24px rgba(0, 0, 0, .8);
  overflow: hidden;
}
.clock__unit::after {
  content: "";
  position: absolute;
  left: 14%; right: 14%; bottom: 0;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, rgba(243, 194, 107, .2), var(--candle));
  transform: scaleX(var(--left));
  transform-origin: left;
  transition: transform .9s var(--ease-out);
}
.clock__unit.is-gone { display: none; }
.clock__num {
  display: flex;
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(2.3rem, 10.5vw, 5.4rem);
  /* A smaller optical size keeps Bodoni's hairlines visible at this size. */
  font-variation-settings: "opsz" 20;
  line-height: 1.1;
  color: var(--candle-soft);
  font-variant-numeric: lining-nums tabular-nums;
  filter: drop-shadow(0 0 22px rgba(243, 194, 107, .22));
}
.reel { position: relative; display: block; width: .64em; height: 1.1em; overflow: hidden; }
.reel--sep { width: .3em; }
.reel__digit {
  position: absolute;
  inset: 0;
  text-align: center;
  transition: transform .65s var(--ease-out), opacity .65s ease, filter .65s ease;
}
.reel__digit.is-entering { transform: translateY(-75%); opacity: 0; filter: blur(3px); transition: none; }
.reel__digit.is-leaving { transform: translateY(75%); opacity: 0; filter: blur(3px); }
.clock__label { color: var(--muted); font-size: clamp(.75rem, 2.6vw, .9rem); letter-spacing: .02em; }
.countdown .gate__candle { grid-row: 1; transition: transform 1.2s var(--ease-out); }
.clock { transition: opacity .9s ease, filter .9s ease; }

/* The candle on the countdown */
.gate__fx { position: absolute; inset: 0; z-index: -1; width: 100%; height: 100%; pointer-events: none; }
.gate__candle { display: grid; justify-items: center; margin-bottom: 1.2rem; }
.gate__candle .gate__flame { margin: 0 0 1px; }
.gate__wax {
  position: relative;
  width: 13px;
  height: clamp(34px, 6svh, 56px);
  border-radius: 3px 3px 2px 2px;
  background:
    linear-gradient(180deg, rgba(255, 214, 150, .55), transparent 40%),
    linear-gradient(90deg, #b9a3a8, #f7ece4 38%, #fff8f1 52%, #d9c5c4 80%, #9d8790);
  box-shadow: 0 0 18px rgba(255, 190, 110, .18);
}
.gate__wax::before { content: ""; position: absolute; left: 50%; top: -5px; width: 1.5px; height: 6px; background: #2a1d18; transform: translateX(-50%); }

/* Last ten seconds: everything else fades, one number beats in the middle */
.final { grid-row: 2; align-self: center; margin-top: clamp(.5rem, 3svh, 2rem); position: relative; display: grid; place-items: center; pointer-events: none; opacity: 0; transition: opacity .6s ease; }
.final__num {
  grid-area: 1 / 1;
  font-family: var(--display);
  font-weight: 500;
  font-size: min(clamp(7rem, 34vw, 15rem), 27svh);
  font-variation-settings: "opsz" 28;
  line-height: 1;
  color: var(--candle-soft);
  font-variant-numeric: lining-nums;
  text-shadow: 0 0 calc(30px + var(--heat) * 60px) rgba(255, 180, 90, .55);
}
.final__ring {
  grid-area: 1 / 1;
  width: min(clamp(10rem, 44vw, 20rem), 34svh);
  aspect-ratio: 1;
  border: 1px solid rgba(243, 194, 107, .5);
  border-radius: 50%;
  opacity: 0;
}
.final__num.is-beat { animation: beat-num .9s var(--ease-out); }
.final__ring.is-beat { animation: beat-ring .95s ease-out; }
@keyframes beat-num { 0% { transform: scale(1.35); opacity: 0; filter: blur(6px); } 22% { transform: scale(.96); opacity: 1; filter: blur(0); } 40% { transform: scale(1.04); } 100% { transform: scale(1); } }
/* The ring pulses out from the number and is gone before it could reach the candle above. */
@keyframes beat-ring { 0% { transform: scale(.6); opacity: .85; } 70% { opacity: .15; } 100% { transform: scale(1.12); opacity: 0; } }
.countdown.is-final .final { opacity: 1; }
.countdown.is-final .clock { opacity: 0; filter: blur(6px); }
.countdown.is-final .gate__candle { transform: translateY(-1rem) scale(1.25); }

/* Zero */
.countdown__zero {
  grid-row: 2;
  align-self: center;
  margin: 0;
  font-family: var(--display);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(2.4rem, 9vw, 4.6rem);
  line-height: 1.1;
  color: var(--candle-soft);
  text-shadow: 0 0 40px rgba(255, 180, 90, .5);
  opacity: 0;
  transform: scale(.94);
  filter: blur(8px);
  transition: opacity 1.4s ease .5s, transform 2.4s var(--ease-out) .5s, filter 1.4s ease .5s;
}
.countdown.is-zero .final { opacity: 0; transition-duration: .3s; }
.countdown:not(.is-zero) .countdown__zero { pointer-events: none; }
.countdown.is-zero .countdown__zero { opacity: 1; transform: none; filter: none; }
.countdown.is-zero .gate__candle { transform: translateY(-1.6rem) scale(1.6); }
.gate:has(.is-zero) { --heat: 1.3; }

/* The welcome: a few lines, one at a time */
.welcome {
  grid-area: 1 / 1;
  width: 100%;
  max-width: 34rem;
  text-align: center;
  opacity: 0;
  visibility: hidden;
  transition: opacity .9s ease, visibility 0s linear .9s;
}
.welcome.is-on { opacity: 1; visibility: visible; transition: opacity .9s ease, visibility 0s; }
.welcome__line {
  margin: 0 0 1rem;
  font-family: var(--display);
  font-style: italic;
  font-size: clamp(1.45rem, 5vw, 2.1rem);
  line-height: 1.3;
  text-wrap: balance;
  opacity: 0;
  transform: translateY(10px);
  filter: blur(6px);
  transition: opacity 1.3s ease, transform 1.6s var(--ease-out), filter 1.3s ease, color 1.2s ease;
}
.welcome__line--name { font-family: var(--hand); font-style: normal; font-size: clamp(2rem, 7vw, 2.8rem); color: var(--candle-soft); margin-bottom: 1.4rem; }
.welcome__line.is-in { opacity: 1; transform: none; filter: none; }
.welcome__line.is-past:not(.welcome__line--name) { color: var(--muted); }
.welcome__tap { margin: 2.4rem 0 0; color: var(--muted); font-size: .95rem; opacity: 0; transition: opacity 1.2s ease; }
.welcome.is-ready .welcome__tap { opacity: 1; animation: breathe 3s ease-in-out 1.2s infinite; }
/* ---------- 1. The cake ---------- */
.scene {
  z-index: 2;
  display: grid;
  grid-template-rows: 1fr auto 1fr;
  justify-items: center;
  padding: 24px 16px;
  overflow: hidden;
  isolation: isolate;
  background: #07050c;
}
/* Phewa Lake at night behind the cake. Hidden for the close-up on the candles, then it fades in. */
.scene__lake { position: absolute; inset: 0; z-index: -2; width: 100%; height: 100%; opacity: 1; transition: opacity 5s ease 1.2s; }
/* The camera is focused on the cake, so the lake behind it is a little soft. */
.scene.is-lit .scene__lake { filter: blur(1.4px); }
.scene.is-intro .scene__lake { opacity: 0; transition: none; }
/* The warm haze of candlelight over the cake, above the darkness. */
.scene__glow {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  background: radial-gradient(circle at var(--gx, 50%) var(--gy, 45%), rgba(255, 176, 92, .3) 0, rgba(255, 150, 70, .1) 18vmin, transparent 44vmin);
  mix-blend-mode: screen;
  opacity: 0;
}
.scene.is-lit .scene__glow { visibility: hidden; }
/* The last part of the night: far lanterns and fireworks between the lake and the table, her lantern in front. */
.scene__lights { position: absolute; inset: 0; z-index: -1; width: 100%; height: 100%; pointer-events: none; filter: blur(.5px); }
/* On a phone her lantern portrait is drawn in front, so the table steps back into the dark for a moment. */
.scene.is-aside.is-finale.is-portrait .cake { filter: brightness(.16) blur(2px); transition: transform 1.6s ease, filter 2s ease; }
.scene.is-portrait .scene__lake, .scene.is-portrait .garland { filter: brightness(.35) blur(2px); transition: filter 2s ease; }
.scene.is-portrait .scene__lights { opacity: .4; transition: opacity 2s ease; }
.scene.is-finale :is(.scene__lake, .garland, .scene__lights) { transition: filter 2s ease, opacity 2s ease; }
.scene__near { position: absolute; inset: 0; z-index: 5; width: 100%; height: 100%; pointer-events: none; }
.scene__fx { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 5; }
.scene__flames { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 4; }

/* Fairy lights: dark glass until the lights come up, then they switch on one by one. */
.garland { position: absolute; left: 0; right: 0; top: 0; z-index: -1; pointer-events: none; opacity: 0; transition: opacity 3s ease 1s; }
.scene:not(.is-intro) .garland { opacity: 1; }
.garland svg { display: block; overflow: visible; }
.garland__wire path { fill: none; stroke: #1b1512; stroke-width: 1.4; }
.bulb__glass { fill: #6d5a4a; opacity: .35; transition: fill .4s ease, opacity .4s ease; transition-delay: calc(var(--i) * 45ms + .4s); }
.bulb__glow { opacity: 0; transition: opacity .6s ease; transition-delay: calc(var(--i) * 45ms + .4s); }
.garland.is-on .bulb__glass { fill: #fff2cf; opacity: 1; }
.garland.is-on .bulb__glow { opacity: 1; animation: bulb var(--tw) ease-in-out calc(var(--i) * 45ms + 1.2s) infinite alternate; }
@keyframes bulb { to { opacity: .55; } }

/* Balloons drift a little; the room stays in shadow until the candles are blown out. */
/* The flowers and chocolates are on the table all along, hidden in the dark until the lights come up. */
.treat { opacity: 0; transition: opacity 2.6s ease .4s; }
.tea-glow, .tea-pool { mix-blend-mode: screen; }
/* The flames flicker in brightness only: nothing on the table may change size, or the whole group would shift. */
.tea-glow { animation: tea-flicker 2.3s ease-in-out infinite; animation-delay: calc(var(--i) * -.77s); }
.tea-pool { animation: tea-flicker 3.1s ease-in-out infinite; }
@keyframes tea-flicker {
  0%, 100% { opacity: .9; }
  18% { opacity: .66; }
  37% { opacity: 1; }
  55% { opacity: .74; }
  76% { opacity: .95; }
}
@media (prefers-reduced-motion: reduce) { .tea-glow, .tea-pool { animation: none; } }
.scene.is-lit .treat { opacity: 1; }
/* The notebook appears on the table once she has closed it. */
.table-book { opacity: 0; transition: opacity .7s ease; }
.scene.has-book .table-book { opacity: 1; }
/* On a phone: the tealights at the front left, the notebook just in front of the chocolates, clear of the words. */
@media (max-aspect-ratio: 5/4) {
  .table-tea { transform: translate(-112px, 30px); }
  .table-bookspot { transform: translate(-6px, -44px); }
}
/* Wide screens have room either side of the cake: spread the gifts outwards and show them larger.
   Each group grows away from the cake, so nothing ever covers it. */
@media (min-aspect-ratio: 5/4) {
  /* There's room on a wide table: everything stands back from the cake, with space round each. */
  .treats-left, .bouquet { transform-box: fill-box; }
  .treats-left { transform-origin: 100% 100%; transform: translate(-190px, 8px) scale(1.1); }
  .bouquet { transform-origin: 0 100%; transform: translate(150px, 4px) scale(1.12); }
  .table-tea { transform: translate(52px, 24px); }
  .table-bookspot { transform: translate(-100px, 26px); }
  .table-petals { transform: translate(-30px, 0); }
  /* Raise the table so its front half is on screen too. */
  .cake { top: -11svh; }
}

/* Candlelight: everything falls into darkness a short way from the flames.
   .scene__night closes in completely while the candles are out. Both lift when the lights come up. */
.scene__dark, .scene__night { position: absolute; inset: 0; z-index: 3; pointer-events: none; transition: opacity 2.6s ease; }
.scene__dark {
  background: radial-gradient(circle at var(--gx, 50%) var(--gy, 30%),
    rgba(4, 3, 9, 0) 0, rgba(4, 3, 9, .3) 9vmin, rgba(4, 3, 9, .78) 26vmin, rgba(3, 2, 7, .93) 48vmin);
}
.scene__night { background: rgba(3, 2, 7, .9); opacity: 1; }
.scene.is-lit .scene__dark, .scene.is-lit .scene__night { opacity: 0 !important; }
.scene__top, .scene__bottom { position: relative; z-index: 6; }

/* The opening: a close-up on the candles in the dark, then the camera pulls back as the room appears. */
.cake-body { transition: opacity 4.5s ease .5s; }
.candle__body { transition: opacity 2.6s ease; }
.scene.is-intro .cake-body { opacity: 0; transition: none; }
.scene.is-intro .candle__body { opacity: .22; transition: none; }



.match {
  position: fixed;
  left: 0; top: 0;
  z-index: 7;
  width: 9px;
  height: 92px;
  margin: -7px 0 0 -4.5px;
  transform-origin: 4.5px 7px;
  pointer-events: none;
  opacity: 0;
  transition: opacity .6s ease;
}
.match.is-on { opacity: 1; }
.match.is-out { opacity: 0; transition: opacity .8s ease .3s; }
.match__stick { position: absolute; left: 0; top: 10px; width: 9px; height: 82px; border-radius: 2px; background: linear-gradient(90deg, #8a6a40, #c9a46a 45%, #7d5c34); filter: brightness(.7); }
.match__head { position: absolute; left: -1.5px; top: 0; width: 12px; height: 16px; border-radius: 50% 50% 45% 45%; background: radial-gradient(circle at 40% 35%, #b4372f, #5a0f0f); z-index: 1; }
.match.is-lit .match__head { background: radial-gradient(circle at 40% 35%, #3a2a20, #120b08); }
.scene__top { align-self: end; display: grid; text-align: center; padding-bottom: 3svh; width: 100%; max-width: 60rem; }
.scene__top > * { grid-area: 1 / 1; align-self: end; }
.prompt {
  margin: 0;
  min-height: 1.2em;
  font-family: var(--display);
  font-style: italic;
  font-size: clamp(1.5rem, 4.4vw, 2.3rem);
  line-height: 1.2;
  color: var(--candle-soft);
  text-wrap: balance;
  transition: opacity .5s ease;
}
.prompt.is-changing, .scene.is-dark .prompt { opacity: 0; }
.whisper {
  margin: 0;
  font-family: var(--hand);
  font-size: clamp(1.7rem, 5.5vw, 2.6rem);
  line-height: 1.2;
  color: var(--candle-soft);
  text-shadow: 0 0 22px rgba(255, 196, 120, .45);
  opacity: 0;
  transition: opacity 1.1s ease;
}
.whisper.is-on { opacity: 1; }
.whisper__ch { display: inline-block; white-space: pre; opacity: 0; filter: blur(6px); transform: translateY(4px); }
.whisper.is-on .whisper__ch { animation: breathe-in 1.4s var(--ease-out) forwards; animation-delay: calc(var(--i) * 70ms + .2s); }
@keyframes breathe-in { to { opacity: 1; filter: blur(0); transform: none; } }
.lyrics { opacity: 0; transition: opacity .6s ease; }
.lyrics.is-on { opacity: 1; }
.lyrics__line {
  margin: 0;
  font-family: var(--display);
  font-style: italic;
  font-size: clamp(1.7rem, 5.6vw, 3.2rem);
  line-height: 1.15;
  animation: line-in .5s var(--ease-out) both;
}
@keyframes line-in { from { opacity: 0; transform: translateY(10px); filter: blur(6px); } }
.lyrics__word { display: inline-block; color: rgba(239, 229, 238, .3); transition: color .25s ease, text-shadow .4s ease; }
.lyrics__word.is-sung { color: var(--candle-soft); text-shadow: 0 0 18px rgba(243, 194, 107, .5); }
.lyrics__word.is-name.is-sung { color: #fff3d0; text-shadow: 0 0 26px rgba(255, 214, 140, .95), 0 0 6px rgba(255, 214, 140, .8); animation: name-pop .9s var(--ease-out); }
@keyframes name-pop { 40% { transform: scale(1.18); } }
.title {
  margin: 0;
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(2.4rem, 7.5vw, 5.2rem);
  line-height: 1;
  letter-spacing: -.015em;
  visibility: hidden;
}
.scene.is-lit .title { visibility: visible; }
.title .word { display: inline-block; white-space: nowrap; }
.title .ch { display: inline-block; opacity: 0; }
.scene.is-lit .title .ch { animation: rise 1.3s var(--ease-out) both; animation-delay: calc(var(--i) * 55ms + 150ms); }
@keyframes rise {
  from { opacity: 0; transform: translateY(.35em); filter: blur(12px); }
  to { opacity: 1; transform: none; filter: none; }
}
.cake {
  position: relative;
  z-index: 1;
  width: min(84vw, calc(62svh * .78), 520px);
  transform-origin: 50% 17%;
}
.scene.is-intro .cake { transform: scale(1.75); transition: none; }
.cake svg { display: block; width: 100%; height: auto; overflow: visible; }
.cake svg * { pointer-events: none; }
.scene__bottom { align-self: start; display: grid; justify-items: center; text-align: center; padding-top: 3svh; width: 100%; max-width: 36rem; }
.scene__bottom > * { grid-area: 1 / 1; }
.wish-count {
  margin: 0;
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(3.6rem, 12vw, 6rem);
  line-height: 1;
  color: var(--candle-soft);
  text-shadow: 0 0 30px rgba(243, 194, 107, .5);
  font-variant-numeric: lining-nums;
  opacity: 0;
  transition: opacity .4s ease;
}
.wish-count.is-on { opacity: 1; }
.wish-count.is-tick { animation: tick 1s ease-out; }
@keyframes tick {
  0% { transform: scale(1.7); opacity: 0; filter: blur(8px); }
  22% { transform: scale(1); opacity: 1; filter: none; }
  80% { opacity: 1; }
  100% { transform: scale(.9); opacity: .15; }
}
.wish-ui { display: grid; justify-items: center; gap: .9rem; transition: opacity .8s ease; }
.scene.is-dark .wish-ui { opacity: 0; }
.hint { margin: 0; min-height: 1.5em; max-width: 26rem; color: var(--muted); font-size: .95rem; }
.meter { width: 150px; height: 2px; background: rgba(255, 255, 255, .12); border-radius: 2px; overflow: hidden; opacity: 0; transition: opacity .4s; }
.meter.is-on { opacity: 1; }
.meter span { display: block; height: 100%; background: var(--candle); transform-origin: left; transform: scaleX(0); }
/* Under the title once the lights are up, clear of the gifts on the table. */
.scene__top > .after-ui { grid-area: 2 / 1; margin-top: .4rem; opacity: 0; transition: opacity 1.6s ease 1.4s; }
.scene .tap-hint { z-index: 6; bottom: max(18px, 3svh); color: var(--text); text-shadow: var(--glow); }
.scene.is-lit .after-ui { opacity: 1; }
.tease {
  margin: 0;
  font-family: var(--display);
  font-style: italic;
  font-size: clamp(1.1rem, 3.2vw, 1.4rem);
  color: var(--candle-soft);
  opacity: 0;
  transition: opacity 1.4s ease;
}
.tease.is-on { opacity: 1; }

/* ---------- 2. The notebook ---------- */
.notebook-act { z-index: 2; display: grid; place-items: center; padding: 30px 16px 110px; background: var(--room); }

/* Opening the gift beside the party: the lit table glides to the left, the notebook opens on the right,
   with Phewa Lake behind both. On a phone the table moves up and dims behind the book instead. */
.scene .cake { transition: transform 5.6s cubic-bezier(.25, .6, .2, 1), filter 1.4s ease; }
.scene.is-aside .cake { transition: transform 1.6s cubic-bezier(.65, 0, .25, 1), filter 1.6s ease; transform: translateY(-16svh) scale(.62); filter: brightness(.45) blur(1.5px); }
.scene.is-aside :is(.scene__top, .scene__bottom) { opacity: 0; transition: opacity .8s ease; }
.notebook-act.is-beside { background: rgba(4, 6, 16, .35); }
/* On a phone, once the book is closed the table comes back into full view for the lanterns. */
@media (max-aspect-ratio: 5/4) {
  .scene.is-aside.is-finale .cake { transform: translateY(-7svh) scale(.92); filter: none; }
}
@media (min-aspect-ratio: 5/4) {
  .scene.is-aside .cake { transform: translateX(-24vw) translateY(4svh) scale(.82); filter: none; }
  .notebook-act.is-beside { background: none; }
  .notebook-act.is-beside .book { --pw: min(24vw, 360px, calc((100svh - 190px) * .7)); left: 22vw; }
  .notebook-act.is-beside .turn-hint { left: 72vw; }
  .notebook-act.is-beside .book::after { box-shadow: 0 40px 70px -20px rgba(0, 0, 0, .95); }
}
.book {
  --pw: min(84vw, 380px, calc((100svh - 190px) * .7));
  --ph: calc(var(--pw) / .7);
  position: relative;
  width: var(--pw);
  height: var(--ph);
  perspective: 2400px;
  transition: transform 1.1s var(--ease-out), opacity 1s ease;
}
.book::before {
  content: "";
  position: absolute;
  top: 5px; bottom: 5px; right: -7px;
  width: 9px;
  border-radius: 0 4px 4px 0;
  /* the page block's fore-edge: old cream paper */
  background: linear-gradient(180deg, rgba(255, 250, 235, .4), transparent 30%, rgba(90, 60, 20, .2)), repeating-linear-gradient(90deg, #f6ecd8 0 1px, #cdb990 1px 2px);
  box-shadow: 4px 6px 12px rgba(0, 0, 0, .4);
}
.book::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: 4px 10px 10px 4px;
  box-shadow: 0 40px 70px -24px rgba(0, 0, 0, .85);
}
/* Nothing shows until its pages are in; then it rises into view whole. */
.book:empty { opacity: 0; transform: translateY(22px) scale(.96); transition: none; }
.book.is-closing { opacity: 0; transform: scale(.94); }
/* Phones and tablets: no blur on big layers that change every frame (the costliest thing a phone can be asked
   to do); the brightness changes stay. */
@media (pointer: coarse) {
  .scene.is-lit .scene__lake, .scene__lights { filter: none; }
  .scene.is-portrait .scene__lake, .scene.is-portrait .garland { filter: brightness(.35); }
  .scene.is-aside.is-finale.is-portrait .cake { filter: brightness(.16); }
}
@media (pointer: coarse) and (max-aspect-ratio: 5/4) {
  .scene.is-aside .cake { filter: brightness(.45); }
  .scene.is-aside.is-finale .cake { filter: none; }
  .scene.is-aside.is-finale.is-portrait .cake { filter: brightness(.16); }
}
/* On a phone, the left-hand page slides into view first (see the notebook script). */
@media (max-width: 819px) { .book.is-open.show-left { transform: translateX(var(--pw)); } }
@media (min-width: 820px) {
  .book.is-open { transform: translateX(calc(var(--pw) / 2)); }
  .book.is-open.is-closing { transform: translateX(calc(var(--pw) / 2)) scale(.94); }
}
.sheet {
  position: absolute;
  inset: 0;
  transform-origin: left center;
  transform-style: preserve-3d;
  transition: transform 1.2s cubic-bezier(.35, .75, .25, 1);
}
.sheet.is-flipped { transform: rotateY(-180deg); }
.sheet__face {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: 3px 10px 10px 3px;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}
.sheet__back { transform: rotateY(180deg); border-radius: 10px 3px 3px 10px; }
.sheet__face::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, rgba(0, 0, 0, .3), transparent 55%);
  opacity: 0;
  transition: opacity .6s ease;
  pointer-events: none;
}
.sheet.is-flipped .sheet__front::after { opacity: 1; }

/* The cover: cream letter paper, darker and softly worn at the edges, with faded handwriting under a collage. */
.cover {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: 0 10% 0 14%;
  overflow: hidden;
  background: linear-gradient(rgba(255, 196, 120, .06), transparent 45%, rgba(28, 12, 18, .22)), url("../assets/notebook/cover.webp") center / 100% 100%;
  box-shadow: inset 0 0 0 1px rgba(90, 55, 20, .35);
}
.old-letter {
  position: absolute;
  inset: -12% -14% -12% -6%;
  padding: 6% 0 0 16%;
  transform: rotate(-5deg);
  font-family: var(--hand);
  font-size: calc(var(--pw) * .04);
  line-height: 1.95;
  color: rgba(95, 58, 35, .17);
  pointer-events: none;
  user-select: none;
}
/* Torn scraps of an old printed page. */
.scrap { position: absolute; overflow: hidden; padding: .7em .9em; background: url("../assets/notebook/scrap.webp") center / 100% 100%, linear-gradient(170deg, #efe3c6, #e0cca2); color: #3a2a1e; font-family: var(--oldbook); line-height: 1.35; box-shadow: 0 3px 8px rgba(60, 35, 15, .25); user-select: none; }
.scrap p { margin: 0; }
.scrap--poem { top: 5%; left: 17%; width: 50%; height: 25%; font-size: calc(var(--pw) * .03); transform: rotate(-3deg); clip-path: polygon(0 3%, 7% 0, 15% 2%, 26% 0, 38% 3%, 52% 0, 64% 2%, 78% 0, 90% 3%, 100% 1%, 98% 22%, 100% 41%, 97% 62%, 100% 80%, 98% 100%, 84% 97%, 70% 100%, 55% 97%, 40% 100%, 26% 97%, 12% 100%, 0 97%, 2% 76%, 0 54%, 3% 30%); }
.scrap--corner { top: -2%; left: -4%; width: 48%; height: 23%; padding: 1.4em 1em 1em 1.6em; font-size: calc(var(--pw) * .026); transform: rotate(-6deg); clip-path: polygon(0 0, 100% 0, 96% 18%, 100% 35%, 93% 52%, 97% 68%, 88% 82%, 70% 90%, 52% 86%, 36% 100%, 18% 92%, 0 100%); }
/* Stickers: a rose with a white border, cherries tied with a bow, red stars, a butterfly sketch. */
.sticker--rose { position: absolute; top: 24%; left: 12%; width: 19%; aspect-ratio: 1; overflow: hidden; border-radius: 50%; border: calc(var(--pw) * .009) solid #fffaf0; box-shadow: 0 3px 6px rgba(60, 30, 15, .35); transform: rotate(-8deg); }
.sticker--rose img { display: block; width: 100%; height: 100%; object-fit: cover; transform: scale(1.6); }
.cherries { position: absolute; top: 4%; right: 15%; width: 25%; filter: drop-shadow(0 3px 3px rgba(60, 20, 15, .35)); transform: rotate(8deg); }
.star { fill: #b8122d; filter: drop-shadow(0 1px 1px rgba(60, 10, 15, .35)); }
.star--c1 { position: absolute; bottom: 21%; right: 21%; width: 7%; transform: rotate(12deg); }
.star--c2 { position: absolute; bottom: 14%; right: 15%; width: 5%; transform: rotate(-10deg); }
.butterfly { fill: rgba(250, 244, 230, .55); stroke: #4a3628; stroke-width: 1.1; stroke-linecap: round; stroke-linejoin: round; }
.butterfly--cover { position: absolute; top: 37%; right: 17%; width: 15%; transform: rotate(18deg); opacity: .8; }
/* A satin bow, pinned on a card or clipping a photo to the page. */
.bow { position: absolute; z-index: 3; filter: drop-shadow(0 2px 2px rgba(60, 10, 15, .35)); }
.bow--clip { top: -8%; left: 50%; width: 30%; transform: translateX(-50%) rotate(3deg); }
.bow--pin { top: -15%; left: 50%; width: 30%; transform: translateX(-50%) rotate(-4deg); }
/* Her name in cut-out letters, and a typed strip under it. */
.cover__text { position: relative; text-align: center; transform: translateY(4%); }
.cover__for { margin: 0 0 .15em; font-family: var(--hand); font-size: calc(var(--pw) * .055); color: #7a2335; }
.cover__name { margin: 0; font-size: calc(var(--pw) * .115); line-height: 1.1; }
.cutout { display: inline-flex; align-items: center; gap: .05em; }
.cut { display: inline-block; padding: .05em .11em .02em; line-height: 1; transform: translateY(var(--lift)) rotate(var(--tilt)); box-shadow: 0 2px 3px rgba(40, 20, 10, .35); }
.cut--0 { background: #1f1a17; color: #f4ead2; font-family: var(--display); font-weight: 700; }
.cut--1 { background: url("../assets/notebook/scrap.webp") center / 100% 100%, #efe3c8; color: #1f1a17; font-family: var(--oldbook); font-style: italic; }
.cut--2 { background: #b3122e; color: #fbefd9; font-family: var(--typed); }
.cut--3 { background: #d6c29b; color: #2a1d14; font-family: var(--display); font-style: italic; font-weight: 600; }
.cut--4 { background: #f8f2e4; color: #b3122e; font-family: var(--oldbook); }
.cover__note { display: inline-block; margin: .9em 0 0; padding: .3em .7em; font-family: var(--typed); font-size: calc(var(--pw) * .038); color: #2a1d14; background: rgba(250, 240, 205, .95); box-shadow: 0 1px 3px rgba(60, 35, 15, .25); transform: rotate(-1.5deg); }
/* A postage stamp with perforated edges, postmarked Pokhara on her birthday. */
.stamp {
  --perf: calc(var(--pw) * .018);
  position: absolute;
  bottom: 8%;
  left: 18%;
  width: 22%;
  aspect-ratio: .82;
  padding: calc(var(--pw) * .012);
  background: #fbf6ea;
  transform: rotate(6deg);
  filter: drop-shadow(0 2px 3px rgba(60, 35, 15, .35));
  -webkit-mask: radial-gradient(circle, #0000 calc(var(--pw) * .0055), #000 calc(var(--pw) * .006)) calc(var(--perf) / -2) calc(var(--perf) / -2) / var(--perf) var(--perf), linear-gradient(#000 0 0) content-box;
  mask: radial-gradient(circle, #0000 calc(var(--pw) * .0055), #000 calc(var(--pw) * .006)) calc(var(--perf) / -2) calc(var(--perf) / -2) / var(--perf) var(--perf), linear-gradient(#000 0 0) content-box;
}
.stamp__inner { position: relative; display: block; width: 100%; height: 100%; overflow: hidden; }
.stamp img { display: block; width: 100%; height: 100%; object-fit: cover; filter: sepia(.35) saturate(.85); }
.stamp__value { position: absolute; left: 0; right: 0; bottom: 5%; text-align: center; font-family: var(--display); font-weight: 700; font-size: calc(var(--pw) * .03); letter-spacing: .15em; color: #fbefd9; text-shadow: 0 1px 2px rgba(0, 0, 0, .6); }
.postmark { position: absolute; bottom: 12%; left: 31%; width: 34%; fill: none; stroke: rgba(40, 30, 45, .55); stroke-width: 1.3; transform: rotate(-12deg); pointer-events: none; }
.postmark text { fill: rgba(40, 30, 45, .62); stroke: none; font-family: var(--typed); }

/* Twin-loop metal rings down the bound edge: curled round the edge while it's closed, standing between the pages once it's open. */
.book__rings { position: absolute; top: 2.5%; bottom: 2.5%; left: calc(var(--pw) * -.06); z-index: 60; width: calc(var(--pw) * .12); pointer-events: none; }
.book__rings svg { display: block; width: 100%; height: 100%; overflow: visible; }
.ring__slot { fill: #2a1a14; }
.ring__wire { fill: none; stroke: url(#ringMetal); stroke-width: 2.1; stroke-linecap: round; }
.ring__shadow { fill: none; stroke: rgba(30, 15, 5, .45); stroke-width: 2.6; stroke-linecap: round; transform: translate(.9px, 2px); filter: blur(.9px); }
.ring__shine { fill: none; stroke: rgba(255, 250, 232, .75); stroke-width: .55; stroke-linecap: round; transform: translateY(-.6px); }
/* Jute twine: a twisted cord, with its own shadow and a little shine, through brass eyelets. */
.twine__cord { fill: none; stroke: #ad8650; stroke-width: 4.3; stroke-linecap: round; }
.twine__twist { fill: none; stroke: #6f5126; stroke-width: 4.3; stroke-dasharray: 1.4 2; stroke-linecap: butt; opacity: .7; }
.twine__shine { fill: none; stroke: rgba(240, 214, 160, .55); stroke-width: .9; stroke-dasharray: 1.3 1.5; transform: translateY(-.7px); }
.twine__shadow { fill: none; stroke: rgba(30, 15, 5, .5); stroke-width: 4.8; stroke-linecap: round; transform: translate(1px, 2.2px); filter: blur(1px); }
.twine__fray { fill: none; stroke: #9c7845; stroke-width: .7; stroke-linecap: round; }
.twine__knot { fill: #9c7845; stroke: #5e4320; stroke-width: .8; filter: drop-shadow(1px 2px 1.5px rgba(30, 15, 5, .5)); }
.eyelet { fill: url(#brass); filter: drop-shadow(.5px 1px 1px rgba(30, 15, 5, .5)); }
.eyelet__hole { fill: #24150e; }
.rings--closed, .rings--open { transition: opacity .35s ease .25s; }
.rings--open { opacity: 0; }
.book.is-open .rings--open { opacity: 1; }
.book.is-open .rings--closed { opacity: 0; }

/* A red satin ribbon round the book, held by the wax seal. */
.cover__band { position: absolute; top: 0; bottom: 0; right: 7%; width: calc(var(--pw) * .045); background: linear-gradient(90deg, #6e0a1c, #c42a45 40%, #a3132e 62%, #6e0a1c); box-shadow: 0 0 5px rgba(40, 10, 5, .45); transition: opacity .5s ease .2s; }
.seal {
  position: absolute;
  top: 68%;
  left: 50%;
  width: calc(var(--pw) * .17);
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
}
.seal__half {
  position: absolute;
  inset: 0;
  border-radius: 46% 54% 50% 50% / 52% 48% 52% 48%;
  background: radial-gradient(circle at 36% 30%, #c94458 0%, #8e1a30 45%, #4f0816 100%);
  box-shadow: 0 3px 6px rgba(40, 0, 10, .5), inset 0 0 0 calc(var(--pw) * .012) rgba(90, 5, 25, .6);
  transition: transform .6s cubic-bezier(.5, -0.4, .6, 1), opacity .6s ease;
}
.seal__half--l { clip-path: polygon(0 0, 54% 0, 44% 40%, 56% 62%, 46% 100%, 0 100%); }
.seal__half--r { clip-path: polygon(54% 0, 100% 0, 100% 100%, 46% 100%, 56% 62%, 44% 40%); }
.seal svg { position: absolute; inset: 27%; width: 46%; height: 46%; fill: #7d0f28; filter: drop-shadow(0 -1px 0 rgba(255, 150, 160, .5)); transition: opacity .3s ease; }
.book.is-unsealed .seal .seal__half--l, .page--envelope.is-cracked .seal__half--l { transform: translate(-30%, 25%) rotate(-28deg); opacity: 0; }
.book.is-unsealed .seal .seal__half--r, .page--envelope.is-cracked .seal__half--r { transform: translate(30%, 30%) rotate(24deg); opacity: 0; }
.book.is-unsealed .seal svg, .page--envelope.is-cracked .envelope__seal svg { opacity: 0; }
.book.is-unsealed .cover__band { opacity: 0; }

/* A satin ribbon bookmark hanging out of the bottom of the pages. */
.book__ribbon {
  position: absolute;
  left: 62%;
  bottom: calc(var(--pw) * -.16);
  z-index: 0;
  width: calc(var(--pw) * .045);
  height: calc(var(--pw) * .2);
  background: linear-gradient(90deg, #6e0a1c, #c42a45 45%, #6e0a1c);
  clip-path: polygon(0 0, 100% 0, 100% 100%, 50% 86%, 0 100%);
  filter: drop-shadow(0 4px 4px rgba(0, 0, 0, .4));
}

/* Paper: aged ivory with a soft fibre, a little foxing, warmer towards the edges, darker into the gutter.
   The ink is sepia. */
.page {
  /* Each page its own coffee-stained sheet (set from the notebook script), lit by the fairy lights at night:
     warm light from above, falling away darker towards the bottom. */
  --paper: linear-gradient(rgba(255, 196, 120, .07), transparent 40%, rgba(28, 12, 18, .2)), var(--sheet, url("../assets/notebook/page_1.webp")) center / 100% 100%;
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  padding: 9% 9% 8% 12%;
  overflow: hidden;
  color: #45291f;
  font-size: calc(var(--pw) * .042);
  background:
    linear-gradient(90deg, rgba(70, 40, 20, .2), transparent 9%),
    radial-gradient(circle at 88% 10%, rgba(176, 124, 62, .1), transparent 16%),
    radial-gradient(circle at 14% 92%, rgba(176, 124, 62, .08), transparent 20%),
    var(--paper),
    linear-gradient(170deg, #fbf3e1, #f1e2c4);
  box-shadow: inset 0 0 36px rgba(150, 100, 45, .2);
}
.page--back {
  padding: 9% 12% 8% 9%;
  background:
    linear-gradient(270deg, rgba(70, 40, 20, .2), transparent 9%),
    radial-gradient(circle at 12% 12%, rgba(176, 124, 62, .09), transparent 18%),
    var(--paper),
    linear-gradient(190deg, #f9f0dc, #efdfbf);
}
/* Endpaper: the same cream letter paper as the cover, faded handwriting and all, with a bookplate bowed on. */
.page--endpaper {
  display: grid;
  place-items: center;
  background: linear-gradient(270deg, rgba(70, 40, 20, .22), transparent 9%), var(--paper);
}
.bookplate { position: relative; z-index: 1; width: 78%; padding: 1.6em 1.2em 1.3em; text-align: center; background: url("../assets/notebook/scrap.webp") center / 100% 100%, #fbf3e1; border: 1px solid #c9a24f; outline: 1px solid rgba(201, 162, 79, .7); outline-offset: -6px; border-radius: 3px; box-shadow: 0 8px 18px rgba(60, 10, 20, .3); transform: rotate(-1.5deg); }
.bookplate__sprig { width: 34%; margin: 0 auto .4em; display: block; fill: none; stroke: #b88a3e; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.bookplate__line { margin: 0 0 .7em; font-family: var(--hand); font-size: 1.12em; line-height: 1.5; }
.bookplate__from { margin: 0; font-family: var(--script); font-size: 1.5em; color: #7a2335; }

/* Old paper tape and a polaroid. */
.tape { position: absolute; z-index: 2; width: 34%; height: 9%; min-height: 14px; background: linear-gradient(rgba(226, 204, 160, .78), rgba(208, 182, 135, .78)); box-shadow: 0 1px 2px rgba(60, 30, 10, .15); clip-path: polygon(0 8%, 4% 0, 9% 10%, 14% 2%, 100% 0, 97% 30%, 100% 55%, 96% 80%, 100% 100%, 6% 96%, 0 100%, 3% 60%); }
.tape--c { top: -5%; left: 33%; transform: rotate(-4deg); }
.page__title { margin: 0 0 .25em; text-align: center; font-family: var(--script); font-size: 2.1em; line-height: 1.1; color: #7a2335; }
.polaroid { position: relative; align-self: center; width: 76%; margin: .3em 0 .5em; padding: 5% 5% 0; background: #ece0c6; box-shadow: 0 10px 22px rgba(70, 35, 20, .25), 0 1px 3px rgba(0, 0, 0, .15); transform: rotate(-3deg) translateY(10px); opacity: 0; transition: transform 1.2s var(--ease-out), opacity .8s ease; }
.polaroid__photo { aspect-ratio: 1; overflow: hidden; background: #1c1418; }
.polaroid__photo img { display: block; width: 100%; height: 100%; object-fit: cover; filter: brightness(2.2) contrast(.4) sepia(.6) blur(3px); opacity: .35; transition: filter 4.5s ease .6s, opacity 3s ease .4s; }
.polaroid__caption { margin: 0; padding: .55em 0 .7em; text-align: center; font-family: var(--hand); font-size: 1.05em; color: #5a3528; }
.page--flowers .page__caption { margin: auto 0 0; text-align: center; font-family: var(--hand); font-size: .98em; line-height: 1.55; opacity: 0; transition: opacity 1.2s ease 2.2s; }
.page--flowers.is-shown .polaroid { opacity: 1; transform: rotate(-3deg); }
.page--flowers.is-shown .polaroid__photo img { filter: sepia(.15) saturate(.92); opacity: 1; }
.page--flowers.is-shown .page__caption { opacity: 1; }

/* Left-hand pages: an optional photo of the two of you, and a little taped note. */
.page--aside { justify-content: center; align-items: center; gap: 1.4em; }
.polaroid--us { width: 66%; margin: 0; opacity: 1; transform: rotate(2.5deg); }
.polaroid--us .polaroid__photo { aspect-ratio: 4 / 5; }
.polaroid--us .polaroid__photo img { filter: none; opacity: 1; }
.note { position: relative; width: 80%; padding: 1.3em 1.1em 1.1em; background: url("../assets/notebook/scrap.webp") center / 100% 100%, #fdf6e6; box-shadow: 0 6px 14px rgba(70, 35, 20, .18); transform: rotate(-1.8deg); }
.note__text { margin: 0; text-align: center; font-family: var(--typed); font-size: .9em; line-height: 1.65; color: #2f2119; }
.page--aside .note { z-index: 1; }
.star--p1 { position: absolute; top: 6%; left: 15%; width: 6%; transform: rotate(-12deg); }
.star--p2 { position: absolute; top: 11%; right: 11%; width: 4.5%; transform: rotate(14deg); }
.butterfly--last { position: absolute; top: 11%; right: 15%; width: 18%; transform: rotate(-14deg); }

/* A pressed flower, dried flat between the pages: faded leaves, a faded rosebud, a strip of tape. */
.pressed { position: absolute; width: 34%; pointer-events: none; opacity: .85; }
.pressed svg { display: block; width: 100%; overflow: visible; fill: #a3a983; stroke: #7f8660; stroke-width: 1.2; stroke-linejoin: round; filter: drop-shadow(0 1px 1px rgba(80, 50, 20, .25)); }
.pressed svg path:first-child { fill: none; stroke: #8b8a62; stroke-width: 2; }
.pressed svg path:nth-last-child(2) { fill: #c98d8f; stroke: #9c5d62; }
.pressed svg path:last-child { fill: none; stroke: #9c5d62; }
.pressed .tape--strip { top: 38%; left: 30%; width: 34%; height: 15%; transform: rotate(-38deg); }
.pressed--corner { right: 8%; bottom: 6%; transform: rotate(-8deg); }
.pressed--low { left: 10%; bottom: 3%; width: 28%; transform: rotate(14deg) scaleX(-1); }

/* The envelope beside the letter: kraft paper, a flap sealed with wax, her name on the front. */
.page--envelope { justify-content: flex-end; align-items: center; padding-bottom: 13%; }
.envelope { position: relative; width: 92%; aspect-ratio: 1.5; transform: rotate(-3deg); perspective: 900px; filter: drop-shadow(0 8px 12px rgba(70, 35, 20, .3)); }
.envelope > * { position: absolute; }
.envelope__inside { inset: 0; border-radius: 3px; background: linear-gradient(#b99a6c, #a3845a); }
.envelope__letter { z-index: 1; left: 7%; right: 7%; top: 6%; height: 86%; display: grid; align-content: start; gap: 11%; padding: 12% 10%; border-radius: 2px; background: url("../assets/notebook/scrap.webp") center / 100% 100%, #fbf5e6; box-shadow: 0 -2px 6px rgba(60, 35, 15, .15); transition: transform 1.2s var(--ease-out) .45s; }
.envelope__letter { gap: .3em; padding: 9% 9%; }
.envelope__hello { margin: 0; font-family: var(--script); font-size: 1.35em; line-height: 1.1; color: #7a2335; }
.envelope__words { margin: 0; font-family: var(--hand); font-size: .78em; line-height: 1.5; color: #4a2e22; }
.envelope__pocket { z-index: 2; inset: 0; border-radius: 3px; clip-path: polygon(0 0, 50% 46%, 100% 0, 100% 100%, 0 100%); background: linear-gradient(160deg, rgba(255, 255, 255, .12), transparent 40%), linear-gradient(20deg, transparent 49.6%, rgba(90, 60, 30, .22) 50%, transparent 50.6%), linear-gradient(-20deg, transparent 49.6%, rgba(90, 60, 30, .22) 50%, transparent 50.6%), url("../assets/notebook/scrap.webp") center / 100% 100%, linear-gradient(#e2c99c, #d2b585); }
.envelope__to { z-index: 2; left: 0; right: 0; bottom: 6%; margin: 0; text-align: center; font-family: var(--script); font-size: 1.9em; color: #6e1a2c; }
.envelope__flap { z-index: 3; left: 0; right: 0; top: 0; height: 52%; transform-origin: top; clip-path: polygon(0 0, 100% 0, 50% 100%); background: linear-gradient(rgba(0, 0, 0, .04), rgba(90, 60, 30, .18)), url("../assets/notebook/scrap.webp") center / 100% 100%, linear-gradient(#ead4ab, #dcc193); transition: transform .9s cubic-bezier(.4, 0, .2, 1), z-index 0s linear .45s; }
.envelope__seal { z-index: 4; top: 52%; left: 50%; width: 18%; aspect-ratio: 1; transform: translate(-50%, -50%); }
.envelope__seal svg { position: absolute; inset: 27%; width: 46%; height: 46%; fill: #4f0816; transition: opacity .3s ease; }
.page--envelope.is-open .envelope__flap { z-index: 0; transform: rotateX(180deg); }
.page--envelope.is-open .envelope__letter { transform: translateY(-62%); }
.star--e1 { position: absolute; top: 12%; left: 16%; width: 6%; transform: rotate(-14deg); }
.star--e2 { position: absolute; top: 19%; left: 27%; width: 4%; transform: rotate(10deg); }

/* Little things she'd recognise, typed on strips of paper and taped in one by one. */
.page--reasons { padding-top: 8%; }
.page--reasons .page__title { font-size: 1.75em; white-space: nowrap; }
.reasons { display: grid; gap: .75em; margin-top: .5em; }
.reason { position: relative; margin: 0; padding: .55em .8em .5em 1.4em; min-height: 2.9em; font-family: var(--typed); font-size: .8em; line-height: 1.5; color: #2f2119; background: url("../assets/notebook/scrap.webp") center / 100% 100%, #fbf3dc; box-shadow: 0 2px 5px rgba(70, 40, 20, .18); transform: rotate(var(--tilt)) translateY(6px); opacity: 0; transition: opacity .4s ease, transform .5s var(--ease-out); }
.reason:nth-child(2n) { margin-left: 6%; }
.reason.is-on { opacity: 1; transform: rotate(var(--tilt)); }
.reason .tape--end { top: -18%; left: -5%; width: 18%; height: 42%; min-height: 0; transform: rotate(-24deg); }
.star--r1 { position: absolute; bottom: 7%; right: 12%; width: 5.5%; transform: rotate(14deg); }
.butterfly--reasons { position: absolute; bottom: 4%; left: 14%; width: 15%; transform: rotate(-12deg); opacity: .8; }

/* Turning a page: light runs across the paper as it bends. */
.sheet.is-turning .sheet__face::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 20;
  pointer-events: none;
  background: linear-gradient(90deg, rgba(60, 35, 15, .18), rgba(255, 252, 240, .38) 45%, rgba(60, 35, 15, .14) 75%, transparent);
  animation: page-light 1.2s ease-in-out both;
}
@keyframes page-light {
  0% { opacity: 0; }
  45% { opacity: 1; }
  100% { opacity: 0; }
}

/* The letter. */
.page--letter { overflow-y: auto; scrollbar-width: none; touch-action: pan-y; background: linear-gradient(90deg, rgba(70, 40, 20, .2), transparent 9%), repeating-linear-gradient(transparent 0 calc(1.8em - 1px), rgba(150, 105, 60, .16) calc(1.8em - 1px) 1.8em), var(--paper), linear-gradient(170deg, #fbf3e1, #f1e2c4); background-attachment: local; }
.page--letter::-webkit-scrollbar { display: none; }
.letter__mark { position: absolute; top: 4%; right: 5%; width: 22%; fill: none; stroke: rgba(176, 130, 62, .55); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; transform: rotate(12deg); }
.page__letter { font-family: var(--hand); font-size: 1em; line-height: 1.8; }
.page__letter p { margin: 0 0 .9em; }
.page__letter .letter__greeting { font-family: var(--script); font-size: 1.9em; line-height: 1.2; color: #7a2335; }
.page__letter .letter__sign { text-align: right; margin-bottom: 0; }
.page__letter .letter__name { font-family: var(--script); font-size: 1.9em; line-height: 1.2; color: #7a2335; }
.page__letter .w { filter: blur(2px); }
.page__letter .w.is-on { filter: none; }
.letter__seal { width: 2.4em; height: 2.4em; margin: .3em 0 0 auto; display: grid; place-items: center; border-radius: 47% 53% 50% 50%; background: radial-gradient(circle at 36% 30%, #e05a6e, #b0213d 50%, #6f0c22); box-shadow: 0 2px 4px rgba(60, 0, 15, .4); transform: scale(1.6) rotate(-10deg); opacity: 0; transition: transform .45s cubic-bezier(.3, 1.6, .5, 1), opacity .2s ease; }
.letter__seal svg { width: 52%; fill: #7d0f28; }
.letter__seal.is-on { transform: rotate(-10deg); opacity: 1; }

/* The heart page. */
.page--love { justify-content: center; text-align: center; background: radial-gradient(80% 60% at 50% 40%, rgba(255, 228, 222, .7), transparent 70%), linear-gradient(90deg, rgba(70, 40, 20, .2), transparent 9%), var(--paper), linear-gradient(170deg, #fbf3e1, #f1e2c4); }
.love { position: relative; display: grid; justify-items: center; }
.love__stage { position: relative; width: 82%; aspect-ratio: 300 / 280; }
.love__heart { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.love__fill { opacity: 0; transform-origin: 50% 50%; transform: scale(.85); transition: opacity 1.2s ease 2.2s, transform 1.4s var(--ease-out) 2.2s; }
.love__ink { fill: none; stroke: #5a1222; stroke-width: 1.6; stroke-linecap: round; stroke-dasharray: 900; stroke-dashoffset: 900; opacity: .75; transition: stroke-dashoffset 2.4s ease 2s; }
.is-shown .love__ink { stroke-dashoffset: 0; }
.love__fill { mix-blend-mode: multiply; }
.love__swarm { position: absolute; inset: 0; }
.love__bit { position: absolute; left: var(--tx); top: var(--ty); width: 9%; aspect-ratio: 24 / 23; transform: translate(calc(-50% + var(--fx)), calc(-50% + var(--fy))) rotate(var(--r)) scale(.4); opacity: 0; transition: transform 1.6s cubic-bezier(.2, .8, .25, 1) var(--d), opacity .5s ease var(--d); }
.love__bit svg { display: block; width: 100%; height: 100%; fill: var(--c); opacity: .85; }
.is-shown .love__bit { transform: translate(-50%, -50%) rotate(0deg) scale(1); opacity: 1; }
.is-shown .love__fill { opacity: 1; transform: none; }
.is-shown .love__stage { animation: beat 1.3s ease-in-out 3.6s infinite; }
@keyframes beat {
  0%, 100% { transform: scale(1); }
  14% { transform: scale(1.07); }
  28% { transform: scale(1); }
  42% { transform: scale(1.04); }
}
.love__words { margin: .1em 0 0; font-family: var(--script); font-size: calc(var(--pw) * .16); line-height: 1.15; color: #8f1d3a; text-shadow: 0 2px 10px rgba(160, 40, 70, .2); }
.love__ch { display: inline-block; opacity: 0; }
.is-shown .love__ch { animation: rise 1s var(--ease-out) both; animation-delay: calc(2.8s + var(--i) * 90ms); }
.love__sub { margin: 0; font-family: var(--hand); font-size: 1em; line-height: 1.5; opacity: 0; transition: opacity 1.2s ease 4.2s; }
.is-shown .love__sub { opacity: 1; }
.love__floats { position: absolute; inset: 0; pointer-events: none; }
.love__float {
  position: absolute;
  bottom: 30%;
  left: var(--x);
  color: #b8405a;
  font-size: calc(16px * var(--s));
  opacity: 0;
  animation: float-up var(--d) ease-in var(--delay) infinite;
}
@keyframes float-up {
  0% { transform: translateY(0) scale(.6); opacity: 0; }
  15% { opacity: .85; }
  100% { transform: translateY(-200px) scale(1.1); opacity: 0; }
}

/* The last page, blank on purpose. */
.page--last { justify-content: center; align-items: center; text-align: center; }
.last__text { margin: 0 0 .8em; max-width: 86%; font-family: var(--hand); font-size: 1.05em; line-height: 1.7; color: #5e3a2c; }
.last__heart svg { width: 1.6em; fill: #d8506d; }

/* Rose petals drifting past the book. */
.petals { position: absolute; inset: 0; overflow: hidden; pointer-events: none; z-index: 3; opacity: 0; transition: opacity 2s ease; }
.petals.is-on { opacity: 1; }
.petal {
  position: absolute;
  top: -6%;
  left: var(--x);
  width: calc(14px * var(--s));
  height: calc(18px * var(--s));
  border-radius: 80% 0 60% 20%;
  background: radial-gradient(circle at 30% 30%, rgba(255, 255, 255, .45), transparent 55%), var(--hue);
  box-shadow: inset -2px -2px 4px rgba(120, 20, 40, .25);
  animation: petal-fall var(--d) linear var(--delay) infinite;
}
@keyframes petal-fall {
  0% { transform: translate(0, 0) rotate(0deg) rotateX(0deg); }
  50% { transform: translate(var(--sway), 55svh) rotate(180deg) rotateX(160deg); }
  100% { transform: translate(calc(var(--sway) * -.4), 112svh) rotate(360deg) rotateX(340deg); }
}

.turn-hint {
  position: absolute;
  left: 50%;
  bottom: max(26px, 4.5svh);
  display: flex;
  align-items: center;
  gap: .55rem;
  padding: .55rem 1.1rem .55rem .8rem;
  transform: translateX(-50%);
  border-radius: 999px;
  border: 1px solid rgba(243, 194, 107, .35);
  background: rgba(24, 16, 36, .75);
  color: var(--candle-soft);
  font-size: .95rem;
  white-space: nowrap;
  opacity: 0;
  transition: opacity .6s ease;
  pointer-events: none;
}
.turn-hint.is-on { opacity: 1; }
.turn-hint__icon { width: 26px; height: 26px; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; animation: press 1.6s ease-in-out infinite; }
.turn-hint__ripple { stroke-width: 1; transform-origin: 10.5px 5px; animation: ripple 1.6s ease-out infinite; }
@keyframes press { 40% { transform: translateY(2px); } }
@keyframes ripple { 0%, 30% { transform: scale(.4); opacity: 0; } 45% { opacity: 1; } 100% { transform: scale(1.3); opacity: 0; } }

/* ---------- 3. Lanterns at the table ---------- */
.party { z-index: 3; pointer-events: none; }
.my-wish {
  position: absolute;
  left: 50%;
  top: max(14svh, 60px);
  width: min(calc(100% - 40px), 34rem);
  transform: translateX(-50%);
  text-align: center;
  font-family: var(--display);
  font-style: italic;
  font-size: clamp(1.4rem, 4.2vw, 2.2rem);
  line-height: 1.4;
  text-shadow: var(--glow);
  text-wrap: balance;
  opacity: 0;
  transition: opacity 1s ease;
}
/* A soft patch of night behind the wish, so it reads clearly whatever the sky is doing. */
.my-wish { padding: 1.4em 1.2em; background: radial-gradient(closest-side, rgba(8, 6, 18, .78), rgba(8, 6, 18, .5) 65%, transparent); }
.my-wish.is-on { opacity: 1; }
.my-wish p { margin: 0; }
.jackpot {
  position: absolute;
  left: 50%;
  top: max(16svh, 60px);
  width: min(calc(100% - 32px), 40rem);
  margin: 0;
  transform: translate(-50%, 12px);
  text-align: center;
  font-family: var(--display);
  font-style: italic;
  font-size: clamp(2.2rem, 7.4vw, 4.6rem);
  line-height: 1.06;
  color: #fff6e0;
  text-shadow: 0 0 34px rgba(255, 214, 140, .65), var(--glow);
  text-wrap: balance;
  opacity: 0;
  filter: blur(12px);
  transition: opacity 1.8s ease, filter 1.8s ease, transform 1.8s var(--ease-out);
}
.jackpot.is-on { opacity: 1; filter: none; transform: translate(-50%, 0); }
.jackpot__line { display: block; margin-top: .7em; font-size: max(.4em, 1.05rem); line-height: 1.4; color: var(--candle-soft); opacity: 0; transform: translateY(8px); transition: opacity 1.4s ease, transform 1.4s var(--ease-out); }
.jackpot__line:first-of-type { margin-top: 1em; }
.jackpot__line.is-on { opacity: 1; transform: none; }
.jackpot { padding: .4em .6em; background: radial-gradient(closest-side, rgba(8, 6, 18, .6), transparent); }
.signature {
  position: absolute;
  left: 16px; right: 16px;
  bottom: max(30px, 5.5svh);
  margin: 0;
  text-align: center;
  font-family: var(--hand);
  color: var(--muted);
  font-size: 1.05rem;
  text-shadow: var(--glow);
  opacity: 0;
  transition: opacity 1.6s ease;
}
.signature.is-on { opacity: 1; }

/* ---------- Sound ---------- */
.sound-btn {
  position: fixed;
  top: max(14px, env(safe-area-inset-top));
  right: 14px;
  z-index: 10;
  display: grid;
  place-items: center;
  width: 40px; height: 40px;
  padding: 0;
  border: 1px solid rgba(243, 194, 107, .3);
  border-radius: 50%;
  background: rgba(18, 12, 30, .55);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  cursor: pointer;
}
.sound-btn svg { width: 18px; height: 18px; fill: none; stroke: var(--candle-soft); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.sound-btn__mute { display: none; }
.sound-btn.is-muted .sound-btn__waves { display: none; }
.sound-btn.is-muted .sound-btn__mute { display: inline; }

@media (prefers-reduced-motion: reduce) {
  .whisper.is-on .whisper__ch, .balloon, .garland.is-on .bulb__glow, .welcome.is-ready .welcome__tap, .final__num.is-beat, .final__ring.is-beat, .gate__flame span, .tap-hint.is-on, .turn-hint__icon, .turn-hint__ripple, .love__float, .is-shown .love__stage, .petal { animation: none; }
  .scene.is-lit .title .ch, .is-shown .love__ch, .whisper.is-on .whisper__ch { animation: none; opacity: 1; filter: none; transform: none; }
  .sheet { transition-duration: .01s; }
  .w, .narration { transition-duration: .01s; filter: none; }
}

/* ?dev only: skip or jump between parts while you work on them. */
.devbar {
  position: fixed; left: 12px; bottom: max(12px, env(safe-area-inset-bottom)); z-index: 1000;
  display: flex; gap: 6px; padding: 5px;
  border-radius: 999px; border: 1px solid rgba(255, 255, 255, .14);
  background: rgba(12, 10, 18, .72); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  font: 500 13px/1 var(--body); user-select: none;
}
.devbar select, .devbar button {
  font: inherit; color: #f4ece6; cursor: pointer;
  padding: 8px 12px; border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, .16); background: rgba(255, 255, 255, .08);
}
.devbar option { color: #1b1720; background: #fff; }
.devbar button:hover:not(:disabled) { background: rgba(255, 255, 255, .16); }
.devbar button:disabled { opacity: .4; cursor: default; }
.devbar :focus-visible { outline: 2px solid #f3c27a; outline-offset: 2px; }
/* On a wide screen the table is on the left, so the last words sit over the open lake on the right. */
@media (min-aspect-ratio: 5/4) {
  .my-wish, .jackpot { left: 62%; width: min(calc(70% - 32px), 34rem); }
}
