/* ==========================================================================
   TOKENS DE MARCA — paleta DER (docs/paleta_colores_der.png)
   Cuatro colores, un solo sistema, dos temas:

     Rojo arcilla  #A94A35 -> ACCION y marca (boton primario, enlaces, activo)
     Verde montana #303E3B -> ESTRUCTURA (sidebar, topbar, tinta, fondo oscuro)
     Ocre maiz     #D5B15A -> ACENTO (filo activo, realces, atencion)
     Crema lana    #E7D8B5 -> SUPERFICIE calida (fondo claro, texto en oscuro)

   Regla: ningun componente escribe un color literal. Todo sale de estos
   tokens, y el tema oscuro es el MISMO CSS con los tokens cambiados
   (`<html data-theme="dark">`, ver `initTheme()` en erp-shell.js).
   Los `*-rgb` existen para poder teñir con alfa: rgba(var(--x-rgb), .12).
   Ver docs/style.md §1.
   ========================================================================== */
:root{
    color-scheme: light;

    /* -- Paleta cruda (no usar directo en componentes: usar los roles) -- */
    --der-arcilla: #A94A35;
    --der-ocre: #D5B15A;
    --der-crema: #E7D8B5;
    --der-montana: #303E3B;

    /* -- Marca / accion -- */
    --erp-primary: #A94A35;
    --erp-primary-strong: #8B3A29;
    --erp-primary-soft: #C4664D;
    --erp-primary-rgb: 169, 74, 53;
    --erp-primary-contrast: #FFF7F0;   /* texto/icono sobre el primario */
    --erp-primary-text: #8B3A29;       /* arcilla legible como texto/sobre tinte */
    --erp-accent: #A07A2A;             /* ocre legible como texto sobre claro */
    --erp-accent-bright: #D5B15A;      /* ocre pleno (sobre fondo oscuro) */
    --erp-accent-rgb: 213, 177, 90;
    --erp-secondary: #7E8A85;
    --erp-gradient: linear-gradient(135deg, #8B3A29 0%, #A94A35 55%, #C87A3C 100%);

    /* -- Superficies y tinta -- */
    --erp-surface: #ffffff;
    --erp-surface-subtle: #F7F2E7;     /* fondo de pagina / relleno tenue */
    --erp-surface-muted: #EFE8D9;      /* hover, celdas, pastillas neutras */
    --erp-surface-strong: #26312E;
    --erp-surface-veil: rgba(255, 255, 255, 0.5);
    --erp-text-strong: #26312E;
    --erp-text-muted: #5E6B66;
    --erp-border: #E4DCCB;
    --erp-border-strong: #CFC3A9;
    --erp-ink-rgb: 48, 62, 59;         /* sombras y velos */
    --erp-thumb: rgba(48, 62, 59, 0.22);
    --erp-thumb-hover: rgba(48, 62, 59, 0.38);
    /* Lavado calido del lienzo (dos manchas suaves detras de todo). */
    --erp-canvas-tint-1: rgba(169, 74, 53, 0.07);
    --erp-canvas-tint-2: rgba(213, 177, 90, 0.10);

    /* -- Cromo oscuro (sidebar, topbar, nav movil): verde montana en ambos
          temas, para que la marca no cambie de sitio al conmutar. -- */
    --erp-chrome: linear-gradient(180deg, #26312E 0%, #303E3B 60%, #394A44 100%);
    --erp-chrome-solid: #26312E;
    --erp-chrome-text: #F3ECDC;
    --erp-chrome-rgb: 231, 216, 181;   /* crema: tintes sobre el cromo */
    --erp-chrome-active: #D5B15A;      /* filo del item activo (ocre) */
    --erp-topbar: linear-gradient(135deg, rgba(169, 74, 53, 0.96) 0%, rgba(48, 62, 59, 0.94) 70%);

    /* -- Estados semanticos (independientes de la marca) -- */
    --erp-ok: #2E7D52;
    --erp-ok-rgb: 46, 125, 82;
    --erp-ok-soft: #E7F1EA;
    --erp-ok-border: #BDD8C7;
    --erp-ok-text: #1E5A3A;
    --erp-ok-dot: #3E9C68;
    --erp-warn: #B07C1A;
    --erp-warn-soft: #FAF0DA;
    --erp-warn-border: #E9D49C;
    --erp-warn-text: #845A10;
    --erp-warn-dot: #D5B15A;
    --erp-danger: #BC2E27;
    --erp-danger-soft: #FAE8E6;
    --erp-danger-border: #EFC2BD;
    --erp-danger-text: #8F221C;
    --erp-danger-dot: #D9544A;
    --erp-info: #2F6F80;
    --erp-info-soft: #E5EFF2;
    --erp-info-border: #B9D3DA;
    --erp-info-text: #1F5563;
    --erp-info-dot: #4A93A6;

    /* -- Series de grafico. Son ROLES, no estados: un grafico de dos series no
          habla de "bien" y "mal", habla de dos cosas distintas, asi que no puede
          tomar prestados los colores semanticos. La segunda no sale de la marca
          porque arcilla y ocre son los dos calidos: contra la arcilla, el ocre
          da 12,4 de separacion normal y hace falta 15 (validado con
          `scripts/validate_palette.js` de la skill dataviz). El teal pasa los
          seis controles en claro y en oscuro. -- */
    --erp-chart-1: #A94A35;
    --erp-chart-1-rgb: 169, 74, 53;
    --erp-chart-2: #0A93A8;
    --erp-chart-2-rgb: 10, 147, 168;

    /* -- Forma -- */
    --erp-radius-lg: 16px;
    --erp-radius-md: 12px;
    --erp-radius-sm: 8px;
    --erp-shadow-soft: 0 16px 40px rgba(var(--erp-ink-rgb), 0.16);
    --erp-shadow-card: 0 10px 30px rgba(var(--erp-ink-rgb), 0.09);
}

/* --------------------------------------------------------------------------
   TEMA OSCURO. `data-theme` lo fija el script de pre-pintado del <head>
   (base.html) con lo elegido en el menu de usuario; "auto" lo resuelve el JS
   contra el sistema operativo, asi que aca solo existe claro/oscuro.
   El verde montana pasa de ser el cromo a ser el lienzo y la crema pasa a ser
   la tinta; la arcilla se aclara apenas para no apagarse sobre el verde.
   -------------------------------------------------------------------------- */
[data-theme="dark"]{
    color-scheme: dark;

    --erp-primary: #B5533B;
    --erp-primary-strong: #9C4530;
    --erp-primary-soft: #D08265;
    --erp-primary-rgb: 181, 83, 59;
    --erp-primary-contrast: #FFF7F0;
    --erp-primary-text: #E0A18C;
    --erp-accent: #D5B15A;
    --erp-accent-bright: #E3C67D;
    --erp-secondary: #8D9994;
    --erp-gradient: linear-gradient(135deg, #9C4530 0%, #B5533B 55%, #C47A45 100%);

    --erp-surface: #2A3532;
    --erp-surface-subtle: #19221F;
    --erp-surface-muted: #35423E;
    --erp-surface-strong: #16201E;
    --erp-surface-veil: rgba(42, 53, 50, 0.55);
    --erp-text-strong: #ECE3D0;
    --erp-text-muted: #A8B2AC;
    --erp-border: #3C4945;
    --erp-border-strong: #506059;
    --erp-ink-rgb: 6, 10, 9;
    --erp-thumb: rgba(236, 227, 208, 0.22);
    --erp-thumb-hover: rgba(236, 227, 208, 0.38);
    --erp-canvas-tint-1: rgba(181, 83, 59, 0.05);
    --erp-canvas-tint-2: rgba(213, 177, 90, 0.03);

    --erp-chrome: linear-gradient(180deg, #1B2422 0%, #222C29 60%, #26312E 100%);
    --erp-chrome-solid: #1B2422;
    --erp-topbar: linear-gradient(135deg, rgba(155, 68, 48, 0.92) 0%, rgba(22, 32, 30, 0.96) 70%);

    --erp-ok: #56B385;
    --erp-ok-rgb: 86, 179, 133;
    --erp-ok-soft: rgba(86, 179, 133, 0.16);
    --erp-ok-border: rgba(86, 179, 133, 0.38);
    --erp-ok-text: #8FD3AE;
    --erp-ok-dot: #56B385;
    --erp-warn: #D5B15A;
    --erp-warn-soft: rgba(213, 177, 90, 0.16);
    --erp-warn-border: rgba(213, 177, 90, 0.38);
    --erp-warn-text: #E3C87F;
    --erp-warn-dot: #D5B15A;
    --erp-danger: #E2705F;
    --erp-danger-soft: rgba(226, 112, 95, 0.16);
    --erp-danger-border: rgba(226, 112, 95, 0.38);
    --erp-danger-text: #F0A093;
    --erp-danger-dot: #E2705F;
    --erp-info: #63A9BC;
    --erp-info-soft: rgba(99, 169, 188, 0.16);
    --erp-info-border: rgba(99, 169, 188, 0.38);
    --erp-info-text: #8FC8D6;
    --erp-info-dot: #63A9BC;

    /* Pasos propios del tema oscuro: sobre el verde montania la arcilla plena
       queda en 2,58:1 de contraste y el teal claro se sale de la banda de
       luminosidad. Ambos revalidados contra la superficie oscura. */
    --erp-chart-1: #C4664D;
    --erp-chart-1-rgb: 196, 102, 77;
    --erp-chart-2: #0F9DB2;
    --erp-chart-2-rgb: 15, 157, 178;

    --erp-shadow-soft: 0 16px 40px rgba(var(--erp-ink-rgb), 0.55);
    --erp-shadow-card: 0 10px 30px rgba(var(--erp-ink-rgb), 0.38);
}

@font-face{
    font-family: 'Bariol';
    src: url("../fonts/Bariol-Regular.woff2") format('woff2'),
         url("../fonts/Bariol-Regular.woff") format('woff');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

html, body{
    font-family: 'Bariol', 'Nunito', sans-serif;
    background: var(--erp-surface-subtle);
    color: var(--erp-text-strong);
}

a{
    color: var(--erp-primary-text);
}

a:hover, a:focus{
    color: var(--erp-primary-soft);
    text-decoration: none;
}

.app-shell{
    min-height: 100vh;
    background: radial-gradient(120% 120% at 15% 20%, var(--erp-canvas-tint-1), transparent 45%), radial-gradient(160% 140% at 80% 0%, var(--erp-canvas-tint-2), transparent 55%), var(--erp-surface-subtle);
}

.app-shell .container-fluid{
    padding-left: 1.25rem;
    padding-right: 1.25rem;
}

/* El shell ya aporta un .container-fluid; las bases del framework anidan otro.
   Neutralizamos el gutter del interior para no duplicar el margen lateral. */
.app-shell .container-fluid .container-fluid{
    padding-left: 0;
    padding-right: 0;
}

.bg-gradient-primary{
    background-image: var(--erp-gradient) !important;
    background-color: var(--erp-primary) !important;
}

.btn-primary,
.app-primary-btn{
    background-image: var(--erp-gradient);
    background-color: var(--erp-primary);
    border-color: var(--erp-primary);
    color: var(--erp-primary-contrast);
    box-shadow: 0 10px 24px rgba(var(--erp-primary-rgb), 0.30);
}

.btn-primary:hover,
.btn-primary:focus,
.app-primary-btn:hover,
.app-primary-btn:focus{
    background-image: linear-gradient(135deg, var(--erp-primary-strong) 0%, var(--erp-primary) 100%);
    border-color: var(--erp-primary-strong);
    color: var(--erp-primary-contrast);
}

.app-primary-bg{
    background: var(--erp-gradient);
    color: var(--erp-primary-contrast);
    border-color: var(--erp-primary);
}

.app-primary-text{
    color: var(--erp-primary-text);
}

.border-left-primary{
    border-left: .25rem solid var(--erp-primary);
}

.bg-primary,
.badge-primary{
    background: var(--erp-gradient) !important;
    color: var(--erp-primary-contrast) !important;
}

.text-primary{
    color: var(--erp-primary-text) !important;
}

.btn-light,
.btn-outline-secondary{
    border-color: var(--erp-border-strong);
}

.sidebar{
    background: var(--erp-chrome);
    box-shadow: 4px 0 24px rgba(var(--erp-ink-rgb), 0.35);
}

.sidebar .sidebar-brand{
    padding: 1.5rem 1rem 1rem;
}

.sidebar .sidebar-brand-icon img{
    max-height: 42px;
    /* El logo lo carga el cliente: se acota tambien a lo ancho para que uno
       apaisado no empuje el nombre fuera de la barra. */
    max-width: 110px;
    object-fit: contain;
}

/* El degradado de marca es el fondo de TODA la pantalla en las paginas sueltas
   (login, cuenta suspendida): sin esto el body mide lo que mide la tarjeta y
   debajo asoma el lienzo de la aplicacion. */
body.bg-gradient-primary{ min-height: 100vh; }

/* --- Logo del producto (Camderon) ----------------------------------------
   Un archivo por tema: el claro es tinta oscura, el oscuro trae halo. El cromo
   (sidebar) es verde montana en AMBOS temas, asi que ahi va siempre el oscuro;
   sobre superficies (login) manda el tema. */
.brand-logo--dark{ display: none; }
[data-theme="dark"] .brand-logo--light{ display: none; }
[data-theme="dark"] .brand-logo--dark{ display: inline-block; }

.sidebar .sidebar-heading{
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-size: 0.7rem;
    color: rgba(var(--erp-chrome-rgb), 0.58);
}

.sidebar .nav-item .nav-link{
    display: flex;
    align-items: center;
    gap: 0.6rem;
    border-left: 3px solid transparent;
    padding-top: 0.75rem;
    padding-bottom: 0.75rem;
    color: rgba(var(--erp-chrome-rgb), 0.84);
    transition: background 150ms ease, color 150ms ease, border-color 150ms ease;
}

.sidebar .nav-item.active .nav-link,
.sidebar .nav-item .nav-link:hover{
    color: var(--erp-chrome-text);
    background: rgba(var(--erp-chrome-rgb), 0.07);
    border-left-color: var(--erp-chrome-active);
}

.sidebar .collapse-inner .collapse-item{
    border-radius: var(--erp-radius-sm);
}

.app-topbar{
    background: var(--erp-topbar);
    border-bottom: 1px solid rgba(var(--erp-chrome-rgb), 0.10);
    backdrop-filter: blur(8px);
    position: sticky;
    top: 0;
    z-index: 1030;
    min-height: 72px;
}

.app-topbar.is-scrolled{
    box-shadow: 0 10px 24px rgba(var(--erp-ink-rgb), 0.28);
}

.app-topbar .navbar-nav .nav-link,
.app-topbar .navbar-text{
    color: var(--erp-chrome-text) !important;
}

.app-topbar .topbar-title{
    display: flex;
    flex-direction: column;
    margin-left: 0.75rem;
}

.app-topbar .page-eyebrow{
    font-size: 0.75rem;
    letter-spacing: 0.04em;
    color: rgba(var(--erp-chrome-rgb), 0.72);
    text-transform: uppercase;
}

.app-topbar .page-title{
    font-size: 1.15rem;
    font-weight: 700;
    color: var(--erp-chrome-text);
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

.app-topbar .order-pill{
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.35rem 0.7rem;
    border-radius: 999px;
    background: rgba(var(--erp-chrome-rgb), 0.12);
    color: var(--erp-chrome-text);
    font-size: 0.9rem;
    border: 1px solid rgba(var(--erp-chrome-rgb), 0.20);
}

.app-topbar .order-pill .status-dot{
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--erp-ok-dot);
    box-shadow: 0 0 0 6px rgba(var(--erp-ok-rgb), 0.20);
}

.app-topbar .mobile-menu button{
    border-radius: 12px;
    font-weight: 700;
    padding: 0.45rem 0.9rem;
}

.app-toolbar{
    background: var(--erp-surface);
    border-bottom: 1px solid var(--erp-border);
    padding: 0.75rem 1.25rem;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    position: sticky;
    top: 72px;
    z-index: 1029;
}

.app-chip{
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.45rem 0.75rem;
    border-radius: 999px;
    border: 1px solid var(--erp-border);
    background: var(--erp-surface);
    color: var(--erp-text-strong);
    font-weight: 600;
}

.app-chip .dot{
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--erp-secondary);
}

.card{
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius-lg);
    box-shadow: var(--erp-shadow-card);
}

.card-header{
    background: linear-gradient(135deg, rgba(var(--erp-primary-rgb), 0.07), rgba(var(--erp-accent-rgb), 0.06));
    border-bottom: 1px solid var(--erp-border);
    color: var(--erp-text-strong);
    font-weight: 700;
}

.card-body{
    padding: 1.25rem;
}

.table thead th{
    border-bottom: 1px solid var(--erp-border-strong);
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.table td{
    vertical-align: middle;
}

.badge-state{
    border-radius: 999px;
    padding: 0.35rem 0.65rem;
    font-weight: 700;
    font-size: 0.8rem;
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}

.badge-state .dot{
    width: 8px;
    height: 8px;
    border-radius: 50%;
}

.badge-state.pending{
    background: var(--erp-warn-soft);
    color: var(--erp-warn-text);
}

.badge-state.pending .dot{
    background: var(--erp-warn-dot);
}

.badge-state.approved{
    background: var(--erp-ok-soft);
    color: var(--erp-ok-text);
}

.badge-state.approved .dot{
    background: var(--erp-ok-dot);
}

.badge-state.flag{
    background: var(--erp-danger-soft);
    color: var(--erp-danger-text);
}

.badge-state.flag .dot{
    background: var(--erp-danger-dot);
}

.mobile-bottom-nav{
    position: fixed;
    inset-inline: 0;
    bottom: 0;
    z-index: 1040;
    background: var(--erp-chrome-solid);
    border-top: 1px solid rgba(var(--erp-chrome-rgb), 0.12);
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    padding: 0.35rem 0.5rem env(safe-area-inset-bottom);
}

.mobile-bottom-nav .mobile-nav-item{
    color: rgba(var(--erp-chrome-rgb), 0.72);
    text-align: center;
    padding: 0.45rem 0.25rem 0.25rem;
    border-radius: 12px;
    font-size: 0.8rem;
    display: grid;
    gap: 0.2rem;
    justify-items: center;
}

.mobile-bottom-nav .mobile-nav-item .icon{
    font-size: 1.05rem;
}

.mobile-bottom-nav .mobile-nav-item.is-active{
    color: var(--erp-chrome-text);
    background: rgba(var(--erp-chrome-rgb), 0.10);
    box-shadow: inset 0 0 0 1px rgba(var(--erp-chrome-rgb), 0.16);
}

.page-spinner-backdrop{
    position: fixed;
    inset: 0;
    background: rgba(var(--erp-ink-rgb), 0.55);
    backdrop-filter: blur(3px);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1085;
}

.page-spinner-card{
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.75rem;
    padding: 1.5rem;
    border-radius: 1rem;
    background: linear-gradient(145deg, var(--erp-surface-strong), var(--erp-chrome-solid));
    color: var(--erp-chrome-text);
    box-shadow: 0 16px 40px rgba(var(--erp-ink-rgb), 0.45);
    min-width: 220px;
}

.page-spinner-card .label{
    font-weight: 700;
    letter-spacing: 0.01em;
}

.page-spinner-card .sub{
    font-size: 0.9rem;
    color: rgba(var(--erp-chrome-rgb), 0.75);
    text-align: center;
}

.bd-example-modal-lg .modal-dialog{
    display: table;
    position: relative;
    margin: 0 auto;
    top: calc(50% - 24px);
}

.bd-example-modal-lg .modal-dialog .modal-content{
    background-color: transparent;
    border: none;
}

.scroll-to-top{
    background: var(--erp-primary);
    border: none;
}

.dropdown-menu{
    border-radius: var(--erp-radius-md);
    border-color: var(--erp-border);
    box-shadow: var(--erp-shadow-soft);
}

@media (min-width: 992px){
    .app-shell .container-fluid{
        padding-left: 2rem;
        padding-right: 2rem;
    }
}

@media (max-width: 767.98px){
    .app-shell{
        /* Espacio para el nav inferior (~4.5rem) + el bar de guardado flotante. */
        padding-bottom: 8rem;
    }

    .app-topbar{
        padding-inline: 1rem;
    }

    /* Recuperar ancho util: margen lateral minimo y tarjetas compactas. */
    .app-shell .container-fluid{
        padding-left: 0.5rem;
        padding-right: 0.5rem;
    }

    .card-body{
        padding: 0.7rem;
    }

    /* Gutters de Bootstrap mas ajustados: menos indent en campos y tarjetas. */
    .app-shell .row{
        margin-left: -0.35rem;
        margin-right: -0.35rem;
    }
    .app-shell [class^="col-"],
    .app-shell [class*=" col-"]{
        padding-left: 0.35rem;
        padding-right: 0.35rem;
    }

    .sidebar{
        box-shadow: none;
    }
}

/* =========================================================================
   FRAMEWORK DE REGISTROS — componentes canonicos (unica fuente de verdad).
   Todo registro (maestro/transaccion) y reporte consume estas clases via las
   plantillas base de `templates/framework/`. No definir CSS de color inline en
   las pantallas: los componentes consumen tokens --erp-*.
   Ver docs/style.md.
   ========================================================================= */

/* -- Cabecera estandar de pagina de registro -- */
.record-header{
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin-bottom: 1rem;
}
.record-header .record-eyebrow{
    font-size: 0.75rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--erp-text-muted);
}
.record-header .record-title{
    margin: 0;
    font-weight: 700;
    color: var(--erp-text-strong);
}
.record-header .record-subtitle{
    color: var(--erp-text-muted);
    font-size: 0.9rem;
}
.panel-toolbar{
    display: flex;
    gap: 0.75rem;
    flex-wrap: wrap;
}
.section-caption{
    font-size: 0.95rem;
    color: var(--erp-text-muted);
}

/* -- Tarjeta de contenido -- */
.report-card{
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius-md);
    box-shadow: var(--erp-shadow-card);
    background: var(--erp-surface);
}

/* -- Accion primaria unica (Nuevo / Guardar) -- */
.btn-create{
    background-image: var(--erp-gradient);
    background-color: var(--erp-primary);
    border: none;
    color: var(--erp-primary-contrast);
    box-shadow: 0 8px 20px rgba(var(--erp-primary-rgb), 0.28);
}
.btn-create:hover,
.btn-create:focus{
    background-image: linear-gradient(135deg, var(--erp-primary-strong) 0%, var(--erp-primary) 100%);
    color: var(--erp-primary-contrast);
}
.btn-ruc{
    padding: 0.2rem 0.5rem;
    font-size: 0.75rem;
    line-height: 1.2;
}

/* -- Chip de estado (semantico, independiente de la marca) -- */
.status-chip{
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.2rem 0.55rem;
    border-radius: 999px;
    font-weight: 600;
    font-size: 0.8rem;
    border: 1px solid transparent;
}
.status-chip .dot{
    width: 0.55rem;
    height: 0.55rem;
    border-radius: 50%;
}
.status-chip.success{ background: var(--erp-ok-soft); border-color: var(--erp-ok-border); color: var(--erp-ok-text); }
.status-chip.success .dot{ background: var(--erp-ok-dot); }
.status-chip.warn{ background: var(--erp-warn-soft); border-color: var(--erp-warn-border); color: var(--erp-warn-text); }
.status-chip.warn .dot{ background: var(--erp-warn-dot); }
.status-chip.danger{ background: var(--erp-danger-soft); border-color: var(--erp-danger-border); color: var(--erp-danger-text); }
.status-chip.danger .dot{ background: var(--erp-danger-dot); }
.status-chip.draft{ background: var(--erp-surface-muted); border-color: var(--erp-border); color: var(--erp-text-muted); }
.status-chip.draft .dot{ background: var(--erp-secondary); }

/* -- Acciones de fila (grupo de botones en columna "Acciones") -- */
.table-actions{
    display: flex;
    align-items: center;
    gap: 6px;
}

/* -- Accion secundaria de consulta ERP (verde) -- */
.btn-erp{
    background: var(--erp-ok-soft);
    border-color: var(--erp-ok-border);
    color: var(--erp-ok-text);
}
.btn-erp:hover,
.btn-erp:focus{
    background: var(--erp-ok-soft);
    color: var(--erp-ok);
}

/* -- Accion utilitaria de copiado (celeste) -- */
.btn-copy-list{
    background: var(--erp-info-soft);
    border-color: var(--erp-info-border);
    color: var(--erp-info-text);
}
.btn-copy-list:hover,
.btn-copy-list:focus{
    background: var(--erp-info-soft);
    color: var(--erp-info);
}

/* -- Badge suave (estado completo/pendiente en listados) -- */
.badge-soft{
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.2rem 0.5rem;
    border-radius: 999px;
    font-size: 0.75rem;
    background: var(--erp-surface-muted);
    color: var(--erp-text-strong);
}
.badge-soft.badge-missing{
    background: var(--erp-danger-soft);
    color: var(--erp-danger-text);
}

/* -- Guardado flotante (form de maestro) -- */
.form-footer{
    position: fixed;
    right: 1.5rem;
    bottom: 1.5rem;
    z-index: 1050;
    background: var(--erp-surface);
    border: 1px solid var(--erp-border);
    padding: 0.6rem 0.9rem;
    border-radius: 999px;
    box-shadow: var(--erp-shadow-soft);
}

/* Guardar con acciones extra: boton partido (Guardar + caret) dentro del pill.
   El menu se abre HACIA ARRIBA (`dropup`) porque el pie flota abajo a la derecha.
   Solo aparece el caret si el formulario declara acciones (ver form_actions). */
.form-footer .btn-group{ display: inline-flex; }
.form-footer .dropdown-toggle-split{
    padding-left: 0.6rem;
    padding-right: 0.6rem;
    border-left: 1px solid rgba(var(--erp-chrome-rgb), 0.35);
}
.form-footer .dropdown-menu{
    min-width: 17rem;
    border-color: var(--erp-border);
    box-shadow: var(--erp-shadow-soft);
    padding: 0.35rem;
}
.form-footer .dropdown-item{
    border-radius: 0.5rem;
    padding: 0.5rem 0.6rem;
    white-space: normal;
}
.form-footer .dropdown-item small{
    display: block;
    color: var(--erp-text-muted);
    line-height: 1.25;
}
.form-footer .dropdown-item:active small{ color: inherit; }

/* -- Form de documento (transaccion): layout 2 columnas + matriz -- */
.doc-panel-left{ border-right: 1px solid var(--erp-border); }
.doc-lines-wrapper{ max-height: 55vh; overflow-y: auto; }
/* Pestañas con más contraste (segmentadas): inactiva = texto oscuro legible,
   activa = rellena con el color de marca. */
.tab-card .nav-tabs{ border-bottom: 2px solid var(--erp-border-strong); gap: 0.25rem; }
.tab-card .nav-tabs .nav-link{
    border: none;
    color: var(--erp-text-strong);
    font-weight: 600;
    opacity: 0.72;
    padding: 0.4rem 0.9rem;
    border-radius: 8px 8px 0 0;
    transition: background-color .12s ease, color .12s ease, opacity .12s ease;
}
.tab-card .nav-tabs .nav-link:hover{ opacity: 1; color: var(--erp-primary-text); background: rgba(var(--erp-primary-rgb), 0.10); }
.tab-card .nav-tabs .nav-link.active{
    border-bottom: 2px solid var(--erp-primary);
    color: var(--erp-primary-contrast);
    opacity: 1;
    font-weight: 700;
    background: var(--erp-primary);
}

/* Cubicacion: texto de apoyo con más contraste. */
.cubicacion-grid .form-label{ color: var(--erp-text-strong); font-weight: 600; }
.cubicacion-meta, .cubicacion-hint{ color: var(--erp-text-muted); }

/* Campos Precio y Merma más vistosos (pestañas Cubicacion y Cotizacion). */
#tab-carga .input-group,
#tab-quote .input-group{ box-shadow: 0 1px 2px rgba(var(--erp-ink-rgb), 0.08); border-radius: 0.5rem; }
#tab-carga .input-group .input-group-text,
#tab-quote .input-group .input-group-text{
    background: var(--erp-primary);
    color: var(--erp-primary-contrast);
    border-color: var(--erp-primary);
    font-weight: 700;
    min-width: 2.1rem;
    justify-content: center;
}
#tab-carga .input-group .form-control,
#tab-quote .input-group .form-control{ font-weight: 600; color: var(--erp-text-strong); }
#tab-carga .input-group:focus-within,
#tab-quote .input-group:focus-within{ box-shadow: 0 0 0 0.18rem rgba(var(--erp-primary-rgb), 0.22); }
.summary-bar{
    background: var(--erp-surface-subtle);
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius-sm);
}
.quick-card{ background: var(--erp-surface-subtle); border: 1px dashed var(--erp-border); }
.doc-save-footer{
    position: fixed;
    right: 1.5rem;
    bottom: 1.5rem;
    z-index: 1050;
    background: var(--erp-surface);
    border: 1px solid var(--erp-border);
    padding: 0.6rem 0.9rem;
    border-radius: 999px;
    box-shadow: var(--erp-shadow-soft);
}
.doc-save-btn{
    background-image: var(--erp-gradient);
    background-color: var(--erp-primary);
    border: none;
    color: var(--erp-primary-contrast);
    box-shadow: 0 8px 20px rgba(var(--erp-primary-rgb), 0.28);
}
.doc-save-btn:hover,
.doc-save-btn:focus{
    background-image: linear-gradient(135deg, var(--erp-primary-strong) 0%, var(--erp-primary) 100%);
    color: var(--erp-primary-contrast);
}

