/* ============================================================
   luzgasia — funnel.css
   Wizard multi-paso: barra de progreso, subida con drag&drop,
   formularios, consentimientos, pantalla de análisis, resultado
   y confirmación. Estados: vacío / cargando / error / éxito.
   ============================================================ */

/* ============================================================
   Shell viewport-fit: cada paso cabe ENTERO en 100dvh menos la
   cabecera ("captura de pantalla limpia"). Objetivos verificados:
   1920×1080, 1366×768, 390×844 y 360×740. En viewports aún más
   bajos el scroller interno actúa de válvula de seguridad (el
   contenido nunca queda inaccesible).
   ============================================================ */
.pagina-funnel main {
  background: var(--lz-papel);
  position: relative;
  isolation: isolate;
}

/* Funnel sin distracciones: el pie global se oculta SOLO aquí para que el
   shell ocupe exactamente el viewport (la privacidad sigue enlazada en el
   paso de consentimientos). */
.pagina-funnel .pie {
  display: none;
}

/* ================== `hidden` DEBE GANAR SIEMPRE (§6.36) ==================
   El `[hidden] { display: none }` que trae el navegador es una regla de hoja
   de usuario-agente y CUALQUIER `display:` de autor la pisa. `.consentimiento`
   declara `display: grid`, así que poner `hidden` en una fila de consentimiento
   NO la ocultaba: se seguía pintando entera.

   Ya explotó (2026-08-23) y no fue un defecto de maqueta, fue LEGAL: las dos
   filas que `vestirParaVia` oculta por vía —«podéis llamarme» (solo vías
   manuales, §6.11) y «podéis comprobar con mi distribuidora» (solo CUPS,
   §6.66)— se le enseñaban a TODO el mundo. A quien subía una factura se le
   ofrecía marcar un permiso cuyo texto dice «mandamos SOLO tu CUPS y tu número
   de documento» sin que en esa vía se pida ni CUPS ni documento: declarar una
   cesión que no ocurre es tan incorrecto como callarse la que sí (§6.40).
   De regalo, esas dos filas de más hacían que el paso desbordara su scroller y
   la barra de acciones pegajosa tapaba la tercera casilla (ver §6.41).

   La regla es GENÉRICA a propósito, no una lista de clases: una lista hay que
   acordarse de ampliarla, y esto se rompe EN SILENCIO —sin error de consola,
   sin test rojo— cada vez que alguien añade un bloque con `display:` que se
   oculte por atributo. `.funnel [hidden]` tiene especificidad (0,2,0) y gana a
   cualquier clase suelta sin necesidad de `!important`. */
.funnel [hidden] {
  display: none;
}

.funnel {
  position: relative;
  z-index: 1; /* por delante del fondo decorativo (papel + gotas) */
  /* Alto VIVO del aviso de cookies (lo mide funnel.js; 0 al decidir). Definida
     aquí para que exista siempre — un var() sin definición descarta la
     declaración entera sin avisar (§6.27). */
  --fn-cookies: 0px;
  /* UN SOLO CARRIL para todo el proceso. Antes el ancho cambiaba en cada paso
     (46 / 60 / 74 / 76rem) y el recuadro crecía y encogía mientras avanzabas;
     además, con 46rem en un portátil el formulario quedaba en una columna
     estrecha con media pantalla vacía a los lados y había que hacer scroll.
     El reparto lo hacen las rejillas de dentro, no el carril. */
  max-width: min(76rem, 100% - 2.5rem);
  margin-inline: auto;
  height: calc(100vh - var(--altura-cabecera)); /* fallback sin dvh */
  height: calc(100dvh - var(--altura-cabecera)); /* barras móviles (dvh) */
  display: flex;
  flex-direction: column;
  padding-block: clamp(0.5rem, 1.6vh, 1.5rem);
  overflow: clip; /* nada empuja la página durante las transiciones */
}

/* EL AVISO DE COOKIES TAPA EL FINAL DEL FUNNEL (misma familia que §6.70: una
   barra fija sobre el control que hay que pulsar). El aviso es `position:
   fixed` al fondo del viewport y el funnel mide 100dvh: mientras el visitante
   no decide, el aviso cubría la barra pegajosa de acciones ENTERA en móvil
   (244px de aviso sobre un CTA que nace debajo, medido 2026-08-28 en 390×844)
   y la mitad inferior de «Continuar» en 1024×768 — el clic se lo llevaba el
   propio aviso. La segunda tarjeta de vía tampoco recibía el tap.

   El arreglo es RESERVAR el alto del aviso mientras viva: funnel.js lo mide
   en `--fn-cookies` (0 al decidir, y sigue en vivo si el aviso cambia de
   alto) y este padding encoge el scroller, así que la barra pegajosa se ancla
   POR ENCIMA del aviso y todo el contenido puede salir de detrás con scroll.
   Solo ≤64rem: en escritorio ancho la maqueta está aprobada tal cual y este
   tramo es donde el aviso se come una franja decisiva del viewport. */
@media (max-width: 64rem) {
  .funnel {
    padding-bottom: calc(clamp(0.5rem, 1.6vh, 1.5rem) + var(--fn-cookies, 0px));
  }
}

.funnel__cabecera {
  text-align: center;
  margin-bottom: clamp(0.5rem, 1.6vh, 1.5rem);
  flex: none;
}

/* El carril del funnel es ancho (76rem) para que los formularios repartan sus
   campos en columnas — pero un PÁRRAFO a 76rem son ~130 caracteres por línea y
   el ojo se pierde al saltar de renglón. El texto se lee en su medida; las
   rejillas usan el ancho.

   La descripción va SIN `margin-inline: auto`: cuelga de un h2 alineado a la
   izquierda, y centrar el bloque la dejaba descolgada de su propio título.
   Quien sí la centra es la pantalla de elección, que tiene su regla aparte. */
.paso__descripcion { max-width: 76ch; }
.funnel__intro { max-width: 76ch; margin-inline: auto; }

.funnel__titulo {
  font-family: var(--fuente-marca);
  font-weight: 700;
  letter-spacing: -0.015em;
  font-size: clamp(1.6rem, 3vh + 0.5rem, 2.5rem);
  line-height: 1.05;
  color: var(--c-marino-900);
}

.funnel__intro {
  margin-top: var(--esp-2);
  font-size: clamp(0.875rem, 1.8vh, 1.0625rem);
  color: var(--c-texto-suave);
}

/* ---------- Indicador de pasos v2 (editorial, con iconos) ----------
   Más presencia: cada paso lleva su MINI ICONO de línea dentro de una ficha
   redonda; al completarse, el icono cede su sitio a un check que hace su gesto
   con --ease-gota. Etiquetas small-caps que se leen ENTERAS (sin recorte). El
   activo es un chip navy con la esquina viva ámbar (la firma de la gota). La
   lógica no cambia: funnel.js toggla .activo/.hecho sobre [data-progreso-paso]
   y fija --progreso en [data-progreso-relleno]. */
.progreso {
  flex: none;
  width: 100%;
  max-width: 46rem;
  margin-inline: auto;
  margin-bottom: clamp(0.6rem, 2vh, 1.6rem);
}

.progreso__pasos {
  display: flex;
  justify-content: center;
  align-items: stretch;
  gap: clamp(0.2rem, 1.2vw, 0.6rem);
  list-style: none;
  margin: 0 0 clamp(0.5rem, 1.4vh, 0.9rem);
  padding: 0;
}

.progreso__paso {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-width: 0;
  padding: 0.4rem 0.75rem;
  border-radius: var(--radius-gota-s);
  overflow: hidden; /* recorta la cuña ámbar de la esquina viva */
  color: var(--lz-tinta-suave);
  transition: background-color var(--trans-media), color var(--trans-media),
    opacity var(--trans-media);
}

/* Ficha del icono: círculo de trazo que aloja el icono del paso y el check
   apilados. En reposo se ve el icono; al completar, aparece el check. */
.progreso__ficha {
  position: relative;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: clamp(1.6rem, 3.4vh, 2rem);
  height: clamp(1.6rem, 3.4vh, 2rem);
  border-radius: 50%;
  border: 1.5px solid currentColor;
  color: inherit;
}

.progreso__ico,
.progreso__check {
  position: absolute;
  width: 62%;
  height: 62%;
}

/* El icono del paso: visible salvo cuando el paso ya está hecho */
.progreso__ico {
  opacity: 1;
  transform: scale(1);
  transition: opacity var(--trans-rapida), transform var(--trans-rapida);
}

.progreso__check {
  opacity: 0;
  transform: scale(0.3);
}

.progreso__paso.hecho .progreso__ico {
  opacity: 0;
  transform: scale(0.4);
}

/* El gesto del check al completar el paso: pop con la firma --ease-gota */
.progreso__paso.hecho .progreso__check {
  animation: nz-check-pop 460ms var(--ease-gota) both;
}

@keyframes nz-check-pop {
  from {
    opacity: 0;
    transform: scale(0.3) rotate(-14deg);
  }
  60% {
    opacity: 1;
    transform: scale(1.15) rotate(3deg);
  }
  to {
    opacity: 1;
    transform: scale(1) rotate(0deg);
  }
}

/* Latido sutil del icono del paso ACTIVO (llama la atención sin gritar) */
@media (prefers-reduced-motion: no-preference) {
  .progreso__paso.activo .progreso__ficha {
    animation: nz-ficha-latido 2.4s ease-in-out infinite;
  }
}

@keyframes nz-ficha-latido {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.06); }
}

/* Etiqueta small-caps editorial que se lee ENTERA (nada de ellipsis) */
.progreso__etiqueta {
  font-family: var(--fuente-marca);
  font-size: clamp(0.75rem, 1.7vh, 0.875rem);
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* Pendientes atenuados; hechos en tinta media; el activo, protagonista */
.progreso__paso:not(.activo):not(.hecho) {
  opacity: 0.55;
}

.progreso__paso.hecho {
  color: var(--c-marino-700);
}

.progreso__paso.hecho .progreso__ficha {
  background: color-mix(in srgb, var(--c-marino-700) 12%, transparent);
  border-color: transparent;
}

.progreso__paso.activo {
  background: var(--c-marino-950);
  color: var(--c-blanco);
}

.progreso__paso.activo .progreso__ficha {
  border-color: var(--c-amarillo-400);
  color: var(--c-amarillo-400);
}

.progreso__paso.activo .progreso__etiqueta {
  font-weight: 700;
  color: var(--c-blanco);
}

/* El paso activo NO se encoge: es el único que enseña su etiqueta, y como
   hermano flexible se le recortaba justo el final («PERMISO» por «PERMISOS»,
   visto en móvil). Los demás son solo icono y sí pueden ceder sitio. */
.progreso__paso.activo { flex: none; }

/* Colapso a icono: SOLO el paso activo muestra su etiqueta en pantalla. Los
   demás la conservan para lectores de pantalla (el texto es el nombre accesible
   del paso; la ficha del icono es aria-hidden), pero sin ocupar espacio. Así la
   fila de 5 pasos NUNCA desborda la tarjeta y el último ("Resultado") deja de
   recortarse — y es a prueba de idiomas (ES/CA/EN) sin depender de que quepan
   las 5 etiquetas completas. */
.progreso__paso:not(.activo) .progreso__etiqueta {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* La esquina viva: cuña ámbar en la esquina inferior izquierda del chip
   (la misma esquina afilada de --radius-gota-s), recortada por overflow */
.progreso__paso.activo::before {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 0.6rem;
  height: 0.6rem;
  background: var(--c-amarillo-500);
  border-radius: 0 100% 0 var(--radius-vivo);
}

/* Línea de progreso: regla fina editorial que se rellena con la firma
   --ease-gota (el gradiente termina en ámbar: el avance apunta al CTA) */
.progreso__barra {
  position: relative;
  height: 4px;
  border-radius: var(--radio-pill);
  background: var(--lz-linea);
  overflow: hidden;
}

.progreso__relleno {
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--c-marino-800), var(--c-amarillo-500));
  transform-origin: left center;
  transform: scaleX(var(--progreso, 0.2));
  transition: transform var(--dur-v2-3) var(--ease-gota);
}

/* Chispa que corre por la punta del relleno cuando avanza (GPU: transform) */
@media (prefers-reduced-motion: no-preference) {
  .progreso__barra::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: calc(var(--progreso, 0.2) * 100% - 1.5rem);
    width: 1.5rem;
    background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--c-amarillo-400) 70%, white));
    opacity: 0.7;
    transition: left var(--dur-v2-3) var(--ease-gota);
  }
}

@media (prefers-reduced-motion: reduce) {
  .progreso__paso,
  .progreso__ico,
  .progreso__relleno {
    transition: none;
  }

  .progreso__paso.hecho .progreso__check {
    animation: none;
    opacity: 1;
    transform: scale(1);
  }
}

/* En móvil solo se muestra la etiqueta del paso activo; los iconos permanecen
   visibles en todos los pasos (siguen leyéndose como un recorrido) */
@media (max-width: 559px) {
  .progreso__paso:not(.activo) .progreso__etiqueta {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }

  .progreso__etiqueta {
    font-size: 0.8125rem;
  }

  /* Los círculos de los pasos se RECORTABAN por el borde derecho en móvil
     (reportado en «sin factura» y «con CUPS»). La causa NO era desbordar el
     viewport —la fila siempre mide 318px a 390px— sino que los chips de icono
     (todos menos el activo) son hermanos flexibles SIN `flex: none`: se
     comprimían para dejar sitio al chip activo, que es el único con etiqueta y
     es `flex: none`. Cuanto más larga la etiqueta, más se aplastan; con
     `overflow: hidden` en el chip, el círculo del icono quedaba cortado. Medido
     a 390px: ancho de chip de icono = 45px con «Tu CUPS», 39px con «Tu factura»
     y solo 33px con «Tus consumos» (y peor aún «Zure kontsumoa» en eu, «El teu
     CUPS» en ca/va — por eso el owner lo vio también en cups). Fijamos la huella
     del icono: `flex: none` + sin padding lateral (el lateral solo sirve al chip
     con texto), así queda un círculo compacto de tamaño constante que NUNCA se
     recorta ni desplaza la fila, en cualquier vía e idioma. */
  .progreso__paso:not(.activo) {
    flex: none;
    padding-inline: 0;
  }

  /* Y el chip activo cede el sobrante en vez de forzar el recorte de los
     iconos o salirse del viewport: puede encogerse (`flex-shrink`) y su
     etiqueta se trunca con "…" SOLO cuando de verdad no cabe (móviles muy
     estrechos o etiquetas largas de otros idiomas). En el caso común (es/en a
     ≥360px) la fila cabe entera y la etiqueta se lee completa — no truncamos
     por gusto. Sustituye en móvil al `flex: none` global del activo, cuyo
     motivo (que no se le recorte «PERMISOS») se respeta: aquí la etiqueta se
     acorta con elipsis intencionada, no con un corte duro, y los pasos cortos
     («Permisos», «Resultado») caben de sobra sin tocarse. */
  .progreso__paso.activo {
    flex: 0 1 auto;
    min-width: 0;
  }
  .progreso__paso.activo .progreso__etiqueta {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}

/* ---------- Contenedor de pasos: scroller estable con centrado seguro ---------- */
.funnel__pasos {
  flex: 1;
  min-height: 0; /* imprescindible para que el scroller no crezca */
  display: flex;
  flex-direction: column;
  overflow-y: auto; /* válvula de seguridad + scroll intencionado del resultado */
  overflow-x: clip; /* el slide horizontal (±28px) nunca crea scrollbars */
  scrollbar-gutter: stable;
  /* LA BARRA DE ACCIONES ES PEGAJOSA Y TAPA LO QUE PASA POR DEBAJO.
     `.paso__acciones` se ancla abajo del scroller (mide 87 px en escritorio y
     151 px en móvil, donde los botones se parten en dos filas) y el contenido
     se desliza POR DEBAJO. Sin reservar ese hueco, un control que caiga en esa
     franja es inalcanzable: el navegador lo considera «ya visible», así que ni
     el foco por tabulador ni `scrollIntoView` mueven nada — se queda detrás de
     la barra y el clic se lo lleva el botón «Volver», que además retrocede un
     paso. Medido el 2026-08-23 en el paso de consentimientos: la tercera
     casilla era literalmente inmarcable en móvil en las tres vías.
     `scroll-padding` es justo la propiedad para esto: no mueve nada de sitio,
     solo le dice al navegador dónde acaba de verdad el hueco útil. El valor
     cubre el peor caso (barra partida) con margen; sobrarse solo hace que el
     elemento aterrice un poco más arriba. */
  scroll-padding-block-end: 10rem;
}

/* Comparativa completa desplegada (funnel.js añade .detalle-abierto): el
   resultado deja de centrarse por `margin-block: auto` —que, al desbordar,
   añadía huecos vacíos desplazables arriba y abajo— y fluye desde arriba.
   `safe center` conserva el centrado cuando el contenido cabe y cae a "start"
   (sin recortes ni huecos) cuando desborda. Solo afecta al paso resultado
   (único visible en esta fase); comportamiento estándar, sin hacks. */
.funnel__pasos.detalle-abierto {
  justify-content: safe center;
}

.funnel__pasos.detalle-abierto .paso--resultado {
  margin-block: 0;
}

/* ---------- Paneles de paso ---------- */
.paso {
  /* margin-block auto = centrado vertical SEGURO: si un paso superase la
     altura disponible, los márgenes colapsan a 0 y se puede hacer scroll
     (nunca se corta contenido por arriba como pasaría con align center). */
  margin-block: auto;
  flex: none;
  background: var(--c-blanco);
  border: 1px solid var(--c-borde);
  border-radius: var(--radio-l);
  box-shadow: var(--sombra-1);
  padding: clamp(1rem, 2.4vh, 2.25rem) clamp(1rem, 3vw, 2.5rem);
}

.paso[hidden] {
  display: none !important;
}

/* Transición de paso direccional: --dir la fija funnel.js (1 adelante, -1 atrás) */
.paso.activo {
  animation: nz-paso-entrada 320ms cubic-bezier(0.22, 0.7, 0.35, 1) both;
}

.paso.saliendo {
  animation: nz-paso-salida 200ms ease-in both;
  pointer-events: none;
}

/* La ELECCIÓN se despide SIN moverse de sitio. Su gesto ya lo hacen las
   tarjetas (la elegida da un paso al frente y las otras se retiran); el slide
   horizontal del wizard la empujaba 28px a la izquierda y `overflow-x: clip`
   —que existe para que ese mismo slide no cree scrollbars— recortaba el borde
   izquierdo de la tarjeta «Con tu factura» en plena transición (lo vio el
   dueño). Un fundido plano no cruza ningún borde. */
.funnel--eleccion .paso.saliendo { animation-name: nz-paso-salida-plano; }
@keyframes nz-paso-salida-plano {
  from { opacity: 1; }
  to   { opacity: 0; }
}

@keyframes nz-paso-entrada {
  from {
    opacity: 0;
    transform: translateX(calc(var(--dir, 1) * 28px));
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes nz-paso-salida {
  from {
    opacity: 1;
    transform: none;
  }
  to {
    opacity: 0;
    transform: translateX(calc(var(--dir, 1) * -28px));
  }
}

/* Stagger de los elementos del paso entrante (el resultado gestiona su propio
   revelado secuencial con .revelable, por eso se excluye) */
.paso.activo:not([data-paso="resultado"]) > * {
  animation: nz-hijo-entrada 420ms cubic-bezier(0.22, 0.7, 0.35, 1) both;
}

.paso.activo:not([data-paso="resultado"]) > :nth-child(2) { animation-delay: 50ms; }
.paso.activo:not([data-paso="resultado"]) > :nth-child(3) { animation-delay: 100ms; }
.paso.activo:not([data-paso="resultado"]) > :nth-child(4) { animation-delay: 150ms; }
.paso.activo:not([data-paso="resultado"]) > :nth-child(5) { animation-delay: 200ms; }
.paso.activo:not([data-paso="resultado"]) > :nth-child(6) { animation-delay: 250ms; }
.paso.activo:not([data-paso="resultado"]) > :nth-child(7) { animation-delay: 300ms; }
.paso.activo:not([data-paso="resultado"]) > :nth-child(n + 8) { animation-delay: 340ms; }

@keyframes nz-hijo-entrada {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .paso.activo,
  .paso.saliendo,
  .paso.activo:not([data-paso="resultado"]) > * {
    animation: none;
  }
}

.paso__titulo {
  font-size: clamp(1.1rem, 2.2vh + 0.3rem, 1.6rem);
  color: var(--c-marino-900);
  outline: none;
}

.paso__descripcion {
  margin-top: var(--esp-1);
  font-size: clamp(0.85rem, 1.8vh, 1.0625rem);
  color: var(--c-texto-suave);
}

.paso__acciones {
  display: flex;
  flex-wrap: wrap;
  gap: var(--esp-3);
  justify-content: space-between;
  align-items: center;
  margin-top: clamp(0.75rem, 2.2vh, 2rem);
}

.paso__acciones .boton--primario {
  margin-left: auto;
}

.paso .sellos {
  margin-top: clamp(0.6rem, 1.8vh, 1.5rem);
  justify-content: center;
}

/* ---------- Paso 1: subida ---------- */
.zona-subida {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(0.4rem, 1.2vh, 0.75rem);
  margin-top: clamp(0.6rem, 1.8vh, 1.5rem);
  padding: clamp(1rem, 3.2vh, 3rem) var(--esp-4);
  border: 2px dashed var(--c-borde-fuerte);
  border-radius: var(--radio-l);
  background: var(--c-fondo-suave);
  text-align: center;
  cursor: pointer;
  transition: border-color var(--trans-rapida), background-color var(--trans-rapida),
    transform 320ms var(--rebote);
}

/* Respiración en reposo: halo que late (solo opacity) + icono que flota */
.zona-subida::after {
  content: "";
  position: absolute;
  inset: -2px;
  border-radius: inherit;
  box-shadow: 0 0 0 6px rgba(255, 138, 30, 0.16), var(--sombra-2);
  opacity: 0;
  pointer-events: none;
  animation: nz-respirar 3.6s ease-in-out infinite;
}

@keyframes nz-respirar {
  0%,
  100% {
    opacity: 0;
  }
  50% {
    opacity: 0.7;
  }
}

.zona-subida:hover,
.zona-subida.arrastrando {
  border-color: var(--c-amarillo-500);
  background: var(--c-amarillo-100);
}

/* Al arrastrar un fichero encima: la caja se activa con claridad */
.zona-subida.arrastrando {
  transform: scale(1.02) rotate(-0.5deg);
}

.zona-subida.arrastrando::after {
  animation: nz-respirar 0.9s ease-in-out infinite;
}

.zona-subida__icono {
  width: clamp(2rem, 4.5vh, 3rem);
  height: clamp(2rem, 4.5vh, 3rem);
  color: var(--c-marino-700);
  animation: nz-flotar-icono 4s ease-in-out infinite;
}

@keyframes nz-flotar-icono {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-4px);
  }
}

.zona-subida.arrastrando .zona-subida__icono {
  animation: nz-rebote 0.5s ease infinite alternate;
  color: var(--c-marino-900);
}

.zona-subida.arrastrando .zona-subida__texto {
  color: var(--c-marino-950);
}

@keyframes nz-rebote {
  from {
    transform: translateY(0) scale(1);
  }
  to {
    transform: translateY(-7px) scale(1.08);
  }
}

/* Sacudida sutil para errores (se aplica por JS con la clase .sacudir) */
.sacudir {
  animation: nz-sacudida 400ms ease both;
}

@keyframes nz-sacudida {
  0%,
  100% {
    transform: translateX(0);
  }
  20% {
    transform: translateX(-7px);
  }
  40% {
    transform: translateX(6px);
  }
  60% {
    transform: translateX(-4px);
  }
  80% {
    transform: translateX(3px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .zona-subida::after,
  .zona-subida__icono,
  .zona-subida.arrastrando .zona-subida__icono,
  .sacudir {
    animation: none;
  }

  .zona-subida.arrastrando {
    transform: none;
  }
}

.zona-subida__texto {
  font-weight: 700;
  color: var(--c-marino-900);
}

.zona-subida__separador {
  font-size: var(--texto-s);
  color: var(--c-texto-suave);
}

.zona-subida__botones {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--esp-3);
}

.zona-subida__formatos {
  font-size: var(--texto-xs);
  color: var(--c-texto-suave);
}

/* En ESCRITORIO (ratón + hover) no se ofrece «Hacer una foto»: encuadrar una
   factura con la webcam es incómodo y la vía de siempre (elegir archivo /
   arrastrar) es mejor. Mismo criterio de puntero que «añadir hoja» del funnel.js
   (§6.41): puntero fino + hover = ratón; en táctil (dedo) el botón se queda. El
   input de cámara nunca se usa en escritorio (funnel.js decide por puntero). */
@media (hover: hover) and (pointer: fine) {
  .zona-subida__foto {
    display: none;
  }
}

/* ---------- Modo foto (solo táctil) ---------- */
/* Lo enciende funnel.js al tomar la primera foto añadiendo `--modo-foto` a la
   zona: la caja deja de invitar a arrastrar/soltar y se centra en la cámara.
   Todo se muestra/oculta por la CLASE DE CONTENEDOR, nunca por `[hidden]` sobre
   un elemento con `display` de autor (§6.70). */
.zona-subida__foto-modo {
  display: none;
}

.zona-subida--modo-foto {
  cursor: default;
  gap: var(--esp-3);
}

/* Se apaga el «ruido» de la zona de arrastre: icono, textos, separador, los
   botones y la nota de formatos. Todo por clase de contenedor. */
.zona-subida--modo-foto .zona-subida__icono,
.zona-subida--modo-foto .zona-subida__texto,
.zona-subida--modo-foto .zona-subida__separador,
.zona-subida--modo-foto .zona-subida__botones,
.zona-subida--modo-foto .zona-subida__formatos {
  display: none;
}

.zona-subida--modo-foto .zona-subida__foto-modo {
  display: flex;
  flex-direction: column;
  gap: var(--esp-3);
  width: 100%;
}

/* En modo foto, el preview grande y la lista de hojas sobran: manda la rejilla
   de miniaturas de la propia zona. Se ocultan por CLASE DE CONTENEDOR (hermanos
   de `.zona-subida`), no por `[hidden]` sobre un elemento con `display` (§6.70).
   Al salir del modo foto la regla deja de aplicar y vuelven a mandar sus propios
   estados JS. */
.zona-subida--modo-foto ~ .factura-preview,
.zona-subida--modo-foto ~ .paginas-extra {
  display: none;
}

.zona-subida__foto-cab {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--esp-2);
  width: 100%;
}

.zona-subida__foto-titulo {
  margin: 0;
  font-weight: 700;
  color: var(--c-marino-900);
}

.zona-subida__contador {
  flex: none;
  display: inline-flex;
  align-items: center;
  padding: 0.15rem 0.6rem;
  border-radius: var(--radio-pill);
  background: var(--c-marino-100);
  color: var(--c-marino-800);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.zona-subida__miniaturas {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(4.75rem, 1fr));
  gap: var(--esp-2);
  width: 100%;
}

.foto-mini {
  position: relative;
  aspect-ratio: 3 / 4;
  border-radius: var(--radio-s);
  overflow: hidden;
  border: 1px solid var(--c-borde);
  background: var(--c-blanco);
}

.foto-mini__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.foto-mini__num {
  position: absolute;
  left: 4px;
  bottom: 4px;
  min-width: 1.2rem;
  padding: 0 0.25rem;
  border-radius: var(--radio-s);
  background: rgba(11, 26, 51, 0.72);
  color: var(--c-blanco);
  font-size: var(--texto-xs);
  font-weight: 700;
  text-align: center;
  line-height: 1.3;
}

.foto-mini__quitar {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 1.6rem;
  height: 1.6rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 50%;
  background: rgba(11, 26, 51, 0.72);
  color: var(--c-blanco);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
}

.foto-mini__quitar:hover,
.foto-mini__quitar:focus-visible {
  background: var(--c-error);
}

/* Estado de subida en modo foto (el preview grande, que trae la barra, está
   oculto aquí). Se muestra por CLASE, no por `[hidden]` (§6.70). */
.zona-subida__foto-estado {
  display: none;
  margin: 0;
  font-size: var(--texto-s);
  font-weight: 600;
  color: var(--c-marino-800);
}

.zona-subida__foto-estado.visible {
  display: block;
}

.zona-subida__foto-estado.es-ok {
  color: var(--c-exito);
}

.zona-subida__foto-acciones {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--esp-2) var(--esp-3);
  width: 100%;
}

