/* ============================================================================
   REFINAMIENTO VISUAL — Abrebox ROOT · Fase 2 (base global)
   ============================================================================
   Qué es este archivo
   -------------------
   Una CAPA de acabado que se carga DESPUÉS de styles.css. Su único trabajo es
   llevar al resto del panel el mismo nivel de acabado que ya tiene la pantalla
   de bienvenida: profundidad suave, tipografía tranquila, un solo azul de
   marca y transiciones cortas.

   Qué NO hace
   -----------
   No toca anchos, posiciones, rejillas ni estructura. No hay una sola regla
   que cambie `width`, `display`, `position` o `flex-direction` de algo que ya
   existiera. Por eso no puede descolocar un formulario ni romper una tabla.

   Cómo revertirlo
   ---------------
   Se quita la línea <link ... refinamiento.css> de panel.php e index.php y
   la web vuelve exactamente a como estaba. Nada más.

   Orden del archivo
   -----------------
     0. Paleta y medidas (variables)
     1. Base: fondo, tipografía, selección, foco
     2. Menú lateral (sidebar)
     3. Barra superior: título y menú de usuario
     4. Lienzo de contenido y tarjetas
     5. Tablas y listados
     6. Formularios: campos, etiquetas y ayudas
     7. Botones
     8. Modales, spinner y estados de carga
     9. Detalles finales y accesibilidad
   ============================================================================ */


/* ============================================================================
   0. PALETA Y MEDIDAS
   ----------------------------------------------------------------------------
   Los valores salen de la pantalla de bienvenida, que es la referencia de
   calidad. Tenerlos aquí como variables evita que cada pantalla invente su
   propio azul o su propia sombra.
   ============================================================================ */
:root {
    /* Azules de marca */
    --abx-tinta:        #0d1b2a;   /* Azul casi negro: textos fuertes */
    --abx-azul:         #105680;   /* Azul Abrebox: acción y estado activo */
    --abx-azul-titulo:  #37568A;   /* Azul de los títulos de pantalla */
    --abx-azul-claro:   #8fd3ff;   /* Acento (degradados) */

    /* Neutros (escala tipo Apple: gris cálido, nunca azulado chillón) */
    --abx-texto:        #1c1c1e;   /* Texto principal */
    --abx-texto-2:      #6e6e73;   /* Texto secundario, descripciones */
    --abx-texto-3:      #9aa0aa;   /* Pies, marcas de agua */
    --abx-linea:        rgba(13, 27, 42, 0.08);  /* Filetes de 1px */
    --abx-linea-suave:  rgba(13, 27, 42, 0.05);

    /* Superficies */
    --abx-lienzo:       #EEEFF2;   /* Fondo de la aplicación */
    --abx-blanco:       #ffffff;   /* Tarjetas */
    --abx-campo:        #F4F5F7;   /* Fondo de inputs y selects */
    --abx-campo-hover:  #EDEEF1;

    /* Semánticos */
    --abx-rojo:         #D50000;
    --abx-rojo-texto:   #C21807;
    --abx-verde:        #2C8D4B;

    /* Radios: tres tamaños, ni uno más */
    --abx-r-s:  12px;   /* campos, botones, píldoras pequeñas */
    --abx-r-m:  16px;   /* bloques internos */
    --abx-r-l:  20px;   /* tarjetas y tablas */

    /* Sombras: profundidad por capas, nunca un borde gris */
    --abx-sombra-1: 0 1px 2px rgba(13, 27, 42, 0.04),
                    0 6px 18px rgba(13, 27, 42, 0.05);
    --abx-sombra-2: 0 2px 6px rgba(13, 27, 42, 0.05),
                    0 14px 34px rgba(13, 27, 42, 0.09);
    --abx-sombra-3: 0 24px 60px rgba(13, 27, 42, 0.26);

    /* Curvas de animación: la misma que usa la bienvenida */
    --abx-curva:     cubic-bezier(0.22, 1, 0.36, 1);
    --abx-curva-mue: cubic-bezier(0.34, 1.2, 0.64, 1);  /* con muelle */
}


/* ============================================================================
   1. BASE
   ============================================================================ */

/* El fondo plano #E5E5E5 aplanaba las tarjetas blancas. Un gris algo más
   claro y ligeramente frío hace que el blanco se despegue y que las sombras
   se lean. Es el mismo truco de la bienvenida, aplicado a toda la web. */
body.body-panel {
    background: var(--abx-lienzo);
}

/* Suavizado de fuentes: con la San Francisco del sistema, esto es la
   diferencia entre "texto de panel de control" y "texto de aplicación". */
body.body-panel,
body.body-index {
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
}

/* Selección de texto en azul de marca en lugar del azul del navegador. */
::selection {
    background: rgba(16, 86, 128, 0.16);
    color: var(--abx-tinta);
}

/* Foco: solo visible cuando se navega con teclado (no al hacer clic), y en
   azul de marca. Antes era un azul claro genérico heredado de un tema oscuro. */
.dropdown-toggle:focus,
li a.item:focus,
button:focus,
a:focus {
    outline: none;
}
.dropdown-toggle:focus-visible,
li a.item:focus-visible,
button:focus-visible,
a:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
    outline: 2px solid rgba(16, 86, 128, 0.55);
    outline-offset: 2px;
    border-radius: 8px;
}

/* Enlaces dentro de tablas: azul de marca y subrayado discreto en vez de
   subrayado permanente en gris. */
table a {
    color: var(--abx-azul);
    text-decoration-color: rgba(16, 86, 128, 0.32);
    text-underline-offset: 2px;
    transition: text-decoration-color 0.18s ease;
}
table a:hover {
    text-decoration-color: rgba(16, 86, 128, 0.85);
}


/* ============================================================================
   2. MENÚ LATERAL
   ----------------------------------------------------------------------------
   El sidebar venía de un tema oscuro: varios `hover` usaban blancos
   translúcidos que sobre fondo blanco no se ven, y los iconos llevaban
   filtros de brillo que los lavaban. Aquí se corrige todo eso.
   ============================================================================ */

.sidebar {
    background: var(--abx-blanco);
    box-shadow: var(--abx-sombra-1);
    border: 1px solid var(--abx-linea-suave);
    border-radius: var(--abx-r-l);
    box-sizing: border-box;   /* el filete no suma ancho al menú */
}

/* El logo se veía lavado por un brightness(1.2) heredado del tema oscuro. */
.logo-nuevo {
    filter: none;
}
.logo-nuevo:hover {
    transform: scale(1.02);
}

/* El separador bajo el logo usaba un blanco translúcido: invisible. */
.contenedor-logo {
    border-bottom: none;
}

.fuente-root {
    color: var(--abx-azul-titulo);
    letter-spacing: 2px;
    font-size: 22px;
    opacity: 0.9;
}

/* --- Elementos del menú ---------------------------------------------------
   Reposo: gris tranquilo. Ratón encima: un gris apenas perceptible (antes era
   un blanco invisible). Activo: fondo azul muy diluido y texto azul. */
.dropdown-toggle,
#dashboard {
    color: #4b5563;
    font-weight: 500;
}

.dropdown-toggle:hover,
#dashboard:hover,
li a.item:hover {
    background: rgba(13, 27, 42, 0.045);
    color: var(--abx-tinta);
    box-shadow: none;              /* el inset blanco anterior no se veía */
}

.dropdown-toggle.selected,
#dashboard.selected {
    background: rgba(16, 86, 128, 0.08);
    color: var(--abx-azul);
    border: 1px solid rgba(16, 86, 128, 0.12);
    font-weight: 600;
}

/* La marca vertical del elemento activo se retira: el fondo azul diluido de
   la píldora ya dice cuál está seleccionado, y el filete sobresalía por fuera
   del botón ensuciando el borde del menú. */
.dropdown-toggle.selected::before,
#dashboard.selected::before {
    display: none;
}

/* Iconos: el filtro de brillo los lavaba sobre fondo claro. Se sustituye por
   opacidad, que es lo que realmente se quería. */
.sidebar .icon,
#dashboard img,
.notificaciones-icon {
    filter: none;
    opacity: 0.5;
    transition: opacity 0.18s ease;
}
.dropdown-toggle:hover .icon,
.dropdown-toggle.selected .icon,
#dashboard:hover img,
#dashboard.selected img,
.dropdown-toggle:hover .notificaciones-icon,
.dropdown-toggle.selected .notificaciones-icon {
    filter: none;
    opacity: 0.95;
}

.sidebar .arrow,
.sidebar .arrow-prox {
    filter: none;
    opacity: 0.35;
}

/* Barra de desplazamiento del menú: era blanca sobre blanco. */
.sidebar::-webkit-scrollbar-thumb {
    background: rgba(13, 27, 42, 0.14);
}
.sidebar::-webkit-scrollbar-thumb:hover {
    background: rgba(13, 27, 42, 0.24);
}

/* Sub-enlaces: tamaño de texto un punto por debajo del menú padre, que es lo
   que crea la jerarquía sin necesidad de líneas ni recuadros. */
li a.item {
    font-size: 0.92rem;
    color: #5b6472;
}
li a.item.selected {
    color: var(--abx-azul);
}

/* Etiqueta "Próximamente" */
.simple {
    color: var(--abx-azul);
    background: rgba(16, 86, 128, 0.10);
}


/* ============================================================================
   3. BARRA SUPERIOR: TÍTULO Y MENÚ DE USUARIO
   ----------------------------------------------------------------------------
   Era el elemento que más delataba la diferencia de nivel: una píldora azul
   grisácea (#B8C8D0) de 20rem, plana y con más peso visual que el propio
   título de la pantalla. Pasa a ser una píldora blanca con filete de 1px y
   una sombra mínima: presente, pero por debajo del título.
   ============================================================================ */

.titulo-boton h1 {
    color: var(--abx-azul-titulo);
    font-size: 2rem;
    font-weight: 700;
    letter-spacing: -0.6px;
    line-height: 1.15;
}

/* Títulos que son enlace de "volver" (Editar usuario, Movimientos...): se
   desplazan levemente al pasar el ratón, que es la pista de que se puede
   pulsar. Sin subrayado. */
.titulo-boton a h1 {
    transition: color 0.18s ease, transform 0.18s var(--abx-curva);
}
.titulo-boton a:hover h1 {
    color: var(--abx-azul);
    transform: translateX(-3px);
}

/* --- Píldora de usuario --------------------------------------------------- */
.dropdown-toggle-user {
    background: var(--abx-blanco);
    border: 1px solid var(--abx-linea);
    box-shadow: 0 1px 2px rgba(13, 27, 42, 0.05),
                0 6px 16px rgba(13, 27, 42, 0.06);
    transition: box-shadow 0.2s ease, transform 0.2s var(--abx-curva),
                background 0.2s ease;
    cursor: pointer;
}
.dropdown-toggle-user:hover {
    box-shadow: 0 2px 4px rgba(13, 27, 42, 0.06),
                0 10px 24px rgba(13, 27, 42, 0.10);
    transform: translateY(-1px);
}
.dropdown-toggle-user:active {
    transform: translateY(0);
}

/* Correo del usuario: gris fuerte en lugar de negro puro, tamaño estable. */
.boton-header .usuario {
    color: var(--abx-texto);
    font-size: 0.875rem !important;
    font-weight: 600 !important;
    letter-spacing: -0.1px;
}

/* Avatar: círculo en azul diluido, sin el filtro de color anterior que
   dejaba el icono de un gris sucio. */
.imagen-boton {
    background: rgba(16, 86, 128, 0.10);
    border: none;
    box-shadow: none;
}
.imagen-boton img {
    filter: none;
    opacity: 0.55;
}

.boton-header .arrow {
    opacity: 0.4;
}

/* Cuando el desplegable está abierto, la píldora y la lista forman un solo
   bloque blanco: se quitan las esquinas de en medio y se iguala el color. */
.boton-header.bordear .dropdown-toggle-user {
    box-shadow: none;
    border-bottom-color: transparent;
    background: var(--abx-blanco);
}

.boton-header ul {
    background: var(--abx-blanco);
    border: 1px solid var(--abx-linea);
    border-top: none;
    box-shadow: 0 16px 40px rgba(13, 27, 42, 0.14);
    padding: 0.75rem 0 1rem;
    overflow: hidden;
}

.boton-header li {
    margin: 0;
    padding: 0;
    width: 100%;
}

/* Cada opción ocupa toda la fila y se ilumina entera al pasar el ratón, en
   vez de subrayar solo el texto. */
.boton-header .item {
    display: block;
    width: 100%;
    box-sizing: border-box;
    padding: 0.7rem 1.5rem;
    text-align: right;
    color: var(--abx-texto);
    font-size: 0.875rem;
    font-weight: 500;
    transition: background 0.16s ease, color 0.16s ease;
}
.boton-header .item:hover {
    background: rgba(13, 27, 42, 0.05);
    text-decoration: none !important;
}
.boton-header .centro-de-ayuda {
    justify-content: flex-end;
}
.boton-header .cerrar-sesion:hover {
    background: rgba(213, 0, 0, 0.07);
}

/* Los separadores eran una línea negra de 0.1rem: demasiado peso. */
.boton-header .salto {
    width: auto !important;
    margin: 0.35rem 1.5rem !important;
    border-bottom: 1px solid var(--abx-linea);
}


/* ============================================================================
   4. LIENZO DE CONTENIDO Y TARJETAS
   ============================================================================ */

/* Entrada suave del contenido en cada carga de pantalla. Es la misma
   sensación que ya daba la bienvenida, ahora en toda la web. No mueve el
   layout: solo opacidad y 10px de desplazamiento. */
.extension {
    /* (La animación se activa desde el bloque 22.) */
    /* `backwards` (no `both`) a propósito: al terminar la animación el
       elemento se queda SIN `transform`. Es importante — un `transform`
       permanente en un contenedor convierte a sus hijos `position: fixed` en
       posicionados respecto a él, y eso descolocaría los modales que algunas
       pantallas definen dentro del propio contenido. */
    animation: none;
}
@keyframes abxEntrar {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* Tarjetas: un solo radio y una sola sombra en todo el panel. */
.contenedores {
    background: var(--abx-blanco);
    border-radius: var(--abx-r-l);
    border: 1px solid var(--abx-linea-suave);
    box-shadow: var(--abx-sombra-1);
    color: var(--abx-texto-2);
    box-sizing: border-box;   /* el filete no suma ancho a la tarjeta */
    transition: box-shadow 0.22s ease;
}

/* Títulos y subtítulos dentro de las tarjetas: la jerarquía la marcan el
   tamaño y el peso, no el color. */
.contenedores h5 {
    color: var(--abx-texto) !important;
    font-weight: 600 !important;
    letter-spacing: -0.4px;
}
.contenedores h6 {
    color: var(--abx-texto) !important;
    font-weight: 600 !important;
    letter-spacing: -0.1px;
}

label {
    color: var(--abx-texto-2);
    letter-spacing: -0.05px;
}


/* ============================================================================
   5. TABLAS Y LISTADOS
   ----------------------------------------------------------------------------
   La estructura no se toca (anchos, columnas y paddings quedan igual). Solo
   cambia el acabado: cebra mucho más tenue, cabecera con más aire y filete
   inferior, y fila bajo el cursor en azul diluido.
   ============================================================================ */

table {
    border-radius: var(--abx-r-l);
    box-shadow: var(--abx-sombra-1);
}
/* Importante: NO se pone `overflow: hidden` en la tabla. Rompería la
   cabecera fija (`position: sticky`) que ya existe en styles.css, y tampoco
   hace falta: las esquinas inferiores ya las redondea la regla que hay sobre
   la última fila. Tampoco se le añade borde, para no sumar 2px al ancho de
   tablas que se calculan al pixel. */

/* Se retira la cebra. Con filas alternas grises, al pasar el ratón por una
   fila blanca esta se volvía del mismo gris que sus vecinas y quedaban tres
   filas seguidas idénticas. Ahora todas las filas son blancas, se separan con
   un filete de 1px y el hover es el ÚNICO fondo de color de la tabla: no hay
   forma de confundir qué fila está señalando el ratón. */
tbody tr:hover {
    background: rgba(16, 86, 128, 0.07) !important;
}

/* Cabecera: texto más contenido y un filete que la separa de los datos. */
* th {
    color: var(--abx-texto);
    font-size: 0.92rem;
    font-weight: 600;
    letter-spacing: -0.1px;
}

* td {
    color: #4a4a4f;
    border-bottom: 1px solid var(--abx-linea-suave);
}
tbody tr:last-child td {
    border-bottom: none;
}

/* Flechas de ordenación: se atenúan hasta que el ratón entra en la cabecera. */
table th div div img {
    filter: none;
    opacity: 0.3;
    transition: opacity 0.16s ease;
}
table th:hover div div img {
    opacity: 0.65;
}

/* Los campos de filtro de la cabecera se definen en el bloque 10. */


/* ============================================================================
   6. FORMULARIOS
   ----------------------------------------------------------------------------
   Dos cambios llevan la mayor parte de la mejora:
     · Se quita la CURSIVA de los campos y los placeholders. Un formulario
       entero en cursiva se lee como un borrador, no como una herramienta.
     · Los campos dejan de ser una caja gris plana: filete de 1px, radio
       consistente y anillo azul al enfocar.
   Las alturas, anchos y márgenes NO se tocan: los definen las reglas
   existentes y siguen mandando ellas.
   ============================================================================ */

/* Se enumeran los tipos de campo que SÍ reciben este acabado, en vez de
   excluir los que no. Es más largo de leer, pero deja el peso del selector
   bajo y predecible: así las reglas más específicas de más abajo (buscadores
   de tabla, buscador general) pueden ganarle sin recurrir a trucos. Casillas,
   radios, ficheros, color y rangos quedan fuera a propósito: tienen su propio
   dibujo nativo. */
.extension input[type="text"],
.extension input[type="email"],
.extension input[type="tel"],
.extension input[type="number"],
.extension input[type="password"],
.extension input[type="search"],
.extension input[type="url"],
.extension input[type="date"],
.extension input[type="time"],
.extension input[type="datetime-local"],
.extension input:not([type]),
.extension select,
.extension textarea {
    font-style: normal !important;
    color: var(--abx-texto) !important;
    /* `background-color`, NO el atajo `background`: el atajo borra el
       background-image y con él la lupa dibujada en los buscadores. */
    background-color: var(--abx-campo) !important;
    border: 1px solid transparent !important;
    border-radius: var(--abx-r-s) !important;
    transition: background 0.16s ease, border-color 0.16s ease,
                box-shadow 0.16s ease !important;
}

.extension input[type="text"]:hover,
.extension input[type="email"]:hover,
.extension input[type="tel"]:hover,
.extension input[type="number"]:hover,
.extension input[type="password"]:hover,
.extension input[type="search"]:hover,
.extension input[type="url"]:hover,
.extension input[type="date"]:hover,
.extension input[type="time"]:hover,
.extension input[type="datetime-local"]:hover,
.extension input:not([type]):hover,
.extension select:hover,
.extension textarea:hover {
    background-color: var(--abx-campo-hover) !important;
}

/* Foco: filete azul + anillo. Sustituye al anillo suelto de la Fase 1 para
   que el campo entero se lea como "aquí estás escribiendo". */
.extension input:focus,
.extension select:focus,
.extension textarea:focus {
    background-color: var(--abx-blanco) !important;
    border-color: rgba(16, 86, 128, 0.55) !important;
    box-shadow: 0 0 0 3px rgba(16, 86, 128, 0.14) !important;
    outline: none !important;
}

/* Placeholders: sin cursiva y en el gris secundario. */
::placeholder {
    font-style: normal;
    color: var(--abx-texto-3);
    opacity: 1;
}

/* Campos bloqueados: se leen como bloqueados, no como "medio rotos". */
input:disabled,
select:disabled,
textarea:disabled {
    background: rgba(13, 27, 42, 0.04) !important;
    color: var(--abx-texto-3) !important;
    opacity: 1;
    cursor: not-allowed;
}

/* Botón de contraseña aleatoria: mismo lenguaje que los campos. */
.contrasenya-aleotoria {
    background: var(--abx-campo);
    border-radius: var(--abx-r-s);
    border: 1px solid transparent;
    transition: background 0.16s ease, transform 0.12s ease;
}
.contrasenya-aleotoria:hover {
    background: var(--abx-campo-hover);
    transform: translateY(-1px);
}

/* Enlace "Añadir más": deja de ser un subrayado permanente. */
.anyadir-mas {
    font-size: 0.95rem !important;
    text-decoration: none;
    box-shadow: inset 0 -1px 0 rgba(16, 86, 128, 0.28);
    transition: box-shadow 0.18s ease;
}
.anyadir-mas:hover {
    box-shadow: inset 0 -1px 0 rgba(16, 86, 128, 0.85);
}

/* Interruptores tipo iOS: sombra interior para que el recorrido se lea. */
.slider_switch {
    box-shadow: inset 0 0 0 1px rgba(13, 27, 42, 0.06);
}
.slider_switch::before {
    box-shadow: 0 1px 3px rgba(13, 27, 42, 0.22);
}


/* ============================================================================
   7. BOTONES
   ----------------------------------------------------------------------------
   Una sola acción principal por pantalla (azul sólido). Las demás se apoyan
   en su color pero con mucho menos peso y recuperan intensidad al pasar el
   ratón. Se retira el `text-decoration: underline` del hover: subrayar un
   botón sólido es un resto de la época en que eran enlaces.
   ============================================================================ */

.boton-guardar,
.boton-guardar-enviar,
.boton-eliminar,
.boton-cancelar,
.boton-traspasar,
.consultar-movimientos {
    border-radius: var(--abx-r-s);
    font-weight: 600;
    letter-spacing: -0.1px;
    transition: background 0.18s ease, color 0.18s ease,
                box-shadow 0.2s ease, transform 0.12s var(--abx-curva-mue);
}

.boton-guardar:hover,
.boton-guardar-enviar:hover,
.boton-eliminar:hover,
.boton-cancelar:hover,
.boton-traspasar:hover,
.consultar-movimientos:hover {
    text-decoration: none;
    transform: translateY(-1px);
}

.boton-guardar:active,
.boton-guardar-enviar:active,
.boton-eliminar:active,
.boton-cancelar:active,
.boton-traspasar:active,
.consultar-movimientos:active {
    transform: translateY(0) scale(0.99);
}

/* Acción principal */
.boton-guardar,
.boton-guardar-enviar,
.consultar-movimientos {
    background: var(--abx-azul);
    box-shadow: 0 1px 2px rgba(16, 86, 128, 0.20),
                0 6px 16px rgba(16, 86, 128, 0.22);
}
.boton-guardar:hover,
.boton-guardar-enviar:hover,
.consultar-movimientos:hover {
    background: #0c6a9e;
    box-shadow: 0 2px 4px rgba(16, 86, 128, 0.22),
                0 10px 24px rgba(16, 86, 128, 0.28);
}

/* Acción destructiva: discreta en reposo, inequívoca al confirmarla. */
.boton-eliminar {
    background: rgba(213, 0, 0, 0.08);
    color: var(--abx-rojo-texto);
    box-shadow: inset 0 0 0 1px rgba(213, 0, 0, 0.20);
}
.boton-eliminar:hover {
    background: var(--abx-rojo);
    color: var(--abx-blanco);
    box-shadow: 0 2px 4px rgba(213, 0, 0, 0.18),
                0 10px 24px rgba(213, 0, 0, 0.26);
}

/* Acciones secundarias */
.boton-cancelar,
.boton-traspasar {
    background: rgba(28, 28, 30, 0.05);
    color: var(--abx-texto);
    box-shadow: inset 0 0 0 1px rgba(28, 28, 30, 0.14);
}
.boton-cancelar:hover,
.boton-traspasar:hover {
    background: var(--abx-texto);
    color: var(--abx-blanco);
    box-shadow: 0 2px 4px rgba(13, 27, 42, 0.14),
                0 10px 24px rgba(13, 27, 42, 0.18);
}


/* ============================================================================
   8. MODALES, SPINNER Y CARGA
   ============================================================================ */

/* Fondo del modal: oscurecido y desenfocado. El desenfoque es lo que hace
   que el diálogo se sienta "por encima" y no pegado sobre la pantalla. */
.modal-pdf,
.modal-imagen,
.modal-sin-imagen,
.modal-selected,
.modal-no-selected {
    background-color: rgba(13, 27, 42, 0.42);
    -webkit-backdrop-filter: saturate(160%) blur(6px);
    backdrop-filter: saturate(160%) blur(6px);
}

.modal-contenedor {
    border-radius: var(--abx-r-l);
    box-shadow: var(--abx-sombra-3);
    border: 1px solid rgba(255, 255, 255, 0.5);
}
.modal-contenedor p {
    color: var(--abx-texto);
    font-size: 1rem;
    line-height: 1.5;
    margin: 0.35rem 1.5rem 0 !important;
}
.modal-contenedor hr {
    border: none;
    border-top: 1px solid var(--abx-linea);
    color: transparent;
}

/* Los botones del modal pasan a ser píldoras: el de confirmar con peso, el
   de cancelar sin él. Así se distingue de un vistazo qué hace cada uno. */
.boton-modal {
    padding: 0.55rem 1.25rem;
    border-radius: 999px;
    font-size: 0.92rem;
    font-weight: 600;
    color: var(--abx-azul);
    transition: background 0.16s ease, color 0.16s ease,
                transform 0.12s var(--abx-curva-mue);
}
.boton-modal:hover {
    background: rgba(16, 86, 128, 0.09);
    filter: none;
}
.boton-modal:active {
    transform: scale(0.97);
}
#confirmarEliminar,
#confirmarEliminarImagen {
    background: var(--abx-azul);
    color: var(--abx-blanco);
}
#confirmarEliminar:hover,
#confirmarEliminarImagen:hover {
    background: #0c6a9e;
    color: var(--abx-blanco);
}

/* Pantallas de carga: tienen que compartir el fondo de la aplicación, si no
   se ve un rectángulo gris distinto cada vez que carga una tabla. */
#cargando,
#cargando_usuarios,
#cargando_accesos {
    background-color: var(--abx-lienzo);
}

/* Spinner: aro fino en azul de marca, sin el borde blanco grueso. */
.spinner {
    border: 3px solid rgba(16, 86, 128, 0.15);
    border-top: 3px solid var(--abx-azul);
    width: 2.25rem;
    height: 2.25rem;
    animation: spin 0.85s cubic-bezier(0.5, 0.1, 0.4, 0.9) infinite;
}


/* ============================================================================
   9. DETALLES FINALES
   ============================================================================ */

/* Avisos y advertencias: filete lateral del color del aviso, que es más
   legible que un fondo de color a secas. */
.aviso-advertencia {
    border-radius: var(--abx-r-m);
    box-shadow: inset 3px 0 0 #E8A33D;
}
.aviso-advertencia.aviso-critico {
    box-shadow: inset 3px 0 0 var(--abx-rojo);
}

/* Filetes horizontales genéricos: una línea de 1px, no un bloque gris. */
hr {
    border: none;
    border-top: 1px solid var(--abx-linea);
    color: transparent;
}

/* Números de serie y códigos: tipografía monoespaciada con el cero barrado
   para no confundir 0 con O al leer un número de serie por teléfono. */
.nserie {
    letter-spacing: 0.2px;
}

/* Overlay del menú en móvil: mismo desenfoque que los modales. */
.sidebar-overlay {
    background: rgba(13, 27, 42, 0.38);
    -webkit-backdrop-filter: blur(4px);
    backdrop-filter: blur(4px);
}

/* Quien tenga activado "reducir movimiento" en su sistema no ve ninguna de
   las animaciones anteriores. */
@media (prefers-reduced-motion: reduce) {
    .extension,
    .modal-contenedor {
        animation: none !important;
    }
    * {
        transition-duration: 0.01ms !important;
    }
}

/* ============================================================================
   FIN DE LA CAPA DE REFINAMIENTO
   ============================================================================ */


/* ============================================================================
   10. CABECERA DE TABLA
   ----------------------------------------------------------------------------
   El problema: la cabecera y la fila de filtros flotaban sobre el mismo blanco
   que los datos, así que no se leían como "cabecera", y cada buscador parecía
   una pastilla gris pegada encima de la tabla.

   La solución: la cabecera entera (título de columna + filtro) pasa a ser UN
   bloque con fondo propio, pegado al borde superior de la tabla y cerrado por
   un filete. Dentro de ese bloque, los buscadores van en blanco con filete:
   sobre fondo gris claro se leen como campos, no como manchas.
   ============================================================================ */

/* La tabla arrancaba con 1–1,5rem de relleno blanco por arriba: ese hueco
   impedía que la cabecera llegase al borde y es lo que la dejaba "flotando". */
table,
.contenedores-mis-paneles table,
.contenedores-mis-usuarios table {
    padding-top: 0;
}

/* --- El bloque de cabecera ------------------------------------------------- */
thead th {
    background: #F5F6F9;
}

/* Solo la fila de títulos queda fija al hacer scroll. Antes lo estaban las
   DOS filas de la cabecera con `top: 0`, así que se montaban una encima de
   otra en cuanto se bajaba por la lista. */
