/* ==========================================================================
   PLANTILLA_BASE.CSS - Hoja de Estilos Principal del Sistema APM Trámites

   Ubicación: css/plantilla/ (antes form/usuarios_apm/). La carga
   form/config/header_css.php usando la constante APP_URL_PLANTILLA, por lo que
   está disponible para las páginas de cualquier módulo, no solo usuarios_apm.

   Reparto: aquí van las reglas que sirven a más de una página. En el <style> de
   cada página solo quedan las suyas (p. ej. anchos por columna del listado).
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. VARIABLES DE DISEÑO (Design Tokens)
   Define los colores de la marca, fondos, bordes, sombras y radios globales.
   -------------------------------------------------------------------------- */
:root {
    color-scheme: light;
    --primary: #2563eb;          /* Azul principal (botones principales, foco) */
    --primary-hover: #1d4ed8;    /* Azul al pasar el cursor (hover) */
    --secondary: #64748b;        /* Gris secundario para elementos neutros */
    --bg-page: #f8fafc;          /* Color de fondo general de la página */
    --bg-card: #ffffff;          /* Fondo blanco de los paneles/tarjetas */
    --text-main: #0f172a;        /* Color de texto principal (casi negro) */
    --text-muted: #475569;       /* Color de texto secundario/atenuado (etiquetas) */
    --border: #e2e8f0;           /* Color de bordes de tarjetas y tablas */
    /* Borde en reposo de las cajas de texto de formulario (sección 12).
       Es a propósito distinto de --border: `app.js` y `appg.js` validan en línea y, al pasar
       la validación, escriben `elemento.style.borderColor = '#ced4da'` como estilo inline
       (6 sitios). Un estilo inline gana a la hoja, así que si aquí pusiéramos --border el
       campo cambiaría de gris después del blur. Igualando el valor no se nota el cambio, y
       el borde rojo de error (`= 'red'`) sigue funcionando, cosa que un !important mataría.
       Si algún día se corrige ese color en el JS, cambiarlo aquí a la vez.
       Se deja SIN variante oscura a propósito (ver bloque [data-apm-theme="dark"] más abajo):
       forkearlo reabriría este mismo bug (el campo cambiaría de color al perder el foco). */
    --input-border: #ced4da;
    /* Altura única de los controles de una BARRA DE FILTROS (selects, cajas de texto y
       botones). Existía repetida a mano en las secciones 3, 4 y 9, y con valores que se
       contradecían entre sí — ver el comentario de la sección 9. Centralizada 2026-07-29:
       cambiar aquí para reescalar todas las barras de filtro del sistema de una vez. */
    --control-height: 27px;
    /* Altura de los controles de un FORMULARIO de captura (sección 12). Más alta a
       propósito: ahí el usuario escribe, no solo elige. */
    --control-height-form: 32px;
    --shadow: 0 4px 12px rgba(0,0,0,0.06); /* Sombra suave para tarjetas */
    --radius: 0.75rem;           /* Radio de redondeo de esquinas general */
    --th-padding-y: 0.8rem;      /* Alto/relleno vertical de la cabecera de la tabla */

    /* ---- Estado semántico (2026-09-04, modo oscuro) ----
       Nombra los ~5 grupos de color de estado que hasta ahora se repetían como hex suelto
       en botones, tarjetas KPI y desplegables (verde éxito ~9 veces, rojo peligro ~8, azul
       info 15+, ámbar warning ~7). --color-info se deja DISTINTO de --primary a propósito:
       son dos azules que ya conviven en el código (uno es la marca, el otro "informativo"),
       no colapsar. Los tres campos por grupo (color/-bg/-text) SÍ se redefinen en el bloque
       [data-apm-theme="dark"]: son colores de estado, tienen que seguir leyéndose sobre fondo
       oscuro. */
    --color-success: #16a34a;   --color-success-bg: #f0fdf4;   --color-success-text: #065f46;
    --color-danger:  #dc2626;   --color-danger-bg:  #fef2f2;   --color-danger-text:  #7f1d1d;
    --color-info:    #0284c7;   --color-info-bg:    #f0f9ff;   --color-info-text:    #0c4a6e;
    --color-warning: #d97706;   --color-warning-bg: #fffbeb;   --color-warning-text: #78350f;
    --color-neutral-bg: #f1f5f9; --color-neutral-text: #475569;

    /* ---- Cajas de aviso / callout (2026-09-04) ----
       Distintas de --color-success-bg etc. de arriba a propósito: aquellas son para un
       CHIP pequeño (icono de 24-38px, ver sección 13/13.c) que se lee bien como pastel claro
       incluso flotando sobre una tarjeta oscura. Estas son para una CAJA grande de texto
       (los recuadros "Se anularán N personas", "La anulación es definitiva", avisos de
       éxito/error dentro de un modal…) — ahí un rectángulo pastel claro ocupando media
       tarjeta oscura sí se lee como la misma "isla clara" que ya se corrigió en otros
       lados, así que estos SÍ tienen variante oscura (ver el bloque [data-apm-theme="dark"]
       más abajo). Los tres campos por grupo son fondo/borde/texto, en ese orden. */
    --alert-neutral-bg: #f8fafc; --alert-neutral-border: #cbd5e1; --alert-neutral-text: #334155;
    --alert-success-bg: #f0fdf4; --alert-success-border: #86efac; --alert-success-text: #166534;
    --alert-danger-bg:  #fef2f2; --alert-danger-border:  #fca5a5; --alert-danger-text:  #991b1b;
    --alert-info-bg:    #f0f9ff; --alert-info-border:    #7dd3fc; --alert-info-text:    #075985;
    --alert-warning-bg: #fffbeb; --alert-warning-border: #fde68a; --alert-warning-text: #92400e;

    /* ---- Superficies y texto sueltos (2026-09-04) ----
       Nombres para hex que se repetían sin variable. A diferencia de --text-main/--bg-card,
       que SÍ cambian de valor en el bloque [data-apm-theme="dark"] de abajo, estos NO se
       redefinen ahí: son tonos fijos para usos puntuales (texto sobre un chip/tinte claro
       que se queda claro en los dos temas, bordes de foco) que no necesitan invertirse. */
    --text-strong:   #0f172a;   --text-subtle: #94a3b8;   --text-faint: #cbd5e1;
    --border-strong: #cbd5e1;
    --primary-tint:  #eff6ff;   --primary-tint-hover: #dbeafe;
    /* ---- Texto/ícono sobre tinte de marca (2026-09-05) ----
       `--primary` (#2563eb) no se invierte en oscuro a propósito (sección 1.b): sirve de
       fondo sólido de botón con texto blanco, y aclararlo ahí rompería ESE contraste. Pero
       el mismo `--primary` se usaba también como COLOR DE TEXTO/ÍCONO sobre fondos que sí se
       oscurecen (`--primary-tint`, o directamente `--bg-card`) — el botón de tema, la
       insignia de usuario/empresa (`.user-badge`), las etiquetas de Área/Destino
       (`.credp-dd-chip`) y varios estados de `.credp-dd-*`. Medido: #2563eb sobre
       `--primary-tint` oscuro (#1e3a5f) da ~2.2:1; sobre `--bg-card` oscuro (#1e293b), ~2.8:1
       — muy por debajo de las 4.5:1 de un texto normal. `--primary-tint-text` es el token
       para ESE uso específico: igual a `--primary` en claro (cero cambio visual), más claro
       en oscuro. No sustituye a `--primary` en fondos de botón ni en bordes de foco. */
    --primary-tint-text: #2563eb;

    /* ---- Tablas de listado .table-modern (2026-09-28) ----
       Traídos del listado de visitas de instituciones de apmtramitesV2
       (frm_gestion_visitas_instituciones.php): marco con esquinas redondeadas, cabecera
       azul pálido y filas con rayado suave. Consumidos solo por la sección 5; con variante
       oscura en 1.b y candado de impresión en la sección 14. */
    --table-radius:        10px;
    --table-border:        #dfeaf5;   /* marco exterior de la tabla */
    --table-head-bg:       #eef7ff;
    --table-head-text:     #47698d;
    --table-head-border:   #d7e5f3;   /* línea bajo la cabecera */
    --table-row-bg:        #ffffff;   /* filas impares */
    --table-row-alt-bg:    #f8fbfe;   /* filas pares */
    --table-row-hover-bg:  #edf6ff;
    --table-cell-border:   #e4edf6;   /* separador entre filas */
    --table-cell-text:     #29445f;

    /* ---- Fondo de la vista (.page-content, sección 7) ---- */
    --page-bg:        #f2f7fc;
    --page-glow:      rgba(87, 174, 255, .13);
    --page-glow-size: 24%;
}

/* ==========================================================================
   1.b MODO OSCURO — bloque de variables

   Redefine lo que tiene que invertirse: fondo/texto/borde/sombra, el tinte de marca
   que usa .user-badge, y --color-neutral-bg/-text (la única pareja de "estado" que SÍ
   se redefine aquí: a diferencia de success/danger/info/warning, que son acentos
   saturados pensados para destacar sobre cualquier fondo, --color-neutral-bg es una
   superficie gris plana de baja saturación — cabecera de tabla, campo de solo lectura —
   y una franja gris clara sobre una tarjeta oscura se lee como un error de contraste,
   no como una decisión de diseño). Los --color-success/-danger/-info/-warning y sus
   -bg/-text SÍ se dejan fijos: son colores de estado saturados, legibles sobre fondo
   oscuro tal cual — cambiarlos sería un rediseño de paleta, no una inversión de tema.
   --input-border y --text-strong/-subtle/-faint/-border-strong tampoco se tocan, ver
   los comentarios en :root de arriba. */
:root[data-apm-theme="dark"] {
    color-scheme: dark;
    --bg-page:  #0f172a;
    --bg-card:  #1e293b;
    --text-main: #e2e8f0;
    --text-muted: #94a3b8;
    --border:    #334155;
    --primary-tint-text: #38bdf8;
    /* rgba(0,0,0,0.06) es correcto en claro pero invisible sobre fondo oscuro: no se
       puede compartir el mismo valor entre los dos temas. */
    --shadow:    0 4px 16px rgba(0,0,0,0.45);
    --primary-tint:       #1e3a5f;
    --primary-tint-hover: #234876;
    --color-neutral-bg:   #273449;
    --color-neutral-text: #94a3b8;

    /* Cajas de aviso: en oscuro se invierte la relación (fondo saturado oscuro + texto claro
       del mismo tono), el mismo patrón que usa Bootstrap 5.3 para sus propias variables
       `--bs-*-bg-subtle`/`--bs-*-text-emphasis` en `[data-bs-theme=dark]` — no se reutilizan
       esas porque su paleta exacta no coincide con la de este proyecto (ver el comentario de
       arriba) y se habría corrido el matiz en claro; se define la propia, con la misma
       filosofía. */
    --alert-neutral-bg: #1e293b; --alert-neutral-border: #334155; --alert-neutral-text: #e2e8f0;
    --alert-success-bg: #052e16; --alert-success-border: #15803d; --alert-success-text: #86efac;
    --alert-danger-bg:  #3f1212; --alert-danger-border:  #991b1b; --alert-danger-text:  #fca5a5;
    --alert-info-bg:    #0c2d3d; --alert-info-border:    #0369a1; --alert-info-text:    #7dd3fc;
    --alert-warning-bg: #3d2c05; --alert-warning-border: #a16207; --alert-warning-text: #fde68a;

    /* Tablas .table-modern: mismos valores que el modo oscuro de apmtramitesV2. Las filas
       pares son apenas más claras que las impares (rayado discreto); el hover sí destaca. */
    --table-border:        #324a62;
    --table-head-bg:       #22384e;
    --table-head-text:     #b9cee3;
    --table-head-border:   #3b536b;
    --table-row-bg:        #18283b;
    --table-row-alt-bg:    #1b2d42;
    --table-row-hover-bg:  #243b54;
    --table-cell-border:   #2e4358;
    --table-cell-text:     #dbe8f5;

    /* Fondo de la vista, modo oscuro de apmtramitesV2. */
    --page-bg:        #101b2a;
    --page-glow:      rgba(41, 130, 220, .13);
    --page-glow-size: 25%;

    /* ---- Variables de Bootstrap 5 (H.1) ----
       `otras_libs/datatable-2.3.8/datatables.css` (Bootstrap 5.3.0 embebido, ver doc B) y
       `otras_libs/bootstrap-5.3.8/dist/css/bootstrap.min.css` (el real) traen CADA UNO su
       propio bloque `[data-bs-theme=dark] { --bs-body-bg:#212529; --bs-body-color:#adb5bd;
       ... }`, que SÍ consumen selectores reales (`.form-control`, `.dropdown-menu`,
       `.modal-content`). El toggle (js/apm_tema.js) pone `data-bs-theme="dark"` a la vez que
       `data-apm-theme="dark"` — sin esto, cualquier componente Bootstrap sin clase `-modern`
       (un `<select>`/`form-control` a secas, un `.modal-content` sin cabecera propia, un
       `.dropdown-menu`) pasaría a los grises de fábrica (#212529/#adb5bd), que no pegan con
       la paleta de arriba. Esta hoja se carga DESPUÉS de los dos Bootstrap (ver doc E), así
       que estas declaraciones ganan por orden de cascada sin necesitar más especificidad ni
       !important. */
    --bs-body-bg: var(--bg-page);
    --bs-body-color: var(--text-main);
    --bs-border-color: var(--border);
    --bs-modal-bg: var(--bg-card);
    --bs-dropdown-bg: var(--bg-card);
    --bs-dropdown-color: var(--text-main);
    --bs-dropdown-link-color: var(--text-main);
    --bs-dropdown-link-hover-bg: var(--bg-page);
    --bs-dropdown-link-hover-color: var(--text-main);
    /* `<body class="bg-light">` es boilerplate en ~55 paginas (ninguna lo puso pensando en
       modo oscuro, ya estaba desde antes de este trabajo) -- `.bg-light` de Bootstrap trae su
       propio `!important` y por eso siempre le gano por ORDEN, nunca por especificidad, a un
       `body { background: var(--bg-page) }` normal de la seccion 2. En claro no se notaba
       (su gris de fabrica #f8f9fa es casi identico a --bg-page claro); en oscuro, sin esto,
       el body entero quedaba pintado de la variable equivocada. Redeclarar el RGB que
       consume `.bg-light` es mas simple y de paso correcto en cualquier otro `.bg-light`
       suelto (hay 4 mas, cajas de aviso dentro de un par de modales) -- ver el detalle de la
       trampa completa en (E) de CLAUDE.md. */
    --bs-light-rgb: 15, 23, 42;
}

/* --------------------------------------------------------------------------
   2. ESTILOS BASE Y CABECERA FIJA
   -------------------------------------------------------------------------- */
body {
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    background: var(--bg-page);
    color: var(--text-main);
    line-height: 1.5;
}

/* Bootstrap 5 quito el margen inferior que BS4 daba por defecto a <label>. Los
   formularios antiguos compensan con margin-top negativo en inputs/textareas, asi
   que sin este margen los titulos se montan sobre las cajas. Estaba repetido en el
   <style> de cada pagina migrada; se centraliza aqui. */
label {
    margin-bottom: 0.5rem;
}

/* Agrupa el alternador de tema con la insignia de usuario, en las dos variantes de
   cabecera (header_imagen.css / header_con_logo.css comparten esta clase — ver doc E). */
.apm-header-actions {
    display: flex;
    align-items: center;
    gap: 0.6rem;
}

/* Imagen original de Inicio en las cabeceras autonomas de usuarios. */
.apm-home-icon {
    display: inline-block;
    width: 25px;
    height: 25px;
    object-fit: contain;
    flex-shrink: 0;
    vertical-align: middle;
}

/* Alternador de tema (js/apm_tema.js). Mismo círculo de 38px que .kpi-tile-icon (sección
   13.c), mismo tinte de marca — es el mismo lenguaje visual que el resto de la cabecera. */
.apm-theme-toggle-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border-radius: 50%;
    border: 1px solid var(--primary-tint-hover);
    background: var(--primary-tint);
    color: var(--primary-tint-text);
    font-size: 1rem;
    cursor: pointer;
    transition: background 0.2s, transform 0.2s;
}

.apm-theme-toggle-btn:hover {
    background: var(--primary-tint-hover);
    transform: scale(1.05);
}

.apm-theme-toggle-btn:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

/* Dropdown del badge de usuario/empresa (header_body.php + js/apm_user_menu.js).
   Reusa .dropdown-menu/.dropdown-item de Bootstrap con texto blanco en oscuro.
   El boton conserva el aspecto de .user-badge (header_imagen.css/header_con_logo.css)
   y cada item distribuye su icono y texto en una fila. */
.apm-user-menu {
    position: relative;
}

.apm-user-menu-btn {
    font: inherit;
    cursor: pointer;
    max-width: 220px;
}

/* Ancho fijo reducido a proposito: un nombre/razon social largo (hay de sobra en el
   modulo externo, ej. "APM & TECNOLOGICO DESARROLLO-WEB & RZ..." ) no debe estirar la
   cabecera. Se trunca aqui con elipsis + `title` (ver header_body.php) para el hover;
   el nombre completo siempre se puede leer entero dentro del panel desplegado
   (`.apm-user-menu-name`, sin este límite). */
.apm-user-menu-label {
    display: inline-block;
    max-width: 140px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: middle;
}

.apm-user-menu-caret {
    font-size: 0.65rem;
    margin-left: 0.1rem;
    transition: transform 0.2s;
}

.apm-user-menu-btn[aria-expanded="true"] .apm-user-menu-caret {
    transform: rotate(180deg);
}

.apm-user-menu-panel {
    min-width: 240px;
}

/* Colores locales del menu: Bootstrap declara estas variables en .dropdown-menu,
   por lo que no hereda las del bloque 1.b. El nombre tambien necesita un color
   explicito para ganar a las reglas de h6 propias de algunas paginas. */
:root[data-apm-theme="dark"] .apm-user-menu-panel {
    --bs-dropdown-color: #fff;
    --bs-dropdown-link-color: #fff;
    --bs-dropdown-link-hover-color: #fff;
    --bs-dropdown-header-color: #fff;
}

:root[data-apm-theme="dark"] .apm-user-menu-panel .apm-user-menu-name {
    color: var(--bs-dropdown-header-color);
}

.apm-user-menu-panel .apm-user-menu-name {
    white-space: normal;
    line-height: 1.3;
}

.apm-user-menu-panel .dropdown-item {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    font-size: 0.9rem;
}

.apm-user-menu-panel .dropdown-item i {
    width: 1.1rem;
    text-align: center;
    color: var(--text-muted);
}

.apm-user-menu-panel .dropdown-item.text-danger i {
    color: var(--color-danger);
}

/* Cabecera superior fija en la parte alta de la pantalla */
.top-header {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: var(--header-height);
    background: var(--bg-card);
    border-bottom: 1px solid var(--border);
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 2rem;
    z-index: 1030;
    box-shadow: 0 2px 8px rgba(0,0,0,0.04);
}

/* --------------------------------------------------------------------------
   3. TARJETAS Y CONTENEDORES DE FILTROS (.card-modern)
   -------------------------------------------------------------------------- */
/* Tarjeta principal que envuelve los formularios de filtro y tablas */
.card-modern {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 0.5rem 1.25rem 1.25rem 1.25rem;
    margin-bottom: 1.25rem;
}

/* Título de la tarjeta con línea decorativa inferior en azul */
.card-title-modern {
    margin-top: 0;
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--text-main);
    margin-bottom: 0.35rem;
    padding-bottom: 0.5rem;
    border-bottom: 2px solid var(--primary);
    display: inline-block;
}

/* Grid responsivo para colocar los filtros en columnas cuadradas */
.filter-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 1rem;
    align-items: end;
}

/* Etiquetas (labels) sobre los campos de filtro */
.form-label-modern {
    font-weight: 600;
    color: var(--text-muted);
    margin-bottom: 0.25rem !important;
    font-size: 0.82rem;
}

/* Inputs y Selects modernos con tamaño compacto de 27px de altura.
   `.form-control-modern` va con `:not(textarea)` desde 2026-09-14 — ver el porqué justo debajo,
   en el bloque de textareas, que es donde de verdad importa. */
input.form-control-modern,
select.form-control-modern,
select.form-select-modern,
.form-select-modern,
.form-control-modern:not(textarea) {
    background-color: var(--bg-card);
    color: var(--text-main);
    border-radius: 4px !important;
    border: 1px solid var(--border);
    padding: 0.2rem 0.5rem !important;
    font-size: 0.81rem !important;
    height: var(--control-height) !important;
    min-height: var(--control-height) !important;
    max-height: var(--control-height) !important;
    line-height: 1.25 !important;
    transition: border-color 0.2s, box-shadow 0.2s;
}

/* Textareas modernas: altura dinámica, crecimiento automático y redimensionamiento vertical libre.
   Bug real 2026-09-14: el bloque de arriba (input/select "compactos de 27px") incluía el selector
   desnudo `.form-control-modern`, que también hace match con cualquier `<textarea
   class="form-control-modern">` — y como este bloque de aquí abajo nunca declaró `height`/
   `max-height` propios, esas dos propiedades se colaban sin competencia desde el bloque de 27px
   con `!important`. Resultado: el textarea quedaba con `max-height:27px` fijo pasara lo que
   pasara — ni arrastrar el tirador de resize podía crecer más allá de eso, y encima
   `height:27px !important` sobrevivía a cualquier `el.style.height=...` que el `autoExpand()` de
   cada página escribiera en línea (un `!important` de hoja siempre le gana a un `style=""` sin
   `!important`). Arreglado en las dos puntas: arriba se excluyó `textarea` del selector de 27px
   con `:not(textarea)`, y aquí `min-height`/`max-height` sí llevan `!important` (ya no compiten
   con nada) pero **`height` NO lleva `!important`** — a propósito, para que el `style=""` inline
   que escribe `autoExpand()` (JS de cada página) lo pueda seguir sobreescribiendo sin trabas. */