.zona-subida__foto-otra {
  gap: 0.5rem;
}

.zona-subida__foto-otra[disabled] {
  opacity: 0.55;
  cursor: not-allowed;
}

.zona-subida__foto-salir {
  background: transparent;
  border: 0;
  padding: 0.4rem 0.6rem;
  color: var(--c-texto-suave);
  font: 600 0.92rem var(--fuente);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.zona-subida__foto-salir:hover,
.zona-subida__foto-salir:focus-visible {
  color: var(--lg-blue);
}

.zona-subida__foto-salir:focus-visible {
  outline: 2px solid var(--c-foco);
  outline-offset: 3px;
  border-radius: var(--radio-s);
}

.zona-subida__foto-ayuda {
  margin: 0;
  font-size: var(--texto-xs);
  color: var(--c-texto-suave);
  text-align: center;
}

/* Entrada suave de cada miniatura al tomarla — tras la puerta de motion; el
   estado oculto vive DENTRO de la @keyframes (`both` + from), así que sin motion
   no falta nada (§6.5). */
@media (prefers-reduced-motion: no-preference) {
  .foto-mini {
    animation: nz-foto-entra 320ms var(--rebote) both;
  }
  @keyframes nz-foto-entra {
    from {
      opacity: 0;
      transform: scale(0.9);
    }
    to {
      opacity: 1;
      transform: none;
    }
  }
}

/* Previsualización del archivo */
.factura-preview {
  display: flex;
  align-items: center;
  gap: var(--esp-3);
  margin-top: clamp(0.6rem, 1.6vh, 1.5rem);
  padding: clamp(0.6rem, 1.6vh, 1rem);
  border: 1px solid var(--c-borde);
  border-radius: var(--radio-m);
  background: var(--c-exito-fondo);
}

.factura-preview[hidden] {
  display: none;
}

.factura-preview__miniatura {
  flex: none;
  width: 3.5rem;
  height: 3.5rem;
  border-radius: var(--radio-s);
  object-fit: cover;
  border: 1px solid var(--c-borde);
  background: var(--c-blanco);
}

.factura-preview__icono {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3.5rem;
  height: 3.5rem;
  border-radius: var(--radio-s);
  background: var(--c-blanco);
  border: 1px solid var(--c-borde);
  color: var(--c-marino-700);
}

.factura-preview__icono svg {
  width: 1.6rem;
  height: 1.6rem;
}

.factura-preview__datos {
  min-width: 0;
  flex: 1;
}

.factura-preview__nombre {
  font-weight: 700;
  color: var(--c-marino-900);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.factura-preview__detalle {
  font-size: var(--texto-xs);
  color: var(--c-texto-suave);
}

/* Entrada del fichero en la caja (aparece con pop al seleccionarlo) */
.factura-preview.entrando {
  animation: nz-archivo-entra 420ms var(--rebote) both;
}

@keyframes nz-archivo-entra {
  from {
    opacity: 0;
    transform: translateY(-14px) scale(0.96);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* Progreso real de subida: barra con transform: scaleX (GPU) */
.factura-preview__progreso {
  display: flex;
  align-items: center;
  gap: var(--esp-2);
  margin-top: var(--esp-2);
}

.factura-preview__barra {
  flex: 1;
  display: block;
  height: 6px;
  border-radius: var(--radio-pill);
  background: var(--c-marino-100);
  overflow: hidden;
}

.factura-preview__barra-relleno {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--c-marino-700), var(--c-amarillo-500));
  transform-origin: left center;
  transform: scaleX(0);
  transition: transform 180ms ease-out;
}

.factura-preview__porcentaje {
  flex: none;
  min-width: 3ch;
  font-size: var(--texto-xs);
  font-weight: 700;
  color: var(--c-marino-800);
  font-variant-numeric: tabular-nums;
}

/* Check de éxito al confirmar el servidor */
.factura-preview__exito {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  background: var(--c-exito);
  color: var(--c-blanco);
}

.factura-preview__exito svg {
  width: 1.1rem;
  height: 1.1rem;
}

.factura-preview__exito:not([hidden]) {
  animation: nz-check-pop 420ms var(--rebote) both;
}

.factura-preview.con-error {
  background: var(--c-error-fondo);
  border-color: var(--c-error);
}

.factura-preview__cambiar {
  flex: none;
}

/* En móvil la fila del preview NO cabe de un solo renglón: miniatura + datos +
   check de éxito + botón «Cambiar archivo» (flex:none, ~150px) sumaban más que
   el ancho de la tarjeta, así que `__datos` (flex:1, aunque tiene min-width:0)
   se aplastaba a ~40px, el detalle se apilaba palabra a palabra en vertical y
   el botón desbordaba la caja ~73px (medido 2026-08-30 a 390px). Se deja que la
   fila SE AJUSTE: `__datos` reserva una base ancha para que el botón caiga a su
   propia línea (alineado a la derecha), y así el NOMBRE recupera ancho y se
   trunca con "…" en lugar de romper la caja. En escritorio todo cabe en un
   renglón y nada de esto llega a activarse (el wrap nunca dispara). */
@media (max-width: 559px) {
  .factura-preview {
    flex-wrap: wrap;
  }
  .factura-preview__datos {
    flex: 1 1 60%;
  }
  .factura-preview__cambiar {
    margin-left: auto;
  }
}

@media (prefers-reduced-motion: reduce) {
  .factura-preview.entrando,
  .factura-preview__exito:not([hidden]) {
    animation: none;
  }

  .factura-preview__barra-relleno {
    transition: none;
  }
}

.nota-seguridad {
  display: flex;
  align-items: flex-start;
  gap: var(--esp-2);
  margin-top: clamp(0.6rem, 1.6vh, 1rem);
  font-size: clamp(0.8125rem, 1.7vh, 0.9375rem);
  color: var(--c-texto-suave);
}

.nota-seguridad svg {
  flex: none;
  width: 1.1rem;
  height: 1.1rem;
  margin-top: 0.2rem;
  color: var(--c-exito);
}

/* ---------- Paso 2: datos ---------- */
.form-datos {
  margin-top: clamp(0.6rem, 1.8vh, 1.5rem);
}

/* Grid 2 col en TODOS los anchos: teléfono y CP comparten fila (compacto);
   nombre y email van a ancho completo (legibilidad). */
.form-datos .campo {
  margin-bottom: clamp(0.5rem, 1.4vh, 1rem);
}

.form-datos .campo__entrada {
  padding: clamp(0.5rem, 1.3vh, 0.8rem) 1rem;
}

/* Selector segmentado de tipo de cliente (radios nativos + thumb animado) */
.campo--segmentos {
  border: 0;
  padding: 0;
  margin: 0 0 var(--esp-4);
}

.campo--segmentos legend {
  padding: 0;
  margin-bottom: var(--esp-1);
}

/* Una sola fila de 4 segmentos en todos los anchos (altura mínima);
   el texto escala con el viewport para caber a 360px */
.segmentos {
  position: relative;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 4px;
  padding: 4px;
  border: 1.5px solid var(--c-borde);
  border-radius: var(--radio-m);
  background: var(--c-fondo-suave);
}

/* Thumb: se posiciona por transform desde funnel.js (GPU) */
.segmentos__thumb {
  position: absolute;
  top: 0;
  left: 0;
  border-radius: calc(var(--radio-m) - 4px);
  background: var(--c-marino-900);
  box-shadow: var(--sombra-1);
  transition: transform 300ms var(--rebote);
  pointer-events: none;
}

.segmentos__thumb.sin-transicion {
  transition: none;
}

.segmentos__opcion {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: clamp(2.1rem, 4.6vh, 2.6rem);
  padding: 0.3rem 0.5rem;
  border-radius: calc(var(--radio-m) - 4px);
  cursor: pointer;
  text-align: center;
}

.segmentos__radio {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.segmentos__texto {
  font-size: clamp(0.72rem, 2.4vw, 0.9375rem);
  font-weight: 700;
  color: var(--c-texto-suave);
  transition: color var(--trans-rapida);
  white-space: nowrap;
}

.segmentos__opcion:hover .segmentos__texto {
  color: var(--c-marino-900);
}

.segmentos__radio:checked ~ .segmentos__texto {
  color: var(--c-blanco);
}

.segmentos__radio:focus-visible ~ .segmentos__texto {
  outline: 3px solid var(--c-foco);
  outline-offset: 4px;
  border-radius: var(--radio-s);
}

@media (prefers-reduced-motion: reduce) {
  .segmentos__thumb {
    transition: none;
  }
}

/* Táctil y legible en móvil: la opción medía 39px de alto (1px bajo el umbral
   de 44) y su texto caía al suelo del clamp, 11.5px. Se sube el mínimo táctil
   a 44px y el texto a 12px; el padding lateral cede (0.2rem) para aprovechar
   el ancho. A 12px la fila de cuatro ya NO cabe en los móviles estrechos:
   de eso se ocupa el 2×2 de más abajo (≤26rem). Solo móvil. */
@media (max-width: 40rem) {
  .segmentos__opcion {
    min-height: 2.75rem;
    padding: 0.3rem 0.2rem;
  }

  .segmentos__texto {
    font-size: clamp(0.75rem, 3.2vw, 0.9375rem);
  }
}

/* Por debajo de ~416px ni 12px caben en UNA fila de cuatro («Particular …
   Comunidad» desbordaba la tarjeta a 360px, medido 2026-08-28): el selector
   pasa a 2×2 — cuatro opciones, rectángulo completo (§6.5), cada una ancha y
   de 44px. El thumb no se entera: mide `offsetLeft/offsetTop` en vivo
   (funnel.js `moverThumb`), también en dos filas. */
@media (max-width: 26rem) {
  .segmentos {
    grid-template-columns: repeat(2, 1fr);
  }
}

.form-datos__rejilla {
  display: grid;
  gap: 0 var(--esp-3);
  /* minmax(0, 1fr) y NO `1fr 1fr`: el mínimo implícito de un `1fr` es el
     min-content del contenido, y un <input> sin `size` mide ~152px de
     intrínseco. En un móvil de 390 la tarjeta deja ~284px para la rejilla y
     los dos tracks computaban 152.5+152.5+gap = 317px: TODOS los campos
     (también los de fila entera, que abarcan ambos tracks) desbordaban la
     tarjeta 16px por la derecha (medido 2026-08-28). Con el mínimo a 0 los
     tracks reparten el ancho REAL y nada se sale. En escritorio no cambia
     nada: allí los tracks van sobrados y el mínimo nunca manda. */
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

/* La otra mitad del mismo desborde: el ITEM de rejilla también tiene mínimo
   automático (min-width: auto = su min-content) y pintaría por fuera de un
   track ya encogido. Sin efecto donde los tracks son anchos. */
.form-datos__rejilla > .campo {
  min-width: 0;
}

.campo--ancho {
  grid-column: 1 / -1;
}

/* ---------- Paso 3: consentimientos ---------- */
.consentimientos {
  border: 0;
  margin: clamp(0.6rem, 1.8vh, 1.5rem) 0 0;
  padding: 0;
  display: grid;
  gap: clamp(0.5rem, 1.4vh, 1rem);
}

.consentimiento {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: clamp(0.25rem, 0.8vh, 0.5rem) var(--esp-3);
  padding: clamp(0.6rem, 1.6vh, 1rem);
  border: 1px solid var(--c-borde);
  border-radius: var(--radio-m);
  cursor: pointer; /* toda la fila es clicable (funnel.js) */
  transition: border-color var(--trans-rapida), background-color var(--trans-rapida);
}

.consentimiento:hover {
  border-color: var(--c-borde-fuerte);
}

.consentimiento:focus-within {
  border-color: var(--c-marino-700);
  box-shadow: 0 0 0 3px var(--c-marino-100);
}

.consentimiento:has(input:checked) {
  border-color: var(--c-exito);
  background: var(--c-exito-fondo);
}

.consentimiento.con-error {
  border-color: var(--c-error);
  background: var(--c-error-fondo);
}

.consentimiento__casilla {
  width: 1.4rem;
  height: 1.4rem;
  margin-top: 0.15rem;
  accent-color: var(--c-marino-800);
  cursor: pointer;
}

/* Táctil móvil: 22px de casilla quedaba al límite del objetivo de 40-44px
   (el label asociado salva el área real, pero la marca visible era pequeña
   justo donde se decide sobre datos personales). Solo en móvil: en
   escritorio la maqueta aprobada no cambia. */
@media (max-width: 40rem) {
  .consentimiento__casilla {
    width: 1.6rem;
    height: 1.6rem;
  }
}

.consentimiento__etiqueta {
  cursor: pointer;
  font-weight: 600;
  font-size: clamp(0.85rem, 1.8vh, 1rem);
  line-height: 1.45;
  color: var(--c-texto);
}

.etiqueta-tipo {
  display: inline-block;
  margin-left: var(--esp-2);
  padding: 0.1rem 0.6rem;
  border-radius: var(--radio-pill);
  font-size: var(--texto-xs);
  font-weight: 700;
  vertical-align: middle;
  white-space: nowrap;
}

.etiqueta-tipo--obligatorio {
  background: var(--c-marino-100);
  color: var(--c-marino-800);
}

.etiqueta-tipo--opcional {
  background: var(--c-fondo-suave);
  border: 1px solid var(--c-borde);
  color: var(--c-texto-suave);
}

.consentimiento__detalle {
  grid-column: 2;
  margin: 0;
  font-size: var(--texto-xs);
  color: var(--c-texto-suave);
}

.consentimiento .campo__error {
  grid-column: 2;
}

.consentimientos__nota {
  display: flex;
  gap: var(--esp-2);
  margin-top: clamp(0.5rem, 1.4vh, 1rem);
  font-size: var(--texto-xs);
  color: var(--c-texto-suave);
}

.consentimientos__nota svg {
  flex: none;
  width: 1rem;
  height: 1rem;
  margin-top: 0.15rem;
  color: var(--c-marino-600);
}

/* ---------- Paso 4: análisis ---------- */
.analisis {
  text-align: center;
  padding-block: clamp(0.5rem, 2vh, 2rem);
}

/* Escáner de factura: tarjeta-factura estilizada (skeleton) que un barrido
   láser azul-gas recorre; a su paso las líneas de dato se "detectan" con un
   tick. Decorativo (aria-hidden). Cohesión con el fondo blueprint del funnel:
   papel frío + retícula fina azul desaturada; la tarjeta es el FOCO (capa con
   sombra, sobre el panel blanco). TODO el movimiento vive tras la puerta de
   motion (más abajo); en reposo la factura se ve YA leída y quieta. */
.escaner {
  --scan-azul: var(--lg-blue);
  --scan-azul-claro: var(--lg-blue-light);
  /* Estado "sin detectar" (solo dentro de la puerta de motion) */
  --scan-muted: color-mix(in srgb, var(--c-marino-600) 42%, var(--lz-papel));
  --scan-muted-bg: color-mix(in srgb, var(--c-marino-600) 15%, var(--lz-papel));
  --scan-linea: color-mix(in srgb, var(--c-marino-600) 16%, var(--lz-papel));
  --scan-regla: color-mix(in srgb, var(--lg-blue) 12%, transparent);
  --scan-dur: 3.1s;   /* un barrido completo; bucle mientras dura la llamada */
  --scan-paso: 0.34s; /* desfase entre filas para el cascadeo de detección */
  width: min(20rem, 82vw);
  margin: 0 auto clamp(0.9rem, 2.4vh, 1.75rem);
  perspective: 900px;
}

.escaner__factura {
  position: relative;
  overflow: hidden;
  display: grid;
  gap: clamp(0.5rem, 1.4vh, 0.85rem);
  padding: clamp(0.85rem, 2.2vh, 1.35rem);
  text-align: left;
  border: 1px solid var(--c-borde);
  border-radius: var(--radius-gota-s);
  background-color: var(--lz-papel);
  background-image:
    linear-gradient(var(--scan-regla) 1px, transparent 1px),
    linear-gradient(90deg, var(--scan-regla) 1px, transparent 1px);
  background-size: 1.25rem 1.25rem;
  box-shadow: 0 12px 30px -18px rgba(11, 26, 51, 0.55),
    0 2px 6px -4px rgba(11, 26, 51, 0.22);
}

/* Barrido láser: banda azul semitransparente con filo brillante al frente.
   Reposo = invisible (opacity 0); el movimiento la enciende y la desplaza. */
.escaner__laser {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  z-index: 2;
  height: 46%;
  opacity: 0;
  pointer-events: none;
  transform: translateY(-72%);
  background: linear-gradient(
    to bottom,
    transparent 0%,
    color-mix(in srgb, var(--scan-azul) 12%, transparent) 60%,
    color-mix(in srgb, var(--scan-azul-claro) 32%, transparent) 92%,
    color-mix(in srgb, var(--scan-azul-claro) 55%, transparent) 100%
  );
}
.escaner__laser::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background: var(--scan-azul-claro);
  box-shadow: 0 0 9px 1px color-mix(in srgb, var(--scan-azul-claro) 70%, transparent);
}

/* Cabecera: bloque de marca + dos líneas de título */
.escaner__cabecera {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding-bottom: clamp(0.3rem, 1vh, 0.55rem);
  border-bottom: 1px solid var(--scan-regla);
}
.escaner__logo {
  flex: none;
  width: 1.9rem;
  height: 1.9rem;
  border-radius: var(--radius-gota-s);
  background: color-mix(in srgb, var(--lg-blue) 16%, var(--lz-papel));
}
.escaner__titulos {
  flex: 1;
  display: grid;
  gap: 0.34rem;
}

/* Barras skeleton reutilizables */
.escaner__linea {
  height: 0.5rem;
  border-radius: var(--radio-pill);
  background: var(--scan-linea);
}
.escaner__linea--titulo { width: 62%; height: 0.6rem; }
.escaner__linea--corta  { width: 38%; }
.escaner__linea--larga  { width: 88%; }
.escaner__linea--media  { width: 64%; }

.escaner__pie {
  display: grid;
  gap: 0.34rem;
  padding-top: clamp(0.3rem, 1vh, 0.5rem);
  border-top: 1px solid var(--scan-regla);
}

/* Filas de dato que se detectan al paso del láser */
.escaner__datos {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: clamp(0.4rem, 1.1vh, 0.6rem);
}
.escaner__dato {
  display: grid;
  grid-template-columns: 1.3rem 1fr auto;
  align-items: center;
  gap: 0.55rem;
  --fila: 0;
}
.escaner__dato:nth-child(2) { --fila: 1; }
.escaner__dato:nth-child(3) { --fila: 2; }
.escaner__dato:nth-child(4) { --fila: 3; }

.escaner__dato-ico {
  width: 1.25rem;
  height: 1.25rem;
  color: var(--scan-azul); /* reposo = detectado */
}
.escaner__dato-ico svg {
  width: 100%;
  height: 100%;
}
.escaner__dato-barra {
  height: 0.5rem;
  border-radius: var(--radio-pill);
  background: var(--scan-linea);
}
.escaner__dato:nth-child(1) .escaner__dato-barra { width: 70%; }
.escaner__dato:nth-child(2) .escaner__dato-barra { width: 54%; }
.escaner__dato:nth-child(3) .escaner__dato-barra { width: 62%; }
.escaner__dato:nth-child(4) .escaner__dato-barra { width: 46%; }

.escaner__dato-val {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  color: var(--scan-azul); /* reposo = detectado */
}
.escaner__dato-chip {
  width: 1.7rem;
  height: 0.5rem;
  border-radius: var(--radio-pill);
  transform-origin: left center;
  background: color-mix(in srgb, var(--scan-azul) 30%, var(--lz-papel));
}
.escaner__tick {
  width: 0.9rem;
  height: 0.9rem;
  color: var(--scan-azul);
}

@keyframes nz-latido {
  0%,
  100% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.12);
  }
}

/* ---- Movimiento del escáner: TODO tras la puerta de motion. Sin ella, la
   factura queda leída y quieta (bloque de arriba). Solo transform/opacity/
   color (compositor); nada de layout. Bucle infinito: no promete un tiempo
   fijo, "sigue leyendo" mientras dura la llamada. ---- */
@media (prefers-reduced-motion: no-preference) {
  .escaner__laser {
    animation: escaner-barre var(--scan-dur) linear infinite;
    will-change: transform, opacity;
  }

  /* El color de cada fila lo controla el padre .escaner__dato (currentColor
     lo heredan icono, valor y tick); el chip y el tick animan su forma. */
  .escaner__dato-ico,
  .escaner__dato-val {
    color: inherit;
  }
  .escaner__dato {
    color: var(--scan-muted);
    animation: escaner-detecta var(--scan-dur) ease-out infinite both;
    animation-delay: calc(var(--fila) * var(--scan-paso));
  }
  .escaner__dato-chip {
    transform: scaleX(0);
    background: var(--scan-muted-bg);
    animation: escaner-chip var(--scan-dur) ease-out infinite both;
    animation-delay: calc(var(--fila) * var(--scan-paso));
  }
  .escaner__tick {
    opacity: 0;
    transform: scale(0.2);
    /* firma de la gota en el "pop" del tick */
    animation: escaner-tick var(--scan-dur) var(--ease-gota) infinite both;
    animation-delay: calc(var(--fila) * var(--scan-paso));
  }

  @keyframes escaner-barre {
    0%   { transform: translateY(-72%); opacity: 0; }
    10%  { opacity: 0.95; }
    82%  { opacity: 0.95; }
    100% { transform: translateY(142%); opacity: 0; }
  }
  @keyframes escaner-detecta {
    0%, 14% { color: var(--scan-muted); }
    24%     { color: var(--scan-azul); }
    100%    { color: var(--scan-azul); }
  }
  @keyframes escaner-chip {
    0%, 14% { transform: scaleX(0); background: var(--scan-muted-bg); }
    24%     { transform: scaleX(1); background: color-mix(in srgb, var(--scan-azul) 30%, var(--lz-papel)); }
    100%    { transform: scaleX(1); background: color-mix(in srgb, var(--scan-azul) 30%, var(--lz-papel)); }
  }
  @keyframes escaner-tick {
    0%, 15% { opacity: 0; transform: scale(0.2); }
    27%     { opacity: 1; transform: scale(1); }
    100%    { opacity: 1; transform: scale(1); }
  }
}

.analisis__mensaje {
  min-height: 2.6em;
  font-size: clamp(1rem, 2.2vh, 1.25rem);
  font-weight: 700;
  color: var(--c-marino-900);
  transition: opacity 260ms ease, transform 260ms ease;
}

.analisis__mensaje.saliendo {
  opacity: 0;
  transform: translateY(8px);
}

/* Fases estimadas del análisis con checks progresivos */
.analisis__fases {
  display: inline-grid;
  gap: clamp(0.35rem, 1.2vh, 0.75rem);
  list-style: none;
  margin: clamp(0.5rem, 1.8vh, 1.5rem) auto 0;
  padding: 0;
  text-align: left;
}

.analisis__fase {
  display: flex;
  align-items: center;
  gap: var(--esp-3);
  font-size: clamp(0.8125rem, 1.8vh, 0.9375rem);
  font-weight: 600;
  color: var(--c-texto-suave);
  opacity: 0.55;
  transition: opacity var(--trans-media), color var(--trans-media);
}

.analisis__fase.activa,
.analisis__fase.hecha {
  opacity: 1;
}

.analisis__fase.activa {
  color: var(--c-marino-900);
}

.analisis__fase.hecha {
  color: var(--c-exito);
}

.analisis__fase-icono {
  position: relative;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 50%;
  border: 2px solid var(--c-borde-fuerte);
  background: var(--c-blanco);
  transition: border-color var(--trans-media), background-color var(--trans-media);
}

.analisis__fase.activa .analisis__fase-icono {
  border-color: var(--c-marino-700);
}

.analisis__fase.hecha .analisis__fase-icono {
  border-color: var(--c-exito);
  background: var(--c-exito);
  color: var(--c-blanco);
}

.analisis__fase-punto {
  width: 0.45rem;
  height: 0.45rem;
  border-radius: 50%;
  background: var(--c-marino-700);
  opacity: 0;
  transform: scale(0.4);
  transition: opacity var(--trans-rapida), transform var(--trans-rapida);
}

.analisis__fase.activa .analisis__fase-punto {
  opacity: 1;
  animation: nz-latido 1.2s ease-in-out infinite;
}

.analisis__fase-check {
  position: absolute;
  width: 0.85rem;
  height: 0.85rem;
  opacity: 0;
  transform: scale(0.3);
}

.analisis__fase.hecha .analisis__fase-punto {
  opacity: 0;
}

.analisis__fase.hecha .analisis__fase-check {
  animation: nz-check-pop 380ms var(--rebote) both;
}

.analisis__nota {
  margin-top: clamp(0.5rem, 1.8vh, 1.5rem);
  font-size: var(--texto-xs);
  color: var(--c-texto-suave);
}

@media (prefers-reduced-motion: reduce) {
  .analisis__mensaje,
  .analisis__fase.activa .analisis__fase-punto,
  .analisis__fase.hecha .analisis__fase-check {
    transition: none;
    animation: none;
  }

  .analisis__fase.activa .analisis__fase-punto {
    opacity: 1;
    transform: scale(1);
  }

  .analisis__fase.hecha .analisis__fase-check {
    opacity: 1;
    transform: scale(1);
  }
}

/* Estado de error del análisis */
.analisis-error {
  max-width: 34rem;
  margin: 0 auto;
  text-align: center;
  padding-block: var(--esp-4);
}

.analisis-error__icono {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 4rem;
  height: 4rem;
  border-radius: 50%;
  background: var(--c-aviso-fondo);
  color: var(--c-aviso);
  margin-bottom: var(--esp-4);
}

.analisis-error__icono svg {
  width: 2rem;
  height: 2rem;
}

.analisis-error__titulo {
  font-size: var(--texto-xl);
  color: var(--c-marino-900);
}

.analisis-error__texto {
  margin-top: var(--esp-3);
  color: var(--c-texto-suave);
}

.analisis-error__acciones {
  display: flex;
  flex-wrap: wrap;
  gap: var(--esp-3);
  justify-content: center;
  margin-top: var(--esp-6);
}

/* ---------- Paso 5: resultado ---------- */

/* Composición principal: pensada para caber ENTERA en el viewport */
.resultado__principal {
  display: flex;
  flex-direction: column;
}

.resultado__ahorro {
  text-align: center;
  padding: clamp(0.5rem, 1.4vh, 1rem) var(--esp-4);
  border-radius: var(--radio-l);
  background: linear-gradient(160deg, var(--c-marino-900), var(--c-marino-800));
  color: var(--c-texto-inverso);
  margin-top: clamp(0.4rem, 1.2vh, 0.75rem);
}

.resultado__ahorro-intro {
  font-size: clamp(0.8125rem, 1.7vh, 0.9375rem);
  color: var(--c-texto-inverso-suave);
}

/* Cifra y "al año" comparten línea: menos altura, más impacto */
.resultado__ahorro-linea {
  margin-top: 2px;
}

.resultado__ahorro-cifra {
  font-size: clamp(1.7rem, 4.6vh, 3rem);
  font-weight: 800;
  line-height: 1.05;
  color: var(--c-amarillo-400);
  font-variant-numeric: tabular-nums;
}

.resultado__ahorro-sufijo {
  margin-left: 0.4rem;
  font-size: clamp(0.9rem, 1.9vh, 1.0625rem);
  font-weight: 700;
  color: var(--c-blanco);
}

/* Datos clave extraídos, dentro del banner */
.resultado__ahorro-clave {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--esp-2);
  margin-top: clamp(0.4rem, 1.2vh, 0.75rem);
}

