:root {
  --bg1: #fff0f5; --bg2: #ffc2d6; --accent: #e11d48; --accent2: #fb7185; --ink: #5c1028; --card: rgba(255,255,255,.7);
  --soft: color-mix(in srgb, var(--ink) 55%, transparent);
  --display: "Fraunces", Georgia, serif; --body: "Plus Jakarta Sans", system-ui, sans-serif; --hand: "Caveat", cursive;
  --sb: env(safe-area-inset-bottom, 0px); --st: env(safe-area-inset-top, 0px);
}
* { box-sizing: border-box; margin: 0; padding: 0; -webkit-tap-highlight-color: transparent; }
html, body { height: 100%; overflow: hidden; background: var(--bg1); color: var(--ink); font-family: var(--body); touch-action: manipulation; }
body {
  background:
    radial-gradient(70% 50% at 50% -10%, color-mix(in srgb, var(--bg2) 90%, white) 0%, transparent 70%),
    radial-gradient(60% 45% at 100% 100%, var(--bg2) 0%, transparent 60%),
    radial-gradient(50% 40% at 0% 85%, color-mix(in srgb, var(--accent2) 35%, transparent) 0%, transparent 60%),
    var(--bg1);
  transition: background .6s;
}
button { font: inherit; color: inherit; cursor: pointer; border: 0; background: none; }
#fx { position: fixed; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 20; }
#bgfloat { position: fixed; inset: 0; overflow: hidden; pointer-events: none; z-index: 0; }
#bgfloat i { position: absolute; bottom: -10vh; font-style: normal; opacity: .5; animation: rise linear infinite; }
@keyframes rise { to { transform: translateY(-120vh) rotate(25deg); } }

#app { position: relative; z-index: 2; height: 100dvh; max-width: 560px; margin: 0 auto; }
.scene {
  position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: safe center;
  padding: calc(28px + var(--st)) 24px calc(54px + var(--sb)); text-align: center; overflow-y: auto; overflow-x: hidden; scrollbar-width: none;
  opacity: 0; visibility: hidden; pointer-events: none; transform: translateY(18px) scale(.985);
  transition: opacity .6s ease, transform .6s ease, visibility 0s linear .6s;
}
.scene::-webkit-scrollbar { display: none; }
.scene.on { opacity: 1; visibility: visible; pointer-events: auto; transform: none; transition: opacity .6s ease, transform .6s ease, visibility 0s; }

.kicker { font-size: 11px; letter-spacing: .28em; text-transform: uppercase; color: var(--accent); font-weight: 700; margin-bottom: 14px; }
.title { font-family: var(--display); font-weight: 700; font-size: clamp(34px, 9.5vw, 54px); line-height: 1.06; letter-spacing: -.02em; margin-bottom: 14px; text-wrap: balance; }
.title em { font-style: italic; color: var(--accent); }
.sub { font-family: var(--display); font-weight: 600; font-size: clamp(26px, 7vw, 36px); line-height: 1.1; margin-bottom: 8px; text-wrap: balance; }
.lede { font-size: 16px; line-height: 1.6; color: var(--soft); max-width: 34ch; margin-bottom: 22px; text-wrap: pretty; }
.hint { font-size: 13px; color: var(--soft); margin-top: 14px; letter-spacing: .04em; animation: pulse 2s ease-in-out infinite; }
@keyframes pulse { 50% { opacity: .45; } }
.hidden { display: none !important; }

.btn {
  position: relative; padding: 15px 30px; border-radius: 999px; font-weight: 700; font-size: 16px; color: #fff;
  background: linear-gradient(135deg, var(--accent), var(--accent2)); box-shadow: 0 10px 26px -8px var(--accent), inset 0 1px 0 rgba(255,255,255,.35);
  transition: transform .15s, box-shadow .2s; min-height: 48px;
}
.btn:active { transform: scale(.96); }
.btn.ghost { background: var(--card); color: var(--ink); box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--ink) 18%, transparent); backdrop-filter: blur(8px); }
.btn.pop-in { animation: popin .5s cubic-bezier(.2,1.4,.4,1) both; }
@keyframes popin { from { transform: scale(.4); opacity: 0; } }

