/* ════════════════════════════════════════════════════════════════
   SPARTAN · LOADING EFFECTS
   Sistema de entrada: Hero (stagger al cargar) + Scroll-reveal
   Solo opacity + transform → GPU compositing, sin reflow
   ════════════════════════════════════════════════════════════════ */

/* ── Variables de timing (ajusta aquí, no en cada regla) ── */
:root {
  --spartan-ease: cubic-bezier(.16, 1, .3, 1);   /* salida rápida, frenado preciso: sensación "táctica" */
  --spartan-dur: .35s;                            /* duración única < 0.4s exigido */
  --spartan-rise: 16px;                           /* desplazamiento vertical, dentro del rango 15-20px */
  --spartan-rise-sm: 10px;                        /* desplazamiento más sutil para tarjetas pequeñas */
}

/* ════════════════════════════════════════════════════════════════
   1) HERO · Staggered Fade-In + Slide-Up
   Se dispara SOLO al cargar la página (no depende de scroll).
   No requiere JS: el estado inicial y la transición están en CSS;
   basta con añadir la clase .is-loaded al <body> (ver JS, 3 líneas).
   ════════════════════════════════════════════════════════════════ */

.hero-item {
  opacity: 0;
  transform: translateY(var(--spartan-rise));
  transition: opacity var(--spartan-dur) var(--spartan-ease),
              transform var(--spartan-dur) var(--spartan-ease);
  will-change: opacity, transform;
}

/* Orden de aparición · escalonado por data-attribute, no por nth-child,
   porque nav / h1 / subtítulo / CTA viven en contenedores distintos */
.hero-item[data-step="1"] { transition-delay: .00s; } /* Nav / Logo */
.hero-item[data-step="2"] { transition-delay: .10s; } /* H1 */
.hero-item[data-step="3"] { transition-delay: .18s; } /* Subtítulo */
.hero-item[data-step="4"] { transition-delay: .26s; } /* CTA */

/* Estado final: lo añade JS en cuanto el DOM está listo */
body.is-loaded .hero-item {
  opacity: 1;
  transform: translateY(0);
}

/* Quita will-change una vez terminada la animación de entrada,
   para no dejar capas GPU innecesarias colgando en memoria */
body.is-loaded .hero-item {
  transition-property: opacity, transform;
}

/* ════════════════════════════════════════════════════════════════
   2) SCROLL-REVEAL · Fade-In + micro slide-up al entrar en viewport
   Requiere IntersectionObserver (ver JS). Progressive enhancement:
   si JS no carga, .reveal permanece visible por defecto (regla base).
   ════════════════════════════════════════════════════════════════ */

.reveal {
  opacity: 1;
  transform: none;
}

/* Solo se oculta si JS confirma que puede revelarlo después */
html.js .reveal {
  opacity: 0;
  transform: translateY(var(--spartan-rise-sm));
  transition: opacity var(--spartan-dur) var(--spartan-ease),
              transform var(--spartan-dur) var(--spartan-ease);
  will-change: opacity, transform;
}

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

/* Stagger opcional dentro de un mismo grid/lista (tarjetas Arsenal,
   bloques de datos científicos). Añade .reveal-group al contenedor
   padre y deja que esto escalone automáticamente los hijos directos */
html.js .reveal-group > .reveal:nth-child(1) { transition-delay: .00s; }
html.js .reveal-group > .reveal:nth-child(2) { transition-delay: .05s; }
html.js .reveal-group > .reveal:nth-child(3) { transition-delay: .10s; }
html.js .reveal-group > .reveal:nth-child(4) { transition-delay: .15s; }
html.js .reveal-group > .reveal:nth-child(5) { transition-delay: .20s; }
html.js .reveal-group > .reveal:nth-child(6) { transition-delay: .25s; }
/* a partir del 7º, sin delay extra para no alargar la espera percibida */

/* ════════════════════════════════════════════════════════════════
   3) ASSEMBLE · "la web se está montando" (BIDIRECCIONAL)
   Diferencia clave con .reveal: .reveal se dispara UNA vez y se
   queda fijo (unobserve). .assemble se activa y se retira cada vez
   que el elemento cruza el viewport, en cualquier sentido del
   scroll, así que el efecto se repite también al subir.
   Reutiliza las mismas variables de timing (--spartan-ease,
   --spartan-dur, --spartan-rise) para sentirse parte del mismo
   sistema visual, no un añadido aparte.
   Se aplica vía JS (ver punto 4 del JS) a bloques de contenido
   genéricos — no requiere tocar el HTML de cada pieza a mano.
   ════════════════════════════════════════════════════════════════ */

/* Variables propias del ASSEMBLE — más lentas y suaves que el resto
   (--spartan-ease/--spartan-dur son "tácticas": rápidas y secas,
   pensadas para hero/reveal de un solo disparo). Como .assemble se
   repite constantemente al hacer scroll, necesita una curva más
   suave para no resultar brusco ni cansar la vista. */
:root {
  --spartan-ease-soft: cubic-bezier(.25, .8, .25, 1);
  --spartan-dur-soft: .6s;
}

.assemble { opacity: 1; transform: none; }

html.js .assemble {
  opacity: 0;
  transform: translateY(calc(var(--spartan-rise) * .7)) scale(.99);
  transition: opacity var(--spartan-dur-soft) var(--spartan-ease-soft),
              transform var(--spartan-dur-soft) var(--spartan-ease-soft);
  will-change: opacity, transform;
}

/* Variantes de "pieza" para que el montaje no sea siempre vertical
   (útil para imágenes o tarjetas de producto a ambos lados) */
html.js .assemble.assemble-left  { transform: translateX(calc(var(--spartan-rise) * -1)) scale(.99); }
html.js .assemble.assemble-right { transform: translateX(calc(var(--spartan-rise) *  1)) scale(.99); }

html.js .assemble.is-visible {
  opacity: 1;
  transform: none;
}

/* Stagger para grupos de piezas que "encajan" a la vez (tarjetas de
   producto, listas de datos). Mismo patrón que .reveal-group, pero
   con un poco más de aire entre cada una para que se note el orden. */
html.js .assemble-group > .assemble:nth-child(1) { transition-delay: .00s; }
html.js .assemble-group > .assemble:nth-child(2) { transition-delay: .08s; }
html.js .assemble-group > .assemble:nth-child(3) { transition-delay: .16s; }
html.js .assemble-group > .assemble:nth-child(4) { transition-delay: .24s; }
html.js .assemble-group > .assemble:nth-child(5) { transition-delay: .32s; }
html.js .assemble-group > .assemble:nth-child(6) { transition-delay: .40s; }

/* ════════════════════════════════════════════════════════════════
   4) Accesibilidad: usuarios con preferencia de movimiento reducido
   ven el contenido directamente, sin animación de ningún tipo.
   ════════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {
  .hero-item,
  html.js .reveal,
  html.js .assemble {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
}
