/* ==========================================================================
   AXIOM SCROLL WORLD — capa de escenografía
   Fase 0: el contrato de arquitectura. Todavía no hay 3D.

   Este fichero NO maquetá contenido. aql.css sigue siendo el sistema de
   diseño y la única fuente de layout. Aquí solo vive lo que hace falta para
   que un <canvas> pueda existir DETRÁS del documento sin tocarlo.

   REGLA DE ORO DEL PROYECTO — se comprueba en test/mundo.test.mjs:
   con la capa 2 vacía o apagada, el sitio se ve y se comporta EXACTAMENTE
   igual que antes. Si quitar este fichero cambia una sola posición, este
   fichero está mal escrito.

   Las tres capas:
     capa 1  documento HTML  ....  z-index 1   (el contenido, lo que indexa Google)
     capa 2  <canvas> mundo  ....  z-index 0   (fija, decorativa, diferida)
     capa 3  interfaz        ....  z-index 2   (marcadores, HUD, stack builder)

   MÓVIL PRIMERO. Ningún @media max-width.
   ========================================================================== */

/* ---------- 1. Tokens del mundo ---------- */
:root {
  /* Duraciones de cámara. La Fase 1 las lee desde JS con getComputedStyle:
     un solo sitio donde ajustar el ritmo del recorrido completo. */
  --mundo-scrub: 0.85;          /* suavizado del scrub, 0 = instantáneo */
  --mundo-inercia: 0.08;        /* damping del rig de cámara */
  --mundo-marca-entrada: 520ms;
  --mundo-fundido: 400ms;

  /* Profundidad. El documento flota sobre el mundo, nunca al revés. */
  --z-mundo: 0;
  --z-documento: 1;
  --z-interfaz: 2;
  --z-cabecera: 10;
}

/* ---------- 2. Capa 2 — el lienzo ---------- */
/* Fijo y a pantalla completa. `pointer-events:none` es obligatorio: el mundo
   no debe robar un solo click al documento que tiene encima. La interacción
   con objetos 3D (punto 14 del directive) se resuelve en la Fase 3 activando
   pointer-events solo sobre las zonas que de verdad son interactivas. */
.mundo-lienzo {
  position: fixed;
  inset: 0;
  z-index: var(--z-mundo);
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--mundo-fundido) var(--sale);
  /* Sin `will-change`: el canvas ya vive en su propia capa de composición y
     declararlo aquí solo reserva memoria de GPU que no se usa hasta la Fase 1. */
}

.mundo-lienzo canvas {
  display: block;
  width: 100%;
  height: 100%;
}

/* El lienzo solo se ve cuando el motor confirma que tiene algo que pintar.
   Un canvas negro visible antes de tiempo es un fundido a negro encubierto,
   y el punto 10 prohíbe los fundidos. */
[data-mundo-estado="activo"] .mundo-lienzo { opacity: 1; }

/* ---------- 2b. El velo — lo que hace que el texto se lea ---------- */
/* Va entre el lienzo y el documento. Tres cosas a la vez, y ninguna es
   decoración:

   1. ESCRIMA. Un titular blanco sobre una mesa iluminada es ilegible, y
      subirle una sombra al texto arruina la tipografía. En cine esto se
      resuelve apagando el fondo donde va el texto, no reforzando el texto.
   2. VIÑETA. La caída hacia los bordes es lo que convierte un render en un
      plano fotografiado. Cuesta cero: es un degradado CSS, no una pasada de
      postprocesado.
   3. GRANO. Una película de ruido casi invisible. Sin él, los degradados
      largos sobre negro producen bandas, y el conjunto se ve digital.

   Todo esto en CSS, encima del canvas, en vez de en el render: no cuesta un
   solo milisegundo de GPU y se apaga solo cuando el mundo está apagado. */
.mundo-velo {
  position: fixed;
  inset: 0;
  z-index: var(--z-mundo);
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--mundo-fundido) var(--sale);
  /* Móvil: el texto ocupa todo el ancho, así que la escrima cae de arriba. */
  background:
    radial-gradient(125% 95% at 52% 42%, rgba(5, 5, 5, 0) 38%, rgba(5, 5, 5, 0.66) 100%),
    linear-gradient(to bottom, rgba(5, 5, 5, 0.9) 0%, rgba(5, 5, 5, 0.42) 36%, rgba(5, 5, 5, 0) 64%);
}

@media (min-width: 52rem) {
  /* Escritorio: el texto vive en la columna izquierda. */
  .mundo-velo {
    background:
      radial-gradient(125% 95% at 56% 46%, rgba(5, 5, 5, 0) 40%, rgba(5, 5, 5, 0.62) 100%),
      linear-gradient(to right, rgba(5, 5, 5, 0.92) 0%, rgba(5, 5, 5, 0.7) 24%, rgba(5, 5, 5, 0) 56%);
  }
}

