/* ============================================================
   NIVORA v2 — Capítulos
   ------------------------------------------------------------
   Todas las secciones son transparentes cuando el material
   (WebGL) está activo: el fondo ES el mosaico. Sin él
   (html sin .has-field) cada sección pinta su propio color.

   Las alturas de los capítulos fijados solo existen con JS
   (html.js). Sin JS todo fluye como un documento normal.
   ============================================================ */

/* ── Estados de revelado (solo con JS y movimiento permitido) ── */
/* Apoyo: el CORTE a 20.35° (la diagonal del monograma) descubre el
   texto. Es el mismo gesto de las palabras-capítulo, a otra escala:
   un solo lenguaje de entrada en toda la página. */
/* Antes de entrar solo hay opacidad 0 (un clip-path de área cero haría
   que IntersectionObserver nunca lo viera entrar). El corte corre como
   animación de una sola vez al recibir .is-in. */
html.motion-ok [data-reveal="soft"] { opacity: 0; }
html.motion-ok [data-reveal="soft"].is-in {
  animation: cut-in 640ms var(--ease-out) both;
  animation-delay: calc(var(--i, 0) * var(--stagger));
}
@keyframes cut-in {
  from { opacity: 0; clip-path: polygon(-4% -8%, -4% -8%, -26% 108%, -4% 108%); }
  25%  { opacity: 1; }
  to   { opacity: 1; clip-path: polygon(-4% -8%, 126% -8%, 104% 108%, -4% 108%); }
}
/* La revelación de IA se enciende y apaga con el scroll: transición
   (interrumpible), no animación. */
html.motion-ok .reveal-ai {
  clip-path: polygon(-4% -8%, -4% -8%, -26% 108%, -4% 108%);
  opacity: 0;
  transition: clip-path 720ms var(--ease-out), opacity 220ms ease-out;
}
html.motion-ok .reveal-ai.is-on { clip-path: polygon(-4% -8%, 126% -8%, 104% 108%, -4% 108%); opacity: 1; }

/* Titulares: cada línea sube desde una máscara (JS envuelve las líneas) */
.line { display: block; overflow: clip; overflow-clip-margin: 0.12em; padding-bottom: 0.06em; margin-bottom: -0.06em; }
.line__inner { display: block; }
html.motion-ok [data-reveal="lines"] .line__inner {
  transform: translateY(108%);
  transition: transform var(--dur-reveal) var(--ease-out);
  transition-delay: calc(var(--l, 0) * var(--stagger));
}
html.motion-ok [data-reveal="lines"].is-in .line__inner { transform: none; }

/* ═════════════════════ 00 · HERO ═════════════════════ */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  align-items: flex-end;
  padding-block: calc(64px + var(--s-6)) var(--s-12);
}
.hero__wrap { position: relative; }

.hero__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(2.4rem, 0.4rem + 4.75vw, 5.75rem);
  line-height: var(--lh-tight);
  letter-spacing: var(--track-display);
  max-width: 13em;
}
.hero__line { display: block; }

.hero__sub {
  margin-top: var(--s-4);
  max-width: 34rem;
  font-size: var(--fs-lead);
  line-height: 1.45;
  color: var(--on-dark-muted);
}

.hero__actions { margin-top: var(--s-6); display: flex; gap: var(--s-2); }

/* Entrada del hero: parte YA visible (el H1 es el LCP) y se asienta.
   La gran animación del hero es la ola del material, no el texto. */
html.motion-ok .hero__line {
  opacity: 0.35;
  transform: translateY(0.22em);
  animation: hero-settle 900ms var(--ease-out) forwards;
  animation-delay: calc(120ms + var(--l, 0) * 90ms);
}
html.motion-ok .hero__line:nth-child(2) { --l: 1; }
html.motion-ok .hero__sub,
html.motion-ok .hero__actions {
  opacity: 0;
  transform: translateY(10px);
  animation: hero-settle 700ms var(--ease-out) forwards;
}
html.motion-ok .hero__sub { animation-delay: 380ms; }
html.motion-ok .hero__actions { animation-delay: 460ms; }
@keyframes hero-settle { to { opacity: 1; transform: none; } }

