/* ═══════════════════════════════════════════════════════════════
   ZentoraAI — capa "definitiva"

   Va DESPUÉS de estilos.css. Aquello es la base heredada que ya
   funcionaba y que no interesa reescribir; esto es lo que cambia la
   cara de la página: titulares en serif, hero claro con degradado
   animado, y todas las animaciones de scroll.

   Regla que se ha seguido aquí: el fondo se queda blanco. El color
   entra por los titulares, por el foco del hero y por el tono propio
   de cada módulo — nunca tiñendo secciones enteras, que es lo que
   convertía la landing anterior en una sucesión de bandas grises.
   ═══════════════════════════════════════════════════════════════ */


/* ─────────────────────────────────────────────────────────────
   1. Tokens que se añaden a los de estilos.css

   No se toca ninguno de los que ya había. --accent (#4A6FA5) sigue
   mandando en botones, enlaces, foco y nav: es el color de marca, el
   mismo que trae la app por defecto (js/51-marca.js). Lo que se añade
   es un degradado SOLO para titulares grandes, hecho con los dos
   colores que ya tiene la marca: el azul y el salvia.
   ───────────────────────────────────────────────────────────── */

:root {
  /* El degradado de los titulares sale de la paleta que YA tiene la
     casa: el azul pizarra de marca (--accent, el mismo que trae la app
     por defecto en js/51-marca.js) abriendo hacia el verde salvia
     (--green). Nada de índigo ni violeta: aquel venía de landing-nueva,
     donde el fondo era negro, y sobre blanco cantaba como un color de
     otra empresa.

     Contraste sobre blanco: 8,1:1, 5,1:1 y 4,3:1. Los tres pasan de
     sobra, así que el titular se lee entero y no solo por el principio. */
  --display-1: #2F4A6D;   /* azul profundo: es también el respaldo */
  --display-2: #4A6FA5;   /* el azul de marca */
  --display-3: #4E9375;   /* salvia, para que el final respire */

  --grad-display: linear-gradient(100deg, #2F4A6D 0%, #4A6FA5 46%, #4E9375 100%);

  --serif: 'Fraunces', Georgia, 'Times New Roman', serif;
  --mono: ui-monospace, SFMono-Regular, 'Roboto Mono', Menlo, Consolas, monospace;

  /* El easing de landing-nueva. Pasa de largo y vuelve: es lo que hace
     que las entradas parezcan físicas y no un fundido. */
  --spring: cubic-bezier(.34, 1.56, .64, 1);
  --suave: cubic-bezier(.16, 1, .3, 1);
}


/* ─────────────────────────────────────────────────────────────
   2. Tipografía de titulares

   El patrón es el de landing-nueva: primera línea en redonda, segunda
   en cursiva y en degradado. En el marcado se escribe

     <h2>Del coche en el patio<br><em>a la factura</em></h2>

   y el <em> se encarga de saltar de línea y de pintarse.
   ───────────────────────────────────────────────────────────── */

h1, h2, .display {
  font-family: var(--serif);
  font-weight: 500;
  letter-spacing: -0.015em;
  line-height: 1.04;
}

h1 { font-size: clamp(2.4rem, 6vw, 4.4rem); }
h2 { font-size: clamp(2rem, 4.6vw, 3.4rem); margin-bottom: 18px; }
h3 { letter-spacing: -0.015em; }

/* El degradado sobre texto. El color plano NO es decorativo: es lo que
   se ve si el recorte de fondo no aplica, y por eso es el extremo
   oscuro del degradado (#2F4A6D, 8,1:1) y no el claro. Sin la regla de
   @supports, un motor sin background-clip pinta el titular invisible. */
h1 em, h2 em, .deg {
  display: block;
  font-style: italic;
  font-weight: 600;
  color: var(--display-1);
  background-image: var(--grad-display);
  -webkit-background-clip: text;
  background-clip: text;

  /* El degradado se recorta a la CAJA del elemento, no a la letra. Con
     line-height 1.04 y una serif en cursiva, el rabo de la «y» o de la
     «g» se sale por debajo de esa caja: ahí ya no hay fondo que
     recortar, así que el trazo sale transparente y parece cortado.

     Se le da aire por abajo y se descuenta con el margen, para que la
     caja cubra el rabo sin mover nada de sitio. */
  line-height: 1.14;
  padding-bottom: 0.14em;
  margin-bottom: -0.14em;
}
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  h1 em, h2 em, .deg { -webkit-text-fill-color: transparent; }
}

/* Alto contraste de Windows e impresión. Los dos ignoran la imagen de
   fondo pero respetan el recorte, así que sin esto el titular sale en
   blanco sobre blanco — en pantalla y en papel. */
@media (forced-colors: active), print {
  h1 em, h2 em, .deg {
    background-image: none;
    -webkit-text-fill-color: currentColor;
    color: var(--display-1);
  }
}

/* La entradilla baja de tamaño y de peso: el titular ya carga el
   golpe visual, y el texto de apoyo tiene que leerse de un vistazo. */
.entradilla { font-size: clamp(1rem, 1.5vw, 1.125rem); max-width: 58ch; }
.cabecera { margin-bottom: 48px; }

/* Etiqueta superior en monoespaciada. Es el detalle que más "producto
   de software" aporta y no cuesta nada. */
.etiqueta {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.14em;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-3);
}
.etiqueta--mint { border-color: rgba(127, 184, 164, .5); }


/* ─────────────────────────────────────────────────────────────
   3. Hero claro

   La forma es la del hero oscuro de landing-nueva —tarjeta redondeada
   a pantalla completa, clara por el centro y con peso hacia los
   bordes— pero en blanco: un núcleo blanco puro detrás del titular,
   tintes del azul de marca y del salvia por las esquinas y una base
   apenas más oscura que el papel.

   La malla es UN solo elemento con cuatro radiales; la animación solo
   mueve las posiciones. No hay orbes, ni blur, ni filtros: en un
   portátil corriente esto no mueve la aguja de la CPU. Lo que responde
   al ratón es el canvas de encima, que se apaga solo cuando se deja de
   mover el puntero.
   ───────────────────────────────────────────────────────────── */

.hero {
  position: relative;
  margin: 12px;
  padding: calc(var(--nav-h) + 72px) 0 72px;
  min-height: calc(100svh - 24px);
  display: flex;
  align-items: center;
  border-radius: 36px;
  overflow: hidden;
  text-align: center;

  /* La estructura es la del hero oscuro —claro en el centro, con peso
     hacia los bordes— pero en blanco. El primer radial es un núcleo
     blanco puro justo detrás del titular; los tres de fuera son tintes
     del azul de marca y del salvia a muy baja opacidad, y la base es un
     gris azulado apenas más oscuro que el papel.

     Antes esto llevaba tintes de índigo y periwinkle al 16-18 % y salía
     lila. Aquí ninguno pasa del 9 %, y el color solo se nota en las
     esquinas: el centro es blanco. */
  background:
    radial-gradient(ellipse 70% 60% at 50% 42%, #FFFFFF 0%, rgba(255,255,255,0) 70%),
    radial-gradient(circle at 84% 16%, rgba(127, 184, 164, .10) 0%, transparent 58%),
    radial-gradient(circle at 14% 82%, rgba(74, 111, 165, .09) 0%, transparent 60%),
    radial-gradient(circle at 88% 88%, rgba(74, 111, 165, .07) 0%, transparent 55%),
    #F2F5F9;
  background-repeat: no-repeat;
  background-size: 160% 160%, 150% 150%, 150% 150%, 150% 150%, auto;
  animation: hero-deriva 26s ease-in-out infinite alternate;
}

@keyframes hero-deriva {
  0%   { background-position: 50% 42%, 0% 0%, 0% 0%, 0% 0%, 0 0; }
  100% { background-position: 50% 42%, -9% 7%, 8% -6%, -7% -8%, 0 0; }
}

/* El rastro del ratón. Es el mismo efecto que en landing-nueva: no un
   foco que sigue al puntero, sino un trazo que se PINTA al moverlo y se
   va borrando solo por detrás.

   Un canvas transparente encima de la malla. Cada fotograma se borra un
   8 % con destination-out, que es lo que deja la estela; si se pintara
   un color encima, el degradado del hero desaparecería debajo.

   La diferencia con el original: allí el canvas iba con mix-blend-mode
   screen y composición "lighter", porque el fondo era negro y el trazo
   tenía que SUMAR luz. Sobre blanco eso es invisible — sumar luz al
   blanco da blanco. Aquí va en multiply, así que el trazo oscurece. */
/* El halo antiguo de estilos.css sobra: la malla ya hace ese trabajo. */
.hero::before { content: none; }

.hero__estela {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  filter: blur(6px);
  mix-blend-mode: multiply;
  opacity: .85;
}

/* Retícula de puntos finísima. Sobre blanco no se "ve", se nota: le
   quita al fondo el aspecto de papel liso. */
.hero::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: .5;
  background-image: radial-gradient(circle at 1px 1px, rgba(31, 41, 51, .10) 1px, transparent 0);
  background-size: 4px 4px;
  mask-image: radial-gradient(ellipse at 50% 45%, #000 20%, transparent 72%);
  -webkit-mask-image: radial-gradient(ellipse at 50% 45%, #000 20%, transparent 72%);
}

.hero__contenido { position: relative; z-index: 1; max-width: 940px; }

.hero h1 { margin-bottom: 24px; }
.hero h1 em { font-size: 1em; }

.hero__sub {
  font-size: clamp(1.0625rem, 1.8vw, 1.25rem);
  max-width: 620px;
  margin: 0 auto 32px;
}

/* Línea de credenciales bajo los botones, en monoespaciada: dice tres
   hechos comprobables en el ancho de una línea. */
.hero__pie {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-3);
  gap: 12px;
}

@media (max-width: 640px) {
  .hero { margin: 8px; border-radius: 24px; padding: calc(var(--nav-h) + 44px) 0 52px; }
}


/* ─────────────────────────────────────────────────────────────
   4. Entradas al hacer scroll

   Se sustituye el .reveal de estilos.css (12px y opacidad) por el de
   landing-nueva, que es bastante más presente: sube 48px, escala y
   desenfoca. El escalonado entre hermanos lo pone animaciones.js
   como transition-delay en línea.
   ───────────────────────────────────────────────────────────── */

.reveal {
  opacity: 0;
  transform: translateY(48px) scale(.96);
  filter: blur(4px);
  transition:
    opacity .7s ease,
    transform .9s var(--spring),
    filter .6s ease;
}
.reveal.visible { opacity: 1; transform: none; filter: blur(0); }

/* Sin JS no hay observador que las encienda: se ven todas y ya. */
html:not(.js) .reveal { opacity: 1; transform: none; filter: none; }

/* La captura del panel entra inclinada y se endereza. Es el único
   sitio donde se usa perspectiva, precisamente para que destaque. */
.hero__mockup.reveal {
  transform: translateY(56px) rotateX(9deg) scale(.95);
  transform-origin: 50% 0;
}
.hero__mockup.reveal.visible { transform: none; }
#producto { perspective: 1400px; padding-top: 0; }


/* ─────────────────────────────────────────────────────────────
   5. "Cómo funciona": la ruta

   Aquí había un carril que se desplazaba de lado conforme bajabas,
   con 240vh de caja y un sticky dentro. Se ha tirado entero: obligaba
   a scrollear tres pantallas para leer tres frases, y en una página
   que tiene que verse en un minuto eso es justo lo contrario de lo
   que se busca.

   Ahora los tres pasos están a la vez en pantalla, en su sitio, y lo
   único que se anima es la LÍNEA que los une: se dibuja de izquierda
   a derecha al entrar la sección, y los hitos se van encendiendo
   detrás de ella. Se sigue leyendo de izquierda a derecha, que era la
   idea, pero sin robarle el scroll a nadie.

   La línea se dibuja cada vez que la sección entra en pantalla, en
   los dos sentidos: subir y volver a bajar la repite.
   ───────────────────────────────────────────────────────────── */

.ruta {
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 30px;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* El raíl: gris de punta a punta, desde el centro del primer hito
   hasta el centro del último. El 16,66 % es medio tramo de tres. */
.ruta::before,
.ruta::after {
  content: '';
  position: absolute;
  top: 15px;
  left: 16.66%;
  right: 16.66%;
  height: 2px;
  border-radius: 2px;
}
.ruta::before { background: var(--border); }

/* Y encima, el trazo de color que lo recorre. */
.ruta::after {
  background: var(--grad-display);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform 1.4s var(--suave);
}
.ruta.trazada::after { transform: scaleX(1); }

.ruta__paso {
  position: relative;
  padding-top: 46px;
  opacity: 0;
  transform: translateY(16px);
  transition: opacity .6s ease, transform .6s var(--spring);
}
.ruta.trazada .ruta__paso { opacity: 1; transform: none; }

/* Cada hito entra justo cuando el trazo pasa por él. Los retardos son
   fijos y no calculados: son tres, y atarlos al ancho real de la línea
   sería precisión que nadie va a notar. */
.ruta.trazada .ruta__paso:nth-child(1) { transition-delay: .10s; }
.ruta.trazada .ruta__paso:nth-child(2) { transition-delay: .55s; }
.ruta.trazada .ruta__paso:nth-child(3) { transition-delay: 1.0s; }

/* El punto tapa el raíl, por eso lleva fondo propio. */
.ruta__punto {
  position: absolute;
  top: 0;
  left: 50%;
  width: 32px;
  height: 32px;
  margin-left: -16px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--bg);
  border: 2px solid var(--border);
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 700;
  color: var(--text-3);
  transition: border-color .5s ease, color .5s ease, transform .5s var(--spring);
}
.ruta.trazada .ruta__paso:nth-child(1) .ruta__punto { transition-delay: .10s; }
.ruta.trazada .ruta__paso:nth-child(2) .ruta__punto { transition-delay: .55s; }
.ruta.trazada .ruta__paso:nth-child(3) .ruta__punto { transition-delay: 1.0s; }
.ruta.trazada .ruta__punto {
  border-color: var(--display-2);
  color: var(--display-1);
  transform: scale(1.08);
}

.ruta__paso h3 {
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(1.35rem, 2.4vw, 1.85rem);
  line-height: 1.12;
  margin-bottom: 10px;
  text-align: center;
}
.ruta__paso p {
  color: var(--text-2);
  font-size: 15.5px;
  text-align: center;
  max-width: 34ch;
  margin: 0 auto;
}

/* En móvil la ruta se pone de pie: el raíl pasa a ser vertical y baja
   por la izquierda, que es como se lee una lista de pasos en un
   teléfono. */
@media (max-width: 860px) {
  .ruta { grid-template-columns: 1fr; gap: 0; }

  .ruta::before,
  .ruta::after {
    top: 15px;
    bottom: 40px;
    left: 15px;
    right: auto;
    width: 2px;
    height: auto;
  }
  .ruta::after { transform: scaleY(0); transform-origin: 50% 0; }
  .ruta.trazada::after { transform: scaleY(1); }

  .ruta__paso { padding: 0 0 34px 52px; }
  .ruta__punto { left: 15px; margin-left: -16px; }
  .ruta__paso h3, .ruta__paso p { text-align: left; margin-left: 0; }
  .ruta__paso:last-child { padding-bottom: 0; }
}


/* ─────────────────────────────────────────────────────────────
   6. Módulos: lista + visor

   Aquí había una rejilla de 3x2 con seis tarjetas idénticas. El
   problema no era el color, era la forma: seis cajas iguales del mismo
   tamaño se leen como una mancha.

   Ahora solo hay un módulo activo, y su diagrama ocupa la mitad
   derecha. La regla que manda en esta sección es que LOS SEIS TIENEN
   QUE CABER A LA VEZ EN PANTALLA: si hay que bajar para ver el sexto,
   el visor ya se ha ido por arriba y el invento no sirve de nada.

   Eso se consigue plegando el texto de los módulos que no están
   activos: se ve el título de los seis y el texto solo del que toca.
   ───────────────────────────────────────────────────────────── */

.mods {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: 30px;
  align-items: center;   /* el visor se centra contra la lista */
}


/* ── La lista ─────────────────────────────────────────────── */

.mods__lista { display: flex; flex-direction: column; gap: 4px; }

.mods__item {
  --tono: var(--accent);
  position: relative;
  display: flex;
  gap: 13px;
  align-items: flex-start;
  width: 100%;
  text-align: left;
  padding: 13px 18px 13px 20px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--r-lg);
  cursor: pointer;
  font: inherit;
  color: inherit;
  transition: background .3s ease, border-color .3s ease;
}

