﻿/* =====================================================================
 * NetOffice.Web.Forms — app.css canónico (CLAUDE.md §6.x — fuente única)
 *
 * Este fichero es la BASE compartida por TODOS los hosts Blazor de
 * pantallas (Contabilidad, DatosBase, UsuariosPermisos, Personal y
 * cualquier host nuevo). Se sirve vía `_content/NetOffice.Web.Forms/app.css`
 * y cada host lo carga ANTES de su `wwwroot/app.css` local.
 *
 * Reglas duras:
 *  1. Toda regla que aplique a más de un host vive AQUÍ, NO en el host.
 *  2. El host SÓLO contiene reglas exclusivas de ese host (overrides
 *     puntuales o estilos de pantallas exóticas). Si una pantalla aporta
 *     CSS distintivo, va a su `Pantalla.razor.css` (scoped CSS), no al
 *     host.
 *  3. El orden de `<link>` en App.razor es: Bootstrap → Bootstrap Icons →
 *     RCL → host → scoped (Blazor lo añade automático). El host puede
 *     overridear el RCL; los scoped overridean a host y RCL.
 *  4. Bumpear `?v=` del RCL en TODOS los App.razor de los hosts cuando
 *     se edite este fichero (CLAUDE.md §6.8).
 *
 * Catálogo de bloques principales (orden de aparición):
 *   - Reset html/body (§2.18 sin scrollbar)
 *   - Layout app-shell / app-body / split / form-panel (§2.20 papel)
 *   - app-toolbar (botones, toggles, traducir)
 *   - Grid maestro (sticky header, filtros, range-mode, resize handles)
 *   - Detalle inline (§2.12 + §2.12.1 titled)
 *   - Auto-numeración clave (§2.21)
 *   - ContextoBar (§2.23)
 *   - Form panel papel iluminado (§2.20)
 *   - Logo flotante / responsive ≤1300px (§2.13)
 *   - Lookup / Confirm / ConfigCols modales
 *   - Doc badge (§2.26)
 * =====================================================================
 */

html, body {
    height: 100%;
    margin: 0;
    /* CLAUDE.md §2.18: nunca scrollbar en la página de host. La ficha entra
       en pantalla — si el form-grid se sale, los píxeles se clipan. */
    overflow: hidden;
    font-family: "Segoe UI", system-ui, -apple-system, Arial, sans-serif;
    font-size: 13px;
    background: #f3f3f3;
    color: #222;
}

h1:focus { outline: none; }

