/* ══════════════════════════════════════════════
   PREFERS-REDUCED-MOTION
   Centralised override block — all decorative
   animation/transition overrides live here only.
   Functional state changes (toasts, XP bar
   width, splash spinner) are deliberately kept.
   ══════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {

    /* ── 1. Kill the CSS custom property used by most interactive
            transitions so every element that inherits it snaps
            to instant without touching individual rules. ── */
    :root {
        --transition: 0s;
    }

    /* ── 2. hero-card.css: borderShimmer
            Decorative box-shadow pulse on the hero card border. ── */
    .hero-card {
        animation: none;
    }

    /* ── 3. hero-card.css: particleDrift (both ::before and ::after)
            Floating gold particles around the avatar. ── */
    .hero-particles::before,
    .hero-particles::after {
        animation: none;
        opacity: 0;          /* hide: static particles add clutter without motion */
    }

    /* ── 4. hero-card.css: heroBob
            Avatar bobbing / floating up-and-down loop. ── */
    .avatar-inner,
    .avatar-fallback {
        animation: none;
        transform: translateY(-10px); /* hold the raised position from the keyframe */
    }

    /* ── 5. hero-card.css: barShine
            Shimmer sweep across the XP progress bar fill. ── */
    .progress-bar-fill.xp-fill::after {
        animation: none;
        display: none;       /* pseudo-element is purely decorative */
    }

    /* ── 6. hero-card.css: xpPulse
            Glow burst on the XP bar when XP is added.
            Purely decorative — the XP gain is already communicated by
            the bar width changing instantly and the toast. Any animation
            duration, even 0.01s, still counts as motion under WCAG intent. ── */
    .progress-bar-fill.xp-pulse {
        animation: none;
    }

    /* ── 7. hero-card.css: flicker
            Flame emoji scale/brightness flicker on the streak counter. ── */
    .hero-streak .streak-fire {
        animation: none;
    }

    /* ── 8. hero-card.css: evolveFlash
            Avatar scale + brightness flash when the player levels up.
            The flash is motion-heavy (scale 1 → 1.25 → 1); remove it.
            The level-up event is still communicated via the level number
            changing and the LEVEL UP toast. ── */
    .avatar-frame.evolve-flash .avatar-inner {
        animation: none;
    }

    /* ── 9. hero-card.css: progress bar width transition
            Smoothed width grow on XP bar. Snap to instant. ── */
    .progress-bar-fill {
        transition: none;
    }

    /* ── 10. style.css: toastIn + toastOut
             Entrance fade/slide and exit fade on all toast variants.
             Cannot use animation:none here — JS removes the toast element
             by listening for animationend {animationName === 'toastOut'};
             animation:none suppresses that event and toasts would leak in
             the DOM forever. Instead we collapse both keyframe phases to
             0s duration so they fire and resolve immediately with no
             visible motion, the animationend event still fires, and JS
             cleanup works normally. opacity:1 ensures instant visibility. ── */
    .toast {
        animation-duration: 0s;
        animation-delay: 0s;
        opacity: 1;
    }

    /* ── 11. style.css: levelUpBounce + overlayFade
             Full-screen "LEVEL UP!" overlay bounce and fade.
             The overlay element is still appended/removed by JS so the
             text appears; we just remove the bounce scale and fade. ── */
    .levelup-overlay {
        animation: none;
        opacity: 1;          /* stay visible; JS removes the element after 2.5 s */
    }
    .levelup-text {
        animation: none;
        transform: scale(1); /* skip the scale-up bounce */
    }

    /* ── 12. style.css: floatUp
             +XP floating number that drifts up from the XP bar. ── */
    .xp-float {
        animation: none;
        opacity: 0;          /* hide immediately; the toast already shows the gain */
    }

    /* ── 13. style.css: fadeSlideIn
             Habits panel content slide-in on tab switch. ── */
    #habits-panel-content {
        animation: none;
    }

    /* ── 14. style.css: onboarding carousel slide transition
             Slide transform on the multi-step onboarding track. ── */
    .onboarding-track {
        transition: none;
    }

    /* ── 15. style.css: onboarding dot state transitions ── */
    .onboarding-dot {
        transition: none;
    }

    /* ── 16. style.css: header hero-mini collapse reveal
             Opacity + translateY fade-in of the sticky mini hero. ── */
    .header-hero-mini {
        transition: none;
    }

    /* ── 17. achievement.css: card hover lift
             translateY(-2px) + box-shadow on achievement card hover. ── */
    .ach-card {
        transition: border-color 0s;  /* keep border-color snap for focus feedback */
    }
    .ach-card:hover {
        transform: none;
    }

    /* ── 18. achievement.css: progress bar fill transitions
             Width grow on ach header bar, card bar, and modal bar. ── */
    .ach-progress-fill,
    .ach-card-progress-fill,
    .ach-modal-progress-fill {
        transition: none;
    }

    /* ── 19. stat.css: SVG ring stroke-dashoffset animation
             Animated circular area-progress rings in the Stats panel. ── */
    .stat-area-circle {
        transition: none;
    }

    /* ── 20. stat.css: stat XP bar and habit bar fill transitions ── */
    .stat-xp-fill,
    .stat-habit-fill {
        transition: none;
    }

    /* ── 21. areas-v2: progress fill and card hover lift ── */
    .area-progress-fill-v2,
    .mq-mini-fill {
        transition: none;
    }
    .area-card-v2:hover {
        transform: none;
    }

    /* ── 22. habits.css: ally/enemy card hover lift (Phase 5) ── */
    .ally-card:hover,
    .enemy-card:hover {
        transform: none;
    }

    /* ── 23. buttons.css: btnSpin (Phase 5, M-7)
             Rotating ring on .btn.is-loading (Restore/Start Fresh/
             Export/Import). The spinner is purely decorative motion —
             loading state itself is still fully conveyed by the
             disabled/cursor:wait state and the status text each caller
             sets alongside it, so it's safe to freeze rather than hide. ── */
    .btn.is-loading::after {
        animation: none;
    }
}