/*
 * mt-theme.css — Tema Meattrack (design tokens + retheming de librerías)
 *
 * Fuente de verdad de los valores: docs/ui/tokens.md
 * Guía de estilo completa (el porqué): docs/ui/guia-estilo-meattrack.pdf
 * Referencia visual viva: /sandbox/styleguide (pendiente de recrear)
 *
 * Estructura:
 *   1. Tokens --mt-* (:root)
 *   2. Remapeo de variables Bootstrap 5.3 (--bs-*)
 *   3. Overrides por componente Bootstrap (botones, forms, dropdowns...)
 *   4. Overrides de librerías ya cargadas (DataTables, Select2, datepicker, SweetAlert)
 *   5. Componentes Meattrack (.mt-chip, .mt-loading-overlay, utilidades)
 *
 * Se carga en skeleton.php DESPUÉS de styles.css para ganar los empates de
 * especificidad contra el CSS legacy.
 */

/* ------------------------------------------------------------------ */
/* 1. TOKENS                                                          */
/* ------------------------------------------------------------------ */
:root {
    /* Marca — verde Meattrack (canónico: green-700 #265642) */
    --mt-green-50:  #eef5f1;
    --mt-green-100: #d9e9e1;
    --mt-green-200: #b5d3c5;
    --mt-green-300: #8ab6a2;
    --mt-green-400: #5b9379;
    --mt-green-500: #3e755d;
    --mt-green-600: #2f634e;
    --mt-green-700: #265642;
    --mt-green-800: #1d4433;
    --mt-green-900: #143226;
    --mt-green-700-rgb: 38, 86, 66;

    /* Teal — EXCLUSIVO del menú lateral (decisión 15/07/2026: el teal #104650
       se probó como marca global y se descartó; queda solo como piel del
       sidebar). No usarlo fuera de #meatrackNav / .mt-sidebar. */
    --mt-teal-50:  #eef5f7;
    --mt-teal-100: #d5e9ec;
    --mt-teal-200: #add5dc;
    --mt-teal-300: #79bcc8;
    --mt-teal-400: #3ca2b4;
    --mt-teal-500: #257d8d;
    --mt-teal-600: #195f6b;
    --mt-teal-700: #104650;
    --mt-teal-800: #0b373f;
    --mt-teal-900: #07282e;

    /* Neutros teñidos de marca (hue verde ~5%) */
    --mt-gray-50:  #f8faf9;
    --mt-gray-100: #f1f4f2;
    --mt-gray-200: #e4e9e6;
    --mt-gray-300: #d4dbd7;
    --mt-gray-400: #aab4ae;
    --mt-gray-500: #7b867f;
    --mt-gray-600: #5d6862;
    --mt-gray-700: #46504a;
    --mt-gray-800: #2f3733;
    --mt-gray-900: #1b211e;
    --mt-gray-800-rgb: 47, 55, 51;

    /* Semánticos (fijos web + tablet) */
    --mt-success:          #198754;
    --mt-success-subtle:   #d1e7dd;
    --mt-success-border:   #a3cfbb;
    --mt-success-mid:      #5b9379; /* = green-400: fondo estado saturado, armoniza con la marca */
    --mt-success-emphasis: #0f5132;
    --mt-danger:           #dc3545;
    --mt-danger-rgb:       220, 53, 69; /* para rgba(var(--mt-danger-rgb), .x): sombras/pulsos rojos */
    --mt-danger-subtle:    #f8d7da;
    --mt-danger-border:    #f1aeb5;
    --mt-danger-mid:       #bd5d52; /* rojo teja desaturado, mismo tono apagado que green-400 */
    --mt-danger-emphasis:  #842029;
    --mt-warning:          #ffc107;
    --mt-warning-subtle:   #fff3cd;
    --mt-warning-border:   #ffe69c;
    --mt-warning-mid:      #c9973f; /* ámbar desaturado, mismo nivel apagado que success/danger-mid */
    --mt-warning-emphasis: #664d03;
    --mt-warning-strong:   #f59e0b; /* ámbar saturado: badge de aviso (!) sobre botones */
    --mt-orange:           #e8590c; /* naranja intenso: avisos operativos (turno de metales olvidado) */
    --mt-orange-subtle:    #ffd9c2;
    --mt-orange-emphasis:  #984c0c;
    --mt-info:             #4a7fa5;
    --mt-info-subtle:      #dde9f1;
    --mt-info-border:      #b7cfe0;
    --mt-info-emphasis:    #2c4c63;
    /* Tarea (notas del calendario): el olive histórico de las tareas
       (BG_COLOR_NOTA, #C8C446) convertido en token. No es un estado: identifica
       las tarjetas de tarea frente a las de control. */
    --mt-tarea:            #c8c446;
    --mt-tarea-subtle:     #f5f5db;
    --mt-tarea-border:     #e4e2a6;
    --mt-tarea-emphasis:   #55530f;
    /* Acción «Cambiar producto» del turno DM (web y tablet): SIEMPRE morado, no es un
       estado. Único uso previsto: ese botón (antes #6966ff inline en vista_diaria). */
    --mt-producto:         #6966ff;

    /* Festivos por origen (pantalla Días festivos): pareja fondo-pastel +
       texto por origen, compartida por celdas, mini-calendarios y leyenda. */
    --mt-festivo-nacional-bg:     #fdecec;
    --mt-festivo-nacional-fg:     #c0392b;
    --mt-festivo-nacional-border: #e8b4b4;
    --mt-festivo-autonomico-bg:     #fdf3e3;
    --mt-festivo-autonomico-fg:     #b9770e;
    --mt-festivo-autonomico-border: #ecd2a4;
    --mt-festivo-manual-bg:     var(--mt-teal-100);
    --mt-festivo-manual-fg:     var(--mt-teal-600);
    --mt-festivo-manual-border: var(--mt-teal-300);
    /* Manual de ámbito parcial (el festivo solo cubre algunas salas): mismo origen
       manual pero azul, para distinguirlo de un vistazo del manual general. */
    --mt-festivo-parcial-bg:     #e1f0fb;
    --mt-festivo-parcial-fg:     #1f6fa6;
    --mt-festivo-parcial-border: #a9cfe8;

    /* Tipografía: Inter única en toda la app (servida en local, src/fonts/inter-v20).
       Sustituye a Poppins (22/08/2026). */
    --mt-font-display: "Inter", -apple-system, "Segoe UI", Roboto, sans-serif;
    --mt-font-body: "Inter", -apple-system, "Segoe UI", Roboto, sans-serif;

    /* Escala tipográfica por rol (tokens.md §5): los textos no se componen «a ojo»
       con tamaños arbitrarios; cada pieza usa el token de su rol */
    --mt-fs-h1: 24px;        /* título de página (uno por vista) */
    --mt-fs-h2: 20px;        /* título de sección */
    --mt-fs-h3: 18px;        /* subsección */
    --mt-fs-h4: 16px;        /* título de bloque/card */
    --mt-fs-body: 14px;      /* cuerpo por defecto */
    --mt-fs-body-sm: 13px;   /* texto de apoyo (era 12.5; entero de la escala desde 22/08/2026) */
    --mt-fs-caption: 12px;   /* etiquetas/cabeceras de columna (uppercase) */

    /* Letter-spacing (tokens.md §5, Refactoring UI «Use letter-spacing effectively»):
       se deja en paz salvo dos casos, y siempre con estos dos valores —nunca un .5px
       a ojo—: mayúsculas pequeñas (captions, cabeceras de tabla, eyebrows) se abren
       un poco para que se distingan las letras; titulares grandes se aprietan un pelo. */
    --mt-tracking-caps: .06em;
    --mt-tracking-tight: -.01em;

    /* Forma — estándar de redondez único (24/07/2026): 8px de radio en TODA
       la web (inputs, botones, cards, dropdowns, paneles, modales...). Los
       antiguos escalones sm/btn/lg/xl se conservan como alias para no tocar
       cada regla que los usa, pero todos resuelven al mismo valor: NO volver
       a diferenciarlos. Únicas excepciones: chips de estado/switches (pill)
       y elementos circulares (50%). */
    --mt-radius: 8px;
    --mt-radius-sm: var(--mt-radius);
    --mt-radius-btn: var(--mt-radius);
    --mt-radius-lg: var(--mt-radius);
    --mt-radius-xl: var(--mt-radius);
    --mt-radius-pill: 50rem;   /* chips */
    --mt-shadow-sm: 0 4px 14px rgba(20, 50, 38, .07);
    --mt-shadow-lg: 0 8px 24px rgba(20, 50, 38, .14);
    --mt-shadow-btn: inset 0 1px 0 rgba(255, 255, 255, .10), 0 1px 2px rgba(20, 50, 38, .16); /* relieve mínimo del botón primario (luz arriba, sombra corta abajo) */
    --mt-focus-ring: 0 0 0 .25rem rgba(38, 86, 66, .18);

    /* Espaciado: escala estándar de Bootstrap (p-*/m-*/g-*, base 4px);
       no hay tokens propios a propósito (tokens.md §7) */

    /* Z-index (tokens.md §8) — escala de apilamiento única */
    --mt-z-dropdown: 1000;
    --mt-z-sticky: 1020;
    --mt-z-fixed: 1030;
    --mt-z-modal-backdrop: 1050;
    --mt-z-modal: 1055;
    --mt-z-popover: 1070;
    --mt-z-tooltip: 1080;
    --mt-z-bulkbar: 1090;

    /* Movimiento y opacidad (tokens.md §9) */
    --mt-dur-fast: 150ms;
    --mt-dur: 250ms;
    --mt-dur-slow: 350ms;
    --mt-ease: cubic-bezier(.4, 0, .2, 1);
    --mt-opacity-disabled: .5;
    --mt-opacity-overlay: .45;
}

/* ------------------------------------------------------------------ */
/* 2. REMAPEO BOOTSTRAP 5.3                                           */
/* primary pasa de azul a verde marca; neutros y radios, a tokens     */
/* ------------------------------------------------------------------ */
:root {
    --bs-primary: var(--mt-green-700);
    --bs-primary-rgb: var(--mt-green-700-rgb);
    --bs-primary-bg-subtle: var(--mt-green-50);
    --bs-primary-border-subtle: var(--mt-green-200);
    --bs-primary-text-emphasis: var(--mt-green-900);

    --bs-info: var(--mt-info);
    --bs-info-rgb: 74, 127, 165;
    --bs-info-bg-subtle: var(--mt-info-subtle);
    --bs-info-border-subtle: var(--mt-info-border);
    --bs-info-text-emphasis: var(--mt-info-emphasis);

    --bs-link-color: var(--mt-green-700);
    --bs-link-color-rgb: var(--mt-green-700-rgb);
    --bs-link-hover-color: var(--mt-green-900);
    --bs-link-hover-color-rgb: 20, 50, 38;

    --bs-body-color: var(--mt-gray-800);
    --bs-body-color-rgb: var(--mt-gray-800-rgb);
    --bs-secondary-bg: var(--mt-gray-100);
    --bs-tertiary-bg: var(--mt-gray-50);
    --bs-border-color: var(--mt-gray-200);

    --bs-border-radius: var(--mt-radius-sm);
    --bs-border-radius-sm: var(--mt-radius);
    --bs-border-radius-lg: var(--mt-radius);
    --bs-border-radius-xl: var(--mt-radius-lg);

    --bs-focus-ring-color: rgba(38, 86, 66, .18);
    --bs-highlight-bg: var(--mt-green-100);
}

body {
    font-family: var(--mt-font-body);
}

/* Scroll suave global: anclas y scrolls programáticos sin behavior explícito
   (los scrollTo/scrollIntoView con behavior propio no cambian). Con movimiento
   reducido del sistema se desactiva, como pide la guía (§9 Movimiento). */
html {
    scroll-behavior: smooth;
}

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

/* Nota: se probó el lienzo B×C (fondo gray-100/gray-50 con superficies blancas)
   y el usuario lo descartó (14/07/2026) — el fondo de página se queda blanco. */

/* Las tablas son superficie: fondo blanco propio (el --bs-table-bg de serie es
   transparente) */
.table {
    --bs-table-bg: #fff;
}

h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
    font-family: var(--mt-font-display);
}

::selection {
    background-color: var(--mt-green-100);
}

/* ------------------------------------------------------------------ */
/* 3. COMPONENTES BOOTSTRAP                                           */
/* (en BS 5.3 cada componente lleva sus propias --bs-*-... compiladas */
/* en azul, hay que sobreescribirlas por clase)                       */
/* ------------------------------------------------------------------ */
/* Botones: redondeo moderado (10px, como la bulkbar — decisión del usuario:
   el pill completo era demasiado redondo; el pill queda solo para chips),
   peso medio y transición suave. */
.btn {
    border-radius: var(--mt-radius-btn);
    font-weight: 500;
    padding-left: 1rem;
    padding-right: 1rem;
    transition: background-color var(--mt-dur-fast) var(--mt-ease),
                border-color var(--mt-dur-fast) var(--mt-ease),
                box-shadow var(--mt-dur-fast) var(--mt-ease);
}

/* Cabecera de página con la acción a la derecha (patrón repetido en ~25 listados:
   <div class="row"><div class="col-md-8"><h2>…</h2></div><div class="col-md-4 text-end">
   <a class="btn">Crear …</a></div></div>): styles.css (legacy) da margin-right:10px
   a todo .btn y el último botón quedaba metido 10px respecto al borde derecho de la
   card/buscador de debajo, mientras el título sí va a ras del izquierdo. Aquí solo
   el último botón de esa columna va a ras (con varios botones el margen legacy sigue
   haciendo de separación entre ellos). */
.row > [class*="col-"].text-end > .btn:last-child,
.row > [class*="col-"].text-end > .d-inline-flex > .btn:last-child {
    margin-right: 0;
}

/* styles.css (legacy) subraya todo a:hover y alcanza a los <a class="btn">;
   el hover de un botón es un cambio ligero de tono, nunca subrayado. */
.btn:hover,
.btn:focus {
    text-decoration: none;
}

/* El aspa de cerrar (modals, alerts, toasts) trae el focus azul de Bootstrap
   hardcodeado en --bs-btn-close-focus-shadow; se sustituye por el anillo corporativo. */
.btn-close {
    --bs-btn-close-focus-shadow: var(--mt-focus-ring);
}

.btn-sm {
    padding-left: .75rem;
    padding-right: .75rem;
}

/* Jerarquía de acciones (tokens.md §18.2, Refactoring UI «Semantics are
   secondary»): la acción secundaria es clara pero discreta. .btn-secondary deja
   de ser el bloque gris sólido de Bootstrap (#6c757d, fuera de la paleta) y pasa
   a botón claro con borde —fondo blanco, borde gray-300, texto gray-800, hover
   gray-50— y .btn-outline-secondary se unifica al mismo aspecto (eran la misma
   intención con dos pieles). La primaria sigue siendo el verde sólido; las
   variantes con intención propia (ND de veredicto, toggles) tienen sus reglas. */
.btn-secondary,
.btn-outline-secondary {
    --bs-btn-color: var(--mt-gray-800);
    --bs-btn-bg: #fff;
    --bs-btn-border-color: var(--mt-gray-300);
    --bs-btn-hover-color: var(--mt-gray-900);
    --bs-btn-hover-bg: var(--mt-gray-50);
    --bs-btn-hover-border-color: var(--mt-gray-400);
    --bs-btn-active-color: var(--mt-gray-900);
    --bs-btn-active-bg: var(--mt-gray-100);
    --bs-btn-active-border-color: var(--mt-gray-400);
    --bs-btn-disabled-color: var(--mt-gray-400);
    --bs-btn-disabled-bg: #fff;
    --bs-btn-disabled-border-color: var(--mt-gray-200);
    --bs-btn-focus-shadow-rgb: var(--mt-green-700-rgb);
}

/* Terciaria (acciones-enlace menores e inline: «Ver más», «Marcar todos»,
   «Cancelar» dentro de un bloque): discreta en reposo —gris, sin subrayado—,
   verde de marca y subrayado en hover. Una navegación como «Volver al listado»
   NO va aquí: se vería escondida; va como secundaria neutra (btn-secondary). */
.btn-link {
    --bs-btn-color: var(--mt-gray-700);
    --bs-btn-hover-color: var(--mt-green-700);
    --bs-btn-active-color: var(--mt-green-800);
    --bs-btn-focus-shadow-rgb: var(--mt-green-700-rgb);
    text-decoration: none;
}

.btn-link:hover,
.btn-link:focus-visible {
    text-decoration: underline;
}

/* Botón «Ahora» (junto a los selects Hora/Minuto en incidencias, notas, verificar
   registro, ficha de control…): es un btn-sm de ~31px al lado de selects que styles.css
   (legacy) deja a 40px; misma altura para que la fila Hora/Minuto/Ahora quede alineada. */
.btn.btn_ahora {
    height: 40px;
    display: inline-flex;
    align-items: center;
}

.btn-primary {
    --bs-btn-bg: var(--mt-green-700);
    --bs-btn-border-color: var(--mt-green-700);
    --bs-btn-hover-bg: var(--mt-green-600);
    --bs-btn-hover-border-color: var(--mt-green-600);
    --bs-btn-active-bg: var(--mt-green-800);
    --bs-btn-active-border-color: var(--mt-green-800);
    --bs-btn-disabled-bg: var(--mt-green-300);
    --bs-btn-disabled-border-color: var(--mt-green-300);
    --bs-btn-focus-shadow-rgb: var(--mt-green-700-rgb);
}

/* styles.css (legacy) fija el fondo de .btn-primary con !important y sin variante
   hover, con lo que el hover por --bs-btn-hover-bg no llega a verse nunca; hay que
   contra-sobreescribir con !important, igual que con los semánticos de más abajo. */
.btn-primary:hover {
    background: var(--mt-green-600) !important;
    border-color: var(--mt-green-600) !important;
}

.btn-primary:active {
    background: var(--mt-green-800) !important;
    border-color: var(--mt-green-800) !important;
}

/* Relieve mínimo de la primaria (Refactoring UI «Emulate a light source»): borde
   superior un pelo más claro y sombra corta debajo; al pulsar se hunde (sin sombra).
   Es el único botón con sombra: es la única acción que debe «salir» de la página. */
.btn-primary {
    box-shadow: var(--mt-shadow-btn);
}

.btn-primary:active,
.btn-primary.disabled,
.btn-primary:disabled {
    box-shadow: none;
}

/* Secundaria de marca (tokens.md §18.2): «clara pero no prominente». Fondo
   green-50 con borde green-200 y texto green-700; en hover sube un escalón de la
   rampa (green-100 / green-300) en lugar de rellenarse de verde sólido, que la
   hacía competir con la primaria. */
.btn-outline-primary {
    --bs-btn-color: var(--mt-green-700);
    --bs-btn-bg: var(--mt-green-50);
    --bs-btn-border-color: var(--mt-green-200);
    --bs-btn-hover-color: var(--mt-green-800);
    --bs-btn-hover-bg: var(--mt-green-100);
    --bs-btn-hover-border-color: var(--mt-green-300);
    --bs-btn-active-color: var(--mt-green-900);
    --bs-btn-active-bg: var(--mt-green-200);
    --bs-btn-active-border-color: var(--mt-green-300);
    --bs-btn-disabled-color: var(--mt-green-300);
    --bs-btn-disabled-bg: #fff;
    --bs-btn-disabled-border-color: var(--mt-green-200);
    --bs-btn-focus-shadow-rgb: var(--mt-green-700-rgb);
}

.btn-info {
    --bs-btn-bg: var(--mt-info);
    --bs-btn-border-color: var(--mt-info);
    --bs-btn-color: #fff;
    --bs-btn-hover-bg: var(--mt-info-emphasis);
    --bs-btn-hover-border-color: var(--mt-info-emphasis);
    --bs-btn-hover-color: #fff;
    --bs-btn-active-bg: var(--mt-info-emphasis);
    --bs-btn-active-border-color: var(--mt-info-emphasis);
    --bs-btn-active-color: #fff;
    --bs-btn-focus-shadow-rgb: 74, 127, 165;
}

/* styles.css (legacy) pisa los botones semánticos con !important y colores
   ad-hoc (#A0B7D3 azul en success, #8B9DAF, #EFCB2E, #C85246). Hasta que se
   limpie ese bloque, hay que contra-sobreescribir también con !important para
   que rijan los colores semánticos de los tokens. */
.btn-success,
.btn-success.disabled,
.btn-success:disabled {
    background: var(--mt-success) !important;
    border-color: var(--mt-success) !important;
    color: #fff !important;
}

.btn-success:hover,
.btn-success:active {
    background: var(--mt-success-emphasis) !important;
    border-color: var(--mt-success-emphasis) !important;
}

.btn-info,
.btn-info.disabled,
.btn-info:disabled {
    background: var(--mt-info) !important;
    border-color: var(--mt-info) !important;
    color: #fff !important;
}

.btn-info:hover,
.btn-info:active {
    background: var(--mt-info-emphasis) !important;
    border-color: var(--mt-info-emphasis) !important;
}

.btn-warning,
.btn-warning.disabled,
.btn-warning:disabled {
    background: var(--mt-warning) !important;
    border-color: var(--mt-warning) !important;
    color: var(--mt-gray-900) !important;
}

.btn-danger,
.btn-danger.disabled,
.btn-danger:disabled {
    background: var(--mt-danger) !important;
    border-color: var(--mt-danger) !important;
    color: #fff !important;
}

.btn-danger:hover,
.btn-danger:active {
    background: var(--mt-danger-emphasis) !important;
    border-color: var(--mt-danger-emphasis) !important;
}

.btn-outline-danger,
.btn-outline-danger.disabled,
.btn-outline-danger:disabled {
    border-color: var(--mt-danger) !important;
    color: var(--mt-danger);
}

.btn-outline-danger:hover {
    background: var(--mt-danger) !important;
    color: #fff !important;
}

/* Botones «Cerrar control/registro» (ficha de control y modal de confirmación):
   rojo teja apagado (danger-mid, el mismo tono del botón de la tablet) en vez del
   danger vivo, que quedaba demasiado llamativo. Clase compartida porque el botón
   sale en varias vistas (ficha, modal_cerrar_control, gestion_consulta_incidencias). */
.btn-danger.mt-btn-cerrar-registro {
    background: var(--mt-danger-mid) !important;
    border-color: var(--mt-danger-mid) !important;
}

.btn-danger.mt-btn-cerrar-registro:hover,
.btn-danger.mt-btn-cerrar-registro:active {
    background: var(--mt-danger-emphasis) !important;
    border-color: var(--mt-danger-emphasis) !important;
}

/* "+" de añadir incidencia (ficha de control, junto a la chapa de incidencias):
   rojo teja apagado en vez del danger vivo, que quedaba demasiado llamativo al
   lado de la chapa "N inc." (mismo tono que usan los estados de la tablet). */
.btn_plus_incidencias.btn-outline-danger {
    border-color: var(--mt-danger-mid) !important;
    color: var(--mt-danger-mid);
}

.btn_plus_incidencias.btn-outline-danger:hover {
    background: var(--mt-danger-mid) !important;
    color: #fff !important;
}

/* Botón «Incidencias Planta» y su desplegable (header del modal de incidencia):
   tonos -mid apagados en vez del warning/danger vivos, mismo criterio que
   btn_plus_incidencias — el ámbar/rojo saturados quedaban demasiado llamativos
   en el header. Se cubre también el estado .show (desplegable abierto), que en
   Bootstrap rellena el outline con el color vivo. */
.ilt-header-actions .btn-outline-warning {
    border-color: var(--mt-warning-mid) !important;
    color: var(--mt-warning-mid) !important;
}

.ilt-header-actions .btn-outline-warning:hover,
.ilt-header-actions .btn-outline-warning.show {
    background: var(--mt-warning-mid) !important;
    border-color: var(--mt-warning-mid) !important;
    color: #fff !important;
}

.ilt-header-actions .btn-outline-danger {
    border-color: var(--mt-danger-mid) !important;
    color: var(--mt-danger-mid) !important;
}

