/*!
 * Noemi Slider Pro — Transitions Library v1.0
 *
 * 24 professional slide transitions. Each transition works via two states:
 *   .nsp-slide.is-entering[data-transition="X"]  → incoming slide animation
 *   .nsp-slide.is-leaving[data-transition="X"]    → outgoing slide animation
 *
 * The JS engine adds is-entering to the new slide and is-leaving to the old one,
 * then cleans up after the animation completes. Duration is controlled via
 * --nsp-trans-dur (set per-slider, default 800ms).
 *
 * Categories:
 *   Fades:      fade, crossfade, fade-through-black, fade-through-white
 *   Slides:     slide-left, slide-right, slide-up, slide-down
 *   Zooms:      zoom-in, zoom-out, zoom-blur
 *   3D:         cube-left, cube-right, flip-horizontal, flip-vertical, fold, rotate-in
 *   Reveals:    wipe-left, wipe-right, wipe-up, circle-reveal, split-vertical, split-horizontal
 *   Creative:   glitch, blur-fade, ken-burns-fade, parallax-slide
 */

/* ============================================================
   BASE — stacking + perspective + duration token
   ============================================================ */
.nsp-slider {
    --nsp-trans-dur: 800ms;
    --nsp-trans-ease: cubic-bezier(0.45, 0, 0.15, 1);
}

.nsp-viewport {
    position: relative;
    width: 100%;
    height: 100%;
    overflow: hidden;
}

.nsp-track {
    position: relative;
    width: 100%;
    height: 100%;
    transform-style: preserve-3d;
    perspective: 1600px;
}

/* All slides absolutely stacked */
.nsp-slide {
    position: absolute;
    inset: 0;
    opacity: 0;
    visibility: hidden;
    z-index: 0;
    backface-visibility: hidden;
    transform-origin: center center;
    will-change: transform, opacity;
}

/* Active = fully shown, on top */
.nsp-slide.is-active {
    opacity: 1;
    visibility: visible;
    z-index: 2;
    pointer-events: auto;
}

/* Entering/leaving share top z-index during animation */
.nsp-slide.is-entering { z-index: 3; visibility: visible; opacity: 1; }
.nsp-slide.is-leaving  { z-index: 1; visibility: visible; opacity: 1; }

/* Animation driver: when entering/leaving, run the keyframes */
.nsp-slide.is-entering { animation-duration: var(--nsp-trans-dur); animation-timing-function: var(--nsp-trans-ease); animation-fill-mode: both; }
.nsp-slide.is-leaving  { animation-duration: var(--nsp-trans-dur); animation-timing-function: var(--nsp-trans-ease); animation-fill-mode: both; }

/* ============================================================
   1. FADE — simplest, opacity only
   ============================================================ */
.nsp-slide.is-entering[data-transition="fade"] { animation-name: nspEnterFade; }
.nsp-slide.is-leaving[data-transition="fade"]  { animation-name: nspLeaveFade; }
@keyframes nspEnterFade { from { opacity: 0; } to { opacity: 1; } }
@keyframes nspLeaveFade { from { opacity: 1; } to { opacity: 0; } }

/* ============================================================
   2. CROSSFADE — both fade simultaneously, slower
   ============================================================ */
.nsp-slide.is-entering[data-transition="crossfade"] { animation-name: nspEnterFade; animation-duration: calc(var(--nsp-trans-dur) * 1.4); }
.nsp-slide.is-leaving[data-transition="crossfade"]  { animation-name: nspLeaveFade; animation-duration: calc(var(--nsp-trans-dur) * 1.4); }

/* ============================================================
   3. FADE THROUGH BLACK
   ============================================================ */
.nsp-slide.is-entering[data-transition="fade-through-black"] { animation-name: nspEnterFadeBlack; }
.nsp-slide.is-leaving[data-transition="fade-through-black"]  { animation-name: nspLeaveFadeBlack; }
@keyframes nspEnterFadeBlack { 0% { opacity: 0; filter: brightness(0); } 50% { opacity: 1; filter: brightness(0); } 100% { opacity: 1; filter: brightness(1); } }
@keyframes nspLeaveFadeBlack { 0% { opacity: 1; filter: brightness(1); } 50% { opacity: 1; filter: brightness(0); } 100% { opacity: 0; filter: brightness(0); } }

/* ============================================================
   4. FADE THROUGH WHITE
   ============================================================ */