thead tr:first-child th {
    position: sticky;
    top: 0;
    z-index: 4;
    padding-top: 1.05rem !important;
    padding-bottom: 0.7rem !important;
}
thead tr:nth-child(2) th {
    position: static;
    z-index: auto;
    padding-bottom: 1rem !important;
    /* Mismo sangrado lateral que la fila de títulos: sin esto, cada buscador
       quedaba unos 7px a la izquierda de su propia etiqueta. */
    padding-left: 0.75rem !important;
    padding-right: 0.75rem !important;
}

/* Las esquinas superiores de la tabla las redondea ahora la cabecera. */
thead tr:first-child th:first-child { border-top-left-radius: var(--abx-r-l); }
thead tr:first-child th:last-child  { border-top-right-radius: var(--abx-r-l); }

/* Filete de cierre: separa la cabecera de los datos de forma inequívoca. */
thead tr:last-child th {
    box-shadow: inset 0 -1px 0 rgba(13, 27, 42, 0.12);
}

/* Títulos de columna: un punto más pequeños y en gris. El dato es lo que
   tiene que pesar; la etiqueta solo tiene que estar. */
thead tr:first-child th,
thead tr:first-child th p {
    color: #6b7280 !important;
    font-size: 0.8rem !important;
    font-weight: 600 !important;
    letter-spacing: 0.15px;
}

/* --- Buscadores de columna ------------------------------------------------- */
.extension thead th input:not([type="checkbox"]),
.extension thead th select {
    box-sizing: border-box;
    width: 100%;
    height: 2rem !important;
    border-radius: 8px !important;
    font-size: 0.82rem !important;
    font-style: normal !important;
    color: var(--abx-texto) !important;
    box-shadow: 0 1px 1px rgba(13, 27, 42, 0.03) !important;
    transition: border-color 0.16s ease, box-shadow 0.16s ease !important;
}

/* Lupa dibujada en el propio campo: es lo que convierte una caja cualquiera
   en "aquí se busca", sin tener que tocar el HTML de ninguna pantalla. */
.extension thead th input[type="text"] {
    padding: 0 0.6rem 0 1.85rem !important;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239aa0aa' stroke-width='2.2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M20 20l-3.6-3.6'/%3E%3C/svg%3E") !important;
    background-repeat: no-repeat !important;
    background-position: 0.55rem center !important;
    background-size: 0.85rem 0.85rem !important;
}

.extension thead th select {
    padding: 0 0.5rem !important;
}

.extension thead th input:not([type="checkbox"]):hover,
.extension thead th select:hover {
    border-color: rgba(13, 27, 42, 0.22) !important;
}

.extension thead th input:not([type="checkbox"]):focus,
.extension thead th select:focus {
    border-color: rgba(16, 86, 128, 0.6) !important;
    box-shadow: 0 0 0 3px rgba(16, 86, 128, 0.13) !important;
    outline: none !important;
}

/* Casilla "seleccionar todos": centrada y del tamaño de las de las filas. */
thead th input[type="checkbox"] {
    width: 1rem;
    height: 1rem;
    accent-color: var(--abx-azul);
}
tbody td input[type="checkbox"] {
    accent-color: var(--abx-azul);
}


/* ============================================================================
   11. BUSCADOR GENERAL Y BOTONES DE LISTADO
   ----------------------------------------------------------------------------
   El buscador general quedó gris sobre fondo gris al unificar los campos del
   panel: desaparecía. Es un control suelto sobre el lienzo, no un campo dentro
   de una tarjeta, así que le toca acabado de tarjeta — blanco y con sombra.
   ============================================================================ */
.extension input.input-buscar {
    background: var(--abx-blanco) !important;
    border: 1px solid transparent !important;
    border-radius: 1.2rem !important;
    box-shadow: var(--abx-sombra-1) !important;
    font-size: 0.95rem !important;
    font-weight: 500 !important;
    color: var(--abx-texto) !important;
    padding: 0 1rem 0 2.5rem !important;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239aa0aa' stroke-width='2.2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M20 20l-3.6-3.6'/%3E%3C/svg%3E") !important;
    background-repeat: no-repeat !important;
    background-position: 1rem center !important;
    background-size: 1rem 1rem !important;
    transition: box-shadow 0.18s ease, border-color 0.18s ease !important;
}
.extension input.input-buscar:hover {
    box-shadow: var(--abx-sombra-2) !important;
}
.extension input.input-buscar:focus {
    border-color: rgba(16, 86, 128, 0.5) !important;
    box-shadow: 0 0 0 3px rgba(16, 86, 128, 0.13) !important;
}

/* Botones de la barra del listado */
.buscar,
.generar-pdf,
.eliminar {
    border-radius: 1.2rem;
    font-weight: 600;
    box-shadow: 0 1px 2px rgba(16, 86, 128, 0.18),
                0 6px 16px rgba(16, 86, 128, 0.18);
    transition: background 0.18s ease, box-shadow 0.2s ease,
                transform 0.12s var(--abx-curva-mue);
}
.buscar:hover,
.generar-pdf:hover,
.eliminar:hover {
    text-decoration: none;
    transform: translateY(-1px);
}
.buscar:active,
.generar-pdf:active,
.eliminar:active { transform: translateY(0) scale(0.99); }

.eliminar {
    box-shadow: 0 1px 2px rgba(213, 0, 0, 0.16),
                0 6px 16px rgba(213, 0, 0, 0.18);
}

/* Un botón deshabilitado tiene que parecerlo: "Eliminar" arrancaba en rojo
   intenso aunque no hubiera ninguna fila marcada. */
.buscar:disabled,
.generar-pdf:disabled,
.eliminar:disabled {
    background: rgba(13, 27, 42, 0.06) !important;
    color: #a0a4ad !important;
    box-shadow: none;
    cursor: not-allowed;
    transform: none;
}

/* Tarjeta de resumen: mismo acabado que el resto de tarjetas. */
.stats-box {
    border-radius: var(--abx-r-l);
    border: 1px solid var(--abx-linea-suave);
    box-shadow: var(--abx-sombra-1);
    box-sizing: border-box;
    padding: 1.1rem 1.4rem 1.2rem;
}
.stats-box h3 {
    color: var(--abx-texto);
    font-weight: 600;
    font-size: 1rem;
    letter-spacing: -0.2px;
    margin-bottom: 0.8rem;
}


/* ============================================================================
   12. MENÚ DE USUARIO — CORRECCIONES
   ----------------------------------------------------------------------------
   Dos fallos que se veían en pantalla:

   a) Los puntitos grises delante de "Configuración", "Centro de Ayuda" y
      "Cerrar sesión". Venían del punto de los submenús del lateral, cuya
      regla (`li a.item::before`) es global y se colaba aquí. Se anula.

   b) La píldora del correo se veía de un blanco sucio mientras la lista de
      debajo era blanco puro. La culpa era de la sombra de la lista: con
      `blur 40 / y 16` se derramaba 24px hacia ARRIBA y teñía el botón. Se
      recorta con un radio negativo para que la sombra caiga solo hacia abajo.
   ============================================================================ */

/* (a) */
.boton-header li a.item::before {
    content: none !important;
}

/* (b) */
.boton-header .dropdown-toggle-user {
    background: var(--abx-blanco) !important;
    position: relative;
    z-index: 3;
}

.boton-header ul {
    z-index: 2;
    border: none;
    box-shadow: 0 22px 44px -16px rgba(13, 27, 42, 0.30);
}

/* Con el menú abierto, píldora y lista son una sola pieza blanca: el botón
   pierde su contorno y solo queda un filete de 1px como separación. */
.boton-header.bordear .dropdown-toggle-user {
    border-color: transparent;
    border-bottom: 1px solid var(--abx-linea);
    box-shadow: none;
    transform: none;
}

/* Avatar: gris neutro. El azul diluido anterior lo hacía competir con el
   correo, que es lo único que hay que leer ahí. */
.imagen-boton {
    background: rgba(13, 27, 42, 0.06);
}
.imagen-boton img {
    opacity: 0.45;
}


/* ============================================================================
   13. MODELOS Y VERSIONES — PULIDO
   ----------------------------------------------------------------------------
   La pantalla está bien construida, pero sus tarjetas eran blancos planos sin
   sombra: sobre el lienzo gris parecían recortes de papel pegados. Se les da
   la misma profundidad que al resto del panel. Se usa `.extension` delante
   porque los estilos de esa pantalla van en un <style> dentro del HTML y, a
   igualdad de peso, ganarían ellos.
   ============================================================================ */

.extension .dv-tarjeta-grafica,
.extension .dv-tarjeta-barras,
.extension .dv-tabla-versiones {
    border: 1px solid var(--abx-linea-suave);
    box-shadow: var(--abx-sombra-1);
}

/* Botón "Actualizar ahora": era un rectángulo azul macizo suelto en la parte
   alta, con más peso que el propio contenido. Pasa a píldora. */
.extension .dv-boton-actualizar {
    border-radius: 999px;
    height: 2.35rem;
    padding: 0 1.25rem;
    box-shadow: 0 1px 2px rgba(16, 86, 128, 0.18),
                0 6px 16px rgba(16, 86, 128, 0.20);
    transition: background 0.18s ease, box-shadow 0.2s ease,
                transform 0.12s var(--abx-curva-mue);
}
.extension .dv-boton-actualizar:hover {
    transform: translateY(-1px);
    box-shadow: 0 2px 4px rgba(16, 86, 128, 0.20),
                0 10px 24px rgba(16, 86, 128, 0.26);
}
.extension .dv-boton-actualizar:active {
    transform: translateY(0) scale(0.99);
}
.extension .dv-boton-actualizar:disabled {
    background: rgba(13, 27, 42, 0.06);
    color: #a0a4ad;
    box-shadow: none;
    transform: none;
}
.extension .dv-boton-actualizar:disabled:hover {
    background: rgba(13, 27, 42, 0.06);
    transform: none;
}

/* Barras de reparto: extremos redondeados y carril más tenue. Una barra con
   esquinas vivas dentro de una tarjeta de 20px de radio desentona. */
.extension .dv-barra-canal {
    background: rgba(13, 27, 42, 0.06);
    border-radius: 999px;
    overflow: hidden;
}
.extension .dv-barra-relleno {
    border-radius: 999px;
}

/* Las filas de la leyenda y de las versiones responden al ratón, igual que
   las filas de las tablas. */
.extension .dv-leyenda-fila,
.extension .dv-barra-item {
    border-radius: 8px;
    transition: background 0.14s ease;
}
.extension .dv-leyenda-fila:hover,
.extension .dv-barra-item:hover {
    background: rgba(16, 86, 128, 0.05);
}

/* La cabecera de esta pantalla se alinea con el ancho de las tarjetas. */
.extension .dv-cabecera {
    padding: 0 0.2rem;
}


/* ============================================================================
   14. AJUSTES DE PRECISIÓN EN LA CABECERA
   ----------------------------------------------------------------------------
   La primera y la última celda de la fila de filtros tienen en styles.css su
   propio `padding ... !important` con más peso que la regla general del
   bloque 10. Sin estas dos líneas, esas dos celdas conservarían los 2rem de
   relleno inferior y el bloque de cabecera quedaría descuadrado justo en los
   extremos, que es donde más se nota.
   ============================================================================ */
thead tr:nth-child(2) th:first-child,
thead tr:nth-child(2) th:last-child {
    padding-bottom: 1rem !important;
}

/* Las esquinas inferiores de la tabla igualan el radio de las superiores. */
tbody tr:last-child td:first-child { border-bottom-left-radius: var(--abx-r-l); }
tbody tr:last-child td:last-child  { border-bottom-right-radius: var(--abx-r-l); }


/* ============================================================================
   15. ICONOS DEL MENÚ LATERAL
   ----------------------------------------------------------------------------
   Los iconos eran PNG sueltos de orígenes distintos (admin_prueba.png,
   telefono.png, user.png...): grosores desiguales, tamaños desiguales y sin
   relación con los iconos de la bienvenida.

   Aquí se dibujan de nuevo con el MISMO trazo que las tarjetas del dashboard
   (línea de 2px, extremos redondeados, lienzo de 24x24) y sin tocar el HTML:
   los PNG se ocultan y el icono se pinta en el `::before` del botón.

   Se usa `mask` en lugar de `background-image` a propósito: así el icono toma
   el color del texto del botón: gris cuando está en reposo y azul de marca
   cuando el menú está activo, sin tener que generar dos versiones de cada uno.
   ============================================================================ */

/* Fuera los PNG antiguos. */
.sidebar .icon,
#dashboard img {
    display: none !important;
}

/* Lienzo común del icono nuevo. */
.sidebar #dashboard::before,
.sidebar .dropdown-toggle::before,
.sidebar #dashboard.selected::before,
.sidebar .dropdown-toggle.selected::before {
    content: '';
    /* Se anula el posicionamiento absoluto que traía este mismo pseudo-
       elemento en styles.css, donde servía de marca lateral del elemento
       activo. Ahora es el icono. */
    position: static;
    transform: none;
    border-radius: 0;
    display: block;
    flex: 0 0 auto;
    width: 1.2rem;
    height: 1.2rem;
    margin-right: 0.8rem;
    background: currentColor;
    opacity: 0.5;
    transition: opacity 0.18s ease;
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
    -webkit-mask-position: center;
            mask-position: center;
    -webkit-mask-size: contain;
            mask-size: contain;
}

.sidebar #dashboard:hover::before,
.sidebar .dropdown-toggle:hover::before,
.sidebar #dashboard.selected::before,
.sidebar .dropdown-toggle.selected::before {
    opacity: 1;
}

/* ----------------------------------------------------------------------------
   LOS ICONOS, DIBUJADOS A MEDIDA
   ----------------------------------------------------------------------------
   Los de antes eran de una libreria genérica: trazo de 2 sobre rejilla de 24 y
   la misma silueta que se ve en media web. Estos están dibujados para este
   menú, con trazo de 1,7 y las formas ajustadas al tamaño real al que se ven.

   Lo que de verdad cambia la sensación: CADA ICONO TIENE DOS VERSIONES. En
   reposo va el contorno; en el apartado donde estás, la versión rellena. Así
   el elemento activo no solo cambia de color, cambia de peso, que es el
   recurso que usa Apple en su barra de pestañas y lo que hace que un menú se
   lea de un vistazo.

   Van como máscara y no como imagen: el color lo pone `currentColor`, así que
   heredan el azul del elemento activo y el gris del resto sin duplicar nada,
   y funcionan igual en claro que en oscuro.
   ---------------------------------------------------------------------------- */
/* --- Dashboard — cuatro paneles --- */
.sidebar #dashboard::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='1.7'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Crect%20x='3.2'%20y='3.2'%20width='7.6'%20height='7.6'%20rx='2.1'/%3E%3Crect%20x='13.2'%20y='3.2'%20width='7.6'%20height='7.6'%20rx='2.1'/%3E%3Crect%20x='3.2'%20y='13.2'%20width='7.6'%20height='7.6'%20rx='2.1'/%3E%3Crect%20x='13.2'%20y='13.2'%20width='7.6'%20height='7.6'%20rx='2.1'/%3E%3C/svg%3E");
            mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='1.7'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Crect%20x='3.2'%20y='3.2'%20width='7.6'%20height='7.6'%20rx='2.1'/%3E%3Crect%20x='13.2'%20y='3.2'%20width='7.6'%20height='7.6'%20rx='2.1'/%3E%3Crect%20x='3.2'%20y='13.2'%20width='7.6'%20height='7.6'%20rx='2.1'/%3E%3Crect%20x='13.2'%20y='13.2'%20width='7.6'%20height='7.6'%20rx='2.1'/%3E%3C/svg%3E");
}
.sidebar #dashboard.selected::before,
.sidebar .dropdown:has(a.item.selected) > #dashboard::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='%23000'%20stroke='none'%3E%3Crect%20x='3.2'%20y='3.2'%20width='7.6'%20height='7.6'%20rx='2.1'/%3E%3Crect%20x='13.2'%20y='3.2'%20width='7.6'%20height='7.6'%20rx='2.1'/%3E%3Crect%20x='3.2'%20y='13.2'%20width='7.6'%20height='7.6'%20rx='2.1'/%3E%3Crect%20x='13.2'%20y='13.2'%20width='7.6'%20height='7.6'%20rx='2.1'/%3E%3C/svg%3E");
            mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='%23000'%20stroke='none'%3E%3Crect%20x='3.2'%20y='3.2'%20width='7.6'%20height='7.6'%20rx='2.1'/%3E%3Crect%20x='13.2'%20y='3.2'%20width='7.6'%20height='7.6'%20rx='2.1'/%3E%3Crect%20x='3.2'%20y='13.2'%20width='7.6'%20height='7.6'%20rx='2.1'/%3E%3Crect%20x='13.2'%20y='13.2'%20width='7.6'%20height='7.6'%20rx='2.1'/%3E%3C/svg%3E");
}

/* --- Admins — dos personas --- */
.sidebar #dropdownAdmin::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='1.7'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Ccircle%20cx='9.1'%20cy='8.6'%20r='3.4'/%3E%3Cpath%20d='M2.9%2020v-1a4.5%204.5%200%200%201%204.5-4.5h3.4a4.5%204.5%200%200%201%204.5%204.5v1'/%3E%3Cpath%20d='M16.5%205.6a3%203%200%200%201%200%205.9'/%3E%3Cpath%20d='M17.9%2014.7a4%204%200%200%201%203.2%203.9V20'/%3E%3C/svg%3E");
            mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='1.7'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Ccircle%20cx='9.1'%20cy='8.6'%20r='3.4'/%3E%3Cpath%20d='M2.9%2020v-1a4.5%204.5%200%200%201%204.5-4.5h3.4a4.5%204.5%200%200%201%204.5%204.5v1'/%3E%3Cpath%20d='M16.5%205.6a3%203%200%200%201%200%205.9'/%3E%3Cpath%20d='M17.9%2014.7a4%204%200%200%201%203.2%203.9V20'/%3E%3C/svg%3E");
}
.sidebar #dropdownAdmin.selected::before,
.sidebar .dropdown:has(a.item.selected) > #dropdownAdmin::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='%23000'%20stroke='none'%3E%3Ccircle%20cx='17.3'%20cy='8.5'%20r='2.7'/%3E%3Cpath%20d='M16.6%2014.6h1.4a4.1%204.1%200%200%201%204.1%204.1V20h-4.4v-1.3a5.7%205.7%200%200%200-1.1-3.4z'/%3E%3Ccircle%20cx='9.1'%20cy='8.6'%20r='3.4'/%3E%3Cpath%20d='M7.4%2014.5h3.4a4.5%204.5%200%200%201%204.5%204.5v1H2.9v-1a4.5%204.5%200%200%201%204.5-4.5z'/%3E%3C/svg%3E");
            mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='%23000'%20stroke='none'%3E%3Ccircle%20cx='17.3'%20cy='8.5'%20r='2.7'/%3E%3Cpath%20d='M16.6%2014.6h1.4a4.1%204.1%200%200%201%204.1%204.1V20h-4.4v-1.3a5.7%205.7%200%200%200-1.1-3.4z'/%3E%3Ccircle%20cx='9.1'%20cy='8.6'%20r='3.4'/%3E%3Cpath%20d='M7.4%2014.5h3.4a4.5%204.5%200%200%201%204.5%204.5v1H2.9v-1a4.5%204.5%200%200%201%204.5-4.5z'/%3E%3C/svg%3E");
}

/* --- Intercom — la placa de calle --- */
.sidebar #dropdownDispositivos::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='1.7'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Crect%20x='5.6'%20y='2.4'%20width='12.8'%20height='19.2'%20rx='2.8'/%3E%3Ccircle%20cx='12'%20cy='8'%20r='2.2'/%3E%3Cpath%20d='M9.3%2013.6h5.4'/%3E%3Cpath%20d='M9.3%2017.2h5.4'/%3E%3C/svg%3E");
            mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='1.7'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Crect%20x='5.6'%20y='2.4'%20width='12.8'%20height='19.2'%20rx='2.8'/%3E%3Ccircle%20cx='12'%20cy='8'%20r='2.2'/%3E%3Cpath%20d='M9.3%2013.6h5.4'/%3E%3Cpath%20d='M9.3%2017.2h5.4'/%3E%3C/svg%3E");
}
.sidebar #dropdownDispositivos.selected::before,
.sidebar .dropdown:has(a.item.selected) > #dropdownDispositivos::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='%23000'%20stroke='none'%3E%3Cpath%20fill-rule='evenodd'%20d='M8.4%202.4%20H15.6%20A2.8%202.8%200%200%201%2018.4%205.2%20V18.8%20A2.8%202.8%200%200%201%2015.6%2021.6%20H8.4%20A2.8%202.8%200%200%201%205.6%2018.8%20V5.2%20A2.8%202.8%200%200%201%208.4%202.4%20Z%20M12%205.8%20A2.2%202.2%200%201%200%2012%2010.2%20A2.2%202.2%200%201%200%2012%205.8%20Z%20M9.3%2012.7%20H14.7%20A0.9%200.9%200%200%201%2014.7%2014.5%20H9.3%20A0.9%200.9%200%200%201%209.3%2012.7%20Z%20M9.3%2016.3%20H14.7%20A0.9%200.9%200%200%201%2014.7%2018.1%20H9.3%20A0.9%200.9%200%200%201%209.3%2016.3%20Z'/%3E%3C/svg%3E");
            mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='%23000'%20stroke='none'%3E%3Cpath%20fill-rule='evenodd'%20d='M8.4%202.4%20H15.6%20A2.8%202.8%200%200%201%2018.4%205.2%20V18.8%20A2.8%202.8%200%200%201%2015.6%2021.6%20H8.4%20A2.8%202.8%200%200%201%205.6%2018.8%20V5.2%20A2.8%202.8%200%200%201%208.4%202.4%20Z%20M12%205.8%20A2.2%202.2%200%201%200%2012%2010.2%20A2.2%202.2%200%201%200%2012%205.8%20Z%20M9.3%2012.7%20H14.7%20A0.9%200.9%200%200%201%2014.7%2014.5%20H9.3%20A0.9%200.9%200%200%201%209.3%2012.7%20Z%20M9.3%2016.3%20H14.7%20A0.9%200.9%200%200%201%2014.7%2018.1%20H9.3%20A0.9%200.9%200%200%201%209.3%2016.3%20Z'/%3E%3C/svg%3E");
}

/* --- Usuarios — una persona --- */
.sidebar #dropdownUsuarios::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='1.7'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Ccircle%20cx='12'%20cy='8'%20r='3.6'/%3E%3Cpath%20d='M4.9%2020v-1.1a5.2%205.2%200%200%201%205.2-5.2h3.8a5.2%205.2%200%200%201%205.2%205.2V20'/%3E%3C/svg%3E");
            mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='1.7'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Ccircle%20cx='12'%20cy='8'%20r='3.6'/%3E%3Cpath%20d='M4.9%2020v-1.1a5.2%205.2%200%200%201%205.2-5.2h3.8a5.2%205.2%200%200%201%205.2%205.2V20'/%3E%3C/svg%3E");
}
.sidebar #dropdownUsuarios.selected::before,
.sidebar .dropdown:has(a.item.selected) > #dropdownUsuarios::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='%23000'%20stroke='none'%3E%3Ccircle%20cx='12'%20cy='8'%20r='3.6'/%3E%3Cpath%20d='M4.9%2020v-1.1a5.2%205.2%200%200%201%205.2-5.2h3.8a5.2%205.2%200%200%201%205.2%205.2V20z'/%3E%3C/svg%3E");
            mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='%23000'%20stroke='none'%3E%3Ccircle%20cx='12'%20cy='8'%20r='3.6'/%3E%3Cpath%20d='M4.9%2020v-1.1a5.2%205.2%200%200%201%205.2-5.2h3.8a5.2%205.2%200%200%201%205.2%205.2V20z'/%3E%3C/svg%3E");
}

/* Con el menú plegado el icono queda centrado y sin margen. */
.sidebar.collapsed #dashboard::before,
.sidebar.collapsed .dropdown-toggle::before {
    margin-right: 0;
}


/* ============================================================================
   16. CORRECCIONES — Fase 2.3
   ============================================================================ */

/* ----------------------------------------------------------------------------
   16.1  LA CEBRA, AHORA SÍ
   ----------------------------------------------------------------------------
   En la ronda anterior quité la cebra por CSS y seguía apareciendo. El motivo:
   no venía de la hoja de estilos, sino del JavaScript, que pinta cada fila una
   a una con `fila.style.backgroundColor = "#f4f4f4"` (javascripts.js, script.js
   y los propios listados). Un estilo en línea gana a cualquier regla normal de
   una hoja externa.

   La única forma de ganarle SIN tocar el JavaScript es `!important`, que sí
   tiene prioridad sobre un estilo en línea sin `!important`. Así el código
   funcional sigue exactamente igual —sigue pintando sus colores— pero mandan
   estos de aquí. Comprobado antes de escribirlo: ese JavaScript solo asigna
   #f4f4f4 y #ffffff, no hay ninguna fila con color propio por significado
   (errores, avisos...) que se pueda estar pisando.
   ---------------------------------------------------------------------------- */
/* (Sustituido por el bloque 17.1: la cebra vuelve, pero aclarada.) */


/* ----------------------------------------------------------------------------
   16.2  CABECERA DE TABLA EN BLANCO
   ----------------------------------------------------------------------------
   El fondo gris convertía la cabecera en una banda pesada. Vuelve a blanco: lo
   que la separa de los datos ahora es la tipografía de las etiquetas, los
   buscadores con su filete, y una línea de cierre algo más marcada. Misma
   diferenciación, cero peso visual.
   ---------------------------------------------------------------------------- */
thead th {
    background: var(--abx-blanco);
}

thead tr:last-child th {
    box-shadow: inset 0 -1px 0 rgba(13, 27, 42, 0.14);
}


/* ----------------------------------------------------------------------------
   16.3  TEXTO DE LAS TABLAS EN NEGRO
   ----------------------------------------------------------------------------
   En listados como Mis intercoms cada celda es un enlace, así que ponerlos en
   azul teñía la tabla entera y convertía el color en ruido. Van en negro, como
   el resto del texto, y solo se subrayan al pasar el ratón: sigue viéndose que
   se puede pulsar, sin pintar la pantalla de azul.
   ---------------------------------------------------------------------------- */
table a,
table a:visited {
    color: var(--abx-texto) !important;
    text-decoration: none !important;
}
table a:hover {
    color: var(--abx-texto) !important;
    text-decoration: underline !important;
    text-decoration-color: rgba(13, 27, 42, 0.45) !important;
    text-underline-offset: 3px;
}

* td {
    color: var(--abx-texto);
}


/* ----------------------------------------------------------------------------
   16.4  EL ICONO DEL BOTÓN DE USUARIO
   ----------------------------------------------------------------------------
   El PNG `usuario.png` es de tonos claros: antes se veía porque un filtro CSS
   lo teñía de gris oscuro, y al quitar ese filtro se quedó casi en blanco
   sobre un círculo claro. En vez de recuperar el filtro —que es una operación
   cara y depende del color del archivo— se dibuja la silueta con el mismo
   sistema que los iconos del lateral: trazo limpio y color controlado.
   ---------------------------------------------------------------------------- */
.imagen-boton {
    /* El giro existía solo para contrarrestar el que se aplica a TODAS las
       imágenes del botón. Al no usar ya imagen, sobra. */
    transform: none;
    align-items: center;
}
.imagen-boton img {
    display: none !important;
}
.imagen-boton::before {
    content: '';
    width: 1.05rem;
    height: 1.05rem;
    background: #6e6e73;
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
    -webkit-mask-position: center;
            mask-position: center;
    -webkit-mask-size: contain;
            mask-size: contain;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2'/%3E%3Ccircle cx='12' cy='7' r='4'/%3E%3C/svg%3E");
            mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2'/%3E%3Ccircle cx='12' cy='7' r='4'/%3E%3C/svg%3E");
}


/* ----------------------------------------------------------------------------
   16.5  FLUIDEZ
   ----------------------------------------------------------------------------
   Movimiento corto y con intención. Nada que haga esperar: todo por debajo de
   medio segundo, y nada que se repita mientras se trabaja.

   Una decisión deliberada: NO se anima la aparición de las filas una a una.
   Las filas las pinta el JavaScript y se ocultan y muestran en cada pulsación
   del buscador, así que una animación por fila parpadearía con cada letra que
   se teclea. Se anima el bloque, que se dibuja una sola vez.
   ---------------------------------------------------------------------------- */

/* Aquí había `scroll-behavior: smooth`. Se ha quitado: convierte en animado
   CUALQUIER salto de scroll, incluidos los que hace el propio JavaScript al
   filtrar o al saltar a una fila. En una tabla larga eso no se siente suave,
   se siente pesado — el scroll deja de responder al instante. */

/* Los elementos del listado entran en cascada, como las tarjetas de la
   bienvenida: buscador, resumen y tabla, uno detrás de otro. */
/* (La cascada se activa desde el bloque 22, cuando el spinner se va.) */
.contenedores-mis-usuarios > *:nth-child(1),
.contenedores-mis-paneles > *:nth-child(1),
.contenedores-mis-admins > *:nth-child(1),
.contenedores-mis-avisos > *:nth-child(1),
.contenedores-mis-invitados > *:nth-child(1),
.contenedores-movimientos > *:nth-child(1) { animation-delay: 0.02s; }

