:root {
  --bg: #03050a;
  --bg-2: #0a1018;
  --fg: #f4f1ea;
  --muted: #8b94a3;
  --rose: #e7bcc6;
  --accent: #e7bcc6;
  --blue: #9fb8e0;
  --gold: #ecc98c;
  --line: rgba(180,200,230,.16);
  --ease: cubic-bezier(.2,.7,.2,1);
  --serif: "Cormorant Garamond", Georgia, serif;
  --sans: "Jost", system-ui, sans-serif;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html { background: var(--bg); }
html, body {
  background: var(--bg); color: var(--fg);
  font-family: var(--serif);
  -webkit-font-smoothing: antialiased; overflow-x: clip;
  text-rendering: optimizeLegibility;
  overscroll-behavior: none;
}
body.locked { overflow: hidden; height: 100svh; }
.kern { font-family: var(--sans); }
::selection { background: rgba(236,201,140,.3); color: #fff; }

/* ---------- Ambient layers ---------- */
.grain { position: fixed; inset: -60%; z-index: 70; pointer-events: none; opacity: .045;
  width: 220%; height: 220%; will-change: transform;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: grainshift .5s steps(1) infinite; }
@keyframes grainshift {
  0%{transform:translate(0,0)} 12%{transform:translate(-4%,3%)} 25%{transform:translate(3%,-4%)}
  37%{transform:translate(-3%,-2%)} 50%{transform:translate(4%,2%)} 62%{transform:translate(-2%,4%)}
  75%{transform:translate(2%,-3%)} 87%{transform:translate(-4%,-3%)} 100%{transform:translate(0,0)} }
@media (prefers-reduced-motion: reduce){ .grain{ animation: none; } }
.vignette { position: fixed; inset: 0; z-index: 69; pointer-events: none;
  background: radial-gradient(120% 100% at 50% 38%, transparent 52%, rgba(0,0,0,.6) 100%); }

/* ---------- Cinematic light leak (analog flare on section transitions) ---------- */
.leak { position: fixed; inset: -10%; z-index: 72; pointer-events: none; opacity: 0;
  mix-blend-mode: screen; will-change: opacity, transform;
  background:
    radial-gradient(38% 64% at 50% 50%, rgba(255,231,182,.92), rgba(255,186,128,.42) 42%, rgba(255,150,110,.10) 64%, transparent 74%),
    radial-gradient(14% 30% at 50% 38%, rgba(255,245,225,.85), transparent 70%);
  background-repeat: no-repeat; background-size: 72% 150%, 30% 60%;
  background-position: -45% var(--leak-y, 50%), -45% var(--leak-y, 42%);
  transform: rotate(var(--leak-rot, 16deg)); }
.leak.sweep { animation: leaksweep var(--leak-dur, 1.25s) cubic-bezier(.33,.66,.3,1); }
@keyframes leaksweep {
  0%   { opacity: 0;                          background-position: -45% var(--leak-y,50%), -45% var(--leak-y,42%); }
  18%  { opacity: var(--leak-peak, .8); }
  100% { opacity: 0;                          background-position: 145% var(--leak-y,50%), 145% var(--leak-y,42%); }
}

/* ---------- Title sequence (auto-timed film open) ---------- */
.titleseq { position: fixed; inset: 0; z-index: 88; background: #000;
  display: grid; place-items: center; overflow: hidden; }
.titleseq[hidden] { display: none; }
.titleseq.done { opacity: 0; transition: opacity 1s ease; pointer-events: none; }
.ts-card { position: absolute; display: grid; justify-items: center; gap: 1rem; text-align: center;
  padding: 2rem; opacity: 0; }
.ts-studio { font-family: var(--sans); font-weight: 300; letter-spacing: .5em; text-transform: uppercase;
  font-size: clamp(.78rem, 3.6vw, 1.05rem); color: #d9cfc0; padding-left: .5em; }
.ts-presents { font-family: var(--serif); font-style: italic; color: var(--muted);
  font-size: clamp(.85rem, 3.6vw, 1.05rem); letter-spacing: .04em; }
.ts-title { font-family: var(--serif); font-weight: 500; font-style: italic; line-height: 1.05;
  font-size: clamp(2.5rem, 12vw, 4.6rem); color: #f3ece0;
  text-shadow: 0 0 50px rgba(236,201,140,.22); animation: tsdrift 8s ease-out both; }
.ts-dates { font-family: var(--sans); font-weight: 300; letter-spacing: .42em; text-transform: uppercase;
  font-size: clamp(.62rem, 3vw, .78rem); color: var(--gold); padding-left: .42em; }
.titleseq.play .ts-1 { animation: tscard 2.9s ease both; }
.titleseq.play .ts-2 { animation: tscard 2.9s ease 2.9s both; }
@keyframes tscard { 0%{opacity:0; transform:translateY(10px) scale(.99)}
  16%{opacity:1; transform:none} 72%{opacity:1; transform:translateY(-4px) scale(1.01)}
  100%{opacity:0; transform:translateY(-10px) scale(1.02)} }
@keyframes tsdrift { from{transform:scale(1.07)} to{transform:scale(1)} }
/* warm projector flare crossing the title cards */
.ts-flare { position: absolute; inset: -20%; pointer-events: none; mix-blend-mode: screen; opacity: 0;
  background: radial-gradient(40% 70% at 50% 42%, rgba(255,231,182,.5), rgba(255,180,120,.16) 46%, transparent 70%);
  background-repeat: no-repeat; background-size: 60% 130%; background-position: -50% 42%; }
.titleseq.play .ts-flare { animation: tsflare 5.8s ease-in-out both; }
@keyframes tsflare { 0%{opacity:0; background-position:-50% 42%} 20%{opacity:.7}
  50%{opacity:.5; background-position:60% 42%} 80%{opacity:.6} 100%{opacity:0; background-position:150% 42%} }
@media (prefers-reduced-motion: reduce){
  .titleseq.play .ts-1, .titleseq.play .ts-2 { animation-duration: .01s; }
  .ts-title, .ts-flare { animation: none; } }

/* ---------- Bokeh: soft drifting lights, depth via size + blur + speed ---------- */
.bokeh { position: fixed; inset: 0; z-index: 2; pointer-events: none; overflow: hidden; mix-blend-mode: screen; }
.bokeh b { position: absolute; border-radius: 50%; opacity: 0;
  background: radial-gradient(circle, rgba(214,224,240,.6) 0%, rgba(188,202,226,.18) 44%, transparent 70%);
  filter: blur(var(--bk-blur, 6px)); will-change: transform, opacity;
  animation: bokehdrift var(--bk-dur, 22s) ease-in-out var(--bk-delay, 0s) infinite; }
@keyframes bokehdrift {
  0%   { transform: translate3d(0,0,0) scale(.9);             opacity: 0; }
  18%  {                                                      opacity: var(--bk-op, .5); }
  50%  { transform: translate3d(var(--bk-dx,20px), var(--bk-dy,-40px),0) scale(1.08); opacity: var(--bk-op, .5); }
  82%  {                                                      opacity: var(--bk-op, .5); }
  100% { transform: translate3d(0,0,0) scale(.9);            opacity: 0; }
}

/* ---------- Living light: a sheen that slides across glossy surfaces with device tilt ---------- */
.pol-photo, .ded-photo, .hg-stage { position: relative; }
.pol-photo::after, .ded-photo::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; z-index: 2; mix-blend-mode: screen;
  background: radial-gradient(60% 55% at calc(50% + var(--gx,0) * 38%) calc(32% + var(--gy,0) * 30%),
    rgba(255,255,255,.30), rgba(255,255,255,.07) 38%, transparent 62%);
  transition: background-position .12s linear; }
.hg-stage::after {
  content: ""; position: absolute; inset: 6%; pointer-events: none; z-index: 4; mix-blend-mode: screen; border-radius: 50% 50% 46% 46%;
  background: radial-gradient(46% 40% at calc(42% + var(--gx,0) * 34%) calc(26% + var(--gy,0) * 26%),
    rgba(255,255,255,.5), rgba(255,255,255,.12) 40%, transparent 60%); }
.heartgate.unlocking .hg-stage::after { opacity: 0; transition: opacity .5s ease; }

/* ---------- Opening constellation (stars draw a heart, then dissolve into the first line) ---------- */
.open-beat.has-constellation { position: relative; }
.constellation { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 0; pointer-events: none;
  opacity: 0; transition: opacity 1.4s ease; }
.constellation.lit { opacity: 1; }
.open-beat.has-constellation .open-line, .open-beat.has-constellation .scroll-cue { position: relative; z-index: 1; }

/* discreet scroll progress (top hairline) */
.progress { position: fixed; top: 0; left: 0; right: 0; height: 2px; z-index: 65; pointer-events: none; background: rgba(255,255,255,.04); }
.progress-fill { display: block; height: 100%; width: 0;
  background: linear-gradient(90deg, var(--rose), var(--gold));
  box-shadow: 0 0 8px rgba(236,201,140,.5); transition: width .12s linear; }

/* ---------- Boot: fade from black (projector coming on) ---------- */
.boot { position: fixed; inset: 0; z-index: 90; background: #000; pointer-events: none;
  opacity: 1; transition: opacity 1s ease; }
.boot.gone { opacity: 0; }

/* ---------- Gate ---------- */
.gate {
  position: fixed; inset: 0; z-index: 60; display: grid; place-items: center;
  background: radial-gradient(135% 120% at 50% 36%, #0c121d 0%, #03050a 72%);
  transition: opacity 1.1s ease;
}
.gate.hidden { opacity: 0; pointer-events: none; }
/* ---------- Gold locket gate: a real engraved heart that opens like a locket ---------- */
.heartgate { position: relative; background: none; border: 0; padding: 2.5rem; cursor: pointer;
  -webkit-tap-highlight-color: transparent; display: grid; place-items: center;
  opacity: 0; transform: translateY(10px); transition: opacity 1.6s ease, transform 1.6s var(--ease); }
body.fonts-ready .heartgate { opacity: 1; transform: none; }

.hg-stage { position: relative; width: clamp(168px, 60vw, 268px); aspect-ratio: 571 / 680;
  transform-style: preserve-3d; perspective: 1300px;
  animation: heartbeat 2.6s ease-in-out infinite; transform-origin: 50% 56%;
  transition: transform .5s var(--ease); }

/* two engraved gold halves of the same locket image, meeting at the centre seam */
.lk-half { position: absolute; top: 0; bottom: 0; width: 50%; backface-visibility: hidden;
  background-image: url("assets/locket.png"); background-repeat: no-repeat; background-size: 200% 100%;
  filter: drop-shadow(0 18px 40px rgba(0,0,0,.55)) drop-shadow(0 0 22px rgba(236,201,140,.18));
  transition: transform 1.35s cubic-bezier(.45,.05,.2,1); }
.lk-left  { left: 0;  background-position: left center;  transform-origin: right center; }
.lk-right { right: 0; background-position: right center; transform-origin: left center; }
/* hairline warm seam down the middle, like the locket's closure */
.hg-stage::before { content: ""; position: absolute; top: 12%; bottom: 8%; left: 50%; width: 1px; z-index: 2;
  transform: translateX(-.5px); background: linear-gradient(rgba(255,225,170,0), rgba(120,80,30,.45) 30%, rgba(120,80,30,.45) 70%, rgba(255,225,170,0));
  transition: opacity .5s ease; }

/* warm light living inside the locket, revealed as it opens */
.hg-glow { position: absolute; left: 50%; top: 52%; width: 86%; aspect-ratio: 1; transform: translate(-50%,-50%) scale(.12);
  border-radius: 50%; opacity: 0; pointer-events: none; z-index: 0;
  background: radial-gradient(circle, rgba(255,242,210,.98) 0%, rgba(255,206,140,.58) 32%, rgba(255,176,112,.12) 60%, transparent 74%);
  transition: opacity 1s ease .2s, transform 1.35s var(--ease) .2s; }

@keyframes heartbeat { 0%,100%{transform:scale(1)} 14%{transform:scale(1.04)} 28%{transform:scale(1)} 42%{transform:scale(1.025)} 56%{transform:scale(1)} }

/* gentle "tocca" hint under the locket, fades away the instant she opens it */
.gate-hint { position: absolute; left: 50%; bottom: .2rem; transform: translateX(-50%);
  font-family: "Caveat", cursive; font-size: 1.5rem; color: rgba(236,201,140,.6); letter-spacing: .02em;
  animation: hintbob 2.6s ease-in-out infinite; transition: opacity .5s ease; }
@keyframes hintbob { 0%,100%{opacity:.4} 50%{opacity:.85} }
.heartgate.unlocking .gate-hint { opacity: 0; animation: none; }
@media (prefers-reduced-motion: reduce){ .gate-hint{ animation: none; } }

/* opening */
.heartgate.unlocking .hg-stage { animation: none; transform: scale(1); }
.heartgate.unlocking .hg-stage::before { opacity: 0; }
.heartgate.unlocking .lk-left  { transform: rotateY(-158deg); }
.heartgate.unlocking .lk-right { transform: rotateY(158deg); }
.heartgate.unlocking .hg-glow  { opacity: 1; transform: translate(-50%,-50%) scale(1.5); }

/* ---------- Opening that builds ---------- */
.opening { position: relative; }
.open-beat { min-height: 100svh; display: grid; place-content: center; align-content: center; justify-items: center;
  text-align: center; gap: 1.5rem; padding: 2rem; }
/* slow camera breath: the whole frame drifts so it never sits still (container scale = no clash with child reveals) */
.open-beat { animation: camdrift 16s ease-in-out infinite alternate; }
@keyframes camdrift { from{transform:scale(1.012)} to{transform:scale(1.05)} }
@media (prefers-reduced-motion: reduce){ .open-beat{ animation: none; } }
.open-line { font-size: clamp(2rem, 9vw, 3.4rem); font-weight: 400; line-height: 1.34; font-style: italic; color: #ece5db; max-width: 16ch; letter-spacing: .012em; }
.open-sub { font-family: var(--serif); font-style: italic; font-size: clamp(1.05rem, 4.6vw, 1.5rem); line-height: 1.45; color: var(--muted); max-width: 22ch; margin-top: .2rem; }
.opening-kicker { font-family: var(--sans); color: var(--muted); letter-spacing: .42em; text-transform: uppercase; font-size: .7rem; font-weight: 300; }
.opening-line { font-size: clamp(2rem, 8.5vw, 3.6rem); font-weight: 400; line-height: 1.28; font-style: italic; letter-spacing: .005em; }
.opening-line .reveal-word { display: inline-block; }
.scroll-cue { font-family: var(--sans); color: var(--muted); font-size: .68rem; letter-spacing: .26em; text-transform: lowercase; margin-top: 1.2rem; animation: bob 2s ease-in-out infinite; }
@keyframes bob { 0%,100%{transform:translateY(0);opacity:.55} 50%{transform:translateY(6px);opacity:1} }

.reveal-word { opacity: 0; transform: translateY(16px); transition: opacity .9s var(--ease), transform .9s var(--ease); }
.reveal-word.in { opacity: 1; transform: none; }
.reveal-up { opacity: 0; transform: translateY(30px); transition: opacity 1s var(--ease), transform 1s var(--ease); }
.reveal-up.in { opacity: 1; transform: none; }

/* ---------- Deck: swipeable polaroids ---------- */
.deck-region { position: relative; min-height: 100svh; display: grid; place-items: center; padding: 8vh 1rem;
  overflow: clip;   /* contain the off-stage cards so they never create horizontal scroll */
  background: radial-gradient(140% 110% at 50% 30%, #1a1410 0%, #0a0805 55%, var(--bg) 100%); }
.deck-region::before { content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(60% 44% at 50% 50%, rgba(120,90,55,.16), transparent 70%); }
.deck-kicker { position: absolute; top: 7vh; left: 0; right: 0; text-align: center; font-family: var(--sans);
  color: var(--muted); letter-spacing: .34em; text-transform: uppercase; font-size: .7rem; font-weight: 300; }

.deck { position: relative; width: min(78vw, 350px); aspect-ratio: 1 / 1.34; touch-action: pan-y; cursor: grab; }
.deck:active { cursor: grabbing; }

.polaroid {
  position: absolute; left: 50%; top: 50%; width: 100%;
  background: #f7f4ec; padding: 4% 4% 15%; border-radius: 3px;
  box-shadow: 0 30px 60px rgba(0,0,0,.55), 0 2px 6px rgba(0,0,0,.4);
  transform: translate(-50%,-50%);
  transition: transform .6s var(--ease), opacity .5s var(--ease); user-select: none; }
.pol-photo {
  width: 100%; aspect-ratio: 1/1; background-size: cover; background-position: center;
  background-color: #2a2520; box-shadow: inset 0 0 0 1px rgba(0,0,0,.06); pointer-events: none; }
.pol-cap {
  font-family: "Caveat", cursive; color: #2c2622; text-align: center;
  font-size: clamp(1.5rem, 6vw, 2rem); line-height: 1; margin-top: 7%;
  display: flex; align-items: baseline; justify-content: center; gap: .5em; flex-wrap: wrap; }
.pol-cap span { font-size: .72em; color: #8a7f72; }
.pol-cap .pol-note { font-size: 1em; color: #2c2622; line-height: 1.05; }

/* chapter title card (a written Polaroid that names the place) */
.polaroid.is-title .pol-titleface {
  display: grid; place-content: center; gap: .25rem; text-align: center;
  background-image: radial-gradient(120% 100% at 50% 30%, #f3ecd8, #e7dcc0);
  box-shadow: inset 0 0 0 1px rgba(120,90,50,.12); }
.pt-name { font-family: "Caveat", cursive; color: #2c2622; font-size: clamp(2.4rem, 11vw, 3.4rem); line-height: 1; }
.pt-date { font-family: var(--sans); color: #9a8c76; letter-spacing: .22em; text-transform: uppercase; font-size: .6rem; }
.pol-blurb { font-style: italic; }
.pol-blurb.pol-cap { font-family: "Cormorant Garamond", serif; color: #4a4138; font-size: 1.05rem; }

/* ---------- The pivot: past → future, alone in the dark ---------- */
.pivot { min-height: 100svh; display: grid; place-content: center; text-align: center; padding: 2.5rem;
  background: #000; }
.pivot-line { font-family: var(--serif); font-style: italic; font-size: clamp(1.9rem, 8vw, 3rem);
  line-height: 1.42; color: #ece5db; max-width: 17ch; letter-spacing: .01em; }
.pivot-line .reveal-word { display: inline-block; }

/* the card in her hand sits proud of the stack */
.polaroid.active { box-shadow: 0 40px 80px rgba(0,0,0,.62), 0 6px 16px rgba(0,0,0,.45), 0 0 50px rgba(120,90,55,.22); }

/* washi tape on the chapter title cards (scrapbook touch) */
.polaroid.is-title::before, .polaroid.is-title::after {
  content: ""; position: absolute; top: -10px; width: 64px; height: 26px; z-index: 2;
  background: rgba(231,221,196,.42); box-shadow: 0 2px 5px rgba(0,0,0,.22);
  border-left: 1px solid rgba(255,255,255,.18); border-right: 1px solid rgba(255,255,255,.18); }
.polaroid.is-title::before { left: 16px; transform: rotate(-7deg); }
.polaroid.is-title::after  { right: 16px; transform: rotate(6deg); }

.deck-ui { position: absolute; bottom: 10vh; left: 0; right: 0; display: flex; align-items: center; justify-content: center; gap: 1.4rem; }
.deck-arrow { background: rgba(255,255,255,.06); border: 1px solid rgba(255,255,255,.18); color: var(--fg);
  width: 40px; height: 40px; border-radius: 50%; font-size: 1.3rem; line-height: 1; cursor: pointer;
  transition: border-color .2s, background .2s; }
.deck-arrow:hover { border-color: rgba(255,255,255,.45); background: rgba(255,255,255,.1); }
.deck-dots { display: flex; gap: 7px; }
.deck-dot { width: 6px; height: 6px; border-radius: 50%; background: rgba(255,255,255,.22); transition: background .3s, transform .3s; }
.deck-dot.on { background: var(--rose); transform: scale(1.3); }
.deck-hint { position: absolute; bottom: 5vh; left: 0; right: 0; text-align: center; font-family: var(--sans);
  color: var(--muted); font-size: .72rem; letter-spacing: .16em; animation: hintpulse 2.6s ease-in-out infinite; }

/* ---------- Globe: the world to discover ---------- */
.globe-region { position: relative; }
.globe-stage { position: sticky; top: 0; height: 100svh; overflow: hidden;
  background: radial-gradient(150% 100% at 50% 30%, var(--bg-2) 0%, var(--bg) 78%); }
.globe { position: absolute; inset: 0; }
.globe canvas { display: block; transform: translateZ(0); }
/* fallback if globe.gl never loads: a soft starfield so the beat never collapses */
.globe-fallback { background:
  radial-gradient(1px 1px at 20% 30%, rgba(255,255,255,.7), transparent),
  radial-gradient(1px 1px at 70% 25%, rgba(255,255,255,.5), transparent),
  radial-gradient(1px 1px at 40% 60%, rgba(231,188,198,.7), transparent),
  radial-gradient(1px 1px at 85% 65%, rgba(190,212,250,.6), transparent),
  radial-gradient(1.5px 1.5px at 55% 45%, rgba(236,201,140,.8), transparent),
  radial-gradient(120% 90% at 50% 40%, #0c1422 0%, var(--bg) 80%); }
.globe-cap { position: absolute; inset: 0; display: grid; place-content: center; text-align: center; gap: .7rem; padding: 2rem; pointer-events: none; }
.gc-line { font-style: italic; font-size: clamp(1.8rem, 7.5vw, 2.9rem); line-height: 1.3; color: #eee7dd; max-width: 16ch; margin: 0 auto;
  text-shadow: 0 3px 30px rgba(0,0,0,.85); }
.gc-sub { font-family: var(--sans); color: var(--blue); letter-spacing: .14em; font-size: .82rem; font-weight: 300; margin-top: .5rem; }
.futuredot { width: 8px; height: 8px; border-radius: 50%; transform: translate(-50%,-50%);
  background: radial-gradient(circle, rgba(190,212,250,.95), rgba(120,150,210,.15));
  box-shadow: 0 0 10px rgba(159,184,224,.7); pointer-events: none;
  animation: twinkle 3s ease-in-out infinite; }
@keyframes twinkle { 0%,100%{ opacity:.5; box-shadow:0 0 6px rgba(159,184,224,.5); } 50%{ opacity:1; box-shadow:0 0 14px rgba(190,212,250,.9); } }
.globe-spacer { height: 70vh; }

/* ---------- The surprise: a polaroid that develops ---------- */
.reveal-region { position: relative; min-height: 100svh; display: grid; place-items: center; padding: 10vh 1rem; text-align: center;
  background: radial-gradient(85% 60% at 50% 46%, rgba(236,201,140,.14), transparent 72%), var(--bg); }
.rr-kicker { position: absolute; top: 13vh; left: 0; right: 0; font-family: var(--sans); color: var(--gold);
  letter-spacing: .32em; text-transform: uppercase; font-size: .72rem; font-weight: 400;
  display: inline-flex; align-items: center; justify-content: center; gap: .9em; }
.rr-kicker::before, .rr-kicker::after { content: ""; width: 26px; height: 1px; background: rgba(236,201,140,.55); }
.reveal-pol { position: relative; left: auto; top: auto; width: min(74vw, 330px);
  border: 0; font: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent;
  transform: translateY(40px) rotate(-2.5deg) scale(.9); opacity: 0;
  transition: transform .9s var(--ease), opacity .9s var(--ease);
  box-shadow: 0 36px 80px rgba(0,0,0,.6), 0 0 60px rgba(236,201,140,.25); }
.reveal-region.show .reveal-pol:not(.developed) { animation: tapnudge 2.4s ease-in-out infinite; }
@keyframes tapnudge {
  0%,100%{ transform: translateY(0) rotate(-2.5deg) scale(1); box-shadow: 0 36px 80px rgba(0,0,0,.6), 0 0 50px rgba(236,201,140,.2); }
  50%{ transform: translateY(-5px) rotate(-2deg) scale(1.015); box-shadow: 0 42px 90px rgba(0,0,0,.6), 0 0 85px rgba(236,201,140,.55); } }
.reveal-region.show .reveal-pol { transform: translateY(0) rotate(-2.5deg) scale(1); opacity: 1; }
.dest-photo { display: grid; place-content: center; gap: .3rem;
  background-image: url('assets/islanda-collage.jpg');
  background-size: cover; background-position: center; }
.dest-place { font-family: var(--serif); font-weight: 600; line-height: 1.04; font-size: clamp(1.9rem, 8.5vw, 2.7rem);
  background: linear-gradient(180deg, #fff 0%, var(--gold) 135%); -webkit-background-clip: text; background-clip: text; color: transparent;
  text-shadow: 0 0 36px rgba(236,201,140,.35); }
.dest-date { font-family: var(--sans); color: var(--gold); letter-spacing: .16em; text-transform: uppercase; font-size: .68rem; margin-top: .6rem; }
/* printed date stamp, like a real photo lab imprint */
.dest-stamp { position: absolute; right: 7%; bottom: 7%; z-index: 3;
  font-family: "Courier New", ui-monospace, monospace; font-size: .82rem; letter-spacing: .04em; font-weight: 700;
  color: #ff8a3d; text-shadow: 0 0 7px rgba(255,138,61,.85), 0 0 2px rgba(255,170,90,.9); opacity: .92; }
.scratch { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 4;
  border-radius: inherit; touch-action: none; cursor: grab; pointer-events: auto; transition: opacity .6s ease; }
.reveal-pol.developed .scratch { opacity: 0; pointer-events: none; }
.rr-tap { position: absolute; bottom: 11vh; left: 0; right: 0; text-align: center; font-family: var(--sans);
  color: var(--gold); letter-spacing: .18em; font-size: .74rem; text-transform: lowercase;
  opacity: 0; transition: opacity .8s ease .6s; animation: hintpulse 2.2s ease-in-out infinite; }
.reveal-region.show .rr-tap { opacity: 1; }
.reveal-region.developed .rr-tap { opacity: 0 !important; animation: none; transition: opacity .35s ease; }

.rr-note { position: absolute; bottom: 11vh; left: 0; right: 0; color: #ddd5cb; font-style: italic;
  font-size: 1.18rem; max-width: 24ch; margin: 0 auto; line-height: 1.45; padding: 0 1.4rem;
  opacity: 0; transition: opacity 1.2s ease 1.6s; }    /* let the destination breathe before the note arrives */
.reveal-region.developed .rr-note { opacity: 1; }
.rr-note.typing::after { content: "▏"; color: var(--gold); animation: caret .7s step-end infinite; }
@keyframes caret { 50% { opacity: 0; } }
/* warm Polaroid flash when she develops the photo (soft, not a camera strobe) */
.flash { position: fixed; inset: 0; z-index: 80; background: radial-gradient(circle at 50% 46%, #fff6e6, #ffe9c8); opacity: 0; pointer-events: none; }
.flash.pop { animation: flashpop .65s ease-out; }
@keyframes flashpop { 0%{opacity:0} 14%{opacity:.5} 100%{opacity:0} }

/* ---------- Finale: out of the screen, the last quiet word ---------- */
.finale { min-height: 72svh; display: grid; place-items: center; text-align: center; padding: 12vh 1.6rem;
  background: radial-gradient(120% 90% at 50% 50%, #0a0c12 0%, #020308 75%); }
.finale-line { font-style: italic; font-size: clamp(2.2rem, 9.5vw, 3.7rem); line-height: 1.4; color: #f1eadf; max-width: 17ch;
  text-shadow: 0 2px 40px rgba(0,0,0,.6); }
.signature { font-family: "Caveat", cursive; color: rgba(231,188,198,.9); font-size: clamp(1.7rem, 7vw, 2.3rem); letter-spacing: .03em; }
.sig-heart { display: inline-block; color: #e7414f; animation: sigbeat 2.4s ease-in-out infinite; }
@keyframes sigbeat { 0%,100%{transform:scale(1)} 14%{transform:scale(1.18)} 28%{transform:scale(1)} 42%{transform:scale(1.1)} 56%{transform:scale(1)} }
@media (prefers-reduced-motion: reduce){ .sig-heart{ animation: none; } }

/* closing line: letters arrive one by one */
.stagger-letters .ch { display: inline-block; opacity: 0; transform: translateY(22px); white-space: pre;
  transition: opacity .6s var(--ease), transform .6s var(--ease); }
.stagger-letters.in .ch { opacity: 1; transform: none; }

/* scroll cue retires for good once she starts scrolling */
body.scrolled .scroll-cue { opacity: 0 !important; animation: none !important; transition: opacity .6s ease; pointer-events: none; }

.scroll-track { position: relative; z-index: 2; }

/* ---------- Le foto buffe (playful interlude) ---------- */
.funny { position: relative; z-index: 3; padding: 16vh 1.2rem 14vh; text-align: center;
  background: radial-gradient(130% 80% at 50% 8%, #17120b 0%, #0a0805 55%, var(--bg) 100%); }
.funny-kicker { font-family: var(--sans); color: var(--muted); letter-spacing: .34em; text-transform: uppercase; font-size: .7rem; font-weight: 300; }
.funny-intro { margin-top: 1rem; font-style: italic; font-size: clamp(1.5rem, 6.5vw, 2.2rem); color: #ece5db; }
.funny-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1.1rem .9rem; max-width: 540px; margin: 8vh auto; align-items: start; }
.funny-pic { background: #f7f4ec; padding: 5% 5% 12%; border-radius: 3px;
  box-shadow: 0 16px 38px rgba(0,0,0,.5);
  opacity: 0; transform: translateY(28px) rotate(var(--r)) scale(.94);
  transition: opacity 1s var(--ease), transform 1s var(--ease); }
.funny-pic.in { opacity: 1; transform: translateY(0) rotate(var(--r)) scale(1); }
.funny-pic:nth-child(even) { margin-top: 1.8rem; }   /* staggered, scrapbook feel */
.funny-pic img { width: 100%; aspect-ratio: 3/4; object-fit: cover; display: block; }
.funny-punch { margin: 5vh auto 0; font-style: italic; font-size: clamp(1.5rem, 6.5vw, 2.3rem); line-height: 1.4; color: #f1eadf; max-width: 20ch; }

/* ---------- Dediche (editorial) ---------- */
.dediche { position: relative; z-index: 3; background:
  radial-gradient(130% 80% at 50% 8%, #0c1118 0%, #060810 55%, var(--bg) 100%); padding: 20vh 0 16vh; }
.ded-intro { text-align: center; font-style: italic; font-size: clamp(1.55rem, 7vw, 2.5rem); line-height: 1.4;
  max-width: 22ch; margin: 0 auto 16vh; padding: 0 1.4rem; color: #efe8de; }
.dedica { position: relative; margin: 0 auto 17vh; max-width: 600px; padding: 0 1.2rem; }
.ded-photo { width: 100%; aspect-ratio: 4/5; border-radius: 6px; background-size: cover; background-position: center;
  background-color: #0e131c;   /* graceful tone if the photo isn't placed yet */
  background-image: radial-gradient(120% 100% at 50% 30%, #141b27, #0a0e16);
  box-shadow: 0 34px 80px rgba(0,0,0,.62); border: 1px solid rgba(255,255,255,.07); transform: scale(1.0); }
.dedica.in .ded-photo { animation: kenburns 18s linear forwards; }
@keyframes kenburns { from { transform: scale(1.0); } to { transform: scale(1.08); } }
.dedica figcaption { margin-top: 2rem; text-align: center; display: grid; justify-items: center; gap: .9rem; }
.dedica figcaption::before { content: ""; width: 30px; height: 1px; background: linear-gradient(90deg, transparent, rgba(231,188,198,.6), transparent); }
.ded-tag { font-family: var(--sans); color: var(--rose); letter-spacing: .26em; text-transform: uppercase; font-size: .66rem; font-weight: 400; }
.dedica figcaption p { font-style: italic; font-size: 1.4rem; line-height: 1.45; color: #ece5db; max-width: 30ch; }
/* if a dedica photo is missing, keep the elegant dark tone + a discreet heart instead of an empty frame */
.dedica.img-missing .ded-photo::before { content: "\2764"; position: absolute; inset: 0; display: grid; place-items: center;
  font-size: 2.4rem; color: rgba(231,188,198,.34); }

/* typographic polish: balance headings so no orphan word drops alone on the last line */
.open-line, .opening-line, .closing-line, .closing-sub, .finale-line,
.ded-intro, .funny-punch, .gc-line, .gc-sub, .rr-note { text-wrap: balance; }
.dedica figcaption p { text-wrap: pretty; }

/* ---------- Closing ---------- */
.closing { position: relative; z-index: 3; text-align: center; padding: 26vh 1.4rem; background: var(--bg); display: grid; justify-items: center; gap: 1.4rem; }
.closing-line { font-size: clamp(2.2rem, 11vw, 3.6rem); font-weight: 500; color: var(--rose); letter-spacing: .01em; }
.closing-line::after { content: ""; display: block; width: 42px; height: 1px; margin: 1.4rem auto 0; background: linear-gradient(90deg, transparent, rgba(231,188,198,.7), transparent); }
.closing-sub { color: #d4cec4; font-style: italic; font-size: 1.25rem; line-height: 1.5; }

/* ---------- Mute ---------- */
.mute { position: fixed; right: calc(1rem + env(safe-area-inset-right)); bottom: calc(1rem + env(safe-area-inset-bottom)); z-index: 50; width: 46px; height: 46px; border-radius: 50%;
  background: rgba(8,10,16,.5); border: 1px solid rgba(244,241,234,.22); color: var(--fg); font-size: 1.05rem; cursor: pointer;
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); transition: border-color .25s ease, color .25s ease; }
.mute:hover { border-color: rgba(244,241,234,.5); }
.mute.off { color: var(--muted); }

/* ---------- Focus (keyboard accessibility) ---------- */
:focus-visible { outline: 2px solid rgba(236,201,140,.85); outline-offset: 4px; border-radius: 4px; }
.heartgate:focus-visible, .reveal-pol:focus-visible { outline-offset: 8px; }
:focus:not(:focus-visible) { outline: none; }

/* ---------- Short / landscape screens ---------- */
@media (max-height: 560px) {
  .deck { width: min(46vh, 230px); }
  .deck-kicker { top: 4vh; }
  .deck-ui { bottom: 5vh; }
  .deck-hint { bottom: 2vh; }
  .reveal-pol { width: min(46vh, 220px); }
  .rr-kicker { top: 7vh; }
  .opening { min-height: 100svh; }
}

@media (prefers-reduced-motion: reduce) {
  .reveal-up, .reveal-word { transition-duration: .4s; }
  .scroll-cue, .dedica.in .ded-photo, .hg-stage, .futuredot, .deck-hint,
  .reveal-region.show .reveal-pol:not(.developed), .rr-tap, .leak.sweep, .bokeh b { animation: none !important; }
  .bokeh { display: none; }
  .progress-fill { transition: none; }
  /* calm the locket open: fade the halves instead of the long 3D swing */
  .lk-half, .hg-glow { transition-duration: .35s; }
  .heartgate.unlocking .lk-left, .heartgate.unlocking .lk-right { transform: none; opacity: 0; }
}

/* ---------- Graceful image fallbacks (until Paolo places the real photos) ---------- */
.funny-pic img.broken { visibility: hidden; }
.funny-pic.is-empty { background:
  radial-gradient(120% 100% at 50% 30%, #141b27, #0a0e16) #0e131c; }
.funny-pic.is-empty::after { content: "♥"; position: absolute; inset: 0; display: grid; place-items: center;
  color: rgba(231,188,198,.32); font-size: 2rem; }
.funny-pic { position: relative; }
