/* ============================================================
   estilo.css — overrides y estilos propios de Factoraje
   NO modificar portal.css. Todos los cambios van aquí.
   ============================================================ */

/* ─────────────────────────────────────────────────────────────────
   PALETA DEL PROYECTO
   --------------------------------------------------------------
   Todo color institucional / de marca vive en variables CSS
   declaradas en :root. Si querés cambiar el azul Monex en toda
   la app, editá SOLO estas tres líneas.

   Para usar el color en cualquier regla:
     color: var(--color-marca);
     background: var(--color-marca-suave);
   ─────────────────────────────────────────────────────────────── */
:root {
  /* Azul Monex — sidebar lateral, hamburguesa, links activos del nav */
  --color-marca: #0095ff;
  --color-marca-oscuro: #007acc;
  --color-marca-suave: #e1f1ff;
  /* Tono del pill (más azul) que aparece al hover sobre un item activo */
  --color-marca-suave-hover: #d0e8ff;

  /* Azul Delta — acento de filas en tablas y de pestañas activas */
  --color-acento-fila: #4472c4;
  --color-acento-fila-suave: #f0f2ff;

  /* Gris suave para hovers sobre items inactivos */
  --color-hover-gris: #f0f1f4;

  /* Semáforo de estatus (timeline de pasos + donut de progreso).
     Dos escalas del MISMO significado (verde=ok, ámbar=advertencia,
     rojo=fallo, gris=vacío) con distinta luminosidad según el trazo:
       -500 → donut de progreso (.fa-prog-circulo, trazos finos, pide
              tono más vibrante) — mismos hex que --prog-color-*.
       -600 → círculo del timeline (28px) y conector (trazo grueso,
              pide tono más profundo para texto blanco legible) —
              mismos hex que hoy están hardcoded en
              .fa-timeline-circulo--sem-* y el conector base.
     Ningún tono cambia acá: son los mismos hex ya usados en el
     proyecto, solo centralizados en variables. */
  --fa-sem-verde-500: #22c55e;
  --fa-sem-rojo-500: #ef4444;
  --fa-sem-ambar-500: #f59e0b;
  --fa-sem-gris-500: #e2e5ea;

  --fa-sem-verde-600: #16a34a;
  --fa-sem-rojo-600: #dc2626;
  --fa-sem-ambar-600: #d97706;
  --fa-sem-gris-600: #e7e9ed;
}

/* ── Placeholder en campos dinámicos ── */
.catalogo-placeholder::placeholder {
  color: #b0b0b0;
  opacity: 1;
}

/* ── Fondo blanco para páginas específicas ── */
.fa-pagina-blanca {
  background-color: #ffffff;
}
/* Aplica al wrapper completo cuando el módulo lo requiere */
.fa-pagina-blanca .app-content {
  background-color: #ffffff;
}

/* ── Botones de acción financieros ── */
.fa-btn-accion {
  /* Navy profundo = mismo tono del encabezado de la tabla (#012e92).
     Texto blanco a 11.6:1, muy por encima de WCAG AA. */
  background-color: #012e92;
  color: #ffffff;
  border: none;
  border-radius: 8px;
  padding: 0.55rem 1.4rem;
  font-size: 0.875rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  cursor: pointer;
  transition:
    background-color 0.18s ease,
    box-shadow 0.18s ease;
}

/* Botón-enlace: el mismo control pero como <a>, para una acción que en realidad
   es navegar (p. ej. "Calcular pago requerido" → /pagos/pago-requerido/). Un <a>
   es inline, así que sin inline-flex el padding vertical no empuja la caja de
   línea y el botón se ve aplastado; y hereda el subrayado del enlace. */
a.fa-btn-accion {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
}

.fa-btn-accion:hover {
  background-color: #023ab5;
  color: #ffffff;
  box-shadow: 0 2px 8px rgba(1, 46, 146, 0.3);
}

.fa-btn-accion:active {
  background-color: #011e63;
  color: #ffffff;
}

.fa-btn-accion:focus {
  outline: none;
  box-shadow: 0 0 0 3px rgba(1, 46, 146, 0.3);
}

/* Variante secundaria — azul cian de la paleta (columna "Contraste" de la
   familia cian: blanco a 4.9:1, sobre AA). Distingue una acción de proceso
   (Sincronizar Datos) del navy de la acción primaria sin salirse del rango
   de marca. */
.fa-btn-accion--cian {
  background-color: #0f76aa;
}

.fa-btn-accion--cian:hover {
  background-color: #1189c4;
  box-shadow: 0 2px 8px rgba(15, 118, 170, 0.3);
}

.fa-btn-accion--cian:active {
  background-color: #0b5c86;
}

.fa-btn-accion--cian:focus {
  box-shadow: 0 0 0 3px rgba(15, 118, 170, 0.3);
}

/* Botón deshabilitado mientras corre el proceso que disparó. */
.fa-btn-accion:disabled {
  opacity: 0.55;
  cursor: progress;
}

/* Deshabilitado porque la acción YA NO SE PERMITE (regla de negocio: el
   «Disponer» de un grupo que ya se dispuso), no porque haya algo en vuelo. El
   cursor `progress` de arriba prometería una espera que nunca termina. */
.fa-btn-accion--inactivo:disabled {
  cursor: not-allowed;
}

/* ── Barra de progreso dentro del SweetAlert ──
   Compartida por la carga de insumos (/admin/insumos) y por Sincronizar Datos
   (/disposiciones); vive acá y no en modulos/insumos.css porque estilo.css es
   el único CSS que cargan las dos páginas. */
.fa-swal-progress {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin-top: 0.5rem;
}

.fa-swal-progress-track {
  height: 10px;
  background: #e7e9ed;
  border-radius: 999px;
  overflow: hidden;
}

.fa-swal-progress-bar {
  height: 100%;
  background: linear-gradient(90deg, #4472c4 0%, #5e8bd5 100%);
  border-radius: 999px;
  transition: width 0.25s ease-out;
}

.fa-swal-progress-msg {
  margin: 0;
  font-size: 0.85rem;
  color: #4a4f57;
}

/* ── Título de sección ── */
.fa-seccion-titulo {
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: 0;
  color: #252930;
  margin-bottom: 0;
}

/* ── Encabezado de módulo (CANÓNICO) ───────────────────────────────
   Un solo encabezado para TODOS los módulos: título a la izquierda,
   acciones a la derecha, en la misma fila. Sin barra, sin sticky: así
   al navegar entre módulos solo cambia el contenido, no el encabezado.
   Única excepción deliberada: /home (Vista general), que conserva su
   propio título suelto.
   Lo usan: clientes · admin · dashboards · disposiciones · pagos ·
   base de operaciones. */
.fa-encabezado-modulo {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.5rem;
  /* Alto FIJO de la fila, tenga o no botones de acción. Sin esto el
     encabezado colapsa al alto del <h1> en los módulos sin botón
     (Dashboards, Base de operaciones) y el título + las pestañas suben
     ~12px respecto de Clientes/Admin: al navegar se nota el salto.
     El valor es el alto natural de .fa-btn-accion--mas, derivado de sus
     propios tokens: padding vertical (0.4rem × 2) + el icono "+", que es
     la línea más alta del botón (1.15rem con line-height 1). Si cambia
     el padding o el icono de ese botón, actualizar este calc. */
  min-height: calc(0.8rem + 1.15rem);
}

.fa-encabezado-modulo .fa-encabezado-acciones {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 0;
  margin-left: auto;
}

/* ── Barra de botones de acción (legacy, otras páginas) ── */
.fa-barra-acciones {
  display: flex;
  gap: 0.75rem;
  margin-bottom: 1.5rem;
}

/* ── Modifier para el botón "+ Entidad" en /clientes ───────────────
   Hereda todo de .fa-btn-accion (color, border, hover, focus, etc.)
   y solo añade el layout flex para alinear icono + texto. */
.fa-btn-accion--mas {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.4rem 1rem;
  font-size: 0.85rem;
  line-height: 1;
}

.fa-btn-accion--mas .fa-btn-mas-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1.15rem;
  font-weight: 600;
  line-height: 1;
  position: relative;
  top: -1px; /* compensa el peso visual del + para alinearlo con la x-height */
}

/* ══════════════════════════════════════════════════════════════
   SUB-NAVEGACIÓN (pestañas horizontales para sub-rutas)
   ──────────────────────────────────────────────────────────────
   USA el azul Delta de las tablas (--color-acento-fila), NO el azul
   Monex del sidebar lateral. Las dos navegaciones son conceptualmente
   independientes y pueden cambiar de color por separado.
     - Inactivo  = texto negro
     - Hover     = velo gris translucido
     - Activo    = texto azul Delta + subrayado azul en la línea
     - Activo+hover = velo azul Delta translucido
   Usado en /clientes/{compradores,vendedores,cofactores}.
   ══════════════════════════════════════════════════════════════ */
.fa-subnav {
  display: flex;
  gap: 0.25rem;
  border-bottom: 1px solid #e7e9ed;
  margin-bottom: 1rem;
  /* Padding vertical para que el rectángulo gris del hover quede
	   "desconectado" del borde inferior del contenedor.
	   margin-left negativo: compensa el padding-left del primer item
	   para que arranque alineado con el título "Clientes". */
  padding: 0.3rem 0;
  margin-left: -0.75rem;
}

.fa-subnav-item {
  position: relative;
  padding: 0.35rem 0.75rem;
  font-size: 0.85rem;
  font-weight: 600;
  color: #252930; /* texto negro en reposo y en hover, no cambia */
  text-decoration: none;
  border-radius: 6px; /* todas las esquinas — look de botón */
  transition: background-color 0.15s ease;
}

/* Hover sobre los inactivos: solo el velo gris. El color del texto
   NO cambia — sobrescribimos el a:hover verde de portal.css. */
.fa-subnav-item:hover {
  color: #252930;
  background-color: rgba(0, 0, 0, 0.05);
  text-decoration: none;
}

/* Activo en reposo: texto azul Delta + subrayado azul Delta
   (vía ::after). Sin fondo. */
.fa-subnav-item.activo {
  color: var(--color-acento-fila);
}

.fa-subnav-item.activo::after {
  content: "";
  position: absolute;
  left: 0.75rem;
  right: 0.75rem;
  /* baja hasta solaparse con el border-bottom de .fa-subnav.
	   bottom: -(padding-vertical del .fa-subnav + 1px del border) */
  bottom: calc(-0.3rem - 1px);
  height: 2px;
  background-color: var(--color-acento-fila);
  border-radius: 2px 2px 0 0;
}

/* Activo + hover: velo azul Delta muy ligero (5% de opacidad). */
.fa-subnav-item.activo:hover {
  color: var(--color-acento-fila);
  background-color: rgba(68, 114, 196, 0.05);
}

/* ─────────────────────────────────────────────────────────────
   Módulo tabla viewport-fit
   ----------------------------------------------------------------
   Layout estándar para páginas tipo /disposiciones y /clientes:
   - Fondo blanco
   - Viewport fijo: la página NO scrollea, solo la tabla
   - Título arriba, botones a la derecha en fila separada
   - Footer pegado al fondo del viewport

   Uso: añadir clase .fa-modulo-tabla al <body> o al .app desde el
   template hijo, o usar <body class="fa-modulo-tabla">.
   ───────────────────────────────────────────────────────────── */
/* OJO: en el body convive class="app fa-modulo-tabla" (ambas en el
   mismo elemento). El selector va concatenado SIN espacio. */
body.fa-modulo-tabla.app {
  background-color: #ffffff !important;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

html:has(body.fa-modulo-tabla) {
  background-color: #ffffff;
}

/* Facturas: la tabla scrollea INTERNAMENTE con su thead pegado arriba
   (estilo "freeze panes"). El header del módulo, los KPIs y los filtros
   quedan fijos por encima. */
.fa-tabla-card:has(#tabla-disposiciones) .fa-tabla-wrapper--scroll {
  /* Mismo alto que /base-operaciones (antes 560px fijo). */
  max-height: calc(100vh - 210px);
  /* Scroll horizontal cuando la tabla no cabe: `#tabla-disposiciones` tiene
     un `min-width` y, por debajo de ese ancho, se desplaza en vez de seguir
     truncando columnas. */
  overflow-x: auto;
  /* Reserva el canal del scrollbar VERTICAL para que no le robe ancho a la
	   tabla (width:100%) y reaparezca un scroll horizontal fantasma con una
	   franja blanca al final (el ancho del scrollbar). Con el canal reservado
	   la tabla calcula su 100% sobre el ancho ya descontado → sin desborde. */
  scrollbar-gutter: stable;
  /* Firefox: barra fina y discreta en vez de la gruesa nativa — roba mucho
	   menos ancho (achica/elimina el fantasma) SIN ocultar el cue de "hay más
	   filas". Ignorado por Chrome/Edge, que usan ::-webkit-scrollbar. */
  scrollbar-width: thin;
  scrollbar-color: #c8cdd6 transparent;
}

.fa-modulo-tabla .app-wrapper,
.fa-modulo-tabla .app-content,
.fa-modulo-tabla .app-content > .container-xl {
  background-color: #ffffff;
}

.fa-modulo-tabla .app-wrapper {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
}

.fa-modulo-tabla .app-wrapper > br {
  display: none;
}

/* ── Facturas: scroll de PÁGINA en el área de contenido ──
   El shell de fa-modulo-tabla deja el <body> con overflow:hidden (no scrollea)
   para que el scroll viva adentro. En facturas movemos ese scroll a
   .app-content: así la página entera scrollea verticalmente. Solo afecta a
   facturas (clientes sigue con el scroll interno de su tabla). */
/* Sin altura definida en <html>, el body (height:100%) se resuelve a 'auto'
   y CRECE con el contenido: entonces el flex no acota a .app-content y, peor,
   el overflow:hidden del body (propagado al viewport) recorta lo que sobra y
   NADA scrollea. Fijando html a 100% el body queda exacto en 100vh, la cadena
   flex acota .app-content y su overflow-y:auto sí scrollea. */
html:has(body.fa-modulo-facturas) {
  height: 100%;
}

.fa-modulo-facturas .app-content {
  flex: 0 0 auto;
  /* min-height: 100% hace que el contenido llene al menos el alto visible,
	   así el footer (que va inmediatamente después) queda JUSTO debajo del
	   fold: no se ve al cargar y aparece recién cuando bajás el scroll. */
  min-height: 100%;
  overflow: visible;
  /* Sin padding lateral: el contenido lo recupera con márgenes propios de
	   1.5rem (abajo). El padding-top de Bootstrap (p-lg-4) se DEJA intacto:
	   es el que da al encabezado el mismo aire superior que en clientes/admin. */
  padding-left: 0 !important;
  padding-right: 0 !important;
}

/* El scroll de página vive en app-wrapper (no en app-content), así el footer
   —que es hijo de app-wrapper— fluye al FINAL del contenido en vez de quedar
   pegado siempre al borde inferior del viewport. */
.fa-modulo-facturas .app-wrapper {
  overflow-y: auto;
  overflow-x: hidden;
}
.fa-modulo-facturas .app-footer {
  margin-top: 0;
}

/* El container deja de limitar el ancho / centrar: ocupa toda el área. */
.fa-modulo-facturas .app-content > .container-xl {
  max-width: 100%;
  padding-left: 0;
  padding-right: 0;
}

/* Gutter lateral (1.5rem) uniforme: el encabezado y las demás secciones quedan
   alineados entre sí y con el de clientes/admin (que lo toma del container-xl). */
.fa-modulo-facturas .fa-encabezado-modulo,
.fa-modulo-facturas .fa-resumen-cards,
.fa-modulo-facturas .fa-tabla-card,
.fa-modulo-facturas .fa-hub-rejilla {
  margin-left: 1.5rem;
  margin-right: 1.5rem;
}

/* La barra de pestañas va en el mismo gutter, PERO no puede llevar el 1.5rem
   pelado: .fa-subnav trae un margin-left:-0.75rem propio que compensa el
   padding-left del primer item, para que el TEXTO —no la caja— arranque
   alineado con el título. Acá esa compensación se resta del gutter
   (1.5rem - 0.75rem), igual que en clientes/admin, donde el 1.5rem lo pone el
   padding del container-xl y el negativo lo descuenta. Sin esta regla las
   pestañas quedan 1.5rem a la izquierda del título y de la tabla. */
.fa-modulo-facturas .fa-subnav {
  margin-left: 0.75rem;
  margin-right: 1.5rem;
}

/* ── Módulos de tabla SIN el shell de facturas (clientes · admin · dashboards) ──
   Usan fa-modulo-tabla con el container centrado de Bootstrap, así que su margen
   lateral no coincidía con base-operaciones/disposiciones/pagos (que usan
   fa-modulo-facturas: contenido a ancho completo con gutter de 1.5rem).
   Replicamos SOLO el ancho lateral: contenido full-width con 1.5rem de gutter,
   uniforme para encabezado, pestañas y tabla. Scope por :not(.fa-modulo-facturas)
   para no alterar el scroll ni la altura del otro shell. */
body.fa-modulo-tabla:not(.fa-modulo-facturas) .app-content {
  padding-left: 0 !important;
  padding-right: 0 !important;
}
body.fa-modulo-tabla:not(.fa-modulo-facturas) .app-content > .container-xl {
  max-width: 100%;
  padding-left: 1.5rem;
  padding-right: 1.5rem;
}

/* ── /admin: respiro lateral propio, que se recoge al angostarse ──
   Ensancha el gutter de 1.5rem de arriba SOLO en el shell de Administrador
   (título, pestañas y contenido se mueven juntos: el margen vive en el
   container, no en cada sub-página, así que las cuatro pestañas quedan
   alineadas entre sí).

   Se recoge por tramos hasta desaparecer: las tablas de este módulo son
   anchas (7 columnas en Usuarios, dos tablas lado a lado en
   Banqueros/Promotores) y en pantalla chica el aire lateral se paga con
   ancho útil de tabla. Los cortes son los de Bootstrap (lg y md) para no
   estrenar breakpoints propios.

   NO SIMPLIFICAR el selector a `body.fa-modulo-admin`: la regla de arriba
   pesa (0,4,1) —`:not()` aporta el peso de su argumento, así que
   `.fa-modulo-tabla` + `:not(.fa-modulo-facturas)` cuentan como dos clases—
   y le ganaría a un `body.fa-modulo-admin`, que pesa (0,3,1), sin importar
   el orden del archivo: el 3.5rem no llegaría a pintarse nunca. Repetir acá
   `.fa-modulo-tabla` y el mismo `:not(.fa-modulo-facturas)` sube este
   selector a (0,5,1) y lo deja leerse como lo que es: un refinamiento de la
   regla anterior, no un empate accidental. */
body.fa-modulo-tabla.fa-modulo-admin:not(.fa-modulo-facturas)
  .app-content
  > .container-xl {
  padding-left: 3.5rem;
  padding-right: 3.5rem;
}

@media (max-width: 1199.98px) {
  body.fa-modulo-tabla.fa-modulo-admin:not(.fa-modulo-facturas)
    .app-content
    > .container-xl {
    padding-left: 1.5rem;
    padding-right: 1.5rem;
  }
}

@media (max-width: 767.98px) {
  body.fa-modulo-tabla.fa-modulo-admin:not(.fa-modulo-facturas)
    .app-content
    > .container-xl {
    padding-left: 0.5rem;
    padding-right: 0.5rem;
  }
}

/* ── Tablas más alargadas: mismo alto que la tabla de /base-operaciones ──
   El área scrollable estira a calc(100vh - 210px) en vez del tope por defecto
   de 570px. Aplica a los cuatro módulos de tabla: base-operaciones +
   disposiciones + pagos (fa-modulo-facturas) y clientes. */
.fa-modulo-facturas .fa-tabla-card .fa-tabla-wrapper--scroll,
body.fa-modulo-tabla:not(.fa-modulo-facturas) .fa-tabla-wrapper--scroll {
  max-height: calc(100vh - 210px);
}

/* Clientes/admin/dashboards: permitir scroll de PÁGINA. El shell fa-modulo-tabla
   pone el body en overflow:hidden (se propaga al viewport y bloquea el scroll),
   pensado para scroll interno de tabla con tope de 570px. Con la tabla más alta
   el paginador queda bajo el fold; habilitamos el scroll de página (como
   /base-operaciones) para que sea alcanzable. */
body.fa-modulo-tabla.app:not(.fa-modulo-facturas) {
  overflow-y: auto;
  overflow-x: hidden;
}

.fa-modulo-tabla .app-footer {
  margin-top: auto;
}

.fa-modulo-tabla .app-footer,
.fa-modulo-tabla .app-footer .container {
  background-color: #ffffff;
}

.fa-modulo-tabla .app-footer .container {
  padding-top: 1rem !important;
  padding-bottom: 1rem !important;
}

/* Variante más pequeña del botón de acción */
.fa-btn-accion--sm {
  padding: 0.35rem 0.9rem;
  font-size: 0.78rem;
}

/* ── Overlay de fondo ── */
.fa-panel-overlay {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 1040;
  background-color: rgba(0, 0, 0, 0.35);
  align-items: center;
  justify-content: center;
}

.fa-panel-overlay.activo {
  display: flex;
}

/* ── Panel central ── */
.fa-panel {
  background: #ffffff;
  border-radius: 18px;
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.04),
    0 8px 24px rgba(0, 0, 0, 0.08),
    0 32px 80px rgba(0, 0, 0, 0.14);
  width: 96%;
  max-width: 1140px;
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  animation: fa-panel-entrada 0.22s ease;
}

@keyframes fa-panel-entrada {
  from {
    opacity: 0;
    transform: translateY(12px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* ── Header del panel ── */
.fa-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.75rem 1.75rem;
  border-bottom: none;
}

.fa-panel-titulo {
  font-size: 0.8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  /* #6c757d sobre blanco = 4.69:1 (WCAG AA). El #9fa7b5 previo daba 2.4:1. */
  color: #6c757d;
  margin: 0;
}

/* Scopeada al header: la clase también se usa en botones "Cancelar" de
   formularios dentro del panel, que necesitan conservar el estilo del botón
   (.fa-co-btn--white) sin que se les impongan 40×40 sin padding ni margin
   negativo. JS sigue escuchando el selector por sí solo (panel_acciones.js). */
.fa-panel-header .fa-panel-cerrar {
  background: none;
  border: none;
  font-size: 1.5rem;
  line-height: 1;
  color: #828d9f;
  cursor: pointer;
  /* Área de toque accesible: 40x40 (WCAG 2.5.5). Antes 24x24. El margin
	   negativo absorbe el crecimiento para no empujar el header. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  margin: -0.5rem -0.5rem -0.5rem 0;
  padding: 0;
  transition: color 0.15s ease;
}

.fa-panel-header .fa-panel-cerrar:hover {
  color: #252930;
}

/* ── Cuerpo del panel ── */
.fa-panel-body {
  padding: 1.5rem 1.75rem;
  overflow-y: auto;
  flex: 1;
}

/* ── Layout dos columnas dentro del panel ── */
.fa-panel-dos-col {
  display: flex;
  gap: 0;
  height: 100%;
  min-height: 480px;
}

.fa-panel-col-izq {
  flex: 0 0 30%;
  width: 30%;
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  padding-right: 1.75rem;
}

.fa-panel-divisor {
  flex: 0 0 1px;
  background: linear-gradient(
    to bottom,
    transparent 0%,
    #e0e3e8 15%,
    #e0e3e8 85%,
    transparent 100%
  );
  margin: 0 1.75rem;
  align-self: stretch;
}

.fa-panel-col-der {
  flex: 1;
  /* min-width:0 conserva el shrink del flex item (lo que daba overflow:hidden)
	   sin recortar la sombra/tooltip de los botones pegados al borde. La tabla
	   de captura ya clipa su propio contenido con overflow-y:auto. */
  min-width: 0;
  display: flex;
  flex-direction: column;
  overflow: visible;
}

/* ── Campos informativos (izquierda) ── */
.fa-campo-grupo {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.fa-campo-label {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  /* #6c757d sobre blanco = 4.69:1 (WCAG AA). El #9fa7b5 previo daba 2.4:1. */
  color: #6c757d;
  margin: 0;
}

.fa-campo-readonly {
  font-size: 0.9rem;
  font-weight: 600;
  color: #252930;
  padding: 0.3rem 0;
  /* line-height + min-height = una línea (0.9×1.5=1.35rem): un campo vacío
	   mide lo mismo que uno con texto. */
  line-height: 1.5;
  min-height: 1.35rem;
  border-bottom: 1px solid #f0f1f4;
}

/* Placeholder "—" (sin dato seleccionado): mismo guion pero en gris suave. */
.fa-campo-readonly--placeholder {
  color: #c8cdd6;
}

/* Dos campos readonly en una sola fila (ej. Última / Próxima dispo). */
.fa-campo-par {
  display: flex;
  gap: 1rem;
}
.fa-campo-par .fa-campo-grupo {
  flex: 1;
  /* min-width:0 deja que el flex-item encoja a su mitad real. Sin esto, el
	   par con TomSelect adentro (Cofactor/Moneda) no encogía y se desbordaba
	   ~15px a la derecha, desalineándose del resto de los campos. */
  min-width: 0;
}

/* Solo en el panel de estatus: anclar el valor al fondo de la celda. La
   grilla estira todas las celdas de la fila a igual altura, así la línea
   gris inferior queda alineada aunque un label ocupe 1 o 2 líneas o el
   campo esté vacío. No se aplica a index.html (columna apilada). */
/* Par label+valor compacto: el dato pegado a su título — los colores ya
   los diferencian; el par apretado refuerza la proximidad y hace más
   legible el espacio entre filas y grupos. */
.fa-panel-seccion-grid .fa-campo-readonly {
  margin-top: auto;
  padding-top: 0.05rem;
}

.fa-panel-seccion-grid .fa-campo-grupo {
  gap: 0.05rem;
}

.fa-campo-select {
  font-size: 0.875rem;
  color: #252930;
  border: 1px solid #e7e9ed;
  border-radius: 6px;
  padding: 0.4rem 0.6rem;
  background: #fafbff;
  width: 100%;
  outline: none;
  transition: border-color 0.15s ease;
}

.fa-campo-select:focus {
  border-color: #1a1a1a;
}

.fa-btn-disposicion {
  margin-top: auto;
  width: 100%;
  /* inline-flex activa el justify/align; min-height 44px = target táctil. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
}

.fa-btn-disposicion:disabled {
  background-color: #6c757d;
  cursor: not-allowed;
  opacity: 0.6;
}

/* ── Tabla de disposiciones (derecha) ── */
.fa-tabla-wrapper {
  overflow-x: auto;
  flex: 1;
}

.fa-tabla {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.8rem;
}

.fa-tabla thead tr {
  border-bottom: 2px solid #e7e9ed;
}

.fa-tabla th {
  padding: 0.6rem 0.75rem;
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: #9fa7b5;
  white-space: nowrap;
  text-align: left;
}

.fa-tabla td {
  padding: 0.65rem 0.75rem;
  color: #5d6778;
  border-bottom: 1px solid #f0f1f4;
  vertical-align: middle;
}

.fa-tabla-vacia {
  text-align: center;
  color: #9fa7b5;
  padding: 2.5rem !important;
  font-size: 0.825rem;
}

/* ── Pagos abiertos (t028) del detalle de una cuenta Monex ── */
.fa-pagos-abiertos-encabezado {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
}

.fa-pagos-abiertos-acciones {
  display: flex;
  gap: 0.5rem;
}

.fa-pagos-abiertos-comentarios {
  min-width: 200px;
  max-width: 280px;
}

/* Comentarios editables en la fila: se ven como texto hasta que se pasa el
   mouse o se enfocan. */
.fa-saldo-comentarios {
  display: block;
  width: 100%;
  min-height: 1.9rem;
  padding: 0.25rem 0.4rem;
  border: 1px solid transparent;
  border-radius: 6px;
  background: transparent;
  color: inherit;
  font: inherit;
  line-height: 1.4;
  resize: none;
  overflow: hidden;
  transition:
    border-color 0.15s ease,
    background-color 0.3s ease;
}

.fa-saldo-comentarios:hover {
  border-color: #e7e9ed;
}

.fa-saldo-comentarios:focus {
  outline: none;
  border-color: var(--color-marca);
  background: #fff;
}

.fa-saldo-comentarios::placeholder {
  color: #c8cdd6;
}

/* Saldo de la cuenta en el detalle: mismo look que los campos de solo
   lectura del modo «ver», pero editable (el borde se marca al pasar el mouse
   y al enfocar). */
.fa-saldo-cuenta {
  width: 100%;
  min-height: 32px;
  padding: 0.35rem 0.4rem;
  border: 1px solid transparent;
  border-bottom-color: #f0f1f4;
  border-radius: 6px 6px 0 0;
  background: transparent;
  color: #252930;
  font: inherit;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  transition:
    border-color 0.15s ease,
    background-color 0.3s ease;
}

.fa-saldo-cuenta:hover {
  border-color: #e7e9ed;
}

.fa-saldo-cuenta:focus {
  outline: none;
  border-color: var(--color-marca);
  background: #fff;
}

/* Sección «Saldos» del detalle: cada saldo abre su propio renglón en la 1.ª
   columna, con su validador a la derecha, aunque la 3.ª quede vacía. */
.fa-form-grupo--inicio-renglon {
  grid-column-start: 1;
}

/* Validador junto al saldo: misma altura y línea base que el input, para
   que la cápsula quede alineada con la cifra de su izquierda. */
.fa-saldo-validador-campo {
  display: flex;
  align-items: center;
  min-height: 32px;
  border-bottom: 1px solid #f0f1f4;
  font-weight: 700;
}

/* Totales al pie de «Pagos abiertos». */
.fa-pagos-abiertos tfoot tr.fa-pagos-abiertos-total:first-child > td {
  border-top: 2px solid #e7e9ed;
}

.fa-pagos-abiertos tr.fa-pagos-abiertos-total > td {
  font-weight: 700;
  color: #1a1a1a;
}

.fa-saldo-validador {
  display: inline-block;
  padding: 0.15rem 0.5rem;
  border-radius: 4px;
  font-variant-numeric: tabular-nums;
}

.fa-saldo-validador--ok {
  background: #d4edda;
  color: #1a6b35;
}

.fa-saldo-validador--error {
  background: #fde8e8;
  color: #c0392b;
}

/* Destello verde breve: confirma que el cambio de la fila se guardó. */
.fa-saldo-guardado {
  background-color: #d4edda !important;
}

/* Paneles «Registrar pago» / «Editar pago» del detalle: pocos campos en una
   columna, así que se acota el .fa-panel global (1140px). */
#overlay-registrar-saldo .fa-panel,
#overlay-editar-saldo .fa-panel {
  max-width: 460px;
}

.fa-saldo-form {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
}

.fa-saldo-form .fa-campo-grupo--monto {
  flex: 1 1 auto;
}

.fa-saldo-form .fa-campo-grupo--moneda {
  flex: 0 0 108px;
}

.fa-saldo-monto {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* Estatus de un saldo en la tabla: pill de color, mismo formato que el
   estado SAT (.fa-badge-sat). El anaranjado de «Definido» es el mismo que
   rellena la fila en el .xlsx exportado (saldo_cero_xlsx.py). */
.fa-saldo-estatus {
  display: inline-block;
  padding: 0.15rem 0.5rem;
  border-radius: 4px;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  white-space: nowrap;
}

/* La cápsula es un <select>: se edita desde la fila. Se le quita el chrome
   nativo y se deja una flecha discreta para que se note que abre. */
select.fa-saldo-estatus {
  appearance: none;
  border: none;
  cursor: pointer;
  padding-right: 1.4rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='5' viewBox='0 0 8 5'%3E%3Cpath d='M0 0l4 5 4-5z' fill='%23252930' fill-opacity='.55'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.45rem center;
}

select.fa-saldo-estatus:focus {
  outline: 2px solid var(--color-marca);
  outline-offset: 1px;
}

select.fa-saldo-estatus option {
  background: #fff;
  color: #252930;
  font-weight: 400;
}

.fa-saldo-estatus--sin-definir {
  background: #f0f1f4;
  color: #9fa7b5;
}

.fa-saldo-estatus--definido {
  background: #ffc000;
  color: #1a1a1a;
}

.fa-saldo-form .fa-btn-disposicion {
  margin-top: 0;
}

/* TomSelect sin chrome, mismo look que el panel de /pagos. */
.fa-saldo-form .ts-wrapper.fa-campo-select {
  padding: 0;
}

.fa-saldo-form .ts-wrapper.fa-campo-select .ts-control {
  border: none;
  border-bottom: 1px solid #e7e9ed;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  padding: 0.3rem 0;
  font-size: 0.9rem;
  font-weight: 600;
  color: #252930;
  min-height: unset;
  cursor: pointer;
}

.fa-saldo-form .ts-wrapper.fa-campo-select .ts-control input {
  color: #252930;
  font-size: 0.9rem;
  font-weight: 600;
  cursor: text;
}

.fa-saldo-form .ts-wrapper.fa-campo-select .ts-control input::placeholder {
  color: #c8cdd6;
  font-weight: 400;
}

.fa-saldo-form .ts-wrapper.fa-campo-select .ts-control:after {
  display: none !important;
}

.fa-saldo-form .ts-wrapper.fa-campo-select.focus .ts-control {
  border-bottom-color: #1a1a1a;
  box-shadow: none;
}

.fa-saldo-form .ts-wrapper.fa-campo-select .ts-dropdown {
  border: 1px solid #e7e9ed;
  border-radius: 8px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
  font-size: 0.875rem;
  margin-top: 4px;
}

.fa-saldo-form .ts-wrapper.fa-campo-select .ts-dropdown .option {
  padding: 0.5rem 0.75rem;
  color: #5d6778;
}

.fa-saldo-form .ts-wrapper.fa-campo-select .ts-dropdown-content {
  max-height: 176px;
}

.fa-saldo-form .ts-wrapper.fa-campo-select .ts-dropdown .option.active,
.fa-saldo-form .ts-wrapper.fa-campo-select .ts-dropdown .option:hover {
  background: #f5f6fe;
  color: #252930;
}

.fa-saldo-form .ts-wrapper.fa-campo-select .ts-control .item {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}

/* ── Sidebar: separadores y footer más ligeros ── */

/* hr del sidebar (los tres separadores entre grupos) */
.app-menu hr {
  background: transparent;
  border: none;
  border-top: 1px solid rgba(0, 0, 0, 0.06);
  opacity: 1;
  margin: 0.35rem 1.25rem;
}

/* Línea superior del footer del sidebar */
.app-sidepanel-footer {
  border-top: 1px solid rgba(0, 0, 0, 0.06) !important;
  background: #fff !important;
}

/* Línea lateral derecha del sidebar */
.app-sidepanel {
  border-right: 1px solid rgba(0, 0, 0, 0.06) !important;
}

/* Línea inferior del header (topbar) */
.app-header {
  border-bottom: 1px solid rgba(0, 0, 0, 0.07) !important;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05) !important;
}

/* ── Sidebar: pill en hover ── */

/* Pill redondeado detrás de cada item del nav (inactivo y activo).
   El color del pill lo define cada estado vía --pill-color. */
.app-nav .nav-link {
  position: relative;
  isolation: isolate;
  --pill-color: #eeeff2; /* gris por defecto (items inactivos) */
}

.app-nav .nav-link::before {
  content: "";
  position: absolute;
  inset: 3px 8px;
  background: var(--pill-color);
  border-radius: 10px;
  z-index: -1;
  opacity: 0;
  transition:
    opacity 0.15s ease,
    background 0.15s ease;
}

/* Hover sobre item inactivo: aparece el pill gris */
.app-nav .nav-link:not(.active):hover::before {
  opacity: 1;
}

.app-nav .nav-link:not(.active):hover {
  color: #252930 !important;
  background: transparent !important;
}

/* ══════════════════════════════════════════════════════════════
   TABLAS DE DATOS PAGINADAS (/disposiciones, /clientes, …)
   ──────────────────────────────────────────────────────────────
   Card único que agrupa search + tabla + footer (contador + paginador).
   Patrón alineado con Carbon Design System, Ant Design y shadcn/ui:
   la paginación vive DENTRO del mismo borde que la tabla — Law of
   Common Region + Uniform Connectedness (Gestalt) hacen que el
   conjunto se perciba como una sola unidad funcional, no tres piezas
   sueltas. Estilos compartidos por TODAS las tablas /disposiciones, /clientes.
   ══════════════════════════════════════════════════════════════ */

/* ══════════════════════════════════════════════════════════════════
   Tarjetas de resumen (KPIs) del módulo de facturas
   ══════════════════════════════════════════════════════════════════ */
/* `minmax(0, 1fr)` y NO `1fr`: `1fr` es azúcar de `minmax(auto, 1fr)`, y ese
   `auto` es un piso de min-content — cualquier tarjeta cuyo contenido no sepa
   encogerse (la fila de años de "Total de facturas": `flex-wrap: nowrap` con
   botones `flex: 0 0 auto`) ensancha SU columna y le roba ancho a las otras
   tres. Con el piso en 0 las cuatro columnas miden exactamente igual y el
   contenido que no entra resuelve por su cuenta (scroll o ellipsis) en vez de
   empujar el grid. */
.fa-resumen-cards {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.9rem;
  margin-bottom: 1.75rem;
}

@media (max-width: 1100px) {
  .fa-resumen-cards {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* KPI: sin borde, pero con ACENTO azul a la izquierda y más presencia
   (sombra azulada + valor más grande). */
.fa-resumen-card {
  display: flex;
  align-items: center;
  padding: 1.05rem 1.7rem;
  min-height: 80px;
  /* Segunda mitad del `minmax(0, 1fr)` de arriba: acotar el TRACK no alcanza,
     porque un grid item también trae `min-width: auto` (piso de min-content) y
     se desbordaría de su celda en vez de encogerse. Con esto el ancho de la
     tarjeta lo manda la columna, y el desborde lo absorbe el contenido. */
  min-width: 0;
  background: #ffffff;
  border: none;
  border-left: 4px solid #4472c4;
  border-radius: 10px;
  box-shadow: 0 4px 14px rgba(68, 114, 196, 0.16);
}

.fa-resumen-card-cuerpo {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 0;
}
.fa-resumen-card-valor {
  font-size: 1.55rem;
  font-weight: 700;
  color: #1a1a1a;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.fa-resumen-card-label {
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: #9fa7b5;
}

/* ══════════════════════════════════════════════════════════════════
   Filtros integrados en el card de la tabla (módulo facturas)
   ══════════════════════════════════════════════════════════════════
   Disposiciones, Vencimientos y Base de Operaciones montan la búsqueda +
   los filtros dentro del MISMO .fa-tabla-card que la tabla, igual que
   /clientes (que lo arma con el macro tabla_datos). Layout del toolbar:
   búsqueda + filtros pegados a la izquierda, y las acciones (Exportar /
   Columnas) empujadas a la derecha con .fa-tabla-toolbar-acciones. Si no
   caben en una línea, el toolbar hace wrap (no scroll horizontal, que
   escondería las acciones). El aspecto de los botones lo heredan de las
   reglas base .fa-filtro-fijo / .fa-btn-filtro (look bordeado). */
.fa-modulo-facturas .fa-tabla-card .fa-tabla-toolbar .fa-filtro-fijo,
.fa-modulo-facturas .fa-tabla-card .fa-tabla-toolbar .fa-btn-filtro {
  flex-shrink: 0;
}

/* Botón "+ Filtro" solo ícono (Disposiciones / Vencimientos). */
.fa-btn-filtro--icono {
  padding: 0.45rem 0.6rem;
}
.fa-btn-filtro--icono i {
  margin: 0;
}

/* Card exterior: único dueño del borde + radius + sombra.
   Todo lo de adentro (toolbar, tabla, footer) usa border-top o
   border-bottom para conectarse sin romper el marco exterior. */
.fa-tabla-card {
  display: flex;
  flex-direction: column;
  background: #ffffff;
  border: 1px solid #c8cdd6;
  border-radius: 10px;
  box-shadow: 0 1px 3px rgba(15, 27, 50, 0.04);
  overflow: hidden;
}

/* Toolbar superior: solo la búsqueda. Padding generoso para que el
   search no quede pegado al borde. Border-bottom suave conecta con
   la rejilla. */
.fa-tabla-card .fa-tabla-toolbar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.75rem;
  row-gap: 0.5rem;
  padding: 0.75rem 1rem;
  border-bottom: 1px solid #e7e9ed;
  background: #ffffff;
}
/* Filtros pegados a la búsqueda (sin margin-left:auto). Las acciones del
   toolbar (Exportar / Columnas) son las que se empujan a la derecha. */
.fa-tabla-card .fa-tabla-toolbar .fa-tabla-toolbar-acciones {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  flex-shrink: 0;
}

/* Toolbar compacto: `tabla_toolbar_compacta.js` pone `.is-solo-iconos` cuando
   el toolbar ya no cabe en un renglón. Los botones de acción CON ícono pierden
   el texto; los que no tienen ícono (los filtros) no cambian. El texto
   es un nodo suelto (y el JS de cada página lo reescribe con innerHTML), así
   que se oculta con font-size: 0 y el ícono recupera su tamaño. `!important`
   porque el ícono trae `me-2` de Bootstrap y /tareas fija el tamaño del botón
   con un selector de id (`#tareas-tabla-card .fa-btn-accion--sm`). */
.fa-tabla-toolbar.is-solo-iconos .fa-tabla-toolbar-acciones .fa-btn-accion:has(> i, > svg) {
  font-size: 0 !important;
  padding: calc(0.35rem + 0.2rem) 0.65rem;
}
.fa-tabla-toolbar.is-solo-iconos .fa-tabla-toolbar-acciones .fa-btn-accion > i,
.fa-tabla-toolbar.is-solo-iconos .fa-tabla-toolbar-acciones .fa-btn-accion > svg {
  font-size: 0.8rem;
  margin-right: 0 !important;
}
.fa-tabla-toolbar.is-solo-iconos .fa-cols-trigger {
  padding: 0 0.7rem;
}
.fa-tabla-toolbar.is-solo-iconos .fa-cols-trigger > span {
  display: none;
}

/* Wrapper de la tabla DENTRO del card. No border / no radius / no shadow
   propios — los hereda del card. Sin padding: el thead toca los bordes
   del card y sus esquinas redondeadas se alinean con el radius del card.
   max-height ≈ 17 filas visibles. */
.fa-tabla-card .fa-tabla-wrapper--scroll {
  overflow-x: auto;
  overflow-y: auto;
  max-height: 570px;
  border: none;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
}

/* /pagos y /disposiciones muestran sus barras, finas y discretas. Una barra
   oculta es una promesa que la tabla no siempre puede cumplir: si algo se sale
   del contenedor no queda ninguna señal de que hay más contenido, y el usuario
   lee "se perdió una columna". En /disposiciones además es el scroll
   horizontal de cuando la tabla no cabe. */
.fa-tabla-wrapper--scroll:has(#pagos-tabla),
.fa-tabla-wrapper--scroll:has(#tabla-disposiciones) {
  scrollbar-width: thin;
  scrollbar-color: #c8cdd6 transparent;
}
.fa-tabla-wrapper--scroll:has(#pagos-tabla)::-webkit-scrollbar,
.fa-tabla-wrapper--scroll:has(#tabla-disposiciones)::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}
.fa-tabla-wrapper--scroll:has(#pagos-tabla)::-webkit-scrollbar-track,
.fa-tabla-wrapper--scroll:has(#tabla-disposiciones)::-webkit-scrollbar-track {
  background: transparent;
}
.fa-tabla-wrapper--scroll:has(#pagos-tabla)::-webkit-scrollbar-thumb,
.fa-tabla-wrapper--scroll:has(#tabla-disposiciones)::-webkit-scrollbar-thumb {
  background: #c8cdd6;
  border-radius: 4px;
}

/* Footer del card: paginador + contador en la misma fila, dentro del
   marco. border-top los conecta visualmente con la tabla. Fondo gris
   un poco más marcado (#f0f2f5) para que el footer se lea como una
   franja independiente de las filas blancas, sin gritar. */
 .fa-tabla-card .fa-tabla-footer {
   display: flex;
   align-items: center;
   justify-content: space-between;
   gap: 1rem;
   padding: 0.2rem 1rem;
   border-top: 1px solid #e7e9ed;
   background: #f0f2f5;
   /* min-height es un PISO, no un techo: en /clientes (sin paginador) el footer
      baja hasta acá; en /disposiciones los botones del paginador empujan el alto por
      encima de este valor, así que no se aprietan. */
   min-height: 30px;
 }

/* Fallback: si una tabla NO está dentro de .fa-tabla-card (por ejemplo
   las tablas auxiliares dentro de paneles, /disposiciones "Generar Factura"),
   el wrapper conserva su propio marco redondeado. La especificidad de
   `.fa-tabla-card .fa-tabla-wrapper--scroll` arriba pisa este fallback
   cuando aplica. */
.fa-tabla-wrapper--scroll {
  overflow-x: auto;
  overflow-y: auto;
  max-height: 510px;
  border: 1px solid #c8cdd6;
  border-radius: 10px;
  background: #ffffff;
  box-shadow: 0 1px 3px rgba(15, 27, 50, 0.04);
}

/* table-layout: fixed permite repartir el ancho según los selectores
   por columna de abajo y que el text-overflow: ellipsis de las celdas
   funcione sin forzar scroll horizontal. Sin esto, el browser sigue
   queriendo darle espacio natural a cada celda y desborda el wrapper.

   Scope: solo /disposiciones (#tabla-disposiciones). En /clientes
   mantenemos el layout automático para no alterar tablas ya validadas. */
#tabla-disposiciones {
  table-layout: fixed;
  width: 100%;
}/* Los encabezados pasan a dos renglones cuando su columna mide lo que su
   dato (el JS de /disposiciones ajusta cada ancho a su contenido). */
#tabla-disposiciones thead th:not([data-sort="comprador"]):not([data-sort="vendedor"]) {
  white-space: normal;
  line-height: 1.15;
}

/* Anchos por columna — presupuesto que LLENA el 100% del contenedor sin
   desbordar (sin scroll horizontal). Las columnas de datos llevan px acotado
   (contenido de rango conocido: fechas, montos, códigos). comprador y
   vendedor NO llevan width fijo: absorben el espacio restante (en partes
   iguales) y truncan con ellipsis + tooltip cuando aprieta. Se quitó el
   min-width de 160px — era el piso duro que forzaba el desborde — y se bajó
   a un mínimo apenas legible. Scope #tabla-disposiciones para no tocar
   /clientes. Suma de columnas de datos ≈ 960px + 2×72px de nombres = ~1104px
   de ancho mínimo de tabla. */
#tabla-disposiciones thead th[data-sort="comprador"],
#tabla-disposiciones thead th[data-sort="vendedor"] {
  min-width: 72px;
}
/* #Disp. lleva la flecha desplegable + el número → algo más ancha que un
   número pelado. */
#tabla-disposiciones thead th[data-sort="disposicion"] {
  width: 84px;
}
#tabla-disposiciones thead th[data-sort="fecha_dispo"],
#tabla-disposiciones thead th[data-sort="vencimiento"],
#tabla-disposiciones thead th[data-sort="fecha_pago"] {
  width: 84px;
}
/* Todas las columnas de MONTO comparten el mismo ancho (diseño uniforme):
   Monto, Financiado, Comisión, Comisión IVA, Comisión Total. 112px acomoda el
   valor más grande (sumas de grupo en millones, p. ej. "$ 2,828,813.56"). */
#tabla-disposiciones thead th[data-sort="monto"],
#tabla-disposiciones thead th[data-campo="financiado"],
#tabla-disposiciones thead th[data-campo="comision"],
#tabla-disposiciones thead th[data-campo="iva"],
#tabla-disposiciones thead th[data-campo="comision_total"] {
  width: 112px;
}
#tabla-disposiciones thead th[data-sort="nom_cofactor"] {
  width: 46px;
}
/* Ancho suficiente para que el encabezado "MONEDA" se muestre completo (no
   "MON…"). */
#tabla-disposiciones thead th[data-sort="moneda"] {
  width: 78px;
  text-align: center;
}
#tabla-disposiciones thead th[data-campo="estado"] {
  width: 74px;
}
/* Padding horizontal más ajustado SOLO en esta tabla: con 16 columnas los
   0.75rem por lado sumaban ~380px de aire. A 0.55rem se recuperan ~90px sin
   que las celdas se sientan apretadas. */
#tabla-disposiciones th,
#tabla-disposiciones td {
  padding-left: 0.55rem;
  padding-right: 0.55rem;
}
/* Filtros del toolbar de /disposiciones al MISMO tamaño que las celdas de la
   tabla, siguiendo los dos escalones de compresión de `tabla-compacta`. */