.contenedores-mis-usuarios > *:nth-child(2),
.contenedores-mis-paneles > *:nth-child(2),
.contenedores-mis-admins > *:nth-child(2),
.contenedores-mis-avisos > *:nth-child(2),
.contenedores-mis-invitados > *:nth-child(2),
.contenedores-movimientos > *:nth-child(2) { animation-delay: 0.07s; }

.contenedores-mis-usuarios > *:nth-child(n+3),
.contenedores-mis-paneles > *:nth-child(n+3),
.contenedores-mis-admins > *:nth-child(n+3),
.contenedores-mis-avisos > *:nth-child(n+3),
.contenedores-mis-invitados > *:nth-child(n+3),
.contenedores-movimientos > *:nth-child(n+3) { animation-delay: 0.12s; }

/* El menú de usuario se despliega en lugar de aparecer de golpe. */
.boton-header.bordear ul {
    animation: abxDesplegar 0.22s var(--abx-curva) both;
    transform-origin: top center;
}
@keyframes abxDesplegar {
    from { opacity: 0; transform: translateY(-6px) scaleY(0.97); }
    to   { opacity: 1; transform: translateY(0) scaleY(1); }
}

/* El icono del menú lateral crece un punto al pasar el ratón: respuesta
   inmediata sin mover nada de sitio. */
.sidebar #dashboard::before,
.sidebar .dropdown-toggle::before {
    transition: opacity 0.18s ease, transform 0.18s var(--abx-curva-mue);
}
.sidebar #dashboard:hover::before,
.sidebar .dropdown-toggle:hover::before {
    transform: scale(1.08);
}

/* Casillas de selección: color de marca y un pequeño acuse al marcarlas. */
input[type="checkbox"],
input[type="radio"] {
    accent-color: var(--abx-azul);
    cursor: pointer;
    transition: transform 0.14s var(--abx-curva-mue);
}
input[type="checkbox"]:active,
input[type="radio"]:active {
    transform: scale(0.88);
}

/* Las etiquetas de estado (Online, Sin uso...) acusan el paso del ratón en
   las que se pueden pulsar para filtrar. */
.estado-pill,
.estado-pill-filtro {
    transition: transform 0.14s var(--abx-curva-mue), filter 0.16s ease;
}
.estado-pill:hover {
    transform: translateY(-1px);
    filter: brightness(1.06);
}

/* La tarjeta de resumen se eleva levemente: indica que está viva, no que sea
   pulsable (no se mueve de sitio ni cambia de color). */
.stats-box {
    transition: box-shadow 0.22s ease;
}
.stats-box:hover {
    box-shadow: var(--abx-sombra-2);
}

/* Enlaces de la tabla: el subrayado aparece dibujándose, no de golpe. */
table a {
    transition: text-decoration-color 0.16s ease, color 0.16s ease;
}

/* Quien tenga activado "reducir movimiento" no ve nada de lo anterior. */
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    .contenedores-mis-usuarios > *,
    .contenedores-mis-paneles > *,
    .contenedores-mis-admins > *,
    .contenedores-mis-avisos > *,
    .contenedores-mis-invitados > *,
    .contenedores-movimientos > *,
    .boton-header.bordear ul {
        animation: none !important;
    }
}


/* ============================================================================
   17. CORRECCIONES — Fase 2.4
   ============================================================================ */

/* ----------------------------------------------------------------------------
   17.1  LA CEBRA VUELVE, PERO ACLARADA
   ----------------------------------------------------------------------------
   Quitarla fue resolver por amputación, y además hacía falta: con 90 admins y
   seis columnas, la franja ayuda a no cambiar de fila al leer a lo ancho.

   El problema real nunca fue la cebra, era que el hover usaba un gris parecido
   al suyo. Así que la cebra se queda y el hover pasa a ser AZUL: ya no hay
   ningún gris con el que confundirlo.

   Cómo se aclara sin tocar el JavaScript: el gris lo pinta el JS en cada fila
   (`fila.style.backgroundColor`), y encima el JS lo RECALCULA al filtrar, que
   es justo lo que una regla `nth-child` no sabe hacer (seguiría contando las
   filas ocultas y el rayado saldría descuadrado al buscar). Por eso no se
   pisa el color de la fila: se pone un blanco translúcido en las CELDAS, que
   van por encima. El #f4f4f4 se suaviza hasta un gris apenas perceptible, el
   blanco sigue blanco, y el patrón lo sigue decidiendo el JS — también
   después de filtrar.
   ---------------------------------------------------------------------------- */
tbody td {
    background-color: rgba(255, 255, 255, 0.62);
}

/* El hover se pinta también en las celdas, con un color sólido: así una fila
   señalada se ve EXACTAMENTE igual esté sobre franja gris o sobre blanco. */
tbody tr:hover td {
    background-color: #DAE8F4 !important;
}


/* ----------------------------------------------------------------------------
   17.2  CABECERA: FONDO BLANCO, BUSCADORES GRISES
   ----------------------------------------------------------------------------
   He probado las dos combinaciones y me equivoqué en las dos: con la cabecera
   gris pesaba como una banda, y con cabecera y buscadores los dos en blanco no
   se distinguía dónde acaba una y empiezan los otros.

   La que funciona es la contraria: cabecera blanca —sin banda— y buscadores
   con relleno gris, como los campos de búsqueda del sistema. El contraste lo
   ponen los campos, que es donde tiene sentido, no un bloque de color.
   ---------------------------------------------------------------------------- */
.extension thead th input:not([type="checkbox"]),
.extension thead th select {
    background-color: #EFF1F5 !important;
    border: 1px solid transparent !important;
    box-shadow: none !important;
}

.extension thead th input:not([type="checkbox"]):hover,
.extension thead th select:hover {
    background-color: #E7E9EF !important;
    border-color: transparent !important;
}

/* Al escribir, el campo se vuelve blanco: marca sin lugar a dudas cuál de los
   filtros está activo. */
.extension thead th input:not([type="checkbox"]):focus,
.extension thead th select:focus {
    background-color: var(--abx-blanco) !important;
    border-color: rgba(16, 86, 128, 0.55) !important;
    box-shadow: 0 0 0 3px rgba(16, 86, 128, 0.13) !important;
}

/* Un poco más de aire en la cabecera y una línea de cierre algo más presente:
   con los campos ya en gris, la banda no hace falta. */
thead tr:first-child th {
    padding-top: 1.15rem !important;
    padding-bottom: 0.6rem !important;
}
thead tr:nth-child(2) th {
    padding-bottom: 1.15rem !important;
}
thead tr:last-child th {
    box-shadow: inset 0 -1px 0 rgba(13, 27, 42, 0.16);
}


/* ----------------------------------------------------------------------------
   17.3  EL BUSCADOR GENERAL AL PASAR EL RATÓN
   ----------------------------------------------------------------------------
   Se ponía gris y perdía la lupa. Dos causas, las dos mías: la regla general
   de campos usaba el atajo `background` (que borra el background-image, o sea
   la lupa) y pintaba el gris de los campos de formulario. Arriba ya se cambió
   el atajo por `background-color`; aquí se fija el comportamiento correcto al
   pasar el ratón: sigue blanco y solo se eleva un punto la sombra.
   ---------------------------------------------------------------------------- */
.extension input.input-buscar:hover {
    background-color: var(--abx-blanco) !important;
    border-color: transparent !important;
    box-shadow: var(--abx-sombra-2) !important;
}
.extension input.input-buscar:focus {
    background-color: var(--abx-blanco) !important;
    border-color: rgba(16, 86, 128, 0.5) !important;
    box-shadow: 0 0 0 3px rgba(16, 86, 128, 0.13) !important;
}


/* ============================================================================
   18. FORMULARIOS — ESTRUCTURA
   ----------------------------------------------------------------------------
   Los campos ya estaban unificados (bloque 6). Lo que faltaba era la
   ESTRUCTURA: en fichas largas como Nuevo admin o Configuración, el título de
   cada apartado flotaba sobre una lista de campos sin nada que marcara dónde
   empieza y dónde acaba cada bloque.

   Solo se tocan tipografía, filetes y separaciones. Ni un ancho, ni una
   altura, ni una columna: el reparto de los formularios lo siguen mandando
   las reglas existentes.
   ============================================================================ */

/* Título de apartado con filete: da pie a la lista de campos y agrupa de un
   vistazo lo que va junto. */
.contenedores h5 {
    margin-bottom: 1.5rem !important;
    padding-bottom: 0.85rem;
    border-bottom: 1px solid var(--abx-linea-suave);
    font-size: 1.2rem !important;
}

/* Etiqueta pegada a su campo: antes había la misma distancia por arriba que
   por abajo y costaba ver a qué campo pertenecía cada una. */
.extension label:not([hidden]) {
    display: block;
}
.extension label {
    margin-bottom: 0.1rem;
    font-weight: 500;
    color: #5b6472;
}

/* Las áreas de texto crecen solo en vertical: arrastrarlas a lo ancho rompía
   la columna del formulario. */
.extension textarea {
    resize: vertical;
    min-height: 5rem;
    line-height: 1.5;
    padding: 0.6rem 0.7rem !important;
}

/* Campos de solo lectura: se distinguen de los editables sin parecer rotos. */
.extension input[readonly] {
    background-color: rgba(13, 27, 42, 0.04) !important;
    color: var(--abx-texto-2) !important;
    cursor: default;
}

/* Botón de "Eliminar sub Admin" y similares: la cursiva los hacía parecer una
   nota al pie en vez de una acción. */
.eliminar-subadmin-btn {
    font-style: normal !important;
    font-weight: 600 !important;
    font-size: 0.82rem !important;
    border-radius: 6px;
    transition: opacity 0.16s ease;
}
.eliminar-subadmin-btn:hover {
    opacity: 0.72;
    text-decoration: underline !important;
    text-underline-offset: 2px;
}


/* ============================================================================
   19. MISMA CABECERA Y MISMA CEBRA EN TODAS LAS TABLAS
   ----------------------------------------------------------------------------
   Hasta aquí el acabado de cabecera dependía de que la tabla tuviera la
   estructura de Mis admins: dos filas en el <thead> (títulos + buscadores).
   Las que no la tienen —las de una sola fila, o las que llevan estilos
   propios dentro del HTML de su pantalla, como las de Modelos y versiones—
   se quedaban fuera.

   Este bloque unifica las tres cosas en CUALQUIER tabla del panel:
     · fondo blanco de cabecera y línea de cierre,
     · buscadores con relleno gris,
     · cebra del mismo tono.

   Lleva `!important` en lo justo, y por un motivo concreto: las pantallas con
   <style> propio usan selectores con ID (`#dvTablas .dv-tabla-versiones ...`),
   que pesan más que cualquier regla de esta hoja por muy específica que sea.
   Sin `!important` esas tablas seguirían yendo por libre.
   ============================================================================ */

/* --- Cabecera ------------------------------------------------------------- */
.extension thead th {
    background-color: var(--abx-blanco) !important;
    color: #6b7280 !important;
    font-size: 0.8rem !important;
    font-weight: 600 !important;
    letter-spacing: 0.15px;
}

.extension thead th p {
    color: #6b7280 !important;
    font-size: 0.8rem !important;
    font-weight: 600 !important;
}

/* Línea de cierre: separa la cabecera de los datos, tenga una fila o dos. */
.extension thead tr:last-child th {
    box-shadow: inset 0 -1px 0 rgba(13, 27, 42, 0.16) !important;
}

/* Cabecera de UNA sola fila (sin buscadores): necesita por abajo el mismo
   aire que en las de dos filas aporta la fila de filtros. El truco es
   `:first-child:last-child`, que solo se cumple cuando esa fila es además la
   única del <thead>. */
.extension thead tr:first-child:last-child th {
    padding-bottom: 1.15rem !important;
}

/* --- Cebra ----------------------------------------------------------------
   Aquí estaba el fallo que dejaba sin rayado a media web: en una ronda
   anterior puse las filas pares e impares en blanco para quitar la cebra, y
   esa regla seguía viva. Anulaba el rayado que la hoja original da a TODAS
   las tablas, así que solo se veían franjas en las tablas que además las
   pinta el JavaScript (Mis admins, Mis intercoms...). Las demás salían
   completamente blancas.

   Se restituye el rayado para todas. Y SIN `!important` a propósito: así un
   color puesto en línea por el JavaScript sigue mandando sobre estas reglas,
   que es lo que permite que el rayado se recalcule bien al filtrar en las
   tablas que lo hacen. */
.extension tbody tr:nth-child(odd) {
    background-color: #F1F2F5;
}
.extension tbody tr:nth-child(even) {
    background-color: var(--abx-blanco);
}

/* El blanco translúcido de las celdas aclara por igual el gris que pinta el
   JavaScript en unas tablas y el que pinta la hoja de estilos en otras, sin
   imponer un patrón propio: el rayado lo sigue decidiendo quien lo decidía
   antes, también al filtrar. */
/* Sin blanco por encima: la franja se queda en su gris completo. Aclararla
   la dejaba casi invisible, que era justo lo contrario de para qué está. */
.extension tbody td {
    background-color: transparent;
}

.extension tbody tr:hover td {
    background-color: #DAE8F4 !important;
}

/* Tablas que habían desactivado la cebra en su propia pantalla: vuelven a
   llevarla, del mismo tono que todas las demás. */
.extension .dv-tabla-versiones tbody tr:nth-child(odd) {
    background-color: #F1F2F5 !important;
}
.extension .dv-tabla-versiones tbody tr:nth-child(even) {
    background-color: var(--abx-blanco) !important;
}


/* ============================================================================
   20. CORRECCIONES — Fase 2.5
   ============================================================================ */

/* ----------------------------------------------------------------------------
   20.1  UN FALLO MÍO: LAS ETIQUETAS QUE DEBÍAN ESTAR OCULTAS
   ----------------------------------------------------------------------------
   En Editar panel se veían a la vez "Botón de llamada:", "Código de llamada*:"
   y "Nº columnas*:", cuando las dos últimas solo corresponden a otras opciones
   del desplegable.

   La causa está en la capa: esas etiquetas se ocultan con el atributo `hidden`
   del HTML, que funciona porque el navegador trae de serie una regla
   `[hidden] { display: none }`. Al escribir yo `.extension label { display:
   block }` para separar etiqueta y campo, esa regla pasó por encima de la del
   navegador —pesa más— y las dejó visibles todas.

   La corrección va más allá del caso concreto: se restituye `[hidden]` con
   `!important` para TODO el panel. Así ninguna regla de esta capa, ni las de
   hoy ni las que vengan, puede volver a destapar algo que el HTML o el
   JavaScript hayan mandado ocultar.
   ---------------------------------------------------------------------------- */
.extension label:not([hidden]) {
    display: block;
}


/* ----------------------------------------------------------------------------
   20.2  EL FILTRO DE ESTADO Y LOS DEMÁS BUSCADORES, IGUALES
   ----------------------------------------------------------------------------
   El filtro "Todos ▾" de Mis intercoms no es un <select>: es un botón con su
   propio desplegable, y por eso se quedaba fuera de las reglas de la cabecera.
   Tenía otro alto, otro radio y otro gris.

   Se igualan los tres, y el gris que se adopta para todos es el SUYO
   (#F2F2F2), no el que yo había puesto: contrasta mejor sobre la cabecera
   blanca, que es justo lo que se le pide a un campo de búsqueda.
   ---------------------------------------------------------------------------- */
.extension thead th input:not([type="checkbox"]),
.extension thead th select,
.extension .filtro-estado-btn {
    box-sizing: border-box;
    height: 2rem !important;
    padding-top: 0 !important;
    padding-bottom: 0 !important;
    border-radius: 8px !important;
    border: 1px solid transparent !important;
    background-color: #F2F2F2 !important;
    color: var(--abx-texto) !important;
    font-size: 0.82rem !important;
    font-style: normal !important;
    font-weight: 400;
    line-height: normal;
    box-shadow: none !important;
    transition: background-color 0.16s ease, border-color 0.16s ease,
                box-shadow 0.16s ease !important;
}

.extension thead th input:not([type="checkbox"]):hover,
.extension thead th select:hover,
.extension .filtro-estado-btn:hover {
    background-color: #E9E9EA !important;
    border-color: transparent !important;
}

.extension thead th input:not([type="checkbox"]):focus,
.extension thead th select:focus,
.extension .filtro-estado-btn:focus-visible {
    background-color: var(--abx-blanco) !important;
    border-color: rgba(16, 86, 128, 0.55) !important;
    box-shadow: 0 0 0 3px rgba(16, 86, 128, 0.13) !important;
    outline: none !important;
}

/* El botón del filtro lleva su flecha en el propio texto ("Todos ▾"), así que
   solo necesita el sangrado lateral de los demás campos. */
.extension .filtro-estado-btn {
    padding-left: 0.6rem !important;
    padding-right: 0.6rem !important;
    width: 100%;
}

/* Su desplegable, como tarjeta flotante y no como recuadro suelto. */
.extension .filtro-estado-dropdown {
    border-radius: var(--abx-r-s);
    border: 1px solid var(--abx-linea);
    box-shadow: 0 16px 34px -12px rgba(13, 27, 42, 0.28);
    padding: 0.35rem;
    background: var(--abx-blanco);
}
.extension .filtro-estado-dropdown label {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.4rem 0.5rem;
    border-radius: 8px;
    cursor: pointer;
    margin: 0;
    transition: background 0.14s ease;
}
.extension .filtro-estado-dropdown label:hover {
    background: rgba(13, 27, 42, 0.05);
}


/* ----------------------------------------------------------------------------
   20.3  TODO LO PULSABLE, CON CURSOR DE MANO
   ----------------------------------------------------------------------------
   "Abrir puerta" y "Reiniciar dispositivo" no cambiaban el cursor al pasar por
   encima: nada decía que fueran botones. No es un detalle estético — es la
   señal por la que se sabe dónde se puede pulsar antes de intentarlo.

   Se aplica a todos los botones del panel de una vez, en lugar de ir
   añadiéndolo clase a clase según vayan apareciendo.
   ---------------------------------------------------------------------------- */
.extension button,
.extension [role="button"],
.extension input[type="submit"],
.extension input[type="button"],
.extension label[for],
.extension summary,
.sidebar button,
.boton-header button,
.boton-modal {
    cursor: pointer;
}

/* Excepto lo que está deshabilitado, que debe decir justo lo contrario. */
.extension button:disabled,
.extension input[type="submit"]:disabled,
.extension input[type="button"]:disabled {
    cursor: not-allowed;
}

/* Los botones de actuación remota acusan la pulsación como el resto. */
.abrir-puerta,
.reiniciar-dispositivo,
.hacer-videollamada {
    transition: filter 0.16s ease, transform 0.12s var(--abx-curva-mue),
                box-shadow 0.18s ease;
}
.abrir-puerta:hover,
.reiniciar-dispositivo:hover,
.hacer-videollamada:hover {
    filter: brightness(1.06);
    transform: translateY(-1px);
    box-shadow: 0 6px 16px rgba(13, 27, 42, 0.16);
}
.abrir-puerta:active,
.reiniciar-dispositivo:active,
.hacer-videollamada:active {
    transform: translateY(0) scale(0.99);
}


/* ============================================================================
   21. CORRECCIONES — Fase 2.6
   ============================================================================ */

/* ----------------------------------------------------------------------------
   21.1  POR QUÉ LOS FILTROS "TODOS" Y "PANELES" SEGUÍAN DESENTONANDO
   ----------------------------------------------------------------------------
   Dos motivos, y ninguno era el color:

   a) No son campos. Son <button>, y mi regla de la cabecera cubría `input` y
      `select` pero no `button`. El de Mis usuarios (#muBtnPaneles) además
      tiene estilos propios con selector de ID dentro de su pantalla, que pesan
      más que cualquier regla normal de esta hoja.

   b) La flecha iba DENTRO del texto ("Todos ▾"), pegada a la palabra y a media
      altura, mientras que en un <select> el navegador la dibuja pegada al
      borde derecho. Por muy igual que fuera el gris, la diferencia saltaba a
      la vista.

   Lo primero se arregla aquí. Lo segundo no se puede arreglar solo con CSS —
   ese carácter es texto que escribe el JavaScript—, así que he quitado el " ▾"
   de las cuatro cadenas de mis-paneles.php y las dos de mis-usuarios.php, y la
   flecha la dibuja ahora el CSS en el borde derecho. Es lo único que he tocado
   en ese JavaScript: el texto de una etiqueta, ninguna condición ni filtro.
   ---------------------------------------------------------------------------- */
.extension thead th button {
    box-sizing: border-box;
    width: 100%;
    height: 2rem !important;
    padding: 0 1.8rem 0 0.6rem !important;
    border-radius: 8px !important;
    border: 1px solid transparent !important;
    background-color: #F2F2F2 !important;
    color: var(--abx-texto) !important;
    font-size: 0.82rem !important;
    font-weight: 400 !important;
    font-style: normal !important;
    text-align: left !important;
    line-height: normal;
    box-shadow: none !important;
    cursor: pointer;
    /* Flecha en el borde derecho, igual que la de un desplegable nativo. */
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236e6e73' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") !important;
    background-repeat: no-repeat !important;
    background-position: right 0.55rem center !important;
    background-size: 0.7rem 0.7rem !important;
    transition: background-color 0.16s ease, border-color 0.16s ease,
                box-shadow 0.16s ease !important;
}

.extension thead th button:hover {
    background-color: #E9E9EA !important;
}

.extension thead th button:focus-visible {
    background-color: var(--abx-blanco) !important;
    border-color: rgba(16, 86, 128, 0.55) !important;
    box-shadow: 0 0 0 3px rgba(16, 86, 128, 0.13) !important;
    outline: none !important;
}

/* Con filtros activos, el botón se tiñe del azul de marca: se ve que la tabla
   no está mostrando todo sin tener que abrirlo. */
.extension thead th button.mu-con-seleccion,
.extension thead th button.filtro-activo {
    background-color: rgba(16, 86, 128, 0.10) !important;
    color: var(--abx-azul) !important;
    font-weight: 600 !important;
}


/* ----------------------------------------------------------------------------
   21.2  EL DESPLEGABLE DEL FILTRO, AL ABRIRSE
   ---------------------------------------------------------------------------- */
.extension .filtro-estado-dropdown {
    min-width: 100%;
    margin-top: 0.3rem;
    padding: 0.4rem;
    border-radius: var(--abx-r-s);
    border: 1px solid var(--abx-linea);
    background: var(--abx-blanco);
    box-shadow: 0 18px 38px -14px rgba(13, 27, 42, 0.32);
}

/* Se despliega, no aparece de golpe. */
.extension .filtro-estado-dropdown.open {
    animation: abxDesplegar 0.18s var(--abx-curva) both;
    transform-origin: top center;
}

.extension .filtro-estado-dropdown label {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    margin: 0;
    padding: 0.42rem 0.5rem;
    border-radius: 8px;
    cursor: pointer;
    transition: background 0.14s ease;
}
.extension .filtro-estado-dropdown label:hover {
    background: rgba(13, 27, 42, 0.05);
}

/* Las casillas, al tamaño de la etiqueta que acompañan. */
.extension .filtro-estado-dropdown input[type="checkbox"] {
    width: 0.95rem;
    height: 0.95rem;
    margin: 0;
    flex: 0 0 auto;
}

/* Dentro del desplegable, las etiquetas de estado son referencia, no aviso:
   van al tamaño del texto del menú. */
.extension .filtro-estado-dropdown .estado-pill-filtro {
    font-size: 0.78em;
    padding: 3px 9px;
}


/* ============================================================================
   22. AJUSTES — Fase 2.7
   ============================================================================ */

/* ----------------------------------------------------------------------------
   22.1  TÍTULOS DE COLUMNA MÁS PRESENTES
   ----------------------------------------------------------------------------
   Los dejé demasiado apagados: en una tabla de seis columnas hay que poder
   saber en qué columna estás mirando sin buscarlo. Suben de gris medio a gris
   oscuro y ganan medio punto de tamaño. Siguen por debajo del dato, que es lo
   que tiene que pesar.
   ---------------------------------------------------------------------------- */
.extension thead th,
.extension thead th p,
.extension thead tr:first-child th,
.extension thead tr:first-child th p {
    color: #3f4650 !important;
    font-size: 0.86rem !important;
    font-weight: 650 !important;
    letter-spacing: -0.05px;
}


/* ----------------------------------------------------------------------------
   22.2  EL DESPLEGABLE DEL FILTRO DE ESTADO
   ----------------------------------------------------------------------------
   Se abría como un panel suelto: ancho de más, mucho aire entre opciones y
   casillas grandes que pesaban más que las propias etiquetas de estado. Ahora
   es un menú compacto, anclado al ancho del botón, con las opciones juntas y
   la casilla al tamaño del texto.
   ---------------------------------------------------------------------------- */
.extension .filtro-estado-dropdown {
    /* `height: 160px` fijo en styles.css dejaba un hueco blanco por debajo de
       la última opción. El menú se ajusta a lo que contiene. */
    height: auto;
    width: max-content;
    min-width: 100%;
    left: auto;
    right: 0;
    margin-top: 0.35rem;
    padding: 0.3rem;
    border-radius: 12px;
    border: 1px solid var(--abx-linea);
    background: var(--abx-blanco);
    box-shadow: 0 12px 28px -10px rgba(13, 27, 42, 0.28),
                0 2px 6px rgba(13, 27, 42, 0.06);
}

.extension .filtro-estado-dropdown label {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    margin: 0;
    padding: 0.3rem 0.45rem;
    border-radius: 7px;
    cursor: pointer;
    white-space: nowrap;
    transition: background 0.14s ease;
}
.extension .filtro-estado-dropdown label:hover {
    background: rgba(13, 27, 42, 0.05);
}

.extension .filtro-estado-dropdown input[type="checkbox"] {
    width: 0.85rem;
    height: 0.85rem;
    margin: 0;
    flex: 0 0 auto;
}

.extension .filtro-estado-dropdown .estado-pill-filtro {
    font-size: 0.72rem;
    padding: 2px 8px;
    font-weight: 600;
}


/* ----------------------------------------------------------------------------
   22.3  LA ANIMACIÓN DE ENTRADA, CUANDO TOCA
   ----------------------------------------------------------------------------
   El problema que describes era real y tenía una causa concreta: la animación
   arrancaba al cargar el HTML, pero en las pantallas con datos el spinner tapa
   toda la zona de contenido durante ese rato. Cuando el spinner se iba, la
   animación ya había terminado por debajo y el contenido aparecía de golpe.

   Ahora la cascada no arranca hasta que el spinner desaparece: es un pequeño
   script en panel.php que vigila el spinner y, cuando se oculta, marca el
   <body>. Si el script no llegara a ejecutarse, simplemente no hay animación
   — nunca se queda nada invisible.
   ---------------------------------------------------------------------------- */
/* Aquí se animaba también el CONTENEDOR de la vista, además de sus bloques.
   Dos opacidades anidadas moviéndose a la vez es una mala idea: el navegador
   promociona el padre a su propia capa, dibuja los hijos dentro, y cuando la
   animación del padre termina —antes que la de los hijos— destruye esa capa y
   lo vuelve a componer todo. Ese recompuesto a media animación es el parpadeo.

   Ahora solo se animan los bloques. El contenedor se limita a estar oculto o
   visible, sin transición propia. */

/* Aquí se enumeraban SEIS clases de contenedor a mano, y el panel tiene once:
   por eso "Nuevo admin", "Editar usuario" o "Configuraciones" no animaban.
   Lo sustituye la sección 54, que apunta a la estructura en vez de a los
   nombres y cubre cualquier vista, incluidas las que se hagan mañana. */


/* ----------------------------------------------------------------------------
   22.4  "ELIMINAR" EN GRIS HASTA QUE HAYA ALGO QUE ELIMINAR
   ----------------------------------------------------------------------------
   En Mis admins funcionaba porque ese botón nace con el atributo `disabled` y
   su JavaScript lo quita al marcar una fila. En el resto de tablas el botón no
   nace deshabilitado, así que no se puede copiar el mismo truco sin tocar su
   JavaScript — y tocarlo es arriesgar el borrado.

   Se consigue el mismo efecto sin tocar nada: `:has()` permite preguntarle al
   contenedor si hay ALGUNA casilla marcada en su tabla, y teñir el botón en
   consecuencia. Rojo solo cuando hay algo seleccionado; gris el resto del
   tiempo. El botón sigue siendo igual de funcional en todo momento.
   ---------------------------------------------------------------------------- */
.extension .eliminar {
    background: rgba(13, 27, 42, 0.07) !important;
    color: #8a8f98 !important;
    box-shadow: none !important;
    transition: background 0.2s ease, color 0.2s ease, box-shadow 0.2s ease;
}

.extension div:has(tbody input[type="checkbox"]:checked) .eliminar:not(:disabled) {
    background: var(--abx-rojo) !important;
    color: #ffffff !important;
    box-shadow: 0 1px 2px rgba(213, 0, 0, 0.16),
                0 6px 16px rgba(213, 0, 0, 0.20) !important;
}
.extension div:has(tbody input[type="checkbox"]:checked) .eliminar:not(:disabled):hover {
    background: #b80000 !important;
}


/* ----------------------------------------------------------------------------
   22.5  EL CAMPO EN EL QUE ESTÁS ESCRIBIENDO
   ----------------------------------------------------------------------------
   Al enfocarlo se ponía blanco, y sobre una tarjeta blanca eso es justo perder
   el borde del campo. Se queda con su relleno gris —algo más claro, para que
   se note el cambio— y lo que marca el foco es el filete azul y el anillo.
   ---------------------------------------------------------------------------- */
