/* ==========================================================================
   AutosLeads — web pública (autosleads.cl)
   Grafito #1E293B + rojo #DC2626 sobre fondo claro #F8FAFC.
   Plus Jakarta Sans. Estética flat: bordes de 1 px, sin sombras.

   FALLA-ABIERTO: el estado base de esta hoja es la página COMPLETA y quieta.
   Todo lo que empieza escondido para poder animarse vive bajo la clase .mov,
   que pone <html> el script en línea del <head> y que se apaga sola si
   movimiento.js no llega a correr entero. Sin JS no se aplica ninguna: no
   existe forma de que la página quede muda.

   Movimiento: lo que se anima cuadro a cuadro es solo transform y opacity.
   Los cambios de color quedan en transiciones cortas de hover y de estado,
   que no corren en bucle.
   Sin dependencias externas.
   ========================================================================== */

*,
*::before,
*::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  /* --- marca --- */
  --grafito:    #1E293B;
  --grafito-2:  #334155;
  --grafito-3:  #0F172A;
  --rojo:       #DC2626;
  --rojo-os:    #B91C1C;
  --rojo-cl:    #FEF2F2;
  --rojo-bor:   #FECACA;

  /* --- superficies --- */
  --fondo:      #F8FAFC;
  --sup:        #FFFFFF;
  --sup-2:      #F1F5F9;
  --bor:        #E2E8F0;
  --bor-2:      #CBD5E1;

  /* --- texto --- */
  --tx:   #1E293B;
  --tx-2: #475569;
  --tx-3: #64748B;
  --tx-inv:   #FFFFFF;
  --tx-inv-2: #CBD5E1;
  --tx-inv-3: #94A3B8;

  /* --- semántico --- */
  --ok:     #15803D;
  --ok-cl:  #F0FDF4;
  --ok-bor: #BBF7D0;
  --verde-vivo: #4ADE80;

  /* --- ESCALA DE ESPACIADO: una sola, de base 4, y NADA fuera de ella ---
     4 · 8 · 12 · 16 · 24 · 32 · 48 · 64 · 96. Todo padding, margen y gap del
     sitio sale de aquí. Las únicas medidas crudas que quedan son las ópticas
     que no son espaciado (bordes de 1-3 px, diámetros de puntos, radios). */
  --e1: 4px;  --e2: 8px;  --e3: 12px; --e4: 16px;
  --e5: 24px; --e6: 32px; --e7: 48px; --e8: 64px; --e9: 96px;

  /* --- ritmo vertical: tres tipos de franja, tres valores, y escalan ---
     Antes el aire de sección era 96 px fijo en todos los anchos: a 360 px eso
     dejaba 192 px entre bloques, el 53 % de la pantalla. Ahora crece con el
     viewport y las juntas quedan en solo tres valores explicables:
       sección↔sección = 2·--sec   ·   sección↔franja = --sec + --band
       cierre↔pie      = --sec + --pie                                        */
  --sec:  clamp(56px, 7.2vw, 96px);   /* bloques de contenido */
  --band: clamp(36px, 4.4vw, 48px);   /* franjas compactas (tira de cifras) */
  --pie:  clamp(24px, 2.6vw, 32px);   /* pie de página */

  /* Un ÚNICO canal lateral para toda la página: cabecera, secciones y pie
     comparten este valor, así nada queda desalineado en ningún ancho. */
  --gut: clamp(20px, 5.4vw, 24px);
  --nav: 71px;                         /* alto real de la cabecera pegajosa */

  --r-sm: 8px; --r: 12px; --r-lg: 16px; --r-xl: 20px;
  --max: 1140px;

  /* --- tokens de movimiento: un solo ritmo en todo el sitio --- */
  --ease:     cubic-bezier(.16, 1, .3, 1);   /* entradas */
  --ease-in:  cubic-bezier(.55, 0, 1, .45);  /* salidas */
  --rebote:   cubic-bezier(.2, 1.5, .4, 1);  /* insignias y puntos */
  --dur-1: 160ms;  /* micro: hover, press */
  --dur-2: 280ms;  /* estados */
  --dur-3: 460ms;  /* entradas al scroll */
  --dur-4: 760ms;  /* dibujos y medidores */
}

/* El recorte horizontal va en <html>: puesto en <body> rompe position:sticky
   (el body pasa a ser el contenedor de scroll y la cabecera deja de fijarse). */
html { scroll-behavior: smooth; overflow-x: hidden; }

body {
  font-family: "Plus Jakarta Sans", "Segoe UI", -apple-system, Roboto, system-ui, sans-serif;
  font-size: 17px;
  line-height: 1.6;
  background: var(--fondo);
  color: var(--tx);
  -webkit-font-smoothing: antialiased;
}

.env { max-width: var(--max); margin: 0 auto; padding: 0 var(--gut); }
.num { font-variant-numeric: tabular-nums; font-feature-settings: "tnum" 1; }
a { color: var(--rojo-os); }
img { max-width: 100%; }
/* La cabecera mide 71 px de alto real: el ancla se detiene ahí + 16 px de aire,
   no en un 92 arbitrario que dejaba cada salto de menú 21 px corrido. */
[id] { scroll-margin-top: calc(var(--nav) + var(--e4)); }

