/* LANDRA CORE — landing pública.
   Los valores de color, tipografía, radio, sombra y motion vienen del design
   system: no se declaran literales aquí salvo los que el sistema no cubre. */

@import url("tokens/fonts.css");
@import url("tokens/colors.css");
@import url("tokens/typography.css");
@import url("tokens/spacing.css");
@import url("tokens/radius.css");
@import url("tokens/elevation.css");
@import url("tokens/motion.css");

/* ============ BASE ============ */

*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--surface-page);
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  line-height: var(--lh-normal);
  color: var(--text-body);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { font-family: var(--font-display); margin: 0; }
p { margin: 0; }
ul { margin: 0; padding: 0; list-style: none; }
img { max-width: 100%; height: auto; display: block; }

a { color: var(--text-link); text-decoration: none; }
a:hover { color: var(--text-link-hover); }

:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: var(--radius-xs); }

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  padding: 10px 16px; background: var(--surface-card); color: var(--text-heading);
  font-family: var(--font-display); font-weight: var(--fw-semibold);
}
.skip-link:focus { left: 8px; top: 8px; }

.icon-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

.icon {
  width: 1em; height: 1em; flex: 0 0 auto;
  font-size: 16px;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}

.num {
  font-family: var(--font-mono);
  font-size: var(--fs-caption);
  font-variant-numeric: tabular-nums;
  color: var(--slate-600);
}
.num--muted { color: var(--text-muted); }

/* ============ LAYOUT ============ */

.wrap { max-width: 1160px; margin: 0 auto; }
.wrap--narrow { max-width: 760px; }
.wrap--center { display: flex; flex-direction: column; align-items: center; gap: 48px; }
.wrap--split {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
  gap: 56px;
  align-items: center;
}

.section { padding: 96px 32px; }
.section--white   { background: var(--surface-card); }
.section--sunken  { background: var(--surface-page); }
.section--inverse { background: var(--surface-inverse); }
.section--dark    { background: var(--slate-900); }

/* La maqueta del hero sobresale hacia abajo; esta sección le deja el aire. */
.section--after-mockup { padding-top: 170px; }

/* ============ FONDO DE VIDEO A SANGRE ============
   Tres capas numeradas: video 0, velo 1, contenido 2. Van declaradas y no
   libradas al orden del documento — `::before` se genera antes que el <video>
   pero se pinta debajo, y el velo terminaría sin velar nada. Es el mismo fallo
   que ya tuvieron la ficha y la tarjeta, por el mismo motivo. */
.section--video { position: relative; overflow: hidden; }

.section__video {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; object-position: center;
  display: block;
  z-index: 0;
}

/* VELO EN DEGRADADO Y NO PAREJO, y el motivo es medible. El video tiene un
   fotograma casi blanco —rgb(255,254,214)— y encima van el eyebrow ámbar y el
   lead en slate-200. Con un velo parejo hace falta .80 para que los dos lleguen
   a 4.5:1, y a .80 el video ya no se ve: deja de valer la pena ponerlo.
   Abajo no hace falta nada de eso. Lo único que hay ahí son las trece tarjetas
   de módulo, que son blancas y OPACAS: el video no les toca el contraste. Así
   que el velo se pone denso donde está el texto y se afloja donde no lo hay, y
   el video se ve justo donde puede verse.

   LAS PARADAS VAN EN PÍXELES, NO EN PORCENTAJE. El encabezado mide siempre lo
   mismo y vive siempre arriba; la sección, en cambio, cambia de alto según
   cuántas filas de módulos entren. Con porcentajes el velo se correría del
   texto cada vez que la grilla reacomoda. */
.section--video::before {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(
    180deg,
    rgba(23, 29, 35, .86) 0,
    rgba(23, 29, 35, .86) 340px,
    rgba(23, 29, 35, .55) 500px,
    rgba(23, 29, 35, .55) 100%
  );
  z-index: 1;
}

.section--video > .wrap { position: relative; z-index: 2; }

/* EN EL TELÉFONO EL VIDEO CUBRE TODO EL ALTO, Y ESTÁ ELEGIDO ASÍ SABIENDO LO
   QUE CUESTA. Un teléfono deja la sección en 375x1259 porque las trece tarjetas
   se apilan. Contra un video 16:9, `object-fit: cover` lo amplía 1.75x para
   llegar a ese alto y se come el 83% del ancho: no se leen pantallas del
   sistema, se lee una textura en movimiento.
   Se probó acotarlo a una banda de 460px. Los números mejoraban mucho —escala
   0.64x, o sea achicando, y 46% del ancho a la vista— pero el movimiento
   quedaba encerrado arriba y la sección perdía justo lo que la hacía atractiva
   en un teléfono: un fondo vivo detrás de todo. Se prefiere la textura completa
   antes que el detalle legible en un recuadro.
   Y que quede dicho para el que venga: UN RECORTE VERTICAL APARTE NO ARREGLA
   ESTO. El origen es 1280x720; recortarlo a 9:16 da 405x720, que para cubrir
   1259px hay que ampliar 1.75x otra vez. Recortar elige el encuadre, no agrega
   píxeles. La única salida real sería re-renderizar el video en vertical desde
   su proyecto original. */

/* NO HAY REGLA DE MÓVIL Y ES A PROPÓSITO. El video pesa 1.37MB desde que se
   recodificó, así que ya no hay motivo para negárselo al teléfono. Antes vivía
   acá un `display: none` con un ancho de corte que el JS tenía que repetir, y
   esos dos números —el mismo, escrito en dos archivos, sin nada que los
   mantuviera atados— fueron los que hicieron que el video no arrancara en una
   ventana angosta durante horas.
   La imagen sigue cubriendo el hueco previo a la reproducción, pero desde el
   `poster` del <video>, que es el mismo archivo. Un solo lugar. */

/* ============ FONDO DE IMAGEN EN SECCIÓN OSCURA ============
   Misma idea que «Plataforma integral» pero con imagen fija en vez de video, y
   con el fondo puesto en el propio elemento en lugar de un hijo: sin `<video>`
   no hace falta un elemento aparte, y `background-image` se pinta por debajo
   del `::before` sin pedir capas declaradas.
   La imagen tiene brillos casi blancos en el escudo, rgb(251,250,249). Medido
   contra ese píxel, el eyebrow ámbar no llega a 4.5:1 hasta un velo de .76; se
   usa .84 arriba para tener margen.
   Abajo afloja a .55 porque ahí sólo hay mosaicos, que son tarjetas OPACAS y no
   dependen de lo que tengan detrás. Encabezado: 96 a 166px. Mosaicos: desde
   214px. Las paradas van en píxeles por el mismo motivo que en las otras dos
   secciones con fondo: el encabezado no cambia de alto, la sección sí. */
.section--seguridad {
  position: relative;
  overflow: hidden;
  background-image: url('../img/confianza_y_seguridad.webp');
  background-size: cover;
  background-position: center;
}

.section--seguridad::before {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(
    180deg,
    rgba(23, 29, 35, .84) 0,
    rgba(23, 29, 35, .84) 200px,
    rgba(23, 29, 35, .55) 320px,
    rgba(23, 29, 35, .55) 100%
  );
}

.section--seguridad > .wrap { position: relative; z-index: 1; }

/* ============ FONDO DE IMAGEN EN «EQUIPOS COMERCIALES» ============
   EL VELO ES PAREJO Y NO EN DEGRADADO, y esta vez el motivo no es el ancho sino
   el contenido. En «Plataforma integral» y en «Confianza y seguridad» el velo
   afloja abajo porque ahí sólo hay tarjetas OPACAS, que no dependen del fondo.
   Acá no hay ninguna: `.checklist li` es texto suelto sobre el fondo, de arriba
   abajo de la sección. No hay ni un tramo donde se pueda aflojar.

   El píxel más claro de la imagen es rgb(254,254,254) —blanco puro, del brillo
   central—. Contra ese píxel el mínimo para el eyebrow ámbar es .76; se usa .84
   por dos motivos: deja margen, y de paso apaga el texto en inglés que la
   imagen trae impreso, que en un sitio en español se lee como ruido. */
.section--equipos {
  position: relative;
  overflow: hidden;
  background-image: url('../img/equipos_comerciales.webp');
  background-size: cover;
  background-position: center;
}

.section--equipos::before {
  content: '';
  position: absolute; inset: 0;
  background: rgba(23, 29, 35, .88);
}

.section--equipos > .wrap { position: relative; z-index: 1; }

/* ============ CAPTURA DE FONDO EN «SITIO PÚBLICO» ============
   La captura tiene su propio fondo en rgb(242,245,247) y `--surface-page` es
   rgb(242,244,246): difieren en UN nivel sobre 255. Ese detalle es lo que hace
   funcionar toda la idea — al terminar el degradado en el color de la sección,
   la imagen no queda recortada dentro de un rectángulo visible sino que se
   disuelve, y sólo se ve el sitio que muestra, flotando.
   Por eso esta sección pasa a gris y no se queda blanca: en blanco el fondo
   gris de la propia captura dibujaría un bloque con bordes. */
   LA CAPTURA VA EN EL FLUJO, NO POSICIONADA EN ABSOLUTO, y eso es lo que
   sostiene todo lo demás. Antes flotaba en absoluto con un `padding-top` fijo
   en píxeles que le hacía lugar; pero su alto depende del ancho de la ventana y
   ese aire no, así que a 900px de ventana quedaban trescientos píxeles de gris
   vacío entre la imagen y el texto. En el flujo, el alto lo pone ella y todo lo
   que sigue se acomoda solo — a cualquier ancho, sin un número que mantener. */
