/* ═══════════════════════════════════════════════════════════════════════════
   pago-facturas.css
   ───────────────────────────────────────────────────────────────────────────
   Estilos del apartado. Estaban DENTRO de pago-facturas.js, en SEIS bloques
   sueltos que se inyectaban en <style> desde JavaScript, cada uno junto al
   código que lo usaba y con su propia guarda por id. Se movieron acá sin cambiar
   una línea; lo único que cambia es que ahora están todos en un lugar y llegan
   con la página en vez de aparecer cuando alguien abre el panel que los usa.

   Los seis, en el orden en que estaban:
     gastos-row-css     el botón de borrar de la fila de Otros Pagos
     pyFiltrosHelpCss   el globo del ícono ⓘ de los filtros
     pyAvisoKeyframes   la entrada del aviso superior (pyAvisoSuperior)
     pyBorradorCSS      el pulso del banner de borrador y el destacado de filas
     cfGastosPopupCss   el desglose de gastos del modal "Enviar a Tesorería"
     pf-spin-css        el spinner del botón mientras se envía

   ⚠ El <link> va ÚLTIMO en el <head> de index.html: los <style> inyectados se
   agregaban en tiempo de ejecución, o sea después de todos los <link>. Moverlo
   antes cambiaría qué regla gana en los empates de especificidad, y eso no se ve
   en ningún error — se ve en la pantalla, torcida.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── gastos-row-css ─────────────────────────────────────────────────────── */
.gasto-del{background:none;border:0;color:var(--red-txt, var(--red));cursor:pointer;font-size:13px;padding:2px 8px;line-height:1;opacity:0;transition:opacity .15s}
.gasto-row:hover .gasto-del{opacity:.75}
.gasto-del:hover{opacity:1 !important}

/* ── pyFiltrosHelpCss ───────────────────────────────────────────────────── */
.pyfh-wrap { position:relative; display:inline-flex; align-items:center; cursor:help; }
.pyfh-ico  { display:inline-flex; align-items:center; justify-content:center;
             width:16px; height:16px; border-radius:50%;
             background:rgba(59,130,246,.15); color:var(--blue-light-txt, var(--blue-light));
             font-size:11px; font-weight:700; font-family:var(--font);
             border:1px solid rgba(59,130,246,.35); transition:all .12s; }
