/* ═══════════════════════════════════════════════════════════════════════════════
   MOLDE DE LISTA DE CATÁLOGO · densidad y recorte de texto
   Regla 5 de CLAUDE.md. Compartido por TODAS las listas de catálogo del sistema.
   Piloto: Pages/ThirdParties/Suppliers.razor · quedan 12 pantallas por migrar.

   POR QUÉ VIVE AQUÍ Y NO EN EL CSS AISLADO DE LA PANTALLA — dos razones, las dos duras:
   (1) Es un MOLDE. Copiarlo en cada pantalla garantiza que a la tercera ya no sean iguales.
   (2) El aislamiento de Blazor NO PUEDE mirar hacia ARRIBA. La densidad la publica el shell
       como [data-density] en .ns-shellv4, que es ANCESTRO de la página; `::deep` alcanza
       descendientes, nunca ancestros. Desde el .razor.css esta regla es inexpresable.

   NO se tocó shell-v4.css a propósito: eso cambiaría TODAS las pantallas del sistema de
   golpe. Aquí solo entra quien se apunta poniendo la clase `ns-lista` en su grilla.
   ═══════════════════════════════════════════════════════════════════════════════ */

/* ── 0 · PALETA DEL MOLDE ──────────────────────────────────────────────────────
   DOS azules, y la diferencia es de LEGIBILIDAD, no de gusto. Medido en navegador
   sobre blanco el 2026-08-29:
     #0071e3  →  4.70:1   acento de marca. Sirve para la LÍNEA y los ICONOS (gráficos:
                          el mínimo exigible es 3:1) pero se queda corto para texto de
                          10.5 px, donde 4.5:1 es el suelo y no un objetivo.
     #0a4a91  →  8.74:1   el mismo azul oscurecido, ya en la paleta del proyecto
                          (brandDk). Es el del TEXTO del encabezado.
   Si algún día se prefiere el tono claro también en el texto, es UNA línea —
   pero baja a 4.70:1, así que se cambia a sabiendas.                              */
:root {
    --ns-lista-azul: #0071e3;         /* línea inferior e iconos */
    --ns-lista-azul-texto: #0a4a91;   /* etiquetas del encabezado */
    /* Fondo del encabezado: TINTE DE MARCA a baja intensidad, SÓLIDO. NO es gris —
       el gris está proscrito por la Regla 1 y además queda inerte junto al azul.
       Es EXACTAMENTE la zebra del PDF de proveedores (Suppliers.razor:3676) y del de
       categorías de gasto (Categorias.razor:476), así que pantalla e impresión comparten
       paleta en vez de parecerse.
       ⚠ NO confundir con #eef4ff (una ff, no fd): ese es el tinte de HOVER de botones y
       chips. Son dos tintes hermanos con usos distintos; no se "corrige" uno por el otro. */
    /* SIN RELLENO (variante A, 2026-08-29). Vuelve a lo que la Regla 1 pedía desde el
       principio: «el peso lo carga la LÍNEA, no un relleno».
       ★ EL RELLENO SE PUSO POR UN MIEDO QUE RESULTÓ INFUNDADO: se temía que al desplazar las
       filas se fundieran con el encabezado fijo. MEDIDO con control positivo —dos filas
       pintadas de rojo y desplazadas bajo la cabecera— NO SE TRANSPARENTAN, porque el propio
       `thead` de DevExpress ya trae fondo opaco `rgb(255,255,254)`. El relleno era redundante.
       Contrastes medidos sin relleno: texto 8,75:1 · embudos 3,64:1 — MEJORES que con tinte.
       ALTERNATIVA B, a una línea de aquí si se prefiere que el encabezado se lea azul:
           /* ENCABEZADO · AZUL SÓLIDO. Decidido por David 2026-08-29 tras comparar tres variantes
       con una fila seleccionada a la vista. Ver la Regla 1 para el porqué y los números. */
    /* UN SOLO TONO para el encabezado Y para los elementos interactivos (código, «+»,
       enlaces). No son dos variables por casualidad: son el MISMO valor a propósito, y
       separarlas volvería a crear la competencia que costó cuatro rondas. */
    /* RESPALDO, no la verdad. Los tres los pone la PÁGINA desde ShellVisuals con el color
       de SU módulo; estos valores solo evitan una lista sin color si alguien olvida
       declararlo. La relación entre ellos —fondo real, texto calculado, chip calculado— vive
       en ShellVisuals, no aquí. */
    --ns-lista-encabezado: #4338ca;
    --ns-lista-acento: #4338ca;
    --ns-lista-encabezado-texto: #ffffff;
    --ns-lista-encabezado-iconos: #ffffff;
    --ns-lista-encabezado-iconos-op: .85;    /* NO bajar: al 65% caían a 2,83:1 */
}

