/* ============ Identidad corporativa GIA Group ============
   Los colores son personalizables desde el panel 🎨 del navbar:
   --gia-primario / --gia-acento se fijan por JS (components/tema.py).
   Por defecto: azul logo #3A67A7, azul web #0578B0.                */

:root {
    /* Marca (las fija en runtime components/tema.py; NO borrar) */
    --gia-primario: #3A67A7;
    --gia-acento: #0578B0;

    /* Marca derivada */
    --brand-ink: var(--gia-primario);   /* texto/enlace/nav activo sobre claro */
    --brand-tint: color-mix(in srgb, var(--gia-primario) 12%, transparent);
    --brand-hover: color-mix(in srgb, var(--gia-primario) 80%, black);

    /* Superficies */
    --surface-0: #FFFFFF;
    --surface-1: #F5F6F8;
    --surface-2: #FFFFFF;
    --surface-nav: #FFFFFF;

    /* Texto */
    --text-strong: #2B2B2A;
    --text: #4B4B4A;
    --text-muted: #767676;   /* AA sobre blanco (>=4.5:1) */
    --text-on-brand: #FFFFFF;

    /* Borde / sombra / radio */
    --border: #E5E5E5;
    --border-strong: #D0D3D9;
    --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.08);
    --shadow-md: 0 2px 10px rgba(0, 0, 0, 0.10);
    --radius-sm: 6px;
    --radius: 10px;
    --radius-lg: 14px;

    /* Espaciado (escala 4px) */
    --sp-1: 0.25rem;
    --sp-2: 0.5rem;
    --sp-3: 0.75rem;
    --sp-4: 1rem;
    --sp-5: 1.5rem;
    --sp-6: 2rem;

    /* Layout del shell */
    --nav-w: 248px;
    --nav-w-rail: 72px;
    --topbar-h: 56px;
    --filters-w: 280px;

    /* Foco accesible */
    --focus-ring: 0 0 0 3px color-mix(in srgb, var(--gia-acento) 45%, transparent);

    /* Estado (deltas, avisos): reservados, nunca como color de serie */
    --success: #2E7D32;
    --danger: #C62828;

    /* Rojo de RELLENO con texto blanco encima (badges). No es --danger: ese
       se aclara en oscuro para leer como tinta sobre superficie oscura, y un
       relleno claro con texto blanco no pasa contraste. Este no cambia. */
    --danger-solid: #C62828;

    /* Colores de los iconos de stat-card (la "cN" de ui.stat_card): identidad
       decorativa, el dato va siempre en tinta de texto. Tonos tomados de la
       paleta de series validada de components/charts.py. El ambar es el tono
       oscuro (#C98500) porque el claro no aguanta un icono blanco encima. */
    --stat-c1: var(--gia-primario);
    --stat-c2: #1BAF7A;
    --stat-c3: #008300;
    --stat-c4: #4A3AA7;
    --stat-c5: #E34948;
    --stat-c6: #EB6834;
    --stat-c7: #C98500;
    --stat-c8: var(--gia-acento);
}

[data-bs-theme="dark"] {
    --surface-0: #16191d;
    --surface-1: #1c2126;
    --surface-2: #22272e;
    --surface-nav: #1a1f24;

    --text-strong: #F1F3F5;
    --text: #dee2e6;
    --text-muted: #A9B1BA;
    --text-on-brand: #FFFFFF;

    --border: #343a40;
    --border-strong: #495057;
    --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.4);
    --shadow-md: 0 4px 14px rgba(0, 0, 0, 0.5);

    /* Marca aclarada: #3A67A7/#0578B0 no pasan contraste sobre superficie oscura */
    --brand-ink: color-mix(in srgb, var(--gia-primario) 55%, white);
    --brand-tint: color-mix(in srgb, var(--gia-primario) 22%, transparent);

    --success: #6FCF7F;
    --danger: #F28B82;
}

/* ============ Theming de los dcc de Dash 4 ============
   Dash 4 dibuja Dropdown/DatePicker/Checklist/Input con sus propios tokens
   --Dash-* (los define en <style> inyectados ANTES de este fichero, asi que
   estas redefiniciones ganan por orden de aparicion). Un solo bloque cubre
   claro y oscuro: los var() se resuelven contra el valor vigente del token.
   Imprescindible ademas porque el menu del Dropdown y el calendario viven
   FUERA del nodo con className (.filtro-dd): ningun selector descendiente
   los alcanza, las variables heredadas si. */
:root {
    --Dash-Fill-Interactive-Strong: var(--gia-primario);
    --Dash-Fill-Interactive-Weak: var(--brand-tint);
    --Dash-Fill-Inverse-Strong: var(--surface-2);
    --Dash-Fill-Primary-Hover: var(--brand-tint);
    --Dash-Fill-Primary-Active: color-mix(in srgb, var(--gia-primario) 20%, transparent);
    --Dash-Fill-Disabled: var(--surface-1);
    --Dash-Text-Primary: var(--text);
    --Dash-Text-Strong: var(--text-strong);
    --Dash-Text-Weak: var(--text-muted);
    --Dash-Text-Disabled: var(--text-muted);
    --Dash-Stroke-Strong: var(--border-strong);
    --Dash-Stroke-Weak: var(--border);
}

body {
    font-family: "Open Sans", "Segoe UI", Arial, sans-serif;
}

[data-bs-theme="light"] body,
body {
    color: var(--text);
}

/* ============ Shell del panel admin ============ */
.app-shell {
    display: flex;
    min-height: 100vh;
    background-color: var(--surface-1);
}

.app-main {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.app-body {
    display: flex;
    flex: 1 1 auto;
    align-items: flex-start;
    min-height: 0;
}

.content-col {
    flex: 1 1 auto;
    min-width: 0;
    padding: var(--sp-5);
    background-color: var(--surface-1);
    overflow-x: hidden;
}

.filters-col {
    flex: 0 0 var(--filters-w);
    max-width: var(--filters-w);
}

/* En ESCRITORIO scrollea el contenido, no la ventana: asi el panel de filtros
   se queda quieto mientras se baja por los graficos, que es como se comporta
   Power BI.

   El `position: sticky` que .sidebar ya tenia no servia de nada, por dos
   motivos independientes:
     1. Su contenedor (.filters-col) mide lo mismo que el —con
        `align-items: flex-start` en .app-body no sobra ni un pixel—, y un
        sticky sin hueco en su contenedor no se mueve nunca.
     2. Aunque lo hubiera, cualquier cosa clavada a `top` acaba POR DEBAJO de
        la cinta de chips, que tambien es sticky, es opaca y mide lo que mide
        (envuelve a dos lineas cuando hay muchos filtros activos). No hay
        numero que poner ahi que sea correcto siempre.
   Con el shell a la altura exacta de la ventana y el scroll dentro de cada
   columna, la altura de la cinta NO aparece en ningun calc(): la reparte el
   propio flex. Y de paso la topbar y la cinta quedan fijas de verdad.
   Solo escritorio: en movil las dos columnas se apilan (ver el @media de
   max-width: 991.98px) y ahi el scroll de la pagina es el correcto. */
@media (min-width: 992px) {
    .app-shell {
        height: 100vh;
        overflow: hidden;
    }

    /* min-height: 0 en los dos contenedores intermedios NO es opcional: por
       defecto un hijo flex no puede encogerse por debajo de su contenido, asi
       que .app-body se desbordaria hacia abajo -devolviendo el scroll a la
       ventana- en vez de scrollear por dentro. */
    .app-main {
        min-height: 0;
    }

    .app-body {
        min-height: 0;
        overflow: hidden;
    }

    .filters-col,
    .content-col {
        max-height: 100%;
        overflow-y: auto;
    }

    /* El sticky ya lo hace el contenedor, y aqui estorbaria: dentro de su
       propio scrollport, un `top: var(--topbar-h)` deja al bajar un hueco en
       blanco de la altura de la topbar. */
    .filters-col .sidebar {
        position: static;
        max-height: none;
    }
}

/* ---- Navegacion lateral ---- */
.nav-sidebar {
    flex: 0 0 var(--nav-w);
    width: var(--nav-w);
    flex-direction: column;
    background-color: var(--surface-nav);
    border-right: 1px solid var(--border);
    align-self: flex-start;
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
    overflow-x: hidden;
}

.nav-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-2);
    height: var(--topbar-h);
    padding: 0 var(--sp-3);
    border-bottom: 1px solid var(--border);
    flex: 0 0 auto;
}

