:root {
  --bg1: #25102e; --bg2: #7a2f5c; --glow: #ff9ec4; --ink: #fff5f8;
  --script: 'Great Vibes', 'Dancing Script', cursive;
  --hand: 'Dancing Script', cursive;
  --ui: 'Quicksand', system-ui, sans-serif;
}
* { box-sizing: border-box; margin: 0; }
html, body { height: 100%; }
body {
  font-family: var(--ui); color: var(--ink); overflow: hidden;
  -webkit-tap-highlight-color: transparent; -webkit-touch-callout: none; overscroll-behavior: none;
  background: radial-gradient(120% 90% at 50% 0%, var(--bg2), var(--bg1) 70%) fixed;
}
body::before, body::after {
  content: ''; position: fixed; width: 60vmax; height: 60vmax; border-radius: 50%;
  background: var(--glow); opacity: .14; filter: blur(90px); pointer-events: none; z-index: 0;
  animation: drift 18s ease-in-out infinite alternate;
}
body::before { top: -25vmax; left: -20vmax; }
body::after { bottom: -30vmax; right: -20vmax; animation-delay: -9s; }
@keyframes drift { to { transform: translate(8vmax, 6vmax) scale(1.15); } }

#app { position: fixed; inset: 0; overflow-y: auto; overflow-x: hidden; z-index: 2; }
#rain { position: fixed; inset: 0; overflow: hidden; pointer-events: none; z-index: 1; }
#wipe { position: fixed; inset: 0; z-index: 50; visibility: hidden; pointer-events: none; }

/* falling petals */
.rp {
  position: absolute; top: -30px; border-radius: 150% 0 150% 0; opacity: 0;
  animation: fall linear infinite;
}
@keyframes fall {
  0% { transform: translate3d(0, -5vh, 0) rotate(0); opacity: 0; }
  8% { opacity: .85; }
  50% { transform: translate3d(var(--sx), 50vh, 0) rotate(200deg); }
  100% { transform: translate3d(calc(var(--sx) * -.6), 108vh, 0) rotate(420deg); opacity: 0; }
}

/* buttons */
button { font: inherit; color: inherit; cursor: pointer; border: 0; background: none; }
.ghost {
  padding: 10px 18px; border-radius: 999px; background: rgba(255,255,255,.1);
  border: 1px solid rgba(255,255,255,.2); backdrop-filter: blur(8px);
  transition: transform .25s, background .25s, box-shadow .25s;
}
.ghost:hover { background: rgba(255,255,255,.2); transform: translateY(-2px); box-shadow: 0 8px 24px -8px var(--glow); }
.round { width: 42px; height: 42px; padding: 0; display: inline-grid; place-items: center; font-size: 1.2rem; }

