/* ============================================================================
   Alio · Sección 1 (héroe) + Sección 2 (revelación del Home)
   ----------------------------------------------------------------------------
   Las dos secciones comparten UN SOLO recorrido de scroll anclado:

     [0 ────────── zoom ──────────][ beat 1 ][ beat 2 ][ beat 3 ][ beat 4 ]
      paisaje + teléfono pequeño    la pantalla queda fija y el texto cambia

   Todo el movimiento lo maneja js/hero.js escribiendo variables CSS sobre
   .hero (--p, --phone-s, --phone-y, --land-s, --amb-s). El CSS solo las
   consume: así hay un único punto de verdad y se puede afinar sin tocar JS.
   ========================================================================== */

/* ---------------------------------------------------------------------------
   Navegación (Mercury: transparente sobre el héroe, esmerilada al bajar)
   ------------------------------------------------------------------------ */

.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 60;
  display: flex;
  align-items: center;
  gap: var(--sp-24);
  padding: var(--sp-20) var(--gutter);
  transition: background-color 0.4s ease, backdrop-filter 0.4s ease,
    border-color 0.4s ease, color 0.4s ease;
  border-bottom: 1px solid transparent;

  /* Arriba del todo la barra flota sobre el cielo del crepúsculo, así que va
     en tinta clara. En cuanto se despega pasa a papel esmerilado con tinta
     pizarra, que es como la define el sistema. */
  color: var(--p-text-d);
  --nav-wash: rgba(233, 237, 242, 0.1);

  /* Y con la tinta viajan los tokens de acción. Sin esto el botón principal se
     quedaba en pizarra sólida sobre el cielo —pizarra sobre pizarra, ilegible—
     y el secundario en tinta oscura sobre oscuro. La regla del sistema es que
     la acción principal es pizarra; sobre banda oscura eso se invierte igual
     que en el modo oscuro del producto: relleno claro y tinta oscura. */
  --cta-bg: var(--p-text-d);
  --cta-bg-hover: #ffffff;
  --cta-fg: var(--p-on-slate-d);
  --ghost-line: rgba(233, 237, 242, 0.5);
  --ghost-wash: rgba(233, 237, 242, 0.08);
  --fg: var(--p-text-d);
}

.nav.is-stuck {
  color: var(--p-text);
  --cta-bg: var(--p-slate);
  --cta-bg-hover: var(--p-slate-deep);
  --cta-fg: var(--p-on-slate);
  --ghost-line: rgba(47, 62, 78, 0.45);
  --ghost-wash: rgba(47, 62, 78, 0.07);
  --fg: var(--p-text);
  background: rgba(246, 247, 248, 0.82);
  backdrop-filter: blur(20px) saturate(1.2);
  -webkit-backdrop-filter: blur(20px) saturate(1.2);
  border-bottom-color: rgba(23, 28, 34, 0.1);
  --nav-wash: rgba(23, 28, 34, 0.06);
}

/* El logotipo trae el nombre dibujado, así que sustituye al conjunto entero
   —marca + la palabra «alio» en Space Grotesk—: mantener las dos escribiría el
   nombre dos veces, una de ellas con una letra que no es la de la marca.

   Va SIEMPRE la versión oficial (pizarra + latón, `Design/Alio logo.png`), tal
   cual, sin recortar ni recolorear: el archivo del sitio es una copia idéntica
   del original. No hay variante clara ni monocroma, ni un `filter` que lo
   recoloree —aplanaría el latón del arco—, así que el fondo que haya detrás
   tiene que ser claro para que el logotipo se lea. Eso lo decide `.nav`, no
   esta regla. */
.nav__brand {
  display: block;
  flex: none;
}

.nav__logo {
  display: block;
  height: 24px;
  width: auto;
}

.nav__links {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  margin: 0 auto;
}

.nav__link {
  padding: 8px 16px;
  border-radius: var(--r-pill);
  font-size: var(--text-body);
  color: inherit;
  opacity: 0.86;
  transition: opacity 0.2s ease, background-color 0.2s ease;
}

.nav__link:hover {
  opacity: 1;
  background: var(--nav-wash);
}

.nav__actions {
  display: flex;
  align-items: center;
  gap: var(--sp-12);
}

/* En escritorio la fila de enlaces ya lleva «Ya tengo cuenta» a la derecha */
.nav__link--only-menu,
.nav__toggle {
  display: none;
}

/* --- El menú de pantalla estrecha ------------------------------------------
   Los enlaces no se esconden: se despliegan bajo la barra. El estado lo manda
   `aria-expanded` sobre el botón (js/nav.js), así que lo que anuncia el lector
   de pantalla y lo que se ve no se pueden desincronizar.
   ------------------------------------------------------------------------ */