.fa-tabla-card:has(#tabla-disposiciones) .fa-tabla-toolbar .fa-filtro-fijo {
  font-size: 0.75rem;
}
@container tabla-compacta (max-width: 1400px) {
  .fa-tabla-card:has(#tabla-disposiciones) .fa-tabla-toolbar .fa-filtro-fijo {
    font-size: 0.7rem;
  }
}
@container tabla-compacta (max-width: 1100px) {
  .fa-tabla-card:has(#tabla-disposiciones) .fa-tabla-toolbar .fa-filtro-fijo {
    font-size: 0.64rem;
  }
}
/* Moneda (col 6): centrada en header, fila-grupo Y sub-filas. La fila-grupo
   ya centra vía renderFn; esta regla alinea el detalle (texto plano) para que
   no quede desfasado. Su posición cambió con el reordenamiento de columnas. */
#tabla-disposiciones td:nth-child(6) {
  text-align: center;
}
/* Sub-fila: la factura vive en la col1 (Comprador). Se alinea a la DERECHA
   (vía .fa-subcell-derecha del componente, igual que los elementos desplegados
   bajo Vendedor en pagos) y conserva la guía azul + indent del td:first-child
   más abajo. No se anula nada: se deja el comportamiento por defecto. */
/* Sub-fila de # FAC: no_factura pegado a la DERECHA, pero truncando el
   FINAL para conservar el prefijo (MXITP00000…, no …046351). El truco:
   span inline-block con max-width:100% dentro de un td text-align:right.
   Corto → se alinea a la derecha; largo → llena el ancho y trunca su final
   con ellipsis (que en LTR cae a la derecha). */
.fa-subrow td.fa-subcell-derecha {
  text-align: right;
}
.fa-subrow td.fa-subcell-derecha .fa-subcell-trunc {
  display: inline-block;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: middle;
}

/* ── Tabla /pagos ── (#pagos-tabla)
   table-layout:fixed, igual que #tabla-disposiciones y #tabla-compradores:
   con layout automático el ancho de una celda nunca baja de su contenido
   (los td son nowrap), así que Comprador y Vendedor —nombres largos— se
   comían la tabla.

   LAS 13 COLUMNAS VAN EN PORCENTAJE y suman exactamente 100%. Es a propósito
   y es distinto del patrón mixto (% + px) de las otras dos tablas: mezclar px
   fijos con porcentajes hace que al angostarse el contenedor los px no cedan
   nada, la suma se pase del 100% y la tabla se desborde de su tarjeta. Con el
   scroll horizontal —que además tiene la barra oculta en este módulo— las
   últimas columnas desaparecían de vista con solo subir el zoom del navegador.
   En porcentaje puro la tabla SIEMPRE entra completa: lo que cambia con el
   zoom es cuánto texto se ve por celda, no cuántas columnas hay.

   El reparto respeta el peso de cada dato: los dos nombres se llevan el 29%
   porque son los textos más largos, las cinco columnas de dinero 7.5% cada una
   (la cifra más grande, "$ 605,268.85", es lo que fija ese piso), Tipo Pago 8%
   ("Indirecto parcial" es el valor más largo de t014.tipo_pago) y el resto lo
   que pide su encabezado. Comprador, Vendedor y Tipo Pago truncan con ellipsis
   y tienen tooltip con el valor completo (tooltipSiNoVacio); el nombre entero
   del cofactor también está en el tooltip (tooltipCampo).

   El card es además el CONTENEDOR DE CONSULTA de los @container de abajo: con
   el zoom del navegador el viewport medido en px de CSS se achica, así que
   reaccionar al ancho del card cubre zoom, sidebar abierto/cerrado y monitor
   distinto con una sola regla.

   /disposiciones y las dos pestañas de /tareas comparten ESTA MISMA escala tipográfica (encabezado
   compacto + los dos escalones de compresión): nacieron para que las 14
   columnas de /pagos quepan, pero con tamaños distintos el portal cambiaba de
   letra al pasar de un módulo al otro. El padding de los escalones solo lo
   toma /disposiciones: /tareas fija el suyo en su template, contra sus anchos
   por `<colgroup>`. */
.fa-tabla-card:has(#pagos-tabla),
.fa-tabla-card:has(#tabla-disposiciones),
.fa-tabla-card:has(#tabla-tareas),
.fa-tabla-card:has(#tabla-documentos) {
  container-type: inline-size;
  container-name: tabla-compacta;
}

#pagos-tabla {
  table-layout: fixed;
  width: 100%;
}

/* Encabezado más compacto que el resto de las tablas: 0.63rem y el
   interletrado a la mitad del 0.08em global. En una tabla de 13 columnas ese
   interletrado es caro —en "REMANENTE" solo el espaciado suma ~9px— y era lo
   que dejaba a ese título y a "COFACTOR" con ellipsis al 100% de zoom. */
#pagos-tabla thead th,
#tabla-disposiciones thead th,
#tabla-tareas thead th,
#tabla-documentos thead th {
  font-size: 0.63rem;
  letter-spacing: 0.04em;
}

/* Columnas de TEXTO LARGO — se llevan el sobrante */
#pagos-tabla thead th[data-col="comprador"] {
  width: 15.5%;
}
#pagos-tabla thead th[data-col="vendedor"] {
  width: 13.5%;
}

/* Columnas de dato corto — el porcentaje sale del ENCABEZADO, que en todas
   ellas es más ancho que su dato ("FCB", "USD", "1"). Cofactor se lleva medio
   punto más que sus pares porque su título es el más largo de las cortas; ese
   punto salió de Comprador y Vendedor, que truncan con ellipsis y tienen el
   valor completo en el tooltip. */
#pagos-tabla thead th[data-col="cofactor"] {
  width: 5.5%;
}
#pagos-tabla thead th[data-col="moneda"] {
  width: 5%;
}
#pagos-tabla thead th[data-col="n_facturas"] {
  width: 5%;
}
#pagos-tabla thead th[data-col="fecha_pago"] {
  width: 5.5%;
}

/* Columnas de DINERO — el mismo ancho las cinco (diseño uniforme). Intereses
   va medio punto abajo: es la única que en los datos reales no pasa de miles. */
#pagos-tabla thead th[data-col="pago"],
#pagos-tabla thead th[data-col="aplicado_facturas"],
#pagos-tabla thead th[data-col="facturas_intereses"],
#pagos-tabla thead th[data-col="remanente"] {
  width: 7.5%;
}
#pagos-tabla thead th[data-col="aplicado_intereses"] {
  width: 7%;
}
/* Tipo Pago — el ancho lo fija "Indirecto parcial", el valor más largo del
   vocabulario de t014.tipo_pago. Trunca con ellipsis y deja el valor entero
   en el tooltip, igual que los dos nombres. */
#pagos-tabla thead th[data-col="tipo_pago"] {
  width: 8%;
}
#pagos-tabla thead th[data-col="estatus"] {
  width: 5%;
}

/* Padding horizontal ajustado, igual que /disposiciones: con 14 columnas los
   0.75rem por lado sumaban ~340px de puro aire. */
#pagos-tabla th,
#pagos-tabla td {
  padding-left: 0.55rem;
  padding-right: 0.55rem;
}

/* Cofactor (col 3) y Moneda (col 4): centradas también en las sub-filas, que
   pintan texto plano y no pasan por el renderFn que centra la fila-grupo. */
#pagos-tabla td:nth-child(3),
#pagos-tabla td:nth-child(4) {
  text-align: center;
}

/* ── Compresión progresiva ──
   El ancho de columna ya es proporcional, pero el TEXTO no: a 150% de zoom
   una celda de dinero baja a ~72px y "$ 605,268.85" a 0.75rem no entra. Estos
   dos escalones bajan tipografía, interletrado y padding para que la cifra
   siga completa en vez de truncarse. Se tocan solo esas tres propiedades: los
   porcentajes no cambian, así que el layout es el mismo a cualquier zoom.
   El selector por id gana sobre el genérico .fa-tabla-wrapper--scroll .fa-tabla. */
@container tabla-compacta (max-width: 1400px) {
  #pagos-tabla thead th,
  #tabla-disposiciones thead th,
  #tabla-tareas thead th,
  #tabla-documentos thead th {
    font-size: 0.58rem;
    letter-spacing: 0.02em;
  }
  #pagos-tabla tbody td,
  #tabla-disposiciones tbody td,
  #tabla-tareas tbody td,
  #tabla-documentos tbody td {
    font-size: 0.7rem;
  }
  #pagos-tabla th,
  #pagos-tabla td,
  #tabla-disposiciones th,
  #tabla-disposiciones td {
    padding-left: 0.4rem;
    padding-right: 0.4rem;
  }
}

@container tabla-compacta (max-width: 1100px) {
  #pagos-tabla thead th,
  #tabla-disposiciones thead th,
  #tabla-tareas thead th,
  #tabla-documentos thead th {
    font-size: 0.55rem;
    letter-spacing: 0.01em;
  }
  #pagos-tabla tbody td,
  #tabla-disposiciones tbody td,
  #tabla-tareas tbody td,
  #tabla-documentos tbody td {
    font-size: 0.64rem;
  }
  #pagos-tabla th,
  #pagos-tabla td,
  #tabla-disposiciones th,
  #tabla-disposiciones td {
    padding-left: 0.28rem;
    padding-right: 0.28rem;
  }
}

/* ── Tablas /clientes/compradores y /clientes/vendedores ──
   (#tabla-compradores, #tabla-vendedores)

   table-layout:fixed con TODAS las columnas en px, ninguna en % ni sin ancho.
   Cada px es lo que esa columna necesita para leer su título (con la flecha
   del orden) y su dato típico. Con todas en px el navegador:
   - reparte el sobrante en PROPORCIÓN entre todas cuando la tarjeta es más
     ancha que la suma (al ocultar columnas en «Columnas», el espacio se
     reparte, no se lo lleva una sola);
   - ensancha la tabla a la suma de las visibles cuando no cabe, y el
     wrapper hace scroll horizontal en vez de aplastar columnas a 0px.
   Por eso no llevan min-width: el piso es la suma de las columnas VISIBLES.
   Mezclar px y % rompe las dos cosas: el % se respeta exacto y el sobrante
   se va solo a las de px; una columna sin ancho se lleva todo el sobrante y,
   si no sobra nada, mide 0px. */

#tabla-compradores,
#tabla-vendedores {
  table-layout: fixed;
  width: 100%;
}

/* Todo el cuerpo en MAYÚSCULAS (visual; no altera datos ni tooltips), igual
   que en cofactores. */
#tabla-compradores tbody td,
#tabla-vendedores tbody td {
  text-transform: uppercase;
}

#tabla-compradores thead th[data-sort="comprador"] {
  width: 130px;
}
#tabla-compradores thead th[data-sort="vendedor"] {
  width: 105px;
}
#tabla-compradores thead th[data-sort="cofactor"] {
  width: 95px;
}
#tabla-compradores thead th[data-sort="estatus"] {
  width: 76px;
}
#tabla-compradores thead th[data-sort="tipo_pago"] {
  width: 78px;
}
#tabla-compradores thead th[data-sort="flujo"] {
  width: 100px;
}
#tabla-compradores thead th[data-sort="porc_financiado"] {
  width: 64px;
}
#tabla-compradores thead th[data-sort="porc_comision"] {
  width: 66px;
}
#tabla-compradores thead th[data-sort="monto_linea"] {
  width: 96px;
}
#tabla-compradores thead th[data-sort="sub_linea"] {
  width: 92px;
}
#tabla-compradores thead th[data-sort="tipo_tasa"] {
  width: 92px;
}
#tabla-compradores thead th[data-sort="moneda"] {
  width: 74px;
}
#tabla-compradores thead th[data-sort="porc_spread"] {
  width: 76px;
}
#tabla-compradores thead th[data-sort="plazo"] {
  width: 64px;
}
#tabla-compradores thead th[data-sort="porc_cofactor"] {
  width: 68px;
}
#tabla-compradores thead th[data-sort="porc_monex"] {
  width: 82px;
}
#tabla-compradores thead th[data-sort="vencimiento_edifactoring"] {
  width: 152px;
}
#tabla-compradores thead th[data-sort="vencimiento_riesgos"] {
  width: 112px;
}
#tabla-compradores thead th[data-sort="comentarios"] {
  width: 112px;
}
#tabla-compradores thead th.fa-tabla-th-acciones {
  width: 34px;
}

#tabla-vendedores thead th[data-sort="vendedor"] {
  width: 200px;
}
#tabla-vendedores thead th[data-sort="comercial"] {
  width: 105px;
}
#tabla-vendedores thead th[data-sort="rfc"] {
  width: 115px;
}
#tabla-vendedores thead th[data-sort="estatus"] {
  width: 96px;
}
#tabla-vendedores thead th[data-sort="monto_linea"] {
  width: 110px;
  text-align: right;
}
#tabla-vendedores thead th[data-sort="cuenta_dispersion"] {
  width: 130px;
}
#tabla-vendedores thead th[data-sort="banquero"] {
  width: 115px;
}
#tabla-vendedores thead th[data-sort="promotor"] {
  width: 105px;
}
#tabla-vendedores thead th[data-sort="regional"] {
  width: 90px;
}
#tabla-vendedores thead th[data-sort="estado"] {
  width: 92px;
}
#tabla-vendedores thead th[data-sort="tipo_factoraje"] {
  width: 150px;
}
#tabla-vendedores thead th[data-sort="comentarios"] {
  width: 120px;
}
#tabla-vendedores thead th.fa-tabla-th-acciones {
  width: 48px;
}
/* La celda de estatus contiene un badge de ancho fijo (72px): darle ancho
   suficiente y NUNCA truncar con ellipsis. Sin esto, el badge desborda la
   celda angosta y el navegador dibuja el glifo "…" que se veía como un
   punto negro tras el badge. La 4ª columna del cuerpo es Estatus. */
#tabla-vendedores tbody td:nth-child(4) {
  overflow: visible;
  text-overflow: clip;
}

/* ── Tabla /clientes/cofactores ── (#tabla-cofactores)
   10 columnas + acciones: abrev, cofactor, monto_linea, estatus,
   fecha_vencimiento, fecha_autorizacion, codigo, contrato, no_wb, producto.

   LAS ONCE VAN EN PORCENTAJE y suman exactamente 100%, igual que #pagos-tabla
   y a diferencia del patrón mixto (px + %) que esta misma tabla usaba cuando
   tenía 9 columnas. Mezclar px fijos con porcentajes es lo que la rompió al
   entrar `fecha_autorizacion`: los px no ceden nada al angostarse el
   contenedor, la suma se pasa del 100% y las últimas columnas se salen del
   card. Con todo en %, agregar o quitar una columna es redistribuir el
   presupuesto, no descubrir un desborde en pantalla.

   `min-width` es el piso para que TODOS los títulos se lean completos; por
   debajo de eso el wrapper hace scroll horizontal en vez de truncarlos. */

#tabla-cofactores {
  table-layout: fixed;
  width: 100%;
  min-width: 1040px;
}

/* Mostrar todo el cuerpo en MAYÚSCULAS para igualar el estilo de
   compradores/vendedores (cuyos datos ya vienen en mayúsculas desde la BD).
   Es puramente visual: no altera los datos ni el tooltip (title) de la celda,
   que sigue mostrando el valor original. */
#tabla-cofactores tbody td {
  text-transform: uppercase;
}

/* Presupuesto de anchos — 9 + 20 + 10 + 7.5 + 8 + 8 + 7 + 7.5 + 6.5 + 13 +
   3.5 = 100%. Al tocar una columna hay que descontarle a otra: el total no
   negocia. `cofactor` (razón social) y `producto` llevan el mayor peso porque
   son los únicos de largo impredecible, y truncan con ellipsis + tooltip. */
#tabla-cofactores thead th[data-sort="abreviacion"] {
  width: 9%;
}
#tabla-cofactores thead th[data-sort="monto_linea"] {
  width: 10%;
  text-align: right;
}
#tabla-cofactores thead th[data-sort="estatus"] {
  width: 7.5%;
}
/* Igual que en vendedores: el badge de estatus es de ancho fijo (72px);
   damos ancho suficiente y evitamos el ellipsis que se ve como un punto
   tras el badge. La 4ª columna del cuerpo es Estatus. */
#tabla-cofactores tbody td:nth-child(4) {
  overflow: visible;
  text-overflow: clip;
}
/* Las dos fechas comparten ancho: mismo tipo de dato, mismo formato
   dd/mm/aaaa. Sus títulos van abreviados («F. Venc.» / «F. Aut.») con el
   mismo criterio que /disposiciones («F. Disp», «F. Venc»): el rótulo largo
   costaba más ancho que el dato que encabeza. */
#tabla-cofactores thead th[data-sort="fecha_vencimiento"],
#tabla-cofactores thead th[data-sort="fecha_autorizacion"] {
  width: 8%;
}
#tabla-cofactores thead th[data-sort="codigo"] {
  width: 7%;
}
#tabla-cofactores thead th[data-sort="contrato"] {
  width: 7.5%;
  text-align: right;
}
#tabla-cofactores thead th[data-sort="no_wb"] {
  width: 6.5%;
  text-align: right;
}
#tabla-cofactores thead th.fa-tabla-th-acciones {
  width: 3.5%;
}
#tabla-cofactores thead th[data-sort="cofactor"] {
  width: 20%;
}
#tabla-cofactores thead th[data-sort="producto"] {
  width: 13%;
}

/* Sticky header — azul Monex profundo + texto blanco.
   Tono navy derivado del azul Monex (--color-marca: #0095ff) bajado en
   luminosidad para look de header de sistema financiero (Bloomberg-like).
   El border-bottom usa el mismo navy para fundir el borde con el fondo.
   El primer y último th llevan border-radius arriba (definidos abajo)
   para crear el efecto de "tabla dentro de la tabla". */
.fa-tabla-wrapper--scroll .fa-tabla thead th {
  position: sticky;
  top: 0;
  background: #012e92;
  color: #ffffff;
  font-weight: 700;
  z-index: 2;
  cursor: pointer;
  padding: 0.4rem 0.6rem;
  font-size: 0.68rem;
  letter-spacing: 0.08em;
  border-bottom: 1px solid #012e92;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Esquinas redondeadas del thead: solo el primer y último th.
   Radius 9px = 10px del card menos 1px del borde, para que el thead
   matchee exactamente con la curva interior del card. */
.fa-tabla-wrapper--scroll .fa-tabla thead th:first-child {
  border-top-left-radius: 9px;
}

.fa-tabla-wrapper--scroll .fa-tabla thead th:last-child {
  border-top-right-radius: 9px;
}

/* Sin línea bajo los encabezados en disposiciones y pagos (solo visual): el
   header navy queda pegado a la primera fila de datos. Scope por id para NO
   tocar /clientes, que comparte .fa-tabla. Anula la regla genérica
   .fa-tabla thead tr {border-bottom:2px #e7e9ed} y el border-bottom del th. */
#tabla-disposiciones thead tr,
#pagos-tabla thead tr,
#tabla-disposiciones thead th,
#pagos-tabla thead th {
  border-bottom: none;
}

/* Mayor presencia en filas de datos.
   Padding horizontal reducido para que las 11 columnas (10 + acciones)
   entren en el viewport sin scroll horizontal. El ancho de cada columna
   lo deciden los th[width] declarados en la macro / template.
   border-bottom: none para eliminar las líneas horizontales entre filas;
   la diferenciación queda solo en la zebra de filas pares. */
.fa-tabla-wrapper--scroll .fa-tabla tbody td {
  padding: 0.45rem 0.6rem;
  font-size: 0.75rem;
  color: #3d4452;
  white-space: nowrap; /* una sola línea por registro */
  overflow: hidden;
  text-overflow: ellipsis;
  vertical-align: middle;
  border-bottom: none;
}

/* Zebra suave: filas pares con fondo gris muy claro */
.fa-tabla-wrapper--scroll .fa-tabla tbody tr:nth-child(even) td {
  background-color: #fafbfc;
}

/* ── Group-only zebra: JS adds .fa-grupo-row--alt to alternating groups ──
   Include :nth-child(even) variants to guarantee these rules beat the
   generic zebra above regardless of DOM position.
   Placed BEFORE the hover rule so :hover (same specificity, later in file)
   still takes over on pointer-entry. */
.fa-tabla-wrapper--scroll .fa-tabla tbody tr.fa-grupo-row td,
.fa-tabla-wrapper--scroll .fa-tabla tbody tr.fa-grupo-row:nth-child(even) td {
  background-color: #ffffff;
}

.fa-tabla-wrapper--scroll .fa-tabla tbody tr.fa-grupo-row--alt td,
.fa-tabla-wrapper--scroll
  .fa-tabla
  tbody
  tr.fa-grupo-row--alt:nth-child(even)
  td {
  background-color: #fafbfc;
}

/* Sub-rows: fondo recesado plano, nunca zebra según posición en el DOM.
   Se profundiza de #f8f9fb a #f1f4f9 para separar mejor el bloque de
   facturas (hijas) de la fila-grupo blanca (padre) — contraste de región. */
.fa-tabla-wrapper--scroll .fa-tabla tbody tr.fa-subrow td,
.fa-tabla-wrapper--scroll .fa-tabla tbody tr.fa-subrow:nth-child(even) td {
  background-color: #f1f4f9;
}

/* Números tabulares + alineación derecha consistente
   (Monto y % Financiado usan class="text-end") */
