/* ==========================================================================
   DAILY LEAF — ANIMATIONS
   All keyframes and motion utilities. Every effect respects
   prefers-reduced-motion at the bottom of this file.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. KEYFRAMES
   -------------------------------------------------------------------------- */

@keyframes fadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes fadeUp {
  from { opacity: 0; transform: translateY(28px); }
  to   { opacity: 1; transform: none; }
}

@keyframes fadeDown {
  from { opacity: 0; transform: translateY(-28px); }
  to   { opacity: 1; transform: none; }
}

@keyframes slideInLeft {
  from { opacity: 0; transform: translateX(-42px); }
  to   { opacity: 1; transform: none; }
}

@keyframes slideInRight {
  from { opacity: 0; transform: translateX(42px); }
  to   { opacity: 1; transform: none; }
}

@keyframes scaleIn {
  from { opacity: 0; transform: scale(0.94); }
  to   { opacity: 1; transform: none; }
}

@keyframes ripple {
  to { transform: scale(3.2); opacity: 0; }
}

@keyframes float {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-14px); }
}

@keyframes pulseRing {
  0%   { box-shadow: 0 0 0 0 rgba(98, 180, 75, 0.42); }
  70%  { box-shadow: 0 0 0 18px rgba(98, 180, 75, 0); }
  100% { box-shadow: 0 0 0 0 rgba(98, 180, 75, 0); }
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

@keyframes shimmer {
  0%   { background-position: -480px 0; }
  100% { background-position: 480px 0; }
}

@keyframes marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

/* --------------------------------------------------------------------------
   2. SCROLL REVEAL
   Elements carrying [data-reveal] start hidden. main.js adds .is-visible
   through an IntersectionObserver as they enter the viewport.
   -------------------------------------------------------------------------- */

[data-reveal] {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity var(--dur-slow) var(--ease),
              transform var(--dur-slow) var(--ease);
  will-change: opacity, transform;
}

[data-reveal].is-visible {
  opacity: 1;
  transform: none;
}

[data-reveal="left"]  { transform: translateX(-42px); }
[data-reveal="right"] { transform: translateX(42px); }
[data-reveal="scale"] { transform: scale(0.94); }
[data-reveal="fade"]  { transform: none; }

[data-reveal="left"].is-visible,
[data-reveal="right"].is-visible,
[data-reveal="scale"].is-visible { transform: none; }

/* Stagger children — set data-stagger on the parent */
[data-stagger] > * { transition-delay: calc(var(--i, 0) * 90ms); }

/* --------------------------------------------------------------------------
   3. UTILITY ANIMATION CLASSES
   -------------------------------------------------------------------------- */

.anim-fade-in   { animation: fadeIn var(--dur-slow) var(--ease) both; }
.anim-fade-up   { animation: fadeUp var(--dur-slow) var(--ease) both; }
.anim-fade-down { animation: fadeDown var(--dur-slow) var(--ease) both; }
.anim-scale-in  { animation: scaleIn var(--dur-slow) var(--ease) both; }
.anim-float     { animation: float 6s var(--ease-in-out) infinite; }
.anim-pulse     { animation: pulseRing 2.4s var(--ease-out) infinite; }
.anim-spin      { animation: spin 900ms linear infinite; }

.delay-1 { animation-delay: 90ms; }
.delay-2 { animation-delay: 180ms; }
.delay-3 { animation-delay: 270ms; }
.delay-4 { animation-delay: 360ms; }
.delay-5 { animation-delay: 450ms; }

/* --------------------------------------------------------------------------
   4. HOVER LIFT
   -------------------------------------------------------------------------- */

.hover-lift {
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.hover-lift:hover { transform: translateY(-6px); box-shadow: var(--shadow-lg); }

.hover-zoom { overflow: hidden; }
.hover-zoom img,
.hover-zoom svg { transition: transform var(--dur-slow) var(--ease); }
.hover-zoom:hover img,
.hover-zoom:hover svg { transform: scale(1.06); }

/* --------------------------------------------------------------------------
   5. SKELETON LOADER
   -------------------------------------------------------------------------- */

.skeleton {
  background: linear-gradient(90deg, var(--n-100) 8%, var(--n-200) 20%, var(--n-100) 34%);
  background-size: 960px 100%;
  animation: shimmer 1.4s linear infinite;
  border-radius: var(--r-sm);
}

/* --------------------------------------------------------------------------
   6. MARQUEE STRIP
   -------------------------------------------------------------------------- */

.marquee { overflow: hidden; }
.marquee-track {
  display: flex;
  gap: var(--sp-16);
  width: max-content;
  animation: marquee 34s linear infinite;
}
.marquee:hover .marquee-track { animation-play-state: paused; }

/* --------------------------------------------------------------------------
   7. LAZY IMAGE FADE
   Prevents layout shift and fades the image in once decoded.
   -------------------------------------------------------------------------- */

img[loading="lazy"] {
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease);
}
img[loading="lazy"].is-loaded,
img[loading="lazy"][data-loaded] { opacity: 1; }

/* --------------------------------------------------------------------------
   8. REDUCED MOTION
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  [data-reveal] { opacity: 1 !important; transform: none !important; }
  img[loading="lazy"] { opacity: 1; }
}