.nsp-slide.is-entering[data-transition="fade-through-white"] { animation-name: nspEnterFadeWhite; }
.nsp-slide.is-leaving[data-transition="fade-through-white"]  { animation-name: nspLeaveFadeWhite; }
@keyframes nspEnterFadeWhite { 0% { opacity: 0; filter: brightness(8); } 50% { opacity: 1; filter: brightness(8); } 100% { opacity: 1; filter: brightness(1); } }
@keyframes nspLeaveFadeWhite { 0% { opacity: 1; filter: brightness(1); } 50% { opacity: 1; filter: brightness(8); } 100% { opacity: 0; filter: brightness(8); } }

/* ============================================================
   5-8. SLIDES (directional push)
   ============================================================ */
.nsp-slide.is-entering[data-transition="slide-left"]  { animation-name: nspEnterSlideLeft; }
.nsp-slide.is-leaving[data-transition="slide-left"]   { animation-name: nspLeaveSlideLeft; }
@keyframes nspEnterSlideLeft { from { transform: translateX(100%); } to { transform: translateX(0); } }
@keyframes nspLeaveSlideLeft { from { transform: translateX(0); } to { transform: translateX(-100%); } }

.nsp-slide.is-entering[data-transition="slide-right"] { animation-name: nspEnterSlideRight; }
.nsp-slide.is-leaving[data-transition="slide-right"]  { animation-name: nspLeaveSlideRight; }
@keyframes nspEnterSlideRight { from { transform: translateX(-100%); } to { transform: translateX(0); } }
@keyframes nspLeaveSlideRight { from { transform: translateX(0); } to { transform: translateX(100%); } }

.nsp-slide.is-entering[data-transition="slide-up"]    { animation-name: nspEnterSlideUp; }
.nsp-slide.is-leaving[data-transition="slide-up"]     { animation-name: nspLeaveSlideUp; }
@keyframes nspEnterSlideUp { from { transform: translateY(100%); } to { transform: translateY(0); } }
@keyframes nspLeaveSlideUp { from { transform: translateY(0); } to { transform: translateY(-100%); } }

.nsp-slide.is-entering[data-transition="slide-down"]  { animation-name: nspEnterSlideDown; }
.nsp-slide.is-leaving[data-transition="slide-down"]   { animation-name: nspLeaveSlideDown; }
@keyframes nspEnterSlideDown { from { transform: translateY(-100%); } to { transform: translateY(0); } }
@keyframes nspLeaveSlideDown { from { transform: translateY(0); } to { transform: translateY(100%); } }

/* ============================================================
   9-11. ZOOMS
   ============================================================ */
.nsp-slide.is-entering[data-transition="zoom-in"]  { animation-name: nspEnterZoomIn; }
.nsp-slide.is-leaving[data-transition="zoom-in"]   { animation-name: nspLeaveZoomIn; }
@keyframes nspEnterZoomIn { from { transform: scale(0.6); opacity: 0; } to { transform: scale(1); opacity: 1; } }
@keyframes nspLeaveZoomIn { from { transform: scale(1); opacity: 1; } to { transform: scale(1.3); opacity: 0; } }

.nsp-slide.is-entering[data-transition="zoom-out"] { animation-name: nspEnterZoomOut; }
.nsp-slide.is-leaving[data-transition="zoom-out"]  { animation-name: nspLeaveZoomOut; }
@keyframes nspEnterZoomOut { from { transform: scale(1.4); opacity: 0; } to { transform: scale(1); opacity: 1; } }
@keyframes nspLeaveZoomOut { from { transform: scale(1); opacity: 1; } to { transform: scale(0.7); opacity: 0; } }

.nsp-slide.is-entering[data-transition="zoom-blur"] { animation-name: nspEnterZoomBlur; }
.nsp-slide.is-leaving[data-transition="zoom-blur"]  { animation-name: nspLeaveZoomBlur; }
@keyframes nspEnterZoomBlur { from { transform: scale(1.3); opacity: 0; filter: blur(20px); } to { transform: scale(1); opacity: 1; filter: blur(0); } }
@keyframes nspLeaveZoomBlur { from { transform: scale(1); opacity: 1; filter: blur(0); } to { transform: scale(0.85); opacity: 0; filter: blur(20px); } }

/* ============================================================
   12-13. CUBE (3D rotation)
   ============================================================ */
.nsp-slide.is-entering[data-transition="cube-left"] { animation-name: nspEnterCubeLeft; transform-origin: left center; }
.nsp-slide.is-leaving[data-transition="cube-left"]  { animation-name: nspLeaveCubeLeft; transform-origin: right center; }
@keyframes nspEnterCubeLeft { from { transform: rotateY(90deg) translateZ(0); opacity: 0.5; } to { transform: rotateY(0) translateZ(0); opacity: 1; } }
@keyframes nspLeaveCubeLeft { from { transform: rotateY(0); opacity: 1; } to { transform: rotateY(-90deg); opacity: 0.5; } }