.fa-tabla-wrapper--scroll .fa-tabla th.text-end,
.fa-tabla-wrapper--scroll .fa-tabla td.text-end {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* Hover: fondo azul Delta tenue + acento azul Delta en borde izquierdo.
   Va después de la zebra para ganar specificity en filas pares.
   Color centralizado en :root — ver "PALETA DEL PROYECTO" arriba. */
.fa-tabla-wrapper--scroll .fa-tabla tbody tr:hover td,
.fa-tabla-wrapper--scroll .fa-tabla tbody tr:nth-child(even):hover td {
  background-color: var(--color-acento-fila-suave);
}

.fa-tabla-wrapper--scroll .fa-tabla tbody tr:hover td:first-child {
  box-shadow: inset 3px 0 0 var(--color-acento-fila);
}

/* El espacio vacío que `tabla_llenar_alto.js` deja antes del total no es un
   renglón: sin hover, sin acento y sin selección. */
.fa-tabla-wrapper--scroll .fa-tabla tbody.fa-tabla-relleno td,
.fa-tabla-wrapper--scroll .fa-tabla tbody.fa-tabla-relleno tr:hover td {
  background-color: transparent;
  box-shadow: none;
  pointer-events: none;
  user-select: none;
}

/* Controles sobre la tabla (LEGACY — antes de .fa-tabla-card).
   Si una página sigue usando .fa-tabla-controles directamente,
   este estilo mantiene el comportamiento viejo. */
.fa-tabla-controles {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.75rem;
}

/* Grupo: ícono lupa + input de búsqueda.
   Look de input box completo — borde, fondo, radius — para darle
   presencia en la toolbar. La lupa queda fija en gris (no cambia
   con el focus) porque es un ícono decorativo de tipo "buscar aquí". */
.fa-tabla-busqueda-grupo {
  position: relative;
  flex: 0 0 auto;
  width: 320px;
}

.fa-tabla-busqueda-icono {
  position: absolute;
  left: 0.7rem;
  top: 50%;
  transform: translateY(-50%);
  color: #9fa7b5;
  width: 14px;
  height: 14px;
  pointer-events: none;
  flex-shrink: 0;
}

/* Input de búsqueda legacy (suelto, sin grupo) — conserva el look
   inline minimalista para usos viejos como .fa-tabla-controles. */
.fa-tabla-busqueda {
  flex: 0 0 auto;
  width: 280px;
  border: none;
  border-bottom: 1px solid #e7e9ed;
  border-radius: 0;
  background: transparent;
  font-size: 0.875rem;
  font-weight: 400;
  color: #252930;
  padding: 0.3rem 0;
  outline: none;
  transition:
    border-color 0.15s ease,
    box-shadow 0.15s ease,
    background-color 0.15s ease;
}

/* Dentro del grupo con ícono: input box completo (borde + fondo + radius).
   Reemplaza el borde inferior por un marco completo para que el search
   se lea como un campo de formulario con peso visual. */
.fa-tabla-busqueda-grupo .fa-tabla-busqueda {
  width: 100%;
  border: 1px solid #d0d4dc;
  border-radius: 8px;
  background: #ffffff;
  padding: 0.45rem 0.7rem 0.45rem 2rem;
  box-shadow:
    0 1px 3px rgba(0, 0, 0, 0.07),
    0 1px 2px rgba(0, 0, 0, 0.04);
  transition:
    border-color 0.12s,
    box-shadow 0.12s;
}
.fa-tabla-busqueda-grupo .fa-tabla-busqueda:hover {
  border-color: #b0b6c2;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
}

.fa-tabla-busqueda::placeholder {
  color: #9fa7b5;
  font-weight: 400;
}

.fa-tabla-busqueda:focus {
  border-bottom-color: #1a1a1a;
}

.fa-tabla-busqueda-grupo .fa-tabla-busqueda:focus {
  border-color: var(--color-marca);
  box-shadow: 0 0 0 3px rgba(0, 149, 255, 0.12);
}

/* Contador "X–Y de Z registros". Vive en el footer del card; tipografía
   tabular para que los números no salten al cambiar de página. */
.fa-tabla-meta {
  font-size: 0.75rem;
  color: #5d6778;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* Indicadores visuales de ordenamiento — heredan el color del header
   (azul Monex oscuro), por lo que las flechas leen como parte del th. */
.fa-tabla-th-asc::after {
  content: " ↑";
  color: inherit;
}

.fa-tabla-th-desc::after {
  content: " ↓";
  color: inherit;
}

/* Encabezados que ordenan: los de una tabla server-side (`th[data-sort]`) y
   los de una tabla completa que ordena tabla_orden_cliente.js. Mismo alcance
   que ese módulo, para que el cursor no prometa un orden que no existe. */
th[data-sort],
:is(table.fa-tabla, table[data-orden="cliente"]):not([data-orden="no"]):not(:has(th[data-sort]))
  thead tr:last-child th:not([data-orden="no"]):not(:empty) {
  cursor: pointer;
  user-select: none;
}

/* Paginador. En el nuevo card vive en el footer (derecha); en uso
   legacy queda como bloque centrado debajo de la tabla. El margin-top
   y padding-bottom se anulan cuando está dentro del footer del card
   para no romper la grilla del flex. */
.fa-paginador {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.25rem;
  margin-top: 0.75rem;
  padding-bottom: 0.25rem;
}

.fa-tabla-card .fa-tabla-footer .fa-paginador {
  margin-top: 0;
  padding-bottom: 0;
  justify-content: flex-start;
  flex-wrap: wrap;
}

/* Botones del paginador: fondo blanco sólido para destacar sobre el
   fondo gris suave del footer (#fafbfc). Borde y texto sutiles. */
/* Botones del paginador: fondo casi blanco, sin borde para look
   más limpio. La diferencia con el fondo del footer (#f0f2f5) los
   sigue distinguiendo como elementos clickeables. */
.fa-paginador-btn {
  background: #fcfcfd;
  border: none;
  border-radius: 5px;
  padding: 0.2rem 0.55rem;
  font-size: 0.78rem;
  font-weight: 500;
  color: #5d6778;
  cursor: pointer;
  transition:
    background-color 0.15s ease,
    color 0.15s ease,
    border-color 0.15s ease;
  min-width: 1.9rem;
  text-align: center;
  line-height: 1.3;
}

.fa-paginador-btn:hover:not(:disabled):not(.activo) {
  background-color: var(--color-acento-fila-suave);
  color: #252930;
}

.fa-paginador-btn.activo {
  background-color: #1a1a1a;
  color: #ffffff;
  font-weight: 600;
  cursor: default;
}

.fa-paginador-btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

.fa-paginador-ellipsis {
  font-size: 0.8rem;
  color: #9fa7b5;
  padding: 0 0.25rem;
  user-select: none;
}

/* ── /Tablas de datos paginadas ───────────────────────────── */

/* ── Acentos Monex (override del verde #15a362 de portal.css) ─────── */
/* Azul Monex inspirado en el logo: anillo cyan → azul vivo.
   Color centralizado en :root — ver "PALETA DEL PROYECTO" arriba. */
.app-nav .nav-link.active {
  color: var(--color-marca);
  background: transparent;
  border-left: 3px solid var(--color-marca);
  /* El rectángulo azul lo dibuja el pill (no el fondo del link), así
	   queda visible y puede animar igual que en los items inactivos. */
  --pill-color: var(--color-marca-suave);
}

/* Activo: cinta azul que cubre TODO el item (ancho y alto completos),
   sin redondeo — banda continua, no botón. El border-left azul queda
   como acento en el filo izquierdo. */
.app-nav .nav-link.active::before {
  inset: 0;
  border-radius: 0;
  opacity: 1;
}

/* Hover sobre un item YA activo (con cinta azul): aparece un pill MÁS azul
   por encima de la cinta — NO se profundiza todo el bloque. Mismo pill
   redondeado que el gris, pero azul. Excluye el toggle "Facturas", que en
   hover usa pill gris. */
.app-nav .nav-link.active:not(.submenu-toggle)::after {
  content: "";
  position: absolute;
  inset: 3px 8px;
  border-radius: 10px;
  background: var(--color-marca-suave-hover);
  z-index: -1;
  opacity: 0;
  transition: opacity 0.15s ease;
}

.app-nav .nav-link.active:not(.submenu-toggle):hover::after {
  opacity: 1;
}

.app-nav .nav-link:hover {
  color: var(--color-marca);
}

/* Hamburguesa de la barra superior (tres líneas) */
.sidepanel-toggler {
  color: var(--color-marca);
}

.sidepanel-toggler:hover,
.sidepanel-toggler:focus {
  color: var(--color-marca-oscuro);
}
/* ── /Acentos Monex ─────────────────────────────────────────── */

/* ══════════════════════════════════════════════════════════════
   FORMULARIOS DE ALTA (clientes - nuevo)
   ──────────────────────────────────────────────────────────────
   Tarjeta blanca centrada con grid responsivo:
   - Desktop ≥992px : 3 columnas
   - Tablet 768-991 : 2 columnas
   - Mobile <768px  : 1 columna
   Algunos campos largos abarcan 2/3 columnas via .fa-form-grupo--ancho.
   ══════════════════════════════════════════════════════════════ */

.fa-form-toolbar {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  margin-bottom: 0.75rem;
}

.fa-form-wrapper {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 0.25rem 0 2rem;
}

/* El regreso de una hoja de captura, alineado al borde izquierdo de la
   tarjeta (mismo ancho máximo). */
.fa-form-volver {
  width: 100%;
  max-width: 1100px;
}

.fa-form-tarjeta {
  width: 100%;
  max-width: 1100px;
  background: #ffffff;
  border: 1px solid #e7e9ed;
  border-radius: 14px;
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.02),
    0 6px 18px rgba(15, 27, 50, 0.05);
  overflow: hidden;
  /* Necesario para posicionar la × con el mismo offset arriba/derecha */
  position: relative;
}

.fa-form-header {
  padding: 1.1rem 2.25rem 0.9rem;
  border-bottom: 1px solid #f0f1f4;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}

.fa-form-header h2 {
  font-size: 0.95rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: #252930;
  margin: 0;
}

.fa-form-cerrar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 8px;
  color: #9fa7b5;
  font-size: 1.5rem;
  line-height: 1;
  font-weight: 400;
  text-decoration: none;
  background: transparent;
  border: none;
  cursor: pointer;
  /* Fuera del flujo: pegada a la esquina con mismo offset top/right */
  position: absolute;
  top: 1rem;
  right: 1rem;
  transition:
    color 0.15s ease,
    background-color 0.15s ease;
}

.fa-form-cerrar:hover,
.fa-form-cerrar:focus {
  color: #5d6778;
  text-decoration: none;
  outline: none;
}

.fa-form-body {
  padding: 1.5rem 2.25rem;
  position: relative;
}

/* Secciones agrupadas dentro del form */
.fa-form-seccion {
  margin-bottom: 1.5rem;
}

.fa-form-seccion:last-of-type {
  margin-bottom: 0.5rem;
}

.fa-form-seccion-titulo {
  font-size: 0.9rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--color-acento-fila);
  margin: 0 0 0.8rem;
  padding-bottom: 0.4rem;
}

/* Grid responsivo de campos */
.fa-form-grid {
  display: grid;
  gap: 1.4rem 1.75rem;
  grid-template-columns: repeat(3, 1fr);
}

@media (max-width: 991px) {
  .fa-form-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 575px) {
  .fa-form-grid {
    grid-template-columns: 1fr;
  }
}

.fa-form-grupo {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  min-width: 0;
}

.fa-form-grupo--ancho-2 {
  grid-column: span 2;
}

.fa-form-grupo--ancho-3 {
  grid-column: 1 / -1;
}

@media (max-width: 575px) {
  .fa-form-grupo--ancho-2,
  .fa-form-grupo--ancho-3 {
    grid-column: 1 / -1;
  }
}

.fa-form-label {
  font-size: 0.83rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: #5d6778;
  margin: 0;
  display: flex;
  align-items: center;
  gap: 0.3rem;
}

.fa-form-label-req {
  color: #d6336c;
  font-weight: 700;
}

.fa-form-control {
  width: 100%;
  border: 1px solid #e0e3e8;
  background: #ffffff;
  border-radius: 8px;
  padding: 0.5rem 0.7rem;
  font-size: 0.89rem;
  color: #252930;
  font-weight: 500;
  outline: none;
  transition:
    border-color 0.15s ease,
    box-shadow 0.15s ease;
  min-height: 38px;
}

.fa-form-control::placeholder {
  color: #c8cdd6;
  font-weight: 400;
}

.fa-form-control:hover {
  border-color: #c8cdd6;
}

.fa-form-control:focus {
  border-color: var(--color-acento-fila);
  box-shadow: 0 0 0 3px rgba(68, 114, 196, 0.12);
}

textarea.fa-form-control {
  resize: vertical;
  min-height: 90px;
  line-height: 1.45;
}

/* Select nativo: limpiamos el chrome marrón del browser */
select.fa-form-control {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3e%3cpath fill='none' stroke='%239fa7b5' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round' d='M1 1l4 4 4-4'/%3e%3c/svg%3e");
  background-repeat: no-repeat;
  background-position: right 0.85rem center;
  padding-right: 2rem;
  cursor: pointer;
}

/* Pista de ayuda debajo del input */
.fa-form-hint {
  font-size: 0.78rem;
  color: #9fa7b5;
  margin: 0;
}

/* Pie del form: botones de acción */
.fa-form-footer {
  display: flex;
  justify-content: flex-end;
  gap: 0.6rem;
  padding: 1rem 2.25rem 1.6rem;
  border-top: none;
  background: #ffffff;
}

/* Quitar las flechitas de inputs numéricos (spinners del navegador).
   Aplica a TODOS los inputs con la clase .fa-form-control. */
input.fa-form-control[type="number"]::-webkit-outer-spin-button,
input.fa-form-control[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
input.fa-form-control[type="number"] {
  -moz-appearance: textfield;
  appearance: textfield;
}

.fa-btn-secundario {
  background: #ffffff;
  color: #252930;
  border: 1px solid #e0e3e8;
  border-radius: 8px;
  padding: 0.5rem 1.2rem;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition:
    background-color 0.15s ease,
    border-color 0.15s ease;
}

/* Variante compacta — mismo tamaño que .fa-btn-accion--sm para que
   convivan en el mismo header del panel sin verse desparejos. */
.fa-btn-secundario--sm {
  padding: 0.35rem 0.9rem;
  font-size: 0.78rem;
}

/* Hover/focus: tinte azul Delta discreto coherente con el halo de la
   timeline. Fondo muy suave (acento-fila-suave = #f0f2ff), borde y
   texto en azul Delta. Reemplaza el hover gris anterior porque el
   azul comunica mejor "elemento activado" y arma sistema con el resto. */
.fa-btn-secundario:hover,
.fa-btn-secundario:focus-visible {
  background: var(--color-acento-fila-suave);
  border-color: var(--color-acento-fila);
  color: var(--color-acento-fila);
  text-decoration: none;
}

/* Ring de focus por teclado — mismo azul del halo de la timeline para
   que el sistema visual sea coherente sin importar dónde estés navegando. */
.fa-btn-secundario:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(68, 114, 196, 0.18);
}

/* Deshabilitado: todo en gris y sin el hover azul. Se usa cuando la acción
   dejó de estar permitida por una regla de negocio (ej. Editar pago después
   del paso 3 del ciclo de cobro), no como estado transitorio — el `title`
   lleva el motivo, porque un botón inerte no puede explicarse solo.

   `[aria-disabled]` cubre el caso en que la acción es un <a>: ese elemento
   ignora `disabled`, así que se pinta como <span> sin href —inerte de verdad,
   también para el teclado— y este es el único gancho que le queda al CSS. */
.fa-btn-secundario:disabled,
.fa-btn-secundario[disabled],
.fa-btn-secundario[aria-disabled="true"] {
  color: #9fa7b5;
  background: #f5f6fe;
  border-color: #e7e9ed;
  cursor: not-allowed;
}

.fa-btn-secundario:disabled:hover,
.fa-btn-secundario[disabled]:hover,
.fa-btn-secundario[aria-disabled="true"]:hover {
  color: #9fa7b5;
  background: #f5f6fe;
  border-color: #e7e9ed;
}

/* ──────────────────────────────────────────────────────────────────────────
   LISTA REPETIBLE ("+ Agregar correo") — banqueros/promotores, t004.correos
   Control genérico de N inputs con un botón "quitar" por fila (JS:
   lista_repetible.js). Cada fila es un input.fa-form-control + botón ×,
   apilados con el mismo gap vertical que el resto del form.
   ────────────────────────────────────────────────────────────────────────── */
.fa-lista-repetible {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.fa-lista-repetible-fila {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.fa-lista-repetible-fila .fa-form-control {
  flex: 1 1 auto;
}

.fa-lista-repetible-quitar {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 8px;
  border: 1px solid #e0e3e8;
  background: #ffffff;
  color: #9fa7b5;
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  transition:
    background-color 0.15s ease,
    border-color 0.15s ease,
    color 0.15s ease;
}

.fa-lista-repetible-quitar:hover,
.fa-lista-repetible-quitar:focus-visible {
  background: rgba(214, 51, 108, 0.08);
  border-color: #d6336c;
  color: #d6336c;
  outline: none;
}

/* Fila triple (Nombre · Correo · Enviar como) — sección "Correos" del form
   de vendedor (rehacer-contactos-vendedor). A diferencia del resto de
   .fa-lista-repetible-fila (que reparte el ancho completo entre sus
   inputs), acá los 3 campos van con ancho fijo y alineados a la
   izquierda: es una fila de captura puntual, no una tabla que deba
   ocupar todo el ancho de la tarjeta del form. */
.fa-lista-repetible-fila--triple {
  justify-content: flex-start;
}

.fa-lista-repetible-fila--triple .fa-form-control:nth-child(1),
.fa-lista-repetible-fila--triple .fa-form-control:nth-child(2) {
  flex: 0 0 240px;
}

.fa-lista-repetible-fila--triple .fa-form-control:nth-child(3) {
  flex: 0 0 110px;
}

/* "+ Agregar correo" (sección "Correos" del vendedor): sigue siendo un
   <button type="button"> real por accesibilidad/teclado, pero se ve como
   texto clickeable — sin caja, fondo ni borde — alineado a la izquierda
   (align-self evita que .fa-form-grupo lo estire a todo el ancho). */
.fa-btn-texto {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  color: var(--color-acento-fila);
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
}

.fa-btn-texto:hover {
  text-decoration: underline;
}

.fa-btn-texto:focus-visible {
  outline: none;
  text-decoration: underline;
  border-radius: 4px;
  box-shadow: 0 0 0 3px rgba(68, 114, 196, 0.18);
}

/* Override TomSelect dentro del form para que herede el look de .fa-form-control.
   Incluye la flecha ▾ a la derecha (mismo SVG que el select nativo) para que
   se lea claramente como un desplegable y no como un input de texto. */
.fa-form-grupo .ts-control {
  border: 1px solid #e0e3e8 !important;
  border-radius: 8px !important;
  padding: 0.35rem 2rem 0.35rem 0.7rem !important;
  min-height: 38px;
  background-color: #ffffff !important;
  background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3e%3cpath fill='none' stroke='%239fa7b5' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round' d='M1 1l4 4 4-4'/%3e%3c/svg%3e") !important;
  background-repeat: no-repeat !important;
  background-position: right 0.85rem center !important;
  font-size: 0.875rem;
  font-weight: 500;
  color: #252930;
  box-shadow: none !important;
  transition:
    border-color 0.15s ease,
    box-shadow 0.15s ease;
}

/* Al abrir el desplegable, rotamos la flecha para reforzar el affordance. */
.fa-form-grupo .ts-wrapper.dropdown-active .ts-control {
  background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3e%3cpath fill='none' stroke='%234472c4' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round' d='M1 5l4-4 4 4'/%3e%3c/svg%3e") !important;
}

.fa-form-grupo .ts-wrapper.focus .ts-control {
  border-color: var(--color-acento-fila) !important;
  box-shadow: 0 0 0 3px rgba(68, 114, 196, 0.12) !important;
}

.fa-form-grupo .ts-control input::placeholder {
  color: #c8cdd6 !important;
  font-weight: 400;
}

/* Aviso informativo arriba del form (ej. "Todos los campos son obligatorios") */
.fa-form-aviso {
  margin: 0 2.25rem 1.1rem;
  padding: 0.55rem 0.85rem;
  border-left: 3px solid #4472c4;
  background: #f5f8fd;
  color: #5d6778;
  font-size: 0.82rem;
  font-weight: 500;
  border-radius: 4px;
}

/* ────── Validación inline ──────
   El estado :invalid del browser solo se pinta cuando el <form> tiene la clase
   .fa-form-validado (se agrega vía JS al primer submit). Así evitamos que el
   form aparezca todo en rojo al abrirlo.                                    */
.fa-form-validado .fa-form-control:invalid,
.fa-form-validado .fa-form-control.fa-input-invalido {
  border-color: #d6336c;
  background-color: #fff7fa;
}

.fa-form-validado .fa-form-control:invalid:focus,
.fa-form-validado .fa-form-control.fa-input-invalido:focus {
  border-color: #d6336c;
  box-shadow: 0 0 0 3px rgba(214, 51, 108, 0.12);
}

/* TomSelect cuando el <select> oculto está inválido */
.fa-form-validado .fa-form-grupo .ts-wrapper:has(select:invalid) .ts-control,
.fa-form-grupo .ts-wrapper.fa-input-invalido .ts-control {
  border-color: #d6336c;
  background-color: #fff7fa;
}

/* Mensaje de error debajo del campo. Por defecto oculto; se muestra cuando
   el form está validado y el control hermano queda inválido. */
.fa-form-feedback {
  font-size: 0.76rem;
  color: #d6336c;
  margin: 0;
  display: none;
  font-weight: 500;
  line-height: 1.3;
}

.fa-form-validado .fa-form-control:invalid ~ .fa-form-feedback,
.fa-form-validado .fa-form-control.fa-input-invalido ~ .fa-form-feedback,
.fa-form-validado .ts-wrapper:has(select:invalid) ~ .fa-form-feedback {
  display: block;
}

/* Resumen sutil en el footer cuando faltan campos */
.fa-form-footer-error {
  margin-right: auto;
  align-self: center;
  color: #d6336c;
  font-size: 0.83rem;
  font-weight: 500;
}

/* Bloque de mensajes flash dentro del form (no usa el alert global) */
.fa-form-flash {
  margin: 0 2.25rem 1rem;
  padding: 0.7rem 0.9rem;
  border-radius: 8px;
  font-size: 0.9rem;
  font-weight: 500;
  border: 1px solid transparent;
}

.fa-form-flash--ok {
  background: #e8f5ec;
  color: #1e7e34;
  border-color: #c3e6cb;
}

.fa-form-flash--err {
  background: #fdecea;
  color: #a02020;
  border-color: #f5c6cb;
}

/* ══════════════════════════════════════════════════════════════
   FILA RECIÉN CREADA: flash con el azul Delta
   ───────────────────────────────────────────────────────────────
   Aplicar .fa-tabla-fila-flash a un <tr> hace 2 parpadeos suaves con el
   color primario (#4472c4). Después la clase se quita y la fila vuelve
   a su estado normal. JS controla el ciclo de vida.                       */
@keyframes fa-flash-fila {
  0% {
    background-color: transparent;
  }
  15% {
    background-color: rgba(68, 114, 196, 0.3);
  }
  35% {
    background-color: transparent;
  }
  55% {
    background-color: rgba(68, 114, 196, 0.3);
  }
  100% {
    background-color: transparent;
  }
}

.fa-tabla tbody tr.fa-tabla-fila-flash > td {
  animation: fa-flash-fila 1.6s ease-in-out;
  /* Borde izquierdo persistente para no perder la fila de vista */
  position: relative;
}

.fa-tabla tbody tr.fa-tabla-fila-flash > td:first-child {
  box-shadow: inset 3px 0 0 0 #4472c4;
}

/* Accesibilidad: usuarios con prefers-reduced-motion no ven la animación,
   pero igual marcamos la fila con fondo suave + borde izquierdo. Así la
   confirmación no se pierde sin movimiento.                              */
@media (prefers-reduced-motion: reduce) {
  .fa-tabla tbody tr.fa-tabla-fila-flash > td {
    animation: none;
    background-color: rgba(68, 114, 196, 0.1);
  }
}

/* Fila que abre su registro al hacer clic o Enter (p. ej. /coberturas). */
.fa-tabla tbody tr.fa-tabla-fila--navegable {
  cursor: pointer;
}

.fa-tabla tbody tr.fa-tabla-fila--navegable:hover > td,
.fa-tabla tbody tr.fa-tabla-fila--navegable:focus-visible > td {
  background: #f5f6fe;
}

.fa-tabla tbody tr.fa-tabla-fila--navegable:focus-visible {
  outline: 2px solid #4472c4;
  outline-offset: -2px;
}

/* ══════════════════════════════════════════════════════════════
   SWEETALERT2: tema Delta para los modales de éxito/error/confirmación
   ───────────────────────────────────────────────────────────────
   Aplicamos la clase .fa-swal vía customClass para no pisar otros usos.
   Cabecera con barra superior color, tipografía más limpia, botón con la
   forma de .fa-btn-accion del resto del sistema.                          */
.swal2-popup.fa-swal {
  border-radius: 14px;
  padding: 1.6rem 1.8rem 1.5rem;
  border-top: 4px solid var(--color-acento-fila, #4472c4);
  font-family: inherit;
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.03),
    0 14px 48px rgba(15, 27, 50, 0.18);
}

.swal2-popup.fa-swal.fa-swal--error {
  border-top-color: #d6336c;
}

.swal2-popup.fa-swal.fa-swal--warning {
  border-top-color: #e0a800;
}

.swal2-popup.fa-swal .swal2-title {
  font-size: 1.05rem;
  font-weight: 700;
  color: #252930;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin: 0.3rem 0 0.4rem;
  line-height: 1.3;
}

/* Foco visible al llegar por teclado (focusConfirm: true ya lo enfoca,
   aquí le damos un ring sutil con el azul Delta).                       */
.swal2-popup.fa-swal .swal2-confirm:focus-visible {
  outline: 3px solid rgba(68, 114, 196, 0.45);
  outline-offset: 2px;
}

.swal2-popup.fa-swal.fa-swal--error .swal2-confirm:focus-visible {
  outline-color: rgba(214, 51, 108, 0.45);
}

.swal2-popup.fa-swal .swal2-html-container,
.swal2-popup.fa-swal #swal2-html-container {
  font-size: 0.92rem;
  color: #5d6778;
  margin: 0.4rem 0 1.1rem;
  line-height: 1.45;
}

/* Mensajes de varios renglones (ej. los insumos sin datos de la sincronización,
   o el reparto de folios que cierra la corrida). `sincronizar_datos.js` los arma
   como un <div> por renglón —escapando cada uno, que el mensaje puede traer el
   texto de una excepción— y por eso van por `html:`. La alineación a la
   izquierda va en el modificador y no acá: una lista centrada queda ragged, pero
   un mensaje de una línea centrado se ve mejor, y el JS solo pone `--lista`
   cuando el texto trae saltos. Mismo criterio que .fa-alerta-folio-log.

   `pre-line` se conserva por si algún mensaje llega sin pasar por esa partición:
   con los <div> ya no hace falta para los saltos, pero tampoco estorba. */
.swal2-popup.fa-swal.fa-swal--lista .swal2-html-container,
.swal2-popup.fa-swal.fa-swal--lista #swal2-html-container {
  white-space: pre-line;
  text-align: left;
}

/* Renglón de VIÑETA: sangría colgante. El `padding-left` empuja el bloque entero
   y el `text-indent` negativo saca la viñeta de vuelta, así que la segunda línea
   de un renglón largo cae alineada con el texto en vez de volver al margen.

   Exige un bloque POR RENGLÓN, que es lo que arma el JS: `text-indent` aplica a
   la primera línea del bloque, y un salto preservado por `pre-line` no abre uno
   nuevo — con el mensaje como un solo bloque, la sangría alcanzaría únicamente a
   la primera línea de todo el mensaje. Por lo mismo la sangría vive acá y no
   como espacios dentro del texto: esos no sobreviven al `pre-line` ni saben nada
   del salto de línea. */
.swal2-popup.fa-swal.fa-swal--lista .fa-swal-linea--vineta {
  padding-left: 2.2em;
  text-indent: -1.1em;
}

/* Énfasis dentro del Swal: <em> resalta el nombre del registro (ej. cofactor).
   Italic + color más oscuro + peso medio para distinguirlo del texto base. */
.swal2-popup.fa-swal .swal2-html-container em,
.swal2-popup.fa-swal #swal2-html-container em {
  font-style: italic;
  font-weight: 600;
  color: #252930;
}

/* Desplegable de una sola opción dentro de un Swal (el corte a descargar de
   /reportes). El <select> nativo no hereda ni el borde ni el tipo de la app. */
.swal2-popup.fa-swal .fa-swal-select {
  width: 100%;
  box-sizing: border-box;
  padding: 0.55rem 0.7rem;
  background: #fff;
  border: 1px solid #c8cdd6;
  border-radius: 6px;
  font-size: 0.9rem;
  color: #252930;
}

.swal2-popup.fa-swal .fa-swal-select:focus {
  outline: none;
  border-color: #4472c4;
}

/* Alerta "Folio Fiscal no coincide": el contenido es un log de facturas,
   no un mensaje centrado. Alineamos a la izquierda y quitamos las viñetas
   para que cada factura se lea como una entrada de log. Scope acotado a
   .fa-alerta-folio-log para no descentrar el resto de los Swal. */
.fa-alerta-folio-log {
  text-align: left;
}

.fa-alerta-folio-lista {
  list-style: none;
  margin: 0;
  padding: 0;
}

.fa-alerta-folio {
  margin-bottom: 0.6rem;
}

.fa-alerta-folio:last-child {
  margin-bottom: 0;
}

/* UUID largo (36 chars): que corte y no desborde el ancho del popup. */
.fa-alerta-folio code {
  word-break: break-all;
}

/* No tocamos width/height del .swal2-icon: SweetAlert2 calcula las
   coordenadas internas del check/cruz/exclamación para 80x80 con
   position:absolute. Si lo achicábamos las líneas quedaban descolocadas.
   En su lugar usamos transform: scale() para reducir manteniendo proporciones. */
.swal2-popup.fa-swal .swal2-icon {
  margin: 0.4rem auto 1rem;
  transform: scale(0.75);
  transform-origin: center center;
}