@media (max-width: 900px) {
  .nav__brand {
    margin-right: auto;
  }

  .nav__actions .nav__login {
    display: none;
  }

  .nav__toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 1px solid currentColor;
    border-radius: 12px;
    background: var(--nav-wash);
    color: inherit;
    opacity: 0.85;
    cursor: pointer;
  }

  /* Tres rayas dibujadas con la propia caja y sus dos pseudo-elementos */
  .nav__burger,
  .nav__burger::before,
  .nav__burger::after {
    display: block;
    width: 18px;
    height: 2px;
    border-radius: 2px;
    background: currentColor;
    transition: transform 0.24s ease, opacity 0.16s ease;
  }

  .nav__burger {
    position: relative;
  }

  .nav__burger::before,
  .nav__burger::after {
    content: "";
    position: absolute;
    left: 0;
  }

  .nav__burger::before {
    top: -6px;
  }

  .nav__burger::after {
    top: 6px;
  }

  .nav.is-open .nav__burger {
    background: transparent;
  }

  .nav.is-open .nav__burger::before {
    transform: translateY(6px) rotate(45deg);
  }

  .nav.is-open .nav__burger::after {
    transform: translateY(-6px) rotate(-45deg);
  }

  .nav__link--only-menu {
    display: block;
  }

  .nav__links {
    position: absolute;
    left: var(--gutter);
    right: var(--gutter);
    top: calc(100% + 8px);
    z-index: 61;
    margin: 0;
    padding: var(--sp-8);
    display: grid;
    gap: 2px;
    border: 1px solid rgba(23, 28, 34, 0.12);
    border-radius: 18px;
    background: rgba(255, 255, 255, 0.97);
    color: var(--p-text);
    backdrop-filter: blur(24px) saturate(1.2);
    -webkit-backdrop-filter: blur(24px) saturate(1.2);
    box-shadow: 0 26px 60px rgba(23, 28, 34, 0.18);

    /* Cerrado no ocupa sitio Y no es tabulable: `visibility` es lo que saca
       sus enlaces del orden de foco. Solo con opacidad seguirían recibiendo el
       tabulador desde una barra que se ve vacía. */
    visibility: hidden;
    opacity: 0;
    transform: translateY(-8px);
    transition: opacity 0.2s ease, transform 0.2s ease,
      visibility 0s linear 0.2s;
  }

  .nav.is-open .nav__links {
    visibility: visible;
    opacity: 1;
    transform: none;
    transition: opacity 0.2s ease, transform 0.2s ease, visibility 0s;
  }

  .nav__links .nav__link {
    padding: 13px 14px;
    border-radius: 12px;
    text-align: left;
  }
}

/* Sin movimiento el panel aparece y desaparece, sin deslizarse */
.no-motion .nav__links {
  transition: none;
  transform: none;
}

/* ---------------------------------------------------------------------------
   El recorrido: un contenedor alto con un escenario anclado dentro
   ------------------------------------------------------------------------ */

.hero {
  position: relative;
  /* vuelo + corrimiento + lectura. El cambio de pestaña NO suma alto: sucede
     con la sección ya saliendo, sobre el scroll que la levanta. */
  height: calc(
    100vh + var(--zoom-scroll) + var(--shift-scroll) + var(--read-scroll)
  );

  /* Valores que escribe el JS. Los defaults dejan el estado inicial correcto
     aunque el JS no llegue a ejecutarse (fallo de red, error). */
  --p: 0; /* 0→1 · el vuelo hacia la pantalla */
  --q: 0; /* 0→1 · el teléfono se corre a la derecha */
  --phone-x: 0px;
  --phone-y: 220px;
  --phone-s: 0.26;
  --bezel: 1; /* opacidad del marco del teléfono */
  --glare: 1; /* brillo sobre el cristal */
  --screen-r: 44px; /* radio de la pantalla */
  --land-s: 1;
  --amb-s: 1;
  --amb-y: 0px;
  --screen-pos: 0; /* pestaña visible dentro del teléfono (0..N-1) */
}

.hero__stage {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
  isolation: isolate;
}

/* ---------------------------------------------------------------------------
   Capa 1 · Paisaje (el Ávila al amanecer, SVG por crestas)
   ------------------------------------------------------------------------ */

.landscape {
  position: absolute;
  inset: 0;
  z-index: 1;
  transform: scale(var(--land-s));
  transform-origin: 50% 45%;
  /* se apaga cuando la cámara ya entró en la pantalla */
  opacity: clamp(0, calc((0.82 - var(--p)) * 5), 1);
}

.landscape__sky {
  position: absolute;
  inset: 0;
  /* Las paradas van más abajo que en la versión anterior: el sistema es más
     desaturado que el amanecer morado que había, y a igual reparto la banda
     clara subía tanto que el titular se quedaba en 2,6:1. Comprimida contra el
     horizonte, que es además donde debe estar la luz, sube a 7:1. */
  background: linear-gradient(
    to bottom,
    var(--sky-0) 0%,
    var(--sky-1) 30%,
    var(--sky-2) 52%,
    var(--sky-3) 70%,
    var(--sky-4) 84%,
    var(--sky-5) 93%,
    var(--sky-6) 100%
  );
}