/* La barra de la izquierda crece de arriba abajo al activarse: así el
   cambio de módulo tiene dirección en vez de aparecer y ya. */
.mods__item::before {
  content: '';
  position: absolute;
  top: 12px;
  bottom: 12px;
  left: 0;
  width: 3px;
  border-radius: 3px;
  background: var(--tono);
  transform: scaleY(0);
  transform-origin: 50% 0;
  transition: transform .4s var(--suave);
}

.mods__item:hover { background: rgba(255, 255, 255, .65); }
.mods__item:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.mods__item[aria-selected="true"] {
  background: var(--bg);
  border-color: var(--border);
  box-shadow: var(--shadow-sm);
}
.mods__item[aria-selected="true"]::before { transform: scaleY(1); }

.mods__icono {
  width: 30px;
  height: 30px;
  flex-shrink: 0;
  display: grid;
  place-items: center;
  border-radius: 9px;
  background: var(--surface);
  color: var(--text-3);
  transition: background .3s ease, color .3s ease;
}
.mods__icono svg { width: 16px; height: 16px; }
.mods__item[aria-selected="true"] .mods__icono {
  background: color-mix(in srgb, var(--tono) 14%, transparent);
  color: var(--tono);
}

.mods__texto { display: block; min-width: 0; padding-top: 4px; }

.mods__titulo {
  display: block;
  font-size: 1rem;
  font-weight: 600;
  color: var(--text-2);
  transition: color .3s ease;
}
.mods__item[aria-selected="true"] .mods__titulo { color: var(--text); }

/* El texto SOLO se despliega en el módulo activo. Es lo que hace que
   los seis quepan en una pantalla. Se pliega con grid-template-rows de
   0fr a 1fr, que es el único truco que anima una altura desconocida sin
   tener que medirla desde JavaScript — el mismo que ya usa el acordeón
   de la FAQ en estilos.css. */
.mods__desc {
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--text-2);
  transition: grid-template-rows .4s var(--suave), opacity .3s ease;
}
.mods__desc > span { overflow: hidden; }
.mods__item[aria-selected="true"] .mods__desc {
  grid-template-rows: 1fr;
  opacity: 1;
}
.mods__desc .texto { display: block; padding-top: 6px; }

.mods__desc .modulo__aviso {
  display: block;
  margin-top: 6px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-3);
}


/* ── El visor ─────────────────────────────────────────────── */

.mods__visor {
  position: relative;
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  background: var(--bg);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  transition: border-color .4s ease;
}

.mods__panel { padding: 22px; }

.mods__lienzo {
  background: var(--canvas);
  border: 1px solid var(--border);
  border-radius: var(--r);
  padding: 14px;
}

/* El SVG lleva su propia proporción, así que el visor mide siempre lo
   mismo aunque el diagrama de dentro cambie. Sin esto la caja pega un
   salto de alto cada vez que se cambia de módulo. */
.dg { display: block; width: 100%; height: auto; aspect-ratio: 520 / 340; }


/* ── Barra de autoavance ──────────────────────────────────── */

.mods__tiempo {
  grid-column: 1 / -1;
  height: 2px;
  margin-top: 10px;
  border-radius: 2px;
  background: var(--border);
  overflow: hidden;
}
.mods__tiempo i {
  display: block;
  height: 100%;
  width: 100%;
  border-radius: 2px;
  background: var(--grad-display);
  transform: scaleX(0);
  transform-origin: 0 50%;
}
.mods__tiempo i.corre { transition: transform 5.5s linear; transform: scaleX(1); }
.mods.a-mano .mods__tiempo { display: none; }


/* ─────────────────────────────────────────────────────────────
   6 bis. Los diagramas del visor

   Cada módulo enseña lo que hace la app por detrás: de dónde entra la
   información, por dónde pasa y en qué acaba. Las piezas entran
   escalonadas con --paso, y por las líneas viaja un pulso — que es lo
   que hace que se lea como un flujo y no como un esquema quieto.

   Todo arranca cuando el panel se activa. Un diagrama animándose en un
   panel escondido es trabajo tirado.
   ───────────────────────────────────────────────────────────── */

.dg-caja {
  fill: var(--bg);
  stroke: var(--border);
  stroke-width: 1.5;
}
/* La caja de la app: la que hay que mirar en cada dibujo. */
.dg-caja--eje {
  fill: color-mix(in srgb, var(--tono) 10%, var(--bg));
  stroke: var(--tono);
  stroke-width: 2;
}
.dg-caja--tenue { stroke-dasharray: 5 4; opacity: .6; }

