/* i2t3 scroll animations — shared by the animation content elements
 * Initial hidden state + reveal transition. The scroll-reveal script adds
 * .is-revealed when the element enters the viewport.
 */

.i2t3-animate {
    opacity: 0;
    transition: opacity .7s ease, transform .7s ease;
    will-change: opacity, transform;
}
.i2t3-animate[data-animation="fade-up"]    { transform: translateY(40px); }
.i2t3-animate[data-animation="fade-down"]  { transform: translateY(-40px); }
.i2t3-animate[data-animation="fade-left"]   { transform: translateX(40px); }
.i2t3-animate[data-animation="fade-right"]  { transform: translateX(-40px); }
.i2t3-animate[data-animation="zoom"]        { transform: scale(.85); }
.i2t3-animate[data-animation="zoom-in"]     { transform: scale(.6); }
.i2t3-animate[data-animation="zoom-out"]    { transform: scale(1.2); }
.i2t3-animate[data-animation="flip-left"]   { transform: perspective(1000px) rotateY(-90deg); }
.i2t3-animate[data-animation="flip-right"]  { transform: perspective(1000px) rotateY(90deg); }
.i2t3-animate[data-animation="flip-up"]     { transform: perspective(1000px) rotateX(90deg); }
.i2t3-animate[data-animation="flip-down"]   { transform: perspective(1000px) rotateX(-90deg); }

/* Revealed end-state — MUST come after the [data-animation] start-states. Both
 * selectors have equal specificity (0,2,0); declaring this last lets it win so
 * the transform actually animates to none (otherwise only opacity would fade
 * and every animation looked identical). */
.i2t3-animate.is-revealed { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
    .i2t3-animate { opacity: 1 !important; transform: none !important; transition: none !important; }
}