.ilt-header-actions .btn-outline-danger:hover,
.ilt-header-actions .btn-outline-danger.show {
    background: var(--mt-danger-mid) !important;
    color: #fff !important;
}

.ilt-header-actions .dropdown-item .text-warning {
    color: var(--mt-warning-mid) !important;
}

.ilt-header-actions .dropdown-item .text-danger {
    color: var(--mt-danger-mid) !important;
}

/* Botones de veredicto C/I/ND (ficha de control, subelementos y verificación de
   canales): réplica del estilo de la app tablet (FormsBaseUI: 37x37dp, radio 8,
   letra en negrita) — I en rojo teja apagado (danger-mid) y ND en gray-600, en vez
   del danger/secondary vivos de Bootstrap. C ya coincide (btn-primary = green-700).
   Los !important contrarrestan los .btn-danger/.btn-outline-danger globales de
   arriba (que a su vez pisan styles.css legacy) y el padding inline del modo fila.
   El padding lateral corto + min-width hace que C/I/ND salgan como cuadrados
   iguales de 40px; las etiquetas personalizadas largas crecen a partir de ahí. */
.btn.correcto, .btn.incorrecto, .btn.nd_option,
.btn.subelemento_correcto, .btn.subelemento_incorrecto, .btn.subelemento_nd_option,
.btn.verif_canales_correcto, .btn.verif_canales_incorrecto, .btn.verif_canales_nd_option,
.btn.canal_incorrecta {
    font-weight: 700;
    min-width: 40px;
    min-height: 40px;
    padding: 8px 6px !important;
    line-height: 1.2;
    border-radius: var(--mt-radius);
}

.btn.incorrecto.btn-outline-danger,
.btn.subelemento_incorrecto.btn-outline-danger,
.btn.verif_canales_incorrecto.btn-outline-danger,
.btn.canal_incorrecta.btn-outline-danger {
    border-color: var(--mt-danger-mid) !important;
    color: var(--mt-danger-mid);
}

.btn.incorrecto.btn-outline-danger:hover,
.btn.subelemento_incorrecto.btn-outline-danger:hover,
.btn.verif_canales_incorrecto.btn-outline-danger:hover,
.btn.canal_incorrecta.btn-outline-danger:hover {
    background: var(--mt-danger-mid) !important;
    color: #fff !important;
}

.btn.incorrecto.btn-danger,
.btn.subelemento_incorrecto.btn-danger,
.btn.verif_canales_incorrecto.btn-danger,
.btn.canal_incorrecta.btn-danger {
    background: var(--mt-danger-mid) !important;
    border-color: var(--mt-danger-mid) !important;
}

/* "C" sin marcar: sin el fondo tintado green-50 de .btn-outline-primary (fondo
   blanco); conserva borde y texto verdes. En hover, green-50 en vez de green-100. */
.btn.correcto.btn-outline-primary,
.btn.subelemento_correcto.btn-outline-primary,
.btn.verif_canales_correcto.btn-outline-primary,
.btn.metal_correcto.btn-outline-primary,
.btn.utiles_ci_c.btn-outline-primary {
    --bs-btn-bg: #fff;
    --bs-btn-hover-bg: var(--mt-green-50);
}

/* Chapa contadora "N inc." / "N incidencias" (ficha de control, junto al "+"):
   mismo rojo teja apagado que el botón "I" del veredicto, para que no destaque
   más que él. Con hover un punto más oscuro (danger-emphasis). Se excluye
   .cerrada (solo incidencias cerradas → verde, styles.css legacy). */
.btn.incidencia.btn-danger:not(.cerrada) {
    background: var(--mt-danger-mid) !important;
    border-color: var(--mt-danger-mid) !important;
    color: #fff !important;
}

.btn.incidencia.btn-danger:not(.cerrada):hover,
.btn.incidencia.btn-danger:not(.cerrada):active {
    background: var(--mt-danger-emphasis) !important;
    border-color: var(--mt-danger-emphasis) !important;
}

.btn.incidencia.btn-outline-danger {
    border-color: var(--mt-danger-mid) !important;
    color: var(--mt-danger-mid);
}

/* .mt-cind-btn: los C/I/ND de las comprobaciones de mantenimiento de una incidencia
   de planta. Son el mismo veredicto que el de los controles, así que comparten estas
   reglas: sin ellas, el ND marcado se quedaba en el .btn-secondary claro de arriba y
   no se distinguía del que no lo está. */
.btn.nd_option.btn-outline-secondary,
.btn.subelemento_nd_option.btn-outline-secondary,
.btn.verif_canales_nd_option.btn-outline-secondary,
.btn.mt-cind-btn.btn-outline-secondary {
    border-color: var(--mt-gray-600) !important;
    color: var(--mt-gray-600);
}

.btn.nd_option.btn-outline-secondary:hover,
.btn.subelemento_nd_option.btn-outline-secondary:hover,
.btn.verif_canales_nd_option.btn-outline-secondary:hover,
.btn.mt-cind-btn.btn-outline-secondary:hover {
    background: var(--mt-gray-600) !important;
    color: #fff !important;
}

.btn.nd_option.btn-secondary,
.btn.subelemento_nd_option.btn-secondary,
.btn.verif_canales_nd_option.btn-secondary,
.btn.mt-cind-btn.btn-secondary {
    background: var(--mt-gray-600) !important;
    border-color: var(--mt-gray-600) !important;
    color: #fff !important;
}

/* styles.css legacy también pisa .text-success con el azul #A0B7D3 (el mismo
   error de rol que .btn-success); devolverlo al verde semántico. */
.text-success {
    color: var(--mt-success) !important;
}

/* Mismo caso: .text-danger legacy es salmón #F19582 y .text-warning mostaza
   #EFCB2E; devolverlos a los semánticos del tema. */
.text-danger {
    color: var(--mt-danger) !important;
}

.text-warning {
    color: var(--mt-warning) !important;
}

/* Inputs: styles.css legacy los deja planos (fondo gris #EEEEEE, sin borde,
   radio 0, texto azul marino) con selectores `form input.form-control` (0,1,2);
   replicamos esa especificidad para devolverlos al estándar del sistema:
   blancos, borde neutro y radio sm. */
.form-control,
.form-select,
form input.form-control,
form select.form-control,
form textarea.form-control,
form select.form-select {
    background-color: #fff;
    border: 1px solid var(--mt-gray-300);
    border-radius: var(--mt-radius-sm);
    color: var(--mt-gray-800);
}

form input.form-control::placeholder,
form select.form-control::placeholder,
.form-control::placeholder {
    color: var(--mt-gray-400);
}

/* Inputs de fichero: el botón «Elegir archivos» (::file-selector-button) mide
   lo que da su padding + line-height, no lo que mide la caja. Con los 40px
   fijos del legacy `form input.form-control` (styles.css) y el texto a 14px
   (line-height 21px) el botón se quedaba en 33px y dejaba 5px de hueco por
   abajo. 26px = 40 de caja − 2 de borde − 12 de padding vertical (§7b). */
form input[type="file"].form-control {
    line-height: 26px;
}

/* Deshabilitado/solo lectura: superficie gris suave, mismo radio */
.form-control:disabled,
.form-control[readonly],
.form-select:disabled,
form input.form-control:disabled,
form input.form-control[readonly],
form select.form-control:disabled {
    background-color: var(--mt-gray-100);
    color: var(--mt-gray-600);
}

/* Selects NATIVOS tematizados. El desplegable de un <select> nativo no se puede
   estilar con CSS clásico (salía el listado del sistema, azul y cuadrado). En los
   navegadores con «customizable select» (Chromium 135+) lo convertimos en un picker
   estilable alineado con el tema; en el resto queda el desplegable nativo de siempre.
   Solo afecta a selects simples (multiple/size siguen nativos) y no toca los select2. */
@supports (appearance: base-select) {
    select.form-select,
    select.form-control {
        appearance: base-select;
    }

    /* base-select añade su propia flecha; la de siempre ya la pinta el
       background-image de .form-select, así que fuera la duplicada */
    select.form-select::picker-icon,
    select.form-control::picker-icon {
        display: none;
    }

    /* Con base-select el valor seleccionado es una caja real y puede partirse
       en dos líneas desbordando el control (un select nativo nunca hace eso);
       lo dejamos como el nativo: una línea con elipsis */
    select.form-select,
    select.form-control {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    /* El texto largo pisaba la flecha: la caja interna que pinta Chrome para
       el valor es max-content y no respeta el padding derecho. helpers.php
       inyecta el <button><selectedcontent> del estándar en los selects
       simples; con markup propio la caja SÍ es estilable y el valor se corta
       con elipsis antes de llegar a la flecha. */
    select.form-select > button,
    select.form-control > button {
        display: flex;
        align-items: center;
        width: 100%;
        /* llena el alto del select (con height fijo en el select, el valor
           quedaba pegado arriba en vez de centrado) */
        height: 100%;
        min-width: 0;
        padding: 0;
        border: 0;
        background: none;
        color: inherit;
        font: inherit;
        text-align: inherit;
    }

    select.form-select > button > selectedcontent,
    select.form-control > button > selectedcontent {
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
    }

    select.form-select::picker(select),
    select.form-control::picker(select) {
        appearance: base-select;
        background: #fff;
        border: 1px solid var(--mt-gray-200);
        border-radius: var(--mt-radius);
        box-shadow: var(--mt-shadow-lg);
        padding: .3rem;
        margin-top: 4px;
        /* Colocación: por defecto hacia abajo (mismo criterio que el datepicker);
           sin position-area el navegador pone el desplegable encima del control y
           lo tapa. Si abajo no cabe, se voltea arriba (flip-block) y, en última
           instancia, también de lado.

           Las dos líneas siguientes son necesarias para que ese "si no cabe"
           funcione; son ajustes de Chrome que hay que anular:
           - position-try-order: el UA trae `most-block-size`, que elige siempre el
             lado con más hueco aunque el desplegable quepa de sobra abajo (con dos
             opciones ya se abría hacia arriba en mitad de la pantalla). Con
             `normal` se respeta el orden de arriba: abajo salvo que no quepa.
           - max-height: el UA trae `stretch`, que encoge el desplegable hasta el
             hueco disponible en vez de considerarlo desbordado; en un select
             pegado al borde inferior (el «Cierre» del modal de incidencia) eso
             dejaba una caja de una sola opción con barra de scroll y nunca se
             volteaba. Con una altura máxima fija, si no cabe se desborda y entra
             el flip-block. */
        position-area: block-end span-inline-end;
        position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline;
        position-try-order: normal;
        max-height: min(60vh, 22rem);
    }

    select.form-select option,
    select.form-control option {
        padding: .4rem .75rem;
        border-radius: var(--mt-radius);
        cursor: pointer;
    }

    select.form-select option:hover,
    select.form-control option:hover,
    select.form-select option:focus,
    select.form-control option:focus {
        background: var(--mt-green-50);
        color: var(--mt-green-900);
    }

    select.form-select option:checked,
    select.form-control option:checked {
        background: var(--mt-green-700);
        color: #fff;
    }

    /* Las opciones placeholder sin texto (<option value=""></option>) salían en
       el picker como una barra verde vacía con el check al estar seleccionadas.
       Select2 ya las oculta de sus resultados; el picker nativo hace lo mismo. */
    select.form-select option:empty,
    select.form-control option:empty {
        display: none;
    }
}

/* El tema select2-bootstrap-5 compila su propio radio; lo alineamos con los inputs */
.select2-container--bootstrap-5 .select2-selection {
    border-radius: var(--mt-radius-sm);
    border-color: var(--mt-gray-300);
}

/* Altura de referencia de los inputs (§7b: 40px). El tema bootstrap-5 deja el
   single en 38px, pero dentro de <form> el legacy de styles.css sube los
   selects nativos a 40px (form select.form-control) — lado a lado en los
   modales se veían distintos. Flex para que el texto quede centrado exacto. */
.select2-container--bootstrap-5 .select2-selection--single {
    height: 40px;
    display: flex;
    align-items: center;
}

/* Y el texto del valor con el gris del tema, como los selects nativos (el
   tema select2-bootstrap-5 compila el #212529 de Bootstrap). */
.select2-container--bootstrap-5 .select2-selection--single .select2-selection__rendered {
    color: var(--mt-gray-800);
}

/* El placeholder de un select2 SIMPLE, del mismo color que el de un select
   nativo (donde «Selecciona…» es una <option> y se pinta como texto normal):
   lado a lado se veían de dos colores. Los múltiples (filtros/buscadores)
   conservan su placeholder gris de campo de búsqueda. El segundo selector
   replica la especificidad compuesta del tema select2-bootstrap-5 (pasa por
   __rendered) para ganarle el empate por orden de carga. */
.select2-container--bootstrap-5 .select2-selection--single .select2-selection__placeholder,
.select2-container--bootstrap-5 .select2-selection--single .select2-selection__rendered .select2-selection__placeholder {
    color: var(--mt-gray-800);
}

/* Placeholder más largo que el control: elipsis en vez de corte seco (se veía
   en pantallas estrechas, p. ej. «Todas las duraciones» en los filtros de la
   vista diaria). Los selectores de select2 cubren el placeholder de los
   múltiples, que se pinta en su campo de búsqueda inline: select2 le pone un
   ancho inline en px según el texto, así que sin el max-width el campo
   desborda el control y lo recorta el contenedor sin llegar a la elipsis. */
.form-control,
.form-select,
.select2-container--bootstrap-5 .select2-selection--multiple .select2-search__field {
    text-overflow: ellipsis;
}

.select2-container--bootstrap-5 .select2-selection--multiple .select2-search--inline,
.select2-container--bootstrap-5 .select2-selection--multiple .select2-search__field {
    max-width: 100%;
    /* styles.css legacy fuerza min-width:260px a todo input[type=search] y el
       campo inline de select2 es type=search: con ese mínimo desbordaba los
       filtros estrechos y el max-width de arriba nunca llegaba a recortar. */
    min-width: 0;
}

.select2-container--bootstrap-5 .select2-selection--multiple .select2-search__field {
    /* Mismo origen legacy (input[type=search] con height:40px y borde): al
       seleccionar un chip, el campo inline de 40px saltaba a una segunda línea
       y el control multiple se hinchaba a doble altura. */
    height: auto;
    border: 0;
}

/* Multiples con chips (select2 4.0.x + tema bootstrap-5, que está pensado
   para 4.1): en 4.0 el campo de búsqueda inline va DENTRO del <ul> de chips y
   el tema le pone width:100%, así que en cuanto había un chip saltaba a una
   segunda línea y el control se hinchaba (81px). Lo dejamos como hueco
   flexible en la misma línea que los chips. */
.select2-container--bootstrap-5 .select2-selection--multiple .select2-selection__rendered {
    row-gap: .25rem;
}

.select2-container--bootstrap-5 .select2-selection--multiple .select2-selection__rendered .select2-search--inline {
    width: auto;
    flex: 1 1 0;
    min-width: 0;
    height: auto;
}

/* Chip más largo que el control (p. ej. «Registro Contaminación Canal…» en
   Tipo control de los filtros): elipsis en vez de desbordar y quedar cortado.
   Reserva 2.5rem para que el campo de búsqueda quepa a su lado. Sin padding
   vertical y sin margen inferior para que con un chip el control mida 40px,
   como el resto de inputs de la barra; el salto entre líneas lo pone el
   row-gap del <ul>. */
.select2-container--bootstrap-5 .select2-selection--multiple .select2-selection__rendered .select2-selection__choice {
    display: inline-block;
    max-width: calc(100% - 2.5rem);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: middle;
    padding: 0 .5em;
    margin-bottom: 0;
}

.select2-container--bootstrap-5 .select2-selection--multiple .select2-selection__choice .select2-selection__choice__remove {
    vertical-align: middle;
    /* La regla de la elipsis de arriba pasa el chip a inline-block y este span
       deja de ser flex-item: vuelve a ser inline, donde text-indent/overflow
       (el truco del tema bootstrap-5 para ocultar la «×» de TEXTO que mete
       select2 4.0) no aplican → se veían dos aspas (la de texto + la SVG de
       fondo). inline-block reactiva el truco y deja solo la SVG. */
    display: inline-block;
}

/* En la barra de filtros compacta los campos son estrechos y con la elipsis de
   arriba los chips se quedaban en «Control p…». Aquí preferimos el nombre
   entero: el chip parte el texto en varias líneas y el control crece en alto
   (la barra ya es de altura variable). Solo dentro de .mt-buscador — en modales
   y fichas los múltiples siguen con elipsis y altura fija.
   Se conserva el max-width con la reserva de 2.5rem de la regla de arriba: así
   el campo de búsqueda sigue cabiendo al lado del chip y con una sola selección
   —el caso normal— el control mantiene sus 40px. */
.mt-buscador .select2-container--bootstrap-5 .select2-selection--multiple .select2-selection__rendered .select2-selection__choice {
    overflow: visible;
    text-overflow: clip;
    white-space: normal;
    /* el texto envuelto arranca alineado con la primera línea, sin meterse
       debajo de la «✕» */
    display: flex;
    align-items: baseline;
    gap: .25em;
    line-height: 1.35;
}

/* Focus de formularios: anillo verde en vez de azul */
.form-control:focus,
.form-select:focus {
    border-color: var(--mt-green-300);
    box-shadow: var(--mt-focus-ring);
}

.form-check-input:checked,
.form-check-input[type="checkbox"]:indeterminate {
    /* :indeterminate = "seleccionar todos" a medias (algunos hijos marcados).
       Bootstrap lo pinta con su azul por defecto; lo retematizamos en verde
       igual que :checked (el guion blanco del SVG se conserva). El selector
       repite [type="checkbox"] para igualar la especificidad de la regla de
       Bootstrap (.form-check-input[type="checkbox"]:indeterminate) y ganarle
       por orden de carga. */
    background-color: var(--mt-green-700);
    border-color: var(--mt-green-700);
}

.form-check-input:focus {
    border-color: var(--mt-green-300);
    box-shadow: var(--mt-focus-ring);
}

/* El knob del switch trae SVGs con azul hardcodeado (focus) en Bootstrap */
.form-switch .form-check-input:focus {
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%238ab6a2'/%3e%3c/svg%3e");
}

.form-switch .form-check-input:checked {
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e");
}

.dropdown-menu {
    --bs-dropdown-link-active-bg: var(--mt-green-700);
    --bs-dropdown-link-active-color: #fff;
    box-shadow: var(--mt-shadow-lg);
}

.nav-pills {
    --bs-nav-pills-link-active-bg: var(--mt-green-700);
}

.pagination {
    --bs-pagination-active-bg: var(--mt-green-700);
    --bs-pagination-active-border-color: var(--mt-green-700);
    --bs-pagination-focus-box-shadow: var(--mt-focus-ring);
}

.list-group {
    --bs-list-group-active-bg: var(--mt-green-700);
    --bs-list-group-active-border-color: var(--mt-green-700);
}

.progress,
.progress-stacked {
    --bs-progress-bar-bg: var(--mt-green-700);
}

.modal-content {
    border-radius: var(--mt-radius-xl);
}

/* styles.css legacy pone `.modal-content, .modal-footer { border-radius: 0 }`, así
   que al redondear solo el .modal-content el footer se quedaba cuadrado. Como el
   .modal-content no recorta (overflow visible), un footer con fondo propio (los de
   incidencias/devoluciones se tiñen del color del estado) asomaba por las esquinas
   de abajo. El -1px descuenta el borde del modal, igual que el inner-radius de
   Bootstrap y que las esquinas de las tablas. */
.modal-footer {
    border-bottom-left-radius: calc(var(--mt-radius-xl) - 1px);
    border-bottom-right-radius: calc(var(--mt-radius-xl) - 1px);
    /* El espacio entre botones lo pone el gap; ver la regla de abajo. */
    gap: 8px;
}

/* Los botones del pie terminan donde terminan los campos del cuerpo (ambos
   con 40px de padding lateral, styles.css legacy). El .btn legacy (styles.css
   §10) trae margin-right:10px + margin-top:15px, y Bootstrap añade .25rem por
   lado a cada hijo del pie: «Guardar» quedaba 10px más adentro que el textarea
   de encima y la fila salía más alta por arriba que por abajo. Se anulan y el
   hueco entre botones lo da el gap del contenedor (misma solución que
   .mt-inc-form .modal-footer > * y .mt-buscador-actions .btn). */
.modal-footer > * {
    margin: 0;
}

/* La X de cierre SIEMPRE anclada a la esquina superior derecha del modal
   (decisión 25/08/2026, uniformidad): mismo punto en todos los modales,
   independiente del layout del header (una o dos líneas de título, botoneras
   propias como la del resumen de registro…). El padding-right del header
   reserva su hueco. */
.modal .modal-content {
    position: relative;
}

.modal .modal-header .btn-close {
    position: absolute;
    top: 8px;
    right: 12px;
    margin: 0;
    z-index: 5;
}

.modal .modal-header {
    padding-right: 56px;
}

/* Título de modal: H3 de la escala (18px/600, gray-900) en lugar del h5
   navy bold legacy (#081234, 22px) que heredaban todos los modales */
.modal-title {
    color: var(--mt-gray-900);
    font-size: 1.125rem;
    font-weight: 600;
}

/* Tarjetas flotantes B×C: radio generoso y sombra suave. El border-radius va
   también como propiedad directa porque styles.css legacy aplasta las cards
   con `.card { border-radius: 0 }` y ahí la variable ya no llega a pintarse. */
.card {
    --bs-card-border-radius: var(--mt-radius);
    --bs-card-inner-border-radius: calc(var(--mt-radius) - 1px);
    border-radius: var(--bs-card-border-radius);
    border-color: var(--mt-gray-200);
    box-shadow: var(--mt-shadow-sm);
}

/* styles.css legacy también deja a 0 las esquinas del header; devolverle el
   radio interior de Bootstrap para que no rompa la esquina redondeada */
.card > .card-header:first-child {
    border-radius: var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius) 0 0;
}

.dropdown-menu {
    border-radius: var(--mt-radius);
    /* El fondo (hover/activo) de los items es cuadrado; sin esto se sale por
       las esquinas redondeadas en el primer y último item */
    overflow: hidden;
}

/* El radio va también como propiedad directa porque styles.css legacy aplasta
   los alerts con `.alert { border-radius: 0 }` y ahí la variable ya no llega a
   pintarse (mismo caso que las .card de abajo). */
.alert {
    --bs-alert-border-radius: var(--mt-radius);
    border-radius: var(--bs-alert-border-radius);
}

/* Tablas: UNA sola separación de filas en toda la plataforma (decisión
   25/08/2026, Refactoring UI §18.5): hairline + hover. La zebra se apaga —
   apilada sobre los bordes era separación redundante y restaba contraste a lo
   que sí informa (bandas de grupo, chips, estados). */
.table {
    --bs-table-striped-bg: transparent;
    --bs-table-hover-bg: var(--mt-green-50);
}

/* Cabecera de tabla estilo Meattrack: ligera, etiquetas pequeñas en mayúsculas
   (sustituye a las cabeceras verde oscuro pleno del estilo antiguo). Tamaño y
   tracking del rol caption (tokens §5), como los labels de .mt-buscador — a
   13.6px la fuente a 600 en mayúsculas quedaba demasiado pesada. */
.table thead th,
table.dataTable thead th,
table.dataTable thead td {
    background-color: var(--mt-gray-100);
    color: var(--mt-gray-600);
    font-size: 13px;              /* entero de la escala (era .8rem = 12.8px) */
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: var(--mt-tracking-caps);
    vertical-align: middle;
    border-bottom: 1px solid var(--mt-gray-300);
}

/* Las cabeceras se alinean con su dato (Refactoring UI, tokens §18.5): texto a
   la izquierda; una columna numérica marca th y td con .text-end y su indicador
   de orden pasa delante de la etiqueta (regla junto a las de ordenación) para
   que el borde derecho del título coincida con las cifras. */
table.dataTable thead th,
table.dataTable thead td {
    text-align: left;
}

/* La celda de cabecera del "seleccionar todo" (la inyecta bulkbar.js con el
   checkbox como único contenido) se centra, alineada con los checkboxes de
   las filas (regla gemela en la sección del cuerpo de tabla). */
