/* ==========================================================================
   WS Animation Texte - effets par lettre/mot/ligne
   - Apparition controlee par data-ws-text-anim sur le wrapper (h2, p, etc.)
   - Le JS handler split le texte (chars/words/lines) en spans .ws-text-char
   - CSS = etats par defaut + effets purs CSS (ceux qui n'ont pas besoin de JS)
   - GSAP/JS = effets complexes (cascade, glitch, scramble, magnetic, etc.)
   ========================================================================== */

[data-ws-text-anim] {
    --ws-text-anim-accent: #6366f1;
    /* Important : isole le contexte pour les transforms 3D */
    perspective: 1000px;
}

/* Container des splits : empeche les espaces parasites entre spans */
.ws-text-char,
.ws-text-word,
.ws-text-line {
    display: inline-block;
    will-change: transform, opacity, filter;
    /* Default invisible avant l'animation - GSAP override */
    backface-visibility: hidden;
}

/* Espaces entre mots preserves quand split=chars */
.ws-text-char.ws-text-char--space {
    width: 0.25em;
}

/* Pour wave-loop et magnetic (effets continus) */
.ws-text-char {
    transform-origin: 50% 100%;
}

/* === EFFET WAVE LOOP (CSS pur, animation infinie) ===
   Chaque char ondule en boucle. Le JS pose --ws-char-index sur chaque char
   pour decaler l'animation. Plus de details : ws-text-animations.js */
[data-ws-text-anim="wave-loop"] .ws-text-char,
[data-ws-text-continuous="wave-loop"] .ws-text-char {
    animation: ws-text-wave-loop var(--ws-text-cont-speed, 2s) ease-in-out infinite;
    animation-delay: calc(var(--ws-char-index, 0) * 0.06s);
    color: var(--ws-text-anim-accent, currentColor);
}

@keyframes ws-text-wave-loop {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-0.2em); }
}

/* === EFFET TYPEWRITER (CSS pur, curseur) ===
   Caret clignotant a la fin du texte. Les chars sont reveles via JS (display:none -> inline-block). */
[data-ws-text-anim="typewriter"]::after {
    content: "|";
    display: inline-block;
    margin-left: 2px;
    animation: ws-text-typewriter-caret 0.8s steps(1) infinite;
    color: var(--ws-text-anim-accent, currentColor);
}

@keyframes ws-text-typewriter-caret {
    0%, 50%   { opacity: 1; }
    51%, 100% { opacity: 0; }
}

/* === EFFET SCROLL FILL (CSS + IntersectionObserver) ===
   La couleur du texte se "remplit" depuis la couleur de base vers --ws-text-anim-accent
   au fur et a mesure du scroll. Apple-style hero text. */
[data-ws-text-anim="scroll-fill"],
[data-ws-text-continuous="scroll-fill"] {
    /* Deux couleurs superposees via background-clip: text */
    background: linear-gradient(
        to right,
        var(--ws-text-anim-accent) 0%,
        var(--ws-text-anim-accent) var(--ws-scroll-fill-progress, 0%),
        currentColor var(--ws-scroll-fill-progress, 0%),
        currentColor 100%
    );
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
    transition: none; /* le JS update --ws-scroll-fill-progress en temps reel */
}

/* === EFFET HOVER WAVE (CSS pur via :hover + transition delay variable) ===
   Au survol du wrapper, chaque char monte avec un delai progressif puis redescend. */
[data-ws-text-anim="hover-wave"] .ws-text-char,
[data-ws-text-continuous="hover-wave"] .ws-text-char {
    transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}

[data-ws-text-anim="hover-wave"]:hover .ws-text-char,
[data-ws-text-continuous="hover-wave"]:hover .ws-text-char {
    transform: translateY(-0.3em);
    transition-delay: calc(var(--ws-char-index, 0) * 0.04s);
}

/* === EFFET MAGNETIC (CSS pur via :hover transform local) ===
   JS gere le tracking souris fine. CSS fournit la transition smooth. */
[data-ws-text-anim="magnetic"] .ws-text-char,
[data-ws-text-continuous="magnetic"] .ws-text-char {
    transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
    /* Le JS pose --ws-mag-x et --ws-mag-y per char */
    transform: translate(var(--ws-mag-x, 0), var(--ws-mag-y, 0));
}

/* === FALLBACK : etat invisible avant que JS prenne la main ===
   Pour les effets qui necessitent JS (cascade, glitch, scramble, blur-stagger,
   roll-in, random-fly, flip-3d), on cache le contenu pendant ~200ms puis JS
   declenche l'apparition. Si JS echoue, fallback FOUC: opacity 1 apres 1s. */
[data-ws-text-anim="cascade"]:not(.ws-text-anim-ready),
[data-ws-text-anim="glitch-reveal"]:not(.ws-text-anim-ready),
[data-ws-text-anim="scramble"]:not(.ws-text-anim-ready),
[data-ws-text-anim="blur-stagger"]:not(.ws-text-anim-ready),
[data-ws-text-anim="roll-in"]:not(.ws-text-anim-ready),
[data-ws-text-anim="random-fly"]:not(.ws-text-anim-ready),
[data-ws-text-anim="flip-3d"]:not(.ws-text-anim-ready),
[data-ws-text-anim="mask-reveal"]:not(.ws-text-anim-ready),
[data-ws-text-anim="wave"]:not(.ws-text-anim-ready) {
    opacity: 0;
}

/* Marqueur "ready" : pose par le JS quand SplitText + GSAP ont charge */
[data-ws-text-anim].ws-text-anim-ready {
    opacity: 1;
}

/* Fallback timer : si pas ready apres 2s (JS error / GSAP non charge), revele quand meme */
@keyframes ws-text-anim-fallback-reveal {
    0%, 99% { opacity: 0; }
    100%    { opacity: 1; }
}

[data-ws-text-anim]:not(.ws-text-anim-ready) {
    animation: ws-text-anim-fallback-reveal 2s steps(1) forwards;
}

[data-ws-text-anim].ws-text-anim-ready {
    animation: none;
}

/* Respect prefers-reduced-motion : desactive toutes les anims continues */
@media (prefers-reduced-motion: reduce) {
    [data-ws-text-anim="wave-loop"] .ws-text-char,
    [data-ws-text-continuous="wave-loop"] .ws-text-char,
    [data-ws-text-anim="typewriter"]::after,
    [data-ws-text-anim="hover-wave"] .ws-text-char,
    [data-ws-text-continuous="hover-wave"] .ws-text-char,
    [data-ws-text-anim="magnetic"] .ws-text-char,
    [data-ws-text-continuous="magnetic"] .ws-text-char {
        animation: none !important;
        transition: none !important;
        transform: none !important;
    }
}
