/* ═══════════════════════════════════════
   LAYOUT PRINCIPAL - app.css
══════════════════════════════════════ */

:root {
    color-scheme: light;
    --sidebar-width: 260px;
    --navbar-height: 60px;

    --app-bg: #f1f5f9;
    --app-surface: #ffffff;
    --app-surface-rgb: 255, 255, 255;
    --app-surface-soft: #f8fafc;
    --app-surface-elevated: #ffffff;
    --app-text: #0f172a;
    --app-muted: #64748b;
    --app-border: #e2e8f0;
    --app-border-strong: #cbd5e1;
    --app-primary: #2563eb;
    --app-primary-soft: #dbeafe;
    --app-link: #2563eb;
    --app-shadow: 0 10px 30px rgba(15, 23, 42, 0.06);
    --app-focus-ring: rgba(37, 99, 235, 0.22);

    --sidebar-bg: #1e293b;
    --sidebar-hover: #334155;
    --sidebar-active: #3b82f6;
    --sidebar-text: #cbd5e1;
    --sidebar-muted: #94a3b8;
    --sidebar-tree: rgba(203, 213, 225, .3);
    /* El nombre de la empresa y el ítem de menú activo/al pasar el mouse:
       siempre blanco por defecto, pero con un sidebar propio muy claro
       (Apariencia por empresa) el partial los pisa con uno oscuro. */
    --sidebar-ink: #ffffff;
    --sidebar-active-ink: #ffffff;
    --table-header-bg: var(--sidebar-bg);
    --table-header-border: var(--sidebar-hover);
    --table-striped-bg: #f8fafc;
    --table-selection-bg: #dbeafe;
    --table-selection-color: #0f172a;
}

[data-bs-theme="dark"] {
    color-scheme: dark;
    --bs-body-bg: #0b1120;
    --bs-body-color: #e5e7eb;
    --bs-emphasis-color: #f8fafc;
    --bs-secondary-color: #94a3b8;
    --bs-tertiary-bg: #111827;
    --bs-border-color: #243044;
    --bs-link-color: #93c5fd;
    --bs-link-hover-color: #bfdbfe;

    --app-bg: #0b1120;
    --app-surface: #111827;
    --app-surface-rgb: 17, 24, 39;
    --app-surface-soft: #162033;
    --app-surface-elevated: #172033;
    --app-text: #f1f5f9;
    --app-muted: #b6c2d2;
    --app-border: #243044;
    --app-border-strong: #334155;
    --app-primary: #60a5fa;
    --app-primary-soft: rgba(96, 165, 250, 0.16);
    --app-link: #93c5fd;
    --app-shadow: 0 0 0 1px rgba(255, 255, 255, 0.07), 0 18px 50px rgba(0, 0, 0, 0.34), 0 0 28px rgba(255, 255, 255, 0.045);
    --app-focus-ring: rgba(96, 165, 250, 0.28);

    --sidebar-bg: #020617;
    --sidebar-hover: #111827;
    --sidebar-active: #2563eb;
    --sidebar-text: #cbd5e1;
    --sidebar-muted: #94a3b8;
    --sidebar-tree: rgba(203, 213, 225, .22);
    --table-header-bg: #111827;
    --table-header-border: #334155;
    --table-striped-bg: rgba(148, 163, 184, 0.06);
    --table-selection-bg: rgba(96, 165, 250, 0.18);
    --table-selection-color: #e5e7eb;
}

body {
    background-color: var(--app-bg);
    color: var(--app-text);
    font-family: Inter, ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
}

/* Global tables: sidebar-colored headers + subtle striped rows. */
.table:not(.table-borderless) > thead,
.table:not(.table-borderless) > thead.table-light,
.table:not(.table-borderless) > thead.table-dark,
.table:not(.table-borderless) > thead > tr,
.table:not(.table-borderless) > thead > tr > th,
.table:not(.table-borderless) > thead > tr > td {
    --bs-table-bg: var(--table-header-bg);
    --bs-table-color: #fff;
    background-color: var(--table-header-bg) !important;
    border-color: var(--table-header-border) !important;
    color: #fff !important;
}

.table:not(.table-borderless) > thead > tr > th a,
.table:not(.table-borderless) > thead > tr > td a {
    color: #fff !important;
}

.table:not(.table-borderless) > tbody > tr:nth-of-type(odd) > * {
    --bs-table-bg-type: var(--table-striped-bg);
}


.table > tbody > tr.table-primary,
.table > tbody > tr.table-active,
.table > tbody > tr.selected {
    --bs-table-bg: var(--table-selection-bg) !important;
    --bs-table-striped-bg: var(--table-selection-bg) !important;
    --bs-table-active-bg: var(--table-selection-bg) !important;
    --bs-table-hover-bg: var(--table-selection-bg) !important;
    --bs-table-color: var(--table-selection-color) !important;
    --bs-table-striped-color: var(--table-selection-color) !important;
    --bs-table-active-color: var(--table-selection-color) !important;
    --bs-table-hover-color: var(--table-selection-color) !important;
}

.table > tbody > tr.table-primary > *,
.table > tbody > tr.table-active > *,
.table > tbody > tr.selected > *,
.table.table-hover > tbody > tr.table-primary:hover > *,
.table.table-hover > tbody > tr.table-active:hover > *,
.table.table-hover > tbody > tr.selected:hover > * {
    --bs-table-color-state: var(--table-selection-color) !important;
    --bs-table-color-type: var(--table-selection-color) !important;
    --bs-table-bg-state: var(--table-selection-bg) !important;
    --bs-table-bg-type: var(--table-selection-bg) !important;
    --bs-table-accent-bg: var(--table-selection-bg) !important;
    color: var(--table-selection-color) !important;
    background-color: var(--table-selection-bg) !important;
    box-shadow: inset 0 0 0 9999px var(--table-selection-bg) !important;
}


/* --- Sidebar --- */
#sidebar {
    position: fixed;
    top: 0;
    left: 0;
    width: var(--sidebar-width);
    height: 100vh;
    /* En el iPhone, `100vh` cuenta la pantalla ENTERA, barra de Safari
       incluida: el menú quedaba más largo que lo visible y su último botón
       caía debajo de la barra. `dvh` mide lo que de verdad se ve. */
    height: 100dvh;
    background: var(--sidebar-bg);
    z-index: 1000;
    overflow-y: auto;
    /* Ocultar scrollbar */
    scrollbar-width: none;
    -ms-overflow-style: none;
}
#sidebar::-webkit-scrollbar {
    display: none;
}
 
.sidebar-nav {
    padding: 1rem 0;
}

.sidebar-brand {
    height: var(--navbar-height);
    display: flex;
    align-items: center;
    padding: 0 1.25rem;
    border-bottom: 1px solid var(--sidebar-hover);
    color: var(--sidebar-ink);
    font-weight: 700;
    font-size: 1.1rem;
    white-space: nowrap;
}

.sidebar-brand i {
    font-size: 1.4rem;
    color: var(--sidebar-active);
    margin-right: 10px;
    flex-shrink: 0;
}

.sidebar-nav {
    flex: 1;
    padding: 1rem 0;
}

.sidebar-nav .nav-section {
    padding: 0.5rem 1rem 0.25rem;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--sidebar-muted);
    white-space: nowrap;
}

.sidebar-nav .nav-link {
    display: flex;
    align-items: center;
    padding: 0.6rem 1.25rem;
    color: var(--sidebar-text);
    border-radius: 0;
    white-space: nowrap;
    transition: all 0.2s;
    font-size: 0.9rem;
}

.sidebar-nav .nav-link i {
    font-size: 1.1rem;
    width: 24px;
    flex-shrink: 0;
    margin-right: 10px;
}

.sidebar-nav .nav-link:hover {
    background: var(--sidebar-hover);
    color: var(--sidebar-ink);
}

.sidebar-nav .nav-link.active {
    background: var(--sidebar-active);
    color: var(--sidebar-active-ink);
}

/* ── Árbol de submenús ──
   La sangría sola no dejaba ver qué cuelga de qué. La guía se dibuja con
   pseudo-elementos sobre la clase ps-4 que ya llevan los subenlaces, así que
   cualquier submenú que se agregue después la hereda sin tocar el HTML.
   Cubre los dos casos que hay: los que viven dentro de un .collapse y los
   sueltos, como «Soportes físicos» bajo Contratos. */
.sidebar-nav .nav-link.ps-4 {
    position: relative;
    padding-left: 2.75rem !important;
}

/* El tramo vertical de la rama. */
.sidebar-nav .nav-link.ps-4::before {
    content: '';
    position: absolute;
    left: 2rem;
    top: 0;
    bottom: 0;
    border-left: 1px solid var(--sidebar-tree);
}

/* En el último de cada grupo la vertical llega sólo hasta el centro: eso es
   lo que dibuja el codo del final. Si el navegador no entiende :has(), la
   línea sigue de largo y no se rompe nada. */
.sidebar-nav .nav-link.ps-4:not(:has(+ .nav-link.ps-4))::before {
    bottom: 50%;
}

/* El brazo horizontal hasta el icono. */
.sidebar-nav .nav-link.ps-4::after {
    content: '';
    position: absolute;
    left: 2rem;
    top: 50%;
    width: 0.75rem;
    border-top: 1px solid var(--sidebar-tree);
}

/* La rama de la pantalla en la que estás se enciende. */
.sidebar-nav .nav-link.ps-4.active::before,
.sidebar-nav .nav-link.ps-4.active::after {
    border-color: rgba(255, 255, 255, .55);
}

/* La flecha del menú padre apunta a la derecha cuando está cerrado y hacia
   abajo cuando está abierto, como en cualquier árbol. */
.sidebar-nav .nav-link[data-bs-toggle="collapse"] .bi-chevron-down {
    transition: transform 0.2s ease;
}

.sidebar-nav .nav-link[data-bs-toggle="collapse"][aria-expanded="false"] .bi-chevron-down {
    transform: rotate(-90deg);
}

/* ── Navbar ── */
#navbar {
    position: fixed;
    top: 0;
    left: var(--sidebar-width);
    right: 0;
    height: var(--navbar-height);
    background: var(--app-surface);
    border-bottom: 1px solid var(--app-border);
    display: flex;
    align-items: center;
    padding: 0 1.5rem;
    z-index: 999;
    transition: left 0.3s;
}

.dashboard-forge-branding {
    display: inline-flex;
    align-items: center;
    min-width: 0;
    flex: 0 1 auto;
}

.forge-brand {
    display: inline-flex;
    align-items: center;
    align-self: center;
    min-height: 28px;
    font-size: 1.32rem;
    font-weight: 900;
    line-height: 1;
    letter-spacing: 0;
    color: #06233b;
    text-shadow:
        0 1px 0 rgba(255, 255, 255, .9),
        0 2px 4px rgba(15, 23, 42, .22);
    -webkit-text-fill-color: #06233b;
    -webkit-text-stroke: .35px rgba(3, 7, 18, .18);
    white-space: nowrap;
}

[data-bs-theme="dark"] .forge-brand {
    background: linear-gradient(90deg, #f8fafc 0%, #facc15 48%, #f87171 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    -webkit-text-stroke: 0;
}
/* ── Main content ── */
#main-content {
    margin-left: var(--sidebar-width);
    margin-top: var(--navbar-height);
    padding: 1.5rem;
    min-height: calc(100vh - var(--navbar-height));
    min-height: calc(100dvh - var(--navbar-height));
    transition: margin-left 0.3s;
}

/* --- Responsive mobile menu button --- */
.mobile-menu-btn { display: none; }