textarea.form-control-modern,
textarea.form-textarea-modern,
textarea.auto-expand,
textarea.plz-auto-expand {
    background-color: var(--bg-card);
    color: var(--text-main);
    border-radius: 4px;
    border: 1px solid var(--border);
    padding: 0.35rem 0.5rem;
    font-size: 0.81rem;
    height: auto;
    min-height: 34px !important;
    max-height: none !important;
    resize: vertical !important;
    line-height: 1.4;
    box-sizing: border-box;
    transition: border-color 0.2s, box-shadow 0.2s;
}

/* Estado al hacer clic o dar foco a las cajas de selección/texto */
.form-select-modern:focus,
.form-control-modern:focus,
select.form-select-modern:focus,
input.form-control-modern:focus {
    border-color: var(--primary) !important;
    box-shadow: 0 0 0 3px rgba(37,99,235,0.15) !important;
    outline: none !important;
}

/* --------------------------------------------------------------------------
   4. BOTONES DEL SISTEMA (.btn-modern y genéricos de filtro)
   -------------------------------------------------------------------------- */
/* Botones modernos (azul por defecto, ej. "Mostrar" o "Buscar"), a la misma altura que los
   demás controles de la barra de filtros. Hasta 2026-07-29 declaraba `min-height: 35px` junto
   a `height: 27px` y `max-height: 30px`: las tres se contradicen y en la cascada gana
   min-height, así que salían a 35px. Ahora todo cuelga de --control-height.
   Los botones de pie de formulario van más altos a propósito: ver sección 12. */
.btn-modern,
.btn-modern-success,
.btn-modern-danger,
.btn-modern-info,
.btn-modern-warning,
.btn-modern-secondary {
    background: var(--primary);
    border: none;
    padding: 0.2rem 0.75rem !important;
    font-size: 0.81rem !important;
    height: var(--control-height) !important;
    min-height: var(--control-height) !important;
    max-height: var(--control-height) !important;
    line-height: 1.25 !important;
    border-radius: 4px !important;
    color: white;
    font-weight: 500;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    gap: 0.35rem;
    transition: all 0.2s;
    cursor: pointer;
}

/* Efecto al pasar el mouse sobre el botón azul principal */
.btn-modern:hover {
    background: var(--primary-hover);
    transform: translateY(-1px);
    box-shadow: 0 3px 8px rgba(37,99,235,0.25);
}

/* Variante verde del botón moderno (ej. Exportar o Agregar) */
.btn-modern-success {
    background: var(--color-success);
}

/* Efecto al pasar el mouse sobre el botón verde */
.btn-modern-success:hover {
    background: #15803d;
    transform: translateY(-1px);
    box-shadow: 0 3px 8px rgba(22,163,74,0.25);
}

/* Resto de variantes. Hasta 2026-07-29 estas cuatro clases existían en el selector
   de arriba pero NO tenían color propio, así que salían azules igual que .btn-modern:
   un "Retornar" y un "Guardar" quedaban indistinguibles. */
.btn-modern-secondary { background: var(--secondary); }
.btn-modern-secondary:hover {
    background: #475569;
    transform: translateY(-1px);
    box-shadow: 0 3px 8px rgba(100,116,139,0.25);
}

.btn-modern-danger { background: var(--color-danger); }
.btn-modern-danger:hover {
    background: #b91c1c;
    transform: translateY(-1px);
    box-shadow: 0 3px 8px rgba(220,38,38,0.25);
}

.btn-modern-info { background: var(--color-info); }
.btn-modern-info:hover {
    background: #0369a1;
    transform: translateY(-1px);
    box-shadow: 0 3px 8px rgba(2,132,199,0.25);
}

.btn-modern-warning { background: var(--color-warning); }
.btn-modern-warning:hover {
    background: #b45309;
    transform: translateY(-1px);
    box-shadow: 0 3px 8px rgba(217,119,6,0.25);
}

/* Botón "decisión pendiente" del módulo de autorización de ingresos (form/usuarios_apm) —
   agregado 2026-08-31, punto 10/13/23/35 de pendientes-flujo-facturacion-credenciales-2026-08-31.
   Sustituye a `btn-warning text-dark` (amarillo #ffc107 de Bootstrap con texto negro, que el
   usuario pidió cambiar por no verse bien) en los botones cuyo clic dispara una decisión abierta
   (autorizar/rechazar, habilitar/inhabilitar, enviar a autorización) — nunca un resultado fijo
   como Retornar (rojo) o Anular (gris). Mismo ámbar `#d97706`/`#b45309` que ya usa `.btn-modern-
   warning` y los encabezados en degradado de los modales de advertencia del módulo (M.4), para no
   introducir un tercer tono. A propósito NO se sobreescribe `.btn-warning` de Bootstrap a secas:
   esa clase la usan páginas de todo el proyecto fuera de este módulo y un cambio global habría
   sido un efecto colateral no pedido. Se aplica ENCIMA de `btn btn-sm/btn-xs`, así que conserva el
   tamaño/padding de Bootstrap de cada botón — no compite con `.btn-modern-warning` de la sección
   3 (barras de filtro, 27px fijos por `--control-height`), pensada para otro contexto. */
.btn-credp-warning,
.btn-credp-warning:not(:disabled) {
    background-color: var(--color-warning) !important;
    border-color: var(--color-warning) !important;
    color: #fff !important;
}
.btn-credp-warning:hover,
.btn-credp-warning:focus {
    background-color: #b45309 !important;
    border-color: #b45309 !important;
    color: #fff !important;
}

/* Regla forzada para que TODOS los botones de filtro dentro de tarjetas coincidan en altura (27px).
   Se excluye .btn-default: esa clase es de Bootstrap 3, ya no existe en BS5 y hoy solo la llevan
   las "etiquetas" de texto que generan los .php de listados dentro de las tablas (ver seccion 5).
   Se excluyen tambien .toggle y sus elementos hijos (.toggle-handle, .toggle-on, .toggle-off):
   bootstrap4-toggle envuelve cada <input data-toggle="toggle"> en un <div class="toggle btn ...">
   y crea <label class="btn toggle-on">, <label class="btn toggle-off"> y <span class="toggle-handle btn">.
   Sin esta exclusion completa, el interruptor y su franja blanca perian su tamano propio y
   salian recortados/desalineados. */
.card-modern .btn:not(.btn-default):not(.toggle):not(.toggle-handle):not(.toggle-on):not(.toggle-off),
.filter-grid .btn:not(.btn-default):not(.toggle):not(.toggle-handle):not(.toggle-on):not(.toggle-off),
.filter-row-grid .btn:not(.btn-default):not(.toggle):not(.toggle-handle):not(.toggle-on):not(.toggle-off) {
    padding: 0.2rem 0.75rem !important;
    font-size: 0.81rem !important;
    height: var(--control-height) !important;
    min-height: var(--control-height) !important;
    max-height: var(--control-height) !important;
    line-height: 1.25 !important;
    border-radius: 4px !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    gap: 0.35rem !important;
}

/* --------------------------------------------------------------------------
   5. ESTILOS DE TABLAS DE DATOS (.table-modern)
   -------------------------------------------------------------------------- */
/* Ajuste de contenedor responsivo dentro de tarjetas.
   .card-modern tiene ademas 1px de borde (sección 3), asi que el hueco que se ve a
   simple vista entre el BORDE de la tarjeta y la tabla = 1px (borde) + 1.25rem (20px,
   padding) + var(--table-margin-x). Con -16px quedan 5px visibles ahi, en ambos
   extremos -- igualado contra producción (#9 lista de debug, 2026-09-21; medido con
   getBoundingClientRect() desde el borde de .card-modern hasta .table-responsive).
   Es la unica variable a tocar para cambiar ese aire de forma global. */
.card-modern .table-responsive {
    --table-margin-x: -16px;
    margin-left: var(--table-margin-x);
    margin-right: var(--table-margin-x);
}

/* Anular márgenes laterales sobrantes de Bootstrap/DataTables */
.card-modern .table-responsive .dt-container .row.dt-layout-table {
    --bs-gutter-x: 0rem;
}

/* Selector de registros más ancho y cómodo en DataTables (evita solapamiento entre número y flecha) */
div.dt-container div.dt-length select,
.dataTables_wrapper .dataTables_length select {
    min-width: 68px !important;
    padding: 0.2rem 1.6rem 0.2rem 0.6rem !important;
    height: var(--control-height, 27px) !important;
    min-height: var(--control-height, 27px) !important;
    line-height: 1.25 !important;
    border-radius: 4px !important;
    display: inline-block !important;
    vertical-align: middle !important;
}

/* Configuración general de la tabla moderna de listados */
.table-modern {
    --table-width: 100%;
    width: var(--table-width) !important;
    table-layout: fixed;
    border-collapse: separate;
    border-spacing: 0;
    /* Marco con esquinas redondeadas (2026-09-28, diseño de apmtramitesV2). Sin
       overflow:hidden a proposito: recortaria cualquier menu o aviso que se abra dentro de
       una celda. El redondeo lo dan las cuatro celdas de esquina (reglas de mas abajo). */
    border: 1px solid var(--table-border);
    border-radius: var(--table-radius);
    /* Bootstrap pinta cada celda con --bs-table-bg (background-color) y encima un
       box-shadow inset con --bs-table-bg-state para el hover. El rayado y el hover de
       abajo cambian --bs-table-bg por fila; el overlay de hover de Bootstrap se anula
       dejando su color transparente, para que no oscurezca el azul propio. */
    --bs-table-bg: var(--table-row-bg);
    --bs-table-color: var(--table-cell-text);
    --bs-table-border-color: var(--table-cell-border);
    --bs-table-hover-bg: transparent;
    --bs-table-hover-color: var(--table-cell-text);
}

/* Esquinas: el radio interior es el exterior menos el 1px del marco. */
.table-modern > thead > tr:first-child > :first-child { border-top-left-radius: calc(var(--table-radius) - 1px); }
.table-modern > thead > tr:first-child > :last-child  { border-top-right-radius: calc(var(--table-radius) - 1px); }
.table-modern > tbody > tr:last-child > :first-child  { border-bottom-left-radius: calc(var(--table-radius) - 1px); }
.table-modern > tbody > tr:last-child > :last-child   { border-bottom-right-radius: calc(var(--table-radius) - 1px); }

/* Celda de encabezado de tabla (THEAD TH) */
.table-modern thead th {
    --bs-table-bg: var(--table-head-bg);
    --bs-table-color: var(--table-head-text);
    background: var(--bs-table-bg) !important;
    color: var(--bs-table-color) !important;
    /* 600 y no el 800 de apmtramitesV2: se conserva el peso que ya tenia este proyecto. */
    font-weight: 600;
    text-transform: uppercase;
    font-size: 0.7rem;
    letter-spacing: 0.025em;
    border-bottom: 1px solid var(--table-head-border);
    padding: var(--th-padding-y) 0.35rem;
    /* Sin overflow:hidden ni ellipsis: el titulo se parte en dos lineas antes que
       recortarse. DataTables mete el titulo en un flex (.dt-column-header) junto a
       la flecha de orden (12px), asi que en columnas estrechas el espacio real es
       bastante menor que el ancho de la celda. */
    white-space: normal;
    overflow-wrap: break-word;
    vertical-align: bottom;
}

.table-modern thead th .dt-column-title {
    min-width: 0;
    line-height: 1.15;
}

/* Celdas de cuerpo de la tabla (TBODY TD) */
.table-modern tbody td {
    padding: 0.72rem 0.35rem;
    vertical-align: top;
    border-bottom: 1px solid var(--table-cell-border);
    font-size: 0.825rem;
    color: var(--table-cell-text);
    word-break: break-word;
    overflow-wrap: break-word;
}

/* Separador entre filas de 2px, como en apmtramitesV2: cada celda lleva 1px arriba y 1px
   abajo del mismo color. estilos2.css (herencia de Bootstrap 4) ya ponia ese border-top,
   pero fijo en #dee2e6 (gris claro tambien en oscuro); aqui se reescribe con el token.
   La cabecera no lleva linea superior: la da el marco de la tabla. */
.table-modern > thead > tr > th {
    border-top: 0;
}
.table-modern > tbody > tr > td {
    border-top: 1px solid var(--table-cell-border);
}

/* Rayado: filas pares un tono mas claro/azulado. */
.table-modern > tbody > tr:nth-child(even) > * {
    --bs-table-bg: var(--table-row-alt-bg);
}

/* Hover de la fila. El segundo selector iguala en especificidad al hover de DataTables
   (`table.table.dataTable.table-hover > tbody > tr:hover > *`, que mete un box-shadow
   gris) y gana por orden de carga. */
.table-modern > tbody > tr:hover > * {
    --bs-table-bg: var(--table-row-hover-bg);
}
table.table.dataTable.table-modern > tbody > tr:hover > * {
    box-shadow: none;
}

/* Ultima persona utilizada en las nominas; independiente del hover y del rayado. */
table.table.dataTable.table-modern[data-apm-fila-activa] > tbody > tr.apm-fila-activa > * {
    --bs-table-bg: var(--primary-tint-hover);
    --bs-table-bg-state: var(--primary-tint-hover);
    --bs-table-accent-bg: transparent;
    background-color: var(--primary-tint-hover);
    box-shadow: none;
}
table.table.dataTable.table-modern[data-apm-fila-activa] > tbody > tr.apm-fila-activa > :first-child {
    box-shadow: inset 3px 0 0 var(--primary-tint-text);
}

/* Etiquetas heredadas de Bootstrap 3 dentro de los listados.
   Los .php que arman las filas (reg_atencion_tramite.php y similares) no usan
   <button class="btn btn-default btn-xs"> como boton, sino como etiqueta de texto de
   varias lineas: dentro llevan varios <span> separados por <br> ("VALIDO HASTA" + la
   fecha, "VIGENTE", etc.). Como .btn-default es de Bootstrap 3 y no existe en BS5,
   solo la llevan esas etiquetas; los botones de accion reales (btn-info, btn-danger,
   btn-primary...) no entran aqui y conservan el aspecto uniforme de 27px.
   Sin esta regla heredan el inline-flex de la regla de botones de filtro: cada <span>
   pasa a ser un item flexible que se encoge y el texto acaba dibujado letra por letra
   en vertical. El margin-top:0 anula los margenes negativos en linea (-17px/-10px)
   que solo tenian sentido con la altura de boton de BS3. */
.table-modern .btn-default {
    display: inline-block !important;
    background: transparent !important;
    border: none !important;
    box-shadow: none !important;
    height: auto !important;
    min-height: 0 !important;
    max-height: none !important;
    margin-top: 0 !important;
    padding: 0 0.3rem !important;
    /* Interlineado en valor ABSOLUTO a proposito: estos botones traen
       font-size:1rem en linea, asi que un valor relativo (1.2) se multiplica por
       esos 16px y deja renglones de ~19px aunque el texto visible sea de 8-10px.
       Con 12px cada renglon mide 12px de verdad. Este es el numero a mover si se
       quiere mas o menos aire entre las lineas de las etiquetas. */
    line-height: 9px !important;
    white-space: normal;
    text-align: center;
    vertical-align: top;
}

/* Las imagenes de celda (iconos PDF) son inline: sin esto se apoyan en la linea
   base y arrastran el hueco del descendente debajo. */
.table-modern tbody td img {
    vertical-align: top;
}

/* Última columna de acciones (iconos o botones pequeños de la derecha) */
.table-modern thead th:last-child,
.table-modern tbody td:last-child {
    width: 48px;
    text-align: center;
    padding-left: 0.25rem;
    padding-right: 0.25rem;
}

/* Botones de accion de esa ultima columna: cuadrados perfectos.
   Venian con el tamano de los botones de filtro (alto 27px pero ancho libre, con
   0.75rem de relleno lateral), asi que en una columna de 48px el contenido se
   partia y quedaban rectangulos irregulares. Se fija la caja y se anula el
   relleno; el contenido se centra solo.
   Se limita a td:last-child a proposito: es donde viven las acciones. Otros
   listados tienen en las celdas botones con texto ("AGREGAR POLIZA") que no
   deben volverse cuadrados. */
.table-modern tbody td:last-child .btn:not(.btn-default) {
    width: 30px !important;
    height: 30px !important;
    min-width: 30px !important;
    min-height: 30px !important;
    max-width: 30px !important;
    max-height: 30px !important;
    padding: 0 !important;
    margin: 1px 0 !important;
    gap: 0 !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    border-radius: 4px !important;
    line-height: 1 !important;
    overflow: hidden;
}

/* Icono y etiqueta ("1A", "1B", "_2"...) apilados dentro del cuadrado. El PHP
   los mete a los dos dentro del mismo <span>, y en un caso el texto va dentro
   del propio <i>, asi que hay que convertir ambos en contenedores para poder
   apilar. La etiqueta es el texto suelto, que pasa a ser un item anonimo. */
.table-modern tbody td:last-child .btn:not(.btn-default) > span,
.table-modern tbody td:last-child .btn:not(.btn-default) > i {
    display: inline-flex !important;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1px;
    font-size: 8px !important;
    line-height: 1 !important;
    font-style: normal;
    letter-spacing: 0;
}

/* El glifo de Font Awesome, con tamano propio: si heredase el de la etiqueta
   (8px, y ademas fa-xs lo multiplica por 0.75) quedaria ilegible. */
.table-modern tbody td:last-child .btn:not(.btn-default) i::before {
    font-size: 11px;
    line-height: 1;
}

/* Botones de acción sin etiqueta (como .btn-outline-apm con <i class="fas fa-edit"></i>):
   al no llevar etiqueta apilada, el glifo mide 13px para mejorar la legibilidad y presencia. */
.table-modern tbody td:last-child .btn-outline-apm i::before {
    font-size: 13px;
}

/* --------------------------------------------------------------------------
   6. CAPA Y ANIMACIÓN DE CARGA (LOADER / SPINNER)
   -------------------------------------------------------------------------- */
/* Capa transparente translúcida que cubre la tabla durante el AJAX */
.loader-overlay {
    position: absolute;
    inset: 0;
    background: rgba(255,255,255,0.85);
    backdrop-filter: blur(4px);
    display: none;
    align-items: center;
    justify-content: center;
    z-index: 50;
    border-radius: var(--radius);
}

/* Círculo giratorio de carga */
.spinner-modern {
    width: 40px;
    height: 40px;
    border: 4px solid var(--border);
    border-top-color: var(--primary);
    border-radius: 50%;
    animation: spin 0.8s linear infinite;
}

@keyframes spin {
    to { transform: rotate(360deg); }
}

/* Texto bajo el spinner giratorio (ej. "Cargando...") */
.loader-text {
    margin-top: 0.75rem;
    font-size: 0.9rem;
    color: var(--text-muted);
    font-weight: 500;
}

/* Variante por ID del mismo patron: es la que usan los listados con AJAX
   (app.js hace $('#loader-overlay').show()/.hide() sobre la tabla). Estaba
   repetida en el <style> de cada pagina; se centraliza aqui. */
#container-tramites {
    position: relative;
    width: 100%;
    margin: 2px 0;
}

#loader-overlay {
    display: none;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(255, 255, 255, 0.9);
    z-index: 1000;
    pointer-events: none;
}

.spinner-container {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    text-align: center;
}

.spinner {
    width: 45px;
    height: 45px;
    border: 5px solid #f3f3f3;
    border-top: 5px solid #e74c3c;
    border-radius: 50%;
    animation: spin 1s linear infinite;
    margin: 0 auto 12px auto;
}

#loader-overlay .loader-text {
    font-size: 15px;
    color: #d35400;
    font-weight: bold;
}

/* --------------------------------------------------------------------------
   7. DISPOSICIÓN Y SCROLL DE PÁGINA / SIDEBAR
   -------------------------------------------------------------------------- */
.sidebar-wrapper {
    position: fixed;
    top: 0px;
}

/* Fondo de la vista (2026-09-28): el de frm_gestion_visitas_instituciones.php de
   apmtramitesV2 — gris azulado claro con un halo azul suave arriba a la derecha. Va en
   .page-content y no en --bg-page, porque ese token lo usan tambien hovers, paneles y
   filas especiales que no deben cambiar de tono. Colores en --page-bg/--page-glow
   (sección 1 y 1.b); la sección 14 lo quita al imprimir. */
.page-content {
    background:
        radial-gradient(circle at 78% 8%, var(--page-glow), transparent var(--page-glow-size)),
        var(--page-bg);
    margin-top: 0;
    padding: 0rem;
    height: 100vh;
    overflow-y: auto !important;
    overflow-x: hidden !important;
}

/* Botón con contorno redondeado tipo píldora */
.btn-outline-apm {
    border: 1px solid #cfdee9;
    border-radius: 40px;
    color: #2c5f7a;
    transition: 0.2s;
}

.btn-outline-apm:hover {
    background: #0a2b3e;
    color: white;
    border-color: #0a2b3e;
}

/* Ajuste de scroll general en html, body y page-wrapper para evitar doble scroll vertical */
html,
body {
    overflow: hidden !important;
    height: 100% !important;
}

.page-wrapper.chiller-theme {
    overflow: hidden !important;
    height: 100vh !important;
    min-height: 100%;
}

/* Contenedor principal responsivo */
.container-fluid_xxx {
    width: 100%;
    padding: 0 0.5rem;
    box-sizing: border-box;
}

/* --------------------------------------------------------------------------
   8. INTEGRACIÓN CON DATATABLES (Buscador, Paginar, Botones)
   -------------------------------------------------------------------------- */
.dataTables_wrapper .dataTables_filter,
div.dt-search {
    margin-bottom: 0.6rem;
}

.dataTables_wrapper .dataTables_paginate,
div.dt-paging {
    float: right;
}