.pyfh-wrap:hover .pyfh-ico { background:rgba(59,130,246,.28); color:#fff; }
/* ⚠ `width:max-content` es lo que hace que cada globo tome lo que NECESITA hasta el
 *   tope. Sin él, un elemento `position:absolute` con `left:0` calcula su ancho por
 *   "shrink-to-fit" contra su contenedor —que es el ícono de 16px—, así que colapsa
 *   al `min-width` y queda angosto y ALTO: medido, la ayuda de Solicitudes quedaba en
 *   320×336 dejando sin usar los 420px del tope. Con max-content: el globo de los
 *   filtros sigue en 320 (su contenido no pide más) y el de Solicitudes usa los 420.
 * ⚠ El tope mira también la PANTALLA: 420px fijos se saldrían del borde en un
 *   notebook angosto, y el globo no tiene forma de reacomodarse solo. */
.pyfh-pop  { position:absolute; top:calc(100% + 8px); left:0;
             width:max-content; min-width:320px; max-width:min(420px, calc(100vw - 32px));
             background:var(--navy-2); border:1px solid var(--border-2);
             border-radius:10px; padding:10px 12px;
             box-shadow:0 12px 32px rgba(0,0,0,.5);
             opacity:0; visibility:hidden; transform:translateY(-4px);
             transition:opacity .15s ease, transform .15s ease, visibility .15s;
             z-index:100; pointer-events:none; }
.pyfh-wrap:hover .pyfh-pop { opacity:1; visibility:visible; transform:translateY(0); }
.pyfh-title { font-size:11px; color:var(--blue-light-txt, var(--blue-light)); text-transform:uppercase;
              letter-spacing:.5px; font-weight:700; margin-bottom:6px; }
.pyfh-table { width:100%; font-size:11px; color:var(--text-2); border-collapse:collapse; }
/* ⚠ `white-space:normal` NO es redundante, es el arreglo: `styles.css` declara un
 *   `td { white-space:nowrap }` GLOBAL para todas las tablas de la app, y esta regla
 *   no lo pisaba. Con nowrap el ancho MÍNIMO de una celda es su texto en UNA línea, y
 *   una tabla no se dimensiona por debajo de su mínimo ni con `max-width` en el padre:
 *   la tabla de la ayuda de Solicitudes salía 638px dentro de un globo de 420px y el
 *   texto se veía 244px afuera del fondo (medido en Chrome, en los dos temas).
 *   Toda tabla con PROSA adentro tiene que declararlo. */
.pyfh-table td { padding:3px 8px; border-bottom:1px solid rgba(255,255,255,.04);
                 vertical-align:top; white-space:normal; }
/* Seguro contra un token sin espacios (una URL, un código largo): sin esto el mismo
   desborde vuelve por otra puerta. La PRIMERA columna conserva su `nowrap` — son
   etiquetas cortas y se quieren en una línea. */
.pyfh-table td + td { overflow-wrap:anywhere; }
.pyfh-table td:first-child { color:var(--text); font-weight:600; white-space:nowrap; }
.pyfh-table tr:last-child td { border-bottom:0; }
.pyfh-hint { font-size:10px; color:var(--text-3); font-style:italic;
             margin-top:6px; padding-top:6px; border-top:1px dashed var(--border); }

/* ── pyAvisoKeyframes ───────────────────────────────────────────────────── */
@keyframes pyAvisoIn{from{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}

/* ── pyBorradorCSS ──────────────────────────────────────────────────────── */
@keyframes pyBorradorPulso {
  0%, 100% { box-shadow: 0 0 0 0 rgba(37,99,235,0);    background: rgba(37,99,235,0.08); }
  50%      { box-shadow: 0 0 0 7px rgba(37,99,235,0.13); background: rgba(37,99,235,0.18); }
}
#pyBorradorBanner.py-banner-pulse { animation: pyBorradorPulso 1.8s ease-in-out 3; }
@keyframes pyRowCambiadaPulso {
  0%, 100% { background: rgba(245,158,11,0.16); }
  50%      { background: rgba(245,158,11,0.32); }
}
tr.py-row-cambiada { animation: pyRowCambiadaPulso 1.6s ease-in-out 3;
                     background: rgba(245,158,11,0.16) !important; }
tr.py-row-cambiada td { border-bottom-color: rgba(245,158,11,0.4) !important; }
/* ⚠ de fila no restaurada. El globo vive FIJO a nivel de página (body):
   un position:absolute dentro del contenedor con scroll de la tabla se
   recortaba en los bordes. La capa fija no la corta ningún overflow. */
.pybwarn-wrap { display:inline-block; margin-left:7px; }
.pybwarn-ico { cursor:help; font-size:12px; color:var(--amber,#f59e0b); outline:none; }
/* ⚠ El fondo iba HARDCODEADO en ámbar oscuro mientras el texto usa var(--text)/var(--amber),
 * que sí se invierten. Mismo defecto que .solpop-bubble (ver 08431e6): en tema claro
 * quedaba texto oscuro sobre un fondo que seguía oscuro.
 * Arreglo: la superficie sale de los tokens que sí se invierten (--navy-3/--navy-2)
 * con un tinte de --amber mezclado por color-mix — conserva el matiz ámbar (distingue
 * esta advertencia de los pop-up de NC/ND) y se invierte con el tema porque --amber
 * también cambia de tono claro/oscuro. */
#pybwarnTip {
  position:fixed; z-index:99999; min-width:380px; max-width:480px;
  background:linear-gradient(180deg,
    color-mix(in srgb, var(--amber,#f59e0b) 8%, var(--navy-3,#1a2540)),
    color-mix(in srgb, var(--amber,#f59e0b) 8%, var(--navy-2,#111827)));
  border:1px solid rgba(245,158,11,.5); border-radius:12px;
  padding:10px 12px;
  box-shadow:0 10px 30px var(--sombra,rgba(0,0,0,.5)), 0 0 0 1px rgba(245,158,11,.08);
  opacity:0; pointer-events:none; transition:opacity .14s ease;
  text-align:left; white-space:normal; font-family:inherit; font-weight:400;
}
#pybwarnTip.on { opacity:1; }
#pybwarnTip .flecha {
  position:absolute; left:18px; border:7px solid transparent;
  filter:drop-shadow(0 1px 0 rgba(245,158,11,.4));
}
/* Cada flecha toma el MISMO color-mix que el extremo del gradiente al que se pega.
   Los dos extremos usan el MISMO % (8%) -- así en tema claro, donde --navy-3 y
   --navy-2 son el mismo blanco, el fondo queda uniforme y el título (que vive
   arriba) no cae contra una mezcla más oscura que la que se midió abajo. */
#pybwarnTip.abajo .flecha { top:100%; border-top-color:color-mix(in srgb, var(--amber,#f59e0b) 8%, var(--navy-2,#111827)); }      /* globo ARRIBA del ícono */
#pybwarnTip.arriba .flecha { bottom:100%; border-bottom-color:color-mix(in srgb, var(--amber,#f59e0b) 8%, var(--navy-3,#1a2540)); } /* globo DEBAJO (sin espacio arriba) */
.pybwarn-title { display:block; font-size:11px; font-weight:700; color:var(--amber,#f59e0b); margin-bottom:6px; }
.pybwarn-text {
  display:block; font-size:11.5px; color:var(--text,#f1f5f9); line-height:1.5;
  background:rgba(245,158,11,.10); border:1px solid rgba(245,158,11,.2);
  border-radius:7px; padding:7px 9px;
}

/* ── cfGastosPopupCss ───────────────────────────────────────────────────── */
.cf-gastos-summary:hover .cf-gastos-popup { opacity:1; transform:translateY(0); pointer-events:auto; }
.cf-gastos-summary { transition: background .15s ease; }
.cf-gastos-summary:hover { background: rgba(245,158,11,.06); }

/* ── pf-spin-css ────────────────────────────────────────────────────────── */
.pf-spin{display:inline-block;width:14px;height:14px;border:2px solid rgba(255,255,255,.35);border-top-color:#fff;border-radius:50%;vertical-align:-2px;margin-right:7px;animation:pfSpin .7s linear infinite}
@keyframes pfSpin{to{transform:rotate(360deg)}}

/* ── #pagoSec1 .kpi-card ─────────────────────────────────────────── */
#pagoSec1 .kpi-card{padding:9px 12px}
#pagoSec1 .kpi-value{font-size:16px !important;margin:1px 0}
#pagoSec1 .kpi-label{font-size:10px}
#pagoSec1 .kpi-sub{font-size:10px}
#pagoSec1 .kpi-grid{gap:8px}
/* Pop-up "globo de cómic" para las NC ligadas (ícono 💵)
 *
 * ⚠ El fondo iba HARDCODEADO en verde oscuro mientras el texto usa var(--text)/var(--green),
 * que sí se invierten. Mismo defecto que .solpop-bubble (ver 08431e6): en tema claro el
 * fondo se quedaba oscuro y el texto se perdía contra él.
 * Arreglo: la superficie sale de los tokens que sí se invierten (--navy-3/--navy-2) con
 * un tinte de --green mezclado por color-mix — conserva el matiz verde (distingue de un
 * vistazo la NC del ND, que es ámbar) y se invierte junto con el tema porque --green
 * también cambia de tono claro/oscuro. */
.ncpop-wrap{position:relative;display:inline-block;margin-left:6px;margin-top:-5px;margin-bottom:-5px;vertical-align:middle}
.ncpop-ico{cursor:help;outline:none;font-size:15px;display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:6px;vertical-align:middle;color:var(--green,#10b981);background:color-mix(in srgb, var(--green,#10b981) 12%, var(--navy-3,#1a2540));border:1px solid color-mix(in srgb, var(--green,#10b981) 40%, transparent);transition:background .12s,border-color .12s}
.ncpop-wrap:hover .ncpop-ico{background:color-mix(in srgb, var(--green,#10b981) 18%, var(--navy-3,#1a2540));border-color:color-mix(in srgb, var(--green,#10b981) 65%, transparent)}
.ncpop-bubble{
  position:absolute;left:50%;bottom:calc(100% + 10px);transform:translateX(-50%) scale(.96);
  transform-origin:bottom center;min-width:230px;max-width:300px;
  background:linear-gradient(180deg,
    color-mix(in srgb, var(--green,#22c55e) 8%, var(--navy-3,#1a2540)),
    color-mix(in srgb, var(--green,#22c55e) 8%, var(--navy-2,#111827)));
  border:1px solid rgba(34,197,94,.45);border-radius:12px;
  padding:10px 12px;z-index:60;
  box-shadow:0 10px 30px var(--sombra,rgba(0,0,0,.5)), 0 0 0 1px rgba(34,197,94,.08);
  opacity:0;visibility:hidden;pointer-events:none;transition:opacity .14s ease, transform .14s ease;
  text-align:left;white-space:normal;
}
/* Ya NO se revela acá con :hover/:focus — position:absolute dentro de
   #pyModalWrap (overflow:auto) se recorta contra el borde del contenedor
   cuando la fila está cerca del encabezado. Ahora es plantilla de contenido,
   siempre oculta; la capa fija #pyPopTip (más abajo) es la que se muestra,
   posicionada por _pyPopMostrar() en pago-facturas.js. */
/* colita del globo: toma el MISMO color-mix que el extremo inferior del gradiente.
   Mismo % (8%) en los dos extremos: ver la nota de #pybwarnTip sobre por qué. */
.ncpop-bubble::after{
  content:"";position:absolute;top:100%;left:50%;transform:translateX(-50%);
  border:7px solid transparent;
  border-top-color:color-mix(in srgb, var(--green,#22c55e) 8%, var(--navy-2,#111827));
  filter:drop-shadow(0 1px 0 rgba(34,197,94,.35));
}
.ncpop-title{display:block;font-size:12px;font-weight:700;color:var(--green,#22c55e)}
.ncpop-sub{display:block;font-size:10px;color:var(--text-3);margin-bottom:7px}
.ncpop-row{
  display:grid;grid-template-columns:1fr auto;gap:2px 8px;align-items:center;
  background:var(--navy-3,#1a2540);
  border:1px solid color-mix(in srgb, var(--green,#22c55e) 26%, transparent);
  border-radius:7px;padding:6px 8px;margin-bottom:5px;
}
.ncpop-doc{font-size:11px;color:var(--text);font-family:var(--mono)}
.ncpop-monto{font-size:12px;font-weight:700;color:var(--green,#22c55e);font-family:var(--mono);text-align:right}
.ncpop-fecha{grid-column:1 / -1;font-size:10px;color:var(--text-3)}
.ncpop-texto{grid-column:1 / -1;font-size:10px;color:var(--text-2);opacity:.85;margin-top:2px}
.ncpop-total{display:flex;justify-content:space-between;align-items:center;font-size:11px;color:var(--text-2);border-top:1px dashed rgba(34,197,94,.25);padding-top:6px;margin-top:2px}
.ncpop-total b{color:var(--green,#22c55e);font-family:var(--mono)}
/* Pop-up para las Notas de Débito (KS) ligadas (ícono 🧾) — mismo layout que
   el de NC pero en ÁMBAR, porque SUMAN al monto en vez de descontarlo.
 *
 * ⚠ Mismo defecto que .ncpop-bubble / .solpop-bubble: fondo hardcodeado en ámbar
 * oscuro que no se invertía en tema claro. Mismo arreglo: superficie con
 * --navy-3/--navy-2 más un tinte de --amber por color-mix, que conserva el matiz
 * ámbar y se invierte con el tema. */
.ndpop-wrap{position:relative;display:inline-block;margin-left:6px;margin-top:-5px;margin-bottom:-5px;vertical-align:middle}
.ndpop-ico{cursor:help;outline:none;font-size:15px;display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:6px;vertical-align:middle;color:var(--amber,#f59e0b);background:color-mix(in srgb, var(--amber,#f59e0b) 12%, var(--navy-3,#1a2540));border:1px solid color-mix(in srgb, var(--amber,#f59e0b) 40%, transparent);transition:background .12s,border-color .12s}
.ndpop-wrap:hover .ndpop-ico{background:color-mix(in srgb, var(--amber,#f59e0b) 18%, var(--navy-3,#1a2540));border-color:color-mix(in srgb, var(--amber,#f59e0b) 65%, transparent)}
.ndpop-bubble{
  position:absolute;left:50%;bottom:calc(100% + 10px);transform:translateX(-50%) scale(.96);
  transform-origin:bottom center;min-width:230px;max-width:300px;
  background:linear-gradient(180deg,
    color-mix(in srgb, var(--amber,#f59e0b) 8%, var(--navy-3,#1a2540)),
    color-mix(in srgb, var(--amber,#f59e0b) 8%, var(--navy-2,#111827)));
  border:1px solid rgba(245,158,11,.45);border-radius:12px;
  padding:10px 12px;z-index:60;
  box-shadow:0 10px 30px var(--sombra,rgba(0,0,0,.5)), 0 0 0 1px rgba(245,158,11,.08);
  opacity:0;visibility:hidden;pointer-events:none;transition:opacity .14s ease, transform .14s ease;
  text-align:left;white-space:normal;
}
/* Ídem .ncpop-bubble más arriba: ya no se revela acá, queda como plantilla
   y la muestra la capa fija #pyPopTip. */
.ndpop-bubble::after{
  content:"";position:absolute;top:100%;left:50%;transform:translateX(-50%);
  border:7px solid transparent;
  border-top-color:color-mix(in srgb, var(--amber,#f59e0b) 8%, var(--navy-2,#111827));
  filter:drop-shadow(0 1px 0 rgba(245,158,11,.35));
}
.ndpop-title{display:block;font-size:12px;font-weight:700;color:var(--amber,#f59e0b)}
.ndpop-sub{display:block;font-size:10px;color:var(--text-3);margin-bottom:7px}
.ndpop-row{
  display:grid;grid-template-columns:1fr auto;gap:2px 8px;align-items:center;
  background:var(--navy-3,#1a2540);
  border:1px solid color-mix(in srgb, var(--amber,#f59e0b) 26%, transparent);
  border-radius:7px;padding:6px 8px;margin-bottom:5px;
}
.ndpop-doc{font-size:11px;color:var(--text);font-family:var(--mono)}
.ndpop-monto{font-size:12px;font-weight:700;color:var(--amber,#f59e0b);font-family:var(--mono);text-align:right}
.ndpop-fecha{grid-column:1 / -1;font-size:10px;color:var(--text-3)}
.ndpop-texto{grid-column:1 / -1;font-size:10px;color:var(--text-2);opacity:.85;margin-top:2px}
.ndpop-total{display:flex;justify-content:space-between;align-items:center;font-size:11px;color:var(--text-2);border-top:1px dashed rgba(245,158,11,.25);padding-top:6px;margin-top:2px}
.ndpop-total b{color:var(--amber,#f59e0b);font-family:var(--mono)}
/* Pop-up para los ANTICIPOS (KZ) ligados — mismo layout que el de NC pero en AZUL.
 *
 * Tres colores para tres cosas, que es de lo que se trata: verde descuenta por una
 * nota de crédito, ámbar suma por una nota de débito, azul descuenta por un pago ya
 * entregado al proveedor. Un KZ comparte el rol 'NC' en el DATO —es lo que mira toda
 * la aritmética— pero no es una nota de crédito, y el globo no puede decir que lo es.
 *
 * ⚠ El acento va en la LETRA, en la LÍNEA y en un tinte MÍNIMO de la superficie; el
 *   fondo de cada renglón es --navy-3 neutro. Es el patrón con el que se arreglaron
 *   .ncpop-row y .fc-org: texto de un acento sobre un tinte del MISMO acento no gana
 *   contraste nunca, porque los dos se mueven juntos al invertir el tema.
 * ⚠ El texto usa --blue-light-txt (el tono 400, 5,04:1) y NUNCA como `background`.
 *   El fallback no es adorno: un `color` inválido se DESCARTA y el texto heredaría el
 *   del padre, que en una celda puede ser el mismo color que el fondo. */
.kzpop-wrap{position:relative;display:inline-block;margin-left:6px;margin-top:-5px;margin-bottom:-5px;vertical-align:middle}
.kzpop-ico{cursor:help;outline:none;font-size:15px;display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:6px;vertical-align:middle;color:var(--blue-light,#3b82f6);background:color-mix(in srgb, var(--blue-light,#3b82f6) 12%, var(--navy-3,#1a2540));border:1px solid color-mix(in srgb, var(--blue-light,#3b82f6) 40%, transparent);transition:background .12s,border-color .12s}
.kzpop-wrap:hover .kzpop-ico{background:color-mix(in srgb, var(--blue-light,#3b82f6) 18%, var(--navy-3,#1a2540));border-color:color-mix(in srgb, var(--blue-light,#3b82f6) 65%, transparent)}
.kzpop-bubble{
  position:absolute;left:50%;bottom:calc(100% + 10px);transform:translateX(-50%) scale(.96);
  transform-origin:bottom center;min-width:230px;max-width:300px;
  background:linear-gradient(180deg,
    color-mix(in srgb, var(--blue-light,#3b82f6) 8%, var(--navy-3,#1a2540)),
    color-mix(in srgb, var(--blue-light,#3b82f6) 8%, var(--navy-2,#111827)));
  border:1px solid color-mix(in srgb, var(--blue-light,#3b82f6) 45%, transparent);
  border-radius:12px;padding:10px 12px;z-index:60;
  box-shadow:0 10px 30px var(--sombra,rgba(0,0,0,.5)),
             0 0 0 1px color-mix(in srgb, var(--blue-light,#3b82f6) 8%, transparent);
  opacity:0;visibility:hidden;pointer-events:none;transition:opacity .14s ease, transform .14s ease;
  text-align:left;white-space:normal;
}
/* Ídem .ncpop-bubble: ya NO se revela acá. Es la plantilla de contenido que la capa
   fija copia — position:absolute se recortaba contra el borde del contenedor. */
.kzpop-bubble::after{
  content:"";position:absolute;top:100%;left:50%;transform:translateX(-50%);
  border:7px solid transparent;
  border-top-color:color-mix(in srgb, var(--blue-light,#3b82f6) 8%, var(--navy-2,#111827));
  filter:drop-shadow(0 1px 0 color-mix(in srgb, var(--blue-light,#3b82f6) 35%, transparent));
}
.kzpop-title{display:block;font-size:12px;font-weight:700;color:var(--blue-light-txt, var(--blue-light,#3b82f6))}
.kzpop-sub{display:block;font-size:10px;color:var(--text-3);margin-bottom:7px}
.kzpop-row{
  display:grid;grid-template-columns:1fr auto;gap:2px 8px;align-items:center;
  background:var(--navy-3,#1a2540);
  border:1px solid color-mix(in srgb, var(--blue-light,#3b82f6) 26%, transparent);
  border-radius:7px;padding:6px 8px;margin-bottom:5px;
}
.kzpop-doc{font-size:11px;color:var(--text);font-family:var(--mono)}
.kzpop-monto{font-size:12px;font-weight:700;color:var(--blue-light-txt, var(--blue-light,#3b82f6));font-family:var(--mono);text-align:right}
.kzpop-fecha{grid-column:1 / -1;font-size:10px;color:var(--text-3)}
.kzpop-texto{grid-column:1 / -1;font-size:10px;color:var(--text-2);opacity:.85;margin-top:2px}
.kzpop-total{display:flex;justify-content:space-between;align-items:center;font-size:11px;color:var(--text-2);border-top:1px dashed color-mix(in srgb, var(--blue-light,#3b82f6) 25%, transparent);padding-top:6px;margin-top:2px}
.kzpop-total b{color:var(--blue-light-txt, var(--blue-light,#3b82f6));font-family:var(--mono)}
/* Pop-up "globo de cómic" para el comentario de una Solicitud (ícono 💬)
 *
 * ⚠ El fondo iba HARDCODEADO en navy oscuro mientras el texto usaba `var(--text)`,
 * que sí se invierte. Resultado en tema claro: letras casi negras sobre navy
 * oscuro, con un contraste de 1,03:1 — prácticamente invisible (el mínimo es 4,5).
 * En oscuro daba 16,53:1, así que el defecto vivía solo en un tema.
 *
 * ⚠ Y no lo detectó la auditoría de contraste de las 13 vistas, por DOS razones que
 * conviene tener juntas: `backgroundColor` reporta `rgba(0,0,0,0)` sobre un
 * `linear-gradient` —el color vive en `backgroundImage`—, y además este globo solo
 * existe mientras el puntero está sobre el ícono, así que no estaba en pantalla
 * cuando se midió. La auditoría concluyó "cero textos sobre gradiente" y este era
 * uno: un caso omitido no es un caso que pasa.
 *
 * La regla: el fondo se declara con los MISMOS tokens que el texto, así los dos se
 * invierten juntos y no puede volver a divergir. */
.solpop-wrap{position:relative;display:inline-block;margin-left:6px}
.solpop-ico{cursor:help;font-size:12px;outline:none}
.solpop-bubble{
  position:absolute;left:50%;bottom:calc(100% + 10px);transform:translateX(-50%) scale(.96);
  transform-origin:bottom center;min-width:200px;max-width:300px;
  background:linear-gradient(180deg,var(--navy-3,#1a2540),var(--navy-2,#111827));
  border:1px solid rgba(37,99,235,.45);border-radius:12px;
  padding:10px 12px;z-index:60;
  /* La sombra usa el token de sombra del tema: negro al 50% sobre papel blanco se
     ve como una mancha, y es lo que pasaba al invertir solo el texto. */
  box-shadow:0 10px 30px var(--sombra,rgba(0,0,0,.5)), 0 0 0 1px rgba(37,99,235,.08);
  opacity:0;visibility:hidden;pointer-events:none;transition:opacity .14s ease, transform .14s ease;
  text-align:left;white-space:normal;
}
/* Ídem .ncpop-bubble más arriba: ya no se revela acá, queda como plantilla
   y la muestra la capa fija #pyPopTip. */
.solpop-bubble::after{
  content:"";position:absolute;top:100%;left:50%;transform:translateX(-50%);
  /* La punta toma el MISMO token que el extremo inferior del gradiente. Con el hex
     a mano, en tema claro quedaba un triángulo navy colgando de un globo blanco. */
  border:7px solid transparent;border-top-color:var(--navy-2,#111827);
  filter:drop-shadow(0 1px 0 rgba(37,99,235,.35));
}
.solpop-title{display:block;font-size:11px;font-weight:700;color:var(--blue-light-txt, var(--blue-light,#60a5fa));margin-bottom:6px}
.solpop-text{
  display:block;font-size:12px;color:var(--text,#f1f5f9);line-height:1.5;
  background:rgba(37,99,235,.10);border:1px solid rgba(37,99,235,.18);
  border-radius:7px;padding:7px 9px;font-style:italic;
}

/* ── Capa fija compartida por los pop-ups de NC / ND / Solicitud ──────────
 * Mismo defecto que el ⚠ de más arriba (#pybwarnTip) y el mismo arreglo:
 * ".ncpop-bubble"/".ndpop-bubble"/".solpop-bubble" son position:absolute
 * DENTRO de #pyModalWrap, que tiene overflow:auto para el scroll de la
 * tabla — con una fila cerca del encabezado el globo se recorta contra el
 * borde superior del contenedor (medido: 111,6px por encima). Ninguna
 * combinación de overflow-x/overflow-y lo resuelve sin romper el scroll.
 *
 * Las tres burbujas de arriba dejan de mostrarse en su lugar (por eso ya no
 * llevan la regla de :hover/:focus) y quedan como PLANTILLA de contenido,
 * siempre oculta. _pyPopMostrar() (pago-facturas.js) copia su innerHTML a
 * esta única capa fija, que toma el color de cada tipo reutilizando la
 * MISMA clase — así el fondo/borde/paleta no se duplican. Con
 * position:fixed a nivel de body, ningún overflow la recorta. Una sola
 * función posiciona los tres. */
#pyPopTip{
  position:fixed;left:0;top:0;right:auto;bottom:auto;z-index:99999;
  transform:none;opacity:0;visibility:hidden;pointer-events:none;
  transition:opacity .14s ease;
}
#pyPopTip.on{ opacity:1;visibility:visible; }
/* La flecha sigue al ícono aunque el globo se haya corrido por el clamp
   contra el borde de la pantalla (mismo ajuste que la de #pybwarnTip). */
#pyPopTip::after{ left:var(--pop-arrow-left, 50%); }

/* ── Globo ACOTADO ─────────────────────────────────────────────────────────
   Cuando el contenido no cabe entero NI arriba NI abajo del ícono —una factura
   en la mitad de la pantalla con muchas notas de crédito—, el JS le pone un
   `max-height` igual al espacio disponible y esta clase. Sin ella el navegador
   lo cortaba por el borde inferior y la mitad del detalle desaparecía sin aviso.

   ⚠ `pointer-events:auto` es obligatorio acá: el globo normal los tiene
   desactivados para no interferir con la tabla que hay debajo, pero uno que se
   lee desplazándolo necesita recibir la rueda del mouse. Sin esto el scroll
   pasaría a la tabla de atrás y el globo quedaría igual de ilegible que antes,
   solo que por otro motivo. */
#pyPopTip.py-pop-acotado{
  overflow-y:auto; overscroll-behavior:contain; pointer-events:auto;
  /* Un poco más de aire a la derecha, para que la barra no pise el texto. */
  padding-right:6px;
}

/* ── La barra de scroll DEL GLOBO ──────────────────────────────────────────
   La app tiene barras de 11px en todas partes (styles.css), y eso está bien en una
   tabla a pantalla completa. Dentro de un globo de 280px es un cuarto de su ancho: se
   lee como parte del contenido en vez de como un control, que es lo que el usuario
   reportó.

   Acá va una barra fina, sin pista visible, con el pulgar del color del acento de cada
   tipo — el mismo verde/ámbar/azul que ya usan su borde y su título, así que la barra
   pertenece al globo en vez de parecer pegada encima.

   ⚠ `--pop-acento` lo define cada tipo más abajo. Si un tipo nuevo no lo define, el
   fallback lo deja en el gris de texto secundario: sigue siendo usable, no desaparece.
   Un `var()` sin fallback en `background-color` haría que la declaración se descarte y
   el pulgar quedaría del color por defecto del navegador, que no es de la app. */
#pyPopTip.py-pop-acotado{ scrollbar-width:thin; scrollbar-color:var(--pop-acento, var(--text-3)) transparent; }
#pyPopTip.py-pop-acotado::-webkit-scrollbar{ width:7px; }
#pyPopTip.py-pop-acotado::-webkit-scrollbar-track{ background:transparent; }
#pyPopTip.py-pop-acotado::-webkit-scrollbar-thumb{
  background-color:var(--pop-acento, var(--text-3)); border-radius:7px;
  /* El borde transparente con `background-clip` afina el pulgar sin afinar el área
     que se puede agarrar con el mouse: un pulgar de 3px sería lindo e inagarrable. */
  border:2px solid transparent; background-clip:padding-box;
}
#pyPopTip.py-pop-acotado::-webkit-scrollbar-thumb:hover{
  background-color:var(--pop-acento, var(--text-2)); border-width:1px;
}
/* El acento de cada tipo, tomado del color que ya usan su borde y su título. */
#pyPopTip.ncpop-bubble  { --pop-acento: var(--green); }
#pyPopTip.ndpop-bubble  { --pop-acento: var(--amber); }
#pyPopTip.kzpop-bubble  { --pop-acento: var(--blue-light); }
#pyPopTip.solpop-bubble { --pop-acento: var(--blue-light); }
/* Sin flecha: el globo acotado no está pegado al ícono, así que la punta
   señalaría un lugar cualquiera del borde. */
#pyPopTip.py-pop-acotado::after{ display:none; }
/* Modo "arriba": sin espacio arriba del ícono, el globo se dibuja DEBAJO y
   la flecha se voltea al borde superior — mismo par abajo/arriba que
   #pybwarnTip; el color de la punta cambia por tipo, así que va uno por
   cada uno. */
#pyPopTip.arriba.ncpop-bubble::after{
  top:auto;bottom:100%;border-top-color:transparent;
  border-bottom-color:color-mix(in srgb, var(--green,#22c55e) 8%, var(--navy-3,#1a2540));
}
#pyPopTip.arriba.ndpop-bubble::after{
  top:auto;bottom:100%;border-top-color:transparent;
  border-bottom-color:color-mix(in srgb, var(--amber,#f59e0b) 8%, var(--navy-3,#1a2540));
}
#pyPopTip.arriba.kzpop-bubble::after{
  top:auto;bottom:100%;border-top-color:transparent;
  border-bottom-color:color-mix(in srgb, var(--blue-light,#3b82f6) 8%, var(--navy-3,#1a2540));
}
#pyPopTip.arriba.solpop-bubble::after{
  top:auto;bottom:100%;border-top-color:transparent;
  border-bottom-color:var(--navy-3,#1a2540);
}

/* ── Encabezado sticky del modal ─────────────────────────────────── */
/* Encabezado sticky del modal: el sticky va en los TH (en thead es
   inconsistente en Chrome) y con fondo OPACO — sin esto, las filas se
   transparentaban bajo el encabezado al scrollear y los números de la
   columna # se mezclaban con los del header. */
#pyModalWrap thead th {
  position: sticky; top: 0; z-index: 3;
  background: var(--navy-3);
  box-shadow: 0 1px 0 var(--border-2);
}

/* ── cf-body-2col ────────────────────────────────────────────────── */
@media (max-width: 720px) {
  .cf-body-2col { grid-template-columns: 1fr !important; }
}

/* ── Semana cerrada (solo lectura) en "Otros Pagos (sem.)" ─────────────────────
   Mismo lenguaje visual que el chip "Mes cerrado" de Deuda Financiera
   (.fin-chip.locked): candado ambar sobre fondo de aviso. Se define acá y no se
   reusa esa clase para no acoplar la hoja de un apartado a la de otro. */
.gastos-chip{display:inline-flex;align-items:center;gap:6px;padding:3px 9px;border-radius:999px;font-size:11.5px;font-weight:600}
.gastos-chip.cerrada{background:var(--mx-avi-bg,#2a1d12);color:var(--mx-avi,#f5b94d);border:1px solid var(--mx-avi-linea,#4a361f)}
/* Un control deshabilitado tiene que VERSE deshabilitado: .gasto-del se revela con
   el hover de la fila, y sin esto el candado quedaba con la cruz igual de viva. */
.gasto-del:disabled{cursor:not-allowed}
.gasto-row:hover .gasto-del:disabled{opacity:.4}

/* El botón "Confirmar pagos" cuando la prenómina de la semana ya se envió.
   ⚠ NO se usa `pointer-events: none` ni el atributo `disabled`: los dos matan el clic, y
   el clic es lo que muestra el pop-up que explica el bloqueo. Un botón gris sin
   explicación es exactamente el problema que este cambio viene a resolver. */
.btn.py-bloqueado {
  opacity: .55;
  cursor: not-allowed;
}