/* Navbar responsive */
@media (max-width: 768px) {
    .mobile-menu-btn { display: block !important; }

    #navbar {
        padding: 0.5rem 1rem !important;
    }

    #navbar .badge {
        font-size: 0.65rem !important;
        padding: 0.2rem 0.4rem !important;
    }

    #navbar .btn-sm {
        font-size: 0.75rem !important;
        padding: 0.25rem 0.5rem !important;
    }

    .forge-brand {
        font-size: 1rem;
    }

    /* El menú entra deslizándose desde el borde, no apareciendo de golpe.
       Antes se animaba el ancho de 0 a 260px y sin transición: el contenido
       quedaba recortado y el menú aparecía y desaparecía de un salto.
       Moviéndolo con `transform` el navegador lo desliza sin recalcular nada.

       `visibility` se apaga al terminar de salir (por eso el retardo) para
       que el menú cerrado no se pueda alcanzar con el tabulador ni lo lea un
       lector de pantalla. */
    #sidebar {
        width: var(--sidebar-width);
        height: 100vh;
        height: 100dvh;
        transform: translateX(-100%);
        visibility: hidden;
        transition: transform .25s ease, visibility 0s linear .25s;
        z-index: 9999;
    }
    #sidebar.open {
        transform: translateX(0);
        visibility: visible;
        transition: transform .25s ease, visibility 0s;
    }

    #navbar  { left: 0; }
    #main-content { margin-left: 0; }

    /* La sombra de fondo se funde con el menú en vez de aparecer de golpe:
       sigue presente siempre y lo que cambia es la opacidad. */
    #sidebar-overlay {
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: rgba(0,0,0,0.5);
        z-index: 9998;
        opacity: 0;
        pointer-events: none;
        transition: opacity .25s ease;
    }
    #sidebar-overlay.show {
        opacity: 1;
        pointer-events: auto;
    }

    /* A quien le molesta el movimiento, sin movimiento. */
    @media (prefers-reduced-motion: reduce) {
        #sidebar, #sidebar-overlay { transition: none; }
    }

    #navbar > button {
        display: block !important;
    }
}


/* AJAX search/autocomplete results */
.cliente-results {
    background-color: var(--app-surface) !important;
    border-color: var(--app-border) !important;
    color: var(--app-text);
}
.cliente-results .cliente-option {
    color: var(--app-text);
    transition: background-color .12s ease, color .12s ease;
}
.cliente-results .cliente-option:hover,
.cliente-results .cliente-option:focus,
.cliente-results .cliente-option.active {
    background-color: rgba(13, 110, 253, .10);
    color: var(--app-text);
}
[data-bs-theme="dark"] .cliente-results {
    background-color: var(--app-surface) !important;
    border-color: var(--app-border-strong) !important;
    box-shadow: 0 16px 36px rgba(0,0,0,.38) !important;
}
[data-bs-theme="dark"] .cliente-results .cliente-option {
    color: var(--app-text);
    border-color: var(--app-border) !important;
}
[data-bs-theme="dark"] .cliente-results .cliente-option:hover,
[data-bs-theme="dark"] .cliente-results .cliente-option:focus,
[data-bs-theme="dark"] .cliente-results .cliente-option.active {
    background-color: var(--app-surface-soft) !important;
    color: #f8fafc !important;
}

/* ── Select2 overrides ── */
.select2-container--bootstrap5 {
    width: 100% !important;
}
.select2-container--bootstrap5 .select2-selection {
    min-height: calc(1.5em + 0.75rem + 2px);
    padding: 0.375rem 2.25rem 0.375rem 0.75rem;
    font-size: 1rem;
    border-radius: 0.375rem;
    border: 1px solid #dee2e6;
    display: flex;
    align-items: center;
}
.select2-container--bootstrap5 .select2-selection__rendered {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.select2-container--bootstrap5.select2-container--focus .select2-selection {
    border-color: #86b7fe;
    box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
}

/* ── Context menu ── */
.ctx-item {
    display: block;
    width: 100%;
    padding: 0.25rem 1rem;
    clear: both;
    font-weight: 400;
    color: #212529;
    text-align: inherit;
    text-decoration: none;
    white-space: nowrap;
    background-color: transparent;
    border: 0;
    cursor: pointer;
}
.ctx-item:hover, .ctx-item:focus {
    color: #1e2128;
    background-color: #e9ecef;
}

/* ── Collapse icon ── */
.collapse-icon { transition: transform 0.2s ease; }
.collapse-icon.collapsed { transform: rotate(-90deg); }

/* ── Card clickable ── */
.card-clickable { cursor: pointer; transition: transform 0.15s, box-shadow 0.15s; }
.card-clickable:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0,0,0,0.1) !important; }


/* ── DataTables responsive polish ── */
.table.dataTable {
    width: 100% !important;
    table-layout: fixed;
}

.table.dataTable > tbody > tr > td,
.table.dataTable > thead > tr > th {
    vertical-align: middle;
}

.table.dataTable td.dt-cell-compact,
.table.dataTable th.dt-cell-compact {
    max-width: 240px;
}