.nsp-slide.is-entering[data-transition="cube-right"] { animation-name: nspEnterCubeRight; transform-origin: right center; }
.nsp-slide.is-leaving[data-transition="cube-right"]  { animation-name: nspLeaveCubeRight; transform-origin: left center; }
@keyframes nspEnterCubeRight { from { transform: rotateY(-90deg); opacity: 0.5; } to { transform: rotateY(0); opacity: 1; } }
@keyframes nspLeaveCubeRight { from { transform: rotateY(0); opacity: 1; } to { transform: rotateY(90deg); opacity: 0.5; } }

/* ============================================================
   14-15. FLIP
   ============================================================ */
.nsp-slide.is-entering[data-transition="flip-horizontal"] { animation-name: nspEnterFlipH; }
.nsp-slide.is-leaving[data-transition="flip-horizontal"]  { animation-name: nspLeaveFlipH; }
@keyframes nspEnterFlipH { from { transform: rotateY(180deg); opacity: 0; } to { transform: rotateY(0); opacity: 1; } }
@keyframes nspLeaveFlipH { from { transform: rotateY(0); opacity: 1; } to { transform: rotateY(-180deg); opacity: 0; } }

.nsp-slide.is-entering[data-transition="flip-vertical"] { animation-name: nspEnterFlipV; }
.nsp-slide.is-leaving[data-transition="flip-vertical"]  { animation-name: nspLeaveFlipV; }
@keyframes nspEnterFlipV { from { transform: rotateX(180deg); opacity: 0; } to { transform: rotateX(0); opacity: 1; } }
@keyframes nspLeaveFlipV { from { transform: rotateX(0); opacity: 1; } to { transform: rotateX(-180deg); opacity: 0; } }

/* ============================================================
   16. FOLD
   ============================================================ */
.nsp-slide.is-entering[data-transition="fold"] { animation-name: nspEnterFold; transform-origin: left center; }
.nsp-slide.is-leaving[data-transition="fold"]  { animation-name: nspLeaveFold; transform-origin: right center; }
@keyframes nspEnterFold { from { transform: rotateY(-90deg); opacity: 0; } to { transform: rotateY(0); opacity: 1; } }
@keyframes nspLeaveFold { from { transform: rotateY(0); opacity: 1; } to { transform: rotateY(90deg); opacity: 0; } }

/* ============================================================
   17. ROTATE IN
   ============================================================ */
.nsp-slide.is-entering[data-transition="rotate-in"] { animation-name: nspEnterRotate; }
.nsp-slide.is-leaving[data-transition="rotate-in"]  { animation-name: nspLeaveRotate; }
@keyframes nspEnterRotate { from { transform: rotate(-12deg) scale(1.4); opacity: 0; } to { transform: rotate(0) scale(1); opacity: 1; } }
@keyframes nspLeaveRotate { from { transform: rotate(0) scale(1); opacity: 1; } to { transform: rotate(12deg) scale(1.4); opacity: 0; } }

/* ============================================================
   18-20. WIPES (clip-path)
   ============================================================ */
.nsp-slide.is-entering[data-transition="wipe-left"] { animation-name: nspEnterWipeLeft; }
.nsp-slide.is-leaving[data-transition="wipe-left"]  { animation-name: nspLeaveFade; }
@keyframes nspEnterWipeLeft { from { clip-path: inset(0 0 0 100%); } to { clip-path: inset(0 0 0 0); } }

.nsp-slide.is-entering[data-transition="wipe-right"] { animation-name: nspEnterWipeRight; }
.nsp-slide.is-leaving[data-transition="wipe-right"]  { animation-name: nspLeaveFade; }
@keyframes nspEnterWipeRight { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }

.nsp-slide.is-entering[data-transition="wipe-up"] { animation-name: nspEnterWipeUp; }
.nsp-slide.is-leaving[data-transition="wipe-up"]  { animation-name: nspLeaveFade; }
@keyframes nspEnterWipeUp { from { clip-path: inset(100% 0 0 0); } to { clip-path: inset(0 0 0 0); } }

/* ============================================================
   21. CIRCLE REVEAL
   ============================================================ */
.nsp-slide.is-entering[data-transition="circle-reveal"] { animation-name: nspEnterCircle; }
.nsp-slide.is-leaving[data-transition="circle-reveal"]  { animation-name: nspLeaveFade; }
@keyframes nspEnterCircle { from { clip-path: circle(0% at 50% 50%); } to { clip-path: circle(75% at 50% 50%); } }

