/* ============================================================================
   Páginas de aterrizaje: la capa de movimiento y los bloques de diseño

   Va DESPUÉS de landing.css y solo la enlazan las aterrizajes (no servicios.html,
   que usa landing.css por el índice y no tiene por qué pagar esto). Igual que
   landing.css, no declara colores ni fuentes: todo sale de los tokens de
   styles.css.

   ---

   LA IDEA

   La página es un tablero que se enciende. El hero es el campo de circuito de
   la marca, vivo: corre señal por la retícula y una luz sigue al cursor. Cada
   tramo, al entrar, prende su costura como una unidad del rack que recibe
   corriente, y lo que tiene adentro sube en orden de lectura. Los números son
   contadores mecánicos (rodillos), no texto que parpadea. Nada se mueve para
   decorar: cada movimiento dice "esto está funcionando" o marca el orden en
   que se lee.

   ---

   LAS TRES REGLAS QUE NO SE NEGOCIAN

   1. Sin JavaScript y con prefers-reduced-motion: reduce, la página se ve
      completa y quieta. Ningún estado oculto vive en esta hoja por sí solo:
      todo lo que arranca invisible cuelga de .landing-vivo, que pone
      assets/js/landing.js en <html> SOLO si hay movimiento, y el mismo script
      marca .visto lo que ya está en pantalla antes de poner esa clase, así
      que nada visible parpadea.
      Las dos excepciones son animaciones CSS que TERMINAN visibles (la entrada
      del hero y la charla): corren sin JS y el estado final es el contenido.

   2. Solo transform y opacity (y sus propiedades sueltas translate/rotate/
      scale). Ni un width, ni un top, ni un color animado.

   3. El titular y la bajada del hero NUNCA pasan por opacity 0: uno de los dos
      es el LCP, y el LCP no puede esperar ni al JavaScript ni a una animación
      (contracts/seo-rendimiento.md, commit c869f87). Se asientan con
      translate; lo que aparece de la nada es lo que no compite por el LCP.
   ========================================================================= */

/* ============================================================================
   0. El riel sobre contenido animado

   El blur del riel se recalcula en cada cuadro en que algo se mueve debajo, y
   en estas páginas siempre hay algo moviéndose: con el blur, el A/B en Edge
   con la GPU de la laptop dio ~50 fps contra 57 de la versión quieta. Apagar
   el blur solo no sirve: el 3% de transparencia que le queda a .riel--opaca
   deja ver nítidos los titulares que pasan por debajo (el blur era lo que los
   borraba). Negro sólido y sin blur resuelve las dos cosas; 97% y 100% de
   negro no se distinguen a ojo. Arriba de todo, sin .riel--opaca, el riel
   sigue siendo el vidrio de siempre.
   ========================================================================= */