.dataTables_wrapper .dataTables_info,
div.dt-info {
    float: left;
}

/* Ocultar botones por defecto de DataTables (Copiar, CSV, PDF) */
.dt-buttons {
    display: none !important;
}

.dataTables_wrapper {
    width: 100%;
    overflow-x: auto;
}

/* Indicador de orden de las columnas.
   DataTables 2 lo dibuja con dos triangulos sueltos y sin asta ("\25B2"/"\25BC"),
   colocados uno ENCIMA del otro (:before con bottom:50% y :after con top:50%,
   ambos absolutos dentro de un .dt-column-order de 12x20px) y practicamente
   invisibles: heredan el gris del encabezado con opacity 0.125.
   NORMA DE DISEÑO (fijada 2026-08-04, a partir de `polizas en dir-financiera.php`):
   las flechas van SIEMPRE a la derecha del titulo, pequeñas y elevadas respecto
   a la linea base del texto -- como un exponente matematico (x²). No van
   centradas ni a tamaño completo: son una nota junto al titulo, no un elemento
   con el mismo peso visual. Al ser una unica regla centralizada aqui, el cambio
   alcanza de golpe a TODAS las tablas modernizadas (misma logica que el resto de
   la hoja, ver la "Regla de reparto" mas arriba); no hace falta tocar cada
   pagina. Aplicar este mismo criterio en toda modernizacion futura -- no
   reinventar el indicador de orden pagina por pagina.
   Los selectores replican los de datatables.css, asi que ganan por orden en la
   cascada: plantilla_base.css se carga despues (header_css.php va tras el <link>
   de datatables en el <head> de cada pagina). No hace falta !important. */

/* 1. El contenedor deja de ser una caja fija de 12x20 y pasa a ser una fila
      compacta. `align-self: flex-start` lo pega a la parte superior de la
      celda (el titulo puede partirse en 1-2 lineas) en vez de centrarlo
      respecto a el -- es lo que empieza a dar el aspecto de exponente. */
table.dataTable thead > tr > th.dt-orderable-asc .dt-column-order,
table.dataTable thead > tr > th.dt-orderable-desc .dt-column-order,
table.dataTable thead > tr > th.dt-ordering-asc .dt-column-order,
table.dataTable thead > tr > th.dt-ordering-desc .dt-column-order,
table.dataTable thead > tr > td.dt-orderable-asc .dt-column-order,
table.dataTable thead > tr > td.dt-orderable-desc .dt-column-order,
table.dataTable thead > tr > td.dt-ordering-asc .dt-column-order,
table.dataTable thead > tr > td.dt-ordering-desc .dt-column-order {
    display: inline-flex;
    align-items: flex-start;
    align-self: flex-start;
    gap: 0;
    width: auto;
    height: auto;
}

/* 2. Las flechas dejan de estar posicionadas en absoluto (por eso se apilaban) y
      pasan a ser dos elementos en linea. La segunda declaracion de content, con
      "/ ''", deja el texto alternativo vacio para que un lector de pantalla no
      lea la flecha; si el navegador no la soporta se queda con la primera. */
table.dataTable thead > tr > th.dt-orderable-asc .dt-column-order:before,
table.dataTable thead > tr > th.dt-ordering-asc .dt-column-order:before,
table.dataTable thead > tr > td.dt-orderable-asc .dt-column-order:before,
table.dataTable thead > tr > td.dt-ordering-asc .dt-column-order:before {
    content: "\2191";
    content: "\2191" / "";
}

table.dataTable thead > tr > th.dt-orderable-desc .dt-column-order:after,
table.dataTable thead > tr > th.dt-ordering-desc .dt-column-order:after,
table.dataTable thead > tr > td.dt-orderable-desc .dt-column-order:after,
table.dataTable thead > tr > td.dt-ordering-desc .dt-column-order:after {
    content: "\2193";
    content: "\2193" / "";
}

/* 3. Tamano y posicion tipo exponente. `font-size` es RELATIVO a proposito
      (0.78em del titulo del encabezado, ~7.6px sobre los ~9.8px de la celda): un
      exponente matematico siempre es mas pequeño que su base, y si el titulo se
      parte en 2 lineas la flecha debe achicarse con el, no competir con el.
      `position:relative` + `top` negativo la levanta por encima de la linea
      base del titulo -- el mismo truco que usaria un <sup>, pero aplicado a un
      pseudo-elemento dentro de una caja flex (donde `vertical-align` no
      funciona). Se sustituye la opacidad 0.125 del original por un gris propio
      para que siga siendo legible pese al tamaño reducido. */
table.dataTable thead > tr > th.dt-orderable-asc .dt-column-order:before,
table.dataTable thead > tr > th.dt-ordering-asc .dt-column-order:before,
table.dataTable thead > tr > th.dt-orderable-desc .dt-column-order:after,
table.dataTable thead > tr > th.dt-ordering-desc .dt-column-order:after,
table.dataTable thead > tr > td.dt-orderable-asc .dt-column-order:before,
table.dataTable thead > tr > td.dt-ordering-asc .dt-column-order:before,
table.dataTable thead > tr > td.dt-orderable-desc .dt-column-order:after,
table.dataTable thead > tr > td.dt-ordering-desc .dt-column-order:after {
    position: relative;
    top: -0.35em;
    line-height: 1;
    font-size: 0.78em;
    opacity: 1;
    color: var(--text-subtle);
}

/* 4. La flecha del sentido activo, en el azul de la marca. */
table.dataTable thead > tr > th.dt-ordering-asc .dt-column-order:before,
table.dataTable thead > tr > th.dt-ordering-desc .dt-column-order:after,
table.dataTable thead > tr > td.dt-ordering-asc .dt-column-order:before,
table.dataTable thead > tr > td.dt-ordering-desc .dt-column-order:after {
    opacity: 1;
    color: var(--primary-tint-text);
    font-weight: 700;
}

/* 5. El titulo SIEMPRE primero y la flecha SIEMPRE a la derecha, pase lo que
      pase con el tipo de columna. datatables.css pone
      `flex-direction: row-reverse` en `div.dt-column-header` cuando detecta la
      columna como numerica o fecha (`dt-type-numeric`, `dt-type-date`) o
      cuando queda alineada a la derecha (`dt-right`, `dt-head-right`) -- y esa
      deteccion se hace sobre los DATOS reales, no sobre la tabla vacia, asi
      que el efecto aparece tarde: la cabecera se ve bien al cargar y la
      flecha "se pasa" al lado izquierdo del titulo justo al consultar. Es la
      misma trampa que ya se documento para la columna PORCENTAJE de
      `consultar solicitud.php`, resuelta entonces pagina por pagina; aqui se
      cierra de una vez para toda `.table-modern`. Hace falta `!important`
      porque los selectores de datatables.css tienen mas clases que este
      (3 contra 2: `table.dataTable th.dt-type-numeric div.dt-column-header`),
      asi que ganarian por especificidad aunque esta hoja se cargue despues. */
.table-modern thead > tr > th div.dt-column-header,
.table-modern thead > tr > td div.dt-column-header {
    flex-direction: row !important;
    justify-content: flex-start !important;
}

/* --------------------------------------------------------------------------
   9. ESTILO COMPACTO GLOBAL PARA DESPLEGABLES (SELECT) DE TODO EL SISTEMA

   OJO CON LA CASCADA: esta sección incluye `.form-select-modern`, que ya se estiló en la
   sección 3 con la misma especificidad (0,1,0). Al ir después, ES ESTA la que manda sobre
   los desplegables. Hasta 2026-07-29 declaraba `height:auto; min-height:35px;
   max-height:30px` —contradictorio, gana min-height— así que los `<select>` salían a 35px
   mientras las cajas de texto y los botones de la misma barra estaban a 27px: por eso las
   barras de filtro se veían desparejas. Ahora todo cuelga de --control-height.
   Si se cambia la altura, hay que hacerlo en la variable, no aquí.
   -------------------------------------------------------------------------- */
select,
.form-select,
.form-select-sm,
.form-select-lg,
.form-select-modern,
.custom-select {
    background-color: var(--bg-card);
    color: var(--text-main);
    border: 1px solid var(--border);
    padding-top: 0.2rem !important;
    padding-bottom: 0.2rem !important;
    padding-left: 0.45rem !important;
    padding-right: 1.5rem !important;
    font-size: 0.81rem !important;
    height: var(--control-height) !important;
    min-height: var(--control-height) !important;
    max-height: var(--control-height) !important;
    line-height: 1.25 !important;
    border-radius: 4px !important;
}

/* Buscadores Select2 del flujo de polizas _NUEVO.
   El menu cuelga de body: el alcance debe estar en body, no en .plz-card. */
.apm-polizas-nuevo .select2-dropdown {
    background-color: var(--bg-card);
    color: var(--text-main);
    border: 1px solid var(--border);
    border-radius: 10px;
    box-shadow: var(--shadow);
    overflow: hidden;
}
.apm-polizas-nuevo .select2-search--dropdown {
    padding: 10px;
}
.apm-polizas-nuevo .select2-container--default .select2-search--dropdown .select2-search__field {
    box-sizing: border-box;
    width: 100%;
    min-width: 0;
    min-height: 36px;
    padding: 7px 12px;
    border: 1px solid var(--border);
    border-radius: 9px;
    background-color: var(--bg-page);
    color: var(--text-main);
    font: inherit;
    font-size: 0.875rem;
    line-height: 1.4;
    outline: none;
}
.apm-polizas-nuevo .select2-container--default .select2-search--dropdown .select2-search__field:focus {
    border-color: var(--primary-tint-text);
    box-shadow: 0 0 0 3px var(--primary-tint);
}

/* Mantener visible la seleccion cuando el foco o el cursor pasan a otra opcion. */
:root[data-apm-theme="dark"] .apm-polizas-nuevo .select2-container--default .select2-results__option--selected,
:root[data-apm-theme="dark"] .apm-polizas-nuevo .select2-container--default .select2-results__option[aria-selected="true"] {
    background-color: var(--primary-tint);
    color: var(--text-main);
    box-shadow: inset 3px 0 0 var(--primary-tint-text);
    font-weight: 600;
}
:root[data-apm-theme="dark"] .apm-polizas-nuevo .select2-container--default .select2-results__option--highlighted {
    background-color: var(--primary);
    color: #ffffff;
}

/* --------------------------------------------------------------------------
   10. BARRA DE FILTROS DE LISTADOS (.filter-row-grid, .btn-filter-search)
   Adaptada a los estándares corporativos de CLAUDE.md: colores neutrales y
   tema-adaptativos, eliminando saturaciones fucsias, arcoíris y bordes chillones.
   -------------------------------------------------------------------------- */
/* Barra de título de listados (conservada por compatibilidad, neutralizada a estilo corporativo) */
.filter-header-bar {
    background: var(--bg-card);
    color: var(--text-main);
    font-weight: 600;
    font-size: 0.9rem;
    padding: 0 0 0.5rem 0;
    letter-spacing: 0.5px;
    border-bottom: 2px solid var(--primary);
    display: inline-block;
    margin-bottom: 0.75rem;
    text-transform: uppercase;
}

/* Línea decorativa multicolor: eliminada por directrices de diseño */
.filter-rainbow-line {
    display: none !important;
}

/* Caja que agrupa los filtros (por compatibilidad, se recomienda .card-modern) */
.filter-container-box {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius, 0.75rem);
    padding: 0.5rem 1.25rem 1.25rem 1.25rem;
    box-shadow: var(--shadow);
    margin-bottom: 1.25rem;
}

/* Fila de filtros: responsiva con alineación al pie */
.filter-row-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    align-items: flex-end;
    width: 100%;
}

/* Cada filtro reparte el ancho equitativamente con mínimo cómodo */
.filter-col-item {
    flex: 1 1 150px;
    min-width: 140px;
}

/* Bloque de acciones al final de la fila (no se estira) */
.filter-col-action {
    flex: 0 0 auto;
}

/* Etiqueta + lupa del filtro, en la misma línea */
.filter-label-group {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 4px;
}

.filter-label {
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--text-muted);
    margin-bottom: 0 !important;
    white-space: nowrap;
}

/* Lupa pequeña junto a cada etiqueta: discreta en reposo, azul en hover */
.btn-filter-search {
    background: transparent;
    border: none;
    color: var(--text-muted);
    font-size: 0.85rem;
    cursor: pointer;
    padding: 0 4px;
    line-height: 1;
    transition: transform 0.15s ease, color 0.15s ease;
}

.btn-filter-search:hover {
    color: var(--primary);
    transform: scale(1.15);
}

/* Colores de borde heredados: neutralizados al borde corporativo */
.select-border-gold,
.select-border-purple,
.select-border-blue,
.select-border-green,
.select-border-teal {
    border: 1px solid var(--border) !important;
    border-radius: 4px;
}

.select-border-gold:focus,
.select-border-purple:focus,
.select-border-blue:focus,
.select-border-green:focus,
.select-border-teal:focus {
    border-color: var(--primary) !important;
    box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.15) !important;
    outline: none;
}

/* Botón de búsqueda general: adaptado al azul corporativo (.btn-modern) */
.btn-search-main {
    background: var(--primary);
    border: 1px solid var(--primary);
    border-radius: 4px;
    padding: 0 10px;
    height: var(--control-height);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    color: #ffffff;
    transition: background 0.15s ease, border-color 0.15s ease;
}

.btn-search-main:hover {
    background: var(--primary-hover);
    border-color: var(--primary-hover);
}

.btn-search-main i {
    color: #ffffff !important;
}

/* --------------------------------------------------------------------------
   11. UTILIDADES HEREDADAS DE LAS PÁGINAS ANTIGUAS
   Clases sueltas que venían repetidas en el <style> de cada formulario (unas 63
   páginas las usan). Se centralizan para no volver a copiarlas al migrar.
   -------------------------------------------------------------------------- */
.confondo            { background-color: #def; }
.sinborde            { border: 0; }
.sinbordefondo       { background-color: #eee; border: 0; }
.outlinenone         { outline: none; background-color: #dfe; border: 0; }
.redondeadonorelieve { border-radius: 5px; border: 1px solid #39c; }

/* Título de formulario de las páginas AÚN NO rediseñadas (`<h4 class="comments_h4">`).
   Lo definía `estilos2.css`, pero la regla se perdió en alguna versión: hoy solo sobrevive en
   `estilos2 - 01junio2024.css`, que no se carga, así que esos títulos salían como un <h4>
   pelado. Se restituye aquí, con el azul original (#0085cf), para que las páginas que solo
   tienen modernización PARCIAL no se queden a medio pintar.
   Al hacerles la modernización COMPLETA, este `<h4>` pasa a `.card-title-modern` dentro de un
   `.card-modern` (ver A.1 en CLAUDE.md) y deja de usar esta clase. */
.comments_h4 {
    background-color: #0085cf;
    border-radius: 4px;
    color: #fff;
    font-size: 14px;
    line-height: 23px;
    margin-top: 0;
    margin-bottom: 0.75rem;
    padding: 0.35rem 0.75rem;
}

/* Icono/texto con relleno degradado (lupas y títulos destacados) */
.search-icon {
    background: linear-gradient(135deg, #007bff, #0056b3, #0d6efd);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
    display: inline-block;
}

/* --------------------------------------------------------------------------
   12. FORMULARIOS DE CAPTURA DE DATOS (páginas de alta/edición, no listados)

   Ojo con no confundirlas con las de la sección 3: `.form-control-modern` y
   `.form-select-modern` están calibradas a 27px de alto porque viven en las
   barras de filtro de los listados, donde el usuario solo elige. Aquí el
   usuario ESCRIBE, así que las cajas son más altas. Mismo lenguaje visual
   (borde, radio, anillo de foco azul), distinta densidad.
   -------------------------------------------------------------------------- */
/* Rejilla responsiva de campos: tantas columnas como quepan a 260px mínimo. */
.form-grid-modern {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 0.85rem 1rem;
    align-items: start;
}

/* Campo que ocupa la fila entera (direcciones, observaciones, nombres largos) */
.form-field-wide {
    grid-column: 1 / -1;
}

/* Caja de texto cómoda para escribir. Se combina con .form-label-modern.
   Usa --input-border (no --border) para no desentonar con el gris que la validación
   en línea de app.js/appg.js escribe inline tras un blur válido — ver sección 1. */
.form-input-modern {
    width: 100%;
    height: var(--control-height-form);
    border: 1px solid var(--input-border);
    border-radius: 4px;
    padding: 0.35rem 0.6rem;
    font-size: 0.85rem;
    line-height: 1.4;
    color: var(--text-main);
    background: var(--bg-card);
    transition: border-color 0.2s, box-shadow 0.2s;
}

.form-input-modern:focus {
    border-color: var(--primary);
    box-shadow: 0 0 0 3px rgba(37,99,235,0.15);
    outline: none;
}

/* Solo lectura: se distingue del editable sin llegar a parecer deshabilitado. */
.form-input-modern[readonly] {
    background: var(--color-neutral-bg);
    color: var(--text-muted);
    cursor: default;
}

/* Barra de botones al pie del formulario, separada por una línea. */
.form-actions-modern {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 0.5rem;
    margin-top: 1.25rem;
    padding-top: 0.9rem;
    border-top: 1px solid var(--border);
}

/* Los botones de pie de formulario NO usan --control-height: esa altura existe para que los
   controles de una barra de filtros cuadren entre sí. Aquí acompañan a .form-input-modern,
   así que usan --control-height-form y quedan a la misma altura que las cajas de texto.
   Especificidad mayor + !important para ganar a la regla base, que también usa !important. */
.form-actions-modern .btn-modern,
.form-actions-modern .btn-modern-success,
.form-actions-modern .btn-modern-danger,
.form-actions-modern .btn-modern-info,
.form-actions-modern .btn-modern-warning,
.form-actions-modern .btn-modern-secondary {
    height: var(--control-height-form) !important;
    min-height: var(--control-height-form) !important;
    max-height: var(--control-height-form) !important;
    font-size: 0.85rem !important;
    padding: 0.35rem 1rem !important;
}

/* --------------------------------------------------------------------------
   13. TARJETAS DE INDICADORES (PANELES DE CONSULTA / DASHBOARD)

   Tercera forma de página del sistema, junto al LISTADO (secciones 3 y 5) y al
   FORMULARIO de captura (sección 12): la pantalla que no lista filas ni captura
   datos, sino que muestra CONTADORES y, al lado de cada uno, el botón que exporta
   ese mismo dato a Excel o PDF. La primera en usarla es
   `frm_consultar_tcredenciales.php` (2026-07-31); su gemela
   `frm_consultar_tcredenciales_2.php` y las páginas de estadísticas usan el mismo
   patrón, por eso vive aquí y no en el <style> de la página.

   Sustituye a los `.card` de Bootstrap con un `.dropdown` dentro por cada cifra.
   Ese diseño no solo era viejo: con las DOS copias de Bootstrap que carga cada
   página migrada (la del bundle y la que trae datatables.js) el `data-api` de
   dropdown queda registrado dos veces, así que un clic ejecuta `toggle()` dos
   veces —abre y cierra— y el menú no llega a verse. Ver sección (B) de CLAUDE.md.
   Aquí no hay menús: los botones de exportación están siempre a la vista.
   -------------------------------------------------------------------------- */
/* Rejilla de tarjetas: tantas columnas como quepan a 320px mínimo. */
.kpi-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    gap: 1rem;
    align-items: start;
    margin-bottom: 1.25rem;
}

.kpi-card {
    /* var(--primary-tint-text), no var(--primary): --kpi-color solo se usa como COLOR DE TEXTO
       (cabecera outline y borde inferior de .kpi-card-header, más abajo) o sobre el tinte
       --primary-tint (.kpi-card-count) — nunca como relleno sólido, así que no aplica la
       reserva de --primary para fondo-de-botón-con-texto-blanco (ver comentario junto a
       --primary-tint-text en :root). Ver CLAUDE.md/E, 2026-09-05. */
    --kpi-color: var(--primary-tint-text);   /* color de identidad de la cabecera; los modificadores de abajo lo cambian */
    background: var(--bg-card);
    border: 1px solid var(--border);   /* gris neutro a propósito: el color solo va en la cabecera */
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    overflow: hidden;
}

/* Cabecera en outline (sin relleno): es lo que distingue de un vistazo cada bloque
   de cifras (autorizadas, no autorizadas, emitidas...) sin saturar la pantalla de
   color solido. El color se hereda de --kpi-color, fijado en .kpi-card. */
.kpi-card-header {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.9rem;
    background: var(--bg-card);
    color: var(--kpi-color);
    border-bottom: 1px solid var(--kpi-color);
    font-size: 0.78rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.kpi-card-header i {
    font-size: 0.9rem;
    opacity: 0.9;
}

.kpi-card-body {
    padding: 0.25rem 0.9rem 0.6rem 0.9rem;
}

/* Modificadores de color: solo cambian --kpi-color, que heredan el borde de la
   tarjeta, la cabecera y el contador (.kpi-card-count, mas abajo). */
.kpi-card--success { --kpi-color: var(--color-success); }
.kpi-card--danger  { --kpi-color: var(--color-danger); }
.kpi-card--info    { --kpi-color: var(--color-info); }
.kpi-card--warning { --kpi-color: var(--color-warning); }
.kpi-card--neutral { --kpi-color: var(--secondary); }

/* Una línea = un contador: etiqueta, cifra y sus botones de exportación. */
.kpi-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.4rem 0;
    border-bottom: 1px dashed var(--border);
}

.kpi-row:last-child {
    border-bottom: none;
}

.kpi-label {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--text-muted);
}

/* La cifra la escribe el JS con innerText, así que el ancho mínimo evita que la
   fila "salte" al pasar de vacío a un número. `tabular-nums` mantiene alineadas
   las cifras de unas filas con otras. */
.kpi-value {
    flex: 0 0 auto;
    min-width: 2.75rem;
    text-align: right;
    font-size: 1rem;
    font-weight: 700;
    color: var(--text-main);
    font-variant-numeric: tabular-nums;
}

.kpi-actions {
    flex: 0 0 auto;
    display: inline-flex;
    gap: 0.25rem;
}

/* Botones-icono cuadrados de 24px. Necesitan mayor especificidad + !important
   porque la sección 4 fija la altura de .btn-modern-* también con !important. */
.kpi-actions .btn-modern,
.kpi-actions .btn-modern-success,
.kpi-actions .btn-modern-danger,
.kpi-actions .btn-modern-info,
.kpi-actions .btn-modern-warning,
.kpi-actions .btn-modern-secondary {
    width: 24px !important;
    height: 24px !important;
    min-height: 24px !important;
    max-height: 24px !important;
    padding: 0 !important;
    gap: 0 !important;
    font-size: 0.72rem !important;
}

/* Outline en vez de relleno: solo dentro de .kpi-actions (Excel/PDF de cada fila),
   sin tocar `.btn-modern-success`/`.btn-modern-danger` base, que siguen rellenos
   en el resto del sistema (Guardar, Retornar, etc.). El relleno vuelve en :hover
   como retroalimentacion de interaccion, no como estado permanente en pantalla. */
.kpi-actions .btn-modern-success {
    background: var(--bg-card);
    border: 1.5px solid var(--color-success);
    color: var(--color-success);
}

.kpi-actions .btn-modern-success:hover {
    background: var(--color-success);
    color: #ffffff;
    box-shadow: none;
}

.kpi-actions .btn-modern-danger {
    background: var(--bg-card);
    border: 1.5px solid var(--color-danger);
    color: var(--color-danger);
}

.kpi-actions .btn-modern-danger:hover {
    background: var(--color-danger);
    color: #ffffff;
    box-shadow: none;
}

/* Fila de acciones generales de la página (reportes globales, gráficos), debajo
   de los filtros. */
.kpi-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 0.5rem;
    margin-top: 0.75rem;
    padding-top: 0.7rem;
    border-top: 1px solid var(--border);
}

/* Grupo etiqueta + control dentro de la barra de acciones (p. ej. "Tipo de reporte"). */
.kpi-toolbar-field {
    display: flex;
    flex-direction: column;
    min-width: 240px;
    flex: 1 1 240px;
}

.kpi-toolbar-spacer {
    flex: 1 1 auto;
}

/* --------------------------------------------------------------------------
   13.b CABECERA DE PÁGINA (título + subtítulo + migas)

   Bloque de encabezado que va sobre las tarjetas, después del header común.
   Es independiente de `.card-modern`: no es un panel, es el rótulo de la
   pantalla. Se separó de la sección 13 para poder usarlo también en listados.
   -------------------------------------------------------------------------- */
.page-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.15rem 0.75rem;
    margin: 0 0 0.5rem 0;
}

/* Rótulo, título y subtítulo en UNA sola línea.
   Apilados ocupaban ~78px de alto antes de la primera tarjeta (rótulo + título de
   1.5rem + subtítulo + 1rem de margen inferior); en línea bajan a ~24px. El
   flex-wrap los deja apilarse solos en pantallas estrechas, así que no se pierde
   nada en móvil: solo se deja de reservar ese alto cuando no hace falta. */
.page-head-main {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.15rem 0.5rem;
    min-width: 0;
}

/* Rótulo pequeño en mayúsculas delante del título ("CONSULTA", "GESTIÓN"...).
   OPCIONAL: si la página ya lleva migas, el rótulo repite esa misma información.
   `frm_consultar_tcredenciales.php` no lo usa por ese motivo. */
.page-head-eyebrow {
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--primary-tint-text);
    margin-bottom: 0;
}

