/* ╔══════════════════════════════════════════════════════════════════════╗
   ║  ElectroSoftERP — Capa MÍNIMA sobre ArchitectUI HTML PRO nativo        ║
   ║                                                                          ║
   ║  Política estricta: NO pelear con `base.min.css`. Solo añadir helpers   ║
   ║  que no estén en la plantilla nativa:                                   ║
   ║    1) Tipografía Inter (sobrescribe la sans-serif del tema)             ║
   ║    2) Z-index modal por encima del sidebar fixed (bug nativo BS4)       ║
   ║    3) Form labels visibles (BS4 los hace muy pequeños)                  ║
   ║    4) Toast container (no incluido en ArchitectUI)                      ║
   ║    5) Helpers ERP: tabular-nums, POS, page-title small refinement       ║
   ║                                                                          ║
   ║  Todo lo demás (cards, badges, botones, sidebar, tablas, dropdowns)     ║
   ║  se respeta del CSS nativo de ArchitectUI sin modificación.             ║
   ╚══════════════════════════════════════════════════════════════════════╝ */


/* ────────────────────────────────────────────────────────────────────────
   1) TIPOGRAFÍA Inter (Google Fonts) sobre el sans-serif base
   ──────────────────────────────────────────────────────────────────────── */
html, body,
.app-header, .app-sidebar, .app-main, .vertical-nav-menu,
.page-title-heading, .card-title, .card-header, .table, .form-control, .btn,
input, button, select, textarea {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;
}