.nav-brand {
    display: inline-flex;
    align-items: center;
    overflow: hidden;
}

.nav-logo {
    height: 30px;
    width: auto;
}

[data-bs-theme="dark"] .nav-logo {
    background-color: #f2f2f2;
    border-radius: 4px;
    padding: 2px 6px;
}

.btn-nav-collapse {
    color: var(--text-muted) !important;
    padding: var(--sp-1) var(--sp-2);
    flex: 0 0 auto;
    text-decoration: none;
}

.nav-list {
    list-style: none;
    margin: 0;
    padding: var(--sp-3) var(--sp-2);
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.nav-item {
    list-style: none;
}

.nav-item-link {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-3);
    min-height: 44px;
    border-radius: var(--radius-sm);
    color: var(--text) !important;
    font-weight: 600;
    white-space: nowrap;
    text-decoration: none !important;
    -webkit-user-select: none;
    user-select: none;
}

.nav-item-link:hover,
.nav-item-link:focus-visible {
    background-color: var(--brand-tint);
    color: var(--brand-ink) !important;
}

/* Boton "Detalle" (abre el listado en modal): mismo aspecto que un enlace
   del nav, reseteando el estilo nativo de <button>. */
button.nav-detalle-btn {
    background: none;
    border: 0;
    width: 100%;
    text-align: left;
    font: inherit;
    cursor: pointer;
}

/* Tras hacer clic con el raton el enlace no debe quedarse "seleccionado" */
.nav-item-link:focus:not(:focus-visible):not(.active),
.nav-group-summary:focus:not(:focus-visible) {
    background-color: transparent;
    color: var(--text) !important;
}

/* Item activo: indicador sutil (borde + tinta), no pildora rellena */
.nav-item-link.active {
    background-color: color-mix(in srgb, var(--gia-primario) 7%, transparent);
    border-left: 3px solid var(--gia-primario);
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
    color: var(--brand-ink) !important;
}

.nav-item-icon {
    font-size: 1.1rem;
    flex: 0 0 auto;
    width: 1.25em;
    text-align: center;
}

/* Grupos desplegables del nav (<details>/<summary>) */
.nav-group {
    list-style: none;
}

.nav-group-summary {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-3);
    min-height: 44px;
    border-radius: var(--radius-sm);
    color: var(--text) !important;
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
    list-style: none;
    -webkit-user-select: none;
    user-select: none;
}

.nav-group-summary::-webkit-details-marker {
    display: none;
}

.nav-group-summary::marker {
    content: "";
}

.nav-group-summary:hover,
.nav-group-summary:focus-visible {
    background-color: var(--brand-tint);
    color: var(--brand-ink) !important;
}

.nav-group-chevron {
    margin-left: auto;
    font-size: 0.75rem;
    transition: transform 0.15s ease;
}

.nav-group[open] > .nav-group-summary .nav-group-chevron {
    transform: rotate(90deg);
}