.dg-ico { fill: none; stroke: var(--tono); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

.dg-et {
  fill: var(--text-2);
  font-size: 13px;
  font-family: inherit;
}
.dg-et--centro { text-anchor: middle; fill: var(--text); font-weight: 600; }
.dg-et--titulo { fill: var(--text); font-weight: 700; font-size: 13.5px; }
.dg-et--pie { fill: var(--text-3); font-size: 12px; text-anchor: middle; }
.dg-et--cifra {
  fill: var(--tono);
  font-family: var(--serif);
  font-size: 30px;
  font-weight: 600;
  text-anchor: middle;
}
.dg-caja--eje ~ .dg-et--centro { fill: var(--tono); }

.dg-linea { fill: none; stroke: var(--border-h); stroke-width: 1.5; }

/* El pulso: la misma ruta, un guion corto, y el desplazamiento del
   guion animado en bucle. Es la forma más barata de mover algo por un
   camino sin offset-path ni SMIL. */
.dg-flujo {
  fill: none;
  stroke: var(--tono);
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-dasharray: 16 260;
  stroke-dashoffset: 276;
  opacity: 0;
}

/* Piezas y campos entran escalonados. --paso lo pone el marcado. */
.dg-nodo { opacity: 0; }
.dg-campo { fill: var(--border); opacity: 0; }
.dg-barra { fill: var(--border-h); transform: scaleY(var(--alto, 1)); transform-origin: 50% 100%; opacity: 0; }
.dg-barra--eje { fill: var(--tono); }
.dg-barras { transform-box: fill-box; }

/* Y todo arranca solo cuando el panel está activo. */
.mods__panel--activo .dg-nodo {
  animation: dg-entra .5s var(--suave) both;
  animation-delay: calc(var(--paso, 0) * .09s);
}
.mods__panel--activo .dg-campo {
  animation: dg-campo .45s var(--suave) both;
  animation-delay: calc(var(--paso, 0) * .09s);
}
.mods__panel--activo .dg-barra {
  animation: dg-barra .6s var(--suave) both;
  animation-delay: calc(var(--paso, 0) * .09s);
}
.mods__panel--activo .dg-flujo {
  animation: dg-pulso 2.4s linear infinite;
  animation-delay: calc(.4s + var(--paso, 0) * .18s);
}

@keyframes dg-entra {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}
@keyframes dg-campo {
  from { opacity: 0; transform: translateX(-10px); }
  to   { opacity: 1; transform: none; }
}
@keyframes dg-barra {
  from { opacity: 0; transform: scaleY(0); }
  to   { opacity: 1; transform: scaleY(var(--alto, 1)); }
}
@keyframes dg-pulso {
  0%   { stroke-dashoffset: 276; opacity: 0; }
  12%  { opacity: .95; }
  70%  { opacity: .95; }
  100% { stroke-dashoffset: 0; opacity: 0; }
}


@media (max-width: 900px) {
  .mods { grid-template-columns: 1fr; }
  /* El visor primero: el diagrama es lo que se entiende de un vistazo,
     y en un móvil una lista de seis antes de ver nada es una pared. */
  .mods__visor { order: -1; }
}

/* color-mix es reciente. Donde no exista, el icono y la caja de la app
   se quedan con el azul de marca: se pierde el matiz, no la lectura. */
@supports not (color: color-mix(in srgb, red 50%, blue)) {
  .mods__item[aria-selected="true"] .mods__icono { background: var(--accent-bg); color: var(--accent); }
  .dg-caja--eje { fill: var(--accent-bg); }
}

/* Los seis tonos. Salen de la paleta que ya existía —azul de marca,
   salvia, ámbar y rojo teja— más dos apagados del mismo registro, para
   que parezcan la misma familia y no un semáforo. */
.mods__item[data-tono="stock"],     .mods__panel[data-tono="stock"]     { --tono: #4A6FA5; }
.mods__item[data-tono="leads"],     .mods__panel[data-tono="leads"]     { --tono: #4E9375; }
.mods__item[data-tono="expe"],      .mods__panel[data-tono="expe"]      { --tono: #B98429; }
.mods__item[data-tono="factura"],   .mods__panel[data-tono="factura"]   { --tono: #2F4A6D; }
.mods__item[data-tono="portales"],  .mods__panel[data-tono="portales"]  { --tono: #5C8AA6; }
.mods__item[data-tono="analitica"], .mods__panel[data-tono="analitica"] { --tono: #C4665E; }


/* ─────────────────────────────────────────────────────────────
   7. "La misma app, con tu nombre encima"

   Lo que queda del antiguo "a tu medida", que prometía desarrollo a
   medida y no era verdad. Se conserva el widget de pestañas —enseñar
   la misma aplicación con tres marcas distintas es exactamente la
   demostración de lo que sí se hace— y se cae todo el discurso.
   ───────────────────────────────────────────────────────────── */

.medida { padding: 96px 0; }
.medida__intro { max-width: 720px; margin: 0 auto 40px; text-align: center; }
.medida__intro .entradilla { margin-left: auto; margin-right: auto; }

.pestanas { justify-content: center; }

/* Tres hechos en una línea, debajo del mockup. Sustituye a las cinco
   "ventajas" de antes, dos de las cuales prometían cosas que no
   hacemos. */
.marca-hechos {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
  max-width: 900px;
  margin: 36px auto 0;
  text-align: center;
}
.marca-hecho__icono {
  width: 38px; height: 38px;
  margin: 0 auto 12px;
  display: grid; place-items: center;
  border-radius: 11px;
  background: var(--accent-bg);
  color: var(--accent);
}
.marca-hecho h3 { font-size: 1rem; margin-bottom: 4px; }
.marca-hecho p { font-size: 14px; color: var(--text-2); }

/* Las tres demostraciones de arriba de cada hecho. Son CSS puro y no
   arrancan hasta que la lista entra en pantalla: animaciones.js le pone
   .vivo. Un bucle corriendo en una sección que nadie está mirando gasta
   batería para nada.

   Todas duran 6s y van desfasadas 0,8s entre sí para que no latan a la
   vez, que es lo que las haría parecer un cartel de neón. */

.mh-demo {
  height: 96px;
  margin-bottom: 18px;
  display: grid;
  place-items: center;
  border-radius: var(--r);
  background: var(--surface);
  border: 1px solid var(--border);
  overflow: hidden;
}


/* ── 1. La app que se recolorea ──────────────────────────────
   Es lo que hace derivarPaleta() en js/51-marca.js: el cliente elige un
   color y el resto —hover, fondo suave, texto encima— sale de ahí. */

.mh-app {
  --c: #4A6FA5;
  width: 132px;
  border-radius: 7px;
  background: var(--bg);
  border: 1px solid var(--border);
  overflow: hidden;
  transition: none;
}
.mh-app__barra {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 8px;
  background: var(--c);
  transition: background .5s ease;
}
.mh-app__logo { width: 11px; height: 11px; border-radius: 3px; background: rgba(255,255,255,.9); }
.mh-app__nombre { width: 44px; height: 5px; border-radius: 3px; background: rgba(255,255,255,.65); }
.mh-app__cuerpo { padding: 9px 8px; display: grid; gap: 6px; }
.mh-app__boton {
  width: 40px; height: 12px; border-radius: 4px;
  background: var(--c);
  transition: background .5s ease;
}
.mh-app__linea { height: 5px; border-radius: 3px; background: var(--border); }
.mh-app__linea--corta { width: 60%; }

.mh-colores { display: none; }

/* El color va rotando entre los cuatro. Se anima la variable a saltos
   con keyframes en vez de con transiciones encadenadas desde JS. */
.marca-hechos.vivo .mh-app { animation: mh-color 8s ease-in-out infinite; }
@keyframes mh-color {
  0%, 20%   { --c: #4A6FA5; }
  25%, 45%  { --c: #4E9375; }
  50%, 70%  { --c: #B98429; }
  75%, 95%  { --c: #C4665E; }
  100%      { --c: #4A6FA5; }
}
/* Sin @property el navegador no sabe interpolar una custom property y el
   cambio sale a saltos secos. Declararla como <color> deja que la
   transición de background haga el degradado. Donde no exista, se ve el
   salto: menos bonito, igual de legible. */
@property --c {
  syntax: '<color>';
  inherits: true;
  initial-value: #4A6FA5;
}


/* ── 2. Los interruptores ────────────────────────────────────── */

.mh-mods { width: 128px; display: grid; gap: 7px; margin: 0; padding: 0; list-style: none; }
.mh-mods li { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.mh-mods__et { flex: 1; height: 5px; border-radius: 3px; background: var(--border); }

.mh-int {
  position: relative;
  width: 24px;
  height: 13px;
  border-radius: 999px;
  background: var(--border-h);
  flex-shrink: 0;
  transition: background .35s ease;
}
.mh-int::after {
  content: '';
  position: absolute;
  top: 2px; left: 2px;
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--bg);
  transition: transform .35s var(--spring);
}
.mh-int--on { background: var(--green); }
.mh-int--on::after { transform: translateX(11px); }

/* Dos de los cuatro se van encendiendo y apagando por turnos. */
.marca-hechos.vivo .mh-mods li:nth-child(2) .mh-int { animation: mh-enciende 6s ease-in-out infinite; }
.marca-hechos.vivo .mh-mods li:nth-child(3) .mh-int { animation: mh-apaga    6s ease-in-out infinite; }
.marca-hechos.vivo .mh-mods li:nth-child(2) .mh-int::after { animation: mh-pomo-on  6s ease-in-out infinite; }
.marca-hechos.vivo .mh-mods li:nth-child(3) .mh-int::after { animation: mh-pomo-off 6s ease-in-out infinite; }

@keyframes mh-enciende { 0%, 30% { background: var(--border-h); } 45%, 100% { background: var(--green); } }
@keyframes mh-apaga    { 0%, 55% { background: var(--green); } 70%, 100% { background: var(--border-h); } }
@keyframes mh-pomo-on  { 0%, 30% { transform: none; } 45%, 100% { transform: translateX(11px); } }
@keyframes mh-pomo-off { 0%, 55% { transform: translateX(11px); } 70%, 100% { transform: none; } }


/* ── 3. El menú que se reordena ──────────────────────────────── */

.mh-menu {
  position: relative;
  width: 118px;
  height: 74px;
  margin: 0; padding: 0;
  list-style: none;
}
.mh-menu__it {
  position: absolute;
  left: 0;
  width: 100%;
  height: 12px;
  border-radius: 4px;
  background: var(--border);
  transition: transform .55s var(--spring), background .4s ease;
}
.mh-menu__it--1    { top: 0;    }
.mh-menu__it--2    { top: 20px; }
.mh-menu__it--3    { top: 40px; }
.mh-menu__it--sube { top: 60px; width: 72%; }

/* El de abajo sube del todo y los tres de encima bajan un hueco. */
.marca-hechos.vivo .mh-menu__it--sube { animation: mh-sube 6s ease-in-out infinite; }
.marca-hechos.vivo .mh-menu__it--1,
.marca-hechos.vivo .mh-menu__it--2,
.marca-hechos.vivo .mh-menu__it--3 { animation: mh-baja 6s ease-in-out infinite; }

@keyframes mh-sube {
  0%, 25%   { transform: none; background: var(--border); }
  45%, 80%  { transform: translateY(-60px); background: var(--accent); }
  100%      { transform: none; background: var(--border); }
}
@keyframes mh-baja {
  0%, 25%  { transform: none; }
  45%, 80% { transform: translateY(20px); }
  100%     { transform: none; }
}


/* ── La invitación a sugerencias ─────────────────────────────── */

/* Antes esto era un párrafo suelto en gris que nadie leía. Prometer que
   "lo que pidas se estudia" sin dar dónde pedirlo es una promesa sin
   sitio donde cobrarla; ahora lleva a una página que existe. */
.marca-cta {
  max-width: 700px;
  margin: 40px auto 0;
  padding: 26px 30px;
  display: flex;
  align-items: center;
  gap: 26px;
  flex-wrap: wrap;
  justify-content: center;
  text-align: left;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-sm);
}
.marca-cta p { flex: 1; min-width: 260px; font-size: 14.5px; color: var(--text-2); }
.marca-cta b { display: block; color: var(--text); font-size: 16px; margin-bottom: 4px; }
.marca-cta .btn { flex-shrink: 0; gap: 8px; }
.marca-cta .btn svg { width: 16px; height: 16px; transition: transform .25s ease; }
.marca-cta .btn:hover svg { transform: translateX(3px); }

@media (max-width: 700px) {
  .marca-hechos { grid-template-columns: 1fr; gap: 24px; }
  .marca-cta { text-align: center; padding: 22px; }
  .marca-cta .btn { width: 100%; justify-content: center; }
}



/* ─────────────────────────────────────────────────────────────
   8. Comparativa a tres columnas

   Antes eran dos tablas separadas por otras dos secciones en medio, y
   el lector no las relacionaba. Ahora es una sola: la misma necesidad
   resuelta de tres maneras, y la de la derecha se enciende al entrar
   en pantalla.
   ───────────────────────────────────────────────────────────── */

/* Con tres columnas la tabla cabe entera en cualquier portátil: 820px
   de mínimo pasan a 620, y ahí ya no hay scroll lateral. El marco sigue
   siendo el que scrollea si hace falta, nunca la página. */
.comparativa--doble { min-width: 620px; }
.comparativa--doble tbody th { width: 34%; }
.comparativa--doble .antes  { width: 30%; }

/* La columna de Zentora entra apagada y se ilumina cuando la tabla
   está en pantalla: el ojo va solo a donde interesa. */
.comparativa .despues {
  background: transparent;
  transition: background .6s ease, color .6s ease;
}
.comparativa-marco.visible .despues { background: rgba(74, 111, 165, .06); }
.comparativa-marco.visible .despues strong { color: var(--display-1); }

.comparativa thead th:last-child {
  color: var(--display-1);
  background: rgba(74, 111, 165, .09);
}

/* Filas escalonadas. El delay lo pone animaciones.js. */
.comparativa tbody tr {
  opacity: 0;
  transform: translateY(10px);
  transition: opacity .5s ease, transform .5s var(--suave);
}
.comparativa-marco.visible tbody tr { opacity: 1; transform: none; }
html:not(.js) .comparativa tbody tr { opacity: 1; transform: none; }

/* Cierre de la comparativa: la pregunta que hay que hacerse después de
   leer ocho filas, y el botón justo debajo. Es el punto de la página
   donde más convencido está el que ha llegado hasta aquí. */
.comparativa__cierre {
  max-width: 620px;
  margin: 40px auto 0;
  text-align: center;
  display: grid;
  justify-items: center;
  gap: 18px;
}
.comparativa__cierre p { font-size: 17px; color: var(--text-2); }
.comparativa__cierre b { color: var(--text); font-size: 19px; }

@media (max-width: 640px) {
  .comparativa--doble th, .comparativa--doble td { padding: 13px 14px; font-size: 13.5px; }
}


/* ─────────────────────────────────────────────────────────────
   9. Calculadora

   Se conserva entera —la cuenta es la misma— y se le añade lo que le
   faltaba: que se VEA el mordisco. Dos barras a escala comparan el
   margen que creías tener con el que queda.
   ───────────────────────────────────────────────────────────── */

.calc__resultado b { transition: color .25s ease; }
.calc__resultado b.cambia { color: var(--display-2); }

.calc__barras { margin: 20px 0 4px; display: grid; gap: 12px; }
.calc__barra-fila { display: grid; gap: 6px; }
.calc__barra-et {
  display: flex;
  justify-content: space-between;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .55);
}
.calc__barra {
  height: 10px;
  border-radius: 6px;
  background: rgba(255, 255, 255, .10);
  overflow: hidden;
}
.calc__barra i {
  display: block;
  height: 100%;
  width: 0;
  border-radius: 6px;
  background: rgba(255, 255, 255, .32);
  transition: width .6s var(--suave);
}
.calc__barra--real i { background: linear-gradient(90deg, #7FB8A4, #9FD6BE); }


/* ─────────────────────────────────────────────────────────────
   10. Resultados: la gráfica y las cifras

   La gráfica ya no tiene mando ni lectura de valores. Pedía trastear
   para sacar una cifra, y la cifra no es el mensaje: el mensaje es que
   las dos curvas se separan mucho. Para eso basta con verla dibujarse.

   Lo único que se mueve es un rectángulo de recorte que se ensancha de
   izquierda a derecha en 15 segundos y vuelve a empezar. Al ir por
   clip-path, el navegador no recalcula nada del dibujo en cada
   fotograma — solo recorta— así que es fluido hasta en un portátil
   flojo.
   ───────────────────────────────────────────────────────────── */

.res-nota {
  max-width: 52ch;
  font-size: 13px;
  line-height: 1.55;
  color: var(--text-3);
}
.res-nota a { color: var(--accent); font-weight: 600; white-space: nowrap; }

.etiqueta--punto::before {
  content: '';
  display: inline-block;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--mint);
  margin-right: 8px;
  vertical-align: middle;
}

.grafico { margin: 0 0 12px; padding: 0; background: none; border: 0; box-shadow: none; }

.grafico__titulo {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-2);
  margin-bottom: 10px;
}

.grafico__svg { display: block; width: 100%; height: auto; overflow: visible; }

.g-rejilla { stroke: var(--border); stroke-width: 1; }

.g-eje-txt { fill: var(--text-3); font-size: 12px; font-family: var(--mono); letter-spacing: .06em; }
.g-eje-v { font-size: 11px; text-transform: uppercase; letter-spacing: .1em; }

/* La capa que recorta el barrido: dentro van el área y las dos curvas,
   así se descubren las tres a la vez y no cada una por su lado. */
.g-capa { clip-path: url(#graf-corte); }

.g-area { fill: url(#graf-relleno); }
.g-linea { fill: none; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.g-linea--sin { stroke: var(--red); }
.g-linea--con { stroke: var(--display-2); }

.g-rotulo { font-size: 13px; font-weight: 700; font-family: inherit; }
.g-rotulo--sin { fill: var(--red); }
.g-rotulo--con { fill: var(--display-2); }

.g-hueco {
  fill: var(--display-2);
  font-size: 13px;
  font-weight: 600;
  font-family: inherit;
  opacity: 0;
  transition: opacity .6s ease;
}
.grafico.viva .g-hueco { opacity: .85; transition-delay: 2.6s; }

/* El frente que va descubriendo el dibujo. */
.g-frente { stroke: var(--display-2); stroke-width: 2; opacity: 0; }

/* transform-box: fill-box hace que el transform-origin se mida contra la
   caja del propio elemento y no contra el lienzo entero, que es lo que
   hace falta para que el rectángulo crezca desde su borde izquierdo. */
.g-corte, .g-frente {
  transform-box: fill-box;
  transform-origin: left center;
}
.g-corte { transform: scaleX(0); }

/* Una sola pasada de 3,5s y se queda dibujada. 'forwards' es lo que
   la deja en el estado final en vez de devolverla a cero al acabar.

   Que se repita al volver a bajar NO lo hace el CSS: lo hace
   animaciones.js quitando y volviendo a poner la clase .viva cada vez
   que la figura entra en pantalla. En bucle infinito quedaba como un
   escáner que no para; así se dice una vez y se calla. */
.grafico.viva .g-corte  { animation: g-avanza 3.5s ease-out forwards; }
.grafico.viva .g-frente { animation: g-frente 3.5s ease-out forwards; }

@keyframes g-avanza {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}
@keyframes g-frente {
  0%   { transform: translateX(0); opacity: 0; }
  10%  { opacity: .75; }
  88%  { opacity: .75; }
  100% { transform: translateX(880px); opacity: 0; }
}

.grafico__pie { margin-top: 14px; max-width: 68ch; }


/* ── Las cuatro cifras, debajo y compactas ────────────────── */

.metricas {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 24px;
  max-width: none;
  margin: 44px 0 0;
  padding-top: 34px;
  border-top: 1px solid var(--border);
  text-align: center;
}
.metrica { text-align: center; }
.metrica__cifra {
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(1.9rem, 3.4vw, 2.7rem);
  line-height: 1.1;
  color: var(--display-1);
  font-variant-numeric: tabular-nums;
  margin-bottom: 8px;
}
.metrica__titulo {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text);
  line-height: 1.4;
}

@media (max-width: 860px) {
  .metricas { grid-template-columns: repeat(2, 1fr); gap: 28px; }
}
@media (max-width: 520px) {
  .metricas { grid-template-columns: 1fr; }
}


/* ─────────────────────────────────────────────────────────────
   11. Precios

   Los planes y sus listas son los de siempre. Lo que se trae de
   landing-nueva es el número que cuenta hacia arriba al entrar en
   pantalla y el destello de color al llegar — y aquí, a diferencia
   de allí, se rearma cada vez que la sección sale y vuelve.
   ───────────────────────────────────────────────────────────── */

.plan { transition: transform .4s var(--spring), box-shadow .4s ease, border-color .3s ease; }
.plan:hover { transform: translateY(-8px); box-shadow: var(--shadow-lg); }

.plan__precio { font-family: var(--serif); font-weight: 500; font-size: 2.6rem; }
.plan__precio-num {
  display: inline-block;
  /* Sin ancho mínimo, el "€/mes" de al lado baila mientras el número
     pasa de una a dos y a tres cifras. */
  min-width: 2.4ch;
  font-variant-numeric: tabular-nums;
  transition: transform .35s var(--spring), color .35s ease;
}
/* En landing-nueva el transition no listaba color, así que el destello
   entraba de golpe. Sobre blanco eso se lee como un parpadeo raro. */
.plan__precio-num.pop { transform: scale(1.22); color: var(--display-2); }

/* El plan destacado respira con la SOMBRA y no con un translateY como en
   landing-nueva. Allí había que parar la animación al pasar el ratón,
   porque el hover mueve el mismo transform y las dos se peleaban; con el
   halo no hay conflicto y además no empuja a los planes de al lado. */
.plan--destacado { animation: plan-respira 3.6s ease-in-out infinite; }
@keyframes plan-respira {
  0%, 100% { box-shadow: 0 10px 30px -18px rgba(74, 111, 165, .40); }
  50%      { box-shadow: 0 22px 52px -18px rgba(74, 111, 165, .55); }
}


/* ─────────────────────────────────────────────────────────────
   12. Retoques sueltos
   ───────────────────────────────────────────────────────────── */

/* La alternancia de bandas grises se suaviza: con el hero claro y los
   módulos en color, el gris fuerte partía la página en trozos. */
.seccion--gris { background: linear-gradient(180deg, #FBFCFE, var(--surface) 40%, #FBFCFE); }

.cta__caja { border-radius: 28px; }
.cta h2 { margin-bottom: 14px; }

/* Las preguntas del FAQ se quedan en Inter. Fraunces por debajo de
   20px se lee más despacio, y esta página tiene que poder verse en un
   minuto: la serif se reserva para los titulares grandes. */
.faq__pregunta { font-weight: 600; }

/* Franja de confianza: lo que queda del bloque del caso real. */
.seccion--franja { padding: 40px 0; }
.franja__nota {
  margin-top: 22px;
  text-align: center;
  font-size: 14.5px;
  color: var(--text-3);
}
.franja__nota a { color: var(--accent); font-weight: 600; white-space: nowrap; }

/* Enlace del nav que apunta a otra página (Reseñas). Se marca con un
   punto para que se entienda que sale del scroll. */
.nav__enlace--fuera::before {
  content: '';
  display: inline-block;
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--mint);
  margin-right: 7px;
  vertical-align: middle;
}


/* ─────────────────────────────────────────────────────────────
   13. Movimiento reducido

   Quien lo pide, lo pide por algo: mareo, migraña o epilepsia
   fotosensible. Aquí se apaga TODO lo que se mueve solo —la deriva
   del hero, el plan que respira, el trazo del gráfico— y las
   entradas se quedan en su estado final, no ocultas.
   ───────────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  .hero { animation: none; }
  .plan--destacado { animation: none; }

  .reveal,
  .hero__mockup.reveal { opacity: 1; transform: none; filter: none; transition: none; }

  /* La ruta se queda dibujada de una vez, sin recorrido. */
  .ruta::after { transform: none; transition: none; }
  .ruta__paso { opacity: 1; transform: none; transition: none; }
  .ruta__punto { transform: none; transition: none; }

  .comparativa tbody tr { opacity: 1; transform: none; }

  /* La gráfica se ve entera de una vez, sin el barrido. */
  .grafico .g-corte  { transform: scaleX(1); animation: none; }
  .grafico .g-frente { opacity: 0; animation: none; }
  .grafico .g-hueco  { opacity: .85; transition: none; }

  .plan__precio-num.pop { transform: none; }

  /* Las tres demos de la sección de marca se quedan quietas. */
  .marca-hechos.vivo .mh-app,
  .marca-hechos.vivo .mh-int,
  .marca-hechos.vivo .mh-int::after,
  .marca-hechos.vivo .mh-menu__it { animation: none; }

  /* El visor cambia sin deslizarse y el autoavance no arranca. Los
     diagramas se quedan dibujados y quietos: se ven enteros, no se
     mueven. */
  .mods__item::before { transition: none; }
  .mods__panel--activo .dg-nodo,
  .mods__panel--activo .dg-campo { animation: none; opacity: 1; transform: none; }
  .mods__panel--activo .dg-barra { animation: none; opacity: 1; }
  .mods__panel--activo .dg-flujo { animation: none; opacity: .5; stroke-dashoffset: 0; stroke-dasharray: none; }

  /* El precargador se salta entero: ni rueda ni monograma, directos
     al contenido. animaciones.js hace lo mismo del lado del JS
     (quita data-fuera de golpe, sin esperar). */
  .pre { transition: none; }
  .pre__rueda, .pre__marca, .pre__marca .c1, .pre__marca .c2 { animation: none; opacity: 0; }
}


/* El nodo que cuenta. tabular-nums es lo que impide que el ancho baile
   mientras pasa de una cifra a otra. */
.cifra-cuenta { font-variant-numeric: tabular-nums; }
.cifra-cuenta.pop { color: var(--display-3); }

.grafico__titulo {
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 18px;
}


/* ─────────────────────────────────────────────────────────────
   14. Página de reseñas

   Vive en resenas.html y comparte con la portada esta hoja, el nav y
   el pie. Es la primera de las páginas sueltas: cuando haya más
   (módulos, comparativa…), este bloque es donde crecen.
   ───────────────────────────────────────────────────────────── */

/* Portada más baja que la de la home: aquí no hay que convencer de
   nada, se viene con la pregunta ya hecha. */
.hero--corto {
  min-height: 0;
  padding: calc(var(--nav-h) + 72px) 0 76px;
}

.resena {
  max-width: 860px;
  margin: 0 auto;
  padding: 40px 44px 44px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-lg);
}

.resena__cabecera {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  padding-bottom: 22px;
  margin-bottom: 26px;
  border-bottom: 1px solid var(--border);
}
.resena__logo {
  width: 54px;
  height: 54px;
  flex-shrink: 0;
  display: grid;
  place-items: center;
  border-radius: 14px;
  background: var(--accent-bg);
  color: var(--accent);
  font-weight: 800;
  font-size: 15px;
  letter-spacing: .04em;
}
.resena__quien { flex: 1; min-width: 200px; }
.resena__nombre { font-family: var(--sans); font-size: 1.15rem; font-weight: 700; margin: 0; }
.resena__meta { font-size: 13.5px; color: var(--text-3); margin-top: 2px; }

/* El sello dice "cliente real" y nada más. Ni estrellas ni nota media:
   inventarse una puntuación sobre un solo cliente sería justo lo que
   esta página no quiere hacer. */
.resena__sello {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 13px;
  border-radius: 100px;
  background: var(--green-bg);
  color: var(--green);
  font-size: 12.5px;
  font-weight: 700;
}
.resena__sello svg { width: 14px; height: 14px; }

.resena__cita { margin: 0; }
.resena__cita p {
  font-family: var(--serif);
  font-size: clamp(1.15rem, 2.1vw, 1.5rem);
  line-height: 1.45;
  color: var(--text);
}
.resena__cita p + p { margin-top: 18px; }
.resena__cita strong { font-weight: 600; color: var(--display-1); }

.resena-cifras {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px;
  max-width: 860px;
  margin: 40px auto 0;
  text-align: center;
}
.resena-cifra {
  font-family: var(--serif);
  font-size: clamp(1.9rem, 4vw, 2.9rem);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  color: var(--display-1);
  line-height: 1.1;
}
.resena-cifra__et {
  margin-top: 6px;
  font-size: 13px;
  color: var(--text-2);
  line-height: 1.45;
}

.resenas .sellos, #resena .sellos { margin-top: 40px; justify-content: center; }

.honestidad {
  max-width: 640px;
  margin: 0 auto;
  text-align: center;
  font-size: 15px;
  color: var(--text-2);
}

.resena-cta { text-align: center; max-width: 560px; margin: 0 auto; }
.resena-cta p { color: var(--text-2); margin: 10px 0 24px; }

@media (max-width: 780px) {
  .resena { padding: 28px 22px 30px; }
  .resena-cifras { grid-template-columns: repeat(2, 1fr); gap: 26px; }
}


/* ─────────────────────────────────────────────────────────────
   15. El logo de verdad

   Aquí había un cuadrado con degradado azul→menta y dentro un coche
   de trazo genérico, que era un marcador de posición. Ahora va la
   marca real (logo-zentora.png, la misma que usa la app).

   Se quita el azulejo: la marca es una silueta negra con su propio
   contorno, y meterla dentro de un cuadrado de color la ensucia y la
   hace competir con el «AI» de al lado.
   ───────────────────────────────────────────────────────────── */

.logo__marca {
  width: 30px;
  height: 30px;
  background: none;
  border-radius: 0;
  box-shadow: none;
}
.logo__marca img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

/* El pie es blanco (.footer usa var(--bg)), así que la marca negra se
   ve igual que arriba y no hay que invertir nada. Si algún día el pie
   se oscurece, aquí hace falta un filter: invert(1). */


/* ─────────────────────────────────────────────────────────────
   16. El resto de módulos

   El visor solo enseña seis, que son los que más se abren. Estos otros
   existen igual y se venden en Precios; sin nombrarlos aquí, quien lee
   la sección se hace una idea del producto más pequeña de lo que es.

   Van como etiquetas y no como tarjetas a propósito: son una lista de
   nombres, no seis bloques más que leer.
   ───────────────────────────────────────────────────────────── */

.mods__resto {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-top: 34px;
  padding-top: 26px;
  border-top: 1px solid var(--border);
  text-align: center;
}
.mods__resto b {
  width: 100%;
  margin-bottom: 6px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-3);
}
.mods__resto small {
  width: 100%;
  margin-top: 12px;
  font-size: 12.5px;
  color: var(--text-3);
}
.mods__resto span {
  padding: 7px 14px;
  border: 1px solid var(--border);
  border-radius: 100px;
  background: var(--bg);
  font-size: 13.5px;
  color: var(--text-2);
}


/* ─────────────────────────────────────────────────────────────
   17. La barra, con ocho entradas

   Con "Sugerencias" ya son ocho y a 1200px iban justas. Se aprieta el
   espaciado y —lo importante— la hamburguesa entra antes: entre 1080 y
   900px la barra cabía, pero apretada hasta dar pena. Es mejor el menú
   plegado que ocho enlaces pegados unos a otros.
   ───────────────────────────────────────────────────────────── */

.nav__inner { gap: 20px; }
.nav__enlace { padding: 7px 10px; font-size: 14px; }
.nav__acciones { gap: 8px; }
.nav__acciones .btn { padding: 9px 15px; font-size: 14px; }

@media (max-width: 1080px) {
  .nav__enlaces { display: none; }
  .nav__hamburguesa { display: flex; }
}

/* El enlace de la página en la que ya estás no se puede pulsar para ir a
   ningún sitio, así que se marca y se deja de ofrecer como destino. */
.nav__enlace[aria-current="page"] { color: var(--text); font-weight: 600; }


/* ─────────────────────────────────────────────────────────────
   18. Página de quejas y sugerencias

   Reaprovecha la ruta de tres pasos de "Cómo funciona" y el estilo de
   formulario que ya existe en estilos.css. Lo único propio es la caja
   de dos columnas y los ejemplos.
   ───────────────────────────────────────────────────────────── */

.sug-caja {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
  gap: 40px;
  align-items: start;
  max-width: 1000px;
  margin: 0 auto;
  padding: 38px 40px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-lg);
}
.sug-caja h2 { font-size: clamp(1.6rem, 2.6vw, 2.1rem); margin-bottom: 12px; }
.sug-caja__texto > p { color: var(--text-2); font-size: 15px; }

/* Tres ejemplos de lo que sirve. Sin ellos, un cuadro de texto vacío y
   la palabra "sugerencia" es una pantalla en blanco: la gente no sabe
   si lo suyo cuenta y se va sin escribir. */
.sug-ejemplos { margin-top: 22px; display: grid; gap: 12px; }
.sug-ejemplos li {
  padding: 12px 14px;
  border-left: 3px solid var(--border);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  background: var(--surface);
  font-size: 13.5px;
  color: var(--text-2);
  transition: border-color .25s ease;
}
.sug-ejemplos li:hover { border-left-color: var(--accent); }
.sug-ejemplos b { color: var(--text); }

.sug-caja__form select,
.sug-caja__form textarea,
.sug-caja__form input {
  width: 100%;
}
/* El <select> del formulario de demo no tenía CSS y salía como control
   crudo del navegador al lado de campos con estilo. Aquí se le da el
   mismo trato, y de paso arregla también aquel. */
.campo select {
  padding: 11px 13px;
  border: 1px solid var(--border);
  border-radius: var(--r);
  background: var(--bg);
  font: inherit;
  font-size: 15px;
  color: var(--text);
  appearance: none;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%235C6B7C' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  padding-right: 36px;
}
.campo select:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.sug-aviso {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  max-width: 620px;
  margin: 44px auto 0;
  padding: 14px 18px;
  border-radius: var(--r-lg);
  background: var(--surface);
  font-size: 14px;
  color: var(--text-2);
}
.sug-aviso svg { width: 18px; height: 18px; flex-shrink: 0; margin-top: 1px; color: var(--text-3); }

.sug-otra {
  text-align: center;
  font-size: 15px;
  color: var(--text-2);
}
.sug-otra a { color: var(--accent); font-weight: 600; }

@media (max-width: 860px) {
  .sug-caja { grid-template-columns: 1fr; gap: 30px; padding: 26px 22px; }
}


/* ─────────────────────────────────────────────────────────────
   19. Canales de entrada: la cinta

   Antes esto era un anillo con las marcas alrededor de un buzón. Era
   grande, obligaba a una caja cuadrada enorme y las fichas quedaban
   sueltas por la pantalla.

   Ahora es una cinta que corre sin parar. Ocupa una línea, cabe
   cualquier número de marcas y no hay que recolocar nada al añadir
   una: se pega al final de la lista y ya.

   Los cinco portales llevan un distintivo de color con su inicial en
   vez del logo oficial. No tenemos sus archivos de marca, y redibujar
   a mano un logo ajeno sale torcido y encima insinúa un acuerdo que no
   existe. Con su color y su inicial se reconocen igual de rápido en
   una cinta que pasa, y no pretenden ser el logo de nadie.
   ───────────────────────────────────────────────────────────── */

.cinta {
  position: relative;
  display: flex;
  gap: 14px;
  overflow: hidden;
  padding: 4px 0;
  /* Se difumina en los dos extremos para que las marcas entren y salgan
     en vez de aparecer cortadas contra el borde. */
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}

.cinta__fila {
  display: flex;
  gap: 14px;
  margin: 0;
  padding: 0;
  list-style: none;
  flex-shrink: 0;
}

/* Las dos copias corren juntas. Al desplazarse un 50 % del total, la
   segunda cae exactamente donde empezó la primera y el bucle no tiene
   costura. El calc del gap es lo que compensa el hueco entre las dos
   listas, que si no se acumula y el salto se ve. */
.cinta.viva .cinta__fila { animation: cinta-corre 34s linear infinite; }
@keyframes cinta-corre {
  from { transform: translateX(0); }
  to   { transform: translateX(calc(-100% - 14px)); }
}
.cinta:hover .cinta__fila { animation-play-state: paused; }

.cinta__it {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 10px 16px;
  border-radius: 100px;
  background: var(--bg);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
  white-space: nowrap;
  transition: border-color .25s ease, box-shadow .25s ease;
}
.cinta__it:hover { border-color: var(--border-h); box-shadow: var(--shadow); }

.cinta__m { display: block; flex-shrink: 0; }
.cinta__m svg { width: 20px; height: 20px; display: block; }
.cinta__t { font-size: 14px; font-weight: 600; color: var(--text); letter-spacing: -0.01em; }

@media (prefers-reduced-motion: reduce) {
  /* Sin movimiento la cinta se queda quieta, y la copia sobra: se
     esconde para no enseñar las marcas dos veces. */
  .cinta.viva .cinta__fila { animation: none; }
  .cinta { flex-wrap: wrap; justify-content: center; mask-image: none; -webkit-mask-image: none; }
  .cinta__fila[aria-hidden='true'] { display: none; }
  .cinta__fila { flex-wrap: wrap; justify-content: center; }
}


/* ─────────────────────────────────────────────────────────────
   20. "En camino"

   Las marcas de aquí NO están conectadas. Van debajo del anillo, en
   gris y con su sello, porque mezcladas arriba darían a entender que
   ya funcionan.

   La animación es la que se pidió —aparecer y desvanecerse por turnos,
   como en la referencia— pero sobre un bloque rotulado. El efecto
   visual es el mismo; lo que cambia es que no engaña.
   ───────────────────────────────────────────────────────────── */

.camino {
  max-width: 720px;
  margin: 44px auto 0;
  padding: 26px 28px;
  border: 1px dashed var(--border-h);
  border-radius: var(--r-xl);
  background: var(--surface);
  text-align: center;
}

.camino__titulo {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  flex-wrap: wrap;
  font-size: 14px;
  font-weight: 600;
  color: var(--text-2);
}
.camino__sello {
  padding: 4px 10px;
  border-radius: 100px;
  background: var(--amber-bg);
  color: var(--amber);
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .1em;
  text-transform: uppercase;
}

.camino__lista {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  margin: 20px 0 0;
  padding: 0;
  list-style: none;
}

/* En gris y sin los colores de marca, a propósito: con su color
   corporativo parecerían activas aunque el rótulo diga lo contrario. */
.camino__chip, .cam-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 15px;
  border-radius: 100px;
  background: var(--bg);
  border: 1px solid var(--border);
  color: var(--text-3);
  opacity: .45;
}
.cam-ico svg { width: 17px; height: 17px; display: block; }
.cam-nombre, .cam-rotulo { font-size: 13px; font-weight: 600; letter-spacing: -0.01em; }

/* Aparecer y desvanecerse por turnos, como en la referencia. Cada chip
   entra desfasado y el ciclo entero dura lo mismo para todos, así que
   siempre hay dos o tres encendidos a la vez y ninguno solo. */
.camino.viva .cam-chip {
  animation: cam-late 6s ease-in-out infinite;
  animation-delay: calc(var(--i) * .55s);
}
@keyframes cam-late {
  0%, 100% { opacity: .35; transform: translateY(0); }
  14%      { opacity: 1;   transform: translateY(-3px); }
  32%      { opacity: 1;   transform: translateY(-3px); }
  46%      { opacity: .35; transform: translateY(0); }
}

.camino__pie {
  margin-top: 18px;
  font-size: 13px;
  line-height: 1.55;
  color: var(--text-3);
}
.camino__pie a { color: var(--accent); font-weight: 600; white-space: nowrap; }

@media (prefers-reduced-motion: reduce) {
  .camino.viva .cam-chip { animation: none; opacity: .7; }
}


/* ─────────────────────────────────────────────────────────────
   21. Precios en corto (portada) y la matriz (precios.html)

   Las tres tarjetas enteras se fueron a su página. En la portada queda
   solo el precio, porque esconderlo del todo se lee como "consultar
   precio" y eso hace que la gente se vaya — y 49 €/mes es barato para
   lo que hace, así que es argumento de venta y no un dato que tapar.
   ───────────────────────────────────────────────────────────── */

.tira {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 30px 40px;
  max-width: 1000px;
  margin: 0 auto;
  padding: 34px 38px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-lg);
}
.tira__texto h2 { font-size: clamp(1.7rem, 3vw, 2.4rem); margin-bottom: 8px; }
.tira__texto p { font-size: 14.5px; color: var(--text-2); max-width: 42ch; }

.tira__planes {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.tira__planes li {
  display: grid;
  gap: 2px;
  padding: 16px 18px;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
}
.tira__destacado { border-color: var(--display-2); background: var(--accent-bg); }

.tira__nombre {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-3);
}
.tira__precio { font-family: var(--serif); font-size: 1.6rem; color: var(--text); line-height: 1.1; }
.tira__precio b { font-weight: 600; }
.tira__cupo { font-size: 12.5px; color: var(--text-3); }

.tira .btn { grid-column: 1 / -1; justify-self: center; gap: 8px; }
.tira .btn svg { width: 16px; height: 16px; transition: transform .25s ease; }
.tira .btn:hover svg { transform: translateX(3px); }

@media (min-width: 861px) {
  /* En ancho, el botón sube a la derecha del titular y los tres planes
     ocupan la fila de abajo entera. */
  .tira { grid-template-areas: 'texto boton' 'planes planes'; }
  .tira__texto { grid-area: texto; }
  .tira .btn { grid-area: boton; grid-column: auto; justify-self: end; }
  .tira__planes { grid-area: planes; }
}
@media (max-width: 620px) {
  .tira { padding: 24px 20px; }
  .tira__planes { grid-template-columns: 1fr; }
  .tira .btn { width: 100%; justify-content: center; }
}


/* ── La matriz de planes ──────────────────────────────────── */

/* La tabla va dentro de la MISMA sección que las tarjetas. Estuvieron
   en secciones separadas y entre las dos quedaban dos rellenos de
   sección enteros más una cabecera grande — casi 300px de vacío en
   medio de lo que en realidad es una sola cosa: el precio y qué entra
   por ese precio.

   Ahora las separa solo esta línea y un filete. */
.matriz-intro {
  max-width: 1000px;
  margin: 46px auto 20px;
  padding-top: 40px;
  border-top: 1px solid var(--border);
  text-align: center;
}
.matriz-intro h3 {
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(1.4rem, 2.4vw, 1.85rem);
  margin-bottom: 6px;
}
.matriz-intro p {
  max-width: 52ch;
  margin: 0 auto;
  font-size: 14.5px;
  color: var(--text-2);
}

.matriz-marco {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  background: var(--bg);
  box-shadow: var(--shadow-sm);
}
.matriz { width: 100%; min-width: 660px; border-collapse: collapse; }
.matriz caption { text-align: left; }

/* Veintidós filas son muchas para ir subiendo a mirar de qué columna
   era cada marca. La cabecera se queda pegada bajo la barra del menú. */
.matriz thead th {
  position: sticky;
  top: calc(var(--nav-h) - 1px);
  z-index: 2;
  padding: 20px 16px;
  background: var(--bg);
  border-bottom: 1px solid var(--border);
  text-align: center;
  font-size: 15px;
  font-weight: 700;
  color: var(--text);
}
.matriz thead th:first-child { text-align: left; font-weight: 600; color: var(--text-2); }
.mx-plan { display: block; }

/* La celda de la izquierda también se queda fija al desplazar la tabla
   de lado: si no, en un móvil se ven tres columnas de marcas sin saber
   de qué función son. */
.matriz tbody th {
  position: sticky;
  left: 0;
  z-index: 1;
  padding: 14px 18px;
  text-align: left;
  font-weight: 400;
  font-size: 14px;
  color: var(--text-2);
  background: var(--bg);
  border-bottom: 1px solid var(--border);
}
.matriz tbody td {
  padding: 14px 16px;
  text-align: center;
  border-bottom: 1px solid var(--border);
  width: 18%;
}
.matriz tbody tr:last-child th,
.matriz tbody tr:last-child td { border-bottom: 0; }

/* Bandas de grupo. Van a todo lo ancho y en gris: son el descanso que
   permite leer veintidós filas sin perderse. */
.mx-banda th {
  padding: 13px 18px !important;
  background: var(--surface) !important;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-2);
  border-bottom: 1px solid var(--border);
}

/* Las tres primeras filas son los datos duros, no funciones. */
.mx-precio-fila th, .mx-dato th { font-weight: 600; color: var(--text); }
.mx-precio-fila td, .mx-dato td { font-weight: 600; color: var(--text); font-size: 14.5px; }
.mx-precio-fila td { padding: 18px 16px; }
.mx-eur { font-family: var(--serif); font-size: 1.5rem; font-weight: 500; color: var(--text); }
.mx-eur b { font-weight: 600; }
.mx-eur small { font-size: 12px; color: var(--text-3); font-family: var(--sans); }

/* Filas de nivel: la misma función con distinto alcance en cada plan.
   El asistente de IA era tres filas con tres marcas verdes diciendo lo
   mismo; así se lee de un vistazo cuál da más. */
.mx-nivel td { font-size: 13px; font-weight: 600; color: var(--text-2); }

/* La marca de incluido va en círculo, como en la referencia: un check
   suelto se pierde en una tabla de veintidós filas. */
.mx-si {
  display: inline-grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--green-bg);
  color: var(--green);
}
.mx-si svg { width: 12px; height: 12px; }

.mx-no { display: inline-grid; place-items: center; width: 22px; height: 22px; color: var(--red); opacity: .55; }
.mx-no svg { width: 13px; height: 13px; }

/* La columna del plan que más se vende, marcada de arriba abajo. */
.mx-destacada { background: var(--accent-bg); }
.mx-th-destacada { box-shadow: inset 0 -2px 0 var(--display-2); }
.matriz tbody tr:hover th,
.matriz tbody tr:hover td { background: var(--surface); }
.matriz tbody tr:hover .mx-destacada { background: var(--accent-bg); }
.matriz .mx-banda:hover th { background: var(--surface) !important; }

@media (max-width: 620px) {
  .matriz thead th, .matriz tbody th, .matriz tbody td { padding: 11px 12px; font-size: 13px; }
  .mx-eur { font-size: 1.25rem; }
}



/* ── Las dudas de la página de precios ────────────────────── */

.dudas {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 18px;
  max-width: 880px;
  margin: 0 auto;
  padding: 0;
  list-style: none;
}
.dudas li {
  padding: 22px 24px;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--bg);
}
.dudas h3 { font-size: 15.5px; margin-bottom: 8px; }
.dudas p { font-size: 14px; color: var(--text-2); }

@media (max-width: 720px) {
  .dudas { grid-template-columns: 1fr; }
}


/* ─────────────────────────────────────────────────────────────
   22. El desplegable de Recursos

   Reseñas y Sugerencias estaban sueltas en la barra. Metidas aquí, la
   barra baja de ocho entradas a siete y las dos páginas quedan donde
   se buscan.

   Se abre al pasar el ratón, pero el disparador es un <button> con
   aria-expanded de verdad: también con Enter, con el dedo y se cierra
   con Escape. Un desplegable solo-hover deja fuera al teclado y a
   cualquiera con un móvil, donde el hover no existe.
   ───────────────────────────────────────────────────────────── */

.nav__grupo { position: relative; }

.nav__desplegable {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  border: 0;
  background: none;
  font: inherit;
  cursor: pointer;
  color: var(--text-2);
}
.nav__chevron { width: 13px; height: 13px; transition: transform .22s ease; }
.nav__desplegable[aria-expanded="true"] { color: var(--text); }
.nav__desplegable[aria-expanded="true"] .nav__chevron { transform: rotate(180deg); }

.nav__panel {
  position: absolute;
  top: calc(100% + 10px);
  left: 50%;
  z-index: 60;
  width: 290px;
  padding: 8px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);

  /* Arranca cerrado con visibility y no solo con opacity: invisible
     pero visitable, el tabulador entraría en un panel que no se ve. */
  opacity: 0;
  visibility: hidden;
  transform: translate(-50%, -6px);
  transition: opacity .2s ease, transform .2s var(--suave), visibility .2s;
}
.nav__grupo[data-abierto="si"] .nav__panel {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, 0);
}

/* El puente. Entre el botón y el panel hay 10px de aire: sin esta zona
   invisible, mover el ratón hacia el panel lo cierra a medio camino. */
.nav__panel::before {
  content: '';
  position: absolute;
  top: -12px;
  left: 0;
  right: 0;
  height: 12px;
}

.nav__item {
  display: flex;
  gap: 11px;
  align-items: flex-start;
  padding: 11px 12px;
  border-radius: var(--r);
  color: var(--text);
  transition: background .18s ease;
}
.nav__item:hover, .nav__item:focus-visible { background: var(--surface); }
.nav__item b { display: block; font-size: 14px; font-weight: 600; }
.nav__item small { display: block; margin-top: 1px; font-size: 12.5px; color: var(--text-3); line-height: 1.4; }

.nav__item-ico {
  flex-shrink: 0;
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border-radius: 8px;
  background: var(--accent-bg);
  color: var(--accent);
}
.nav__item-ico svg { width: 15px; height: 15px; }

/* En el menú del móvil no hay desplegable: las dos entradas van sueltas
   bajo su rótulo. Anidar un acordeón dentro de un menú que ya es un
   acordeón es una vuelta de tuerca que no aporta nada. */
.menu__rotulo {
  padding: 14px 0 4px;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-3);
}

@media (prefers-reduced-motion: reduce) {
  .nav__panel, .nav__chevron { transition: none; }
}


/* ─────────────────────────────────────────────────────────────
   23. Mensual o anual

   Dos botones, no un interruptor disfrazado. Van con aria-pressed, así
   que el lector de pantalla dice cuál está puesto y con el teclado se
   cambian con Enter como cualquier otro botón.
   ───────────────────────────────────────────────────────────── */

.ciclo {
  display: inline-flex;
  gap: 4px;
  margin: 0 auto 34px;
  padding: 4px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 100px;
}
.contenedor > .ciclo { display: flex; width: max-content; }

.ciclo__op {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 20px;
  border: 0;
  border-radius: 100px;
  background: none;
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  color: var(--text-3);
  cursor: pointer;
  transition: background .22s ease, color .22s ease, box-shadow .22s ease;
}
.ciclo__op:hover { color: var(--text-2); }
.ciclo__op:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ciclo__op--on {
  background: var(--bg);
  color: var(--text);
  box-shadow: var(--shadow-sm);
}

.ciclo__ahorro {
  padding: 3px 8px;
  border-radius: 100px;
  background: var(--green-bg);
  color: var(--green);
  font-family: var(--mono);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .04em;
}

/* La cuota de alta, debajo del cupo de cada plan. En verde cuando sale
   gratis: es el argumento del plan anual y tiene que verse. */
.plan__alta {
  margin-top: 6px;
  font-size: 12.5px;
  color: var(--text-3);
  transition: color .22s ease;
}
.plan__alta[data-gratis] { color: var(--green); font-weight: 600; }

/* El precio no salta al cambiar de ciclo: se funde. */
.plan__precio-num { transition: opacity .18s ease; }
.planes[data-cambiando] .plan__precio-num { opacity: .25; }

@media (max-width: 520px) {
  .ciclo { width: 100%; }
  .ciclo__op { flex: 1; justify-content: center; padding: 10px 12px; }
}


/* ─────────────────────────────────────────────────────────────
   24. WhatsApp y teléfono

   Todo esto arranca con hidden puesto en el HTML y lo enseña
   landing.js solo si la constante TELEFONO tiene número. Un botón de
   WhatsApp que abre un chat con un número que no existe hace más daño
   que no estar.
   ───────────────────────────────────────────────────────────── */

/* El `hidden` del HTML no bastaba, y por eso el botón de WhatsApp salía en
   la barra ANTES de que hubiera número: `.btn` trae `display: inline-flex`
   (estilos.css), que es una regla de autor y le gana al `display: none` que
   el navegador aplica a `[hidden]`. El botón se veía, se podía pulsar, y
   como su href seguía siendo "#" no llevaba a ninguna parte.

   O sea, exactamente el daño que el mecanismo pretendía evitar: alguien
   pulsa "WhatsApp", no pasa nada, y se va pensando que esto no funciona.

   Es la misma trampa que ya está explicada en estilos.css para .cta-fija, y
   se arregla igual: una regla de autor que gane a la otra. Va sobre `.btn` y
   no sobre `.btn--wasap` porque el problema lo tiene cualquier botón que se
   esconda con `hidden`, no solo este. */
.btn[hidden] { display: none; }

.btn--wasap {
  padding: 9px;
  background: #25D366;
  color: #fff;
  border: 0;
  border-radius: 10px;
  line-height: 0;
}
.btn--wasap:hover { background: #1FB855; color: #fff; }
.btn--wasap svg { width: 19px; height: 19px; display: block; }

/* La salida de emergencia del formulario: para quien no quiere rellenar
   ocho campos. En este sector se llama y se mandan audios, y obligar a
   todo el mundo a pasar por el formulario deja fuera a media cartera. */
.vias {
  margin-top: 20px;
  padding-top: 20px;
  border-top: 1px solid var(--border);
  text-align: center;
}
.vias__o {
  display: block;
  margin-bottom: 12px;
  font-size: 13px;
  color: var(--text-3);
}
.vias__botones { display: flex; gap: 10px; }
.vias__botones .btn { flex: 1; justify-content: center; gap: 8px; font-size: 14px; }
.vias__botones svg { width: 16px; height: 16px; flex-shrink: 0; }
.vias__botones .btn:first-child svg { color: #25D366; }

@media (max-width: 420px) {
  .vias__botones { flex-direction: column; }
}


/* ─────────────────────────────────────────────────────────────
   25. El agente de IA

   Dos columnas: el argumento a la izquierda y una conversación a la
   derecha. La conversación es el argumento — enseñarla vale más que
   describirla, porque lo que hay que entender es que se le habla en
   castellano y punto.

   Las burbujas entran escalonadas al aparecer la sección, como si se
   estuviera escribiendo. Se repite al volver a bajar.
   ───────────────────────────────────────────────────────────── */

.agente {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 56px;
  align-items: center;
}

/* La columna del texto no necesita nada propio salvo no desbordarse:
   los <h2> y la entradilla ya vienen estilados de la capa base. */
.agente__texto { min-width: 0; }

.agente__capas { margin: 28px 0 0; padding: 0; list-style: none; display: grid; gap: 18px; }
.agente__capas li { padding-left: 16px; border-left: 2px solid var(--border); }
.agente__capas h3 { font-size: 15px; margin-bottom: 3px; }
.agente__capas p { font-size: 14px; color: var(--text-2); }

.agente__nota {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  margin-top: 28px;
  padding: 15px 18px;
  border-radius: var(--r-lg);
  background: var(--green-bg);
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--text-2);
}
.agente__nota svg { width: 18px; height: 18px; flex-shrink: 0; margin-top: 1px; color: var(--green); }
.agente__nota b { color: var(--text); }

/* ── La conversación ──────────────────────────────────────── */

.agente__chat {
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  background: var(--bg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}

.ag-barra {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 13px 18px;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
  font-weight: 600;
  color: var(--text-2);
}
.ag-punto {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--green);
}
#agente-chat.viva .ag-punto { animation: ag-late 2.4s ease-in-out infinite; }
@keyframes ag-late { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }

.ag-hilo {
  display: grid;
  gap: 10px;
  margin: 0;
  padding: 20px 18px;
  list-style: none;
  background: var(--canvas);
}

.ag-linea { display: flex; opacity: 0; transform: translateY(8px); }
#agente-chat.viva .ag-linea {
  animation: ag-entra .5s var(--suave) both;
  animation-delay: calc(var(--i) * .55s);
}
@keyframes ag-entra {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

.ag-linea--yo { justify-content: flex-end; }

.ag-burbuja {
  max-width: 84%;
  padding: 11px 14px;
  border-radius: 14px;
  font-size: 13.5px;
  line-height: 1.5;
}
.ag-linea--yo .ag-burbuja {
  background: var(--accent);
  color: #fff;
  border-bottom-right-radius: 4px;
}
.ag-linea--agente .ag-burbuja {
  background: var(--bg);
  border: 1px solid var(--border);
  color: var(--text);
  border-bottom-left-radius: 4px;
}
/* La que lleva la foto del permiso: se marca para que se lea como un
   adjunto y no como un mensaje escrito. */
.ag-linea--foto .ag-burbuja {
  background: var(--accent-d);
  font-family: var(--mono);
  font-size: 12px;
}

.ag-acciones { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 9px; }
.ag-acciones b {
  padding: 5px 11px;
  border-radius: 100px;
  border: 1px solid var(--border);
  background: var(--surface);
  font-size: 12px;
  font-weight: 600;
  color: var(--accent);
}

.ag-pie {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 18px;
  border-top: 1px solid var(--border);
}
.ag-campo { flex: 1; font-size: 13px; color: var(--text-3); }
.ag-micro {
  display: grid;
  place-items: center;
  width: 30px; height: 30px;
  border-radius: 50%;
  background: var(--accent-bg);
  color: var(--accent);
}
.ag-micro svg { width: 15px; height: 15px; }

@media (max-width: 900px) {
  .agente { grid-template-columns: 1fr; gap: 36px; }
}
@media (prefers-reduced-motion: reduce) {
  #agente-chat.viva .ag-linea { animation: none; opacity: 1; transform: none; }
  #agente-chat.viva .ag-punto { animation: none; }
}


/* El panel de Recursos crece: de dos entradas a cinco, en dos grupos.
   El rótulo separa "las dos páginas de la casa" de "las guías", que se
   leen de forma distinta. */
.nav__panel { width: 330px; }
.nav__panel-rotulo {
  margin: 10px 12px 4px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-3);
}


/* ─────────────────────────────────────────────────────────────
   26. Precargador

   El mismo gesto que llevaba landing-nueva (rueda de color +
   monograma con aberración cromática), traído al fondo blanco de
   aquí. Allí vivía sobre --negro y el monograma se aclaraba con
   mix-blend-mode: screen; aquí el fondo es --bg (blanco), así que
   el "Z" de base sale directamente en el degradado de los
   titulares (--grad-display) y las dos copias fantasma no llevan
   blend mode — con la opacidad baja del keyframe ya basta para leer
   el desdoble de color sobre blanco.
   ───────────────────────────────────────────────────────────── */
.pre {
  position: fixed; inset: 0; z-index: 500; background: var(--bg);
  display: grid; place-items: center;
  transition: opacity .6s ease, visibility .6s ease;
}
.pre[data-fuera="true"] { opacity: 0; visibility: hidden; pointer-events: none; }

.pre__rueda {
  grid-area: 1 / 1; width: 64px; height: 64px; border-radius: 50%; filter: blur(2px);
  background: conic-gradient(from 0deg, var(--amber), var(--red), var(--display-2), var(--display-3), var(--amber));
  animation: pre-gira .9s linear infinite, pre-desvanece 1.6s ease forwards;
}
@keyframes pre-gira { to { transform: rotate(360deg); } }
@keyframes pre-desvanece { 0%, 55% { opacity: 1; transform: scale(1); } 100% { opacity: 0; transform: scale(.6); } }

.pre__marca {
  grid-area: 1 / 1; position: relative; font-family: var(--serif); font-style: italic; font-weight: 600;
  font-size: 2.6rem; opacity: 0;
  animation: pre-marca-entra 1.8s ease forwards;
}
.pre__marca span { display: inline-block; }
.pre__marca .c0 {
  position: relative; color: var(--display-1);
  background-image: var(--grad-display);
  -webkit-background-clip: text; background-clip: text;
}
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .pre__marca .c0 { -webkit-text-fill-color: transparent; }
}
.pre__marca .c1 { color: var(--amber); position: absolute; left: 0; top: 0; animation: pre-glitch .5s steps(2) infinite; }
.pre__marca .c2 { color: var(--display-3); position: absolute; left: 0; top: 0; animation: pre-glitch .5s steps(2) infinite reverse; }

@keyframes pre-marca-entra {
  0%, 40% { opacity: 0; filter: blur(6px); }
  55% { opacity: 1; filter: blur(0); }
  85% { opacity: 1; transform: scale(1) translateY(0); }
  100% { opacity: 0; transform: scale(.5) translateY(-46vh); }
}
@keyframes pre-glitch {
  0% { transform: translate(0, 0); opacity: .85; }
  25% { transform: translate(-3px, 1px); opacity: .55; }
  50% { transform: translate(2px, -1px); opacity: .85; }
  75% { transform: translate(-1px, 2px); opacity: .5; }
  100% { transform: translate(0, 0); opacity: .85; }
}

@media (max-width: 640px) {
  .pre__rueda { width: 48px; height: 48px; }
  .pre__marca { font-size: 2rem; }
}

/* ─────────────────────────────────────────────────────────────
   25. Alta de cuenta

   Dos clases que solo usa crear-cuenta.html. Van aquí y no en
   estilos.css porque ahí está lo que comparten todas las páginas,
   y esto lo usa una sola.
   ───────────────────────────────────────────────────────────── */

/* La casilla del consentimiento comercial. El <input> va DENTRO del
   <label> para que se pueda marcar pulsando también en el texto: en
   móvil, acertar en un cuadrito de 16px es lo que hace que la gente
   no lo marque aunque quiera. */
.campo--casilla label {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  font-size: 14px;
  line-height: 1.55;
  color: var(--text-2);
  font-weight: 400;
  cursor: pointer;
  margin-bottom: 0;
}
.campo--casilla input {
  width: 17px;
  height: 17px;
  margin: 2px 0 0;
  flex: 0 0 auto;
  accent-color: var(--accent);
  cursor: pointer;
}

.doc__nota {
  margin: 14px 0 0;
  font-size: 13px;
  line-height: 1.6;
  color: var(--text-3);
  text-align: center;
}
.doc__nota a { color: var(--accent); }


/* ─────────────────────────────────────────────────────────────
   26. Contratar y entrar

   Lo que hace falta para que desde Precios se pueda pagar y para
   que se pueda iniciar sesión sin salir de la web.
   ───────────────────────────────────────────────────────────── */

/* Los dos caminos de cada tarjeta. El margen inferior lo llevaba
   `.plan .btn` cuando solo había un botón; ahora lo lleva el grupo,
   o los dos botones quedarían separados por 22px y parecerían dos
   cosas sin relación. */
.plan__acciones {
  display: grid;
  gap: 8px;
  margin-bottom: 22px;
}
.plan__acciones .btn { margin-bottom: 0; }

/* El de la demo va un punto más bajo. La diferencia de tamaño es
   pequeña a propósito: sigue siendo una opción de primera, no un
   enlace de consolación. */
.plan__demo {
  padding: 11px 20px;
  font-size: 14px;
}

/* El aviso del pago. Hereda de .form__ok el color y el estar oculto
   hasta que el JS lo enseña; aquí solo se centra bajo las tarjetas. */
.planes__aviso {
  max-width: 620px;
  margin: 22px auto 0;
  text-align: center;
}

/* "Seguimos con el plan X". Se pinta en entrar y en crear cuenta
   cuando el visitante venía de pulsar Contratar. Azul de marca y no
   verde: no es una confirmación de nada todavía, es un recordatorio
   de lo que eligió. */
/* El `display` de aquí abajo es una regla de autor y el `[hidden]` del
   navegador solo una del agente de usuario, así que sin esta línea el
   aviso se vería SIEMPRE, incluso sin plan elegido. Es la misma trampa
   que ya documenta `.btn[hidden]` unas secciones más arriba. */
.plan-pendiente[hidden],
.sesion-abierta[hidden] { display: none; }

.plan-pendiente {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin: 0 0 22px;
  padding: 14px 18px;
  border: 1px solid rgba(74, 111, 165, 0.28);
  background: var(--accent-bg);
  border-radius: var(--r);
}
/* Que el texto ceda y "Elegir otro plan" se quede a la derecha en la
   misma línea mientras quepa; en móvil el flex-wrap lo baja solo. */
.plan-pendiente p {
  flex: 1 1 240px;
  margin: 0;
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--text-2);
}
.plan-pendiente strong { color: var(--text); }
.plan-pendiente a {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--accent);
  text-decoration: underline;
  white-space: nowrap;
}