table.dataTable thead th:has(> input[type="checkbox"]:first-child:last-child) {
    text-align: center;
}

/* Contenedor de scroll horizontal de cada DataTable (lo añade
   datatable-module.js al inicializar, mismo papel que .table-responsive de
   Bootstrap). Una tabla con celdas nowrap no puede encoger por debajo de su
   contenido: en las que no llevan la extensión Responsive (/controles,
   /gestion_datos, por el chevron parent-child) o cuyas columnas son todas "all"
   (nunca colapsar), al hacer zoom o en pantallas medianas desbordaba la página
   entera. Con el contenedor solo se desliza la tabla; buscador, paginación y
   demás controles del wrapper se quedan quietos. Si la tabla cabe, sigue
   ocupando el 100% (antes, con display:block sobre la propia tabla en <992px,
   encogía a su contenido y dejaba un hueco a la derecha). */
.dataTables_wrapper .mt-dt-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

/* Columnas de fecha (dataType date/datetime; la clase la pone DataTableComun en
   el th). Su contenido es de ancho fijo (dd/mm/yyyy hh:mm) pero, al ser de las
   pocas columnas sin tope, el layout automático les endosaba el ancho sobrante
   de la tabla — la Fecha del historial salía al triple de ancho que su dato. El
   !important gana al width inline que escribe el autoWidth de DataTables. */
table.dataTable thead th.dt-col-fecha {
    width: 150px !important;
}

/* Columna del nombre de la fila: se lee entera, hasta un 30 % del ancho de la
   tabla. El ancho lo calcula datatable-module.js (reservar_ancho_nombre) y lo
   deja en --mt-dt-nombre-ancho; sin la variable vale el tope común de 250px. */
table.dataTable thead th.mt-col-nombre {
    width: var(--mt-dt-nombre-ancho);
}
.dt-truncate td.mt-col-nombre {
    max-width: var(--mt-dt-nombre-ancho, 250px);
}

/* El <select> original que select2 deja oculto (clip) conserva su ancho previo
   al init; aunque es invisible, ese ancho cuenta para el scroll horizontal de la
   página y en móvil provocaba unos px de desbordamiento (visto en informes BI).
   El CSS upstream de select2 lo fija a 1px; este build no lo trae. */
.select2-hidden-accessible {
    width: 1px !important;
}

/* DataTables cierra su cabecera con un rgba(0,0,0,.3) y lo hace desde un
   selector más específico (thead>tr>th) que el genérico de aquí arriba, así que
   ganaba él: hay que repetir su forma para que la línea sea la del token. */
table.dataTable thead > tr > th,
table.dataTable thead > tr > td {
    border-bottom: 1px solid var(--mt-gray-300);
}

/* Orden de DataTables: UN solo indicador, pegado a la etiqueta.
   De serie DataTables pinta dos triángulos (:before ▲ + :after ▼) en absoluto a
   la derecha de la celda, lejos del texto, como un glifo suelto en la cabecera.
   Aquí el ▲ se retira y el ▼ pasa a flujo normal (position:static) para que
   caiga pegado tras el nombre. */
table.dataTable thead > tr > th.sorting,
table.dataTable thead > tr > th.sorting_asc,
table.dataTable thead > tr > th.sorting_desc {
    /* DataTables reserva 26px a la derecha para los triángulos absolutos: ya no
       hay nada absoluto que alojar y ese hueco descentraba la etiqueta */
    padding-right: 12px;
}

table.dataTable thead > tr > th.sorting:before,
table.dataTable thead > tr > th.sorting_asc:before,
table.dataTable thead > tr > th.sorting_desc:before {
    display: none;
}

table.dataTable thead > tr > th.sorting:after,
table.dataTable thead > tr > th.sorting_asc:after,
table.dataTable thead > tr > th.sorting_desc:after {
    position: static;
    display: inline-block;
    margin-left: .45em;
    /* styles.css legacy los pinta con la FontAwesome v4 a 14px: aquí se rehacen
       con la 7 y al tamaño que pide una etiqueta de 12,8px */
    font-family: "Font Awesome 7 Free";
    font-weight: 900;
    font-size: 9px;
    line-height: 1;
    vertical-align: middle;
    opacity: 1;
    color: var(--mt-gray-400);
    transition: color var(--mt-dur-fast) var(--mt-ease);
}

/* Ordenable pero sin ordenar: doble flecha tenue que se afirma al pasar por encima */
table.dataTable thead > tr > th.sorting:after { content: "\f0dc"; }
table.dataTable thead > tr > th.sorting:hover:after { color: var(--mt-gray-600); }

/* Columna ordenada: es lo único de la cabecera que se tiñe de marca */
table.dataTable thead > tr > th.sorting_asc,
table.dataTable thead > tr > th.sorting_desc {
    color: var(--mt-green-700);
}

table.dataTable thead > tr > th.sorting_asc:after {
    content: "\f0de";
    color: var(--mt-green-700);
}

table.dataTable thead > tr > th.sorting_desc:after {
    content: "\f0dd";
    color: var(--mt-green-700);
}

/* Columnas numéricas (th.text-end): el indicador pasa DELANTE de la etiqueta
   (tokens §5) para que el borde derecho del título coincida con las cifras. */
table.dataTable thead > tr > th.text-end.sorting:after,
table.dataTable thead > tr > th.text-end.sorting_asc:after,
table.dataTable thead > tr > th.text-end.sorting_desc:after {
    display: none;
}

table.dataTable thead > tr > th.text-end.sorting:before,
table.dataTable thead > tr > th.text-end.sorting_asc:before,
table.dataTable thead > tr > th.text-end.sorting_desc:before {
    display: inline-block;
    position: static;
    margin-right: .45em;
    font-family: "Font Awesome 7 Free";
    font-weight: 900;
    font-size: 9px;
    line-height: 1;
    vertical-align: middle;
    opacity: 1;
    color: var(--mt-gray-400);
    transition: color var(--mt-dur-fast) var(--mt-ease);
}

table.dataTable thead > tr > th.text-end.sorting:before { content: "\f0dc"; }
table.dataTable thead > tr > th.text-end.sorting:hover:before { color: var(--mt-gray-600); }
table.dataTable thead > tr > th.text-end.sorting_asc:before { content: "\f0de"; color: var(--mt-green-700); }
table.dataTable thead > tr > th.text-end.sorting_desc:before { content: "\f0dd"; color: var(--mt-green-700); }

/* Control de expandir/colapsar de DataTables Responsive. De serie lo pinta con los
   caracteres Unicode ► / ▼ (responsive.dataTables.min.css) al 50% de negro: como no
   son un icono sino texto, los renderiza la fuente de texto y quedan toscos y descuadrados.
   Aquí se rehacen con chevrons de la FA7, igual que las flechas de ordenación de
   arriba. Hay que repetir la forma del selector de la librería (table.dataTable
   .dtr-inline.collapsed > tbody > tr > td.dtr-control) porque tiene más
   especificidad que un selector corto y ganaría ella. */
table.dataTable.dtr-inline.collapsed > tbody > tr > td.dtr-control:before,
table.dataTable.dtr-inline.collapsed > tbody > tr > th.dtr-control:before {
    font-family: "Font Awesome 7 Free";
    font-weight: 900;
    font-size: 11px;
    content: "\f054";
    color: var(--mt-gray-400);
    /* Un único glifo que ROTA al expandir (en vez de cambiar \f054 por \f078 en
       seco): el giro con transición hace el despliegue suave. inline-block para
       que el transform tenga efecto sobre el pseudoelemento. */
    display: inline-block;
    transition: color var(--mt-dur-fast) var(--mt-ease),
                transform var(--mt-dur-fast) var(--mt-ease);
}

table.dataTable.dtr-inline.collapsed > tbody > tr.parent > td.dtr-control:before,
table.dataTable.dtr-inline.collapsed > tbody > tr.parent > th.dtr-control:before {
    /* Se repite el content: la hoja de Responsive trae su propia regla .parent
       con content:"▼" (carácter de texto) a la misma especificidad; sin esto
       gana ella y el ▼ girado 90° acaba apuntando a la izquierda. */
    content: "\f054";
    transform: rotate(90deg);
    color: var(--mt-green-700);
}

table.dataTable.dtr-inline.collapsed > tbody > tr > td.dtr-control:hover:before,
table.dataTable.dtr-inline.collapsed > tbody > tr > th.dtr-control:hover:before {
    color: var(--mt-green-700);
}

/* Chevron de grupos parent-child (a.dt-chevron-toggle, lo pinta
   chevron_function en renders_datatables.js): mismos colores que la flecha de
   detalle de Responsive de arriba — gris en reposo, verde al pasar la fila y
   con el grupo expandido — porque conviven en los mismos listados (en
   gestion_datos incluso en la misma celda) y deben leerse como el mismo
   control. El tamaño (11px) va inline en el propio icono. */
table.dataTable a.dt-chevron-toggle { color: var(--mt-gray-400); }
table.dataTable > tbody > tr:hover a.dt-chevron-toggle,
table.dataTable > tbody > tr.parent-shown a.dt-chevron-toggle {
    color: var(--mt-green-700);
}

/* El chevron va en el flujo de la celda, así que empuja al contenido que lleva
   detrás. Hay que resolverlo distinto según lo que haya en la primera columna:

   a) Columna de checkbox (el caso de la mayoría de listados, con bulkbar): el
      chevron se ancla a la izquierda, fuera del flujo, y el checkbox queda centrado
      en su columna. Si se deja en el flujo, el par chevron+checkbox se centra como
      grupo y el checkbox se va ~6px a la derecha del centro de la columna.
   b) Columna de texto: el chevron se queda en el flujo (en absoluto se solaparía con
      el texto) y es la cabecera la que reserva el mismo hueco con un glifo
      invisible, para que la etiqueta caiga alineada con el texto de las filas. */
table.dataTable.dtr-inline.collapsed > tbody > tr > td.dtr-control:has(> input[type="checkbox"]) {
    position: relative;
}

table.dataTable.dtr-inline.collapsed > tbody > tr > td.dtr-control:has(> input[type="checkbox"]):before {
    position: absolute;
    left: 6px;
    top: 50%;
    transform: translateY(-50%);
    margin-right: 0;
}

/* Variante con checkbox + fila expandida: el translateY del anclaje y el giro
   del despliegue tienen que convivir en el mismo transform. */
table.dataTable.dtr-inline.collapsed > tbody > tr.parent > td.dtr-control:has(> input[type="checkbox"]):before {
    transform: translateY(-50%) rotate(90deg);
}

/* Fila de grupo con columnas plegadas en una celda SIN checkbox (/controles): las
   dos flechas no caben en la columna (48px) y la segunda se recortaba. Se queda
   solo la del grupo, y el clic en la celda abre el grupo (renders_datatables.js);
   el detalle de columnas plegadas de un grupo va vacío y no se ofrece. */
table.dataTable.dtr-inline.collapsed > tbody > tr > td.dtr-control:has(> a.dt-chevron-toggle):before {
    content: none;
}
/* Mismo hueco a la derecha que deja la flecha de Responsive (margin-right de su
   :before), para que la del grupo caiga en la misma vertical que las demás filas. */
table.dataTable.dtr-inline.collapsed > tbody > tr > td.dtr-control > a.dt-chevron-toggle {
    margin-right: 5.5px;
}

/* Fila entera clicable cuando hay flecha de desplegar (handler en
   renders_datatables.js): cursor de mano en filas de grupo (chevron
   parent-child) y en filas de tablas con columnas plegadas por Responsive —
   incluidos los hijos inyectados de grupo, que despliegan su propio detalle.
   Las filas-detalle (tr.child, también la del hijo) no despliegan nada y
   quedan fuera. */
table.dataTable > tbody > tr:has(a.dt-chevron-toggle),
table.dataTable.dtr-inline.collapsed > tbody > tr:not(.child) {
    cursor: pointer;
}

/* El contenido del desplegable (fila hija de Responsive) lo inserta DataTables
   en el DOM de golpe; un fundido corto acompasado con el giro del chevron hace
   el despliegue suave sin animar alturas (que dan tirones con tablas anchas). */
@keyframes mt-dt-child-in {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: none; }
}

table.dataTable > tbody > tr.child ul.dtr-details {
    animation: mt-dt-child-in var(--mt-dur-fast) var(--mt-ease);
}

/* Maquetación del desplegable: de serie la lista es inline-block compacta (y hereda
   alineaciones de columna de la tabla). Aquí cada campo es una FILA a todo el ancho:
   etiqueta secundaria a la izquierda (gris, ancho fijo para que los valores queden
   en columna) y valor al lado, con separador suave entre filas. */
table.dataTable > tbody > tr.child > td.child {
    text-align: left;
    padding: 8px 16px 8px 48px;
}

table.dataTable > tbody > tr.child ul.dtr-details {
    display: block;
    width: 100%;
}

table.dataTable > tbody > tr.child ul.dtr-details > li {
    display: flex;
    align-items: baseline;
    gap: 16px;
    padding: 8px 0;
    border-bottom: 0; /* anula el border-bottom #efefef de serie; el separador va arriba */
}

/* Separador entre filas por border-top (y no bottom + :last-child a 0): así una
   fila fantasma oculta al final (ver regla de abajo) no deja línea suelta. */
table.dataTable > tbody > tr.child ul.dtr-details > li + li {
    border-top: 1px solid var(--mt-gray-100);
}

/* Campo sin etiqueta NI valor (p. ej. la preview de "primer elemento" cuando va
   vacía, cuya cabecera además no tiene texto): fuera del desplegable — dejaba
   una fila en blanco al final. */
table.dataTable > tbody > tr.child ul.dtr-details > li:has(> span.dtr-title:empty):has(> span.dtr-data:empty) {
    display: none;
}

table.dataTable > tbody > tr.child span.dtr-title {
    min-width: 160px;
    font-weight: 600;
    color: var(--mt-gray-600);
}

table.dataTable.dtr-inline.collapsed > thead > tr > th:first-child:before {
    font-family: "Font Awesome 7 Free";
    font-weight: 900;
    font-size: 11px;
    content: "\f054";
    display: inline-block;
    margin-right: .5em;
    /* la cabecera lleva letter-spacing y el pseudo lo heredaría, metiendo un pelo de
       tracking de más tras el chevron fantasma */
    letter-spacing: normal;
    visibility: hidden;
}

/* Caso (a): si la cabecera es un checkbox, su chevron de las filas ya no ocupa sitio,
   así que aquí tampoco hay que reservarlo */
table.dataTable.dtr-inline.collapsed > thead > tr > th:first-child:has(> input[type="checkbox"]):before {
    content: none;
}

/* Los checkboxes de las tablas (columna de selección del bulkbar) van con el
   vertical-align:baseline de serie del input: se apoyan en la línea base del texto y
   dejan hueco para los descendentes debajo, así que quedan ~2px por encima del centro
   de la fila. Al lado del chevron, que sí está centrado, se nota. */
table.dataTable > thead > tr > th > input[type="checkbox"],
table.dataTable > tbody > tr > td > input[type="checkbox"] {
    vertical-align: middle;
}

/* Cuando el checkbox es lo único que hay en la celda, se pasa a bloque: así lo centra
   la propia celda (el vertical-align:middle del <td> centra el content box dentro del
   padding box) en vez de colgarlo de la línea base del texto. Es lo que hace falta
   para que coincida con el chevron, que al ser absolute se centra por geometría contra
   ese mismo padding box: con vertical-align el checkbox se quedaba ~1px más abajo que
   el eje del chevron, porque middle alinea con la mitad de la altura-x de la fuente y
   no con el centro real de la caja. El margin auto le devuelve el centrado horizontal
   que el text-align de la celda ya no puede darle al ser un bloque. */
table.dataTable > thead > tr > th > input[type="checkbox"]:only-child,
table.dataTable > tbody > tr > td > input[type="checkbox"]:only-child {
    display: block;
    margin: 0 auto;
}

/* Pista de que la columna se puede ordenar: la celda se marca al pasar por encima */
table.dataTable thead > tr > th.sorting:hover,
table.dataTable thead > tr > th.sorting_asc:hover,
table.dataTable thead > tr > th.sorting_desc:hover {
    background-color: var(--mt-gray-200);
}

table.dataTable tbody tr:hover {
    background-color: var(--mt-green-50);
}

/* Controles del wrapper de DataTables, discretos */
.dataTables_wrapper .dataTables_filter input,
.dataTables_wrapper .dataTables_length select {
    border: 1px solid var(--mt-gray-300);
    border-radius: var(--mt-radius-sm);
    padding: .25rem .5rem;
}

.dataTables_wrapper .dataTables_info {
    color: var(--mt-gray-500);
}

/* ------------------------------------------------------------------ */
/* 4. LIBRERÍAS YA CARGADAS                                           */
/* ------------------------------------------------------------------ */

/* DataTables 1.13 — selección de filas (por defecto azul #0d6efd) */
:root {
    --dt-row-selected: var(--mt-green-700-rgb);
    --dt-row-selected-text: 255, 255, 255;
    --dt-row-selected-link: 255, 255, 255;
}

/* Marco de tabla — variante T3 «densa con marco» (mockup aprobado 14/07/2026):
   marco de borde visible sin sombra, esquinas 10px, filas compactas, celdas
   13px. El radio en <table> necesita border-collapse separate y esquinas
   redondeadas también en las celdas extremas.
   Lo llevan de oficio las tablas de DataTables y, con la clase .mt-table, las
   tablas estáticas que quieran el mismo aspecto (p. ej. listados de modales): sin
   ella se quedan como una tabla pelada de Bootstrap, sin borde ni esquinas, y
   desentonan del resto de la app. */
table.dataTable,
table.mt-table {
    font-size: 15px;
    border: 1px solid var(--mt-gray-300);
    border-collapse: separate !important;
    border-spacing: 0;
    border-radius: var(--mt-radius-btn);
    /* clip y no hidden: recorta igual (fondos de fila sobre las esquinas
       redondeadas) pero NO convierte la tabla en contenedor de scroll, que
       anulaba el position:sticky de cabeceras dentro de la tabla (visto en la
       cabecera fija de /ektor_auditoria). */
    overflow: clip;
}

/* styles.css legacy le mete padding-top:6px !important a .dataTable: dejaba una
   franja blanca dentro del marco, sobre la cabecera */
table.dataTable {
    padding: 0 !important;
}

table.dataTable thead th,
table.dataTable thead td,
table.mt-table thead th,
table.mt-table thead td {
    padding: 8px 12px;
}

table.dataTable tbody th,
table.dataTable tbody td,
table.mt-table tbody th,
table.mt-table tbody td {
    padding: 7px 12px;
    /* Divisor en negro translúcido (no gris opaco): se adapta al fondo de la
       fila. Sobre filas blancas queda un gris suave; sobre filas coloreadas
       (estados rojo/verde) es una sombra del propio color, en vez de la línea
       blanca que cortaba el color. */
    border-bottom: 1px solid rgba(0, 0, 0, .18);
    /* Bootstrap alinea las celdas arriba (vertical-align: top del .table);
       con contenidos de distinta altura en la misma fila (iconos, chips,
       texto) cada celda quedaba a una altura distinta */
    vertical-align: middle;
}

table.dataTable tbody tr:last-child td,
table.mt-table tbody tr:last-child td { border-bottom: 0; }

table.dataTable thead tr:first-child th:first-child,
table.mt-table thead tr:first-child th:first-child { border-top-left-radius: calc(var(--mt-radius-btn) - 1px); }
table.dataTable thead tr:first-child th:last-child,
table.mt-table thead tr:first-child th:last-child { border-top-right-radius: calc(var(--mt-radius-btn) - 1px); }
table.dataTable tbody tr:last-child td:first-child,
table.mt-table tbody tr:last-child td:first-child { border-bottom-left-radius: calc(var(--mt-radius-btn) - 1px); }
table.dataTable tbody tr:last-child td:last-child,
table.mt-table tbody tr:last-child td:last-child { border-bottom-right-radius: calc(var(--mt-radius-btn) - 1px); }

/* Filtros por columna. La fila vive en el <tfoot> y styles.css la sube bajo la
   cabecera con display:table-header-group. Comparte el fondo de la cabecera para
   que nombre de columna + su filtro se lean como UNA sola cabecera de columna
   (antes eran dos bandas distintas: gris arriba, blanca debajo) con los inputs
   embutidos en blanco dentro del gris. */
table.dataTable tr.filter-row td {
    position: relative;
    /* padding vertical simétrico a propósito: deja el input centrado en la celda,
       y así la lupa y la X pueden anclarse con top:50% sin números mágicos */
    padding: 4px 8px;
    background: var(--mt-gray-100);
    border-bottom: 1px solid var(--mt-gray-300);
}

/* La línea de cierre de la cabecera la pone la fila de filtros: sin esto queda
   un corte entre la etiqueta y su filtro y vuelven a leerse como dos bandas.
   Va por clase y no por :has(tr.filter-row) porque la fila existe en el DOM aunque
   esté escondida (datatable-module.js la oculta con 0/1 resultados): en ese caso
   :has() seguía casando, la cabecera se quedaba sin borde y no la cerraba nadie, así
   que se fundía con la primera fila. La clase la pone ese mismo JS al alternarla. */
table.dataTable.mt-filtros-visibles thead > tr > th {
    border-bottom-color: transparent;
}

/* Un filtro de columna puede ser de texto o un desplegable (p. ej. Estado en
   /controles): misma caja para los dos, o la fila se ve descuadrada */
table.dataTable tr.filter-row .finput {
    width: 100%;
    height: 26px;
    border: 1px solid var(--mt-gray-200);
    border-radius: var(--mt-radius-sm);
    background-color: #fff;
    font-size: 12px;
    font-family: inherit;
    color: var(--mt-gray-800);
    transition: border-color var(--mt-dur-fast) var(--mt-ease),
                background-color var(--mt-dur-fast) var(--mt-ease),
                box-shadow var(--mt-dur-fast) var(--mt-ease);
}

table.dataTable tr.filter-row input.search_init {
    /* huecos para la lupa (izquierda) y la X de quitar filtro (derecha) */
    padding: 0 26px 0 24px;
}

/* El desplegable ya trae su propia flecha (Bootstrap la pinta a la derecha) */
table.dataTable tr.filter-row select.finput {
    padding: 0 24px 0 8px;
}

table.dataTable tr.filter-row .finput:hover { border-color: var(--mt-gray-300); }

table.dataTable tr.filter-row .finput:focus {
    outline: 0;
    border-color: var(--mt-green-300);
    box-shadow: var(--mt-focus-ring);
}

/* Lupa: la pinta el <td>, y solo donde hay filtro (hay columnas sin él) */
table.dataTable tr.filter-row td:has(input.search_init)::before {
    content: "\f002";
    font-family: "Font Awesome 7 Free";
    font-weight: 900;
    font-size: 10px;
    position: absolute;
    left: 17px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--mt-gray-400);
    pointer-events: none;
    transition: color var(--mt-dur-fast) var(--mt-ease);
}

/* Filtro relleno = columna acotada. Se tiñe de marca para poder ver de un
   vistazo QUÉ columnas están recortando la tabla sin leer sus valores.
   El de texto se detecta por el placeholder=" " que pone DataTableComun.php: es
   un espacio invisible que existe solo para que :placeholder-shown signifique
   "vacío". El desplegable, por que su opción elegida no sea la vacía («Todos»). */
table.dataTable tr.filter-row input.search_init:not(:placeholder-shown),
table.dataTable tr.filter-row select.finput:has(option:checked:not([value=""])) {
    background-color: var(--mt-green-50);
    border-color: var(--mt-green-200);
    color: var(--mt-gray-900);
}

table.dataTable tr.filter-row td:has(input.search_init:not(:placeholder-shown))::before {
    color: var(--mt-green-700);
}

/* En un desplegable la X sobra —para quitar el filtro se elige «Todos»— y encima
   chocaría con su flecha. Va con !important porque el JS se la pone en línea. */
table.dataTable tr.filter-row td:has(select.finput) .delfilter {
    display: none !important;
}