::selection { background: var(--rojo); color: #fff; }

.sr {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* --------------------------------------------------------------------------
   1. Botones
   -------------------------------------------------------------------------- */
.btn {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center; gap: var(--e2);
  min-height: 46px; padding: var(--e3) var(--e5);
  background: var(--rojo); color: #fff;
  font: inherit; font-size: 16px; font-weight: 600; text-decoration: none;
  border: 1px solid transparent; border-radius: var(--r-sm);
  cursor: pointer; overflow: hidden;
  transition: background var(--dur-1) var(--ease),
              transform var(--dur-1) var(--ease);
}
.btn::after {                       /* barrido de luz al pasar el mouse */
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(105deg, transparent 35%, rgba(255,255,255,.28) 50%, transparent 65%);
  transform: translateX(-120%);
  transition: transform 620ms var(--ease);
}
.btn:hover { background: var(--rojo-os); transform: translateY(-1px); }
.btn:hover::after { transform: translateX(120%); }
/* Respuesta al toque: en el teléfono no hay hover, así que el press ES el único
   acuse de recibo. .97 se siente sin mover a los vecinos (el botón no cambia
   de caja, solo se escala). */
.btn:active { transform: translateY(0) scale(.97); transition-duration: 90ms; }
.btn:focus-visible { outline: 3px solid var(--grafito); outline-offset: 2px; }

.btn.sec { background: transparent; color: var(--grafito); border-color: var(--bor-2); }
.btn.sec:hover { background: var(--sup); border-color: var(--grafito); }
.btn.sec::after { display: none; }
.btn.claro { background: #fff; color: var(--rojo-os); }
.btn.claro:hover { background: var(--rojo-cl); }
.btn.claro:focus-visible { outline-color: #fff; }

.btn .fl { transition: transform var(--dur-2) var(--ease); }
.btn:hover .fl { transform: translateX(3px); }

/* --------------------------------------------------------------------------
   2. Cabecera + barra de progreso de lectura
   La altura NO se anima: cambiar height es layout. Al hacer scroll solo se
   mueven el borde (color) y el logo (transform), que son baratos por frame.
   -------------------------------------------------------------------------- */
.saltar {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--grafito); color: #fff; padding: var(--e3) var(--e4); border-radius: 0 0 var(--r-sm) 0;
}
.saltar:focus { left: 0; }

header {
  position: sticky; top: 0; z-index: 40;
  background: var(--fondo);
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur-2) var(--ease);
}
header.compacto { border-bottom-color: var(--bor); }
header .env { display: flex; align-items: center; gap: var(--e5); height: 70px; }
header .marca { display: flex; align-items: center; text-decoration: none; }
/* width:auto SIEMPRE que se fije el alto: sin él manda el atributo width del
   HTML y el logotipo se estira. La proporción real es 8:3, así que 30 px de
   alto son 80 px de ancho exactos — el mismo par que declara el atributo. */
header .marca img { height: 30px; width: auto; display: block; transform-origin: left center;
                    transition: transform var(--dur-2) var(--ease); }
header.compacto .marca img { transform: scale(.88); }

header nav { margin-left: auto; display: flex; align-items: center; gap: var(--e5); }
header nav .lnk {
  position: relative; color: var(--tx-2); text-decoration: none;
  font-size: 15px; font-weight: 500; padding: 6px 2px;
  transition: color var(--dur-1) var(--ease);
}
/* El subrayado crece desde el centro, no desde la izquierda: la misma distancia
   de recorrido a cada lado hace que se sienta más rápido con la misma duración. */
header nav .lnk::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
  background: var(--rojo); transform: scaleX(0); transform-origin: center;
  transition: transform var(--dur-2) var(--ease);
}
header nav .lnk:hover { color: var(--grafito); }
header nav .lnk:hover::after, header nav .lnk:focus-visible::after { transform: scaleX(1); }
/* Sección en la que va el visitante. Lo marca el JS; sin JS simplemente no hay
   marca, que es el estado de siempre. El color hace el trabajo y el subrayado
   lo acompaña: nunca es el color solo. */
header nav .lnk.activo { color: var(--grafito); font-weight: 600; }
header nav .lnk.activo::after { transform: scaleX(1); background: var(--rojo); }
header nav .btn { min-height: 42px; padding: var(--e2) var(--e4); font-size: 15px; }

/* Sin will-change fijo: es una barra de 2 px de color plano, la capa extra no
   compensa y dejarla puesta para siempre contradice la regla de la casa (el JS
   suelta will-change a los 1,6 s en todo lo demás). */
.progreso {
  position: absolute; left: 0; right: 0; bottom: -1px; height: 2px;
  background: var(--rojo); transform: scaleX(0); transform-origin: left;
}

/* Rótulo corto para pantallas angostas: el mismo enlace, menos texto. */
.t-sm { display: none; }

/* En el teléfono se caen los anclas de sección (el contenido está ahí abajo),
   pero "Iniciar sesión" NO se cae: sin él no hay forma de llegar a /panel/
   desde un celular, y no hay menú hamburguesa que lo reemplace. */
/* Ojo: aquí NO se toca el padding lateral. La cabecera usa el mismo --gut que
   .env, si no el logotipo queda 8 px adentro respecto de todo el resto de la
   página — que es exactamente lo que pasaba antes en todo el móvil y tablet. */
@media (max-width: 880px) {
  header nav .lnk { display: none; }
  header .env { gap: var(--e2); }
  header nav { gap: var(--e2); }
  header .marca img { height: 24px; }   /* 8:3 → 64 px de ancho exactos */
  header nav .btn { min-height: 44px; padding: var(--e2) var(--e3); font-size: 14px; }
  header nav .btn .t-lg { display: none; }
  header nav .btn .t-sm { display: inline; }
}
@media (max-width: 360px) {
  header nav .btn { padding: var(--e2); font-size: 13.5px; }
}

/* --------------------------------------------------------------------------
   3. Hero
   -------------------------------------------------------------------------- */
/* Aire simétrico: el hero era el único bloque con 96 arriba y 64 abajo, y esa
   asimetría era la que hacía que la primera junta de la página midiera distinto
   que todas las demás. */
.hero {
  position: relative; overflow: hidden;
  padding: var(--sec) 0;
  background:
    radial-gradient(1100px 460px at 12% -8%, #FEF2F2 0%, rgba(254,242,242,0) 62%),
    var(--fondo);
}
.hero .rejilla {
  position: absolute; inset: 0; pointer-events: none;
  background-image:
    linear-gradient(to right, rgba(30,41,59,.045) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(30,41,59,.045) 1px, transparent 1px);
  background-size: 56px 56px;
  -webkit-mask-image: radial-gradient(760px 420px at 70% 40%, #000 0%, transparent 78%);
  mask-image: radial-gradient(760px 420px at 70% 40%, #000 0%, transparent 78%);
}
.hero .barrido {
  position: absolute; top: 0; bottom: 0; left: 0; width: 42%;
  pointer-events: none;
  background: linear-gradient(100deg, transparent 0%, rgba(220,38,38,.055) 45%, transparent 100%);
  transform: translateX(-110%);
  animation: barrer 9s linear infinite;
}
/* Con JS vivo el barrido queda en pausa hasta que el hero se ve. Sin JS corre
   suelto: es decorativo y no vale la pena que dependa de nada. */
.mov .hero .barrido { animation-play-state: paused; }
.mov .hero.vivo .barrido { animation-play-state: running; }
@keyframes barrer { 0% { transform: translateX(-110%); } 100% { transform: translateX(340%); } }

.hero-grid {
  position: relative;
  display: grid; grid-template-columns: 1.02fr .98fr; gap: var(--e8); align-items: center;
}
@media (max-width: 980px) { .hero-grid { grid-template-columns: 1fr; gap: var(--e7); } }

.pastilla {
  display: inline-flex; align-items: center; gap: var(--e2);
  font-size: 13px; font-weight: 700; letter-spacing: .6px; text-transform: uppercase;
  color: var(--rojo-os); background: var(--rojo-cl);
  border: 1px solid var(--rojo-bor); padding: 6px var(--e3); border-radius: 99px;
}
.pastilla .lat {
  position: relative; width: 7px; height: 7px; border-radius: 50%;
  background: var(--rojo); flex: 0 0 auto;
}
.pastilla .lat::after {
  content: ""; position: absolute; inset: 0; border-radius: 50%; background: var(--rojo);
  animation: latir 2.2s var(--ease) infinite;
}
@keyframes latir {
  0%, 100% { transform: scale(1);   opacity: .55; }
  50%      { transform: scale(2.1); opacity: 0; }
}

/* -- titular: entra palabra por palabra, con máscara por línea -- */
h1 {
  font-size: clamp(38px, 5.4vw, 62px); line-height: 1.06; font-weight: 800;
  letter-spacing: -.032em; margin: var(--e5) 0 0; max-width: 16ch;
}
h1 .ln { display: block; overflow: hidden; padding-bottom: .08em; }
h1 .w { display: inline-block; }
h1 .w > i { display: inline-block; font-style: inherit; }
/* El titular solo se esconde bajo la máscara si hay quien lo saque de ahí. */
.mov h1 .w > i {
  transform: translateY(108%);
  transition: transform 760ms var(--ease);
  transition-delay: calc(var(--w, 0) * 72ms);
}
.mov body.cargado h1 .w > i { transform: translateY(0); }
h1 em { font-style: normal; color: var(--rojo); }

.bajada {
  font-size: clamp(17px, 1.9vw, 20px); color: var(--tx-2);
  margin-top: var(--e5); max-width: 52ch; font-weight: 400;
}
.acciones { margin-top: var(--e6); display: flex; gap: var(--e3); flex-wrap: wrap; }

/* --tx-2 y no --tx-3: en texto chico 4,55:1 pasa raspando la AA y cualquier
   perfil de pantalla lo tumba. Con --tx-2 el margen es 7:1. */
.vigila { margin-top: var(--e5); display: flex; align-items: center; gap: var(--e3); flex-wrap: wrap;
          font-size: 14px; color: var(--tx-2); }
.fuente {
  display: inline-flex; align-items: center; gap: var(--e2);
  background: var(--sup); border: 1px solid var(--bor); border-radius: 99px;
  padding: 6px var(--e3); font-size: 13.5px; font-weight: 600; color: var(--tx-2);
}
.fuente .pt {
  position: relative; width: 7px; height: 7px; border-radius: 50%;
  background: var(--verde-vivo); flex: 0 0 auto;
}
/* RECORTE (§7 excessive-motion): aquí había DOS aros infinitos más, y con el
   barrido y el latido de la pastilla el hero tenía cuatro bucles peleándole la
   atención al titular. Los aros de las fuentes se apagaron: los puntos verdes
   siguen diciendo "vivo" sin moverse. El aro queda solo donde es una
   affordance de verdad, en los puntos calientes del panel. */
@keyframes aro {
  0%   { transform: scale(1); opacity: .6; }
  70%  { transform: scale(3.4); opacity: 0; }
  100% { transform: scale(3.4); opacity: 0; }
}

/* --------------------------------------------------------------------------
   4. Tarjeta de alerta que se arma en vivo
   -------------------------------------------------------------------------- */
.alerta-caja { position: relative; }

.alerta {
  position: relative;
  background: var(--sup); border: 1px solid var(--bor-2); border-radius: var(--r-lg);
  overflow: hidden;
}

.alerta .barra {
  background: var(--grafito); color: #fff; padding: var(--e3) var(--e4);
  display: flex; align-items: center; gap: var(--e3);
  font-size: 13px; font-weight: 600; letter-spacing: .3px;
}
/* Segundo recorte: este punto también latía en bucle. La tarjeta ya se arma
   sola cada pasada —ese SÍ es movimiento que demuestra el producto—, así que
   el latido solo sumaba ruido al lado del titular. */
.alerta .barra .pt {
  position: relative; width: 8px; height: 8px; border-radius: 50%;
  background: var(--verde-vivo); flex: 0 0 auto;
}
.alerta .barra .et { margin-left: auto; font-weight: 500; color: var(--tx-inv-3); font-size: 12px; }

.alerta .cuerpo { position: relative; padding: var(--e5); min-height: 316px; }
@media (max-width: 420px) { .alerta .cuerpo { min-height: 344px; } }

/* -- capa de escaneo (fase 0) --
   Solo existe si hay JS que la saque: sin JS taparía la alerta para siempre.
   Al salir se apaga con visibility y se corta el shimmer: si solo se baja la
   opacidad, las 4 animaciones infinitas siguen corriendo detrás para siempre. */
.escaner { display: none; }
.mov .escaner {
  position: absolute; inset: 0; z-index: 2; padding: var(--e5); background: var(--sup);
  display: flex; flex-direction: column; gap: var(--e3);
  transition: opacity var(--dur-2) var(--ease), visibility 0s linear var(--dur-2);
}
.escaner.fuera { opacity: 0; visibility: hidden; pointer-events: none; }
.escaner.fuera .rot::after,
.escaner.fuera .leyenda .giro { animation: none; }
.escaner .rot { height: 13px; border-radius: 4px; background: var(--sup-2); position: relative; overflow: hidden; }
.escaner .rot:nth-child(1) { width: 62%; height: 20px; }
.escaner .rot:nth-child(2) { width: 44%; }
.escaner .rot:nth-child(3) { width: 78%; height: 30px; margin-top: var(--e2); }
.escaner .rot:nth-child(4) { width: 55%; }
.escaner .rot::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, rgba(203,213,225,.85), transparent);
  transform: translateX(-100%);
  animation: brillo 1.15s linear infinite;
  animation-delay: calc(var(--i, 0) * 110ms);
}
@keyframes brillo { to { transform: translateX(100%); } }
.escaner .leyenda {
  margin-top: auto; display: flex; align-items: center; gap: var(--e2);
  font-size: 13.5px; font-weight: 600; color: var(--tx-3);
}
.escaner .leyenda .giro {
  width: 15px; height: 15px; border-radius: 50%; flex: 0 0 auto;
  border: 2px solid var(--bor-2); border-top-color: var(--rojo);
  animation: girar .8s linear infinite;
}
@keyframes girar { to { transform: rotate(360deg); } }

/* -- etapas que se encienden una por una -- */
.mov .et-anim {
  opacity: 0; transform: translateY(12px);
  transition: opacity var(--dur-3) var(--ease), transform var(--dur-3) var(--ease);
}
.mov .et-anim.on { opacity: 1; transform: none; }

.alerta .auto { font-size: 21px; font-weight: 700; letter-spacing: -.4px; }
.alerta .meta { display: flex; gap: var(--e2); flex-wrap: wrap; margin-top: var(--e3); }
.alerta .meta .ch {
  font-size: 13.5px; color: var(--tx-2); background: var(--sup-2);
  border: 1px solid var(--bor); border-radius: 99px; padding: var(--e1) var(--e3);
}
.mov .alerta .meta .ch {
  opacity: 0; transform: translateY(8px) scale(.96);
  transition: opacity 320ms var(--ease), transform 320ms var(--ease);
  transition-delay: calc(var(--i, 0) * 70ms);
}
.mov .alerta .meta.on .ch { opacity: 1; transform: none; }

.alerta .precio { display: flex; align-items: baseline; gap: var(--e3); margin-top: var(--e4); flex-wrap: wrap; }
.alerta .precio .v { font-size: clamp(28px, 6vw, 34px); font-weight: 800; letter-spacing: -.03em; }

.desv {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--ok-cl); color: var(--ok); border: 1px solid var(--ok-bor);
  font-weight: 700; font-size: 15px; padding: 6px 12px; border-radius: var(--r-sm);
}
.mov .desv {
  opacity: 0; transform: scale(.72);
  transition: opacity 420ms var(--ease), transform 520ms var(--rebote);
}
.mov .desv.on { opacity: 1; transform: none; }

/* -- medidor precio vs referencia -- */
.medidor { margin-top: var(--e5); }
.medidor .pista {
  position: relative; height: 12px; border-radius: 99px;
  background: repeating-linear-gradient(-45deg, #FEE2E2 0 6px, #FECACA 6px 12px);
  overflow: hidden;
}
.medidor .relleno {
  position: absolute; inset: 0; border-radius: 99px; background: var(--grafito);
  transform: scaleX(var(--p, .82)); transform-origin: left;
}
.mov .medidor .relleno {
  transform: scaleX(0);
  transition: transform var(--dur-4) var(--ease);
}
.mov .medidor.on .relleno { transform: scaleX(var(--p, .82)); }
.medidor .pies {
  display: flex; justify-content: space-between; gap: var(--e3);
  margin-top: var(--e2); font-size: 12.5px; color: var(--tx-2);
}
.medidor .pies b { color: var(--tx); font-weight: 600; }

.ref {
  margin-top: var(--e4); padding-top: var(--e4); border-top: 1px solid var(--bor);
  font-size: 14px; color: var(--tx-2); line-height: 1.5;
}
.nota-ej { margin-top: var(--e3); font-size: 13px; color: var(--tx-2); text-align: center; }
.nota-ej b { color: var(--tx); font-weight: 700; }

/* -- control real: pausa mientras corre, repite cuando está detenida --
   Sin JS no controla nada, así que no se muestra. -- */
.control { display: none; }
.mov .control {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--sup); border: 1px solid var(--bor-2); padding: 6px var(--e3); margin-left: var(--e2);
  font: inherit; font-size: 13px; font-weight: 600; color: var(--rojo-os);
  cursor: pointer; border-radius: 99px; min-height: 34px;
  transition: border-color var(--dur-1) var(--ease), background var(--dur-1) var(--ease);
}
.control:hover { border-color: var(--rojo); background: var(--rojo-cl); }
.control:focus-visible { outline: 3px solid var(--grafito); outline-offset: 2px; }
.control svg { transition: transform 520ms var(--ease); }
.control:hover svg { transform: rotate(-180deg); }
.control .ic-pausa { display: none; }
.control[data-estado="corriendo"] .ic-pausa { display: block; }
.control[data-estado="corriendo"] .ic-repetir { display: none; }
.control[data-estado="corriendo"]:hover svg { transform: none; }

/* --------------------------------------------------------------------------
   5. Tira de indicadores con contadores
   -------------------------------------------------------------------------- */
.tira { background: var(--grafito); color: #fff; padding: var(--band) 0; overflow: hidden; }
/* Mismo gap que .bento y .limites: eran tres grillas hermanas con 32 aquí y 24
   allá, y la diferencia solo se veía en escritorio. */
.tira .grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--e5); }
@media (max-width: 900px) { .tira .grid { grid-template-columns: repeat(2, 1fr); gap: var(--e5); } }
@media (max-width: 460px) { .tira .grid { grid-template-columns: 1fr; } }

