/* =====================================================================
   RENDIX · Sistema de diseño
   =====================================================================

   MOBILE FIRST DE VERDAD
   ----------------------
   No es "que se vea bien en el celular": es que el celular sea el caso
   PRINCIPAL. El trabajador rinde en la obra, de pie, con una mano, con
   guantes, con sol en la pantalla y con señal mala. El escritorio es el
   caso secundario (el que aprueba, sentado).

   De ahí salen las decisiones:
     · Barra de pestañas abajo, donde llega el pulgar. Los menús arriba
       obligan a hacer malabares con el teléfono.
     · Botón de escanear flotante y enorme: es LA acción del sistema.
     · Áreas táctiles de 48px mínimo. Un botón de 32px con guantes no
       se acierta.
     · Contraste alto: la pantalla se lee a pleno sol.
     · Nada depende de "pasar el mouse por encima": en un táctil no existe.

   COLOR
   -----
   Todo sale de --marca, que la empresa configura. Los tonos derivados se
   calculan con color-mix, así que cambiar un color en la configuración
   repinta el sistema entero sin tocar una línea de CSS.
   ===================================================================== */

/* ---------------------------------------------------------------------
   1. Tokens
   --------------------------------------------------------------------- */
:root {
  /* La inyecta el layout desde la configuración de la empresa. */
  --marca: #2563eb;

  --marca-hover:  color-mix(in srgb, var(--marca) 85%, black);
  --marca-suave:  color-mix(in srgb, var(--marca) 10%, white);
  --marca-borde:  color-mix(in srgb, var(--marca) 25%, white);
  /* La marca escrita como TEXTO (enlaces, insignias, títulos de sección).
     Se mezcla con --texto, no con negro ni con blanco: --texto es por
     definición el color que mejor contrasta con el fondo del tema, así
     que mezclar hacia él sólo puede mejorar la legibilidad, nunca
     empeorarla, y la misma fórmula sirve en claro y en oscuro.
     Con "80% marca + negro" un amarillo corporativo se quedaba en 2.3:1
     sobre fondo claro: ilegible. */
  --marca-texto:  color-mix(in srgb, var(--marca) 45%, var(--texto));

  /* Estados. Verde = plata que entra, rojo = plata que sale. */
  --exito:   #059669;
  --peligro: #dc2626;
  --alerta:  #d97706;
  --info:    #0284c7;

  --exito-suave:   #ecfdf5;
  --peligro-suave: #fef2f2;
  --alerta-suave:  #fffbeb;
  --info-suave:    #f0f9ff;

  /* Neutros */
  --fondo:        #f1f5f9;
  --superficie:   #ffffff;
  --superficie-2: #f8fafc;
  --borde:        #e2e8f0;
  --borde-fuerte: #cbd5e1;

  --texto:        #0f172a;
  --texto-suave:  #475569;
  /* Era #94a3b8 y contrastaba 2,56:1 sobre blanco: por debajo del 4,5:1 que
     este mismo archivo se exige arriba («la pantalla se lee a pleno sol»).
     De ahí cuelgan los folios, los contadores, las fechas y —lo que más
     estorbaba— el TEXTO DE AYUDA de todos los campos: el «12.345.678-9» que
     enseña cómo se escribe un RUT no se leía en la obra.
     #616e82 da 5,17:1 sobre --superficie, 4,94:1 sobre --superficie-2 y
     4,72:1 sobre --fondo, que es el más apretado de los tres; y se sigue
     distinguiendo de --texto-suave, que va en 7,6:1. El tema oscuro no se
     toca: ahí el gris de siempre ya daba 4,96:1. */
  --texto-tenue:  #616e82;

  /* Elevación: sombras suaves, nada de cajas flotando. */
  --sombra-sm: 0 1px 2px rgba(15, 23, 42, .06);
  --sombra:    0 1px 3px rgba(15, 23, 42, .08), 0 1px 2px rgba(15, 23, 42, .04);
  --sombra-md: 0 4px 12px rgba(15, 23, 42, .08), 0 2px 4px rgba(15, 23, 42, .04);
  --sombra-lg: 0 12px 32px rgba(15, 23, 42, .12), 0 4px 8px rgba(15, 23, 42, .06);

  --radio-sm: .5rem;
  --radio:    .75rem;
  --radio-lg: 1rem;
  --radio-xl: 1.25rem;

  --nav-alto: 4.25rem;
  --barra-alto: 3.75rem;

  --trans: 160ms cubic-bezier(.4, 0, .2, 1);

  /* Bootstrap toma estas para sus componentes. */
  --bs-primary: var(--marca);
  --bs-body-bg: var(--fondo);
  --bs-body-color: var(--texto);
  --bs-border-color: var(--borde);
  /* Bootstrap la deja fija en #f8f9fa y de ella cuelga el fondo de
     `.dropdown-item:hover` y `:focus`. En oscuro eso pintaba un fondo casi
     blanco con el texto también casi blanco encima: 1,03:1, el ítem
     desaparecía al pasar por encima o al tabular — justo en el menú de la
     cuenta, que es donde vive el selector de tema. Apuntándola al token del
     sistema se arregla en los tres temas de una vez, porque --superficie-2
     ya se redefine en cada uno. En claro vale #f8fafc contra el #f8f9fa de
     Bootstrap: no se distingue a ojo. */
  --bs-tertiary-bg: var(--superficie-2);
  --bs-border-radius: var(--radio);
  --bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
}

/* Modo oscuro: se sigue al sistema. Quien rinde de noche en la obra lo
   agradece, y de paso ahorra batería en pantallas OLED. */