.table.dataTable td.dt-cell-compact,
.table.dataTable th.dt-cell-compact {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.table.dataTable td.dtr-control,
table.dataTable.dtr-inline.collapsed > tbody > tr > td.dtr-control,
table.dataTable.dtr-inline.collapsed > tbody > tr > th.dtr-control {
    cursor: pointer;
}

table.dataTable.dtr-inline.collapsed > tbody > tr > td.dtr-control:before,
table.dataTable.dtr-inline.collapsed > tbody > tr > th.dtr-control:before {
    background-color: #2563eb;
    border: 0;
    box-shadow: none;
    line-height: 1.05rem;
    height: 1.05rem;
    width: 1.05rem;
    margin-top: -0.55rem;
}

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

.dt-child-table td {
    white-space: normal !important;
    word-break: break-word;
}

.dt-child-table .dt-child-value {
    color: #334155;
}

@media (max-width: 1200px) {
    .table.dataTable td.dt-cell-compact,
    .table.dataTable th.dt-cell-compact {
        max-width: 190px;
    }
}

@media (max-width: 768px) {
    .dataTables_wrapper .row {
        row-gap: 0.5rem;
    }

    .table.dataTable td.dt-cell-compact,
    .table.dataTable th.dt-cell-compact {
        max-width: 150px;
    }

    .table.dataTable .btn-group,
    .table.dataTable .d-flex {
        flex-wrap: nowrap;
    }
}


.table-responsive:has(table.dataTable.dtr-inline) {
    overflow-x: visible;
}

table.dataTable.dtr-inline.collapsed > tbody > tr > td.dtr-control,
table.dataTable.dtr-inline.collapsed > tbody > tr > th.dtr-control {
    padding-left: 2rem !important;
}


/* DataTables expand/collapse button: separate visual affordance from row checkbox. */
table.dataTable.dtr-inline.collapsed > tbody > tr > td.dtr-control:before,
table.dataTable.dtr-inline.collapsed > tbody > tr > th.dtr-control:before {
    content: "+" !important;
    display: inline-grid;
    place-items: center;
    background: #0ea5e9 !important;
    color: #fff;
    border-radius: 999px;
    font-weight: 800;
    font-size: 0.85rem;
}

table.dataTable.dtr-inline.collapsed > tbody > tr.parent > td.dtr-control:before,
table.dataTable.dtr-inline.collapsed > tbody > tr.parent > th.dtr-control:before {
    content: "−" !important;
    background: #f97316 !important;
}

table.dataTable td.dt-responsive-control-cell {
    cursor: pointer;
}

table.dataTable td:first-child:has(.check-fila),
table.dataTable th:first-child:has(#checkTodos) {
    width: 42px !important;
    max-width: 42px !important;
    text-align: center;
}


/* Final DataTables detail trigger: only this button expands/collapses rows. */
.dt-row-details-toggle {
    width: 1.35rem;
    height: 1.35rem;
    border: 0;
    border-radius: 999px;
    background: #0ea5e9;
    color: #fff;
    display: inline-grid;
    place-items: center;
    font-weight: 900;
    line-height: 1;
    margin-right: 0.45rem;
    vertical-align: middle;
    cursor: pointer;
}

.dt-row-details-toggle::before {
    content: "+";
}

tr.parent .dt-row-details-toggle {
    background: #f97316;
}

tr.parent .dt-row-details-toggle::before {
    content: "−";
}

table.dataTable.dtr-inline.collapsed > tbody > tr > td.dtr-control:before,
table.dataTable.dtr-inline.collapsed > tbody > tr > th.dtr-control:before {
    display: none !important;
    content: none !important;
}

table.dataTable td.dt-responsive-control-cell {
    cursor: default;
}

table.dataTable td.dt-responsive-control-cell .dt-row-details-toggle + * {
    vertical-align: middle;
}


/* Disable DataTables Responsive automatic row/cell toggles; NetFlow uses manual button only. */
table.dataTable.dtr-inline.collapsed > tbody > tr > td.dtr-control:before,
table.dataTable.dtr-inline.collapsed > tbody > tr > th.dtr-control:before,
table.dataTable > tbody > tr > td.dtr-control:before,
table.dataTable > tbody > tr > th.dtr-control:before {
    display: none !important;
    content: none !important;
}

table.dataTable td.dtr-control,
table.dataTable th.dtr-control {
    cursor: default !important;
}


/* Mobile DataTables: avoid one-letter-per-line headers. */
@media (max-width: 576px) {
    .table.dataTable {
        table-layout: fixed;
        font-size: 0.82rem;
    }

    .table.dataTable > thead > tr > th,
    .table.dataTable > tbody > tr > td {
        padding: 0.45rem 0.4rem;
    }

    .table.dataTable th.dt-cell-compact,
    .table.dataTable td.dt-cell-compact {
        max-width: 105px;
        min-width: 0;
    }

    .table.dataTable th {
        white-space: nowrap !important;
        word-break: normal !important;
        overflow-wrap: normal !important;
    }

    .dt-row-details-toggle {
        width: 1.25rem;
        height: 1.25rem;
        margin-right: 0.25rem;
    }

    table.dataTable td:first-child:has(.check-fila),
    table.dataTable th:first-child:has(#checkTodos) {
        width: 34px !important;
        max-width: 34px !important;
    }
}


/* Phone layout: DataTables as compact list cards, not squeezed spreadsheet. */
@media (max-width: 576px) {
    .dataTables_wrapper table.dataTable,
    .dataTables_wrapper table.dataTable tbody,
    .dataTables_wrapper table.dataTable tr,
    .dataTables_wrapper table.dataTable td {
        display: block;
        width: 100% !important;
    }

    .dataTables_wrapper table.dataTable tbody tr {
        position: relative;
        background: var(--app-surface);
        border: 1px solid var(--app-border);
        border-radius: 0.85rem;
        margin-bottom: 0.75rem;
        padding: 0.55rem 0.65rem 0.65rem 2.5rem;
        box-shadow: 0 6px 18px rgba(15, 23, 42, 0.05);
    }

    .dataTables_wrapper table.dataTable tbody tr.child {
        margin-top: -0.65rem;
        padding: 0.25rem 0.65rem 0.65rem 0.65rem;
        border-top: 0;
        box-shadow: none;
    }

    .dataTables_wrapper table.dataTable tbody td {
        border: 0;
        padding: 0.16rem 0;
        max-width: none !important;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .dataTables_wrapper table.dataTable tbody td:first-child:has(.check-fila) {
        position: absolute;
        left: 0.65rem;
        top: 0.75rem;
        width: auto !important;
        max-width: none !important;
        padding: 0;
    }


    .dataTables_wrapper table.dataTable tbody tr:not(.child) > td.dt-mobile-visible {
        text-align: left !important;
    }

    .dataTables_wrapper table.dataTable tbody td.dt-responsive-control-cell {
        font-weight: 700;
        color: #0f172a;
        padding-right: 0.25rem;
    }

    .dataTables_wrapper table.dataTable tbody td:last-child {
        margin-top: 0.4rem;
        padding-top: 0.45rem;
        border-top: 1px dashed #e2e8f0;
        white-space: normal;
        overflow: visible;
    }

    .dataTables_wrapper table.dataTable tbody td:last-child .btn,
    .dataTables_wrapper table.dataTable tbody td:last-child .dropdown,
    .dataTables_wrapper table.dataTable tbody td:last-child .btn-group {
        margin-top: 0.15rem;
    }

    .dt-child-table td {
        display: table-cell !important;
        width: auto !important;
        padding: 0.18rem 0.25rem !important;
        white-space: normal !important;
    }
}


/* Mobile table overflow + action buttons containment. */
@media (max-width: 576px) {
    html, body {
        max-width: 100%;
        overflow-x: hidden;
    }

    #main-content {
        padding-left: 0.75rem;
        padding-right: 0.75rem;
        padding-bottom: calc(7rem + env(safe-area-inset-bottom, 0px));
        overflow-x: hidden;
    }

    .card,
    .card-body,
    .table-responsive,
    .dataTables_wrapper {
        max-width: 100%;
        overflow-x: hidden !important;
    }

    .dataTables_wrapper table.dataTable tbody tr {
        width: 100% !important;
        max-width: 100% !important;
        overflow: hidden;
    }

    .dataTables_wrapper table.dataTable tbody td:last-child {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        justify-content: flex-start;
        gap: 0.35rem;
        max-width: 100% !important;
    }

    .dataTables_wrapper table.dataTable tbody td:last-child .btn-group,
    .dataTables_wrapper table.dataTable tbody td:last-child .dropdown,
    .dataTables_wrapper table.dataTable tbody td:last-child .d-flex {
        display: flex !important;
        flex-wrap: wrap !important;
        gap: 0.3rem;
        max-width: 100%;
        min-width: 0;
    }

    .dataTables_wrapper table.dataTable tbody td:last-child .btn,
    .dataTables_wrapper table.dataTable tbody td:last-child .dropdown-toggle,
    .dataTables_wrapper table.dataTable tbody td:last-child a.btn,
    .dataTables_wrapper table.dataTable tbody td:last-child button.btn {
        max-width: 100%;
        min-width: 0;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .dataTables_wrapper table.dataTable tbody td:last-child .dropdown-menu {
        max-width: calc(100vw - 2rem);
    }
}


@media (max-width: 576px) {
    .dataTables_wrapper table.dataTable tbody td:last-child .dropdown-menu {
        z-index: 1060;
    }
}


/* Mobile expanded details must read like normal key/value content, not squeezed table columns. */
@media (max-width: 576px) {
    .dataTables_wrapper table.dataTable tbody tr.child {
        padding-left: 0.65rem;
        padding-right: 0.65rem;
        overflow: visible;
    }

    .dataTables_wrapper table.dataTable tbody tr.child > td {
        display: block !important;
        width: 100% !important;
        max-width: 100% !important;
        white-space: normal !important;
        overflow: visible !important;
    }

    .dataTables_wrapper table.dataTable tbody tr.child .dt-child-table,
    .dataTables_wrapper table.dataTable tbody tr.child .dt-child-table tbody,
    .dataTables_wrapper table.dataTable tbody tr.child .dt-child-table tr,
    .dataTables_wrapper table.dataTable tbody tr.child .dt-child-table td {
        display: block !important;
        width: 100% !important;
        max-width: 100% !important;
        white-space: normal !important;
        overflow: visible !important;
        text-overflow: clip !important;
        word-break: normal !important;
        overflow-wrap: anywhere !important;
    }

    .dataTables_wrapper table.dataTable tbody tr.child .dt-child-table tr {
        border: 0;
        box-shadow: none;
        margin: 0 0 0.45rem 0;
        padding: 0;
        background: transparent;
    }

    .dataTables_wrapper table.dataTable tbody tr.child .dt-child-table td:first-child {
        position: static !important;
        color: var(--sidebar-muted);
        font-size: 0.72rem;
        text-transform: uppercase;
        letter-spacing: 0.04em;
        font-weight: 800;
        padding: 0 !important;
    }

    .dataTables_wrapper table.dataTable tbody tr.child .dt-child-table .dt-child-value {
        color: #0f172a;
        font-size: 0.9rem;
        line-height: 1.35;
        padding: 0.08rem 0 0 0 !important;
    }

    .dataTables_wrapper table.dataTable tbody tr.child .dt-child-table .dt-child-value * {
        max-width: 100%;
        white-space: normal !important;
        word-break: normal !important;
        overflow-wrap: anywhere !important;
    }
}


/* Detail rows as readable list blocks, avoiding nested-table mobile compression. */
.dt-child-list {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 0.65rem 1rem;
    width: 100%;
    max-width: 100%;
}

.dt-child-item {
    min-width: 0;
    padding: 0.55rem 0.65rem;
    border: 1px solid #e2e8f0;
    border-radius: 0.65rem;
    background: #f8fafc;
}

.dt-child-label {
    display: block;
    color: var(--sidebar-muted);
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-weight: 800;
    margin-bottom: 0.2rem;
}

.dt-child-value {
    display: block;
    color: #0f172a;
    font-size: 0.92rem;
    line-height: 1.35;
    white-space: normal !important;
    word-break: normal !important;
    overflow-wrap: break-word !important;
}

.dt-child-value * {
    max-width: 100%;
    white-space: normal !important;
    word-break: normal !important;
    overflow-wrap: break-word !important;
}

/* DataTables responsive expanded rows (+) in dark mode. */
[data-bs-theme="dark"] .dataTables_wrapper table.dataTable tbody tr.child,
[data-bs-theme="dark"] .dataTables_wrapper table.dataTable tbody tr.child > td {
    --bs-table-bg: var(--app-surface-soft);
    --bs-table-color: var(--app-text);
    --bs-table-border-color: var(--app-border);
    background-color: var(--app-surface-soft) !important;
    color: var(--app-text) !important;
    border-color: var(--app-border) !important;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.035);
}

[data-bs-theme="dark"] .dataTables_wrapper table.dataTable tbody tr.child ul.dtr-details,
[data-bs-theme="dark"] .dataTables_wrapper table.dataTable tbody tr.child ul.dtr-details > li {
    color: var(--app-text) !important;
    border-color: var(--app-border) !important;
}

[data-bs-theme="dark"] .dataTables_wrapper table.dataTable tbody tr.child ul.dtr-details span.dtr-title,
[data-bs-theme="dark"] .dt-child-label,
[data-bs-theme="dark"] .dataTables_wrapper table.dataTable tbody tr.child .dt-child-table td:first-child {
    color: var(--app-muted) !important;
}

[data-bs-theme="dark"] .dataTables_wrapper table.dataTable tbody tr.child ul.dtr-details span.dtr-data,
[data-bs-theme="dark"] .dt-child-value,
[data-bs-theme="dark"] .dt-child-value *,
[data-bs-theme="dark"] .dataTables_wrapper table.dataTable tbody tr.child .dt-child-table .dt-child-value,
[data-bs-theme="dark"] .dataTables_wrapper table.dataTable tbody tr.child .dt-child-table .dt-child-value * {
    color: var(--app-text) !important;
}

[data-bs-theme="dark"] .dt-child-item {
    background:
        linear-gradient(180deg, rgba(96, 165, 250, 0.06), rgba(255, 255, 255, 0.018)),
        var(--app-surface-soft) !important;
    border-color: var(--app-border) !important;
    color: var(--app-text) !important;
}

@media (max-width: 576px) {
    .dt-child-list {
        display: block;
    }

    .dt-child-item {
        display: block;
        width: 100%;
        margin-bottom: 0.55rem;
        padding: 0.55rem 0.65rem;
    }

    .dataTables_wrapper table.dataTable tbody tr.child,
    .dataTables_wrapper table.dataTable tbody tr.child > td {
        display: block !important;
        width: 100% !important;
        max-width: 100% !important;
        overflow: visible !important;
        white-space: normal !important;
    }
}


/* Responsive static tables used in show pages. */
@media (max-width: 576px) {
    .table-info-mobile,
    .table-info-mobile tbody,
    .table-info-mobile tr,
    .table-info-mobile td {
        display: block;
        width: 100% !important;
    }

    .table-info-mobile tr {
        padding: 0.55rem 0;
        border-bottom: 1px solid #e2e8f0;
    }

    .table-info-mobile tr:last-child {
        border-bottom: 0;
    }

    .table-info-mobile td {
        border: 0 !important;
        padding: 0.08rem 0 !important;
        text-align: left !important;
        white-space: normal !important;
        word-break: normal !important;
        overflow-wrap: break-word !important;
    }

    .table-info-mobile td:first-child {
        color: #64748b !important;
        font-size: 0.72rem;
        text-transform: uppercase;
        letter-spacing: 0.04em;
        font-weight: 800;
    }

    .table-info-mobile td:last-child {
        color: #0f172a;
        line-height: 1.35;
    }

    .table-info-mobile td:last-child .btn,
    .table-info-mobile td:last-child a,
    .table-info-mobile td:last-child code,
    .table-info-mobile td:last-child .badge {
        max-width: 100%;
        white-space: normal;
        overflow-wrap: break-word;
    }

    .table-stack-mobile,
    .table-stack-mobile tbody,
    .table-stack-mobile tr,
    .table-stack-mobile td {
        display: block;
        width: 100% !important;
    }

    .table-stack-mobile tr {
        border: 1px solid #e2e8f0;
        border-radius: 0.75rem;
        padding: 0.65rem;
        margin-bottom: 0.65rem;
        background: #fff;
    }

    .table-stack-mobile td {
        border: 0 !important;
        padding: 0.18rem 0 !important;
        text-align: left !important;
        white-space: normal !important;
        overflow-wrap: break-word !important;
    }

    .table-stack-mobile td[colspan] {
        text-align: center !important;
    }
}


/* Mobile labels for card-style rows. */
@media (max-width: 576px) {
    .dataTables_wrapper table.dataTable tbody tr:not(.child) > td[data-label]::before,
    .table-stack-mobile tbody tr > td[data-label]::before {
        content: attr(data-label);
        display: block;
        color: var(--sidebar-muted);
        font-size: 0.68rem;
        text-transform: uppercase;
        letter-spacing: 0.04em;
        font-weight: 800;
        margin-bottom: 0.08rem;
    }

    .dataTables_wrapper table.dataTable tbody tr:not(.child) > td:first-child:has(.check-fila)::before {
        display: none;
        content: none;
    }

    .table-stack-mobile tbody tr > td[data-label] {
        padding-top: 0.35rem !important;
        padding-bottom: 0.35rem !important;
    }
}


/* Responsive bulk action bars used by index/catalog tables. */
#barraAccionesMasivas .card-body,
#barraAccionesMasivasOrdenes .card-body {
    flex-wrap: wrap;
}

#barraAccionesMasivas .dropdown-menu,
#barraAccionesMasivasOrdenes .dropdown-menu {
    max-width: min(22rem, calc(100vw - 2rem));
    white-space: normal;
}

#barraAccionesMasivas .dropdown-item,
#barraAccionesMasivasOrdenes .dropdown-item,
#contextMenuMasivas .dropdown-item,
#contextMenuMasivas .ctx-item,
#contextMenuOrdenesMasivas .dropdown-item,
#contextMenuOrdenesMasivas .ctx-item {
    white-space: normal;
}

@media (max-width: 576px) {
    #barraAccionesMasivas .card-body,
    #barraAccionesMasivasOrdenes .card-body {
        align-items: stretch !important;
        gap: 0.65rem !important;
        padding: 0.85rem !important;
    }

    #barraAccionesMasivas .fw-semibold,
    #barraAccionesMasivasOrdenes .fw-semibold {
        width: 100%;
        line-height: 1.25;
    }

    #barraAccionesMasivas .dropdown,
    #barraAccionesMasivas .dropdown > .btn,
    #barraAccionesMasivas #btnDeseleccionarTodo,
    #barraAccionesMasivasOrdenes .dropdown,
    #barraAccionesMasivasOrdenes .dropdown > .btn,
    #barraAccionesMasivasOrdenes #btnDeseleccionarOrdenes {
        width: 100%;
    }

    #barraAccionesMasivas #btnDeseleccionarTodo,
    #barraAccionesMasivasOrdenes #btnDeseleccionarOrdenes {
        margin-left: 0 !important;
    }

    #barraAccionesMasivas .dropdown-menu,
    #barraAccionesMasivasOrdenes .dropdown-menu {
        width: 100%;
        min-width: 100%;
    }
}







