:root{
    --bg-dark-1:#05070f;
    --bg-dark-2:#0a1830;
    --bg-dark-3:#081326;
    --ink:#12172a;
    --muted:#384152;
    --icon:#454f60;
    --line:#8a92a4;
    --accent:#ff2f7e;
    /* El mismo rosa, oscurecido para cuando hace de TEXTO. El de arriba
       da 3.52:1 contra el blanco —suficiente para un relleno o un borde,
       no para leer— y este da 7.53:1. Son dos usos distintos del mismo
       color de marca, y por eso son dos variables y no una (1-sep-2026). */
    --accent-txt:#ab0045;
    --btn-bg:#0c1424;
    --shadow-btn:0 10px 24px rgba(12,20,36,.22)
}

/* =====================================================================
   REGLA DE LEGIBILIDAD  ·  31-ago-2026
   =====================================================================
   Ningún texto que el funcionario necesite LEER baja de 14px, el gris
   claro queda reservado para lo que de verdad no importa, y nada
   informativo va en cursiva.

   Por qué existe esta regla. La costumbre de pintar el texto secundario
   más chico y más claro sirve cuando ese texto es decorativo. En un
   portal presupuestal casi nada lo es: el rótulo de un campo, el
   encabezado de una columna, el estado de una nota o el aviso de que un
   borrador está por caducar son datos, y achicarlos degrada justo lo
   que hay que leer. La convención está además calibrada para pantallas
   nuevas y vista joven; esto lo usa gente ocho horas al día.

   El 31-ago-2026 se subieron 36 reglas de una vez (rótulos de campo,
   encabezados de tabla, menú lateral, estados, paginación, avisos de
   login y recuperación). Se midió antes de hacerlo: el modal de
   afectación presupuestal —el más denso del sistema— mide EXACTAMENTE
   lo mismo con los rótulos en 14.5px que en 13.5px. La densidad no
   costaba legibilidad; solo la estaba regalando.

   Quedan a propósito por debajo de 14px, y son las únicas excepciones:
   iconos (.portal-modulo-flecha, .badge-anot i), que no son texto, y
   los sobretítulos en versalitas (.login-eyebrow, .bienv-eyebrow), que
   nombran la pantalla en la que uno ya está.
   ===================================================================== */

*{
    box-sizing:border-box
}
html{
    scroll-behavior:smooth
}
body{
    margin:0;
    min-height:100vh;
    color:var(--ink);
    background:#fff;
    font-family:'Inter',ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;
    -webkit-font-smoothing:antialiased
}

/* ============================================================
   COMPONENTES BASE REUTILIZABLES
   Un mismo campo, etiqueta, tarjeta o botón debe verse igual en
   cualquier formulario del sistema (login, bienvenida, recuperación
   y los que se vayan agregando); lo único que cambia entre usos es
   el id/name de cada elemento. Los formularios nuevos se arman con
   estas clases en vez de crear una clase exclusiva por campo/sección.
   ============================================================ */

/* Campo de texto/select. Sin espacio de ícono por defecto — ver
   .campo--icono más abajo para el caso contrario (login). */
.campo{
    width:100%;
    height:46px;
    padding:0 14px;
    border:1px solid var(--line);
    border-radius:10px;
    outline:none;
    background:#fff;
    font:inherit;
    font-size:16px;
    font-weight:700;
    color:var(--ink);
    appearance:none;
    transition:border-color .2s,box-shadow .2s
}
.campo::placeholder{
    color:var(--muted);
    opacity:1
}
.campo:focus{
    border-color:var(--accent);
    box-shadow:0 0 0 3px rgba(255,47,126,.14)
}
/* CAMPO BLOQUEADO — el gris, más claro (usuario, 1-sep-2026).
   =====================================================================
   Dos cambios, y el que de verdad hace resaltar el contenido es el
   segundo:

   1) EL FONDO baja de #f3f4f6 / #eef0f4 a #f5f6f9, que ya es un color
      del proyecto (el hover del botón secundario). Sigue distinguiéndose
      del campo editable —el borde y el cursor también lo dicen— pero deja
      pasar más el dato.

   2) EL TEXTO sube de #4b5563 a --muted (#384152), de 6.87:1 a 9.50:1
      contra ese fondo. Y esto no es solo gusto: 6.87 era lo ÚNICO que
      quedaba por debajo del mínimo de 7:1 que se fijó el 31-ago-2026 para
      todo el sistema. Un campo bloqueado se lee tanto como uno editable;
      lo que cambia es que no se puede escribir en él, no que importe
      menos — y en consulta, que es como se usa la mitad del tiempo, TODO
      el formulario está bloqueado. */
.campo:disabled{
    background:#f5f6f9;
    color:var(--muted);
    cursor:not-allowed
}
/* Campo de solo lectura (inputs en modo consulta): a diferencia de
   :disabled, el texto se ve exactamente igual de nítido que uno editable,
   solo cambia el fondo para dejar claro que no se puede escribir ahí. */
.campo[readonly]{
    background:#f5f6f9;
    cursor:default
}
/* Mismo tratamiento para <select>, que no admite el atributo readonly:
   se bloquea con pointer-events en vez de disabled, para no perder
   contraste de texto. */
.campo--bloqueado{
    pointer-events:none;
    background:#f5f6f9
}
/* .campo ya no reserva espacio de ícono por defecto (así queda sin
   modificador en el 99% de los campos del proyecto); .campo--icono es la
   excepción para los pocos campos que sí llevan un ícono a la izquierda
   (login). */
.campo--icono{
    padding-left:40px
}

/* Campo de búsqueda contra catálogo (input readonly + botón de lupa que
   abre f90sel/catmod.php — ver ejemplo de HTML en ese archivo): el input
   de solo lectura y el botón de búsqueda quedan pegados, y el botón se
   dimensiona igual de alto que el campo para que la línea se vea pareja. */
.campo-busqueda{
    display:flex;
    gap:8px;
    align-items:stretch
}
.campo-busqueda .campo{
    flex:1;
    min-width:0
}
.btn-ico--buscar{
    width:46px;
    height:46px;
    flex-shrink:0;
    border-radius:10px;
    /* MEDIDO, no ajustado a ojo (1-sep-2026). Estos tres valores daban
       1.51:1 el borde, 1.15:1 el fondo y 3.07:1 el ícono contra el blanco
       de la página. Un borde por debajo de 3:1 no se ve como borde: se ve
       como nada, y el botón solo aparecía al pasarle el mouse porque el
       hover sí tenía relleno sólido. Ahora el borde va en 4.86:1 y el
       ícono en 5.39:1 sobre su propio fondo. */
    border:1.5px solid #e0005c;
    background:#ffd9e7;
    color:#a30048;
    display:inline-flex;
    align-items:center;
    justify-content:center;
    cursor:pointer;
    font-size:18px;
    transition:background .15s,color .15s,border-color .15s
}
.btn-ico--buscar:hover{
    background:var(--accent);
    color:#fff;
    border-color:var(--accent)
}

/* La ALCANCÍA: buscar en los saldos ya registrados en el libro, en vez de
   armar la clasificación a mano en el catálogo.

   Va en verde y no en el rosa de las demás lupas porque no es otra lupa
   más: son DOS CAMINOS DISTINTOS para llenar el mismo campo, uno al lado
   del otro y con el mismo tamaño. Pintadas iguales, el funcionario tiene
   que acordarse de cuál es cuál cada vez —o probar—, y el de saldos es
   justo el que conviene: trae la clasificación completa de una línea que
   ya existe, con lo cual la nueva sale idéntica a la que ajusta. Armarla
   a mano es el camino largo y el que se presta a que dos líneas que
   deberían compartir saldo terminen en llaves distintas por un
   clasificador puesto diferente.

   El verde es el mismo del proyecto para "correcto/disponible" (#146138),
   y la medida no cambia: 46px, igual que las otras. El ancho del campo de
   rubro está calculado contando estos dos botones (calc(33ch + 120px) en
   ppform.php), así que tocarle el tamaño descuadraría la línea. */
.btn-ico--saldos{
    /* 1.64:1 el borde. Mismo caso que la lupa; ahora 5.39:1 y 6.64:1. */
    border-color:#127a46;
    background:#d5efe0;
    color:#0d5c34
}
.btn-ico--saldos:hover{
    background:#146138;
    color:#fff;
    border-color:#146138
}

/* Etiqueta de campo. --fuerte es la variante un poco más grande y
   oscura usada en tarjetas (bienvenida, recuperación). */
.campo-label{
    display:block;
    margin-bottom:7px;
    font-size:14.5px;
    font-weight:600;
    color:#1f2937
}
.campo-label--fuerte{
    font-size:14.5px;
    font-weight:700;
    color:#1f2937
}

/* Contenedor genérico para agrupar campos en fila. Cada campo controla su
   propio ancho con style="width:XX%" directo en su <div class="campo-full">
   (igual que en el proyecto original: width:43%, width:17%, etc., junto al
   id/name del campo) — no hay grilla ni número de columnas que traducir:
   los campos simplemente se acomodan uno tras otro en el orden en que
   aparecen en el HTML/PHP, y saltan de línea solos cuando no caben. Mover
   un campo de sitio es mover su bloque de código; el diseño sigue el orden
   del código siempre. .campo-full sin ancho propio ocupa toda la fila. */
.form-grid{
    display:flex;
    flex-wrap:wrap;
    gap:14px;
    margin-bottom:6px
}
.form-grid:last-child{margin-bottom:0}
.form-grid .campo-full{width:100%}
/* Salto de línea explícito dentro de un .form-grid: obliga a que el
   siguiente campo empiece en una fila nueva aunque quepa al lado del
   anterior. Hace falta porque .form-grid es flex-wrap y los campos se
   acomodan solos: un <div> vacío NO sirve (sin ancho, el flex lo encoge a
   cero y no rompe la línea); lo que rompe es ocupar el 100% del ancho. */
.form-salto{
    flex-basis:100%;
    width:100%;
    height:0;
    margin:0;
    padding:0
}

