/* =========================================================
   A Birthday Surprise — stylesheet
   Mobile-first. Desktop enhancements live in @media (min-width)
   Nothing personal lives here — edit config.js instead.
   ========================================================= */

/* ---------- tokens ---------- */
:root{
  --bg:            #07040d;
  --bg-2:          #100722;
  --ink:           #f6ecff;
  --ink-soft:      #cbb9de;
  --ink-faint:     #8f7fa6;

  --pink:          #ff8fc3;
  --rose:          #ff5f9e;
  --lav:           #c4a7ff;
  --violet:        #8b5cf6;
  --gold:          #ffd9a0;
  --ta-ink:        #dcc9f5;   /* the Tamil layer's own colour */

  --glass:         rgba(255,255,255,.045);
  --glass-line:    rgba(255,255,255,.10);

  --f-display: "Cormorant Garamond", "Iowan Old Style", Georgia, serif;
  --f-body:    "Manrope", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --f-tamil:   "Noto Serif Tamil", "Noto Sans Tamil", "Nirmala UI", "Latha", sans-serif;
  --f-script:  "Great Vibes", cursive;

  --pad: clamp(20px, 6vw, 40px);
  --ease: cubic-bezier(.22,.61,.36,1);
  --ease-soft: cubic-bezier(.4,0,.2,1);
}

*,*::before,*::after{ box-sizing:border-box; }

html{
  -webkit-text-size-adjust:100%;
  scroll-behavior:smooth;
}