.mundo-velo::after {
  content: "";
  position: absolute;
  inset: 0;
  opacity: 0.055;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

[data-mundo-estado="activo"] .mundo-velo { opacity: 1; }

/* Con el mundo encendido, la retícula y el halo del sitio estático sobran:
   son el fondo que existía cuando no había escena detrás, y sumados a ella
   producen ruido. Se apagan SOLO mientras el mundo está activo — apagarlo
   devuelve el sitio exactamente como estaba, que es la regla de oro. */
[data-mundo-estado="activo"] .reticula::before,
[data-mundo-estado="activo"] .halo { display: none; }

/* ---------- 2c. El interruptor ---------- */
/* `prefers-reduced-motion` cubre a quien ya lo tiene configurado. No cubre a
   quien nunca supo que existía, ni a quien lo quiere apagar solo aquí, ni a
   quien está con batería al 4%. Un mundo que no se puede apagar es una
   decisión tomada en nombre del usuario.
   Aparece solo si el motor llegó a arrancar: ofrecer apagar algo que no está
   encendido es ruido. */
.mundo-interruptor {
  position: fixed;
  right: var(--e-4);
  bottom: var(--e-4);
  z-index: var(--z-interfaz);
  min-height: 44px;
  padding: var(--e-2) var(--e-4);
  font-family: var(--mono);
  font-size: var(--t-micro);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--tinta-media);
  background: rgba(13, 13, 13, 0.82);
  border: 1px solid var(--linea-fuerte);
  border-radius: 999px;
  cursor: pointer;
  opacity: 0.35;
  transition: opacity var(--rapido) var(--sale), color var(--rapido) var(--sale);
}

.mundo-interruptor:hover,
.mundo-interruptor:focus-visible { opacity: 1; color: var(--tinta); }
.mundo-interruptor[hidden] { display: none; }

/* ---------- 3. Capa 1 — el documento por encima ---------- */
/* Se crea contexto de apilamiento sin tocar el flujo. `position: relative`
   sobre elementos que ya son de bloque no mueve un píxel. */
.mundo-escena {
  position: relative;
  z-index: var(--z-documento);
}

/* ---------- 4. Capa 3 — marcadores narrativos ---------- */
/* El punto 6: la cámara es el narrador y cada movimiento lleva una palabra.
   Inertes hasta que el motor los enciende. */
.mundo-marca {
  display: block;
  font-family: var(--mono);
  font-size: var(--t-micro);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--tinta-tenue);
  margin-bottom: var(--e-3);
}

[data-mundo-estado="activo"] .mundo-marca {
  color: var(--tinta-media);
  transition: color var(--mundo-marca-entrada) var(--sale);
}

/* Numeración del mundo. Es orientación espacial, no decoración: en un
   recorrido continuo el usuario necesita saber dónde está. */
.mundo-indice {
  font-family: var(--mono);
  font-size: var(--t-micro);
  color: var(--tinta-tenue);
  letter-spacing: 0.1em;
}

/* ---------- 5. Bloque de regla (WORLD 04) ---------- */
.mundo-regla {
  margin-top: var(--e-8);
  padding: var(--e-6);
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  background: var(--sup-1);
  font-family: var(--mono);
  font-size: var(--t-pequeno);
  line-height: 2;
  color: var(--tinta-media);
  overflow-x: auto;
}

.mundo-regla span { display: block; white-space: nowrap; }
.mundo-regla span:first-child { color: var(--tinta); }

/* ---------- 6. El ciclo (WORLD 06) ---------- */
.mundo-ciclo {
  display: flex;
  flex-direction: column;
  gap: var(--e-2);
  margin-top: var(--e-8);
  list-style: none;
  padding: 0;
}

.mundo-ciclo li {
  display: flex;
  align-items: center;
  gap: var(--e-3);
  font-family: var(--mono);
  font-size: var(--t-pequeno);
  letter-spacing: 0.08em;
  color: var(--tinta-media);
  padding: var(--e-3) var(--e-4);
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  background: var(--sup-1);
}

.mundo-ciclo li::before {
  content: attr(data-n);
  font-size: var(--t-micro);
  color: var(--tinta-tenue);
}

@media (min-width: 52rem) {
  .mundo-ciclo { flex-direction: row; flex-wrap: wrap; }
  .mundo-ciclo li { flex: 1 1 0; min-width: 9rem; }
}

.mundo-cierre {
  margin-top: var(--e-12);
  font-family: var(--mono);
  font-size: var(--t-h3);
  letter-spacing: 0.06em;
  color: var(--tinta);
}

/* ---------- 7. Degradación ---------- */
/* Perfil LITE: no hay WebGL, y no se descarga. El recorrido sigue existiendo
   como documento. No es una versión recortada del sitio: es el mismo sitio
   sin la capa que ese dispositivo no puede permitirse. */
[data-mundo-perfil="lite"] .mundo-lienzo { display: none; }

/* Reduced motion apaga la capa 2 entera, sin "versión suave". Un recorrido
   de cámara atenuado sigue provocando malestar vestibular; media medida aquí
   es no haber tomado la decisión. */
@media (prefers-reduced-motion: reduce) {
  .mundo-lienzo { display: none !important; }
  .mundo-marca { transition: none !important; }
}

/* Impresión: igual que el resto del sitio, el mundo desaparece. */
@media print {
  .mundo-lienzo { display: none !important; }
}