.section--sitio { position: relative; }

/* Mismo ancho que el `.wrap` de la sección: 1160px, o el ancho disponible menos
   los 32px de padding a cada lado. Así la captura queda alineada con el texto y
   con la línea divisoria en vez de flotar con una medida propia. */
.sitio__marco { position: relative; max-width: 1160px; margin: 0 auto; }
.sitio__captura { display: block; width: 100%; height: auto; }

/* EL FUNDIDO VA EN PORCENTAJE DE LA IMAGEN, no en píxeles de la sección — y es
   el caso opuesto al de las otras secciones con fondo, donde el porcentaje era
   el error. Allá el degradado tenía que quedarse quieto mientras la sección
   cambiaba de alto; acá tiene que seguir a la imagen, porque lo que debe cruzar
   —el fondo gris propio de la captura, por debajo de las tarjetas— está a una
   proporción fija de ella: las tarjetas terminan al 84% de su alto. Con el 15%
   de abajo el fundido arranca al 85% y nunca las corta, mida lo que mida. */
.sitio__marco::after {
  content: '';
  position: absolute; left: 0; right: 0; bottom: 0;
  height: 15%;
  background: linear-gradient(180deg, rgba(242, 244, 246, 0), var(--surface-page));
}

/* La línea que separa la captura del texto, del boceto. Va sobre el primer
   `.wrap` y no como elemento aparte: es una separación, no contenido. */
.section--sitio > .wrap--split {
  margin-top: 52px;
  padding-top: 52px;
  border-top: 1px solid var(--border-default);
}

.section__head { display: flex; flex-direction: column; gap: 14px; max-width: 640px; margin-bottom: 48px; }
.section__head--center { text-align: center; max-width: 680px; align-items: center; margin-bottom: 0; }

.section__title {
  font-size: var(--fs-display-2);
  font-weight: var(--fw-bold);
  letter-spacing: var(--tracking-heading);
  line-height: 1.15;
  color: var(--slate-900);
  text-wrap: balance;
}
.section__title--inverse { color: var(--white); }

.section__lead { font-size: var(--fs-h4); line-height: var(--lh-relaxed); color: var(--slate-500); text-wrap: pretty; }
/* Slate-200 y no slate-300: sobre el slate-700 de las secciones inversas, el
   300 queda en 4.1:1 y no llega al mínimo. */
.section__lead--inverse { color: var(--slate-200); }

.eyebrow {
  font-family: var(--font-display);
  font-size: var(--type-eyebrow-size);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: uppercase;
  color: var(--text-muted);
}
.eyebrow--accent { color: var(--amber-400); }
.eyebrow--amber  { color: var(--amber-700); }
.eyebrow--sm     { font-size: 10px; letter-spacing: .1em; margin-left: auto; }

/* ============ BOTONES ============ */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  border: 1px solid transparent;
  border-radius: var(--radius-control);
  cursor: pointer;
  white-space: nowrap;
  transition: var(--transition-control);
}
.btn--sm { height: 30px; padding: 0 12px; font-size: var(--fs-body-sm); }
.btn--md { height: 38px; padding: 0 16px; font-size: var(--fs-body-sm); }
.btn--lg { height: 46px; padding: 0 22px; font-size: var(--fs-h4); }

.btn--primary { background: var(--accent); color: var(--text-on-accent); }
.btn--primary:hover { background: var(--accent-hover); color: var(--text-on-accent); }
.btn--primary:active { background: var(--accent-press); }

.btn--outline { background: var(--surface-card); color: var(--slate-600); border-color: var(--border-default); }
.btn--outline:hover { background: var(--surface-hover); color: var(--slate-800); }

/* NO ES TRANSPARENTE, y ese fue el hallazgo. Vive fuera del panel esmerilado,
   sobre la imagen apenas velada al 60%: con fondo transparente su texto blanco
   daba 4.48:1 contra el peor píxel, por debajo del mínimo de 4.5. Con el mismo
   respaldo que el panel deja de depender de lo que tenga detrás — y de paso
   rima con él en vez de flotar suelto. */
.btn--outline-inverse { background: rgba(23, 29, 35, .55); color: var(--white); border-color: var(--slate-500); }

/* ---- Botones esmerilados, sólo en el hero ----
   Scopeado a `.hero` a propósito: el mismo `.btn--primary` vive en la cabecera
   sobre blanco y en el formulario sobre una tarjeta clara, donde un cristal no
   tendría nada detrás que refractar y además perdería contraste.

   EL ÁMBAR VA AL 82% Y NO MÁS ABAJO, y el motivo es su propio texto. El design
   system pide texto slate-800 sobre ámbar porque el ámbar es claro. Al volverlo
   translúcido sobre las zonas negras de la imagen el relleno se apaga y arrastra
   al texto con él: medido, al 60% da 3.20:1 y al 70% da 4.04:1, los dos por
   debajo del mínimo. Al 82% da 5.15:1. Es un cristal que para seguir siendo
   legible casi no puede ser cristal — el efecto se nota poco, y esa es la
   consecuencia honesta de la medición, no una falta de convicción.

   El natural no tiene ese problema: su texto es blanco y su respaldo oscuro. */
.hero .btn--primary {
  background: rgba(245, 166, 36, .82);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
.hero .btn--primary:hover { background: rgba(217, 143, 30, .92); }

.hero .btn--outline-inverse {
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
.btn--outline-inverse:hover { background: rgba(255, 255, 255, .08); color: var(--white); border-color: var(--slate-300); }

.btn[disabled] { opacity: .45; cursor: default; box-shadow: none; }

/* ============ CABECERA ============ */

.site-header {
  position: sticky; top: 0; z-index: 50;
  background: var(--surface-card);
  border-bottom: 1px solid var(--border-subtle);
}
.site-header__inner {
  max-width: 1160px; margin: 0 auto; padding: 0 32px;
  height: 64px; display: flex; align-items: center; justify-content: space-between; gap: 24px;
}
.site-header__logo img { height: 34px; width: auto; }

.site-nav {
  display: flex; align-items: center; gap: 28px;
  font-family: var(--font-display);
  font-size: var(--fs-body-sm);
  font-weight: var(--fw-semibold);
  letter-spacing: .01em;
}
.site-nav a { color: var(--slate-600); }
.site-nav a:hover { color: var(--slate-900); }

.site-header__toggle {
  display: none;
  width: 38px; height: 38px; padding: 0;
  align-items: center; justify-content: center;
  background: transparent; border: 1px solid var(--border-default);
  border-radius: var(--radius-control); color: var(--slate-600); cursor: pointer;
}
.site-header__toggle .icon { font-size: 18px; }

/* ============ HERO ============ */

.hero { position: relative; background: var(--slate-900); padding: 88px 32px 0; }

/* SIN `overflow: hidden` A PROPÓSITO: la maqueta del panel sobresale 70px por
   abajo con margen negativo, y recortarla arruinaría el efecto. No hace falta:
   el fondo está anclado a `inset: 0`, que es exactamente la caja del hero. */
/* El recorte va ACÁ y no en `.hero`, que lo evita a propósito para dejar
   sobresalir la maqueta. Este contenedor sólo tiene los fondos, así que
   recortarlo no toca nada más — y hace falta porque la imagen difusa se agranda
   un 4% y si no se saldría de la sección. */
.hero__fondos { position: absolute; inset: 0; overflow: hidden; }

.hero__fondo {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; object-position: center;
  display: block;
  opacity: 0;
  transition: opacity 900ms var(--ease-standard);
}
.hero__fondo.is-activo { opacity: 1; }

/* DESENFOQUE, Y NO MÁS VELO. Esta imagen trae un tablero con sus rótulos
   —BORRADORES, VENDIDOS, RENTADOS, «Contratos en proceso»— y la maqueta que va
   encima del hero dice esas mismas palabras. Leerlas dos veces distrae.
   Subir el velo no lo arregla: oscurece la letra y su fondo por igual, así que
   la diferencia entre ambos sólo se reduce en proporción. A .76 todavía queda
   el 24% del contraste original y el texto se sigue leyendo; para taparlo haría
   falta un velo que se lleve puesta la imagen entera.
   El desenfoque sí destruye la forma de la letra y deja el color y la luz, que
   es lo único que se le pide a un fondo. El `scale` compensa los bordes
   blandos que el filtro deja en el perímetro. */
.hero__fondo--difuso { filter: blur(7px); transform: scale(1.04); }

/* Puntos de control. Ámbar el activo, hairline los demás: el mismo vocabulario
   que el resto del sistema, sin inventar un componente nuevo. */
.hero__puntos { display: flex; gap: 8px; margin-top: 4px; }
.hero__punto {
  width: 8px; height: 8px; padding: 0;
  border: 1px solid var(--slate-500);
  border-radius: var(--radius-pill);
  background: transparent;
  cursor: pointer;
  transition: var(--transition-control);
}
.hero__punto:hover { border-color: var(--slate-300); }
.hero__punto.is-activo { background: var(--accent); border-color: var(--accent); }

/* El velo que garantiza el contraste del texto.
   NO SE ELIGIÓ A OJO. La imagen parece uniformemente oscura, pero los halos de
   las banderas llegan a rgb(243,250,255) —casi blanco—, y el texto puede caer
   encima de cualquiera de ellos según cómo recorte `cover` en cada pantalla.
   Medido contra ese peor caso: al 78% el titular da 8.48:1, el párrafo 5.13:1 y
   el eyebrow ámbar 4.98:1. Al 72% el párrafo caía a 4.17:1 y no pasaba.
   El 82% del diseño original resultó estar bien fundado; 78% deja ver un poco
   más del mapa conservando margen sobre el mínimo de 4.5:1. */
.hero::after {
  content: '';
  position: absolute; inset: 0;
  background: rgba(23, 29, 35, var(--velo, .78));
  pointer-events: none;
  /* Acompaña al fundido de la imagen: si el velo saltara de golpe, se vería un
     parpadeo de luminosidad en mitad de la transición. */
  transition: background-color 900ms var(--ease-standard);
}

.hero__inner {
  position: relative; z-index: 1;
  max-width: 1160px; margin: 0 auto;
  display: flex; flex-direction: column; align-items: center; text-align: center; gap: 22px;
}
/* PANEL ESMERILADO. Invierte de dónde sale el contraste: antes lo daba el velo
   sobre toda la imagen, y para proteger el texto había que tapar el arte
   entero. Acá el respaldo es local, así que el velo puede bajar a .60 y la
   imagen se ve.
   La opacidad no es estética: se calculó contra el peor píxel de las tres
   imágenes ya veladas, para que el párrafo conserve 4.5:1. El desenfoque solo
   suaviza, no aporta contraste — quitarlo dejaría los números igual. */
.hero__panel {
  display: flex; flex-direction: column; align-items: center; gap: 22px;
  max-width: 900px;
  padding: 40px 48px 44px;
  background: rgba(23, 29, 35, .55);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border: 1px solid var(--slate-500);
  border-radius: var(--radius-lg);
}

/* Tamaño medio: por encima del logo de la cabecera (34px) y del cierre (44px),
   sin competir con el titular, que es lo que tiene que leerse primero. */
.hero__logo { height: 72px; width: auto; margin-bottom: 6px; }

.hero__title {
  max-width: 820px;
  font-size: clamp(36px, 4.6vw, 56px);
  font-weight: var(--fw-bold);
  letter-spacing: var(--tracking-display);
  line-height: 1.08;
  color: var(--white);
  text-wrap: balance;
}
.hero__lead {
  max-width: 720px;
  font-size: 18px; line-height: var(--lh-relaxed);
  color: var(--slate-200); text-wrap: pretty;
}
.hero__actions { display: flex; gap: 14px; flex-wrap: wrap; justify-content: center; margin-top: 8px; }

/* ============ MAQUETA DEL PANEL ============ */

.mockup {
  width: 100%; max-width: 1080px;
  margin: 44px 0 -70px;
  background: var(--surface-card);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-dialog);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  display: flex; text-align: left;
}
.mockup__rail {
  width: 56px; flex: 0 0 auto;
  background: var(--surface-inverse);
  display: flex; flex-direction: column; align-items: center; padding: 14px 0; gap: 4px;
}
.mockup__rail-item {
  width: 100%; display: flex; justify-content: center; padding: 9px 0;
  border-left: 2px solid transparent; color: var(--slate-300);
}
.mockup__rail-item .icon { font-size: 17px; }
.mockup__rail-item.is-active { border-left-color: var(--accent); color: var(--accent); }
.mockup__rail-spacer { flex: 1; }

.mockup__body { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.mockup__topbar {
  height: 48px; border-bottom: 1px solid var(--border-subtle);
  display: flex; align-items: center; gap: 14px; padding: 0 18px;
}
.mockup__topbar-title {
  font-family: var(--font-display); font-size: 14px;
  font-weight: var(--fw-semibold); color: var(--text-heading);
  margin-right: auto;
}
.mockup__search {
  display: flex; align-items: center; gap: 8px;
  height: 30px; padding: 0 12px; min-width: 180px;
  background: var(--surface-page); border: 1px solid var(--border-subtle);
  border-radius: var(--radius-control);
  color: var(--text-muted); font-size: var(--fs-body-sm);
}
.mockup__bell { color: var(--slate-400); }
.mockup__avatar {
  width: 28px; height: 28px; border-radius: var(--radius-pill);
  background: var(--slate-200); color: var(--slate-600);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display); font-size: var(--fs-micro); font-weight: var(--fw-semibold);
}
.mockup__content {
  flex: 1; background: var(--surface-page);
  padding: 18px; display: flex; flex-direction: column; gap: 14px;
}
.mockup__stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr)); gap: 12px; }
.mockup__split { display: grid; grid-template-columns: 1.55fr 1fr; gap: 12px; }