.tira .cel { position: relative; padding-left: var(--e4); }
.tira .cel::before {
  content: ""; position: absolute; left: 0; top: 4px; bottom: 4px; width: 2px;
  background: var(--rojo); transform-origin: top;
}
.mov .tira .cel::before {
  transform: scaleY(0);
  transition: transform 560ms var(--ease); transition-delay: calc(var(--i, 0) * 90ms);
}
.mov .tira .grid.on .cel::before { transform: scaleY(1); }

.tira .k { font-size: clamp(30px, 4vw, 42px); font-weight: 800; letter-spacing: -.03em; line-height: 1.05; }
.tira .k small { display: block; font-size: 15px; font-weight: 600; color: var(--tx-inv-3);
                 letter-spacing: 0; margin-top: 2px; }
.tira .l { font-size: 14px; color: var(--tx-inv-2); margin-top: var(--e2); line-height: 1.45; }
.tira .l b { color: #fff; font-weight: 700; }

/* "días → minutos": el argumento de venta convertido en microanimación.
   Aquí el falla-abierto no es cosmético: si "→ minutos" arranca en opacity 0 y
   nadie lo enciende, el indicador queda leyendo solo "días" bajo el rótulo
   "Desde que el aviso aparece hasta que llega a tu WhatsApp", o sea justo lo
   contrario de lo que vende. Por eso el estado base es el completo. */
.trueque { display: inline-flex; align-items: baseline; gap: var(--e3); flex-wrap: wrap; }
.trueque .antes { position: relative; color: var(--tx-inv-3); font-size: .62em; font-weight: 700; }
.trueque .antes::after {
  content: ""; position: absolute; left: -3px; right: -3px; top: 52%; height: 3px;
  background: var(--rojo); border-radius: 2px; transform-origin: left;
}
.trueque .fl { color: var(--tx-inv-3); font-size: .5em; }

.mov .trueque .antes::after {
  transform: scaleX(0);
  transition: transform 420ms var(--ease); transition-delay: 420ms;
}
.mov .trueque.on .antes::after { transform: scaleX(1); }
.mov .trueque .fl {
  opacity: 0; transform: translateX(-8px);
  transition: opacity 320ms var(--ease), transform 320ms var(--ease); transition-delay: 820ms;
}
.mov .trueque.on .fl { opacity: 1; transform: none; }
.mov .trueque .ahora {
  opacity: 0; transform: translateY(10px);
  transition: opacity 420ms var(--ease), transform 420ms var(--ease); transition-delay: 980ms;
}
.mov .trueque.on .ahora { opacity: 1; transform: none; }

/* --------------------------------------------------------------------------
   6. Secciones
   -------------------------------------------------------------------------- */
section { padding: var(--sec) 0; }
section.alt { background: var(--sup); border-top: 1px solid var(--bor); border-bottom: 1px solid var(--bor); }

.enc { max-width: 60ch; margin-bottom: var(--e7); }
h2 { font-size: clamp(28px, 3.6vw, 42px); font-weight: 800; letter-spacing: -.03em; line-height: 1.14; }

/* Subrayado que se dibuja bajo la palabra que carga el argumento. El trazo va
   detrás del texto (z-index -1) para no comerse las letras, y el estado base
   —sin JS— es el subrayado ya puesto. */
.subr { position: relative; white-space: nowrap; }
.subr::after {
  content: ""; position: absolute; left: -2px; right: -2px; bottom: .06em; height: .16em;
  background: var(--rojo-bor); border-radius: 3px; z-index: -1; transform-origin: left;
}
.mov .subr::after {
  transform: scaleX(0);
  transition: transform 620ms var(--ease) 260ms;
}
.mov .enc.visto .subr::after { transform: scaleX(1); }
.enc p { color: var(--tx-2); margin-top: var(--e4); font-size: 18px; }
.antetitulo {
  display: block; font-size: 13px; font-weight: 700; letter-spacing: 1.2px;
  text-transform: uppercase; color: var(--rojo-os); margin-bottom: var(--e3);
}

/* -- reveals genéricos al hacer scroll --
   Bajo .mov y nada más: es la regla que dejaba la landing en blanco cuando el
   JS no llegaba (titular, bajada, botones, gráfico, panel y cierre). -- */
.mov [data-rev] {
  opacity: 0; transform: translateY(18px);
  transition: opacity var(--dur-3) var(--ease), transform var(--dur-3) var(--ease);
  transition-delay: calc(var(--i, 0) * 80ms);
}
.mov [data-rev].visto { opacity: 1; transform: none; }

/* -- los 3 pasos, unidos por un riel que se dibuja -- */
.riel { position: relative; }
.riel .via {
  position: absolute; left: 8%; right: 8%; top: 52px; height: 2px; background: var(--bor);
}
/* La cabeza clara del degradado viaja pegada al borde que crece: se lee como
   una señal recorriendo el riel de "Detectamos" a "Te avisamos", y no cuesta
   ni un nodo ni un frame extra — es el mismo scaleX de siempre. */
.riel .via i {
  position: absolute; inset: 0; display: block; transform-origin: left;
  background: linear-gradient(90deg, var(--rojo) 0%, var(--rojo) 86%, #FCA5A5 100%);
}
.mov .riel .via i {
  transform: scaleX(0);
  transition: transform 1100ms var(--ease);
}
.mov .riel.visto .via i { transform: scaleX(1); }
@media (max-width: 900px) { .riel .via { display: none; } }

.pasos { position: relative; display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--e5); }
@media (max-width: 900px) { .pasos { grid-template-columns: 1fr; } }

.paso {
  background: var(--fondo); border: 1px solid var(--bor); border-radius: var(--r);
  padding: var(--e6) var(--e5);
  transition: transform var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease);
}
section.alt .paso { background: var(--fondo); }
.paso:hover { transform: translateY(-3px); border-color: var(--bor-2); }
.paso .ic {
  position: relative; width: 48px; height: 48px; border-radius: var(--r);
  background: var(--rojo-cl); border: 1px solid var(--rojo-bor);
  display: flex; align-items: center; justify-content: center; margin-bottom: var(--e4);
}
.paso .ic svg { width: 22px; height: 22px; stroke: var(--rojo-os); fill: none; stroke-width: 2;
                stroke-linecap: round; stroke-linejoin: round; }
