/* ==========================================================================
   Soul Voice — Landing de campaña · tema "navy + naranja"
   --------------------------------------------------------------------------
   TEMA DE CAMPAÑA, NO REBRAND. Esta hoja es un tema completo y REVERSIBLE:
   para volver atrás se cambia el <link> de vuelta a oferta.css y nada más.
   oferta.css sigue en el repo intacto justo para eso.

   DIRECCIÓN (día 73) — aprobada por Leonardo, no deducida:
   El tema vino/magenta del día 72 fue RECHAZADO ("no me gusta el color, ni la
   letra ni nada"), igual que el teal/coral del día 70. Lo único que Leonardo
   nunca rechazó es la HOME (soulvoice.lat). Así que el tema deja de inventar y
   copia la home:

   - Color: navy + naranja, MEDIDOS en vivo de la home, no elegidos por gusto.
     El naranja de la home es #eb7532 = oklch(0.685 0.160 45) = el --ember que
     esta hoja ya tenía. El botón siempre estuvo bien; lo demás no.
   - Letra: Nunito. Es la que YA usan GroupCos y Soul 360, y Soul Voice es la
     misma casa (confirmado por Leonardo el día 73). Una sola familia, dos pesos
     (400/700), como ellos. Se fue Bricolage/Archivo: Leonardo dijo que se ven
     "muy fake" — son las tipografías de moda de las startups de IA.
   - Base clara + hero/cierre oscuros: se conserva. Es lo que ya hacía
     SOULVOICE-BRAND.md y lo que hace la home. Lo único que cambia es el hue.

   CONTRASTE — la trampa que ya nos costó un bug vivo:
   El naranja sobre BLANCO da 2.89:1 y REPRUEBA AA. Por eso hay dos acentos:
     --accent-ink    → naranja quemado, para texto sobre CLARO   (pasa AA)
     --accent-bright → naranja vivo,    para texto sobre OSCURO  (pasa AA)
   Y el CTA lleva tinta OSCURA (--ink) sobre el naranja = 6.3:1, igual que la
   home. Nunca texto claro sobre naranja: eso es el bug de oferta.css.

   NO lleva: partículas · orbes con anillos · cuñas diagonales · gradientes en
   texto · glassmorphism · border-left de color · manos de robot · dobles
   exposiciones (el cliché #1 de la IA, y dice lo contrario de nuestra promesa).
   ========================================================================== */

/* ---------- Tokens ---------- */
:root {
  /* Navy — medido EN VIVO de la home (#0b1220 · #0f1a33 · #191f2e), no del deck */
  --navy-950:       oklch(0.16 0.030 265);  /* fondo hero/cierre — #0b1220 */
  --navy-900:       oklch(0.21 0.045 265);  /* #0f1a33 */
  --navy-800:       oklch(0.27 0.045 265);  /* chips oscuros + texto fuerte sobre claro */

  /* Dos acentos, uno por fondo. No es adorno: es lo que evita el bug de contraste. */
  --accent-ink:     oklch(0.50 0.140 45);   /* naranja quemado → sobre CLARO  (~5:1) */
  --accent-bright:  oklch(0.72 0.150 48);   /* naranja vivo    → sobre OSCURO (~6:1) */

  /* Naranja = CTA. Es el de la home: #eb7532. Siempre con tinta oscura encima. */
  --ember:          oklch(0.685 0.160 45);
  --ember-bright:   oklch(0.755 0.165 48);

  /* Neutros TINTADOS al hue del navy (265). Nada de gris verdadero. */
  --paper:          oklch(0.99 0.004 265);
  --surface:        oklch(0.968 0.008 265);
  --surface-sunk:   oklch(0.945 0.010 265);
  --line:           oklch(0.90 0.014 265);
  --line-strong:    oklch(0.82 0.020 265);
  --ink:            oklch(0.22 0.030 265);  /* titular tono 1 + tinta del CTA */
  --ink-soft:       oklch(0.46 0.028 265);
  --ink-faint:      oklch(0.545 0.022 265); /* 4.6:1 sobre --paper. En 0.62 daba 3.55 y REPROBABA AA:
                                               es el color de las etiquetas y pistas del formulario. */
  --on-dark:        oklch(0.97 0.008 265);
  --on-dark-soft:   oklch(0.78 0.020 265);
  --on-dark-faint:  oklch(0.68 0.025 265);  /* 4.8:1 sobre --navy-950 */

  /* Tipografía: UNA familia, como Soul 360. Nunito es humanista de terminales
     redondeadas — cálida a propósito. Contraste por ESCALA (~3x), no por peso:
     ellos cargan 8 pesos y usan 2. Nosotros cargamos 3 y usamos 2. */
  --font-display: 'Nunito', system-ui, sans-serif;
  --font-body:    'Nunito', system-ui, sans-serif;

  /* Escala modular fluida, ratio ~1.28 */
  --text-xs:   0.78rem;
  --text-sm:   0.875rem;
  --text-base: 1rem;
  --text-lg:   clamp(1.06rem, 1rem + 0.28vw, 1.2rem);
  --text-xl:   clamp(1.3rem, 1.18rem + 0.55vw, 1.6rem);
  --text-2xl:  clamp(1.7rem, 1.44rem + 1.2vw, 2.4rem);
  --text-3xl:  clamp(2.2rem, 1.7rem + 2.3vw, 3.4rem);
  --text-hero: clamp(2.6rem, 1.75rem + 3.9vw, 5.1rem);
  --text-stat: clamp(2.4rem, 1.9rem + 2.2vw, 3.5rem);

  /* Espaciado 4pt, semántico */
  --space-2xs: 0.25rem;
  --space-xs:  0.5rem;
  --space-sm:  0.75rem;
  --space-md:  1rem;
  --space-lg:  1.5rem;
  --space-xl:  2rem;
  --space-2xl: 3rem;
  --space-3xl: 4rem;
  --space-section: clamp(3.5rem, 2.5rem + 4.5vw, 7rem);

  /* Motion — curvas fuertes; las de CSS por defecto no tienen punch */
  --ease-out:    cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  --dur-press: 160ms;
  --dur-fast:  200ms;
  --dur-mid:   260ms;

  --radius:    14px;
  --radius-sm: 9px;
  --wrap: 1180px;
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
img, svg { max-width: 100%; }
svg { display: block; }
a { color: inherit; }

h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 800;
  line-height: 1.02;
  letter-spacing: -0.025em;
  margin: 0;
  text-wrap: balance;
}
h3 { font-weight: 700; line-height: 1.18; letter-spacing: -0.015em; }
p { margin: 0; }
ul { margin: 0; padding: 0; list-style: none; }

.wrap { width: 100%; max-width: var(--wrap); margin-inline: auto; padding-inline: clamp(1.1rem, 4vw, 2rem); }

/* Titular a dos tonos. Color SÓLIDO — jamás background-clip. */
.hl { color: var(--navy-800); }
.on-dark .hl, .hero .hl, .closing .hl { color: var(--accent-bright); }

/* ---------- El ornamento firma: la regla corta ----------
   Es lo que de verdad se repite en el deck. Va bajo el titular, mide 3rem y
   nunca cruza la caja: es un signo tipográfico, no un borde de tarjeta. */
.rule {
  width: 3rem; height: 3px;
  background: var(--navy-800);
  border: 0; margin: var(--space-md) 0 0;
}
.on-dark .rule, .hero .rule, .closing .rule { background: var(--accent-bright); }
.center .rule { margin-inline: auto; }

/* ---------- Eyebrow ---------- */
.eyebrow {
  display: inline-flex; align-items: center; gap: var(--space-xs);
  font-family: var(--font-body);
  font-size: var(--text-xs); font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--accent-ink);
}
.hero .eyebrow, .closing .eyebrow, .on-dark .eyebrow { color: var(--accent-bright); }

/* ---------- Botones ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.6rem;
  font-family: var(--font-body); font-weight: 700; font-size: var(--text-base);
  padding: 0.85rem 1.4rem; min-height: 48px;   /* target táctil */
  border: 0; border-radius: var(--radius-sm);
  cursor: pointer; text-decoration: none;
  transition: transform var(--dur-press) var(--ease-out),
              background-color var(--dur-fast) ease,
              box-shadow var(--dur-fast) ease;
}
.btn svg { width: 1.05em; height: 1.05em; flex: none; }
.btn:active { transform: scale(0.97); }   /* el botón tiene que sentirse oído */
.btn:focus-visible { outline: 3px solid var(--accent-bright); outline-offset: 3px; }

/* CTA: tinta oscura sobre ámbar.
   Blanco sobre este naranja da 3.00:1 y REPRUEBA AA — es el bug que arrastra
   oferta.css hoy. Tinta oscura da 5.83:1 y encima se ve más caro. */
.btn-primary { background: var(--ember); color: var(--ink); }
@media (hover: hover) and (pointer: fine) {
  .btn-primary:hover { background: var(--ember-bright); }
  .btn-primary:hover svg { transform: translateX(3px); }
}
.btn-primary svg { transition: transform var(--dur-fast) var(--ease-out); }

.btn-ghost { background: transparent; color: var(--ink); box-shadow: inset 0 0 0 1px var(--line-strong); }
@media (hover: hover) and (pointer: fine) {
  .btn-ghost:hover { box-shadow: inset 0 0 0 1px var(--ink); }
}
.hero .btn-ghost, .closing .btn-ghost { color: var(--on-dark); box-shadow: inset 0 0 0 1px oklch(0.97 0.008 265 / 0.28); }
@media (hover: hover) and (pointer: fine) {
  .hero .btn-ghost:hover, .closing .btn-ghost:hover { box-shadow: inset 0 0 0 1px var(--on-dark); }
}
.btn-lg { min-height: 56px; padding: 1rem 1.8rem; font-size: var(--text-lg); }
.btn-block { display: flex; width: 100%; }

/* Ghost dentro del header: el .btn-ghost base usa --ink (tinta oscura) porque
   nace pensado para las secciones claras. Sobre el campo navy del header sería
   ilegible, así que hereda el mismo tratamiento que .hero .btn-ghost. */
.site-header .btn-ghost { color: var(--on-dark); box-shadow: inset 0 0 0 1px oklch(0.97 0.008 265 / 0.28); }
@media (hover: hover) and (pointer: fine) {
  .site-header .btn-ghost:hover { box-shadow: inset 0 0 0 1px var(--on-dark); }
}

/* Botón "Agendar demo" del header. Algo más estrecho que un .btn normal para no
   empujar al CTA primario; bajo 640px se queda en icono, que es justo donde el
   selector de idioma desaparece y libera el sitio. El aria-label (traducido con
   data-i18n-aria) sigue nombrando el botón cuando el texto no se ve. */
.btn-demo { padding-inline: 1.05rem; }
@media (max-width: 640px) {
  .btn-demo { padding-inline: 0.8rem; }
  .btn-demo .btn-demo-txt { display: none; }
  /* Con el botón de agendar al lado, el CTA se quedaba sin ancho y "Prueba
     gratis" partía en dos líneas: el header doblaba de alto y tapaba el hero.
     ("Teste grátis" sí cabía, así que solo se veía en español.) El nowrap más
     el gap corto lo mantienen en una línea a 375px. */
  .site-header .btn-primary { white-space: nowrap; padding-inline: 0.95rem; }
  .site-header .nav { gap: var(--space-sm); }
}