/* DataTables readable cells: visible content should not be cut with ellipsis.
   If there is not enough room, the global responsive wrapper hides columns and
   moves them to the + details instead of clipping the text. */
.table.dataTable td.dt-cell-compact,
.table.dataTable td.dt-client-name-cell,
.table.dataTable td.dt-client-email-cell,
.table.dataTable td.dt-invoice-client-cell,
.table.dataTable td.dt-contract-number-cell {
    max-width: none;
    overflow: visible;
    text-overflow: clip;
    white-space: normal;
    overflow-wrap: anywhere;
    word-break: normal;
}

#tablaFacturas.dataTable td.dt-invoice-client-cell a {
    display: inline;
    max-width: none;
    overflow: visible;
    text-overflow: clip;
    white-space: normal;
    overflow-wrap: anywhere;
}

/* /clientes: compact DataTable columns, aligned with /contratos and /facturas. */
#tablaClientes.dataTable > tbody > tr > td {
    padding-top: 0.35rem;
    padding-bottom: 0.35rem;
    line-height: 1.2;
}

#tablaClientes.dataTable {
    table-layout: fixed;
}

#tablaClientes .dt-client-col-id { width: 11.5%; }
#tablaClientes .dt-client-col-name { width: 29%; }
#tablaClientes .dt-client-col-city { width: 19%; }
#tablaClientes .dt-client-col-phone { width: 9.5%; }
#tablaClientes .dt-client-col-email { width: 19.5%; }
#tablaClientes .dt-client-col-status { width: 5%; }
#tablaClientes .dt-client-col-actions { width: 6.5%; }

#tablaClientes.dataTable > thead > tr > th,
#tablaClientes.dataTable > tbody > tr > td {
    overflow: hidden;
    padding-left: 0.45rem;
    padding-right: 0.45rem;
}

#tablaClientes.dataTable td.dt-client-id-cell,
#tablaClientes.dataTable th.dt-client-id-cell {
    white-space: nowrap !important;
}

#tablaClientes.dataTable td.dt-client-city-cell,
#tablaClientes.dataTable th.dt-client-city-cell {
    white-space: nowrap !important;
}

#tablaClientes.dataTable td.dt-client-phone-cell,
#tablaClientes.dataTable th.dt-client-phone-cell {
    white-space: nowrap !important;
}

#tablaClientes.dataTable td.dt-client-status-cell,
#tablaClientes.dataTable th.dt-client-status-cell {
    white-space: nowrap !important;
}

#tablaClientes.dataTable td.dt-client-id-cell,
#tablaClientes.dataTable td.dt-client-city-cell,
#tablaClientes.dataTable td.dt-client-phone-cell,
#tablaClientes.dataTable td.dt-client-status-cell {
    padding-top: 0.22rem;
    padding-bottom: 0.22rem;
}

#tablaClientes.dataTable td.dt-client-status-cell .badge {
    display: inline-flex;
    align-items: center;
    min-height: 1.3rem;
    line-height: 1;
    padding: 0.26rem 0.48rem;
    font-size: 0.74rem;
}

#tablaClientes.dataTable td.dt-client-name-cell,
#tablaClientes.dataTable td.dt-client-email-cell {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

#tablaClientes.dataTable td.dt-client-name-cell a,
#tablaClientes.dataTable td.dt-client-email-cell a {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

@media (min-width: 769px) {
    #tablaClientes.dataTable td.dt-client-actions-cell,
    #tablaClientes.dataTable th.dt-client-actions-cell {
        white-space: nowrap !important;
    }

    #tablaClientes.dataTable td.dt-client-actions-cell .d-flex {
        flex-wrap: nowrap !important;
        gap: 0.12rem !important;
    }

    #tablaClientes.dataTable td.dt-client-actions-cell form {
        display: inline-flex !important;
        margin: 0;
    }

    #tablaClientes.dataTable td.dt-client-actions-cell .btn {
        width: 1.62rem;
        height: 1.62rem;
        padding: 0;
        line-height: 1;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        font-size: 0.82rem;
    }
}

/* /facturas: compact DataTable columns.
   Mirrors /contratos: each visible column gets a scoped class so small badges,
   dates and icon actions do not inherit excessive generic table spacing. */
#tablaFacturas.dataTable > tbody > tr > td {
    padding-top: 0.35rem;
    padding-bottom: 0.35rem;
    line-height: 1.2;
}

#tablaFacturas.dataTable td.dt-invoice-number-cell,
#tablaFacturas.dataTable th.dt-invoice-number-cell {
    width: 9rem;
    min-width: 9rem;
    white-space: nowrap !important;
}

#tablaFacturas.dataTable td.dt-invoice-date-cell,
#tablaFacturas.dataTable th.dt-invoice-date-cell {
    width: 7.25rem;
    min-width: 7.25rem;
    white-space: nowrap !important;
}

#tablaFacturas.dataTable td.dt-invoice-total-cell,
#tablaFacturas.dataTable th.dt-invoice-total-cell {
    width: 7.5rem;
    min-width: 7.5rem;
    white-space: nowrap !important;
}

#tablaFacturas.dataTable td.dt-invoice-status-cell,
#tablaFacturas.dataTable th.dt-invoice-status-cell {
    width: 6.75rem;
    min-width: 6.75rem;
    white-space: nowrap !important;
}

#tablaFacturas.dataTable td.dt-invoice-number-cell,
#tablaFacturas.dataTable td.dt-invoice-date-cell,
#tablaFacturas.dataTable td.dt-invoice-total-cell,
#tablaFacturas.dataTable td.dt-invoice-status-cell {
    padding-top: 0.22rem;
    padding-bottom: 0.22rem;
}

#tablaFacturas.dataTable td.dt-invoice-number-cell .fw-semibold,
#tablaFacturas.dataTable td.dt-invoice-status-cell .badge {
    display: inline-flex;
    align-items: center;
    min-height: 1.3rem;
    line-height: 1;
}

#tablaFacturas.dataTable td.dt-invoice-status-cell .badge {
    padding: 0.26rem 0.48rem;
    font-size: 0.74rem;
}

#tablaFacturas.dataTable td.dt-invoice-client-cell {
    overflow: hidden;
    text-overflow: ellipsis;
}

#tablaFacturas.dataTable td.dt-invoice-client-cell a {
    display: inline-block;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: middle;
}

@media (min-width: 769px) {
    #tablaFacturas.dataTable td.dt-invoice-actions-cell,
    #tablaFacturas.dataTable th.dt-invoice-actions-cell {
        white-space: nowrap !important;
        width: 17rem;
        min-width: 17rem;
    }

    #tablaFacturas.dataTable td.dt-invoice-actions-cell .d-flex {
        flex-wrap: nowrap !important;
        gap: 0.25rem !important;
    }

    #tablaFacturas.dataTable td.dt-invoice-actions-cell form {
        display: inline-flex !important;
        margin: 0;
    }

    #tablaFacturas.dataTable td.dt-invoice-actions-cell .btn {
        width: 1.85rem;
        height: 1.85rem;
        padding: 0;
        line-height: 1;
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }
}


/* /contratos: compact desktop rows.
   The actions cell can contain 5-7 icon buttons/forms. The global DataTables
   action rule allowed flex-wrap, so those buttons broke into two lines and
   forced the whole row to become taller than the small badges/text content. */
#tablaContratos.dataTable > tbody > tr > td {
    padding-top: 0.35rem;
    padding-bottom: 0.35rem;
    line-height: 1.2;
}

#tablaContratos.dataTable {
    table-layout: fixed;
}

#tablaContratos .dt-col-select { width: 4%; }
#tablaContratos .dt-col-contract { width: 11%; }
#tablaContratos .dt-col-client { width: 22%; }
#tablaContratos .dt-col-status { width: 7%; }
#tablaContratos .dt-col-cut { width: 7%; }
#tablaContratos .dt-col-plan { width: 12%; }
#tablaContratos .dt-col-connection { width: 12%; }
#tablaContratos .dt-col-ip { width: 8%; }
#tablaContratos .dt-col-actions { width: 17%; }

#tablaContratos.dataTable > thead > tr > th,
#tablaContratos.dataTable > tbody > tr > td {
    overflow: hidden;
}

#tablaContratos.dataTable td.dt-col-client,
#tablaContratos.dataTable td.dt-col-plan,
#tablaContratos.dataTable td.dt-col-connection,
#tablaContratos.dataTable td.dt-col-ip,
#tablaContratos.dataTable td.dt-col-cut {
    white-space: nowrap;
    text-overflow: ellipsis;
}

#tablaContratos.dataTable td.dt-col-client a,
#tablaContratos.dataTable td.dt-col-plan a {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

#tablaContratos.dataTable td.dt-contract-number-cell,
#tablaContratos.dataTable th.dt-contract-number-cell {
    white-space: nowrap !important;
}

#tablaContratos.dataTable td.dt-contract-number-cell {
    padding-top: 0.22rem;
    padding-bottom: 0.22rem;
}

#tablaContratos.dataTable td.dt-contract-number-cell .fw-semibold {
    display: inline-flex;
    align-items: center;
    min-height: 1.3rem;
    line-height: 1;
}

#tablaContratos.dataTable td.dt-status-cell,
#tablaContratos.dataTable th.dt-status-cell {
    width: 6.25rem;
    min-width: 6.25rem;
    white-space: nowrap !important;
    text-align: center;
}

#tablaContratos.dataTable td.dt-status-cell {
    padding-top: 0.22rem;
    padding-bottom: 0.22rem;
}

#tablaContratos.dataTable td.dt-status-cell .badge {
    display: inline-flex;
    align-items: center;
    min-height: 1.3rem;
    line-height: 1;
    padding: 0.26rem 0.48rem;
    font-size: 0.74rem;
}

@media (min-width: 769px) {
    #tablaContratos.dataTable td.dt-actions-cell,
    #tablaContratos.dataTable th.dt-actions-cell {
        white-space: nowrap !important;
    }

    #tablaContratos.dataTable td.dt-actions-cell .d-flex {
        flex-wrap: nowrap !important;
        gap: 0.18rem !important;
    }

    #tablaContratos.dataTable td.dt-actions-cell form {
        display: inline-flex !important;
        margin: 0;
    }

    #tablaContratos.dataTable td.dt-actions-cell .btn {
        width: 1.7rem;
        height: 1.7rem;
        padding: 0;
        line-height: 1;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        font-size: 0.82rem;
    }
}

/* Responsive Actions column: keep buttons usable without horizontal overflow. */
table.dataTable td.dt-actions-cell,
table.dataTable th.dt-actions-cell,
table.dataTable th:last-child,
table.dataTable td:last-child {
    white-space: normal !important;
}

table.dataTable td.dt-actions-cell .btn,
table.dataTable td:last-child .btn,
.table-stack-mobile td[data-label="Acciones"] .btn {
    flex: 0 0 auto;
}

table.dataTable td.dt-actions-cell .btn-group,
table.dataTable td.dt-actions-cell .d-flex,
table.dataTable td:last-child .btn-group,
table.dataTable td:last-child .d-flex,
.table-stack-mobile td[data-label="Acciones"] .btn-group,
.table-stack-mobile td[data-label="Acciones"] .d-flex {
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.25rem !important;
    max-width: 100%;
}