/* ============ PIEZAS DE PRODUCTO (stat, panel, badge) ============ */

.stat {
  background: var(--surface-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-sm);
  padding: 14px 16px;
  display: flex; flex-direction: column; gap: 4px;
}
.stat__label {
  font-family: var(--font-display); font-size: var(--fs-micro);
  font-weight: var(--fw-semibold); letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase; color: var(--text-muted);
}
.stat__value {
  font-family: var(--font-display); font-size: 26px;
  font-weight: var(--fw-bold); color: var(--text-heading);
  display: flex; align-items: baseline; gap: 8px;
}
.stat__delta { font-family: var(--font-mono); font-size: var(--fs-caption); font-style: normal; color: var(--green-600); }
.stat__foot { font-size: var(--fs-micro); color: var(--text-muted); }

.panel {
  background: var(--surface-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  display: flex; flex-direction: column;
}
.panel--accent { border-top: 2px solid var(--accent); box-shadow: var(--shadow-md); }
.panel--pad { padding: 14px 18px; gap: 10px; }
.panel__head {
  padding: 12px 16px; border-bottom: 1px solid var(--border-subtle);
  display: flex; align-items: center; gap: 8px;
}
.panel__title {
  font-family: var(--font-display); font-size: 14px;
  font-weight: var(--fw-semibold); color: var(--text-heading);
}
.panel__head .num, .panel__head .badge { margin-left: auto; }
.panel__head .eyebrow { margin-left: auto; }
.panel__list { padding: 4px 16px 10px; }
.panel__pad { padding: 14px 18px; display: flex; flex-direction: column; gap: 12px; }
.panel__foot {
  margin-top: auto; padding: 10px 16px;
  border-top: 1px solid var(--border-subtle);
  display: flex; align-items: center; justify-content: space-between;
  font-size: var(--fs-caption); color: var(--slate-500);
}

.row {
  display: flex; align-items: center; gap: 12px;
  padding: 0 16px; height: 52px;
  border-bottom: 1px solid var(--border-subtle);
}
.row__main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.row__main b { font-size: var(--fs-body-sm); font-weight: var(--fw-medium); color: var(--text-heading); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.row__main small { font-size: var(--fs-micro); color: var(--text-muted); }

.listrow {
  display: flex; align-items: center; justify-content: space-between;
  height: 40px; border-bottom: 1px solid var(--border-subtle);
  font-size: var(--fs-body-sm); color: var(--slate-600);
}
.listrow:last-child { border-bottom: none; }
.listrow--plain { height: auto; border-bottom: none; font-size: var(--fs-body-sm); color: var(--slate-500); }

.badge {
  display: inline-flex; align-items: center;
  padding: 3px 8px; border-radius: var(--radius-badge);
  font-family: var(--font-display); font-size: var(--fs-micro); font-weight: var(--fw-semibold);
}
.badge--success { background: var(--status-success-bg); color: var(--status-success-fg); }
.badge--warning { background: var(--status-warning-bg); color: var(--status-warning-fg); }
.badge--info    { background: var(--status-info-bg);    color: var(--status-info-fg); }
.badge--neutral { background: var(--status-neutral-bg); color: var(--status-neutral-fg); }

.mapgrid {
  flex: 1; min-height: 130px; position: relative; overflow: hidden;
  background: var(--surface-page);
}
/* `cover` y no `contain`: el recuadro es flexible y cambia de proporción según
   el ancho de pantalla. Con `cover` la imagen siempre lo llena y se recorta lo
   que sobra; con `contain` aparecerían franjas vacías a los lados. Y en ningún
   caso se deforma — eso sólo pasaría con `fill`, que es el default de <img>
   estirado y justamente lo que hay que evitar. */
.mapgrid__mapa {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  /* ANCLADA ABAJO Y NO AL CENTRO. La atribución de Google va en el borde
     inferior de la imagen, y `cover` recorta por arriba y por abajo cuando el
     recuadro se ensancha — en móvil se comía justo esa franja. Anclando el
     borde inferior, lo que se recorta es el cielo del mapa y la atribución
     queda siempre visible, que es condición de uso y no una preferencia. */
  object-position: center bottom;
  display: block;
}
.mapgrid__pin--a { left: 24%; top: 30%; color: var(--accent); }
.mapgrid__pin--b { left: 58%; top: 52%; color: var(--accent); }
.mapgrid__pin--c { left: 40%; top: 66%; }
.mapgrid__pin--d { left: 74%; top: 22%; }

/* ============ TARJETAS DE BENEFICIO ============ */

.grid { display: grid; gap: 20px; }
.grid--cards { grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); }
.grid--tiles { grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); gap: 16px; }

/* TARJETAS OSCURAS SOBRE SECCIÓN BLANCA. El cambio no es sólo de fondo: sobre
   claro el enlace «Más información» tenía que usar amber-700, el ámbar más
   oscuro del sistema, y aun así daba 3.70:1 — por debajo del mínimo, sin
   ninguna variante que lo salvara. Sobre oscuro el mismo enlace puede usar
   amber-400 y llega a 8.5:1. La restricción se resolvió cambiando el fondo,
   no buscando un color que no existía. */