/* La X de quitar filtro: styles.css la deja con un top fijo, descentrada
   respecto al input nuevo */
table.dataTable tr.filter-row .delfilter {
    top: 50%;
    transform: translateY(-50%);
    right: 14px;
    color: var(--mt-gray-400);
    /* centra el glifo dentro de su caja de 16px (sin esto queda alto) */
    line-height: 16px;
    text-align: center;
    font-size: 12px;
    transition: color var(--mt-dur-fast) var(--mt-ease);
}

table.dataTable tr.filter-row .delfilter:hover { color: var(--mt-danger); }

/* Iconos de acción solos dentro de un enlace de celda (editar/eliminar…):
   sin el margin-right de `.dataTable .fa` (styles.css, pensado para iconos
   seguidos de texto). Ese margen ensancha el ancla por la derecha y descentra
   la burbuja del tooltip común respecto al glifo. */
.dataTable td a > .fa:only-child,
.dataTable td a > i:only-child {
    margin-right: 0;
}

/* Controles del wrapper discretos */
.dataTables_wrapper .dataTables_length,
.dataTables_wrapper .dataTables_filter,
.dataTables_wrapper .dataTables_info {
    color: var(--mt-gray-600);
    font-size: .85rem;
}

/* Loading tipo skeleton por celda (mockup aprobado): al lanzar cada petición
   AJAX, datatable-module.js pinta filas hueso en el tbody respetando las
   columnas; el draw las sustituye. La caja "Procesando..." sobra. */
div.dataTables_wrapper div.dataTables_processing { display: none !important; }

.mt-sk-overlay {
    position: absolute;
    z-index: 5;
    background: #fff;
    overflow: hidden;
    border-radius: 0 0 calc(var(--mt-radius-btn) - 1px) calc(var(--mt-radius-btn) - 1px);
}

.mt-sk-fila {
    display: flex;
    align-items: center;
    height: 39px;
    border-bottom: 1px solid var(--mt-gray-200);
}

.mt-sk-fila:last-child { border-bottom: 0; }

.mt-sk-celda {
    display: block;
    padding: 0 12px;
    flex: 0 0 auto;
    box-sizing: border-box;
}

.mt-sk {
    display: block;
    height: 13px;
    width: 80%;
    border-radius: var(--mt-radius);
    background: linear-gradient(90deg,
        var(--mt-gray-100) 25%, var(--mt-gray-200) 50%, var(--mt-gray-100) 75%);
    background-size: 400% 100%;
    animation: mt-shimmer 1.2s ease-in-out infinite;
}

/* Anchos alternos para que parezca contenido y no barras */
.mt-sk-celda:nth-child(2n) .mt-sk { width: 55%; }
.mt-sk-celda:nth-child(3n) .mt-sk { width: 95%; }

@keyframes mt-shimmer {
    0% { background-position: 100% 0; }
    100% { background-position: 0 0; }
}

@media (prefers-reduced-motion: reduce) {
    .mt-sk { animation: none; }
}

/* DataTables — paginación como el mockup T3: cuadraditos limpios sin marco,
   hover verde suave y solo la página actual en verde sólido */
.dataTables_wrapper .dataTables_paginate .paginate_button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 28px;
    height: 28px;
    padding: 0 5px;
    margin: 0 2px;
    border: 0;
    border-radius: var(--mt-radius-sm);
    background: transparent;
    color: var(--mt-gray-600) !important; /* el CSS de DataTables trae !important */
    font-size: 13px;
    font-variant-numeric: tabular-nums;
    text-decoration: none !important;
}

/* Distribución del wrapper: botones a la izquierda, info y paginación a la
   derecha; abajo la paginación repetida, también a la derecha */
.dataTables_wrapper .top {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 10px;
    /* Sticky bajo el navbar fijo (y bajo el banner de soporte si lo hay, ver
       support_banner.php): en listados largos la info + paginación siguen a
       mano mientras se hace scroll por la tabla. Si la tabla cabe en pantalla
       no cambia nada. Va arriba y no abajo para no chocar con la bulkbar
       flotante. Funciona porque el scroll horizontal lo lleva .mt-dt-scroll
       (solo la tabla), no el wrapper. Fondo opaco para tapar las filas. */
    position: sticky;
    top: calc(var(--mt-navbar-h, 76px) + var(--mt-soporte-h, 0px));
    z-index: var(--mt-z-sticky);
    background: var(--bs-body-bg);
    padding: 8px 0;
}

/* Opt-out del sticky de la fila .top: para tablas que no paginan (p. ej. la
   tabla de elementos de ficha_estructura_control) no aporta nada y choca con
   otras barras sticky de la página. Se envuelve el DataTable en este div. */
.mt-dt-top-static .dataTables_wrapper .top {
    position: static;
}

/* styles.css legacy reordena con flex order; fijamos el orden completo:
   botones · buscador · (hueco) · info · paginación */
.dataTables_wrapper .top .dt-buttons { order: 1; }
.dataTables_wrapper .top .dataTables_filter { order: 2; }
.dataTables_wrapper .top .dataTables_info {
    order: 3;
    margin-left: auto;
    padding-top: 0;
}
.dataTables_wrapper .top .dataTables_paginate { order: 4; }
.dataTables_wrapper .top .clear { order: 5; }

.dataTables_wrapper .bottom {
    display: flex;
    align-items: center;
    /* aire también por abajo y por la derecha: sin él la paginación queda
       pegada al borde del contenedor (y a la bulkbar cuando está activa) */
    margin-top: 10px;
    margin-bottom: 12px;
}

.dataTables_wrapper .bottom .dataTables_paginate {
    margin-left: auto;
    margin-right: 6px;
}

/* Layouts DataTables SIN fila .bottom (dom:'lrtip' — p. ej. las listas duales de
   los modales de proveedores): el paginado cuelga directo del wrapper, no recibe
   los márgenes de arriba y quedaba pegado a la tabla y al borde del bloque. Mismo
   aire que el estándar. */
.dataTables_wrapper > .dataTables_paginate {
    margin-top: 10px;
    margin-bottom: 12px;
}

.dataTables_wrapper .dataTables_paginate .paginate_button:hover {
    background: var(--mt-green-50);
    border: 0;
    color: var(--mt-green-700) !important;
}

.dataTables_wrapper .dataTables_paginate .paginate_button.current,
.dataTables_wrapper .dataTables_paginate .paginate_button.current:hover {
    background: var(--mt-green-700);
    border: 0;
    color: #fff !important;
    font-weight: 600;
}

.dataTables_wrapper .dataTables_paginate .paginate_button.disabled,
.dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover {
    background: transparent;
    color: var(--mt-gray-300) !important;
    cursor: default;
}

/* Botones del wrapper (Mostrar/Ocultar columnas, exports) como el mockup:
   blancos, borde neutro, radio de botón, hover verde. Los selectores con
   elemento delante ganan al CSS de DataTables Buttons (gradientes grises). */
.dataTables_wrapper button.dt-button,
.dataTables_wrapper div.dt-button,
.dataTables_wrapper a.dt-button {
    border: 1px solid var(--mt-gray-300);
    background: #fff;
    color: var(--mt-gray-700);
    border-radius: var(--mt-radius-btn);
    padding: 6px 14px;
    font-size: .85rem;
    font-family: inherit;
    line-height: 1.4;
}

.dataTables_wrapper button.dt-button:hover:not(.disabled),
.dataTables_wrapper div.dt-button:hover:not(.disabled),
.dataTables_wrapper a.dt-button:hover:not(.disabled) {
    border: 1px solid var(--mt-green-300);
    background: var(--mt-green-50);
    color: var(--mt-green-700);
}

.dataTables_wrapper button.dt-button:focus:not(.disabled) {
    background: #fff;
    color: var(--mt-gray-700);
    border: 1px solid var(--mt-gray-300);
    box-shadow: var(--mt-focus-ring);
    text-shadow: none;
}

.dataTables_wrapper button.dt-button.active:not(.disabled),
.dataTables_wrapper button.dt-button:active:not(.disabled) {
    background: var(--mt-green-50);
    color: var(--mt-green-700);
    border: 1px solid var(--mt-green-300);
    box-shadow: none;
}

/* Desplegable del botón "Mostrar/Ocultar columnas" (colvis). El estilo pill de
   los .dt-button del wrapper (arriba) le gana al CSS de DataTables Buttons y se
   colaba en los items del desplegable; aquí se restaura el aspecto de dropdown
   (tarjeta blanca + items de menú full-width), alineado con el de Select2 (abajo). */
div.dt-button-collection {
    width: 220px;
    padding: .3rem;
    border: 1px solid var(--mt-gray-200);
    border-radius: var(--mt-radius);
    box-shadow: var(--mt-shadow-lg);
}

.dataTables_wrapper div.dt-button-collection button.dt-button {
    display: block;
    width: 100%;
    margin: 0;
    border: 0;
    border-radius: var(--mt-radius);
    padding: .4rem .75rem;
    background: none;
    color: var(--mt-gray-700);
    text-align: left;
    box-shadow: none;
}

/* El ✓ del item activo lo pinta Buttons con :after posicionado a la derecha;
   se recupera su hueco (el padding de arriba pisa el del CSS de Buttons). */
.dataTables_wrapper div.dt-button-collection button.dt-button.dt-button-active {
    padding-right: 3em;
}

.dataTables_wrapper div.dt-button-collection button.dt-button:hover:not(.disabled),
.dataTables_wrapper div.dt-button-collection button.dt-button:focus:not(.disabled) {
    border: 0;
    background: var(--mt-green-50);
    color: var(--mt-green-700);
    box-shadow: none;
}

/* Select2 (tema bootstrap-5, que trae los azules de serie). Los selectores
   replican los del tema (compuestos) para ganarle en el cascade. */
.select2-container--bootstrap-5 .select2-dropdown .select2-results__options .select2-results__option.select2-results__option--highlighted {
    background-color: var(--mt-green-50);
    color: var(--mt-green-900);
}

/* Seleccionado: verde marca SIEMPRE, aunque select2 lo deje «resaltado» (al quitar
   un item re-resalta el primero de la lista y si el resaltado gana se queda con el
   color de hover hasta mover el ratón). El :not(.select2-results__message) no excluye
   nada relevante: está para IGUALAR la especificidad de la regla azul del tema
   ([aria-selected=true]:not(--highlighted)) y ganarle por orden de carga. */
.select2-container--bootstrap-5 .select2-dropdown .select2-results__options .select2-results__option.select2-results__option--selected,
.select2-container--bootstrap-5 .select2-dropdown .select2-results__options .select2-results__option[aria-selected="true"]:not(.select2-results__message) {
    background-color: var(--mt-green-700);
    color: #fff;
}

/* Seleccionado con el cursor/teclado encima: un punto más claro como feedback */
.select2-container--bootstrap-5 .select2-dropdown .select2-results__options .select2-results__option.select2-results__option--highlighted.select2-results__option--selected,
.select2-container--bootstrap-5 .select2-dropdown .select2-results__options .select2-results__option.select2-results__option--highlighted[aria-selected="true"] {
    background-color: var(--mt-green-600);
    color: #fff;
}

/* El seleccionado lleva ✓ como en los pickers nativos (base-select), solo en
   selects simples: en los múltiples el tema ya pinta su propio check */
.select2-container--bootstrap-5 .select2-dropdown .select2-results__options:not([aria-multiselectable="true"]) .select2-results__option.select2-results__option--selected::before,
.select2-container--bootstrap-5 .select2-dropdown .select2-results__options:not([aria-multiselectable="true"]) .select2-results__option[aria-selected="true"]::before {
    content: "✓ ";
}

.select2-container--bootstrap-5.select2-container--focus .select2-selection,
.select2-container--bootstrap-5.select2-container--open .select2-selection {
    border-color: var(--mt-green-300);
    box-shadow: var(--mt-focus-ring);
}

/* La caja del desplegable, igual que el picker de los selects nativos (arriba):
   tarjeta blanca redondeada con aire e items con radio. Se incluyen las variantes
   --below/--above porque el tema les quita el radio del lado pegado al control. */
.select2-container--bootstrap-5 .select2-dropdown,
.select2-container--bootstrap-5 .select2-dropdown.select2-dropdown--below,
.select2-container--bootstrap-5 .select2-dropdown.select2-dropdown--above {
    border-color: var(--mt-gray-200);
    border-radius: var(--mt-radius);
    overflow: hidden;
    box-shadow: var(--mt-shadow-lg);
    padding: .3rem;
}

.select2-container--bootstrap-5 .select2-dropdown .select2-results__options .select2-results__option {
    padding: .4rem .75rem;
    border-radius: var(--mt-radius);
}

/* Scrollbar ALINEADO al borde del panel: con el padding de .3rem del dropdown, la
   barra de scroll de la lista quedaba flotando a ~5px del borde derecho y se veía
   descolocada. El margin negativo acerca el borde del contenedor (donde pinta el
   navegador la barra) al borde del panel — a medio camino, no pegada del todo
   (feedback del usuario) — y el padding-right equivalente mantiene los items con
   su aire de siempre respecto a la barra. */
.select2-container--bootstrap-5 .select2-dropdown .select2-results__options {
    margin-right: -.15rem;
    padding-right: .15rem;
}

.select2-container--bootstrap-5 .select2-dropdown .select2-search.select2-search--dropdown {
    padding: 0 0 .3rem;
}

.select2-container--bootstrap-5 .select2-dropdown .select2-search .select2-search__field {
    border-radius: var(--mt-radius);
}

.select2-container--bootstrap-5 .select2-dropdown .select2-search .select2-search__field:focus {
    border-color: var(--mt-green-300);
    box-shadow: var(--mt-focus-ring);
}

/* ------------------------------------------------------------------ */
/* Movimiento de los desplegables (guía §9): entrada tipo menú de      */
/* Google — despliegue con fundido + escala desde el control           */
/* ------------------------------------------------------------------ */
/* OJO: usar las propiedades individuales translate/scale, NO transform.
   Popper posiciona los .dropdown-menu de Bootstrap con un transform inline
   (translate3d) y una animación sobre transform lo pisa mientras dura: el
   menú aparece un instante en la esquina superior izquierda y luego salta
   a su sitio. translate/scale se COMPONEN con ese transform inline. */
@keyframes mt-dropdown-in {
    from { opacity: 0; translate: 0 -8px; scale: .97; }
    to   { opacity: 1; translate: 0 0; scale: 1; }
}

@keyframes mt-dropdown-in-up {
    from { opacity: 0; translate: 0 8px; scale: .97; }
    to   { opacity: 1; translate: 0 0; scale: 1; }
}

/* Los .dropdown-menu de Bootstrap, además, no pueden llevar scale. Popper los coloca
   ENTERAMENTE con el transform inline (deja top/left a 0), y las propiedades
   individuales se componen en el orden translate·rotate·scale·transform: el scale
   multiplica también ese vector de posición. Con un menú en translate(1375px, 529px),
   un scale de .97 lo desplaza 41px en x y 16px en y, y se ve entrar en diagonal desde
   el origen de la página. transform-origin no lo salva, porque el vector de Popper no
   depende del origen. Aquí, solo fundido y deslizamiento vertical.
   Select2 no tiene este problema: posiciona su desplegable con top/left, no con
   transform, así que se queda con la escala de arriba. */
@keyframes mt-dropdown-in-sin-escala {
    from { opacity: 0; translate: 0 -8px; }
    to   { opacity: 1; translate: 0 0; }
}

/* Entrada de los desplegables: select2 y dropdowns de Bootstrap */
.select2-container--bootstrap-5 .select2-dropdown {
    animation: mt-dropdown-in var(--mt-dur) var(--mt-ease);
    transform-origin: top center;
}

.dropdown-menu.show {
    animation: mt-dropdown-in-sin-escala var(--mt-dur) var(--mt-ease);
}

/* Si el desplegable abre hacia arriba, se despliega desde abajo */
.select2-container--bootstrap-5 .select2-dropdown.select2-dropdown--above {
    animation-name: mt-dropdown-in-up;
    transform-origin: bottom center;
}

/* Pickers de selects nativos (base-select) */
@supports (appearance: base-select) {
    select.form-select::picker(select),
    select.form-control::picker(select) {
        animation: mt-dropdown-in var(--mt-dur) var(--mt-ease);
        transform-origin: top center;
    }
}

@media (prefers-reduced-motion: reduce) {
    .select2-container--bootstrap-5 .select2-dropdown,
    .dropdown-menu.show,
    select.form-select::picker(select),
    select.form-control::picker(select) {
        animation: none;
    }
}

/* Pulso del control al ELEGIR una opción (la clase la añade y retira el handler
   global de pages/js/helpers.php): anillo verde que se expande y desvanece. El
   focus-ring se mantiene como segunda capa para no parpadear mientras anima. */
@keyframes mt-select-pulse {
    from { box-shadow: 0 0 0 0 rgba(38, 86, 66, .28), var(--mt-focus-ring); }
    to   { box-shadow: 0 0 0 .5rem rgba(38, 86, 66, 0), var(--mt-focus-ring); }
}

.mt-select-pulse {
    animation: mt-select-pulse .4s var(--mt-ease);
}

@media (prefers-reduced-motion: reduce) {
    .mt-select-pulse { animation: none; }
}

/* bootstrap-datepicker 1.10 — día activo/rango (azul con gradiente de serie) */
.datepicker table tr td.active,
.datepicker table tr td.active:hover,
.datepicker table tr td.active.disabled,
.datepicker table tr td.active.disabled:hover,
.datepicker table tr td.active.active,
.datepicker table tr td.active.highlighted.active,
.datepicker table tr td span.active.active,
.datepicker table tr td span.active:hover.active {
    background-image: none;
    background-color: var(--mt-green-700);
    border-color: var(--mt-green-800);
    color: #fff;
}

.datepicker table tr td.today,
.datepicker table tr td.today:hover,
.datepicker table tr td.today.disabled,
.datepicker table tr td.today.disabled:hover {
    background-image: none;
    background-color: var(--mt-green-100);
    border-color: var(--mt-green-200);
    color: var(--mt-green-900);
}

/* Botones del pie del calendario («Hoy» de todayBtn, «Borrar» de clearBtn): de serie
   vienen como bloque gris con gradiente tipo btn-default; los dejamos como acción
   discreta en verde corporativo, a juego con el hover del addon de fecha. */
.datepicker tfoot tr th.today,
.datepicker tfoot tr th.clear {
    background-image: none;
    background-color: transparent;
    color: var(--mt-green-700);
    font-weight: 600;
    border-radius: var(--mt-radius-sm);
    transition: background-color var(--mt-dur-fast) var(--mt-ease),
                color var(--mt-dur-fast) var(--mt-ease);
}

.datepicker tfoot tr th.today:hover,
.datepicker tfoot tr th.clear:hover {
    background-image: none;
    background-color: var(--mt-green-50);
    color: var(--mt-green-800);
}

/* Botón-addon del calendario en los campos de fecha (patrón .input-group.date
   del proyecto): al hacer clic abre el datepicker, así que debe comportarse
   como botón — cursor de mano y hover, como los addons de los inputs con lupa. */
/* El shim v4 de FA7 pinta `fa fa-calendar` en SOLID (weight 900) y el icono se ve
   "en negrita"; con weight 400 el mismo glifo renderiza en su variante REGULAR
   (trazo fino, incluida en FA Free). Solo aquí — no tocar .fa global. */
.input-group.date .input-group-text .fa-calendar {
    font-weight: 400;
}

/* styles.css legacy (`.date .input-group-text`) lo deja gris, sin borde y sin
   radio, y el icono queda como una pieza suelta; lo devolvemos al estándar del
   sistema: mismo borde que el input, pegado a él (esquinas rectas en la unión)
   y redondeado SOLO por la derecha, para que input+icono se lean como un único
   control. */
.input-group.date .input-group-text {
    cursor: pointer;
    background-color: #fff;
    border: 1px solid var(--mt-gray-300);
    border-radius: 0 var(--mt-radius-sm) var(--mt-radius-sm) 0;
    transition: background-color var(--mt-dur-fast) var(--mt-ease),
                color var(--mt-dur-fast) var(--mt-ease);
}

.input-group.date .input-group-text:hover {
    background-color: var(--mt-green-50);
    color: var(--mt-green-700);
}

/* SweetAlert2 — botón de confirmación (azul #3085d6 de serie; ojo, las vistas
   suelen pasar SWEET_ALERT_BTN_CONFIRMAR_COLOR = #e20010 por parámetro, que
   gana a este CSS: se corregirá en Constants.php al implementar) */
.swal2-styled.swal2-confirm {
    background-color: var(--mt-green-700);
}

.swal2-styled.swal2-confirm:focus {
    box-shadow: var(--mt-focus-ring);
}

/* Espaciado de los diálogos: de serie el título, el texto y los botones quedan
   muy pegados entre sí. Aire con pasos de la escala (§7: 12/24). */
.swal2-title {
    padding-top: 24px;
}

.swal2-html-container {
    margin-top: 12px;
    line-height: 1.5;
}

.swal2-actions {
    margin-top: 24px;
}

.swal2-popup {
    padding-bottom: 24px;
}

/* ------------------------------------------------------------------ */
/* 5. COMPONENTES MEATTRACK                                           */
/* ------------------------------------------------------------------ */

/* Resumen de período (n% completado · X/Y registros · incidencias) — compartido
   por las vistas diaria/semanal/mensual del calendario. */
.mt-vd-resumen {
    font-size: .92rem;
    color: var(--mt-gray-600);
    background: var(--mt-gray-50);
}

.mt-vd-resumen strong {
    font-weight: 400;
    color: var(--mt-gray-900);
    font-variant-numeric: tabular-nums;
}

.mt-vd-resumen i {
    font-size: 1.15rem;
    vertical-align: -.12em;
}

/* Skeleton loader — placeholder con shimmer para cargas de página/bloque.
   Un bloque = un .mt-skeleton; la composición (filas, columnas, rejilla)
   la pone cada vista con utilidades de layout. */
.mt-skeleton {
    background: var(--mt-gray-100);
    border-radius: var(--mt-radius);
    position: relative;
    overflow: hidden;
}

.mt-skeleton::after {
    content: "";
    position: absolute;
    inset: 0;
    transform: translateX(-100%);
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .65), transparent);
    animation: mt-skeleton-shimmer 1.4s ease-in-out infinite;
}

@keyframes mt-skeleton-shimmer {
    100% { transform: translateX(100%); }
}

@media (prefers-reduced-motion: reduce) {
    .mt-skeleton::after { animation: none; }
}

/* Píldora de recuento — nº de hijos de una agrupación en tablas/listas
   (sustituye al "(N)" en texto plano). Sin punto de estado: es un contador,
   no un veredicto. OJO: no usar .badge (position:absolute legacy). */
.mt-count-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.7em;
    /* line-height 1 + padding vertical simétrico: con 1.5 el dígito quedaba
       ópticamente descentrado dentro de la píldora (Inter deja más aire bajo
       la cifra que sobre ella). */
    padding: .3em .55em;
    border-radius: var(--mt-radius-pill);
    background-color: var(--mt-gray-100);
    border: 1px solid var(--mt-gray-200);
    color: var(--mt-gray-600);
    font-size: .78em;
    font-weight: 600;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Variante de alarma del contador (incidencias pendientes…): misma anatomía,
   colores del chip danger. El número ya es la señal — sin icono extra. */
.mt-count-pill.mt-count-pill-danger {
    background-color: var(--mt-danger-subtle);
    border-color: var(--mt-danger-border);
    color: var(--mt-danger-emphasis);
}

/* Selector segmentado (.mt-seg) — grupo de opciones excluyentes de un mismo
   nivel (salas del resumen de registro): banda gray-100 con el segmento activo
   en blanco elevado. Es el hermano sobre fondo claro del segmentado de cierre
   de incidencias (.mt-inc-estado-seg, que vive sobre el pie de color). No es
   un tab canónico: se usa como SEGUNDO nivel de navegación bajo unos tabs, o
   para alternar vistas equivalentes de un mismo contenido. */
