/* =====================================================================
   VITROLAB - theme.css  (VTL011 - "Laboratorio sobrio")
   ---------------------------------------------------------------------
   Capa de rediseño visual y de densidad. Se carga SIEMPRE DESPUÉS de
   app.css / auth.css, de modo que:
     - no se ha borrado ni una sola regla del CSS anterior;
     - revertir el rediseño completo = quitar el <link> de este archivo
       en views/app.php y views/login.php (y de sw.js).
   Todas las reglas van agrupadas por componente y comentadas con el
   problema concreto que corrigen.

   Criterios del tema:
     - El azul deja de ser fondo y pasa a ser SOLO acento de acción.
       La cabecera es pizarra oscura, el lienzo gris muy claro y las
       superficies blancas: menos saturación, más legible en jornadas
       largas delante de tablas.
     - Más densidad: se ven ~2 veces más filas por pantalla.
     - Un único sistema de botones y de badges.
     - En móvil las tablas dejan de desbordarse y se leen como fichas.
   ===================================================================== */

/* =====================================================================
   1. TOKENS
   ===================================================================== */
:root {
    /* Superficies y texto */
    --vtl-canvas: #f1f4f8;
    --vtl-surface: #ffffff;
    --vtl-surface-2: #f7f9fb;
    --vtl-surface-3: #eef2f6;
    --vtl-border: #dde3ea;
    --vtl-border-strong: #c6ced9;

    --vtl-ink: #16202c;
    --vtl-ink-2: #44515f;
    --vtl-ink-3: #6b7887;

    /* Cabecera / chrome */
    --vtl-chrome: #16202c;
    --vtl-chrome-2: #1e2a38;
    --vtl-chrome-ink: #e8edf3;
    --vtl-chrome-ink-2: #9fb0c2;

    /* Acento (se mantiene el azul de marca, solo para acción) */
    --vtl-accent: #1a6fd4;
    --vtl-accent-strong: #1558a8;
    --vtl-accent-soft: #e8f1fc;

    /* Semánticos suaves para badges y avisos */
    --vtl-ok: #197b4a;
    --vtl-ok-soft: #e4f4ec;
    --vtl-warn: #9a6400;
    --vtl-warn-soft: #fdf1dc;
    --vtl-danger: #b3261e;
    --vtl-danger-soft: #fbe9e7;
    --vtl-info: #1558a8;
    --vtl-info-soft: #e8f1fc;
    --vtl-neutral: #4a5765;
    --vtl-neutral-soft: #eceff3;

    /* Métrica */
    --vtl-r-sm: 6px;
    --vtl-r: 10px;
    --vtl-r-lg: 14px;
    --vtl-header-h: 56px;
    --vtl-header-h-desktop: 62px;
    --vtl-nav-h: 62px;
    --vtl-sidebar-w: 232px;

    --vtl-shadow-xs: 0 1px 2px rgba(16, 24, 40, .05);
    --vtl-shadow-sm: 0 1px 3px rgba(16, 24, 40, .07), 0 1px 2px rgba(16, 24, 40, .04);
    --vtl-shadow-md: 0 8px 24px rgba(16, 24, 40, .10);
    --vtl-shadow-lg: 0 24px 48px rgba(16, 24, 40, .18);
    --vtl-ring: 0 0 0 3px rgba(26, 111, 212, .28);

    /* Se realinean los tokens antiguos para que TODO lo que ya usaba
       var(--primary-color), var(--border-color), etc. herede el tema
       nuevo sin tener que reescribir las reglas viejas. */
    --primary-color: var(--vtl-accent);
    --primary-light: #4a90e2;
    --primary-dark: var(--vtl-accent-strong);
    --secondary-color: var(--vtl-ok);
    --secondary-dark: #14603a;
    --text-color: var(--vtl-ink);
    --text-darker: var(--vtl-ink);
    --text-light: var(--vtl-ink-3);
    --bg-color: var(--vtl-canvas);
    --card-bg: var(--vtl-surface);
    --border-color: var(--vtl-border);
    --input-border-color: var(--vtl-border-strong);
    --success-color: var(--vtl-ok);
    --warning-color: #c98a00;
    --danger-color: var(--vtl-danger);
    --info-color: var(--vtl-info);
    --shadow: var(--vtl-shadow-sm);
    --shadow-hover: var(--vtl-shadow-md);
    --radius-md: var(--vtl-r);
}

/* =====================================================================
   2. BASE Y TIPOGRAFÍA
   Problema: h1/h2 con clamp() hasta 3rem y subrayado degradado comían
   una franja enorme en cada sección.
   ===================================================================== */
body {
    background-color: var(--vtl-canvas);
    color: var(--vtl-ink);
    font-size: 15px;
    line-height: 1.55;
    letter-spacing: 0;
    padding-top: var(--vtl-header-h);
    padding-bottom: var(--vtl-nav-h);
}

h1, h2, h3, h4 {
    color: var(--vtl-ink);
    letter-spacing: -0.015em;
}
h2 {
    font-size: 1.3rem;
    font-weight: 700;
    color: var(--vtl-ink);
    border-bottom: none;
    padding-bottom: 0;
    margin-bottom: 0;
    display: flex;
    align-items: center;
    gap: 10px;
}
h2::after { display: none; }          /* fuera el subrayado degradado */
h2 > i {
    color: var(--vtl-accent);
    font-size: 1.05rem;
}
h3 {
    font-size: 1rem;
    font-weight: 650;
    color: var(--vtl-ink);
    margin-bottom: 14px;
    display: flex;
    align-items: center;
    gap: 8px;
}
h3 > i { color: var(--vtl-ink-3); font-size: .95rem; }
h4 { font-size: .9rem; font-weight: 650; }

.text-muted { color: var(--vtl-ink-3); }

/* Enfoque visible y coherente en todo lo interactivo (accesibilidad) */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
    outline: 2px solid var(--vtl-accent);
    outline-offset: 2px;
    border-radius: var(--vtl-r-sm);
}

/* Respeta a quien pide menos animación en el sistema */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .001ms !important;
        scroll-behavior: auto !important;
    }
}

/* =====================================================================
   3. CABECERA
   Problema: azul saturado a pantalla completa + botón EMERGENCIA
   amarillo centrado dominando la interfaz; en 390px el nombre
   "VITROLAB" se solapaba con ese botón y con el usuario.
   ===================================================================== */
.header {
    height: var(--vtl-header-h);
    background: var(--vtl-chrome);
    color: var(--vtl-chrome-ink);
    box-shadow: none;
    border-bottom: 1px solid rgba(255, 255, 255, .07);
}
.header-content {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 0 14px;
    max-width: 100%;
}
.logo-section {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;          /* permite que el texto se recorte en vez de empujar */
    flex: 0 1 auto;
    overflow: hidden;
}
.logo { gap: 10px; min-width: 0; }
.logogdp {
    width: 34px;
    height: 34px;
    border-radius: 8px;
    flex: 0 0 auto;
    background-color: #fff;
    background-size: 82%;
    background-position: center;
    background-repeat: no-repeat;
    border: 1px solid rgba(255, 255, 255, .18);
}
.text-content { min-width: 0; }
.inline-title span,
.text-content span {
    font-family: var(--font-secondary);
    font-size: 1rem;
    font-weight: 700;
    letter-spacing: .02em;
    color: #fff;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    display: block;
}

/* El botón de emergencia deja de ser el elemento más llamativo de la
   pantalla: sigue siendo el único ámbar, pero discreto y a la derecha. */
.header-actions { margin-left: auto; flex: 0 0 auto; }
#emergency-protocol-btn.btn,
.header-actions .btn {
    width: auto;
    margin-top: 0;
    padding: 7px 12px;
    font-size: .74rem;
    border-radius: 999px;
    text-transform: none;
    letter-spacing: .01em;
    background: rgba(255, 193, 7, .14);
    color: #ffd257;
    border: 1px solid rgba(255, 193, 7, .45);
    box-shadow: none;
}
#emergency-protocol-btn.btn:hover,
.header-actions .btn:hover {
    background: rgba(255, 193, 7, .24);
    color: #ffdd85;
    transform: none;
}