/* `.doc a` subraya y pinta de azul TODOS los enlaces de estas páginas, y
   pesa más que `.btn--primario`: un enlace con forma de botón azul se
   quedaba con la letra azul sobre fondo azul, o sea sin texto. Los
   botones se salen de esa regla; los enlaces de leer siguen igual. */
.doc .btn { text-decoration: none; }
.doc .btn--primario { color: #fff; }
.doc .btn--secundario { color: var(--text); }
.doc .btn--fantasma { color: var(--text-2); }
/* Repetidos para el hover porque las reglas de arriba tienen el mismo
   peso que `.btn--secundario:hover` y van después: sin esto el botón se
   quedaría sin su cambio de color al pasar por encima. */
.doc .btn--secundario:hover { color: var(--accent); }
.doc .btn--fantasma:hover { color: var(--text); }

/* Lo que sustituye al formulario cuando ya hay sesión. */
.sesion-abierta { display: grid; gap: 10px; }
.sesion-abierta__quien {
  margin: 0 0 6px;
  font-size: 15px;
  line-height: 1.6;
  color: var(--text-2);
}
.sesion-abierta__quien strong { color: var(--text); }

/* El "+ IVA" pegado al precio.

   Va aquí y no en una nota al pie porque el pie no lo lee nadie: quien
   compara tres planes mira la cifra grande y decide. Que aparezca 89 € en la
   web y 107,69 € en la pasarela es la peor sorpresa posible, y justo en el
   momento en que ya había dicho que sí.

   Discreto a propósito —más pequeño, más claro y sin negrita— para que
   informe sin competir con el precio, que es lo que tiene que destacar. */
.plan__iva {
  font-size: .78em;
  font-weight: 500;
  color: var(--text-3);
  white-space: nowrap;
}


/* ─────────────────────────────────────────────────────────────
   27. Pantalla de acceso

   Cuatro páginas: entrar, crear cuenta, pedir el enlace de la
   contraseña y ponerla nueva. Ninguna lleva ya la nav ni el pie de
   la landing, y no es un descuido: quien llega aquí viene a hacer
   UNA cosa. Un menú de siete entradas y un pie de veinte enlaces
   son veintisiete formas de irse sin haber entrado.

   Lo que queda es el reparto de siempre en las pantallas de acceso
   de producto: a la izquierda la marca —lo único que hay que
   recordarle a quien ya decidió— y a la derecha la tarjeta con el
   formulario y nada más. El logo sigue siendo un enlace a la
   portada, que es la única salida que hace falta.
   ───────────────────────────────────────────────────────────── */

.acceso {
  display: grid;
  grid-template-columns: minmax(0, 1.02fr) minmax(0, 1fr);
  min-height: 100vh;
  /* svh y no vh: en el móvil, con la barra del navegador desplegada,
     100vh se pasa de alto y deja la tarjeta cortada por abajo. */
  min-height: 100svh;
}

/* ── El lado de la marca ───────────────────────────────────── */

/* Único fondo oscuro de toda la web. Aquí se lo puede permitir
   porque no hay nada largo que leer: son cuatro líneas y unas
   etiquetas. Los dos halos son el azul y el salvia de marca muy
   rebajados; sin ellos el panel es una losa azul plana. */
.acceso__marca {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 40px;
  padding: 44px 52px;
  color: #fff;
  background:
    radial-gradient(820px 560px at 12% 8%, rgba(127, 184, 164, 0.22), transparent 62%),
    radial-gradient(680px 520px at 92% 96%, rgba(78, 147, 117, 0.20), transparent 60%),
    linear-gradient(158deg, #2F4A6D 0%, #263B54 56%, #1C2B3D 100%);
}

/* Retícula muy tenue. Da textura sin dibujar nada, que es justo lo
   que se quiere detrás de un titular. */
.acceso__marca::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.045) 1px, transparent 1px);
  background-size: 64px 64px;
  /* Se desvanece hacia abajo para que la retícula no compita con las
     etiquetas, que es donde acaba la mirada. */
  -webkit-mask-image: linear-gradient(180deg, #000 0%, transparent 78%);
  mask-image: linear-gradient(180deg, #000 0%, transparent 78%);
  pointer-events: none;
}

.acceso__marca > * { position: relative; }

/* El logo de la barra, en blanco. El cuadrado del monograma conserva
   su degradado —es el activo de marca— y solo cambia la palabra:
   el `.logo__ai` en --accent sobre azul oscuro no se leería. */
.acceso__logo { color: #fff; }
.acceso__logo .logo__ai { color: var(--mint); }

.acceso__cuerpo { max-width: 30ch; }

/* Serif y no la sans del formulario: es la voz de la landing, y es lo
   que separa esta pantalla de un login genérico. */
.acceso__lema {
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(1.9rem, 2.9vw, 2.85rem);
  line-height: 1.08;
  letter-spacing: -0.02em;
  margin: 0 0 18px;
}
/* Sobre fondo oscuro el degradado de los titulares no sirve: sus tres
   colores están elegidos para leerse sobre blanco. Se sustituye por el
   salvia claro, que sí contrasta. */
.acceso__lema em {
  display: block;
  font-style: italic;
  font-weight: 600;
  color: #A8D5C2;
}

.acceso__texto {
  margin: 0 0 26px;
  font-size: 15.5px;
  line-height: 1.65;
  color: rgba(255, 255, 255, 0.78);
}

/* Las etiquetas son la lista de módulos, no adorno: quien duda de si
   esto le sirve, lo decide leyéndolas. */
.acceso__etiquetas {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.acceso__etiquetas li {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 13px;
  font-size: 13px;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.9);
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 999px;
}
.acceso__etiquetas svg {
  width: 14px;
  height: 14px;
  flex: 0 0 auto;
  color: #A8D5C2;
}

/* La frase de abajo del panel resuelve la duda que trae casi todo el
   que llega: si esta cuenta es la misma que la del programa. */
.acceso__nota {
  margin: 0;
  font-size: 13.5px;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.62);
  max-width: 40ch;
}

/* ── El lado del formulario ────────────────────────────────── */

.acceso__panel {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 26px;
  padding: 48px 32px;
  background: var(--surface);
}

.acceso__tarjeta {
  width: 100%;
  max-width: 440px;
  padding: 40px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-lg);
}