.valid.modified:not([type=checkbox]) { outline: 1px solid #26b050; }
.invalid { outline: 1px solid #e50000; }
.validation-message { color: #e50000; font-size: 11px; }

/* ===== Shell ===== */
.app-shell {
    display: flex;
    flex-direction: column;
    height: 100vh;
    overflow: hidden;
    background: #fff;
}

.title-bar {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 4px 10px;
    border-bottom: 1px solid #c7cdd6;
    min-height: 34px;
    font-size: 13px;
    transition: background-color 0.2s ease;
}
.title-logo img {
    height: 24px;
    width: auto;
    display: block;
}
.title-form {
    font-weight: 600;
    color: #222;
}
.title-company {
    color: #333;
    font-style: italic;
}
.title-spacer { flex: 1; }
.title-product {
    font-weight: 700;
    color: #1b3a6c;
    letter-spacing: 0.4px;
    padding-right: 4px;
    font-size: 26px;
    line-height: 1;
}

.app-menubar {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 4px 10px;
    background: #f7f7f7;
    border-bottom: 1px solid #d8d8d8;
    font-size: 13px;
}
.app-menubar .menu-item {
    padding: 2px 8px;
    cursor: pointer;
    border-radius: 2px;
}
.app-menubar .menu-item:hover { background: #e1efff; }

.app-toolbar {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 4px 8px;
    background: linear-gradient(#fafbfc, #eceff2);
    border-bottom: 1px solid #d8d8d8;
}
.app-toolbar .tb-btn {
    width: 28px; height: 28px;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid transparent;
    border-radius: 3px;
    background: transparent;
    color: #2a55a3;
    cursor: pointer;
}
.app-toolbar .tb-btn:hover:not(:disabled) {
    background: #e7f1ff; border-color: #b6d0ea;
}
.app-toolbar .tb-btn.active {
    background: #cfe3ff; border-color: #7ba4d6;
}
.app-toolbar .tb-btn.tb-excel {
    color: #fff;
    background: #1d6f42;
    border-color: #145530;
}
.app-toolbar .tb-btn.tb-excel:hover:not(:disabled) {
    background: #248b52;
    border-color: #1d6f42;
}
.app-toolbar .tb-btn.tb-excel i { color: #fff; font-size: 15px; }
.app-toolbar .tb-btn.tb-help {
    color: #1f4a87;
    font-size: 16px;
}
.app-toolbar .tb-btn.tb-help:hover:not(:disabled) {
    background: #fff7d6;
    border-color: #e0c87a;
}
.app-toolbar .tb-spacer { flex: 1; }
.app-toolbar .tb-translate {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 2px 8px;
    background: #fff7d6;
    border: 1px solid #e0c87a;
    border-radius: 4px;
    color: #8a5b00;
    font-size: 12px;
}
.app-toolbar .tb-translate i.bi-translate {
    font-size: 14px;
    color: #b06900;
}
.app-toolbar .tb-translate-spin {
    font-size: 13px;
    color: #b06900;
    animation: tb-spin 0.9s linear infinite;
}
@keyframes tb-spin {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}
.app-toolbar .tb-lang {
    height: 24px;
    padding: 1px 4px;
    border: 1px solid #d0bb6d;
    border-radius: 3px;
    background: #fff;
    font-size: 12px;
    font-family: inherit;
    color: #1f3147;
    cursor: pointer;
    min-width: 130px;
}
.app-toolbar .tb-lang:hover { border-color: #b06900; }
.app-toolbar .tb-lang:focus {
    outline: none;
    border-color: #b06900;
    box-shadow: 0 0 0 2px rgba(176,105,0,0.18);
}

.translate-bar {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 14px;
    background: #fff7d6;
    border-bottom: 1px solid #e0c87a;
    color: #8a5b00;
    font-size: 12px;
}
.translate-bar i.bi-translate {
    font-size: 14px;
    color: #b06900;
}

.translating-overlay {
    position: fixed;
    inset: 0;
    background: rgba(255, 255, 255, 0.55);
    z-index: 5000;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: wait;
}
.translating-overlay * { cursor: wait; }
.translating-card {
    background: #fff;
    border: 1px solid #e0c87a;
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.20);
    padding: 18px 26px;
    border-radius: 10px;
    display: flex;
    align-items: center;
    gap: 14px;
    font-size: 14px;
    color: #1f3147;
    font-weight: 500;
}
.translating-card .bi-translate {
    font-size: 22px;
    color: #b06900;
}
.translating-card .tb-translate-spin {
    font-size: 18px;
    color: #b06900;
}
.app-toolbar .tb-btn:disabled { color: #b6b6b6; cursor: default; }
.app-toolbar .tb-sep {
    width: 1px; height: 22px; background: #cfcfcf; margin: 0 4px;
}

/* ===== Main content split ===== */
.app-body {
    flex: 1;
    display: grid;
    grid-template-columns: 1fr 1px 1fr;
    min-height: 0;
}
.app-body.grid-full {
    grid-template-columns: 1fr 0 0;
}
.app-body.grid-full .app-split,
.app-body.grid-full .form-panel {
    display: none;
}
.app-body.form-full {
    grid-template-columns: 1fr;
}
.app-body.form-full .app-split,
.app-body.form-full .grid-panel {
    display: none;
}
.app-split {
    background: #d0d0d0;
}

/* ===== Grid panel ===== */
.grid-panel {
    display: flex;
    flex-direction: column;
    min-height: 0;
    min-width: 0;
    background: #fff;
}
.grid-scroll {
    flex: 1;
    overflow: auto;
    outline: none;
}
.grid-scroll:focus-visible {
    box-shadow: inset 0 0 0 1px #3874cb;
}
.grid-table {
    border-collapse: collapse;
    font-size: 12px;
    table-layout: fixed;
    width: 100%;
}
.grid-table thead th {
    background: #e9edf2;
    border: 1px solid #c9ced4;
    padding: 4px 6px;
    text-align: left;
    font-weight: 600;
    position: sticky;
}
.grid-table thead tr.grid-filter-row th {
    top: 0;
    background: #f7f7f7;
    padding: 2px 3px;
    z-index: 12;
    height: 26px;
    box-sizing: border-box;
    /* §2.8 — filtro por columna: alinear arriba para que las columnas en modo
       "contiene" (1 input) no se descuadren respecto a las de "desde/hasta"
       (2 inputs apilados). Sin efecto cuando ninguna columna está en rango. */
    vertical-align: top;
}
.grid-table thead tr:nth-child(2) th {
    top: 26px;
    z-index: 10;
}
.grid-table thead th.sortable {
    cursor: pointer;
    user-select: none;
}
.grid-table thead th.sortable:hover {
    background: #dce3ec;
}

/* ----- Resize de columnas (drag handle en el `<th>`, ver gridHelpers.attachColumnResize) ----- */
.grid-table thead th[data-col-key] {
    position: sticky; /* heredado, lo dejamos explícito por si rebuild reordena reglas */
    /* `<th>` queda como contenedor del handle absoluto; `position` ya viene de la regla global */
}
.col-resize-handle {
    position: absolute;
    top: 0;
    right: 0;
    width: 7px;
    height: 100%;
    cursor: col-resize;
    user-select: none;
    background: transparent;
    z-index: 20;
    /* Línea vertical sutil siempre visible para indicar dónde está el handle.
       El propio borde del `<th>` (1px solid #c9ced4) la tapa parcialmente,
       así que la pintamos al lado interior. */
    border-right: 2px solid rgba(0, 0, 0, 0.08);
    box-sizing: border-box;
}
.col-resize-handle:hover {
    background: rgba(31, 74, 135, 0.18);
    border-right-color: rgba(31, 74, 135, 0.55);
}
.col-resize-handle.dragging {
    background: rgba(31, 74, 135, 0.40);
    border-right-color: rgba(31, 74, 135, 0.85);
}
.sort-ind {
    font-size: 10px;
    color: #1f4a87;
    margin-left: 4px;
}
.grid-table.range-mode thead tr.grid-filter-row th {
    height: 50px;
}
.grid-table.range-mode thead tr:nth-child(2) th {
    top: 50px;
}
/* Reserva el alto de cabeceras sticky para que scrollIntoView no
   tape la fila bajo el thead (26px filtro + 28px columnas = 54px). */
.grid-table tbody tr {
    scroll-margin-top: 54px;
    scroll-margin-bottom: 0;
}
.grid-table.range-mode tbody tr {
    scroll-margin-top: 78px;
}
/* Oculta las flechitas del spinner en inputs numericos. */
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}
input[type="number"] {
    -moz-appearance: textfield;
    appearance: textfield;
}
.grid-filter-inp {
    width: 100%;
    box-sizing: border-box;
    height: 20px;
    padding: 1px 4px;
    border: 1px solid #b5b5b5;
    background: #fff;
    font-size: 12px;
    font-family: inherit;
}
.grid-filter-inp:focus {
    outline: none;
    border-color: #3874cb;
}
.grid-filter-inp.range {
    display: block;
    height: 20px;
    margin-bottom: 2px;
}
.grid-filter-inp.range:last-child {
    margin-bottom: 0;
}
.grid-filter-inp.range::placeholder {
    color: #aab3bd;
    font-size: 10px;
    font-style: italic;
}
.grid-table tbody td {
    border: 1px solid #e4e4e4;
    padding: 3px 6px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.grid-table tbody td.row-indicator {
    padding: 3px 2px;
    text-align: center;
    color: #1f4a87;
    background: #f7f7f7;
}
.grid-table tbody td.cell-center { text-align: center; }
.grid-table tbody tr.selected td.row-indicator {
    background: #f7f7f7;
    color: #1f4a87;
}
.grid-table tbody tr { cursor: pointer; }
.grid-table tbody tr:hover { background: #f1f7ff; }
.grid-table tbody tr.selected {
    background: #3874cb; color: #fff;
}
.grid-table tbody tr.selected td { border-color: #2a5fa8; }
.grid-arrow {
    display: inline-block; width: 10px; color: #1f4a87;
}

.grid-bottom-bar {
    display: flex;
    justify-content: flex-start;
    gap: 16px;
    padding: 8px 12px;
    background: #f7f7f7;
    border-top: 1px solid #d8d8d8;
}
.bbtn {
    display: flex; flex-direction: column; align-items: center;
    min-width: 62px; padding: 4px 8px;
    border: 1px solid transparent; border-radius: 3px;
    background: transparent; cursor: pointer; font-size: 11px;
}
.bbtn:hover { background: #e7f1ff; border-color: #b6d0ea; }
.bbtn i { font-size: 22px; color: #2a55a3; margin-bottom: 2px; }

/* Botón unificado de Delegaciones del registro (§2.40) — mismo look que Doc/Notas
   con un badge que indica en cuántas delegaciones está el registro (0 = global). */
.bbtn-deleg .bbtn-deleg-ico { position: relative; display: inline-flex; margin-bottom: 2px; }
.bbtn-deleg .bbtn-deleg-ico i { margin-bottom: 0; }
.bbtn-deleg.on i { color: #1f7a34; }
.bbtn-deleg .bbtn-deleg-badge {
    position: absolute; top: -6px; right: -10px;
    min-width: 16px; height: 16px; padding: 0 4px;
    border-radius: 9px; background: #9aa4b2; color: #fff;
    font-size: 10px; font-weight: 700; line-height: 16px; text-align: center;
}
.bbtn-deleg.on .bbtn-deleg-badge { background: #1f9d3f; }
.bbtn-deleg:disabled { opacity: .5; cursor: default; }

/* Modal "Delegaciones del registro" (§2.40) — cuerpo del checklist. Contenedor y
   footer heredan del canon lookup-dialog/lookup-header/lookup-footer + btn-circle. */
.deleg-dialog { width: 440px; }
.deleg-dialog-body { max-height: 50vh; overflow: auto; padding: 10px 14px; background: #fff; }
.deleg-dialog-hint {
    display: flex; align-items: center; gap: 7px;
    margin: 0 0 8px; padding: 6px 10px;
    background: #eef4fb; border: 1px solid #d3e2f4; border-radius: 4px;
    font-size: 12px; color: #3c5a80;
}
.deleg-dialog-hint i { color: #2a55a3; }
.deleg-dialog-row {
    display: flex; align-items: center; gap: 10px;
    padding: 6px 8px; border-radius: 4px; cursor: pointer;
    font-size: 13px;
}
.deleg-dialog-row:hover { background: #eef4fb; }
.deleg-dialog-id {
    min-width: 30px; text-align: center;
    background: #f1f3f6; border: 1px solid #d8dde4; border-radius: 3px;
    font-size: 11px; font-weight: 600; color: #4a5568; padding: 1px 4px;
}
.deleg-dialog-nom { flex: 1; }
.deleg-dialog-empty { color: #888; padding: 10px 4px; font-size: 13px; }

/* ===== Gestión documental — patrón canónico (validado 2026-05-09 en
   PlanContable, replicado en Empresas) =================================
   Tres elementos visuales que toda pantalla con DocumentosDialog reusa:
     1. Columna "Doc." al inicio del grid (32px) con badge:
          - has-docs: círculo azul de 18px con paperclip blanco
          - no-docs:  círculo punteado de 8px tenue (placeholder)
     2. Filtro 3-state inline en el thead de esa columna (1/0/vacío).
     3. Botón "Documentos" en la grid-bottom-bar con clase bbtn-docs
        (gradiente azul claro, borde corporativo, paperclip).
   Reglas globales (no scoped) para que se hereden en todas las pantallas
   sin tener que duplicar el .razor.css por cada una. */

.grid-table tbody td.doc-cell {
    text-align: center;
    padding: 0;
    width: 32px;
}
.doc-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    vertical-align: middle;
    transition: transform 0.15s, box-shadow 0.15s;
}
.doc-badge.has-docs {
    background: linear-gradient(180deg, #2f6ec1 0%, #1f4a87 100%);
    color: #fff;
    box-shadow: 0 1px 2px rgba(0,0,0,0.18), inset 0 1px 0 rgba(255,255,255,0.20);
}
.doc-badge.has-docs i { font-size: 10px; }
.grid-table tbody tr:hover .doc-badge.has-docs {
    transform: scale(1.15);
    box-shadow: 0 2px 4px rgba(31,74,135,0.35), inset 0 1px 0 rgba(255,255,255,0.25);
}
.doc-badge.no-docs {
    width: 8px;
    height: 8px;
    background: transparent;
    border: 1px dashed #c5cdd9;
    opacity: 0.5;
}
/* Filtro 3-state en la propia columna Doc — input estrecho centrado. */
.grid-filter-inp.doc-filter-inp {
    width: 28px !important;
    text-align: center;
    font-weight: 600;
    padding: 1px 2px !important;
    font-size: 11px !important;
}
/* Botón Documentos en la grid-bottom-bar y en el ficha-only-topbar. */
.grid-bottom-bar .bbtn-docs,
.ficha-only-topbar .bbtn-docs {
    background: linear-gradient(180deg, #f5fbff 0%, #d8ecff 100%);
    border: 1px solid #7ba4d6;
    color: #1f4a87;
}
.grid-bottom-bar .bbtn-docs:hover:not(:disabled),
.ficha-only-topbar .bbtn-docs:hover:not(:disabled) {
    background: linear-gradient(180deg, #e6f3ff 0%, #c3def5 100%);
    border-color: #1f4a87;
}
.grid-bottom-bar .bbtn-docs:disabled,
.ficha-only-topbar .bbtn-docs:disabled {
    opacity: 0.55;
    cursor: not-allowed;
}
.grid-bottom-bar .bbtn-docs i,
.ficha-only-topbar .bbtn-docs i { margin-right: 4px; color: #1f4a87; }

/* §3.4 — botón Documentos dentro del FormFooter (slot ExtraButtons, junto a
   Eliminar). Auto-contenido (no depende de un .bbtn base). */
.form-footer .bbtn-docs {
    background: linear-gradient(180deg, #f5fbff 0%, #d8ecff 100%);
    border: 1px solid #7ba4d6;
    color: #1f4a87;
    border-radius: 4px;
    padding: 4px 12px;
    cursor: pointer;
    font-size: 12px;
    display: inline-flex;
    align-items: center;
}
.form-footer .bbtn-docs:hover:not(:disabled) {
    background: linear-gradient(180deg, #e6f3ff 0%, #c3def5 100%);
    border-color: #1f4a87;
}
.form-footer .bbtn-docs:disabled { opacity: 0.55; cursor: not-allowed; }
.form-footer .bbtn-docs i { margin-right: 4px; color: #1f4a87; }

/* NOTA §2.26: el "clip" de la ficha se implementa con `.btn-circle .btn-docs`
   (círculo azul, ver arriba junto a .btn-eliminar/.btn-aceptar), NO con una
   clase propia. El botón COMPLETO (clip+texto) sigue en el footer de la tabla
   (.grid-bottom-bar .bbtn-docs). */

/* Botón Notas en la grid-bottom-bar (patrón form_notas — CLAUDE.md §2.29).
   Mismo lenguaje visual que bbtn-docs pero verde para distinguirlos: el
   ojo asocia documentos al paperclip azul y notas al cuaderno verde. */
.grid-bottom-bar .bbtn-notas,
.ficha-only-topbar .bbtn-notas {
    background: linear-gradient(180deg, #f5fff8 0%, #d8f2dc 100%);
    border: 1px solid #7bbc8d;
    color: #1d6f42;
    position: relative;
}
.grid-bottom-bar .bbtn-notas:hover:not(:disabled),
.ficha-only-topbar .bbtn-notas:hover:not(:disabled) {
    background: linear-gradient(180deg, #e7faec 0%, #b8e5c0 100%);
    border-color: #1d6f42;
}
.grid-bottom-bar .bbtn-notas:disabled,
.ficha-only-topbar .bbtn-notas:disabled {
    opacity: 0.55;
    cursor: not-allowed;
}
.grid-bottom-bar .bbtn-notas i,
.ficha-only-topbar .bbtn-notas i { margin-right: 4px; color: #1d6f42; }

/* Badge numérico al lado del label (replica el patrón doc-badge §2.26 pero
   en pill rectangular porque va dentro del botón).
   Diseño: pill blanca con borde verde corporativo y texto verde — máxima
   legibilidad sobre el gradient verde del botón, y se lee de un vistazo
   como "contador". Antes era azul oscuro sobre verde y el cliente no
   identificaba qué significaba el número (2026-05-12). */
.grid-bottom-bar .bbtn-notas .notas-badge,
.ficha-only-topbar .bbtn-notas .notas-badge {
    display: inline-block;
    min-width: 18px;
    padding: 0 6px;
    margin-left: 6px;
    height: 17px;
    line-height: 15px;
    text-align: center;
    background: #ffffff;
    color: #1d6f42;
    border: 1.5px solid #1d6f42;
    border-radius: 9px;
    font-size: 11px;
    font-weight: 700;
    box-shadow: 0 1px 2px rgba(0,0,0,0.10);
    vertical-align: 1px;
}

/* Boton "Texto legal RGPD" en la grid-bottom-bar (CLAUDE.md §1.11).
   Mismo lenguaje visual que bbtn-docs / bbtn-notas pero con paleta ambar/
   institucional para distinguirlo a primera vista — el ojo asocia "aviso
   legal" con tono advertencia formal (escudo + dorado). */
.grid-bottom-bar .bbtn-legal,
.ficha-only-topbar .bbtn-legal {
    background: linear-gradient(180deg, #fffbeb 0%, #fbeec0 100%);
    border: 1px solid #d8a728;
    color: #8a6500;
}
.grid-bottom-bar .bbtn-legal:hover:not(:disabled),
.ficha-only-topbar .bbtn-legal:hover:not(:disabled) {
    background: linear-gradient(180deg, #fff5d6 0%, #f5dc91 100%);
    border-color: #8a6500;
}
.grid-bottom-bar .bbtn-legal:disabled,
.ficha-only-topbar .bbtn-legal:disabled {
    opacity: 0.55;
    cursor: not-allowed;
}
.grid-bottom-bar .bbtn-legal i,
.ficha-only-topbar .bbtn-legal i { margin-right: 4px; color: #8a6500; }

/* ===== Form panel =====
   Tratamiento "papel enmarcado" para que el panel derecho se
   distinga del grid blanco SIN ser un contorno:
     1. Gradiente diagonal blanco-frío → azul-grisáceo tenue.
     2. Radial sutil en la esquina inferior-derecha que añade calidez.
     3. Sombra interior junto al splitter (borde izquierdo) que da
        profundidad — el formulario parece "embutido" detrás del grid.
   Hairline blanca arriba refuerza la sensación de papel iluminado. */
.form-panel {
    display: flex;
    flex-direction: column;
    min-height: 0;
    min-width: 0;
    background:
        radial-gradient(circle at 100% 100%, rgba(95,140,200,0.10) 0%, transparent 55%),
        linear-gradient(135deg, #f6f9fd 0%, #dbe5f1 100%);
    box-shadow:
        inset 14px 0 18px -14px rgba(15,30,55,0.18),
        inset 0 1px 0 rgba(255,255,255,0.7);
    position: relative;
}
/* CLAUDE.md §2.18: el formulario NO debe mostrar barra de desplazamiento.
   Norma del proyecto: la ficha tiene que entrar en pantalla en la carga
   principal. `overflow: hidden` clipa cualquier overflow visual — si una
   pantalla nueva se sale, hay que rediseñarla, no tolerar el scroll. */
.form-scroll { flex: 1; overflow: hidden; padding: 4px 14px; }
/* Placeholder cuando el form-panel no tiene registro seleccionado todavía.
   Sin esta clase, las pantallas basic-master del template (Valoracion-style)
   muestran el texto pegado a la esquina superior izquierda de un panel
   enorme blanco — parece roto. CLAUDE.md feature/migrar-formularios-transporte-jj
   (2026-05-17): añadido junto con la pasada de fix de templates. */
.form-empty {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    color: #6b7785;
    font-style: italic;
    font-size: 0.95rem;
    padding: 32px 24px;
    min-height: 200px;
    user-select: none;
}
.form-empty::before {
    /* Sin icono — antes intenté `\F2BE` pensando que era bi-card-list pero
       en Bootstrap Icons 1.11.3 ese unicode es bi-cloud-sun y salía un
       icono meteorológico ridículo. Para no equivocarme otra vez con
       unicode-hardcoded, dejo solo el texto centrado. Si en algún momento
       se quiere un icono, mejor poner `<i class="bi bi-card-list">` en
       el Razor y dejar este pseudo-elemento sin content. */
    content: "";
    display: none;
}
.form-grid {
    display: grid;
    grid-template-columns:
        minmax(110px, 150px)   /* col 1: label */
        minmax(60px,  90px)    /* col 2: code / short field */
        minmax(180px, 1fr)     /* col 3: medium field */
        minmax(70px,  110px)   /* col 4: secondary label */
        minmax(180px, 1fr)     /* col 5: stretch field */
        minmax(70px,  110px)   /* col 6: tertiary label */
        minmax(120px, 1.2fr);  /* col 7: end field (CIF, etc.) */
    column-gap: 6px;
    row-gap: 4px;
    align-items: center;
    max-width: 1400px;
}
.form-grid label.lbl {
    grid-column: 1;
    color: #333;
    padding-right: 6px;
}
.form-grid .full {
    grid-column: 2 / -1;
}
.form-grid .code-field { grid-column: 2; }
.form-grid .name-field { grid-column: 3 / 8; }
.form-grid .inp.readonlyname {
    grid-column: 3;
}
.form-grid .cif-wrap {
    grid-column: 4 / -1;
    justify-self: end;
    display: flex;
    align-items: center;
    gap: 6px;
}
.form-grid .cif-wrap .cif-lbl {
    grid-column: auto;
    padding-right: 0;
}

/* ===== Grupo de datos en ficha — NORMA del proyecto (2026-06-29) =====
   Toda agrupación de campos relacionados dentro de una ficha se enmarca en un
   `.form-block`: caja ligera (borde gris + fondo sutil) con cabecera
   `.form-block-title` en MAYÚSCULAS azul + subrayado fino. Patrón canónico del
   Plan Contable, promovido al RCL para que valga en TODO el proyecto. El layout
   interno de los campos es libre (form-grid 3-col, o .val-row flex para fichas
   con filas mixtas). Sustituye a la tarjeta de cabecera azul rellena (.val-group). */
.form-block {
    background: linear-gradient(180deg, #ffffff 0%, #f4f7fc 100%);
    border: 1px solid #d4dae3;
    border-top: 3px solid #1f4a87;   /* franja superior azul corp — sello de la tarjeta */
    border-radius: 4px;
    box-shadow: 0 1px 3px rgba(31, 74, 135, 0.06), inset 0 1px 0 rgba(255, 255, 255, 0.6);
    margin-bottom: 8px;
    padding: 6px 14px 10px;
}
.form-block-title {
    color: #1f4a87;
    font-weight: 700;
    font-size: 11px;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    border-bottom: none;             /* la franja superior ya separa; sin subrayado */
    padding: 4px 0 6px;
    margin-bottom: 4px;
}
.form-block-body {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
/* Layout interno COMPACTO del .form-block (3 columnas: etiqueta / código /
   nombre, 1 campo por fila), idéntico al Plan Contable. Sobrescribe el
   .form-grid global (7-col) cuando va dentro de un form-block. NORMA. */
.form-block .form-grid {
    display: grid;
    grid-template-columns: 130px 86px minmax(150px, 1fr);
    column-gap: 6px;
    row-gap: 4px;
    align-items: center;
    max-width: none;
}
.form-block .form-grid > label.lbl {
    grid-column: 1;
    font-weight: 500;
    color: #333;
    font-size: 12px;
    padding-right: 6px;
}
.form-block .form-grid .full { grid-column: 2 / -1; }
.form-block .form-grid .code-field { grid-column: 2; width: 80px; }
.form-block .form-grid .inp.readonlyname {
    grid-column: 3;
    background: #f5f7fa;
    color: #555;
    max-width: 360px;
}
/* Fila de checks o varios mini-inputs que ocupa de la col 2 al final. */
.form-block .form-grid .grid-row-full {
    grid-column: 1 / -1;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px 16px;
}
/* Fila de campo (label + input/es) dentro de un .form-block-body — layout flex
   para fichas con filas mixtas (2 campos por fila, checkboxes, selects…). */
.form-block .val-row,
.form-block-body .val-row {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}
.form-block .val-lbl,
.form-block-body .val-lbl {
    flex: 0 0 150px;
    color: #333;
    font-size: 12.5px;
}
.form-block .val-lbl.val-lbl-2,
.form-block-body .val-lbl.val-lbl-2 {
    flex: 0 0 auto;
    margin-left: 10px;
}
.form-block .val-chk,
.form-block-body .val-chk {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12.5px;
    color: #333;
    white-space: nowrap;
}
@media (max-width: 1660px) {
    .form-block .val-lbl,
    .form-block-body .val-lbl { flex: 0 0 auto; }
}

/* form-grid column-placement helper classes (NIF msg, logo flotante a la
   derecha y bloque de checkboxes ocupando las primeras 4 columnas).
   Teléfono y Fax usan `inp full` (cada uno en su propia fila). */
.form-grid .nif-msg   { grid-column: 4 / -1; text-align: right; }

.bottom-row {
    grid-column: 1 / 5;
    padding-top: 4px;
}
.left-stack {
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-width: 0;
}
.logo-panel.logo-floating {
    grid-column: 5 / -1;
    grid-row: var(--logo-row-start, 12) / span 5;
    align-self: start;
    margin-top: 0;
}

/* Wrapper Logo + checks + color (Empresas).
   - Escritorio (>1660): `display: contents` hace al wrapper invisible para el
     layout; los hijos (logo-panel y bottom-row) se proyectan al form-grid
     con sus grid-column originales. Sin cambios respecto al layout previo.
   - Modal F8 / responsive (<=1660): se vuelve flex row para que Logo y
     checks vayan lado a lado en la misma franja, evitando el scroll.
     La regla concreta vive dentro del @media (max-width:1660px) de mas abajo. */
.side-block { display: contents; }

/* row variations */
.row-codename { display: contents; }
.row-two { display: contents; }

/* ===== Inputs de ficha — estética "papel iluminado".
   Norma del proyecto desde 2026-05-14 (sustituye al subrayado rojo
   "winforms look" heredado del desktop). Se alinea con el tratamiento
   del form-panel §2.20:
   - Reposo: borde lateral muy suave + subrayado gris frío + gradiente
     blanco→azulado tenue + sombra interior 1px que aporta sensación
     de papel sobre papel.
   - Hover (campo editable): subrayado se ilumina a cian #5fa8ff
     (pista de "campo vivo") + fondo blanco más puro.
   - Focus: borde y subrayado pasan a azul corporativo + halo cian
     de 3px (focus ring suave).
   - Variantes:
       .readonlyname / [readonly] → gris frío sin glow,
       .clave-field               → cápsula amarillo PK con subrayado
                                     dorado y focus dorado coherente,
       .code-field                → slab izquierdo F2/F2+F8 §2.28 se
                                     sobrepone sin romper la base,
       .nif-invalid               → ring rojo de validación. ===== */
.inp {
    width: 100%;
    box-sizing: border-box;
    padding: 2px 8px;
    border: 1px solid #e2e8f0;
    border-bottom: 1.5px solid #c5cdd9;
    border-radius: 3px;
    background: linear-gradient(180deg, #ffffff 0%, #f8fafd 100%);
    box-shadow: inset 0 1px 1px rgba(15, 30, 55, 0.03);
    font-size: 12px;
    height: 22px;
    color: #1f2937;
    caret-color: #1f4a87;
    transition: border-color 0.15s, box-shadow 0.15s, background 0.15s;
}
.inp:hover:not([readonly]):not(:focus):not(.readonlyname) {
    border-color: #c8d3e0;
    border-bottom-color: #5fa8ff;
    background: linear-gradient(180deg, #ffffff 0%, #fbfdff 100%);
}
.inp:focus {
    outline: none;
    border-color: #3874cb;
    border-bottom-color: #1f4a87;
    background: #fff;
    box-shadow: 0 0 0 3px rgba(31, 74, 135, 0.16),
                inset 0 1px 1px rgba(31, 74, 135, 0.04);
}
.inp[readonly],
.inp.readonlyname {
    background: #f1f4f8;
    color: #4b5563;
    border-color: #dde4ec;
    border-bottom-color: #cfd6df;
    box-shadow: none;
    cursor: default;
}
.inp.clave-field {
    background: linear-gradient(180deg, #fffbe6 0%, #fff3b5 100%);
    border-color: #e4d68a;
    border-bottom-color: #c9a700;
    color: #5a4400;
    font-weight: 600;
}
.inp.clave-field:focus {
    border-color: #b48b00;
    border-bottom-color: #8c6b00;
    box-shadow: 0 0 0 3px rgba(180, 139, 0, 0.20),
                inset 0 1px 1px rgba(180, 139, 0, 0.06);
    background: linear-gradient(180deg, #fffef5 0%, #fff7c8 100%);
}
/* Campos lookup — slab izquierdo discriminador F2 / F2+F8.
   Norma del proyecto (CLAUDE.md §2.28, trabajo #205199, sesión c1a10656 del 11-may-2026):
   - Azul tenue por defecto: el campo SOLO tiene F2 (buscar).
   - Azul corporativo (.has-f8): el campo tiene F2 + F8 (buscar + mantenimiento).
   El usuario distingue al vuelo qué atajos hay disponibles sin probar.
   Aplica tanto a inputs de ficha (`inp.code-field`) como a celdas de grids
   inline (`detalle-inp.code-field`). */
.inp.code-field,
.detalle-inp.code-field {
    border-left: 3px solid #9ab6d6;   /* azul tenue — F2 solo (buscar) */
    padding-left: 8px;
}
.inp.code-field.has-f8,
.detalle-inp.code-field.has-f8 {
    border-left-color: #1f4a87;        /* azul corp. — F2 + F8 (buscar + mant.) */
}
.inp.code-field:focus,
.detalle-inp.code-field:focus {
    border-left-color: #3874cb;
}
.inp.nif-invalid {
    border-color: #c62828;
    border-bottom-color: #c62828;
    box-shadow: 0 0 0 3px rgba(198, 40, 40, 0.15),
                inset 0 1px 1px rgba(198, 40, 40, 0.04);
}
.nif-msg {
    color: #c62828;
    font-size: 11px;
    margin-top: -2px;
}

.form-row-check-group {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 4px 18px;
    padding: 4px 0;
    grid-column: 1 / -1;
}
.chk {
    display: flex; align-items: center; gap: 6px;
}
.chk input { margin: 0; }

/* logo panel */
.logo-panel {
    border: 1px solid #b5b5b5;
    background: #fff;
    padding: 4px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    /* Panel "Identidad": altura segun contenido (logo compacto + color).
       Sustituye al fijo de 260px — cliente interno 2026-06-06. */
    height: auto;
    overflow: hidden;
}
.logo-toolbar {
    display: flex;
    align-items: center;
    gap: 4px;
    border-bottom: 1px solid #e4e4e4;
    padding-bottom: 4px;
}
.logo-toolbar .tb-btn {
    width: 22px;
    height: 22px;
    font-size: 13px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid transparent;
    border-radius: 3px;
    background: transparent;
    cursor: pointer;
    padding: 0;
    line-height: 1;
}
.logo-toolbar .tb-btn:hover:not(:disabled) {
    background: #e7f1ff;
    border-color: #b6d0ea;
}
.logo-toolbar .tb-btn:disabled { opacity: 0.4; cursor: default; }
.logo-toolbar .tb-btn i { line-height: 1; }
.logo-image {
    /* Logo compacto ~120px (antes flex:1 sobre panel de 260px) — cliente
       interno 2026-06-06. */
    flex: none;
    height: 120px;
    display: flex; align-items: center; justify-content: center;
    background: #fafafa;
    overflow: hidden;
    position: relative;
    border: 1px dashed transparent;
}
.logo-image:hover {
    border-color: #3874cb;
    background: #f2f7ff;
}
.logo-image img { max-width: 100%; max-height: 100%; object-fit: contain; }
.logo-placeholder {
    color: #888; font-style: italic; font-size: 11px; text-align: center;
    pointer-events: none;
}
.logo-file-input {
    position: absolute;
    inset: 0;
    opacity: 0;
    cursor: pointer;
    width: 100%;
    height: 100%;
}
.logo-label {
    font-size: 11px;
    font-weight: 600;
    color: #444;
    margin-right: auto;
    padding-left: 4px;
}

.color-swatch {
    width: 140px; height: 22px;
    border: 1px solid #b5b5b5;
    cursor: pointer;
}

/* Fila de color dentro del panel "Identidad" (logo + color agrupados) —
   cliente interno 2026-06-06. Separador superior fino, etiqueta + muestra
   en linea. La muestra se estira al ancho disponible del panel. */
.logo-color-row {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    border-top: 1px solid #e4e4e4;
    padding-top: 6px;
}
.logo-color-label {
    font-size: 11px;
    font-weight: 600;
    color: #444;
    padding-left: 4px;
}
.logo-color-row .color-swatch {
    flex: 1 1 auto;
    min-width: 60px;
}
.logo-color-row input[type="color"] {
    flex-basis: 100%;
    margin-top: 4px;
}

/* footer buttons */
.form-footer {
    display: flex; align-items: center; gap: 10px;
    padding: 8px 14px;
    background: #e9eff7;
    border-top: 1px solid #c7d2e2;
}
.footer-spacer { flex: 1; }

.audit-bar {
    display: flex; align-items: center; flex-wrap: wrap;
    gap: 18px;
    padding: 4px 14px;
    background: #f3f6fb;
    border-top: 1px solid #d4dde9;
    font-size: 11px;
    color: #4a5566;
}
.audit-bar .audit-item { white-space: nowrap; }
.audit-bar .audit-lbl { color: #6a7686; margin-right: 4px; }
.audit-bar .audit-val { color: #1f3147; font-weight: 600; }
.audit-bar .audit-spacer { flex: 1; }
.audit-bar .audit-val-strong { color: #11243d; font-weight: 700; }

.btn-circle {
    width: 34px; height: 34px;
    border-radius: 50%;
    border: 1px solid rgba(0, 0, 0, 0.25);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-size: 16px;
    line-height: 1;
    padding: 0;
    box-shadow: 0 1px 2px rgba(0,0,0,0.28), inset 0 1px 1px rgba(255,255,255,0.35), inset 0 -2px 4px rgba(0,0,0,0.22);
    transition: filter 0.12s ease, transform 0.08s ease;
}
.btn-circle i { color: #fff; }
.btn-circle:hover:not(:disabled) { filter: brightness(1.08); }
.btn-circle:active:not(:disabled) { transform: translateY(1px); filter: brightness(0.95); }
.btn-circle:disabled { opacity: 0.5; cursor: default; }

.btn-aceptar {
    background: radial-gradient(circle at 35% 30%, #8bd178 0%, #46a13a 55%, #2e7d32 100%);
}
.btn-cancelar,
.btn-eliminar {
    background: radial-gradient(circle at 35% 30%, #ef6b6b 0%, #c62828 55%, #8a1b1b 100%);
}
/* §2.26 — botón Documentos circular AZUL (mismo cuerpo .btn-circle que
   Eliminar/Aceptar, con paperclip): acceso a gestión documental "desde dentro"
   de la ficha. Vive en el footer de la ficha; el botón completo (texto) sigue
   en el footer de la tabla como estaba. */
.btn-docs {
    background: radial-gradient(circle at 35% 30%, #5b9bd5 0%, #2f6ec1 55%, #1f4a87 100%);
}

/* right side composite */
.side-stack {
    display: grid;
    grid-template-columns: 1fr;
    gap: 10px;
    grid-column: 1 / -1;
    grid-template-columns: 1fr 300px;
    align-items: start;
}

.blazor-error-boundary {
    background: #b32121; padding: 1rem; color: #fff;
}

.error-bar {
    background: #fde2e2;
    color: #8a1b1b;
    border-bottom: 1px solid #c62828;
    padding: 6px 12px;
    font-size: 12px;
}

/* ===== Lookup dialog ===== */
.lookup-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.35);
    z-index: 1000;
}
.lookup-dialog {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 680px;
    max-width: 92vw;
    max-height: 80vh;
    background: #fff;
    border: 1px solid #888;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.35);
    display: flex;
    flex-direction: column;
    /* Debe quedar POR ENCIMA del .lookup-backdrop. La sección reportes/
       revisión-punteo redefine .lookup-backdrop a z-index:1100 (y .rp-dialog
       a 1101); por eso este diálogo va a 1102 — si no, el velo taparía
       ayuda/lookup/ficha en todos los hosts. Aprob. crítica #42 (2026-05-27). */
    z-index: 1102;
    font-size: 13px;
    outline: none;
}
/* F2 SIEMPRE por encima de la ventana desde la que se abre (buzón 2026-10-29).
   El lookup se abre por acción del usuario, así que lo correcto es que tape
   cualquier modal de pantalla (que llegan a 1200-1300). Selector triplicado para
   ganar a las redefiniciones locales y scoped (::deep) de .lookup-backdrop.
   Por debajo de GuiaProcesoOverlay (12000). */
.lookup-f2.lookup-f2.lookup-f2.lookup-backdrop { z-index: 11000; }
.lookup-f2.lookup-f2.lookup-f2.lookup-dialog   { z-index: 11001; }
.lookup-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 6px 10px;
    background: linear-gradient(#f5f7fa, #e4e8ee);
    border-bottom: 1px solid #c9ced4;
    font-weight: 600;
}
.lookup-close {
    border: none;
    background: transparent;
    font-size: 22px;
    line-height: 1;
    cursor: pointer;
    color: #555;
    padding: 0 4px;
}
.lookup-close:hover { color: #000; }
.lookup-filter {
    padding: 6px 10px;
    border-bottom: 1px solid #e4e4e4;
    background: #fafafa;
    display: flex;
    align-items: center;
    gap: 8px;
}
.lookup-filter input {
    flex: 1;
    box-sizing: border-box;
    height: 24px;
    padding: 2px 6px;
    border: 1px solid #b5b5b5;
    font-size: 12px;
    font-family: inherit;
}
.lookup-loading {
    font-size: 11px;
    color: #3874cb;
    font-style: italic;
}
.lookup-filter input:focus {
    outline: none;
    border-color: #3874cb;
}
.lookup-body {
    flex: 1;
    overflow: auto;
}
.lookup-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 12px;
}
.lookup-table thead th {
    position: sticky;
    top: 0;
    background: #e9edf2;
    border: 1px solid #c9ced4;
    padding: 4px 6px;
    text-align: left;
    font-weight: 600;
}
.lookup-table tbody td {
    border: 1px solid #e4e4e4;
    padding: 3px 6px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.lookup-table tbody tr { cursor: pointer; }
.lookup-table tbody tr:hover { background: #f1f7ff; }
.lookup-table tbody tr.selected {
    background: #3874cb;
    color: #fff;
}
.lookup-table tbody tr.selected td { border-color: #2a5fa8; }
.lookup-footer {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 10px;
    background: #f7f7f7;
    border-top: 1px solid #d8d8d8;
}
.lookup-footer-spacer { flex: 1; }
.lookup-count {
    font-size: 11px;
    color: #555;
    font-style: italic;
}
.btn-lookup-aceptar,
.btn-lookup-cancelar {
    padding: 4px 18px;
    border: 1px solid #b5b5b5;
    border-radius: 3px;
    background: #fafafa;
    cursor: pointer;
    font-size: 12px;
}
.btn-lookup-aceptar:hover:not(:disabled) { background: #e6f4ea; }
.btn-lookup-cancelar:hover { background: #fde7e7; }
/* Tercera opción del ConfirmDialog (ConfirmarTresAsync, JJ 2026-09-11): la
   alternativa que existe pero no se recomienda, plana y apartada a la
   izquierda del todo — sin el rojo del cancelar ni el verde del aceptar. */
.confirm-footer .confirm-alternativa { color: #5b6b7d; border-color: #c8d2de; background: #f6f8fb; }
.confirm-footer .confirm-alternativa:hover { background: #eef2f7; }
.btn-lookup-aceptar:disabled { opacity: 0.5; cursor: default; }

/* Botón opt-in "Crear nueva" del LookupDialog (param OnCrearNuevo). Va a la
   izquierda del footer; verde para distinguirlo de Aceptar/Cancelar. §3.4. */
.btn-lookup-crear {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 7px 18px;
    border: 1px solid #1d7a45;
    border-radius: 6px;
    background: linear-gradient(180deg, #34b06e 0%, #1f8a4d 100%);
    color: #ffffff;
    font-size: 12.5px;
    font-weight: 700;
    letter-spacing: .2px;
    cursor: pointer;
    box-shadow: 0 2px 5px rgba(31, 138, 77, .28);
    transition: background .12s ease, box-shadow .12s ease, transform .05s ease;
}
.btn-lookup-crear:hover:not(:disabled) {
    background: linear-gradient(180deg, #3cc079 0%, #239a56 100%);
    box-shadow: 0 3px 8px rgba(31, 138, 77, .38);
}
.btn-lookup-crear:active:not(:disabled) { transform: translateY(1px); box-shadow: 0 1px 3px rgba(31, 138, 77, .3); }
.btn-lookup-crear i { font-size: 15px; }

.confirm-body {
    padding: 16px 18px;
    font-size: 13px;
    color: #222;
    white-space: pre-line;
    line-height: 1.5;
    min-height: 60px;
}

/* ===== ConfirmDialog — modal canónico de confirmación / aviso ===== */
/* Sustituye a los confirm()/alert() nativos del navegador. Reutiliza
   .lookup-* (backdrop/dialog/header/body/footer) + estos específicos. */
.confirm-dialog {
    width: 460px;
    /* hereda max-height:80vh de .lookup-dialog; el .confirm-body (lookup-body)
       scrollea si el mensaje es largo (p.ej. respuesta IA del soporte). */
    /* Un confirm SIEMPRE queda por encima del modal que lo lanza. Con el
       z-index heredado de .lookup-dialog (1001) nacía DETRÁS del modal de
       gesdoc (1400) y de su visor (1600-1602): el usuario daba a borrar y
       la confirmación quedaba invisible (caso real JJ 2026-08-20, borrar
       desde Gestión documental de un pedido TMS). */
    z-index: 3001;
}
.confirm-backdrop {
    z-index: 3000;
}
.confirm-icon {
    margin-right: 6px;
    color: #2a5fa8;
}
.confirm-icon.peligro {
    color: #c0392b;
}
.confirm-mensaje {
    margin: 0;
}
/* Botón de acción destructiva (borrado irreversible) — rojo corporativo. */
.btn-confirm-peligro {
    padding: 4px 18px;
    border: 1px solid #a5281c;
    border-radius: 3px;
    background: #c0392b;
    color: #fff;
    cursor: pointer;
    font-size: 12px;
    display: inline-flex;
    align-items: center;
}
.btn-confirm-peligro:hover { background: #a5281c; }
.btn-confirm-peligro:active { background: #8f2118; }

.config-cols-body {
    padding: 10px 14px;
    max-height: 50vh;
    overflow: auto;
}
.config-col-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 0;
    border-bottom: 1px solid #f0f0f0;
    font-size: 12px;
}
.config-col-row:last-child { border-bottom: none; }
.config-col-row input[type=checkbox] { margin: 0; }
.config-col-name { flex: 1; }
.config-col-btn {
    width: 26px; height: 24px;
    border: 1px solid #b5b5b5;
    background: #fafafa;
    border-radius: 3px;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    font-size: 11px;
}
.config-col-btn:hover:not(:disabled) { background: #e7f1ff; border-color: #7ba4d6; }
.config-col-btn:disabled { opacity: 0.4; cursor: default; }

/* Hint informativo dentro del modal de configuración de columnas: explica que
   los anchos se persisten en el mismo instante del drag (no necesitan Guardar). */
.config-cols-hint {
    margin-top: 10px;
    padding: 6px 8px;
    background: #f0f6ff;
    border: 1px solid #c9d8ee;
    border-radius: 4px;
    font-size: 12px;
    color: #1f4a87;
    display: flex;
    align-items: center;
    gap: 6px;
}
.config-cols-hint .bi { font-size: 14px; }
/* Botones del footer disabled (ej. "Restaurar anchos" cuando el grid está en modo %) */
.lookup-footer .btn-lookup-cancelar:disabled,
.lookup-footer .btn-lookup-aceptar:disabled {
    opacity: 0.45;
    cursor: not-allowed;
}

/* ===== Footer botones modal config-cols ===== */
/*
   Versión con icono + texto, nowrap y tipografía proporcional. Sustituye a
   los .btn-lookup-cancelar/.btn-lookup-aceptar cuando el modal lleva 4 botones
   (Restaurar todo / Restaurar anchos / Cancelar / Guardar) — con texto largo
   los antiguos botones rompían línea ("Restaurar anchos" en 2 filas).
*/
.config-cols-footer {
    gap: 6px;
    flex-wrap: nowrap;
}
.btn-cfg {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 12px;
    border-radius: 4px;
    border: 1px solid transparent;
    font-size: 12px;
    font-family: inherit;
    line-height: 1.2;
    cursor: pointer;
    white-space: nowrap;
    transition: background-color 0.12s ease, border-color 0.12s ease;
}
.btn-cfg .bi {
    font-size: 13px;
    line-height: 1;
}
.btn-cfg:disabled {
    opacity: 0.45;
    cursor: not-allowed;
}

/* Secundario (los dos "Restaurar"): outline azul claro, fondo blanco. */
.btn-cfg-secondary {
    background: #fff;
    border-color: #c0d2e8;
    color: #1f4a87;
}
.btn-cfg-secondary:hover:not(:disabled) {
    background: #eaf2fb;
    border-color: #7ba4d6;
}

/* Cancelar: gris discreto. */
.btn-cfg-cancel {
    background: #f3f3f3;
    border-color: #ccc;
    color: #444;
}
.btn-cfg-cancel:hover:not(:disabled) {
    background: #e8e8e8;
    border-color: #aaa;
}

/* Primario (Guardar): azul lleno — la acción que el usuario espera por defecto. */
.btn-cfg-primary {
    background: #2a55a3;
    border-color: #1f3f7a;
    color: #fff;
    font-weight: 500;
}
.btn-cfg-primary:hover:not(:disabled) {
    background: #1f3f7a;
    border-color: #173061;
}
.btn-cfg-primary .bi { color: #fff; }

/* ===== Documentos dialog ===== */
.docs-dialog {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 96vw;
    height: 92vh;
    max-width: 1600px;
    max-height: 1100px;
    background: #fff;
    border: 1px solid #888;
    box-shadow: 0 8px 32px rgba(0,0,0,0.35);
    display: flex;
    flex-direction: column;
    z-index: 1001;
    font-size: 13px;
    outline: none;
}
.docs-body {
    flex: 1;
    display: grid;
    grid-template-columns: 1fr 1.6fr;
    gap: 1px;
    background: #d0d0d0;
    min-height: 0;
}
.docs-list {
    overflow: auto;
    background: #fff;
}
.docs-preview {
    display: flex;
    flex-direction: column;
    background: #fafafa;
    min-height: 0;
}
.docs-preview-empty {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #888;
    font-style: italic;
    font-size: 12px;
}
.docs-preview-header {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 10px;
    border-bottom: 1px solid #e0e0e0;
    background: #f5f7fa;
    font-size: 12px;
}
.docs-preview-name {
    flex: 1;
    font-weight: 600;
    color: #222;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.docs-preview-btn {
    width: 26px;
    height: 24px;
    border: 1px solid #b5b5b5;
    border-radius: 3px;
    background: #fafafa;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: #2a55a3;
    text-decoration: none;
}
.docs-preview-btn:hover { background: #e7f1ff; border-color: #7ba4d6; }
.docs-preview-content {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 8px;
    overflow: auto;
    background: #fff;
    min-height: 0;
}
.docs-preview-content img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
}
.docs-preview-content iframe {
    width: 100%;
    height: 100%;
    border: none;
}
.docs-preview-unknown {
    text-align: center;
    color: #888;
    font-size: 12px;
}
.docs-preview-unknown i {
    font-size: 48px;
    color: #bbb;
    display: block;
    margin-bottom: 8px;
}
.docs-preview-hint {
    margin-top: 4px;
    font-size: 11px;
    color: #aaa;
}
.docs-preview-meta {
    padding: 6px 10px;
    border-top: 1px solid #e4e4e4;
    font-size: 11px;
    color: #444;
    background: #f7f7f7;
    max-height: 120px;
    overflow: auto;
}
.docs-preview-meta > div { margin-bottom: 3px; }
.docs-preview-ruta {
    color: #888;
    font-family: Consolas, monospace;
    font-size: 10px;
    word-break: break-all;
}

/* ===== Detalle (grid de empresas dentro de la ficha) ===== */
.detalle-section {
    display: flex;
    flex-direction: column;
    border: 1px solid #b5b5b5;
    background: #fff;
    height: 260px;
    min-height: 0;
}
.detalle-toolbar {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 4px 6px;
    background: linear-gradient(#fafbfc, #eceff2);
    border-bottom: 1px solid #d8d8d8;
}
.detalle-toolbar .det-title {
    font-weight: 600;
    color: #333;
    margin-right: auto;
    padding-left: 4px;
}
.detalle-toolbar .tb-btn {
    width: 26px; height: 24px;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid transparent;
    border-radius: 3px;
    background: transparent;
    color: #2a55a3;
    cursor: pointer;
    padding: 0;
}
.detalle-toolbar .tb-btn:hover:not(:disabled) {
    background: #e7f1ff; border-color: #b6d0ea;
}
.detalle-toolbar .tb-btn:disabled { opacity: 0.4; cursor: default; }
.detalle-toolbar .tb-btn.tb-excel {
    color: #fff;
    background: #1d6f42;
    border-color: #145530;
}
.detalle-toolbar .tb-btn.tb-excel:hover:not(:disabled) {
    background: #248b52;
    border-color: #1d6f42;
}
.detalle-toolbar .tb-btn.tb-excel:disabled {
    background: #1d6f42;
    border-color: #145530;
}
.detalle-toolbar .tb-btn.tb-excel i { color: #fff; font-size: 14px; }
.detalle-toolbar .tb-btn.active {
    background: #cfe3ff;
    border-color: #7ba4d6;
}
.detalle-toolbar .tb-sep {
    display: inline-block;
    width: 1px;
    height: 18px;
    background: #c9ced4;
    margin: 0 4px;
    vertical-align: middle;
}
.detalle-body {
    flex: 1;
    overflow: auto;
    background: #fff;
    min-height: 180px;
}
.detalle-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 12px;
    table-layout: fixed;
}
.detalle-table thead th {
    position: sticky;
    top: 0;
    background: #e9edf2;
    border: 1px solid #c9ced4;
    padding: 4px 6px;
    text-align: left;
    font-weight: 600;
    z-index: 1;
}
.detalle-table tbody td {
    border: 1px solid #e4e4e4;
    padding: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.detalle-table tbody td.det-cell-text {
    padding: 3px 6px;
    background: #f4f4f4;
    color: #333;
}
.detalle-table tbody tr.selected td.det-cell-text {
    background: #d6e6fb;
}
.detalle-table tbody tr:hover td.det-cell-text {
    background: #e8eef6;
}
.detalle-table tbody tr.selected:hover td.det-cell-text {
    background: #d6e6fb;
}
.detalle-table tbody tr.selected { background: #d6e6fb; }
.detalle-table tbody tr:hover { background: #f1f7ff; }
.detalle-table tbody tr.selected:hover { background: #d6e6fb; }
.detalle-table tbody tr.row-empty td { color: #aaa; font-style: italic; }
/* Modo rango (filtros desde/hasta apilados) en grid de detalle.
   Alinea con el patrón del grid maestro (.grid-table.range-mode). */
.detalle-table.range-mode thead tr.grid-filter-row th {
    height: 50px;
    vertical-align: top;
    padding-top: 4px;
}
.detalle-table tbody tr {
    scroll-margin-top: 28px;
}
.detalle-table.range-mode tbody tr {
    scroll-margin-top: 78px;
}
.detalle-inp {
    width: 100%;
    box-sizing: border-box;
    border: none;
    background: transparent;
    padding: 3px 6px;
    font-size: 12px;
    font-family: inherit;
    outline: none;
    height: 22px;
}
.detalle-inp:focus {
    background: #fff8d0;
    box-shadow: inset 0 0 0 1px #3874cb;
}
.detalle-row-indicator {
    width: 22px;
    text-align: center;
    background: #f7f7f7;
    color: #1f4a87;
    padding: 3px 2px;
}

/* ===== Multiselección de filas del detalle (CLAUDE.md §2.12.1) =====
   Celda corner del thead con checkbox "select-all" + celda por fila con
   checkbox de marcado (multiselección para borrar en bulk). El click en
   el corner toggle la selección de TODAS las filas filtradas. */
.detalle-table thead th.det-select-corner {
    width: 26px;
    text-align: center;
    cursor: pointer;
    padding: 2px 0;
    background: #e9edf2;
}
.detalle-table thead th.det-select-corner:hover { background: #dde6f1; }
.detalle-table thead th.det-select-corner input[type="checkbox"] {
    cursor: pointer; margin: 0; vertical-align: middle;
}
.detalle-table tbody td.det-select-cell {
    width: 26px;
    text-align: center;
    background: #f7f7f7;
    padding: 3px 2px;
}
.detalle-table tbody td.det-select-cell input[type="checkbox"] {
    cursor: pointer; margin: 0; vertical-align: middle;
}
/* Fila marcada con checkbox: tono ligeramente teñido para distinguirla
   visualmente de la fila simplemente "seleccionada con foco" (▶). */
.detalle-table tbody tr.checked td.det-select-cell { background: #e3eef9; }
.detalle-table tbody tr.checked td.detalle-row-indicator { background: #e3eef9; }
.detalle-table tbody tr.checked td:not(.det-select-cell):not(.detalle-row-indicator) {
    background: #f4f8fd;
}
.detalle-table tbody tr.selected.checked td:not(.det-select-cell):not(.detalle-row-indicator) {
    background: #cfe0f3;
}

/* ===== Variante "titled": cabecera slate oscura con título en mayúsculas =====
   CLAUDE.md §2.12.1 — patrón canónico para grids de entrada con título
   asociado. Mismo gradiente y acento cian que `.grid-pais-header` para
   coherencia visual. Aplicar añadiendo `detalle-toolbar-titled` al
   `<div class="detalle-toolbar">`. */
.detalle-toolbar.detalle-toolbar-titled {
    background: linear-gradient(180deg, #27548f 0%, #173a6b 100%);
    border-left: 3px solid #5fa8ff;
    border-bottom: 1px solid #1a242e;
    color: #ffffff;
    box-shadow: 0 1px 0 rgba(0, 0, 0, 0.12), inset 0 1px 0 rgba(255, 255, 255, 0.10);
    user-select: none;
    padding: 4px 10px 4px 8px;
    gap: 6px;
}
.detalle-toolbar.detalle-toolbar-titled .det-title {
    font-weight: 700;
    font-size: 12px;
    color: #ffffff;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    text-shadow: 0 1px 1px rgba(0, 0, 0, 0.22);
    padding-left: 0;
}
.detalle-toolbar.detalle-toolbar-titled .det-title > i {
    color: #aac6e8;
    font-size: 13px;
    margin-right: 6px;
}
/* Botones blancos sobre la banda slate. Cada botón es una cápsula de
   "papel" claro con su icono en color de marca (azul = consulta,
   verde = export, gris = config, rojo = destructivo). */
.detalle-toolbar.detalle-toolbar-titled .tb-btn {
    width: 30px;
    height: 26px;
    background: linear-gradient(180deg, #ffffff 0%, #eef3f9 100%);
    border: 1px solid #b9c6d6;
    border-radius: 5px;
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.9),
        0 1px 2px rgba(0, 0, 0, 0.30),
        0 0 0 1px rgba(0, 0, 0, 0.08);
    transition: transform 0.08s ease, box-shadow 0.12s ease, background 0.12s ease;
}
.detalle-toolbar.detalle-toolbar-titled .tb-btn i {
    font-size: 14px;
    color: #1f4a87;
    line-height: 1;
}
.detalle-toolbar.detalle-toolbar-titled .tb-btn:hover:not(:disabled) {
    background: linear-gradient(180deg, #f5f9ff 0%, #dbe7f6 100%);
    border-color: #6e93c0;
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.9),
        0 2px 4px rgba(0, 0, 0, 0.35),
        0 0 0 1px rgba(31, 74, 135, 0.20);
}
.detalle-toolbar.detalle-toolbar-titled .tb-btn:active:not(:disabled) {
    transform: translateY(1px);
    box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.18), 0 0 0 1px rgba(0, 0, 0, 0.15);
}
.detalle-toolbar.detalle-toolbar-titled .tb-btn:disabled {
    background: linear-gradient(180deg, #f3f5f8 0%, #e1e6ed 100%);
    border-color: #c7cdd6;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.6), 0 1px 1px rgba(0, 0, 0, 0.15);
    cursor: default;
}
.detalle-toolbar.detalle-toolbar-titled .tb-btn:disabled i { color: #a4adb8; }

.detalle-toolbar.detalle-toolbar-titled .tb-btn.active {
    background: linear-gradient(180deg, #2f6ec1 0%, #1f4a87 100%);
    border-color: #173b6e;
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.30),
        0 0 0 2px rgba(95, 168, 255, 0.55),
        0 1px 2px rgba(0, 0, 0, 0.35);
}
.detalle-toolbar.detalle-toolbar-titled .tb-btn.active i { color: #ffffff; }

.detalle-toolbar.detalle-toolbar-titled .tb-btn.tb-excel,
.detalle-toolbar.detalle-toolbar-titled .tb-btn.tb-excel:disabled {
    background: linear-gradient(180deg, #29a663 0%, #1a6b3d 100%);
    border-color: #145530;
}
.detalle-toolbar.detalle-toolbar-titled .tb-btn.tb-excel:hover:not(:disabled) {
    background: linear-gradient(180deg, #34bd72 0%, #207a48 100%);
    border-color: #1d6f42;
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.25),
        0 2px 4px rgba(0, 0, 0, 0.35),
        0 0 0 1px rgba(29, 111, 66, 0.40);
}
.detalle-toolbar.detalle-toolbar-titled .tb-btn.tb-excel i {
    color: #ffffff !important;
    text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25);
}
.detalle-toolbar.detalle-toolbar-titled .tb-btn.tb-excel:disabled { opacity: 0.55; }

.detalle-toolbar.detalle-toolbar-titled .tb-btn:has(i[style*="#c62828"]) {
    background: linear-gradient(180deg, #d94f4f 0%, #a31f1f 100%);
    border-color: #7c1414;
}
.detalle-toolbar.detalle-toolbar-titled .tb-btn:has(i[style*="#c62828"]) i {
    color: #ffffff !important;
    text-shadow: 0 1px 1px rgba(0, 0, 0, 0.30);
}
.detalle-toolbar.detalle-toolbar-titled .tb-btn:has(i[style*="#c62828"]):hover:not(:disabled) {
    background: linear-gradient(180deg, #e36767 0%, #b82424 100%);
    border-color: #8e1818;
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.25),
        0 2px 4px rgba(0, 0, 0, 0.35),
        0 0 0 1px rgba(180, 30, 30, 0.40);
}
.detalle-toolbar.detalle-toolbar-titled .tb-btn:has(i[style*="#c62828"]):disabled { opacity: 0.45; }

.detalle-toolbar.detalle-toolbar-titled .tb-btn:has(i.bi-plus-lg),
.detalle-toolbar.detalle-toolbar-titled .tb-btn:has(i.bi-plus-square) {
    background: linear-gradient(180deg, #ffffff 0%, #eaf6ee 100%);
    border-color: #8fc7a4;
}
.detalle-toolbar.detalle-toolbar-titled .tb-btn:has(i.bi-plus-lg) i,
.detalle-toolbar.detalle-toolbar-titled .tb-btn:has(i.bi-plus-square) i {
    color: #1d6f42;
    font-weight: 700;
}
.detalle-toolbar.detalle-toolbar-titled .tb-btn:has(i.bi-plus-lg):hover:not(:disabled),
.detalle-toolbar.detalle-toolbar-titled .tb-btn:has(i.bi-plus-square):hover:not(:disabled) {
    background: linear-gradient(180deg, #f3fbf6 0%, #cae8d4 100%);
    border-color: #4a9b69;
}

.detalle-toolbar.detalle-toolbar-titled .tb-btn:has(i.bi-gear-fill) i,
.detalle-toolbar.detalle-toolbar-titled .tb-btn:has(i.bi-gear) i {
    color: #4a5566;
}

.detalle-toolbar.detalle-toolbar-titled .tb-sep {
    background: rgba(255, 255, 255, 0.30);
    height: 18px;
    margin: 0 6px;
    width: 1px;
    align-self: center;
}

/* ===== Ficha modal (iframe) ===== */
.lookup-dialog.ficha-modal {
    width: 920px;
    max-width: 96vw;
    height: 92vh;
    max-height: 92vh;
    padding: 0;
}
.ficha-modal-body {
    flex: 1;
    min-height: 0;
    background: #e9eff7;
    overflow: hidden;
}
.ficha-modal-body iframe {
    width: 100%;
    height: 100%;
    border: 0;
    display: block;
}


/* ===== Ayuda ===== */
.lookup-dialog.ayuda-dialog {
    width: 720px;
    max-width: 94vw;
    max-height: 86vh;
    display: flex;
    flex-direction: column;
}
.ayuda-body {
    flex: 1;
    overflow: auto;
    padding: 14px 18px;
    font-size: 13px;
    color: #2a3140;
    line-height: 1.45;
}
.ayuda-body h4 {
    font-size: 13px;
    font-weight: 700;
    color: #1f4a87;
    margin: 14px 0 4px;
    padding-bottom: 3px;
    border-bottom: 1px solid #d8e0ec;
}
.ayuda-body h4:first-child { margin-top: 0; }
.ayuda-body p { margin: 4px 0; }
.ayuda-body ul { margin: 4px 0 8px 20px; padding: 0; }
.ayuda-body li { margin: 2px 0; }
.ayuda-body b { color: #1f3147; }

.grid-bottom-bar .grid-spacer { flex: 1; }
.grid-bottom-bar .grid-counter {
    font-size: 11px;
    color: #4a5566;
    padding: 0 8px;
    align-self: center;
}
.grid-bottom-bar .grid-counter-hint {
    color: #b06900;
    font-style: italic;
    margin-left: 6px;
}

/* ===== Modo ficha-only (cuando se abre por F8 desde otro proyecto) =====
   El `!important` es DELIBERADO y es lo que hace que el F8 salga bien SIEMPRE.
   Motivo (JJ 2026-07-31, medido en pantalla): cada pantalla que ajusta el ancho
   de su divisor escribe en su CSS scoped una regla del tipo

       [b-xxxxxxxx] .app-body:not(.grid-full):not(.form-full) { ...: 1fr 1px 3fr }

   que excluye los modos "sólo grid" y "sólo ficha ampliada" pero SE OLVIDA de
   excluir ficha-only — y al llevar atributo scoped gana en especificidad a
   `.app-body.ficha-only`. Resultado: en modo F8, donde el grid NI SIQUIERA se
   renderiza, la ficha caía en la primera columna del reparto (320 px de 1280) y
   salía cortada. De ocho pantallas con divisor propio, sólo una recordaba el
   `:not(.ficha-only)`, así que el F8 salía bien o mal según la pantalla.
   ficha-only es un MODO, no una preferencia de anchura: tiene que ganar a
   cualquier reparto de columnas que la pantalla haya definido. */
.app-body.ficha-only {
    grid-template-columns: 1fr !important;
}
/* Y el panel ocupa toda la fila aunque alguien añada columnas implícitas. */
.app-body.ficha-only > .form-panel {
    grid-column: 1 / -1;
}
.app-shell--ficha-only {
    height: 100vh;
    outline: none;
}
.ficha-only-topbar {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 4px 10px;
    background: linear-gradient(#fafbfc, #eceff2);
    border-bottom: 1px solid #d8d8d8;
}
.ficha-only-topbar .tb-btn {
    width: 28px; height: 28px;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid transparent;
    border-radius: 3px;
    background: transparent;
    color: #2a55a3;
    cursor: pointer;
}
.ficha-only-topbar .tb-btn:hover:not(:disabled) {
    background: #e7f1ff; border-color: #b6d0ea;
}
.ficha-only-topbar .tb-btn:disabled { color: #b6b6b6; cursor: default; }
.ficha-only-topbar .tb-btn.tb-help {
    color: #1f4a87;
    font-size: 16px;
}
.ficha-only-topbar .tb-btn.tb-help:hover:not(:disabled) {
    background: #fff7d6;
    border-color: #e0c87a;
}
.ficha-only-topbar .tb-sep {
    width: 1px; height: 22px; background: #cfcfcf; margin: 0 4px;
}
.ficha-only-topbar .tb-spacer { flex: 1; }
.ficha-only-topbar .tb-translate {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 2px 8px;
    background: #fff7d6;
    border: 1px solid #e0c87a;
    border-radius: 4px;
    color: #8a5b00;
    font-size: 12px;
}
.ficha-only-topbar .tb-translate i.bi-translate {
    font-size: 14px;
    color: #b06900;
}
.ficha-only-topbar .tb-translate-spin {
    font-size: 13px;
    color: #b06900;
    animation: tb-spin 0.9s linear infinite;
}
.ficha-only-topbar .tb-lang {
    height: 24px;
    padding: 1px 4px;
    border: 1px solid #d0bb6d;
    border-radius: 3px;
    background: #fff;
    font-size: 12px;
    font-family: inherit;
    color: #1f3147;
    cursor: pointer;
    min-width: 130px;
}
.ficha-only-topbar .bbtn {
    flex-direction: row;
    min-width: 0;
    padding: 2px 8px;
    height: 28px;
    gap: 4px;
}
.ficha-only-topbar .bbtn i {
    font-size: 14px;
    margin-bottom: 0;
}

/* tb-help y tb-spacer en la toolbar superior también */
.app-toolbar .tb-btn.tb-help {
    color: #1f4a87;
    font-size: 16px;
}
.app-toolbar .tb-btn.tb-help:hover:not(:disabled) {
    background: #fff7d6;
    border-color: #e0c87a;
}
.app-toolbar .tb-spacer { flex: 1; }

/* Diálogo de ayuda */
.lookup-dialog.ayuda-dialog {
    width: 600px;
    max-width: 92vw;
    max-height: 80vh;
    display: flex;
    flex-direction: column;
}
.ayuda-body {
    flex: 1;
    overflow: auto;
    padding: 14px 18px;
    font-size: 13px;
    color: #2a3140;
    line-height: 1.45;
}
.ayuda-body h4 {
    font-size: 13px;
    font-weight: 700;
    color: #1f4a87;
    margin: 14px 0 4px;
    padding-bottom: 3px;
    border-bottom: 1px solid #d8e0ec;
}
.ayuda-body h4:first-child { margin-top: 0; }
.ayuda-body p, .ayuda-body ul { margin: 4px 0; }
.ayuda-body ul { padding-left: 20px; }

/* ===== Responsive: viewport-narrow body split + form-grid collapse =====
   Norma del proyecto NetOffice (ver CLAUDE.md §2.13).
   Aplica a viewport <= 1660px en split, form-full y ficha-only.
   Breakpoint subido de 1300 a 1660 (2026-05-15, auditoría T4 Empresas):
   el form-grid de pantallas anchas como Empresas necesita ~826px y con
   split 50/50 el form-panel solo tiene la mitad del viewport, así que a
   1366/1440/1500/1600 (portátiles 14-15") el CIF/NIF quedaba fuera de
   pantalla. A 1660px el contenido del layout normal de 7 columnas ya
   entra; por debajo se aplica el layout colapsado de 3 columnas.
   - Body: el form se queda en 380px y el grid pilla el resto del ancho.
   - Form-grid: pasa de N columnas a 3 (label + code + input), capped en 760px
     para que en form-full no se estire por todo el viewport. */
@media (max-width: 1660px) {
    .app-body:not(.grid-full):not(.form-full):not(.ficha-only) {
        grid-template-columns: minmax(380px, 0.8fr) 1px 1.4fr;
    }
    .form-grid {
        grid-template-columns:
            minmax(100px, 130px)
            minmax(60px, 90px)
            minmax(0, 1fr);
        max-width: 760px;
    }
    .form-grid .name-field       { grid-column: 3 / -1; }
    .form-grid .full             { grid-column: 2 / -1; }
    .form-grid .inp.readonlyname { grid-column: 3 / -1; }
    .form-grid .cif-wrap {
        grid-column: 1 / -1;
        justify-self: stretch;
        display: grid;
        grid-template-columns: minmax(100px, 130px) 1fr;
        gap: 0 6px;
        align-items: center;
    }
    .form-grid .cif-wrap .cif-lbl { padding-right: 6px; text-align: left; }
    .form-grid .cif-wrap .inp     { width: auto !important; max-width: 220px; }
    .form-grid .nif-msg   { grid-column: 1 / -1; text-align: left; }

    /* Regla legacy (sin wrapper): apila Logo y bottom-row a toda la anchura.
       Aplica cuando NO hay .side-block envolviendolos. */
    .logo-panel.logo-floating {
        grid-column: 1 / -1;
        grid-row: auto;
        height: auto;
        margin-top: 10px;
    }
    .bottom-row { grid-column: 1 / -1; }

    /* En modal F8 / viewport estrecho con .side-block: Logo y checkboxes/Color
       comparten franja en lugar de apilarse. El wrapper se vuelve flex y ocupa
       toda la anchura del form-grid. Las reglas mas especificas ganan a las
       legacy de arriba.
       Orden visual: checks/Color a la IZQUIERDA, Logo a la DERECHA, igual que
       el escritorio. Lo conseguimos con `row-reverse` para no alterar el DOM
       ni el orden de tab. */
    .side-block {
        display: flex;
        flex-direction: row-reverse;
        gap: 16px;
        align-items: flex-start;
        grid-column: 1 / -1;
        margin-top: 10px;
    }
    .side-block .logo-panel.logo-floating {
        grid-column: auto;
        grid-row: auto;
        width: 200px;
        height: auto;
        flex-shrink: 0;
        margin-top: 0;
    }
    .side-block .bottom-row {
        grid-column: auto;
        flex: 1 1 auto;
        min-width: 0;
        padding-top: 0;
        margin-top: 0;
    }
    /* Compactar el bloque de checkboxes para que la altura del side-block no
       fuerce scroll en el modal F8: gap menor, sin padding vertical. */
    .side-block .form-row-check-group {
        padding: 0;
        gap: 4px 18px;
    }
    .side-block .left-stack {
        gap: 8px;
    }
}

/* ===== Auto-numeración de clave (CLAUDE.md §2.21, refinado 2026-05-07) =====
   Los 2 botones (siguiente / primer hueco) viven DENTRO del wrap, que pasa a
   ser el "campo aparente" — un único bloque con borde, fondo amarillo de
   clave y los iconos integrados a la derecha como adornos sufijo. */
/* Cápsula clave-num-wrap §2.21 — armonizada con la estética "papel
   iluminado" de los .inp.clave-field (CLAUDE.md §2.NN): mismo gradient
   amarillo PK, mismo subrayado dorado, mismo focus dorado con halo. */
.clave-num-wrap {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: stretch;
    height: 22px;
    border: 1px solid #e4d68a;
    border-bottom: 1.5px solid #c9a700;
    border-radius: 3px;
    background: linear-gradient(180deg, #fffbe6 0%, #fff3b5 100%);
    overflow: hidden;
    box-sizing: border-box;
    transition: border-color 0.15s, box-shadow 0.15s;
}
.clave-num-wrap:focus-within {
    border-color: #b48b00;
    border-bottom-color: #8c6b00;
    box-shadow: 0 0 0 3px rgba(180, 139, 0, 0.20),
                inset 0 1px 1px rgba(180, 139, 0, 0.06);
}
.clave-num-wrap .clave-field-num {
    width: 70px;
    text-align: right;
    border: none;
    background: transparent;
    height: 20px;
    padding: 0 6px;
    outline: none;
    flex: 0 0 auto;
    box-shadow: none;
}
.clave-num-btn {
    flex: 0 0 auto;
    width: 22px;
    height: 100%;
    display: inline-flex; align-items: center; justify-content: center;
    border: none;
    border-left: 1px solid rgba(0,0,0,0.10);
    background: transparent;
    color: #1f4a87;
    cursor: pointer;
    padding: 0;
    line-height: 1;
}
.clave-num-btn:hover  { background: rgba(31,74,135,0.08); }
.clave-num-btn:active { background: rgba(31,74,135,0.14); }
.clave-num-btn:disabled {
    color: #a4adb8; cursor: not-allowed; background: transparent;
}
.clave-num-btn i { font-size: 11px; line-height: 1; }

/* ===== ContextoBar v2 (CLAUDE.md §2.23) =====
   Switcher de empresa embebido arriba del formulario, en pantallas
   multi-empresa. Versión compacta (~52 px) con combobox/popover en
   lugar del mini-grid persistente — selector más moderno + flechas
   visibles a la derecha.

   Layout (de izquierda a derecha):
     [Empresa:] [combo trigger]  [◀ ▶]   [meta comercial]
                  ↓ click
                  [popover con search + lista]

   Acento visual: --ctx-color (gene_empresas.colorargb) como
   border-bottom de 3 px y como fondo del chip del id. Banda con
   --ctx-color-soft (alpha bajo) para teñir suavemente. */
.contexto-bar {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 4px 16px;
    /* §2.13 — la barra REPLIEGA en vez de recortar cuando su contenido
       (empresa + slot <Extra> de filtros + traducción) no cabe en una línea.
       Norma del RCL (cliente 2026-07-06, aprobado promover a norma tras el
       bug de recorte reportado en Cartera de cobros): height auto + min-height
       conserva los 52px en el caso de una sola línea y crece al envolver.
       Sin esto, con el app-shell en overflow:hidden, los últimos controles
       quedaban cortados en pantallas estrechas (ya a 1280px con filtros en
       el <Extra>, patrón Cartera/Albaranes/Pedidos). */
    height: auto;
    min-height: 52px;
    flex-wrap: wrap;
    row-gap: 4px;
    background: linear-gradient(180deg, #fbfcfd 0%, #eef2f8 100%);
    background-color: var(--ctx-color-soft, transparent);
    border-bottom: 3px solid var(--ctx-color, #1f4a87);
    transition: border-color 0.25s ease, background-color 0.25s ease;
    flex: 0 0 auto;
    position: relative;
    /* z-index alto para que el popover del combo (z-index 100 dentro del
       stacking context creado por position:relative) quede POR ENCIMA del
       thead sticky del grid maestro (z-index 10-20). Antes era 5, lo que
       atrapaba el popover detras de la cabecera. Fix 2026-05-18 fix/plan-contable. */
    z-index: 50;
}
/* Slot opcional de la pantalla (ContextoBar `Extra`): controles propios en la
   misma línea que el selector de empresa. Aditivo — sin uso, no ocupa nada. */
.contexto-bar .ctx-extra {
    display: flex;
    align-items: center;
    gap: 16px;
    margin-left: 18px;
    flex-wrap: wrap;   /* §2.13 — los grupos de filtros del slot repliegan entre sí */
    row-gap: 6px;
}
.contexto-bar .ctx-lbl {
    font-size: 12px;
    color: #4a5566;
    font-weight: 600;
    flex: 0 0 auto;
}

/* Combo (trigger + popover) */
.contexto-bar .ctx-combo {
    position: relative;
    flex: 0 0 auto;
}
.contexto-bar .ctx-trigger {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    height: 30px;
    padding: 0 10px 0 4px;
    border: 1px solid #c9ced4;
    background: linear-gradient(180deg, #fff 0%, #f5f7fa 100%);
    border-radius: 4px;
    cursor: pointer;
    min-width: 240px;
    max-width: 360px;
    color: #1b3a6c;
    box-shadow: 0 1px 2px rgba(0,0,0,0.06);
    font-size: 13px;
}
.contexto-bar .ctx-combo.open .ctx-trigger,
.contexto-bar .ctx-trigger:hover:not(:disabled) {
    border-color: #3874cb;
    background: linear-gradient(180deg, #fff 0%, #eaf2ff 100%);
}
.contexto-bar .ctx-trigger:disabled { cursor: not-allowed; opacity: 0.6; }
.contexto-bar .ctx-trigger-chip {
    background: var(--ctx-color, #1f4a87);
    /* NO poner #fff fijo: el fondo es el color que el cliente configura en la
       empresa y con un verde/amarillo claro el chip se vuelve ilegible (LASO
       S.L. daba 1,2:1). ContextoBar calcula el texto por contraste real y lo
       pasa en --ctx-fg (ColorLegible, norma 2026-08-26). */
    color: var(--ctx-fg, #fff);
    padding: 3px 9px;
    border-radius: 10px;
    font-weight: 700;
    font-size: 11px;
    letter-spacing: 0.4px;
    box-shadow: 0 1px 3px rgba(0,0,0,0.18);
    flex: 0 0 auto;
}
.contexto-bar .ctx-trigger-name {
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 600;
}
.contexto-bar .ctx-trigger-empty {
    color: #8a93a3;
    font-style: italic;
    flex: 1 1 auto;
}
/* Ámbito VACÍO (norma 2026-08-19): no es "aún no has elegido", es "no hay nada
   que elegir". Se separa visualmente del placeholder gris para que se lea como
   lo que es —un aviso— y no como una invitación a abrir el desplegable. */
.contexto-bar .ctx-trigger-alerta {
    color: #92400e;
    font-style: normal;
}
.contexto-bar .ctx-trigger-alerta-ico {
    color: #d97706;
    flex: 0 0 auto;
    margin-right: .35rem;
    font-size: .95em;
}
.contexto-bar .ctx-trigger-chev {
    flex: 0 0 auto;
    color: #6c7384;
    font-size: 12px;
    transition: transform 0.15s ease;
}
.contexto-bar .ctx-combo.open .ctx-trigger-chev { transform: rotate(180deg); }

/* Popover de selección */
.ctx-pop-backdrop {
    position: fixed;
    inset: 0;
    background: transparent;
    z-index: 90;
}
.contexto-bar .ctx-popover {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    width: 360px;
    max-height: 360px;
    background: #fff;
    border: 1px solid #c9ced4;
    border-radius: 6px;
    box-shadow: 0 8px 24px rgba(0,0,0,0.18);
    display: flex;
    flex-direction: column;
    z-index: 100;
    overflow: hidden;
}
.contexto-bar .ctx-popover-search {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 8px;
    background: #f4f6f9;
    border-bottom: 1px solid #e4e8ee;
}
.contexto-bar .ctx-popover-search i { color: #6c7384; font-size: 13px; }
.contexto-bar .ctx-search-inp {
    flex: 1 1 auto;
    height: 24px;
    padding: 0 6px;
    border: 1px solid #c9ced4;
    border-radius: 3px;
    background: #fff;
    font-size: 12px;
    outline: none;
    box-sizing: border-box;
}
.contexto-bar .ctx-search-inp:focus {
    border-color: #3874cb;
    box-shadow: inset 0 0 0 1px #3874cb;
}
.contexto-bar .ctx-popover-list {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 4px 0;
}
.contexto-bar .ctx-item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 5px 10px;
    cursor: pointer;
    font-size: 12px;
    color: #2a3147;
    white-space: nowrap;
    overflow: hidden;
}
.contexto-bar .ctx-item:hover,
.contexto-bar .ctx-item.hover { background: #eef4ff; }
.contexto-bar .ctx-item.selected { background: var(--ctx-color-soft, #e6efff); font-weight: 600; }
.contexto-bar .ctx-item-chip {
    color: #fff;
    background: #1f4a87;
    padding: 2px 8px;
    border-radius: 9px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.3px;
    flex: 0 0 auto;
    box-shadow: 0 1px 2px rgba(0,0,0,0.18);
}
.contexto-bar .ctx-item-name {
    flex: 0 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
}
.contexto-bar .ctx-item-comercial {
    color: #6c7384;
    font-weight: normal;
    overflow: hidden;
    text-overflow: ellipsis;
}
.contexto-bar .ctx-item-check {
    margin-left: auto;
    color: #1f4a87;
    font-size: 14px;
    flex: 0 0 auto;
}
.contexto-bar .ctx-item-empty {
    padding: 16px;
    text-align: center;
    color: #8a93a3;
    font-style: italic;
    font-size: 12px;
}
.contexto-bar .ctx-popover-footer {
    flex: 0 0 auto;
    padding: 5px 10px;
    background: #f4f6f9;
    border-top: 1px solid #e4e8ee;
    color: #6c7384;
    font-size: 11px;
    text-align: right;
}

/* Nav buttons */
.contexto-bar .ctx-nav {
    display: inline-flex;
    gap: 3px;
    flex: 0 0 auto;
}
.contexto-bar .ctx-nav-btn {
    width: 28px; height: 28px;
    border: 1px solid #c9ced4;
    background: linear-gradient(180deg, #fff 0%, #f0f3f8 100%);
    border-radius: 4px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    color: #1f4a87;
    box-shadow: 0 1px 2px rgba(0,0,0,0.06);
    padding: 0;
}
.contexto-bar .ctx-nav-btn:hover:not(:disabled) {
    background: linear-gradient(180deg, #f8faff 0%, #e7eef9 100%);
    border-color: #97a9c4;
}
.contexto-bar .ctx-nav-btn:active:not(:disabled) { transform: translateY(1px); }
.contexto-bar .ctx-nav-btn:disabled {
    color: #a4adb8;
    cursor: not-allowed;
    box-shadow: none;
    background: linear-gradient(180deg, #f5f7fa 0%, #e9edf2 100%);
}
.contexto-bar .ctx-nav-btn i { font-size: 12px; }

/* Comercial junto al combo + nav (no al fondo derecho) */
.contexto-bar .ctx-meta-comercial {
    color: #4a5566;
    font-size: 12px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-style: italic;
    flex: 0 1 auto;
    max-width: 380px;
    padding-left: 4px;
}
/* Spacer empuja todo lo que va detrás (botón ayuda, RightExtra) al fondo */
.contexto-bar .ctx-spacer {
    flex: 1 1 auto;
    min-width: 8px;
}
/* Botón ayuda canónico al fondo derecho del bar */
.contexto-bar .ctx-help-btn {
    width: 28px; height: 28px;
    border: 1px solid #c9ced4;
    background: linear-gradient(180deg, #fff 0%, #f0f3f8 100%);
    border-radius: 4px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    color: #1f4a87;
    box-shadow: 0 1px 2px rgba(0,0,0,0.06);
    padding: 0;
    flex: 0 0 auto;
}
.contexto-bar .ctx-help-btn:hover { background: linear-gradient(180deg,#f8faff 0%,#e7eef9 100%); border-color:#97a9c4; }
.contexto-bar .ctx-help-btn:active { transform: translateY(1px); }
.contexto-bar .ctx-help-btn i { font-size: 16px; }

/* CLAUDE.md §2.10 — dropdown de traducción canónico al final del bar.
   Mismos colores y dimensiones que .tb-translate del MasterToolbar para
   coherencia visual cross-pantalla. */
.contexto-bar .ctx-translate {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 2px 8px;
    background: #fff7d6;
    border: 1px solid #e0c87a;
    border-radius: 4px;
    color: #8a5b00;
    font-size: 12px;
    flex: 0 0 auto;
}
.contexto-bar .ctx-translate i.bi-translate {
    font-size: 14px;
    color: #b06900;
}
.contexto-bar .ctx-translate-spin {
    font-size: 13px;
    color: #b06900;
    animation: tb-spin 0.9s linear infinite;
}
.contexto-bar .ctx-lang {
    height: 24px;
    padding: 1px 4px;
    border: 1px solid #d0bb6d;
    border-radius: 3px;
    background: #fff;
    font-size: 12px;
    font-family: inherit;
    color: #1f3147;
    cursor: pointer;
    min-width: 130px;
}
.contexto-bar .ctx-lang:hover { border-color: #b06900; }
.contexto-bar .ctx-lang:focus {
    outline: none;
    border-color: #b06900;
    box-shadow: 0 0 0 2px rgba(176,105,0,0.18);
}

@media (max-width: 1100px) {
    .contexto-bar { padding: 0 10px; gap: 6px; }
    .contexto-bar .ctx-trigger { min-width: 200px; max-width: 260px; }
    .contexto-bar .ctx-meta-comercial { display: none; }
}

/* Logo de empresa en el trigger del combobox */
.contexto-bar .ctx-trigger-logo {
    width: 24px;
    height: 24px;
    border-radius: 3px;
    background: #fff;
    object-fit: contain;
    border: 1px solid #d4dbe6;
    flex: 0 0 auto;
    margin-right: 2px;
    padding: 1px;
}
/* Logo de empresa en items del popover */
.contexto-bar .ctx-item-logo {
    width: 22px;
    height: 22px;
    border-radius: 3px;
    background: #fff;
    object-fit: contain;
    border: 1px solid #e4e8ee;
    flex: 0 0 auto;
    padding: 1px;
}
.contexto-bar .ctx-item-logo--placeholder {
    background: transparent;
    border: 1px dashed #e4e8ee;
    display: inline-block;
}

/* ===== Layout split form_empresa (CLAUDE.md §2.23) =====
   Para pantallas multi-empresa cuyo cuerpo cabe holgado en ~50% del
   viewport (CuentasConsolidar = 3 cols). El form a la izquierda, tapiz
   neutro a la derecha. Por debajo de 1100px colapsa a 1 columna y
   oculta el tapiz. */
.cuentas-split {
    display: grid;
    grid-template-columns: 1fr 1px 1fr;
    flex: 1 1 auto;
    min-height: 0;
    overflow: hidden;
}
.cuentas-split .form-panel {
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
}
.cuentas-split .scope-tapiz {
    background:
        radial-gradient(ellipse at 30% 20%, rgba(31,74,135,0.06) 0%, transparent 60%),
        linear-gradient(180deg, #eef2f8 0%, #e0e7f1 100%);
    position: relative;
    overflow: hidden;
}
.cuentas-split .scope-tapiz::before {
    content: "";
    position: absolute;
    inset: 0;
    background-image: radial-gradient(rgba(15,30,55,0.06) 1px, transparent 1px);
    background-size: 24px 24px;
    pointer-events: none;
}
@media (max-width: 1100px) {
    .cuentas-split { grid-template-columns: 1fr; }
    .cuentas-split .scope-tapiz, .cuentas-split .app-split { display: none; }
}

/* =====================================================================
 * Heredado de hosts (merge automatico, 2026-05-10).
 * Bloques que vivian solo en los locales y se subieron al RCL para que
 * cualquier host (incluido futuros) los herede sin atraso.
 * ===================================================================== */

/* ----- Heredado de DatosBase (host local) ----- */
@keyframes tb-spin {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}
.loading-overlay {
    position: fixed;
    inset: 0;
    background: rgba(255, 255, 255, 0.55);
    z-index: 5000;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: wait;
}
.loading-overlay * { cursor: wait; }
.loading-card {
    background: #fff;
    border: 1px solid #b6d0ea;
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.20);
    padding: 16px 22px;
    border-radius: 10px;
    display: flex;
    align-items: center;
    gap: 12px;
    font-size: 13px;
    color: #1f3147;
    font-weight: 500;
    min-width: 240px;
}
.loading-card .bi-arrow-clockwise {
    font-size: 20px;
    color: #2a55a3;
    animation: tb-spin 0.9s linear infinite;
}
.form-grid .detalle-section.detalle-full {
    grid-column: 1 / -1;
}
.detalle-section.detalle-full {
    flex: 1 1 auto;
    min-height: 220px;
    height: auto;
}
.detalle-body.detalle-body-wide {
    overflow: auto;
    min-height: 0;
    flex: 1;
}
.detalle-table.detalle-table-impuestos {
    table-layout: auto;
    width: max-content;
    min-width: 100%;
}
.detalle-table.detalle-table-impuestos thead th {
    white-space: nowrap;
    padding: 4px 8px;
    font-size: 11px;
}
.detalle-table.detalle-table-impuestos tbody td {
    padding: 0;
}
.clave-num-btn i { font-size: 11px; line-height: 1; }
.detalle-table .grid-filter-row th {
    background: #fafbfc;
    padding: 2px 4px;
    border-bottom: 1px solid #c9ced4;
    position: sticky;
    top: 0;
    z-index: 2;
}
.detalle-table .grid-filter-row .grid-filter-inp {
    width: 100%;
    box-sizing: border-box;
    height: 22px;
    padding: 2px 4px;
    font-size: 11px;
    border: 1px solid #c9ced4;
    border-radius: 2px;
    background: #fff;
    outline: none;
}
.detalle-table .grid-filter-row .grid-filter-inp:focus {
    border-color: #3874cb;
    box-shadow: inset 0 0 0 1px #3874cb;
}
.detalle-table .grid-filter-row .grid-filter-inp.range {
    width: 100%;
    display: block;
    height: 20px;
    margin-bottom: 2px;
}
.detalle-table .grid-filter-row .grid-filter-inp.range:last-child {
    margin-bottom: 0;
}
.detalle-table .grid-filter-row .grid-filter-inp.range::placeholder {
    color: #aab3bd;
    font-size: 10px;
    font-style: italic;
}
.detalle-table.range-mode .grid-filter-row th {
    height: 50px;
    vertical-align: top;
    padding-top: 4px;
}
.detalle-table .grid-filter-row + tr th {
    top: 26px;
    z-index: 1;
}
.detalle-table.range-mode .grid-filter-row + tr th {
    top: 50px;
}
.detalle-table .date-cell-wrap {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.detalle-table .date-cell-icon {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 22px;
    color: #6b7785;
    cursor: pointer;
}
.detalle-table .date-cell-icon i {
    pointer-events: none;
}
.detalle-table .date-cell-overlay {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
    border: 0;
    padding: 0;
}
.ayuda-body h4:first-child { margin-top: 0; }
.ayuda-body p, .ayuda-body ul { margin: 4px 0; }
.ayuda-body ul { padding-left: 20px; }
.texto-section {
    flex: 1 1 auto;
    min-height: 220px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-top: 8px;
    width: 100%;
}
.texto-section > .lbl {
    color: #333;
    font-size: 13px;
}
.rich-editor-wrap {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    background: #fff;
    min-height: 200px;
}
.rich-editor-wrap .ql-toolbar {
    background: #f7f9fc;
    border: 1px solid #c9ced4;
    border-bottom: 0;
    border-radius: 4px 4px 0 0;
    flex: 0 0 auto;
}
.rich-editor-wrap .ql-container {
    flex: 1 1 auto;
    border: 1px solid #c9ced4;
    border-radius: 0 0 4px 4px;
    font-size: 13px;
    overflow: hidden;
}
.rich-editor-wrap .ql-editor {
    height: 100%;
    overflow-y: auto;
}
.rich-editor-wrap .rich-editor-target {
    height: 100%;
    display: flex;
    flex-direction: column;
}

/* ----- Heredado de UsuariosPermisos (host local) ----- */
.form-scroll > form {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-height: 0;
}
.ayuda-body h4:first-child { margin-top: 0; }
.ayuda-body p, .ayuda-body ul { margin: 4px 0; }
.ayuda-body ul { padding-left: 20px; }
.seleccion-grid {
    margin-top: 8px;
    border: 1px solid #d4dbe6;
    border-radius: 4px;
    overflow: hidden;
    background: #fff;
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    min-height: 0;
}
.seleccion-grid-title {
    padding: 6px 10px;
    background: #eef1f6;
    border-bottom: 1px solid #d4dbe6;
    font-weight: 600;
    color: #1b3a6c;
    font-size: 13px;
}
.seleccion-grid-toolbar {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    background: #f7f9fc;
    border-bottom: 1px solid #d4dbe6;
}
.seleccion-grid-search {
    flex: 1;
    max-width: 320px;
    height: 24px;
    padding: 2px 6px;
    border: 1px solid #b9c2d2;
    border-radius: 3px;
    font-size: 12.5px;
    background: #fff;
}
.seleccion-grid-search:focus {
    outline: none;
    border-color: #3874cb;
    box-shadow: 0 0 0 2px rgba(56, 116, 203, 0.18);
}
.seleccion-grid-btn {
    height: 24px;
    padding: 0 8px;
    background: #fff;
    border: 1px solid #b9c2d2;
    border-radius: 3px;
    font-size: 12px;
    color: #1b3a6c;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.seleccion-grid-btn:hover { background: #e7eef9; border-color: #3874cb; }
.seleccion-grid-counter {
    margin-left: auto;
    color: #5a6478;
    font-size: 12px;
    font-variant-numeric: tabular-nums;
}
.seleccion-grid-scroll {
    flex: 1 1 0;
    min-height: 0;
    overflow-y: scroll;
    overflow-x: hidden;
    background: #fff;
    outline: none;
    scrollbar-gutter: stable;
}
.seleccion-grid-scroll::-webkit-scrollbar { width: 12px; }
.seleccion-grid-scroll::-webkit-scrollbar-track { background: #f1f5fa; }
.seleccion-grid-scroll::-webkit-scrollbar-thumb {
    background: #a3b5cd;
    border-radius: 6px;
    border: 2px solid #f1f5fa;
}
.seleccion-grid-scroll::-webkit-scrollbar-thumb:hover { background: #6e87a8; }
.seleccion-grid-scroll:focus { box-shadow: inset 0 0 0 2px rgba(56, 116, 203, 0.25); }
.seleccion-grid-table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    background: #fff;
}
.seleccion-grid-table thead th {
    position: sticky;
    top: 0;
    z-index: 1;
    background: #eef1f6;
    border-bottom: 1px solid #c7d0dd;
    padding: 4px 8px;
    font-weight: 600;
    color: #1b3a6c;
    font-size: 12.5px;
    text-align: left;
}
.seleccion-grid-table tbody tr {
    background: #fff;
    cursor: pointer;
    scroll-margin-top: 30px;
}
.seleccion-grid-table tbody tr:hover { background: #f3f7ff; }
.seleccion-grid-table tbody tr.row-focus { background: #cfe1ff; }
.seleccion-grid-table tbody tr.row-focus:hover { background: #c4d8f7; }
.seleccion-grid-table td {
    padding: 3px 8px;
    border-bottom: 1px solid #eef1f6;
    font-size: 12.5px;
    color: #2a3147;
}
.seleccion-grid-table td.check-cell { text-align: center; }
.seleccion-grid-table td.check-cell input[type="checkbox"] {
    width: 16px; height: 16px;
    cursor: pointer;
}
.btn-permisos {
    background: radial-gradient(circle at 35% 30%, #8aabe0 0%, #3874cb 55%, #1f4a87 100%);
    margin-left: 10px;
}
.logs-resumen {
    font-size: 12px;
    color: #555;
    padding: 0 8px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
.logs-resumen .logs-trunc { color: #b06900; font-weight: 600; }
.logs-resumen .logs-total { color: #1f4a87; }
.ev-tag {
    display: inline-block;
    font-size: 11px;
    font-weight: 600;
    padding: 1px 6px;
    border-radius: 3px;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    color: #fff;
}
.ev-tag.ev-login    { background: #1d6f42; }   /* verde */
.ev-tag.ev-logout   { background: #6c757d; }   /* gris */
.ev-tag.ev-pantalla { background: #1f4a87; }   /* azul */
.ev-tag.ev-api      { background: #6f42c1; }   /* morado */
.ev-tag.ev-config   { background: #c2410c; }   /* naranja — cambio de config de formulario (§2.17) */
.ev-ok { color: #1d6f42; font-weight: 700; }
.ev-ko { color: #b00020; font-weight: 700; }
.grid-table .td-rutapantalla {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-family: ui-monospace, "Cascadia Mono", Menlo, monospace;
    font-size: 11.5px;
}
.grid-table .td-ok { text-align: center; }
.grid-table .td-ms { text-align: right; font-variant-numeric: tabular-nums; }
.grp-fechas-panel {
    margin: 6px 0 4px;
    border: 1px solid #c9d2dd;
    border-radius: 5px;
    background: #fff;
    overflow: hidden;
    box-shadow: 0 1px 2px rgba(15, 30, 55, 0.04);
}
.grp-fechas-header {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 12px;
    background: linear-gradient(180deg, #27548f 0%, #173a6b 100%);
    border-left: 3px solid #5fa8ff;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.12);
    color: #fff;
}
.grp-fechas-header > i {
    font-size: 16px;
    color: #aac6e8;
    flex: 0 0 auto;
}
.grp-fechas-header .grp-fechas-title {
    display: block;
    font-weight: 700;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    font-size: 12px;
    text-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
}
.grp-fechas-header .grp-fechas-sub {
    display: block;
    font-size: 11px;
    color: #cdd9e6;
    font-style: italic;
    margin-top: 1px;
}
.grp-fechas-checks {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 18px;
    padding: 10px 14px;
}
.grp-fechas-checks .chk {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12.5px;
    color: #1f3a5c;
    cursor: pointer;
    user-select: none;
}
.grp-fechas-checks .chk input[type="checkbox"] {
    margin: 0;
    cursor: pointer;
}


/* ----- Heredado de DatosBase (utility classes manuales) ----- */
/* Anchos por defecto de cada celda input según la clase .num-w-50 / .num-w-70 / .num-w-90 / .txt-w-50 / .txt-w-90 / .date-w-90 */
.detalle-inp.num-w-50  { width: 60px;  text-align: right; }
.detalle-inp.num-w-70  { width: 80px;  text-align: right; }
.detalle-inp.num-w-90  { width: 100px; text-align: right; }
.detalle-inp.txt-w-50  { width: 60px;  text-align: center; }
/* CLAUDE.md S3 (norma 2026-05-12, peticion cliente): el tipo de letra del
   campo cuenta contable se unifica con el resto del proyecto (Segoe UI
   heredada). Antes habia Consolas/monospace que rompia la consistencia
   visual con %Iva y demas inputs del mismo grid. */
.detalle-inp.txt-w-90  { width: 110px; text-align: center; }
.detalle-inp.date-w-90 { width: 100px; text-align: center; }

/* CLAUDE.md §1.4 + §2.21 — inputs numéricos del form-grid alineados a la
   derecha (importes, contadores, claves). Aplicar con clase .inp-num. */
.inp.inp-num { text-align: right; }


/* ===== TabsFicha — pestañas dentro de una ficha (CLAUDE.md §2.18 bis) =====
   Recurso canónico cuando la ficha excede el presupuesto vertical sin
   scrollbar. Diseño slim: una banda de 28px con botones de pestaña ligeros
   que no compitan con el contenido. Banda inferior gris-azul corp para
   reforzar la jerarquía visual con el form-panel "papel iluminado" §2.20.
*/
.tabs-ficha {
    display: flex;
    flex-direction: column;
    min-height: 0;
    flex: 1 1 auto;
}
.tabs-ficha-bar {
    display: flex;
    gap: 2px;
    border-bottom: 1px solid #c9d2dd;
    padding: 4px 10px 0;
    flex: 0 0 auto;
    background: linear-gradient(180deg, #f1f5fb 0%, #e6eef7 100%);
}
.tabs-ficha-btn {
    appearance: none;
    border: 1px solid transparent;
    background: transparent;
    color: #4a5568;
    padding: 4px 14px;
    font-size: 12.5px;
    font-weight: 500;
    border-radius: 4px 4px 0 0;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 24px;
    line-height: 1;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.tabs-ficha-btn:hover {
    color: #1f4a87;
    background: rgba(255,255,255,0.50);
}
.tabs-ficha-btn.active {
    background: #ffffff;
    border-color: #c9d2dd;
    border-bottom-color: #ffffff;
    color: #1f4a87;
    font-weight: 600;
    margin-bottom: -1px;  /* tapar el border-bottom del bar */
    box-shadow: inset 0 1px 0 #3874cb;  /* franja superior azul corp */
}
.tabs-ficha-btn i { font-size: 13px; color: inherit; }
.tabs-ficha-body {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

/* ===== RichTextEditor — wrapper del editor Quill 2.0 inyectado via JS ===== */
.rich-editor-wrap {
    width: 100%;
    background: #ffffff;
    border: 1px solid #c9ced4;
    border-radius: 3px;
    overflow: hidden;
}
.rich-editor-wrap .ql-toolbar { border: none; border-bottom: 1px solid #e5e9ef; }
.rich-editor-wrap .ql-container { border: none; font-size: 14px; }


/* ===== RichTextEditor barra de modo (Visual / Source HTML) ===== */
.rich-editor-bar {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 6px;
    padding: 4px 8px;
    background: #f1f5fb;
    border-bottom: 1px solid #e5e9ef;
    font-size: 11px;
    color: #5a6878;
}
.rich-editor-mode-label { font-style: italic; }
.rich-editor-mode-btn {
    appearance: none;
    border: 1px solid #c9d2dd;
    background: #fff;
    color: #1f4a87;
    border-radius: 3px;
    width: 26px;
    height: 22px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background 0.15s;
}
.rich-editor-mode-btn:hover { background: #eaf3ff; }
.rich-editor-mode-btn.active { background: #1f4a87; color: #fff; border-color: #1f4a87; }
.rich-editor-mode-btn i { font-size: 12px; }
.rich-editor-source { background: #fafbfd; }


/* =====================================================================
   FirmaPreviewDialog — vista previa de firma de correo HTML.
   Modal canónico (CLAUDE.md §2.30) sobre LookupDialog.
   ===================================================================== */
.firma-preview-dialog {
    width: 920px;
    max-width: 95vw;
    max-height: 92vh;
    display: flex;
    flex-direction: column;
}
.firma-preview-toolbar {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    background: linear-gradient(180deg, #f1f5fb 0%, #e6eef7 100%);
    border-bottom: 1px solid #c9d2dd;
    font-size: 12.5px;
    color: #5a6878;
    flex-shrink: 0;
}
.firma-preview-label {
    font-weight: 600;
    color: #4a5566;
}
.firma-preview-tema-btn {
    appearance: none;
    border: 1px solid #c5cdd6;
    background: #fff;
    color: #4a5566;
    border-radius: 4px;
    padding: 4px 10px;
    font-size: 12px;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.firma-preview-tema-btn:hover { background: #eaf3ff; color: #1f4a87; }
.firma-preview-tema-btn.active {
    background: linear-gradient(180deg, #2f6ec1 0%, #1f4a87 100%);
    color: #fff;
    border-color: #1f4a87;
}
.firma-preview-tema-btn i { font-size: 11px; }
.firma-preview-spacer { flex: 1 1 auto; }
.firma-preview-loading {
    font-style: italic;
    color: #5a6878;
    display: inline-flex;
    align-items: center;
    gap: 5px;
}
@keyframes spin {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}
.firma-preview-info {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    color: #1d6f42;
    font-size: 11.5px;
}
.firma-preview-info i { color: inherit; }
.firma-preview-body {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}
.firma-preview-body.tema-claro  { background: #f5f5f5; }
.firma-preview-body.tema-oscuro { background: #262626; }
.firma-preview-warn {
    background: #fff8e1;
    border-bottom: 1px solid #f0d77a;
    color: #7a4a00;
    padding: 6px 12px;
    font-size: 12px;
    display: flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
}
.firma-preview-warn i { color: #d4860b; }
.firma-preview-warn code {
    background: #fff;
    border: 1px solid #f0d77a;
    border-radius: 3px;
    padding: 1px 6px;
    font-size: 11.5px;
    color: #5a4400;
    font-family: Consolas, monospace;
}
.firma-preview-iframe {
    flex: 1 1 auto;
    min-height: 320px;
    width: 100%;
    border: none;
    background: transparent;
}


/* =====================================================================
   Bloques apilados de ficha (alternativa a TabsFicha cuando todos los
   bloques caben verticalmente y se quiere ver todo a la vez).
   Patrón canónico usado en CuentasCorreoPropias §2.18 (variante "bloques").
   ===================================================================== */
.ficha-bloques {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 12px 14px;
    flex: 1 1 auto;
    min-height: 0;
}
.ficha-bloque {
    border: 1px solid #c9d2dd;
    border-radius: 5px;
    background: linear-gradient(180deg, #ffffff 0%, #f8fafd 100%);
    box-shadow: 0 1px 2px rgba(15,30,55,0.04);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    flex-shrink: 0;
}
.ficha-bloque-firma {
    flex: 1 1 auto;
    min-height: 280px;
}
.ficha-bloque-header {
    background: linear-gradient(180deg, #27548f 0%, #173a6b 100%);
    color: #fff;
    padding: 7px 12px;
    display: flex;
    align-items: center;
    gap: 8px;
    border-bottom: 2px solid #5fa8ff;
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.10),
                inset 0 -1px 0 rgba(0,0,0,0.18);
    flex-shrink: 0;
}
.ficha-bloque-header > i {
    color: #aac6e8;
    font-size: 13px;
}
.ficha-bloque-header-title {
    flex: 1 1 auto;
}
.ficha-bloque-header-actions {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.ficha-bloque-header-actions .bloque-btn {
    appearance: none;
    border: 1px solid rgba(255,255,255,0.22);
    background: rgba(255,255,255,0.10);
    color: #fff;
    border-radius: 4px;
    padding: 3px 9px;
    font-size: 11.5px;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    line-height: 1.2;
    transition: background 0.12s, border-color 0.12s;
    text-transform: none;
    letter-spacing: 0;
    font-weight: 500;
}
.ficha-bloque-header-actions .bloque-btn:hover:not(:disabled) {
    background: rgba(255,255,255,0.20);
    border-color: rgba(255,255,255,0.40);
}
.ficha-bloque-header-actions .bloque-btn:disabled {
    opacity: 0.45;
    cursor: not-allowed;
}
.ficha-bloque-header-actions .bloque-btn i { font-size: 11px; }
.ficha-bloque-body {
    padding: 10px 14px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    flex: 1 1 auto;
    min-height: 0;
}
.ficha-bloque-firma .ficha-bloque-body {
    padding: 8px 12px;
}
.ficha-bloque .form-grid {
    grid-row-gap: 4px;
    grid-column-gap: 6px;
}

/* ===== Checkbox canónico custom (CLAUDE.md §2.31b — norma del proyecto)
   Render consistente cross-browser/SO. Sustituye al checkbox nativo del
   navegador (que dependía del accent-color del SO). Selector universal —
   se aplica a TODOS los `<input type="checkbox">` del proyecto. Estados
   cubiertos: idle / hover / focus / checked / indeterminate / disabled. */
input[type="checkbox"] {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    width: 16px;
    height: 16px;
    border: 1px solid #c5cdd9;
    border-radius: 3px;
    background: linear-gradient(180deg, #ffffff 0%, #f8fafd 100%);
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.7);
    cursor: pointer;
    position: relative;
    vertical-align: middle;
    margin: 0;
    padding: 0;
    flex-shrink: 0;
    transition: border-color 0.1s ease, box-shadow 0.1s ease,
                background 0.15s ease;
}
input[type="checkbox"]:hover:not(:disabled) {
    border-color: #5fa8ff;
    background: linear-gradient(180deg, #fbfdff 0%, #eef5ff 100%);
}
input[type="checkbox"]:focus-visible {
    outline: none;
    border-color: #3874cb;
    box-shadow: 0 0 0 3px rgba(31,74,135,0.16),
                inset 0 1px 0 rgba(255,255,255,0.7);
}
input[type="checkbox"]:checked {
    background: linear-gradient(180deg, #3874cb 0%, #1f4a87 100%);
    border-color: #1f4a87;
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.20);
}
input[type="checkbox"]:checked::after {
    content: "";
    position: absolute;
    left: 4px;
    top: 1px;
    width: 5px;
    height: 9px;
    border-right: 2px solid #fff;
    border-bottom: 2px solid #fff;
    transform: rotate(45deg);
}
input[type="checkbox"]:checked:hover:not(:disabled) {
    background: linear-gradient(180deg, #4a82d4 0%, #2a5a99 100%);
}
input[type="checkbox"]:indeterminate {
    background: linear-gradient(180deg, #3874cb 0%, #1f4a87 100%);
    border-color: #1f4a87;
}
input[type="checkbox"]:indeterminate::after {
    content: "";
    position: absolute;
    left: 3px;
    top: 6px;
    width: 8px;
    height: 2px;
    background: #fff;
    border-radius: 1px;
}
input[type="checkbox"]:disabled {
    opacity: 0.55;
    cursor: not-allowed;
    background: #f1f4f8;
    border-color: #d4dae3;
}
input[type="checkbox"]:disabled:checked {
    background: linear-gradient(180deg, #8aa7d0 0%, #6a85ad 100%);
    border-color: #6a85ad;
}

/* ===== RADIO BUTTON canónico — norma del proyecto (cliente 2026-05-26) =====
   Espejo del checkbox §2.31b: caja redonda 16px con gradiente blanco/gris en
   idle, fondo azul corporativo + punto blanco interior en :checked, halo en
   :focus-visible. NUNCA usar el render nativo del navegador para garantizar
   coherencia cross-pantalla (el `accent-color` no aplica con `appearance:none`). */
input[type="radio"] {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    width: 16px;
    height: 16px;
    border: 1px solid #c5cdd9;
    border-radius: 50%;
    background: linear-gradient(180deg, #ffffff 0%, #f8fafd 100%);
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.7);
    cursor: pointer;
    position: relative;
    vertical-align: middle;
    margin: 0;
    padding: 0;
    flex-shrink: 0;
    transition: border-color 0.1s ease, box-shadow 0.1s ease,
                background 0.15s ease;
}
input[type="radio"]:hover:not(:disabled) {
    border-color: #5fa8ff;
    background: linear-gradient(180deg, #fbfdff 0%, #eef5ff 100%);
}
input[type="radio"]:focus-visible {
    outline: none;
    border-color: #3874cb;
    box-shadow: 0 0 0 3px rgba(31,74,135,0.16),
                inset 0 1px 0 rgba(255,255,255,0.7);
}
input[type="radio"]:checked {
    background: linear-gradient(180deg, #3874cb 0%, #1f4a87 100%);
    border-color: #1f4a87;
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.20);
}
input[type="radio"]:checked::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 0 1px rgba(0,0,0,0.20);
}
input[type="radio"]:checked:hover:not(:disabled) {
    background: linear-gradient(180deg, #4a82d4 0%, #2a5a99 100%);
}
input[type="radio"]:disabled {
    opacity: 0.55;
    cursor: not-allowed;
    background: #f1f4f8;
    border-color: #d4dae3;
}
input[type="radio"]:disabled:checked {
    background: linear-gradient(180deg, #8aa7d0 0%, #6a85ad 100%);
    border-color: #6a85ad;
}

/* ===== LoadingBar (cliente 2026-05-26) =====
   Norma del proyecto: indicador visible mientras se recargan datos en
   grids de consulta para que el usuario no perciba que el sistema se
   cuelga. Barra fixed top con animación de barrido tipo NProgress.
   Sin overlay bloqueante — el usuario sigue viendo el contenido previo. */
.netoffice-loading-bar {
    position: fixed;
    top: 0; left: 0; right: 0;
    height: 3px;
    background: linear-gradient(90deg, transparent 0%, #3874cb 30%, #1f4a87 50%, #3874cb 70%, transparent 100%);
    background-size: 200% 100%;
    z-index: 10000;
    pointer-events: none;
    animation: netoffice-loading-sweep 1.4s linear infinite;
    box-shadow: 0 0 6px rgba(31,74,135,0.55);
}
.netoffice-loading-bar-glow {
    position: absolute;
    top: 0; left: 0; right: 0; bottom: 0;
    background: linear-gradient(90deg, transparent 40%, rgba(255,255,255,0.5) 50%, transparent 60%);
    animation: netoffice-loading-glow 1.4s linear infinite;
}
@keyframes netoffice-loading-sweep {
    0%   { background-position: -100% 0; }
    100% { background-position:  100% 0; }
}
@keyframes netoffice-loading-glow {
    0%   { transform: translateX(-100%); }
    100% { transform: translateX(100%); }
}

/* ===== RevisionPunteoDialog (form_revision_punteo, cliente 2026-05-27) ====
   Bloque movido AQUÍ desde el scoped CSS local del componente porque el
   bundle scoped del RCL NetOffice.Web.Forms NO se sirve al navegador en
   esta configuración del proyecto (mismo motivo por el que ExtractoDialog
   y otros modales del RCL tienen sus estilos clave aquí en el app.css
   global). Las clases .rp-* son ÚNICAS de RevisionPunteoDialog. */
/* RevisionPunteoDialog — scoped CSS (CLAUDE.md form_revision_punteo).
   Lenguaje visual canónico:
     - Header con chip empresa (clon de ExtractoDialog §2.30).
     - Toolbar slate con radio de modo + filtros.
     - KPI Familia A §2.30a con border-left semántico.
     - Grid con OK 1ª columna (checkbox grande), filas zebra, selección azul.
     - Footer con dirty badge + acciones primarias. */

.rp-dialog {
    width: 96vw; max-width: 1700px;
    height: 92vh;
    display: flex; flex-direction: column;
    background: #fff;
    border-radius: 6px;
    box-shadow: 0 12px 40px rgba(0,0,0,0.30);
    overflow: hidden;
}

/* ===== Header ===== */
.rp-header {
    display: flex; align-items: center; gap: 14px;
    padding: 10px 14px;
    background: linear-gradient(180deg, #f6f9fd 0%, #dbe5f1 100%);
    border-bottom: 1px solid #c5cdd9;
}
.rp-empresa-chip {
    display: inline-flex; align-items: center; gap: 8px;
    padding: 4px 12px 4px 6px;
    border: 1.5px solid #c5cdd9; border-radius: 16px;
    background: #fff;
    font-size: 12px;
    box-shadow: 0 1px 2px rgba(0,0,0,0.06);
}
.rp-empresa-logo {
    width: 24px; height: 24px;
    border-radius: 50%;
    object-fit: cover;
    background: #fff;
    border: 1px solid rgba(255,255,255,0.6);
}
.rp-empresa-chip i.bi-building {
    color: #4a5566; font-size: 16px;
}
.rp-empresa-nom {
    font-weight: 700; color: #1a2530;
}
.rp-empresa-sub {
    color: #4a5566; font-weight: 500; margin-left: 2px;
}
.rp-titulo {
    flex: 1; text-align: center;
    font-size: 15px; font-weight: 700; color: #1f4a87;
    letter-spacing: 0.04em;
}
.rp-titulo i { color: #1f4a87; margin-right: 6px; }

.lookup-close {
    width: 32px; height: 32px;
    border: none; background: transparent;
    color: #4a5566;
    border-radius: 4px;
    cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center;
}
.lookup-close:hover { background: rgba(0,0,0,0.06); color: #1a2530; }

/* ===== Toolbar ===== */
.rp-toolbar {
    padding: 8px 14px;
    background: #f1f4f8;
    border-bottom: 1px solid #d4dae3;
    display: flex; flex-direction: column; gap: 8px;
}
.rp-modo-group {
    display: inline-flex; gap: 16px;
}
.rp-modo-radio {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 4px 10px;
    border: 1px solid #c5cdd9;
    border-radius: 4px;
    background: #fff;
    cursor: pointer;
    font-size: 12px;
    font-weight: 600;
    color: #3a4754;
}
.rp-modo-radio input[type="radio"]:checked + span {
    color: #1f4a87;
}
.rp-modo-radio:has(input[type="radio"]:checked) {
    border-color: #1f4a87;
    background: linear-gradient(180deg, #f5fbff 0%, #d8ecff 100%);
    box-shadow: 0 1px 3px rgba(31,74,135,0.15);
}
.rp-modo-radio span i { margin-right: 4px; }

.rp-toolbar-row {
    display: inline-flex; align-items: center; gap: 8px;
    flex-wrap: wrap;
}
.rp-lbl {
    font-size: 11px;
    color: #3a4754;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}
.rp-fecha {
    width: 100px; height: 26px;
    padding: 2px 6px;
    text-align: center;
    font-size: 12px;
    font-variant-numeric: tabular-nums;
}
.rp-picker {
    width: 28px; height: 26px;
    padding: 0;
    border: 1px solid #c5cdd9;
    border-radius: 3px;
    background: #fff;
    cursor: pointer;
}
.rp-cuenta {
    width: 130px; height: 26px;
    padding: 2px 6px;
    font-size: 12px;
    font-variant-numeric: tabular-nums;
}
.rp-cuenta-nom {
    font-size: 12px;
    color: #1f4a87;
    font-weight: 600;
    min-width: 140px;
    font-style: italic;
}
.rp-filtro {
    width: 120px; height: 26px;
    padding: 2px 6px;
    font-size: 12px;
    background: #fff;
    border: 1px solid #c5cdd9;
    border-radius: 3px;
}
.rp-sep {
    display: inline-block;
    width: 1px; height: 20px;
    background: #c5cdd9;
    margin: 0 6px;
}
.rp-flex { flex: 1 1 auto; }

.rp-btn-calcular {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 5px 14px;
    background: linear-gradient(180deg, #2f6ec1 0%, #1f4a87 100%);
    color: #fff;
    border: 1px solid #1f4a87;
    border-radius: 4px;
    font-weight: 600;
    font-size: 12px;
    cursor: pointer;
    letter-spacing: 0.02em;
}
.rp-btn-calcular:hover:not(:disabled) {
    background: linear-gradient(180deg, #3a7cd8 0%, #2a5a9b 100%);
}
.rp-btn-calcular:disabled { opacity: 0.6; cursor: not-allowed; }
.rp-spin {
    animation: rp-spin 0.8s linear infinite;
}
@keyframes rp-spin { to { transform: rotate(360deg); } }

/* ===== Error bar ===== */
.rp-error {
    display: flex; align-items: center; gap: 8px;
    padding: 8px 14px;
    background: #fff4f4;
    color: #a31f1f;
    border-bottom: 1px solid #f0c5c5;
    font-size: 13px;
}
.rp-error i { font-size: 16px; }
.rp-error button {
    margin-left: auto;
    background: transparent; border: none;
    color: #a31f1f; cursor: pointer;
    font-size: 14px;
}

/* ===== KPI Familia A §2.30a ===== */
.rp-kpi-row {
    display: flex; gap: 12px;
    padding: 12px 14px;
    background: #fff;
    border-bottom: 1px solid #e2e8f0;
}
.rp-kpi {
    flex: 1;
    display: flex; flex-direction: column;
    background: #fafdff;
    border: 0.6px solid #c5cdd9;
    border-left: 3px solid #c5cdd9;
    border-radius: 2px;
    padding: 6px 14px;
    box-shadow: 0 1px 2px rgba(0,0,0,0.04);
}
.rp-kpi-punteado   { border-left-color: #1d6f42; }
.rp-kpi-sinpuntear { border-left-color: #a31f1f; }
.rp-kpi-saldo      { border-left-color: #d8a728; background: #fffce8; }
.rp-kpi-pendientes { border-left-color: #1f4a87; }
.rp-kpi label {
    font-size: 9px;
    font-weight: 700;
    color: #4a5566;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}
.rp-kpi-punteado label   { color: #1d6f42; }
.rp-kpi-sinpuntear label { color: #a31f1f; }
.rp-kpi-saldo label      { color: #b08000; }
.rp-kpi-pendientes label { color: #1f4a87; }

.rp-kpi span.num {
    font-size: 18px;
    font-weight: 700;
    color: #2b3640;
    text-align: right;
    font-variant-numeric: tabular-nums;
    margin: 2px 0;
}
.rp-kpi span.num.neg { color: #a31f1f; }
.rp-kpi span.num.pos { color: #1d6f42; }
.rp-kpi small {
    font-size: 10px;
    color: #6a7585;
    text-align: right;
}

/* ===== Grid ===== */
.rp-grid-wrap {
    flex: 1 1 auto;
    overflow: hidden;
    background: #fff;
    display: flex; flex-direction: column;
}
.rp-grid-scroll {
    flex: 1 1 auto;
    overflow: auto;
    outline: none;
}
.rp-empty {
    display: flex; align-items: center; justify-content: center;
    flex-direction: column; gap: 8px;
    padding: 40px;
    color: #6a7585;
    font-size: 13px;
}
.rp-empty i { font-size: 28px; color: #c5cdd9; }

.rp-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 12px;
    table-layout: fixed;
}
.rp-table thead th {
    position: sticky; top: 0; z-index: 2;
    background: linear-gradient(180deg, #f6f9fd 0%, #e6ecf3 100%);
    color: #1a2530;
    text-align: left;
    padding: 4px 6px;
    border-bottom: 1px solid #c5cdd9;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.rp-table thead tr.rp-filter-row th {
    background: #f1f4f8;
    padding: 2px 4px;
    top: 0;
}
.rp-table thead tr:not(.rp-filter-row) th {
    top: 28px;
}
.rp-table thead th.num    { text-align: right; }
.rp-table thead th.center { text-align: center; }
.rp-table thead th.cta    { text-align: left; font-variant-numeric: tabular-nums; }

.rp-table tbody td {
    padding: 4px 6px;
    border-bottom: 1px solid #f0f3f7;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.rp-table tbody td.num    { text-align: right; font-variant-numeric: tabular-nums; }
.rp-table tbody td.center { text-align: center; }
.rp-table tbody td.cta    { font-variant-numeric: tabular-nums; color: #2a55a3; }

.rp-table tbody tr:nth-child(even) { background: #fafbfd; }
.rp-table tbody tr:hover           { background: #fff8e1; }
.rp-table tbody tr.selected        {
    background: #d8ecff !important;
    box-shadow: inset 3px 0 0 #1f4a87;
}
.rp-table tbody tr.rp-row-mark     {
    background: #e7f7eb;
}
.rp-table tbody tr.rp-row-mark.selected { background: #c4e3ce !important; }

.rp-table tbody td.row-indicator {
    color: #1f4a87; font-weight: 700; text-align: center;
}

/* OK column — checkbox visible, grande */
.rp-table tbody td:nth-child(2) input[type="checkbox"],
.rp-table thead .rp-check-all {
    transform: scale(1.2);
    cursor: pointer;
}
.rp-table.readonly-mode tbody td:nth-child(2) input[type="checkbox"] {
    cursor: not-allowed; opacity: 0.5;
}

/* D/H pill */
.dh-pill {
    display: inline-block;
    width: 18px; height: 18px;
    line-height: 18px;
    border-radius: 50%;
    font-weight: 700;
    font-size: 11px;
    text-align: center;
    color: #fff;
}
.dh-pill.dh-d { background: #1f4a87; }
.dh-pill.dh-h { background: #a4642a; }

/* Filtros (heredan estilo del proyecto) */
.grid-filter-inp {
    width: 100%;
    box-sizing: border-box;
    padding: 1px 4px;
    border: 1px solid #c5cdd9;
    border-radius: 2px;
    font-size: 11px;
    background: #fff;
}

/* ===== Footer ===== */
.rp-footer {
    display: flex; align-items: center; gap: 12px;
    padding: 10px 14px;
    background: linear-gradient(180deg, #fcfcf3 0%, #f5f4dc 100%);
    border-top: 2px solid #d4cc8a;
    flex-shrink: 0;
}
.rp-dirty {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 4px 10px;
    background: #fff4d6;
    color: #8a6500;
    border: 1px solid #d8a728;
    border-radius: 12px;
    font-size: 11px;
    font-weight: 600;
}
.rp-info-revision {
    color: #4a5566;
    font-size: 11px;
    font-style: italic;
}

.rp-btn {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 6px 14px;
    border-radius: 4px;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    border: 1px solid #c5cdd9;
    background: linear-gradient(180deg, #ffffff 0%, #eef3f9 100%);
    color: #2b3640;
    letter-spacing: 0.02em;
}
.rp-btn:hover:not(:disabled) {
    background: linear-gradient(180deg, #eaf2fb 0%, #d4e1f2 100%);
}
.rp-btn:disabled { opacity: 0.5; cursor: not-allowed; }

.rp-btn-revisar {
    background: linear-gradient(180deg, #f5fff8 0%, #cee9d3 100%);
    border-color: #5fa97a;
    color: #1d6f42;
}
.rp-btn-revisar:hover:not(:disabled) {
    background: linear-gradient(180deg, #d6f1de 0%, #a0d8af 100%);
    border-color: #1d6f42;
}
.rp-btn-revisar i { color: #1d6f42; }

.rp-btn-grabar {
    background: linear-gradient(180deg, #2f6ec1 0%, #1f4a87 100%);
    color: #fff;
    border-color: #1f4a87;
}
.rp-btn-grabar:hover:not(:disabled) {
    background: linear-gradient(180deg, #3a7cd8 0%, #2a5a9b 100%);
}
.rp-btn-grabar i { color: #fff; }

.rp-btn-salir {
    background: linear-gradient(180deg, #fff5f5 0%, #ffd9d9 100%);
    border-color: #d6a4a4;
    color: #a31f1f;
}
.rp-btn-salir:hover:not(:disabled) {
    background: linear-gradient(180deg, #ffe8e8 0%, #ffb8b8 100%);
}
.rp-btn-salir i { color: #a31f1f; }

.rp-btn-danger {
    background: linear-gradient(180deg, #d94f4f 0%, #a31f1f 100%);
    color: #fff;
    border-color: #a31f1f;
}
.rp-btn-danger:hover { background: linear-gradient(180deg, #e26565 0%, #b82a2a 100%); }

/* ===== Confirm dirty ===== */
.rp-confirm {
    position: fixed;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    background: #fff;
    border-radius: 6px;
    box-shadow: 0 12px 40px rgba(0,0,0,0.40);
    min-width: 380px; max-width: 480px;
    z-index: 1300;
    overflow: hidden;
}
.rp-confirm-header {
    display: flex; align-items: center; gap: 10px;
    padding: 12px 16px;
    background: #fff8e1;
    border-bottom: 1px solid #f5e3a8;
    font-weight: 700;
    color: #8a6500;
}
.rp-confirm-header i { font-size: 20px; }
.rp-confirm-body {
    padding: 18px 16px;
    color: #2b3640;
    font-size: 13px;
}
.rp-confirm-footer {
    display: flex; justify-content: flex-end; gap: 8px;
    padding: 10px 16px;
    background: #fafbfd;
    border-top: 1px solid #e2e8f0;
}

/* ===== rp-dialog — posicionamiento y z-index =====
   NO redeclarar `.lookup-backdrop` aquí: es la clase canónica compartida
   por TODOS los modales del RCL (TestCorreoDialog, LookupDialog,
   DocumentosDialog, NotasDialog, ExtractoDialog, CarteraDialog,
   FacturasDialog, FormConfigDialog, …). Su z-index 1000 + el z-index
   1001 de `.lookup-dialog` ya funcionaban correctamente.

   Bug previo (commit 624aeb0): este bloque definía `.lookup-backdrop`
   a z-index 1100 y `.rp-dialog` a 1101. Como `.lookup-backdrop` es
   global, eso dejaba el backdrop por encima de TODOS los `.lookup-dialog`
   y los clicks caían sobre el backdrop, aparentando readonly. Fix
   2026-05-27 cliente: borrar la redeclaración del backdrop y alinear
   `.rp-dialog` al z-index 1001 que ya usa `.lookup-dialog`. */
.rp-dialog {
    position: fixed;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    z-index: 1001;
}

/* =====================================================================
 * Aviso de llamada al API tragada — "pantallas en blanco honestas".
 *
 * Banda fina SOBRE el contenido de la pantalla (no una overlay: la pantalla
 * sigue siendo usable). Distingue los tres estados que hasta 2026-09-22 se
 * veian igual — un grid vacio y mudo:
 *
 *   --fallo      ambar   algo se ha roto (5xx, API caida, timeout)
 *   --permiso    azul    la API ha dicho que no (401/403). No es una averia.
 *   --configurar gris    funcion no configurada en esta instalacion (501)
 *
 * Los colores NO son los del error-bar rojo a proposito: el rojo esta cogido
 * para los errores de validacion del formulario y mezclarlos haria que el
 * usuario leyera "he hecho algo mal" cuando lo que pasa es que falta un alta
 * o se ha caido un servicio.
 * ===================================================================== */
.aviso-llamada {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 8px 12px;
    font-size: 12.5px;
    line-height: 1.45;
    border-bottom: 1px solid transparent;
}
.aviso-llamada-icono { font-size: 15px; line-height: 1.3; flex: 0 0 auto; }
.aviso-llamada-texto { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1 1 auto; }
.aviso-llamada-titulo { font-weight: 600; }
.aviso-llamada-detalle { opacity: .9; }
.aviso-llamada-cerrar {
    flex: 0 0 auto;
    background: none;
    border: 0;
    cursor: pointer;
    color: inherit;
    opacity: .55;
    padding: 0 2px;
    line-height: 1;
}
.aviso-llamada-cerrar:hover { opacity: 1; }

/* Marco de ApiErrorBoundary: 100vh repartidos entre el aviso y la pantalla. Dentro del marco
   la .app-shell deja de medir 100vh y se queda el resto (JJ 2026-11-02): así un aviso no
   empuja el pie de la pantalla fuera de la ventana. Fuera del marco, .app-shell sigue igual. */
.api-marco { display: flex; flex-direction: column; height: 100vh; min-height: 0; }
.api-marco > .aviso-llamada { flex: 0 0 auto; }
.api-marco > .app-shell, .api-marco > .app-shell--ficha-only { flex: 1 1 auto; height: auto; min-height: 0; }

.aviso-llamada--fallo      { background: #fff4e0; color: #7a4a05; border-bottom-color: #e8a13a; }
.aviso-llamada--permiso    { background: #e8f1fd; color: #16416f; border-bottom-color: #4a90d9; }
.aviso-llamada--configurar { background: #f1f3f6; color: #3c4653; border-bottom-color: #9aa6b4; }

/* =====================================================================
 * ApiErrorBoundary — panel "Servicio no disponible" / error generico.
 * CLAUDE.md §4.x. Global (sin scope) para que aplique en todos los hosts
 * que cableen <ApiErrorBoundary> en su MainLayout. La overlay es
 * position:fixed con z-index alto para TAPAR el #blazor-error-ui nativo.
 * ===================================================================== */
.api-down-overlay {
    position: fixed;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    background: linear-gradient(180deg, #f7f9fc 0%, #eef1f6 100%);
    z-index: 3000;
}
.api-down-card {
    width: 100%;
    max-width: 460px;
    background: #fff;
    border: 1px solid #e6eaf0;
    border-radius: 16px;
    box-shadow: 0 18px 48px rgba(30, 41, 59, 0.16);
    padding: 36px 32px 30px;
    text-align: center;
    font-family: "Segoe UI", system-ui, sans-serif;
    animation: api-down-pop 0.22s ease-out;
}
@keyframes api-down-pop {
    from { opacity: 0; transform: translateY(8px) scale(0.98); }
    to   { opacity: 1; transform: none; }
}
.api-down-icon {
    width: 72px;
    height: 72px;
    margin: 0 auto 18px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: #eaf0fb;
    color: #3b5ba5;
    font-size: 34px;
}
.api-down-card--error .api-down-icon {
    background: #fdecea;
    color: #c0392b;
}
.api-down-title {
    margin: 0 0 10px;
    font-size: 22px;
    font-weight: 600;
    color: #1e293b;
}
.api-down-text {
    margin: 0 0 20px;
    font-size: 14.5px;
    line-height: 1.5;
    color: #5b6675;
}
.api-down-status {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    font-size: 13px;
    color: #3b5ba5;
    background: #eef3fc;
    border-radius: 999px;
    padding: 7px 16px;
    margin-bottom: 22px;
}
.api-down-spinner {
    width: 14px;
    height: 14px;
    flex: none;
    border: 2px solid #c2d2ef;
    border-top-color: #3b5ba5;
    border-radius: 50%;
    animation: api-down-spin 0.8s linear infinite;
}
@keyframes api-down-spin {
    to { transform: rotate(360deg); }
}
.api-down-actions {
    display: flex;
    justify-content: center;
}
.api-down-btn {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    border: none;
    background: #3b5ba5;
    color: #fff;
    border-radius: 9px;
    padding: 10px 22px;
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
    box-shadow: 0 2px 6px rgba(59, 91, 165, 0.28);
    transition: background 0.15s, transform 0.05s, opacity 0.15s;
}
.api-down-btn:hover:not(:disabled) {
    background: #2f4a8a;
}
.api-down-btn:active:not(:disabled) {
    transform: translateY(1px);
}
.api-down-btn:disabled {
    opacity: 0.55;
    cursor: default;
    box-shadow: none;
}
.api-down-hint {
    margin: 18px 0 0;
    font-size: 12px;
    color: #97a1b0;
}


/* =============================================================
   <DocRichTextEditor> — editor enriquecido con toolbar extendida.
   RCL desde 2026-07-05 (antes vivia en el app.css local de Personal
   como excepcion 3.4 de Calidad; al consumirlo Transporte > Tarifa
   clientes subio aqui — 6.9 fuente unica). Estilos globales (no
   scoped) porque los popovers se montan en document.body desde JS y
   no caen bajo el subtree con prefijos b-XXX.
   ============================================================= */

/* Footer del contador palabras/caracteres dentro del editor. */
.doc-rt-footer {
    display: flex;
    justify-content: flex-end;
    gap: 14px;
    padding: 4px 8px;
    font-size: 11px;
    color: #6b7785;
    border-top: 1px solid #e2e8f0;
    background: #fafdff;
}
.doc-rt-count { font-variant-numeric: tabular-nums; }

/* Botones custom de la toolbar — el RCL ya define .ql-toolbar; aqui
   solo damos color e icono propio. */
.ql-toolbar.ql-snow .doc-rt-custom-btn,
.ql-toolbar.ql-snow button.doc-rt-custom-btn {
    color: #1f4a87;
}
.ql-toolbar.ql-snow .doc-rt-custom-btn:hover {
    background: rgba(31, 74, 135, 0.08);
}
.ql-toolbar.ql-snow .doc-rt-custom-btn i {
    font-size: 14px;
    line-height: 1;
}
.ql-toolbar.ql-snow .doc-rt-custom-btn .doc-rt-text-btn {
    font-weight: 600;
    font-size: 13px;
    line-height: 1;
}
/* Feedback visual del paste-plain armado. */
.ql-toolbar.ql-snow .doc-rt-custom-btn.doc-rt-armed {
    background: #fff3cd !important;
    color: #6f5a00 !important;
    box-shadow: 0 0 0 2px #d8a728 inset;
}

/* Boton custom con LABEL (caso "Formato"): icono + texto inline. */
.ql-toolbar.ql-snow button.doc-rt-custom-btn-labeled {
    width: auto !important;
    padding: 1px 8px 1px 4px !important;
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.ql-toolbar.ql-snow .doc-rt-custom-btn-label {
    font-size: 12px;
    font-weight: 500;
    color: #000;
    line-height: 1;
}

/* Popover de PEGAR (texto plano / enriquecido). */
.doc-rt-pegar-pop { min-width: 280px; max-width: 320px; }
.doc-rt-pegar-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-top: 4px;
}
.doc-rt-pegar-btn {
    display: grid;
    grid-template-columns: 22px 1fr;
    grid-template-rows: auto auto;
    column-gap: 10px;
    padding: 8px 10px;
    text-align: left;
    background: #fafdff;
    border: 1px solid #e2e8f0;
    border-radius: 4px;
    cursor: pointer;
    transition: all 0.12s ease;
}
.doc-rt-pegar-btn:hover {
    background: #eef3f9;
    border-color: #5fa8ff;
}
.doc-rt-pegar-btn > i {
    grid-row: 1 / 3;
    grid-column: 1 / 2;
    font-size: 18px;
    color: #1f4a87;
    align-self: center;
}
.doc-rt-pegar-btn .doc-rt-pegar-label {
    grid-row: 1 / 2;
    grid-column: 2 / 3;
    font-weight: 600;
    font-size: 12px;
    color: #1f4a87;
}
.doc-rt-pegar-btn .doc-rt-pegar-hint {
    grid-row: 2 / 3;
    grid-column: 2 / 3;
    font-size: 11px;
    color: #6b7785;
    line-height: 1.3;
    margin-top: 2px;
}
.doc-rt-pegar-foot {
    margin-top: 8px;
    padding-top: 6px;
    border-top: 1px solid #e2e8f0;
    color: #95a1ad;
    font-size: 10.5px;
    text-align: center;
}
.doc-rt-pegar-foot small { font-size: 10.5px; }

/* Popover de FORMATO (B/I/U/S). */
.doc-rt-formato-pop { min-width: 200px; }
.doc-rt-formato-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 4px;
    margin-top: 4px;
}
.doc-rt-formato-btn {
    height: 36px;
    border: 1px solid #c5cdd9;
    border-radius: 3px;
    background: linear-gradient(180deg, #ffffff 0%, #f8fafd 100%);
    color: #000;
    cursor: pointer;
    font-size: 16px;
    line-height: 1;
    padding: 0;
}
.doc-rt-formato-btn:hover { background: #eef3f9; border-color: #5fa8ff; }
.doc-rt-formato-btn.active {
    background: linear-gradient(180deg, #3874cb 0%, #1f4a87 100%);
    color: #fff;
    border-color: #1f4a87;
    box-shadow: inset 0 1px 2px rgba(0,0,0,0.18);
}

/* === Popovers comunes (tabla / emoji / variable) === */
.doc-rt-popover {
    background: #fff;
    border: 1px solid #c5cdd9;
    border-radius: 4px;
    box-shadow: 0 8px 24px rgba(15, 30, 55, 0.16);
    padding: 10px 12px;
    min-width: 240px;
    max-width: 380px;
    max-height: 380px;
    overflow-y: auto;
}
.doc-rt-pop-title {
    font-weight: 700;
    color: #1f4a87;
    font-size: 13px;
    margin-bottom: 6px;
    border-bottom: 1px solid #e2e8f0;
    padding-bottom: 4px;
}
.doc-rt-pop-foot {
    display: flex;
    justify-content: flex-end;
    gap: 6px;
    margin-top: 10px;
    border-top: 1px solid #e2e8f0;
    padding-top: 6px;
}
.doc-rt-pop-foot button {
    padding: 4px 12px;
    font-size: 12px;
    border-radius: 3px;
    border: 1px solid #c5cdd9;
    background: linear-gradient(180deg, #ffffff 0%, #eef3f9 100%);
    color: #3a4754;
    cursor: pointer;
}
.doc-rt-pop-foot .doc-rt-pop-ok {
    background: linear-gradient(180deg, #3874cb 0%, #1f4a87 100%);
    color: #fff;
    border-color: #1f4a87;
    font-weight: 600;
}

/* === Popover de TABLA === */
.doc-rt-tabla-fields {
    display: flex;
    flex-direction: column;
    gap: 8px;
    font-size: 12px;
}
.doc-rt-tabla-fields label {
    display: flex;
    align-items: center;
    gap: 6px;
    color: #3a4754;
}
.doc-rt-tabla-fields input[type="number"] {
    width: 60px;
    padding: 2px 4px;
    border: 1px solid #c5cdd9;
    border-radius: 3px;
    text-align: right;
}

/* === Popover de EMOJI === */
.doc-rt-emoji-cat {
    font-size: 11px;
    font-weight: 600;
    color: #6b7785;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin: 8px 0 4px;
}
.doc-rt-emoji-cat:first-of-type { margin-top: 4px; }
.doc-rt-emoji-grid {
    display: grid;
    grid-template-columns: repeat(8, 1fr);
    gap: 2px;
}
.doc-rt-emoji-btn {
    width: 28px;
    height: 28px;
    font-size: 18px;
    line-height: 1;
    border: 1px solid transparent;
    border-radius: 3px;
    background: transparent;
    cursor: pointer;
    padding: 0;
}
.doc-rt-emoji-btn:hover {
    background: #eef3f9;
    border-color: #c5cdd9;
}

/* === Popover de VARIABLES (mergetags) === */
.doc-rt-var-help {
    font-size: 11px;
    color: #6b7785;
    margin-bottom: 6px;
    line-height: 1.4;
}
.doc-rt-var-help code {
    background: #eef3f9;
    padding: 1px 4px;
    border-radius: 2px;
    font-size: 11px;
    color: #1f4a87;
}
.doc-rt-var-list {
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.doc-rt-var-btn {
    display: grid;
    grid-template-columns: minmax(140px, max-content) 1fr;
    grid-template-rows: auto auto;
    column-gap: 8px;
    padding: 6px 8px;
    text-align: left;
    background: #fafdff;
    border: 1px solid #e2e8f0;
    border-radius: 3px;
    cursor: pointer;
    font-size: 11px;
}
.doc-rt-var-btn:hover {
    background: #eef3f9;
    border-color: #5fa8ff;
}
.doc-rt-var-btn code {
    grid-column: 1 / 2;
    grid-row: 1 / 2;
    background: #eef3f9;
    color: #1f4a87;
    padding: 2px 4px;
    border-radius: 2px;
    font-size: 11px;
}
.doc-rt-var-btn .doc-rt-var-label {
    grid-column: 2 / 3;
    grid-row: 1 / 2;
    color: #3a4754;
    font-weight: 500;
}
.doc-rt-var-btn .doc-rt-var-prev {
    grid-column: 1 / 3;
    grid-row: 2 / 3;
    color: #6b7785;
    font-style: italic;
    margin-top: 2px;
}


/* =============================================================
   <DocRichTextEditor> — dropdowns ampliados (CLAUDE.md sec.3.4
   excepcion). Mapea las whitelist de Quill (font/size/header) a su
   render real, y muestra cada opcion del menu CON su propio estilo
   para que el usuario vea preview en vivo.
   ============================================================= */

/* Quitar el margin-right entre grupos de la toolbar (cliente
   2026-05-29): el default Quill mete 15 px entre cada `.ql-formats`,
   con 11 grupos eso suma demasiado y la toolbar se desborda. */
.ql-toolbar.ql-snow .ql-formats { margin-right: 0 !important; }

/* Tamaño compacto de los iconos de la toolbar (cliente 2026-05-29).
   Quill defaults: button 28x24, svg 18x18. Bajamos ~20% para que la
   toolbar sea mas compacta sin perder legibilidad. */
.ql-toolbar.ql-snow                                 { padding: 4px 6px; }
.ql-toolbar.ql-snow button                          { width: 24px; height: 22px; padding: 1px 3px; }
.ql-toolbar.ql-snow button svg                      { width: 14px; height: 14px; }
.ql-toolbar.ql-snow .ql-formats > button            { line-height: 1; }
/* Pickers (Estilo / Fuente / Tamaño / Color / Align / Header) — altura
   alineada con los botones y font-size del label uniforme. */
.ql-toolbar.ql-snow .ql-picker                      { height: 22px; line-height: 22px; font-size: 12px; }
.ql-toolbar.ql-snow .ql-picker-label                { padding: 0 16px 0 6px; height: 22px; line-height: 22px; }
.ql-toolbar.ql-snow .ql-picker-label svg            { width: 14px; height: 14px; right: 2px; }
/* Iconos Bootstrap de mis botones custom — bajar font-size. */
.ql-toolbar.ql-snow .doc-rt-custom-btn i            { font-size: 12px; }
.ql-toolbar.ql-snow .doc-rt-custom-btn .doc-rt-text-btn { font-size: 12px; line-height: 1; }

/* Iconos de toolbar uniformes en NEGRO (cliente 2026-05-29).
   Quill por defecto usa #444 (gris oscuro) para los SVG nativos y
   azul Quill (#06c) para hover. Forzamos negro y dejamos el azul
   corp NetOffice solo para el estado :active (formato aplicado en
   el cursor) — asi se sigue distinguiendo visualmente que comando
   esta activo. */

/* SVG nativos (bold, italic, underline, link, image, video, align,
   list, indent, blockquote, code-block, clean, sub, super, color
   picker arrow, etc.) */
.ql-toolbar.ql-snow .ql-stroke,
.ql-toolbar.ql-snow .ql-stroke-miter                 { stroke: #000; }
.ql-toolbar.ql-snow .ql-fill,
.ql-toolbar.ql-snow .ql-stroke.ql-fill               { fill: #000; }
/* Even-odd para el icono de imagen (Quill usa esa subclase). */
.ql-toolbar.ql-snow .ql-even.ql-stroke               { stroke: #000; }
.ql-toolbar.ql-snow .ql-even.ql-fill                 { fill: #000; }
/* Color picker mantiene su muestra de color — solo cambiamos el arrow. */
.ql-toolbar.ql-snow .ql-color-picker .ql-picker-label svg .ql-stroke,
.ql-toolbar.ql-snow .ql-background .ql-picker-label svg .ql-stroke { stroke: #000; }

/* Texto / labels de pickers (Estilo, Fuente, Tamaño) y el chevron. */
.ql-toolbar.ql-snow .ql-picker                       { color: #000; }
.ql-toolbar.ql-snow .ql-picker-label::before         { color: #000; }
.ql-toolbar.ql-snow .ql-picker-label svg .ql-stroke  { stroke: #000; }

/* Iconos Bootstrap de mis botones custom (tabla, emoji, variable,
   hr, paste-plain, undo, redo) — el texto-icono de las casings
   (A / a / Aa) tambien. */
.ql-toolbar.ql-snow .doc-rt-custom-btn,
.ql-toolbar.ql-snow button.doc-rt-custom-btn          { color: #000 !important; }

/* Hover NEUTRO — gris muy oscuro + fondo gris suave. Sin cambio de tono. */
.ql-toolbar.ql-snow button:hover .ql-stroke,
.ql-toolbar.ql-snow button:hover .ql-stroke-miter,
.ql-toolbar.ql-snow .ql-picker-label:hover .ql-stroke,
.ql-toolbar.ql-snow .ql-picker-item:hover .ql-stroke { stroke: #000; }
.ql-toolbar.ql-snow button:hover .ql-fill,
.ql-toolbar.ql-snow button:hover .ql-stroke.ql-fill,
.ql-toolbar.ql-snow .ql-picker-label:hover .ql-fill,
.ql-toolbar.ql-snow .ql-picker-item:hover .ql-fill   { fill: #000; }
.ql-toolbar.ql-snow button:hover                      { background: #eef3f9; }
.ql-toolbar.ql-snow .ql-picker-label:hover::before,
.ql-toolbar.ql-snow .ql-picker-item:hover::before    { color: #000; }
.ql-toolbar.ql-snow .ql-picker-label:hover,
.ql-toolbar.ql-snow .ql-picker-item:hover            { color: #000; }

/* ACTIVO — azul corp NetOffice (pista visual del formato aplicado). */
.ql-toolbar.ql-snow button.ql-active .ql-stroke,
.ql-toolbar.ql-snow button.ql-active .ql-stroke-miter,
.ql-toolbar.ql-snow .ql-picker-label.ql-active .ql-stroke,
.ql-toolbar.ql-snow .ql-picker-item.ql-selected .ql-stroke { stroke: #1f4a87; }
.ql-toolbar.ql-snow button.ql-active .ql-fill,
.ql-toolbar.ql-snow button.ql-active .ql-stroke.ql-fill,
.ql-toolbar.ql-snow .ql-picker-label.ql-active .ql-fill,
.ql-toolbar.ql-snow .ql-picker-item.ql-selected .ql-fill   { fill: #1f4a87; }
.ql-toolbar.ql-snow button.ql-active,
.ql-toolbar.ql-snow .ql-picker-label.ql-active             { color: #1f4a87; }
.ql-toolbar.ql-snow .ql-picker-label.ql-active::before,
.ql-toolbar.ql-snow .ql-picker-item.ql-selected::before    { color: #1f4a87; }


/* ---- 1) FUENTE (24 slugs). El CSS .ql-font-XXX se aplica al texto
   editado; el .ql-picker-label[data-value="XXX"]::before y
   .ql-picker-item[data-value="XXX"]::before muestra el nombre en el
   propio dropdown CON la font correspondiente. ---- */

.ql-snow .ql-editor .ql-font-arial,
.ql-snow .ql-picker.ql-font [data-value="arial"]::before                 { font-family: Arial, sans-serif; content: 'Arial'; }
.ql-snow .ql-editor .ql-font-helvetica,
.ql-snow .ql-picker.ql-font [data-value="helvetica"]::before             { font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; content: 'Helvetica'; }
.ql-snow .ql-editor .ql-font-verdana,
.ql-snow .ql-picker.ql-font [data-value="verdana"]::before               { font-family: Verdana, Geneva, sans-serif; content: 'Verdana'; }
.ql-snow .ql-editor .ql-font-tahoma,
.ql-snow .ql-picker.ql-font [data-value="tahoma"]::before                { font-family: Tahoma, Geneva, sans-serif; content: 'Tahoma'; }
.ql-snow .ql-editor .ql-font-trebuchet,
.ql-snow .ql-picker.ql-font [data-value="trebuchet"]::before             { font-family: 'Trebuchet MS', sans-serif; content: 'Trebuchet MS'; }
.ql-snow .ql-editor .ql-font-segoe,
.ql-snow .ql-picker.ql-font [data-value="segoe"]::before                 { font-family: 'Segoe UI', Tahoma, sans-serif; content: 'Segoe UI'; }
.ql-snow .ql-editor .ql-font-calibri,
.ql-snow .ql-picker.ql-font [data-value="calibri"]::before               { font-family: Calibri, sans-serif; content: 'Calibri'; }

.ql-snow .ql-editor .ql-font-georgia,
.ql-snow .ql-picker.ql-font [data-value="georgia"]::before               { font-family: Georgia, serif; content: 'Georgia'; }
.ql-snow .ql-editor .ql-font-times,
.ql-snow .ql-picker.ql-font [data-value="times"]::before                 { font-family: 'Times New Roman', Times, serif; content: 'Times New Roman'; }
.ql-snow .ql-editor .ql-font-cambria,
.ql-snow .ql-picker.ql-font [data-value="cambria"]::before               { font-family: Cambria, Georgia, serif; content: 'Cambria'; }
.ql-snow .ql-editor .ql-font-garamond,
.ql-snow .ql-picker.ql-font [data-value="garamond"]::before              { font-family: Garamond, serif; content: 'Garamond'; }
.ql-snow .ql-editor .ql-font-palatino,
.ql-snow .ql-picker.ql-font [data-value="palatino"]::before              { font-family: 'Palatino Linotype', Palatino, serif; content: 'Palatino'; }
.ql-snow .ql-editor .ql-font-book-antiqua,
.ql-snow .ql-picker.ql-font [data-value="book-antiqua"]::before          { font-family: 'Book Antiqua', Palatino, serif; content: 'Book Antiqua'; }

.ql-snow .ql-editor .ql-font-courier,
.ql-snow .ql-picker.ql-font [data-value="courier"]::before               { font-family: 'Courier New', Courier, monospace; content: 'Courier New'; }
.ql-snow .ql-editor .ql-font-consolas,
.ql-snow .ql-picker.ql-font [data-value="consolas"]::before              { font-family: Consolas, 'Lucida Console', monospace; content: 'Consolas'; }
.ql-snow .ql-editor .ql-font-monaco,
.ql-snow .ql-picker.ql-font [data-value="monaco"]::before                { font-family: Monaco, Consolas, monospace; content: 'Monaco'; }
.ql-snow .ql-editor .ql-font-lucida-console,
.ql-snow .ql-picker.ql-font [data-value="lucida-console"]::before        { font-family: 'Lucida Console', Monaco, monospace; content: 'Lucida Console'; }

.ql-snow .ql-editor .ql-font-impact,
.ql-snow .ql-picker.ql-font [data-value="impact"]::before                { font-family: Impact, Charcoal, sans-serif; content: 'Impact'; }
.ql-snow .ql-editor .ql-font-arial-black,
.ql-snow .ql-picker.ql-font [data-value="arial-black"]::before           { font-family: 'Arial Black', Gadget, sans-serif; content: 'Arial Black'; }
.ql-snow .ql-editor .ql-font-comic-sans,
.ql-snow .ql-picker.ql-font [data-value="comic-sans"]::before            { font-family: 'Comic Sans MS', cursive; content: 'Comic Sans'; }
.ql-snow .ql-editor .ql-font-lucida-sans,
.ql-snow .ql-picker.ql-font [data-value="lucida-sans"]::before           { font-family: 'Lucida Sans Unicode', 'Lucida Grande', sans-serif; content: 'Lucida Sans'; }

.ql-snow .ql-editor .ql-font-serif,
.ql-snow .ql-picker.ql-font [data-value="serif"]::before                 { font-family: serif; content: 'Serif genérico'; }
.ql-snow .ql-editor .ql-font-sans-serif,
.ql-snow .ql-picker.ql-font [data-value="sans-serif"]::before            { font-family: sans-serif; content: 'Sans-serif genérico'; }
.ql-snow .ql-editor .ql-font-monospace,
.ql-snow .ql-picker.ql-font [data-value="monospace"]::before             { font-family: monospace; content: 'Monospace genérico'; }

/* Label por defecto del picker de fuente cuando no hay seleccion.
   Mismo font-size/font-weight que Estilo y Tamaño para coherencia visual. */
.ql-snow .ql-picker.ql-font .ql-picker-label::before                     { content: 'Fuente'; font-size: 13px; font-weight: 500; font-family: inherit; }
/* Pickers de Estilo / Fuente / Tamaño con ancho uniforme (cliente). */
.ql-snow .ql-picker.ql-font                                              { width: 80px; }
.ql-snow .ql-picker.ql-font .ql-picker-options                           { max-height: 360px; overflow-y: auto; min-width: 180px; }
/* Truncar con ellipsis cuando la fuente seleccionada tenga nombre largo
   (el dropdown desplegable mantiene 180px para verse legible). */
.ql-snow .ql-picker.ql-font .ql-picker-label                             { overflow: hidden; }
.ql-snow .ql-picker.ql-font .ql-picker-label::before                     { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: inline-block; max-width: 60px; vertical-align: middle; }

/* ---- 2) TAMAÑO (20 valores). Cada item del dropdown se renderiza
   CON su tamaño real para preview en vivo. ---- */

.ql-snow .ql-picker.ql-size [data-value="8px"]::before  { content: '8';  font-size: 8px;  }
.ql-snow .ql-picker.ql-size [data-value="9px"]::before  { content: '9';  font-size: 9px;  }
.ql-snow .ql-picker.ql-size [data-value="10px"]::before { content: '10'; font-size: 10px; }
.ql-snow .ql-picker.ql-size [data-value="11px"]::before { content: '11'; font-size: 11px; }
.ql-snow .ql-picker.ql-size [data-value="12px"]::before { content: '12'; font-size: 12px; }
.ql-snow .ql-picker.ql-size [data-value="13px"]::before { content: '13'; font-size: 13px; }
.ql-snow .ql-picker.ql-size [data-value="14px"]::before { content: '14'; font-size: 14px; }
.ql-snow .ql-picker.ql-size [data-value="15px"]::before { content: '15'; font-size: 15px; }
.ql-snow .ql-picker.ql-size [data-value="16px"]::before { content: '16'; font-size: 16px; }
.ql-snow .ql-picker.ql-size [data-value="18px"]::before { content: '18'; font-size: 18px; }
.ql-snow .ql-picker.ql-size [data-value="20px"]::before { content: '20'; font-size: 20px; }
.ql-snow .ql-picker.ql-size [data-value="22px"]::before { content: '22'; font-size: 22px; }
.ql-snow .ql-picker.ql-size [data-value="24px"]::before { content: '24'; font-size: 24px; }
.ql-snow .ql-picker.ql-size [data-value="28px"]::before { content: '28'; font-size: 28px; }
.ql-snow .ql-picker.ql-size [data-value="32px"]::before { content: '32'; font-size: 32px; }
.ql-snow .ql-picker.ql-size [data-value="36px"]::before { content: '36'; font-size: 36px; }
.ql-snow .ql-picker.ql-size [data-value="40px"]::before { content: '40'; font-size: 40px; }
.ql-snow .ql-picker.ql-size [data-value="48px"]::before { content: '48'; font-size: 48px; }
.ql-snow .ql-picker.ql-size [data-value="60px"]::before { content: '60'; font-size: 60px; }
.ql-snow .ql-picker.ql-size [data-value="72px"]::before { content: '72'; font-size: 72px; }

.ql-snow .ql-picker.ql-size .ql-picker-label::before                     { content: 'Tamaño'; font-size: 13px; font-weight: 500; }
.ql-snow .ql-picker.ql-size                                              { width: 80px; }
.ql-snow .ql-picker.ql-size .ql-picker-options                           { max-height: 360px; overflow-y: auto; min-width: 100px; }
.ql-snow .ql-picker.ql-size .ql-picker-item                              { line-height: 1.2; padding: 4px 8px; }

/* ---- 3) CABECERAS (H1-H6 + Normal). HTML solo admite 6 niveles.
   Mejoramos UX dando preview del tamaño/peso real en el dropdown. ---- */

.ql-snow .ql-picker.ql-header [data-value="1"]::before { content: 'Título 1';  font-size: 22px; font-weight: 700; }
.ql-snow .ql-picker.ql-header [data-value="2"]::before { content: 'Título 2';  font-size: 19px; font-weight: 700; }
.ql-snow .ql-picker.ql-header [data-value="3"]::before { content: 'Título 3';  font-size: 17px; font-weight: 600; }
.ql-snow .ql-picker.ql-header [data-value="4"]::before { content: 'Subtítulo'; font-size: 15px; font-weight: 600; }
.ql-snow .ql-picker.ql-header [data-value="5"]::before { content: 'Apartado';  font-size: 14px; font-weight: 600; color: #3a4754; }
.ql-snow .ql-picker.ql-header [data-value="6"]::before { content: 'Etiqueta';  font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: #6b7785; }
.ql-snow .ql-picker.ql-header .ql-picker-label::before                   { content: 'Estilo'; font-size: 13px; font-weight: 500; }
.ql-snow .ql-picker.ql-header                                            { width: 80px; }
.ql-snow .ql-picker.ql-header .ql-picker-options                         { min-width: 170px; padding: 4px; max-height: 360px; overflow-y: auto; }
.ql-snow .ql-picker.ql-header .ql-picker-item                            { padding: 6px 10px; line-height: 1.2; }

/* Estilar H4/H5/H6 en el editor para que coincidan con el preview. */
.ql-snow .ql-editor h4 { font-size: 15px; font-weight: 600; margin: 8px 0 4px; }
.ql-snow .ql-editor h5 { font-size: 14px; font-weight: 600; color: #3a4754; margin: 6px 0 3px; }
.ql-snow .ql-editor h6 { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: #6b7785; margin: 6px 0 3px; }

/* Separador horizontal <hr> (Blot 'divider' registrado por
   documentacion-richtext.js). Linea fina gris, margen vertical
   moderado. */
.ql-snow .ql-editor hr {
    border: none;
    border-top: 1px solid #c5cdd9;
    margin: 12px 0;
    height: 0;
    background: none;
}

/* Toolbar del <DocRichTextEditor> — botones principales mas legibles
   (cliente 2026-07-05: "muy poco intuitivo, no se aprecia la negrita ni el
   color"). Hover azul suave + estado activo marcado en azul; aplica a los
   botones estandar de Quill (B/I/U/S, listas, alineacion, etc.). */
.rich-editor-wrap .ql-toolbar.ql-snow button {
    width: 26px;
    height: 24px;
    border-radius: 4px;
}
.rich-editor-wrap .ql-toolbar.ql-snow button:hover { background: #e7f1ff; }
.rich-editor-wrap .ql-toolbar.ql-snow button.ql-active { background: #d6e8ff; }
.rich-editor-wrap .ql-toolbar.ql-snow button.ql-active .ql-stroke { stroke: #1d4ed8; }
.rich-editor-wrap .ql-toolbar.ql-snow button.ql-active .ql-fill   { fill: #1d4ed8; }
.rich-editor-wrap .ql-toolbar.ql-snow .ql-picker-label:hover { background: #e7f1ff; border-radius: 4px; }

/* ============================================================================
   <RichTextEditorFull> — editor rich text COMPLETO (RCL, 2026-07-06).
   Cabecera (label + IA/pantalla-completa/ayuda) + <DocRichTextEditor> +
   modales (fullscreen / código fuente / ayuda de iconos). Portado GLOBAL
   desde el scoped de Personal > Calidad > RegistroIncidencias (donde nació
   el patrón); aquí es la fuente única reutilizable (CLAUDE.md §3.4).
   Los `::deep` del scoped se han convertido a selectores descendientes.
   ============================================================================ */

/* ----- Layout del wrap: columna flex para que el editor rellene bajo la
   cabecera, tanto en altura fija como cuando el host lo pone full-height. ----- */
.rtef-wrap { display: flex; flex-direction: column; min-height: 0; }
.rtef-wrap > .cali-desc-header { flex: 0 0 auto; }
.rtef-editor { flex: 1 1 auto; min-height: 0; }
.rtef-editor .rich-editor-target-wrap { flex: 1 1 auto; min-height: 0; }

/* ----- Cabecera: label + botones ----- */
.cali-area-lbl { display: block; font-size: 11px; color: #3a4754; font-weight: 600; margin: 6px 0 2px; }
.cali-desc-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin: 6px 0 2px;
    gap: 8px;
}
.cali-desc-label { margin: 0 !important; }
.cali-desc-ia {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 12px;
    height: 26px;
    border: 1px solid #1a6b3d;
    border-radius: 5px;
    background: linear-gradient(180deg, #29a663 0%, #1a6b3d 100%);
    color: #fff;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.2px;
    cursor: pointer;
    transition: all 0.14s ease;
    box-shadow:
        0 1px 2px rgba(0, 0, 0, 0.20),
        inset 0 1px 0 rgba(255, 255, 255, 0.18);
}
.cali-desc-ia i { font-size: 13px; color: #fff; }
.cali-desc-ia:hover:not(:disabled) {
    background: linear-gradient(180deg, #2fb56e 0%, #1d7a45 100%);
    border-color: #145530;
    transform: translateY(-1px);
    box-shadow:
        0 2px 4px rgba(0, 0, 0, 0.25),
        inset 0 1px 0 rgba(255, 255, 255, 0.22);
}
.cali-desc-ia:active:not(:disabled) { transform: translateY(0); }
.cali-desc-ia:disabled {
    opacity: 0.45;
    cursor: not-allowed;
    transform: none;
}
.cali-ia-spin { animation: cali-ia-spin 1s linear infinite; }
@keyframes cali-ia-spin {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}
.cali-desc-actions {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
.cali-desc-fullscreen {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 12px;
    height: 26px;
    border: 1px solid #c5cdd9;
    border-radius: 5px;
    background: linear-gradient(180deg, #ffffff 0%, #eef3f9 100%);
    color: #3a4754;
    font-size: 12px;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.14s ease;
    box-shadow: 0 1px 1px rgba(15, 30, 55, 0.08);
}
.cali-desc-fullscreen i { font-size: 13px; color: #1f4a87; }
.cali-desc-fullscreen:hover {
    background: linear-gradient(180deg, #f8fafd 0%, #d8ecff 100%);
    border-color: #5fa8ff;
}
.cali-desc-fullscreen:active { transform: translateY(1px); }
.cali-desc-ia.cali-desc-ia-icon {
    padding: 4px 8px;
    gap: 0;
    width: 32px;
    justify-content: center;
}
.cali-desc-ia.cali-desc-ia-icon span { display: none; }
.cali-desc-fullscreen.cali-desc-fullscreen-icon {
    padding: 4px 8px;
    gap: 0;
    width: 32px;
    justify-content: center;
}
.cali-desc-help {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 26px;
    padding: 0;
    border: 1px solid #c5cdd9;
    border-radius: 5px;
    background: linear-gradient(180deg, #ffffff 0%, #f8fafd 100%);
    color: #1f4a87;
    cursor: pointer;
    transition: all 0.14s ease;
    box-shadow: 0 1px 1px rgba(15, 30, 55, 0.08);
}
.cali-desc-help i { font-size: 14px; }
.cali-desc-help:hover {
    background: linear-gradient(180deg, #f8fafd 0%, #d8ecff 100%);
    border-color: #5fa8ff;
}
.cali-desc-help:active { transform: translateY(1px); }

/* Placeholder del editor inline mientras está abierto el fullscreen. */
.cali-desc-fs-placeholder {
    height: 240px;
    border: 1px dashed #c5cdd9;
    border-radius: 4px;
    background: #fafdff;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    color: #6b7785;
    font-style: italic;
    font-size: 13px;
}
.cali-desc-fs-placeholder i { font-size: 18px; color: #1f4a87; }

/* ----- Modal "Ver / editar código HTML fuente" ----- */
.cali-src-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(15, 30, 55, 0.55);
    z-index: 9200;
    animation: cali-src-fade 0.14s ease-out;
}
.cali-src-modal {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: min(900px, calc(100vw - 32px));
    height: min(640px, calc(100vh - 48px));
    background: #fff;
    border-radius: 6px;
    box-shadow:
        0 12px 36px rgba(0, 0, 0, 0.28),
        0 4px 12px rgba(0, 0, 0, 0.12);
    z-index: 9201;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    animation: cali-src-pop 0.16s ease-out;
}
@keyframes cali-src-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
}
@keyframes cali-src-pop {
    from { transform: translate(-50%, -50%) scale(0.985); opacity: 0; }
    to   { transform: translate(-50%, -50%) scale(1);     opacity: 1; }
}
.cali-src-header {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 16px;
    background: linear-gradient(180deg, #27548f 0%, #173a6b 100%);
    color: #fff;
    border-bottom: 1px solid #1f4a87;
}
.cali-src-title {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: 14px;
    font-weight: 600;
    letter-spacing: 0.02em;
}
.cali-src-title i { color: #aac6e8; font-size: 16px; }
.cali-src-close {
    width: 28px;
    height: 26px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid rgba(255, 255, 255, 0.18);
    border-radius: 5px;
    background: rgba(255, 255, 255, 0.08);
    color: #fff;
    cursor: pointer;
}
.cali-src-close i { font-size: 13px; color: #fff; }
.cali-src-close:hover {
    background: rgba(255, 255, 255, 0.16);
    border-color: rgba(255, 255, 255, 0.30);
}
.cali-src-body {
    flex: 1 1 auto;
    min-height: 0;
    padding: 12px;
    background: #f8fafd;
    display: flex;
}
.cali-src-textarea {
    flex: 1 1 auto;
    width: 100%;
    height: 100%;
    border: 1px solid #c5cdd9;
    border-radius: 4px;
    padding: 10px 12px;
    background: #fff;
    color: #1a2129;
    font-family: Consolas, Monaco, 'Courier New', monospace;
    font-size: 12.5px;
    line-height: 1.55;
    resize: none;
    outline: none;
    box-shadow: inset 0 1px 2px rgba(15, 30, 55, 0.08);
    tab-size: 2;
}
.cali-src-textarea:focus {
    border-color: #5fa8ff;
    box-shadow:
        inset 0 1px 2px rgba(15, 30, 55, 0.08),
        0 0 0 3px rgba(31, 74, 135, 0.16);
}
.cali-src-footer {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 16px;
    background: #fff;
    border-top: 1px solid #e2e8f0;
}
.cali-src-meta {
    font-size: 11px;
    color: #6b7785;
    font-variant-numeric: tabular-nums;
}
.cali-src-actions {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}
.cali-src-btn {
    padding: 6px 16px;
    border-radius: 4px;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.14s ease;
    display: inline-flex;
    align-items: center;
    gap: 5px;
}
.cali-src-btn-cancel {
    background: #fff;
    border: 1px solid #c5cdd9;
    color: #3a4754;
}
.cali-src-btn-cancel:hover {
    background: #eef3f9;
    border-color: #5fa8ff;
}
.cali-src-btn-ok {
    background: linear-gradient(180deg, #3874cb 0%, #1f4a87 100%);
    border: 1px solid #1f4a87;
    color: #fff;
}
.cali-src-btn-ok:hover {
    background: linear-gradient(180deg, #4485dc 0%, #2a5fa8 100%);
}
.cali-src-btn-ok i { font-size: 13px; }

/* ----- Modal de AYUDA (leyenda de iconos) ----- */
.cali-help-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(15, 30, 55, 0.45);
    z-index: 9100;
    animation: cali-help-fade 0.14s ease-out;
}
.cali-help-modal {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: min(720px, calc(100vw - 32px));
    max-height: calc(100vh - 48px);
    background: #fff;
    border-radius: 6px;
    box-shadow:
        0 12px 36px rgba(0, 0, 0, 0.28),
        0 4px 12px rgba(0, 0, 0, 0.12);
    z-index: 9101;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    animation: cali-help-pop 0.16s ease-out;
}
@keyframes cali-help-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
}
@keyframes cali-help-pop {
    from { transform: translate(-50%, -50%) scale(0.985); opacity: 0; }
    to   { transform: translate(-50%, -50%) scale(1);     opacity: 1; }
}
.cali-help-header {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 12px 16px;
    background: linear-gradient(180deg, #27548f 0%, #173a6b 100%);
    color: #fff;
    border-bottom: 1px solid #1f4a87;
}
.cali-help-title {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: 14px;
    font-weight: 600;
    letter-spacing: 0.02em;
}
.cali-help-title i { color: #aac6e8; font-size: 16px; }
.cali-help-close {
    width: 28px;
    height: 26px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid rgba(255, 255, 255, 0.18);
    border-radius: 5px;
    background: rgba(255, 255, 255, 0.08);
    color: #fff;
    cursor: pointer;
}
.cali-help-close i { font-size: 13px; color: #fff; }
.cali-help-close:hover {
    background: rgba(255, 255, 255, 0.16);
    border-color: rgba(255, 255, 255, 0.30);
}
.cali-help-body {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 16px 20px;
    color: #3a4754;
    font-size: 12.5px;
    line-height: 1.5;
}
.cali-help-cat {
    margin-bottom: 18px;
}
.cali-help-cat:last-child { margin-bottom: 0; }
.cali-help-cat h4 {
    font-size: 12px;
    font-weight: 700;
    color: #1f4a87;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin: 0 0 8px;
    padding-bottom: 4px;
    border-bottom: 1px solid #e2e8f0;
}
.cali-help-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 6px;
}
.cali-help-row {
    display: grid;
    grid-template-columns: 28px 1fr;
    align-items: center;
    column-gap: 10px;
    padding: 4px 8px;
    border-radius: 3px;
}
.cali-help-row:hover { background: #f8fafd; }
.cali-help-row > i {
    font-size: 16px;
    color: #000;
    text-align: center;
}
.cali-help-row > .cali-q-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 22px;
    flex-shrink: 0;
}
.cali-help-row > .cali-q-icon svg {
    width: 18px;
    height: 18px;
    display: block;
}
.cali-help-row.cali-help-sub {
    padding-left: 28px;
}
.cali-help-row.cali-help-sub > i { font-size: 14px; color: #6b7785; }
.cali-help-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 22px;
    padding: 0 10px;
    background: #eef3f9;
    border: 1px solid #c5cdd9;
    border-radius: 3px;
    color: #1f4a87;
    font-size: 11px;
    font-weight: 600;
    font-family: inherit;
}
.cali-help-row code {
    background: #eef3f9;
    color: #1f4a87;
    padding: 1px 4px;
    border-radius: 2px;
    font-size: 11.5px;
}
.cali-help-row kbd {
    display: inline-block;
    padding: 1px 5px;
    border: 1px solid #c5cdd9;
    border-bottom-width: 2px;
    border-radius: 3px;
    background: #fafdff;
    color: #3a4754;
    font-family: Consolas, Monaco, monospace;
    font-size: 10.5px;
    font-weight: 600;
    line-height: 1.2;
}
.cali-help-footer {
    flex: 0 0 auto;
    display: flex;
    justify-content: flex-end;
    padding: 10px 16px;
    border-top: 1px solid #e2e8f0;
    background: #fafdff;
}
.cali-help-btn-ok {
    padding: 6px 16px;
    background: linear-gradient(180deg, #3874cb 0%, #1f4a87 100%);
    color: #fff;
    border: 1px solid #1f4a87;
    border-radius: 4px;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.14s ease;
}
.cali-help-btn-ok:hover {
    background: linear-gradient(180deg, #4485dc 0%, #2a5fa8 100%);
}

/* cali-q-icon — SVG de Quill inyectados en runtime (clonados de la toolbar
   viva). Se pintan aquí porque el clonado ocurre fuera del scope. */
.cali-q-icon svg                          { display: block !important; }
.cali-q-icon svg .ql-stroke,
.cali-q-icon svg .ql-stroke-miter,
.cali-q-icon svg .ql-even.ql-stroke       { stroke: #000 !important; fill: none !important; stroke-linecap: round; stroke-linejoin: round; stroke-width: 2; }
.cali-q-icon svg .ql-fill,
.cali-q-icon svg .ql-even.ql-fill         { fill: #000 !important; }
.cali-q-icon svg .ql-stroke.ql-fill       { stroke: #000 !important; fill: #000 !important; }
.cali-q-icon svg .ql-even                 { fill-rule: evenodd; }

/* ----- Modal de pantalla completa (ri-fs-*) ----- */
.ri-fs-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(15, 30, 55, 0.55);
    z-index: 9000;
    animation: ri-fs-fade 0.14s ease-out;
}
.ri-fs-modal {
    position: fixed;
    inset: 16px;
    background: #fff;
    border-radius: 6px;
    box-shadow:
        0 12px 36px rgba(0, 0, 0, 0.28),
        0 4px 12px rgba(0, 0, 0, 0.12);
    z-index: 9001;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    animation: ri-fs-pop 0.16s ease-out;
}
@keyframes ri-fs-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
}
@keyframes ri-fs-pop {
    from { transform: scale(0.985); opacity: 0; }
    to   { transform: scale(1);     opacity: 1; }
}
.ri-fs-header {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 16px;
    background: linear-gradient(180deg, #27548f 0%, #173a6b 100%);
    color: #fff;
    border-bottom: 1px solid #1f4a87;
}
.ri-fs-title {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: 14px;
    font-weight: 600;
    letter-spacing: 0.02em;
    color: #fff;
    min-width: 0;
}
.ri-fs-title i { color: #aac6e8; font-size: 16px; flex: 0 0 auto; }
.ri-fs-title span {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ri-fs-actions {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex: 0 0 auto;
}
.ri-fs-close {
    width: 28px;
    height: 26px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid rgba(255, 255, 255, 0.18);
    border-radius: 5px;
    background: rgba(255, 255, 255, 0.08);
    color: #fff;
    cursor: pointer;
    transition: all 0.14s ease;
}
.ri-fs-close i { font-size: 13px; color: #fff; }
.ri-fs-close:hover {
    background: rgba(255, 255, 255, 0.16);
    border-color: rgba(255, 255, 255, 0.30);
}
.ri-fs-body {
    flex: 1 1 auto;
    min-height: 0;
    padding: 12px;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}
.ri-fs-body .cali-desc-editor-fs {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}
.ri-fs-body .cali-desc-editor-fs .rich-editor-target-wrap {
    flex: 1 1 auto;
    min-height: 0;
}

/* ═══════════════════════════════════════════════════════════════════════════
   CANON VISUAL SUBIDO AL RCL — importes (`num`/`neg`), pie de totales
   (`totalbox`) y contador de las pastillas de filtro (`op-count`).
   Norma aprobada por el cliente (JJ) el 2026-08-15.

   POR QUÉ ESTÁ AQUÍ. Estas cuatro clases eran «canon de facto»: decenas de
   pantallas las escriben en su markup, pero NINGUNA estaba definida en esta
   hoja. Cada pantalla se las redefinía en su CSS aislado y **la que se olvidaba
   se quedaba sin estilo sin que nadie se enterara**. Caso real que destapó la
   norma: la bandeja de validación del registro de impuestos salía con los
   importes a la izquierda, en fuente proporcional e indistinguibles del texto,
   y los contadores del pie completamente sin formato — en una pantalla que
   además decía en su cabecera que los tomaba «del app.css canónico del RCL».

   ⚠ REGLA DE ESPECIFICIDAD — LEER ANTES DE TOCAR ESTE BLOQUE.
   Los selectores de aquí se mantienen DELIBERADAMENTE MÍNIMOS (`td.num` =
   0-1-1, `.totalbox` = 0-1-0, `.op-pill .op-count` = 0-2-0) para que cualquier
   definición local los gane SIEMPRE: el CSS aislado de Blazor añade `[b-xxxxx]`
   a sus selectores, así que un `.num` de pantalla vale 0-2-0 y un `td.num`
   vale 0-2-1 — por encima de lo de aquí en los dos casos. Consecuencia
   buscada: este bloque **sólo pinta las pantallas que NO traen definición
   propia**; las que ya la tienen no cambian ni un píxel.

   NO subir la especificidad. En concreto, `.grid-table tbody td.num` (0-2-2)
   parece más «correcto» y es justo lo que NO hay que poner: pasaría a PISAR a
   toda pantalla que declare un `.num` a secas en su CSS aislado (0-2-0).
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Importes en celdas de tabla ─────────────────────────────────────────────
   `num` = celda numérica: a la derecha y con cifras de ancho fijo, para que las
   unidades queden alineadas en columna y los importes se puedan comparar de un
   vistazo. Vale para cualquier tabla (`grid-table`, `detalle-table` o la tabla
   propia de la pantalla), no sólo para el grid maestro. */
td.num,
th.num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* `neg` = importe negativo, en el rojo corporativo del proyecto.
   Sobre la fila ACTIVA del grid (fondo azul `#3874cb` del RCL) se vuelve al
   color heredado de la fila: el rojo oscuro sobre azul es ilegible (~2:1).
   `inherit` resuelve los dos casos de golpe — blanco en `.grid-table`, tinta
   oscura en `.detalle-table`, cuya fila activa es azul CLARO. */
td.num.neg { color: #a31f1f; }
tr.selected td.num.neg { color: inherit; }

/* ── Pie de totales ──────────────────────────────────────────────────────────
   Caja del pie con la etiqueta arriba en versalitas y la cifra abajo. Es la
   variante mayoritaria del árbol (13 de las 20 pantallas que la definen) y la
   más reciente: banda «papel enmarcado» §2.20 con acento de 3px a la izquierda
   que cada pantalla recolorea por tipo de total (`totalbox-total`,
   `totalbox-pend`, `totalbox-saldo`…). Esas variantes de color siguen viviendo
   en cada pantalla: aquí sólo va la base. */
.totalbox {
    display: flex;
    flex-direction: column;
    background: #fafdff;
    border: 0.6px solid #c5cdd9;
    border-left: 3px solid #c5cdd9;
    border-radius: 2px;
    padding: 3px 9px;
    min-width: 86px;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
}
.totalbox label {
    font-size: 8.5px;
    font-weight: 700;
    color: #4a5566;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}
.totalbox .num {
    font-size: 13px;
    font-weight: 700;
    color: #2b3640;
    text-align: right;
    font-variant-numeric: tabular-nums;
}
.totalbox .num.neg { color: #a31f1f; }
.totalbox .num.pos { color: #1d6f42; }

/* ── Contador de las pastillas de filtro (§2.40b) ────────────────────────────
   Badge con el conteo dentro de una `.op-pill`. Copia exacta de la definición
   del componente RCL `OperativoPills`, para que las pantallas que escriben las
   pastillas a mano (que cogen `.op-pill` del `estadisticas.css` de su host,
   donde el badge NO existe) se vean igual que las que usan el componente.
   Sin `display` a propósito: `.op-pill` es `inline-flex`, así que el `<span>`
   ya se comporta como ítem flex y el padding / `min-width` funcionan. */
.op-pill .op-count {
    background: rgba(0, 0, 0, 0.10);
    color: inherit;
    font-weight: 600;
    padding: 0 6px;
    border-radius: 8px;
    font-size: 10.5px;
    min-width: 20px;
    text-align: center;
    line-height: 16px;
}
.op-pill.active .op-count { background: rgba(255, 255, 255, 0.25); }

/* ═══════════════════════════════════════════════════════════════════════════
   Estadisticas TMS (DOC TECNICA/77, fase 1 cimientos 2026-08-15).
   Clases bs-* / op-pills-inline / est-grid / bbtn-analisis / pdf-preview
   traidas del canon de estadisticas de Gastos (GASTOS/.../estadisticas.css,
   replica Familia B, CLAUDE.md 2.35a) para que el host Transporte las herede
   del RCL sin duplicar CSS local. APPEND-ONLY — no colisionan con nada previo
   del RCL (verificado con grep 2026-08-15).
   ═══════════════════════════════════════════════════════════════════════ */

/* Layout de las pantallas de Estadisticas TMS: fila panel de filtros + cuerpo */
.est-tms-main { flex: 1 1 auto; display: flex; align-items: stretch; min-height: 0; }

/* ===== Filtros del header (InlineExtra del ContextoBar) ===== */
.bs-hdr-block { display: inline-flex; align-items: center; gap: 4px; margin-left: 10px; padding: 0 8px; height: 26px; background: rgba(31,74,135,0.05); border: 1px solid #c5cdd9; border-radius: 4px; }
.bs-hdr-lbl { font-size: 10px; font-weight: 700; color: #1f4a87; letter-spacing: 0.06em; text-transform: uppercase; margin-right: 2px; }
.bs-hdr-nav, .bs-hdr-refrescar { height: 20px; width: 22px; padding: 0; border: 1px solid #c5cdd9; background: linear-gradient(180deg, #fff 0%, #f1f4f8 100%); color: #1f4a87; border-radius: 3px; display: inline-flex; align-items: center; justify-content: center; cursor: pointer; transition: filter 0.12s; }
.bs-hdr-nav:hover:not(:disabled), .bs-hdr-refrescar:hover:not(:disabled) { filter: brightness(0.95); border-color: #1f4a87; }
.bs-hdr-nav:disabled, .bs-hdr-refrescar:disabled { opacity: 0.55; cursor: not-allowed; }
.bs-hdr-nav i, .bs-hdr-refrescar i { font-size: 12px; line-height: 1; }
.bs-hdr-refrescar { margin-left: 8px; width: 24px; }
.bs-hdr-refrescar i.spinning { animation: bs-spin 0.9s linear infinite; }
.bs-hdr-inp { width: 60px; height: 20px; text-align: center; font-weight: 700; font-size: 12px; background: #fff; color: #1f4a87; border: 1px solid #c5cdd9; border-radius: 3px; padding: 0 4px; outline: none; -moz-appearance: textfield; appearance: textfield; }
.bs-hdr-inp:focus { border-color: #3874cb; box-shadow: 0 0 0 2px rgba(31,74,135,0.18); }
.bs-hdr-inp::-webkit-outer-spin-button, .bs-hdr-inp::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
/* FechaInput (§1.5) en la cabecera bs-*: el wrap del componente es width:100% y en un
   contenedor flex/inline se estira o salta de línea. WrapClass="bs-hdr-fecha" lo acota
   a lo que ocupa dd/MM/yyyy + icono (auditoría 2026-08-17, tarea #12). */
.fecha-input-wrap.bs-hdr-fecha { width: 7.2rem !important; flex: 0 0 auto; }   /* !important: gana al width:100% del scoped CSS del componente */
.bs-hdr-sel { height: 20px; font-size: 12px; font-weight: 600; color: #1f4a87; background: #fff; border: 1px solid #c5cdd9; border-radius: 3px; padding: 0 4px; outline: none; }
.bs-hdr-sel:focus { border-color: #3874cb; box-shadow: 0 0 0 2px rgba(31,74,135,0.18); }
.bs-hdr-chk { display: inline-flex; align-items: center; gap: 5px; margin-left: 10px; font-size: 11px; color: #1f4a87; font-weight: 600; cursor: pointer; white-space: nowrap; }
.bs-filtro-grp .bs-hdr-chk { margin-left: 0; }

/* ===== Banda de filtros ===== */
.bs-filtros-panel { display: flex; align-items: flex-end; flex-wrap: wrap; gap: 10px 16px; padding: 8px 14px; background: linear-gradient(180deg, #f6f9fd 0%, #e8eff8 100%); border-bottom: 1px solid #c9d4e2; }
.bs-filtro-grp { border: 1px solid #cdd8e6; border-radius: 5px; padding: 3px 10px 7px; margin: 0; background: #fff; display: flex; align-items: center; gap: 8px; }
.bs-filtro-grp legend { font-size: 10px; font-weight: 700; letter-spacing: 0.06em; color: #1f4a87 !important; padding: 0 4px; }

.op-pills-inline { display: inline-flex; align-items: center; gap: 6px; flex-wrap: nowrap; }
.op-pills-inline .op-pill { display: inline-flex; align-items: center; gap: 6px; height: 26px; padding: 0 12px; background: #fff; border: 1px solid #b9c6d6; border-radius: 13px; color: #1f4a87; cursor: pointer; transition: all 0.15s; font-size: 12px; font-weight: 500; white-space: nowrap; box-shadow: 0 1px 1px rgba(31,74,135,0.03); }
.op-pills-inline .op-pill i { font-size: 12px; }
.op-pills-inline .op-pill:hover:not(:disabled):not(.active) { background: #eaf2fb; border-color: #7ba4d6; color: #1f4a87; }
.op-pills-inline .op-pill.active { background: linear-gradient(180deg, #2f6ec1 0%, #1f4a87 100%); border-color: #1f4a87; color: #fff; font-weight: 600; box-shadow: inset 0 1px 0 rgba(255,255,255,0.20), 0 1px 3px rgba(31,74,135,0.20); }
.op-pills-inline .op-pill.active:hover:not(:disabled) { background: linear-gradient(180deg, #3580d0 0%, #2655a0 100%); border-color: #2655a0; }
.op-pills-inline .op-pill:disabled { opacity: 0.55; cursor: not-allowed; }

.bs-cuentas-rango { display: inline-flex; align-items: center; gap: 6px; }
.bs-cuenta-inp { width: 110px; text-align: left; font-weight: 600; letter-spacing: 0.02em; }
.bs-cuentas-sep { color: #7488a0; font-size: 12px; display: inline-flex; align-items: center; }

.bs-filtros-spacer { flex: 1 1 auto; }
.bs-filtros-calcular { display: inline-flex; align-items: center; gap: 6px; padding: 5px 16px; border: 1px solid #1a6b3d; border-radius: 5px; cursor: pointer; font-weight: 600; background: linear-gradient(180deg, #29a663 0%, #1a6b3d 100%); color: #fff; }
.bs-filtros-calcular:disabled { opacity: 0.5; cursor: not-allowed; }
.bs-filtros-calcular .spinning { animation: bs-spin 0.8s linear infinite; }
@keyframes bs-spin { to { transform: rotate(360deg); } }

/* ===== Panel + rejilla ===== */
.bs-single { flex: 1 1 auto; display: flex; align-items: flex-start; padding: 8px; min-height: 0; overflow: hidden; }
.bs-panel { display: flex; flex-direction: column; min-height: 0; min-width: 0; flex: 1 1 auto; border: 1px solid #c9ced4; border-radius: 6px; overflow: hidden; background: #fff; max-height: 100%; }
.bs-panel-title { display: flex; align-items: center; gap: 8px; padding: 6px 10px; background: linear-gradient(180deg, #1f4a87 0%, #14315c 100%); border-left: 3px solid #5fa8ff; color: #fff; }
.bs-panel-title i { color: rgba(255,255,255,0.78); }
.bs-panel-titletext { font-weight: 700; letter-spacing: 0.04em; flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bs-panel-total { font-weight: 700; font-variant-numeric: tabular-nums; }

.est-grid-scroll { flex: 1 1 auto; overflow: auto; outline: none; }
.est-grid { border-collapse: collapse; font-size: 12.5px; white-space: nowrap; width: 100%; }
.est-grid thead th { position: sticky; top: 0; z-index: 2; background: #e9eff7; color: #1f4a87; font-weight: 600; font-size: 11px; text-align: right; padding: 5px 9px; border-bottom: 1px solid #1f4a87; }
.est-grid thead th.est-c-cod, .est-grid thead th.est-c-nom, .est-grid thead th.est-c-com { text-align: left; }
.est-grid tbody td { padding: 3px 9px; border-bottom: 1px solid #eef2f7; text-align: right; font-variant-numeric: tabular-nums; }
.est-grid tbody td.est-c-cod, .est-grid tbody td.est-c-nom, .est-grid tbody td.est-c-com { text-align: left; }
.est-c-cod { color: #1f4a87; font-weight: 600; }
.est-c-nom { max-width: 280px; overflow: hidden; text-overflow: ellipsis; color: #3a4754; }
.est-c-com { max-width: 170px; overflow: hidden; text-overflow: ellipsis; color: #5a6470; }
.est-grid tbody tr:nth-child(even) td { background: #f8fafd; }
.est-grid tbody tr:hover td { background: #eef5ff; }
.est-grid tbody tr.est-total td { background: #eef3fb !important; font-weight: 700; color: #1f4a87; border-top: 1.5px solid #1f4a87; border-bottom: none; }
.est-pos { color: #1d6f42; }
.est-neg { color: #a31f1f; }
.est-vacio { padding: 28px; text-align: center; color: #7a838d; font-size: 13px; }

/* ===== Footer ===== */
.bs-footer { display: flex; align-items: center; gap: 8px; padding: 6px 12px; border-top: 1px solid #c9ced4; background: #f8fafd; flex-wrap: wrap; }
.bs-tot { display: flex; flex-direction: column; padding: 3px 12px; border: 0.6px solid #c9ced4; border-left: 3px solid #1f4a87; background: #fafdff; border-radius: 3px; min-width: 120px; }
.bs-tot-lbl { font-size: 8px; font-weight: 700; letter-spacing: 0.03em; color: #1f4a87; }
.bs-tot-val { font-size: 14px; font-weight: 700; color: #3a4754; font-variant-numeric: tabular-nums; }
.bs-tot-verde { border-left-color: #1d6f42; } .bs-tot-verde .bs-tot-lbl, .bs-tot-verde .bs-tot-val { color: #1d6f42; }
.bs-footer-spacer { flex: 1 1 auto; }

/* Boton Analisis IA — acento morado (igual que informes contables). */
.bbtn-analisis { background: linear-gradient(180deg, #7d5ba6 0%, #6a4c93 100%); border: 1px solid #5a3c83; color: #fff; }
.bbtn-analisis:hover:not(:disabled) { background: linear-gradient(180deg, #8d6bb6 0%, #5a3c83 100%); border-color: #4a2c73; }
.bbtn-analisis:disabled { opacity: 0.5; cursor: not-allowed; }
.bbtn-analisis i { color: #fff; margin-right: 5px; }

/* ===== Modal PDF preview ===== */
.pdf-preview-backdrop { position: fixed; inset: 0; background: rgba(15,30,55,0.45); z-index: 1200; display: flex; align-items: center; justify-content: center; }
.pdf-preview-panel { width: 92vw; height: 92vh; max-width: 1200px; background: #fff; border-radius: 8px; box-shadow: 0 8px 40px rgba(0,0,0,0.4); display: flex; flex-direction: column; overflow: hidden; }
.pdf-preview-header { display: flex; align-items: center; gap: 8px; padding: 8px 14px; background: linear-gradient(180deg, #2f6ec1 0%, #1f4a87 100%); color: #fff; font-weight: 600; }
.pdf-preview-spacer { flex: 1 1 auto; }
.pdf-preview-close { background: transparent; border: none; color: #fff; font-size: 22px; line-height: 1; cursor: pointer; padding: 0 4px; }
.pdf-preview-body { flex: 1 1 auto; min-height: 0; background: #525659; }
.pdf-preview-iframe { width: 100%; height: 100%; border: none; }
.pdf-preview-footer { display: flex; align-items: center; gap: 8px; padding: 8px 14px; border-top: 1px solid #c9ced4; background: #f8fafd; }

/* ═══════════════════════════════════════════════════════════════════════════
   NORMA 2026-08-16 (JJ) — `.lookup-modal` sube al RCL
   ═══════════════════════════════════════════════════════════════════════════
   `.lookup-modal` era canon de FACTO: 26 pantallas la escriben en el markup
   como raíz del diálogo (junto al `.lookup-backdrop`, que sí es global), pero
   NO estaba definida en ningún `app.css` — ni aquí ni en los de host. Cada
   pantalla se la copiaba en su `.razor.css`, y **sólo 9 lo hacían**.

   La pantalla que se olvidaba no daba error ni rompía el build: el contenedor
   se quedaba en flujo normal (`position: static`) DETRÁS del `.app-shell`
   (`height:100vh; overflow:hidden`), o sea el modal se abría íntegro por
   debajo del borde inferior de la ventana mientras el velo oscurecía la
   página. El usuario lo reporta como "el modal no se abre" / "se queda en
   segundo plano". Medido en el panel fiscal (ventana 1280×720): sin la regla
   `rect [0, 720, 900×626]`; con ella `fixed` + `[190, 50, 900×619]`, centrado.

   ── Especificidad DELIBERADAMENTE MÍNIMA (`.lookup-modal` a secas = 0-1-0) ──
   El CSS aislado de Blazor añade `[b-xxxxx]` a sus selectores, así que
   CUALQUIER definición de pantalla (0-2-0) sigue ganando. Este bloque sólo
   pinta a las pantallas que NO traen definición propia. NO convertirlo en
   `.app-shell .lookup-modal` ni en `div.lookup-modal` "para que sea más
   correcto": pasaría a PISAR a las 9 pantallas que ya la definen.

   Las propiedades se han elegido de forma que las 9 pantallas con definición
   propia las declaran TODAS (no hay fuga de propiedad a ninguna de ellas):
   position/top/left/transform, z-index, display+flex-direction, background,
   border, border-radius y box-shadow. `max-width`/`max-height` los declaran 7
   en la raíz y las otras 2 (PanelFiscal, Declaración) en su clase de ancho,
   que es 0-2-0 y gana. A propósito NO se declaran aquí:
     · `width`  — el ancho lo pone cada pantalla (`.ayuda-modal`,
                  `.config-cols-modal`, `.pf-modelos-modal`, `style="width:…"`).
     · `min-width` — 2 de las 9 no lo declaran y lo heredarían.
     · `font-size` / `overflow` — idem; `overflow` además duplicaría scrollbars
       con el `.ayuda-body { flex:1; overflow:auto }` de arriba.

   Valores = variante MAYORITARIA del árbol (7 de las 9 copias existentes).
   z-index 1102, el mismo que `.lookup-dialog`: el `.lookup-backdrop` es 1000
   aquí pero la sección de revisión/punteo lo sube a 1100 (aprob. crítica #42),
   así que 1001 dejaría el modal DEBAJO del velo. */
.lookup-modal {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    flex-direction: column;
    background: #fff;
    border: 1px solid #b9c6d6;
    border-radius: 4px;
    box-shadow: 0 12px 36px rgba(15, 30, 55, 0.30);
    z-index: 1102;
    max-width: 92vw;
    max-height: 86vh;
}

/* ═══════════════════════════════════════════════════════════════════════════
   CANON VISUAL SUBIDO AL RCL — banda de herramientas (`tb-slate`) y su botón
   (`tb-btn`). Norma aprobada por el cliente (JJ) el 2026-08-17.

   POR QUÉ ESTÁ AQUÍ. Estas dos clases eran «canon de facto»: las escriben
   decenas de pantallas en su markup, pero NINGUNA estaba definida en esta
   hoja, así que cada pantalla se las redefinía en su CSS aislado — y la que
   se olvidaba **mostraba los botones con el gris y el borde `outset` NATIVOS
   del navegador**, el look de sistema que el canon destierra. Caso real que
   destapó la norma: siete pantallas de tesorería con banda clara salían así,
   y dos (Mandatos e Importación) además con la banda transparente porque
   usaban `tb-slate` sin declararla. Se llegó a tener `.tb-btn` duplicado en
   11 ficheros y `.tb-slate` en 4.

   ⚠ REGLA DE ESPECIFICIDAD — LEER ANTES DE TOCAR ESTE BLOQUE.
   Los selectores se mantienen DELIBERADAMENTE MÍNIMOS (`.tb-slate` y
   `.tb-btn` = 0-1-0) para que cualquier definición local los gane SIEMPRE:
   el CSS aislado de Blazor añade `[b-xxxxx]`, así que el `.xx-toolbar .tb-btn`
   que ya tienen las pantallas vale 0-3-0 y pisa a lo de aquí sin discusión.
   Consecuencia buscada: este bloque **sólo pinta las pantallas que NO traen
   definición propia** — las que ya la tienen no cambian ni un píxel. Es el
   mismo criterio que el bloque de importes/totalbox de más arriba.

   NO subir la especificidad, y en particular NO escribir
   `.app-toolbar .tb-btn`: pasaría a pisar a toda pantalla que declare su
   propio botón de banda.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Banda de herramientas oscura: la cinta bajo la ContextoBar donde viven los
   botones de acción de la pantalla. */
.tb-slate {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    padding: 5px 10px;
    background: linear-gradient(180deg, #2c3d55 0%, #24344a 100%);
    border-bottom: 1px solid #1b2838;
    color: #eaf0f8;
}

/* Botón de la banda. Sirve tanto en banda clara (fondo blanco, texto azul)
   como dentro de `.tb-slate`, donde la regla de abajo lo invierte. */
.tb-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    height: 26px;
    min-width: 28px;
    padding: 0 8px;
    border: 1px solid #c8d2df;
    border-radius: 4px;
    background: #fff;
    color: #1f4a87;
    font-size: 13.5px;
    line-height: 1;
    cursor: pointer;
    transition: filter .12s, border-color .12s;
}
.tb-btn:hover:not(:disabled) { filter: brightness(.96); border-color: #1f4a87; }
.tb-btn:disabled { opacity: .55; cursor: not-allowed; }
.tb-btn i { font-size: 14px; line-height: 1; }

/* Dentro de la banda oscura el botón va translúcido, no blanco. */
.tb-slate .tb-btn {
    background: rgba(255, 255, 255, .10);
    border-color: rgba(255, 255, 255, .28);
    color: #eaf0f8;
}
.tb-slate .tb-btn:hover:not(:disabled) {
    background: rgba(255, 255, 255, .18);
    border-color: rgba(255, 255, 255, .45);
}

/* ═══════════════════════════════════════════════════════════════════════════
   FASE DEL LOTE DE FACTURACIÓN — CALCULADO · PRESENTADO · IMPRESO
   Petición de Angel (2026-08-23): «puedes darle un color diferente a ese
   identificador para saber si están calculado, presentado e impreso».

   Vive AQUÍ, en el app.css canónico del RCL, y no en el scoped CSS de ninguna
   pantalla, porque lo pintan TRES sitios —la bandeja de gestión de lotes, la
   cabecera de la pantalla del lote y la columna «Lote» de los listados de
   facturas, que además está en otro host— y con tres copias acabarían
   discrepando (§3.4 / §6.9). El nombre de la clase lo dice el contrato
   (LoteFase.Clase), así que tampoco se puede escribir mal a mano.

   La lectura del color es la de siempre en NetOffice:
     ámbar  = pendiente de que alguien haga algo   (calculado)
     azul   = en marcha, ya es oficial             (presentado)
     verde  = terminado                            (impreso)
     rojo   = no salió                             (sin emitir)
     gris   = fuera del circuito                   (deshecho / sin facturas)
   El rayado diagonal marca los lotes A MEDIAS: la fase no sube hasta que
   llegan todas sus facturas, y el rayado lo dice de un vistazo.
   ═════════════════════════════════════════════════════════════════════════ */
.lote-badge {
    display: inline-flex; align-items: center; gap: 5px;
    max-width: 100%;
    padding: 1px 8px;
    border: 1px solid transparent; border-radius: 10px;
    font-size: 11px; font-weight: 700; line-height: 17px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    vertical-align: middle;
}
.lote-badge > i { font-size: 10.5px; line-height: 1; }

.lote-fase-calculado  { background: #fff4dd; border-color: #e6c98a; color: #7c5b12; }
.lote-fase-presentado { background: #e7f0fb; border-color: #9dbde4; color: #1f4a87; }
.lote-fase-impreso    { background: #e8f6ea; border-color: #9ccfa6; color: #1f5c2a; }
.lote-fase-sinemitir  { background: #fdeeee; border-color: #d8a7a7; color: #8d1f1f; }
.lote-fase-deshecho   { background: #eef1f5; border-color: #c3ccd8; color: #5a6b80; }
.lote-fase-vacio      { background: #eef1f5; border-color: #c3ccd8; color: #7a8798; }

/* A MEDIAS — mismo color de fase, con rayado: «va por la mitad». */
.lote-badge.is-parcial {
    background-image: repeating-linear-gradient(
        135deg, rgba(255,255,255,.55) 0 5px, rgba(255,255,255,0) 5px 10px);
    border-style: dashed;
}

/* El IDENTIFICADOR del lote (el «nº 31» que Angel quiere reconocer de un
   vistazo) — se pinta con el color de su fase, así que el número y el estado
   son la misma cosa y no pueden decir cosas distintas. */
.lote-chip {
    display: inline-flex; align-items: center; gap: 4px;
    padding: 0 7px; border: 1px solid transparent; border-radius: 9px;
    font-size: 11px; font-weight: 700; line-height: 17px;
    font-variant-numeric: tabular-nums; white-space: nowrap;
    cursor: pointer;
}
/* El chip es un <button>: el navegador le pone su fondo gris de control y hay
   que apagarlo. Se hace AQUÍ ABAJO y repitiendo el color de la fase, no con un
   `background: none` dentro de `.lote-chip`: aquella versión pisaba el color
   —las reglas `.lote-fase-*` están más arriba y a igual especificidad gana la
   última—, y el identificador salía transparente. Se vio en la prueba real:
   los lotes deshechos aparecían sin su gris. */
.lote-chip:not([class*="lote-fase-"]) { background: none; }
.lote-chip.lote-fase-calculado  { background-color: #fff4dd; border-color: #e6c98a; color: #7c5b12; }
.lote-chip.lote-fase-presentado { background-color: #e7f0fb; border-color: #9dbde4; color: #1f4a87; }
.lote-chip.lote-fase-impreso    { background-color: #e8f6ea; border-color: #9ccfa6; color: #1f5c2a; }
.lote-chip.lote-fase-sinemitir  { background-color: #fdeeee; border-color: #d8a7a7; color: #8d1f1f; }
.lote-chip.lote-fase-deshecho   { background-color: #eef1f5; border-color: #c3ccd8; color: #5a6b80; }
.lote-chip.lote-fase-vacio      { background-color: #eef1f5; border-color: #c3ccd8; color: #7a8798; }
.lote-chip:hover { filter: brightness(.95); text-decoration: none; }
.lote-chip:disabled, .lote-chip.no-clic { cursor: default; }
.lote-chip > i { font-size: 10px; }

/* ═══════════════════════════════════════════════════════════════════════════
   TRATAMIENTO DE CELDA DE LOS GRIDS DEL TMS  (prefijo `gc-` = grid cell)
   ═══════════════════════════════════════════════════════════════════════════
   Petición de Angel (2026-08-23): «el estilo y diseño de las columnas del grid,
   tanto en la selección de viajes para facturar como en los viajes que forman
   parte de una factura, quiero que tengan este estilo [el de Consulta de
   viajes], para mantener ese mismo entorno y presentación de los datos».

   Los valores son los de `ConsultaViajes.razor.css`, movidos aquí SIN CAMBIAR
   NI UN NÚMERO — la pantalla de referencia tiene que quedar exactamente igual
   que estaba. Viven en el RCL y no en el scoped CSS de una pantalla porque el
   scoped CSS NO se hereda entre componentes: cada consumidor tendría que
   copiarlo, y a la tercera copia el diseño ya habría divergido (§3.4 «objeto
   base + overrides por pantalla»).

   Consumidores: Consulta de viajes · entorno de facturación (grid PEDIDOS/
   VIAJES) · emergente «Pedidos de la factura». PENDIENTES de migrar (siguen
   con su copia scoped de la cápsula de fecha, que nació antes que este
   bloque): el panel Gestión TMS de vehículos y Pedidos semanal — cuando se
   toquen, cambiar su `.fecha-badge` propia por <CeldaFecha> y borrar la copia.

   La LÓGICA que decide el color de una fecha, o de dónde sale el ISO del país,
   es común y vive junto a estas clases: `NetOffice.Web.Forms.Celdas.GridCelda`
   y los componentes <CeldaFecha> / <CeldaLugar>.

   Nota de especificidad: son reglas GLOBALES (sin atributo de scope), así que
   cualquier regla scoped de la pantalla les gana. Es lo que se quiere: la fila
   seleccionada, los tintes de fila y los avisos funcionales de cada pantalla
   siguen mandando sobre el color base de la celda.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Fecha en cápsula con semáforo ────────────────────────────────────────
   LA MISMA CAJA para carga y descarga («que se vean hermanas»); lo único que
   cambia entre columnas es el CRITERIO de color. */
.gc-fecha {
    display: inline-flex; align-items: center; justify-content: center;
    padding: 1px 6px; border-radius: 5px; font-size: 11px; font-weight: 600;
    white-space: nowrap; letter-spacing: .1px;
}
/* Color POR FECHA: vencida · hoy · futura. */
.gc-fecha-pasada { background: #f2b3b3; color: #5c1414; box-shadow: inset 0 0 0 1px rgba(140,20,20,.25); }
.gc-fecha-hoy    { background: #ffffff; color: #333;    box-shadow: inset 0 0 0 1px #cfd6de; }
.gc-fecha-futura { background: #bfe6bf; color: #17481a; box-shadow: inset 0 0 0 1px rgba(20,90,25,.2); }
/* Color POR SEMÁFORO ETA (manda sobre el color por fecha cuando lo hay):
   verde llega con margen · ámbar justo · rojo tarde. */
.gc-fecha-eta-ok    { background: #d9f2df; color: #14682f; box-shadow: inset 0 0 0 1px rgba(20,104,47,.25); }
.gc-fecha-eta-justo { background: #fdeccb; color: #8a5b06; box-shadow: inset 0 0 0 1px rgba(138,91,6,.28); }
.gc-fecha-eta-tarde { background: #fadbdb; color: #a11212; box-shadow: inset 0 0 0 1px rgba(161,18,18,.28); }

/* ── Distintivo de país delante del lugar (estilo placa euro) ───────────── */
.gc-pais {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 18px; padding: 0 3px; margin-right: 4px;
    border-radius: 3px; background: #039; color: #fff;
    font-size: 9px; font-weight: 800; letter-spacing: .4px; line-height: 13px;
    vertical-align: middle; cursor: default;
}

/* ── Celda de LUGAR (Origen / Destino): azul oscuro seminegrita ─────────── */
td.gc-lugar { font-weight: 600; color: #1f3a5f; }

/* ── Celda de IMPORTE: verde «dinero» seminegrita ────────────────────────
   La alineación a la derecha con cifras de ancho fijo NO se repite aquí: ya la
   da `td.num` (bloque «Importes en celdas de tabla» de más arriba), que es el
   canon del proyecto. Se combinan: `class="num gc-importe"`. */
td.gc-importe { font-weight: 700; color: #166534; }

/* ── Nº de pedido / viaje: cápsula azul clicable + mini-botones pegados ───
   `flex: 0 0 auto` en la cápsula: es hija flex del envoltorio y con el
   `flex-shrink` por defecto se ENCOGÍA hasta recortar números de 9 cifras. */
.gc-idwrap { display: inline-flex; align-items: center; gap: 1px; white-space: nowrap; }
/* La celda que aloja las cápsulas: manda su contenido, así que va a la
   izquierda (no a la derecha como un importe) y, cuando lleva varias —un
   pedido respaldado por varios viajes—, se separan entre sí. */
td.gc-idcell { text-align: left; }
td.gc-idcell .gc-pill-id + .gc-pill-id { margin-left: 3px; }
.gc-pill-id {
    display: inline-flex; align-items: center; justify-content: center;
    flex: 0 0 auto;
    min-width: 0; padding: 1px 5px; border-radius: 8px;
    background: #e8eef7; color: #24487f; font-weight: 600; font-size: 11.5px;
    box-shadow: inset 0 0 0 1px #cdd9ec;
    cursor: pointer;
    white-space: nowrap;
}
.gc-pill-id:hover { background: #d6e5fa; box-shadow: inset 0 0 0 1px #7fa8dc; text-decoration: underline; }
/* Variante NO clicable: mismo dibujo, sin afordancia. Para el nº de viaje en
   pantallas donde no hay ficha a la que ir — una cápsula con manita que no
   lleva a ningún sitio es peor que no tener cápsula. */
.gc-pill-id.gc-pill-plain { cursor: default; }
.gc-pill-id.gc-pill-plain:hover { background: #e8eef7; box-shadow: inset 0 0 0 1px #cdd9ec; text-decoration: none; }
/* Mini-botón de fila (17px): blanco con borde, azul para «situación», ámbar
   para ETA y rojo para la geo del pedido. */
.gc-mini-btn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 17px; height: 16px; border: 1px solid #c9d8ee; border-radius: 4px;
    background: #fff; color: #1f4a87; cursor: pointer; font-size: .55rem;
    padding: 0; vertical-align: middle; flex: 0 0 auto;
}
.gc-mini-btn:hover { background: #1f4a87; color: #fff; }
.gc-mini-btn.gc-mini-eta { border-color: #ecd9b0; color: #b45309; }
.gc-mini-btn.gc-mini-eta:hover { background: #b45309; color: #fff; }
.gc-mini-btn.gc-mini-geo-ped { border-color: #e6bcbc; color: #c0392b; }
.gc-mini-btn.gc-mini-geo-ped:hover { background: #c0392b; color: #fff; }

/* ── Fila SELECCIONADA de un grid del TMS ────────────────────────────────
   El canon del RCL (`.grid-table tbody tr.selected`) pinta azul SÓLIDO con
   texto blanco. En los grids que llevan tintes funcionales (pendiente, sin
   importe, excluido…) ese azul los tapa, así que la marca es un azul PÁLIDO
   con marco inset y —esto es lo que se olvidaba— el texto vuelve a OSCURO en
   TODA la fila: pisar sólo el fondo deja el `color:#fff` heredado y la fila se
   lee «toda en blanco» (Angel, dos veces: 2026-08-22 y 2026-08-23).
   Se aplica poniendo `gc-sel` en la <table>. */
.gc-sel tbody tr.selected { background: #dcebff; color: #10243f; }
.gc-sel tbody tr.selected td {
    color: #10243f; font-weight: 600;
    box-shadow: inset 0 1px 0 #1f5fbf, inset 0 -1px 0 #1f5fbf;
}
.gc-sel tbody tr.selected td:first-child {
    box-shadow: inset 1px 0 0 #1f5fbf, inset 0 1px 0 #1f5fbf, inset 0 -1px 0 #1f5fbf;
}
.gc-sel tbody tr.selected td:last-child {
    box-shadow: inset -1px 0 0 #1f5fbf, inset 0 1px 0 #1f5fbf, inset 0 -1px 0 #1f5fbf;
}
/* El hover NO se pinta sobre la fila seleccionada: al pasar el ratón por
   encima de la que acabas de clicar, el fondo pálido del hover ganaba al de la
   selección y el texto (blanco por el canon) desaparecía. */
.gc-sel tbody tr.selected:hover { background: #dcebff; }

/* ===== Campo clave alfanumérico con botón de alta — CLAUDE.md §2.21b =====
   La única vía de alta en NetOffice es teclear en el campo clave un código que
   no exista (§2.21 regla 6 prohíbe el botón "Nuevo" del toolbar). En las claves
   NUMÉRICAS los 2 botones de §2.21 insinúan que ahí ocurre algo; en las
   ALFANUMÉRICAS no había NADA — censo del 2026-08-31: de 58 inputs de clave
   alfanumérica, 0 con title= y 1 con placeholder (y era un ejemplo de valor).

   El wrap y el botón son los MISMOS de §2.21 (`.clave-num-wrap` /
   `.clave-num-btn`): así una clave alfanumérica y una numérica se ven por fin
   igual. Aquí sólo se ajusta el <input>, que a diferencia del numérico no es
   estrecho ni va alineado a la derecha — se come el ancho disponible y cede su
   borde/fondo al wrap, que es el "campo aparente" (§2.21 regla 9). */
.clave-field-wrap {
    width: 100%;
    /* El botón se lleva 22px. Sin este min-width el input se quedaba con lo que
       sobrara de una columna ya colapsada: la col 2 del form-grid es
       `minmax(60px, 90px)` y con el grid apretado vale 60px, así que el input
       de clave caía de 60px a 36px — una REGRESIÓN, y en pantallas como Grupos
       esa clave admite 45 caracteres. Pidiendo 88px la columna sube a su máximo
       (90px, ya previsto por el grid: no desborda ni empuja a las vecinas) y el
       input queda en ~66px, algo MÁS ancho que antes de añadir el botón. */
    min-width: 88px;
}
/* `> input` y no `> .inp`: Transporte tiene su propio sistema de clases
   (`ip clv`) y con `.inp` el input no cedía su borde al wrap — saldría una
   cápsula dentro de otra. */
/* Botón de alta: cruz BLANCA sobre pastilla VERDE. Pisa a `.clave-num-btn`
   (transparente + azul), que es correcto para los botones de auto-numeración
   de §2.21 pero dejaba el de alta como una manchita gris a 11px. El verde es
   el mismo que el proyecto ya usa para "alta" en EfectoCarteraDialog. */
.clave-nuevo-btn {
    background: linear-gradient(180deg, #34ac6c 0%, #268a55 100%);
    color: #fff;
    border-left: 1px solid #1f7347;
    width: 24px;
}
.clave-nuevo-btn:hover  { background: linear-gradient(180deg, #3cbd78 0%, #2c9a5f 100%); }
.clave-nuevo-btn:active { background: linear-gradient(180deg, #23814f 0%, #1c6b41 100%); }
/* La cruz manda sobre el tamaño de icono de `.clave-num-btn i` (11px): a 11px
   sobre verde se leía como un punto. */
.clave-nuevo-btn i { font-size: 13px; font-weight: 700; color: #fff; }

.clave-field-wrap > input {
    flex: 1 1 auto;
    min-width: 0;
    width: auto;
    height: 20px;
    border: none;
    background: transparent;
    box-shadow: none;
    outline: none;          /* el focus lo pinta el wrap (:focus-within) */
}
