/* ============================================================
   styles-extra.css
   Estilos adicionales para las nuevas secciones:
   - Toggle de moneda (topbar)
   - Toggle de sociedad (topbar)
   - Aging bars (Facturas de Venta)
   - Bloques de Indicadores Globales
   - Banner de alerta del Cashflow
   - Ajustes responsive
   ============================================================ */

/* ── TOGGLES (FX + SOCIEDAD) ─────────────────── */


/* ── AGING BARS ──────────────────────────────── */


/* ── TABLA ESPACIOSA (Detalle de Facturas) ───── */
/* Sobrescribe el padding default de td/th sólo en tablas marcadas con esta clase.
   Las tablas existentes (sin la clase) mantienen su padding original. */
.tbl-spacious table td {
  padding: 14px 14px;
  font-size: 13px;
  line-height: 1.4;
}
.tbl-spacious table th {
  padding: 12px 14px;
  font-size: 11px;
}
.tbl-spacious table td:first-child { padding-left: 20px; }
.tbl-spacious table td:last-child  { padding-right: 20px; }
.tbl-spacious table tbody tr {
  border-bottom: 1px solid var(--border);
}

/* ── SKELETON LOADING PULSE ──────────────────── */
.skeleton-pulse {
  display: inline-block;
  animation: skeleton-pulse 1.4s ease-in-out infinite;
  opacity: 0.6;
}
@keyframes skeleton-pulse {
  0%, 100% { opacity: 0.4; }
  50%      { opacity: 0.85; }
}

/* ── BLOQUES DE TÍTULO EN INDICADORES ────────── */
.kpi-block-title {
  font-size: 13px;
  font-weight: 700;
  color: var(--text-2);
  text-transform: uppercase;
  letter-spacing: 1px;
  margin-top: 20px;
  margin-bottom: -8px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border);
}
.kpi-block-title:first-child { margin-top: 0; }

/* ── BANNER DE ALERTA ────────────────────────── */
.alert-banner {
  background: var(--red-bg);
  border: 1px solid rgba(239, 68, 68, 0.3);
  border-left: 4px solid var(--red);
  padding: 14px 18px;
  border-radius: 8px;
  font-size: 13px;
  color: var(--text);
  display: flex;
  align-items: center;
  gap: 8px;
}
.alert-banner strong { color: var(--red-txt, var(--red)); margin-right: 4px; }

/* ── INPUTS Y SELECTS ────────────────────────── */
input[type="text"]:focus,
select:focus {
  outline: none;
  border-color: var(--blue);
}

/* ── TABLA DEL CASHFLOW (sticky first column) ── */
.tbl-wrap table th:first-child,
.tbl-wrap table td:first-child {
  position: sticky;
  left: 0;
  z-index: 1;
}
.tbl-wrap thead tr th:first-child {
  z-index: 4;
}

/* ── HOVER TARJETAS KPI ──────────────────────── */
.kpi-card {
  transition: transform .15s ease, border-color .15s ease;
}
.kpi-card:hover {
  border-color: var(--border-2);
  transform: translateY(-1px);
}
/* Movimiento reducido: el realce se aplica sin recorrido (misma idea que la regla global de
   esta hoja: se acorta la duración, no se quita el cambio). */
@media (prefers-reduced-motion: reduce) {
  .kpi-card { transition-duration: .01ms; }
}

/* ── CHIPS NEW BADGE ─────────────────────────── */
.chip-open[style*="font-size:9px"] {
  background: linear-gradient(135deg, var(--cyan), var(--blue));
  color: white;
  font-weight: 600;
  letter-spacing: 0.5px;
}

/* ── FIX FLEX SHRINK del .main ────────────────── */
/* Sin esto, las cards se comprimen para caber en la altura del viewport
   en vez de overflowear y permitir scroll. Esto fuerza a que cada card
   mantenga su altura natural y el .main scrollee cuando excede. */
.main > * {
  flex-shrink: 0;
}

/* ── RESPONSIVE ──────────────────────────────── */
/* NOTA: el stacking vertical del aging fue removido porque rompía
   la legibilidad cuando el sidebar (220px) reducía el viewport efectivo
   debajo de 900px. Las columnas compactas 80+1fr+100+60 caben perfecto
   incluso en viewport de 600px. */

/* ── Historial de Pagos ── */
/* La barra ocupa el ancho: fechas y usuario con el ancho que necesitan, y el
   buscador se queda con TODO el resto. Antes los cuatro controles median lo mismo y
   se apiñaban a la izquierda dejando media pantalla vacía. */
.hist-filtros {
  display: grid;
  grid-template-columns: auto auto auto 1fr;
  gap: 10px 14px; align-items: end; margin: 12px 0 14px;
}
/* Rótulo ARRIBA del control, no al lado: en línea, cuatro pares rótulo+campo dan
   ocho elementos que compiten; apilados, la fila se lee como cuatro. */
.hist-f-campo { display: flex; flex-direction: column; gap: 4px; }
.hist-f-campo > span {
  font-size: 10px; font-weight: 600; letter-spacing: .6px; text-transform: uppercase;
  color: var(--text-3);
}
.hist-f-buscar { display: flex; }
.hist-f-buscar input { width: 100%; }
/* El aviso de rango invertido toma toda la fila: es un error de lo que se pidió, no
   una decoración al lado de un campo. */