/* El h1 de estas páginas dice qué se hace aquí, no cómo se llama la
   empresa —eso ya lo dice el panel de al lado—, así que se queda muy
   por debajo del clamp de los titulares de la landing. */
.acceso__titulo {
  font-family: var(--serif);
  font-size: 1.7rem;
  font-weight: 500;
  line-height: 1.15;
  letter-spacing: -0.02em;
  margin: 0 0 8px;
}
.acceso__sub {
  margin: 0 0 26px;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--text-2);
}
.acceso__sub a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }

/* Botón de Google. Blanco con borde, que es lo que pide la guía de
   marca de Google y además lo que la gente reconoce; con el azul de
   esta casa pasaría por un botón nuestro. */
.acceso__google {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  padding: 13px 18px;
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--border-h);
  border-radius: var(--r);
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.acceso__google:hover { background: var(--surface); border-color: var(--text-3); }
.acceso__google:disabled { opacity: 0.6; cursor: default; }
.acceso__google svg { width: 18px; height: 18px; flex: 0 0 auto; }

/* Separador con la línea partida por el texto. */
.acceso__o {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 22px 0;
  font-size: 12.5px;
  color: var(--text-3);
}
.acceso__o::before,
.acceso__o::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border);
}

/* La etiqueta del campo y el enlace de ayuda en la misma línea: el
   "¿Has olvidado tu contraseña?" tiene que estar donde se descubre el
   problema, no al final del formulario. */