.landing-vivo .riel--hud.riel--opaca {
  background: var(--negro);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

/* Sin barra de avance de lectura: se probó (fija arriba, llenada con
   animation-timeline: scroll()) y era la pieza que más costaba. Con ella el
   p95 del scroll en la laptop era 33 ms; sin ella, 17. No vuelve. */

/* ============================================================================
   1. El hero con pieza

   .aterrizaje--pieza parte el hero en dos: texto a la izquierda, una pieza
   visual a la derecha (la charla, el despiece, o lo que traiga la próxima
   aterrizaje). Debajo de 900px es una columna y la pieza va después de las
   teclas: el titular y el botón siguen en el primer viewport del teléfono.
   ========================================================================= */

.aterrizaje__texto { position: relative; }

.aterrizaje--pieza .aterrizaje__interior {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
  gap: calc(var(--u) * 6);
  align-items: center;
}

/* Con pieza al lado el titular comparte ancho: a tamaño completo un titular de
   seis palabras baja a cuatro líneas y empuja la tecla fuera del primer
   viewport de una laptop (1280x800). */
@media (min-width: 900px) {
  .aterrizaje--pieza {
    padding-top: calc(var(--unidad) * 0.9);
  }
  .aterrizaje--pieza .aterrizaje__titular {
    font-size: calc(var(--t-hero) * 0.8);
  }
}

.aterrizaje__pieza {
  position: relative;
  justify-self: end;
  width: 100%;
  max-width: 30rem;
}

/* Inclinación hacia el cursor: landing.js escribe --rx/--ry. El paralaje del
   scroll (12b) va en el hijo, no acá, para que no se pisen los transform. */
.landing-vivo .aterrizaje__pieza {
  transform: perspective(1200px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
  transition: transform 700ms var(--ease);
}

@media (max-width: 899px) {
  .aterrizaje--pieza .aterrizaje__interior {
    grid-template-columns: minmax(0, 1fr);
    gap: calc(var(--u) * 5);
  }
  .aterrizaje__pieza { justify-self: center; max-width: 26rem; }
}

/* ============================================================================
   2. El campo: retícula viva

   Capa decorativa (aria-hidden) que va al principio de .aterrizaje y de
   .desenlace. La retícula estática de landing.css (.aterrizaje::before) sigue
   ahí; esto le agrega señal que corre por las líneas y una luz que sigue al
   cursor. Todo es transform/opacity sobre capas propias.

   Los pulsos caen justo sobre la retícula: la celda mide --u * 6 (48px) y cada
   pulso se ubica en un múltiplo de eso.
   ========================================================================= */

.campo {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

.desenlace { position: relative; overflow: hidden; }
.desenlace__interior { position: relative; }

/* En el cierre la retícula no viene de landing.css: la pone el campo. */
.desenlace .campo {
  background-image:
    linear-gradient(to right, var(--circuito-linea) 1px, transparent 1px),
    linear-gradient(to bottom, var(--circuito-linea) 1px, transparent 1px);
  background-size: calc(var(--u) * 6) calc(var(--u) * 6);
  background-position: center center;
  mask-image: radial-gradient(ellipse at 50% 60%, var(--negro) 10%, transparent 72%);
}

.campo__luz {
  position: absolute;
  left: 0;
  top: 0;
  width: 44rem;
  height: 44rem;
  margin: -22rem 0 0 -22rem;
  border-radius: 50%;
  background: radial-gradient(circle, var(--hud-superficie) 0%, var(--hud-superficie-tenue) 38%, transparent 68%);
  translate: var(--luz-x, 70vw) var(--luz-y, 30%);
  opacity: 0.9;
}

.desenlace .campo__luz { translate: var(--luz-x, 50vw) var(--luz-y, 60%); }

.campo__pulso {
  position: absolute;
  display: none;
  background: linear-gradient(to right, transparent, var(--hud-borde-fuerte) 70%, var(--luz-calida));
}

/* Horizontales: corren por una línea de la retícula de izquierda a derecha. */
.campo__pulso:nth-child(2) { top: calc(var(--u) * 6 * 2); --dur: 5.5s; --retraso: 0.4s; }
.campo__pulso:nth-child(3) { top: calc(var(--u) * 6 * 5); --dur: 7s;   --retraso: 2.2s; }
.campo__pulso:nth-child(4) { top: calc(var(--u) * 6 * 8); --dur: 6.2s; --retraso: 4.1s; }

.campo__pulso:nth-child(-n + 4) {
  left: 0;
  width: 7rem;
  height: 1px;
}

/* Verticales: bajan por una columna. */
.campo__pulso:nth-child(5) { left: calc(var(--u) * 6 * 7);  --dur: 6.8s; --retraso: 1.3s; }
.campo__pulso:nth-child(6) { left: calc(var(--u) * 6 * 17); --dur: 8s;   --retraso: 3.4s; }

.campo__pulso:nth-child(n + 5) {
  top: 0;
  width: 1px;
  height: 6rem;
  background: linear-gradient(to bottom, transparent, var(--hud-borde-fuerte) 70%, var(--luz-calida));
}

/* Los pulsos no cruzan el texto: una línea de luz que pasa sobre una palabra
   se lee como un cursor de texto perdido. En escritorio el campo del hero se
   desvanece sobre la columna del texto; en el teléfono, donde el texto ocupa
   todo el ancho, y en el cierre, que es texto centrado, no hay pulsos. */
@media (min-width: 900px) {
  .aterrizaje--pieza .campo {
    mask-image: linear-gradient(to right, transparent 0 42%, var(--negro) 62%);
  }
}

@media (max-width: 899px) {
  .campo .campo__pulso { display: none; }
}

.desenlace .campo__pulso { display: none; }

@media (prefers-reduced-motion: no-preference) {
  .campo__pulso {
    display: block;
    animation: campo-corre-x var(--dur) linear var(--retraso) infinite both;
  }
  .campo__pulso:nth-child(n + 5) { animation-name: campo-corre-y; }
  .campo--quieto .campo__pulso { animation-play-state: paused; }
}

@keyframes campo-corre-x {
  from { transform: translateX(-8rem); }
  to   { transform: translateX(110vw); }
}

@keyframes campo-corre-y {
  from { transform: translateY(-7rem); }
  to   { transform: translateY(70rem); }
}

/* ============================================================================
   3. Entrada del hero

   CSS puro, desde el primer pintado, sin esperar al JS. El rótulo y las teclas
   aparecen; el titular y la bajada solo se asientan (ver regla 3 arriba). Un
   barrido de luz cruza el titular una vez: es el tablero encendiéndose.
   ========================================================================= */

.aterrizaje__titular { position: relative; }

@media (prefers-reduced-motion: no-preference) {
  .aterrizaje__rotulo,
  .aterrizaje__teclas,
  .aterrizaje__pieza {
    animation: hero-aparece var(--dur-lenta) var(--ease) both;
  }
  .aterrizaje__rotulo  { animation-delay: 60ms; }
  .aterrizaje__teclas  { animation-delay: 420ms; }
  .aterrizaje__pieza   { animation-delay: 300ms; animation-duration: 1.2s; }

  .aterrizaje__titular { animation: hero-asienta 1.1s var(--ease) 80ms both; }
  .aterrizaje__bajada  { animation: hero-asienta 1.1s var(--ease) 220ms both; }

  .aterrizaje__titular::after {
    content: "";
    position: absolute;
    top: -10%;
    bottom: -10%;
    left: 0;
    width: 30%;
    background: linear-gradient(90deg, transparent, var(--barrido) 30%, var(--hud-superficie) 50%, var(--barrido) 70%, transparent);
    transform: translateX(-120%) skewX(-18deg);
    pointer-events: none;
    animation: hero-barrido 1.6s var(--ease) 700ms both;
  }

  .campo__luz { animation: campo-prende 1.8s var(--ease) both; }
}

@keyframes hero-aparece {
  from { opacity: 0; translate: 0 18px; }
}

@keyframes hero-asienta {
  from { translate: 0 0.45em; }
}

@keyframes hero-barrido {
  from { transform: translateX(-120%) skewX(-18deg); opacity: 1; }
  80%  { opacity: 1; }
  to   { transform: translateX(380%) skewX(-18deg); opacity: 0; }
}

@keyframes campo-prende {
  from { opacity: 0; }
}

/* ============================================================================
   4. Revelado al bajar

   landing.js pone .revela en cada pieza que entra con el scroll y .visto
   cuando la ve. --orden escalona hermanos (lo pone el mismo script). Sin
   .landing-vivo nada de esto aplica.
   ========================================================================= */

.landing-vivo .revela {
  transition:
    opacity 650ms var(--ease),
    translate 650ms var(--ease);
  transition-delay: calc(var(--orden, 0) * 70ms);
}

/* 0.001 y no 0: con opacity 0 Chrome no pinta el elemento, así que su texto
   no se rasteriza por adelantado como el resto de la página mientras se
   acerca, y todo ese trabajo cae en el cuadro del revelado (cuadros de más de
   50 ms en el A/B de scroll). Con 0.001 ya está pintado y el revelado es solo
   compositor. A ojo es invisible igual. */
.landing-vivo .revela:not(.visto) {
  opacity: 0.001;
  translate: 0 28px;
}

/* Lo que tiene el foco se ve siempre. Con Tab se puede llegar a un ítem que
   el navegador desplaza solo hasta el borde de abajo, dentro del 12% donde el
   observador todavía no lo marcó: sin esto quedaría enfocado e invisible.
   landing.js además lo marca .visto en el focusin. */
.landing-vivo .revela:focus-within {
  opacity: 1;
  translate: none;
}

/* Titulares por palabra. landing.js envuelve cada palabra en .palabra. */
.palabra { display: inline-block; }

.landing-vivo .palabra {
  transition:
    opacity 700ms var(--ease),
    translate 900ms var(--ease);
  transition-delay: calc(var(--orden, 0) * 55ms);
}

.landing-vivo .partido:not(.visto) .palabra {
  opacity: 0.001;
  translate: 0 0.6em;
}

/* La costura de cada tramo se prende al entrar: una línea de luz que corre de
   izquierda a derecha sobre la ranura. */
.tramo { position: relative; }

.landing-vivo .tramo::after {
  content: "";
  position: absolute;
  top: -1px;
  left: 0;
  right: 0;
  height: 1px;
  background: linear-gradient(to right, transparent, var(--hud-borde-fuerte) 20%, var(--saffron) 50%, var(--hud-borde-fuerte) 80%, transparent);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform 1.4s var(--ease);
  pointer-events: none;
}

.landing-vivo .tramo.visto::after { transform: scaleX(1); }

/* El rótulo lleva la marca delante: el isotipo en blanco, donde antes iba una
   raya (pedido de Axel, 2026-10-04). Aparece antes que el texto, por opacidad:
   el scaleX de la raya lo estiraría. */
.tramo__rotulo::before {
  content: "";
  display: inline-block;
  width: var(--marca);
  height: var(--marca);
  margin-right: calc(var(--u) * 1.25);
  vertical-align: middle;
  background: var(--tinta);
  -webkit-mask: var(--isotipo-justo);
  mask: var(--isotipo-justo);
}

.landing-vivo .tramo__rotulo::before { transition: opacity 900ms var(--ease) 150ms; }
.landing-vivo .tramo__rotulo:not(.visto)::before { opacity: 0; }

/* ============================================================================
   5. Cifras: los números que sí se pueden verificar

   Un tramo corto debajo del hero. Solo cifras reales (precio publicado, plazo
   del método, puntaje medible del propio sitio, ciudades donde se trabaja en
   persona). El número es texto en el HTML; landing.js lo convierte en rodillos
   mecánicos cuando va a entrar en pantalla, y deja el número original para el
   lector de pantalla.
   ========================================================================= */

.cifras {
  position: relative;
  border-top: 1px solid var(--costura-luz);
  background: var(--hud-superficie-tenue);
}

.cifras__lista {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  width: min(100%, 76rem);
  margin: 0 auto;
  padding: 0 var(--tablero-margen);
  list-style: none;
}

.cifra {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: baseline;
  column-gap: var(--u);
  padding: calc(var(--u) * 4) calc(var(--u) * 3);
  border-left: 1px solid var(--costura-luz);
}

.cifra:first-child { border-left: 0; padding-left: 0; }

.cifra__valor {
  color: var(--saffron);
  font: 700 var(--t-display)/1 var(--fuente-titulo);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.03em;
}

.cifra__unidad {
  white-space: nowrap;
  color: var(--tinta);
  font: 700 var(--t-sub)/1 var(--fuente-titulo);
}

.cifra__texto {
  grid-column: 1 / -1;
  margin-top: var(--u);
  max-width: 30ch;
  color: var(--tinta-suave);
  font-size: var(--t-menor);
}

@media (max-width: 719px) {
  .cifra,
  .cifra:first-child {
    padding: calc(var(--u) * 3) 0;
    border-left: 0;
    border-top: 1px solid var(--costura-luz);
  }
  .cifra:first-child { border-top: 0; }
}

/* Rodillos: una cinta de dígitos por posición, recortada a un dígito de alto.
   Solo se mueve la cinta (translate). */
.rodillos { display: inline-flex; }

.rodillo {
  display: inline-block;
  height: 1em;
  overflow: hidden;
}

.rodillo__cinta {
  display: flex;
  flex-direction: column;
  transition: translate 1.8s cubic-bezier(0.2, 0.9, 0.1, 1);
  transition-delay: calc(var(--orden, 0) * 140ms);
}

.rodillo__cinta > span { height: 1em; }

.visto .rodillo__cinta { translate: 0 calc(var(--destino, 0) * -1em); }

/* Texto solo para el lector de pantalla. */
.solo-lector {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ============================================================================
   6. Señal: la franja que corre

   Una por página, como máximo. Dice en frases cortas lo que la página promete,
   en tipo grande de contorno, y corre sola. Es decorativa (aria-hidden) porque
   repite lo que el texto ya dice. landing.js le cambia la velocidad según lo
   rápido que se baje, sin saltos (playbackRate de la misma animación CSS).
   ========================================================================= */

.senal {
  overflow: hidden;
  padding-block: calc(var(--u) * 3);
  border-top: 1px solid var(--costura-luz);
  border-bottom: 1px solid var(--costura-luz);
  user-select: none;
}

.senal__pista {
  display: flex;
  width: max-content;
}

.senal__grupo {
  display: flex;
  flex-shrink: 0;
}

.senal__frase {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--u) * 4);
  padding-right: calc(var(--u) * 4);
  color: transparent;
  -webkit-text-stroke: 1px var(--hud-borde-fuerte);
  font: 700 var(--t-display)/1.05 var(--fuente-titulo);
  letter-spacing: -0.02em;
  text-transform: uppercase;
  white-space: nowrap;
}

.senal__frase:nth-child(2n) {
  color: var(--tinta);
  -webkit-text-stroke: 0;
}

/* El separador: un tornillo, no un punto medio. */
.senal__frase::after {
  content: "";
  width: 0.28em;
  height: 0.28em;
  background: var(--saffron);
  transform: rotate(45deg);
}

@media (prefers-reduced-motion: no-preference) {
  .senal__pista { animation: senal-corre 38s linear infinite; }
  .senal--quieta .senal__pista { animation-play-state: paused; }
}

@keyframes senal-corre {
  to { transform: translateX(-50%); }
}

/* ============================================================================
   7. Puntos con luz: tilt y foco bajo el cursor

   Refuerza .punto de landing.css. Los tornillos de las esquinas son fondo
   estático. La luz (::before) y el tilt solo existen con puntero fino y con
   movimiento: landing.js escribe --px/--py/--rx/--ry.
   ========================================================================= */

.punto {
  position: relative;
  overflow: hidden;
  background-image:
    radial-gradient(circle at 10px 10px, var(--hud-borde) 1.5px, transparent 2.5px),
    radial-gradient(circle at calc(100% - 10px) 10px, var(--hud-borde) 1.5px, transparent 2.5px),
    radial-gradient(circle at 10px calc(100% - 10px), var(--hud-borde) 1.5px, transparent 2.5px),
    radial-gradient(circle at calc(100% - 10px) calc(100% - 10px), var(--hud-borde) 1.5px, transparent 2.5px);
}

.punto > * { position: relative; }

/* El transform 3D solo existe mientras el cursor está encima: fijo en las
   tres tarjetas eran tres capas 3D permanentes que el scroll arrastra. */
.landing-vivo .punto--luz:hover {
  transform: perspective(900px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
}

.landing-vivo .punto--luz {
  transition:
    opacity 650ms var(--ease),
    translate 650ms var(--ease),
    transform 500ms var(--ease);
  transition-delay: calc(var(--orden, 0) * 70ms), calc(var(--orden, 0) * 70ms), 0s;
}

.landing-vivo .punto--luz::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  width: 26rem;
  height: 26rem;
  margin: -13rem 0 0 -13rem;
  border-radius: 50%;
  background: radial-gradient(circle, var(--hud-superficie) 0%, transparent 65%);
  translate: var(--px, -30rem) var(--py, -30rem);
  opacity: 0;
  transition: opacity var(--dur-media) var(--ease);
  pointer-events: none;
}

.landing-vivo .punto--luz::after {
  content: "";
  position: absolute;
  inset: 0;
  border: 1px solid var(--hud-borde-fuerte);
  border-radius: inherit;
  opacity: 0;
  transition: opacity var(--dur-media) var(--ease);
  pointer-events: none;
}

.landing-vivo .punto--luz:hover::before,
.landing-vivo .punto--luz:hover::after { opacity: 1; }

/* ============================================================================
   8. Entrega: la marca aparece y el texto entra detrás

   La marca es el isotipo: entra por opacidad y no por un scaleX, que lo
   estiraba a lo ancho mientras duraba (el manual prohíbe deformarlo).
   ========================================================================= */

.landing-vivo .entrega__item::before {
  transition: opacity 700ms var(--ease);
  transition-delay: calc(var(--orden, 0) * 80ms);
}

.landing-vivo .entrega__item.revela:not(.visto)::before { opacity: 0; }
.landing-vivo .entrega__item.revela:not(.visto) { translate: -12px 0; }

/* ============================================================================
   9. Marcha: los pasos se encienden en orden con el scroll

   Cada paso tiene su línea (::after) que se llena mientras el paso cruza la
   pantalla, y el paso pasa de apagado a encendido con ella. Con
   animation-timeline: view() corre en el compositor; en fila (escritorio) el
   rango de cada uno se corre un poco, así que se encienden de a uno. Sin
   soporte, la línea no existe y los pasos quedan encendidos.
   ========================================================================= */

.marcha__paso { position: relative; padding-top: calc(var(--u) * 2); }
.marcha__paso:nth-child(1) { --i: 0; }
.marcha__paso:nth-child(2) { --i: 1; }
.marcha__paso:nth-child(3) { --i: 2; }
.marcha__paso:nth-child(4) { --i: 3; }
.marcha__paso:nth-child(5) { --i: 4; }

/* ============================================================================
   10. La charla: un chat que se escribe solo

   Pieza del hero para las páginas de agentes. SIEMPRE rotulada "Ejemplo
   ilustrativo" (PRODUCT.md principio 2: nada finge ser real) y sin nombres ni
   datos de clientes. Es una lista real: sin JS y con movimiento reducido se
   lee entera y quieta.

   El orden de aparición sale de la posición (--paso por nth-child), así que la
   próxima aterrizaje escribe otra conversación sin tocar esta hoja. Los
   mensajes del agente muestran "escribiendo" antes de aparecer.

   .charla--viva viene en el HTML: la animación corre desde el primer pintado
   y termina visible. landing.js la pausa (.charla--espera) si la charla está
   fuera de pantalla y la arranca cuando entra.
   ========================================================================= */

.charla {
  margin: 0;
  border: 1px solid var(--hud-borde);
  border-radius: var(--radio);
  background: var(--hud-vidrio);
  box-shadow: 0 0 60px var(--hud-superficie), inset 0 1px 0 var(--costura-luz);
}

.charla__cabecera {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--u);
  padding: calc(var(--u) * 1.5) calc(var(--u) * 2);
  border-bottom: 1px solid var(--hud-borde-suave);
}

.charla__cabecera .chip { flex-shrink: 0; white-space: nowrap; }

.charla__nombre {
  margin: 0;
  color: var(--tinta);
  font: 700 var(--t-menor)/1.2 var(--fuente-titulo);
}

.charla__estado {
  display: block;
  color: var(--granito-claro);
  font: 400 var(--t-placa)/1.4 var(--fuente-cuerpo);
}

.charla__lista {
  display: grid;
  gap: calc(var(--u) * 1.25);
  margin: 0;
  padding: calc(var(--u) * 2);
  list-style: none;
}

.charla__mensaje {
  display: grid;
  max-width: 85%;
}

.charla__mensaje:nth-child(1) { --paso: 0; }
.charla__mensaje:nth-child(2) { --paso: 1; }
.charla__mensaje:nth-child(3) { --paso: 2; }
.charla__mensaje:nth-child(4) { --paso: 3; }
.charla__mensaje:nth-child(5) { --paso: 4; }
.charla__mensaje:nth-child(6) { --paso: 5; }
.charla__mensaje:nth-child(7) { --paso: 6; }
.charla__mensaje:nth-child(8) { --paso: 7; }

.charla__mensaje--agente { justify-self: end; }
.charla__mensaje--aviso { justify-self: center; max-width: 100%; }

/* Burbuja y "escribiendo" comparten la misma celda: el espacio del mensaje
   está reservado desde el principio, así que nada empuja a nada. */
.charla__burbuja,
.charla__puntos { grid-area: 1 / 1; }

.charla__burbuja {
  padding: var(--u) calc(var(--u) * 1.5);
  border: 1px solid var(--hud-borde-suave);
  border-radius: var(--radio);
  background: var(--hud-superficie-tenue);
  color: var(--tinta);
  font-size: var(--t-menor);
  line-height: 1.45;
}

.charla__mensaje--agente .charla__burbuja {
  border-color: var(--hud-borde);
  background: var(--hud-superficie);
}

.charla__mensaje--aviso .charla__burbuja {
  border-style: dashed;
  border-color: var(--hud-borde-fuerte);
  background: transparent;
  color: var(--saffron);
  font: 700 var(--t-placa)/1.4 var(--fuente-titulo);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-align: center;
}

.charla__hora {
  display: block;
  margin-top: calc(var(--u) * 0.5);
  color: var(--granito-claro);
  font-size: var(--t-placa);
  text-align: right;
}

.charla__puntos {
  display: none;
  align-self: start;
  justify-self: end;
  width: calc(var(--u) * 7);
  height: calc(var(--u) * 4);
  border: 1px solid var(--hud-borde);
  border-radius: var(--radio);
  background:
    radial-gradient(circle at 30% 50%, var(--saffron) 2.5px, transparent 3.5px),
    radial-gradient(circle at 50% 50%, var(--saffron) 2.5px, transparent 3.5px),
    radial-gradient(circle at 70% 50%, var(--saffron) 2.5px, transparent 3.5px),
    var(--hud-superficie);
}

.charla__pie {
  margin: 0;
  padding: calc(var(--u) * 1.25) calc(var(--u) * 2);
  border-top: 1px solid var(--hud-borde-suave);
  color: var(--granito-claro);
  font-size: var(--t-placa);
  letter-spacing: 0.04em;
}

@media (prefers-reduced-motion: no-preference) {
  .charla--viva .charla__burbuja {
    animation: charla-entra 520ms var(--ease) both;
    animation-delay: calc(0.6s + var(--paso) * 1.25s);
  }
  .charla--viva .charla__mensaje--agente .charla__burbuja { animation-delay: calc(1.3s + var(--paso) * 1.25s); }

  .charla--viva .charla__puntos {
    display: block;
    opacity: 0;
    animation: charla-escribe 1s linear both;
    animation-delay: calc(0.3s + var(--paso) * 1.25s);
  }

  .charla--espera .charla__burbuja,
  .charla--espera .charla__puntos { animation-play-state: paused; }
}

@keyframes charla-entra {
  from { opacity: 0; translate: 0 10px; scale: 0.96; }
}

@keyframes charla-escribe {
  0%   { opacity: 0; }
  12%  { opacity: 1; }
  40%  { opacity: 0.55; }
  65%  { opacity: 1; }
  90%  { opacity: 1; }
  100% { opacity: 0; }
}

/* ============================================================================
   11. Despiece: la vista explotada de lo que lleva una página

   Pieza del hero para las páginas de diseño web. Cuatro placas apiladas en
   isométrico que se separan al cargar y se abren más al bajar (12b). Decorativa: repite en dibujo lo que la lista "Qué incluye" dice en
   texto, así que va aria-hidden.
   ========================================================================= */

.despiece {
  position: relative;
  aspect-ratio: 1;
  perspective: 1400px;
  transform-style: preserve-3d;
}

.despiece__escena {
  position: absolute;
  inset: 12% 10%;
  transform: rotateX(58deg) rotateZ(-38deg);
  transform-style: preserve-3d;
}

.despiece__capa {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: flex-end;
  padding: calc(var(--u) * 1.5);
  border: 1px solid var(--hud-borde);
  border-radius: var(--radio);
  background-color: var(--hud-vidrio);
  background-image:
    radial-gradient(circle at 8px 8px, var(--hud-borde-fuerte) 1.5px, transparent 2.5px),
    radial-gradient(circle at calc(100% - 8px) 8px, var(--hud-borde-fuerte) 1.5px, transparent 2.5px),
    radial-gradient(circle at 8px calc(100% - 8px), var(--hud-borde-fuerte) 1.5px, transparent 2.5px),
    radial-gradient(circle at calc(100% - 8px) calc(100% - 8px), var(--hud-borde-fuerte) 1.5px, transparent 2.5px),
    linear-gradient(to right, var(--circuito-linea) 1px, transparent 1px),
    linear-gradient(to bottom, var(--circuito-linea) 1px, transparent 1px);
  background-size: auto, auto, auto, auto, 24px 24px, 24px 24px;
  transform: translateZ(calc(var(--i) * 3.2rem));
}

.despiece__capa:nth-child(1) { --i: 0; }
.despiece__capa:nth-child(2) { --i: 1; }
.despiece__capa:nth-child(3) { --i: 2; }
.despiece__capa:nth-child(4) {
  --i: 3;
  border-color: var(--hud-borde-fuerte);
  box-shadow: 0 0 40px var(--hud-superficie);
}

.despiece__rotulo {
  color: var(--tinta);
  font: 700 var(--t-placa)/1.2 var(--fuente-titulo);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.despiece__capa:nth-child(4) .despiece__rotulo { color: var(--saffron); }

@media (prefers-reduced-motion: no-preference) {
  .despiece__capa {
    animation: despiece-abre 1.4s var(--ease) both;
    animation-delay: calc(500ms + var(--i) * 110ms);
  }
}

@keyframes despiece-abre {
  from { transform: translateZ(0); opacity: 0.4; }
}

/* ============================================================================
   12. Botones magnéticos, FAQ y cierre
   ========================================================================= */

/* translate y no transform: .tecla usa transform para el :active y así se
   suman en vez de pisarse. */
.landing-vivo .magnetica {
  translate: var(--mx, 0) var(--my, 0);
  transition: translate 450ms var(--ease-tecla);
}

.faq__pregunta::after { transition: transform var(--dur-media) var(--ease); }
.faq__item[open] .faq__pregunta::after { transform: rotate(180deg); }

/* ============================================================================
   12b. Todo lo que va atado al scroll

   animation-timeline en vez de un scrub de GSAP: el A/B en la laptop dio ~50
   fps con los scrub en el hilo principal y 57-58 sin ellos (ver landing.js).
   Estas corren en el compositor. Solo transform y opacity; sin soporte
   (@supports) no hay nada de esto y la página queda quieta.
   ========================================================================= */

@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    /* El hero se va: el texto sube y se apaga más rápido que el campo, y la
       pieza se queda un poco atrás. Empieza en 0 con el scroll en 0. */
    .aterrizaje { view-timeline: --hero block; }

    .aterrizaje__texto,
    .aterrizaje .campo,
    .aterrizaje__pieza > * {
      animation: hero-sale linear both;
      animation-timeline: --hero;
      animation-range: exit 0% exit 100%;
    }
    .aterrizaje .campo { animation-name: campo-baja; }
    .aterrizaje__pieza > * { animation-name: pieza-queda; }

    /* El despiece se abre más al bajar: translate suelto, que se suma al
       transform de la entrada en vez de pisarlo. */
    .despiece__capa {
      translate: 0 0 0;
      animation: despiece-abre 1.4s var(--ease) both, despiece-separa linear both;
      animation-delay: calc(500ms + var(--i) * 110ms), 0s;
      animation-timeline: auto, --hero;
      animation-range: normal, exit 0% exit 100%;
    }

    .marcha__paso {
      view-timeline: --paso block;
      animation: paso-prende linear both;
      animation-timeline: --paso;
      animation-range: entry calc(60% + var(--i) * 8%) cover calc(35% + var(--i) * 6%);
    }

    .marcha__paso::after {
      content: "";
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      height: 2px;
      background: var(--saffron);
      box-shadow: 0 0 10px var(--hud-glow);
      transform-origin: 0 50%;
      animation: linea-llena linear both;
      animation-timeline: --paso;
      animation-range: entry calc(60% + var(--i) * 8%) cover calc(40% + var(--i) * 6%);
    }

    /* El cierre: el campo se abre mientras el desenlace entra. */
    .desenlace .campo {
      animation: cierre-abre linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 55%;
    }
  }
}