/* Resplandor del sol justo detrás de la cresta */
.landscape__sun {
  position: absolute;
  left: 50%;
  bottom: 14%;
  width: min(1100px, 130vw);
  aspect-ratio: 1;
  translate: -50% 0;
  background: radial-gradient(
    circle at center,
    rgba(230, 224, 212, 0.88) 0%,
    rgba(212, 178, 105, 0.46) 26%,
    rgba(169, 128, 58, 0.18) 46%,
    transparent 68%
  );
  filter: blur(4px);
}

.landscape__ridges {
  position: absolute;
  inset: auto 0 0 0;
  height: 78%;
}

.landscape__ridges svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* Bandas de neblina entre crestas: lo que da la profundidad de Mercury */
.mist {
  position: absolute;
  left: -10%;
  width: 120%;
  height: 16%;
  background: linear-gradient(
    to bottom,
    transparent,
    rgba(230, 224, 212, 0.22) 45%,
    transparent
  );
  filter: blur(14px);
  animation: mist-drift 34s ease-in-out infinite alternate;
}

.mist--a {
  bottom: 32%;
  animation-duration: 38s;
}
.mist--b {
  bottom: 28%;
  opacity: 0.7;
  animation-duration: 46s;
  animation-direction: alternate-reverse;
}
.mist--c {
  bottom: 15%;
  opacity: 0.5;
  animation-duration: 52s;
}

@keyframes mist-drift {
  from {
    transform: translateX(-3%);
  }
  to {
    transform: translateX(3%);
  }
}

/* Viñeta: oscurece los bordes para que el texto respire (Mercury) */
.landscape__veil {
  position: absolute;
  inset: 0;
  background: radial-gradient(
      120% 90% at 50% 40%,
      transparent 40%,
      rgba(16, 20, 25, 0.58) 100%
    ),
    linear-gradient(to bottom, rgba(16, 20, 25, 0.62) 0%, transparent 34%);
}

/* ---------------------------------------------------------------------------
   Capa 2 · Ambiental (Wealthsimple: línea-gráfico, tarjetas, número)
   ------------------------------------------------------------------------ */

.ambient {
  position: absolute;
  inset: 0;
  z-index: 2;
  transform: translateY(var(--amb-y)) scale(var(--amb-s));
  transform-origin: 50% 45%;
  pointer-events: none;
  /* pasa de largo junto a la cámara: se va antes que el paisaje */
  opacity: clamp(0, calc((0.44 - var(--p)) * 4), 1);
}

.ambient__chart {
  position: absolute;
  left: -4%;
  top: 8%;
  width: 108%;
  height: 30%;
  overflow: visible;
}

.ambient__line {
  fill: none;
  stroke: rgba(255, 255, 255, 0.92);
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  filter: drop-shadow(0 2px 10px rgba(255, 255, 255, 0.35));
  stroke-dasharray: var(--len, 3000);
  stroke-dashoffset: var(--len, 3000);
  animation: draw-line 3.2s cubic-bezier(0.32, 0.72, 0.24, 1) 0.35s forwards;
}

@keyframes draw-line {
  to {
    stroke-dashoffset: 0;
  }
}

/* Punto que viaja por la línea mientras se dibuja */
.ambient__dot {
  fill: #fff;
  opacity: 0;
  animation: dot-in 0.5s ease 3.3s forwards;
}

@keyframes dot-in {
  to {
    opacity: 1;
  }
}

/* --- Tarjetas flotantes ---------------------------------------------------
   Wealthsimple usa fotos de estilo de vida. Aquí son fragmentos REALES de la
   app: una tasa, un gasto, una meta, un presupuesto. Además de decorar,
   adelantan de qué trata Alio.
   ------------------------------------------------------------------------ */

/* Las fichas se COLOCAN en porcentajes del escenario, así que su posición ya
   era responsive — pero su tamaño no: el relleno y la letra iban en píxeles
   fijos, y al encoger la ventana crecían en proporción a todo lo demás hasta
   competir con el titular. Ahora el tamaño también sigue al ancho. El tope
   superior es el valor de siempre, así que en escritorio no cambia nada. */
.chip {
  position: absolute;
  display: flex;
  align-items: center;
  gap: clamp(5px, 0.6vw, 8px);
  padding: clamp(6px, 0.7vw, 9px) clamp(9px, 1vw, 13px);
  border-radius: clamp(9px, 0.9vw, 12px);
  background: rgba(255, 255, 255, 0.92);
  color: var(--p-text);
  font-size: clamp(10px, 0.94vw, 12px);
  font-weight: 500;
  letter-spacing: -0.01em;
  white-space: nowrap;
  box-shadow: 0 14px 34px rgba(16, 20, 25, 0.3);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  opacity: 0;
  transform: translateY(10px) scale(0.94);
  animation: chip-in 0.8s cubic-bezier(0.2, 0.8, 0.2, 1) forwards,
    chip-float 7s ease-in-out infinite alternate;
}