/* --largo va calibrado por trazo, no un 90 genérico: así el dibujo termina
   exactamente cuando termina el path. */
.mov .paso .ic svg path, .mov .paso .ic svg circle {
  stroke-dasharray: var(--largo, 90); stroke-dashoffset: var(--largo, 90);
  transition: stroke-dashoffset 900ms var(--ease);
  transition-delay: calc(220ms + var(--i, 0) * 160ms);
}
.mov .paso.visto .ic svg path, .mov .paso.visto .ic svg circle { stroke-dashoffset: 0; }
/* Un solo pulso cuando el ícono termina de dibujarse —no un bucle—: cierra el
   gesto y deja la franja de "Cómo funciona" con acento propio. */
.paso .ic::after { content: ""; position: absolute; inset: -1px; border-radius: inherit;
                   border: 2px solid var(--rojo); opacity: 0; pointer-events: none; }
.mov .paso.visto .ic::after {
  animation: pulso-ic 900ms var(--ease) forwards;
  animation-delay: calc(900ms + var(--i, 0) * 160ms);
}
@keyframes pulso-ic {
  0%   { opacity: .85; transform: scale(1); }
  100% { opacity: 0;   transform: scale(1.45); }
}
.paso .nro {
  position: absolute; top: -9px; right: -9px; width: 22px; height: 22px; border-radius: 50%;
  background: var(--grafito); color: #fff; font-size: 11px; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}
.paso h3 { font-size: 19px; font-weight: 700; letter-spacing: -.3px; margin-bottom: var(--e2); }
.paso p { color: var(--tx-2); font-size: 16px; }

/* --------------------------------------------------------------------------
   7. Gráfico de comparables que se dibuja solo
   -------------------------------------------------------------------------- */
.grafico-caja {
  background: var(--fondo); border: 1px solid var(--bor); border-radius: var(--r-lg);
  padding: var(--e5); margin-bottom: var(--e5);
}
section.alt .grafico-caja { background: var(--fondo); }
/* En pantallas angostas el gráfico no se achica hasta volverse ilegible:
   se desliza dentro de su propia caja y el resto de la página no se mueve. */
.lienzo { overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch; }
.lienzo svg { display: block; width: 100%; height: auto; }
.desliza { display: none; font-size: 12.5px; color: var(--tx-2); margin-top: var(--e2); }
@media (max-width: 720px) {
  .lienzo svg { width: 620px; max-width: none; }
  .desliza { display: block; }
}

.gr-eje { stroke: var(--bor-2); stroke-width: 1.5; fill: none; }
.mov .gr-eje { stroke-dasharray: 700; stroke-dashoffset: 700;
               transition: stroke-dashoffset 900ms var(--ease); }
.mov .dibujado .gr-eje { stroke-dashoffset: 0; }

.gr-malla { stroke: var(--bor); stroke-width: 1; }
.mov .gr-malla { opacity: 0; transition: opacity 500ms var(--ease) 160ms; }
.mov .dibujado .gr-malla { opacity: 1; }

/* La banda es "Banda de mercado" en la leyenda: como relleno translúcido queda
   en 1,15:1 contra el fondo, así que el que carga el contraste (WCAG 1.4.11)
   es el borde, no el relleno. */
.gr-banda { fill: rgba(30, 41, 59, .09); stroke: var(--tx-3); stroke-width: 1.5;
            transform-origin: left center; transform-box: fill-box; }
.mov .gr-banda { transform: scaleX(0); transition: transform 1000ms var(--ease) 260ms; }
.mov .dibujado .gr-banda { transform: scaleX(1); }

.gr-linea { fill: none; stroke: var(--grafito); stroke-width: 2.5; stroke-linecap: round; }
.mov .gr-linea { stroke-dasharray: 640; stroke-dashoffset: 640;
                 transition: stroke-dashoffset 1200ms var(--ease) 300ms; }
.mov .dibujado .gr-linea { stroke-dashoffset: 0; }

/* .55 dejaba los comparables en 2,1:1 — justo el objeto que el gráfico pide
   leer. Con .9 sobre #F8FAFC quedan sobre 3:1 y siguen leyéndose como nube. */
.gr-pt { fill: var(--tx-3); opacity: .9;
         transform-origin: center; transform-box: fill-box; }
.mov .gr-pt { opacity: 0; transform: scale(0);
              transition: opacity 260ms var(--ease), transform 380ms var(--rebote);
              transition-delay: calc(420ms + var(--i, 0) * 22ms); }
.mov .dibujado .gr-pt { opacity: .9; transform: scale(1); }

.gr-caida { stroke: var(--rojo); stroke-width: 2; stroke-dasharray: 4 5; opacity: .9; }
.mov .gr-caida { opacity: 0; transition: opacity 380ms var(--ease) 1700ms; }
.mov .dibujado .gr-caida { opacity: .9; }

.gr-obj { fill: var(--rojo); }
.mov .gr-obj { opacity: 0; transform: translateY(-26px);
               transition: opacity 320ms var(--ease) 1450ms,
                           transform 620ms cubic-bezier(.2,1.35,.4,1) 1450ms; }
.mov .dibujado .gr-obj { opacity: 1; transform: translateY(0); }

.gr-halo { fill: none; stroke: var(--rojo); stroke-width: 2; opacity: 0; }
.mov .dibujado.late .gr-halo { animation: halo 2.6s var(--ease) infinite 2s; }
@keyframes halo {
  0%   { opacity: .6; transform: scale(.6);  transform-origin: center; transform-box: fill-box; }
  70%  { opacity: 0;  transform: scale(2.6); transform-origin: center; transform-box: fill-box; }
  100% { opacity: 0;  transform: scale(2.6); transform-origin: center; transform-box: fill-box; }
}

.gr-txt { font-family: inherit; font-size: 13px; font-weight: 600; fill: var(--tx-2); }
.mov .gr-txt { opacity: 0; transition: opacity 400ms var(--ease) 1900ms; }
.mov .dibujado .gr-txt { opacity: 1; }
.gr-txt.rojo { fill: var(--rojo-os); }
.gr-eje-txt { font-family: inherit; font-size: 12px; font-weight: 600; fill: var(--tx-2);
              letter-spacing: .4px; text-transform: uppercase; }

/* Las muestras de la leyenda repiten EXACTO lo que se ve en el gráfico: el
   punto a opacidad .9 y la banda con su borde, que es lo que da el contraste. */
.leyenda { display: flex; gap: var(--e5); flex-wrap: wrap; margin-top: var(--e4);
           font-size: 13.5px; color: var(--tx-2); }
.leyenda span { display: inline-flex; align-items: center; gap: var(--e2); }
.leyenda i { width: 11px; height: 11px; border-radius: 50%; display: block; }
.leyenda .i-cmp { background: var(--tx-3); opacity: .9; }
.leyenda .i-ban { background: rgba(30,41,59,.09); border: 1.5px solid var(--tx-3);
                  border-radius: 3px; width: 18px; height: 12px; }
.leyenda .i-obj { background: var(--rojo); }
.pie-graf { font-size: 13px; color: var(--tx-2); margin-top: var(--e3); }

/* --------------------------------------------------------------------------
   8. Bento de argumentos
   -------------------------------------------------------------------------- */
.bento { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--e5); }
@media (max-width: 860px) { .bento { grid-template-columns: 1fr; } }
.punto {
  position: relative; background: var(--sup); border: 1px solid var(--bor);
  border-radius: var(--r); padding: var(--e6) var(--e5) var(--e6) var(--e6);
  overflow: hidden;
  transition: transform var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease);
}
section.alt .punto { background: var(--fondo); }
.punto::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: var(--rojo);
  transform-origin: top;
}
.mov .punto::before {
  transform: scaleY(0);
  transition: transform 520ms var(--ease); transition-delay: calc(var(--i, 0) * 80ms + 120ms);
}
.mov .punto.visto::before { transform: scaleY(1); }
.punto:hover { transform: translateY(-3px); border-color: var(--bor-2); }
.punto h3 { font-size: 18px; font-weight: 700; margin-bottom: var(--e2); letter-spacing: -.2px; }
.punto p { color: var(--tx-2); font-size: 16px; }