@keyframes hero-sale     { to { transform: translateY(-70px); opacity: 0.2; } }
@keyframes campo-baja    { to { transform: translateY(90px); } }
@keyframes pieza-queda   { to { transform: translateY(-40px); } }
@keyframes despiece-separa { to { translate: 0 0 calc(var(--i) * 2.4rem); } }
@keyframes paso-prende   { from { opacity: 0.3; } to { opacity: 1; } }
@keyframes linea-llena   { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes cierre-abre   { from { transform: scale(0.85); opacity: 0.2; } to { transform: none; opacity: 1; } }

/* ============================================================================
   14. Casos: capturas reales en marcos dibujados

   Lo usan /casos, cada /caso-* y el bloque de prueba de las aterrizajes. Las
   capturas son de los sitios en línea de los clientes (assets/img/casos/), y
   los marcos (pantalla con barra de dirección, teléfono) son CSS: la imagen es
   lo único que finge ser una pantalla, y es una pantalla de verdad.

   Movimiento: la vitrina del hero llega con transform (sin opacity: puede ser
   el LCP y no espera a nada), el teléfono flota más rápido que la pantalla al
   bajar, y cada marco de la galería se asienta con su propia línea de tiempo.
   Todo con animation-timeline, en el compositor; sin soporte o con movimiento
   reducido, las capturas quedan quietas y completas.
   ========================================================================= */

.marco { position: relative; margin: 0; }
.marco img { display: block; width: 100%; height: auto; }

.marco--pantalla {
  overflow: hidden;
  border: 1px solid var(--hud-borde);
  border-radius: var(--radio);
  background: var(--negro-lienzo);
  box-shadow: 0 28px 70px var(--costura-sombra);
}

.marco__barra {
  display: flex;
  align-items: center;
  gap: var(--u);
  padding: 6px 12px;
  border-bottom: 1px solid var(--costura-luz);
  background: var(--acero-riel);
  color: var(--tinta-suave);
  font: 500 var(--t-placa)/1.4 var(--fuente-cuerpo);
  letter-spacing: 0.08em;
}

.marco__barra::before {
  content: "";
  width: 7px;
  height: 7px;
  border: 1px solid var(--hud-borde-fuerte);
  border-radius: 50%;
}

/* Un teléfono tiene esquinas redondas: es la única excepción al radio de 2px
   del sistema, y es la forma del objeto, no una decisión de estilo. */
.marco--telefono {
  padding: 5px;
  border-radius: 1.5rem;
  background: var(--acero);
  box-shadow: inset 0 0 0 1px var(--hammertone), 0 24px 60px var(--costura-sombra);
}

.marco--telefono img { border-radius: 1.15rem; }

/* El barrido: una franja de luz que cruza la pantalla una vez al llegar. */
.marco--pantalla::after {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 40%;
  background: linear-gradient(100deg, transparent, var(--barrido) 45%, var(--barrido) 55%, transparent);
  transform: translateX(-120%) skewX(-12deg);
  pointer-events: none;
}

.puntos--pares { grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: 60rem; }

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

.marco-figura { margin: 0; }

.pie-foto {
  margin-top: calc(var(--u) * 1.5);
  max-width: 44ch;
  color: var(--tinta-suave);
  font-size: var(--t-menor);
}

/* --- La vitrina del hero: pantalla y teléfono encimados ------------------- */

.aterrizaje__pieza--vitrina { max-width: 36rem; }

.vitrina { position: relative; padding: 0 0 14% 9%; }

.vitrina .marco--telefono {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 29%;
}

/* --- Galería: dos pantallas desfasadas y una tira de teléfonos ------------ */

.galeria-caso {
  display: grid;
  gap: calc(var(--u) * 6);
  margin-top: calc(var(--u) * 5);
}

.galeria-caso__pantallas {
  display: grid;
  grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
  gap: calc(var(--u) * 4);
  align-items: start;
}

.galeria-caso__pantallas > :nth-child(2) { margin-top: 18%; }

.tira {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: calc(var(--u) * 4);
  max-width: 52rem;
  margin: 0 auto;
  padding: 0;
  list-style: none;
}

.tira > :nth-child(2) { margin-top: 12%; --vel: -70px; }
.tira > :nth-child(3) { margin-top: 4%; --vel: -30px; }

@media (max-width: 719px) {
  .galeria-caso__pantallas { grid-template-columns: minmax(0, 1fr); }
  .galeria-caso__pantallas > :nth-child(2) { margin-top: 0; }
  .tira {
    grid-auto-flow: column;
    grid-template-columns: none;
    grid-auto-columns: 62%;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    padding-bottom: calc(var(--u) * 2);
  }
  .tira > * { scroll-snap-align: center; margin-top: 0; }
}

/* --- Ficha del cliente ------------------------------------------------------ */

.ficha {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr));
  margin: calc(var(--u) * 4) 0 0;
  border-top: 1px solid var(--costura-luz);
}