.user-menu {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 0 0 auto;
    color: var(--vtl-chrome-ink);
    font-size: .82rem;
}
.user-menu > span:first-child {
    max-width: 130px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.user-menu .user-role-badge {
    background: rgba(255, 255, 255, .12);
    color: var(--vtl-chrome-ink-2);
    border: 1px solid rgba(255, 255, 255, .16);
    border-radius: 999px;
    padding: 2px 9px;
    font-size: .66rem;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
}
.user-menu button {
    background: transparent;
    border: 1px solid rgba(255, 255, 255, .18);
    color: var(--vtl-chrome-ink);
    border-radius: 8px;
    width: 34px;
    height: 34px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
}
.user-menu button:hover { background: rgba(255, 255, 255, .1); }

.icon-only-btn {
    color: var(--vtl-chrome-ink);
    border-radius: 8px;
    margin-right: 0;
    padding: 8px 10px;
}
.icon-only-btn:hover { background: rgba(255, 255, 255, .1); }

/* =====================================================================
   4. NAVEGACIÓN
   Problema (escritorio): `.nav a { flex: 1 }` del layout móvil no se
   reseteaba en la columna lateral, así que los 6 enlaces se repartían
   TODA la altura de la pantalla y quedaban separados ~130 px.
   ===================================================================== */
@media (min-width: 768px) {
    body { padding-top: var(--vtl-header-h-desktop); padding-bottom: 0; }
    .header { height: var(--vtl-header-h-desktop); }

    .nav {
        top: var(--vtl-header-h-desktop);
        width: var(--vtl-sidebar-w);
        background: var(--vtl-surface);
        border-right: 1px solid var(--vtl-border);
        box-shadow: none;
        padding: 10px 8px;
    }
    .nav-content { gap: 2px; padding-top: 0; }
    .nav a {
        flex: 0 0 auto;                /* <- la corrección del reparto */
        min-height: 0;
        padding: 9px 12px;
        margin: 0;
        border-radius: var(--vtl-r-sm);
        font-size: .875rem;
        font-weight: 500;
        color: var(--vtl-ink-2);
    }
    .nav a i {
        font-size: 1rem;
        width: 20px;
        margin-right: 12px;
        color: var(--vtl-ink-3);
    }
    .nav a:hover {
        background: var(--vtl-surface-3);
        color: var(--vtl-ink);
        transform: none;
    }
    .nav a:hover i { transform: none; color: var(--vtl-ink-2); }
    .nav a.active {
        background: var(--vtl-accent-soft);
        color: var(--vtl-accent-strong);
        font-weight: 650;
    }
    .nav a.active i { color: var(--vtl-accent); }
    .nav a.active::before { display: none; }
    .nav a::after { display: none; }   /* fuera el destello radial */

    .main-content {
        margin-left: var(--vtl-sidebar-w);
        max-width: calc(100% - var(--vtl-sidebar-w));
        padding: 22px 26px 40px;
    }
    .footer { margin-left: var(--vtl-sidebar-w); }
    .sidebar-collapsed .main-content,
    .sidebar-collapsed .footer { margin-left: 72px; max-width: calc(100% - 72px); }
    .sidebar-collapsed .nav { width: 72px; }
}

/* Cabecera en pantallas estrechas: el nombre de la app se oculta antes
   de llegar a recortarse con puntos suspensivos, y el botón de
   emergencia se reduce a su icono. Así deja de solaparse todo. */
@media (max-width: 560px) {
    .header-content { gap: 8px; padding: 0 10px; }
    .text-content, .inline-title { display: none; }
    .user-menu > span:first-child { max-width: 92px; font-size: .78rem; }
    #emergency-protocol-btn.btn,
    .header-actions .btn { padding: 7px 10px; }
}
@media (max-width: 400px) {
    .user-menu .user-role-badge { display: none; }
}

/* Barra inferior en móvil: iconos legibles y respeto del área segura */
@media (max-width: 767px) {
    .nav {
        height: auto;
        padding-bottom: env(safe-area-inset-bottom);
        border-top: 1px solid var(--vtl-border);
        box-shadow: 0 -1px 6px rgba(16, 24, 40, .06);
    }
    .nav-content { height: var(--vtl-nav-h); }
    .nav a { font-size: .66rem; gap: 2px; color: var(--vtl-ink-3); }
    .nav a i { font-size: 1.15rem; margin-bottom: 2px; }
    .nav a.active { color: var(--vtl-accent); }
    .main-content { padding: 14px 12px 28px; }
}

/* =====================================================================
   5. CABECERA DE PÁGINA  (nuevo .page-head en views/app.php)
   Problema: el botón "Nueva Muestra" ocupaba una tarjeta blanca entera
   para él solo, empujando la tabla fuera de la primera pantalla.
   ===================================================================== */
.page-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px 16px;
    margin-bottom: 16px;
    padding-bottom: 14px;
    border-bottom: 1px solid var(--vtl-border);
}
.page-head h2 { margin: 0; flex: 1 1 auto; }
.page-head .section-actions {
    background: none;
    box-shadow: none;
    border: 0;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    gap: 8px;
    width: auto;
}
.page-head .section-actions .btn { width: auto; margin-top: 0; }
@media (max-width: 600px) {
    .page-head { gap: 10px; }
    .page-head .section-actions { width: 100%; }
    .page-head .section-actions .btn { flex: 1 1 auto; }
}

/* =====================================================================
   6. TARJETAS
   ===================================================================== */
.card {
    background: var(--vtl-surface);
    border: 1px solid var(--vtl-border);
    border-radius: var(--vtl-r);
    box-shadow: var(--vtl-shadow-xs);
    padding: 18px;
    margin-bottom: 16px;
}
.card:hover { box-shadow: var(--vtl-shadow-xs); transform: none; }
@media (min-width: 768px) { .card { padding: 20px 22px; } }

/* Barra de filtros dentro de la tarjeta de listado */
.card > .form-grid:first-child {
    padding-bottom: 14px;
    margin-bottom: 14px;
    border-bottom: 1px solid var(--vtl-border);
}

/* =====================================================================
   7. BOTONES  (un único sistema)
   Problema: convivían botones amarillos, rojos, verdes, morados y
   azules sin criterio semántico, todos en mayúsculas y a 12px de alto.
   Ahora: 1 primario sólido, el resto contorno neutro, y el rojo
   reservado a lo destructivo.
   ===================================================================== */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    width: auto;
    margin-top: 0;
    padding: 9px 15px;
    font-family: var(--font-primary);
    font-size: .84rem;
    font-weight: 600;
    letter-spacing: 0;
    text-transform: none;
    border: 1px solid transparent;
    border-radius: var(--vtl-r-sm);
    line-height: 1.2;
    box-shadow: var(--vtl-shadow-xs);
    transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
.btn i { margin-right: 0; }
.btn:hover { transform: none; }
.btn:disabled, .btn[disabled] { opacity: .55; cursor: not-allowed; }

