/* ============================================================================
   La máquina — hero cinematográfico (laboratorio, _maquina.html)

   Dos estados en un solo archivo:

   1. SIN JavaScript (o con reduced-motion): la portada es un hero de una
      pantalla —la misma composición que abre el recorrido— y debajo, en
      flujo, las cuatro áreas en dos columnas con su escena. Nada depende de
      un observador ni de una librería, y por eso el LCP no espera a nadie.

   2. CON JavaScript: maquina.js le pone .maquina--viva y la sección pasa a ser
      un recorrido de varias pantallas con una etapa fija de 100vh. Todo lo que
      anima es transform, opacity, filter y clip-path: nunca layout.

   Tokens propios en :root, abajo. Un solo color fuera del manual de marca:
   --maquina-frio, el cyan de las partículas y la bruma. Es la excepción
   pedida para esta zona y documentada en BRIEF_HERO_MAQUINA.md; no sale de
   esta sección. tests/maquina.test.mjs verifica que ningún otro color literal
   viva fuera de este bloque.
   ========================================================================= */

:root {
  /* El frío. Complementario del saffron en el círculo cromático: adentro de la
     máquina lo cálido está cerca (hélice, pantallas) y lo frío lejos (bruma,
     constelación), que es como el ojo lee profundidad. */
  --maquina-frio:        #22B8CF;
  --maquina-frio-suave:  color-mix(in srgb, var(--maquina-frio) 38%, transparent);
  --maquina-bruma:       color-mix(in srgb, var(--maquina-frio) 16%, transparent);
  --maquina-vidrio:      color-mix(in srgb, var(--negro) 74%, transparent);
  --maquina-vidrio-luz:  color-mix(in srgb, var(--off-white) 6%, transparent);

  /* Cuántas pantallas mide el recorrido. Ocho: dos para portada y
     zambullida, cuatro y media para los capítulos y una y media para el
     remate, que Axel pidió con tiempo para ver girar el isotipo. */
  --maquina-recorrido: 800vh;

  /* El monitor en reposo. 2752:1536 = 1.79, así que 124vh de ancho son 69vh
     de alto: entra con aire arriba para el kicker y abajo para la bajada. */
  --maquina-monitor-ancho: min(78vw, 124vh);

  /* Tamaño de las pantallas que orbitan, y del titular. */
  --maquina-pantalla-ancho: min(34vw, 58vh);
  /* Contra el monitor, no contra la ventana: al 10% del cuadro el titular
     mide 1,4 veces el vidrio en cualquier pantalla (letras quemadas adentro,
     llenas afuera). Medido en vw, en el teléfono salía todo blanco (apaisado)
     o todo contorno (vertical). */
  --t-maquina:         max(2.2rem, var(--maquina-monitor-ancho) * 0.1);
  --t-maquina-titulo:  clamp(1.9rem, 1rem + 3.4vw, 4.4rem);

  --maquina-margen: clamp(1.25rem, 0.5rem + 5vw, 7rem);

  /* A qué altura de la etapa va el centro del monitor y del titular que lo
     cruza. En teléfono sube: abajo hace falta lugar para la bajada y la tecla. */
  --maquina-centro: 50%;

  /* Ventana baja: aire entre la nav (con el kicker) y el tope del chasis. */
  --maquina-margen-superior: 3.5rem;
}

/* --- Estado base: la portada, sin JavaScript -----------------------------
   La composición del primer viewport (monitor centrado, titular cruzándolo,
   kicker arriba, bajada bajo el pie) es el estado base: existe en el primer
   CSS y no la enciende nadie.

   Vivió adentro de .maquina--viva hasta el 2026-09-06, y ahí el monitor —el
   LCP de la home— no llegaba a su caja final hasta que bajaban y corrían
   GSAP, ScrollTrigger y maquina.js. PageSpeed móvil lo midió: la imagen
   tardaba 96 ms en bajar y 1083 ms más en pintarse; LCP 3,2 s, Rendimiento
   92. El problema nunca fue la imagen, era que su caja la decidía el
   JavaScript.

   .maquina--viva se agrega encima y cambia solo lo que necesita JavaScript:
   el recorrido, la etapa pegada, el interior, los capítulos y el remate. Con
   el scroll en cero los dos estados se ven igual, que es lo que hace que el
   LCP no espere y que no haya salto; lo cuida maquina-capturas.mjs --lcp.
   ----------------------------------------------------------------------- */

.maquina {
  position: relative;
  background: var(--negro-lienzo);
  color: var(--tinta);
  overflow: hidden;
}

.maquina__etapa {
  position: relative;
  background: var(--negro-lienzo);
}