/* ----- envelope: letter slides out of the pocket ----- */
.env { position: relative; width: min(300px, 78vw); aspect-ratio: 1.45; margin: 120px 0 24px; filter: drop-shadow(0 24px 30px color-mix(in srgb, var(--accent) 35%, transparent)); animation: bob 3.2s ease-in-out infinite; }
@keyframes bob { 50% { transform: translateY(-8px); } }
.env > * { position: absolute; }
.e-back { inset: 0; border-radius: 10px; background: color-mix(in srgb, var(--accent) 80%, black); z-index: 1; transition: opacity .6s, transform .8s; }
.e-paper { left: 7%; right: 7%; top: 9%; bottom: 8%; z-index: 2; border-radius: 6px; background: #fffdf8; color: #7a2540; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  background-image: repeating-linear-gradient(transparent 0 23px, rgba(200,140,150,.22) 23px 24px); box-shadow: 0 -2px 10px rgba(0,0,0,.12); transition: transform .9s cubic-bezier(.35,1.1,.4,1), opacity .5s; transform-origin: 50% 100%; }
.e-paper small { font-size: 12px; letter-spacing: .24em; text-transform: uppercase; opacity: .7; } .e-paper b { font-family: var(--hand); font-size: 34px; line-height: 1.1; } .e-paper span { font-size: 22px; }
.e-pocket { inset: 0; z-index: 3; border-radius: 10px; background: linear-gradient(165deg, var(--accent2), var(--accent)); clip-path: polygon(0 0, 50% 54%, 100% 0, 100% 100%, 0 100%); transition: opacity .6s, transform .8s; }
.e-flap { left: 0; right: 0; top: 0; height: 56%; z-index: 4; border-radius: 10px 10px 0 0; background: linear-gradient(180deg, color-mix(in srgb, var(--accent2) 80%, white), var(--accent2)); clip-path: polygon(0 0, 100% 0, 50% 100%); transform-origin: top; transition: transform .6s cubic-bezier(.5,0,.3,1), opacity .6s; }
.e-seal { left: 50%; top: 53%; width: 58px; height: 58px; margin: -29px 0 0 -29px; z-index: 6; border-radius: 50%; font-size: 26px; display: grid; place-items: center; background: radial-gradient(circle at 30% 30%, #ff7a95, #b4123a); box-shadow: 0 6px 14px rgba(0,0,0,.3), inset 0 -3px 6px rgba(0,0,0,.25); animation: beat 1.4s ease-in-out infinite; transition: transform .3s, opacity .3s; }
@keyframes beat { 50% { transform: scale(1.12); } }
.env.s1 { animation: none; } .env.s1 .e-seal { transform: scale(0); opacity: 0; animation: none; }
.env.s1 .e-flap { transform: rotateX(180deg); } .env.flapback .e-flap { z-index: 0; }
.env.s2 .e-paper { transform: translateY(-58%); }
.env.s3 .e-paper { z-index: 5; transform: translateY(-112%) scale(1.14) rotate(-2deg); box-shadow: 0 20px 40px rgba(0,0,0,.25); }
.env.s3 .e-back, .env.s3 .e-pocket, .env.s3 .e-flap { opacity: 0; transform: translateY(40px); }
.env.s4 .e-paper { z-index: 5; transform: translateY(-112%) scale(2); opacity: 0; transition: transform .6s ease-in, opacity .5s; }
.env.s4 .e-back, .env.s4 .e-pocket, .env.s4 .e-flap { opacity: 0; }

/* ----- balloons ----- */
.sky { position: relative; width: 100%; flex: 1; min-height: 280px; max-height: 460px; margin: 4px 0; overflow: hidden; }
.balloon { position: absolute; bottom: -20px; padding: 0; animation: rise var(--d) linear infinite; z-index: 1; }
.balloon .bl { position: absolute; inset: 0; display: block; border-radius: 50% 50% 48% 48% / 55% 55% 45% 45%; background: radial-gradient(circle at 32% 26%, rgba(255,255,255,.75) 0 7%, transparent 8%), radial-gradient(circle at 36% 30%, color-mix(in srgb, var(--c) 60%, white), var(--c) 55%, color-mix(in srgb, var(--c) 70%, black)); box-shadow: inset -8px -12px 20px rgba(0,0,0,.18), 0 10px 18px -8px rgba(0,0,0,.35); animation: sway 3.4s ease-in-out infinite alternate; transform-origin: 50% 110%; }
.balloon .bl::before { content: ""; position: absolute; left: 50%; bottom: -6px; margin-left: -6px; border: 6px solid transparent; border-bottom: 9px solid var(--c); border-top: 0; filter: brightness(.85); }
.balloon .bl::after { content: ""; position: absolute; left: 50%; top: 100%; width: 1.5px; height: 46px; background: linear-gradient(color-mix(in srgb, var(--ink) 45%, transparent), transparent); }
@keyframes rise { from { transform: translateY(0); } to { transform: translateY(calc(-1 * var(--h))); } }
@keyframes sway { from { transform: rotate(-6deg) translateX(-8px); } to { transform: rotate(6deg) translateX(8px); } }
.balloon.popped { animation-play-state: paused; transform: scale(1.4); opacity: 0; transition: transform .25s, opacity .25s; }
.words { min-height: 54px; display: flex; flex-wrap: wrap; gap: 4px 10px; justify-content: center; font-family: var(--display); font-style: italic; font-size: 26px; font-weight: 600; color: var(--accent); margin-top: 6px; }
.words span { animation: popin .4s both; }

/* ----- cake ----- */
.cake { position: relative; width: 250px; height: 240px; margin: 22px 0 10px; }
.c-tier { position: absolute; left: 50%; transform: translateX(-50%); border-radius: 16px 16px 10px 10px; box-shadow: inset 0 -8px 12px rgba(0,0,0,.08); }
.t1 { bottom: 12px; width: 250px; height: 74px; background: radial-gradient(circle at 20% 30%, #fff 0 2px, transparent 3px) 0 0 / 30px 26px, linear-gradient(#ffd1dc, #ff9db5); }
.t2 { bottom: 82px; width: 192px; height: 62px; background: radial-gradient(circle at 70% 40%, #ff6b8a 0 2px, transparent 3px) 0 0 / 26px 22px, linear-gradient(#fff3d6, #ffd9a0); }
.t3 { bottom: 140px; width: 136px; height: 52px; background: radial-gradient(circle at 40% 40%, #fff 0 2px, transparent 3px) 0 0 / 24px 20px, linear-gradient(#ffd1dc, #ff8fab); }
.c-plate { position: absolute; left: 50%; bottom: 0; transform: translateX(-50%); width: 290px; height: 18px; border-radius: 50%; background: linear-gradient(#fff, #e8e0e6); box-shadow: 0 14px 20px -8px rgba(0,0,0,.35); }
.c-drip { position: absolute; bottom: 184px; left: 50%; width: 140px; height: 14px; transform: translateX(-50%); border-radius: 10px; background: #fff; }
.candles { position: absolute; bottom: 192px; left: 50%; transform: translateX(-50%); display: flex; gap: 10px; }
.candle { position: relative; width: 9px; height: 42px; border-radius: 3px; background: repeating-linear-gradient(135deg, #fff 0 6px, var(--accent2) 6px 12px); }
.flame { position: absolute; left: 50%; top: -28px; width: 22px; height: 30px; margin-left: -11px; cursor: pointer; }
.flame::before { content: ""; position: absolute; inset: 0; border-radius: 50% 50% 50% 50% / 62% 62% 38% 38%; background: radial-gradient(circle at 50% 70%, #fff6b0, #ffb300 60%, #ff6a00); box-shadow: 0 0 18px 6px rgba(255,170,0,.55); animation: flick .18s ease-in-out infinite alternate; transform-origin: bottom; }
.flame::after { content: ""; position: absolute; inset: -16px; }
@keyframes flick { to { transform: scaleY(1.12) rotate(3deg); } }
.flame.out::before { animation: none; opacity: 0; transition: .3s; }
.smoke { position: absolute; left: 50%; top: -30px; width: 8px; height: 8px; border-radius: 50%; background: rgba(120,120,120,.5); animation: smoke 1.4s ease-out forwards; }
@keyframes smoke { to { transform: translate(8px, -50px) scale(4); opacity: 0; } }

/* ----- question ----- */
.qwrap { position: relative; width: 100%; height: 160px; margin-top: 8px; }
.qwrap .btn { position: absolute; }
#yes { left: 50%; top: 20px; transform: translateX(-50%); transition: transform .25s; z-index: 2; }
#no { left: 50%; top: 100px; transform: translateX(-50%); transition: left .22s cubic-bezier(.3,1.6,.5,1), top .22s cubic-bezier(.3,1.6,.5,1), transform .2s; }
.tease { min-height: 22px; font-family: var(--hand); font-size: 24px; color: var(--accent); margin-top: 6px; }
.big-emoji { font-size: 64px; animation: beat 1.2s ease-in-out infinite; margin-bottom: 8px; }

/* ----- puzzle ----- */
.puz { position: relative; width: min(330px, 100%); aspect-ratio: 1; display: grid; grid-template: repeat(3, 1fr) / repeat(3, 1fr); gap: 3px; margin: 12px 0 8px; border-radius: 16px; overflow: hidden; box-shadow: 0 20px 40px -14px rgba(0,0,0,.35); }
.puz button { background-size: 300% 300%; border-radius: 3px; transition: transform .25s, opacity .25s; outline: 0; }
.puz button.sel { transform: scale(.9); box-shadow: 0 0 0 3px var(--accent); z-index: 1; }
.puz.done { gap: 0; }
.puz.done button { border-radius: 0; }
.reveal { font-family: var(--hand); font-size: 32px; color: var(--accent); margin: 6px 0 14px; animation: popin .6s both; }

/* ----- countdown ----- */
.counter { display: flex; gap: 10px; margin: 8px 0 22px; }
.counter div { min-width: 82px; padding: 16px 8px; border-radius: 20px; background: var(--card); backdrop-filter: blur(10px); box-shadow: 0 10px 30px -14px rgba(0,0,0,.25); }
.counter b { display: block; font-family: var(--display); font-size: 40px; line-height: 1; color: var(--accent); }
.counter small { font-size: 11px; letter-spacing: .18em; text-transform: uppercase; color: var(--soft); }

/* ----- hearts ----- */
.hearts { position: relative; width: 100%; flex: 1; min-height: 280px; max-height: 420px; }
.fheart { position: absolute; font-size: 38px; animation: drift var(--d) ease-in-out infinite alternate; filter: drop-shadow(0 6px 8px rgba(0,0,0,.2)); }
@keyframes drift { to { transform: translate(var(--dx), var(--dy)) rotate(var(--r)); } }
.bar { width: 200px; height: 8px; border-radius: 9px; background: color-mix(in srgb, var(--ink) 12%, transparent); overflow: hidden; margin: 10px 0; }
.bar i { display: block; height: 100%; width: 0; background: linear-gradient(90deg, var(--accent2), var(--accent)); transition: width .3s; }

/* ----- gallery ----- */
.stack { position: relative; width: min(280px, 72vw); aspect-ratio: .82; margin: 18px 0 14px; }
.pol { position: absolute; inset: 0; background: #fff; padding: 12px 12px 44px; border-radius: 6px; box-shadow: 0 18px 36px -12px rgba(0,0,0,.4); transition: transform .5s cubic-bezier(.3,1.2,.4,1), opacity .4s; cursor: pointer; }
.pol img { width: 100%; height: 100%; object-fit: cover; border-radius: 3px; display: block; pointer-events: none; }
.pol span { position: absolute; bottom: 10px; left: 0; right: 0; font-family: var(--hand); font-size: 22px; color: #6a3a48; }

/* ----- letter ----- */
.paper-l { width: 100%; max-height: 62dvh; overflow-y: auto; text-align: left; background: #fffdf8; color: #4a2733; border-radius: 6px; padding: 26px 24px; box-shadow: 0 24px 44px -16px rgba(0,0,0,.4); background-image: repeating-linear-gradient(transparent 0 31px, rgba(200,140,150,.25) 31px 32px); line-height: 32px; font-family: var(--hand); font-size: 25px; user-select: text; scrollbar-width: thin; }
.paper-l .to { font-weight: 700; color: var(--accent); }
.paper-l .sig { margin-top: 12px; text-align: right; font-weight: 700; }
.paper-l p { white-space: pre-wrap; word-break: break-word; }
.caret::after { content: "▍"; animation: pulse .8s steps(2) infinite; color: var(--accent); }

/* ----- finale ----- */
.signature { font-family: var(--hand); font-size: 36px; color: var(--accent); margin: 4px 0 18px; }
.badge { position: fixed; z-index: 6; bottom: calc(10px + var(--sb)); left: 14px; font-size: 11px; color: var(--soft); text-decoration: none; opacity: .75; padding: 6px 10px; border-radius: 99px; background: var(--card); backdrop-filter: blur(6px); }

#dots { position: fixed; z-index: 5; left: 0; right: 0; bottom: calc(14px + var(--sb)); display: flex; justify-content: center; gap: 6px; pointer-events: none; }
#dots span { width: 6px; height: 6px; border-radius: 50%; background: color-mix(in srgb, var(--ink) 20%, transparent); transition: .3s; }
#dots span.on { width: 20px; border-radius: 4px; background: var(--accent); }
#mute { position: fixed; z-index: 7; top: calc(12px + var(--st)); right: 12px; width: 40px; height: 40px; border-radius: 50%; background: var(--card); backdrop-filter: blur(8px); font-size: 17px; box-shadow: 0 6px 16px -8px rgba(0,0,0,.4); }
.boot { position: fixed; inset: 0; z-index: 50; display: grid; place-items: center; background: var(--bg1); font-size: 54px; transition: opacity .5s; }
.boot span { animation: beat 1s ease-in-out infinite; }
.boot.gone { opacity: 0; pointer-events: none; }
.error { padding: 40px 28px; }

@media (min-width: 720px) and (min-height: 760px) {
  .lede { font-size: 17px; }
  #app { max-width: 600px; }
}
@media (prefers-reduced-motion: reduce) {
  .env, .seal, .hint, .big-emoji, .flame::before { animation: none; }
  #bgfloat { display: none; }
}


/* ----- font scale + dark themes ----- */
.paper-l { font-family: var(--hand); font-size: calc(25px * var(--hscale, 1)); }
.signature, .tease, .reveal, .pol span { font-family: var(--hand); }
.dark .paper-l, .dark .e-paper, .dark .pol { color: #3a1f2a; }
.dark .btn.ghost { color: var(--ink); }
.shake { animation: shake .45s; } @keyframes shake { 20%, 60% { transform: translateX(-9px); } 40%, 80% { transform: translateX(9px); } }

/* ----- lock screen ----- */
.lockform { display: flex; gap: 10px; width: min(340px, 100%); margin-bottom: 8px; }
.lockform input { flex: 1; min-width: 0; padding: 14px 16px; border-radius: 99px; border: 1.5px solid color-mix(in srgb, var(--ink) 25%, transparent); background: var(--card); color: var(--ink); font: inherit; font-size: 16px; outline: 0; text-align: center; }
.lockform input:focus { border-color: var(--accent); }
.lockcount { margin-bottom: 10px; } .lockcount > div { min-width: 64px; } .lockcount b { font-size: 30px; }

/* ----- reasons deck ----- */
.deck { position: relative; width: min(290px, 76vw); aspect-ratio: .78; margin: 18px 0 12px; perspective: 900px; }
.rcard { position: absolute; inset: 0; cursor: pointer; transition: transform .45s cubic-bezier(.3,1.2,.4,1), opacity .3s; }
.rin { position: absolute; inset: 0; transform-style: preserve-3d; transition: transform .7s cubic-bezier(.3,1.1,.4,1); }
.rcard.flip .rin { transform: rotateY(180deg); }
.rface { position: absolute; inset: 0; backface-visibility: hidden; -webkit-backface-visibility: hidden; border-radius: 22px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; padding: 22px; box-shadow: 0 24px 44px -16px rgba(0,0,0,.4); }
.rface.front { background: linear-gradient(155deg, var(--accent2), var(--accent)); color: #fff; }
.rface.front i { font-style: normal; font-size: 70px; animation: beat 1.6s ease-in-out infinite; } .rface.front small { opacity: .85; font-size: 13px; letter-spacing: .1em; }
.rface.back { background: #fffdf8; color: #4a2733; transform: rotateY(180deg); border: 3px solid var(--accent2); }
.rface.back p { font-family: var(--display); font-weight: 600; font-size: 24px; line-height: 1.25; text-wrap: balance; }
.rnum { font-size: 12px; font-weight: 800; letter-spacing: .2em; text-transform: uppercase; opacity: .8; }
.rface.back .rnum { color: var(--accent); }

/* ----- timeline ----- */
.tl { position: relative; width: 100%; max-width: 360px; text-align: left; padding-left: 34px; margin: 10px 0 20px; }
.tl::before { content: ""; position: absolute; left: 10px; top: 6px; bottom: 6px; width: 3px; border-radius: 2px; background: linear-gradient(var(--accent), var(--accent2)); opacity: .5; }
.tli { position: relative; padding: 0 0 22px; opacity: 0; transform: translateY(14px); transition: .6s cubic-bezier(.2,.9,.3,1); }
.tli.show { opacity: 1; transform: none; }
.tli i { position: absolute; left: -33px; top: 4px; width: 17px; height: 17px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 5px color-mix(in srgb, var(--accent) 25%, transparent); }
.tli small { font-size: 12px; letter-spacing: .14em; text-transform: uppercase; font-weight: 800; color: var(--accent); }
.tli p { font-family: var(--display); font-weight: 600; font-size: 21px; line-height: 1.25; }

/* ----- quiz ----- */
.opts { display: grid; gap: 10px; width: min(360px, 100%); margin: 14px 0 6px; }
.opt { padding: 15px 18px; border-radius: 16px; background: var(--card); backdrop-filter: blur(8px); font-weight: 700; font-size: 16px; box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--ink) 16%, transparent); transition: .2s; text-align: left; }
.opt:active { transform: scale(.98); } .opt.good { background: #22c55e; color: #fff; box-shadow: none; } .opt.bad { background: #ef4444; color: #fff; opacity: .7; animation: shake .4s; box-shadow: none; }

/* ----- scratch ----- */
.scratch { position: relative; width: min(320px, 100%); aspect-ratio: 2; margin: 14px 0 6px; border-radius: 18px; overflow: hidden; box-shadow: 0 20px 36px -14px rgba(0,0,0,.4); touch-action: none; }
.s-under { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; padding: 16px; background: linear-gradient(135deg, #fff8e1, #ffe0ec); color: #5c1028; }
.s-under small { font-size: 11px; letter-spacing: .2em; text-transform: uppercase; opacity: .6; font-weight: 800; } .s-under p { font-family: var(--display); font-weight: 700; font-size: 20px; line-height: 1.2; text-wrap: balance; }
.scratch canvas { position: absolute; inset: 0; width: 100%; height: 100%; touch-action: none; cursor: crosshair; }

/* ----- stars ----- */
.skybox { position: relative; width: min(330px, 100%); aspect-ratio: 1; margin: 10px 0 12px; border-radius: 26px; overflow: hidden; background: radial-gradient(circle at 50% 40%, #1b2a5a, #090d24 75%); box-shadow: 0 24px 44px -16px rgba(0,0,0,.55), inset 0 0 0 1px rgba(255,255,255,.1); touch-action: manipulation; }
.skybox.glow { box-shadow: 0 0 60px 6px rgba(255,200,230,.35), inset 0 0 0 1px rgba(255,255,255,.25); }
.bg-star { position: absolute; width: 2px; height: 2px; border-radius: 50%; background: #fff; animation: twinkle 2.4s ease-in-out infinite alternate; }
@keyframes twinkle { to { opacity: .1; transform: scale(.5); } }
.star { position: absolute; width: 40px; height: 40px; margin: -20px 0 0 -20px; font-size: 22px; color: #6f78a8; z-index: 2; transition: .3s; }
.star.next { color: #ffe066; animation: pulsestar 1s ease-in-out infinite; text-shadow: 0 0 14px #ffe066; }
.star.lit { color: #fff6b8; text-shadow: 0 0 16px #ffd24d, 0 0 30px #ff9bd0; transform: scale(1.25); animation: none; }
.star.wiggle { animation: shake .35s; }
@keyframes pulsestar { 50% { transform: scale(1.4); } }
.constel { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 1; }
.constel line { stroke: rgba(255,240,180,.8); stroke-width: .7; stroke-linecap: round; filter: drop-shadow(0 0 1.5px #ffd24d); }

/* ----- lanterns ----- */
.lsky { position: relative; width: min(340px, 100%); height: min(320px, 38dvh); margin: 8px 0; border-radius: 26px; overflow: hidden; background: linear-gradient(#1a1440, #6a3a6a 70%, #f0925a); box-shadow: 0 24px 44px -16px rgba(0,0,0,.5); cursor: pointer; }
.lantern { position: absolute; bottom: -70px; width: 40px; height: 52px; border-radius: 12px 12px 18px 18px; background: linear-gradient(#ffb347, #ff6a3d); box-shadow: 0 0 26px 8px rgba(255,170,70,.7); display: grid; place-items: center; font-size: 15px; animation: lift 8s ease-in forwards; pointer-events: none; }
.lantern::before { content: ""; position: absolute; top: -6px; left: 6px; right: 6px; height: 6px; border-radius: 3px; background: #7a3a1a; }
@keyframes lift { to { transform: translate(var(--sw), -420px) scale(.6); opacity: 0; } }

/* ----- gifts ----- */
.gifts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; width: 100%; max-width: 420px; margin: 12px 0; }
.gift { position: relative; aspect-ratio: .78; border-radius: 20px; background: var(--card); backdrop-filter: blur(8px); box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--ink) 14%, transparent); animation: bob 2.6s ease-in-out infinite; perspective: 600px; overflow: hidden; }
.g-box { position: absolute; inset: 0; display: grid; place-items: center; font-size: 54px; transition: .5s; }
.g-card { position: absolute; inset: 6px; display: grid; place-items: center; padding: 8px; border-radius: 14px; background: linear-gradient(155deg, var(--accent2), var(--accent)); color: #fff; font-weight: 700; font-size: 13px; line-height: 1.25; opacity: 0; transform: scale(.6) rotate(-6deg); transition: .5s cubic-bezier(.3,1.4,.4,1); }
.gift.open { animation: none; } .gift.open .g-box { transform: translateY(-120%); opacity: 0; } .gift.open .g-card { opacity: 1; transform: none; }

/* ----- flowers ----- */
.bed { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; margin: 14px 0; } .seed { width: 82px; height: 82px; border-radius: 50%; font-size: 40px; background: color-mix(in srgb, #8b5a2b 22%, var(--card)); display: grid; place-items: center; transition: .4s; }
.seed.bloom { background: var(--card); animation: popin .6s cubic-bezier(.2,1.5,.4,1); font-size: 52px; }

/* ----- fireworks ----- */
.fwsky { position: relative; width: min(340px, 100%); height: min(340px, 42dvh); margin: 8px 0; border-radius: 26px; overflow: hidden; background: radial-gradient(circle at 50% 100%, #3a1c5a, #070816 75%); box-shadow: 0 24px 44px -16px rgba(0,0,0,.55); cursor: crosshair; }
.fw-hint { position: absolute; left: 0; right: 0; top: 45%; color: rgba(255,255,255,.7); font-weight: 700; letter-spacing: .2em; text-transform: uppercase; font-size: 12px; animation: pulse 2s infinite; }
.rocket { position: absolute; bottom: 0; width: 4px; height: 18px; margin-left: -2px; border-radius: 2px; background: linear-gradient(#fff, transparent); box-shadow: 0 0 10px #ffd; transition: transform .65s cubic-bezier(.2,.7,.4,1); }

/* ----- heartbeat ----- */
.hb { font-size: 120px; line-height: 1; margin: 6px 0 4px; filter: drop-shadow(0 18px 20px color-mix(in srgb, var(--accent) 55%, transparent)); user-select: none; touch-action: none; }
.hb.beat { animation: thump .55s ease-out; } @keyframes thump { 0% { transform: scale(1); } 20% { transform: scale(1.28); } 40% { transform: scale(1.05); } 60% { transform: scale(1.18); } 100% { transform: scale(1); } }

/* ----- chat bubbles ----- */
.chat { display: flex; flex-direction: column; gap: 10px; width: 100%; max-width: 380px; margin: 12px 0 20px; text-align: left; }
.msg { align-self: flex-start; max-width: 86%; padding: 13px 17px; border-radius: 20px 20px 20px 6px; background: linear-gradient(135deg, var(--accent), var(--accent2)); color: #fff; font-weight: 600; font-size: 16px; line-height: 1.35; animation: popin .4s cubic-bezier(.2,1.4,.4,1) both; box-shadow: 0 10px 22px -10px var(--accent); }
.msg:nth-child(even) { align-self: flex-end; border-radius: 20px 20px 6px 20px; }
.msg.typing { background: var(--card); color: var(--soft); letter-spacing: .3em; box-shadow: none; }

/* ----- song / rsvp ----- */
.vinyl { width: 150px; height: 150px; border-radius: 50%; margin: 6px 0 18px; display: grid; place-items: center; background: radial-gradient(circle, var(--accent) 0 17%, #111 18% 30%, #222 31% 33%, #111 34% 46%, #222 47% 49%, #111 50%); box-shadow: 0 22px 36px -12px rgba(0,0,0,.5); animation: spin 5s linear infinite; }
.vinyl i { font-style: normal; font-size: 26px; } @keyframes spin { to { transform: rotate(360deg); } }
.artist { color: var(--soft); font-weight: 600; margin-bottom: 8px; letter-spacing: .05em; }
.evcard { width: min(340px, 100%); padding: 26px 22px; border-radius: 24px; background: var(--card); backdrop-filter: blur(12px); box-shadow: 0 24px 44px -18px rgba(0,0,0,.35), inset 0 0 0 1.5px color-mix(in srgb, var(--accent) 35%, transparent); margin-bottom: 18px; }
.evcard small { font-size: 11px; letter-spacing: .26em; text-transform: uppercase; color: var(--accent); font-weight: 800; }
.evcard h3 { font-family: var(--display); font-size: 34px; line-height: 1.1; margin: 8px 0; text-wrap: balance; } .ev-date { font-weight: 700; } .ev-meta { color: var(--soft); margin-top: 4px; }
.choice { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; margin-bottom: 12px; }
.ps { font-family: var(--hand); font-size: 24px; color: var(--soft); margin: -6px 0 16px; max-width: 28ch; }
.sky { -webkit-mask-image: linear-gradient(transparent, #000 7%, #000 93%, transparent); mask-image: linear-gradient(transparent, #000 7%, #000 93%, transparent); }

/* no accidental text selection or focus boxes on interactive slides (the blue squares around tapped stars) */
html, body, .scene, .scene * { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
.scene .paper-l, .scene .paper-l *, .scene input, .scene textarea { -webkit-user-select: text; user-select: text; }
.scene button, .scene .star, .scene .balloon, .scene .fheart, .scene .seed, .scene .hb, .scene .fwsky, .scene .lsky { -webkit-tap-highlight-color: transparent; outline: none; }
.scene button:focus:not(:focus-visible) { outline: none; box-shadow: none; }
.scene button:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; border-radius: 12px; }
.star:focus-visible { outline-offset: -4px; border-radius: 50%; }
.scene ::selection { background: transparent; }
.paper-l ::selection { background: color-mix(in srgb, var(--accent) 30%, transparent); }

.boot-mark { width: 64px; height: 64px; animation: beat 1s ease-in-out infinite; filter: drop-shadow(0 10px 24px rgba(255,61,133,.6)); }

/* every slide container is capped by the space the scene really has */
.scene > .skybox, .scene > .lsky, .scene > .fwsky, .scene > .scratch, .scene > .puz, .scene > .deck, .scene > .stack, .scene > .env { max-width: 100%; }
.scene { overscroll-behavior: contain; }