@media (prefers-color-scheme: dark) {
  :root:not([data-tema="claro"]) {
    --fondo:        #0b1120;
    --superficie:   #131c31;
    --superficie-2: #1a2438;
    --borde:        #263449;
    --borde-fuerte: #364357;

    --texto:        #f1f5f9;
    --texto-suave:  #b8c4d6;
    --texto-tenue:  #7d8ba1;

    --marca-suave: color-mix(in srgb, var(--marca) 22%, #131c31);
    --marca-borde: color-mix(in srgb, var(--marca) 40%, #131c31);
    --marca-texto: color-mix(in srgb, var(--marca) 45%, var(--texto));

    --exito-suave:   color-mix(in srgb, var(--exito) 18%, #131c31);
    --peligro-suave: color-mix(in srgb, var(--peligro) 18%, #131c31);
    --alerta-suave:  color-mix(in srgb, var(--alerta) 18%, #131c31);
    --info-suave:    color-mix(in srgb, var(--info) 18%, #131c31);

    --sombra-sm: 0 1px 2px rgba(0, 0, 0, .4);
    --sombra:    0 1px 3px rgba(0, 0, 0, .5);
    --sombra-md: 0 4px 12px rgba(0, 0, 0, .5);
    --sombra-lg: 0 12px 32px rgba(0, 0, 0, .6);

    --bs-body-bg: var(--fondo);
    --bs-body-color: var(--texto);
    color-scheme: dark;
  }
}

/* Oscuro ELEGIDO a mano, independiente del sistema operativo.
   Va con `:root` delante a propósito: `:root:not([data-tema="claro"])` del
   bloque de arriba pesa (0,2,0) y un `[data-tema="oscuro"]` pelado pesa
   (0,1,0), así que en un equipo con el SO en oscuro ganaba el @media y este
   bloque no pintaba nada. Empatando el peso gana éste, que viene después.
   Se nota sólo al añadir algo que el @media no tenga —las sombras, sin ir
   más lejos—: se prueba en un PC con el SO oscuro, no se ve el efecto y uno
   concluye que el atributo no sirve. */
:root[data-tema="oscuro"] {
  --fondo: #0b1120;      --superficie: #131c31;  --superficie-2: #1a2438;
  --borde: #263449;      --borde-fuerte: #364357;
  --texto: #f1f5f9;      --texto-suave: #b8c4d6; --texto-tenue: #7d8ba1;
  --marca-suave: color-mix(in srgb, var(--marca) 22%, #131c31);
  --marca-borde: color-mix(in srgb, var(--marca) 40%, #131c31);
  --marca-texto: color-mix(in srgb, var(--marca) 45%, var(--texto));
  --exito-suave:   color-mix(in srgb, var(--exito) 18%, #131c31);
  --peligro-suave: color-mix(in srgb, var(--peligro) 18%, #131c31);
  --alerta-suave:  color-mix(in srgb, var(--alerta) 18%, #131c31);
  --info-suave:    color-mix(in srgb, var(--info) 18%, #131c31);

  /* Faltaban. Una sombra de rgba(15,23,42,.06) sobre un fondo #0b1120 no
     existe: las tarjetas quedaban planas y la hoja de opciones no se
     despegaba de la página de abajo. */
  --sombra-sm: 0 1px 2px rgba(0, 0, 0, .4);
  --sombra:    0 1px 3px rgba(0, 0, 0, .5);
  --sombra-md: 0 4px 12px rgba(0, 0, 0, .5);
  --sombra-lg: 0 12px 32px rgba(0, 0, 0, .6);

  --bs-body-bg: var(--fondo);
  --bs-body-color: var(--texto);
  color-scheme: dark;
}

/* Claro ELEGIDO a mano. Los tokens ya son los de :root, así que aquí sólo
   hace falta lo que el CSS no pinta: `color-scheme` gobierna lo que dibuja
   el navegador y no la hoja de estilos —el calendario de <input type=date>,
   el desplegable de <select>, las barras de desplazamiento y el
   autorrelleno de Chrome en el login—. Sin declararlo, en un equipo con el
   SO en oscuro esos controles salen oscuros sobre una página blanca. */
:root[data-tema="claro"] {
  color-scheme: light;
}

/* ---------------------------------------------------------------------
   2. Base
   --------------------------------------------------------------------- */
* { -webkit-tap-highlight-color: transparent; }

html { -webkit-text-size-adjust: 100%; }

body {
  background: var(--fondo);
  color: var(--texto);
  font-family: var(--bs-font-sans-serif);
  /* La barra inferior tapa el contenido si no se deja aire, y en iPhone
     la franja del gesto de inicio se come otro tanto. */
  padding-bottom: calc(var(--nav-alto) + env(safe-area-inset-bottom) + 1rem);
  overscroll-behavior-y: none;
  min-height: 100dvh;
}

@media (min-width: 992px) {
  body { padding-bottom: 2rem; }
}

/* Los números de plata SIEMPRE tabulares: si no, las columnas de montos
   bailan porque el "1" es más angosto que el "8" y la tabla se lee mal. */
.plata, .tabular, td.plata, .monto {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
}

a { color: var(--marca-texto); text-decoration: none; }
/* Al pasar por encima el enlace se acerca a --texto, NO a --marca-hover.
   --marca-hover mezcla la marca con NEGRO, que sirve sobre fondo claro pero
   en tema oscuro hunde el enlace contra el fondo: medido, 2,34:1 en «Ver
   todos» y 2,56:1 en los nombres de la lista de fondos — peor que el enlace
   en reposo, que es lo contrario de lo que tiene que pasar al apuntarlo.
   Mezclando contra --texto (30% marca en vez del 45% de reposo) el enlace
   SIEMPRE gana contraste al pasar por encima, en los dos temas y con
   cualquier color de marca. --marca-hover se queda como está: lo usan los
   botones y el degradado del manual, donde sí va sobre la marca. */
a:hover { color: color-mix(in srgb, var(--marca) 30%, var(--texto)); text-decoration: underline; }

:focus-visible {
  outline: 3px solid color-mix(in srgb, var(--marca) 60%, transparent);
  outline-offset: 2px;
  border-radius: 4px;
}

/* Quien tenga activado "reducir movimiento" no ve ninguna animación. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ---------------------------------------------------------------------
   3. Estructura
   --------------------------------------------------------------------- */
.contenedor {
  width: 100%;
  max-width: 1180px;
  margin-inline: auto;
  padding-inline: 1rem;
}

@media (min-width: 768px) { .contenedor { padding-inline: 1.5rem; } }

/* --- Iconos dentro de cajas de tamaño fijo --- */
/* Los iconos de Bootstrap son una fuente, y su alto de línea heredado
   puede descuadrarlos dentro de un círculo o cuadrado. La solución es
   fijar line-height:1 y el tamaño del glyph SOLO al icono que está dentro
   de la caja (el hijo directo <i>), nunca a todos los .bi de la página:
   tocar .bi en general desalinea los iconos que van en línea con texto,
   en botones y en la barra inferior.

   Cada caja declara el tamaño de SU icono para que quepa con holgura y no
   se salga (el reloj de arena de "Esperando revisión" se salía por esto). */
.stat-icono > i,
.cat-icono > i,
.vacio-icono > i,
.cabecera-marca .logo > i {
  display: block;
  line-height: 1;
}

.stat-icono > i { font-size: 1.125rem; }
.cat-icono > i  { font-size: 1.125rem; }
.vacio-icono > i { font-size: 2rem; }

/* Los contenedores de icono nunca se encogen en una fila flex. */
.stat-icono, .cat-icono, .avatar, .cat-icono, .cabecera-marca .logo {
  flex-shrink: 0;
}

/* --- Cabecera --- */
.cabecera {
  position: sticky;
  top: 0;
  z-index: 1030;
  background: color-mix(in srgb, var(--superficie) 88%, transparent);
  backdrop-filter: saturate(180%) blur(12px);
  -webkit-backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--borde);
  padding-top: env(safe-area-inset-top);
}

.cabecera-fila {
  height: var(--barra-alto);
  display: flex;
  align-items: center;
  gap: .75rem;
}

.cabecera-marca {
  display: flex;
  align-items: center;
  gap: .625rem;
  font-weight: 700;
  font-size: 1.0625rem;
  color: var(--texto);
  letter-spacing: -.01em;
  min-width: 0;
}

.cabecera-marca:hover { color: var(--texto); text-decoration: none; }

.cabecera-marca .logo {
  width: 2rem; height: 2rem;
  border-radius: .5rem;
  background: var(--marca);
  color: var(--sobre-marca, #fff);
  display: grid; place-items: center;
  font-size: 1rem;
  flex-shrink: 0;
}

.cabecera-marca .nombre {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* --- Navegación de escritorio --- */
.nav-escritorio { display: none; }

@media (min-width: 992px) {
  .nav-escritorio {
    display: flex;
    align-items: center;
    gap: .25rem;
    margin-left: 1.5rem;
  }

  .nav-escritorio a {
    padding: .5rem .875rem;
    border-radius: var(--radio-sm);
    color: var(--texto-suave);
    font-weight: 500;
    font-size: .9375rem;
    display: flex;
    align-items: center;
    gap: .5rem;
    transition: var(--trans);
  }

  .nav-escritorio a:hover {
    background: var(--superficie-2);
    color: var(--texto);
    text-decoration: none;
  }

  .nav-escritorio a.activo {
    background: var(--marca-suave);
    color: var(--marca-texto);
    font-weight: 600;
  }
}

/* --- Barra inferior (la principal en celular) --- */
.barra-inferior {
  position: fixed;
  bottom: 0; left: 0; right: 0;
  z-index: 1040;
  background: color-mix(in srgb, var(--superficie) 92%, transparent);
  backdrop-filter: saturate(180%) blur(16px);
  -webkit-backdrop-filter: saturate(180%) blur(16px);
  border-top: 1px solid var(--borde);
  padding-bottom: env(safe-area-inset-bottom);
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
}

@media (min-width: 992px) { .barra-inferior { display: none; } }

.barra-inferior a {
  height: var(--nav-alto);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .1875rem;
  color: var(--texto-tenue);
  font-size: .6875rem;
  font-weight: 600;
  position: relative;
  transition: color var(--trans);
}

.barra-inferior a:hover { text-decoration: none; }
.barra-inferior a i {
  font-size: 1.375rem;
  line-height: 1;      /* el alto de línea heredado descuadraba el icono */
  height: 1.375rem;
  display: flex;
  align-items: center;
}
.barra-inferior a.activo { color: var(--marca); }

/* Marca fina sobre la pestaña activa: se entiende sin leer. */
.barra-inferior a.activo::before {
  content: "";
  position: absolute;
  top: 0;
  width: 2rem; height: 3px;
  border-radius: 0 0 3px 3px;
  background: var(--marca);
}

/* --- Escanear, dentro de la barra --------------------------------
   Es LA acción del sistema, así que va destacada: el icono sobre un
   cuadrado de color de marca, con su nombre debajo como el resto.
   Antes era un botón redondo flotando sobre la barra, y se escondía
   solo en cada pantalla que tuviera una barra de acciones fija abajo
   —el formulario de gasto, el detalle del informe—. Aparecer y
   desaparecer sin motivo visible es peor que ser menos vistoso. */
.barra-inferior a.escanear i {
  width: 2.25rem;
  height: 2.25rem;
  border-radius: .75rem;
  background: var(--marca);
  color: var(--sobre-marca, #fff);
  justify-content: center;
  font-size: 1.25rem;
  transition: background var(--trans), transform var(--trans);
}

.barra-inferior a.escanear { color: var(--marca); }
.barra-inferior a.escanear:active i { transform: scale(.92); }
.barra-inferior a.escanear:hover i { background: var(--marca-hover); }

/* --- Encabezado de página --- */
.pagina-encabezado {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  margin: 1.5rem 0 1.25rem;
  flex-wrap: wrap;
}

.pagina-titulo {
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: -.02em;
  margin: 0;
  line-height: 1.2;
}

.pagina-bajada {
  color: var(--texto-suave);
  font-size: .9375rem;
  margin: .25rem 0 0;
}

@media (min-width: 768px) {
  .pagina-titulo { font-size: 1.75rem; }
}

/* ---------------------------------------------------------------------
   4. Tarjetas
   --------------------------------------------------------------------- */
.tarjeta {
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio-lg);
  box-shadow: var(--sombra-sm);
  overflow: hidden;
}

.tarjeta-cuerpo { padding: 1.125rem; }
@media (min-width: 768px) { .tarjeta-cuerpo { padding: 1.375rem; } }

.tarjeta-encabezado {
  padding: 1rem 1.125rem;
  border-bottom: 1px solid var(--borde);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  background: var(--superficie-2);
}

/* Lo de la derecha ("Ver todos", "Ver cartola", "Agregar") no se encoge:
   con un título largo el flex le quitaba el ancho y el enlace caía
   partido en dos líneas, una palabra en cada una. El que envuelve es el
   título, que para eso es texto. */
.tarjeta-encabezado > :last-child:not(:only-child) {
  flex-shrink: 0;
  white-space: nowrap;
}

.tarjeta-titulo {
  font-size: .9375rem;
  font-weight: 700;
  margin: 0;
  display: flex;
  align-items: center;
  gap: .5rem;
}

.tarjeta-pie {
  padding: .875rem 1.125rem;
  border-top: 1px solid var(--borde);
  background: var(--superficie-2);
}

/* ---------------------------------------------------------------------
   5. Panel de saldo
   --------------------------------------------------------------------- */
/* Lo primero que mira el trabajador al abrir la app: cuánta plata le
   queda. Por eso ocupa el lugar más visible y usa el número más grande
   de todo el sistema. */
.panel-saldo {
  background: linear-gradient(135deg, var(--marca), color-mix(in srgb, var(--marca) 55%, #7c3aed));
  color: var(--sobre-marca, #fff);
  border-radius: var(--radio-xl);
  padding: 1.5rem;
  position: relative;
  overflow: hidden;
  box-shadow: var(--sombra-md);
}

/* Círculo decorativo: da profundidad sin cargar la vista. */
.panel-saldo::after {
  content: "";
  position: absolute;
  top: -45%; right: -15%;
  width: 17rem; height: 17rem;
  border-radius: 50%;
  background: rgba(255, 255, 255, .09);
  pointer-events: none;
}

.panel-saldo .etiqueta {
  font-size: .75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  opacity: .85;
  display: flex;
  align-items: center;
  gap: .375rem;
}

.panel-saldo .cifra {
  font-size: clamp(2.125rem, 9vw, 2.75rem);
  font-weight: 800;
  letter-spacing: -.03em;
  line-height: 1.1;
  margin: .375rem 0 0;
  font-variant-numeric: tabular-nums;
}

.panel-saldo .detalle {
  font-size: .875rem;
  opacity: .9;
  margin-top: .5rem;
}

.panel-saldo .separador {
  border-top: 1px solid rgba(255, 255, 255, .2);
  margin: 1.125rem 0 .875rem;
}

/* Saldo negativo: el trabajador gastó más de lo que se le entregó. Se
   pinta distinto porque significa que la EMPRESA le debe, no al revés. */
.panel-saldo.negativo {
  background: linear-gradient(135deg, #b91c1c, #7f1d1d);
}

/* ---------------------------------------------------------------------
   6. Estadísticas
   --------------------------------------------------------------------- */
.grilla-stats {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: .75rem;
}

@media (min-width: 768px) {
  .grilla-stats { grid-template-columns: repeat(4, 1fr); gap: 1rem; }
  .grilla-stats.de-3 { grid-template-columns: repeat(3, 1fr); }
}

.stat {
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  padding: 1rem;
  display: flex;
  flex-direction: column;
  gap: .375rem;
  transition: var(--trans);
}

a.stat:hover {
  border-color: var(--marca-borde);
  box-shadow: var(--sombra-md);
  text-decoration: none;
  transform: translateY(-1px);
}

.stat-icono {
  width: 2.25rem; height: 2.25rem;
  border-radius: .625rem;
  display: grid; place-items: center;
  font-size: 1.125rem;
  background: var(--marca-suave);
  color: var(--marca-texto);
}

.stat-icono.exito   { background: var(--exito-suave);   color: var(--exito); }
.stat-icono.peligro { background: var(--peligro-suave); color: var(--peligro); }
.stat-icono.info    { background: var(--info-suave);    color: var(--info); }

/* OJO colisión de nombres: ".alerta" es también el componente caja-de-aviso
   (con su padding, borde y display:flex). Un <div class="stat-icono alerta">
   heredaba esa caja y se INFLABA (se veía como un icono gigante saliéndose
   del recuadro). Aquí se re-declara la caja del icono junto al color, con
   mayor especificidad (0,2,0 gana sobre el componente 0,1,0). */
.stat-icono.alerta {
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  padding: 0;
  border: 0;
  gap: 0;
  background: var(--alerta-suave);
  color: var(--alerta);
}

.stat-valor {
  font-size: 1.375rem;
  font-weight: 800;
  letter-spacing: -.02em;
  color: var(--texto);
  font-variant-numeric: tabular-nums;
  line-height: 1.15;
}

.stat-etiqueta {
  font-size: .75rem;
  color: var(--texto-suave);
  font-weight: 600;
  line-height: 1.3;
}

/* ---------------------------------------------------------------------
   7. Lista de informes y gastos
   --------------------------------------------------------------------- */
/* En celular NO se usan tablas: una tabla de 8 columnas en 375px obliga
   a hacer scroll horizontal, que es la peor experiencia posible. Se usan
   tarjetas apiladas con la información jerarquizada. */
.lista { display: flex; flex-direction: column; gap: .625rem; }

.lista-item {
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  padding: .875rem 1rem;
  display: block;
  color: var(--texto);
  transition: var(--trans);
  position: relative;
}

.lista-item:hover {
  border-color: var(--borde-fuerte);
  box-shadow: var(--sombra-md);
  text-decoration: none;
  color: var(--texto);
}

.lista-item:active { transform: scale(.995); }

/* Franja de color a la izquierda según el estado: se identifica de un
   vistazo, sin leer la etiqueta. */
.lista-item.con-franja { padding-left: 1.125rem; }

.lista-item.con-franja::before {
  content: "";
  position: absolute;
  left: 0; top: .625rem; bottom: .625rem;
  width: 4px;
  border-radius: 0 4px 4px 0;
  background: var(--borde-fuerte);
}

.lista-item.estado-enviado::before     { background: var(--info); }
.lista-item.estado-en_revision::before { background: var(--alerta); }
.lista-item.estado-aprobado::before    { background: var(--exito); }
.lista-item.estado-rechazado::before   { background: var(--peligro); }
.lista-item.estado-pagado::before      { background: var(--marca); }
.lista-item.estado-borrador::before    { background: var(--texto-tenue); }

.item-fila {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: .75rem;
}

/* Para las filas cuya derecha son BOTONES CON TEXTO, no una cifra corta.
   Sin esto, en 390 px los botones se quedan con el ancho y la columna de
   la izquierda baja a cuatro palabras por línea: el nombre del archivo se
   corta y los separadores «·» del meta caen solos en su propio renglón.
   Aquí los botones bajan a su propia fila y el texto recupera el ancho. */
.item-fila-envuelve { flex-wrap: wrap; }
.item-fila-envuelve > :first-child { flex: 1 1 15rem; min-width: 0; }
/* flex-shrink 1 y max-width 100%, no «0 0 auto»: con «0 0 auto» el bloque
   de acciones mide lo que miden todos sus hijos en una sola línea y no se
   puede encoger, así que un formulario de tres campos y un botón (la
   lista «por reponer») se salía 130 px del teléfono en vez de envolver.
   Medido en el DOM, no a ojo. */
.item-fila-envuelve > .item-acciones { flex: 0 1 auto; min-width: 0; max-width: 100%; margin-left: auto; }

.item-titulo {
  font-weight: 650;
  font-size: .9375rem;
  line-height: 1.35;
  margin: 0;
  /* Una línea con puntos suspensivos: un nombre de archivo del teléfono
     ("IMG_20260718_1234.jpg") es un token sin espacios que a 360px se
     derramaba por encima de los botones de la fila. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Cuando el título es TEXTO, no un nombre de archivo: que fluya en varias
   líneas. Con la elipsis de arriba, un detalle largo se llevaba por
   delante las insignias que van al final del título («Por revisar»), que
   es justo el dato por el que uno abre esa pantalla. */
.item-titulo-libre {
  overflow: visible;
  text-overflow: clip;
  white-space: normal;
  overflow-wrap: anywhere;
}

.item-meta {
  font-size: .8125rem;
  color: var(--texto-suave);
  display: flex;
  align-items: center;
  gap: .375rem;
  flex-wrap: wrap;
  margin-top: .1875rem;
}

.item-meta .punto { color: var(--texto-tenue); }

/* --- El separador viaja pegado al trozo que lo precede -------------
   Cada «·» es un elemento suelto dentro de un flex que envuelve, así
   que al partirse la línea quedaba flotando al final con aire a los dos
   lados o —peor— abriendo la siguiente línea, donde parece una viñeta
   («· N° 2300»). Con :has() el punto se dibuja como parte del trozo
   anterior: no puede empezar una línea nunca, y cuando la termina lo
   hace pegado al texto, como una coma.

   Para que funcione, cada trozo tiene que ser un ELEMENTO: el texto
   suelto no se puede seleccionar. Por eso los .item-meta llevan todos
   sus trozos en <span>.

   El @supports deja el comportamiento de antes en un navegador que no
   entienda :has(), en vez de dejarlo sin separadores. */
@supports selector(:has(*)) {
  .item-meta .punto { display: none; }

  .item-meta > *:has(+ .punto)::after {
    content: '·';
    margin-left: .375rem;
    color: var(--texto-tenue);
  }
}

.item-monto {
  font-size: 1.0625rem;
  font-weight: 800;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  text-align: right;
}

/* --- Ocultar es ocultar -------------------------------------------
   Bootstrap declara `[hidden]{display:none!important}` cerca del
   principio y `.d-flex{display:flex!important}` 150 KB más abajo. Las
   dos con !important y la misma especificidad, así que gana la última:
   un elemento con clase de display NO se ocultaba nunca. Se veía en el
   formulario de gasto, donde «Cambio a CLP» aparecía en todos los
   gastos en pesos —el 99%— y el JS tampoco lograba esconderlo.
   app.css se carga después de Bootstrap, así que esta regla manda. */
[hidden] { display: none !important; }

/* --- Icono de categoría --- */
.cat-icono {
  width: 2.5rem; height: 2.5rem;
  border-radius: .625rem;
  display: grid; place-items: center;
  font-size: 1.125rem;
  flex-shrink: 0;
  /* --cat lo pone la vista con el color de la categoría. */
  background: color-mix(in srgb, var(--cat, var(--marca)) 14%, var(--superficie));
  color: var(--cat, var(--marca));
}

/* ---------------------------------------------------------------------
   8. Insignias
   --------------------------------------------------------------------- */
.insignia {
  display: inline-flex;
  align-items: center;
  gap: .3125rem;
  padding: .25rem .5625rem;
  border-radius: 2rem;
  font-size: .75rem;
  font-weight: 700;
  line-height: 1.4;
  white-space: nowrap;
}

.insignia i { font-size: .8125rem; }

/* El texto de las insignias NO es el color puro del estado: medido con
   WCAG, el naranja/celeste/verde puros sobre su fondo suave daban 3.1 a
   4.4 de contraste (mínimo legible: 4.5). Se oscurecen mezclando con el
   color del texto del tema: en claro los oscurece, y en oscuro (donde
   --texto es casi blanco) los ACLARA — la misma regla sirve para ambos. */
.insignia-secondary { background: var(--superficie-2);  color: var(--texto-suave); border: 1px solid var(--borde); }
.insignia-info      { background: var(--info-suave);    color: color-mix(in srgb, var(--info) 62%, var(--texto)); }
.insignia-warning   { background: var(--alerta-suave);  color: color-mix(in srgb, var(--alerta) 62%, var(--texto)); }
.insignia-success   { background: var(--exito-suave);   color: color-mix(in srgb, var(--exito) 62%, var(--texto)); }
.insignia-danger    { background: var(--peligro-suave); color: color-mix(in srgb, var(--peligro) 62%, var(--texto)); }
.insignia-primary   { background: var(--marca-suave);   color: var(--marca-texto); }
.insignia-dark      { background: var(--texto-suave);   color: var(--superficie); }

/* ---------------------------------------------------------------------
   9. Formularios
   --------------------------------------------------------------------- */
.campo { margin-bottom: 1.125rem; }

/* Autocompletado de proveedor: lista que aparece bajo el campo mientras se
   teclea el nombre o el RUT. El contenedor .campo se hace relative por JS. */
.autocompletar {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 40;
  margin-top: .25rem;
  max-height: 15rem;
  overflow-y: auto;
  background: var(--superficie);
  border: 1px solid var(--borde-fuerte);
  border-radius: .625rem;
  box-shadow: 0 10px 30px rgba(0, 0, 0, .18);
}
.autocompletar-item {
  display: flex;
  flex-direction: column;
  gap: .1rem;
  width: 100%;
  padding: .55rem .8rem;
  border: 0;
  border-bottom: 1px solid var(--borde);
  background: transparent;
  text-align: left;
  cursor: pointer;
}
.autocompletar-item:last-child { border-bottom: 0; }
.autocompletar-item:hover,
.autocompletar-item.activo { background: var(--marca-suave); }
.autocompletar-item .ac-nombre { font-weight: 600; font-size: .9rem; color: var(--texto); }
.autocompletar-item .ac-rut { font-size: .78rem; color: var(--texto-tenue); }

/* Modal de confirmación propio (App.confirmar). Reemplaza al confirm()
   nativo, que en el teléfono produce clicks fantasma al cerrarse. */
.confirmar-velo {
  position: fixed;
  inset: 0;
  z-index: 1080;                       /* sobre el resto, bajo nada */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.25rem;
  background: rgba(2, 8, 23, .55);
  animation: velo-entra .12s ease-out;
}
@keyframes velo-entra { from { opacity: 0; } to { opacity: 1; } }
.confirmar-caja {
  width: 100%;
  max-width: 26rem;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: .875rem;
  padding: 1.25rem;
  box-shadow: 0 20px 50px rgba(0, 0, 0, .35);
  animation: caja-entra .14s ease-out;
}
@keyframes caja-entra {
  from { opacity: 0; transform: translateY(.5rem) scale(.98); }
  to   { opacity: 1; transform: none; }
}
.confirmar-texto {
  margin: 0 0 1rem;
  font-size: .95rem;
  line-height: 1.55;
  color: var(--texto);
  white-space: pre-line;               /* respeta saltos de línea del mensaje */
}
.confirmar-botones {
  display: flex;
  gap: .625rem;
  justify-content: flex-end;
}
.confirmar-botones .btn { min-width: 6.5rem; }
@media (max-width: 30rem) {
  /* En el teléfono los botones a lo ancho: más fáciles de acertar. */
  .confirmar-botones { flex-direction: column-reverse; }
  .confirmar-botones .btn { width: 100%; }
}

/* --- Hoja de opciones (App.elegir) ---
   Sube desde abajo: las opciones quedan donde está el pulgar, no arriba
   en una esquina que obliga a recolocar la mano. En escritorio no tiene
   sentido pegarla al borde inferior, así que ahí se centra como diálogo. */
.hoja-velo {
  position: fixed;
  inset: 0;
  z-index: 1080;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  background: rgba(2, 8, 23, .55);
  animation: velo-entra .12s ease-out;
}
.hoja {
  width: 100%;
  max-width: 30rem;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: 1.125rem 1.125rem 0 0;
  padding: .5rem .75rem calc(.75rem + env(safe-area-inset-bottom));
  box-shadow: 0 -12px 40px rgba(0, 0, 0, .35);
  animation: hoja-sube .18s cubic-bezier(.2, .8, .3, 1);
  max-height: 85dvh;
  overflow-y: auto;
  overscroll-behavior: contain;
}
@keyframes hoja-sube {
  from { transform: translateY(100%); }
  to   { transform: none; }
}
/* La manito de agarre: señal universal de "esto sube y baja". */
.hoja::before {
  content: '';
  display: block;
  width: 2.25rem; height: .25rem;
  margin: .375rem auto .625rem;
  border-radius: 1rem;
  background: var(--borde);
}
.hoja-titulo {
  font-size: .8125rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--texto-suave);
  padding: .25rem .5rem .625rem;
}
.hoja-opcion {
  display: flex;
  align-items: center;
  gap: .875rem;
  width: 100%;
  min-height: 3.5rem;                  /* zona táctil cómoda */
  padding: .75rem;
  border: 1px solid transparent;
  border-radius: .75rem;
  background: transparent;
  color: var(--texto);
  text-align: left;
  transition: background var(--trans);
}
.hoja-opcion:hover,
.hoja-opcion:focus-visible { background: var(--superficie-2); }
.hoja-opcion:active { background: var(--superficie-2); transform: scale(.99); }
.hoja-opcion > .bi {
  flex: 0 0 2.5rem;
  height: 2.5rem;
  display: grid; place-items: center;
  border-radius: .625rem;
  /* Los tokens ya resueltos para tinte + texto sobre la marca: la marca la
     elige cada empresa y un color claro con `var(--marca)` encima se
     vuelve ilegible. Ya pasó con las insignias. */
  background: var(--marca-suave);
  color: var(--marca-texto);
  font-size: 1.125rem;
}
.hoja-textos { display: flex; flex-direction: column; gap: .125rem; min-width: 0; }
.hoja-opcion-titulo { font-weight: 600; font-size: .9375rem; }
.hoja-opcion-detalle { font-size: .8125rem; color: var(--texto-suave); line-height: 1.35; }
.hoja-cancelar {
  width: 100%;
  min-height: 3rem;
  margin-top: .5rem;
  border: 1px solid var(--borde);
  border-radius: .75rem;
  background: transparent;
  color: var(--texto-suave);
  font-weight: 600;
  font-size: .9375rem;
}
.hoja-cancelar:hover { background: var(--superficie-2); color: var(--texto); }

/* «Es este»: marca el botón al que hay que ir cuando la acción se pidió
   desde otra pantalla y el navegador no deja abrirla sola. */
.destacado {
  animation: destacar 1.3s ease-out 2;
  position: relative;
  z-index: 1;
}
@keyframes destacar {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--marca) 55%, transparent); }
  35%      { box-shadow: 0 0 0 .45rem color-mix(in srgb, var(--marca) 0%, transparent); }
}
@media (prefers-reduced-motion: reduce) {
  .destacado { animation: none; outline: 3px solid var(--marca); outline-offset: 2px; }
  .hoja { animation: none; }
}

@media (min-width: 48rem) {
  .hoja-velo { align-items: center; padding: 1.25rem; }
  .hoja {
    border-radius: 1rem;
    padding-bottom: .75rem;
    animation: caja-entra .14s ease-out;
    box-shadow: 0 20px 50px rgba(0, 0, 0, .35);
  }
  .hoja::before { display: none; }
}

.campo-etiqueta {
  display: block;
  font-size: .875rem;
  font-weight: 650;
  margin-bottom: .4375rem;
  color: var(--texto);
}

.campo-etiqueta .opcional {
  font-weight: 500;
  color: var(--texto-tenue);
  font-size: .8125rem;
}

.campo-ayuda {
  font-size: .8125rem;
  color: var(--texto-suave);
  margin-top: .375rem;
  line-height: 1.45;
}

.form-control, .form-select {
  background: var(--superficie);
  border: 1.5px solid var(--borde);
  border-radius: var(--radio-sm);
  color: var(--texto);
  /* 16px EXACTOS: con menos, Safari en iPhone hace zoom al enfocar el
     campo y descuadra toda la pantalla. Es el detalle que más delata
     a un formulario no pensado para celular. */
  font-size: 16px;
  padding: .6875rem .875rem;
  min-height: 3rem;
  transition: border-color var(--trans), box-shadow var(--trans);
}

@media (min-width: 992px) {
  .form-control, .form-select { font-size: .9375rem; min-height: 2.75rem; }
}

.form-control:focus, .form-select:focus {
  background: var(--superficie);
  border-color: var(--marca);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--marca) 12%, transparent);
  color: var(--texto);
}

.form-control::placeholder { color: var(--texto-tenue); }

.form-control.is-invalid, .form-select.is-invalid {
  border-color: var(--peligro);
  background-image: none; /* el icono de Bootstrap pisa el texto en campos cortos */
}

.form-control.is-invalid:focus {
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--peligro) 12%, transparent);
}

.invalid-feedback {
  font-size: .8125rem;
  font-weight: 500;
  color: var(--peligro);
  display: block;
  margin-top: .375rem;
}

/* --- Campo de monto --- */
/* El campo más importante del formulario: se ve grande y con el signo
   pegado, para que no quepa duda de qué se está escribiendo. */
.campo-monto { position: relative; }

.campo-monto .simbolo {
  position: absolute;
  left: .875rem;
  top: 50%;
  transform: translateY(-50%);
  color: var(--texto-tenue);
  font-weight: 700;
  font-size: 1.125rem;
  pointer-events: none;
}

.campo-monto input {
  padding-left: 2.125rem !important;
  font-size: 1.375rem !important;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
  min-height: 3.5rem;
}

/* --- Selector de opciones en tarjetas --- */
/* Un <select> nativo con 15 categorías en el celular es una ruleta
   imposible. Estas tarjetas se tocan directo. */
.opciones-grilla {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(6.5rem, 1fr));
  gap: .5rem;
}

.opcion-tarjeta { position: relative; }

.opcion-tarjeta input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.opcion-tarjeta label {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .375rem;
  padding: .875rem .5rem;
  min-height: 5rem;
  border: 2px solid var(--borde);
  border-radius: var(--radio);
  background: var(--superficie);
  cursor: pointer;
  text-align: center;
  font-size: .75rem;
  font-weight: 600;
  line-height: 1.25;
  color: var(--texto-suave);
  transition: var(--trans);
}

.opcion-tarjeta label i { font-size: 1.375rem; }

.opcion-tarjeta input:checked + label {
  border-color: var(--marca);
  background: var(--marca-suave);
  color: var(--marca-texto);
}

/* Variante en fila: un ícono y dos líneas de texto a la izquierda (una
   persona con su correo). La columna centrada de la tarjeta grande
   desperdicia el ancho y corta los correos largos. */
.opcion-tarjeta.opcion-fila label {
  flex-direction: row;
  justify-content: flex-start;
  text-align: left;
  gap: .625rem;
  min-height: 3.5rem;
  padding: .625rem .875rem;
  font-size: .875rem;
}
.opcion-tarjeta.opcion-fila label small {
  display: block;
  font-weight: 500;
  color: var(--texto-tenue);
  overflow-wrap: anywhere;
}
.opcion-tarjeta.opcion-fila input:checked + label small { color: inherit; opacity: .85; }

/* Variante compacta: una sigla, como los días de la semana. 48px de alto
   para que se acierte con el dedo aunque sean siete en una fila. */
.opcion-tarjeta.opcion-compacta label {
  min-height: 3rem;
  padding: .25rem;
  font-size: .8125rem;
}

/* --- Configuración: bloques dentro de una pestaña --- */
.config-subtitulo {
  font-size: 1rem;
  font-weight: 800;
  margin: 0 0 .25rem;
  color: var(--texto);
}
.config-subtitulo-sm { font-size: .9375rem; }
.config-bloque {
  margin-top: .5rem;
  padding: 1rem;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  background: var(--superficie-2);
}
.config-rejilla-personas {
  display: grid;
  gap: .5rem;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  /* Una empresa con muchos administradores no puede convertir la pestaña en
     un rollo infinito: la lista se desplaza sola dentro de su caja. */
  max-height: 19rem;
  overflow-y: auto;
  padding: .125rem;
  overscroll-behavior: contain;
}
.config-rejilla-dias {
  display: grid;
  gap: .375rem;
  grid-template-columns: repeat(7, minmax(0, 1fr));
}
.config-resumen {
  cursor: pointer;
  font-weight: 600;
  font-size: .875rem;
  color: var(--texto-suave);
  min-height: 2.75rem;
  display: flex;
  align-items: center;
}
.config-enlace-secreto {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .75rem;
}

/* El foco tiene que verse: se navega con teclado en escritorio. */
.opcion-tarjeta input:focus-visible + label {
  outline: 3px solid color-mix(in srgb, var(--marca) 60%, transparent);
  outline-offset: 2px;
}

/* --- Interruptor --- */
.interruptor {
  display: flex;
  align-items: flex-start;
  gap: .75rem;
  padding: .875rem 1rem;
  border: 1.5px solid var(--borde);
  border-radius: var(--radio);
  background: var(--superficie);
  cursor: pointer;
  transition: var(--trans);
}

.interruptor:has(input:checked) {
  border-color: var(--marca-borde);
  background: var(--marca-suave);
}

.interruptor .form-check-input {
  margin: 0;
  flex-shrink: 0;
  width: 2.75rem;
  height: 1.5rem;
  cursor: pointer;
}

.interruptor .form-check-input:checked {
  background-color: var(--marca);
  border-color: var(--marca);
}

/* Mismo caso: sin display:block la ayuda continuaba en la misma linea
   del titulo en cuanto el titulo no llenaba el renglon justo. */
.interruptor .texto { display: block; font-size: .875rem; font-weight: 650; line-height: 1.35; }
.interruptor .sub   { display: block; font-size: .8125rem; color: var(--texto-suave); margin-top: .125rem; line-height: 1.4; }

/* ---------------------------------------------------------------------
   10. Botones
   --------------------------------------------------------------------- */
.btn {
  border-radius: var(--radio-sm);
  font-weight: 650;
  font-size: .9375rem;
  padding: .6875rem 1.125rem;
  /* 48px: el mínimo que se acierta con el pulgar y con guantes. */
  min-height: 3rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  transition: var(--trans);
  border: 1.5px solid transparent;
}

.btn:active { transform: scale(.97); }

/* --sobre-marca la calcula PHP según el color que configuró la empresa:
   blanco para marcas oscuras, casi-negro para marcas claras. Con #fff
   fijo, una marca amarilla dejaba los botones primarios ilegibles. */
.btn-primary {
  background: var(--marca);
  border-color: var(--marca);
  color: var(--sobre-marca, #fff);
}

.btn-primary:hover, .btn-primary:focus {
  background: var(--marca-hover);
  border-color: var(--marca-hover);
  color: var(--sobre-marca, #fff);
}

.btn-secondary {
  background: var(--superficie);
  border-color: var(--borde-fuerte);
  color: var(--texto);
}

.btn-secondary:hover {
  background: var(--superficie-2);
  border-color: var(--texto-tenue);
  color: var(--texto);
}

.btn-success { background: var(--exito);   border-color: var(--exito);   color: #fff; }
.btn-danger  { background: var(--peligro); border-color: var(--peligro); color: #fff; }
.btn-success:hover { background: color-mix(in srgb, var(--exito) 85%, black);   color: #fff; }
.btn-danger:hover  { background: color-mix(in srgb, var(--peligro) 85%, black); color: #fff; }

.btn-outline-danger {
  border-color: var(--peligro);
  color: var(--peligro);
  background: transparent;
}
.btn-outline-danger:hover { background: var(--peligro); color: #fff; }

.btn-fantasma {
  background: transparent;
  color: var(--texto-suave);
  border-color: transparent;
}
.btn-fantasma:hover { background: var(--superficie-2); color: var(--texto); }

.btn-sm { min-height: 2.25rem; padding: .375rem .75rem; font-size: .8125rem; }
.btn-lg { min-height: 3.375rem; font-size: 1rem; font-weight: 700; }

.btn-bloque { width: 100%; }

/* Botón principal fijo abajo en móvil: "Guardar" siempre visible sin
   tener que hacer scroll hasta el fondo de un formulario largo.

   Compacta a propósito: una sola fila de botones, sin apilar. Antes eran
   2-3 botones grandes uno debajo del otro y, sumados a la barra de
   navegación y al botón flotante, se comían media pantalla del teléfono. */
.acciones-fijas {
  position: sticky;
  bottom: calc(var(--nav-alto) + env(safe-area-inset-bottom));
  background: color-mix(in srgb, var(--fondo) 94%, transparent);
  backdrop-filter: saturate(180%) blur(12px);
  -webkit-backdrop-filter: saturate(180%) blur(12px);
  padding: .625rem 1rem;
  margin: 1.25rem -1rem 0;
  border-top: 1px solid var(--borde);
  z-index: 20;
}

/* Una fila: el botón principal crece, los secundarios quedan compactos. */
.acciones-fila {
  display: flex;
  align-items: center;
  gap: .5rem;
  /* En el teléfono el botón principal se lleva la fila entera y los demás
     bajan debajo. Antes iban los tres apretados en una línea, y para que
     cupieran había que esconder los textos: quedaban botones con sólo un
     icono, imposibles de distinguir del principal. */
  flex-wrap: wrap;
}

.acciones-fila .btn {
  min-height: 3rem;
  padding-inline: .875rem;
  white-space: nowrap;
}

.acciones-fila .btn-principal {
  flex: 1 1 100%;
  min-width: 0;
}

/* Los secundarios se reparten la segunda fila. */
.acciones-fila .btn:not(.btn-principal) { flex: 1 1 auto; }

@media (min-width: 36rem) {
  .acciones-fila { flex-wrap: nowrap; }
  .acciones-fila .btn-principal { flex: 1 1 auto; }
  .acciones-fila .btn:not(.btn-principal) { flex: 0 0 auto; }
}


@media (min-width: 992px) {
  .acciones-fijas {
    position: static;
    background: transparent;
    backdrop-filter: none;
    border-top: 1px solid var(--borde);
    margin-inline: 0;
    padding: 1rem 0 0;
  }
  /* En escritorio el botón principal no necesita estirarse a todo el ancho. */
  .acciones-fila .btn-principal { flex: 0 0 auto; }
}

/* ---------------------------------------------------------------------
   11. Escáner
   --------------------------------------------------------------------- */
.escaner-capa {
  position: fixed;
  inset: 0;
  z-index: 2000;
  background: #000;
  display: none;
  flex-direction: column;
}

.escaner-capa.activo { display: flex; }

.escaner-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Ventana de puntería sobre el video, con el resto oscurecido.
   El truco del box-shadow gigante deja el recuadro limpio y todo lo
   demás en penumbra, sin necesidad de superponer cuatro divs. */
.escaner-mira {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  /* Los timbres PDF417 vienen de muy distinto alto y ancho. La ventana se
     hace GENEROSA (más ancha y más alta que antes) para que quepan tanto
     los apaisados como los más cuadrados, sin obligar a encuadrar justo.
     El lector igual analiza más allá de este recuadro (ver scanner.js), así
     que esto es sobre todo una guía visual holgada. */
  width: min(94vw, 34rem);
  aspect-ratio: 2.2 / 1;
  max-height: 60vh;
  border-radius: 1rem;
  box-shadow: 0 0 0 100vmax rgba(0, 0, 0, .55);
  pointer-events: none;
}

.escaner-mira::before,
.escaner-mira::after {
  content: "";
  position: absolute;
  width: 2rem; height: 2rem;
  border: 3px solid var(--marca);
}

.escaner-mira::before {
  top: -2px; left: -2px;
  border-right: none; border-bottom: none;
  border-radius: 1rem 0 0 0;
}

.escaner-mira::after {
  bottom: -2px; right: -2px;
  border-left: none; border-top: none;
  border-radius: 0 0 1rem 0;
}

/* ── Recuadro DINÁMICO: se pega al código encontrado ──────────────
   Cuando el localizador (scanner.js) ubica el código, el recuadro deja
   de estar centrado y pasa a posicionarse por píxeles sobre él. Como
   los timbres vienen de todos los tamaños, esto le muestra al usuario
   EXACTAMENTE qué está viendo el lector, y si le falta acercarse. */
.escaner-mira.dinamica {
  top: auto; left: auto;
  transform: none;
  width: auto;                 /* las medidas las pone el JS en píxeles */
  aspect-ratio: auto;
  max-height: none;
  /* El movimiento se acompaña, no se teletransporta. */
  transition: left .16s ease-out, top .16s ease-out,
              width .16s ease-out, height .16s ease-out,
              box-shadow .25s ease;
}

/* Enganchado: el marco se pinta en verde para decir "lo tengo". */
.escaner-mira.siguiendo::before,
.escaner-mira.siguiendo::after {
  border-color: var(--exito);
  width: 1.5rem; height: 1.5rem;
}

.escaner-mira.siguiendo {
  box-shadow: 0 0 0 100vmax rgba(0, 0, 0, .62),
              0 0 0 2px color-mix(in srgb, var(--exito) 70%, transparent),
              0 0 24px color-mix(in srgb, var(--exito) 55%, transparent);
}

.escaner-mira.siguiendo .escaner-linea {
  background: linear-gradient(90deg, transparent, var(--exito), transparent);
  box-shadow: 0 0 12px var(--exito);
  animation-duration: 1.1s;    /* late más rápido: está trabajando sobre el código */
}

/* Quien pidió menos movimiento no recibe el deslizamiento ni el barrido. */
@media (prefers-reduced-motion: reduce) {
  .escaner-mira.dinamica { transition: none; }
  .escaner-linea { animation: none; opacity: .8; }
}

/* Línea que barre: comunica "estoy buscando" sin texto. */
.escaner-linea {
  position: absolute;
  left: 6%; right: 6%;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--marca), transparent);
  animation: barrer 2.2s ease-in-out infinite;
  box-shadow: 0 0 12px var(--marca);
}

@keyframes barrer {
  0%, 100% { top: 12%; opacity: .4; }
  50%      { top: 88%; opacity: 1; }
}

.escaner-barra-sup {
  position: relative;
  z-index: 2;
  padding: calc(env(safe-area-inset-top) + .875rem) 1rem .875rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  background: linear-gradient(rgba(0, 0, 0, .75), transparent);
}

.escaner-barra-inf {
  position: relative;
  z-index: 2;
  margin-top: auto;
  padding: 1.5rem 1rem calc(env(safe-area-inset-bottom) + 1.5rem);
  background: linear-gradient(transparent, rgba(0, 0, 0, .85));
  text-align: center;
}

.escaner-instruccion {
  color: #fff;
  font-size: .9375rem;
  font-weight: 600;
  text-shadow: 0 1px 4px rgba(0, 0, 0, .8);
  margin-bottom: 1rem;
  line-height: 1.5;
}

.escaner-cerrar {
  width: 2.75rem; height: 2.75rem;
  border-radius: 50%;
  background: rgba(255, 255, 255, .16);
  backdrop-filter: blur(8px);
  color: #fff;
  border: none;
  display: grid; place-items: center;
  font-size: 1.25rem;
}

.escaner-chip {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  padding: .5rem 1rem;
  border-radius: 2rem;
  background: rgba(255, 255, 255, .16);
  backdrop-filter: blur(8px);
  color: #fff;
  font-size: .8125rem;
  font-weight: 600;
  border: none;
}

.escaner-chip.activo { background: var(--marca); }

/* Éxito: destello verde. Es feedback inmediato sin leer nada, que es lo
   que se necesita cuando estás apuntando el teléfono a una boleta. */
.escaner-exito {
  position: absolute;
  inset: 0;
  background: rgba(5, 150, 105, .35);
  display: grid;
  place-items: center;
  animation: destello .5s ease-out;
  z-index: 3;
}

.escaner-exito i { font-size: 5rem; color: #fff; }

@keyframes destello {
  from { opacity: 0; transform: scale(.85); }
  50%  { opacity: 1; }
  to   { opacity: 1; transform: scale(1); }
}

/* ---------------------------------------------------------------------
   12. Adjuntos
   --------------------------------------------------------------------- */
.adjuntos-grilla {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(5.5rem, 1fr));
  gap: .625rem;
}

.adjunto {
  position: relative;
  aspect-ratio: 3 / 4;
  border-radius: var(--radio-sm);
  overflow: hidden;
  border: 1.5px solid var(--borde);
  background: var(--superficie-2);
}

.adjunto img { width: 100%; height: 100%; object-fit: cover; }

.adjunto .pdf {
  width: 100%; height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .375rem;
  color: var(--peligro);
  font-size: 1.75rem;
}

.adjunto .pdf span { font-size: .625rem; font-weight: 700; color: var(--texto-suave); }

.adjunto-quitar {
  position: absolute;
  top: .3125rem; right: .3125rem;
  width: 1.625rem; height: 1.625rem;
  border-radius: 50%;
  background: rgba(0, 0, 0, .65);
  backdrop-filter: blur(4px);
  color: #fff;
  border: none;
  display: grid; place-items: center;
  font-size: .8125rem;
}

/* La zona TÁCTIL del botón de quitar es más grande que su dibujo: 26px
   visuales no se aciertan con el pulgar; el ::after invisible la lleva a
   ~44px sin cambiar cómo se ve. */
.adjunto-quitar::after {
  content: "";
  position: absolute;
  inset: -.5625rem;
}

/* Botón de agregar foto: caja punteada, el patrón que todo el mundo
   reconoce como "suelta algo aquí". */
.adjunto-agregar {
  aspect-ratio: 3 / 4;
  border: 2px dashed var(--borde-fuerte);
  border-radius: var(--radio-sm);
  background: var(--superficie-2);
  color: var(--texto-suave);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .375rem;
  font-size: .6875rem;
  font-weight: 600;
  cursor: pointer;
  transition: var(--trans);
}

.adjunto-agregar i { font-size: 1.5rem; }
.adjunto-agregar:hover { border-color: var(--marca); color: var(--marca); background: var(--marca-suave); }

/* ---------------------------------------------------------------------
   13. Alertas
   --------------------------------------------------------------------- */
.alerta {
  display: flex;
  gap: .75rem;
  padding: .875rem 1rem;
  border-radius: var(--radio);
  border: 1px solid;
  font-size: .875rem;
  line-height: 1.5;
  align-items: flex-start;
}

.alerta i.icono { font-size: 1.125rem; flex-shrink: 0; margin-top: .0625rem; }
/* display:block y no inline: el margen de abajo no hacia nada y el
   titulo quedaba pegado al texto en la misma linea, en los 21 avisos
   del sistema que lo usan. */
.alerta .titulo { display: block; font-weight: 700; margin-bottom: .1875rem; }

/* El texto se mezcla contra --texto, no contra negro ni contra blanco.
   --texto es por definición el color que mejor contrasta con el fondo del
   tema, así que la MISMA fórmula sirve en claro y en oscuro y no hace falta
   media query. Es el idioma que ya documenta .insignia más arriba.

   Antes eran dos juegos de reglas: uno mezclado con negro y otro, dentro de
   un @media, mezclado con blanco. Al poder elegir el tema a mano eso se
   rompía: con el SO en claro y el usuario en oscuro el fondo sí se
   oscurecía (viene de un token) pero el texto se quedaba en la variante
   negra — medido, 1.6:1, ilegible. Y son los 21 avisos del sistema: «Gasto
   guardado», «No se pudo aprobar». */
.alerta-exito   { background: var(--exito-suave);   border-color: color-mix(in srgb, var(--exito) 30%, transparent);   color: color-mix(in srgb, var(--exito) 62%, var(--texto)); }
.alerta-error   { background: var(--peligro-suave); border-color: color-mix(in srgb, var(--peligro) 30%, transparent); color: color-mix(in srgb, var(--peligro) 62%, var(--texto)); }
.alerta-aviso   { background: var(--alerta-suave);  border-color: color-mix(in srgb, var(--alerta) 30%, transparent);  color: color-mix(in srgb, var(--alerta) 62%, var(--texto)); }
.alerta-info    { background: var(--info-suave);    border-color: color-mix(in srgb, var(--info) 30%, transparent);    color: color-mix(in srgb, var(--info) 62%, var(--texto)); }

/* --- Avisos de política --- */
/* Lo que el motor de políticas levantó. Ámbar y no rojo: son señales
   para que un humano mire, no bloqueos. */
.avisos-politica {
  background: var(--alerta-suave);
  border: 1px solid color-mix(in srgb, var(--alerta) 35%, transparent);
  border-radius: var(--radio-sm);
  padding: .75rem .875rem;
  font-size: .8125rem;
  line-height: 1.5;
}

.avisos-politica ul { margin: .375rem 0 0; padding-left: 1.125rem; }
.avisos-politica li { margin-bottom: .1875rem; }

/* ---------------------------------------------------------------------
   14. Avisos flotantes
   --------------------------------------------------------------------- */
.avisos-flotantes {
  position: fixed;
  top: calc(env(safe-area-inset-top) + .75rem);
  left: 50%;
  transform: translateX(-50%);
  z-index: 2100;
  width: min(94vw, 28rem);
  display: flex;
  flex-direction: column;
  gap: .5rem;
  pointer-events: none;
}

/* Cerrar un aviso con el pulgar: 48px de zona táctil (el mínimo del
   sistema) aunque la X dibujada sea chica. El margen negativo absorbe el
   padding del aviso para que la caja no crezca. */
.btn-cerrar-aviso {
  background: none;
  border: none;
  padding: 0;
  color: var(--texto-tenue);
  font-size: .875rem;
  min-width: 3rem;
  min-height: 3rem;
  display: grid;
  place-items: center;
  margin: -.875rem -1rem -.875rem 0;
  flex-shrink: 0;
}

.aviso-flotante {
  pointer-events: auto;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-left: 4px solid var(--marca);
  border-radius: var(--radio);
  box-shadow: var(--sombra-lg);
  padding: .875rem 1rem;
  display: flex;
  gap: .75rem;
  align-items: flex-start;
  animation: entrar-arriba .28s cubic-bezier(.16, 1, .3, 1);
  font-size: .875rem;
  line-height: 1.45;
}

.aviso-flotante.exito   { border-left-color: var(--exito); }
.aviso-flotante.error   { border-left-color: var(--peligro); }
.aviso-flotante.aviso   { border-left-color: var(--alerta); }
.aviso-flotante.saliendo { animation: salir-arriba .22s ease-in forwards; }

@keyframes entrar-arriba {
  from { opacity: 0; transform: translateY(-1rem) scale(.96); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes salir-arriba {
  to { opacity: 0; transform: translateY(-.75rem) scale(.96); }
}

/* ---------------------------------------------------------------------
   15. Estado vacío
   --------------------------------------------------------------------- */
/* Una lista vacía no es un error: es una oportunidad de decirle a la
   persona qué hacer. Nunca dejar un "no hay datos" a secas. */
.vacio {
  text-align: center;
  padding: 3rem 1.5rem;
}

.vacio-icono {
  width: 4.5rem; height: 4.5rem;
  margin: 0 auto 1rem;
  border-radius: 50%;
  background: var(--marca-suave);
  color: var(--marca);
  display: grid; place-items: center;
  font-size: 2rem;
}

.vacio h3 { font-size: 1.0625rem; font-weight: 700; margin-bottom: .375rem; }
.vacio p  { color: var(--texto-suave); font-size: .875rem; max-width: 24rem; margin: 0 auto 1.25rem; line-height: 1.55; }

/* ---------------------------------------------------------------------
   16. Tablas (sólo escritorio)
   --------------------------------------------------------------------- */
.tabla-envoltorio {
  overflow-x: auto;
  border-radius: var(--radio);
  border: 1px solid var(--borde);
  background: var(--superficie);
  -webkit-overflow-scrolling: touch;
}

.tabla {
  width: 100%;
  margin: 0;
  border-collapse: collapse;
  font-size: .875rem;
}

.tabla th {
  background: var(--superficie-2);
  padding: .75rem 1rem;
  text-align: left;
  font-weight: 700;
  font-size: .75rem;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--texto-suave);
  border-bottom: 1px solid var(--borde);
  white-space: nowrap;
  position: sticky;
  top: 0;
  z-index: 1;
}

.tabla td {
  padding: .8125rem 1rem;
  border-bottom: 1px solid var(--borde);
  color: var(--texto);
  vertical-align: middle;
}

.tabla tbody tr:last-child td { border-bottom: none; }
.tabla tbody tr:hover { background: var(--superficie-2); }

.tabla tfoot td {
  background: var(--superficie-2);
  font-weight: 800;
  border-top: 2px solid var(--borde-fuerte);
}

.tabla .num { text-align: right; font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------------
   17. Línea de tiempo
   --------------------------------------------------------------------- */
.linea-tiempo { position: relative; padding-left: 1.75rem; }

.linea-tiempo::before {
  content: "";
  position: absolute;
  left: .4375rem; top: .375rem; bottom: .375rem;
  width: 2px;
  background: var(--borde);
}

.hito { position: relative; padding-bottom: 1.25rem; }
.hito:last-child { padding-bottom: 0; }

.hito::before {
  content: "";
  position: absolute;
  left: -1.75rem; top: .3125rem;
  width: 1rem; height: 1rem;
  border-radius: 50%;
  background: var(--superficie);
  border: 3px solid var(--borde-fuerte);
  z-index: 1;
}

.hito.exito::before   { border-color: var(--exito); }
.hito.peligro::before { border-color: var(--peligro); }
.hito.info::before    { border-color: var(--info); }
.hito.alerta::before  { border-color: var(--alerta); }

/* Misma colisión que en los iconos: un <div class="hito alerta"> no debe
   tomar la caja del componente de aviso. Se restablece la del hito. */
.hito.alerta {
  display: block;
  padding: 0 0 1.25rem;
  border: 0;
  background: none;
  gap: 0;
  align-items: initial;
}

.hito-titulo { font-size: .875rem; font-weight: 650; }
.hito-meta   { font-size: .75rem; color: var(--texto-tenue); margin-top: .0625rem; }
.hito-texto  { font-size: .8125rem; color: var(--texto-suave); margin-top: .375rem; line-height: 1.5; }

/* ---------------------------------------------------------------------
   18. Gráfico de barras
   --------------------------------------------------------------------- */
/* Sin librería de gráficos: son barras. Meter 200 KB de Chart.js para
   dibujar rectángulos proporcionales no se justifica. */
.barras { display: flex; flex-direction: column; gap: .875rem; }

.barra-fila { display: flex; flex-direction: column; gap: .375rem; }

.barra-cabecera {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  font-size: .8125rem;
}

.barra-nombre {
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: .4375rem;
  min-width: 0;
}

.barra-nombre span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.barra-punto {
  width: .625rem; height: .625rem;
  border-radius: 50%;
  flex-shrink: 0;
}

.barra-valor {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.barra-pista {
  height: .5rem;
  background: var(--superficie-2);
  border-radius: 1rem;
  overflow: hidden;
}

.barra-relleno {
  height: 100%;
  border-radius: 1rem;
  transition: width .5s cubic-bezier(.16, 1, .3, 1);
  min-width: 3px;
}

/* ---------------------------------------------------------------------
   19. Selector de tema
   --------------------------------------------------------------------- */
/* Tres botones pegados, como el de claro/oscuro del teléfono: se ve de un
   vistazo cuál está puesto y cuáles son las otras opciones, sin desplegar
   nada. Es un <form> con tres <button type=submit name=tema>: funciona sin
   una línea de JavaScript, que es lo que permite que el tema no dependa del
   navegador ni parpadee al cargar. */
.tema-grupo {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: .1875rem;
  background: var(--superficie-2);
  border: 1px solid var(--borde);
  border-radius: var(--radio-sm);
  padding: .1875rem;
  margin: 0;
}

.tema-opcion {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .1875rem;
  /* Sin esto, una etiqueta larga —o el tamaño de letra mínimo que algunos
     navegadores fuerzan— ensancha su columna y las otras dos se estrechan:
     los botones dejan de ser tercios iguales y el más chico baja del mínimo
     táctil. Con min-width:0 la rejilla manda y las tres miden lo mismo. */
  min-width: 0;
  /* 3.25rem = 52 px. La regla de la casa es 48 mínimo: esto se toca con
     guantes y con una mano. */
  min-height: 3.25rem;
  padding: .375rem .25rem;
  border: 0;
  background: transparent;
  border-radius: calc(var(--radio-sm) - .1875rem);
  color: var(--texto-suave);
  font-size: .6875rem;
  font-weight: 600;
  line-height: 1.2;
  cursor: pointer;
  transition: background var(--trans), color var(--trans);
}

.tema-opcion i { font-size: 1.0625rem; }

.tema-opcion:hover { color: var(--texto); }

/* El que está puesto. El borde NO es adorno: la pastilla blanca sobre la
   pista gris contrasta 1,05:1, o sea que sin él la única señal de cuál está
   elegido es el TONO del texto — invisible para quien no distingue colores,
   y casi invisible a pleno sol.

   Va con --marca-texto y NO con --marca a secas. La marca la configura cada
   empresa, y en crudo puede ser cualquier cosa: con un amarillo claro el
   borde caía a 1,5:1 sobre la pastilla blanca y con una marca casi negra
   caía a 1,05:1 en tema oscuro — o sea, desaparecía justo en el sitio que
   tiene que decir «éste es el que está puesto». --marca-texto se mezcla
   contra --texto, que por definición contrasta con el fondo del tema, así
   que aguanta cualquier marca en los dos temas. Medido con amarillo, verde
   limón, gris casi blanco y casi negro. */
.tema-opcion.activo {
  background: var(--superficie);
  color: var(--marca-texto);
  box-shadow: var(--sombra-sm), inset 0 0 0 1.5px var(--marca-texto);
}

/* ---------------------------------------------------------------------
   19b. Utilidades
   --------------------------------------------------------------------- */
.texto-suave { color: var(--texto-suave); }
.texto-tenue { color: var(--texto-tenue); }
/* Mezclados contra --texto, igual que .insignia y .alerta: el color plano
   sirve para un fondo de color, no para TEXTO sobre el fondo de la página.
   El ámbar crudo daba 3,19:1 sobre blanco en «1 informe(s) por revisar», que
   es un aviso que alguien tiene que leer. La misma fórmula sirve en los dos
   temas porque --texto es, por definición, lo que contrasta con el fondo. */
.texto-exito { color: color-mix(in srgb, var(--exito) 62%, var(--texto)); }
.texto-peligro { color: color-mix(in srgb, var(--peligro) 62%, var(--texto)); }
.texto-alerta { color: color-mix(in srgb, var(--alerta) 62%, var(--texto)); }
.texto-marca { color: var(--marca-texto); }

.solo-movil { display: block; }
.solo-escritorio { display: none; }

@media (min-width: 992px) {
  .solo-movil { display: none; }
  .solo-escritorio { display: block; }
}

/* Sólo para lectores de pantalla. */
.sr-solo {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.avatar {
  width: 2.5rem; height: 2.5rem;
  border-radius: 50%;
  background: var(--marca-suave);
  color: var(--marca-texto);
  display: grid; place-items: center;
  font-weight: 700;
  font-size: .8125rem;
  flex-shrink: 0;
}

.avatar-sm { width: 2rem; height: 2rem; font-size: .6875rem; }
.avatar-lg { width: 3.5rem; height: 3.5rem; font-size: 1.125rem; }

.separador-texto {
  display: flex;
  align-items: center;
  gap: .875rem;
  color: var(--texto-tenue);
  font-size: .8125rem;
  font-weight: 600;
  margin: 1.25rem 0;
}

.separador-texto::before,
.separador-texto::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--borde);
}

/* Esqueleto de carga: mejor que un spinner porque anticipa la forma
   de lo que viene. */
.esqueleto {
  background: linear-gradient(90deg, var(--superficie-2) 25%, var(--borde) 50%, var(--superficie-2) 75%);
  background-size: 200% 100%;
  animation: brillar 1.4s infinite;
  border-radius: var(--radio-sm);
}

@keyframes brillar {
  from { background-position: 200% 0; }
  to   { background-position: -200% 0; }
}

/* ---------------------------------------------------------------------
   19a. Pestañas (la configuración)
   ---------------------------------------------------------------------
   Bootstrap pinta la pestaña activa con `--bs-emphasis-color` (negro) sobre
   `--bs-body-bg`, y como el sistema apunta esa variable a --fondo, en modo
   oscuro quedaba NEGRO SOBRE CASI NEGRO: la pestaña abierta era la única
   que no se podía leer. Aquí se repinta con los tokens propios, que son
   los que saben del tema y del color de la empresa.
   --------------------------------------------------------------------- */
.nav-tabs {
  border-bottom: none;
  gap: .25rem;
  margin-bottom: -1px;          /* la activa tapa el borde de la franja */
  /* Nueve pestañas no caben en un teléfono. Antes que apilarlas en tres
     filas, se deslizan: la fila se mantiene y el pulgar arrastra. */
  flex-wrap: nowrap;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
}
.nav-tabs::-webkit-scrollbar { display: none; }

.nav-tabs .nav-link {
  display: flex;
  align-items: center;
  gap: .375rem;
  white-space: nowrap;
  padding: .5rem .875rem;
  border: 1px solid transparent;
  border-radius: var(--radio-sm) var(--radio-sm) 0 0;
  background: transparent;
  color: var(--texto-suave);
  font-weight: 600;
  font-size: .9375rem;
  transition: background var(--trans), color var(--trans);
}
.nav-tabs .nav-link:hover { color: var(--texto); background: var(--superficie); }

.nav-tabs .nav-link.active {
  color: var(--marca-texto);
  background: var(--superficie);
  border-color: var(--borde);
  /* Sin borde abajo: la pestaña abierta se funde con su contenido. */
  border-bottom-color: var(--superficie);
}
.nav-tabs .nav-link.active > .bi { color: var(--marca-texto); }

.nav-tabs .nav-link:focus-visible {
  outline: 3px solid color-mix(in srgb, var(--marca) 60%, transparent);
  outline-offset: -2px;
}

/* ---------------------------------------------------------------------
   19b. Manual de uso
   ---------------------------------------------------------------------
   Una página larga que se lee de corrido, en el teléfono y de pie. Por eso
   el texto es más grande que en el resto del sistema, las secciones están
   muy separadas y cada una entra por un color distinto: quien lee busca
   "la parte de la cámara", no el capítulo 4.

   Los dibujos (el teléfono, el escáner, el botón redondo) son HTML y CSS.
   Ninguna imagen: no se despixelan, se ven bien en modo oscuro y no hay
   archivos que se pierdan al actualizar por FTP.
   --------------------------------------------------------------------- */

/* --- Portada --- */
.manual-portada {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
  align-items: center;
  margin: 1.5rem 0 2rem;
  padding: 2rem 1.5rem;
  border-radius: var(--radio-xl);
  /* El degradado va de la marca a su propio tono oscuro, NO a un violeta
     fijo. Con un violeta, una marca clara (un amarillo, por ejemplo)
     dejaba un extremo casi blanco y el texto encima desaparecía. Así los
     dos extremos son del mismo color y --sobre-marca sirve para ambos:
     el extremo oscuro sólo puede MEJORAR el contraste, nunca empeorarlo. */
  background: linear-gradient(135deg, var(--marca), var(--marca-hover));
  color: var(--sobre-marca, #fff);
  box-shadow: var(--sombra-lg);
  overflow: hidden;
}
.manual-portada h1 {
  font-size: 1.875rem;
  font-weight: 800;
  letter-spacing: -.03em;
  line-height: 1.15;
  margin: .75rem 0 .875rem;
  color: var(--sobre-marca, #fff);
}
.manual-portada p {
  font-size: 1.0625rem;
  line-height: 1.6;
  margin: 0;
  color: var(--sobre-marca, #fff);
  opacity: .92;
  max-width: 34rem;
}
.manual-etiqueta {
  display: inline-block;
  font-size: .75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .1em;
  padding: .3rem .7rem;
  border-radius: 2rem;
  /* Sin relleno, sólo contorno. Un velo del color del texto ACLARA el
     fondo hacia el propio texto y el contraste baja (medido: 3.89:1, bajo
     el mínimo para letra chica). Sin relleno, la etiqueta se apoya en el
     degradado igual que el título, que ya está comprobado. */
  color: var(--sobre-marca, #fff);
  background: transparent;
  border: 1.5px solid color-mix(in srgb, var(--sobre-marca, #fff) 45%, transparent);
}
.manual-portada-botones { display: flex; gap: .625rem; flex-wrap: wrap; margin-top: 1.5rem; }
.btn-claro {
  background: var(--superficie); color: var(--texto); font-weight: 700; border: none;
}
.btn-claro:hover { background: var(--superficie-2); color: var(--texto); }
.btn-contorno-claro {
  background: transparent;
  color: var(--sobre-marca, #fff);
  border: 1.5px solid color-mix(in srgb, var(--sobre-marca, #fff) 55%, transparent);
  font-weight: 600;
}
/* Sin velo de fondo. El velo aclaraba el fondo justo donde va un texto del
   mismo color claro, así que al apuntarlo el botón se leía PEOR que en
   reposo: 3,98:1 con 15%, 4,32:1 con 10%, y el mínimo son 4,5. La señal de
   que está bajo el cursor la da el borde, que pasa de medio velado a
   completo: se nota igual y no cuesta nada de contraste. */
.btn-contorno-claro:hover {
  border-color: var(--sobre-marca, #fff);
  color: var(--sobre-marca, #fff);
}

/* --- Teléfono dibujado --- */
.manual-telefono { display: flex; justify-content: center; }
.manual-telefono-marco {
  width: 11rem;
  border-radius: 1.75rem;
  padding: .5rem;
  background: rgba(15, 23, 42, .5);
  border: 1px solid rgba(255, 255, 255, .22);
  box-shadow: 0 18px 40px rgba(0, 0, 0, .3);
}
.manual-telefono-pantalla {
  background: #f8fafc;
  border-radius: 1.35rem;
  padding: .55rem .5rem 0;
  display: flex; flex-direction: column; gap: .4rem;
  height: 15rem;
  position: relative;
  overflow: hidden;
}
.mt-cabecera {
  display: flex; align-items: center; gap: .3rem;
  font-size: .7rem; color: var(--marca); font-weight: 700;
}
.mt-cabecera span { flex: 1; height: .4rem; border-radius: 1rem; background: #e2e8f0; }
.mt-tarjeta {
  background: #fff; border: 1px solid #e2e8f0; border-radius: .5rem;
  padding: .45rem; display: flex; flex-direction: column; gap: .28rem;
}
.mt-linea { height: .35rem; border-radius: 1rem; background: #e2e8f0; width: 100%; }
.mt-linea.media { width: 60%; }
.mt-linea.corta { width: 38%; }
.mt-monto { height: .55rem; width: 45%; border-radius: 1rem; background: color-mix(in srgb, var(--marca) 35%, #e2e8f0); }
.mt-barra {
  position: absolute; left: 0; right: 0; bottom: 0;
  height: 2.4rem;
  background: #fff; border-top: 1px solid #e2e8f0;
  display: flex; align-items: center; justify-content: space-around;
  font-size: .7rem; color: #94a3b8;
}
.mt-boton {
  width: 1.9rem; height: 1.9rem; border-radius: 50%;
  background: var(--marca); color: #fff;
  display: grid; place-items: center; font-size: .8rem;
  margin-top: -1.1rem; border: 3px solid #fff;
  box-shadow: 0 4px 10px rgba(0, 0, 0, .2);
}

@media (min-width: 48rem) {
  .manual-portada { grid-template-columns: 1.4fr .9fr; padding: 2.75rem 2.5rem; }
  .manual-portada h1 { font-size: 2.5rem; }
}

/* --- Índice --- */
.manual-indice {
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio-lg);
  padding: 1.25rem;
  margin-bottom: 2rem;
  box-shadow: var(--sombra-sm);
}
.manual-indice-titulo {
  font-size: .8125rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .05em; color: var(--texto-suave); margin-bottom: .875rem;
}
.manual-indice-lista { display: grid; grid-template-columns: 1fr; gap: .375rem; }
.manual-indice-lista a {
  display: flex; align-items: center; gap: .75rem;
  padding: .625rem .75rem;
  border-radius: var(--radio-sm);
  color: var(--texto);
  font-weight: 600; font-size: .9375rem;
  min-height: 2.75rem;
  transition: background var(--trans);
}
.manual-indice-lista a:hover { background: var(--superficie-2); text-decoration: none; }
.manual-indice-lista span {
  flex: 0 0 1.75rem; height: 1.75rem;
  display: grid; place-items: center;
  border-radius: .5rem;
  background: var(--marca-suave); color: var(--marca-texto);
  font-size: .8125rem; font-weight: 800;
}
@media (min-width: 40rem) { .manual-indice-lista { grid-template-columns: 1fr 1fr; } }

/* --- Secciones --- */
.manual-seccion {
  margin-bottom: 3.5rem;
  scroll-margin-top: 5rem;
}
.manual-seccion:focus { outline: none; }
.manual-seccion-titulo {
  display: flex; align-items: flex-start; gap: 1rem;
  padding-bottom: 1rem;
  margin-bottom: 1.5rem;
  border-bottom: 2px solid var(--borde);
}
.manual-seccion-titulo h2 {
  font-size: 1.5rem; font-weight: 800; letter-spacing: -.02em;
  margin: 0; line-height: 1.2;
}
.manual-seccion-titulo p { margin: .25rem 0 0; color: var(--texto-suave); font-size: .9375rem; }
.manual-numero {
  flex: 0 0 2.75rem; height: 2.75rem;
  display: grid; place-items: center;
  border-radius: var(--radio);
  background: var(--marca); color: var(--sobre-marca, #fff);
  font-size: 1.25rem; font-weight: 800;
  box-shadow: var(--sombra-md);
}
.manual-subtitulo {
  font-size: 1.125rem; font-weight: 700;
  margin: 2rem 0 1rem;
}
.manual-parrafo { font-size: 1rem; line-height: 1.65; color: var(--texto); margin-bottom: 1.25rem; }
.manual-menor { font-size: .875rem; color: var(--texto-suave); line-height: 1.55; }

/* --- Los 3 pasos --- */
.manual-pasos { display: grid; grid-template-columns: 1fr; gap: 1rem; }
@media (min-width: 48rem) { .manual-pasos { grid-template-columns: repeat(3, 1fr); } }
.manual-paso {
  position: relative;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio-lg);
  padding: 1.75rem 1.25rem 1.25rem;
  box-shadow: var(--sombra-sm);
}
.manual-paso-numero {
  position: absolute; top: -1rem; left: 1.25rem;
  width: 2.25rem; height: 2.25rem;
  border-radius: 50%;
  background: var(--marca); color: var(--sobre-marca, #fff);
  display: grid; place-items: center;
  font-weight: 800; font-size: 1rem;
  border: 3px solid var(--fondo);
}
.manual-paso h3 { font-size: 1.0625rem; font-weight: 700; margin: .25rem 0 .5rem; }
.manual-paso p { margin: 0; font-size: .9375rem; line-height: 1.55; color: var(--texto-suave); }

/* --- Tarjetas de contenido --- */
.manual-tarjetas { display: grid; grid-template-columns: 1fr; gap: 1rem; }
@media (min-width: 34rem) { .manual-tarjetas { grid-template-columns: 1fr 1fr; } }
@media (min-width: 62rem) { .manual-tarjetas { grid-template-columns: repeat(3, 1fr); } }
.manual-tarjeta {
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio-lg);
  padding: 1.25rem;
  box-shadow: var(--sombra-sm);
}
.manual-tarjeta h3 { font-size: 1rem; font-weight: 700; margin: .75rem 0 .5rem; }
.manual-tarjeta p { margin: 0; font-size: .9375rem; line-height: 1.55; color: var(--texto-suave); }
.manual-icono {
  width: 2.75rem; height: 2.75rem;
  border-radius: var(--radio);
  background: var(--marca-suave); color: var(--marca-texto);
  display: grid; place-items: center;
  font-size: 1.25rem;
}
.manual-icono-grande { width: 3.5rem; height: 3.5rem; font-size: 1.625rem; }

/* --- Bloque destacado (con dibujo al lado) --- */
.manual-destacado {
  display: flex; gap: 1.25rem; align-items: flex-start; flex-wrap: wrap;
  background: var(--superficie);
  border: 1px solid var(--marca-borde);
  border-left: 4px solid var(--marca);
  border-radius: var(--radio-lg);
  padding: 1.25rem;
}
.manual-destacado > div:last-child { flex: 1; min-width: 15rem; }
.manual-destacado p { font-size: .9375rem; line-height: 1.6; }
.manual-destacado p:last-child { margin-bottom: 0; }
.manual-destacado-suave { border-left-color: var(--borde-fuerte); border-color: var(--borde); }
.manual-destacado-visual { flex: 0 0 auto; display: grid; place-items: center; }
/* Imita el botón de escanear de la barra: cuadrado redondeado, no un
   círculo flotante. El dibujo tiene que parecerse a lo que la persona
   va a ver en la pantalla, o el manual enseña algo que no existe. */
.manual-fab {
  width: 3rem; height: 3rem;
  border-radius: .75rem;
  background: var(--marca); color: var(--sobre-marca, #fff);
  display: grid; place-items: center;
  font-size: 1.375rem;
}

/* --- Listas ---
   El icono va posicionado, NO en un flex. Con `display:flex` en el <li>,
   el <strong> del principio y el texto que le sigue se vuelven dos ítems
   distintos y se acomodan en columnas: «Los montos vienen del timbre»
   quedaba en un bloque angosto y el resto de la frase empezaba a su
   derecha, a media altura. El texto de una lista tiene que fluir como
   texto. */
.manual-lista { list-style: none; padding: 0; margin: 0 0 1rem; }
.manual-lista li {
  position: relative;
  padding: .4rem 0 .4rem 1.625rem;
  font-size: .9375rem; line-height: 1.55;
}
.manual-lista li > .bi {
  position: absolute;
  left: 0; top: .55rem;
  color: var(--marca-texto); font-size: 1rem;
}
.manual-lista-suelta li { padding: .625rem 0 .625rem 1.625rem; border-bottom: 1px solid var(--borde); }
.manual-lista-suelta li > .bi { top: .775rem; }
.manual-lista-suelta li:last-child { border-bottom: none; }
.manual-lista-suelta li > .bi { color: var(--exito); }

.manual-numerada { padding-left: 1.25rem; margin: 0 0 1rem; }
.manual-numerada li { padding: .3rem 0; font-size: .9375rem; line-height: 1.55; }

/* --- Notas / avisos --- */
.manual-nota {
  display: flex; gap: .875rem; align-items: flex-start;
  background: var(--info-suave);
  border: 1px solid color-mix(in srgb, var(--info) 30%, transparent);
  border-radius: var(--radio);
  padding: 1rem 1.125rem;
  margin: 1.25rem 0;
  font-size: .9375rem; line-height: 1.6;
}
.manual-nota > .bi { font-size: 1.125rem; color: var(--info); flex-shrink: 0; margin-top: .1rem; }
.manual-nota-truco { background: var(--alerta-suave); border-color: color-mix(in srgb, var(--alerta) 30%, transparent); }
.manual-nota-truco > .bi { color: var(--alerta); }
.manual-nota-ojo { background: var(--peligro-suave); border-color: color-mix(in srgb, var(--peligro) 30%, transparent); }
.manual-nota-ojo > .bi { color: var(--peligro); }

/* --- Métodos para cargar --- */
.manual-metodo {
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio-lg);
  padding: 1.5rem 1.25rem;
  margin-bottom: 1.25rem;
  box-shadow: var(--sombra-sm);
}
.manual-metodo-estrella { border-color: var(--marca-borde); box-shadow: var(--sombra-md); }
.manual-metodo-cabecera { display: flex; gap: 1rem; align-items: center; margin-bottom: 1rem; }
.manual-metodo-cabecera h3 { font-size: 1.1875rem; font-weight: 800; margin: .25rem 0 0; letter-spacing: -.01em; }
.manual-metodo-icono {
  flex: 0 0 3rem; height: 3rem;
  border-radius: var(--radio);
  background: var(--marca); color: var(--sobre-marca, #fff);
  display: grid; place-items: center;
  font-size: 1.375rem;
}
.manual-metodo p { font-size: .9375rem; line-height: 1.65; }
.manual-insignia {
  display: inline-block;
  font-size: .6875rem; font-weight: 800;
  text-transform: uppercase; letter-spacing: .06em;
  padding: .15rem .5rem;
  border-radius: 1rem;
  background: var(--marca-suave); color: var(--marca-texto);
}
.manual-insignia-gris { background: var(--superficie-2); color: var(--texto-suave); border: 1px solid var(--borde); }

/* --- Dibujo del escáner --- */
.manual-escaner {
  background: #0b1120;
  border-radius: var(--radio);
  padding: 1rem;
  margin: 1.25rem 0;
}
.manual-escaner-visor {
  position: relative;
  height: 7rem;
  display: grid; place-items: center;
  background: #1a2438;
  border-radius: var(--radio-sm);
  overflow: hidden;
}
.manual-escaner-codigo {
  display: flex; align-items: center; gap: 2px;
  height: 55%; width: 60%;
}
.manual-escaner-codigo span { flex: 1; background: #cbd5e1; border-radius: 1px; }
.manual-escaner-mira {
  position: absolute;
  width: 68%; height: 68%;
  border: 2px solid #fff;
  border-radius: .375rem;
  box-shadow: 0 0 0 9999px rgba(2, 8, 23, .45);
  animation: manual-mira 2.4s ease-in-out infinite;
}
@keyframes manual-mira {
  0%, 100% { width: 78%; height: 78%; opacity: .75; }
  50%      { width: 64%; height: 62%; opacity: 1; }
}
.manual-escaner-pie {
  display: flex; align-items: center; gap: .625rem;
  margin-top: .75rem;
  color: #b8c4d6; font-size: .8125rem;
}
.manual-escaner-boton {
  width: 1.875rem; height: 1.875rem;
  border-radius: 50%;
  background: rgba(255, 255, 255, .15);
  color: #fbbf24;
  display: grid; place-items: center;
  flex-shrink: 0;
}

/* --- Campos explicados --- */
.manual-campos { display: flex; flex-direction: column; gap: 1rem; }
.manual-campo {
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  padding: 1.125rem 1.25rem;
}
.manual-campo-clave { border-left: 4px solid var(--marca); }
.manual-campo-nombre {
  font-weight: 800; font-size: 1rem;
  margin-bottom: .5rem;
  display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
}
.manual-campo p { margin: 0 0 .625rem; font-size: .9375rem; line-height: 1.6; color: var(--texto-suave); }
.manual-campo p:last-child { margin-bottom: 0; }
.manual-campo code {
  background: var(--superficie-2); border: 1px solid var(--borde);
  border-radius: .3rem; padding: .05rem .35rem;
  font-size: .875rem; color: var(--texto);
}
.manual-opcional {
  font-size: .6875rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .05em;
  /* --texto-tenue da 2.6:1 y este texto es chico: no llega al mínimo. */
  color: var(--texto-suave);
  border: 1px solid var(--borde); border-radius: 1rem; padding: .1rem .45rem;
}
.manual-campo-ojo {
  background: var(--alerta-suave);
  border-radius: var(--radio-sm);
  padding: .625rem .75rem;
  font-size: .875rem; line-height: 1.5;
  color: var(--texto);
}

/* --- Ejemplos bien / mal --- */
.manual-ejemplos { display: grid; grid-template-columns: 1fr; gap: .625rem; margin: .875rem 0; }
@media (min-width: 40rem) { .manual-ejemplos { grid-template-columns: 1fr 1fr; } }
.manual-ejemplo {
  border-radius: var(--radio-sm);
  padding: .75rem .875rem;
  font-size: .9375rem; line-height: 1.5;
}
.manual-ejemplo span {
  display: flex; align-items: center; gap: .375rem;
  font-size: .75rem; font-weight: 800; text-transform: uppercase;
  letter-spacing: .05em; margin-bottom: .375rem;
}
/* Las etiquetas «Así no / Así sí» van mezcladas con --texto: el rojo y el
   verde puros sobre su propio fondo suave se quedaban en 3.5–4.4:1, y son
   letras chicas. Mezclar con --texto oscurece en tema claro y aclara en
   oscuro, así que el color sigue diciendo lo suyo y además se lee. */
.manual-ejemplo-mal { background: var(--peligro-suave); color: var(--texto); }
.manual-ejemplo-mal span { color: color-mix(in srgb, var(--peligro) 62%, var(--texto)); }
.manual-ejemplo-bien { background: var(--exito-suave); color: var(--texto); }
.manual-ejemplo-bien span { color: color-mix(in srgb, var(--exito) 62%, var(--texto)); }

/* --- Interruptores explicados --- */
.manual-interruptores { display: flex; flex-direction: column; gap: 1rem; }
.manual-interruptor {
  display: flex; gap: 1rem; align-items: flex-start;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  padding: 1.125rem 1.25rem;
}
.manual-interruptor p { margin: 0 0 .5rem; font-size: .9375rem; line-height: 1.6; color: var(--texto-suave); }
.manual-interruptor p:last-child { margin-bottom: 0; }
.manual-interruptor-visual {
  flex: 0 0 2.75rem; height: 1.625rem;
  border-radius: 1rem;
  background: var(--marca);
  position: relative;
  margin-top: .15rem;
}
.manual-interruptor-visual span {
  position: absolute; top: .1875rem; right: .1875rem;
  width: 1.25rem; height: 1.25rem;
  border-radius: 50%; background: #fff;
  box-shadow: var(--sombra-sm);
}

/* --- Camino del informe --- */
.manual-camino { display: flex; flex-direction: column; gap: 0; margin: 1.5rem 0; }
.manual-etapa {
  display: grid;
  grid-template-columns: 2.75rem 1fr;
  gap: 1rem;
  padding-bottom: 1.5rem;
  position: relative;
}
/* El punto ocupa la primera columna; el título y el texto van los DOS en
   la segunda. Sin esto, la rejilla colocaba el <p> en la fila siguiente
   PRIMERA columna —2.75 rem de ancho— y la descripción de cada etapa
   salía a palabra por línea, con la línea del tiempo cruzándola. */
.manual-etapa > .manual-etapa-punto { grid-column: 1; grid-row: 1 / span 2; }
.manual-etapa > h3,
.manual-etapa > p { grid-column: 2; }
/* La línea que une las etapas: se dibuja detrás de los puntos. */
.manual-etapa::before {
  content: '';
  position: absolute;
  left: 1.3125rem; top: 2.75rem; bottom: 0;
  width: 2px;
  background: var(--borde);
}
.manual-etapa:last-child { padding-bottom: 0; }
.manual-etapa:last-child::before { display: none; }
.manual-etapa-punto {
  width: 2.75rem; height: 2.75rem;
  border-radius: 50%;
  display: grid; place-items: center;
  font-size: 1.125rem;
  border: 2px solid var(--borde);
  background: var(--superficie);
  color: var(--texto-suave);
  position: relative; z-index: 1;
}
.manual-etapa h3 { font-size: 1rem; font-weight: 700; margin: .35rem 0 .25rem; }
.manual-etapa p { margin: 0; font-size: .9375rem; line-height: 1.55; color: var(--texto-suave); }
.manual-etapa-borrador .manual-etapa-punto { border-color: var(--borde-fuerte); }
.manual-etapa-enviado  .manual-etapa-punto { border-color: var(--info);    color: var(--info); }
.manual-etapa-revision .manual-etapa-punto { border-color: var(--alerta);  color: var(--alerta); }
.manual-etapa-aprobado .manual-etapa-punto { border-color: var(--exito);   color: var(--exito); }
.manual-etapa-pagado   .manual-etapa-punto { background: var(--exito); border-color: var(--exito); color: #fff; }

/* --- Fórmula del fondo --- */
.manual-formula {
  display: flex; align-items: stretch; justify-content: center;
  gap: .625rem; flex-wrap: wrap;
  margin: 1.5rem 0;
}
.manual-formula-item {
  flex: 1 1 8rem;
  text-align: center;
  padding: 1rem .75rem;
  border-radius: var(--radio);
  border: 1px solid var(--borde);
  background: var(--superficie);
}
.manual-formula-item span { display: block; font-size: .8125rem; color: var(--texto-suave); margin-bottom: .35rem; }
.manual-formula-item strong { font-size: .9375rem; font-weight: 800; }
.manual-formula-mas   { border-color: color-mix(in srgb, var(--exito) 40%, transparent); }
.manual-formula-mas   strong { color: color-mix(in srgb, var(--exito) 62%, var(--texto)); }
.manual-formula-menos { border-color: color-mix(in srgb, var(--peligro) 40%, transparent); }
.manual-formula-menos strong { color: color-mix(in srgb, var(--peligro) 62%, var(--texto)); }
.manual-formula-igual { border-color: var(--marca-borde); background: var(--marca-suave); }
.manual-formula-igual strong { color: var(--marca-texto); }
.manual-formula-signo {
  display: grid; place-items: center;
  font-size: 1.5rem; font-weight: 800; color: var(--texto-tenue);
  flex: 0 0 auto;
}

/* --- Preguntas frecuentes --- */
.manual-preguntas { display: flex; flex-direction: column; gap: .625rem; }
.manual-pregunta {
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  overflow: hidden;
}
.manual-pregunta summary {
  cursor: pointer;
  list-style: none;
  padding: 1rem 1.125rem;
  font-weight: 700; font-size: .9375rem;
  display: flex; align-items: center; gap: .75rem;
  min-height: 3.25rem;
}
.manual-pregunta summary::-webkit-details-marker { display: none; }
/* La flecha se dibuja con CSS y gira al abrir: sin ella no se ve que
   la pregunta se puede desplegar. */
.manual-pregunta summary::before {
  content: '';
  flex: 0 0 .5rem; height: .5rem;
  border-right: 2px solid var(--marca);
  border-bottom: 2px solid var(--marca);
  transform: rotate(-45deg);
  transition: transform var(--trans);
  margin-left: .25rem;
}
.manual-pregunta[open] summary::before { transform: rotate(45deg); }
.manual-pregunta summary:hover { background: var(--superficie-2); }
.manual-pregunta > div { padding: 0 1.125rem 1.125rem 2.625rem; }
.manual-pregunta p { font-size: .9375rem; line-height: 1.6; color: var(--texto-suave); margin: 0 0 .75rem; }
.manual-pregunta p:last-child { margin-bottom: 0; }

/* --- Reglas de oro --- */
.manual-reglas { display: grid; grid-template-columns: 1fr; gap: .75rem; }
@media (min-width: 48rem) { .manual-reglas { grid-template-columns: 1fr 1fr; } }
.manual-regla {
  display: flex; gap: .875rem; align-items: flex-start;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  padding: 1rem 1.125rem;
  font-size: .9375rem; line-height: 1.55;
}
.manual-regla > .bi { font-size: 1.375rem; color: var(--marca); flex-shrink: 0; }
.manual-regla strong { display: block; margin-bottom: .15rem; }

/* --- La entrada al manual, en el menú de la cuenta --- */
.dropdown-item-manual {
  display: flex; align-items: center;
  padding-top: .625rem; padding-bottom: .625rem;
  background: var(--marca-suave);
  color: var(--marca-texto);
  font-weight: 700;
}
.dropdown-item-manual small {
  display: block;
  font-weight: 500; font-size: .75rem;
  color: var(--texto-suave);
}
.dropdown-item-manual > .bi { font-size: 1.125rem; }
.dropdown-item-manual:hover,
.dropdown-item-manual:focus {
  background: var(--marca);
  color: var(--sobre-marca, #fff);
}
.dropdown-item-manual:hover small,
.dropdown-item-manual:focus small { color: inherit; opacity: .85; }

/* --- Cierre --- */
.manual-cierre {
  display: flex; gap: 1.25rem; align-items: flex-start; flex-wrap: wrap;
  margin-top: 2rem;
  padding: 1.75rem 1.5rem;
  border-radius: var(--radio-lg);
  background: var(--exito-suave);
  border: 1px solid color-mix(in srgb, var(--exito) 35%, transparent);
}
.manual-cierre > .bi { font-size: 2rem; color: var(--exito); }
.manual-cierre h3 { font-size: 1.25rem; font-weight: 800; margin: 0 0 .5rem; }
.manual-cierre p { font-size: .9375rem; line-height: 1.6; color: var(--texto-suave); margin: 0 0 1rem; max-width: 34rem; }
.manual-pie {
  text-align: center;
  font-size: .875rem;
  color: var(--texto-suave);
  margin: 2rem 0 1rem;
}

@media (prefers-reduced-motion: reduce) {
  .manual-escaner-mira { animation: none; }
}

/* ---------------------------------------------------------------------
   20. Impresión
   --------------------------------------------------------------------- */
/* El informe se imprime o se guarda como PDF para contabilidad. El
   navegador ya sabe hacer PDF: no hace falta una librería. */
@media print {
  /* En papel SIEMPRE se imprime claro, se haya elegido lo que se haya
     elegido en pantalla. No es una preferencia: es tinta.

     Hasta ahora esto salía bien por casualidad. El oscuro vivía sólo dentro
     de `@media (prefers-color-scheme: dark)`, que al imprimir no encaja
     porque el navegador fuerza el esquema claro. Un atributo en <html> sí
     encaja, y a la impresora le da igual: el informe que va a contabilidad
     habría salido con texto #f1f5f9 sobre papel blanco. O sea, en blanco.

     El `body { color: #000 }` de abajo no bastaba: hay 31 reglas con
     `color: var(--texto)` —.tabla td, .lista-item, .stat-valor— que le
     ganan por especificidad. Hay que reponer los TOKENS, no el body. Y el
     manual y la vista del informe se imprimen desde el layout normal, no
     desde el de impresión, así que pinear ese layout no habría alcanzado.

     Los tres selectores son a propósito, y no adorno: un `:root` pelado
     pesa (0,1,0) y PIERDE contra los dos que ponen el oscuro, que pesan
     (0,2,0). Repitiéndolos aquí se empata el peso y gana éste por venir
     después en el archivo. Con uno solo, el papel salía en blanco igual. */
  :root,
  :root[data-tema="oscuro"],
  :root:not([data-tema="claro"]) {
    --fondo:        #f1f5f9;
    --superficie:   #ffffff;
    --superficie-2: #f8fafc;
    --borde:        #e2e8f0;
    --borde-fuerte: #cbd5e1;
    --texto:        #0f172a;
    --texto-suave:  #475569;
    --texto-tenue:  #616e82;
    --marca-suave:  color-mix(in srgb, var(--marca) 10%, white);
    --marca-borde:  color-mix(in srgb, var(--marca) 25%, white);
    --exito-suave:   #ecfdf5;
    --peligro-suave: #fef2f2;
    --alerta-suave:  #fffbeb;
    --info-suave:    #f0f9ff;
    /* También las sombras: las del tema oscuro son negros al 40-60% y en
       papel salen como halos grises alrededor de cada tarjeta. */
    --sombra-sm: 0 1px 2px rgba(15, 23, 42, .06);
    --sombra:    0 1px 3px rgba(15, 23, 42, .08), 0 1px 2px rgba(15, 23, 42, .04);
    --sombra-md: 0 4px 12px rgba(15, 23, 42, .08), 0 2px 4px rgba(15, 23, 42, .04);
    --sombra-lg: 0 12px 32px rgba(15, 23, 42, .12), 0 4px 8px rgba(15, 23, 42, .06);
    --bs-body-bg: var(--fondo);
    --bs-body-color: var(--texto);
    color-scheme: light;
  }

  .cabecera, .barra-inferior, .acciones-fijas,
  .no-imprimir, .avisos-flotantes { display: none !important; }

  body {
    background: #fff;
    color: #000;
    padding: 0;
    font-size: 11pt;
  }

  .contenedor { max-width: none; padding: 0; }

  .tarjeta {
    border: 1px solid #ccc;
    box-shadow: none;
    break-inside: avoid;
  }

  .tabla { font-size: 9pt; }
  .tabla th { background: #f0f0f0 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }

  /* Que se vea a dónde apunta cada enlace en el papel. */
  a[href^="http"]::after {
    content: " (" attr(href) ")";
    font-size: 8pt;
    color: #666;
  }

  .pagina-nueva { break-before: page; }

  /* --- El manual en papel ---
     Se imprime más de lo que uno cree: queda pegado en el pizarrón de la
     oficina o en la carpeta del vehículo. Los degradados y las sombras se
     van (gastan tinta y en blanco y negro ensucian), las preguntas
     frecuentes se abren todas (en papel no hay dónde tocar) y ninguna
     tarjeta se parte entre dos hojas. */
  .manual-portada {
    background: none !important;
    color: #000;
    box-shadow: none;
    border: 2px solid #000;
    padding: 1rem;
  }
  .manual-portada h1, .manual-portada p { color: #000 !important; }
  .manual-etiqueta { border: 1px solid #000; background: none; }
  .manual-portada-botones, .manual-telefono, .manual-indice { display: none !important; }

  .manual-seccion { break-inside: auto; margin-bottom: 1.5rem; }
  .manual-seccion-titulo { break-after: avoid; }
  .manual-paso, .manual-tarjeta, .manual-campo, .manual-metodo,
  .manual-regla, .manual-nota, .manual-etapa, .manual-pregunta {
    break-inside: avoid;
    box-shadow: none;
  }

  /* En papel no se puede desplegar nada: va todo abierto. */
  .manual-pregunta > div { display: block !important; }
  .manual-pregunta summary::before { display: none; }

  .manual-escaner { background: #fff; border: 1px solid #999; }
  .manual-escaner-visor { background: #eee; }
  .manual-escaner-mira { box-shadow: none; border-color: #000; animation: none; }
  .manual-escaner-pie { color: #333; }

  .manual-numero, .manual-paso-numero, .manual-metodo-icono, .manual-fab {
    background: #000 !important; color: #fff !important;
    -webkit-print-color-adjust: exact; print-color-adjust: exact;
  }

  /* El manual no lleva enlaces externos: la URL detrás de cada ancla
     interna sólo ensucia la hoja. */
  .manual-seccion a[href^="http"]::after,
  .manual-indice a[href]::after { content: ""; }
}

/* ---------------------------------------------------------------------
   17b. Sugerencias del lector · elegir con un toque
   ---------------------------------------------------------------------
   Cuando el OCR no está seguro (dos montos posibles, dos RUT, varios
   nombres), en vez de adivinar se ofrecen las opciones bajo el campo y
   la persona toca la correcta. Un toque es más rápido que teclear, y
   con plata real es MUCHO más seguro que una adivinanza. */
.sugerencias {
  display: flex;
  flex-wrap: wrap;
  gap: .375rem;
  margin-top: .5rem;
  align-items: center;
}

.sugerencias-titulo {
  width: 100%;
  font-size: .75rem;
  font-weight: 700;
  color: var(--marca-texto);
  display: flex;
  align-items: center;
  gap: .35rem;
  margin-bottom: .1rem;
}

.sugerencia {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  gap: .05rem;
  padding: .45rem .7rem;
  min-height: 2.75rem;           /* zona táctil cómoda con guantes */
  border: 1px solid var(--marca-borde);
  border-radius: .625rem;
  background: var(--marca-suave);
  color: var(--texto);
  font-size: .875rem;
  font-weight: 650;
  line-height: 1.2;
  cursor: pointer;
  text-align: left;
  max-width: 100%;
  transition: transform var(--trans), background var(--trans);
}

.sugerencia:hover { background: color-mix(in srgb, var(--marca) 20%, var(--superficie)); }
.sugerencia:active { transform: scale(.97); }

.sugerencia .por-que {
  font-size: .6875rem;
  font-weight: 500;
  color: var(--texto-suave);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}

/* La opción que el sistema eligió sola: se marca para que se note cuál
   está puesta en el campo ahora mismo. */
.sugerencia.puesta {
  background: color-mix(in srgb, var(--exito) 16%, var(--superficie));
  border-color: color-mix(in srgb, var(--exito) 45%, transparent);
}

.sugerencia-larga { max-width: 100%; }
.sugerencia-larga .valor {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 17rem;
}

/* ---------------------------------------------------------------------
   18. Correcciones de modales y capas (auditoría visual)
   --------------------------------------------------------------------- */

/* TODOS los modales del sistema envuelven header/body/footer en un <form>
   dentro de .modal-content. Eso rompe el scroll de modal-dialog-scrollable:
   Bootstrap arma el scroll con flex (content flex -> body flex:1 con
   overflow), y el form interpuesto corta esa cadena — el body crecía a su
   altura natural, el content lo recortaba con overflow:hidden y los campos
   de abajo quedaban INALCANZABLES (era el bug de "no puedo hacer scroll en
   la categoría"). Replicar el layout flex en el form restaura el scroll. */
.modal-content > form {
  display: flex;
  flex-direction: column;
  max-height: 100%;
  min-height: 0;
  overflow: hidden;
}

/* La lista de sugerencias del proveedor se dibuja DENTRO de la tarjeta del
   formulario, y .tarjeta recorta con overflow:hidden (por los bordes
   redondeados): la lista quedaba cortada e intocable. Sólo mientras la
   lista existe (se crea al teclear y se destruye al elegir), la tarjeta
   deja de recortar. */
.tarjeta:has(.autocompletar) {
  overflow: visible;
}

/* La X de cerrar de los modales de Bootstrap es un SVG NEGRO fijo: en modo
   oscuro desaparecía contra el fondo. (Bootstrap lo resuelve con
   data-bs-theme, que este sistema no usa: se invierte a mano.) */
@media (prefers-color-scheme: dark) {
  :root:not([data-tema="claro"]) .btn-close {
    filter: invert(1) grayscale(100%) brightness(150%);
  }
}
:root[data-tema="oscuro"] .btn-close {
  filter: invert(1) grayscale(100%) brightness(150%);
}