@keyframes chip-in {
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

@keyframes chip-float {
  from {
    translate: 0 -5px;
  }
  to {
    translate: 0 5px;
  }
}

.chip__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex: none;
}

.chip__val {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.chip--a {
  left: 8%;
  top: 21%;
  animation-delay: 1s, 1.8s;
}
.chip--b {
  left: 19%;
  top: 38%;
  animation-delay: 1.5s, 2.3s;
}
.chip--c {
  right: 10%;
  top: 18%;
  animation-delay: 1.25s, 2.05s;
}
.chip--d {
  right: 20%;
  top: 37%;
  animation-delay: 1.75s, 2.55s;
}
.chip--e {
  left: 64%;
  top: 10%;
  animation-delay: 2s, 2.8s;
}

@media (max-width: 900px) {
  .chip--b,
  .chip--e {
    display: none;
  }
  .chip--a {
    left: 3%;
    top: 18%;
  }
  .chip--c {
    right: 3%;
    top: 16%;
  }
  .chip--d {
    right: 6%;
    top: 34%;
  }
}

/* --- Número grande --------------------------------------------------------
   Corre rápido y se asienta. El valor final NO es decorativo: es la suma de
   los dos saldos que se ven en el teléfono, convertidos a la tasa BCV.
   ------------------------------------------------------------------------ */

.ambient__figure {
  position: absolute;
  left: 50%;
  /* El suelo en píxeles NO es decorativo: la barra de navegación es fija y mide
     ~81 px pase lo que pase, mientras que un porcentaje encoge con la ventana.
     Con `13 %` a secas, en un escenario de 800 px la cifra empezaba 4 px por
     debajo del borde de la barra. */
  top: clamp(120px, 15%, 180px);
  translate: -50% -50%;
  text-align: center;
  width: min(560px, 92vw);
  opacity: 0;
  animation: figure-in 0.9s ease 0.6s forwards;
}

@keyframes figure-in {
  to {
    opacity: 1;
  }
}

.ambient__number {
  margin: 0;
  font-size: clamp(1.75rem, 0.8rem + 1.6vh + 2.2vw, 3.75rem);
  font-weight: 700;
  letter-spacing: var(--tracking-display);
  line-height: 1;
  color: #fff;
  font-variant-numeric: tabular-nums;
  text-shadow: 0 4px 40px rgba(10, 12, 34, 0.5);
}


/* Ventana baja: el número encoge, así que su centro puede subir un poco — pero
   nunca por encima de la barra. */
.hero.is-tight .ambient__figure {
  top: clamp(108px, 15%, 160px);
}

.hero.is-tight .ambient__number {
  font-size: clamp(1.4rem, 0.7rem + 2vw, 2rem);
}

/* ---------------------------------------------------------------------------
   Capa 3 · Teléfono
   ------------------------------------------------------------------------
   Clave de nitidez: el teléfono se maqueta al tamaño FINAL (pantalla completa)
   y arranca reducido (--phone-s ≈ 0.26). Al terminar el vuelo la escala es 1,
   así que el estado que el usuario se queda mirando está sin escalar y el
   texto se lee perfecto. Al revés (maquetar pequeño y agrandar) se vería
   borroso justo donde más importa.
   ------------------------------------------------------------------------ */

.phone {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 3;
  translate: -50% -50%;
  transform: translate(var(--phone-x), var(--phone-y)) scale(var(--phone-s));
  transform-origin: 50% 50%;
}

/* El marco escala con la pantalla, no en pixeles fijos: js/hero.js escribe
   `--home-s`, la misma escala con la que se dibuja el contenido de la app.
   Con un valor fijo, el grosor relativo del marco cambiaba con el tamano de
   la ventana — y un telefono no cambia de proporciones al cambiar de
   monitor. De paso baja de 12 a 10: los telefonos de 2026 tienen menos
   marco que el que dibujaba esta maqueta. */
.phone__body {
  position: relative;
  padding: calc(10px * var(--home-s, 1));
}

/* El marco es un pseudo-elemento, no el contenedor: así puede desvanecerse
   por su cuenta sin llevarse la pantalla con él. Se va al entrar en la
   pantalla y VUELVE cuando la cámara retrocede y el teléfono se corre a la
   derecha — que es lo que hace legible que sigues viendo un teléfono. */
.phone__body::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: calc(54px * var(--home-s, 1));
  background: linear-gradient(160deg, #3c4c5e 0%, #141a21 46%, #2f3e4e 100%);
  box-shadow: 0 40px 90px rgba(16, 20, 25, 0.5),
    0 0 0 1px rgba(255, 255, 255, 0.1), inset 0 1px 2px rgba(255, 255, 255, 0.22);
  opacity: var(--bezel);
}

/* La camara frontal, tambien proporcional. Y mas discreta: 108x26 era una
   isla de iPhone antiguo sobre una maqueta de 400 px de ancho. */
.phone__notch {
  position: absolute;
  left: 50%;
  top: calc(20px * var(--home-s, 1));
  translate: -50% 0;
  width: calc(96px * var(--home-s, 1));
  height: calc(24px * var(--home-s, 1));
  border-radius: var(--r-pill);
  background: #0c1015;
  opacity: var(--bezel);
  z-index: 4;
}

/* Brillo diagonal sobre el cristal, se va al entrar */
.phone__glare {
  position: absolute;
  inset: calc(10px * var(--home-s, 1));
  border-radius: calc(44px * var(--home-s, 1));
  background: linear-gradient(
    122deg,
    rgba(255, 255, 255, 0.24) 0%,
    rgba(255, 255, 255, 0.06) 26%,
    transparent 52%
  );
  pointer-events: none;
  z-index: 3;
  opacity: var(--glare);
}

.phone__screen {
  position: relative;
  z-index: 2;
  overflow: hidden;
  border-radius: var(--screen-r);
  background: var(--p-bg);
}

/* Una pantalla de app entera, brillante y a tamaño de sello, es ruido: hay
   demasiada información compitiendo cuando todavía no se puede leer ninguna.

   Arranca APAGADA DEL TODO —un teléfono que aún no has encendido— y se
   enciende a medida que la cámara entra, así que la legibilidad llega justo
   cuando el tamaño ya la permite. El velo es opaco: antes eran 0,9 y 0,82 de
   alfa, o sea que la interfaz se transparentaba desde el primer momento.

   La curva la escribe js/hero.js en `--screen-off` y no se calcula aquí: desde
   el negro absoluto una rampa lineal se lee como un interruptor. El valor de
   reserva es 1 —apagada— para que un fallo del script no destape la pantalla a
   tamaño de sello, que es justo lo que este velo viene a evitar. */
.phone__screen::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  border-radius: inherit;
  background: linear-gradient(170deg, #161d25 0%, #0c1015 100%);
  opacity: var(--screen-off, 1);
}

/* La promoción a capa propia SOLO mientras hay movimiento. Si se deja fija,
   el navegador congela la rasterización a la escala pequeña y el Home se lee
   borroso justo donde el usuario se detiene. */
.hero.is-scrolling .phone,
.hero.is-scrolling .landscape,
.hero.is-scrolling .ambient,
.hero.is-scrolling .app__track {
  will-change: transform;
}

.hero.is-scrolling .panel {
  will-change: transform, opacity;
}

/* ---------------------------------------------------------------------------
   Copia del héroe (se retira apenas empieza el vuelo)
   ------------------------------------------------------------------------ */

/* El titular va DEBAJO del teléfono, como en Wealthsimple: arriba manda la
   animación (línea, tarjetas y número) y el texto cierra la composición.
   Con el titular arriba, la línea y el número no tenían dónde caber. */
/* El bloque ya no cierra la composición por abajo: sube a la franja central
   —donde antes estaba el teléfono— y le deja a este toda la parte baja del
   escenario. El anclaje es por ARRIBA, porque lo que tiene que quedar fijo es
   dónde empieza a leerse; lo que crezca hacia abajo se lo come el hueco del
   teléfono, que js/hero.js vuelve a medir. */
.hero__copy {
  position: absolute;
  z-index: 4;
  left: 50%;
  top: clamp(148px, 23vh, 232px);
  translate: -50% 0;

  /* El bloque vive sobre el cielo del crepúsculo, así que sus acciones toman
     los tokens de banda OSCURA — misma inversión que en .nav. Sin esto el
     botón principal salía en pizarra sólida sobre pizarra y el secundario en
     tinta oscura sobre oscuro: los dos ilegibles. */
  --cta-bg: var(--p-text-d);
  --cta-bg-hover: #ffffff;
  --cta-fg: var(--p-on-slate-d);
  --ghost-line: rgba(233, 237, 242, 0.5);
  --ghost-wash: rgba(233, 237, 242, 0.08);
  --fg: var(--p-text-d);
  /* Ancho generoso a propósito: con 680 px el titular caía en tres líneas y
     esa tercera línea se comía justo el hueco donde va el teléfono. */
  width: min(880px, calc(100vw - 2 * var(--gutter)));
  text-align: center;
  opacity: clamp(0, calc((0.16 - var(--p)) * 8), 1);
  transform: translateY(calc(var(--p) * 60px));
  pointer-events: auto;
}

/* El velo propio del bloque. Un titular blanco sobre un paisaje depende de por
   dónde caiga: medido, sobre la banda de peltre con la neblina encima se
   quedaba en 2,8:1. La sombra de texto no cuenta para WCAG; esto sí. El
   degradado no tiene borde visible, así que no se lee como una caja. */
.hero__copy::before {
  content: "";
  position: absolute;
  inset: -14% -10%;
  z-index: -1;
  border-radius: 50%;
  background: radial-gradient(
    58% 68% at 50% 50%,
    rgba(16, 20, 25, 0.74) 0%,
    rgba(16, 20, 25, 0.55) 46%,
    rgba(16, 20, 25, 0) 74%
  );
  pointer-events: none;
}

.hero.is-flying .hero__copy {
  pointer-events: none;
}

.hero__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 var(--sp-20);
  padding: 6px 14px;
  border: 1px solid rgba(233, 237, 242, 0.34);
  border-radius: var(--r-pill);
  font-family: var(--font-display);
  font-size: var(--text-caption);
  font-weight: 600;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: rgba(233, 237, 242, 0.9);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

.hero__eyebrow::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--p-slate-d);
  box-shadow: 0 0 0 3px rgba(159, 180, 201, 0.22);
}