/* Título de la pantalla. Comparte tipografía con `.card-title-modern` a propósito:
   mismo peso (600) y mismo color, y solo un escalón de tamaño por encima (1rem
   frente a 0.9rem). Con 700 y un color propio parecía otra fuente distinta, aunque
   la familia siempre fue la misma.
   `font-family: inherit` es explícito para no depender de que Bootstrap siga sin
   fijar familia en los encabezados: hoy su reboot solo emite margen, peso, interlineado
   y color, pero basta con que alguien defina `--bs-heading-font-family` para que estos
   títulos se despeguen del resto de la interfaz.
   El `font-size` de la clase también neutraliza el `calc(1.375rem + 1.5vw)` que
   Bootstrap le da a `h1`, que además es RESPONSIVO: sin esto el título cambiaba de
   tamaño con el ancho de la ventana mientras el resto de la página no. */
.page-head-title {
    margin: 0;
    font-family: inherit;
    font-size: 1rem;
    font-weight: 600;
    line-height: 1.3;
    letter-spacing: 0;
    color: var(--text-main);
}

/* Punto separador entre el título y el subtítulo cuando comparten línea. */
.page-head-sep {
    color: var(--text-faint);
    font-size: 0.8rem;
}

.page-head-subtitle {
    margin: 0;
    font-size: 0.8rem;
    color: var(--text-muted);
}

/* Título de tarjeta con su texto de ayuda a la derecha, en la MISMA línea.
   Un `<p>` de ayuda debajo del título añade dos renglones antes de que empiecen
   los controles; aquí el texto acompaña al título y no cuesta alto. Envuelve solo
   en pantallas estrechas. */
.card-head-row {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.1rem 0.6rem;
    margin-bottom: 0.35rem;
}

/* El margen inferior lo pone ya `.card-head-row`. */
.card-head-row .card-title-modern {
    margin-bottom: 0;
}

.card-head-hint {
    margin: 0;
    font-size: 0.78rem;
    color: var(--text-muted);
}

/* Línea de metadatos del documento (generado el…, período, usuario).
   NO es `.card-head-hint`: aquella explica cómo usar un control y por eso se oculta
   al imprimir; ésta dice de cuándo son los datos, que en papel es justo lo que hay
   que conservar. La sección 14 la deja visible a propósito. */
.doc-meta {
    margin: 0.5rem 0 0 0;
    font-size: 0.75rem;
    color: var(--text-muted);
}

/* --------------------------------------------------------------------------
   14. IMPRESIÓN

   Vale para todas las páginas migradas: el cromo de la aplicación (menú lateral,
   migas, barras de filtro, botones) no es contenido y no va al papel.

   La regla importante es la primera, y su causa no es evidente: `.page-content`
   (sección 7) es una VENTANA con `height: 100vh` + `overflow-y: auto`. En pantalla
   eso es lo que da el scroll interno de la aplicación; al imprimir, el navegador
   compone únicamente lo que cabe en esa ventana y el resto del documento no llega
   nunca al papel. El síntoma es "sale una sola hoja con el contenido cortado a
   media altura", y se atribuye al gráfico o a la tabla cuando en realidad es el
   layout. Lo mismo con `position: fixed` de `.top-header`: un elemento fijo se
   ancla a la primera página y arrastra consigo todo lo que contiene.
   -------------------------------------------------------------------------- */
@media print {
    html,
    body,
    .page-wrapper.chiller-theme,
    .page-content {
        height: auto !important;
        max-height: none !important;
        overflow: visible !important;
    }

    .page-wrapper.top-header {
        position: static !important;
    }

    /* El hueco de 270px que el contenido reserva para el menú lateral. */
    .page-wrapper .page-content,
    .page-wrapper.toggled .page-content {
        padding-left: 0 !important;
        padding-top: 0 !important;
    }

    body {
        background: #ffffff !important;
    }

    /* El fondo azulado de la vista (sección 7) no va al papel. */
    .page-content {
        background: #ffffff !important;
    }

    /* CANDADO DE IMPRESIÓN EN MODO OSCURO. Lo de arriba ya fuerza `background:#ffffff` en
       `body`, pero eso por sí solo no basta: si el usuario imprime con el tema oscuro
       activo en pantalla, `:root[data-apm-theme="dark"]` sigue vivo dentro del propio
       `@media print` (los `data-*` del `<html>` no se tocan al imprimir) y todo lo que
       cuelgue de `--text-main`/`--bg-card`/`--border`/`--shadow`/`--primary-tint*`/
       `--color-neutral-*` seguiría resolviendo a sus valores oscuros — texto claro sobre
       el fondo blanco que la regla de arriba acaba de forzar. Se reponen aquí los mismos
       valores que tienen en claro, para que el papel salga siempre igual sin depender de
       qué tema esté activo en pantalla. */
    :root[data-apm-theme="dark"] {
        --bg-page:  #f8fafc;
        --bg-card:  #ffffff;
        --text-main: #0f172a;
        --text-muted: #475569;
        --border:    #e2e8f0;
        --shadow:    0 4px 12px rgba(0,0,0,0.06);
        --primary-tint:       #eff6ff;
        --primary-tint-hover: #dbeafe;
        --color-neutral-bg:   #f1f5f9;
        --color-neutral-text: #475569;
        --alert-neutral-bg: #f8fafc; --alert-neutral-border: #cbd5e1; --alert-neutral-text: #334155;
        --alert-success-bg: #f0fdf4; --alert-success-border: #86efac; --alert-success-text: #166534;
        --alert-danger-bg:  #fef2f2; --alert-danger-border:  #fca5a5; --alert-danger-text:  #991b1b;
        --alert-info-bg:    #f0f9ff; --alert-info-border:    #7dd3fc; --alert-info-text:    #075985;
        --alert-warning-bg: #fffbeb; --alert-warning-border: #fde68a; --alert-warning-text: #92400e;
        --table-border: #dfeaf5;
        --table-head-bg: #eef7ff; --table-head-text: #47698d; --table-head-border: #d7e5f3;
        --table-row-bg: #ffffff; --table-row-alt-bg: #f8fbfe; --table-row-hover-bg: #edf6ff;
        --table-cell-border: #e4edf6; --table-cell-text: #29445f;
    }

    .container-fluid_xxx {
        padding: 0 !important;
    }

    /* EL MENÚ LATERAL NECESITA MÁS ESPECIFICIDAD, no basta con nombrarlo.
       `menubs4xb_n.php` trae un `<style>` embebido que declara
           nav#sidebar.sidebar-wrapper { display: flex !important }      (0,1,1,1)
           #show-sidebar               { display: inline-flex !important } (0,1,0,0)
       Ese bloque se inserta en el `<body>`, o sea DESPUÉS de esta hoja, y también usa
       `!important`: a igualdad de especificidad e importancia gana el último, así que
       un `.sidebar-wrapper { display:none !important }` de aquí NO puede ganarle, y
       `#show-sidebar` solo empata (y pierde por orden). Hay que subir por encima
       anteponiendo `.page-wrapper`, que es el ancestro de los dos:
           .page-wrapper nav#sidebar.sidebar-wrapper  (0,1,2,1) > (0,1,1,1)
           .page-wrapper #show-sidebar                (0,1,1,0) > (0,1,0,0)
       Síntoma si se toca esto y se pierde la especificidad: el menú y la hamburguesa
       vuelven a salir impresos, y parece que el CSS "no se aplica" o que es la caché.
       Se conservan también los selectores simples, para páginas con el sidebar viejo. */
    .page-wrapper nav#sidebar.sidebar-wrapper,
    .page-wrapper #show-sidebar,
    .page-wrapper #close-sidebar,
    .sidebar-wrapper,
    #sidebar,
    #close-sidebar,
    #show-sidebar,
    .breadcrumb-modern,
    .kpi-toolbar,
    .filter-grid,
    .filter-header-bar,
    .filter-rainbow-line,
    .filter-container-box,
    .card-head-hint,
    .kpi-actions,
    .dt-search,
    .dt-length,
    .dt-paging,
    .dt-buttons,
    .no-print {
        display: none !important;
    }

    /* Ningún botón sirve en un papel, así que se ocultan TODOS en vez de ir
       enumerando el contenedor de cada uno — que es lo que deja siempre alguno
       suelto. La excepción es `.btn-default`: en este proyecto esa clase no marca
       botones sino ETIQUETAS de texto dentro de las celdas de los listados
       ("VÁLIDO HASTA", "VIGENTE"…), que sí son contenido. Es de Bootstrap 3, no
       existe en BS5 y solo la llevan esas etiquetas, así que es un discriminador
       fiable — el mismo que ya usa la sección 4.

       Segunda excepción, `.apm-user-menu-btn`: es el badge de usuario/empresa de
       header_body.php, un `<button>` solo porque ahora abre un dropdown -- antes
       de esa conversión era un `<div>` y esta regla no lo tocaba, así que el
       nombre de quien inició sesión SÍ se imprimía siempre. Sin esta excepción,
       convertirlo en `<button>` lo habría hecho desaparecer de golpe de
       cualquier documento impreso en las ~72 páginas que cargan esta cabecera. */
    button:not(.btn-default):not(.apm-user-menu-btn),
    .btn:not(.btn-default),
    input[type="button"],
    input[type="submit"],
    input[type="reset"] {
        display: none !important;
    }

    /* La flechita de abrir/cerrar no significa nada en papel (no hay clic posible) --
       se oculta sola, sin arrastrar el resto del badge (ver excepción de arriba). */
    .apm-user-menu-caret {
        display: none !important;
    }

    /* En pantalla el nombre se trunca con elipsis a proposito (ancho fijo reducido,
       ver seccion 2); en papel no hay hover ni desplegable para leer el resto, así
       que aquí se anula el límite y se ve completo, aunque ocupe más de una línea. */
    .apm-user-menu-btn,
    .apm-user-menu-label {
        max-width: none !important;
        overflow: visible !important;
        white-space: normal !important;
    }

    /* Sin sombras; un borde fino basta para seguir delimitando cada bloque. */
    .card-modern,
    .kpi-card,
    .kpi-tile {
        box-shadow: none !important;
        border: 1px solid #cbd5e1 !important;
        break-inside: avoid;
        page-break-inside: avoid;
    }

    /* Los navegadores suprimen los fondos al imprimir. Sin esto las cabeceras de
       color de las tarjetas de indicadores salen en blanco y dejan de distinguir
       un bloque de otro, que es justamente su función. */
    * {
        -webkit-print-color-adjust: exact !important;
        print-color-adjust: exact !important;
    }

    /* Tablas largas: cabecera repetida en cada hoja y ninguna fila partida. */
    thead { display: table-header-group; }
    tfoot { display: table-footer-group; }
    tr,
    img,
    canvas {
        break-inside: avoid;
        page-break-inside: avoid;
    }

    /* Red de seguridad para los <canvas>: se componen al tamaño en píxeles con el
       que se dibujaron, así que uno más ancho que el papel se recorta por la
       derecha. Lo correcto es volver a renderizarlo en `beforeprint` (ver la página
       del gráfico); esto solo evita el desbordamiento si eso no ocurriera. */
    canvas {
        max-width: 100% !important;
    }

    /* Bootstrap imprime la URL entre paréntesis detrás de cada enlace. */
    a[href]::after {
        content: "" !important;
    }

    .page-head { margin-bottom: 0.5rem !important; }
    .kpi-tile-grid { gap: 0.5rem !important; }
    .kpi-tile { padding: 0.5rem 0.7rem !important; }

    @page { margin: 12mm; }
}

/* Migas de pan. Se apoya en el separador como ::before para no depender del
   componente breadcrumb de Bootstrap ni de su variable --bs-breadcrumb-divider. */
.breadcrumb-modern {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem;
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: 0.8rem;
    color: var(--text-muted);
}

.breadcrumb-modern li + li::before {
    content: "\203A";
    margin-right: 0.35rem;
    color: var(--text-subtle);
}

.breadcrumb-modern a {
    color: var(--text-muted);
    text-decoration: none;
}

.breadcrumb-modern a:hover {
    color: var(--primary-tint-text);
    text-decoration: underline;
}

.breadcrumb-modern .is-current {
    color: var(--text-main);
    font-weight: 600;
}

/* --------------------------------------------------------------------------
   13.c FRANJA DE CIFRAS DESTACADAS (.kpi-tile)

   La lectura "de un vistazo" que va sobre las tarjetas de detalle: icono a la
   izquierda, cifra grande y una leyenda debajo. No sustituye a `.kpi-card`
   (que desglosa y exporta), la resume.

   El valor lo escribe el JS, así que `.kpi-tile-value` reserva alto de línea y
   usa `tabular-nums` por el mismo motivo que `.kpi-value`: que la franja no
   salte ni baile al pasar de "—" a una cifra de tres dígitos.
   -------------------------------------------------------------------------- */
.kpi-tile-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 0.75rem;
    margin-bottom: 1.25rem;
}

.kpi-tile {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 0.7rem 0.9rem;
}

/* Cuadro del icono. El color lo dan los modificadores de abajo. */
.kpi-tile-icon {
    flex: 0 0 auto;
    width: 38px;
    height: 38px;
    border-radius: 10px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1rem;
    background: var(--primary-tint);
    color: var(--primary-tint-text);
}

.kpi-tile-body {
    min-width: 0;
}

.kpi-tile-label {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
    margin-bottom: 0.1rem;
}

.kpi-tile-value {
    font-size: 1.6rem;
    font-weight: 700;
    line-height: 1.1;
    color: var(--text-main);
    font-variant-numeric: tabular-nums;
}

.kpi-tile-hint {
    font-size: 0.72rem;
    color: var(--text-subtle);
}

/* Estado "sin consultar": la cifra es un guion, no un 0. Un 0 significaría
   "consulté y no hay registros", que es información distinta. */
.kpi-tile-value.is-empty,
.kpi-value.is-empty {
    color: var(--text-faint);
}

.kpi-tile--success .kpi-tile-icon { background: var(--color-success-bg); color: var(--color-success); }
.kpi-tile--danger  .kpi-tile-icon { background: var(--color-danger-bg);  color: var(--color-danger); }
.kpi-tile--info    .kpi-tile-icon { background: var(--color-info-bg);    color: var(--color-info); }
.kpi-tile--warning .kpi-tile-icon { background: var(--color-warning-bg); color: var(--color-warning); }
.kpi-tile--neutral .kpi-tile-icon { background: var(--color-neutral-bg); color: var(--secondary); }

/* Contador al extremo derecho de la cabecera de una `.kpi-card`. Antes era un
   parche blanco translucido pensado para una cabecera de color solido; con la
   cabecera en outline (blanca) pasa a un tinte claro de --kpi-color + texto en
   el mismo color. Los tintes van explicitos (no color-mix) para que casen con
   los mismos pares fondo/texto que ya usa `.kpi-tile-icon` en la seccion 13.c. */
.kpi-card-count {
    margin-left: auto;
    background: var(--primary-tint);
    color: var(--kpi-color);
    border-radius: 999px;
    padding: 0.05rem 0.55rem;
    font-size: 0.75rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.kpi-card--success .kpi-card-count { background: var(--color-success-bg); }
.kpi-card--danger  .kpi-card-count { background: var(--color-danger-bg); }
.kpi-card--info    .kpi-card-count { background: var(--color-info-bg); }
.kpi-card--warning .kpi-card-count { background: var(--color-warning-bg); }
.kpi-card--neutral .kpi-card-count { background: var(--color-neutral-bg); }

/* ==========================================================================
   15. SIDEBAR MODERNO - ESTABILIZACIÓN DE CARGA (ANTI-PARPADEO / ANTI-FOUC)
   Neutraliza el CSS heredado de custom_bottom.css desde el <head> para que el
   renderizado inicial sea 100% estático e instantáneo en el primer frame.
   ========================================================================== */
.page-wrapper.chiller-theme .sidebar-wrapper,
.page-wrapper.chiller-theme .page-content,
.page-wrapper.chiller-theme #show-sidebar {
    -webkit-transition: none !important;
    -moz-transition: none !important;
    -ms-transition: none !important;
    -o-transition: none !important;
    transition: none !important;
}

.page-wrapper.chiller-theme nav#sidebar.sidebar-wrapper {
    top: 0 !important;
    width: 280px !important;
    height: 100vh !important;
    max-height: 100vh !important;
    z-index: 1025 !important;
}

.page-wrapper.chiller-theme.toggled .page-content {
    margin-left: 280px !important;
    width: calc(100% - 280px) !important;
    max-width: calc(100% - 280px) !important;
    padding-left: 5px !important;
}

.page-wrapper.chiller-theme:not(.toggled) .page-content {
    margin-left: 0 !important;
    width: 100% !important;
    max-width: 100% !important;
}


/* ==========================================================================
   16. DESPLEGABLE CON BUSCADOR (.credp-dd)

   El desplegable con panel propio: botón + buscador + lista + "no coincide
   nada" + "+ Agregar «…»" para lo que no está en el catálogo.

   Nació dentro de `frm_solcredencialespers.php` para el campo "Barco / Flota"
   y estaba DUPLICADO letra por letra en `frm_solactcredevent.php` (90 líneas
   idénticas en cada una, comprobado con diff antes de moverlo aquí). Se sube a
   la hoja global al reutilizarlo en el campo "Cargo / Función", que vive en
   cuatro páginas — dos de ellas sin esa copia.

   NO se renombró el prefijo `credp-` pese a que ya no es solo del módulo de
   credenciales: las clases las escribe `js/app_credpers_barco.js`, que está en
   producción, y renombrarlas obligaría a tocarlo sin ninguna ganancia.

   SIRVE PARA LOS DOS MODOS, y la diferencia la pone el JS, no el CSS:
     - selección MÚLTIPLE (barcos): los `.credp-dd-item` llevan checkbox, y el
       pie muestra el contador `.credp-dd-tope` y el botón "Quitar marcas".
     - selección ÚNICA (cargos): los ítems no llevan casilla y el pie sobra;
       `.credp-dd-tope:empty` ya se oculta solo, así que no estorba.

   Lo que se quedó en las páginas por ser suyo y no del componente: la regla
   `#nbarco[readonly]`, que pinta el campo compuesto como dato y no como caja
   de escritura.

   2026-08-25: se añadió `.credp-dd-chips` (recuadro sombreado con chips de lo
   marcado, debajo del botón — solo modo MÚLTIPLE) y se quitó el botón
   "+ Agregar «…»" de `.credp-dd-pie` de un área nueva: el catálogo Área/Destino
   pasó a ser de solo lectura para los dos módulos (externo e interno), lo
   mantiene únicamente el administrador de TI contra la BD. Ver la entrada
   fechada en (Q) de CLAUDE.md. El botón de Cargo/Función (`apm_cargo_select.js`)
   NO se tocó: ese catálogo sigue con su circuito de propuesta/aprobación.
   ========================================================================== */