/* --------------------------------------------------------------------------
   9. Los límites — lo que AutosLeads NO hace
   -------------------------------------------------------------------------- */
.limites { list-style: none; display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--e5); }
@media (max-width: 860px) { .limites { grid-template-columns: 1fr; } }
.limites li { position: relative; padding-left: var(--e7); }
.mov .limites li {
  opacity: 0; transform: translateY(16px);
  transition: opacity var(--dur-3) var(--ease), transform var(--dur-3) var(--ease);
  transition-delay: calc(var(--i, 0) * 110ms);
}
.mov .limites.visto li { opacity: 1; transform: none; }
/* La marca de "no" pasó de ser un guion plano a dibujarse: primero se traza el
   aro, después entra la barra. Es la sección que construye confianza y era la
   más quieta de la página; ahora cada límite se escribe delante del visitante.
   El estado base (sin JS) es la marca completa, como corresponde. */
.limites .no { position: absolute; left: 0; top: 2px; width: 28px; height: 28px; }
.limites .no .ar { fill: var(--fondo); stroke: var(--bor-2); stroke-width: 1.5; }
.limites .no .ln { fill: none; stroke: var(--rojo); stroke-width: 2; stroke-linecap: round; }
.mov .limites .no .ar,
.mov .limites .no .ln {
  stroke-dasharray: var(--largo, 90); stroke-dashoffset: var(--largo, 90);
  transition: stroke-dashoffset 720ms var(--ease);
  transition-delay: calc(var(--i, 0) * 110ms + 180ms);
}
.mov .limites .no .ln {
  transition-duration: 340ms;
  transition-delay: calc(var(--i, 0) * 110ms + 620ms);
}
.mov .limites.visto .no .ar,
.mov .limites.visto .no .ln { stroke-dashoffset: 0; }
.limites h3 { font-size: 18px; font-weight: 700; letter-spacing: -.2px; margin-bottom: var(--e2); }
.limites p { color: var(--tx-2); font-size: 16px; }