.nav-sublist {
    list-style: none;
    margin: 2px 0 var(--sp-2);
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.nav-sub-link.nav-item-link {
    padding-left: calc(var(--sp-3) + 1.25em + var(--sp-3));
    font-weight: 500;
}

/* Rail colapsado: grupos como iconos, sin chevron ni sangria */
.app-shell[data-nav-collapsed="1"] .nav-group-chevron {
    display: none;
}

.app-shell[data-nav-collapsed="1"] .nav-group-summary {
    justify-content: center;
    gap: 0;
    padding-left: 0;
    padding-right: 0;
}

.app-shell[data-nav-collapsed="1"] .nav-sub-link.nav-item-link {
    padding-left: 0;
}

/* Rail colapsado (solo escritorio) */
.app-shell[data-nav-collapsed="1"] .nav-sidebar {
    flex-basis: var(--nav-w-rail);
    width: var(--nav-w-rail);
}

.app-shell[data-nav-collapsed="1"] .nav-brand {
    display: none;
}

/* Rail: oculta la etiqueta visualmente pero la mantiene para lectores de
   pantalla (nombre accesible del enlace); el tooltip lo da el title. */
.app-shell[data-nav-collapsed="1"] .nav-item-label {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.app-shell[data-nav-collapsed="1"] .nav-header {
    justify-content: center;
}

.app-shell[data-nav-collapsed="1"] .nav-item-link {
    justify-content: center;
    gap: 0;
    padding-left: 0;
    padding-right: 0;
}

.app-shell[data-nav-collapsed="1"] .btn-nav-collapse i {
    transform: rotate(180deg);
    display: inline-block;
}

/* ---- Topbar ---- */
.topbar {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    height: var(--topbar-h);
    padding: 0 var(--sp-4);
    background-color: var(--surface-0);
    border-bottom: 1px solid var(--border);
    box-shadow: var(--shadow-sm);
    position: sticky;
    top: 0;
    z-index: 1020;
}

.topbar-title {
    font-weight: 700;
    font-size: 1.05rem;
    color: var(--text-strong);
    /* Puede encogerse y truncar para no empujar las acciones fuera de pantalla */
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.topbar-brand img {
    display: block;
}

[data-bs-theme="dark"] .topbar-brand img {
    background-color: #f2f2f2;
    border-radius: 4px;
    padding: 2px 6px;
}

.topbar-actions {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    margin-left: auto;
}

.topbar-user {
    color: var(--text-muted);
    font-size: 0.9rem;
    display: inline-flex;
    align-items: center;
}

/* La identidad es un enlace a /mi-cuenta: sin subrayado y sin color de enlace. */
a.topbar-user {
    text-decoration: none;
}

a.topbar-user:hover,
a.topbar-user:focus-visible {
    color: var(--brand-ink);
}

.topbar-logout {
    color: var(--brand-ink) !important;
    text-decoration: none;
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    padding: var(--sp-2) var(--sp-3);
    min-height: 44px;
    border-radius: var(--radius-sm);
}

.topbar-logout:hover {
    background-color: var(--brand-tint);
}

/* Vista previa de administrador ("Ver como", components/navbar.py). El rojo es
   deliberado: mientras esta puesto, lo que se ve NO son tus permisos. */
.vercomo-dd {
    min-width: 200px;
}

.vercomo-cinta {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    padding: var(--sp-1) var(--sp-3);
    border: 1px solid var(--danger);
    border-radius: var(--radius-sm);
    background-color: color-mix(in srgb, var(--danger) 12%, transparent);
    color: var(--text-strong);
    font-size: 0.85rem;
    white-space: nowrap;
}

.vercomo-salir {
    color: var(--danger) !important;
    text-decoration: none;
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    padding: var(--sp-1) var(--sp-2);
    min-height: 32px;
    border-radius: var(--radius-sm);
}

.vercomo-salir:hover,
.vercomo-salir:focus-visible {
    background-color: color-mix(in srgb, var(--danger) 18%, transparent);
}

/* Marca de agua en toda la barra: que no se pueda olvidar (app.py fija el
   atributo en #app-shell desde serve_layout). */
.app-shell[data-vercomo="1"] .topbar {
    box-shadow: inset 0 -3px 0 var(--danger);
}

.btn-nav-toggle {
    color: var(--text) !important;
    font-size: 1.3rem;
    padding: var(--sp-1) var(--sp-2);
    text-decoration: none;
}

/* Enlace de salto al contenido (accesibilidad) */
.skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 2000;
    padding: var(--sp-2) var(--sp-4);
    background: var(--gia-primario);
    color: var(--text-on-brand) !important;
    border-radius: 0 0 var(--radius-sm) 0;
}

.skip-link:focus {
    left: 0;
}

.btn-tema {
    border: none;
    font-size: 1rem;
}

/* ---- Visibilidad por seccion (data-seccion lo fija el clientside de ruta) ----
   Panel de filtros: en las secciones que consumen el Store global-filters
   (principal, albaranes, clientes, canales, articulos) y en SAT (que muestra
   en el mismo panel su bloque propio .solo-sat, ver abajo). Catalogo y
   almacenes llevan barra propia y no leen ese Store, por eso no lo muestran.
   content-col (flex:1) ocupa el ancho sobrante cuando el panel no esta. */
.filters-col {
    display: none;
}

body[data-seccion="principal"] .filters-col,
body[data-seccion="albaranes"] .filters-col,
body[data-seccion="clientes"] .filters-col,
body[data-seccion="canales"] .filters-col,
body[data-seccion="articulos"] .filters-col,
body[data-seccion="sat"] .filters-col {
    display: block;
}

/* Ocultado manual del panel de filtros (boton embudo / boton del panel) */
.app-shell[data-filters-hidden="1"] .filters-col {
    display: none !important;
}

/* Boton embudo (mostrar/ocultar filtros): donde hay panel lateral */
.btn-filtros-toggle {
    display: none;
    color: var(--text) !important;
    font-size: 1.15rem;
    padding: var(--sp-1) var(--sp-2);
    text-decoration: none;
}

body[data-seccion="principal"] .btn-filtros-toggle,
body[data-seccion="albaranes"] .btn-filtros-toggle,
body[data-seccion="clientes"] .btn-filtros-toggle,
body[data-seccion="canales"] .btn-filtros-toggle,
body[data-seccion="articulos"] .btn-filtros-toggle,
body[data-seccion="sat"] .btn-filtros-toggle {
    display: inline-flex;
    align-items: center;
}

/* Botones del listado en modal (Excel + reset de filtros): en toda seccion
   con listado (lista propia, NO la del embudo: aqui entran tambien las
   secciones con barra de filtros propia). Ocultos quedan datos, mi-cuenta
   y "otro" (login, 404). El d-none del reset lo alterna un callback segun
   haya o no filtros activos en la seccion. */
.btn-listado-toggle,
.btn-listado-reset {
    display: none;
    color: var(--text) !important;
    font-size: 1.15rem;
    padding: var(--sp-1) var(--sp-2);
    text-decoration: none;
    position: relative;
}

body[data-seccion="principal"] .btn-listado-toggle,
body[data-seccion="albaranes"] .btn-listado-toggle,
body[data-seccion="clientes"] .btn-listado-toggle,
body[data-seccion="canales"] .btn-listado-toggle,
body[data-seccion="articulos"] .btn-listado-toggle,
body[data-seccion="sat"] .btn-listado-toggle,
body[data-seccion="compras"] .btn-listado-toggle,
body[data-seccion="almacenes"] .btn-listado-toggle,
body[data-seccion="visitas"] .btn-listado-toggle,
body[data-seccion="transitarios"] .btn-listado-toggle,
body[data-seccion="catalogo"] .btn-listado-toggle,
body[data-seccion="litigios"] .btn-listado-toggle,
body[data-seccion="presupuestos"] .btn-listado-toggle,
body[data-seccion="logistica"] .btn-listado-toggle,
body[data-seccion="fgas"] .btn-listado-toggle,
body[data-seccion="principal"] .btn-listado-reset,
body[data-seccion="albaranes"] .btn-listado-reset,
body[data-seccion="clientes"] .btn-listado-reset,
body[data-seccion="canales"] .btn-listado-reset,
body[data-seccion="articulos"] .btn-listado-reset,
body[data-seccion="sat"] .btn-listado-reset,
body[data-seccion="compras"] .btn-listado-reset,
body[data-seccion="almacenes"] .btn-listado-reset,
body[data-seccion="visitas"] .btn-listado-reset,
body[data-seccion="transitarios"] .btn-listado-reset,
body[data-seccion="catalogo"] .btn-listado-reset,
body[data-seccion="litigios"] .btn-listado-reset,
body[data-seccion="presupuestos"] .btn-listado-reset,
body[data-seccion="logistica"] .btn-listado-reset,
body[data-seccion="fgas"] .btn-listado-reset {
    display: inline-flex;
    align-items: center;
}

/* Badge del boton Excel: numero de filtros del listado activos */
.listado-badge {
    position: absolute;
    top: 0;
    right: 0;
    font-size: 0.62rem;
    line-height: 1;
    padding: 2px 4px;
    border-radius: 8px;
    background: var(--danger-solid);
    color: var(--text-on-brand);
}

/* Modal del listado: altura de viewport EXPLICITA en el contenedor del grid.
   Nada de cadenas height:100% a traves del wrapper de dcc.Loading: el
   porcentaje contra un flex sin altura definida colapsa a ~0 y el modal se
   ve en blanco (verificado midiendo el DOM). 110px = cabecera del modal
   (~67) + padding del body (24) + margen del aviso de export. */
.modal-listado .modal-body {
    padding: var(--sp-3);
    overflow: hidden;
}

.modal-listado .listado-grid-wrap {
    height: calc(100vh - 110px);
    min-height: 240px;
}

/* dcc.Loading en Dash 4 interpone DOS divs (en Dash 3 era uno): ambos
   eslabones necesitan el 100% para que el grid no colapse. */
.modal-listado .listado-grid-wrap > div,
.modal-listado .listado-grid-wrap > div > div {
    height: 100%;
}

.modal-listado-objeto {
    margin-left: var(--sp-3);
    font-size: 0.8rem;
    font-weight: 400;
    color: var(--text-muted);
}

.btn-filtros-collapse {
    color: var(--text-muted) !important;
    text-decoration: none;
}

/* ---- Barra de chips de filtros rapidos ---- */
.topfilters {
    display: none;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-1) var(--sp-3);
    padding: var(--sp-2) var(--sp-4);
    background-color: var(--surface-0);
    border-bottom: 1px solid var(--border);
    position: sticky;
    top: var(--topbar-h);
    z-index: 1010;
}

body[data-seccion="principal"] .topfilters,
body[data-seccion="clientes"] .topfilters,
body[data-seccion="canales"] .topfilters,
body[data-seccion="albaranes"] .topfilters,
body[data-seccion="articulos"] .topfilters,
body[data-seccion="sat"] .topfilters {
    display: flex;
}

/* Contenido por seccion dentro del panel y de la barra: el informe SAT
   comparte panel/chips con el resto, pero muestra sus propios controles
   (.solo-sat) y oculta los del informe de ventas (.solo-global). */
.topfilters .solo-sat,
.sidebar .solo-sat {
    display: none;
}

body[data-seccion="sat"] .topfilters .topf-grupo.solo-sat {
    display: flex;
}

body[data-seccion="sat"] .topfilters .chip.solo-sat {
    display: inline-block;
}

body[data-seccion="sat"] .sidebar .solo-sat {
    display: block;
}

body[data-seccion="sat"] .topfilters .solo-global,
body[data-seccion="sat"] .sidebar .solo-global {
    display: none;
}

.topf-grupo {
    display: flex;
    align-items: center;
    gap: var(--sp-1);
    flex-wrap: wrap;
}

.topf-label {
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-size: 0.72rem;
    font-weight: 700;
    color: var(--text-muted);
    margin-right: var(--sp-1);
}

.chip {
    border-radius: 999px;
    border: 1px solid var(--border);
    background-color: var(--surface-2);
    color: var(--text);
    font-size: 0.78rem;
    font-weight: 600;
    padding: 0.2rem 0.7rem;
    min-height: 30px;
    line-height: 1.1;
    cursor: pointer;
}

.chip:hover {
    border-color: var(--gia-primario);
    color: var(--brand-ink);
}

.chip.active,
.chip.active:hover {
    background-color: var(--gia-primario);
    border-color: var(--gia-primario);
    color: var(--text-on-brand);
}

.chip:focus:not(:focus-visible) {
    outline: none;
}

/* Limpiar filtros: alineado a la derecha, tono discreto */
.chip-limpiar {
    margin-left: auto;
    color: var(--text-muted);
    border-style: dashed;
}

.chip-limpiar:hover {
    color: var(--danger);
    border-color: var(--danger);
}

/* ---- Botones primarios (Aplicar filtros, exportar...) ---- */
.btn-primary {
    background-color: var(--gia-primario) !important;
    border-color: var(--gia-primario) !important;
}

.btn-primary:hover,
.btn-primary:active,
.btn-primary:focus {
    background-color: color-mix(in srgb, var(--gia-primario) 80%, black) !important;
    border-color: color-mix(in srgb, var(--gia-primario) 80%, black) !important;
}

.btn-link {
    color: var(--brand-ink) !important;
}

a {
    color: var(--brand-ink);
}

/* ---- Sidebar de filtros ---- */
.sidebar {
    background-color: var(--surface-1);
    border-right: 1px solid var(--border);
    font-size: 0.85rem;
    position: sticky;
    top: var(--topbar-h);
    max-height: calc(100vh - var(--topbar-h));
    overflow-y: auto;
    /* El sticky crea un contexto de apilamiento: sin z-index propio, los
       popovers Radix de los dcc (calendario del DatePickerRange, 524px)
       que sobresalen del panel quedan DEBAJO de las tarjetas con graficos
       por orden de documento. Con z-index bajo basta (topbar en 1020). */
    z-index: 3;
}

.sidebar .form-check-input:checked {
    background-color: var(--gia-primario);
    border-color: var(--gia-primario);
}

/* DatePickerRange (Dash 4): por defecto el wrapper es display:block con los
   inputs en flujo inline y ancho fijado como estilo inline por un medidor de
   texto (que ademas mide 0 si el bloque se monta oculto, caso de
   f-bloque-fechas). Con otra fuente o zoom el flujo inline PARTE las dos
   fechas en dos lineas y la caja se hincha. Flex nowrap con reparto
   equitativo (como el CSS de react-dates en Dash 3): no puede envolver a
   ningun tamano de fuente. Los !important ganan a los estilos inline del
   componente. Colores via tokens --Dash-*. */
.sidebar .dash-datepicker-input-wrapper {
    display: flex;
    align-items: center;
    flex-wrap: nowrap;
    gap: 2px;
    width: 100%;
    box-sizing: border-box;
    padding: 0 8px;
}

.sidebar .dash-datepicker-input-wrapper > div {
    flex: 1 1 0;
    min-width: 0;
}

.sidebar .dash-datepicker-input-wrapper > svg {
    flex: 0 0 auto;
}

.sidebar .dash-datepicker-input {
    font-size: 0.8rem;
    text-align: center;
    width: 100% !important;
    box-sizing: border-box !important;
    min-width: 0;
    padding: 4px 2px;
}

/* El popover del calendario a veces abre con la caja pintada mas estrecha
   que los dos meses (estado transitorio de Radix) y el segundo mes queda
   transparente sobre la pagina: fondo opaco en el propio calendario. */
.dash-datepicker-calendar-wrapper {
    background: var(--surface-2);
}

.btn-atajos .btn {
    font-size: 0.78rem;
}

/* Dropdown (Dash 4): el className cae en el propio boton disparador, la
   fuente compacta se hereda a los spans interiores. El menu de opciones
   cuelga de un wrapper hermano (fuera de .filtro-dd): sus colores llegan
   por los tokens --Dash-* del bloque de identidad, tambien en oscuro. */
.filtro-dd {
    font-size: 0.8rem;
}

/* Desplegable de mes en la barra de filtros: ancho compacto y sin desbordar */
.topf-dd-mes {
    min-width: 130px;
}

/* ---- Tarjetas KPI ---- */
.kpi-card {
    border: 1px solid var(--border);
    border-top: 3px solid var(--gia-primario);
    box-shadow: var(--shadow-sm);
}

.kpi-titulo {
    font-weight: 600;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--text-muted);
}