@media (min-width: 900px) {
  .hero { align-items: center; padding-bottom: var(--s-8); }
}
@media (max-width: 599px) {
  /* En móvil el arco ocupa la mitad superior; el texto, la inferior */
  .hero { padding-bottom: var(--s-6); }
  .hero__title { font-size: 2.35rem; }
  .hero__sub { font-size: 1rem; margin-top: var(--s-3); }
  .hero__actions { margin-top: var(--s-4); }
  .hero__actions .btn { width: 100%; }
}

/* ═════════════════════ 01 · LA SEÑAL ═════════════════════ */
.signal { position: relative; }
.signal__wrap { position: relative; }
.signal__list { display: grid; gap: var(--s-16); padding-block: var(--section-y); }
.statement {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--fs-statement);
  line-height: 1.06;
  letter-spacing: -0.03em;
  max-width: 16em;
}
.statement .w { transition: color 240ms ease; }

html.js .signal { height: 360svh; }
html.js .signal__stage {
  position: sticky;
  top: 0;
  height: 100svh;
  display: flex;
  align-items: center;
  overflow: clip;
}
html.js .signal__list { display: grid; padding: 0; gap: 0; }
html.js .signal__item {
  grid-area: 1 / 1;
  visibility: hidden;
}
html.js .signal__item.is-active,
html.js .signal__item.is-leaving { visibility: visible; }
/* Las palabras se encienden al ritmo del scroll (scrub, sin duración) */
html.js .signal__item .w { color: color-mix(in srgb, var(--ivory) 40%, var(--ink)); }   /* 3.6:1: legible aun sin encender */
html:not(.motion-ok) .signal__item .w { color: var(--ivory); }                             /* movimiento reducido: todo encendido */
html.js .signal__item .w.is-lit { color: var(--ivory); }
html.js .signal__item[data-step="2"] .w.is-lit:nth-last-child(-n+3) { color: var(--ivory); }
html.js .signal__item.is-leaving { opacity: 0; transition: opacity 360ms ease-out; }
html.js .signal__item.is-active { opacity: 1; transition: opacity 240ms ease-out; }
html.motion-ok .signal__item { opacity: 0; transform: translateY(0.4em); }
html.motion-ok .signal__item.is-leaving { opacity: 0; transform: translateY(-0.4em); transition: opacity 200ms ease-out, transform 360ms var(--ease-out); }
html.motion-ok .signal__item.is-active { opacity: 1; transform: none; transition: opacity 320ms var(--ease-out), transform 480ms var(--ease-out); }

/* ═════════════ 02 · ENTENDER · CONSTRUIR · INTEGRAR ═════════════ */
.verbs { position: relative; }
/* La pista mide 300vw: se recorta aquí (clip no crea contenedor de
   scroll, así que position: sticky sigue funcionando dentro). */
.verbs__stage { overflow-x: clip; }
.verbs__intro { padding-top: var(--section-y); padding-bottom: var(--s-12); }
.verbs__lead {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-h2);
  line-height: var(--lh-head);
  letter-spacing: var(--track-display);
  max-width: 18em;
}

.verb { position: relative; min-height: 88svh; display: flex; align-items: flex-end; }
.verb__inner {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding: var(--s-12) var(--gutter);
  display: grid;
  gap: var(--s-3);
}
.verb__word {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-word);
  line-height: 0.84;
  letter-spacing: var(--track-word);
  margin-left: -0.04em;
}
.verb__text {
  font-size: var(--fs-lead);
  max-width: 24ch;
  color: var(--on-dark-muted);
}

/* La revelación: la página como prueba */
.reveal-ai { margin-top: var(--s-6); max-width: 30rem; }
.reveal-ai__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-h3);
  line-height: 1.15;
  letter-spacing: -0.02em;
}
.reveal-ai__text { margin-top: var(--s-1); color: var(--on-dark); }

/* La palabra-capítulo se revela con un corte a 20.35° (la diagonal
   del monograma). --wipe va de 0 a 1 con el scroll. */
html.motion-ok .verb__word {
  --wipe: 0;
  clip-path: polygon(
    0 0,
    calc(var(--wipe) * 130% - 30%) 0,
    calc(var(--wipe) * 130% - 30% - 0.37 * 1em) 100%,
    0 100%);
}


