/* ============================================================
   Alexander's First Birthday — image-based parallax invitation
   Mobile-first. Artworks by the family; live overlays on top.
   ============================================================ */
@import url('https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,500;0,600;0,700;1,500&family=Pinyon+Script&family=Plus+Jakarta+Sans:wght@400;500;600;700&display=swap');

:root{
  --cream:#F3EBD7;
  --cream-2:#EFE6C2;
  --ivory:#F7F2E7;
  --blue:#9BB5CB;
  --blue-ink:#5E7C98;
  --blue-deep:#46637E;
  --sage:#8A9866;
  --sage-deep:#6E7A52;
  --ink:#3a382f;
  --ink-soft:#6b6657;
  --line:#DAD0B4;
  --white:#fff;

  --font-script:'Pinyon Script', cursive;
  --font-serif:'Cormorant Garamond', serif;
  --font-sans:'Plus Jakarta Sans', system-ui, sans-serif;

  --col:min(100vw, 470px);   /* design column width */
  --shadow-card:0 22px 48px -26px rgba(70,80,60,.5), 0 6px 16px -10px rgba(70,80,60,.3);
  --ease:cubic-bezier(.22,.61,.36,1);
}

*{box-sizing:border-box; margin:0; padding:0}
html{scroll-behavior:smooth}
body{
  font-family:var(--font-sans);
  color:var(--ink);
  background:#e9e2cf;
  -webkit-font-smoothing:antialiased;
  overflow-x:clip;
}
img{display:block; width:100%; height:auto}
body.intro-active{overflow:hidden; height:100svh}