/* ---------- Header ---------- */
.site-header {
  position: fixed; inset: 0 0 auto; z-index: 50;
  padding-block: var(--space-md);
  transition: background-color var(--dur-mid) ease, box-shadow var(--dur-mid) ease;
}
/* Fondo SÓLIDO, sin backdrop-filter. Un blur en un elemento fijo a todo el
   ancho que se enciende al hacer scroll es caro y produce jank — colgó el
   renderer del navegador en la verificación, de forma reproducible. Sobre un
   campo vino sólido el desenfoque no aporta nada de todos modos. */
.site-header.scrolled {
  background: var(--navy-950);
  box-shadow: 0 1px 0 oklch(0.97 0.008 265 / 0.12);
}
.nav { display: flex; align-items: center; justify-content: space-between; gap: var(--space-md); }
.brand {
  display: inline-flex; align-items: center; gap: 0.5rem;
  font-family: var(--font-display); font-weight: 800;
  font-size: 1.16rem; letter-spacing: -0.02em; color: var(--on-dark); text-decoration: none;
}
/* Logotipo oficial completo (isotipo + marca denominativa + descriptor).
   Antes aquí había el isotipo suelto y la palabra "Soul Voice" compuesta en
   Nunito: parecido, pero NO es el logo — la marca tiene su propia tipografía y
   la V en naranja. En este tema el header se queda en navy al hacer scroll, así
   que basta la variante clara. */
.brand-logo { height: 40px; width: auto; display: block; flex: none; }
.site-footer .brand-logo { height: 34px; }
@media (max-width: 640px) { .brand-logo { height: 32px; } }
.brand .dot { width: 0.6rem; height: 0.6rem; border-radius: 50%; background: var(--ember); flex: none; }
.nav-live {
  display: none; align-items: center; gap: 0.5rem;
  font-size: var(--text-xs); font-weight: 600; letter-spacing: 0.06em;
  color: var(--on-dark-soft);
}
@media (min-width: 900px) { .nav-live { display: inline-flex; } }
.wave { display: inline-flex; align-items: flex-end; gap: 2px; height: 0.85rem; }
.wave span {
  width: 2px; background: var(--accent-bright); border-radius: 1px;
  animation: wv 1.1s var(--ease-in-out) infinite;
}
.wave span:nth-child(1) { height: 40%; animation-delay: 0ms; }
.wave span:nth-child(2) { height: 75%; animation-delay: 110ms; }
.wave span:nth-child(3) { height: 100%; animation-delay: 220ms; }
.wave span:nth-child(4) { height: 65%; animation-delay: 330ms; }
.wave span:nth-child(5) { height: 35%; animation-delay: 440ms; }
@keyframes wv { 0%, 100% { transform: scaleY(0.45); } 50% { transform: scaleY(1); } }

/* ---------- Hero ---------- */
.hero {
  position: relative;
  isolation: isolate;
  background: var(--navy-950);
  color: var(--on-dark);
  padding-block: clamp(6.5rem, 5rem + 9vw, 9.5rem) clamp(5rem, 3rem + 8vw, 8rem);
  overflow: hidden;
}

/* ---------- Hero cinematográfico full-bleed (día 76) ----------
   Sube el hero de campaña al estándar /us: video navy a sangre DETRÁS del
   contenido, con velo para legibilidad. El video es ATMÓSFERA — no reemplaza la
   isla de conversión: el copy va a la izquierda y el formulario blanco a la
   derecha, ambos sobre el velo. Poster webp para pintar el LCP al instante; el
   mp4 entra después (preload metadata). En reduced-motion se congela en el
   poster. Capas: media(-3) < velo(-2) < halos ::before(0) < contenido(1). */
.hero__media { position: absolute; inset: 0; z-index: -3; overflow: hidden; background: var(--navy-950); }
.hero__media video, .hero__media img {
  width: 100%; height: 100%; object-fit: cover; object-position: 78% center;
  opacity: 1;
  /* Sin mix-blend luminosity: las imágenes DX YA son navy/naranja; el blend
     mataba el naranja de la data-viz. El velo (.hero__scrim) da la legibilidad. */
}
/* Velo direccional: OSCURO a la izquierda (donde va el copy, legibilidad) y se
   ABRE hacia la derecha para que la persona y el video se vean. El formulario es
   opaco, así que tapa su zona; la persona respira en el hueco copy↔form y al
   borde derecho. Ajustado d76 tras el pedido de Leonardo ("que se vea más"). */
.hero__scrim {
  position: absolute; inset: 0; z-index: -2; pointer-events: none;
  background:
    linear-gradient(100deg,
      var(--navy-950) 2%,
      oklch(0.16 0.03 265 / 0.82) 28%,
      oklch(0.16 0.03 265 / 0.34) 52%,
      oklch(0.16 0.03 265 / 0.08) 76%,
      oklch(0.16 0.03 265 / 0) 100%),
    linear-gradient(to top, var(--navy-950) 1%, transparent 40%);
}
@media (max-width: 980px) {
  .hero__media video, .hero__media img { object-position: 70% center; }
  /* Móvil: el form va bajo el copy, así que el velo cubre casi todo para que
     ambos sean legibles sobre el video. */
  .hero__scrim {
    background: linear-gradient(to top,
      var(--navy-950) 34%,
      oklch(0.16 0.03 265 / 0.74) 64%,
      oklch(0.16 0.03 265 / 0.52) 100%);
  }
}
@media (prefers-reduced-motion: reduce) {
  .hero__media video { display: none; }  /* cae al poster (img de fallback) */
}
/* Atmósfera: DOS halos radiales suaves. No partículas, no nodos, no ruido. */
.hero::before {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(70rem 40rem at 78% 8%,  oklch(0.62 0.15 45 / 0.10), transparent 62%),
    radial-gradient(48rem 34rem at 8% 92%, oklch(0.50 0.12 262 / 0.55), transparent 66%);
}
.hero > .wrap { position: relative; z-index: 1; }
.hero-grid { display: grid; gap: clamp(2.5rem, 2rem + 3vw, 4rem); align-items: center; }
@media (min-width: 980px) { .hero-grid { grid-template-columns: 1.02fr 0.98fr; } }

.hero h1 { font-size: var(--text-hero); margin-top: var(--space-lg); color: var(--on-dark); }
.hero .lead {
  font-size: var(--text-lg); color: var(--on-dark-soft);
  max-width: 46ch; margin-top: var(--space-lg);
  line-height: 1.72;   /* texto claro sobre oscuro pesa menos: +0.07 */
}
.hero .lead b { color: var(--on-dark); font-weight: 600; }
.hero-cta { display: flex; flex-wrap: wrap; gap: var(--space-sm); margin-top: var(--space-xl); }
.hero-trust { display: flex; flex-wrap: wrap; gap: var(--space-sm) var(--space-lg); margin-top: var(--space-xl); }
.hero-trust li {
  display: inline-flex; align-items: center; gap: 0.45rem;
  font-size: var(--text-sm); color: var(--on-dark-soft);
}
.hero-trust svg { width: 1rem; height: 1rem; color: var(--accent-bright); flex: none; }

/* ---------- RESPALDO GROUPCOS (día 102) ----------
   Chip de confianza dura bajo el titular, subido desde #confianza. Va sobre el
   hero oscuro: texto claro (--on-dark-soft), ícono en acento y un velo de vidrio
   sobre el navy para separarlo del video sin robarle peso al titular ni al CTA.
   El escudo es el mismo lenguaje visual que la barra de confianza de más abajo. */
.hero-backed {
  display: inline-flex; align-items: flex-start; gap: 0.55rem;
  margin-top: var(--space-lg);
  padding: 0.6rem 0.95rem;
  border: 1px solid color-mix(in oklch, var(--on-dark) 20%, transparent);
  border-radius: var(--radius);
  background: color-mix(in oklch, var(--navy-950) 45%, transparent);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  font-size: var(--text-sm); color: var(--on-dark-soft); line-height: 1.5;
  max-width: 50ch;
}
.hero-backed__ico { width: 1.15rem; height: 1.15rem; color: var(--accent-bright); flex: none; margin-top: 0.05rem; }
.hero-backed b { color: var(--on-dark); font-weight: 700; }

/* ---------- ISLA DE CONVERSIÓN ----------
   La regla #1 del consejo, unánime en los 4 modelos: el hero puede ser oscuro,
   pero el formulario va SIEMPRE sobre superficie blanca. Además es justo el
   contraste que hace el deck: tarjeta blanca sobre campo oscuro. */
.form-card {
  background: var(--paper);
  /* La isla es dueña de SU color de texto. Sin esto hereda el `color` claro de
     .hero/.closing y pinta texto casi-blanco sobre fondo blanco (~1:1): el
     kicker y el titular del mensaje de éxito quedan invisibles. Es el borde
     entre el campo oscuro y la superficie clara — aquí se corta la herencia. */
  color: var(--ink);
  border-radius: var(--radius);
  box-shadow: 0 30px 70px -20px oklch(0.16 0.03 265 / 0.55), 0 2px 6px oklch(0.16 0.03 265 / 0.18);
  overflow: hidden;
}
.form-card__head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-sm);
  padding: 0.8rem var(--space-lg);
  background: var(--navy-800); color: var(--on-dark);
}
.form-card__head .title {
  display: inline-flex; align-items: center; gap: 0.45rem;
  font-family: var(--font-display); font-weight: 700; font-size: var(--text-sm);
   letter-spacing: 0.01em;
}
.form-card__head .title svg { width: 1rem; height: 1rem; }
.badge-live { display: inline-flex; align-items: center; gap: 0.4rem; font-size: var(--text-xs); font-weight: 600; color: oklch(0.97 0.008 265 / 0.85); }
.badge-live .dot { width: 0.45rem; height: 0.45rem; border-radius: 50%; background: var(--ember); animation: pulse 2.2s ease-in-out infinite; }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
.form-card__body { padding: var(--space-lg); }
.closing .form-card { max-width: 34rem; margin-inline: auto; text-align: left; }

.kicker { font-family: var(--font-display); font-weight: 700; font-size: var(--text-lg);  letter-spacing: -0.01em; }
.sub { font-size: var(--text-sm); color: var(--ink-soft); margin-top: var(--space-2xs); }
.form-fields { display: grid; gap: var(--space-sm); }
.kicker + .sub { margin-bottom: var(--space-xs); }

/* Honeypot: fuera de vista y fuera del tab, pero NO display:none (varios bots
   ignoran los campos ocultos con display:none). */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* Campos con label flotante */