/* =========================================================================
   DOCUMENTO EN SOLO LECTURA — "ficha compacta"
   Estandar unico de TODA transaccion aprobada/anulada (Orden de Venta,
   Recepcion, Entrega, Factura...). No hay plantilla aparte: el mismo DOM del
   editor se relee como una ficha. Tres reglas de diseno:

     1. DATO, NO CONTROL. El campo deshabilitado pierde el cromo de formulario
        (borde, fondo, alto de input, flecha del select) y queda como
        etiqueta en versalita + valor en negrita sobre una hairline. Se lee
        como una ficha impresa, no como un formulario apagado.
     2. COMPLETO. Nada colapsado ni con scroll interno: el documento entero se
        lee de corrido (los bloques colapsables los abre `initDocReadonly()`,
        que ademas retira su disparador y las columnas sin dato).
     3. COMPACTO. Rejilla auto-ajustable (2-3 columnas segun el ancho) y
        alturas reducidas, para que la cabecera del documento entre de un
        vistazo al lado de la matriz de lineas.

   Todo vive aca, en el framework: una pantalla nueva no escribe CSS de
   solo-lectura, solo marca su UI de edicion con `.doc-edit-only`.
   Ver docs/style.md §8.1.
   ========================================================================= */

/* Oculta la UI de edicion (buscadores, cargas, botones de fila). */
.doc-readonly .doc-edit-only{ display: none !important; }