table.dataTable td.dt-actions-cell .dropdown-menu,
table.dataTable td:last-child .dropdown-menu,
.table-stack-mobile td[data-label="Acciones"] .dropdown-menu {
    max-width: min(18rem, calc(100vw - 2rem));
    white-space: normal;
}

@media (max-width: 768px) {
    table.dataTable th:last-child,
    table.dataTable td.dt-actions-cell,
    table.dataTable td:last-child {
        min-width: 0 !important;
        max-width: 100% !important;
    }

    table.dataTable td.dt-actions-cell,
    table.dataTable td:last-child,
    .table-stack-mobile td[data-label="Acciones"] {
        overflow: visible !important;
        text-align: left !important;
    }

    table.dataTable td.dt-actions-cell .btn,
    table.dataTable td:last-child .btn,
    .table-stack-mobile td[data-label="Acciones"] .btn {
        min-width: 2.15rem;
        min-height: 2.15rem;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        margin: 0.12rem;
    }

    table.dataTable td.dt-actions-cell .btn-group,
    table.dataTable td:last-child .btn-group,
    .table-stack-mobile td[data-label="Acciones"] .btn-group {
        display: flex !important;
        width: 100%;
    }
}

@media (max-width: 576px) {
    .dataTables_wrapper table.dataTable tbody tr:not(.child) > td.dt-actions-cell,
    .dataTables_wrapper table.dataTable tbody tr:not(.child) > td:last-child,
    .table-stack-mobile td[data-label="Acciones"] {
        padding-top: 0.45rem !important;
        border-top: 1px dashed #e2e8f0 !important;
    }
}

/* Final readable overrides for tables with table-specific compact CSS. */
#tablaClientes.dataTable td.dt-client-name-cell,
#tablaClientes.dataTable td.dt-client-email-cell,
#tablaClientes.dataTable td.dt-client-city-cell,
#tablaClientes.dataTable td.dt-client-phone-cell,
#tablaClientes.dataTable th.dt-client-city-cell,
#tablaClientes.dataTable th.dt-client-phone-cell,
#tablaClientes.dataTable th.dt-client-email-cell {
    max-width: none !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    white-space: nowrap !important;
    overflow-wrap: normal !important;
    word-break: normal !important;
}

#tablaFacturas.dataTable td.dt-invoice-client-cell,
#tablaFacturas.dataTable td.dt-invoice-client-cell a {
    max-width: none !important;
    overflow: visible !important;
    text-overflow: clip !important;
    white-space: normal !important;
    overflow-wrap: anywhere !important;
    word-break: normal !important;
}

#tablaClientes.dataTable {
    table-layout: fixed !important;
}

@media (max-width: 1200px) {
    #tablaClientes.dataTable td.dt-client-city-cell,
    #tablaClientes.dataTable td.dt-client-phone-cell,
    #tablaClientes.dataTable td.dt-client-email-cell {
        max-width: 100% !important;
    }
}


/* Cliente show: nested contract/invoice tables are much narrower than /contratos.
   Keep them inside the card at high browser zoom and let NetFlow details (+)
   carry secondary columns instead of creating horizontal scroll. */
.table-client-detail-contracts.dataTable,
.table-client-detail-invoices.dataTable {
    width: 100% !important;
    table-layout: auto;
}

.table-client-detail-contracts.dataTable th,
.table-client-detail-contracts.dataTable td,
.table-client-detail-invoices.dataTable th,
.table-client-detail-invoices.dataTable td {
    max-width: none;
}

.table-client-detail-contracts.dataTable td.dt-client-contract-number-cell,
.table-client-detail-contracts.dataTable th.dt-client-contract-number-cell {
    min-width: 6.5rem;
    width: auto;
    white-space: nowrap !important;
}

.table-client-detail-contracts.dataTable td.dt-client-contract-plan-cell,
.table-client-detail-contracts.dataTable td.dt-client-contract-date-cell {
    white-space: normal !important;
    word-break: break-word;
}

@media (min-width: 769px) {
    .table-client-detail-contracts.dataTable td.dt-actions-cell,
    .table-client-detail-contracts.dataTable th.dt-actions-cell,
    .table-client-detail-invoices.dataTable td.dt-actions-cell,
    .table-client-detail-invoices.dataTable th.dt-actions-cell {
        width: auto !important;
        min-width: 0 !important;
        max-width: 8rem;
        white-space: normal !important;
    }

    .table-client-detail-contracts.dataTable td.dt-actions-cell .d-flex,
    .table-client-detail-invoices.dataTable td.dt-actions-cell .d-flex {
        flex-wrap: wrap !important;
        justify-content: center;
    }
}


.quick-action-card {
    transition: transform .15s ease, box-shadow .15s ease;
}

.quick-action-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 .5rem 1rem rgba(15, 23, 42, .08);
}


/* ═══════════════════════════════════════
   THEME SYSTEM - Bootstrap 5.3 + app tokens
═══════════════════════════════════════ */
#preloader {
    position: fixed;
    inset: 0;
    background:
        radial-gradient(circle at center, rgba(var(--bs-primary-rgb), .10), transparent 34rem),
        var(--app-bg);
    color: var(--app-text);
    z-index: 9999;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    transition: opacity 0.12s ease;
}

.preloader-spinner {
    width: 2.75rem;
    height: 2.75rem;
    border-width: .22rem;
}

.preloader-title {
    color: var(--app-text);
    letter-spacing: 0;
}

.preloader-status {
    color: var(--app-muted);
}

[data-bs-theme="dark"] #preloader {
    background:
        radial-gradient(circle at center, rgba(34, 197, 94, .12), transparent 34rem),
        var(--app-bg);
}

/* Loader Beta (Netflow - dashboard_beta feature flag) */
.preloader-logo {
    width: 64px;
    height: auto;
    object-fit: contain;
}

.preloader-logo-giratorio {
    animation: girar 1.5s linear infinite;
}

@keyframes girar {
    from { transform: rotate(0deg); }
    to { transform: rotate(360deg); }
}

@keyframes preloaderPulse {
    0%, 100% { opacity: 0.7; }
    50% { opacity: 1; }
}

.preloader-spinner-beta {
    width: 3.5rem !important;
    height: 3.5rem !important;
    border-width: .25rem !important;
}

.preloader-title-beta {
    font-weight: 600 !important;
    font-size: 1.1rem !important;
    color: var(--bs-primary) !important;
    margin-bottom: 0.5rem !important;
}

.dots-anim {
    display: inline-block;
    width: 2ch;
    text-align: left;
}

[data-bs-theme="dark"] .preloader-title-beta {
    color: #3b82f6 !important;
}

#main-content,
#navbar,
.card,
.dropdown-menu,
.modal-content,
.offcanvas,
.list-group-item,
.table,
.form-control,
.form-select,
.input-group-text,
.page-link {
    transition: background-color 0.18s ease, border-color 0.18s ease, color 0.18s ease, box-shadow 0.18s ease;
}

.card,
.dropdown-menu,
.modal-content,
.offcanvas {
    background-color: var(--app-surface);
    border-color: var(--app-border);
    color: var(--app-text);
}

.card.border-0,
.card.shadow-sm,
.card.shadow {
    box-shadow: var(--app-shadow) !important;
}

.card-header,
.card-footer {
    background-color: var(--app-surface-soft);
    border-color: var(--app-border);
    color: var(--app-text);
}

[data-bs-theme="dark"] .bg-white,
[data-bs-theme="dark"] .card-header.bg-white,
[data-bs-theme="dark"] .card-footer.bg-white,
[data-bs-theme="dark"] .tab-content.bg-white,
[data-bs-theme="dark"] .position-fixed.bg-white {
    background-color: var(--app-surface) !important;
    color: var(--app-text) !important;
}

[data-bs-theme="dark"] .bg-light:not(.badge),
[data-bs-theme="dark"] .table-light {
    background-color: var(--app-surface-soft) !important;
    color: var(--app-text) !important;
    --bs-table-bg: var(--app-surface-soft) !important;
    --bs-table-bg-state: var(--app-surface-soft) !important;
    --bs-table-color-state: var(--app-text) !important;
}
[data-bs-theme="dark"] .table-light > :not(caption) > * > * {
    background-color: var(--app-surface-soft) !important;
    color: var(--app-text) !important;
}

[data-bs-theme="dark"] #main-content .text-dark:not(.badge):not(.btn),
[data-bs-theme="dark"] .card .text-dark:not(.badge):not(.btn),
[data-bs-theme="dark"] .dropdown-menu .text-dark:not(.badge):not(.btn) {
    color: var(--app-text) !important;
}

[data-bs-theme="dark"] .text-muted,
[data-bs-theme="dark"] .text-secondary {
    color: var(--app-muted) !important;
}

[data-bs-theme="dark"] .border,
[data-bs-theme="dark"] .border-top,
[data-bs-theme="dark"] .border-end,
[data-bs-theme="dark"] .border-bottom,
[data-bs-theme="dark"] .border-start {
    border-color: var(--app-border) !important;
}

[data-bs-theme="dark"] .btn-light,
[data-bs-theme="dark"] .btn-outline-secondary {
    --bs-btn-color: var(--app-text);
    --bs-btn-bg: var(--app-surface-soft);
    --bs-btn-border-color: var(--app-border-strong);
    --bs-btn-hover-color: #fff;
    --bs-btn-hover-bg: #1f2937;
    --bs-btn-hover-border-color: #475569;
    --bs-btn-active-bg: #243044;
    --bs-btn-active-border-color: #475569;
}

.theme-dropdown .dropdown-item .theme-check {
    opacity: 0;
}
.theme-dropdown .dropdown-item.active .theme-check {
    opacity: 1;
}
.theme-dropdown .dropdown-item.active {
    background-color: var(--app-primary-soft);
    color: var(--app-text);
}
#themeToggleButton {
    border-color: var(--app-border);
}

.form-control,
.form-select,
.input-group-text {
    background-color: var(--app-surface);
    border-color: var(--app-border-strong);
    color: var(--app-text);
}
.form-control:focus,
.form-select:focus {
    border-color: var(--app-primary);
    box-shadow: 0 0 0 0.25rem var(--app-focus-ring);
}
.form-control::placeholder {
    color: var(--app-muted);
}

.table {
    --bs-table-color: var(--app-text);
    --bs-table-bg: var(--app-surface);
    --bs-table-border-color: var(--app-border);
    --bs-table-striped-bg: var(--table-striped-bg);
    --bs-table-hover-bg: var(--app-surface-soft);
}

[data-bs-theme="dark"] .table > tbody > tr > * {
    color: var(--app-text);
    border-color: var(--app-border);
}

[data-bs-theme="dark"] .table-responsive,
[data-bs-theme="dark"] .dataTables_wrapper,
[data-bs-theme="dark"] .dt-container {
    color: var(--app-text);
}

[data-bs-theme="dark"] .dataTables_wrapper .dataTables_length,
[data-bs-theme="dark"] .dataTables_wrapper .dataTables_filter,
[data-bs-theme="dark"] .dataTables_wrapper .dataTables_info,
[data-bs-theme="dark"] .dataTables_wrapper .dataTables_processing,
[data-bs-theme="dark"] .dt-container .dt-length,
[data-bs-theme="dark"] .dt-container .dt-search,
[data-bs-theme="dark"] .dt-container .dt-info,
[data-bs-theme="dark"] .dt-container .dt-processing {
    color: var(--app-muted) !important;
}

[data-bs-theme="dark"] .page-link {
    background-color: var(--app-surface);
    border-color: var(--app-border);
    color: var(--app-link);
}
[data-bs-theme="dark"] .active > .page-link,
[data-bs-theme="dark"] .page-link.active {
    background-color: var(--app-primary);
    border-color: var(--app-primary);
    color: #fff;
}