.campo__cabecera {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}
.campo__cabecera label { margin-bottom: 6px; }
.campo__ayuda {
  font-size: 12.5px;
  font-weight: 500;
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 2px;
  white-space: nowrap;
}

/* El ojo va DENTRO del campo. El hueco que se le reserva a la derecha
   evita que una contraseña larga pase por debajo del icono. */
.campo__caja { position: relative; }
.campo__caja input { padding-right: 46px; }
.campo__ojo {
  position: absolute;
  top: 50%;
  right: 6px;
  transform: translateY(-50%);
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 0;
  border-radius: var(--r-sm);
  background: none;
  color: var(--text-3);
  cursor: pointer;
}
.campo__ojo:hover { color: var(--text-2); background: var(--surface); }
.campo__ojo svg { width: 19px; height: 19px; }
/* Un solo botón con los dos dibujos dentro: cambia cuál se ve, no el
   contenido. Así al lector de pantalla no le aparecen y desaparecen
   nodos en cada pulsación; solo cambia el aria-pressed. */
.campo__ojo .ojo-off { display: none; }
.campo__ojo[aria-pressed="true"] .ojo-on { display: none; }
.campo__ojo[aria-pressed="true"] .ojo-off { display: block; }

/* Pie de la tarjeta: la otra pantalla a la que se puede querer ir. */
.acceso__cambiar {
  margin: 24px 0 0;
  padding-top: 20px;
  border-top: 1px solid var(--border);
  font-size: 14px;
  text-align: center;
  color: var(--text-2);
}
.acceso__cambiar a {
  font-weight: 600;
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* La letra pequeña de dentro de la tarjeta: condiciones, y el aviso
   de que la aplicación pide plan. Va pegada al botón que la provoca. */
.acceso__letra {
  margin: 14px 0 0;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--text-3);
  text-align: center;
}
.acceso__letra a { color: var(--text-2); text-decoration: underline; text-underline-offset: 2px; }