.mt-seg {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 3px;
    border-radius: var(--mt-radius);
    background-color: var(--mt-gray-100);
    border: 1px solid var(--mt-gray-200);
}

.mt-seg-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    border: 0;
    margin: 0;
    padding: 6px 14px;
    border-radius: calc(var(--mt-radius) - 2px);
    background: transparent;
    color: var(--mt-gray-600);
    font-size: var(--mt-fs-body-sm);
    font-weight: 600;
    line-height: 1.4;
    white-space: nowrap;
    transition: background-color var(--mt-dur-fast) var(--mt-ease), color var(--mt-dur-fast) var(--mt-ease);
}

.mt-seg-btn:hover {
    color: var(--mt-gray-800);
}

.mt-seg-btn.active {
    background-color: #fff;
    color: var(--mt-gray-900);
    box-shadow: var(--mt-shadow-sm);
}

/* Chip de estado — lenguaje único de veredictos/estados en toda la app.
   Anatomía: punto de color + texto, pill, fondo subtle + texto emphasis. */
.mt-chip {
    display: inline-flex;
    align-items: center;
    gap: .45em;
    padding: .25em .75em;
    border-radius: var(--mt-radius-pill);
    border: 1px solid transparent;
    font-size: .875em;
    font-weight: 500;
    line-height: 1.4;
    white-space: nowrap;
}

.mt-chip::before {
    content: "";
    flex: none;
    width: .55em;
    height: .55em;
    border-radius: 50%;
    background-color: var(--mt-chip-dot, currentColor);
}

/* Aviso operativo destacado (mismo estilo que el pad de detectores de la
   tablet): rectángulo redondeado —no pill—, cuerpo grande y negrita, para que
   el aviso se vea a la primera entre los botones de la banda. */
.mt-chip-lg {
    font-size: 1rem;
    font-weight: 700;
    padding: .45em 1.1em;
    border-radius: var(--mt-radius);
}

/* Naranja: avisos operativos (turno de metales olvidado). A diferencia del
   resto de variantes lleva el borde fuerte, porque es un aviso, no un estado. */
.mt-chip-orange {
    --mt-chip-dot: var(--mt-orange);
    color: var(--mt-orange-emphasis);
    background-color: var(--mt-orange-subtle);
    border-color: var(--mt-orange);
}

/* El aviso lleva icono propio (reloj), así que va sin el punto de estado. */
.mt-chip-orange::before {
    display: none;
}

/* Aviso clicable (enlace): en hover se rellena del naranja fuerte para marcar
   que abre el detalle. */
a.mt-chip-orange:hover {
    --mt-chip-dot: #fff;
    color: #fff;
    background-color: var(--mt-orange);
    border-color: var(--mt-orange);
}

.mt-chip-success {
    --mt-chip-dot: var(--mt-success);
    color: var(--mt-success-emphasis);
    background-color: var(--mt-success-subtle);
    border-color: var(--mt-success-border);
}

.mt-chip-danger {
    --mt-chip-dot: var(--mt-danger);
    color: var(--mt-danger-emphasis);
    background-color: var(--mt-danger-subtle);
    border-color: var(--mt-danger-border);
}

.mt-chip-warning {
    --mt-chip-dot: var(--mt-warning);
    color: var(--mt-warning-emphasis);
    background-color: var(--mt-warning-subtle);
    border-color: var(--mt-warning-border);
}

/* Chip de veredicto clicable (enlace, p. ej. «Sin verificar» en la ficha del
   registro): mismo aspecto que el chip estático; en hover sube un paso el
   fondo como pista de que abre el modal de verificación. */
a.mt-chip {
    text-decoration: none;
}

a.mt-chip-warning:hover {
    background-color: var(--mt-warning-border);
    border-color: var(--mt-warning);
}

.mt-chip-info {
    --mt-chip-dot: var(--mt-info);
    color: var(--mt-info-emphasis);
    background-color: var(--mt-info-subtle);
    border-color: var(--mt-info-border);
}

.mt-chip-neutral {
    --mt-chip-dot: var(--mt-gray-400);
    color: var(--mt-gray-700);
    background-color: var(--mt-gray-100);
    border-color: var(--mt-gray-300);
}

/* Tarea: no es un veredicto, marca el tipo de tarjeta (tareas del calendario)
   con el olive histórico de las notas. */
.mt-chip-tarea {
    --mt-chip-dot: var(--mt-tarea);
    color: var(--mt-tarea-emphasis);
    background-color: var(--mt-tarea-subtle);
    border-color: var(--mt-tarea-border);
}

.mt-chip-brand {
    --mt-chip-dot: var(--mt-green-500);
    color: var(--mt-green-900);
    background-color: var(--mt-green-50);
    border-color: var(--mt-green-200);
}

/* Badge de aviso «!» — puntito ámbar anclado a la esquina superior derecha de
   un botón (cambios pendientes en "Actualizar controles", preavisos pendientes...).
   El botón anfitrión necesita position:relative (utilidad Bootstrap
   .position-relative). Dentro va un <i class="fa fa-exclamation">, que hereda
   el color y el tamaño del badge. */
.mt-badge-aviso {
    position: absolute;
    top: -8px;
    right: -8px;
    min-width: 19px;
    height: 19px;
    padding: 0 4px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--mt-radius-pill);
    background-color: var(--mt-warning-strong);
    border: 2px solid #fff;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .35);
    color: #fff;
    font-size: 11px;
    line-height: 1;
}

/* Variante roja del badge «!» (aviso bloqueante: productos del detector sin elementos). */
.mt-badge-aviso.mt-badge-aviso-danger {
    background-color: var(--mt-danger);
}

/* Variante neutra: lo que indica el badge es solo informativo (p. ej. «Revisión
   pendiente» de Ektor detrás del chip de la columna Avisos de /controles). */
.mt-badge-aviso.mt-badge-aviso-neutral {
    background-color: var(--mt-gray-500);
}

/* Variante inline: el mismo círculo pero en flujo (junto a un texto de tabla, no anclado
   a la esquina de un botón). 18px para no romper la altura de fila. */
.mt-badge-aviso.mt-badge-aviso-inline {
    position: relative;
    top: -1px;
    right: auto;
    min-width: 18px;
    width: 18px;
    height: 18px;
    padding: 0;
    font-size: 10px;
    vertical-align: middle;
}
/* font-size:inherit: dentro de un DataTable, `.dataTable .fa` (styles.css) fija 15px al icono
   y el «!» se salía del círculo de 18px. */
.mt-badge-aviso.mt-badge-aviso-inline i { margin: 0; font-size: inherit; line-height: 1; }

/* Caja de registro (vista diaria, B×C): tarjeta blanca con acento de estado
   en el borde izquierdo. Sustituye a las cards con fondos de color plenos. */
.mt-card-registro {
    background-color: #fff;
    border: 1px solid var(--mt-gray-200);
    border-left: 4px solid var(--mt-gray-300);
    border-radius: var(--mt-radius);
    box-shadow: var(--mt-shadow-sm);
    transition: box-shadow var(--mt-dur-fast) var(--mt-ease);
}

.mt-card-registro:hover {
    box-shadow: var(--mt-shadow-lg);
}

.mt-card-registro.mt-estado-success { border-left-color: var(--mt-success); }
.mt-card-registro.mt-estado-danger { border-left-color: var(--mt-danger); }
.mt-card-registro.mt-estado-warning { border-left-color: var(--mt-warning); }
.mt-card-registro.mt-estado-brand { border-left-color: var(--mt-green-500); }
.mt-card-registro.mt-estado-info { border-left-color: var(--mt-info); }

/* Fila de registro (lista tipo bandeja): la variante SIN caja — filas continuas
   dentro de un único panel, separadas por línea fina, con el mismo acento de
   estado en el borde izquierdo. Es el formato de la vista diaria. */
.mt-list-row {
    background-color: #fff;
    border-left: 4px solid var(--mt-gray-300);
    border-bottom: 1px solid var(--mt-gray-200);
    transition: background-color var(--mt-dur-fast) var(--mt-ease);
}

.mt-list-row:hover {
    background-color: var(--mt-green-50);
}

.mt-list-row.mt-estado-success { border-left-color: var(--mt-success); }
.mt-list-row.mt-estado-danger { border-left-color: var(--mt-danger); }
.mt-list-row.mt-estado-warning { border-left-color: var(--mt-warning); }
.mt-list-row.mt-estado-brand { border-left-color: var(--mt-green-500); }
.mt-list-row.mt-estado-info { border-left-color: var(--mt-info); }

/* Las filas reutilizan card-header/card-body del markup existente, pero sin
   la piel de card: cabecera transparente y paddings compactos y continuos */
.mt-list-row > .card-header {
    background-color: transparent;
    border-bottom: 0;
    padding: .7rem 1.25rem .1rem;
}

.mt-list-row > .card-body {
    padding: .1rem 1.25rem .7rem;
}

/* Hilo de comentarios (modal de comentarios de registro, ILP, proveedores…):
   filas continuas dentro de un único marco con scroll propio, separadas por
   línea fina —nada de una card por comentario—, cabecera en UNA línea (autor ·
   «Tú» · fecha) con las acciones a la derecha, y el texto justo debajo. Los
   comentarios propios llevan el lavado green-50 del item activo. Los iconos de
   acción son la señal, así que van a 16px en un área táctil de 32px; el rojo
   destructivo se reserva al Swal de confirmación (tokens.md §18). */
.mt-comentarios {
    border: 1px solid var(--mt-gray-200);
    border-radius: var(--mt-radius);
    max-height: 340px;
    overflow-y: auto;
}

.mt-comentario {
    padding: 8px 12px;                 /* pasos 2 / 3 */
}

.mt-comentario + .mt-comentario {
    border-top: 1px solid var(--mt-gray-200);
}

.mt-comentario.mt-comentario-mio {
    background-color: var(--mt-green-50);
}

.mt-comentario-cabecera {
    display: flex;
    align-items: center;
    gap: 8px;
    min-height: 32px;
}

.mt-comentario-autor {
    font-weight: 600;
    color: var(--mt-gray-900);
}

/* «Tú»: marca de autoría, no un estado — pill pequeña sin punto de color */
.mt-comentario-propio {
    display: inline-flex;
    align-items: center;
    padding: 0 8px;
    border: 1px solid var(--mt-gray-300);
    border-radius: var(--mt-radius-pill);
    background-color: var(--mt-gray-100);
    color: var(--mt-gray-600);
    font-size: var(--mt-fs-caption);
    line-height: 18px;
}

.mt-comentario-fecha {
    font-size: var(--mt-fs-body-sm);
    color: var(--mt-gray-500);
    white-space: nowrap;
}

.mt-comentario-acciones {
    display: flex;
    align-items: center;
    gap: 4px;
    margin-left: auto;
}

.mt-comentario-accion {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    padding: 0;
    margin: 0;
    border: 0;
    border-radius: var(--mt-radius);
    background-color: transparent;
    color: var(--mt-gray-500);
    font-size: 16px;
    line-height: 1;
    transition: background-color var(--mt-dur-fast) var(--mt-ease), color var(--mt-dur-fast) var(--mt-ease);
}

.mt-comentario-accion:hover,
.mt-comentario-accion:focus-visible {
    background-color: var(--mt-gray-100);
    color: var(--mt-green-700);
    outline: 0;
}

.mt-comentario-accion.mt-comentario-accion-eliminar:hover,
.mt-comentario-accion.mt-comentario-accion-eliminar:focus-visible {
    color: var(--mt-danger-emphasis);
}

/* Los tooltips de las acciones salen a la IZQUIERDA del icono: la lista tiene
   overflow-y:auto (recorta también en X) y una burbuja encima o debajo quedaría
   cortada en la primera/última fila; a la izquierda siempre hay sitio. */
.mt-comentario-accion.has-tooltip::after {
    bottom: auto;
    left: auto;
    right: calc(100% + 10px);
    top: 50%;
    transform: translateY(-50%);
}

.mt-comentario-accion.has-tooltip::before {
    bottom: auto;
    left: auto;
    right: calc(100% - 2px);
    top: 50%;
    transform: translateY(-50%);
    border-color: transparent transparent transparent var(--mt-gray-900);
}

.mt-comentario-texto {
    margin-top: 4px;
    color: var(--mt-gray-800);
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.mt-comentario-editor {
    margin-top: 8px;
}

/* ── Hilo de comentarios en formato CHAT (WhatsApp/Telegram) ────────────────
   Variante del hilo de comentarios para modales donde el hilo se lee como una
   conversación: burbujas, las propias a la derecha con el lavado green-50 y las
   de los demás a la izquierda firmadas con el nombre. Ocupa bastante menos que
   una fila por comentario porque la hora y las acciones (lápiz / papelera) van
   dentro de la burbuja, en su pie. Los botones de acción siguen siendo
   .mt-comentario-accion (32px de área táctil, rojo reservado al Swal). Cuando
   el hilo no cabe hace scroll y se abre por el final, como un chat.
   Hoy lo usan el modal de comentarios de incidencias de planta y el «Comentario
   común» de los documentos de proveedor (/ver_documentos y el portal del
   proveedor); los demás modales de comentarios siguen con .mt-comentarios. */
.mt-chat {
    display: flex;
    flex-direction: column;
    gap: 8px;
    max-height: 340px;
    overflow-y: auto;
}

.mt-chat-fila {
    display: flex;
}

.mt-chat-fila-mia {
    justify-content: flex-end;
}

.mt-chat-burbuja {
    /* Como en un chat, la burbuja no llega al borde contrario: se ve de un
       vistazo de qué lado es cada mensaje. */
    max-width: 82%;
    padding: 8px 12px;
    border-radius: 12px 12px 12px 2px;
    background-color: var(--mt-gray-100);
}

.mt-chat-burbuja-mia {
    border-radius: 12px 12px 2px 12px;
    background-color: var(--mt-green-50);
}

.mt-chat-autor {
    font-size: var(--mt-fs-body-sm);
    font-weight: 600;
    color: var(--mt-green-700);
}

.mt-chat-texto {
    color: var(--mt-gray-900);
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.mt-chat-pie {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 4px;
    margin-top: 2px;
}

.mt-chat-hora {
    font-size: var(--mt-fs-body-sm);
    color: var(--mt-gray-500);
    white-space: nowrap;
}

.mt-chat-editor {
    margin-top: 8px;
}

/* Aire entre la topbar y el arranque del contenido: los títulos de página
   (h2 al inicio de cada vista) quedaban pegados a la barra. Acotado con
   [role="main"] porque .custom-container se reutiliza en header y banner. */
.custom-container[role="main"] {
    padding-top: .75rem;
}

/* Responsive móvil: .custom-container es width:88% (styles.css), que en un
   teléfono de ~390px regala ~47px de márgenes laterales que el contenido
   necesita. En pantallas pequeñas el contenedor pasa a ancho completo (el
   padding de 12px del container-fluid ya da el aire suficiente). */
@media (max-width: 767.98px) {
    .custom-container {
        width: 100%;
    }
}

/* Buscador compacto (variante A, mockup aprobado 14/07/2026): una card de una
   sola fila con labels pequeños en mayúsculas, acciones a la derecha y filtros
   secundarios plegados tras «Más filtros» (collapse de Bootstrap). Sustituye a
   la card «Buscador» de 3-4 filas; la cabecera verde sí se mantiene
   (.mt-buscador-head), igual que la caja de filtros de la tablet. */
.mt-buscador {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: .75rem .75rem;
    background-color: #fff;
    border: 1px solid var(--mt-gray-200);
    border-radius: var(--mt-radius);
    box-shadow: var(--mt-shadow-sm);
    padding: .875rem 1rem;
}

/* Cabecera «Filtros» de la barra: banda verde a sangre en la parte superior de
   la card, misma pieza que la caja de filtros de la tablet (IncidencesScreen:
   Green700 + título blanco). Va como primer hijo del flex y ocupa la fila
   entera; los márgenes negativos cancelan el padding de la card y el `+ 2rem`
   del ancho lo recupera (el 100% del flex mide solo la caja interior, sin el
   padding), para que la banda llegue a los dos bordes. El radio se descuenta
   1px (el grosor del borde) para que no asome un píxel gris en las esquinas
   superiores — el mismo inset de 1dp que hace la Card de la tablet. */
.mt-buscador-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
    flex: 0 0 calc(100% + 2rem);
    /* min-height para que la banda mida lo mismo lleve o no la píldora «Más
       filtros» (mismo criterio que el heightIn(min = 40.dp) de la tablet) */
    min-height: 3rem;
    margin: -.875rem -1rem 0;
    padding: .5rem 1rem;
    background-color: var(--mt-green-700);
    border: 0;
    border-radius: calc(var(--mt-radius) - 1px) calc(var(--mt-radius) - 1px) 0 0;
    color: #fff;
    font-family: var(--mt-font-display);
    font-size: 1rem;
    font-weight: 600;
    line-height: 1.4;
    text-align: left;
}

/* En los buscadores con filtros secundarios la cabecera es el propio disparador
   del plegable (un <button>): toda la banda es pulsable, no solo la píldora. */
button.mt-buscador-head {
    cursor: pointer;
    transition: background-color var(--mt-dur) var(--mt-ease);
}

button.mt-buscador-head:hover {
    background-color: var(--mt-green-800);
}

button.mt-buscador-head:focus-visible {
    outline: 2px solid #fff;
    outline-offset: -5px;
}

/* Un campo del buscador: label caption arriba + control debajo. El ancho lo
   pone cada vista inline (ajuste puntual de layout permitido). */
.mt-buscador-field {
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    min-width: 0;
}

/* Responsive: los campos con control crecen desde su ancho base (inline) hasta
   llenar la fila, así la barra usa todo el ancho y, cuando no cabe y salta de
   línea, cada fila queda llena en vez de dejar las acciones huérfanas junto a
   un hueco (captura consulta incidencias 22/07/2026). El tope evita selects
   desproporcionados en pantallas muy anchas, y el :has deja fuera los campos
   sin control (botones Hoy/Ayer, checkboxes), que no deben estirarse. */
.mt-buscador-field:has(.form-control) {
    flex: 1 1 auto;
    max-width: 26rem;
}

/* Contenedores de selects dinámicos (AJAX) vacíos: no dejan hueco */
.mt-buscador-field:empty { display: none; }

/* Botones rápidos junto a las fechas («Hoy»/«Ayer»): el btn-sm queda más bajo
   que los inputs; los igualamos a la altura real de estos (40px, fijada por el
   legacy `form input.form-control` de styles.css) */
.mt-buscador .btn-group > .btn {
    height: 40px;
    display: inline-flex;
    align-items: center;
}

.mt-buscador label {
    font-size: .72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: var(--mt-tracking-caps);
    color: var(--mt-gray-600);
    margin-bottom: .25rem;
}

/* Las vistas load_select_* llegan envueltas en .form-group con margen y
   padding legacy (styles.css: form .form-group { padding-bottom: 7px }) —
   sin el reset, sus selects quedan 7px más altos que el resto de campos */
.mt-buscador .form-group { margin-bottom: 0; padding-bottom: 0; }

/* Los select2 (también los que se cargan por AJAX) llenan el ancho del campo */
.mt-buscador-field .select2 { width: 100% !important; }

/* Subzonas AJAX (buscador de ficha de estructura): el parcial compartido
   load_select_subzonas trae wrappers col-md-* y una cabecera <h5>Subzonas</h5>
   pensados para los .row de los modales. En la barra compacta el select llena
   el campo y la cabecera sobra (el select ya lleva su propio label) */
.mt-buscador-field .dev_select_subzona {
    width: 100%;
    padding: 0;
}
.mt-buscador-field > div:has(> h5) { display: none; }

/* Los labels de checkbox son frase, no caption */
.mt-buscador .form-check-label,
.mt-buscador input[type="checkbox"] + label {
    text-transform: none;
    letter-spacing: 0;
    font-size: .85rem;
    font-weight: 400;
    color: var(--mt-gray-700);
    margin-bottom: 0;
}

.mt-buscador-actions {
    display: flex;
    align-items: center;
    gap: .5rem;
    margin-left: auto;
}

/* El .btn legacy (styles.css §10) trae margin-top:15px y margin-right:10px;
   hacían la fila de acciones más alta que los campos (el padding superior de
   la barra parecía mayor que el inferior). Dentro de la barra el espaciado
   lo pone el gap del contenedor. Además su padding 15px deja los botones a
   50px: los igualamos a los 40px de los inputs y del grupo Hoy/Ayer para que
   toda la fila comparta altura (antes sobresalían 10px por arriba). */
.mt-buscador-actions .btn {
    margin-top: 0;
    margin-right: 0;
    height: 40px;
    display: inline-flex;
    align-items: center;
}

/* Fila plegable de filtros secundarios: el div .collapse (w-100) anima la
   altura; esta fila interior es la que maqueta en flex */
.mt-buscador-mas {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: .75rem .75rem;
    padding-top: .375rem;
}

/* Toggle «Más filtros»: botón fantasma con borde para que se vea que es
   pulsable (el btn-link plano pasaba desapercibido), sin competir con la
   acción primaria (Buscar). Vive junto a los campos, no con las acciones. */
.mt-buscador-toggle {
    height: 40px;
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    padding: 0 .9rem;
    border: 1px solid var(--mt-gray-300);
    border-radius: var(--mt-radius);
    background: transparent;
    color: var(--mt-green-700);
    font-weight: 600;
    cursor: pointer;
    transition: background-color var(--mt-dur) var(--mt-ease), border-color var(--mt-dur) var(--mt-ease);
}

.mt-buscador-toggle:hover,
.mt-buscador-toggle[aria-expanded="true"] {
    background: var(--mt-green-50);
    border-color: var(--mt-green-300);
    color: var(--mt-green-700);
}

/* Dentro de la cabecera verde el toggle es solo la píldora indicadora (un
   <span>: quien recibe el clic es la cabecera entera). Blanco sólido para que
   destaque sobre la banda y más bajo, para que la cabecera no crezca a la
   altura de un control de formulario. */
.mt-buscador-head .mt-buscador-toggle {
    height: 32px;
    padding: 0 .75rem;
    background: #fff;
    border-color: #fff;
    color: var(--mt-green-700);
    font-size: .85rem;
}

.mt-buscador-head:hover .mt-buscador-toggle,
.mt-buscador-head[aria-expanded="true"] .mt-buscador-toggle {
    background: var(--mt-green-50);
    border-color: var(--mt-green-50);
    color: var(--mt-green-700);
}

/* Chevron del botón «Más filtros», girado cuando está desplegado */
.mt-buscador [data-bs-toggle="collapse"] i {
    transition: transform var(--mt-dur) var(--mt-ease);
}

.mt-buscador [data-bs-toggle="collapse"][aria-expanded="true"] i {
    transform: rotate(180deg);
}

@media (prefers-reduced-motion: reduce) {
    .mt-buscador [data-bs-toggle="collapse"] i { transition: none; }
}

/* Separación título de página ↔ fila de cabecera con el botón «Volver».
   Estos botones anulan el margin-top:15px legacy de .btn con un inline
   margin-top:0 (para alinearse entre ellos), lo que dejaba la fila pegada
   al <h2>. Damos aire desde la fila. El :has(.fa-arrow-left) lo acota a la
   fila que realmente lleva el botón de volver, no a cualquier .row tras un h2. */
h2 + .row:has(.fa-arrow-left) {
    margin-top: 1.5rem;
}

/* Menú lateral B×C (sidebar oscuro de marca): grupos con cabecera pequeña,
   items píldora, activo verde medio. Ver tokens.md §15.
   Fondo green-800: el 900 resultó demasiado oscuro (decisión 13/07/2026). */
.mt-sidebar {
    background-color: var(--mt-teal-800);
}

.mt-menu-heading {
    font-size: .68rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: var(--mt-tracking-caps);
    color: var(--mt-teal-400);
    margin: 1rem 0 .25rem;
    padding: 0 .75rem;
}

.mt-menu-link {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .45rem .75rem;
    border-radius: var(--mt-radius-btn);
    color: var(--mt-teal-100);
    text-decoration: none;
    font-weight: 500;
}

.mt-menu-link:hover {
    background-color: rgba(255, 255, 255, .08);
    color: #fff;
}

.mt-menu-link.active {
    background-color: var(--mt-teal-600);
    color: #fff;
}

.mt-menu-link .fa {
    width: 1.1em;
    text-align: center;
    color: var(--mt-teal-300);
}

.mt-menu-link:hover .fa,
.mt-menu-link.active .fa {
    color: #fff;
}

/* Banner de modo soporte: ámbar sobrio (atención, no catástrofe). Sticky bajo
   el navbar fijo. El body lleva padding-top 84px (navbar ~76px + respiro de 8px,
   ver header-private); el margin-top negativo cancela ese respiro para que el
   banner quede pegado al navbar, y el top sticky (76px = alto del navbar) lo
   mantiene ahí al hacer scroll — el navbar (z 1030) queda por encima. */
.mt-banner-soporte {
    background-color: var(--mt-warning-subtle);
    color: var(--mt-warning-emphasis);
    border-bottom: 1px solid var(--mt-warning-border);
    border-left: 4px solid var(--mt-warning);
    padding: 8px 16px;
    position: sticky;
    /* Altura REAL del navbar medida por JS (support_banner.php); con el 76px fijo,
       en cuanto el navbar no medía exactamente eso (zoom, resolución) el banner
       anclaba en un sitio distinto que las barras sticky de página (que miden el
       navbar por JS) y quedaba un hueco o solape entre ambos. */
    top: var(--mt-navbar-h, 76px);
    margin-top: -8px;
    /* +1 sobre los stickies normales (1020): el banner de soporte es el más
       importante y debe quedar SIEMPRE por encima de cualquier barra sticky de
       página (que se stackean debajo sumando --mt-soporte-h a su top, ver
       support_banner.php). Sigue por debajo del navbar fijo (1030). */
    z-index: calc(var(--mt-z-sticky) + 1);
}

@media (max-width: 767px) {
    .mt-banner-soporte { top: var(--mt-navbar-h, 80px); }
}

.mt-banner-soporte .btn-salir-soporte {
    background-color: transparent;
    border: 1px solid var(--mt-warning-emphasis);
    color: var(--mt-warning-emphasis);
    /* Compacto como btn-sm pero con el texto al tamaño del banner */
    padding: 3px 14px;
    font-size: 15px;
    /* styles.css legacy mete margin 15px 10px 0 0 a los .btn: desalineaba el
       botón y engordaba la fila del banner */
    margin: 0;
}

.mt-banner-soporte .btn-salir-soporte:hover {
    background-color: var(--mt-warning-emphasis);
    color: #fff;
}

/* Loading de página (.page_loading): lo muestran script.js (page_loading())
   y el sProcessing de DataTables. Nunca tuvo CSS (el div iba vacío e
   invisible); ahora es el spinner corporativo centrado. */
.page_loading {
    display: none;
    visibility: hidden;
    text-align: center;
    padding: 1.25rem 0;
}

/* Dentro del "Procesando..." de DataTables el wrapper lo muestra/oculta
   DataTables, así que el loading interno va siempre visible */
.dataTables_processing .page_loading {
    display: block;
    visibility: visible;
    padding: 0;
}

/* Overlay de carga estándar: se coloca dentro de un contenedor con
   position relative y lo cubre entero con el spinner corporativo. */
.mt-loading-overlay {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: rgba(255, 255, 255, .7);
    border-radius: inherit;
    z-index: 10;
}

/* Overlay de navegación a pantalla completa: feedback al pulsar botones de
   acción/navegación pequeños dentro de tablas (donde el spinner dentro del
   propio botón queda apretado). script.js lo inyecta al hacer clic y
   desaparece al cargar la nueva página. Mismo atenuado que
   .mt-loading-overlay pero fijado al viewport. */
.mt-page-overlay {
    position: fixed;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: rgba(255, 255, 255, .7);
    z-index: 2000;
}

/* Cifras tabulares para celdas numéricas de tablas (los números alinean) */
.mt-tnum {
    font-variant-numeric: tabular-nums;
}

/* ── Piezas de composición (tokens.md §12 y §18 — Refactoring UI) ─────────── */

/* Línea secundaria bajo un valor principal (celdas de tabla, filas de lista,
   stats): la jerarquía la dan tamaño y color, no una columna/etiqueta más */
.mt-sub {
    display: block;
    font-size: var(--mt-fs-body-sm);
    line-height: 1.4;
    color: var(--mt-gray-500);
}

/* Miniatura de imagen subida por el usuario (fotos de incidencias, imágenes de
   elementos) en celdas de tabla y listas: caja fija cuadrada con recorte
   (object-fit: cover), nunca al ratio intrínseco (tokens.md §18.7) — así todas
   las miniaturas miden lo mismo y la altura de fila no se dispara. El outline
   translúcido (pintado ENCIMA de la foto; un box-shadow inset quedaría tapado
   por la propia imagen) evita el «sangrado» de fotos con fondo blanco sobre la
   celda blanca. */
.mt-thumb {
    width: 48px;
    height: 48px;
    object-fit: cover;
    border-radius: var(--mt-radius);
    outline: 1px solid rgba(27, 33, 30, .08);   /* gray-900 al 8% */
    outline-offset: -1px;
    cursor: pointer;
}

/* Contador «+N» de imágenes adicionales: overlay DENTRO de la esquina de la
   miniatura (el td de DataTables lleva overflow hidden y un badge colgado fuera
   del borde se recorta). El contenedor de la miniatura debe llevar
   position-relative. */
.mt-thumb-badge {
    position: absolute;
    bottom: 2px;
    right: 2px;
    padding: 2px 4px;
    background-color: rgba(27, 33, 30, .65);    /* gray-900 al 65% */
    color: #fff;
    font-size: 10px;
    font-weight: 600;
    line-height: 1;
    border-radius: 4px;
    pointer-events: none;
}

/* Dato con etiqueta: la etiqueta es apoyo (caption uppercase gris) y el valor
   manda. Para cabeceras de resumen y paneles de cifras. */
.mt-stat {
    display: flex;
    flex-direction: column;
    gap: .25rem;                       /* espaciado paso 1 */
}

.mt-stat-label {
    font-size: var(--mt-fs-caption);
    font-weight: 600;
    letter-spacing: var(--mt-tracking-caps);
    text-transform: uppercase;
    color: var(--mt-gray-600);
}

.mt-stat-value {
    font-size: var(--mt-fs-h2);
    font-weight: 700;
    line-height: 1.2;
    color: var(--mt-gray-900);
    font-variant-numeric: tabular-nums;
}

/* Variante compacta del valor (H4 16px) para bandas densas de muchos stats. */
.mt-stat-value-sm {
    font-size: var(--mt-fs-h4);
    font-weight: 600;
    line-height: 1.3;
}

/* Cabecera de metadatos de fichas (ficha_estructura_control), estilo «ficha
   técnica»: cada par etiqueta-valor como stat vertical (caption encima del
   valor) fluyendo en horizontal para aprovechar el ancho de la tarjeta,
   agrupados por familias (registro / planificación / extras) con un hairline
   vertical entre grupos, y el pie de documento (código / revisión / fecha).
   Iteración 24/08/2026: la versión en columna fija etiqueta|valor dejaba
   media tarjeta vacía a la derecha. */
.mt-statband-card {
    background: #fff;
    border: 1px solid var(--mt-gray-200);
    border-radius: var(--mt-radius);
    box-shadow: var(--mt-shadow-sm);
    padding: 20px 24px;
}

.mt-statband-deflist {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    column-gap: 32px;
    row-gap: 16px;
}

/* Cada par etiqueta+valor: bloque vertical con la etiqueta caption encima. */
.mt-statband-stat {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}

/* Separación entre familias de stats (registro / planificación / extras): el
   último stat de cada familia lleva margen extra a la derecha, así el salto de
   familia se lee como espacio (32px dentro, 64px entre familias).
   Antes había un hairline vertical como elemento propio, pero con valores
   largos («Realizan el registro» con 15 usuarios) la fila envolvía y el
   hairline caía al principio de la línea siguiente: quedaba una rayita suelta
   y el resto de stats sangrados. El margen derecho es invisible cuando el
   stat termina la línea, así que no puede descolocar nada. */
.mt-statband-stat--fin-grupo {
    margin-right: 32px;
}

.mt-statband-deflist-label {
    font-size: var(--mt-fs-caption);
    font-weight: 600;
    letter-spacing: var(--mt-tracking-caps);
    text-transform: uppercase;
    color: var(--mt-gray-500);
}

.mt-statband-deflist-value {
    font-size: var(--mt-fs-h4);
    font-weight: 600;
    color: var(--mt-gray-900);
}

.mt-statband-deflist-value .mt-statband-sub {
    font-weight: 400;
    color: var(--mt-gray-600);
}

/* «X veces al día» con las horas en el tooltip común: subrayado punteado como
   pista de hover, y burbuja multilínea (la lista de horas desborda el nowrap
   por defecto de .has-tooltip). */
.mt-statband-sub .has-tooltip {
    text-decoration: underline dotted;
    text-underline-offset: 3px;
    cursor: help;
}

.mt-statband-sub .has-tooltip::after {
    white-space: normal;
    width: max-content;
    max-width: 320px;
}

/* En estrecho la fila no cabe: los stats se apilan en columna y la separación
   entre familias pasa de horizontal a vertical. */
@media only screen and (max-width: 575px) {
    .mt-statband-deflist {
        flex-direction: column;
        row-gap: 12px;
    }

    .mt-statband-stat--fin-grupo {
        margin-right: 0;
        margin-bottom: 8px;
    }
}

.mt-statband-foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-top: 16px;
    padding-top: 12px;
    border-top: 1px solid var(--mt-gray-200);
    font-size: var(--mt-fs-body-sm);
    color: var(--mt-gray-500);
}