body{
  margin:0;
  min-height:100vh;
  min-height:100svh;
  background:
    radial-gradient(120% 80% at 50% -10%, #1a0b30 0%, rgba(26,11,48,0) 60%),
    radial-gradient(90% 60% at 100% 100%, #240f2e 0%, rgba(36,15,46,0) 55%),
    var(--bg);
  color:var(--ink);
  font-family:var(--f-body);
  font-size:16px;
  line-height:1.65;
  overflow-x:hidden;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
  overscroll-behavior-y:none;
}

body.is-locked{ overflow:hidden; height:100vh; height:100svh; }

img{ max-width:100%; display:block; }
button{ font:inherit; color:inherit; background:none; border:0; cursor:pointer; -webkit-tap-highlight-color:transparent; }
::selection{ background:rgba(255,95,158,.35); }

/* ---------- atmosphere layers ---------- */
#atmosphere{
  position:fixed; inset:0;
  width:100%; height:100%;
  z-index:1;
  pointer-events:none;
}

.aurora{ position:fixed; inset:0; z-index:0; pointer-events:none; overflow:hidden; }
.aurora__blob{
  position:absolute; display:block;
  border-radius:50%;
  filter:blur(60px);
  opacity:.42;
  will-change:transform;
}
.aurora__blob--a{
  width:70vw; height:70vw; max-width:520px; max-height:520px;
  left:-18vw; top:-10vh;
  background:radial-gradient(circle, rgba(255,95,158,.55), rgba(255,95,158,0) 70%);
  animation:drift-a 26s var(--ease-soft) infinite alternate;
}
.aurora__blob--b{
  width:80vw; height:80vw; max-width:600px; max-height:600px;
  right:-24vw; top:28vh;
  background:radial-gradient(circle, rgba(139,92,246,.5), rgba(139,92,246,0) 70%);
  animation:drift-b 32s var(--ease-soft) infinite alternate;
}
.aurora__blob--c{
  width:60vw; height:60vw; max-width:460px; max-height:460px;
  left:10vw; bottom:-16vh;
  background:radial-gradient(circle, rgba(196,167,255,.4), rgba(196,167,255,0) 70%);
  animation:drift-c 38s var(--ease-soft) infinite alternate;
}
@keyframes drift-a{ to{ transform:translate3d(8vw,6vh,0) scale(1.15); } }
@keyframes drift-b{ to{ transform:translate3d(-10vw,-8vh,0) scale(1.1); } }
@keyframes drift-c{ to{ transform:translate3d(6vw,-10vh,0) scale(1.2); } }

.vignette{
  position:fixed; inset:0; z-index:2; pointer-events:none;
  background:radial-gradient(120% 90% at 50% 45%, rgba(0,0,0,0) 35%, rgba(3,1,7,.72) 100%);
}

/* =========================================================
   STAGE 1 — opening / balloons
   ========================================================= */
.gate{
  position:fixed; inset:0; z-index:20;
  display:flex; align-items:center; justify-content:center;
  padding:calc(var(--pad) + env(safe-area-inset-top)) var(--pad)
          calc(var(--pad) + env(safe-area-inset-bottom));
  transition:opacity .9s var(--ease), transform 1.1s var(--ease);
}
.gate.is-gone{ opacity:0; transform:scale(1.06); pointer-events:none; }

.gate__inner{
  width:100%; max-width:560px; height:100%;
  display:flex; flex-direction:column; align-items:center; justify-content:space-between;
  gap:16px;
}

.gate__eyebrow{
  margin:clamp(8px,4vh,32px) 0 0;
  font-family:var(--f-display);
  font-size:clamp(21px,5.6vw,30px);
  font-weight:300; font-style:italic;
  line-height:1.45;
  letter-spacing:.01em;
  text-align:center;
  color:var(--ink);
  text-shadow:0 0 32px rgba(255,143,195,.35);
  opacity:0;
  animation:fade-up 1.4s var(--ease) .3s forwards;
  max-width:19ch;
}

.gate__hint{
  margin:0 0 clamp(6px,3vh,26px);
  font-size:14px; letter-spacing:.16em; text-transform:uppercase;
  color:var(--ink-faint);
  opacity:0;
  animation:fade-up 1.4s var(--ease) 1.5s forwards;
}
.gate__hint span{ display:inline-block; animation:breathe 2.8s ease-in-out infinite; }

.balloons{
  position:relative;
  flex:1 1 auto;
  width:100%;
  min-height:0;
}

.balloon{
  position:absolute;
  width:var(--w);
  left:var(--x); top:var(--y);
  transform:translate3d(-50%,-50%,0);
  border:0; padding:0; background:none;
  will-change:transform;
  animation:bob var(--dur) ease-in-out var(--delay) infinite alternate;
  transition:filter .25s var(--ease);
  touch-action:manipulation;
}
.balloon svg{ width:100%; height:auto; overflow:visible; display:block;
  filter:drop-shadow(0 10px 26px rgba(255,95,158,.28)); }
.balloon::after{ /* enlarged touch target */
  content:""; position:absolute; inset:-14px -14px -30px; border-radius:40%;
}
.balloon:active{ filter:brightness(1.25); }

@keyframes bob{
  0%   { transform:translate3d(-50%,-50%,0) rotate(-2.5deg); }
  100% { transform:translate3d(-50%,calc(-50% - 22px),0) rotate(2.5deg); }
}

.balloon.is-popping{ animation:pop .42s var(--ease) forwards; }
@keyframes pop{
  0%   { transform:translate3d(-50%,-50%,0) scale(1); opacity:1; }
  38%  { transform:translate3d(-50%,-50%,0) scale(1.28); opacity:1; }
  100% { transform:translate3d(-50%,-50%,0) scale(.35); opacity:0; }
}

.balloon.is-flyaway{ animation:flyaway 1.6s var(--ease) forwards; }
@keyframes flyaway{
  0%   { transform:translate3d(-50%,-50%,0) rotate(0); opacity:1; }
  100% { transform:translate3d(-50%,-160vh,0) rotate(14deg); opacity:0; }
}

/* =========================================================
   STAGE 2 — the story
   ========================================================= */
.story{
  position:relative; z-index:3;
  opacity:0;
  transition:opacity 1.1s var(--ease);
}
.story.is-live{ opacity:1; }

.panel{
  position:relative;
  min-height:100vh;
  min-height:100svh;
  display:flex; flex-direction:column;
  align-items:center; justify-content:center;
  padding:clamp(72px,14vh,120px) var(--pad) clamp(96px,15vh,140px);
  padding-bottom:calc(clamp(96px,15vh,140px) + env(safe-area-inset-bottom));
}
.panel__body{ width:100%; max-width:640px; }
.panel--center .panel__body{ text-align:center; }
.panel--final{ min-height:100vh; min-height:100svh; }

/* scroll-in animation */
.reveal-item{
  opacity:0;
  transform:translate3d(0,26px,0);
  transition:opacity .95s var(--ease), transform .95s var(--ease);
  transition-delay:calc(var(--d,0) * 140ms);
  will-change:opacity, transform;
}
.is-shown .reveal-item, .reveal-item.is-shown{ opacity:1; transform:none; }

/* --- continue cue --- */
.cue{
  position:absolute;
  bottom:calc(22px + env(safe-area-inset-bottom));
  left:50%; transform:translateX(-50%);
  display:flex; flex-direction:column; align-items:center; gap:8px;
  padding:14px 22px;
  border-radius:999px;
  font-size:11.5px; letter-spacing:.2em; text-transform:uppercase;
  white-space:nowrap;
  color:var(--ink-faint);
  opacity:0; transition:opacity .8s var(--ease) .6s, color .3s;
  min-height:56px;
}
.is-shown .cue{ opacity:1; }
.cue:active{ color:var(--pink); }
.cue__chev{
  width:9px; height:9px; display:block;
  border-right:1.4px solid currentColor; border-bottom:1.4px solid currentColor;
  transform:rotate(45deg);
  animation:nudge 2.2s ease-in-out infinite;
}
@keyframes nudge{
  0%,100%{ transform:rotate(45deg) translate(0,0); opacity:.55; }
  50%    { transform:rotate(45deg) translate(3px,3px); opacity:1; }
}

/* --- shared type --- */
.eyebrow{
  margin:0 0 14px;
  font-family:var(--f-body);
  font-size:11.5px; font-weight:500;
  letter-spacing:.28em; text-transform:uppercase;
  color:var(--pink);
  opacity:.9;
}
.lead{
  margin:0 0 clamp(28px,6vh,48px);
  font-family:var(--f-display);
  font-size:clamp(20px,5.4vw,26px);
  font-weight:300; font-style:italic; line-height:1.5;
  color:var(--ink-soft);
  white-space:pre-line;
}
.lead--sm{ font-size:clamp(16px,4.2vw,19px); margin-bottom:clamp(18px,3vh,30px); }

/* ❤ and ∞ inside headings pick up the palette */
.hx{ color:var(--rose); -webkit-text-fill-color:var(--rose); }
.ix{ color:var(--lav); -webkit-text-fill-color:var(--lav); }

/* --- 1. birthday reveal --- */
#sec-reveal .panel__body{ position:relative; }
.reveal-halo{
  position:absolute; left:50%; top:38%;
  width:min(88vw,460px); aspect-ratio:1;
  transform:translate(-50%,-50%);
  background:radial-gradient(circle, rgba(255,143,195,.30), rgba(255,143,195,0) 62%);
  filter:blur(18px);
  opacity:0;
  animation:halo 6s ease-in-out infinite;
  animation-play-state:paused;
  pointer-events:none;
}
.is-shown .reveal-halo{ animation-play-state:running; }
@keyframes halo{
  0%,100%{ opacity:.5; transform:translate(-50%,-50%) scale(1); }
  50%    { opacity:.85; transform:translate(-50%,-50%) scale(1.12); }
}

.bday{
  position:relative;
  margin:0 0 clamp(20px,4vh,30px);
  font-family:var(--f-display);
  font-weight:400;
  line-height:1.08;
  letter-spacing:-.005em;
}
.bday span{ display:block; }
.bday__l1{
  font-size:clamp(34px,10.5vw,58px);
  font-style:italic; font-weight:300;
  color:var(--ink-soft);
}
.bday__l2{
  font-size:clamp(42px,13.5vw,76px);
  background:linear-gradient(105deg,#fff 0%,var(--pink) 34%,var(--lav) 68%,#fff 100%);
  background-size:220% 100%;
  -webkit-background-clip:text; background-clip:text;
  color:transparent;
  -webkit-text-fill-color:transparent;
  animation:sheen 9s ease-in-out infinite;
  filter:drop-shadow(0 0 26px rgba(255,95,158,.28));
}
.bday__l2 em{
  font-style:normal;
  -webkit-text-fill-color:var(--rose);
  color:var(--rose);
  font-size:.72em;
  display:inline-block;
  animation:beat 2.6s ease-in-out infinite;
}
@keyframes sheen{ 0%,100%{ background-position:0% 50%; } 50%{ background-position:100% 50%; } }
@keyframes beat{
  0%,100%{ transform:scale(1); } 12%{ transform:scale(1.16); } 24%{ transform:scale(1); }
  36%{ transform:scale(1.1); } 48%{ transform:scale(1); }
}

.bday__msg{
  margin:0 auto;
  max-width:26ch;
  font-family:var(--f-display);
  font-size:clamp(18px,4.9vw,23px);
  font-weight:300; font-style:italic;
  line-height:1.62;
  color:var(--ink-soft);
  white-space:pre-line;
}

/* --- 2. memories --- */
#sec-memories .panel__body{ text-align:center; }
.gallery{ display:flex; flex-direction:column; gap:clamp(34px,7vh,58px); }

.frame{
  position:relative;
  opacity:0;
  transform:translate3d(0,34px,0) scale(.985);
  transition:opacity 1s var(--ease), transform 1.1s var(--ease);
  will-change:opacity, transform;
}
.frame.is-shown{ opacity:1; transform:none; }

.frame__shot{
  position:relative;
  border-radius:20px;
  overflow:hidden;
  background:linear-gradient(150deg, rgba(255,143,195,.14), rgba(139,92,246,.14));
  border:1px solid var(--glass-line);
  box-shadow:0 18px 46px rgba(0,0,0,.5), 0 0 0 1px rgba(255,255,255,.03) inset;
  aspect-ratio:4/5;
}
.frame__shot img{
  width:100%; height:100%;
  object-fit:cover;
  transform:scale(1.07);          /* JS drives zoom + parallax from here */
  will-change:transform;
  backface-visibility:hidden;
}

/* each memory surfaces slowly instead of just appearing - a different,
   quiet way for each photo. Only filter / opacity / clip-path move here;
   transform stays with the JS zoom + parallax. */
.frame__shot img{
  transition:
    filter 2.4s var(--ease) .25s,
    opacity 1.9s var(--ease) .15s,
    clip-path 2.2s var(--ease) .2s;
}
/* 1 - comes into focus */
.frame:nth-child(5n+1) .frame__shot img{ filter:blur(16px) brightness(.78) saturate(.8); opacity:.5; }
/* 2 - rises out of soft light */
.frame:nth-child(5n+2) .frame__shot img{ filter:brightness(1.55) saturate(.45) blur(6px); opacity:0; }
/* 3 - an old memory warming into colour */
.frame:nth-child(5n+3) .frame__shot img{ filter:sepia(.85) blur(8px) brightness(.9); opacity:.35; }
.frame:nth-child(5n+3).is-shown .frame__shot img{ transition-duration:3s, 2.2s, 2.2s; }
/* 4 - a window gently opening */
.frame:nth-child(5n+4) .frame__shot img{ filter:blur(10px); opacity:0; clip-path:inset(9% 9% 9% 9% round 16px); }
/* 5 - a soft glow widening from the centre */
.frame:nth-child(5n+5) .frame__shot img{ filter:blur(12px) brightness(1.2); opacity:.2; clip-path:circle(22% at 50% 45%); }

.frame.is-shown .frame__shot img{ filter:none; opacity:1; }
.frame:nth-child(5n+4).is-shown .frame__shot img{ clip-path:inset(0 0 0 0 round 0); }
.frame:nth-child(5n+5).is-shown .frame__shot img{ clip-path:circle(80% at 50% 45%); }

@media (prefers-reduced-motion:reduce){
  .frame .frame__shot img{ filter:none !important; clip-path:none !important; }
}

.frame__shot::after{
  content:""; position:absolute; inset:0;
  background:linear-gradient(to top, rgba(7,4,13,.62) 0%, rgba(7,4,13,0) 48%);
  pointer-events:none;
}
.frame__glow{
  position:absolute; inset:-8% -4%;
  border-radius:26px;
  background:radial-gradient(60% 55% at 50% 50%, rgba(255,143,195,.22), rgba(255,143,195,0) 70%);
  filter:blur(20px);
  z-index:-1;
}
.frame__capTa{
  margin:14px 4px 2px;
  font-family:var(--f-tamil);
  font-size:clamp(14.5px,3.9vw,16.5px);
  line-height:1.75;
  color:var(--ta-ink);
  white-space:pre-line;
}
.frame__cap{
  margin:2px 4px 0;
  font-family:var(--f-display);
  font-size:clamp(16px,4.3vw,19px);
  font-style:italic; font-weight:300;
  line-height:1.5;
  color:var(--ink-soft);
}
.frame__no{
  position:absolute; top:12px; left:14px; z-index:2;
  font-size:11px; letter-spacing:.24em;
  color:rgba(255,255,255,.62);
  text-shadow:0 1px 8px rgba(0,0,0,.6);
}

/* placeholder shown when a photo file is missing */
.frame__shot.is-empty{
  display:flex; align-items:center; justify-content:center;
}
.frame__shot.is-empty img{ display:none; }
.ph{
  text-align:center; padding:22px;
  font-size:12px; letter-spacing:.16em; text-transform:uppercase;
  color:rgba(255,255,255,.42);
}
.ph b{ display:block; font-size:34px; margin-bottom:10px; letter-spacing:0; color:rgba(255,143,195,.6); }
.ph code{
  display:block; margin-top:10px;
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace;
  font-size:11px; letter-spacing:0; text-transform:none;
  color:rgba(255,255,255,.55);
}

/* --- 3. unspoken --- */
.whisper{ margin:0 0 clamp(26px,5vh,40px); }
.whisper p{
  margin:0 0 .55em;
  font-family:var(--f-display);
  font-size:clamp(20px,5.6vw,28px);
  font-weight:300; line-height:1.55;
  color:var(--ink);
  opacity:0; transform:translate3d(0,18px,0);
  transition:opacity 1.1s var(--ease), transform 1.1s var(--ease);
  transition-delay:calc(var(--d) * 420ms);
}
.whisper p:nth-child(even){ color:var(--ink-soft); font-style:italic; }
.is-shown .whisper p{ opacity:1; transform:none; }

.bridge{
  margin:0;
  font-size:clamp(14px,3.8vw,16px);
  letter-spacing:.04em;
  color:var(--pink);
  opacity:0; transform:translateY(14px);
  transition:opacity 1s var(--ease) 2.4s, transform 1s var(--ease) 2.4s;
}
.is-shown .bridge{ opacity:.92; transform:none; }

/* --- cards (poem + letter) --- */
.card{
  position:relative;
  border-radius:22px;
  padding:clamp(26px,7vw,44px) clamp(22px,6vw,40px);
  background:
    linear-gradient(160deg, rgba(255,255,255,.075), rgba(255,255,255,.02) 55%),
    rgba(18,9,32,.55);
  border:1px solid var(--glass-line);
  box-shadow:0 22px 60px rgba(0,0,0,.55), 0 0 60px rgba(139,92,246,.10);
  backdrop-filter:blur(10px);
  -webkit-backdrop-filter:blur(10px);
  overflow:hidden;
}
.card::before{
  content:""; position:absolute; inset:0;
  background:radial-gradient(90% 60% at 50% 0%, rgba(255,143,195,.13), rgba(255,143,195,0) 70%);
  pointer-events:none;
}
.card--paper::after{
  content:""; position:absolute; left:0; right:0; top:0; height:1px;
  background:linear-gradient(90deg, transparent, rgba(255,217,160,.55), transparent);
}

.poem__title{
  margin:0 0 clamp(18px,4vh,26px);
  font-family:var(--f-tamil);
  font-size:clamp(19px,5vw,24px);
  font-weight:500;
  line-height:1.7;
  color:var(--gold);
  text-align:center;
  letter-spacing:.01em;
}
.poem{ text-align:center; }
.poem p{
  margin:0 0 .38em;
  font-family:var(--f-tamil);
  font-size:clamp(17px,4.7vw,21px);
  font-weight:400;
  line-height:2.05;
  color:var(--ink);
  opacity:0; transform:translate3d(0,14px,0);
  transition:opacity .9s var(--ease), transform .9s var(--ease);
  transition-delay:calc(var(--d) * 240ms);
}
.poem p.is-gap{ height:.9em; margin:0; }
.is-shown .poem p{ opacity:1; transform:none; }
.poem__sig{
  margin:22px 0 0; text-align:right;
  font-family:var(--f-tamil);
  font-size:clamp(15px,4vw,17px);
  color:var(--ink-faint);
}
.poem__sig:empty{ display:none; }

/* --- letter --- */
.card--letter{ min-height:340px; }
.letter__greet{
  margin:0 0 18px;
  font-family:var(--f-script);
  font-size:clamp(28px,7.4vw,36px);
  line-height:1.2;
  color:var(--pink);
}
.letter__body p{
  margin:0 0 1.05em;
  font-family:var(--f-display);
  font-size:clamp(17px,4.6vw,20px);
  font-weight:300;
  line-height:1.78;
  color:var(--ink-soft);
  min-height:1.78em;
}
.letter__body p:last-child{ margin-bottom:0; }
.caret{
  display:inline-block; width:2px; height:1em;
  margin-left:2px; vertical-align:-.12em;
  background:var(--pink);
  animation:blink 1s steps(2) infinite;
}
@keyframes blink{ 50%{ opacity:0; } }
.letter__sign{
  margin:26px 0 0;
  font-family:var(--f-display); font-style:italic;
  font-size:clamp(16px,4.2vw,18px);
  color:var(--ink-faint);
  opacity:0; transition:opacity .9s var(--ease);
}
.letter__sign.is-shown{ opacity:1; }
.letter__sign b{
  display:block; margin-top:6px;
  font-family:var(--f-script); font-style:normal; font-weight:400;
  font-size:clamp(26px,6.8vw,32px);
  color:var(--pink);
}
.skip{
  position:absolute; right:14px; bottom:12px;
  font-size:10.5px; letter-spacing:.18em; text-transform:uppercase;
  color:var(--ink-faint);
  padding:10px 12px;
}

/* --- song / player --- */
.song-head{
  margin:0 0 12px;
  font-family:var(--f-display);
  font-size:clamp(25px,7vw,40px);
  font-weight:300; font-style:italic;
  line-height:1.28;
  white-space:pre-line;
  color:var(--ink);
  text-shadow:0 0 34px rgba(255,143,195,.22);
}

.player{
  position:relative;
  margin:clamp(4px,1.5vh,16px) auto 0;
  max-width:400px;
  padding:18px 18px 20px;
  border-radius:26px;
  background:linear-gradient(165deg, rgba(255,255,255,.08), rgba(255,255,255,.02));
  border:1px solid var(--glass-line);
  box-shadow:0 24px 64px rgba(0,0,0,.55);
  backdrop-filter:blur(12px);
  -webkit-backdrop-filter:blur(12px);
  text-align:center;
}

/* while the song plays the player breathes inside its own halo */
.player::before{
  content:""; position:absolute; inset:-18px;
  border-radius:38px;
  background:
    radial-gradient(60% 60% at 30% 25%, rgba(120,180,255,.30), rgba(120,180,255,0) 70%),
    radial-gradient(60% 60% at 75% 80%, rgba(255,95,158,.22), rgba(255,95,158,0) 70%);
  filter:blur(14px);
  opacity:0;
  transition:opacity 1.4s var(--ease);
  pointer-events:none;
  z-index:-1;
}
.player.is-playing::before{
  opacity:1;
  animation:playerBreathe 5.2s ease-in-out infinite;
}
@keyframes playerBreathe{
  0%,100%{ transform:scale(1);     opacity:.75; }
  50%    { transform:scale(1.045); opacity:1; }
}

.player__art{
  position:relative;
  width:min(46vw,170px); aspect-ratio:1;
  margin:2px auto 15px;
  border-radius:50%;
  overflow:hidden;
  background:
    radial-gradient(circle at 32% 28%, rgba(255,143,195,.5), rgba(255,143,195,0) 58%),
    conic-gradient(from 210deg, #2a1240, #4b1f5e, #7a2b63, #2a1240);
  box-shadow:0 0 0 1px rgba(255,255,255,.10) inset, 0 16px 40px rgba(0,0,0,.5);
  display:flex; align-items:center; justify-content:center;
}
.player__art img{ width:100%; height:100%; object-fit:cover; }
.art__fallback span{
  font-family:var(--f-display);
  font-size:clamp(52px,16vw,76px);
  color:rgba(255,255,255,.86);
  text-shadow:0 0 34px rgba(255,143,195,.7);
  display:block;
  animation:breathe 4.4s ease-in-out infinite;
}
.art__ring{
  position:absolute; inset:6px;
  border-radius:50%;
  border:1px solid rgba(255,255,255,.14);
  pointer-events:none;
}
.is-playing .player__art{ animation:spin 16s linear infinite; }
.is-playing .art__ring{
  box-shadow:0 0 26px rgba(255,95,158,.45), 0 0 62px rgba(120,180,255,.5);
  border-color:rgba(176,216,255,.35);
}
.is-playing .seek__fill{ background:linear-gradient(90deg,var(--rose),#78b2ff); }
@keyframes spin{ to{ transform:rotate(360deg); } }

.player__meta h3{
  margin:0 0 3px;
  font-family:var(--f-display);
  font-size:clamp(24px,6.4vw,30px);
  font-weight:500; letter-spacing:.005em;
  color:var(--ink);
}
.player__meta p{ margin:0; font-size:13.5px; color:var(--ink-soft); letter-spacing:.03em; }
.player__meta .credit{ margin-top:3px; font-size:11.5px; color:var(--ink-faint); letter-spacing:.1em; }

.eq{ display:flex; gap:4px; justify-content:center; align-items:flex-end; height:16px; margin:11px 0 4px; opacity:.25; transition:opacity .4s; }
.eq i{ width:3px; height:5px; border-radius:2px; background:var(--pink); display:block; }
.is-playing .eq{ opacity:1; }
.is-playing .eq i{ animation:eq .9s ease-in-out infinite; }
.eq i:nth-child(2){ animation-delay:.15s; } .eq i:nth-child(3){ animation-delay:.3s; }
.eq i:nth-child(4){ animation-delay:.45s; } .eq i:nth-child(5){ animation-delay:.6s; }
@keyframes eq{ 0%,100%{ height:5px; } 50%{ height:16px; } }

.player__bar{ margin:6px 0 16px; }
.seek{
  position:relative;
  height:4px; border-radius:99px;
  background:rgba(255,255,255,.13);
  cursor:pointer;
  touch-action:none;
}
.seek::before{ content:""; position:absolute; inset:-16px 0; }  /* fat touch area */
.seek__fill{
  position:absolute; left:0; top:0; bottom:0; width:0;
  border-radius:99px;
  background:linear-gradient(90deg,var(--rose),var(--lav));
  box-shadow:0 0 12px rgba(255,95,158,.6);
}
.seek__knob{
  position:absolute; top:50%; left:0;
  width:12px; height:12px; border-radius:50%;
  transform:translate(-50%,-50%);
  background:#fff;
  box-shadow:0 0 12px rgba(255,143,195,.9);
  opacity:0; transition:opacity .25s;
}
.is-playing .seek__knob, .seek:active .seek__knob{ opacity:1; }
.times{
  display:flex; justify-content:space-between;
  margin-top:9px;
  font-size:11px; letter-spacing:.1em;
  color:var(--ink-faint);
  font-variant-numeric:tabular-nums;
}

.play{
  position:relative;
  width:72px; height:72px; border-radius:50%;
  display:inline-flex; align-items:center; justify-content:center;
  background:linear-gradient(150deg,var(--rose),var(--violet));
  box-shadow:0 12px 34px rgba(255,95,158,.42), 0 0 0 1px rgba(255,255,255,.14) inset;
  transition:transform .22s var(--ease), box-shadow .3s;
  touch-action:manipulation;
}
.play:active{ transform:scale(.93); }
.play .ic{ width:28px; height:28px; fill:#fff; }
.play .ic--pause{ display:none; }
.is-playing .play .ic--play{ display:none; }
.is-playing .play .ic--pause{ display:block; }
.is-playing .play{ box-shadow:0 12px 40px rgba(255,95,158,.6), 0 0 0 1px rgba(255,255,255,.2) inset; }
.play::after{
  content:""; position:absolute; inset:0; border-radius:50%;
  border:1px solid rgba(255,143,195,.5);
  opacity:0; pointer-events:none;
}
.is-playing .play::after{ animation:ripple 2.4s ease-out infinite; }
@keyframes ripple{ 0%{ transform:scale(1); opacity:.7; } 100%{ transform:scale(1.85); opacity:0; } }

.player__err{
  margin:14px 0 0; font-size:12px; line-height:1.6; color:var(--ink-faint);
}
.player__err code{ color:var(--pink); font-size:11.5px; }

/* --- finale --- */
.final p{
  margin:0 auto .5em;
  max-width:21ch;
  font-family:var(--f-display);
  font-size:clamp(22px,6.2vw,32px);
  font-weight:300; font-style:italic;
  line-height:1.5;
  color:var(--ink);
  opacity:0; transform:translate3d(0,20px,0);
  transition:opacity 1.4s var(--ease), transform 1.4s var(--ease);
  transition-delay:calc(var(--d) * 900ms);
  text-shadow:0 0 30px rgba(196,167,255,.25);
}
.final p{ transition-delay:calc(var(--d) * 700ms + 1.3s); }
.is-shown .final p{ opacity:1; transform:none; }

.final__symbol{
  margin:clamp(22px,5vh,36px) 0;
  font-family:var(--f-display);
  font-size:clamp(30px,9vw,44px);
  letter-spacing:.28em;
  color:var(--rose);
  text-shadow:0 0 30px rgba(255,95,158,.6);
  transition-delay:4.6s !important;
  animation:breathe 4.5s ease-in-out infinite;
}
.final__closing{
  margin:0;
  font-family:var(--f-script);
  font-size:clamp(34px,9.6vw,52px);
  line-height:1.35;
  background:linear-gradient(100deg,#fff,var(--pink) 45%,var(--lav));
  -webkit-background-clip:text; background-clip:text;
  color:transparent; -webkit-text-fill-color:transparent;
  filter:drop-shadow(0 0 24px rgba(255,143,195,.35));
  transition-delay:5.2s !important;
}
.replay{
  margin-top:clamp(34px,7vh,54px);
  padding:14px 26px; min-height:48px;
  border-radius:999px;
  border:1px solid var(--glass-line);
  background:var(--glass);
  font-size:11.5px; letter-spacing:.2em; text-transform:uppercase;
  color:var(--ink-faint);
  opacity:0; transition:opacity 1s var(--ease) 6.2s, color .3s, border-color .3s;
}
.is-shown .replay{ opacity:1; }
.replay:active{ color:var(--pink); border-color:rgba(255,143,195,.4); }

/* =========================================================
   TAMIL LAYER — its own voice, not a subtitle of the English
   ========================================================= */
.ta{
  margin:clamp(12px,2.5vh,20px) 0 clamp(22px,4.5vh,32px);
  padding-left:18px;
  border-left:1px solid rgba(255,143,195,.22);
}

/* Tamil leads, so anything English after it waits its turn */
.ta ~ .reveal-item  { transition-delay:calc(var(--d,0) * 140ms + 1.2s); }
.ta ~ .whisper p    { transition-delay:calc(var(--d) * 380ms + 1.5s); }
.ta ~ .bridge       { transition-delay:3.6s; }
.ta ~ .card-label   { transition-delay:2.8s; }
.card-label + .card { transition-delay:3.3s !important; }
.ta--center{
  padding-left:0; border-left:0;
  text-align:center;
  margin-left:auto; margin-right:auto;
  max-width:34ch;
}
.ta p{
  margin:0 0 .18em;
  font-family:var(--f-tamil);
  font-size:clamp(16px,4.4vw,19px);
  font-weight:400;
  line-height:2.02;
  color:var(--ta-ink);
  opacity:0; transform:translate3d(0,14px,0);
  transition:opacity .95s var(--ease), transform .95s var(--ease);
  transition-delay:calc(var(--d) * 170ms + 150ms);
}
.is-shown .ta p{ opacity:1; transform:none; }
.ta p.is-gap{ height:.75em; margin:0; }
.ta:empty{ display:none; }

.ta--final p{
  font-size:clamp(17px,4.7vw,21px);
  color:var(--gold);
  transition-delay:calc(var(--d) * 320ms + 200ms);
}

/* smaller whisper, used by the last-year section */
.whisper--sm p{ font-size:clamp(18px,4.9vw,23px); }

.card-label{
  margin:clamp(26px,5vh,38px) 0 12px;
  font-size:11px; letter-spacing:.24em; text-transform:uppercase;
  color:var(--ink-faint);
  transition-delay:.9s;
}

/* =========================================================
   THE HIDDEN SURPRISE — a sealed card she has to scratch open
   Nothing here may hint at what is underneath.
   ========================================================= */
.scratch{
  margin:clamp(24px,5vh,44px) auto 0;
  width:100%;
  max-width:360px;
}

.scratch__stage{
  position:relative;
  width:100%;
  height:clamp(258px,44vh,320px);
  border-radius:26px;
  overflow:hidden;
  background:linear-gradient(165deg, rgba(255,255,255,.075), rgba(255,255,255,.02));
  border:1px solid var(--glass-line);
  box-shadow:0 22px 58px rgba(0,0,0,.5);
  isolation:isolate;
}

/* what is waiting under the cover */
.scratch__under{
  position:absolute; inset:0;
  display:flex; flex-direction:column;
  align-items:center; justify-content:center;
  gap:10px;
  padding:26px 22px;
  text-align:center;
  background:
    radial-gradient(120% 90% at 50% 0%, rgba(255,143,195,.16), rgba(255,143,195,0) 62%),
    linear-gradient(170deg, rgba(255,255,255,.05), rgba(255,255,255,.015));
}
.scratch__found{
  margin:0;
  font-family:var(--f-display);
  font-size:clamp(28px,7.6vw,40px);
  font-weight:300; font-style:italic;
  line-height:1.24;
  color:var(--ink);
  text-shadow:0 0 34px rgba(255,143,195,.28);
}
.scratch__foundSub{
  margin:0;
  font-family:var(--f-display);
  font-size:clamp(18px,4.8vw,22px);
  font-weight:300;
  letter-spacing:.02em;
  color:var(--ink-soft, var(--ink));
  opacity:.85;
}

/* the cover itself — painted in canvas so the text scratches off too */
.scratch__cover{
  position:absolute; inset:0;
  width:100%; height:100%;
  display:block;
  cursor:grab;
  touch-action:none;                 /* so a swipe scratches, not scrolls */
  -webkit-user-select:none; user-select:none;
  transition:opacity .85s var(--ease), filter .85s var(--ease);
}
.scratch__cover:active{ cursor:grabbing; }
.scratch.is-open .scratch__cover{
  opacity:0; filter:blur(6px); pointer-events:none;
}
.scratch.is-open .scratch__stage{
  box-shadow:0 22px 64px rgba(255,95,158,.22), 0 22px 58px rgba(0,0,0,.5);
}

/* sparkles + hearts that follow her finger */
.scratch__sparks{ position:absolute; inset:0; pointer-events:none; overflow:hidden; }
.spark{
  position:absolute;
  font-size:14px; line-height:1;
  opacity:0;
  will-change:transform,opacity;
  animation:sparkUp 900ms var(--ease) forwards;
}
@keyframes sparkUp{
  0%   { opacity:0;  transform:translate3d(-50%,-50%,0) scale(.4) rotate(0deg); }
  22%  { opacity:1;  transform:translate3d(-50%,-58%,0) scale(1)  rotate(6deg); }
  100% { opacity:0;  transform:translate3d(-50%,-150%,0) scale(.7) rotate(-10deg); }
}

.scratch__skip{
  display:block;
  margin:16px auto 0;
  font-size:11.5px; letter-spacing:.18em; text-transform:uppercase;
  color:var(--ink-faint);
  opacity:.65;
  transition:opacity .4s, color .3s;
}
.scratch__skip[hidden]{ display:none; }
.scratch__skip:hover, .scratch__skip:focus-visible{ opacity:1; color:var(--ink); }

/* everything that gives the secret away lives in here */
.vreveal{
  opacity:0; transform:translate3d(0,16px,0);
  transition:opacity 1s var(--ease), transform 1s var(--ease);
}
.vreveal.is-open{ opacity:1; transform:none; }

/* =========================================================
   MY VOICE — deliberately not a normal audio player
   ========================================================= */
.voice-head{
  margin:0 0 6px;
  font-family:var(--f-display);
  font-size:clamp(24px,6.6vw,38px);
  font-weight:300; font-style:italic;
  line-height:1.32;
  white-space:pre-line;
  color:var(--ink);
  text-shadow:0 0 34px rgba(255,143,195,.22);
}

.vnote{
  position:relative;
  margin:clamp(30px,6vh,48px) auto 0;
  max-width:340px;
  padding:30px 24px 26px;
  border-radius:26px;
  background:linear-gradient(165deg, rgba(255,255,255,.075), rgba(255,255,255,.02));
  border:1px solid var(--glass-line);
  box-shadow:0 22px 58px rgba(0,0,0,.5);
  backdrop-filter:blur(12px);
  -webkit-backdrop-filter:blur(12px);
  text-align:center;
}

.vnote__btn{
  position:relative;
  width:96px; height:96px;
  border-radius:50%;
  display:inline-flex; align-items:center; justify-content:center;
  background:
    radial-gradient(circle at 34% 30%, rgba(255,255,255,.22), rgba(255,255,255,0) 60%),
    linear-gradient(150deg, var(--rose), var(--violet));
  box-shadow:0 14px 38px rgba(255,95,158,.4), 0 0 0 1px rgba(255,255,255,.14) inset;
  transition:transform .22s var(--ease), box-shadow .3s, filter .3s;
  touch-action:manipulation;
}
.vnote__btn:active{ transform:scale(.94); }
.vnote__ico{ display:block; line-height:0; }
.vnote__ico .ic{ width:36px; height:36px; fill:#fff; }
.vnote__ico .ic--play{ margin-left:3px; }        /* optically centred triangle */
.vnote__ico .ic--pause{ display:none; }
.is-speaking .vnote__ico .ic--play{ display:none; }
.is-speaking .vnote__ico .ic--pause{ display:block; }

/* a slow ring, like the words are still travelling */
.vnote__ring{
  position:absolute; inset:0;
  border-radius:50%;
  border:1px solid rgba(255,143,195,.55);
  opacity:0; pointer-events:none;
}
.is-speaking .vnote__ring{ animation:ripple 2.6s ease-out infinite; }
.vnote.is-idle .vnote__btn{ animation:breathe 3.6s ease-in-out infinite; }

.vnote__wave{
  display:flex; align-items:center; justify-content:center;
  gap:3px; height:26px;
  margin:20px 0 4px;
  opacity:.22; transition:opacity .45s;
}
.vnote__wave i{
  display:block; width:3px; height:4px;
  border-radius:2px;
  background:linear-gradient(180deg,var(--pink),var(--lav));
}
.is-speaking .vnote__wave{ opacity:1; }
.is-speaking .vnote__wave i{ animation:wave 1.1s ease-in-out infinite; }
.vnote__wave i:nth-child(1){ animation-delay:0s }    .vnote__wave i:nth-child(2){ animation-delay:.08s }
.vnote__wave i:nth-child(3){ animation-delay:.16s }  .vnote__wave i:nth-child(4){ animation-delay:.24s }
.vnote__wave i:nth-child(5){ animation-delay:.32s }  .vnote__wave i:nth-child(6){ animation-delay:.4s }
.vnote__wave i:nth-child(7){ animation-delay:.48s }  .vnote__wave i:nth-child(8){ animation-delay:.56s }
.vnote__wave i:nth-child(9){ animation-delay:.64s }  .vnote__wave i:nth-child(10){ animation-delay:.72s }
.vnote__wave i:nth-child(11){ animation-delay:.8s }  .vnote__wave i:nth-child(12){ animation-delay:.88s }
@keyframes wave{ 0%,100%{ height:4px; } 50%{ height:24px; } }

.vnote__label{
  margin:6px 0 0;
  font-family:var(--f-display);
  font-size:clamp(19px,5vw,23px);
  font-style:italic; font-weight:300;
  color:var(--ink);
}
.vnote__labelTa{
  margin:2px 0 0;
  font-family:var(--f-tamil);
  font-size:clamp(14px,3.8vw,16px);
  color:var(--ta-ink);
  opacity:.85;
}
.vnote__note{
  margin:14px 0 0;
  font-size:12.5px; line-height:1.6;
  color:var(--ink-faint);
}
.vnote.is-empty .vnote__btn{ filter:grayscale(.45) brightness(.72); animation:none; }
.vnote.is-empty .vnote__wave{ opacity:.12; }
.vnote.is-empty .vnote__ring{ animation:none; opacity:0; }

/* a slow heartbeat around the card while she's listening */
.vnote.is-speaking{ animation:vheart 1.9s ease-in-out infinite; }
@keyframes vheart{
  0%,100%{ box-shadow:0 22px 58px rgba(0,0,0,.5), 0 0 0 0 rgba(255,95,158,.30); }
  18%    { box-shadow:0 22px 58px rgba(0,0,0,.5), 0 0 34px 8px rgba(255,95,158,.34); }
  34%    { box-shadow:0 22px 58px rgba(0,0,0,.5), 0 0 18px 2px rgba(255,95,158,.22); }
  52%    { box-shadow:0 22px 58px rgba(0,0,0,.5), 0 0 40px 10px rgba(255,143,195,.30); }
}

/* soft hearts drifting up out of the card while the voice plays */
.vnote__hearts{
  position:absolute; inset:-10px -6px 0;
  pointer-events:none; overflow:hidden;
}
.vheart{
  position:absolute; bottom:14%;
  font-size:15px; line-height:1;
  opacity:0;
  will-change:transform,opacity;
  animation:vfloat 4.2s var(--ease) forwards;
}
@keyframes vfloat{
  0%  { opacity:0; transform:translate3d(0,0,0) scale(.5); }
  14% { opacity:.85; }
  70% { opacity:.55; }
  100%{ opacity:0; transform:translate3d(var(--dx,0px),-190px,0) scale(1.05); }
}

/* a warm rose aura behind the card - fades in only while the voice plays */
.vnote::before{
  content:""; position:absolute; inset:-34px -26px;
  border-radius:44px;
  background:
    radial-gradient(55% 50% at 50% 42%, rgba(255,143,195,.30), rgba(255,143,195,0) 72%),
    radial-gradient(45% 40% at 50% 70%, rgba(139,92,246,.20), rgba(139,92,246,0) 75%);
  filter:blur(18px);
  opacity:0;
  transition:opacity 1.2s var(--ease);
  pointer-events:none;
  z-index:-1;
}
.vnote.is-speaking::before{ opacity:1; animation:vaura 3.8s ease-in-out infinite; }
@keyframes vaura{
  0%,100%{ transform:scale(.97); }
  50%    { transform:scale(1.05); }
}

@media (prefers-reduced-motion: reduce){
  .vnote.is-speaking{ animation:none; }
  .spark, .vheart{ animation-duration:.01ms; display:none; }
  .scratch__cover, .vreveal{ transition-duration:.01ms; }
}

/* =========================================================
   THE FINAL WORDS
   ========================================================= */
.love{
  position:relative;
  margin:clamp(26px,6vh,44px) 0 clamp(6px,2vh,14px);
  font-family:var(--f-display);
  font-size:clamp(38px,13.5vw,86px);
  font-weight:500;
  line-height:1.06;
  letter-spacing:.05em;
  max-width:100%;
  transition:opacity 1.5s var(--ease), transform 1.5s var(--ease), filter 1.5s var(--ease);
  transition-delay:3s !important;
  filter:blur(9px);
  transform:scale(.93);
}
.is-shown .love{ filter:blur(0); transform:none; }

.love__text{
  background:linear-gradient(102deg,#fff 0%,var(--pink) 30%,var(--lav) 62%,#fff 100%);
  background-size:220% 100%;
  -webkit-background-clip:text; background-clip:text;
  color:transparent; -webkit-text-fill-color:transparent;
  animation:sheen 7s ease-in-out infinite;
  filter:drop-shadow(0 0 30px rgba(255,95,158,.45));
}
.love__heart{
  display:inline-block;
  margin-left:.12em;
  color:var(--rose);
  -webkit-text-fill-color:var(--rose);
  font-size:.78em;
  animation:beat 2.4s ease-in-out infinite;
  filter:drop-shadow(0 0 22px rgba(255,95,158,.7));
}
.love__glow{
  position:absolute; left:50%; top:50%;
  width:min(86vw,700px); aspect-ratio:1;   /* must stay inside the viewport */
  transform:translate(-50%,-50%);
  background:radial-gradient(circle, rgba(255,95,158,.30), rgba(255,95,158,0) 64%);
  filter:blur(26px);
  z-index:-1; pointer-events:none;
  animation:halo 6.5s ease-in-out infinite;
  animation-play-state:paused;
}
.is-shown .love__glow{ animation-play-state:running; }

/* --- shared keyframes --- */
@keyframes fade-up{ from{ opacity:0; transform:translateY(18px); } to{ opacity:1; transform:none; } }
@keyframes breathe{ 0%,100%{ opacity:.72; transform:scale(1); } 50%{ opacity:1; transform:scale(1.05); } }

/* =========================================================
   DESKTOP / LARGE SCREENS  (mobile stays the default)
   ========================================================= */
@media (min-width:768px){
  body{ font-size:17px; }
  .panel__body{ max-width:720px; }

  .gallery{
    gap:clamp(48px,8vh,90px);
  }
  .frame{ max-width:520px; }
  .frame:nth-child(odd){ margin-right:auto; }
  .frame:nth-child(even){ margin-left:auto; }
  #sec-memories .panel__body{ text-align:left; }
  .frame__shot{ aspect-ratio:3/4; }

  .card{ padding:52px 56px; }
  .player{ max-width:440px; padding:28px 30px 30px; }
  .player__art{ width:216px; }
}

@media (min-width:1100px){
  .panel__body{ max-width:820px; }
  .gallery{
    display:grid;
    grid-template-columns:1fr 1fr;
    align-items:start;
    gap:56px 48px;
  }
  .frame{ max-width:none; }
  .frame:nth-child(3n+1),
  .frame:last-child:nth-child(odd){ grid-column:1 / -1; max-width:560px; margin:0 auto; }
}

/* hover only where a real pointer exists */
@media (hover:hover) and (pointer:fine){
  .balloon:hover{ filter:brightness(1.18); }
  .cue:hover{ color:var(--pink); }
  .play:hover{ transform:scale(1.05); }
  .replay:hover{ color:var(--pink); border-color:rgba(255,143,195,.4); }
  .frame:hover .frame__shot img{ transform:scale(1.04); }
}

/* short phones in landscape — don't force full height */
@media (max-height:520px) and (orientation:landscape){
  .panel{ min-height:auto; padding-top:64px; padding-bottom:96px; }
  .gate__inner{ gap:6px; }
}

/* =========================================================
   ACCESSIBILITY — reduced motion
   ========================================================= */
@media (prefers-reduced-motion:reduce){
  html{ scroll-behavior:auto; }
  *,*::before,*::after{
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.18s !important;
    transition-delay:0ms !important;
  }
  .balloon{ animation:none; }
  .aurora__blob{ animation:none; }
}

/* =========================================================
   ONE LAST SURPRISE — card from the top, then the black-screen
   heart sequence and the final wish. Built by script.js.
   ========================================================= */
html.lsx-lock, html.lsx-lock body{ overflow:hidden; overscroll-behavior:none; }

/* --- the card --- */
.lsx-card{
  position:fixed; z-index:60;
  top:calc(env(safe-area-inset-top) + 18px); left:0; right:0;
  width:min(86vw,340px); margin:0 auto;
  transform:translate3d(0,calc(-100% - 70px),0);
}
.lsx-card[hidden]{ display:none; }
.lsx-card.is-down{ animation:lsx-pull 1.4s cubic-bezier(.3,.7,.25,1) forwards; }
.lsx-card.is-leaving{ animation:lsx-lift .65s var(--ease-soft) forwards; }

.lsx-card__cord{
  position:absolute; left:50%; bottom:100%;
  width:1.5px; height:100vh; margin-left:-.75px;
  background:linear-gradient(to top, rgba(165,205,255,.75), rgba(165,205,255,0) 70%);
  pointer-events:none;
}
.lsx-card__cord::after{           /* the little knot where the cord meets the card */
  content:""; position:absolute; left:50%; bottom:-3px;
  width:7px; height:7px; margin-left:-3.5px; border-radius:50%;
  background:#bcd9ff; box-shadow:0 0 10px rgba(130,185,255,.9);
}

.lsx-card__btn{
  position:relative; display:block; width:100%;
  padding:40px 22px 20px;
  border-radius:22px;
  border:1px solid rgba(150,195,255,.30);
  background:
    radial-gradient(120% 90% at 50% 0%, rgba(90,140,255,.20), rgba(90,140,255,0) 60%),
    linear-gradient(160deg,#141d3b 0%,#1b1134 58%,#2a0f2e 100%);
  color:var(--ink);
  font:inherit; text-align:center; cursor:pointer;
  overflow:hidden;
  -webkit-tap-highlight-color:transparent;
  touch-action:manipulation;
  box-shadow:
    0 22px 50px rgba(0,0,0,.55),
    0 0 42px rgba(90,150,255,.28),
    inset 0 1px 0 rgba(255,255,255,.08);
  animation:lsx-bob 3.8s ease-in-out 1.9s infinite, lsx-shine 3.2s ease-in-out 1.9s infinite;
  transition:transform .45s var(--ease), opacity .7s var(--ease) .25s;
}
.lsx-card__btn:active{ transform:scale(.97); }
.lsx-card__btn:focus-visible{ outline:2px solid #9cc6ff; outline-offset:4px; }

.lsx-card__glow{
  position:absolute; inset:-30% -20% auto; height:120%;
  background:radial-gradient(closest-side, rgba(120,175,255,.28), rgba(120,175,255,0));
  pointer-events:none;
  animation:breathe 3.2s ease-in-out infinite;
}
.lsx-card__flap{
  position:absolute; left:0; right:0; top:0; height:62px;
  background:linear-gradient(180deg, rgba(140,185,255,.22), rgba(140,185,255,.05));
  clip-path:polygon(0 0,100% 0,50% 100%);
  transform-origin:top center;
  transition:transform .6s var(--ease);
}
.lsx-card__seal{
  position:absolute; left:50%; top:44px;
  width:42px; height:42px; margin:-21px 0 0 -21px;
  display:grid; place-items:center;
  border-radius:50%;
  font-size:19px; line-height:1;
  background:radial-gradient(circle at 34% 30%, #6f9bff, #2346b8 70%);
  box-shadow:0 0 0 3px rgba(255,255,255,.06), 0 0 22px rgba(80,140,255,.75);
  transition:transform .6s var(--ease), opacity .5s;
}
.lsx-card__title{
  display:block; margin-top:26px;
  font-family:var(--f-display);
  font-size:clamp(27px,7.6vw,33px);
  font-weight:400; font-style:italic; line-height:1.2;
  color:#f3f7ff;
  text-shadow:0 0 22px rgba(120,175,255,.55);
}
.lsx-card__hint{
  display:flex; align-items:center; justify-content:center; gap:10px;
  margin-top:12px;
  font-size:10.5px; letter-spacing:.26em; text-transform:uppercase;
  color:rgba(195,218,255,.8);
}
.lsx-card__hint b{ font-weight:500; }
.lsx-card__hint i{
  position:relative; width:8px; height:8px; border-radius:50%;
  background:#9cc6ff; box-shadow:0 0 10px #7fb2ff;
}
.lsx-card__hint i::after{
  content:""; position:absolute; inset:-6px; border-radius:50%;
  border:1px solid rgba(156,198,255,.8);
  animation:lsx-ring 1.8s ease-out infinite;
}

.lsx-card.is-opening .lsx-card__flap{ transform:perspective(400px) rotateX(180deg); }
.lsx-card.is-opening .lsx-card__seal{ transform:scale(1.6); opacity:0; }
.lsx-card.is-opening .lsx-card__btn{ transform:scale(1.05); opacity:0; animation:none; }

@keyframes lsx-pull{
  0%  { transform:translate3d(0,calc(-100% - 70px),0); }
  62% { transform:translate3d(0,14px,0); }
  80% { transform:translate3d(0,-5px,0); }
  92% { transform:translate3d(0,3px,0); }
  100%{ transform:translate3d(0,0,0); }
}
@keyframes lsx-lift{
  from{ transform:translate3d(0,0,0); }
  to  { transform:translate3d(0,calc(-100% - 70px),0); }
}
@keyframes lsx-bob{ 0%,100%{ transform:translateY(0); } 50%{ transform:translateY(5px); } }
@keyframes lsx-shine{
  0%,100%{ box-shadow:0 22px 50px rgba(0,0,0,.55), 0 0 36px rgba(90,150,255,.22), inset 0 1px 0 rgba(255,255,255,.08); }
  50%    { box-shadow:0 22px 50px rgba(0,0,0,.55), 0 0 62px rgba(110,170,255,.48), inset 0 1px 0 rgba(255,255,255,.12); }
}
@keyframes lsx-ring{ from{ transform:scale(.5); opacity:1; } to{ transform:scale(1.6); opacity:0; } }

/* --- the black screen --- */
.lsx{
  position:fixed; inset:0; z-index:90;
  width:100%; height:100%;
  background:#000;
  overflow:hidden;
  touch-action:none;
  opacity:0;
  transition:opacity .9s var(--ease);
  -webkit-user-select:none; user-select:none;
}
.lsx.is-on{ opacity:1; }
.lsx.is-leaving{ opacity:0; transition-duration:1.4s; pointer-events:none; }

.lsx__cv{ position:absolute; inset:0; width:100%; height:100%; z-index:0; }

/* a touch of cinema: soft vignette, a slow push-in on the hearts,
   and one gentle wash of blue light as the heart opens with the music */
.lsx::after{
  content:""; position:absolute; inset:0; z-index:1;
  background:radial-gradient(120% 90% at 50% 50%, rgba(0,0,0,0) 55%, rgba(0,0,0,.55) 100%);
  pointer-events:none;
}
.lsx::before{
  content:""; position:absolute; inset:0; z-index:1;
  background:radial-gradient(42% 34% at 50% 50%, rgba(110,170,255,.32), rgba(110,170,255,0) 70%);
  opacity:0; transform:scale(.6);
  pointer-events:none;
}
.lsx.is-on .lsx__cv{ animation:lsx-push 7s cubic-bezier(.2,.6,.3,1) both; }
.lsx.is-bloom::before{ animation:lsx-bloom 2.4s var(--ease) forwards; }
@keyframes lsx-push{ from{ transform:scale(1.06); } to{ transform:scale(1); } }
@keyframes lsx-bloom{
  0%  { opacity:0;   transform:scale(.6); }
  30% { opacity:1;   transform:scale(1.15); }
  100%{ opacity:0;   transform:scale(1.8); }
}

/* the first blue heart */
.lsx__heart{
  position:absolute; left:50%; top:50%; z-index:2;
  transform:translate(-50%,-50%);
  pointer-events:none;
  transition:transform .9s var(--ease), opacity .9s var(--ease), filter .9s var(--ease);
}
.lsx__heart span{
  display:block;
  font-size:clamp(64px,19vw,96px); line-height:1;
  font-family:"Apple Color Emoji","Segoe UI Emoji","Noto Color Emoji",sans-serif;
  opacity:0;
  filter:drop-shadow(0 0 18px rgba(70,140,255,.95)) drop-shadow(0 0 46px rgba(70,140,255,.6));
}
.lsx__heart.is-in span{
  animation:lsx-heart-in 1.6s var(--ease) forwards, lsx-heartbeat 1.35s ease-in-out 1.6s infinite;
}
.lsx__heart.is-open{ transform:translate(-50%,-50%) scale(2.6); opacity:0; filter:blur(6px); }

@keyframes lsx-heart-in{
  0%  { opacity:0; transform:scale(.35); }
  100%{ opacity:1; transform:scale(1); }
}
@keyframes lsx-heartbeat{
  0%,100%{ opacity:1; transform:scale(1); }
  14%    { opacity:1; transform:scale(1.14); }
  28%    { opacity:1; transform:scale(1.02); }
  42%    { opacity:1; transform:scale(1.2); }
  70%    { opacity:1; transform:scale(1.08); }
}

/* the love words */
.lsx__words{ position:absolute; inset:0; z-index:2; pointer-events:none; }
.lsx__word{
  position:absolute; left:calc(50% + var(--dx, 0px));
  width:max-content; max-width:min(84vw,540px);
  margin:0; padding:.2em .5em;
  text-align:center;
  font-family:var(--f-display);
  font-size:clamp(24px,6.8vw,36px);
  font-weight:400; font-style:italic; line-height:1.25;
  color:#fbf6ff;
  isolation:isolate;
  text-shadow:0 0 10px rgba(0,0,0,.95), 0 0 26px rgba(0,0,0,.85), 0 0 34px rgba(255,120,180,.45);
  opacity:0;
  animation:lsx-word var(--life, 2.9s) var(--ease-soft) forwards;
}
.lsx__word::before{               /* soft dark bed so the line reads over hearts */
  content:""; position:absolute; inset:-35% -10%; z-index:-1;
  background:radial-gradient(closest-side, rgba(0,0,0,.62), rgba(0,0,0,0));
}
.lsx__word--blue{ color:#eef5ff; text-shadow:0 0 10px rgba(0,0,0,.95), 0 0 26px rgba(0,0,0,.85), 0 0 34px rgba(90,155,255,.6); }
.lsx__word--big{
  font-family:var(--f-script); font-style:normal;
  font-size:clamp(40px,11.5vw,64px); line-height:1.15;
}
@keyframes lsx-word{
  0%  { opacity:0; transform:translate(-50%,calc(-50% + 14px)) scale(.96); filter:blur(8px); }
  28% { opacity:1; transform:translate(-50%,-50%) scale(1); filter:blur(0); }
  72% { opacity:1; transform:translate(-50%,calc(-50% - 4px)) scale(1.01); filter:blur(0); }
  100%{ opacity:0; transform:translate(-50%,calc(-50% - 14px)) scale(1.02); filter:blur(6px); }
}

/* the final wish */
.lsx__wish{
  position:absolute; inset:0; z-index:3;
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  padding:0 var(--pad);
  text-align:center;
  pointer-events:none;
  transition:opacity 1.2s var(--ease), filter 1.2s var(--ease);
}
.lsx__wish p{ margin:0; }
.lsx__wish1{
  font-family:var(--f-display); font-style:italic; font-weight:300;
  font-size:clamp(26px,7.4vw,40px); line-height:1.3;
  transition:transform 1.4s var(--ease), opacity 1.4s var(--ease);
}
.lsx__wish .lsx__wish2{
  margin-top:clamp(14px,3vh,24px);
  max-width:13ch;
  font-family:var(--f-script);
  font-size:clamp(46px,13.5vw,84px); line-height:1.12;
  filter:drop-shadow(0 0 22px rgba(90,155,255,.55)) drop-shadow(0 0 40px rgba(255,110,175,.3));
}
.lsx__w{
  display:inline-block;
  opacity:0; filter:blur(10px); transform:translateY(14px) scale(.96);
  transition:opacity 1.1s var(--ease), filter 1.1s var(--ease), transform 1.1s var(--ease);
  transition-delay:calc(var(--i) * 260ms);
  background:linear-gradient(100deg,#ffffff 0%,#bcd8ff 42%,#ffc2dc 100%);
  -webkit-background-clip:text; background-clip:text;
  color:transparent; -webkit-text-fill-color:transparent;
}
.lsx__w--emo{
  background:none; -webkit-text-fill-color:currentColor; color:#fff;
  font-family:"Apple Color Emoji","Segoe UI Emoji","Noto Color Emoji",sans-serif;
  font-size:.7em; vertical-align:.12em;
}
.lsx__wish1 .lsx__w{ transition-delay:calc(var(--i) * 200ms); }
.lsx__wish.is-wish .lsx__wish1 .lsx__w,
.lsx__wish.is-final .lsx__wish2 .lsx__w{ opacity:1; filter:blur(0); transform:none; }
.lsx__wish.is-final .lsx__wish1{ transform:translateY(-10px) scale(.84); opacity:.72; }
.lsx__wish.is-final .lsx__wish2{ animation:lsx-pulse 1.9s ease-in-out 2.4s infinite; }
.lsx__wish.is-gone{ opacity:0; filter:blur(8px); }

@keyframes lsx-pulse{
  0%,100%{ transform:scale(1); }
  12%    { transform:scale(1.035); }
  24%    { transform:scale(1.005); }
  36%    { transform:scale(1.045); }
  60%    { transform:scale(1); }
}

@media (min-width:768px){
  .lsx-card{ width:360px; }
  .lsx-card__btn:hover{ border-color:rgba(170,210,255,.5); }
}

@media (prefers-reduced-motion:reduce){
  .lsx-card.is-down{ animation:none; transform:none; }
  .lsx-card.is-leaving{ animation:none; display:none; }
  .lsx-card__btn, .lsx-card__glow, .lsx-card__hint i::after{ animation:none !important; }
  .lsx__heart.is-in span{ animation:none; opacity:1; }
  .lsx__heart.is-open{ transform:translate(-50%,-50%); }
  .lsx__word{ animation:lsx-word-calm var(--life, 2.4s) linear forwards !important; }
  .lsx__w{ filter:none; transform:none; }
  .lsx__wish.is-final .lsx__wish2{ animation:none; }
}
@keyframes lsx-word-calm{
  0%,100%{ opacity:0; transform:translate(-50%,-50%); }
  25%,75%{ opacity:1; transform:translate(-50%,-50%); }
}