.card {
  position: relative;
  /* La imagen se recorta con el radio en vez de asomar por las esquinas. */
  overflow: hidden;
  background: var(--slate-900);
  border: 1px solid var(--slate-700);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-md);
  padding: 26px 24px;
  display: flex; flex-direction: column; gap: 14px;
  /* Sólo cuenta sin JS: con JS el revelado se adueña de `transition` en este
     mismo elemento y la reemplaza entera. Por eso la de allá abajo también
     lleva `translate` y `box-shadow`. */
  transition:
    translate var(--dur-base) var(--ease-out),
    box-shadow var(--dur-base) var(--ease-out);
}
.card--accent { border-top: 2px solid var(--accent); }

/* HOVER: SUBE UN POCO Y APOYA UNA SOMBRA MÁS ABIERTA.
   USA `translate` Y NO `transform`, A PROPÓSITO. Estas tarjetas llevan
   `data-reveal` y el revelado ya es dueño de `transform`: su estado final lo
   fija en `none` desde `.js [data-reveal].is-revealed`, que con tres clases le
   gana a cualquier `:hover` de dos. Un hover escrito con `transform` acá no se
   vería nunca. `translate` es una propiedad independiente —se compone con
   `transform` en vez de pisarlo— así que los dos efectos conviven.
   `:focus-within` va junto al hover porque quien llega con el tabulador al
   botón merece la misma respuesta que quien llega con el puntero. */
.card:hover,
.card:focus-within {
  translate: 0 -4px;
  box-shadow: var(--shadow-lg);
}

/* La tarjeta es la ficha en chico: misma imagen, mismo velo, misma regla ámbar
   arriba. Lo único que cambia es la escala.
   VELO PAREJO Y NO DEGRADADO LATERAL: a este ancho no hay lugar para separar
   texto de imagen, que es lo mismo que hace la ficha en pantallas angostas. */
.card__fondo {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; object-position: center;
  z-index: 0;
}
.card::before {
  content: '';
  position: absolute; inset: 0;
  background: rgba(23, 29, 35, .88);
  z-index: 1;
}
/* El contenido sube de capa. Sin esto la imagen se pinta encima del velo, que
   es exactamente el fallo que tuvo la ficha por el mismo motivo. */
.card > *:not(.card__fondo) { position: relative; z-index: 2; }
.card__icon {
  width: 40px; height: 40px; border-radius: var(--radius-card);
  /* Ámbar traslúcido en vez del amber-50 sólido: sobre oscuro ese tono claro
     sería un rectángulo brillante compitiendo con el título. */
  background: rgba(245, 166, 36, .14); color: var(--amber-400);
  display: flex; align-items: center; justify-content: center;
}
.card__icon .icon { font-size: 20px; }
.card__title { font-size: 17px; font-weight: var(--fw-semibold); color: var(--white); }
.card__text { font-size: 14px; line-height: 1.55; color: var(--slate-200); text-wrap: pretty; }

/* `margin-top: auto` empuja el enlace al pie de la tarjeta. Los cuatro textos
   tienen largos distintos, y sin esto cada «Más información» quedaría a una
   altura diferente: la fila se leería desalineada aunque las tarjetas midan
   igual. */
.card__mas {
  margin-top: auto;
  align-self: flex-start;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 0;
  background: none; border: none; cursor: pointer;
  font-family: var(--font-display);
  font-size: var(--fs-micro);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  /* AMBER-400 Y NO AMBER-700, y ese fue el motivo real de oscurecer la tarjeta.
     Sobre fondo claro este enlace tenía que usar amber-700, el ámbar más oscuro
     del sistema, y aun así daba 3.70:1 — por debajo del mínimo, sin ninguna
     variante que lo salvara. Sobre el velo oscuro, amber-400 llega a 6.81:1. */
  color: var(--amber-400);
  transition: var(--transition-control);
}
.card__mas:hover { color: var(--amber-300); }
.card__mas .icon { font-size: 13px; transition: transform var(--dur-fast) var(--ease-standard); }
.card__mas:hover .icon { transform: translateX(3px); }

.tile {
  display: flex; align-items: center; gap: 14px;
  background: var(--surface-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-xs);
  padding: 20px 22px;
  font-size: var(--fs-body); font-weight: var(--fw-medium); color: var(--slate-700);
}
.tile .icon { font-size: 18px; color: var(--slate-400); }

/* ============ MÓDULOS ============ */

.modules {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 14px; width: 100%;

  /* Entrada propia de esta sección: son trece tarjetas iguales, así que el
     escalonado es lo que las vuelve una secuencia en vez de un parpadeo
     colectivo. Paso y duración más largos que el default a propósito — acá el
     movimiento es el contenido, no un acuse de un control. */
  --reveal-paso: 90ms;
  --reveal-dur: 460ms;
  --reveal-x: 34px;
}
.module {
  flex: 0 0 auto; width: 262px;
  display: flex; align-items: center; gap: 12px;
  background: var(--surface-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-xs);
  padding: 16px 18px;
  font-size: 14px; font-weight: var(--fw-medium); color: var(--slate-700);
}
/* Ámbar 700 y no el 500 de los botones: ahí el ámbar es relleno con texto
   oscuro encima, acá es trazo sobre blanco y el 500 queda lavado. El 700 es el
   token del sistema para ámbar sobre fondo claro, y es el que ya usan los
   iconos de beneficios y los chips. */
.module .icon { font-size: 17px; color: var(--amber-700); }

/* ============ TABLERO ============ */

.board {
  background: var(--surface-page);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-dialog);
  padding: 22px;
  display: flex; flex-direction: column; gap: 14px;
}

/* SIMULACIÓN DEL TABLERO. Los datos entran en su lugar en vez de estar ahí
   desde siempre: las barras crecen y las cifras suben hasta su valor. No es
   adorno — es la diferencia entre una captura de pantalla y algo que se está
   usando, que es justamente lo que la sección promete.
   El estado inicial en cero sólo existe con JS disponible y antes de que el
   tablero entre en pantalla. Sin JS, las barras salen a su altura final. */
.js .board .chart__bar i,
.js .board .bars__track i {
  transition:
    height var(--simulacion-dur, 760ms) var(--ease-standard),
    width var(--simulacion-dur, 760ms) var(--ease-standard);
  transition-delay: calc(var(--barra, 0) * 45ms);
}
.js .board:not(.is-simulado) .chart__bar i { height: 0; }
.js .board:not(.is-simulado) .bars__track i { width: 0; }
.board__stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(170px, 100%), 1fr)); gap: 12px; }
.board__split { display: grid; grid-template-columns: 1.55fr 1fr; gap: 12px; align-items: start; }
.board__col { display: flex; flex-direction: column; gap: 12px; }

.chart { padding: 20px 18px 14px; display: flex; align-items: flex-end; gap: 10px; height: 140px; }
.chart__bar {
  flex: 1; height: 100%;
  display: flex; flex-direction: column; align-items: center; justify-content: flex-end; gap: 6px;
}
.chart__bar i {
  width: 100%; max-width: 26px; height: var(--h);
  background: var(--slate-200);
  border-radius: var(--radius-xs) var(--radius-xs) 0 0;
}
.chart__bar--accent i { background: var(--accent); }
.chart__bar small { font-family: var(--font-mono); font-size: 10px; color: var(--text-muted); }

.bars { padding: 16px 18px; display: flex; flex-direction: column; gap: 12px; }
.bars__row { display: flex; align-items: center; gap: 12px; }
.bars__name {
  width: 150px; flex: 0 0 auto;
  font-size: var(--fs-body-sm); color: var(--slate-600);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.bars__track { flex: 1; height: 8px; background: var(--slate-100); border-radius: var(--radius-pill); overflow: hidden; }
.bars__track i { display: block; height: 100%; width: var(--w); background: var(--accent); border-radius: var(--radius-pill); }
.bars__row .num { width: 28px; text-align: right; }

.quick { display: flex; flex-wrap: wrap; gap: 8px; }

/* ============ CHECKLIST (fondo inverso) ============ */

.checklist { display: flex; flex-direction: column; }
.checklist li {
  display: flex; align-items: center; gap: 14px;
  padding: 15px 0; border-bottom: 1px solid var(--border-inverse);
  font-size: var(--fs-h4); color: var(--slate-100);
}
.checklist li:last-child { border-bottom: none; }
.checklist .icon { font-size: 18px; color: var(--accent); }

/* ============ PROTECCIÓN AL ASESOR ============ */

.features { display: flex; flex-direction: column; gap: 20px; margin-top: 26px; }

/* La misma pieza en grilla en vez de en columna. NO ES UN COMPONENTE NUEVO: el
   icono, el título y el texto se quedan como están y sólo cambia cómo se
   reparten. Un «feature» en tarjeta y un «feature» en lista que se vieran
   distintos serían dos cosas que mantener. */
.features--grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(290px, 100%), 1fr));
  gap: 34px 40px;
  margin-top: 64px;
}
.feature { display: flex; gap: 16px; align-items: flex-start; }
.feature__icon {
  width: 38px; height: 38px; flex: 0 0 auto;
  border-radius: var(--radius-card);
  background: var(--surface-card); border: 1px solid var(--border-default);
  display: flex; align-items: center; justify-content: center; color: var(--amber-700);
}
.feature__icon .icon { font-size: 18px; }
.feature__title { font-size: var(--fs-h4); font-weight: var(--fw-semibold); color: var(--text-heading); margin-bottom: 4px; }
.feature__text { font-size: 14px; line-height: 1.55; color: var(--slate-500); text-wrap: pretty; }