/* ---------- fixed striped parallax backdrop ---------- */
.backdrop{
  position:fixed; inset:-6% 0; z-index:0; pointer-events:none;
  background:
    repeating-linear-gradient(90deg,
      #efe7d2 0 26px,
      #e7dcc0 26px 28px,
      #efe7d2 28px 52px,
      #d9e3ec 52px 78px,
      #cdd9e6 78px 80px,
      #d9e3ec 80px 104px);
  will-change:transform;
}
.backdrop::after{
  content:""; position:absolute; inset:0;
  background:radial-gradient(120% 70% at 50% 0%, rgba(247,242,231,0) 50%, rgba(247,242,231,.5) 100%);
}

/* ---------- scroll column ---------- */
.stage{
  position:relative; z-index:1;
  width:100%; max-width:470px; margin-left:auto; margin-right:auto;
  display:flex; flex-direction:column;
  gap:0; padding:0;
}

/* ---------- a scene (one artwork + its live overlays) ----------
   Seamless: no gap, no rounded corners, no card shadow, no per-scene motion —
   the seven artworks stack edge-to-edge as one continuous page. */
.scene{position:relative}
.scene-inner{
  position:relative; container-type:inline-size;
  overflow:hidden;
  background:var(--ivory);
  margin-top:-1px;            /* hairline overlap kills sub-pixel seams between images */
}
.scene:first-child .scene-inner{margin-top:0}
.scene-inner > img{display:block}

/* entrance (only when JS is active; without JS everything stays visible).
   Parallax sets an inline transform on every .scene, so the entrance is an
   opacity fade only. `.js .scene.in` (3 classes) outranks `.js .scene`. */
/* Scenes are always visible — no opacity gating (it proved unreliable in this
   runtime, leaving artwork invisible). Parallax drives the only motion. */

/* per-scene float disabled so adjacent artworks never separate (one continuous page).
   Ambient life now comes only from the atmosphere canvas, grain and backdrop. */
.float .scene-inner{animation:none}

/* ============================================================
   COUNTDOWN overlay (on art/1.png)
   ============================================================ */
/* Each number is a cream patch matching the box interior (#FAF3E9): it hides
   the baked number on the artwork, while the FULL baked labels below stay intact.
   This is why we use the original art (full labels) instead of the erased one. */
.cd-num{
  position:absolute; top:80%; transform:translate(-50%,-50%);
  width:14cqw; height:6.6cqw;
  display:flex; align-items:center; justify-content:center;
  background:#FAF3E9; border-radius:7px;
  font-family:var(--font-serif); font-weight:600;
  color:var(--blue-ink); line-height:1;
  font-size:6.2cqw; letter-spacing:.01em;
  font-variant-numeric:tabular-nums; text-align:center;
}
.cd-num.d{left:19%}
.cd-num.h{left:39.4%}
.cd-num.m{left:60%}
.cd-num.s{left:80.1%}

/* ============================================================
   MAP link overlay (on art/3.png)
   ============================================================ */
.overlay-link{
  position:absolute; display:block;
  border-radius:999px; cursor:pointer;
  -webkit-tap-highlight-color:transparent;
}
.overlay-link:focus-visible{outline:2px solid var(--blue-ink); outline-offset:3px}
.map-hit{left:26%; width:48%; top:89.4%; height:5.2%}
.tag-hit{left:7%; width:86%; top:76%; height:15%; border-radius:18px}

/* ============================================================
   RSVP overlays (on art/6.png)
   ============================================================ */
.rsvp-scene .scene-inner{overflow:visible}
.rsvp-scene .scene-inner > img{border-radius:18px}
.ov{position:absolute; -webkit-tap-highlight-color:transparent}
/* Clean, fully-enclosed fields (the baked boxes had erased/cut edges).
   Symmetric 12%–88% so both sides are always fully visible. */
.ov-input, .ov-msg{
  left:12%; width:76%;
  background:rgba(255,255,255,.66); outline:none;
  border:1.4px solid rgba(94,124,152,.34); border-radius:13px;
  font-family:var(--font-sans); color:var(--blue-deep);
  box-shadow:inset 0 1px 2px rgba(70,80,60,.05);
  transition:border-color .22s var(--ease), background .22s var(--ease), box-shadow .22s var(--ease);
}
.ov-input{ top:54%; height:6.6%; font-size:4cqw; padding:0 14px; }
.ov-msg{ top:76.6%; height:11%; resize:none; font-size:3.8cqw; line-height:1.4; padding:9px 14px; }
.ov-input::placeholder, .ov-msg::placeholder{color:#9fb0bf; font-style:italic}
.ov-input:focus, .ov-msg:focus{
  background:rgba(255,255,255,.78); border-color:var(--blue-ink);
  box-shadow:0 0 0 3px rgba(94,124,152,.14);
}
/* Equal-size, aligned choice buttons (fully cover the unequal baked boxes) */
.ov-radio{
  top:63.6%; height:9%; cursor:pointer;
  display:flex; align-items:center; justify-content:center; gap:8px;
  background:#FAF7EE;
  border:1.5px solid rgba(94,124,152,.34); border-radius:14px;
  color:var(--blue-deep); text-align:left;
  box-shadow:inset 0 1px 2px rgba(70,80,60,.05);
  transition:background .22s var(--ease), box-shadow .22s var(--ease), transform .18s var(--ease), border-color .22s var(--ease);
}
.ov-radio.joy{left:13%; width:35.5%}
.ov-radio.regret{left:49.5%; width:35.5%}
.rb-ico{ font-size:4.8cqw; line-height:1; flex:none; }
.rb-tx{ font-family:var(--font-sans); font-weight:600; font-size:3.3cqw; line-height:1.16; }
.ov-radio:hover{ background:#fff; border-color:rgba(94,124,152,.55); }
.ov-radio:active{ transform:scale(.97); }
.ov-radio[aria-pressed="true"]{
  background:#E8EFF5;            /* opaque so the baked label never ghosts through */
  border-color:var(--blue-ink);
  box-shadow:inset 0 0 0 2px var(--blue-ink);
  animation:radioPop .32s var(--ease);
}
@keyframes radioPop{ 0%{transform:scale(.94)} 55%{transform:scale(1.03)} 100%{transform:scale(1)} }
.ov-send{
  left:15.5%; width:69%; top:88.2%; height:5.9%;
  background:transparent; border:none; cursor:pointer; border-radius:999px;
  overflow:hidden; transition:transform .18s var(--ease), filter .22s var(--ease);
}
.ov-send::after{
  content:""; position:absolute; top:0; bottom:0; width:42%;
  left:-60%; transform:skewX(-18deg);
  background:linear-gradient(90deg, transparent, rgba(255,255,255,.45), transparent);
  animation:sendShine 3.6s ease-in-out 1.4s infinite;
}
.ov-send:hover{ filter:brightness(1.05); }
.ov-send:active{transform:scale(.985)}
@keyframes sendShine{ 0%{left:-60%} 18%,100%{left:130%} }
@media (prefers-reduced-motion:reduce){ .ov-send::after{animation:none} }

/* thank-you + wishes wall (below the RSVP art) */
.after{margin-top:16px}
.thanks{
  display:none; text-align:center;
  background:var(--white); border:1px solid var(--line); border-radius:18px;
  padding:20px 22px; box-shadow:var(--shadow-card);
  font-family:var(--font-serif); font-style:italic; font-size:19px; color:var(--sage-deep);
}
.wishes{margin-top:16px}
.wishes-head{
  text-align:center; font-family:var(--font-serif); color:var(--sage-deep);
  letter-spacing:.16em; text-transform:uppercase; font-size:12px; font-weight:600;
  margin-bottom:12px;
}
.wish-list{display:flex; flex-direction:column; gap:10px}
.wish{
  background:var(--white); border:1px solid var(--line); border-radius:16px;
  padding:14px 16px; box-shadow:0 10px 24px -18px rgba(70,80,60,.5);
}
.wish .top{display:flex; align-items:center; gap:9px; margin-bottom:5px}
.wish .av{
  width:30px; height:30px; border-radius:50%; flex:none; display:grid; place-items:center;
  background:var(--cream-2); color:var(--sage-deep); font-family:var(--font-serif);
  font-weight:700; font-size:15px;
}
.wish .nm{font-weight:700; font-size:13.5px; color:var(--ink)}
.wish .badge{margin-left:auto; font-size:9.5px; font-weight:700; letter-spacing:.06em; text-transform:uppercase; padding:3px 9px; border-radius:999px}
.wish .badge.joy{background:rgba(138,152,102,.18); color:var(--sage-deep)}
.wish .badge.regret{background:rgba(94,124,152,.16); color:var(--blue-deep)}
.wish .msg{font-size:13.5px; line-height:1.55; color:var(--ink-soft)}
.wishes-empty{text-align:center; font-family:var(--font-serif); font-style:italic; color:var(--ink-soft); font-size:16px}

/* ============================================================
   INTRO / OPENING cover (art/opening.png)
   ============================================================ */
.intro{
  position:fixed; inset:0; z-index:1000; perspective:1700px;
  background:
    radial-gradient(120% 80% at 50% 18%, #F7F2E7 0%, #EFE6D0 70%, #E7DCC1 100%);
}
.intro-inner{
  position:absolute; inset:0; transform-origin:top center; backface-visibility:hidden;
  transition:transform 1.15s cubic-bezier(.7,.04,.3,1), opacity .8s ease .35s;
}
body.opening .intro-inner{transform:rotateX(-96deg); opacity:0}

.intro-mat{
  position:absolute; inset:0; overflow-y:auto;
  display:flex;
  -webkit-overflow-scrolling:touch;
}
/* the whole card is the tap target; margin:auto centering never clips the top */
.intro-open{
  margin:auto; display:block; cursor:pointer; border:none; background:transparent;
  padding:clamp(16px,3.5svh,30px) 14px;
  -webkit-tap-highlight-color:transparent;
  animation:cardBreath 2.8s ease-in-out infinite;
}
.intro-open:focus-visible{outline:3px solid rgba(110,122,82,.5); outline-offset:4px; border-radius:18px}
@keyframes cardBreath{0%,100%{transform:scale(1)}50%{transform:scale(1.02)}}

.intro-art{
  position:relative; container-type:inline-size;
  width:min(96vw, calc((100svh - 56px) * 0.75), 460px);
  border-radius:14px; overflow:hidden;
  box-shadow:0 26px 60px -28px rgba(70,80,60,.55), 0 8px 20px -12px rgba(70,80,60,.34);
}
.intro-art > img{ width:100%; height:auto; display:block; }

/* editable guest name sits in the cleaned slot under “Dear” */
.intro-guest{
  position:absolute; left:50%; top:29%; transform:translate(-50%,-50%);
  font-family:var(--font-script); color:var(--sage-deep);
  font-size:12cqw; line-height:1; white-space:nowrap; text-align:center;
}

/* soft pulsing cue over the baked “open invitation” text */
.open-pulse{
  position:absolute; left:50%; bottom:2.6%; transform:translateX(-50%);
  width:52%; height:5.2%; border-radius:999px;
  border:1.6px solid var(--sage); pointer-events:none;
  animation:openPulse 1.9s ease-in-out infinite;
}
@keyframes openPulse{
  0%,100%{transform:translateX(-50%) scale(.9); opacity:.2}
  50%{transform:translateX(-50%) scale(1.05); opacity:.6}
}
@media (prefers-reduced-motion:reduce){
  .intro-open{animation:none}
  .open-pulse{animation:none; opacity:.4}
}

/* ============================================================
   MUSIC toggle
   ============================================================ */
.music-btn{
  position:fixed; right:14px; bottom:14px; z-index:1200;
  width:50px; height:50px; border-radius:50%; cursor:pointer;
  background:var(--white); border:1px solid var(--line);
  box-shadow:var(--shadow-card); display:grid; place-items:center;
  color:var(--sage-deep);
}
.music-btn svg{width:21px; height:21px}
.music-btn .ring{position:absolute; inset:-5px; border-radius:50%; border:1.5px solid var(--sage); opacity:0}
.music-btn.playing .ring{animation:mpulse 2.4s ease-out infinite}
@keyframes mpulse{0%{transform:scale(.85); opacity:.5}100%{transform:scale(1.35); opacity:0}}
.music-btn .pause{display:none}
.music-btn.playing .play{display:none}
.music-btn.playing .pause{display:block}

@media (min-width:480px){
  .music-btn{right:calc(50vw - 235px + 8px)}
}

/* ============================================================
   AWARD-LEVEL ENHANCEMENT LAYER
   ============================================================ */

/* ---- Preloader ---- */
.preloader{
  position:fixed; inset:0; z-index:2000;
  background:radial-gradient(125% 95% at 50% 34%, #F7F2E7 0%, #ECE2CB 70%, #E4D9BE 100%);
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:20px;
  transition:opacity .8s ease;
}
.preloader.done{ opacity:0; pointer-events:none; }
.pl-mark{ position:relative; width:98px; height:98px; display:grid; place-items:center; }
.pl-mark svg{ position:absolute; inset:0; width:100%; height:100%; transform:rotate(-90deg); }
.pl-ring{
  fill:none; stroke:var(--sage); stroke-width:3; stroke-linecap:round;
  stroke-dasharray:327; stroke-dashoffset:327;
  animation:plRing 1.7s cubic-bezier(.6,.02,.2,1) forwards;
}
@keyframes plRing{ to{ stroke-dashoffset:46; } }
.pl-initial{
  font-family:var(--font-script); font-size:56px; color:var(--sage-deep);
  line-height:1; margin-top:-.08em; opacity:0; animation:plFade .9s ease .4s forwards;
}
.pl-word{
  font-family:var(--font-serif); letter-spacing:.46em; text-transform:uppercase;
  font-size:12px; font-weight:600; color:var(--sage-deep);
  opacity:0; transform:translateY(6px); animation:plFade 1s ease .65s forwards;
}
@keyframes plFade{ to{ opacity:1; transform:none; } }
@media (prefers-reduced-motion:reduce){
  .pl-ring{ animation:none; stroke-dashoffset:46; }
  .pl-initial, .pl-word{ animation:none; opacity:1; transform:none; }
}

/* ---- Atmosphere / grain / vignette ---- */
.atmosphere{ position:fixed; inset:0; z-index:1090; pointer-events:none; }
.vignette{
  position:fixed; inset:0; z-index:1080; pointer-events:none;
  background:radial-gradient(132% 96% at 50% 42%, transparent 56%, rgba(70,64,44,.17) 100%);
}
.grain{
  position:fixed; inset:0; z-index:1086; pointer-events:none; opacity:.05; mix-blend-mode:multiply;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:160px 160px;
}
@media (prefers-reduced-motion:reduce){ .atmosphere{ display:none; } }

/* ---- Scroll progress ribbon ---- */
.progress{
  position:fixed; top:0; left:0; right:0; height:3px; z-index:1300; pointer-events:none;
  background:rgba(110,122,82,.12);
}
.progress span{
  display:block; height:100%; width:100%; transform:scaleX(0); transform-origin:0 50%;
  background:linear-gradient(90deg, var(--sage), var(--blue-ink));
  transition:transform .12s linear;
}

/* ---- Opening: kinetic guest name + light sweep + wax-seal ritual ---- */
body.revealed .intro-guest{ animation:guestIn 1.1s var(--ease) both; }
@keyframes guestIn{
  0%{ transform:translate(-50%,-34%) scale(.96); letter-spacing:.1em; }
  100%{ transform:translate(-50%,-50%) scale(1); }
}

.intro-art .sweep{
  position:absolute; inset:0; pointer-events:none; opacity:0; z-index:4; border-radius:14px;
  background:linear-gradient(105deg, transparent 32%, rgba(255,255,255,.6) 48%, transparent 64%);
  transform:translateX(-60%);
}
body.opening .intro-art .sweep{ animation:sweep .85s ease-out .04s forwards; }
@keyframes sweep{
  0%{ opacity:0; transform:translateX(-65%); }
  28%{ opacity:1; } 100%{ opacity:0; transform:translateX(65%); }
}

.wax-seal{
  position:absolute; left:50%; top:91.2%; transform:translate(-50%,-50%);
  width:14cqw; height:14cqw; border-radius:50%; z-index:5;
  background:radial-gradient(circle at 38% 32%, #9aa873 0%, #6e7a52 62%, #58623f 100%);
  box-shadow:0 5px 12px rgba(60,70,45,.5), inset 0 -3px 6px rgba(0,0,0,.28), inset 0 3px 5px rgba(255,255,255,.28);
  display:grid; place-items:center;
  animation:sealBreath 2.1s ease-in-out infinite;
}
.wax-seal::before{ content:""; position:absolute; inset:9%; border-radius:50%; border:1.4px dashed rgba(243,235,215,.55); }
/* Pinyon Script capital sits high in its em box; nudge down to optically centre it in the seal */
.wax-initial{ font-family:var(--font-script); color:var(--cream-2); font-size:7.4cqw; line-height:1; transform:translateY(0.07em); }
@keyframes sealBreath{ 0%,100%{ transform:translate(-50%,-50%) scale(1); } 50%{ transform:translate(-50%,-50%) scale(1.06); } }
body.opening .wax-seal{ animation:sealBreak .5s var(--ease) forwards; }
@keyframes sealBreak{ to{ transform:translate(-50%,-50%) scale(1.55) rotate(-12deg); opacity:0; filter:blur(2px); } }
@media (prefers-reduced-motion:reduce){ .wax-seal{ animation:none; } body.opening .intro-art .sweep{ animation:none; } }

/* Countdown pop-in removed: the number is now a cream cover-patch over the
   baked number, so scaling it down (pop-in) or fading it would briefly expose
   the artwork's baked digit. Numbers appear cleanly; the seconds heartbeat
   (scale-UP only) stays safe because growing the patch never uncovers it. */
/* tiny heartbeat on the seconds digit each tick */
.cd-num.s.tick{ animation:secTick .9s var(--ease); }
@keyframes secTick{ 0%{transform:translate(-50%,-50%) scale(1.14)} 100%{transform:translate(-50%,-50%) scale(1)} }
@media (prefers-reduced-motion:reduce){ .cd-num.s.tick{ animation:none; } }

/* ============================================================
   DETAIL PHOTO — sharp photo overlaid on the baked photo slot of art/3.png
   (replaces the pixellated baked-in photo above the date/place card)
   ============================================================ */
.detail-photo{
  position:absolute; left:18%; top:4.3%; width:64%; height:38%;
  object-fit:cover; object-position:50% 42%;
  border-radius:18px; display:block;
  box-shadow:0 14px 30px -18px rgba(70,80,60,.45);
}
.detail-photo{ animation:photoBreath 9s ease-in-out infinite; transform-origin:center; }
@keyframes photoBreath{ 0%,100%{transform:scale(1)} 50%{transform:scale(1.018)} }
@media (prefers-reduced-motion:reduce){ .detail-photo{ animation:none; } }

/* ============================================================
   SCROLL-REVEAL — intentionally DISABLED.
   The opacity fade-in is unreliable in this runtime (inline opacity:1 computes
   as 0 — a documented cascade anomaly that blanks the artwork). Scenes are kept
   always visible, matching the original handoff. Every OTHER micro-animation
   (atmosphere, seal, countdown pop/heartbeat, photo breath, button states,
   link hint, etc.) stays on. The page never risks rendering blank.
   ============================================================ */
.js .scene{ opacity:1; filter:none; }

/* ============================================================
   LINK HINT — soft pulsing ring so tappable overlays read as buttons
   ============================================================ */
.overlay-link::after{
  content:""; position:absolute; inset:0; border-radius:inherit;
  box-shadow:0 0 0 0 rgba(94,124,152,.0);
  animation:linkHint 2.6s ease-out infinite;
}
@keyframes linkHint{
  0%{ box-shadow:0 0 0 0 rgba(94,124,152,.28); }
  70%,100%{ box-shadow:0 0 0 10px rgba(94,124,152,0); }
}
.overlay-link:active{ transform:scale(.99); }
@media (prefers-reduced-motion:reduce){ .overlay-link::after{ animation:none; } }