.field { position: relative; }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-sm); }
.field input, .field select {
  width: 100%; min-height: 52px;
  padding: 1.35rem 0.9rem 0.5rem;
  font-family: var(--font-body); font-size: var(--text-base); color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  transition: border-color var(--dur-fast) ease, box-shadow var(--dur-fast) ease;
  appearance: none;
}
.field select { cursor: pointer; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23735' stroke-width='2.4' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 0.8rem center; background-size: 1rem; }
.field input::placeholder { color: transparent; }
.field label {
  position: absolute; left: 0.9rem; top: 0.95rem;
  font-size: var(--text-base); color: var(--ink-faint);
  pointer-events: none;
  transition: transform var(--dur-fast) var(--ease-out), color var(--dur-fast) ease;
  transform-origin: left top;
}
.field input:focus + label,
.field input:not(:placeholder-shown) + label,
.field select:focus + label,
.field select:valid + label { transform: translateY(-0.62rem) scale(0.76); color: var(--accent-ink); }
.field input:focus, .field select:focus {
  outline: none; border-color: var(--accent-ink);
  box-shadow: 0 0 0 3px oklch(0.685 0.16 45 / 0.22);
}
.field.valid input { border-color: oklch(0.58 0.13 155); }
.field.invalid input, .field.invalid select { border-color: var(--accent-ink); }
.ok-check {
  position: absolute; right: 0.85rem; top: 50%; width: 1.05rem; height: 1.05rem;
  color: oklch(0.58 0.13 155);
  opacity: 0; transform: translateY(-50%) scale(0.9);
  transition: opacity var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
  pointer-events: none;
}
.field.valid .ok-check { opacity: 1; transform: translateY(-50%) scale(1); }
.field-row .ok-check, .field select ~ .ok-check { display: none; }
.err {
  font-size: var(--text-xs); color: var(--accent-ink); font-weight: 600;
  margin-top: var(--space-2xs);
  display: none;
}
.field.invalid .err { display: block; }

.consent { display: flex; gap: 0.6rem; align-items: flex-start; font-size: var(--text-xs); color: var(--ink-soft); line-height: 1.5; margin-top: var(--space-2xs); cursor: pointer; }
.consent input { width: 1.05rem; height: 1.05rem; margin-top: 0.15rem; accent-color: var(--accent-ink); flex: none; cursor: pointer; }
.consent a { color: var(--accent-ink); font-weight: 600; }
.form-note { font-size: var(--text-xs); color: var(--ink-faint); text-align: center; }

/* Éxito del formulario */
.lead-form { position: relative; }
.lead-form.is-submitted .form-fields { display: none; }
.form-success { display: none; text-align: center; padding: var(--space-lg) 0; }
.form-success.show { display: block; animation: rise var(--dur-mid) var(--ease-out) both; }
@keyframes rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
.form-success .ring {
  width: 3.6rem; height: 3.6rem; margin: 0 auto var(--space-md);
  display: grid; place-items: center; border-radius: 50%;
  background: var(--navy-800); color: var(--on-dark);
}
.form-success h3 { font-size: var(--text-xl); }
.form-success p { color: var(--ink-soft); font-size: var(--text-sm); margin-top: var(--space-xs); }

/* ---------- Stat tiles ----------
   Tarjetas blancas que MONTAN sobre el borde del hero: profundidad por
   solapamiento, no por glassmorphism. Del deck.
   Los números son HECHOS VERIFICABLES del producto, no métricas de vanidad:
   no hay 6.000 colaboradores que presumir y no se inventan. */
/* Cuánto MONTAN las stat tiles sobre el borde del hero. Es un token y no un
   número suelto porque el hero tiene que reservarle ese espacio abajo: si no,
   las tarjetas blancas le pasan por encima a la fila de confianza ("Sin
   tarjeta · Lista en minutos · Pasa a un humano"). Pasó, se vio, se ató.
   Ver .hero--stage, que calcula su padding inferior a partir de aquí. */
:root { --stats-overlap: clamp(2.5rem, 2rem + 3vw, 4rem); }
.stats { margin-top: calc(-1 * var(--stats-overlap)); position: relative; z-index: 2; }
.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: var(--space-md); }
.stat {
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--radius); padding: var(--space-lg);
  box-shadow: 0 14px 34px -16px oklch(0.16 0.03 265 / 0.30);
}
.stat .rule { margin: 0 0 var(--space-sm); width: 2rem; height: 3px; }
.stat .n {
  font-family: var(--font-display); font-weight: 800;
  font-size: var(--text-stat); line-height: 0.95; letter-spacing: -0.03em;
  color: var(--navy-800);
}
.stat .lbl { display: block; font-size: var(--text-sm); color: var(--ink-soft); margin-top: var(--space-xs); }

/* ---------- Secciones ---------- */
.section { padding-block: var(--space-section); }
.section--tint { background: var(--surface); }
.section--dark { background: var(--navy-950); color: var(--on-dark); }
.section--dark h2 { color: var(--on-dark); }
.section--dark p { color: var(--on-dark-soft); }

.section-head { max-width: 44rem; }
.section-head.center { margin-inline: auto; text-align: center; }
.section-head h2 { font-size: var(--text-3xl); margin-top: var(--space-sm); }
.section-head > p { color: var(--ink-soft); font-size: var(--text-lg); margin-top: var(--space-md); max-width: 60ch; }
.section-head.center > p { margin-inline: auto; }
.section-head .rule { margin-bottom: var(--space-lg); }

/* ---------- WIDGET CALENDLY INLINE (#demo-agenda, día 102) ----------
   El iframe de Calendly trae su propio ancho mínimo (320px). Lo centramos y le
   ponemos un marco/sombra de tarjeta para que se lea como parte de la página y
   no como un incrustado ajeno. El fallback queda discreto y centrado debajo. */
.calendly-embed { max-width: 760px; margin-inline: auto; margin-top: var(--space-2xl); }
.calendly-embed .calendly-inline-widget {
  border-radius: var(--radius); overflow: hidden;
  box-shadow: 0 24px 60px -24px oklch(0.16 0.03 265 / 0.5);
  border: 1px solid var(--line); background: var(--paper);
}
.agenda-fallback { text-align: center; margin-top: var(--space-md); font-size: var(--text-sm); }
.agenda-fallback a { color: var(--ink-soft); text-decoration: underline; text-underline-offset: 3px; }
.agenda-fallback a:hover { color: var(--accent-ink); }

/* ---------- Calculadora ---------- */
.calc { display: grid; gap: var(--space-xl); margin-top: var(--space-2xl); align-items: start; }
@media (min-width: 900px) { .calc { grid-template-columns: 1.15fr 0.85fr; gap: var(--space-2xl); } }
.calc-controls { display: grid; gap: var(--space-xl); }
.control label { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-md); font-size: var(--text-sm); font-weight: 600; color: var(--ink); }
.control .val { font-family: var(--font-display); font-weight: 800;  font-size: var(--text-lg); color: var(--navy-800); font-variant-numeric: tabular-nums; }
.control .hint { font-size: var(--text-xs); color: var(--ink-faint); margin-top: var(--space-2xs); max-width: 54ch; }
input[type=range] {
  width: 100%; margin: var(--space-sm) 0 0; height: 22px;
  appearance: none; background: transparent; cursor: pointer;
}
input[type=range]::-webkit-slider-runnable-track { height: 5px; border-radius: 3px; background: var(--line); }
input[type=range]::-moz-range-track { height: 5px; border-radius: 3px; background: var(--line); }
input[type=range]::-webkit-slider-thumb {
  appearance: none; width: 21px; height: 21px; margin-top: -8px; border-radius: 50%;
  background: var(--navy-800); border: 3px solid var(--paper);
  box-shadow: 0 2px 8px oklch(0.16 0.03 265 / 0.35);
  transition: transform var(--dur-press) var(--ease-out);
}
input[type=range]::-moz-range-thumb {
  width: 15px; height: 15px; border-radius: 50%;
  background: var(--navy-800); border: 3px solid var(--paper);
}
input[type=range]:active::-webkit-slider-thumb { transform: scale(1.15); }
input[type=range]:focus-visible { outline: 3px solid var(--accent-bright); outline-offset: 4px; border-radius: 4px; }

.calc-result {
  background: var(--navy-950); color: var(--on-dark);
  border-radius: var(--radius); padding: var(--space-xl);
  position: relative; overflow: hidden;
}
.calc-result::before {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(30rem 18rem at 85% 0%, oklch(0.62 0.15 45 / 0.10), transparent 68%);
}
.calc-result > * { position: relative; }
.calc-result .tag { font-size: var(--text-xs); font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--accent-bright); }
.calc-result .money {
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(2.3rem, 1.8rem + 2.4vw, 3.5rem); line-height: 1; letter-spacing: -0.035em;
  margin-top: var(--space-sm); font-variant-numeric: tabular-nums; color: var(--on-dark);
}
.calc-result .per { font-size: var(--text-sm); color: var(--on-dark-faint); }
.calc-result .year { font-size: var(--text-sm); color: var(--on-dark-soft); margin-top: var(--space-md); padding-top: var(--space-md); border-top: 1px solid oklch(0.97 0.008 265 / 0.14); }
.calc-result .year b { color: var(--on-dark); font-variant-numeric: tabular-nums; }
.calc-result .recover { display: flex; gap: 0.5rem; align-items: flex-start; font-size: var(--text-sm); color: var(--on-dark-soft); margin-top: var(--space-md); }
.calc-result .recover svg { color: var(--accent-bright); flex: none; margin-top: 0.15rem; }
.calc-cta { margin-top: var(--space-lg); }

/* ---------- Pasos ---------- */
.steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: var(--space-lg); margin-top: var(--space-2xl); }
.step { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius); padding: var(--space-xl); counter-increment: step; }
.step .n {
  font-family: var(--font-display); font-weight: 800;
  font-size: var(--text-xl); color: var(--navy-800); line-height: 1;
}
.step .n::before { content: '0' counter(step); }
.step h3 { font-size: var(--text-xl); margin-top: var(--space-sm); }
.step p { color: var(--ink-soft); font-size: var(--text-sm); margin-top: var(--space-sm); }
.steps { counter-reset: step; }