[data-bs-theme="dark"] .select2-container--bootstrap5 .select2-selection,
[data-bs-theme="dark"] .select2-dropdown {
    background-color: var(--app-surface);
    border-color: var(--app-border-strong);
    color: var(--app-text);
}
[data-bs-theme="dark"] .select2-container--bootstrap5 .select2-selection__rendered,
[data-bs-theme="dark"] .select2-results__option {
    color: var(--app-text);
}
[data-bs-theme="dark"] .select2-results__option--highlighted {
    background-color: var(--app-primary) !important;
    color: #fff !important;
}
[data-bs-theme="dark"] .select2-search__field {
    background-color: var(--app-surface-soft) !important;
    border-color: var(--app-border-strong) !important;
    color: var(--app-text) !important;
}

[data-bs-theme="dark"] .ctx-item {
    color: var(--app-text);
}
[data-bs-theme="dark"] .ctx-item:hover,
[data-bs-theme="dark"] .ctx-item:focus {
    color: #fff;
    background-color: var(--app-surface-soft);
}
[data-bs-theme="dark"] .dt-child-table .dt-child-value {
    color: var(--app-text);
}
[data-bs-theme="dark"] .swal2-popup {
    background: var(--app-surface) !important;
    color: var(--app-text) !important;
    border: 1px solid var(--app-border);
}
[data-bs-theme="dark"] .swal2-title {
    color: var(--app-text) !important;
}
[data-bs-theme="dark"] .swal2-html-container {
    color: var(--app-text) !important;
}
[data-bs-theme="dark"] .swal2-icon:not(.swal2-success):not(.swal2-error):not(.swal2-warning):not(.swal2-info):not(.swal2-question) {
    border-color: var(--app-border);
}
[data-bs-theme="dark"] .swal2-timer-progress-bar {
    background: var(--app-border);
}
[data-bs-theme="dark"] .swal2-cancel {
    color: var(--app-text) !important;
}
[data-bs-theme="dark"] .swal2-validation-message {
    background: var(--app-surface-soft);
    color: var(--app-text);
}

[data-bs-theme="dark"] ::selection {
    background: rgba(96, 165, 250, 0.35);
    color: #fff;
}


/* Dark dashboard polish: clearer metric text + subtle light elevation */
[data-bs-theme="dark"] #main-content .card {
    background:
        linear-gradient(180deg, rgba(255, 255, 255, 0.035), rgba(255, 255, 255, 0.012)),
        var(--app-surface);
    border: 1px solid rgba(255, 255, 255, 0.075) !important;
}

[data-bs-theme="dark"] #main-content .card.shadow-sm,
[data-bs-theme="dark"] #main-content .card.shadow,
[data-bs-theme="dark"] #main-content .card.border-0 {
    box-shadow:
        0 0 0 1px rgba(255, 255, 255, 0.055),
        0 16px 42px rgba(0, 0, 0, 0.32),
        0 0 24px rgba(255, 255, 255, 0.04) !important;
}

[data-bs-theme="dark"] #main-content .card-clickable:hover,
[data-bs-theme="dark"] #main-content .quick-action-card:hover {
    box-shadow:
        0 0 0 1px rgba(96, 165, 250, 0.28),
        0 18px 48px rgba(0, 0, 0, 0.38),
        0 0 30px rgba(96, 165, 250, 0.12) !important;
}

[data-bs-theme="dark"] #main-content .card .fw-bold,
[data-bs-theme="dark"] #main-content .card .fw-semibold,
[data-bs-theme="dark"] #main-content .card h1,
[data-bs-theme="dark"] #main-content .card h2,
[data-bs-theme="dark"] #main-content .card h3,
[data-bs-theme="dark"] #main-content .card h4,
[data-bs-theme="dark"] #main-content .card h5,
[data-bs-theme="dark"] #main-content .card h6,
[data-bs-theme="dark"] #main-content .card .text-dark:not(.badge):not(.btn) {
    color: #f8fafc !important;
}

[data-bs-theme="dark"] #main-content .card .text-muted,
[data-bs-theme="dark"] #main-content .card small.text-muted,
[data-bs-theme="dark"] #main-content .card .small.text-muted {
    color: #b6c2d2 !important;
}

[data-bs-theme="dark"] #main-content .quick-action-card.bg-light-subtle {
    background:
        linear-gradient(180deg, rgba(96, 165, 250, 0.06), rgba(255, 255, 255, 0.018)),
        var(--app-surface-soft) !important;
}

