/* ==========================================================================
   ANIMATION.CSS
   Keyframes + animated state classes used across the site.
   Kept separate from landing.css so it can be reused on journey.html
   and invitation.html later.
   ========================================================================== */

/* ---------- LOADING SCREEN ---------- */
@keyframes fadeUpIn {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}

.loading-line { animation: fadeUpIn 0.8s var(--ease-luxury) forwards; }
.loading-line#loading-line-1 { animation-delay: 0.2s; }
.loading-line#loading-line-2 { animation-delay: 0.8s; }

#loading-screen.is-hidden {
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.9s var(--ease-luxury);
}

/* ---------- BOOK-OPENING ENTRANCE ---------- */
@keyframes pageOpenLeft {
  from { opacity: 0; transform: rotateY(-58deg); }
  to   { opacity: 1; transform: rotateY(0deg); }
}

@keyframes pageOpenRight {
  from { opacity: 0; transform: rotateY(58deg); }
  to   { opacity: 1; transform: rotateY(0deg); }
}

.landing-left, .landing-right-inner > * {
  opacity: 0;
}

.landing-left {
  transform-origin: right center;
  backface-visibility: hidden;
}

.landing-right {
  transform-origin: left center;
}

body.is-ready .landing-left {
  animation: pageOpenLeft 1.1s var(--ease-luxury) forwards;
  animation-delay: 0.2s;
}

body.is-ready .landing-right {
  animation: pageOpenRight 1.1s var(--ease-luxury) forwards;
  animation-delay: 0.2s;
}

body.is-ready .landing-right-inner > * {
  animation: fadeUpIn 1s var(--ease-luxury) forwards;
}

/* staggered reveal for right-side text block, timed after the page settles open */
body.is-ready .eyebrow          { animation-delay: 1.05s; }
body.is-ready .hero-title       { animation-delay: 1.2s; }
body.is-ready .hero-subtitle    { animation-delay: 1.35s; }
body.is-ready .hero-paragraph   { animation-delay: 1.5s; }
body.is-ready .countdown-block  { animation-delay: 1.65s; }
body.is-ready .cta-block        { animation-delay: 1.8s; }

/* ---------- BUTTON GLOW (once countdown reaches zero) ---------- */
@keyframes btnGlowPulse {
  0%, 100% { box-shadow: 0 12px 30px rgba(110, 74, 147, 0.45); }
  50%      { box-shadow: 0 18px 46px rgba(110, 74, 147, 0.85); }
}

.btn-open-letter.is-ready-to-open {
  animation: btnGlowPulse 2.2s ease-in-out infinite;
}

/* ---------- COUNTDOWN NUMBER TICK ---------- */
@keyframes numberTick {
  0%   { transform: translateY(4px); opacity: 0.4; }
  100% { transform: translateY(0);   opacity: 1; }
}

.countdown-number.is-ticking { animation: numberTick 0.35s var(--ease-luxury); }

/* ---------- PASSWORD POPUP: WRONG PASSWORD SHAKE ---------- */
@keyframes shakeCard {
  0%, 100% { transform: translateX(0); }
  20%      { transform: translateX(-10px); }
  40%      { transform: translateX(8px); }
  60%      { transform: translateX(-6px); }
  80%      { transform: translateX(4px); }
}

.popup-card.is-shaking { animation: shakeCard 0.5s ease; }

/* ---------- PAGE TRANSITION (white fade before redirect) ---------- */
@keyframes fadeToWhite {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.page-transition.is-active {
  animation: fadeToWhite 0.9s var(--ease-luxury) forwards;
  pointer-events: all;
}

/* ---------- MUSIC EQUALIZER BARS ---------- */
@keyframes eqBar1 { 0%,100% { height: 40%; } 50% { height: 100%; } }
@keyframes eqBar2 { 0%,100% { height: 70%; } 50% { height: 30%; } }
@keyframes eqBar3 { 0%,100% { height: 50%; } 50% { height: 90%; } }

.music-toggle.is-playing .music-bar:nth-child(1) { animation: eqBar1 0.9s ease-in-out infinite; }
.music-toggle.is-playing .music-bar:nth-child(2) { animation: eqBar2 1.1s ease-in-out infinite; }
.music-toggle.is-playing .music-bar:nth-child(3) { animation: eqBar3 0.8s ease-in-out infinite; }

/* ---------- REDUCED MOTION ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ==========================================================================
   ROMANTIC PARTICLE LAYER
   Sparkles (twinkling dots) + floating hearts (bursts + ambient drift).
   Sparkles are generated once by animation.js into .sparkle-layer.
   Hearts are spawned on demand via window.spawnHearts(container, count).
   ========================================================================== */

.sparkle-layer {
  position: absolute;
  inset: 0;
}

.sparkle {
  position: absolute;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--color-accent);
  opacity: 0;
  animation: sparkleTwinkle 3.5s ease-in-out infinite;
}

@keyframes sparkleTwinkle {
  0%, 100% { opacity: 0; transform: scale(0.6); }
  50%      { opacity: 0.8; transform: scale(1.3); }
}

/* fixed full-viewport overlay that receives spawned hearts (see js: spawnHearts) */
.heart-burst-layer {
  position: fixed;
  inset: 0;
  overflow: visible;
  pointer-events: none;
  z-index: 600;
}

.floating-heart {
  position: absolute;
  bottom: 0;
  font-size: 1rem;
  color: var(--color-ink-deep);
  opacity: 0;
  animation-name: heartRise;
  animation-timing-function: ease-out;
  animation-fill-mode: forwards;
  will-change: transform, opacity;
}

@keyframes heartRise {
  0% {
    opacity: 0;
    transform: translate(0, 0) scale(0.6) rotate(0deg);
  }
  12% {
    opacity: 0.9;
  }
  100% {
    opacity: 0;
    transform: translate(var(--drift, 20px), -140px) scale(1.05) rotate(var(--spin, 12deg));
  }
}

/* ambient, always-on hearts inside the June "Kita" section — pure CSS,
   no JS dependency so it always plays even before scripts finish loading */
.journey-june { position: relative; overflow: hidden; }

.june-heart {
  position: absolute;
  bottom: -10%;
  font-size: 1.1rem;
  color: var(--color-ink-deep);
  opacity: 0.75;
  animation: juneHeartFloat 8s ease-in infinite;
}

@keyframes juneHeartFloat {
  0%   { transform: translateY(0) translateX(0) scale(0.8); opacity: 0; }
  10%  { opacity: 0.8; }
  100% { transform: translateY(-320px) translateX(var(--drift, 0px)) scale(1.1); opacity: 0; }
}

.june-heart:nth-child(1) { left: 8%;  animation-delay: 0s;   --drift: 18px;  }
.june-heart:nth-child(2) { left: 22%; animation-delay: 1.4s; --drift: -14px; font-size: 0.85rem; }
.june-heart:nth-child(3) { left: 38%; animation-delay: 2.8s; --drift: 22px;  font-size: 1.3rem; }
.june-heart:nth-child(4) { left: 55%; animation-delay: 0.7s; --drift: -20px; }
.june-heart:nth-child(5) { left: 70%; animation-delay: 3.6s; --drift: 16px;  font-size: 0.9rem; }
.june-heart:nth-child(6) { left: 84%; animation-delay: 2s;   --drift: -10px; font-size: 1.2rem; }
.june-heart:nth-child(7) { left: 92%; animation-delay: 4.4s; --drift: 12px;  }
.june-heart:nth-child(8) { left: 15%; animation-delay: 5s;   --drift: -18px; font-size: 0.8rem; }