.proof { display: flex; flex-direction: column; gap: 14px; max-width: 440px; width: 100%; justify-self: center; }
.agent {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 14px;
  background: var(--surface-page); border: 1px solid var(--border-subtle);
  border-radius: var(--radius-control);
}
.agent__avatar {
  width: 34px; height: 34px; flex: 0 0 auto; border-radius: var(--radius-pill);
  background: var(--slate-200); color: var(--slate-600);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display); font-size: var(--fs-caption); font-weight: var(--fw-semibold);
}
.agent__id { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.agent__id b { font-size: var(--fs-body-sm); font-weight: var(--fw-medium); color: var(--text-heading); }
.agent__id small { font-size: var(--fs-micro); color: var(--text-muted); }
.agent .icon { color: var(--slate-400); font-size: 15px; }

/* ============ CHIPS ============ */

.chips {
  display: flex; flex-wrap: wrap; gap: 10px; align-content: center;

  /* Misma entrada que los módulos: son otra lista de piezas iguales y merecen
     leerse igual. Los valores se repiten a propósito en vez de compartirse en
     una clase común — el día que una de las dos secciones quiera otro ritmo,
     cambiarla no debe mover la otra. */
  --reveal-paso: 90ms;
  --reveal-dur: 460ms;
  --reveal-x: 34px;
}
.chip {
  display: inline-flex; align-items: center; gap: 8px;
  height: 38px; padding: 0 16px;
  background: var(--surface-page); border: 1px solid var(--border-default);
  border-radius: var(--radius-pill);
  white-space: nowrap;
  font-size: 14px; font-weight: var(--fw-medium); color: var(--slate-600);
}
.chip .icon { font-size: 15px; color: var(--amber-700); }

/* ============ COMPARATIVA ============ */

/* ============ PLANES ============
   LAS DOS LISTAS DICEN LO MISMO, Y ES DELIBERADO. La única diferencia real
   entre los planes es cuántos agentes entran. Inventar funciones distintas
   sería mentir dos veces: en la promesa, y en la capacidad de cumplirla — el
   sistema no tiene banderas por plan, todo inquilino tiene todo. La diferencia
   se muestra donde de verdad está, en el límite, y no repartida en una lista
   recortada a mano. */
.planes {
  display: grid;
  /* Tres tarjetas de 320px con sus dos separaciones dan 1008px y el `.wrap`
     mide 1160: entran holgadas en una fila. */
  grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
  gap: 24px;
  /* SE ESTIRAN A LA MISMA ALTURA, que es lo que hace que los botones queden
     alineados entre sí gracias al `margin-top: auto` de cada uno. Con
     `align-items: start` cada tarjeta medía lo suyo y los botones quedaban a
     tres alturas distintas — no se notaba con dos listas iguales, se nota
     apenas una tercera tiene otra cantidad de puntos. */
  align-items: stretch;
}

/* Selector de forma de pago. Son BOTONES con `aria-pressed` y no pestañas: no
   hay dos paneles de contenido entre los que navegar, hay un mismo precio que
   se expresa de dos maneras. `aria-pressed` dice exactamente eso —esta opción
   está activa— y funciona con teclado sin escribir una línea de JS. */
.periodo { display: flex; flex-direction: column; align-items: center; gap: 10px; margin-bottom: 38px; }

.periodo__grupo {
  display: inline-flex; gap: 4px; padding: 4px;
  background: var(--surface-card);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-pill);
}

.periodo__opcion {
  border: none; background: transparent; cursor: pointer;
  font-family: var(--font-display);
  font-size: var(--fs-body-sm); font-weight: var(--fw-semibold);
  color: var(--slate-500);
  padding: 9px 22px; border-radius: var(--radius-pill);
  transition: var(--transition-control);
}
.periodo__opcion:hover { color: var(--slate-800); }
.periodo__opcion[aria-pressed="true"] { background: var(--slate-900); color: var(--white); }

.periodo__nota { font-size: 13px; color: var(--slate-500); }

.plan {
  display: flex; flex-direction: column;
  background: var(--surface-card);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-sm);
  padding: 30px 32px 32px;
}

/* La regla ámbar arriba, el mismo recurso con el que el sitio marca lo que
   quiere que mires: la ficha, la tarjeta de beneficio, la comparativa. */
.plan--destacado { border-top: 2px solid var(--accent); box-shadow: var(--shadow-md); }

.plan__encabezado { display: flex; align-items: center; gap: 10px; margin-bottom: 4px; }

.plan__nombre { font-size: var(--fs-h3); font-weight: var(--fw-semibold); color: var(--text-heading); }

.plan__insignia {
  font-family: var(--font-display);
  font-size: 10px; letter-spacing: .1em; text-transform: uppercase;
  font-weight: var(--fw-semibold);
  padding: 4px 9px; border-radius: var(--radius-pill);
  background: var(--accent); color: var(--text-on-accent);
}

.plan__limite { font-size: 14px; color: var(--slate-500); }

.plan__precio { display: flex; align-items: baseline; gap: 8px; margin: 22px 0 6px; }
.plan__monto {
  font-family: var(--font-display);
  font-size: var(--fs-display-2);
  font-weight: var(--fw-bold);
  letter-spacing: var(--tracking-heading);
  color: var(--slate-900);
}
.plan__periodo { font-size: 14px; color: var(--slate-500); }

/* «A la medida» son palabras, no una cifra. Al tamaño del precio se partiría en
   dos renglones y competiría con los números de al lado, que es justo lo que no
   queremos: esta tarjeta no participa de la comparación de precios. */
.plan__monto--medida { font-size: var(--fs-h2); }

/* Lo que cubre el pago de entrada. Va sobre fondo ámbar tenue y no como una
   línea más de texto: es el argumento que separa a este producto de un
   competidor que cobra la infraestructura y el sitio por separado, y enterrado
   entre párrafos grises no lo lee nadie. */
.plan__incluye {
  background: rgba(245, 166, 36, .12);
  border-radius: var(--radius-card);
  padding: 13px 15px;
  font-size: 14px; line-height: 1.5; color: var(--slate-700);
  text-wrap: pretty;
}
.plan__incluye b { font-weight: var(--fw-semibold); color: var(--text-heading); }

/* LA RENOVACIÓN SE LEE COMO UN PRECIO, NO COMO UNA NOTA AL PIE. Estaba en 14px
   y en gris medio, del mismo tamaño que una aclaración legal — y una sección
   que se titula «un precio claro, sin sorpresas» no puede achicar justamente la
   cifra que el cliente va a pagar todos los años. Queda subordinada al pago de
   entrada por tamaño, que es la jerarquía correcta, pero se lee de lejos. */
.plan__renovacion {
  display: flex; flex-direction: column; gap: 1px;
  margin-top: 18px;
  padding-bottom: 22px; border-bottom: 1px solid var(--border-subtle);
}
.plan__renovacion-etiqueta { font-size: 13px; color: var(--slate-500); }
.plan__renovacion-cifra {
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  font-weight: var(--fw-semibold);
  color: var(--text-heading);
}
.plan__renovacion-periodo { font-size: 14px; font-weight: var(--fw-medium); color: var(--slate-500); }

.plan__lista { margin: 22px 0 26px; display: flex; flex-direction: column; gap: 11px; }
.plan__lista li { display: flex; align-items: flex-start; gap: 11px; font-size: 14px; line-height: 1.5; color: var(--slate-600); }
/* Ámbar 700, el más oscuro del sistema: es un icono, así que le basta 3:1 —
   como texto no llegaría. */
.plan__lista .icon { color: var(--amber-700); margin-top: 2px; }

/* `margin-top: auto` empuja el botón al pie aunque las tarjetas queden de
   distinto alto, así los dos quedan alineados entre sí. */
.plan .btn { margin-top: auto; align-self: flex-start; }

/* El paquete de usuarios extra va en su propia franja y no dentro de las
   tarjetas: aplica igual a los dos planes, y repetirlo en ambas lo convertiría
   en una diferencia donde no la hay. */
.extra {
  margin-top: 24px;
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 14px 26px;
  background: var(--surface-card);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-card);
  padding: 20px 26px;
}
.extra__titulo {
  font-family: var(--font-display);
  font-size: var(--fs-h4); font-weight: var(--fw-semibold);
  color: var(--text-heading);
}
.extra__texto { font-size: 14px; color: var(--slate-500); text-wrap: pretty; }
.extra__cifra {
  font-family: var(--font-display);
  font-size: var(--fs-h3); font-weight: var(--fw-semibold);
  color: var(--text-heading);
  white-space: nowrap;
}
.extra__periodo { font-size: 14px; font-weight: var(--fw-medium); color: var(--slate-500); }

.planes__nota { margin-top: 22px; font-size: 14px; color: var(--slate-500); text-wrap: pretty; }

.compare { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr)); gap: 20px; }
.compare__col { border-radius: var(--radius-card); padding: 28px 30px; }
.compare__col--before { background: var(--surface-page); border: 1px solid var(--border-default); }
/* La columna «con Landra» va oscura y encendida contra la «antes», que queda
   pálida. El contraste entre las dos cuenta la comparación sin una palabra.
   El resplandor nace del borde ámbar superior y cae hacia el centro: no es un
   degradado decorativo suelto, es esa regla de acento difundiéndose. */