/* ============================================================
   22-23. SPLITS
   ============================================================ */
.nsp-slide.is-entering[data-transition="split-vertical"] { animation-name: nspEnterSplitV; }
.nsp-slide.is-leaving[data-transition="split-vertical"]  { animation-name: nspLeaveFade; }
@keyframes nspEnterSplitV { from { clip-path: inset(0 50% 0 50%); } to { clip-path: inset(0 0 0 0); } }

.nsp-slide.is-entering[data-transition="split-horizontal"] { animation-name: nspEnterSplitH; }
.nsp-slide.is-leaving[data-transition="split-horizontal"]  { animation-name: nspLeaveFade; }
@keyframes nspEnterSplitH { from { clip-path: inset(50% 0 50% 0); } to { clip-path: inset(0 0 0 0); } }

/* ============================================================
   24. GLITCH
   ============================================================ */
.nsp-slide.is-entering[data-transition="glitch"] { animation-name: nspEnterGlitch; }
.nsp-slide.is-leaving[data-transition="glitch"]  { animation-name: nspLeaveFade; animation-duration: calc(var(--nsp-trans-dur) * 0.5); }
@keyframes nspEnterGlitch {
    0%   { opacity: 0; transform: translate(0); filter: hue-rotate(0); clip-path: inset(0 0 0 0); }
    10%  { opacity: 1; transform: translate(-8px, 4px); filter: hue-rotate(90deg); clip-path: inset(20% 0 30% 0); }
    20%  { transform: translate(8px, -4px); filter: hue-rotate(-90deg); clip-path: inset(60% 0 10% 0); }
    30%  { transform: translate(-6px, 2px); clip-path: inset(10% 0 60% 0); }
    40%  { transform: translate(6px, -2px); filter: hue-rotate(45deg); clip-path: inset(40% 0 40% 0); }
    50%  { transform: translate(0); filter: hue-rotate(0); clip-path: inset(0 0 0 0); }
    100% { opacity: 1; transform: translate(0); filter: none; clip-path: inset(0 0 0 0); }
}

/* ============================================================
   BLUR FADE
   ============================================================ */
.nsp-slide.is-entering[data-transition="blur-fade"] { animation-name: nspEnterBlurFade; }
.nsp-slide.is-leaving[data-transition="blur-fade"]  { animation-name: nspLeaveBlurFade; }
@keyframes nspEnterBlurFade { from { opacity: 0; filter: blur(30px); } to { opacity: 1; filter: blur(0); } }
@keyframes nspLeaveBlurFade { from { opacity: 1; filter: blur(0); } to { opacity: 0; filter: blur(30px); } }

/* ============================================================
   PARALLAX SLIDE — slide + bg moves at different speed
   ============================================================ */
.nsp-slide.is-entering[data-transition="parallax-slide"] { animation-name: nspEnterSlideLeft; }
.nsp-slide.is-leaving[data-transition="parallax-slide"]  { animation-name: nspLeaveParallax; }
.nsp-slide.is-entering[data-transition="parallax-slide"] .nsp-slide-bg { animation: nspParallaxBg var(--nsp-trans-dur) var(--nsp-trans-ease) both; }
@keyframes nspLeaveParallax { from { transform: translateX(0); } to { transform: translateX(-30%); } }
@keyframes nspParallaxBg { from { transform: scale(1.1) translateX(20%); } to { transform: scale(1.1) translateX(0); } }

/* ============================================================
   KEN BURNS FADE — fade + slow zoom on bg (great for hero)
   ============================================================ */
.nsp-slide.is-entering[data-transition="ken-burns-fade"] { animation-name: nspEnterFade; }
.nsp-slide.is-leaving[data-transition="ken-burns-fade"]  { animation-name: nspLeaveFade; }
.nsp-slide[data-transition="ken-burns-fade"].is-active .nsp-slide-bg { animation: nspKenBurnsZoom 8s ease-out both; }
@keyframes nspKenBurnsZoom { from { transform: scale(1); } to { transform: scale(1.15); } }

/* ============================================================
   REDUCED MOTION — respect user preference, fall back to fade
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
    .nsp-slide.is-entering,
    .nsp-slide.is-leaving {
        animation-name: nspEnterFade !important;
        animation-duration: 300ms !important;
    }
    .nsp-slide.is-leaving { animation-name: nspLeaveFade !important; }
    .nsp-slide-bg { animation: none !important; }
}
