/* =========================================================
   ANIMATIONS
   Scroll reveals + entrance motion
========================================================= */

/* ---------------------------------------------------------
   Reveal on scroll.

   Elements start shifted and transparent; main.js adds the
   .is-visible class through an IntersectionObserver. If JS
   never runs the .no-js fallback below keeps everything
   readable.
--------------------------------------------------------- */

.fade-up,
.fade-left,
.fade-right,
.zoom-in{
    opacity:0;
    will-change:transform,opacity;
    transition:opacity .75s var(--ease-out),
               transform .75s var(--ease-out);
}

.fade-up{
    transform:translate3d(0,32px,0);
}

.fade-left{
    transform:translate3d(-36px,0,0);
}

.fade-right{
    transform:translate3d(36px,0,0);
}

.zoom-in{
    transform:scale(.94);
}

.fade-up.is-visible,
.fade-left.is-visible,
.fade-right.is-visible,
.zoom-in.is-visible{
    opacity:1;
    transform:none;
}

/* Generic reveal applied by main.js to section children */

.reveal{
    opacity:0;
    transform:translate3d(0,26px,0);
    transition:opacity .7s var(--ease-out),
               transform .7s var(--ease-out);
    transition-delay:var(--reveal-delay,0ms);
    will-change:transform,opacity;
}

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

/* =========================================================
   KEYFRAMES
========================================================= */

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

@keyframes fadeUp{
    from{ opacity:0; transform:translate3d(0,26px,0); }
    to{ opacity:1; transform:none; }
}

@keyframes fadeDown{
    from{ opacity:0; transform:translate3d(0,-20px,0); }
    to{ opacity:1; transform:none; }
}

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

@keyframes slideInLeft{
    from{ opacity:0; transform:translate3d(-30px,0,0); }
    to{ opacity:1; transform:none; }
}

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

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

/* =========================================================
   UTILITY ANIMATION CLASSES
========================================================= */

.animate-fade-in{ animation:fadeIn .6s var(--ease) both; }
.animate-fade-up{ animation:fadeUp .7s var(--ease-out) both; }
.animate-fade-down{ animation:fadeDown .6s var(--ease-out) both; }
.animate-scale-in{ animation:scaleIn .6s var(--ease-spring) both; }
.animate-float{ animation:floatY 6s ease-in-out infinite; }

/* Staggered children */

.stagger > *{
    animation:fadeUp .7s var(--ease-out) both;
}

.stagger > *:nth-child(1){ animation-delay:.05s; }
.stagger > *:nth-child(2){ animation-delay:.12s; }
.stagger > *:nth-child(3){ animation-delay:.19s; }
.stagger > *:nth-child(4){ animation-delay:.26s; }
.stagger > *:nth-child(5){ animation-delay:.33s; }
.stagger > *:nth-child(6){ animation-delay:.40s; }

/* Skeleton loading shimmer */

.skeleton{
    background:linear-gradient(
        90deg,
        var(--surface-light) 25%,
        var(--surface-sunken) 50%,
        var(--surface-light) 75%);
    background-size:1000px 100%;
    animation:shimmer 1.6s linear infinite;
    border-radius:var(--radius-xs);
}

/* =========================================================
   NO-JS / REDUCED MOTION FALLBACKS
========================================================= */

.no-js .fade-up,
.no-js .fade-left,
.no-js .fade-right,
.no-js .zoom-in,
.no-js .reveal{
    opacity:1;
    transform: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;
    }

    .fade-up,
    .fade-left,
    .fade-right,
    .zoom-in,
    .reveal{
        opacity:1 !important;
        transform:none !important;
    }
}