.compare__col--after {
  /* EL RADIO VA EN PÍXELES Y NO EN PORCENTAJE, y es una decisión medida. El
     resplandor aclara el fondo, y sobre fondo aclarado la palomita verde cae de
     4.41:1 a 2.64:1 — por debajo del 3:1 que pide un icono con significado. La
     lista arranca a 77px del borde superior, así que el brillo se apaga a los
     66px y nunca la alcanza. En porcentaje crecería con la altura de la tarjeta
     y volvería a taparlas en las pantallas donde no estoy mirando. */
  background:
    radial-gradient(340px 95px at 50% 0%, rgba(245, 166, 36, .25), transparent 70%),
    var(--slate-800);
  border: 1px solid var(--slate-600);
  border-top: 2px solid var(--accent);
  box-shadow: var(--shadow-md);
}
.compare__title {
  font-size: 17px; font-weight: var(--fw-semibold);
  padding-bottom: 12px; margin-bottom: 8px;
  border-bottom: 1px solid var(--border-default);
}
.compare__col--before .compare__title { color: var(--slate-500); }
.compare__col--after  .compare__title { color: var(--white); border-bottom-color: var(--slate-600); }
.compare li { display: flex; align-items: center; gap: 12px; padding: 9px 0; font-size: var(--fs-body); }
.compare__col--before li { color: var(--slate-500); }
.compare__col--before .icon { color: var(--slate-300); }
.compare__col--after li { color: var(--white); font-weight: var(--fw-medium); }
.compare__col--after .icon { color: var(--green-500); }

/* ============ CTA FINAL ============ */

.cta { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 22px; }
.cta__logo { height: 44px; width: auto; }
.cta__title {
  font-size: clamp(30px, 3.6vw, 42px);
  font-weight: var(--fw-bold);
  letter-spacing: var(--tracking-display);
  line-height: 1.12;
  color: var(--white);
  text-wrap: balance;
  margin-top: 14px;
}
.cta__lead { max-width: 560px; font-size: 17px; line-height: var(--lh-relaxed); color: var(--slate-300); text-wrap: pretty; }

/* ============ FORMULARIO ============ */

.form {
  margin-top: 48px;
  background: var(--surface-card);
  border: 1px solid var(--border-subtle);
  border-top: 2px solid var(--accent);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-lg);
  padding: 30px;
  text-align: left;
}
.form__title {
  font-size: var(--fs-h3); font-weight: var(--fw-semibold);
  color: var(--text-heading); margin-bottom: 20px;
}
.form__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); gap: 16px; }

.field { display: flex; flex-direction: column; gap: 6px; }
.field--full { grid-column: 1 / -1; }
.field label {
  font-family: var(--font-display); font-size: var(--fs-body-sm);
  font-weight: var(--fw-semibold); color: var(--slate-700);
}
.field input, .field select, .field textarea {
  height: 38px; padding: 0 12px;
  font-family: var(--font-sans); font-size: var(--fs-body); color: var(--text-body);
  background: var(--surface-card);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-control);
  transition: var(--transition-control);
}
.field textarea { height: auto; padding: 10px 12px; resize: vertical; }
.field input:hover, .field select:hover, .field textarea:hover { border-color: var(--border-strong); }
.field input:focus, .field select:focus, .field textarea:focus { outline: none; border-color: var(--border-focus); box-shadow: var(--focus-ring); }

/* ============ ASISTENTE VIRTUAL ============
   La sección va en oscuro para que se lea como lo que es: un módulo aparte,
   no una función más del plan. Cae entre la comparativa (blanca) y los planes
   (gris), así que además alterna bien.

   `.feature` está hecho para fondo claro —título casi negro, texto slate-500—
   y acá sería ilegible. La variante sube a (0,2,0) anidando bajo el modificador
   y no depende del orden del archivo. */
.features--inverse .feature__title { color: var(--white); }
.features--inverse .feature__text { color: var(--slate-200); }
.features--inverse .feature__icon {
  background: rgba(245, 166, 36, .12);
  border-color: rgba(245, 166, 36, .30);
  color: var(--amber-400);
}

/* El avatar del asistente vive pegado al título: círculo fijo que no se
   deforma (`object-fit: cover`) y que no se encoge si el título crece. */
#asistente .section__head { max-width: 760px; }
.asistente__encabezado { display: flex; align-items: center; gap: 22px; }
.asistente__avatar { flex: 0 0 auto; width: 88px; height: 88px; border-radius: 50%; object-fit: cover; background: var(--slate-800); border: 2px solid rgba(245,166,36,.35); }
/* En móvil el círculo pasa ARRIBA del título: al lado le robaba ancho y el
   título caía en cuatro renglones. */
@media (max-width: 640px) { .asistente__encabezado { flex-direction: column; align-items: flex-start; gap: 16px; } .asistente__avatar { width: 72px; height: 72px; } }
.asistente__listas { margin-top: 64px; align-items: start; }
.asistente__subtitulo {
  font-size: var(--fs-h4); font-weight: var(--fw-semibold);
  color: var(--white);
  margin-bottom: 6px;
}

/* El precio y su alcance en una sola caja: lo que incluye y lo que no se leen
   junto al número, no en una nota aparte. */
.asistente__precio {
  margin-top: 56px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
  align-items: center;
  gap: 22px 36px;
  background: var(--slate-800);
  border: 1px solid var(--slate-600);
  border-top: 2px solid var(--accent);
  border-radius: var(--radius-card);
  padding: 28px 30px;
}
.asistente__monto {
  font-family: var(--font-display);
  font-size: var(--fs-display-2); font-weight: var(--fw-bold);
  letter-spacing: var(--tracking-heading);
  color: var(--white);
}
.asistente__monto span { font-family: var(--font-sans); font-size: 14px; font-weight: var(--fw-medium); letter-spacing: 0; color: var(--slate-200); }
.asistente__nota { margin-top: 4px; font-size: 14px; color: var(--slate-200); }

.asistente__alcance { display: flex; flex-direction: column; gap: 8px; font-size: 14px; line-height: 1.5; color: var(--slate-200); }
.asistente__alcance b { color: var(--white); font-weight: var(--fw-semibold); }

/* Reusa el enlace de clientes pero en ámbar claro: el `amber-700` que usa
   sobre fondo claro se perdería sobre el slate-800. */
.asistente__precio .asistente__prueba { color: var(--amber-400); }
.asistente__precio .asistente__prueba:hover { color: var(--amber-300); }

.extra__texto a { color: var(--amber-700); font-weight: var(--fw-semibold); }
.extra__texto a:hover { color: var(--amber-600); }

/* ============ CLIENTES ============
   Lista y no una tarjeta suelta: hoy hay uno y el dia que haya tres se agregan
   `<li>` sin tocar el CSS. `auto-fit` con `min()` para que en telefono caiga a
   una columna en vez de desbordar, como en el resto de las grillas. */
.clientes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
  gap: 20px;
}

.cliente {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 16px 24px;
  background: var(--surface-page);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-card);
  padding: 24px 26px;
}

.cliente__marca { display: flex; align-items: center; gap: 18px; }

/* El logo se acota por ALTO y no por ancho: los logos de los clientes van a
   venir con proporciones distintas —uno apaisado, otro casi cuadrado— y fijar
   el ancho los dejaria de tamanos visuales dispares. Con el alto parejo se leen
   con la misma jerarquia aunque midan cosas distintas. */
.cliente__logo { height: 46px; width: auto; max-width: 160px; object-fit: contain; }

.cliente__nombre { font-size: var(--fs-h3); font-weight: var(--fw-semibold); color: var(--text-heading); }
.cliente__lugar { margin-top: 3px; font-size: 14px; color: var(--slate-500); }

.cliente__enlace {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font-display);
  font-size: var(--fs-body-sm); font-weight: var(--fw-semibold);
  color: var(--amber-700);
  transition: var(--transition-control);
}
.cliente__enlace:hover { color: var(--amber-600); }
.cliente__enlace:hover .icon { transform: translateX(3px); }
.cliente__enlace .icon { transition: transform var(--dur-fast) var(--ease-out); }

@media (prefers-reduced-motion: reduce) {
  .cliente__enlace:hover .icon { transform: none; }
}

/* ============ GRUPO DE OPCIONES ============
   RADIOS Y NO UN MENÚ, y con cinco opciones cortas la diferencia es medible: se
   ven todas de una —lo que ya dice que se atiende a inmobiliarias de varios
   estados— y elegir es un toque en vez de tres (abrir, desplazar, confirmar).
   Un `select` recién gana desde seis o siete opciones, cuando mostrarlas todas
   empieza a costar más de lo que ahorra.

   LOS SELECTORES VAN ANIDADOS BAJO `.opciones` A PROPÓSITO. `.field label` y
   `.field input` son (0,1,1) y le ganarían en especificidad a una clase sola:
   al radio le pondrían 38px de alto con borde y fondo, y a las pastillas la
   tipografía de una etiqueta. Anidar sube a (0,2,0) y el arreglo no depende de
   dónde esté escrito este bloque. */
.opciones { border: 0; padding: 0; margin: 0; }
/* `min-width: 0` no es decorativo: un `fieldset` trae un mínimo implícito de su
   contenido que desborda la grilla en pantallas angostas. */
.opciones { min-width: 0; }

.opciones .opciones__pregunta {
  padding: 0;
  margin-bottom: 12px;
  font-family: var(--font-display);
  font-size: var(--fs-body-sm); font-weight: var(--fw-semibold);
  color: var(--slate-700);
}

.opciones__lista { display: flex; flex-wrap: wrap; gap: 10px; }

/* EL RADIO SE ESCONDE PERO NO SE ELIMINA. Con `display: none` sale del árbol de
   accesibilidad y del orden de tabulación: el grupo dejaría de poder usarse con
   teclado y el lector de pantalla no lo anunciaría. Así queda invisible y
   plenamente operable. */
.opciones .opciones__radio {
  position: absolute;
  width: 1px; height: 1px;
  opacity: 0;
  margin: 0; padding: 0; border: 0;
  pointer-events: none;
}