.credp-dd { position: relative; width: 100%; margin: 0; padding: 0; }

.credp-dd-btn {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    width: 100%;
    height: var(--control-height, 27px);
    min-height: var(--control-height, 27px);
    max-height: var(--control-height, 27px);
    padding: 0.2rem 0.5rem;
    font-size: 0.81rem;
    line-height: 1.25;
    color: var(--text-main, #1e293b);
    background: var(--bg-card, #fff);
    border: 1px solid var(--border, #cbd5e1);
    border-radius: var(--radius-sm, 4px);
    cursor: pointer;
    box-sizing: border-box;
    margin: 0;
}
.credp-dd-btn:hover { border-color: var(--primary-tint-text, #0284c7); }
.credp-dd-btn .credp-dd-txt {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    text-align: left;
    font-size: 0.81rem;
    line-height: 1.25;
}
.credp-dd-caret { flex: 0 0 auto; color: var(--text-muted, #64748b); font-size: 0.70rem; }
.credp-dd-btn.credp-dd-con-seleccion { border-color: var(--primary-tint-text, #0284c7); font-weight: 600; }

/* Recuadro sombreado con las areas ya marcadas, en forma de chips. Debajo del boton, SIEMPRE
   visible (no vive dentro de .credp-dd-panel, que solo se ve con el desplegable abierto).
   Se ajusta y se expande solo: es un flex-wrap normal, sin ningun calculo de alto por JS -mismo
   mecanismo que ya usa .credp-dd-pie mas abajo-, y desaparece con :empty cuando no hay ninguna
   area marcada, igual que .credp-dd-tope:empty. Solo lo usa el modo MULTIPLE
   (app_credpers_area.js); el de seleccion unica no lo necesita, ya muestra su unico valor en el
   boton. Anadido 2026-08-25. */
.credp-dd-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    margin-top: 0.35rem;
    padding: 0.35rem 0.45rem;
    background: var(--color-neutral-bg, #f8fafc);
    border: 1px solid var(--border, #e2e8f0);
    border-radius: var(--radius-sm, 4px);
}
.credp-dd-chips:empty { display: none; }
.credp-dd-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.15rem 0.5rem;
    font-size: 0.72rem;
    line-height: 1.3;
    background: var(--primary-tint, #eff6ff);
    /* var(--primary-tint-text), no var(--primary): sobre --primary-tint oscuro, #2563eb daba
       ~2.2:1 -las etiquetas de Área/Destino ("BARCO", "PATIO"...) se leían apagadas, reportado
       2026-09-05-. Ver el comentario junto a --primary-tint-text en :root (sección 1). */
    color: var(--primary-tint-text, #0284c7);
    border: 1px solid var(--primary-tint-hover, #bfdbfe);
    border-radius: 999px;
    white-space: nowrap;
}
.credp-dd-chip-x {
    cursor: pointer;
    font-weight: 700;
    color: var(--secondary, #64748b);
    line-height: 1;
}
.credp-dd-chip-x:hover { color: var(--color-danger, #dc2626); }

/* Fila de acciones al pie de una tarjeta, separada de los campos de datos por un hairline
   superior -- mismo patrón ya probado en el módulo externo (frm_solcredencialespers.php /
   frm_solactcredevent.php), portado aquí (2026-09-14) para las 8 pantallas de verificación/
   autorización de credenciales de form/usuarios_apm/. El objetivo es que un campo que crece con
   la cantidad de datos (Destino, con chips) no comparta fila con los botones de acción: si lo
   hace, una columna angosta con muchos chips se apila en varias líneas y desalinea el resto de
   la fila (align-items:flex-end la deja con hueco vacío arriba). Separando "campos" de
   "acciones" en dos filas, cada una alinea bien por su cuenta. */
.credp-fila-acciones-bottom {
    border-top: 1px solid var(--border);
    margin-top: 0.65rem;
    padding-top: 0.55rem;
}

/* Modificador de .credp-seccion-cabecera para el campo que debe quedarse con el espacio libre
   de la fila de cabecera (normalmente Destino) en vez de un min-width fijo -- mismo mecanismo que
   .credp-seccion-area en el módulo externo, solo que aquí el campo es de solo lectura. */
.credp-seccion-crece {
    flex: 1 1 280px;
}

/* Caja unificada "campo de etiquetas" para selección múltiple (2026-09-03): variante de
   .credp-dd sin botón separado -sustituye al patrón "botón + chips al lado" que usaba
   Área/Destino hasta entonces, documentado como historial en el <style> de las dos páginas
   que la usan-. Los chips viven DENTRO de esta caja y crecen en alto con flex-wrap: wrap,
   sin ningún tope de línea ni recorte a "+N más": .credp-fila-cabecera / .credp-seccion-cabecera
   usan align-items:flex-start, así que una columna que crece en alto no empuja ni estira a
   sus vecinas de la misma fila ("Agregar persona", etc.). El botón separado con su propio
   texto ("N áreas seleccionadas") se quitó por ser redundante con los chips que ya dicen lo
   mismo: ahora la caja no repite nada, y el único disparador es el "+ Agregar" del final.
   Solo la usa Área/Destino (app_credpers_area.js) en frm_solcredencialespers.php y
   frm_solactcredevent.php; si un futuro catálogo multi-selección la necesita, queda lista
   para reutilizar tal cual. */
.credp-dd-caja {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
    width: 100%;
    min-height: var(--control-height, 27px);
    padding: 0.25rem 0.4rem;
    background: var(--bg-card, #fff);
    border: 1px solid var(--border, #cbd5e1);
    border-radius: var(--radius-sm, 4px);
    cursor: pointer;
    box-sizing: border-box;
}
.credp-dd-caja:hover,
.credp-dd-caja.credp-dd-con-seleccion { border-color: var(--primary-tint-text, #0284c7); }
.credp-dd-caja .credp-dd-chips {
    /* Dentro de la caja los chips no llevan su propio fondo/borde -.credp-dd-chips a secas,
       arriba, está pensada para vivir SUELTA debajo de un botón-: aquí serían un recuadro
       sombreado dentro de otro. */
    flex: 1 1 auto;
    margin-top: 0;
    padding: 0;
    background: none;
    border: none;
    gap: 0.35rem;
}
.credp-dd-placeholder {
    /* Sin "display" a propósito: lo oculta el atributo [hidden] nativo (ver()), y cualquier
       "display" declarado aquí ganaría siempre a [hidden] -un author origin le gana al
       user-agent origin sin importar la especificidad- y lo dejaría visible por error. */
    color: var(--text-muted, #64748b);
    font-size: 0.81rem;
    white-space: nowrap;
}
.credp-dd-agregar-pill {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    flex: 0 0 auto;
    padding: 0.15rem 0.6rem;
    font-size: 0.72rem;
    font-weight: 600;
    line-height: 1.3;
    color: var(--text-muted, #64748b);
    background: transparent;
    border: 1px dashed var(--border, #cbd5e1);
    border-radius: 999px;
    cursor: pointer;
    white-space: nowrap;
}
.credp-dd-caja:hover .credp-dd-agregar-pill,
.credp-dd-caja.credp-dd-con-seleccion .credp-dd-agregar-pill {
    color: var(--primary-tint-text, #0284c7);
    border-color: var(--primary-tint-text, #0284c7);
}

/* Modales: altura compacta de 27px para todos los inputs, selects y desplegables de Cargo/Área.
   `textarea` va excluido a propósito desde 2026-09-14 — mismo bug que el de la sección 3 más
   arriba (`.form-control-modern`), aquí con `.form-control-sm` de Bootstrap: el `height`/
   `max-height: 27px !important` se colaba también en cualquier `<textarea class="form-control
   form-control-sm">` dentro de un modal (p.ej. "Motivo de la anulación" en
   md_anular_solic_credpers.php), dejándolo congelado a una sola línea sin poder crecer por
   auto-alto ni arrastrando el tirador de resize. El bloque de aquí abajo,
   `.modal textarea.form-control-sm`, es el que ahora les da su propia altura libre. */
.modal .form-control-sm:not(textarea),
.modal .form-select-sm,
.modal .credp-dd-btn {
    height: var(--control-height, 27px) !important;
    min-height: var(--control-height, 27px) !important;
    max-height: var(--control-height, 27px) !important;
    padding: 0.2rem 0.5rem !important;
    font-size: 0.81rem !important;
    line-height: 1.25 !important;
    border: 1px solid var(--border, #cbd5e1) !important;
    border-radius: var(--radius-sm, 4px) !important;
    box-sizing: border-box !important;
    margin: 0 !important;
}

/* Textareas de modal con `form-control-sm`: mismo padding/tipografía/borde compacto que el resto
   de controles del modal, pero SIN techo de alto -- `height` queda libre (sin !important) para que
   el atributo `rows` del HTML, un auto-alto propio de la página (`el.style.height=...` inline) o el
   tirador de resize manden. `min-height` sí lleva !important, como piso, nunca como límite. */
.modal textarea.form-control-sm {
    height: auto;
    min-height: var(--control-height, 27px) !important;
    max-height: none !important;
    padding: 0.2rem 0.5rem !important;
    font-size: 0.81rem !important;
    line-height: 1.25 !important;
    border: 1px solid var(--border, #cbd5e1) !important;
    border-radius: var(--radius-sm, 4px) !important;
    box-sizing: border-box !important;
    margin: 0 !important;
    resize: vertical;
}
.modal .credp-dd-btn .credp-dd-txt {
    font-size: 0.81rem !important;
    line-height: 1.25 !important;
}
.modal .credp-dd-panel {
    min-width: 100% !important;
    width: 100% !important;
    max-width: 100% !important;
}

/* Modales: permitir desbordamiento flotante para evitar recortes de listas hacia arriba
   (credp-dd-panel de Cargo/Area, ver O.5 y Q.8 de CLAUDE.md). SIN `.modal` en esta lista
   a proposito -corregido 2026-08-26-: Bootstrap le da a `.modal` (el overlay fijo a
   pantalla completa) `overflow-y: auto`, que es el scroll "por fuera" que deja ver un
   dialogo mas alto que la ventana. Forzarlo aqui a `visible !important` se lo quitaba a
   TODOS los modales del sistema (no solo a los que tienen un credp-dd-panel): sin scroll
   propio y sin nada mas que pueda scrollear (el body queda con overflow:hidden mientras
   el modal esta abierto), el contenido que no entraba en la pantalla quedaba inalcanzable
   sin ningun error visible. Bug de raiz confirmado en paginas que este trabajo nunca
   toco (comunicado_autorizing.php / encuesta.php, incluidos desde homeautoring.php) y
   que por vivir en la hoja compartida alcanzaba a todas las paginas modernizadas por
   igual. `.modal-dialog`/`.modal-content`/`.modal-body` se quedan: no tienen overflow
   propio salvo que una pagina se lo fije en linea (para el recorte de esquinas
   redondeadas de una cabecera en degradado), y ahi seguir forzando visible es el efecto
   que se buscaba desde el principio. */
.modal-dialog,
.modal-content,
.modal-body {
    overflow: visible !important;
}

/* z-index alto y por encima de la tarjeta */
.credp-dd-panel {
    position: absolute;
    z-index: 1060;
    top: calc(100% + 2px);
    left: 0;
    width: 100%;
    min-width: 250px;
    max-width: 320px;
    background: var(--bg-card, #fff);
    border: 1px solid var(--border, #cbd5e1);
    border-radius: 4px;
    box-shadow: 0 4px 14px rgba(15, 23, 42, 0.18);
}
.credp-dd-panel.credp-dd-panel-arriba {
    top: auto;
    bottom: calc(100% + 2px);
    box-shadow: 0 -4px 14px rgba(15, 23, 42, 0.18);
}
.credp-dd-tools { padding: 0.3rem 0.4rem; border-bottom: 1px solid var(--border, #e2e8f0); }
.credp-dd-tools input.credp-dd-buscar {
    height: 24px !important;
    min-height: 24px !important;
    padding: 1px 5px !important;
    font-size: 0.75rem !important;
    border-radius: 3px !important;
}
.credp-dd-hint {
    display: flex;
    align-items: flex-start;
    gap: 0.3rem;
    margin-top: 0.25rem;
    padding: 0.2rem 0.35rem;
    font-size: 0.67rem;
    line-height: 1.25;
    color: var(--text-muted, #475569);
    background: var(--color-neutral-bg, #f8fafc);
    border: 1px solid var(--border, #e2e8f0);
    border-radius: 3px;
    white-space: normal !important;
    word-break: normal;
    overflow-wrap: break-word;
    box-sizing: border-box;
}
.credp-dd-hint span {
    flex: 1 1 auto;
    white-space: normal !important;
    word-break: normal;
    overflow-wrap: break-word;
    text-align: left !important;
}
.credp-dd-hint i {
    color: var(--primary-tint-text, #0284c7);
    font-size: 0.70rem;
    margin-top: 0.1rem;
    flex-shrink: 0;
}

.credp-dd-lista { max-height: 120px; overflow-y: auto; padding: 0.2rem 0; text-align: left !important; }
.credp-dd-item {
    display: flex;
    align-items: center;
    justify-content: flex-start !important;
    text-align: left !important;
    gap: 0.35rem;
    margin: 0;
    padding: 0.25rem 0.5rem;
    font-size: 0.75rem;
    font-weight: 400;
    line-height: 1.25;
    cursor: pointer;
    white-space: normal;
    word-break: break-word;
}
.credp-dd-item span {
    flex: 1 1 auto;
    text-align: left !important;
    word-break: break-word;
}
.credp-dd-item:hover { background: var(--primary-tint, #eff6ff); }
/* Obligatorio: el display:none que el navegador aplica a [hidden] viene de SU hoja, y
   cualquier regla de autor le gana sin importar la especificidad. Sin esto, el buscador
   marcaria los items como hidden y se seguirian viendo los 909. */
.credp-dd-item[hidden] { display: none; }
.credp-dd-item input { margin-top: 0.1rem; flex: 0 0 auto; }
/* Lo que se escribio a mano y no esta en ningun catalogo, marcado para distinguirlo. */
.credp-dd-item-propio span { font-style: italic; color: var(--primary-tint-text, #0284c7); }
/* "VARIAS EMBARCACIONES" (solo operadores portuarios, ver js/app_credpers_barco.js): opcion
   general, no un barco del catalogo; va primera y separada de la lista de barcos. */
.credp-dd-item-varias { border-bottom: 1px solid var(--border); margin-bottom: 0.15rem; }
.credp-dd-item-varias span { font-weight: 600; }
.credp-dd-item-varias i { flex: 0 0 auto; color: var(--primary-tint-text, #2563eb); }

.credp-dd-sinresultados,
.credp-dd-pie {
    padding: 0.3rem 0.5rem;
    font-size: 0.72rem;
    border-top: 1px solid var(--border, #e2e8f0);
}
.credp-dd-sinresultados { color: var(--secondary, #64748b); border-top: 0; }
.credp-dd-pie { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; justify-content: space-between; }
/* Cuantas marcas quedan segun dbo.parametros; se pone en rojo al llegar al tope. */
.credp-dd-tope { flex: 1 1 100%; order: -1; color: var(--secondary, #64748b); }
.credp-dd-tope:empty { display: none; }
.credp-dd-tope.credp-dd-tope-lleno { color: var(--color-danger, #dc2626); font-weight: 600; }
.credp-dd-pie button {
    padding: 0;
    font-size: 0.72rem;
    color: var(--primary-tint-text, #0284c7);
    background: none;
    border: 0;
    cursor: pointer;
}
.credp-dd-pie .credp-dd-limpiar { color: var(--secondary, #64748b); }
.credp-dd-pie button:hover { text-decoration: underline; }
.credp-dd-agregar-txt { font-weight: 600; }

/* --------------------------------------------------------------------------
   16.b Modo SELECCIÓN ÚNICA (campo "Cargo / Función")

   Un ítem sin casilla: la selección se ve por el resaltado, no por una marca.
   Se distingue con `.credp-dd-simple` en la raíz para no alterar el modo
   múltiple, que sigue exactamente igual.
   -------------------------------------------------------------------------- */
.credp-dd-simple .credp-dd-item { align-items: center; }
.credp-dd-simple .credp-dd-item[aria-selected="true"] {
    font-weight: 600;
    color: var(--primary-tint-text, #0284c7);
    background: var(--primary-tint, #eff6ff);
}
/* El check de la opción elegida. Ocupa sitio siempre para que la lista no
   se desplace lateralmente al cambiar de opción. */
.credp-dd-simple .credp-dd-check {
    flex: 0 0 auto;
    width: 0.8rem;
    font-size: 0.65rem;
    color: var(--primary-tint-text, #0284c7);
    visibility: hidden;
}
.credp-dd-simple .credp-dd-item[aria-selected="true"] .credp-dd-check { visibility: visible; }

/* El renglón "+ Agregar «…»" y el aviso de que no hay coincidencias comparten
   el pie del panel. `.credp-dd-agregar` es un botón de ancho completo para que
   sea fácil de acertar con el ratón. */
.credp-dd-agregar {
    display: block;
    width: 100%;
    padding: 0.3rem 0.5rem;
    font-size: 0.72rem;
    font-weight: 600;
    text-align: left;
    color: var(--primary-tint-text, #0284c7);
    background: none;
    border: 0;
    border-top: 1px solid var(--border, #e2e8f0);
    cursor: pointer;
}
.credp-dd-agregar:hover { background: var(--primary-tint, #eff6ff); }
.credp-dd-agregar[hidden] { display: none; }

.credp-dd-aviso { margin-top: 2px; font-size: 0.65rem; color: var(--secondary, #64748b); }
.credp-dd-aviso:empty { display: none; }
.credp-dd-aviso.credp-aviso-alerta { color: var(--color-danger, #dc2626); font-weight: 600; }

/* --------------------------------------------------------------------------
   16.c Badge informativo "N vigentes" dentro de una celda de nómina
   (.credp-badge-vigentes). Lo usan la nómina de Autorización de Credenciales
   de Personal (vigentes por cargo) y las dos de Cartas Pase (vigentes por
   persona). Es un <button> -accesible por teclado, abre un modal- pero SIN la
   clase .btn, a propósito: esas páginas fuerzan `.table-modern tbody td .btn`
   a cuadrados de 26x26px para los íconos de fila, y aplastarían el texto.
   Aquí solo se quita el cromo nativo del <button>; el color lo ponen
   .badge.bg-warning.text-dark de Bootstrap.
   -------------------------------------------------------------------------- */
.credp-badge-vigentes {
    background-color: #fffbeb !important;
    border: 1px solid #f59e0b !important;
    color: #92400e !important;
    cursor: pointer;
    font: inherit;
    font-size: 0.74rem !important;
    font-weight: 600 !important;
    padding: 0.22rem 0.55rem !important;
    border-radius: 5px !important;
    display: inline-flex !important;
    align-items: center !important;
    gap: 0.35rem !important;
    line-height: 1.25 !important;
    vertical-align: middle !important;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05) !important;
    transition: all 0.15s ease-in-out !important;
}
.credp-badge-vigentes i {
    color: #d97706 !important;
    font-size: 0.74rem !important;
}
.credp-badge-vigentes:hover,
.credp-badge-vigentes:focus-visible {
    background-color: #fef3c7 !important;
    border-color: #d97706 !important;
    color: #78350f !important;
    outline: 2px solid var(--primary-tint, #93c5fd);
    outline-offset: 1px;
}
.credp-badge-vigentes:hover i,
.credp-badge-vigentes:focus-visible i {
    color: #b45309 !important;
}

/* --------------------------------------------------------------------------
   16.d Badges de estado de resolución (.badge-status-autorizado / .badge-status-no-autorizado)
   Utilizados en el pie de las pantallas de verificación de credenciales y cartas pase
   (frm_checksolcartaspase.php, frm_checksolcredencialespers.php, frm_checksolactcredevent.php,
   frm_checksolcredencialesevent.php) cuando la solicitud fue AUTORIZADA (5) o NO AUTORIZADA (7).
   Diseño de pastilla de alto contraste y legibilidad en modo claro y modo oscuro.
   -------------------------------------------------------------------------- */
.badge-status-autorizado {
    background-color: #f0fdf4 !important;
    border: 1px solid #16a34a !important;
    color: #15803d !important;
    font-size: 0.82rem !important;
    font-weight: 700 !important;
    padding: 0.25rem 0.85rem !important;
    border-radius: 6px !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    letter-spacing: 0.03em !important;
    height: 26px !important;
    line-height: 1 !important;
    vertical-align: middle !important;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05) !important;
    transition: all 0.15s ease-in-out !important;
}
.badge-status-autorizado i {
    color: #16a34a !important;
    font-size: 0.85rem !important;
}

.badge-status-no-autorizado {
    background-color: #fef2f2 !important;
    border: 1px solid #dc2626 !important;
    color: #991b1b !important;
    font-size: 0.82rem !important;
    font-weight: 700 !important;
    padding: 0.25rem 0.85rem !important;
    border-radius: 6px !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    letter-spacing: 0.03em !important;
    height: 26px !important;
    line-height: 1 !important;
    vertical-align: middle !important;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05) !important;
    transition: all 0.15s ease-in-out !important;
}
.badge-status-no-autorizado i {
    color: #dc2626 !important;
    font-size: 0.85rem !important;
}

/* Solicitud ANULADA (0 antigua o 24, 2026-10-17): gris, no rojo. Rojo = rechazada, que es
   corregible; anular es definitivo. Mismos tonos que .estado-pill--anulada del modulo externo. */
.badge-status-anulado {
    background-color: #f1f5f9 !important;
    border: 1px solid #94a3b8 !important;
    color: #475569 !important;
    font-size: 0.82rem !important;
    font-weight: 700 !important;
    padding: 0.25rem 0.85rem !important;
    border-radius: 6px !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    letter-spacing: 0.03em !important;
    height: 26px !important;
    line-height: 1 !important;
    vertical-align: middle !important;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05) !important;
}
.badge-status-anulado i {
    color: #64748b !important;
    font-size: 0.85rem !important;
}

/* Boton "Anular" de la EMPRESA en sus consultas (frm_consulta_af02/af03/cartaspase) y linea de
   quien anulo bajo ANULADA. Los pinta lib/anulacion_solicitud.php; ver (P.18). Rojo apagado:
   es una accion definitiva, pero no debe competir con la etiqueta de estado. */
.btn-anular-empresa {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    margin: 0.3rem auto 0;
    padding: 0.12rem 0.5rem;
    font-size: 0.68rem;
    font-weight: 600;
    line-height: 1.3;
    color: #b4232c;
    background-color: #fff0f1;
    border: 1px solid #f1b8bd;
    border-radius: 999px;
    cursor: pointer;
}
.btn-anular-empresa:hover,
.btn-anular-empresa:focus-visible {
    color: #ffffff;
    background-color: #b4232c;
    border-color: #b4232c;
}
.anul-origen-mini {
    margin-top: 0.15rem;
    font-size: 0.62rem;
    color: #64748b;
    white-space: nowrap;
}

/* --------------------------------------------------------------------------
   16.e Chips de barco en las vistas de VERIFICACION (ficha de barcos, 2026-10-02)
   Los pinta barcos_chips_revision() (lib/barcos.php) bajo el campo Barco de
   frm_checksolcredencialespers.php, frm_checksolactcredevent.php y frm_checksolcartaspase.php.
   Aqui y no en md_revisar_barco.php: ese modal solo se incluye con el permiso (2,2,13) y los
   chips se ven siempre. Colores de las familias --alert-*, que ya invierten en modo oscuro.
   -------------------------------------------------------------------------- */
.barco-chips { display: flex; flex-wrap: wrap; gap: .3rem .4rem; margin-top: .35rem; }
.barco-chip {
    display: inline-flex; align-items: center; gap: .35rem;
    padding: .15rem .5rem; border-radius: 12px;
    background: var(--color-neutral-bg, #f1f5f9); border: 1px solid var(--border, #e2e8f0);
    color: var(--text-main, #1e293b); font-size: 11.5px; font-weight: 600; line-height: 1.4;
}
.barco-chip > .fa-ship { color: var(--text-muted, #64748b); font-size: 10px; }
.barco-chip .barco-chip-info { color: var(--text-muted, #64748b); font-size: 11px; cursor: help; }
/* Procedencia del dato vigente del barco (Fase A, 2026-10-08): confirmado por la fuente o aprobado por
   APM. Solo en las vistas internas de verificacion. Lo copiado de GS va sin icono desde 2026-10-14. */
.barco-chip .barco-chip-proc { font-size: 10px; cursor: help; }
.barco-chip .barco-chip-proc-oficial { color: var(--alert-success-text); }
.barco-chip .barco-chip-proc-ficha   { color: var(--primary-tint-text); }
.barco-chip .btn.barco-pend-btn {
    background: var(--alert-warning-bg, #fffbeb) !important;
    border: 1px solid var(--alert-warning-border, #fcd34d) !important;
    color: var(--alert-warning-text, #92400e) !important;
    font-size: 10px !important; font-weight: 700; line-height: 1.3 !important;
    padding: 1px 7px !important; border-radius: 9px !important;
    width: auto !important; height: auto !important; min-height: 0 !important;
    display: inline-flex !important; align-items: center; gap: .25rem; white-space: nowrap;
}
.barco-chip .btn.barco-pend-btn:hover { filter: brightness(0.95); }
/* Correccion de datos por APM (2026-10-12): icono discreto, area pulsable de 24 px. */
.barco-chip .btn.barco-corregir-btn {
    background: transparent !important; border: 1px solid transparent !important;
    color: var(--text-muted, #64748b) !important; font-size: 10px !important; line-height: 1 !important;
    padding: 0 !important; border-radius: 50% !important;
    width: 24px !important; height: 24px !important; min-height: 0 !important;
    display: inline-flex !important; align-items: center; justify-content: center;
}
.barco-chip .btn.barco-corregir-btn:hover, .barco-chip .btn.barco-corregir-btn:focus-visible {
    border-color: var(--border, #e2e8f0) !important; color: var(--primary-tint-text) !important;
}
.barco-chip .barco-chip-nota, .barco-chip .barco-chip-ok, .barco-chip .barco-chip-rech {
    font-size: 10px; font-weight: 700; padding: 0 6px; border-radius: 9px; border: 1px solid;
}
.barco-chip .barco-chip-nota { background: var(--alert-neutral-bg); border-color: var(--alert-neutral-border); color: var(--alert-neutral-text); }
.barco-chip .barco-chip-ok   { background: var(--alert-success-bg); border-color: var(--alert-success-border); color: var(--alert-success-text); }
.barco-chip .barco-chip-rech { background: var(--alert-danger-bg);  border-color: var(--alert-danger-border);  color: var(--alert-danger-text); }
/* Icono del listado de tramites (js_tramitescredpersevent.php): solicitud con barco por revisar. */
.barco-lista-pend {
    display: inline-flex; align-items: center; justify-content: center;
    width: 18px; height: 18px; margin-left: .2rem; border-radius: 50%; vertical-align: middle;
    background: var(--alert-warning-bg, #fffbeb); border: 1px solid var(--alert-warning-border, #fcd34d);
    color: var(--alert-warning-text, #92400e); font-size: 9px;
}

/* --------------------------------------------------------------------------
   16.b ÁREA / DESTINO CON INTERRUPTORES (.apm-sw-*)
   2026-10-19, petición expresa: el destino de la solicitud vuelve a ser una fila de
   interruptores SÍ/NO, uno por destino permitido (como antes del desplegable de chips),
   porque el "+ Agregar" daba a entender que se podían crear áreas nuevas. Lo pinta
   form/servicios_autoring/js/app_credpers_area.js; en Patio, el campo de número va pegado
   a su interruptor. Los colores salen de tokens con variante oscura (sección 1.b).
   -------------------------------------------------------------------------- */
.apm-sw-lista {
    display: flex; flex-wrap: wrap; align-items: center; gap: .35rem .5rem;
    min-height: var(--control-height, 27px);
}
.apm-sw-item {
    display: inline-flex; align-items: center; gap: .4rem;
    padding: 2px 4px 2px 10px; border-radius: 999px;
    border: 1px solid var(--border, #e2e8f0); background: var(--bg-card, #fff);
    transition: border-color .15s, background-color .15s;
}
.apm-sw-item.apm-sw-on { border-color: var(--color-success, #16a34a); background: var(--alert-success-bg, #f0fdf4); }
.apm-sw-item.apm-sw-propio .apm-sw-nombre { font-style: italic; }
.apm-sw-nombre {
    font-size: .78rem; font-weight: 600; color: var(--text-main, #0f172a);
    white-space: nowrap; cursor: pointer; margin: 0; user-select: none;
}
.apm-sw-item #npatio {
    height: 22px !important; min-height: 22px !important; max-height: 22px !important;
    width: 64px; padding: 0 .3rem !important; text-align: center;
    font-size: .76rem !important; font-weight: 600; border-radius: 4px !important;
}
.apm-sw-toggle { position: relative; display: inline-flex; margin: 0; cursor: pointer; }
.apm-sw-toggle input {
    position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; pointer-events: none;
}
.apm-sw-pista {
    position: relative; display: inline-flex; align-items: center;
    width: 46px; height: 20px; border-radius: 999px;
    background: var(--color-neutral-bg, #f1f5f9); border: 1px solid var(--border-strong, #cbd5e1);
    font-size: 9px; font-weight: 700; letter-spacing: .03em;
    transition: background-color .15s, border-color .15s;
}
.apm-sw-pista::after {
    content: ""; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px;
    border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(15, 23, 42, .35);
    transition: transform .15s;
}
.apm-sw-si, .apm-sw-no { position: absolute; top: 50%; transform: translateY(-50%); }
.apm-sw-si { left: 7px; color: #fff; visibility: hidden; }
.apm-sw-no { right: 6px; color: var(--color-neutral-text, #475569); }
.apm-sw-toggle input:checked + .apm-sw-pista { background: var(--color-success, #16a34a); border-color: var(--color-success, #16a34a); }
.apm-sw-toggle input:checked + .apm-sw-pista::after { transform: translateX(26px); }
.apm-sw-toggle input:checked + .apm-sw-pista .apm-sw-si { visibility: visible; }
.apm-sw-toggle input:checked + .apm-sw-pista .apm-sw-no { visibility: hidden; }
.apm-sw-toggle input:focus-visible + .apm-sw-pista { outline: 2px solid var(--primary, #2563eb); outline-offset: 2px; }
.apm-sw-toggle input:disabled + .apm-sw-pista { opacity: .55; cursor: not-allowed; }

/* Motivo de la solicitud (2026-10-19): <textarea rows=1> que crece con el texto en vez de una
   caja de una línea que escondía parte de los 150/300 caracteres. Mismo alto de partida que
   los controles de la fila (27px, no los 34px de los textarea de la sección 3); el Enter se
   bloquea en el JS de la página, así que el motivo sigue siendo un solo párrafo. */
textarea.form-control-modern.apm-motivo {
    min-height: var(--control-height, 27px) !important;
    resize: none !important; overflow: hidden; line-height: 1.35;
    padding-top: .2rem; padding-bottom: .2rem;
}
.apm-motivo-contador {
    font-size: .7rem; color: var(--text-muted, #475569); text-align: right;
    line-height: 1.2; margin-top: 2px; min-height: .85rem;
}
.apm-motivo-contador.apm-motivo-tope { color: var(--color-danger, #dc2626); font-weight: 600; }

/* ==========================================================================
   17. MODO OSCURO — OVERRIDES DE COMPONENTES Y LIBRERÍAS VENDOR

   Lo que las variables de la sección 1.b no alcanzan a resolver por sí solas:
   veladuras blancas fijas (rgba literal, no hex, así que no hay token que sustituir),
   y librerías vendorizadas que no traen ninguna hoja "dark" propia (DataTables 2.3.8,
   Select2 4.1.0, SweetAlert2, bootstrap4-toggle — ver doc B). Todo colgado de
   `:root[data-apm-theme="dark"]` + selector del componente, nunca tocando los .js
   compartidos (app.js sigue vetado, ver doc F/L): el theming es 100% CSS.
   ========================================================================== */

/* Las dos veladuras translúcidas que cubren la tabla/tarjeta durante un AJAX
   (.loader-overlay de .card-modern y #loader-overlay de los listados con app.js) son
   blancas a proposito en claro: en oscuro, ese mismo blanco es un fogonazo. Mismo
   backdrop-filter/blur, solo cambia el color por debajo. */
:root[data-apm-theme="dark"] .loader-overlay {
    background: rgba(15, 23, 42, 0.82);
}
:root[data-apm-theme="dark"] #loader-overlay {
    background-color: rgba(15, 23, 42, 0.85);
}

/* -------------------- DataTables 2.3.8 -------------------- */
/* El buscador, el selector de registros y el paginador son <input>/<select> que ya
   cubre la sección 3/9 via var(); lo que falta es el texto suelto (dt-info, los
   números del paginador) y el fondo de la fila "hover" que datatables.css fija en
   claro. Los botones de página deshabilitados/activos de datatables.css usan sus
   propias variables --dt-*, que no están declaradas por defecto (initial), asi que
   caen al valor inicial (currentColor/transparent) y heredan bien de aqui sin
   necesitar redeclararlas una a una. */
:root[data-apm-theme="dark"] div.dt-info,
:root[data-apm-theme="dark"] div.dt-length,
:root[data-apm-theme="dark"] div.dt-search label {
    color: var(--text-muted);
}
:root[data-apm-theme="dark"] .dataTable tbody tr:hover > * {
    box-shadow: none;
}
:root[data-apm-theme="dark"] .dt-paging .dt-paging-button {
    color: var(--text-main) !important;
}
:root[data-apm-theme="dark"] .dt-paging .dt-paging-button.disabled {
    color: var(--text-faint) !important;
}
:root[data-apm-theme="dark"] .dt-paging .dt-paging-button.current {
    background: var(--primary) !important;
    color: #ffffff !important;
    border-color: var(--primary) !important;
}

/* -------------------- Tablas en Modo Oscuro: Textos heredados y etiquetas --------------------
   Ciertas respuestas AJAX heredadas (reg_atencion_tramite.php y similares) inyectan
   estilos en línea como `style='color:black;'` o botones `<button class="btn btn-default btn-xs">`
   para mostrar estados ("APROBADO", "NO APROBADO", etc.). En modo oscuro sobre el fondo #1e293b
   de la fila, ese texto negro resulta ilegible. Esta regla fuerza a que el texto herede el color
   claro (`--text-main`) en modo oscuro, y aclara textos verdes/rojos para darles contraste suficiente. */
:root[data-apm-theme="dark"] .table-modern [style*="color:black" i],
:root[data-apm-theme="dark"] .table-modern [style*="color: black" i],
:root[data-apm-theme="dark"] .table-modern [style*="color:#000" i],
:root[data-apm-theme="dark"] .table-modern [style*="color: #000" i],
:root[data-apm-theme="dark"] .table-modern [style*="color:rgb(0,0,0)" i],
:root[data-apm-theme="dark"] .table-modern [style*="color: rgb(0, 0, 0)" i],
:root[data-apm-theme="dark"] .dataTable [style*="color:black" i],
:root[data-apm-theme="dark"] .dataTable [style*="color: black" i],
:root[data-apm-theme="dark"] .dataTable [style*="color:#000" i],
:root[data-apm-theme="dark"] .dataTable [style*="color: #000" i],
:root[data-apm-theme="dark"] .dataTable [style*="color:rgb(0,0,0)" i],
:root[data-apm-theme="dark"] .dataTable [style*="color: rgb(0, 0, 0)" i],
:root[data-apm-theme="dark"] .table-modern .btn-default,
:root[data-apm-theme="dark"] .table-modern .btn-default span,
:root[data-apm-theme="dark"] .table-modern .btn-default strong,
:root[data-apm-theme="dark"] .dataTable .btn-default,
:root[data-apm-theme="dark"] .dataTable .btn-default span,
:root[data-apm-theme="dark"] .dataTable .btn-default strong {
    color: var(--text-main) !important;
}

:root[data-apm-theme="dark"] .table-modern [style*="color:green" i],
:root[data-apm-theme="dark"] .table-modern [style*="color: green" i],
:root[data-apm-theme="dark"] .dataTable [style*="color:green" i],
:root[data-apm-theme="dark"] .dataTable [style*="color: green" i] {
    color: #4ade80 !important;
}

:root[data-apm-theme="dark"] .table-modern [style*="color:red" i],
:root[data-apm-theme="dark"] .table-modern [style*="color: red" i],
:root[data-apm-theme="dark"] .dataTable [style*="color:red" i],
:root[data-apm-theme="dark"] .dataTable [style*="color: red" i] {
    color: #f87171 !important;
}

/* -------------------- Select2 4.1.0 -------------------- */
/* `dropdownParent:$('body')` (ver doc B) lo cuelga de <body>, fuera de .page-wrapper —
   pero sigue bajo <html>, así que `:root[data-apm-theme="dark"]` lo alcanza igual. */
:root[data-apm-theme="dark"] .select2-container--default .select2-selection--single {
    background-color: var(--bg-card);
    border-color: var(--border);
}
:root[data-apm-theme="dark"] .select2-container--default .select2-selection--single .select2-selection__rendered {
    color: var(--text-main);
}
:root[data-apm-theme="dark"] .select2-dropdown {
    background-color: var(--bg-card);
    border-color: var(--border);
    color: var(--text-main);
}
:root[data-apm-theme="dark"] .select2-search--dropdown .select2-search__field {
    background-color: var(--bg-page);
    border-color: var(--border);
    color: var(--text-main);
}
:root[data-apm-theme="dark"] .select2-results__option {
    color: var(--text-main);
}
:root[data-apm-theme="dark"] .select2-container--default .select2-results__option--highlighted[aria-selected] {
    background-color: var(--primary);
    color: #ffffff;
}

/* -------------------- SweetAlert2 -------------------- */
/* `data-apm-theme` está en <html>, así que alcanza al popup tanto si se dibuja en
   document.body como con `target: elModal` (ver la trampa de foco de doc B) — sin caso
   especial. Nunca se toca app.js: los parámetros de Swal.fire() siguen igual. */
:root[data-apm-theme="dark"] .swal2-popup {
    background: var(--bg-card);
    color: var(--text-main);
}
:root[data-apm-theme="dark"] .swal2-popup .swal2-html-container,
:root[data-apm-theme="dark"] .swal2-popup #swal2-title {
    color: var(--text-main);
}
:root[data-apm-theme="dark"] .swal2-popup .swal2-close {
    color: var(--text-muted);
}

/* -------------------- bootstrap4-toggle -------------------- */
/* El interruptor en sí (data-toggle="toggle") ya es de color solido en los dos
   estados (verde/gris) y no necesita ajuste; solo el borde del "hueco" del switch,
   que bootstrap4-toggle fija en un gris de Bootstrap 4 que no viene de esta hoja. */
:root[data-apm-theme="dark"] .toggle.btn {
    border-color: var(--border) !important;
}

/* -------------------- Modales con fondo blanco EN LÍNEA (2026-09-04) --------------------
   La mayoría de los `md_*.php` del proyecto (~23, auditados con grep: md_showmensajesolic.php,
   md_verificacion_neg.php, md_anular_solic_*.php, md_add_persona*.php, md_agregar_personas.php,
   md_modificar_personas.php, md_solic_*_rert_persona.php, md_finaverif_*.php…) escriben la
   tarjeta del modal así: `.modal-content` con un `<div class="modal-header" style="background:
   linear-gradient(...)">` de color fijo (eso SÍ se queda: cabecera con texto blanco siempre,
   autocontenida, ver el criterio de "isla clara" más abajo) y un `<div class="modal-body"
   style="...background:#fff;">` — el cuerpo, blanco EN LÍNEA, sin `!important`. Con solo la
   variable `--bs-modal-bg` (sección 1.b) el `.modal-content` de fondo ya queda oscuro, pero ese
   `background:#fff` en línea del `.modal-body` se pinta encima y gana visualmente porque un
   estilo en línea sin `!important` sigue venciendo a cualquier regla NORMAL de esta hoja — hace
   falta `!important` aquí también (un `!important` de hoja de estilos sí vence a un estilo en
   línea sin `!important`, es la única combinación que lo permite). Detectado en vivo probando
   `#dataSwhowms` con Chrome DevTools MCP: `.modal-content` medía `rgb(15,23,42)` por CSS
   computado pero se veía blanco en pantalla — el cuerpo encima lo tapaba.
   No hace falta editar los ~23 archivos: esta única regla, con más especificidad que un
   `style=""` (por ser `!important` en hoja) y aplicada al mismo selector `.modal-body` que usan
   todos, los corrige de una sola vez. */
:root[data-apm-theme="dark"] .modal-content {
    background-color: var(--bg-card) !important;
    color: var(--text-main) !important;
}
:root[data-apm-theme="dark"] .modal-body {
    background-color: var(--bg-card) !important;
    color: var(--text-main) !important;
}
/* Mismo defecto, mismo arreglo, tercera pieza del molde: el pie del modal (los botones
   Guardar/Cancelar) también trae `style="...background:#f8fafc;border-top:1px solid
   #e2e8f0;..."` en línea en la mayoría de estos `md_*.php` (auditado 2026-09-04: md_anular_
   solic_*, md_finaverif_*, md_autorizaingpuerto, md_retornarsolicitud, md_add_persona*,
   md_agregar_personas, md_modificar_personas, md_solic_*_canc_solicitud, md_solic_*_
   rert_persona, md_extender_plazo_credpers, md_registrar_pago_presencial, md_verificacion_neg,
   md_verificacionSCPyE, md_showmensajesolic, md_aprobar_rechazar_comprobante — todos alojados
   en páginas ya modernizadas). */
:root[data-apm-theme="dark"] .modal-footer {
    background-color: var(--bg-card) !important;
    border-top-color: var(--border) !important;
}

/* Los campos de solo lectura de estos mismos modales van con `readonly` + un
   `style="background-color:#f1f5f9;..."` en línea, SIN color propio: heredan el color de
   `.modal-body`/`.form-control`, que ya es claro-sobre-claro se vuelve CLARO-SOBRE-CLARO en
   oscuro (texto ahora claro, vía --bs-body-color, sobre ese mismo gris casi blanco que se
   quedó fijo) — la misma familia de bug que la colisión de `home.php` (H.3), solo que por
   herencia en vez de por coincidencia exacta de hex.
   Para [readonly] el texto debe tener alto contraste con --text-main (los datos que el usuario
   lee: Cédula, Nombres, RUC, Empresa, etc.). Para :disabled (deshabilitados inactivos)
   se conserva --text-muted. */
:root[data-apm-theme="dark"] input[readonly],
:root[data-apm-theme="dark"] textarea[readonly] {
    background-color: var(--color-neutral-bg) !important;
    color: var(--text-main) !important;
    -webkit-text-fill-color: var(--text-main);
}
:root[data-apm-theme="dark"] input:disabled,
:root[data-apm-theme="dark"] textarea:disabled,
:root[data-apm-theme="dark"] select:disabled {
    background-color: var(--color-neutral-bg) !important;
    color: var(--text-muted) !important;
    -webkit-text-fill-color: var(--text-muted);
}

/* Subtítulos de sección en modales (.credp-modal-seccion-header) */
.credp-modal-seccion-header {
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-muted);
    padding-bottom: 0.25rem;
    margin-bottom: 0.5rem;
    border-bottom: 1px solid var(--border);
    display: flex;
    align-items: center;
    gap: 0.4rem;
}
.credp-modal-seccion-header i {
    color: var(--primary-tint-text) !important;
    font-size: 0.8rem;
}
:root[data-apm-theme="dark"] .credp-modal-seccion-header {
    color: var(--text-main);
    border-bottom-color: var(--border);
}

/* Tarjetas de formulario de credenciales (.credp-card-cabecera, .credp-card-cuerpo, .credp-card-nomina) */
.credp-card-cabecera,
.credp-card-cuerpo,
.credp-card-nomina {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--border-radius, 8px);
    box-shadow: var(--shadow);
}

/* .credp-card-cabecera traía padding/margin propios repetidos (idénticos) en 6 de las 8 páginas
   de la familia de verificación/autorización de credenciales — se centraliza aquí. */
.credp-card-cabecera {
    padding: 0.75rem 1.25rem 0.55rem 1.25rem;
    margin-bottom: 0.65rem;
}

/* Título de cabecera de esta misma familia (icono + nombre de pantalla + N.° Trámite a la
   derecha). Estaba duplicado letra por letra en 6 `<style>` de página (mismo hex #1e3a8a, mismo
   border-bottom) — un cambio aquí ahora alcanza a las 8 de una vez, incluida la única que todavía
   no lo usaba (frm_checksolcartaspase.php, que tenía su propio título con card-title-modern). */
.credp-titulo-cabecera {
    font-size: 0.95rem;
    font-weight: 700;
    color: #1e3a8a;
    letter-spacing: 0.02em;
    margin: 0;
    padding-bottom: 0.5rem;
    border-bottom: 1px solid var(--border);
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}

:root[data-apm-theme="dark"] .credp-card-cabecera,
:root[data-apm-theme="dark"] .credp-card-cuerpo,
:root[data-apm-theme="dark"] .credp-card-nomina {
    background: var(--bg-card) !important;
    border-color: var(--border) !important;
}

:root[data-apm-theme="dark"] .credp-titulo-cabecera {
    color: var(--primary-tint-text) !important;
    border-bottom-color: var(--border) !important;
}

/* "Solicitado como" junto al N.° de trámite (2026-10-01) — vistas de check de Credenciales y
   Activación. nombarco mezcla los TIPOS de empresa con los barcos; Separar_empresas_barcos() los
   reparte y cada tipo va en su propia etiqueta, que envuelve a la línea siguiente si no cabe.
   Hereda el tamaño del título, así que se fija en normal y sin mayúsculas forzadas. */
.credp-solicitado-como {
    display: inline-flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.3rem;
    font-size: 0.82rem;
    font-weight: 400;
    letter-spacing: 0;
    color: var(--text-muted);
}
.credp-solicitado-sep { color: var(--text-muted); margin-right: 0.1rem; }
.credp-tipo-chip {
    display: inline-block;
    padding: 0.05rem 0.5rem;
    border-radius: 6px;
    background: var(--color-neutral-bg);
    border: 1px solid var(--border);
    color: var(--text-main);
    font-weight: 600;
    line-height: 1.4;
    white-space: normal;
    overflow-wrap: anywhere;
}

/* Cabecera compacta de las 8 vistas de verificación/autorización (2026-10-19). Objetivo: que la
   nómina empiece más arriba (maqueta medida a 1600x900: de 589 a 368 px, de 1 a 4 filas a la
   vista). Son modificadores, no reemplazan a .credp-card-cabecera/.credp-card-cuerpo, porque el
   módulo externo usa las mismas clases sin compactar. Lo que hace cada uno:
   - .credp-compacta (sobre .credp-card-cabecera) + .credp-cuerpo-compacto (sobre la
     .credp-card-cuerpo que la sigue): las dos tarjetas se ven como UNA, sin hueco ni borde entre
     ellas. Se unen por CSS y no moviendo el marcado para no tocar el anidado de <div> de 8 páginas.
   - El Destino / Área de trabajo sube a la línea del título (.credp-destino-chips, dentro de un
     .credp-solicitado-como). La fila .credp-fila-cabecera, si queda algo en ella (Vigencia,
     Toneladas, Período, Peatonales...), pasa a etiqueta a la izquierda y una sola línea.
   - En el cuerpo, cada columna .row > .col-* se vuelve rejilla "etiqueta | campo".
   - Con chips de ficha de barcos (.barco-chips) la caja del barco se oculta: dice lo mismo que
     los chips. Sigue en el DOM (#nbarco lo leen scripts). Sin soporte de :has() se ven las dos,
     como antes.
   - "Mostrar N registros" y "Buscar" de DataTables suben a la línea del título de la nómina:
     .credp-nomina-ctrls es el hueco y js/apm_nomina_compacta.js los mueve. */
.credp-card-cabecera.credp-compacta {
    padding: 0.6rem 1.25rem 0.15rem 1.25rem !important;
    margin-bottom: 0 !important;
    border-bottom: 0 !important;
    border-bottom-left-radius: 0 !important;
    border-bottom-right-radius: 0 !important;
}
.credp-compacta .credp-titulo-cabecera {
    border-bottom: 0 !important;
    padding-bottom: 0 !important;
    row-gap: 0.3rem;
}
/* display: contents: los chips son hermanos de la etiqueta dentro del .credp-solicitado-como
   (flex-wrap), así que con muchos destinos la etiqueta y los primeros chips comparten línea y el
   resto envuelve debajo, en vez de quedar la etiqueta sola. */
.credp-destino-chips { display: contents; }

/* Período de Cartas pase en la línea del título: fechas en cifras tabulares, unidas por una
   flecha, dentro de una píldora neutra que no se confunde con los chips azules de Área. */
.credp-periodo-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.15rem 0.6rem;
    font-size: 0.76rem;
    font-weight: 600;
    line-height: 1.3;
    font-variant-numeric: tabular-nums;
    color: var(--text-main);
    background: var(--bg-page);
    border: 1px solid var(--border);
    border-radius: 999px;
    white-space: nowrap;
}
.credp-periodo-chip .fa-calendar-alt { color: var(--primary-tint-text, #2563eb); }
.credp-periodo-chip .credp-periodo-flecha { color: var(--text-muted); font-size: 0.62rem; }

.credp-compacta .credp-fila-cabecera {
    align-items: center !important;
    gap: 0.35rem 1rem !important;
    margin-top: 0.35rem !important;
}
.credp-compacta .credp-seccion-cabecera {
    align-items: center !important;
    gap: 0.35rem 1rem !important;
}
.credp-compacta .credp-col-control {
    flex-direction: row !important;
    align-items: center !important;
    gap: 0.45rem !important;
}
.credp-compacta .credp-col-destino { min-width: 0 !important; }
.credp-compacta .credp-fila-cabecera .credp-dd-chips {
    margin: 0;
    padding: 0;
    background: none;
    border: 0;
}
.credp-compacta .credp-separador-v {
    height: 20px !important;
    align-self: center !important;
    margin: 0 0.25rem !important;
}

.credp-card-cabecera.credp-compacta + .credp-card-cuerpo.credp-cuerpo-compacto {
    padding-top: 0.45rem !important;
    margin-top: 0 !important;
    border-top: 0 !important;
    border-top-left-radius: 0 !important;
    border-top-right-radius: 0 !important;
    /* La sombra de esta tarjeta no debe pintar una raya sobre la cabecera, que es su otra mitad. */
    clip-path: inset(0 -16px -16px -16px);
}
.credp-cuerpo-compacto > .row {
    --bs-gutter-y: 0.4rem;
    margin-bottom: 0.4rem !important;
}
.credp-cuerpo-compacto > .row > [class*="col-"] {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: start;
    column-gap: 0.6rem;
}
.credp-cuerpo-compacto > .row > [class*="col-"] > .form-label-modern {
    grid-column: 1;
    margin: 0 !important;
    padding-top: 0.45rem;
    font-size: 0.8rem;
    white-space: nowrap;
}
.credp-cuerpo-compacto > .row > [class*="col-"]:first-child > .form-label-modern { min-width: 6.6rem; }
.credp-cuerpo-compacto > .row > [class*="col-"] > :not(.form-label-modern) { grid-column: 2; }
/* La etiqueta vacía (&nbsp;) que alineaba el botón Guardar con el campo de al lado ya no hace falta. */
.credp-cuerpo-compacto > .row > [class*="col-"] > .form-label-modern.d-none { display: none !important; }
.credp-cuerpo-compacto [class*="col-"]:has(> .barco-chips) > textarea { display: none; }
.credp-cuerpo-compacto .barco-chips { margin-top: 0; padding-top: 0.3rem; }
.credp-cuerpo-compacto .credp-modal-seccion-header { margin: 0.2rem 0 0.4rem !important; }
.credp-cuerpo-compacto .credp-fila-acciones-bottom {
    margin-top: 0.45rem;
    padding-top: 0.45rem;
}

/* Título de la nómina ("NÓMINA DE PERSONAS ...") - mismo valor que ya traían en su <style> varias
   páginas de la familia; aquí para las que no lo tenían y ahora llevan la línea de título con
   .credp-nomina-ctrls. El <style> de cada página va después y sigue mandando donde lo redefine. */
.credp-subtitulo-seccion {
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--text-muted);
    letter-spacing: 0.03em;
    text-transform: uppercase;
    display: inline-flex;
    align-items: center;
    line-height: 1.2;
}
:root[data-apm-theme="dark"] .credp-subtitulo-seccion { color: var(--text-main); }

.credp-nomina-ctrls {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.35rem 1.25rem;
    margin-left: auto;
}
.credp-nomina-ctrls .dt-length,
.credp-nomina-ctrls .dt-search,
.credp-nomina-ctrls .dt-length label,
.credp-nomina-ctrls .dt-search label {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    margin: 0 !important;
    font-size: 0.82rem;
    color: var(--text-muted);
    white-space: nowrap;
}
.credp-nomina-ctrls .form-select,
.credp-nomina-ctrls .form-control {
    height: 28px;
    min-height: 28px;
    padding-top: 0;
    padding-bottom: 0;
    margin: 0 !important;
    font-size: 0.82rem;
}
.credp-nomina-ctrls .form-select { width: auto; display: inline-block; }
.credp-nomina-ctrls .form-control { width: 210px; }

/* Vigencia por persona en la celda ESTADO de la nómina (credenciales y activación): al lado del
   botón y no debajo, para que la fila mida una línea. Si no cabe, envuelve sola debajo. */
.table-modern .credp-vig-celda {
    display: inline-block;
    margin: 0 0 0 0.3rem !important;
    vertical-align: middle;
}

:root[data-apm-theme="dark"] .credp-separador-v {
    background: var(--border) !important;
}

/* .credp-campo-info (2026-09-05) — el azul informativo de los `<select>` "Tipo Identificación"/
   "Estado Civil"/"Tipo Licencia" (md_agregar_personas.php, md_modificar_personas.php,
   md_solic_cred_add_persona.php, md_add_personaasoliccredencpers.php) y del campo de cédula
   readonly de las tarjetas de retiro de persona (md_solic_cred_rert_persona.php,
   md_solic_actcredevent_rert_persona.php). Traía `style="color:#0284c7"` en línea, fijo en los
   dos temas: sobre --bg-page/--bg-card oscuro ese azul da ~4:1 de contraste (AA raspado, se
   nota apagado al lado del resto del texto en --text-main, que da ~15:1). Se sube a #38bdf8 en
   oscuro -el mismo acento que ya usa el sidebar (--apm-header-title-accent, ver doc E)-, y se
   deja el hex original en claro para que ese tema no cambie. */
.credp-campo-info {
    color: #0284c7;
    font-weight: 600;
}
:root[data-apm-theme="dark"] .credp-campo-info,
:root[data-apm-theme="dark"] input[readonly].credp-campo-info {
    color: #38bdf8 !important;
    -webkit-text-fill-color: #38bdf8 !important;
}

/* El icono de cerrar (X) de Bootstrap es un SVG negro fijo (`--bs-btn-close-bg`, sin variante
   oscura en este build) — sobre una cabecera en degradado ya tenía contraste (fondo de color),
   pero un modal con cabecera lisa (sin gradiente propio) lo dejaría casi invisible en negro
   sobre `--bg-card` oscuro. Se invierte solo en oscuro. */
:root[data-apm-theme="dark"] .btn-close {
    filter: invert(1) grayscale(100%) brightness(200%);
}

/* Clases de texto de Bootstrap que SÍ hay que revisar dentro de estos modales (auditado con
   grep sobre los `md_*.php`: 51 `.text-danger`, 31 `.text-white`, 19 `.text-muted`, 10
   `.text-dark`, 5 `.text-warning`, 4 `.text-secondary`, 2 `.text-primary`, 1 `.text-info`).
   `.text-danger/-warning/-primary/-info` son colores de estado saturados — legibles sobre
   fondo oscuro tal cual, mismo criterio que `--color-danger` etc. de la sección 1.b, no se
   tocan. `.text-white` tampoco (blanco fijo, pensado para ir sobre un fondo de color, sigue
   siendo el fondo que sea). Las que SÍ son un gris pensado solo para fondo claro:
   `.text-dark` (`--bs-dark-rgb`, #212529 fijo) y `.text-muted`/`.text-secondary`
   (`--bs-secondary-color`/`--bs-secondary-rgb`, tampoco redeclaradas en la sección 1.b). */
:root[data-apm-theme="dark"] .text-dark {
    color: var(--text-main) !important;
}
:root[data-apm-theme="dark"] .text-muted,
:root[data-apm-theme="dark"] .text-secondary {
    color: var(--text-muted) !important;
}

/* `.bg-light` NO se sobreescribe aquí con una regla propia: se resuelve redeclarando
   `--bs-light-rgb` en el bloque de variables de más arriba (sección 1.b) — ver el comentario
   ahí. Una regla `.bg-light{...!important}` en esta sección competiría con la de Bootstrap
   (también `.bg-light` + `!important`) y ganaría solo por cargarse después, nunca por
   especificidad — exactamente la misma trampa que rompía el `<body class="bg-light">` de
   ~55 páginas, así que no se repite el patrón aquí a propósito. `.bg-*-subtle` (parejas
   fondo/texto ya pensadas para leerse juntas) se deja igual que `.kpi-tile-icon`, sin tocar. */

/* -------------------- Formularios Bootstrap SIN clase `-modern` --------------------
   Un `<select>`/`<input class="form-control">` a secas (sin `-modern`) ya recibe fondo/texto
   oscuros vía `--bs-body-bg`/`--bs-body-color` (sección 1.b) porque Bootstrap los define con
   esas variables — comprobado en vivo sobre el campo `#nombre` readonly de
   `md_solic_cred_rert_persona.php`/`md_solic_actcredevent_rert_persona.php`. Ese campo en
   concreto tiene su PROPIO `background-color:#f8fafc` + `color:#1e293b` en línea (pareja
   autocontenida, "isla clara" a propósito — un campo de solo lectura sobre un modal oscuro,
   legible en los dos temas) y se deja tal cual, no se fuerza aquí. */

/* -------------------- Botones de Bootstrap por defecto (sin `-modern`) --------------------
   `.btn-modern*` (sección 4) ya tienen su propio color de marca en los dos temas; lo que
   queda sin tocar son los `.btn-light`/`.btn-outline-secondary` de Bootstrap "a secas" que
   aparecen sueltos en algún modal viejo (p. ej. un "Cancelar" sin clase `-modern`): en claro
   ya combinan, en oscuro un `.btn-light` (blanco puro) queda demasiado brillante contra el
   resto de la tarjeta. Se atenúa con las variables `--bs-btn-*` que Bootstrap ya expone por
   componente, sin necesidad de pisar cada botón por separado. */
:root[data-apm-theme="dark"] .btn-light {
    --bs-btn-color: var(--text-main);
    --bs-btn-bg: var(--color-neutral-bg);
    --bs-btn-border-color: var(--border);
    --bs-btn-hover-color: var(--text-main);
    --bs-btn-hover-bg: var(--border);
    --bs-btn-hover-border-color: var(--border);
    --bs-btn-active-color: var(--text-main);
    --bs-btn-active-bg: var(--border);
    --bs-btn-active-border-color: var(--border);
}
:root[data-apm-theme="dark"] .btn-outline-secondary {
    --bs-btn-color: var(--text-muted);
    --bs-btn-border-color: var(--border);
    --bs-btn-hover-color: var(--text-main);
    --bs-btn-hover-bg: var(--border);
    --bs-btn-hover-border-color: var(--border);
    --bs-btn-active-color: var(--text-main);
    --bs-btn-active-bg: var(--border);
    --bs-btn-active-border-color: var(--border);
}

/* `.btn-secondary` RELLENO (no outline) es el "Cerrar"/"Cancelar" más repetido de los
   `md_*.php` (~34 archivos, `class="btn btn-secondary"`). Su gris de fábrica (#6c757d) no
   está pensado para conjuntarse con --bg-card oscuro (#1e293b) y queda notablemente más
   claro/brillante que la tarjeta que lo rodea — el efecto concreto que se pidió atenuar.
   Un gris pizarra más oscuro (mismo tono de --border/--text-muted en claro) resuelve sin
   perder el contraste del texto blanco de encima. */
:root[data-apm-theme="dark"] .btn-secondary {
    --bs-btn-bg: #475569;
    --bs-btn-border-color: #475569;
    --bs-btn-hover-bg: #334155;
    --bs-btn-hover-border-color: #334155;
    --bs-btn-active-bg: #334155;
    --bs-btn-active-border-color: #334155;
}

/* -------------------- Indicadores de Progreso Circular (.c100) -------------------- */
:root[data-apm-theme="dark"] .c100 {
    background-color: var(--border);
}
:root[data-apm-theme="dark"] .c100:after {
    background-color: var(--bg-card);
}
:root[data-apm-theme="dark"] .c100 > span {
    color: var(--text-main);
}
:root[data-apm-theme="dark"] .c100:hover > span {
    color: var(--primary-tint-text);
}
/* Dentro de una tabla, el hueco del círculo toma el fondo de SU fila (impar, par u hover):
   --bs-table-bg lo fija la sección 5 en la celda y se hereda hasta el pseudo-elemento. */
:root[data-apm-theme="dark"] .table-modern tbody td .c100:after {
    background-color: var(--bs-table-bg);
}

/* -------------------- Insignias de Estado (.estado-pill) -------------------- */
:root[data-apm-theme="dark"] .estado-pill--tramite {
    background: var(--alert-info-bg) !important;
    color: var(--alert-info-text) !important;
    border-color: var(--alert-info-border) !important;
}
:root[data-apm-theme="dark"] .estado-pill--solicitado {
    background: var(--alert-warning-bg) !important;
    color: var(--alert-warning-text) !important;
    border-color: var(--alert-warning-border) !important;
}
:root[data-apm-theme="dark"] .estado-pill--autorizado {
    background: var(--alert-success-bg) !important;
    color: var(--alert-success-text) !important;
    border-color: var(--alert-success-border) !important;
}
:root[data-apm-theme="dark"] .estado-pill--noautorizado {
    background: var(--alert-danger-bg) !important;
    color: var(--alert-danger-text) !important;
    border-color: var(--alert-danger-border) !important;
}
:root[data-apm-theme="dark"] .estado-pill--anulada {
    background: var(--color-neutral-bg) !important;
    color: var(--color-neutral-text) !important;
    border-color: var(--border) !important;
}

/* -------------------- Botones de Menú Lateral (Sidebar) -------------------- */
:root[data-apm-theme="dark"] nav#sidebar #close-sidebar {
    background: #1e293b !important;
    color: #38bdf8 !important;
    border-color: #334155 !important;
}
:root[data-apm-theme="dark"] nav#sidebar #close-sidebar:hover {
    background: #273449 !important;
    color: #7dd3fc !important;
    border-color: #475569 !important;
}
:root[data-apm-theme="dark"] #show-sidebar {
    background: #1e293b !important;
    border-color: #334155 !important;
    color: #38bdf8 !important;
}
:root[data-apm-theme="dark"] #show-sidebar i {
    color: #38bdf8 !important;
}
:root[data-apm-theme="dark"] #show-sidebar:hover,
:root[data-apm-theme="dark"] #show-sidebar:focus {
    background: #273449 !important;
    border-color: #475569 !important;
    color: #7dd3fc !important;
}
:root[data-apm-theme="dark"] #show-sidebar:hover i,
:root[data-apm-theme="dark"] #show-sidebar:focus i {
    color: #7dd3fc !important;
}

/* -------------------- Preservar y Aclarar Colores Verde y Rojo en Tablas (Modo Oscuro) -------------------- */
:root[data-apm-theme="dark"] .table-modern [style*="color:green" i],
:root[data-apm-theme="dark"] .table-modern [style*="color: green" i],
:root[data-apm-theme="dark"] .table-modern [style*="color:#008000" i],
:root[data-apm-theme="dark"] .table-modern .btn-default [style*="color:green" i],
:root[data-apm-theme="dark"] .table-modern .btn-default [style*="color: green" i],
:root[data-apm-theme="dark"] .table-modern .btn-default span[style*="color:green" i],
:root[data-apm-theme="dark"] .table-modern .btn-default span[style*="color: green" i],
:root[data-apm-theme="dark"] .dataTable [style*="color:green" i],
:root[data-apm-theme="dark"] .dataTable [style*="color: green" i],
:root[data-apm-theme="dark"] .dataTable [style*="color:#008000" i],
:root[data-apm-theme="dark"] .dataTable .btn-default [style*="color:green" i],
:root[data-apm-theme="dark"] .dataTable .btn-default [style*="color: green" i],
:root[data-apm-theme="dark"] .dataTable .btn-default span[style*="color:green" i],
:root[data-apm-theme="dark"] .dataTable .btn-default span[style*="color: green" i] {
    color: #4ade80 !important;
}

:root[data-apm-theme="dark"] .table-modern [style*="color:red" i],
:root[data-apm-theme="dark"] .table-modern [style*="color: red" i],
:root[data-apm-theme="dark"] .table-modern [style*="color:#ff0000" i],
:root[data-apm-theme="dark"] .table-modern .btn-default [style*="color:red" i],
:root[data-apm-theme="dark"] .table-modern .btn-default [style*="color: red" i],
:root[data-apm-theme="dark"] .table-modern .btn-default span[style*="color:red" i],
:root[data-apm-theme="dark"] .table-modern .btn-default span[style*="color: red" i],
:root[data-apm-theme="dark"] .dataTable [style*="color:red" i],
:root[data-apm-theme="dark"] .dataTable [style*="color: red" i],
:root[data-apm-theme="dark"] .dataTable [style*="color:#ff0000" i],
:root[data-apm-theme="dark"] .dataTable .btn-default [style*="color:red" i],
:root[data-apm-theme="dark"] .dataTable .btn-default [style*="color: red" i],
:root[data-apm-theme="dark"] .dataTable .btn-default span[style*="color:red" i],
:root[data-apm-theme="dark"] .dataTable .btn-default span[style*="color: red" i] {
    color: #f87171 !important;
}

/* -------------------- Desplegables (select) y Controles de Formulario en Modo Oscuro --------------------
   Neutraliza el `color: #303F9F` y `background-color: transparent` heredado de `estilos2.css:200`
   en elementos `<select>`, que en modo oscuro resultaba en texto azul oscuro casi invisible sobre
   el fondo `#1e293b` de la tarjeta. Aplica fondo `--bg-card` y texto `--text-main` (#e2e8f0)
   con contraste superior a 13:1, activa `color-scheme: dark` para que el navegador dibuje
   la flecha nativa y el menú popup de opciones en oscuro, y estiliza también las `<option>`. */
:root[data-apm-theme="dark"] select,
:root[data-apm-theme="dark"] .form-select,
:root[data-apm-theme="dark"] .form-select-modern,
:root[data-apm-theme="dark"] select.form-select-modern,
:root[data-apm-theme="dark"] select.form-control-modern,
:root[data-apm-theme="dark"] .form-control-modern,
:root[data-apm-theme="dark"] input.form-control-modern,
:root[data-apm-theme="dark"] textarea.form-control-modern {
    color-scheme: dark !important;
    background-color: var(--bg-card) !important;
    color: var(--text-main) !important;
    border-color: var(--border) !important;
}

:root[data-apm-theme="dark"] select option,
:root[data-apm-theme="dark"] .form-select option,
:root[data-apm-theme="dark"] .form-select-modern option,
:root[data-apm-theme="dark"] option {
    color-scheme: dark !important;
    background-color: var(--bg-card) !important;
    color: var(--text-main) !important;
}

/* Flecha SVG de Bootstrap 5 para .form-select en modo oscuro */
:root[data-apm-theme="dark"] .form-select,
:root[data-apm-theme="dark"] .form-select-modern {
    --bs-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23e2e8f0' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
}

/* -------------------- Insignias de Estado de Cargos (.cargo-badge) -------------------- */
:root[data-apm-theme="dark"] .cargo-badge-pendiente,
:root[data-apm-theme="dark"] #tb_cargos [style*="background:#fef3c7" i],
:root[data-apm-theme="dark"] #tb_cargos [style*="background: #fef3c7" i] {
    background: var(--alert-warning-bg) !important;
    color: var(--alert-warning-text) !important;
    border-color: var(--alert-warning-border) !important;
}

:root[data-apm-theme="dark"] .cargo-badge-aprobada,
:root[data-apm-theme="dark"] #tb_cargos [style*="background:#dcfce7" i],
:root[data-apm-theme="dark"] #tb_cargos [style*="background: #dcfce7" i] {
    background: var(--alert-success-bg) !important;
    color: var(--alert-success-text) !important;
    border-color: var(--alert-success-border) !important;
}

:root[data-apm-theme="dark"] .cargo-badge-rechazada,
:root[data-apm-theme="dark"] #tb_cargos [style*="background:#fee2e2" i],
:root[data-apm-theme="dark"] #tb_cargos [style*="background: #fee2e2" i] {
    background: var(--alert-danger-bg) !important;
    color: var(--alert-danger-text) !important;
    border-color: var(--alert-danger-border) !important;
}

:root[data-apm-theme="dark"] .cargo-badge-anulada,
:root[data-apm-theme="dark"] #tb_cargos [style*="background:#f1f5f9" i],
:root[data-apm-theme="dark"] #tb_cargos [style*="background: #f1f5f9" i] {
    background: var(--color-neutral-bg) !important;
    color: var(--color-neutral-text) !important;
    border-color: var(--border) !important;
}

:root[data-apm-theme="dark"] .cargo-txt-corregido {
    color: #4ade80 !important;
}

:root[data-apm-theme="dark"] .cargo-txt-baja {
    color: #f87171 !important;
}

/* -------------------- Familia VERIFICACIÓN/AUTORIZACIÓN de credenciales (.credp-card-cuerpo, .badge-status-*, .credp-fila-anulada) --------------------
   Compartido por 8 páginas de form/usuarios_apm/ (frm_checksolcredencialespers*.php,
   frm_checksolcartaspase*.php, frm_checksolactcredevent*.php, frm_checksolcredencialesevent*.php):
   cada una traía su propio <style> con estos mismos hex fijos, sin ningún override oscuro salvo
   en frm_checksolcredencialespersa.php (de donde se tomaron los valores). Al repartirse aquí,
   una sola regla corrige las 8 de golpe — mismo criterio que ya usa esta sección con
   .cargo-badge-*/.estado-pill--*. */
:root[data-apm-theme="dark"] .badge-status-autorizado {
    background-color: #052e16 !important;
    border: 1px solid #15803d !important;
    color: #86efac !important;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4) !important;
}
:root[data-apm-theme="dark"] .badge-status-autorizado i {
    color: #4ade80 !important;
}

:root[data-apm-theme="dark"] .badge-status-no-autorizado {
    background-color: #3f1212 !important;
    border: 1px solid #991b1b !important;
    color: #fca5a5 !important;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4) !important;
}
:root[data-apm-theme="dark"] .badge-status-no-autorizado i {
    color: #f87171 !important;
}
:root[data-apm-theme="dark"] .badge-status-anulado {
    background-color: #1e293b !important;
    border: 1px solid #475569 !important;
    color: #cbd5e1 !important;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4) !important;
}
:root[data-apm-theme="dark"] .badge-status-anulado i {
    color: #94a3b8 !important;
}

:root[data-apm-theme="dark"] .btn-anular-empresa {
    color: #fca5a5;
    background-color: #3b1218;
    border-color: #7f1d1d;
}
:root[data-apm-theme="dark"] .btn-anular-empresa:hover,
:root[data-apm-theme="dark"] .btn-anular-empresa:focus-visible {
    color: #ffffff;
    background-color: #b91c1c;
    border-color: #b91c1c;
}
:root[data-apm-theme="dark"] .anul-origen-mini { color: #94a3b8; }

/* Badge "N vigentes" en modo oscuro: fondo ámbar profundo, borde nítido y texto dorado de alto contraste */
:root[data-apm-theme="dark"] .credp-badge-vigentes {
    background-color: #3d2c05 !important;
    border: 1px solid #d97706 !important;
    color: #fde68a !important;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4) !important;
}
:root[data-apm-theme="dark"] .credp-badge-vigentes i {
    color: #fbbf24 !important;
}
:root[data-apm-theme="dark"] .credp-badge-vigentes:hover,
:root[data-apm-theme="dark"] .credp-badge-vigentes:focus-visible {
    background-color: #523b08 !important;
    border-color: #f59e0b !important;
    color: #ffffff !important;
}
:root[data-apm-theme="dark"] .credp-badge-vigentes:hover i,
:root[data-apm-theme="dark"] .credp-badge-vigentes:focus-visible i {
    color: #ffffff !important;
}

/* Fila de persona ANULADA en la nómina: fondo claro fijo (#f8fafc/#f1f5f9 según el archivo) +
   texto #94a3b8, invisible sobre el fondo oscuro de .table-modern. El selector de una sola clase
   (sin table-modern/tbody/tr por delante) ya tiene más especificidad que la regla de cada página
   (que sí encadena esos ancestros pero sin data-apm-theme), así que no hace falta repetir la cadena. */
:root[data-apm-theme="dark"] .credp-fila-anulada {
    background-color: rgba(255, 255, 255, 0.03) !important;
    color: var(--text-faint) !important;
}
:root[data-apm-theme="dark"] .credp-fila-anulada td:not(:last-child) {
    text-decoration-color: var(--border) !important;
}

/* Campos de solo lectura (empresa/barco/sumilla) dentro de la tarjeta .credp-card-cuerpo: llevan
   background-color/border en línea (style=""), así que hace falta !important para vencerlos. */
:root[data-apm-theme="dark"] .credp-card-cuerpo textarea[readonly],
:root[data-apm-theme="dark"] .credp-card-cuerpo input[readonly] {
    background-color: #172338 !important;
    border-color: #334155 !important;
    color: #f1f5f9 !important;
    -webkit-text-fill-color: #f1f5f9 !important;
}

/* -------------------- Botón de Acción de Edición (.btn-outline-apm) en Modo Oscuro --------------------
   En modo claro .btn-outline-apm tiene borde #cfdee9 y texto/icono #2c5f7a.
   En modo oscuro, sobre el fondo de tarjeta #1e293b, el icono #2c5f7a resultaba prácticamente
   invisible (contraste ~1.4:1). Se aplica el azul cielo eléctrico de la marca (#38bdf8 / --primary-tint-text)
   con fondo sutil translúcido rgba(56, 189, 248, 0.12) y borde nítido #0284c7 (contraste ~6.6:1),
   y efecto hover luminoso con fondo sólido #0284c7 e icono blanco. */
:root[data-apm-theme="dark"] .btn-outline-apm,
:root[data-apm-theme="dark"] .table-modern tbody td:last-child .btn-outline-apm {
    border-color: #0284c7 !important;
    color: #38bdf8 !important;
    background-color: rgba(56, 189, 248, 0.12) !important;
}

:root[data-apm-theme="dark"] .btn-outline-apm i,
:root[data-apm-theme="dark"] .table-modern tbody td:last-child .btn-outline-apm i {
    color: #38bdf8 !important;
}

:root[data-apm-theme="dark"] .btn-outline-apm:hover,
:root[data-apm-theme="dark"] .btn-outline-apm:focus,
:root[data-apm-theme="dark"] .table-modern tbody td:last-child .btn-outline-apm:hover,
:root[data-apm-theme="dark"] .table-modern tbody td:last-child .btn-outline-apm:focus {
    background-color: #0284c7 !important;
    border-color: #38bdf8 !important;
    color: #ffffff !important;
    box-shadow: 0 0 8px rgba(56, 189, 248, 0.45) !important;
}

:root[data-apm-theme="dark"] .btn-outline-apm:hover i,
:root[data-apm-theme="dark"] .btn-outline-apm:focus i,
:root[data-apm-theme="dark"] .table-modern tbody td:last-child .btn-outline-apm:hover i,
:root[data-apm-theme="dark"] .table-modern tbody td:last-child .btn-outline-apm:focus i {
    color: #ffffff !important;
}

/* --------------------------------------------------------------------------
   18. TRANSICIÓN DE TEMA (claro/oscuro)

   El toggle de tema (js/apm_tema.js) solo escribe el atributo `data-apm-theme` en
   `<html>`; el cambio de color en sí lo produce el navegador al recalcular cada
   `var(--bg-page)`/`var(--text-main)`/etc. contra el bloque `[data-apm-theme="dark"]` de
   la sección 1.b. SIN una regla de `transition`, ese recálculo se aplica de golpe en el
   mismo frame — de ahí el "flash" al pulsar el botón.

   La regla es deliberadamente `*` (especificidad 0,0,0,0), la más baja posible: así
   cualquier selector más específico que YA declare su propio `transition` (`.btn-modern`,
   `.apm-theme-toggle-btn`, los tres `.apm-sidebar-ready ...` de cada `menubs4xb_n*.php`,
   los `!important` de `plantilla_base.css` sección 15 que anulan la transición del sidebar
   en el primer frame para evitar el parpadeo de apertura) sigue ganando tal cual — esta
   regla NUNCA compite con esas, solo rellena lo que ningún otro selector ya cubre. Por la
   misma razón no hace falta excluir nada a mano: donde ya hay una transición a propósito
   (o a propósito NINGUNA, como el anti-FOUC del sidebar), esta ni se nota.

   No lleva parpadeo en la carga de la página: el script anti-FOUC de header_css.php fija
   `data-apm-theme` de forma síncrona, ANTES del primer paint — no hay "valor anterior" del
   que partir, así que ningún elemento transiciona al cargar, solo al alternar el botón.

   Con las cuatro propiedades típicas de un cambio de tema (fondo, borde, texto, sombra) más
   `fill`/`stroke` para el SVG suelto de algún topbar (p. ej. `usuario/editar clave.php`).
   Sin `all`: transicionar TODO (incluyendo `width`/`height`/`transform`/`opacity`) es el
   antipatrón que haría temblar cualquier `<td>` que cambie de ancho al redibujar DataTables
   o retrasaría la apertura/cierre de un modal — aquí solo se anima color. */
:root {
    --apm-theme-transition: background-color .25s ease, border-color .25s ease,
        color .25s ease, box-shadow .25s ease, fill .25s ease, stroke .25s ease;
}
*, *::before, *::after {
    transition: var(--apm-theme-transition);
}
/* Celdas de tabla: sin box-shadow en la transición. Bootstrap 5 pinta el fondo de estado de
   la celda con `inset 0 0 0 9999px`; al cambiar a otra sombra (el filete `inset 3px 0 0` de
   .apm-fila-activa, el `none` del hover de .table-modern) el navegador interpola el spread de
   0 a 9999px y la celda destella entera en azul durante la transición. */
.table > :not(caption) > * > * {
    transition: background-color .25s ease, border-color .25s ease, color .25s ease;
}
@media (prefers-reduced-motion: reduce) {
    /* Misma especificidad que la regla de arriba (0,0,0,0): la desactiva sin tocar
       ninguna otra transición del sistema (todas viven en selectores más específicos). */
    *, *::before, *::after {
        transition: none;
    }
    .table > :not(caption) > * > * {
        transition: none;
    }
}

/* --------------------------------------------------------------------------
   19. BURBUJA DE TEXTO COMPLETO (TextPopover) — celdas largas de listados

   Adaptado de la maqueta en "idea popover/" (text-popover.css + .js), que el usuario
   diseñó como componente standalone. Aquí solo viven los estilos; el comportamiento
   (mostrar/ocultar, posicionamiento, reenganche tras redraw de DataTables) está en
   js/apm_text_popover.js — se agrega a una tabla llamando a
   `TextPopover.attach({ selector: '#idTabla', columns: ['OBSERVACIÓN', 'SUMILLA'] })`
   después de inicializar la DataTable de esa página (o junto al arranque en vacío de
   la receta F.1).

   No trae variables `--tp-*` propias de color (la maqueta original sí, colgadas de
   `[data-theme="dark"]`, un atributo que este proyecto no usa — ver doc E): reusa los
   tokens de la sección 1/1.b, así que invierte de tema solo, sin ningún bloque
   `[data-apm-theme="dark"]` aparte. Las únicas variables que sobreviven,
   `--tp-max-width` y `--tp-arrow-left`, no son de tema: las escribe el JS en cada
   apertura para el ancho configurable (`opts.maxWidth`) y la posición de la flecha,
   así que se quedan con su valor por defecto como segundo argumento de `var()`.
   El prefijo de clase `tp-` se conserva tal cual (verificado sin colisión en el resto
   del árbol).

   La celda NO muestra ningún fragmento de texto junto al botón (decisión expresa del
   usuario, 2026-09-15): nada de un `.tp-cell__text` truncado con ellipsis conviviendo
   con el ícono — el texto completo vive únicamente dentro de la burbuja. `.tp-cell` por
   eso solo centra el botón dentro del ancho de la celda, ya reducida en cada página al
   integrar el popover (ver el comentario de los `<colgroup>` de OBSERVACIÓN/SUMILLA en
   cada página migrada). */

/* Bootstrap 5.3.8 encadena .table{vertical-align:top} -> .table>tbody{vertical-align:
   inherit} -> el <td> hereda "inherit" del user-agent stylesheet, así que sin esto el
   botón queda pegado arriba de la fila en vez de centrado verticalmente (más notorio
   cuando otra columna, ej. DESCRIPCIÓN, envuelve a varias líneas y alarga la fila). */
.tp-td {
    vertical-align: middle !important;
}

.tp-cell {
    display: flex;
    align-items: center;
    justify-content: center;
    max-width: 100%;
}

.tp-trigger {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: var(--color-neutral-bg);
    color: var(--text-muted);
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease, transform 0.1s ease;
}

.tp-trigger:hover,
.tp-trigger:focus-visible,
.tp-trigger[aria-expanded="true"] {
    background: var(--color-neutral-bg);
    color: var(--primary);
}

.tp-trigger:active {
    transform: scale(0.92);
}

.tp-trigger:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

.tp-trigger svg {
    display: block;
    width: 14px;
    height: 14px;
}

/* Burbuja de diálogo (popover). El JS la agrega una sola vez a <body> con
   `position: fixed` — no queda atrapada por el overflow de `.table-responsive` ni por
   el scroll interno de `.page-content` (sección 7), mismo motivo por el que ningún
   modal puede quedarse dentro de `.page-wrapper` (doc B). */
.tp-bubble {
    position: fixed;
    z-index: 9999;
    box-sizing: border-box;
    max-width: min(var(--tp-max-width, 340px), calc(100vw - 24px));
    width: max-content;
    background: var(--bg-card);
    color: var(--text-main);
    border: 1px solid var(--border);
    border-radius: 10px;
    box-shadow: var(--shadow);
    padding: 10px 12px;
    font-size: 13px;
    line-height: 1.45;
    white-space: pre-wrap;
    word-break: break-word;
    opacity: 0;
    visibility: hidden;
    transform: translateY(4px) scale(0.98);
    transition: opacity 0.12s ease, transform 0.12s ease, visibility 0.12s;
    pointer-events: none;
}

.tp-bubble.is-open {
    opacity: 1;
    visibility: visible;
    transform: translateY(0) scale(1);
    pointer-events: auto;
}

.tp-bubble__title {
    font-weight: 600;
    font-size: 11px;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin: 0 0 4px;
}

/* Flecha de la burbuja, apunta hacia el botón disparador */
.tp-bubble::before,
.tp-bubble::after {
    content: "";
    position: absolute;
    left: var(--tp-arrow-left, 16px);
    width: 0;
    height: 0;
    border-left: 7px solid transparent;
    border-right: 7px solid transparent;
}

.tp-bubble--bottom::before {
    top: -7px;
    border-bottom: 7px solid var(--border);
}
.tp-bubble--bottom::after {
    top: -6px;
    border-bottom: 6px solid var(--bg-card);
}

.tp-bubble--top::before {
    bottom: -7px;
    border-top: 7px solid var(--border);
}
.tp-bubble--top::after {
    bottom: -6px;
    border-top: 6px solid var(--bg-card);
}

/* En pantallas muy angostas, prioriza legibilidad sobre ancho fijo */
@media (max-width: 420px) {
    .tp-bubble {
        max-width: calc(100vw - 16px);
        font-size: 12.5px;
    }
}

@media (prefers-reduced-motion: reduce) {
    .tp-bubble,
    .tp-trigger {
        transition: none;
    }
}

/* --------------------------------------------------------------------------
   20. MÓVIL — LISTADOS Y CABECERA (2026-10-25)
   -------------------------------------------------------------------------- */
/* Medido en producción a 390px: con `table-layout: fixed` (sección 5) y el width:100%
   de DataTables, la tabla se encogía al ancho de la pantalla en vez de desbordar, y las
   columnas bajaban de 40px hasta partir números y palabras letra a letra. Con un ancho
   mínimo que depende del número de columnas, el `.table-responsive` que ya envuelve
   cada listado pasa a desplazarse en horizontal. Solo `screen`: en papel (sección 14)
   la tabla sigue ajustándose a la hoja. */
@media screen and (max-width: 767.98px) {
    .table-responsive table.table-modern:has(> thead > tr > th:nth-child(4)) {
        min-width: 560px;
    }

    .table-responsive table.table-modern:has(> thead > tr > th:nth-child(6)) {
        min-width: 760px;
    }

    .table-responsive table.table-modern:has(> thead > tr > th:nth-child(9)) {
        min-width: 940px;
    }

    /* Cabecera: el badge del usuario (max-width 220px, sección 2) se salía por la
       derecha. Se deja encoger y el nombre se trunca antes; completo en el desplegable. */
    .apm-header-actions,
    .apm-user-menu {
        min-width: 0;
        flex-shrink: 1;
    }

    .apm-user-menu-btn {
        max-width: 100%;
    }

    .apm-user-menu-label {
        max-width: 24vw;
    }
}
