/* ==========================================================================
   The Daily Key — animations.css
   Keyframes + initial states for GSAP-driven motion. Initial "hidden" states
   only apply once animations.js adds .motion-ready, so content is never lost
   if JavaScript fails. All motion is removed under prefers-reduced-motion.
   ========================================================================== */
@keyframes bump { 0% { transform: scale(1); } 35% { transform: scale(1.5); } 100% { transform: scale(1); } }
@keyframes slideDown { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: none; } }
@keyframes lineIn { from { background: var(--blush); } to { background: transparent; } }
@keyframes floaty { 0%, 100% { transform: translateY(0) rotate(-4deg); } 50% { transform: translateY(-8px) rotate(4deg); } }
@keyframes cue { 0% { transform: scaleY(0); opacity: 1; } 55% { transform: scaleY(1); opacity: 1; } 100% { transform: scaleY(1); opacity: 0; } }
@keyframes heartpop { 0% { transform: scale(1); } 30% { transform: scale(1.35); } 60% { transform: scale(.92); } 100% { transform: scale(1); } }
@keyframes ripple { from { transform: scale(.4); opacity: .6; } to { transform: scale(2.4); opacity: 0; } }
@keyframes tickPop { 0% { transform: scale(.6); opacity: 0; } 70% { transform: scale(1.08); opacity: 1; } 100% { transform: scale(1); } }

.wish-btn.pop .ico, .wish-big.pop .ico { animation: heartpop .6s var(--ease); }
.wish-btn.pop::after { content: ''; position: absolute; inset: 0; border-radius: 50%; border: 1px solid var(--rose-deep); animation: ripple .7s var(--ease) forwards; }
.btn-add.is-done { animation: heartpop .5s var(--ease); }
.success .seal svg { animation: tickPop .8s var(--ease) .2s both; }

/* masked heading reveal */
.motion-ready .mask-line { display: block; overflow: hidden; padding-bottom: .1em; margin-bottom: -.1em; }
.motion-ready .mask-line > span { display: block; transform: translateY(108%); will-change: transform; }
.motion-ready .mask-line.is-in > span { transform: none; transition: transform 1.1s var(--ease); }

/* image reveal (clip-path) and gentle rise */
.motion-ready [data-reveal="img"] { clip-path: inset(0 0 100% 0); will-change: clip-path; }
.motion-ready [data-reveal="img"].is-in { clip-path: inset(0 0 0 0); transition: clip-path 1.3s var(--ease); }
.motion-ready [data-reveal="up"], .motion-ready [data-reveal="stagger"] > * { opacity: 0; transform: translateY(22px); }
.motion-ready [data-reveal="up"].is-in, .motion-ready [data-reveal="stagger"] > .is-in { opacity: 1; transform: none; transition: opacity .9s var(--ease), transform 1.1s var(--ease); }

/* hero starting states are set by GSAP; fall back to visible without it */
.motion-ready .hero-frame { clip-path: inset(100% 0 0 0); }
.motion-ready .hero-title .hl > span { opacity: 0; }
.motion-ready .hero-script, .motion-ready .hero-sub, .motion-ready .hero-cta .btn, .motion-ready .hero-card, .motion-ready .hero-deco, .motion-ready .scroll-cue, .motion-ready .hero-key { opacity: 0; }
.motion-ready.has-intro .announce, .motion-ready.has-intro .header-inner > * { opacity: 0; }
.motion-ready.hero-done .hero-frame { clip-path: none; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; scroll-behavior: auto !important; }
  .veil { display: none !important; }
  .motion-ready .mask-line > span, .motion-ready [data-reveal], .motion-ready [data-reveal="stagger"] > *, .motion-ready .hero-frame, .motion-ready .hero-title .hl > span,
  .motion-ready .hero-script, .motion-ready .hero-sub, .motion-ready .hero-cta .btn, .motion-ready .hero-card, .motion-ready .hero-deco, .motion-ready .scroll-cue, .motion-ready .hero-key, .motion-ready .announce, .motion-ready .header-inner > * { opacity: 1 !important; transform: none !important; clip-path: none !important; }
  .scroll-cue i { animation: none; }
}