.resultado__ahorro-clave .chip-dato {
  background: rgba(255, 255, 255, 0.08);
  border-color: rgba(255, 255, 255, 0.16);
}

.resultado__ahorro-clave .chip-dato__etiqueta {
  color: var(--c-texto-inverso-suave);
}

.resultado__ahorro-clave .chip-dato__valor {
  color: var(--c-blanco);
}

.resultado__sin-ahorro .resultado__ahorro-clave .chip-dato {
  background: var(--c-blanco);
  border-color: var(--c-borde);
}

.resultado__sin-ahorro .resultado__ahorro-clave .chip-dato__etiqueta {
  color: var(--c-texto-suave);
}

.resultado__sin-ahorro .resultado__ahorro-clave .chip-dato__valor {
  color: var(--c-marino-900);
}

.resultado__ahorro-nota {
  margin-top: clamp(0.25rem, 0.8vh, 0.5rem);
  font-size: var(--texto-xs);
  color: var(--c-texto-inverso-suave);
}

.resultado__sin-ahorro {
  margin-top: clamp(0.6rem, 1.8vh, 1.25rem);
  padding: clamp(0.75rem, 2.2vh, 1.5rem);
  border-radius: var(--radio-l);
  background: var(--c-exito-fondo);
  border: 1px solid var(--c-exito);
  text-align: center;
}

.resultado__sin-ahorro h3 {
  color: var(--c-exito);
}

.resultado__sin-ahorro p {
  margin-top: var(--esp-2);
  color: var(--c-texto);
  font-size: var(--texto-s);
}

/* Apoyo del ahorro: % y coste mensual */
.resultado__ahorro-apoyo {
  margin-top: 2px;
  font-size: clamp(0.8rem, 1.7vh, 0.95rem);
  font-weight: 700;
  color: var(--c-blanco);
}

/* --- Datos extraídos (chips) al inicio del resultado --- */
.resultado__chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--esp-2);
  margin-top: clamp(0.3rem, 1vh, 0.6rem);
}

/* ============================================================
   RESULTADO v4 — la cifra ancla: el ahorro EXACTO de esta factura

   Mobile-first. La comparación grande es de COSTE TOTAL (lo que el
   cliente paga), no de €/kWh: ese duelo de precios unitarios se
   leía como "mitad de precio" cuando la factura bajaba un 1,5 %.
   ============================================================ */
.ahorro-factura {
  padding: clamp(0.7rem, 2vh, 1.15rem) clamp(0.75rem, 3vw, 1.25rem);
  border-radius: var(--radio-l);
  border: 1px solid var(--c-borde);
  background: var(--c-blanco);
  box-shadow: var(--sombra-1);
  text-align: center;
}

/* La forma del bloque cambia con el resultado, no solo el número. */
.ahorro-factura--ahorro {
  border-color: var(--c-exito);
  background: var(--c-exito-fondo);
}

.ahorro-factura--ajustado {
  border-color: var(--c-borde-fuerte);
  background: var(--c-fondo-suave);
}

.ahorro-factura--peor,
.ahorro-factura--sin_cifra {
  border-color: var(--c-borde-fuerte);
  background: var(--c-fondo-suave);
}

.ahorro-factura__etq {
  font-size: var(--texto-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--c-texto-suave);
}

/* Duelo de COSTES TOTALES: 51,44 € → 50,85 € */
.ahorro-factura__duelo {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: clamp(0.4rem, 2.5vw, 1rem);
  margin-top: clamp(0.35rem, 1.2vh, 0.6rem);
}

.ahorro-factura__lado {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  min-width: 5.5rem;
}

.ahorro-factura__lado-etq {
  font-size: var(--texto-xs);
  color: var(--c-texto-suave);
}

.ahorro-factura__lado-num {
  font-size: clamp(1.15rem, 3vh, 1.6rem);
  font-weight: 800;
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
  color: var(--c-texto);
}

.ahorro-factura__lado--actual .ahorro-factura__lado-num {
  color: var(--c-texto-suave);
}

.ahorro-factura--ahorro .ahorro-factura__lado--propio .ahorro-factura__lado-num {
  color: var(--c-exito);
}

.ahorro-factura__flecha {
  display: inline-flex;
  color: var(--c-texto-suave);
}

.ahorro-factura__flecha svg {
  width: 1.25rem;
  height: 1.25rem;
}

/* El delta, con la etiqueta cargando el signo (nunca un "-0,59 €" suelto) */
.ahorro-factura__delta {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  margin-top: clamp(0.35rem, 1.2vh, 0.6rem);
}

.ahorro-factura__delta-etq {
  font-size: var(--texto-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--c-texto-suave);
}

.ahorro-factura__delta-cifra {
  font-size: clamp(1.9rem, 5vh, 3rem);
  font-weight: 800;
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
  color: var(--c-texto);
}

.ahorro-factura__delta--positivo .ahorro-factura__delta-cifra { color: var(--c-exito); }
.ahorro-factura__delta--positivo .ahorro-factura__delta-cifra::before { content: '+'; }
/* Los casos malos SE PINTAN: ocultarlos sería la presentación que induce a
   error que este rediseño existe para evitar. */
.ahorro-factura__delta--negativo .ahorro-factura__delta-cifra { color: var(--c-error); }
.ahorro-factura__delta--negativo .ahorro-factura__delta-cifra::before { content: '−'; }

.ahorro-factura__declaracion {
  margin-top: clamp(0.3rem, 1vh, 0.55rem);
  font-size: var(--texto-xs);
  line-height: 1.45;
  color: var(--c-texto-suave);
  text-wrap: pretty;
}

/* ============================================================
   LAS DOS FACTURAS COMPARADAS (resultado) — mismo lenguaje visual
   que la demo del hero (.lzi-factura): papel cálido, tinta, radio
   gota, filas concepto ······ importe. Izquierda "Tu factura ahora",
   derecha "La misma, con luzgasia". Todo movimiento tras la puerta
   de motion, con el estado oculto DENTRO de la puerta.
   ============================================================ */
.fac-modulo {
  margin-top: clamp(0.4rem, 1.4vh, 0.9rem);
  display: flex;
  flex-direction: column;
}

.fac-modulo__titulo {
  font-family: var(--fuente-marca);
  font-size: clamp(0.9rem, 2vh, 1.1rem);
  font-weight: 700;
  color: var(--c-marino-900);
  text-align: center;
}

.fac-modulo__intro {
  margin-top: 1px;
  text-align: center;
  font-size: var(--texto-xs);
  color: var(--c-texto-suave);
}

/* Dos facturas, lado a lado SIEMPRE (es una comparación): en móvil encogen la
   tipografía en vez de apilarse, para no perder el "izquierda vs derecha". */
.fac-duelo {
  margin-top: clamp(0.5rem, 1.6vh, 1rem);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(0.4rem, 1.8vw, 0.9rem);
  align-items: start;
}

.fac {
  position: relative;
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: clamp(0.6rem, 1.8vh, 1rem) clamp(0.55rem, 2.2vw, 1rem) clamp(0.7rem, 2vh, 1.1rem);
  background: var(--lz-papel);
  color: var(--lz-tinta);
  border: 1px solid var(--lz-linea);
  border-radius: var(--radius-gota);
  box-shadow: var(--sombra-2);
  overflow: clip; /* recorta el sello de esquina */
}

/* La factura "con luzgasia" es la protagonista: borde ámbar y ligera elevación */
.fac--propia {
  border-color: var(--c-amarillo-500);
  box-shadow: var(--sombra-3);
}

.fac__cab {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.35rem;
  margin-bottom: clamp(0.4rem, 1.2vh, 0.7rem);
}

.fac__chip {
  font-family: var(--fuente-marca);
  font-weight: 700;
  font-size: 0.62rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.18rem 0.5rem;
  border-radius: var(--radio-pill);
}

.fac__chip--actual {
  background: color-mix(in srgb, var(--lz-tinta) 10%, var(--lz-papel));
  color: var(--lz-tinta-suave);
}

.fac__chip--propia {
  background: color-mix(in srgb, var(--c-amarillo-400) 34%, var(--lz-papel));
  color: #7a5800;
}

.fac__doc {
  font-family: var(--fuente-marca);
  font-size: clamp(0.62rem, 1.5vh, 0.72rem);
  font-weight: 600;
  color: var(--lz-tinta-suave);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.fac__cuerpo {
  display: grid;
  gap: clamp(0.3rem, 1vh, 0.5rem);
}

.fac__fila {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.35rem;
  font-size: clamp(0.68rem, 1.5vh, 0.8rem);
  line-height: 1.25;
}

.fac__concepto {
  display: grid;
  color: var(--lz-tinta);
  font-weight: 600;
  min-width: 0;
}

.fac__concepto small {
  font-weight: 400;
  font-size: 0.82em;
  color: var(--lz-tinta-suave);
}

.fac__puntos {
  flex: 1;
  min-width: 0.75rem;
  border-bottom: 2px dotted color-mix(in srgb, var(--lz-tinta) 22%, transparent);
  translate: 0 -0.28em;
}

.fac__importe {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  white-space: nowrap;
}

/* Fila donde se GANA (solo lado propio): subrayado de marcador ámbar bajo el
   concepto, marca estática de "aquí bajas". */
.fac__fila--gana .fac__concepto {
  background: linear-gradient(transparent 62%, color-mix(in srgb, var(--c-amarillo-400) 40%, transparent) 62%);
  align-self: start;
  padding-inline: 0.1rem;
}

.fac__fila--gana .fac__importe {
  color: var(--c-exito);
}

/* Anotación corta del ahorro (solo existe en filas ganadoras del lado propio) */
.fac__anota {
  flex-basis: 100%;
  justify-self: end;
  margin-left: auto;
  width: fit-content;
  max-width: 92%;
  font-size: 0.64rem;
  line-height: 1.25;
  font-weight: 600;
  color: var(--c-marino-700);
  background: color-mix(in srgb, var(--c-amarillo-400) 16%, var(--lz-papel));
  border-left: 3px solid var(--c-amarillo-500);
  padding: 0.22rem 0.45rem;
  border-radius: 0 var(--radius-vivo) var(--radius-vivo) 0;
}

.fac__total {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.4rem;
  margin-top: clamp(0.45rem, 1.4vh, 0.8rem);
  padding-top: clamp(0.35rem, 1vh, 0.55rem);
  border-top: 2px solid var(--lz-tinta);
  font-family: var(--fuente-marca);
}

.fac__total-etq {
  font-size: 0.66rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--lz-tinta-suave);
}

