/*
 * animations.css — Interaction Designer Layer
 * Advance Our Youth | Funding Engine
 *
 * All animations are hardware-accelerated: they only touch `transform` and
 * `opacity` so the browser keeps them on the GPU compositor thread.
 * This prevents layout recalculation (reflow) and guarantees 60fps.
 *
 * Usage:
 *   Add  data-animate="fade-in-up"  (or another variant) to any element.
 *   The IntersectionObserver in main.js will add `.is-visible` when it
 *   enters the viewport, triggering the transition.
 */

/* ─── 1. RESPECT USER PREFERENCES ─────────────────────────────────────────── */
/*
 * If the user has enabled "Reduce Motion" in their OS accessibility settings,
 * all animations collapse to a simple fade so nothing ever flashes or spins.
 */
@media (prefers-reduced-motion: reduce) {
  [data-animate],
  [data-stagger-child] {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
}

/* ─── 2. BASE STATE: elements start hidden ─────────────────────────────────── */
/*
 * Every animated element is invisible until .is-visible is applied by JS.
 * `will-change` hints to the browser to promote the element to its own
 * composited layer ahead of time, eliminating frame-drop on trigger.
 */
[data-animate] {
  opacity: 0;
  will-change: transform, opacity;
}

/* ─── 3. ANIMATION VARIANTS (pre-visible state) ────────────────────────────── */

/* Rises up from 32px below its natural position */
[data-animate="fade-in-up"] {
  transform: translateY(32px);
}

/* Falls down from 32px above */
[data-animate="fade-in-down"] {
  transform: translateY(-32px);
}

/* Slides in from the left */
[data-animate="fade-in-left"] {
  transform: translateX(-48px);
}

/* Slides in from the right */
[data-animate="fade-in-right"] {
  transform: translateX(48px);
}

/* Scales up from 92% — subtle "pop" for cards and CTAs */
[data-animate="scale-in"] {
  transform: scale(0.92);
}

/* Pure fade, no movement — for backgrounds and overlays */
[data-animate="fade-in"] {
  transform: none;
}

/* ─── 4. VISIBLE STATE: applied by IntersectionObserver ────────────────────── */
/*
 * When JS adds .is-visible, all variants transition to the same natural state.
 * The `transition` is defined here so it only applies on the "reveal" direction
 * (not on the reverse), preventing re-animation on scroll-out.
 */
[data-animate].is-visible {
  opacity: 1;
  transform: none;
  transition:
    opacity  0.65s cubic-bezier(0.16, 1, 0.3, 1),
    transform 0.65s cubic-bezier(0.16, 1, 0.3, 1);
}

/* ─── 5. STAGGER GROUPS ────────────────────────────────────────────────────── */
/*
 * Add  data-stagger-group  to a parent element. Its direct children tagged
 * with  data-stagger-child  receive progressively delayed transitions,
 * creating the "cascading reveal" effect for stat cards and program cards.
 *
 * The JS IntersectionObserver observes the parent; when the parent becomes
 * visible, it adds .is-visible to each child in sequence.
 */
[data-stagger-child] {
  opacity: 0;
  transform: translateY(28px);
  will-change: transform, opacity;
}

[data-stagger-child].is-visible {
  opacity: 1;
  transform: none;
  transition:
    opacity  0.55s cubic-bezier(0.16, 1, 0.3, 1),
    transform 0.55s cubic-bezier(0.16, 1, 0.3, 1);
}

/* Individual stagger delays — JS sets inline delay via CSS custom property */
[data-stagger-child].is-visible {
  transition-delay: var(--stagger-delay, 0ms);
}

/* ─── 6. COUNTER ANIMATION ─────────────────────────────────────────────────── */
/*
 * The impact stat counters use a CSS clip-path trick to mask the number
 * as it counts up. JS handles the numeric increment; CSS handles the
 * container's reveal entrance.
 */
.stat-number {
  display: inline-block;
  /* Numbers count up via JS requestAnimationFrame — no CSS keyframes needed */
}

/* ─── 7. STICKY HEADER TRANSITION ─────────────────────────────────────────── */
/*
 * The header gains .scrolled when the user scrolls past the hero.
 * The JS scroll handler applies this class; CSS handles all visual effects.
 * backdrop-filter creates the glassmorphism blur without JS doing any painting.
 */
.site-header {
  transition:
    background-color 0.4s ease,
    box-shadow       0.4s ease,
    backdrop-filter  0.4s ease;
}

.site-header.scrolled {
  background-color: rgba(10, 10, 20, 0.88);
  backdrop-filter: blur(12px) saturate(160%);
  -webkit-backdrop-filter: blur(12px) saturate(160%);
  box-shadow: 0 1px 24px rgba(0, 0, 0, 0.35);
}

/* ─── 8. DONATE BUTTON PULSE ───────────────────────────────────────────────── */
/*
 * A slow, ambient pulse on the primary donate CTA draws the eye without
 * being distracting. Uses a box-shadow bloom to feel premium rather than
 * tacky. Only applies to the hero CTA — not every button on the page.
 */
@keyframes cta-pulse {
  0%   { box-shadow: 0 0 0   0px rgba(var(--color-accent-rgb), 0.55); }
  60%  { box-shadow: 0 0 0  14px rgba(var(--color-accent-rgb), 0.0); }
  100% { box-shadow: 0 0 0   0px rgba(var(--color-accent-rgb), 0.0); }
}

.btn-pulse {
  animation: cta-pulse 2.8s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}

/* ─── 9. HERO TEXT ENTRANCE ─────────────────────────────────────────────────── */
/*
 * The hero h1, subtitle, and CTAs each animate in on page load with a
 * short stagger. These are keyframe-based (not IntersectionObserver) because
 * they need to fire immediately, not on scroll.
 */
@keyframes hero-rise {
  from {
    opacity: 0;
    transform: translateY(24px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.hero-section h1 {
  animation: hero-rise 0.75s cubic-bezier(0.16, 1, 0.3, 1) 0.15s both;
}

.hero-section p {
  animation: hero-rise 0.75s cubic-bezier(0.16, 1, 0.3, 1) 0.30s both;
}

.hero-section .hero-ctas {
  animation: hero-rise 0.75s cubic-bezier(0.16, 1, 0.3, 1) 0.48s both;
}

/* ─── 10. ACTIVE NAV LINK INDICATOR ────────────────────────────────────────── */
/*
 * JS uses IntersectionObserver on each section to apply .active-section to
 * the body as a data-attribute. The CSS underline slides to the correct link.
 */
.nav-links a {
  position: relative;
}

.nav-links a::after {
  content: '';
  position: absolute;
  bottom: -4px;
  left: 0;
  width: 0;
  height: 2px;
  background-color: var(--color-accent, #e63a2e);
  transition: width 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}

.nav-links a.active-link::after,
.nav-links a:hover::after {
  width: 100%;
}
