/* ==========================================================================
   Animaciones — entrada inicial, revelado al hacer scroll y microinteracciones.
   Las de scroll las activa IntersectionObserver añadiendo .is-visible.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Revelado al entrar en el viewport
   El estado inicial sólo se aplica si JavaScript está disponible (html.js);
   sin JS el contenido se ve normal, nunca invisible.
   -------------------------------------------------------------------------- */
.js [data-reveal] {
    opacity: 0;
    transform: translateY(18px);
    transition:
        opacity var(--duration-slow) var(--ease-out),
        transform var(--duration-slow) var(--ease-out);
}

.js [data-reveal='fade'] {
    transform: none;
}

.js [data-reveal='left'] {
    transform: translateX(-22px);
}

.js [data-reveal='right'] {
    transform: translateX(22px);
}

.js [data-reveal='scale'] {
    transform: scale(0.97);
}

.js [data-reveal].is-visible {
    opacity: 1;
    transform: none;
}

/* Escalonado de hijos: hasta ocho elementos, 70 ms entre cada uno. */
.js [data-reveal-group] > * {
    opacity: 0;
    transform: translateY(16px);
    transition:
        opacity var(--duration-slow) var(--ease-out),
        transform var(--duration-slow) var(--ease-out);
}

.js [data-reveal-group].is-visible > * {
    opacity: 1;
    transform: none;
}

.js [data-reveal-group].is-visible > *:nth-child(1) { transition-delay: 0ms; }
.js [data-reveal-group].is-visible > *:nth-child(2) { transition-delay: 70ms; }
.js [data-reveal-group].is-visible > *:nth-child(3) { transition-delay: 140ms; }
.js [data-reveal-group].is-visible > *:nth-child(4) { transition-delay: 210ms; }
.js [data-reveal-group].is-visible > *:nth-child(5) { transition-delay: 280ms; }
.js [data-reveal-group].is-visible > *:nth-child(6) { transition-delay: 350ms; }
.js [data-reveal-group].is-visible > *:nth-child(7) { transition-delay: 420ms; }
.js [data-reveal-group].is-visible > *:nth-child(8) { transition-delay: 490ms; }

/* --------------------------------------------------------------------------
   Entrada del hero — secuencia completa por debajo de 1.2 s

   Arranca con .is-ready, que añade preloader.js al retirar la pantalla de
   bienvenida. Sin esa clase no hay animación y el contenido se ve tal cual:
   si el script fallara, la portada seguiría siendo perfectamente legible.
   -------------------------------------------------------------------------- */
/*
 * Cada pieza entra con el gesto que le corresponde, no todas con el mismo:
 *
 *   barra        aparece bajando           0 ms
 *   etiqueta     crece desde el 94 %      60 ms
 *   titular      asoma línea a línea     120 / 215 ms
 *   subtítulo    sube y aparece          330 ms
 *   botones      escalonados             420 / 495 ms
 *   filete       se traza de izq. a der. 500 ms
 *   beneficios   escalonados             570 ms + 55 ms cada uno
 *   globo        crece y se posa         150 ms (1,3 s)
 *
 * Los primeros 250 ms se solapan con el desvanecido del velo, así que la
 * portada nunca se ve vacía. Todo termina antes de 1,5 s. `backwards` mantiene el estado inicial durante
 * la espera; sin la clase .is-ready no hay animación y la página se ve tal cual.
 */
.js.is-ready .header {
    animation: intro-header var(--duration-slow) var(--ease-out) backwards;
}

.js.is-ready .hero__badge {
    animation: intro-pop 620ms var(--ease-reveal) backwards;
    animation-delay: 60ms;
}

/* Revelado con máscara: el texto sube desde debajo de su propia línea. */
.js.is-ready .hero__line-in {
    animation: intro-mask 900ms var(--ease-reveal) backwards;
}