.mt-statband-foot b {
    color: var(--mt-gray-700);
    font-weight: 600;
}

.mt-statband-dot {
    color: var(--mt-gray-300);
}

/* ── Pie de leyenda de las fichas (.mt-ficha-leyenda) ─────────────────────────
   Plegada por defecto (una línea con ellipsis) y botón «Ver leyenda» que la
   despliega, igual que en la tablet. Nació en la ficha de registro
   (ficha_control_calendario) y se comparte con la ficha de estructura. */
.mt-ficha-leyenda {
    display: flex;
    align-items: baseline;
    gap: 12px;
    padding: 11px 18px;
    border-top: 1px solid var(--mt-gray-200);
    background-color: var(--mt-gray-100);
    border-radius: 0 0 var(--mt-radius) var(--mt-radius);
    font-size: 13.5px;
}

.mt-ficha-leyenda .mt-leyenda-label {
    flex: none;
    font-size: 12.5px;
    color: var(--mt-gray-600);
}

.mt-ficha-leyenda .mt-leyenda-texto {
    flex: 1;
    min-width: 0;
    color: var(--mt-gray-700);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.mt-ficha-leyenda.mt-leyenda-abierta .mt-leyenda-texto {
    white-space: normal;
    overflow: visible;
}

/* Botón desnudo a propósito: con .btn heredaría el margin 15px 10px del legacy
   (styles.css §10) y descuadraría la línea del pie. */
.mt-ficha-leyenda .mt-leyenda-toggle {
    flex: none;
    background: none;
    border: 0;
    padding: 0;
    font-size: 13px;
    font-weight: 600;
    color: var(--mt-green-700);
    white-space: nowrap;
}

.mt-ficha-leyenda .mt-leyenda-toggle:hover {
    text-decoration: underline;
}

/* Dentro de la tarjeta de stats (ficha de estructura): la tarjeta lleva padding
   20px 24px, así que el pie sangra en negativo para ocupar el ancho completo. */
.mt-statband-card .mt-ficha-leyenda {
    margin: 16px -24px -20px;
}

/* Barra de acciones sticky de las fichas (Volver + Editar/Actualizar/…): al
   scrollear queda pegada bajo el navbar fijo (altura medida --mt-navbar-h,
   como el resto de stickies + banner de soporte si lo hay), con fondo blanco
   para tapar el contenido que pasa por debajo. La barra de revisión de carga
   IA (ficha_estructura_control) se apila debajo sumando los ~62px de esta. */
.mt-ficha-actions {
    position: sticky;
    top: calc(var(--mt-navbar-h, 76px) + var(--mt-soporte-h, 0px));
    z-index: var(--mt-z-sticky);
    background: #fff;
    /* Full-bleed: la superficie de la barra rompe el container (.custom-container,
       width 88% centrado) y ocupa todo el ancho del viewport, como el navbar; el
       padding horizontal devuelve el contenido a la alineación del container.
       100vw incluye el scrollbar, así que sobresale ~7px por cada lado: lo recorta
       el overflow-x:clip de <html> (regla de abajo). El sticky no se rompe porque
       el overflow se gestiona SOLO en <html> (ver memoria banner soporte). */
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
    padding: 12px calc(50vw - 50%);
    transition: box-shadow var(--mt-dur-fast) var(--mt-ease);
}

/* Recorte del desbordamiento horizontal del truco full-bleed (50vw incluye el
   ancho del scrollbar). En <body> y con clip, a propósito:
   - clip no crea scroll container → los position:sticky siguen anclando al
     scroller de la página;
   - en <body> (y NO en <html>): con overflow-x en <html>, el overflow:hidden
     que Bootstrap pone en <body> al abrir un modal dejaría de propagarse al
     viewport, el body pasaría a ser el scroll container (scroll 0) y las
     barras sticky «desaparecerían» mientras el modal está abierto;
   - como <html> queda visible, este clip del body se propaga al viewport y
     no aparece scrollbar horizontal. Las tablas anchas ya scrollean dentro
     de .mt-dt-scroll. */
body {
    overflow-x: clip;
}

/* El scroller de la página no re-ancla (scroll anchoring de Chrome): al abrir
   un modal, Bootstrap pone overflow:hidden en el body y las barras sticky
   full-bleed de las fichas cambian de geometría; el anclaje lo «compensaba»
   desplazando el documento (~98px de hueco al principio de la página, visible
   detrás del modal de Actualizar controles). Sin anclaje, el scroll se queda
   exactamente donde estaba. */
html {
    overflow-anchor: none;
}

/* Y el gesto de rueda/trackpad dentro de un modal alto no encadena al
   documento al llegar al tope (scroll chaining): la página de detrás se
   quedaba desplazada, el mismo hueco de arriba por otra vía. */
.modal {
    overscroll-behavior-y: contain;
}

/* Botón de quitar una miniatura (fotos de incidencia…): circulito con scrim
   oscuro translúcido y × blanca DENTRO de la esquina de la imagen — ni rojo
   (quitar una foto no es destructivo-semántico) ni desbordado (tapaba la
   línea de texto de arriba). */
.mt-foto-quitar {
    position: absolute;
    top: 4px;
    right: 4px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: rgba(var(--mt-gray-800-rgb), .55);
    color: #fff;
    font-size: 11px;
    line-height: 1;
    text-decoration: none;
    transition: background var(--mt-dur-fast) var(--mt-ease);
}

.mt-foto-quitar:hover,
.mt-foto-quitar:focus-visible {
    background: rgba(var(--mt-gray-800-rgb), .8);
    color: #fff;
}

/* Ancho contenido para selects/inputs de nombre de persona (§18.3: el ancho
   del control insinúa la longitud del dato; un nombre no necesita la fila
   entera cuando la columna se apila). La segunda regla capa también el
   contenedor que select2 inserta justo después del <select> original. */
.mt-w-nom {
    max-width: 320px;
}

.mt-w-nom + .select2-container {
    max-width: 320px;
}

.mt-ficha-actions > [class*="col-"] {
    padding-left: 0;
    padding-right: 0;
}

/* Pegada (is-stuck, JS de la ficha): deja de ser una fila suelta y se lee
   como barra — hairline inferior + sombra corta que la separa del contenido
   que pasa por debajo. */
.mt-ficha-actions.is-stuck {
    border-bottom: 1px solid var(--mt-gray-200);
    box-shadow: var(--mt-shadow-sm);
}

/* Hueco de la barra de ficha donde aterrizan las acciones de la cabecera de
   sección («Opciones control» / «Añadir elemento») cuando esa cabecera pasa por
   debajo, para tenerlas a mano con la lista recorrida (JS de la ficha de
   control). Vacío no ocupa: la barra se ve igual que siempre. */
.mt-ficha-actions-slot {
    display: inline-flex;
    align-items: center;
    gap: 8px;                          /* espaciado paso 2 */
    vertical-align: middle;
    margin-right: 8px;
}

.mt-ficha-actions-slot:empty {
    display: none;
}

/* Dentro de la barra mandan el gap y el alto de la fila, no los márgenes legacy
   de .btn (styles.css). */
.mt-ficha-actions-slot .btn {
    margin-top: 0;
    margin-right: 0;
}

/* Nombre del control dentro de la barra: aparece (is-stuck, JS de la ficha)
   solo cuando el título h2 de la página ya no se ve. */
.mt-ficha-actions .mt-ficha-actions-nom {
    min-width: 0;
    font-size: var(--mt-fs-h4);
    font-weight: 600;
    color: var(--mt-gray-900);
    opacity: 0;
    transition: opacity var(--mt-dur-fast) var(--mt-ease);
}

.mt-ficha-actions.is-stuck .mt-ficha-actions-nom {
    opacity: 1;
}

/* Barra de acciones de una sección (cabecera de la pestaña Elementos de la
   ficha de control: título + «Opciones control» / «Añadir elemento»). Son
   acciones del CONTENIDO, no del registro, así que viajan juntas y se pegan
   debajo de la barra de ficha en lugar de subir a ella. El top se apila sobre
   la altura real de esa barra (--mt-ficha-actions-h, publicada por el JS de la
   ficha) y no sobre un alto fijo, que se rompía si la fila hacía wrap. */
.mt-section-actions {
    position: sticky;
    top: calc(var(--mt-navbar-h, 76px) + var(--mt-soporte-h, 0px) + var(--mt-ficha-actions-h, 62px));
    /* Un escalón por debajo de la barra de ficha: al alcanzarla pasa bajo su
       sombra en vez de montarse encima. */
    z-index: calc(var(--mt-z-sticky) - 1);
    background: #fff;
    align-items: center;
    /* Mismo full-bleed que .mt-ficha-actions (ver arriba): la superficie tapa
       todo el ancho y el padding devuelve el contenido a la alineación del
       container. */
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
    padding: 10px calc(50vw - 50%);
    transition: box-shadow var(--mt-dur-fast) var(--mt-ease),
                padding-top var(--mt-dur-fast) var(--mt-ease),
                padding-bottom var(--mt-dur-fast) var(--mt-ease);
}

.mt-section-actions > [class*="col-"] {
    padding-left: 0;
    padding-right: 0;
}

/* Las dos barras acaban en el MISMO borde derecho. La regla general de arriba
   («Cabecera de página con la acción a la derecha») solo alcanza al último hijo
   cuando es el propio .btn: en la barra de ficha el último es el envoltorio del
   menú ⋮ (y en soporte, el form/btn-group de las cargas), así que el
   margin-right:10px legacy de styles.css se quedaba dentro y la fila de arriba
   terminaba 10px antes que la de abajo. `:last-of-type` y no `:last-child`
   porque dentro del envoltorio el botón lleva detrás su <ul class="dropdown-menu">,
   así que no es el último hijo. */
.mt-ficha-actions > [class*="col-"] > *:last-child > .btn:last-of-type,
.mt-section-actions > [class*="col-"] > *:last-child > .btn:last-of-type {
    margin-right: 0;
}

/* El alto de la barra lo marcan los botones (título sin margen, para que
   cambiar el título no mueva la caja). */
.mt-section-actions h3 {
    margin: 0;
    transition: font-size var(--mt-dur-fast) var(--mt-ease), color var(--mt-dur-fast) var(--mt-ease);
}

.mt-section-actions .btn {
    transition: padding var(--mt-dur-fast) var(--mt-ease);
}

/* Pegada: se lee como barra (hairline + sombra corta) y se compacta — menos
   aire propio y botones de 38px, el alto del .btn estándar de §7b, en vez de los
   50px generosos de styles.css. Con el navbar y la barra de ficha encima, cada
   píxel de cabecera es lista que no se ve. Encoger aquí NO provoca el bucle
   pegar → despegar: la posición de la barra EN EL FLUJO no cambia, solo su alto. */
.mt-section-actions.is-stuck {
    border-bottom: 1px solid var(--mt-gray-200);
    box-shadow: var(--mt-shadow-sm);
    padding-top: 8px;
    padding-bottom: 8px;
}

/* El título pasa a segundo plano (el nombre del registro ya lo enseña la barra
   de arriba) y desaparecen las acciones de arranque (.mt-solo-desplegada:
   cargar elementos con IA / desde Excel, solo soporte y solo con el control
   vacío), que no se usan recorriendo la lista. */
.mt-section-actions.is-stuck h3 {
    font-size: var(--mt-fs-h4);
    color: var(--mt-gray-600);
}

.mt-section-actions.is-stuck .btn {
    padding-top: 9px;
    padding-bottom: 9px;
}

.mt-section-actions.is-stuck .mt-solo-desplegada {
    display: none !important;
}

/* Variante estática (modo revisión de carga IA): manda la barra
   Aceptar/Descartar, que ya se apila bajo la de ficha; una tercera barra pegada
   dejaría media pantalla de cabeceras. */
.mt-section-actions-estatica {
    position: static;
}

/* Por debajo de lg las columnas de la barra se apilan (título arriba, botones
   debajo): pegada ocuparía el doble de alto en la pantalla que menos sitio
   tiene, así que ahí se queda quieta. */
@media (max-width: 991.98px) {
    .mt-section-actions {
        position: static;
    }
}

/* Párrafos legibles: 45–75 caracteres por línea (texto de ayuda, descripciones
   de modales, estados vacíos). Se aplica al bloque de texto, no al contenedor. */
.mt-prose {
    max-width: 65ch;
}

/* «Well»: bloque agrupado dentro de una card que debe leerse como unidad sin
   competir con ella (método de pago, resumen previo, sub-formulario). Hundido
   por color —fondo gray-50— en lugar de con borde. */
.mt-well {
    background-color: var(--mt-gray-50);
    border-radius: var(--mt-radius);
    padding: 1rem;                     /* espaciado paso 4 */
}

/* Tarjetas seleccionables (tokens.md §12 y §18.4): una opción importante como tarjeta
   pulsable en vez de un radio pelado. La tarjeta es un <label> que envuelve el radio
   (clic en toda la tarjeta) con título y, debajo, una vista previa o ayuda en .mt-sub.
   Marcada con .is-checked (la pone el JS de la vista; sin :has() por compatibilidad con
   navegadores antiguos): borde green-500 y fondo green-50. */
.mt-option-cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: .75rem;                       /* paso 3 */
}

.mt-option-card {
    display: flex;
    align-items: flex-start;
    gap: .75rem;                       /* paso 3 */
    margin: 0;
    padding: .75rem 1rem;              /* pasos 3 / 4 */
    background-color: var(--bs-white);
    border: 1px solid var(--mt-gray-200);
    border-radius: var(--mt-radius);
    cursor: pointer;
    transition: border-color var(--mt-dur-fast) var(--mt-ease), background-color var(--mt-dur-fast) var(--mt-ease);
}

.mt-option-card:hover {
    border-color: var(--mt-gray-300);
    background-color: var(--mt-gray-50);
}

.mt-option-card.is-checked {
    border-color: var(--mt-green-500);
    background-color: var(--mt-green-50);
}

.mt-option-card:focus-within {
    box-shadow: var(--mt-focus-ring);
}

.mt-option-card > .form-check-input {
    flex: none;
    margin: 2px 0 0;
}

.mt-option-card-body {
    min-width: 0;
}

.mt-option-card-title {
    display: block;
    font-weight: 600;
    color: var(--mt-gray-900);
}

/* Lista seleccionable (tokens.md §12): filas con checkbox para elegir varios
   elementos dentro de un modal (controles sin grupo → grupo destino…). Marco
   único con scroll propio; fila entera pulsable (es un <label>), hover verde
   suave y seleccionada en green-50. Sustituye a montar un DataTable de dos
   columnas solo para marcar filas. */
