/* ===== LAYOUT GENERAL ===== */
.container {
    padding-top: 10px;
}

/* ===== ACCESIBILIDAD ===== */
/* Texto solo para lectores de pantalla (oculto visualmente pero presente en el DOM) */
.sr-only {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    padding: 0 !important;
    margin: -1px !important;
    overflow: hidden !important;
    clip: rect(0, 0, 0, 0) !important;
    white-space: nowrap !important;
    border: 0 !important;
}
/* Foco visible para navegacion por teclado */
a:focus-visible,
button:focus-visible,
.btn:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
    outline: 3px solid #ffbf47 !important;
    outline-offset: 2px !important;
    box-shadow: 0 0 0 3px rgba(0, 123, 255, .4) !important;
}
/* Celda de tabla clickeable para copiar su valor al portapapeles (ver copiarAlPortapapeles en api.js) */
.valor-copiable {
    cursor: pointer;
    border-radius: 4px;
    padding: 1px 4px;
    margin: -1px -4px;
}
.valor-copiable:hover {
    background-color: rgba(0, 123, 255, .12);
}
html[data-theme="dark"] .valor-copiable:hover {
    background-color: rgba(96, 165, 250, .18);
}
/* Salto al contenido principal (skip link) */
.skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
    background: #007bff;
    color: #fff;
    padding: 10px 14px;
    z-index: 10000;
    font-weight: 600;
    text-decoration: none;
}
.skip-link:focus {
    left: 8px;
    top: 8px;
    outline: 3px solid #ffbf47;
}