/* ============ Accesibilidad ============ */
/* Foco visible por teclado (no habia ninguna regla propia hasta ahora) */
:focus-visible {
    outline: 2px solid transparent;
    outline-offset: 2px;
    box-shadow: var(--focus-ring);
}

/* No mostrar el anillo con foco de raton/tactil */
:focus:not(:focus-visible) {
    outline: none;
    box-shadow: none;
}

/* Targets tactiles minimos (WCAG 2.5.5) */
.btn-tema,
.btn-nav-toggle {
    min-width: 44px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* Respeta la preferencia de movimiento reducido */
@media (prefers-reduced-motion: no-preference) {
    .nav-sidebar {
        transition: flex-basis 0.18s ease, width 0.18s ease;
    }

    .nav-item-link,
    .topbar-logout,
    .btn-primary {
        transition: background-color 0.15s ease, color 0.15s ease;
    }
}

/* ============ Responsive ============ */
/* <992px: la navegacion va en el drawer (d-lg-flex/d-lg-none lo gestionan).
   Los filtros pasan a apilarse sobre el contenido, con scroll propio para no
   empujarlo fuera de la pantalla. */
@media (max-width: 991.98px) {
    .app-body {
        flex-direction: column;
        /* En columna el eje transversal es el ancho: sin stretch los hijos se
           encogen/crecen a su contenido y content-col se desborda del viewport
           (causa del scroll horizontal en movil). */
        align-items: stretch;
    }

    .content-col {
        width: 100%;
        padding: var(--sp-3);
    }

    .filters-col {
        flex: 0 0 auto;
        max-width: none;
        width: 100%;
    }

    /* Defecto en movil/tablet: apilado sobre el contenido, el panel se comia
       la primera pantalla completa y el usuario aterrizaba en 366px de
       filtros sin ver un solo dato. "auto" = todavia no ha decidido nada
       (ver el tri-estado de app.py); el embudo sigue abriendolo y su
       eleccion persiste en localStorage. */
    .app-shell[data-filters-hidden="auto"] .filters-col {
        display: none !important;
    }

    .filters-col .sidebar {
        position: static;
        /* dvh y no vh: en movil vh cuenta la barra de URL retraida, asi que
           45vh reservaba mas alto del que hay de verdad. El vh queda como
           respaldo para navegadores sin dvh (sin el, la declaracion se
           descarta y el panel crece sin tope). */
        max-height: 45vh;
        max-height: 60dvh;
        overflow-y: auto;
        border-right: none;
        border-bottom: 1px solid var(--border);
    }

    /* Atajos de fecha: targets mas comodos al tacto */
    .btn-atajos .btn {
        min-height: 40px;
    }

    /* Drawer de navegacion: ancho acotado para que el backdrop quede visible y
       se lea como una capa por encima (no una pagina nueva a pantalla completa). */
    .nav-drawer.offcanvas {
        --bs-offcanvas-width: min(320px, 85vw);
    }
}

/* Tablet/movil (nav en drawer): compactar la topbar para que las acciones
   quepan sin desbordarse. */
@media (max-width: 767.98px) {
    .topbar {
        padding: 0 var(--sp-3);
        gap: var(--sp-2);
    }

    /* La identidad del usuario ya aparece en el pie del drawer: en la topbar
       movil solo estorba y ocupa espacio. */
    .topbar-user {
        display: none;
    }

    /* Logout: solo el icono (el texto "Salir" se queda para lectores de pantalla) */
    .topbar-logout .topbar-logout-label {
        position: absolute;
        width: 1px;
        height: 1px;
        padding: 0;
        margin: -1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
        white-space: nowrap;
        border: 0;
    }

    .topbar-logout .bi {
        margin-right: 0 !important;
    }
}

@media (max-width: 575.98px) {
    /* En pantallas muy estrechas el logo de la marca cede su sitio al titulo */
    .topbar-brand.d-lg-none {
        display: none !important;
    }
}

/* ---- Barra de chips (topfilters) en movil ---- */
/* Apilada en filas por grupo con scroll horizontal propio: evita que envuelva
   en un bloque alto y pegajoso que se coma la pantalla del telefono. */
@media (max-width: 991.98px) {
    .topfilters {
        position: static;
        flex-direction: column;
        /* nowrap: en columna, wrap crearia multi-columnas y estiraria los
           grupos a su contenido (desbordando la pagina). */
        flex-wrap: nowrap;
        align-items: stretch;
        gap: var(--sp-2);
        padding: var(--sp-2) var(--sp-3);
    }

    .topf-grupo {
        flex-wrap: nowrap;
        /* min-width:0 permite que el grupo se encoja al ancho del contenedor;
           sin el, min-width:auto lo estira a su contenido y desborda la pagina. */
        min-width: 0;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: thin;
        padding-bottom: 3px;
    }

    .topf-label {
        position: sticky;
        left: 0;
        flex: 0 0 auto;
        background-color: var(--surface-0);
        padding-right: var(--sp-2);
        z-index: 1;
    }

    .topf-grupo .chip {
        flex: 0 0 auto;
    }

    .chip-limpiar {
        margin-left: 0;
        align-self: flex-start;
    }
}

/* ============ Interior de paginas ============ */
.page-header {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--sp-4);
    margin-bottom: var(--sp-4);
    flex-wrap: wrap;
}