/* Pie mínimo: los tres enlaces legales y el año. Son los únicos que
   tienen que estar en todas las páginas por obligación. */
.acceso__pie {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 6px 16px;
  font-size: 12.5px;
  color: var(--text-3);
}
.acceso__pie a { color: var(--text-3); }
.acceso__pie a:hover { color: var(--text-2); text-decoration: underline; }

/* ── Estados que sustituyen al formulario ──────────────────── */

/* Se enseñan cuando ya no queda nada que rellenar: el enlace mandado,
   la contraseña cambiada, o el enlace caducado. Un formulario que
   sigue ahí después de haber funcionado invita a repetirlo.

   El `display` es regla de autor y el `[hidden]` del navegador solo
   del agente de usuario, así que sin estas dos líneas se verían
   SIEMPRE. Misma trampa que ya documentan `.btn[hidden]` y
   `.plan-pendiente[hidden]`. */
.acceso__hecho[hidden],
.acceso__caduco[hidden] { display: none; }

.acceso__hecho,
.acceso__caduco { display: grid; gap: 14px; }

.acceso__icono {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: var(--mint-bg);
  color: #35695A;
}
.acceso__icono svg { width: 24px; height: 24px; }
.acceso__icono--aviso { background: var(--amber-bg); color: var(--amber); }