/* Una pantalla, y todo lo de adentro posicionado contra ella. Con
   .maquina--viva pasa a llenar la etapa pegada: la misma caja. */
.maquina__portada {
  position: relative;
  height: 100vh;
  height: 100svh;
  text-align: center;
  z-index: 1;
}

.maquina__monitor {
  line-height: 0;
}

.maquina__monitor-imagen {
  width: 100%;
  height: auto;
  display: block;
}

.maquina__kicker {
  font: 700 var(--t-placa)/1 var(--fuente-titulo);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--saffron);
  margin: 0;
}

.maquina__titular {
  font-size: var(--t-maquina);
  line-height: 0.94;
  letter-spacing: -0.025em;
  text-transform: uppercase;
  text-wrap: balance;
  margin: 0;
}

.maquina__linea { display: block; }

/* Cada palabra lleva su propio relleno: --relleno es cuánto del ancho está
   pintado con tinta, --contorno cuánto se ve el trazo saffron. Con relleno
   100% y contorno 0 es texto normal; con relleno 0 y contorno 1 es solo el
   trazo, que es como aparecen y como se van los títulos adentro de la
   máquina. Sin JS nadie toca las variables y el texto se ve lleno. */
.maquina__palabra {
  --relleno: 100%;
  --contorno: 0;
  display: inline-block;
  color: transparent;
  -webkit-text-stroke: 1px color-mix(in srgb, var(--saffron) calc(var(--contorno) * 100%), transparent);
  background-image: linear-gradient(var(--tinta), var(--tinta));
  background-repeat: no-repeat;
  background-size: var(--relleno) 100%;
  -webkit-background-clip: text;
  background-clip: text;
}

.maquina__intro {
  display: grid;
  justify-items: center;
  gap: calc(var(--u) * 2.5);
}

.maquina__bajada {
  max-width: 56ch;
  color: var(--tinta-suave);
  margin: 0;
}

.maquina__acciones {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: calc(var(--u) * 2);
}

/* Lo que solo existe con JS. */
.maquina__interior,
.maquina__pista,
.maquina__flecha,
.maquina__remate,
.maquina__riel,
.maquina__medicion,
.maquina__titular--contorno { display: none; }

/* El padding vive acá y no en la etapa: la portada es a sangre. */
.maquina__capitulos {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: calc(var(--u) * 3);
  padding: calc(var(--u) * 6) var(--maquina-margen) calc(var(--u) * 8);
}

/* grid-area auto a propósito: .area--leads y compañía traen de styles.css un
   grid-area con nombre para el tablero. Acá no hay áreas con esos nombres y
   el navegador manda las cuatro tarjetas a la misma celda implícita, una
   encima de otra. La captura sin JavaScript lo mostró. */
.maquina__capitulo {
  grid-area: auto;
  justify-self: stretch;
  align-self: auto;
  max-width: none;
}

/* Tampoco hay escena arriba o abajo a la que atar la costura. */
.maquina__capitulo::after { display: none; }

.maquina__capitulo-titulo { font-size: var(--t-sub); }

.maquina__capitulo-escena {
  width: 100%;
  height: auto;
  margin-top: calc(var(--u) * 2.5);
  border-radius: var(--radio);
}

@media (max-width: 900px) {
  .maquina__capitulos { grid-template-columns: minmax(0, 1fr); }
}

/* ============================================================================
   Portada: la composición del primer viewport

   El header de la home va fijo, no pegado en el flujo: pegado (styles.css,
   .riel sticky) ocupa 72px arriba de la sección a scroll 0 y empuja la etapa
   de 100vh hacia abajo, así que el pie de la portada (la bajada, la guía de
   scroll) queda fuera de la ventana hasta que se scrollea; y como la etapa
   recorta, no se ve nunca a scroll 0. Axel lo vio el 2026-09-16 en una ventana
   de 1030×560 ("ya no se ve Cancún... ni Cuatro frentes"). Fijo, la etapa es la
   ventana desde el primer pixel y en el estado pegado, que es lo que toda la
   composición asume (el kicker ya despeja --nav-alto). tools/maquina-portada.mjs
   lo mide en seis ventanas.
   ========================================================================= */

.riel--hud {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
}

/* ============================================================================
   Portada: la composición del primer viewport (reglas)

   Sin prefijo de estado a propósito: es lo que tiene que pintarse con el
   primer CSS, sin esperar a nadie. Ver el bloque del estado base, arriba.
   ========================================================================= */

