/* ══════════════════════════════════════════════════════════════════
   GINNOA · Landing Scroll FX — capa de animación del home
   Acompaña a /assets/js/core/landing-scroll.js

   Todo el estado "oculto" vive bajo `html.fx-on`, clase que SOLO añade
   ese script. Si el JS no carga, no se aplica ningún ocultamiento y la
   página se ve completa. Nada aquí depende de librerías externas.
   ══════════════════════════════════════════════════════════════════ */

/* ───────── 1 · Barra de progreso de lectura ───────── */
.scroll-progress {
  position: fixed;
  inset: 0 0 auto 0;
  height: 3px;
  z-index: 2000;
  pointer-events: none;
  background: rgba(0, 34, 30, 0.08);
}
.scroll-progress__fill {
  display: block;
  height: 100%;
  transform: scaleX(0);
  transform-origin: 0 50%;
  background: linear-gradient(90deg, #00665c 0%, #65beac 45%, #ffcc00 100%);
  box-shadow: 0 0 10px rgba(255, 204, 0, 0.5);
  will-change: transform;
}

/* ───────── 2 · Hero: salida cinematográfica ─────────
   El JS escribe transform/opacity inline; aquí solo preparamos las capas
   para que el navegador las promueva y no repinte de más. */
.fx-on .hero--video .hero__inner,
.fx-on .hero--video .hero-bg__video {
  will-change: transform, opacity;
}
.fx-on .hero--video .hero-bg__video { transform-origin: center 40%; }
.fx-on .hero--video .hero__scroll { transition: opacity .3s linear; }

/* ───────── 3 · Reveal por líneas de títulos ─────────
   Cada línea del título se envuelve en .ln (máscara) + .ln__i (móvil).
   El desplazamiento es del 110 % para que la línea entre desde fuera
   de su propia máscara, no desde un fundido. */
.fx-on [data-reveal="lines"] {
  opacity: 1;          /* neutraliza el opacity:0 base de [data-reveal] */
  transform: none;
  filter: none;
}
.has-lines .ln {
  display: block;
  overflow: hidden;
  /* Aire vertical para que tildes y descendentes no se recorten */
  padding-block: 0.08em;
  margin-block: -0.08em;
}
.fx-on .has-lines .ln__i {
  display: block;
  transform: translateY(110%);
  transition:
    transform 0.95s cubic-bezier(0.16, 1, 0.3, 1),
    opacity 0.75s ease;
  opacity: 0;
  transition-delay: calc(var(--ln, 0) * 105ms);
}
.fx-on [data-reveal="lines"].is-revealed .ln__i {
  transform: translateY(0);
  opacity: 1;
}

/* ───────── 4 · Stagger genérico por índice ─────────
   El JS pone --i en cada tarjeta de una grilla; el retardo se calcula
   solo. Sustituye a los nth-child cableados a mano. */
.fx-on [data-reveal][style*="--i"] {
  transition-delay: calc(var(--i, 0) * 85ms);
}

/* ───────── 5 · Parallax de decoraciones ───────── */
.fx-on .section-helix__orb--1,
.fx-on .section-helix__orb--2,
.fx-on .gal-home__glow--a,
.fx-on .gal-home__glow--b,
.fx-on .cta-banner__orb--1,
.fx-on .cta-banner__orb--2 {
  will-change: transform;
}

/* ───────── 6 · Afinado de curvas por bloque ─────────
   Un solo easing (expo-out) en todo el landing: la sensación "pro"
   viene de que TODO frene igual, no de tener muchas curvas distintas. */
.fx-on [data-reveal] {
  transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
  transition-duration: 0.85s;
}

/* Las tarjetas con portada entran con un punto de escala: se sienten
   "sólidas" al aterrizar en vez de solo desplazarse. */
.fx-on .bento-card[data-reveal],
.fx-on .caso-card[data-reveal],
.fx-on .blog-home-card[data-reveal] {
  transform: translateY(34px) scale(0.985);
}
.fx-on .bento-card[data-reveal].is-revealed,
.fx-on .caso-card[data-reveal].is-revealed,
.fx-on .blog-home-card[data-reveal].is-revealed {
  transform: none;
}

/* ───────── 6-bis · RED DE SEGURIDAD EN CSS PURO ─────────
   Regla más importante del archivo. Todo lo que esta capa oculta lleva
   además una animación que, a los 4 segundos, lo devuelve a su estado
   final pase lo que pase. No depende de JavaScript, ni del
   IntersectionObserver, ni de que haya scroll.

   Consecuencia: en el peor de los casos imaginable —el JS no carga, el
   observer no dispara, el usuario entra por un enlace con ancla— el
   contenido APARECE igual. Nunca una sección en blanco.

   Si el reveal normal ya ocurrió, la animación aterriza en los mismos
   valores y no se nota. */
@keyframes fxFailsafe {
  to { opacity: 1; transform: none; filter: none; }
}
.fx-on [data-reveal],
.fx-on [data-reveal-group] > *,
.fx-on .has-lines .ln__i {
  animation: fxFailsafe 0.01s linear 4s forwards;
}

/* ───────── 7 · Accesibilidad ─────────
   El script ni siquiera arranca con movimiento reducido, pero dejamos
   la red de seguridad por si la preferencia cambia en caliente. */
@media (prefers-reduced-motion: reduce) {
  .scroll-progress { display: none; }
  .fx-on .has-lines .ln__i,
  .fx-on [data-reveal] {
    transform: none !important;
    opacity: 1 !important;
    transition: none !important;
  }
  .fx-on .hero--video .hero__inner,
  .fx-on .hero--video .hero-bg__video {
    transform: none !important;
    opacity: 1 !important;
  }
}