.extension input[type="text"]:focus,
.extension input[type="email"]:focus,
.extension input[type="tel"]:focus,
.extension input[type="number"]:focus,
.extension input[type="password"]:focus,
.extension input[type="search"]:focus,
.extension input[type="url"]:focus,
.extension input[type="date"]:focus,
.extension input[type="time"]:focus,
.extension input[type="datetime-local"]:focus,
.extension input:not([type]):focus,
.extension select:focus,
.extension textarea:focus {
    background-color: #FAFBFC !important;
    border-color: rgba(16, 86, 128, 0.65) !important;
    box-shadow: 0 0 0 3px rgba(16, 86, 128, 0.15) !important;
}


/* ----------------------------------------------------------------------------
   22.6  EL MENÚ LATERAL NO SE ENCOGE
   ----------------------------------------------------------------------------
   Existe un modo "plegado" (`.sidebar.collapsed`) que reduce el menú a 4,5rem
   y esconde los textos. Lo activaba un botón que hoy está comentado en
   sidebar.php, pero el estado se guardaba en el navegador, así que una vez
   plegado seguía plegándose en cada carga.

   No se toca ese JavaScript: se deja la clase sin efecto visual. Aunque algo
   la ponga, el menú se queda como está.
   ---------------------------------------------------------------------------- */
.sidebar.collapsed {
    width: 17rem;
}
.sidebar.collapsed span {
    display: inline;
}
.sidebar.collapsed button,
.sidebar.collapsed .dropdown-toggle {
    justify-content: space-between;
}
.sidebar.collapsed .arrow,
.sidebar.collapsed .arrow-prox {
    display: inline;
}
.sidebar.collapsed .dropdown-content {
    display: block !important;
}
.sidebar.collapsed #dashboard::before,
.sidebar.collapsed .dropdown-toggle::before {
    margin-right: 0.8rem;
}


/* ============================================================================
   23. ACABADOS — botones de añadir y títulos con apostilla
   ============================================================================ */

/* ----------------------------------------------------------------------------
   23.1  "AÑADIR MÁS" / "AÑADIR RELÉ"
   ----------------------------------------------------------------------------
   Se veían mal porque eran dos cosas a la vez: `.anyadir-mas` los deja sin
   fondo y subrayados, pero al ser <button> dentro de una tarjeta heredaban
   también el alto de 2,7rem y el fondo gris de los campos del formulario. El
   resultado era un texto azul flotando sobre una caja gris que no pintaba
   nada. Pasan a ser lo que son: una acción secundaria, en píldora, con su "+".
   ---------------------------------------------------------------------------- */
.extension .anyadir-mas {
    display: inline-flex !important;
    align-items: center;
    gap: 0.45rem;
    width: fit-content !important;
    height: auto !important;
    padding: 0.5rem 0.95rem !important;
    margin: 0.25rem 0 0.5rem !important;
    background: rgba(16, 86, 128, 0.08) !important;
    color: var(--abx-azul) !important;
    border: none !important;
    border-radius: 10px !important;
    box-shadow: none !important;
    font-size: 0.88rem !important;
    font-weight: 600 !important;
    font-style: normal !important;
    text-decoration: none !important;
    transition: background 0.16s ease, transform 0.12s var(--abx-curva-mue);
}
.extension .anyadir-mas::before {
    content: '+';
    font-size: 1.05em;
    font-weight: 500;
    line-height: 1;
    opacity: 0.85;
}
.extension .anyadir-mas:hover {
    background: rgba(16, 86, 128, 0.14) !important;
    transform: translateY(-1px);
}
.extension .anyadir-mas:active {
    transform: translateY(0) scale(0.98);
}


/* ----------------------------------------------------------------------------
   23.2  "(Opcional)" EN LA MISMA LÍNEA QUE SU TÍTULO
   ----------------------------------------------------------------------------
   Colgaba solo bajo el filete del título, como si fuera otro apartado. El HTML
   ya envuelve título y apostilla en `.titulo-h5-h6`, así que basta con ponerlos
   en línea y pasar el filete al contenedor.
   ---------------------------------------------------------------------------- */
.extension .titulo-h5-h6 {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 0 0 1.5rem;
    padding-bottom: 0.85rem;
    border-bottom: 1px solid var(--abx-linea-suave);
}
.extension .titulo-h5-h6 h5 {
    margin: 0 !important;
    padding-bottom: 0;
    border-bottom: none;
}
.extension .titulo-h5-h6 h6 {
    margin: 0 !important;
    font-size: 0.82rem !important;
    font-weight: 500 !important;
    color: var(--abx-texto-2) !important;
}


/* ============================================================================
   24. FLUIDEZ — carga y respuesta
   ============================================================================ */

/* Barra de progreso indeterminada sobre el velo de carga. El círculo solo dice
   "espera"; una barra que avanza dice además "esto sigue vivo", y es lo que
   hace que una espera de tres segundos se perciba más corta. */
#cargando::before,
#cargando_usuarios::before,
#cargando_accesos::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 2px;
    background: linear-gradient(90deg,
        transparent 0%,
        var(--abx-azul) 35%,
        var(--abx-azul-claro) 50%,
        var(--abx-azul) 65%,
        transparent 100%);
    background-size: 45% 100%;
    background-repeat: no-repeat;
    animation: abxProgreso 1.15s ease-in-out infinite;
}
@keyframes abxProgreso {
    0%   { background-position: -45% 0; }
    100% { background-position: 145% 0; }
}

/* El velo de carga entra sin brusquedad. */
#cargando,
#cargando_usuarios,
#cargando_accesos {
    animation: abxVelo 0.18s ease both;
}
@keyframes abxVelo {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Respuesta al pulsar en los elementos interactivos que aún no la tenían. */
.extension .contenedores a:not(.anyadir-mas),
.sidebar a,
.boton-header a {
    transition: color 0.16s ease, opacity 0.16s ease;
}

/* Las filas de tabla y las opciones de menú responden con la misma curva. */
tbody tr,
tbody tr td {
    transition: background-color 0.13s ease;
}

/* Las tarjetas y la tabla acompañan el desplazamiento sin saltos. */
.contenedores,
table,
.stats-box {
    will-change: auto;
}

/* Al pasar de una página a otra, lo que se va no da un tirón. */
@media (prefers-reduced-motion: no-preference) {
    .extension {
        backface-visibility: hidden;
    }
}


/* ============================================================================
   25. MODO OSCURO
   ----------------------------------------------------------------------------
   Por qué esto sí se puede hacer sin tocar las vistas
   ---------------------------------------------------
   Toda esta capa está escrita con variables de color (bloque 0). El fondo del
   panel, las tarjetas, el menú, los campos, las tablas, los modales... ninguno
   lleva un color escrito a mano: todos leen su valor de una variable. Así que
   redefinir esas ocho variables voltea el armazón entero de golpe, sin repetir
   una sola regla.

   Lo que sí hay que añadir a mano son los colores que están escritos dentro de
   styles.css, que sí los tiene literales. Eso es lo que hace el segundo bloque
   de aquí abajo: un puñado de reglas, no una hoja entera.

   Riesgo de romper algo: ninguno. Esto es CSS, no puede alterar una consulta,
   un guardado ni un borrado. Lo peor que puede pasar es que una pantalla se
   vea con una zona clara hasta que la pula.

   Lo que queda pendiente, con nombre y apellidos: las pantallas que llevan su
   propio <style> dentro del HTML (Modelos y versiones, el mapa de ubicaciones
   y los editores) tienen tarjetas en blanco escritas ahí dentro, y seguirán
   claras hasta que las repase una a una.
   ============================================================================ */

/* ---- 1. Las variables, dadas la vuelta ---------------------------------- */
:root[data-tema="oscuro"] {
    /* Le dice al navegador que los controles nativos —casillas, desplegables,
       barras de desplazamiento, selectores de fecha— se dibujen en oscuro. Sin
       esto se quedan blancos y cantan muchísimo. */
    color-scheme: dark;

    /* Los tres grises de texto subieron un escalon entero.

       El oscuro estaba calcado del claro: allí el texto secundario es gris
       sobre blanco y descansa la vista, pero sobre una tarjeta casi negra
       ese mismo gris no descansa nada, se apaga. En oscuro hace falta MAS
       separacion entre el texto y el fondo, no la misma.

       Medido sobre la tarjeta (#212630), que es el caso peor de los tres
       fondos: principal 12.6 -> 13.8, secundario 5.8 -> 8.3, y el terciario
       3.3 -> 5.0, que es el que de verdad estaba mal: por debajo de 4.5 no
       llega a legible para texto corrido, y ahi viven los pies y las marcas
       de agua.

       No son blanco puro a proposito. Sobre un fondo casi negro el blanco
       del todo vibra y cansa en parrafos largos; ese se reserva para los
       titulos del menu, que son cuatro palabras. */
    --abx-tinta:        #F2F4F7;
    --abx-azul:         #58A6DC;   /* el azul de marca, aclarado para que
                                      mantenga contraste sobre fondo oscuro */
    --abx-azul-titulo:  #F5F7F9;   /* el título va casi blanco, no azul lavado */
    --abx-azul-claro:   #B7E0FF;

    --abx-texto:        #F2F4F7;
    --abx-texto-2:      #B9C0CB;
    --abx-texto-3:      #8C949F;
    --abx-linea:        rgba(255, 255, 255, 0.13);
    --abx-linea-suave:  rgba(255, 255, 255, 0.08);

    /* La clave de un oscuro que no parece una mancha: el lienzo tiene que ser
       CLARAMENTE más oscuro que las tarjetas. Si van casi al mismo tono, todo
       se funde en una masa plana — que es lo que pasaba. */
    --abx-lienzo:       #0A0C0F;   /* lo más al fondo */
    --abx-blanco:       #212630;   /* la superficie: tarjetas, menú, tablas */
    --abx-campo:        #2F3540;   /* lo que va encima de una superficie */
    --abx-campo-hover:  #343A45;

    --abx-rojo-texto:   #FF6B6B;

    --abx-sombra-1: 0 1px 2px rgba(0, 0, 0, 0.45),
                    0 6px 18px rgba(0, 0, 0, 0.35);
    --abx-sombra-2: 0 2px 6px rgba(0, 0, 0, 0.45),
                    0 14px 34px rgba(0, 0, 0, 0.45);
    --abx-sombra-3: 0 24px 60px rgba(0, 0, 0, 0.65);
}

/* ---- 2. Los colores que styles.css tiene escritos a mano ---------------- */
:root[data-tema="oscuro"] body.body-panel,
:root[data-tema="oscuro"] .body-index {
    background: var(--abx-lienzo);
    color: var(--abx-texto);
}

:root[data-tema="oscuro"] table,
:root[data-tema="oscuro"] .stats-box,
:root[data-tema="oscuro"] .modal-contenedor,
:root[data-tema="oscuro"] .filtro-estado-dropdown,
:root[data-tema="oscuro"] .boton-header ul {
    background: var(--abx-blanco) !important;
    color: var(--abx-texto);
}

/* Las filas las pinta el JavaScript en blanco y gris claro; en oscuro se
   cubren desde la celda, que no lleva color en línea. */
:root[data-tema="oscuro"] tbody td {
    background-color: #212630 !important;
}
:root[data-tema="oscuro"] tbody tr:nth-child(odd) td {
    background-color: #282E39 !important;
}
:root[data-tema="oscuro"] tbody tr:hover td {
    background-color: #223244 !important;
}
:root[data-tema="oscuro"] * td,
:root[data-tema="oscuro"] table a,
:root[data-tema="oscuro"] table a:visited {
    color: var(--abx-texto) !important;
}
:root[data-tema="oscuro"] .extension thead th,
:root[data-tema="oscuro"] .extension thead th p {
    color: #C6CCD6 !important;
}

/* Menú lateral */
:root[data-tema="oscuro"] #dashboard.selected,
:root[data-tema="oscuro"] .dropdown-toggle.selected {
    background: rgba(88, 166, 220, 0.16) !important;
    border-color: rgba(88, 166, 220, 0.22) !important;
    color: var(--abx-azul) !important;
}
/* Las entradas de primer nivel, en blanco puro. Son los titulos del menu y
   se leen de un vistazo, sin buscarlos. */
:root[data-tema="oscuro"] .dropdown-toggle,
:root[data-tema="oscuro"] #dashboard,
:root[data-tema="oscuro"] .sidebar span {
    color: #FFFFFF;
}

/* Las de dentro de un desplegable siguen un punto por debajo: es lo unico
   que dice, sin sangrias ni lineas, que cuelgan de la de arriba. Iguales las
   dos, el menu se vuelve una lista plana de doce cosas al mismo nivel. */
:root[data-tema="oscuro"] li a.item {
    color: #C3CAD4;
}

:root[data-tema="oscuro"] .dropdown-toggle:hover,
:root[data-tema="oscuro"] #dashboard:hover {
    background: rgba(255, 255, 255, 0.06);
    color: #FFFFFF;
}
:root[data-tema="oscuro"] li a.item:hover {
    background: rgba(255, 255, 255, 0.06);
    color: #FFFFFF;
}
:root[data-tema="oscuro"] li a.item.selected {
    background: rgba(88, 166, 220, 0.14);
    color: var(--abx-azul);
}
:root[data-tema="oscuro"] li a.item::before { background: #414956; }
:root[data-tema="oscuro"] li a.item.selected::before { background: var(--abx-azul); }

/* El logotipo se deja EXACTAMENTE igual que en claro, sin ningún filtro.
   Probé a invertirlo y a pasarlo a silueta y ninguna de las dos respetaba la
   marca: el icono cambiaba de color o se convertía en un bloque blanco. Una
   imagen de marca no se retoca con filtros; si algún día hace falta una
   versión para fondo oscuro, se hace el PNG y se cambia el archivo. */
.logo-nuevo {
    filter: none;
}

/* Iconos que son imágenes (flechas del menú, ordenación de tablas). */
:root[data-tema="oscuro"] .sidebar .arrow,
:root[data-tema="oscuro"] .sidebar .arrow-prox,
:root[data-tema="oscuro"] .boton-header .arrow,
:root[data-tema="oscuro"] table th div div img {
    filter: invert(1);
}

/* Barra superior */
:root[data-tema="oscuro"] .dropdown-toggle-user {
    background: var(--abx-blanco) !important;
    border-color: var(--abx-linea) !important;
}
:root[data-tema="oscuro"] .imagen-boton {
    background: rgba(255, 255, 255, 0.08);
}
:root[data-tema="oscuro"] .imagen-boton::before {
    background: var(--abx-texto-2);
}
:root[data-tema="oscuro"] .boton-header .item {
    color: var(--abx-texto);
}
:root[data-tema="oscuro"] .boton-header .item:hover {
    background: rgba(255, 255, 255, 0.07);
}

/* Formularios */
:root[data-tema="oscuro"] .extension thead th input:not([type="checkbox"]),
:root[data-tema="oscuro"] .extension thead th select,
:root[data-tema="oscuro"] .extension thead th button {
    /* Iban a #23272F, casi el mismo tono que la cabecera (#212630): por eso no
       se despegaban. Ahora van claramente por encima, con su filete. */
    background-color: #303742 !important;
    border-color: rgba(255, 255, 255, 0.10) !important;
    color: var(--abx-texto) !important;
}
:root[data-tema="oscuro"] .extension thead th input:not([type="checkbox"]):hover,
:root[data-tema="oscuro"] .extension thead th select:hover,
:root[data-tema="oscuro"] .extension thead th button:hover {
    background-color: #3A414D !important;
}
:root[data-tema="oscuro"] .extension input.input-buscar {
    background-color: var(--abx-blanco) !important;
    color: var(--abx-texto) !important;
}
:root[data-tema="oscuro"] .extension input:focus,
:root[data-tema="oscuro"] .extension select:focus,
:root[data-tema="oscuro"] .extension textarea:focus {
    background-color: #272C35 !important;
}
:root[data-tema="oscuro"] .contrasenya-aleotoria {
    background: var(--abx-campo);
}

/* Botones secundarios y de cancelar, que en claro usan el negro como color */
:root[data-tema="oscuro"] .boton-cancelar,
:root[data-tema="oscuro"] .boton-traspasar {
    background: rgba(255, 255, 255, 0.09) !important;
    color: var(--abx-texto) !important;
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.16) !important;
}
:root[data-tema="oscuro"] .boton-cancelar:hover,
:root[data-tema="oscuro"] .boton-traspasar:hover {
    background: #E8EAED !important;
    color: #14171C !important;
}
:root[data-tema="oscuro"] .extension .eliminar {
    background: rgba(255, 255, 255, 0.08) !important;
    color: #9AA2AE !important;
}
:root[data-tema="oscuro"] .extension .anyadir-mas {
    background: rgba(88, 166, 220, 0.14) !important;
}

/* Modales y velos */
:root[data-tema="oscuro"] .modal-contenedor {
    border-color: rgba(255, 255, 255, 0.10);
}
:root[data-tema="oscuro"] .modal-contenedor p {
    color: var(--abx-texto);
}
:root[data-tema="oscuro"] .modal-pdf,
:root[data-tema="oscuro"] .modal-imagen,
:root[data-tema="oscuro"] .modal-sin-imagen,
:root[data-tema="oscuro"] .modal-selected,
:root[data-tema="oscuro"] .modal-no-selected {
    background-color: rgba(0, 0, 0, 0.62);
}

/* Etiquetas, avisos y barras de desplazamiento */
:root[data-tema="oscuro"] .extension label,
:root[data-tema="oscuro"] label {
    color: #C3CAD4;
}
:root[data-tema="oscuro"] .aviso-advertencia {
    background-color: #2A2413;
}
:root[data-tema="oscuro"] .aviso-advertencia.aviso-critico {
    background-color: #2E1717;
}
:root[data-tema="oscuro"] * {
    scrollbar-color: rgba(255, 255, 255, 0.22) transparent;
}
:root[data-tema="oscuro"] *::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.20);
}
:root[data-tema="oscuro"] ::selection {
    background: rgba(88, 166, 220, 0.30);
    color: #ffffff;
}

/* El cambio de tema se nota, pero no deslumbra. */
body.body-panel,
.sidebar,
.contenedores,
table,
.stats-box,
tbody td,
.dropdown-toggle-user {
    transition: background-color 0.25s ease, color 0.25s ease,
                border-color 0.25s ease;
}


/* ============================================================================
   26. EL INTERRUPTOR DE TEMA
   ----------------------------------------------------------------------------
   Lo crea el script de panel.php y se inserta al final del menú lateral, así
   que no hay que tocar sidebar.php ni header.php. Es una píldora con el sol y
   la luna y un pastilla que se desliza entre los dos.
   ============================================================================ */
.abx-tema {
    margin: 0 1.5rem 1.25rem;
    display: flex;
    justify-content: center;
}

/* Todas las medidas en píxeles y el hueco entre iconos a cero: así el
   desplazamiento de la pastilla es exactamente el ancho de un icono, sin
   depender de cómo redondee el navegador los rem. Con 0,15rem de hueco y
   1,95rem de desplazamiento, la pastilla caía un poco corrida — que es lo que
   se veía. Lleva `!important` porque `.sidebar button` de styles.css impone
   su propio fondo, margen y alineación a todos los botones del menú. */
.sidebar .abx-tema .abx-tema-pista {
    position: relative !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: flex-start !important;
    gap: 0 !important;
    width: auto !important;
    height: auto !important;
    margin: 0 !important;
    padding: 3px !important;
    border: 1px solid rgba(13, 27, 42, 0.06) !important;
    border-radius: 999px !important;
    background: rgba(13, 27, 42, 0.07) !important;
    line-height: 0 !important;
    cursor: pointer;
    transition: background 0.2s ease;
}
.sidebar .abx-tema .abx-tema-pista:hover {
    background: rgba(13, 27, 42, 0.11) !important;
}

.abx-tema-pastilla {
    position: absolute;
    top: 3px;
    left: 3px;
    width: 32px;
    height: 32px;
    border-radius: 999px;
    background: #ffffff;
    box-shadow: 0 1px 3px rgba(13, 27, 42, 0.22);
    /* Se mueve con `left`, no con `transform`. Desplazarla "el ancho de un
       icono" daba por supuesto que entre los dos iconos no hay separación, y
       medido resultó haber 5px: la pastilla quedaba corrida y la luna no caía
       centrada. Con `calc(100% - 35px)` se ancla al borde derecho de la pista
       —100% del ancho, menos los 32 de la pastilla y los 3 del relleno—, así
       que cae exacta pase lo que pase con los huecos. */
    transition: left 0.28s var(--abx-curva-mue), background 0.2s ease;
}
:root[data-tema="oscuro"] .abx-tema-pastilla {
    left: calc(100% - 35px);
    transform: none;
    background: #4B5462;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.55),
                inset 0 1px 0 rgba(255, 255, 255, 0.12);
}

.abx-tema-icono {
    margin: 0 !important;
    flex: 0 0 32px;
    position: relative;
    z-index: 1;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--abx-texto-2);
    transition: color 0.2s ease;
}
.abx-tema-icono svg {
    width: 15px;
    height: 15px;
}
:root:not([data-tema="oscuro"]) .abx-tema-icono[data-modo="claro"],
:root[data-tema="oscuro"] .abx-tema-icono[data-modo="oscuro"] {
    color: var(--abx-azul);
}

:root[data-tema="oscuro"] .sidebar .abx-tema .abx-tema-pista {
    background: rgba(255, 255, 255, 0.08) !important;
    border-color: rgba(255, 255, 255, 0.09) !important;
}
:root[data-tema="oscuro"] .sidebar .abx-tema .abx-tema-pista:hover {
    background: rgba(255, 255, 255, 0.13) !important;
}


/* ============================================================================
   29. EL MENÚ DE LA SECCIÓN EN LA QUE ESTÁS SE QUEDA ABIERTO
   ----------------------------------------------------------------------------
   Al navegar, el submenú de la sección activa se plegaba y había que volver a
   abrirlo para ver dónde estabas. `:has()` permite detectar qué submenú
   contiene el elemento marcado como seleccionado y dejarlo desplegado.

   Se hace SIN `!important` en `display` a propósito: así, si pulsas el título
   de la sección, el JavaScript sigue pudiendo cerrarla. Lo único que cambia es
   el estado de partida al cargar la página.
   ============================================================================ */
.sidebar .dropdown-content:has(a.item.selected) {
    display: block;
    max-height: 1000px !important;
    opacity: 1 !important;
    overflow: visible !important;
    padding: 0 0 0.25rem !important;
}

/* La flecha del título acompaña: apunta hacia arriba cuando está desplegado. */
.sidebar .dropdown:has(a.item.selected) .dropdown-toggle .arrow {
    transform: rotate(180deg);
}


/* ============================================================================
   30. MODO OSCURO — las pantallas que faltaban
   ----------------------------------------------------------------------------
   Repasé todos los <style> incrustados en las vistas buscando fondos blancos y
   textos casi negros, y los agrupé aquí. Son las pantallas que llevan su
   diseño escrito dentro del HTML: bienvenida, estadísticas, mapa, editores,
   traspaso de datos, buscador de NFC y los modales de selección.
   ============================================================================ */

/* ---- Superficies: lo que era blanco pasa a ser superficie oscura -------- */
:root[data-tema="oscuro"] .bv-tarjeta,
:root[data-tema="oscuro"] .dv-tarjeta-tabla,
:root[data-tema="oscuro"] .es-apartado,
:root[data-tema="oscuro"] .es-boton-suave,
:root[data-tema="oscuro"] .ed-card,
:root[data-tema="oscuro"] .mp-filtro,
:root[data-tema="oscuro"] .mp-cifras,
:root[data-tema="oscuro"] .mp-sugerencias,
:root[data-tema="oscuro"] .mp-tarjeta-mapa,
:root[data-tema="oscuro"] .mp-btn-pantalla,
:root[data-tema="oscuro"] .mp-popup-lugar,
:root[data-tema="oscuro"] .mp-sin-ubicar,
:root[data-tema="oscuro"] .mu-modal,
:root[data-tema="oscuro"] .tsp-modal,
:root[data-tema="oscuro"] .tsp-conflictos-cabecera,
:root[data-tema="oscuro"] .tsp-conflicto-fila,
:root[data-tema="oscuro"] .tsp-fila-acceso,
:root[data-tema="oscuro"] .sel-modal,
:root[data-tema="oscuro"] #selAccesoModal,
:root[data-tema="oscuro"] #nfcModal {
    background: var(--abx-blanco) !important;
    border-color: rgba(255, 255, 255, 0.08) !important;
}

/* ---- Campos y botones sueltos de esas pantallas ------------------------- */
:root[data-tema="oscuro"] #mpBuscar,
:root[data-tema="oscuro"] #selAccesoBuscar,
:root[data-tema="oscuro"] #selReleBuscar,
:root[data-tema="oscuro"] .bnfc-input-fila input[type="text"],
:root[data-tema="oscuro"] .bnfc-sugerencia-chip,
:root[data-tema="oscuro"] .tsp-modal input[type="text"],
:root[data-tema="oscuro"] #nfcModal #nfcCipherInput,
:root[data-tema="oscuro"] .mu-stats-acciones button,
:root[data-tema="oscuro"] .tsp-seg button,
:root[data-tema="oscuro"] .btn-increment,
:root[data-tema="oscuro"] .btn-decrement {
    background: var(--abx-campo) !important;
    color: var(--abx-texto) !important;
    border-color: rgba(255, 255, 255, 0.10) !important;
}
:root[data-tema="oscuro"] .btn-increment:hover,
:root[data-tema="oscuro"] .btn-decrement:hover,
:root[data-tema="oscuro"] .mu-stats-acciones button:hover,
:root[data-tema="oscuro"] .tsp-seg button:hover,
:root[data-tema="oscuro"] .mp-sugerencia:hover,
:root[data-tema="oscuro"] .mp-base-opcion:hover {
    background: var(--abx-campo-hover) !important;
}

/* ---- Textos que estaban en negro --------------------------------------- */
:root[data-tema="oscuro"] .bv-tarjeta-titulo,
:root[data-tema="oscuro"] .es-titulo,
:root[data-tema="oscuro"] .es-metrica,
:root[data-tema="oscuro"] .es-metrica-valor,
:root[data-tema="oscuro"] .es-barra-cab .es-barra-nombre,
:root[data-tema="oscuro"] .es-barra-cab .es-barra-cifra,
:root[data-tema="oscuro"] .ed-card-tit,
:root[data-tema="oscuro"] .ed-col-tit,
:root[data-tema="oscuro"] .ed-col-sub strong,
:root[data-tema="oscuro"] .ed-fila-n,
:root[data-tema="oscuro"] .ed-fila-c,
:root[data-tema="oscuro"] .ed-dato-v,
:root[data-tema="oscuro"] .mp-cifra .mp-cifra-valor,
:root[data-tema="oscuro"] .mp-popup-equipo,
:root[data-tema="oscuro"] .mp-sin-ubicar h6,
:root[data-tema="oscuro"] .mp-fila-sin .mp-sin-nombre,
:root[data-tema="oscuro"] .mu-modal h5,
:root[data-tema="oscuro"] .tsp-modal h5,
:root[data-tema="oscuro"] .tsp-modal p,
:root[data-tema="oscuro"] .tsp-stat .tsp-numero,
:root[data-tema="oscuro"] .tsp-conflictos-cabecera strong,
:root[data-tema="oscuro"] .tsp-anomalia-texto strong,
:root[data-tema="oscuro"] #tarjetaSubAdmins .sa-etiqueta,
:root[data-tema="oscuro"] #tarjetaSubAdmins .sa-pildora-texto,
:root[data-tema="oscuro"] .acceso-fijo-nombre,
:root[data-tema="oscuro"] .sel-acceso-nombre,
:root[data-tema="oscuro"] #selAccesoModal h5,
:root[data-tema="oscuro"] .sel-modal h5,
:root[data-tema="oscuro"] #nfcModal h5,
:root[data-tema="oscuro"] .dv-tarjeta-tabla h6,
:root[data-tema="oscuro"] .dv-tarjeta-barras h6,
:root[data-tema="oscuro"] #dvTablas .dv-tabla-versiones td {
    color: var(--abx-texto) !important;
}

/* ---- Textos secundarios: el gris de claro no contrasta sobre oscuro ----- */
:root[data-tema="oscuro"] .bv-tarjeta-texto,
:root[data-tema="oscuro"] .bv-pie,
:root[data-tema="oscuro"] #nfcModal label,
:root[data-tema="oscuro"] #nfcModal .nfc-modal-subtitulo,
:root[data-tema="oscuro"] .es-barra-cab,
:root[data-tema="oscuro"] .ed-col-sub {
    color: var(--abx-texto-2) !important;
}

/* ---- El número del centro del gráfico circular -------------------------- */
:root[data-tema="oscuro"] .dv-grafica-svg text {
    fill: var(--abx-texto) !important;
}
:root[data-tema="oscuro"] .dv-grafica-svg text:last-of-type {
    fill: var(--abx-texto-2) !important;
}

/* ---- Filas y separadores de esas pantallas ------------------------------ */
:root[data-tema="oscuro"] .tsp-check-todos,
:root[data-tema="oscuro"] .mp-base-opcion,
:root[data-tema="oscuro"] .mp-sugerencia {
    background: transparent !important;
    color: var(--abx-texto) !important;
}