.maquina__monitor {
  position: absolute;
  left: 50%;
  top: var(--maquina-centro);
  width: var(--maquina-monitor-ancho);
  translate: -50% -50%;
  /* El zoom entra por el centro del vidrio, no por el centro de la imagen. */
  transform-origin:
    calc((var(--pantalla-x) + var(--pantalla-ancho) / 2) * 100%)
    calc((var(--pantalla-y) + var(--pantalla-alto) / 2) * 100%);
  will-change: transform, opacity;
}

/* El polvo detrás del monitor: la misma caja que el chasis (mismo cuadro,
   tools/maquina-chasis.mjs). El envoltorio lo mueve maquina.js con el mouse
   (paralaje, en sentido contrario al chasis) y la imagen deriva sola por CSS:
   dos transforms en dos elementos, ninguno pisa al otro. Debajo del monitor
   en el orden del DOM, o sea detrás. */
.maquina__polvo {
  position: absolute;
  left: 50%;
  top: var(--maquina-centro);
  width: var(--maquina-monitor-ancho);
  translate: -50% -50%;
  line-height: 0;
  pointer-events: none;
  will-change: transform;
}

.maquina__polvo img {
  width: 100%;
  height: auto;
  display: block;
  animation: maquina-polvo-flota 14s ease-in-out infinite alternate;
}

@keyframes maquina-polvo-flota {
  from { translate: 0 0; }
  to   { translate: 0.4% -0.7%; }
}

/* max-width: none en el kicker y en la pista: styles.css le pone --medida a
   todo <p>, y un párrafo de 64ch con left/right 0 queda pegado a la izquierda
   en vez de centrado. */
.maquina__kicker {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(var(--nav-alto) + var(--u) * 2);
  max-width: none;
  text-align: center;
}

.maquina__titular {
  position: absolute;
  left: 0;
  right: 0;
  top: var(--maquina-centro);
  translate: 0 -50%;
  text-align: center;
  padding-inline: var(--u);
  pointer-events: none;
}

.maquina--viva .maquina__linea { will-change: transform, filter, opacity; }

/* La bajada arranca debajo del pie del monitor, no a una distancia fija del
   borde de abajo: en un portátil bajo se pisaban. La base del pie la mide
   tools/maquina-pantalla.mjs (--monitor-base, fracción del alto del cuadro) y
   --monitor-aspecto convierte el ancho del monitor en alto. */
.maquina__intro {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(
    var(--maquina-centro)
    + var(--maquina-monitor-ancho) * var(--monitor-aspecto, 0.56) * (var(--monitor-base, 0.82) - 0.5)
    + var(--u) * 3
  );
  padding-inline: var(--maquina-margen);
  will-change: transform, opacity;
}

/* ============================================================================
   Estado vivo: la etapa fija y el recorrido
   ========================================================================= */

/* overflow visible a propósito: un ancestro con overflow hidden se vuelve el
   contenedor de scroll del sticky, y como ese ancestro no scrollea, la etapa
   nunca se pega al viewport y se va con la sección. La primera captura con
   scroll real salió negra por esto. El recorte lo hace la etapa misma. */
.maquina--viva {
  height: var(--maquina-recorrido);
  overflow: visible;
}

.maquina--viva .maquina__etapa {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
}

/* La portada pasa de bloque de una pantalla a llenar la etapa pegada: la
   misma caja, y los capítulos dejan de estar en flujo. */
.maquina--viva .maquina__portada {
  position: absolute;
  inset: 0;
  height: auto;
}

.maquina--viva .maquina__capitulos { padding: 0; }

.maquina--viva .maquina__pista {
  display: grid;
  justify-items: center;
  gap: calc(var(--u) * 0.75);
  position: absolute;
  left: 50%;
  bottom: calc(var(--u) * 1.5);
  translate: -50% 0;
  margin: 0;
  padding: calc(var(--u) * 0.5) calc(var(--u) * 1.5);
  max-width: none;
  border: 0;
  background: none;
  text-align: center;
  font: 700 var(--t-placa)/1 var(--fuente-titulo);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--tinta-suave);
  cursor: pointer;
  z-index: 6;
}

.maquina--viva .maquina__pista:hover,
.maquina--viva .maquina__pista:focus-visible { color: var(--saffron); outline: none; }

/* La flecha: un chevrón de saffron que baja y vuelve, 1,6 s. Es lo que se
   lee como "seguí para abajo" sin leer el texto (Axel, 2026-09-16). */
.maquina--viva .maquina__pista-flecha,
.maquina--viva .maquina__flecha {
  display: block;
  width: 0.9rem;
  height: 0.9rem;
  border-right: 2px solid var(--saffron);
  border-bottom: 2px solid var(--saffron);
  rotate: 45deg;
  animation: maquina-flecha 1.6s var(--ease) infinite;
}