.mt-pick-list {
    max-height: 50vh;
    overflow-y: auto;
    border: 1px solid var(--mt-gray-200);
    border-radius: var(--mt-radius);
    background-color: #fff;
}

/* Cabecera de la lista (checkbox maestro + contador): mismo padding horizontal
   que las filas para que el checkbox maestro quede alineado con los de abajo */
.mt-pick-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
    padding: 0 1rem;
    margin-bottom: .5rem;              /* paso 2 */
}

.mt-pick-row {
    display: flex;
    align-items: center;
    gap: .75rem;                       /* paso 3 */
    margin: 0;
    padding: .6rem 1rem;
    border-bottom: 1px solid var(--mt-gray-200);
    cursor: pointer;
    transition: background-color var(--mt-dur-fast) var(--mt-ease);
}

.mt-pick-row:last-of-type {
    border-bottom: 0;
}

.mt-pick-row:hover {
    background-color: var(--mt-gray-50);
}

.mt-pick-row.is-checked {
    background-color: var(--mt-green-50);
}

.mt-pick-row > .form-check-input {
    flex: none;
    margin: 0;
}

.mt-pick-row-main {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Estado vacío: icono + mensaje + (opcional) acción, centrado y con aire.
   Sustituye al «No hay datos» pelado. El icono va a su tamaño (20px) dentro de
   un círculo gray-100: los iconos no se escalan a 3x. */
.mt-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: .5rem;                        /* paso 2 */
    padding: 3rem 1rem;                /* pasos 7 / 4 */
    color: var(--mt-gray-600);
}

.mt-empty-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 48px;
    height: 48px;
    margin-bottom: .5rem;
    border-radius: 50%;
    background-color: var(--mt-gray-100);
    color: var(--mt-gray-500);
    font-size: 20px;
}

.mt-empty-title {
    font-size: var(--mt-fs-h4);
    font-weight: 600;
    color: var(--mt-gray-800);
}

.mt-empty-text {
    max-width: 45ch;
    font-size: var(--mt-fs-body);
}

.mt-empty > .btn {
    margin-top: .5rem;
}

/* Variante compacta: celda de tabla vacía (es lo que skeleton.php inyecta como
   sZeroRecords de DataTables) y paneles pequeños — menos aire, icono contenido */
.mt-empty.mt-empty-sm {
    gap: .25rem;
    padding: 1.5rem 1rem;
}

.mt-empty.mt-empty-sm .mt-empty-icon {
    width: 40px;
    height: 40px;
    margin-bottom: .25rem;
    font-size: 18px;
}

/* ── Tooltip común de la plataforma (.has-tooltip + data-tooltip) ─────────────
   Burbuja CSS sobre el elemento (botones, iconos de acción, bulkbar). Antes vivía
   en bulkbar.css, que solo se carga en páginas con DataTables; aquí es global
   (22/08/2026). Dentro de celdas de DataTable usar solo data-tooltip (sin la
   clase): el overflow de la celda recorta la burbuja y datatable-module.js pinta
   el flotante .dt-cell-tooltip. Nunca title= nativo en elementos visibles. */
.has-tooltip {
    position: relative;
}

.has-tooltip::after {
    content: attr(data-tooltip);
    position: absolute;
    bottom: calc(100% + 10px);
    left: 50%;
    transform: translateX(-50%);
    background: var(--mt-gray-900);
    color: #fff;
    padding: 6px 10px;
    font-size: var(--mt-fs-body-sm);
    font-weight: 400;
    line-height: 1.3;
    border-radius: var(--mt-radius);
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--mt-dur-fast) var(--mt-ease);
    z-index: 5;
}

.has-tooltip::before {
    content: "";
    position: absolute;
    bottom: calc(100% - 2px);
    left: 50%;
    transform: translateX(-50%);
    border-width: 6px;
    border-style: solid;
    border-color: var(--mt-gray-900) transparent transparent transparent;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--mt-dur-fast) var(--mt-ease);
    z-index: 5;
}

.has-tooltip:hover::after,
.has-tooltip:hover::before,
.has-tooltip:focus-visible::after,
.has-tooltip:focus-visible::before {
    opacity: 1;
}

/* Columna de selección: el th donde la bulkbar inyecta el checkbox lleva un
   padding legacy distinto (4px) y quedaba desalineado con los de las filas */
table.dataTable thead th:has(> .bulk-select-all) {
    padding-left: 12px;
    padding-right: 12px;
}

/* Listado estrecho (Refactoring UI «You don't have to fill the whole screen»): una
   tabla de 2-3 columnas + acción (controles sin grupo, catálogos simples) estirada
   al ancho del contenedor deja columnas kilométricas y se lee rara. Envolver el
   DataTableComun en este wrapper la deja al ancho que necesita, centrada en la
   página (decisión del usuario 22/08/2026). Ancho de la escala de tamaños (tokens.md §7b). */
.mt-dt-estrecho {
    max-width: 760px;
    margin-left: auto;
    margin-right: auto;
}

/* Los checkboxes de las filas se centran en su celda, alineados con el
   "seleccionar todo" de la cabecera (centrado por su regla gemela en la
   sección de cabeceras de tabla).
   Solo celdas cuyo único contenido es el checkbox (columna de selección). */
table.dataTable tbody td:has(> input[type="checkbox"]:first-child:last-child) {
    text-align: center;
}

/* Cabeceras: aire a la derecha para los iconos de orden — sin él, el texto de
   una columna chocaba con el de la siguiente (ej. IDENTIFICADOR/CONTROL) */
table.dataTable thead th.sorting,
table.dataTable thead th.sorting_asc,
table.dataTable thead th.sorting_desc {
    padding-right: 26px;
}

/* Guarda anti-solape de cabeceras: con table-layout fixed + nowrap, una columna
   más estrecha que su etiqueta pintaba el texto ENCIMA de la cabecera vecina
   (ej. IDENTIFICADOR/CONTROL en Incidencias). Con overflow hidden el exceso se
   recorta con elipsis dentro de su propia celda y el choque es imposible. */
table.dataTable thead th {
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ------------------------------------------------------------------ */
/* Login (guía §10.9): card sobria centrada sobre gray-100, logo       */
/* comedido y botón primario ancho (el flujo de 2 pasos se mantiene    */
/* pero sin indicador visible — decisión 15/07/2026). Scoped a         */
/* BODY.login (controlador Login); el lienzo gray-100 es intencional   */
/* aquí — el login no tiene shell y la card necesita fondo del que     */
/* despegar (excepción a la nota del §2: página blanca).               */
/* ------------------------------------------------------------------ */
BODY.login {
    background-color: var(--mt-gray-100);
}

.mt-login {
    max-width: 440px;
    margin: 0 auto;
}

.mt-login-logo {
    text-align: center;
    margin-bottom: 1.5rem;
}

.mt-login-logo img {
    width: 190px;
    height: auto;
}

.mt-login-card {
    background-color: #fff;
    border: 1px solid var(--mt-gray-200);
    border-radius: var(--mt-radius-lg);
    box-shadow: var(--mt-shadow-sm);
    padding: 2rem;
    text-align: left;
}

@media only screen and (max-width: 575px) {
    .mt-login-card {
        padding: 1.5rem 1.25rem;
    }
}

.mt-login-title {
    font-family: var(--mt-font-display);
    font-size: 24px;
    font-weight: 700;
    line-height: 1.15;
    letter-spacing: var(--mt-tracking-tight);
    color: var(--mt-gray-900);
    margin: 0 0 1.5rem;
}

/* Empresa recordada (paso 2): resumen con enlace «Cambiar» */
.mt-login-empresa {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    background-color: var(--mt-gray-50);
    border: 1px solid var(--mt-gray-200);
    border-radius: var(--mt-radius-sm);
    padding: .625rem .875rem;
    margin-bottom: 1rem;
}

.mt-login-empresa-label {
    display: block;
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: var(--mt-tracking-caps);
    color: var(--mt-gray-600);
}

.mt-login-empresa-nombre {
    font-weight: 600;
    color: var(--mt-gray-800);
}

.mt-login-empresa a {
    font-size: var(--mt-fs-body-sm);
    font-weight: 600;
    white-space: nowrap;
}

/* Ritmo de campos y botón ancho (neutraliza los márgenes legacy de .btn) */
.mt-login .form-group {
    margin-bottom: 1rem;
}

.mt-login .btn {
    margin-right: 0;
    margin-top: .5rem;
}

.mt-login .alert {
    margin-top: 0;
    margin-bottom: 1.25rem;
}

/* styles.css legacy infla los iconos de alert del login a 25px */
.mt-login .alert i {
    font-size: 16px;
}

/* Login admin (/login_admin): misma card que el login normal, con dos
   distintivos sobrios — filete superior verde y chip «Acceso administrador»
   sobre el título. El chip lleva icono propio (escudo), así que va sin el
   punto de estado. */
.mt-login-card-admin {
    border-top: 3px solid var(--mt-green-600);
}

.mt-login-admin-chip {
    margin-bottom: .75rem;
}

.mt-login-admin-chip::before {
    display: none;
}

/* Cambio al login de empresa: botón secundario compacto y centrado bajo la
   card, con fondo blanco para que no se lave sobre el lienzo gray-100 (el
   hover lo rellena igual) y texto algo mayor que el de un botón normal. */
.mt-login-switch {
    margin-top: 1rem;
}

.mt-login-switch .btn {
    background-color: #fff;
    font-size: 15px;
    padding: .45rem 1.25rem;
}

/* Iconos dentro de las celdas (+ duplicar, mover, lápiz, papelera…): van a 19px
   sobre texto de 15px y, apoyados en la línea base (vertical-align:baseline por
   defecto), su glifo queda ~2px por encima del centro del texto y del checkbox
   de la fila. Bajarlos 0.1em (medido en pantalla) deja el glifo a ±0,3px del
   centro de las mayúsculas del texto y del checkbox de selección. */
.dataTable tbody td .fa,
.dataTable tbody td .fa-solid,
.dataTable tbody td .fa-regular {
    vertical-align: -0.1em;
}

/* Los iconos con sintaxis moderna FA7 (fa-solid/fa-regular, sin la clase
   legacy .fa) dentro de un DataTable heredan el mismo tamaño que styles.css
   da a los .fa — sin esto salían más pequeños que el resto de la fila. */
.dataTable .fa-solid,
.dataTable .fa-regular {
    font-size: 15px;
    margin-right: 5px;
}

@media only screen and (min-width: 768px) {
    .dataTable .fa-solid,
    .dataTable .fa-regular {
        font-size: 16px;
    }
}

@media only screen and (min-width: 1068px) {
    .dataTable .fa-solid,
    .dataTable .fa-regular {
        font-size: 19px;
    }
}

/* El icono del estado vacío (.mt-empty-icon, §5) va centrado por flex dentro de
   su círculo y con el tamaño del propio círculo: cuando el vacío se pinta en la
   celda de un DataTable, anular el tamaño/margen de celda que le daría la regla
   anterior (el margin-right de 5px descentraba el glifo dentro del círculo). */
.dataTable .mt-empty-icon .fa,
.dataTable .mt-empty-icon .fa-solid,
.dataTable .mt-empty-icon .fa-regular {
    font-size: inherit;
    margin-right: 0;
}

/* ------------------------------------------------------------------ */
/* Modo soporte (/support) — listado de una sola pantalla (07/2026):  */
/* filas de empresa con contexto, «Entrar» directo como MT_SOPORTE y  */
/* usuarios desplegables inline (fragmento AJAX). El buscador tiene   */
/* foco automático y ⏎ entra en la primera coincidencia.              */
/* ------------------------------------------------------------------ */
.mt-sup-search .mt-sup-search-hint {
    font-size: 13.5px;
    color: var(--mt-gray-600);
}

.mt-sup-search kbd {
    font-family: inherit;
    font-size: 11px;
    font-weight: 600;
    color: var(--mt-gray-700);
    background-color: #fff;
    border: 1px solid var(--mt-gray-300);
    border-bottom-width: 2px;
    border-radius: 5px;
    padding: 0 5px;
}

/* Lista compacta (sept 2026): una sola columna de filas finas en orden
   alfabético de arriba abajo — el ojo baja por la columna como en una tabla.
   (La rejilla anterior de 3-4 columnas rompía el orden alfabético en zigzag
   y hacía difícil localizar una empresa.) Ancho capado: con solo nombre +
   acciones no tiene sentido ocupar toda la pantalla. */
.mt-sup-search,
.mt-sup-list {
    max-width: 900px;
}

.mt-sup-list {
    display: grid;
    grid-template-columns: 1fr;
    gap: 8px;                          /* paso 3: filas compactas, poco aire */
    align-items: start;
}

#support_no_results {
    grid-column: 1 / -1;
}

.mt-sup-emp {
    background-color: #fff;
    border: 1px solid var(--mt-gray-200);
    border-radius: var(--mt-radius);
    box-shadow: var(--mt-shadow-sm);
}

/* Primera coincidencia del buscador: es donde entra ⏎ */
.mt-sup-emp.mt-sup-first {
    border-color: var(--mt-green-500);
    box-shadow: var(--mt-focus-ring);
}

/* Toda la fila es clicable (equivale a «Entrar» directo) */
.mt-sup-emp-row {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 8px 16px;                 /* fila fina ~48px: caben 15-18 por pantalla */
    cursor: pointer;
    border-radius: var(--mt-radius);
}

.mt-sup-emp-row:hover {
    background-color: var(--mt-green-50);
}

.mt-sup-emp-id {
    flex: 1;
    min-width: 0;
}

.mt-sup-emp-nom {
    font-weight: 600;
    font-size: var(--mt-fs-body);
    color: var(--mt-gray-900);
}

.mt-sup-emp-acts {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: none;
}

/* Neutraliza los márgenes legacy de .btn dentro del listado */
.mt-sup-emp-acts .btn,
.mt-sup-user-acts .btn {
    margin: 0;
}

/* Jerarquía: «Entrar» es secundaria de marca (outline-primary) en todas las
   filas y solo pasa a primaria en la fila que recibe ⏎ (.mt-sup-first, lo
   conmuta markFirst en gestion.php): una sola primaria por vista, no N
   «Entrar» sólidos. Tamaño btn-sm normal, a juego con la fila compacta. */

/* «Usuarios ▾» terciaria: enlace gris sin borde; verde al pasar, como el resto
   de btn-link del tema. El chevron acompaña al texto. */
.mt-sup-emp-acts .btn-link {
    color: var(--mt-gray-700);
    text-decoration: none;
    padding-left: .5rem;
    padding-right: .5rem;
}

.mt-sup-emp-acts .btn-link:hover,
.mt-sup-emp-acts .btn-link:focus-visible {
    color: var(--mt-green-700);
    text-decoration: underline;
}

.mt-sup-chev {
    font-size: 10px;
    margin-left: 2px;
    transition: transform .15s ease;
}

.mt-sup-emp.open .mt-sup-chev {
    transform: rotate(180deg);
}

/* Zona desplegable de usuarios (fragmento AJAX) */
.mt-sup-users {
    border-top: 1px solid var(--mt-gray-200);
    background-color: var(--mt-gray-50);
    border-radius: 0 0 var(--mt-radius) var(--mt-radius);
    /* Sin padding vertical: las filas (clicables de borde a borde) cubren
       también el primer y último tramo del desplegable */
    padding: 0 16px;
    /* Recorta el hover de las filas en las esquinas redondeadas de abajo */
    overflow: hidden;
}

/* Fila de usuario: bloque de identidad a la izquierda (nombre y, debajo, el
   chip de rol/estado cuando lo hay) y acciones ancladas a la derecha. Sin
   wrap: el layout no baila aunque la card sea estrecha. Toda la fila es
   clicable y equivale a «Entrar como» ese usuario. */
.mt-sup-user {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    /* La fila llega de borde a borde de la card (compensa el padding lateral
       de .mt-sup-users): no queda ningún margen muerto sin click. */
    padding: 12px 16px;
    margin: 0 -16px;
    font-size: var(--mt-fs-body);
    border-bottom: 1px dashed var(--mt-gray-200);
    cursor: pointer;
}

.mt-sup-user:hover {
    background-color: var(--mt-green-50);
}

.mt-sup-user:last-of-type {
    border-bottom: none;
}

.mt-sup-user-info {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}

.mt-sup-user-nom {
    display: flex;
    align-items: center;
    gap: 8px;
}

.mt-sup-user-rol {
    font-size: 13px;
}

.mt-sup-user-acts {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: none;
}

/* Chip «frecuente» junto al nombre: lleva icono propio (rayo), así que va sin
   el punto de estado; algo más pequeño que el cuerpo del nombre. */
.mt-sup-emp-nom .mt-chip {
    font-size: var(--mt-fs-body-sm);
    vertical-align: 1px;
}

.mt-sup-emp-nom .mt-chip::before {
    display: none;
}

@media only screen and (max-width: 767px) {
    .mt-sup-emp-row {
        flex-wrap: wrap;
        gap: 8px;
    }
}

/* ------------------------------------------------------------------ */
/* Incidencias — ficha por secciones                                   */
/* ------------------------------------------------------------------ */
/* El formulario de incidencia es largo (de 6 a 11 bloques según el tipo
   de control) y crece al vuelo: contestas "Sí" a una acción correctora y
   aparecen campos por debajo del fold. Estas clases le dan estructura sin
   partirlo en pestañas —se rellena de una sentada—: cada bloque es una
   card con su estado, y un rail sticky a la izquierda hace de índice.
   El comportamiento (estado, contador, scroll-spy) lo calcula el partial
   pages/incidencias/partials/secciones_incidencia.php a partir del DOM. */

.mt-inc-layout {
    display: grid;
    grid-template-columns: 180px minmax(0, 1fr);
    gap: 24px;
    align-items: start;
}

/* El rail se pega arriba del .modal-body, que es el contenedor con scroll
   (la vista añade .modal-dialog-scrollable al abrirse).
   Es un índice, no contenido: va en texto secundario (gray-500), con puntos
   de estado pequeños en los tonos apagados (-mid) y sin rellenos de color,
   para que no compita con las cards del formulario. El ítem activo se marca
   solo con el color de texto y el peso. */
.mt-inc-rail {
    position: sticky;
    top: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 4px 0;
}

.mt-inc-rail-item {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    width: 100%;
    padding: 4px 8px;
    border: 0;
    border-radius: var(--mt-radius);
    background: transparent;
    color: var(--mt-gray-500);
    font-size: var(--mt-fs-body-sm);
    line-height: 1.35;
    text-align: left;
    transition: background-color var(--mt-dur-fast) ease, color var(--mt-dur-fast) ease;
}

.mt-inc-rail-item:hover {
    background-color: var(--mt-gray-100);
    color: var(--mt-gray-900);
}

.mt-inc-rail-item.is-active {
    color: var(--mt-gray-900);
    font-weight: 600;
}

/* Texto del item. */
.mt-inc-rail-cuerpo {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

/* Punto de estado del rail: mismo lenguaje que el dot de .mt-chip, pero más
   pequeño y en los tonos -mid; el estado real ya lo dice el chip de cada
   sección. Centrado en la primera línea de texto (13px × 1.35 ≈ 18px). */
.mt-inc-rail-punto {
    flex: none;
    width: 6px;
    height: 6px;
    margin-top: 6px;
    border-radius: 50%;
    background-color: var(--mt-gray-300);
}

.mt-inc-rail-item[data-estado="completa"] .mt-inc-rail-punto { background-color: var(--mt-success-mid); }
.mt-inc-rail-item[data-estado="pendiente"] .mt-inc-rail-punto { background-color: var(--mt-warning-mid); }
.mt-inc-rail-item[data-estado="no-aplica"] .mt-inc-rail-punto { background-color: var(--mt-gray-300); }

.mt-inc-rail-item[data-estado="no-aplica"] .mt-inc-rail-texto { color: var(--mt-gray-400); }

.mt-inc-seccion {
    padding: 16px 18px;
    margin-bottom: 16px;
    border: 1px solid var(--mt-gray-200);
    border-radius: var(--mt-radius);
    background-color: #fff;
    scroll-margin-top: 8px;
}

.mt-inc-seccion-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 14px;
}

.mt-inc-seccion-titulo {
    display: flex;
    align-items: center;
    gap: 9px;
    margin: 0;
    font-size: var(--mt-fs-h4);
    font-weight: 600;
    color: var(--mt-gray-900);
}

.mt-inc-seccion-titulo i {
    color: var(--mt-green-500);
}

/* Un bloque que este tipo de incidencia no tiene (el PHP no ha pintado ni un
   campo, así que no hay desplegable que pueda sacarlo) desaparece del todo. */
.mt-inc-seccion[data-estado="nunca"] { display: none; }

/* Una sección sin ningún campo visible (su "¿aplica?" está en No, o depende
   de otra que no aplica) se queda en una línea en vez de dejar el hueco. */
.mt-inc-seccion[data-estado="no-aplica"] .mt-inc-seccion-body { display: none; }
.mt-inc-seccion[data-estado="no-aplica"] .mt-inc-seccion-head { margin-bottom: 0; }
.mt-inc-seccion[data-estado="no-aplica"] .mt-inc-seccion-titulo { color: var(--mt-gray-500); }
.mt-inc-seccion[data-estado="no-aplica"] .mt-inc-seccion-titulo i { color: var(--mt-gray-400); }

/* Destello al llegar desde el rail o desde el salto de validación. */
.mt-inc-seccion.is-destacada {
    box-shadow: var(--mt-focus-ring);
    border-color: var(--mt-green-300);
}

/* Los campos que aparecen al contestar "Sí" entran desde arriba, para que se
   vea que el bloque ha crecido y no parezca que el modal ha dado un salto. */
.mt-inc-seccion-body .mt-inc-revelado {
    animation: mt-inc-revelar var(--mt-dur) ease;
}

@keyframes mt-inc-revelar {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: none; }
}

/* En la incidencia el <form> envuelve cabecera, cuerpo y pie, o sea que se
   cuela entre el .modal-content y el .modal-body y rompe la cadena flex con
   la que Bootstrap deja el cuerpo con scroll propio y el pie fijo. El
   formulario asume ese papel. */
.modal-dialog-scrollable .modal-content > .mt-inc-form {
    display: flex;
    flex-direction: column;
    max-height: 100%;
    overflow: hidden;
}

.modal-dialog-scrollable .modal-content > .mt-inc-form > .modal-body {
    min-height: 0;
}

/* Contador de campos pendientes: comparte fila con el selector de cierre y los
   botones del pie. */
.mt-inc-contador {
    display: flex;
    align-items: center;
}

/* Cuerpo del formulario a escala: los .form-control/.form-select heredaban el
   1rem de Bootstrap y salían más grandes que todo lo que tienen alrededor (el
   pie ya lo corregía para su select, más abajo). La caja se queda en los 40px
   de §7b; solo baja el texto al cuerpo de la app. */
.mt-inc-form .modal-body .form-control,
.mt-inc-form .modal-body .form-select,
/* …y lo mismo para los select2: su caja no es un .form-select, así que sin
   estos selectores se quedaban en el 1rem del tema y el placeholder se veía
   más grande que el de los selects nativos de al lado. */
.mt-inc-form .modal-body .select2-selection__rendered,
.mt-inc-form .modal-body .select2-selection__placeholder,
.mt-inc-form .modal-body .select2-search__field {
    font-size: var(--mt-fs-body);
}

/* Etiquetas y opciones sin el peso 300 del `form label` legacy (styles.css
   §formularios): la guía trabaja con dos pesos, 400/600 (tokens.md §18.2).
   Etiquetas al rol de texto secundario… */
.mt-inc-form .modal-body label {
    font-weight: 400;
    color: var(--mt-gray-600);
}

/* …y las opciones de checkbox/radio como contenido normal, no como etiqueta:
   con el 300 + azul legacy se leían como deshabilitadas. */
.mt-inc-form .modal-body .form-check-label {
    color: var(--mt-gray-800);
}

