/* ============================================================
   FUENTES PROPIAS

   Servidas desde la web, no desde Google: en la primera visita
   eran dos conexiones mas (fonts.googleapis.com y gstatic) antes
   de poder pintar una letra, y el texto cambiaba de fuente a
   media carga. Los archivos son los mismos .woff2 de Google.
   ============================================================ */
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(assets/fonts/jetbrainsmono-400-normal-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(assets/fonts/jetbrainsmono-400-normal-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(assets/fonts/jetbrainsmono-500-normal-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(assets/fonts/jetbrainsmono-500-normal-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url(assets/fonts/spacegrotesk-300-normal-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url(assets/fonts/spacegrotesk-300-normal-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(assets/fonts/spacegrotesk-400-normal-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(assets/fonts/spacegrotesk-400-normal-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(assets/fonts/spacegrotesk-500-normal-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(assets/fonts/spacegrotesk-500-normal-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(assets/fonts/spacegrotesk-600-normal-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(assets/fonts/spacegrotesk-600-normal-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(assets/fonts/spacegrotesk-700-normal-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(assets/fonts/spacegrotesk-700-normal-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ============================================================
   Studio Barrón — Web & Motion
   sb.css

   Arquitectura de escenario fijo:

     canvas.world     fixed  z0   <- el mundo Y su sombreado (sb.js)
     .stage-spacer    ALTURA REAL <- lo unico que scrollea
     .stage-overlay   fixed  z3   <- el contenido
     .cue             fixed  z4   <- indicador de deslizar

   Nada del contenido tiene altura propia. Si algo la tuviera, la
   pagina scrollearia por dos motivos a la vez y el recorrido se
   desincronizaria del texto.
   ============================================================ */

:root {
  /* Sacados del propio material: el negro es el negro del video y el
     azul es el azul de la rejilla final, para que el texto viva DENTRO
     del mundo. */
  --ink:      #04060A;
  --paper:    #EAF2FF;
  --dim:      #9AA8C0;

  --blue:     #4BAEFF;
  --blue-hi:  #8FD6FF;
  --mag:      #FF4FC8;
  --cyan:     #3BEBDF;
  /* rojo de ADVERTENCIA, no rosa ni fucsia: es la amenaza de la
     historia. Cerrado hasta donde aguanta el contraste sobre la calle
     (medido con tools/revisar.mjs; mas oscuro no pasa). */
  --red:      #E21024;

  --f-disp: "Space Grotesk", "Helvetica Neue", Arial, sans-serif;
  --f-mono: "JetBrains Mono", ui-monospace, "SF Mono", Consolas, monospace;

  --gut: clamp(20px, 3.4vw, 56px);
  --ease: cubic-bezier(.22, 1, .36, 1);
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html {
  background: var(--ink);
  /* smooth pelearia contra el scrub: el navegador animaria la posicion
     por su cuenta y el mundo perseguiria un objetivo que se mueve solo */
  scroll-behavior: auto;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

/* body SIN fondo propio: el fondo de la pagina es el de html, que es el
   color que Safari de iPhone pone en su franja de abajo (sb.js edge()) */
body {
  color: var(--paper);
  font-family: var(--f-disp);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
  text-rendering: optimizeLegibility;
}

::selection { background: var(--blue); color: #001424; }

/* ============================================================
   EL MUNDO
   ============================================================ */
canvas.world {
  position: fixed;
  left: 0; top: 0;
  width: 100vw;
  /* lvh: en el celular cubre tambien cuando la barra del navegador se
     esconde; con svh quedaria una franja vacia abajo */
  height: 100vh;
  height: 100lvh;
  object-fit: cover;
  object-position: center center;
  z-index: 0;
  background: var(--ink);
  pointer-events: none;
  /* nada de filtros encima: obligarian a recomponer el fotograma
     entero en cada dibujo */
  opacity: 0;
  transition: opacity .6s ease;
}
html.world-ready canvas.world { opacity: 1; }

/* NADA de capas a pantalla completa encima del mundo: ni grano (medido:
   costaba 4x el ritmo de la pagina) ni viñeta ni velo. El sombreado
   —viñeta, bandas y velo para el texto— se dibuja DENTRO del canvas, que
   en un celular a 3 pixeles por punto es la diferencia entre mover
   0.66 millones de pixeles o 3 millones por capa. Ver sb.js. */

/* ============================================================
   ALTURA Y ESCENARIO
   ============================================================ */
/* +14% de recorrido: es lo que cuesta que el tramo "de local a digital"
   avance a la mitad de velocidad sin acelerar el resto (ver EL RITMO DEL
   RECORRIDO en sb.js) */
.stage-spacer { height: 1940vh; width: 100%; }

/* ============================================================
   iPHONE: LA PAGINA NO SCROLLEA, SCROLLEA UNA CAJA

   Safari solo se va a pantalla completa cuando scrollea la PAGINA, y a
   pantalla completa deja abajo una franja que ninguna web puede pintar
   (probado en el iPhone de Alexander: ventana 669, pantalla completa
   777, y esos 78 px de diferencia no son pintables).

   Asi que la pagina se queda quieta y lo que scrollea es .scroller, una
   caja fija del tamaño de la ventana. Safari mantiene su barra siempre,
   nunca entra a pantalla completa y la franja no existe. Es lo que hacen
   oryzo.ai e igloo.inc, las webs que Alexander toma de referencia
   (decidido con el, 2026-09-21).

   Con la pagina quieta, el mundo vuelve a ser una capa fija normal: ya
   no hay franja que recorte capas fijas, asi que no hace falta ni el
   pegado (sticky) ni el colchon del final.
   ============================================================ */
html.iphone, html.iphone body { height: 100%; overflow: hidden; }
html.iphone .scroller {
  position: fixed; inset: 0;
  overflow-y: auto; overflow-x: hidden;
  /* el rebote no se propaga a la pagina: si lo hiciera, Safari volveria
     a jugar con sus barras */
  overscroll-behavior: none;
  -webkit-overflow-scrolling: touch;
}
/* la ventana ya es lo que se ve: el mundo mide justo eso */
html.iphone canvas.world { height: 100%; }
.tail { display: none; }

/* Colocacion contra lo que se ve DE VERDAD en iPhone. Cuando el navegador
   esconde sus barras, lo que ya estaba colocado no se recoloca: el mundo
   queda por encima del borde y las capas fijas siguen midiendo contra la
   pantalla anterior (la barra de avance flotaba por encima del borde de
   abajo). sb.js mide cada pieza y deja aqui lo que hay que correr:
   --ios-dy para lo anclado abajo y --ios-dy-c para lo que va centrado.
   Va por variable y no pisando el transform, porque DESLIZA lleva el
   suyo propio. Ver "iPHONE: COLOCAR TODO CONTRA LO QUE SE VE" en sb.js. */
.stage-overlay {
  position: fixed;
  left: 0; top: 0; width: 100%;
  /* svh: el contenido se compone dentro de lo que SIEMPRE se ve, asi no
     salta cuando la barra del navegador aparece y desaparece */
  height: 100vh;
  height: 100svh;
  z-index: 3;
  pointer-events: none;
}

/* ============================================================
   ZONAS
   ============================================================ */
.zone {
  position: absolute; inset: 0;
  display: flex; flex-direction: column;
  justify-content: center;
  padding: calc(var(--gut) * 2) var(--gut);
  opacity: 0;
  /* Apagar por visibility y no solo por opacidad: ocho capas de
     pantalla completa siempre pintadas le quitan fluidez al scrub. Lo
     que se llevan del arbol de accesibilidad lo devuelve el bloque .sr */
  visibility: hidden;
}
.zone.is-live { visibility: visible; }
.zone:not(.is-live) a { pointer-events: none; }
/* Nada se anima sin verse: una animacion dentro de una capa oculta
   sigue obligando al compositor a trabajar en cada fotograma. Medido en
   v22: seis animaciones corriendo en reposo en cualquier tramo. */
.zone:not(.is-live) *,
.zone:not(.is-live) *::before,
.zone:not(.is-live) *::after { animation-play-state: paused !important; }

.zone > * { position: relative; z-index: 1; }

.zone--c { align-items: center; text-align: center; }
.zone--l { align-items: center; text-align: left; }
.zone--r { align-items: center; text-align: right; }
/* sin tope en px: el titular escala con la pantalla y su caja tambien,
   o en pantallas grandes "TU COMPETENCIA." se partia en dos lineas */
.zone > * { max-width: 66vw; width: 100%; }
.zone--l > *, .zone--r > * { max-width: 58vw; }

/* Los tramos con la mitad de abajo encendida —la ciudad aerea, la
   rejilla que se dibuja, el resplandor final— llevan el texto ARRIBA:
   centrarlo lo pondria encima de lo unico brillante del plano. */
.zone[data-zone="beneficios"] { justify-content: flex-start; padding-top: 10vh; }
/* el salto NO: va centrado en el alto, en medio de su visor simetrico
   (Alexander, 2026-09-14). Su fondo es oscuro arriba y el velo del
   centro lo cubre; medido con tools/revisar.mjs. */
/* LOS DOS ULTIMOS TRAMOS VAN ANCLADOS AL HORIZONTE, NO A LA VENTANA.

   El fondo azul del final no es plano: medido sobre el propio fotograma
   f0695, el brillo por filas vale 30 sobre 255 a mitad de alto, 47 en el
   55%, 78 en el 60% y pica en 154 en el 65%. O sea que del 60% para
   abajo el texto se lee sobre luz.

   Por eso estos dos bloques no se centran: apoyan su borde de abajo en
   el 57% del LIENZO. Se comprueba en todas las pantallas con
   tools/horizonte.mjs. (En celular el ancla es distinta —ver el bloque
   de (max-aspect-ratio: 1/1)— porque alli el lienzo mide 100lvh y el
   texto se compone dentro de 100svh, y no son lo mismo.) */
/* Los dos ultimos tramos van sobre el fondo azul final, y ese fondo no
   es plano: medido sobre el fotograma f0695, el brillo por filas vale 30
   sobre 255 a mitad de alto, 47 en el 55%, 78 en el 60% y pica en 154 en
   el 65%. Del 60% para abajo el texto se leeria sobre luz, asi que los
   dos bloques se suben hasta que su borde de abajo queda por encima.
   Se comprueba en todas las pantallas con tools/horizonte.mjs. */
.zone[data-zone="precio"]     { justify-content: flex-start; padding-top: 4vh; }
.zone[data-zone="cta"]        { justify-content: flex-start; padding-top: 8vh; }

/* ============================================================
   TIPOGRAFIA — tres voces, y varios tamaños dentro de un titular
     grotesk  — la estructura, en bloques grandes
     serif    — la bisagra, en cursiva y mas pequeña
     mono     — etiquetas y datos

   Cada tamaño se limita por el ANCHO y por el ALTO: en 16:9 manda el
   ancho y en pantallas mas apaisadas o bajas manda el alto, asi el
   titular nunca se come la pantalla.

   Y SIN tope fijo en rem: el mundo escala con la pantalla, y si el
   texto dejara de escalar a partir de cierto tamaño, en un 1920x1080
   caeria sobre otra parte del plano que en un 1600x900 (medido: el
   punto de DIGITAL. quedaba encima de una luz del skyline, 1.32:1).
   Asi toda pantalla 16:9 es la misma composicion.
   ============================================================ */

/* La mascara recorta la palabra para que ENTRE deslizando.

   El colchon tiene que ir en la MASCARA, que es quien recorta: ponerlo
   en la palabra no servia de nada (la mascara seguia midiendo el alto
   de linea y se comia la "g" de Google). Y la mascara no sabe de que
   tamaño es su linea, asi que el tamaño viaja en --fs: la clase de
   tamaño se pone en la MASCARA, la palabra lo hereda, y el colchon se
   calcula sobre --fs.

   Con line-height .88 la caja de linea es MAS BAJA que el glifo: hace
   falta .34em abajo (la "g" y la cola del "¿" bajan .21em) y .18em
   arriba (la tilde de la Ó). El margen negativo devuelve ese aire al
   layout para que las lineas sigan apretadas. */
.mask {
  display: block;
  overflow: hidden;
  padding: calc(var(--fs, 1rem) * .18) 0 calc(var(--fs, 1rem) * .34);
  /* ...y se le devuelve al layout, o las lineas quedan sueltas unas de
     otras (Alexander, 2026-09-21). El hueco real entre la tinta de dos
     lineas queda medido con tools/tipografia.mjs. */
  margin: calc(var(--fs, 1rem) * -.13) 0 calc(var(--fs, 1rem) * -.27);
  margin: calc(var(--fs, 1rem) * -.18) 0 calc(var(--fs, 1rem) * -.34);
}
/* la cursiva es la bisagra entre bloques: necesita aire propio o su
   "y" toca la mayuscula de abajo */
.mask.s--md, .mask.s--lg {
  padding: calc(var(--fs, 1rem) * .12) 0 calc(var(--fs, 1rem) * .3);
  margin: calc(var(--fs, 1rem) * -.1) 0 calc(var(--fs, 1rem) * -.24);
}

.ttl { font-weight: 400; }

.w {
  display: block;
  font-family: var(--f-disp);
  font-weight: 700;
  font-size: var(--fs, 1rem);
  line-height: .88;
  letter-spacing: -.045em;
  text-wrap: balance;
}
/* las clases de tamaño solo declaran --fs: asi sirven puestas en la
   mascara (que necesita el dato para su colchon) o en la palabra */
/* UN PUNTO MAS GRANDE, NI UNO MAS (Alexander, 2026-09-23: "te dije que
   lo agrandes un poco nomas").

   Estos titulares van SIEMPRE en una sola linea: partirlos en dos cambia
   la composicion, y la composicion ya estaba aprobada. Eso pone un techo
   que no se puede saltar: medido en 1600x900 con la columna de 66vw,
   "TU COMPETENCIA" ya ocupaba el 90% de su columna, asi que el margen
   real para crecer era del 10-15%, no del 40%. Es lo que se sube aqui.
   tools/revisar.mjs avisa en cuanto uno se parte en dos. */
.w--xxl { --fs: max(3.2rem, min(11.7vw, 20.8vh)); }
.w--xl  { --fs: max(2.4rem, min(8.3vw, 14.8vh)); }
.w--lg  { --fs: max(2rem, min(6.2vw, 11vh)); }
.w--md  { --fs: max(1.6rem, min(4.7vw, 8.4vh)); }
.w--sm  { --fs: max(1.2rem, min(2.6vw, 4.6vh)); }
.w--soft { font-weight: 400; letter-spacing: -.015em; line-height: 1.08; }

.w--blue { color: var(--blue); }
.w--mag  { color: var(--mag); }
.w--cyan { color: var(--cyan); }
/* "TU COMPETENCIA" manda en su tramo: es el golpe de la historia, asi
   que va un punto por encima del resto de titulares de su tamaño */
.zone[data-zone="costo"] .w--xl { --fs: max(2.6rem, min(7.9vw, 14.1vh)); }
/* El golpe ya toca el 90% de su columna y no da mas de si: la que crece
   es la linea de apoyo, que iba al 55%. */
.zone[data-zone="costo"] .w--sm { --fs: max(1.3rem, min(3.2vw, 5.7vh)); }
/* "¿TE ENCUENTRAN?" es el titular mas largo de su tamaño: con el valor
   general se iria al 95% de la columna y se partiria en dos. */
.zone[data-zone="problema"] .w--xl { --fs: max(2.4rem, min(7.7vw, 13.7vh)); }
.w--red  {
  color: var(--red);
  /* resplandor rojo + halo oscuro: el rojo oscuro necesita separarse
     del plano para no perderse sobre los escaparates */
  text-shadow: 0 0 28px rgba(255, 45, 60, .5), 0 0 70px rgba(255, 25, 45, .28),
               0 2px 22px rgba(2, 4, 8, .96), 0 0 9px rgba(2, 4, 8, .92);
}

/* "¿" a la altura de las mayusculas: medido en Space Grotesk 700, el
   "¿" ocupa de -.21 a .51 em y el "?" de 0 a .71 — subirlo .2em los
   pone en la misma franja, y deja de colgar fuera de la mascara */
.inv { position: relative; top: -.2em; }

/* LA COMPETENCIA — roja y con falla de señal. Dos copias del texto
   (cian y blanca) saltan desfasadas en rafagas cortas, y el propio
   texto parpadea. Solo transform y opacidad: la GPU lo compone sin
   repintar. Rafagas contadas, no infinitas: una animacion que no para
   mantiene la tarjeta de video trabajando para siempre. */
/* las copias van DETRAS del texto (isolation + z-index -1): el rojo
   manda siempre y la falla se ve como bordes desfasados. Encima, la
   copia cian volvia cian la palabra entera en cada rafaga. */
.glitch { position: relative; isolation: isolate; }
.glitch::before,
.glitch::after {
  content: attr(data-text);
  position: absolute; inset: 0;
  z-index: -1;
  padding: inherit;
  pointer-events: none;
  opacity: 0;
}
.glitch::before { color: var(--cyan); }
.glitch::after  { color: #FFFFFF; }
/* Las rafagas las dispara sb.js cada ~2.4 s mientras el tramo se ve, y
   duran 0.42 s. Asi se repiten siempre, pero ENTRE rafaga y rafaga no
   queda ninguna animacion corriendo (una animacion infinita mantiene a
   la tarjeta de video componiendo la pantalla entera sin parar). */
.glitch.is-glitch::before { animation: glitch-a .56s steps(1, end) 1; }
.glitch.is-glitch::after  { animation: glitch-b .56s steps(1, end) 1; }
@keyframes glitch-a {
  0%        { opacity: 1;   transform: translate(-.105em, .02em);  clip-path: inset(6% 0 58% 0); }
  14%       { opacity: .95; transform: translate(.085em, -.018em); clip-path: inset(44% 0 26% 0); }
  26%       { opacity: 0;   transform: translate(0, 0); }
  40%       { opacity: 1;   transform: translate(-.075em, .016em); clip-path: inset(66% 0 4% 0); }
  52%       { opacity: .9;  transform: translate(.06em, 0);        clip-path: inset(24% 0 48% 0); }
  66%       { opacity: 0;   transform: translate(0, 0); }
  80%       { opacity: .8;  transform: translate(-.05em, -.01em);  clip-path: inset(52% 0 18% 0); }
  88%, 100% { opacity: 0;   transform: translate(0, 0); clip-path: inset(0 0 0 0); }
}
@keyframes glitch-b {
  0%        { opacity: .85; transform: translate(.1em, -.022em);  clip-path: inset(18% 0 44% 0); }
  12%       { opacity: 0;   transform: translate(0, 0); }
  34%       { opacity: .8;  transform: translate(-.085em, .02em); clip-path: inset(0 0 70% 0); }
  46%       { opacity: 0;   transform: translate(0, 0); }
  62%       { opacity: .75; transform: translate(.07em, .012em);  clip-path: inset(58% 0 12% 0); }
  76%, 100% { opacity: 0;   transform: translate(0, 0); clip-path: inset(0 0 0 0); }
}

/* La palabra misma se RASGA: trozos que saltan de sitio un fotograma,
   como una señal que se corta. Va en pasos (steps) para que sean saltos
   secos, no un movimiento suave, y termina siempre en su sitio. */
@keyframes glitch-corte {
  0%        { transform: translate(0, 0);        clip-path: inset(0 0 0 0); }
  10%       { transform: translate(.035em, 0);   clip-path: inset(34% 0 40% 0); }
  18%       { transform: translate(-.03em, 0);   clip-path: inset(0 0 0 0); }
  30%       { transform: translate(0, 0); }
  44%       { transform: translate(-.045em, 0);  clip-path: inset(62% 0 12% 0); }
  52%       { transform: translate(.02em, 0);    clip-path: inset(0 0 0 0); }
  70%       { transform: translate(.03em, 0);    clip-path: inset(12% 0 66% 0); }
  78%, 100% { transform: translate(0, 0);        clip-path: inset(0 0 0 0); }
}
/* el parpadeo va DESPUES del desfase: si coinciden, el rojo a media luz
   sobre la copia cian se ve turbio */
@keyframes redflick {
  0%, 22%   { opacity: 1; }
  28%       { opacity: .2; }
  34%       { opacity: 1; }
  48%       { opacity: .45; }
  54%       { opacity: 1; }
  64%       { opacity: .6; }
  70%, 100% { opacity: 1; }
}
.w--glow {
  /* Nucleo BLANCO con aura azul, como un tubo de neon. En azul puro el
     punto de "DIGITAL." caia sobre ventanas encendidas del skyline y se
     medía 1.6:1; el blanco se lee sobre cualquier luz y el aura
     conserva el azul del tramo. */
  color: #F4FAFF;
  text-shadow: 0 0 14px rgba(75, 174, 255, .95), 0 0 42px rgba(61, 165, 255, .6),
               0 0 110px rgba(61, 165, 255, .3), 0 2px 24px rgba(2, 4, 8, .9);
}

/* LA LINEA DE ENLACE ("Antes de ir,", "se va con", "a", "y").
   Era cursiva serif y Alexander la rechazo por tercera vez (2026-09-23).
   Ahora es la misma familia del titular en su peso mas fino: el contraste
   ya no lo da otra tipografia, lo da el PESO —300 contra 800— y eso es lo
   que se ve caro. Sin cursiva en ningun sitio de la web. */
.s {
  display: block;
  font-family: var(--f-disp);
  font-style: normal;
  font-weight: 300;
  font-size: var(--fs, 1rem);
  line-height: 1.06;
  letter-spacing: -.015em;
  color: var(--paper);
}
.s--lg { --fs: max(2rem, min(5.6vw, 10vh)); }
.s--md { --fs: max(1.35rem, min(3.35vw, 6vh)); }
/* Linea suelta bajo un titular. Sus trazos finos sobre escaparates
   encendidos se veian dentados: va mas grande, en blanco puro, con un
   halo oscuro en tres capas que la despega del fondo y una sombra del
   propio color que engorda medio pixel el trazo. */
.s--sub {
  --fs: max(1.6rem, min(3.6vw, 6.4vh));
  margin-top: .3em;
  line-height: 1.14;
  color: #FFFFFF;
  text-shadow: 0 0 1px rgba(255, 255, 255, .9),
               0 0 8px rgba(2, 4, 8, .98), 0 2px 16px rgba(2, 4, 8, .95),
               0 0 34px rgba(2, 4, 8, .85);
  text-wrap: balance;
}

.m {
  display: inline-block;
  font-family: var(--f-mono);
  font-size: clamp(11px, .82vw, 14px);
  font-weight: 500;
  letter-spacing: .26em;
  text-transform: uppercase;
  color: var(--blue-hi);
  text-shadow: 0 1px 14px rgba(2, 4, 8, .95), 0 0 4px rgba(2, 4, 8, .8);
}

.kicker { margin-bottom: clamp(12px, 2vh, 26px); }

/* Parrafo de apoyo: texto normal, legible, no mono en mayusculas */
.lede {
  margin-top: clamp(9px, 1.6vh, 19px);
  font-family: var(--f-disp);
  font-weight: 400;
  font-size: clamp(1rem, min(1.35vw, 2.45vh), 1.6rem);
  line-height: 1.45;
  color: var(--paper);
  text-shadow: 0 1px 14px rgba(2, 4, 8, .95), 0 0 5px rgba(2, 4, 8, .85);
  text-wrap: balance;
}
.lede b { font-weight: 600; color: var(--cyan); }

/* ============================================================
   NEON — el letrero del inicio y la competencia encendida
   El encendido va en un ENVOLTORIO que solo mueve opacidad (la GPU la
   compone sin repintar). filter: brightness() costaba un repintado por
   fotograma: medido, un pico de 0.833s de desfase contra 0.395s.
   ============================================================ */
@keyframes neon {
  0%, 11%, 19% { opacity: .12; }
  6%, 15%, 27% { opacity: 1; }
  100%         { opacity: 1; }
}
.flick { display: block; }
.zone.is-live .flick { animation: neon 1s steps(1, end) .3s 1 both; }
.zone.is-live .flick--mag  { animation-delay: .6s; }
.glitch.is-glitch { animation: redflick .56s steps(1, end) 1, glitch-corte .56s steps(1, end) 1; }
.zone.is-live .flick--hero { animation-delay: 1.05s; animation-duration: 1.2s; }

/* ============================================================
   EL WORDMARK — entra encendiendose
   Una linea de escaneo baja por el bloque y cada letra prende a su
   paso, con un parpadeo corto. Nada de mascara: asi no hay recorte y
   las letras pueden llevar su propio brillo.
   ============================================================ */
.wordmark { position: relative; }
.wm__ch { display: inline-block; }
.wm__scan {
  position: absolute; top: 0; left: -3%; right: -3%;
  height: max(2px, calc(var(--fs, 1rem) * .05));
  border-radius: 2px;
  background: linear-gradient(to right, transparent, rgba(143, 214, 255, .85) 18%, #FFFFFF 50%, rgba(143, 214, 255, .85) 82%, transparent);
  box-shadow: 0 0 24px 5px rgba(61, 165, 255, .55);
  opacity: 0;
  pointer-events: none;
}

.neon { margin-top: clamp(10px, 1.7vh, 22px); }
.neon__txt {
  display: inline-block;
  font-family: var(--f-disp);
  font-style: normal;
  font-weight: 300;
  letter-spacing: -.015em;
  /* 3.3vw es su techo: a 3.6 la frase pasa de los 1056 px de la columna
     en una pantalla de 1600 y se parte en dos */
  font-size: max(1.7rem, min(3.3vw, 5.9vh));
  line-height: 1.12;
  color: #F6FCFF;
  /* nucleo blanco, dos resplandores y un halo oscuro debajo: se lee
     sobre fachadas grises y sobre letreros encendidos */
  text-shadow: 0 0 1px #fff, 0 0 9px rgba(143, 214, 255, .9), 0 0 24px rgba(59, 235, 223, .55),
               0 0 52px rgba(61, 165, 255, .4), 0 2px 22px rgba(2, 4, 8, .92);
  text-wrap: balance;
}

/* ============================================================
   LA BUSQUEDA — se escribe sola mientras el tramo esta encendido
   ============================================================ */
.search-row { margin-block: clamp(18px, 3vh, 34px); }
.search {
  display: inline-flex; align-items: center; gap: 12px;
  width: min(100%, 31rem);
  height: clamp(50px, 6.4vh, 62px);
  padding: 0 22px;
  border-radius: 999px;
  background: rgba(5, 9, 16, .88);
  border: 1px solid rgba(143, 214, 255, .4);
  box-shadow: 0 0 0 4px rgba(61, 165, 255, .08), 0 20px 60px -24px rgba(61, 165, 255, .75);
  font-family: var(--f-disp);
  font-size: clamp(16px, 1.2vw, 20px);
  color: var(--paper);
  text-align: left;
}
.search__ico {
  flex: none; width: 20px; height: 20px;
  fill: none; stroke: var(--blue-hi); stroke-width: 2; stroke-linecap: round;
}
.search__q { white-space: nowrap; overflow: hidden; }
.search__caret {
  flex: none; width: 2px; height: 1.15em; margin-left: -9px;
  background: var(--blue-hi); box-shadow: 0 0 8px var(--blue);
  animation: caret 1.05s steps(1) infinite;
  transition: opacity .4s var(--ease);
}
@keyframes caret { 50% { opacity: 0; } }
/* terminada la ronda de busquedas, el cursor se apaga: nada queda
   latiendo mientras el visitante lee */
.search.is-done .search__caret { animation: none; opacity: 0; }

/* ============================================================
   FICHAS — lo que trae la web, con icono que se dibuja
   ============================================================ */
.chips {
  list-style: none;
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: 12px;
  margin-top: clamp(22px, 3.6vh, 42px);
}
/* Todo en em: la ficha escala con la pantalla igual que los titulares
   (con un tope en px quedaba diminuta en 1920 al lado de "MÁS VENTAS").
   El borde es un degradado de verdad: el fondo se pinta en padding-box
   y el degradado en border-box. */
.chip {
  position: relative;
  display: inline-flex; align-items: center; gap: .7em;
  padding: .62em 1.35em .62em .62em;
  border-radius: 999px;
  border: 1px solid transparent;
  background:
    linear-gradient(rgba(9, 15, 26, .94), rgba(4, 8, 15, .94)) padding-box,
    linear-gradient(130deg, rgba(143, 214, 255, .9), rgba(59, 235, 223, .55) 42%, rgba(61, 165, 255, .18)) border-box;
  box-shadow: 0 14px 34px -18px rgba(0, 0, 0, .95), inset 0 1px 0 rgba(255, 255, 255, .1);
  font-family: var(--f-disp);
  font-weight: 600;
  font-size: max(13px, min(1.06vw, 1.9vh));
  letter-spacing: .06em;
  text-transform: uppercase;
  line-height: 1.1;
  color: var(--paper);
  white-space: nowrap;
  transition: transform .35s var(--ease), box-shadow .35s var(--ease);
}
.chip__ico {
  flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.1em; height: 2.1em;
  border-radius: 50%;
  background: radial-gradient(circle at 32% 26%, rgba(59, 235, 223, .32), rgba(61, 165, 255, .1) 72%);
  box-shadow: inset 0 0 0 1px rgba(143, 214, 255, .35), 0 0 18px -6px rgba(59, 235, 223, .8);
}
.chip svg {
  flex: none; width: 1.15em; height: 1.15em;
  fill: none; stroke: var(--cyan); stroke-width: 1.9;
  stroke-linecap: round; stroke-linejoin: round;
}
.chip svg * { stroke-dasharray: 1; stroke-dashoffset: 1; transition: stroke-dashoffset 1s var(--ease); }
.zone.is-live .chip svg * { stroke-dashoffset: 0; }
.zone.is-live .chip:nth-child(1) svg * { transition-delay: .55s; }
.zone.is-live .chip:nth-child(2) svg * { transition-delay: .7s; }
.zone.is-live .chip:nth-child(3) svg * { transition-delay: .85s; }
@media (hover: hover) {
  .chip:hover { transform: translateY(-2px); box-shadow: 0 18px 40px -18px rgba(61, 165, 255, .9), inset 0 1px 0 rgba(255, 255, 255, .16); }
}

/* ============================================================
   BARRA DE AVANCE — al ras del borde inferior, un color por tramo
   Se mueve por transform (la compone la GPU) y solo cambia de color
   cuando cambia el tramo. Queda debajo del indicador DESLIZA.
   ============================================================ */
.prog {
  position: fixed; left: 0; right: 0; bottom: 0;
  height: 3px;
  z-index: 5;
  background: rgba(234, 242, 255, .09);
  pointer-events: none;
}
.prog i {
  display: block; height: 100%; width: 100%;
  transform: scaleX(0);
  transform-origin: left center;
  background: var(--accent, #4BAEFF);
  box-shadow: 0 0 14px var(--accent, #4BAEFF);
  transition: background .55s var(--ease), box-shadow .55s var(--ease);
}

/* ============================================================
   DE LOCAL A DIGITAL
   ============================================================ */
.ttl--beat .mask + .mask { margin-top: -.02em; }
.scan-row { display: block; }
.w.scan { display: inline-block; position: relative; }
.scan__line {
  position: absolute; left: 0; top: -4%; bottom: 0;
  width: 3px; margin-left: -1.5px; border-radius: 2px;
  background: linear-gradient(to bottom, transparent, #D6F4FF 18%, #fff 50%, #D6F4FF 82%, transparent);
  box-shadow: 0 0 16px 3px rgba(61, 165, 255, .85), 0 0 56px 12px rgba(61, 165, 255, .35);
  opacity: 0;
  pointer-events: none;
}

/* Visor del tramo "de local a digital": esquinas y dos rieles con
   marcas. Entra con el tramo y no se anima despues: son lineas de 1px
   sobre un plano blando, que es lo que lo hace ver nitido.
   ".zone > .deco" y no ".deco": la regla general de las zonas le pone
   max-width 66vw a todo hijo, y en PC el visor quedaba en los 2/3 de la
   izquierda. El visor es de la PANTALLA, no de la columna de texto. */
.zone > .deco {
  position: absolute; inset: 0;
  width: auto; max-width: none;
  pointer-events: none;
  opacity: 0;
  transition: opacity .7s var(--ease) .25s;
  /* El mismo margen por los cuatro lados, pegado al borde de la pantalla.
     Con 9vh arriba la linea rozaba el techo de "DE LOCAL". Y nunca debajo
     de la muesca de un iPhone acostado (viewport-fit=cover). */
  --dx: max(min(4.5vw, 5.5vh), env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px));
  --dt: max(min(4.5vw, 5.5vh), env(safe-area-inset-top, 0px));
  --db: max(min(4.5vw, 5.5vh), env(safe-area-inset-bottom, 0px));
}
.zone.is-live .deco { opacity: 1; }
.deco__c {
  position: absolute;
  width: clamp(22px, 2.6vw, 46px); height: clamp(22px, 2.6vw, 46px);
  border: 0 solid rgba(143, 214, 255, .55);
}
.deco__c--tl { left: var(--dx); top: var(--dt);  border-left-width: 1.5px; border-top-width: 1.5px; }
.deco__c--tr { right: var(--dx); top: var(--dt);  border-right-width: 1.5px; border-top-width: 1.5px; }
.deco__c--bl { left: var(--dx); bottom: var(--db); border-left-width: 1.5px; border-bottom-width: 1.5px; }
.deco__c--br { right: var(--dx); bottom: var(--db); border-right-width: 1.5px; border-bottom-width: 1.5px; }
.deco__rail {
  position: absolute; left: var(--dx); right: var(--dx);
  height: 1px;
  background:
    linear-gradient(to right, transparent, rgba(143, 214, 255, .32) 12%, rgba(143, 214, 255, .32) 88%, transparent);
}
/* la de abajo se abre en el centro: ahi aparece DESLIZA (90 px de ancho,
   104 en tablet), y una linea cruzandole el icono se veia rota */
.deco__rail--b {
  background:
    linear-gradient(to right, transparent, rgba(143, 214, 255, .32) 12%,
      rgba(143, 214, 255, .32) calc(50% - 92px), transparent calc(50% - 76px),
      transparent calc(50% + 76px), rgba(143, 214, 255, .32) calc(50% + 92px),
      rgba(143, 214, 255, .32) 88%, transparent);
}
.deco__rail::before, .deco__rail::after {
  content: ""; position: absolute; top: -3px;
  width: 1.5px; height: 7px;
  background: rgba(143, 214, 255, .6);
}
.deco__rail::before { left: 18%; }
.deco__rail::after  { right: 18%; }
.deco__rail--a { top: var(--dt); }
.deco__rail--b { bottom: var(--db); }

/* PC: el visor MARCADO (Alexander, 2026-09-14: "que se note mas").
   Esquinas como dos brazos de luz con resplandor, y rieles con nucleo de
   1px y halo. Al entrar el tramo se dibujan UNA vez —las esquinas crecen
   desde el vertice y los rieles desde las esquinas hacia el centro— y
   quedan quietos. Todo por transform: nada se repinta.
   Solo con alto de sobra: el celular acostado conserva el marco fino, y
   de pie el marco ni existe (ver el final del archivo). */
@media (min-height: 521px) {
  .deco__c {
    width: clamp(34px, 3.6vw, 70px); height: clamp(34px, 3.6vw, 70px);
    border: 0;
  }
  .deco__c::before, .deco__c::after {
    content: ""; position: absolute;
    background: rgba(206, 238, 255, .95);
    box-shadow: 0 0 10px rgba(75, 174, 255, .8), 0 0 22px rgba(61, 165, 255, .35);
  }
  .deco__c::before { left: 0; width: 100%; height: 2px; }
  .deco__c::after  { top: 0; width: 2px; height: 100%; }
  .deco__c--tl::before { top: 0;    transform-origin: left center; }
  .deco__c--tl::after  { left: 0;   transform-origin: center top; }
  .deco__c--tr::before { top: 0;    transform-origin: right center; }
  .deco__c--tr::after  { right: 0;  transform-origin: center top; }
  .deco__c--bl::before { bottom: 0; transform-origin: left center; }
  .deco__c--bl::after  { left: 0;   transform-origin: center bottom; }
  .deco__c--br::before { bottom: 0; transform-origin: right center; }
  .deco__c--br::after  { right: 0;  transform-origin: center bottom; }

  /* el riel mide 9px: 1px de nucleo en el centro (justo en --dt/--db) y
     halo a los lados. Los bordes que se desvanecen y el hueco de DESLIZA
     van en la mascara, asi las dos mitades solo llevan su luz. */
  .deco__rail {
    height: 9px;
    background: none;
    -webkit-mask-image: linear-gradient(to right, transparent, #000 10%, #000 90%, transparent);
            mask-image: linear-gradient(to right, transparent, #000 10%, #000 90%, transparent);
  }
  .deco__rail--a { top: calc(var(--dt) - 4px); }
  .deco__rail--b {
    bottom: calc(var(--db) - 4px);
    background: none;
    -webkit-mask-image: linear-gradient(to right, transparent, #000 10%, #000 calc(50% - 92px),
      transparent calc(50% - 76px), transparent calc(50% + 76px), #000 calc(50% + 92px), #000 90%, transparent);
            mask-image: linear-gradient(to right, transparent, #000 10%, #000 calc(50% - 92px),
      transparent calc(50% - 76px), transparent calc(50% + 76px), #000 calc(50% + 92px), #000 90%, transparent);
  }
  .deco__rail b {
    position: absolute; top: 0; bottom: 0; width: 50%;
    background: linear-gradient(to bottom, transparent 0, rgba(75, 174, 255, .3) 3px,
      rgba(214, 242, 255, .95) 4px, rgba(214, 242, 255, .95) 5px, rgba(75, 174, 255, .3) 6px, transparent 9px);
  }
  .deco__rail b:first-child { left: 0;  transform-origin: left center; }
  .deco__rail b + b         { right: 0; transform-origin: right center; }
  .deco__rail::before, .deco__rail::after { top: 1px; width: 2px; height: 7px; background: rgba(206, 238, 255, .9); }

  .zone.is-live .deco__c::before { animation: decoX .55s var(--ease) .3s both; }
  .zone.is-live .deco__c::after  { animation: decoY .55s var(--ease) .3s both; }
  .zone.is-live .deco__rail b    { animation: decoX .9s var(--ease) .62s both; }
}
@keyframes decoX { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes decoY { from { transform: scaleY(0); } to { transform: scaleY(1); } }

/* ============================================================
   PRECIO — UN LETRERO QUE ENCIENDE

   Los dos numeros como datos de un panel, separados por una regla de
   luz; cada uno con su filo y su etiqueta. Sin caja: en toda la web no
   hay una sola, y cualquier recuadro se ve pegado encima del plano.

   TODO enciende como un neon, uno tras otro y con su parpadeo: la regla,
   la cifra grande, la del mes, los filos, las etiquetas, el sello y el
   cierre. Las cifras ademas giran un instante antes de fijarse (sb.js).
   Cada animacion tiene FIN: en reposo no queda nada corriendo.

   La rejilla es lo que impide que algo quede torcido:
     fila 1  las dos cifras, compartiendo LINEA DE BASE
     fila 2  el filo de cada columna
     fila 3  las dos etiquetas, arrancando a la misma altura
     la regla ocupa las tres filas y cae en el centro exacto
   minmax(0,1fr) en las columnas: sin eso, la etiqueta mas larga ensancha
   su columna y la regla se sale del centro (medido: 13 px).
   Se comprueba en pixeles con tools/alineacion.mjs.
   ============================================================ */
.precio { display: block; width: 100%; }
.precio__par {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 1px minmax(0, 1fr);
  column-gap: clamp(20px, 3vw, 40px);
  align-items: baseline;
  justify-items: center;
  width: 100%;
}
.precio__num {
  grid-row: 1;
  font-family: var(--f-disp);
  font-weight: 700;
  font-size: max(3rem, min(6.4vw, 11.4vh));
  line-height: .92;
  letter-spacing: -.045em;
  color: #FFFFFF;
  font-variant-numeric: tabular-nums;
  text-shadow: 0 0 20px rgba(75, 174, 255, .5), 0 0 64px rgba(61, 165, 255, .28),
               0 2px 20px rgba(2, 4, 8, .92);
}
.precio__num--sec {
  grid-column: 3;
  font-size: max(2rem, min(4.2vw, 7.5vh));
  color: var(--blue);
  text-shadow: 0 0 18px rgba(61, 165, 255, .5), 0 2px 16px rgba(2, 4, 8, .92);
}
.precio__regla {
  grid-column: 2; grid-row: 1 / span 3;
  width: 1px; align-self: stretch;
  background: linear-gradient(to bottom, rgba(143, 214, 255, 0), rgba(143, 214, 255, .5), rgba(143, 214, 255, 0));
  transform: scaleY(0); transform-origin: top;
}
.precio__filo {
  grid-row: 2;
  width: 100%; max-width: 9em; height: 1px;
  margin: clamp(12px, 1.8vh, 22px) 0 clamp(10px, 1.5vh, 18px);
  background: linear-gradient(to right, rgba(143, 214, 255, 0), rgba(143, 214, 255, .65), rgba(143, 214, 255, 0));
  transform: scaleX(0);
}
.precio__filo--b { grid-column: 3; }
.precio__lbl {
  grid-row: 3; align-self: start;
  max-width: 100%; text-wrap: balance;
  font-family: var(--f-disp);
  font-weight: 600;
  font-size: clamp(11px, min(1.05vw, 1.8vh), 14px);
  line-height: 1.35;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: #DCEBFF;
  text-shadow: 0 0 12px rgba(75, 174, 255, .5), 0 0 10px rgba(2, 6, 14, .95);
  opacity: 0;
}
.precio__lbl:nth-of-type(2) { grid-column: 3; }
.precio__sello {
  margin: clamp(30px, 5.2vh, 64px) 0 0;
  font-family: var(--f-disp);
  font-weight: 700;
  font-size: max(2.2rem, min(5vw, 8.9vh));
  line-height: 1;
  letter-spacing: -.035em;
  color: var(--cyan);
  text-shadow: 0 0 20px rgba(59, 235, 223, .45), 0 0 70px rgba(59, 235, 223, .2),
               0 2px 18px rgba(2, 4, 8, .92);
  opacity: 0;
}
.precio__pie {
  margin: clamp(10px, 1.6vh, 20px) 0 0;
  font-family: var(--f-disp);
  font-weight: 400;
  font-size: clamp(1rem, min(1.35vw, 2.4vh), 1.5rem);
  line-height: 1.4;
  color: #FFFFFF;
  text-shadow: 0 0 10px rgba(2, 4, 8, .95), 0 2px 16px rgba(2, 4, 8, .9);
  opacity: 0;
}
.precio__num { opacity: 0; }
/* el remate de venta, ya fuera de la rejilla: cierra el tramo y ocupa el
   hueco que quedaba entre el cierre y el horizonte */
.precio__filo--largo {
  display: block;
  grid-row: auto; grid-column: auto;
  width: min(34vw, 15rem); max-width: none;
  margin: clamp(26px, 4.4vh, 54px) auto clamp(16px, 2.4vh, 26px);
}
/* El remate NO es un parrafo: es el cambio de marco, puesto en escena.
   Primero aparece "NO ES UN GASTO" en chico y apagado; una linea de luz
   lo TACHA; y recien entonces enciende la frase de verdad, con los tres
   verbos prendiendo uno detras de otro. El tachado es el argumento: se
   ve como se cae la palabra gasto y se levanta la palabra inversion. */
.precio__remate {
  display: flex; flex-direction: column; align-items: center;
  margin: 0; padding: 0;
}
.precio__tacha {
  position: relative;
  font-family: var(--f-disp);
  font-weight: 600;
  font-size: clamp(11px, min(1vw, 1.7vh), 14px);
  line-height: 1.2;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: rgba(146, 172, 208, .92);
  text-shadow: 0 0 10px rgba(2, 6, 14, .95);
  margin-bottom: clamp(12px, 1.9vh, 22px);
  opacity: 0;
}
/* la linea que tacha: nace a la izquierda y cruza la palabra */
.precio__tacha > i {
  position: absolute; left: -.14em; right: -.28em; top: 52%;
  height: 1px;
  background: linear-gradient(to right, rgba(143, 214, 255, .1), rgba(143, 214, 255, .85) 22%,
              rgba(143, 214, 255, .85) 78%, rgba(143, 214, 255, .1));
  box-shadow: 0 0 8px rgba(75, 174, 255, .55);
  transform: scaleX(0); transform-origin: left center;
}
.precio__inv {
  max-width: 20em;
  font-family: var(--f-disp);
  font-weight: 500;
  font-size: clamp(1.05rem, min(1.6vw, 2.85vh), 1.8rem);
  line-height: 1.25;
  letter-spacing: -.012em;
  color: #C8D8EE;
  text-shadow: 0 0 10px rgba(2, 4, 8, .95), 0 2px 16px rgba(2, 4, 8, .9);
  text-wrap: balance;
  opacity: 0;
}
.precio__inv b {
  font-weight: 700;
  font-size: 1.14em;
  letter-spacing: -.03em;
  color: var(--cyan);
  text-shadow: 0 0 18px rgba(59, 235, 223, .5), 0 0 46px rgba(59, 235, 223, .22),
               0 2px 14px rgba(2, 4, 8, .9);
}
/* los tres verbos: el remate del remate. Van en una fila, separados por
   la misma regla de luz que parte las dos cifras, y encienden uno detras
   de otro. Nada de cursiva. */
.precio__verbos {
  display: flex; align-items: center; justify-content: center;
  gap: clamp(12px, 1.6vw, 22px);
  margin-top: clamp(10px, 1.6vh, 18px);
}
.precio__verbos em {
  font-style: normal;
  font-family: var(--f-disp);
  font-weight: 700;
  font-size: clamp(1.05rem, min(1.6vw, 2.85vh), 1.8rem);
  line-height: 1.2;
  letter-spacing: -.02em;
  white-space: nowrap;
  color: #FFFFFF;
  text-shadow: 0 0 16px rgba(75, 174, 255, .6), 0 0 44px rgba(61, 165, 255, .25),
               0 2px 14px rgba(2, 4, 8, .9);
  opacity: 0;
}
.precio__verbos > i {
  flex: 0 0 auto;
  width: 1px; height: 1.15em;
  background: linear-gradient(to bottom, rgba(143, 214, 255, 0), rgba(143, 214, 255, .6), rgba(143, 214, 255, 0));
  transform: scaleY(0);
}


/* ---------- el encendido, pieza por pieza ---------- */
.zone.is-live .precio__regla   { animation: pr-regla .7s var(--ease) .04s forwards; }
.zone.is-live .precio__num     { animation: pr-neon .8s steps(1, end) .16s forwards; }
.zone.is-live .precio__num--sec{ animation-delay: .3s; }
.zone.is-live .precio__filo    { animation: pr-filo .6s var(--ease) .46s forwards; }
.zone.is-live .precio__filo--b { animation-delay: .56s; }
.zone.is-live .precio__lbl     { animation: pr-neon .8s steps(1, end) .62s forwards; }
.zone.is-live .precio__lbl:nth-of-type(2) { animation-delay: .72s; }
.zone.is-live .precio__sello   { animation: pr-neon 1s steps(1, end) .86s forwards; }
.zone.is-live .precio__pie     { animation: pr-suave .6s var(--ease) 1.15s forwards; }
.zone.is-live .precio__filo--largo { animation: pr-filo .7s var(--ease) 1.2s forwards; }
.zone.is-live .precio__tacha   { animation: pr-suave .5s var(--ease) 1.3s forwards; }
.zone.is-live .precio__tacha>i { animation: pr-filo .42s var(--ease) 1.62s forwards; }
.zone.is-live .precio__inv     { animation: pr-neon .8s steps(1, end) 1.86s forwards; }
.zone.is-live .precio__verbos em { animation: pr-neon .55s steps(1, end) 2.1s forwards; }
.zone.is-live .precio__verbos em:nth-of-type(2) { animation-delay: 2.24s; }
.zone.is-live .precio__verbos em:nth-of-type(3) { animation-delay: 2.38s; }
.zone.is-live .precio__verbos > i { animation: pr-regla .4s var(--ease) 2.18s forwards; }
.zone.is-live .precio__verbos > i:nth-of-type(2) { animation-delay: 2.32s; }

@keyframes pr-regla { from { transform: scaleY(0); } to { transform: scaleY(1); } }
@keyframes pr-filo  { from { transform: scaleX(0); } to { transform: scaleX(1); } }
/* el parpadeo del tubo: enciende, duda dos veces y se queda */
@keyframes pr-neon {
  0%        { opacity: 0;   filter: blur(7px); }
  12%       { opacity: .85; filter: blur(2.5px); }
  20%       { opacity: .12; filter: blur(3px); }
  32%       { opacity: 1;   filter: blur(0); }
  42%       { opacity: .35; filter: blur(1px); }
  52%, 100% { opacity: 1;   filter: blur(0); }
}
@keyframes pr-suave { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .zone.is-live .precio__num, .zone.is-live .precio__lbl,
  .zone.is-live .precio__sello, .zone.is-live .precio__pie,
  .zone.is-live .precio__tacha, .zone.is-live .precio__inv,
  .zone.is-live .precio__verbos em { animation: pr-suave .01s both; }
  .zone.is-live .precio__regla, .zone.is-live .precio__filo,
  .zone.is-live .precio__tacha > i,
  .zone.is-live .precio__verbos > i { animation: none; transform: none; }
}

.price-row {
  display: flex; align-items: flex-end; justify-content: center;
  gap: clamp(18px, 2.6vw, 46px);
  flex-wrap: wrap;
}
.price { display: block; text-align: left; }
.price--big { --fs: max(3.4rem, min(10vw, 17.8vh)); }
.price--mid { --fs: max(1.6rem, min(3.6vw, 6.4vh)); }
.price__big {
  display: block;
  font-family: var(--f-disp);
  font-weight: 700;
  font-size: var(--fs, 1rem);
  line-height: .84;
  letter-spacing: -.055em;
  color: var(--paper);
  font-variant-numeric: tabular-nums;
}
.price__plus {
  font-family: var(--f-disp);
  font-weight: 300;
  font-size: max(1.4rem, min(3vw, 5.3vh));
  color: var(--dim);
  line-height: 1;
  padding-bottom: .9em;
}
.price--sec { padding-bottom: .35em; }
.price__mid {
  display: block;
  font-family: var(--f-disp);
  font-weight: 600;
  font-size: var(--fs, 1rem);
  line-height: 1;
  letter-spacing: -.03em;
  color: var(--blue);
  font-variant-numeric: tabular-nums;
}
.price__mid em {
  font-style: normal; font-weight: 400;
  font-size: .5em; color: var(--paper); letter-spacing: 0;
}
.price .s--md { margin-top: .18em; }
.price__note {
  display: block;
  margin-top: .8em;
  font-family: var(--f-disp);
  font-size: clamp(15px, min(1.2vw, 2.1vh), 19px);
  color: var(--paper);
}
.deal { margin-top: clamp(22px, 3.8vh, 46px); }
/* la garantia es el gancho: va mas grande que un parrafo de apoyo.
   En el tramo digital el fondo vuelve a su estado original (sin velo),
   asi que este texto lleva su propio halo para no perderse sobre el
   resplandor del horizonte. */
.zone[data-zone="precio"] .lede {
  color: #FFFFFF;
  font-size: clamp(1.1rem, min(1.55vw, 2.8vh), 1.75rem);
  text-shadow: 0 0 10px rgba(2, 4, 8, .98), 0 2px 18px rgba(2, 4, 8, .96), 0 0 40px rgba(2, 4, 8, .9);
}
.zone[data-zone="precio"] .price__note,
.zone[data-zone="precio"] .s {
  text-shadow: 0 0 9px rgba(2, 4, 8, .96), 0 2px 16px rgba(2, 4, 8, .92);
}

/* ============================================================
   CONTACTO — el boton
   Solido y no de contorno: es la accion de toda la pagina. Un haz de
   luz recorre el borde y un brillo lo cruza cada pocos segundos. Todo
   por transform: el haz es un cuadrado con degradado conico que GIRA
   detras del boton; solo asoma por el anillo de 2px.
   ============================================================ */
.cta__wrap { margin-top: clamp(18px, 3vh, 38px); }
.btn {
  --mx: 0px; --my: 0px;
  position: relative;
  display: inline-block;
  isolation: isolate;
  padding: 2px;
  border-radius: 999px;
  overflow: hidden;
  background: rgba(143, 214, 255, .22);
  text-decoration: none;
  pointer-events: auto;
  transform: translate3d(var(--mx), var(--my), 0);
  transition: transform .45s var(--ease), box-shadow .45s var(--ease);
  box-shadow: 0 16px 56px -18px rgba(61, 165, 255, .8);
  -webkit-tap-highlight-color: transparent;
}
.btn::before {
  content: "";
  position: absolute; z-index: -1;
  left: 50%; top: 50%;
  width: 160%; aspect-ratio: 1;
  background: conic-gradient(from 0deg, transparent 0deg 250deg, rgba(143, 214, 255, .25) 290deg, #fff 342deg, transparent 360deg);
  transform: translate(-50%, -50%) rotate(0deg);
}
/* Vueltas contadas al entrar al contacto (y sin fin solo con el raton
   encima): una animacion infinita mantiene la tarjeta de video
   componiendo la pantalla entera para siempre, y con el tiempo el
   equipo se calienta y baja su rendimiento. */
.zone.is-live .btn::before { animation: beam 3.2s linear .6s 5; }
@keyframes beam { to { transform: translate(-50%, -50%) rotate(360deg); } }
.btn__in {
  position: relative;
  display: inline-flex; align-items: center; gap: 14px;
  padding: clamp(18px, 2.4vh, 25px) clamp(30px, 2.9vw, 48px);
  border-radius: 999px;
  overflow: hidden;
  background: linear-gradient(100deg, #A9E5FF 0%, #56B6FF 50%, #3FE6DB 100%);
  color: #03111C;
  font-family: var(--f-disp);
  font-weight: 700;
  font-size: clamp(15px, 1.22vw, 20px);
  letter-spacing: .08em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: transform .45s var(--ease);
}
.btn__in::after {
  content: "";
  position: absolute; top: 0; bottom: 0; left: -45%;
  width: 38%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .7), transparent);
  transform: translateX(0) skewX(-20deg);
  pointer-events: none;
}
.zone.is-live .btn__in::after { animation: shine 4.4s var(--ease) 1.4s 3; }
@keyframes shine {
  0%        { transform: translateX(0) skewX(-20deg); }
  38%, 100% { transform: translateX(460%) skewX(-20deg); }
}
.btn__wa { flex: none; width: 1.45em; height: 1.45em; }
.btn__wa .o { fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linejoin: round; }
.btn__wa .h { fill: currentColor; }
.btn__txt { position: relative; }
.btn__arrow {
  flex: none; width: 1.3em; height: 1.3em;
  fill: none; stroke: currentColor; stroke-width: 2.2;
  stroke-linecap: round; stroke-linejoin: round;
  transition: transform .45s var(--ease);
}
@media (hover: hover) {
  .zone.is-live .btn:hover::before { animation: beam 2.4s linear infinite; }
  .btn:hover { box-shadow: 0 22px 70px -14px rgba(61, 165, 255, 1); }
  .btn:hover .btn__in { transform: translateY(-1px); }
  .btn:hover .btn__arrow { transform: translateX(5px); }
}
.btn:active .btn__in { transform: scale(.975); }
.btn:focus-visible { outline: 2px solid var(--blue-hi); outline-offset: 5px; }

/* La firma: el logo de la marca (el numero ya no va: el boton abre el
   chat). Entra encendiendose como el wordmark: una linea de escaneo baja
   y el logo aparece a su paso. Una vez por entrada, nada en bucle. El
   recorte se abre 24px mas alla de la caja para no cortar la sombra. */
.cta__meta {
  margin-top: clamp(28px, 4.6vh, 56px);
  display: flex; justify-content: center;
}
.cta__sig { position: relative; display: inline-block; line-height: 0; }
.cta__logo {
  display: block; width: auto;
  height: clamp(34px, 5.2vh, 54px);
  color: #BFD9FF;
  filter: drop-shadow(0 2px 14px rgba(2, 4, 8, .92));
}
.cta__scan {
  position: absolute; left: -8%; right: -8%; top: 0; height: 100%;
  pointer-events: none; opacity: 0;
}
.cta__scan::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0;
  height: 2px; border-radius: 2px;
  background: linear-gradient(to right, transparent, rgba(143, 214, 255, .85) 18%, #FFFFFF 50%, rgba(143, 214, 255, .85) 82%, transparent);
  box-shadow: 0 0 18px 4px rgba(61, 165, 255, .55);
}
.zone.is-live .cta__logo { animation: firma .9s linear 1s both; }
.zone.is-live .cta__scan { animation: firma-scan .9s linear 1s both; }
@keyframes firma {
  from { clip-path: inset(-24px -24px calc(100% + 24px) -24px); }
  to   { clip-path: inset(-24px); }
}
@keyframes firma-scan {
  0%   { opacity: 0; transform: translateY(0); }
  8%   { opacity: 1; }
  88%  { opacity: 1; }
  100% { opacity: 0; transform: translateY(100%); }
}
@media (prefers-reduced-motion: reduce) {
  .zone.is-live .cta__logo, .zone.is-live .cta__scan { animation: none; }
}
/* ?sinfx=1 — logo pelado, sin sombra ni recorte animado (prueba de la
   franja de Safari en un telefono de verdad) */
html.sinfx .cta__logo { filter: none; animation: none; clip-path: none; }
html.sinfx .cta__scan { display: none; }

/* ============================================================
   DESLIZA
   Sale al entrar, se va con el primer scroll y vuelve tras 5 s sin
   scroll (sb.js). Solo por clase: una animacion CSS con fill forwards
   sobre la misma opacidad le ganaba al JS y el indicador anterior no
   se escondia nunca.
   ============================================================ */
.cue {
  position: fixed;
  left: 50%;
  bottom: max(calc(var(--gut) * .9), calc(env(safe-area-inset-bottom) + 14px));
  z-index: 4;
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  pointer-events: none;
  opacity: 0;
  transform: translate(-50%, 12px);
  transition: opacity .6s var(--ease), transform .6s var(--ease);
}
.cue.is-on { opacity: 1; transform: translate(-50%, 0); }
/* Sin filter: drop-shadow — con la rueda animada dentro, el filtro se
   recalculaba en cada fotograma. Y las animaciones son de vueltas
   contadas cada vez que aparece: el indicador sale justo cuando el
   visitante esta quieto, que es cuando nada deberia estar trabajando. */
.cue__ico { width: 44px; height: 50px; overflow: visible; }
.cue__ico .br  { fill: none; stroke: rgba(143, 214, 255, .7); stroke-width: 1.6; }
.cue__ico .cap { fill: rgba(5, 9, 16, .6); stroke: var(--blue-hi); stroke-width: 1.8; }
.cue__ico .whl { fill: var(--blue-hi); transform-box: fill-box; }
.cue.is-on .cue__ico .whl { animation: wheel 1.9s var(--ease) 4; }
@keyframes wheel {
  0%        { transform: translateY(0);   opacity: 0; }
  18%       { opacity: 1; }
  70%, 100% { transform: translateY(9px); opacity: 0; }
}
.cue__ico--touch { display: none; }
/* en tactil: una mano deslizando hacia arriba, que es el gesto real */
.cue__ico .arc  { fill: none; stroke: rgba(143, 214, 255, .7); stroke-width: 1.7;
                  stroke-linecap: round; stroke-dasharray: 3.5 4.5; transform-box: fill-box; }
.cue__ico .hand { fill: rgba(5, 9, 16, .7); stroke: var(--blue-hi); stroke-width: 1.9;
                  stroke-linejoin: round; stroke-linecap: round; transform-box: fill-box; }
.cue.is-on .cue__ico .hand { animation: swipe 2s var(--ease) 4; }
.cue.is-on .cue__ico .arc  { animation: swipeArc 2s var(--ease) 4; }
@keyframes swipe {
  0%        { transform: translateY(4px); }
  45%       { transform: translateY(-5px); }
  75%, 100% { transform: translateY(4px); }
}
@keyframes swipeArc {
  0%, 20%   { opacity: 0; }
  50%       { opacity: 1; }
  80%, 100% { opacity: 0; }
}
.cue__chev { display: flex; flex-direction: column; align-items: center; margin-top: -4px; }
.cue__chev i {
  display: block; width: 8px; height: 8px; margin-top: -2px;
  border-right: 1.6px solid var(--blue-hi); border-bottom: 1.6px solid var(--blue-hi);
  transform: rotate(45deg);
  opacity: .6;
}
.cue.is-on .cue__chev i { animation: chev 1.9s ease-in-out 4; }
.cue.is-on .cue__chev i + i { animation-delay: .22s; }
@keyframes chev { 0%, 100% { opacity: .15; } 40% { opacity: 1; } }
.cue__lbl {
  font-family: var(--f-mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .42em;
  padding-left: .42em;
  text-transform: uppercase;
  color: var(--blue-hi);
  text-shadow: 0 0 10px rgba(61, 165, 255, .6), 0 1px 10px rgba(2, 4, 8, .95);
}
/* en tactil el gesto es deslizar hacia arriba, no una rueda */
@media (hover: none) and (pointer: coarse) {
  .cue__ico--mouse { display: none; }
  .cue__ico--touch { display: block; }
  .cue__chev { display: none; }
}

/* ============================================================
   ACCESIBILIDAD Y RESPALDO
   ============================================================ */
.sr {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden; white-space: nowrap;
  clip: rect(0 0 0 0); clip-path: inset(50%);
}

/* medidor de ?fps=1 (ver sb.js) */
/* EL BORDE DE ABAJO EN iPHONE

   A pantalla completa Safari deja debajo de la pagina una franja de unos
   78 pt que NINGUNA web puede pintar: la rellena con el color de fondo de
   la pagina (probado en el iPhone de Alexander, 2026-09-15: una capa
   fixed y otra sticky mas altas que la pantalla se cortan justo ahi).

   Lo que se hace entonces es que no haya CORTE: el mundo se apaga hacia
   el negro de la pagina en los ultimos 96 px, y la franja de Safari
   —negra, porque el fondo de la pagina es negro— sigue ese mismo negro.
   No se ve una franja: se ve que el plano se apaga abajo.
   En la calle y la ciudad esto casi no se nota (el sombreado ya oscurece
   ese borde); donde se ve es en la rejilla azul del final. */
.edge { display: none; }

.meter {
  /* separado del borde de arriba a proposito: en iPhone, una capa fija
     pegada al borde hace que Safari deje de extender la pagina bajo sus
     barras y reaparece su franja de abajo (visto el 2026-09-16 con una
     etiqueta de pruebas: misma pagina, con la etiqueta salia franja y sin
     ella no). El medidor solo existe con ?fps=1, pero que no enganie. */
  position: fixed; left: 0; right: 0; top: 56px;
  z-index: 9;
  padding: 6px 8px;
  padding-top: max(6px, env(safe-area-inset-top));
  background: rgba(2, 4, 8, .82);
  color: #7CF5C0;
  font-family: var(--f-mono);
  font-size: 11px;
  line-height: 1.35;
  letter-spacing: .02em;
  pointer-events: none;
}

/* ============================================================
   LA CARGA
   Tapa la pagina hasta que las 696 imagenes del mundo estan abajo. La
   cuenta es real (sb.js la saca del contador de descargas), no un relleno
   animado: si la conexion va lenta se ve que avanza, y si se para se ve
   que se paro. Todo lo que se anima aqui termina; en reposo no queda
   nada corriendo.
   ============================================================ */
.boot {
  position: fixed; inset: 0; z-index: 20;
  display: grid; place-items: center;
  background: var(--ink);
  transition: opacity .55s var(--ease), visibility 0s linear .55s;
}
html.boot-listo .boot { opacity: 0; visibility: hidden; pointer-events: none; }
.no-js .boot { display: none; }
.boot__in {
  display: flex; flex-direction: column; align-items: center;
  width: min(74vw, 320px);
}
.boot__mark {
  width: clamp(52px, 13vw, 76px); height: auto;
  border-radius: 12px;
  /* el mismo halo azul del resto de la web, para que la espera ya sea
     parte de la pieza y no una pantalla de sistema */
  box-shadow: 0 0 34px rgba(61, 165, 255, .28), 0 0 90px rgba(61, 165, 255, .14);
}
.boot__pct {
  margin: clamp(18px, 3vh, 30px) 0 clamp(10px, 1.6vh, 16px);
  font-family: var(--f-disp);
  font-weight: 700;
  font-size: clamp(1.7rem, min(6vw, 4.6vh), 2.6rem);
  line-height: 1;
  letter-spacing: -.04em;
  color: #FFFFFF;
  font-variant-numeric: tabular-nums;
  text-shadow: 0 0 22px rgba(75, 174, 255, .45);
}
.boot__barra {
  position: relative;
  width: 100%; height: 2px;
  background: rgba(143, 214, 255, .14);
  overflow: hidden;
}
.boot__fill {
  position: absolute; inset: 0;
  transform: scaleX(0); transform-origin: left center;
  background: linear-gradient(to right, rgba(61, 165, 255, .85), rgba(59, 235, 223, 1));
  box-shadow: 0 0 14px rgba(59, 235, 223, .55);
  transition: transform .35s linear;
}
.boot__pie {
  margin: clamp(12px, 2vh, 20px) 0 0;
  font-family: var(--f-mono);
  font-size: clamp(10px, 2.8vw, 12px);
  letter-spacing: .24em;
  text-transform: uppercase;
  color: rgba(146, 172, 208, .8);
}
@media (prefers-reduced-motion: reduce) {
  .boot, .boot__fill { transition: none; }
}

.skip {
  position: absolute; left: -9999px;
  z-index: 9; padding: 12px 18px;
  background: var(--blue); color: #001424;
  font-family: var(--f-mono); font-size: 12px; text-decoration: none;
}
.skip:focus { left: var(--gut); top: var(--gut); }

/* SIN JS: si el motor no carga, las zonas se apilan y la pagina sigue
   siendo legible y contactable */
.no-js .stage-overlay { position: static; height: auto; pointer-events: auto; }
.no-js .zone {
  position: relative; inset: auto;
  opacity: 1; visibility: visible;
  min-height: 70vh;
}
.no-js .zone a { pointer-events: auto; }
.no-js .stage-spacer { display: none; }
.no-js .cue { display: none; }
/* El tramo del precio enciende pieza por pieza cuando el JS le pone
   .is-live. Sin JS esa clase no llega nunca y el bloque entero —cifras,
   sello, remate— se quedaba invisible: un hueco negro entre "DE LOCAL a
   DIGITAL" y el cierre (medido con tools/nojs.mjs). Aqui se entrega ya
   encendido, sin animacion. */
.no-js .precio__num, .no-js .precio__lbl, .no-js .precio__sello,
.no-js .precio__pie, .no-js .precio__tacha, .no-js .precio__inv,
.no-js .precio__verbos em { opacity: 1; }
.no-js .precio__regla, .no-js .precio__filo,
.no-js .precio__tacha > i, .no-js .precio__verbos > i { transform: none; }

@media (prefers-reduced-motion: reduce) {
  .flick, .btn::before, .btn__in::after, .search__caret,
  .glitch::before, .glitch::after,
  .cue__ico .whl, .cue__ico .hand, .cue__ico .arc, .cue__chev i { animation: none !important; }
  .deco__c::before, .deco__c::after, .deco__rail b { animation: none !important; }
  .cue__chev i { opacity: .7; }
  * { transition-duration: .01ms !important; }
}

/* ============================================================
   VERTICAL — celular y tablet de pie
   Todo al centro y a todo el ancho: en vertical no hay lados. El juego
   de fotogramas es el recorte central 9:16, cuya mitad de arriba es
   cielo oscuro — ahi va el texto.
   ============================================================ */
@media (max-aspect-ratio: 1/1), (max-width: 760px) {
  :root { --gut: clamp(18px, 5.2vw, 40px); }
  /* mas recorrido por fotograma: el mundo avanza mas lento por pixel de
     scroll y la frenada del dedo se ve continua en vez de a saltos */
  .stage-spacer { height: 2620vh; }
  /* Centrado en el ALTO de la pantalla (Alexander, 2026-09-14: arriba
     dejaba media pantalla vacia). Abajo el colchon es mayor: ahi vive
     DESLIZA, y el centro optico queda un poco por encima del geometrico.
     [data-zone] para ganarle a las reglas de escritorio de cada tramo. */
  .zone {
    align-items: center; text-align: center;
    padding: max(13vh, calc(env(safe-area-inset-top) + 60px)) var(--gut) max(17vh, calc(env(safe-area-inset-bottom) + 112px));
  }
  .zone[data-zone] { justify-content: center; padding-top: max(13vh, calc(env(safe-area-inset-top) + 60px)); }
  .zone > *, .zone--l > *, .zone--r > * { max-width: 100%; }

  /* Tamaños calculados para que cada linea quepa entera en el ancho de
     un celular: un titular partido a la mitad pierde el golpe. */
  /* Con la pantalla completa del iPhone sobra alto, asi que las lineas
     CHICAS y MEDIANAS de la calle crecen (Alexander, 2026-09-16). Los
     titulares grandes NO se tocan: ya llegan casi al borde y crecerlos
     los parte en dos lineas. */
  /* UNA linea por titular, siempre. Medido con tools/tipografia.mjs:
     cada uno llega al 87-94% del ancho util del telefono, que es su
     techo real — por encima del 95% se parte en dos y cambia la
     composicion. Lo que si tenia sitio de sobra eran las lineas de
     enlace ("Antes de ir,", "se va con", "a") y el contacto: esas son
     las que suben. */
  .zone--hero .w--xxl { --fs: min(22vw, 13.6vh); }
  .neon__txt { font-size: min(8.3vw, 4.9vh); }
  .lede { font-size: min(4.6vw, 2.8vh, 1.45rem); }

  .zone[data-zone="problema"] .s--md { --fs: min(9.2vw, 5.5vh); }
  .zone[data-zone="problema"] .w--md { --fs: min(8.9vw, 5.4vh); }
  .zone[data-zone="problema"] .w--xl { --fs: min(10.6vw, 6.45vh); }

  /* esta linea es la mas larga de la web: por encima de 5.6vw se parte
     en dos en un telefono de 390 px, asi que se queda como estaba */
  .zone[data-zone="costo"] .w--sm { --fs: min(5.6vw, 3.4vh); }
  .zone[data-zone="costo"] .s--md { --fs: min(9.8vw, 5.9vh); }
  /* un punto mas grande, pero sin pasar del 95% del ancho util: por
     encima se parte en dos (Alexander, 2026-09-21) */
  .zone[data-zone="costo"] .w--xl { --fs: min(10.9vw, 6.6vh); }

  .zone[data-zone="solucion"] .w--lg { --fs: min(12.4vw, 7.5vh); }
  .zone[data-zone="solucion"] .w--xl { --fs: min(13.8vw, 8.25vh); }
  .zone[data-zone="solucion"] .s--sub { --fs: min(8.4vw, 5vh); }

  /* El aire entre lineas va CON el tamaño de cada linea, no fijo: asi el
     bloque respira igual en un telefono chico que en uno grande, y las
     lineas no quedan ni pegadas ni sueltas (el wordmark del inicio va
     aparte: sus dos lineas son una sola pieza). */
  .zone .ttl:not(.wordmark) > * + * { margin-top: calc(var(--fs, 1rem) * .07); }
  .zone[data-zone="solucion"] .s--sub { margin-top: .3em; }
  .kicker { margin-bottom: clamp(10px, 1.6vh, 20px); }
  /* el bloque de contacto estaba suelto: el boton y los datos se acercan
     al titular para que se lea como una sola pieza */
  .chips { margin-top: clamp(13px, 2.2vh, 26px); }
  .cta__wrap { margin-top: clamp(15px, 2.5vh, 30px); }
  .cta__meta { margin-top: clamp(13px, 2.1vh, 25px); }

  .zone[data-zone="beneficios"] .s--md { --fs: min(7.7vw, 4.6vh); }
  .zone[data-zone="beneficios"] .w--xl { --fs: min(14.8vw, 8.85vh); }
  .zone[data-zone="beneficios"] .w--lg { --fs: min(10.1vw, 6vh); }

  .zone[data-zone="salto"] .w--xxl { --fs: min(19.6vw, 11.7vh); }

  /* el contacto era el unico titular que se quedaba al 74% del ancho */
  .zone[data-zone="cta"] .s--lg { --fs: min(9.8vw, 5.9vh); }
  .zone[data-zone="cta"] .w--xl { --fs: min(11.2vw, 6.8vh); }
  .zone[data-zone="salto"] .s--lg { --fs: min(13vw, 7.8vh); }

  /* el tramo del precio en celular: la cifra manda y el sello pesa casi
     igual, para que el bloque llene la pantalla en vez de flotar chico */
  .precio__num { font-size: min(17.5vw, 10.5vh); }
  .precio__num--sec { font-size: min(11.5vw, 6.9vh); }
  .precio__lbl { font-size: min(3.2vw, 1.9vh); letter-spacing: .06em; }
  .precio__sello { font-size: min(13vw, 7.8vh); margin-top: clamp(20px, 3.4vh, 40px); }
  .precio__pie { font-size: min(4.4vw, 2.6vh); }
  .precio__filo--largo { width: min(50vw, 11rem); margin-block: clamp(16px, 2.6vh, 30px) clamp(10px, 1.6vh, 18px); }
  .precio__tacha { font-size: max(10px, min(3vw, 1.8vh)); letter-spacing: .16em; margin-bottom: clamp(10px, 1.7vh, 18px); }
  .precio__inv { font-size: min(4.6vw, 2.7vh); max-width: 15em; line-height: 1.24; }
  /* Los tres verbos siguen en FILA, con su regla de luz entre medias
     (Alexander, 2026-09-23). En un telefono de 390 px la fila entera
     —36 caracteres, dos huecos y dos reglas— cabe justo en un renglon
     con la letra a 4.1vw; por eso el hueco se aprieta y la letra se
     ajusta al ancho en vez de partirse. */
  .precio__verbos {
    flex-wrap: nowrap;
    gap: clamp(7px, 2.2vw, 14px);
    margin-top: clamp(9px, 1.5vh, 16px);
  }
  .precio__verbos > i { display: block; }
  .precio__verbos em { font-size: min(4.1vw, 2.45vh); white-space: nowrap; }
}

/* celular de pie CORTO (iPhone SE y parecidos): el remate de venta cae
   demasiado cerca del resplandor del horizonte, asi que se aprieta */
@media (max-aspect-ratio: 1/1) and (max-height: 700px) {
  /* medido en 375x667: con el remate completo la ultima linea caia dentro
     del resplandor (2.4:1). Se sube todo el tramo y se recortan los aires */
  .zone[data-zone="precio"] { padding-top: 3vh; }
  .precio__num { font-size: min(15.4vw, 9.2vh); }
  .precio__num--sec { font-size: min(10.2vw, 6.1vh); }
  .precio__sello { margin-top: clamp(13px, 2.2vh, 24px); font-size: min(11.4vw, 6.8vh); }
  .precio__pie { margin-top: clamp(7px, 1.2vh, 14px); }
  .precio__filo--largo { margin-block: clamp(10px, 1.7vh, 18px) clamp(7px, 1.2vh, 12px); }
  .precio__tacha { margin-bottom: clamp(6px, 1vh, 10px); }
  .precio__inv { font-size: min(3.9vw, 2.35vh); }
  .precio__verbos em { font-size: min(3.8vw, 2.3vh); }

  .zone[data-zone="cta"] .s--lg { --fs: min(11vw, 6.6vh); }
  .zone[data-zone="cta"] .w--xl { --fs: min(12vw, 7.2vh); }

  /* En pantalla chica el interletrado cerrado del titular aprieta
     demasiado las palabras: se afloja un punto (los titulares siguen
     cabiendo en una linea, medido). */
  .w { letter-spacing: -.035em; }

  /* En celular los resplandores grandes son raster caro en cada
     repintado: a este tamaño la mitad de radio se ve igual. */
  .neon__txt { text-shadow: 0 0 1px #fff, 0 0 6px rgba(143, 214, 255, .9),
               0 0 15px rgba(59, 235, 223, .5), 0 2px 12px rgba(2, 4, 8, .92); }
  .w--glow { text-shadow: 0 0 9px rgba(75, 174, 255, .95), 0 0 22px rgba(61, 165, 255, .5),
             0 2px 13px rgba(2, 4, 8, .9); }
  .w--red { text-shadow: 0 0 13px rgba(255, 45, 60, .5), 0 2px 12px rgba(2, 4, 8, .96); }
  .s--sub { text-shadow: 0 0 1px rgba(255, 255, 255, .9), 0 0 6px rgba(2, 4, 8, .98),
            0 2px 11px rgba(2, 4, 8, .95); }
  .btn { box-shadow: 0 10px 26px -14px rgba(61, 165, 255, .85); }
  .chip { box-shadow: 0 8px 18px -12px rgba(0, 0, 0, .95), inset 0 1px 0 rgba(255, 255, 255, .1); }
  .search { box-shadow: 0 0 0 3px rgba(61, 165, 255, .07), 0 10px 26px -16px rgba(61, 165, 255, .7); }
  .prog i { box-shadow: 0 0 8px var(--accent, #4BAEFF); }
  .search { height: 52px; padding: 0 18px; font-size: 16px; }
  .chips { flex-direction: column; align-items: center; gap: 10px; }
  .chip { font-size: 15px; }
  .btn__in { padding: 18px 26px; font-size: 15px; gap: 10px; }
  .cta__logo { height: min(10.4vw, 6vh); }
}

/* TABLET DE PIE: los titulares escalan con el ancho, asi que el texto
   de apoyo tiene que escalar con ellos o queda diminuto al lado */
@media (max-aspect-ratio: 1/1) and (min-width: 600px) {
  .lede { font-size: min(3.1vw, 2.2vh); }
  .zone[data-zone="precio"] .lede { font-size: min(3.4vw, 2.4vh); }
  .m { font-size: min(1.7vw, 1.2vh); }
  .search { height: min(8.6vw, 6vh); font-size: min(2.6vw, 1.8vh); padding: 0 3vw; width: min(100%, 66vw); }
  .search__ico { width: 1.2em; height: 1.2em; }
  .chip { font-size: min(2.3vw, 1.6vh); }
  .price__note { font-size: min(2.5vw, 1.75vh); }
  .btn__in { font-size: min(2.9vw, 2vh); padding: 3.2vw 5.4vw; gap: 1.8vw; }
  .cta__logo { height: min(5.6vw, 4vh); }
  .cue__lbl { font-size: 14px; }
}

/* ============================================================
   APAISADO Y BAJO — celular acostado
   Poca altura: todo se mide por el alto y el texto vuelve arriba.
   ============================================================ */
/* TABLETA DE PIE (iPad y parecidos). Las medidas en vw del celular aqui
   se disparan —820 px de ancho— y el tramo del precio crece tanto que el
   remate cae dentro del resplandor del horizonte (medido: 2.49:1 en
   820x1180). Se acotan los tamaños y los verbos vuelven a una sola fila,
   que aqui si cabe. */
@media (max-aspect-ratio: 1/1) and (min-width: 700px) {
  .precio__num { font-size: min(11vw, 7.6vh); }
  .precio__num--sec { font-size: min(7.4vw, 5.1vh); }
  .precio__lbl { font-size: min(2.1vw, 1.45vh); }
  .precio__sello { font-size: min(9vw, 6.2vh); margin-top: clamp(20px, 3vh, 36px); }
  .precio__pie { font-size: min(3vw, 2.1vh); }
  .precio__filo--largo { width: min(34vw, 15rem); margin-block: clamp(16px, 2.2vh, 26px) clamp(10px, 1.5vh, 18px); }
  .precio__tacha { font-size: max(11px, min(1.9vw, 1.3vh)); letter-spacing: .18em; }
  .precio__inv { font-size: min(3.1vw, 2.15vh); max-width: 20em; }
  .precio__verbos { gap: clamp(14px, 2vw, 26px); margin-top: clamp(10px, 1.4vh, 18px); }
  .precio__verbos em { font-size: min(3.4vw, 2.35vh); }
}

@media (min-aspect-ratio: 1/1) and (max-height: 520px) {
  .zone { justify-content: flex-start; padding: max(7vh, 18px) var(--gut) 18px; }
  .zone[data-zone] { justify-content: flex-start; padding-top: max(7vh, 18px); }
  .kicker { margin-bottom: 1.6vh; }
  .neon { margin-top: 2vh; }
  .lede, .deal, .cta__wrap, .cta__meta, .chips, .search-row { margin-top: 2.4vh; }
  .search-row { margin-bottom: 2.4vh; }
  .search { height: 42px; font-size: 15px; }
  .chip { padding: 8px 14px 8px 11px; font-size: 13px; }
  .btn__in { padding: 12px 22px; font-size: 13px; }
  .cta__logo { height: max(26px, 8vh); }
  .cue { bottom: 10px; }
  /* el tramo del precio crece con el remate de venta: aqui abajo hay que
     apretarlo o la ultima linea cae sobre el resplandor del horizonte */
  .precio__num { font-size: min(9.6vh, 5.6vw); }
  .precio__num--sec { font-size: min(6.6vh, 3.9vw); }
  .precio__filo { margin: 1.6vh 0 1.2vh; }
  .precio__sello { margin-top: 3vh; font-size: min(7vh, 4.6vw); }
  .precio__pie { margin-top: 1.1vh; font-size: min(2.8vh, 1.9vw); }
  .precio__filo--largo { width: min(24vw, 10rem); margin: 2.4vh auto 1.5vh; }
  .precio__tacha { font-size: max(9px, min(1.7vh, 1.15vw)); margin-bottom: 1.2vh; }
  .precio__inv { font-size: min(2.9vh, 2vw); max-width: 24em; line-height: 1.2; }
  .precio__verbos { margin-top: .9vh; gap: min(1.8vw, 18px); }
  .precio__verbos em { font-size: min(2.9vh, 2vw); }
  .zone > .deco {
    --dx: max(min(4.5vw, 5.5vh), env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px));
    --dt: max(min(4.5vw, 5.5vh), env(safe-area-inset-top, 0px));
    --db: max(min(4.5vw, 5.5vh), env(safe-area-inset-bottom, 0px));
  }
}

/* ============================================================
   CELULAR DE PIE — el lienzo, la franja de Safari y el escaneo
   Mismo criterio que sb.js para elegir el juego vertical.
   ============================================================ */
@media (max-aspect-ratio: 1/1) {
  /* el marco de esquinas es de escritorio: aqui el efecto digital es la
     linea de escaneo dibujada en el lienzo (sb.js) */
  .zone > .deco { display: none; }
  /* Precio y contacto van sobre el fondo azul final, cuyo resplandor del
     horizonte sube desde el 58% del alto: centrados, el texto chico caia
     encima y no se leia (medido 1.8:1). Van lo mas abajo posible SIN
     tocarlo: el bloque apoya su borde de abajo en el 58%. El margin auto
     es el seguro: si en un telefono bajo el bloque no cabe, no se sale
     por arriba (bajo la barra de Safari) sino que arranca en el colchon
     de arriba como los demas tramos. */
  /* El precio SUBE: apoyado en el 58% chocaba con la rejilla digital y
     "La ves terminada antes de pagar" caia dentro del resplandor
     (Alexander, 2026-09-21). Ahora apoya en el 52%, sobre el cielo
     oscuro de la mitad de arriba. */
  /* EL ANCLA. El lienzo mide 100lvh (la ventana con la barra del
     navegador escondida) y el texto se compone dentro de 100svh (lo que
     SIEMPRE se ve). En un Android con la barra puesta esas dos medidas
     no coinciden, asi que un colchon en vh dejaba el bloque flotando muy
     por encima del horizonte —justo lo que se veia en el celular de
     Alexander (2026-09-23)—. Restando una de otra, el borde de abajo del
     bloque cae SIEMPRE en el 52% del lienzo, que es donde empieza a
     aclarar el horizonte, mida lo que mida la barra del navegador. */
  .zone[data-zone="precio"] { justify-content: flex-start; padding-bottom: max(0px, calc(100svh - 52lvh)); }
  /* El contacto baja: con el bloque apoyado en el 58% quedaba pegado a la
     mitad de arriba y se veia alto (Alexander, 2026-09-21). Ahora apoya en
     el 68%, justo por encima del resplandor del horizonte. */
  /* El contacto apoyaba en el 63% del lienzo y ahi ya esta el resplandor:
     medido sobre el propio fotograma f0695, el plano empieza a aclarar en
     el 54% del alto y el brillo pica en el 66%. En el iPhone de Alexander
     el logo caia justo encima de la rejilla (2026-09-23). Sube al 53%,
     igual que el precio: el bloque entero queda sobre el cielo oscuro. */
  .zone[data-zone="cta"] { justify-content: flex-start; padding-bottom: max(0px, calc(100svh - 53lvh)); }
  .zone[data-zone="precio"] > :first-child, .zone[data-zone="cta"] > :first-child { margin-top: auto; }
}