.hero__title {
  margin: 0;
  font-size: var(--text-h1);
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: var(--tracking-display);
  color: #fff;
  text-shadow: 0 6px 44px rgba(16, 20, 25, 0.45);
  text-wrap: balance;
}

.hero__sub {
  margin: var(--sp-20) auto 0;
  max-width: 46ch;
  font-size: var(--text-lg);
  line-height: 1.5;
  color: rgba(233, 237, 242, 0.92);
  text-wrap: pretty;
}

.hero__cta {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--sp-12);
  margin-top: var(--sp-32);
}

/* Pista de scroll + salto accesible */
.hero__hint {
  margin-top: clamp(16px, 2.4vh, 26px);
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 9px 18px;
  border-radius: var(--r-pill);
  border: 1px solid rgba(233, 237, 242, 0.3);
  background: rgba(16, 20, 25, 0.42);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  font-size: var(--text-sm);
  color: rgba(233, 237, 242, 0.94);
  transition: border-color 0.2s ease;
}

.hero__hint:hover {
  border-color: rgba(233, 237, 242, 0.62);
}

.hero__hint svg {
  animation: hint-bob 2.2s ease-in-out infinite;
}

@keyframes hint-bob {
  0%,
  100% {
    transform: translateY(-2px);
  }
  50% {
    transform: translateY(2px);
  }
}