/* --------------------------------------------------------------------------
   10. El panel: reproducción anotada con puntos calientes
   -------------------------------------------------------------------------- */
.anotado { position: relative; }
.marco {
  background: var(--sup); border: 1px solid var(--bor-2); border-radius: var(--r-lg);
  overflow: visible;
}
.marco-barra {
  display: flex; align-items: center; gap: var(--e2);
  background: var(--sup-2); border-bottom: 1px solid var(--bor);
  border-radius: var(--r-lg) var(--r-lg) 0 0; padding: var(--e3) var(--e4);
}
.marco-barra .url {
  font-size: 12.5px; color: var(--tx-3); font-weight: 600;
  background: var(--sup); border: 1px solid var(--bor); border-radius: 6px; padding: var(--e1) var(--e3);
}
.pnl { padding: var(--e4); }
@media (max-width: 620px) { .pnl { padding: var(--e3); } }

.pnl-top { display: flex; align-items: center; gap: var(--e3); padding-bottom: var(--e3);
           border-bottom: 1px solid var(--bor); margin-bottom: var(--e6); }
.pnl-top img { height: 21px; width: auto; }   /* 8:3 → 56 px, el par del atributo */
.pnl-chip { font-size: 10px; font-weight: 800; letter-spacing: .7px; text-transform: uppercase;
            background: var(--grafito); color: #E2E8F0; padding: var(--e1) var(--e2); border-radius: 5px; }
.pnl-user { margin-left: auto; font-size: 12.5px; color: var(--tx-3); font-weight: 600; }

.filtros-rep { display: flex; gap: var(--e2); flex-wrap: wrap; background: var(--fondo);
               border: 1px solid var(--bor); border-radius: var(--r-sm); padding: var(--e3) var(--e4); }
.campo-rep { font-size: 11.5px; color: var(--tx-3); font-weight: 600; background: var(--sup);
             border: 1px solid var(--bor-2); border-radius: 6px; padding: 6px var(--e3); white-space: nowrap; }
.campo-rep b { color: var(--tx); font-weight: 700; }
.btn-rep { font-size: 11.5px; font-weight: 800; color: #fff; background: var(--rojo);
           border-radius: 6px; padding: 6px var(--e4); }

.pnl-kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--e3); }
@media (max-width: 900px) { .pnl-kpis { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 620px) { .pnl-kpis { grid-template-columns: 1fr 1fr; } }
.pnl-kpi { background: var(--fondo); border: 1px solid var(--bor);
           border-left: 3px solid var(--bor-2); border-radius: var(--r-sm); padding: var(--e3) var(--e4); }
.pnl-kpi.rojo { border-left-color: var(--rojo); }
.pnl-kpi.grafito { border-left-color: var(--grafito); }
.pnl-kpi .n { font-size: 24px; font-weight: 800; letter-spacing: -1px; line-height: 1.05;
              display: flex; align-items: center; min-height: 25px; }
.pnl-kpi.rojo .n { color: var(--rojo-os); }
.pnl-kpi .t { font-size: 11.5px; color: var(--tx-2); margin-top: var(--e1); font-weight: 700; line-height: 1.35; }
/* Valor tapado a propósito: el indicador sale de la base de cada cliente y esta
   página no inventa cifras. El borde discontinuo lo separa de un "cargando". */
.pnl-kpi .tapa {
  display: block; width: 62px; height: 17px; border-radius: 4px;
  background: var(--sup-2); border: 1px dashed var(--bor-2);
}

/* -- tabla: las columnas se esconden por breakpoint en vez de truncarse -- */
.pnl-tabla { border: 1px solid var(--bor); border-radius: var(--r-sm); overflow: hidden; }
.pnl-fila { display: grid; grid-template-columns: 2fr .7fr 1fr 1.05fr .9fr; gap: var(--e3);
            align-items: center; padding: var(--e3); font-size: 13px; border-top: 1px solid var(--bor); }
.pnl-fila.cabeza { background: var(--sup-2); border-top: none; font-size: 10.5px; font-weight: 800;
                   text-transform: uppercase; letter-spacing: .5px; color: var(--tx-2); }
.pnl-fila > * { min-width: 0; white-space: nowrap; }
.pnl-fila .der { text-align: right; }
.pnl-fila .veh { font-weight: 700; color: var(--grafito); overflow: hidden; text-overflow: ellipsis; }
.pnl-fila .precio { font-weight: 800; }
.pnl-fila .cuando { color: var(--tx-3); font-size: 12px; }
.chip-pend {
  display: inline-flex; align-items: center; font-style: normal; font-size: 11px; font-weight: 700;
  letter-spacing: .2px; padding: 3px 8px; border-radius: 5px;
  background: var(--sup-2); color: var(--tx-2); border: 1px dashed var(--bor-2);
}
.oculto-sm { display: initial; } .oculto-xs { display: initial; }
@media (max-width: 900px) {
  .oculto-sm { display: none !important; }
  .pnl-fila { grid-template-columns: 1.9fr 1fr 1.05fr .9fr; }
}
/* En el teléfono las columnas van en píxeles y no en fracciones: con fr la de
   precio caía a 70 px y "$11.490.000" (78 px) se desbordaba hasta pegarse al
   chip. Aquí el precio tiene su ancho asegurado y el que cede es el vehículo,
   que sí sabe truncar con puntos suspensivos. */
@media (max-width: 620px) {
  .oculto-xs { display: none !important; }
  .pnl-fila { grid-template-columns: minmax(0, 1fr) 82px 96px;
              font-size: 12.5px; padding: var(--e3) var(--e2); gap: var(--e2); }
  .pnl-fila.cabeza { font-size: 10.5px; letter-spacing: .1px; }
  .pnl-fila .precio { font-size: 12px; }
  .chip-pend { font-size: 10.5px; padding: 2px 6px; letter-spacing: 0; }
}
@media (max-width: 380px) {
  .pnl-fila { grid-template-columns: minmax(0, 1fr) 76px 92px; gap: 6px; padding: var(--e3) 6px; }
  .pnl-fila .precio { font-size: 11.5px; }
}

/* filas que caen en vivo */
.mov #filas-vivas .pnl-fila { opacity: 0; transform: translateY(-6px); }
.mov #filas-vivas .pnl-fila.puesta {
  opacity: 1; transform: none;
  transition: opacity 480ms var(--ease), transform 480ms var(--ease);
}
/* El destello se hace con la opacidad de una capa, no animando background:
   animar color repinta la fila entera en cada cuadro. */
#filas-vivas .pnl-fila { position: relative; isolation: isolate; }
#filas-vivas .pnl-fila.nueva::before {
  content: ""; position: absolute; inset: 0; z-index: -1; background: #FEE2E2;
  animation: destello 2.6s var(--ease) forwards;
}
@keyframes destello { from { opacity: 1; } to { opacity: 0; } }
.marca-nueva {
  font-size: 9.5px; font-weight: 800; letter-spacing: .5px; text-transform: uppercase;
  font-style: normal; color: var(--rojo-os); background: var(--rojo-cl);
  border: 1px solid var(--rojo-bor); border-radius: 4px; padding: 1px 6px; margin-left: var(--e2);
}

/* -- puntos calientes -- */
/* El hueco entre zonas es donde vive el punto caliente: el punto ocupa 34 px y
   sube 27 px sobre su zona, así que el hueco (--e6 = 32) es el escalón de la
   escala que lo deja entrar entero sin pisar la zona de arriba. */
.zona { position: relative; margin-bottom: var(--e6); transition: opacity var(--dur-2) var(--ease); }
.zona:last-child { margin-bottom: 0; }
.anotado.hay-abierta .zona:not(.abierta) { opacity: .5; }