.swal2-popup.fa-swal .swal2-icon.swal2-success {
  border-color: var(--color-acento-fila, #4472c4);
  color: var(--color-acento-fila, #4472c4);
}

.swal2-popup.fa-swal .swal2-icon.swal2-success .swal2-success-ring {
  border-color: rgba(68, 114, 196, 0.3);
}

.swal2-popup.fa-swal .swal2-icon.swal2-success [class^="swal2-success-line"] {
  background-color: var(--color-acento-fila, #4472c4);
}

.swal2-popup.fa-swal .swal2-icon.swal2-error {
  border-color: #d6336c;
  color: #d6336c;
}

.swal2-popup.fa-swal .swal2-icon.swal2-error [class^="swal2-x-mark-line"] {
  background-color: #d6336c;
}

.swal2-popup.fa-swal .swal2-icon.swal2-warning {
  border-color: #e0a800;
  color: #e0a800;
}

.swal2-popup.fa-swal .swal2-actions {
  gap: 0.6rem;
  margin-top: 0.4rem;
}

.swal2-popup.fa-swal .swal2-confirm,
.swal2-popup.fa-swal .swal2-deny,
.swal2-popup.fa-swal .swal2-cancel {
  border-radius: 8px !important;
  padding: 0.55rem 1.2rem !important;
  font-size: 0.85rem !important;
  font-weight: 600 !important;
  letter-spacing: 0.02em !important;
  box-shadow: none !important;
  border: none !important;
}

.swal2-popup.fa-swal .swal2-confirm {
  background: #1a1a1a !important;
}

.swal2-popup.fa-swal .swal2-confirm:hover,
.swal2-popup.fa-swal .swal2-confirm:focus {
  background: #333333 !important;
}

.swal2-popup.fa-swal.fa-swal--error .swal2-confirm {
  background: #d6336c !important;
}

.swal2-popup.fa-swal.fa-swal--error .swal2-confirm:hover {
  background: #b8275c !important;
}

.swal2-popup.fa-swal .swal2-cancel {
  background: #ffffff !important;
  color: #5d6778 !important;
  border: 1px solid #e0e3e8 !important;
}

.swal2-popup.fa-swal .swal2-cancel:hover {
  background: #f5f6fe !important;
}

/* Variante "exportar" (tabla_exportar_columnas.js): «Columnas seleccionadas» y
   «Todas las columnas» son dos opciones del mismo peso, así que el denyButton
   va igual que el confirm y no con el rojo de SweetAlert, que lo leería como
   una acción destructiva. */
.swal2-popup.fa-swal.fa-swal--exportar .swal2-deny {
  background: #1a1a1a !important;
  color: #ffffff !important;
}

.swal2-popup.fa-swal.fa-swal--exportar .swal2-deny:hover,
.swal2-popup.fa-swal.fa-swal--exportar .swal2-deny:focus {
  background: #333333 !important;
}

/* Variante "revalidar" (avisos de la validación SAT y de la carga de CFDI):
   botón de confirmación azul Delta en vez del negro por defecto. Borde
   superior azul (heredado de .fa-swal). */
.swal2-popup.fa-swal.fa-swal--revalidar .swal2-confirm {
  background: var(--color-acento-fila, #4472c4) !important;
  color: #ffffff !important;
}

.swal2-popup.fa-swal.fa-swal--revalidar .swal2-confirm:hover,
.swal2-popup.fa-swal.fa-swal--revalidar .swal2-confirm:focus {
  background: #375ba3 !important;
}

/* Variante "disponer" (Paso 4): el confirmButton "Disponer" del diálogo
   de confirmación usa el MISMO navy que el botón "Disponer" del header
   del panel (.fa-btn-accion → #012e92) para que ambos se vean iguales a
   lo largo del flujo. El cancelButton "Revisar" sigue siendo blanco con
   borde (mismo estilo que el cancel por defecto de fa-swal). */
.swal2-popup.fa-swal.fa-swal--disponer .swal2-confirm {
  background: #012e92 !important;
  color: #ffffff !important;
}

.swal2-popup.fa-swal.fa-swal--disponer .swal2-confirm:hover,
.swal2-popup.fa-swal.fa-swal--disponer .swal2-confirm:focus {
  background: #023ab5 !important;
}

/* Backdrop más sutil para no apagar la pantalla por completo */
.swal2-backdrop-show.fa-swal-backdrop {
  background: rgba(15, 27, 50, 0.42);
}

/* ══════════════════════════════════════════════════════════════
   COLUMNA DE ACCIONES EN TABLAS (/clientes y /disposiciones)
   ──────────────────────────────────────────────────────────────
   Última columna fija de cada listado.
   - Modo legacy (Ver + Editar): dos íconos lado a lado → 72px
   - Modo kebab (tres puntitos): un solo botón → 36px (ancho mínimo,
     que era el pedido explícito de Pedro)
   El selector --kebab reduce la columna sólo cuando la celda contiene
   un dropdown kebab, así no afecta a /clientes que sigue con dos íconos.
   ══════════════════════════════════════════════════════════════ */
.fa-tabla-wrapper--scroll .fa-tabla th.fa-tabla-th-acciones,
.fa-tabla-wrapper--scroll .fa-tabla td.fa-tabla-td-acciones {
  width: 45px;
  min-width: 45px;
  max-width: 45px;
  text-align: center;
  cursor: default;
  white-space: nowrap;
  overflow: visible;
  padding-left: 0.25rem;
  padding-right: 0.25rem;
}

/* Columna de acciones cuando contiene un kebab (un solo botón).
   Detectamos la presencia del kebab con :has() — si no está soportado
   en algún browser viejo, la columna queda con el ancho legacy (72px),
   que sigue siendo aceptable. */
.fa-tabla-wrapper--scroll
  .fa-tabla
  tbody
  td.fa-tabla-td-acciones:has(.fa-tabla-acciones--kebab) {
  width: 36px;
  min-width: 36px;
  max-width: 36px;
  padding-left: 0;
  padding-right: 0;
}

/* Si en el thead hay un kebab en cualquier fila, encogemos también el th.
   Como el th no "sabe" del contenido de la columna, usamos :has() sobre
   la propia tabla. */
.fa-tabla-wrapper--scroll
  .fa-tabla:has(td.fa-tabla-td-acciones .fa-tabla-acciones--kebab)
  th.fa-tabla-th-acciones {
  width: 36px;
  min-width: 36px;
  max-width: 36px;
  padding-left: 0;
  padding-right: 0;
}

.fa-tabla-wrapper--scroll .fa-tabla th.fa-tabla-th-acciones {
  cursor: default;
}

.fa-tabla-acciones {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
}

.fa-tabla-acciones-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 6px;
  color: #9fa7b5;
  background: transparent;
  border: none;
  cursor: pointer;
  text-decoration: none;
  font-size: 0.85rem;
  transition:
    color 0.15s ease,
    background-color 0.15s ease;
}

.fa-tabla-acciones-btn:hover,
.fa-tabla-acciones-btn:focus {
  background: rgba(68, 114, 196, 0.1);
  color: var(--color-acento-fila, #4472c4);
  text-decoration: none;
  outline: none;
}

.fa-tabla-acciones-btn--editar:hover,
.fa-tabla-acciones-btn--editar:focus {
  background: rgba(214, 51, 108, 0.1);
  color: #d6336c;
}

/* ══════════════════════════════════════════════════════════════
   MODO VER (solo lectura) DENTRO DEL FORM
   ──────────────────────────────────────────────────────────────
   En modo "ver", los inputs/selects se muestran como texto con un sutil
   borde inferior — visualmente más compactos, sin chrome de input. */
.fa-form--ver .fa-form-control,
.fa-form-control.fa-form-control--lectura {
  background: transparent !important;
  border: none !important;
  border-bottom: 1px solid #f0f1f4 !important;
  border-radius: 0 !important;
  padding: 0.35rem 0 !important;
  min-height: 32px;
  color: #252930;
  font-weight: 600;
  cursor: default;
  pointer-events: none;
}

.fa-form--ver textarea.fa-form-control,
textarea.fa-form-control.fa-form-control--lectura {
  min-height: 60px;
  resize: none;
}

.fa-form--ver select.fa-form-control,
select.fa-form-control.fa-form-control--lectura {
  background-image: none !important;
  padding-right: 0 !important;
}

.fa-form--ver .fa-form-hint,
.fa-form--ver .fa-form-feedback {
  display: none;
}

/* ══════════════════════════════════════════════════════════════
   CAMPOS PK BLOQUEADOS EN MODO EDITAR
   ──────────────────────────────────────────────────────────────
   En modo "editar", la PK (comprador, vendedor, cofactor) se muestra
   readonly. Visualmente distingue del resto por fondo y badge. */
.fa-form-control[readonly].fa-form-control--pk {
  background: #f5f6fe;
  color: #5d6778;
  cursor: not-allowed;
}

.fa-form-pk-badge {
  display: inline-block;
  background: #eef0f5;
  color: #5d6778;
  font-size: 0.65rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 0.1rem 0.45rem;
  border-radius: 4px;
  margin-left: 0.4rem;
}

/* ══════════════════════════════════════════════════════════════
   BOTÓN DE ELIMINAR DENTRO DEL FORM EDITAR
   ────────────────────────────────────────────────────────────── */
.fa-btn-eliminar {
  margin-right: auto;
  background: #ffffff;
  color: #d6336c;
  border: 1px solid #f5c6cb;
  border-radius: 8px;
  padding: 0.5rem 1.1rem;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  transition:
    background-color 0.15s ease,
    border-color 0.15s ease;
}

.fa-btn-eliminar:hover,
.fa-btn-eliminar:focus {
  background: #fdecea;
  border-color: #d6336c;
  color: #a02020;
  outline: none;
}

/* Botón "Editar" en el header de la vista Ver — pegado a la ×.
   Usa el mismo look pequeño que .fa-btn-accion pero menos prominente. */
.fa-form-header-editar {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  background: #1a1a1a;
  color: #ffffff;
  border: none;
  border-radius: 8px;
  padding: 0.45rem 0.95rem;
  font-size: 0.8rem;
  font-weight: 600;
  text-decoration: none;
  letter-spacing: 0.02em;
  cursor: pointer;
  position: absolute;
  top: 1rem;
  right: 3.4rem; /* a la izquierda de la × (32px botón + 1rem offset + gap) */
  transition: background-color 0.15s ease;
}

.fa-form-header-editar:hover,
.fa-form-header-editar:focus {
  background: #333333;
  color: #ffffff;
  text-decoration: none;
  outline: none;
}

/* Botón "Editar" dentro del fa-form-body, arriba a la derecha.
   Mismo layout que el del header pero blanco con borde. */
.fa-form-body-editar {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  background: #ffffff;
  color: #252930;
  border: 1.5px solid #d0d4db;
  border-radius: 8px;
  padding: 0.5rem 1.1rem;
  font-size: 0.82rem;
  font-weight: 600;
  text-decoration: none;
  letter-spacing: 0.03em;
  cursor: pointer;
  position: absolute;
  top: 1rem;
  right: 2.25rem;
  box-shadow:
    0 1px 3px rgba(15, 27, 50, 0.08),
    0 1px 2px rgba(15, 27, 50, 0.04);
  transition:
    background-color 0.15s ease,
    border-color 0.15s ease,
    box-shadow 0.15s ease;
}

/* «Historial de cambios» + «Editar» de la vista de detalle: el contenedor toma
   la posición absoluta que el botón «Editar» tiene cuando va solo. */
.fa-form-body-acciones {
  position: absolute;
  top: 1rem;
  right: 2.25rem;
  display: flex;
  gap: 0.5rem;
}

.fa-form-body-acciones .fa-form-body-editar {
  position: static;
}

.fa-form-body-editar i {
  color: #4472c4;
  font-size: 0.85rem;
}

.fa-form-body-editar:hover,
.fa-form-body-editar:focus {
  background: #f5f6fe;
  border-color: #b0b8c8;
  color: #252930;
  text-decoration: none;
  outline: none;
  box-shadow:
    0 2px 6px rgba(15, 27, 50, 0.1),
    0 1px 3px rgba(15, 27, 50, 0.06);
}

/* Tabla — acciones modo kebab (dropdown Bootstrap 5) */

.fa-tabla-acciones--kebab {
  position: relative;
  display: inline-flex;
}

.fa-tabla-acciones-kebab {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 6px;
  background: transparent;
  border: none;
  color: #9fa7b5;
  font-size: 1rem;
  cursor: pointer;
  transition:
    color 0.15s ease,
    background-color 0.15s ease;
}

.fa-tabla-acciones-kebab:hover,
.fa-tabla-acciones-kebab[aria-expanded="true"] {
  background: #f5f6fe;
  color: #1a1a1a;
}

/* Foco por teclado: outline explícito (WCAG). :focus-visible evita
 * que aparezca con click de mouse, solo con navegación por teclado. */
.fa-tabla-acciones-kebab:focus-visible {
  outline: 2px solid #4472c4;
  outline-offset: 1px;
  background: #f5f6fe;
  color: #1a1a1a;
}

/* Override Bootstrap .dropdown-menu para alinearlo con paneles fa-* */
.fa-tabla-acciones-menu.dropdown-menu {
  border: 1px solid #e7e9ed;
  border-radius: 8px;
  padding: 0.25rem 0;
  min-width: 160px;
  margin: 0.25rem 0 0;
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.04),
    0 2px 8px rgba(0, 0, 0, 0.06),
    0 8px 24px rgba(0, 0, 0, 0.08);
  font-size: 0.85rem;
  background: #ffffff;
}

.fa-tabla-acciones-item.dropdown-item {
  padding: 0.5rem 0.85rem;
  color: #252930;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  text-decoration: none;
}

.fa-tabla-acciones-item.dropdown-item:hover,
.fa-tabla-acciones-item.dropdown-item:focus {
  background: var(--color-hover-gris);
  color: #252930;
}

/* Estado activo (se mantiene seleccionado por teclado o tras click): mismo
   gris suave, no negro. Bootstrap aplica .active al item enfocado por
   keyboard arrow navigation. */
.fa-tabla-acciones-item.dropdown-item.active,
.fa-tabla-acciones-item.dropdown-item:active {
  background: var(--color-hover-gris);
  color: #252930;
}

.fa-tabla-acciones-item .fa-solid,
.fa-tabla-acciones-item .fa-regular {
  font-size: 0.85rem;
  width: 1rem;
  text-align: center;
  color: inherit;
}

/* Página de estatus de disposición — header + timeline + panel.
 * (responsive: colapsa a vertical en <800px)
 *
 * Fondo blanco a toda la página (igual que /disposiciones, /clientes). */
html:has(body.fa-pagina-estatus),
html:has(body.fa-pagina-editar) {
  background-color: #ffffff;
}

body.fa-pagina-estatus.app,
body.fa-pagina-editar.app {
  background-color: #ffffff !important;
}

.fa-pagina-estatus .app-wrapper,
.fa-pagina-estatus .app-content,
.fa-pagina-estatus .app-content > .container-xl,
.fa-pagina-estatus .app-footer,
.fa-pagina-estatus .app-footer .container,
.fa-pagina-editar .app-wrapper,
.fa-pagina-editar .app-content,
.fa-pagina-editar .app-content > .container-xl,
.fa-pagina-editar .app-footer,
.fa-pagina-editar .app-footer .container {
  background-color: #ffffff;
}

.fa-pagina-estatus .container-xl {
  max-width: 1180px;
}

.fa-estatus-wrapper {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  padding: 0 0 2rem;
}

/* El footer siempre abajo
   .app-wrapper crece solo lo que crece su contenido, con pocas
   facturas el footer se queda a media pantalla. Lo convertimos
   a una columna flex que llena el alto visible (56px mide el header)
   y dejamos que .app-content absorba el sobrante. */
.fa-pagina-estatus .app-wrapper {
  display: flex;
  flex-direction: column;
  min-height: calc(100vh - 56px);
}

.fa-pagina-estatus .app-content {
  flex: 1 0 auto;
}

/* ── Header de identificación ─────────────────────────────── */
/* Header de identificación: padding superior leve para respirar,
   tipografías un toque más grandes para ganar peso. Border-bottom
   más grueso y más oscuro para separar con autoridad del timeline. */
.fa-estatus-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 1.5rem;
  padding: 0.5rem 0 clamp(0.75rem, 2vw, 1rem);
  border-bottom: 1px solid #e7e9ed;
  flex-wrap: wrap;
}

.fa-estatus-header-titulo {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}

.fa-estatus-header-eyebrow {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: #9fa7b5;
  line-height: 1;
}

.fa-estatus-header-h1 {
  font-size: clamp(1.25rem, 1rem + 1vw, 1.55rem);
  font-weight: 800;
  color: #1a1a1a;
  margin: 0;
  line-height: 1.15;
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.5rem;
}

/* Número de factura: peso máximo, color negro — hereda del h1. */
.fa-estatus-header-factura {
  font-weight: 800;
}

/* Separador entre factura y comprador. Gris claro para no competir
   con los dos identificadores. */
.fa-estatus-header-sep {
  color: #c8cdd6;
  font-weight: 400;
}

/* Comprador: misma línea que la factura pero un peso menos para
   jerarquía visual. La factura sigue siendo el identificador primario. */
.fa-estatus-header-comprador {
  font-weight: 600;
  color: #252930;
}

/* Flexbox en vez de grid: cada tarjeta de metadato se ancha lo que
   necesite y envuelve sola en pantallas chicas — sin puntos de quiebre
   fijos en grid-template-columns por resolución. */
.fa-estatus-header-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem clamp(1.1rem, 3vw, 1.85rem);
  margin: 0;
  align-items: end;
}

.fa-estatus-header-meta-item {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 6rem;
}

.fa-estatus-header-meta dt {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: #9fa7b5;
  margin: 0;
  line-height: 1;
}

.fa-estatus-header-meta dd {
  font-size: 0.95rem;
  font-weight: 600;
  color: #252930;
  margin: 0;
  line-height: 1.2;
}

/* ── Timeline (5 pasos horizontales) ──────────────────────── */
/* Timeline de 10 pasos. Cada paso es un link clickeable al mismo URL
   con ?paso=N. El estado del paso (completado/disabled) no cambia al
   navegar; sólo cambia cuál está --seleccionado. */
.fa-timeline {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 0;
  list-style: none;
  padding: 1.25rem 0.5rem 0.5rem;
  margin: 0;
}

.fa-timeline-paso {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  /* Separación del conector respecto al centro de cada círculo. Son
	   variables (no valores fijos) porque el paso seleccionado agranda su
	   círculo y su ripple: ahí hay que retirar la línea unos píxeles más
	   para que no quede tapada. `inicio` = lado del círculo propio,
	   `fin` = lado del círculo del paso siguiente. */
  --fa-conector-inicio: 22px;
  --fa-conector-fin: 22px;
}

/* El link envuelve círculo + título. Cubre todo el ancho del paso
   para que la zona clickeable sea generosa (Fitts). */
.fa-timeline-paso-link {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.55rem;
  padding: 0.3rem 0.25rem;
  text-decoration: none;
  color: inherit;
  border-radius: 8px;
  transition: background-color 0.15s ease;
}

.fa-timeline-paso-link:hover {
  text-decoration: none;
}

/* Hover sobre un paso (que no sea el seleccionado): el círculo crece y
   muestra el mismo ripple de anillos translúcidos como preview, en vez
   del recuadro gris de fondo. Alphas un poco más suaves que el estado
   seleccionado (0.28 → 0.15 → 0.07) porque es un estado transitorio.
   El `transition: all 0.15s` del círculo base anima scale + box-shadow. */
.fa-timeline-paso:not(.fa-timeline-paso--seleccionado)
  .fa-timeline-paso-link:hover
  .fa-timeline-circulo {
  transform: scale(1.12);
  border-color: transparent;
  /* Gris del sistema (#9fa7b5): los pasos sin estatus son grises, así
	   que su preview de hover también — el azul Delta desentonaba con
	   la escala verde/ámbar/rojo/gris del timeline. */
  box-shadow:
    0 0 0 3px rgba(159, 167, 181, 0.32),
    0 0 0 6px rgba(159, 167, 181, 0.17),
    0 0 0 9px rgba(159, 167, 181, 0.08);
}

/* Paso completado en hover → ripple verde (mismo verde bosque del
   círculo) para no mezclar azul con el relleno verde. Va después de la
   regla genérica para ganarle en orden de cascada (misma especificidad). */
.fa-timeline-paso--completado:not(.fa-timeline-paso--seleccionado)
  .fa-timeline-paso-link:hover
  .fa-timeline-circulo {
  box-shadow:
    0 0 0 3px rgba(22, 163, 74, 0.28),
    0 0 0 6px rgba(22, 163, 74, 0.15),
    0 0 0 9px rgba(22, 163, 74, 0.07);
}

/* Paso con semáforo en hover → ripple del color del veredicto (verde /
   ámbar / rojo), no el azul genérico. Una clase más de especificidad
   que la regla genérica del hover azul → gana. Mismos alphas suaves
   que el hover de completado (estado transitorio). */
.fa-timeline-paso:not(.fa-timeline-paso--seleccionado)
  .fa-timeline-paso-link:hover
  .fa-timeline-circulo.fa-timeline-circulo--sem-1 {
  box-shadow:
    0 0 0 3px rgba(22, 163, 74, 0.28),
    0 0 0 6px rgba(22, 163, 74, 0.15),
    0 0 0 9px rgba(22, 163, 74, 0.07);
}

.fa-timeline-paso:not(.fa-timeline-paso--seleccionado)
  .fa-timeline-paso-link:hover
  .fa-timeline-circulo.fa-timeline-circulo--sem-2 {
  box-shadow:
    0 0 0 3px rgba(217, 119, 6, 0.32),
    0 0 0 6px rgba(217, 119, 6, 0.17),
    0 0 0 9px rgba(217, 119, 6, 0.08);
}

.fa-timeline-paso:not(.fa-timeline-paso--seleccionado)
  .fa-timeline-paso-link:hover
  .fa-timeline-circulo.fa-timeline-circulo--sem-0 {
  box-shadow:
    0 0 0 3px rgba(220, 38, 38, 0.28),
    0 0 0 6px rgba(220, 38, 38, 0.15),
    0 0 0 9px rgba(220, 38, 38, 0.07);
}

.fa-timeline-paso-link:focus-visible {
  outline: 2px solid var(--color-acento-fila);
  outline-offset: 2px;
}

/* Conector horizontal entre círculos. El selector ::after del paso
   (no del link) lo mantiene sobre la fila de círculos.
   La línea es continua de punta a punta: el color "desde" domina el
   primer tercio, el color "hasta" el último, y el tramo central es un
   degradado suave entre ambos — así el ojo sigue el trazo de un paso
   al otro sin el corte transparente que había antes.
   `--fa-conector-desde`/`--fa-conector-hasta` los
   inyecta el macro `timeline_pasos()` por <li> (color del semáforo de
   cada paso) y los repinta en vivo `facturasEstatusPintarPaso()`
   (facturas_estatus_circulo.js) — el fallback a `--fa-sem-gris-600`
   cubre el primer render antes de que el JS corra o cuando el paso no
   tiene semáforo. Reemplaza las reglas previas de
   `--completado::after` (verde sólido) y `--disabled::after`
   (punteado): ambas quedan superseded por este único gradiente, que
   ahora comunica el color EXACTO del paso (no solo completado/no). */
.fa-timeline-paso::after {
  content: "";
  position: absolute;
  /* Centro del círculo = padding-top del link (0.3rem ≈ 4.8px) + radio
	   del círculo de 28px (14px) ≈ 18.8px. La línea es de 2px, así que
	   top = ~18px deja su centro en ~19px, alineado al centro del círculo
	   (antes estaba en 23px → caía ~5px por debajo). */
  top: 18px;
  left: calc(50% + var(--fa-conector-inicio));
  width: calc(100% - var(--fa-conector-inicio) - var(--fa-conector-fin));
  height: 2px;
  background: linear-gradient(
    to right,
    var(--fa-conector-desde, var(--fa-sem-gris-600)) 0% 32%,
    var(--fa-conector-hasta, var(--fa-sem-gris-600)) 68% 100%
  );
  /* Acompaña el scale del círculo al cambiar de paso seleccionado:
	   la línea se recoge/estira con la misma duración (0.15s). */
  transition:
    left 0.15s ease,
    width 0.15s ease;
  /* Punta afinada en los dos extremos (0%/100% → un punto, no un
     borde recto) y grosor completo en el tramo central (6%-94%):
     el trazo de 2px se lee como una línea más elegante que un
     rectángulo plano, sin afectar el split de color del gradiente. */
  clip-path: polygon(0% 50%, 6% 0%, 94% 0%, 100% 50%, 94% 100%, 6% 100%);
  z-index: 0;
  pointer-events: none;
}

.fa-timeline-paso:last-child::after {
  display: none;
}

/* El paso seleccionado crece (scale 1.1 ≈ 31 px) y suma un ripple de
   hasta 11 px de radio extra: el conector quedaba pisado por debajo.
   Se recoge la línea 8 px de cada lado del círculo seleccionado — el
   suyo (`inicio`) y el del paso previo, que llega a él (`fin`). */
.fa-timeline-paso--seleccionado {
  --fa-conector-inicio: 30px;
}

.fa-timeline-paso:has(+ .fa-timeline-paso--seleccionado) {
  --fa-conector-fin: 30px;
}

/* Círculo: tamaño reducido (28px en lugar de 36px) para acomodar 10 pasos. */
.fa-timeline-circulo {
  position: relative;
  z-index: 1;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.75rem;
  font-weight: 700;
  background: #f5f6fe;
  border: 2px solid #e7e9ed;
  color: #9fa7b5;
  flex-shrink: 0;
  transition: all 0.15s ease;
}

.fa-timeline-numero {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

.fa-timeline-titulo {
  font-size: 0.68rem;
  /* 500: solo el paso seleccionado va en negritas (800) — la jerarquía
	   selección/resto se lee por peso, no solo por color. */
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #9fa7b5;
  text-align: center;
  line-height: 1.2;
  transition: transform 0.15s ease;
}

/* Estado completado: círculo verde, check blanco, conector verde.
   Verde `#16a34a` (green-600 escala Tailwind): verde bosque sobrio que
   tiene el mismo peso visual que el negro `#1a1a1a` del sistema. Se
   diferencia a propósito del `#2ecc71` del semáforo de comprador:
   aquel es un indicador chico (8 px) donde el verde vibrante se lee
   bien; este es un círculo de 28 px + conector largo que requiere un
   verde más sobrio para no gritar al lado del resto del sistema. */
.fa-timeline-paso--completado .fa-timeline-circulo {
  background: #16a34a;
  border-color: #16a34a;
  color: #ffffff;
}

/* El número del paso se mantiene visible aunque el paso esté completado:
   el estado ya se lee por el color del círculo y por el conector relleno.
   Nota: el conector propio de este estado (antes background verde sólido
   en ::after) quedó superseded por el gradiente único de
   `.fa-timeline-paso::after` — ver esa regla. */
.fa-timeline-paso--completado .fa-timeline-titulo {
  color: #252930;
}

/* Estado disabled: cursor not-allowed sobre el link.
   El link sigue siendo navegable — cargamos la página vacía ("en desarrollo")
   para que el usuario pueda ver el paso futuro.
   Nota: el conector punteado que tenía este estado (::after) quedó
   superseded por el gradiente único de `.fa-timeline-paso::after` —
   ver esa regla (color "desde"/"hasta" caen a --fa-sem-gris-600 por
   default cuando el paso no tiene semáforo, mismo tono neutro que
   usaba el punteado). */
.fa-timeline-paso--disabled .fa-timeline-paso-link {
  cursor: pointer;
}

/* Estado seleccionado (el paso que estás viendo en el panel inferior):
   halo de color según estado + leve escalado + sin border. El indicador
   de foco es el halo + el scale, no un anillo sólido. La elección de
   color es semántica:
     - Completado seleccionado → halo verde (mismo verde del círculo).
     - Cualquier otro seleccionado → halo azul Delta.
   El border desaparece (transparent) para que solo halo y escala
   comuniquen "estoy parado en este paso". El transition de all 0.15s
   del círculo base anima el scale al cambiar de paso. */
/* Reglas comunes del seleccionado — sin border + escalado suave.
   scale(1.12) ≈ 31 px efectivos: mantiene jerarquía visual con el resto
   (28 px) sin gritar. Bajado de 1.25 (35 px) por consulta a Raven —
   Fitts + Von Restorff cubiertos con esta diferencia. */
.fa-timeline-paso--seleccionado .fa-timeline-circulo {
  border-color: transparent;
  transform: scale(1.1);
}

/* El seleccionado también reacciona al hover: crece un poquito más
   (1.1 → 1.16) conservando su ripple, para dar feedback de "te paraste
   encima" aunque ya sea el paso activo. Más específica que la regla
   base del seleccionado, así gana el transform en hover. */
.fa-timeline-paso--seleccionado
  .fa-timeline-paso-link:hover
  .fa-timeline-circulo {
  transform: scale(1.16);
}

/* Disabled + seleccionado: ripple natural — círculo central sólido +
   3 anillos translúcidos del MISMO gris del sistema (`#9fa7b5`), cada
   uno más grueso y más claro hacia afuera. Un solo tono que se aclara
   por capas se lee como ondas concéntricas reales. Sin anillo de
   sello: el `background` sólido pinta bajo el border transparente,
   así que el centro fluye directo al primer anillo sin línea de
   borde. */
.fa-timeline-paso--seleccionado.fa-timeline-paso--disabled
  .fa-timeline-circulo {
  /* Gris del sistema, más saturado que el hover (estado persistente).
	   El azul Delta desentonaba con la escala de color del timeline. */
  box-shadow:
    0 0 0 3px rgba(159, 167, 181, 0.45),
    0 0 0 7px rgba(159, 167, 181, 0.22),
    0 0 0 11px rgba(159, 167, 181, 0.1);
}

/* Solo cuando el paso seleccionado NO tiene estatus (sem-na): centro
   blanco + número en gris de texto, para que el centro dialogue con
   los anillos grises del ripple. Los círculos con semáforo conservan
   su relleno (verde/ámbar/rojo). */
.fa-timeline-paso--seleccionado.fa-timeline-paso--disabled
  .fa-timeline-circulo.fa-timeline-circulo--sem-na {
  background: #ffffff;
  color: #252930;
}

/* Completado + seleccionado: mismo ripple en verde bosque
   (`#16a34a`). Centro sólido + 3 anillos translúcidos del mismo
   verde, cada vez más claros (0.40 → 0.20 → 0.09). Sin saltos de
   tono ni anillo de sello: el efecto natural sale de aclarar el
   alpha por capa. */
.fa-timeline-paso--seleccionado.fa-timeline-paso--completado
  .fa-timeline-circulo {
  box-shadow:
    0 0 0 3px rgba(22, 163, 74, 0.4),
    0 0 0 7px rgba(22, 163, 74, 0.2),
    0 0 0 11px rgba(22, 163, 74, 0.09);
}

.fa-timeline-paso--seleccionado .fa-timeline-titulo {
  color: #1a1a1a;
  font-weight: 800;
  transform: translateY(3px);
}

/* Seleccionado (completado o no): siempre negro + negritas. El estado
   del paso lo comunica el círculo; el título marca DÓNDE estás parado. */

/* El título baja un poquito también en hover (mismo gesto que el
   seleccionado), acompañando el crecimiento del círculo. */
.fa-timeline-paso-link:hover .fa-timeline-titulo {
  transform: translateY(3px);
}

/* ── Panel inferior del paso activo ───────────────────────── */
.fa-estatus-panel {
  background: #ffffff;
  border-radius: 18px;
  padding: 1.5rem 1.75rem;
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.04),
    0 2px 8px rgba(0, 0, 0, 0.04),
    0 8px 24px rgba(0, 0, 0, 0.06);
}

.fa-estatus-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  border-bottom: 1px solid #f0f1f4;
  padding-bottom: 0.85rem;
  margin-bottom: 0.5rem;
}

/* Acciones del paso agrupadas a la derecha (contenedor propio: evita que el
   space-between del header reparta cada botón por el ancho). */
.fa-estatus-panel-acciones {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-left: auto;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.fa-estatus-panel-titulo {
  font-size: 1rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: #252930;
  margin: 0;
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
}

.fa-estatus-panel-body {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.fa-panel-seccion {
  margin-top: 1rem;
}

.fa-panel-seccion:first-child {
  margin-top: 0.5rem;
}

/* Subtítulo de sección: azul Delta con barra lateral (opción C).
   El margen inferior (1.2rem) más el margin-top del grid (0.5rem) dan los
   mismos 1.7rem que separan un subgrupo de otro: así el título se lee como
   un salto de sección y no como el label de la primera fila de campos. */
.fa-panel-seccion-titulo {
  font-size: 0.85rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--color-acento-fila);
  margin: 0 0 1.2rem;
  padding: 0 0 0 0.6rem;
  border-left: 3px solid var(--color-acento-fila);
}

/* Subgrupos temáticos dentro de una sección (identificación,
   condiciones financieras, WB…): SIN subtítulos — el agrupamiento lo
   comunica solo el ESPACIO. La separación entre grupos (1.7rem) debe
   ser claramente mayor que la separación entre filas del grid (0.7rem)
   para que el chunk se lea sin etiquetas. */
.fa-panel-seccion--sub {
  margin-top: 1.7rem;
}

/* Comentarios: texto libre a ancho completo, una sola columna. */
.fa-seccion-comentarios .fa-panel-seccion-grid {
  grid-template-columns: 1fr;
}

/* 3 columnas en desktop (unificado con la fila de partes del resumen);
   2/1 columnas en pantallas chicas según los media queries de abajo. */
.fa-panel-seccion-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.7rem 1.25rem;
  margin-top: 0.5rem;
}

/* Panel vacío: para los pasos 2–10 (aún no implementados). Centrado,
   icono grande tenue + texto explicativo — invita a esperar sin dar
   la sensación de error. */
.fa-estatus-panel-vacio {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 3rem 1.5rem;
  gap: 0.5rem;
  color: #9fa7b5;
}

.fa-estatus-panel-vacio-icono {
  font-size: 2.5rem;
  color: #c8cdd6;
  margin-bottom: 0.5rem;
}

.fa-estatus-panel-vacio-titulo {
  font-size: 1rem;
  font-weight: 700;
  color: #252930;
  margin: 0;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.fa-estatus-panel-vacio-texto {
  font-size: 0.875rem;
  color: #5d6778;
  margin: 0;
  max-width: 420px;
  line-height: 1.5;
}

/* ── Editar disposición ──────────────────────────────────── */
/* Pantalla /disposiciones/<id>/<fact>/editar. Reusa header + panel +
   secciones del template `estatus.html`; sólo agrega inputs editables
   y la fila de acciones (Cancelar / Guardar) en el header del panel. */
.fa-editar-flashes {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-top: 0.25rem;
}

/* Input mínimo, coherente con .fa-campo-readonly. Sólo border-bottom
   para que se integre con el grid de la sección sin meter chrome de
   caja completa. Foco usa el azul de marca. */
.fa-campo-input {
  width: 100%;
  font-size: 0.9rem;
  font-weight: 600;
  color: #252930;
  background: transparent;
  border: none;
  border-bottom: 1px solid #e7e9ed;
  border-radius: 0;
  padding: 0.3rem 0;
  margin-top: 0.1rem;
  transition: border-color 0.15s ease;
  font-family: inherit;
}

.fa-campo-input:focus {
  outline: none;
  border-bottom-color: var(--color-marca);
}

.fa-campo-input::placeholder {
  color: #c8cdd6;
  font-weight: 400;
}

/* Textarea: sí lleva borde de caja porque crece verticalmente y el
   border-bottom solo se vería raro. */
.fa-campo-input--textarea {
  border: 1px solid #e7e9ed;
  border-radius: 6px;
  padding: 0.4rem 0.6rem;
  resize: vertical;
  min-height: 2.4rem;
  line-height: 1.4;
}

.fa-campo-input--textarea:focus {
  border-color: var(--color-marca);
  border-bottom-color: var(--color-marca);
}

/* Barra de destinatarios estilo Outlook: botones "Para" / "CC" del mismo
   tamaño en un solo renglón, con el valor al lado. Sin funcionalidad aún. */
.fa-correo-dest {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.3rem 0;
}

/* min-width igual para que "Para" y "CC" queden del mismo ancho pese al
   texto distinto (el base .fa-btn-icono ya centra el contenido).
   Selector con 2 clases (.fa-correo-dest .fa-correo-btn-dest) para ganarle
   por especificidad a .fa-btn-icono, que se define después en este archivo
   y si no sobrescribía font-size/padding. */
.fa-correo-dest .fa-correo-btn-dest {
  min-width: 3.5rem;
  font-size: 0.85rem;
  padding: 0.45rem 0.9rem;
}

/* La línea arranca después del botón: el border-bottom vive en el valor,
   que ocupa el resto del renglón (no debajo del botón). */
.fa-correo-dest-val {
  flex: 1;
  min-width: 0;
  font-size: 0.9rem;
  font-weight: 600;
  color: #252930;
  padding: 0.3rem 0;
  border-bottom: 1px solid #f0f1f4;
}

/* Asunto sin label: input que hereda el estilo mínimo de .fa-campo-input. */
.fa-correo-asunto {
  margin-top: 0;
}

/* Barra de destinatarios EDITABLE (centralizacion-correos): chips + input,
   en vez del span de solo texto de .fa-correo-dest-val. La línea sigue
   arrancando después del botón Para/CC, ahora sobre el contenedor de chips. */
.fa-correo-dest--editable {
  flex-wrap: wrap;
  align-items: flex-start;
}

/* Campo tipo cliente de correo: los chips y el input viven en el MISMO
   renglón y la línea la lleva este contenedor, no el input — así los
   correos ya agregados quedan SOBRE la línea y se sigue escribiendo a
   continuación en vez de en un renglón aparte. */
.fa-correo-campo {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem;
  flex: 1;
  min-width: 8rem;
  padding: 0.2rem 0;
  border-bottom: 1px solid #f0f1f4;
}

.fa-correo-campo:focus-within {
  border-bottom-color: var(--color-marca);
}

/* display: contents — el contenedor sigue existiendo como gancho del JS
   (data-chips-to / -cc-fijo / -cc-extra) pero no genera caja, así sus chips
   son hijos de flex de .fa-correo-campo y comparten renglón con el input. */
.fa-correo-chips {
  display: contents;
}

.fa-correo-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  background: #eef1fb;
  color: #252930;
  border-radius: 999px;
  padding: 0.15rem 0.35rem 0.15rem 0.65rem;
  font-size: 0.8rem;
  line-height: 1.6;
}

/* `hidden` no alcanza contra `display: inline-flex`: sin esta regla el chip
   sugerido que se elige se quedaría a la vista. */
.fa-correo-chip[hidden],
.fa-correo-sugeridos[hidden] {
  display: none;
}

/* CC fijo: viene de /admin/correos, así que se distingue de un chip suelto.
   Se puede excluir de ESTE envío, no borrar. */
.fa-correo-chip--fijo {
  background: #f0f1f4;
  color: #9fa7b5;
}

/* Excluido de este envío: el chip sigue ahí (un segundo click lo restaura),
   tachado y atenuado para que se lea como "no va a recibirlo". */
.fa-correo-chip--excluido {
  opacity: 0.55;
}

.fa-correo-chip--excluido .fa-correo-chip-texto {
  text-decoration: line-through;
}

.fa-correo-chip-excluir {
  border: none;
  background: transparent;
  color: #9fa7b5;
  font-size: 0.9rem;
  line-height: 1;
  cursor: pointer;
  padding: 0;
}

.fa-correo-chip-excluir:hover {
  color: #d64545;
}

.fa-correo-chip-quitar {
  border: none;
  background: transparent;
  color: #9fa7b5;
  font-size: 0.9rem;
  line-height: 1;
  cursor: pointer;
  padding: 0;
}

.fa-correo-chip-quitar:hover {
  color: #d64545;
}

/* Input de agregar destinatario/CC suelto: sin borde propio — la línea la
   pone .fa-correo-campo, que lo comparte con los chips. */
.fa-correo-chip-input {
  flex: 1 1 8rem;
  min-width: 6rem;
  border: none;
  font-size: 0.85rem;
  padding: 0.3rem 0;
  background: transparent;
}

.fa-correo-chip-input:focus {
  outline: none;
}

/* Recomendaciones de la plantilla: correos que el catálogo conoce pero que
   no entraron solos al envío. Sangrado a la altura del campo (ancho del
   botón Para/CC + su gap) para que se lean colgando de la línea de arriba.
   Sin recomendaciones el bloque no se renderiza (el macro lo omite). */
.fa-correo-sugeridos {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  padding: 0.15rem 0 0.35rem 4rem;
}

.fa-correo-sugeridos-label {
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: #9fa7b5;
  flex-shrink: 0;
}

.fa-correo-sugeridos-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}

/* Chip de recomendación: no es un destinatario — borde punteado y fondo
   plano para que no se confunda con un chip ya agregado. Lo clickeable son
   sus dos micro-botones de destino, no el chip. */
.fa-correo-chip--sugerido {
  background: transparent;
  border: 1px dashed #d7dbe4;
  color: #9fa7b5;
  padding: 0.1rem 0.35rem 0.1rem 0.55rem;
  gap: 0.25rem;
}

.fa-correo-chip--sugerido:hover {
  border-color: var(--color-marca);
  border-style: solid;
  color: #252930;
}

/* Los DOS destinos posibles de una recomendación (Para / CC). Se etiquetan
   con la palabra en vez de un icono porque son exactamente los rótulos de
   los dos campos de arriba: el destino se lee sin aprenderse un símbolo. */
.fa-correo-sugerido-accion {
  border: none;
  background: #eef1fb;
  color: #4472c4;
  border-radius: 999px;
  font-size: 0.65rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  line-height: 1;
  cursor: pointer;
  padding: 0.2rem 0.4rem;
}

.fa-correo-sugerido-accion:hover {
  background: var(--color-marca);
  color: #fff;
}