.page-header-titulo {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--text-strong);
    margin: 0;
}

.page-header-subtitulo {
    color: var(--text-muted);
    margin: 2px 0 0;
    font-size: 0.9rem;
}

.page-header-acciones {
    display: flex;
    gap: var(--sp-2);
    align-items: center;
    flex-wrap: wrap;
}

.section-header {
    font-size: 1rem;
    font-weight: 700;
    color: var(--text-strong);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    margin: var(--sp-2) 0 var(--sp-3);
}

/* Tarjeta unificada del panel */
.gia-card {
    background-color: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    padding: var(--sp-4);
    height: 100%;
}

.gia-card-cabecera {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-3);
    margin-bottom: var(--sp-2);
}

.gia-card-titulo {
    font-size: 0.95rem;
    font-weight: 700;
    color: var(--text-strong);
    margin: 0;
}

.gia-card-acciones {
    display: flex;
    gap: var(--sp-2);
    align-items: center;
    flex-wrap: wrap;
}

/* Cuerpo de la tarjeta: existe como punto de engarce del body_class de
   ui.card (lo emiten las 232 tarjetas y no tenia ninguna regla). min-width:0
   deja que un hijo ancho (rejilla, tabla, grid) se encoja en vez de estirar
   la tarjeta y desbordar la pagina. */
.gia-card-cuerpo {
    min-width: 0;
}

/* Tarjetas dbc genericas (menu, login, KPI) sobre la nueva superficie */
.card {
    background-color: var(--surface-2);
    border-color: var(--border);
    border-radius: var(--radius);
}

/* ---- AG Grid: variables ancladas a los tokens (adaptan claro/oscuro) ----
   Se fija todo el set sobre ambos temas para no depender de que dash-ag-grid
   cargue las variables de "alpine-dark" (no lo hace de forma fiable). */
.ag-theme-alpine,
.ag-theme-alpine-dark {
    --ag-font-family: "Open Sans", "Segoe UI", Arial, sans-serif;
    --ag-background-color: var(--surface-2);
    --ag-foreground-color: var(--text);
    --ag-data-color: var(--text);
    --ag-secondary-foreground-color: var(--text-muted);
    --ag-header-background-color: var(--surface-1);
    --ag-header-foreground-color: var(--text-strong);
    --ag-odd-row-background-color: var(--surface-1);
    --ag-row-hover-color: var(--brand-tint);
    --ag-selected-row-background-color: var(--brand-tint);
    --ag-border-color: var(--border);
    --ag-row-border-color: var(--border);
    --ag-input-border-color: var(--border);
    --ag-control-panel-background-color: var(--surface-1);
    --ag-subheader-background-color: var(--surface-1);
    --ag-wrapper-border-radius: var(--radius);
    --ag-header-column-separator-display: none;
}

/* ---- Stat cards (datos rapidos del dashboard y fichas) ---- */
.stat-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: var(--sp-3);
}

.stat-grid-4 {
    /* 190 y no 170: con 170 la pista se queda en ~145px utiles en tablet, que
       es donde los importes largos se salian. Una fila mas de alto a cambio
       de numeros legibles. */
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}