/* ---------- Demo de llamada ---------- */
.demo-panel { display: grid; gap: var(--space-xl); margin-top: var(--space-2xl); align-items: center; }
@media (min-width: 900px) { .demo-panel { grid-template-columns: 0.9fr 1.1fr; gap: var(--space-2xl); } }
.phone { background: var(--paper); border-radius: var(--radius); overflow: hidden; box-shadow: 0 24px 60px -24px oklch(0.16 0.03 265 / 0.5); }
.phone__top { display: flex; align-items: center; justify-content: space-between; padding: 0.7rem var(--space-md); background: var(--navy-900); color: var(--on-dark); }
.phone__top .who { display: inline-flex; align-items: center; gap: 0.5rem; font-size: var(--text-sm); font-weight: 600; }
.phone__top .av { width: 1.6rem; height: 1.6rem; border-radius: 50%; background: var(--ember); color: var(--ink); display: grid; place-items: center; font-size: 0.6rem; font-weight: 800; font-family: var(--font-display); }
.chat { padding: var(--space-md); min-height: 21rem; max-height: 21rem; overflow-y: auto; display: flex; flex-direction: column; gap: var(--space-sm); background: var(--surface-sunk); }
.bubble {
  max-width: 82%; padding: 0.6rem 0.85rem; border-radius: 12px; font-size: var(--text-sm); line-height: 1.5;
  opacity: 0; transform: translateY(6px) scale(0.98);
  transition: opacity var(--dur-mid) var(--ease-out), transform var(--dur-mid) var(--ease-out);
}
.bubble.show { opacity: 1; transform: none; }
.bubble .lbl { display: block; font-size: 0.62rem; font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase; opacity: 0.62; margin-bottom: 0.15rem; }
.bubble.user { align-self: flex-start; background: var(--paper); border: 1px solid var(--line); color: var(--ink); border-bottom-left-radius: 4px; }
.bubble.ai { align-self: flex-end; background: var(--navy-800); color: var(--on-dark); border-bottom-right-radius: 4px; }
.typing { align-self: flex-end; display: inline-flex; gap: 3px; padding: 0.7rem 0.85rem; background: var(--navy-800); border-radius: 12px; border-bottom-right-radius: 4px; }
.typing span { width: 5px; height: 5px; border-radius: 50%; background: oklch(0.97 0.008 265 / 0.75); animation: blink 1.2s ease-in-out infinite; }
.typing span:nth-child(2) { animation-delay: 160ms; }
.typing span:nth-child(3) { animation-delay: 320ms; }
@keyframes blink { 0%, 100% { opacity: 0.3; transform: translateY(0); } 50% { opacity: 1; transform: translateY(-2px); } }
.demo-copy h2 { font-size: var(--text-2xl); }
.demo-copy ul { display: grid; gap: var(--space-sm); margin: var(--space-lg) 0; }
.demo-copy li { display: flex; gap: 0.6rem; align-items: flex-start; font-size: var(--text-base); color: var(--ink-soft); }
.demo-copy li svg { width: 1.1rem; height: 1.1rem; color: var(--accent-ink); flex: none; margin-top: 0.32rem; }

/* ---------- Beneficios (bento, no rejilla uniforme) ---------- */
.benefits { display: grid; gap: var(--space-md); margin-top: var(--space-2xl); grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); }
@media (min-width: 900px) { .benefits { grid-template-columns: repeat(3, 1fr); } .benefit--feature { grid-column: span 2; } }
.benefit { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius); padding: var(--space-xl); }
.benefit--feature { background: var(--navy-950); color: var(--on-dark); border-color: transparent; display: flex; flex-direction: column; justify-content: space-between; gap: var(--space-xl); position: relative; overflow: hidden; }
.benefit--feature::before { content: ''; position: absolute; inset: 0; background: radial-gradient(28rem 16rem at 92% 6%, oklch(0.62 0.15 45 / 0.10), transparent 66%); pointer-events: none; }
.benefit--feature > * { position: relative; }
.benefit--feature h3 { color: var(--on-dark); }
.benefit--feature p { color: var(--on-dark-soft); }
.benefit h3 { font-size: var(--text-lg); margin-top: var(--space-sm); }
.benefit p { color: var(--ink-soft); font-size: var(--text-sm); margin-top: var(--space-xs); }
.benefit .ico { color: var(--accent-ink); }
.benefit--feature .ico { color: var(--accent-bright); }
.benefit .big {
  font-family: var(--font-display); font-weight: 800;
  font-size: var(--text-2xl); letter-spacing: -0.03em; line-height: 1; color: var(--accent-bright);
}

/* ---------- Confianza ---------- */
.pioneras { display: grid; gap: var(--space-2xl); align-items: center; }
@media (min-width: 900px) { .pioneras { grid-template-columns: 1fr 1fr; } }
.pioneras-copy h2 { font-size: var(--text-3xl); margin-top: var(--space-sm); }
.pioneras-card { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius); padding: var(--space-xl); }
.proof { padding-bottom: var(--space-lg); border-bottom: 1px solid var(--line); }
.proof-lbl { font-size: var(--text-xs); font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--accent-ink); }
.proof-txt { font-size: var(--text-base); color: var(--ink-soft); margin-top: var(--space-sm); }
.proof-txt b { color: var(--ink); font-weight: 700; }
.assurances { display: grid; gap: var(--space-md); margin-top: var(--space-lg); }
.assurance { display: flex; gap: var(--space-sm); align-items: flex-start; }
.assurance svg { width: 1.2rem; height: 1.2rem; color: var(--accent-ink); flex: none; margin-top: 0.2rem; }
.assurance b { display: block; font-size: var(--text-sm); font-weight: 700; }
.assurance span { display: block; font-size: var(--text-xs); color: var(--ink-soft); margin-top: 0.1rem; line-height: 1.5; }

/* ---------- Precio ---------- */
.precio-card { display: grid; gap: var(--space-xl); margin-top: var(--space-2xl); background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius); padding: clamp(1.5rem, 1rem + 2vw, 2.5rem); }
@media (min-width: 800px) { .precio-card { grid-template-columns: 1fr 1fr; align-items: center; gap: var(--space-2xl); } }
.precio-lbl { font-size: var(--text-xs); font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--accent-ink); }
.precio-num { font-family: var(--font-display); font-weight: 800; font-size: var(--text-3xl); letter-spacing: -0.035em; line-height: 1; margin-top: var(--space-sm); color: var(--ink); }
.precio-num small { font-family: var(--font-body); font-size: var(--text-base); font-weight: 500; color: var(--ink-soft); letter-spacing: 0; }
.precio-nota { font-size: var(--text-sm); color: var(--ink-soft); margin-top: var(--space-md); max-width: 46ch; }
.precio-lista { display: grid; gap: var(--space-sm); }
.precio-lista li { display: flex; gap: 0.6rem; font-size: var(--text-sm); color: var(--ink-soft); }
.precio-lista li::before { content: ''; width: 1.25rem; height: 1.25rem; flex: none; margin-top: 0.15rem; background: var(--navy-800); border-radius: 50%; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center/0.8rem no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center/0.8rem no-repeat; }

/* ---------- FAQ ---------- */
.faq { margin-top: var(--space-2xl); border-top: 1px solid var(--line); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-md);
  padding: var(--space-lg) 0; cursor: pointer; list-style: none;
  font-family: var(--font-display); font-weight: 700;
  font-size: var(--text-lg); letter-spacing: -0.012em;
  transition: color var(--dur-fast) ease;
}
.faq summary::-webkit-details-marker { display: none; }
@media (hover: hover) and (pointer: fine) { .faq summary:hover { color: var(--accent-ink); } }
.faq summary:focus-visible { outline: 3px solid var(--accent-bright); outline-offset: 2px; }
.faq .chev { width: 1.1rem; height: 1.1rem; flex: none; color: var(--accent-ink); transition: transform var(--dur-fast) var(--ease-out); }
.faq details[open] .chev { transform: rotate(180deg); }
.faq .ans { padding-bottom: var(--space-lg); color: var(--ink-soft); font-size: var(--text-base); max-width: 68ch; }

/* ---------- Cierre ---------- */
.closing { background: var(--navy-950); color: var(--on-dark); text-align: center; position: relative; overflow: hidden; }
.closing::before { content: ''; position: absolute; inset: 0; pointer-events: none; background: radial-gradient(56rem 30rem at 50% 0%, oklch(0.62 0.15 45 / 0.10), transparent 65%); }
.closing > .wrap { position: relative; }
.closing h2 { font-size: var(--text-3xl); margin-top: var(--space-md); color: var(--on-dark); max-width: 20ch; margin-inline: auto; }
.closing .lead { color: var(--on-dark-soft); font-size: var(--text-lg); margin-top: var(--space-md); }
.closing .form-card { margin-top: var(--space-2xl); }

/* ---------- Footer ---------- */
.site-footer { background: var(--navy-950); color: var(--on-dark-faint); padding-block: var(--space-2xl); border-top: 1px solid oklch(0.97 0.008 265 / 0.10); }
.site-footer .wrap { display: grid; gap: var(--space-lg); }
@media (min-width: 760px) { .site-footer .wrap { grid-template-columns: auto 1fr; align-items: center; } .site-footer .fine { grid-column: 1 / -1; } }
.site-footer nav { display: flex; flex-wrap: wrap; gap: var(--space-lg); justify-content: flex-start; }
@media (min-width: 760px) { .site-footer nav { justify-content: flex-end; } }
.site-footer nav a { font-size: var(--text-sm); color: var(--on-dark-soft); text-decoration: none; transition: color var(--dur-fast) ease; }
@media (hover: hover) and (pointer: fine) { .site-footer nav a:hover { color: var(--on-dark); } }
.site-footer .fine { font-size: var(--text-xs); color: var(--on-dark-faint); line-height: 1.6; padding-top: var(--space-lg); border-top: 1px solid oklch(0.97 0.008 265 / 0.10); max-width: 76ch; }

/* ---------- CTA móvil ---------- */
.mobile-cta {
  position: fixed; inset: auto 0 0; z-index: 40;
  padding: var(--space-sm) var(--space-md) calc(var(--space-sm) + env(safe-area-inset-bottom));
  background: var(--navy-950);   /* sólido: ver la nota de .site-header.scrolled */
  box-shadow: 0 -1px 0 oklch(0.97 0.008 265 / 0.12);
  transform: translateY(110%);
  transition: transform var(--dur-mid) var(--ease-out);
}
.mobile-cta.show { transform: none; }
@media (min-width: 900px) { .mobile-cta { display: none; } }

/* ---------- Reveal ---------- */
.js .reveal { opacity: 0; transform: translateY(14px); }
.js .reveal.is-visible {
  opacity: 1; transform: none;
  transition: opacity 620ms var(--ease-out), transform 620ms var(--ease-out);
}
.js .reveal[data-delay="1"].is-visible { transition-delay: 60ms; }
.js .reveal[data-delay="2"].is-visible { transition-delay: 120ms; }
.js .reveal[data-delay="3"].is-visible { transition-delay: 180ms; }

/* ---------- Reduced motion ----------
   Menos movimiento, no cero: se conservan opacidad/color, se quita el
   desplazamiento y la animación decorativa en bucle. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .js .reveal { opacity: 1; transform: none; }
  .mobile-cta { transition: none; }
}

/* ==========================================================================
   Clases que solo usa /oferta
   --------------------------------------------------------------------------
   /oferta pasó a esta hoja el día 73 (antes tenía oferta.css, el tema teal).
   Estas 6 clases existen solo en su HTML, así que había que vestirlas o
   saldrían sin estilo: el selector de idioma y la barra de confianza son las
   que se verían rotas. Portadas de oferta.css con los tokens navy.
   ========================================================================== */

/* ---------- Selector de idioma (es/en/pt) ----------
   Lo llena y cablea oferta-i18n.js. Nace con [hidden]: si el JS no carga, no
   aparece y la página se queda en español, que es lo correcto. */
.lang-switch {
  display: flex; gap: 2px; padding: 2px;
  border: 1px solid var(--line); border-radius: 999px;
  background: var(--surface);
}
.lang-switch[hidden] { display: none; }
.lang-btn {
  border: 0; background: transparent; color: var(--ink-faint);
  font-family: inherit; font-size: 0.7rem; font-weight: 700; letter-spacing: 0.04em;
  padding: 0.3rem 0.55rem; border-radius: 999px; cursor: pointer;
  transition: color var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out);
}
.lang-btn:hover { color: var(--ink); }
.lang-btn.is-on { background: var(--paper); color: var(--ink); box-shadow: 0 1px 3px oklch(0.16 0.03 265 / 0.18); }
.lang-btn:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 2px; }
/* En el header oscuro el selector invierte: si no, es una pastilla blanca flotando. */
.site-header .lang-switch { border-color: oklch(0.97 0.008 265 / 0.22); background: oklch(0.97 0.008 265 / 0.06); }
.site-header .lang-btn { color: var(--on-dark-soft); }
.site-header .lang-btn:hover { color: var(--on-dark); }
.site-header .lang-btn.is-on { background: oklch(0.97 0.008 265 / 0.16); color: var(--on-dark); box-shadow: none; }
@media (max-width: 640px) { .lang-switch { display: none; } }

