/* =====================================================================
   WAIFI — Animations (animations.css)
   ---------------------------------------------------------------------
   Responsibility: @keyframes + scroll-reveal utility classes toggled by
   Intersection Observer (frontend.md §15, uiux.md §22). Motion is
   DECORATIVE — content must be readable without it.
   Progressive enhancement: the hidden initial state (.reveal) is applied
   ONLY when scripting is enabled, so no-JS users still see all content.
   Load order: 6th.
   ===================================================================== */

/* ---------------------------------------------------------------------
   1. KEYFRAMES — entrance effects (uiux.md §22)
   --------------------------------------------------------------------- */
@keyframes fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

@keyframes fade-up {
    from { opacity: 0; transform: translateY(var(--space-5)); }
    to   { opacity: 1; transform: translateY(0); }
}

@keyframes fade-left {
    from { opacity: 0; transform: translateX(calc(-1 * var(--space-5))); }
    to   { opacity: 1; transform: translateX(0); }
}

@keyframes fade-right {
    from { opacity: 0; transform: translateX(var(--space-5)); }
    to   { opacity: 1; transform: translateX(0); }
}

@keyframes scale-in {
    from { opacity: 0; transform: scale(0.95); }
    to   { opacity: 1; transform: scale(1); }
}

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

/* ---------------------------------------------------------------------
   2. REVEAL UTILITIES — applied to elements observed by animation.js
   Default = visible. The hidden start state only applies when JS is on,
   so the page never shows blank content if JS fails. animation.js adds
   .is-revealed when an element enters the viewport.
   --------------------------------------------------------------------- */
@media (scripting: enabled) {

    .reveal {
        opacity: 0;
        transition: opacity var(--transition-slow) var(--ease-out),
                    transform var(--transition-slow) var(--ease-out);
        will-change: opacity, transform;
    }

    .reveal--up    { transform: translateY(var(--space-5)); }
    .reveal--left  { transform: translateX(calc(-1 * var(--space-5))); }
    .reveal--right { transform: translateX(var(--space-5)); }
    .reveal--scale { transform: scale(0.95); }

    /* When revealed, animate to natural state */
    .reveal.is-revealed {
        opacity: 1;
        transform: none;
    }

    /* Stagger children via inline --reveal-delay or nth-child in sections */
    .reveal[style*="--reveal-delay"] {
        transition-delay: var(--reveal-delay);
    }
}

/* ---------------------------------------------------------------------
   3. REDUCED MOTION — no movement, content appears instantly
   (Hard guard also in reset.css; this block ensures reveal elements
   are visible even when the (scripting: enabled) state applies.)
   --------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    .reveal,
    .reveal--up,
    .reveal--left,
    .reveal--right,
    .reveal--scale {
        opacity: 1 !important;
        transform: none !important;
        transition: none !important;
    }
}

/* ---------------------------------------------------------------------
   4. UTILITY ANIMATIONS — small reusable helpers
   --------------------------------------------------------------------- */
.animate-fade-in { animation: fade-in var(--transition-normal) var(--ease-out) both; }

/* Spinner for future loading states */
.spinner {
    display: inline-block;
    width: 1.25rem;
    height: 1.25rem;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: var(--radius-full);
    animation: spin 0.7s linear infinite;
}