.ficha > div { padding: calc(var(--u) * 2.5) calc(var(--u) * 3) calc(var(--u) * 2.5) 0; }

.ficha dt {
  color: var(--saffron);
  font: 600 var(--t-placa)/1.4 var(--fuente-cuerpo);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.ficha dd { margin: var(--u) 0 0; }

/* --- La salida al sitio real ---------------------------------------------- */

.salida__enlace {
  display: inline-flex;
  align-items: baseline;
  gap: 0.35em;
  max-width: 100%;
  margin-top: calc(var(--u) * 2);
  padding-bottom: 0.1em;
  border-bottom: 2px solid var(--hud-borde-fuerte);
  color: var(--tinta);
  font: 700 var(--t-titulo)/1.1 var(--fuente-titulo);
  letter-spacing: -0.02em;
  overflow-wrap: anywhere;
  text-decoration: none;
}

.salida__enlace::after {
  content: "↗";
  color: var(--saffron);
  transition: transform var(--dur-media) var(--ease);
}

.salida__enlace:hover { border-bottom-color: var(--saffron); }
.salida__enlace:hover::after { transform: translate(5px, -5px); }

.salida__enlace:focus-visible,
.caso-tarjeta__enlace:focus-visible {
  outline: 2px solid var(--saffron);
  outline-offset: 6px;
}

/* --- Tarjetas de caso ------------------------------------------------------ */

.casos-lista {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
  gap: calc(var(--u) * 4);
  margin: calc(var(--u) * 4) 0 0;
  padding: 0;
  list-style: none;
}

.caso-tarjeta {
  position: relative;
  display: grid;
  align-content: start;
  gap: calc(var(--u) * 1.5);
  padding: calc(var(--u) * 2) calc(var(--u) * 2) calc(var(--u) * 3);
  border: 1px solid var(--hud-borde-suave);
  border-radius: var(--radio);
  background: var(--hud-superficie-tenue);
}

.caso-tarjeta .marco { margin-bottom: var(--u); }
.caso-tarjeta .marco img { transition: transform 900ms var(--ease); }
.caso-tarjeta:hover .marco img { transform: scale(1.04); }

.caso-tarjeta__rubro {
  color: var(--saffron);
  font: 600 var(--t-placa)/1.4 var(--fuente-cuerpo);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.caso-tarjeta__nombre { margin: 0; font-size: var(--t-sub); line-height: 1.15; }

/* El nombre es el enlace; su ::after cubre la tarjeta entera. */
.caso-tarjeta__enlace { color: inherit; text-decoration: none; }
.caso-tarjeta__enlace::after { content: ""; position: absolute; inset: 0; }

.caso-tarjeta__texto { margin: 0; color: var(--tinta-suave); }

.caso-tarjeta__ir {
  color: var(--saffron);
  font-weight: 600;
  font-size: var(--t-menor);
}

/* --- El movimiento de los casos ------------------------------------------ */

@media (prefers-reduced-motion: no-preference) {
  /* Llega sin JS y termina visible. Sin opacity: la captura puede ser el LCP. */
  .vitrina .marco--pantalla { animation: marco-llega 1.3s var(--ease) 150ms both; }
  .vitrina .marco--telefono { animation: telefono-llega 1.4s var(--ease) 450ms both; }
  .vitrina .marco--pantalla::after { animation: barrido-cruza 1.6s var(--ease) 900ms both; }

  @supports (animation-timeline: view()) {
    .vitrina .marco--telefono {
      animation: telefono-llega 1.4s var(--ease) 450ms both, telefono-sale linear both;
      animation-timeline: auto, --hero;
      animation-range: normal, exit 0% exit 100%;
      --vel: -90px;
    }

    .galeria-caso .marco {
      animation: marco-asienta linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 40%;
    }

    .galeria-caso .marco--pantalla::after {
      animation: barrido-cruza linear both;
      animation-timeline: view();
      animation-range: cover 25% cover 60%;
    }

    .tira > * {
      animation: flota linear both;
      animation-timeline: view();
      animation-range: cover;
    }
  }
}

@keyframes marco-llega    { from { transform: perspective(1400px) translateY(56px) rotateX(16deg) scale(0.94); } }
@keyframes telefono-llega { from { transform: translate(-24%, 22%) rotate(-9deg); } }
@keyframes barrido-cruza  { to { transform: translateX(320%) skewX(-12deg); } }
@keyframes marco-asienta  { from { transform: perspective(1400px) translateY(28px) rotateX(14deg) scale(0.93); opacity: 0.4; } }
@keyframes telefono-sale  { to { translate: 0 var(--vel); } }
@keyframes flota          { from { translate: 0 calc(var(--vel, -50px) * -1); } to { translate: 0 var(--vel, -50px); } }

/* ============================================================================
   15. Piezas de las páginas de precio y de ciudad

   Cada aterrizaje trae su propia idea en el hero:
   - .desglose (precio del agente): la tarjeta de precio. Los dos números,
     grandes, y lo que ganas con ellos; nada de total anual ni de desglose.
     La luz del estado late (opacity) como un "en línea".
   - .plano (precio de la web): la landing de 250 USD dibujada bloque por
     bloque, con el mismo botón después de cada uno. Repite en dibujo lo que
     el texto dice, así que va aria-hidden, como el despiece.
   - .abanico (Tulum): tres capturas reales de un sitio en teléfono.
   Entran con animaciones CSS que TERMINAN visibles, como la charla. La
   animación va en los nietos de .aterrizaje__pieza: el hijo directo ya tiene
   la suya atada al scroll (12b) y se pisarían.
   ========================================================================= */

.desglose {
  width: 100%;
  margin: 0;
  padding: calc(var(--u) * 3);
  border: 1px solid var(--hud-borde);
  border-radius: var(--radio);
  background: var(--hud-vidrio);
  box-shadow: 0 28px 70px var(--costura-sombra);
}

.desglose__cabecera {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--u) calc(var(--u) * 2);
  margin: 0 0 calc(var(--u) * 2);
  color: var(--tinta-suave);
  font: 700 var(--t-placa)/1.3 var(--fuente-titulo);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.desglose__estado { display: inline-flex; align-items: center; gap: var(--u); color: var(--tinta); }

.desglose__estado::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--saffron);
  box-shadow: 0 0 12px var(--hud-glow);
}

