/* ============================================================
   IDEALUM — animaciones.css
   Motor de animaciones reutilizable. Se puede incluir en
   cualquier página junto con su CSS propio.

   USO RÁPIDO
   ----------
   Entrada al hacer scroll (elige una):
     <div data-anim="fade-up">        ← sube
     <div data-anim="fade-left">      ← entra desde la izquierda
     <div data-anim="fade-right">     ← entra desde la derecha
     <div data-anim="zoom">           ← escala
     <div data-anim="flip">           ← gira en 3D
     <div data-anim="mask">           ← se descubre como cortina

   Retraso escalonado (para rejillas):
     style="--d: 120ms;"

   Texto palabra por palabra:
     <h2 data-split="words">Mi título</h2>

   Contador numérico:
     <span data-count="1250" data-suffix="+">0</span>
   ============================================================ */

/* ══════════════════════════════════════════════
   ENTRADAS AL HACER SCROLL
══════════════════════════════════════════════ */
[data-anim] {
    transition:
        opacity .75s cubic-bezier(.22, .61, .36, 1),
        transform .75s cubic-bezier(.22, .61, .36, 1),
        clip-path .9s cubic-bezier(.22, .61, .36, 1);
    transition-delay: var(--d, 0ms);
    will-change: opacity, transform;
}

.has-js [data-anim] {
    opacity: 0;
}

.has-js [data-anim="fade-up"] {
    transform: translateY(42px);
}

.has-js [data-anim="fade-down"] {
    transform: translateY(-42px);
}

.has-js [data-anim="fade-left"] {
    transform: translateX(-48px);
}

.has-js [data-anim="fade-right"] {
    transform: translateX(48px);
}

.has-js [data-anim="zoom"] {
    transform: scale(.88);
}

.has-js [data-anim="flip"] {
    transform: perspective(900px) rotateX(-32deg);
    transform-origin: center bottom;
}

.has-js [data-anim="mask"] {
    opacity: 1;
    clip-path: inset(0 100% 0 0);
}

[data-anim].is-visible {
    opacity: 1;
    transform: none;
    clip-path: inset(0 0 0 0);
}

/* Compatibilidad con las clases .reveal / .reveal-fade */
.reveal {
    transition: opacity .6s cubic-bezier(.22, .61, .36, 1), transform .6s cubic-bezier(.22, .61, .36, 1);
    transition-delay: var(--d, 0ms);
    will-change: opacity, transform;
}

.has-js .reveal {
    opacity: 0;
    transform: translateY(24px);
}

.reveal.is-visible {
    opacity: 1;
    transform: translateY(0);
}

.reveal-fade {
    transition: opacity .5s ease;
    transition-delay: var(--d, 0ms);
}

.has-js .reveal-fade {
    opacity: 0;
}

.reveal-fade.is-visible {
    opacity: 1;
}

/* ══════════════════════════════════════════════
   TEXTO PALABRA POR PALABRA
   Se usa @keyframes (no transition) porque los .word-inner
   los crea JavaScript: un elemento que nace ya coincidiendo
   con el estado final nunca dispara una transición.
══════════════════════════════════════════════ */
.word-mask {
    display: inline-block;
    overflow: hidden;
    vertical-align: top;
}

.word-mask .word-inner {
    display: inline-block;
    transform: translateY(105%);
    will-change: transform;
}

.is-visible .word-inner,
.hero-slide.active .word-inner {
    animation: wordUp .6s cubic-bezier(.22, .61, .36, 1) both;
    animation-delay: var(--wd, 0ms);
}

/* Los títulos del slider vuelven a su posición inicial cuando el
   slide no está activo, para que la animación se repita en cada
   cambio de slide (su especificidad gana sobre .is-visible). */
.hero-slide:not(.active) .word-inner {
    animation: none;
    transform: translateY(105%);
}

@keyframes wordUp {
    from {
        transform: translateY(105%);
    }

    to {
        transform: translateY(0);
    }
}

/* ══════════════════════════════════════════════
   BOTONES CON BARRIDO
══════════════════════════════════════════════ */
.btn-sweep {
    position: relative;
    overflow: hidden;
    isolation: isolate;
}

.btn-sweep::before {
    content: '';
    position: absolute;
    inset: 0;
    background: currentColor;
    opacity: .12;
    transform: translateX(-101%);
    transition: transform .38s cubic-bezier(.22, .61, .36, 1);
    z-index: -1;
}

.btn-sweep:hover::before {
    transform: translateX(0);
}

/* ══════════════════════════════════════════════
   ENLACES CON SUBRAYADO ANIMADO
══════════════════════════════════════════════ */
.link-underline {
    position: relative;
    padding-bottom: 3px;
}

.link-underline::after {
    content: '';
    position: absolute;
    left: 0;
    bottom: 0;
    width: 100%;
    height: 1.5px;
    background: currentColor;
    transform: scaleX(0);
    transform-origin: right center;
    transition: transform .35s cubic-bezier(.22, .61, .36, 1);
}

.link-underline:hover::after {
    transform: scaleX(1);
    transform-origin: left center;
}

/* ══════════════════════════════════════════════
   ACCESIBILIDAD
══════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {

    *,
    *::before,
    *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
        scroll-behavior: auto !important;
    }

    .has-js [data-anim] {
        opacity: 1;
        transform: none;
        clip-path: none;
    }
}