/* Toolbar de la acción principal del panel (Enviar en los paneles de correo,
   Guardar en /admin/correos): sube pegado al título (menos aire con el
   padding-top del panel-body) y manda el botón al extremo derecho, la misma
   posición que ya usaba el toolbar de /pagos. */
.fa-correo-toolbar {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  margin-top: -0.75rem;
  margin-bottom: 0.5rem;
}

/* Enviar: mismo tamaño de letra que Para/CC y adjuntos (0.85rem) y un poco
   más de separación entre el icono y el texto. Scopeado al toolbar de correo
   para no cambiar el resto de botones .fa-btn-icono. */
.fa-correo-toolbar .fa-btn-icono {
  font-size: 0.85rem;
  gap: 0.55rem;
}

/* Aviso de plantilla desactivada (R3 reliability review — el chip Activo/
   Inactivo de /admin/correos ahora sí bloquea el envío): mismo par
   ámbar/fondo que .fa-cfdi-sin-timbrar, la convención ya establecida del
   proyecto para "atención sin ser un error rojo". */
.fa-correo-inactivo-aviso {
  margin: 0 0 0.5rem;
  padding: 0.4rem 0.6rem;
  border-radius: 4px;
  background: #fef3c7;
  color: #92400e;
  font-size: 0.8rem;
}

/* Nota de un pago de DEVOLUCIÓN: el depósito llegó por equivocación y su
   línea no tenía facturas por cobrar. Mismo par ámbar/fondo que
   .fa-correo-inactivo-aviso — es "atención sin ser un error rojo", que es
   exactamente lo que comunica un expediente que no va a cerrar como cobro. */
.fa-pago-devolucion-nota {
  margin: 0;
  padding: 0.6rem 0.75rem;
  border-radius: 4px;
  background: #fef3c7;
  color: #92400e;
  font-size: 0.82rem;
  line-height: 1.5;
}

.fa-pago-devolucion-nota a {
  color: inherit;
  text-decoration: underline;
}

/* Selector del expediente de un cobro indirecto (paso 2). Tres tarjetas-botón
   en una fila que se apila en pantallas angostas — son opciones EXCLUYENTES y
   de peso parejo, así que ninguna se destaca sobre las otras: la que se elija
   ya no se puede cambiar y sugerir una sería empujar la decisión. */
.fa-expediente-opciones {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 1rem;
}

.fa-expediente-opcion {
  flex: 1 1 12rem;
  padding: 1.1rem 1rem;
  border: 1px solid #e7e9ed;
  border-radius: 6px;
  background: #fff;
  color: #252930;
  cursor: pointer;
  text-align: center;
  transition: border-color 0.15s, box-shadow 0.15s;
}

.fa-expediente-opcion:hover:not(:disabled),
.fa-expediente-opcion:focus-visible {
  border-color: #4472c4;
  box-shadow: 0 0 0 3px rgba(68, 114, 196, 0.12);
}

.fa-expediente-opcion:disabled {
  opacity: 0.55;
  cursor: default;
}

.fa-expediente-opcion-titulo {
  font-size: 0.9rem;
  font-weight: 600;
}

/* Barra de TinyMCE más compacta dentro de los paneles de correo. Scopeada
   a .fa-panel para no tocar los diálogos (.tox-tinymce-aux van en <body>). */
.fa-panel .tox .tox-toolbar__primary {
  padding: 0;
}
/* Toolbar compacta SIN recortes: se conserva el alto natural del botón del
   skin (28px, que nunca corta) y solo se reduce el icono (24→20px) y el
   margen vertical (6/5→3px). Nada de height/width forzados que provoquen
   clipping en las filas del wrap. */
.fa-panel .tox .tox-tbtn {
  margin: 3px 1px;
}
.fa-panel .tox .tox-tbtn svg {
  width: 20px;
  height: 20px;
}

/* ── Responsive ───────────────────────────────────────────── */
@media (max-width: 800px) {
  .fa-estatus-header {
    flex-direction: column;
    align-items: flex-start;
    gap: 1rem;
  }

  .fa-estatus-header-meta {
    width: 100%;
  }

  /* Timeline colapsa a vertical: pasos en columna, círculo + título en fila */
  .fa-timeline {
    flex-direction: column;
    align-items: stretch;
    gap: 0.9rem;
    padding: 1rem 0.5rem;
  }

  .fa-timeline-paso {
    flex: 0 0 auto;
  }

  .fa-timeline-paso-link {
    flex-direction: row;
    justify-content: flex-start;
    align-items: center;
    gap: 0.85rem;
    padding: 0.25rem 0.5rem;
  }

  /* En vertical el conector pasa al lado izquierdo del círculo.
     Mismo gradiente de 2 stops duros que la versión horizontal, pero
     con el eje girado a "to bottom" (el largo del trazo ahora es la
     altura, no el ancho) y el clip-path con x/y intercambiados para
     que la punta afinada quede en los extremos superior/inferior. */
  .fa-timeline-paso::after {
    top: 28px;
    left: 18px; /* centro horizontal del círculo (28px / 2 + padding) */
    width: 2px;
    height: calc(100% + 0.4rem);
    background: linear-gradient(
      to bottom,
      var(--fa-conector-desde, var(--fa-sem-gris-600)) 0% 47%,
      transparent 47% 53%,
      var(--fa-conector-hasta, var(--fa-sem-gris-600)) 53% 100%
    );
    clip-path: polygon(50% 0%, 0% 6%, 0% 94%, 50% 100%, 100% 94%, 100% 6%);
  }

  .fa-timeline-titulo {
    text-align: left;
  }

  .fa-panel-seccion-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 520px) {
  .fa-estatus-header-meta-item {
    min-width: 100%;
  }

  .fa-panel-seccion-grid {
    grid-template-columns: 1fr;
  }

  .fa-estatus-panel {
    padding: 1.25rem 1rem;
  }
}

/* ── Anchos de columna de la tabla del panel Generar Factura ── */
/* table-layout: fixed + porcentajes para que las 8 columnas llenen el ancho
   del panel de forma pareja.  Con layout automático alguna columna angosta
   podía acaparar espacio sobrante y dejar un hueco visible; los porcentajes
   lo reparten.  Las columnas 1 (indicador CFDI), 6 (Plazo) y 8 (eliminar) son
   angostas.  Columna 7 (Estatus) solo necesita caber "Duplicada" (el texto
   más largo de los 4 posibles) — el resto de su ancho original (heredado de
   las extintas "Vencida"+"Duplicado") se repartió proporcionalmente entre
   las columnas de datos reales (2-5).  Suma = 100%.
   Scopeado a .fa-panel-col-der para NO afectar la tabla principal de /disposiciones. */
.fa-panel-col-der .fa-tabla {
  table-layout: fixed;
}
.fa-panel-col-der .fa-tabla thead th:nth-child(1) {
  width: 4%;
} /* Indicador CFDI */
.fa-panel-col-der .fa-tabla thead th:nth-child(2) {
  width: 15%;
} /* Factura */
.fa-panel-col-der .fa-tabla thead th:nth-child(3) {
  width: 20%;
} /* F. Factura */
.fa-panel-col-der .fa-tabla thead th:nth-child(4) {
  width: 20%;
} /* F. Vencimiento */
.fa-panel-col-der .fa-tabla thead th:nth-child(5) {
  width: 16%;
} /* Importe USD */
.fa-panel-col-der .fa-tabla thead th:nth-child(6) {
  width: 7%;
} /* Plazo */
.fa-panel-col-der .fa-tabla thead th:nth-child(7) {
  width: 12%;
} /* Estatus */
.fa-panel-col-der .fa-tabla thead th:nth-child(8) {
  width: 6%;
} /* Eliminar */

/* La tabla iguala el alto de la columna de datos de la izquierda — ni más
   (no empuja el panel) ni menos (no deja hueco). Patrón "slot + capa
   absoluta":
   - El wrapper es un SLOT flex:1 que ocupa el espacio bajo los botones. Al no
     tener contenido en flujo (la tabla va absoluta), su alto intrínseco es 0,
     así que NO infla la columna derecha: la columna izquierda manda el alto y
     el stretch del flex iguala ambas.
   - .fa-captura-scroll es la capa absoluta (inset:0) que contiene la tabla y
     scrollea internamente. Reemplaza al viejo max-height:360px fijo.
   El encabezado sigue sticky (ahora respecto del scroller). */
.fa-tabla-wrapper--captura {
  position: relative;
  flex: 1 1 0;
  min-height: 0;
  overflow: visible;
}
.fa-captura-scroll {
  position: absolute;
  inset: 0;
  overflow: auto;
}
/* "+ Agregar factura": vive DENTRO del scroller, justo debajo de la última
   fila, así que sube y baja con la tabla. .fa-btn-texto es inline-flex, o sea
   inline-level, y por eso alcanza con text-align para llevarlo a la derecha
   (su align-self del base no aplica: este contenedor no es flex). */
.fa-captura-agregar {
  text-align: right;
  padding: 0.4rem 0.25rem 0.25rem;
}

.fa-tabla-wrapper--captura .fa-tabla thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: #ffffff;
  /* Override del #9fa7b5 base (2.4:1) → 4.69:1. Scope solo a esta tabla. */
  color: #6c757d;
}

/* Indicador CFDI (columna izquierda): badge cuando un CFDI válido coincide
   con la factura. */
.fa-panel-col-der .fa-tabla .fa-celda-indicador {
  text-align: center;
  padding-left: 0;
  padding-right: 0;
}

/* Badge "CFDI válido": cuadradito redondeado con fondo verde suave y check
   nítido. Estático y discreto — pensado para leerse igual en muchas filas. */
.fa-cfdi-ok {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: 6px;
  background: #d6f1e3;
  color: #039855;
  font-size: 0.6rem;
  line-height: 1;
}

/* CFDI válido pero sin timbrar (sin firma SAT): triángulo amarillo. */
.fa-cfdi-sin-timbrar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: 6px;
  background: #fef3c7;
  color: #d97706;
  font-size: 0.6rem;
  line-height: 1;
}

/* Botón eliminar fila (columna derecha): sutil en reposo, rojo al hover. */
.fa-panel-col-der .fa-tabla .fa-celda-eliminar {
  text-align: center;
  padding-left: 0;
  padding-right: 0;
}
/* La regla .fa-btn-eliminar-fila vive consolidada más abajo (sección
   "Botón icono para eliminar UNA factura"). Antes estaba duplicada acá con
   valores en conflicto (color #c8cdd6 vs #9fa7b5) — se unificó en un solo
   bloque con área de toque accesible. */

/* ── Tooltip blanco reusable (data-tooltip) ──────────────────────────
   Leyenda custom en hover, sin librería ni title nativo (caja amarilla
   del navegador). El host lleva .fa-tip + un modificador de dirección y
   data-tooltip="texto". Las variantes --izq/--der quedan centradas
   verticalmente para no chocar con el overflow del scroll de las tablas. */
.fa-tip {
  position: relative;
}
.fa-tip::after {
  content: attr(data-tooltip);
  position: absolute;
  /* Posición por defecto: arriba, centrado. */
  bottom: calc(100% + 7px);
  left: 50%;
  transform: translateX(-50%);
  background: #ffffff;
  color: #252930;
  border: 1px solid #e7e9ed;
  font-size: 0.72rem;
  font-weight: 600;
  line-height: 1.35;
  white-space: nowrap;
  padding: 0.3rem 0.55rem;
  border-radius: 7px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.14);
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.13s ease;
  transition-delay: 0s; /* al salir, se oculta de inmediato */
  z-index: 9999;
}
/* Elevamos el host en hover para que el tooltip no quede detrás de hermanos
   posteriores (ej. la tabla de captura, que se pinta después en el DOM). */
.fa-tip:hover {
  z-index: 5;
}
.fa-tip:hover::after {
  opacity: 1;
  transition-delay: 1.5s; /* aparece tras 1.5s de hover sostenido */
}
/* Abajo, centrado (botones de importación). */
.fa-tip--abajo::after {
  top: calc(100% + 7px);
  bottom: auto;
  left: 50%;
  transform: translateX(-50%);
}
/* Variante anclada al borde izquierdo: para hosts pegados al borde del
   panel (ej. "Subir Excel"), evita que el tooltip se corte a la izquierda. */
.fa-tip--abajo.fa-tip--ini::after {
  left: 0;
  transform: none;
}
/* A la izquierda, centrado vertical (X eliminar, columna derecha). */
.fa-tip--izq::after {
  top: 50%;
  bottom: auto;
  right: calc(100% + 7px);
  left: auto;
  transform: translateY(-50%);
}
/* A la derecha, centrado vertical (indicador CFDI, columna izquierda). */
.fa-tip--der::after {
  top: 50%;
  bottom: auto;
  left: calc(100% + 7px);
  transform: translateY(-50%);
}

/* Resumen de validación XML al lado de los botones (sin listar archivos). */
.fa-resumen-xml {
  margin-left: auto;
  align-self: center;
  font-size: 0.76rem;
  font-weight: 600;
  color: #252930;
  white-space: nowrap;
}

/* Separador vertical entre los segmentos del resumen (Total | Válidos |
   Inválidos). Reemplaza al punto medio "·" por una línea fina. */
.fa-resumen-xml-sep {
  display: inline-block;
  width: 1px;
  height: 0.85em;
  margin: 0 0.6rem;
  vertical-align: middle;
  background: #c8cdd6;
}

/* ── Edición "en el lugar" del comprador (panel Generar Factura) ── */
/* Vendedor: el item seleccionado no se parte en varias líneas — trunca con
   elipsis. TomSelect genera el .ts-wrapper como hermano inmediato del
   <select> original (que queda oculto). */
#sel-vendedor + .ts-wrapper .ts-control .item {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}

/* Al clickear el comprador ya elegido (clase .fa-editando, cableada en
   generar_factura.js) ocultamos el chip y mostramos el input editable.
   Forzamos el input visible incluso vacío para que el control no quede en
   blanco al borrar el texto antes de reescribir. */
.ts-wrapper.fa-campo-select .ts-control.fa-editando .item {
  display: none;
}
.ts-wrapper.fa-campo-select .ts-control.fa-editando input {
  opacity: 1 !important;
  position: static !important;
  left: auto !important;
  width: 100% !important;
}

/* Cursor del desplegable: la flecha (chevron, background-image sobre el
   .ts-control) y el resto del control usan "pointer" (manito) porque al
   clickearlos se abre/cierra el menú; el input de búsqueda usa "text"
   (barrita) porque ahí se escribe. Por defecto TomSelect los tenía al revés.
   Scope con el id del panel (#overlay-generar-factura) para ganarle en
   especificidad al CSS que TomSelect inyecta por JS en runtime (mismo número
   de clases, pero se carga DESPUÉS de estilo.css). */
#overlay-generar-factura .ts-wrapper.fa-campo-select .ts-control {
  cursor: pointer;
}
#overlay-generar-factura .ts-wrapper.fa-campo-select .ts-control input {
  cursor: text;
}

/* ── Inputs de la tabla del panel Generar Factura ── */
/* Inputs editables dentro de .fa-tabla del panel "Generar Factura".  Sin
   chrome de Bootstrap; solo un borde inferior sutil consistente con el
   resto de los campos del proyecto. */
.fa-tabla .fa-input-celda {
  width: 100%;
  font-size: 0.8rem;
  font-weight: 600;
  color: #252930;
  border: none;
  border-bottom: 1px solid transparent;
  background: transparent;
  padding: 0.2rem 0;
  outline: none;
}

.fa-tabla .fa-input-celda:focus {
  border-bottom-color: #1a1a1a;
}

.fa-tabla .fa-input-celda[type="date"] {
  font-family: inherit;
}

/* Importe USD alineado a la derecha. El valor se muestra con separadores
   de miles (10,000.00) vía JS; el estado guarda el número crudo (10000.00). */
.fa-tabla .fa-input-celda[data-col="monto"] {
  text-align: right;
}

/* Celda "Estatus" (ex "Vencida" + "Duplicado", ahora unificadas): texto
   centrado, no estira la columna. */
.fa-tabla .fa-bandera {
  text-align: center;
  font-size: 0.9rem;
  color: #d9822b;
  width: 60px;
}

/* Input de fecha del panel "Generar Factura": hereda el look de
   .fa-campo-readonly pero acepta edición (solo input nativo type=date).
   Se necesita editable porque la regla de "vencida" compara contra esta
   fecha (no contra hoy), como en la celda D12 del Excel. */
.fa-campo-fecha {
  font-size: 0.9rem;
  font-weight: 600;
  color: #252930;
  padding: 0.3rem 0;
  border: none;
  border-bottom: 1px solid #f0f1f4;
  background: transparent;
  outline: none;
  font-family: inherit;
}

.fa-campo-fecha:focus {
  border-bottom-color: #1a1a1a;
}

/* Placeholder "mm/dd/aaaa" en gris cuando NO hay fecha elegida; al elegir
   una, el texto vuelve al negro base (.fa-campo-fecha). La clase la togglea
   actualizarColorFecha() en generar_factura.js porque los <input type="date">
   no soportan ::placeholder.
   Cross-browser: coloreamos el `color` del input completo (Firefox + Chrome);
   el pseudo ::-webkit-datetime-edit es refuerzo para Chrome/Edge. */
.fa-campo-fecha.fa-campo-fecha--vacio {
  color: #c8cdd6;
}
.fa-campo-fecha.fa-campo-fecha--vacio::-webkit-datetime-edit {
  color: #c8cdd6;
}

/* Columna "Plazo" (vencimiento − fecha de factura): solo lectura, calculada
   en JS (calcPlazo). Angosta (el ancho lo fija el nth-child de la tabla) y con
   padding lateral 0 para que el número de días quepa justo. Mismo color y
   tipografía que los inputs de captura. */
.fa-tabla .fa-th-plazo,
.fa-tabla .fa-celda-plazo {
  text-align: center;
  padding-left: 0;
  padding-right: 0;
}

.fa-tabla .fa-celda-plazo {
  font-size: 0.8rem;
  font-weight: 600;
  color: #252930;
}

/* Factura duplicada: se remarcan los DATOS de la fila en ámbar (mismo tono de
   la columna Estatus), sin fondo ni barra lateral. La clase la togglea el
   JS (crearFila / actualizarBanderasFila). */
.fa-tabla tbody tr.fa-fila-duplicada .fa-input-celda,
.fa-tabla tbody tr.fa-fila-duplicada .fa-celda-plazo {
  color: #d9822b;
}

/* El ícono nativo de los <input type="date"> (F. Factura / F. Vencimiento)
   es un SVG del navegador que ignora `color` — por eso no se pintaba junto
   con el resto de la fila duplicada. `filter` es la única forma de teñirlo;
   los valores están calculados para llevar el negro nativo exactamente a
   #d9822b (mismo tono que el resto de la fila). Solo Chrome/Edge exponen
   este pseudo-elemento (misma limitación que ::-webkit-datetime-edit arriba
   en .fa-campo-fecha--vacio); Firefox no tiene hook para recolorear su ícono. */
.fa-tabla tbody tr.fa-fila-duplicada
  .fa-input-celda[type="date"]::-webkit-calendar-picker-indicator {
  filter: invert(64%) sepia(100%) saturate(193%) hue-rotate(-11deg)
    brightness(69%) contrast(187%);
}

/* Chip del ícono CFDI (columna izquierda) en fila duplicada: pasa a ámbar
   aunque el CFDI esté válido y timbrado (.fa-cfdi-ok, normalmente verde) —
   "Duplicada" manda sobre el estado del CFDI, un solo color en toda la fila. */
.fa-tabla tbody tr.fa-fila-duplicada .fa-cfdi-ok {
  background: #f6e0c8;
  color: #d9822b;
}

/* ── Semáforo de estatus del comprador en el panel "Generar Factura" ── */
/* Punto pequeño junto al label "Comprador" que cambia de color según
   el estatus devuelto por /disposiciones/dispo/comprador/<nombre>. Replica la
   fórmula =SI(VLOOKUP(D3,Compradores,5)="ACTIVO",1,...) del Excel:
       1  -> verde   (ACTIVO)
      -1  -> rojo    (CANCELADO)
       0  -> ámbar   (cualquier otro)
   Pensado para ser invisible cuando no hay comprador seleccionado
   (data-estatus="otro" en gris suave, neutral). */
.fa-semaforo {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  margin-right: 6px;
  vertical-align: middle;
  background: #d0d4dc; /* neutral por defecto */
  transition: background-color 0.15s ease;
}

.fa-semaforo[data-estatus="activo"] {
  background: #2ecc71;
  box-shadow: 0 0 0 2px rgba(46, 204, 113, 0.15);
}

.fa-semaforo[data-estatus="cancelado"] {
  background: #e74c3c;
  box-shadow: 0 0 0 2px rgba(231, 76, 60, 0.15);
}

.fa-semaforo[data-estatus="otro-activo"] {
  /* Tiene comprador pero el estatus no es ni Activo ni Cancelado.
	   Lo dejamos ámbar suave para que no pase desapercibido pero sin
	   gritar como un error. */
  background: #e0a800;
  box-shadow: 0 0 0 2px rgba(224, 168, 0, 0.15);
}

/* ══════════════════════════════════════════════════════════════════
   ENCABEZADO ACCIONES (/disposiciones — Exportar + Generar Factura)
   ══════════════════════════════════════════════════════════════════ */

.fa-encabezado-acciones {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

/* Variante ghost (Exportar) */
.fa-btn-accion--ghost {
  background: transparent;
  color: #1a1a1a;
  border: 1px solid #c8cdd6;
  box-shadow: none;
}

.fa-btn-accion--ghost:hover {
  background: #f5f6fe;
  border-color: #9fa7b5;
  color: #1a1a1a;
}

/* ── Estado badges para tabla de facturas ── */
.fa-estado-badge {
  display: inline-block;
  padding: 0.25rem 0.6rem;
  border-radius: 12px;
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  white-space: nowrap;
}

.fa-estado-badge--abierta {
  background-color: #d4edda;
  color: #155724;
  border: 1px solid #c3e6cb;
}

.fa-estado-badge--pagada {
  background-color: #e2e3e5;
  color: #383d41;
  border: 1px solid #d6d8db;
}

/* ══════════════════════════════════════════════════════════════════
   CÍRCULO DE PROGRESO DE ESTATUS (columna Estado de /disposiciones y
   de /pagos). Arcos desconectados en un SVG circular — cuatro en
   /disposiciones (ciclo de vida de la factura), cuatro en /pagos
   (ciclo de cobro del evento de pago); dos catálogos independientes que
   coinciden en longitud. El JS los genera a partir del largo de
   estatus_pasos; estas reglas son agnósticas al conteo.
   El color depende del valor del paso:
     verde  (--prog-color-ok)     → valor 1  (paso completado OK)
     rojo   (--prog-color-error)  → valor 0  (paso fallido)
     ámbar  (--prog-color-warn)   → valor 2  (paso con advertencia)
     gris   (--prog-color-vacio)  → null      (paso no ejecutado)
   ══════════════════════════════════════════════════════════════════ */
.fa-prog-circulo {
  --prog-color-ok: #22c55e; /* verde  */
  --prog-color-error: #ef4444; /* rojo   */
  --prog-color-warn: #f59e0b; /* ámbar  */
  --prog-color-vacio: #e2e5ea; /* gris   */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  vertical-align: middle;
}
.fa-prog-circulo svg {
  display: block;
}
/* Cada arco: por defecto gris (no ejecutado). */
.fa-prog-arco {
  stroke: var(--prog-color-vacio);
  stroke-linecap: round;
  fill: none;
  pointer-events: none; /* el hit lo hace .fa-prog-hit */
}
/* Colores según estado del paso */
.fa-prog-arco[data-val="1"] {
  stroke: var(--prog-color-ok);
}
.fa-prog-arco[data-val="0"] {
  stroke: var(--prog-color-error);
}
.fa-prog-arco[data-val="2"] {
  stroke: var(--prog-color-warn);
}

/* Área de hit invisible (stroke transparente, más gordo que el arco) */
/* El JS (bindSegmentoHover) pone/quita transform en el <g>.fa-prog-seg */
.fa-prog-hit {
  stroke: transparent;
  stroke-linecap: round;
  fill: none;
  pointer-events: stroke;
  cursor: pointer;
}
/* Tooltip CSS para el círculo de progreso.
   El tooltip vive en la <td> (no en el .fa-prog-circulo) para escapar
   del overflow:hidden del wrapper de tabla.
   JS transfiere el data-tooltip del span a la <td> al renderizar.
   JS transfiere el data-tooltip del span a la <td> al renderizar. */
#tabla-disposiciones thead th[data-campo="estado"] {
  width: 70px;
  text-align: center;
}
/* /pagos NO fija px acá: su ancho es el 5% declarado arriba (todas sus
   columnas van en porcentaje para que la tabla nunca se pase del contenedor).
   Un width en px acá lo pisaría — misma especificidad, pero esta regla va
   después en el archivo. */
#pagos-tabla thead th[data-col="estado"] {
  text-align: center;
}
#tabla-disposiciones td:has(.fa-prog-circulo),
#pagos-tabla td:has(.fa-prog-circulo) {
  position: relative;
  overflow: visible;
  text-align: center;
  padding-left: 0;
  padding-right: 0;
}

/* Link que envuelve el círculo de estatus */
.fa-prog-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  outline: none;
  cursor: pointer;
}

/* Tooltip: vive en la <td> para escapar del overflow del wrapper */
#tabla-disposiciones td:has(.fa-prog-circulo)::after,
#pagos-tabla td:has(.fa-prog-circulo)::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%);
  background: #1a1a1a;
  color: #f5f6fe;
  font-size: 0.7rem;
  font-weight: 500;
  line-height: 1.6;
  white-space: pre;
  padding: 0.4rem 0.6rem;
  border-radius: 6px;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.15s ease;
  z-index: 9999;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
}
#tabla-disposiciones td:has(.fa-prog-circulo):hover::after,
#pagos-tabla td:has(.fa-prog-circulo):hover::after {
  opacity: 1;
}

/* ══════════════════════════════════════════════════════════════════
   FILTROS TIPO CHIP (/disposiciones)
   Botón "+ Filtro", barra de chips activos, selector de columna y
   editores tipados (list / contains / range / daterange).
   ══════════════════════════════════════════════════════════════════ */

/* Botón "+ Filtro" en el toolbar */
.fa-btn-filtro {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.4rem 0.85rem;
  background: transparent;
  border: 1px solid #c8cdd6;
  border-radius: 8px;
  color: #1a1a1a;
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
  transition:
    background 0.12s,
    border-color 0.12s;
}
.fa-btn-filtro:hover {
  background: #f5f6fe;
  border-color: #9fa7b5;
}

/* Barra de chips */
.fa-chips-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  padding: 0.6rem 1rem 0;
}
.fa-chips-bar--empty {
  display: none;
}
/* Chips dentro del card de la tabla (Disposiciones/Vencimientos/Clientes): el
   padding base deja 0 abajo, así que los chips quedan pegados al encabezado de
   la tabla. Se agrega el mismo espacio abajo que arriba para que la barra
   "respire" simétrica respecto a la línea que la separa de los filtros. */
.fa-tabla-card .fa-chips-bar:not(.fa-chips-bar--empty) {
  padding-bottom: 0.6rem;
}

/* Chip individual */
.fa-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.3rem 0.35rem 0.3rem 0.65rem;
  background: #eef1fb;
  border: 1px solid #d4dbf5;
  border-radius: 16px;
  font-size: 0.75rem;
  color: #252930;
  max-width: 320px;
}
.fa-chip-label {
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.fa-chip-label i {
  color: #4472c4;
}
.fa-chip-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  padding: 0;
  background: transparent;
  border: none;
  border-radius: 50%;
  color: #9fa7b5;
  font-size: 0.6rem;
  cursor: pointer;
  flex-shrink: 0;
  transition:
    background 0.12s,
    color 0.12s;
}
.fa-chip-close:hover {
  background: #d4dbf5;
  color: #1a1a1a;
}

/* Overlay compartido (selector + editores) */
.fa-filtro-selector-overlay,
.fa-filtro-editor-overlay {
  position: fixed;
  inset: 0;
  z-index: 1060;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.35);
}

/* Caja flotante */
.fa-filtro-selector,
.fa-filtro-editor {
  background: #fff;
  border-radius: 14px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.18);
  width: 92%;
  max-width: 340px;
  padding: 1rem;
  max-height: 80vh;
  overflow-y: auto;
}

/* Selector de columna */
.fa-filtro-selector-title,
.fa-filtro-editor-title {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: #9fa7b5;
  margin-bottom: 0.6rem;
}
/* Encabezado del selector: título + botón cerrar en una fila. */
.fa-filtro-selector-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.6rem;
}
.fa-filtro-selector-header .fa-filtro-selector-title {
  margin-bottom: 0;
}
.fa-filtro-selector-cerrar {
  flex: 0 0 auto;
}
.fa-filtro-selector-list {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}
.fa-filtro-selector-item {
  display: flex;
  align-items: center;
  width: 100%;
  padding: 0.5rem 0.6rem;
  background: transparent;
  border: none;
  border-radius: 8px;
  color: #252930;
  font-size: 0.85rem;
  text-align: left;
  cursor: pointer;
  transition: background 0.1s;
}
.fa-filtro-selector-item:hover {
  background: #f5f6fe;
}
.fa-filtro-selector-item i {
  color: #9fa7b5;
}

/* Editor: búsqueda + checkboxes (list) */
.fa-filtro-editor-search {
  margin-bottom: 0.5rem;
}
.fa-filtro-search-input,
.fa-filtro-text-input {
  width: 100%;
  padding: 0.45rem 0.6rem;
  border: 1px solid #e7e9ed;
  border-radius: 8px;
  font-size: 0.85rem;
  color: #252930;
}
.fa-filtro-search-input:focus,
.fa-filtro-text-input:focus,
.fa-filtro-range-input:focus,
.fa-filtro-date-input:focus {
  outline: none;
  border-color: #4472c4;
}
.fa-filtro-editor-checkboxes {
  max-height: 240px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}
.fa-filtro-checkbox-group {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.35rem 0.4rem;
  border-radius: 6px;
}
.fa-filtro-checkbox-group:hover {
  background: #f5f6fe;
}
.fa-filtro-checkbox-group input[type="checkbox"] {
  width: 14px;
  height: 14px;
  accent-color: #4472c4;
  cursor: pointer;
  flex-shrink: 0;
}
.fa-filtro-checkbox-group input[type="checkbox"]:disabled {
  cursor: not-allowed;
}
.fa-filtro-checkbox-label {
  flex: 1;
  font-size: 0.82rem;
  color: #252930;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
.fa-filtro-checkbox-group
  input[type="checkbox"]:disabled
  + .fa-filtro-checkbox-label {
  color: #c8cdd6;
}
/* Cuentas Monex del form de comprador: filas de checkbox (.fa-filtro-checkbox-group)
   con el radio «Principal» a la derecha. */
.fa-cuentas-monex {
  max-height: 240px;
  overflow-y: auto;
  border-bottom: 1px solid #e7e9ed;
  padding-bottom: 0.25rem;
}
.fa-cuenta-principal {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.75rem;
  color: #9fa7b5;
  cursor: pointer;
  flex-shrink: 0;
}
.fa-cuenta-principal input[type="radio"] {
  accent-color: #4472c4;
  cursor: pointer;
}
.fa-cuenta-principal input[type="radio"]:disabled {
  cursor: not-allowed;
}
.fa-cuenta-principal-badge {
  font-size: 0.7rem;
  font-weight: 600;
  color: #4472c4;
  background: #eef2fb;
  border-radius: 999px;
  padding: 0.1rem 0.5rem;
  flex-shrink: 0;
}
.fa-filtro-loading,
.fa-filtro-no-options {
  padding: 0.5rem 0.4rem;
  font-size: 0.8rem;
  color: #9fa7b5;
}

/* Editor: rangos numéricos y de fecha */
.fa-filtro-editor-range,
.fa-filtro-editor-daterange {
  display: flex;
  gap: 0.75rem;
}
.fa-filtro-range-group,
.fa-filtro-date-group {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  flex: 1;
}
.fa-filtro-range-label,
.fa-filtro-date-label {
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #9fa7b5;
}
.fa-filtro-range-input,
.fa-filtro-date-input {
  width: 100%;
  padding: 0.45rem 0.6rem;
  border: 1px solid #e7e9ed;
  border-radius: 8px;
  font-size: 0.85rem;
  color: #252930;
}

/* Acciones del editor (Aplicar / Cancelar) */
.fa-filtro-editor-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
  margin-top: 1rem;
}

/* ── Filtros fijos desplegables (Cofactor / Moneda / Estado) ── */
/* flex-wrap porque el .fa-tabla-card que los contiene tiene overflow:hidden:
   el toolbar hace wrap ENTRE sus bloques, pero un grupo de seis o siete
   botones más ancho que la tarjeta se recortaría en silencio. */
.fa-filtros-fijos {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
}

.fa-filtro-fijo {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.45rem 0.85rem;
  background: #ffffff;
  border: 1px solid #d0d4dc;
  border-radius: 8px;
  color: #252930;
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
  box-shadow:
    0 1px 3px rgba(0, 0, 0, 0.07),
    0 1px 2px rgba(0, 0, 0, 0.04);
  transition:
    background 0.12s,
    border-color 0.12s,
    box-shadow 0.12s;
}
.fa-filtro-fijo:hover {
  background: #f5f6fe;
  border-color: #b0b6c2;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
}
.fa-filtro-fijo i:first-child {
  color: #9fa7b5;
}
.fa-filtro-fijo-chevron {
  width: 10px;
  height: 6px;
  color: #9fa7b5;
  flex-shrink: 0;
  transition: transform 0.2s ease;
}

/* Estado activo: borde + acento azul Delta */
.fa-filtro-fijo--activo {
  border-color: #4472c4;
  background: #eef1fb;
  color: #1a1a1a;
}
.fa-filtro-fijo--activo i:first-child,
.fa-filtro-fijo--activo .fa-filtro-fijo-chevron {
  color: #4472c4;
}

/* Dropdown abierto: chevron rotado */
.fa-filtro-fijo--abierto .fa-filtro-fijo-chevron {
  transform: rotate(180deg);
}

/* Badge de conteo de valores seleccionados */
.fa-filtro-fijo-conteo {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  background: #4472c4;
  color: #fff;
  border-radius: 8px;
  font-size: 0.65rem;
  font-weight: 700;
}
.fa-filtro-fijo-conteo[hidden] {
  display: none;
}

/* Popover del desplegable fijo (anclado bajo el botón) */
.fa-filtro-dropdown {
  z-index: 1060;
  background: #fff;
  border: 1px solid #e7e9ed;
  border-radius: 10px;
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.14);
  padding: 0.75rem;
  width: 260px;
  max-height: 360px;
  overflow-y: auto;
}
.fa-filtro-dropdown-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.6rem;
  padding-top: 0.6rem;
  border-top: 1px solid #f0f1f4;
}

/* Editor de fechas DENTRO del desplegable de un filtro fijo (F. Disposición,
   F. Pago, Fecha Dispo). Los 260px del dropdown no alcanzan para los dos
   <input type="date"> en fila: se cortan y piden scroll horizontal. Se apilan
   y el desplegable se ensancha. Vive acá y no en cada página porque el control
   es el mismo en /disposiciones, /pagos, /base-operaciones y /tareas. El
   editor modal del menú "+ Filtro" queda afuera a propósito: es ancho y los
   dos recuadros entran en fila. */
.fa-filtro-dropdown:has(.fa-filtro-editor-daterange) {
  width: 300px;
}
.fa-filtro-dropdown .fa-filtro-editor-daterange {
  flex-direction: column;
  gap: 0.7rem;
}
.fa-filtro-dropdown .fa-filtro-date-input {
  width: 100%;
  box-sizing: border-box;
}