.fac__total-num {
  font-size: clamp(0.95rem, 2.2vh, 1.2rem);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.fac--propia .fac__total-num {
  color: var(--c-exito);
}

/* Honestidad del color: en el caso "peor"/sin ahorro (resultado sin
   celebración) el total propio SALE MÁS CARO — pintarlo de verde-éxito
   engañaría. Cae a tinta neutra para que el número hable por sí solo (el
   copy `resumen_peor` ya lo explica). */
.resultado--sin-celebracion .fac--propia .fac__total-num {
  color: var(--c-marino-950);
}

/* Sello de esquina "−X en esta factura": estampa en la esquina superior derecha
   de la factura propia. NO cubre el total (el importe sigue leyéndose). */
.fac__sello {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  line-height: 1;
  font-family: var(--fuente-marca);
  font-weight: 700;
  font-size: clamp(0.72rem, 1.7vh, 0.9rem);
  color: var(--c-marino-950);
  background: var(--c-amarillo-400);
  padding: 0.3rem 0.5rem;
  border-radius: var(--radius-gota-s);
  rotate: 3deg;
  box-shadow: var(--sombra-2);
}

.fac__sello small {
  font-size: 0.5rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

/* La cifra de ahorro, en grande, bajo las dos facturas */
.fac-ahorro {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  margin-top: clamp(0.5rem, 1.6vh, 1rem);
  padding: clamp(0.5rem, 1.6vh, 0.9rem) var(--esp-4);
  border-radius: var(--radio-l);
  text-align: center;
}

.fac-ahorro--positivo {
  background: linear-gradient(160deg, var(--c-marino-900), var(--c-marino-800));
}

.fac-ahorro--negativo,
.fac-ahorro--cero {
  background: var(--c-fondo-suave);
  border: 1px solid var(--c-borde);
}

.fac-ahorro__etq {
  font-size: var(--texto-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.fac-ahorro--positivo .fac-ahorro__etq {
  color: var(--c-texto-inverso-suave);
}

.fac-ahorro--negativo .fac-ahorro__etq,
.fac-ahorro--cero .fac-ahorro__etq {
  color: var(--c-texto-suave);
}

.fac-ahorro__num {
  font-size: clamp(1.7rem, 4.4vh, 2.9rem);
  font-weight: 800;
  line-height: 1.02;
  font-variant-numeric: tabular-nums;
}

.fac-ahorro--positivo .fac-ahorro__num { color: var(--c-amarillo-400); }
.fac-ahorro--positivo .fac-ahorro__num::before { content: "−"; }
.fac-ahorro--negativo .fac-ahorro__num { color: var(--c-error); }
.fac-ahorro--negativo .fac-ahorro__num::before { content: "+"; }
.fac-ahorro--cero .fac-ahorro__num { color: var(--c-marino-800); }

.fac-modulo__decl {
  margin-top: clamp(0.3rem, 1vh, 0.55rem);
  text-align: center;
  font-size: var(--texto-xs);
  line-height: 1.45;
  color: var(--c-texto-suave);
  text-wrap: pretty;
}

/* --- Movimiento: barrido de la factura propia + revelado de anotaciones y
   sello. TODO dentro de la puerta; el estado oculto vive AQUÍ, así que con
   reduced-motion (o sin soporte) las anotaciones y el sello se ven ya. --- */
@media (prefers-reduced-motion: no-preference) {
  /* Barrido ámbar que recorre la factura propia al revelarse (una vez) */
  .fac--propia::after {
    content: "";
    position: absolute;
    inset-inline: 0;
    top: 0;
    height: 42%;
    background: linear-gradient(180deg, color-mix(in srgb, var(--c-amarillo-400) 26%, transparent), transparent);
    opacity: 0;
    pointer-events: none;
  }

  .revelable.es-visible .fac--propia::after {
    animation: nz-fac-barrido 900ms var(--ease-gota) 260ms both;
  }

  @keyframes nz-fac-barrido {
    0% { opacity: 0.9; transform: translateY(-100%); }
    100% { opacity: 0; transform: translateY(240%); }
  }

  /* Anotaciones ocultas hasta que la secuencia marca su fila (.es-gana) */
  .fac__anota {
    opacity: 0;
    translate: 8px 0;
    transition: opacity 360ms ease, translate 360ms var(--ease-gota);
  }

  .fac__fila.es-gana .fac__anota {
    opacity: 1;
    translate: 0 0;
  }

  /* Latido breve de la fila al resaltarse */
  .fac__fila.es-gana .fac__importe {
    animation: nz-fac-gana 620ms var(--ease-gota) both;
  }

  @keyframes nz-fac-gana {
    0% { transform: scale(1); }
    45% { transform: scale(1.18); }
    100% { transform: scale(1); }
  }

  /* Sello oculto hasta el remate (.fac--rematada), entonces se estampa */
  .fac__sello {
    opacity: 0;
    scale: 1.5;
    rotate: 10deg;
  }

  .fac--rematada .fac__sello {
    animation: nz-fac-sello 520ms var(--ease-gota) both;
  }

  @keyframes nz-fac-sello {
    0% { opacity: 0; scale: 1.5; rotate: 10deg; }
    60% { opacity: 1; scale: 1; rotate: -4deg; }
    100% { opacity: 1; scale: 1; rotate: 3deg; }
  }
}

/* ---------- Resumen BREVE bajo las facturas (sustituye al formulario largo) ---------- */
.resultado-resumen {
  margin-top: clamp(0.5rem, 1.6vh, 1rem);
  text-align: center;
  text-wrap: pretty;
}

.resultado-resumen__linea {
  font-size: clamp(0.85rem, 1.9vh, 1rem);
  color: var(--c-marino-900);
  font-weight: 600;
}

.resultado-resumen__anual {
  margin-top: 2px;
  font-size: var(--texto-s);
  color: var(--c-exito);
  font-weight: 700;
}

.resultado-resumen__nota {
  margin-top: 3px;
  font-size: var(--texto-xs);
  color: var(--c-texto-suave);
}

/* ---------- Proyección anual (secundaria: SÍ es una aproximación) ---------- */
.proyeccion {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  margin-top: clamp(0.5rem, 1.6vh, 0.9rem);
  padding: clamp(0.5rem, 1.6vh, 0.85rem) var(--esp-4);
  border-radius: var(--radio-m);
  background: var(--c-marino-900);
  color: var(--c-texto-inverso);
  text-align: center;
}

.proyeccion__etq {
  font-size: var(--texto-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--c-texto-inverso-suave);
}

.proyeccion__cifra {
  font-size: clamp(1.4rem, 3.6vh, 2.1rem);
  font-weight: 800;
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
  color: var(--c-amarillo-400);
}

.proyeccion--negativa .proyeccion__cifra { color: var(--c-amarillo-100); }

/* Degradación sin `ahorro_factura`: la etiqueta es una frase, no un rótulo */
.proyeccion--fallback .proyeccion__etq {
  text-transform: none;
  letter-spacing: normal;
  font-weight: 400;
  font-size: var(--texto-s);
}

.proyeccion__linea {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 0.35rem;
}

.proyeccion__sufijo {
  font-size: var(--texto-s);
  font-weight: 700;
  color: var(--c-blanco);
}

.proyeccion__declaracion {
  margin-top: 2px;
  font-size: var(--texto-xs);
  line-height: 1.45;
  color: var(--c-texto-inverso-suave);
  text-wrap: pretty;
}

/* ============================================================
   Curva de sensibilidad — CSS puro, sin librerías de gráficas.
   "El ahorro crece con el consumo": es lo que convierte un
   +0,59 € en información útil en vez de en una decepción.
   ============================================================ */
.sensibilidad {
  margin-top: clamp(0.6rem, 1.8vh, 1rem);
  padding: clamp(0.6rem, 1.8vh, 1rem) clamp(0.6rem, 3vw, 1rem);
  border-radius: var(--radio-m);
  border: 1px solid var(--c-borde);
  background: var(--c-blanco);
}

.sensibilidad__titulo {
  font-size: var(--texto-s);
  font-weight: 700;
  color: var(--c-texto);
  text-align: center;
}

.sensibilidad__grafica {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  align-items: stretch;
  gap: clamp(0.4rem, 2.5vw, 1rem);
  margin-top: clamp(0.5rem, 1.6vh, 0.85rem);
  /* Alto fijo del área de barras: las columnas comparten línea base sin
     depender de lo largo que sea el texto de cada etiqueta. */
  min-height: 8.5rem;
  list-style: none;
}

.sensibilidad__punto {
  display: grid;
  grid-template-rows: auto 1fr auto auto;
  align-items: end;
  justify-items: center;
  gap: 2px;
  height: 100%;
}

.sensibilidad__valor {
  font-size: var(--texto-xs);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--c-exito);
}

.sensibilidad__punto--negativo .sensibilidad__valor { color: var(--c-error); }

.sensibilidad__barra-caja {
  display: flex;
  align-items: flex-end;
  width: 100%;
  height: 100%;
  min-height: 2.75rem;
}

/* Se escala por transform (GPU), no por height: sin recálculo de layout.
   Arranca a 0 y crece cuando el bloque se revela (`.es-visible`), igual que el
   resto de la composición del resultado. */
.sensibilidad__barra {
  width: 100%;
  height: 100%;
  border-radius: var(--radio-s) var(--radio-s) 2px 2px;
  background: linear-gradient(180deg, var(--c-marino-600), var(--c-marino-800));
  transform: scaleY(0);
  transform-origin: bottom center;
  transition: transform 600ms cubic-bezier(0.22, 1, 0.36, 1);
  transition-delay: calc(var(--animar-orden, 0) * 90ms);
}

.es-visible .sensibilidad__barra {
  transform: scaleY(var(--altura, 0.1));
}

.sensibilidad__punto--negativo .sensibilidad__barra {
  background: linear-gradient(180deg, var(--c-error), #7d1a15);
}

/* La barra de SU factura se distingue sin depender solo del color */
.sensibilidad__punto--suya .sensibilidad__barra {
  background: linear-gradient(180deg, var(--c-amarillo-500), var(--c-amarillo-500));
  outline: 2px solid var(--c-marino-900);
  outline-offset: -2px;
}

.sensibilidad__punto--suya .sensibilidad__etq {
  font-weight: 800;
  color: var(--c-marino-900);
}

.sensibilidad__etq {
  font-size: var(--texto-xs);
  line-height: 1.25;
  color: var(--c-texto-suave);
  text-align: center;
  text-wrap: balance;
}

.sensibilidad__kwh {
  font-size: 0.75rem;
  color: var(--c-texto-suave);
  font-variant-numeric: tabular-nums;
}

.sensibilidad__mensaje {
  margin-top: clamp(0.4rem, 1.2vh, 0.7rem);
  font-size: var(--texto-xs);
  line-height: 1.5;
  color: var(--c-texto);
  text-align: center;
  text-wrap: pretty;
}

@media (prefers-reduced-motion: reduce) {
  .sensibilidad__barra {
    transition: none;
    /* Sin movimiento la barra debe estar ya a su altura final: si se quedara
       en scaleY(0) la gráfica desaparecería para quien pide menos animación. */
    transform: scaleY(var(--altura, 0.1));
  }
}

/* ---------- Formas alternativas del resultado ---------- */
.sin-cifra,
.resultado__nota-forma {
  margin-top: clamp(0.5rem, 1.6vh, 0.9rem);
  padding: clamp(0.6rem, 2vh, 1rem) clamp(0.7rem, 3vw, 1.1rem);
  border-radius: var(--radio-m);
  border: 1px solid var(--c-borde-fuerte);
  background: var(--c-fondo-suave);
  text-align: center;
}

.resultado__nota-forma--ajustado {
  border-color: var(--c-aviso);
  background: var(--c-aviso-fondo);
}

.sin-cifra__titulo,
.resultado__nota-forma h3 {
  font-size: var(--texto-s);
  font-weight: 700;
  color: var(--c-texto);
}

.resultado__nota-forma--ajustado h3 { color: var(--c-aviso); }

.sin-cifra__texto,
.resultado__nota-forma p {
  margin-top: var(--esp-1);
  font-size: var(--texto-xs);
  line-height: 1.5;
  color: var(--c-texto);
  text-wrap: pretty;
}

/* Resultado que desaconseja el cambio: el CTA sigue disponible pero baja a
   secundario. Un botón amarillo de "Quiero contratar" debajo de "cambiarte
   ahora no te compensa" es la página contradiciéndose a sí misma. */
.resultado--sin-celebracion .resultado__cta .boton--primario {
  background: transparent;
  color: var(--c-marino-900);
  border: 1.5px solid var(--c-borde-fuerte);
  box-shadow: none;
}

.resultado--sin-celebracion .resultado__cta .boton--primario:hover {
  border-color: var(--c-marino-900);
  background: var(--c-fondo-suave);
}

/* ---------- Hallazgos (valor FUERA de la cifra de ahorro) ---------- */
.hallazgos {
  margin-top: clamp(0.6rem, 1.8vh, 1rem);
}

.hallazgos__lista {
  display: flex;
  flex-direction: column;
  gap: var(--esp-2);
  margin-top: var(--esp-2);
  list-style: none;
}

/* Sin banda izquierda ni fondo pastel (cliche de IA, retirado 2026-08-13):
   borde fino completo tenido y el ICONO que ya traia como marca de color. */
.hallazgos__item {
  display: flex;
  align-items: flex-start;
  gap: var(--esp-2);
  padding: var(--esp-2) var(--esp-3);
  border-radius: var(--radio-s);
  border: 1px solid var(--c-borde);
  background: var(--c-blanco);
  font-size: var(--texto-xs);
  line-height: 1.5;
  color: var(--c-texto);
}

.hallazgos__item--aviso { border-color: #ecdcbe; }
.hallazgos__item--aviso svg { color: var(--c-aviso); }
.hallazgos__item--importante { border-color: #eecdca; }
.hallazgos__item--importante svg { color: var(--c-error); }

.hallazgos__item svg { flex: 0 0 auto; width: 1rem; height: 1rem; margin-top: 0.15rem; }

/* ---------- Precio de la energía (DETALLE, con su aviso fiscal) ---------- */
.precio-energia {
  margin-top: clamp(0.6rem, 1.8vh, 1rem);
}

.precio-energia__fila {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--esp-1) var(--esp-3);
  margin-top: var(--esp-2);
  padding: var(--esp-3);
  border-radius: var(--radio-s);
  background: var(--c-fondo-suave);
  font-size: var(--texto-s);
}

.precio-energia__fila dt { color: var(--c-texto-suave); }
.precio-energia__fila dd {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.3rem;
  font-variant-numeric: tabular-nums;
  color: var(--c-texto);
}

.precio-energia__ud { font-size: var(--texto-xs); color: var(--c-texto-suave); }

/* Etiqueta del impuesto REALMENTE aplicado ("con IGIC 0 %", "con IPSI 1 %").
   Va pegada a la cifra final porque su función es que el cliente sepa contra
   qué impuesto cuadrar su factura, no adornar. */
.precio-energia__impuesto {
  font-size: var(--texto-xs);
  color: var(--c-texto-suave);
  white-space: nowrap;
}

/* La cifra SIN impuestos, en segunda línea (`flex-basis: 100%` fuerza el salto
   dentro del dd). Es secundaria: la que la ley obliga a destacar es la final. */
.precio-energia__neto {
  flex-basis: 100%;
  font-size: var(--texto-xs);
  color: var(--c-texto-suave);
}

.precio-energia__neto-etq { opacity: 0.85; }

/* Solo aparece fuera de península: explica por qué NO pone "IVA". */
.precio-energia__zona {
  margin-top: var(--esp-1);
  font-size: var(--texto-xs);
  line-height: 1.5;
  color: var(--c-texto-suave);
  text-wrap: pretty;
}

/* El aviso NO es letra pequeña decorativa: es lo que impide leer estos
   números como el precio final de la factura. */
.precio-energia__aviso {
  margin-top: var(--esp-2);
  padding: var(--esp-2) var(--esp-3);
  border-radius: var(--radio-s);
  border: 1px solid #ecdcbe;
  background: var(--c-blanco);
  font-size: var(--texto-xs);
  line-height: 1.5;
  color: var(--c-texto);
  text-wrap: pretty;
}

/* ============================================================
   Comparativa ANTES→DESPUÉS (LEGADO)
   Ya no la construye funnel.js: el titular es `.ahorro-factura`.
   Se conservan las reglas porque `.comparativa` sigue siendo el
   contenedor del bloque ancla en la plantilla.
   ============================================================ */
.comparativa {
  margin-top: clamp(0.4rem, 1.4vh, 0.9rem);
}

.comparativa__cuerpo {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: stretch;
  gap: clamp(0.35rem, 1.6vw, 0.9rem);
}

.comparativa__lado {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: clamp(0.5rem, 1.6vh, 0.9rem) clamp(0.4rem, 2vw, 0.85rem);
  border-radius: var(--radio-m);
  border: 1px solid var(--c-borde);
  background: var(--c-blanco);
  text-align: center;
}

.comparativa__lado--despues {
  border-color: var(--c-exito);
  background: var(--c-exito-fondo);
}

.comparativa__cab {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.3rem;
}

.comparativa__etq {
  font-size: var(--texto-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--c-texto-suave);
}

.comparativa__estrella {
  display: inline-flex;
  align-items: center;
  padding: 0.05rem 0.45rem;
  border-radius: var(--radio-pill);
  background: var(--c-amarillo-500);
  color: var(--c-marino-900);
  font-size: 0.6875rem;
  font-weight: 800;
}

.comparativa__precio {
  position: relative;
  display: inline-flex;
  align-items: baseline;
  gap: 0.2rem;
  margin-top: 2px;
}

.comparativa__precio-num {
  font-size: clamp(1.25rem, 3.4vh, 1.9rem);
  font-weight: 800;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.comparativa__precio-ud {
  font-size: var(--texto-xs);
  color: var(--c-texto-suave);
}

.comparativa__precio--tachado .comparativa__precio-num {
  color: var(--c-texto-suave);
}

/* Tachado rojo que se dibuja al revelarse la comparativa */
.comparativa__precio--tachado::after {
  content: "";
  position: absolute;
  left: -6%;
  right: -6%;
  top: 52%;
  height: 3px;
  border-radius: 2px;
  background: var(--c-error);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 480ms cubic-bezier(0.22, 0.7, 0.35, 1) 340ms;
}

.comparativa.es-visible .comparativa__precio--tachado::after {
  transform: scaleX(1);
}

.comparativa__precio--oferta .comparativa__precio-num {
  color: var(--c-exito);
}

/* El precio de la tarifa recomendada entra con overshoot al revelarse */
.comparativa.es-visible .comparativa__precio--oferta {
  animation: nz-precio-pop 560ms var(--rebote) 420ms both;
}

@keyframes nz-precio-pop {
  0% { opacity: 0; transform: scale(0.5); }
  60% { opacity: 1; transform: scale(1.18); }
  100% { opacity: 1; transform: scale(1); }
}

.comparativa.es-visible .comparativa__estrella {
  animation: nz-badge-pop 520ms var(--rebote) 520ms both;
}

.comparativa__contrato {
  font-size: var(--texto-xs);
  color: var(--c-marino-800);
  font-weight: 600;
}

.comparativa__comercializadora {
  font-size: var(--texto-s);
  font-weight: 800;
  color: var(--c-marino-900);
}

.comparativa__coste {
  font-size: var(--texto-xs);
  color: var(--c-texto-suave);
}

.comparativa__vs {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  color: var(--c-marino-700);
}

.comparativa__vs-texto {
  font-size: var(--texto-xs);
  font-weight: 800;
  text-transform: uppercase;
}

.comparativa__vs svg {
  width: clamp(1rem, 2.4vh, 1.4rem);
  height: clamp(1rem, 2.4vh, 1.4rem);
}

/* ---------- Contrato v2: comparativa sin "antes" ----------
   Cuando la factura no permite calcular el €/kWh actual, la mitad izquierda no
   se rellena con un cero ni con un guion: desaparece, y la propuesta pasa a
   ocupar el ancho completa con una nota que explica la ausencia. */
.comparativa__cuerpo--solo-oferta {
  grid-template-columns: 1fr;
  max-width: 26rem;
  margin-inline: auto;
}

/* Etiqueta de precio no numérica (tarifa indexada: "Precio de mercado +
   margen"). Menor que la cifra porque es texto, no un número que impacte. */
.comparativa__precio-etiqueta {
  font-size: clamp(0.95rem, 2.1vh, 1.2rem);
  font-weight: 800;
  line-height: 1.2;
  color: var(--c-exito);
  text-wrap: balance;
}

/* Sello "Estimado": marca el dato que hemos supuesto, no leído de la factura */
.comparativa__estimado {
  display: inline-flex;
  align-items: center;
  padding: 0.05rem 0.45rem;
  border-radius: var(--radio-pill);
  background: var(--c-aviso-fondo);
  color: var(--c-aviso);
  border: 1px solid rgba(122, 88, 0, 0.25);
  font-size: 0.6875rem;
  font-weight: 800;
}

.comparativa__nota,
.comparativa__nota-oferta {
  margin-top: clamp(0.35rem, 1.2vh, 0.7rem);
  font-size: var(--texto-xs);
  color: var(--c-texto-suave);
  text-align: center;
  text-wrap: pretty;
}

.comparativa__nota-oferta {
  margin-top: 0.25rem;
}

/* ============================================================
   Tramos horarios de la tarifa recomendada (Punta/Llano/Valle)
   ============================================================ */
.tramos {
  margin-top: clamp(0.4rem, 1.4vh, 0.85rem);
}

.tramos__titulo {
  margin: 0 0 clamp(0.25rem, 0.9vh, 0.5rem);
  font-size: var(--texto-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--c-texto-suave);
  text-align: center;
}

.tramos__lista {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(5.5rem, 1fr));
  gap: clamp(0.3rem, 1.4vw, 0.6rem);
  margin: 0;
  padding: 0;
  list-style: none;
}

.tramos__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  padding: clamp(0.3rem, 1vh, 0.5rem) 0.4rem;
  border: 1px solid var(--c-borde);
  border-top: 3px solid var(--c-marino-600);
  border-radius: var(--radio-s);
  background: var(--c-blanco);
  text-align: center;
}

/* El color del borde superior codifica la franja: punta cara → valle barata.
   Es refuerzo visual, nunca el único portador de la información (cada tramo
   lleva su nombre escrito). */
.tramos__item--p1 { border-top-color: var(--c-error); }
.tramos__item--p2 { border-top-color: var(--c-aviso); }
.tramos__item--p3 { border-top-color: var(--c-exito); }

.tramos__etq {
  font-size: 0.6875rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--c-texto-suave);
}

.tramos__valor {
  font-size: var(--texto-s);
  font-weight: 800;
  color: var(--c-marino-900);
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}

.tramos__ud {
  font-size: 0.6875rem;
  color: var(--c-texto-suave);
}

/* Entrada escalonada de los tramos (--animar-orden lo fija funnel.js) */
.revelable .tramos__item {
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 380ms ease, transform 380ms cubic-bezier(0.22, 0.7, 0.35, 1);
  transition-delay: calc(var(--animar-orden, 0) * 80ms + 520ms);
}

.revelable.es-visible .tramos__item {
  opacity: 1;
  transform: none;
}

/* ============================================================
   Declaraciones de estimación (qué hemos supuesto y qué hemos leído)
   ============================================================ */
.declaraciones {
  margin-top: clamp(0.4rem, 1.4vh, 0.9rem);
}

.declaraciones__lista {
  display: grid;
  gap: var(--esp-2);
  margin: 0;
  padding: 0;
  list-style: none;
  text-align: start;
}

.declaraciones__item {
  display: flex;
  align-items: flex-start;
  gap: var(--esp-2);
  padding: clamp(0.35rem, 1vh, 0.55rem) clamp(0.5rem, 2vw, 0.8rem);
  border-radius: var(--radio-s);
  background: var(--c-marino-50);
  font-size: var(--texto-xs);
  line-height: 1.45;
  color: var(--c-texto-suave);
  text-wrap: pretty;
}

.declaraciones__item svg {
  flex: none;
  width: 1rem;
  height: 1rem;
  margin-top: 0.12rem;
  color: var(--c-marino-600);
}

.revelable .declaraciones__item {
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 380ms ease, transform 380ms cubic-bezier(0.22, 0.7, 0.35, 1);
  transition-delay: calc(var(--animar-orden, 0) * 90ms + 620ms);
}

.revelable.es-visible .declaraciones__item {
  opacity: 1;
  transform: none;
}

.resultado__bloque-titulo {
  margin-top: clamp(0.6rem, 1.8vh, 1.5rem);
  font-size: clamp(1rem, 2vh, 1.25rem);
  color: var(--c-marino-900);
}

/* Chip de dato clave (base) */
.chip-dato {
  flex: 1;
  min-width: 5rem;
  text-align: center;
  padding: clamp(0.3rem, 1vh, 0.5rem) 0.5rem;
  border: 1px solid var(--c-borde);
  border-radius: var(--radio-m);
  background: var(--c-fondo-suave);
  display: grid;
  gap: 2px;
}

.chip-dato__etiqueta {
  font-size: var(--texto-xs);
  color: var(--c-texto-suave);
}

.chip-dato__valor {
  font-weight: 800;
  font-size: clamp(0.9rem, 1.9vh, 1.0625rem);
  color: var(--c-marino-900);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Disclosure "ver comparativa completa": scroll intencionado, sin pliegues */
.resultado__ver-mas {
  align-self: center;
  display: inline-flex;
  align-items: center;
  gap: var(--esp-2);
  margin-top: clamp(0.5rem, 1.4vh, 1rem);
  padding: 0.4rem 0.9rem;
  border: 0;
  background: none;
  border-radius: var(--radio-pill);
  font: inherit;
  font-size: var(--texto-s);
  font-weight: 700;
  color: var(--c-marino-700);
  cursor: pointer;
}

.resultado__ver-mas:hover {
  color: var(--c-marino-900);
}

.resultado__ver-mas svg {
  width: 1rem;
  height: 1rem;
  animation: nz-chevron 1.8s ease-in-out infinite;
}

@keyframes nz-chevron {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(4px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .resultado__ver-mas svg {
    animation: none;
  }
}

/* Sección secundaria (colapsada hasta pulsar "ver más") */
.resultado__detalle {
  margin-top: var(--esp-6);
  padding-top: var(--esp-5);
  border-top: 1px solid var(--c-borde);
  display: grid;
  gap: var(--esp-4);
}

/* Cerrado: no reservar espacio. El `display:grid` de arriba pisaba al atributo
   `hidden` (los estilos de autor ganan al `[hidden]` del navegador), dejando un
   hueco vacío bajo "ver comparativa completa". Con esto el detalle SOLO ocupa
   sitio cuando funnel.js le quita `hidden` al abrirlo (se crea dinámicamente). */
.resultado__detalle[hidden] {
  display: none;
}

/* Tarjetas de oferta */
.oferta {
  position: relative;
  margin-top: clamp(0.6rem, 1.6vh, 1rem);
  padding: clamp(0.625rem, 1.6vh, 1rem) clamp(0.9rem, 2.2vh, 1.5rem);
  border: 1px solid var(--c-borde);
  border-radius: var(--radio-l);
  background: var(--c-blanco);
}

.oferta--mejor {
  border: 2px solid var(--c-amarillo-500);
  box-shadow: var(--sombra-2);
}

.oferta__badge {
  position: absolute;
  top: calc(-1 * var(--esp-3));
  left: var(--esp-5);
  padding: 0.2rem 0.8rem;
  border-radius: var(--radio-pill);
  background: var(--c-amarillo-500);
  color: var(--c-marino-900);
  font-size: var(--texto-xs);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.oferta__nombre {
  font-size: var(--texto-l);
  color: var(--c-marino-900);
}

.oferta__comercializadora {
  margin-top: 2px;
  font-size: var(--texto-xs);
  color: var(--c-texto-suave);
}

/* En la tarjeta recomendada se muestran 2 motivos (mínimo de CA12) en
   letra compacta; la lectura completa vive en la comparativa del detalle */
.oferta--mejor .motivos li:nth-child(n + 3) {
  display: none;
}

.oferta--mejor .motivos li {
  font-size: var(--texto-xs);
}

/* En móvil estrecho los motivos ocupan 2 líneas cada uno y rompen el
   viewport-fit: la tarjeta queda limpia y el detalle (a un toque) los
   muestra íntegros. */
@media (max-width: 559px) {
  .oferta--mejor .motivos {
    display: none;
  }
}

.oferta__cifras {
  display: flex;
  flex-wrap: wrap;
  gap: var(--esp-2) var(--esp-6);
  margin-top: var(--esp-3);
}

.oferta__cifra {
  display: grid;
}

.oferta__cifra-etiqueta {
  font-size: var(--texto-xs);
  color: var(--c-texto-suave);
}

.oferta__cifra-valor {
  font-weight: 800;
  color: var(--c-marino-900);
}

.oferta__cifra-valor--ahorro {
  color: var(--c-exito);
}

.oferta__descripcion {
  margin-top: var(--esp-3);
  font-size: var(--texto-s);
  color: var(--c-texto-suave);
}

/* Precio ya formateado por el backend ("0,119 €/kWh" | "Punta 0,171 · …" |
   "Precio de mercado + margen"): sirve para TODOS los modos de tarifa, así que
   sustituye a tres pintados distintos en el JS. */
.oferta__precio {
  margin-top: var(--esp-2);
  font-size: var(--texto-s);
  font-weight: 700;
  color: var(--c-marino-800);
  text-wrap: pretty;
}

/* Tarifa informativa (indexada sin referencia de mercado): se muestra, pero no
   se puede costear y nunca se recomienda. Se distingue en gris para que no
   compita visualmente con las que sí llevan cifra. */
.oferta--informativa {
  border-style: dashed;
  background: var(--c-marino-50);
}

.oferta--informativa .oferta__nombre {
  color: var(--c-marino-800);
}

.oferta__nota {
  display: flex;
  gap: var(--esp-2);
  margin-top: var(--esp-3);
  padding: var(--esp-2) var(--esp-3);
  border-inline-start: 3px solid var(--c-borde-fuerte);
  border-radius: var(--radio-s);
  background: var(--c-blanco);
  font-size: var(--texto-xs);
  color: var(--c-texto-suave);
  text-wrap: pretty;
}

/* Motivos de la recomendación */
.motivos {
  margin: var(--esp-3) 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--esp-2);
}

.motivos li {
  display: flex;
  gap: var(--esp-2);
  align-items: flex-start;
  font-size: var(--texto-s);
}

.motivos svg {
  flex: none;
  width: 1.15rem;
  height: 1.15rem;
  margin-top: 0.2rem;
  color: var(--c-exito);
}

/* Otras ofertas */
.otras-ofertas {
  display: grid;
  gap: var(--esp-4);
  grid-template-columns: 1fr;
  margin-top: var(--esp-4);
}

@media (min-width: 640px) {
  .otras-ofertas {
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  }

  .otras-ofertas .oferta {
    margin-top: 0;
  }
}

/* ---------- Revelado secuencial del resultado ---------- */
.revelable {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 520ms cubic-bezier(0.22, 0.7, 0.35, 1),
    transform 520ms cubic-bezier(0.22, 0.7, 0.35, 1);
}

.revelable.es-visible {
  opacity: 1;
  transform: none;
}

/* Stagger interno: filas de la factura y tarjetas de otras ofertas
   (--animar-orden lo fija funnel.js por elemento) */
.revelable .resumen-factura__fila,
.revelable .otras-ofertas .oferta {
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 420ms ease, transform 420ms cubic-bezier(0.22, 0.7, 0.35, 1);
  transition-delay: calc(var(--animar-orden, 0) * 90ms + 150ms);
}

.revelable.es-visible .resumen-factura__fila,
.revelable.es-visible .otras-ofertas .oferta {
  opacity: 1;
  transform: none;
}

/* Badge de la oferta recomendada: pop al revelarse */
.revelable.es-visible .oferta__badge {
  animation: nz-badge-pop 520ms var(--rebote) 260ms both;
}

@keyframes nz-badge-pop {
  from {
    opacity: 0;
    transform: scale(0.4) rotate(-6deg);
  }
  60% {
    transform: scale(1.12) rotate(2deg);
  }
  to {
    opacity: 1;
    transform: scale(1) rotate(0deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .revelable,
  .revelable .resumen-factura__fila,
  .revelable .otras-ofertas .oferta,
  .revelable .tramos__item,
  .revelable .declaraciones__item {
    opacity: 1;
    transform: none;
    transition: none;
  }

  .revelable.es-visible .oferta__badge {
    animation: none;
  }

  /* Comparativa: sin dibujado del tachado ni overshoot (estado final directo) */
  .comparativa__precio--tachado::after,
  .comparativa.es-visible .comparativa__precio--tachado::after {
    transition: none;
    transform: scaleX(1);
  }

  .comparativa.es-visible .comparativa__precio--oferta,
  .comparativa.es-visible .comparativa__estrella {
    animation: none;
  }
}

/* Resumen de la factura leída (tarjeta abierta, en la sección detalle) */
.resumen-factura {
  margin-top: 0;
  border: 1px solid var(--c-borde);
  border-radius: var(--radio-m);
  background: var(--c-fondo-suave);
  padding: var(--esp-4) var(--esp-5) var(--esp-5);
}

.resumen-factura .resultado__bloque-titulo {
  margin-top: 0;
}

.resumen-factura__datos {
  display: grid;
  gap: var(--esp-3) var(--esp-5);
  grid-template-columns: 1fr;
  margin: var(--esp-4) 0 0;
  padding: 0;
}

@media (min-width: 640px) {
  .resumen-factura__datos {
    grid-template-columns: 1fr 1fr;
  }
}

.resumen-factura__fila dt {
  font-size: var(--texto-xs);
  color: var(--c-texto-suave);
}

.resumen-factura__fila dd {
  margin: 0;
  font-weight: 700;
  color: var(--c-marino-900);
  font-variant-numeric: tabular-nums;
}

.resultado__cta {
  margin-top: clamp(0.5rem, 1.6vh, 1rem);
  padding-top: clamp(0.5rem, 1.4vh, 0.875rem);
  border-top: 1px solid var(--c-borde);
  text-align: center;
}

.resultado__decides {
  font-weight: 800;
  font-size: clamp(0.9375rem, 2vh, 1.0625rem);
  color: var(--c-marino-900);
}

.resultado__cta .boton {
  margin-top: clamp(0.4rem, 1.2vh, 0.75rem);
}

.resultado__micro {
  margin-top: clamp(0.25rem, 0.8vh, 0.5rem);
  font-size: var(--texto-xs);
  color: var(--c-texto-suave);
}

/* CTA horizontal en pantallas anchas: menos altura, misma jerarquía */
@media (min-width: 560px) {
  .resultado__cta {
    display: grid;
    grid-template-columns: 1fr auto;
    column-gap: var(--esp-5);
    align-items: center;
    text-align: left;
  }

  .resultado__cta .boton {
    grid-area: 1 / 2 / 3 / 3;
    margin-top: 0;
  }
}

.resultado__volver {
  display: inline-block;
  font-size: var(--texto-s);
}

/* ---------- Paso 6: confirmación ---------- */
.confirmacion {
  text-align: center;
  padding-block: clamp(0.75rem, 2.4vh, 2rem);
}

.confirmacion__icono {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: clamp(3.25rem, 7vh, 4.5rem);
  height: clamp(3.25rem, 7vh, 4.5rem);
  border-radius: 50%;
  background: var(--c-exito-fondo);
  color: var(--c-exito);
  margin-bottom: var(--esp-4);
  animation: nz-aparecer-icono 0.5s var(--trans-media) both;
}

@keyframes nz-aparecer-icono {
  from {
    opacity: 0;
    transform: scale(0.6);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

@media (prefers-reduced-motion: reduce) {
  .confirmacion__icono {
    animation: none;
  }
}

.confirmacion__icono svg {
  width: 2.2rem;
  height: 2.2rem;
}

.confirmacion__titulo {
  font-size: var(--texto-2xl);
  color: var(--c-marino-900);
}

.confirmacion__saludo {
  margin-top: var(--esp-3);
  font-weight: 700;
  color: var(--c-marino-900);
}

.confirmacion__texto,
.confirmacion__seguimiento {
  margin: var(--esp-3) auto 0;
  max-width: 48ch;
  color: var(--c-texto-suave);
}

.confirmacion .boton {
  margin-top: clamp(0.75rem, 2.2vh, 2rem);
}

/* ============================================================
   Tiers por ALTURA de viewport: lo decorativo/redundante cede
   antes que el contenido funcional (labels y foco intactos).
   ============================================================ */

/* ≤850px de alto (incluye 390×844 y 1366×768) */
@media (max-height: 850px) {
  /* Sellos: redundantes en el funnel (la nota de seguridad permanece) */
  .paso .sellos {
    display: none;
  }

  /* Los consentimientos conservan ÍNTEGRO su texto legal + enlace a la
     política; se ocultan solo las aclaraciones complementarias. */
  .consentimiento__detalle {
    display: none;
  }

  /* El "o" entre los dos botones de subida sobra en altura corta */
  .zona-subida__separador {
    display: none;
  }

  .form-datos .campo {
    margin-bottom: 0.5rem;
  }

  /* La descripción de la oferta recomendada cede (visible en el detalle) */
  .oferta--mejor .oferta__descripcion {
    display: none;
  }

  /* Margen de seguridad del resultado en alturas medias */
  .resultado__ahorro-cifra {
    font-size: clamp(1.6rem, 4.2vh, 2.5rem);
  }

  .resultado__cta {
    margin-top: 0.5rem;
    padding-top: 0.5rem;
  }

  .resultado__ver-mas {
    margin-top: 0.375rem;
  }
}

/* ≤800px de alto: la tarjeta recomendada se queda con lo esencial —
   el banner ya da el titular económico y el detalle tiene las cifras */
@media (max-height: 800px) {
  .oferta--mejor .oferta__cifras {
    display: none;
  }
}

/* ≤760px de alto (incluye 360×740) */
@media (max-height: 760px) {
  .funnel__intro {
    display: none;
  }

  .consentimientos__nota {
    display: none;
  }

  .zona-subida {
    padding-block: 0.9rem;
  }

  .form-datos .campo {
    margin-bottom: 0.4rem;
  }

  /* La nota "sin DNI/NIE" cede (el formulario simplemente no lo pide;
     el mensaje sigue en landing, FAQ y consentimientos) */
  .form-datos .campo__ayuda {
    display: none;
  }

  /* Los chips del banner ceden: la lectura completa está en el detalle */
  .resultado__ahorro-clave {
    display: none;
  }

  .resultado__ver-mas {
    margin-top: 0.25rem;
    padding: 0.25rem 0.75rem;
  }
}

/* ============================================================
   Fondo v2 "Editorial del dato" — ESCENA DE ENERGÍA (detrás del
   wizard): gris-papel frío + grano de marca + skyline energético
   en línea fina estilo blueprint anclado abajo (torres, cables,
   molinos, fábrica, gasómetro, antorcha). Estático es una lámina
   completa; el movimiento (aspas, humo, pulsos por los cables,
   llama, ventana) vive ÍNTEGRO tras prefers-reduced-motion:
   no-preference y usa SOLO transform / opacity / stroke-dashoffset
   (nada de filtros animados). El wizard va encima (z-index 1).
   ============================================================ */
.funnel-fondo {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  /* Gris-papel neutro: el papel cálido v2 enfriado con marino-50 */
  background: var(--lg-fog); /* fallback sin color-mix */
  background: color-mix(in srgb, var(--c-marino-50) 62%, var(--lz-papel));
}

/* Escena en línea fina (trazo 1.4 constante vía non-scaling-stroke),
   azul desaturado ≈18% de marino sobre papel: acompaña sin competir.
   Móvil: anclada a la derecha (clúster fábrica+molinos+gasómetro) para
   no aplastar el dibujo; pantallas anchas: todo el pie del viewport. */
.funnel-fondo__escena {
  position: absolute;
  bottom: 0;
  right: 0;
  height: 12.5rem;
  width: auto;
  /* Más MARCADO: sube el contraste del azul desaturado para que la escena
     se lea de fondo sin tapar el formulario (que va sobre tarjetas blancas). */
  color: var(--c-borde-fuerte); /* fallback sin color-mix */
  color: color-mix(in srgb, var(--c-marino-600) 34%, var(--lz-papel));
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

@media (min-width: 900px) {
  .funnel-fondo__escena {
    right: auto;
    left: 0;
    width: 100%;
    height: auto;
  }
}

/* Cielo (parte de arriba): más tenue que el suelo para no pelearse con el
   título. Ancho completo, anclado arriba. */
.funnel-fondo__cielo {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: auto;
  color: color-mix(in srgb, var(--c-marino-600) 22%, var(--lz-papel));
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.funnel-fondo__cielo .fx-estela {
  stroke-dasharray: 3 6;
  color: color-mix(in srgb, var(--c-marino-600) 14%, var(--lz-papel));
}
/* Profundidad del cielo: las nubes NO son todas del mismo plano — dos quedan
   más lejanas (más tenues) y dos más cercanas. */
.funnel-fondo__cielo .fx-nube--2 { opacity: 0.55; }
.funnel-fondo__cielo .fx-nube--3 { opacity: 0.7; }

/* Texto de marca en los guiños del cielo (pancarta del avión y bocadillo del
   paracaidista). El "ia" en ámbar es la excepción permitida del wordmark. */
.funnel-fondo .fx-texto-marca {
  font: 700 12px var(--fuente-marca);
  letter-spacing: 0.04em;
  fill: currentColor;
}
.funnel-fondo .fx-texto-marca__ia { fill: var(--c-amarillo-500); }
.funnel-fondo .fx-texto-marca--zepelin { font-size: 11px; }
/* Bocadillo del paracaidista: dos lineas (frase fina + marca) sobre fondo
   papel para que se lea contra el cielo. */
.funnel-fondo .fx-texto-marca--fina { font-weight: 500; font-size: 8px; }
.funnel-fondo__salto .fx-paraca__globo { fill: var(--lz-papel); }

/* Paracaidista: base FUERA de pantalla (arriba). Solo la animación lo deja
   caer, así que con reduced-motion no existe — igual que las aeronaves. */
.funnel-fondo__salto {
  position: absolute;
  top: 0;
  /* A la DERECHA y separado del contenido (peticion directa): cae por el
     margen derecho, donde no compite con el asistente. */
  right: 6%;
  left: auto;
  width: clamp(6.5rem, 9vw, 9.5rem);
  color: color-mix(in srgb, var(--c-marino-600) 30%, var(--lz-papel));
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  transform: translateY(-140vh);
  pointer-events: none;
}
.funnel-fondo__salto .fx-texto-marca { font-size: 9.5px; letter-spacing: 0.02em; }
.funnel-fondo__salto .fx-paraca__bocadillo { opacity: 0; }
/* Aeronaves: base FUERA de pantalla (izquierda). Solo la animación las cruza,
   así que con reduced-motion quedan ocultas (no "aparcadas" en el aire). */
.funnel-fondo__cielo .fx-vuela {
  transform-box: view-box;
  transform: translate(-260px, var(--y, 8px));
}

/* Camión + luces de la fábrica: base fuera de escena y apagadas (con
   reduced-motion no hay camión ni encendido). */
.funnel-fondo__escena .fx-camion {
  transform-box: view-box;
  transform: translate(-260px, 0);
}
.funnel-fondo__escena .fx-luces rect {
  fill: var(--c-amarillo-400);
  stroke: none;
  opacity: 0;
}

/* Línea de carga en el MEDIO de la página (horizonte de datos), muy tenue y
   por detrás de las tarjetas de elección: cruza por su mitad (petición
   directa; el % está afinado a esa composición). */
.funnel-fondo__montes {
  position: absolute;
  top: 38%;
  left: 0;
  width: 100%;
  height: clamp(9rem, 20vh, 15rem);
  color: color-mix(in srgb, var(--c-marino-600) 15%, var(--lz-papel));
  fill: none;
  stroke: currentColor;
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.funnel-fondo__montes .fx-onda--cerca { opacity: 0.9; }
.funnel-fondo__montes .fx-onda-puntos circle {
  fill: var(--lz-papel);
  color: color-mix(in srgb, var(--c-marino-600) 34%, var(--lz-papel));
}
/* Pulso que recorre la onda cercana: mismo truco que los cables de la escena
   (pathLength=100 normaliza el dash). Quieto sin motion: un herraje más. */
.funnel-fondo__montes .fx-onda-pulso {
  color: color-mix(in srgb, var(--c-marino-600) 58%, var(--lz-papel));
  stroke-width: 2.4;
  stroke-dasharray: 5 95;
  stroke-dashoffset: -40;
}
@media (prefers-reduced-motion: no-preference) {
  .funnel-fondo__montes .fx-onda-pulso {
    animation: fx-onda-viaja 8s linear infinite;
  }
  @keyframes fx-onda-viaja {
    from { stroke-dashoffset: 0; }
    to   { stroke-dashoffset: -200; }
  }
}

/* Pulsos de energía: un guion corto sobre el propio cable
   (pathLength="100" normaliza el dasharray al largo del trazado).
   Sin animación queda quieto a media catenaria, como un herraje
   más; algo más oscuro que el cable para leerse como "carga". */
.funnel-fondo__escena .fx-pulso {
  color: color-mix(in srgb, var(--c-marino-600) 60%, var(--lz-papel));
  stroke-width: 2.6;
  stroke-dasharray: 4 96;
  stroke-dashoffset: -48;
}
/* Brillo que barre el panel solar (dash corto que recorre la diagonal). */
.funnel-fondo__escena .fx-brillo {
  color: color-mix(in srgb, var(--c-marino-600) 12%, var(--lz-papel));
  stroke-width: 3;
}

/* Grano de marca, muy sutil, POR ENCIMA de la escena (mismo asset
   que los momentos navy v2) */
.funnel-fondo__grano {
  position: absolute;
  inset: 0;
  background-image: url("/static/img/noise.svg");
  background-size: 240px;
  mix-blend-mode: soft-light;
  opacity: 0.05;
}

/* ---------- Movimiento de la escena (TODO dentro de la puerta:
   con reduced-motion la lámina queda estática y completa). Bucles
   largos (6-22s) y amplitudes mínimas: acompañan, no distraen. --- */
@media (prefers-reduced-motion: no-preference) {
  /* Aspas de los aerogeneradores: giro continuo lento. El origen es
     el buje en coordenadas del viewBox (transform-box: view-box);
     los grupos NO tienen transforms de padre, así que es exacto. */
  .funnel-fondo__escena .fx-aspas {
    transform-box: view-box;
    transform-origin: 1090px 104px;
    animation: fx-fondo-gira 16s linear infinite;
    will-change: transform;
  }

  .funnel-fondo__escena .fx-aspas--b {
    transform-origin: 1170px 132px;
    animation-duration: 22s;
  }

  /* Humo: cada circulito nace en la boca, sube y se disipa; en
     cascada (backwards: durante el delay toman el frame 0 = opacidad
     0, sin pop al cargar). La opacity animada multiplica el
     fill-opacity estático de cada uno (más tenue cuanto más alto). */
  .funnel-fondo__escena .fx-humo {
    transform-box: fill-box;
    transform-origin: center;
    animation: fx-fondo-humo 10s linear infinite backwards;
  }

  .funnel-fondo__escena .fx-humo--b {
    animation-delay: 3.4s;
  }

  .funnel-fondo__escena .fx-humo--c {
    animation-delay: 6.8s;
  }

  /* Chimenea corta: ciclo distinto (no múltiplo del otro) para que las dos
     columnas nunca coincidan y el humo no se lea como un patrón. */
  .funnel-fondo__escena .fx-humo--d {
    animation-duration: 8.5s;
    animation-delay: 1.6s;
  }

  .funnel-fondo__escena .fx-humo--e {
    animation-duration: 8.5s;
    animation-delay: 5.1s;
  }

  /* Pulso recorriendo el cable: dashoffset 0 → -100 (pathLength
     normalizado) = una vuelta completa por ciclo, bucle sin costura */
  .funnel-fondo__escena .fx-pulso {
    animation: fx-fondo-recorre 9s linear infinite backwards;
  }

  .funnel-fondo__escena .fx-pulso--lento {
    animation-duration: 19s;
    animation-delay: 3s;
  }

  /* Llama de la antorcha: oscilación mínima desde la base */
  .funnel-fondo__escena .fx-llama {
    transform-box: view-box;
    transform-origin: 1588px 209px;
    animation: fx-fondo-llama 6s ease-in-out infinite;
  }

  /* Ventana encendida: doble parpadeo MUY ocasional (una vez por
     ciclo de 18s), el resto del tiempo luce fija */
  .funnel-fondo__escena .fx-ventana {
    animation: fx-fondo-parpadea 18s linear infinite;
  }

  @keyframes fx-fondo-gira {
    to {
      transform: rotate(360deg);
    }
  }

  @keyframes fx-fondo-humo {
    0% {
      opacity: 0;
      transform: translateY(8px) scale(0.7);
    }
    18% {
      opacity: 0.9;
    }
    70% {
      opacity: 0.35;
    }
    100% {
      opacity: 0;
      transform: translateY(-26px) scale(1.3);
    }
  }

  @keyframes fx-fondo-recorre {
    from {
      stroke-dashoffset: 0;
    }
    to {
      stroke-dashoffset: -100;
    }
  }

  @keyframes fx-fondo-llama {
    0%,
    100% {
      transform: none;
    }
    35% {
      transform: scaleY(1.08) scaleX(0.95) skewX(-1.6deg);
    }
    65% {
      transform: scaleY(0.94) scaleX(1.04) skewX(1.4deg);
    }
  }

  @keyframes fx-fondo-parpadea {
    0%,
    87.5%,
    90%,
    92.5%,
    100% {
      opacity: 1;
    }
    88.5% {
      opacity: 0.15;
    }
    91.5% {
      opacity: 0.25;
    }
  }

  /* --- Cielo: aeronaves que cruzan de UNA EN UNA (ciclo de 44s con delays
     escalonados: cada una cruza en su ventana y espera fuera de pantalla),
     nubes que derivan, sol que respira --- */
  .funnel-fondo__cielo .fx-vuela { will-change: transform; animation: fx-cruza 44s linear infinite; }
  /* El avión baja su línea de vuelo: con la pancarta remolcada, a 8px el
     cartel rozaba el borde superior y se recortaba (bajado 2 veces a peticion). */
  .funnel-fondo__cielo .fx-avion { --y: 28px; animation-delay: 0s; }
  .funnel-fondo__cielo .fx-avioneta { --y: 40px; animation-delay: 11s; }
  .funnel-fondo__cielo .fx-zepelin { --y: 32px; animation-delay: 22s; }
  /* La pancarta ondea colgada de su cuerda (origen en el lado de la cuerda). */
  .funnel-fondo__cielo .fx-pancarta {
    transform-box: fill-box;
    transform-origin: 100% 50%;
    animation: fx-pancarta-ondea 1.8s ease-in-out infinite alternate;
  }
  @keyframes fx-pancarta-ondea {
    from { transform: rotate(-1.6deg); }
    to   { transform: rotate(1.8deg); }
  }
  /* Paracaidista: cae en el primer tercio de un ciclo largo y espera fuera;
     el balanceo vive en el grupo interior y el bocadillo se enciende a ratos. */
  .funnel-fondo__salto {
    will-change: transform;
    animation: fx-paraca-cae 75s linear infinite;
    animation-delay: 6s;
  }
  @keyframes fx-paraca-cae {
    0%   { transform: translateY(-40vh); }
    36%  { transform: translateY(105vh); }
    100% { transform: translateY(105vh); }
  }
  /* Balanceo mas lento y suave (legibilidad); el bocadillo vive FUERA del
     grupo que se mece, asi que el texto no baila. */
  .funnel-fondo__salto .fx-paraca {
    transform-box: view-box;
    transform-origin: 48px 24px;
    animation: fx-paraca-mece 4.4s ease-in-out infinite alternate;
  }
  @keyframes fx-paraca-mece {
    from { transform: rotate(-3deg); }
    to   { transform: rotate(3deg); }
  }
  /* Habla PRONTO (peticion directa): el bocadillo aparece casi al entrar y
     acompana la mayor parte de la bajada. */
  .funnel-fondo__salto .fx-paraca__bocadillo { animation: fx-paraca-habla 15s ease-in-out infinite; }
  @keyframes fx-paraca-habla {
    0%, 3%    { opacity: 0; }
    8%, 62%   { opacity: 1; }
    70%, 100% { opacity: 0; }
  }
  /* El globo va MÁS BAJO y MÁS LENTO: cruza en el 60% de un ciclo doble. */
  .funnel-fondo__cielo .fx-globo {
    --y: 56px;
    animation-duration: 88s;
    animation-delay: 22s;
    animation-name: fx-cruza-lento;
  }
  .funnel-fondo__cielo .fx-bandada { --y: 84px; animation-delay: 33s; }
  /* Hélice de la avioneta girando. */
  .funnel-fondo__cielo .fx-helice {
    transform-box: fill-box;
    transform-origin: center;
    animation: fx-helice 0.5s linear infinite;
  }
  .funnel-fondo__cielo .fx-nube--1 { transform-box: view-box; animation: fx-fondo-nube 70s linear infinite; }
  .funnel-fondo__cielo .fx-nube--2 { transform-box: view-box; animation: fx-fondo-nube 95s linear infinite; animation-delay: -30s; }
  .funnel-fondo__cielo .fx-nube--3 { transform-box: view-box; animation: fx-fondo-nube 120s linear infinite; animation-delay: -70s; }
  .funnel-fondo__cielo .fx-nube--4 { transform-box: view-box; animation: fx-fondo-nube 85s linear infinite; animation-delay: -50s; }
  .funnel-fondo__cielo .fx-nube--5 { transform-box: view-box; animation: fx-fondo-nube 110s linear infinite; animation-delay: -15s; }
  .funnel-fondo__cielo .fx-nube--6 { transform-box: view-box; animation: fx-fondo-nube 78s linear infinite; animation-delay: -62s; }
  .funnel-fondo__cielo .fx-nube--7 { transform-box: view-box; animation: fx-fondo-nube 130s linear infinite; animation-delay: -90s; }
  .funnel-fondo__cielo .fx-sol {
    transform-box: view-box;
    transform-origin: 1476px 40px;
    animation: fx-fondo-sol 12s ease-in-out infinite;
  }
  /* Brillo del panel solar: barre la diagonal una vez por ciclo. */
  .funnel-fondo__escena .fx-brillo {
    stroke-dasharray: 6 40;
    stroke-dashoffset: 46;
    animation: fx-fondo-brillo 7s ease-in-out infinite;
  }

  /* Cada aeronave cruza en el primer 22% de su ciclo y espera fuera de
     pantalla el resto → con los delays escalonados, pasan de una en una. */
  @keyframes fx-cruza {
    0% { transform: translate(-200px, var(--y, 8px)); }
    22% { transform: translate(1780px, var(--y, 8px)); }
    100% { transform: translate(1780px, var(--y, 8px)); }
  }
  /* Travesía lenta (globo): ocupa más del ciclo, con una deriva vertical suave. */
  @keyframes fx-cruza-lento {
    0% { transform: translate(-220px, var(--y, 56px)); }
    30% { transform: translate(560px, calc(var(--y, 56px) - 10px)); }
    60% { transform: translate(1800px, var(--y, 56px)); }
    100% { transform: translate(1800px, var(--y, 56px)); }
  }
  @keyframes fx-helice { to { transform: rotate(360deg); } }

  /* Camión: entra por la IZQUIERDA y rueda DESPACIO y en línea recta hacia la
     fábrica. Al tocar el muro izquierdo (x=1240) el clipPath del grupo padre lo
     va comiendo: se mete por detrás de la nave hasta desaparecer, sin fundidos
     ni encogimientos (el recorte hace todo el trabajo). Velocidad constante
     (linear): un camión no acelera con ease. Al entrar, las ventanas se
     ENCIENDEN en ámbar con un parpadeo eléctrico y se apagan despacio. */
  .funnel-fondo__escena .fx-camion {
    animation: fx-camion 34s linear infinite;
  }
  .funnel-fondo__escena .fx-luces rect {
    animation: fx-luces 34s ease-in-out infinite;
  }
  .funnel-fondo__escena .fx-luces rect:nth-child(2) { animation-delay: 0.22s; }
  .funnel-fondo__escena .fx-luces rect:nth-child(3) { animation-delay: 0.44s; }
  .funnel-fondo__escena .fx-luces rect:nth-child(4) { animation-delay: 0.66s; }
  @keyframes fx-camion {
    0% { transform: translate(-260px, 0); }
    /* recorrido largo y constante hasta el muro; a partir de 1240 el clip lo
       va ocultando y en 1300 ya está entero dentro de la nave */
    78%, 100% { transform: translate(1300px, 0); }
  }
  /* Ventanas encendidas: no es un fade plano, es corriente entrando — dos
     chispazos rápidos antes de estabilizarse, y apagado lento al final. */
  @keyframes fx-luces {
    0%, 74% { opacity: 0; }
    75% { opacity: 0.9; }
    76.5% { opacity: 0.15; }
    78% { opacity: 0.95; }
    79% { opacity: 0.3; }
    80%, 92% { opacity: 0.85; }
    100% { opacity: 0; }
  }
  /* Cruce COMPLETO: de fuera de pantalla (izq) a fuera de pantalla (der).
     Las nubes van ancladas en x=0, así que ninguna reaparece en medio al
     reiniciar el bucle; los delays negativos las reparten por el cielo. */
  @keyframes fx-fondo-nube {
    0% { transform: translateX(-170px); }
    100% { transform: translateX(1700px); }
  }
  @keyframes fx-fondo-sol {
    0%, 100% { transform: scale(1); opacity: 1; }
    50% { transform: scale(1.06); opacity: 0.82; }
  }
  @keyframes fx-fondo-brillo {
    0%, 55% { stroke-dashoffset: 46; }
    80%, 100% { stroke-dashoffset: -8; }
  }
}

/* ============================================================
   Confeti de celebración (decorativo). funnel.js crea la capa
   .confeti sobre el shell del funnel cuando el resultado revela
   ahorro y retira sus nodos al terminar (una sola ráfaga, sin
   bucles). Piezas animadas con transform/opacity (GPU). No
   captura eventos y queda fuera del árbol de accesibilidad.
   Con prefers-reduced-motion no se pinta (y funnel.js no la crea).
   ============================================================ */
.confeti {
  position: absolute;
  inset: 0;
  z-index: 3; /* sobre el contenido del wizard; nunca bajo un modal (no hay) */
  overflow: hidden; /* las piezas que caen fuera se recortan: sin scroll extra */
  pointer-events: none;
}

.confeti__pieza {
  position: absolute;
  top: -6%;
  left: var(--x, 50%);
  width: 8px;
  height: 14px;
  background: var(--color, var(--c-amarillo-500));
  border-radius: 1px;
  opacity: 0;
  will-change: transform, opacity;
  animation: nz-confeti-cae var(--dur, 2.2s) cubic-bezier(0.2, 0.6, 0.35, 1) var(--delay, 0s) both;
}

/* Un tercio de las piezas son "chispas" redondas (temática energía) */
.confeti__pieza--redonda {
  width: 9px;
  height: 9px;
  border-radius: 50%;
}

@keyframes nz-confeti-cae {
  0% {
    opacity: 0;
    transform: translate3d(0, -10%, 0) rotate(0deg) scale(0.8);
  }
  12% {
    opacity: 1;
  }
  85% {
    opacity: 1;
  }
  100% {
    opacity: 0;
    transform: translate3d(var(--dx, 0px), 100vh, 0) rotate(var(--rot, 540deg)) scale(1);
  }
}

@media (prefers-reduced-motion: reduce) {
  .confeti {
    display: none;
  }
}

/* ============================================================
   Selector de tipo de titular (paso resultado, antes de contratar)
   Dos tarjetas-radio claras: "a mi nombre" vs "cambio de titular".
   ============================================================ */
.resultado__titular {
  margin-top: clamp(0.5rem, 1.6vh, 1rem);
  padding-top: clamp(0.5rem, 1.4vh, 0.875rem);
  border-top: 1px solid var(--c-borde);
  text-align: left;
}

.resultado__titular-intro {
  font-weight: 800;
  font-size: clamp(0.9rem, 1.9vh, 1rem);
  color: var(--c-marino-900);
  margin: 0 0 var(--esp-2);
}

.titular-opciones {
  display: grid;
  gap: var(--esp-2);
}

@media (min-width: 560px) {
  .titular-opciones { grid-template-columns: 1fr 1fr; }
}

.titular-opcion {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: var(--esp-2);
  padding: 0.7rem 0.85rem;
  border: 1.5px solid var(--c-borde-fuerte);
  border-radius: var(--radio-m);
  background: var(--c-blanco);
  cursor: pointer;
  transition: border-color var(--trans-rapida), box-shadow var(--trans-rapida), background-color var(--trans-rapida);
}

.titular-opcion:hover { border-color: var(--c-marino-700); }

.titular-opcion__radio {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
}

.titular-opcion__cuerpo { display: flex; flex-direction: column; gap: 0.15rem; flex: 1; min-width: 0; }
.titular-opcion__titulo { font-weight: 700; font-size: var(--texto-s); color: var(--c-marino-900); }
.titular-opcion__desc { font-size: var(--texto-xs); color: var(--c-texto-suave); }

.titular-opcion__marca {
  flex: none;
  width: 1.4rem;
  height: 1.4rem;
  border-radius: 50%;
  border: 2px solid var(--c-borde-fuerte);
  background: var(--c-blanco);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--c-blanco);
  transition: background-color var(--trans-rapida), border-color var(--trans-rapida);
}

.titular-opcion__marca svg { width: 0.8rem; height: 0.8rem; opacity: 0; transform: scale(0.4); transition: opacity var(--trans-rapida), transform 260ms var(--rebote); }

.titular-opcion__radio:checked ~ .titular-opcion__marca { background: var(--c-marino-700); border-color: var(--c-marino-700); }
.titular-opcion__radio:checked ~ .titular-opcion__marca svg { opacity: 1; transform: scale(1); }
.titular-opcion:has(.titular-opcion__radio:checked) { border-color: var(--c-marino-700); box-shadow: 0 0 0 1px var(--c-marino-700) inset; background: var(--c-marino-50); }
.titular-opcion__radio:focus-visible ~ .titular-opcion__marca { outline: 3px solid var(--c-foco); outline-offset: 2px; }

.resultado__titular-nota { margin: var(--esp-2) 0 0; font-size: var(--texto-xs); color: var(--c-texto-suave); }

@media (max-height: 760px) {
  .resultado__titular-nota { display: none; }
  .titular-opcion { padding: 0.55rem 0.75rem; }
}

/* ============================================================
   Overlay "creando tu área" (auto-login tras contratar).
   Cubre el wizard con un mensaje tranquilizador hasta navegar.
   ============================================================ */
.funnel-creando {
  position: fixed;
  inset: 0;
  z-index: var(--capa-flotante);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--esp-5);
  background: rgba(7, 21, 39, 0.82);
  backdrop-filter: blur(3px);
  animation: nz-creando-fundido var(--trans-media) ease;
}

.funnel-creando[hidden] { display: none; }

.funnel-creando__caja {
  max-width: 26rem;
  text-align: center;
  color: var(--c-texto-inverso);
}

.funnel-creando__anillo {
  display: block;
  width: 3rem;
  height: 3rem;
  margin: 0 auto var(--esp-4);
  border-radius: 50%;
  border: 4px solid rgba(255, 255, 255, 0.25);
  border-top-color: var(--c-amarillo-500);
  animation: nz-girar 0.9s linear infinite;
}

.funnel-creando__titulo { font-size: var(--texto-xl); color: var(--c-blanco); }
.funnel-creando__texto { margin-top: var(--esp-3); color: var(--c-texto-inverso-suave); font-size: var(--texto-m); }

.funnel-creando__nota {
  display: inline-flex;
  align-items: flex-start;
  gap: var(--esp-2);
  margin-top: var(--esp-4);
  padding: var(--esp-3) var(--esp-4);
  border-radius: var(--radio-m);
  background: rgba(255, 255, 255, 0.1);
  color: var(--c-texto-inverso);
  font-size: var(--texto-s);
  text-align: left;
}

.funnel-creando__nota svg { flex: none; width: 1.1rem; height: 1.1rem; margin-top: 0.1rem; color: var(--c-amarillo-500); }

@keyframes nz-creando-fundido {
  from { opacity: 0; }
  to { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .funnel-creando { animation: none; }
  .funnel-creando__anillo { animation-duration: 1.6s; }
  .titular-opcion__marca svg { transition: opacity var(--trans-rapida); transform: none; }
}

/* ==================== Bloque de GAS del resultado (aditivo) ====================
   Se distingue del resultado eléctrico con el azul de la gota de gas del kit
   (--lg-blue). Todos los importes que muestra son CON impuestos. */
.resultado-gas__caja {
  margin-top: var(--esp-4);
  padding: var(--esp-4);
  border: 1px solid var(--c-borde, rgba(0,0,0,.1));
  border-left: 4px solid var(--lg-blue);
  border-radius: var(--radio-m);
  background: color-mix(in srgb, var(--lg-blue) 5%, transparent);
}
.resultado-gas__titulo { margin: 0; font-size: var(--texto-l, 1.15rem); color: var(--lg-blue); }
.resultado-gas__sub { margin: 0.15rem 0 var(--esp-3); font-size: var(--texto-s); color: var(--c-texto-suave, #667); }
.resultado-gas__comp { display: flex; gap: var(--esp-3); flex-wrap: wrap; }
.resultado-gas__col { flex: 1 1 8rem; }
.resultado-gas__col-etq { display: block; font-size: var(--texto-xs, .8rem); color: var(--c-texto-suave, #667); }
.resultado-gas__col-val { font-size: var(--texto-l, 1.15rem); }
.resultado-gas__ahorro {
  display: flex; align-items: baseline; gap: .5rem;
  margin-top: var(--esp-3); padding-top: var(--esp-3);
  border-top: 1px dashed var(--c-borde, rgba(0,0,0,.12));
}
.resultado-gas__ahorro-etq { font-size: var(--texto-s); color: var(--c-texto-suave, #667); }
.resultado-gas__ahorro-num { font-size: var(--texto-xl, 1.5rem); font-weight: 700; color: var(--lg-blue); }
.resultado-gas__decl { margin: var(--esp-2) 0 0; font-size: var(--texto-s); color: var(--c-texto-suave, #667); }
.resultado-gas__nota { margin: 0 0 var(--esp-2); font-size: var(--texto-s); }
.resultado-gas__tarifa { margin: var(--esp-3) 0 0; font-size: var(--texto-s); }
.resultado-gas__tarifa-etq { font-weight: 600; }

/* ============================================================
   Guía "¿Cómo lo calculamos?" (paso resultado) — botón discreto
   + <dialog> NATIVO con la explicación por partes. Look v2:
   papel, Space Grotesk, radios gota; el ámbar solo en el índice
   de parte y en la cifra de ahorro (sobre navy). funnel.js la
   construye desde la propuesta ya recibida (cero llamadas API).
   ============================================================ */
.como-calculamos {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  width: max-content;
  margin: clamp(0.35rem, 1.2vh, 0.65rem) auto 0;
  padding: 0.3rem 0.75rem;
  border: 0;
  background: none;
  border-radius: var(--radio-pill);
  font: inherit;
  font-size: var(--texto-xs);
  font-weight: 700;
  color: var(--c-marino-700);
  cursor: pointer;
}

.como-calculamos:hover,
.como-calculamos:focus-visible {
  color: var(--c-marino-900);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.como-calculamos:focus-visible {
  outline: 2px solid var(--c-foco);
  outline-offset: 2px;
}

.como-calculamos svg {
  flex: none;
  width: 1rem;
  height: 1rem;
}

/* ---------- El diálogo ---------- */
.guia {
  margin: auto;
  width: min(30rem, calc(100vw - 2rem));
  border: 1px solid var(--lz-linea);
  border-radius: var(--radius-gota);
  padding: 0;
  background: var(--lz-papel);
  color: var(--lz-tinta);
  box-shadow: var(--sombra-4);
}

.guia::backdrop {
  background: rgba(6, 16, 31, 0.55);
}

.guia__caja {
  padding: clamp(1.1rem, 3vh, 1.6rem) clamp(1.1rem, 4vw, 1.75rem);
}

.guia__cabecera {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--esp-3);
}

.guia__titulo {
  margin: 0;
  font-family: var(--fuente-marca);
  font-weight: 700;
  font-size: clamp(1.05rem, 2.3vh, 1.3rem);
  letter-spacing: -0.02em;
  color: var(--c-marino-950);
  outline: none;
}

.guia__cerrar {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border: 1px solid var(--lz-linea);
  border-radius: var(--radius-vivo);
  background: var(--c-blanco);
  color: var(--lz-tinta);
  cursor: pointer;
  transition: border-color var(--trans-rapida);
}

.guia__cerrar:hover {
  border-color: var(--c-marino-900);
}

.guia__cerrar:focus-visible {
  outline: 2px solid var(--c-foco);
  outline-offset: 2px;
}

.guia__cerrar svg {
  width: 1rem;
  height: 1rem;
}

/* "Parte n de 4": etiqueta small-caps que ancla la navegación */
.guia__paso-de {
  margin: var(--esp-2) 0 0;
  font-family: var(--fuente-marca);
  font-size: var(--texto-xs);
  font-weight: 500;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--lz-tinta-suave);
}

/* Alto mínimo: la navegación no salta entre partes de distinta altura */
.guia__partes {
  margin-top: var(--esp-3);
  min-height: 12.5rem;
}

/* ---------- Cada parte ---------- */
.guia-parte {
  display: grid;
  gap: var(--esp-2);
  justify-items: start;
}

.guia-parte[hidden] {
  display: none;
}

.guia-parte__indice {
  margin: 0;
  font-family: var(--fuente-marca);
  font-weight: 700;
  font-size: var(--texto-xs);
  font-variant-numeric: tabular-nums;
  color: var(--c-amarillo-500); /* índice numérico: patrón .lz-etiqueta__num */
}

.guia-parte__titulo {
  margin: 0;
  font-family: var(--fuente-marca);
  font-weight: 700;
  font-size: clamp(1.1rem, 2.5vh, 1.4rem);
  letter-spacing: -0.02em;
  line-height: 1.12;
  color: var(--c-marino-950);
}

/* La cifra de la parte: tarjeta gota con el dato como protagonista */
.guia-parte__dato {
  display: grid;
  gap: 2px;
  margin: 0;
  padding: var(--esp-3) var(--esp-4);
  max-width: 100%;
  border: 1px solid var(--lz-linea);
  border-radius: var(--radius-gota-s);
  background: var(--c-blanco);
}

.guia-parte__dato-etq {
  font-size: var(--texto-xs);
  color: var(--lz-tinta-suave);
}

.guia-parte__dato-num {
  font-family: var(--fuente-marca);
  font-weight: 700;
  font-size: clamp(1.5rem, 3.6vh, 2.1rem);
  line-height: 1.05;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  color: var(--c-marino-950);
}

/* Variante ahorro: navy con la cifra en ámbar (uso permitido del ámbar) */
.guia-parte__dato--ahorro {
  border-color: var(--c-marino-950);
  background: var(--c-marino-950);
}

.guia-parte__dato--ahorro .guia-parte__dato-etq {
  color: var(--c-texto-inverso-suave);
}

.guia-parte__dato--ahorro .guia-parte__dato-num {
  color: var(--c-amarillo-400);
}

/* Variante negativa: se pinta tal cual, sin celebración */
.guia-parte__dato--negativo {
  border-color: var(--c-error);
  background: var(--c-error-fondo);
}

.guia-parte__dato--negativo .guia-parte__dato-num {
  color: var(--c-error);
}

.guia-parte__texto {
  margin: 0;
  font-size: var(--texto-s);
  line-height: 1.55;
  color: var(--lz-tinta-suave);
  text-wrap: pretty;
}

/* ---------- Navegación anterior/siguiente + puntos ---------- */
.guia__nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--esp-3);
  margin-top: var(--esp-4);
  padding-top: var(--esp-3);
  border-top: 1px solid var(--lz-linea);
}

.guia__nav-boton {
  font-family: var(--fuente-marca);
  font-weight: 600;
  font-size: var(--texto-s);
  padding: 0.5rem 1rem;
  border: 1.5px solid var(--lz-tinta);
  border-radius: var(--radius-gota-s);
  background: transparent;
  color: var(--lz-tinta);
  cursor: pointer;
  transition: border-radius var(--dur-v2-2) var(--ease-salida-v2),
    opacity var(--trans-rapida);
}

.guia__nav-boton:hover:not(:disabled),
.guia__nav-boton:focus-visible {
  border-radius: var(--radius-vivo); /* la esquina viva se afila al interactuar */
}

.guia__nav-boton:focus-visible {
  outline: 2px solid var(--c-foco);
  outline-offset: 3px;
}

.guia__nav-boton:disabled {
  opacity: 0.35;
  cursor: default;
}

.guia__nav-boton--siguiente {
  border-color: var(--c-marino-950);
  background: var(--c-marino-950);
  color: var(--c-blanco);
}

.guia__puntos {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.guia__punto {
  display: block;
  width: 0.55rem;
  height: 0.55rem;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--lz-linea);
  cursor: pointer;
  transition: background-color var(--trans-rapida), transform var(--trans-media);
}

.guia__punto.activo {
  background: var(--c-marino-900);
  transform: scale(1.35);
}

.guia__punto:focus-visible {
  outline: 2px solid var(--c-foco);
  outline-offset: 3px;
}

/* ---------- Movimiento de la guía ----------
   Entradas con @starting-style + allow-discrete (display/overlay del
   top layer). TODO detrás de la puerta de reduced-motion: sin ella el
   diálogo y las partes aparecen/desaparecen al corte, sin estados
   ocultos fuera de la puerta. */
@media (prefers-reduced-motion: no-preference) {
  .guia {
    opacity: 1;
    translate: 0 0;
    transition: opacity var(--dur-v2-2) var(--ease-salida-v2),
      translate var(--dur-v2-2) var(--ease-gota),
      display var(--dur-v2-2) allow-discrete,
      overlay var(--dur-v2-2) allow-discrete;
  }

  .guia:not([open]) {
    opacity: 0;
    translate: 0 14px;
  }

  @starting-style {
    .guia[open] {
      opacity: 0;
      translate: 0 14px;
    }
  }

  .guia::backdrop {
    opacity: 1;
    transition: opacity var(--dur-v2-2) ease,
      display var(--dur-v2-2) allow-discrete,
      overlay var(--dur-v2-2) allow-discrete;
  }

  .guia:not([open])::backdrop {
    opacity: 0;
  }

  @starting-style {
    .guia[open]::backdrop {
      opacity: 0;
    }
  }

  /* Cada parte entra al mostrarse (quitar [hidden] dispara @starting-style) */
  .guia-parte {
    transition: opacity var(--dur-v2-2) var(--ease-salida-v2),
      translate var(--dur-v2-2) var(--ease-salida-v2),
      display var(--dur-v2-2) allow-discrete;
  }

  @starting-style {
    .guia-parte:not([hidden]) {
      opacity: 0;
      translate: 10px 0;
    }
  }
}

/* Microinteracciones de la guía también quietas con reduced-motion */
@media (prefers-reduced-motion: reduce) {
  .guia__punto,
  .guia__nav-boton,
  .guia__cerrar {
    transition: none;
  }

  .guia__punto.activo {
    transform: none;
  }
}

/* --- Petición de llamada (solo en resultados sin cobertura) ---------------
   Bloque discreto: aparece cuando NO tenemos tarifa para su perfil y el
   resultado ya se ha entregado. No compite con el CTA ni lo sustituye. */
.valoracion[hidden] { display: none; }

.valoracion {
  margin-top: var(--esp-3);
  padding: var(--esp-3);
  border-radius: var(--radio-m);
  border: 1px solid var(--c-borde);
  background: var(--c-fondo-suave);
  text-align: left;
}

.valoracion__intro {
  margin: 0 0 var(--esp-2);
  font-weight: 600;
  color: var(--c-texto);
}

.valoracion__casilla {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  cursor: pointer;
  font-size: var(--texto-s);
  line-height: 1.5;
  color: var(--c-texto);
}

.valoracion__casilla input { margin-top: 0.2rem; flex: 0 0 auto; }

.valoracion__detalle {
  margin: var(--esp-2) 0 0;
  font-size: var(--texto-xs);
  line-height: 1.55;
  color: var(--c-texto-suave);
  text-wrap: pretty;
}

.valoracion__estado[hidden] { display: none; }

.valoracion__estado {
  margin: var(--esp-2) 0 0;
  font-size: var(--texto-xs);
  font-weight: 600;
  color: var(--c-exito, #196f3d);
}

/* --- Ahorro anual + potencial + total ------------------------------------
   Lo que ve quien SOLO mira el primer cuadro. Tres filas, de menos a mas:
   lo que le ahorra la tarifa, lo que puede recuperar dando de baja servicios
   que no son luz, y la suma. La tercera fila es suma VISUAL: el backend nunca
   las junta (ver el invariante en `bloqueAhorroAnualTotal`). */
.ahorro-anual {
  margin-top: var(--esp-3);
  border-radius: var(--radio-m);
  border: 1px solid var(--c-borde);
  overflow: hidden;
  text-align: left;
}

.ahorro-anual__fila {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  gap: 0.2rem var(--esp-3);
  padding: var(--esp-3);
  border-top: 1px solid var(--c-borde);
}

.ahorro-anual__fila:first-child { border-top: 0; }

.ahorro-anual__etq {
  font-size: var(--texto-s);
  font-weight: 700;
  color: var(--c-texto);
}

.ahorro-anual__cifra {
  font-size: var(--texto-xl, 1.7rem);
  font-weight: 800;
  line-height: 1;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  color: var(--c-exito, #196f3d);
}

.ahorro-anual__nota {
  grid-column: 1 / -1;
  margin-top: 0.35rem;
  font-size: var(--texto-xs);
  line-height: 1.5;
  color: var(--c-texto-suave);
  text-wrap: pretty;
}

/* Aviso, no oferta: este dinero no se lo damos nosotros. */
.ahorro-anual__fila--potencial { background: var(--c-aviso-fondo, #fff4e5); }
.ahorro-anual__fila--potencial .ahorro-anual__cifra { color: var(--c-aviso, #a35f00); }

.ahorro-anual__fila--total { background: var(--c-fondo-suave); }
.ahorro-anual__fila--total .ahorro-anual__etq { font-size: var(--texto-m, 1rem); }
.ahorro-anual__fila--total .ahorro-anual__cifra { font-size: var(--texto-2xl); }

/* ============================================================================
   RESULTADO — lo único que hace distinto es quitarse la cabecera
   ============================================================================
   El ancho ya NO se toca aquí: `.funnel` fija un carril único para todo el
   proceso (2026-08-15). Antes este paso era el que «se liberaba» del carril de
   46rem, y ese salto de anchura era justo lo que hacía que el recuadro creciera
   y encogiera de un paso a otro.

   En el RESULTADO la cabecera ("Analiza tu factura…") y la barra de pasos ya no
   cuentan nada: el análisis está hecho (petición directa 2026-08-07). Al
   quitarlas, el informe sube y toda la información entra centrada de una. */
.funnel--resultado .funnel__cabecera,
.funnel--resultado .progreso { display: none; }

/* El panel del resultado ocupa el ancho disponible y respira. */
.funnel--resultado .paso--resultado {
  padding: clamp(1rem, 2.4vh, 2.25rem) clamp(1rem, 2.6vw, 2.75rem);
}

/* A partir de tablet grande, lo PRIORITARIO se reparte en dos columnas: la
   comparación de facturas a la izquierda y el ahorro + servicios a la derecha,
   de modo que las dos cifras que deciden la venta caben juntas sin scroll.
   Por debajo de ese ancho se mantiene el apilado de siempre. */
@media (min-width: 60rem) {
  .funnel--resultado .resultado__principal {
    display: grid;
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    grid-template-areas:
      "chips  chips"
      "comp   ahorro"
      "comp   titular"
      "comp   cta"
      "gas    gas";
    gap: clamp(1rem, 2vw, 1.75rem);
    align-items: start;
  }

  /* TODO hijo directo ocupa la fila entera POR DEFECTO, y solo los cinco de
     abajo reciben su area. Sin esta regla, los hijos sin `grid-area` (el h2
     accesible, el boton de la guia, el bloque de valoracion, la alerta de
     error, el disclosure del detalle) se auto-colocan en las celdas libres y
     descuadran toda la rejilla. Ademas deja el layout a prueba de futuro: un
     bloque nuevo cae a ancho completo en vez de romper la composicion. */
  .funnel--resultado .resultado__principal > * { grid-column: 1 / -1; }

  .funnel--resultado .resultado__principal > [data-resultado-chips] { grid-area: chips; }
  .funnel--resultado .resultado__principal > [data-resultado-comparativa] { grid-area: comp; }
  .funnel--resultado .resultado__principal > [data-resultado-ahorro] { grid-area: ahorro; }
  .funnel--resultado .resultado__principal > [data-resultado-gas] { grid-area: gas; }
  .funnel--resultado .resultado__principal > [data-titular] { grid-area: titular; }
  .funnel--resultado .resultado__principal > .resultado__cta { grid-area: cta; }

  /* El detalle (tras el disclosure) sí va a ancho completo y en dos columnas
     fluidas: es lectura, no decisión. */
  .funnel--resultado .resultado__detalle {
    columns: 2;
    column-gap: clamp(1rem, 2.5vw, 2.25rem);
  }
  .funnel--resultado .resultado__detalle > * {
    break-inside: avoid;
    -webkit-column-break-inside: avoid;
  }
}

/* ---------- Rotación CON / SIN servicios de valor añadido ----------------
   Sin botones: la tarjeta de luzgasia se reescribe sola y una frase dice qué
   se está mirando. Se pidió expresamente que no hubiera controles. */
.sva-rotador {
  margin-top: var(--esp-2);
  text-align: center;
}

/* Esta nota es la que EXPLICA por qué la factura de al lado cambia sola. Iba en
   letra pequeña y gris de pie de página, y era ilegible justo cuando más falta
   hacía. Ahora tiene tamaño y contraste de contenido, no de nota al margen. */
.sva-rotador__nota {
  margin: 0 auto;
  max-width: 52ch;
  min-height: 3.2em;
  padding: var(--esp-2) var(--esp-3);
  border-radius: var(--radio-s);
  background: var(--c-fondo-suave);
  font-size: var(--texto-s);
  font-weight: 500;
  line-height: 1.55;
  color: var(--c-texto);
  text-wrap: pretty;
}

@media (prefers-reduced-motion: no-preference) {
  .sva-rotador__nota {
    transition: opacity 240ms ease, transform 240ms ease;
  }

  .sva-rotador__nota--sale {
    opacity: 0;
    transform: translateY(-6px);
  }

  .sva-rotador__nota--entra {
    animation: sva-nota-entra 420ms var(--ease-gota, ease);
  }

  @keyframes sva-nota-entra {
    0%   { opacity: 0; transform: translateY(8px); }
    100% { opacity: 1; transform: translateY(0); }
  }
}


/* Vista "solo la luz": la fila de los servicios se ATENÚA en vez de
   desaparecer. Quitarla movería toda la tarjeta y el ojo perdería la
   referencia entre una vista y la otra. */
.fac--sin-sva .fac__fila:has(+ .fac__total),
.fac--sin-sva .fac__fila:last-of-type {
  opacity: 0.32;
  text-decoration: line-through;
  text-decoration-thickness: 1px;
}

@media (prefers-reduced-motion: no-preference) {
  .fac__fila { transition: opacity 320ms ease; }
  /* El total "late" al cambiar de vista para que se note que ha cambiado. */
  .fac__total-num--cambia { animation: fac-total-cambia 420ms var(--ease-gota, ease); }
  @keyframes fac-total-cambia {
    0%   { transform: scale(1); }
    45%  { transform: scale(1.09); }
    100% { transform: scale(1); }
  }
}

.fac__total-num { display: inline-block; }

/* La cifra total del ahorro anual: la que tiene que quedarse en la cabeza. */
.ahorro-anual__cifra--total { letter-spacing: -0.02em; }

/* ======================= GUÍA GUIADA (robot + blur) =======================
   Un robot asoma por la esquina; si lo pulsas, difumina la pantalla y va
   iluminando zona a zona con una frase en lenguaje llano. Pensado para que lo
   entienda alguien mayor que ve doce cifras y no sabe dónde mirar. */

/* --- El robot que asoma --- */
.robot-asoma {
  position: fixed;
  top: calc(var(--altura-cabecera, 4rem) + 0.75rem);
  right: clamp(0.5rem, 2vw, 1.5rem);
  z-index: 35;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
}

.robot-asoma[hidden] { display: none; }

.robot-asoma__bocadillo {
  position: relative;
  padding: 0.45rem 0.8rem;
  border-radius: var(--radio-pill);
  background: var(--c-texto, #0f172a);
  color: var(--c-blanco, #fff);
  font-size: var(--texto-xs);
  font-weight: 700;
  white-space: nowrap;
  box-shadow: var(--sombra-2, 0 10px 26px rgba(0, 0, 0, 0.22));
}

/* Piquito del bocadillo, apuntando al robot */
.robot-asoma__bocadillo::after {
  content: "";
  position: absolute;
  right: -5px;
  top: 50%;
  width: 10px;
  height: 10px;
  transform: translateY(-50%) rotate(45deg);
  background: inherit;
}

.robot-asoma__cuerpo {
  position: relative;
  width: 2.9rem;
  height: 2.9rem;
  border-radius: 1rem;
  background: var(--c-acento, #f59e0b);
  display: grid;
  place-items: center;
  box-shadow: var(--sombra-2, 0 10px 26px rgba(0, 0, 0, 0.22));
}

/* Antena */
.robot-asoma__cuerpo::before {
  content: "";
  position: absolute;
  top: -0.5rem;
  width: 2px;
  height: 0.5rem;
  background: var(--c-acento, #f59e0b);
}

.robot-asoma__cuerpo::after {
  content: "";
  position: absolute;
  top: -0.8rem;
  width: 0.4rem;
  height: 0.4rem;
  border-radius: 50%;
  background: var(--c-acento, #f59e0b);
}

.robot-asoma__cara { display: flex; gap: 0.45rem; }

.robot-asoma__ojo {
  width: 0.42rem;
  height: 0.42rem;
  border-radius: 50%;
  background: var(--c-texto, #0f172a);
}

/* Manita que saluda */
.robot-asoma__mano {
  position: absolute;
  left: -0.5rem;
  bottom: 0.3rem;
  width: 0.7rem;
  height: 0.7rem;
  border-radius: 50%;
  background: var(--c-acento, #f59e0b);
  transform-origin: bottom right;
}

@media (prefers-reduced-motion: no-preference) {
  .robot-asoma__cuerpo { animation: robot-flota 3.2s ease-in-out infinite; }

  @keyframes robot-flota {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-5px); }
  }

  .robot-asoma__mano { animation: robot-saluda 2.4s ease-in-out infinite; }

  @keyframes robot-saluda {
    0%, 60%, 100% { transform: rotate(0); }
    70%           { transform: rotate(-28deg); }
    85%           { transform: rotate(12deg); }
  }

  .robot-asoma__ojo { animation: guia-parpadeo 4.5s steps(1) infinite; }
}

/* En móvil el bocadillo estorba: solo el robot. */
@media (max-width: 42rem) {
  .robot-asoma__bocadillo { display: none; }
}

/* --- Velo que difumina el resto --- */
/* Capa de rescate: solo captura el clic para salir. El oscurecido lo dibuja el
   spotlight del elemento enfocado (ver `.guia-foco`), asi que aqui NO se pinta
   nada — dos capas oscuras se sumaban y ennegrecian la pantalla. */
.guia-velo {
  position: fixed;
  inset: 0;
  z-index: 29;
  background: transparent;
}

.guia-velo[hidden] { display: none; }

/* La zona que se explica se LEVANTA por encima del velo y se queda nítida; el
   resto se difumina de verdad (filter), no solo se oscurece: obliga al ojo a ir
   donde toca. */
body.guia-activa .funnel__cabecera,
body.guia-activa .progreso,
body.guia-activa .resultado__detalle,
body.guia-activa .resultado__principal > *:not(.guia):not(.guia-velo) {
  filter: blur(3px) saturate(0.65);
  opacity: 0.5;
  transition: filter 320ms ease, opacity 320ms ease;
}

/* La zona enfocada NUNCA lleva blur. El `:where(...)` no suma especificidad,
   así que se repite la cadena `:not()` de la regla de arriba para empatar y
   ganar por orden: al añadir aquellos dos `:not` la regla del blur pasó a pesar
   más que esta exención y el area iluminada salia borrosa — justo lo contrario
   de lo que tiene que pasar. */
body.guia-activa .resultado__principal > .guia-zona:not(.guia):not(.guia-velo) {
  position: relative;
  z-index: 31;
  filter: none !important;
  opacity: 1 !important;
}

/* Y tampoco lo lleva nada DENTRO de ella: un filtro se hereda visualmente a
   todos los descendientes y no se puede "desaplicar" hijo a hijo. */
body.guia-activa .guia-zona,
body.guia-activa .guia-zona * { filter: none; }

@media (prefers-reduced-motion: reduce) {
  body.guia-activa .resultado__principal > *:not(.guia):not(.guia-velo) {
    filter: none;
    opacity: 0.45;
    transition: none;
  }
}

/* El elemento exacto, con su anillo. Va dentro de una zona ya nítida. */
/* SPOTLIGHT de verdad, no un `outline`.
   El outline se recortaba contra los contenedores con `overflow: hidden` (el
   cuadro de ahorro lo tiene, y por eso el foco de "Te ahorrarías" salía cortado)
   y encima no daba ninguna sensación de profundidad: era una raya plana.

   Con `box-shadow` en capas se consiguen tres cosas de golpe:
     1. un halo interior claro que despega el bloque del fondo,
     2. el anillo de marca,
     3. una sombra de 9999px que OSCURECE todo lo de fuera recortando
        exactamente la silueta del elemento — el velo se dibuja solo, con las
        esquinas redondeadas correctas y sin recortes.
   `box-shadow` no lo clipa `overflow` como al outline. */
.guia-foco {
  position: relative;
  z-index: 32;
  border-radius: var(--radio-m);
  background: var(--c-blanco);
  box-shadow:
    0 0 0 1px rgba(255, 255, 255, 0.9),
    0 0 0 5px var(--c-acento, #f59e0b),
    0 0 34px 8px rgba(245, 158, 11, 0.45),
    0 18px 44px -12px rgba(15, 23, 42, 0.55),
    0 0 0 9999px rgba(15, 23, 42, 0.62);
}

/* Los contenedores que recortan a sus hijos dejan de hacerlo mientras la guía
   está activa: si no, el spotlight de una fila interior sale mutilado. */
body.guia-activa .ahorro-anual,
body.guia-activa .fac-duelo,
body.guia-activa .comparativa { overflow: visible; }

@media (prefers-reduced-motion: no-preference) {
  /* Entra con un "aterrizaje" y luego respira. Parpadear el color del anillo
     (lo de antes) despistaba mas que guiaba: el ojo persigue el MOVIMIENTO. */
  .guia-foco { animation: guia-aterriza 460ms var(--ease-gota, ease), guia-respira 2.6s ease-in-out 460ms infinite; }

  @keyframes guia-aterriza {
    0%   { transform: scale(1.035); }
    100% { transform: scale(1); }
  }

  @keyframes guia-respira {
    0%, 100% { box-shadow:
      0 0 0 1px rgba(255,255,255,0.9),
      0 0 0 5px var(--c-acento, #f59e0b),
      0 0 34px 8px rgba(245,158,11,0.45),
      0 18px 44px -12px rgba(15,23,42,0.55),
      0 0 0 9999px rgba(15,23,42,0.62); }
    50%      { box-shadow:
      0 0 0 1px rgba(255,255,255,0.9),
      0 0 0 5px var(--c-acento, #f59e0b),
      0 0 52px 14px rgba(245,158,11,0.62),
      0 18px 44px -12px rgba(15,23,42,0.55),
      0 0 0 9999px rgba(15,23,42,0.62); }
  }
}

/* --- El panel explicativo --- */
.guia {
  position: fixed;
  /* Lo coloca `posicionarPanel()` junto al bloque que esta explicando: un panel
     clavado abajo obligaba a mirar a dos sitios a la vez, y en pantallas cortas
     tapaba justo la zona iluminada. */
  top: var(--guia-top, auto);
  left: var(--guia-left, 50%);
  z-index: 40;
  transition: top 380ms var(--ease-gota, ease), left 380ms var(--ease-gota, ease);
  width: min(30rem, calc(100vw - 1.5rem));
  padding: var(--esp-3) var(--esp-3) var(--esp-3) 4.5rem;
  border-radius: var(--radio-m);
  background: var(--c-texto, #0f172a);
  color: var(--c-blanco, #fff);
  box-shadow: var(--sombra-2, 0 12px 32px rgba(0, 0, 0, 0.3));
  text-align: left;
}

.guia[hidden] { display: none; }

.guia__cerrar {
  position: absolute;
  top: 0.4rem;
  right: 0.6rem;
  border: 0;
  background: transparent;
  color: inherit;
  opacity: 0.6;
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
}

.guia__cerrar:hover { opacity: 1; }

.guia__robot {
  position: absolute;
  left: var(--esp-3);
  top: var(--esp-3);
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 0.85rem;
  background: var(--c-acento, #f59e0b);
  display: grid;
  place-items: center;
}

.guia__robot::before {
  content: "";
  position: absolute;
  top: -0.45rem;
  width: 2px;
  height: 0.45rem;
  background: var(--c-acento, #f59e0b);
}

.guia__robot::after {
  content: "";
  position: absolute;
  top: -0.7rem;
  width: 0.35rem;
  height: 0.35rem;
  border-radius: 50%;
  background: var(--c-acento, #f59e0b);
}

.guia__robot-cara { display: flex; gap: 0.4rem; }

.guia__ojo {
  width: 0.4rem;
  height: 0.4rem;
  border-radius: 50%;
  background: var(--c-texto, #0f172a);
}

@media (prefers-reduced-motion: no-preference) {
  .guia__ojo { animation: guia-parpadeo 4.5s steps(1) infinite; }

  @keyframes guia-parpadeo {
    0%, 92%, 100% { transform: scaleY(1); }
    95%           { transform: scaleY(0.15); }
  }

  .guia--saluda .guia__robot { animation: guia-saludo 520ms var(--ease-gota, ease); }

  @keyframes guia-saludo {
    0%   { transform: translateY(0) rotate(0); }
    35%  { transform: translateY(-4px) rotate(-7deg); }
    70%  { transform: translateY(0) rotate(5deg); }
    100% { transform: translateY(0) rotate(0); }
  }
}

.guia__paso {
  margin: 0 0 0.3rem;
  font-size: var(--texto-xs);
  font-weight: 700;
  opacity: 0.65;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

/* Texto grande: se lee de un vistazo y a un metro de distancia. */
.guia__texto {
  margin: 0 0 var(--esp-2);
  font-size: var(--texto-m, 1.02rem);
  line-height: 1.55;
  text-wrap: pretty;
}

.guia__barra {
  height: 3px;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.18);
  margin-bottom: var(--esp-3);
  overflow: hidden;
}

.guia__barra::after {
  content: "";
  display: block;
  height: 100%;
  width: var(--guia-pct, 0%);
  border-radius: 3px;
  background: var(--c-acento, #f59e0b);
  transition: width 380ms var(--ease-gota, ease);
}

.guia__acciones {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 0.5rem;
}

.guia__flecha {
  width: 2.1rem;
  height: 2.1rem;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.35);
  background: transparent;
  color: inherit;
  cursor: pointer;
  font-size: 1rem;
  line-height: 1;
}

.guia__flecha:hover { background: rgba(255, 255, 255, 0.12); }

.guia__btn {
  padding: 0.5rem 1.2rem;
  border-radius: var(--radio-pill);
  border: 0;
  cursor: pointer;
  font-size: var(--texto-s);
  font-weight: 700;
  background: var(--c-acento, #f59e0b);
  color: var(--c-texto, #0f172a);
}


/* ---------- Continuar SIEMPRE a la vista (pasos 1-4) ----------------------
   Los pasos de formulario pueden desbordar en pantallas bajas (o con el teclado
   del movil abierto) y el boton de seguir se quedaba por debajo del pliegue: el
   usuario cree que la pantalla ha terminado y abandona. Cero friccion para
   pasar de paso es la regla.

   `sticky` NO saca el boton del flujo, asi que al final del scroll queda en su
   sitio; solo se mantiene visible mientras haya contenido por debajo. El
   RESULTADO se excluye: alli el CTA vive en la columna derecha. */
.paso:not(.paso--resultado) .paso__acciones {
  position: sticky;
  bottom: 0;
  z-index: 3;
  padding-block: clamp(0.5rem, 1.4vh, 0.9rem);
  /* Degradado en vez de corte duro: deja intuir que hay mas contenido debajo.
     El blanco OPACO empieza donde empiezan los botones y el degradado queda
     ENCIMA de ellos: con el corte al 70 % la mitad de arriba del boton era
     semitransparente y en el movil se veia la tarjeta de detras cruzando el
     «Volver» — parecia un solape, no una barra fija. La franja difuminada la
     da el `padding` de arriba, que es espacio vacio. */
  background: linear-gradient(
    to top,
    var(--c-blanco) calc(100% - clamp(0.5rem, 1.4vh, 0.9rem)),
    transparent
  );
}

/* El altavoz va con las flechas, pero a la izquierda: es un ajuste, no un paso. */
.guia__voz { margin-right: auto; font-size: 1rem; }


/* --- Transición "otra versión de la factura" (solo la tarjeta de luzgasia) ---
   La del cliente NO se mueve: es su referencia fija. Mover las dos hacía que la
   pantalla entera pareciera inestable. */
@media (prefers-reduced-motion: no-preference) {
  .fac--propia { transition: transform 240ms ease, opacity 240ms ease; }

  .fac--mutando {
    transform: translateY(-10px) scale(0.985);
    opacity: 0;
  }

  .fac--mutada { animation: fac-entra 460ms var(--ease-gota, ease); }

  @keyframes fac-entra {
    0%   { transform: translateY(14px) scale(0.985); opacity: 0; }
    60%  { transform: translateY(-3px) scale(1.004); opacity: 1; }
    100% { transform: translateY(0) scale(1); opacity: 1; }
  }
}


/* El robot deja su esquina y viaja con el panel mientras guía: así se lee como
   que la explicación sale de él. Sin bocadillo (lo dice el panel) y por encima
   del velo para que se le vea entero. */
.robot-asoma--guiando {
  top: var(--robot-top, 1rem);
  left: var(--robot-left, auto);
  right: auto;
  z-index: 41;
  transition: top 380ms var(--ease-gota, ease), left 380ms var(--ease-gota, ease);
  pointer-events: none;   /* no tapa los botones del panel */
}

.robot-asoma--guiando .robot-asoma__bocadillo { display: none; }


/* --- Entrada escalonada del cuadro de ahorro ---
   Cada fila aparece un poco después que la anterior, así el total se lee como
   el resultado de sumar las dos de arriba y no como un número más. */
@media (prefers-reduced-motion: no-preference) {
  .ahorro-anual--secuencia .ahorro-anual__fila {
    animation: ahorro-fila-entra 620ms var(--ease-gota, ease) backwards;
  }

  .ahorro-anual--secuencia .ahorro-anual__fila:nth-child(1) { animation-delay: 120ms; }
  .ahorro-anual--secuencia .ahorro-anual__fila:nth-child(2) { animation-delay: 520ms; }
  .ahorro-anual--secuencia .ahorro-anual__fila--total {
    animation: ahorro-total-entra 760ms var(--ease-gota, ease) 980ms backwards;
  }

  @keyframes ahorro-fila-entra {
    0%   { opacity: 0; transform: translateY(14px); }
    100% { opacity: 1; transform: translateY(0); }
  }

  /* El total además "aterriza": un rebote corto que remata la suma. */
  @keyframes ahorro-total-entra {
    0%   { opacity: 0; transform: translateY(20px) scale(0.96); }
    55%  { opacity: 1; transform: translateY(-4px) scale(1.03); }
    100% { opacity: 1; transform: translateY(0) scale(1); }
  }
}


/* --- Banner de ahorro en tres estados ---
   Verde para lo que damos nosotros (firme); ámbar para lo que depende de que el
   cliente cancele sus servicios. El color hace de código: no hace falta leer la
   etiqueta para saber de qué tipo de dinero se está hablando. */
.fac-ahorro--rota {
  transition: background 520ms ease;
}

.fac-ahorro--firme .fac-ahorro__num { color: var(--c-exito-claro); }
.fac-ahorro--potencial .fac-ahorro__num { color: var(--c-acento, #f59e0b); }

@media (prefers-reduced-motion: no-preference) {
  .fac-ahorro--cambia .fac-ahorro__etq { animation: banner-etq 520ms var(--ease-gota, ease); }
  .fac-ahorro--cambia .fac-ahorro__num { animation: banner-num 620ms var(--ease-gota, ease); }

  @keyframes banner-etq {
    0%   { opacity: 0; transform: translateY(-6px); }
    100% { opacity: 1; transform: translateY(0); }
  }

  @keyframes banner-num {
    0%   { opacity: 0; transform: translateY(16px) scale(0.94); }
    55%  { opacity: 1; transform: translateY(-3px) scale(1.04); }
    100% { opacity: 1; transform: translateY(0) scale(1); }
  }
}


/* --- Cartel "usa las flechas" (una vez, al empezar la guía) --- */
.guia-pista {
  position: fixed;
  inset: 0;
  z-index: 42;
  display: grid;
  place-content: center;
  gap: var(--esp-3);
  justify-items: center;
  pointer-events: none;   /* nunca intercepta un clic */
}

.guia-pista[hidden] { display: none; }

.guia-pista__teclas { display: flex; gap: var(--esp-2); }

.guia-pista__tecla {
  display: grid;
  place-items: center;
  width: 4.5rem;
  height: 4.5rem;
  border-radius: var(--radio-m);
  background: var(--c-texto, #0f172a);
  color: var(--c-blanco, #fff);
  font-size: 2rem;
  line-height: 1;
  box-shadow: 0 14px 38px rgba(0, 0, 0, 0.35);
}

.guia-pista__texto {
  margin: 0;
  padding: 0.6rem 1.2rem;
  border-radius: var(--radio-pill);
  background: var(--c-texto, #0f172a);
  color: var(--c-blanco, #fff);
  font-size: var(--texto-m, 1.05rem);
  font-weight: 700;
  text-align: center;
}

@media (prefers-reduced-motion: no-preference) {
  .guia-pista__tecla:first-child { animation: pista-izq 1.5s ease-in-out infinite; }
  .guia-pista__tecla:last-child  { animation: pista-der 1.5s ease-in-out infinite; }

  @keyframes pista-izq {
    0%, 100% { transform: translateX(0); }
    50%      { transform: translateX(-9px); }
  }
  @keyframes pista-der {
    0%, 100% { transform: translateX(0); }
    50%      { transform: translateX(9px); }
  }

  .guia-pista { animation: pista-entra 420ms var(--ease-gota, ease); }
  @keyframes pista-entra {
    0%   { opacity: 0; transform: scale(0.94); }
    100% { opacity: 1; transform: scale(1); }
  }

  .guia-pista--sale { animation: pista-sale 600ms ease forwards; }
  @keyframes pista-sale {
    0%   { opacity: 1; }
    100% { opacity: 0; transform: scale(1.04); }
  }
}

/* ===== Hojas adicionales de la misma factura =====
   Solo tokens `--c-*`: la rampa resuelve claro/oscuro sin hex de fallback. */
.paginas-extra {
  margin: var(--esp-3) 0 0;
  padding: var(--esp-3);
  border: 1px solid var(--c-borde);
  border-radius: var(--radio-m);
  background: var(--c-blanco);
}
.paginas-extra[hidden] { display: none; }

.paginas-extra__titulo {
  margin: 0 0 var(--esp-2);
  font-size: var(--texto-s);
  font-weight: 600;
  color: var(--c-texto-suave);
}

.paginas-extra__lista {
  margin: 0 0 var(--esp-2);
  padding: 0;
  list-style: none;
  display: grid;
  /* Columna ACOTADA al contenedor: la implícita es `auto` (= max-content), que
     se estira al nombre de fichero largo y arrastra a `.paginas-extra` fuera de
     la caja (desbordaba ~330px pese a la elipsis del nombre, medido 2026-08-30).
     `minmax(0, 1fr)` la fija al ancho real; recién entonces el `min-width: 0` de
     `.paginas-extra__nombre` puede truncar. Las dos piezas son necesarias. */
  grid-template-columns: minmax(0, 1fr);
  gap: var(--esp-1);
}

.paginas-extra__item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--esp-2);
  padding: var(--esp-1) var(--esp-2);
  border-radius: var(--radio-s);
  background: var(--c-fondo);
  min-width: 0; /* item de grid: sin esto su min-content volvería a expandir la columna */
}

.paginas-extra__nombre {
  font-size: var(--texto-s);
  /* Los nombres de fichero del móvil son largos: se cortan en vez de romper la
     caja. `min-width: 0` es IMPRESCINDIBLE aquí — es un hijo flex directo de
     `.paginas-extra__item`, cuyo `min-width` por defecto es `auto` (= su
     min-content), así que sin esto NO se encoge y la elipsis nunca dispara: el
     nombre empujaba la fila y `.paginas-extra` desbordaba ~330px a 390px
     (medido 2026-08-30). Con `min-width: 0` se trunca con "…" y la caja aguanta. */
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.paginas-extra__quitar {
  flex: none;
  width: 1.75rem;
  height: 1.75rem;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--c-texto-suave);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
}
.paginas-extra__quitar:hover,
.paginas-extra__quitar:focus-visible { background: var(--c-borde); color: var(--c-texto); }

/* ==========================================================================
   PASO 0 · ELECCION DE VIA — tres tarjetas grandes
   --------------------------------------------------------------------------
   Cada tarjeta transiciona a SU sistema: al elegir, la escogida crece un punto
   y las demas se apagan, y el wizard cambia de paso con su animacion de
   siempre. El dibujo es de trazo (como el resto del lenguaje visual del
   producto), nada de fotos de banco.
   ========================================================================== */
.tvias {
  display: grid;
  /* 11rem y no 13.5: el carril del wizard es estrecho y con el minimo alto la
     tercera tarjeta caia a una segunda fila dejando un hueco muerto al lado. */
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: var(--esp-4);
  margin-top: var(--esp-5);
}

.tvia {
  position: relative;
  display: grid;
  justify-items: center;
  text-align: center;
  gap: var(--esp-2);
  padding: var(--esp-6) var(--esp-4) var(--esp-5);
  border: 1px solid var(--c-borde);
  border-radius: var(--radio-l);
  /* --c-blanco y no --c-superficie (que no existe como token): con un valor
     inválido la tarjeta quedaba TRANSPARENTE y la onda del fondo la cruzaba. */
  background: var(--c-blanco);
  box-shadow: var(--sombra-1);
  color: var(--c-texto);
  cursor: pointer;
  transition: transform .22s cubic-bezier(.2,.8,.2,1), border-color .22s, box-shadow .22s;
}
.tvia:hover,
.tvia:focus-visible {
  transform: translateY(-4px);
  border-color: var(--lg-blue);
  box-shadow: 0 14px 34px rgb(11 26 51 / 0.10);
}
.tvia:focus-visible { outline: 2px solid var(--c-foco); outline-offset: 3px; }

.tvia__arte { width: clamp(6.5rem, 9vw, 8.5rem); color: var(--c-texto-suave); }
.tvia:hover .tvia__arte, .tvia:focus-visible .tvia__arte { color: var(--lg-blue); }
.tvia__acento { color: var(--lg-blue); }
.tvia__mono { font: 700 14px var(--fuente-marca); fill: currentColor; letter-spacing: .08em; }
.tvia__laser { fill: var(--lg-blue); opacity: .55; stroke: none; }
/* Sello de ahorro de la tarjeta CUPS: ámbar permitido (es cifra de ahorro). */
.tvia__ahorro-placa { fill: var(--c-amarillo-400); }
.tvia__ahorro-texto { font: 700 12px var(--fuente-marca); fill: var(--c-marino-950); letter-spacing: .03em; }

.tvia__t { font-family: var(--fuente-display); font-weight: 600; font-size: 1.25rem; margin: 0; }
.tvia__p { font-size: 0.95rem; color: var(--c-texto-suave); margin: 0; max-width: 17rem; }

.tvia__sello {
  position: absolute; top: -0.7rem;
  font-size: 0.72rem; font-weight: 600; letter-spacing: .06em;
  padding: 0.28rem 0.7rem; border-radius: 99px;
  background: var(--c-amarillo-500); color: var(--c-marino-900);
}

/* En móvil el sello «Recomendada» se leía a 11.5px: sube al mínimo legible.
   Solo móvil — en escritorio la maqueta aprobada no se toca. */
@media (max-width: 40rem) {
  .tvia__sello { font-size: 0.75rem; }
}

/* La ELECCION, coreografiada (2026-08-15, «se puede conseguir algo mas
   bonito»): las tarjetas NO elegidas se retiran posandose hacia abajo y
   desvaneciendose; la escogida se alza un instante con su sombra —el «te he
   oido»— y SE ABRE hacia el flujo: sigue subiendo mientras se desvanece, y el
   paso de su via entra debajo. Un solo gesto continuo, sin destellos.
   Movimiento por `translate`/`scale` (propiedades independientes): no pisa el
   `transform` del hover. La escala tope es 1.05 = ~9px por lado, dentro del
   aire de 12px del carril — nada cruza el clip del scroller (el parpadeo del
   borde que ya se arreglo una vez). */
@media (prefers-reduced-motion: no-preference) {
  .tvias.decidido .tvia {
    transition: opacity 0.3s ease, translate 0.3s var(--ease-gota), scale 0.3s var(--ease-gota);
  }
  .tvias.decidido .tvia:not(.elegida) {
    opacity: 0;
    translate: 0 16px;
    scale: 0.955;
  }
  .tvia.elegida {
    border-color: var(--lg-blue);
    animation: tvia-abre 460ms cubic-bezier(0.3, 0, 0.3, 1) forwards;
  }
  @keyframes tvia-abre {
    0%   { translate: 0 0; scale: 1; opacity: 1; }
    45%  { translate: 0 -12px; scale: 1.045; opacity: 1;
           box-shadow: 0 26px 52px rgb(11 26 51 / 0.16); }
    100% { translate: 0 -30px; scale: 1.05; opacity: 0;
           box-shadow: 0 32px 60px rgb(11 26 51 / 0); }
  }
}

/* Cada tarjeta tiene su gesto propio en bucle, solo tras la puerta (peticion
   directa: las tres opciones animadas, no solo la factura). */
@media (prefers-reduced-motion: no-preference) {
  /* Con tu factura: el laser barre el documento. */
  .tvia__laser { animation: tvia-laser 2.8s ease-in-out infinite; }
  @keyframes tvia-laser {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-34px); }
  }
  /* Sin factura: los pomos de los sliders se ajustan solos, desfasados. */
  .tvia__pomo { animation: tvia-pomo 5.6s ease-in-out infinite; }
  .tvia__pomo--2 { animation-delay: 0.9s; animation-direction: reverse; }
  .tvia__pomo--3 { animation-delay: 1.8s; }
  @keyframes tvia-pomo {
    0%, 100% { transform: translateX(0); }
    35%      { transform: translateX(16px); }
    70%      { transform: translateX(-10px); }
  }
  /* Con tu CUPS — la historia en bucle de 7s: campo vacío un instante, el
     código se TECLEA (clip que avanza a saltos, como caracteres), el rayo
     chisporrotea cargando y brota el sello de ahorro con la firma gota. */
  .tvia__cups-texto { animation: tvia-cups-teclea 7s linear infinite; }
  @keyframes tvia-cups-teclea {
    0%, 12%  { clip-path: inset(0 100% 0 0); }
    17%      { clip-path: inset(0 82% 0 0); }
    22%      { clip-path: inset(0 68% 0 0); }
    27%      { clip-path: inset(0 55% 0 0); }
    32%      { clip-path: inset(0 42% 0 0); }
    37%      { clip-path: inset(0 26% 0 0); }
    42%, 96% { clip-path: inset(0 0 0 0); }
    100%     { clip-path: inset(0 100% 0 0); }
  }
  .tvia__cups-ahorro {
    transform-box: fill-box;
    transform-origin: center;
    animation: tvia-cups-ahorro 7s var(--ease-gota, ease-out) infinite;
  }
  @keyframes tvia-cups-ahorro {
    0%, 60%  { opacity: 0; transform: scale(0.5); }
    67%      { opacity: 1; transform: scale(1.12); }
    71%, 92% { opacity: 1; transform: scale(1); }
    98%, 100%{ opacity: 0; transform: scale(0.8); }
  }
}

/* ---------- Formularios de las vias manuales ---------- */
.svia__rejilla {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: var(--esp-4);
  margin-bottom: var(--esp-4);
  /* Sin esto, la ayuda bajo un campo (el importe) estira su celda y los
     vecinos de la fila quedan descolgados a media altura. */
  align-items: start;
}

/* Los INPUTS de una misma fila, a la MISMA altura aunque sus etiquetas ocupen
   distinto número de líneas.
   ---------------------------------------------------------------------------
   Cada `.campo` es un grid INDEPENDIENTE de tres filas —etiqueta · control ·
   ayuda (base.css)— así que mide sus filas por su cuenta. En la vía CUPS la
   etiqueta de «¿Cuántos kWh marcaba esa factura? (opcional)» ocupa dos líneas y
   la de «¿Con qué compañía estás ahora?» una sola: 24 px de desfase entre dos
   inputs de la misma fila, que es lo que se ve raro.

   Con `subgrid` esas filas dejan de ser de cada campo y pasan a ser las de la
   rejilla: todos los campos de la fila comparten altura de etiqueta, de control
   y de ayuda. Es lo único que aguanta SEIS idiomas — no depende de cuántas
   líneas ocupe cada traducción ni de cuántos campos haya. Un `min-height` en la
   etiqueta fijaría un número de líneas que cambia con el idioma y con el ancho
   de columna, y además no alinearía las ayudas.

   El span es 3 para TODOS, también para los campos sin ayuda: con spans
   distintos la colocación automática descuadra la rejilla. `margin-bottom: 0`
   porque el margen de un subgrid se cuela dentro de su última pista; el aire
   entre filas lo pone el `gap` de la rejilla.

   Sin soporte de subgrid todo queda exactamente como está hoy. */
@supports (grid-template-rows: subgrid) {
  .svia__rejilla > .campo {
    grid-row: span 3;      /* etiqueta · control · ayuda */
    grid-template-rows: subgrid;
    margin-bottom: 0;
  }
}
/* Lo que se teclea se tiene que LEER (peticion directa 2026-08-13: "ni se
   puede leer porque es enano"). 1rem minimo — que ademas evita el auto-zoom
   de iOS en inputs menores de 16px — y un poco mas de aire vertical. */
.svia .campo__entrada {
  font-size: 1rem;
  padding: 0.85rem 1rem;
}
/* Campo culpable de la validacion inline: el JS pone aria-invalid y este
   borde lo señala — el aviso de texto solo no dice CUAL de los campos falla. */
.svia .campo__entrada[aria-invalid="true"] {
  border-color: var(--c-error, #b3372c);
}
.svia .campo__etiqueta { font-size: 0.95rem; }
.svia .campo__ayuda { font-size: 0.85rem; line-height: 1.5; }
/* El CUPS es un CODIGO: mono, mas grande y con tracking, como se lee en la
   factura. El placeholder ensena la forma antes de escribir. */
.campo__entrada--codigo {
  font-family: var(--fuente-mono, ui-monospace, "Cascadia Mono", Consolas, monospace);
  font-size: 1.05rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.svia__subtitulo {
  font-family: var(--fuente-display);
  font-size: 1.15rem;
  margin: var(--esp-5) 0 var(--esp-3);
  padding-top: var(--esp-4);
  border-top: 1px solid var(--c-borde);
}
.svia__check { display: flex; gap: var(--esp-2); align-items: flex-start;
               margin: var(--esp-2) 0; font-size: 0.95rem; color: var(--c-texto-suave); }
.svia__check input { margin-top: 0.2rem; }
/* Fila de acciones de las vias manuales: volver IZQ, enviar DER, mismo
   nivel (peticion directa 2026-08-07). */
.svia__acciones {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: var(--esp-4);
  margin-top: var(--esp-4);
}
.svia__acciones .svia__enviar { margin-top: 0; margin-left: auto; }
.svia__acciones .svia__volver,
.paso__acciones .svia__volver { margin-top: 0; }
.svia__enviar { margin-top: var(--esp-4); }
/* "Elegir otra forma": pildora fantasma con flecha propia que entra deslizando
   y responde al hover (peticion directa: mas dinamica que un boton gris). */
.svia__volver {
  margin-top: var(--esp-5);
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  background: transparent;
  border: 1.5px solid var(--c-borde);
  border-radius: 999px;
  padding: 0.55rem 1.15rem;
  font: 600 0.92rem var(--fuente);
  color: var(--c-texto-suave);
  cursor: pointer;
  transition: border-color .2s, color .2s, transform .25s cubic-bezier(.2,.8,.2,1), box-shadow .2s;
}
.svia__volver::before {
  content: "←";
  font-weight: 700;
  transition: transform .25s cubic-bezier(.2,.8,.2,1);
}
.svia__volver:hover,
.svia__volver:focus-visible {
  border-color: var(--lg-blue);
  color: var(--lg-blue);
  transform: translateX(-3px);
  box-shadow: 0 6px 18px rgb(11 26 51 / 0.08);
}
.svia__volver:hover::before,
.svia__volver:focus-visible::before { transform: translateX(-4px); }
.svia__volver:focus-visible { outline: 2px solid var(--c-foco); outline-offset: 3px; }
@media (prefers-reduced-motion: no-preference) {
  .svia__volver { animation: svia-volver-entra .5s cubic-bezier(.2,.8,.2,1) both .15s; }
  @keyframes svia-volver-entra {
    from { opacity: 0; transform: translateX(14px); }
    to   { opacity: 1; transform: translateX(0); }
  }
}

.svia__gracias { display: grid; justify-items: center; text-align: center;
                 gap: var(--esp-2); padding: var(--esp-8) var(--esp-4); }
/* El display:grid de arriba PISABA al atributo hidden del parcial y el
   "Recibido" salia debajo del formulario sin haber enviado nada (bug visto
   por el cliente). El atributo tiene que ganar SIEMPRE. */
.svia__gracias[hidden] { display: none !important; }
.svia__gracias svg { width: 3rem; height: 3rem; color: var(--c-exito, #2e9960); }
.svia__gracias h3 { font-family: var(--fuente-display); font-size: 1.5rem; margin: 0; }
.svia__gracias p { color: var(--c-texto-suave); max-width: 30rem; margin: 0; }

/* La barra de progreso no aplica a la eleccion ni a las vias manuales: son
   caminos laterales, no tramos del asistente. */
.progreso.progreso--oculta { visibility: hidden; }

/* ==========================================================================
   CADA ZONA EN UNA PANTALLA — se usa el ANCHO antes que crecer hacia abajo
   --------------------------------------------------------------------------
   Petición directa (2026-08-15): «evita que cualquiera de las 3 vías se tenga
   que scrollear innecesariamente en cada zona individual del proceso, siempre
   centrado y usando espacio dinámicamente si existiera».

   Medido en un portátil de 1366x768 —la pantalla más común— con la cabecera y
   la barra de progreso puestas quedan 530 px de hueco, y los pasos medían:
   CUPS 837 · consentimientos 697 · sin factura 685 · datos 558. Los cuatro se
   salían, y el scroller del wizard (que existe como VÁLVULA para pantallas
   diminutas) se estaba usando como maqueta de todos los días.

   El arreglo no es encoger tipografías: es dejar de apilar en un carril de
   46rem cuando hay 1366 px de ancho vacíos a los lados.
   ========================================================================== */

/* MÓVIL — la cabecera del proceso se encoge para devolverle alto al paso.
   En un teléfono de 844 px, entre el header del sitio (72), el título con su
   promesa (127) y la barra (57) se iban 256 px de los 844: el formulario se
   quedaba con 534 y todo pedía scroll desde el primer paso.

   La promesa «gratis, en menos de un minuto y sin compromiso» es del briefing y
   NO se toca donde importa —antes de subir la factura o de dar tus datos, que
   es cuando se decide—; a partir de ahí ya has decidido, y ese alto vale más
   como formulario. En pantalla grande no se quita nada: allí sobra sitio. */
@media (max-width: 40rem) {
  .funnel__titulo { font-size: clamp(1.3rem, 6vw, 1.7rem); }
  .funnel__cabecera { margin-bottom: var(--esp-2); }
  .funnel:not([data-paso="subida"]):not([data-paso="sin-factura"]):not([data-paso="cups"]) .funnel__intro {
    display: none;
  }
}

/* Consentimientos en DOS COLUMNAS a partir de tablet grande.
   `columns` (multicolumna) y no una rejilla de dos carriles a propósito: el
   número de casillas VARÍA —la de la llamada solo sale en las vías manuales y
   la de lectura del DNI depende de un toggle— y una rejilla dejaría un hueco
   muerto abajo a la derecha cada vez que el número fuera impar. La
   multicolumna se equilibra sola: siempre compone un rectángulo, salgan tres
   casillas o cinco.

   El orden de lectura y el de tabulación siguen siendo el del DOM (arriba a
   abajo por columna), que es justo por donde va saltando el auto-foco. */
@media (min-width: 56rem) {
  .consentimientos {
    display: block; /* `columns` no aplica sobre un contenedor de rejilla */
    columns: 2;
    column-gap: var(--esp-3);
    /* Con la lista en dos columnas el bloque ya no es una tira larga y no
       necesita tanto aire por arriba; esos milímetros son los que hacen que
       las CINCO casillas (vías manuales, el peor caso) quepan sin scroll. */
    margin-top: var(--esp-2);
  }
  .consentimiento {
    /* Sin esto una casilla se parte por la mitad entre las dos columnas. */
    break-inside: avoid;
    /* El `gap` de la rejilla ya no existe en modo columna. */
    margin-bottom: var(--esp-3);
  }

  /* CONTACTO en tres filas en vez de cuatro. `campo--ancho` (fila entera)
     estaba puesto pensando en el carril de 46rem, donde un correo largo no
     cabía de otra forma; con 60rem cada carril mide ya ~26rem y nombre y
     correo caben en paralelo. El selector de tipo de cliente SÍ se queda a
     fila completa: es una botonera segmentada, no un campo. */
  .form-datos__rejilla > .campo--ancho:not(.campo--segmentos) {
    grid-column: auto;
  }

  /* ANÁLISIS: el escáner al lado de las fases, no encima.
     Apilados medían 548 px y se salían por 18. Puestos en paralelo la espera
     además se lee mejor: a la izquierda lo que está pasando (el barrido sobre
     la factura) y a la derecha por dónde va. NO se toca nada del escáner —
     ni su tamaño ni su animación—, solo dónde se coloca. */
  .analisis {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: center;
    gap: clamp(1rem, 3vw, 2.25rem);
  }
  /* El escáner ocupa la columna izquierda entera; mensaje, fases y nota se
     colocan solos en la derecha. Contar filas aquí es seguro: son los tres
     hermanos que quedan, y si alguien añade un cuarto caerá debajo, no encima
     del escáner. */
  .analisis > .escaner { grid-column: 1; grid-row: 1 / span 3; }
}

/* ==========================================================================
   MODO ELECCION — las tres tarjetas, LIBRES
   --------------------------------------------------------------------------
   Feedback directo (con dibujo) del cliente: la eleccion NO va dentro del
   recuadro del formulario ni bajo el titulo "Analiza tu factura" — ese titulo
   y la barra solo existen cuando ya has elegido "con tu factura". Aqui el
   carril estrecho se suelta, el panel pierde el recuadro y las tarjetas se
   extienden a lo ancho, como una portada.
   ========================================================================== */
.funnel--eleccion .funnel__cabecera,
.funnel--eleccion .progreso { display: none; }

/* Vias manuales en pantalla grande: el carril de 46rem apretaba el formulario
   en el centro con media pantalla vacia a cada lado (peticion 2026-08-14).
   Se suelta el carril y la rejilla se recompone en DOS filas completas
   (regla del "recuadro completo": sin columnas cojas ni huecos):
     fila 1 · potencia | consumo | tarifa
     fila 2 · importe (mas ancho, lleva ayuda) | tipo de cliente        */
/* TRES columnas, no un mapa de posiciones.
   ANTES esto repartía los campos con `:nth-child(1..5)` y coordenadas fijas.
   Funcionaba hasta que se añadió un campo en medio (la compañía actual): a
   partir de ahí cada regla apuntaba a otro campo, el sexto se quedaba sin
   ninguna y la rejilla salía descuadrada — sin ningún error, solo mal.

   Con tres carriles iguales los seis campos componen DOS FILAS COMPLETAS
   («recuadro completo», sin columnas cojas) y el reparto ya no depende de en
   qué posición esté cada uno:
     fila 1 · potencia | consumo  | importe
     fila 2 · compañía | tarifa   | tipo de cliente
   Lo que necesite doble ancho lo pide en el MARCADO con `.campo--doble`, al
   lado del campo, donde se ve.

   La vía CUPS compone sus DOS filas con cinco campos, porque el CUPS ocupa
   dos carriles (es un código de 20-22 caracteres):
     fila 1 · CUPS (doble)  | documento del titular
     fila 2 · importe       | consumo | compañía
   Al añadir el documento (§6.66) la compañía dejó de pedir doble ancho: con
   ella a 2/3 quedaban ocho celdas en tres carriles y la última fila salía con
   un hueco muerto. Si se añade o se quita un campo ahí, hay que recolocar los
   `.campo--doble` para que la suma vuelva a ser múltiplo de tres. */
@media (min-width: 56rem) {
  [data-form-svia] > .svia__rejilla {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    align-items: start;
  }
  [data-form-svia] > .svia__rejilla > .campo--doble { grid-column: span 2; }
}

/* TRAMO TABLET (37-56rem): el auto-fit de la rejilla daba DOS columnas con
   CINCO campos y el último («Tu tarifa» / la compañía en CUPS) quedaba solo
   en la última fila con media fila vacía al lado (medido en 768×1024,
   2026-08-28) — y en la franja alta del tramo podía dar TRES columnas SIN el
   `campo--doble` (que solo existe desde 56rem): otra rejilla coja, según el
   ancho del scrollbar. Se toma el tramo con dos carriles EXPLÍCITOS y, si el
   número de campos es IMPAR, el último cierra la fila entera («recuadro
   completo», §6.5). `:last-child:nth-child(odd)` es paridad ESTRUCTURAL, no
   un mapa de posiciones (§6.41): si un campo entra o sale, se adapta solo —
   con un número par de campos no hay nada que cerrar y no actúa. */
@media (min-width: 37rem) and (max-width: 55.9375rem) {
  [data-form-svia] > .svia__rejilla {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  [data-form-svia] > .svia__rejilla > .campo:last-child:nth-child(odd) {
    grid-column: 1 / -1;
  }
}

.funnel--eleccion .paso {
  background: transparent;
  border: 0;
  box-shadow: none;
  /* Un dedo de aire lateral, y NO es estético: la tarjeta elegida hace
     `scale(1.04)` y crece ~8px por cada lado. Sin este margen, el borde
     izquierdo de «Con tu factura» (la primera, pegada al límite) cruzaba el
     `overflow-x: clip` del scroller y PARPADEABA — desaparecía una fracción
     de segundo en plena transición (lo vio el dueño). El clip no se puede
     quitar: existe para que el slide entre pasos no cree scrollbars. */
  padding-inline: 0.75rem;
}
/* Y la ENTRADA de la elección va en fundido, como su salida: el slide de
   ±28px del wizard también asomaba las tarjetas por el borde del clip al
   volver con «Elegir otra forma». */
.funnel--eleccion .paso.activo { animation-name: nz-paso-salida-plano; animation-direction: reverse; }

/* ==========================================================================
   APERTURA DE VÍA — el primer paso de cada camino entra con su propio gesto
   --------------------------------------------------------------------------
   Petición directa (2026-08-15): «cuando clickeo con tu factura, sin factura
   o con tu CUPS, me gustaría una animación chula al inicio de cada área».
   La tarjeta elegida SE ABRE hacia el flujo (tvia-abre, arriba) y, al entrar
   el paso, cada vía enciende SU protagonista. (El barrido de luz que cruzaba
   el panel se quitó el mismo día a petición del dueño: «cambia el destello
   ese».) Todo tras la puerta de motion; el estado oculto vive dentro de las
   @keyframes (`both` + from), así que sin motion no falta nada.
   ========================================================================== */
@media (prefers-reduced-motion: no-preference) {
  /* CON FACTURA: el borde de puntos de la zona de subida se tiñe un instante
     y el icono del documento asciende con la firma gota, como diciendo
     «aquí». */
  /* OJO: `animation` es un shorthand — esta regla PISA el stagger base
     (`nz-hijo-entrada`) de la zona, así que se declaran las dos juntas. */
  .paso.activo[data-paso="subida"] .zona-subida {
    animation:
      nz-hijo-entrada 420ms cubic-bezier(0.22, 0.7, 0.35, 1) both,
      via-zona-borde 900ms ease-out 260ms both;
  }
  @keyframes via-zona-borde {
    from { border-color: var(--lg-blue); background-color: color-mix(in srgb, var(--lg-blue) 6%, transparent); }
    to   { border-color: var(--c-borde-fuerte); background-color: transparent; }
  }
  .paso.activo[data-paso="subida"] .zona-subida__icono {
    animation: via-icono 640ms var(--ease-gota) 320ms both;
  }
  @keyframes via-icono {
    from { opacity: 0; transform: translateY(14px) scale(0.72); }
    to   { opacity: 1; transform: none; }
  }

  /* SIN FACTURA: los campos del suministro se colocan en cascada, cada uno
     asentándose con la gota — la sensación de «tres datos y listo». */
  .paso.activo[data-paso="sin-factura"] .svia__rejilla > .campo {
    animation: via-campo 520ms var(--ease-gota) both;
  }
  .paso.activo[data-paso="sin-factura"] .svia__rejilla > .campo:nth-child(1) { animation-delay: 240ms; }
  .paso.activo[data-paso="sin-factura"] .svia__rejilla > .campo:nth-child(2) { animation-delay: 330ms; }
  .paso.activo[data-paso="sin-factura"] .svia__rejilla > .campo:nth-child(3) { animation-delay: 420ms; }
  .paso.activo[data-paso="sin-factura"] .svia__rejilla > .campo:nth-child(4) { animation-delay: 510ms; }
  .paso.activo[data-paso="sin-factura"] .svia__rejilla > .campo:nth-child(5) { animation-delay: 600ms; }
  @keyframes via-campo {
    from { opacity: 0; transform: translateY(12px) scale(0.985); }
    to   { opacity: 1; transform: none; }
  }

  /* CON CUPS: el campo del código es el protagonista — llega, y su borde
     pulsa una vez en azul-gas invitando a teclear. */
  .paso.activo[data-paso="cups"] .svia__rejilla > .campo {
    animation: via-campo 520ms var(--ease-gota) both;
  }
  .paso.activo[data-paso="cups"] .svia__rejilla > .campo:nth-child(1) { animation-delay: 240ms; }
  .paso.activo[data-paso="cups"] .svia__rejilla > .campo:nth-child(2) { animation-delay: 360ms; }
  .paso.activo[data-paso="cups"] .svia__rejilla > .campo:nth-child(3) { animation-delay: 480ms; }
  .paso.activo[data-paso="cups"] .svia__rejilla > .campo:nth-child(4) { animation-delay: 600ms; }
  .paso.activo[data-paso="cups"] .campo__entrada--codigo {
    animation: via-codigo 1100ms ease-out 700ms both;
  }
  @keyframes via-codigo {
    0%   { border-color: var(--c-borde); box-shadow: 0 0 0 0 color-mix(in srgb, var(--lg-blue) 35%, transparent); }
    35%  { border-color: var(--lg-blue); box-shadow: 0 0 0 6px color-mix(in srgb, var(--lg-blue) 18%, transparent); }
    100% { border-color: var(--c-borde); box-shadow: 0 0 0 0 transparent; }
  }
}
.funnel--eleccion .paso__titulo {
  text-align: center;
  font-family: var(--fuente-display);
  font-size: clamp(1.8rem, 1.2rem + 2.4vw, 2.9rem);
  margin-bottom: var(--esp-3);
}
.funnel--eleccion .paso__descripcion { text-align: center; margin-inline: auto; }

/* El bloque se sesga hacia arriba (peticion directa, subida dos veces): las
   TARJETAS quedan super centradas en altura y el titulo respira encima. El
   padding inferior desplaza el centro optico sin romper el auto-centrado ni
   provocar scroll cuando falta altura (margin-block auto colapsa antes). */
.funnel--eleccion .funnel__pasos { padding-bottom: 13vh; }

/* El primer paso de cada via, tambien sesgado hacia arriba («siento
   demasiado lejos la caja del primer paso y la linea del menu de arriba»,
   2026-08-15). Aqui NO vale el padding fijo de la eleccion: en un portatil
   comun (1366x768) la caja ya casi llena el alto y un padding provocaria
   scroll con cola muerta. Separadores FLEXIBLES en reparto 1:3 — el aire
   sobrante se reparte un cuarto arriba y tres abajo, y en cuanto falta
   altura se encogen a 0 (base 0) antes de que aparezca scroll. El
   `margin-block: auto` del paso no compite: el crecimiento flex consume el
   hueco libre antes de que los margenes auto vean nada. */
.funnel[data-paso="subida"] .funnel__pasos::before,
.funnel[data-paso="sin-factura"] .funnel__pasos::before,
.funnel[data-paso="cups"] .funnel__pasos::before {
  content: "";
  flex: 1 1 0;
}
.funnel[data-paso="subida"] .funnel__pasos::after,
.funnel[data-paso="sin-factura"] .funnel__pasos::after,
.funnel[data-paso="cups"] .funnel__pasos::after {
  content: "";
  flex: 3 1 0;
}

/* A lo ancho, las tarjetas crecen: mas dibujo, mas aire, sensacion de portal. */
.funnel--eleccion .tvias {
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: var(--esp-5);
  margin-top: var(--esp-8);
}

/* TRAMO TABLET (40-57rem): el auto-fit colocaba las TRES tarjetas en dos
   columnas y «Con tu CUPS» quedaba sola con una celda entera vacía al lado
   (~590×560 de hueco muerto, medido en 768×1024, 2026-08-28) — la rejilla
   coja que prohíbe la regla del recuadro completo (§6.5). En este tramo se
   fijan DOS carriles y, con un número IMPAR de vías activas, la última cierra
   la fila a lo ancho: composición 2+1, rectángulo completo. Paridad
   estructural, no mapa de posiciones (§6.41): las vías van por toggles de
   Admin y con DOS activas no hay nada que cerrar — el selector no actúa. */
@media (min-width: 40rem) and (max-width: 57rem) {
  .funnel--eleccion .tvias {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .funnel--eleccion .tvia:last-child:nth-child(odd) {
    grid-column: 1 / -1;
  }
}
.funnel--eleccion .tvia { padding: var(--esp-8) var(--esp-5) var(--esp-6); }
.funnel--eleccion .tvia__arte { width: clamp(8rem, 12vw, 11rem); }
.funnel--eleccion .tvia__t { font-size: 1.45rem; }

/* ============ Vias manuales: puente a factura + aviso de estimacion ======== */
/* (2026-08-13) El puente vive dentro del "gracias": un boton que parece
   enlace, coherente con el lz-flecha de al lado. */
.svia__gracias-puente { margin: 0.4rem 0 0; color: var(--c-texto-suave); }
.svia__gracias-puente .lz-flecha {
  background: none; border: 0; padding: 0; cursor: pointer; font: inherit;
}

/* Aviso de resultado ESTIMADO: arriba del todo, antes de la cifra. Fondo y
   color PROPIOS (leccion del aviso de cookies, §6.27): flota sobre bloques
   claros y no puede heredar. */
.resultado__estimado {
  margin: 0 0 1rem;
  padding: 0.85rem 1.1rem;
  border-radius: var(--radio-m);
  background: var(--c-aviso-fondo, #fdf3e3);
  border: 1px solid var(--c-aviso, #b7791f);
  color: var(--c-marino-900);
  font-size: var(--texto-s);
  line-height: 1.55;
}