/* Aviso legal al pie del héroe (Mercury) */
.hero__legal {
  position: absolute;
  z-index: 5;
  left: 50%;
  bottom: 0;
  translate: -50% 0;
  width: 100%;
  padding: 8px var(--gutter);
  text-align: center;
  font-size: 11px;
  letter-spacing: 0.01em;
  color: rgba(233, 237, 242, 0.74);
  background: linear-gradient(to top, rgba(16, 20, 25, 0.62), transparent);
  opacity: clamp(0, calc((0.06 - var(--p)) * 18), 1);
}

/* Móvil: el titular se lleva media pantalla si no se le pone freno. Se reduce
   la escala, se retira la acción secundaria (la pista de scroll ya cumple ese
   papel) y se sube todo el pie para que el teléfono conserve su hueco. */
@media (max-width: 720px) {
  .hero__title {
    font-size: clamp(1.75rem, 1.1rem + 4vw, 2.25rem);
  }

  .hero__sub {
    margin-top: 14px;
    font-size: 15px;
  }

  .hero__cta {
    margin-top: 20px;
  }

  .hero__cta .btn--ghost {
    display: none;
  }

  .hero__copy {
    top: clamp(124px, 20vh, 186px);
  }

  .hero__hint {
    margin-top: clamp(12px, 2vh, 20px);
  }

  /* El sistema pone el suelo en 11 px: por debajo no se usa nada. */
  .hero__legal {
    padding: 6px 16px;
    font-size: 11px;
  }
}

/* Ventana baja (un portátil de 1280×800 deja ~700 px de viewport): el bloque
   de texto se comprime para que al teléfono le quede un hueco digno. Sin
   esto, en esas pantallas el teléfono bajaba a 55 px de ancho. */
@media (max-height: 840px) {
  .hero__eyebrow {
    margin-bottom: 12px;
    padding: 4px 12px;
  }

  .hero__sub {
    margin-top: 14px;
    font-size: var(--text-body);
  }

  .hero__cta {
    margin-top: 20px;
  }

  .hero__cta .btn {
    padding: 11px 22px;
  }

  /* El suelo tiene que dejar pasar la cifra, que se ancla en píxeles por la
     barra fija: con 142 px el titular arrancaba pegado a ella en un escenario
     de 700 (1 px de separación). */
  .hero__copy {
    top: clamp(164px, 21vh, 196px);
  }

  .hero__hint {
    margin-top: 14px;
    padding: 7px 15px;
  }

  .hero__legal {
    padding: 6px var(--gutter);
    font-size: 11px;
  }

  /* El bloque de la sección 2 también se comprime: en 700 px de alto medía
     635 y su titular acababa por debajo de la barra de navegación. */
  .panel__index {
    margin-bottom: var(--sp-12);
  }

  .panel__text {
    margin-top: var(--sp-12);
    font-size: var(--text-body);
  }

  .panel__list {
    margin-top: var(--sp-16);
    gap: var(--sp-8);
  }

  .panel__list li {
    padding-left: 22px;
    font-size: var(--text-sm);
  }

  .panel__list li::before {
    width: 6px;
    height: 6px;
  }

  .panel__close {
    margin-top: var(--sp-16);
    padding-top: var(--sp-12);
    font-size: var(--text-body);
  }
}