/* ---------- Barra de confianza ----------
   Va bajo el hero. El check usa --accent-ink (naranja quemado): sobre la
   superficie clara el naranja vivo reprobaría contraste. */
.trustbar { border-block: 1px solid var(--line); background: var(--surface); }
.trustbar ul {
  list-style: none; display: flex; flex-wrap: wrap; justify-content: center;
  gap: var(--space-md) var(--space-2xl); padding: var(--space-lg) 0;
}
.trustbar li {
  display: flex; align-items: center; gap: 0.6ch;
  font-size: var(--text-sm); font-weight: 600; color: var(--ink-soft);
}
.trustbar svg { width: 1.15em; height: 1.15em; color: var(--accent-ink); flex: none; }

/* ---------- Variantes de beneficio ----------
   En /empresas los beneficios se distinguen por posición en el bento; en
   /oferta van con modificador. Sin regla propia heredan .benefit y ya: el
   layout no depende de ellas, así que no se inventa nada aquí. */
.benefit--a, .benefit--b, .benefit--c, .benefit--d { /* heredan .benefit */ }

/* La tarjeta destacada es OSCURA (--navy-950), pero su texto secundario heredaba
   --ink-soft, que es el gris pensado para fondo claro: daba 2.72:1 y reprobaba
   AA. Sobre oscuro el equivalente es --on-dark-soft. */
.benefit--feature p,
.benefit--feature .ben-p,
.benefit--feature li { color: var(--on-dark-soft); }
.benefit--feature .eyebrow { color: var(--accent-bright); }

/* ==========================================================================
   Bandas de imagen (día 73)
   --------------------------------------------------------------------------
   Leonardo pidió imágenes que den confianza. Van a sangre, a lo ancho, con
   la persona real colombiana que aprobó. La foto CARGA información (el rol y
   los canales), no decora — que es lo único que la evidencia respalda.
   ========================================================================== */

/* Banda 1: la persona + paneles de conversación (el tema omnicanal, dibujado) */
.band-omni {
  position: relative; overflow: hidden; isolation: isolate;
  min-height: clamp(22rem, 30vw, 34rem);
  display: grid; align-items: center;
  background: var(--navy-950);
}
.band-omni__img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: center right; z-index: -2;
}
.band-omni__veil {
  position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(90deg, var(--navy-950) 18%, rgba(11,18,32,.82) 44%, rgba(11,18,32,.25) 78%);
}
.band-omni .wrap { width: 100%; }
.band-omni__copy { max-width: 34rem; color: var(--on-dark); }
.band-omni__copy h2 { color: var(--on-dark); margin-bottom: var(--space-md); }
.band-omni__copy p { color: var(--on-dark-soft); font-size: var(--text-lg); }
.band-omni .eyebrow { color: var(--accent-bright); }  /* banda oscura → naranja vivo, no el quemado de fondo claro */

/* Paneles de conversación en CÓDIGO (traducibles, nítidos, accesibles) */
.omni-chips { display: flex; flex-wrap: wrap; gap: var(--space-sm); margin-top: var(--space-lg); }
.omni-chip {
  display: inline-flex; align-items: center; gap: 0.5ch;
  background: rgba(9,14,26,.72); backdrop-filter: blur(8px);
  border: 1px solid var(--navy-800); border-radius: 999px;
  padding: 0.5rem 0.9rem; font-size: var(--text-sm); font-weight: 600; color: var(--on-dark);
}
.omni-chip svg { width: 1.05em; height: 1.05em; flex: none; }
.omni-chip--wa svg { color: #25d366; }
.omni-chip--voz svg { color: var(--accent-bright); }

/* Banda 2: la doble exposición que pidió Leonardo. Navy, no vino.
   Va abajo, lejos del hero, que es donde menos choca con la foto real. */
.band-dx {
  position: relative; overflow: hidden;
  min-height: clamp(16rem, 22vw, 24rem);
  display: grid; align-items: center;
  background: var(--navy-950);
}
.band-dx__img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: center; z-index: -2; opacity: .9;
}
.band-dx__veil {
  position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(90deg, var(--navy-950) 22%, rgba(11,18,32,.55) 62%, transparent 100%);
}
.band-dx__copy { max-width: 32rem; color: var(--on-dark); }
.band-dx__copy h2 { color: var(--on-dark); font-size: var(--text-2xl); }
.band-dx__copy p { color: var(--on-dark-soft); margin-top: var(--space-sm); }

/* Botones de prueba en vivo (voz/video). Abren los widgets reales de prod. */
/* .demo-live se eliminó el día 77: era el grupito de botones de texto que abría
   los widgets de voz/video al final de la columna de la demo. Lo reemplazan las
   tarjetas .demo-card, que muestran los dos widgets con su maqueta. Ya no lo usa
   ningún HTML — se borra en vez de quedarse como CSS muerto. */

/* ==========================================================================
   Bandas cinematográficas premium (día 76 · nivel Soul 360)
   --------------------------------------------------------------------------
   Imagen/video de doble-exposición a sangre + velo direccional para legibilidad
   + HALO NARANJA QUE RESPIRA (efecto "con vida" recomendado por el consejo:
   0% CPU, puro CSS, respeta reduced-motion). El sujeto va a la derecha, el copy
   a la izquierda sobre el velo. Reutilizable en todas las bandas nuevas.
   ========================================================================== */
.band-cine {
  position: relative; overflow: hidden; isolation: isolate;
  min-height: clamp(23rem, 32vw, 38rem);
  display: grid; align-items: center;
  background: var(--navy-950);
  padding-block: var(--space-2xl);
}
.band-cine__media { position: absolute; inset: 0; z-index: -3; }
.band-cine__media img, .band-cine__media video {
  width: 100%; height: 100%; object-fit: cover; object-position: 72% center;
}
.band-cine__veil {
  position: absolute; inset: 0; z-index: -2; pointer-events: none;
  background: linear-gradient(94deg,
    var(--navy-950) 16%,
    oklch(0.16 0.03 265 / 0.80) 42%,
    oklch(0.16 0.03 265 / 0.28) 74%,
    oklch(0.16 0.03 265 / 0) 100%);
}
.band-cine__halo {
  position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: radial-gradient(42rem 26rem at 60% 40%, oklch(0.64 0.16 45 / 0.20), transparent 64%);
  animation: haloBreath 7.5s var(--ease-in-out) infinite;
}
@keyframes haloBreath { 0%, 100% { opacity: 0.5; transform: scale(1); } 50% { opacity: 1; transform: scale(1.05); } }
.band-cine .wrap { width: 100%; position: relative; }
.band-cine__copy { max-width: 40rem; color: var(--on-dark); }
.band-cine__copy .eyebrow { color: var(--accent-bright); }
.band-cine__copy h2 { color: var(--on-dark); font-size: var(--text-3xl); margin-top: var(--space-sm); }
.band-cine__copy .rule { background: var(--accent-bright); }
.band-cine__copy p { color: var(--on-dark-soft); font-size: var(--text-lg); margin-top: var(--space-md); max-width: 46ch; }
.band-cine__copy .band-cta { margin-top: var(--space-lg); }
@media (max-width: 720px) {
  .band-cine__media img, .band-cine__media video { object-position: 76% center; }
  .band-cine__veil { background: linear-gradient(to top, var(--navy-950) 28%, oklch(0.16 0.03 265 / 0.72) 66%, oklch(0.16 0.03 265 / 0.5) 100%); }
}
@media (prefers-reduced-motion: reduce) { .band-cine__halo { animation: none; } }

/* Las reglas de la vieja tarjeta del mapa (.alcance, .alcance-copy, .alcance-map
   y el #alcance::before) se borraron el día 77: el mapa pasó a ser la banda a
   sangre .alcance-band, que vive más abajo en esta hoja. Ningún HTML las usa. */

/* ---------- Halos que "respiran" en las secciones oscuras (día 76) ----------
   Efecto con vida recomendado por el consejo: 0% CPU (solo opacity/scale en un
   pseudo-elemento que ya existía como halo estático). Respeta reduced-motion. */
.hero::before,
.calc-result::before,
.benefit--feature::before,
.closing::before {
  animation: haloBreath 8s var(--ease-in-out) infinite;
  will-change: opacity, transform;
}
.calc-result::before { transform-origin: 85% 0; }
.benefit--feature::before { transform-origin: 92% 6%; }
@media (prefers-reduced-motion: reduce) {
  .hero::before, .calc-result::before, .benefit--feature::before, .closing::before { animation: none; }
}

/* ==========================================================================
   DÍA 77 — Armonización con /us
   --------------------------------------------------------------------------
   Pedido de Leonardo: "/oferta y /empresas no se parecen a /us, quiero que se
   parezcan. No ocultes la cara con el formulario. El botón de hablar con la IA
   como en /us. Que se vea tanto el widget de voz como el de video."

   Tres cambios estructurales, todos copiados del patrón de /us (us.css), pero
   traducidos a los tokens navy/naranja de esta hoja — NO se importa us.css:
   esa hoja vive en el tema vino/blanco de la landing en inglés y mezclar las
   dos rompería el contraste medido.

     1. .hero-stage  — el hero deja de ser dos columnas (copy + formulario) y
        pasa a ser una sola columna sobre el video a sangre. El formulario se
        fue al cierre. Motivo: en /oferta el form tapaba a la persona entera
        (solo se veía la nuca) y exprimía el h1 a cuatro líneas.
     2. .hero-chip   — las dos fichas de datos flotantes de /us.
     3. .demo-grid   — las dos tarjetas ricas (voz / video) de /us, que hacen
        visibles los DOS widgets en vez de dos botones de texto perdidos.

   EXCEPCIÓN CONSCIENTE A LA CABECERA DE ESTA HOJA: arriba dice "NO lleva
   glassmorphism". Las .hero-chip son de vidrio. No es un descuido: es el
   elemento de /us que Leonardo aprobó explícitamente y pidió replicar. Son
   dos, llevan dato real (no adorno), y no se repite el efecto en ningún otro
   sitio de la página.
   ========================================================================== */

/* ---------- Hero de una sola columna (sin isla de conversión) ----------
   Reemplaza a .hero-grid en oferta.html y empresas.html. .hero-grid SIGUE
   definida más arriba, intacta: para revertir basta cambiar la clase en el
   HTML de vuelta y devolver el <div class="form-card"> al hero. */