.opciones .opciones__pastilla {
  display: inline-flex; align-items: center;
  height: 38px; padding: 0 16px;
  background: var(--surface-card);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-pill);
  font-family: var(--font-sans);
  font-size: var(--fs-body); font-weight: var(--fw-medium);
  color: var(--slate-600);
  cursor: pointer;
  user-select: none;
  transition: var(--transition-control);
}
.opciones .opciones__pastilla:hover { border-color: var(--border-strong); color: var(--slate-800); }

.opciones .opciones__radio:checked + .opciones__pastilla {
  background: var(--slate-900);
  border-color: var(--slate-900);
  color: var(--white);
}

/* El anillo de foco viaja del radio escondido a la pastilla visible: sin esto,
   quien navega con teclado se queda sin saber dónde está parado. */
.opciones .opciones__radio:focus-visible + .opciones__pastilla {
  border-color: var(--border-focus);
  box-shadow: var(--focus-ring);
}

.field__error { font-size: var(--fs-caption); color: var(--status-danger-fg); min-height: 0; }
.field.is-invalid input, .field.is-invalid select, .field.is-invalid textarea { border-color: var(--red-500); }

/* Honeypot: fuera de pantalla, nunca oculto con display:none —
   algunos bots ignoran los campos con display:none. */
.form__trap { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.form__foot { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; margin-top: 24px; }
.form__note { font-size: var(--fs-caption); color: var(--text-muted); }

.form__status { margin-top: 16px; font-size: var(--fs-body-sm); }
.form__status:empty { margin-top: 0; }
.form__status.is-ok    { color: var(--status-success-fg); }
.form__status.is-error { color: var(--status-danger-fg); }

/* Ni éxito ni error: el demo ya existía, o no hay lugar por ahora. Se distingue
   de los otros dos porque pedirle algo distinto al visitante — revisar su
   bandeja, volver más tarde — no es lo mismo que felicitarlo ni que culparlo. */
.form__status.is-aviso { color: var(--status-warning-fg); }

/* ============ AVISO DE RESULTADO ============
   El único lugar del sitio donde el sistema usa transparencia y blur. No es
   licencia: el design system los reserva explícitamente para el scrim de un
   modal, y este es el primer modal que existe. */

.aviso {
  width: min(440px, calc(100vw - 32px));
  padding: 0;
  border: none;
  border-top: 2px solid var(--accent);
  border-radius: var(--radius-dialog);
  background: var(--surface-card);
  box-shadow: var(--shadow-dialog);
  color: var(--text-body);

  opacity: 0;
  transform: translateY(8px);
  transition:
    opacity var(--dur-slow) var(--ease-standard),
    transform var(--dur-slow) var(--ease-standard);
}
.aviso.is-abierto { opacity: 1; transform: none; }

.aviso::backdrop {
  background: rgba(23, 29, 35, .55);
  backdrop-filter: blur(2px);
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease-standard);
}
.aviso.is-abierto::backdrop { opacity: 1; }

.aviso__caja { padding: 30px; display: flex; flex-direction: column; gap: 12px; }

.aviso__titulo {
  font-size: var(--fs-h2);
  font-weight: var(--fw-bold);
  letter-spacing: var(--tracking-heading);
  line-height: var(--lh-snug);
  color: var(--slate-900);
  text-wrap: balance;
}
.aviso__texto { font-size: var(--fs-body); line-height: var(--lh-relaxed); color: var(--slate-500); text-wrap: pretty; }
.aviso__cerrar { align-self: flex-start; margin-top: 10px; }

/* El acento superior toma el color del desenlace: ámbar cuando salió como se
   esperaba, y el ámbar de advertencia cuando hay algo que el visitante tiene
   que saber. Nunca rojo — ninguno de estos casos es un error suyo. */
.aviso--aviso { border-top-color: var(--status-warning-fg); }

/* ============ FICHAS DE BENEFICIO ============
   Mismo mecanismo que el aviso: <dialog> nativo por la trampa de foco, el
   cierre con Escape y la inertización del fondo. Lo que cambia es el contenido
   —imagen propia y texto largo— no la mecánica. */

/* EL `display` VA CONDICIONADO A [open], NO SUELTO EN `.ficha`. El navegador
   oculta los <dialog> cerrados con su propia regla `display: none`; declarar
   `display: flex` sin condición la pisa y las seis fichas cerradas se apilan en
   el flujo, una debajo de otra, después del pie. Eran 3324px de página vacía.
   `.aviso` nunca lo tuvo: no declara `display` y por eso no se notó antes. */
.ficha[open] { display: flex; }

.ficha {
  position: relative;
  /* Mismo ancho útil que una sección: 1160px de `.wrap` más sus 32px de padding
     a cada lado. La ficha se alinea con el resto de la página en vez de flotar
     con una medida propia. */
  width: min(1224px, calc(100vw - 32px));
  max-height: min(86vh, 780px);
  padding: 0;
  border: none;
  border-top: 2px solid var(--accent);
  border-radius: var(--radius-dialog);
  background: var(--slate-900);
  box-shadow: var(--shadow-dialog);
  overflow: hidden;
  color: var(--slate-200);

  opacity: 0;
  transform: translateY(8px);
  transition:
    opacity var(--dur-slow) var(--ease-standard),
    transform var(--dur-slow) var(--ease-standard);
}
.ficha.is-abierto { opacity: 1; transform: none; }

.ficha::backdrop {
  background: rgba(23, 29, 35, .55);
  backdrop-filter: blur(2px);
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease-standard);
}
.ficha.is-abierto::backdrop { opacity: 1; }

/* La imagen queda fija mientras el texto se desplaza: está anclada al diálogo,
   no al contenedor que scrollea. */
.ficha__fondo {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; object-position: center;
  /* LOS TRES z-index SON OBLIGATORIOS. `::before` se genera como primer hijo
     del diálogo, pero la imagen viene después en el documento y sin capas
     declaradas se pinta ENCIMA del velo: la ficha salía a brillo completo con
     el texto ilegible. */
  z-index: 0;
}

/* Velo al 82%. Las cuatro imágenes llegan al blanco puro, que exige 75% para
   que el párrafo conserve 4.5:1; acá la imagen es atmósfera y el texto es el
   contenido, así que el margen extra no cuesta nada. */
/* DEGRADADO LATERAL EN VEZ DE VELO PAREJO. El texto vive a la izquierda, así
   que ahí el oscuro es casi opaco y protege el contraste; hacia la derecha se
   abre y la imagen se ve casi limpia. Un velo uniforme tenía que elegir entre
   texto legible o imagen visible: el degradado da las dos, porque no ocupan el
   mismo lugar. */
.ficha::before {
  content: '';
  position: absolute; inset: 0;
  /* Las paradas acompañan al ancho de la caja: la zona casi opaca llega hasta
     donde termina la segunda columna de texto, y recién ahí se abre. Si se
     ensancha la caja, estos números se mueven con ella. */
  background: linear-gradient(
    90deg,
    rgba(23, 29, 35, .96) 0%,
    rgba(23, 29, 35, .94) 58%,
    rgba(23, 29, 35, .55) 78%,
    rgba(23, 29, 35, .20) 100%
  );
  z-index: 1;
}

.ficha__caja {
  position: relative; z-index: 2;
  display: flex; flex-direction: column; gap: 14px;
  /* El contenido se queda en la zona oscura del degradado. Si se estirara a
     todo el ancho, las últimas líneas caerían sobre la parte clara y perderían
     contraste. */
  width: min(790px, 100%);
  padding: 40px 44px 44px;
  overflow-y: auto;
}

.ficha__titulo {
  font-size: var(--fs-h2);
  font-weight: var(--fw-bold);
  letter-spacing: var(--tracking-heading);
  line-height: var(--lh-snug);
  color: var(--white);
  text-wrap: balance;
}
.ficha__lead { font-size: var(--fs-h3); line-height: var(--lh-relaxed); color: var(--slate-200); text-wrap: pretty; }

/* DOS COLUMNAS CON `columns` Y NO CON GRID. Con columnas el texto fluye hacia
   abajo y recién después salta a la derecha, que es como se lee una lista; una
   rejilla la ordenaría de izquierda a derecha y los puntos quedarían
   entrelazados. Además `columns` no altera el orden del documento, así que un
   lector de pantalla los recorre en el orden escrito. */
.ficha__lista {
  columns: 2;
  column-gap: 36px;
  margin-top: 6px;
}
/* Slate-200 y no slate-300, aunque el 300 se vea más discreto: sobre el fondo
   velado al 82% el 300 da 3.80:1 y el mínimo es 4.5. Es el texto más chico de
   la ficha —13px— que es justo donde el contraste importa más. */
.ficha__lista li {
  position: relative;
  /* `break-inside` es obligatorio con columnas: sin él un punto se parte por la
     mitad y sus dos renglones quedan en columnas distintas. */
  break-inside: avoid;
  padding-left: 20px;
  margin-bottom: 14px;
  font-size: var(--fs-h4);
  line-height: var(--lh-relaxed);
  color: var(--slate-200);
  text-wrap: pretty;
}
.ficha__lista li:last-child { margin-bottom: 0; }
/* El marcador es la regla de 2px ámbar del sistema, no una viñeta genérica. */
.ficha__lista li::before {
  content: '';
  position: absolute; left: 0; top: .68em;
  width: 8px; height: 2px;
  background: var(--accent);
}

/* La X va sobre la zona clara del degradado, así que necesita su propio
   respaldo: el ámbar de los botones se lo da y de paso la vuelve el único
   elemento accionable evidente de la ficha. */