/* ── Importar Excel/XML: fila de acciones + resumen (panel Generar Factura) ── */
.fa-importar-acciones {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-bottom: 0.85rem;
}

/* Botones "Subir Excel" / "Subir XML": blancos con presencia (borde + sombra
   + ícono en su color semántico). Sobrescriben la base sólida negra de
   .fa-btn-accion. La elevación se acentúa en hover para reforzar que son la
   acción principal del panel. */
.fa-btn-importar {
  background: #ffffff;
  color: #252930;
  border: 1px solid #e7e9ed;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
  /* Altura táctil 40px + centrado de ícono/texto. Antes 32px. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 40px;
  transition:
    box-shadow 0.2s ease,
    transform 0.2s ease;
}
/* Elevación limpia: solo sube la pieza (transform) y crece una sombra
   difusa pareja. El borde NO cambia para que no se vea un contorno
   "rezagado" detrás del botón. */
.fa-btn-importar:hover {
  background: #ffffff;
  color: #252930;
  border-color: #e7e9ed;
  box-shadow:
    0 2px 4px rgba(0, 0, 0, 0.06),
    0 8px 18px rgba(0, 0, 0, 0.14);
  transform: translateY(-2px);
}
#fa-btn-subir-excel .fa-file-excel {
  color: #1ca35e;
}
#fa-btn-subir-xml .fa-file-code {
  color: #3b7ddd;
}

.fa-input-oculto {
  display: none;
}

/* ── Semáforo agregado por paso — facturas-disposiciones-agrupadas ── */
/* Clases fa-timeline-circulo--sem-* colorizan el círculo del timeline
   según el estado agregado del grupo para ese paso del ciclo de vida.
   1 = verde (todas completadas), 2 = amarillo (parcial), 0 = rojo (ninguna),
   na = neutro (sin ejecutar — sin cambio sobre el estado base del paso). */
/* Escala Tailwind 600 para los tres semáforos: mismo nivel de
   luminosidad entre verde/ámbar/rojo → armonía entre ellos y texto
   blanco legible. El donut del index usa la escala 500 (más vibrante)
   porque sus trazos son finos; estos círculos de 28px piden tonos
   profundos (misma lógica documentada en el verde del completado). */
.fa-timeline-circulo--sem-1 {
  background: var(--fa-sem-verde-600);
  color: #fff;
} /* green-600 */
.fa-timeline-circulo--sem-2 {
  background: var(--fa-sem-ambar-600);
  color: #fff;
} /* amber-600 */
.fa-timeline-circulo--sem-0 {
  background: var(--fa-sem-rojo-600);
  color: #fff;
} /* red-600 */
.fa-timeline-circulo--sem-na {
  /* neutro — sin cambio sobre el estado base del paso */
}

/* Paso seleccionado con semáforo: los anillos concéntricos del ripple
   toman el color del círculo principal en vez del azul Delta genérico,
   para que el estado siga legible aunque el paso esté seleccionado.
   Misma especificidad (3 clases) que la regla del ripple azul, pero
   declarado después → gana. */
.fa-timeline-paso--seleccionado
  .fa-timeline-circulo.fa-timeline-circulo--sem-1 {
  box-shadow:
    0 0 0 3px rgba(22, 163, 74, 0.4),
    0 0 0 7px rgba(22, 163, 74, 0.2),
    0 0 0 11px rgba(22, 163, 74, 0.09);
}

.fa-timeline-paso--seleccionado
  .fa-timeline-circulo.fa-timeline-circulo--sem-2 {
  box-shadow:
    0 0 0 3px rgba(217, 119, 6, 0.45),
    0 0 0 7px rgba(217, 119, 6, 0.22),
    0 0 0 11px rgba(217, 119, 6, 0.1);
}

.fa-timeline-paso--seleccionado
  .fa-timeline-circulo.fa-timeline-circulo--sem-0 {
  box-shadow:
    0 0 0 3px rgba(220, 38, 38, 0.4),
    0 0 0 7px rgba(220, 38, 38, 0.2),
    0 0 0 11px rgba(220, 38, 38, 0.09);
}

/* ══════════════════════════════════════════════════════════════
   PASO 2 — VALIDACIÓN SAT (estatus.html)
   ──────────────────────────────────────────────────────────────
   Alerta de conteo, barra de progreso y lista de facturas
   inválidas para el panel del ciclo de vida "Validar (SAT)".
   ══════════════════════════════════════════════════════════════ */

/* Alerta de conteo SAT — fila de métricas (validadas / inválidas / sin XML).
   margin-top propio (0.5rem) se suma al margin-bottom de
   .fa-estatus-panel-header (0.5rem) → 1rem arriba. Ver el override de
   .fa-panel-seccion de abajo: mismo delta agregado ahí para que el
   espacio hacia "Datos por factura" quede igual (1rem) y ambos lados
   sigan simétricos. */
.fa-alert-sat {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  padding: 0.6rem 1.75rem;
  background: #f5f6fe;
  border: 1px solid #e7e9ed;
  border-radius: 8px;
  margin-top: 0.5rem;
  flex-wrap: wrap;
}

/* Cuando "Datos por factura" viene justo después de la alerta SAT (paso 2):
   0.5rem propio + el gap de .fa-estatus-panel-body (0.5rem) = 1rem,
   igual que el 1rem de arriba (ver comentario en .fa-alert-sat). */
.fa-alert-sat + .fa-panel-seccion {
  margin-top: 0.5rem;
}

.fa-alert-sat-item {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}

.fa-alert-sat-label {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: #9fa7b5;
}

.fa-alert-sat-valor {
  font-size: 0.9rem;
  font-weight: 600;
  color: #252930;
}

/* Valor de inválidas: rojo cuando hay al menos una */
.fa-alert-sat-valor--invalidas {
  color: #e74c3c;
}

/* Separadores verticales entre métricas */
.fa-alert-sat-sep {
  width: 1px;
  height: 28px;
  background: #e7e9ed;
  flex-shrink: 0;
}

/* Celda "Estado SAT": centra el badge y el circulito de carga en la columna. */
.fa-tabla-sat .fa-sat-celda-estado {
  text-align: center;
}

/* Columna de selección (checkbox por factura + "seleccionar todas"). Angosta
   y centrada; el checkbox usa el color primario y no encoge la fila. */
.fa-tabla-sat .fa-sat-col-check {
  width: 2.25rem;
  text-align: center;
  padding-left: 0.5rem;
  padding-right: 0.5rem;
}

.fa-tabla-sat .fa-sat-check,
.fa-tabla-sat .fa-sat-check-todas {
  width: 15px;
  height: 15px;
  margin: 0;
  cursor: pointer;
  accent-color: #4472c4;
  vertical-align: middle;
}

.fa-tabla-sat .fa-sat-check:disabled,
.fa-tabla-sat .fa-sat-check-todas:disabled {
  cursor: not-allowed;
  opacity: 0.5;
}

/* Circulito de carga en la celda "Estado SAT" mientras se valida la factura.
   Rotación propia (no dependemos de fa-spin del build de FontAwesome). */
.fa-sat-cargando {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #4472c4;
  font-size: 0.85rem;
  line-height: 1;
}

.fa-sat-cargando .fa-spinner {
  animation: fa-sat-rotate 0.8s linear infinite;
}

@keyframes fa-sat-rotate {
  to {
    transform: rotate(360deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .fa-sat-cargando .fa-spinner {
    animation-duration: 2s;
  }
}

/* Tabla de facturas inválidas — hereda .fa-tabla, sin wrapper scroll */
.fa-tabla-invalidas {
  margin-top: 1.25rem;
}

.fa-tabla-invalidas-titulo {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: #9fa7b5;
  margin: 0 0 0.5rem;
}

/* Estado SAT en celda: pill de color */
.fa-badge-sat {
  display: inline-block;
  padding: 0.15rem 0.5rem;
  border-radius: 4px;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.03em;
}

.fa-badge-sat--vigente {
  background: #d4edda;
  color: #1a6b35;
}

.fa-badge-sat--cancelado {
  background: #fde8e8;
  color: #c0392b;
}

.fa-badge-sat--no-encontrado {
  background: #fff3cd;
  color: #856404;
}

.fa-badge-sat--desconocido {
  background: #f0f1f4;
  color: #9fa7b5;
}

/* ── Tabla "Datos por factura" (estatus, pasos 1 y 8) ──────────────
   Una fila por factura, debajo del "Resumen del grupo". Columnas
   numéricas alineadas a la derecha; la factura de la URL (?f=) se
   resalta con el acento azul de las tablas del módulo. */
.fa-tabla-facturas .fa-td-num {
  text-align: right;
}

/* Sin líneas horizontales entre filas — solo separa el título (thead,
   heredado de .fa-tabla thead tr) del cuerpo. La zebra de abajo ya marca
   dónde termina cada fila, así que la línea es redundante. Cubre "Datos
   por factura" en todos los pasos que usa esta clase (1, 2/SAT, 8). */
.fa-tabla-facturas td {
  border-bottom: none;
}

/* Zebra muy ligera — mismo gris que la zebra de la tabla de Disposiciones
   ("Zebra suave" más arriba). En tr, no en td: así el fondo de la fila
   resaltada (.fa-tabla-fila--resaltada, pintado en el td, regla siguiente)
   sigue ganando visualmente sin pelear con la especificidad de este
   selector. .fa-tabla-facturas cubre "Datos por factura" en todos los
   pasos que la usan (1, 2/SAT, 8). */
.fa-tabla-facturas tbody tr:nth-child(even) {
  background-color: #fafbfc;
}

.fa-tabla-facturas .fa-tabla-fila--resaltada td {
  background-color: var(--color-acento-fila-suave);
}

.fa-tabla-facturas .fa-tabla-fila--resaltada td:first-child {
  box-shadow: inset 3px 0 0 var(--color-acento-fila);
}

.fa-tabla-facturas .fa-tabla-fila--total td {
  font-weight: 700;
}

/* ── Tabla con scroll propio ───────────────────────────────────────
   Contenedor para una tabla larga dentro de un panel: en vez de estirar la
   página hasta que el resto del contenido quede fuera de vista, la tabla se
   queda en su caja y desplaza adentro.

   El alto se declara en FILAS, no en píxeles: `--fa-filas-visibles` (default
   10) lo fija cada sección según lo que quiera mostrar de un vistazo. Las
   alturas se derivan del padding y el line-height reales de .fa-tabla, y esas
   dos propiedades se fijan acá explícitamente para que el cálculo no dependa
   del line-height heredado del navegador.

   Una celda que envuelve a dos renglones (razones sociales largas) hace la
   fila más alta que el cálculo y el scroll aparece un poco antes: es
   preferible a recortar el texto con ellipsis, que escondería el nombre del
   comprador — que es justamente la columna por la que se busca. */
.fa-tabla-scroll {
  --fa-alto-encabezado: calc(0.6rem * 2 + 0.68rem * 1.3 + 2px);
  --fa-alto-fila: calc(0.65rem * 2 + 0.8rem * 1.45 + 1px);
  max-height: calc(
    var(--fa-alto-encabezado) + var(--fa-filas-visibles, 10) * var(--fa-alto-fila)
  );
  overflow-y: auto;
  overflow-x: auto;
}

.fa-tabla-scroll .fa-tabla th {
  line-height: 1.3;
}

.fa-tabla-scroll .fa-tabla td {
  line-height: 1.45;
}

/* Encabezado fijo: con 15 filas desplazándose, saber qué columna se está
   leyendo importa más que ganar esos 30px de alto.
   El borde inferior va como `box-shadow` y no como `border`: la tabla usa
   border-collapse, y un borde colapsado NO acompaña a la celda sticky — se
   queda arriba y desaparece al desplazar. El fondo blanco tampoco es
   decorativo: sin él, las filas se ven pasar por debajo del encabezado. */
.fa-tabla-scroll .fa-tabla thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: #ffffff;
  box-shadow: inset 0 -2px 0 #e7e9ed;
}

/* UUID fiscal (36 chars): monoespaciado chico con quiebre para que no
   reviente el ancho de la tabla del paso 2. 270px (antes 240px) le da
   lugar al UUID completo en una sola línea — a 240px se quebraba un
   único carácter suelto a la línea siguiente. */
.fa-tabla-facturas .fa-td-uuid {
  font-family: SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.7rem;
  word-break: break-all;
  max-width: 270px;
}

/* Fila de las partes en el resumen: SIEMPRE 3 columnas (comprador,
   vendedor, cofactor) — razones sociales largas, necesitan el ancho. */
.fa-seccion-partes .fa-panel-seccion-grid {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

@media (max-width: 520px) {
  .fa-seccion-partes .fa-panel-seccion-grid {
    grid-template-columns: 1fr;
  }
}

/* ── Editor del grupo de facturas (/editar) ────────────────────────── */
/* Sin la línea divisoria bajo el título: acá el header ya se separa del
   cuerpo por espacio. La regla general (.fa-form-header) la conservan los
   formularios de Clientes, que sí la usan. */
.fa-pagina-editar .fa-form-header {
  border-bottom: none;
}

/* Aire entre el textarea de comentarios (grupal) y la tabla de facturas:
   sin esto los dos bloques se leen como una sola sección. */
.fa-editar-titulo-facturas {
  margin-top: 2rem;
}

/* Número de factura: readonly (no editable). Apagado y con cursor de
   "no permitido" para señalar que no se puede modificar. */
.fa-tabla .fa-input-celda--readonly {
  color: #9fa7b5;
  cursor: not-allowed;
}

.fa-tabla .fa-input-celda--readonly:focus {
  border-bottom-color: transparent;
}

/* Tabla editable: columna # angosta y gris, columna acción al ras. */
.fa-tabla-editar .fa-tabla-editar-num {
  width: 42px;
  color: #9fa7b5;
  font-weight: 600;
}

.fa-tabla-editar .fa-tabla-editar-th-accion,
.fa-tabla-editar .fa-tabla-editar-td-accion {
  width: 44px;
  text-align: center;
}

.fa-tabla-editar tbody td {
  border-bottom: 1px solid #f0f1f4;
  padding: 0.35rem 0.5rem;
}

/* Botón icono para eliminar UNA factura de la tabla. Regla única (antes
   estaba duplicada en la sección del panel "Generar Factura"). */
.fa-btn-eliminar-fila {
  border: none;
  background: transparent;
  /* #828d9f = 3.36:1, supera el 3:1 que WCAG pide para íconos. */
  color: #828d9f;
  font-size: 0.85rem;
  /* Área de toque: 32x32 centrada (la celda mide 48px, hay lugar). */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 32px;
  min-height: 32px;
  padding: 0.3rem 0.45rem;
  border-radius: 6px;
  cursor: pointer;
  transition:
    color 0.15s ease,
    background-color 0.15s ease;
}

.fa-btn-eliminar-fila:hover,
.fa-btn-eliminar-fila:focus-visible {
  color: #c0392b;
  background: #fde8e8;
  outline: none;
}

/* Botón peligro (eliminar disposición completa): blanco con texto rojo
   en reposo, rojo pleno al hover — destructivo pero no grita en reposo. */
.fa-btn-peligro {
  background: #ffffff;
  color: #c0392b;
  border: 1px solid #f1c3bd;
  border-radius: 8px;
  padding: 0.5rem 1.2rem;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition:
    background-color 0.15s ease,
    border-color 0.15s ease,
    color 0.15s ease;
}

.fa-btn-peligro--sm {
  padding: 0.35rem 0.9rem;
  font-size: 0.78rem;
}

.fa-btn-peligro:hover,
.fa-btn-peligro:focus-visible {
  background: #c0392b;
  border-color: #c0392b;
  color: #ffffff;
}

.fa-btn-peligro:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(192, 57, 43, 0.18);
}

/* Deshabilitado: el rojo se apaga a gris. Mismo criterio que
   .fa-btn-secundario:disabled — el motivo viaja en el `title`. */
.fa-btn-peligro:disabled,
.fa-btn-peligro[disabled] {
  color: #9fa7b5;
  background: #f5f6fe;
  border-color: #e7e9ed;
  cursor: not-allowed;
}

.fa-btn-peligro:disabled:hover,
.fa-btn-peligro[disabled]:hover {
  color: #9fa7b5;
  background: #f5f6fe;
  border-color: #e7e9ed;
}

/* ── Acordeón de grupos: fila-grupo y sub-filas de disposiciones ── */
.fa-subrow {
  display: none;
  background: #fafbfc;
}

.fa-subrow--visible {
  display: table-row;
}

.fa-subrow td {
  font-size: 0.75rem;
  /* Antes #9fa7b5 (gris label): el dato por factura quedaba ilegible. Se
	   sube al gris de texto estándar (#5d6778, mismo que las filas normales)
	   para que los datos se LEAN — el usuario quiere verlos, no insinuarlos. */
  color: #5d6778;
}

.fa-grupo-toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border: none;
  background: none;
  cursor: pointer;
  padding: 2px 6px;
  border-radius: 4px;
}

.fa-grupo-toggle:hover {
  background: #f0f1f4;
}

/* Chevron que señala que el conteo es un desplegable. Caret hecho con
   bordes (sin assets) que apunta hacia abajo y rota 180° al abrir el
   grupo. Se apoya en el aria-expanded que ya togglea el engine
   (tabla_datos.js); por eso es CSS puro, sin tocar el render. */
.fa-grupo-toggle::after {
  content: "";
  display: inline-block;
  width: 6px;
  height: 6px;
  margin-bottom: 2px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg);
  transition:
    transform 0.18s ease,
    opacity 0.18s ease;
  opacity: 0.65;
}

/* Al pasar por la fila el caret se intensifica → refuerza que es desplegable. */
.fa-grupo-row:hover .fa-grupo-toggle::after {
  opacity: 0.9;
}

.fa-grupo-toggle[aria-expanded="true"]::after {
  transform: rotate(-135deg);
  margin-bottom: 0;
  margin-top: 2px;
  opacity: 0.9;
}

.fa-grupo-row {
  background: #fff;
  font-weight: 500;
  /* Toda la fila es click-target: la columna #Disp. (flecha + número)
     expande/colapsa; el resto de la fila navega al detalle de estatus
     (filaClickVerUrl en tabla_datos.js). */
  cursor: pointer;
}

/* ── Expanded group: anidación por guía vertical ────────────────────────
   Grupo abierto (toggle[aria-expanded="true"]): el estado se comunica con
   UNA guía vertical izquierda (#4472C4) que recorre el header del grupo Y
   todas sus sub-filas visibles → forma un bar único e ininterrumpido que
   dice "estas facturas pertenecen a esta disposición" (Gestalt: región
   común). Se quitó la línea azul horizontal superior: marcaba un borde, no
   contención, y bracketeaba contra la fila ANTERIOR (límite equivocado).
   El header se separa de su detalle con un divisor gris sutil; la guía
   vertical hace el trabajo de anidación, no el horizontal.
   Usa :has() — soportado en navegadores modernos (Chrome 105+, FF 121+). */
.fa-grupo-row:has(.fa-grupo-toggle[aria-expanded="true"]) td {
  border-bottom: 1px solid #e7e9ed;
}

.fa-grupo-row:has(.fa-grupo-toggle[aria-expanded="true"]) td:first-child {
  box-shadow: inset 3px 0 0 #4472c4;
}

/* Sin separadores horizontales DENTRO del detalle: las sub-filas comparten
   fondo recesado + la guía vertical, así que las líneas entre facturas solo
   ensuciaban. El bloque se lee como una región continua; el escalón de bg
   (blanco→recesado) ya separa el detalle de la fila-grupo y de la siguiente. */
.fa-tabla-wrapper--scroll .fa-tabla tbody tr.fa-subrow--visible td {
  border-bottom: 0;
}

/* Guía vertical continua: la primera celda de cada sub-fila visible repite
   la barra azul del grupo → un bar único que conecta las facturas con su
   disposición. Indent leve (1.5rem vs 0.75rem base) para el escalón visual
   de hija, sin descuadrar el resto de las columnas. */
/* Scope con #tabla-disposiciones para ganar especificidad sobre la regla de
   padding ajustado (#tabla-disposiciones td) y conservar el indent de hija. */
#tabla-disposiciones tbody tr.fa-subrow--visible td:first-child {
  box-shadow: inset 3px 0 0 #4472c4;
  padding-left: 1.5rem;
}

/* ══════════════════════════════════════════════════════════════
   WIDGET CUPO DISPONIBLE — Panel Generar Factura
   ──────────────────────────────────────────────────────────────
   Muestra restante / total + barra de uso coloreada.
   Estado de color:
     verde  → usa < 50 % del cupo
     ámbar  → usa 50–80 %
     rojo   → usa > 80 %  (o restante negativo)
   ══════════════════════════════════════════════════════════════ */

.fa-cupo-widget {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  padding: 0.3rem 0;
}

/* Etiqueta clickeable "Línea"/"Global" — alterna el modo del widget sin
   refetch (cupo-global-vendedor). Estado activo visualmente distinto para
   no confundir cuál de los dos topes se está viendo. */
.fa-cupo-modo {
  cursor: pointer;
  font-weight: 700;
  color: #4472c4;
  border-bottom: 1px dashed #4472c4;
  user-select: none;
}
.fa-cupo-modo:hover {
  color: #2f5aa8;
}

/* Fila superior: restante / de / total */
.fa-cupo-cifras {
  display: flex;
  align-items: baseline;
  gap: 0.35rem;
  line-height: 1.4;
}

.fa-cupo-restante {
  font-size: 0.95rem;
  font-weight: 700;
  color: #252930;
  font-variant-numeric: tabular-nums;
  transition: color 0.25s ease;
}

.fa-cupo-restante--placeholder {
  color: #c8cdd6;
  font-weight: 600;
}

.fa-cupo-sep {
  font-size: 0.72rem;
  color: #9fa7b5;
  font-weight: 500;
}

.fa-cupo-total {
  font-size: 0.78rem;
  color: #9fa7b5;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}

/* Fila inferior: barra + porcentaje */
.fa-cupo-barra-wrap {
  display: flex;
  align-items: center;
  gap: 0.55rem;
}

.fa-cupo-barra {
  display: flex;
  flex: 1;
  height: 5px;
  background: #e7e9ed;
  border-radius: 4px;
  overflow: hidden;
}

/* Segmento amarillo: cupo ya ocupado por disposiciones previas (antes del form) */
.fa-cupo-barra__ocupado {
  height: 100%;
  width: 0%;
  flex-shrink: 0;
  background: #f1c40f; /* ámbar: ocupado hasta ahora */
  transition: width 0.3s ease;
}

/* Segmento gris: disposiciones en proceso (todavía no cerraron su paso 4).
   No ocupan línea —el cupo no las cuenta— pero la van a ocupar en cuanto se
   dispongan, así que el alta las descuenta de lo que deja capturar. Tono
   intermedio entre el ocupado y el fill a propósito: se lee como "hablado,
   todavía no gastado". */
.fa-cupo-barra__por-disponer {
  height: 100%;
  width: 0%;
  flex-shrink: 0;
  background: #c9ccd4;
  transition: width 0.3s ease;
}

/* Segmento verde: crece con las facturas capturadas en el formulario */
.fa-cupo-barra__fill {
  height: 100%;
  width: 0%;
  flex-shrink: 0;
  background: #27ae60; /* verde base */
  transition:
    width 0.3s ease,
    background 0.3s ease;
}

.fa-cupo-pct {
  font-size: 0.7rem;
  font-weight: 700;
  color: #9fa7b5;
  min-width: 2.8rem;
  text-align: right;
  font-variant-numeric: tabular-nums;
  transition: color 0.25s ease;
}

.fa-cupo-pct--placeholder {
  color: #c8cdd6;
  font-weight: 600;
}

/* ── Modificador de color: rojo solo si se excede el cupo ── */

.fa-cupo-widget--critico .fa-cupo-barra__fill {
  background: #e74c3c;
}
.fa-cupo-widget--critico .fa-cupo-restante {
  color: #e74c3c;
}
.fa-cupo-widget--critico .fa-cupo-pct {
  color: #e74c3c;
}

/* ── Barra de cupo dentro de una tabla (.fa-tabla-lineas) ──
   Modificadores genéricos de la barra de cupo, acá y no en el <style> de una
   página porque ya tienen dos consumidores: las "Líneas del vendedor" del Paso
   1 de /pagos y la tabla de líneas por vendedor del tablero COF.

   f_pagos/estatus_pago.html conserva sus equivalentes con prefijo
   `fa-pago-cupo-*` (mismos valores, nombres viejos): renombrarlos ahí es un
   cambio aparte, no arrastrable a este. */

/* Rojo cuando lo dispuesto se pasó de la línea: el ámbar de .fa-cupo-barra__
   ocupado significa "ocupado", no "excedido". */
.fa-cupo-barra__ocupado--excedido {
  background: #e74c3c;
}

.fa-cupo-pct--excedido {
  color: #e74c3c;
}

/* Una línea sin tope (monto_linea NULL) no dibuja barra: en su lugar va el
   texto "Sin límite", en el gris de dato secundario. */
.fa-cupo-sin-limite {
  font-size: 0.75rem;
  color: #9fa7b5;
}

/* La barra vive dentro de una celda, así que el wrap no debe estirarse a lo
   ancho de la columna del monto. */
.fa-tabla-lineas .fa-cupo-barra-wrap {
  min-width: 9rem;
}
.fa-tabla-lineas .fa-cupo-pct {
  min-width: 2.4rem;
}

/* ══════════════════════════════════════════════════════════════
   PASO 3 — NOTIFICACIÓN (estatus.html)
   ──────────────────────────────────────────────────────────────
   Checklist de 4 etapas + contexto de vendedor para el panel
   del ciclo de vida "Notificación".
   ══════════════════════════════════════════════════════════════ */

/* Context sub-header: vendedor / cofactor / moneda above the checklist */
.fa-notif-vendedor-ctx {
  font-size: 0.75rem;
  color: #6c757d;
  margin-bottom: 1rem;
}

/* Ordered list container — vertical rhythm */
.fa-notif-checklist {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

/* Stage row: badge + body + actions (flex layout). Recuadro más compacto
   (padding vertical reducido) — menos aire por etapa sin perder el
   click-target de los botones de acción. */
.fa-notif-stage {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  padding: 0.6rem 0;
}

/* Estado de la etapa: iconografía, no texto.
   Completada → disco verde con palomita. Pendiente → anillo vacío.
   El mismo elemento sirve para ambos: la palomita se oculta en pendiente. */
.fa-notif-check {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.1rem;
  height: 1.1rem;
  border-radius: 50%;
  flex-shrink: 0;
  margin-top: 0.1rem;
  font-size: 0.58rem;
  transition:
    background 0.15s ease,
    border-color 0.15s ease;
}
.fa-notif-check--completada {
  background: #1e8e3e;
  border: 1px solid #1e8e3e;
  color: #ffffff;
}
/* Hecha pero sin alcanzar (complemento registrado que no cubre el faltante):
   mismo ámbar que el paso en amarillo del timeline. */
.fa-notif-check--insuficiente {
  background: var(--fa-sem-ambar-600);
  border: 1px solid var(--fa-sem-ambar-600);
  color: #ffffff;
}
.fa-notif-check--pendiente {
  background: transparent;
  border: 1.5px solid #c8cdd6;
  color: transparent;
}
.fa-notif-check--pendiente > i {
  visibility: hidden;
}

/* Aviso de fallo de la última acción — junto al título de la etapa */
.fa-notif-stage-error {
  color: #c0392b;
  font-size: 0.75rem;
  margin-left: 0.35rem;
}

/* Label + description column */
.fa-notif-stage-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}

/* Bold stage name */
.fa-notif-stage-label {
  font-size: 0.85rem;
  font-weight: 600;
  color: #252930;
}

/* Secondary description text */
.fa-notif-stage-desc {
  font-size: 0.75rem;
  color: #9fa7b5;
}

/* Action slot — trailing edge */
.fa-notif-stage-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-shrink: 0;
}

/* Ancho común de la acción principal de cada etapa.
   Las etiquetas tienen largos distintos ("Correo" y "Cargar"), así que
   sin un piso
   común la columna de acciones y los kebabs quedan dentados entre filas.
   5.5rem (88px) cubre la etiqueta más ancha con margen holgado para
   variaciones de fuente entre sistemas, sin recortar texto (el base ya
   trae white-space: nowrap).
   El ícono queda anclado al borde izquierdo (justify-content: flex-start)
   y no se corre entre filas aunque cambie el largo de la etiqueta; la
   etiqueta se centra en el espacio restante vía .fa-btn-icono-texto (regla
   siguiente), que es lo que de verdad varía de ancho entre "Correo" y
   "Cargar".
   Se usa `>` a propósito: el kebab es nieto (.fa-kebab > .fa-btn-icono) y
   debe conservar su ancho compacto de ícono. */
.fa-notif-stage-actions > .fa-btn-icono,
.fa-notif-stage-actions > form > .fa-btn-icono {
  min-width: 5.5rem;
  justify-content: flex-start;
}

/* Piso propio del checklist del cobro (/pagos): sus cuatro etapas se reparten
   entre dos pantallas, así que el ancho tiene que ser el mismo en las dos y no
   depender de cuál sea la etiqueta más larga de cada paso — con el piso común
   de 5.5rem, un paso con solo "Correo" quedaba más angosto que el que trae
   "Agregar". 7.5rem (120px) las cubre a todas con margen para variaciones de
   fuente entre sistemas. Va como modificador y no subiendo el piso común para
   no ensanchar el checklist del Paso 3 de /disposiciones, que se ve entero de
   una sola vez. */
.fa-notif-checklist--pago .fa-notif-stage-actions > .fa-btn-icono,
.fa-notif-checklist--pago .fa-notif-stage-actions > form > .fa-btn-icono {
  min-width: 7.5rem;
}

/* Etiqueta de la acción principal de cada etapa: ocupa el espacio que deja
   libre el ícono anclado a la izquierda y centra su texto ahí — así el
   ícono queda fijo en la misma columna en las 5 filas y el texto no arrastra
   el layout completo hacia la izquierda por ser más angosto que el botón.
   No toca el ícono (flex-shrink: 0 evita que se comprima si el texto crece)
   ni a otros consumidores de .fa-btn-icono (toolbar de Enviar, Para/CC,
   kebab): la regla está scopeada al slot de acciones de etapa. */
.fa-notif-stage-actions > .fa-btn-icono > .fa-btn-icono-texto,
.fa-notif-stage-actions > form > .fa-btn-icono > .fa-btn-icono-texto {
  flex: 1;
  text-align: center;
}
/* FontAwesome se carga por JS (all.min.js) y reemplaza cada <i> por un
   <svg>, así que una regla que apunte solo a `i` deja de aplicar apenas
   termina de cargar. Se listan ambos para cubrir el render inicial y el
   definitivo. */
.fa-notif-stage-actions > .fa-btn-icono > i,
.fa-notif-stage-actions > .fa-btn-icono > svg,
.fa-notif-stage-actions > form > .fa-btn-icono > i,
.fa-notif-stage-actions > form > .fa-btn-icono > svg {
  flex-shrink: 0;
}

/* ── Compact icon button (PR 4: UI restructure) ──────────────
   Primary variant: navy blue — identical hue to .fa-btn-accion.
   Secondary variant (.fa-btn-icono--sec): white with border,
   mirrors .fa-btn-secundario.  Never in portal.css. */
.fa-btn-icono {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  background: #012e92;
  color: #ffffff;
  border: 1px solid transparent;
  border-radius: 6px;
  padding: 0.3rem 0.6rem;
  font-size: 0.72rem;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
  transition:
    background 0.15s ease,
    border-color 0.15s ease;
  white-space: nowrap;
  line-height: 1.3;
}
.fa-btn-icono:hover {
  background: #023ab5;
  color: #ffffff;
  text-decoration: none;
}