/* ============================================================================
   31. CIERRE DEL MODO OSCURO — barrido completo de las vistas
   ----------------------------------------------------------------------------
   Generado recorriendo TODOS los <style> incrustados en todas las vistas y
   midiendo la luminosidad de cada color declarado. Dos correcciones sobre la
   versión anterior, que me dio dos problemas que tú viste:

   · Se excluyen los selectores amplios (`body`, `html`, `.container`, `*`).
     Antes colaba un `body` de nfcslocales.php que pintaba el LIENZO del color
     de las tarjetas — de ahí que dijeras que el fondo y las tarjetas no se
     diferenciaban. Era eso exactamente.

   · Ahora distingue dos casos. Lo que era blanco puro es una tarjeta y va al
     color de superficie. Lo que era gris claro es un elemento DENTRO de una
     tarjeta —una ficha de acceso, un chip, un campo— y va un tono POR ENCIMA
     de ella; antes les daba el color de la tarjeta y desaparecían, que es lo
     que pasaba en Accesos y en Relés.

   Los colores con carácter —verdes, rojos, el azul de marca— se respetan.
   Lo que esto no alcanza: colores escritos en el atributo `style` por el
   JavaScript. Esos hay que cambiarlos donde se escriben.
   ============================================================================ */

/* Tarjetas y superficies que eran blancas (30) */
:root[data-tema="oscuro"] #contenedorUsuarios,
:root[data-tema="oscuro"] #mpBuscar,
:root[data-tema="oscuro"] #mpBuscar:focus,
:root[data-tema="oscuro"] #mpMapa .leaflet-control-zoom a:hover,
:root[data-tema="oscuro"] #nfcModal,
:root[data-tema="oscuro"] #selAccesoModal, .sel-modal,
:root[data-tema="oscuro"] .bnfc-input-fila input[type="text"],
/* .bv-boton-principal NO va aqui. Entro de barrido con "lo que era blanco
   se oscurece", pero ese boton no esta sobre el lienzo de la pagina: esta
   encima del degradado oscuro de la bienvenida, que es oscuro en los dos
   temas. Oscurecerlo lo hacia desaparecer justo en modo oscuro. */
:root[data-tema="oscuro"] .bv-tarjeta,
:root[data-tema="oscuro"] .dv-tarjeta-barras,
:root[data-tema="oscuro"] .dv-tarjeta-grafica,
:root[data-tema="oscuro"] .dv-tarjeta-tabla,
:root[data-tema="oscuro"] .ed-card,
:root[data-tema="oscuro"] .ed-kpi-boton,
:root[data-tema="oscuro"] .ed-kpi-boton:hover,
:root[data-tema="oscuro"] .mp-btn-pantalla:hover,
:root[data-tema="oscuro"] .mp-cifras,
:root[data-tema="oscuro"] .mp-filtro,
:root[data-tema="oscuro"] .mp-sin-ubicar,
:root[data-tema="oscuro"] .mp-sugerencias,
:root[data-tema="oscuro"] .mp-tarjeta-mapa,
:root[data-tema="oscuro"] .mp-tarjeta-mapa.mp-pantalla-completa,
:root[data-tema="oscuro"] .mu-modal,
:root[data-tema="oscuro"] .mu-modal input[type="search"]:focus,
:root[data-tema="oscuro"] .mu-stats-acciones button,
:root[data-tema="oscuro"] .tsp-conflicto-fila,
:root[data-tema="oscuro"] .tsp-conflictos-cabecera,
:root[data-tema="oscuro"] .tsp-fila-acceso,
:root[data-tema="oscuro"] .tsp-modal,
:root[data-tema="oscuro"] .tsp-resumen {
    background-color: var(--abx-blanco) !important;
    border-color: rgba(255, 255, 255, 0.10) !important;
}

/* Elementos DENTRO de una tarjeta: van un tono por encima de ella (21) */
:root[data-tema="oscuro"] #muBtnPaneles,
:root[data-tema="oscuro"] #muBtnPaneles:hover,
:root[data-tema="oscuro"] #nfcAbrirModal,
:root[data-tema="oscuro"] #nfcModal #nfcCipherInput,
:root[data-tema="oscuro"] #nfcModal #nfcModalCerrar,
:root[data-tema="oscuro"] #selAccesoBuscar, #selReleBuscar,
:root[data-tema="oscuro"] #selReleBuscar,
:root[data-tema="oscuro"] #tarjetaSubAdmins .sa-pildora,
:root[data-tema="oscuro"] .acceso-fijo,
:root[data-tema="oscuro"] .bnfc-sugerencia-chip,
:root[data-tema="oscuro"] .bnfc-sugerencia-chip:hover,
:root[data-tema="oscuro"] .mp-filtro.apagado,
:root[data-tema="oscuro"] .mu-modal input[type="search"],
:root[data-tema="oscuro"] .sel-acceso-item,
:root[data-tema="oscuro"] .tsp-conflictos,
:root[data-tema="oscuro"] .tsp-lista-accesos,
:root[data-tema="oscuro"] .tsp-modal #tspModalCancelar,
:root[data-tema="oscuro"] .tsp-modal input[type="text"],
:root[data-tema="oscuro"] .tsp-seg button,
:root[data-tema="oscuro"] .tsp-seg button:hover,
:root[data-tema="oscuro"] input[type="file"] {
    background-color: var(--abx-campo) !important;
    border-color: rgba(255, 255, 255, 0.10) !important;
}

/* Textos que estaban en negro (60) */
:root[data-tema="oscuro"] #dvTablas .dv-tabla-versiones td,
:root[data-tema="oscuro"] #mpBuscar,
:root[data-tema="oscuro"] #mpMapa .leaflet-control-zoom a,
:root[data-tema="oscuro"] #mpMapa .leaflet-popup-close-button:hover,
:root[data-tema="oscuro"] #nfcModal,
:root[data-tema="oscuro"] #nfcModal #nfcCipherInput,
:root[data-tema="oscuro"] #nfcModal #nfcModalCerrar,
:root[data-tema="oscuro"] #nfcModal h5,
:root[data-tema="oscuro"] #nfcModal label, #nfcModal .nfc-modal-subtitulo,
:root[data-tema="oscuro"] #selAccesoBuscar, #selReleBuscar,
:root[data-tema="oscuro"] #selAccesoModal h5, .sel-modal h5,
:root[data-tema="oscuro"] #selReleBuscar,
:root[data-tema="oscuro"] #tarjetaSubAdmins .sa-etiqueta,
:root[data-tema="oscuro"] #tarjetaSubAdmins .sa-pildora-texto,
:root[data-tema="oscuro"] .acceso-fijo-nombre,
:root[data-tema="oscuro"] .bnfc-input-fila input[type="text"],
:root[data-tema="oscuro"] .bnfc-sugerencia-chip,
:root[data-tema="oscuro"] .bv-tarjeta-titulo,
:root[data-tema="oscuro"] .dv-barra-item .dv-barra-cifra strong,
:root[data-tema="oscuro"] .dv-barra-item .dv-barra-version,
:root[data-tema="oscuro"] .dv-barra-item.dv-resto:hover .dv-barra-version,
:root[data-tema="oscuro"] .dv-leyenda-cifra,
:root[data-tema="oscuro"] .dv-leyenda-fila,
:root[data-tema="oscuro"] .dv-resto-fila .dv-resto-version,
:root[data-tema="oscuro"] .dv-resumen-item .dv-resumen-valor,
:root[data-tema="oscuro"] .dv-resumen-item .dv-resumen-version,
:root[data-tema="oscuro"] .dv-tarjeta-barras h6,
:root[data-tema="oscuro"] .dv-tarjeta-grafica h5,
:root[data-tema="oscuro"] .dv-tarjeta-tabla h6,
:root[data-tema="oscuro"] .ed-card-tit,
:root[data-tema="oscuro"] .ed-col-sub strong,
:root[data-tema="oscuro"] .ed-col-tit,
:root[data-tema="oscuro"] .ed-dato-v,
:root[data-tema="oscuro"] .ed-fila-c,
:root[data-tema="oscuro"] .ed-fila-n,
:root[data-tema="oscuro"] .mp-base-opcion:hover,
:root[data-tema="oscuro"] .mp-btn-pantalla,
:root[data-tema="oscuro"] .mp-cifra .mp-cifra-valor,
:root[data-tema="oscuro"] .mp-fila-sin .mp-sin-nombre,
:root[data-tema="oscuro"] .mp-filtro,
:root[data-tema="oscuro"] .mp-lista-sin,
:root[data-tema="oscuro"] .mp-popup-equipo,
:root[data-tema="oscuro"] .mp-popup-lugar,
:root[data-tema="oscuro"] .mp-sin-ubicar h6,
:root[data-tema="oscuro"] .mp-sugerencia,
:root[data-tema="oscuro"] .mu-modal,
:root[data-tema="oscuro"] .mu-modal h5,
:root[data-tema="oscuro"] .mu-stats-acciones button,
:root[data-tema="oscuro"] .sel-acceso-nombre,
:root[data-tema="oscuro"] .tsp-anomalia-texto strong,
:root[data-tema="oscuro"] .tsp-check-todos,
:root[data-tema="oscuro"] .tsp-conflictos-cabecera strong,
:root[data-tema="oscuro"] .tsp-modal,
:root[data-tema="oscuro"] .tsp-modal #tspModalCancelar,
:root[data-tema="oscuro"] .tsp-modal h5,
:root[data-tema="oscuro"] .tsp-modal input[type="text"],
:root[data-tema="oscuro"] .tsp-modal p,
:root[data-tema="oscuro"] .tsp-seg button,
:root[data-tema="oscuro"] .tsp-stat .tsp-numero,
:root[data-tema="oscuro"] h2, h3 {
    color: var(--abx-texto) !important;
}

/* Textos secundarios sin contraste (51) */
:root[data-tema="oscuro"] #bnfcTabla td:nth-child(4),
:root[data-tema="oscuro"] #dvTablas .dv-tabla-versiones th,
:root[data-tema="oscuro"] #mpMapa.mp-base-oscura .leaflet-control-attribution,
:root[data-tema="oscuro"] #muBtnPaneles,
:root[data-tema="oscuro"] #selAccesoInfo, #selReleInfo,
:root[data-tema="oscuro"] #selReleInfo,
:root[data-tema="oscuro"] #tarjetaPermisos .pm-proximamente,
:root[data-tema="oscuro"] #tarjetaSubAdmins p.sa-nota,
:root[data-tema="oscuro"] #tspContenedorPlan p.tsp-intro,
:root[data-tema="oscuro"] #usuarios td:nth-child(2),     #usuarios td:nth-child(6),
:root[data-tema="oscuro"] #usuarios td:nth-child(4),
:root[data-tema="oscuro"] #usuarios td:nth-child(5),
:root[data-tema="oscuro"] .acceso-fijo-sub,
:root[data-tema="oscuro"] .bnfc-estado,
:root[data-tema="oscuro"] .bnfc-sugerencia-chip .motivo,
:root[data-tema="oscuro"] .bnfc-sugerencias-titulo,
:root[data-tema="oscuro"] .bv-tarjeta-texto,
:root[data-tema="oscuro"] .dv-barra-item .dv-barra-cifra,
:root[data-tema="oscuro"] .dv-barra-item.dv-resto .dv-barra-version,
:root[data-tema="oscuro"] .dv-estado,
:root[data-tema="oscuro"] .dv-info-actualizacion,
:root[data-tema="oscuro"] .dv-leyenda-pct,
:root[data-tema="oscuro"] .dv-resto-fila .dv-resto-cifra,
:root[data-tema="oscuro"] .dv-resumen-item .dv-resumen-detalle,
:root[data-tema="oscuro"] .dv-resumen-item .dv-resumen-etiqueta,
:root[data-tema="oscuro"] .dv-tarjeta-barras .dv-subtotal,
:root[data-tema="oscuro"] .dv-tarjeta-tabla .dv-subtotal,
:root[data-tema="oscuro"] .ed-dato-e,
:root[data-tema="oscuro"] .mp-base-opcion,
:root[data-tema="oscuro"] .mp-cifra .mp-cifra-etiqueta,
:root[data-tema="oscuro"] .mp-estado,
:root[data-tema="oscuro"] .mp-filtro .mp-conteo,
:root[data-tema="oscuro"] .mp-info-resultados,
:root[data-tema="oscuro"] .mp-nota,
:root[data-tema="oscuro"] .mp-sin-ubicar .mp-sub,
:root[data-tema="oscuro"] .mu-cargando-tabla,
:root[data-tema="oscuro"] .mu-info-resultados,
:root[data-tema="oscuro"] .mu-modal-contador,
:root[data-tema="oscuro"] .mu-stats-fecha,
:root[data-tema="oscuro"] .sel-acceso-meta,
:root[data-tema="oscuro"] .tsp-anomalia-fila code,
:root[data-tema="oscuro"] .tsp-anomalia-texto,
:root[data-tema="oscuro"] .tsp-conflicto-meta,
:root[data-tema="oscuro"] .tsp-conflictos-cabecera,
:root[data-tema="oscuro"] .tsp-detalle summary,
:root[data-tema="oscuro"] .tsp-fila-acceso .tsp-acceso-direccion,
:root[data-tema="oscuro"] .tsp-nota,
:root[data-tema="oscuro"] .tsp-progreso,
:root[data-tema="oscuro"] .tsp-stat .tsp-etiqueta,
:root[data-tema="oscuro"] .ue-cargando-tabla,
:root[data-tema="oscuro"] .ue-info-resultados {
    color: var(--abx-texto-2) !important;
}


/* ============================================================================
   32. DOS REMATES
   ============================================================================ */

/* ---- 32.1  "(Opcional)" junto a su título, en todas sus variantes -------
   Lo arreglé para `.titulo-h5-h6`, pero en Nuevo usuario y Editar usuario el
   contenedor se llama `.titulo-directorio-contacto`. En vez de ir sumando
   nombres, la regla pregunta por la forma: cualquier bloque dentro de una
   tarjeta que contenga un h5 y un h6 los pone en la misma línea. */
.extension .contenedores > div:has(> h5):has(> h6),
.extension .titulo-h5-h6,
.extension .titulo-directorio-contacto {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 0 0 1.5rem;
    padding-bottom: 0.85rem;
    border-bottom: 1px solid var(--abx-linea-suave);
}
.extension .contenedores > div:has(> h5):has(> h6) > h5,
.extension .titulo-h5-h6 > h5,
.extension .titulo-directorio-contacto > h5 {
    margin: 0 !important;
    padding-bottom: 0;
    border-bottom: none;
}
.extension .contenedores > div:has(> h5):has(> h6) > h6,
.extension .titulo-h5-h6 > h6,
.extension .titulo-directorio-contacto > h6 {
    margin: 0 !important;
    font-size: 0.82rem !important;
    font-weight: 500 !important;
    color: var(--abx-texto-2) !important;
}

/* ---- 32.2  El campo que el navegador rellena solo ----------------------
   Safari y Chrome pintan de blanco los campos autocompletados, y en oscuro
   aparecía un recuadro blanco en mitad del formulario (el "Email..." de tu
   captura). No se puede cambiar el fondo directamente: se cubre con una
   sombra interior del color del campo, que es el truco estándar. */
:root[data-tema="oscuro"] input:-webkit-autofill,
:root[data-tema="oscuro"] input:-webkit-autofill:hover,
:root[data-tema="oscuro"] input:-webkit-autofill:focus {
    -webkit-box-shadow: 0 0 0 100px var(--abx-campo) inset !important;
    -webkit-text-fill-color: var(--abx-texto) !important;
    caret-color: var(--abx-texto);
}
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus {
    -webkit-box-shadow: 0 0 0 100px var(--abx-campo) inset !important;
    -webkit-text-fill-color: var(--abx-texto) !important;
}


/* ============================================================================
   33. LOS TIPOS DE CAMPO QUE NO EXISTEN
   ----------------------------------------------------------------------------
   Esto explica varias de las cosas raras que venías viendo, y no era el tema
   oscuro: en el HTML hay campos con un `type` que no existe en HTML.

       <input type="string"   ...>   (42 campos en todo el panel)
       <input type="email-usuario" ...>   (el "Email*" de Nuevo usuario)

   El navegador los trata como texto normal y funcionan, pero un selector
   `input[type="text"]` NO los alcanza — por eso quedaban con su aspecto de
   fábrica mientras sus vecinos sí se estilaban. Ese es el campo blanco que
   viste al crear un usuario.

   Se añaden a la lista. Lo correcto de verdad sería cambiar esos `type` en el
   HTML a "text" y "email"; son 43 atributos y ninguno cambia el comportamiento,
   pero es tu código y prefiero que la decisión sea tuya.
   ---------------------------------------------------------------------------- */
.extension input[type="string"],
.extension input[type="email-usuario"] {
    font-style: normal !important;
    color: var(--abx-texto) !important;
    background-color: var(--abx-campo) !important;
    border: 1px solid transparent !important;
    border-radius: var(--abx-r-s) !important;
    transition: background-color 0.16s ease, border-color 0.16s ease,
                box-shadow 0.16s ease !important;
}
.extension input[type="string"]:hover,
.extension input[type="email-usuario"]:hover {
    background-color: var(--abx-campo-hover) !important;
}
.extension input[type="string"]:focus,
.extension input[type="email-usuario"]:focus {
    background-color: #FAFBFC !important;
    border-color: rgba(16, 86, 128, 0.65) !important;
    box-shadow: 0 0 0 3px rgba(16, 86, 128, 0.15) !important;
}
:root[data-tema="oscuro"] .extension input[type="string"]:focus,
:root[data-tema="oscuro"] .extension input[type="email-usuario"]:focus {
    background-color: #272C35 !important;
}


/* ============================================================================
   34. REMATES DE ESTA RONDA
   ============================================================================ */

/* ---- El filtro "Paneles" de Mis usuarios -------------------------------
   Tiene sus propios estilos con selector de ID dentro de su pantalla, y el
   barrido automático le daba además color de tarjeta, así que acababa siendo
   el único control de la cabecera con otro aspecto. Se alinea con el resto. */
.extension thead th #muBtnPaneles,
:root[data-tema="oscuro"] .extension thead th #muBtnPaneles {
    box-sizing: border-box !important;
    width: 100% !important;
    height: 2rem !important;
    padding: 0 1.8rem 0 0.6rem !important;
    border-radius: 8px !important;
    font-size: 0.82rem !important;
    font-weight: 400 !important;
    text-align: left !important;
}
.extension thead th #muBtnPaneles {
    background-color: #F2F2F2 !important;
    color: var(--abx-texto) !important;
    border: 1px solid transparent !important;
}
:root[data-tema="oscuro"] .extension thead th #muBtnPaneles {
    background-color: #303742 !important;
    color: var(--abx-texto) !important;
    border-color: rgba(255, 255, 255, 0.10) !important;
}

/* ---- Estados vacíos de las tablas --------------------------------------
   "Busca un usuario o grupo de usuarios" se quedaba en negro sobre oscuro. */
.extension .sin-resultados-titulo,
.extension .mu-cargando-tabla {
    color: var(--abx-texto) !important;
}
.extension .sin-resultados-subtitulo {
    color: var(--abx-texto-2) !important;
}
.extension .sin-resultados-contenedor {
    background: transparent !important;
}
:root[data-tema="oscuro"] .extension .fila-sin-resultados td,
:root[data-tema="oscuro"] .extension .fila-sin-resultados {
    background-color: var(--abx-blanco) !important;
}

/* ---- Fichas de acceso y de relé ----------------------------------------
   Son elementos dentro de una tarjeta: van un tono por encima de ella, con su
   filete, para que se lean como fichas y no como texto suelto. */
:root[data-tema="oscuro"] .acceso-fijo-nombre,
:root[data-tema="oscuro"] .sel-acceso-nombre,
:root[data-tema="oscuro"] .rele-fijo-nombre {
    background-color: var(--abx-campo) !important;
    border: 1px solid rgba(255, 255, 255, 0.08) !important;
    border-radius: var(--abx-r-s) !important;
    color: var(--abx-texto) !important;
}


/* ============================================================================
   35. EL VELO DE "COMPROBANDO PERMISOS"
   ----------------------------------------------------------------------------
   Traspaso de datos levanta un velo a pantalla completa mientras comprueba si
   eres ROOT, y lo crea desde JavaScript con el color escrito en el propio
   elemento: `background: rgba(245,245,247,0.98)`. Casi blanco, a pantalla
   completa y por encima de todo — en oscuro deslumbra, tal cual.

   Este es justo el caso del que te avisé: color en el atributo `style`, que
   ninguna hoja alcanza por las buenas. Aquí sí se puede, porque el elemento
   tiene id y con `!important` una regla de hoja gana a un estilo en línea.
   ============================================================================ */
:root[data-tema="oscuro"] #tspVeloAcceso {
    background: rgba(10, 12, 15, 0.97) !important;
    color: var(--abx-texto-2) !important;
}
:root[data-tema="oscuro"] #tspVeloAcceso div {
    color: var(--abx-texto) !important;
}

/* En claro también conviene: el velo iba a un gris distinto al del panel. */
#tspVeloAcceso {
    background: rgba(238, 239, 242, 0.97) !important;
    -webkit-backdrop-filter: blur(3px);
            backdrop-filter: blur(3px);
}


/* ============================================================================
   36. EL AGUJERO DEL GRÁFICO CIRCULAR
   ----------------------------------------------------------------------------
   El centro del donut se dibujaba con el color escrito en el propio SVG
   (`fill="#ffffff"`), igual que su número y su etiqueta. Intenté alcanzarlo
   por selector de atributo y no era fiable. La solución buena es no tener el
   color ahí: les he puesto una clase en dashboard-versiones.php y el color lo
   decide el CSS, que es quien sabe en qué tema estamos.
   ============================================================================ */
.dv-hueco        { fill: #ffffff; }
.dv-cifra-centro { fill: #1c1c1e; }
.dv-cifra-sub    { fill: #6e6e73; }

:root[data-tema="oscuro"] .dv-hueco        { fill: var(--abx-blanco); }
:root[data-tema="oscuro"] .dv-cifra-centro { fill: var(--abx-texto); }
:root[data-tema="oscuro"] .dv-cifra-sub    { fill: var(--abx-texto-2); }


/* ============================================================================
   37. LOS CONTROLES DEL MAPA EN MODO OSCURO

   Los botones de zoom y el de pantalla completa se pintan en mapa-ubicaciones
   con rgba(255,255,255,0.94). El barrido automatico de la seccion 31 solo
   reconoce colores hexadecimales, asi que esos tres botones seguian siendo
   pastillas blancas sobre un mapa oscuro. Aqui se les da el mismo cristal
   translucido que al resto del panel, con su borde y su sombra propios.
   ============================================================================ */

:root[data-tema="oscuro"] #mpMapa .leaflet-control-zoom {
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.55) !important;
    border: 1px solid rgba(255, 255, 255, 0.10) !important;
}

:root[data-tema="oscuro"] #mpMapa .leaflet-control-zoom a,
:root[data-tema="oscuro"] .mp-btn-pantalla {
    background: rgba(33, 38, 48, 0.92) !important;
    -webkit-backdrop-filter: saturate(180%) blur(12px);
    backdrop-filter: saturate(180%) blur(12px);
    color: var(--abx-texto) !important;
}

:root[data-tema="oscuro"] .mp-btn-pantalla {
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.55) !important;
    border: 1px solid rgba(255, 255, 255, 0.10) !important;
}

/* La linea que separa el "+" del "−" la dibuja Leaflet con un borde gris
   claro; en oscuro se veia como un corte blanco. */
:root[data-tema="oscuro"] #mpMapa .leaflet-control-zoom a.leaflet-control-zoom-in {
    border-bottom: 1px solid rgba(255, 255, 255, 0.10) !important;
}

:root[data-tema="oscuro"] #mpMapa .leaflet-control-zoom a:hover,
:root[data-tema="oscuro"] .mp-btn-pantalla:hover {
    background: rgba(48, 55, 68, 0.96) !important;
    color: var(--abx-azul) !important;
}

/* Zoom al limite: Leaflet le pone la clase "disabled" y un gris muy claro. */
:root[data-tema="oscuro"] #mpMapa .leaflet-control-zoom a.leaflet-disabled {
    background: rgba(28, 32, 40, 0.92) !important;
    color: rgba(232, 234, 237, 0.28) !important;
}

/* El icono de pantalla completa es un SVG que hereda el color del boton. */
:root[data-tema="oscuro"] .mp-btn-pantalla svg { color: inherit; }


/* ============================================================================
   38. EL PIE DE ESTADÍSTICAS EN MODO OSCURO

   Bloque nuevo ("Datos del ... · Actualizar datos"), asi que el barrido de
   la seccion 31 no lo conocia.
   ============================================================================ */

:root[data-tema="oscuro"] .ed-pie-t { color: var(--abx-texto-2); }

:root[data-tema="oscuro"] .ed-boton-pie {
    color: var(--abx-azul);
    border-color: rgba(88, 166, 220, 0.30);
    background: transparent;
}

:root[data-tema="oscuro"] .ed-boton-pie:hover:not(:disabled) {
    background: rgba(88, 166, 220, 0.12);
    border-color: rgba(88, 166, 220, 0.55);
}


/* ============================================================================
   39. EL COLOR DE A7 EN MODO OSCURO

   A7 se pinta en gris pizarra (#4A5260). Sobre fondo claro se lee bien, pero
   sobre el lienzo oscuro desaparecia: sus barras, su punto de leyenda y su
   porcion del donut quedaban practicamente invisibles.

   El color lo escribe JavaScript en el atributo style, asi que la unica forma
   de sustituirlo desde aqui es con !important sobre el atributo data-m que
   ahora llevan esos elementos. Se usa el mismo gris pero aclarado, para que
   siga siendo "el gris" y no se confunda con ningun otro modelo.
   ============================================================================ */

:root[data-tema="oscuro"] [data-m="A7"] {
    background-color: #98A2B3 !important;   /* barras y puntos */
}

/* El donut es SVG: ahi el color va en "fill", no en "background". */
:root[data-tema="oscuro"] path[data-m="A7"],
:root[data-tema="oscuro"] circle[data-m="A7"] {
    background-color: transparent !important;
    fill: #98A2B3 !important;
}

/* "Otros / no reconocido" (#9aa0aa) queda demasiado cerca del A7 aclarado:
   se separa un poco hacia el frio apagado. */
:root[data-tema="oscuro"] .ed-dg-p[style*="#9aa0aa"] {
    background-color: #6B7280 !important;
}


/* ============================================================================
   40. SEGUNDO REPASO DEL MENÚ LATERAL

   Lo que fallaba mirándolo con calma:

   a) Dos píldoras azules encajadas. Cuando estás en "Mis intercoms", PHP marca
      como `selected` tanto el apartado "Intercom" como el enlace de dentro, y
      las dos se pintaban con fondo azul y filete. El resultado es una caja
      dentro de otra caja, y la vista no sabe cuál de las dos es la página en
      la que estás.
      Ahora: el apartado abierto solo cambia de COLOR (azul, semibold) y la
      píldora se la queda el enlace concreto, que es el que de verdad dice
      dónde estás. Un apartado marcado con su submenú cerrado sí conserva la
      píldora, porque ahí no compite con nada.

   b) Los sub-enlaces flotaban sin nada que los atara a su apartado. Se añade
      un hilo vertical por la izquierda: es el recurso de siempre para decir
      "esto cuelga de lo de arriba" sin dibujar una caja.

   c) Los puntitos de cada sub-enlace tenían todos el mismo peso. Ahora el
      activo es un punto azul sólido que se apoya en el hilo, y los demás se
      quedan atrás.
   ============================================================================ */

/* --- a) El apartado abierto cede el protagonismo ------------------------- */
.sidebar .dropdown:has(a.item.selected) > .dropdown-toggle.selected {
    background: transparent;
    border-color: transparent;
}
.sidebar .dropdown:has(a.item.selected) > .dropdown-toggle.selected:hover {
    background: rgba(16, 86, 128, 0.06);
}

/* --- b) El hilo del submenú --------------------------------------------- */
/* Medido en px y no en rem a proposito: el hilo y los puntos tienen que
   caer en el MISMO eje, y con rem cualquier cambio de tamaño de fuente los
   descuadraba. Cuentas: el enlace empieza en 22px (padding del ul), su
   punto a 2px con 5px de ancho -> el centro del punto cae en 26,5px. El
   hilo, de 1px, va de 26 a 27: mismo centro. */
.sidebar .dropdown-content ul {
    position: relative;
    padding-left: 22px;
}
.sidebar .dropdown-content ul::before {
    content: '';
    position: absolute;
    left: 26px;
    top: 0.45rem;
    bottom: 0.45rem;
    width: 1px;
    background: rgba(13, 27, 42, 0.11);
    border-radius: 1px;
}

/* --- c) Ritmo y puntos --------------------------------------------------- */
.sidebar li { margin: 0.1rem 0; }

.sidebar li a.item {
    padding: 0.52rem 0.9rem 0.52rem 20px;
    border-radius: 0.6rem;
    letter-spacing: -0.005em;
}