/* Escena horizontal: tablet horizontal y escritorio */
@media (min-width: 900px) {
  html.motion-ok .verbs__stage { height: 420svh; }
  html.motion-ok .verbs__track {
    position: sticky;
    top: 0;
    height: 100svh;
    display: flex;
    width: 300vw;            /* will-change lo pone chapters.js solo mientras se usa */
  }
  html.motion-ok .verb { width: 100vw; min-height: 0; height: 100svh; flex: none; align-items: flex-end; }
  html.motion-ok .verb__inner {
    grid-template-columns: minmax(0, 1fr) minmax(0, 22rem);
    align-items: end;
    column-gap: var(--s-8);
    row-gap: var(--s-2);
    padding-top: calc(64px + var(--s-6));
    padding-bottom: var(--s-8);
  }
  html.motion-ok .verb__word { grid-column: 1 / -1; }
  html.motion-ok .verb__text { grid-column: 2; }
  html.motion-ok .reveal-ai { grid-column: 2; margin-top: 0; }
}
@media (max-width: 899px) {
  html.js .verb[data-verb="construir"] { min-height: 150svh; align-items: flex-start; }
  html.js .verb[data-verb="construir"] .verb__inner { position: sticky; top: 64px; }
}

/* ═════════════════ 03 · PRIMERA GENERACIÓN ═════════════════ */
.generation { position: relative; padding-block: var(--section-y); }
.generation__grid {
  display: grid;
  gap: var(--s-8);
}
.generation__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-h2);
  line-height: var(--lh-head);
  letter-spacing: var(--track-display);
  max-width: 12em;
}
.reasons { display: grid; gap: var(--s-6); }
.reason__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-h3);
  line-height: 1.15;
  letter-spacing: -0.015em;
}
.reason__text { margin-top: var(--s-1); max-width: 34ch; color: var(--on-dark-muted); }
.generation__close {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--fs-h3);
  line-height: 1.3;
  max-width: 24em;
}
@media (min-width: 900px) {
  .generation__grid {
    grid-template-columns: repeat(12, minmax(0, 1fr));
    row-gap: var(--s-12);
  }
  .generation__title { grid-column: 1 / span 7; }
  .reasons { grid-column: 7 / -1; grid-row: 2; gap: var(--s-8); }
  /* translate (no transform) para no chocar con el revelado */
  .reason:nth-child(2) { translate: calc(var(--cell) * -6) 0; }
  .generation__close { grid-column: 1 / span 6; grid-row: 3; }
}

/* ═════════════════════ 04 · EL UMBRAL ═════════════════════ */
.threshold { position: relative; height: 70svh; }
html.js .threshold { height: 240svh; }
.threshold__stage {
  position: sticky;
  top: 0;
  height: 100svh;
  display: grid;
  place-items: center;
}
.threshold__word {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(2.75rem, 1rem + 6vw, 7rem);
  letter-spacing: var(--track-display);
  color: var(--ivory);
  transition: color 300ms ease;
}
html.motion-ok .threshold__word { opacity: 0; transform: scale(0.96); }
/* La palabra aparece cuando el vano de luz ya cubre la pantalla */
html.has-field .threshold__word { color: var(--black-brand); }

/* ── Fondos cuando NO hay material (sin WebGL / sin JS) ───── */
html:not(.has-field) .threshold { background: var(--ivory); }
html:not(.has-field) .threshold__word { color: var(--black-brand); }
html:not(.has-field) .signup { background: var(--ivory); }

/* La reserva cierra Integrar, dentro del panel */
.verb__reserve {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--fs-lead);
  color: var(--on-dark);
  max-width: 24ch;
  margin-top: var(--s-2);
}
@media (min-width: 900px) { html.motion-ok .verb__reserve { grid-column: 2; margin-top: 0; } }

/* 9 · la palabra-capítulo nunca desborda (también con espaciado de texto aumentado) */
.verb__word { font-size: min(var(--fs-word), 21vw); overflow-wrap: anywhere; }

/* ── El contraste nunca depende de WebGL ─────────────────────
   Antes de cruzar el umbral, preregistro y footer tienen marfil
   sólido (están fuera de pantalla). Al cruzarlo, el propio body es
   marfil DEBAJO del canvas: si el material fallara, el texto oscuro
   seguiría sobre marfil. Con el material activo nada de esto se ve. */
html.has-field:not([data-theme="light"]) .signup,
html.has-field:not([data-theme="light"]) .footer { background: var(--ivory); }
html[data-theme="light"],
html[data-theme="light"] body { background: var(--ivory); }
html.has-field[data-theme="light"] .hero,
html.has-field[data-theme="light"] .signal,
html.has-field[data-theme="light"] .verbs,
html.has-field[data-theme="light"] .generation { background: var(--ink); }