code, kbd, samp, pre, .tabular-nums, .font-monospace {
    font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.tabular-nums { font-variant-numeric: tabular-nums; }


/* ────────────────────────────────────────────────────────────────────────
   2) MODALES — backdrop full viewport + bloqueo interacción del fondo
      BS4 calcula altura del backdrop con 100% del padre, lo que falla cuando
      body.modal-open tiene overflow:hidden y el body es más alto que viewport.
      Forzamos 100vw x 100vh con position:fixed inset:0.
   ──────────────────────────────────────────────────────────────────────── */

/* Backdrop SIEMPRE cubre viewport completo y con oscuridad fuerte
   IMPORTANTE: ArchitectUI nativo aplica `background-color:#000; opacity:.5` al
   .modal-backdrop.show, lo que da un gris muy ligero. Usamos #000 sólido
   con opacity 0.7 para un velo claramente notable (estilo Stripe/Linear). */
.modal-backdrop,
.modal-backdrop.show,
.modal-backdrop.fade.show {
    position: fixed !important;
    top: 0 !important; left: 0 !important;
    right: 0 !important; bottom: 0 !important;
    width: 100vw !important;
    height: 100vh !important;
    z-index: 1080 !important;
    background-color: #000 !important;
    opacity: 0.7 !important;
}

/* Modal contenedor también full viewport */
.modal {
    position: fixed !important;
    top: 0 !important; left: 0 !important;
    width: 100vw !important;
    height: 100vh !important;
    z-index: 1090 !important;
}

.tooltip { z-index: 1100 !important; }
.popover { z-index: 1100 !important; }

/* SweetAlert2 por defecto usa z-index 1060, que queda DEBAJO de nuestros
   modales (1090). Lo subimos para que las alertas/confirmaciones siempre
   aparezcan por encima de cualquier modal abierto. */
.swal2-container { z-index: 11000 !important; }

/* Cuando hay modal abierto: bajar capas del fondo y bloquear su interacción */
body.modal-open {
    overflow: hidden !important;
    padding-right: 0 !important;
}
body.modal-open .app-sidebar,
body.modal-open .app-header,
body.modal-open .app-main,
body.modal-open .app-page-title,
body.modal-open .pos-shell {
    z-index: 1 !important;
    pointer-events: none !important;
}
/* El modal y sus hijos SIEMPRE reciben clicks (anula el pointer-events:none del padre si se aplica) */
.modal, .modal-backdrop,
.modal-dialog, .modal-content,
.modal-header, .modal-body, .modal-footer {
    pointer-events: auto !important;
}

/* Modal-content limpio: borde sutil, sin sombra proyectada */
.modal-content {
    border-radius: 8px;
    border: 1px solid rgba(0, 0, 0, .12);
    box-shadow: none;
}


/* ────────────────────────────────────────────────────────────────────────
   3) SIDEBAR ICONS — ArchitectUI nativo pone opacity:.3 a .metismenu-icon
      (pensado para sidebar oscuro). En sidebar claro queda casi invisible.
      Forzamos opacidad completa y mantenemos el color que pone la clase
      (text-primary, text-warning, icon-gradient bg-*).
   ──────────────────────────────────────────────────────────────────────── */
.vertical-nav-menu i.metismenu-icon,
.vertical-nav-menu i.metismenu-state-icon,
.metismenu-icon {
    opacity: 1 !important;
}
.vertical-nav-menu li a:hover i.metismenu-icon { opacity: 1 !important; }

/* Para sidebar oscuro (clase opcional), bajar a .85 sin desaparecer */
.app-sidebar.sidebar-dark .metismenu-icon { opacity: .85 !important; }

/* Iconos sin clase de color: dar un color neutro fuerte para que se vean */
.vertical-nav-menu i.metismenu-icon:not([class*="text-"]):not([class*="icon-gradient"]) {
    color: #3f6ad8;
}

/* metismenu-state-icon (la flecha de submenú) — gris medio */
.vertical-nav-menu i.metismenu-state-icon { color: #6c757d; }

/* icon-gradient bg-* en el sidebar: ArchitectUI tiene una 2ª regla que pone
   color:#fff + background:0 0 !important, lo que en sidebar claro deja el
   icono blanco sobre blanco (invisible). Forzamos el clip a 'text' para que
   se renderice el gradient real definido por bg-mean-fruit, bg-mixed-hopes, etc. */
.vertical-nav-menu .metismenu-icon.icon-gradient,
.app-sidebar .metismenu-icon.icon-gradient {
    -webkit-background-clip: text !important;
    background-clip: text !important;
    -webkit-text-fill-color: transparent !important;
    color: transparent !important;
}

/* Si por alguna razón el gradient no aplica, fallback a brand visible */
.vertical-nav-menu .metismenu-icon.icon-gradient:not([class*="bg-"]) {
    -webkit-text-fill-color: #3f6ad8 !important;
    color: #3f6ad8 !important;
}


/* ────────────────────────────────────────────────────────────────────────
   3) FORM LABELS — BS4 los hace muy chicos y sin peso. Hacerlos legibles.
   ──────────────────────────────────────────────────────────────────────── */
label, .form-label {
    font-weight: 600;
    font-size: 13px;
    margin-bottom: 6px;
    color: #495057;
    display: block;
}


/* ────────────────────────────────────────────────────────────────────────
   4) WIDGET KPI — truncado de números muy largos (que se desbordan en RD$)
   ──────────────────────────────────────────────────────────────────────── */
/* ── Cards KPI: auto-fit del valor numérico ──
   Combinamos: tamaño conservador + flex con min-width:0 + ellipsis.
   El JS auto-fit del layout reduce más si el contenido aún excede. */
.widget-chart .widget-numbers,
.widget-chart .widget-subheading,
.widget-chart-flex {
    max-width: 100%;
    overflow: hidden;
    white-space: nowrap;
    min-width: 0;
}
.widget-chart .widget-numbers,
.widget-content .widget-numbers,
.widget-numbers.auto-fit {
    font-variant-numeric: tabular-nums;
    /* Base conservador: 22px desktop, 15px mobile. El JS reduce más si hace falta. */
    font-size: clamp(15px, 1.2vw + .4rem, 22px) !important;
    line-height: 1.2;
    display: block;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* .fit-text: el JS auto-fit reduce la fuente hasta que el contenido (nombre o monto)
   se muestre COMPLETO en una sola línea, en lugar de cortarse con ellipsis. */
.fit-text {
    display: block;
    max-width: 100%;
    white-space: nowrap;
    overflow: hidden;
}
/* Utilidad: permite que un flex item encoja y su contenido haga ellipsis/fit. */
.min-width-0 { min-width: 0; }
/* Flex anidado (widget-chart2): min-width:0 OBLIGA al flex item a respetar el padre.
   flex-wrap permite que el <small> ("vs mes anterior") baje a otra línea si no cabe. */
.widget-chart2 .widget-chart-flex,
.widget-chart .widget-chart-flex {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    min-width: 0;
    overflow: hidden;
    width: 100%;
}
.widget-chart2 .widget-chart-flex > div,
.widget-chart .widget-chart-flex > div {
    min-width: 0;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 4px;
}
/* El <small> que acompaña al número va a línea separada */
.widget-chart2 .widget-chart-flex > div > small,
.widget-chart .widget-chart-flex > div > small {
    flex-basis: 100%;
    margin-top: 4px;
    padding-left: 0 !important;
    font-size: 11.5px !important;
    line-height: 1.2;
}
/* Icono lateral: tamaño fijo en cuadro 32x32, no compite por ancho con el número */
.widget-chart2 .widget-chart-flex > div > span:first-child,
.widget-chart .widget-chart-flex > div > span:first-child {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    padding: 0 !important;
    margin-right: 4px !important;
    font-size: 18px !important;
    opacity: 1 !important;
}
.widget-chart2 .widget-chart-flex > div > span:first-child > i { font-size: 20px; }


/* ────────────────────────────────────────────────────────────────────────
   5) PAGE-TITLE refinement (compatible con app-page-title-simple)
   ──────────────────────────────────────────────────────────────────────── */
.page-title-head { display: flex; align-items: center; }
.page-title-head .icon-gradient { font-size: 30px; margin-right: 8px; }


/* ────────────────────────────────────────────────────────────────────────
   6) TOAST CONTAINER (no nativo en ArchitectUI; lo usamos en POS y forms)
   ──────────────────────────────────────────────────────────────────────── */
.erp-toast-wrap {
    position: fixed; top: 20px; right: 20px;
    /* Por encima de modales (1090) y de los popups SweetAlert (11000):
       los toasts siempre deben ser visibles, incluso sobre un modal abierto. */
    z-index: 12000;
    display: flex; flex-direction: column; gap: 10px;
    pointer-events: none;
    max-width: 380px;
}
.erp-toast {
    background: #ffffff;
    border: 1px solid #e9ecef;
    border-left: 4px solid #3f6ad8;
    border-radius: 6px;
    padding: 12px 16px;
    box-shadow: 0 8px 24px rgba(15,23,42,.16);
    color: #212529;
    pointer-events: auto;
    display: flex; align-items: flex-start; gap: 12px;
    animation: erp-toast-in 200ms ease-out;
    font-size: 14px;
    line-height: 1.4;
}
.erp-toast.success { border-left-color: #3ac47d; }
.erp-toast.danger  { border-left-color: #d92550; }
.erp-toast.warning { border-left-color: #f7b924; }
.erp-toast.info    { border-left-color: #16aaff; }
.erp-toast .erp-toast-icon { font-size: 22px; flex-shrink: 0; }
.erp-toast.success .erp-toast-icon { color: #3ac47d; }
.erp-toast.danger  .erp-toast-icon { color: #d92550; }
.erp-toast.warning .erp-toast-icon { color: #f7b924; }
.erp-toast.info    .erp-toast-icon { color: #16aaff; }
.erp-toast .erp-toast-close { background: none; border: 0; color: #6c757d; cursor: pointer; padding: 0 4px; font-size: 18px; line-height: 1; }
@keyframes erp-toast-in { from { transform: translateX(120%); opacity: 0; } to { transform: translateX(0); opacity: 1; } }


/* ────────────────────────────────────────────────────────────────────────
   7) POS — layout enterprise sobre la grid nativa del tema
   ──────────────────────────────────────────────────────────────────────── */
/* ── MODO POS: sin scroll global, layout flex en altura completa ─────── */
body.pos-no-scroll { overflow: hidden !important; }
/* El tema reserva 60px abajo (.app-main__outer padding-bottom) para el footer.
   En POS lo anulamos: si no, .app-main__inner queda 60px más alto que el área
   visible y empuja el bloque de totales/botones fuera de la pantalla. */
body.pos-no-scroll .app-main__outer { padding-bottom: 0 !important; }
/* CLAVE (ancho): bug clásico de flex — un item de flex con min-width:auto NO se
   encoge por debajo del ancho mínimo de su contenido. Sin min-width:0 en la
   cadena, el POS (cuya barra superior + grid no quieren encoger) ensancha
   .app-main__inner más allá del viewport (~1488px a 1080) y empuja la columna
   del carrito fuera de la pantalla. Forzamos que toda la cadena pueda encoger. */
body.pos-no-scroll .app-main,
body.pos-no-scroll .app-main__outer { min-width: 0 !important; max-width: 100%; }
body.pos-no-scroll .app-main__outer { overflow-x: hidden; }
body.pos-no-scroll .app-main__inner {
    display: flex;
    flex-direction: column;
    /* CLAVE: el tema aplica flex:1 (flex-basis:0%) aquí, lo que ANULA la
       propiedad height en el eje flex. Forzamos flex:0 0 auto para que la
       altura explícita gane y el contenedor quede acotado al viewport.
       Sin esto, .app-container (min-height:100vh, puede crecer) deja que el
       contenido empuje todo y el body (overflow:hidden) recorta los botones. */
    flex: 0 0 auto !important;
    height: calc(100vh - 60px);          /* 60px = .app-header — fallback */
    height: calc(100dvh - 60px);         /* dvh: respeta barras del navegador */
    min-height: 0;
    max-height: calc(100vh - 60px);
    /* Acotar el ANCHO al área disponible: no debe crecer con el contenido. */
    width: 100%;
    max-width: 100%;
    min-width: 0;
    box-sizing: border-box;
    padding: 10px !important;
    overflow: hidden;
}
body.pos-no-scroll .app-page-title,
body.pos-no-scroll .app-wrapper-footer,
body.pos-no-scroll .app-footer { display: none !important; }

/* ── Topbar (compacta y de altura fija) ──────────────────────────────── */
.pos-topbar {
    background: #fff;
    border: 1px solid #e9ecef;
    border-radius: 8px;
    padding: 8px 12px;
    margin-bottom: 8px;
    display: flex;
    flex-wrap: nowrap;
    gap: 10px;
    justify-content: space-between;
    align-items: center;
    flex-shrink: 0;
    overflow: hidden;
}
.pos-topbar-left  { display: flex; flex-wrap: nowrap; gap: 12px; align-items: center; min-width: 0; overflow: hidden; }
.pos-topbar-title { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.pos-topbar-title > i { font-size: 24px; color: #3f6ad8; }
.pos-topbar-title-main { font-weight: 700; font-size: 15px; color: #212529; line-height: 1.1; }
.pos-topbar-title-sub  { font-size: 11px; color: #6c757d; margin-top: 1px; line-height: 1.1; }
.pos-topbar-title-sub i { color: #adb5bd; }
.pos-topbar-pills { display: flex; flex-wrap: nowrap; gap: 5px; min-width: 0; overflow-x: auto; scrollbar-width: none; }
.pos-topbar-pills::-webkit-scrollbar { display: none; }
.pos-topbar-actions { display: flex; flex-wrap: nowrap; gap: 5px; flex-shrink: 0; }
.pos-topbar .pos-stat-pill { padding: 4px 9px; font-size: 11.5px; white-space: nowrap; flex-shrink: 0; }
.pos-topbar .pos-stat-pill i { font-size: 12px; }

.pos-tool-btn {
    background: #fff;
    border: 1px solid #ced4da;
    color: #495057;
    border-radius: 6px;
    padding: 5px 10px;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    white-space: nowrap;
    transition: all .12s;
}
.pos-tool-btn:hover { background: #f1f5f9; border-color: #3f6ad8; color: #3f6ad8; }
.pos-tool-btn i { font-size: 16px; }
.pos-tool-btn-success { background: #198754; color: #fff; border-color: #198754; }
.pos-tool-btn-success:hover { background: #146c43; border-color: #146c43; color: #fff; }
.pos-tool-btn-warning { background: #ffc107; color: #212529; border-color: #ffc107; }
.pos-tool-btn-warning:hover { background: #e0a800; border-color: #e0a800; color: #212529; }
.pos-tool-btn-danger { background: #dc3545; color: #fff; border-color: #dc3545; }
.pos-tool-btn-danger:hover { background: #b02a37; border-color: #b02a37; color: #fff; }
.pos-tool-btn-info { background: #0dcaf0; color: #053742; border-color: #0dcaf0; }
.pos-tool-btn-info:hover { background: #31d2f2; border-color: #31d2f2; color: #053742; }
.pos-hold-count {
    background: rgba(255,255,255,.3); color: #fff;
    border-radius: 999px; padding: 1px 7px; font-size: 11px; font-weight: 700;
    margin-left: 2px; min-width: 18px; text-align: center;
}
.pos-tool-btn-success .pos-hold-count { background: rgba(0,0,0,.15); color: #fff; }
.pos-stat-pill.stat-money { background: #d1e7dd; color: #0a3622; border-color: #a3cfbb; }
.pos-stat-pill.stat-money i { color: #198754; }
.pos-stat-pill.stat-tx { background: #cfe2ff; color: #084298; border-color: #9ec5fe; }
.pos-stat-pill.stat-tx i { color: #0d6efd; }
.pos-stat-pill.stat-clock { background: #f8f9fa; color: #495057; }
.pos-stat-pill.stat-clock i { color: #6c757d; }
.pos-stat-pill.stat-conn { font-variant-numeric: tabular-nums; }
.pos-stat-pill.stat-conn.online { background: #d1e7dd; color: #0a3622; border-color: #a3cfbb; }
.pos-stat-pill.stat-conn.online i { color: #198754; }
.pos-stat-pill.stat-conn.offline { background: #f8d7da; color: #842029; border-color: #f5c2c7; }
.pos-stat-pill.stat-conn.offline i { color: #dc3545; }

/* ── Shell — ocupa el resto del viewport con flex ────────────────────── */
.pos-shell {
    display: grid;
    grid-template-columns: 1fr 420px;
    /* Fila única acotada a la altura del contenedor: evita que la columna del
       carrito crezca con su contenido y empuje totales/botones fuera de vista.
       minmax(0,1fr) permite que los hijos (cart-list) hagan scroll interno. */
    grid-template-rows: minmax(0, 1fr);
    gap: 10px;
    flex: 1 1 auto;
    min-height: 0;
    position: relative;
    overflow: hidden;
}
@media (max-width: 1599.98px) { .pos-shell { grid-template-columns: 1fr 400px; } }
@media (max-width: 1399.98px) { .pos-shell { grid-template-columns: 1fr 370px; } }
@media (max-width: 1199.98px) { .pos-shell { grid-template-columns: 1fr 340px; } }
@media (max-width: 991.98px) {
    body.pos-no-scroll { overflow: auto !important; }
    body.pos-no-scroll .app-main__inner { height: auto; overflow: visible; }
    /* Layout apilado: la página vuelve a hacer scroll, así que las filas se
       dimensionan por contenido (no acotadas a la altura del viewport). */
    .pos-shell { grid-template-columns: 1fr; grid-template-rows: none; overflow: visible; }
    .pos-side { order: -1; }
    .pos-side, .pos-main { overflow: visible; }
    .pos-cart-list { max-height: 260px; }
    .pos-products-grid { max-height: 60vh; }
}
@media (max-width: 767.98px) {
    .pos-topbar-title-sub { display: none; }
    .pos-topbar-actions .pos-tool-btn span:not(.pos-hold-count):not(.pos-hotkey-chip) { display: none; }
    .pos-topbar-actions .pos-tool-btn { padding: 5px 8px; }
    .pos-stat-pill { font-size: 10.5px; padding: 3px 7px; }
}

/* Fullscreen toggle */
body.pos-fullscreen .app-main__inner { padding: 6px !important; height: 100vh; }
body.pos-fullscreen .app-header,
body.pos-fullscreen .app-sidebar { display: none !important; }
body.pos-fullscreen .app-main { padding-top: 0 !important; }

/* Panels (main + side) — internal scroll */
body.pos-no-scroll .pos-main,
body.pos-no-scroll .pos-side { min-height: 0; }
body.pos-no-scroll .pos-main { overflow: hidden; }
body.pos-no-scroll .pos-side { overflow: hidden; }

.pos-main, .pos-side {
    background: #ffffff;
    border: 1px solid #e9ecef;
    border-radius: 6px;
    display: flex; flex-direction: column;
    overflow: hidden;
    min-height: 0;
    /* CLAVE: sin min-width:0 el track 1fr de productos no puede encogerse por
       debajo del ancho mínimo de su contenido (barra de búsqueda + grid), lo que
       desborda horizontalmente y empuja la columna del carrito fuera del área
       visible (overflow:hidden la recorta). Pasaba a ~1080px de ancho. */
    min-width: 0;
}

.pos-search-bar { padding: 8px 10px 6px; border-bottom: 1px solid #e9ecef; flex-shrink: 0; }
.pos-search-bar .input-group-lg .form-control,
.pos-search-bar .input-group-lg .input-group-text,
.pos-search-bar .input-group-lg .btn { padding-top: 6px; padding-bottom: 6px; font-size: 14px; height: auto; }
.pos-categories {
    display: flex; gap: 5px; flex-wrap: nowrap; overflow-x: auto;
    padding: 6px 10px;
    border-bottom: 1px solid #e9ecef;
    flex-shrink: 0;
}
.pos-cat-pill {
    padding: 4px 12px; border-radius: 999px;
    border: 1px solid #ced4da;
    background: #ffffff;
    color: #495057;
    cursor: pointer;
    font-size: 12px; font-weight: 500;
    white-space: nowrap;
    flex-shrink: 0;
    transition: all 120ms;
}
.pos-cat-pill:hover { border-color: #3f6ad8; color: #3f6ad8; }
.pos-cat-pill.active { background: #3f6ad8; color: #fff; border-color: #3f6ad8; }

.pos-products-grid {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    padding: 10px;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: 8px;
    align-content: start;
    background: #f8f9fa;
}
.pos-tile {
    background: #ffffff;
    border: 1px solid #e9ecef;
    border-radius: 8px;
    padding: 8px;
    cursor: pointer;
    transition: all 150ms;
    text-align: center;
    display: flex; flex-direction: column;
    user-select: none;
}
.pos-tile:hover {
    transform: translateY(-2px);
    border-color: #3f6ad8;
    box-shadow: 0 6px 16px rgba(63,106,216,.15);
}
.pos-tile .tile-img {
    width: 100%; height: 64px;
    background: #f1f4f6;
    border-radius: 6px;
    display: flex; align-items: center; justify-content: center;
    margin-bottom: 6px;
    color: #adb5bd; font-size: 28px;
    overflow: hidden;
}
.pos-tile .tile-img img { width: 100%; height: 100%; object-fit: cover; }
.pos-tile .tile-name { font-size: 12.5px; font-weight: 600; color: #212529; line-height: 1.25; min-height: 2.5em; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.pos-tile .tile-sku  { font-size: 10.5px; color: #6c757d; font-family: 'JetBrains Mono', monospace; margin-top: 1px; }
.pos-tile .tile-price { font-size: 14px; font-weight: 700; color: #3f6ad8; margin-top: 2px; font-variant-numeric: tabular-nums; }

/* Stock badge (esquina superior derecha de la tile) */
.pos-tile { position: relative; }
.pos-tile .tile-stock {
    position: absolute; top: 6px; right: 6px;
    font-size: 10px; font-weight: 700;
    padding: 2px 6px; border-radius: 999px;
    background: #d1e7dd; color: #0a3622; border: 1px solid #a3cfbb;
    font-variant-numeric: tabular-nums; letter-spacing: 0;
}
.pos-tile .tile-stock.low  { background: #fff3cd; color: #664d03; border-color: #ffe69c; }
.pos-tile .tile-stock.out  { background: #f8d7da; color: #842029; border-color: #f5c2c7; }
.pos-tile .tile-stock.untracked { background: #e9ecef; color: #6c757d; border-color: #dee2e6; }
/* Servicio / producto sin control de inventario: chip azul informativo. */
.pos-tile .tile-stock.service { background: #cfe2ff; color: #084298; border-color: #9ec5fe; }
.pos-tile.is-out { opacity: .55; }
.pos-tile.is-out::after {
    content: "AGOTADO"; position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    background: rgba(220,53,69,.08);
    font-weight: 800; color: #842029; font-size: 11px; letter-spacing: .1em;
    border-radius: 8px; pointer-events: none;
}

/* Toolbar de productos: switch grid/list + ordenamiento */
.pos-products-toolbar {
    display: flex; gap: 6px; align-items: center;
    padding: 4px 10px;
    border-bottom: 1px solid #e9ecef;
    background: #fff;
    font-size: 11.5px; color: #6c757d;
    flex-shrink: 0;
}
.pos-products-toolbar .pp-spacer { flex: 1; }
.pos-view-toggle { display: inline-flex; border: 1px solid #ced4da; border-radius: 6px; overflow: hidden; }
.pos-view-toggle button {
    background: #fff; border: 0; color: #6c757d; padding: 3px 9px; cursor: pointer; font-size: 12px;
}
.pos-view-toggle button.active { background: #3f6ad8; color: #fff; }

/* Modo lista (alternativa al grid) */
.pos-products-grid.view-list { grid-template-columns: 1fr; gap: 4px; padding: 8px; }
.pos-products-grid.view-list .pos-tile {
    display: grid; grid-template-columns: 50px 1fr auto auto; gap: 12px;
    align-items: center;
    text-align: left;
    padding: 6px 12px;
    border-radius: 6px;
}
.pos-products-grid.view-list .pos-tile:hover { transform: none; }
.pos-products-grid.view-list .tile-img { width: 50px; height: 50px; margin: 0; }
.pos-products-grid.view-list .tile-name { min-height: auto; -webkit-line-clamp: 1; font-size: 14px; }
.pos-products-grid.view-list .tile-sku  { display: inline; margin: 0; }
.pos-products-grid.view-list .tile-stock { position: static; align-self: center; }
.pos-products-grid.view-list .tile-price { margin: 0; }
.pos-products-grid.view-list .pos-tile.is-out::after { display: none; }

.pos-customer-bar { padding: 8px 12px; border-bottom: 1px solid #e9ecef; background: #f8f9fa; flex-shrink: 0; }
.pos-customer-bar .form-label { margin-bottom: 4px; font-size: 12px; }
.pos-cart-list { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 6px; }
.pos-cart-row {
    display: grid; grid-template-columns: 1fr auto; gap: 6px;
    padding: 7px 10px;
    border-radius: 6px;
    border: 1px solid transparent;
    margin-bottom: 3px;
    transition: background 120ms;
}
.pos-cart-row:hover { background: #f8f9fa; border-color: #e9ecef; }
.pos-cart-row.is-active { background: #e7f1ff; border-color: #9ec5fe; box-shadow: inset 3px 0 0 #0d6efd; }
.pos-cart-row .r-name { font-weight: 600; color: #212529; font-size: 13px; line-height: 1.3; }
.pos-cart-row .r-meta { font-size: 11px; color: #6c757d; margin-top: 2px; font-family: 'JetBrains Mono', monospace; }
.pos-cart-row .r-note { font-size: 11px; color: #b45309; margin-top: 3px; font-style: italic; display: flex; align-items: center; gap: 4px; }
.pos-cart-row .r-disc-tag {
    display: inline-block; margin-left: 6px;
    background: #fff3cd; color: #664d03;
    font-size: 10px; font-weight: 700;
    padding: 1px 5px; border-radius: 4px;
}
.pos-cart-row .r-ctrl { display: flex; align-items: center; gap: 4px; }
.pos-cart-row .r-qty { width: 56px; text-align: center; padding: 4px; font-variant-numeric: tabular-nums; font-weight: 600; }
.pos-cart-row .r-total { font-weight: 700; color: #212529; min-width: 80px; text-align: right; font-variant-numeric: tabular-nums; }
.pos-cart-row .btn { padding: 4px 8px; }
.pos-cart-row .r-edit { background: transparent; border: 0; color: #6c757d; padding: 4px 6px; cursor: pointer; font-size: 14px; }
.pos-cart-row .r-edit:hover { color: #0d6efd; }

.pos-cart-empty { text-align: center; padding: 30px 20px; color: #adb5bd; }
.pos-cart-empty i { font-size: 48px; opacity: .4; display: block; margin-bottom: 8px; }

.pos-cart-totals { border-top: 1px solid #e9ecef; background: #f8f9fa; padding: 10px 12px; flex-shrink: 0; }
.pos-cart-totals .t-line { display: flex; justify-content: space-between; padding: 2px 0; font-size: 13px; color: #495057; }
.pos-cart-totals .t-line strong { font-variant-numeric: tabular-nums; color: #212529; }
.pos-cart-totals .t-line.t-grand {
    font-size: 19px; font-weight: 800;
    color: #212529;
    border-top: 1px dashed #ced4da;
    padding-top: 7px; margin-top: 4px;
}
.pos-cart-totals .t-line.t-grand strong { color: #3f6ad8; }

.pos-actions-row { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin-top: 8px; }
.pos-actions-row .btn { padding: 7px; font-weight: 600; font-size: 13px; }
.pos-actions-row .btn-charge {
    grid-column: span 2;
    padding: 12px;
    font-size: 16px;
    font-weight: 700;
    letter-spacing: .03em;
}

.pos-stat-pill {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 6px 12px;
    border-radius: 999px;
    font-size: 12px; font-weight: 600;
    background: #ffffff;
    border: 1px solid #e9ecef;
    color: #495057;
}
.pos-stat-pill i { font-size: 14px; }
.pos-stat-pill.open { background: #e6f7ef; color: #1d6b48; border-color: #b8e8d2; }

.pay-amount-display {
    text-align: center;
    font-size: 36px;
    font-weight: 800;
    padding: 16px;
    background: #f8f9fa;
    border-radius: 8px;
    border: 1px solid #e9ecef;
    font-variant-numeric: tabular-nums;
    color: #212529;
    margin-bottom: 12px;
    letter-spacing: -.02em;
}
.pay-amount-display .change-positive { color: #3ac47d; }
.pay-amount-display .change-negative { color: #d92550; }

.pos-hotkey-chip {
    display: inline-block;
    font-size: 10.5px; font-weight: 700;
    color: #6c757d;
    background: #f1f4f6;
    border: 1px solid #ced4da;
    border-bottom-width: 2px;
    border-radius: 5px;
    padding: 1px 5px;
    margin-left: 4px;
    font-family: 'JetBrains Mono', monospace;
}

/* ── Drawer lateral derecho (deslizable) ─────────────────────────────── */
.pos-drawer {
    position: fixed; top: 0; right: 0; bottom: 0; width: 420px; max-width: 96vw;
    background: #fff;
    box-shadow: -8px 0 30px rgba(0,0,0,0.16);
    border-left: 1px solid #dee2e6;
    z-index: 1060;
    display: flex; flex-direction: column;
    transform: translateX(100%);
    transition: transform .22s ease;
}
.pos-drawer.open { transform: translateX(0); }
.pos-drawer-backdrop {
    position: fixed; inset: 0; background: rgba(0,0,0,.25);
    opacity: 0; pointer-events: none;
    z-index: 1059; transition: opacity .22s;
}
.pos-drawer-backdrop.open { opacity: 1; pointer-events: auto; }
.pos-drawer-header {
    padding: 14px 18px;
    border-bottom: 1px solid #dee2e6;
    background: #f8f9fa;
    display: flex; align-items: center; justify-content: space-between;
}
.pos-drawer-header h5 { margin: 0; font-size: 16px; font-weight: 700; display: flex; align-items: center; gap: 8px; }
.pos-drawer-header h5 i { color: #0d6efd; }
.pos-drawer-close {
    background: transparent; border: 0; color: #6c757d; font-size: 24px;
    line-height: 1; cursor: pointer; padding: 0 6px;
}
.pos-drawer-close:hover { color: #212529; }
.pos-drawer-tabs {
    display: flex; gap: 0;
    border-bottom: 1px solid #dee2e6;
    background: #fff;
}
.pos-drawer-tab {
    flex: 1; background: transparent; border: 0;
    padding: 10px 8px; cursor: pointer;
    font-size: 12.5px; font-weight: 600; color: #6c757d;
    border-bottom: 3px solid transparent;
    display: flex; align-items: center; justify-content: center; gap: 6px;
    transition: all .12s;
}
.pos-drawer-tab:hover { color: #0d6efd; background: #f8f9fa; }
.pos-drawer-tab.active { color: #0d6efd; border-bottom-color: #0d6efd; }
.pos-drawer-tab .badge { background: #6c757d; color: #fff; border-radius: 999px; padding: 0 6px; font-size: 10px; }
.pos-drawer-tab.active .badge { background: #0d6efd; }
.pos-drawer-body { flex: 1; overflow-y: auto; padding: 12px; background: #f8f9fa; }
.pos-drawer-empty { text-align: center; padding: 40px 20px; color: #adb5bd; }
.pos-drawer-empty i { font-size: 56px; opacity: .4; display: block; margin-bottom: 10px; }

/* Filas dentro del drawer (suspendidas / ventas recientes) */
.pos-drawer-row {
    background: #fff;
    border: 1px solid #e9ecef;
    border-radius: 8px;
    padding: 10px 12px;
    margin-bottom: 8px;
    transition: all .12s;
}
.pos-drawer-row:hover { border-color: #0d6efd; box-shadow: 0 2px 6px rgba(13,110,253,.08); }
.pos-drawer-row .pdr-head {
    display: flex; justify-content: space-between; align-items: baseline;
    margin-bottom: 4px;
}
.pos-drawer-row .pdr-code {
    font-family: 'JetBrains Mono', monospace; font-weight: 700; font-size: 12px;
    color: #0d6efd;
}
.pos-drawer-row .pdr-total {
    font-weight: 700; font-size: 15px; color: #198754;
    font-variant-numeric: tabular-nums;
}
.pos-drawer-row .pdr-meta { font-size: 11.5px; color: #6c757d; margin-top: 2px; }
.pos-drawer-row .pdr-actions { display: flex; gap: 6px; margin-top: 8px; }
.pos-drawer-row .pdr-actions .btn { padding: 4px 12px; font-size: 12px; font-weight: 600; }

/* Ayuda — listado de atajos */
.pos-help-grid { display: grid; gap: 6px; }
.pos-help-row {
    display: grid; grid-template-columns: 80px 1fr; gap: 12px;
    background: #fff; border: 1px solid #e9ecef; border-radius: 6px;
    padding: 8px 12px;
}
.pos-help-row kbd {
    background: #212529; color: #fff;
    padding: 3px 10px; border-radius: 4px; font-size: 11.5px;
    font-family: 'JetBrains Mono', monospace; font-weight: 700;
    text-align: center; align-self: center;
    box-shadow: 0 2px 0 #000;
}
.pos-help-row .desc { font-size: 13px; color: #212529; align-self: center; }
.pos-help-section-title {
    font-size: 11px; font-weight: 700; color: #6c757d; letter-spacing: .12em;
    text-transform: uppercase; margin: 12px 0 6px;
}
.pos-help-section-title:first-child { margin-top: 0; }


/* ────────────────────────────────────────────────────────────────────────
   8) LOGIN — fondo gradient consistente con plantilla
   ──────────────────────────────────────────────────────────────────────── */
body.app-login-bg {
    background: linear-gradient(150deg, rgba(73, 80, 161, 0.95) 0%, rgba(124, 95, 240, 0.95) 100%);
    min-height: 100vh;
}
.erp-login-card {
    max-width: 440px;
    margin: 8vh auto;
    background: #ffffff;
    border-radius: 8px;
    box-shadow: 0 24px 64px rgba(15,23,42,.25);
    padding: 32px;
}


/* ────────────────────────────────────────────────────────────────────────
   9) PRINT (reportes PDF)
   ──────────────────────────────────────────────────────────────────────── */
@media print {
    .app-header, .app-sidebar, .app-footer, .page-title-actions { display: none !important; }
    .app-main__outer { padding-left: 0 !important; }
    .card { box-shadow: none !important; border: 1px solid #e5e7eb !important; }
}

/* ────────────────────────────────────────────────────────────────────────
   10) SIDEBAR SCROLL — fix para menús largos (Contabilidad, Manufactura, etc.)
   ──────────────────────────────────────────────────────────────────────── */
.app-sidebar {
    height: 100vh !important;
    overflow: hidden !important;
    display: flex !important;
    flex-direction: column !important;
}

.app-sidebar .app-header__logo {
    flex: 0 0 auto;
}

.app-sidebar .scrollbar-sidebar {
    flex: 1 1 auto !important;
    height: auto !important;
    max-height: calc(100vh - 60px) !important;
    overflow-y: auto !important;
    overflow-x: hidden !important;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
    scrollbar-color: rgba(0,0,0,0.25) transparent;
}

/* Scrollbar custom (WebKit) */
.app-sidebar .scrollbar-sidebar::-webkit-scrollbar {
    width: 6px;
}
.app-sidebar .scrollbar-sidebar::-webkit-scrollbar-track {
    background: transparent;
}
.app-sidebar .scrollbar-sidebar::-webkit-scrollbar-thumb {
    background-color: rgba(0,0,0,0.2);
    border-radius: 3px;
}
.app-sidebar .scrollbar-sidebar::-webkit-scrollbar-thumb:hover {
    background-color: rgba(0,0,0,0.4);
}

/* Scroll vertical también con el sidebar COLAPSADO (y al hacer hover sobre él).
   ArchitectUI asume PerfectScrollbar y fuerza overflow:initial / overflow:hidden
   en estos estados; como aquí NO se inicializa PerfectScrollbar, restauramos el
   scroll nativo para que en pantallas de poca altura los iconos no se recorten
   y se pueda hacer scroll hasta el último item. */
.closed-sidebar:not(.sidebar-mobile-open) .app-sidebar .scrollbar-sidebar,
.closed-sidebar:not(.sidebar-mobile-open) .app-sidebar:hover .scrollbar-sidebar {
    position: static !important;
    height: auto !important;
    max-height: calc(100vh - 60px) !important;
    overflow-y: auto !important;
    overflow-x: hidden !important;
}

/* Asegurar que el inner no fuerce altura limitada */
.app-sidebar .app-sidebar__inner {
    height: auto !important;
    min-height: 100%;
}

/* PerfectScrollbar override (ArchitectUI lo usa por default y a veces se rompe) */
.app-sidebar .ps {
    overflow: auto !important;
}
.app-sidebar .ps__rail-y {
    opacity: 0.6 !important;
}

/* Mobile: sidebar a pantalla completa cuando se abre */
@media (max-width: 991.98px) {
    .app-sidebar .scrollbar-sidebar {
        max-height: calc(100vh - 60px) !important;
    }
}

/* ─────────────────────────────────────────────────────────────────
   Logo corporativo — Nombre de la empresa (tipografía ejecutiva)
   ───────────────────────────────────────────────────────────────── */

/* Forzar visibilidad del contenedor (ArchitectUI lo oculta en algunos breakpoints) */
.app-header__logo,
.app-sidebar .app-header__logo {
    visibility: visible !important;
    opacity: 1 !important;
    background: transparent !important;
}

.app-header__logo .logo-src,
.app-sidebar .app-header__logo .logo-src,
.app-header.header-text-light .app-header__logo .logo-src,
.app-header.header-text-dark  .app-header__logo .logo-src,
.app-sidebar.sidebar-text-light .app-header__logo .logo-src,
.closed-sidebar.closed-sidebar-mobile .app-sidebar .app-header__logo .logo-src,
.closed-sidebar.closed-sidebar-mobile .app-sidebar:hover .app-header__logo .logo-src,
.sidebar-mobile-open .app-sidebar .app-header__logo .logo-src {
    background: transparent !important;
    background-image: none !important;
    width: auto !important;
    min-width: 0 !important;
    height: auto !important;
    display: inline-flex !important;
    align-items: center;
    padding: 6px 0;
    flex: 1 1 auto;
    opacity: 1 !important;
    visibility: visible !important;
    filter: none !important;
}

/* Texto principal — Manrope, peso 800, máximo contraste */
.app-header__logo .logo-src .logo-text,
.app-sidebar .app-header__logo .logo-src .logo-text {
    font-family: 'Manrope', 'Inter', -apple-system, BlinkMacSystemFont, sans-serif !important;
    font-weight: 800 !important;
    font-size: clamp(0.82rem, 1.2vw, 0.98rem) !important;
    color: #0f172a !important;
    letter-spacing: 0.015em !important;
    text-transform: uppercase !important;
    white-space: nowrap !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    line-height: 1.15 !important;
    flex: 1 1 auto;
    min-width: 0;
    opacity: 1 !important;
    visibility: visible !important;
    filter: none !important;
    text-shadow: none !important;
    -webkit-text-fill-color: #0f172a !important;
}

/* ── Colapso del sidebar (.closed-sidebar) ──────────────────────────────
   Al colapsar, ArchitectUI reduce el área de logo a 80px. Los overrides de
   arriba fuerzan el logo visible con width:auto, así que aquí lo ocultamos
   explícitamente (con mayor especificidad + !important) para que el nombre
   de la empresa NO se muestre ni desborde sobre los iconos del header. */

/* Header: el logo se oculta por completo cuando el sidebar está colapsado
   (el header no se expande por hover; solo queda el botón hamburger). */
.closed-sidebar .app-header .app-header__logo .logo-src,
.closed-sidebar .app-header .app-header__logo .logo-src .logo-text {
    display: none !important;
}

/* Sidebar (configuraciones donde su logo es visible, p.ej. móvil): ocultar el
   texto salvo cuando el sidebar se expande por hover; el logo se reduce a 80px. */
.closed-sidebar .app-sidebar:not(:hover) .app-header__logo .logo-src .logo-text {
    display: none !important;
}
.closed-sidebar .app-sidebar:not(:hover) .app-header__logo .logo-src {
    width: 21px !important;
    min-width: 0 !important;
    flex: 0 0 auto !important;
    overflow: hidden !important;
}

/* Guard anti-apilamiento de iconos: si el <ul.vertical-nav-menu> RAÍZ recibe
   por error la clase `mm-show` (p. ej. desde un script que abre los padres del
   item activo), ArchitectUI aplicaría `ul.mm-show>li>a{height:0}` a TODOS los
   items de primer nivel y sus iconos se apilarían en una sola posición. Aquí
   forzamos que los links de primer nivel conserven su altura. NO afecta a los
   submenús reales (esos son `ul.mm-show` pero no `.vertical-nav-menu`). */
.closed-sidebar .app-sidebar .app-sidebar__inner ul.vertical-nav-menu.mm-show > li > a {
    height: 2.4rem !important;
}

/* ─────────────────────────────────────────────────────────────────
   SweetAlert2 — tema corporativo
   ───────────────────────────────────────────────────────────────── */
.swal2-popup.erp-swal-popup {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
    border-radius: 14px;
    padding: 24px 22px 20px;
    box-shadow: 0 25px 60px rgba(15, 23, 42, 0.2),
                0 8px 20px rgba(15, 23, 42, 0.08);
}
.swal2-popup .erp-swal-title {
    font-family: 'Manrope', 'Inter', sans-serif;
    font-weight: 700;
    color: #0f172a;
    font-size: 1.15rem;
    letter-spacing: 0.005em;
}
.swal2-popup .swal2-html-container,
.swal2-popup .swal2-content {
    color: #495057;
    font-size: 0.92rem;
    line-height: 1.5;
}
.swal2-styled.swal2-confirm,
.swal2-styled.swal2-cancel {
    font-family: 'Inter', sans-serif;
    font-weight: 600;
    border-radius: 8px;
    padding: 9px 18px;
    font-size: 0.875rem;
    box-shadow: none !important;
    outline: none !important;
}
.swal2-styled.swal2-confirm:focus,
.swal2-styled.swal2-cancel:focus {
    box-shadow: 0 0 0 3px rgba(63, 106, 216, 0.25) !important;
}
/* Fix: base.css pinta el botón Cancelar con fondo casi blanco (#f8f9fa) y texto
   blanco → invisible sobre el popup. Forzamos colores legibles para TODOS los
   SweetAlert, incluso los que llaman Swal.fire directo sin cancelButtonColor.
   Mismo selector específico que base.css + !important para ganar siempre. */
.swal2-popup .swal2-styled.swal2-confirm {
    background-color: #3f6ad8 !important;
    color: #fff !important;
    border: 0 !important;
}
.swal2-popup .swal2-styled.swal2-cancel {
    background-color: #6c757d !important;  /* gris sólido, legible */
    color: #fff !important;
    border: 0 !important;
}
.swal2-popup .swal2-styled.swal2-confirm:hover { background-color: #355cc0 !important; }
.swal2-popup .swal2-styled.swal2-cancel:hover  { background-color: #5a6268 !important; }
.swal2-popup .swal2-styled.swal2-deny {
    background-color: #d92550 !important;
    color: #fff !important;
    border: 0 !important;
}
.swal2-icon { margin-top: 8px; }

/* Toast */
.swal2-toast.erp-swal-toast {
    box-shadow: 0 10px 30px rgba(15, 23, 42, 0.18) !important;
    border-radius: 12px !important;
}
.swal2-toast .swal2-title { font-size: 0.9rem !important; font-weight: 600 !important; }

/* Modal de Ayuda contextual */
.swal2-popup.erp-help-popup .erp-help-body {
    font-size: 0.93rem;
    line-height: 1.55;
    color: #344256;
}
.swal2-popup.erp-help-popup .erp-help-label {
    display: inline-block;
    font-family: 'Manrope', 'Inter', sans-serif;
    font-weight: 700;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: #3f6ad8;
    margin-bottom: 4px;
}
.swal2-popup.erp-help-popup .erp-help-example {
    background: rgba(63, 106, 216, 0.06);
    border-left: 3px solid #3f6ad8;
    padding: 10px 14px;
    border-radius: 6px;
    margin-top: 4px;
}
/* ─────────────────────────────────────────────────────────────────
   Loader global (overlay translúcido + panel glass)
   Velo apenas perceptible con leve blur; panel flotante con
   transición suave de entrada/salida.
   Excluir con data-no-loader o $.ajax({silent:true}).
   ───────────────────────────────────────────────────────────────── */
.erp-loader {
    position: fixed;
    inset: 0;
    background: rgba(255, 255, 255, 0.35);
    backdrop-filter: blur(3px) saturate(110%);
    -webkit-backdrop-filter: blur(3px) saturate(110%);
    z-index: 20000;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity 0.22s ease, visibility 0.22s ease, backdrop-filter 0.22s ease;
}
.erp-loader.is-active {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
}
.erp-loader__panel {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 22px 32px 18px;
    background: rgba(255, 255, 255, 0.78);
    border: 1px solid rgba(255, 255, 255, 0.6);
    border-radius: 18px;
    box-shadow:
        0 10px 30px rgba(15, 23, 42, 0.10),
        0 2px 6px rgba(15, 23, 42, 0.06),
        inset 0 1px 0 rgba(255, 255, 255, 0.6);
    backdrop-filter: blur(12px) saturate(140%);
    -webkit-backdrop-filter: blur(12px) saturate(140%);
    transform: translateY(6px) scale(0.92);
    transition: transform 0.22s cubic-bezier(0.34, 1.3, 0.55, 1);
}
.erp-loader.is-active .erp-loader__panel {
    transform: translateY(0) scale(1);
}

/* Loader: bola roja rebotando sobre línea punteada
   (scopeado bajo el panel para no chocar con .loader de ArchitectUI) */
.erp-loader__panel .loader {
    height: 60px;
    aspect-ratio: 2;
    border-bottom: 3px solid transparent;
    background:
        linear-gradient(90deg, #524656 50%, transparent 0)
        -25% 100% / 50% 3px repeat-x border-box;
    position: relative;
    animation: l3-0 .75s linear infinite;
}
.erp-loader__panel .loader::before {
    content: "";
    position: absolute;
    inset: auto 42.5% 0;
    aspect-ratio: 1;
    border-radius: 50%;
    background: #CF4647;
    animation: l3-1 .75s cubic-bezier(0, 900, 1, 900) infinite;
}
@keyframes l3-0 {
    to { background-position: -125% 100%; }
}
@keyframes l3-1 {
    0%, 2% { bottom: 0%; }
    98%, to { bottom: .1%; }
}
@media (prefers-reduced-motion: reduce) {
    .erp-loader, .erp-loader__panel { transition: opacity 0.3s ease, visibility 0.3s ease; }
    .erp-loader__panel .loader,
    .erp-loader__panel .loader::before { animation-duration: 1.6s; }
}
/* ── LOW-07: focus visible reforzado + outline accesible ───────────────── */
:focus-visible {
    outline: 2px solid var(--c-brand, #6366f1) !important;
    outline-offset: 2px;
    border-radius: 4px;
}

/* MED-16: feedback visual de errores de validación reforzado para a11y */
.is-invalid + .invalid-feedback,
[aria-invalid="true"] + .invalid-feedback {
    display: block;
}


/* ─────────────────────────────────────────────────────────────────
   KPI cards — anti-overflow global
   Aplica a TODA `.widget-content` (KPI tiles, cards de header de
   módulos, etc.) para que números grandes (moneda, +5 dígitos)
   nunca empujen al label fuera de la card.
   ───────────────────────────────────────────────────────────────── */
.widget-content .widget-content-wrapper {
    gap: 0.75rem;
    min-width: 0;
    align-items: center;
}
.widget-content .widget-content-left {
    min-width: 0;
    flex: 1 1 0;
}
.widget-content .widget-content-right {
    flex: 0 1 auto;
    text-align: right;
    min-width: 0;
    max-width: 70%;
}
.widget-content .widget-heading,
.widget-content .widget-subheading {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Base — conservador (overridea el clamp del bloque "Cards KPI auto-fit" sin pelear) */
.widget-content .widget-numbers {
    line-height: 1.1;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
}
/* Variante explícita para montos: tipografía menor para que quepa moneda (con !important
   porque el bloque "Cards KPI auto-fit" tiene una regla previa con !important).
   Aplica tanto a .widget-content (cards manuales) como a .widget-chart (helper widget_kpi). */
.widget-content .widget-numbers.kpi-money,
.widget-chart .widget-numbers.kpi-money {
    font-size: clamp(13px, 1.1vw + .3rem, 19px) !important;
    letter-spacing: -0.01em;
}
/* Cuando hay icono inline en el número, separación reducida para liberar espacio */
.widget-content .widget-numbers > i,
.widget-chart .widget-numbers > div > div > .kpi-value-flex > span > i {
    font-size: 0.85em;
    vertical-align: -0.05em;
}

/* widget_kpi() helper: que el flex interno y el valor de la card no rompan */
.widget-chart .widget-chart-content { min-width: 0; max-width: 100%; }
.widget-chart .widget-chart-flex { min-width: 0; }
.widget-chart .kpi-value-flex {
    display: flex;
    align-items: baseline;
    flex-wrap: nowrap;
    min-width: 0;
    max-width: 100%;
    gap: 0.25rem;
}
.widget-chart .kpi-value {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    flex: 1 1 auto;
}
.widget-chart .widget-title {
    /* Mostrar el título COMPLETO: si no cabe en una línea, envuelve (no se recorta). */
    overflow: visible;
    text-overflow: clip;
    white-space: normal;
    word-break: break-word;
    max-width: 100%;
    line-height: 1.2;
}

/* ─────────────────────────────────────────────────────────────────
   Cards principales: que el contenido nunca rompa el ancho del grid
   ───────────────────────────────────────────────────────────────── */
.main-card, .card {
    min-width: 0;
}
.card-header {
    flex-wrap: wrap;
    gap: 0.5rem;
}

/* ─────────────────────────────────────────────────────────────────
   Tablas: forzar `table-layout: auto` y truncate en celdas largas
   marcadas con .cell-truncate (para descripciones, direcciones, etc.).
   ───────────────────────────────────────────────────────────────── */
.table-responsive { min-width: 0; }
.table .cell-truncate {
    max-width: 240px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ─────────────────────────────────────────────────────────────────
   Badges: que el contenido de un badge largo no rompa el flujo.
   Permite multi-línea con wrap suave cuando el contenido es muy largo.
   ───────────────────────────────────────────────────────────────── */
.badge {
    white-space: normal;
    word-break: break-word;
}

/* ─────────────────────────────────────────────────────────────────
   PULIDO FINO — micro-interacciones globales (2026-06-06)
   Subtle, tema claro, sin gradientes. Transiciones suaves + hover en
   KPI cards/filas/botones, fade-in del contenido y estados vacíos
   consistentes. No altera layout, colores base ni tipografía.
   ───────────────────────────────────────────────────────────────── */

/* Transiciones suaves en elementos interactivos */
.card, .btn, .badge, .nav-link, .widget-chart,
.table tbody tr, .form-control, .form-select, .pi-kpi {
    transition: box-shadow .18s ease, transform .18s ease,
                background-color .15s ease, border-color .15s ease, color .15s ease;
}

/* KPI / widget cards: leve elevación al pasar el cursor */
.widget-chart:hover,
.card.widget-content:hover {
    transform: translateY(-3px);
    box-shadow: 0 .5rem 1.4rem rgba(33, 40, 55, .12) !important;
}

/* main-card: profundiza la sombra sin saltar (contienen tablas/formularios) */
.main-card:hover { box-shadow: 0 .4rem 1.1rem rgba(33, 40, 55, .10); }

/* Filas de listados: acento izquierdo sutil al pasar el cursor */
.table-hover tbody tr:hover { box-shadow: inset 3px 0 0 rgba(63, 106, 216, .5); }

/* Botones: micro-presión al click + sombra suave en btn-shadow */
.btn:active { transform: translateY(1px); }
.btn-shadow:hover { box-shadow: 0 .35rem .8rem rgba(33, 40, 55, .14); }

/* Chips KPI propios (pi-kpi): leve realce */
.pi-kpi:hover { box-shadow: 0 .25rem .6rem rgba(33, 40, 55, .10); }

/* Aparición suave del contenido al cargar (un solo fade, sin saltos) */
@keyframes erpFadeIn { from { opacity: 0; } to { opacity: 1; } }
.app-main__inner { animation: erpFadeIn .22s ease both; }

/* Estado vacío reutilizable + realce de celdas "Sin registros" existentes */
.empty-state { text-align: center; color: #9aa1a9; padding: 2.5rem 1rem; }
.empty-state .es-icon { font-size: 3rem; opacity: .35; display: block; margin-bottom: .5rem; }
td.text-soft.text-center, td.text-center.text-soft { color: #9aa1a9; font-style: italic; }

/* Respeto a usuarios con movimiento reducido */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after { animation: none !important; transition: none !important; }
}