/* Secondary — white with border, same hover tint as .fa-btn-secundario */
.fa-btn-icono--sec {
  background: #ffffff;
  color: #252930;
  border-color: #e0e3e8;
}
.fa-btn-icono--sec:hover {
  background: var(--color-acento-fila-suave, #f0f2ff);
  border-color: var(--color-acento-fila, #4472C4);
  color: var(--color-acento-fila, #4472C4);
  text-decoration: none;
}

/* Bloqueado — la acción existe pero todavía no le toca (paso secuencial).
   Gris apagado, mismo lenguaje visual que .fa-kebab-item--inactivo.

   NO se usa el atributo `disabled` ni `pointer-events: none`: la acción
   principal de una etapa puede ser un <label> (el de subir archivo, que no
   admite disabled), y un elemento sin eventos no puede explicar POR QUÉ está
   bloqueado. El click se sigue recibiendo y el JS del módulo lo intercepta en
   fase de captura para mostrar el motivo (data-bloqueado-msg). El cursor
   `not-allowed` es la señal de que no va a hacer lo de siempre. */
.fa-btn-icono--bloqueado,
.fa-btn-icono--bloqueado:hover {
  background: #f0f1f4;
  color: #9fa7b5;
  border-color: #e7e9ed;
  cursor: not-allowed;
}

/* Botón que alterna entre alta y edición (etapa 4 del Paso 1 de /pagos): los
   dos íconos vienen renderizados y el modificador elige cuál se muestra. Es
   CSS y no un swap de clases en JS porque FontAwesome ya reemplazó cada <i>
   por un <svg> que trae el path adentro: cambiarle la clase al svg no cambia
   el dibujo. `display` (no visibility) para que el ícono oculto no ocupe
   lugar dentro del botón. */
.fa-btn-icono .fa-icono-edicion,
.fa-btn-icono--registrado .fa-icono-alta {
  display: none;
}
.fa-btn-icono--registrado .fa-icono-edicion {
  display: inline-block;
}

/* Mismo gris para el botón deshabilitado por `disabled` (el "Enviar" de un
   correo ya enviado, o cualquier acción mientras su fetch está en vuelo). Sin
   esta regla conserva el navy de una acción viva y lo único que delata el
   estado es que el click no hace nada. Los dos estados no-accionables del
   mismo botón se ven igual a propósito: la diferencia entre "todavía no toca"
   y "ya se hizo" la explica el mensaje, no el color. */
.fa-btn-icono:disabled,
.fa-btn-icono:disabled:hover {
  background: #f0f1f4;
  color: #9fa7b5;
  border-color: #e7e9ed;
  cursor: not-allowed;
}

/* ── Kebab de acciones secundarias ───────────────────────────
   Cada etapa expone UN botón principal; el resto de las acciones
   (plantillas, descargas, ver documento) viven acá. A diferencia del
   botón principal, el kebab es un disparador neutro: fondo blanco, sin
   borde y solo los tres puntos en negro, para que no compita con la
   acción azul de la fila. Sobrescribe el fondo navy y el texto blanco
   que hereda de .fa-btn-icono (gana por orden de aparición, misma
   especificidad). */
.fa-kebab {
  position: relative;
  display: inline-flex;
}
.fa-kebab-btn {
  padding: 0.3rem 0.5rem;
  background: #ffffff;
  border-color: transparent;
  color: #1a1a1a;
}
.fa-kebab-btn:hover,
.fa-kebab-btn[aria-expanded="true"] {
  background: var(--color-hover-gris, #f0f1f4);
  color: #1a1a1a;
}
/* Sin borde ni fondo de color, el foco de teclado necesita su propio
   anillo: el disparador abre un menú y debe ser localizable sin mouse. */
.fa-kebab-btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(68, 114, 196, 0.22);
}
.fa-kebab-menu {
  position: absolute;
  top: calc(100% + 0.3rem);
  right: 0;
  z-index: 20;
  min-width: 12rem;
  display: flex;
  flex-direction: column;
  padding: 0.25rem;
  background: #ffffff;
  border: 1px solid #e7e9ed;
  border-radius: 6px;
  box-shadow: 0 6px 18px rgba(26, 26, 26, 0.12);
}
.fa-kebab-menu[hidden] {
  display: none;
}
/* Botón partido «Enviar | v» (macro boton_enviar_split). El cuerpo envía y la
   flecha despliega «Marcar como enviado», para cuando el correo tuvo que salir
   por fuera del sistema.

   Las dos mitades se pegan sin costura: el botón de envío pierde el radio
   derecho y la flecha el izquierdo, con una línea tenue de separación. La
   flecha NO reusa el look neutro de .fa-kebab-btn (fondo blanco) — acá es la
   segunda mitad del botón principal, así que hereda su fondo, y por eso las
   reglas van DESPUÉS de las del kebab. */
.fa-btn-split {
  display: inline-flex;
  align-items: stretch;
}
.fa-btn-split > .fa-btn-icono {
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
}
.fa-btn-split-flecha {
  padding: 0.3rem 0.55rem;
  background: inherit;
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
  border-left: 1px solid rgba(255, 255, 255, 0.28);
}
/* El fondo lo pone el contenedor y no `inherit` sobre el <button>: el
   .fa-kebab intermedio no tiene fondo propio, así que heredar lo dejaría
   transparente sobre el panel blanco. */
.fa-btn-split-mas {
  background: #012e92;
  border-radius: 0 6px 6px 0;
}
.fa-btn-split-flecha,
.fa-btn-split-flecha:hover,
.fa-btn-split-flecha[aria-expanded="true"] {
  color: #ffffff;
}
.fa-btn-split-flecha:hover,
.fa-btn-split-flecha[aria-expanded="true"] {
  background: rgba(255, 255, 255, 0.14);
}

/* Hueco del kebab (macro notif_kebab_hueco): ocupa el mismo ancho que un
   kebab real para que las etapas sin menú alineen su acción principal con las
   que sí lo tienen. visibility (no display) es lo que conserva la caja. */
.fa-kebab-hueco {
  display: inline-flex;
  visibility: hidden;
}
.fa-kebab-item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  padding: 0.45rem 0.6rem;
  background: transparent;
  border: none;
  border-radius: 4px;
  color: #252930;
  font-size: 0.75rem;
  font-weight: 500;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
}
.fa-kebab-item > i {
  width: 1rem;
  color: #012e92;
}
.fa-kebab-item:hover {
  background: var(--color-acento-fila-suave, #f0f2ff);
  color: #012e92;
  text-decoration: none;
}
/* Acción que aún no aplica (documento sin cargar): visible pero atenuada;
   el JS la intercepta y explica por qué en vez de abrir un 404. */
.fa-kebab-item--inactivo {
  color: #9fa7b5;
  cursor: not-allowed;
}
.fa-kebab-item--inactivo > i {
  color: #c8cdd6;
}
.fa-kebab-item--inactivo:hover {
  background: transparent;
  color: #9fa7b5;
}

/* Attachment list + links in correo panels */
.fa-notif-attach-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  column-gap: 1.25rem;
  row-gap: 0.4rem;
}
.fa-notif-attach-link {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  color: #4472C4;
  font-size: 0.85rem;
  text-decoration: none;
  border: 1px solid #e7e9ed;
  border-radius: 6px;
  padding: 0.45rem 0.7rem;
  margin: 0.15rem;
  /* Ancho fijo de 13rem (208px): cubre la etiqueta más ancha medida
     ("Solicitud vendedor firmada", 206.11px) y mantiene los chips
     uniformes aunque cambien los textos. Si en el futuro un nombre no
     entra, se trunca con ellipsis y el title del <a> lo revela en hover. */
  width: 13rem;
}
.fa-notif-attach-link:hover {
  text-decoration: none;
  border-color: #4472C4;
  background: #f0f2ff;
}
/* El ícono no debe encoger cuando el nombre largo fuerza la ellipsis;
   el ancho fijo del link lo cede el texto, no el ícono.
   Se incluye `svg` porque FontAwesome-JS sustituye el <i> por un <svg>. */
.fa-notif-attach-link > i,
.fa-notif-attach-link > svg {
  flex-shrink: 0;
}
/* Nombre visible del adjunto: trunca con ellipsis si no entra en el
   width fijo del link. Los atributos title del <a> lo develan en hover. */
.fa-notif-attach-nombre {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
.fa-notif-attach-link--pdf  { color: #c0392b; }
.fa-notif-attach-link--html { color: #4472C4; }
/* Verde del icono de Excel: reusamos el #1ca35e que ya usa
   #fa-btn-subir-excel .fa-file-excel, sin introducir un nuevo tono. */
.fa-notif-attach-link--excel { color: #1ca35e; }
/* Azul para Word: reusamos el azul de la paleta (#4472C4, también
   usado por la variante --html) para no introducir un nuevo color. */
.fa-notif-attach-link--word  { color: #4472C4; }
/* Naranja de PowerPoint: es el ÚNICO tono nuevo de la paleta de adjuntos.
   No hay ningún naranja reusable en el resto de la UI y las alternativas
   (rojo, azul) ya identifican PDF y Word — repetirlas volvería el color
   ambiguo justo donde su trabajo es distinguir el tipo de archivo. */
.fa-notif-attach-link--powerpoint { color: #c55a11; }
/* Archivo sin tipo reconocido: gris secundario de la paleta. No es un
   estado de error, así que no lleva color propio. */
.fa-notif-attach-link--generico { color: #9fa7b5; }
/* Mantener el color del texto en hover: el a:hover global de portal.css
   (#128c54, especificidad 0,1,1) le ganaba al color de la variante (0,1,0)
   y ponía el texto verde. Estas reglas :hover (0,2,0) lo fijan. */
.fa-notif-attach-link--pdf:hover   { color: #c0392b; }
.fa-notif-attach-link--html:hover  { color: #4472C4; }
.fa-notif-attach-link--excel:hover { color: #1ca35e; }
.fa-notif-attach-link--word:hover  { color: #4472C4; }
.fa-notif-attach-link--powerpoint:hover { color: #c55a11; }
.fa-notif-attach-link--generico:hover   { color: #9fa7b5; }
/* Adjunto aún no cargado: visible pero atenuado, mismo patrón que
   .fa-kebab-item--inactivo. El JS (notificacion.js) quita la clase
   cuando se sube el documento. */
.fa-notif-attach-link--inactivo {
  color: #9fa7b5;
  cursor: not-allowed;
}
.fa-notif-attach-link--inactivo > i,
.fa-notif-attach-link--inactivo > svg {
  color: #c8cdd6;
}
.fa-notif-attach-link--inactivo:hover {
  background: transparent;
  color: #9fa7b5;
}

/* Adjuntos con botón de quitar (libres de t020 y defaults de t013): una sola
   tarjeta `[ NOMBRE | X ]`. El borde, el radio, el fondo y el ancho fijo son
   del <li>, no del chip de adentro: así el botón queda DENTRO del recuadro y
   el divisor lo separa del nombre. Un chip suelto (`notif_adjunto`, sin
   botón) conserva ese mismo borde en .fa-notif-attach-link y las dos formas
   se leen como la misma familia.

   El hueco (.fa-adjunto-hueco) comparte estas reglas de PRESENTACIÓN y ninguna
   de COMPORTAMIENTO: .fa-adjunto-item y .fa-adjunto-catalogo son las clases que
   barren `pintarAdjuntos()` y el delegado de exclusión, y el hueco no lleva
   ninguna de las dos (ver el bloque del <li> en macros/notificacion.html). Por
   eso se lista acá en vez de heredar la clase. */
.fa-adjunto-item,
.fa-adjunto-hueco {
  display: inline-flex;
  align-items: stretch;
  border: 1px solid #e7e9ed;
  border-radius: 6px;
  background: #fff;
  margin: 0.15rem;
  /* Mismo ancho total que un chip suelto (13rem), para que la fila no se lea
     como dos tamaños de tarjeta. */
  width: 13rem;
  overflow: hidden;
}
/* La mitad que hoy no viaja de un par de adjuntos excluyentes nace con
   `hidden` (macro notif_adjunto). Sin esta regla el display:inline-flex de
   arriba le gana a la regla [hidden] del navegador y el chip se sigue viendo:
   el modo de fallar es exactamente el bug que el par vino a resolver. */
.fa-adjunto-item[hidden],
.fa-adjunto-hueco[hidden] {
  display: none;
}
/* El chip de adentro cede el chrome a la tarjeta y se queda solo con el
   contenido; el ancho lo reparte flex, no una medida escrita a mano. */
.fa-adjunto-item .fa-notif-attach-link,
.fa-adjunto-hueco .fa-notif-attach-link {
  border: none;
  border-radius: 0;
  background: transparent;
  margin: 0;
  width: auto;
  flex: 1 1 auto;
  min-width: 0;
}
.fa-adjunto-item .fa-notif-attach-link:hover,
.fa-adjunto-hueco .fa-notif-attach-link:hover {
  background: transparent;
}
.fa-adjunto-item:hover {
  border-color: #4472C4;
  background: #f0f2ff;
}
.fa-adjunto-quitar,
.fa-adjunto-quitar-hueco {
  border: none;
  /* El divisor es lo que hace legible la tarjeta como `[ NOMBRE | X ]`. */
  border-left: 1px solid #e7e9ed;
  background: transparent;
  color: #9fa7b5;
  font-size: 0.9rem;
  line-height: 1;
  cursor: pointer;
  padding: 0 0.5rem;
  flex: 0 0 auto;
}
.fa-adjunto-item:hover .fa-adjunto-quitar {
  border-left-color: #4472C4;
}
.fa-adjunto-quitar:hover {
  color: #d64545;
}
/* Hueco de lo que el correo ESPERA llevar y todavía no tiene. Se ve EXACTAMENTE
   igual que una tarjeta de adjunto —misma caja, mismo ícono por tipo, misma
   tipografía y mismo ancho— porque el chrome lo aportan las reglas de
   .fa-adjunto-item de arriba, que lo listan. Acá solo queda lo que lo
   distingue: no es clickeable, así que no tiene cursor de link ni hover.

   El hover se deja afuera a propósito: cambiarle el borde a algo que no se
   puede abrir es un control que miente, que es justo lo que este chip no debe
   ser. */
.fa-adjunto-hueco {
  cursor: default;
}
/* Reserva del ancho del botón de quitar, para que la caja mida lo mismo que una
   tarjeta con botón. Es un <span> con visibility:hidden y no un <button>: acá no
   hay nada que borrar ni que excluir. visibility:hidden lo saca del orden de
   tabulación y de los clicks, así que no hay un botón fantasma (mismo criterio
   que `notif_kebab_hueco`). Las métricas las hereda del selector de
   .fa-adjunto-quitar; la clase propia es lo que lo deja fuera del delegado de
   borrado de notificacion.js. */
.fa-adjunto-quitar-hueco {
  visibility: hidden;
}

/* Estado vacío de la lista: mismo gris de los textos secundarios. */
.fa-adjunto-vacio {
  color: #9fa7b5;
  font-size: 0.8rem;
  padding: 0.45rem 0;
}

/* Grilla de UN panel de correo: defaults de plantilla (t013) + libres (t020)
   comparten este <ul>, mismo layout que .fa-notif-attach-list. */
.fa-adjunto-grid {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  column-gap: 1.25rem;
  row-gap: 0.4rem;
}

/* La etiqueta «Adjuntar» y la primera tarjeta deben arrancar en la MISMA
   línea. El desfase venía de tres separaciones superiores apiladas —el
   padding del campo, el margen del <ul> y el de cada chip—, que acá se
   anulan por arriba; la separación entre tarjetas la dan column-gap/row-gap.
   El modificador acota la regla a la barra de adjuntos: Para/CC comparten
   .fa-correo-campo y conservan su respiro. */
.fa-correo-campo--adjuntos {
  padding-top: 0;
  /* Sin adjuntos este campo no tiene NINGÚN hijo con altura: el <ul> queda
     vacío y el <form> solo guarda un <input type="file" hidden>. Con el
     padding-top de arriba en cero colapsa a la altura del borde, y como el
     contenedor alinea a flex-start, su border-bottom se dibujaba a la altura
     del BORDE SUPERIOR del botón «Adjuntar» en vez de al pie de la fila.
     `stretch` le devuelve el alto de la línea flex —que fija ese botón— sin
     tocar el caso con adjuntos, donde el alto ya lo pone el contenido.
     Para/CC no lo necesitan: su campo siempre lleva el chip-input. */
  align-self: stretch;
}
.fa-adjunto-grid > li,
.fa-adjunto-grid > .fa-adjunto-item,
.fa-adjunto-grid .fa-notif-attach-link {
  margin-top: 0;
}

/* Default de plantilla (t013): misma tarjeta que un libre, con un borde y un
   fondo propios para no leerse como "eliminado" al excluirlo de este envío —
   a diferencia de un libre borrado, una recarga del panel lo vuelve a
   mostrar. El chrome vive en el <li>, igual que en la tarjeta base. */
.fa-adjunto-item--defecto {
  border-color: #4472C4;
  background: #eef1fb;
}
.fa-adjunto-item--defecto .fa-adjunto-quitar {
  border-left-color: #4472C4;
}

/* Adjunto del CATÁLOGO (documento del expediente, fijo del repo o plantilla
   generada): misma tarjeta `[ NOMBRE | X ]` que un default o un libre, así
   que el chrome lo aporta .fa-adjunto-item y acá NO se clona ninguna de sus
   reglas. Esta clase queda como IDENTIDAD: la leen
   `correo_adjuntos_exclusion.js` y el corte de `pintarAdjuntos()`, y es el
   ancla del estado de exclusión de abajo. Un chip del catálogo SIN botón de
   quitar (`notif_adjunto` sin `clave_exclusion`) no lleva ninguna de las dos
   y sigue siendo el chip suelto de .fa-notif-attach-link. */

/* Excluido de ESTE envío: la tarjeta sigue ahí y un segundo click la
   restaura. Mismo lenguaje que un CC fijo excluido
   (.fa-correo-chip--excluido): atenuada y con el nombre tachado. */
.fa-adjunto-catalogo--excluido {
  opacity: 0.55;
}
.fa-adjunto-catalogo--excluido .fa-notif-attach-nombre {
  text-decoration: line-through;
}
/* Sin esto el hover de .fa-adjunto-item pinta de azul una tarjeta excluida y
   la deja indistinguible de una activa justo cuando el usuario apunta al ×
   para restaurarla. Atenuada + tachada tiene que seguir leyéndose como "no
   viaja", no como "algo se rompió". */
.fa-adjunto-catalogo--excluido:hover {
  border-color: #e7e9ed;
  background: #fff;
}
.fa-adjunto-catalogo--excluido:hover .fa-adjunto-quitar {
  border-left-color: #e7e9ed;
}

/* ============================================================
   Dashboard — Vista General (c_portal)
   Paleta propia de Factoraje: azul Delta (--color-acento-fila).
   ============================================================ */
/* Barra de filtros: la tarjeta y los botones de las tablas, sin tabla debajo.
   Sin tabla, el borde inferior del toolbar se encimaría con el de la tarjeta;
   el separador pasa a la barra de chips, que solo aparece con filtros. */
.fa-dash-barra-filtros {
  margin-bottom: 1.5rem;
}
.fa-dash-barra-filtros .fa-tabla-toolbar {
  border-bottom: none;
}
.fa-dash-barra-filtros .fa-chips-bar:not(.fa-chips-bar--empty) {
  border-top: 1px solid #e7e9ed;
}
/* Botón secundario blanco de «Limpiar» en los dropdowns de filtros. */
.fa-filtro-btn-limpiar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  border: 1px solid #e7e9ed;
  background: #fff;
  color: #252930;
  border-radius: 8px;
  font-family: inherit;
  font-weight: 600;
  line-height: 1.5;
  white-space: nowrap;
  cursor: pointer;
  transition:
    background-color 0.15s ease,
    border-color 0.15s ease,
    color 0.15s ease,
    box-shadow 0.15s ease;
}

.fa-filtro-btn-limpiar {
  padding: 0.35rem 0.9rem;
  font-size: 0.78rem;
}

.fa-filtro-btn-limpiar:hover {
  background: #f5f6fe;
  border-color: #9fa7b5;
  color: #1a1a1a;
}

.fa-filtro-btn-limpiar:active {
  background: #eef0f7;
}

.fa-filtro-btn-limpiar:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(68, 114, 196, 0.22);
}

/* Anchos según lo que carga cada tarjeta: las dos de montos (USD y MXN)
   necesitan aire, «Facturas vencidas hoy» es una sola cifra corta y la meta
   (el recuadro de /tareas) reparte tres cifras. */
.fa-dash-kpis {
  display: grid;
  grid-template-columns:
    minmax(0, 1.2fr) minmax(0, 1.2fr) minmax(0, 0.8fr) minmax(0, 1.9fr);
  gap: 1rem;
  margin-bottom: 1.5rem;
}
/* El recuadro de la meta con el marco de sus vecinas: en /tareas trae
   sombra, sin borde y `span 2` de su propia rejilla de cuatro columnas. */
.fa-dash-kpis .fa-tareas-kpi--meta {
  grid-column: auto;
  min-height: 0;
  padding: 0.8rem 1.1rem;
  border: 1px solid #e7e9ed;
  border-left: 5px solid var(--color-acento-fila);
  border-radius: 12px;
  box-shadow: none;
}
/* Sin espacio para las cuatro, la meta baja a su propio renglón completo. */
@media (max-width: 1400px) {
  .fa-dash-kpis {
    grid-template-columns: minmax(0, 1.2fr) minmax(0, 1.2fr) minmax(0, 0.8fr);
  }
  .fa-dash-kpis .fa-tareas-kpi--meta {
    grid-column: 1 / -1;
  }
}
@media (max-width: 800px) {
  .fa-dash-kpis {
    grid-template-columns: minmax(0, 1fr);
  }
}
.fa-dash-kpi {
  min-width: 0;
  background: #fff;
  border: 1px solid #e7e9ed;
  border-left: 5px solid var(--color-acento-fila);
  border-radius: 12px;
  padding: 0.8rem 1.1rem;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}
.fa-dash-kpi--alerta {
  border-left-color: #d9534f;
}
.fa-dash-kpi-label {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #9fa7b5;
}
.fa-dash-kpi-valor {
  font-size: 1.55rem;
  font-weight: 700;
  color: #1a1a1a;
  line-height: 1;
}
/* Número + monto lado a lado (KPI Próximas 48 h): evita la 3ª línea que
   estiraba la altura de TODAS las tarjetas del grid. */
.fa-dash-kpi-cifra {
  display: flex;
  align-items: baseline;
  gap: 0.45rem;
}
.fa-dash-kpi-sub {
  font-size: 0.78rem;
  color: #9fa7b5;
}
/* KPI con dos montos (Volumen financiado valorizado): el USD manda y el MXN
   va debajo, más chico, para no estirar de más la fila de tarjetas. */
.fa-dash-kpi-valor--secundario {
  font-size: 1.1rem;
  color: #252930;
}
/* Etiqueta + conteo en un renglón (Próximas disposiciones): así la tarjeta
   mide lo mismo que la del volumen, que también lleva USD y MXN. */
.fa-dash-kpi-encabezado {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.5rem;
}
.fa-dash-kpi-moneda {
  font-size: 0.72rem;
  font-weight: 700;
  color: #9fa7b5;
}

.fa-dash-graficas {
  display: grid;
  grid-template-columns: repeat(3, 1fr); /* 3×2: tres por fila */
  gap: 1rem;
}
/* Las tarjetas de un renglón miden lo que la más alta (el grid las estira) y
   cada gráfica se queda con el alto que le sobra a su tarjeta, en vez de un
   alto fijo que dejaba huecos abajo. El canvas va absoluto para que NO aporte
   alto: con él en el flujo, Chart.js lo agrandaría, la tarjeta crecería y el
   renglón con ella, en un ciclo. */
.fa-dash-graficas .fa-dash-card {
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.fa-dash-graficas .fa-dash-canvas-wrap {
  flex: 1 1 auto;
  height: auto;
  min-height: 220px;
}
.fa-dash-graficas .fa-dash-canvas-wrap canvas {
  position: absolute;
  inset: 0;
}
@media (max-width: 1100px) {
  .fa-dash-graficas {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (max-width: 700px) {
  .fa-dash-graficas {
    grid-template-columns: 1fr;
  }
}
.fa-dash-card {
  background: #fff;
  border: 1px solid #e7e9ed;
  border-radius: 14px;
  padding: 1.25rem;
}
.fa-dash-card-titulo {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #9fa7b5;
  margin-bottom: 0.9rem;
}
.fa-dash-canvas-wrap {
  position: relative;
  height: 220px;
}
/* Empty state de cada gráfica: overlay centrado sobre el canvas oculto. */
.fa-dash-vacio {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  text-align: center;
  color: #9fa7b5;
  font-size: 0.825rem;
}
.fa-dash-vacio i {
  font-size: 1.6rem;
  color: #e7e9ed;
}
.fa-dash-vacio[hidden] {
  display: none; /* gana al display:flex cuando el JS lo oculta */
}

/* ==========================================================================
   Dashboards → pestaña General (volumen operado)
   Layout de dos columnas: la gráfica (flexible, crece con la serie) + un panel
   de configuración angosto a la derecha. En pantallas chicas se apila.
   ========================================================================== */
.fa-dash-general {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 260px;
  gap: 1rem;
  margin-top: 1rem;
  /* align-items por defecto (stretch): las dos columnas quedan a la MISMA
     altura, la del panel de configuración (la más alta). Así la caja de la
     gráfica tiene su alto reservado desde el inicio y no salta al cargar. */
}
@media (max-width: 900px) {
  .fa-dash-general {
    grid-template-columns: 1fr;
  }
}
.fa-dash-card--grafica {
  min-width: 0; /* deja que el canvas encoja dentro del grid */
  /* Columna flex para que el canvas absorba el alto sobrante (encabezado y
     total ocupan lo suyo; el resto es la gráfica). */
  display: flex;
  flex-direction: column;
}
.fa-dash-card-encabezado {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}
/* La caja del canvas crece hasta llenar el alto de la tarjeta (igualado al del
   panel de config por el stretch del grid); min-height es el piso cuando el
   layout se apila en una sola columna. */
.fa-dash-canvas-wrap--alta {
  flex: 1 1 auto;
  min-height: 320px;
}
@media (max-width: 700px) {
  .fa-dash-canvas-wrap--alta {
    min-height: 280px;
  }
}
/* Antes de que Chart.js inicialice, el <canvas> mide 150px por defecto y deja
   la caja a medias; forzarlo a llenar la caja reserva el alto desde el arranque. */
#chartVolumen {
  width: 100%;
  height: 100%;
}

/* Leyenda período cerrado / en curso — la identidad no queda solo en el color. */
.fa-dash-leyenda {
  display: flex;
  gap: 1rem;
  list-style: none;
  margin: 0 0 0.9rem;
  padding: 0;
  font-size: 0.75rem;
  color: #9fa7b5;
}
.fa-dash-leyenda li {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
.fa-dash-leyenda[hidden] {
  display: none;
}
.fa-dash-leyenda-marca {
  width: 12px;
  height: 12px;
  border-radius: 3px;
  display: inline-block;
}
.fa-dash-leyenda-marca--cerrado {
  background: #12309b; /* azul Monex */
}
.fa-dash-leyenda-marca--curso {
  background: #5bd1e0; /* turquesa Monex */
}

/* Total del período — figura destacada al pie de la gráfica. */
.fa-dash-total {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px solid #f0f1f4;
}
.fa-dash-total[hidden] {
  display: none;
}
.fa-dash-total-texto {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}
.fa-dash-total-label {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #9fa7b5;
}
.fa-dash-total-rango {
  font-size: 0.85rem;
  font-weight: 600;
  color: #252930;
}
.fa-dash-total-cifra {
  display: flex;
  align-items: baseline;
  gap: 0.35rem;
  font-size: 1.65rem;
  font-weight: 700;
  color: #12309b;
  font-variant-numeric: tabular-nums;
}
.fa-dash-total-unidad {
  font-size: 0.85rem;
  font-weight: 600;
  color: #9fa7b5;
}
/* Versión de tarjeta chica (Vista general): el total se encoge, y la gráfica
   puede bajar de los 220px de piso porque leyenda y total ya ocupan su parte. */
.fa-dash-graficas .fa-dash-canvas-wrap--con-total {
  min-height: 170px;
}
.fa-dash-total--compacto {
  margin-top: 0.6rem;
  padding-top: 0.6rem;
}
.fa-dash-total--compacto .fa-dash-total-cifra {
  font-size: 1.2rem;
}
.fa-dash-total--compacto .fa-dash-total-rango {
  font-size: 0.78rem;
}
.fa-dash-aviso {
  margin: 0.5rem 0 0;
  font-size: 0.75rem;
  color: #9fa7b5;
}
.fa-dash-aviso[hidden] {
  display: none;
}

/* ── Panel de configuración ─────────────────────────────────────────────── */
.fa-dash-config {
  background: #fff;
  border: 1px solid #e7e9ed;
  border-radius: 14px;
  padding: 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
  position: sticky;
  top: 1rem;
}
.fa-dash-config-titulo {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0;
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #9fa7b5;
}
.fa-dash-config-titulo i {
  color: #12309b;
}
.fa-dash-config-grupo {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}
.fa-dash-config-label {
  font-size: 0.78rem;
  font-weight: 600;
  color: #252930;
}
/* Encabezado de grupo: la label a la izquierda y su acción ("Limpiar") a la
   derecha, en la misma línea. Solo lo usan los grupos que tienen acción; el
   wrap evita que la acción desborde el aside de 260 px si crece el texto. */
.fa-dash-config-cab {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.4rem;
}
.fa-dash-config-limpiar {
  border: none;
  background: none;
  padding: 0;
  font-family: inherit;
  font-size: 0.7rem;
  font-weight: 600;
  color: #9fa7b5;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  white-space: nowrap;
  transition: color 0.12s;
}
.fa-dash-config-limpiar:hover {
  color: #12309b;
}
.fa-dash-config-campo {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  font-size: 0.72rem;
  color: #9fa7b5;
}
.fa-dash-config-input {
  border: 1px solid #e7e9ed;
  border-radius: 8px;
  padding: 0.45rem 0.6rem;
  font-size: 0.82rem;
  color: #252930;
  font-family: inherit;
}
.fa-dash-config-input:focus {
  outline: none;
  border-color: #12309b;
}

/* Toggle de granularidad (Año / Mes). */
.fa-dash-toggle {
  display: grid;
  grid-template-columns: 1fr 1fr;
  border: 1px solid #e7e9ed;
  border-radius: 8px;
  overflow: hidden;
}
.fa-dash-toggle-btn {
  border: none;
  background: #fff;
  padding: 0.5rem 0.4rem;
  font-size: 0.8rem;
  font-weight: 600;
  color: #9fa7b5;
  cursor: pointer;
  font-family: inherit;
  transition: background 0.12s, color 0.12s;
}
.fa-dash-toggle-btn + .fa-dash-toggle-btn {
  border-left: 1px solid #e7e9ed;
}
.fa-dash-toggle-btn:hover {
  color: #252930;
}
.fa-dash-toggle-btn.is-activo {
  background: #12309b;
  color: #fff;
}

.fa-dash-config-reset {
  border: 1px solid #e7e9ed;
  border-radius: 8px;
  background: #fff;
  padding: 0.5rem 0.6rem;
  font-size: 0.78rem;
  font-weight: 600;
  color: #252930;
  cursor: pointer;
  font-family: inherit;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
}
.fa-dash-config-reset:hover {
  background: #f5f6fe;
}

/* Descarga PNG — botón primario, debajo de Restablecer. */
.fa-dash-config-descarga {
  border: 1px solid #12309b;
  border-radius: 8px;
  background: #12309b;
  padding: 0.5rem 0.6rem;
  font-size: 0.78rem;
  font-weight: 600;
  color: #fff;
  cursor: pointer;
  font-family: inherit;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
}
.fa-dash-config-descarga:hover {
  background: #0d2477;
  border-color: #0d2477;
}
.fa-dash-config-descarga:disabled {
  background: #c7cde4;
  border-color: #c7cde4;
  cursor: not-allowed;
}

/* ── Segundo tablero (comparativa) + checkboxes de años/meses ──────────── */
.fa-dash-comparativo {
  margin-top: 1.5rem;
}
.fa-dash-checks {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
/* Meses en rejilla de 3 columnas para que quepan compactos. */
.fa-dash-checks--meses {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.4rem 0.5rem;
}
.fa-dash-check {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.8rem;
  color: #252930;
  cursor: pointer;
}
.fa-dash-check input {
  accent-color: #12309b; /* casilla en azul Monex */
  cursor: pointer;
  margin: 0;
}
.fa-dash-check-swatch {
  width: 12px;
  height: 12px;
  border-radius: 3px;
  display: inline-block;
  flex: 0 0 auto;
}

/* ─────────────────────────────────────────────────────────────────
   Flash stack — alert flotante único en toda la app (base_portal.html).
   position:fixed al borde inferior del viewport, no desplaza contenido.
   Stack vertical: si hay varios flashes simultáneos, se apilan hacia arriba.
   Ancho controlado para mantener legibilidad; en mobile ocupa casi todo.

   Stacking JS: el script al final del template calcula y setea el `bottom`
   de cada flash en función de la altura del anterior, así cubrimos N
   simultáneos sin overlap. Acá dejamos reglas CSS-only de respaldo para
   los casos 2, 3, 4 flashes (cuando JS esté apagado), pero la fuente de
   verdad en runtime es el JS (ver base_portal.html).
   ───────────────────────────────────────────────────────────────── */
.fa-flash-stack {
  position: fixed;
  left: 50%;
  transform: translateX(-50%);
  bottom: 1.75rem;             /* ~28px: un poco más arriba del borde */
  z-index: 1080;            /* por encima del sidepanel del template */
  width: min(560px, calc(100vw - 2rem));
  margin: 0;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.08);
  border-radius: 10px;
  padding-right: 2.6rem;     /* espacio para la × (btn-close) sin chocar texto */
}
/* Fallback CSS-only (sin JS) para los casos más comunes. El JS reescribe
   `bottom` en runtime y maneja N >= 4 midiendo la altura real de cada
   flash. Estas reglas solo aplican si JS no corrió. */
.fa-flash-stack + .fa-flash-stack {
  bottom: calc(1.75rem + 4.5rem);  /* 2 flashes */
}
.fa-flash-stack + .fa-flash-stack + .fa-flash-stack {
  bottom: calc(1.75rem + 9rem);    /* 3 flashes */
}
.fa-flash-stack + .fa-flash-stack + .fa-flash-stack + .fa-flash-stack {
  bottom: calc(1.75rem + 13.5rem); /* 4 flashes */
}
/* Marca explícita para los flashes persistentes (alert-danger/error): sin
   auto-dismiss. Útil como hook si en el futuro queremos styling distinto. */
.fa-flash-persistent { /* noop, hook semántico */ }
/* Marca explícita para los flashes auto-dismiss (alert-success/warning). */
.fa-flash-auto { /* noop, hook semántico */ }

/* ══════════════════════════════════════════════════════════════════
   BITÁCORA DE COBRANZA — pestaña lateral + drawer
   Portado de producto-interno (.pi-bitacora-*), con la paleta de este
   repo: negro #1a1a1a en vez del azul de marca del origen.
   ══════════════════════════════════════════════════════════════════ */

/* La pestaña vive fija en el borde derecho y se arrastra en vertical.
   z-index por debajo del backdrop para que el panel abierto la tape. */
/* Banda de z-index PROPIA (1070-1090), arriba de los overlays de filtros y
   paneles (1040-1060): la bitácora puede quedar abierta junto con ellos y el
   apilado no debe depender del orden del DOM. */
.fa-bitacora-tab {
  position: fixed; right: 0; top: 150px; z-index: 1070;
  writing-mode: vertical-rl; text-orientation: mixed;
  background: #4472C4; color: #fff; border: 0; cursor: grab;
  padding: 1rem 0.42rem; border-radius: 8px 0 0 8px;
  font-size: 0.82rem; font-weight: 700; letter-spacing: 0.05em;
  display: flex; align-items: center; gap: 0.4rem;
  box-shadow: -2px 2px 10px rgba(15, 27, 50, 0.18);
  touch-action: none; user-select: none;
}
.fa-bitacora-tab:hover { background: #3a63ad; }
/* El contador va SIN píldora: en una pestaña vertical el fondo redondeado se
   leía como un círculo suelto de otro color alrededor del número. Es un dato
   más de la etiqueta, no una insignia aparte. */
.fa-bitacora-conteo {
  font-size: inherit; font-weight: 700; color: inherit;
  background: none; border-radius: 0; padding: 0;
}
/* Mientras se arrastra: sin cursor de "agarrar", con feedback de "agarrado" */
.fa-bitacora-tab--arrastrando { cursor: grabbing; box-shadow: -4px 4px 16px rgba(15, 27, 50, 0.28); }

.fa-bitacora-backdrop {
  position: fixed; inset: 0; background: rgba(15, 27, 50, 0.35); z-index: 1080;
  opacity: 0; visibility: hidden; transition: opacity 0.2s ease, visibility 0.2s ease;
}
.fa-bitacora-drawer {
  position: fixed; top: 0; right: 0; height: 100%; width: min(560px, 94vw);
  background: #fff; z-index: 1090; display: flex; flex-direction: column;
  box-shadow: -8px 0 24px rgba(15, 27, 50, 0.15);
  transform: translateX(100%); transition: transform 0.25s ease;
}
/* Estado abierto: se muestra el fondo y entra el panel */
.fa-bitacora-lateral.abierta .fa-bitacora-backdrop { opacity: 1; visibility: visible; }
.fa-bitacora-lateral.abierta .fa-bitacora-drawer { transform: translateX(0); }

.fa-bitacora-drawer-cab {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem;
  padding: 1.1rem 1.4rem; border-bottom: 1px solid #f0f1f4;
}
.fa-bitacora-titulo { margin: 0; font-size: 0.95rem; font-weight: 700; color: #4472C4; }
.fa-bitacora-subtitulo { margin: 0.25rem 0 0; font-size: 0.72rem; color: #9fa7b5; }
.fa-bitacora-cerrar {
  background: transparent; border: 0; cursor: pointer; line-height: 1;
  font-size: 1.4rem; color: #9fa7b5; padding: 0 0.3rem;
}
.fa-bitacora-cerrar:hover { color: #52606d; }
.fa-bitacora-drawer-cuerpo { overflow-y: auto; padding: 1.1rem 1.4rem; }

/* Un bloque por vendedor. La cabecera es un BOTÓN que pliega/despliega sus
   facturas: con decenas de vendedores, todo abierto es ilegible. Lleva el
   subtotal para que se pueda comparar entre vendedores sin abrir nada. */
.fa-bitacora-vendedor { margin-bottom: 0.5rem; }
.fa-bitacora-vendedor:last-child { margin-bottom: 0; }
.fa-bitacora-vendedor-cab {
  width: 100%; text-align: left; cursor: pointer;
  background: none; border: 0; border-radius: 0;
  display: grid; grid-template-columns: 0.9rem minmax(0, 1fr) auto auto;
  align-items: center; gap: 0.6rem; padding: 0.6rem 0.25rem;
}
.fa-bitacora-vendedor-cab:hover .fa-bitacora-vendedor-nombre { color: #4472C4; }
/* Al pasar por la cabecera el caret se intensifica → refuerza que es
   desplegable (mismo gesto que .fa-grupo-row:hover en la tabla). */
.fa-bitacora-vendedor-cab:hover .fa-bitacora-caret { opacity: 0.9; }
/* MISMO caret que la tabla de disposiciones (.fa-grupo-toggle::after): dos
   bordes rotados 45°, no un triángulo relleno. Se replica en vez de reusar esa
   regla porque aquélla es un ::after atado a .fa-grupo-toggle; extraer un
   selector común obligaría a tocar la tabla, que es el corazón del módulo.
   Si algún día se unifica, este es el par a mantener sincronizado.

   Sin FontAwesome, además, por lo que explica el fragmento: FA carga por JS y
   este markup se inyecta con innerHTML. */
.fa-bitacora-caret {
  justify-self: center;
  display: inline-block;
  width: 6px; height: 6px;
  margin-bottom: 2px;
  color: #5d6778;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg);
  transition: transform 0.18s ease, opacity 0.18s ease;
  opacity: 0.65;
}
.fa-bitacora-vendedor-cab[aria-expanded="true"] .fa-bitacora-caret {
  transform: rotate(-135deg);
  margin-bottom: 0; margin-top: 2px;
  opacity: 0.9;
}
.fa-bitacora-vendedor-nombre {
  font-size: 0.82rem; font-weight: 700; color: #252930;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.fa-bitacora-dias {
  flex: none; font-size: 0.7rem; font-weight: 700; color: #b42318;
  background: #fdecea; border-radius: 999px; padding: 0.1rem 0.55rem;
}
.fa-bitacora-facturas { padding: 0 0 0.5rem; }
.fa-bitacora-facturas[hidden] { display: none; }

.fa-bitacora {
  list-style: none; margin: 0; padding: 0; background: none;
}
/* 4 columnas: folio | comprador | vencimiento | monto */
.fa-bitacora-fila {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.3fr) minmax(0, 1fr) minmax(0, 1fr);
  gap: 0.75rem; padding: 0.4rem 0.25rem 0.4rem 1.4rem;
  font-size: 0.78rem; color: #52606d; align-items: baseline;
}
.fa-bitacora-folio { font-weight: 600; color: #252930; }
.fa-bitacora-comprador { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fa-bitacora-fecha { color: #9fa7b5; font-size: 0.74rem; }
.fa-bitacora-monto { text-align: right; font-variant-numeric: tabular-nums; }

.fa-bitacora-vendedor-pie {
  margin: 0.3rem 0 0; padding: 0 0 0 1.4rem; font-size: 0.74rem; color: #9fa7b5;
}
.fa-bitacora-totales {
  flex: none; font-size: 0.76rem; font-weight: 600; color: #252930;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
/* Estados del cuerpo cargado por demanda: "Cargando…", vacío y error. */
.fa-bitacora-vacio { margin: 0; font-size: 0.78rem; color: #9fa7b5; }

/* ══ Selectores del layout (fecha de disposición + moneda) ══
   Compartidos por la pestaña Layout de /dashboards y el panel "Enviar
   Layout" del encabezado de /disposiciones: los dos ofrecen los MISMOS dos
   filtros y deben verse igual. Sin chrome, solo border-bottom — la misma
   convención visual de los TomSelect del resto del portal. */
.fa-layout-filtros {
  display: flex; align-items: center; gap: 1.5rem; flex-wrap: wrap;
}
.fa-layout-filtro { display: flex; align-items: center; gap: 0.5rem; }
.fa-layout-filtro-label {
  font-size: 0.68rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.07em; color: #9fa7b5; white-space: nowrap;
}
.fa-layout-select {
  appearance: none; background: transparent; border: none;
  border-bottom: 1px solid #e7e9ed; border-radius: 0; color: #252930;
  font-size: 0.8rem; font-weight: 600; padding: 0.25rem 1.25rem 0.25rem 0.15rem;
  cursor: pointer;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6' fill='none'><path d='M1 1l4 4 4-4' stroke='%239fa7b5' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat; background-position: right 0.15rem center;
  background-size: 10px 6px;
}
.fa-layout-select:focus { outline: none; border-bottom-color: #012e92; }

/* El selector de FECHA del panel "Enviar Layout" pasa por TomSelect: el
   `<select>` nativo abre un popup del alto que decide el sistema operativo y
   el histórico son cientos de fechas. TomSelect copia las clases del select
   original al wrapper, así que acá se le saca el chrome que trae de Bootstrap
   para que siga viéndose como los demás selectores del layout. El alto del
   desplegable (8 renglones) lo fija layout_correo.js, que lo mide de una
   opción real. */
.ts-wrapper.fa-layout-select { border: none; padding: 0; width: 10rem; flex: none; }
.ts-wrapper.fa-layout-select .ts-control {
  border: none; border-bottom: 1px solid #e7e9ed; border-radius: 0;
  background: transparent; box-shadow: none; min-height: unset;
  padding: 0.25rem 1.6rem 0.25rem 0.15rem;
  font-size: 0.8rem; font-weight: 600; color: #252930; cursor: pointer;
}
.ts-wrapper.fa-layout-select.focus .ts-control { border-bottom-color: #012e92; }
.ts-wrapper.fa-layout-select .ts-dropdown { font-size: 0.8rem; font-weight: 600; }

/* ══ Estado de envío del layout (spec layout-envio-estado) ══
   Mensaje único en la fila de selectores del panel C-007 + punto rojo del
   botón del encabezado. Mismos tres colores que .fa-prog-circulo
   (verde/ámbar/gris) para que el vocabulario visual del estatus sea uno solo
   en toda la app.

   `margin-left: auto` lo empuja al extremo derecho de `.fa-layout-filtros`,
   que es flex: queda alineado con los dos selectores que determinan su valor.
   Ese contenedor lleva `flex-wrap`, así que en pantalla angosta baja de renglón
   en vez de comprimir los selectores. */
.fa-layout-estado-pill {
  display: inline-block;
  margin: 0 0 0 auto;
  padding: 0.3rem 0.7rem;
  border-radius: 6px;
  font-size: 0.76rem;
  font-weight: 600;
}
.fa-layout-estado-pill--sin_enviar {
  background: #f0f1f4;
  color: #9fa7b5;
}
.fa-layout-estado-pill--enviado {
  background: #e7f8ee;
  color: #1e8a4c;
}
.fa-layout-estado-pill--actualizado {
  background: #fef3e0;
  color: #b3730a;
}

/* Botón "Enviar Layout" del encabezado: el punto rojo se ancla arriba a la
   derecha, por eso el botón necesita `position: relative` (hereda estático
   de .fa-btn-accion). */
.fa-layout-btn-header {
  position: relative;
}
.fa-layout-punto-rojo {
  position: absolute;
  top: -3px;
  right: -3px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: #ef4444;
  border: 1.5px solid #fff;
}

/* ── Modal de selección de facturas a liquidar (paso 1, cobro DIRECTO) ── */

/* La tabla, el scroll con encabezado sticky y los botones se reusan tal cual
   (.fa-tabla, .fa-tabla-scroll, .fa-btn-icono): acá va solo el cromo propio del
   modal. El ancho del overlay y --fa-filas-visibles viven en el extra_styles de
   estatus_pago.html, junto a los de los otros paneles de esa página. */

.fa-sel-toolbar {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-bottom: 0.75rem;
}

.fa-sel-toolbar-acciones {
  margin-left: auto;
  display: flex;
  gap: 0.5rem;
}

.fa-sel-contador {
  font-size: 0.75rem;
  color: #9fa7b5;
  /* Cifras de ancho fijo: el contador cambia con cada clic y sin esto la
     toolbar se mueve sola. */
  font-variant-numeric: tabular-nums;
}

/* Avance del pago: reusa .fa-cupo-widget entero (cifras, barra, --critico) y
   solo lo separa del resto del modal. La barra va más gruesa que la del cupo
   de /disposiciones porque acá es el dato principal del panel, no un adorno
   al costado de un formulario. */
.fa-sel-cupo {
  padding: 0.6rem 0 0.75rem;
  border-bottom: 1px solid #f0f1f4;
  margin-bottom: 0.75rem;
}

.fa-sel-cupo .fa-cupo-barra {
  height: 9px;
}

/* Fila superior. Mismo gap que .fa-cupo-barra-wrap y misma partición —zona
   flexible + elemento de ancho fijo—, que es lo que hace que el remanente
   quede alineado con el fin de la BARRA y no con el del widget (a la derecha
   de la barra vive el porcentaje). */
.fa-sel-cupo-fila {
  display: flex;
  align-items: baseline;
  gap: 0.55rem;
}

.fa-sel-cupo-texto {
  flex: 1;
  display: flex;
  align-items: baseline;
  gap: 0.35rem;
  /* Con muchos dígitos, antes de romper el renglón se recorta el bloque
     izquierdo: el remanente es el dato que no puede perderse de vista. */
  min-width: 0;
}

/* `auto` y no un ancho: empuja el remanente al extremo derecho de la zona
   flexible, que termina exactamente donde termina la barra. */
.fa-sel-cupo-remanente {
  margin-left: auto;
  display: flex;
  align-items: baseline;
  gap: 0.35rem;
  white-space: nowrap;
}

/* «Monto utilizado» / «Remanente». En gris de label, como el resto de los
   rótulos secundarios. */
.fa-sel-cupo-etiqueta {
  font-size: 0.72rem;
  color: #9fa7b5;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  margin-right: 0.15rem;
}

.fa-sel-filtros {
  display: grid;
  /* Tres columnas, una por cada campo filtrable, alineadas con las tres
     primeras de la tabla. */
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.75rem;
  margin-bottom: 0.5rem;
}

/* Columna del checkbox: angosta y centrada, igual que .fa-sat-col-check. */
.fa-tabla-seleccion .fa-sel-col-check {
  width: 6rem;
  text-align: center;
}

.fa-sel-th-texto {
  display: block;
  font-size: 0.62rem;
}

/* ── Login / signup / reset-password: desenfoque tras la tarjeta de texto ── */
/* portal.css ya pinta ".overlay-content" como la tarjeta flotante (fondo
   rgba(37,41,48,.6), esquinas redondeadas, padding de Bootstrap en el HTML)
   sobre la foto de fondo. Lo único que le falta, y que agrega esta regla, es
   el desenfoque del fondo detrás de la tarjeta (mismo tratamiento que usa la
   app hermana Omega) para separarla visualmente de la imagen. */
.auth-background-overlay .overlay-content {
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}

/* ============================================================
   Tabla del tablero Layout (/dashboards/layout)
   Que las 15 columnas quepan en una sola vista.
   ============================================================ */

/* La tabla deja de estirarse al 100 %: con ancho automático cada columna mide
   lo que pide su DATO más ancho (los <td> no envuelven) y el espacio sobrante
   queda afuera en vez de repartirse entre columnas que no lo necesitan. Si el
   total aun así no entra, el scroll horizontal del wrapper queda como red de
   seguridad. */
#fa-tabla-layout {
  width: auto;
}

/* El encabezado SÍ puede partirse en dos líneas: cuando el dato es más angosto
   que el título ("Spread Interés", "No. WB Dispersión", "Días Layout"...), la
   columna la marca el dato y el título cae a dos renglones. Override del
   white-space:nowrap global de los th. */
#fa-tabla-layout thead th {
  white-space: normal;
}

/* Excepción: Vendedor/Comprador/Cofactor llevan ancho FIJO — una razón social
   larga no tiene derecho a comerse el viewport. El recorte con ellipsis va en
   un <div> interior y no en el <td>: en table-layout:auto el min-content de un
   texto nowrap le gana al max-width de la celda, pero el bloque con
   overflow:hidden sí acota lo que la columna pide. El nombre completo queda en
   el title. El div lo arma el renderFn de las columnas de nombre de
   i_dashboards/layout.html. */
#fa-tabla-layout td .fa-col-nombre {
  max-width: 100px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ============================================================
   Tabla del tablero Vencidas (/dashboards/vencidas)
   ============================================================ */

/* Razones sociales y comentarios son texto libre —comentarios es NVARCHAR(MAX)—
   y sin tope una sola fila empuja las nueve columnas fuera de la vista. Se
   recortan con ellipsis; el valor completo queda en el title de la celda
   (tooltipSiNoVacio en la config de tabla_datos). */
#fa-tabla-vencidas td {
  max-width: 260px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Vendedor y comprador (columnas 2 y 3) con un tope menor: son las más
   largas y le quitaban espacio a las demás. */
#fa-tabla-vencidas td:nth-child(2),
#fa-tabla-vencidas td:nth-child(3) {
  max-width: 190px;
}

/* El estado vacío ocupa una celda con colspan: recortarla escondería el
   mensaje. */
#fa-tabla-vencidas td.fa-tabla-vacia {
  max-width: none;
  white-space: normal;
}

/* Días en mora: rojo solo cuando el atraso es real (> 0). Mismo rojo
   de error que ya usa el portal (#d9534f). El span lo arma renderDiasVencidos
   en vencidas.html — así el cero y los negativos quedan neutros y el rojo
   significa una sola cosa: esta factura ya se pasó del plazo. */
#fa-tabla-vencidas .fa-dias-vencidos {
  color: #d9534f;
  font-weight: 700;
}

/* ============================================================
   Hub de tableros (/dashboards)
   Rejilla de tarjetas que reemplazó a la barra de pestañas.
   ============================================================ */

.fa-hub-intro {
  font-size: 0.85rem;
  color: #252930;
  margin: 0 0 1.3rem;
  max-width: 78ch;
}

/* Con auto-fill no hay que decidir cuántas columnas: caen dos o tres según el
   ancho disponible, y una sola en pantalla angosta. */
.fa-hub-rejilla {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fill, minmax(290px, 1fr));
}

/* La tarjeta ENTERA es el enlace: un "Abrir" chico obligaría a apuntarle a un
   blanco de 40px teniendo una tarjeta de 300 al lado. */
.fa-hub-card {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  background: #fff;
  border: 1px solid #e7e9ed;
  border-radius: 14px;
  padding: 1.1rem 1.2rem;
  text-decoration: none;
  color: inherit;
  transition:
    border-color 0.15s,
    box-shadow 0.15s;
}

a.fa-hub-card:hover {
  border-color: #4472c4;
  box-shadow: 0 2px 10px rgba(68, 114, 196, 0.16);
}

.fa-hub-icono {
  width: 34px;
  height: 34px;
  border-radius: 9px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #eef2fb;
  color: #4472c4;
  font-size: 0.95rem;
}

.fa-hub-titulo {
  font-size: 0.95rem;
  font-weight: 700;
  color: #252930;
  margin: 0;
}

.fa-hub-contesta {
  font-size: 0.82rem;
  color: #52606d;
  margin: 0;
}

.fa-hub-abrir {
  font-size: 0.76rem;
  font-weight: 700;
  color: #4472c4;
  margin: 0.2rem 0 0;
}

/* Los tableros sin alcance se ven DISTINTOS a propósito: nadie tiene que
   confundir lo que se puede abrir con lo que todavía no existe. */
.fa-hub-card--pendiente {
  background: #f8f9fe;
  border: 1px dashed #b8c4e8;
}

.fa-hub-card--pendiente .fa-hub-icono {
  background: #e6ebfa;
  color: #26356b;
}

.fa-hub-etiqueta {
  align-self: flex-start;
  font-size: 0.62rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #26356b;
  background: #e6ebfa;
  border-radius: 999px;
  padding: 0.15rem 0.5rem;
}

/* Rejilla de /pagos/cuentas: el ícono a la izquierda y, en la esquina
   superior derecha, los totales de «Pagos abiertos» con la forma de
   .fa-hub-etiqueta (USD en lavanda, MXN en aqua). */
.fa-cuenta-encabezado {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.75rem;
}

.fa-cuenta-totales {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 0.35rem;
}

.fa-cuenta-total {
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  border-radius: 999px;
  padding: 0.15rem 0.5rem;
  border: 1px solid transparent;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* El tipo de cuenta, como texto sin pastilla: que no compita con las de
   totales. Clase propia y no modificador de .fa-hub-etiqueta, que es global. */
.fa-cuenta-tipo {
  align-self: flex-start;
  font-size: 0.62rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #9fa7b5;
}

.fa-cuenta-total--usd {
  color: #26356b;
  background: #e5e9f5;
}

.fa-cuenta-total--mxn {
  color: #0b5c63;
  background: #eefbfc;
}

/* Total en 0: la pastilla se queda en blanco; el color es solo para montos
   distintos de cero. */
.fa-cuenta-total--cero {
  color: #9fa7b5;
  background: #fff;
  border: 1px solid #e7e9ed;
}

/* Retorno al hub desde una sub-página: reemplaza a la barra de pestañas. */
.fa-hub-volver {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: #9fa7b5;
  text-decoration: none;
  margin-bottom: 0.2rem;
  transition: color 0.15s;
  /* Dentro de un contenedor flex en columna no se estira: el área de clic
     es solo el texto. */
  align-self: flex-start;
}

/* En el detalle de estatus va pegado a su encabezado, no al `gap` del
   contenedor. */
.fa-estatus-wrapper > .fa-hub-volver {
  margin-bottom: -0.6rem;
}

.fa-hub-volver:hover {
  color: #4472c4;
}

/* Modo PARCIAL del modal de selección: las columnas «%» y «Pago» reemplazan a
   la casilla «Liquidar». El pago captura una fracción del saldo de cada
   factura, así que en vez de marcar se escribe un número. */
.fa-tabla-seleccion .fa-sel-col-pct {
  width: 6rem;
}

.fa-tabla-seleccion .fa-sel-col-monto {
  width: 9rem;
}

.fa-tabla-seleccion .fa-sel-pct,
.fa-tabla-seleccion .fa-sel-monto {
  width: 100%;
  border: none;
  border-bottom: 1px solid #e7e9ed;
  background: transparent;
  padding: 0.15rem 0.2rem;
  font-size: 0.8rem;
  /* A la derecha como el resto de las celdas de monto (.fa-td-num), para que
     los decimales queden alineados entre filas. */
  text-align: right;
  color: #252930;
}

.fa-tabla-seleccion .fa-sel-pct:focus,
.fa-tabla-seleccion .fa-sel-monto:focus {
  outline: none;
  border-bottom-color: #4472c4;
}

/* Fila fuera de rango: 0 o el saldo entero (el 100 % que este alcance no
   admite). Mientras haya una, «Aceptar» queda deshabilitado. */
.fa-tabla-seleccion .fa-sel-fila--error .fa-sel-pct,
.fa-tabla-seleccion .fa-sel-fila--error .fa-sel-monto {
  border-bottom-color: #d9534f;
  color: #d9534f;
}

/* Fila que el .xlsx del vendedor traía marcada. En el modo parcial el archivo
   solo dice CUÁLES liquidar —el monto lo captura el usuario—, así que se
   resalta en vez de rellenarse. */
.fa-tabla-seleccion .fa-sel-fila--sugerida {
  background: #f5f6fe;
}

/* Factura que no se puede ligar: sin folio de crédito no hay tasa en la
   cartera, y sin tasa no hay intereses calculables. La casilla va `disabled`
   y la fila atenuada; el motivo viaja en el `title` de la fila. */
.fa-tabla-seleccion .fa-sel-fila--bloqueada {
  opacity: 0.55;
}

.fa-tabla-seleccion .fa-sel-fila--bloqueada .fa-sel-check {
  cursor: not-allowed;
}

/* ── /tareas: celda de catálogo cuya clave no tiene ícono ── */
/* Las 4 columnas de catálogo de `/tareas` (Estatus, Codix, Disp IMX, Doc
   Original) se pintan como un botón con un solo ícono. Una clave cuyo
   catálogo NO define `icon` —`sin_estatus`, en Estatus y en Codix/Disp IMX—
   debe LEERSE como celda vacía, pero necesita algo que clickear para poder
   abrir el menú: el círculo se dibuja igual y se esconde acá.
   La regla es "el catálogo no define ícono", no una lista de claves: así
   vale para las tres columnas que tienen una clave sin ícono, y `doc_original`
   —cuyos dos estados sí lo tienen— nunca entra. */
.fa-tareas-estatus-boton .fa-tareas-icono-vacio {
  opacity: 0;
  transition: opacity 0.15s ease;
}

.fa-tareas-estatus-boton:hover .fa-tareas-icono-vacio,
.fa-tareas-estatus-boton:focus-visible .fa-tareas-icono-vacio {
  opacity: 1;
}

/* Sin ícono visible no hay blanco al que apuntar: el botón ocupa la celda
   entera para que el click caiga en cualquier parte de la columna. */
.fa-tareas-estatus-boton {
  width: 100%;
}

/* Tablas anchas (30-50 columnas, las de insumos de /base-operaciones y /admin):
   layout automático + scroll horizontal. Cada celda en una sola línea; los
   valores largos se truncan con ellipsis para que ninguna columna se dispare.
   La celda .fa-tabla-vacia (colspan) nunca se oculta con su columna. */
.fa-tabla--ancha td {
  white-space: nowrap;
  max-width: 320px;
  overflow: hidden;
  text-overflow: ellipsis;
}
.fa-tabla--ancha td.fa-tabla-vacia { display: table-cell !important; }

/* ── Selector de columnas ("Columnas", tabla_columnas.js) ─────────
   Compartido por /base-operaciones y /reportes. La visibilidad la aplica el
   <style> nth-child que inyecta el JS; cada tabla protege además su celda
   .fa-tabla-vacia (colspan), que no debe ocultarse con su columna. */
.fa-cols {
  position: relative;
}
.fa-cols-trigger {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  height: 34px;
  padding: 0 0.85rem;
  border: 1px solid #e7e9ed;
  border-radius: 8px;
  background: #fff;
  color: #252930;
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
}
.fa-cols-trigger:hover { border-color: #cfd3db; }
.fa-cols-trigger i { color: #9fa7b5; }
/* position: fixed + posicionado por JS (posicionar()) para escapar del
   .fa-tabla-card que ahora lo contiene (overflow:hidden lo recortaría).
   Mismo patrón que los dropdowns de filtro, que cuelgan del <body>. */
.fa-cols-menu {
  position: fixed;
  z-index: 1060;
  width: 260px;
  max-height: 60vh;
  overflow-y: auto;
  background: #fff;
  border: 1px solid #e7e9ed;
  border-radius: 10px;
  box-shadow: 0 8px 28px rgba(26, 26, 26, 0.12);
  padding: 0.5rem;
}
.fa-cols-menu[hidden] { display: none; }
.fa-cols-menu-cabecera {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.25rem 0.5rem 0.5rem;
  border-bottom: 1px solid #f0f1f4;
  margin-bottom: 0.35rem;
}
.fa-cols-menu-titulo {
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #9fa7b5;
}
.fa-cols-reset {
  border: none;
  background: none;
  color: #4472c4;
  font-size: 0.72rem;
  font-weight: 600;
  cursor: pointer;
  padding: 0;
}
.fa-cols-reset:hover { text-decoration: underline; }
.fa-cols-item {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.32rem 0.5rem;
  border-radius: 6px;
  font-size: 0.8rem;
  color: #252930;
  cursor: pointer;
}
.fa-cols-item:hover { background: #f5f6fe; }
.fa-cols-item input { cursor: pointer; margin: 0; }
.fa-cols-item--base { color: #9fa7b5; }

/* ── Tarjeta de proceso (/reportes, pestaña "Generar reporte") ─────────
   Un proceso que se ejecuta por fecha: datos de solo lectura arriba, la
   fecha de la nueva ejecución y las acciones abajo. La franja verde de la
   izquierda va en el azul primario de la app. */
.fa-proceso-card {
  margin: 0 1.5rem 1.5rem;
  padding: 1.5rem 1.75rem 1.25rem;
  background: #fff;
  border-left: 5px solid #4472c4;
  border-radius: 10px;
  box-shadow: 0 2px 10px rgba(26, 26, 26, 0.06);
}

.fa-proceso-cabecera {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1.25rem;
}

.fa-proceso-titulo {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 700;
  text-transform: uppercase;
  color: #252930;
}

.fa-proceso-iconos {
  display: flex;
  gap: 0.35rem;
}

.fa-proceso-icono {
  padding: 0.2rem 0.4rem;
  border: 0;
  background: none;
  color: #6b7280;
  font-size: 0.9rem;
  cursor: default;
}

a.fa-proceso-icono {
  cursor: pointer;
  text-decoration: none;
}

a.fa-proceso-icono:hover {
  color: #1a1a1a;
}

.fa-proceso-fila {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 1.5rem;
}

.fa-proceso-campo {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  margin-bottom: 1rem;
  min-width: 0;
}

.fa-proceso-label {
  margin: 0;
  font-size: 0.85rem;
  color: #252930;
}

.fa-proceso-valor {
  padding: 0.55rem 0.8rem;
  background: #e9ecef;
  border: 1px solid transparent;
  border-radius: 6px;
  font-size: 0.85rem;
  color: #6b7280;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.fa-proceso-valor--borde {
  border-color: #c8cdd6;
}

.fa-proceso-fecha {
  width: 18rem;
  max-width: 100%;
  padding: 0.45rem 0.6rem;
  border: 1px solid #c8cdd6;
  border-radius: 6px;
  font-size: 0.85rem;
  color: #252930;
}

.fa-proceso-acciones {
  display: flex;
  justify-content: center;
  gap: 0.5rem;
  margin-top: 0.5rem;
}

@media (max-width: 768px) {
  .fa-proceso-fila {
    grid-template-columns: 1fr;
  }
}

/* ── Cofactor · EDI Factoring ──
   «Fecha reporte» a la izquierda; a la derecha, «Sincronizar» con su periodo. */
/* Mismo patrón que #tabla-disposiciones: los montos llevan ancho fijo y
   Cofactor, Vendedor y Comprador se reparten el resto, truncando con «…»
   (el nombre completo va en el tooltip). Por debajo del piso, scroll. */
#tabla-edi-factoring {
  table-layout: fixed;
  min-width: 790px;
}
#tabla-edi-factoring thead th[data-sort="moneda"] {
  width: 90px;
}
#tabla-edi-factoring thead th[data-sort="monto"],
#tabla-edi-factoring thead th[data-sort="monto_edi"],
#tabla-edi-factoring thead th[data-sort="diferencia"] {
  width: 140px;
}
#tabla-edi-factoring tbody td:nth-child(-n + 3) {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.fa-edi-diferencia {
  display: inline-block;
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  background: #fde8e8;
  color: #c0392b;
  font-weight: 600;
}

.fa-edi-barra {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 1rem;
  margin-top: 1rem;
  margin-bottom: 1rem;
}

.fa-edi-barra-derecha {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 1rem;
  margin-left: auto;
}

/* Sin esto `.fa-btn-secundario` pega el ícono al texto. */
.fa-edi-barra .fa-edi-btn-catalogo {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
}

.fa-edi-campo {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  margin: 0;
  font-size: 0.75rem;
  color: #9fa7b5;
}

.fa-edi-campo .fa-proceso-fecha {
  width: 11rem;
}

/* Panel «Catálogo de nombres» (t031 y t034): búsqueda y la lista con scroll propio
   para que el panel no crezca con el catálogo. */
.fa-edi-catalogo {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.fa-edi-catalogo-error {
  margin: 0;
  font-size: 0.78rem;
  color: #c0392b;
}

.fa-edi-catalogo-tabla {
  max-height: 55vh;
  overflow-y: auto;
}

.fa-edi-catalogo-tabla .fa-edi-mismo-nombre {
  color: #9fa7b5;
  font-style: italic;
}

.fa-edi-catalogo-tabla td .form-control {
  min-width: 12rem;
}

/* Acciones de la fila: botones cuadrados de 30px, centrados con el campo y
   con aire entre sí (los de edición son ✓ primario y ✕ neutro). */
.fa-edi-catalogo-tabla td.fa-edi-acciones {
  vertical-align: middle;
  white-space: nowrap;
}

.fa-edi-catalogo-tabla td.fa-edi-acciones .fa-edifactoring-btn-icono {
  width: 30px;
  height: 30px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  vertical-align: middle;
}

.fa-edi-catalogo-tabla td.fa-edi-acciones .fa-edifactoring-btn-icono + .fa-edifactoring-btn-icono {
  margin-left: 0.45rem;
}

.fa-edi-catalogo-tabla tr:has(input) td {
  vertical-align: middle;
}

.fa-edi-catalogo-tabla td:has(input) {
  padding-right: 0.5rem;
}

/* Los botones Comprador · Vendedor · Cofactor del panel: sin esto la columna flex los
   estira a todo el ancho. */
.fa-edi-catalogo .fa-edi-catalogo-modo {
  align-self: flex-start;
  grid-template-columns: repeat(3, 1fr);
}

/* Segmentado sin bordes ni acento: el activo se distingue solo por fondo y peso. */
.fa-edi-catalogo .fa-edi-catalogo-modo {
  border: none;
  background: #f0f1f4;
  padding: 0.2rem;
  gap: 0.2rem;
}

.fa-edi-catalogo .fa-dash-toggle-btn {
  padding: 0.4rem 0.9rem;
  font-size: 0.78rem;
  white-space: nowrap;
  border: none;
  border-radius: 6px;
  background: transparent;
}

.fa-edi-catalogo .fa-dash-toggle-btn + .fa-dash-toggle-btn {
  border-left: none;
}

.fa-edi-catalogo .fa-dash-toggle-btn.is-activo {
  background: #ffffff;
  color: #252930;
  font-weight: 700;
}

.fa-edi-catalogo-barra {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.75rem;
}

.fa-edi-catalogo-barra .fa-tabla-busqueda-grupo {
  flex: 1 1 14rem;
  width: auto;
  min-width: 12rem;
}

/* Sugerencias mientras se escribe en un campo libre (sugerencias_campo.js).
   El desplegable cuelga del grupo del campo; `top` lo calcula el JS. */
.fa-form-grupo--sugerencias {
  position: relative;
}

.fa-sugerencias {
  position: absolute;
  left: 0;
  right: 0;
  z-index: 30;
  max-height: 17rem;
  overflow-y: auto;
  padding: 0.3rem;
  background: #ffffff;
  border: 1px solid #e7e9ed;
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(37, 41, 48, 0.12);
}

.fa-sugerencias-opcion {
  padding: 0.45rem 0.65rem;
  border-radius: 7px;
  font-size: 0.85rem;
  color: #252930;
  cursor: pointer;
  line-height: 1.3;
}

.fa-sugerencias-opcion.is-activa {
  background: var(--color-acento-fila-suave);
  color: var(--color-acento-fila);
}

.fa-sugerencias-opcion mark {
  padding: 0;
  background: none;
  color: var(--color-acento-fila);
  font-weight: 700;
}

.fa-sugerencias-pie {
  margin-top: 0.2rem;
  padding: 0.4rem 0.65rem 0.25rem;
  border-top: 1px solid #f0f1f4;
  font-size: 0.74rem;
  color: #9fa7b5;
}

/* Sin coincidencias, el pie es lo único: sin la raya de arriba. */
.fa-sugerencias-pie:first-child {
  border-top: none;
  margin-top: 0;
}

/* ───────────── Paneles MSG09 / MSG12 de Edifactoring ───────────── */

.fa-edifactoring-barra {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 0.75rem;
}

.fa-edifactoring-barra .fa-tabla-busqueda-grupo {
  flex: 1 1 auto;
  width: auto;
  max-width: 26rem;
}

.fa-edifactoring-filtro {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 0.6rem;
  white-space: nowrap;
}

.fa-edifactoring-filtro .fa-campo-input {
  width: auto;
}

.fa-edifactoring-etiqueta {
  margin: 0;
  font-size: 0.8rem;
  color: #9fa7b5;
}

.fa-edifactoring-error {
  margin-bottom: 0.5rem;
  font-size: 0.8rem;
  color: #c0392b;
}

.fa-edifactoring-tabla {
  max-height: 60vh;
  overflow: auto;
}

/* Acordeón de compradores: mismas clases que el de /disposiciones
   (.fa-grupo-row, .fa-grupo-toggle, .fa-subrow), sin su guía vertical. */
.fa-edifactoring-tabla tbody tr.fa-subrow--visible td {
  border-bottom: 0;
}

/* Sin la guía azul izquierda que el acordeón de /disposiciones pone en el grupo abierto. */
.fa-edifactoring-tabla .fa-grupo-row:has(.fa-grupo-toggle[aria-expanded="true"]) td:first-child {
  box-shadow: none;
}

/* Columnas fijas: la flecha, y los tres nombres se reparten el ancho que sobra y
   se cortan con puntos suspensivos en vez de partirse en renglones. */
.fa-edifactoring-lista {
  table-layout: fixed;
}

.fa-edifactoring-lista th:nth-child(1) { width: 44px; }
.fa-edifactoring-lista th:nth-child(5) { width: 80px; }
.fa-edifactoring-lista th:nth-child(6) { width: 110px; }
.fa-edifactoring-lista th:nth-child(7) { width: 130px; }
.fa-edifactoring-lista th:nth-child(8) { width: 84px; }

.fa-edifactoring-lista td,
.fa-edifactoring-lista th {
  text-align: left;
}

.fa-edifactoring-lista td.text-end,
.fa-edifactoring-lista th.text-end {
  text-align: right;
}

.fa-edifactoring-lista td.fa-edifactoring-corta {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Comprador con nombre EDI (el BuyerNr del XML): texto azul, sin fondo. */
.fa-edifactoring-comprador-edi {
  color: #4472c4;
}

.fa-edifactoring-comprador {
  color: #5d6778;
}

.fa-edifactoring-archivo {
  margin-bottom: 0.5rem;
  font-size: 0.8rem;
  color: #9fa7b5;
}

.fa-edifactoring-xml {
  max-height: 65vh;
  margin: 0;
  padding: 0.75rem;
  overflow: auto;
  border: 1px solid #e7e9ed;
  border-radius: 6px;
  background: #f5f6fe;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.75rem;
  line-height: 1.55;
  color: #252930;
  white-space: pre;
  user-select: text;
}

.fa-edifactoring-btn-icono {
  padding: 0.3rem 0.5rem;
  border: none;
  border-radius: 6px;
  background: none;
  color: #9fa7b5;
  cursor: pointer;
}

.fa-edifactoring-btn-icono:hover,
.fa-edifactoring-btn-icono:focus-visible {
  background: #f0f1f4;
  color: #252930;
}

.fa-edifactoring-btn-icono--primario,
.fa-edifactoring-btn-icono--primario:hover,
.fa-edifactoring-btn-icono--primario:focus-visible {
  background: #4472c4;
  color: #ffffff;
}

.fa-edifactoring-btn-icono--primario:hover {
  background: #3a63ab;
}

.fa-xml-signo {
  color: #9fa7b5;
}

.fa-xml-etiqueta {
  color: #4472c4;
}

.fa-xml-atributo {
  color: #6b7686;
}

.fa-xml-valor {
  color: #3d7a6a;
}

#overlay-edifactoring-msg09 .fa-panel,
#overlay-edifactoring-msg12 .fa-panel,
#overlay-edifactoring-msg09-visor .fa-panel,
#overlay-edifactoring-msg12-visor .fa-panel {
  max-width: 1100px;
}

.fa-edi-catalogo-ayuda {
  margin-bottom: 0.5rem;
  font-size: 0.78rem;
  color: #9fa7b5;
}

/* ── Marca: nombre + subtítulo ────────────────────────────────
   portal.css fija .app-branding en 60px de alto y no alcanza para
   dos líneas. Se apilan pegaditos, con el subtítulo pequeño y gris. */
.app-branding {
  height: auto;
}
.fa-marca {
  display: flex;
  flex-direction: column;
  text-align: left;
  line-height: 1.15;
}
.fa-marca .logo-text {
  vertical-align: baseline; /* el valign de portal.css sobra dentro del flex */
}
.fa-marca-sub {
  font-size: 0.72rem;
  font-weight: 500;
  color: #9fa7b5;
  letter-spacing: 0.01em;
}
.app-404-page .app-branding .app-logo {
  display: inline-flex; /* centra la marca de dos líneas junto al logo */
  align-items: center;
}