.hero--stage {
  display: flex;
  align-items: center;
  min-height: min(90vh, 860px);
  /* El padding inferior NO es un valor de gusto: es el solape de las stat tiles
     más un respiro. Así la fila de confianza nunca queda debajo de las tarjetas
     blancas, a ningún ancho. */
  padding-block: clamp(6rem, 4.5rem + 4vw, 8rem) calc(var(--stats-overlap) + var(--space-xl));
}
/* Ritmo interno más apretado que el hero de dos columnas: aquí la columna es
   una sola y muy alta (nueve palabras de titular = cuatro líneas), así que cada
   hueco de más empuja el CTA fuera de la pantalla. */
.hero--stage h1 { margin-top: var(--space-md); }
.hero--stage .lead { margin-top: var(--space-md); }
.hero--stage .hero-cta { margin-top: var(--space-lg); }
.hero--stage .hero-trust { margin-top: var(--space-lg); }

/* Portátiles bajitos (1280×720 y parientes). Sin esto el hero medía 906px y la
   fila de botones quedaba PARTIDA por el pliegue — medido en vivo, no supuesto.
   Se aprieta por altura, no por ancho: en un monitor alto el hero respira. */
@media (min-width: 980px) and (max-height: 820px) {
  /* 7rem arriba, no 6: el header fijo mide 86px y con 6rem (96px) el eyebrow le
     quedaba a 14px, rozándolo. 7rem da 30px de aire y el CTA sigue sobrando
     sobre el pliegue. */
  .hero--stage { min-height: auto; padding-block: 7rem calc(var(--stats-overlap) + var(--space-2xl)); }
  .hero--stage h1 { font-size: clamp(2.6rem, 1.6rem + 3.1vw, 4rem); }
  .hero--stage .lead { font-size: var(--text-base); }
}
.hero-stage { position: relative; }
/* La medida corta es lo que hace que el titular pegue. Sin tope, el h1 cruza
   el ancho completo, se mete encima de la persona y pierde la forma de bloque
   que tiene en /us. */
.hero-stage .hero-copy { max-width: 44rem; }
/* 15ch medido, no elegido: el titular de estas dos landings son nueve palabras
   (el de /us son tres). A 13ch se parte en CINCO líneas y empuja los botones
   fuera de la pantalla en un portátil de 900px de alto — verificado en vivo.
   A 15ch son cuatro líneas, el CTA queda sobre el pliegue y el texto termina
   ~54% del ancho: pisa los monitores del fondo, nunca la cara del sujeto. */
.hero--stage h1 { max-width: 15ch; }
.hero--stage .lead { max-width: 42ch; }

/* El velo puede abrirse antes ahora que no hay formulario opaco tapando la
   mitad derecha: la persona del video es el sujeto, y taparla era justo la
   queja. Oscuro donde vive el copy, transparente donde vive la cara. */
.hero--stage .hero__scrim {
  background:
    linear-gradient(100deg,
      var(--navy-950) 2%,
      oklch(0.16 0.03 265 / 0.78) 26%,
      oklch(0.16 0.03 265 / 0.30) 48%,
      oklch(0.16 0.03 265 / 0.04) 72%,
      oklch(0.16 0.03 265 / 0) 100%),
    linear-gradient(to top, var(--navy-950) 1%, transparent 38%);
}
@media (max-width: 980px) {
  .hero--stage { min-height: auto; }
  /* Móvil: el sujeto queda detrás del texto, así que el velo sube para que el
     copy sea legible. Mismo criterio que ya usaba el hero de dos columnas. */
  .hero--stage .hero__scrim {
    background: linear-gradient(to top,
      var(--navy-950) 30%,
      oklch(0.16 0.03 265 / 0.72) 62%,
      oklch(0.16 0.03 265 / 0.48) 100%);
  }
}

/* ---------- Fichas de datos flotantes ----------
   Sobre el video, a la derecha, donde antes estaba el formulario. Llevan HECHOS
   verificables del producto (24/7 y los 6 canales), no métricas inventadas: la
   Ley 1480 art. 30 nos pone a nosotros la carga de la prueba. */
.hero-chip {
  position: absolute; z-index: 2;
  display: flex; align-items: center; gap: 0.6rem;
  padding: 0.7rem 0.95rem;
  border-radius: var(--radius);
  /* Navy translúcido SIN backdrop-filter. Dos razones, las dos aprendidas a
     golpes en esta misma hoja:
     1. Con vidrio BLANCO al 10% (que es lo que hace us.css) la ficha era
        ilegible sobre las luces de ciudad del hero de /oferta: mandaba el
        fondo y el texto claro desaparecía. Base navy = el texto siempre cae
        sobre oscuro, pase lo que pase detrás en el video.
     2. Nada de blur: la cabecera de esta hoja ya avisa que un backdrop-filter
        colgó el renderer "de forma reproducible", y volvió a colgarlo hoy al
        ponérselo a estas fichas sobre un hero con video. Con 0.72 de opacidad
        el efecto de profundidad se sostiene solo, sin desenfocar nada. */
  background: oklch(0.16 0.03 265 / 0.72);
  border: 1px solid oklch(0.97 0.008 265 / 0.20);
  box-shadow: 0 14px 34px oklch(0.16 0.03 265 / 0.5);
  color: var(--on-dark);
  font-weight: 800; font-size: var(--text-sm); line-height: 1.2;
  animation: floaty 5.5s var(--ease-in-out) infinite;
}
.hero-chip small {
  display: block; font-weight: 700; font-size: var(--text-xs);
  letter-spacing: 0.02em; color: var(--on-dark-faint);
}
.hero-chip .big { display: block; font-size: 1.15rem; line-height: 1.1; }
/* El ámbar siempre lleva tinta oscura encima — misma regla que el CTA. */
.hero-chip .ico {
  width: 30px; height: 30px; border-radius: 9px; flex: none;
  background: var(--ember); color: var(--ink);
  display: grid; place-items: center;
}
.hero-chip .ico svg { width: 1rem; height: 1rem; }
/* Ancladas al BORDE DERECHO, en diagonal. No a un punto del encuadre: las dos
   landings usan videos distintos, y una posición calculada para la cara de uno
   se le monta en la frente al otro (pasó: la ficha de 24/7 aterrizaba en el
   pelo de la agente de /oferta). El borde derecho es cielo/ciudad/ventana en
   los dos videos, así que es el único sitio estable. */
.hero-chip--a { top: 15%; right: 3.5%; }
.hero-chip--b { bottom: 17%; right: 3.5%; animation-delay: 1.2s; }
/* Contra-fase: si las dos flotaran igual parecerían un solo bloque rígido. */
.hero-chip--b { animation-direction: reverse; }
@keyframes floaty { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-9px); } }
@media (prefers-reduced-motion: reduce) { .hero-chip { animation: none; } }
/* Bajo 1100px el sujeto se recorta y las fichas caen encima de la cara o del
   copy. Se ocultan: son refuerzo, no información única (los mismos datos están
   en las stat tiles justo debajo del hero). */
@media (max-width: 1100px) { .hero-chip { display: none; } }

/* ==========================================================================
   Tarjetas de demo en vivo — voz y video (patrón /us)
   --------------------------------------------------------------------------
   Antes los dos widgets vivían como dos botones de texto al final de una
   columna. Ahora cada uno tiene su tarjeta con una maqueta que muestra QUÉ va
   a pasar al hacer clic: ecualizador + transcripción para la llamada, marco de
   videollamada con avatar y controles para el video.
   ========================================================================== */
.demo-grid {
  display: grid; grid-template-columns: repeat(2, 1fr);
  gap: clamp(1rem, 0.6rem + 1.6vw, 1.8rem);
  margin-top: var(--space-2xl);
}
@media (max-width: 820px) { .demo-grid { grid-template-columns: 1fr; } }

.demo-card {
  position: relative; overflow: hidden; isolation: isolate;
  display: flex; flex-direction: column; gap: var(--space-lg);
  padding: clamp(1.5rem, 1.1rem + 1.4vw, 2.2rem);
  border-radius: var(--radius);
  background: linear-gradient(140deg, var(--navy-900) 0%, var(--navy-950) 100%);
  color: var(--on-dark);
  box-shadow: 0 30px 70px -24px oklch(0.16 0.03 265 / 0.6);
  border: 1px solid oklch(0.97 0.008 265 / 0.08);
  transition: transform var(--dur-mid) var(--ease-out), box-shadow var(--dur-mid) var(--ease-out);
}
/* Hover solo con puntero fino: en táctil el :hover se queda pegado al tocar. */
@media (hover: hover) and (pointer: fine) {
  .demo-card:hover { transform: translateY(-4px); box-shadow: 0 38px 80px -24px oklch(0.16 0.03 265 / 0.7); }
}
/* La segunda tarjeta se calienta hacia el ámbar en la esquina baja: distingue
   video de voz sin cambiar la familia de color. */
.demo-card--video {
  background: linear-gradient(140deg, var(--navy-900) 0%, var(--navy-950) 54%, oklch(0.34 0.095 45) 132%);
}
.demo-card h3 { font-size: var(--text-2xl); margin-top: var(--space-sm); color: var(--on-dark); }
.demo-card > p, .demo-card__head p { color: var(--on-dark-soft); margin-top: var(--space-sm); }
.demo-card__head { position: relative; z-index: 1; }
.demo-card .kick {
  display: inline-flex; align-items: center; gap: 0.5rem;
  font-size: var(--text-xs); font-weight: 800;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--accent-bright);
}
.kick-dot {
  width: 8px; height: 8px; border-radius: 50%; background: var(--accent-bright);
  animation: pulseRing 2.2s var(--ease-out) infinite;
}
@keyframes pulseRing {
  0%   { box-shadow: 0 0 0 0 oklch(0.72 0.15 48 / 0.55); }
  70%  { box-shadow: 0 0 0 8px oklch(0.72 0.15 48 / 0); }
  100% { box-shadow: 0 0 0 0 oklch(0.72 0.15 48 / 0); }
}
/* El botón se pega al fondo de la tarjeta para que las dos tarjetas alineen su
   CTA aunque el copy de una sea más largo. */
.demo-card .btn { margin-top: auto; align-self: flex-start; }
/* Botón claro: la alternativa al ámbar dentro de una tarjeta oscura. Papel con
   tinta oscura = 16:1. Le da ritmo al par voz/video sin meter un segundo
   naranja idéntico al lado. */