/* -- 1. Dato, no control -------------------------------------------------- */
.doc-readonly .form-control:disabled,
.doc-readonly .form-control[readonly],
.doc-readonly select.form-control:disabled,
.doc-readonly textarea.form-control:disabled{
    background: transparent;
    border: 0;
    border-bottom: 1px solid var(--erp-border);
    border-radius: 0;
    box-shadow: none;
    padding: 0 0 0.1rem;
    height: auto;
    min-height: 1.35rem;
    font-size: 0.9rem;
    line-height: 1.35;
    font-weight: 700;
    color: var(--erp-text-strong);
    -webkit-text-fill-color: var(--erp-text-strong);
    opacity: 1;
    cursor: default;
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
}
/* Vacio = raya, nunca un hueco mudo (el "—" lo pone initDocReadonly()). */
.doc-readonly .form-control:disabled::placeholder,
.doc-readonly .form-control[readonly]::placeholder{
    color: var(--erp-secondary);
    font-weight: 600;
    opacity: 1;
}
/* Sin cronometro/calendario nativo ni resize: son affordances de edicion. */
.doc-readonly .form-control:disabled::-webkit-calendar-picker-indicator{ display: none; }
.doc-readonly textarea.form-control:disabled{
    resize: none;
    overflow: hidden;
    field-sizing: content;  /* crece con el texto donde el navegador lo soporte */
}
.doc-readonly .form-label{
    display: block;
    margin-bottom: 0.02rem;
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--erp-text-muted);
}
/* La ayuda de captura ("lo usa la Entrega", "busca en el maestro y
   selecciona"...) no aporta al leer: el dato ya esta puesto. Solo en el panel
   de datos; los `small` de la matriz son contenido (nombre del item). */
.doc-readonly .tab-pane small.text-muted{ display: none; }

/* Tira de resumen de la cabecera (los chips del panel: "Cliente: …",
   "N° oficial: …"). Llenando el formulario son pastillas flotantes y esta bien:
   son un recordatorio movil. Leyendo, la pastilla redondeada no alinea con
   ningun otro elemento y compite con los campos. Se relee como una tira: sin
   borde ni fondo, pegada al mismo margen que la ficha, separada por filetes y
   cerrada por la misma hairline que los valores. */
.doc-readonly .tab-pane .d-flex:has(> .app-chip){
    gap: 0 !important;
    align-items: baseline;
    padding-bottom: 0.4rem;
    margin-bottom: 0.6rem !important;
    border-bottom: 1px solid var(--erp-border);
}
.doc-readonly .tab-pane .app-chip{
    border: 0;
    border-right: 1px solid var(--erp-border);
    border-radius: 0;
    background: transparent;
    padding: 0 0.7rem 0 0;
    margin-right: 0.7rem;
    gap: 0.3rem;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--erp-text-muted);
}
.doc-readonly .tab-pane .app-chip:last-child{
    border-right: 0;
    padding-right: 0;
    margin-right: 0;
}
.doc-readonly .tab-pane .app-chip .dot{ display: none; }
/* El valor es lo que se lee; la etiqueta acompana. */
.doc-readonly .tab-pane .app-chip strong,
.doc-readonly .tab-pane .app-chip a,
.doc-readonly .tab-pane .app-chip .font-weight-bold{ color: var(--erp-text-strong); }
/* Sin la pastilla sobra ancho: el valor no necesita elipsis (el maximo va
   inline en la plantilla). */
.doc-readonly .tab-pane .app-chip .text-truncate{ max-width: none !important; }
/* El chip destacado (N° oficial de una factura) conserva su color de marca. */
.doc-readonly .tab-pane .app-chip.app-primary-text,
.doc-readonly .tab-pane .app-chip.app-primary-text strong{ color: var(--erp-primary-text); }

/* -- 2. Compacto: rejilla de datos ---------------------------------------- */
/* Las filas bootstrap del panel se releen como rejilla auto-ajustable: 2
   columnas en el panel normal, 3 en pantallas anchas, 1 en movil. Los campos
   largos (cliente, direccion, notas) cuelgan del panel, no de la fila, y por
   eso siguen ocupando el ancho completo. */
.doc-readonly .tab-pane .row{
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 0 1.1rem;
    margin: 0;
}
.doc-readonly .tab-pane .row > [class*="col-"]{
    flex: none;
    width: auto;
    max-width: none;
    padding-left: 0;
    padding-right: 0;
}
.doc-readonly .tab-pane .mb-3,
.doc-readonly .tab-pane .row > [class*="col-"]{ margin-bottom: 0.5rem !important; }
.doc-readonly .tab-card .card-body{ gap: 0.45rem !important; padding: 0.9rem 1rem; }
/* La tarjeta de datos se ajusta a lo que tiene. En edicion se estira (`h-100`)
   para dar sitio a los buscadores; leyendo, estirarla solo deja un vacio blanco
   debajo de la ficha. */
.doc-readonly .doc-panel-left > .card{ height: auto !important; }  /* gana a .h-100 */
/* Sin la columna estirada, el divisor vertical quedaria colgando en el vacio:
   las tarjetas ya se separan solas. */
.doc-readonly .doc-panel-left{ border-right: 0; }
.doc-readonly .record-header{ margin-bottom: 0.6rem; }
.doc-readonly .card.report-card{ margin-bottom: 0.75rem; }

/* -- 3. Completo: sin scroll interno ni pestana huerfana ------------------ */
/* Leer un documento no debe obligar a un segundo scroll dentro de la matriz:
   la pagina scrollea, la ficha se ve entera. */
.doc-readonly .doc-lines-wrapper,
.doc-readonly .report-card .table-responsive{ max-height: none; }
/* La barra de pestanas que quedo con una sola solapa la oculta
   `initDocReadonly()` con esta clase (el titulo del panel ya nombra el bloque). */
.doc-readonly .nav-tabs.doc-tabs-lone{ display: none; }

/* -- Matriz de lineas en lectura ------------------------------------------ */
.doc-readonly #lines-table th,
.doc-readonly #lines-table td{ padding: 0.3rem 0.5rem; }
/* Encabezado en versalita fina: al achicarlo cabe entero en el % que le da la
   plantilla y deja de partirse a mitad de palabra ("CANTID/AD", "MEDIDA/S").
   No se fuerza `nowrap`: eso empujaria la tabla fuera de la tarjeta en pantallas
   angostas, que es peor que un titulo en dos lineas. */
.doc-readonly #lines-table thead th{
    font-size: 0.62rem;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--erp-text-muted);
    padding: 0.3rem 0.35rem;
}
/* Identidad de la fila: codigo fuerte, nombre tenue (§8.3). Vale para toda
   matriz: la celda de item marca su codigo con `.fw-bold` (OV, Recepcion...). */
.doc-readonly #lines-table .fw-bold,
.doc-readonly #lines-table .line-item-code{ color: var(--erp-text-strong); }
/* Lo que sobrevive en la fila es visor, no accion (la lupa de medidas): va en
   tamano de dato. Ademas evita que la matriz desborde la tarjeta en pantallas
   angostas, donde el boton pesaba mas que su columna. */
.doc-readonly #lines-table .btn{
    padding: 0.1rem 0.3rem;
    font-size: 0.75rem;
    line-height: 1.3;
}
/* Booleanos (IGV, "incluye flete"...): la etiqueta ES el dato, no una ayuda.
   Bootstrap la apaga con `:disabled ~ label`; hay que igualar esa especificidad. */
.doc-readonly .form-check-label,
.doc-readonly .form-check-input:disabled ~ .form-check-label{
    color: var(--erp-text-strong);
    font-weight: 600;
}
/* El total es el dato que se busca al abrir una aprobada: que resalte. */
.doc-readonly .summary-bar{ background: var(--erp-surface); border-color: var(--erp-border-strong); }
.doc-readonly .summary-bar .app-primary-text strong{ font-size: 1.05rem; }

/* -- Autocomplete (cliente / proveedor / item) -- */
.suggestion-list{
    position: absolute;
    z-index: 1090;
    width: 100%;
    max-height: 240px;
    overflow-y: auto;
    background: var(--erp-surface);
    border: 1px solid var(--erp-border-strong);
    border-radius: var(--erp-radius-sm);
    box-shadow: var(--erp-shadow-soft);
}
.suggestion-item{ padding: 0.4rem 0.6rem; cursor: pointer; }
.suggestion-item:hover,
.suggestion-item.active{ background: var(--erp-surface-subtle); }

/* -- Reportes -- */
/* Tarjeta de filtros: la barra superior de todo reporte. */
.report-filters .form-label{
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--erp-text-muted);
    margin-bottom: 0.2rem;
}
.report-filters-apply .btn{ margin-top: 0.2rem; }

/* Boton "Ejecutar" del reporte (accion, no navegacion). */
.btn-run-report{ font-weight: 600; }

/* Estado / toggles de filtro: checkboxes como pastillas seleccionables (mucho mas
   legibles que un check suelto). Sin :has() para maxima compatibilidad. */
.filter-toggle{ display: flex; flex-wrap: wrap; gap: 0.4rem; }
.filter-toggle-option{ margin: 0; cursor: pointer; }
.filter-toggle-option input{
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}
.filter-toggle-pill{
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.28rem 0.7rem;
    border-radius: 999px;
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--erp-text-muted);
    background: var(--erp-surface);
    border: 1px solid var(--erp-border-strong);
    transition: all 0.12s ease;
    user-select: none;
}
.filter-toggle-pill i{ opacity: 0.5; }
.filter-toggle-option:hover .filter-toggle-pill{ border-color: var(--erp-primary-soft); }
/* Seleccionado */
.filter-toggle-option input:checked + .filter-toggle-pill.approved{
    background: var(--erp-ok-soft); border-color: var(--erp-ok-border); color: var(--erp-ok-text);
}
.filter-toggle-option input:checked + .filter-toggle-pill.pending{
    background: var(--erp-warn-soft); border-color: var(--erp-warn-border); color: var(--erp-warn-text);
}
.filter-toggle-option input:checked + .filter-toggle-pill i{ opacity: 1; }
/* Foco accesible por teclado */
.filter-toggle-option input:focus-visible + .filter-toggle-pill{
    outline: 2px solid var(--erp-primary-soft);
    outline-offset: 1px;
}