.acceso__hecho p,
.acceso__caduco p {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.65;
  color: var(--text-2);
}
.acceso__hecho strong,
.acceso__caduco strong { color: var(--text); font-weight: 650; }

/* ── Móvil ─────────────────────────────────────────────────── */

/* Por debajo de 900px el panel de marca deja de ser una columna y
   pasa a ser una banda de cabecera: se queda el logo y el lema —lo
   que da confianza de un vistazo— y se van las etiquetas, que en
   vertical empujarían el formulario fuera de la primera pantalla. */
@media (max-width: 900px) {
  .acceso {
    grid-template-columns: 1fr;
    min-height: 0;
  }
  .acceso__marca {
    gap: 18px;
    padding: 24px 24px 30px;
  }
  .acceso__cuerpo { max-width: none; }
  .acceso__lema {
    font-size: 1.45rem;
    margin: 0;
  }
  .acceso__lema em { display: inline; }
  .acceso__texto,
  .acceso__etiquetas,
  .acceso__nota { display: none; }

  .acceso__panel { padding: 30px 20px 44px; }
}

@media (max-width: 520px) {
  /* Sin borde: a este ancho la tarjeta ocupa la pantalla entera y el
     marco solo le roba 40px de sitio al formulario. */
  .acceso__tarjeta {
    padding: 28px 20px;
    border: 0;
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-sm);
  }
  .acceso__titulo { font-size: 1.5rem; }
  /* En una línea de 300px la etiqueta y "¿Has olvidado…?" no caben
     juntas, y el enlace se partiría en dos. */
  .campo__cabecera { flex-wrap: wrap; gap: 0 12px; }
}