.btn-light { background: var(--paper); color: var(--ink); }
@media (hover: hover) and (pointer: fine) {
  .btn-light:hover { background: #fff; }
  .btn-light:hover svg { transform: translateX(3px); }
}
.btn-light svg { transition: transform var(--dur-fast) var(--ease-out); }
/* Resplandor de fondo. Se llama __glow y NO .wave a propósito: .wave ya existe
   en esta hoja (el ecualizador del header) y reusar el nombre lo rompería. */
.demo-card__glow {
  position: absolute; right: -12%; bottom: -24%; width: 62%; height: 122%;
  z-index: -1; pointer-events: none;
  background: radial-gradient(circle at center, oklch(0.72 0.15 48 / 0.22) 0%, transparent 62%);
}

/* ---------- Maqueta: llamada de voz ---------- */
.demo-preview { position: relative; z-index: 1; border-radius: var(--radius); }
.demo-preview--voice {
  padding: 1.05rem 1.15rem;
  background: oklch(0.97 0.008 265 / 0.08);
  border: 1px solid oklch(0.97 0.008 265 / 0.16);
  /* Crece para llenar la tarjeta. Sin esto la maqueta de voz medía lo que mide
     su contenido y la de video —que tiene aspect-ratio 16/10— era mucho más
     alta: la rejilla igualaba las dos tarjetas y a la de voz le quedaban ~200px
     de hueco muerto entre la maqueta y el botón. Ahora respira centrada. */
  flex: 1 1 auto;
  display: flex; flex-direction: column; justify-content: center;
  gap: 0.45rem;
}
.dp-top {
  display: flex; justify-content: space-between; align-items: center;
  font-size: var(--text-xs); font-weight: 800; letter-spacing: 0.04em;
}
.dp-live { display: inline-flex; align-items: center; gap: 0.42rem; text-transform: uppercase; color: var(--on-dark); }
.dp-live-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: oklch(0.78 0.19 145); box-shadow: 0 0 9px oklch(0.78 0.19 145 / 0.8);
  animation: pulseRing 1.8s var(--ease-out) infinite;
}
.dp-time { color: var(--on-dark-soft); font-variant-numeric: tabular-nums; }
.eq { display: flex; align-items: center; gap: 3px; height: 34px; margin: 0.8rem 0; }
.eq i {
  flex: 1; height: 100%; border-radius: 3px;
  background: linear-gradient(180deg, var(--accent-bright), oklch(0.72 0.15 48 / 0.35));
  transform: scaleY(0.3); transform-origin: center;
  animation: eqBar 1s var(--ease-in-out) infinite;
}
/* Las barras no pueden ir todas al mismo compás o parece un código de barras.
   Números primos distintos = el ciclo tarda mucho en repetirse. */
.eq i:nth-child(2n) { animation-delay: -0.15s; animation-duration: 0.82s; }
.eq i:nth-child(3n) { animation-delay: -0.35s; animation-duration: 1.28s; }
.eq i:nth-child(5n) { animation-delay: -0.55s; }
.eq i:nth-child(7n) { animation-delay: -0.72s; animation-duration: 0.94s; }
@keyframes eqBar { 0%, 100% { transform: scaleY(0.28); } 50% { transform: scaleY(1); } }
/* Dos burbujas = un mini-guion, no un adorno: se lee quién dice qué. La de la
   agente lleva la esquina viva abajo-izquierda; la del cliente, abajo-derecha,
   que es la convención de todo chat. */
.dp-bubble {
  font-size: var(--text-sm); line-height: 1.5; color: var(--on-dark);
  background: oklch(0.97 0.008 265 / 0.14);
  border-radius: 12px 12px 12px 4px; padding: 0.62rem 0.8rem;
  max-width: 92%; align-self: flex-start;
}
.dp-bubble--user {
  align-self: flex-end;
  border-radius: 12px 12px 4px 12px;
  background: oklch(0.97 0.008 265 / 0.06);
  color: var(--on-dark-soft);
}

/* ---------- Maqueta: videollamada ---------- */
.vframe {
  position: relative; aspect-ratio: 16 / 10; overflow: hidden;
  border-radius: var(--radius); display: grid; place-items: center;
  background: radial-gradient(120% 130% at 32% 18%, oklch(0.97 0.008 265 / 0.16), oklch(0.16 0.03 265 / 0.42) 78%);
  border: 1px solid oklch(0.97 0.008 265 / 0.18);
}
.vframe__rec {
  position: absolute; top: 0.7rem; left: 0.85rem;
  display: inline-flex; align-items: center; gap: 0.35rem;
  font-size: 0.66rem; font-weight: 800; letter-spacing: 0.1em; color: var(--on-dark);
}
.vframe__rec-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: oklch(0.62 0.21 22); box-shadow: 0 0 8px oklch(0.62 0.21 22 / 0.9);
  animation: pulseRing 1.4s var(--ease-out) infinite;
}
.vframe__time {
  position: absolute; top: 0.7rem; right: 0.85rem;
  font-size: var(--text-xs); font-weight: 800;
  font-variant-numeric: tabular-nums; color: var(--on-dark-soft);
}
.vframe__orb {
  position: relative; width: 84px; height: 84px; border-radius: 50%;
  display: grid; place-items: center;
  background: oklch(0.97 0.008 265 / 0.94);
  box-shadow: 0 14px 32px oklch(0.16 0.03 265 / 0.4);
}
.vframe__orb img { width: 58px; height: auto; }
.vframe__ring {
  position: absolute; inset: -9px; border-radius: 50%;
  border: 2px solid oklch(0.97 0.008 265 / 0.5);
  animation: orbRing 2.4s var(--ease-out) infinite;
}
@keyframes orbRing { 0% { transform: scale(0.82); opacity: 0.85; } 100% { transform: scale(1.3); opacity: 0; } }
.vframe__cap { position: absolute; bottom: 2.8rem; font-size: var(--text-sm); font-weight: 800; color: var(--on-dark); }
.vframe__controls { position: absolute; bottom: 0.7rem; display: flex; gap: 0.55rem; }
.vctl {
  width: 34px; height: 34px; border-radius: 50%;
  display: grid; place-items: center;
  background: oklch(0.97 0.008 265 / 0.18); color: var(--on-dark);
}
.vctl svg { width: 1rem; height: 1rem; }
.vctl--end { background: oklch(0.62 0.21 22); }

/* Reduced-motion: se apaga TODO el movimiento de las maquetas, pero se dejan
   en un estado legible (las barras a media altura, no aplastadas). */
@media (prefers-reduced-motion: reduce) {
  .kick-dot, .dp-live-dot, .eq i, .vframe__rec-dot, .vframe__ring { animation: none; }
  .eq i { transform: scaleY(0.7); }
  .demo-card { transition: none; }
}

/* ==========================================================================
   DÍA 77 (segunda ronda) — anclas, logo, mapa protagonista y movimiento
   --------------------------------------------------------------------------
   Pedido de Leonardo tras ver la primera ronda:
     · "cuando le doy al botón de hablar con la IA no llega a la sección de voz
        y video"  -> el header es fixed y NO había scroll-margin en ningún lado:
        el ancla dejaba el destino DEBAJO de la barra. Se arregla abajo.
     · "no olvides el logo de Soul Voice, respétalo" -> la cabecera llevaba un
        punto naranja genérico en vez del símbolo real.
     · "cambia el mapa, dale vida, que sea más protagonista, es muy simple"
     · "dale movimiento, vida a las imágenes"
   ========================================================================== */

/* ---------- Anclas bajo un header fijo ----------
   La barra mide ~86px y está en position:fixed, así que un scrollIntoView deja
   el titular del destino TAPADO. scroll-margin-top le reserva ese alto a
   cualquier elemento al que se salte. Es la causa raíz del botón "Habla con la
   IA ahora": sí saltaba, pero aterrizaba debajo de la barra y parecía que no. */
:root { --header-h: 5.5rem; }
[id] { scroll-margin-top: calc(var(--header-h) + var(--space-lg)); }

/* ---------- El símbolo real de Soul Voice ----------
   Sustituye al punto naranja. Es el mismo archivo que usa /us y el mismo que
   va dentro de la maqueta de videollamada: perfil + onda de voz. La versión
   BLANCA es la correcta en las dos landings porque la cabecera vive siempre
   sobre navy (el hero o, al hacer scroll, el fondo sólido) y el pie también. */
.brand .brand-mark {
  width: 34px; height: auto; display: block; flex: none;
  animation: markBreath 3.6s var(--ease-in-out) infinite;
}
@keyframes markBreath { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.05); } }
@media (hover: hover) and (pointer: fine) {
  .brand:hover .brand-mark { animation-play-state: paused; transform: scale(1.06); }
}
@media (prefers-reduced-motion: reduce) { .brand .brand-mark { animation: none; } }
.site-footer .brand .brand-mark { width: 28px; }

/* ==========================================================================
   Alcance LATAM — de tarjeta encogida a BANDA CINEMATOGRÁFICA
   --------------------------------------------------------------------------
   El mapa no era simple: estaba metido en una tarjeta de ~50% de ancho dentro
   de una rejilla de dos columnas, o sea a media escala. Y la propia imagen
   tiene el continente a la DERECHA y medio lienzo vacío a la izquierda — que
   es exactamente donde cabe el copy. Así que la imagen pasa a sangre, a
   tamaño de héroe, y el texto se apoya en su vacío. Cero recorte forzado.
   ========================================================================== */
.alcance-band {
  position: relative; isolation: isolate; overflow: hidden;
  display: flex; align-items: center;
  min-height: min(80vh, 720px);
  padding-block: var(--space-section);
  background: var(--navy-950); color: var(--on-dark);
}
.alcance-band__media { position: absolute; inset: 0; z-index: -3; }
.alcance-band__media img, .alcance-band__media video {
  width: 100%; height: 100%; object-fit: cover; object-position: 64% center;
  /* Arranca en 1.06 y no en 1: el deriva-zoom mueve la imagen, y sin ese
     margen de sobra se asomaría el borde del lienzo. */
  transform: scale(1.06);
  animation: mapDrift 34s var(--ease-in-out) infinite alternate;
}
@keyframes mapDrift {
  from { transform: scale(1.06) translate3d(0, 0, 0); }
  to   { transform: scale(1.13) translate3d(-1.4%, -1%, 0); }
}
/* Velo direccional: opaco donde va el copy, transparente sobre el continente. */
.alcance-band__veil {
  position: absolute; inset: 0; z-index: -2; pointer-events: none;
  background:
    linear-gradient(100deg,
      var(--navy-950) 3%,
      oklch(0.16 0.03 265 / 0.88) 24%,
      oklch(0.16 0.03 265 / 0.42) 46%,
      oklch(0.16 0.03 265 / 0.06) 70%,
      oklch(0.16 0.03 265 / 0) 100%),
    linear-gradient(to bottom, oklch(0.16 0.03 265 / 0.45), transparent 26%, transparent 74%, oklch(0.16 0.03 265 / 0.45));
}
/* Halo que respira sobre Colombia. Es un radial ANCHO a propósito: con
   object-fit:cover el recorte cambia según el ancho de la pantalla, así que un
   anillo de posición exacta se saldría del país en cuanto cambie el viewport.
   Un halo grande lee "Colombia encendida" y aguanta cualquier recorte. */
.alcance-band__halo {
  position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: radial-gradient(26rem 22rem at 64% 34%, oklch(0.72 0.15 48 / 0.20), transparent 68%);
  animation: haloBreath 7s var(--ease-in-out) infinite;
}
/* .alcance-band es flex; sin width:100% el .wrap se encoge al ancho de su
   contenido y el copy deja de alinearse con el resto de la página. */