/* Estado vacio: reporte aun no ejecutado. */
.report-placeholder .card-body{ padding: 2.75rem 1rem; }
.report-placeholder-icon{
    width: 3.25rem;
    height: 3.25rem;
    margin: 0 auto 0.85rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--erp-surface-subtle);
    color: var(--erp-primary-soft);
    font-size: 1.35rem;
}

/* Fila de metricas: stat-tiles homogeneos e identicos entre reportes. Todas la
   misma altura, con franja de marca y el VALOR grande justificado a la derecha. */
.report-metric{
    position: relative;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: 0.4rem;
    min-height: 5rem;
    padding: 0.8rem 1rem 0.8rem 1.15rem;
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius-md);
    background: var(--erp-surface);
    box-shadow: var(--erp-shadow-card);
    overflow: hidden;
    transition: box-shadow 0.15s ease, transform 0.15s ease;
}
.report-metric::before{
    content: "";
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 4px;
    background-image: var(--erp-gradient);
}
.report-metric:hover{
    box-shadow: var(--erp-shadow-soft);
    transform: translateY(-1px);
}
.metric-label{
    font-size: 0.72rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--erp-text-muted);
}
.metric-value{
    font-size: 1.5rem;
    font-weight: 700;
    line-height: 1.15;
    color: var(--erp-text-strong);
    text-align: right;
    font-variant-numeric: tabular-nums;
}
.metric-sub{
    font-size: 0.8rem;
    color: var(--erp-text-muted);
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* Anatomia ampliada de la metrica (docs/report-metric-modern-dashboard-guide.md
   §2 y §6): etiqueta + valor + VARIACION contra el periodo previo + un
   micrografico de contexto. Un monto suelto no dice si el negocio va mejor o
   peor; la variacion y la tendencia son la otra mitad del dato. Todas las
   piezas son opcionales: una metrica que solo trae label + value se sigue
   viendo exactamente igual que antes. */

/* Cabecera de la metrica: nombre a la izquierda, dato de contexto (conteo,
   periodo, estado) a la derecha. */
.metric-head{
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.5rem;
}
.metric-meta{
    font-size: 0.72rem;
    color: var(--erp-text-muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Fila de variacion: pastilla con la direccion + contra que se compara. Va
   justificada a la derecha para colgar del valor, que tambien lo esta. */
.metric-delta-row{
    display: flex;
    align-items: baseline;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: 0.35rem;
}
.metric-delta{
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    padding: 0.1rem 0.4rem;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}
/* El TONO no es el signo: en Costo, subir es malo. Lo decide la vista. */
.metric-delta--positive{ background: var(--erp-ok-soft); color: var(--erp-ok-text); }
.metric-delta--negative{ background: var(--erp-danger-soft); color: var(--erp-danger-text); }
.metric-delta--neutral{ background: var(--erp-surface-muted); color: var(--erp-text-muted); }
.metric-compare{
    font-size: 0.72rem;
    color: var(--erp-text-muted);
}

/* Sparkline: tendencia sin ejes ni etiquetas, para leer la forma de un vistazo.
   Es contexto, no el dato: la metrica se entiende igual sin ella (por eso el
   <svg> va con aria-label o aria-hidden, nunca mudo). */
.metric-spark{
    display: block;
    width: 100%;
    height: 2rem;
    margin-top: 0.15rem;
    color: var(--erp-primary-soft);
    overflow: visible;
}

/* Barra de proporcion: solo para una parte de un TODO conocido (0-100%), como
   el costo dentro de la venta o el margen. Nunca para un valor arbitrario. */
.metric-progress{
    height: 6px;
    margin-top: 0.4rem;
    border-radius: 999px;
    background: var(--erp-surface-muted);
    overflow: hidden;
}
.metric-progress > span{
    display: block;
    height: 100%;
    border-radius: inherit;
    background: var(--erp-primary);
}
.metric-progress--ok > span{ background: var(--erp-ok); }
.metric-progress--warn > span{ background: var(--erp-warn); }
.metric-progress--danger > span{ background: var(--erp-danger); }

/* Aviso de calidad del dato dentro de la metrica (p. ej. articulos sin costo
   promedio, que inflan la utilidad). Avisa en la tarjeta, no en una nota al pie. */
.metric-flag{
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--erp-warn-text);
}

/* Toolbar de la tarjeta de tabla (titulo + conteo). */
.report-table-toolbar{ gap: 0.75rem; }

/* Tabla de reporte: densa, legible, con cabecera fija y pie de totales marcado. */
.report-table thead th{
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--erp-surface-subtle);
    border-bottom: 1px solid var(--erp-border-strong);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--erp-text-muted);
    white-space: nowrap;
}
.report-table tbody td{
    vertical-align: middle;
    border-top-color: var(--erp-border);
}
.report-table tbody tr:hover{ background: var(--erp-surface-subtle); }
.report-table .cell-strong{ font-weight: 600; color: var(--erp-text-strong); }
.report-table .cell-sub{
    font-size: 0.78rem;
    color: var(--erp-text-muted);
}
/* Valor en rojo: SOLO para un numero que de verdad esta mal (utilidad o margen
   negativos). El signo menos ya esta en la cifra, asi que el color acompaña y
   no es la unica señal (guia §25). */
.report-table .cell-neg,
.report-metric .metric-value.cell-neg{ color: var(--erp-danger-text); font-weight: 600; }

/* -- Grafico de un reporte (bloque `report_chart`) ------------------------
   Vive entre las metricas y la tabla. Alto fijo y no aspect-ratio: doce meses en
   el eje x con alto proporcional al ancho dejan el grafico de 900px de alto en
   escritorio y de 90px en el celular. La leyenda es HTML y no la de Chart.js:
   asi la muestra lleva el mismo trazo que la linea (llena o cortada), que es lo
   que distingue las series sin depender del color. */
.report-chart-canvas{
    position: relative;
    height: 280px;
}
.report-chart-legend{
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 1.1rem;
    align-items: center;
}
.report-chart-legend .legend-item{
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--erp-text-muted);
}
.report-chart-legend .legend-mark{
    width: 1.5rem;
    height: 0;
    border-top-width: 2px;
    border-top-style: solid;
    flex: 0 0 auto;
}
.report-chart-legend .legend-mark.series-1{ border-top-color: var(--erp-chart-1); }
/* La serie de comparacion se dibuja cortada, en el grafico y en la leyenda. */
.report-chart-legend .legend-mark.series-2{
    border-top-color: var(--erp-chart-2);
    border-top-style: dashed;
}
.report-chart-note{
    font-size: 0.75rem;
    color: var(--erp-text-muted);
}

/* -- Matriz de ocupacion: una celda por mes ------------------------------
   La celda dice alquilado / libre con una FORMA (punto o guion) y no solo con
   color, para que se lea igual en blanco y negro y con cualquier vision del
   color. El mes que todavia no paso no es un mes libre: va vacio y atenuado,
   nunca con el guion de "libre". */
.rent-matrix td.rent-cell,
.rent-matrix th.rent-cell{
    text-align: center;
    padding-left: 0.2rem;
    padding-right: 0.2rem;
    white-space: nowrap;
}
.rent-dot{
    display: inline-block;
    width: 0.62rem;
    height: 0.62rem;
    border-radius: 50%;
    background: var(--erp-chart-1);
}
.rent-free{
    color: var(--erp-border-strong);
    font-weight: 700;
}
.rent-unknown{
    color: var(--erp-border);
}
/* Fila de un equipo que ya no esta en la flota: estuvo alquilado en el periodo
   pero hoy no tiene stock en los depositos de alquiler. Se muestra igual --su
   historia es real-- y se marca para que nadie lo cuente como capacidad de hoy. */
.rent-matrix tr.is-gone .cell-strong{ color: var(--erp-text-muted); }
.report-table tfoot td{
    background: var(--erp-surface-subtle);
    border-top: 2px solid var(--erp-border-strong);
    font-weight: 700;
    color: var(--erp-text-strong);
}
.report-table td.text-end,
.report-table th.text-end{ font-variant-numeric: tabular-nums; }

/* Vista DETALLADO: cada cabecera (documento) agrupa sus lineas + un subtotal. */
.report-table tbody.report-group + tbody.report-group{
    border-top: 8px solid transparent;
}
.report-table tr.report-group-head td{
    background: var(--erp-surface-subtle);
    border-top: 2px solid var(--erp-border-strong);
    padding-top: 0.5rem;
    padding-bottom: 0.5rem;
}
.report-group-head .group-title{ font-weight: 700; color: var(--erp-text-strong); }
.report-group-head .group-meta{ color: var(--erp-text-muted); }
.report-table tr.report-group-sub td{
    background: var(--erp-surface);
    border-top: 1px dashed var(--erp-border-strong);
    font-weight: 600;
    color: var(--erp-text-strong);
}

/* Switch de vistas Resumen / Detallado (cabecera del reporte). */
.report-mode-switch .btn{ font-weight: 600; }

/* Envoltura con scroll y cabecera fija para listados largos. */
.report-card .table-responsive{ max-height: 62vh; overflow-y: auto; }

/* Aviso de scroll horizontal de la tabla. Oculto por defecto: lo enciende
   `reportScrollHint` (erp-shell.js) SOLO cuando la tabla realmente desborda,
   asi no miente en un reporte de pocas columnas. Ver docs/style.md §10.2. */
.report-scroll-hint{
    display: none;
    align-items: center;
    gap: 0.35rem;
    margin-bottom: 0.4rem;
    font-size: 0.78rem;
}
.report-scroll-hint.is-visible{ display: flex; }
/* En escritorio la barra de scroll ya se ve y la tabla vuelve a su caja con
   scroll propio: el aviso seria ruido. */
@media (min-width: 992px){
    .report-scroll-hint.is-visible{ display: none; }
}

/* =====================================================================
   REPORTES EN TABLET Y MOVIL (docs/style.md §10.2)
   El reporte es la pantalla mas ancha del sistema (hasta 16 columnas) y a la
   vez la que mas se consulta desde el celular. Estas reglas solo ajustan
   ancho, gutters y densidad; el layout de escritorio no cambia.
   ===================================================================== */

/* Gutter vertical real de la barra de filtros y de la fila de metricas.
   `g-3` es una clase de Bootstrap 5 y este proyecto corre Bootstrap 4: no
   existe, asi que al envolverse las columnas quedaban pegadas (el label de un
   filtro contra el input de la fila de arriba, las metricas sin aire entre
   ellas). Se limita al reporte para no mover el resto de pantallas. */
.report-filters .row,
.row.report-metrics{ row-gap: 0.75rem; }

@media (max-width: 991.98px){
    /* En tablet el `.container` de Bootstrap se clava en 720px: hasta 270px de
       pantalla desperdiciados justo donde la tabla los necesita. El reporte
       usa todo el ancho disponible por debajo de lg. */
    .report-page{ max-width: none; }

    /* El scroll vertical anidado (62vh) deja el reporte en una ventana diminuta
       y en touch se come el gesto de scroll de la pagina. Debajo de lg la
       pagina scrollea normal y la tabla solo se desplaza en horizontal. */
    .report-page .report-card .table-responsive{ max-height: none; }
    .report-page .report-table thead th{ position: static; }
}

@media (max-width: 767.98px){
    /* Cabecera: la barra de acciones toma la linea completa y el switch de
       vistas reparte el ancho, en vez de desbordarse contra el borde. */
    .report-page .record-header .panel-toolbar{ width: 100%; gap: 0.5rem; }
    .report-page .report-mode-switch{
        display: flex;
        flex: 1 1 100%;
        margin-right: 0 !important;
    }
    .report-page .report-mode-switch .btn{
        flex: 1 1 0;
        padding-left: 0.25rem;
        padding-right: 0.25rem;
    }

    /* Metrica: a 1.5rem un monto como "S/ 1.234.567,89" parte en dos lineas
       dentro de una tarjeta de media pantalla. */
    .report-metric{
        min-height: 4.5rem;
        padding: 0.65rem 0.75rem 0.65rem 0.9rem;
    }
    .report-metric .metric-label{ font-size: 0.66rem; letter-spacing: 0.05em; }
    .report-metric .metric-value{ font-size: 1.15rem; }
    .report-metric .metric-sub{ font-size: 0.72rem; }
    /* Media pantalla: la sparkline se achica antes que el numero, y la
       variacion se queda (es lo que se mira primero en el celular). */
    .report-metric .metric-spark{ height: 1.5rem; }
    .report-metric .metric-meta,
    .report-metric .metric-compare{ font-size: 0.68rem; }

    /* Densidad de la tabla: entran ~2 columnas mas por pantalla sin perder
       legibilidad, y se acorta el desplazamiento horizontal. */
    .report-table{ font-size: 0.78rem; }
    .report-table th,
    .report-table td{ padding: 0.35rem 0.4rem; }
    .report-table .cell-sub{ font-size: 0.7rem; }
    .report-table .status-chip{ font-size: 0.7rem; padding: 0.15rem 0.45rem; }

    /* Toolbar de la tarjeta: titulo y conteo en dos lineas antes que apretados. */
    .report-table-toolbar{ flex-wrap: wrap; gap: 0.25rem 0.75rem; }

    /* "Ejecutar" ocupa el ancho completo al final de los filtros: es la accion
       de la pantalla y en touch necesita objetivo grande. */
    .report-filters-apply{ margin-top: 0.15rem; }
    .report-filters-apply .btn{ padding-top: 0.45rem; padding-bottom: 0.45rem; }

    /* Paginacion: los controles a la derecha y el conteo arriba, sin apretarse. */
    .report-pagination .pagination{ margin-left: auto; }
}