/* ===== TOASTS / NOTIFICACIONES FLOTANTES ===== */
.toast-container {
    position: fixed;
    top: 90px;
    right: 20px;
    z-index: 9999;
    display: flex;
    flex-direction: column;
    gap: 8px;
    pointer-events: none;
    max-width: 420px;
}
.toast-msg {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    background: #fff;
    border-radius: 8px;
    padding: 12px 14px;
    box-shadow: 0 6px 18px rgba(0,0,0,.18);
    border-left: 4px solid #007bff;
    transform: translateX(120%);
    opacity: 0;
    transition: transform .25s ease, opacity .25s ease;
    pointer-events: auto;
    font-size: 0.9rem;
    line-height: 1.35;
    min-width: 280px;
}
.toast-msg.toast-show { transform: translateX(0); opacity: 1; }
.toast-msg.toast-hide { transform: translateX(120%); opacity: 0; }
.toast-success { border-left-color: #28a745; }
.toast-danger  { border-left-color: #dc3545; }
.toast-warning { border-left-color: #ffc107; }
.toast-info    { border-left-color: #17a2b8; }
.toast-icon {
    width: 26px;
    height: 26px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    flex-shrink: 0;
    font-size: 0.85rem;
}
.toast-success .toast-icon { background: #28a745; }
.toast-danger  .toast-icon { background: #dc3545; }
.toast-warning .toast-icon { background: #ffc107; color: #212529; }
.toast-info    .toast-icon { background: #17a2b8; }
.toast-body {
    flex: 1;
    color: #2c3e50;
    word-break: break-word;
}
.toast-close {
    background: none;
    border: none;
    font-size: 1.4rem;
    line-height: 1;
    color: #95a5a6;
    cursor: pointer;
    padding: 0 4px;
    margin-top: -2px;
}
.toast-close:hover { color: #2c3e50; }

.alerta-seccion {
    display: none;
}

/* ===== ENCABEZADO DE SECCIÓN ===== */
.seccion-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 10px;
    margin-bottom: 16px;
    padding-bottom: 12px;
    border-bottom: 2px solid #007bff;
}
.seccion-header h4 {
    margin: 0;
    color: #007bff;
    font-weight: 600;
}
.seccion-controles {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

/* ===== BARRA DE BÚSQUEDA ===== */
.input-busqueda {
    position: relative;
}
.input-busqueda .fa-magnifying-glass {
    position: absolute;
    left: 10px;
    top: 50%;
    transform: translateY(-50%);
    color: #aaa;
    pointer-events: none;
}
.input-busqueda input {
    padding-left: 32px;
    min-width: 200px;
}

/* ===== TOGGLE ACTIVOS/INACTIVOS ===== */
.btn-toggle-estado {
    min-width: 130px;
}
.badge-inactivo {
    background-color: #6c757d;
    color: #fff;
    padding: 2px 7px;
    border-radius: 10px;
    font-size: 0.75em;
    margin-left: 4px;
}
.badge-activo {
    background-color: #28a745;
    color: #fff;
    padding: 2px 7px;
    border-radius: 10px;
    font-size: 0.75em;
    margin-left: 4px;
}

/* ===== TABLA ===== */
.table thead th {
    background-color: var(--admin-surface-soft);
    border-bottom: 2px solid var(--admin-border);
    font-size: 0.82rem;
    white-space: nowrap;
}
.table tbody tr:hover {
    background-color: var(--admin-surface-soft);
}
.table td {
    vertical-align: middle;
    font-size: 0.86rem;
}
.table-inactivos tbody tr {
    opacity: 0.75;
    background-color: #fafafa;
}

/* ===== BOTONES DE ACCIÓN ===== */
.btn-accion {
    padding: 3px 8px;
    font-size: 0.8rem;
    margin-right: 3px;
}
.acciones-col {
    white-space: nowrap;
    width: 1%;
}

/* ===== SPINNER / OVERLAY ===== */
.spinner-overlay {
    display: none;
    position: fixed;
    top: 0; left: 0;
    width: 100%; height: 100%;
    background: rgba(255,255,255,.7);
    z-index: 8000;
    align-items: center;
    justify-content: center;
}
.spinner-overlay.visible {
    display: flex;
}

/* ===== PAGINACIÓN ===== */
#paginacion-equipos,
#paginacion-usuarios,
#paginacion-marcas,
#paginacion-modelos,
#paginacion-ubicaciones {
    display: flex;
    justify-content: center;
    margin-top: 12px;
}

/* ===== MODAL ===== */
.modal-header {
    background-color: #007bff;
    color: #fff;
}
/* El azul del header de modal quedaba fijo en el tono de modo claro incluso en
   modo oscuro (unico elemento "de marca" de la app que no seguia el tema). Se ata
   a la misma variable que ya usan botones/titulos, mas oscura para que siga
   destacando como header sin quemar contra el resto de la paleta oscura. */
html[data-theme="dark"] .modal-header {
    /* --admin-primary-dark (#3b82f6) es casi el mismo azul que el fijo de modo
       claro (#007bff) a simple vista — no alcanzaba para notarse "distinto".
       Se usa un azul marino bien oscuro (el mismo tono que ya usan los iconos
       de cabecera en modo oscuro, ver .page-icon en adminhmd.css) para que el
       header quede claramente identificado como parte de la paleta oscura. */
    background-color: #16324f;
}
.modal-header .modal-title {
    color: #fff;
    font-weight: 600;
}
.modal-header .close {
    color: #fff;
    opacity: 0.8;
}
.modal-header .close:hover {
    opacity: 1;
}
/* La cruz de cerrar del header (fondo azul en todos los modales) necesita el
   filtro "blanco" de Bootstrap para tener contraste real; por defecto es
   casi negra y se pierde contra el azul. En modo oscuro se satura un poco
   mas para que quede blanca de verdad, no gris. */
.modal-header .btn-close {
    filter: invert(1) grayscale(100%) brightness(200%);
}
html[data-theme="dark"] .modal-header .btn-close {
    filter: invert(1) grayscale(100%) brightness(260%);
}
/* TODOS los modales del sistema quedan acotados al 80% del alto de la ventana
   (encabezado + pie siempre visibles, el cuerpo scrollea si el contenido no entra),
   sin importar tamaño (sm/md/lg/xl) ni si el contenido crece dinámicamente (listados,
   checklists). Bootstrap ya deja .modal-content en flex-column con
   max-height:100%/overflow:hidden heredado de .modal-dialog (mismo mecanismo de
   .modal-dialog-scrollable) — alcanza con topear .modal-dialog y darle scroll propio
   a .modal-body, sin tener que agregar la clase modal-dialog-scrollable a cada partial. */
.modal-dialog {
    max-height: 80vh;
}
.modal-body {
    overflow-y: auto;
}

.modal-section-title {
    font-size: 0.8rem;
    font-weight: 700;
    text-transform: uppercase;
    color: #6c757d;
    letter-spacing: .5px;
    margin: 14px 0 6px;
    border-bottom: 1px solid #eee;
    padding-bottom: 4px;
}

/* ===== MARCAS / MODELOS — lista interactiva dos columnas ===== */
#marcastable .list-group-item,
#modelostable .list-group-item {
    cursor: pointer;
    font-size: 0.88rem;
    padding: 8px 12px;
    transition: background-color 0.15s;
}
#marcastable .list-group-item.active {
    background-color: #007bff;
    border-color: #007bff;
    color: #fff;
}
#marcastable .list-group-item.active .btn {
    color: #fff;
    border-color: rgba(255,255,255,.5);
}
#marcastable .list-group-item.active .btn-warning {
    background-color: #ffc107;
    border-color: #ffc107;
    color: #212529;
}
#marcastable .list-group-item.active .btn-danger {
    background-color: #dc3545;
    border-color: #dc3545;
    color: #fff;
}
.font-weight-500 { font-weight: 500; }

/* ===== LOGIN ===== */
.signin-form {
    min-height: 100vh;
    display: flex;
    align-items: center;
    background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
}

/* ===== ESTADO VACÍO ===== */
.estado-vacio {
    text-align: center;
    padding: 40px;
    color: #aaa;
}
.estado-vacio i {
    font-size: 3rem;
    margin-bottom: 12px;
}

/* ===== FILA INACTIVA ===== */
tr.inactivo td {
    color: #999;
}

/* ===== CONTROL FORM ===== */
.form-control {
    font-size: 0.87rem;
}
.form-group label {
    font-size: 0.83rem;
    font-weight: 600;
    color: #495057;
}

/* ===== BADGE ROLES ===== */
.badge-superadmin { background: #dc3545; }
.badge-admin      { background: #fd7e14; }
.badge-usuario    { background: #6c757d; }

/* ===== DASHBOARD ===== */
.kpi-card {
    background: #fff;
    border-radius: 8px;
    box-shadow: 0 2px 6px rgba(0,0,0,.06);
    padding: 16px 18px;
    display: flex;
    align-items: center;
    gap: 14px;
    border-left: 4px solid #007bff;
    height: 100%;
    transition: transform .15s ease, box-shadow .15s ease;
}
.kpi-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(0,0,0,.1);
}
.kpi-equipos     { border-left-color: #007bff; }
.kpi-servers     { border-left-color: #ffc107; }
.kpi-backups     { border-left-color: #28a745; }
.kpi-conexiones  { border-left-color: #17a2b8; }
.kpi-icon {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    background: #f1f7ff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.4rem;
    color: #007bff;
    flex-shrink: 0;
}
.kpi-equipos    .kpi-icon { color: #007bff; background: #e7f1ff; }
.kpi-servers    .kpi-icon { color: #d39e00; background: #fff8e1; }
.kpi-backups    .kpi-icon { color: #28a745; background: #e7f8ed; }
.kpi-conexiones .kpi-icon { color: #17a2b8; background: #e3f6f9; }
.kpi-body { flex: 1; min-width: 0; }
.kpi-label {
    font-size: 0.78rem;
    color: #6c757d;
    text-transform: uppercase;
    letter-spacing: .4px;
    font-weight: 600;
}
.kpi-value {
    font-size: 1.85rem;
    font-weight: 700;
    color: #2c3e50;
    line-height: 1.1;
}
.kpi-sub {
    font-size: 0.78rem;
    color: #95a5a6;
    margin-top: 2px;
}

.mini-kpi {
    background: #fff;
    border-radius: 6px;
    padding: 8px 12px;
    box-shadow: 0 1px 3px rgba(0,0,0,.05);
    font-size: 0.9rem;
    text-align: center;
}
.mini-kpi span { font-weight: 700; color: #2c3e50; }
.mini-kpi small { color: #6c757d; }

.dashboard-card {
    background: #fff;
    border-radius: 8px;
    box-shadow: 0 2px 6px rgba(0,0,0,.06);
    overflow: hidden;
}
.dashboard-card-header {
    background: #f8f9fa;
    padding: 10px 14px;
    font-weight: 600;
    color: #495057;
    border-bottom: 1px solid #e9ecef;
    font-size: 0.95rem;
}
.dashboard-card-body { padding: 14px; }
.dashboard-card-body.p-0 { padding: 0; }

.dist-block { margin-bottom: 16px; }
.dist-block:last-child { margin-bottom: 0; }
.dist-titulo {
    font-size: 0.8rem;
    font-weight: 600;
    color: #6c757d;
    text-transform: uppercase;
    letter-spacing: .3px;
    margin-bottom: 6px;
}
.dist-row { margin-bottom: 6px; }
.dist-row-label {
    font-size: 0.85rem;
    color: #2c3e50;
    margin-bottom: 2px;
    display: flex;
    justify-content: space-between;
}
.dist-row-valor { color: #6c757d; font-weight: 600; }
.dist-progress {
    height: 14px;
    border-radius: 3px;
    background: #eef2f5;
}
.dist-progress .progress-bar {
    font-size: 0.7rem;
    line-height: 14px;
    color: #fff;
    font-weight: 600;
    transition: width .4s ease;
}

/* ===== BACKUP MASIVO — tarjetas de selección ===== */
.bm-tipo-card {
    cursor: pointer;
    margin: 0 8px 8px 0;
}
.bm-tipo-card input[type="radio"] {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}
.bm-tipo-card .bm-tipo-inner {
    border: 2px solid #dee2e6;
    border-radius: 8px;
    padding: 18px 26px;
    text-align: center;
    transition: all .15s ease;
    min-width: 130px;
    background: #fff;
}
.bm-tipo-card .bm-tipo-inner i {
    font-size: 1.8rem;
    color: #6c757d;
    margin-bottom: 6px;
    display: block;
}
.bm-tipo-card input[type="radio"]:checked + .bm-tipo-inner {
    border-color: #007bff;
    background: #e7f1ff;
    box-shadow: 0 2px 6px rgba(0,123,255,.15);
}
.bm-tipo-card input[type="radio"]:checked + .bm-tipo-inner i {
    color: #007bff;
}
.bm-tipo-card:hover .bm-tipo-inner {
    border-color: #007bff;
}

.actividad-feed { max-height: 460px; overflow-y: auto; }
.act-item {
    display: flex;
    gap: 12px;
    padding: 10px 14px;
    border-bottom: 1px solid #f1f3f5;
    align-items: flex-start;
}
.act-item:last-child { border-bottom: none; }
.act-icon {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: #f8f9fa;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    font-size: 0.85rem;
}
.act-body { flex: 1; min-width: 0; }
.act-evento {
    font-weight: 600;
    font-size: 0.85rem;
    color: #2c3e50;
    text-transform: capitalize;
}
.act-detalle {
    font-size: 0.83rem;
    color: #495057;
    word-break: break-word;
}
.act-meta {
    font-size: 0.75rem;
    color: #95a5a6;
    margin-top: 2px;
}

/* ===== REPORTES ===== */
.reporte-tabla td { vertical-align: middle; }
.rep-progress {
    height: 14px;
    background: #eef2f5;
    border-radius: 3px;
    margin: 0;
}
.rep-progress .progress-bar {
    font-size: 0.7rem;
    line-height: 14px;
    transition: width .4s ease;
}

/* Checklists de equipos/politicas de los modales MikroTik. No se usa la clase Bootstrap
   ".rounded" a proposito: frontend/lib/css/estilos.css la pisa con "width: 100px" (pensada
   para otro componente), lo que dejaba estos checklists angostos y ocultaba los <select>
   de perfil por fila del modal de Usuarios. */
.checklist-box {
    width: 100%;
    border-radius: 0.25rem;
}

@media print {
    header, .seccion-controles, .header-row, nav.collapse, #btn-refrescar-reportes,
    #rep-export-csv, #rep-print, #rep-selector,
    #alerta-global, .modal-backdrop, .modal { display: none !important; }
    .container { padding-top: 0 !important; }
    .seccion-header { border-bottom: 2px solid #000; }
    .dashboard-card { box-shadow: none; border: 1px solid #ddd; }
    .progress-bar { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}

/* ===== COMPATIBILIDAD DE BADGES BOOTSTRAP 4 -> 5 =====
   El proyecto usa en TODO el JS la sintaxis de Bootstrap 4 (.badge-success, .badge-danger,
   etc.), pero frontend/lib/css/bootstrapkike.min.css es Bootstrap 5.1.3 (y el JS,
   frontend/lib/js/bootstrap.min.js, es 5.3.3), que renombro esas
   clases a .bg-* y NO define las viejas. Efecto real: como .badge de BS5 trae
   "--bs-badge-color:#fff" (texto blanco) y sin la clase de color el fondo queda
   transparente, TODOS los badges del sistema se veian como texto blanco sobre fondo
   blanco, o sea invisibles (detectado 2026-07-17 en el modal de Estado de Equipos
   Permitidos: las columnas Estado e Internet aparecian vacias aunque el texto SI estaba
   en el DOM — por eso un lector de pantalla lo lee bien y el problema paso desapercibido).
   Se define aca el equivalente en vez de reescribir ~10 archivos JS: arregla de una todos
   los modulos (equipos, servers, conexiones, pacheras, marcas, mikrotik...) y mantiene el
   patron que ya usa el proyecto. Los colores son los oficiales de Bootstrap 5. */
.badge-success   { background-color: #198754; color: #fff; }
.badge-danger    { background-color: #dc3545; color: #fff; }
.badge-secondary { background-color: #6c757d; color: #fff; }
.badge-primary   { background-color: #0d6efd; color: #fff; }
/* warning e info llevan texto oscuro: sobre amarillo/celeste el texto blanco no alcanza
   la relacion de contraste minima de accesibilidad (mismo criterio que .text-bg-* de BS5) */
.badge-warning   { background-color: #ffc107; color: #000; }
.badge-info      { background-color: #0dcaf0; color: #000; }
/* badge-light faltaba y caia en el mismo problema (texto blanco sobre fondo transparente
   = invisible): lo usan los badges de CPU/uptime del modal "Ver puertos en tiempo real",
   el contador de dispositivos por puerto y el reparto por ubicacion de Tareas. */
.badge-light     { background-color: #f8f9fa; color: #000; }

/* ===== COMPATIBILIDAD DE UTILIDADES BOOTSTRAP 4 -> 5 =====
   Mismo caso (y misma decision) que el bloque de badges de arriba: el codigo del proyecto
   usa las utilidades de Bootstrap 4, pero el CSS es Bootstrap 5, donde fueron RENOMBRADAS
   (ml-/mr- pasaron a ms-/me-, text-left/right a text-start/end) o ELIMINADAS (form-row,
   input-group-prepend/append). Al no existir, hoy simplemente NO HACEN NADA: los ~685 usos
   de estas clases en el sistema quedan sin el margen/alineacion que el codigo pretendia
   (iconos pegados al texto, botones sin separacion, columnas de formulario sin gutter).
   Es un defecto puramente VISUAL —el contenido y el orden del DOM no cambian, por eso un
   lector de pantalla nunca lo delato— y se corrige aca en vez de reescribir 685 llamadas
   repartidas en todo el frontend.
   Se definen SOLO las variantes realmente usadas por el proyecto (relevadas con grep), con
   los valores de la escala de espaciado de Bootstrap (1 = .25rem, 2 = .5rem).
   Si en algun momento se migra el codigo a la sintaxis nativa de BS5, este bloque se borra. */
.mr-1 { margin-right: .25rem !important; }
.mr-2 { margin-right: .5rem !important; }
.ml-1 { margin-left: .25rem !important; }
.ml-2 { margin-left: .5rem !important; }
.mr-auto { margin-right: auto !important; }
.ml-auto { margin-left: auto !important; }
.text-left  { text-align: left !important; }
.text-right { text-align: right !important; }
.float-right { float: right !important; }

/* form-row: era la variante compacta de .row para formularios (gutter de 5px en vez de 15px) */
.form-row {
    display: flex;
    flex-wrap: wrap;
    margin-right: -5px;
    margin-left: -5px;
}
.form-row > [class*="col-"] {
    padding-right: 5px;
    padding-left: 5px;
}

/* input-group-prepend/append: en BS5 el wrapper desaparecio y .input-group-text va suelto
   dentro de .input-group. Se les da el mismo display flex que tenian para que el addon
   (los iconos de usuario/candado del login, entre otros) siga alineado con el input. */
.input-group-prepend,
.input-group-append {
    display: flex;
    align-items: stretch;
}
/* BS5 redondea el input-group mirando a los hijos DIRECTOS de .input-group
   (":first-child"/":last-child"), pero como el icono/boton vive adentro de
   estos wrappers -prepend/-append, el radius le queda aplicado al wrapper
   (que no tiene fondo/borde propio) y el elemento visible de adentro se ve
   con esquinas cuadradas — de ahi que los inputs con icono (nombre/ip/mac/
   usuario/contraseña en varios modales) se vean "pegados" y sin la misma
   redondez que el resto de la interfaz. Se replica el mismo esquema de
   esquinas apuntando directo al elemento visible. */
.input-group-prepend .input-group-text {
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
}
.input-group-append .input-group-text,
.input-group-append .btn {
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
}
.input-group-prepend + .form-control {
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
}
.input-group:has(.input-group-append) > .form-control {
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
}

/* Contador de sesion (abajo a la derecha, ver sesion_contador.js). Bajo z-index normal
   (por debajo de modales/toasts) pero fijo para quedar siempre visible mientras se
   trabaja. Estado normal: discreto y de bajo contraste. */
.sesion-contador {
    position: fixed;
    right: 16px;
    bottom: 12px;
    z-index: 1030;
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    background: rgba(255, 255, 255, 0.92);
    border: 1px solid #dee2e6;
    border-radius: 4px;
    font-size: 0.8rem;
    color: #6c757d;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
}
/* Aviso de expiracion proxima (agregado por JS al acercarse a los ultimos minutos) */
.sesion-contador.sesion-contador-aviso {
    color: #fff;
    background: #dc3545;
    border-color: #dc3545;
    font-weight: 600;
}
.sesion-contador.sesion-contador-aviso #sc-btn-extender {
    color: #fff;
    text-decoration: underline;
    padding: 0 0 0 4px;
}
@media print {
    .sesion-contador { display: none !important; }
}

/* =====================================================================
   Sidebar del layout adminHMD (ver frontend/lib/css/adminhmd.css) — clases
   propias de esta app, no vienen del template: los encabezados de grupo
   (Equipamiento/Red/Servidores/...) y los sub-items del submenu Mikrotik
   (2 niveles: Gestion Usuarios / Wifi). Son <h2>/<h3> reales (no <div>) para
   que un lector de pantalla pueda saltar entre secciones del menu por
   encabezado, en vez de tener que recorrer 30+ links uno por uno.
   ===================================================================== */
.sidebar-section-label {
    margin: 0.9rem 0 0.15rem;
    padding: 0 0.4rem;
    color: #9ca3af;
    font-size: 0.72rem;
    font-weight: 800;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    white-space: nowrap;
}
.sidebar-section-label:first-child {
    margin-top: 0;
}
/* Mismo estilo que .sidebar-section-label (mayusculas, tamaño, negrita): el
   submenu de Mikrotik (Gestion Usuarios / Wifi) tenia su propio tamaño mas chico,
   sin mayusculas y con menos peso, rompiendo la consistencia con el resto de los
   encabezados de grupo del menu lateral. */
.sidebar-section-label-sub {
    margin: 0.9rem 0 0.15rem;
    padding: 0 0.4rem;
    color: #9ca3af;
    font-size: 0.72rem;
    font-weight: 800;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    white-space: nowrap;
}

/* La barra de scroll del menu lateral usaba el scrollbar por defecto del
   navegador (ancho, gris, pegado literalmente contra el texto de cada item) —
   se angosta y se le da un color discreto acorde al tema oscuro del sidebar. El
   "scrollbar-gutter: stable" de adminhmd.css ya reserva el espacio de un
   scrollbar normal, asi que al angostar el real queda un margen de aire real
   entre la barra y los links, en vez de quedar pegada. */
.admin-sidebar {
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, 0.22) transparent;
}
.admin-sidebar::-webkit-scrollbar {
    width: 6px;
}
.admin-sidebar::-webkit-scrollbar-thumb {
    background-color: rgba(255, 255, 255, 0.22);
    border-radius: 4px;
}
.admin-sidebar::-webkit-scrollbar-track {
    background: transparent;
}

.sidebar-nav .nav-link-sub {
    padding-left: 1.6rem;
    min-height: 40px;
    font-size: 0.92rem;
}
.sidebar-nav .nav-link-sub .nav-icon {
    width: 24px;
    height: 24px;
    font-size: 0.68rem;
}
/* El template trae avatar como <img>; acá se reemplazó por un ícono
   (el proyecto no tiene fotos de usuario) — mismo tamaño/forma que el <img>. */
.sidebar-user-avatar,
.profile-button .avatar-sm {
    border-radius: 50%;
}

/* ===== TABULATOR — tema propio, ligado a las mismas variables --admin-* que el
   resto del layout (adminhmd.css) para que siga el toggle claro/oscuro solo, sin
   necesitar una hoja de estilos "midnight" aparte cargada condicionalmente. ===== */
.tabulator {
    background-color: var(--admin-surface);
    border: 1px solid var(--admin-border);
    border-radius: 8px;
    color: var(--admin-text);
    font-size: 0.87rem;
}
/* tabulator.min.css pinta ".tabulator-table" (el elemento INTERNO que envuelve
   las filas, no ".tabulator" el contenedor externo que ya cubríamos arriba) con
   fondo blanco fijo — normalmente invisible porque cada fila tiene su propio
   fondo solido encima, pero el hover translucido (rgba con alpha<1) deja ver ese
   blanco de fondo por transparencia, dando un lavanda palido en vez del tono
   oscuro esperado. */
.tabulator-table,
.tabulator .tabulator-tableholder .tabulator-table {
    background-color: var(--admin-surface);
}
.tabulator .tabulator-header {
    background-color: var(--admin-surface-soft);
    border-bottom: 1px solid var(--admin-border);
    color: var(--admin-text);
}
.tabulator .tabulator-header .tabulator-col {
    background-color: var(--admin-surface-soft);
    border-right: 1px solid var(--admin-border);
}
.tabulator .tabulator-header .tabulator-col .tabulator-col-content .tabulator-col-title {
    font-weight: 700;
    text-transform: uppercase;
    font-size: 0.72rem;
    letter-spacing: .4px;
    color: var(--admin-muted);
}
.tabulator .tabulator-header .tabulator-col.tabulator-sortable:hover {
    background-color: var(--admin-surface);
}
.tabulator-row {
    background-color: var(--admin-surface);
    color: var(--admin-text);
    border-bottom: 1px solid var(--admin-border);
}
.tabulator-row.tabulator-row-even {
    background-color: var(--admin-surface-soft);
}
.tabulator-row:hover,
.tabulator-row.tabulator-selectable:hover {
    background-color: rgba(37, 99, 235, 0.08);
}
.tabulator-row.tabulator-selected {
    background-color: rgba(37, 99, 235, 0.15);
}
/* tabulator.min.css trae su propio hover con mas especificidad
   (".tabulator-row.tabulator-selectable:hover{background-color:#bbb}", gris claro
   fijo) que le ganaba tanto a la regla de arriba como a la de abajo — hace falta
   iguales esa especificidad. En modo oscuro ese gris claro fijo se veía además
   como "el color del tema claro" filtrándose (justamente el bug reportado): se
   reemplaza por el mismo azul claro que ya usa el resto de la interfaz oscura. */
html[data-theme="dark"] .tabulator-row:hover,
html[data-theme="dark"] .tabulator-row.tabulator-selectable:hover {
    background-color: rgba(96, 165, 250, 0.14);
}
html[data-theme="dark"] .tabulator-row.tabulator-selected {
    background-color: rgba(96, 165, 250, 0.22);
}
.tabulator-row .tabulator-cell {
    border-right: 1px solid var(--admin-border);
}
/* La columna de Acciones (siempre la ultima de cada tabla, formateada con el
   menu hamburguesa) no es un dato tabular real — no deberia sentirse "encerrada"
   como una columna mas con su propia linea divisoria, header con texto/fondo y
   barra de resize. Se le saca todo eso: queda el boton flotando libre a la
   derecha de la fila, sin marco.
   OJO: ":last-child" NUNCA matcheaba acá — Tabulator agrega un nodo extra
   despues de la ultima .tabulator-col dentro de .tabulator-headers (confirmado
   en vivo: ".tabulator-col.acciones-celda".matches(':last-child') da false),
   asi que todas las reglas de abajo tenian que apuntar directo a la clase
   "acciones-celda" (que Tabulator SI propaga tanto al header col como a la
   celda de cada fila, via cssClass en la config de la columna) en vez de
   ":last-child". Con ":last-child" el borde/fondo de esta columna nunca se
   sacaba en la práctica, pese a que el CSS existía. */
.tabulator-col.acciones-celda {
    background-color: transparent !important;
    border-right: none !important;
}
.tabulator-cell.acciones-celda {
    border-right: none !important;
    background-color: transparent !important;
    padding: 0 6px 0 0 !important;
}
.tabulator-col.acciones-celda .tabulator-col-resize-handle {
    display: none;
}
.tabulator-col.acciones-celda .tabulator-col-content {
    padding-left: 0;
    padding-right: 6px;
}
/* Fila inactiva (equipo dado de baja) — mismo criterio visual que la tabla vieja
   (tr.inactivo td), aplicado por rowFormatter agregando esta clase a la fila. */
.tabulator-row.fila-inactiva .tabulator-cell {
    color: var(--admin-muted);
}
.tabulator .tabulator-footer {
    background-color: var(--admin-surface-soft);
    border-top: 1px solid var(--admin-border);
    color: var(--admin-muted);
}
.tabulator .tabulator-footer .tabulator-page {
    background-color: var(--admin-surface);
    border: 1px solid var(--admin-border);
    color: var(--admin-text);
    border-radius: 6px;
}
.tabulator .tabulator-footer .tabulator-page.active {
    background-color: var(--admin-primary);
    border-color: var(--admin-primary);
    color: #fff;
}
.tabulator .tabulator-footer .tabulator-page:not(.disabled):hover {
    background-color: var(--admin-primary);
    color: #fff;
}
.tabulator .tabulator-footer .tabulator-page.disabled {
    opacity: .45;
}
.tabulator .tabulator-placeholder {
    color: var(--admin-muted);
}
.tabulator .tabulator-col-resize-handle {
    background-color: var(--admin-border);
}
/* Los botones de acción viven dentro de una celda Tabulator: se acota su alto y se
   evita que el wrap de varios botones angoste la fila más de lo necesario. */
.tabulator-cell.acciones-celda {
    overflow: visible;
    white-space: nowrap;
}
/* El menu hamburguesa (dropdown) de la columna Acciones se corta cuando la tabla
   tiene pocas filas (poca altura total): .tabulator-tableholder recorta cualquier
   contenido que se salga de su caja. Ninguna tabla de la app usa scroll interno
   propio (todas se inicializan con height:false y usan paginacion en su lugar),
   asi que es seguro liberar el overflow sin romper ningun scroll real. */
.tabulator,
.tabulator-tableholder,
.tabulator-table,
.tabulator-row {
    overflow: visible;
}
/* tabulator.min.css define ".tabulator .tabulator-tableholder{overflow:auto}" con
   selector compuesto (mas especificidad que el de arriba): hace falta igualar esa
   especificidad para poder ganarlo. */
.tabulator .tabulator-tableholder {
    overflow: visible;
}
/* Modal "Estado API" con pestañas: la primera sección de cada pestaña arranca con un
   <hr> (heredado del separador que tenía entre secciones cuando todo era un único
   scroll) — se oculta solo el primero de cada pestaña para no dejar una línea suelta
   arriba de todo sin nada que separar. */
.tab-pane > hr:first-child {
    display: none;
}
/* Fila seleccionada en tablas maestro-detalle (ej. Pacheras -> Puertos,
   Marcas -> Modelos): mismo criterio visual que el .table-active de Bootstrap
   que reemplazaron, pero aplicado por Tabulator vía rowFormatter. */
.tabulator-row.fila-seleccionada {
    background-color: rgba(37, 99, 235, 0.18) !important;
    border-left: 3px solid var(--admin-primary);
}

/* =====================================================================
   CORRECCIONES DE UI — sesión 2026-08-11 (relevamiento de accesibilidad
   visual del usuario, no vidente pero con baja visión residual: usa el
   modo oscuro real, no solo el lector de pantalla, así que el contraste
   de texto le importa tanto como a un usuario totalmente vidente).
   ===================================================================== */

/* --- Sidebar en modo oscuro: texto mas claro (nav-link y usuario) --- */
html[data-theme="dark"] .sidebar-nav .nav-link {
    color: #e5e7eb !important;
}
html[data-theme="dark"] .sidebar-nav .nav-link:hover,
html[data-theme="dark"] .sidebar-nav .nav-link:focus,
html[data-theme="dark"] .sidebar-nav .nav-link.active {
    color: #ffffff !important;
}
/* Mismo color exacto que los encabezados de grupo principales ("Red",
   "Equipamiento") — antes el sub-encabezado de Mikrotik quedaba un poco mas
   apagado (#9ca3af vs #cbd5e1), una diferencia de jerarquia que no se pidio y
   se notaba como inconsistencia de tema, no como diseño intencional. */
html[data-theme="dark"] .sidebar-section-label,
html[data-theme="dark"] .sidebar-section-label-sub {
    color: #cbd5e1 !important;
}
html[data-theme="dark"] .sidebar-user strong {
    color: #ffffff !important;
}
html[data-theme="dark"] .sidebar-user small {
    color: #d1d5db !important;
}
html[data-theme="dark"] .sidebar-footer {
    color: #d1d5db !important;
}

/* Ningun elemento del menu lateral (icono o texto) debe subrayarse al pasar el mouse */
.sidebar-nav .nav-link,
.sidebar-nav .nav-link:hover,
.sidebar-nav .nav-link:focus,
.sidebar-nav .nav-link *,
.sidebar-nav .nav-link:hover *,
.sidebar-nav .nav-link:focus * {
    text-decoration: none !important;
}

/* Submenu Mikrotik (Gestion Usuarios / Wifi): alinear con el resto del menu
   (mismo padding e icono que un nav-link normal, en vez del tamaño reducido
   e indentado que traia el patron "sub" del template). */
.sidebar-nav .nav-link-sub {
    padding-left: 0.9rem;
}
.sidebar-nav .nav-link-sub .nav-icon {
    width: 30px;
    height: 30px;
    font-size: 0.76rem;
}

/* --- Tonos de azul mas claros en modo oscuro (titulos/lineas/botones) --- */
html[data-theme="dark"] .seccion-header {
    border-bottom-color: var(--admin-primary);
}
html[data-theme="dark"] .seccion-header h4 {
    color: var(--admin-primary);
}
html[data-theme="dark"] .btn-outline-primary {
    color: var(--admin-primary);
    border-color: var(--admin-primary);
}
html[data-theme="dark"] .btn-outline-primary:hover,
html[data-theme="dark"] .btn-outline-primary:focus {
    background-color: var(--admin-primary);
    border-color: var(--admin-primary);
    color: #0a0a0a;
}

/* --- Contador de sesion: seguir el tema oscuro/claro (antes quedaba
   siempre con la paleta clara, fija, sin importar el tema activo) --- */
html[data-theme="dark"] .sesion-contador {
    background: rgba(10, 10, 10, 0.92);
    border-color: var(--admin-border);
    color: var(--admin-muted);
}
html[data-theme="dark"] .sesion-contador.sesion-contador-aviso {
    background: var(--admin-danger);
    border-color: var(--admin-danger);
    color: #0a0a0a;
}

/* --- Cards en modo oscuro: el template las dejaba con fondo blanco fijo,
   idénticas al modo claro. Se atan a las mismas variables --admin-* que
   ya usan .metric-card/.panel (adminhmd.css) para que sigan el tema solo. --- */
.kpi-card,
.dashboard-card,
.mini-kpi,
.bm-tipo-card .bm-tipo-inner {
    background: var(--admin-surface);
    color: var(--admin-text);
}
.dashboard-card-header {
    background: var(--admin-surface-soft);
    color: var(--admin-text);
    border-bottom-color: var(--admin-border);
}
.kpi-value,
.mini-kpi span {
    color: var(--admin-text);
}
.kpi-label,
.kpi-sub,
.dist-titulo,
.dist-row-valor,
.mini-kpi small {
    color: var(--admin-muted);
}
.dist-row-label {
    color: var(--admin-text);
}
html[data-theme="dark"] .kpi-icon {
    background: rgba(96, 165, 250, 0.16);
}
html[data-theme="dark"] .kpi-equipos    .kpi-icon { background: rgba(96, 165, 250, 0.18); }
html[data-theme="dark"] .kpi-servers    .kpi-icon { background: rgba(251, 191, 36, 0.16); }
html[data-theme="dark"] .kpi-backups    .kpi-icon { background: rgba(45, 212, 191, 0.16); }
html[data-theme="dark"] .kpi-conexiones .kpi-icon { background: rgba(34, 211, 238, 0.16); }
html[data-theme="dark"] .dist-progress {
    background: var(--admin-surface-soft);
}
html[data-theme="dark"] .bm-tipo-card .bm-tipo-inner {
    border-color: var(--admin-border);
}
html[data-theme="dark"] .bm-tipo-card input[type="radio"]:checked + .bm-tipo-inner {
    background: rgba(96, 165, 250, 0.14);
    border-color: var(--admin-primary);
}
html[data-theme="dark"] .act-item {
    border-bottom-color: var(--admin-border);
}
html[data-theme="dark"] .act-icon {
    background: var(--admin-surface-soft);
}
html[data-theme="dark"] .act-evento {
    color: var(--admin-text);
}
html[data-theme="dark"] .act-detalle {
    color: var(--admin-muted);
}
html[data-theme="dark"] .estado-vacio {
    color: var(--admin-muted);
}
html[data-theme="dark"] .toast-msg {
    background: var(--admin-surface);
    color: var(--admin-text);
    box-shadow: 0 6px 18px rgba(0,0,0,.5);
}
html[data-theme="dark"] .toast-body {
    color: var(--admin-text);
}

/* Las etiquetas naranjas (ej. "DHCP", velocidad de enlace baja, duplex "Half")
   usan .text-bg-warning, que en modo claro cae en el amarillo/texto oscuro por
   defecto de Bootstrap — se ven bien, pero a pedido puntual se mantiene la MISMA
   combinación (naranja oscuro + texto blanco) que ya se usa en modo oscuro,
   en los dos temas por igual, en vez de alternar. Se pisa tambien la clase
   ".text-dark" que algunos de estos badges agregan ademas (JS), porque esa
   utilidad de Bootstrap tiene su propio !important. */
.badge.text-bg-warning,
.badge.text-bg-warning.text-dark {
    background-color: #b45309 !important;
    color: #fff7ed !important;
}

/* --- Fix de un remanente del template viejo: frontend/lib/css/style.css
   define "p, span, ul, li { color: #2d4338; ... }" (una regla genérica,
   pensada para un componente puntual del template original) que pisa el
   color de CUALQUIER span/p/li de toda la app que no tenga su propio color
   explícito — se vía en la lista de Marcas ("ALHUA" etc. en verde oscuro
   casi invisible en modo oscuro). Se restituye la herencia normal: que
   tomen el color de su contenedor como haría cualquier span sin estilos. */
p, span, ul, li {
    color: inherit;
}
/* Mismo criterio que arriba: bootstrap.min.css pinta <code> de un rosa/magenta fijo
   (pensado para resaltar snippets de codigo), pero en esta app se usa nomas como
   fuente monoespaciada para IP/MAC/IDs — no deberian llevar un color propio,
   sino heredar el texto normal del tema activo (claro u oscuro). */
code {
    color: inherit;
}

/* --- .list-group (Marcas/Modelos): Bootstrap pinta texto/fondo con sus
   propias variables --bs-list-group-* (atadas a --bs-body-color, nunca
   redefinidas por adminhmd.css), asi que en modo oscuro quedaba con texto
   gris oscuro casi invisible sobre fondo igual de oscuro. --- */
.list-group-item {
    background-color: var(--admin-surface);
    color: var(--admin-text);
    border-color: var(--admin-border);
}
.list-group-item.list-group-item-action:hover,
.list-group-item.list-group-item-action:focus {
    background-color: var(--admin-surface-soft);
    color: var(--admin-text);
}
html[data-theme="dark"] #marcastable .list-group-item.active,
html[data-theme="dark"] #modelostable .list-group-item.active {
    background-color: var(--admin-primary);
    border-color: var(--admin-primary);
    color: #0a0a0a;
}

/* --- Padding irregular de mini-kpi: al estar en fila (flex) quedaba bien,
   pero apilados verticalmente (columna) no tenian separacion consistente
   entre si porque el padding era horizontal-heavy y no incluia margen
   propio; se agrega gap uniforme independiente del contenedor padre. --- */
.mini-kpi {
    padding: 10px 12px;
    margin-bottom: 8px;
}
.mini-kpi:last-child {
    margin-bottom: 0;
}

/* --- table-bordered en modo oscuro: Bootstrap pinta sus bordes con la
   variable global --bs-border-color (no la --bs-table-border-color que
   .table ya sigue via adminhmd.css), asi que quedaba con un borde gris
   claro fijo sin importar el tema. Se fuerza a que use el mismo borde que
   el resto de la interfaz oscura. --- */
html[data-theme="dark"] .table-bordered > :not(caption) > * > * {
    border-color: var(--admin-border) !important;
}

/* --- Modal Detalle de Equipo: menos padding en las tablas de datos (se
   veian sueltas/con aire de mas) y elementos mejor alineados. --- */
#detalle-equipo-body table.table-sm th,
#detalle-equipo-body table.table-sm td {
    padding: 0.35rem 0.5rem;
    vertical-align: middle;
}
#detalle-equipo-body table.table-sm th {
    width: 40%;
    color: var(--admin-muted);
    font-weight: 600;
    white-space: nowrap;
}

/* --- Select2 (aplicado a TODOS los <select> de la app, incluidos los
   combos de filtro) en modo oscuro: el tema select2-bootstrap-5-theme.min.css
   es un CSS de terceros que no conoce las variables --admin-*, asi que
   quedaba siempre con la paleta clara fija, rompiendo la vista en modo
   oscuro (ej. "Todos los tipos"/"Todas las marcas"/"Todas las ubicaciones"
   en Equipos). --- */
html[data-theme="dark"] .select2-container--bootstrap-5 .select2-selection {
    background-color: var(--admin-surface);
    border-color: var(--admin-border) !important;
    color: var(--admin-text);
}
html[data-theme="dark"] .select2-container--bootstrap-5 .select2-selection__rendered {
    color: var(--admin-text);
}
html[data-theme="dark"] .select2-container--bootstrap-5 .select2-selection__placeholder {
    color: var(--admin-muted);
}
html[data-theme="dark"] .select2-container--bootstrap-5 .select2-selection__arrow b {
    border-color: var(--admin-muted) transparent transparent transparent;
}
html[data-theme="dark"] .select2-dropdown {
    background-color: var(--admin-surface);
    border-color: var(--admin-border);
    color: var(--admin-text);
}
/* El tema select2-bootstrap-5-theme.min.css define el campo de busqueda con un
   selector compuesto de 4 clases (".select2-container--bootstrap-5 .select2-dropdown
   .select2-search .select2-search__field") — hace falta igualar esa especificidad
   para poder pisarlo, la regla simple de una sola clase no alcanza. */
html[data-theme="dark"] .select2-container--bootstrap-5 .select2-dropdown .select2-search .select2-search__field {
    background-color: var(--admin-surface-soft);
    border-color: var(--admin-border) !important;
    color: var(--admin-text);
}
html[data-theme="dark"] .select2-results__option {
    color: var(--admin-text);
}
html[data-theme="dark"] .select2-results__option--highlighted {
    background-color: var(--admin-primary) !important;
    color: #0a0a0a !important;
}
html[data-theme="dark"] .select2-results__option--selected {
    background-color: var(--admin-surface-soft);
}
html[data-theme="dark"] .select2-container--bootstrap-5.select2-container--focus .select2-selection,
html[data-theme="dark"] .select2-container--bootstrap-5.select2-container--open .select2-selection {
    border-color: #93c5fd !important;
    box-shadow: var(--admin-ring);
}

/* --- Boton "Exportar": mismo estilo (verde solido) en TODA la app y en
   ambos temas, sin importar que clase bootstrap tenga cada seccion
   (outline-success/outline-secondary quedaban inconsistentes entre si y
   contra el resto de los botones del encabezado). --- */
[id^="btn-export-"] {
    background-color: #198754 !important;
    border-color: #198754 !important;
    color: #fff !important;
}
[id^="btn-export-"]:hover,
[id^="btn-export-"]:focus {
    background-color: #157347 !important;
    border-color: #146c43 !important;
    color: #fff !important;
}

/* --- Dashboard: los mini-kpi (usuarios/vlans/proveedores/.../pacheras) viven
   TODOS en un unico .row que envuelve (col-6/col-sm-4 en pantallas
   angostas), asi que "Pacheras" cae justo debajo de "Usuarios" en una
   segunda linea del mismo flex container. Bootstrap no agrega separacion
   vertical automatica entre lineas de un row que wrappea — el
   margin-bottom de .mini-kpi no alcanza a separar bien esa segunda linea
   en algunos anchos. row-gap es la forma robusta de garantizarlo. */
.dashboard-mini-kpis {
    row-gap: 10px;
}

/* --- Barra de resize de columnas de Tabulator: mas fina en todos lados --- */
.tabulator .tabulator-col-resize-handle {
    width: 4px;
}

/* --- Panel Equipos: redondeo consistente entre todos los botones del
   encabezado/filtros y el borde de la tabla (antes la tabla usaba 10px y
   los botones 8px, se pareja todo a 8px) --- */
.seccion-controles .btn,
.btn-accion,
.btn-toggle-estado,
.input-busqueda input {
    border-radius: 8px;
}
/* El campo de busqueda siempre a la derecha del bloque de filtros/controles
   en el que vive, en todas las secciones de la app. */
.input-busqueda {
    margin-left: auto;
}

/* Menu lateral contraido (body.sidebar-mini, boton de "resumir" arriba a la
   izquierda): los iconos de cada seccion no se veian y el menu quedaba
   inutilizable. Causa real: ".nav-link" es un item de CSS Grid (".sidebar-nav"
   usa display:grid) y por defecto los items de grid tienen min-width:auto, que
   los hace NO achicarse por debajo del tamaño minimo de su contenido aunque el
   texto (".nav-text") ya este colapsado a width:0/opacity:0 — en la practica
   ".nav-link" seguia midiendo ~223px (el ancho completo, con texto) dentro de
   un contenedor de solo 83px, y como ".nav-link" tiene overflow:visible, ese
   exceso de ancho empujaba el icono centrado bien a la derecha, fuera del
   area visible del sidebar (que si recorta con overflow-x:hidden) — quedaba
   ahi, invisible, en vez de centrado en los 84px del menu contraido. Es el
   bug clasico de "grid blowout": la solucion estandar es min-width:0 en el
   item de grid para que respete el ancho real de su columna. */
@media (min-width: 992px) {
    /* Los encabezados de grupo ("EQUIPAMIENTO", "RED", "MIKROTIK — WIFI", etc.)
       son texto puro sin icono — en modo contraido no hay forma de mostrarlos
       apropiadamente (no entran, y no tienen un icono propio como los nav-link)
       asi que se ocultan del todo en vez de dejarlos truncados/recortados. */
    body.sidebar-mini .sidebar-section-label,
    body.sidebar-mini .sidebar-section-label-sub {
        display: none;
    }
}
@media (min-width: 992px) {
    /* min-width:0 en el item no alcanzaba solo: la columna implicita del
       grid (".sidebar-nav" no define grid-template-columns) se autodimensiona
       al max-content de sus items ANTES de que el item reciba su ancho final
       — con el track ya "inflado" a 223px, "width:100%" en el item vuelve a
       dar 223px (100% de un track que sigue siendo ancho). Hay que fijar el
       track mismo a un tamaño acotado por el contenedor (1fr en vez de auto). */
    body.sidebar-mini .sidebar-nav {
        grid-template-columns: minmax(0, 1fr);
    }
    body.sidebar-mini .sidebar-nav .nav-link {
        width: 100%;
        min-width: 0;
    }
    /* El icono seguia viendose pegado a la izquierda pese a justify-content:center:
       ".nav-link" es flex con "gap: 0.75rem" entre el icono y el texto — ese gap
       se sigue reservando ENTRE los dos hijos aunque el texto tenga width:0 (el
       gap no depende del tamaño de los items, solo de que existan como hijos
       separados), asi que el navegador centraba "icono + gap + texto invisible"
       como grupo: el icono quedaba corrido a la izquierda de ese grupo, con el
       espacio del gap totalmente vacio a su derecha, dando la sensacion de estar
       "haciendo tope". Sacando el texto del flujo con display:none (no solo
       opacity/width) el link queda con un solo hijo real (el icono) y
       justify-content:center lo centra de verdad, sin gap fantasma. */
    body.sidebar-mini .sidebar-nav .nav-link .nav-text {
        display: none;
    }
    /* El usuario (avatar/nombre/rol) y "Sistema en línea" no entran legibles en
       84px y ocupan espacio vertical valioso — se ocultan del todo contraido,
       igual que ya se hace con los encabezados de grupo. */
    body.sidebar-mini .sidebar-user,
    body.sidebar-mini .sidebar-footer {
        display: none;
    }
}