.sidebar li a.item::before {
    left: 2px;                   /* centro en 26,5px: justo sobre el hilo */
    width: 5px;
    height: 5px;
    background: var(--abx-linea);
    transition: background 0.18s ease, transform 0.18s ease, box-shadow 0.18s ease;
}

.sidebar li a.item:hover::before {
    background: var(--abx-texto-2);
}

.sidebar li a.item.selected {
    background: rgba(16, 86, 128, 0.09);
    font-weight: 600;
}

.sidebar li a.item.selected::before {
    background: var(--abx-azul);
    transform: translateY(-50%) scale(1.35);
    /* Un halo del color del menú: tapa el hilo justo detrás del punto, para
       que se vea el punto apoyado encima y no atravesado por la línea. */
    box-shadow: 0 0 0 3px var(--abx-blanco);
}

/* En modo oscuro el barrido de la sección 31 repinta el fondo del apartado,
   así que hay que repetirle aquí que el abierto va sin píldora. */
:root[data-tema="oscuro"] .sidebar .dropdown:has(a.item.selected) > .dropdown-toggle.selected {
    background: transparent !important;
    border-color: transparent !important;
}
:root[data-tema="oscuro"] .sidebar .dropdown:has(a.item.selected) > .dropdown-toggle.selected:hover {
    background: rgba(88, 166, 220, 0.10) !important;
}

/* El hilo, sobre fondo oscuro, con el contraste equivalente. */
:root[data-tema="oscuro"] .sidebar .dropdown-content ul::before {
    background: rgba(255, 255, 255, 0.13);
}

/* Separación entre apartados: la que había dejaba el menú apelmazado. */
.sidebar .dropdowns > .dropdown,
.sidebar .dropdowns > #dashboard {
    margin-bottom: 0.15rem;
}


/* ============================================================================
   41. EL LOGO EN MODO OSCURO

   El PNG del logo lleva la palabra "abrebox" en negro con un brillo claro
   dentro de cada letra y un borde blanco de antialias. Sobre fondo oscuro
   se leía fatal, y no hay filtro CSS que lo arregle: invertirlo deja las
   letras huecas (el brillo interior se vuelve oscuro) y aclararlo del todo
   se come también el azul del icono.

   Se ha generado una variante, img/logo_nuevo_oscuro.png, con la palabra
   rellena en plano (blanco roto arriba, gris en "INTERCOM") y el icono azul
   intacto. Aquí solo se sustituye la imagen; sidebar.php no se toca.
   ============================================================================ */

/* --- Logo en modo oscuro, incrustado --------------------------------------
   Estaba como archivo aparte (img/logo_nuevo_oscuro.png) y llegaba roto: un
   PNG nuevo es un archivo mas que subir y al que ponerle permisos, y si falla
   cualquiera de las dos cosas el menu se queda con el icono de imagen rota.

   Va dentro del propio CSS como data: URI. No es un archivo, no se puede
   quedar atras al subir y no puede dar 403. Son 67 KB dentro de un fichero
   que el navegador ya cachea de todas formas.
   ------------------------------------------------------------------------ */
:root[data-tema="oscuro"] .logo-nuevo {
    content: url("data:image/webp;base64,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");
}


/* ============================================================================
   42. REMATES DE ESTA RONDA EN MODO OSCURO
   ============================================================================ */

/* El hilo del submenú y el halo del punto activo van con el color de la
   tarjeta, que en oscuro es otro. */
:root[data-tema="oscuro"] .sidebar li a.item.selected::before {
    box-shadow: 0 0 0 3px var(--abx-blanco);
}

/* Lista de versiones con scroll propio (dashboard-versiones). */
:root[data-tema="oscuro"] .dv-barras-lista {
    scrollbar-color: rgba(255, 255, 255, 0.20) transparent;
}
:root[data-tema="oscuro"] .dv-barras-lista::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.18);
}


/* ============================================================================
   43. (LIBRE)

   Aquí estaban las correcciones de la tabla de "Otros / no reconocidos" en
   modo oscuro. Esa tabla ya no existe: ahora es una tarjeta de barras igual
   que las de los modelos, así que hereda el tratamiento de las demás y no
   necesita nada propio.
   ============================================================================ */

/* ============================================================================
   44. LOS BOTONES NEGROS EN MODO OSCURO

   `.boton-negro` (Restablecer contraseña y compañía) es negro sólido. Sobre el
   lienzo oscuro se convierte en un rectángulo invisible con texto flotando.

   En oscuro pasa a ser un botón de superficie elevada con filete, que es como
   se resuelve un secundario cuando el fondo ya es oscuro: mantiene su papel de
   "tercera opción, menos importante que Actualizar" sin desaparecer.
   ============================================================================ */

:root[data-tema="oscuro"] .boton-negro {
    background: var(--abx-campo) !important;
    color: var(--abx-texto) !important;
    border: 1px solid rgba(255, 255, 255, 0.12) !important;
}

:root[data-tema="oscuro"] .boton-negro:hover {
    background: var(--abx-campo-hover) !important;
    border-color: rgba(255, 255, 255, 0.22) !important;
}


/* ============================================================================
   45. EL FONDO, CON EL CONTRASTE DE ANTES

   El lienzo estaba en #EEEFF2, casi blanco. Las tarjetas son blancas, así que
   apenas se distinguían del fondo y la página se veía plana. Se vuelve al
   #E5E5E5 de siempre: un gris de verdad contra el que el blanco de las
   tarjetas destaca y se ve dónde empieza y acaba cada bloque.
   ============================================================================ */

:root {
    --abx-lienzo: #E5E5E5;
}


/* ============================================================================
   46. LOS TÍTULOS DE COLUMNA

   Estaban en gris medio (#6b7280) y a 0,8rem, con la idea de que el dato
   pesara más que la etiqueta. Pasada de frenada: parecían tener transparencia
   y las filas los tapaban. Un título de columna tiene que poder leerse de
   lejos, porque es por donde se busca.

   Ahora van en el mismo negro que los datos, un punto más pequeños, en
   versalitas y con algo de espaciado: se leen perfectamente y aun así no
   compiten con la cifra, porque el recurso que los distingue es la forma, no
   el desvanecerlos.
   ============================================================================ */

thead tr:first-child th,
thead tr:first-child th p {
    color: var(--abx-tinta) !important;
    font-size: 0.74rem !important;
    font-weight: 700 !important;
    letter-spacing: 0.04em !important;
    text-transform: uppercase;
}

:root[data-tema="oscuro"] thead tr:first-child th,
:root[data-tema="oscuro"] thead tr:first-child th p {
    color: var(--abx-texto) !important;
}

/* La cabecera necesita separarse del lienzo ahora que este es más oscuro. */
:root[data-tema="oscuro"] thead th {
    background: var(--abx-campo) !important;
}


/* ============================================================================
   47. EL BOTÓN DEL CORREO, EN LA BARRA SUPERIOR

   En oscuro llevaba un filete que no pinta nada: sobre fondo oscuro el propio
   cambio de superficie ya separa el botón, y el contorno lo convertía en una
   pastilla dibujada a mano.

   El icono era la silueta genérica de la librería. Se cambia por la misma
   persona que el apartado "Usuarios" del lateral, en su versión rellena, que
   es como se dibuja un avatar: una silueta sólida, no un contorno.
   ============================================================================ */

:root[data-tema="oscuro"] .dropdown-toggle-user {
    border-color: transparent !important;
    box-shadow: none !important;
}

/* Con el desplegable abierto sí hace falta la línea que separa la píldora
   de la lista; esa se mantiene. */
:root[data-tema="oscuro"] .boton-header.bordear .dropdown-toggle-user {
    border-bottom: 1px solid rgba(255, 255, 255, 0.10) !important;
}

.imagen-boton::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='%23000'%20stroke='none'%3E%3Ccircle%20cx='12'%20cy='8'%20r='3.6'/%3E%3Cpath%20d='M4.9%2020v-1.1a5.2%205.2%200%200%201%205.2-5.2h3.8a5.2%205.2%200%200%201%205.2%205.2V20z'/%3E%3C/svg%3E") !important;
            mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='%23000'%20stroke='none'%3E%3Ccircle%20cx='12'%20cy='8'%20r='3.6'/%3E%3Cpath%20d='M4.9%2020v-1.1a5.2%205.2%200%200%201%205.2-5.2h3.8a5.2%205.2%200%200%201%205.2%205.2V20z'/%3E%3C/svg%3E") !important;
}

/* Un pelín más pequeño: la silueta rellena pesa más que el contorno y con el
   mismo tamaño se comía el círculo. */
.imagen-boton::before {
    width: 0.95rem;
    height: 0.95rem;
}


/* ============================================================================
   49. "SOLO CONECTADOS" EN MODO OSCURO
   ============================================================================ */

:root[data-tema="oscuro"] .mp-solo-online {
    background: var(--abx-campo) !important;
    border-color: rgba(255, 255, 255, 0.12) !important;
    color: var(--abx-texto) !important;
}
:root[data-tema="oscuro"] .mp-solo-online:hover {
    border-color: rgba(255, 255, 255, 0.22) !important;
}
:root[data-tema="oscuro"] .mp-solo-online .mp-conteo { color: var(--abx-texto-2) !important; }
:root[data-tema="oscuro"] .mp-solo-online-luz { background: #4A5260 !important; }

:root[data-tema="oscuro"] .mp-solo-online.activo {
    background: rgba(45, 190, 90, 0.14) !important;
    border-color: rgba(45, 190, 90, 0.40) !important;
    color: #7BE09B !important;
}
:root[data-tema="oscuro"] .mp-solo-online.activo .mp-conteo { color: #7BE09B !important; }
:root[data-tema="oscuro"] .mp-solo-online.activo .mp-solo-online-luz {
    background: #34D964 !important;
}


/* ============================================================================
   50. LOS DOS GRISES: A7 Y "OTROS"

   A7 y "Otros" son los dos modelos sin color propio, así que los dos caen en
   la familia de los grises. El problema es distinguirlos entre sí sin que
   ninguno desaparezca sobre su fondo.

   Lo que NO funcionó:
   · Mismo gris en los dos temas: el gris oscuro de A7 se tragaba el fondo
     negro y "Otros" se perdía sobre el blanco.
   · Aclarar A7 con un gris azulado (#8FA8C4): sobre fondo oscuro parecía un
     A10Pro descolorido, porque compartía tono con el azul de la marca.

   Lo que se hace ahora: los dos son grises NEUTROS, sin pizca de azul, y lo
   que los separa es la CLARIDAD. "Otros" se va al extremo del tema —casi
   negro en claro, casi blanco en oscuro—, que además es lo suyo para algo
   que significa "esto no lo reconozco". A7 se queda a media distancia. Entre
   los dos hay unos 22 puntos de luminosidad en ambos temas: puestos uno al
   lado del otro no hay duda, y funciona igual para quien no distingue bien
   los colores, porque la diferencia no está en el tono.

   Los colores base (claro) van en el JavaScript de cada página; aquí solo se
   invierten para el tema oscuro.
   ============================================================================ */

/* A7: #3F454F en claro  ->  gris medio-claro neutro en oscuro */
:root[data-tema="oscuro"] [data-m="A7"] {
    background-color: #ACB2BC !important;
}
:root[data-tema="oscuro"] path[data-m="A7"],
:root[data-tema="oscuro"] circle[data-m="A7"] {
    background-color: transparent !important;
    fill: #ACB2BC !important;
}

/* Otros: #121417 (casi negro) en claro  ->  casi blanco en oscuro */
:root[data-tema="oscuro"] [data-m="Otros"] {
    background-color: #F2F4F7 !important;
}
:root[data-tema="oscuro"] path[data-m="Otros"],
:root[data-tema="oscuro"] circle[data-m="Otros"] {
    background-color: transparent !important;
    fill: #F2F4F7 !important;
}

/* El MAPA queda fuera de esto a propósito: allí los colores no van sobre el
   fondo de la página sino sobre las teselas, y un marcador casi negro sobre
   el mapa oscuro —o casi blanco sobre el claro— desaparecería. Sus modelos
   conservan el gris medio de siempre. */


/* ============================================================================
   51. LA BARRA DE FILTROS FLOTANTE, EN MODO OSCURO

   En pantalla completa los filtros se meten dentro de la tarjeta del mapa y
   flotan abajo a la izquierda. Sobre el mapa oscuro necesitan su propio
   cristal, no el blanco translúcido del tema claro.
   ============================================================================ */

:root[data-tema="oscuro"] .mp-tarjeta-mapa.mp-pantalla-completa .mp-cabecera {
    background: rgba(20, 24, 31, 0.82) !important;
    box-shadow: 0 6px 30px rgba(0, 0, 0, 0.60) !important;
    border: 1px solid rgba(255, 255, 255, 0.10);
}
:root[data-tema="oscuro"] .mp-tarjeta-mapa.mp-pantalla-completa .mp-filtro,
:root[data-tema="oscuro"] .mp-tarjeta-mapa.mp-pantalla-completa .mp-solo-online {
    background: rgba(255, 255, 255, 0.07) !important;
}
:root[data-tema="oscuro"] .mp-tarjeta-mapa.mp-pantalla-completa .mp-solo-online.activo {
    background: rgba(45, 190, 90, 0.16) !important;
}

/* La tarjeta en pantalla completa: el fondo blanco de base asomaba durante
   el instante en que Leaflet recalcula el tamaño. */
:root[data-tema="oscuro"] .mp-tarjeta-mapa.mp-pantalla-completa {
    background: var(--abx-lienzo) !important;
}


/* ============================================================================
   52. EL SELECTOR DE MAPA BASE, EN MODO OSCURO

   Es la pastilla de arriba a la izquierda del mapa (Claro / Oscuro /
   Detallado / Satélite). Su fondo es rgba(255,255,255,0.82), un blanco
   translúcido escrito a mano en mapa-ubicaciones, y el barrido automático
   del modo oscuro solo reconoce colores hexadecimales: por eso se quedaba
   como la única pieza clara de toda la pantalla.

   Recibe el mismo cristal oscuro que ya tienen los botones de zoom y el de
   pantalla completa, para que los cuatro controles del mapa sean del mismo
   material. La opción activa conserva el azul de la marca, aclarado lo justo
   para que se lea sobre el cristal oscuro.
   ============================================================================ */

:root[data-tema="oscuro"] .mp-selector-base {
    background: rgba(33, 38, 48, 0.88) !important;
    border: 1px solid rgba(255, 255, 255, 0.10);
    box-shadow: 0 2px 14px rgba(0, 0, 0, 0.55) !important;
}

:root[data-tema="oscuro"] .mp-base-opcion {
    color: var(--abx-texto-2) !important;
}
:root[data-tema="oscuro"] .mp-base-opcion:hover {
    color: var(--abx-texto) !important;
}

:root[data-tema="oscuro"] #mpSelectorBase .mp-base-opcion.activa {
    background: #2E88C4 !important;
    color: #FFFFFF !important;
    box-shadow: 0 1px 6px rgba(46, 136, 196, 0.50) !important;
}


/* ============================================================================
   53. SISTEMA DE MOVIMIENTO

   Hasta ahora el Dashboard tenía su propia animación de entrada, escrita a
   mano dentro de dashboard.php, y el resto de las páginas no tenían ninguna.
   De ahí que solo esa "se sintiera" bien hecha.

   Esto es lo que faltaba: un único sistema para todo el panel. Tres duraciones
   y dos curvas, y a partir de ahí todo lo que se mueve usa las mismas. Que las
   cosas se muevan con el mismo ritmo es justamente lo que hace que una
   interfaz parezca de una pieza y no un conjunto de pantallas sueltas.

   La curva es la misma que ya usaba el Dashboard —cubic-bezier(.22,1,.36,1)—:
   arranca rápido y frena despacio, que es como se mueven las cosas con masa.
   Nada aquí rebota: el rebote llama la atención, y una herramienta de trabajo
   que se usa ocho horas al día no debe llamar la atención.
   ============================================================================ */

:root {
    --abx-t-rapido: 120ms;   /* respuesta al dedo: pulsar, marcar */
    --abx-t-medio:  220ms;   /* cambios de estado: color, sombra, foco */
    --abx-t-lento:  360ms;   /* entradas y salidas de bloques */
    --abx-t-paso:    38ms;   /* separación entre elementos escalonados */
}

body {
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}


/* ============================================================================
   54. LA ENTRADA, EN CUALQUIER PÁGINA

   El problema era de cobertura: la regla anterior enumeraba SEIS clases de
   contenedor a mano, y el panel tiene once. "Nuevo admin", "Editar usuario",
   "Configuraciones" y compañía no estaban en la lista, así que aparecían de
   golpe. Y cualquier vista nueva habría nacido igual de seca.

   Ahora se apunta a la estructura y no a los nombres: el contenido de una
   página siempre cuelga de `.extension`, así que se animan los hijos del
   contenedor que haya dentro — se llame como se llame. Si una vista no tiene
   contenedor, se animan directamente los hijos de `.extension`.

   Y entran ESCALONADOS. Que todo aparezca a la vez es un efecto; que aparezca
   en cascada de arriba abajo acompaña a la vista, que es como se lee.
   ============================================================================ */

body.abx-listo .extension > [class*="contenedores"] > *,
body.abx-listo .extension:not(:has(> [class*="contenedores"])) > * {
    animation: abxEntrar var(--abx-t-lento) var(--abx-curva) backwards;
}

/* El escalonado. Se llega hasta el décimo bloque: más abajo ya no se ve al
   cargar, así que retrasarlo solo serviría para que tardara en aparecer si
   alguien baja rápido. */
body.abx-listo .extension > [class*="contenedores"] > *:nth-child(1),
body.abx-listo .extension:not(:has(> [class*="contenedores"])) > *:nth-child(1) { animation-delay: 0ms; }
body.abx-listo .extension > [class*="contenedores"] > *:nth-child(2),
body.abx-listo .extension:not(:has(> [class*="contenedores"])) > *:nth-child(2) { animation-delay: 38ms; }
body.abx-listo .extension > [class*="contenedores"] > *:nth-child(3),
body.abx-listo .extension:not(:has(> [class*="contenedores"])) > *:nth-child(3) { animation-delay: 76ms; }
body.abx-listo .extension > [class*="contenedores"] > *:nth-child(4),
body.abx-listo .extension:not(:has(> [class*="contenedores"])) > *:nth-child(4) { animation-delay: 114ms; }
body.abx-listo .extension > [class*="contenedores"] > *:nth-child(5),
body.abx-listo .extension:not(:has(> [class*="contenedores"])) > *:nth-child(5) { animation-delay: 150ms; }
body.abx-listo .extension > [class*="contenedores"] > *:nth-child(6),
body.abx-listo .extension:not(:has(> [class*="contenedores"])) > *:nth-child(6) { animation-delay: 180ms; }
body.abx-listo .extension > [class*="contenedores"] > *:nth-child(7),
body.abx-listo .extension:not(:has(> [class*="contenedores"])) > *:nth-child(7) { animation-delay: 205ms; }
body.abx-listo .extension > [class*="contenedores"] > *:nth-child(n+8),
body.abx-listo .extension:not(:has(> [class*="contenedores"])) > *:nth-child(n+8) { animation-delay: 225ms; }

/* Las filas de una tabla entran también, pero con dos diferencias
   importantes respecto a los bloques:

   1) SOLO OPACIDAD, sin desplazamiento. Mover un <tr> obliga al navegador a
      rehacer el reparto de la tabla en cada fotograma, y eso es de lo más caro
      que se le puede pedir. Era una de las cosas que se trababan.

   2) SOLO LAS OCHO PRIMERAS y muy seguidas. Doce filas animándose a la vez son
      doce capas que el navegador crea y destruye; en una tabla llena eso se
      nota. Las de más abajo no se ven al cargar de todas formas. */
body.abx-listo tbody tr:nth-child(-n+8) {
    animation: abxEntrarFila 260ms ease-out backwards;
}
body.abx-listo tbody tr:nth-child(1) { animation-delay: 40ms; }
body.abx-listo tbody tr:nth-child(2) { animation-delay: 58ms; }
body.abx-listo tbody tr:nth-child(3) { animation-delay: 76ms; }
body.abx-listo tbody tr:nth-child(4) { animation-delay: 94ms; }
body.abx-listo tbody tr:nth-child(5) { animation-delay: 112ms; }
body.abx-listo tbody tr:nth-child(6) { animation-delay: 130ms; }
body.abx-listo tbody tr:nth-child(7) { animation-delay: 148ms; }
body.abx-listo tbody tr:nth-child(8) { animation-delay: 166ms; }

@keyframes abxEntrarFila {
    from { opacity: 0; }
    to   { opacity: 1; }
}


/* ============================================================================
   55. RESPUESTA AL DEDO

   Lo que de verdad hace que una interfaz "se sienta" bien no es la animación
   de entrada —esa se ve una vez— sino lo que pasa cada vez que tocas algo.
   Un botón que no acusa la pulsación parece que no ha recibido el clic.

   Dos reglas y nada más: al pasar por encima sube un pelo, al pulsar se hunde.
   1 píxel y un 2% de escala; lo justo para notarlo sin que salte a la vista.

   OJO con dónde se aplica `transform`: un elemento transformado se convierte
   en el marco de referencia de sus descendientes `position: fixed`, y eso
   rompe menús y modales que cuelguen de él. Por eso va sobre una lista
   concreta de botones de acción y no sobre `button` a secas — los del menú
   lateral y el del correo llevan desplegables dentro.
   ============================================================================ */

.ed-boton,
.ed-kpi-boton,
.ed-boton-pie,
.mp-boton,
.mp-filtro,
.mp-solo-online,
.mp-base-opcion,
.boton-negro,
.dv-boton,
.extension button[type="submit"],
.extension .boton-principal,
.extension .boton-secundario {
    transition: transform var(--abx-t-rapido) var(--abx-curva),
                box-shadow var(--abx-t-medio) ease,
                background-color var(--abx-t-medio) ease,
                border-color var(--abx-t-medio) ease,
                color var(--abx-t-medio) ease;
}

.ed-boton:hover,
.ed-kpi-boton:hover,
.mp-boton:hover:not(:disabled),
.boton-negro:hover,
.dv-boton:hover,
.extension button[type="submit"]:hover:not(:disabled) {
    transform: translateY(-1px);
}

.ed-boton:active,
.ed-kpi-boton:active,
.ed-boton-pie:active,
.mp-boton:active:not(:disabled),
.mp-filtro:active,
.mp-solo-online:active,
.mp-base-opcion:active,
.boton-negro:active,
.dv-boton:active,
.extension button[type="submit"]:active:not(:disabled) {
    transform: scale(0.975);
    transition-duration: 60ms;   /* al pulsar, inmediato; al soltar, suave */
}

/* Los campos y los desplegables acompañan el foco en vez de saltar a él. */
.extension input,
.extension select,
.extension textarea {
    transition: border-color var(--abx-t-medio) ease,
                box-shadow var(--abx-t-medio) ease,
                background-color var(--abx-t-medio) ease;
}

/* Un aro de foco igual en todo el panel, solo para quien navega con teclado.
   `:focus-visible` no se dispara al hacer clic con el ratón, así que esto no
   ensucia el uso normal. */
.extension :focus-visible,
.sidebar :focus-visible,
.boton-header :focus-visible {
    outline: 2px solid var(--abx-azul);
    outline-offset: 2px;
    border-radius: 6px;
}


/* ============================================================================
   56. NADA DE ESTO SE MUEVE SI EL SISTEMA PIDE QUE NO

   macOS, Windows e iOS tienen un ajuste de accesibilidad para reducir el
   movimiento. Quien lo activa suele hacerlo porque las animaciones le marean.

   Se apagan las animaciones que hemos añadido, NO todas las del panel: el
   indicador de carga tiene que seguir girando, porque si se queda quieto
   parece que la página se ha colgado.
   ============================================================================ */

@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }

    body.abx-listo .extension > [class*="contenedores"] > *,
    body.abx-listo .extension:not(:has(> [class*="contenedores"])) > *,
    body.abx-listo tbody tr,
    body.abx-listo .extension {
        animation: none !important;
    }

    .ed-boton:hover, .ed-kpi-boton:hover, .mp-boton:hover, .boton-negro:hover,
    .dv-boton:hover, .extension button[type="submit"]:hover,
    .ed-boton:active, .ed-kpi-boton:active, .ed-boton-pie:active,
    .mp-boton:active, .mp-filtro:active, .mp-solo-online:active,
    .mp-base-opcion:active, .boton-negro:active, .dv-boton:active,
    .extension button[type="submit"]:active {
        transform: none;
    }
}


/* ============================================================================
   57. EL PASO DE UNA PÁGINA A OTRA

   El panel no es una aplicación de una sola página: cada elemento del menú
   recarga el navegador entero. Por eso, por muy bien que entre el contenido,
   entre pantalla y pantalla había un parpadeo — el menú y la cabecera, que son
   idénticos en las dos páginas, se destruían y se volvían a dibujar.

   Esto lo resuelve la API de transiciones de vista del navegador. Se le dice
   que el menú y la cabecera son "la misma cosa" en las dos páginas: el
   navegador las deja quietas y cruza solo el contenido. El resultado es que
   la estructura de la aplicación permanece y lo único que cambia es lo que
   tiene que cambiar, que es exactamente la sensación de una app nativa.

   No lleva JavaScript, y en los navegadores que aún no la implementan
   simplemente no pasa nada: se navega como siempre. Por eso se puede poner
   sin riesgo.
   ============================================================================ */

/* RETIRADA A PROPÓSITO.

   Aquí estaba la transición de vista entre páginas. Sobre el papel encajaba:
   dejar quietos el menú y la cabecera y cruzar solo el contenido.

   En la práctica choca de frente con la sección 58. El navegador funde la
   página vieja con el PRIMER PINTADO de la nueva, y ese primer pintado tiene
   el contenido oculto a propósito, porque aún no ha cargado. Resultado: se
   funde hacia una pantalla vacía y luego aparece el contenido. Justo el
   parpadeo que se quería evitar.

   Las dos cosas no pueden convivir tal cual, y de las dos la que de verdad
   arregla algo es ocultar el contenido hasta que está listo. Para recuperar
   esta, habría que revelar el contenido en el mismo instante del cruce, y eso
   solo tiene sentido en pantallas que no cargan datos — es decir, casi
   ninguna de este panel. */



/* ============================================================================
   58. EL RELEVO ENTRE LA CARGA Y EL CONTENIDO

   El problema, en orden de aparición: la página pintaba media interfaz, luego
   aparecía el indicador de carga tapándola a pantalla completa, y al terminar
   todo salía de golpe. Tres saltos donde debería haber uno.

   La causa es que el contenido ya estaba pintado antes de que su JavaScript
   mostrara el indicador. La animación de entrada no arreglaba eso: solo se
   aplica al terminar, así que hasta ese momento el contenido estaba a la
   vista, por debajo del velo.

   Ahora el contenido nace oculto y no se revela hasta que la vista está
   lista. La secuencia queda: marco (menú y cabecera) -> indicador, si esta
   pantalla carga datos -> contenido entrando en cascada.

   El menú y la cabecera NO se ocultan a propósito: son lo que dice que la
   aplicación ya está ahí. Ocultarlos dejaría la pantalla vacía.
   ============================================================================ */

html.abx-cargando .extension {
    opacity: 0;
    /* Mientras no se ve, no debe poder pulsarse por error. */
    pointer-events: none;
}

/* El velo de carga cubre desde el menú hacia la derecha, así que su color de
   fondo tiene que ser el del lienzo, no un blanco fijo. */
:root[data-tema="oscuro"] #cargando,
:root[data-tema="oscuro"] #cargando_usuarios,
:root[data-tema="oscuro"] #cargando_accesos {
    background-color: var(--abx-lienzo) !important;
}


/* ============================================================================
   59. LAS PANTALLAS DE FORMULARIO

   "Nuevo admin", "Nuevo panel", "Nuevo usuario", "Configuraciones" y demás no
   siguen la estructura de las pantallas de listado. Estas empiezan por
   `.contenedores-algo` colgando de `.extension`; las de formulario empiezan
   por `.espaciado-general`, y dentro va un <form>, luego las columnas y ya al
   fondo las tarjetas.

   La regla de la sección 54 sí las cogía, pero solo llegaba al primer nivel:
   animaba `.espaciado-general`, o sea la página ENTERA como un único bloque.
   Moverse todo a la vez y no moverse se parecen bastante — de ahí que
   pareciera que no tenían animación.

   Aquí se baja hasta donde están las piezas de verdad: las tarjetas. Y el
   escalonado va por posición dentro de su columna, que es lo que hace que las
   tarjetas que están a la misma altura entren juntas y las de debajo después
   — se lee como una página que se compone, no como una lista.
   ============================================================================ */

body.abx-listo .espaciado-general .contenedores,
body.abx-listo .espaciado-general .contenedores-botones {
    animation: abxEntrar var(--abx-t-lento) var(--abx-curva) backwards;
}

body.abx-listo .espaciado-general .contenedores:nth-child(1) { animation-delay: 0ms; }
body.abx-listo .espaciado-general .contenedores:nth-child(2) { animation-delay: 70ms; }
body.abx-listo .espaciado-general .contenedores:nth-child(3) { animation-delay: 140ms; }
body.abx-listo .espaciado-general .contenedores:nth-child(4) { animation-delay: 200ms; }
body.abx-listo .espaciado-general .contenedores:nth-child(n+5) { animation-delay: 250ms; }