/* ── 1 · DENSIDAD ──────────────────────────────────────────────────────────────
   UNA SOLA VERDAD: la preferencia es la del shell (ShellThemePanel → localStorage
   `nanchesoft.ui.theme` → data-density). El interruptor de la barra de la lista NO
   tiene estado propio: escribe esa misma preferencia. Dos puertas, un solo ajuste.
   COMPACTA es el default y no necesita reglas: es como ya se veía la grilla.        */

/* CÓMODA · el texto puede ocupar dos renglones y la fila respira. */
.ns-shellv4[data-density="comodo"] .ns-lista td {
    padding-top: 8px !important;
    padding-bottom: 8px !important;
    font-size: 13.5px !important;
}

/* ── EL SEGUNDO NIVEL · la fila de dos alturas de la Regla 1 ───────────────────
   Antes, en Cómoda, el NOMBRE se partía en dos renglones. Eso gastaba la segunda línea en
   más de lo mismo. Ahora la segunda línea lleva OTRO DATO —la razón social y el contacto—,
   que es lo que la Regla 1 pide: «dato principal arriba, secundario abajo en gris claro».
   El nombre se queda SIEMPRE en una línea con elipsis.

   ★ Y ASÍ SE RESUELVE LA TENSIÓN QUE QUEDÓ ABIERTA: la Regla 5 fijó «compacta = una línea»
   como default y el doble nivel parecía contradecirla. No se contradicen si el segundo nivel
   ES la densidad cómoda: el interruptor deja de cambiar solo el ALTO y pasa a cambiar CUÁNTA
   INFORMACIÓN ves, que es mucho más útil que engordar filas.

   Lo decide el CSS y no un @if de Blazor: así cambiar de densidad no re-renderiza la grilla
   —el subtítulo ya está en el DOM— y el interruptor responde al instante. */
.ns-lista .ns-lista__sub {
    display: none;
}

.ns-shellv4[data-density="comodo"] .ns-lista .ns-lista__sub {
    display: block;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 11.5px;
    line-height: 1.35;
    color: #64748b;          /* gris claro: secundario, no compite con el nombre */
    margin-top: 1px;
}

/* ── 2 · RECORTE DE TEXTO ──────────────────────────────────────────────────────
   `ns-lista__texto`  = se puede recortar. SIEMPRE con title, para que el texto
                        completo esté a un puntero de distancia.
   `ns-lista__literal`= NUNCA se recorta.

   ⛔ LA DISTINCIÓN NO ES ESTÉTICA. Un nombre cortado es un dato INCOMPLETO y se nota.
   Un RFC cortado es un dato EQUIVOCADO y NO se nota: «XAXX010101…» parece un RFC.
   Lo mismo un código, un folio o un importe. Esos van enteros o no van.
   Su columna se dimensiona por el máximo real medido, nunca «a ojo».                */