/* Variante COMPACTA del formulario, para los comprobantes transaccionales:
   campos más bajos y menos aire entre filas. No se cambian los valores
   base de .campo/.campo-label porque los módulos de parámetros —que ya
   están validados— dependen de ellos; aquí solo se ajusta lo que hay
   dentro de un .form-grid--compacto. El espacio que se ahorra arriba es el
   que gana la tabla de afectaciones, que es la que crece. */
.form-grid--compacto{gap:10px;margin-bottom:2px}
.form-grid--compacto .campo{
    height:38px;
    font-size:14.5px;
    /* Borde más oscuro que el --line general (#8a92a4): en un comprobante
       hay muchos campos juntos y con el borde claro se pierde dónde empieza
       y termina cada uno. Se limita a esta variante para no cambiar el
       aspecto de los módulos de parámetros, ya validados. */
    border-color:#6f7889
}
.form-grid--compacto .campo:focus{border-color:var(--accent)}
.form-grid--compacto .campo--calculado{border-color:#8a92a4}
.form-grid--compacto select.campo{height:38px}
.form-grid--compacto textarea.campo{height:auto;padding-top:8px;padding-bottom:8px}
.form-grid--compacto .campo-label{margin-bottom:4px;font-size:14px}
.form-grid--compacto .seccion-tit{padding-top:10px;margin-top:2px}
.form-grid--compacto .btn-ico--buscar{width:38px;height:38px}

/* Variante DENSA, para los formularios de parámetros que tienen muchos
   campos y se estaban volviendo un rollo vertical (el de Rubros llegaba a
   once filas más tres títulos de sección).

   La diferencia con --compacto es a propósito y es el punto entero de que
   existan las dos: --compacto BAJA la letra y la altura del campo (16px/46px
   pasan a 14.5px/38px) porque en un comprobante importa ver muchas líneas a
   la vez. Aquí NO se toca ni una cosa ni la otra —el campo sigue en 46px, la
   letra en 16px y en peso 700— y la altura se recorta solo de lo que no es
   contenido: el aire entre filas, el respiro bajo cada rótulo y el margen de
   los títulos de sección.

   El resto de la altura se gana en el HTML, repartiendo los anchos para que
   quepan más campos por fila. Eso vale más que cualquier CSS: cada fila que
   desaparece son ~80px, y ninguna letra se encogió para conseguirlo. */
.form-grid--denso{gap:9px;margin-bottom:2px}
.form-grid--denso .campo-label{margin-bottom:4px}
.form-grid--denso .seccion-tit{padding-top:8px;margin-top:2px}
.form-grid--denso textarea.campo{padding-top:8px;padding-bottom:8px}
/* Piso de ancho: con filas de cuatro y cinco campos, en una pantalla
   angosta un 13.5% se vuelve una casilla de dos centímetros. El min-width
   hace que en vez de encogerse salten de línea, que es lo que se quiere.

   OJO CON EL EFECTO DE LADO, que costó una tarde encontrarlo: en el ancho
   normal del modal este piso son ~12.9%, y todo porcentaje que dé menos
   SE IGNORA. Se escribe 6%, se escribe 8%, y los dos campos salen del
   mismo tamaño. Quien esté maquetando el formulario no tiene cómo
   saberlo: lo que escribió no es lo que ve, y no hay nada en pantalla que
   lo diga. Para eso está el interruptor de abajo. */
.form-grid--denso .campo-full{min-width:118px}

/* ---------------------------------------------------------------
   ANCHOS EXACTOS — el interruptor para maquetar sin sorpresas
   ---------------------------------------------------------------
   Se le agrega al .form-grid del formulario que quiera control total:

       <div class="form-grid form-grid--denso form-grid--exacto">

   Con eso, el ancho de cada campo es EXACTAMENTE el que dice su
   style="width:XX%" y nada de esta hoja lo pisa. Es opt-in y por
   formulario: el que no lo lleve sigue igual que siempre, así que
   ponerlo o quitarlo no puede dañar ningún otro formulario.

   LO QUE SE PIERDE, dicho claro: sin el piso, en una pantalla angosta un
   campo del 7% se encoge de verdad en vez de saltar de línea. Si algún
   campo suelto necesita un mínimo, se le pone en el propio formulario y
   a la vista — style="width:7%;min-width:60px" —, que gana sobre esta
   regla por ser estilo en línea.

   DECISIÓN DEL USUARIO, 02-sep-2026: el control de anchos y posiciones
   vive en el formulario, no repartido entre el formulario y esta hoja.
   Aquí quedan el aspecto y el comportamiento; allá, la maqueta. */
.form-grid--exacto .campo-full{min-width:0}

/* Campo con el rótulo A LA IZQUIERDA, todo en una sola línea (Tercero,
   Acto administrativo). Ahorra una fila por campo frente al rótulo encima. */
.campo-linea{
    display:flex;
    align-items:center;
    gap:10px;
    flex-wrap:wrap
}
.campo-linea > .campo-label{
    margin:0;
    flex:none;
    white-space:nowrap
}

/* Marco de la tabla de afectaciones dentro del modal de un comprobante:
   encabezado de una línea (título + totales + botón) y la tabla debajo,
   con alto máximo propio para que el modal no crezca sin control. */
.afec-marco{
    border:1px solid var(--line);
    border-radius:12px;
    overflow:hidden;
    background:#fbfcfe
}
.afec-encab{
    display:flex;
    align-items:center;
    gap:12px;
    flex-wrap:wrap;
    padding:8px 12px;
    border-bottom:1px solid var(--line);
    background:#f3f5f9
}
.afec-titulo{
    display:flex;
    align-items:center;
    gap:8px;
    flex:1;
    min-width:220px;
    font-size:14px;
    font-weight:800;
    letter-spacing:.05em;
    color:var(--ink)
}
.afec-titulo i{font-size:15px;color:var(--accent-txt)}
.afec-totales{
    display:flex;
    align-items:center;
    gap:8px;
    flex-wrap:wrap
}
.afec-rotulo{
    font-size:14.5px;
    font-weight:700;
    color:#2f3746;
    white-space:nowrap
}
/* Totales del marco de afectaciones. El ancho NO es fijo: lo ajusta
   ajustarAnchoTotal() en el JS del módulo según lo que haya escrito, porque
   un valor formateado puede ir de "0,00" a "9.999.999.999.999.999,99" —
   hasta 24 caracteres con los separadores de miles— y un ancho fijo o
   recorta el número o deja un hueco enorme la mayor parte del tiempo.
   El min-width evita que se encoja hasta verse ridículo con valores
   pequeños, y tabular-nums hace que todos los dígitos midan igual, que es
   lo que vuelve fiable el cálculo en unidades "ch". Si al crecer ya no cabe
   el botón al lado, .afec-encab tiene flex-wrap y baja de línea solo. */
.campo.afec-total{
    width:auto;
    /* El mínimo se dimensiona para una cifra REALISTA de presupuesto
       municipal —"999.999.999.999,99", 18 caracteres— y no para "0,00".
       Si no, el campo se ve diminuto todo el tiempo, que es justo lo que
       pasa mientras la tabla de afectaciones todavía no existe y los dos
       totales están en cero. Por encima de ese mínimo sigue creciendo solo
       hasta los 24 caracteres del tope de decimal(18,2). */
    min-width:calc(18ch + 24px);
    height:32px;
    padding:0 10px;
    font-size:15px;
    text-align:right;
    font-variant-numeric:tabular-nums
}
/* Descuadre entre los dos totales. Lo enciende ppscri.js en los tipos
   que deben cuadrar al peso (inicial, adicion, reduccion, reserva, cxp y
   traslado) y solo cuando ya hay lineas: un comprobante a medio armar no
   esta descuadrado, esta incompleto.
   Va con borde y color de texto, no con fondo rojo: el fondo compite con
   la cifra, que es lo que hay que leer. */
.campo.afec-total--descuadre{
    border-color:#dc2626;
    color:#9b1717;
    font-weight:700;
    box-shadow:0 0 0 2px rgba(220,38,38,.12)
}

/* Alto de la tabla de afectaciones.
   clamp() en vez de un número fijo: en una pantalla grande se aprovecha
   el alto disponible, y en un portátil pequeño no empuja los botones del
   modal fuera de la vista. El piso son los 230px que tenía antes. */
.afec-tabla{max-height:clamp(230px, 38vh, 430px);overflow-y:auto}
.afec-tabla .tabla thead th{position:sticky;top:0;z-index:1}

/* Filas más juntas SOLO en esta tabla, y sin tocar el tamaño de la letra.
   El relleno de 13px arriba y abajo es lo correcto para un listado que se
   navega; aquí se está revisando un detalle contra otro y lo que importa
   es cuántas líneas se ven de una vez. Bajarlo a 7px quita 12px por fila
   —de ~44px a ~32px— sin que el texto cambie de tamaño ni se junte: eso,
   con el alto de arriba, pasa de unas 5 filas visibles a cerca de 12.
   Va acotado a .afec-tabla para no alterar ningún otro listado. */
.afec-tabla .tabla thead th,
.afec-tabla .tabla tbody td{padding:7px 14px}

/* Los botones de cada fila mandan la altura si se quedan en 32px: con las
   filas más juntas hay que encogerlos a la par, o el relleno de arriba no
   sirve de nada. El área de clic sigue siendo cómoda. */
.afec-tabla .tabla tbody .btn-ico{width:28px;height:28px;font-size:14px}
.afec-vacio{padding:18px 12px;font-size:14.5px}

/* Aviso de caducidad del borrador: hasta cuándo viven las afectaciones
   sin confirmar. Va al pie del marco, en tono de nota — es información,
   no un error, y la mayor parte del tiempo el plazo está lejos.

   --urgente lo enciende ppscri.js en las últimas dos horas, y solo
   entonces: un aviso que grita desde el primer día deja de leerse, y
   entonces tampoco sirve el día que sí importa. */
.afec-caduca{
    margin:0;
    padding:9px 14px;
    border-top:1px solid var(--line);
    background:#f4f6fa;
    font-size:14.5px;
    font-weight:600;
    line-height:1.45;
    color:#4b5563
}
.afec-caduca i{margin-right:6px}
.afec-caduca strong{font-weight:800;color:#1f2937}
.afec-caduca--urgente{
    background:#fdeaea;
    border-top-color:#f3bcbc;
    color:#9b1c1c
}
.afec-caduca--urgente strong{color:#9b1c1c}

/* Tarjeta contenedora: bloque con fondo gris claro y borde suave
   para agrupar campos o información dentro de un modal/formulario.
   --prosa es la variante para bloques de texto largo (términos y
   condiciones), con tipografía e interlineado propios. */
.tarjeta{
    border:1px solid var(--line);
    border-radius:12px;
    background:#f9fafb;
    padding:20px 22px;
    margin-bottom:16px;
    transition:opacity .25s,background .25s
}
.tarjeta:last-child{margin-bottom:0}
.tarjeta--prosa{
    font-size:14.5px;
    font-weight:500;
    line-height:1.62;
    color:#1f2937
}
.tarjeta--prosa p{margin:0 0 12px}
.tarjeta--prosa p:last-child{margin-bottom:0}
.tarjeta--prosa strong{color:var(--ink);font-weight:700}

/* Botón base: variante primaria oscura, tamaño de pie de modal.
   --ancho = 100% de ancho (como "Ingresar", con efecto al pulsar);
   --chico = botón en línea junto a un campo (como "Verificar
   código"); --secundario = borde, sin relleno (como "Cancelar");
   --texto = tipo enlace, sin fondo (como "Reenviar código"). */
.btn{
    height:48px;
    padding:0 24px;
    border:0;
    border-radius:10px;
    font:inherit;
    font-size:15px;
    font-weight:600;
    color:#fff;
    background:var(--btn-bg);
    box-shadow:var(--shadow-btn);
    cursor:pointer;
    transition:filter .2s,background .2s
}
.btn:hover:not(:disabled){filter:brightness(1.12)}
.btn:disabled{opacity:.55;cursor:not-allowed}
.btn--ancho{
    width:100%;
    margin-top:6px;
    font-size:15px;
    transition:filter .2s,transform .2s
}
.btn--ancho:active:not(:disabled){transform:translateY(1px)}
.btn--chico{height:40px;padding:0 18px;font-size:14px;font-weight:700;border-radius:9px}
.btn--secundario{
    background:transparent;
    color:#1f2937;
    /* var(--line) es #8a92a4: 1.25:1 contra el blanco. Sirve como línea
       divisoria, no como contorno de un botón — con ella, "Cancelar" era
       un texto flotando. */
    border:1.5px solid #5a6577;
    box-shadow:none
}
.btn--secundario:hover:not(:disabled){background:#f5f6f9;filter:none}
.btn--editar{
    background:var(--accent);
    color:#fff;
    border:0;
    box-shadow:0 8px 18px rgba(255,47,126,.32)
}
.btn--editar i{color:#fff}
.btn--editar:hover:not(:disabled){filter:brightness(1.1)}
.btn--cerrar{
    background:var(--icon);
    color:#fff;
    border:0;
    box-shadow:0 6px 14px rgba(69,79,96,.28)
}
.btn--cerrar:hover:not(:disabled){filter:brightness(1.15)}
.btn--exportar{
    background:#1e7a45;
    color:#fff;
    border:0;
    box-shadow:0 6px 14px rgba(30,122,69,.28)
}
.btn--exportar:hover:not(:disabled){filter:brightness(1.12)}
.btn--certi{
    background:#1d5fd6;
    color:#fff;
    border:0;
    box-shadow:0 6px 14px rgba(29,95,214,.30)
}
.btn--certi i{color:#fff}
.btn--certi:hover:not(:disabled){filter:brightness(1.12)}
.btn--conciliar{
    background:#6d28d9;
    color:#fff;
    border:0;
    box-shadow:0 6px 14px rgba(109,40,217,.30)
}
.btn--conciliar i{color:#fff}
.btn--conciliar:hover:not(:disabled){filter:brightness(1.12)}
/* Comprobante en PDF. Ámbar oscuro: es el único color de la paleta que no
   choca con sus vecinos en el pie del modal —Cerrar (gris), Editar (rosa
   del acento) y Guardar (azul muy oscuro)— y evita el rojo, que en esa
   fila se leería como una acción destructiva. */
.btn--comprobante{
    background:#b45309;
    color:#fff;
    border:0;
    box-shadow:0 6px 14px rgba(180,83,9,.30)
}
.btn--comprobante i{color:#fff}
.btn--comprobante:hover:not(:disabled){filter:brightness(1.12)}

.btn--texto{
    height:auto;
    padding:0;
    background:none;
    color:var(--accent-txt);
    box-shadow:none;
    font-size:14.5px;
    font-weight:600
}
.btn--texto:hover:not(:disabled){filter:none}
.btn--texto:disabled{opacity:.5}

.login-shell{
    display:grid;
    grid-template-columns:minmax(0,1.05fr) minmax(0,1fr);
    min-height:100vh;
    width:100%
}

/* Panel izquierdo: institucional */
.login-visual{
    position:relative;
    overflow:hidden;
    display:flex;
    flex-direction:column;
    align-items:center;
    justify-content:center;
    gap:44px;
    padding:56px 64px;
    text-align:center;
    background:linear-gradient(165deg,var(--bg-dark-1) 0%,var(--bg-dark-2) 55%,var(--bg-dark-3) 100%)
}
.login-visual::before{
    content:"";
    position:absolute;
    inset:0;
    background-image:radial-gradient(rgba(255,255,255,.07) 1px,transparent 1px);
    background-size:28px 28px;
    opacity:.5
}
.login-visual::after{
    content:"";
    position:absolute;
    top:-140px;
    right:-120px;
    width:480px;
    height:480px;
    border-radius:50%;
    background:radial-gradient(closest-side,rgba(255,47,126,.20),rgba(107,63,245,.10) 55%,transparent 75%)
}
.login-logo-dark{
    position:relative;
    display:block;
    width:180px;
    height:auto
}
.login-logo-light{
    display:block;
    width:160px;
    height:auto;
    margin:0 0 26px
}
.login-body{
    position:relative;
    max-width:600px
}
.login-eyebrow{
    display:flex;
    align-items:center;
    justify-content:center;
    gap:8px;
    margin:0 0 18px
}
.login-eyebrow .dot{
    width:6px;
    height:6px;
    border-radius:50%;
    background:var(--accent);
    display:inline-block
}
.login-eyebrow span{
    font-size:14px;
    font-weight:700;
    letter-spacing:.16em;
    text-transform:uppercase;
    color:rgba(255,255,255,.75)
}
.login-title{
    margin:0;
    font-family:'Space Grotesk','Inter',sans-serif;
    font-weight:600;
    font-size:clamp(28px,2.6vw,38px);
    line-height:1.16;
    letter-spacing:-.01em;
    color:#f6f8ff
}
.login-lead{
    margin:16px 0 0;
    max-width:600px;
    font-size:15.5px;
    line-height:1.65;
    color:rgba(230,235,250,.80)
}
.login-trend{
    position:relative;
    margin-top:32px;
    width:100%;
    max-width:600px;
    height:150px
}
.login-chips{
    display:flex;
    flex-wrap:wrap;
    justify-content:center;
    gap:10px;
    margin-top:24px
}
.login-chip{
    display:inline-flex;
    align-items:center;
    gap:7px;
    padding:8px 14px;
    border-radius:999px;
    background:rgba(255,255,255,.06);
    border:1px solid rgba(255,255,255,.14);
    font-size:14px;
    font-weight:500;
    color:rgba(255,255,255,.92)
}
.login-chip .dot{
    width:5px;
    height:5px;
    border-radius:50%;
    background:var(--accent)
}

/* Panel derecho: formulario */
.login-form{
    display:flex;
    align-items:center;
    justify-content:center;
    padding:48px 40px;
    background:#f8f9fb
}
.login-card{
    width:100%;
    max-width:420px;
    background:#fff;
    border:1px solid var(--line);
    border-radius:20px;
    padding:40px 36px 34px;
    box-shadow:0 24px 48px -14px rgba(15,23,42,.14)
}
.login-heading{
    margin:0;
    font-family:'Space Grotesk','Inter',sans-serif;
    font-weight:600;
    font-size:22px;
    color:var(--ink)
}
.login-sub{
    margin:8px 0 26px;
    font-size:14.5px;
    color:var(--muted)
}
.login-fields{
    display:flex;
    flex-direction:column;
    gap:16px
}
.login-input-wrap{
    position:relative
}
.login-icon{
    position:absolute;
    left:13px;
    top:50%;
    transform:translateY(-50%);
    color:var(--icon);
    display:flex;
    align-items:center;
    font-size:15px;
    line-height:1;
    pointer-events:none
}
.login-footnote i{
    font-size:14px
}
.login-footnote{
    display:flex;
    align-items:center;
    justify-content:center;
    gap:6px;
    margin-top:4px;
    color:#4b5563;
    font-size:14.5px
}
.error{
    margin-top:18px;
    padding:12px;
    color:#a01f1f;
    background:#fff0f0;
    border-radius:10px;
    border:1px solid #9e2b1f;
    font-size:.88rem
}

@media(max-width:960px){
    .login-shell{
        grid-template-columns:1fr;
        min-height:auto
    }
    .login-visual{
        gap:32px;
        padding:48px 28px 40px
    }
    .login-trend{ height:120px }
    .login-form{ padding:40px 22px 56px }
}

/* #modalBienvenidaFondo (indini.php) solo existe en el DOM cuando debe
   mostrarse, así que se ve siempre visible en cuanto PHP lo incluye. Los
   modales reutilizables con clase .modal-fondo (como el de recuperación)
   pueden quedar incluidos en el DOM ya cerrados, así que empiezan ocultos
   y una clase .abierto (agregada por JS) los muestra. */
#modalBienvenidaFondo,
.modal-fondo{
    position:fixed;
    inset:0;
    z-index:9999;
    align-items:center;
    justify-content:center;
    padding:20px;
    background:rgba(5,7,15,.72)
}
#modalBienvenidaFondo{ display:flex }
.modal-fondo{ display:none }
.modal-fondo.abierto{ display:flex }
#modalBienvenida,
.modal-caja{
    position:relative;
    width:100%;
    max-width:900px;
    max-height:92vh;
    overflow:hidden;
    display:flex;
    flex-direction:column;
    background:#fff;
    border-radius:20px;
    box-shadow:0 30px 70px rgba(8,12,24,.4)
}
.modal-caja--angosta{ max-width:560px }
/* Un 10% más ancho que los 900px estándar. Para los modales de parámetros
   que tienen muchos campos y, aun repartidos por fila, quedaban altos: los
   90px extra son casi un campo más por fila y no rompen la proporción del
   modal (a 1350px, el ancho de los comprobantes, un formulario de columna
   única se ve desbalanceado). Decisión del usuario, 30-ago-2026. */
.modal-caja--media{ max-width:990px }
/* Modales de TRANSACCIONES (f00npt y los módulos de Presupuesto/Tesorería/
   Contabilidad que vengan): ~50% más anchos que los 900px de los módulos de
   parámetros. Un comprobante tiene muchos más campos por fila (número, tipo,
   fecha, valor, documentos asociados, acto administrativo…) y a 900px se
   apilaban de a uno — decisión del usuario, 27-ago-2026. El mismo ancho lo
   usa el selector de terceros (f90sel/selec.php), que a 560px quedaba
   demasiado angosto para su tabla. */
.modal-caja--ancha{ max-width:1350px }

/* Textos largos de los comprobantes (Concepto, Observaciones): crecen solos
   con el contenido en vez de mostrar barra de scroll, y no se dejan
   redimensionar a mano — la altura la maneja autoAltura() en el JS del
   módulo. */
textarea.campo--auto{
    overflow:hidden;
    resize:none;
    min-height:64px;
    line-height:1.45
}

/* Encabezado: mismo degradado del panel institucional del login */
.bienvenida-encabezado{
    position:relative;
    overflow:hidden;
    flex:none;
    padding:32px 36px 28px;
    color:#fff;
    background:linear-gradient(150deg,var(--bg-dark-1) 0%,var(--bg-dark-2) 55%,var(--bg-dark-3) 100%);
    border-radius:20px 20px 0 0
}
.bienvenida-encabezado::before{
    content:"";
    position:absolute;
    inset:0;
    background-image:radial-gradient(rgba(255,255,255,.07) 1px,transparent 1px);
    background-size:24px 24px;
    opacity:.5
}
.bienvenida-encabezado::after{
    content:"";
    position:absolute;
    top:-120px;
    right:-90px;
    width:320px;
    height:320px;
    border-radius:50%;
    background:radial-gradient(closest-side,rgba(255,47,126,.24),rgba(107,63,245,.12) 55%,transparent 75%)
}
.bienvenida-encabezado-top{
    position:relative;
    display:flex;
    align-items:flex-start;
    justify-content:space-between;
    gap:20px
}
.bienv-eyebrow{
    display:flex;
    align-items:center;
    gap:8px;
    margin:0 0 12px
}
.bienv-eyebrow .dot{
    width:6px;
    height:6px;
    border-radius:50%;
    background:var(--accent);
    display:inline-block
}
.bienv-eyebrow span{
    font-size:14px;
    font-weight:700;
    letter-spacing:.14em;
    text-transform:uppercase;
    color:rgba(255,255,255,.9)
}
.bienvenida-encabezado h2{
    position:relative;
    margin:0;
    font-family:'Space Grotesk','Inter',sans-serif;
    font-weight:600;
    font-size:25px;
    line-height:1.2;
    color:#f6f8ff
}
.bienvenida-encabezado p{
    position:relative;
    margin:10px 0 0;
    max-width:460px;
    font-size:15.5px;
    font-weight:500;
    line-height:1.55;
    color:rgba(235,239,250,.9)
}
.bienv-check{
    position:relative;
    flex:none;
    width:52px;
    height:52px;
    border-radius:50%;
    display:flex;
    align-items:center;
    justify-content:center;
    background:rgba(255,255,255,.06);
    border:1px solid rgba(255,255,255,.16)
}
.bienv-check i{
    font-size:22px;
    line-height:1;
    background:linear-gradient(135deg,#ff9a3d,#ff2f7e 45%,#8b3df5);
    -webkit-background-clip:text;
    background-clip:text;
    color:transparent;
    -webkit-text-fill-color:transparent
}

/* Cuerpo */
.bienvenida-contenido{
    padding:28px 36px 6px;
    overflow-y:auto
}
.bienv-section{
    margin-bottom:24px
}
/* La caja de términos usa las clases base .tarjeta/.tarjeta--prosa;
   este margen en 0 es porque aquí, a diferencia del resto de
   tarjetas, le sigue el bloque de aceptación (.bienv-check-row), que
   ya trae su propio margin-top. */
#resumenTerminos{margin-bottom:0}
.bienv-intro{
    font-size:15.5px;
    font-weight:500;
    line-height:1.6;
    color:var(--ink);
    padding-bottom:16px;
    margin-bottom:16px !important;
    border-bottom:1px dashed var(--line)
}
.bienv-intro strong{
    color:var(--accent-txt);
    font-weight:700
}
.bienv-check-row{
    display:flex;
    align-items:flex-start;
    gap:10px;
    margin-top:14px
}
.bienv-check-row input[type="checkbox"]{
    margin-top:2px;
    width:17px;
    height:17px;
    flex:none;
    accent-color:var(--accent)
}
.bienv-check-row label{
    font-size:14.5px;
    font-weight:500;
    color:#1f2937;
    line-height:1.5
}
.bienv-check-row a{
    color:var(--accent-txt);
    font-weight:700
}
.mensaje-zentvr{
    display:none;
    margin:18px 0 0;
    padding:12px 14px;
    border-radius:8px;
    font-size:14.5px;
    line-height:1.4;
    font-weight:600
}
.mensaje-zentvr.correcto{
    display:block;
    color:#125430;
    background:#eaf8f0;
    border:1px solid #38855c
}
.mensaje-zentvr.error{
    display:block;
    color:#a52a2a;
    background:#fff0f0;
    border:1px solid #9e2b1f
}

/* Anotación del tercero (Teresp: Proceso Fiscal/Disciplinario, Embargo,
   Orden de no pago — ver f11ter/scri11.js ESTADO_TERESP y config/restr.php).
   .alerta-tercero es el banner del modal (oculto salvo que tenga un
   modificador); .badge-anot es la marca chiquita que acompaña el nombre
   en las tablas (listado principal y selector reutilizable). */
.alerta-tercero{
    display:none;
    align-items:center;
    gap:10px;
    margin-bottom:18px;
    padding:12px 16px;
    border-radius:10px;
    font-size:14px;
    font-weight:700;
    line-height:1.4
}
.alerta-tercero--bloquea,
.alerta-tercero--advierte{display:flex}
.alerta-tercero--bloquea{color:#8a1f1f;background:#fdecec;border:1px solid #9e2b1f}
.alerta-tercero--bloquea i{color:#9e2b1f;font-size:18px;flex-shrink:0}
.alerta-tercero--advierte{color:#7a4a00;background:#fff6e6;border:1px solid #a86a00}
.alerta-tercero--advierte i{color:#6f4800;font-size:18px;flex-shrink:0}

.badge-anot{
    display:inline-flex;
    align-items:center;
    gap:4px;
    margin-left:6px;
    padding:2px 8px;
    border-radius:20px;
    font-size:14px;
    font-weight:700;
    white-space:nowrap;
    vertical-align:middle
}
.badge-anot i{font-size:14px}
.badge-anot--bloquea{color:#8a1f1f;background:#fdecec;border:1px solid #9e2b1f}
.badge-anot--advierte{color:#7a4a00;background:#fff6e6;border:1px solid #a86a00}

/* Pie */
.bienvenida-pie{
    flex:none;
    display:flex;
    align-items:center;
    justify-content:space-between;
    gap:16px;
    padding:20px 36px;
    background:#f7f8fa;
    border-top:1px solid #8a92a4;
    border-radius:0 0 20px 20px
}
.bienv-nota{
    font-size:14.5px;
    font-weight:500;
    color:#4b5563
}
.bienv-botones{
    display:flex;
    gap:10px;
    flex:none
}

/* =====================================================================
   ALTURA DE LOS MODALES DE CAPTURA  ·  3-sep-2026 (usuario)
   =====================================================================
   El encabezado oscuro, su separacion con el cuerpo y el pie se
   disenaron para la PANTALLA DE BIENVENIDA (indini.php), que es una
   pagina entera y agradece el aire. Dentro de un modal de captura ese
   mismo aire son 50px que se le quitan a la tabla de afectaciones, que
   es la que de verdad necesita crecer.

   TODO lo de aqui cuelga de .modal-caja a proposito: indini.php NO
   esta dentro de una, asi que la bienvenida conserva su diseno
   original intacto y solo se comprimen los modales. */
.modal-caja .bienvenida-encabezado{padding:18px 36px 16px}

/* El rotulo de arriba ("PRESUPUESTO · EJECUCION") pedia margin:0 0 12px
   en .bienv-eyebrow, pero .bienvenida-encabezado p —que va despues en
   este archivo y ademas pesa mas por especificidad (0,1,1 contra
   0,1,0)— se lo reescribia entero a margin:10px 0 0. Resultado real:
   10px de aire ARRIBA que nadie pidio, y cero separacion con el
   titulo. Aqui se vuelve a decir, con peso suficiente para ganar. */
.modal-caja .bienv-eyebrow{margin:0 0 6px}

.modal-caja .bienvenida-contenido{padding-top:14px}
.modal-caja .bienvenida-pie{padding:14px 36px}
/* Columna del pie que apila el texto de modo (Modo consulta / Tercero en
   edición) y, debajo, el mensaje de éxito/error (p.ej. Terceros) con el
   mínimo interlineado posible. El pie es estático (no se desplaza con el
   contenido) así que el resultado de la acción se ve de inmediato, y al
   ir pegado al texto de modo casi no cambia el alto del pie ni la
   distribución del formulario al aparecer o desaparecer. */
.bienv-nota-col{display:flex;flex-direction:column;gap:2px;min-width:0}
/* Estado del comprobante en el pie del modal: mismo tamaño que la nota de
   modo, pero destacado, porque es dato del documento y no una indicación
   de la pantalla. */
.bienv-nota--estado{font-weight:800;color:var(--ink)}

/* Bloque derecho del encabezado de un modal de comprobante: un campo
   informativo (el usuario que elaboró) al lado del ícono redondo. El campo
   va sobre el degradado oscuro del encabezado, así que invierte los colores
   de .campo. */
.bienv-encab-der{
    display:flex;
    align-items:center;
    gap:12px;
    flex:none
}
.campo.campo--encab{
    width:170px;
    height:36px;
    padding:0 12px;
    text-align:center;
    font-size:14.5px;
    font-weight:700;
    color:#fff;
    background:rgba(255,255,255,.10);
    border-color:rgba(255,255,255,.24)
}
.bienv-nota-col .mensaje-zentvr{
    margin:0;
    padding:0;
    border:0;
    background:none;
    font-size:14px;
    line-height:1.3
}
/* Los botones del pie usan la clase base .btn (.btn--secundario para
   Cancelar, .btn sola para Continuar/Actualizar). */

/* Enlace "¿Olvidó su contraseña?" y asistente de recuperación (f99ent) */
.login-olvido{display:block;margin-top:14px;text-align:center;font-size:14.5px;font-weight:600;color:var(--accent-txt);text-decoration:none}
.login-olvido:hover{text-decoration:underline}
.olvido-progreso{display:flex;gap:6px;margin-bottom:22px}
.olvido-progreso span{flex:1;height:4px;border-radius:2px;background:var(--line)}
.olvido-progreso span.activo{background:var(--accent)}
.olvido-paso{display:none}
.olvido-paso.activo{display:block}
.olvido-lead{margin:0 0 18px;font-size:14px;line-height:1.5;color:var(--muted)}
/* Dentro de una tarjeta el texto introductorio queda un poco más
   apretado que el valor por defecto de arriba. */
.tarjeta .olvido-lead{margin:0 0 14px}
.tarjeta .olvido-lead:last-child{margin-bottom:0}

.olvido-canales{display:flex;gap:12px;margin-bottom:6px}
.olvido-canales:last-child{margin-bottom:0}
.olvido-canal{flex:1;display:flex;align-items:center;justify-content:center;gap:8px;height:52px;background:#fff;border:1px solid var(--line);border-radius:10px;font-size:14.5px;font-weight:600;color:#374151;cursor:pointer;transition:border-color .2s,background .2s}
.olvido-canal input{margin:0;accent-color:var(--accent)}
.olvido-canal.seleccionado{border-color:var(--accent);background:rgba(255,47,126,.06);color:var(--ink)}
.olvido-canal.deshabilitado{opacity:.5;cursor:not-allowed}

.olvido-codigo{width:100%;height:56px;text-align:center;font-size:26px;font-weight:700;letter-spacing:10px;border:1px solid var(--line);border-radius:10px;outline:none;background:#fff;color:var(--ink);font-family:inherit}
.olvido-codigo:focus{border-color:var(--accent);box-shadow:0 0 0 3px rgba(255,47,126,.14)}

/* Fila de acciones bajo el código: vence a la izquierda, reenviar/verificar a la derecha */
.olvido-codigo-fila{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-top:12px}
.olvido-vence{margin:0;font-size:14px;color:var(--muted)}
.olvido-codigo-botones{display:flex;align-items:center;gap:14px}
/* Reenviar código = .btn--texto; Verificar código = .btn--chico */

/* Tarjeta de nueva contraseña: deshabilitada/atenuada hasta verificar el código */
.olvido-card--clave{background:#f3f4f6}
.olvido-card--clave.olvido-desbloqueada{background:#f9fafb}
.olvido-nota-bloqueo{display:flex;align-items:center;gap:8px;margin:0;font-size:14.5px;font-weight:600;color:var(--muted)}
.olvido-nota-bloqueo i{color:var(--icon)}
.olvido-nota-bloqueo.correcto{color:#146138}
.olvido-nota-bloqueo.correcto i{color:#146138}

@media(max-width:650px){
    #modalBienvenidaFondo, .modal-fondo{padding:10px}
    .bienvenida-encabezado{padding:26px 22px 22px}
    .bienvenida-contenido{padding:22px 22px 4px}
    .bienvenida-pie{padding:16px 22px;flex-direction:column;align-items:stretch}
    .bienv-botones{width:100%}
    .bienv-botones .btn{flex:1 1 0;width:100%}
    .form-grid{grid-template-columns:1fr}
    .olvido-canales{flex-direction:column}
    .olvido-codigo-fila{flex-direction:column;align-items:stretch;text-align:center}
    .olvido-codigo-botones{justify-content:center}
}

/* ============================================================
   PORTAL: barra superior de sesión + encabezado institucional
   ============================================================ */

/* Barra angosta con los datos de la sesión activa (usuario, grupo,
   vigencia) y el botón de salida. */
.portal-topbar{
    display:flex;
    align-items:center;
    justify-content:space-between;
    gap:16px;
    padding:10px 28px;
    background:var(--btn-bg);
    color:rgba(255,255,255,.85)
}
.portal-chip-vigencia{
    display:inline-flex;
    align-items:center;
    gap:6px;
    font-size:14px;
    font-weight:600;
    color:rgba(255,255,255,.95)
}
.portal-topbar-user{
    display:flex;
    align-items:center;
    gap:16px
}
.portal-user-datos{
    display:flex;
    flex-direction:column;
    align-items:flex-end;
    line-height:1.3
}
.portal-user-nombre{
    font-size:14.5px;
    font-weight:700;
    color:#fff
}
.portal-user-grupo{
    font-size:14px;
    font-weight:600;
    color:rgba(255,255,255,.9)
}
.portal-btn-salir{
    display:inline-flex;
    align-items:center;
    gap:6px;
    padding:7px 14px;
    border-radius:8px;
    border:1px solid rgba(255,255,255,.22);
    font-size:14px;
    font-weight:600;
    color:#fff;
    text-decoration:none;
    transition:background .2s
}
.portal-btn-salir:hover{background:rgba(255,255,255,.08)}

/* Encabezado institucional: logo de la entidad a la izquierda, nombre y
   NIT centrados, logo de Activos a la derecha. */
.portal-encabezado{
    display:grid;
    grid-template-columns:1fr auto 1fr;
    align-items:center;
    gap:20px;
    padding:22px 32px;
    background:#fff;
    border-bottom:1px solid var(--line)
}
.portal-logo-entidad,
.portal-logo-activos{
    display:flex;
    align-items:center;
    height:56px
}
.portal-logo-activos{justify-content:flex-end}
.portal-logo-entidad img,
.portal-logo-activos img{
    max-height:100%;
    width:auto
}
.portal-identidad{
    text-align:center
}
.portal-entidad-nombre{
    margin:0;
    font-family:'Space Grotesk','Inter',sans-serif;
    font-weight:600;
    font-size:20px;
    color:var(--ink)
}
.portal-entidad-nit{
    margin:4px 0 0;
    font-size:14px;
    font-weight:500;
    color:var(--muted)
}

@media(max-width:650px){
    .portal-topbar{padding:10px 16px}
    .portal-user-datos{display:none}
    .portal-encabezado{
        grid-template-columns:1fr;
        justify-items:center;
        padding:20px 20px;
        gap:12px
    }
    .portal-logo-activos{justify-content:center}
}

/* ============================================================
   PORTAL: estructura general (menú lateral a toda la altura +
   columna principal con barra superior, encabezado y contenido)
   ============================================================ */
.portal-app{
    display:flex;
    align-items:stretch;
    min-height:100vh
}
.portal-main{
    flex:1;
    min-width:0;
    display:flex;
    flex-direction:column
}

/* Menú lateral: corre a todo lo alto de la ventana (no solo detrás del
   contenido), para que no se vea cortado contra la barra superior. Un
   .portal-modulo (<details>) por módulo del sistema; cada uno se
   expande/colapsa sin JavaScript, y arrancan cerrados (sin el atributo
   "open") para que quepan muchos módulos sin verse todos desplegados a
   la vez. Fondo oscuro con la misma textura de puntos del panel
   institucional del login, para que se sienta "técnico". */
.portal-sidebar{
    position:relative;
    flex:none;
    width:260px;
    overflow:hidden;
    padding:20px 14px;
    background:linear-gradient(165deg,var(--bg-dark-1) 0%,var(--bg-dark-2) 55%,var(--bg-dark-3) 100%);
    transition:width .2s
}
.portal-sidebar.colapsado{width:68px}

/* Botón que colapsa el sidebar a solo íconos. Arranca siempre desplegado;
   colapsarlo es una decisión manual del usuario (config/jsact/portal.js
   recuerda su elección con localStorage para que no se le olvide entre
   una página del sistema y otra). */
.portal-colapsar{
    position:relative;
    display:flex;
    align-items:center;
    justify-content:center;
    width:100%;
    height:36px;
    margin-bottom:14px;
    border:0;
    border-radius:8px;
    background:rgba(255,255,255,.06);
    color:rgba(255,255,255,.9);
    font-size:14px;
    cursor:pointer;
    transition:background .15s
}
.portal-colapsar:hover{background:rgba(255,255,255,.13)}
.portal-colapsar i{transition:transform .2s}
.portal-sidebar.colapsado .portal-colapsar i{transform:rotate(180deg)}
.portal-sidebar::before{
    content:"";
    position:absolute;
    inset:0;
    background-image:radial-gradient(rgba(255,255,255,.06) 1px,transparent 1px);
    background-size:22px 22px;
    opacity:.6;
    pointer-events:none
}

/* "Inicio": mismo lenguaje visual que .portal-modulo summary (para que se
   sienta parte del mismo menú), pero es un enlace normal, no un <details> —
   siempre vuelve a portal.php. */
.portal-inicio{
    position:relative;
    display:flex;
    align-items:center;
    gap:10px;
    padding:11px 12px;
    margin-bottom:14px;
    border-radius:10px;
    border-left:2px solid transparent;
    font-size:14.5px;
    font-weight:700;
    color:#f6f8ff;
    text-decoration:none;
    transition:background .15s,border-color .15s
}
.portal-inicio:hover{background:rgba(255,255,255,.09)}
.portal-inicio i{
    font-size:16px;
    color:rgba(255,255,255,.75);
    transition:color .15s
}
.portal-inicio.activo{
    background:rgba(255,255,255,.12);
    border-left-color:var(--accent)
}
.portal-inicio.activo i{color:var(--accent-txt)}
.portal-sidebar.colapsado .portal-inicio{
    justify-content:center;
    padding:11px 0
}
.portal-sidebar.colapsado .portal-inicio span{display:none}
.portal-nav{position:relative}
.portal-modulo{
    margin-bottom:4px
}
.portal-modulo summary{
    display:flex;
    align-items:center;
    gap:10px;
    padding:11px 12px;
    border-radius:10px;
    font-size:14.5px;
    font-weight:700;
    color:#f6f8ff;
    cursor:pointer;
    list-style:none;
    user-select:none;
    transition:background .15s
}
.portal-modulo summary::-webkit-details-marker{display:none}
.portal-modulo summary:hover{background:rgba(255,255,255,.07)}
.portal-modulo summary > i:first-child{
    font-size:16px;
    background:linear-gradient(135deg,#ff9a3d,#ff2f7e 45%,#8b3df5);
    -webkit-background-clip:text;
    background-clip:text;
    color:transparent;
    -webkit-text-fill-color:transparent
}
.portal-modulo summary > span{flex:1}
.portal-modulo-flecha{
    font-size:14.5px;
    color:rgba(255,255,255,.6);
    transition:transform .2s
}
.portal-modulo[open] > summary .portal-modulo-flecha{transform:rotate(180deg)}
.portal-submenu{
    list-style:none;
    margin:2px 0 10px;
    padding:0;
    display:flex;
    flex-direction:column;
    gap:2px
}
.portal-submenu a{
    display:flex;
    align-items:center;
    gap:10px;
    padding:9px 12px 9px 38px;
    border-radius:8px;
    border-left:2px solid transparent;
    font-size:14px;
    font-weight:600;
    color:rgba(244,247,255,.97);
    text-decoration:none;
    transition:background .15s,color .15s,border-color .15s
}
.portal-submenu a:hover{
    background:rgba(255,255,255,.09);
    border-left-color:var(--accent);
    color:#fff
}
.portal-submenu a i{
    font-size:14px;
    color:rgba(255,255,255,.62);
    width:16px;
    text-align:center
}
.portal-submenu a:hover i{color:var(--accent-txt)}
.portal-submenu a.activo{
    background:rgba(255,255,255,.12);
    border-left-color:var(--accent);
    color:#fff
}
.portal-submenu a.activo i{color:var(--accent-txt)}

/* Tercer nivel del menú: un <details class="portal-subgrupo"> dentro de
   .portal-submenu (Presupuesto ▸ Apropiaciones ▸ Nota Presupuestal). Su
   summary se ve igual que una opción normal del submenú, pero con flecha
   en vez de enlace; las opciones que cuelgan van sangradas un escalón más
   (.portal-submenu--n2). */
.portal-subgrupo > summary{
    display:flex;
    align-items:center;
    gap:10px;
    padding:9px 12px 9px 38px;
    border-radius:8px;
    border-left:2px solid transparent;
    font-size:14px;
    font-weight:600;
    color:rgba(244,247,255,.97);
    cursor:pointer;
    list-style:none;
    user-select:none;
    transition:background .15s,color .15s,border-color .15s
}
.portal-subgrupo > summary::-webkit-details-marker{display:none}
.portal-subgrupo > summary:hover{
    background:rgba(255,255,255,.09);
    border-left-color:var(--accent);
    color:#fff
}
.portal-subgrupo > summary > i:first-child{
    font-size:14px;
    color:rgba(255,255,255,.62);
    width:16px;
    text-align:center
}
.portal-subgrupo > summary:hover > i:first-child{color:var(--accent-txt)}
.portal-subgrupo > summary > span{flex:1}
.portal-subgrupo[open] > summary .portal-modulo-flecha{transform:rotate(180deg)}
.portal-submenu--n2{margin:2px 0 6px}
.portal-submenu--n2 a{padding-left:58px}

/* Sidebar colapsado: el subgrupo también se reduce a su ícono. */
.portal-sidebar.colapsado .portal-subgrupo > summary{
    justify-content:center;
    padding:9px 0;
    border-left:0
}
.portal-sidebar.colapsado .portal-subgrupo > summary > span,
.portal-sidebar.colapsado .portal-subgrupo > summary .portal-modulo-flecha{display:none}
.portal-sidebar.colapsado .portal-submenu--n2 a{padding-left:0}

/* Opción del menú todavía sin módulo construido: enlaza a enobra.php. Se
   deja clicable a propósito (así se ve el árbol completo funcionando), pero
   más apagada que las demás para que se note que no hay nada detrás. */
.portal-submenu a.pendiente{color:rgba(240,244,255,.5)}
.portal-submenu a.pendiente i{color:rgba(255,255,255,.32)}
.portal-submenu a.pendiente:hover{color:rgba(255,255,255,.82)}

/* Sidebar colapsado: mismo acordeón, solo que reducido a íconos (el
   texto de cada opción sigue disponible como tooltip nativo vía
   "title"). */
.portal-sidebar.colapsado .portal-modulo summary{
    justify-content:center;
    padding:11px 0
}
.portal-sidebar.colapsado .portal-modulo summary > span,
.portal-sidebar.colapsado .portal-modulo-flecha{
    display:none
}
.portal-sidebar.colapsado .portal-submenu a{
    justify-content:center;
    padding:9px 0;
    border-left:0
}
.portal-sidebar.colapsado .portal-submenu a span{
    display:none
}

/* Contenido principal */
.portal-contenido{
    flex:1;
    min-width:0;
    padding:32px;
    background:#f8f9fb
}
/* Solo portal.php la usa (ver $claseContenido en config/marco1.php): hace
   que su único contenido (.portal-vacio) crezca hasta llenar el alto
   disponible, en vez de quedarse en su alto mínimo — antes dejaba un
   colchón de fondo plano muy grande debajo de la tarjeta en pantallas
   altas, que se veía como si el sidebar "cortara" contra ese vacío. */
.portal-contenido--inicio{
    display:flex;
    flex-direction:column
}
.portal-contenido--inicio .portal-vacio{
    flex:1
}
.portal-contenido-vacio{
    margin:0;
    font-size:14px;
    color:var(--muted)
}

/* Pantalla de bienvenida (portal.php, sin ningún módulo cargado): misma
   "personalidad técnico-financiera" del panel del login (textura de
   puntos + resplandores de color + una gráfica de tendencia), pero en
   versión clara para que combine con el resto del contenido del portal.
   Va SOLO aquí (no en .portal-contenido en general) para no meterle este
   fondo decorativo detrás de tablas/formularios de los módulos, donde
   estorbaría la lectura de los datos. */
.portal-vacio{
    position:relative;
    overflow:hidden;
    display:flex;
    flex-direction:column;
    align-items:center;
    justify-content:center;
    gap:0;
    min-height:480px;
    padding:56px 24px;
    border-radius:20px;
    text-align:center;
    background:linear-gradient(165deg,#fbfbfe 0%,#f4f3fb 55%,#eef1fb 100%);
    border:1px solid var(--line)
}
.portal-vacio::before{
    content:"";
    position:absolute;
    inset:0;
    background-image:radial-gradient(rgba(18,23,42,.055) 1px,transparent 1px);
    background-size:26px 26px;
    opacity:.8;
    pointer-events:none
}
.portal-vacio-glow{
    position:absolute;
    top:-160px;
    right:-140px;
    width:520px;
    height:520px;
    border-radius:50%;
    background:radial-gradient(closest-side,rgba(255,47,126,.16),rgba(107,63,245,.09) 55%,transparent 75%);
    pointer-events:none
}
.portal-vacio-glow--izq{
    top:auto;
    right:auto;
    bottom:-200px;
    left:-160px;
    width:460px;
    height:460px;
    background:radial-gradient(closest-side,rgba(43,107,255,.12),rgba(255,154,61,.07) 55%,transparent 75%)
}
.portal-vacio-trend{
    position:absolute;
    left:0;
    right:0;
    bottom:0;
    width:100%;
    height:200px;
    opacity:.4;
    pointer-events:none
}
.portal-vacio-cuerpo{
    position:relative;
    max-width:440px
}
.portal-vacio-icono{
    width:60px;
    height:60px;
    margin:0 auto 20px;
    border-radius:16px;
    display:flex;
    align-items:center;
    justify-content:center;
    font-size:26px;
    color:#fff;
    background:linear-gradient(135deg,#ff9a3d,#ff2f7e 45%,#8b3df5);
    box-shadow:0 12px 26px rgba(255,47,126,.28)
}
.portal-vacio-titulo{
    margin:0 0 8px;
    font-family:'Space Grotesk','Inter',sans-serif;
    font-size:21px;
    font-weight:600;
    color:var(--ink)
}
.portal-vacio .portal-contenido-vacio{
    font-size:14.5px
}

@media(max-width:768px){
    .portal-app{
        flex-direction:column;
        min-height:auto
    }
    .portal-sidebar{
        width:100%;
        border-bottom:1px solid rgba(255,255,255,.1)
    }
    .portal-contenido{padding:24px 20px}
}

/* ============================================================
   MÓDULOS DE DATOS (listados + formularios)
   Vocabulario compartido por Terceros y los módulos que sigan:
   encabezado de módulo, tabla de listado, botones de fila e
   íconos, bloques de subsección dentro de un formulario grande
   (ej. "Información tributaria" / "Información bancaria").
   ============================================================ */

.mod-encab{
    display:flex;
    align-items:center;
    justify-content:space-between;
    gap:16px;
    flex-wrap:wrap;
    margin-bottom:18px
}
.mod-titulo{
    display:flex;
    align-items:center;
    gap:10px;
    margin:0;
    font-size:19px;
    font-weight:800;
    color:var(--ink)
}
.mod-titulo i{color:var(--accent-txt);font-size:20px}

/* =====================================================================
   EL «?» DE AYUDA Y SU PARRAFO
   =====================================================================
   Idea del usuario (11-sep-2026): en vez de una nota en letra chica
   debajo de cada campo, un «?» al lado de lo que necesita explicacion.
   La nota chica se lee una vez y despues estorba todos los dias; el «?»
   esta ahi el dia que hace falta y no ocupa alto el resto del tiempo.

   YA EXISTIA, COPIADO DOS VECES: .imp-ayuda en p25imp y .liq-ayuda en
   p25liq, con su CSS y su JS duplicados en cada modulo. Aqui queda una
   sola vez, y el manejador vive en assets/jsact/portal.js, que se carga
   en todas las paginas: una pantalla nueva solo pone la clase.

   NO ES UN COMPONENTE NUEVO. El boton es un <button> sin cromo, para que
   al icono lo pinte la regla del sitio donde se pare —.mod-titulo i le da
   el color de acento y su tamaño, un .campo-label le da el suyo—. Por eso
   color:inherit y no un color propio.

   LO QUE NO VA DETRAS DEL «?»: la advertencia operativa —«sin estos tres
   datos no podra recuperar su contraseña», «cargar uno nuevo reemplaza el
   anterior»— se queda a la vista, en 14px. Esconder detras de un clic lo
   que evita saltarse una accion obligatoria es como no haberlo escrito.
   El «?» es para la explicacion, no para la advertencia. */
.ayuda-btn{
    background:none;
    border:0;
    padding:0;
    margin:0 0 0 6px;
    cursor:pointer;
    line-height:1;
    display:inline-flex;
    align-items:center;
    color:inherit
}
.ayuda-btn:hover i{opacity:.65}

/* Nace oculto y lo abre la clase 'abierto' —el mismo verbo que ya usan
   .modal-fondo y el resto del sistema— y no un style.display escrito a
   mano desde el JS. */
.ayuda-panel{
    display:none;
    margin:0 0 11px;
    max-width:1200px;
    font-size:15px;
    line-height:1.35
}
.ayuda-panel.abierto{display:block}
/* Ícono de filtro entre campos de la barra de filtros (ver f11ter, la
   plantilla base para los módulos que vienen). flex-shrink:0 para que no
   se aplaste cuando el espacio esté justo. */
.icono-filtro{
    color:var(--accent-txt);
    font-size:20px;
    flex-shrink:0
}
.mod-filtros{
    display:flex;
    align-items:center;
    gap:10px;
    flex-wrap:wrap
}
.mod-filtros .campo{height:42px;font-size:15px}
.mod-acciones{display:flex;align-items:center;gap:10px}

.mod-vacio{
    padding:36px 20px;
    text-align:center;
    font-size:15px;
    color:var(--muted)
}

/* Estado de un comprobante transaccional dentro de la tabla (f00npt y los
   módulos de Presupuesto/Tesorería/Contabilidad que vengan). Reemplaza el
   coloreado directo de la celda que hacía el sistema original. */
.estado-npt{
    display:inline-block;
    padding:2px 10px;
    border-radius:999px;
    border:1px solid transparent;
    font-size:14px;
    font-weight:700;
    letter-spacing:.02em;
    white-space:nowrap
}
.estado-npt--pendiente{background:rgba(43,107,255,.10);border-color:rgba(43,107,255,.28);color:#1740ad}
.estado-npt--guardado{background:rgba(22,148,96,.10);border-color:rgba(22,148,96,.28);color:#0e5636}
.estado-npt--anulado{background:rgba(120,120,120,.12);border-color:rgba(120,120,120,.3);color:#4a4a4a}

/* ESTADO DE PAGO de una orden. Misma familia .estado-npt, pero SÓLIDOS y
   no traslúcidos, y esa es toda la diferencia: los de arriba dicen en qué
   etapa va un documento —información— y estos dicen que hay plata sin
   girar —trabajo pendiente—. Un fondo lleno lo saca del renglón y se ve
   antes de leerlo, que es justo lo que se le pide a esta columna
   (usuario, 7-sep-2026, sobre lo que vio en una fiduciaria).

   Blanco sobre estos dos tonos pasa el contraste AA a 14px/700, que es el
   mínimo de legibilidad del portal. Si se aclaran, el texto tiene que
   volver a oscuro. */
.estado-npt--porpagar{background:#c2410c;border-color:#c2410c;color:#fff}
.estado-npt--abonada{background:#a16207;border-color:#a16207;color:#fff}
/* Pagada NO va sólida a propósito: ya no pide nada, y si gritara igual
   que las otras dos la columna volvería a ser un bloque de color parejo
   donde no se distingue lo que falta. Comparte el verde suave de lo
   guardado. */
.estado-npt--pagada{background:rgba(22,148,96,.10);border-color:rgba(22,148,96,.28);color:#0e5636}

/* Página enobra.php — destino común de las opciones del menú que aún no
   tienen módulo propio. */
.enobra{
    display:flex;
    flex-direction:column;
    align-items:center;
    gap:10px;
    padding:56px 24px;
    text-align:center
}
.enobra-icono{
    display:grid;
    place-items:center;
    width:64px;
    height:64px;
    margin-bottom:6px;
    border-radius:18px;
    background:linear-gradient(135deg,rgba(255,154,61,.16),rgba(139,61,245,.16));
    font-size:28px;
    color:var(--accent-txt)
}
.enobra-ruta{
    margin:0;
    font-size:14px;
    font-weight:700;
    letter-spacing:.04em;
    text-transform:uppercase;
    color:var(--muted)
}
.enobra-titulo{
    margin:0;
    font-size:18px;
    font-weight:800;
    color:var(--ink)
}
.enobra-texto{
    max-width:460px;
    margin:0 0 8px;
    font-size:14.5px;
    line-height:1.55;
    color:var(--muted)
}

.tabla-wrap{
    overflow-x:auto;
    border:1px solid var(--line);
    border-radius:14px;
    /* LA BARRA HORIZONTAL SE VE, no aparece solo al pasar el mouse.
       El navegador la esconde por defecto en Windows y macOS, y una tabla
       que se corta sin barra visible no se lee como "hay más a la
       derecha": se lee como "la última columna no existe" (usuario,
       1-sep-2026). 12px y con color propio, para que se note. */
    scrollbar-width:auto;
    scrollbar-color:#6f7889 #e9ecf3;
    padding-bottom:2px
}
.tabla-wrap::-webkit-scrollbar{height:12px}
.tabla-wrap::-webkit-scrollbar-track{background:#e9ecf3;border-radius:0 0 14px 14px}
.tabla-wrap::-webkit-scrollbar-thumb{
    background:#6f7889;
    border-radius:8px;
    border:2px solid #e9ecf3
}
.tabla-wrap::-webkit-scrollbar-thumb:hover{background:#4b5563}
.tabla{
    width:100%;
    border-collapse:collapse;
    font-size:15.5px;
    background:#fff
}
.tabla thead th{
    text-align:left;
    padding:13px 14px;
    background:linear-gradient(180deg,#eef1f8 0%,#e5e8f2 100%);
    color:#1f2937;
    font-size:14px;
    font-weight:800;
    letter-spacing:.05em;
    text-transform:uppercase;
    border-bottom:2px solid var(--accent);
    white-space:nowrap
}
.tabla tbody td{
    padding:13px 14px;
    border-bottom:1px solid var(--line);
    color:var(--ink);
    font-weight:500;
    vertical-align:middle
}
.tabla tbody tr:last-child td{border-bottom:none}
.tabla tbody tr:hover td{background:#fafbfe}

/* LA COLUMNA DE ACCIONES NO SE PIERDE AL DESPLAZARSE.
   Queda pegada al borde derecho: por ancha que sea la tabla, el botón de
   ver el comprobante está siempre a la vista. Sin esto, el desplazamiento
   horizontal se la lleva fuera de pantalla y hay que arrastrar hasta el
   final cada vez para hacer lo que más se hace (usuario, 1-sep-2026).

   El fondo propio es obligatorio —si no, el contenido de las otras
   columnas se ve por debajo al pasar— y la sombra al costado es lo que
   dice que ahí hay un borde y que atrás sigue habiendo tabla. */
.tabla th.col-acciones,
.tabla td.col-acciones{
    position:sticky;
    right:0;
    z-index:2;
    background:#fff;
    box-shadow:-8px 0 10px -8px rgba(12,20,36,.35)
}
.tabla thead th.col-acciones{background:#e7eaf2}
.tabla tbody tr:hover td.col-acciones{background:#fafbfe}
.tabla td.col-acciones{
    width:1%;
    white-space:nowrap;
    text-align:right
}
.tabla th.col-num,
.tabla td.col-num{
    width:16ch;
    white-space:nowrap;
    font-variant-numeric:tabular-nums
}
/* Columna corta para valores cortos (porcentajes, cifras pequeñas) —
   mismo criterio que .col-num pero a la mitad del ancho (8ch en vez de
   16ch), para columnas que sin esto quedan "muy anchas para el dato que
   manejan" (ej. Porcentaje en f15ded). */
/* COLUMNA DE TEXTO ACOTADA. Para las columnas que traen frases —origen,
   concepto, tercero— en tablas donde lo que importa es ver muchas filas a
   la vez.

   El problema que resuelve: sin ancho, un concepto largo envuelve en tres
   o cuatro renglones y estira toda la fila; con diez comprobantes en
   pantalla, la tabla deja de caber y hay que desplazarse para leer lo
   mismo. Aquí el texto se corta con puntos suspensivos y el completo
   queda en el title, que es donde ya estaba. */
.tabla th.col-texto,
.tabla td.col-texto{
    width:18ch;
    max-width:18ch;
    white-space:nowrap;
    overflow:hidden;
    text-overflow:ellipsis;
    text-align:left
}
.tabla th.col-corto,
.tabla td.col-corto{
    width:8ch;
    white-space:nowrap;
    font-variant-numeric:tabular-nums;
    text-align:right
}

.fila-acciones{display:inline-flex;gap:6px}
.btn-ico{
    display:inline-flex;
    align-items:center;
    justify-content:center;
    width:32px;
    height:32px;
    border-radius:9px;
    /* 1.5px y no 1px: a 32px de lado, un contorno de un pixel se pierde
       incluso teniendo buen contraste. */
    border:1.5px solid transparent;
    cursor:pointer;
    font-size:16px;
    font-weight:700;
    transition:background .15s,color .15s,border-color .15s
}
.btn-ico:hover{filter:none}
/* LOS TRES BOTONES DE ACCIÓN DE LAS TABLAS, medidos contra el blanco de
   la página (1-sep-2026):

     ver       borde 1.41:1   ->  5.89:1
     editar    borde 1.51:1   ->  4.86:1
     eliminar  borde 1.69:1   ->  5.44:1

   Todos estaban construidos con tintes de 7% a 16% sobre blanco, que dan
   un rectángulo indistinguible del papel. El usuario lo dijo así: "se
   sabe que están porque uno pasa el mouse encima". Tenía razón — el
   estado normal no comunicaba nada y el hover hacía todo el trabajo.

   El RELLENO se queda claro a propósito; lo que define un botón chico no
   es el fondo sino su contorno y su glifo, y esos dos son los que ahora
   pasan de 4.5:1. */
.btn-ico--ver{background:#e4e8ef;color:#1b2436;border-color:#5a6577}
.btn-ico--ver:hover{background:#5a6577;color:#fff;border-color:#1b2436}
.btn-ico--editar{background:#ffd9e7;color:#a30048;border-color:#e0005c}
.btn-ico--editar:hover{background:var(--accent);color:#fff;border-color:#a30048}
.btn-ico--eliminar{background:#fbdedb;color:#96271b;border-color:#9e2b1f}
.btn-ico--eliminar:hover{background:#9e2b1f;color:#fff;border-color:#96271b}
/* PAGAR: el botón que abre el pago de una orden desde su listado.

   LLEVA EL MISMO FONDO SÓLIDO DEL CHIP «Por Pagar» (usuario, 7-sep-2026),
   y no un color propio: la fila señala la deuda con ese naranja y el
   botón es lo que la resuelve, así que la vista se va de uno al otro sin
   tener que traducir dos códigos de color.

   SOBRE UNA ORDEN YA PAGADA el botón NO desaparece: se inhabilita. Que
   aparezca y desaparezca según el saldo haría bailar la columna de
   acciones de fila en fila, y el gris apagado dice lo que hay que decir
   —ese camino existe y aquí ya está recorrido—. */
.btn-ico--pagar{background:#c2410c;color:#fff;border-color:#c2410c}
.btn-ico--pagar:hover{background:#9a340a;color:#fff;border-color:#7d2a08}
.btn-ico--pagar:disabled,
.btn-ico--pagar[disabled]{background:#e8e8e8;color:#8a8a8a;border-color:#cfcfcf;
    cursor:default;opacity:1}
.btn-ico--pagar:disabled:hover,
.btn-ico--pagar[disabled]:hover{background:#e8e8e8;color:#8a8a8a;border-color:#cfcfcf}

/* Subsecciones dentro de un formulario grande (Información tributaria,
   Información bancaria, etc.) */
.seccion-tit{
    width:100%;
    margin:6px 0 0;
    padding-top:14px;
    border-top:1px dashed var(--line);
    font-size:14px;
    font-weight:800;
    letter-spacing:.06em;
    text-transform:uppercase;
    color:var(--accent-txt)
}
.form-grid > .seccion-tit:first-child{border-top:none;padding-top:0;margin-top:0}

/* Nombre/razón social calculado: se muestra de solo lectura, nunca se
   captura directamente (se arma en PHP a partir de Tenoma/Tenomb/Teapea/
   Teapeb o Terazo según Tenatu). */
.campo--calculado{
    background:#fffbea;
    font-weight:700;
    color:#5b3a00
}

/* Campo obligatorio sin diligenciar: se resalta solo al intentar Guardar
   sin completarlo (ver validarFormulario() en cada scri1x.js), y se quita
   solo en cuanto el usuario corrige ese campo puntual. Mismo lenguaje de
   color que ya usa el proyecto para "esto bloquea la acción" (btn-ico--
   eliminar / badge-anot--bloquea), para no introducir un color nuevo.
   Selector ".campo.campo--falta" (no solo ".campo--falta") a propósito:
   iguala la especificidad de .campo[readonly] y .campo--bloqueado, y al
   quedar más abajo en el archivo esta regla gana el empate — así el
   resalto también se ve en campos de solo lectura que se llenan por
   catálogo (ej. Ciudad, Banco) y quedaron vacíos. */
.campo.campo--falta{
    border-color:#9e2b1f;
    background:#fdecec;
    box-shadow:0 0 0 3px rgba(192,57,43,.14)
}
.campo-label--falta{
    color:#9e2b1f
}

/* Las flechas van a los EXTREMOS de la franja y el conteo al centro. Antes
   iban las tres cosas juntas en el centro: se leian como una sola masa y,
   con el rotulo largo, el texto llegaba a tocar los botones (usuario,
   3-sep-2026). .pag-info se queda con todo el sobrante y se centra sola
   dentro de el, asi que el conteo no se corre de sitio aunque uno de los
   dos botones este deshabilitado. */
.tabla-paginacion{
    display:flex;
    align-items:center;
    justify-content:space-between;
    gap:16px;
    padding:16px 0 2px
}
.btn-pag{
    display:inline-flex;
    align-items:center;
    justify-content:center;
    /* flex:none es obligatorio con space-between: sin el, el reparto del
       sobrante encogeria los botones y volverian a quedar diminutos. */
    flex:none;
    width:40px;
    height:40px;
    /* La flecha es el UNICO contenido del boton, asi que el tamano del
       icono es el tamano visible del control. Heredaba los 15px del cuerpo
       y se perdia dentro del recuadro. */
    font-size:20px;
    line-height:1;
    border-radius:10px;
    /* Mismo motivo que en .btn--secundario: un contorno de boton necesita
       verse, y var(--line) no se ve. */
    border:1.5px solid #5a6577;
    background:#fff;
    color:var(--ink);
    cursor:pointer;
    transition:border-color .15s,color .15s,background .15s,box-shadow .15s
}
.btn-pag:hover:not(:disabled){
    border-color:var(--accent);
    color:var(--accent-txt);
    background:#fff2f7;
    box-shadow:0 1px 4px rgba(12,20,36,.12)
}
.btn-pag:disabled{opacity:.4;cursor:not-allowed}
.pag-info{flex:1;text-align:center;font-size:14.5px;font-weight:600;color:var(--muted)}

@media(max-width:640px){
    .mod-encab{flex-direction:column;align-items:stretch}
    .mod-filtros{flex:1 1 100%}
    .mod-filtros .campo{flex:1;min-width:0}
}

/* Botón CONFIRMAR de los comprobantes (f00npt y los siete que vienen).
   Verde, y distinto del "Guardar" azul a propósito: guardar deja el
   encabezado a salvo y el comprobante sigue pendiente; confirmar pasa las
   afectaciones al libro y lo cierra. Son dos acciones con consecuencias
   muy distintas y no deben parecerse. */
.btn--confirmar{ background:#15803d; border-color:#15803d }
.btn--confirmar:hover{ background:#166534; border-color:#166534 }

/* =====================================================================
   INFORMES — pantalla única de selección (f00inf/inform.php)
   =====================================================================
   Una lista de tarjetas con marca, DE A DOS POR LÍNEA. Se eligió tarjeta
   y no un <select> porque un informe necesita explicarse: el nombre solo
   no distingue "Afectaciones" de "Estado de Apropiaciones", y en un
   desplegable no cabe la frase que sí lo hace.

   Dos por línea y no una, porque se vienen más informes y en una sola
   columna la pantalla se vuelve un rollo que hay que bajar. Dos columnas
   es el punto en que todavía caben unos 60 caracteres por renglón —el
   ancho cómodo de lectura— y a la vez se ven el doble de opciones sin
   desplazarse.

   SOBRE EL TAMAÑO DE LA LETRA. La descripción va en 14.5px y en color de
   tinta, no en 13px gris. La costumbre de pintar el texto secundario más
   chico y más claro sirve cuando ese texto es decorativo; aquí NO lo es:
   la descripción es justamente lo que permite distinguir un informe de
   otro, así que es contenido, no adorno. Y la cursiva se quitó del todo:
   en tamaño pequeño es lo que más cuesta leer.

   El <input type="radio"> va DENTRO del <label>, así que toda la tarjeta
   es zona de clic sin necesidad de JS. */

.inf-lista{
    display:grid;
    grid-template-columns:repeat(2,minmax(0,1fr));
    gap:12px;
    align-items:stretch
}

.inf-op{
    display:flex;
    align-items:flex-start;
    gap:12px;
    padding:14px 16px;
    border:1px solid var(--line);
    border-radius:12px;
    background:#f9fafb;
    cursor:pointer;
    transition:border-color .18s,background .18s,box-shadow .18s
}
.inf-op:hover{border-color:#8a92a4;background:#fff}

/* La marca se ve, pero no manda: quien dice cuál está elegido es el
   borde de la tarjeta entera, que se lee de un vistazo desde lejos. */
.inf-op input[type="radio"]{
    margin:3px 0 0;
    width:18px;
    height:18px;
    flex:none;
    accent-color:var(--accent);
    cursor:pointer
}
.inf-op:has(input:checked){
    border-color:var(--accent);
    background:#fff;
    box-shadow:0 0 0 3px rgba(255,47,126,.12)
}

.inf-op-ico{
    font-size:21px;
    line-height:1.1;
    color:var(--icon);
    flex:none
}
.inf-op:has(input:checked) .inf-op-ico{color:var(--accent-txt)}

.inf-op-txt{display:flex;flex-direction:column;gap:4px;min-width:0}
.inf-op-tit{font-size:16px;font-weight:700;color:var(--ink);line-height:1.25}
.inf-op-des{font-size:14.5px;line-height:1.55;color:#2f3746}

/* El período se separa de la lista con una línea: es el único bloque de
   la pantalla que no es una elección entre informes. */
.inf-periodo{
    margin-top:22px;
    padding-top:18px;
    border-top:1px solid var(--line)
}

/* Por debajo de 900px las dos columnas dejan de caber sin partir
   palabras: se pasa a una. */
@media (max-width:900px){
    .inf-lista{grid-template-columns:1fr}
}
@media (max-width:640px){
    .inf-periodo .campo-full{width:100% !important}
}
