/* ============================================================================
   ANIMATIONS.CSS — Todo el movimiento del sitio en un solo lugar
   ============================================================================
   Filosofía (la misma de Clay):
     · El movimiento explica, no decora. Cada animación revela jerarquía o
       causa-efecto.
     · Distancias cortas (16–32px), duraciones cortas (0.2–0.9s), curva expo-out.
     · Nada se mueve dos veces: los reveals ocurren una sola vez por elemento.
     · Todo se apaga con `prefers-reduced-motion` (ver el bloque final).

   CÓMO FUNCIONA EL SISTEMA DE REVEAL
   -----------------------------------
   1. Marca cualquier elemento con   data-reveal
   2. Elige la variante             data-reveal="up | fade | scale | left | right | blur"
   3. (Opcional) Cascada:           data-reveal-stagger  en el CONTENEDOR
      → main.js reparte --reveal-index a los hijos automáticamente.
   4. (Opcional) Retraso manual:    style="--reveal-delay: 200ms"
   El IntersectionObserver de main.js añade .is-inview y dispara la transición.
   ========================================================================== */


/* ==========================================================================
   1. SISTEMA DE REVEAL AL SCROLL
   ====================================================================== */

/* RED DE SEGURIDAD — leer antes de tocar el reveal.
   Todo lo animado parte de opacity:0 y solo lo levanta el JS al añadir
   .is-inview. Si el JS no corre (bloqueado, error en cualquier módulo del
   arranque, navegador viejo) la página entera se queda invisible: hero, textos,
   eventos, footer. Esta regla es lo que evita eso. El <html> nace con .no-js y
   un script en el <head> se la quita antes del primer paint; si ese script
   nunca corre, la clase se queda y aquí se muestra todo sin animación.
   No borres esto sin sustituirlo por otra salvaguarda. */
.no-js [data-reveal],
.no-js [data-split-lines],
.no-js .mock,
.no-js .stat {
  opacity: 1 !important;
  transform: none !important;
  filter: none !important;
}

[data-reveal] {
  opacity: 0;
  transition:
    opacity   var(--dur-slow) var(--ease-out),
    transform var(--dur-slow) var(--ease-out),
    filter    var(--dur-slow) var(--ease-out);
  /* El retraso combina el manual con el de la cascada */
  transition-delay: calc(
    var(--reveal-delay, 0ms) + var(--reveal-index, 0) * var(--reveal-stagger)
  );
  /* Sin `will-change` a propósito: hay ~60 elementos con data-reveal y
     declararlo aquí crearía 60 capas de composición desde el primer pintado.
     El navegador ya promociona el elemento al iniciar la transición. */
}

[data-reveal="up"],
[data-reveal=""]        { transform: translateY(var(--reveal-distance)); }
[data-reveal="down"]    { transform: translateY(calc(var(--reveal-distance) * -1)); }
[data-reveal="left"]    { transform: translateX(calc(var(--reveal-distance) * -1)); }
[data-reveal="right"]   { transform: translateX(var(--reveal-distance)); }
[data-reveal="scale"]   { transform: scale(0.94); }
[data-reveal="blur"]    { filter: blur(10px); transform: translateY(12px); }
[data-reveal="fade"]    { transform: none; }

[data-reveal].is-inview {
  opacity: 1;
  transform: none;
  filter: none;
}

/* ==========================================================================
   2. TITULAR POR LÍNEAS
   --------------------------------------------------------------------------
   main.js → splitHeadline() envuelve cada línea en .line > .line__inner.
   Las líneas suben desde detrás de una máscara, en cascada. Es la entrada
   del H1 del hero.
   ====================================================================== */

/* La máscara necesita overflow:hidden, pero con line-height:1 eso recortaría
   los descendentes (g, j, p, y). El padding da aire por abajo y el margen
   negativo lo devuelve, así el interlineado visual no cambia. */
.split-line {
  display: block;
  overflow: hidden;
  padding-bottom: 0.14em;
  margin-bottom: -0.14em;
}
.split-line__inner {
  display: block;
  transform: translateY(105%);
  transition: transform var(--dur-slower) var(--ease-out);
  transition-delay: calc(var(--line-index, 0) * 90ms);
}
.is-inview .split-line__inner,
.split-lines.is-inview .split-line__inner { transform: translateY(0); }


/* ==========================================================================
   3. KEYFRAMES
   ====================================================================== */

/* Marquee infinito: la pista contiene 2 grupos idénticos → -50% = 1 vuelta */
@keyframes marquee-scroll {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

/* Entrada de panel de tabs */
@keyframes tab-in {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Punto "en vivo" */
@keyframes pulse-dot {
  0%, 100% { opacity: 1;   transform: scale(1); }
  50%      { opacity: 0.4; transform: scale(0.8); }
}

/* Flotación suave — ilustraciones del hero y de los pilares */
@keyframes float-y {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-10px); }
}

/* Rotación lenta continua — engranajes */
@keyframes spin-slow {
  to { transform: rotate(360deg); }
}

/* Bola que recorre el tubo del hero (usa offset-path en el SVG) */
@keyframes travel {
  from { offset-distance: 0%; }
  to   { offset-distance: 100%; }
}

/* Cruce entre las fotos del hero. Cuatro fotos, ciclo de 32s: cada una
   visible unos 7s con 1s de fundido. Si añades o quitas fotos, ajusta los
   porcentajes y los animation-delay en sections.css. */