.stat-grid-3 {
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
}

.stat-card {
    background-color: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    padding: var(--sp-4);
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
    /* Contenedor de consulta: lo que hace que el cuerpo de .stat-valor se
       ajuste al ancho de ESTA tarjeta y no al del viewport (los breakpoints
       no ven cuantas columnas ha decidido el auto-fit de la rejilla). */
    container-type: inline-size;
    /* Cinturon: con el clamp de .stat-valor no deberia activarse nunca, pero
       un valor patologico no debe poder pintar sobre la tarjeta vecina. */
    overflow: clip;
}

/* KPI clicable (ui.stat_card con id): filtra el resto de la pagina. Resetea
   el estilo nativo de <button> para que sea indistinguible de la tarjeta
   normal, y marca con el color de marca la que esta aplicada. */
.stat-card-btn {
    font: inherit;
    color: inherit;
    text-align: left;
    cursor: pointer;
    width: 100%;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.stat-card-btn:hover {
    border-color: var(--brand-ink);
    box-shadow: var(--shadow-md, var(--shadow-sm));
}

.stat-card-btn:focus-visible {
    outline: 2px solid var(--brand-ink);
    outline-offset: 2px;
}

.stat-card-activa {
    border-color: var(--brand-ink);
    background-color: var(--brand-tint);
}

.stat-icono {
    width: 36px;
    height: 36px;
    border-radius: 999px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1rem;
    color: var(--text-on-brand);
    margin-bottom: 2px;
}

/* Colores de icono: identidad decorativa (el dato va en tinta de texto) */
.stat-c1 { background-color: var(--stat-c1); }
.stat-c2 { background-color: var(--stat-c2); }
.stat-c3 { background-color: var(--stat-c3); }
.stat-c4 { background-color: var(--stat-c4); }
.stat-c5 { background-color: var(--stat-c5); }
.stat-c6 { background-color: var(--stat-c6); }
.stat-c7 { background-color: var(--stat-c7); }
.stat-c8 { background-color: var(--stat-c8); }

.stat-titulo {
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.stat-valor {
    /* Cuerpo fluido con el ancho de la TARJETA (cqi), no del viewport: en las
       rejillas de 4-8 columnas la pista baja a ~150px utiles y un importe de
       9 cifras a 1.45rem mide mas que eso. Sin esto el texto (nowrap, y la
       tarjeta no tenia overflow) se pintaba ENCIMA de la tarjeta vecina, y el
       overflow-x:hidden de .content-col lo recortaba en silencio: no genera
       scroll horizontal, asi que no lo caza ninguna prueba de scroll.
       Nunca ellipsis en un numero: un importe truncado no es un dato
       incompleto, es un dato falso. Se reduce el cuerpo, no la cifra.
       tabular-nums fija el avance del digito y hace el calculo auditable. */
    font-size: clamp(1.125rem, 7cqi, 1.45rem);
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    color: var(--text-strong);
    line-height: 1.1;
    white-space: nowrap;
}

.stat-pie {
    display: flex;
    align-items: baseline;
    gap: var(--sp-2);
    flex-wrap: wrap;
}

.stat-delta {
    font-size: 0.8rem;
    font-weight: 700;
}

.stat-delta-pos { color: var(--success); }
.stat-delta-neg { color: var(--danger); }

.stat-sub {
    font-size: 0.74rem;
    color: var(--text-muted);
}

/* ---- Barras de progreso "ventas por canal" ---- */
.vc-lista {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    column-gap: var(--sp-6);
    row-gap: var(--sp-3);
}

.vc-cabecera {
    display: flex;
    align-items: baseline;
    gap: var(--sp-2);
    margin-bottom: 4px;
}

.vc-punto {
    width: 10px;
    height: 10px;
    border-radius: 999px;
    flex: 0 0 auto;
    align-self: center;
}

.vc-nombre {
    font-weight: 700;
    font-size: 0.82rem;
    color: var(--text-strong);
    text-transform: uppercase;
    letter-spacing: 0.02em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.vc-valor {
    margin-left: auto;
    font-weight: 700;
    font-size: 0.85rem;
    color: var(--text-strong);
    white-space: nowrap;
}

.vc-pct {
    font-size: 0.78rem;
    color: var(--text-muted);
    min-width: 3.2em;
    text-align: right;
}

.vc-barra {
    height: 8px;
    border-radius: 999px;
    background-color: var(--surface-1);
    border: 1px solid var(--border);
    overflow: hidden;
}

.vc-barra-fill {
    height: 100%;
    border-radius: 999px;
}

/* ---- Accesos del dashboard Principal ---- */
.acceso-link {
    text-decoration: none;
    display: block;
    height: 100%;
}

.acceso-card {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    transition: box-shadow 0.15s ease, transform 0.15s ease, border-color 0.15s ease;
}

.acceso-link:hover .acceso-card {
    border-color: var(--gia-primario);
    box-shadow: var(--shadow-md);
}

.acceso-icono {
    flex: 0 0 auto;
    width: 44px;
    height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius);
    background-color: var(--brand-tint);
    color: var(--brand-ink);
    font-size: 1.3rem;
}

.acceso-titulo {
    font-weight: 700;
    color: var(--text-strong);
}

.acceso-desc {
    font-size: 0.82rem;
    color: var(--text-muted);
}

/* ---- Explorador de clientes ---- */
.cli-buscar {
    width: 100%;
    padding: 0.5rem 0.75rem;
    margin-bottom: var(--sp-3);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background-color: var(--surface-1);
    color: var(--text);
    font-size: 0.9rem;
}

.cli-buscar .dash-input-element {
    flex: 1 1 auto;
    width: 100%;
    padding: 0;
    font-size: inherit;
}

.cli-buscar:focus-within {
    outline: none;
    border-color: var(--gia-primario);
    box-shadow: var(--focus-ring);
}

.cli-lista {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    max-height: calc(100vh - 260px);
    overflow-y: auto;
    padding-right: 2px;
}

.cli-item {
    display: block;
    width: 100%;
    text-align: left;
    background-color: var(--surface-1);
    border: 1px solid var(--border);
    border-left: 3px solid transparent;
    border-radius: var(--radius-sm);
    padding: var(--sp-2) var(--sp-3);
    cursor: pointer;
    color: var(--text);
    text-decoration: none;
}

.cli-item:hover {
    background-color: var(--brand-tint);
    border-left-color: var(--gia-primario);
    color: var(--text);
    text-decoration: none;
}

.cli-item:active {
    transform: translateY(1px);
}

/* Cliente seleccionado (el de la URL ?cif=...) */
.cli-item-activo,
.cli-item-activo:hover {
    background-color: var(--brand-tint);
    border-left-color: var(--gia-primario);
}

.cli-item-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-2);
}

.cli-item-nombre {
    font-weight: 700;
    font-size: 0.85rem;
    color: var(--text-strong);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.cli-item-bot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-2);
    margin-top: 2px;
}

.cli-item-agente {
    font-size: 0.72rem;
    color: var(--text-muted);
}

.cli-dif-pos {
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--success);
}

.cli-dif-neg {
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--danger);
}

.cli-badge {
    flex: 0 0 auto;
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    padding: 2px 8px;
    border-radius: 999px;
    background-color: var(--brand-tint);
    color: var(--brand-ink);
}