/* La fila de botones va la última: primero se ve lo que hay que rellenar y
   luego con qué confirmarlo. */
body.abx-listo .espaciado-general .contenedores-botones { animation-delay: 300ms; }

/* Y se deja de animar el envoltorio, que era lo que producía el "bloque
   único". Las tarjetas de dentro ya se mueven solas. */
body.abx-listo .extension > .espaciado-general {
    animation: none;
}

@media (prefers-reduced-motion: reduce) {
    body.abx-listo .espaciado-general .contenedores,
    body.abx-listo .espaciado-general .contenedores-botones {
        animation: none !important;
    }
}


/* ============================================================================
   60. APAGAR LAS ANIMACIONES CUANDO YA HAN TERMINADO

   Este es el remate contra el parpadeo del final.

   Mientras un elemento se anima, el navegador lo saca a una capa propia para
   poder moverlo sin repintar el resto. Cuando la animación acaba, deshace esa
   capa y vuelve a dibujar el elemento con el procedimiento normal. El texto se
   vuelve a componer, y en esa fracción de segundo se ve un temblor.

   Con veinte elementos terminando en veinte instantes distintos, eso no es un
   temblor: es un chisporroteo.

   La solución es dejar de hacerlo de uno en uno. Cuando la última animación ha
   terminado —lo calcula el script de panel.php— se marca el <body> y aquí se
   retiran TODAS las animaciones de golpe. El navegador suelta todas las capas
   en un único recálculo, y un recálculo no se ve.

   No hay riesgo de que algo se quede invisible: al llegar aquí las animaciones
   ya han terminado, y su estado final es exactamente el natural del elemento.
   ============================================================================ */

body.abx-entrada-hecha .extension > [class*="contenedores"] > *,
body.abx-entrada-hecha .extension > * ,
body.abx-entrada-hecha .espaciado-general .contenedores,
body.abx-entrada-hecha .espaciado-general .contenedores-botones,
body.abx-entrada-hecha tbody tr {
    animation: none !important;
}

/* Durante la entrada, el texto se compone en escala de grises dentro de la
   capa. Fijarlo también fuera evita que cambie de grosor al soltarla: es la
   otra mitad del parpadeo, la que se ve en las letras. */
.extension [class*="contenedores"] > *,
.espaciado-general .contenedores {
    -webkit-font-smoothing: antialiased;
}


/* ============================================================================
   61. LA PANTALLA DE ACCESO

   Rehecha con el material de la pantalla de bienvenida del panel, que es la
   que mejor funciona: el mismo lienzo azul con la red de nodos dibujada por
   código, las mismas esquinas de 28px, la misma sombra y la misma tipografía.

   Lo que había antes —una pantalla completa de cristal oscuro sobre degradado—
   se veía bien por sí sola, pero era la ÚNICA pantalla del producto con ese
   lenguaje. Entrar y pasar al panel era cambiar de aplicación.

   Ahora la composición dice lo que toca: a la izquierda quién eres (la marca,
   con el fondo que ya usa el Dashboard), a la derecha lo único que hay que
   hacer aquí (dos campos y un botón). Y al entrar, el fondo gris y las
   esquinas redondeadas ya son los del panel.

   Todo cuelga de `.body-index`, así que no puede afectar al panel.
   ============================================================================ */

.body-index {
    background: #E5E5E5;
}

.body-index .login {
    height: auto;
    min-height: 100vh;
    background: #E5E5E5;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 2.5rem 1.5rem 1.5rem;
    box-sizing: border-box;
}

/* --- La tarjeta, en dos columnas ----------------------------------------- */
.body-index .lg-lienzo {
    width: 100%;
    max-width: 58rem;
    display: flex;
    background: #ffffff;
    border-radius: 28px;
    overflow: hidden;
    box-shadow: 0 18px 50px rgba(13, 27, 42, 0.18);
    animation: lgEntrar 0.62s cubic-bezier(0.22, 1, 0.36, 1) both;
}

@keyframes lgEntrar {
    from { opacity: 0; transform: translateY(16px); }
    to   { opacity: 1; transform: none; }
}

/* --- Columna de marca ---------------------------------------------------- */
.body-index .lg-marca {
    position: relative;
    flex: 1 1 50%;
    min-height: 29rem;
    padding: 3rem 2.8rem;
    box-sizing: border-box;
    display: flex;
    /* El logo y el nombre van centrados a media altura de la tarjeta azul:
       sin subtítulo debajo, apoyarlos en la base dejaba todo el peso abajo
       y un hueco muerto arriba. */
    align-items: center;
    /* El mismo degradado, ángulo y paradas que el lienzo del Dashboard. */
    background: linear-gradient(145deg, #0d1b2a 0%, #14324d 55%, #105680 100%);
}

.body-index #lgRed {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0.55;
}

.body-index .lg-marca-contenido {
    position: relative;
    z-index: 2;
}

.body-index .lg-icono {
    width: 2.9rem;
    height: auto;
    display: block;
    margin: 0 0 1.6rem;
    animation: lgEntrar 0.7s cubic-bezier(0.22, 1, 0.36, 1) 0.10s both;
}

.body-index .lg-eyebrow {
    margin: 0 0 0.7rem;
    font-size: 0.74rem;
    font-weight: 600;
    letter-spacing: 2.4px;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.78);
    animation: lgEntrar 0.7s cubic-bezier(0.22, 1, 0.36, 1) 0.16s both;
}

.body-index .lg-titulo {
    margin: 0 0 0.9rem;
    font-size: 2.6rem;
    line-height: 1.06;
    font-weight: 700;
    letter-spacing: -0.5px;
    color: #ffffff;
    animation: lgEntrar 0.7s cubic-bezier(0.22, 1, 0.36, 1) 0.22s both;
}

/* La palabra destacada con el mismo degradado de texto del Dashboard. */
.body-index .lg-acento {
    background: linear-gradient(90deg, #8fd3ff 0%, #ffffff 100%);
    -webkit-background-clip: text;
            background-clip: text;
    -webkit-text-fill-color: transparent;
}

/* Sin subtítulo debajo, el margen inferior del título desplazaba el grupo
   hacia arriba al centrarlo. Cuando el título es lo último, no lleva margen. */
.body-index .lg-titulo:last-child { margin-bottom: 0; }

.body-index .lg-subtitulo {
    margin: 0;
    max-width: 22rem;
    font-size: 0.95rem;
    line-height: 1.6;
    color: rgba(255, 255, 255, 0.78);
    animation: lgEntrar 0.7s cubic-bezier(0.22, 1, 0.36, 1) 0.28s both;
}

/* --- Columna del formulario ---------------------------------------------- */
.body-index .lg-acceso {
    flex: 1 1 50%;
    padding: 3rem 2.8rem;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    justify-content: center;
    background: #ffffff;
}

.body-index .lg-logo-movil { display: none; }

.body-index .lg-titulo-form {
    margin: 0 0 0.3rem;
    font-size: 1.45rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    color: #1c1c1e;
}

.body-index .lg-sub-form {
    margin: 0 0 1.9rem;
    font-size: 0.88rem;
    color: #6e6e73;
}

/* El contenedor del formulario deja de centrar: en un formulario se lee y se
   escribe de izquierda a derecha, y las etiquetas van encima de su campo. */
.body-index .formulario-index {
    display: block;
    margin: 0;
    gap: 0;
}

.body-index .lg-etiqueta {
    display: block;
    margin: 0 0 0.42rem;
    font-size: 0.8rem;
    font-weight: 600;
    color: #4b5563;
}

.body-index .formulario-index input {
    display: block;
    width: 100%;
    height: 2.85rem;
    box-sizing: border-box;
    margin: 0 0 1.05rem;
    padding: 0 0.95rem;
    text-align: left;
    font-size: 0.95rem;
    color: #1c1c1e;
    background: #F1F2F5;
    border: 1px solid transparent;
    border-radius: 12px;
    box-shadow: none;
    transition: background 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease;
}

.body-index .formulario-index input::placeholder { color: #9aa0aa; }

.body-index .formulario-index input:hover {
    background: #ECEEF2;
}

/* El foco se marca con un aro, no cambiando el relleno: así se ve cuál de los
   dos campos está activo aunque los dos tengan texto. */
.body-index .formulario-index input:focus,
.body-index .formulario-index input:focus-visible {
    outline: none;
    background: #ffffff;
    border-color: rgba(16, 86, 128, 0.55);
    box-shadow: 0 0 0 4px rgba(16, 86, 128, 0.12);
}

/* Autorrelleno de Chrome: pinta el campo de amarillo. Se neutraliza con una
   sombra interior del tamaño del campo. */
.body-index .formulario-index input:-webkit-autofill,
.body-index .formulario-index input:-webkit-autofill:hover,
.body-index .formulario-index input:-webkit-autofill:focus {
    -webkit-text-fill-color: #1c1c1e;
    -webkit-box-shadow: 0 0 0 1000px #F1F2F5 inset;
    transition: background-color 9999s ease-out;
}

/* --- El botón ------------------------------------------------------------- */
.body-index .formulario-index button[type="submit"] {
    display: block;
    width: 100%;
    height: 2.85rem;
    margin: 0.35rem 0 0;
    border: none;
    border-radius: 12px;
    font-size: 0.95rem;
    font-weight: 600;
    letter-spacing: 0.1px;
    color: #ffffff;
    cursor: pointer;
    background: #105680 !important;
    box-shadow: 0 8px 20px -8px rgba(6, 6, 6, 0.75);
    transition: background 0.18s ease, transform 0.14s cubic-bezier(0.22, 1, 0.36, 1),
                box-shadow 0.18s ease;
}

.body-index .formulario-index button:hover[type="submit"] {
    background: #0d466a !important;
    transform: translateY(-1px);
    box-shadow: 0 12px 26px -8px rgba(16, 86, 128, 0.8);
}

.body-index .formulario-index button:active[type="submit"] {
    transform: scale(0.985);
    transition-duration: 60ms;
}

/* --- "¿Has olvidado tu contraseña?" --------------------------------------- */
.body-index a.passForgot {
    display: inline-flex;
    justify-content: flex-start;
    margin-top: 1.1rem;
    font-size: 0.83rem;
    color: #6e6e73;
    transition: color 0.18s ease;
}
.body-index a.passForgot:hover { color: #105680; }

.body-index .login a img {
    height: 0.62rem;
    opacity: 0.5;
    /* El filtro de styles.css lo dejaba blanco, invisible sobre la tarjeta. */
    filter: none;
}
.body-index a.passForgot:hover img { opacity: 0.9; }

/* --- El pie --------------------------------------------------------------- */
.body-index .footer-index {
    position: static;
    margin: 1.6rem auto 0;
    opacity: 0.4;
    transition: opacity 0.25s ease;
}
.body-index .footer-index:hover { opacity: 0.65; }
.body-index .footer-index .logo2 {
    width: 7.5rem;
    /* El logo del pie es la versión blanca; sobre el lienzo gris hay que
       devolverlo a oscuro. */
    filter: brightness(0) saturate(100%) opacity(0.55);
}

/* --- Aviso de sesión caducada --------------------------------------------- */
.body-index #sessionExpiredBanner {
    background: #ffffff !important;
    color: #1c1c1e !important;
    border-bottom: 1px solid rgba(13, 27, 42, 0.10);
    box-shadow: 0 4px 16px rgba(13, 27, 42, 0.08) !important;
}
.body-index #sessionExpiredBanner button {
    background: rgba(13, 27, 42, 0.07) !important;
    color: #1c1c1e !important;
}

/* --- Pantallas estrechas --------------------------------------------------- */
/* Por debajo de este ancho la columna de marca dejaría el formulario en una
   rendija, así que se retira y en su lugar va el logo completo arriba. */
@media (max-width: 860px) {
    .body-index .lg-lienzo { flex-direction: column; max-width: 26rem; }
    .body-index .lg-marca { display: none; }
    .body-index .lg-acceso { padding: 2.4rem 1.8rem; }
    .body-index .lg-logo-movil {
        display: block;
        width: 11rem;
        height: auto;
        margin: 0 0 1.8rem;
    }
}

@media (prefers-reduced-motion: reduce) {
    .body-index .lg-lienzo,
    .body-index .lg-icono,
    .body-index .lg-eyebrow,
    .body-index .lg-titulo,
    .body-index .lg-subtitulo {
        animation: none;
    }
}

/* styles.css centra globalmente los <h1> y los <p> del login (viene de cuando
   la pantalla era una columna centrada). Aquí la composición es de izquierda a
   derecha, así que hay que devolverlos a su sitio uno por uno: si se pusiera
   `text-align: left` en el contenedor no bastaría, porque las reglas globales
   apuntan al elemento y ganan por especificidad. */
.body-index .lg-titulo,
.body-index .lg-eyebrow,
.body-index .lg-subtitulo,
.body-index .lg-titulo-form,
.body-index .lg-sub-form,
.body-index .lg-etiqueta {
    text-align: left;
}

/* El logo del pie es la versión blanca del logotipo; sobre el lienzo gris
   necesita volverse oscuro, y con algo más de cuerpo del que tenía. */
.body-index .footer-index { opacity: 1; }
.body-index .footer-index .logo2 {
    filter: brightness(0) saturate(100%);
    opacity: 0.38;
    transition: opacity 0.25s ease;
}
.body-index .footer-index:hover .logo2 { opacity: 0.6; }


/* ============================================================================
   62. LOS DOS ICONOS QUE SOLO EXISTEN EN EL PANEL DE ADMINISTRACIÓN

   El menú del panel normal tiene dos apartados que ROOT no tiene: "Avisos" y
   "Invitados". Se dibujan con el mismo trazo que los demás (lienzo de 24x24,
   línea de 1.7, extremos redondeados) y con la misma pareja: contorno cuando
   estás fuera del apartado, relleno cuando estás dentro.

   Avisos    -> una campana. Es el gesto universal de "algo que anunciar", y
                además es la figura del propio logotipo de Abrebox.
   Invitados -> una llave. Se evita a propósito dibujar otra persona: al lado
                de "Usuarios" dos siluetas humanas no se distinguen de un
                vistazo, y lo que un invitado recibe es justamente un acceso
                temporal, no una ficha de usuario.

   En ROOT estas reglas no pintan nada: esos dos identificadores no existen
   en su menú. Por eso pueden vivir en la capa compartida.
   ============================================================================ */

/* --- Avisos --------------------------------------------------------------- */
.sidebar #dropdownAvisos::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='1.7'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%20%3Cpath%20d='M5.9%209.4a6.1%206.1%200%200%201%2012.2%200c0%203.5.9%205%201.5%205.7a.6.6%200%200%201-.5%201H4.9a.6.6%200%200%201-.5-1c.6-.7%201.5-2.2%201.5-5.7z'/%3E%20%3Cpath%20d='M10.1%2018.7a2%202%200%200%200%203.8%200'/%3E%20%3C/svg%3E");
            mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='1.7'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%20%3Cpath%20d='M5.9%209.4a6.1%206.1%200%200%201%2012.2%200c0%203.5.9%205%201.5%205.7a.6.6%200%200%201-.5%201H4.9a.6.6%200%200%201-.5-1c.6-.7%201.5-2.2%201.5-5.7z'/%3E%20%3Cpath%20d='M10.1%2018.7a2%202%200%200%200%203.8%200'/%3E%20%3C/svg%3E");
}

.sidebar #dropdownAvisos.selected::before,
.sidebar .dropdown:has(a.item.selected) > #dropdownAvisos::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='%23000'%20stroke='none'%3E%20%3Cpath%20d='M5.9%209.4a6.1%206.1%200%200%201%2012.2%200c0%203.5.9%205%201.5%205.7a.6.6%200%200%201-.5%201H4.9a.6.6%200%200%201-.5-1c.6-.7%201.5-2.2%201.5-5.7z'/%3E%20%3Cpath%20d='M9.5%2018.1h5a2.5%202.5%200%200%201-5%200z'/%3E%20%3C/svg%3E");
            mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='%23000'%20stroke='none'%3E%20%3Cpath%20d='M5.9%209.4a6.1%206.1%200%200%201%2012.2%200c0%203.5.9%205%201.5%205.7a.6.6%200%200%201-.5%201H4.9a.6.6%200%200%201-.5-1c.6-.7%201.5-2.2%201.5-5.7z'/%3E%20%3Cpath%20d='M9.5%2018.1h5a2.5%202.5%200%200%201-5%200z'/%3E%20%3C/svg%3E");
}

/* --- Invitados ------------------------------------------------------------ */
.sidebar #dropdownInvitados::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='1.7'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%20%3Ccircle%20cx='7.7'%20cy='16.3'%20r='3.8'/%3E%20%3Cpath%20d='M10.4%2013.6%2019.9%204.1'/%3E%20%3Cpath%20d='M17.2%206.8l2.1%202.1'/%3E%20%3Cpath%20d='M14.7%209.3l1.7%201.7'/%3E%20%3C/svg%3E");
            mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='1.7'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%20%3Ccircle%20cx='7.7'%20cy='16.3'%20r='3.8'/%3E%20%3Cpath%20d='M10.4%2013.6%2019.9%204.1'/%3E%20%3Cpath%20d='M17.2%206.8l2.1%202.1'/%3E%20%3Cpath%20d='M14.7%209.3l1.7%201.7'/%3E%20%3C/svg%3E");
}

.sidebar #dropdownInvitados.selected::before,
.sidebar .dropdown:has(a.item.selected) > #dropdownInvitados::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='2.2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%20%3Cpath%20fill='%23000'%20stroke='none'%20fill-rule='evenodd'%20d='M7.7%2011.5a4.8%204.8%200%201%200%200%209.6%204.8%204.8%200%200%200%200-9.6zm0%203.2a1.6%201.6%200%201%201%200%203.2%201.6%201.6%200%200%201%200-3.2z'/%3E%20%3Cpath%20d='M10.4%2013.6%2019.9%204.1'/%3E%20%3Cpath%20d='M17.2%206.8l2.1%202.1'/%3E%20%3Cpath%20d='M14.7%209.3l1.7%201.7'/%3E%20%3C/svg%3E");
            mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='2.2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%20%3Cpath%20fill='%23000'%20stroke='none'%20fill-rule='evenodd'%20d='M7.7%2011.5a4.8%204.8%200%201%200%200%209.6%204.8%204.8%200%200%200%200-9.6zm0%203.2a1.6%201.6%200%201%201%200%203.2%201.6%201.6%200%200%201%200-3.2z'/%3E%20%3Cpath%20d='M10.4%2013.6%2019.9%204.1'/%3E%20%3Cpath%20d='M17.2%206.8l2.1%202.1'/%3E%20%3Cpath%20d='M14.7%209.3l1.7%201.7'/%3E%20%3C/svg%3E");
}


/* ============================================================================
   63. LOS REMATES DEL PANEL DE ADMINISTRACIÓN

   Tres cosas que solo se ven en el panel normal, porque su HTML no es igual
   que el de ROOT. Las reglas van en la capa compartida, pero cada una está
   anclada a algo que en ROOT no existe, así que allí no cambian nada.
   ============================================================================ */

/* ----------------------------------------------------------------------------
   a) EL INTERRUPTOR DE TEMA, AL FONDO DEL MENÚ

   El interruptor se añade como último hijo del menú. En ROOT eso ya lo dejaba
   abajo del todo, porque justo antes va `.sidebar-footer` (la palabra ROOT),
   que lleva `margin-top: auto` y se come el espacio libre.

   El menú del panel normal no tiene ese pie, así que el interruptor se
   quedaba pegado al último apartado, flotando en mitad de la columna. Como
   `.sidebar` ya es una columna flexible, basta con darle al interruptor el
   mismo `margin-top: auto`.

   La condición `:not(:has(.sidebar-footer))` es importante: si se aplicara
   también en ROOT, habría DOS elementos repartiendo el espacio libre a
   partes iguales y el interruptor subiría a media altura.
   ---------------------------------------------------------------------------- */
.sidebar:not(:has(.sidebar-footer)) .abx-tema {
    margin-top: auto;
}


/* ----------------------------------------------------------------------------
   b) CONFIGURACIÓN, EN MODO OSCURO

   Esta página trae su propio <style> dentro del PHP con los colores escritos
   a mano (#1c1c1e para el texto, #f1f1f3 para las píldoras). Al ir dentro del
   documento, ese bloque se lee DESPUÉS de esta hoja, así que para corregirlo
   no vale con repetir el selector: hay que ganarle en especificidad. Por eso
   cada regla lleva delante `:root[data-tema="oscuro"]` y repite el id.

   Lo que se veía mal: los dos rótulos de "Sub Administradores" eran texto
   casi negro sobre tarjeta oscura (invisibles), la línea de separación era
   negra sobre negro, y las píldoras de email habrían salido blancas.
   ---------------------------------------------------------------------------- */
:root[data-tema="oscuro"] #cfgSubAdmins .cfg-etiqueta {
    color: var(--abx-texto);
}

:root[data-tema="oscuro"] #cfgSeguridad .cfg-nota,
:root[data-tema="oscuro"] #cfgSubAdmins .cfg-nota {
    color: var(--abx-texto-2);
}

:root[data-tema="oscuro"] #cfgSubAdmins .cfg-pildora {
    background: var(--abx-campo);
    color: var(--abx-texto);
}

:root[data-tema="oscuro"] #cfgSubAdmins .cfg-separador {
    border-top-color: var(--abx-linea);
}


/* ----------------------------------------------------------------------------
   c) "RESTABLECER CONTRASEÑA", QUE ERA UN AGUJERO NEGRO

   El botón se pinta con `#cfgSeguridad #cfgResetPass { background:#1c1c1e
   !important }` en el propio PHP. Dos ids más un !important le ganan incluso
   a la regla general de `.boton-negro` en oscuro, así que en modo oscuro
   seguía siendo un rectángulo negro sobre una tarjeta oscura: se leía el
   texto flotando, pero no el botón.

   Aquí pasa a ser una superficie POR ENCIMA de la tarjeta, con filete, que es
   como se resuelve un botón secundario cuando el fondo ya es oscuro.
   ---------------------------------------------------------------------------- */
:root[data-tema="oscuro"] #cfgSeguridad #cfgResetPass {
    background: var(--abx-campo) !important;
    color: var(--abx-texto) !important;
    border: 1px solid rgba(255, 255, 255, 0.12) !important;
}

:root[data-tema="oscuro"] #cfgSeguridad #cfgResetPass:hover {
    background: var(--abx-campo-hover) !important;
    border-color: rgba(255, 255, 255, 0.22) !important;
}


/* ============================================================================
   64. LA PANTALLA DE ACCESO DE ROOT VA SOBRE FONDO OSCURO

   Los dos paneles comparten login.php y esta hoja, así que la pantalla de
   acceso era la misma en los dos sitios salvo por dos palabras. Para alguien
   que entra y sale de ambos, eso es medio segundo de duda cada vez.

   La señal más rápida que existe no es un texto, es el fondo: ROOT sobre
   negro, administración sobre el gris claro de siempre. Se distingue antes de
   leer nada, incluso de reojo. La tarjeta no cambia, así que sigue siendo
   evidentemente el mismo producto.

   Todo cuelga de `.body-root`, que solo lleva root/index.php.
   ============================================================================ */

.body-index.body-root,
.body-index.body-root .login {
    background: #0A0C0F;
}

/* Sobre negro, la sombra de antes no se ve: una sombra clara solo existe
   cuando hay algo más claro debajo. Se sustituye por una más profunda y
   abierta, que es lo que separa una tarjeta del fondo cuando el fondo ya es
   oscuro. */
.body-index.body-root .lg-lienzo {
    box-shadow: 0 28px 70px rgba(0, 0, 0, 0.65);
}

/* El logotipo del pie es la versión blanca. En claro se le da la vuelta a
   negro; aquí hay que dejarlo como nació, blanco y discreto. */
.body-index.body-root .footer-index .logo2 {
    filter: none;
    opacity: 0.28;
}
.body-index.body-root .footer-index:hover .logo2 {
    opacity: 0.5;
}


/* ============================================================================
   65. LOS DOS CARTELES DE SEGURIDAD

   a) El aviso del pie de la pantalla de acceso. Es corto a propósito: un
      párrafo largo no lo lee nadie. Va discreto, porque quien tiene derecho
      a entrar no necesita que le griten, y quien no lo tiene ya ha entendido
      el mensaje con leerlo una vez.

   b) El aviso de que la sesión va a cerrarse. Aparece arriba y centrado, por
      encima de todo, y se va solo en cuanto mueves el ratón.
   ============================================================================ */

/* El selector lleva `.body-index` delante por una razón concreta: styles.css
   trae `.login p { color:#ffffff; text-align:center; margin:0.75rem }` de
   cuando el fondo era una foto oscura. Esa regla vale dos (clase + elemento)
   y ganaba, así que el aviso salía blanco sobre blanco y solo se veía la
   parte en negrita. Con dos clases delante, gana esta. */
.body-index .lg-aviso-seguridad {
    margin: 1.6rem 0 0;
    padding-top: 1.1rem;
    border-top: 1px solid rgba(13, 27, 42, 0.09);
    font-size: 0.74rem;
    line-height: 1.5;
    text-align: left;
    color: #8a8f98;
}

.body-index .lg-aviso-seguridad strong {
    color: #5f646d;
    font-weight: 600;
}

.abx-aviso-inactividad {
    position: fixed;
    z-index: 100000;
    top: 1.1rem;
    left: 50%;
    transform: translateX(-50%);
    max-width: calc(100vw - 2rem);
    padding: 0.8rem 1.3rem;
    border-radius: 999px;
    background: #1c1c1e;
    color: #ffffff;
    font-size: 0.85rem;
    font-weight: 500;
    line-height: 1.3;
    text-align: center;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.30);
    animation: abxAvisoEntra 0.28s cubic-bezier(0.22, 1, 0.36, 1) both;
}

@keyframes abxAvisoEntra {
    from { opacity: 0; transform: translate(-50%, -12px); }
    to   { opacity: 1; transform: translate(-50%, 0); }
}

:root[data-tema="oscuro"] .abx-aviso-inactividad {
    background: #2F3540;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.6);
}

@media (prefers-reduced-motion: reduce) {
    .abx-aviso-inactividad { animation: none; }
}


/* ============================================================================
   66. EL AIRE BAJO EL TÍTULO CUANDO NO HAY SUBTÍTULO

   El título del formulario lleva un margen inferior muy corto (0.3rem) porque
   estaba pensado para tener justo debajo la línea "Introduce tus credenciales
   de administrador". Si esa línea se quita, el título se queda pegado a la
   primera etiqueta y las dos cosas se leen como un bloque.

   Este selector solo acierta cuando el <form> va INMEDIATAMENTE después del
   título, que es exactamente el caso "no hay subtítulo". Si la línea vuelve a
   ponerse, la regla deja de aplicar sola. No hace falta tocar nada.
   ============================================================================ */

.body-index .lg-titulo-form + form {
    margin-top: 1.5rem;
}


/* ============================================================================
   67. DOS CAMPOS EN UNA FILA  (tarjeta "Datos del excel", solo ROOT)

   Las tarjetas de formulario apilan etiqueta y campo, uno debajo de otro y a
   todo el ancho. Está bien para casi todo, pero un número de cuatro dígitos
   ocupando una línea entera parece un campo importante, y no lo es.

   `.dx-fila` pone dos campos en horizontal. Cada uno sigue siendo etiqueta
   encima y campo debajo, así que se leen igual que los demás; lo único que
   cambia es que comparten línea.

   El `min-width: 0` no es decorativo: sin él, un hijo de un contenedor flexible
   se niega a encogerse por debajo del ancho de su contenido y el segundo campo
   se sale de la tarjeta.

   Estas clases solo existen en nuevo-panel y editar-panel de ROOT, así que en
   el panel de administración estas reglas no pintan nada.
   ============================================================================ */

.dx-fila {
    display: flex;
    gap: 0.9rem;
    width: 100%;
    align-items: stretch;
}

.dx-fila .dx-campo {
    display: flex;
    flex-direction: column;
    flex: 1 1 0;
    min-width: 0;
}

/* Las dos columnas miden lo mismo. La tentación es estrechar la de las
   licencias porque el número es corto, pero entonces su etiqueta
   —"Licencias compradas:", que es la larga— se parte en dos líneas. Se
   reparte el ancho a medias y es el CAMPO, no la columna, el que se queda
   corto. */
.dx-fila .dx-campo > label,
.dx-fila .dx-campo > input,
.dx-fila .dx-campo > select {
    width: 100%;
    max-width: none;
    box-sizing: border-box;
}

/* El aire entre la etiqueta y su campo lo pone normalmente el margen superior
   del campo (12px). Aquí ese margen está ocupado por el `auto` que alinea la
   fila por abajo, así que la separación se la damos a la etiqueta. El
   resultado en pantalla es el mismo que en el resto del formulario. */
.dx-fila .dx-campo > label {
    margin-bottom: 0.75rem;
}

.dx-fila .dx-campo-corto > input {
    max-width: 8rem;
}

/* Los campos se alinean por ABAJO, no por arriba. Si una de las dos etiquetas
   acaba ocupando dos líneas —en una ventana estrecha, o si alguien alarga el
   texto— alinear por arriba dejaría un campo más bajo que el otro y la fila
   parecería rota. Con el margen automático, la etiqueta que sobra crece hacia
   arriba y los dos campos siguen a la misma altura. */