.alcance-band > .wrap { position: relative; width: 100%; }
.alcance-band__copy { position: relative; max-width: 36rem; }
.alcance-band__copy .eyebrow { color: var(--accent-bright); }
.alcance-band__copy h2 { font-size: var(--text-3xl); margin-top: var(--space-sm); color: var(--on-dark); }
.alcance-band__copy .rule { background: var(--accent-bright); }
.alcance-band__copy p { color: var(--on-dark-soft); font-size: var(--text-lg); margin-top: var(--space-md); max-width: 44ch; }
.alcance-band__copy .band-cta { margin-top: var(--space-xl); }
@media (max-width: 900px) {
  /* En móvil el continente y el copy se pelean por el mismo sitio: el velo
     sube entero y la imagen se centra en el continente. */
  .alcance-band { min-height: auto; }
  .alcance-band__media img, .alcance-band__media video { object-position: 72% center; }
  .alcance-band__veil {
    background: linear-gradient(to top, var(--navy-950) 26%, oklch(0.16 0.03 265 / 0.78) 60%, oklch(0.16 0.03 265 / 0.55) 100%);
  }
  .alcance-band__halo { background: radial-gradient(18rem 16rem at 72% 30%, oklch(0.72 0.15 48 / 0.18), transparent 70%); }
}

/* ==========================================================================
   Movimiento en las imágenes de banda
   --------------------------------------------------------------------------
   Deriva lenta tipo Ken Burns. Solo `transform`, que va al compositor y no
   toca layout ni pintura (regla de rendimiento de emil-design-eng). Duraciones
   largas y ease-in-out: es atmósfera, no una micro-interacción — nadie tiene
   que NOTARLA, solo sentir que la página está viva.
   ========================================================================== */
.band-omni__img { transform: scale(1.05); animation: bandDrift 30s var(--ease-in-out) infinite alternate; }
.band-dx__img   { transform: scale(1.05); animation: bandDrift 36s var(--ease-in-out) infinite alternate reverse; }
.band-cine__media img, .band-cine__media video { animation: bandDrift 32s var(--ease-in-out) infinite alternate; }
@keyframes bandDrift {
  from { transform: scale(1.05) translate3d(0, 0, 0); }
  to   { transform: scale(1.11) translate3d(1.2%, -0.9%, 0); }
}

/* Entrada de las imágenes atada al SCROLL, no a un temporizador: la foto se
   revela conforme entra en pantalla. `animation-timeline: view()` corre fuera
   del hilo principal (no es JS), así que no compite con el video del hero.
   Va tras @supports: donde no exista, la imagen simplemente ya está visible. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .frame img, .alcance-band__media img, .alcance-band__media video, .demo-preview--video .vframe {
      animation-name: mediaEnter;
      animation-timeline: view();
      animation-range: entry 10% cover 34%;
      animation-fill-mode: both;
    }
    /* El mapa lleva DOS animaciones: la deriva infinita por tiempo y la
       entrada por scroll. Se declaran juntas o la segunda pisa a la primera. */
    .alcance-band__media img, .alcance-band__media video {
      animation-name: mapDrift, mediaEnter;
      animation-timeline: auto, view();
      animation-duration: 34s, auto;
      animation-timing-function: var(--ease-in-out), linear;
      animation-iteration-count: infinite, 1;
      animation-direction: alternate, normal;
    }
  }
}
@keyframes mediaEnter {
  from { opacity: 0.35; clip-path: inset(0 0 18% 0); }
  to   { opacity: 1;    clip-path: inset(0 0 0 0); }
}

@media (prefers-reduced-motion: reduce) {
  .alcance-band__media img, .alcance-band__media video, .alcance-band__halo,
  .band-omni__img, .band-dx__img,
  .band-cine__media img, .band-cine__media video { animation: none; }
}

/* ==========================================================================
   DÍA 77 (tercera ronda) — calculadora, formulario, FAQ y más movimiento
   ========================================================================== */

/* ---------- Calculadora: los mandos ahora son un instrumento ----------
   Antes los tres deslizadores flotaban sueltos sobre el fondo blanco, al lado
   de una tarjeta oscura con mucho peso: la sección se leía coja. Ahora los
   mandos viven en su propia superficie y las dos mitades se equilibran. */
.calc-controls {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: clamp(1.25rem, 1rem + 1vw, 1.9rem);
  box-shadow: 0 1px 2px oklch(0.16 0.03 265 / 0.04), 0 12px 32px -18px oklch(0.16 0.03 265 / 0.25);
}

/* El deslizador SE LLENA. Es la mejora que más se nota: antes la pista era gris
   uniforme y no se veía dónde estaba el valor dentro del rango. oferta.js
   escribe --fill en cada input; sin JS la pista se queda gris y sigue usable. */
input[type=range] { --fill: 0%; }
input[type=range]::-webkit-slider-runnable-track {
  height: 6px; border-radius: 4px;
  background: linear-gradient(to right, var(--ember) var(--fill), var(--line) var(--fill));
}
input[type=range]::-moz-range-track {
  height: 6px; border-radius: 4px;
  background: linear-gradient(to right, var(--ember) var(--fill), var(--line) var(--fill));
}
input[type=range]::-webkit-slider-thumb { margin-top: -9px; width: 24px; height: 24px; }
input[type=range]::-moz-range-thumb { width: 18px; height: 18px; }
@media (hover: hover) and (pointer: fine) {
  input[type=range]:hover::-webkit-slider-thumb { transform: scale(1.08); }
}

/* El medidor "de cada 10". Convierte el deslizador abstracto en algo que se
   VE: diez bloques, y los que se pierden se encienden en ámbar y crecen.
   aria-hidden porque el dato ya lo dice la etiqueta del deslizador. */
.calc-meter { display: flex; gap: 5px; margin-top: var(--space-md); align-items: center; height: 22px; }
.calc-meter i {
  flex: 1; height: 9px; border-radius: 3px;
  background: var(--line-strong);
  transform-origin: center;
  transition: background-color var(--dur-mid) var(--ease-out), transform var(--dur-mid) var(--ease-out);
}
.calc-meter i.is-lost { background: var(--ember); transform: scaleY(2.1); }
@media (prefers-reduced-motion: reduce) { .calc-meter i { transition: none; } }
.calc-meter-lbl { font-size: var(--text-xs); color: var(--ink-faint); margin-top: var(--space-2xs); }

/* La cifra late cuando cambia. 160ms, escala mínima: confirma que el número se
   actualizó sin distraer de leerlo (el conteo ya lo anima oferta.js). */
.calc-result .money { transition: transform 160ms var(--ease-out); }
.calc-result .money.is-bump { transform: scale(1.035); }
@media (prefers-reduced-motion: reduce) { .calc-result .money { transition: none; } }

/* ---------- Formulario ----------
   La flecha del <select> venía con stroke='%23735': eso NO es un gris, es el
   hex de 3 dígitos #773355 — un morado sucio que no está en ninguna paleta de
   la marca. Se pinta con la tinta suave real. */
.field select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2.4' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
}
/* Elevación al escribir: la tarjeta reacciona al foco dentro de ella. */
.form-card { transition: box-shadow var(--dur-mid) var(--ease-out); }
.form-card:focus-within {
  box-shadow: 0 30px 70px -20px oklch(0.16 0.03 265 / 0.55),
              0 2px 6px oklch(0.16 0.03 265 / 0.18),
              0 0 0 1px oklch(0.685 0.16 45 / 0.35);
}
/* El campo activo se levanta del resto. Solo transform+shadow. */
.field input:focus, .field select:focus { transform: translateY(-1px); }
.field input, .field select { transition: border-color var(--dur-fast) ease, box-shadow var(--dur-fast) ease, transform var(--dur-fast) var(--ease-out), background-color var(--dur-fast) ease; }
.field input:hover:not(:focus), .field select:hover:not(:focus) { background: var(--surface-sunk); }

/* ---------- FAQ: apertura animada ----------
   grid-template-rows 0fr->1fr es la única forma de animar "de alto automático"
   sin medir en JS ni saltar (truco de emil-design-eng). El <details> nativo no
   anima solo; el grid interior sí. */
.faq details { overflow: hidden; }
.faq details .ans-wrap { display: grid; grid-template-rows: 0fr; transition: grid-template-rows var(--dur-mid) var(--ease-out); }
.faq details[open] .ans-wrap { grid-template-rows: 1fr; }
.faq details .ans-wrap > * { overflow: hidden; }
.faq summary .chev { transition: transform var(--dur-mid) var(--ease-out); }
.faq details[open] summary .chev { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) {
  .faq details .ans-wrap { transition: none; }
  .faq summary .chev { transition: none; }
}

/* ---------- Más vida al pasar el ratón ----------
   Solo con puntero fino: en táctil el :hover se queda pegado tras el toque.
   Solo transform/box-shadow, nunca alto ni margen. */
@media (hover: hover) and (pointer: fine) {
  .step, .benefit, .chan, .stat, .precio-card, .assurance {
    transition: transform var(--dur-mid) var(--ease-out), box-shadow var(--dur-mid) var(--ease-out), border-color var(--dur-fast) ease;
  }
  .step:hover, .benefit:hover, .stat:hover {
    transform: translateY(-4px);
    box-shadow: 0 18px 40px -20px oklch(0.16 0.03 265 / 0.35);
    border-color: var(--line-strong);
  }
  .omni-chip { transition: transform var(--dur-fast) var(--ease-out); }
  .omni-chip:hover { transform: translateY(-2px); }
}

/* Escalonado de entrada más largo: había hasta data-delay="3"; con listas de
   seis (los beneficios, los canales) el resto entraba de golpe. 60ms por paso,
   dentro del rango que no se siente lento. */
.js .reveal[data-delay="4"].is-visible { transition-delay: 240ms; }
.js .reveal[data-delay="5"].is-visible { transition-delay: 300ms; }

/* Con reduced-motion el video del mapa NO se reproduce: se oculta y queda el
   poster (la <img> de respaldo dentro del <video>), igual que hacen el hero y
   la banda cinematográfica. */
@media (prefers-reduced-motion: reduce) {
  .alcance-band__media video { display: none; }
}

/* ===== Franja de promo (campaña d112) — oferta por tiempo limitado =========
   Va entre las stat tiles y la captura rápida: sección OSCURA entre dos claras,
   así se mantiene el ritmo claro/oscuro. El naranja vivo (--accent-bright) sobre
   navy pasa AA (~6:1); el CTA reusa .btn-primary (tinta oscura sobre ámbar).
   Sin backdrop-filter (cuelga el renderer). Solo color/opacidad, cero layout. */
.promo-band { background: var(--navy-950); color: #fff; text-align: center; }
.promo-band .wrap { display: flex; flex-direction: column; align-items: center; gap: var(--space-sm); }
.promo-flag {
  display: inline-flex; align-items: center; gap: var(--space-2xs);
  font-weight: 800; font-size: 0.82rem; letter-spacing: 0.09em; text-transform: uppercase;
  color: var(--navy-950); background: var(--accent-bright);
  padding: 0.45rem 1rem; border-radius: 100px;
}
.promo-band h2 {
  margin: var(--space-xs) 0 0; color: #fff; line-height: 1.06;
  font-size: clamp(1.7rem, 1.1rem + 2.6vw, 3rem); letter-spacing: -0.01em;
}
.promo-band h2 .hl { color: var(--accent-bright); }
.promo-band .promo-sub {
  color: var(--on-dark-faint); margin: 0 0 var(--space-md);
  font-size: clamp(1rem, 0.95rem + 0.4vw, 1.2rem); max-width: 42ch;
}
.promo-band .promo-sub b { color: #fff; }