/* ---- Pagina Canales ---- */
.canal-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: var(--sp-3);
}

.canal-card {
    background-color: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    padding: var(--sp-4);
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
    cursor: pointer;
    text-align: left;
    min-width: 0;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.canal-card:hover {
    border-color: var(--gia-primario);
    box-shadow: var(--shadow-md);
}

.canal-card.canal-activo {
    border-color: var(--gia-primario);
    box-shadow: 0 0 0 1px var(--gia-primario), var(--shadow-sm);
}

.canal-pill {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 2px 10px;
    border-radius: 999px;
    color: var(--text-on-brand);
}

.canal-valor {
    font-size: 1.4rem;
    font-weight: 700;
    color: var(--text-strong);
    line-height: 1.1;
    white-space: nowrap;
}

.canal-dif {
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--text-muted);
}

/* Tabla "Analisis por canal" */
.tabla-canales {
    font-variant-numeric: tabular-nums;
}

.tabla-canales th {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
    font-weight: 700;
    border-bottom-color: var(--border-strong) !important;
}

.tabla-canales td {
    vertical-align: middle;
}

.tabla-canales .fila-total td {
    font-weight: 700;
    border-top: 2px solid var(--border-strong);
    color: var(--text-strong);
}

.texto-pos { color: var(--success); font-weight: 600; }
.texto-neg { color: var(--danger); font-weight: 600; }

/* ---- Pie del nav lateral: identidad del usuario ---- */
.nav-footer {
    margin-top: auto;
    padding: var(--sp-3);
    border-top: 1px solid var(--border);
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    min-width: 0;
    -webkit-user-select: none;
    user-select: none;
}