.dx-fila .dx-campo > input,
.dx-fila .dx-campo > select {
    margin-top: auto;
}

/* En cuanto la tarjeta se estrecha, la fila deja de tener sentido: dos campos
   en una rendija se leen peor que dos campos seguidos. */
@media (max-width: 720px) {
    .dx-fila { flex-direction: column; gap: 0; }
    .dx-fila .dx-campo,
    .dx-fila .dx-campo-corto { flex: 1 1 auto; }
}

/* El área de observaciones nace con sitio para cuatro líneas: si naciera con
   una, nadie escribiría más de una.

   Los márgenes se ponen a mano porque las reglas de siempre solo alcanzan a
   <input> y <select>: un <textarea> se quedaba pegado a su etiqueta y al
   borde de la tarjeta.

   Y no se puede estirar: arrastrando la esquina se descuadraba la tarjeta, y
   con cuatro líneas y 300 caracteres no hace ninguna falta. */
#observaciones {
    min-height: 6.5rem;
    margin-top: 0.75rem;
    margin-bottom: 1.25rem;
    resize: none;
}


/* ============================================================================
   68. LOS CAMPOS BLOQUEADOS, EN MODO OSCURO

   Un campo desactivado o de solo lectura se pinta con `rgba(13, 27, 42, 0.04)`:
   una pizca de azul oscuro al 4%. Sobre una tarjeta blanca eso es un gris
   suave, exactamente lo que se busca. Sobre una tarjeta oscura es NADA: un 4%
   de negro sobre un fondo ya oscuro no se distingue, y el campo desaparece.
   Quedaban flotando el texto y la flechita del desplegable, sin caja.

   Pasa en "Fotovigilancia (No tienes permiso)", en "Administrado por", en el
   contador de segundos del relé —que es de solo lectura, no desactivado— y en
   cualquier otro campo bloqueado del panel.

   En oscuro se invierte el gesto: en vez de oscurecer el fondo, se aclara un
   poco. Sigue distinguiéndose de un campo editable, que es más claro todavía,
   pero ya se ve que ahí hay una caja.
   ============================================================================ */

:root[data-tema="oscuro"] .extension input:disabled,
:root[data-tema="oscuro"] .extension select:disabled,
:root[data-tema="oscuro"] .extension textarea:disabled,
:root[data-tema="oscuro"] .extension input[readonly],
:root[data-tema="oscuro"] .extension textarea[readonly] {
    background-color: rgba(255, 255, 255, 0.055) !important;
    color: var(--abx-texto-3) !important;
    opacity: 1;
}


/* ============================================================================
   69. TRES REMATES DE LAS PANTALLAS DE PANEL
   ============================================================================ */

/* ----------------------------------------------------------------------------
   a) UN CAMPO BLOQUEADO SE LEE, AUNQUE NO SE TOQUE

   Hasta aquí el texto de un campo desactivado o de solo lectura usaba el tono
   más claro de la paleta, el de los pies de página y las marcas de agua. Sobre
   fondo blanco aún pasaba; sobre el lienzo oscuro, "A10Pro" o "2026.05.04" se
   quedaban a un paso de no leerse.

   El fallo estaba en el razonamiento, no en el color: un campo bloqueado no
   tiene por qué tener el CONTENIDO apagado. Lo que está apagado es la caja.
   Así que la caja sigue siendo más tenue que la de un campo editable —eso ya
   dice "esto no se toca"— y el texto sube al tono secundario, que se lee sin
   esfuerzo en los dos modos.

   `-webkit-text-fill-color` no es un adorno: Safari aplica su propio gris a los
   campos desactivados y se salta `color`. Sin esa línea, en el Mac se seguía
   viendo mal.
   ---------------------------------------------------------------------------- */
.extension input:disabled,
.extension select:disabled,
.extension textarea:disabled,
.extension input[readonly],
.extension textarea[readonly] {
    color: var(--abx-texto-2) !important;
    -webkit-text-fill-color: var(--abx-texto-2) !important;
}

/* El texto de ejemplo sí se queda atrás: no es contenido, es una pista. */
.extension input:disabled::placeholder,
.extension textarea:disabled::placeholder,
.extension input[readonly]::placeholder,
.extension textarea[readonly]::placeholder {
    color: var(--abx-texto-3) !important;
    -webkit-text-fill-color: var(--abx-texto-3) !important;
}


/* ----------------------------------------------------------------------------
   b) "ELIMINAR RELÉ" DEJA DE PARECER UN BOTÓN PRINCIPAL

   Era un rectángulo blanco a todo el ancho con el texto en cursiva: pesaba más
   que el propio relé que borra, y en una tarjeta oscura resultaba un bloque
   claro que se lleva la vista antes que nada.

   Pasa a ser lo que ya es "Eliminar acceso" en la ficha de un propietario: un
   texto rojo debajo de su bloque. Una acción destructiva tiene que estar a
   mano, pero no puede competir con la acción principal de la pantalla.
   ---------------------------------------------------------------------------- */
.extension .eliminar-rele {
    display: inline-block !important;
    width: auto !important;
    min-width: 0 !important;
    height: auto !important;
    min-height: 0 !important;
    margin: 0.1rem 0 1rem !important;
    padding: 0 !important;
    background: none !important;
    border: none !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    color: var(--abx-rojo-texto) !important;
    font-style: normal !important;
    font-weight: 600 !important;
    font-size: 0.85rem !important;
    line-height: 1.4 !important;
    text-align: left !important;
    cursor: pointer;
    transition: opacity 0.16s ease;
}

.extension .eliminar-rele:hover {
    opacity: 0.75;
    background: none !important;
    box-shadow: none !important;
    transform: none !important;
    text-decoration: underline !important;
    text-underline-offset: 2px;
}


/* ----------------------------------------------------------------------------
   c) EL ESTADO DE CONEXIÓN, DE UN VISTAZO

   El campo ya escribía "Online" u "Offline desde ...", pero en gris de campo
   bloqueado: había que leerlo para enterarse. Es el dato que más rápido se
   quiere saber al abrir un panel, y el color lo dice antes que la palabra.

   Se pinta desde aquí y no con `.css('color', ...)` desde el JavaScript porque
   un verde fijo que funciona sobre blanco no funciona sobre negro; así cada
   modo tiene el suyo. El JavaScript solo marca el estado con un atributo.
   ---------------------------------------------------------------------------- */
.extension #ultimavez[data-estado] {
    font-weight: 600 !important;
}

.extension #ultimavez[data-estado="online"] {
    background-color: rgba(27, 127, 75, 0.12) !important;
    color: #1B7F4B !important;
    -webkit-text-fill-color: #1B7F4B !important;
}

.extension #ultimavez[data-estado="offline"] {
    background-color: rgba(194, 24, 7, 0.10) !important;
    color: #C21807 !important;
    -webkit-text-fill-color: #C21807 !important;
}

:root[data-tema="oscuro"] .extension #ultimavez[data-estado="online"] {
    background-color: rgba(74, 222, 128, 0.14) !important;
    color: #4ADE80 !important;
    -webkit-text-fill-color: #4ADE80 !important;
}

:root[data-tema="oscuro"] .extension #ultimavez[data-estado="offline"] {
    background-color: rgba(255, 107, 107, 0.14) !important;
    color: #FF8A8A !important;
    -webkit-text-fill-color: #FF8A8A !important;
}


/* ============================================================================
   70. AJUSTES DE COLOR Y PESO EN MODO OSCURO
   ============================================================================ */

/* ----------------------------------------------------------------------------
   a) EL AZUL DEL BOTÓN PRINCIPAL

   En oscuro, `--abx-azul` es #58A6DC: un azul aclarado a propósito para que un
   TEXTO azul se lea sobre fondo negro. Pero el mismo valor usado como RELLENO
   de un botón grande da una mancha luminosa que se lleva toda la pantalla: lo
   que en texto es contraste, en un bloque de 400px es deslumbramiento.

   Un botón relleno en oscuro necesita el camino contrario: azul más profundo y
   el texto en blanco. El token no se toca, porque lo usan enlaces y el menú,
   donde sí hace falta claro.
   ---------------------------------------------------------------------------- */
:root[data-tema="oscuro"] .boton-guardar,
:root[data-tema="oscuro"] .boton-guardar-enviar {
    background: #17679A !important;
    color: #FFFFFF !important;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.35),
                0 8px 20px rgba(0, 0, 0, 0.30);
}

:root[data-tema="oscuro"] .boton-guardar:hover,
:root[data-tema="oscuro"] .boton-guardar-enviar:hover {
    background: #1B7AB4 !important;
}


/* ----------------------------------------------------------------------------
   b) EL BOTÓN DE ELIMINAR

   Tenía el mismo rojo al 8% que en modo claro. Sobre blanco eso es un rosa
   pálido que se lee; sobre el lienzo oscuro es casi negro, y el texto rojo
   encima quedaba apagado, más marrón que rojo. Una acción destructiva tiene
   que leerse como tal.
   ---------------------------------------------------------------------------- */
:root[data-tema="oscuro"] .boton-eliminar {
    background: rgba(255, 107, 107, 0.13) !important;
    color: #FF8080 !important;
    box-shadow: inset 0 0 0 1px rgba(255, 107, 107, 0.30) !important;
}

:root[data-tema="oscuro"] .boton-eliminar:hover {
    background: #C0342F !important;
    color: #FFFFFF !important;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.35),
                0 10px 24px rgba(0, 0, 0, 0.30) !important;
}


/* ----------------------------------------------------------------------------
   c) "CONSULTAR MOVIMIENTOS", SIN FILETE

   El filete se lo pone la regla general de los botones negros en oscuro, donde
   sirve para despegarlos del fondo. Aquí no hace falta: el botón está entre
   otros dos y ya se distingue por su color.
   ---------------------------------------------------------------------------- */
:root[data-tema="oscuro"] .extension a.consultar-movimientos.boton-negro,
:root[data-tema="oscuro"] a.consultar-movimientos.boton-negro {
    border-color: transparent !important;
}


/* ----------------------------------------------------------------------------
   d) "ELIMINAR RELÉ", PEGADO A SU RELÉ

   El campo de arriba cierra con 20px de margen inferior, pensados para separar
   un campo del siguiente. Pero esto no es el campo siguiente: es la acción de
   ESE bloque, y tenía que ir junto a él, como "Eliminar acceso" en la ficha de
   un propietario. Se recupera ese hueco con un margen negativo.
   ---------------------------------------------------------------------------- */
.extension .eliminar-rele {
    margin-top: -0.8rem !important;
    margin-bottom: 1.1rem !important;
}


/* ----------------------------------------------------------------------------
   e) LOS PUNTOS DE LA LEYENDA DE MODELOS

   Un punto de 10px de diámetro no tiene sitio para defenderse: si su color se
   parece al fondo, desaparece. A7 es gris y "Otros" es casi negro, así que
   sobre un lienzo oscuro se borraban los dos.

   Además de subirles el tono en oscuro (eso ya estaba), se le pone a TODOS un
   aro finito del color del texto. No se ve como un borde: lo que hace es que
   ningún punto pueda fundirse con lo que tenga detrás, sea cual sea el fondo
   de la tarjeta donde acabe la leyenda.
   ---------------------------------------------------------------------------- */
.ed-dg-p {
    box-shadow: 0 0 0 1px rgba(13, 27, 42, 0.20);
}

:root[data-tema="oscuro"] .ed-dg-p {
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.35);
}

/* Se repiten con más peso que la sección 50 por si el color en línea del
   JavaScript llega después: dos atributos ganan a uno. */
:root[data-tema="oscuro"] span.ed-dg-p[data-m="A7"] {
    background-color: #ACB2BC !important;
}

:root[data-tema="oscuro"] span.ed-dg-p[data-m="Otros"] {
    background-color: #F2F4F7 !important;
}


/* ============================================================================
   71. LA GRÁFICA DE ALTAS POR AÑO  (Estadísticas, solo ROOT)

   Seis barras dibujadas con un <svg> escrito a mano. No hay libreria de
   graficas de por medio a proposito: traer 300 KB para dibujar seis
   rectangulos es cargar un camion para llevar una caja, y esta pagina se abre
   desde el movil tan a menudo como desde el escritorio.

   Las dos series comparten escala. Si cada una tuviera la suya, dos barras de
   la misma altura estarian diciendo cosas distintas, que es la forma mas
   comun de mentir con una grafica sin proponerselo.
   ============================================================================ */

#edAltas {
    width: 100%;
}

.ed-altas-svg {
    display: block;
    width: 100%;
    max-height: 15rem;
    margin: 0.4rem 0 0;
    overflow: visible;
}

.ed-altas-b-intercoms  { fill: #105680; }
.ed-altas-b-propietarios { fill: #1d7e37; }

:root[data-tema="oscuro"] .ed-altas-b-intercoms   { fill: #3E8FC4; }
:root[data-tema="oscuro"] .ed-altas-b-propietarios { fill: #3FA95C; }

/* La cifra encima de cada barra y el año debajo. Se escriben dentro del SVG,
   asi que no heredan la tipografia de la pagina y hay que decirsela. */
.ed-altas-n,
.ed-altas-a {
    font-family: inherit;
    text-anchor: middle;
}

.ed-altas-n {
    font-size: 12px;
    font-weight: 600;
    fill: var(--abx-texto);
}

.ed-altas-a {
    font-size: 12px;
    font-weight: 500;
    fill: var(--abx-texto-2);
}

.ed-altas-leyenda {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem 1.1rem;
    margin: 0.9rem 0 0;
    font-size: 0.8rem;
    color: var(--abx-texto-2);
}

.ed-altas-leyenda span {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
}

.ed-altas-p {
    width: 0.62rem;
    height: 0.62rem;
    border-radius: 50%;
    flex: 0 0 auto;
}

.ed-altas-p-intercoms    { background: #105680; }
.ed-altas-p-propietarios { background: #1d7e37; }

:root[data-tema="oscuro"] .ed-altas-p-intercoms    { background: #3E8FC4; }
:root[data-tema="oscuro"] .ed-altas-p-propietarios { background: #3FA95C; }

.ed-altas-aviso {
    color: var(--abx-texto-3);
    font-size: 0.76rem;
}


/* ============================================================================
   72. LOS ANILLOS  (Estadísticas, solo ROOT)

   Un anillo y no un sector macizo: comparar dos ángulos que salen del mismo
   centro es fácil, comparar dos áreas no lo es. Y el hueco del medio no es
   decoración, es donde va el dato que de verdad se busca.

   Solo dos porciones (tres como mucho). Un anillo con cinco trozos es un
   gráfico bonito y una tabla mala.
   ============================================================================ */

/* El conjunto (anillo + leyenda) va centrado en la tarjeta.

   Pegado a la izquierda dejaba medio ancho de tarjeta vacio a la derecha y
   parecia que faltaba algo por cargar. Se centra el grupo entero, no cada
   cosa por su lado: el anillo y su leyenda se leen juntos, y separarlos para
   repartirlos por la tarjeta rompe esa lectura. */
.ed-anillo {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1.6rem;
    flex-wrap: wrap;
    margin-top: 0.8rem;
    margin-bottom: 0.2rem;
}

.ed-anillo-svg {
    width: 8.75rem;
    height: 8.75rem;
    flex: 0 0 auto;
}

.ed-anillo-arco { transition: stroke 0.2s ease; }

/* El color sale de la POSICION, y por eso el orden de las porciones no es
   decorativo: es lo que fija que Abrebox salga azul y HONOACALL verde. Tener
   ademas clases con nombre de marca era un segundo mecanismo para lo mismo,
   y ademas obligaba a tener esta hoja al dia para que el anillo se viera. */
.ed-anillo-0 { stroke: #105680; background: #105680; }
.ed-anillo-1 { stroke: #1d7e37; background: #1d7e37; }
.ed-anillo-2 { stroke: #9aa0aa; background: #9aa0aa; }

:root[data-tema="oscuro"] .ed-anillo-0 { stroke: #3E8FC4; background: #3E8FC4; }
:root[data-tema="oscuro"] .ed-anillo-1 { stroke: #3FA95C; background: #3FA95C; }
:root[data-tema="oscuro"] .ed-anillo-2 { stroke: #767E8B; background: #767E8B; }


.ed-anillo-cifra,
.ed-anillo-sub {
    font-family: inherit;
    text-anchor: middle;
}

.ed-anillo-cifra {
    font-size: 21px;
    font-weight: 700;
    fill: var(--abx-texto);
}

.ed-anillo-sub {
    font-size: 10px;
    font-weight: 500;
    fill: var(--abx-texto-2);
}

.ed-anillo-leyenda {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    font-size: 0.85rem;
    color: var(--abx-texto-2);
    min-width: 8rem;
}

.ed-anillo-leyenda span {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.ed-anillo-leyenda b {
    margin-left: auto;
    color: var(--abx-texto);
    font-weight: 600;
}

.ed-anillo-p {
    width: 0.62rem;
    height: 0.62rem;
    border-radius: 50%;
    flex: 0 0 auto;
    box-shadow: 0 0 0 1px rgba(13, 27, 42, 0.18);
}

:root[data-tema="oscuro"] .ed-anillo-p {
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.30);
}


/* ============================================================================
   73. EL BUSCADOR Y LA TARJETA DE RESUMEN, DEL MISMO ANCHO

   La tarjeta salia mas corta que el buscador de encima y el escalon cantaba.
   No era medio rem de diferencia: el input es `content-box`, asi que a sus
   21rem hay que sumarles los 3.5rem de relleno (la lupa ocupa 2.5rem a la
   izquierda) y ocupaba 24.5rem de verdad, contra los 20.5rem de la tarjeta.

   En vez de volver a cuadrar dos numeros a mano -que es lo que se descuadra
   al primer cambio- los dos salen ahora del mismo sitio: el input pasa a
   `border-box`, que hace que su `width` sea por fin lo que mide, y ambos
   toman la misma medida. Cambiar el ancho del listado es cambiar un numero.
   ============================================================================ */

:root {
    --abx-ancho-listado: 24.5rem;
}

.extension input.input-buscar {
    box-sizing: border-box !important;
    width: var(--abx-ancho-listado) !important;
    max-width: 100% !important;
}

.extension .stats-box {
    max-width: var(--abx-ancho-listado);
    width: 100%;
}

/* En pantallas estrechas los dos ocupan el ancho disponible, como ya hacia
   la tarjeta por su cuenta. */
@media (max-width: 900px) {
    .extension input.input-buscar,
    .extension .stats-box {
        width: 100% !important;
        max-width: 100%;
    }
}

/* El dato dentro de la tarjeta era un rectangulo gris claro con texto oscuro
   escrito a mano, asi que en modo oscuro salia como una pastilla blanca
   dentro de una tarjeta negra. */
:root[data-tema="oscuro"] .stat-item {
    background: rgba(255, 255, 255, 0.06);
    color: var(--abx-texto);
}


/* ============================================================================
   74. EL PIE DE LA COLUMNA AZUL DEL LOGIN

   Misma letra y mismo alpha que "Área privada": es el mismo registro, texto
   de apoyo sobre el lienzo, y dos grises distintos para lo mismo se notan.

   Va colgado de la base con position:absolute y no como un hermano en el
   flujo, porque .lg-marca centra su contenido a media altura: metido en el
   flujo empujaría el título hacia arriba para hacerse sitio.
   ============================================================================ */

.body-index .lg-pie-marca {
    position: absolute;
    left: 2.8rem;
    right: 2.8rem;
    bottom: 2rem;
    z-index: 2;
    font-size: 0.78rem;
    font-weight: 500;
    line-height: 1.5;
    color: rgba(255, 255, 255, 0.78);
    text-decoration: none;
    transition: color 0.18s ease;
    animation: lgEntrar 0.7s cubic-bezier(0.22, 1, 0.36, 1) 0.3s both;
}

/* Solo se subraya el dominio, no la frase entera: el subrayado es lo que
   dice "esto se pulsa", y puesto en las nueve palabras se convierte en una
   raya larga que pesa mas que el texto. En el dominio basta. */
.body-index .lg-pie-enlace {
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
    text-decoration-color: rgba(255, 255, 255, 0.45);
    transition: color 0.18s ease, text-decoration-color 0.18s ease;
}

.body-index .lg-pie-marca:hover,
.body-index .lg-pie-marca:focus-visible {
    color: #FFFFFF;
}

.body-index .lg-pie-marca:hover .lg-pie-enlace,
.body-index .lg-pie-marca:focus-visible .lg-pie-enlace {
    text-decoration-color: #FFFFFF;
}

/* En movil la columna azul se encoge y el pie se comeria el titulo, asi que
   ahi vuelve al flujo, debajo de todo. */
@media (max-width: 860px) {
    .body-index .lg-pie-marca {
        position: static;
        display: block;
        margin-top: 1.4rem;
    }
}


/* ============================================================================
   75. LO QUE EN OSCURO SE QUEDABA APAGADO

   Dos sitios donde el color estaba pensado SOLO para fondo claro y en oscuro
   se apagaba contra el fondo en vez de despegarse de el.
   ============================================================================ */

/* 75a. Los iconos de las tarjetas del Dashboard.

   La pastilla era azul de marca al 10 % y el icono azul oscuro (#105680).
   Sobre blanco eso es un acento discreto; sobre una tarjeta casi negra es un
   icono oscuro sobre fondo oscuro, que es justo lo contrario de un icono.
   El trazo pasa a blanco roto y la pastilla a un azul claro tenue, que la
   hace visible sin convertirla en un boton. */
:root[data-tema="oscuro"] .bv-tarjeta-icono {
    background: rgba(88, 166, 220, 0.16) !important;
    color: #EAF3FA !important;
}

/* 75b. El boton del correo de la barra superior.

   La pildora, la silueta y la flecha iban los tres en gris medio y sobre el
   lienzo oscuro se leia como algo desactivado. Se aclara la superficie un
   punto y la silueta y la flecha suben al gris de texto normal. */
:root[data-tema="oscuro"] .dropdown-toggle-user {
    background: rgba(255, 255, 255, 0.07) !important;
}
:root[data-tema="oscuro"] .dropdown-toggle-user:hover {
    background: rgba(255, 255, 255, 0.11) !important;
}
:root[data-tema="oscuro"] .imagen-boton {
    background: rgba(255, 255, 255, 0.14) !important;
}
:root[data-tema="oscuro"] .imagen-boton::before {
    background: #E4E8EE !important;
}
:root[data-tema="oscuro"] .dropdown-toggle-user .usuario {
    color: #FFFFFF !important;
}


/* ============================================================================
   76. LA TARJETA DE SUB USUARIOS  (ficha de propietario, los dos paneles)

   Los correos son campos de solo lectura y no una lista con puntos porque es
   lo que son: datos del usuario, del mismo tipo que los de las tarjetas de
   al lado. Una lista aqui los haria parecer acciones.
   ============================================================================ */

/* La altura, explicada, porque el numero no sale de la nada: los campos de
   este panel son `content-box` con `height: 1.7rem` y `padding: 0.5rem`, o
   sea 2.7rem de alto real. Aqui hace falta `border-box` para que el 100 % de
   ancho no se salga de la tarjeta, y con border-box ese 1.7rem pasaria a ser
   el TOTAL: el campo salia mucho mas estrecho que sus vecinos. Se le devuelve
   la suma. */
.extension #tarjetaSubUsuarios .su-email {
    width: 100%;
    box-sizing: border-box;
    height: 2.7rem;
    cursor: pointer;
}

.extension #tarjetaSubUsuarios .su-email:hover {
    background-color: var(--abx-campo-hover) !important;
}

.extension .su-aviso {
    font-size: 0.85rem;
    color: var(--abx-texto-2);
    margin: 0.3rem 0 0.9rem;
    line-height: 1.5;
}

.extension #tarjetaSubUsuarios .su-vacio {
    font-size: 0.88rem;
    color: var(--abx-texto-3);
    margin: 0.2rem 0 0;
}


/* ============================================================================
   77. MÓVIL — LA CAUSA, NO LOS SÍNTOMAS

   Todo vive dentro de `@media (max-width: 1024px)`. El escritorio empieza en
   1050 px (lo fija styles.css con su `@media (max-width: 1049px)`), así que
   ninguna regla de aquí existe siquiera en una pantalla de ordenador.

   QUÉ PASABA DE VERDAD
   --------------------
   `body` es un contenedor flex y `.contenedor-principal` es su hijo. Un hijo
   flex trae de serie `min-width: auto`, que significa "no me encojas por
   debajo de lo que mida mi contenido". Y dentro hay una tabla con
   `min-width: 600px`.

   Resultado: en un móvil de 393 px la página entera se maquetaba a 632 px.
   No es que la tabla se saliera: es que la tabla estiraba la PÁGINA, y
   entonces la cabecera, la píldora del correo, los buscadores y las tarjetas
   se calculaban todos sobre un lienzo de 632 px que el teléfono solo enseña
   a trozos. De ahí que todo pareciera descuadrado y corrido hacia un lado.

   Por eso los parches anteriores no servían: apretar un botón aquí o alinear
   una caja allá no arregla que el lienzo mida 240 px de más.

   Con `min-width: 0` el hijo flex puede encogerse hasta los 393 px reales, y
   entonces el `overflow-x: auto` que la sección YA tenía por fin hace su
   trabajo: la tabla se desplaza dentro de su tarjeta en vez de arrastrar la
   página. Medido en un navegador a 393 px: antes la página medía 632 px de
   ancho; ahora mide 393.
   ============================================================================ */

@media (max-width: 1024px) {

    .contenedor-principal,
    .contenido,
    .header-contenido,
    .extension {
        min-width: 0 !important;
    }

    /* Lo único que se añade además de la causa: el buscador y su botón, que
       en "Mis intercoms" salían en la misma fila sin caber ("Buscador gene…"
       cortado) mientras en "Mis usuarios" sí se apilaban. Mismo componente,
       dos comportamientos. */
    .seleccionar-buscar-input {
        flex-direction: column !important;
        align-items: stretch !important;
        gap: 0.75rem !important;
    }

    .extension input.input-buscar,
    .seleccionar-buscar-input .eliminar,
    .seleccionar-buscar-input .buscar,
    .seleccionar-buscar-input .generar-pdf {
        width: 100% !important;
        max-width: 100% !important;
        height: 2.75rem !important;
    }
}


/* ============================================================================
   78. DATOS DE GESTIÓN — extras contratados  (solo ROOT)

   EL RITMO VERTICAL DE ESTA TARJETA, QUE ES LO QUE SE VEÍA MAL
   ------------------------------------------------------------
   En este formulario la separación entre un campo y la etiqueta siguiente no
   la pone la etiqueta: la pone el `margin-bottom: 1.25rem` del campo de
   arriba. Por eso todas las etiquetas guardan exactamente la misma distancia
   sin que ninguna declare margen superior.

   Los dos fallos eran justo eso:

   · "EXTRAS CONTRATADOS" se separaba de más. Llevaba 1.4rem propios ADEMÁS
     del 1.25rem del campo de arriba, y esos dos no se funden porque el campo
     anterior vive dentro de `.dx-fila`, que es un contenedor flex: el margen
     de un hijo flex no sale fuera. Sumaban. Ahora el subtítulo no declara
     margen superior y hereda el mismo 1.25rem que todos.

   · "Garantía ampliada:" se separaba de menos. Venía detrás de una casilla,
     cuyo margen inferior es de 0.7rem —el aire justo entre dos casillas
     hermanas—, no los 1.25rem que le tocan a una etiqueta nueva. Se le da
     margen superior solo a la etiqueta que rompe el grupo.
   ============================================================================ */

:root {
    /* El aire entre dos casillas hermanas. Vive aquí porque lo usan dos
       reglas distintas y tienen que moverse juntas. */
    --dx-aire-casilla: 0.7rem;
}

.extension .dx-subtitulo {
    /* Sin margen superior a propósito: lo pone el campo de arriba, como a
       cualquier otra etiqueta de la tarjeta. */
    margin: 0 0 0.75rem;
    font-size: 0.82rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--abx-texto-2);
}

.extension .dx-casilla {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    /* Entre casillas hermanas, poco aire: son un grupo. */
    margin: 0 0 var(--dx-aire-casilla);
    cursor: pointer;
    font-size: 0.92rem;
    color: var(--abx-texto);
}

/* La primera etiqueta que NO es una casilla cierra el grupo y recupera la
   distancia normal del formulario.

   Se resta el aire que ya pone la casilla en vez de declarar 1.25rem a secas.
   Esos dos márgenes NO se funden: una casilla es `display:flex` y un
   contenedor flex establece su propio contexto, así que los márgenes se
   suman. Medido, ponerle 1.25rem dejaba 31px donde tocaban 20.

   La resta se hace con la misma variable que usa la casilla, así que si algún
   día cambia ese aire, esto sigue cuadrando solo. */
.extension .dx-casilla + label:not(.dx-casilla) {
    margin-top: calc(1.25rem - var(--dx-aire-casilla));
}

.extension .dx-casilla input[type="checkbox"] {
    width: 1.05rem;
    height: 1.05rem;
    margin: 0;
    flex: 0 0 auto;
    accent-color: var(--abx-azul);
    cursor: pointer;
}

/* El código, en gris: es una ayuda para cruzarlo con el Excel, no el nombre. */
.extension .dx-casilla em {
    font-style: normal;
    color: var(--abx-texto-3);
}