/* ============ HOME ============ */
.home { min-height: 100%; display: flex; flex-direction: column; justify-content: center; padding: 28px 0 24px; text-align: center; }
.home header { padding: 0 20px; animation: fadeup 1.2s .1s both; }
.eyebrow { letter-spacing: .4em; text-transform: uppercase; font-size: .75rem; opacity: .75; }
.title {
  font-family: var(--script); font-weight: 400; line-height: 1.1;
  font-size: clamp(3.4rem, 12vw, 7rem); margin: 6px 0;
  background: linear-gradient(100deg, #fff 20%, var(--glow) 45%, #fff 70%); background-size: 250% 100%;
  -webkit-background-clip: text; background-clip: text; color: transparent;
  animation: shimmer 6s linear infinite; filter: drop-shadow(0 6px 24px rgba(255,120,170,.35));
}
@keyframes shimmer { to { background-position: -250% 0; } }
.sub { max-width: 30em; margin: 0 auto; opacity: .85; line-height: 1.6; }

.carousel-wrap { position: relative; margin-top: 10px; }
.carousel {
  --cw: min(76vw, 290px);
  display: flex; gap: 26px; overflow-x: auto; padding: 34px calc(50vw - var(--cw) / 2) 30px;
  scroll-snap-type: x proximity; scrollbar-width: none; cursor: grab;
}
.carousel::-webkit-scrollbar { display: none; }
.carousel.dragging { scroll-snap-type: none; cursor: grabbing; }
.card {
  flex: 0 0 var(--cw); height: min(58vh, 400px); min-height: 330px; scroll-snap-align: center; position: relative;
  border-radius: 30px; padding: 22px 18px; display: flex; flex-direction: column; align-items: center; justify-content: flex-end;
  background: linear-gradient(160deg, rgba(255,255,255,.16), rgba(255,255,255,.04));
  border: 1px solid rgba(255,255,255,.22); backdrop-filter: blur(10px); overflow: hidden;
  transform: scale(.86); opacity: .55; filter: saturate(.6);
  transition: transform .55s cubic-bezier(.2,.9,.3,1), opacity .5s, filter .5s, box-shadow .5s;
  animation: fadeup .9s both; animation-delay: calc(.4s + var(--i) * .12s);
  user-select: none; -webkit-user-drag: none;
}
.card::before {
  content: ''; position: absolute; inset: 0;
  background: radial-gradient(circle at 50% 38%, var(--c), transparent 62%); opacity: .35;
}
.card.active { transform: scale(1); opacity: 1; filter: none; box-shadow: 0 30px 60px -25px var(--c), 0 0 0 1px rgba(255,255,255,.3) inset; }
.card.active:hover { transform: scale(1.03) translateY(-4px); }
.letter {
  position: absolute; top: 4px; left: 20px; font-family: var(--script); font-size: 6.5rem; line-height: 1; opacity: .35;
}
.card svg { position: absolute; top: 8%; left: 8%; width: 84%; height: 58%; overflow: visible; }
.card .flw { animation: bob 5s ease-in-out infinite; }
.cname { position: relative; font-family: var(--script); font-size: 2.3rem; line-height: 1.1; }
.csub { position: relative; font-size: .8rem; letter-spacing: .22em; text-transform: uppercase; opacity: .8; margin-top: 4px; }
.copen { position: relative; margin-top: 12px; font-size: .85rem; opacity: 0; transform: translateY(6px); transition: .4s; }
.card.active .copen { opacity: .9; transform: none; animation: nudge 1.6s ease-in-out infinite; }
@keyframes nudge { 50% { transform: translateX(5px); } }

.arrow { position: absolute; top: 50%; transform: translateY(-50%); z-index: 3; }
.arrow.l { left: 12px; } .arrow.r { right: 12px; }
@media (max-width: 700px) { .arrow { display: none; } }

.chips { display: flex; justify-content: center; gap: 12px; margin-top: 4px; animation: fadeup 1s 1.1s both; }
.chip {
  width: 46px; height: 46px; border-radius: 50%; font-family: var(--script); font-size: 1.7rem; line-height: 1;
  background: rgba(255,255,255,.1); border: 1px solid rgba(255,255,255,.25);
  transition: .35s cubic-bezier(.2,.9,.3,1);
}
.chip:hover { transform: translateY(-4px) scale(1.08); }
.chip.active { background: #fff; color: #5a1f45; box-shadow: 0 0 26px var(--glow); transform: scale(1.12); }
.hint { margin-top: 16px; font-size: .8rem; letter-spacing: .2em; opacity: .55; animation: fadeup 1s 1.3s both; }

/* ============ BOUQUET ============ */
.bq { min-height: 100%; display: flex; flex-direction: column; padding: 16px; }
.topbar { display: flex; justify-content: space-between; align-items: center; gap: 10px; position: relative; z-index: 5; }
.tag { font-family: var(--script); font-size: 1.7rem; opacity: .9; }
.pn { display: flex; gap: 8px; }
.stage { flex: 1; display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: clamp(10px, 4vw, 56px); padding: 6px; }
.bouquet-wrap { position: relative; width: min(90vw, 520px, calc((100dvh - 110px) * .714)); aspect-ratio: 400 / 560; cursor: pointer; }
.halo {
  position: absolute; inset: 4% 0 24%; border-radius: 50%; background: radial-gradient(circle, var(--glow), transparent 65%);
  filter: blur(28px); opacity: 0; animation: halo 3s 1s ease-out forwards;
}
@keyframes halo { to { opacity: .5; } }
.bob { position: relative; width: 100%; height: 100%; animation: bob 6s ease-in-out infinite; }
.bq-svg { width: 100%; height: 100%; overflow: visible; filter: drop-shadow(0 24px 30px rgba(0,0,0,.35)); }
@keyframes bob { 50% { transform: translateY(-8px) rotate(.6deg); } }

.msg {
  width: min(92vw, 460px); padding: 28px 26px; border-radius: 28px;
  background: rgba(255,255,255,.09); border: 1px solid rgba(255,255,255,.2); backdrop-filter: blur(14px);
  box-shadow: 0 30px 60px -30px rgba(0,0,0,.5); animation: fadeup 1s .4s both;
}
.kicker { font-size: .72rem; letter-spacing: .3em; text-transform: uppercase; opacity: .7; }
.msg h2 { font-family: var(--ui); font-weight: 600; font-size: clamp(1.6rem, 4.5vw, 2.1rem); margin: 4px 0 6px; }
.text p { font-family: var(--ui); font-weight: 500; font-size: clamp(1rem, 2.2vw, 1.15rem); line-height: 1.7; margin: .7em 0; }
.tap-hint { font-size: .8rem; opacity: .75; margin-top: 6px; animation: nudge2 2.4s ease-in-out infinite; }
@keyframes nudge2 { 50% { opacity: 1; transform: translateY(-2px); } }

/* tappable flowers */
.fl { cursor: pointer; outline: none; }
.fl:hover .sway, .fl:focus-visible .sway { filter: brightness(1.12) drop-shadow(0 0 8px var(--glow)); }

/* flower that was picked: hidden on its stem while it sits on the polaroid */
.fl.picked { visibility: hidden; }
.fl.back { animation: regrow .6s cubic-bezier(.3,1.6,.5,1); }
@keyframes regrow { from { opacity: 0; } to { opacity: 1; } }
.fly { position: fixed; z-index: 70; pointer-events: none; transform-origin: center; filter: drop-shadow(0 10px 14px rgba(0,0,0,.4)); }
.fly svg, .lb-flower svg { width: 100%; height: 100%; overflow: visible; display: block; }
/* cloned flower must not replay the bloom animation */
.flw-clone .petal { animation: none; transform: none; opacity: 1; }
.flw-clone .core { animation: none; opacity: 1; }
.flw-clone .spin { animation: none; }
.flw-clone .sway { animation: sway 6s ease-in-out infinite alternate; }

/* picture popup */
.lb { position: fixed; inset: 0; z-index: 60; display: grid; place-items: center; padding: 16px; background: rgba(10,4,14,.72); backdrop-filter: blur(6px); opacity: 0; transition: opacity .3s; }
.lb[hidden] { display: none; }
.lb.open { opacity: 1; }
.polaroid { position: relative; width: min(86vw, 380px); padding: 14px 14px 18px; background: #fffaf5; color: #3a2230; border-radius: 6px; box-shadow: 0 30px 70px -20px rgba(0,0,0,.7); text-align: center; }
.polaroid.flip { animation: polain .5s cubic-bezier(.2,.9,.3,1); }
@keyframes polain { from { transform: translateY(24px) rotate(-4deg) scale(.92); opacity: .4; } to { transform: none; opacity: 1; } }
.ph { position: relative; aspect-ratio: 1; background: #eadfe3; overflow: hidden; display: grid; place-items: center; }
.ph img { width: 100%; height: 100%; object-fit: cover; cursor: pointer; display: none; }
.ph-miss { display: none; padding: 18px; font-size: .85rem; line-height: 1.5; color: #7a5a68; word-break: break-word; }
.polaroid figcaption { font-family: var(--ui); font-weight: 600; font-size: 1.05rem; line-height: 1.5; margin-top: 12px; padding: 0 6px; }
.lb-nav { display: flex; justify-content: center; align-items: center; gap: 16px; margin-top: 10px; font-size: .85rem; }
.polaroid .ghost { color: #3a2230; background: rgba(58,34,48,.08); border-color: rgba(58,34,48,.18); }
.lb-flower { position: absolute; top: -42px; left: -38px; width: 104px; height: 104px; transform: rotate(14deg); pointer-events: none; filter: drop-shadow(0 8px 10px rgba(0,0,0,.35)); z-index: 2; }
.lb-x { position: absolute; top: -14px; right: -14px; width: 36px; height: 36px; font-size: .9rem; background: #fff !important; box-shadow: 0 6px 16px rgba(0,0,0,.35); }
.w { display: inline-block; white-space: nowrap; }
.c { opacity: 0; filter: blur(4px); transition: opacity .5s, filter .5s; }
.c.on { opacity: 1; filter: none; }
.sig { font-family: var(--ui); font-weight: 600; font-size: 1.15rem; margin-top: 10px; text-align: right; opacity: 0; transform: translateY(8px); transition: 1s; }
.sig.on { opacity: 1; transform: none; }
.actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 16px; }

/* burst particles */
.pt { position: fixed; z-index: 40; pointer-events: none; }

/* ============ FLOWER ANIMATIONS ============ */
.stem { stroke-dasharray: 1; stroke-dashoffset: 1; animation: grow 1.5s cubic-bezier(.3,.7,.2,1) forwards; animation-delay: var(--sd); }
@keyframes grow { to { stroke-dashoffset: 0; } }
.leaf { transform: scale(0); animation: pop 1.1s cubic-bezier(.3,1.3,.5,1) forwards; animation-delay: var(--ld); }
.bl, .bow { transform: scale(0); opacity: 0; animation: pop .9s cubic-bezier(.3,1.6,.5,1) forwards; animation-delay: var(--bd); }
@keyframes pop { to { transform: scale(1); opacity: 1; } }
.paper { opacity: 0; animation: paperin .9s cubic-bezier(.2,.9,.3,1) forwards; animation-delay: var(--pd); }
@keyframes paperin { from { transform: translateY(50px); opacity: 0; } to { transform: none; opacity: 1; } }

.petal { transform: scale(0); opacity: 0; animation: unfurl 1.2s cubic-bezier(.2,1.15,.3,1) forwards; animation-delay: calc(var(--base) + var(--pd)); }
@keyframes unfurl { 0% { transform: scale(0); opacity: 0; } 25% { opacity: 1; } 100% { transform: scale(1); opacity: 1; } }
.core { opacity: 0; animation: fadein .9s forwards; animation-delay: calc(var(--base) + .55s); }
@keyframes fadein { to { opacity: 1; } }
.spin { animation: spinin 2s cubic-bezier(.2,.9,.3,1) both; animation-delay: var(--base); }
@keyframes spinin { from { transform: rotate(-45deg) scale(.4); } to { transform: none; } }
.sway { animation: sway 6s ease-in-out infinite alternate; animation-delay: calc(var(--base) + 1.8s); }
@keyframes sway { from { transform: rotate(-1.8deg); } to { transform: rotate(1.8deg); } }

.tw { transform: scale(0); opacity: 0; animation: twinkle var(--td) ease-in-out infinite; animation-delay: var(--tl); }
@keyframes twinkle { 0%, 100% { transform: scale(0) rotate(0); opacity: 0; } 50% { transform: scale(1) rotate(45deg); opacity: .95; } }

@keyframes fadeup { from { opacity: 0; transform: translateY(24px); } to { opacity: 1; transform: none; } }
/* .card overrides opacity/transform, so give it its own entrance */
.card { animation-name: cardin; }
@keyframes cardin { from { translate: 0 30px; opacity: 0; } to { translate: 0 0; } }

@media (prefers-reduced-motion: reduce) {
  .rp, body::before, body::after { display: none; }
}
@media (max-width: 800px) { .stage { flex-direction: column; } }

/* ============ FINALE: spinning peony, capybara, memory book ============ */
.fin { position: fixed; inset: 0; z-index: 55; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px;
  background: radial-gradient(90% 70% at 50% 40%, rgba(120,40,90,.82), rgba(22,6,22,.94)); backdrop-filter: blur(6px);
  opacity: 0; transition: opacity .4s; overflow: hidden; }
.fin.on { opacity: 1; }
.fin-x { position: absolute; top: max(14px, env(safe-area-inset-top)); right: 14px; z-index: 5; }

.fin-stage { position: relative; width: var(--S); height: var(--S); transition: opacity .6s, transform .6s; }
.fin-stage.away { opacity: 0; transform: scale(.8); pointer-events: none; }
.fin-flower { position: absolute; left: 50%; top: 50%; width: var(--F); height: var(--F); margin: calc(var(--F) / -2) 0 0 calc(var(--F) / -2); filter: drop-shadow(0 14px 24px rgba(0,0,0,.45)); }
.fin-clone, .fin-spin { position: absolute; inset: 0; }
.fin-clone svg, .fin-spin svg { width: 100%; height: 100%; display: block; overflow: visible; }
.fin-clone { transition: opacity 1.6s; }
.fin-clone.fade { opacity: 0; }
.fin-spin.go { animation: finspin 24s linear infinite; }
@keyframes finspin { to { transform: rotate(360deg); } }
/* the bloom in the spinner should unfurl, not sway */
.fin-spin .sway { animation: none; }

.orbit { position: absolute; inset: 0; animation: finspin var(--dur) linear infinite var(--dir); }
.it { position: absolute; left: 50%; top: 50%; width: var(--isz); height: calc(var(--isz) * 1.22);
  margin: calc(var(--isz) * -.61) 0 0 calc(var(--isz) / -2);
  transform: rotate(var(--a)) translateY(calc(var(--R) * -1)) rotate(calc(var(--a) * -1)); }
.it .p { width: 100%; height: 100%; padding: 3px 3px 9px; background: #fffaf5; border-radius: 3px; box-shadow: 0 10px 22px rgba(0,0,0,.45);
  opacity: 0; animation: finspin var(--dur) linear infinite var(--cdir), fadein .8s var(--d) forwards; }
.it img { width: 100%; height: 100%; object-fit: cover; display: block; border-radius: 2px; }

/* capybara peeking out of the flower centre */
.capy { position: absolute; left: 50%; top: 50%; width: calc(var(--S) * .27); transform: translate(-50%, -30%) scale(0); transform-origin: 50% 85%;
  cursor: pointer; padding: 0; opacity: 0; filter: drop-shadow(0 10px 14px rgba(0,0,0,.4)); }
.capy[hidden] { display: none; }
.capy.on { animation: capypop 2.6s ease-in-out forwards, capybob 2.2s 2.7s ease-in-out infinite; }
.capy .bubble { opacity: 0; animation: fadein .5s 2.4s forwards; }
/* struggles out of the flower: peeks, slips back, wiggles, pushes harder, then bursts out */
@keyframes capypop {
  0%   { opacity: 0; transform: translate(-50%, -30%) scale(.1) rotate(0deg); }
  14%  { opacity: 1; transform: translate(-50%, -40%) scale(.4, .5) rotate(-7deg); }
  26%  { transform: translate(-50%, -34%) scale(.3, .36) rotate(6deg); }
  40%  { transform: translate(-50%, -46%) scale(.58, .66) rotate(-8deg); }
  52%  { transform: translate(-50%, -38%) scale(.46, .52) rotate(7deg); }
  66%  { transform: translate(-50%, -50%) scale(.76, .86) rotate(-5deg); }
  76%  { transform: translate(-50%, -44%) scale(.7, .76) rotate(4deg); }
  90%  { transform: translate(-50%, -68%) scale(.94, 1.12) rotate(0deg); }
  100% { opacity: 1; transform: translate(-50%, -60%) scale(1) rotate(0deg); }
}
@keyframes capybob { 50% { margin-top: -8px; } }
.capy-svg { width: 100%; display: block; }
.bubble { position: absolute; left: 50%; bottom: calc(100% - 2px); transform: translateX(-50%); white-space: nowrap; font-size: .85rem; font-weight: 600;
  padding: 7px 12px; border-radius: 14px; background: #fffaf5; color: #3a2230; box-shadow: 0 6px 16px rgba(0,0,0,.35); }
.bubble::after { content: ''; position: absolute; left: 50%; top: 100%; margin-left: -6px; border: 6px solid transparent; border-top-color: #fffaf5; }

/* memory book: pages flip away one by one, the last page stays */
.book-wrap { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px;
  opacity: 0; transform: scale(.9); transition: opacity .6s, transform .6s; perspective: 1400px; }
.book-wrap.on { opacity: 1; transform: none; }
.book { position: relative; max-width: 96vw; filter: drop-shadow(0 24px 30px rgba(0,0,0,.5)); }
.bleaf { position: absolute; inset: 0; transform-origin: left center; border-radius: 6px 12px 12px 6px; overflow: hidden; background: #fffaf5;
  transition: transform .55s ease-in, opacity .25s .3s; box-shadow: inset 8px 0 14px -8px rgba(0,0,0,.25); }
.bleaf.flipped { transform: rotateY(-105deg); opacity: 0; pointer-events: none; }
.book.fast .bleaf { transition: none; }
.cover { background: linear-gradient(150deg, #f07aa3, #b8456f); color: #fff; }
.cv { height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; text-align: center; border: 2px solid rgba(255,255,255,.55); margin: 12px; height: calc(100% - 24px); border-radius: 8px; }
.cv span { font-size: .95rem; letter-spacing: .4em; text-transform: uppercase; opacity: .9; }
.cv b { font-size: clamp(1.8rem, 8vw, 2.4rem); font-weight: 700; }
.cv i { font-style: normal; font-size: 1.8rem; opacity: .9; }
.pg { height: 100%; padding: 16px 16px 12px; display: flex; flex-direction: column; gap: 8px; color: #3a2230; }
.pimg { flex: 1; min-height: 0; background: #eadfe3; border-radius: 3px; overflow: hidden; }
.pimg img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pg p { font-weight: 600; font-size: .92rem; line-height: 1.4; text-align: center; min-height: 2.6em; }
.pg small { text-align: center; font-size: .72rem; opacity: .55; letter-spacing: .15em; }
.tog { align-items: center; }
.tog .to-letter { flex: none; }
.tog h3 { font-weight: 700; font-size: 1.25rem; padding-top: 4px; }
.tgrid { flex: 1; min-height: 0; width: 100%; display: flex; flex-wrap: wrap; align-content: center; justify-content: center; gap: 10px; }
.tg { width: 38%; aspect-ratio: 3 / 4; padding: 5px 5px 14px; background: #fff; border-radius: 3px; box-shadow: 0 8px 18px rgba(0,0,0,.28);
  transform: rotate(var(--r)); transition: transform .3s; cursor: pointer; animation: tgpulse 2.2s ease-in-out infinite; }
.tg:hover { transform: rotate(0) scale(1.06); }
.tg img { width: 100%; height: 100%; object-fit: cover; display: block; }
@keyframes tgpulse { 50% { box-shadow: 0 8px 18px rgba(0,0,0,.28), 0 0 0 4px rgba(240,122,163,.55); } }

.capy2 { position: relative; width: min(24vw, 100px); align-self: flex-end; margin-right: max(12px, calc(50% - 46vw)); opacity: 0; transform: translateX(60px); transition: opacity .6s, transform .7s cubic-bezier(.2,.9,.3,1); }
.capy2[hidden] { display: none; }
.capy2.on { opacity: 1; transform: none; }
.capy2 .bubble { left: auto; right: 40%; transform: none; }
.capy2 .bubble::after { left: auto; right: 22px; margin-left: 0; }
.cpaw { transform-origin: 30px 150px; animation: point 1s ease-in-out infinite alternate; }
@keyframes point { from { transform: rotate(-10deg); } to { transform: rotate(8deg); } }
.fin-skip { position: absolute; bottom: max(16px, env(safe-area-inset-bottom)); left: 50%; transform: translateX(-50%); }
.fin-skip[hidden] { display: none; }

@media (prefers-reduced-motion: reduce) {
  .orbit, .it .p, .fin-spin.go { animation-duration: 0s; }
}

/* a few capybaras wandering along the bottom of the finale */
.walkers { position: absolute; left: 0; right: 0; bottom: 0; height: 180px; pointer-events: none; z-index: 1; overflow: hidden;
  background: linear-gradient(to top, rgba(255,150,190,.16), transparent); }
.wk { position: absolute; left: 0; bottom: var(--b); width: var(--sz); opacity: 0;
  animation: wander var(--dur) linear var(--dly) infinite, fadein .8s var(--in) forwards; }
/* walk right, turn around, walk back left */
@keyframes wander {
  0%      { transform: translateX(0) scaleX(1); }
  49.9%   { transform: translateX(calc(100vw - var(--sz))) scaleX(1); }
  50%     { transform: translateX(calc(100vw - var(--sz))) scaleX(-1); }
  99.9%   { transform: translateX(0) scaleX(-1); }
  100%    { transform: translateX(0) scaleX(1); }
}
.capy-body { width: 100%; display: block; overflow: visible; animation: walkbob .7s ease-in-out infinite alternate; filter: drop-shadow(0 5px 6px rgba(0,0,0,.3)); }
@keyframes walkbob { from { transform: translateY(0) rotate(-.8deg); } to { transform: translateY(-3px) rotate(.8deg); } }
.lg { transform-box: fill-box; transform-origin: 50% 0; animation: legstep .7s ease-in-out infinite alternate; }
.lg2 { animation-direction: alternate-reverse; }
@keyframes legstep { from { transform: rotate(-16deg); } to { transform: rotate(16deg); } }
/* keep the Skip button clear of the floor */
.fin-skip { bottom: calc(max(6px, env(safe-area-inset-bottom)) + 128px); }
@media (prefers-reduced-motion: reduce) { .capy-body, .lg, .wk { animation: none; opacity: 1; } }

/* letter page + button on the photos page */
.to-letter { margin-top: 8px; padding: 8px 16px; font-size: .9rem; color: #3a2230; background: rgba(240,122,163,.16); border-color: rgba(184,69,111,.4); }
.to-letter:hover { background: rgba(240,122,163,.3); box-shadow: none; }
.lt { padding-top: 18px; background: repeating-linear-gradient(to bottom, transparent 0 27px, rgba(184,69,111,.12) 27px 28px); background-position: 0 70px; background-repeat: repeat-y; }
.lt h3 { font-weight: 700; font-size: 1.2rem; padding-bottom: 6px; }
.ltxt { flex: 1; min-height: 0; overflow-y: auto; padding-right: 6px; -webkit-overflow-scrolling: touch; }
.ltxt p { font-weight: 500; font-size: .95rem; line-height: 28px; margin: 0 0 14px; text-align: left; min-height: 0; }
.ltxt .lsign { text-align: right; font-weight: 700; margin-top: 6px; }
.lact { display: flex; justify-content: space-between; gap: 8px; padding-top: 8px; }
.lact .ghost { color: #3a2230; background: rgba(58,34,48,.08); border-color: rgba(58,34,48,.18); padding: 8px 14px; font-size: .85rem; }
.lact .lt-close { background: rgba(240,122,163,.2); border-color: rgba(184,69,111,.45); font-weight: 600; }

/* ============ MUSEUM (first page): a dim 360° gallery you can turn around in ============ */
.mus { position: relative; height: 100%; background: #0d070e; overflow: hidden; animation: musin 2.2s ease both; }
@keyframes musin { from { opacity: 0; } to { opacity: 1; } }
/* vignette + a little grain so it feels like a dim room, not a flat graphic */
.mus::after { content: ''; position: absolute; inset: 0; pointer-events: none; z-index: 3;
  background:
    radial-gradient(120% 90% at 50% 45%, transparent 38%, rgba(4,2,6,.62) 100%),
    linear-gradient(rgba(8,4,10,.18), rgba(8,4,10,.18)); }

/* the camera: you stand in the middle of a ring of walls (sizes come from JS as --R --W --H --ceil --floor --Rc) */
.v360 { position: absolute; inset: 0; perspective: var(--R, 800px); perspective-origin: 50% 50%; overflow: hidden;
  touch-action: none; cursor: grab; user-select: none; -webkit-user-select: none; -webkit-tap-highlight-color: transparent; }
.v360.grab { cursor: grabbing; }
.v360 img { pointer-events: none; -webkit-user-drag: none; }
.world { position: absolute; left: 50%; top: 50%; width: 0; height: 0; transform-style: preserve-3d; }

/* ceiling and floor */
.ceil3, .floor3 { position: absolute; left: 0; top: 0; transform-origin: 0 0; backface-visibility: hidden; }
.ceil3 { background: radial-gradient(circle at 50% 50%, #120a12 0, #1a0f19 60%, #0b060c 100%); }

/* a wall: plaster texture, panelled lower part, a light track along the ceiling */
.wp { position: absolute; left: 0; top: 0; width: var(--W); height: var(--H); transform-origin: 0 0; backface-visibility: hidden;
  transform: rotateY(var(--a)) translate3d(calc(var(--W) * -.5), var(--ceil), calc(var(--R) * -1));
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 .5 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.55'/%3E%3C/svg%3E"), linear-gradient(#2c2229, #221a22 70%, #1c141c);
  box-shadow: inset 0 0 calc(var(--W) * .12) rgba(0,0,0,.4); }
.wp::before { content: ''; position: absolute; left: 0; right: 0; top: 0; height: 7%; background: linear-gradient(#07040a, #150c15); box-shadow: 0 6px 18px rgba(0,0,0,.6); }
.wp::after { content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 25%;
  background:
    repeating-linear-gradient(90deg, transparent 0 138px, rgba(0,0,0,.28) 138px 140px, rgba(255,255,255,.04) 140px 142px),
    linear-gradient(#1d141b, #170f16);
  border-top: 5px solid #2c2128; box-shadow: 0 -2px 0 rgba(201,160,100,.35), 0 -14px 24px rgba(0,0,0,.35); }
.rail { position: absolute; left: 0; right: 0; top: 5.2%; height: 6px; background: linear-gradient(#2a2a30, #121216); box-shadow: 0 3px 6px rgba(0,0,0,.6); }
.fix, .mspot { position: absolute; left: 50%; width: 20px; height: 20px; transform: translateX(-50%); border-radius: 4px 4px 12px 12px; background: linear-gradient(#303036, #0f0f12); box-shadow: 0 6px 14px rgba(255,222,170,.35); }
.fix { top: calc(var(--ty) * -1 - 4px); }
.mspot { top: 6.2%; }
.fix::after, .mspot::after { content: ''; position: absolute; left: 50%; bottom: -2px; width: 11px; height: 6px; transform: translateX(-50%); border-radius: 50%; background: #ffe6b8; box-shadow: 0 0 14px 5px rgba(255,226,170,.55); }
/* the wall behind the vase gets a warm wash from its own spot */
.wp[data-k="0"] { background: radial-gradient(60% 70% at 50% 62%, rgba(255,226,170,.13), transparent 70%), url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 .5 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.55'/%3E%3C/svg%3E"), linear-gradient(#2c2229, #221a22 70%, #1c141c); }

/* dust floating in the light */
.dust { position: absolute; inset: 8% 0 24%; pointer-events: none; z-index: 2; }
.dust b { position: absolute; width: var(--s); height: var(--s); border-radius: 50%; background: #ffe9c4; opacity: 0;
  animation: mote var(--dur) linear var(--dl) infinite; }
@keyframes mote { 0% { opacity: 0; transform: translate(0, 0); } 20% { opacity: .55; } 80% { opacity: .35; } 100% { opacity: 0; transform: translate(var(--dx), -90px); } }

/* frames: dark wood moulding, gold inner edge, matted picture behind glass. Position + size are set by JS. */
.mframe { position: absolute; padding: 0; transform: rotate(var(--tilt, 0deg)); transform-origin: 50% 0; opacity: 0;
  animation: framein 1.4s calc(.8s + var(--i) * .1s) cubic-bezier(.2,.8,.3,1) forwards; cursor: pointer; z-index: 1; }
@keyframes framein { from { opacity: 0; } to { opacity: 1; } }
/* the light cone from the fixture above the frame */
.mframe::before { content: ''; position: absolute; left: 50%; bottom: 30%; width: 230%; height: calc(var(--ty) + 70%); transform: translateX(-50%); z-index: -1; pointer-events: none;
  clip-path: polygon(47% 0, 53% 0, 100% 100%, 0 100%); background: linear-gradient(rgba(255,226,170,.2), rgba(255,226,170,.04) 70%, transparent); }
.mframe:hover .mwood, .mframe:focus-visible .mwood { filter: brightness(1.12); }
.mwood { position: relative; display: block; padding: 5.5%; border-radius: 2px; transition: filter .4s;
  background: linear-gradient(135deg, #5b3b22, #2e1b0e 50%, #4d311b);
  box-shadow: 0 22px 30px -10px rgba(0,0,0,.8), 0 6px 10px rgba(0,0,0,.5), inset 0 1px 0 rgba(255,255,255,.14), inset 0 0 0 1px rgba(0,0,0,.5); }
.mwood::before { content: ''; position: absolute; left: 50%; top: -26px; width: 36%; height: 26px; transform: translateX(-50%); opacity: .55;
  background: linear-gradient(#8a8a90, #4a4a50); clip-path: polygon(49% 0, 51% 0, 100% 100%, 98% 100%, 50% 6%, 2% 100%, 0 100%); }
.mfil { display: block; padding: 2.5%; background: linear-gradient(135deg, #d2ae6c, #8a6a30 55%, #bf9a56); box-shadow: inset 0 0 6px rgba(0,0,0,.5); }
.mmat { position: relative; display: block; aspect-ratio: var(--ratio); background: #e9e1d4; padding: 8%; box-shadow: inset 0 2px 8px rgba(0,0,0,.45); overflow: hidden; }
.mmat img { width: 100%; height: 100%; object-fit: cover; display: block; filter: brightness(.86) contrast(1.03) saturate(.92); }
.mmat::after { content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(118deg, rgba(255,255,255,.2), rgba(255,255,255,.04) 32%, transparent 55%), linear-gradient(to bottom, rgba(255,226,170,.12), transparent 40%); }
.mplaque { display: block; margin: 12px auto 0; width: fit-content; max-width: 100%; padding: 4px 11px; font-size: .68rem; font-weight: 600; letter-spacing: .08em; text-transform: uppercase;
  color: #2a1f10; background: linear-gradient(#bfa169, #8e7340); border-radius: 2px; box-shadow: 0 5px 8px rgba(0,0,0,.5), inset 0 1px 0 rgba(255,255,255,.3); }

/* things that stand on the floor between you and the wall: each is a flat cut-out placed on a ring (--a angle, --r distance) */
.bb { position: absolute; left: 0; top: 0; transform-origin: 0 0; pointer-events: none;
  transform: rotateY(var(--a)) translate3d(0, var(--floor), calc(var(--r) * -1)) translate(-50%, -100%); }

/* a museum bench to rest on */
.bench { width: calc(var(--H) * .34 * .8); height: calc(var(--H) * .104); }
.bench .seat { position: absolute; left: 0; right: 0; top: 0; height: 38%; border-radius: 10px; background: linear-gradient(#4a3a3d, #2a1f22); box-shadow: 0 -2px 6px rgba(255,255,255,.07) inset, 0 10px 14px rgba(0,0,0,.5); }
.bench .lg { position: absolute; top: 36%; width: 5%; height: 64%; background: linear-gradient(90deg, #2b1a0f, #4d321e); border-radius: 2px; }
.bench .l1 { left: 9%; } .bench .l2 { right: 9%; }

/* table + vase */
.vase-btn { pointer-events: auto; height: calc(var(--H) * .5); width: calc(var(--H) * .5 * 360 / 470); padding: 0; cursor: pointer;
  filter: drop-shadow(0 0 16px rgba(255,190,200,.22)); animation: vglow 5s ease-in-out infinite; }
.vase-svg { height: 100%; width: 100%; display: block; overflow: visible; transition: transform .6s cubic-bezier(.2,.9,.3,1); }
.vase-btn:hover .vase-svg, .vase-btn:focus-visible .vase-svg { transform: scale(1.03); }
@keyframes vglow { 50% { filter: drop-shadow(0 0 28px rgba(255,190,200,.4)); } }
.vase-hint { position: absolute; left: 50%; top: -6px; transform: translateX(-50%); z-index: 2; white-space: nowrap; font-size: .8rem; font-weight: 600; letter-spacing: .05em; padding: 7px 14px; border-radius: 999px;
  color: #f1dcb4; background: rgba(18,10,16,.72); border: 1px solid rgba(232,201,143,.45); backdrop-filter: blur(6px); box-shadow: 0 6px 16px rgba(0,0,0,.5); animation: nudge2 3.4s ease-in-out infinite; }

.mus-hint { position: absolute; left: 50%; bottom: 18px; transform: translateX(-50%); z-index: 4; font-size: .74rem; letter-spacing: .2em; text-transform: uppercase; white-space: nowrap; color: #d9c7a6; opacity: .65; transition: opacity .8s; pointer-events: none; text-shadow: 0 2px 8px rgba(0,0,0,.8); }
.mus-hint.gone { opacity: 0; }
.to-vase { position: absolute; right: 14px; bottom: 14px; z-index: 4; font-weight: 600; color: #f1dcb4; background: rgba(18,10,16,.6); border-color: rgba(232,201,143,.4); }
.back-gal { position: absolute; top: 14px; left: 14px; z-index: 4; }
.home { position: relative; }
@media (prefers-reduced-motion: reduce) { .dust b, .vase-btn, .vase-hint { animation: none; } }

/* the boy, quietly looking at the frames */
.viewers { height: calc(var(--H) * .46); width: calc(var(--H) * .46 * 124 / 520); opacity: 0; animation: musin 3s 1.6s ease forwards; }
.viewers-svg { height: 100%; width: 100%; display: block; overflow: visible; }
.fig { transform-origin: 50% 70%; animation: figsway 9s ease-in-out infinite alternate; }
@keyframes figsway { from { transform: rotate(-.35deg); } to { transform: rotate(.35deg); } }
@media (prefers-reduced-motion: reduce) { .fig { animation: none; } }

/* the girl sits on the bench beside the vase, turned toward it */
.sitter { height: calc(var(--H) * .34); width: calc(var(--H) * .34 * .75); opacity: 0; animation: musin 3s 2.2s ease forwards; }
.sitter-svg { height: 100%; width: 100%; display: block; overflow: visible; }
.sit2 { transform-origin: 50% 100%; animation: sitbreath 6s ease-in-out infinite alternate; }
@keyframes sitbreath { from { transform: translateY(0); } to { transform: translateY(-1.5px); } }
/* greeting the flowers: a slow nod, her hand drifts toward the vase and back, a few hearts float up */
.nod { transform-box: view-box; transform-origin: 156px 140px; animation: nod 6s ease-in-out infinite; }
@keyframes nod { 0%, 100% { transform: rotate(0deg); } 18% { transform: rotate(4deg); } 34% { transform: rotate(-1deg); } 60% { transform: rotate(2deg); } }
.reach { transform-box: view-box; transform-origin: 176px 164px; animation: reach 6s ease-in-out infinite; }
@keyframes reach { 0%, 100% { transform: rotate(-4deg); } 22% { transform: rotate(7deg); } 40% { transform: rotate(3deg); } 62% { transform: rotate(-4deg); } }
.ack path { opacity: 0; transform-box: fill-box; transform-origin: 50% 100%; animation: heart 6s ease-in infinite; }
.ack .h2 { animation-delay: 1.4s; }
@keyframes heart { 0%, 20% { opacity: 0; transform: translateY(0) scale(.4); } 32% { opacity: .9; } 60% { opacity: .6; transform: translateY(-34px) scale(1); } 80%, 100% { opacity: 0; transform: translateY(-58px) scale(1.1); } }
@media (prefers-reduced-motion: reduce) { .sit2, .nod, .reach, .ack path { animation: none; } }

.mus-mute { position: absolute; top: 14px; right: 14px; z-index: 4; color: #f1dcb4; background: rgba(18,10,16,.6); border-color: rgba(232,201,143,.4); }

/* book photo pages: the picture only, filling the page */
.bleaf:not(.cover):not(.last) .pg:not(.tog) { padding: 12px; }
.bleaf:not(.cover):not(.last) .pimg { border-radius: 2px; }

/* ============ intro door ============ */
.intro { position: relative; height: 100%; display: grid; place-items: center; cursor: pointer; overflow: hidden; outline: none;
  background: radial-gradient(70% 60% at 50% 56%, #1d101b, #07040a); }
.door { position: relative; width: min(46vw, 250px); aspect-ratio: 3 / 5; max-height: 62vh; overflow: hidden; border: 3px solid #2f2229; border-radius: 50% 50% 4px 4px / 26% 26% 4px 4px;
  background: #060309; box-shadow: 0 0 70px rgba(255,214,150,.1), inset 0 0 20px rgba(0,0,0,.8); animation: doorbreath 5s ease-in-out infinite alternate; }
@keyframes doorbreath { to { box-shadow: 0 0 90px rgba(255,214,150,.2), inset 0 0 20px rgba(0,0,0,.8); } }
.dglow { position: absolute; inset: 0; background: linear-gradient(#ffe7bb, #ffcf86 60%, #e6a459); }
.dl, .dr { position: absolute; top: 0; bottom: 0; width: 50.5%; transition: transform 1.4s cubic-bezier(.6,.05,.2,1);
  background: linear-gradient(90deg, #3b2434, #2a1822), repeating-linear-gradient(to bottom, transparent 0 46%, rgba(0,0,0,.25) 46% 47%); }
.dl { left: 0; border-right: 1px solid #120a10; }
.dr { right: 0; }
.dl::after, .dr::after { content: ''; position: absolute; top: 52%; width: 9px; height: 9px; border-radius: 50%; background: #c9a064; box-shadow: 0 0 6px rgba(201,160,100,.5); }
.dl::after { right: 10px; } .dr::after { left: 10px; }
.intro.open .dl { transform: translateX(-104%); }
.intro.open .dr { transform: translateX(104%); }
.itap { position: absolute; bottom: 13%; left: 0; right: 0; text-align: center; font-size: .78rem; letter-spacing: .36em; text-transform: uppercase; color: #d9c7a6; opacity: .75; animation: nudge2 3.2s ease-in-out infinite; }
.intro.open .itap { opacity: 0; transition: opacity .5s; animation: none; }
.intro::after { content: ''; position: absolute; inset: 0; background: #fff1d2; opacity: 0; pointer-events: none; transition: opacity .8s .75s; }
.intro.open::after { opacity: .97; }
.flood { position: fixed; inset: 0; z-index: 90; background: #fff1d2; opacity: 1; pointer-events: none; transition: opacity 2s ease; }
.flood.go { opacity: 0; }

/* flashlight */
.torch { position: absolute; inset: 0; z-index: 3; pointer-events: none;
  background: radial-gradient(circle at var(--tx, 50%) var(--ty, 45%), transparent 0, transparent 13vmax, rgba(3,1,5,.5) 40vmax); }

/* date plaque on the wall */
.mdate { position: absolute; left: 50%; top: 22%; transform: translateX(-50%); padding: 9px 16px; text-align: center; border-radius: 2px; color: #2a1f10;
  background: linear-gradient(#c3a56d, #8f7440); box-shadow: 0 6px 10px rgba(0,0,0,.55), inset 0 1px 0 rgba(255,255,255,.3); }
.mdate span { display: block; font-size: .62rem; letter-spacing: .3em; text-transform: uppercase; opacity: .75; }
.mdate b { display: block; font-weight: 700; font-size: 1rem; letter-spacing: .06em; margin-top: 2px; }

/* falling petals */
.petal-fall { position: absolute; z-index: 2; border-radius: 150% 0 150% 0; pointer-events: none; opacity: 0; filter: drop-shadow(0 2px 3px rgba(0,0,0,.4)); }

/* end page of the book */
.endp { justify-content: space-between; }
.endmid { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; text-align: center; }
.endmid h3 { font-weight: 700; font-size: 1.7rem; }
.enote { font-weight: 500; font-size: .95rem; line-height: 1.6; max-width: 90%; }
.edate { font-size: .8rem; letter-spacing: .22em; text-transform: uppercase; opacity: .65; }
.endmid .lsign { margin-top: 4px; }
@media (prefers-reduced-motion: reduce) { .door, .itap, .petal-fall { animation: none; } }

/* ============ FLOWER SECTION (bouquet list): simple, dark, calm ============ */
.hm { position: relative; min-height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: clamp(8px, 2vh, 20px); padding: 60px 0 24px; text-align: center; }
.hm-top { padding: 0 20px; animation: fadeup 1s .1s both; }
.hm-eyebrow { font-size: .7rem; letter-spacing: .34em; text-transform: uppercase; color: #c9a064; opacity: .9; }
.hm-title { font-family: var(--ui); font-weight: 600; font-size: clamp(1.7rem, 4.4vw, 2.4rem); letter-spacing: .02em; color: #f6ead2; margin: 6px 0 2px; }
.hm-sub { font-size: .9rem; color: #cdbfc4; opacity: .8; }
.hm-back { position: absolute; top: max(14px, env(safe-area-inset-top)); left: 14px; z-index: 4; color: #f1dcb4; background: rgba(18,10,16,.5); border-color: rgba(232,201,143,.3); }

.hm-wrap { position: relative; width: 100%; }
.hm-carousel { --cw: min(68vw, 250px); display: flex; gap: 16px; overflow-x: auto; padding: 14px calc(50vw - var(--cw) / 2) 30px;
  scroll-snap-type: x mandatory; scrollbar-width: none; cursor: grab; }
.hm-carousel::-webkit-scrollbar { display: none; }
.hm-carousel.dragging { scroll-snap-type: none; cursor: grabbing; }
.hm-card { flex: 0 0 var(--cw); height: clamp(270px, 48vh, 370px); scroll-snap-align: center; position: relative; overflow: hidden;
  border-radius: 20px; padding: 16px 14px 20px; display: flex; flex-direction: column; align-items: center; justify-content: flex-end;
  background: linear-gradient(180deg, rgba(255,255,255,.055), rgba(255,255,255,.015)); border: 1px solid rgba(232,201,143,.16);
  opacity: .42; transform: scale(.92); user-select: none; -webkit-user-drag: none;
  transition: transform .5s cubic-bezier(.2,.9,.3,1), opacity .5s, border-color .5s, box-shadow .5s;
  animation: hmin .9s calc(.25s + var(--i) * .1s) both; }
@keyframes hmin { from { translate: 0 18px; opacity: 0; } }
.hm-card::before { content: ''; position: absolute; inset: 0; background: radial-gradient(circle at 50% 36%, var(--c), transparent 62%); opacity: .16; transition: opacity .5s; }
.hm-card.active { opacity: 1; transform: none; border-color: rgba(232,201,143,.5); box-shadow: 0 14px 28px -22px var(--c); }
.hm-card.active::before { opacity: .26; }
.hm-card svg { position: absolute; top: 7%; left: 10%; width: 80%; height: 58%; overflow: visible; }
.hm-card .flw { animation: bob 6s ease-in-out infinite; }
.hm-name { position: relative; font-weight: 600; font-size: 1.25rem; color: #f6ead2; }
.hm-sub2 { position: relative; margin-top: 4px; font-size: .7rem; letter-spacing: .22em; text-transform: uppercase; color: #c9a064; }
.hm-open { position: relative; margin-top: 14px; font-size: .78rem; letter-spacing: .08em; padding: 6px 18px; border: 1px solid rgba(232,201,143,.45); border-radius: 999px; color: #f1dcb4; opacity: 0; transition: opacity .4s; }
.hm-card.active .hm-open { opacity: 1; }
.hm-card.active:hover { transform: translateY(-3px); }

.hm .arrow { color: #f1dcb4; background: rgba(18,10,16,.5); border-color: rgba(232,201,143,.3); }
.hm-dots { display: flex; gap: 8px; justify-content: center; align-items: center; }
.hm-dot { width: 8px; height: 8px; padding: 0; border-radius: 999px; background: rgba(255,255,255,.25); transition: width .4s, background .4s; }
.hm-dot.active { width: 22px; background: #e8c98f; }
.hm-hint { font-size: .72rem; letter-spacing: .2em; text-transform: uppercase; color: #d9c7a6; opacity: .55; animation: fadeup 1s 1s both; }

/* long letter: soft fade at the bottom + a scroll hint */
.ltxt { padding-bottom: 22px; -webkit-mask-image: linear-gradient(to bottom, #000 82%, transparent); mask-image: linear-gradient(to bottom, #000 82%, transparent); }
.lt-scroll { font-size: .68rem; letter-spacing: .2em; text-transform: uppercase; text-align: center; opacity: .5; margin: -4px 0 0; transition: opacity .4s; animation: nudge2 2.4s ease-in-out infinite; }
.lt-scroll.gone { opacity: 0; animation: none; height: 0; margin: 0; overflow: hidden; }

/* bigger book: keep the stack a little above the capybaras on the floor */
.book-wrap { padding-bottom: 56px; }

/* ============ SECRET BOUQUET ============ */
/* the bouquet is put together in front of her: each stem + flower drops into the wrap one after another */
.drop { opacity: 0; transform-origin: 200px 440px; animation: dropin 1.3s cubic-bezier(.25,.9,.3,1.12) forwards; animation-delay: var(--dd); }
/* the flowers pop out from the left and right edges (--sx = -1 left / 1 right) and swing into place */
@keyframes dropin {
  0% { opacity: 0; transform: translate(calc(var(--sx) * 600px), var(--sy)) rotate(calc(var(--sx) * 45deg)) scale(.35); }
  14% { opacity: 1; }
  72% { opacity: 1; transform: translate(calc(var(--sx) * -16px), 0) rotate(calc(var(--sx) * -7deg)) scale(1.06); }
  100% { opacity: 1; transform: none; }
}
/* a flower arrives as a tight bud, then opens once it has landed */
.asm .petal { transform: scale(.3); opacity: 1; animation: budopen 1.5s cubic-bezier(.2,1.15,.3,1) forwards; animation-delay: calc(var(--base) + var(--pd)); }
@keyframes budopen { to { transform: scale(1); } }
.asm .spin { animation-name: spinin2; }
@keyframes spinin2 { from { transform: rotate(-40deg) scale(.8); } to { transform: none; } }
/* Thumbelina and her wings */
.thumb { transform-box: fill-box; transform-origin: 50% 100%; animation: thumbbob 3.6s ease-in-out infinite; }
@keyframes thumbbob { 50% { transform: translateY(-2.5px) rotate(1.2deg); } }
.wing { transform-box: view-box; animation: flutter .55s ease-in-out infinite alternate; }
@keyframes flutter { from { transform: scaleX(1); } to { transform: scaleX(.8); } }
/* slowly turning rays of light behind the finished bouquet */
.rays { position: absolute; inset: -22%; border-radius: 50%; pointer-events: none; opacity: 0; transition: opacity 3s ease;
  background: repeating-conic-gradient(rgba(255,226,170,.2) 0 5deg, transparent 5deg 15deg);
  -webkit-mask-image: radial-gradient(circle, #000 0, transparent 66%); mask-image: radial-gradient(circle, #000 0, transparent 66%);
  animation: spinrays 50s linear infinite; }
.bouquet-wrap.done .rays { opacity: 1; }
.bouquet-wrap.done .halo { opacity: .6; }
@keyframes spinrays { to { transform: rotate(360deg); } }
.ripple { position: fixed; z-index: 80; width: 22px; height: 22px; margin: -11px 0 0 -11px; border-radius: 50%; border: 2px solid var(--rc, #fff); box-shadow: 0 0 18px var(--rc, #fff); pointer-events: none; }

/* its card on the bouquet list: a dark shape with a lock until she has opened the other five */
.hm-card.locked { border-style: dashed; }
.hm-card.locked svg:not(.lockico) { filter: brightness(0) opacity(.3); }
.hm-card .lockico { position: absolute; left: 50%; top: 36%; width: 52px; height: 52px; z-index: 2; transform: translate(-50%, -50%); color: #e8c98f; filter: drop-shadow(0 0 12px rgba(232,201,143,.55)); animation: lockfloat 3.4s ease-in-out infinite; }
.hm-card:not(.locked) .lockico { display: none; }
@keyframes lockfloat { 50% { transform: translate(-50%, -54%); } }
.hm-card.shake { animation: shake .5s; }
@keyframes shake { 20%, 60% { translate: -8px 0; } 40%, 80% { translate: 8px 0; } }
.hm-card.unlocking svg:not(.lockico) { animation: unsil 2s ease forwards; }
@keyframes unsil { from { filter: brightness(0) opacity(.3); } to { filter: none; } }
.hm-card.unlocking .lockico { animation: lockpop 1.2s ease forwards; }
@keyframes lockpop {
  0% { transform: translate(-50%, -50%) rotate(0); }
  18% { transform: translate(-50%, -50%) rotate(-14deg); }
  36% { transform: translate(-50%, -50%) rotate(12deg); }
  55% { transform: translate(-50%, -50%) scale(1.25); opacity: 1; }
  100% { transform: translate(-50%, -70%) scale(2.4); opacity: 0; }
}
.hm-card.unlocking::after { content: ''; position: absolute; inset: 0; pointer-events: none; background: radial-gradient(circle at 50% 36%, #fff3cf, transparent 60%); animation: flash 1.6s ease-out forwards; }
@keyframes flash { 0% { opacity: 0; } 25% { opacity: .95; } 100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .thumb, .wing, .rays, .hm-card .lockico { animation: none; } }

/* ============ REVEAL (secret bouquet): dark backdrop, SweetAlert-style yes/no cards, flood of light ============ */
.reveal { position: fixed; inset: 0; z-index: 95; display: grid; place-items: center; overflow: hidden; padding: 20px;
  background: radial-gradient(120% 90% at 50% 50%, #1d1030, #05020a 72%); opacity: 0; transition: opacity 1.2s ease; }
.reveal.on { opacity: 1; }
.rv-halo { position: absolute; left: 50%; top: 50%; width: 80vmin; height: 80vmin; transform: translate(-50%, -50%); border-radius: 50%;
  background: radial-gradient(circle, var(--rg, #ffd9a0), transparent 65%); opacity: .22; filter: blur(30px); animation: rvbreathe 3.6s ease-in-out infinite; }
@keyframes rvbreathe { 50% { opacity: .42; transform: translate(-50%, -50%) scale(1.12); } }
.rv-pop { position: relative; width: min(100%, 330px); padding: 28px 22px 24px; text-align: center; border-radius: 26px;
  background: linear-gradient(165deg, rgba(58,24,50,.92), rgba(26,10,28,.95)); border: 1px solid rgba(255,205,222,.28);
  box-shadow: 0 24px 70px rgba(0,0,0,.55), 0 0 60px color-mix(in srgb, var(--rg, #ffd9a0) 26%, transparent), inset 0 1px 0 rgba(255,235,242,.12);
  opacity: 0; transform: scale(.82) translateY(16px); transition: opacity .5s ease, transform .6s cubic-bezier(.2,1.2,.4,1); }
.rv-pop.in { opacity: 1; transform: none; }
.rv-bud svg { width: 74px; height: 74px; display: block; margin: 0 auto 4px; filter: drop-shadow(0 0 14px var(--rg, #ffd9a0)); animation: rvpulse 3s ease-in-out infinite; }
@keyframes rvpulse { 50% { transform: scale(1.07); } }
.rv-pop h3 { margin: 2px 0 20px; font-family: var(--ui); font-weight: 700; font-size: 1.4rem; line-height: 1.35; letter-spacing: .005em; color: #fff1f6; }
.rv-pop h3:last-child { margin-bottom: 6px; }
.rv-acts { display: flex; gap: 12px; justify-content: center; }
.rv-acts button { min-width: 104px; padding: 11px 22px; border-radius: 999px; font-family: var(--ui); font-weight: 600; font-size: .98rem; letter-spacing: .06em; transition: transform .2s, box-shadow .2s; }
.rv-acts button:active { transform: scale(.94); }
.rv-yes { color: #3a1228; background: linear-gradient(135deg, #ffe3ec, #ffa9c8); box-shadow: 0 6px 20px rgba(255,160,200,.38); }
.rv-no { color: #f6dce8; background: transparent; border: 1px solid rgba(255,205,222,.38) !important; }
.rv-flash { position: absolute; inset: -20%; opacity: 0; transform: scale(.2); pointer-events: none;
  background: radial-gradient(circle, #fffaf0 0%, #ffe3b0 35%, rgba(255,217,160,0) 70%); transition: opacity 1.1s ease, transform 1.6s cubic-bezier(.2,.7,.3,1); }
.reveal.flash .rv-flash { opacity: 1; transform: scale(2.4); }
.reveal.out { opacity: 0; transition: opacity 2.4s ease; pointer-events: none; }
@media (prefers-reduced-motion: reduce) { .rv-halo, .rv-bud svg { animation: none; } }

/* narrow phones: a long tag ("The Secret Bouquet") gets its own centered row instead of being squeezed between the buttons */
@media (max-width: 480px) {
  .topbar { flex-wrap: wrap; row-gap: 2px; }
  .topbar .tag { order: 3; width: 100%; text-align: center; font-size: 1.5rem; line-height: 1.1; white-space: nowrap; }
}

/* museum ceiling: night sky with the Aries constellation */
.ceil3 .sky { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.sk-s { fill: #fff6e6; opacity: .8; animation: sktw var(--d) ease-in-out infinite; animation-delay: var(--l); }
@keyframes sktw { 0%, 100% { opacity: .2; } 50% { opacity: 1; } }
.sk-ring { fill: none; stroke: rgba(255,214,235,.14); stroke-width: 1.5; stroke-dasharray: 3 9; }
.sk-line { fill: none; stroke: rgba(255,226,196,.75); stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; filter: drop-shadow(0 0 5px rgba(255,214,170,.7)); }
.sk-star { fill: #fffaf0; filter: drop-shadow(0 0 8px #ffe3b0); }
.sk-halo { fill: rgba(255,214,170,.14); }
.sk-glyph { font-family: 'Segoe UI Symbol', 'Noto Sans Symbols', serif; font-size: 86px; text-anchor: middle; fill: rgba(255,226,196,.9); filter: drop-shadow(0 0 10px rgba(255,200,150,.6)); }
.sk-name { font-family: var(--script); font-size: 72px; text-anchor: middle; fill: #ffe9f0; filter: drop-shadow(0 0 10px rgba(255,170,205,.5)); }
.sk-date { font-family: var(--ui); font-size: 34px; letter-spacing: 9px; text-anchor: middle; fill: rgba(255,226,196,.85); }

/* ---- sky: constellation draws itself, stars light up one by one ---- */
.sk-line { stroke-dasharray: 1; stroke-dashoffset: 1; }
.ceil3.drawn .sk-line { stroke-dashoffset: 0; transition: stroke-dashoffset 5s ease-in-out .4s; }
.sk-pt { opacity: .25; }
.ceil3.drawn .sk-pt { opacity: 1; transition: opacity 1.4s ease calc(var(--i) * 1.2s); }

/* ---- shooting star (tap to wish) + toasts ---- */
.shoot { position: absolute; left: 0; top: 0; width: 88px; height: 88px; margin: -44px 0 0 -44px; z-index: 4; background: none; border: 0; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.shoot::before { content: ''; position: absolute; left: 50%; top: 50%; width: 170px; height: 3px; transform-origin: 0 50%; transform: rotate(calc(var(--ang, 25deg) + 180deg)); border-radius: 3px;
  background: linear-gradient(90deg, rgba(255,255,255,.95), rgba(255,226,196,.35) 45%, transparent); filter: drop-shadow(0 0 6px #fff); }
.shoot::after { content: ''; position: absolute; left: 50%; top: 50%; width: 10px; height: 10px; margin: -5px 0 0 -5px; border-radius: 50%; background: #fff; box-shadow: 0 0 14px 6px rgba(255,236,200,.85); }
.mtoast { position: absolute; left: 50%; top: 24%; z-index: 5; max-width: 82vw; transform: translateX(-50%); text-align: center; pointer-events: none;
  font-family: var(--script); font-size: 1.9rem; line-height: 1.2; color: #fff1f6; text-shadow: 0 0 18px rgba(255,170,205,.55); animation: toastin .7s ease both; transition: opacity 1.1s; }
.mtoast.big { font-size: 2.6rem; top: 34%; }
.mtoast.out { opacity: 0; }
@keyframes toastin { from { opacity: 0; transform: translate(-50%, 10px); } to { opacity: 1; transform: translate(-50%, 0); } }

/* ---- fireflies ---- */
.dust b.ff { background: #ffe08a; box-shadow: 0 0 12px 4px rgba(255,214,120,.6); animation: ffly var(--dur) ease-in-out var(--dl) infinite; }
@keyframes ffly {
  0% { opacity: 0; transform: translate(0, 0); } 15% { opacity: .95; } 35% { opacity: .25; }
  55% { opacity: 1; transform: translate(var(--dx), -40px); } 80% { opacity: .3; } 100% { opacity: 0; transform: translate(calc(var(--dx) * -.6), -90px); }
}

/* ---- the two figures can be tapped ---- */
.viewers, .sitter { pointer-events: auto; cursor: pointer; }

/* ---- the last moment of the secret bouquet ---- */
.lookup { position: fixed; inset: 0; z-index: 40; display: grid; place-items: center; padding: 24px; cursor: pointer; opacity: 0; transition: opacity 2.6s ease;
  background: radial-gradient(90% 70% at 50% 50%, rgba(10,4,16,.55), rgba(6,2,10,.88)); }
.lookup.on { opacity: 1; }
.lookup p { font-family: var(--script); font-size: clamp(2.8rem, 13vw, 4.4rem); text-align: center; color: #fff1f6; text-shadow: 0 0 28px rgba(255,170,205,.7), 0 0 60px rgba(255,214,170,.4);
  animation: lookbreath 3.4s ease-in-out infinite; }
@keyframes lookbreath { 50% { transform: scale(1.04); opacity: .88; } }
@media (prefers-reduced-motion: reduce) { .lookup p, .dust b.ff { animation: none; } }

/* ---- the last page can wear the photo as its background ---- */
.bq.has-photo { position: relative; isolation: isolate; }
.bq.has-photo::before { content: ''; position: fixed; inset: 0; z-index: -1; background: linear-gradient(rgba(20,8,26,.58), rgba(20,8,26,.82)), var(--photo) center / cover no-repeat; filter: blur(1.5px); transform: scale(1.03); animation: musin 2s ease both; }

/* ---- camera ---- */
.cam { position: fixed; inset: 0; z-index: 97; background: #000; display: grid; place-items: center; overflow: hidden; animation: musin .5s ease both; transition: opacity .6s; }
.cam.out { opacity: 0; pointer-events: none; }
.cam video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.cam video.mirror { transform: scaleX(-1); }
.cam-frame { position: absolute; inset: 14px; border-radius: 26px; border: 2px solid rgba(255,214,230,.55); box-shadow: 0 0 0 100vmax rgba(10,4,16,.18) inset, 0 0 40px rgba(255,170,205,.3) inset; pointer-events: none; }
.cam-count { position: absolute; inset: 0; display: grid; place-items: center; margin: 0; font-family: var(--script); font-size: 9rem; color: #fff; text-shadow: 0 0 30px rgba(255,170,205,.9); pointer-events: none; }
.cam-count.pop { animation: campop .9s ease both; }
@keyframes campop { from { transform: scale(1.6); opacity: 0; } 25% { opacity: 1; } to { transform: scale(.9); opacity: .15; } }
.cam-bar { position: absolute; left: 0; right: 0; bottom: max(24px, env(safe-area-inset-bottom)); display: flex; align-items: center; justify-content: space-around; padding: 0 24px; }
.cam-x, .cam-flip { width: 52px; height: 52px; border-radius: 50%; font-size: 1.4rem; color: #fff; background: rgba(20,8,26,.55); border: 1px solid rgba(255,255,255,.3); }
.cam-shot { width: 78px; height: 78px; border-radius: 50%; border: 5px solid #fff; background: radial-gradient(circle, #ffd1e0 0 55%, #ff9ec4 100%); box-shadow: 0 0 24px rgba(255,170,205,.6); }
.cam-shot:active { transform: scale(.92); }
.cam.flash::after { content: ''; position: absolute; inset: 0; background: #fff; animation: camflash .35s ease both; }
@keyframes camflash { from { opacity: 1; } to { opacity: 0; } }
.cam-review { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; padding: 18px; background: radial-gradient(120% 90% at 50% 50%, #1d1030, #05020a 72%); }
.cam-review img { max-width: 100%; max-height: 72dvh; border-radius: 6px; box-shadow: 0 20px 60px rgba(0,0,0,.6), 0 0 50px rgba(255,170,205,.25); transform: rotate(-1.2deg); }
.cam-saved { margin: 0; font-family: var(--ui); font-weight: 600; font-size: 1.15rem; color: #fff1f6; text-align: center; }
.cam-acts { display: flex; gap: 12px; }
.cam-acts button { min-width: 120px; padding: 12px 22px; border-radius: 999px; font-weight: 600; letter-spacing: .05em; }
.cam-msg { text-align: center; padding: 24px; color: #fff1f6; }
.cam-msg p { font-family: var(--ui); font-weight: 600; font-size: 1.25rem; margin: 0 0 18px; }
.cam-msg .rv-yes { padding: 11px 30px; border-radius: 999px; font-weight: 600; }

/* =====================================================================
   PHONE PERFORMANCE: blur filters, backdrop blur, animated drop-shadows and many animated SVG nodes are cheap on a PC
   but make phones lag, because each frame has to be repainted. On touch screens / small screens we swap them for flat
   gradients that look almost the same. (Nothing here changes how it works, only how it is painted.)
   ===================================================================== */
@media (pointer: coarse), (max-width: 700px) {
  /* the two big drifting glows behind everything: gradient instead of a 90px blur */
  body::before, body::after { filter: none; opacity: .2; background: radial-gradient(circle, var(--glow) 0, transparent 66%); will-change: transform; }
  .halo { filter: none; }
  .rv-halo { filter: none; }
  .bq-svg { filter: none; }
  .title, .hm-title { filter: none; animation: none; }
  /* backdrop blur makes the browser re-blur everything behind it every frame */
  .ghost, .hm-back, .lb, .fin, .vase-hint, .mus-mute, .to-vase, .back-gal { backdrop-filter: none; -webkit-backdrop-filter: none; }
  .lb { background: rgba(10,4,14,.86); }
  .fin { background: radial-gradient(90% 70% at 50% 40%, rgba(120,40,90,.92), rgba(22,6,22,.97)); }
  /* animated or large drop-shadows */
  .vase-btn { animation: none; filter: none; }
  .fly, .petal-fall, .capy-body, .book, .fin-flower, .lb-flower { filter: none; }
  /* the question cards: a static glow instead of an animated filter */
  .rv-bud svg { filter: none; animation: none; }
  .rv-bud { position: relative; }
  .rv-bud::before { content: ''; position: absolute; left: 50%; top: 50%; width: 120px; height: 120px; transform: translate(-50%, -50%); border-radius: 50%; background: radial-gradient(circle, color-mix(in srgb, var(--rg, #ffd9a0) 55%, transparent), transparent 70%); }
  .rv-bud svg { position: relative; }
  /* night sky: static (190 twinkling circles on a big 3D ceiling repaint it every frame) and no glow filters */
  .sk-s { animation: none; opacity: .85; }
  .sk-line, .sk-star, .sk-glyph, .sk-name { filter: none; }
  .shoot::before, .shoot::after { filter: none; }
  .mtoast { text-shadow: none; }
  .dust b.ff { box-shadow: 0 0 8px 2px rgba(255,214,120,.5); }
}

/* phones: skip the grain texture on every wall (it is a noise filter repainted as an image) */
@media (pointer: coarse), (max-width: 700px) {
  .wp { background: linear-gradient(#2c2229, #221a22 70%, #1c141c); }
  .wp[data-k="0"] { background: radial-gradient(60% 70% at 50% 62%, rgba(255,226,170,.13), transparent 70%), linear-gradient(#2c2229, #221a22 70%, #1c141c); }
}