/* El pie va fijo, así que cada píxel que ocupa se lo quita al formulario. Se
   compacta a una sola línea: el "Cierre" pasa de label apilado sobre el select
   a label al lado, y se neutralizan los márgenes verticales del .btn legacy
   (styles.css §10, margin-top:15px), que por sí solos añadían 30px. */
.mt-inc-form .modal-footer {
    padding-top: 10px;
    padding-bottom: 10px;
    /* El fondo sigue siendo el que cada tipo pinta en línea con el color que la
       empresa configura por tipo de control (TCBgColorIncidencia*): aquí solo se
       compacta el pie a una fila, porque va fijo y cada píxel que ocupa se lo
       quita al formulario. */
}

/* Bootstrap le da .25rem de margen a cada hijo del pie para separar botones
   sueltos; aquí dentro solo hay una fila, así que sobra. */
.mt-inc-form .modal-footer > * {
    margin: 0;
}

/* El bloque de acciones del pie (contador + cierre + botones) es un div suelto:
   sin flex, el hueco de la línea de texto le añadía 7px por debajo. */
.mt-inc-form .modal-footer .w-100 > div {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 0;
    /* El .form-group legacy trae 7px de padding inferior pensados para el hueco
       del mensaje de validación, que en el pie no existe. */
    padding-bottom: 0;
}

/* La etiqueta del cierre solo existe hasta que secciones_incidencia.php la
   quita (los segmentos Abierta/Cerrada se explican solos): esta regla cubre el
   instante de render previo, para que no parpadee en gris sobre el color. */
.mt-inc-form .modal-footer .form-group label {
    margin-bottom: 0;
    white-space: nowrap;
    /* El pie lleva el color de empresa por tipo de control (TCBgColorIncidencia*:
       rojo abierta / verde cerrada, ambos oscuros): el gris de texto por defecto
       se pierde encima. */
    color: #fff;
    font-weight: 600;
}

/* El grupo del cierre ancla el lado izquierdo del pie (contador + segmentado
   Abierta/Cerrada, los monta secciones_incidencia.php): se neutraliza el hueco
   de validación del .form-group legacy para que no descentre la fila. */
.mt-inc-form .modal-footer .form-group {
    display: flex;
    align-items: center;
    margin: 0;
    padding-bottom: 0;
}

.mt-inc-form .modal-footer .form-select {
    width: auto;
    /* A cuerpo de texto del tema y a la altura de los botones del pie: con el
       1rem de Bootstrap el select salía notablemente más grande que todo lo
       que tiene al lado. */
    font-size: var(--mt-fs-body);
    height: 40px;
    /* Con base-select la caja del valor no se auto-ajusta al contenido como un
       select nativo: se queda en el min-width y elipsiza. A 14px el placeholder
       «Selecciona...» cabe entero con la flecha en 170px. */
    min-width: 170px;
}

.mt-inc-form .modal-footer .btn {
    margin-top: 0;
    margin-bottom: 0;
    /* El espacio entre botones lo pone el gap del contenedor. */
    margin-right: 0;
    /* El padding 15px del .btn legacy los deja en 50px y estiraba la fila; se
       igualan a los 40px del selector de cierre, como ya se hace en la barra de
       acciones de los buscadores. */
    height: 40px;
    display: inline-flex;
    align-items: center;
}

/* Estado de cierre como control segmentado (lo monta secciones_incidencia.php
   sobre el select oculto): banda translúcida sobre el color del pie con el
   segmento activo en blanco. */
.mt-inc-estado-seg {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    height: 40px;
    padding: 4px;
    border-radius: var(--mt-radius);
    background-color: rgba(255, 255, 255, .22);
}

.mt-inc-estado-btn {
    display: inline-flex;
    align-items: center;
    height: 100%;
    padding: 0 16px;
    margin: 0;
    border: 0;
    border-radius: calc(var(--mt-radius) - 2px);
    background: transparent;
    color: #fff;
    font-size: var(--mt-fs-body);
    font-weight: 600;
    transition: background-color var(--mt-dur-fast) ease, color var(--mt-dur-fast) ease;
}

.mt-inc-estado-btn:hover {
    background-color: rgba(255, 255, 255, .18);
}

.mt-inc-estado-btn.is-active {
    background-color: #fff;
    color: var(--mt-gray-900);
    box-shadow: var(--mt-shadow-sm);
}

.mt-inc-estado-seg.is-disabled {
    opacity: .75;
}

.mt-inc-estado-seg.is-disabled .mt-inc-estado-btn {
    cursor: default;
}

/* Cabecera de contexto plegable (id, hora, registro, sala, zona). */
.mt-inc-contexto {
    margin-bottom: 16px;
    padding: 12px 16px;
    border: 1px solid var(--mt-gray-200);
    border-radius: var(--mt-radius);
    background-color: var(--mt-gray-50);
}

.mt-inc-contexto-resumen {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
}

.mt-inc-contexto-titulo {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    min-width: 0;
    font-size: var(--mt-fs-body);
    color: var(--mt-gray-700);
}

.mt-inc-contexto-titulo strong {
    color: var(--mt-gray-900);
}

.mt-inc-contexto-detalle {
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid var(--mt-gray-200);
}

.mt-inc-contexto .toggle-contexto[aria-expanded="true"] .fa-chevron-down {
    transform: rotate(180deg);
}

.mt-inc-contexto .toggle-contexto .fa-chevron-down {
    transition: transform var(--mt-dur-fast) ease;
}

@media only screen and (max-width: 991.98px) {
    .mt-inc-layout {
        grid-template-columns: minmax(0, 1fr);
    }

    .mt-inc-rail {
        display: none;
    }
}

/* ============================================================
   Visor de fotos de incidencia (partials/visor_fotos_incidencia.php)
   Flechas del paginador con el mismo lenguaje que las flechas de la
   barra de día del calendario (.mt-vd-daybar-arrow en vista_diaria):
   caja 38px, borde green-200, chevron green-700, hover green-100.
   ============================================================ */

.mt-visor-fotos-nav-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 38px;
    min-width: 38px;
    padding: 0 12px;
    border: 1px solid var(--mt-green-200);
    background: #fff;
    color: var(--mt-green-700);
    border-radius: var(--mt-radius);
    cursor: pointer;
    transition: background-color var(--mt-dur-fast) ease;
}

.mt-visor-fotos-nav-btn:hover {
    background: var(--mt-green-100);
    color: var(--mt-green-800);
}

/* Contador «1 / 3»: cifras tabulares para que no baile al pasar de foto */
.mt-visor-fotos-contador {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    color: var(--mt-gray-700);
}

/* ============================================================
   Ficha de control: botonera del pie («Volver a inicio» /
   «Siguiente sala» / «Cerrar control»).
   Antes era un text-center con inline-blocks: el .btn legacy
   (styles.css §10) trae margin-right:10px sin margin-left, así que
   cada botón quedaba 5px a la izquierda del centro de la card.
   Flex centrado con gap de la escala y margen legacy a 0.
   ============================================================ */
.mt-ficha-footer-actions {
    display: flex;
    justify-content: center;
    align-items: center;
    flex-wrap: wrap;
    gap: 16px;
}

.mt-ficha-footer-actions .btn {
    margin: 0;
}

/* ── Prevalidación para verificadores (SOLO MODO SOPORTE, piloto) ─────────────
   Semáforo «antes de firmar» (App\Libraries\PrevalidacionVerificacion): un punto
   de 8px con el color del peor aviso junto al botón de verificar del historial,
   y el bloque «Antes de firmar» de los modales de verificar (dentro de un
   .mt-well). Discreto a propósito: avisa, no bloquea. */
/* Icono de gravedad de cada aviso (sustituye a los puntos de color): la forma
   dice el nivel, el color lo refuerza. Ancho fijo para que los textos alineen. */
.mt-preval-ico {
    flex: none;
    width: 20px;
    text-align: center;
    font-size: 16px;
    color: var(--mt-gray-400);
}
.mt-preval-ico-rojo  { color: var(--mt-danger); }
/* El ámbar es un SVG propio (triángulo con «!» grueso), algo mayor que los
   círculos para que pesen igual a la vista. */
.mt-preval-ico-ambar { color: var(--mt-warning); }
svg.mt-preval-ico {
    width: 20px;
    height: 20px;
    /* Con la primera línea del texto, no centrado en avisos de varias líneas. */
    align-self: flex-start;
    margin-top: 2px;
}
.mt-preval-ico-info  { color: var(--mt-info); }
.mt-preval-ico-verde { color: var(--mt-success); }

/* En la celda de verificar: el punto delante del tick, sin mover el tick. */
/* Celda del tick de verificar: anfitrión del «!» de la prevalidación. */
.mt-preval-cell {
    position: relative;
    display: inline-block;
}
/* El «!» va como el contador de la campana de la cabecera: montado 6px sobre la
   esquina superior derecha del tick (más tapaba el tick, menos quedaba separado; el
   borde blanco los separa) y a 3px de la fila de encima. Cabe dentro del td con su relleno normal
   (el td corta lo que sobresale). Absolute: no mueve el tick ni la columna. */
.mt-preval-cell .mt-preval-badge {
    box-sizing: border-box;
    top: 0;
    right: auto;
    left: 100%;
    transform: translate(-6px, -4px);
    width: 14px;
    min-width: 14px;
    height: 14px;
    padding: 0;
    border: 2px solid #fff;
    font-size: 8px;
    line-height: 1;
    cursor: default;
}
.mt-preval-cell .mt-preval-badge i {
    display: block;
    width: auto;
    margin: 0;
    font-size: 8px;
    line-height: 1;
}

/* Modal de prevalidación de un control (Refactoring UI, 02/10/2026). Se lee de arriba
   abajo en tres golpes: cabecera = qué control es (nombre y, debajo, la fecha
   en pequeño); cuerpo = los avisos, lo principal (mensaje fuerte, qué hacer debajo y
   más suave, una línea fina entre avisos); y Ektor aparte, en una superficie gris
   (.mt-well): un extra, no un paso.
   Todo con los valores de la guía (docs/ui/tokens.md): tamaños de la escala de roles
   (§5: h4 16 / body 14 / caption 12), dos pesos (400 y 600), tres grises de texto
   (900-800 / 600 / 500) y espaciado de la escala (§7: 4, 8, 12, 16, 24). */
.mt-preval {
    padding: 4px 0 8px;
    font-size: var(--mt-fs-body);
    line-height: 1.55;
    color: var(--mt-gray-800);
}
.mt-preval-control-id {
    min-width: 0;
}
/* Veredicto y fecha, juntos bajo el nombre: son los datos del control. */
.mt-preval-control-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 16px;
    margin-top: 4px;
    font-size: var(--mt-fs-body);
    line-height: 1.55;
}
.mt-preval-control-fecha {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    color: var(--mt-gray-600);
}
/* Icono junto a texto: un tono por debajo (tokens.md §10). */
.mt-preval-control-fecha i {
    color: var(--mt-gray-500);
}
.mt-preval-avisos {
    list-style: none;
    margin: 0;
    padding: 0;
}
.mt-preval-avisos li {
    display: flex;
    align-items: baseline;
    gap: 12px;
    padding: 12px 0;
}
.mt-preval-avisos li + li {
    border-top: 1px solid var(--mt-gray-200);
}
.mt-preval-avisos li > span {
    min-width: 0;
}
/* Avisos del sistema: un card por aviso, a todo el ancho, sin borde y con la sombra
   de los cards de la plataforma (elegido por el usuario entre maquetas, 02/10/2026).
   Las observaciones de Ektor (dentro de su .mt-well) siguen como lista con línea. */
.mt-preval > .mt-preval-seccion {
    margin-bottom: 12px;
}
.mt-preval > .mt-preval-avisos {
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.mt-preval > .mt-preval-avisos li {
    padding: 16px;
    border: 0;
    border-radius: var(--mt-radius);
    background-color: #fff;
    box-shadow: var(--mt-shadow-sm);
}
/* Mensaje del aviso: lo que hay que leer (rol h4 de la escala). */
.mt-preval-texto {
    display: block;
    font-size: var(--mt-fs-h4);
    font-weight: 600;
    line-height: 1.3;
    color: var(--mt-gray-900);
}
/* Aviso personal de quien firma (modales de verificar). */
.mt-preval-personal {
    display: flex;
    align-items: baseline;
    gap: 12px;
    margin-bottom: 16px;
}
/* Qué se puede hacer con el hallazgo: debajo de su mensaje, subordinado (cuerpo,
   sin negrita y en gris secundario), pero legible. */
.mt-preval-accion {
    display: block;
    margin-top: 4px;
    font-size: var(--mt-fs-body);
    font-weight: 400;
    line-height: 1.55;
    color: var(--mt-gray-600);
}
/* Ektor, aparte de los avisos: es un .mt-well (la superficie la pone esa clase); aquí
   solo el aire que lo separa de los avisos. Son dos apartados distintos: mucho más
   espacio entre ellos (paso 7, «entre secciones») que dentro de cada uno
   (Refactoring UI, «espacio no ambiguo», tokens.md §18.3). */
.mt-preval-ektor {
    margin-top: 3rem;                  /* paso 7 */
}
/* Modal apilado que oculta al de debajo mientras está abierto (enlace .open_modal_2
   con data-ocultar_debajo="1", script.js): el de debajo sigue abierto y con su
   contenido, solo deja de verse; el velo del apilado va transparente para no sumar
   oscuridad al del primero. */
.modal.mt-modal-tapado {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    /* Se funde al ocultarse (la visibilidad cambia al acabar el fundido); al volver,
       reaparece con el fundido propio de .modal.fade de Bootstrap. */
    transition: opacity var(--mt-dur) var(--mt-ease), visibility 0s linear var(--mt-dur);
}
@media (prefers-reduced-motion: reduce) {
    .modal.mt-modal-tapado {
        transition: none;
    }
}
.modal-backdrop.mt-backdrop-sin-velo.show {
    opacity: 0;
}
/* Pie: «Cerrar» y «Ver control», juntos a la derecha. */
.mt-preval-pie {
    gap: 8px;
}
/* Icono del veredicto de cada control en la tabla de los modales de verificar (junto a
   «Resumen» y «Ver»): varita (la de Ektor), del mismo color que sus vecinos; la gravedad
   la dice un punto pequeño en su esquina (rojo = Mal, ámbar = Regular), con un aro
   blanco para que se despegue del icono. Bien = sin punto y apagada. */
.mt-preval-fila {
    position: relative;
    display: inline-block;
}
.mt-preval-fila-rojo::after,
.mt-preval-fila-ambar::after {
    content: "";
    position: absolute;
    top: -4px;
    right: -5px;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    box-shadow: 0 0 0 2px #fff;
    background: var(--mt-danger);
}
.mt-preval-fila-ambar::after { background: var(--mt-warning); }
/* Modal de avisos (apilado sobre el de verificar, y más estrecho que él): con muchos
   avisos se desplaza su cuerpo, el modal no crece ni se sale de la pantalla. */
.mt-preval-modal-cuerpo {
    max-height: calc(100vh - 260px);
    overflow-y: auto;
}
/* Bien: la varita se apaga (lo normal no pide atención); en hover vuelve a su color. */
.mt-preval-fila-verde:not(:hover) { color: var(--mt-gray-400); }
.mt-preval-ektor .fa-wand-magic-sparkles {
    color: var(--mt-green-700);
}
.mt-preval-ektor-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 16px;
    background-color: #fff;
}
.mt-preval-ektor-cab {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px 12px;
}
/* Con análisis debajo (aviso de cambio, resumen u observaciones), aire tras la cabecera. */
.mt-preval-ektor-cab:not(:last-child) {
    margin-bottom: 8px;
}
/* Títulos de sección («Avisos detectados», «Revisión de Ektor»): mayores que el texto
   de los avisos (pedido por el usuario, 02/10/2026), para que los dos apartados se
   lean como tales. Escalera del modal, toda de la escala de roles: título del modal
   h2 (20) > título de sección h3 (18) > mensaje del aviso h4 (16) > detalle body (14). */
.mt-preval-seccion {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin-bottom: 8px;
    font-size: var(--mt-fs-h3);
    font-weight: 600;
    line-height: 1.25;
    color: var(--mt-gray-900);
}
.mt-preval-seccion i {
    font-size: 16px;
}
/* El título del modal, un paso por encima de los de sección. */
.mt-preval-control-id .modal-title {
    font-size: var(--mt-fs-h2);
    line-height: 1.2;
}
/* Recuento de avisos junto al título: dato de apoyo, más suave que la etiqueta. */
.mt-preval-seccion-num {
    font-size: var(--mt-fs-body);
    font-weight: 400;
    color: var(--mt-gray-500);
}
.mt-preval-ektor-cab .mt-preval-seccion {
    margin-bottom: 0;
}
.mt-preval-ektor-fecha {
    font-size: var(--mt-fs-caption);
    color: var(--mt-gray-500);
    white-space: nowrap;
}
.mt-preval-ektor-resumen {
    max-width: 65ch;
    color: var(--mt-gray-800);
    margin: 0;
}
/* El elemento, en su propia línea: primero de qué se habla, luego qué pasa. */
.mt-preval-ektor-elemento {
    display: block;
    margin-bottom: 4px;
    font-weight: 600;
    color: var(--mt-gray-900);
}
.mt-preval-ektor .mt-preval-avisos li {
    color: var(--mt-gray-800);
}
/* El relleno de la superficie ya cierra el bloque por abajo. */
.mt-preval-ektor .mt-preval-avisos li:last-child {
    padding-bottom: 0;
}
.mt-preval-ektor-cambiado {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 4px 8px;
    color: var(--mt-warning-emphasis);
    margin-bottom: 8px;
}
.mt-preval-ektor-cambiado .btn-link {
    font-size: inherit;
    font-weight: 600;
    vertical-align: baseline;
}
.mt-preval-ektor-error {
    display: flex;
    align-items: baseline;
    gap: 8px;
    color: var(--mt-danger-emphasis);
    margin-top: 8px;
}

/* ============================================================
   Widget «Novedades» (tokens.md §12): caja flotante abajo a la
   derecha con el resumen de la última versión, slide a slide
   (template/novedades_widget.php + pages/js/novedades.php).
   Va en --mt-z-fixed a propósito: modales, Swal y tooltips
   quedan por encima (salvo el modal que abre el propio tutorial).
   ============================================================ */
.mt-novedades {
    position: fixed;
    right: 24px;                       /* paso 5 */
    bottom: 24px;
    width: 360px;
    max-width: calc(100vw - 24px);
    display: flex;
    flex-direction: column;
    background-color: var(--bs-white);
    border: 1px solid var(--mt-gray-200);
    border-radius: var(--mt-radius);
    box-shadow: var(--mt-shadow-lg);
    overflow: hidden;
    z-index: var(--mt-z-fixed);
    animation: mt-novedades-in var(--mt-dur-slow) var(--mt-ease);
}

/* Entrada ease-out desde abajo (guía §9); salida simétrica al cerrar */
@keyframes mt-novedades-in {
    from { opacity: 0; translate: 0 16px; }
    to   { opacity: 1; translate: 0 0; }
}

/* Excepción: el modal que abre el propio tutorial («Ver cómo funciona» con 'modal').
   Ahí el widget sube justo por encima del modal para poder seguir con «Siguiente»;
   Swal y tooltips siguen por encima. Lo pone y lo quita pages/js/novedades.php. */
.mt-novedades.mt-novedades-sobre-modal {
    z-index: calc(var(--mt-z-modal) + 1);
}

.mt-novedades.is-saliendo {
    opacity: 0;
    translate: 0 16px;
    transition: opacity var(--mt-dur) var(--mt-ease), translate var(--mt-dur) var(--mt-ease);
}

.mt-novedades-cabecera {
    display: flex;
    align-items: center;
    gap: 8px;                          /* paso 2 */
    padding: 12px 16px;                /* pasos 3 / 4 */
    border-bottom: 1px solid var(--mt-gray-200);
}

.mt-novedades-titulo {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: var(--mt-fs-body);
    font-weight: 600;
    color: var(--mt-gray-900);
}

/* El icono es la señal de la caja, no un adorno junto al texto: va en marca */
.mt-novedades-titulo .fa-solid {
    color: var(--mt-green-500);
}

.mt-novedades-paso {
    margin-left: auto;
    font-size: var(--mt-fs-caption);
    color: var(--mt-gray-500);
}

.mt-novedades-cabecera .btn-close {
    font-size: 12px;
    margin: 0;
}

.mt-novedades-cuerpo {
    transition: opacity var(--mt-dur-fast) var(--mt-ease);
}

.mt-novedades-cuerpo.is-cambiando {
    opacity: 0;
}

/* Media en contenedor fijo 16:9 (tokens.md §18.7), nunca al ratio de la captura */
.mt-novedades-media {
    aspect-ratio: 16 / 9;
    background-color: var(--mt-gray-100);
}

.mt-novedades-media img,
.mt-novedades-media video {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.mt-novedades-texto {
    display: flex;
    flex-direction: column;
    gap: 4px;                          /* paso 1 */
    padding: 16px;                     /* paso 4 */
}

.mt-novedades-slide-titulo {
    font-size: var(--mt-fs-h4);
    font-weight: 600;
    color: var(--mt-gray-900);
}

.mt-novedades-slide-texto {
    margin: 0;
    font-size: var(--mt-fs-body);
    color: var(--mt-gray-600);
}

/* Acción terciaria: enlace, no botón (tokens.md §18.2) */
.mt-novedades-enlace {
    margin-top: 4px;
    font-size: var(--mt-fs-body-sm);
    font-weight: 600;
    color: var(--mt-green-600);
    text-decoration: none;
}

.mt-novedades-enlace:hover,
.mt-novedades-enlace:focus {
    color: var(--mt-green-700);
    text-decoration: underline;
}

.mt-novedades-pie {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 8px;
    padding: 12px 16px;
    border-top: 1px solid var(--mt-gray-200);
}

/* El .btn legacy (styles.css §10) trae margin-top:15px y margin-right:10px */
.mt-novedades-pie .btn {
    margin: 0;
}

/* Con una sola slide «Anterior» va oculto y la primaria se queda a la derecha */
.mt-novedades-pie .btn-primary {
    margin-left: auto;
}

/* Variante a la izquierda: cuando el elemento resaltado de la novedad quedaría
   tapado por el widget (lo decide pages/js/novedades.php al mostrarlo). */
.mt-novedades-izquierda {
    right: auto;
    left: 24px;
}

@media (max-width: 767.98px) {
    .mt-novedades {
        right: 12px;
        bottom: 12px;
        left: 12px;
        width: auto;
        max-width: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    .mt-novedades { animation: none; }
    .mt-novedades.is-saliendo,
    .mt-novedades-cuerpo { transition: none; }
}

/* Pista al llegar a la página de la novedad (sustituye a «Ver cómo funciona») */
.mt-novedades-pista {
    display: flex;
    align-items: flex-start;
    gap: 8px;                          /* paso 2 */
    margin-top: 4px;
    padding: 8px 12px;                 /* pasos 2 / 3 */
    border-radius: var(--mt-radius);
    background-color: var(--mt-green-50);
    color: var(--mt-green-800);
    font-size: var(--mt-fs-body-sm);
}

.mt-novedades-pista .fa-solid {
    margin-top: 2px;
    color: var(--mt-green-500);
}

/* Elemento de la novedad resaltado en su página: anillo de marca que pulsa tres
   veces y se queda mientras el slide siga abierto. Va con outline (no con
   box-shadow) porque los inputs/selects del tema anulan la sombra con más
   especificidad. */
.mt-novedades-destacado {
    border-radius: var(--mt-radius);
    outline: 3px solid rgba(var(--mt-green-700-rgb), .45);
    outline-offset: 3px;
    animation: mt-novedades-pulso 1.2s var(--mt-ease) 3;
}

@keyframes mt-novedades-pulso {
    0%, 100% { outline-offset: 3px; outline-color: rgba(var(--mt-green-700-rgb), .45); }
    50%      { outline-offset: 8px; outline-color: rgba(var(--mt-green-700-rgb), .15); }
}

@media (prefers-reduced-motion: reduce) {
    .mt-novedades-destacado { animation: none; }
}