.js.is-ready .hero__line:nth-child(1) .hero__line-in { animation-delay: 120ms; }
.js.is-ready .hero__line:nth-child(2) .hero__line-in { animation-delay: 215ms; }

.js.is-ready .hero__subtitle {
    animation: intro-up var(--duration-slower) var(--ease-out) backwards;
    animation-delay: 330ms;
}

.js.is-ready .hero__actions .btn {
    animation: intro-up 620ms var(--ease-out) backwards;
}

.js.is-ready .hero__actions .btn:nth-child(1) { animation-delay: 420ms; }
.js.is-ready .hero__actions .btn:nth-child(2) { animation-delay: 495ms; }

.js.is-ready .hero__benefits::before {
    animation: intro-line 820ms var(--ease-reveal) backwards;
    animation-delay: 500ms;
}

.js.is-ready .hero__benefit {
    animation: intro-up 560ms var(--ease-out) backwards;
}

.js.is-ready .hero__benefit:nth-child(1) { animation-delay: 570ms; }
.js.is-ready .hero__benefit:nth-child(2) { animation-delay: 625ms; }
.js.is-ready .hero__benefit:nth-child(3) { animation-delay: 680ms; }
.js.is-ready .hero__benefit:nth-child(4) { animation-delay: 735ms; }

.js.is-ready .hero__visual {
    animation: intro-scale 1300ms var(--ease-reveal) backwards;
    animation-delay: 150ms;
}

/* La plataforma se abre por debajo del globo, un poco después que él. */
.js.is-ready .hero__pedestal {
    animation: intro-pedestal 1200ms var(--ease-out) backwards;
    animation-delay: 400ms;
}

/* El globo entra creciendo un poco: refuerza la sensación de que "aterriza". */
@keyframes intro-scale {
    from {
        opacity: 0;
        transform: scale(0.92);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

/* 105 % y no 100 %: así el trazo descendente queda fuera de la ventana. */
@keyframes intro-mask {
    from {
        transform: translateY(105%);
    }

    to {
        transform: none;
    }
}

@keyframes intro-line {
    from {
        transform: scaleX(0);
    }

    to {
        transform: none;
    }
}

@keyframes intro-pop {
    from {
        opacity: 0;
        transform: scale(0.94) translateY(6px);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

@keyframes intro-pedestal {
    from {
        opacity: 0;
        /* El translateX es la posición de reposo del pedestal, no parte del gesto. */
        transform: translateX(-50%) scale(0.72);
    }

    to {
        opacity: 1;
        transform: translateX(-50%) scale(1);
    }
}

@keyframes intro-header {
    from {
        opacity: 0;
        transform: translateY(-10px);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

@keyframes intro-up {
    from {
        opacity: 0;
        transform: translateY(18px);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

@keyframes intro-fade {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

/* --------------------------------------------------------------------------
   Piezas sueltas
   -------------------------------------------------------------------------- */
@keyframes spin {
    to {
        transform: rotate(360deg);
    }
}

@keyframes orbit-spin {
    from {
        transform: rotate(0deg);
    }

    to {
        transform: rotate(360deg);
    }
}

@keyframes bar-rise {
    from {
        transform: scaleY(0.1);
        opacity: 0;
    }

    to {
        transform: scaleY(1);
        opacity: 0.85;
    }
}

/*
 * En pantallas estrechas el desplazamiento lateral inicial (22 px) supera al
 * margen del contenedor (20 px) y añadía 2 px de scroll horizontal antes de
 * revelarse. Ahí el movimiento pasa a ser vertical.
 */
@media (max-width: 768px) {
    .js [data-reveal='left'],
    .js [data-reveal='right'] {
        transform: translateY(16px);
    }
}

/* Con movimiento reducido las órbitas se detienen en su posición inicial. */
@media (prefers-reduced-motion: reduce) {
    .orbit__track,
    .orbit__node-inner {
        animation: none;
    }

    .js [data-reveal],
    .js [data-reveal-group] > * {
        opacity: 1;
        transform: none;
    }
}