.filter-bar{
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    align-items: flex-end;
}

/* -- Tablas de registro: alineacion derecha utilitaria -- */
.table th.text-end,
.table td.text-end{ text-align: right; }

/* Utilidades de Bootstrap 5 que el proyecto ya escribe en las plantillas pero
   que BS 4.1 no trae (igual que `.text-end` de arriba). Sin esto, el codigo de
   item de toda matriz de lineas se pinta sin negrita y se pierde la jerarquia
   "codigo fuerte + nombre tenue" que pide docs/style.md §8.3. */
.fw-bold{ font-weight: 700 !important; }

/* -- Cabeceras ordenables de listado (docs/style.md §8.5) --
   La cabecera se ve igual que una fija; solo cambia el cursor y, en la columna
   activa, la flecha del sentido. Sin subrayado ni color de enlace: el listado no
   debe parecer un menu de links. */
.table thead th .sort-link{
    color: inherit;
    text-decoration: none;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    white-space: nowrap;
}

.table thead th .sort-link:hover{
    color: var(--erp-primary-text);
    text-decoration: none;
}

.table thead th .sort-link.is-active{
    color: var(--erp-primary-text);
}

.table thead th .sort-caret{
    font-size: 0.85em;
    opacity: 0.85;
}

/* Campos de valor (montos/cantidades): la utilidad .text-end tambien alinea a la
   derecha el texto DENTRO del input/select, no solo la celda. Estandariza los
   inputs numericos de las matrices de transaccion (ver docs/style.md §2.1). */
input.text-end,
select.text-end,
textarea.text-end,
.form-control.text-end{ text-align: right; }

@media (max-width: 991.98px){
    .doc-panel-left{
        border-right: 0;
        border-bottom: 1px solid var(--erp-border);
        padding-bottom: 1rem;
        margin-bottom: 1rem;
    }
}
@media (max-width: 991.98px){
    /* En pantallas sin scroll anidado comodo, la matriz fluye con la pagina. */
    .doc-lines-wrapper{
        max-height: none;
    }
}

@media (max-width: 767.98px){
    /* Guardado como barra full-width por ENCIMA del nav inferior (evita colision). */
    .form-footer,
    .doc-save-footer{
        left: 0;
        right: 0;
        bottom: 4.25rem;
        padding: 0.6rem 0.85rem calc(0.6rem + env(safe-area-inset-bottom));
        border-radius: 0;
        border-left: 0;
        border-right: 0;
        box-shadow: 0 -8px 24px rgba(var(--erp-ink-rgb), 0.16);
    }

    .doc-save-footer .doc-save-btn,
    .form-footer .btn{
        width: 100%;
        justify-content: center;
    }

    /* En movil el pie es una barra: el boton partido la ocupa entera, pero el
       caret conserva su ancho (si no, quedan dos mitades iguales). */
    .form-footer .btn-group{ display: flex; width: 100%; }
    .form-footer .btn-group > .btn{ width: auto; }
    .form-footer .btn-group > .btn:first-child{ flex: 1 1 auto; }
    .form-footer .btn-group > .dropdown-toggle-split{ flex: 0 0 auto; }

    /* -- Cabecera de transaccion compacta en movil --
       Se retira lo no accionable en touch: el breadcrumb (eyebrow) y el hint de
       atajos de teclado (Ctrl+Enter/F2). El estado del documento ya se comunica
       con el chip junto al titulo, asi que no se pierde informacion util. Solo
       aplica a documentos (`.doc-header`); los maestros no se tocan. */
    .doc-header .record-eyebrow,
    .doc-header .record-subtitle{
        display: none;
    }
    /* La barra de acciones cabe en una sola fila: el menu de herramientas queda
       icon-only (⋯) y "Adjuntos" pasa a vivir dentro de ese menu. */
    .doc-header .record-tools-menu-label{
        display: none;
    }
    .doc-header #record-tools-menu .fa-ellipsis-h{
        margin-right: 0;
    }
}

/* ==========================================================================
   Buscador global de pantallas (topbar)
   ========================================================================== */
.app-search{
    position: relative;
    width: 420px;
    max-width: 42vw;
}
.app-search-box{
    display: flex;
    align-items: center;
    height: 44px;
    background: rgba(var(--erp-chrome-rgb), 0.16);
    border: 1px solid rgba(var(--erp-chrome-rgb), 0.32);
    border-radius: 12px;
    padding: 0 0.9rem;
    transition: background .15s ease, border-color .15s ease, box-shadow .15s ease;
}
.app-search-box:focus-within{
    background: var(--erp-surface);
    border-color: var(--erp-surface);
    box-shadow: 0 8px 24px rgba(var(--erp-ink-rgb), 0.22);
}
.app-search-icon{
    color: rgba(var(--erp-chrome-rgb), 0.92);
    font-size: .95rem;
    flex: 0 0 auto;
}
.app-search-box:focus-within .app-search-icon{
    color: var(--erp-primary-text);
}
.app-search-input{
    flex: 1 1 auto;
    background: transparent;
    border: 0;
    outline: 0;
    color: var(--erp-chrome-text);
    font-size: .95rem;
    padding: .55rem .6rem;
    min-width: 0;
}
.app-search-input::placeholder{
    color: rgba(var(--erp-chrome-rgb), 0.72);
}
.app-search-box:focus-within .app-search-input{
    color: var(--erp-text-strong);
}
.app-search-box:focus-within .app-search-input::placeholder{
    color: var(--erp-text-muted);
}