@keyframes maquina-flecha {
  0%, 100% { translate: 0 0; opacity: 0.55; }
  50%      { translate: 0 6px; opacity: 1; }
}

/* La flecha del recorrido: abajo al centro, sobre los capítulos (z 4) y
   debajo del remate (z 6 → 7). Su opacidad la lleva la línea de tiempo.

   Por eso late con sus propios cuadros, que no tocan la opacidad: con los de
   la guía (maquina-flecha, que la lleva de 0,55 a 1) la animación le ganaba
   al opacity: 0 de acá y al que pone la línea de tiempo, y esta flecha se veía
   siempre. En la portada quedaban dos, una arriba de la otra (lo vio Axel el
   2026-10-04). Y llevan el -50% del centrado, que los otros pisaban con 0. */
.maquina--viva .maquina__flecha {
  position: absolute;
  left: 50%;
  bottom: calc(var(--u) * 2);
  translate: -50% 0;
  z-index: 5;
  opacity: 0;
  pointer-events: none;
  animation-name: maquina-flecha-recorrido;
}

@keyframes maquina-flecha-recorrido {
  0%, 100% { translate: -50% 0; }
  50%      { translate: -50% 6px; }
}

/* --- La entrada de la portada ----------------------------------------------
   Estaba en maquina.js con tres gsap.from(); es CSS porque tiene que arrancar
   en el primer cuadro pintado y no cuando terminan de bajar 173 KB de
   JavaScript. Con la portada ya compuesta, un gsap.from() a los tres segundos
   apagaba texto ya leído y encogía un monitor ya pintado.

   Dos reglas medidas en PageSpeed, las dos con su prueba en
   tests/maquina.test.mjs y el detalle en BRIEF_HERO_MAQUINA.md:

   1. El monitor no anima nada que cambie su tamaño pintado. Chrome anota el
      LCP en el pintado más grande, así que un scale de 1,4 s le suma 1,4 s.
      Si alguna vez tiene que "encender", con brillo, nunca con su tamaño.
   2. Lo demás termina dentro de los 0,65 s del primer pintado. Los tiempos de
      abajo son cortos a propósito: cada décima de entrada es una décima de
      Speed Index, y no se alargan sin volver a medir.

   Eases heredados de GSAP: power3.out = easeOutQuart, power2.out =
   easeOutCubic. fill backwards para que el estado normal sea el final.
   @property porque un custom property sin registrar no interpola, salta. */
@property --relleno {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 100%;
}

@property --contorno {
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}

@keyframes maquina-entra-palabra {
  from { --relleno: 0%; --contorno: 1; translate: 0 18px; }
  to   { --relleno: 100%; --contorno: 0; translate: 0 0; }
}

@keyframes maquina-entra-bloque {
  from { opacity: 0; translate: 0 12px; }
  to   { opacity: 1; translate: 0 0; }
}

.maquina__titular .maquina__palabra {
  animation: maquina-entra-palabra 0.45s cubic-bezier(0.165, 0.84, 0.44, 1) backwards;
  animation-delay: calc(0.04s + var(--escalon, 0) * 0.05s);
}

/* Cuatro palabras en dos renglones: el escalón sigue el orden de lectura. */
.maquina__titular .maquina__linea[data-linea="2"] .maquina__palabra { --escalon: 2; }
.maquina__titular .maquina__palabra:nth-child(2) { --escalon: 1; }
.maquina__titular .maquina__linea[data-linea="2"] .maquina__palabra:nth-child(2) { --escalon: 3; }

.maquina__kicker,
.maquina__intro,
.maquina__pista {
  animation: maquina-entra-bloque 0.4s cubic-bezier(0.215, 0.61, 0.355, 1) backwards;
  animation-delay: calc(0.1s + var(--escalon, 0) * 0.06s);
}

.maquina__intro { --escalon: 1; }
.maquina__pista { --escalon: 2; }

/* El contorno del titular es una copia del h1 que solo existe en el recorrido:
   sin esto entraría con la misma animación, medio segundo tarde y encima del
   titular de verdad. */
.maquina__titular--contorno .maquina__palabra { animation: none; }

/* Quien recarga a mitad del recorrido no ve una entrada: ve el cuadro que le
   toca. maquina.js pone la clase cuando arranca con scroll, porque una
   animación de CSS en curso le gana a los estilos en línea del scrub. */
.maquina--sin-entrada .maquina__titular .maquina__palabra,
.maquina--sin-entrada .maquina__kicker,
.maquina--sin-entrada .maquina__intro,
.maquina--sin-entrada .maquina__pista { animation: none; }