.btn-primary { background: var(--vtl-accent); border-color: var(--vtl-accent); color: #fff; }
.btn-primary:hover { background: var(--vtl-accent-strong); border-color: var(--vtl-accent-strong); }

.btn-secondary,
.btn-orange,
.btn-purple-medium {
    background: var(--vtl-surface);
    border-color: var(--vtl-border-strong);
    color: var(--vtl-ink-2);
}
.btn-secondary:hover,
.btn-orange:hover,
.btn-purple-medium:hover {
    background: var(--vtl-surface-3);
    border-color: var(--vtl-ink-3);
    color: var(--vtl-ink);
}

.btn-warning { background: var(--vtl-surface); border-color: var(--vtl-border-strong); color: var(--vtl-ink-2); }
.btn-warning:hover { background: var(--vtl-surface-3); color: var(--vtl-ink); }

.btn-danger { background: var(--vtl-surface); border-color: #e6b7b3; color: var(--vtl-danger); }
.btn-danger:hover { background: var(--vtl-danger); border-color: var(--vtl-danger); color: #fff; }

.btn-group { gap: 8px; margin-top: 14px; margin-bottom: 0; }
.btn-group .btn { flex-grow: 0; }
@media (max-width: 600px) { .btn-group .btn { flex-grow: 1; } }

/* Acciones dentro de una fila: iconos discretos, no bloques de color */
.action-buttons { gap: 4px; justify-content: flex-end; }
.action-buttons .btn {
    width: 32px;
    height: 32px;
    padding: 0;
    border-radius: var(--vtl-r-sm);
    background: transparent;
    border-color: transparent;
    box-shadow: none;
    color: var(--vtl-ink-3);
    font-size: .82rem;
}
.action-buttons .btn:hover { background: var(--vtl-surface-3); color: var(--vtl-ink); }
.action-buttons .btn.btn-danger:hover { background: var(--vtl-danger-soft); color: var(--vtl-danger); border-color: transparent; }
.action-buttons .btn i { margin: 0; }

.icon-btn {
    border-radius: var(--vtl-r-sm);
    color: var(--vtl-ink-3);
    background: transparent;
    border: 1px solid transparent;
}
.icon-btn:hover { background: var(--vtl-surface-3); color: var(--vtl-ink); }
/* Los iconos de borrar no van en rojo permanente: en una lista larga
   convierten la pantalla en un semáforo. Rojo solo al apuntarlos. */
.icon-btn.danger,
.catalog-item-row .icon-btn.danger,
.user-row .icon-btn.danger { color: var(--vtl-ink-3); }
.icon-btn.danger:hover,
.catalog-item-row .icon-btn.danger:hover,
.user-row .icon-btn.danger:hover { background: var(--vtl-danger-soft); color: var(--vtl-danger); }
.catalog-item-row .icon-btn { padding: 6px 8px; border-radius: var(--vtl-r-sm); }
.catalog-item-row .icon-btn:hover { background: var(--vtl-surface-3); color: var(--vtl-ink); }

/* =====================================================================
   8. BADGES  (un solo sistema de píldoras en tonos apagados)
   Problema: cada valor de catálogo pintaba un color plano distinto, y
   una prioridad vacía dejaba un cuadrado verde sin texto.
   ===================================================================== */
[class^="badge-"],
[class*=" badge-"] {
    display: inline-block;
    padding: 3px 9px;
    border-radius: 999px;
    font-size: .72rem;
    font-weight: 600;
    line-height: 1.5;
    letter-spacing: .01em;
    white-space: nowrap;
    background: var(--vtl-neutral-soft);
    color: var(--vtl-neutral);
    border: 1px solid transparent;
}
/* Una píldora sin texto no se pinta (prioridad/estado sin asignar) */
[class^="badge-"]:empty,
[class*=" badge-"]:empty { display: none; }

.badge-urgente,
.badge-contaminado { background: var(--vtl-danger-soft); color: var(--vtl-danger); border-color: #f0cdc9; }
.badge-alta,
.badge-anormal,
.badge-amarillo { background: var(--vtl-warn-soft); color: var(--vtl-warn); border-color: #f0dcb4; }
.badge-naranja { background: #fdeadb; color: #8a4b12; border-color: #f2d0b4; }
.badge-media,
.badge-azul-celeste { background: var(--vtl-info-soft); color: var(--vtl-info); border-color: #cfe1f6; }
.badge-baja,
.badge-normal,
.badge-verde-claro { background: var(--vtl-ok-soft); color: var(--vtl-ok); border-color: #c8e6d6; }
.badge-necrosado { background: #ece7e2; color: #6b4a2f; border-color: #ddd2c7; }

.status-pill {
    display: inline-block;
    padding: 3px 9px;
    border-radius: 999px;
    font-size: .7rem;
    font-weight: 600;
    text-transform: capitalize;
    background: var(--vtl-neutral-soft);
    color: var(--vtl-neutral);
}
.status-pill.active { background: var(--vtl-ok-soft); color: var(--vtl-ok); }
.status-pill.pending { background: var(--vtl-warn-soft); color: var(--vtl-warn); }
.status-pill.disabled { background: var(--vtl-neutral-soft); color: var(--vtl-ink-3); }

/* =====================================================================
   9. FORMULARIOS
   Problema: los campos de contraseña tenían un estilo propio (borde
   fino, sin radio) distinto al resto; los campos medían 48-52 px de
   alto y un campo suelto dejaba media fila vacía.
   ===================================================================== */
label {
    font-size: .74rem;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--vtl-ink-3);
    margin-bottom: 5px;
    display: block;
}
.form-group { margin-bottom: 14px; }
.form-grid { gap: 14px 18px; }

input[type="text"],
input[type="password"],
input[type="email"],
input[type="number"],
input[type="date"],
input[type="search"],
select,
textarea,
.password-field input {
    width: 100%;
    padding: 9px 11px;
    font-family: var(--font-primary);
    font-size: .9rem;
    color: var(--vtl-ink);
    background: var(--vtl-surface);
    border: 1px solid var(--vtl-border-strong);
    border-radius: var(--vtl-r-sm);
    box-shadow: none;
    transition: border-color .15s ease, box-shadow .15s ease;
}
textarea { min-height: 84px; resize: vertical; }
input::placeholder, textarea::placeholder { color: #9aa5b1; }

input:focus,
select:focus,
textarea:focus,
.password-field input:focus {
    outline: none;
    border-color: var(--vtl-accent);
    box-shadow: var(--vtl-ring);
    transform: none;          /* anula el salto de -5px en móvil */
}
input:disabled, select:disabled, textarea:disabled,
input[readonly] {
    background: var(--vtl-surface-3);
    color: var(--vtl-ink-3);
    cursor: not-allowed;
}

.password-field { position: relative; }
.password-field input { padding-right: 40px; }
.password-field .password-toggle {
    position: absolute;
    right: 4px;
    top: 50%;
    transform: translateY(-50%);
    width: 32px;
    height: 32px;
    border: 0;
    background: transparent;
    color: var(--vtl-ink-3);
    border-radius: var(--vtl-r-sm);
    cursor: pointer;
}
.password-field .password-toggle:hover { background: var(--vtl-surface-3); color: var(--vtl-ink); }

/* En móvil los controles se quedan en 16 px reales: por debajo de ese
   tamaño iOS hace zoom automático al enfocar un campo y descoloca la
   pantalla. */
@media (max-width: 767px) {
    input[type="text"], input[type="password"], input[type="email"],
    input[type="number"], input[type="date"], input[type="search"],
    select, textarea, .password-field input {
        font-size: 16px;
        padding: 11px 12px;
    }
}

/* Un campo suelto al final de una rejilla de 2 columnas ocupa la fila
   entera en lugar de dejar el hueco a la derecha. */
@media (min-width: 768px) {
    .form-grid > .form-group:last-child:nth-child(odd) { grid-column: 1 / -1; }
    .form-grid > .form-group:has(textarea) { grid-column: 1 / -1; }
}

/* =====================================================================
   10. TABLAS
   Problema: cabecera azul sólida, filas de 60 px, cebra marcada.
   ===================================================================== */
.table-container {
    border: 1px solid var(--vtl-border);
    border-radius: var(--vtl-r);
    overflow-x: auto;
    background: var(--vtl-surface);
}
.data-table { border-radius: 0; box-shadow: none; overflow: visible; }

/* Dentro de una tarjeta la tabla va a sangre: la tarjeta ya hace de
   marco, así que se evita el efecto "caja dentro de caja". */
@media (min-width: 768px) {
    .card > .table-container {
        border-left: 0;
        border-right: 0;
        border-radius: 0;
        margin-left: -22px;
        margin-right: -22px;
    }
}
.data-table th {
    background: var(--vtl-surface-2);
    color: var(--vtl-ink-3);
    font-family: var(--font-primary);
    font-size: .7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .06em;
    padding: 10px 14px;
    border-bottom: 1px solid var(--vtl-border);
    white-space: nowrap;
}
.data-table td {
    padding: 10px 14px;
    font-size: .875rem;
    color: var(--vtl-ink-2);
    border-bottom: 1px solid var(--vtl-surface-3);
    vertical-align: middle;
}
.data-table tbody tr:last-child td { border-bottom: 0; }
.data-table tbody tr:nth-child(even) { background: transparent; }
.data-table tbody tr:hover { background: var(--vtl-surface-2); }
.data-table td:first-child {
    font-weight: 650;
    color: var(--vtl-ink);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.data-table td:last-child { text-align: right; }

/* Fila de "sin resultados": deja de parecer un dato más */
.data-table tbody tr td[colspan] {
    text-align: center;
    padding: 34px 16px;
    color: var(--vtl-ink-3);
    font-size: .875rem;
}

/* ---------------------------------------------------------------------
   10b. TABLAS COMO FICHAS EN MÓVIL
   Problema: en 390 px la tabla se desbordaba y el código
   "M-05092026-0062" se partía en tres líneas.
   Solo afecta a las tablas marcadas con .data-table-cards (los tres
   listados principales); las tablas de dentro de los modales siguen
   comportándose como antes.
   --------------------------------------------------------------------- */
@media (max-width: 767px) {
    .table-container:has(.data-table-cards) {
        border: 0;
        background: transparent;
        overflow: visible;
    }
    .data-table-cards,
    .data-table-cards tbody,
    .data-table-cards tr,
    .data-table-cards td { display: block; width: 100%; }
    /* .data-table lleva min-width:600px para el scroll horizontal; en
       modo ficha hay que anularlo o las tarjetas se salen de la pantalla. */
    .data-table-cards { min-width: 0; }
    .data-table-cards thead { display: none; }
    .data-table-cards tr {
        background: var(--vtl-surface);
        border: 1px solid var(--vtl-border);
        border-radius: var(--vtl-r);
        box-shadow: var(--vtl-shadow-xs);
        padding: 10px 14px;
        margin-bottom: 10px;
    }
    .data-table-cards tbody tr:hover { background: var(--vtl-surface); }
    .data-table-cards td {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 14px;
        padding: 5px 0;
        border: 0;
        text-align: right;
    }
    .data-table-cards td::before {
        content: attr(data-label);
        flex: 0 0 auto;
        font-size: .68rem;
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: .05em;
        color: var(--vtl-ink-3);
        text-align: left;
    }
    .data-table-cards td:first-child {
        display: block;
        font-size: 1rem;
        text-align: left;
        padding-bottom: 8px;
        margin-bottom: 4px;
        border-bottom: 1px solid var(--vtl-surface-3);
    }
    .data-table-cards td:first-child::before { content: ''; display: none; }

    /* La tarjeta contenedora se retira en móvil: si no, cada ficha
       quedaría como una caja blanca dentro de otra caja blanca. Los
       filtros conservan su propia superficie. */
    .card:has(.data-table-cards) {
        background: transparent;
        border: 0;
        box-shadow: none;
        padding: 0;
    }
    .card:has(.data-table-cards) > .form-grid:first-child {
        background: var(--vtl-surface);
        border: 1px solid var(--vtl-border);
        border-radius: var(--vtl-r);
        padding: 14px;
        margin-bottom: 14px;
    }
    .card:has(.data-table-cards) > .api-pagination { border-top: 0; }
    .data-table-cards td:last-child {
        padding-top: 9px;
        margin-top: 5px;
        border-top: 1px solid var(--vtl-surface-3);
    }
    .data-table-cards td[colspan] { display: block; text-align: center; }
    .data-table-cards td[colspan]::before { content: ''; }
    .data-table-cards .action-buttons .btn {
        width: auto;
        min-width: 40px;
        height: 34px;
        border: 1px solid var(--vtl-border);
    }
}
/* Reserva para navegadores sin :has() - la tabla sigue con scroll
   horizontal, que es el comportamiento anterior (nunca peor). */
@supports not (selector(:has(*))) {
    @media (max-width: 767px) {
        .data-table-cards, .data-table-cards tbody,
        .data-table-cards tr, .data-table-cards td { display: revert; }
        .data-table-cards thead { display: revert; }
    }
}

/* =====================================================================
   11. PANEL / KPI
   Problema: las tarjetas se pintan con la clase .gades-widget, pero la
   regla responsive del CSS antiguo apuntaba a .kpi-widget, así que en
   móvil nunca se aplicaba y las tarjetas se quedaban en 180 px sueltos
   ocupando media pantalla.
   ===================================================================== */
.dashboard-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
    gap: 12px;
    margin-bottom: 16px;
}
.gades-widget,
.kpi-widget {
    display: block;
    width: auto;
    min-width: 0;
    max-width: none;
    margin: 0;
    padding: 14px 16px;
    text-align: left;
    background: var(--vtl-surface);
    border: 1px solid var(--vtl-border);
    border-left-width: 3px;
    border-radius: var(--vtl-r);
    box-shadow: var(--vtl-shadow-xs);
}
.gades-widget:hover,
.kpi-widget:hover { transform: none; box-shadow: var(--vtl-shadow-sm); border-color: var(--vtl-border-strong); }
.gades-widget-icon,
.kpi-widget-icon {
    display: block;
    font-size: 1rem;
    margin-bottom: 8px;
    opacity: .85;
}
.gades-widget-title,
.kpi-widget-title {
    font-family: var(--font-primary);
    font-size: .72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--vtl-ink-3);
    margin-bottom: 2px;
}
.gades-widget-value,
.kpi-widget-value {
    font-family: var(--font-secondary);
    font-size: 1.7rem;
    font-weight: 700;
    color: var(--vtl-ink);
    line-height: 1.15;
    font-variant-numeric: tabular-nums;
}
@media (max-width: 600px) {
    .dashboard-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
    .gades-widget, .kpi-widget { padding: 12px; }
    .gades-widget-value, .kpi-widget-value { font-size: 1.45rem; }
}

.chart-container { height: 250px; margin-top: 4px; }

/* Gráfico y actividad, lado a lado cuando hay sitio */
.dash-columns { display: grid; gap: 14px; }
@media (min-width: 1150px) {
    .dash-columns { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: start; }
    .dash-columns > .card { margin-bottom: 0; }
}

/* Registro de actividad: lista legible en dos columnas, no párrafos
   con float que se solapan en pantallas estrechas. */
#activity-log > p {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 4px 16px;
    border-bottom: 1px solid var(--vtl-surface-3) !important;
    border-bottom-style: solid !important;
    padding: 9px 0 !important;
    font-size: .85rem !important;
}
#activity-log > p > span:last-child { float: none !important; color: var(--vtl-ink-3) !important; }
#activity-log > p:last-child { border-bottom: 0 !important; }

/* =====================================================================
   12. MODALES
   Problema: los botones de guardar quedaban por debajo del pliegue y
   había que desplazarse a ciegas hasta el final de un formulario largo.

   Enfoque: el elemento que se desplaza sigue siendo .modal-content (como
   antes), y lo que cambia es que la cabecera y la barra de acciones son
   "sticky" dentro de él. Así funciona con TODAS las formas de modal que
   hay en la app -las que cuelgan un <form>, las que cuelgan bloques
   sueltos y las que ya traen .modal-footer- sin tocar su marcado.

   NOTA de especificidad: el CSS antiguo define `.ininewmodal
   .modal-content` (0,2,0), que gana a un `.modal-content` a secas; por
   eso se repiten los dos selectores.
   ===================================================================== */
.modal-overlay .modal-content,
.ininewmodal .modal-content,
.modal-content {
    padding: 0 20px 18px;
    border-radius: var(--vtl-r-lg);
    box-shadow: var(--vtl-shadow-lg);
    max-height: min(88vh, 900px);
    overflow-y: auto;
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
}

.modal-overlay .modal-header,
.ininewmodal .modal-header,
.modal-header {
    position: sticky;
    top: 0;
    z-index: 4;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin: 0 -20px 16px;
    padding: 15px 20px;
    background: var(--vtl-surface);
    border-bottom: 1px solid var(--vtl-border);
}
.modal-overlay .modal-title,
.ininewmodal .modal-title,
.modal-title {
    font-family: var(--font-secondary);
    font-size: 1.02rem;
    font-weight: 700;
    color: var(--vtl-ink);
    margin: 0;
    display: flex;
    align-items: center;
    gap: 9px;
    min-width: 0;
}
.modal-title i { color: var(--vtl-accent); font-size: .95rem; }
.modal-overlay .modal-close,
.ininewmodal .modal-close,
.modal-close {
    width: 34px;
    height: 34px;
    min-height: 34px;
    padding: 0;
    border: 0;
    border-radius: var(--vtl-r-sm);
    background: transparent;
    color: var(--vtl-ink-3);
    font-size: 1.3rem;
    line-height: 1;
    cursor: pointer;
    flex: 0 0 auto;
}
.modal-overlay .modal-close:hover,
.ininewmodal .modal-close:hover,
.modal-close:hover { background: var(--vtl-surface-3); color: var(--vtl-ink); }

/* Barra de acciones anclada al pie del modal.
   Los modales de datos no usan .modal-footer: cierran el <form> con un
   .btn-group. Se le da tratamiento de pie fijo sin tocar el marcado. */
.modal-content > form > .btn-group:last-child,
.modal-content > .btn-group:last-child,
.modal-overlay .modal-footer,
.ininewmodal .modal-footer,
.modal-content .modal-footer {
    position: sticky;
    bottom: -18px;                     /* compensa el padding inferior */
    z-index: 4;
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    align-items: center;
    gap: 8px;
    margin: 20px -20px -18px;
    padding: 12px 20px;
    background: var(--vtl-surface-2);
    border-top: 1px solid var(--vtl-border);
    text-align: right;
}
.modal-content > form > .btn-group:last-child .btn,
.modal-content > .btn-group:last-child .btn,
.modal-footer .btn { width: auto; margin-top: 0; flex-grow: 0; }

@media (max-width: 600px) {
    .modal-overlay .modal-content,
    .ininewmodal .modal-content,
    .modal-content { padding: 0 15px 14px; max-height: 92vh; border-radius: var(--vtl-r); }
    .modal-overlay .modal-header,
    .ininewmodal .modal-header,
    .modal-header { margin: 0 -15px 14px; padding: 13px 15px; }
    .modal-content > form > .btn-group:last-child,
    .modal-content > .btn-group:last-child,
    .ininewmodal .modal-footer,
    .modal-content .modal-footer { margin: 16px -15px -14px; padding: 11px 15px; bottom: -14px; }
    .modal-content > form > .btn-group:last-child .btn,
    .modal-content > .btn-group:last-child .btn,
    .modal-footer .btn { flex: 1 1 auto; }
}

/* Separadores sueltos dentro de modales de administración */
.modal-content > hr {
    border: 0;
    border-top: 1px solid var(--vtl-border);
    margin: 18px -20px;
}

/* Bloques "relacionados" dentro de un modal */
#related-data-sample, #related-data-culture {
    border-top: 1px solid var(--vtl-border) !important;
    margin-top: 18px !important;
    padding-top: 16px !important;
}

/* Separador de bloques dentro de un formulario largo */
.form-section-title {
    grid-column: 1 / -1;
    margin: 6px 0 2px;
    padding-top: 14px;
    border-top: 1px solid var(--vtl-border);
    font-size: .74rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--vtl-ink-3);
}
.form-section-title:first-child { border-top: 0; padding-top: 0; margin-top: 0; }

/* =====================================================================
   13. AVISOS, CARGA Y PAGINACIÓN
   ===================================================================== */
#message-box {
    border-radius: var(--vtl-r);
    box-shadow: var(--vtl-shadow-md);
    font-size: .875rem;
    font-weight: 550;
    padding: 12px 16px;
    border: 1px solid transparent;
}
.message-success { background: var(--vtl-ok-soft); color: var(--vtl-ok); border-color: #c8e6d6; }
.message-error { background: var(--vtl-danger-soft); color: var(--vtl-danger); border-color: #f0cdc9; }

.loading-box {
    border-radius: var(--vtl-r-lg);
    box-shadow: var(--vtl-shadow-lg);
    border: 1px solid var(--vtl-border);
}

.api-pagination {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 10px;
    margin-top: 14px;
    padding-top: 12px;
    border-top: 1px solid var(--vtl-border);
    font-size: .8rem;
    color: var(--vtl-ink-3);
}
.api-pagination button {
    width: 32px;
    height: 32px;
    border: 1px solid var(--vtl-border-strong);
    border-radius: var(--vtl-r-sm);
    background: var(--vtl-surface);
    color: var(--vtl-ink-2);
    cursor: pointer;
}
.api-pagination button:hover:not(:disabled) { background: var(--vtl-surface-3); }
.api-pagination button:disabled { opacity: .4; cursor: not-allowed; }
.api-pagination span { order: -1; margin-right: auto; }

/* Listas de administración (catálogos / usuarios) */
.catalog-item-row,
.user-row {
    border: 1px solid var(--vtl-border);
    border-radius: var(--vtl-r-sm);
    background: var(--vtl-surface);
    padding: 8px 10px;
    gap: 8px;
}
.catalog-item-row.inactive { background: var(--vtl-surface-2); opacity: .75; }
.user-row { flex-wrap: wrap; }
.user-meta { color: var(--vtl-ink-3); font-size: .78rem; }

.install-pwa-banner {
    border-radius: 999px;
    box-shadow: var(--vtl-shadow-md);
    font-size: .82rem;
    font-weight: 600;
}

.footer {
    border-top: 1px solid var(--vtl-border);
    background: var(--vtl-surface);
    color: var(--vtl-ink-3);
    font-size: .78rem;
}

/* =====================================================================
   14. IMPRESIÓN
   El informe PDF se genera con html2pdf a partir de #pdf-content, así
   que aquí solo se limpia la impresión directa del navegador.
   ===================================================================== */
@media print {
    .header, .nav, .footer, .section-actions, .page-head .section-actions,
    .api-pagination, .install-pwa-banner { display: none !important; }
    .main-content { margin: 0 !important; max-width: 100% !important; padding: 0 !important; }
    .card { border: 0; box-shadow: none; padding: 0; }
}

/* =====================================================================
   15. PIE DE PÁGINA
   El botón de ayuda dejaba de ser ayuda para convertirse en la llamada
   a la acción más grande de la pantalla.
   ===================================================================== */
.footer { padding: 16px 12px; }
.footer button {
    background: transparent;
    border: 1px solid var(--vtl-border-strong);
    color: var(--vtl-ink-2);
    border-radius: var(--vtl-r-sm);
    padding: 7px 14px;
    font-size: .82rem;
    font-weight: 600;
    box-shadow: none;
    width: auto;
    margin: 0 0 8px;
    cursor: pointer;
}
.footer button:hover { background: var(--vtl-surface-3); color: var(--vtl-ink); }

/* =====================================================================
   16. PANTALLA DE ACCESO
   El fondo azul plano no encajaba con el tema y el botón "Entrar"
   quedaba pequeño y desalineado a la izquierda.
   ===================================================================== */
.auth-body {
    background: radial-gradient(120% 120% at 20% 0%, #24344a 0%, var(--vtl-chrome) 55%, #0e1620 100%);
    padding: 24px 16px;
}
.auth-wrapper { max-width: 400px; }
.auth-card {
    padding: 30px 26px 26px;
    border: 1px solid rgba(255, 255, 255, .08);
    border-radius: var(--vtl-r-lg);
    box-shadow: 0 30px 70px rgba(0, 0, 0, .35);
}
.auth-logo h1 { font-size: 1.4rem; letter-spacing: -.02em; }
/* El logotipo iba sobre un rectángulo gris con sombra: se deja limpio
   sobre el blanco de la tarjeta. */
.logogdpAN {
    background-color: transparent;
    box-shadow: none;
    width: 210px;
    height: 120px;
}
.auth-tagline { margin-bottom: 22px; line-height: 1.45; }

.auth-form label {
    text-transform: none;      /* las etiquetas de acceso van en caja normal */
    letter-spacing: 0;
    font-size: .8rem;
    font-weight: 600;
    color: var(--vtl-ink-2);
}
.auth-form input {
    padding: 10px 12px;
    font-size: .95rem;
    border-color: var(--vtl-border-strong);
    border-radius: var(--vtl-r-sm);
}
.auth-form input:focus { box-shadow: var(--vtl-ring); }
.auth-form .btn { width: 100%; margin-top: 6px; padding: 11px 16px; font-size: .9rem; }

/* Fila de "recordar sesión": casilla y texto alineados y sin mayúsculas */
.auth-form input[type="checkbox"] {
    width: 16px;
    height: 16px;
    min-height: 0;
    accent-color: var(--vtl-accent);
    flex: 0 0 auto;
    padding: 0;
    box-shadow: none;
}
.auth-form input[type="checkbox"] + label {
    text-transform: none;
    letter-spacing: 0;
    font-weight: 500;
    font-size: .84rem;
    color: var(--vtl-ink-2);
    cursor: pointer;
}
.btn-link {
    font-family: var(--font-primary);
    font-size: .82rem;
    color: var(--vtl-accent);
    margin-top: 16px;
    font-weight: 550;
}
.auth-message.success { background: var(--vtl-ok-soft); color: var(--vtl-ok); }
.auth-message.error { background: var(--vtl-danger-soft); color: var(--vtl-danger); }
.auth-hint { color: var(--vtl-ink-3); font-size: .85rem; line-height: 1.5; }
.auth-footer { margin-top: 22px; }

/* =====================================================================
   17. CONTENIDOS EDITABLES  (Acerca / Guía / Protocolo)  - VTL012
   Bloques que ahora se pintan desde content_blocks (ver content.js) y
   pantalla de administración de esos bloques.
   ===================================================================== */
.content-block { margin-bottom: 18px; }
.content-block:last-child { margin-bottom: 0; }
.content-block-title {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 8px;
    font-size: .95rem;
    font-weight: 700;
    color: var(--vtl-ink);
}
.content-block-title i { color: var(--vtl-accent); font-size: .9rem; }
.content-emoji { font-size: 1.05rem; line-height: 1; }
.content-block p { margin: 0 0 8px; font-size: .9rem; line-height: 1.6; color: var(--vtl-ink-2); }
.content-block p:last-child { margin-bottom: 0; }
.content-block a { color: var(--vtl-accent); text-decoration: none; }
.content-block a:hover { text-decoration: underline; }
.content-bullets {
    margin: 8px 0 0;
    padding-left: 20px;
    font-size: .88rem;
    color: var(--vtl-ink-2);
}
.content-bullets li { margin-bottom: 4px; }

/* El bloque de "Acerca de" cierra con el aviso de copyright y versión */
.about-meta {
    margin-top: 16px;
    padding-top: 12px;
    border-top: 1px solid var(--vtl-border);
    text-align: center;
    font-size: .78rem;
    color: var(--vtl-ink-3);
}
.about-meta p { margin: 0; }

/* --- Administración de bloques --- */
.content-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 4px; }
.content-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 12px;
    background: var(--vtl-surface);
    border: 1px solid var(--vtl-border);
    border-radius: var(--vtl-r-sm);
}
.content-row.inactive { background: var(--vtl-surface-2); opacity: .7; }
.content-row-main { min-width: 0; flex: 1 1 auto; }
.content-row-title {
    display: flex;
    align-items: center;
    gap: 7px;
    font-weight: 650;
    font-size: .88rem;
    color: var(--vtl-ink);
}
.content-row-excerpt {
    font-size: .78rem;
    color: var(--vtl-ink-3);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.content-row-actions { display: flex; gap: 2px; flex: 0 0 auto; }
.content-row-actions .icon-btn {
    width: 32px;
    height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    font-size: .8rem;
}
.content-row-actions .icon-btn:disabled { opacity: .3; cursor: not-allowed; }

.content-preview {
    background: var(--vtl-surface-2);
    border: 1px dashed var(--vtl-border-strong);
    border-radius: var(--vtl-r-sm);
    padding: 12px 14px;
    min-height: 60px;
}
.field-hint {
    margin: 6px 0 0;
    font-size: .75rem;
    color: var(--vtl-ink-3);
    line-height: 1.5;
}
.field-hint code {
    background: var(--vtl-surface-3);
    padding: 1px 5px;
    border-radius: 4px;
    font-size: .95em;
}
.checkbox-row {
    display: flex;
    align-items: center;
    gap: 9px;
    text-transform: none;
    letter-spacing: 0;
    font-size: .88rem;
    font-weight: 500;
    color: var(--vtl-ink-2);
    cursor: pointer;
}
.checkbox-row input[type="checkbox"] {
    width: 16px;
    height: 16px;
    min-height: 0;
    padding: 0;
    accent-color: var(--vtl-accent);
    box-shadow: none;
    flex: 0 0 auto;
}

/* =====================================================================
   18. VERSIÓN EN LA BARRA SUPERIOR
   ===================================================================== */
.app-version {
    display: inline-block;
    margin-left: 8px;
    padding: 1px 7px;
    border-radius: 999px;
    background: rgba(255, 255, 255, .12);
    border: 1px solid rgba(255, 255, 255, .16);
    color: var(--vtl-chrome-ink-2);
    font-family: var(--font-primary);
    font-size: .66rem;
    font-weight: 600;
    letter-spacing: .03em;
    vertical-align: middle;
    white-space: nowrap;
}
.inline-title, .text-content .system-subtitle { display: flex; align-items: center; }

/* =====================================================================
   19. GUÍA DE BIENVENIDA
   ===================================================================== */
.welcome-icon { font-size: 2.4rem; text-align: center; margin-bottom: 10px; line-height: 1; }
.welcome-description { text-align: center; margin-bottom: 14px; }
.welcome-description p { margin: 0 0 8px; font-size: .92rem; line-height: 1.6; color: var(--vtl-ink-2); }
.welcome-description p:last-child { margin-bottom: 0; }
.welcome-features {
    background: var(--vtl-surface-2);
    border: 1px solid var(--vtl-border);
    padding: 12px 14px;
    border-radius: var(--vtl-r-sm);
    margin-top: 14px;
}
.welcome-features ul { margin: 0; padding-left: 18px; font-size: .87rem; color: var(--vtl-ink-2); }
.welcome-features li { margin-bottom: 4px; }

/* El logotipo de "Acerca de" va centrado bajo la cabecera del modal */
.about-logo { text-align: center; margin-bottom: 6px; }
.about-logo .logogdpAN { width: 190px; height: 96px; background-color: transparent; box-shadow: none; }

/* =====================================================================
   20. ACCESO POR APLICACIÓN  (VTL_F0b)
   ---------------------------------------------------------------------
   Problema: la fila de usuario solo mostraba rol y estado, y el acceso a
   VITROLAB / Glovebox era implícito (toda cuenta activa entraba en las
   dos). Ahora cada fila lleva sus casillas de acceso, y una cuenta sin
   ninguna marcada se distingue de un vistazo.
   ===================================================================== */
.app-access-list {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 6px;
}
.app-access-item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin: 0;
    padding: 4px 10px 4px 8px;
    border: 1px solid var(--vtl-border);
    border-radius: 999px;
    background: var(--vtl-surface-2);
    font-size: .78rem;
    font-weight: 500;
    color: var(--vtl-ink-2);
    text-transform: none;
    letter-spacing: 0;
    cursor: pointer;
    line-height: 1.4;
}
.app-access-item input[type="checkbox"] {
    width: auto;
    min-height: 0;
    height: auto;
    margin: 0;
    accent-color: var(--vtl-accent);
    cursor: pointer;
}
/* Concedido: la píldora se tiñe del verde semántico, igual que el resto
   de estados correctos de la aplicación. */
.app-access-item:has(input:checked) {
    background: var(--vtl-ok-soft);
    border-color: var(--vtl-ok-soft);
    color: var(--vtl-ok);
}
.app-access-item.locked,
.app-access-item:has(input:disabled) {
    cursor: not-allowed;
    opacity: .8;
}
.app-access-item.locked input,
.app-access-item:has(input:disabled) input { cursor: not-allowed; }

.user-row-main { min-width: 0; flex: 1 1 260px; }

.user-no-access {
    margin-top: 6px;
    font-size: .76rem;
    font-weight: 500;
    color: var(--vtl-danger);
    display: flex;
    align-items: center;
    gap: 6px;
}

/* Respaldo para navegadores sin :has() — el color de la píldora es un
   refuerzo visual, nunca la única señal: la casilla marcada ya lo dice. */
@supports not selector(:has(*)) {
    .app-access-item { background: var(--vtl-surface-2); color: var(--vtl-ink-2); }
}

/* =====================================================================
   21. SEMÁFORO DE CINCO NIVELES  (VTL_F3)
   ---------------------------------------------------------------------
   Problema: el sistema de avisos solo tenía dos estilos, correcto y
   error. El módulo de trazabilidad necesita cinco, y tienen que ser los
   MISMOS colores en el aviso flotante, en las píldoras de los pasos y en
   la barra de progreso del expediente: un vocabulario visual único.
   ===================================================================== */

/* --- Tokens de severidad --------------------------------------------
   El peligro no reutiliza el rojo de "incorrecto": es un morado propio.
   Si los dos fuesen rojos, de un vistazo no se distinguiría un dato mal
   escrito de un lote en riesgo, que es justo la diferencia que importa. */
:root {
    --sev-correcto: var(--vtl-ok);
    --sev-correcto-soft: var(--vtl-ok-soft);
    --sev-correcto-line: #c8e6d6;

    --sev-informacion: var(--vtl-info);
    --sev-informacion-soft: var(--vtl-info-soft);
    --sev-informacion-line: #c9dcf3;

    --sev-advertencia: var(--vtl-warn);
    --sev-advertencia-soft: var(--vtl-warn-soft);
    --sev-advertencia-line: #f0dcb4;

    --sev-incorrecto: var(--vtl-danger);
    --sev-incorrecto-soft: var(--vtl-danger-soft);
    --sev-incorrecto-line: #f0cdc9;

    --sev-peligro: #6b1f5c;
    --sev-peligro-soft: #f6e7f3;
    --sev-peligro-line: #e2c2da;
}

/* --- Aviso flotante -------------------------------------------------- */
#message-box {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    text-align: left;
    max-width: min(560px, 92vw);
    pointer-events: none;
}
/* El aviso flotante NUNCA llegaba a verse: app.css declara la opacidad en
   `#message-box` (especificidad de id) y la volvía a 1 en `.message-visible`
   (especificidad de clase), que pierde siempre, venga después o no. Se
   corrige aquí con id + clase, que es lo que gana. Es un fallo anterior a
   la trazabilidad; se descubrió al comprobar que los hallazgos de un paso
   se veían en pantalla. */
#message-box.message-visible {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
    /* El aviso NO intercepta clics: flota sobre la cabecera de los modales
       y, en el nivel «peligro» -que no se cierra solo-, dejaba muerta esa
       franja de pantalla hasta que se cerraba a mano. Lo único que hay que
       poder pulsar en él es su propia X. */
    pointer-events: none;
}
#message-box.message-visible .message-close { pointer-events: auto; }
.message-icon { flex: none; font-size: 1rem; line-height: 1.5; margin-top: 1px; }
.message-text { flex: 1 1 auto; min-width: 0; }
.message-main { display: block; }
.message-detalle {
    margin: 6px 0 0;
    padding-left: 16px;
    font-weight: 450;
    font-size: .82rem;
    line-height: 1.5;
    opacity: .92;
}
.message-detalle li { margin-bottom: 3px; }
.message-detalle li:last-child { margin-bottom: 0; }
.message-close {
    flex: none;
    background: transparent;
    border: 0;
    color: inherit;
    font-size: 1.15rem;
    line-height: 1;
    padding: 0 2px;
    cursor: pointer;
    opacity: .55;
}
.message-close:hover { opacity: 1; }

.message-correcto    { background: var(--sev-correcto-soft);    color: var(--sev-correcto);    border-color: var(--sev-correcto-line); }
.message-informacion { background: var(--sev-informacion-soft); color: var(--sev-informacion); border-color: var(--sev-informacion-line); }
.message-advertencia { background: var(--sev-advertencia-soft); color: var(--sev-advertencia); border-color: var(--sev-advertencia-line); }
.message-incorrecto  { background: var(--sev-incorrecto-soft);  color: var(--sev-incorrecto);  border-color: var(--sev-incorrecto-line); }
.message-peligro     { background: var(--sev-peligro-soft);     color: var(--sev-peligro);     border-color: var(--sev-peligro-line); }

/* Los nombres antiguos siguen funcionando: hay una decena de archivos
   que llaman a showMessage(..., 'success' | 'error'). */
.message-success { background: var(--sev-correcto-soft);   color: var(--sev-correcto);   border-color: var(--sev-correcto-line); }
.message-error   { background: var(--sev-incorrecto-soft); color: var(--sev-incorrecto); border-color: var(--sev-incorrecto-line); }

/* --- Píldoras de severidad ------------------------------------------- */
.sev-pill {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 10px 3px 8px;
    border-radius: 999px;
    font-size: .74rem;
    font-weight: 600;
    line-height: 1.5;
    white-space: nowrap;
    border: 1px solid transparent;
}
.sev-pill i { font-size: .8em; }
.sev-correcto    { background: var(--sev-correcto-soft);    color: var(--sev-correcto);    border-color: var(--sev-correcto-line); }
.sev-informacion { background: var(--sev-informacion-soft); color: var(--sev-informacion); border-color: var(--sev-informacion-line); }
.sev-advertencia { background: var(--sev-advertencia-soft); color: var(--sev-advertencia); border-color: var(--sev-advertencia-line); }
.sev-incorrecto  { background: var(--sev-incorrecto-soft);  color: var(--sev-incorrecto);  border-color: var(--sev-incorrecto-line); }
.sev-peligro     { background: var(--sev-peligro-soft);     color: var(--sev-peligro);     border-color: var(--sev-peligro-line); }

/* Fondos planos, para barras y franjas laterales */
.sev-bg-correcto    { background: var(--sev-correcto); }
.sev-bg-informacion { background: var(--sev-informacion); }
.sev-bg-advertencia { background: var(--sev-advertencia); }
.sev-bg-incorrecto  { background: var(--sev-incorrecto); }
.sev-bg-peligro     { background: var(--sev-peligro); }

/* --- Barra de progreso del expediente --------------------------------
   El porcentaje va al lado, no dentro: encima del relleno se volvía
   ilegible en cuanto la barra pasaba del 60 %. */
.trace-progress-wrap {
    display: flex;
    align-items: center;
    gap: 10px;
}
.trace-progress {
    position: relative;
    flex: 1 1 auto;
    height: 10px;
    background: var(--vtl-surface-3);
    border: 1px solid var(--vtl-border);
    border-radius: 999px;
    overflow: hidden;
    min-width: 90px;
}
.trace-progress-bar {
    height: 100%;
    border-radius: 999px;
    transition: width .35s ease;
}
.trace-progress-pct {
    flex: none;
    font-size: .74rem;
    font-weight: 600;
    color: var(--vtl-ink-2);
    font-variant-numeric: tabular-nums;
    min-width: 44px;
    text-align: right;
}

/* --- Franja lateral para bloques de mensaje -------------------------- */
.sev-block {
    border: 1px solid var(--vtl-border);
    border-left-width: 4px;
    border-radius: var(--vtl-r-sm);
    padding: 10px 14px;
    font-size: .85rem;
    line-height: 1.55;
    background: var(--vtl-surface);
}
.sev-block.sev-correcto    { border-left-color: var(--sev-correcto); }
.sev-block.sev-informacion { border-left-color: var(--sev-informacion); }
.sev-block.sev-advertencia { border-left-color: var(--sev-advertencia); }
.sev-block.sev-incorrecto  { border-left-color: var(--sev-incorrecto); }
.sev-block.sev-peligro     { border-left-color: var(--sev-peligro); }

@media (prefers-reduced-motion: reduce) {
    .trace-progress-bar { transition: none; }
}

/* =====================================================================
   22. TRAZABILIDAD  ·  pantalla dentro de los modales   (VTL_F4)
   ---------------------------------------------------------------------
   Dos piezas: las pestañas del modal (Ficha / Trazabilidad) y la lista
   de pasos del expediente. Los colores no se definen aquí: salen de los
   tokens --sev-* de la sección 21, para que un paso incorrecto tenga
   exactamente el mismo rojo que su aviso flotante.
   ===================================================================== */

/* --- Pestañas del modal --------------------------------------------- */
.modal-tabs {
    display: flex;
    gap: 4px;
    border-bottom: 1px solid var(--vtl-border);
    margin: 0 0 18px;
    overflow-x: auto;
}
.modal-tab {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 16px;
    border: none;
    border-bottom: 2px solid transparent;
    background: none;
    color: var(--vtl-ink-3);
    font: inherit;
    font-size: .875rem;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    transition: color .15s ease, border-color .15s ease;
}
.modal-tab:hover:not(:disabled) { color: var(--vtl-ink); }
.modal-tab.active {
    color: var(--vtl-accent);
    border-bottom-color: var(--vtl-accent);
}
.modal-tab:disabled { opacity: .45; cursor: not-allowed; }
.modal-tab:focus-visible { outline: none; box-shadow: var(--vtl-ring); border-radius: var(--vtl-r-sm); }

.modal-tab-pill { display: inline-flex; align-items: center; gap: 6px; }
.modal-tab-dot {
    width: 9px; height: 9px;
    border-radius: 50%;
    display: inline-block;
}
.modal-tab-pct {
    font-size: .72rem;
    font-weight: 700;
    color: var(--vtl-ink-3);
    font-variant-numeric: tabular-nums;
}

.modal-tab-panel { display: none; }
.modal-tab-panel.active { display: block; }

/* --- Expediente sin abrir ------------------------------------------- */
.trace-vacio {
    text-align: center;
    padding: 34px 20px;
    border: 1px dashed var(--vtl-border-strong);
    border-radius: var(--vtl-r);
    background: var(--vtl-surface-2);
}
.trace-vacio-icono { font-size: 2rem; color: var(--vtl-ink-3); margin-bottom: 10px; }
.trace-vacio h4 { margin: 0 0 8px; }
.trace-vacio p { margin: 0 auto 10px; max-width: 62ch; font-size: .875rem; line-height: 1.6; }

/* --- Cabecera del expediente ---------------------------------------- */
.trace-head {
    display: grid;
    gap: 12px;
    padding: 16px;
    border: 1px solid var(--vtl-border);
    border-radius: var(--vtl-r);
    background: var(--vtl-surface-2);
    margin-bottom: 14px;
}
.trace-head-title { display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px; }
.trace-head-title h4 { margin: 0; font-size: 1rem; }
.trace-version { font-size: .75rem; color: var(--vtl-ink-3); }
.trace-head-estado { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.trace-estado-texto { font-size: .82rem; font-weight: 600; color: var(--vtl-ink-2); }
.trace-estado-pasos { font-size: .78rem; color: var(--vtl-ink-3); }
.trace-head-acciones { margin: 0; }
.trace-bloqueo { margin-bottom: 14px; }

/* --- Lista de pasos -------------------------------------------------- */
.trace-steps {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.trace-step {
    border: 1px solid var(--vtl-border);
    border-left-width: 4px;
    border-radius: var(--vtl-r-sm);
    background: var(--vtl-surface);
    overflow: hidden;
}
.trace-step-correcto    { border-left-color: var(--sev-correcto); }
.trace-step-informacion { border-left-color: var(--sev-informacion); }
.trace-step-advertencia { border-left-color: var(--sev-advertencia); }
.trace-step-incorrecto  { border-left-color: var(--sev-incorrecto); }
.trace-step-peligro     { border-left-color: var(--sev-peligro); }

.trace-step-head {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    padding: 12px 14px;
    border: none;
    background: none;
    font: inherit;
    text-align: left;
    cursor: pointer;
}
.trace-step-head:hover { background: var(--vtl-surface-2); }
.trace-step-head:focus-visible { outline: none; box-shadow: var(--vtl-ring); }
.trace-step-icon {
    flex: none;
    width: 32px; height: 32px;
    display: grid; place-items: center;
    border-radius: 50%;
    color: #fff;
    font-size: .82rem;
}
.trace-step-main { flex: 1 1 auto; min-width: 0; }
.trace-step-name { display: block; font-size: .9rem; font-weight: 650; color: var(--vtl-ink); }
.trace-step-sub { display: block; font-size: .75rem; color: var(--vtl-ink-3); margin-top: 2px; }
.trace-step-state { flex: none; }
.trace-step-caret { flex: none; color: var(--vtl-ink-3); transition: transform .2s ease; }
.trace-step.abierto .trace-step-caret { transform: rotate(180deg); }

.trace-step-body {
    padding: 4px 14px 16px;
    border-top: 1px solid var(--vtl-border);
}
.trace-step-ayuda {
    margin: 12px 0;
    font-size: .82rem;
    line-height: 1.55;
    color: var(--vtl-ink-2);
}
.trace-step-flags { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.trace-flag {
    display: inline-flex; align-items: center; gap: 5px;
    padding: 2px 9px;
    border-radius: 999px;
    background: var(--vtl-neutral-soft);
    color: var(--vtl-neutral);
    font-size: .7rem;
    font-weight: 650;
}
.trace-flag-opt     { background: var(--vtl-surface-3); }
.trace-flag-info    { background: var(--sev-informacion-soft); color: var(--sev-informacion); }
.trace-flag-aviso   { background: var(--sev-advertencia-soft); color: var(--sev-advertencia); }
.trace-flag-critico { background: var(--sev-peligro-soft); color: var(--sev-peligro); }
.trace-flag-bloquea { background: var(--sev-incorrecto-soft); color: var(--sev-incorrecto); }

.trace-mensajes {
    list-style: none;
    margin: 0 0 14px;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.trace-step-form { margin: 0; }
.trace-step-acciones { margin-top: 14px; }

/* --- Ayudas de campo ------------------------------------------------- */
.trace-ayuda, .trace-rango {
    display: block;
    margin-top: 4px;
    font-size: .74rem;
    line-height: 1.45;
    color: var(--vtl-ink-3);
}
.trace-rango { color: var(--vtl-ink-2); font-weight: 600; }
.trace-unidad { color: var(--vtl-ink-3); font-weight: 500; }
.trace-req { color: var(--sev-incorrecto); font-weight: 700; }
.trace-check { display: flex; align-items: center; gap: 8px; font-weight: 500; }
.trace-check input { width: auto; margin: 0; }
.trace-firma { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.trace-firma input { flex: 1 1 180px; }

/* --- Fotografías del paso -------------------------------------------- */
.trace-fotos-lista { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 8px; }
.trace-foto { position: relative; margin: 0; }
.trace-foto img {
    width: 96px; height: 96px;
    object-fit: cover;
    border-radius: var(--vtl-r-sm);
    border: 1px solid var(--vtl-border);
    display: block;
}
.trace-foto-quitar {
    position: absolute;
    top: -6px; right: -6px;
    width: 22px; height: 22px;
    border-radius: 50%;
    border: 1px solid var(--vtl-border);
    background: var(--vtl-surface);
    color: var(--sev-incorrecto);
    font-size: 1rem;
    line-height: 1;
    cursor: pointer;
}

/* --- Historial de cambios -------------------------------------------- */
.trace-changes { margin-top: 18px; }
.trace-changes h5 { margin: 0 0 10px; font-size: .9rem; }

@media (max-width: 640px) {
    .trace-step-head { flex-wrap: wrap; }
    .trace-step-state { width: 100%; padding-left: 44px; }
    .modal-tab { padding: 10px 12px; }
}
@media (prefers-reduced-motion: reduce) {
    .trace-step-caret { transition: none; }
}

/* =====================================================================
   23. DISEÑADOR DE PROTOCOLOS  (VTL_F6)
   ---------------------------------------------------------------------
   Reutiliza las piezas de la trazabilidad (.trace-step, .trace-flag,
   .sev-block): es la misma información, vista desde el otro lado.
   ===================================================================== */
.modal-ancho { width: min(1080px, 96vw); }

/* Un paso o un campo desactivado sigue viéndose -hay que poder
   reactivarlo- pero sin competir con los que están en uso. */
.fila-inactiva { opacity: .55; }
.fila-inactiva td strong { text-decoration: line-through; }

/* El formulario de protocolo/paso/campo se abre ENCIMA del modal del
   diseñador o del de catálogos, que son .ininewmodal con z-index 2000.
   Sin esto quedaba por debajo y sus botones no se podían pulsar. */
#traceFormModal { z-index: 2100; }

/* =====================================================================
   24. LECTURA DE LA IA  (VTL_F7)
   ---------------------------------------------------------------------
   Deliberadamente distinto del resto del expediente: fondo propio y
   franja lateral. Lo que hay dentro es opinión de una máquina, y tiene
   que notarse a simple vista que no es lo que registró el técnico.
   ===================================================================== */
.trace-ia {
    border: 1px solid var(--vtl-border);
    border-left: 4px solid var(--vtl-accent);
    border-radius: var(--vtl-r-sm);
    background: var(--vtl-accent-soft);
    margin-bottom: 14px;
    overflow: hidden;
}
.trace-ia-cab {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    padding: 11px 14px;
    cursor: pointer;
    font-size: .86rem;
    list-style: none;
}
.trace-ia-cab::-webkit-details-marker { display: none; }
.trace-ia-titulo { font-weight: 650; color: var(--vtl-accent-strong); }
.trace-ia-nota {
    margin-left: auto;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--vtl-ink-2);
}
.trace-ia-cuerpo {
    padding: 0 14px 14px;
    background: var(--vtl-surface);
    border-top: 1px solid var(--vtl-border);
}
.trace-ia-resumen {
    margin: 12px 0;
    font-size: .875rem;
    line-height: 1.6;
}
.trace-ia-reco {
    display: inline-block;
    margin-top: 4px;
    font-size: .8rem;
    color: var(--vtl-ink-2);
}
.trace-ia-pie {
    margin: 12px 0 0;
    padding-top: 10px;
    border-top: 1px dashed var(--vtl-border);
    font-size: .76rem;
    line-height: 1.5;
    color: var(--vtl-ink-3);
}

/* =====================================================================
   25. ASISTENTE, DIAGNOSTICO Y TENDENCIAS  (VTL_F8)
   ---------------------------------------------------------------------
   Todo lo de aqui reutiliza .trace-ia de la seccion 24 a proposito: sea
   una auditoria, un diagnostico o un informe, lo que se esta mirando es
   opinion de maquina y tiene que reconocerse por el mismo aspecto.
   ===================================================================== */

/* --- Franja lateral y texto por severidad, para el asistente --- */
.sev-borde-correcto    { border-left-color: var(--sev-correcto) !important; }
.sev-borde-informacion { border-left-color: var(--sev-informacion) !important; }
.sev-borde-advertencia { border-left-color: var(--sev-advertencia) !important; }
.sev-borde-incorrecto  { border-left-color: var(--sev-incorrecto) !important; }
.sev-borde-peligro     { border-left-color: var(--sev-peligro) !important; }

.sev-texto-correcto    { color: var(--sev-correcto); }
.sev-texto-informacion { color: var(--sev-informacion); }
.sev-texto-advertencia { color: var(--sev-advertencia); }
.sev-texto-incorrecto  { color: var(--sev-incorrecto); }
.sev-texto-peligro     { color: var(--sev-peligro); }

/* --- Asistente en vivo, dentro del paso --- */
.trace-asistencia { margin: 10px 0 4px; }
.trace-ia-asistente { margin-bottom: 0; }
.trace-ia-asistente .trace-ia-cab { cursor: default; }
.trace-ia-cerrar {
    margin-left: auto;
    border: 0;
    background: none;
    font-size: 1.2rem;
    line-height: 1;
    cursor: pointer;
    color: var(--vtl-ink-3);
    padding: 0 2px;
}
.trace-ia-cerrar:hover { color: var(--vtl-ink); }

.trace-ia-sugerencias {
    margin: 6px 0 0;
    padding: 0;
    list-style: none;
    font-size: .84rem;
    line-height: 1.55;
}
.trace-ia-sugerencias li { margin-bottom: 5px; }
.trace-ia-sugerencias li i { color: var(--vtl-accent); margin-right: 5px; }

/* --- Panel de diagnostico y de informe --- */
.ai-panel { display: block; }

.ai-vacio {
    text-align: center;
    padding: 34px 20px;
    border: 1px dashed var(--vtl-border);
    border-radius: var(--vtl-r-sm);
    background: var(--vtl-surface-2, var(--vtl-surface));
}
.ai-vacio-icono { font-size: 2.2rem; color: var(--vtl-ink-3); margin-bottom: 10px; }
.ai-vacio h4 { margin: 0 0 8px; }
.ai-vacio p { margin: 0 auto 10px; max-width: 640px; font-size: .875rem; line-height: 1.6; }

.ai-sub {
    margin: 16px 0 8px;
    font-size: .8rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--vtl-ink-2);
}

/* Cada causa lleva SIEMPRE en que se basa. Una causa sin dato que la
   sostenga no vale nada, y la maquetacion lo refleja: el dato va
   pegado debajo, no escondido. */
.ai-causas { margin: 0; padding: 0; list-style: none; }
.ai-causa {
    border: 1px solid var(--vtl-border);
    border-radius: var(--vtl-r-sm);
    padding: 10px 12px;
    margin-bottom: 8px;
    background: var(--vtl-surface);
}
.ai-causa-cab {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    font-size: .875rem;
}
.ai-causa-base,
.ai-causa-check {
    margin: 7px 0 0;
    font-size: .8rem;
    line-height: 1.55;
    color: var(--vtl-ink-2);
}
.ai-causa-base i { color: var(--vtl-ink-3); margin-right: 5px; }
.ai-causa-check i { color: var(--vtl-accent); margin-right: 5px; }

/* --- Cifras del periodo --- */
.ai-cifras {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 10px;
    margin: 12px 0;
}
.ai-cifra {
    border: 1px solid var(--vtl-border);
    border-radius: var(--vtl-r-sm);
    padding: 12px 14px;
    background: var(--vtl-surface);
    text-align: center;
}
.ai-cifra-mal { border-color: var(--sev-incorrecto-line, var(--vtl-border)); }
.ai-cifra-mal .ai-cifra-num { color: var(--sev-incorrecto); }
.ai-cifra-num {
    display: block;
    font-size: 1.25rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--vtl-ink);
}
.ai-cifra-txt {
    display: block;
    margin-top: 3px;
    font-size: .74rem;
    color: var(--vtl-ink-3);
}

.ai-tabla { width: 100%; border-collapse: collapse; font-size: .82rem; margin-top: 6px; }
.ai-tabla th, .ai-tabla td { padding: 7px 10px; border-bottom: 1px solid var(--vtl-border); text-align: left; }
.ai-tabla th { font-weight: 650; color: var(--vtl-ink-2); }
.ai-tabla .ai-num { text-align: right; font-variant-numeric: tabular-nums; }

/* --- Tendencias --- */
.ai-tendencias { margin: 0; padding: 0; list-style: none; }
.ai-tendencia {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 8px 0;
    border-bottom: 1px solid var(--vtl-border);
}
.ai-tendencia:last-child { border-bottom: 0; }
.ai-tendencia-icono {
    flex: 0 0 auto;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-size: .72rem;
}
.ai-tendencia-txt { font-size: .855rem; line-height: 1.5; }
.ai-tendencia-dato {
    display: block;
    margin-top: 2px;
    font-size: .78rem;
    color: var(--vtl-ink-3);
    font-style: normal;
}

/* La pestana de diagnostico se oculta con el atributo [hidden] cuando no
   hay IA configurada. Sin esta regla, el display:inline-flex de
   .modal-tab gana al display:none del navegador y la pestana seguia
   viendose: un boton que no lleva a ninguna parte. */
.modal-tab[hidden] { display: none !important; }

/* --- Estado de la IA, en Ajustes --- */
.ai-estado { margin: 10px 0 14px; }
.ai-estado code { font-size: .8rem; }

@media (max-width: 640px) {
    .ai-cifras { grid-template-columns: repeat(auto-fit, minmax(128px, 1fr)); }
    .ai-cifra-num { font-size: 1.05rem; }
}

/* =====================================================================
   26. CATALOGO DE MODELOS DE IA  (VTL_F81)
   ---------------------------------------------------------------------
   El catalogo de Google no es el mismo para todas las claves. Esta caja
   es donde se ve el de la suya y se elige uno, en vez de escribir un
   nombre a ciegas en el .env.
   ===================================================================== */
.ai-modelos {
    margin-top: 14px;
    padding-top: 14px;
    border-top: 1px dashed var(--vtl-border);
}
.ai-modelos select { width: 100%; }
.ai-modelos small {
    display: block;
    margin-top: 6px;
    font-size: .78rem;
    line-height: 1.5;
    color: var(--vtl-ink-3);
}
.ai-modelos code { font-size: .8rem; }

/* Diagnostico tecnico (VTL_F83): texto plano, monoespaciado y
   seleccionable de golpe. Aqui lo util es que se pueda copiar entero. */
.ai-diag {
    width: 100%;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: .74rem;
    line-height: 1.5;
    white-space: pre;
    overflow-x: auto;
    background: var(--vtl-surface);
    border: 1px solid var(--vtl-border);
    border-radius: var(--vtl-r-sm);
    padding: 10px 12px;
    resize: vertical;
}

/* =====================================================================
   27. COMPROBACION DEL SISTEMA  (VTL_F9)
   ---------------------------------------------------------------------
   Lista de repaso, no volcado: cada linea con su franja de color y, si
   hay algo que hacer, con que hacer.
   ===================================================================== */
.sys-lista { margin: 0 0 10px; padding: 0; list-style: none; }
.sys-item {
    border: 1px solid var(--vtl-border);
    border-left: 4px solid var(--vtl-border);
    border-radius: var(--vtl-r-sm);
    padding: 9px 12px;
    margin-bottom: 7px;
    background: var(--vtl-surface);
}
.sys-item-cab {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    font-size: .875rem;
}
.sys-item-txt { margin: 6px 0 0; font-size: .82rem; line-height: 1.55; }
.sys-item-arreglo {
    margin: 6px 0 0;
    font-size: .79rem;
    line-height: 1.5;
    color: var(--vtl-ink-2);
}
.sys-item-arreglo i { color: var(--vtl-accent); margin-right: 5px; }

/* =====================================================================
   VTL_F10 · LOTES DE SIEMBRA / PRODUCCIÓN
   Recuento del lote (tarjetas de cifras), caja de movimientos y lista
   de lotes dentro de la ficha del cultivo.
   ===================================================================== */
.lot-control {
    margin-top: 20px;
    border-top: 1px solid var(--vtl-border);
    padding-top: 20px;
}
.lot-control h4 { margin: 18px 0 10px; }
.lot-control h4:first-child { margin-top: 0; }
.lot-counters {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
    gap: 10px;
}
.lot-counter {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    padding: 12px 8px;
    background: var(--vtl-surface-2);
    border: 1px solid var(--vtl-border);
    border-radius: var(--vtl-r-sm);
    text-align: center;
}
.lot-counter-value { font-size: 1.6rem; font-weight: 700; line-height: 1.1; color: var(--vtl-ink); }
.lot-counter-label { font-size: .75rem; color: var(--vtl-ink-3); }
.lot-counter-ok { background: var(--vtl-ok-soft); }
.lot-counter-ok .lot-counter-value { color: var(--vtl-ok); }
.lot-counter-danger { background: var(--vtl-danger-soft); }
.lot-counter-danger .lot-counter-value { color: var(--vtl-danger); }
.lot-counter-muted { background: var(--vtl-neutral-soft); }
.lot-counter-muted .lot-counter-value { color: var(--vtl-neutral); }
.lot-counter-state {
    grid-column: 1 / -1;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px 16px;
    font-size: .85rem;
    color: var(--vtl-ink-2);
}
.lot-movement-box {
    margin-top: 16px;
    padding: 14px;
    background: var(--vtl-surface-2);
    border: 1px solid var(--vtl-border);
    border-radius: var(--vtl-r-sm);
}
.lot-movement-box h4 { margin-top: 0; }
#related-lots-list tr[data-lot-id] { cursor: pointer; }
#related-lots-list tr[data-lot-id]:hover { background: var(--vtl-accent-soft); }

/* =====================================================================
   VTL_F11 · LOTES DE MUESTRAS
   Etiqueta del lote bajo el código de cada muestra del listado.
   ===================================================================== */
.sample-lot-tag {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-top: 3px;
    padding: 1px 7px;
    font-size: .72rem;
    font-weight: 600;
    color: var(--vtl-accent);
    background: var(--vtl-accent-soft);
    border-radius: var(--vtl-r-sm);
    white-space: nowrap;
}
#sampleLotModal .lot-control h4 { margin-top: 0; }

/* =====================================================================
   VTL_F12 · ETIQUETAS ESCALONADAS E IMAGEN DEL LOTE
   ===================================================================== */
.label-canvas-wrap {
    display: flex;
    justify-content: center;
    padding: 14px;
    background: var(--vtl-surface-2);
    border: 1px solid var(--vtl-border);
    border-radius: var(--vtl-r-sm);
}
#label-canvas {
    width: 100%;
    max-width: 320px;
    height: auto;
    aspect-ratio: 4 / 3;
    background: #fff;
    box-shadow: var(--vtl-shadow-sm);
    image-rendering: pixelated;
}
.sample-lot-image-current {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 8px;
}
.sample-lot-image-current img {
    max-width: 120px;
    max-height: 120px;
    border-radius: 8px;
    border: 1px solid var(--vtl-border);
}

/* =====================================================================
   VTL_F13 · AJUSTES COMO PANEL DE KPI
   Tarjetas con dato vivo que abren su contenido en un modal.
   ===================================================================== */
.settings-intro {
    flex-basis: 100%;
    margin: 2px 0 0;
    font-size: .85rem;
    color: var(--vtl-ink-3);
}
.settings-group { margin-bottom: 22px; }
.settings-group-title {
    margin: 0 0 10px;
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--vtl-ink-3);
}
.settings-kpis {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
    gap: 12px;
}
.settings-kpi {
    --kpi-accent: var(--vtl-accent);
    --kpi-soft: var(--vtl-accent-soft);
    display: flex;
    align-items: center;
    gap: 14px;
    width: 100%;
    min-height: 92px;
    padding: 14px 14px 14px 16px;
    text-align: left;
    font: inherit;
    color: var(--vtl-ink);
    background: var(--vtl-surface);
    border: 1px solid var(--vtl-border);
    border-left: 4px solid var(--kpi-accent);
    border-radius: var(--vtl-r);
    box-shadow: var(--vtl-shadow-xs);
    cursor: pointer;
    transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease;
}
.settings-kpi:hover {
    transform: translateY(-2px);
    box-shadow: var(--vtl-shadow-md);
    border-color: var(--vtl-border-strong);
    border-left-color: var(--kpi-accent);
}
.settings-kpi:focus-visible { outline: none; box-shadow: var(--vtl-ring); }
.settings-kpi:active { transform: translateY(0); }
.settings-kpi[data-level="ok"]     { --kpi-accent: var(--vtl-ok);     --kpi-soft: var(--vtl-ok-soft); }
.settings-kpi[data-level="warn"]   { --kpi-accent: var(--vtl-warn);   --kpi-soft: var(--vtl-warn-soft); }
.settings-kpi[data-level="danger"] { --kpi-accent: var(--vtl-danger); --kpi-soft: var(--vtl-danger-soft); }
.settings-kpi[data-level="info"]   { --kpi-accent: var(--vtl-info);   --kpi-soft: var(--vtl-info-soft); }
.settings-kpi-icon {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    font-size: 1.15rem;
    color: var(--kpi-accent);
    background: var(--kpi-soft);
    border-radius: 12px;
}
.settings-kpi-body {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.settings-kpi-title {
    font-size: .78rem;
    font-weight: 600;
    color: var(--vtl-ink-2);
}
.settings-kpi-value {
    font-size: 1.08rem;
    font-weight: 700;
    line-height: 1.25;
    color: var(--vtl-ink);
    overflow-wrap: anywhere;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.settings-kpi[data-level] .settings-kpi-value { color: var(--kpi-accent); }
.settings-kpi-sub {
    font-size: .75rem;
    line-height: 1.35;
    color: var(--vtl-ink-3);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.settings-kpi-go {
    flex: 0 0 auto;
    font-size: .8rem;
    color: var(--vtl-ink-3);
    transition: transform .15s ease, color .15s ease;
}
.settings-kpi:hover .settings-kpi-go { transform: translateX(3px); color: var(--kpi-accent); }

/* Modal: la tarjeta original se muestra sin su marco ni su título (el
   título ya está en la cabecera del modal). */
.settings-panel-content { max-width: 720px; }
.settings-panel-body > .card {
    display: block !important;
    margin: 0;
    padding: 4px 0 0;
    border: 0;
    box-shadow: none;
    background: transparent;
}
.settings-panel-body > .card > h4:first-child { display: none; }
.settings-panel-body .btn-group { flex-wrap: wrap; }

/* Móvil: dos columnas compactas, icono arriba */
@media (max-width: 600px) {
    .settings-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
    .settings-kpi {
        position: relative;
        flex-direction: column;
        align-items: flex-start;
        gap: 8px;
        min-height: 0;
        padding: 12px 12px 12px 13px;
    }
    .settings-kpi-icon { width: 34px; height: 34px; font-size: .95rem; border-radius: 10px; }
    .settings-kpi-value { font-size: .98rem; }
    .settings-kpi-go { position: absolute; top: 14px; right: 12px; }
}

/* =====================================================================
   6.6.0 · BUSCADOR EN LOS DESPLEGABLES DE MUESTRA Y CULTIVO
   ===================================================================== */
.select-search {
    width: 100%;
    margin-bottom: 6px;
    padding: 7px 10px;
    font-size: .85rem;
    border: 1px dashed var(--vtl-border-strong);
    border-radius: var(--vtl-r-sm);
    background: var(--vtl-surface-2);
}
.select-search:focus {
    border-style: solid;
    border-color: var(--vtl-accent);
    background: var(--vtl-surface);
    outline: none;
    box-shadow: var(--vtl-ring);
}

/* =====================================================================
   6.6.5 · SECCIÓN LOTES CON PESTAÑAS (siembra / muestras)
   ---------------------------------------------------------------------
   Reutiliza .modal-tabs / .modal-tab / .modal-tab-panel (sección 22).
   El botón de alta de cada pestaña va dentro de .lots-actions, que no
   ocupa caja propia (display: contents) para no alterar el hueco entre
   botones de .section-actions. applyRoleVisibility() solo toca el
   botón, así que ocultar la envoltura con [hidden] no choca con él.
   ===================================================================== */
.lots-actions { display: contents; }
.lots-actions[hidden] { display: none !important; }

.lots-tabs { margin-bottom: 16px; }

.lots-tab-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 22px;
    height: 20px;
    padding: 0 7px;
    border-radius: 999px;
    background: var(--vtl-neutral-soft);
    color: var(--vtl-ink-2);
    font-size: .72rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    line-height: 1;
}
.lots-tab-count:empty { display: none; }
.modal-tab.active .lots-tab-count {
    background: var(--vtl-accent-soft);
    color: var(--vtl-accent-strong);
}

/* Tabla vacía con explicación y enlace a la otra pestaña */
.lots-empty {
    white-space: normal;          /* las celdas de .data-table no parten línea */
    text-align: left;
    padding: 14px 4px;
    color: var(--vtl-ink-2);
    line-height: 1.55;
}
.lots-empty strong { color: var(--vtl-ink); }
.lots-empty-link {
    display: inline;
    padding: 0;
    border: 0;
    background: none;
    color: var(--vtl-accent);
    font: inherit;
    font-weight: 600;
    text-decoration: underline;
    text-underline-offset: 2px;
    cursor: pointer;
}
.lots-empty-link:hover { color: var(--vtl-accent-strong); }
.lots-empty-link:focus-visible { outline: none; box-shadow: var(--vtl-ring); border-radius: 3px; }

/* Móvil: las dos pestañas a partes iguales y sin icono, para que quepan
   enteras sin desplazamiento lateral. */
@media (max-width: 600px) {
    .lots-tabs .modal-tab {
        flex: 1 1 0;
        justify-content: center;
        gap: 6px;
        padding: 10px 6px;
    }
    .lots-tabs .modal-tab > i { display: none; }
}