.app-search-results{
    display: none;
    position: absolute;
    top: calc(100% + 10px);
    right: 0;
    left: 0;
    width: 100%;
    min-width: 380px;
    background: var(--erp-surface);
    border: 1px solid var(--erp-border);
    border-radius: 14px;
    box-shadow: var(--erp-shadow-soft);
    padding: .4rem;
    z-index: 1050;
    max-height: 72vh;
    overflow-y: auto;
}
.app-search-results.is-open{
    display: block;
}
.app-search-item{
    display: flex;
    align-items: center;
    gap: .8rem;
    padding: .6rem .7rem;
    border-radius: 10px;
    color: var(--erp-text-strong);
    text-decoration: none;
}
.app-search-item:hover,
.app-search-item.is-active{
    background: var(--erp-surface-subtle);
    color: var(--erp-text-strong);
}
.app-search-item-icon{
    flex: 0 0 38px;
    width: 38px;
    height: 38px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 10px;
    background: rgba(var(--erp-primary-rgb), 0.12);
    color: var(--erp-primary-text);
    font-size: .95rem;
}
.app-search-item-main{
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    line-height: 1.25;
}
.app-search-item-label{
    font-weight: 600;
    font-size: .95rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.app-search-item-module{
    font-size: .75rem;
    color: var(--erp-text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.app-search-item-kind{
    flex: 0 0 auto;
    font-size: .68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .03em;
    padding: .18rem .55rem;
    border-radius: 999px;
    background: var(--erp-surface-subtle);
    color: var(--erp-text-muted);
    border: 1px solid var(--erp-border);
}
.app-search-item-kind.kindregistro{
    background: rgba(var(--erp-primary-rgb), 0.12);
    color: var(--erp-primary-text);
    border-color: rgba(var(--erp-primary-rgb), 0.26);
}
.app-search-item-kind.kindtransaccion{
    background: var(--erp-info-soft);
    color: var(--erp-info-text);
    border-color: var(--erp-info-border);
}
.app-search-item-kind.kindreporte{
    background: var(--erp-ok-soft);
    color: var(--erp-ok-text);
    border-color: var(--erp-ok-border);
}
.app-search-empty{
    padding: .9rem .7rem;
    color: var(--erp-text-muted);
    font-size: .9rem;
    text-align: center;
}
.app-search-empty-hint{
    display: inline-block;
    margin-top: .2rem;
    font-size: .8rem;
    color: var(--erp-secondary);
}

/* --- Recientes (mismo panel del buscador; JS: erp-recents.js) --- */
.app-search-recents-btn{
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    padding: 0;
    margin-left: .25rem;
    border: 0;
    border-radius: 9px;
    background: transparent;
    color: rgba(var(--erp-chrome-rgb), 0.92);
    font-size: .9rem;
    cursor: pointer;
    transition: background .15s ease, color .15s ease;
}
.app-search-recents-btn:hover{
    background: rgba(var(--erp-chrome-rgb), 0.20);
    color: var(--erp-chrome-text);
}
.app-search-box:focus-within .app-search-recents-btn{
    color: var(--erp-primary-text);
}
.app-search-box:focus-within .app-search-recents-btn:hover{
    background: rgba(var(--erp-primary-rgb), 0.12);
}

/* Cabecera de seccion del panel ("Recientes" + Limpiar). */
.app-search-section{
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    padding: .45rem .7rem .35rem;
}
.app-search-section-title{
    font-size: .68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--erp-secondary);
}
.app-search-section-action{
    border: 0;
    background: transparent;
    padding: .1rem .35rem;
    border-radius: 8px;
    font-size: .75rem;
    font-weight: 600;
    color: var(--erp-primary-text);
    cursor: pointer;
}
.app-search-section-action:hover{
    background: rgba(var(--erp-primary-rgb), 0.12);
}

/* Fila = enlace + acciones (el <a> no puede contener botones). */
.app-search-row{
    display: flex;
    align-items: center;
    border-radius: 10px;
}
.app-search-row .app-search-item{
    flex: 1 1 auto;
    min-width: 0;
}
.app-search-row:hover{
    background: var(--erp-surface-subtle);
}
.app-search-item-actions{
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: .1rem;
    padding-right: .45rem;
}
.app-search-item-btn{
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    padding: 0;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: var(--erp-secondary);
    font-size: .75rem;
    cursor: pointer;
    opacity: .55;          /* visible tambien en tactil (no depende del hover) */
    transition: opacity .15s ease, background .15s ease, color .15s ease;
}
.app-search-row:hover .app-search-item-btn{
    opacity: 1;
}
.app-search-item-btn:hover{
    background: rgba(var(--erp-primary-rgb), 0.12);
    color: var(--erp-primary-text);
    opacity: 1;
}
/* Fijado: el pin queda encendido y girado, como una chinche clavada. */
.app-search-item-btn.is-on{
    color: var(--erp-primary-text);
    opacity: 1;
    transform: rotate(-35deg);
}

/* Overlay movil */
.app-search-overlay{
    position: fixed;
    inset: 0;
    background: rgba(var(--erp-ink-rgb), 0.55);
    z-index: 1060;
}
.app-search-overlay-bar{
    display: flex;
    align-items: center;
    gap: .35rem;
    padding: .7rem .8rem;
    background: var(--erp-gradient);
    background-color: var(--erp-primary);
}
.app-search-overlay-bar .app-search-box,
.app-search-overlay-bar > .app-search-input{
    flex: 1 1 auto;
}
.app-search-overlay-bar .app-search-input{
    background: rgba(var(--erp-chrome-rgb), 0.18);
    border: 1px solid rgba(var(--erp-chrome-rgb), 0.32);
    border-radius: 12px;
    padding: .6rem 1rem;
    height: 44px;
}
.app-search-overlay-bar .app-search-input:focus{
    background: var(--erp-surface);
    color: var(--erp-text-strong);
}
.app-search-results--overlay{
    display: block;
    position: static;
    width: auto;
    min-width: 0;
    max-width: none;
    margin: .6rem;
    border: 0;
    box-shadow: var(--erp-shadow-card);
    max-height: calc(100vh - 96px);
}
.app-search-results--overlay:empty{
    display: none;
}
body.app-search-overlay-open{
    overflow: hidden;
}

@media (max-width: 1200px){
    .app-search{ width: 320px; }
}

/* ==========================================================================
   Avisos: toasts y confirmaciones  (JS: erp-notify.js · docs/style.md §11)
   Componente canónico de notificación. No usar window.alert/confirm ni
   modales ad-hoc: consumir ErpToast / ErpConfirm.
   ========================================================================== */

/* Los tokens semanticos (--erp-ok/-warn/-danger/-info y sus variantes) viven
   con el resto de la marca al inicio de este archivo. */

/* --- Pila de toasts --- */
.erp-toast-stack{
    position: fixed;
    z-index: 1080;               /* por encima de modales Bootstrap (1050) */
    top: calc(1rem + env(safe-area-inset-top, 0px));
    right: 1rem;
    left: auto;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    width: min(380px, calc(100vw - 2rem));
    pointer-events: none;        /* la pila no intercepta; cada toast sí */
}

.erp-toast{
    pointer-events: auto;
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: 0.7rem;
    padding: 0.85rem 0.95rem;
    background: var(--erp-surface);
    color: var(--erp-text-strong);
    border-radius: var(--erp-radius-md);
    box-shadow: var(--erp-shadow-soft);
    border: 1px solid var(--erp-border);
    border-left: 4px solid var(--erp-info);
    overflow: hidden;
    opacity: 0;
    transform: translateY(-12px) scale(0.98);
    transition: opacity 0.28s ease, transform 0.28s cubic-bezier(0.16, 1, 0.3, 1);
}
.erp-toast.is-in{ opacity: 1; transform: translateY(0) scale(1); }
.erp-toast.is-out{ opacity: 0; transform: translateY(-8px) scale(0.98); }

.erp-toast__icon{
    flex: 0 0 auto;
    font-size: 1.15rem;
    line-height: 1.4;
    margin-top: 1px;
}
.erp-toast__content{ flex: 1 1 auto; min-width: 0; }
.erp-toast__title{
    font-weight: 700;
    font-size: 0.9rem;
    margin-bottom: 0.1rem;
}
.erp-toast__message{
    font-size: 0.9rem;
    line-height: 1.35;
    color: var(--erp-text-muted);
    word-wrap: break-word;
}
.erp-toast__title + .erp-toast__message{ color: var(--erp-text-muted); }
.erp-toast:not(:has(.erp-toast__title)) .erp-toast__message{ color: var(--erp-text-strong); }

.erp-toast__close{
    flex: 0 0 auto;
    border: 0;
    background: transparent;
    color: var(--erp-secondary);
    font-size: 1.35rem;
    line-height: 1;
    padding: 0 0.15rem;
    cursor: pointer;
    opacity: 0.7;
    transition: opacity 0.15s ease;
}
.erp-toast__close:hover{ opacity: 1; }

.erp-toast__progress{
    position: absolute;
    left: 0;
    bottom: 0;
    height: 3px;
    width: 100%;
    transform-origin: left center;
    background: currentColor;
    opacity: 0.35;
}

/* Variantes semánticas */
.erp-toast--success{ border-left-color: var(--erp-ok); }
.erp-toast--success .erp-toast__icon, .erp-toast--success .erp-toast__progress{ color: var(--erp-ok); }
.erp-toast--error{ border-left-color: var(--erp-danger); }
.erp-toast--error .erp-toast__icon, .erp-toast--error .erp-toast__progress{ color: var(--erp-danger); }
.erp-toast--warn{ border-left-color: var(--erp-warn); }
.erp-toast--warn .erp-toast__icon, .erp-toast--warn .erp-toast__progress{ color: var(--erp-warn); }
.erp-toast--info{ border-left-color: var(--erp-info); }
.erp-toast--info .erp-toast__icon, .erp-toast--info .erp-toast__progress{ color: var(--erp-info); }

/* En móvil: aterrizan abajo, ancho completo, entran desde abajo */
@media (max-width: 575.98px){
    .erp-toast-stack{
        top: auto;
        right: 0.75rem;
        left: 0.75rem;
        width: auto;
        bottom: calc(0.75rem + env(safe-area-inset-bottom, 0px));
        flex-direction: column-reverse;
    }
    .erp-toast{ transform: translateY(14px) scale(0.98); }
    .erp-toast.is-out{ transform: translateY(10px) scale(0.98); }
}

/* --- Diálogo de confirmación / aprobación --- */
.erp-modal-open{ overflow: hidden; }

.erp-confirm-backdrop{
    position: fixed;
    inset: 0;
    z-index: 1090;               /* por encima de toasts y modales */
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    background: rgba(var(--erp-ink-rgb), 0.55);
    backdrop-filter: blur(2px);
    opacity: 0;
    transition: opacity 0.2s ease;
}
.erp-confirm-backdrop.is-in{ opacity: 1; }
.erp-confirm-backdrop.is-out{ opacity: 0; }

.erp-confirm{
    width: min(420px, 100%);
    background: var(--erp-surface);
    border-radius: var(--erp-radius-lg);
    box-shadow: var(--erp-shadow-soft);
    padding: 1.5rem 1.4rem 1.2rem;
    text-align: center;
    transform: translateY(16px) scale(0.96);
    opacity: 0;
    transition: transform 0.26s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.26s ease;
}
.erp-confirm-backdrop.is-in .erp-confirm{ transform: translateY(0) scale(1); opacity: 1; }

.erp-confirm__icon{
    width: 3.25rem;
    height: 3.25rem;
    margin: 0 auto 0.85rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    font-size: 1.4rem;
    background: var(--erp-info-soft);
    color: var(--erp-info);
}
.erp-confirm--danger .erp-confirm__icon{ background: var(--erp-danger-soft); color: var(--erp-danger); }

.erp-confirm__title{
    font-weight: 700;
    font-size: 1.1rem;
    margin: 0 0 0.35rem;
    color: var(--erp-text-strong);
}
.erp-confirm__message{
    font-size: 0.95rem;
    line-height: 1.45;
    color: var(--erp-text-muted);
    margin: 0 0 1.25rem;
}
.erp-confirm__actions{
    display: flex;
    gap: 0.6rem;
}
.erp-confirm__btn{
    flex: 1 1 0;
    border: 0;
    border-radius: var(--erp-radius-sm);
    padding: 0.7rem 1rem;
    font-weight: 700;
    font-size: 0.92rem;
    cursor: pointer;
    transition: filter 0.15s ease, background 0.15s ease;
}
.erp-confirm__btn--cancel{
    background: var(--erp-surface-subtle);
    color: var(--erp-text-strong);
    border: 1px solid var(--erp-border-strong);
}
.erp-confirm__btn--cancel:hover{ background: var(--erp-surface-muted); }
.erp-confirm__btn--ok{
    background: var(--erp-gradient);
    color: var(--erp-primary-contrast);
}
.erp-confirm--danger .erp-confirm__btn--ok{ background: var(--erp-danger); }
.erp-confirm__btn--ok:hover{ filter: brightness(1.05); }
.erp-confirm__btn:focus-visible{ outline: 2px solid var(--erp-primary); outline-offset: 2px; }

@media (max-width: 575.98px){
    .erp-confirm-backdrop{ align-items: flex-end; padding: 0; }
    .erp-confirm{
        width: 100%;
        border-bottom-left-radius: 0;
        border-bottom-right-radius: 0;
        padding-bottom: calc(1.2rem + env(safe-area-inset-bottom, 0px));
        transform: translateY(100%);
    }
    .erp-confirm__actions{ flex-direction: column-reverse; }
}

@media (prefers-reduced-motion: reduce){
    .erp-toast, .erp-confirm-backdrop, .erp-confirm, .erp-toast__progress{
        transition: none !important;
    }
    .erp-toast{ transform: none; }
    .erp-confirm{ transform: none; }
}

/* ---- KPI del dashboard -------------------------------------------------
   Un solo numero, en el mismo hueco que ocuparia un grafico. Reusa los tokens
   de `.metric-value` pero en grande: aca el numero ES la tarjeta, no un
   acompanamiento de una tabla. */
.kpi-hero-wrap{
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 240px;
    gap: 0.5rem;
}
.kpi-hero{
    font-size: 3.25rem;
    font-weight: 700;
    line-height: 1;
    color: var(--erp-text-strong);
    font-variant-numeric: tabular-nums;
}
/* El rojo lo enciende el umbral, no el signo de la variacion: subir no siempre
   es malo, y el indicador es quien sabe que significa su propio numero. */
.kpi-hero.danger{ color: var(--erp-danger); }
.kpi-hero-unit{
    font-size: 1.25rem;
    font-weight: 600;
    margin-left: 0.15rem;
    color: var(--erp-text-muted);
}
.kpi-delta{
    font-size: 0.85rem;
    color: var(--erp-text-muted);
    font-variant-numeric: tabular-nums;
}


/* ==========================================================================
   PANELES — tablero tipo KANBAN (arquetipo `framework/panel_base.html`, §12)
   Un panel de trabajo se lee como un tablero: columnas con lienzo propio,
   tarjetas que se arrastran de una a otra, y —cuando el orden importa— una
   PILA numerada donde arriba es lo primero. Todo generico: otro panel los
   consume sin escribir CSS propio.
   ========================================================================== */

.panel-page{
    /* Lienzo del tablero: un gris apenas mas oscuro que la pagina, para que la
       tarjeta blanca flote sobre la columna en vez de fundirse con el fondo. */
    --panel-canvas: var(--erp-surface-subtle);
    --panel-card-border: var(--erp-border);
    --panel-card-shadow: 0 1px 1px rgba(var(--erp-ink-rgb), 0.12), 0 1px 3px rgba(var(--erp-ink-rgb), 0.08);
    --panel-card-shadow-hover: 0 8px 18px rgba(var(--erp-ink-rgb), 0.16), 0 2px 5px rgba(var(--erp-ink-rgb), 0.09);
    --panel-tint: rgba(var(--erp-primary-rgb), 0.10);
    --panel-erp-edge: var(--erp-info);
    /* Microtipografia del tablero (etiquetas, chips, numeros): Bariol solo trae
       la regular, y en versalitas pequenas la negrita sintetica se ensucia.
       Nunito —ya cargada por el shell— si tiene 700/800 reales. */
    --panel-font-ui: 'Nunito', 'Bariol', sans-serif;
}

.panel-board{
    display: grid;
    grid-template-columns: 1fr;
    gap: 1rem;
    align-items: stretch;
}
@media (min-width: 992px){
    .panel-board{ grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* --- columna del tablero ------------------------------------------------ */
.panel-column{
    position: relative;
    display: flex;
    flex-direction: column;
    min-height: 20rem;
    border: 1px solid var(--erp-border);
    border-radius: var(--erp-radius-lg);
    background: var(--panel-canvas);
    box-shadow: 0 1px 2px rgba(var(--erp-ink-rgb), 0.06);
    overflow: hidden;
}
/* Filo superior: identifica la columna sin gritar. La columna de destino
   (`.is-primary`) lleva el degradado de marca; el origen, un gris. */
.panel-column::before{
    content: "";
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 3px;
    background: var(--erp-border-strong);
    z-index: 2;
}
.panel-column.is-primary::before{ background-image: var(--erp-gradient); }
.panel-column.is-primary{ border-color: rgba(var(--erp-primary-rgb), 0.28); }

.panel-column-head{
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.7rem 0.85rem;
    background: var(--erp-surface);
    border-bottom: 1px solid var(--erp-border);
}
.panel-column-title{
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-family: var(--panel-font-ui);
    font-size: 0.72rem;
    font-weight: 800;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--erp-text-strong);
}
/* El icono va en su pastilla: da un ancla visual a la cabecera y alinea el
   subtitulo debajo del texto, no debajo del icono. */
.panel-column-title i{
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.6rem;
    height: 1.6rem;
    border-radius: 9px;
    background: var(--panel-tint);
    color: var(--erp-primary-text);
    font-size: 0.8rem;
    letter-spacing: 0;
}
.panel-column-sub{
    margin-top: 0.2rem;
    padding-left: 2.1rem;
    font-size: 0.74rem;
    line-height: 1.3;
    color: var(--erp-text-muted);
}
/* Conteo de la columna: reemplaza a la fila de metricas cuando el tablero ya
   dice cuanto hay de cada lado. */
.panel-count{
    flex: 0 0 auto;
    min-width: 1.9rem;
    padding: 0.15rem 0.55rem;
    border-radius: 999px;
    background: var(--erp-surface-subtle);
    border: 1px solid var(--erp-border);
    font-family: var(--panel-font-ui);
    font-size: 0.8rem;
    font-weight: 800;
    color: var(--erp-text-muted);
    font-variant-numeric: tabular-nums;
    text-align: center;
    transition: background 0.18s ease, color 0.18s ease, border-color 0.18s ease;
}
/* Con contenido, el conteo se enciende: es el que dice si hay recorrido. */
.panel-count.is-active{
    background-image: var(--erp-gradient);
    border-color: transparent;
    color: var(--erp-primary-contrast);
    box-shadow: 0 2px 8px rgba(var(--erp-primary-rgb), 0.28);
}

.panel-column-meta{
    padding: 0.7rem 0.85rem 0.15rem;
    background: var(--erp-surface);
    border-bottom: 1px solid var(--erp-border);
}
.panel-column-meta .form-label{
    font-family: var(--panel-font-ui);
    font-size: 0.66rem;
    font-weight: 800;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--erp-text-muted);
    margin-bottom: 0.2rem;
}
.panel-column-meta .form-control{
    border-radius: 8px;
    border-color: var(--erp-border-strong);
}
.panel-column-foot{
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0.5rem;
    padding: 0.7rem 0.85rem;
    background: var(--erp-surface);
    border-top: 1px solid var(--erp-border);
}

/* --- zona soltable ------------------------------------------------------ */
.panel-dropzone{
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    min-height: 8rem;
    max-height: 58vh;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 0.7rem;
    scrollbar-width: thin;
    scrollbar-color: var(--erp-thumb) transparent;
    transition: background 0.15s ease, box-shadow 0.15s ease;
}
.panel-dropzone::-webkit-scrollbar{ width: 10px; }
.panel-dropzone::-webkit-scrollbar-track{ background: transparent; }
.panel-dropzone::-webkit-scrollbar-thumb{
    background: var(--erp-thumb);
    border: 3px solid transparent;
    background-clip: padding-box;
    border-radius: 999px;
}
.panel-dropzone::-webkit-scrollbar-thumb:hover{ background: var(--erp-thumb-hover); background-clip: padding-box; }
 /* "Suelta aqui": marco punteado por dentro, con las esquinas redondeadas de la
   columna. Un recuadro cuadrado dentro de una columna redonda se ve roto. */
.panel-dropzone.is-over{
    background: rgba(var(--erp-primary-rgb), 0.10);
    border-radius: var(--erp-radius-md);
    outline: 2px dashed var(--erp-primary-soft);
    outline-offset: -6px;
}
/* Con la zona vacia, el marco de "suelta aqui" ya es el borde punteado: el del
   estado vacio sobra y se ven dos rectangulos discontinuos, uno dentro del otro. */
.panel-dropzone.is-over .panel-dropzone-empty{
    border-color: transparent;
    background: transparent;
}
.panel-dropzone-empty{
    margin: auto;
    width: 100%;
    padding: 1.35rem 0.9rem;
    text-align: center;
    border: 1px dashed var(--erp-border-strong);
    border-radius: var(--erp-radius-md);
    background: var(--erp-surface-veil);
    color: var(--erp-text-muted);
    font-size: 0.8rem;
    line-height: 1.45;
}
.panel-dropzone-empty i{
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.3rem;
    height: 2.3rem;
    margin: 0 auto 0.55rem;
    border-radius: 50%;
    background: var(--erp-surface);
    border: 1px solid var(--erp-border);
    font-size: 0.95rem;
    opacity: 0.75;
}

/* --- tarjeta ------------------------------------------------------------ */
.panel-card{
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.55rem;
    padding: 0.55rem 0.6rem 0.55rem 0.75rem;
    border: 1px solid var(--panel-card-border);
    border-radius: var(--erp-radius-sm);
    background: var(--erp-surface);
    box-shadow: var(--panel-card-shadow);
    cursor: grab;
    -webkit-font-smoothing: antialiased;
    transition: box-shadow 0.18s ease, transform 0.18s ease, border-color 0.18s ease;
}
.panel-card:hover{
    box-shadow: var(--panel-card-shadow-hover);
    border-color: var(--erp-border-strong);
    transform: translateY(-1px);
}
.panel-card:active{ cursor: grabbing; }
/* La tarjeta levantada se inclina, como el papel que se despega del tablero. */
.panel-card.is-dragging{
    opacity: 0.5;
    transform: rotate(1.2deg);
    box-shadow: none;
}
/* Mientras se arrastra, el resto del tablero se queda quieto: el hover que
   levanta tarjetas compite con la linea de destino. */
.is-dragging-card .panel-card:hover{
    transform: none;
    box-shadow: var(--panel-card-shadow);
    border-color: var(--panel-card-border);
}
/* La entrega que viene del ERP se distingue por el filo, no por otra etiqueta:
   la tarjeta tiene que leerse de un vistazo (cliente, direccion, fecha). */
.panel-card::before{
    content: "";
    position: absolute;
    left: 0;
    top: 0.45rem;
    bottom: 0.45rem;
    width: 3px;
    border-radius: 0 3px 3px 0;
    background: var(--erp-primary-soft);
}
.panel-card.from-erp::before{ background: var(--panel-erp-edge); }
/* La tarjeta que acaba de moverse entra sola: confirma el movimiento sin toast. */
@keyframes panelCardIn{
    from{ opacity: 0; transform: translateY(-5px) scale(0.985); }
    to{ opacity: 1; transform: none; }
}
.panel-card.is-moved{ animation: panelCardIn 0.2s ease-out; }

/* Agarradera: seis puntos, la senal universal de "esto se arrastra". */
.panel-card-grip{
    flex: 0 0 auto;
    width: 0.5rem;
    height: 1.1rem;
    color: var(--erp-text-muted);
    opacity: 0.3;
    background-image: radial-gradient(currentColor 1.1px, transparent 1.2px);
    background-size: 0.25rem 0.28rem;
    transition: opacity 0.15s ease;
}
.panel-card:hover .panel-card-grip{ opacity: 0.6; }

.panel-card-main{
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
}
/* Primera linea: cliente a la izquierda, fecha estimada a la derecha. La fecha
   se alinea en columna entre tarjetas, que es como se escanea una lista. */
.panel-card-head{
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}
.panel-card-title{
    font-weight: 700;
    font-size: 0.88rem;
    line-height: 1.25;
    letter-spacing: -0.005em;
    color: var(--erp-text-strong);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Segunda linea: donde. El pin lo dice sin gastar una palabra. */
.panel-card-sub{
    display: flex;
    align-items: center;
    gap: 0.32rem;
    font-size: 0.76rem;
    line-height: 1.3;
    color: var(--erp-text-muted);
    min-width: 0;
}
.panel-card-sub::before{
    content: "\f3c5";
    font-family: "Font Awesome 5 Free";
    font-weight: 900;
    font-size: 0.68rem;
    opacity: 0.45;
    flex: 0 0 auto;
}
.panel-card-sub span{
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Etiqueta de carga (bultos): numero pegado a su icono, al final de la linea
   de la direccion. No compite con la fecha —que es cuando— porque responde otra
   pregunta: cuanto sube al camion. */
.panel-card-tag{
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    margin-left: auto;
    padding: 0.05rem 0.4rem;
    border-radius: 6px;
    background: var(--erp-surface-subtle);
    border: 1px solid var(--erp-border);
    font-family: var(--panel-font-ui);
    font-size: 0.68rem;
    font-weight: 700;
    color: var(--erp-text-muted);
    font-variant-numeric: tabular-nums;
}
.panel-card-tag i{ font-size: 0.62rem; opacity: 0.65; }

.panel-card-date{
    flex: 0 0 auto;
    padding: 0.1rem 0.45rem;
    border-radius: 999px;
    background: var(--panel-tint);
    font-family: var(--panel-font-ui);
    font-size: 0.7rem;
    font-weight: 700;
    color: var(--erp-primary-text);
    font-variant-numeric: tabular-nums;
}
.panel-card-date.is-empty{
    background: var(--erp-surface-muted);
    color: var(--erp-text-muted);
    font-weight: 600;
}

/* Acciones: aparecen tenues y se encienden en hover/foco. En touch quedan
   siempre visibles, porque ahi son el unico camino (no hay arrastre HTML5). */
.panel-card-actions{
    display: flex;
    align-items: center;
    gap: 0.1rem;
    flex: 0 0 auto;
    opacity: 0.4;
    transition: opacity 0.15s ease;
}
.panel-card:hover .panel-card-actions,
.panel-card:focus-within .panel-card-actions{ opacity: 1; }
@media (hover: none){
    .panel-card-actions{ opacity: 1; }
    /* Sin mouse no hay arrastre HTML5: la agarradera prometeria algo que no pasa. */
    .panel-card-grip{ display: none; }
}
/* Boton de icono del tablero: sin caja hasta que se apunta, para que la
   tarjeta se lea como una tarjeta y no como una barra de herramientas. */
.panel-icon-btn{
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.65rem;
    height: 1.65rem;
    padding: 0;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: var(--erp-text-muted);
    font-size: 0.74rem;
    line-height: 1;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease;
}
.panel-icon-btn:hover{ background: var(--erp-surface-muted); color: var(--erp-text-strong); }
.panel-icon-btn.is-primary:hover{ background: var(--panel-tint); color: var(--erp-primary-text); }
.panel-icon-btn.is-danger:hover{ background: var(--erp-danger-soft); color: var(--erp-danger-text); }
.panel-icon-btn:focus{ outline: none; }
.panel-icon-btn:focus-visible{ box-shadow: 0 0 0 2px rgba(var(--erp-primary-rgb), 0.40); }

/* --- la PILA: el recorrido, arriba lo primero que se entrega ------------- */
.panel-stack{ position: relative; }
/* Hilo del recorrido, entre los numeros de parada. */
.panel-stack .panel-card + .panel-card::after{
    content: "";
    position: absolute;
    left: 1.57rem;
    top: -0.5rem;
    height: 0.5rem;
    border-left: 2px dotted rgba(var(--erp-primary-rgb), 0.45);
}
.panel-card-order{
    flex: 0 0 auto;
    width: 1.65rem;
    height: 1.65rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 9px;
    background: var(--erp-surface-subtle);
    border: 1px solid var(--erp-border);
    color: var(--erp-text-muted);
    font-family: var(--panel-font-ui);
    font-weight: 800;
    font-size: 0.76rem;
    font-variant-numeric: tabular-nums;
}
/* La primera parada es la que ordena todo el recorrido: se ve. */
.panel-stack .panel-card:first-child .panel-card-order{
    background-image: var(--erp-gradient);
    border-color: transparent;
    color: var(--erp-primary-contrast);
    box-shadow: 0 2px 6px rgba(var(--erp-primary-rgb), 0.30);
}
.panel-stack-hint{
    padding: 0.15rem 0.75rem 0.4rem;
    font-size: 0.72rem;
    color: var(--erp-text-muted);
}

/* Marca de donde va a caer la tarjeta que se arrastra. */
.panel-drop-line{
    position: relative;
    height: 0;
    border-top: 2px solid var(--erp-primary);
    border-radius: 2px;
    margin: -0.05rem 0;
}
.panel-drop-line::before{
    content: "";
    position: absolute;
    left: -1px;
    top: -4px;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--erp-primary);
}

@media (max-width: 575.98px){
    .panel-dropzone{ max-height: 52vh; padding: 0.55rem; }
    .panel-card-title{ font-size: 0.85rem; }
}


/* ==========================================================================
   MAPA DEL RECORRIDO (Google Maps Embed API)
   Lo usan el panel de Programacion de Entregas y el registro Hoja de Ruta con
   el mismo marcado, para que el recorrido se vea igual en las dos pantallas.
   ========================================================================== */
.route-map-head{
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-bottom: 0.6rem;
}
/* Relacion de aspecto fija: el iframe de Google no tiene alto propio, y sin
   esto el mapa colapsa a cero. Alto acotado para que no se coma la pantalla. */
.route-map-frame{
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 6;
    min-height: 240px;
    /* Acotado a proposito: el mapa acompana al tablero, no lo reemplaza. Si se
       lo deja crecer, empuja fuera de pantalla lo que hay debajo. */
    max-height: 360px;
    border-radius: var(--erp-radius-md);
    overflow: hidden;
    background: var(--erp-surface-subtle);
    border: 1px solid var(--erp-border);
}
.route-map-frame iframe{
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
    display: block;
}
/* El enlace a Google Maps no se apaga con `disabled` (es un <a>): se apaga a
   mano cuando todavia no hay recorrido que abrir. */
.route-map-head .btn.disabled{
    pointer-events: none;
    opacity: 0.45;
}

/* Enlace a Maps DENTRO de la tarjeta del tablero: un icono mas entre las
   acciones, no una fila aparte. */
.panel-card-actions .panel-icon-btn.is-map:hover{
    background: var(--erp-info-soft);
    color: var(--erp-info-text);
}


/* ==========================================================================
   MARCA SOBRE BOOTSTRAP 4 / sb-admin-2  (aplica en los dos temas)
   Las hojas de vendor traen su propio azul (#007bff) y sus pasteles en
   paginacion, checkboxes, alertas, badges y focus. Aca se reescriben con
   tokens: es la unica forma de que "sin colores hardcodeados" sea cierto sin
   editar las hojas de vendor (que se reemplazan al actualizar).
   ========================================================================== */

/* Foco: el anillo tambien es marca. */
.form-control:focus,
.custom-select:focus,
.custom-file-input:focus ~ .custom-file-label,
.form-check-input:focus{
    border-color: var(--erp-primary-soft);
    box-shadow: 0 0 0 0.2rem rgba(var(--erp-primary-rgb), 0.20);
}
.btn:focus,
.btn.focus{ box-shadow: 0 0 0 0.2rem rgba(var(--erp-primary-rgb), 0.25); }

/* Checkboxes, radios y switches. */
.custom-control-input:checked ~ .custom-control-label::before{
    background-color: var(--erp-primary);
    border-color: var(--erp-primary);
}
.custom-control-input:focus ~ .custom-control-label::before{
    box-shadow: 0 0 0 0.2rem rgba(var(--erp-primary-rgb), 0.20);
}
.custom-control-input:focus:not(:checked) ~ .custom-control-label::before{
    border-color: var(--erp-primary-soft);
}
.custom-range::-webkit-slider-thumb{ background-color: var(--erp-primary); }
.custom-range::-moz-range-thumb{ background-color: var(--erp-primary); }

/* Paginacion. */
.page-link{ color: var(--erp-primary-text); }
.page-link:hover{ color: var(--erp-primary-strong); }
.page-item.active .page-link{
    background-color: var(--erp-primary);
    border-color: var(--erp-primary);
    color: var(--erp-primary-contrast);
}

/* Seleccion activa en listas y menus. */
.list-group-item.active{
    background-color: var(--erp-primary);
    border-color: var(--erp-primary);
    color: var(--erp-primary-contrast);
}
.dropdown-item.active,
.dropdown-item:active{
    background-color: var(--erp-primary);
    color: var(--erp-primary-contrast);
}
.nav-pills .nav-link.active,
.nav-pills .show > .nav-link{
    background-color: var(--erp-primary);
    color: var(--erp-primary-contrast);
}
.progress-bar{ background-color: var(--erp-primary); }
.btn-link{ color: var(--erp-primary-text); }
.btn-link:hover{ color: var(--erp-primary-strong); }
.btn-outline-primary{
    color: var(--erp-primary-text);
    border-color: var(--erp-primary);
}
.btn-outline-primary:hover,
.btn-outline-primary:focus,
.btn-outline-primary:not(:disabled):not(.disabled).active{
    background-color: var(--erp-primary);
    border-color: var(--erp-primary);
    color: var(--erp-primary-contrast);
}
.border-bottom-primary{ border-bottom: .25rem solid var(--erp-primary) !important; }

/* Utilidades de texto y de estado: mismo vocabulario que los chips. */
.text-muted{ color: var(--erp-text-muted) !important; }
.text-success{ color: var(--erp-ok-text) !important; }
.text-danger{ color: var(--erp-danger-text) !important; }
.text-warning{ color: var(--erp-warn-text) !important; }
.text-info{ color: var(--erp-info-text) !important; }

/* Alertas y badges: pastilla suave (mismo lenguaje que .status-chip), no
   bloques saturados que en oscuro quedan ilegibles. */
.alert-primary{
    background-color: rgba(var(--erp-primary-rgb), 0.10);
    border-color: rgba(var(--erp-primary-rgb), 0.28);
    color: var(--erp-primary-text);
}
.alert-success{ background-color: var(--erp-ok-soft); border-color: var(--erp-ok-border); color: var(--erp-ok-text); }
.alert-danger{ background-color: var(--erp-danger-soft); border-color: var(--erp-danger-border); color: var(--erp-danger-text); }
.alert-warning{ background-color: var(--erp-warn-soft); border-color: var(--erp-warn-border); color: var(--erp-warn-text); }
.alert-info{ background-color: var(--erp-info-soft); border-color: var(--erp-info-border); color: var(--erp-info-text); }
.alert-secondary,
.alert-light,
.alert-dark{
    background-color: var(--erp-surface-muted);
    border-color: var(--erp-border);
    color: var(--erp-text-strong);
}
.badge-success{ background-color: var(--erp-ok-soft); color: var(--erp-ok-text); }
.badge-danger{ background-color: var(--erp-danger-soft); color: var(--erp-danger-text); }
.badge-warning{ background-color: var(--erp-warn-soft); color: var(--erp-warn-text); }
.badge-info{ background-color: var(--erp-info-soft); color: var(--erp-info-text); }
.badge-secondary,
.badge-light{ background-color: var(--erp-surface-muted); color: var(--erp-text-muted); }
.badge-dark{ background-color: var(--erp-surface-strong); color: var(--erp-chrome-text); }

/* Tooltips y popovers: verde montana, como el resto del cromo. */
.tooltip-inner{ background-color: var(--erp-surface-strong); color: var(--erp-chrome-text); }
.bs-tooltip-top .arrow::before,
.bs-tooltip-auto[x-placement^="top"] .arrow::before{ border-top-color: var(--erp-surface-strong); }
.bs-tooltip-bottom .arrow::before,
.bs-tooltip-auto[x-placement^="bottom"] .arrow::before{ border-bottom-color: var(--erp-surface-strong); }
.bs-tooltip-left .arrow::before,
.bs-tooltip-auto[x-placement^="left"] .arrow::before{ border-left-color: var(--erp-surface-strong); }
.bs-tooltip-right .arrow::before,
.bs-tooltip-auto[x-placement^="right"] .arrow::before{ border-right-color: var(--erp-surface-strong); }


/* ==========================================================================
   TEMA OSCURO — superficies de vendor
   El shell ya es todo tokens; lo que falta son los componentes que Bootstrap
   pinta en blanco duro (tarjetas, modales, menus, tablas, campos). Se reescribe
   el fondo/borde/tinta con los mismos tokens, para que el tema sea un cambio de
   variables y no una segunda hoja de estilos.
   ========================================================================== */
[data-theme="dark"] .card,
[data-theme="dark"] .modal-content,
[data-theme="dark"] .dropdown-menu,
[data-theme="dark"] .popover,
[data-theme="dark"] .list-group-item,
[data-theme="dark"] .accordion > .card{
    background-color: var(--erp-surface);
    color: var(--erp-text-strong);
    border-color: var(--erp-border);
}
[data-theme="dark"] .card-footer,
[data-theme="dark"] .modal-header,
[data-theme="dark"] .modal-footer,
[data-theme="dark"] .list-group-item + .list-group-item{ border-color: var(--erp-border); }
[data-theme="dark"] .card-footer{ background-color: var(--erp-surface-subtle); }
[data-theme="dark"] hr{ border-top-color: var(--erp-border); }
[data-theme="dark"] .bg-white,
[data-theme="dark"] .bg-light{ background-color: var(--erp-surface) !important; }
[data-theme="dark"] .text-dark,
[data-theme="dark"] .text-gray-900,
[data-theme="dark"] .text-gray-800,
[data-theme="dark"] .text-black-50{ color: var(--erp-text-strong) !important; }
[data-theme="dark"] .text-gray-600,
[data-theme="dark"] .text-gray-500,
[data-theme="dark"] .text-gray-400,
[data-theme="dark"] .text-gray-300{ color: var(--erp-text-muted) !important; }
[data-theme="dark"] .border,
[data-theme="dark"] .border-top,
[data-theme="dark"] .border-right,
[data-theme="dark"] .border-bottom,
[data-theme="dark"] .border-left{ border-color: var(--erp-border) !important; }

/* Campos. El `color-scheme: dark` del token raiz ya oscurece los controles
   nativos (flecha del select, calendario, barras de scroll). */
[data-theme="dark"] .form-control,
[data-theme="dark"] .custom-select,
[data-theme="dark"] .input-group-text,
[data-theme="dark"] .custom-file-label{
    background-color: var(--erp-surface-muted);
    border-color: var(--erp-border-strong);
    color: var(--erp-text-strong);
}
[data-theme="dark"] .form-control:focus,
[data-theme="dark"] .custom-select:focus{
    background-color: var(--erp-surface-muted);
    color: var(--erp-text-strong);
}
[data-theme="dark"] .form-control::placeholder{ color: var(--erp-secondary); }
[data-theme="dark"] .form-control:disabled,
[data-theme="dark"] .form-control[readonly]{
    background-color: var(--erp-surface-subtle);
    color: var(--erp-text-muted);
}
[data-theme="dark"] .custom-control-label::before{
    background-color: var(--erp-surface-muted);
    border-color: var(--erp-border-strong);
}

/* Tablas. */
[data-theme="dark"] .table{ color: var(--erp-text-strong); }
[data-theme="dark"] .table th,
[data-theme="dark"] .table td,
[data-theme="dark"] .table-bordered,
[data-theme="dark"] .table-bordered th,
[data-theme="dark"] .table-bordered td{ border-color: var(--erp-border); }
[data-theme="dark"] .table thead th{ border-bottom-color: var(--erp-border-strong); }
[data-theme="dark"] .table-striped tbody tr:nth-of-type(odd){
    background-color: rgba(var(--erp-chrome-rgb), 0.035);
}
[data-theme="dark"] .table-hover tbody tr:hover{
    background-color: var(--erp-surface-muted);
    color: var(--erp-text-strong);
}
[data-theme="dark"] .table-light,
[data-theme="dark"] .table-light > th,
[data-theme="dark"] .table-light > td,
[data-theme="dark"] .thead-light th{
    background-color: var(--erp-surface-muted);
    color: var(--erp-text-muted);
    border-color: var(--erp-border);
}

/* Menus, pestañas, paginacion y cierres. */
[data-theme="dark"] .dropdown-item{ color: var(--erp-text-strong); }
[data-theme="dark"] .dropdown-item:hover,
[data-theme="dark"] .dropdown-item:focus{
    background-color: var(--erp-surface-muted);
    color: var(--erp-text-strong);
}
[data-theme="dark"] .dropdown-divider{ border-color: var(--erp-border); }
[data-theme="dark"] .dropdown-header:not([class*="app-primary"]){ color: var(--erp-text-muted); }
[data-theme="dark"] .close{ color: var(--erp-text-strong); text-shadow: none; opacity: 0.75; }
[data-theme="dark"] .close:hover{ color: var(--erp-text-strong); opacity: 1; }
[data-theme="dark"] .nav-tabs{ border-bottom-color: var(--erp-border); }
[data-theme="dark"] .nav-tabs .nav-link{ color: var(--erp-text-muted); }
[data-theme="dark"] .nav-tabs .nav-link:hover{ border-color: transparent; }
[data-theme="dark"] .nav-tabs .nav-link.active{
    background-color: var(--erp-surface);
    border-color: var(--erp-border) var(--erp-border) var(--erp-surface);
    color: var(--erp-text-strong);
}
[data-theme="dark"] .page-link{
    background-color: var(--erp-surface);
    border-color: var(--erp-border);
}
[data-theme="dark"] .page-item.disabled .page-link{
    background-color: var(--erp-surface-subtle);
    color: var(--erp-secondary);
}
[data-theme="dark"] .btn-light,
[data-theme="dark"] .btn-secondary,
[data-theme="dark"] .btn-outline-secondary{
    background-color: var(--erp-surface-muted);
    border-color: var(--erp-border-strong);
    color: var(--erp-text-strong);
}
[data-theme="dark"] .btn-light:hover,
[data-theme="dark"] .btn-secondary:hover,
[data-theme="dark"] .btn-outline-secondary:hover{
    background-color: var(--erp-border);
    border-color: var(--erp-border-strong);
    color: var(--erp-text-strong);
}
[data-theme="dark"] .modal-backdrop.show{ opacity: 0.7; }

/* La tabla de reporte tiene la cabecera pegajosa sobre el propio lienzo: en
   oscuro necesita opacidad real o las filas se ven por debajo. */
[data-theme="dark"] .report-table thead th,
[data-theme="dark"] .report-table tfoot td{ background-color: var(--erp-surface-muted); }


/* ==========================================================================
   CONMUTADOR DE TEMA (menu de usuario · JS: initTheme en erp-shell.js)
   Tres estados explicitos —Claro / Oscuro / Automatico— porque "automatico"
   sigue al sistema operativo y no todo el mundo quiere eso en horario de
   oficina. La eleccion se guarda por navegador (localStorage).
   ========================================================================== */
.theme-switch{
    display: flex;
    gap: 0.2rem;
    padding: 0.2rem;
    margin: 0.15rem 0.75rem 0.35rem;
    border-radius: 999px;
    background: var(--erp-surface-muted);
    border: 1px solid var(--erp-border);
}
.theme-switch__opt{
    flex: 1 1 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.3rem;
    padding: 0.3rem 0.4rem;
    border: 0;
    border-radius: 999px;
    background: transparent;
    color: var(--erp-text-muted);
    font-size: 0.72rem;
    font-weight: 700;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease;
}
.theme-switch__opt:hover{ color: var(--erp-text-strong); }
.theme-switch__opt.is-on{
    background: var(--erp-surface);
    color: var(--erp-primary-text);
    box-shadow: 0 1px 2px rgba(var(--erp-ink-rgb), 0.12);
}
.theme-switch__opt i{ font-size: 0.72rem; }


/* --------------------------------------------------------------------------
   Fugas de color de sb-admin-2: la plantilla trae su propio azul (#4e73df) y
   sus grises en el submenu del sidebar y en el desplegable de la campana. Se
   reescriben con la misma especificidad que la hoja original (que carga antes)
   para que no quede un solo color ajeno a la marca.
   -------------------------------------------------------------------------- */
.sidebar .nav-item .collapse .collapse-inner,
.sidebar .nav-item .collapsing .collapse-inner{ background-color: var(--erp-surface); }
.sidebar .nav-item .collapse .collapse-inner .collapse-header,
.sidebar .nav-item .collapsing .collapse-inner .collapse-header{ color: var(--erp-text-muted); }
.sidebar .nav-item .collapse .collapse-inner .collapse-item,
.sidebar .nav-item .collapsing .collapse-inner .collapse-item{ color: var(--erp-text-strong); }
.sidebar .nav-item .collapse .collapse-inner .collapse-item:hover,
.sidebar .nav-item .collapsing .collapse-inner .collapse-item:hover{ background-color: var(--erp-surface-muted); }
.sidebar .nav-item .collapse .collapse-inner .collapse-item:active,
.sidebar .nav-item .collapsing .collapse-inner .collapse-item:active{ background-color: var(--erp-border); }
.sidebar .nav-item .collapse .collapse-inner .collapse-item.active,
.sidebar .nav-item .collapsing .collapse-inner .collapse-item.active{ color: var(--erp-primary-text); }

.topbar .topbar-divider{ border-right-color: rgba(var(--erp-chrome-rgb), 0.25); }
.topbar .dropdown-list .dropdown-header{
    background-color: var(--erp-primary);
    border-color: var(--erp-primary);
    background-image: var(--erp-gradient);
    color: var(--erp-primary-contrast);
}
.topbar .dropdown-list .dropdown-item{
    border-left-color: var(--erp-border);
    border-right-color: var(--erp-border);
    border-bottom-color: var(--erp-border);
}

/* Miniatura del logo en Configuracion: se muestra sobre el mismo verde del
   sidebar, que es donde el logo va a vivir. */
.settings-logo-preview{
    max-height: 48px;
    max-width: 120px;
    object-fit: contain;
    padding: 4px;
    background: var(--erp-chrome-solid);
}

/* --------------------------------------------------------------------------
   Lienzo y cromo: sb-admin-2 los fija con un ID (`#wrapper #content-wrapper`)
   y con `.bg-gradient-primary` en el propio sidebar, asi que hace falta la
   misma artilleria para que manden los tokens. El sidebar es VERDE MONTANA en
   los dos temas: el gradiente de marca es de la accion, no del cromo.
   -------------------------------------------------------------------------- */
#wrapper #content-wrapper{ background-color: transparent; }
.sidebar.bg-gradient-primary{
    background-image: var(--erp-chrome) !important;
    background-color: var(--erp-chrome-solid) !important;
}

/* Cebra de las tablas en tono de tinta (verde), no el negro de Bootstrap: sobre
   el papel crema un gris frio se nota. */
.table-striped tbody tr:nth-of-type(odd){ background-color: rgba(var(--erp-ink-rgb), 0.04); }

/* En oscuro, la arcilla plena sobre el verde apenas se recorta: un filo claro
   le devuelve el borde al boton (WCAG 1.4.11 pide 3:1 contra el fondo). */
[data-theme="dark"] .btn-primary,
[data-theme="dark"] .app-primary-btn,
[data-theme="dark"] .btn-create,
[data-theme="dark"] .doc-save-btn{ border: 1px solid var(--erp-primary-soft); }