/* --- Interior: lo que se ve a través del vidrio ----------------------------- */

.maquina--viva .maquina__interior {
  display: block;
  position: absolute;
  inset: 0;
  z-index: 2;
  /* La ventana. maquina.js escribe las cuatro variables en px a partir del
     rectángulo real del monitor en pantalla, y la zambullida las lleva a 0. */
  clip-path: inset(var(--ventana-arriba, 0px) var(--ventana-derecha, 0px) var(--ventana-abajo, 0px) var(--ventana-izquierda, 0px));
  background: var(--negro-lienzo);
  /* El monitor respira (Máquina v2, paso 8): maquina.js le escribe al interior
     el mismo giro que al chasis (perspective + rotateY/rotateX, con el origen
     en el centro del vidrio, que también escribe él). La ventana, el canvas
     3D y el reflejo giran con el chasis como una sola pieza: el vidrio es
     parte del monitor. Un polígono recortado por cuadro habría sido una
     máscara rasterizada en cada cuadro; un transform es solo compositor. */
  will-change: transform;
}

/* El reflejo del vidrio en la portada: una luz diagonal fija y un brillo
   arriba a la izquierda, sobre una caja que maquina.js dimensiona un 30% más
   grande que el vidrio para que al deslizarse (el doble que el chasis, con
   0,3 s de retraso) nunca deje un borde sin cubrir. Alfa normal y no
   mix-blend-mode: screen: sobre negro se ven igual y el blend obliga a
   recomponer la capa en cada cuadro (medido en web-dralorenny, 2026-09-15). */
.maquina--viva .maquina__reflejo {
  position: absolute;
  z-index: 3;
  pointer-events: none;
  background:
    radial-gradient(ellipse at 26% 22%, rgba(255, 255, 255, 0.13), transparent 46%),
    linear-gradient(112deg, transparent 34%, rgba(255, 255, 255, 0.085) 46%, rgba(255, 255, 255, 0.03) 54%, transparent 64%);
  will-change: transform, opacity;
}

.maquina--viva .maquina__mundo {
  position: absolute;
  inset: 0;
  transform-origin: 50% 50%;
  will-change: transform;
}

.maquina__capa {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* Fondo (bruma, constelación y hélice) entre las pantallas de atrás (1) y
   las de adelante (3); el polvo por encima de todo. */
.maquina__capa--fondo  { z-index: 2; }
.maquina__capa--polvo  { z-index: 5; }

/* Las pantallas: vidrio HUD con la escena adentro. Su transform lo escribe el
   JS cuadro a cuadro (posición en la órbita, escala por profundidad, giro), y
   el z-index decide si pasan por delante o por detrás de la hélice. */
.maquina--viva .maquina__pantalla {
  position: absolute;
  left: 50%;
  top: 50%;
  width: var(--maquina-pantalla-ancho);
  aspect-ratio: 16 / 10;
  margin: 0;
  border: 1px solid var(--hud-borde-fuerte);
  border-radius: 14px;
  background:
    linear-gradient(160deg, var(--maquina-vidrio-luz), transparent 45%),
    var(--maquina-vidrio);
  box-shadow:
    0 0 90px var(--hud-glow),
    0 40px 90px rgba(0, 0, 0, 0.65),
    inset 0 0 0 1px rgba(255, 255, 255, 0.04);
  overflow: hidden;
  opacity: 0;
  will-change: transform, filter, opacity;
  transition:
    border-color var(--dur-media) var(--ease),
    box-shadow var(--dur-media) var(--ease);
}

/* Con el cursor encima: el borde enciende y el halo crece. La inclinación
   hacia el cursor y el brillo que lo sigue los escribe maquina.js. */
.maquina--viva .maquina__pantalla.activa {
  border-color: var(--saffron);
  box-shadow:
    0 0 140px var(--hud-glow),
    0 40px 90px rgba(0, 0, 0, 0.65),
    inset 0 0 0 1px rgba(255, 255, 255, 0.08);
}

/* La escena llena el vidrio de borde a borde, como un video en una pantalla:
   son composiciones dedicadas a 3:2 sobre negro, así que el recorte a 16:10
   solo se come un poco de vacío arriba y abajo. */
.maquina--viva .maquina__pantalla img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* El reflejo del vidrio: una luz diagonal fija, y un brillo redondo que sigue
   al cursor (--brillo-x/--brillo-y) y se enciende con él (--brillo). */
.maquina--viva .maquina__pantalla::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(circle at var(--brillo-x, 30%) var(--brillo-y, 20%),
      rgba(255, 255, 255, calc(0.04 + 0.16 * var(--brillo, 0))), transparent 42%),
    linear-gradient(115deg, rgba(255, 255, 255, 0.07), transparent 38%);
  pointer-events: none;
}