.ficha__x {
  position: absolute; top: 16px; right: 16px; z-index: 3;
  width: 40px; height: 40px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--accent);
  color: var(--text-on-accent);
  border: none;
  border-radius: var(--radius-pill);
  cursor: pointer;
  box-shadow: var(--shadow-md);
  transition: var(--transition-control);
}
.ficha__x:hover { background: var(--accent-hover); }
.ficha__x:active { background: var(--accent-press); }
.ficha__x .icon { font-size: 18px; }

@media (max-width: 900px) {
  /* Sin ancho para separar texto e imagen, el degradado lateral dejaría las
     líneas largas sobre la zona clara. Vuelve el velo parejo. */
  .ficha::before { background: rgba(23, 29, 35, .88); }
  .ficha__caja { width: 100%; padding: 30px 24px 32px; }
  .ficha__x { top: 12px; right: 12px; width: 36px; height: 36px; }
  /* Una columna: partir en dos un ancho de teléfono deja renglones de cinco
     palabras, que se leen peor que una lista larga. */
  .ficha__lista { columns: 1; }
}

/* ============ FOOTER ============ */

.site-footer { background: var(--slate-900); border-top: 1px solid var(--slate-800); padding: 46px 32px 26px; }
.site-footer__inner {
  max-width: 1160px; margin: 0 auto;
  display: grid;
  /* COLUMNAS IGUALES Y CON `min()`, y las dos cosas por el mismo motivo.
     Acá decía `minmax(240px, 1.4fr) repeat(auto-fit, minmax(170px, 1fr))` para
     darle más aire a la columna de marca. Pero esa primera pista tenía un
     mínimo DURO de 240px que `auto-fit` no puede colapsar —sólo colapsa pistas
     vacías—, así que en un teléfono de 375px el pie pedía 240 + 40 de gap + 170
     = 450 sobre 311 disponibles y desbordaba 139px. Con el documento más ancho
     que la pantalla, el navegador se aleja para que entre y TODA la página se
     ve chica y angosta.
     `min(220px, 100%)` hace que el mínimo nunca supere al contenedor, y con
     todas las pistas iguales `auto-fit` cae a una sola columna cuando no entran
     dos. Sin media query y sin un ancho que mantener. */
  grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr));
  gap: 34px 40px;
}
.site-footer img { height: 26px; width: auto; opacity: .9; }

.site-footer__lema { margin-top: 14px; font-size: var(--fs-body-sm); color: var(--slate-400); max-width: 320px; text-wrap: pretty; }

.site-footer__titulo {
  font-family: var(--font-display);
  font-size: var(--type-eyebrow-size);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--type-eyebrow-tracking);
  text-transform: uppercase;
  /* Slate-300 y no slate-400: el 400 sobre el slate-900 del pie se queda en
     3.97:1. Es texto chico aunque vaya en versalitas, así que le corresponde
     4.5 y no 3. */
  color: var(--slate-300);
  margin-bottom: 14px;
}
.site-footer__lista { display: flex; flex-direction: column; gap: 9px; }
/* Slate-200 y no slate-400: sobre el slate-900 del pie, el 400 se queda en
   4.1:1 y no llega al mínimo. El 400 alcanza para los rótulos, que son texto
   grande en versalitas, no para los enlaces. */
.site-footer__lista a { font-size: var(--fs-body-sm); color: var(--slate-200); transition: var(--transition-control); }
.site-footer__lista a:hover { color: var(--white); }

.site-footer__legal {
  max-width: 1160px; margin: 34px auto 0;
  padding-top: 22px; border-top: 1px solid var(--slate-800);
  font-size: var(--fs-body-sm); color: var(--text-muted);
}

/* ============ BOTÓN DE WHATSAPP ============
   VA EN EL VERDE DE LA MARCA Y NO EN EL ÁMBAR DEL SISTEMA, que es la única
   excepción de color en todo el sitio y está tomada a propósito. Un botón de
   WhatsApp que no es verde deja de reconocerse de un vistazo, y lo que hace
   valioso a ese botón es justamente que no haya que leerlo. */
.wasap {
  position: fixed; right: 20px; bottom: 20px; z-index: 60;
  width: 54px; height: 54px; border-radius: var(--radius-pill);
  background: #25D366; color: var(--white);
  display: flex; align-items: center; justify-content: center;
  /* EL ANILLO NO ES ADORNO: es lo que hace identificable al control. El verde
     de marca contra una sección blanca da 1.96:1, por debajo del 3:1 que pide
     un componente de interfaz, así que sobre fondo claro el botón se
     desdibujaba. El anillo verde oscuro aporta ese borde —4.19:1 contra el
     fondo de página— sin tocar el color que lo vuelve reconocible.
     El glifo blanco sobre el verde queda en 1.98:1 y eso NO se puede arreglar
     sin dejar de parecer WhatsApp: invertirlo o oscurecerlo rompe justo lo que
     hace útil a este botón, que es reconocerse sin leerse. Se acepta a
     conciencia, con el `aria-label` cubriendo a quien no lo distinga. */
  box-shadow: 0 0 0 2px #128C7E, 0 6px 20px rgba(23, 29, 35, .28);
  transition: transform var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}
.wasap:hover { color: var(--white); transform: translateY(-2px); box-shadow: 0 0 0 2px #128C7E, 0 10px 26px rgba(23, 29, 35, .34); }
/* El glifo de WhatsApp es una silueta rellena, no un trazo como el resto del
   set: hay que revertir lo que `.icon` da por sentado. */
.wasap .icon { width: 27px; height: 27px; font-size: 27px; fill: currentColor; stroke: none; }

@media (prefers-reduced-motion: reduce) {
  .wasap:hover { transform: none; }
}

/* Aire al final para que el botón flotante no se apoye sobre los enlaces del
   pie. Al llegar abajo de todo el botón queda justo encima de la última línea,
   y en pantalla angosta ahí viven el correo y el propio WhatsApp — o sea que
   taparía el enlace que duplica. */
@media (max-width: 720px) {
  .site-footer { padding-bottom: 96px; }
}

/* ============ REVELADO AL SCROLL ============
   El estado inicial se aplica solo si JS está disponible (clase en <html>):
   sin JS el contenido queda visible, nunca en blanco. */

/* Tres cosas son variables para que cada sección pueda tener su propia entrada
   sin duplicar reglas: de dónde entra, cuánto tarda y cuánto se separa un
   elemento del siguiente. El default es el de siempre — sube 16px, 320ms, 80ms
   de paso — y una sección sólo declara lo que quiera cambiar. */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(var(--reveal-y, 16px));
  --reveal-espera: calc(var(--reveal-delay, 0) * var(--reveal-paso, 80ms));
  /* EL RETARDO VA DENTRO DEL ATAJO, POR PROPIEDAD, y ya no en un
     `transition-delay` suelto. Suelto alcanza a TODA propiedad que se anime en
     el elemento, ahora o el día de mañana: la sexta tarjeta de beneficios
     esperaba sus 400ms de escalonado antes de responder al puntero. El
     escalonado es de la entrada, no de todo lo que le pase al elemento después.

     `translate` y `box-shadow` están acá porque el hover de las tarjetas los
     usa y esta regla reemplaza la `transition` que declaran ellas. Para lo que
     no los anima no cuestan nada. */
  transition:
    opacity var(--reveal-dur, var(--dur-slow)) var(--ease-standard) var(--reveal-espera),
    transform var(--reveal-dur, var(--dur-slow)) var(--ease-standard) var(--reveal-espera),
    translate var(--dur-base) var(--ease-out),
    box-shadow var(--dur-base) var(--ease-out);
}
.js [data-reveal].is-revealed { opacity: 1; transform: none; }

/* Entra desde la derecha en vez de desde abajo. */
.js [data-reveal="derecha"] { transform: translateX(var(--reveal-x, 28px)); }
.js [data-reveal="izquierda"] { transform: translateX(calc(var(--reveal-x, 28px) * -1)); }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .js [data-reveal] { opacity: 1; transform: none; transition: none; }
  /* La sombra se queda —no es movimiento—, el salto no. */
  .card:hover, .card:focus-within { translate: none; }
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ============ RESPONSIVE ============ */

@media (max-width: 900px) {
  .mockup__split, .board__split { grid-template-columns: 1fr; }
  .section { padding: 72px 24px; }
  .section--after-mockup { padding-top: 120px; }
  .hero { padding: 64px 24px 0; }
  .wrap--split { gap: 40px; }
}

@media (max-width: 720px) {
  .site-header__inner { padding: 0 20px; }
  .site-header__cta { display: none; }
  .site-header__toggle { display: inline-flex; }

  .site-nav {
    position: absolute; left: 0; right: 0; top: 64px;
    flex-direction: column; align-items: stretch; gap: 0;
    background: var(--surface-card);
    border-bottom: 1px solid var(--border-subtle);
    box-shadow: var(--shadow-md);
    display: none;
  }
  .site-nav.is-open { display: flex; }
  .site-nav a { padding: 14px 20px; border-bottom: 1px solid var(--border-subtle); font-size: var(--fs-body); }

  /* A 56px el logo ocupaba el 82% del ancho útil y competía con el titular.
     A 44px queda presente sin disputarle la primera lectura. */
  .hero__logo { height: 48px; }

  /* Los 48px de padding lateral dejaban 230px útiles en una pantalla de 375 y
     partían el titular en cuatro líneas. El panel importa por su respaldo, no
     por su margen interno. */
  .hero__panel { padding: 28px 22px 32px; gap: 18px; }

  .mockup { margin-bottom: -40px; }
  .mockup__rail { display: none; }
  .section--after-mockup { padding-top: 92px; }

  .section__title { font-size: 27px; }
  .module { width: 100%; }
  .bars__name { width: 110px; }
  .form { padding: 22px; }
}