@keyframes hero-cross {
  0%          { opacity: 1; }
  22%         { opacity: 1; }
  25%         { opacity: 0; }
  97%         { opacity: 0; }
  100%        { opacity: 1; }
}

/* Zoom imperceptible sobre la foto activa */
@keyframes hero-zoom {
  0%   { transform: scale(1.06); }
  25%  { transform: scale(1); }
  100% { transform: scale(1.06); }
}

/* Halo que respira detrás del hero */
@keyframes breathe {
  0%, 100% { transform: scale(1);    opacity: 0.55; }
  50%      { transform: scale(1.08); opacity: 0.8; }
}

/* Aparición del header al hacer scroll hacia arriba */
@keyframes slide-down {
  from { transform: translateY(-100%); }
  to   { transform: translateY(0); }
}

/* Brillo que barre un elemento (badge del anuncio) */
@keyframes shimmer {
  from { background-position: 200% 0; }
  to   { background-position: -200% 0; }
}


/* ==========================================================================
   4. CLASES DE ANIMACIÓN CONTINUA
   ====================================================================== */

.anim-float      { animation: float-y 6s var(--ease-in-out) infinite; }
.anim-float--alt { animation: float-y 7.5s var(--ease-in-out) infinite reverse; }
.anim-spin       { animation: spin-slow 18s linear infinite; transform-origin: center; }
.anim-spin--slow { animation-duration: 40s; }
.anim-breathe    { animation: breathe 9s var(--ease-in-out) infinite; }

/* --- Bolas que viajan por el tubo del hero -------------------------------
   `offset-path` hace que el elemento siga una curva. La `path()` debe ser
   IDÉNTICA a la del <path id="tube-path"> del SVG en index.html: si cambias
   el dibujo del tubo, copia aquí la misma cadena de coordenadas.

   Las bolas se ocultan por defecto y solo aparecen si el navegador soporta
   offset-path (Safari es irregular con SVG). Sin este @supports quedarían
   apiladas en la esquina 0,0 del viewBox, que es un fallo muy visible.
   OJO: no les pongas cx/cy — con offset-path activo se suman a la posición
   de la curva y las mandan fuera del tubo. */
.travel-ball { opacity: 0; }

@supports (offset-path: path("M0 0 L1 1")) {
  .travel-ball {
    opacity: 1;
    offset-path: path("M300 258 C 300 350, 466 350, 466 252 C 466 186, 620 186, 620 264 L 620 336");
    offset-rotate: 0deg;
    animation: travel 4.5s linear infinite;
  }
  .travel-ball--2 { animation-delay: 1.5s; }
  .travel-ball--3 { animation-delay: 3s; }
}

/* Retrasos utilitarios para desincronizar elementos hermanos */
.delay-1 { animation-delay: 0.4s; }
.delay-2 { animation-delay: 0.8s; }
.delay-3 { animation-delay: 1.2s; }
.delay-4 { animation-delay: 1.6s; }


/* ==========================================================================
   5. HOVER / MICRO-INTERACCIONES
   ====================================================================== */

.hover-lift { transition: transform var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out); }
.hover-lift:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); }

.hover-tilt { transition: transform var(--dur-base) var(--ease-spring); }
.hover-tilt:hover { transform: rotate(-1.5deg) scale(1.02); }

/* Subrayado que crece desde la izquierda */
.hover-underline { position: relative; }
.hover-underline::after {
  content: ""; position: absolute; left: 0; bottom: -2px; height: 1px; width: 100%;
  background: currentColor; transform: scaleX(0); transform-origin: left;
  transition: transform var(--dur-base) var(--ease-out);
}
.hover-underline:hover::after { transform: scaleX(1); }


/* ==========================================================================
   6. PARALLAX
   --------------------------------------------------------------------------
   main.js escribe --parallax-y (px) en cada [data-parallax] durante el scroll,
   usando requestAnimationFrame. data-parallax="0.15" = 15% de la velocidad.
   ====================================================================== */

[data-parallax] {
  transform: translate3d(0, var(--parallax-y, 0), 0);
  will-change: transform;
}


/* ==========================================================================
   7. CONTADORES
   --------------------------------------------------------------------------
   <span data-count-to="140" data-count-prefix="+" data-count-suffix="%">
   main.js interpola el número cuando entra en viewport.
   `tabular-nums` evita que el ancho salte mientras cuenta.
   ====================================================================== */

[data-count-to] { font-variant-numeric: tabular-nums; }


/* ==========================================================================
   8. ACCESIBILIDAD — respetar "reducir movimiento"
   --------------------------------------------------------------------------
   Con esta preferencia activa el sitio sigue siendo 100% funcional: los
   elementos aparecen ya visibles, sin desplazamiento ni bucles infinitos.
   NO borres este bloque.
   ====================================================================== */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  [data-reveal] { opacity: 1 !important; transform: none !important; filter: none !important; }
  .split-line__inner { transform: none !important; }
  .marquee__track { animation: none !important; }
  [data-parallax] { transform: none !important; }
  .anim-float, .anim-float--alt, .anim-spin, .anim-breathe { animation: none !important; }
  /* Sin el carrusel, solo se ve la primera foto (las demás nacen en opacity:0) */
  .hero__slide { animation: none !important; }
  .hero__slide img { animation: none !important; transform: none !important; }
}