.maquina--viva .maquina__titular--contorno {
  display: block;
  z-index: 7;
}

.maquina--viva .maquina__titular--contorno .maquina__palabra {
  --relleno: 0%;
  --contorno: 1;
}

.maquina--viva .maquina__flash {
  position: absolute;
  inset: 0;
  z-index: 8;
  background: radial-gradient(ellipse at center, var(--saffron) 0%, var(--ventana-glow) 40%, transparent 75%);
  mix-blend-mode: screen;
  opacity: 0;
  pointer-events: none;
}

/* --- Capítulos: el texto a la izquierda de la órbita ----------------------- */

.maquina--viva .maquina__capitulos {
  display: block;
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
}

.maquina--viva .maquina__capitulo {
  position: absolute;
  left: var(--maquina-margen);
  top: 50%;
  translate: 0 -50%;
  width: min(30rem, 32vw);
  max-width: none;
  padding: 0;
  border: 0;
  background: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  opacity: 0;
  pointer-events: none;
}

.maquina--viva .maquina__capitulo.activo { pointer-events: auto; }

.maquina--viva .maquina__capitulo::after { display: none; }

.maquina--viva .maquina__capitulo .area__eyebrow,
.maquina--viva .maquina__capitulo .area__como,
.maquina--viva .maquina__capitulo .area__tools {
  will-change: transform, opacity;
}

.maquina--viva .maquina__capitulo-titulo {
  font-size: var(--t-maquina-titulo);
  line-height: 0.98;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  margin-bottom: calc(var(--u) * 2.5);
  will-change: filter;
}

/* En los títulos de capítulo el relleno y el contorno viven en cada letra
   (maquina.js las separa en spans): así el cursor puede vaciar una sola letra
   y dejar las demás llenas, como en la referencia del choclo. La palabra
   queda solo como unidad de salto de línea. */
.maquina--viva .maquina__capitulo-titulo .maquina__palabra {
  background-image: none;
  -webkit-text-stroke: 0;
}

.maquina__letra {
  --relleno: 0%;
  --contorno: 1;
  display: inline-block;
  color: transparent;
  -webkit-text-stroke: 1px color-mix(in srgb, var(--saffron) calc(var(--contorno) * 100%), transparent);
  background-image: linear-gradient(var(--tinta), var(--tinta));
  background-repeat: no-repeat;
  background-size: var(--relleno) 100%;
  -webkit-background-clip: text;
  background-clip: text;
  will-change: transform, translate, background-size;
}

.maquina--viva .maquina__capitulo .area__como { font-size: var(--t-cuerpo); }

.maquina--viva .maquina__capitulo-escena { display: none; }

/* --- Remate: las pantallas se ordenan alrededor del logotipo --------------- */

.maquina--viva .maquina__remate {
  display: grid;
  justify-items: center;
  gap: calc(var(--u) * 4);
  position: absolute;
  left: 50%;
  top: 50%;
  translate: -50% -50%;
  /* Un absoluto con left: 50% se encoge a media etapa: en 844px apilaba
     las teclas. */
  width: max-content;
  max-width: calc(100% - var(--maquina-margen) * 2);
  z-index: 6;
  opacity: 0;
  will-change: transform, opacity;
}

.maquina__logotipo {
  width: min(34vw, 21rem);
  height: auto;
  filter: drop-shadow(0 0 40px var(--hud-glow));
}

/* El isotipo 3D reemplaza al logotipo plano cuando sus cuadros cargaron. */
.maquina__logo3d { display: none; }

.maquina--viva .maquina__remate.con-logo3d .maquina__logo3d {
  display: block;
  width: min(40vw, 24rem);
  height: auto;
  aspect-ratio: 1;
  filter: drop-shadow(0 0 48px var(--hud-glow));
}

.maquina--viva .maquina__remate.con-logo3d .maquina__logotipo { display: none; }

/* --- Riel de progreso --------------------------------------------------- */

.maquina--viva .maquina__riel {
  display: grid;
  gap: calc(var(--u) * 2.5);
  position: absolute;
  right: clamp(1rem, 2.5vw, 2.5rem);
  top: 50%;
  translate: 0 -50%;
  z-index: 9;
  margin: 0;
  padding: 0;
  list-style: none;
  opacity: 0;
}