/* Grupo facturación panel */
.billing-panel__month { width: 130px; }
.billing-panel__year { width: 95px; }
.billing-panel .card-header {
    background: var(--app-surface, #fff);
    border-bottom-color: var(--app-border, rgba(0, 0, 0, .08));
}
.billing-panel__tile {
    background: #f8f9fa;
    color: var(--app-text, #212529);
    border: 1px solid var(--app-border, rgba(0, 0, 0, .08));
}
[data-bs-theme="dark"] .billing-panel .card,
[data-bs-theme="dark"] .billing-panel .card-body,
[data-bs-theme="dark"] .billing-panel .card-header {
    background-color: var(--app-surface, #111827) !important;
    color: var(--app-text, #f1f5f9) !important;
    border-color: var(--app-border, rgba(148, 163, 184, .18)) !important;
}
[data-bs-theme="dark"] .billing-panel__tile {
    background:
        linear-gradient(180deg, rgba(96, 165, 250, .075), rgba(255, 255, 255, .018)),
        var(--app-surface-soft, #1f2937) !important;
    color: var(--app-text, #f1f5f9) !important;
    border-color: var(--app-border, rgba(148, 163, 184, .20)) !important;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .035);
}
[data-bs-theme="dark"] .billing-panel__tile small {
    color: var(--app-muted, #b6c2d2) !important;
}
[data-bs-theme="dark"] .billing-panel hr {
    border-color: var(--app-border, rgba(148, 163, 184, .18));
    opacity: 1;
}
[data-bs-theme="dark"] .billing-panel .table-light,
[data-bs-theme="dark"] .billing-panel .table-light > tr,
[data-bs-theme="dark"] .billing-panel .table-light > tr > th,
[data-bs-theme="dark"] .billing-panel .table-light > th,
[data-bs-theme="dark"] .billing-panel .table-light > td {
    --bs-table-bg: rgba(148, 163, 184, .10);
    --bs-table-color: var(--app-text, #f1f5f9);
    --bs-table-border-color: var(--app-border, rgba(148, 163, 184, .18));
    background-color: rgba(148, 163, 184, .10) !important;
    color: var(--app-text, #f1f5f9) !important;
    border-color: var(--app-border, rgba(148, 163, 184, .18)) !important;
}
[data-bs-theme="dark"] .billing-panel .modal-content {
    background: var(--app-surface, #111827);
    color: var(--app-text, #f1f5f9);
    border-color: var(--app-border, rgba(148, 163, 184, .18));
}

/* ── Colores extra para la paleta de Actualizaciones ────────────────────────
   Bootstrap 5.3 solo deja 7 colores usables con el patron -subtle: "light"
   queda ilegible (texto casi blanco sobre fondo casi blanco) y "dark" y
   "secondary" se ven ambos grises. La pagina de Actualizaciones necesita un
   color distinto por bloque, asi que se completan con --bs-purple y
   --bs-orange, que Bootstrap define pero no expande a -subtle.
   Valores calculados con su misma formula: bg = tint 80%, border = tint 60%,
   texto = shade 40%; en modo oscuro bg = shade 80%, border = shade 60%,
   texto = tint 40%.                                                          */
:root {
    --bs-purple-bg-subtle: #e2d9f3;
    --bs-purple-border-subtle: #c5b3e6;
    --bs-purple-text-emphasis: #432874;
    --bs-orange-bg-subtle: #ffe5d0;
    --bs-orange-border-subtle: #fecba1;
    --bs-orange-text-emphasis: #984c0c;
}
[data-bs-theme="dark"] {
    --bs-purple-bg-subtle: #160d27;
    --bs-purple-border-subtle: #2c1a4d;
    --bs-purple-text-emphasis: #a98eda;
    --bs-orange-bg-subtle: #331904;
    --bs-orange-border-subtle: #653208;
    --bs-orange-text-emphasis: #feb272;
}
.bg-purple-subtle { background-color: var(--bs-purple-bg-subtle) !important; }
.border-purple-subtle { border-color: var(--bs-purple-border-subtle) !important; }
.text-purple { color: var(--bs-purple-text-emphasis) !important; }
.bg-orange-subtle { background-color: var(--bs-orange-bg-subtle) !important; }
.border-orange-subtle { border-color: var(--bs-orange-border-subtle) !important; }
.text-orange { color: var(--bs-orange-text-emphasis) !important; }
.btn-outline-purple {
    --bs-btn-color: var(--bs-purple-text-emphasis);
    --bs-btn-border-color: var(--bs-purple-border-subtle);
    --bs-btn-hover-color: #fff;
    --bs-btn-hover-bg: var(--bs-purple, #6f42c1);
    --bs-btn-hover-border-color: var(--bs-purple, #6f42c1);
    --bs-btn-focus-shadow-rgb: 111, 66, 193;
    --bs-btn-active-color: #fff;
    --bs-btn-active-bg: var(--bs-purple, #6f42c1);
    --bs-btn-active-border-color: var(--bs-purple, #6f42c1);
    --bs-btn-disabled-color: var(--bs-purple-text-emphasis);
    --bs-btn-disabled-border-color: var(--bs-purple-border-subtle);
}
.btn-outline-orange {
    --bs-btn-color: var(--bs-orange-text-emphasis);
    --bs-btn-border-color: var(--bs-orange-border-subtle);
    --bs-btn-hover-color: #000;
    --bs-btn-hover-bg: var(--bs-orange, #fd7e14);
    --bs-btn-hover-border-color: var(--bs-orange, #fd7e14);
    --bs-btn-focus-shadow-rgb: 253, 126, 20;
    --bs-btn-active-color: #000;
    --bs-btn-active-bg: var(--bs-orange, #fd7e14);
    --bs-btn-active-border-color: var(--bs-orange, #fd7e14);
    --bs-btn-disabled-color: var(--bs-orange-text-emphasis);
    --bs-btn-disabled-border-color: var(--bs-orange-border-subtle);
}

/* ── Modales con el formulario por fuera ───────────────
   Muchos modales envuelven cabecera, cuerpo y pie en un solo <form> para poder
   enviarlo entero. Eso rompe el scroll: .modal-content es una columna flex con
   overflow oculto, y al meter el <form> en medio su hijo directo deja de ser el
   cuerpo. El form crece con todo lo que lleva dentro, el cuerpo nunca se
   encoge, y lo que sobra se recorta contra el borde sin barra que lo alcance.
   En el celular eso deja el botón de guardar fuera de la pantalla.

   Se le da al form el mismo comportamiento que tendría el cuerpo: que sea él
   la columna que se estira y que pueda encogerse (min-height: 0, que es lo que
   permite a un hijo flex ser más bajo que su contenido). */
.modal-content > form {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
}
.modal-content > form > .modal-body {
    min-height: 0;
}
/* El recorte solo donde ya hay altura limitada: en un modal que crece libre,
   ocultar el desbordamiento del form cortaría los desplegables (tom-select,
   autocompletados) que se salen de su caja. */
.modal-dialog-scrollable .modal-content > form {
    overflow: hidden;
}

/* ── Modales: scroll interno en pantallas bajas ────────
   Bootstrap solo hace scrolleable el cuerpo del modal cuando lleva la clase
   .modal-dialog-scrollable, y la mayoría de los modales no la llevan. En el
   celular (o en cualquier ventana de poca altura, p. ej. horizontal) eso
   recortaba el contenido más alto que la pantalla: mientras el modal está
   abierto el scroll del body está bloqueado, y no había scroll interno que lo
   sustituyera. Quedaban botones de guardar a los que no se llegaba.

   Aquí se fuerza el mismo comportamiento a TODOS los modales cuando la ventana
   es estrecha o baja: cabecera y pie fijos, el cuerpo scrollea. No afecta a
   escritorio (ventana ancha y alta) ni rompe los que ya eran scrolleables.
   Se excluye modal-fullscreen, que ya ocupa toda la pantalla.

   Vive aquí y no en crm.css porque los dos portales cargan esta hoja; en el
   CRM ya funcionaba y en el panel de la ISP faltaba. */
@media (max-width: 767.98px), (max-height: 700px) {
    .modal-dialog:not(.modal-fullscreen) {
        max-height: calc(100vh - 1rem);
        max-height: calc(100dvh - 1rem);
        margin: .5rem;
    }
    .modal-dialog:not(.modal-fullscreen) .modal-content {
        max-height: calc(100vh - 1rem);
        max-height: calc(100dvh - 1rem);
        overflow: hidden; /* recorta al radio; el scroll vive en el cuerpo */
    }
    .modal-dialog:not(.modal-fullscreen) .modal-content > form {
        overflow: hidden;
    }
    .modal-dialog:not(.modal-fullscreen) .modal-body {
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
    }
}

/* ===================================================================
   El CRM instalado en la pantalla de inicio (iPhone y Android)
   ===================================================================
   Sin barra del navegador, la página empieza pegada a la hora y a la
   batería, y termina debajo de la rayita de inicio del iPhone. Estos
   márgenes solo se aplican a la app instalada: en el navegador, donde
   la barra ya ocupa ese espacio, `display-mode` no coincide y todo
   sigue igual. */
@media (display-mode: standalone) {
    .crm-topbar {
        padding-top: calc(0.5rem + env(safe-area-inset-top, 0px));
    }

    .crm-page,
    #main-content {
        padding-bottom: calc(1rem + env(safe-area-inset-bottom, 0px));
    }

    /* Los laterales importan en horizontal: ahí el notch se come un borde. */
    .crm-topbar,
    .crm-page {
        padding-left: calc(0.75rem + env(safe-area-inset-left, 0px));
        padding-right: calc(0.75rem + env(safe-area-inset-right, 0px));
    }
}


/* ===================================================================
   Pantallas táctiles: que el iPhone no haga zoom solo
   ===================================================================
   Safari amplía la página cada vez que se toca un campo de menos de
   16px, y el CRM usa `form-control-sm` (14px) en casi todos. El efecto
   es que al escribir la pantalla salta, se descuadra y hay que volver a
   encuadrar a mano; es lo que hace que el portal se sienta roto en el
   iPhone y bien en Android, que no hace eso.

   16px es el mínimo exacto que desactiva el zoom. Va encerrado en un
   `@supports` que solo cumple WebKit de iOS —`-webkit-touch-callout` no
   existe en Chrome—, porque Android no tiene este problema y allí los
   campos deben seguir del tamaño de siempre: la app de Android ya se ve
   como tiene que verse y no hay que tocarla. En el computador tampoco
   aplica: no hay dedo (`pointer: coarse`). */
@supports (-webkit-touch-callout: none) {
@media (pointer: coarse) {
    input:not([type="checkbox"]):not([type="radio"]):not([type="range"]),
    select,
    textarea,
    .form-control,
    .form-control-sm,
    .form-select,
    .form-select-sm,
    .ts-control,
    .ts-control input {
        font-size: 16px !important;
    }
}
}


/* ===================================================================
   Nada de «tirar para recargar» dentro del CRM
   ===================================================================
   En el iPhone, al llegar al tope de una lista y seguir arrastrando,
   Safari recarga la página entera. En el inbox eso es justo el gesto de
   leer mensajes anteriores: se perdía la conversación a medio escribir
   y había que esperar la carga otra vez. Cada lista sigue haciendo su
   propio scroll con normalidad; lo que se corta es el rebote que se
   propagaba a la página. */
html,
body.crm-body {
    overscroll-behavior-y: none;
}


/* ===================================================================
   El detalle en modal, a lo ancho de la pantalla
   ===================================================================
   El ojito de los listados de pagos y facturas abre la ficha dentro de
   un modal (public/js/ver-en-modal.js). Llevaba .modal-xl, que Bootstrap
   topa en 1140px: en un monitor normal eso deja media pantalla vacía a
   los lados y la ficha se lee apretada, con las tablas partidas.

   Solo de lg hacia arriba: por debajo manda .modal-fullscreen-lg-down,
   que ya lo pone a pantalla completa, y pisarlo aquí le devolvería los
   márgenes en el celular.

   Y el alto lo decide el modal, no un número fijo: el cuerpo llevaba
   height:82vh escrito en el JS, que dejaba una franja muerta abajo y, en el
   celular, hueco por debajo del iframe aunque el modal fuera a pantalla
   completa. Ahora el cuerpo se estira con el flex del modal y el iframe lo
   llena entero. El min-height es la red por si el navegador no resuelve la
   cadena de alturas: mejor un modal bajito que uno sin contenido visible. */
#modalVerEnModal .modal-body {
    display: flex;
    flex-direction: column;
    min-height: 60vh;
}
#modalVerEnModal .js-vm-iframe {
    flex: 1 1 auto;
    min-height: 0;
}

@media (min-width: 992px) {
    #modalVerEnModal .modal-dialog {
        max-width: 95vw;
        /* Casi toda la altura, dejando el aire justo para no pegarlo al borde. */
        height: calc(100vh - 2rem);
    }
    #modalVerEnModal .modal-content {
        height: 100%;
    }
}


/* ── Visor de documentos (public/js/visor-documento.js) ─────────────────────
   El PDF se dibuja en canvas dentro del modal. Arriba va lo que saca el
   documento del sistema (descargar, imprimir) y abajo, al centro, lo de
   mirarlo (tamaño, página, lista de páginas).

   Los tokens del sistema de diseño hacen el modo oscuro solo; la zona del
   documento se queda gris siempre, porque el papel es blanco en los dos modos
   y sobre fondo oscuro se lee mejor con un marco que lo separe. */
.visor-doc .modal-dialog {
    max-width: 95vw;
    width: 95vw;
}
.visor-doc .modal-content {
    border-radius: 16px;
    overflow: hidden;
    height: calc(100vh - 2rem);
    max-height: calc(100vh - 2rem);
}

/* Barra de arriba: el documento y lo que se puede sacar de él. */
.visor-doc-barra {
    padding: .55rem .75rem;
    gap: .5rem;
    flex-wrap: nowrap;
    align-items: center;
}
.visor-doc-titulo {
    display: flex;
    align-items: center;
    gap: .5rem;
    min-width: 0;
    font-weight: 600;
    font-size: .95rem;
}
.visor-doc-titulo .js-visor-titulo {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Que el papel de la pantalla no se confunda con el bueno. */
.visor-doc-chip {
    flex-shrink: 0;
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    padding: .18rem .5rem;
    border-radius: 999px;
    background: var(--amber-50, #fffbeb);
    color: var(--amber-600, #d97706);
    border: 1px solid var(--amber-500, #f59e0b);
}
.visor-doc-acciones {
    display: flex;
    align-items: center;
    gap: .4rem;
    margin-left: auto;
    flex-shrink: 0;
}
/* El aire entre el icono y su texto. Sin esto quedaban pegados: el botón es
   flex y el margen de Bootstrap no aplica a un <span> hermano del icono. */
.visor-doc .btn > .bi {
    line-height: 1;
}
.visor-doc-acciones .btn,
.visor-doc-pie .btn {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
}

/* Cuerpo: la lista de páginas a un lado y el documento al otro. */
.visor-doc-marco {
    padding: 0;
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
    overflow: hidden;
}
.visor-doc-zona {
    display: flex;
    flex: 1 1 auto;
    min-height: 0;
}
.visor-doc-cuerpo {
    position: relative;      /* lo que mide offsetTop de cada página */
    background: #94a3b8;
    overflow: auto;
    flex: 1 1 auto;
    min-width: 0;
}
.visor-doc-paginas {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    padding: 12px;
}
.visor-doc-pagina {
    display: block;
    background: #fff;
    box-shadow: 0 4px 14px rgba(15, 23, 42, .35);
    max-width: 100%;
}

/*
 | Documento acercado: la página puede ser más ancha que el marco y hay que
 | poder llegar hasta su borde.
 |
 | El tope de ancho se levanta solo al acercar; ajustado (escala 1) se queda
 | como cinturón, para que un cálculo de ancho equivocado no desborde el visor.
 |
 | Y el centrado pasa a `flex-start` con márgenes automáticos: en un flex, el
 | hijo más ancho que su caja queda cortado por la izquierda y el scroll no
 | alcanza esa parte. Eso hacía que acercar en el teléfono no sirviera de nada
 | —la letra seguía igual de chica— porque el lienzo crecía y el CSS lo recortaba
 | al ancho de la pantalla. Con márgenes automáticos sigue centrado mientras
 | quepa.
 */
.visor-doc-paginas.es-ampliado {
    align-items: flex-start;
}
.visor-doc-paginas.es-ampliado .visor-doc-pagina {
    max-width: none;
    margin-inline: auto;
}

/* La lista de páginas, como la del visor del navegador. */
.visor-doc-tiras {
    flex: 0 0 auto;
    width: 138px;
    overflow: auto;
    padding: 12px 0;
    background: #64748b;
    border-right: 1px solid rgba(15, 23, 42, .25);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
}
.visor-doc-tira {
    border: 2px solid transparent;
    background: none;
    padding: 0;
    border-radius: 4px;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    line-height: 1;
}
.visor-doc-tira canvas {
    display: block;
    background: #fff;
    box-shadow: 0 2px 6px rgba(15, 23, 42, .3);
}
.visor-doc-tira span {
    font-size: .72rem;
    font-weight: 600;
    color: #f1f5f9;
}
.visor-doc-tira:hover canvas {
    outline: 2px solid rgba(255, 255, 255, .5);
}
.visor-doc-tira.es-actual {
    border-color: var(--blue-500, #3b82f6);
}
.visor-doc-tira.es-actual span {
    color: #fff;
}

.visor-doc-cargando,
.visor-doc-error {
    padding: 2.5rem 1rem;
    text-align: center;
    color: #f8fafc;
    font-size: .9rem;
}
.visor-doc-error i {
    display: block;
    font-size: 1.8rem;
}
.visor-doc-aviso {
    margin: 0;
    padding: .6rem .9rem;
    font-size: .85rem;
    background: var(--blue-50, #eff6ff);
    color: var(--blue-600, #2563eb);
    border-bottom: 1px solid var(--border, #e2e8f0);
}
.visor-doc-aviso.es-ok {
    background: var(--green-50, #f0fdf4);
    color: var(--green-700, #15803d);
}

/* Barra de abajo: el tamaño y la página, centrados. El botón de la lista va
   colocado aparte para que el centro sea el centro de verdad y no se corra
   según lo que haya a los lados. */
.visor-doc-pie {
    position: relative;
    padding: .5rem .75rem;
    justify-content: center;
    gap: .5rem;
    flex-wrap: nowrap;
}
/* Bootstrap le pone un margen a cada hijo del pie del modal; con el gap de
   arriba quedaría doble, y al botón de la izquierda le corría su posición. */
.visor-doc-pie > * {
    margin: 0;
}
.visor-doc-pie-izq {
    position: absolute;
    left: .75rem;
}
.visor-doc-pie-centro {
    display: flex;
    align-items: center;
    gap: .75rem;
}
.visor-doc-zoom {
    display: flex;
    gap: .15rem;
}
.visor-doc-zoom .js-visor-ajustar {
    min-width: 58px;
    justify-content: center;
    font-variant-numeric: tabular-nums;
}
.visor-doc-paginado {
    font-size: .82rem;
    font-weight: 600;
    color: var(--ink-muted, #94a3b8);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* En el teléfono las barras solo tienen sitio para los iconos, y el modal va a
   pantalla completa: el documento necesita todo el alto que haya. La lista de
   páginas se estrecha, que si no se come media pantalla. */
@media (max-width: 767.98px) {
    .visor-doc .modal-dialog {
        max-width: 100%;
        width: 100%;
        margin: 0;
    }
    .visor-doc .modal-content {
        height: 100vh;
        max-height: 100vh;
        border-radius: 0;
    }
    .visor-doc-texto {
        display: none;
    }
    .visor-doc-chip {
        display: none;
    }
    .visor-doc-titulo {
        font-size: .85rem;
    }
    .visor-doc-tiras {
        width: 96px;
    }
    .visor-doc-pie-centro {
        gap: .5rem;
    }
}

/* Imprimir la pantalla no es imprimir el documento: el papel bueno sale por el
   botón, que pasa por la ruta que sella. Si alguien manda Ctrl+P con el visor
   abierto, sale el aviso y no un recibo a medias. */
@media print {
    body:has(.visor-doc.show) > *:not(.visor-doc) {
        display: none !important;
    }
    .visor-doc.show .visor-doc-marco,
    .visor-doc.show .visor-doc-pie,
    .visor-doc.show .visor-doc-acciones {
        display: none !important;
    }
    .visor-doc.show .visor-doc-barra::after {
        content: 'Para imprimir este documento usá el botón Imprimir del visor: ese papel sale sellado y queda anotado.';
        font-weight: 400;
        font-size: .9rem;
    }
}

/* ═══════════════════════════════════════════════════════════════
   El confirmador (window.Confirmar)

   El diálogo de las acciones que mueven dinero o cierran una jornada.
   No usa el modal de Bootstrap ni SweetAlert: se dibuja aquí para poder
   decir de un vistazo QUÉ se está haciendo —el color y el icono cambian
   con la acción— y para quedarse con un spinner que nombra lo que está
   pasando mientras el navegador envía el formulario.
══════════════════════════════════════════════════════════════ */
.cfm-fondo {
    position: fixed;
    inset: 0;
    z-index: 20050;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    background: rgba(15, 23, 42, .55);
    backdrop-filter: blur(3px);
    opacity: 0;
    transition: opacity .18s ease;
    overflow-y: auto;
}

.cfm-fondo.abierto { opacity: 1; }

.cfm-caja {
    /* El acento lo pone el tono de la acción; este es el neutro. */
    --cfm-acento: #2563eb;
    --cfm-acento-ink: #1d4ed8;
    --cfm-acento-suave: #eff6ff;
    --cfm-borde-acento: #bfdbfe;

    position: relative;
    width: 100%;
    max-width: 480px;
    margin: auto;
    background: var(--app-surface, #fff);
    color: var(--app-text, #0f172a);
    border: 1px solid var(--app-border, #e2e8f0);
    border-radius: 18px;
    box-shadow: 0 24px 60px rgba(15, 23, 42, .25);
    overflow: hidden;
    transform: translateY(16px) scale(.96);
    opacity: 0;
    transition: transform .22s cubic-bezier(.2, .8, .3, 1), opacity .18s ease;
}

.cfm-fondo.abierto .cfm-caja {
    transform: translateY(0) scale(1);
    opacity: 1;
}

.cfm-tono-verde  { --cfm-acento: #16a34a; --cfm-acento-ink: #15803d; --cfm-acento-suave: #f0fdf4; --cfm-borde-acento: #bbf7d0; }
.cfm-tono-ambar  { --cfm-acento: #d97706; --cfm-acento-ink: #b45309; --cfm-acento-suave: #fffbeb; --cfm-borde-acento: #fde68a; }
.cfm-tono-rojo   { --cfm-acento: #dc2626; --cfm-acento-ink: #b91c1c; --cfm-acento-suave: #fef2f2; --cfm-borde-acento: #fecaca; }
.cfm-tono-azul   { --cfm-acento: #2563eb; --cfm-acento-ink: #1d4ed8; --cfm-acento-suave: #eff6ff; --cfm-borde-acento: #bfdbfe; }

/* La franja de color de arriba es la señal más rápida de qué acción es. */
.cfm-caja::before {
    content: '';
    position: absolute;
    inset: 0 0 auto 0;
    height: 4px;
    background: var(--cfm-acento);
}

.cfm-cabecera {
    display: flex;
    align-items: flex-start;
    gap: .85rem;
    padding: 1.35rem 1.35rem 0 1.35rem;
}

.cfm-icono {
    flex-shrink: 0;
    width: 44px;
    height: 44px;
    border-radius: 13px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.25rem;
    color: var(--cfm-acento-ink);
    background: var(--cfm-acento-suave);
    border: 1px solid var(--cfm-borde-acento);
}

.cfm-encabezado { flex: 1 1 auto; min-width: 0; }

.cfm-titulo {
    margin: 0;
    font-size: 1.08rem;
    font-weight: 700;
    line-height: 1.3;
    color: var(--app-text, #0f172a);
}

.cfm-sub {
    margin: .25rem 0 0;
    font-size: .875rem;
    line-height: 1.45;
    color: var(--app-muted, #64748b);
}

.cfm-cerrar {
    flex-shrink: 0;
    width: 30px;
    height: 30px;
    border: 0;
    border-radius: 9px;
    background: transparent;
    color: var(--app-muted, #64748b);
    font-size: .85rem;
    line-height: 1;
    cursor: pointer;
    transition: background .15s ease, color .15s ease;
}

.cfm-cerrar:hover {
    background: var(--app-surface-soft, #f1f5f9);
    color: var(--app-text, #0f172a);
}

.cfm-cuerpo { padding: 1.1rem 1.35rem 0 1.35rem; }
.cfm-cuerpo > *:last-child { margin-bottom: 0; }

/* El resumen de lo que va a pasar. */
.cfm-datos {
    margin: 0 0 1rem;
    border: 1px solid var(--app-border, #e2e8f0);
    border-radius: 12px;
    background: var(--app-surface-soft, #f8fafc);
    overflow: hidden;
}

.cfm-fila {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    padding: .55rem .85rem;
}

.cfm-fila + .cfm-fila { border-top: 1px solid var(--app-border, #e2e8f0); }

.cfm-fila-etiqueta {
    font-size: .74rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--app-muted, #64748b);
}

.cfm-fila-valor {
    font-size: .92rem;
    font-weight: 600;
    text-align: right;
    color: var(--app-text, #0f172a);
}

.cfm-aviso {
    display: flex;
    gap: .6rem;
    margin-bottom: .75rem;
    padding: .65rem .8rem;
    font-size: .845rem;
    line-height: 1.45;
    border-radius: 11px;
    color: #92400e;
    background: #fffbeb;
    border: 1px solid #fde68a;
}

.cfm-aviso > i { flex-shrink: 0; margin-top: .1rem; }
.cfm-aviso strong { font-weight: 700; }

.cfm-campos { margin-bottom: .25rem; }
.cfm-campos .form-label { font-size: .78rem; font-weight: 600; }

.cfm-pie {
    display: flex;
    justify-content: flex-end;
    gap: .6rem;
    padding: 1.15rem 1.35rem 1.35rem;
}

.cfm-btn {
    border: 1px solid transparent;
    border-radius: 11px;
    padding: .55rem 1.1rem;
    font-size: .9rem;
    font-weight: 600;
    cursor: pointer;
    transition: transform .12s ease, filter .15s ease, background .15s ease;
}

.cfm-btn:active { transform: scale(.97); }
.cfm-btn:focus-visible { outline: 3px solid var(--app-focus-ring, rgba(37, 99, 235, .22)); outline-offset: 1px; }

.cfm-btn-fantasma {
    background: transparent;
    border-color: var(--app-border-strong, #cbd5e1);
    color: var(--app-muted, #64748b);
}

.cfm-btn-fantasma:hover {
    background: var(--app-surface-soft, #f1f5f9);
    color: var(--app-text, #0f172a);
}

.cfm-btn-accion {
    background: var(--cfm-acento);
    color: #fff;
    box-shadow: 0 6px 16px -6px var(--cfm-acento);
}

.cfm-btn-accion:hover { filter: brightness(1.06); }

/* Mientras el formulario viaja: la caja se queda, y encima aparece el nombre
   de lo que está pasando. Un spinner sin frase no dice si abrió o cerró. */
.cfm-cargando {
    position: absolute;
    inset: 0;
    display: none;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .85rem;
    padding: 1.5rem;
    text-align: center;
    background: rgba(var(--app-surface-rgb, 255, 255, 255), .92);
    backdrop-filter: blur(2px);
}

.cfm-caja.cargando .cfm-cargando { display: flex; }

.cfm-spinner {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    border: 3px solid var(--cfm-borde-acento);
    border-top-color: var(--cfm-acento);
    animation: cfmGiro .7s linear infinite;
}

.cfm-cargando-texto {
    font-size: .95rem;
    font-weight: 600;
    color: var(--cfm-acento-ink);
}

.cfm-cargando-nota {
    font-size: .8rem;
    color: var(--app-muted, #64748b);
}

@keyframes cfmGiro { to { transform: rotate(360deg); } }

[data-bs-theme="dark"] .cfm-caja {
    box-shadow: 0 24px 60px rgba(0, 0, 0, .55);
}

[data-bs-theme="dark"] .cfm-tono-verde  { --cfm-acento: #22c55e; --cfm-acento-ink: #86efac; --cfm-acento-suave: rgba(34, 197, 94, .12); --cfm-borde-acento: rgba(34, 197, 94, .35); }
[data-bs-theme="dark"] .cfm-tono-ambar  { --cfm-acento: #f59e0b; --cfm-acento-ink: #fcd34d; --cfm-acento-suave: rgba(245, 158, 11, .12); --cfm-borde-acento: rgba(245, 158, 11, .35); }
[data-bs-theme="dark"] .cfm-tono-rojo   { --cfm-acento: #ef4444; --cfm-acento-ink: #fca5a5; --cfm-acento-suave: rgba(239, 68, 68, .12); --cfm-borde-acento: rgba(239, 68, 68, .35); }
[data-bs-theme="dark"] .cfm-tono-azul   { --cfm-acento: #3b82f6; --cfm-acento-ink: #93c5fd; --cfm-acento-suave: rgba(59, 130, 246, .12); --cfm-borde-acento: rgba(59, 130, 246, .35); }

[data-bs-theme="dark"] .cfm-aviso {
    color: #fde68a;
    background: rgba(245, 158, 11, .1);
    border-color: rgba(245, 158, 11, .3);
}

[data-bs-theme="dark"] .cfm-btn-accion { color: #0b1120; }

@media (max-width: 575.98px) {
    .cfm-fondo { padding: .75rem; align-items: flex-end; }
    .cfm-caja { max-width: 100%; border-radius: 20px 20px 14px 14px; }
    .cfm-pie { flex-direction: column-reverse; }
    .cfm-pie .cfm-btn { width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
    .cfm-fondo,
    .cfm-caja { transition: none; }
    .cfm-spinner { animation-duration: 1.6s; }
}

/*
 | Lo que se teclea en el mostrador se ve como se va a guardar.
 |
 | La referencia y las observaciones de un cobro se guardan en mayúsculas —los
 | recibos salen por impresoras térmicas y así es como se imprimen—, y el
 | cajero tiene que verlo mientras escribe: si teclea «consignación nequi» en
 | minúscula y el papel sale en mayúscula, parece que el sistema le cambió lo
 | que puso.
 |
 | Es solo la pintura: el valor que viaja sigue siendo el tecleado y quien lo
 | pasa a mayúsculas de verdad es el servidor, que es el único sitio donde eso
 | no se puede saltar.
 */
.texto-de-mostrador {
    text-transform: uppercase;
}

.texto-de-mostrador::placeholder {
    text-transform: none;
}
