/* Not My Event: the look of "The City Is Alive" (public/templates/the-city-is-alive.html). Midnight navy, graphite, warm amber, champagne gold, electric magenta, deep violet, teal and fireworks white.
   Layers, from the back: the pictures of each scene (.bg, fixed), the drifting lanterns (.floats), the scenes (#app) with their own buttons above anything they might cover (.cta, .dock: z-index 6),
   the top bar (z 30) and the dialogs. Nothing is ever drawn over something a guest has to press. Everything that moves is transform and opacity only (nothing blurs, nothing blends). */
:root { --gold: #F2C562; --gold2: #FBEFC0; --magenta: #FF3DB8; --teal: #3DD6C8; --violet: #B388FF; --ink: #05030F; --card: rgba(10, 8, 30, .84); --line: rgba(242, 197, 98, .4); --ui: 'Montserrat', system-ui, sans-serif; --serif: 'Cormorant Garamond', Georgia, serif; --safe-t: env(safe-area-inset-top, 0px); --safe-b: env(safe-area-inset-bottom, 0px); }
body[data-accent="magenta"] { --gold: #FF3DB8; --gold2: #FFD0EE; --line: rgba(255, 61, 184, .45); }
body[data-accent="teal"] { --gold: #3DD6C8; --gold2: #D8FFF8; --line: rgba(61, 214, 200, .45); }
body[data-accent="violet"] { --gold: #B388FF; --gold2: #E6D4FF; --line: rgba(179, 136, 255, .45); }
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; background: var(--ink); color: #fff; font-family: var(--ui); -webkit-tap-highlight-color: transparent; }
body { overflow: hidden; }
button { font: inherit; color: inherit; cursor: pointer; }
.sr, .skip:not(:focus) { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.skip:focus { position: fixed; z-index: 99; left: 12px; top: 12px; padding: 10px 14px; background: #fff; color: #000; border-radius: 8px; }
:focus-visible { outline: 3px solid var(--teal); outline-offset: 3px; }

/* the pictures behind the scenes */
.bg { position: fixed; inset: 0; opacity: 0; transition: opacity .8s ease; pointer-events: none; overflow: hidden; }
.bg.on { opacity: 1; }
.layer, .bg canvas { position: absolute; left: 0; top: 0; width: 100%; height: 100%; display: block; pointer-events: none; }
.layer svg { width: 100%; height: 100%; display: block; }
.wa { animation: cy-twinkle 3.4s ease-in-out infinite alternate; } .wb { animation: cy-twinkle 4.3s ease-in-out -1.8s infinite alternate; }
.cloud { animation: cy-drift 80s linear infinite alternate; } .cloud.c1 { animation-duration: 110s; } .cloud.c2 { animation-duration: 60s; }
.bulb { animation: cy-twinkle 1.6s ease-in-out infinite alternate; } .flame { transform-box: fill-box; transform-origin: 50% 100%; animation: cy-flick 1.3s ease-in-out infinite alternate; }
.lane { stroke-dasharray: 3 26; animation: cy-flow 1.4s linear infinite; } .lane.r { animation-direction: reverse; }
/* people never bob, sway or rock (the user, 2026-11-09): a person stands still; a dancer switches between two arm moves (.arA and .arB), the body stays where it is */
.pv { transform-box: fill-box; transform-origin: 50% 100%; }
.arA { animation: cy-armA 1.3s steps(1, end) infinite; } .arB { opacity: 0; animation: cy-armB 1.3s steps(1, end) infinite; }
.v1 .arA, .v1 .arB { animation-delay: -.45s; } .v2 .arA, .v2 .arB { animation-delay: -.9s; }
@keyframes cy-armA { 0% { opacity: 1; } 50% { opacity: 0; } } @keyframes cy-armB { 0% { opacity: 0; } 50% { opacity: 1; } }
.rm .arA, .rm .arB { animation: none; } .rm .arB { opacity: 0; } @media (prefers-reduced-motion: reduce) { .arA, .arB { animation: none; } .arB { opacity: 0; } }
.ball { transform-box: fill-box; transform-origin: 50% 50%; animation: cy-twinkle 1.2s ease-in-out infinite alternate; } .spk { animation: cy-twinkle 1.1s ease-in-out infinite alternate; }
.tile { animation: cy-tile 1.1s ease-in-out infinite alternate; } .tile.t1 { animation-delay: -.3s; } .tile.t2 { animation-delay: -.6s; } .tile.t3 { animation-delay: -.9s; }
.flag { transform-box: fill-box; transform-origin: 50% 0; animation: cy-sway 2.4s ease-in-out infinite alternate; } .beam.b1 { transform-origin: 50% 0; animation: cy-sway 3s ease-in-out infinite alternate; } .beam.b2 { transform-origin: 50% 0; animation: cy-sway 3s ease-in-out -1.5s infinite alternate-reverse; }
.far-burst { transform-box: fill-box; transform-origin: 50% 50%; opacity: 0; animation: cy-burst 6s ease-out infinite; } .far-burst.b1 { animation-delay: -1.5s; } .far-burst.b2 { animation-delay: -3s; } .far-burst.b3 { animation-delay: -4.5s; }
.dest-beam, .dest-glow { animation: cy-pulse 2.6s ease-in-out infinite alternate; }
.ripple { animation: cy-twinkle 2.4s ease-in-out infinite alternate; }
@keyframes cy-twinkle { from { opacity: .55; } to { opacity: 1; } } @keyframes cy-pulse { from { opacity: .45; } to { opacity: 1; } }
@keyframes cy-drift { to { transform: translateX(80px); } } @keyframes cy-flow { to { stroke-dashoffset: -58; } }
@keyframes cy-flick { from { transform: scale(1, .85); opacity: .8; } to { transform: scale(.9, 1.12); opacity: 1; } }
@keyframes cy-bob { from { transform: translateY(0) rotate(-3deg); } to { transform: translateY(-5px) rotate(3deg); } }
@keyframes cy-step { from { transform: translateX(-6px) rotate(-2deg); } to { transform: translateX(6px) rotate(2deg); } } @keyframes cy-tile { from { opacity: .35; } to { opacity: .95; } } @keyframes cy-sway { from { transform: rotate(-8deg); } to { transform: rotate(8deg); } }
@keyframes cy-burst { 0% { transform: scale(.2); opacity: 0; } 12% { opacity: 1; } 70% { transform: scale(1); opacity: .8; } 100% { transform: scale(1.2); opacity: 0; } }
.lit { opacity: 0; transition: opacity 1.4s ease; } #bg3.l1 .lit1, #bg3.l2 .lit2, #bg3.l3 .lit3 { opacity: 1; }

/* the top bar: menu, the always-visible way to the invitation, skip; the speaker is made by public/assets/speaker.js */
#bar { position: fixed; z-index: 30; left: 12px; top: calc(12px + var(--safe-t)); display: flex; gap: 8px; flex-wrap: wrap; max-width: calc(100vw - 84px); align-items: flex-start; }
#bar button { min-height: 44px; padding: 0 14px; border-radius: 22px; background: rgba(10, 8, 30, .78); border: 1px solid var(--line); font-weight: 700; font-size: 12.5px; letter-spacing: .05em; }
#b-inv { background: linear-gradient(180deg, var(--gold2), var(--gold)) !important; color: #1A1230; border: 0 !important; }
#menu { position: absolute; top: 52px; left: 0; width: min(300px, calc(100vw - 24px)); padding: 10px; background: var(--card); border: 1px solid var(--line); border-radius: 16px; display: grid; gap: 6px; }
#menu[hidden] { display: none; }
#menu button { min-height: 44px; text-align: left; padding: 0 14px; border-radius: 10px; border: 0; background: rgba(255, 255, 255, .06); }
#menu small { color: rgba(255, 255, 255, .7); line-height: 1.4; padding: 2px 6px 4px; }
#prog { position: fixed; z-index: 20; left: 50%; bottom: calc(8px + var(--safe-b)); translate: -50% 0; display: flex; gap: 8px; align-items: center; pointer-events: none; font-size: 11px; letter-spacing: .1em; color: rgba(255, 255, 255, .75); }
#prog i { width: 8px; height: 8px; border-radius: 50%; background: rgba(255, 255, 255, .3); } #prog i.on { background: var(--gold); box-shadow: 0 0 10px var(--gold); }
#bubble { position: fixed; z-index: 40; left: 50%; bottom: 200px; translate: -50% 0; pointer-events: none; max-width: min(90vw, 440px); padding: 12px 16px; border-radius: 14px; background: var(--card); border: 1px solid var(--line); text-align: center; font-weight: 600; }
#bubble[hidden] { display: none; }

/* scenes */
#app { position: fixed; inset: 0; z-index: 10; }
.scene { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; padding: calc(68px + var(--safe-t)) 16px calc(34px + var(--safe-b)); text-align: center; overflow-y: auto; overflow-x: hidden; }
.scene[hidden] { display: none; }
#s1, #s2, #s4 { overflow: hidden; } #s3 { overflow-x: hidden; overflow-y: auto; } #s5 { padding: 0; overflow: hidden; }
.cap { max-width: 640px; position: relative; z-index: 2; text-shadow: 0 2px 18px rgba(0, 0, 0, .95); pointer-events: none; }
.cap h1, .cap h2 { margin: 0 0 8px; font-family: var(--serif); font-weight: 700; font-size: clamp(24px, 6vw, 44px); line-height: 1.12; }
.cap p { margin: 6px 0; font-size: clamp(14px, 3.6vw, 19px); line-height: 1.45; color: rgba(255, 255, 255, .94); }
.kick { font-weight: 800; letter-spacing: .24em; font-size: 12px; color: var(--gold); text-transform: uppercase; }
.btn { min-height: 48px; padding: 0 24px; border-radius: 26px; border: 0; background: linear-gradient(180deg, var(--gold2), var(--gold)); color: #1A1230; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; font-size: 13px; text-decoration: none; display: inline-flex; align-items: center; justify-content: center; box-shadow: 0 8px 22px -10px var(--gold); }
.btn.ghost { background: rgba(10, 8, 30, .78); color: #fff; border: 1px solid var(--line); box-shadow: none; } .btn.big { min-height: 54px; font-size: 14px; padding: 0 30px; } .btn[disabled] { opacity: .5; cursor: default; }
.btns { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; margin-top: 14px; }
.cta { position: relative; z-index: 6; margin-top: auto; display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; padding-top: 10px; }
.small { font-size: 13px; color: rgba(255, 255, 255, .8); } .err { color: #FFB3C1; font-weight: 700; margin: 8px 0; }

/* scene 1: the picture. It covers the screen and the guest drags to look around (up and down on a wide screen, in both ways on a phone). The lights, traffic and notes that move are laid over it and
   never take a tap; the glowing places are real buttons laid on it. Only transform and opacity move. */
#pan { position: absolute; inset: 0; overflow: hidden; touch-action: none; cursor: grab; z-index: 0; background: var(--ink); }
#pan.drag { cursor: grabbing; }
#pic { position: absolute; left: 0; top: 0; will-change: transform; background: linear-gradient(#0c1236 0%, #1b2552 42%, #0a0f2a 100%); --hs: 72px; user-select: none; -webkit-user-select: none; }
#pan.smooth #pic { transition: transform .45s ease-out; } #pan.glide #pic { transition: transform 3.6s cubic-bezier(.45, 0, .25, 1); }
#pic .painting, #pic .glow { position: absolute; left: 0; top: 0; width: 100%; height: 100%; display: block; pointer-events: none; -webkit-user-drag: none; }
/* the live fireworks: a canvas over the sky half of the picture, cut out with the picture's own sky (--sky) so every burst goes BEHIND the towers; it never takes a tap */
#pic .fwfront { position: absolute; left: 0; top: 0; width: 100%; height: 100%; display: block; pointer-events: none; }   /* the foreground fireworks: NOT cut out, so they burst in front of the buildings, over the roof party */
#pic .carscv { position: absolute; left: 0; top: 44%; width: 100%; height: 56%; display: block; pointer-events: none; }   /* the cars of the avenue move on this canvas (the lower part of the picture, VIEW.carsTop) */
.cft { position: absolute; z-index: 1; width: 7px; height: 11px; border-radius: 2px; pointer-events: none; opacity: 0; animation: cy-cft linear forwards; }
@keyframes cy-cft { 0% { opacity: 0; transform: translate3d(0, 0, 0) rotate(0deg); } 8% { opacity: 1; } 100% { opacity: .85; transform: translate3d(var(--dx), 780px, 0) rotate(560deg); } }
.rm .cft { display: none; }
#pic .fwcv { position: absolute; left: 0; top: 0; width: 100%; display: block; pointer-events: none; -webkit-mask-image: var(--sky); mask-image: var(--sky); -webkit-mask-size: 100% 100%; mask-size: 100% 100%; }
#pic .glow { opacity: 0; will-change: opacity; animation: cy-glow 4.4s ease-in-out infinite; } #pic .glow.g1 { animation-duration: 5.7s; animation-delay: -1.8s; } #pic .glow.g2 { animation-duration: 3.5s; animation-delay: -2.5s; }
@keyframes cy-glow { 0%, 100% { opacity: .08; } 42% { opacity: .95; } 70% { opacity: .4; } }
.rm #pic .glow { animation: none; opacity: .5; } .rm .hs, .rm .hs::before, .rm .hs::after { animation: none; }
/* the opening: the camera comes down out of the clouds (it only ever grows the painting, so no edge shows), under a drifting mist */
#pan-in { position: absolute; inset: 0; transform-origin: 40% 24%; animation: cy-descend 3.8s cubic-bezier(.2, .7, .2, 1) both; }
@keyframes cy-descend { from { transform: scale(1.4); } to { transform: scale(1); } }
#pan-veil { position: absolute; inset: 0; pointer-events: none; background: radial-gradient(ellipse at 50% 18%, rgba(170, 180, 225, .9), rgba(110, 120, 180, .55) 42%, rgba(60, 60, 120, 0) 78%); animation: cy-veil 3.6s ease-out both; }
@keyframes cy-veil { from { opacity: 1; transform: translateY(0); } to { opacity: 0; transform: translateY(40%); } }
/* the glowing places: a ring with a note in it, laid on a rooftop of the painting (the size is --hs, set by the page); the name shows when you hover or focus it, and in the card when you tap it */
.hs { position: absolute; width: var(--hs); height: var(--hs); padding: 0; border-radius: 50%; display: grid; place-items: center; color: #fff; border: 2px solid rgba(255, 255, 255, .9); background: radial-gradient(circle, rgba(255, 214, 120, .42), rgba(255, 150, 80, .08) 72%); box-shadow: 0 0 22px 4px rgba(255, 200, 110, .6); animation: cy-ring 2s ease-in-out infinite; }
.hs svg { width: 46%; height: 46%; display: block; filter: none; }
.hs span { position: absolute; left: 50%; top: 100%; translate: -50% 6px; white-space: nowrap; padding: 4px 10px; border-radius: 12px; background: rgba(5, 3, 15, .9); border: 1px solid var(--line); font-size: 11px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; opacity: 0; pointer-events: none; transition: opacity .2s; }
.hs:hover span, .hs:focus-visible span { opacity: 1; }
@keyframes cy-ring { 0%, 100% { transform: scale(.92); } 50% { transform: scale(1.1); } }
.hs.seen { border-color: #7DF5B0; background: radial-gradient(circle, rgba(125, 245, 176, .32), rgba(125, 245, 176, .05) 72%); box-shadow: 0 0 18px 3px rgba(125, 245, 176, .5); animation-duration: 3.8s; }
.hs.dest { width: auto; height: auto; border-radius: 0; border: 0; background: none; box-shadow: none; animation: none; }
/* the destination is the tower itself: a soft gold light runs down its two real edges (no frame drawn over it) */
.hs.dest span { opacity: 1; top: auto; bottom: 14px; translate: -50% 0; border-color: var(--gold); color: var(--gold2); }
/* the title shows while the camera comes down, over a soft shade, then fades so the painting is clear */
.scrim { position: absolute; left: 0; right: 0; top: 0; height: 52%; z-index: 1; pointer-events: none; background: linear-gradient(rgba(4, 3, 18, .82), rgba(4, 3, 18, .5) 55%, rgba(4, 3, 18, 0)); opacity: 0; transition: opacity 1.2s ease; } #s1.t1 .scrim { opacity: 1; }
#s1 .cap { opacity: 0; transition: opacity 1.2s ease; } #s1.t1 .cap { opacity: 1; } #s1 #t1b { opacity: 0; transition: opacity 1.2s ease; } #s1.t2 #t1b { opacity: 1; }
#s1.t3 .cap, #s1.t3 .scrim { opacity: 0; }
#s1.still:not(.t3) .cap, #s1.still:not(.t3) #t1b, #s1.still:not(.t3) .scrim { opacity: 1 !important; transition: none; } #s1.still #pan-in, #s1.still #pan-veil { animation: none; } #s1.still #pan-veil { display: none; }
/* what a tapped place says, the hint and the arrows sit at the bottom, above the button; the empty space around them lets taps through to the painting */
#vig { max-width: min(92vw, 460px); margin: 0 auto; padding: 10px 16px; border-radius: 16px; background: var(--card); border: 1px solid var(--line); font-weight: 600; font-size: 15px; line-height: 1.4; text-align: center; text-shadow: none; pointer-events: none; }
#vig[hidden], #hint[hidden], .arrows[hidden] { display: none; } #vig b { display: block; color: var(--gold); margin-bottom: 2px; }
#hint { margin: 0; padding: 6px 14px; border-radius: 16px; background: rgba(5, 3, 15, .68); font-size: 12.5px; font-weight: 600; line-height: 1.3; pointer-events: none; }
#s1 .dock { position: relative; z-index: 6; margin-top: auto; display: flex; flex-direction: column; align-items: center; gap: 8px; width: 100%; pointer-events: none; }
#s1 .dock .arrows, #s1 .dock .cta { pointer-events: auto; }
.arrows { display: flex; gap: 10px; } .arrows button { width: 48px; height: 48px; border-radius: 50%; background: rgba(10, 8, 30, .8); border: 1px solid var(--line); font-size: 20px; }

/* scene 2: three rooftops you PLAY. Every thing to tap is a real button laid on its drawing; a tap plays a note, makes the thing react (its drawing gets .hit), pops a note and fills the party meter. The party
   effects (confetti and fireworks) are drawn on a canvas BEHIND the buttons, and the meter and the cards sit below the picture, so nothing is ever drawn over something to press. */
#roof-art, #rx { transition: opacity .3s ease, transform .3s ease; } #roof-art { position: absolute; inset: 0; }
#roof-art.swap, #rx.swap { opacity: 0; transform: translateX(-9%); } #roof-art.swap.in, #rx.swap.in { transform: translateX(9%); }
#bg2 canvas { z-index: 1; }
#rx { position: absolute; inset: 0; z-index: 3; pointer-events: none; }
.rx { position: absolute; padding: 0; border: 0; border-radius: 16px; background: transparent; pointer-events: auto; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.rx::before { content: ''; position: absolute; left: 50%; top: 50%; width: 14px; height: 14px; margin: -7px 0 0 -7px; border-radius: 50%; background: rgba(255, 255, 255, .92); box-shadow: 0 0 0 5px rgba(255, 255, 255, .22), 0 0 16px 4px var(--gold); animation: cy-ping 1.8s ease-in-out infinite; }
.rx.done::before { opacity: 0; animation: none; }
.rx:hover::before, .rx:focus-visible::before { opacity: 1; }
.rx span { position: absolute; left: 50%; top: 100%; translate: -50% 4px; white-space: nowrap; padding: 3px 9px; border-radius: 12px; background: rgba(5, 3, 15, .9); border: 1px solid var(--line); font-size: 11px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; opacity: 0; pointer-events: none; transition: opacity .2s; z-index: 5; }
.rx:hover span, .rx:focus-visible span { opacity: 1; }
@keyframes cy-ping { 0%, 100% { transform: scale(.8); opacity: .75; } 50% { transform: scale(1.3); opacity: 1; } }
/* the reactions: the drawing moves, a note pops up, a tile lights, a dancer jumps */
.rg { transform-box: fill-box; transform-origin: 50% 100%; } .rg.lamp { transform-origin: 50% 0; } .jumpy { transform-box: fill-box; transform-origin: 50% 100%; }
.rg.hit { animation: cy-jump .46s ease-out; } .rg.lamp.hit { animation: cy-swing .75s ease-out; } .jumpy.hit { animation: cy-jump .46s ease-out; }
@keyframes cy-hitg { 0% { transform: scale(1); } 28% { transform: scale(1.15, .9) rotate(-2deg); } 58% { transform: scale(.96, 1.1) rotate(2deg); } 100% { transform: scale(1); } }
@keyframes cy-swing { 0% { transform: rotate(0); } 25% { transform: rotate(20deg) scale(1.15); } 60% { transform: rotate(-12deg); } 100% { transform: rotate(0); } }
@keyframes cy-jump { 0% { transform: translateY(0); } 40% { transform: translateY(-16px); } 100% { transform: translateY(0); } }
.ktile { opacity: .62; animation: cy-twinkle 2.4s ease-in-out infinite alternate; } .ktile.lit { animation: cy-tilelit .8s ease-out; }
@keyframes cy-tilelit { 0% { fill: #fff; opacity: 1; } 100% { opacity: .62; } }
.pop { position: absolute; z-index: 4; transform: translate(-50%, 0); font-size: 24px; font-weight: 800; line-height: 1; pointer-events: none; text-shadow: 0 0 10px currentColor; animation: cy-pop 1s ease-out forwards; }
@keyframes cy-pop { 0% { transform: translate(-50%, 0) scale(.6); opacity: 0; } 15% { opacity: 1; } 100% { transform: translate(-50%, -76px) scale(1.15) rotate(12deg); opacity: 0; } }
.pcap { position: absolute; z-index: 5; transform: translate(-50%, 0); width: max-content; max-width: min(78vw, 280px); padding: 5px 11px; border-radius: 12px; text-align: center; background: rgba(5, 3, 15, .88); border: 1px solid var(--line); font-size: 12.5px; font-weight: 700; line-height: 1.3; pointer-events: none; animation: cy-pcap 2.4s ease-out forwards; }
@keyframes cy-pcap { 0% { opacity: 0; transform: translate(-50%, 8px); } 12% { opacity: 1; transform: translate(-50%, 0); } 78% { opacity: 1; } 100% { opacity: 0; transform: translate(-50%, -8px); } }
.rm .rg.hit, .rm .jumpy.hit, .rm .ktile, .rm .ktile.lit, .rm .rx::before { animation: none; } .rm .pop, .rm .pcap { display: none; }
#s2 .cap h2 { font-size: clamp(20px, 5vw, 30px); } #s2 .cap p { margin: 2px 0; }
/* the party meter fills with every tap; when it is full the rooftop erupts and earns a star */
#meter { position: relative; z-index: 6; width: min(100%, 620px); height: 28px; margin-top: auto; border-radius: 14px; background: rgba(10, 8, 30, .84); border: 1px solid var(--line); overflow: hidden; }
#meter i { position: absolute; left: 0; top: 0; bottom: 0; width: 0; background: linear-gradient(90deg, var(--magenta), var(--gold)); transition: width .25s ease; }
#meter span { position: relative; display: block; text-align: center; line-height: 26px; font-size: 11.5px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; text-shadow: 0 1px 3px #000; }
#meter.full i { animation: cy-flash .5s ease-out 3; } @keyframes cy-flash { 50% { filter: brightness(1.8); } }
.rm #meter i { transition: none; } .rm #meter.full i { animation: none; }
#rt-cards { position: relative; z-index: 6; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; width: min(100%, 620px); margin-top: 8px; }
.rt { min-height: 74px; padding: 8px; border-radius: 14px; background: rgba(10, 8, 30, .86); border: 1px solid var(--line); text-align: left; }
.rt b { display: block; font-size: 12.5px; } .rt small { display: block; font-size: 11px; line-height: 1.3; color: rgba(255, 255, 255, .78); } .rt[aria-checked="true"] { border: 2px solid var(--gold); background: rgba(242, 197, 98, .16); }
.rt .star { color: var(--gold); margin-left: 4px; text-shadow: 0 0 8px var(--gold); }
#s2 .cta, #s3 .cta { margin-top: 8px; }

/* scene 3: a message across the skyline, then the wish */
.lan { margin-top: 10px; text-align: left; font-size: 13px; } .lan summary { min-height: 44px; display: flex; align-items: center; cursor: pointer; font-weight: 700; color: var(--gold2); }
.lan .list { max-height: 28vh; overflow-y: auto; margin: 0; padding: 0; list-style: none; } .lan .list li { display: flex; justify-content: space-between; align-items: center; gap: 8px; padding: 6px 0; border-top: 1px solid var(--line); } .lan .list button { min-height: 36px; padding: 0 12px; border-radius: 18px; border: 1px solid var(--line); background: transparent; }
.fac-line { position: absolute; z-index: 2; margin: 0; padding: 4px; text-align: center; font-family: var(--serif); font-weight: 700; font-size: clamp(13px, 2.8vw, 26px); line-height: 1.1; letter-spacing: .04em; color: #fff; text-shadow: 0 0 14px var(--gold), 0 2px 8px #000; opacity: 0; transition: opacity 1.2s ease; display: flex; align-items: center; justify-content: center; pointer-events: none; }
#s3.l1 #w1, #s3.l2 #w2, #s3.l3 #w3 { opacity: 1; } #s3.still .fac-line { opacity: 1 !important; transition: none; }
.wishbox { position: relative; z-index: 6; width: min(100%, 640px); margin-top: auto; padding: 14px 12px 6px; border-radius: 18px; background: rgba(5, 3, 15, .72); border: 1px solid var(--line); opacity: 0; transition: opacity 1s ease; pointer-events: none; } #s3.l3 .wishbox, #s3.still .wishbox { opacity: 1; pointer-events: auto; }
#wish-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; } @media (min-width: 720px) { #wish-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.wish { min-height: 52px; padding: 8px 10px; border-radius: 14px; background: rgba(10, 8, 30, .86); border: 1px solid var(--line); font-weight: 800; font-size: 13px; }
.wish[aria-checked="true"] { border: 2px solid var(--gold); background: rgba(242, 197, 98, .18); }
#wish-msg { margin: 8px 0 4px; min-height: 22px; font-family: var(--serif); font-size: 18px; font-style: italic; color: var(--gold2); text-shadow: 0 2px 10px #000; }
#wish-custom { width: 100%; min-height: 44px; margin-top: 6px; padding: 8px 12px; border-radius: 12px; border: 1px solid var(--line); background: rgba(255, 255, 255, .08); color: #fff; font: inherit; }
.lantern { position: fixed; z-index: 5; left: 50%; bottom: 14%; width: 46px; height: 62px; margin-left: -23px; pointer-events: none; animation: cy-rise 7s ease-in forwards; }
.lantern i { display: block; width: 100%; height: 100%; border-radius: 40% 40% 30% 30%; background: radial-gradient(circle at 50% 70%, #FFF3C8, #FFB45A 55%, #C2561A); box-shadow: 0 0 26px 6px rgba(255, 180, 90, .7); }
@keyframes cy-rise { 0% { transform: translate(0, 0) scale(.6); opacity: 0; } 10% { opacity: 1; } 50% { transform: translate(-28px, -45vh) scale(1); } 100% { transform: translate(24px, -105vh) scale(.7); opacity: 0; } }
.floats { position: fixed; inset: 0; z-index: 4; pointer-events: none; overflow: hidden; }
.floats .amb { position: absolute; bottom: -80px; width: 22px; height: 30px; border-radius: 40% 40% 30% 30%; background: radial-gradient(circle at 50% 70%, #FFF3C8, #FFB45A 60%, #C2561A); box-shadow: 0 0 16px 3px rgba(255, 180, 90, .55); animation: cy-float 26s linear infinite; opacity: .85; }
.floats .words { position: absolute; bottom: -80px; max-width: 60vw; padding: 6px 12px; border-radius: 14px; background: rgba(10, 8, 30, .72); border: 1px solid var(--line); font-family: var(--serif); font-weight: 700; font-size: 15px; color: var(--gold2); animation: cy-float 30s linear infinite; }
@keyframes cy-float { from { transform: translateY(0); opacity: 0; } 8% { opacity: 1; } 92% { opacity: 1; } to { transform: translateY(-112vh); opacity: 0; } }

/* scene 4: midnight across the city */
#stage { position: absolute; inset: 0; transition: transform 2.6s cubic-bezier(.45, 0, .25, 1); transform-origin: 50% 70%; }
#stage[data-view="left"] { transform: translateX(7%) scale(1.14); } #stage[data-view="right"] { transform: translateX(-7%) scale(1.14); }
.cdn { position: absolute; z-index: 3; display: flex; align-items: center; justify-content: center; font-family: var(--serif); font-weight: 700; color: #fff8e0; text-shadow: 0 0 22px var(--gold), 0 0 50px var(--magenta); opacity: 0; transform: scale(.7); transition: opacity .5s ease, transform .5s ease; pointer-events: none; }
.cdn.on { opacity: 1; transform: scale(1); }
.gspot { position: absolute; z-index: 2; width: 260px; height: 260px; margin: -130px 0 0 -130px; border-radius: 50%; opacity: 0; pointer-events: none; }
.gspot.pulse { animation: cy-gspot .9s ease-out; } @keyframes cy-gspot { 0% { opacity: .5; transform: scale(.5); } 100% { opacity: 0; transform: scale(1.5); } }
/* the crowd at the railing stands still with their backs to us, watching the fireworks (no cheering bob, no hug sway) */
.crowd { transform-box: fill-box; transform-origin: 50% 100%; }
#happy { position: fixed; inset: 0; z-index: 8; display: flex; align-items: center; justify-content: center; text-align: center; pointer-events: none; font-family: var(--serif); font-weight: 700; font-size: clamp(34px, 10vw, 110px); line-height: 1; padding: 0 16px; color: var(--gold2); text-shadow: 0 0 32px var(--gold), 0 0 70px var(--magenta), 0 4px 0 rgba(0, 0, 0, .5); }
#happy[hidden] { display: none; } #happy span { animation: cy-pop .9s cubic-bezier(.3, 1.4, .5, 1) both; }
/* after a few seconds the words drop down the screen and fade into nothing */
#happy.drop span { animation: cy-hdrop 2.6s cubic-bezier(.55, 0, .8, .4) forwards; } @keyframes cy-hdrop { from { transform: translateY(0); opacity: 1; } to { transform: translateY(42vh); opacity: 0; } }
.rm #happy.drop span { animation: none; opacity: 0; } @keyframes cy-pop { from { transform: scale(.2); opacity: 0; } to { transform: scale(1); opacity: 1; } }
#f-bar { position: fixed; z-index: 9; left: 0; right: 0; bottom: calc(30px + var(--safe-b)); display: flex; justify-content: center; gap: 8px; flex-wrap: wrap; padding: 0 10px; } #f-bar[hidden] { display: none; }
#f-bar .btn { min-height: 44px; padding: 0 16px; font-size: 12px; }
#montage { position: fixed; inset: 0; z-index: 3; pointer-events: none; display: none; } #s4.still #montage { display: block; }

/* scene 5: the invitation */
.scroll { position: absolute; inset: 0; overflow-y: auto; overscroll-behavior: contain; padding: calc(68px + var(--safe-t)) 14px calc(40px + var(--safe-b)); display: flex; flex-direction: column; align-items: center; gap: 14px; }
.card { width: min(100%, 560px); padding: 22px 18px; border-radius: 20px; background: var(--card); border: 1px solid var(--line); text-align: center; } .card h2 { margin: 0 0 8px; font-family: var(--serif); font-size: clamp(24px, 6vw, 32px); }
.card.invite { border: 2px solid var(--gold); box-shadow: 0 0 40px -12px var(--gold); animation: cy-up 1.2s cubic-bezier(.2, .9, .3, 1) both; } #s5.still .card.invite { animation: none; }
.card.invite .big { margin: 6px 0; font-family: var(--serif); font-size: clamp(32px, 9vw, 52px); font-weight: 700; color: var(--gold2); line-height: 1.05; } .happy { font-weight: 700; letter-spacing: .08em; } .host { color: var(--gold2); font-weight: 700; } .when { font-weight: 700; margin: 8px 0 2px; } .where { margin: 0 0 8px; color: rgba(255, 255, 255, .86); }
@keyframes cy-up { from { transform: translateY(46px) scale(.96); opacity: 0; } to { transform: translateY(0) scale(1); opacity: 1; } }
.det { margin: 0; text-align: left; } .det div { padding: 8px 0; border-bottom: 1px solid rgba(255, 255, 255, .1); } .det dt { font-size: 11px; letter-spacing: .14em; text-transform: uppercase; color: var(--gold); } .det dd { margin: 2px 0 0; } .det small { display: block; color: rgba(255, 255, 255, .75); }
.field-row { text-align: left; margin: 10px 0; } .field-row label { display: block; font-weight: 700; font-size: 13px; margin-bottom: 4px; }
input[type=text], textarea.f { width: 100%; min-height: 46px; padding: 10px 12px; border-radius: 10px; border: 1px solid var(--line); background: rgba(255, 255, 255, .07); color: #fff; font: inherit; } textarea.f { min-height: 84px; resize: vertical; }
.radios { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; margin: 10px 0; } .radios label { padding: 10px 14px; border-radius: 22px; border: 1px solid var(--line); background: rgba(255, 255, 255, .05); font-weight: 700; cursor: pointer; }
.radios label:has(input:checked) { border-color: var(--gold); background: rgba(242, 197, 98, .18); } .radios input { accent-color: var(--gold); margin-right: 6px; }
.stepper { display: inline-flex; align-items: center; gap: 12px; } .stepper button { width: 44px; height: 44px; border-radius: 50%; border: 1px solid var(--line); background: rgba(255, 255, 255, .06); font-size: 22px; } .stepper output { min-width: 28px; font-weight: 800; font-size: 20px; }
.check { display: flex; gap: 8px; align-items: flex-start; text-align: left; font-size: 13.5px; } .check input { accent-color: var(--gold); margin-top: 3px; }
.keep canvas { max-width: 100%; height: auto; border-radius: 14px; border: 1px solid var(--line); }
.list { list-style: none; margin: 10px 0 0; padding: 0; display: grid; gap: 8px; text-align: left; } .list li { padding: 10px 12px; border-radius: 12px; background: rgba(255, 255, 255, .06); border: 1px solid var(--line); display: flex; gap: 10px; justify-content: space-between; align-items: center; } .list small { color: rgba(255, 255, 255, .7); display: block; } .list button { min-height: 36px; padding: 0 12px; border-radius: 18px; border: 1px solid var(--line); background: rgba(255, 255, 255, .06); font-size: 12px; font-weight: 700; }
.nav { display: flex; justify-content: space-between; width: min(100%, 560px); } .link { background: none; border: 0; color: var(--gold2); text-decoration: underline; min-height: 44px; font-weight: 700; }
.sheet { position: fixed; inset: 0; z-index: 60; background: rgba(0, 0, 0, .72); display: flex; align-items: center; justify-content: center; padding: 14px; } .sheet[hidden] { display: none; }
.sheet-in { width: min(100%, 520px); max-height: 90vh; overflow: auto; padding: 20px; border-radius: 20px; background: #0C0724; border: 1px solid var(--line); text-align: center; } .sheet-in h2 { margin: 0 0 10px; font-family: var(--serif); }
html.rm *, html.rm *::before, html.rm *::after { animation: none !important; transition-duration: .01ms !important; transition-delay: 0s !important; }
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation: none !important; transition-duration: .01ms !important; transition-delay: 0s !important; } }
.pts { position: fixed; z-index: 9; pointer-events: none; }