.maquina__punto {
  position: relative;
  width: 8px;
  height: 8px;
  border: 1px solid var(--hud-borde-fuerte);
  border-radius: 50%;
  transition:
    background var(--dur-media) var(--ease),
    box-shadow var(--dur-media) var(--ease);
}

.maquina__punto::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 100%;
  width: 1px;
  height: calc(var(--u) * 2.5);
  background: var(--hud-borde);
}

.maquina__punto:last-child::after { display: none; }

.maquina__punto.activo {
  background: var(--saffron);
  box-shadow: 0 0 14px var(--hud-glow);
}

/* --- Medición (solo con ?medir) ------------------------------------------- */

.maquina--viva .maquina__medicion {
  display: block;
  position: absolute;
  left: var(--u);
  bottom: var(--u);
  z-index: 10;
  margin: 0;
  padding: var(--u);
  font: 500 var(--t-menor)/1.4 var(--fuente-cuerpo);
  color: var(--tinta);
  background: var(--hud-vidrio);
  border: 1px solid var(--hud-borde);
}

.maquina--viva .maquina__medicion[hidden] { display: none; }

/* --- Teléfono vertical ------------------------------------------------------
   Solo vertical: apaisado es una ventana baja (390px) y manda la altura, en
   el bloque de abajo. Se excluyen por orientación; el orden no decide. */
@media (max-width: 900px) and (orientation: portrait) {
  :root {
    /* Más ancho que la pantalla a propósito: los bordes del cuadro son vacío
       negro, y así el monitor llena el ancho y el titular lo cruza de verdad. */
    --maquina-monitor-ancho: min(120vw, 80vh);
    --maquina-pantalla-ancho: min(74vw, 46vh);
    --maquina-centro: 40%;
  }

  /* El kicker baja a acompañar al monitor: arriba quedaba una banda vacía. */
  .maquina__kicker { top: calc(var(--maquina-centro) - 26vh); }

  /* Sin polvo en el teléfono (liviano, MOTION.md sección 1): es una capa de
     pantalla completa más que componer, y a 120vw casi todo queda fuera del cuadro. */
  .maquina__polvo { display: none; }

  /* En el teléfono la guía queda solo como flecha (el texto no entra) y la
     flecha del recorrido no va: el texto del capítulo vive abajo. */
  .maquina--viva .maquina__pista-texto { display: none; }
  .maquina--viva .maquina__pista { bottom: var(--u); }
  .maquina--viva .maquina__flecha { display: none; }

  /* El texto abajo y la pantalla arriba: no hay ancho para dos columnas. */
  .maquina--viva .maquina__capitulo {
    left: var(--maquina-margen);
    right: var(--maquina-margen);
    top: auto;
    bottom: calc(var(--u) * 6);
    translate: 0;
    width: auto;
  }

  /* La altura de las pantallas la decide maquina.js (la órbita sube al 36%
     en teléfono); acá no se toca top, porque el JS mide desde el 50%. */
}

/* --- Ventana baja (un portátil de 1366x600, o un teléfono apaisado) --------
   Menos monitor, sin pista: la bajada y las teclas entran debajo del pie.
   Solo apaisado: un teléfono vertical con barra mide 664px y es un teléfono. */
@media (max-height: 720px) and (orientation: landscape) {
  :root {
    /* Lo que la altura tiene que reservar fuera del monitor: nav (4.5rem, que
       queda fija encima de la etapa), kicker (3rem), bajada de dos líneas
       (4.5rem), la guía de scroll (3rem) y aire (2rem). Sin las teclas desde el
       2026-09-16: eran 19.5rem y a 560px de alto la bajada quedaba cortada. */
    --maquina-reserva-vertical: 17rem;
    /* El monitor se dimensiona por la altura que queda, no por el ancho: el
       tramo visible del cuadro (del tope del chasis a la base del pie,
       medidos) tiene que entrar en lo que sobra. */
    --maquina-monitor-ancho: min(
      78vw,
      calc((100vh - var(--maquina-reserva-vertical)) / ((var(--monitor-base, 0.82) - var(--monitor-tope, 0.19)) * var(--monitor-aspecto, 0.56)))
    );
    /* Y sube: el chasis arranca justo debajo del kicker (que va debajo de la
       nav fija) en vez de quedar centrado con un vacío arriba. */
    --maquina-centro: calc(var(--nav-alto) + var(--maquina-margen-superior) + var(--maquina-monitor-ancho) * var(--monitor-aspecto, 0.56) * (0.5 - var(--monitor-tope, 0.19)));
  }

  .maquina__kicker { top: calc(var(--nav-alto) + var(--u)); }
  .maquina--viva .maquina__pista { bottom: calc(var(--u) * 0.5); }
  .maquina__intro { gap: calc(var(--u) * 1.5); }
}