.desglose__filas { margin: 0; }

.desglose__fila {
  display: flex;
  flex-wrap: wrap-reverse;
  justify-content: space-between;
  align-items: baseline;
  gap: 0 calc(var(--u) * 2);
  padding: calc(var(--u) * 2) 0;
  border-top: 1px solid var(--costura-luz);
}

.desglose__fila dt { flex: 1 1 12rem; color: var(--tinta-suave); font-size: var(--t-menor); }

.desglose__fila dd {
  margin: 0;
  color: var(--saffron);
  font: 700 var(--t-titulo)/1 var(--fuente-titulo);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.desglose__nota {
  margin: 0;
  padding-top: calc(var(--u) * 2);
  border-top: 1px solid var(--costura-luz);
  color: var(--tinta);
  font: 700 var(--t-cuerpo)/1.3 var(--fuente-titulo);
}

/* Una hoja en vertical, con la proporción de una página que se lee en el
   teléfono: la landing es eso. Las líneas grises son texto dibujado, no texto. */
.plano { position: relative; max-width: 21rem; margin-inline: auto; padding-top: calc(var(--u) * 3); }

.plano__hoja {
  display: grid;
  gap: 6px;
  margin: 0;
  padding: calc(var(--u) * 1.5);
  list-style: none;
  border: 1px solid var(--hud-borde);
  border-radius: var(--radio);
  background:
    linear-gradient(to right, var(--circuito-linea) 1px, transparent 1px) 0 0 / 24px 24px,
    var(--hud-vidrio);
  box-shadow: 0 28px 70px var(--costura-sombra);
}

.plano__bloque {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: end;
  gap: var(--u);
  min-height: calc(var(--u) * 7.5);
  padding: var(--u) calc(var(--u) * 1.25);
  border: 1px dashed var(--hud-borde);
  border-radius: var(--radio);
  background: var(--hud-superficie-tenue);
  color: var(--tinta);
  font: 700 var(--t-placa)/1.25 var(--fuente-titulo);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.plano__bloque::before {
  content: "";
  grid-column: 1 / -1;
  height: 11px;
  background:
    linear-gradient(var(--hud-borde-suave) 0 0) 0 0 / 82% 3px no-repeat,
    linear-gradient(var(--hud-borde-suave) 0 0) 0 8px / 58% 3px no-repeat;
}

.plano__bloque:first-child { min-height: calc(var(--u) * 12); border-style: solid; }
.plano__bloque:first-child::before { height: 26px; background-size: 90% 8px, 64% 3px; background-position: 0 0, 0 16px; }

.plano__boton {
  padding: 3px 8px;
  border-radius: var(--radio-tecla);
  background: var(--saffron);
  color: var(--tinta-oscura);
  letter-spacing: 0.06em;
}

.plano__precio {
  position: absolute;
  top: 0;
  right: 0;
  z-index: 1;
  margin: 0;
  padding: var(--u) calc(var(--u) * 1.5);
  border: 1px solid var(--hud-borde-fuerte);
  border-radius: var(--radio);
  background: var(--negro);
  color: var(--tinta);
  font: 700 var(--t-sub)/1 var(--fuente-titulo);
  transform: rotate(4deg);
  box-shadow: 0 12px 30px var(--costura-sombra);
}

.plano__precio b { color: var(--saffron); font-size: 1.6em; }

/* Los cinco bloques de la landing van en una fila: en cuatro columnas el
   quinto quedaba solo en la segunda, como si fuera otra cosa. */
@media (min-width: 1100px) {
  .marcha--cinco { grid-template-columns: repeat(5, minmax(0, 1fr)); }
}

/* La charla fuera del hero (la de Tulum) no se estira: con el ancho del
   tramo el pie quedaba en líneas de 150 caracteres. */
.charla--tramo { max-width: 36rem; }

/* Un solo caso no se estira a todo el ancho: la captura se volvía un muro. */
.casos-lista > :only-child { max-width: 36rem; }

.abanico {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  align-items: end;
  padding: 6% 2% 10%;
}

.abanico .marco--telefono:nth-child(1) { --final: translate(12%, 8%) rotate(-8deg); }
.abanico .marco--telefono:nth-child(2) { --final: translateY(-6%) scale(1.08); z-index: 1; }
.abanico .marco--telefono:nth-child(3) { --final: translate(-12%, 8%) rotate(8deg); }
.abanico .marco--telefono { transform: var(--final); }

@media (prefers-reduced-motion: no-preference) {
  .desglose__estado::before { animation: estado-late 2.4s ease-in-out infinite alternate; }
  .desglose__nota { animation: fila-entra 900ms var(--ease) 900ms both; }

  .desglose__fila,
  .plano__bloque { animation: fila-entra 900ms var(--ease) both; animation-delay: calc(500ms + var(--n, 0) * 130ms); }
  .desglose__fila:nth-child(2), .plano__bloque:nth-child(2) { --n: 1; }
  .desglose__fila:nth-child(3), .plano__bloque:nth-child(3) { --n: 2; }
  .desglose__fila:nth-child(4), .plano__bloque:nth-child(4) { --n: 3; }
  .desglose__fila:nth-child(5), .plano__bloque:nth-child(5) { --n: 4; }

  .plano__boton { animation: boton-prende 600ms var(--ease) both; animation-delay: calc(900ms + var(--n, 0) * 130ms); }
  .plano__precio { animation: sello-cae 900ms var(--ease-tecla) 1.5s both; }

  .abanico .marco--telefono { animation: abanico-abre 1.3s var(--ease) 250ms both; }
  .abanico .marco--telefono:nth-child(1) { --desde: translateX(100%); }
  .abanico .marco--telefono:nth-child(3) { --desde: translateX(-100%); }
}

@keyframes estado-late  { to { opacity: 0.35; } }
@keyframes fila-entra   { from { transform: translateY(12px); opacity: 0; } }
@keyframes boton-prende { from { transform: scale(0.6); opacity: 0; } }
@keyframes sello-cae    { from { transform: translateY(-24px) rotate(-6deg) scale(1.2); opacity: 0; } }
@keyframes abanico-abre { from { transform: var(--desde, none); } }

/* ============================================================================
   13. Movimiento reducido e impresión: todo quieto y todo visible
   ========================================================================= */

@media (prefers-reduced-motion: reduce) {
  .faq__pregunta::after,
  .salida__enlace::after,
  .caso-tarjeta .marco img,
  .aterrizaje__pieza { transition-duration: 0.001ms; }
}

@media print {
  .landing-vivo .revela,
  .landing-vivo .palabra { opacity: 1; translate: none; }
  .campo,
  .senal { display: none; }
}