.hist-f-aviso {
  grid-column: 1 / -1; font-size: 12px; color: var(--amber, #f59e0b);
  background: rgba(245,158,11,.08); border: 1px solid rgba(245,158,11,.3);
  border-radius: 8px; padding: 7px 10px;
}
.hist-f-aviso[hidden] { display: none; }

@media (max-width: 820px) {
  .hist-filtros { grid-template-columns: 1fr 1fr; }
  .hist-f-buscar { grid-column: 1 / -1; }
}
.hist-tbl .num { text-align:right; font-family:var(--mono); }
.hist-tanda { cursor:pointer; }
/* --bg-hover y --bg-2 NO existen en el :root de styles.css (las variables de la
   app son --navy-*). Van con fallback para que el hover y el detalle se pinten
   igual: una custom property sin definir invalida la declaración completa. */
.hist-tanda:hover { background:var(--navy-4, rgba(255,255,255,0.03)); }
.hist-chevron { color:var(--text-2); }
.hist-sap.ok    { color:var(--green); }
.hist-sap.fallo { color:var(--red-txt, var(--red)); font-weight:600; }
.hist-sap.pend  { color:var(--text-2); }
.hist-diverg { color:var(--amber); font-weight:600; }
/* El sello de una tanda reemplazada por un reenvío autorizado.
   ⚠ Acento en la LETRA y en la LÍNEA, fondo en la superficie neutra. Un tinte del
   propio ámbar debajo de su ámbar mueve los dos colores juntos, así que el contraste
   entre ellos no crece por más que se baje el tinte: es el patrón que más veces quedó
   corto en este proyecto. Contra --navy-3 el tema ya invierte los dos lados. */
.hist-reemplazada {
  display:inline-block; font-size:11px; font-weight:600; white-space:nowrap;
  margin-left:6px; padding:2px 7px; border-radius:6px;
  color:var(--amber); border:1px solid var(--amber); background:var(--navy-3);
}
.hist-nota td { color:var(--text-2); font-style:italic; }

/* Clases de armazón que el apartado usa y styles.css no define: sin esto el
   encabezado, la fila de KPIs y los estados de carga/vacío quedan sin estilo.
   .page-head es la variante en columna de .page-header (no lleva acciones a la
   derecha) y .kpi-row es un .kpi-grid de 5 columnas, una por KPI del historial. */
.page-head { display:flex; flex-direction:column; }
.kpi-row { display:grid; grid-template-columns:repeat(5,1fr); gap:14px; }
@media(max-width:1100px) { .kpi-row { grid-template-columns:repeat(2,1fr); } }
.hist-tbl { width:100%; border-collapse:collapse; font-size:13px; }
#histTabla .loading,
#histTabla .empty {
  padding:28px 20px; text-align:center; color:var(--text-2); font-size:13px;
  background:var(--navy-3); border:1px solid var(--border); border-radius:var(--radius);
}
#histTabla .empty p + p { margin-top:6px; }
#histTabla .muted { color:var(--text-3); font-size:12px; }
.hist-filtros input,
.hist-filtros select,
.hist-filtros .mxdp-campo {
  background:var(--navy-4); color:var(--text); border:1px solid var(--border-2);
  border-radius:8px; padding:7px 11px; font-family:var(--font); font-size:12px;
}
.hist-filtros input:focus,
.hist-filtros select:focus { outline:2px solid var(--blue-light,#60a5fa); outline-offset:1px; }

/* ── Historial de Pagos: drill-down y búsqueda ── */
/* Cabecera del detalle: quién autorizó, quién sub-confirmó y, cuando SAP
   rechazó, el detalle del error (que antes solo existía en la consola). */
.hist-detalle-head {
  display:flex; align-items:center; gap:16px; flex-wrap:wrap;
  font-size:12px; color:var(--text-2); margin-bottom:10px;
}
.hist-detalle-head strong {
  color:var(--text-3); font-weight:600; font-size:10px;
  letter-spacing:.5px; text-transform:uppercase; margin-right:4px;
}
.hist-detalle-head .btn { margin-left:auto; }
/* El mensaje de SAP toma toda una línea: es texto largo, no un chip. */
/* `.hist-sap-detalle` (el mensaje de SAP en una línea completa) se declara una sola vez, más abajo. */

/* La regla global `.tbl-wrap table td:first-child { position:sticky; left:0 }`
   viene de la tabla del cashflow, donde la primera columna es el rótulo de la
   fila. Acá no aporta y, sin fondo propio, la columna "Doc SAP" se superpondría
   al contenido que pasa por debajo al scrollear en horizontal.

   El selector repite `.tbl-wrap table` a propósito: `.hist-tbl td:first-child`
   es (0,2,1) y PIERDE contra la regla global (0,2,2) —dos selectores de tipo,
   `table` y `td`, contra uno—, así que estar más abajo en el archivo no alcanza.
   Con la clase sobre el `table` queda (0,3,2) y gana. */
.tbl-wrap table.hist-tbl th:first-child,
.tbl-wrap table.hist-tbl td:first-child { position:static; }

/* Pie del grupo de notas. Va después de `.hist-nota td` (misma especificidad) a
   propósito: el neto no es una nota más, se lee como total. */
/* ── .btn-danger ───────────────────────────────────────────────────────────
   No existía: styles.css define .btn, .btn-primary y .btn-ghost, pero ninguna
   variante para acciones destructivas. La necesita mxConfirmar() en app.js
   para el botón de un diálogo con `peligro:true`, y queda disponible para los
   11 confirm() nativos que todavía faltan migrar.

   Sigue la misma forma que .btn-primary (fondo pleno, texto blanco) cambiando
   solo el color, para que un botón peligroso se lea como botón y no como otra
   cosa. El rojo es el mismo que usa la app para estados de error. */
/* ⚠ Medido: texto blanco sobre `var(--red)` a secas da 3,76:1 en oscuro (el
   rojo de acento es demasiado brillante para blanco encima), y el hover en
   el literal #f87171 —más brillante todavía, pensado como el "highlight" de
   un botón que YA cumplía— caía a 2,77:1 en los DOS temas. No es un problema
   de tema (el literal no cambia y el defecto tampoco), es que ninguno de los
   dos alcanzaba el mínimo 4,5:1 con texto blanco encima. `color-mix` sobre el
   token de siempre lo oscurece sin tocar ningún archivo ajeno: 4,99:1 en
   oscuro y 7,11:1 en claro para el reposo; 6,76:1 / 7,72:1 para el hover
   (más oscuro todavía, para que se note el cambio). */
.btn-danger        { background:var(--red-solido, #CB3A3A); color:#fff; }
.btn-danger:hover  { background:color-mix(in srgb, var(--red, #ef4444) 70%, black); }

/* ── Columna de selección masiva del modal "Definir Solicitudes" ───────────
   La casilla de la tanda se muestra u oculta con UNA clase en #solResults, no
   re-renderizando la lista. Antes el switch llamaba a solicitudRender(), que
   reconstruye con innerHTML todas las filas de la prenómina — de ahí que se
   sintiera trabado. Con la clase, el trabajo lo hace el navegador.

   Y de paso la transición sale gratis: la casilla crece desde ancho 0, así que
   parece desplegarse junto al `Sel` empujándolo a la derecha.

   `flex-shrink:0` y `overflow:hidden` evitan que el contenido se salga mientras
   el ancho está a medio camino. */
.sol-cb-masivo,
.sol-th-masivo {
  width: 0;
  min-width: 0;
  opacity: 0;
  margin-right: 0;
  overflow: hidden;
  flex-shrink: 0;
  pointer-events: none;
  transition: width .18s ease, opacity .16s ease, margin-right .18s ease;
}
#solResults.masivo .sol-cb-masivo { width: 15px; opacity: 1; margin-right: 14px; pointer-events: auto; }
#solResults.masivo .sol-th-masivo { width: 21px; opacity: 1; margin-right: 14px; pointer-events: auto; }

/* Sin animación para quien pidió menos movimiento: la columna aparece y
   desaparece, pero sin recorrido. */
@media (prefers-reduced-motion: reduce) {
  .sol-cb-masivo, .sol-th-masivo { transition: none; }
}

/* ── Historial de Pagos: el modal de UN pago ─────────────────────────────────
   Reemplaza al despliegue en línea. Con 1300 facturas, el detalle empujaba el
   listado fuera de la pantalla y había que hacer scroll a ciegas para volver.
   z-index por debajo del toast (100000) y de mxConfirmar (9800): un aviso tiene
   que poder verse por encima del modal. */
.hist-modal-ov {
  position: fixed; inset: 0; z-index: 9600;
  background: rgba(0,0,0,.72); backdrop-filter: blur(4px);
  display: flex; align-items: center; justify-content: center; padding: 24px;
}
.hist-modal-ov[hidden] { display: none; }
.hist-modal {
  background: var(--navy-2); border: 1px solid var(--border-2); border-radius: 14px;
  /* Grande a propósito: es una tabla de 9 columnas con cientos de filas. */
  width: 96vw; max-width: 1500px; max-height: 90vh;
  display: flex; flex-direction: column; overflow: hidden;
  box-shadow: 0 24px 60px rgba(0,0,0,.55);
}
/* El encabezado es identidad, no datos: qué pago es y de cuándo. Todo lo demás
   —quién autorizó, quién confirmó, cuántas facturas— vive abajo, y repetirlo acá
   obligaba a mantener dos formatos del mismo dato. */
.hist-modal-head {
  display: flex; align-items: center; gap: 14px;
  padding: 16px 20px; border-bottom: 1px solid var(--border-2); flex-shrink: 0;
  background: var(--navy-3);
}
/* "PAGO #1320" se lee como UN título, no como rótulo + dato: a 11px y apagado, la
   palabra quedaba como una etiqueta suelta al lado de un número el doble de grande.
   Mismo tamaño y mismo color; lo único que los distingue es la tipografía —el número
   va en mono porque es un identificador. */
.hist-modal-id { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.hist-modal-rot {
  font-size: 21px; font-weight: 700; letter-spacing: .5px; text-transform: uppercase;
  color: var(--text);
}
.hist-modal-num {
  font-size: 21px; font-weight: 700; color: var(--text);
  font-family: var(--mono); letter-spacing: -.5px;
}
/* La fecha se separa del número con un punto medio dibujado, no escrito: así el JS
   pone solo el dato y el separador no viaja en el texto. */
.hist-modal-sub { font-size: 13px; color: var(--text-2); font-family: var(--mono); }
.hist-modal-sub::before { content: '·'; color: var(--text-3); margin-right: 14px; }
.hist-modal-x {
  margin-left: auto; flex-shrink: 0;
  width: 32px; height: 32px; display: flex; align-items: center; justify-content: center;
  background: transparent; border: 1px solid var(--border-2); border-radius: 8px;
  cursor: pointer; color: var(--text-3); font-size: 15px; line-height: 1;
  transition: color .12s ease, background .12s ease, border-color .12s ease;
}
.hist-modal-x:hover { color: var(--text); background: var(--navy-4); border-color: var(--text-3); }
.hist-modal-x:focus-visible { outline: 2px solid var(--blue-light, #60a5fa); outline-offset: 2px; }

@media (max-width: 640px) {
  .hist-modal-sub::before { display: none; }
  .hist-modal-head { flex-wrap: wrap; }
}
/* El cuerpo es lo único que scrollea: el encabezado queda fijo, así que nunca se
   pierde de vista de qué pago son las facturas que se están mirando. */
.hist-modal-body { overflow: auto; padding: 16px 20px 20px; flex: 1; }
.hist-modal-kpis { margin-bottom: 16px; } /* única declaración (antes había otra más abajo con 14px → 16px) */

/* ── Historial de Pagos: el interior del modal ───────────────────────────────
   Escala de espaciado: 6 · 10 · 16 · 24. Ningún par queda a menos de ~25%, así
   que dos medidas contiguas siempre se distinguen a ojo. */

/* Las cards del pago reusan `.kpi-card` entera, incluida su barra de acento de
   3px (`--accent-color`). El tono solo cambia esa variable y el color del valor:
   no se duplica el componente. */
/* `.hist-modal-kpis` lleva su margen arriba, junto al cuerpo del modal. */
.hist-kpi .kpi-value { font-size: 24px; }
/* El estado de SAP es texto, no una cifra: a 24px mono compite con el total
   pagado, que es el número que la gente vino a mirar. */
.hist-kpi-chico { font-size: 15px; font-family: var(--font); }

.hist-kpi-dato   { --accent-color: var(--blue-light, #60a5fa); }
.hist-kpi-si     { --accent-color: var(--green, #22c55e); }
.hist-kpi-si    .kpi-value { color: var(--green, #22c55e); }
/* NO PAGAR queda GRIS a propósito: es una decisión normal, no un error. En rojo
   pesaría igual que un fallo de SAP, que sí lo es. */
.hist-kpi-no     { --accent-color: var(--border-2); }
.hist-kpi-no    .kpi-value { color: var(--text-2); }
.hist-kpi-ok     { --accent-color: var(--border-2); }
.hist-kpi-alerta { --accent-color: var(--amber, #f59e0b); border-color: rgba(245,158,11,.45); }
.hist-kpi-alerta .kpi-value { color: var(--amber, #f59e0b); }

/* ── La cadena de autoría ──────────────────────────────────────────────────
   Tres eslabones con jerarquía de tres niveles: rótulo apagado, el CORREO como
   dato principal, la fecha como apoyo. Antes los tres pesaban igual y no se leía
   ninguno. */
/* El espacio se reparte ENTRE los elementos, no dentro de columnas.
   
   Con `grid-template-columns: 1fr auto 1fr …` la flecha caía geométricamente en el
   medio, pero se VEÍA pegada al bloque de la derecha: el texto de cada eslabón no
   llena su columna de `1fr`, así que todo el sobrante se acumulaba a su derecha y la
   flecha quedaba lejos del bloque anterior y a 16px del siguiente.
   
   Con `space-between` los seis elementos miden lo que mide su contenido y el
   sobrante se reparte en huecos IGUALES, así que la flecha queda de verdad
   equidistante entre los dos eslabones que conecta. */
.hist-traza {
  display: flex; flex-wrap: wrap;
  justify-content: space-between;
  /* `flex-start` y no `center`: el eslabón de SAP tiene una línea más (el correo de
     quien envió), y centrando cada bloque los rótulos quedaban a distinta altura. */
  align-items: flex-start;
  gap: 12px 0;
  padding: 16px 20px; margin-bottom: 16px;
  background: var(--navy-3); border: 1px solid var(--border); border-radius: var(--radius);
}
/* `min-width:0` permite que el ellipsis del correo funcione: sin esto el bloque se
   estira hasta que el texto entre y se come el espacio de los demás. El tope evita
   que un correo largo desbalancee la fila entera. */
.hist-paso { min-width: 0; max-width: 300px; }
.hist-paso-rot {
  font-size: 10px; font-weight: 600; letter-spacing: .6px; text-transform: uppercase;
  color: var(--text-3); margin-bottom: 3px;
}
.hist-paso-quien {
  font-size: 14px; font-weight: 600; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* El correo de quien envió a SAP: mismo blanco que los otros dos responsables, un
   punto más chico porque va bajo el badge de estado. Antes iba apagado, como si
   fuera relleno — y es el último eslabón de la cadena de autoría. */
/* El correo de quien envió a SAP va EN LÍNEA con el badge de estado. Mismo blanco
   que los otros responsables; el separador es espacio, no un punto medio, porque el
   badge ya trae su propio ícono y dos separadores seguidos se leen como ruido. */
.hist-paso-mail {
  margin-left: 8px; font-size: 13px; font-weight: 600; color: var(--text);
}
.hist-paso-cuando { font-size: 12px; color: var(--text-2); font-family: var(--mono); margin-top: 3px; }
.hist-pendiente   { color: var(--text-3); font-weight: 400; font-style: italic; }
/* La flecha es orientación, no contenido: se dibuja con CSS —una línea que se
   desvanece y termina en punta— en vez de una '→' tipográfica, que a este tamaño
   se veía como un carácter suelto y competía con los correos. Sin texto adentro y
   oculta a los lectores de pantalla: el orden ya lo da la lectura. */
.hist-traza-flecha {
  position: relative; width: 46px; height: 2px; border-radius: 2px;
  /* Centrada respecto de los bloques, no alineada a su primera línea. */
  align-self: center; flex: 0 0 auto; margin: 0 18px;
  background: linear-gradient(90deg, transparent, var(--border-2) 45%, var(--border-2));
}
.hist-traza-flecha::after {
  content: ''; position: absolute; right: 0; top: 50%;
  width: 7px; height: 7px; transform: translateY(-50%) rotate(45deg);
  border-top: 2px solid var(--border-2); border-right: 2px solid var(--border-2);
  border-top-right-radius: 2px;
}
/* Excel es una acción secundaria acá: el contenido es la traza, no el botón.
   Centrado verticalmente respecto del bloque, no pegado a su primera línea. */
.hist-traza-xls { white-space: nowrap; align-self: center; flex: 0 0 auto; }
.hist-sap-detalle {
  flex-basis:100%; margin-left:0; font-style:normal;
  grid-column: 1 / -1; margin-top: 6px; padding: 8px 10px; font-size: 12px;
  color: var(--red-txt, var(--red, #ef4444));
  background: rgba(239,68,68,.08); border: 1px solid rgba(239,68,68,.28); border-radius: 8px;
}

/* ── Spinner ───────────────────────────────────────────────────────────────
   `.loading` está estilada solo dentro de `#histTabla`; en el modal era texto
   pelado, sin centrar ni animar. */
.hist-cargando {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 10px; padding: 48px 24px; color: var(--text-2);
}
.hist-spinner {
  width: 30px; height: 30px; border-radius: 50%;
  border: 3px solid var(--border-2);
  border-top-color: var(--blue-light, #60a5fa);
  animation: histSpin .8s linear infinite;
}
.hist-cargando-txt { font-size: 13px; }
@keyframes histSpin { to { transform: rotate(360deg); } }
/* Quien pidió menos movimiento ve un pulso en vez de un giro: sigue indicando
   actividad sin rotación continua. */
@media (prefers-reduced-motion: reduce) {
  .hist-spinner { animation: skeleton-pulse 1.4s ease-in-out infinite; border-top-color: var(--border-2); }
}

/* Angosto: los eslabones se apilan y las flechas sobran — la lectura pasa a ser
   de arriba abajo, que ya indica el orden sin necesidad de dibujarlo. */
@media (max-width: 900px) {
  .hist-traza { flex-direction: column; align-items: stretch; gap: 14px; }
  .hist-traza-flecha { display: none; }
  .hist-paso { max-width: none; }
  .hist-traza-xls { align-self: flex-start; }
}

/* El spinner también se usa en la carga del apartado y en la búsqueda, dentro de
   #histTabla. Ahí no lleva el fondo con borde que tenía `.loading`: es una espera,
   no un bloque de contenido. */
#histTabla .hist-cargando { padding: 56px 24px; }

/* ── Calendario propio (date-picker.js) ──────────────────────────────────────
   El panel de un <input type="date"> lo dibuja el sistema operativo y no acepta
   CSS. Acá el input real queda oculto —sigue siendo la fuente de verdad— y lo que
   se ve es un botón más este panel. */
/* Sin `!important`: `:is(…, #mxdp-oculto#mxdp-oculto)` le da especificidad de dos `#id` (el id no existe) para
   ganarle a cualquier regla de la app que estilice el control nativo oculto. */
:is(.mxdp-oculto, #mxdp-oculto#mxdp-oculto) { position: absolute; opacity: 0; pointer-events: none; width: 0; height: 0; padding: 0; border: 0; }

.mxdp-campo {
  display: inline-flex; align-items: center; justify-content: space-between; gap: 8px;
  background: var(--navy-4); color: var(--text); border: 1px solid var(--border-2);
  border-radius: 8px; padding: 6px 10px; font-family: var(--font); font-size: 12px;
  cursor: pointer; min-width: 132px; text-align: left;
  transition: border-color .12s ease, background .12s ease;
}
.mxdp-campo:hover:not(:disabled) { border-color: var(--text-3); background: var(--navy-3); }
.mxdp-campo:focus-visible { outline: 2px solid var(--blue-light, #60a5fa); outline-offset: 1px; }
.mxdp-campo:disabled { opacity: .5; cursor: not-allowed; }
.mxdp-vacio { color: var(--text-3); }
.mxdp-ico   { color: var(--text-3); font-size: 10px; }

.mxdp-panel {
  position: absolute; z-index: 10050; width: 268px; padding: 12px;
  background: var(--navy-2); border: 1px solid var(--border-2); border-radius: 12px;
  box-shadow: 0 16px 40px rgba(0,0,0,.5); animation: fadeUp .14s ease;
}
.mxdp-panel[hidden] { display: none; }
.mxdp-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.mxdp-mes  { font-size: 13px; font-weight: 700; color: var(--text); }
.mxdp-nav {
  width: 26px; height: 26px; border-radius: 7px; cursor: pointer; font-size: 15px;
  background: transparent; border: 1px solid var(--border-2); color: var(--text-2);
}
.mxdp-nav:hover { color: var(--text); background: var(--navy-4); }

.mxdp-sem, .mxdp-dias { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.mxdp-sem span {
  text-align: center; font-size: 10px; font-weight: 600; color: var(--text-3);
  padding-bottom: 4px; text-transform: uppercase;
}
.mxdp-dia {
  height: 32px; border-radius: 7px; cursor: pointer; font-size: 12px;
  background: transparent; border: 1px solid transparent; color: var(--text);
  font-family: var(--mono);
}
.mxdp-dia:hover { background: var(--navy-4); }
.mxdp-dia:focus-visible { outline: 2px solid var(--blue-light, #60a5fa); outline-offset: -2px; }
/* El día de hoy se marca con un BORDE y el elegido con relleno: dos señales
   distintas, así se distinguen aunque coincidan en el mismo casillero. */
.mxdp-hoy   { border-color: var(--border-2); font-weight: 700; }
.mxdp-sel   { background: var(--blue-light, #60a5fa); color: #0b1120; font-weight: 700; border-color: transparent; }
.mxdp-sel:hover { background: var(--blue-light, #60a5fa); }
.mxdp-fuera { color: var(--text-3); opacity: .35; height: 32px; display: flex; align-items: center; justify-content: center; font-size: 12px; }
.mxdp-hueco { height: 32px; }

.mxdp-pie { display: flex; gap: 8px; margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border-2); }
.mxdp-accion {
  flex: 1; padding: 6px; border-radius: 7px; cursor: pointer; font-size: 12px;
  background: var(--navy-4); border: 1px solid var(--border-2); color: var(--text-2);
}
.mxdp-accion:hover { color: var(--text); background: var(--navy-3); }

@media (prefers-reduced-motion: reduce) { .mxdp-panel { animation: none; } }

/* ── Desplegables propios (select-propio.js) ─────────────────────────────────
   Mismo lenguaje visual que el desplegable de Proveedores Críticos
   (`.clasif-dd-*`), que fue el primero del proyecto. El `<select>` real queda
   oculto y sigue siendo la fuente de verdad. */
/* Sin `!important`: `:is(…, #mxsel-oculto#mxsel-oculto)` le da especificidad de dos `#id` (el id no existe) para
   ganarle a cualquier regla de la app que estilice el control nativo oculto. */
:is(.mxsel-oculto, #mxsel-oculto#mxsel-oculto) { position: absolute; opacity: 0; pointer-events: none; width: 0; height: 0; padding: 0; border: 0; }

.mxsel-btn {
  display: inline-flex; align-items: center; justify-content: space-between; gap: 8px;
  min-width: 150px; padding: 7px 11px;
  background: var(--navy-4); border: 1px solid var(--border-2); border-radius: 8px;
  color: var(--text-3); font-size: 12px; font-family: var(--font);
  cursor: pointer; text-align: left;
  transition: border-color .12s ease, background .12s ease;
}
.mxsel-btn:hover:not(:disabled) { border-color: var(--text-3); background: var(--navy-3); }
.mxsel-btn:focus-visible { outline: 2px solid var(--blue-light, #60a5fa); outline-offset: 1px; }
.mxsel-btn:disabled { opacity: .5; cursor: not-allowed; }
/* Con valor elegido el texto pasa a blanco: distingue "elegí esto" de "está en el
   valor vacío", igual que el desplegable de Críticos. */
.mxsel-btn.has-val { color: var(--text); }
.mxsel-lbl { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mxsel-car { color: var(--text-3); font-size: 10px; flex-shrink: 0; }

/* `fixed` para escapar del overflow de una tabla, donde el panel quedaría
   recortado. El JS pone left/top. */
.mxsel-panel {
  position: fixed; z-index: 10050; max-width: 340px;
  background: var(--navy-2); border: 1px solid var(--border-2); border-radius: 10px;
  box-shadow: 0 14px 36px rgba(0,0,0,.5); overflow: hidden; animation: fadeUp .12s ease;
}
.mxsel-panel[hidden] { display: none; }
.mxsel-fijo { padding: 8px; border-bottom: 1px solid var(--border-2); }
.mxsel-fijo input {
  width: 100%; background: var(--navy-4); border: 1px solid var(--border-2);
  border-radius: 7px; padding: 6px 9px; color: var(--text); font-size: 12px;
  font-family: var(--font); outline: none;
}
.mxsel-scroll { max-height: 260px; overflow-y: auto; padding: 5px; scrollbar-width: thin; }
.mxsel-item {
  display: block; width: 100%; text-align: left; padding: 7px 10px; border: 0;
  border-radius: 7px; background: transparent; color: var(--text-2);
  font-size: 12px; font-family: var(--font); cursor: pointer;
}
.mxsel-item:hover:not(:disabled) { background: var(--navy-4); color: var(--text); }
.mxsel-item:focus-visible { outline: 2px solid var(--blue-light, #60a5fa); outline-offset: -2px; }
.mxsel-item:disabled { opacity: .45; cursor: not-allowed; }
.mxsel-item.sel { background: var(--navy-3); color: var(--text); font-weight: 600; }
.mxsel-item[hidden] { display: none; }
.mxsel-vacio { padding: 12px; font-size: 12px; color: var(--text-3); text-align: center; }

@media (prefers-reduced-motion: reduce) { .mxsel-panel { animation: none; } }

/* El bruto bajo el neto, cuando una nota de crédito o débito los separa. Chico y
   apagado: está para poder reconstruir de dónde salió el neto, no para competir
   con él. */
.hist-bruto {
  font-size: 10.5px; color: var(--text-3); font-weight: 400; margin-top: 2px;
  font-family: var(--mono);
}

/* El signo de una nota dice qué HACE, no qué número se archivó: la convención del
   feed guarda las NC en positivo y las ND en negativo, al revés de la intuición.
   Colores apagados: el dato principal de la fila es el neto de la madre. */
.hist-nota-resta { color: var(--red-txt, var(--red, #ef4444)); opacity: .85; }
.hist-nota-suma  { color: var(--amber, #f59e0b); opacity: .85; }
/* Signo archivado incoherente con el rol: se muestra crudo y se avisa. */
.hist-nota-rara  { color: var(--amber, #f59e0b); font-weight: 600; cursor: help; }

/* ── Listado de pagos: jerarquía y filas que piden atención ──────────────────── */

/* El N° de pago es el identificador: mono para que los dígitos se alineen entre
   filas y se puedan comparar de un vistazo. */
.hist-npago { font-family: var(--mono); color: var(--text-2); font-weight: 600; }

/* Dato de apoyo dentro de una celda: el correo de Tesorería va DEBAJO de su fecha
   —son dos cosas distintas—, y el desglose SI/NO va EN LINEA con el total, porque
   es el mismo dato repartido. */
.hist-sub { font-size: 10.5px; color: var(--text-3); margin-top: 2px; font-weight: 400; }
.hist-sub-inline { font-size: 10.5px; color: var(--text-3); font-weight: 400; margin-left: 6px; }

/* Una franja lateral marca la fila que necesita atención. El fondo va MUY tenue:
   con varios pagos con divergencias seguidos, un tinte fuerte deja la tabla
   manchada y deja de señalar nada.

   ⚠ El color nunca es el único indicador: la columna SAP conserva su badge con
   ícono (✅/❌/⏳) y el contador ⚠N de divergencias. */
.hist-tanda.hist-fila-fallo   { box-shadow: inset 3px 0 0 var(--red, #ef4444);   background: rgba(239,68,68,.045); }
.hist-tanda.hist-fila-diverg  { box-shadow: inset 3px 0 0 var(--amber, #f59e0b); background: rgba(245,158,11,.045); }
.hist-tanda.hist-fila-fallo:hover  { background: rgba(239,68,68,.09); }
.hist-tanda.hist-fila-diverg:hover { background: rgba(245,158,11,.09); }

/* Los montos y el número de pago no se parten en dos renglones al angostar. */
.hist-tbl td.num { white-space: nowrap; }

/* El vínculo de una nota, DEBAJO de su número de documento. Apagado: el dato es el
   documento; el "NC → n.º de factura" es la explicación de a qué factura pertenece.

   ⚠ En su propio renglón, y no al lado, por una razón medida: al lado, la celda más
   ancha de la columna pasaba a ser "└ (10 dígitos) NC → (10 dígitos)" y el navegador
   dimensionaba TODA la columna por ella — 224px para un dato de 10 dígitos. Basta
   una nota en la tanda para inflar la columna en las mil filas restantes. Abajo, la
   columna baja a 139px y solo las filas de nota crecen 13px de alto. */
.hist-vinculo {
  display: block; font-size: 10.5px; color: var(--text-3);
  margin-left: 14px; margin-top: 1px;
}

/* ═══════════════════════════════════════════════════════════════════════════
   Historial de Pagos — desglose semanal por rubro de abastecimiento
   ═══════════════════════════════════════════════════════════════════════════ */

.hist-grafico {
  background: var(--navy-3);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px 20px 12px;
  margin-bottom: 16px;
}

.hist-graf-head {
  display: flex; align-items: baseline; justify-content: space-between;
  flex-wrap: wrap; gap: 4px 16px;
  margin-bottom: 12px;
}
.hist-graf-tit {
  font-size: 13px; font-weight: 600; color: var(--text);
  letter-spacing: .2px;
}
/* Dice cuántos rubros y semanas se están viendo, y —cuando aplica— cuántas
   semanas quedaron fuera del recorte. Un recorte que no se anuncia se lee como
   "esto es todo lo que hay". */
.hist-graf-nota {
  font-size: 11px; color: var(--text-3); font-family: var(--mono);
}

/* Altura fija: Chart.js con maintainAspectRatio:false necesita que el contenedor
   la defina, y sin esto el lienzo crece en cada repintado hasta llenar la página. */
.hist-graf-lienzo { position: relative; height: 320px; }
/* El atributo `hidden` lo pisa cualquier regla que declare `display`, y este
   contenedor la tiene. Sin esto el lienzo no se oculta y el spinner queda
   debajo del gráfico ya dibujado. */
.hist-graf-lienzo[hidden] { display: none; }

.hist-graf-vacio {
  display: flex; align-items: center; justify-content: center;
  min-height: 120px;
  font-size: 13px; color: var(--text-3); text-align: center;
}
/* Igual que el lienzo: `display: flex` GANA sobre el atributo `hidden`, asi que
   sin esta regla el spinner se seguia viendo DEBAJO del grafico ya dibujado, con
   `el.hidden === true` en el DOM. Una sonda que mire el atributo informa "oculto"
   mientras la pantalla muestra lo contrario: hay que medir el display calculado. */
.hist-graf-vacio[hidden] { display: none; }

/* La columna Rubro de la tabla del modal. Se recorta con puntos suspensivos en vez
   de partir en dos renglones: son nombres largos ("REDES, FONDEO Y ESTRUCTURAS DE
   CULTIVO") y dejarlos crecer descuadraba el alto de todas las filas. El nombre
   completo queda en el title. */
.hist-rubro {
  display: inline-block; max-width: 160px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  vertical-align: bottom;
  font-size: 11.5px; color: var(--text-2);
}
.hist-sin-rubro {
  font-size: 11.5px; color: var(--text-3); font-style: italic;
}

@media (max-width: 900px) {
  .hist-graf-lienzo { height: 260px; }
  .hist-rubro { max-width: 110px; }
}


/* El switch "Ver todos los rubros" del panel del gráfico.
   Mismas medidas que el switch de REVISAR en Pago de Facturas (pista 36x20, perilla
   de 14) para que los dos se lean como el mismo control, pero como clases: aquel
   está escrito con estilos en línea y no se puede reusar. */
.hist-graf-ctrl {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
}

/* Acá vivían las 7 reglas del switch "Ver todos los rubros" (.hist-switch y su
   .hist-switch-pista). El switch se retiró el 17-08-2026 y su CSS se fue con él:
   dejarlo habría sido código muerto, y `Backend/tests/css-muerto.test.js` lo
   detecta — ya se acumularon 45 reglas de funcionalidad retirada una vez.
   Si vuelve a hacer falta un switch en este apartado, el patrón está en el
   historial de git. */



/* ═══════════════════════════════════════════════════════════════════════════
   Historial de Pagos — anchos de la tabla del modal
   ═══════════════════════════════════════════════════════════════════════════

   El problema: una tabla normal se dimensiona por su CONTENIDO, así que medía
   1636px fijos y no se adaptaba a nada. Resultado: scroll horizontal SIEMPRE —
   178px de sobra en un monitor de 1920, 367px en uno de 1366. Y el zoom del
   navegador achica el ancho útil en la misma proporción, así que un 1920 al 125%
   se comporta como un 1536.

   `table-layout: fixed` invierte eso: la tabla ocupa el ancho disponible y las
   columnas se reparten lo que hay.

   ⚠ El reparto NO es uniforme, y ahí está todo el criterio: las columnas que se
   leen EXACTAS —vencimiento, monto, y las dos decisiones— llevan ancho fijo
   suficiente para su contenido completo. Un primer intento las puso en porcentajes
   y quedaron "07-08-20…" y "NO…", que es bastante peor que el scroll: un dato
   cortado se lee como un dato distinto. Solo se recortan las tres columnas de
   texto libre (proveedor, rubro, texto), que llevan el valor completo en su
   `title`.

   Medido con la grabación de producción: entra sin scroll en 1920, 1536 y 1366. */

#histModalBody .hist-tbl { table-layout: fixed; width: 100%; }

/* El recorte con puntos suspensivos es la contrapartida del ancho fijo: sin esto
   el texto largo se desborda sobre la columna vecina. */
#histModalBody .hist-tbl th,
#histModalBody .hist-tbl td { overflow: hidden; text-overflow: ellipsis; }

/* Los anchos de las columnas EXACTAS no son a ojo: salen de medir, con la grabación
   de producción, el ancho que necesita la celda más larga de cada una. Bajarlos
   vuelve a cortar el dato. */
#histModalBody .hist-tbl th:nth-child(1) { width: 140px; }  /* Doc SAP    — exacto */
#histModalBody .hist-tbl th:nth-child(2) { width: 120px; }  /* Ref. prov. — se recorta */
#histModalBody .hist-tbl th:nth-child(3) { width: auto;  }  /* Proveedor  — se recorta */
#histModalBody .hist-tbl th:nth-child(4) { width: 150px; }  /* Rubro      — se recorta */
#histModalBody .hist-tbl th:nth-child(5) { width: auto;  }  /* Texto      — se recorta */
#histModalBody .hist-tbl th:nth-child(6) { width: 115px; }  /* Venc.      — exacto */
#histModalBody .hist-tbl th:nth-child(7) { width: 135px; }  /* Neto USD   — exacto */
#histModalBody .hist-tbl th:nth-child(8) { width: 100px; }  /* CFO        — exacto */
#histModalBody .hist-tbl th:nth-child(9) { width: 135px; }  /* Tesorería  — exacto */

/* La columna Rubro ya no necesita su propio tope: se lo da la tabla. */
#histModalBody .hist-rubro { max-width: 100%; }



/* Encabezados que ordenan (tabla del modal). Misma convención visual que
   Proveedores Críticos: la columna activa en azul, ⇅ / ▾ / ▴ como indicador. */
#histModalBody .hist-tbl th[data-hist-sort] { cursor: pointer; user-select: none; }
#histModalBody .hist-tbl th[data-hist-sort]:hover { color: var(--text); }
#histModalBody .hist-tbl th.hist-th-activa { color: var(--blue-light-txt, var(--blue-light, #60a5fa)); }
/* La flecha no compite con el rótulo: es el estado del control, no un dato. */
#histModalBody .hist-tbl .sort-arrow { opacity: .55; font-size: 10px; }
#histModalBody .hist-tbl th.hist-th-activa .sort-arrow { opacity: 1; }



/* ── Íconos del menú ──────────────────────────────────────────────────────────
   Eran emoji. Un emoji lo dibuja el SISTEMA OPERATIVO: sale distinto en Windows
   y en Mac, y trae SUS colores — en el menú convivían un azul, un amarillo, un
   rojo y un gris que nadie eligió. Y como no heredan el color del texto, al
   marcar un ítem como activo se iluminaba la etiqueta y el ícono no la seguía.

   Ahora son SVG de una sola familia con `stroke: currentColor`: heredan el color,
   así que el ítem activo se ilumina entero y sirven igual en los dos diseños. */
.nav-icon { display: inline-flex; align-items: center; justify-content: center; }
.nav-icon svg { width: 18px; height: 18px; display: block; }
/* Acá había un `.sidebar.collapsed .nav-icon svg { width:19px }`. La clase
   `collapsed` dejó de existir el 17-08-2026 (commit 528222c) y la regla quedó
   muerta 24 horas SIN que el test de CSS muerto la viera: `collapsed` aparecía
   suelta en `pago-facturas.js` (`const collapsed = …`, un colapso de grupos de
   la tabla que no tiene nada que ver con el menú) y eso alcanzaba para que el
   detector de uso literal la diera por viva. Es exactamente el falso negativo
   que ese test documenta.
   No se revive con el nombre nuevo a propósito: el ícono mide 18px en los dos
   estados, y volver a los 19px al colapsar metería un salto de 1px NO animado
   —`width` del svg no está en ninguna transición— en cada uso del botón, justo
   en la animación que el usuario aprobó y pidió no tocar. */


/* ══════════════════════════════════════════════════════════════════════════════
   MOVIMIENTO REDUCIDO  (ítem 13 de la auditoría de fluidez, 21-08-2026)
   ──────────────────────────────────────────────────────────────────────────────
   Quien pide menos movimiento en su sistema operativo lo pide por algo: mareos,
   migraña, trastornos vestibulares. La aplicación tiene ~38 animaciones repartidas
   en once hojas, y hasta hoy solo las de `componentes.css` y el login respetaban
   la preferencia.

   ⚠ Se anula la DURACIÓN, no la animación. Con `animation: none` una animación de
     salida —las que terminan en `opacity: 0` con `forwards`— deja al elemento en su
     estado inicial, o sea VISIBLE cuando debía irse; y una de entrada que arranca en
     `opacity: 0` puede dejarlo invisible para siempre. Con `.01ms` cada animación
     corre completa y termina donde tenía que terminar, solo que sin que se vea el
     recorrido. Es la diferencia entre quitar el movimiento y romper la pantalla.

   ⚠ Los indicadores de PROGRESO se quedan animando. Un spinner congelado no se lee
     como "sin movimiento": se lee como una aplicación colgada, que es peor que la
     animación. La lista de abajo restaura solo el TIEMPO —duración e iteraciones— y
     no vuelve a nombrar ninguna animación: así cada elemento conserva la suya y no
     hay dos lugares declarando el mismo `@keyframes`.

   ⚠ La lista está escrita a mano porque el CSS no permite seleccionar por
     "animación infinita". Para que no quede vieja en silencio hay un test que la
     DERIVA de las hojas y exige que toda animación infinita esté acá o tenga su
     propio bloque de `prefers-reduced-motion` (`Backend/tests/movimiento.test.js`).
   ══════════════════════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {
  /* ⚠ Sin `!important`: la prioridad la da `:is(*, #mx-reducir#mx-reducir#mx-reducir)`, que vale
   *   lo que su argumento más fuerte —tres `#id`, aunque ese id no exista—, así que le gana a toda
   *   regla de la app (ninguna llega a tres id; hay una prueba). Lo único que podría ganarle es un
   *   estilo en línea de animación o transición, y el JS no escribe ninguno (también probado). */
  :is(*, #mx-reducir#mx-reducir#mx-reducir),
  :is(*, #mx-reducir#mx-reducir#mx-reducir)::before,
  :is(*, #mx-reducir#mx-reducir#mx-reducir)::after {
    animation-duration: .01ms;
    animation-delay: 0s;
    animation-iteration-count: 1;
    transition-duration: .01ms;
    transition-delay: 0s;
    scroll-behavior: auto;
  }

  /* Los indicadores de progreso: solo se les devuelve el tiempo. */
  /* Misma especificidad que la regla de arriba y escrita después: gana por orden. */
  :is(
    #loadBar,
    .skeleton-pulse,
    .hist-spinner,
    .mx-ico-gira,
    .pf-spin,
    .pc-spin,
    .mx-dash-spinner,
    #mx-reducir#mx-reducir#mx-reducir
  ) {
    animation-duration: 1.2s;
    animation-iteration-count: infinite;
  }
}