/* Sin JS el punto no abre nada: se esconde y el callout se lee de corrido. */
.hotspot { display: none; }
/* Pegado a la esquina de su zona el punto tapaba contenido en TODOS los anchos
   —el indicador de arriba, el encabezado "Detectado" de la tabla—, no solo en
   el teléfono. Por eso se sube al hueco de arriba y ahí se queda. */
.mov .hotspot {
  display: block;
  position: absolute; right: -8px; top: -27px; width: 34px; height: 34px;
  border: none; background: transparent; cursor: pointer; padding: 0; z-index: 3;
}
.hotspot:focus-visible { outline: 3px solid var(--grafito); outline-offset: 2px; border-radius: 50%; }
.hs-p { position: absolute; inset: 7px; border-radius: 50%; background: var(--rojo); display: block; }
.hs-p::before {
  content: ""; position: absolute; inset: 0; border-radius: 50%; border: 2px solid var(--rojo);
  animation: aro 2.4s var(--ease) infinite;
}
.hs-p::after {
  content: ""; position: absolute; inset: 0; border-radius: 50%; background: #fff;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black'%3E%3Crect x='11' y='6' width='2' height='12' rx='1'/%3E%3Crect x='6' y='11' width='12' height='2' rx='1'/%3E%3C/svg%3E") center/15px no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black'%3E%3Crect x='11' y='6' width='2' height='12' rx='1'/%3E%3Crect x='6' y='11' width='12' height='2' rx='1'/%3E%3C/svg%3E") center/15px no-repeat;
  transition: transform var(--dur-2) var(--ease);
}
.zona.abierta .hs-p::after { transform: rotate(135deg); }
.zona.abierta .hs-p::before { animation: none; opacity: 0; }