/* --- Teléfono apaisado (844x390) --------------------------------------------
   La ventana baja con menos aire: con 19,5rem de reserva quedaba un monitor
   de 221px y el titular blanco encima (lo que Axel vio en el celular). Bajada
   chica, teclas pegadas, y los capítulos en el orden de escritorio: hay ancho
   y no hay alto. */
@media (max-width: 900px) and (orientation: landscape) {
  :root {
    --maquina-reserva-vertical: 14.5rem;
    --maquina-margen-superior: 1.5rem;
    --maquina-pantalla-ancho: min(34vw, 46vh);
    --t-maquina-titulo: clamp(1.4rem, 0.5rem + 2.6vw, 2.2rem);
  }

  .maquina__intro { gap: var(--u); }

  .maquina__bajada {
    max-width: 72ch;
    font-size: var(--t-menor);
    line-height: 1.45;
  }

  /* Centrado en lo que queda debajo de la nav fija, no en la etapa entera. */
  .maquina--viva .maquina__capitulo {
    top: calc(50% + var(--nav-alto) / 2);
    width: min(30rem, 38vw);
  }

  .maquina--viva .maquina__capitulo-titulo { margin-bottom: calc(var(--u) * 1.5); }
  .maquina--viva .maquina__capitulo .area__como { font-size: var(--t-menor); }

  /* Centrado debajo de la nav (el isotipo se metía abajo de ella);
     maquina.js lee este centro para el anillo. */
  .maquina--viva .maquina__remate {
    top: calc(50% + var(--nav-alto) / 2);
    gap: calc(var(--u) * 2.5);
  }
  .maquina__logotipo { width: min(34vw, 21rem, 32vh); }
  .maquina--viva .maquina__remate.con-logo3d .maquina__logo3d { width: min(40vw, 24rem, 36vh); }
}

@media (max-width: 620px) {
  .maquina--viva .maquina__riel { display: none; }
}

/* --- Sin movimiento --------------------------------------------------------
   maquina.js no le pone .maquina--viva a la sección cuando el visitante pidió
   menos movimiento, así que acá solo queda apagar lo que anima en CSS puro.
   Se pierde el espectáculo, no la información ni la acción. */
@media (prefers-reduced-motion: reduce) {
  .maquina__pista-flecha,
  .maquina__flecha { animation: none; }
  .maquina__punto { transition: none; }

  /* La entrada de la portada también es CSS puro desde que dejó de ser
     gsap.from(): acá se apaga sola, y como el estado normal de cada elemento
     es el final de la animación, la portada queda entera. */
  .maquina__titular .maquina__palabra,
  .maquina__kicker,
  .maquina__intro,
  .maquina__pista { animation: none; }
}

/* --- Máquina v2: la escena 3D (MOTION.md) ------------------------------------
   maquina.js decide por visita si hay GPU real; si la hay, la sección pasa a
   .maquina--3d: el canvas WebGL reemplaza al mundo 2D (lienzos y pantallas del
   DOM) y el isotipo del remate vive en la escena. Sin la clase, nada cambia. */

.maquina--viva .maquina__gl {
  display: none;
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
  pointer-events: none;
}
.maquina--3d .maquina__gl { display: block; }
/* En 3D el mundo 2D no dibuja el fondo ni las pantallas del DOM, pero su lienzo
   del polvo sigue vivo por encima del canvas WebGL: ahí van las chispas y la
   malla de puntos y rayitas de las letras bajo el cursor (el hover del choclo),
   que con el mundo apagado se perdían (Axel, 2026-09-16). */
.maquina--3d .maquina__mundo { z-index: 2; pointer-events: none; }
.maquina--3d .maquina__capa--fondo,
.maquina--3d .maquina__orbita { display: none; }

/* Teléfono vertical: el texto de capítulo va abajo y la hélice y la cinta pasan
   por atrás. Un degradado al negro en el tercio inferior del interior, por
   encima del canvas (z 1) y debajo del titular en contorno (z 7). En la portada
   no toca el vidrio (que queda alrededor del 40% del alto) y en el remate le
   da fondo al CTA. */
@media (max-width: 900px) and (orientation: portrait) {
  .maquina--3d .maquina__interior::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 2;
    background: linear-gradient(to top, rgba(0, 0, 0, 0.88) 0%, rgba(0, 0, 0, 0.62) 28%, transparent 48%);
    pointer-events: none;
  }
}
.maquina--3d .maquina__remate .maquina__logotipo,
.maquina--3d .maquina__remate .maquina__logo3d { display: none; }