/* Pantallas muy pequeñas (320×568 sigue siendo el suelo real de Android). Aquí
   el escenario estaba sobresuscrito: barra + cifra + teléfono + titular + pista
   + aviso legal no caben en 568 px, y el resultado medido era el hueco del
   teléfono reducido a 30 px, la pista pisando el titular y el aviso pisando la
   pista. El motor ya no dibuja un teléfono más grande que su hueco (hero.js),
   así que aquí solo hay que devolverle hueco quitando lo prescindible.

   Se va la pista «Baja para entrar»: en una pantalla táctil nadie necesita que
   le digan que la página baja, y era lo único de los cuatro que no aporta
   información. El aviso legal se queda: dice que Alio no es un banco. */
@media (max-width: 380px), (max-width: 900px) and (max-height: 600px) {
  .hero__eyebrow {
    display: none;
  }

  .hero__hint {
    display: none;
  }

  .hero__title {
    font-size: clamp(1.5rem, 1rem + 3.4vw, 1.9rem);
  }

  .hero__sub {
    margin-top: 10px;
    font-size: 14px;
  }

  .hero__cta {
    margin-top: 16px;
  }

  /* Aquí la cifra ya va anclada en píxeles bajo la barra fija, así que el
     titular tiene que arrancar por debajo de ella y no de un porcentaje: con
     17vh en un escenario de 568 empezaba 2 px POR ENCIMA del número. */
  .hero__copy {
    top: clamp(146px, 26vh, 182px);
  }

  .hero__legal {
    padding: 5px var(--gutter);
    font-size: 11px;
    line-height: 1.35;
  }
}

/* ---------------------------------------------------------------------------
   Sección 2 · Los beneficios, sobre la pantalla ya revelada
   ------------------------------------------------------------------------ */

/* Fondo limpio que aparece detrás cuando el paisaje se va */
.reveal__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  /* El vuelo termina en PAPEL, no en otra noche: es el mismo salto que hace
     el sistema al pasar del crepúsculo a la superficie de lectura. */
  background: radial-gradient(90% 70% at 50% 42%, #ffffff 0%, var(--p-bg) 64%),
    var(--p-bg);
  opacity: clamp(0, calc((var(--p) - 0.6) * 3.2), 1);
}

/* El texto de la izquierda: un solo bloque, el que explica por qué Alio.
   Aparece cuando el teléfono ya se corrió a la derecha (--q) y se queda ahí
   hasta que la sección entera se va con el scroll. */
.panels {
  position: absolute;
  z-index: 5;
  inset: 0;
  pointer-events: none;
  opacity: clamp(0, calc((var(--q) - 0.2) * 2.6), 1);
}

.panel {
  position: absolute;
  left: clamp(32px, 7vw, 120px);
  top: 50%;
  translate: 0 -50%;
  width: min(470px, 39vw);
  /* entra con un empujoncito desde abajo, atado al mismo progreso */
  transform: translateY(calc((1 - var(--q)) * 26px));
}

.panel__index {
  display: block;
  margin-bottom: var(--sp-16);
  font-family: var(--font-display);
  font-size: var(--text-caption);
  font-weight: 600;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--p-sub);
}

.panel__title {
  font-size: var(--text-h2);
  font-weight: 600;
  line-height: 1.08;
  letter-spacing: var(--tracking-display);
  color: var(--p-text);
  text-wrap: balance;
}

.panel__text {
  margin-top: var(--sp-16);
  font-size: var(--text-lg);
  line-height: 1.5;
  color: var(--p-text);
  text-wrap: pretty;
}

.panel__list {
  margin: var(--sp-24) 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--sp-12);
}

.panel__list li {
  position: relative;
  padding-left: 26px;
  font-size: var(--text-body);
  line-height: 1.45;
  color: var(--p-sub);
  text-wrap: pretty;
}

/* La marca de cada línea es pizarra: en el sistema el color no decora, y el
   latón está reservado a la celebración de un logro. */
.panel__list li::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 0.55em;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--p-slate);
  box-shadow: 0 0 0 3px rgba(47, 62, 78, 0.14);
}

.panel__close {
  margin-top: var(--sp-24);
  padding-top: var(--sp-20);
  border-top: 1px solid rgba(23, 28, 34, 0.14);
  font-size: var(--text-lg);
  font-weight: 500;
  color: var(--p-text);
}