.nav-avatar {
    flex: 0 0 auto;
    width: 36px;
    height: 36px;
    border-radius: 999px;
    background-color: var(--gia-primario);
    color: var(--text-on-brand);
    font-weight: 700;
    font-size: 0.8rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.nav-footer-texto {
    min-width: 0;
}

.nav-footer-nombre {
    font-weight: 700;
    font-size: 0.82rem;
    color: var(--text-strong);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.nav-footer-version {
    font-size: 0.72rem;
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.nav-footer-online {
    font-size: 0.72rem;
    color: var(--success);
}

.nav-footer-online::before {
    content: "●";
    margin-right: 4px;
}

.app-shell[data-nav-collapsed="1"] .nav-footer-texto {
    display: none;
}

.app-shell[data-nav-collapsed="1"] .nav-footer {
    justify-content: center;
}

/* ---- Metadatos de la topbar (ultima actualizacion) ---- */
.topbar-meta {
    display: inline-flex;
    align-items: baseline;
    gap: var(--sp-2);
    white-space: nowrap;
}

.topbar-meta-label {
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-muted);
}

.topbar-meta-valor {
    font-size: 0.82rem;
    font-weight: 700;
    color: var(--text-strong);
}

@media (max-width: 991.98px) {
    .topbar-meta {
        display: none;   /* en movil prima el espacio */
    }
}

/* ---- Filtro de seleccion de los grids (FiltroSeleccion) ----
   Equivalente interno al set filter de AG Grid Enterprise: buscador,
   "(Seleccionar todo)" y filas clicables enteras con hover. */
.dag-filtro-select {
    padding: 10px;
    width: 300px;
    font-size: 0.85rem;
}

.dag-filtro-select-busqueda {
    width: 100%;
    box-sizing: border-box;
    margin-bottom: 8px;
    padding: 6px 10px;
    border: 1px solid var(--ag-border-color, var(--border));
    border-radius: 6px;
    background: transparent;
    color: inherit;
}

.dag-filtro-select-busqueda:focus {
    outline: 2px solid var(--gia-primario);
    outline-offset: -1px;
}

.dag-filtro-select-acciones {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 6px;
    color: var(--text-muted);
}

.dag-filtro-select-limpiar {
    border: 1px solid var(--ag-border-color, var(--border));
    border-radius: 6px;
    background: transparent;
    color: inherit;
    padding: 3px 10px;
    cursor: pointer;
}

.dag-filtro-select-limpiar:hover:not(:disabled) {
    background: var(--brand-tint, rgba(37, 99, 235, 0.08));
}

.dag-filtro-select-limpiar:disabled {
    opacity: 0.5;
    cursor: default;
}

/* Flujo en bloque a proposito: con display:flex + max-height, al desbordar
   flex ENCOGE los items (con overflow:hidden colapsan a ~0 y la lista se ve
   aplastada con cientos de valores). */
.dag-filtro-select-lista {
    max-height: 300px;
    overflow-y: auto;
}

.dag-filtro-select-item {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0;
    padding: 5px 6px;
    border-radius: 6px;
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
}

.dag-filtro-select-item:hover {
    background: var(--brand-tint, rgba(37, 99, 235, 0.08));
}

.dag-filtro-select-item input[type="checkbox"] {
    flex: 0 0 auto;
    width: 15px;
    height: 15px;
    margin: 0;
    accent-color: var(--gia-primario);
    cursor: pointer;
}

.dag-filtro-select-texto {
    overflow: hidden;
    text-overflow: ellipsis;
}

/* "(Seleccionar todo)" anclado sobre la lista, con separador */
.dag-filtro-select-todo {
    font-weight: 600;
    border-bottom: 1px solid var(--ag-border-color, var(--border));
    border-radius: 6px 6px 0 0;
    margin-bottom: 2px;
}

.dag-filtro-select-vacio {
    padding: 8px 6px;
    color: var(--text-muted);
    font-style: italic;
}

/* ---- Selector multiple con checkboxes (components/filtro_multi.py) ----
   Sustituto de dcc.Dropdown(multi=True) en el panel lateral y las barras de
   filtros, con la misma UX que el FiltroSeleccion de los grids (bloque de
   arriba) pero con los tokens del tema (los --ag-* solo existen dentro de
   los grids). Apertura/cierre y busqueda en assets/filtro_multi.js. */
.fm {
    position: relative;
}

.fm-btn {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 6px;
    width: 100%;
    min-height: 34px;
    padding: 4px 8px;
    font-size: 0.8rem;
    text-align: left;
    color: var(--text);
    background: var(--surface-2);
    border: 1px solid var(--border-strong);
    border-radius: 4px;
}

.fm-btn:focus-visible {
    outline: none;
    box-shadow: var(--focus-ring);
}

.fm-label {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.fm-btn.fm-activo .fm-label {
    color: var(--brand-ink);
    font-weight: 600;
}

.fm-caret {
    flex: 0 0 auto;
    color: var(--text-muted);
}

.fm.fm-abierto .fm-caret {
    transform: rotate(180deg);
}

.fm-panel {
    display: none;
    position: absolute;
    top: calc(100% + 2px);
    left: 0;
    z-index: 1015;   /* sobre tarjetas y graficos; bajo topbar (1020) */
    width: max-content;
    min-width: 100%;
    max-width: 340px;
    padding: 8px;
    background: var(--surface-2);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-md);
    font-size: 0.85rem;
}

.fm.fm-abierto .fm-panel {
    display: block;
}

/* Con .fm-derecha (la pone filtro_multi.js si el panel se sale del viewport)
   el panel se ancla al borde derecho del control. */
.fm-panel.fm-derecha {
    left: auto;
    right: 0;
}

/* En el panel lateral (~250px y overflow-y:auto, que clipa a lo ancho) el
   panel no puede sobresalir: ocupa el ancho del control. */
.sidebar .fm-panel {
    width: 100%;
    max-width: none;
}

/* dcc.Input en Dash 4 pone el className en un contenedor (inline-flex) y el
   <input> real va dentro sin borde: el contenedor lleva el marco y el input
   se estira; el foco se detecta con :focus-within. */
.fm-buscar {
    width: 100%;
    box-sizing: border-box;
    margin-bottom: 8px;
    padding: 6px 10px;
    border: 1px solid var(--border-strong);
    border-radius: 6px;
    background: transparent;
    color: inherit;
}

.fm-buscar .dash-input-element {
    flex: 1 1 auto;
    width: 100%;
    padding: 0;
}

.fm-buscar:focus-within {
    outline: 2px solid var(--gia-primario);
    outline-offset: -1px;
}

/* Flujo en bloque a proposito, como .dag-filtro-select-lista: con flex +
   max-height los items encogen al desbordar. */
.fm-lista {
    max-height: 300px;
    overflow-y: auto;
}

/* .fm-item viste el boton "(Todos)"; las filas del dbc.Checklist son
   div.form-check con el input y el label dentro. La fila entera es flex
   (se anulan el padding-left y el margen negativo de Bootstrap). */
.fm-item,
.fm-lista .form-check {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0;
    padding: 6px 8px;
    border-radius: 6px;
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.fm-item:hover,
.fm-lista .form-check:hover {
    background: var(--brand-tint);
}

.fm-lista .form-check-input {
    flex: 0 0 auto;
    width: 15px;
    height: 15px;
    margin: 0;
    cursor: pointer;
}

/* Bootstrap dibuja el checkbox (appearance:none): el marcado se tiñe con
   los tokens, no con accent-color. */
.fm-lista .form-check-input:checked {
    background-color: var(--gia-primario);
    border-color: var(--gia-primario);
}

/* El label ocupa el resto de la fila (toda la fila clicable) y corta con
   elipsis los valores largos. */
.fm-lista .form-check-label {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    cursor: pointer;
}

/* "(Todos)" anclado sobre la lista: un boton con checkbox dibujado en CSS
   (uno real se alternaria solo al clicar y su estado lo gobierna el value
   del Checklist, no el click). filtro_multi.js le pone .fm-marcado cuando
   la seleccion esta vacia (= sin filtro). */
.fm-todos {
    width: 100%;
    font: inherit;
    font-weight: 600;
    color: inherit;
    background: transparent;
    border: 0;
    border-bottom: 1px solid var(--border);
    border-radius: 6px 6px 0 0;
    margin-bottom: 2px;
}

.fm-todos-check {
    flex: 0 0 auto;
    position: relative;
    width: 15px;
    height: 15px;
    border: 1px solid var(--border-strong);
    border-radius: 3px;
    background: transparent;
}

.fm-todos.fm-marcado .fm-todos-check {
    background: var(--gia-primario);
    border-color: var(--gia-primario);
}

.fm-todos.fm-marcado .fm-todos-check::after {
    content: "";
    position: absolute;
    left: 4px;
    top: 1px;
    width: 5px;
    height: 9px;
    border: solid var(--text-on-brand);
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}

.fm-vacio {
    padding: 8px 6px;
    color: var(--text-muted);
    font-style: italic;
}

.fm-oculto {
    display: none !important;
}

/* ==================== Pagina de permisos por perfil ====================
   Todo con los tokens del panel (--sp-*, --surface-*, --border, --radius-*):
   ninguna medida ni color a pelo. */

/* Es un formulario, no un dashboard: a ancho completo el desplegable de
   perfil medía media pantalla. */
.perm-panel {
    max-width: 1040px;
}

.perm-label {
    font-weight: 600;
    color: var(--text-strong);
    margin-bottom: var(--sp-1);
}

.perm-flash:not(:empty) {
    margin-top: var(--sp-3);
}

/* ---- estado vacio (sin perfil elegido) ---- */
.perm-vacio {
    text-align: center;
    padding: var(--sp-6) var(--sp-4);
}

.perm-vacio-icono {
    font-size: 2rem;
    color: var(--text-muted);
    opacity: 0.55;
}

.perm-vacio-texto {
    margin: var(--sp-3) 0 var(--sp-1);
    font-weight: 600;
    color: var(--text-strong);
}

.perm-vacio-ayuda {
    margin: 0;
    font-size: 0.85rem;
    color: var(--text-muted);
}

/* ---- los dos flags del perfil ---- */
.perm-flags {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
}

/* El aviso de que son columnas del ERP: aqui, junto a los dos controles que
   afecta, en vez de como banda naranja a toda pagina. */
.perm-nota-erp {
    margin: var(--sp-3) 0 0;
    padding-top: var(--sp-3);
    border-top: 1px solid var(--border);
    font-size: 0.8rem;
    color: var(--text-muted);
}

.perm-nota-erp code {
    color: var(--text);
    background-color: var(--surface-1);
    padding: 1px 4px;
    border-radius: var(--radius-sm);
}

/* ---- acordeon de secciones ---- */
.perm-cuerpo-acordeon {
    padding: 0;
}

.perm-total {
    font-size: 0.8rem;
    color: var(--text-muted);
    white-space: nowrap;
}

.perm-seccion-titulo {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    width: 100%;
}

.perm-seccion-icono {
    color: var(--text-muted);
    width: 1.1rem;
    text-align: center;
}

.perm-seccion-nombre {
    font-weight: 600;
    color: var(--text-strong);
}

/* El contador es lo que hace legible el acordeon cerrado: sin el, la cabecera
   solo decia cuantas paginas TIENE la seccion, no cuantas ve el perfil. */
.perm-conteo {
    margin-left: auto;
    margin-right: var(--sp-2);
    font-size: 0.75rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    padding: 2px var(--sp-2);
    border-radius: 999px;
    border: 1px solid var(--border-strong);
    color: var(--text-muted);
    background-color: var(--surface-1);
}

.perm-conteo-parcial {
    color: var(--brand-ink);
    border-color: var(--brand-ink);
    background-color: var(--brand-tint);
}

.perm-conteo-todo {
    color: var(--text-on-brand);
    border-color: var(--brand-ink);
    background-color: var(--brand-ink);
}

.perm-toda-seccion {
    font-weight: 600;
    padding-bottom: var(--sp-2);
    margin-bottom: var(--sp-2);
    border-bottom: 1px solid var(--border);
}

/* Dos columnas cuando caben: 7 paginas en vertical hacian scrollear. */
.perm-paginas {
    columns: 2;
    column-gap: var(--sp-5);
}

@media (max-width: 575.98px) {
    .perm-paginas { columns: 1; }
}

/* ---- barra de acciones ---- */
/* Pegada abajo: con las 12 secciones desplegadas, Guardar quedaba fuera de
   pantalla. */
.perm-acciones {
    position: sticky;
    bottom: 0;
    z-index: 5;
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    margin-top: var(--sp-4);
    padding: var(--sp-3) 0;
    background-color: var(--surface-1);
    border-top: 1px solid var(--border);
}

.perm-sin-guardar {
    margin-right: auto;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--danger);
}