/* Estado base (sin JS): el callout es un párrafo más, debajo de su zona. */
.callout {
  position: static; width: auto; margin-top: var(--e3);
  background: var(--grafito); color: #E2E8F0; border-radius: var(--r);
  padding: var(--e4); font-size: 13.5px; line-height: 1.55;
}
.callout b { display: block; color: #fff; font-size: 14.5px; font-weight: 800; margin-bottom: var(--e1); }
.callout::before { display: none; }

/* Con JS pasa a ser globo: se abre y se cierra desde el punto caliente. */
.mov .callout {
  position: absolute; right: 14px; top: calc(100% + 12px); margin-top: 0;
  width: min(330px, calc(100% - 28px)); z-index: 6;
  opacity: 0; visibility: hidden; transform: translateY(-8px) scale(.97);
  transform-origin: top right;
  transition: opacity var(--dur-2) var(--ease), transform var(--dur-2) var(--ease),
              visibility 0s linear var(--dur-2);
}
.mov .callout.izq { right: auto; left: 14px; transform-origin: top left; }
.mov .callout.sobre { top: 34px; }
.mov .callout::before {
  content: ""; display: block; position: absolute; right: 22px; top: -6px;
  width: 12px; height: 12px; background: var(--grafito); transform: rotate(45deg);
}
.mov .callout.izq::before { right: auto; left: 22px; }
.mov .zona.abierta .callout {
  opacity: 1; visibility: visible; transform: none; transition-delay: 0s;
}

/* En el teléfono el globo ocupa casi todo el ancho de la zona. */
@media (max-width: 720px) {
  .mov .callout { width: calc(100% - 8px); right: 4px; }
  .mov .callout.izq { left: 4px; }
  .mov .callout.sobre { top: 6px; }
  /* Aquí el globo ocupa el ancho completo, así que la punta va donde está el
     punto que lo abrió: arriba a la derecha, no en la esquina contraria. */
  .mov .callout::before, .mov .callout.izq::before { left: auto; right: 20px; }
}

/* --------------------------------------------------------------------------
   10 bis. Precio — un plan único, con ancla y descuento
   Un solo plan: nada de tarjetas comparativas ni un "Pro" que no existe. La
   caja reusa el lenguaje ya puesto (borde fino, sin sombra, pastilla del
   hero) y no inventa tokens nuevos. El tachado del precio de lista es
   ESTÁTICO —no depende de .mov ni de "visto"— para que se lea igual en
   cualquier posición de scroll y con o sin JavaScript: es información, no
   una demostración de movimiento.
   -------------------------------------------------------------------------- */
.plan-caja {
  max-width: 640px; margin: 0 auto;
  background: var(--sup); border: 1px solid var(--bor-2); border-radius: var(--r-lg);
  padding: var(--e7) var(--e6);
}
section.alt .plan-caja { background: var(--fondo); }
@media (max-width: 560px) { .plan-caja { padding: var(--e6) var(--e5); } }

.plan-precio { display: flex; align-items: baseline; gap: var(--e4); flex-wrap: wrap; margin-top: var(--e5); }
.plan-ancla {
  position: relative; font-size: clamp(20px, 2.6vw, 24px); font-weight: 600; color: var(--tx-2);
}
/* Mismo trazo que .br-v.tachado (la brecha del cierre), pero fijo: aquí el
   precio de lista no se "revela" al hacer scroll, se lee tachado siempre. */
.plan-ancla::after {
  content: ""; position: absolute; left: -3px; right: -3px; top: 53%; height: 2px;
  background: var(--rojo); border-radius: 2px;
}
.plan-cifra { font-size: clamp(44px, 7vw, 60px); font-weight: 800; letter-spacing: -.03em; line-height: 1; }
.plan-cuando { margin-top: var(--e3); font-size: 15.5px; color: var(--tx-2); line-height: 1.55; }
.plan-cuando b { color: var(--tx); font-weight: 700; }

.plan-valor {
  margin-top: var(--e5); padding-left: var(--e4); border-left: 3px solid var(--rojo);
  font-size: 15.5px; color: var(--tx-2); font-style: italic; line-height: 1.5;
}

.plan-div { height: 1px; border: none; background: var(--bor); margin: var(--e6) 0; }

.plan-tit { font-size: 18px; font-weight: 700; letter-spacing: -.2px; margin-bottom: var(--e4); }
.plan-incluye { list-style: none; display: flex; flex-direction: column; gap: var(--e3); }
.plan-incluye li { display: flex; align-items: flex-start; gap: var(--e3); font-size: 16px; color: var(--tx); line-height: 1.5; }
.plan-incluye svg { flex: 0 0 auto; width: 20px; height: 20px; margin-top: 2px; }
.plan-incluye circle { fill: var(--ok-cl); stroke: var(--ok-bor); stroke-width: 1.5; }
.plan-incluye path { fill: none; stroke: var(--ok); stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }

.plan-nota { margin-top: var(--e3); font-size: 14px; color: var(--tx-2); line-height: 1.6; }
.plan-nota:first-of-type { margin-top: var(--e5); }
.plan-nota b { color: var(--tx); font-weight: 700; }

.plan-cta { margin-top: var(--e6); display: flex; justify-content: center; }

/* --------------------------------------------------------------------------
   11. Cierre y pie
   -------------------------------------------------------------------------- */
.cierre {
  position: relative; overflow: hidden;
  background: var(--grafito); color: #fff; text-align: center; padding: var(--sec) 0;
}
.cierre .rejilla {
  position: absolute; inset: 0; pointer-events: none;
  background-image:
    linear-gradient(to right, rgba(255,255,255,.05) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(255,255,255,.05) 1px, transparent 1px);
  background-size: 48px 48px;
  -webkit-mask-image: radial-gradient(620px 320px at 50% 40%, #000 0%, transparent 76%);
  mask-image: radial-gradient(620px 320px at 50% 40%, #000 0%, transparent 76%);
}
.cierre .env { position: relative; }
.cierre h2 { color: #fff; max-width: 20ch; margin: 0 auto; }
.cierre p { color: var(--tx-inv-2); margin: var(--e4) auto var(--e6); max-width: 52ch; font-size: 18px; }
.cierre .pie-cierre { font-size: 14px; color: var(--tx-inv-3); margin: var(--e5) auto 0; }
.cierre .btn { font-size: 17px; padding: var(--e4) var(--e6); }

/* --- La brecha: el argumento entero en dos números, donde se decide ---------
   Es el mismo ejemplo ilustrativo de la alerta del hero, no una cifra nueva.
   El tachado se dibuja y el precio publicado sube: primero se ve lo que vale,
   después lo que pedían. Sin JS los dos números están completos y el tachado
   puesto: el bloque se entiende igual, solo que quieto. */
.brecha {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--e5);
  flex-wrap: wrap; margin: var(--e7) auto 0; padding: var(--e5) var(--e6);
  background: rgba(255,255,255,.045); border: 1px solid rgba(255,255,255,.13);
  border-radius: var(--r-lg);
}
.br-lado { display: flex; flex-direction: column; align-items: center; gap: var(--e1); }
.br-et { font-size: 12.5px; font-weight: 700; letter-spacing: .8px; text-transform: uppercase;
         color: var(--tx-inv-3); }
.br-v { position: relative; font-size: clamp(24px, 3.4vw, 32px); font-weight: 800;
        letter-spacing: -.03em; color: var(--tx-inv-2); line-height: 1.2; }
.br-lado.alta .br-v { color: #fff; }
.br-v.tachado::after {
  content: ""; position: absolute; left: -4px; right: -4px; top: 54%; height: 3px;
  background: var(--rojo); border-radius: 2px; transform-origin: left;
}
.br-fl { display: flex; color: var(--rojo); }
.mov .br-v.tachado::after {
  transform: scaleX(0);
  transition: transform 480ms var(--ease) 420ms;
}
.mov .brecha.visto .br-v.tachado::after { transform: scaleX(1); }
.mov .br-fl { opacity: 0; transform: translateX(-10px);
              transition: opacity 320ms var(--ease) 760ms, transform 420ms var(--ease) 760ms; }
.mov .brecha.visto .br-fl { opacity: 1; transform: none; }
.br-nota { font-size: 13px; color: var(--tx-inv-3); margin: var(--e3) auto var(--e6); }
@media (max-width: 560px) {
  .brecha { gap: var(--e3); padding: var(--e4) var(--e5); width: 100%; }
  .br-fl { transform: rotate(90deg); }
  .mov .brecha.visto .br-fl { transform: rotate(90deg); }
  .mov .br-fl { transform: rotate(90deg) translateX(-10px); }
}

footer { padding: var(--pie) 0; font-size: 14px; color: var(--tx-3);
         border-top: 1px solid var(--bor); background: var(--fondo); }
footer .env { display: flex; gap: var(--e4); flex-wrap: wrap;
              justify-content: space-between; align-items: center; }
/* height + width:auto: sin el width:auto mandaba el atributo del HTML y el
   logotipo salía 76 % más ancho de lo que le corresponde. Y sin opacidad: el
   .68 apagaba el rojo de marca y bajaba el grafito a 5,06:1. */
footer img { height: 21px; width: auto; display: block; }

/* --------------------------------------------------------------------------
   12. Presupuesto de movimiento del teléfono
   En el celular el movimiento tiene que ser más sobrio y más BARATO, no el
   mismo del escritorio: se apagan los bucles infinitos decorativos (el barrido
   del hero, el latido de la pastilla, el halo del gráfico), se acortan los
   escalonados —una lista de 4 con 110 ms por ítem son 440 ms de espera en una
   pantalla donde se hace scroll rápido— y se quedan solo los movimientos que
   DEMUESTRAN el producto: la alerta que se arma, el gráfico que se dibuja, la
   tabla que recibe avisos y la brecha de precio.
   -------------------------------------------------------------------------- */
@media (max-width: 720px) {
  .hero .barrido, .pastilla .lat::after { display: none; }
  .mov .dibujado.late .gr-halo { animation: none; }
  .mov .paso.visto .ic::after { animation: none; }
  .mov [data-rev] { transform: translateY(12px); transition-delay: calc(var(--i, 0) * 50ms); }
  .mov .limites .no .ar { transition-delay: calc(var(--i, 0) * 70ms + 140ms); }
  .mov .limites .no .ln { transition-delay: calc(var(--i, 0) * 70ms + 500ms); }
  .mov .limites li { transition-delay: calc(var(--i, 0) * 70ms); }
  .mov .tira .cel::before { transition-delay: calc(var(--i, 0) * 60ms); }
  .mov .gr-pt { transition-delay: calc(360ms + var(--i, 0) * 14ms); }
}

/* --------------------------------------------------------------------------
   13. Movimiento reducido — se respeta de verdad
   No basta con bajar las duraciones a 1 ms y confiar en que la transición
   alcance a correr: cada estado inicial se restaura de forma explícita y las
   animaciones infinitas se apagan con display:none.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    animation-delay: 0ms !important;
    transition-duration: .001ms !important;
    transition-delay: 0ms !important;
  }
  [data-rev], .et-anim, .desv, .alerta .meta .ch, .limites li,
  #filas-vivas .pnl-fila, .gr-pt, .gr-txt, .gr-obj, h1 .w > i {
    opacity: 1 !important; transform: none !important;
  }
  .gr-pt { opacity: .9 !important; }
  #filas-vivas .pnl-fila.nueva::before { display: none !important; }
  .gr-caida { opacity: .9 !important; }
  .gr-malla { opacity: 1 !important; }
  .gr-banda { transform: none !important; }
  .gr-eje, .gr-linea { stroke-dashoffset: 0 !important; }
  .paso .ic svg path, .paso .ic svg circle { stroke-dashoffset: 0 !important; }
  .medidor .relleno { transform: scaleX(var(--p, .82)) !important; }
  .tira .cel::before, .punto::before, .riel .via i { transform: none !important; }
  .trueque .antes::after { transform: scaleX(1) !important; }
  .trueque .fl, .trueque .ahora { opacity: 1 !important; transform: none !important; }
  .limites .no .ar, .limites .no .ln { stroke-dashoffset: 0 !important; }
  .subr::after, .br-v.tachado::after { transform: scaleX(1) !important; }
  .br-fl { opacity: 1 !important; transform: none !important; }
  .hero .barrido, .escaner, .gr-halo, .paso .ic::after,
  .pastilla .lat::after, .hs-p::before { display: none !important; }
}

/* --------------------------------------------------------------------------
   14. Impresión
   Al imprimir, Chrome vuelve a correr transiciones y animaciones en el
   documento nuevo y puede capturar el estado inicial: sin esto, una landing
   impresa sale con secciones en blanco. Se apaga todo y se fuerza lo visible.
   -------------------------------------------------------------------------- */
@media print {
  *, *::before, *::after {
    animation: none !important; transition: none !important;
  }
  .mov [data-rev], .mov .et-anim, .mov .desv, .mov .alerta .meta .ch,
  .mov .limites li, .mov #filas-vivas .pnl-fila, .mov .gr-txt, .mov .gr-obj,
  .mov h1 .w > i, .mov .trueque .fl, .mov .trueque .ahora {
    opacity: 1 !important; transform: none !important;
  }
  .mov .gr-pt { opacity: .9 !important; transform: none !important; }
  .mov .gr-caida { opacity: .9 !important; }
  .mov .gr-malla { opacity: 1 !important; }
  .mov .gr-banda, .mov .tira .cel::before, .mov .punto::before,
  .mov .riel .via i, .mov .trueque .antes::after,
  .mov .subr::after, .mov .br-v.tachado::after {
    transform: none !important;
  }
  .mov .br-fl { opacity: 1 !important; transform: none !important; }
  .mov .gr-eje, .mov .gr-linea { stroke-dashoffset: 0 !important; }
  .mov .limites .no .ar, .mov .limites .no .ln { stroke-dashoffset: 0 !important; }
  .mov .paso .ic svg path, .mov .paso .ic svg circle { stroke-dashoffset: 0 !important; }
  .mov .medidor .relleno { transform: scaleX(var(--p, .82)) !important; }
  .escaner, .hero .barrido, .progreso, .hotspot, .control { display: none !important; }
  .mov .callout {
    position: static; width: auto; margin-top: var(--e3);
    opacity: 1 !important; visibility: visible !important; transform: none !important;
  }
  .mov .callout::before { display: none !important; }
}