/* Sin sitio a los lados: el texto se va arriba y el teléfono baja. */
@media (max-width: 900px) {
  .panel {
    left: 0;
    right: 0;
    top: clamp(80px, 12vh, 124px);
    translate: none;
    width: auto;
    padding: 0 var(--gutter) 48px;
    text-align: center;
    /* El teléfono sube hasta rozar el texto. El degradado hace de colchón:
       lo que queda encima de la pantalla se sigue leyendo, y el borde
       superior es invisible porque cae sobre el mismo lienzo. */
    background: linear-gradient(
      to bottom,
      rgba(246, 247, 248, 0.96) 0%,
      rgba(246, 247, 248, 0.92) 62%,
      rgba(246, 247, 248, 0) 100%
    );
  }

  .panel__index {
    margin-bottom: var(--sp-8);
  }

  .panel__title {
    font-size: clamp(1.4rem, 1rem + 2.6vw, 1.9rem);
  }

  .panel__text {
    margin-top: var(--sp-12);
    font-size: 15px;
  }

  /* Apilado no hay sitio para las cinco líneas encima de la pantalla: manda
     el titular y la frase que lo resume. */
  .panel__list,
  .panel__close {
    display: none;
  }
}

/* ---------------------------------------------------------------------------
   Sección siguiente (marcador de posición — estructura pendiente)
   ------------------------------------------------------------------------ */

/* Marcador de posición para las secciones que faltan. El scroll que la salida
   de la sección 2 necesita ya lo aporta la franja lateral, que va justo
   debajo; aun así el motor lo mide en vivo y acorta el giro si algún día no
   cupiera (js/hero.js · L.turn). */
.next {
  position: relative;
  z-index: 2;
  background: var(--canvas);
  padding: var(--sp-112) var(--gutter);
  border-top: 1px solid var(--hairline);
  text-align: center;
}

.next__inner {
  max-width: 640px;
  margin: 0 auto;
}

.next h2 {
  margin: 0;
  font-size: var(--text-h3);
  font-weight: 500;
  letter-spacing: var(--tracking-tight);
}

.next p {
  margin: var(--sp-16) 0 0;
  color: var(--fg-soft);
}

/* ---------------------------------------------------------------------------
   Modo sin movimiento: el recorrido se desarma en una lectura normal
   ------------------------------------------------------------------------ */

.no-motion .hero {
  height: auto;
}

.no-motion .hero__stage {
  position: relative;
  height: auto;
  min-height: 100vh;
  padding: clamp(120px, 18vh, 200px) var(--gutter) var(--sp-72);
  display: grid;
  justify-items: center;
  gap: var(--sp-56);
}

.no-motion .hero__copy,
.no-motion .hero__hint,
.no-motion .hero__legal,
.no-motion .ambient,
.no-motion .ambient__figure,
.no-motion .phone {
  position: static;
  translate: none;
  transform: none;
  opacity: 1;
}

/* La cifra grande baja al flujo como una fila más de la rejilla. Antes se
   quedaba ABSOLUTA (era lo único que este bloque no devolvía a `static`) y
   flotaba sobre el teléfono: en 1280×800 el número se imprimía encima de la
   pantalla de la app. */
.no-motion .ambient__figure {
  width: auto;
  animation: none;
}

/* La gráfica y las fichas solo tienen sentido flotando sobre el paisaje
   durante el vuelo. Sin vuelo no tienen dónde posarse. */
.no-motion .ambient__chart,
.no-motion .chip {
  display: none;
}

/* `scale` no cambia la caja de maquetación, así que hacía falta compensarla
   con un margen negativo — pero un porcentaje VERTICAL se resuelve contra el
   ANCHO del contenedor, no contra el alto. En un escenario de 1265 px eso eran
   −407 px por lado: el teléfono se metía debajo de la barra fija y sus últimos
   50 px pisaban el titular.

   La compensación exacta de `scale: s` sobre la caja de 424 × 924 px del
   teléfono (400 + 24 de marco, 900 + 24) es (1−s)/2 de cada dimensión, en
   píxeles. Y hay que hacerla en LOS DOS ejes: sin la horizontal, la columna de
   la rejilla la fijaba el teléfono sin escalar, y en 390 px el titular salía
   desplazado 37 px a la derecha con el borde cortado. */
.no-motion .phone {
  --nm-s: 0.62;
  scale: var(--nm-s);
  margin: calc((var(--nm-s) - 1) * 462px) calc((var(--nm-s) - 1) * 212px);
}

@media (max-width: 720px) {
  .no-motion .phone {
    --nm-s: 0.7;
  }
}

@media (max-width: 380px) {
  .no-motion .phone {
    --nm-s: 0.56;
  }
}

.no-motion .landscape {
  transform: none;
  opacity: 1;
}

.no-motion .panels {
  position: static;
  display: grid;
  gap: var(--sp-56);
  opacity: 1;
  padding: var(--sp-72) var(--gutter);
  background: var(--canvas);
}

.no-motion .panel {
  position: static;
  translate: none;
  transform: none !important;
  opacity: 1 !important;
  width: min(640px, 100%);
  margin: 0 auto;
  text-align: left;
}

.no-motion .reveal__bg {
  display: none;
}