.ns-lista .ns-lista__texto {
    display: block;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ns-lista .ns-lista__literal {
    white-space: nowrap;
    text-overflow: clip;        /* sin elipsis: una elipsis aquí MENTIRÍA */
    overflow: visible;
}

/* ── 3 · EL EMBUDO HUÉRFANO DE LA COLUMNA DEL CHEVRON ──────────────────────────
   SÍNTOMA: encabezado vacío al final de la tabla con un embudo de filtro suelto debajo.
   CAUSA (medida): FilterMenuButtonDisplayMode="Always" se pone A NIVEL DE LA GRILLA y
   DevExpress lo aplica a TODAS las columnas, la de comandos incluida — que no filtra nada.

   ⛔ EL ARREGLO EVIDENTE ES EL QUE REVIENTA: poner FilterMenuButtonDisplayMode="Never"
   en la DxGridCommandColumn lanza InvalidOperationException al renderizar y tumba la
   pantalla entera (lección #2 de CLAUDE.md: esas props son exclusivas de
   DxGridDataColumn). Por eso esto se resuelve por CSS y no por marcado.

   Selectores TOMADOS DEL DOM REAL el 2026-08-29, no supuestos:
     encabezado    → th.dxbl-grid-header.dxbl-grid-action.dxbl-grid-command-cell
     fila de filtro→ td.dxbl-grid-command-cell.dxbl-align-center
   Acotado a `thead`: en el CUERPO esa misma clase es la celda del CHEVRON.             */
.ns-lista thead .dxbl-grid-command-cell > * {
    display: none !important;
}

/* ── 4 · ENCABEZADO · BLANCO CON LETRA AZUL (Regla 1 · decidido por David 2026-08-29) ──
   Sustituye a la banda azul de marca. NO es un cambio de gusto: la banda rellena pesaba más
   que los propios datos y se comía las flechas de orden y los embudos, que iban en blanco
   sobre azul. Aquí EL PESO LO CARGA UNA LÍNEA, no un relleno.

   Vive en el MOLDE y no en la pantalla justamente porque va a replicarse a 12 listas más:
   una copia por pantalla garantiza que a la tercera ya no sean iguales.                  */

.ns-lista thead th,
.ns-lista thead .dxbl-grid-header-content {
    background: #fff !important;
    background-image: none !important;   /* mata el degradado azul heredado */
    color: var(--ns-lista-encabezado-texto, #fff) !important;
}

/* El encabezado se lee como ETIQUETA, no como título: pequeño, en versales y espaciado.
   Así ocupa poco y aun así se distingue del dato, que va en gris muy oscuro. */
.ns-lista thead .dxbl-grid-header-content {
    font-weight: 700;
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: .08em;
}

/* LA LÍNEA, que es la que marca dónde acaba el encabezado ahora que no hay banda de color.
   `inset` y no `border-bottom`: el borde alteraría la altura de la celda y descuadraría la
   columna fija del chevron respecto al resto. */
.ns-lista thead th {
    /* SIN LÍNEA DE ACENTO. La llevó mientras el relleno era índigo fijo y el módulo tenía
       que identificarse por otro lado. Ahora EL RELLENO ES EL COLOR DEL MÓDULO, así que la
       línea sería el mismo color contra sí mismo: ruido. */
    box-shadow: none;
}

/* ── 5 · LOS ICONOS DEL ENCABEZADO SOBRE BLANCO ────────────────────────────────
   Embudos de filtro y flechas de orden iban BLANCOS porque heredaban el `color:#fff` de la
   banda. Con el fondo blanco eso los volvía invisibles — el icono seguía ahí, midiendo y
   ocupando, pero sin verse. Se pintan de azul y se ATENÚAN: presentes pero sin competir con
   el texto; a opacidad plena en cuanto la columna está ordenada o filtrada, que es cuando
   el icono SIGNIFICA algo.
   ⚠ DevExpress no dibuja un icono sino CUATRO <use> hermanos y deja que el tema enseñe el
   que toca; por eso se pinta el CONTENEDOR vía `color` + `currentColor`, nunca un <use>. */
.ns-lista thead .dxbl-grid-filter-menu-funnel-btn,
.ns-lista thead .dxbl-grid-header-content svg {
    color: var(--ns-lista-encabezado-iconos, #fff) !important;
    fill: currentColor;
    opacity: var(--ns-lista-encabezado-iconos-op, .85);
    /* ⚠ LA OPACIDAD ES PARTE DEL CONTRASTE, y es fácil olvidarlo: un icono atenuado se
       COMPONE contra el fondo, así que el color declarado NO es el que se ve. Medido: el
       azul claro a .45 daba 1,94:1 compuesto sobre blanco — por debajo del 3:1 exigible a
       un elemento gráfico, o sea un embudo que técnicamente «se ve» y en la práctica no.
       .65 y no .60: sobre el tinte #eef4fd, .60 daba 3,09:1 — CUMPLE, pero pegado al mínimo,
       y ahí cualquier retoque futuro del tinte lo rompe SIN QUE NADIE SE ENTERE. Con .65
       quedan en 3,43:1 y la diferencia visual es imperceptible: se compra margen gratis. */
}

.ns-lista thead .dxbl-grid-filter-menu-funnel-btn:hover,
.ns-lista thead .dxbl-grid-filter-menu-funnel-btn:focus-visible,
.ns-lista thead th[aria-sort]:not([aria-sort="none"]) .dxbl-grid-header-content svg,
.ns-lista thead .dxbl-grid-filter-menu-funnel-btn.dxbl-active {
    opacity: 1;
}

/* ── 6 · LA FILA DE FILTRO NO ES UNA SEGUNDA BANDA ─────────────────────────────
   Fondo blanco y un separador de medio píxel. Tres bandas apiladas —encabezado, filtro y
   panel de agrupar— fue justo lo que hundió el intento del encabezado azul. */
.ns-lista thead tr:nth-child(2) td,
.ns-lista thead tr:nth-child(2) th {
    background: #fff !important;
    border-bottom: .5px solid #e2e8f0;
}

/* ── 7 · ENCABEZADO SIEMPRE FIJO ───────────────────────────────────────────────
   Regla permanente (David, 2026-08-29): en NINGUNA lista se pierden los encabezados al
   desplazarse. Con 22 filas ya no se sabe qué columna se mira; con 500 la lista es
   inservible. Es un DEFECTO FUNCIONAL, no un adorno.

   ⛔ DevExpress.Blazor 25.2.8 NO LO TRAE. Verificado por REFLEXIÓN sobre el ensamblado, no
   por `strings` ni por compilar: `HeaderFixed`, `FixedHeader` y `StickyHeader` NO EXISTEN
   como parámetros de DxGrid. Y OJO — escribirlos COMPILA IGUAL, porque DxGrid declara
   `Attributes` con CaptureUnmatchedValues y se los traga como atributos HTML sueltos. Es la
   lección #0 en su forma más traicionera: build verde, cero efecto. Lo único nativo es
   `VirtualScrollingEnabled`, que SUSTITUYE al paginador — otro comportamiento, no este.

   POR ESO SE HACE CON CSS, y hace falta LA COMBINACIÓN DE DOS COSAS; ninguna sirve sola:
     (1) que el CUERPO de la grilla sea lo que scrollea, no la página. Medido: el scroller
         era `.ns-shellv4__pane`, y entre él y el thead hay un `.dxbl-scroll-viewer-content`
         con overflow-y:auto que sería el scrollport de un sticky y NUNCA scrollea. Un
         `position:sticky` a secas ahí no habría hecho NADA.
     (2) el thead pegado con `position:sticky` DENTRO de ese scroller.
   Se usa flex y no alturas en píxeles: cada una de las 13 pantallas tiene un encabezado de
   distinto alto encima de la grilla, y un `calc(100vh - 15rem)` sería falso en 12 de ellas. */
.ns-lista-pagina {
    height: 100%;
    display: flex;
    flex-direction: column;
    min-height: 0;              /* sin esto un hijo flex no puede encoger y el scroll no nace */
}

.ns-lista-pagina .ns-lista {
    flex: 1 1 auto;
    min-height: 0;
}

/* Sticky sobre el THEAD ENTERO y no sobre cada th: así el encabezado y la fila de filtro
   viajan juntos, sin tener que calcular el desplazamiento de la segunda a mano (que cambiaría
   con la densidad compacta/cómoda y volvería a ser un número mágico). */
.ns-lista thead {
    position: sticky;
    top: 0;
    z-index: 3;
}

/* Las celdas de columna FIJA (selección y chevron) ya están pegadas en horizontal por
   DevExpress. Solo se les sube el z-index para que en la esquina manden sobre las demás;
   NO se les toca `left`/`right` o se perdería su anclaje lateral. */
.ns-lista thead .dxbl-grid-fixed-cell {
    z-index: 4;
}

/* ── 8 · EL FONDO DEL ENCABEZADO · GRIS TENUE Y SÓLIDO ─────────────────────────
   Consecuencia directa de fijarlo: con el encabezado quieto, el blanco puro deja de servir
   porque las filas se FUNDEN por debajo al desplazar.
   ⛔ SÓLIDO, NUNCA TRANSLÚCIDO: con alfa se vería el texto de las filas atravesando el
   encabezado. Nada de `rgba()` ni de `backdrop-filter` aquí.
   Se distingue por el fondo tenue, la versal pequeña y el peso — NO por una banda de color.
   Referencia: Linear, Notion, Stripe. */
.ns-lista thead tr:nth-child(1) th,
.ns-lista thead tr:nth-child(1) .dxbl-grid-header-content {
    background: var(--ns-lista-encabezado, #0a4a91) !important;
}

/* ⛔ EL RELLENO DE LA DERECHA NO LLEVA BANDA. Al acotar el ancho de las columnas, la tabla
   deja de llenar el panel y DevExpress mete una celda de relleno (`dxbl-grid-empty-cell`) que
   heredaba el fondo del encabezado: se veía una franja oscura de 512 px sobre la nada, como
   una columna rota. Sin fondo, la tabla simplemente TERMINA — que es lo que hace NetSuite
   cuando la lista no llena el lienzo. */
/* ⚠ La especificidad IMPORTA aquí: la regla de arriba es `.ns-lista thead tr:nth-child(1) th`
   (0,2,2) y la celda de relleno ES un th de esa fila, así que se llevaba la banda. Hay que
   ganarle con `th.dxbl-grid-empty-cell` (0,3,2); con `!important` a secas no basta porque el
   otro selector también lo lleva. */
.ns-lista thead tr:nth-child(1) th.dxbl-grid-empty-cell,
.ns-lista thead th.dxbl-grid-empty-cell {
    background: transparent !important;
    box-shadow: none !important;
}

/* ⛔ LA FILA DE FILTRO SE QUEDA BLANCA. DOS BANDAS AZULES APILADAS SON LO QUE HUNDIÓ EL
   INTENTO DE JULIO (Regla 1): juntas pesaban más que los datos, que es lo contrario de lo
   que se busca. Una banda de color, no dos. */
.ns-lista thead tr:nth-child(2) td,
.ns-lista thead tr:nth-child(2) th {
    background: #fff !important;
}

/* La sombra aparece SOLO cuando hay algo desplazado debajo; es lo que dice «esto flota».
   Va en el thead y no en las celdas para que no se corte entre columnas. */
.ns-lista thead::after {
    content: "";
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 6px;
    pointer-events: none;
    background: linear-gradient(to bottom, rgba(15,23,42,.07), transparent);
}

/* ── 9 · LA CABECERA DE LA LISTA · UNA BARRA, NO TRES ──────────────────────────
   Regla 25 (máxima densidad) llevada a la cabecera: en una pantalla cuyo objetivo es VER
   REGISTROS, cada píxel de cromo se paga en filas.
   MEDIDO en proveedores antes de esto: 176 px hasta la primera fila a 1920 y 292 px a 390,
   repartidos en TRES filas — migaja+título, controles, y contadores.

   CONTRASTE (Ley Nº1): SAP Fiori, al colapsar su Dynamic Page, deja el título con un RESUMEN
   al lado en la misma línea, y manda las acciones globales al menú de desbordamiento DE
   DERECHA A IZQUIERDA. NetSuite ajusta la lista al lienzo disponible. Se adopta lo de Fiori.

   · La MIGAJA se retira: el menú lateral ya marca dónde estás. Era una línea entera para
     repetir lo que ya se ve.
   · El CONTADOR viaja junto al título, en menor tamaño: deja de ser fila propia.
   · Excel, PDF y Refrescar van al desbordamiento. «Nuevo» e «Importar» se quedan visibles:
     son las que se usan a diario.                                                        */
.ns-lista-barra {
    display: flex;
    align-items: center;
    gap: 12px;
    /* ⛔ NO `wrap`. Con `wrap`, a 390 px el bloque de título+contador ocupaba los 390 y empujaba
       las acciones a un SEGUNDO renglón: la barra normal medía 51 px y la de selección —cuyo
       texto es más corto y sí cabía— 37 px. Resultado: marcar una casilla SUBÍA la lista 14 px,
       justo el gesto que más se repite y justo donde menos filas hay. El `min-height` igualaba
       los dos estados en escritorio y no podía hacer nada aquí, porque el problema no era la
       altura mínima sino el ENVOLVIMIENTO. Con `nowrap` los dos estados son de un renglón a
       cualquier ancho; quien cede es el contador, que ya tenía elipsis. */
    flex-wrap: nowrap;
    padding: 2px 0 5px;   /* apretado a conciencia: cada píxel aquí es una fila menos abajo */
    /* ALTURA FIJA para los DOS estados. Sin esto, al marcar la primera casilla la barra
       cambiaba de 45 a 48 px y la lista entera daba un salto de 3 px: poco, pero es un
       tirón visible justo en el gesto que más se repite. Que sustituya sin moverse. */
    min-height: 40px;
}

.ns-lista-barra__id {
    display: flex;
    align-items: baseline;   /* baseline y no center: título y contador comparten renglón óptico */
    gap: 10px;
    min-width: 0;
    flex: 1 1 auto;
    /* Altura de línea FIJA: el bloque de texto cambia entre «Proveedores 22 de 22» y
       «2 seleccionados · 1 activo, 1 inactivo», y con line-height automática esos dos
       medían distinto — 2 px de tirón al marcar. Anclarla los iguala. */
    line-height: 30px;
}

.ns-lista-barra__titulo {
    margin: 0;
    font-size: 19px;
    font-weight: 700;
    letter-spacing: -.01em;
    color: #0f172a;
    white-space: nowrap;
}

.ns-lista-barra__conteo {
    font-size: 12px;
    color: #64748b;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    /* La elipsis que ya estaba declarada NO SE ACTIVABA: un hijo flex tiene `min-width:auto` y
       por eso se niega a encoger por debajo de su contenido. Sin esta línea el contador empujaba
       y la barra envolvía. Es el mismo tipo de fallo silencioso de siempre: la regla escrita
       parecía suficiente y no lo era. */
    min-width: 0;
}

.ns-lista-barra__acciones {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 0 0 auto;
}

/* ── EL MENÚ DE DESBORDAMIENTO ─────────────────────────────────────────────────
   <details> y no un dropdown propio: abre y cierra con teclado DE FÁBRICA (Enter y Espacio
   sobre el summary, Esc para cerrar), no necesita JS, y no entra en la pelea de z-index con
   los modales que ya costó una cacería (ver la nota de DevExpress popup z-index). */
.ns-lista-mas { position: relative; }

.ns-lista-mas > summary {
    list-style: none;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px; height: 30px;
    border: 1px solid #cbd5e1;
    border-radius: 7px;
    background: #fff;
    color: #0a4a91;
    font-size: 17px;
    line-height: 1;
    user-select: none;
}

.ns-lista-mas > summary::-webkit-details-marker { display: none; }   /* fuera el triangulito */
.ns-lista-mas > summary:focus-visible { outline: 2px solid #0071e3; outline-offset: 2px; }

.ns-lista-mas__menu {
    position: absolute;
    right: 0;
    top: calc(100% + 4px);
    z-index: 20;
    min-width: 200px;
    padding: 5px;
    background: #fff;
    border: 1px solid #e2e8f0;
    border-radius: 9px;
    box-shadow: 0 10px 24px rgba(15,23,42,.13);
    display: flex;
    flex-direction: column;
}

.ns-lista-mas__menu button {
    all: unset;
    box-sizing: border-box;
    padding: 8px 10px;
    border-radius: 6px;
    font-size: 13px;
    color: #0f172a;
    cursor: pointer;
    white-space: nowrap;
}

/* Aquí SÍ hay realce al enfocar/apuntar, y no contradice el «sin hover» del molde: aquello
   prohíbe que un elemento APAREZCA con el hover. Esto ya está visible; solo se resalta. */
.ns-lista-mas__menu button:hover,
.ns-lista-mas__menu button:focus-visible { background: #eef4fd; }
.ns-lista-mas__menu button:disabled { opacity: .45; cursor: default; }

/* ── LA FILA DE FILTROS ────────────────────────────────────────────────────────
   Buscador + segmentados en UNA línea. Sin las acciones, que se fueron arriba. */
.ns-lista-filtros {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    padding-bottom: 0;
    margin-bottom: 6px;
}

/* En móvil el buscador manda: ocupa la línea y los segmentados bajan juntos debajo. */
@media (max-width: 640px) {
    .ns-lista-filtros > .sup-search { flex: 1 1 100%; }
}

/* ── 10 · CREAR · el «+» de la barra ───────────────────────────────────────────
   Fiori: Crear va en la barra de la tabla y, por ser función PRINCIPAL, NUNCA baja al
   desbordamiento. De ahí que el ⋯ se lleve Importar/Excel/PDF/Refrescar y el «+» no.
   Icono y no texto porque «+» es de los poquísimos glifos que se leen sin tooltip — la
   propia guía de Fiori solo admite botón de icono en ese caso. Aun así lleva `title` Y
   `aria-label`: el title es para el ratón, el aria-label para el lector de pantalla.
   ⚠ SIEMPRE VISIBLE. Nada de aparecer al pasar por encima: en táctil no hay hover, y lo que
   solo se ve al apuntar no lo encuentra quien no apunta.                                  */
.ns-lista-nuevo {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px; height: 30px;
    border: 1px solid transparent;
    border-radius: 7px;
    background: var(--ns-lista-acento, #4338ca);
    color: #fff;
    font-size: 17px;
    line-height: 1;
    cursor: pointer;
}

.ns-lista-nuevo:focus-visible { outline: 2px solid #0a4a91; outline-offset: 2px; }

/* LOS DOS ESTADOS TIENEN QUE MEDIR IGUAL, o marcar una casilla da un tirón.
   Medido: con los botones de texto de la selección a 34 px y los iconos a 30, la barra
   pasaba de 132 a 136 px — 4 px de salto en el gesto más repetido de la pantalla.
   Se igualan a 30 px, que además aprieta el estado de selección. */
.ns-lista-barra .sup-selbtn {
    height: 30px;
    /* ⚠ `min-height` HAY QUE BAJARLO TAMBIÉN: la pantalla trae `.sup-selbtn{min-height:34px}`
       y min-height GANA A height pase lo que pase en la cascada — no es cuestión de
       especificidad ni de orden, es que min-height acota después. Sin esta línea el botón
       seguía midiendo 34 y la regla de arriba no hacía absolutamente nada (build verde,
       cero efecto: la lección #0 otra vez, ahora en CSS). */
    min-height: 30px;
    box-sizing: border-box;
    padding-top: 0;
    padding-bottom: 0;
    display: inline-flex;
    align-items: center;
}

.ns-lista-barra { min-height: 37px; }

/* ══ §11 · VISUAL DE UN LOOKUP CON COLOR / GLIFO / GRUPO ═══════════════════════════════════
   La grilla vieja los pintaba con `renderLookupVisual`; el molde los tiraba a texto plano y la
   información se perdía SIN QUE NADA FALLARA. Se porta en el lenguaje de la Regla 1 —círculo de
   color + nombre— y no como la tarjeta de tres líneas de la vieja, que contradice la densidad:
   lo que allá eran líneas aquí es el segundo nivel, y solo en Cómoda.
   ⚠ Va con ::deep: este markup lo renderiza DxGrid (componente hijo) desde CellDisplayTemplate,
   y el atributo de aislamiento de Blazor NO llega ahí. Sin ::deep no aplica nada, en silencio. */
::deep .cv2-lk {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    min-width: 0;          /* sin esto el hijo flex no encoge y la elipsis no se activa */
    max-width: 100%;
}

::deep .cv2-lk__punto {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    flex: 0 0 auto;
    /* Aro claro: sobre la fila cebra un punto saturado «vibra» contra el fondo. */
    box-shadow: 0 0 0 1.5px #fff;
}

::deep .cv2-lk__cuerpo {
    display: flex;
    flex-direction: column;
    min-width: 0;
    line-height: 1.25;
}

::deep .cv2-lk__nombre {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

::deep .cv2-lk__meta {
    font-size: 11px;
    color: #64748b;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ══ §12 · LA LISTA VACÍA ══════════════════════════════════════════════════════════════════
   DxGrid pinta «No data to display» en INGLÉS aunque la cultura sea es-MX: sus 568 cadenas
   vienen solo en inglés y el paquete no trae satélites de idioma. Se sustituye por
   `EmptyDataAreaTemplate` —no hay propiedad `NoDataText`, verificado por reflexión— y de paso
   se dice algo útil: qué hacer, no solo que no hay nada. */
::deep .cv2-vacio {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 26px 16px;
    text-align: center;
}

::deep .cv2-vacio__titulo {
    font-weight: 600;
    color: #334155;
}

::deep .cv2-vacio__pista {
    font-size: 12px;
    color: #64748b;
}

/* Separador del menú ⋯ · agrupa los comandos de VISTAS y los deja distinguibles de Refrescar,
   Excel y PDF sin meter un encabezado que ocupe otra fila en un menú que ya es largo. */
.ns-lista-mas__sep {
    height: 1px;
    margin: 5px 6px;
    background: rgba(15, 23, 42, .1);
}

/* Aviso de filtros que no aplican en la empresa activa. Ámbar porque es señal de ESTADO
   (Regla 1.3), no decoración: dice que lo que ves no es lo que la vista pedía. */
.sup-avisovista {
    display: flex; align-items: flex-start; gap: .5rem;
    margin: 0 0 .5rem; padding: .5rem .7rem;
    background: #fffbeb; border: 1px solid #fcd34d; border-radius: 8px;
    font-size: .82rem; color: #78350f; line-height: 1.35;
}
.sup-avisovista__ico { flex: 0 0 auto; font-size: .95rem; }

/* Editor de columnas y orden. Denso a propósito: son 12 filas y tiene que caber sin scroll en
   escritorio y con uno corto en móvil. */
.sup-cols { margin: 0 0 .5rem; padding: .5rem .6rem; border: 1px solid rgba(15,23,42,.12);
            border-radius: 9px; background: #fff; max-height: 15rem; overflow-y: auto; }
.sup-cols__tit { font-size: .68rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
                 color: #0071e3; margin-bottom: .35rem; }
.sup-cols__fila { display: flex; align-items: center; justify-content: space-between; gap: .5rem;
                  padding: .18rem 0; min-height: 32px; }
.sup-cols__chk { display: flex; align-items: center; gap: .4rem; font-size: .82rem; cursor: pointer; }
.sup-cols__btns { display: flex; gap: .15rem; }
.sup-cols__btns button { all: unset; cursor: pointer; padding: .1rem .32rem; border-radius: 5px;
                         font-size: .78rem; color: #475569; }
.sup-cols__btns button:hover { background: rgba(0,113,227,.09); color: #0071e3; }
.sup-cols__btns button.is-on { color: #0071e3; font-weight: 700; }
