/* ============================================================
   ISBO — tokens de marca sobre el tema Fluent de DevExpress.
   Se carga vía CustomUrls en TODOS los temas ISBO (appsettings.json),
   después del css de acento (css/fluent/*), por lo que --dxbl-accent-color
   ya tiene el valor del acento elegido (royal purple / cornflower / titanium).
   Los temas oscuros cargan además isbo-brand-dark.css.
   PROHIBIDO: overrides de clases .dxbl-* internas de DevExpress.
   ============================================================ */

:root {
    /* Acento: sigue al tema ISBO seleccionado */
    --isbo-accent: var(--dxbl-accent-color, #5f21ad);
    --isbo-font-mono: ui-monospace, "SF Mono", "Cascadia Mono", Consolas, monospace; /* códigos, IDs, CDC */
    --isbo-accent-strong: var(--dxbl-accent-color-dark, #4a1a87);
    --isbo-accent-soft: color-mix(in srgb, var(--dxbl-accent-color, #5f21ad) 12%, #ffffff);
    --isbo-on-accent: #FFFFFF; /* texto sobre bloques de acento / semánticos */

    /* Semánticos (para componentes propios: badges de estado, diferencia,
       timeline SIFEN). Texto AA sobre fondo claro. */
    --isbo-success: #0E700E;
    --isbo-success-strong: #0E700E; /* fondo de bloques success con texto blanco (dark lo aclara) */
    --isbo-success-bg: #E7F4E7;
    --isbo-warning: #8A5300;
    --isbo-warning-bg: #FFF4E5;
    --isbo-danger: #B10E1C;
    --isbo-danger-strong: #B10E1C; /* fondo de bloques danger con texto blanco (dark lo aclara) */
    --isbo-danger-bg: #FBEAEB;
    --isbo-info: #0F548C;
    --isbo-info-bg: #E8F1FA;

    /* Superficies neutras (cards, paneles propios) */
    --isbo-surface: #FFFFFF;
    --isbo-surface-alt: #F7F6FA;
    --isbo-border: #E3E1E8;
    --isbo-text: #1F1E24;
    --isbo-text-secondary: #615F6B;
}

/* ------------------------------------------------------------
   Badge de estado de documento (componente propio:
   Editors/EstadoDocumentoBadgeComponent.razor). Pill semántico —
   el radio redondeado es intrínseco al badge, no un override DX.
   Variantes por token semántico: el dark las resuelve isbo-brand-dark.css.
   ------------------------------------------------------------ */
.isbo-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.45em;
    padding: 0.25em 0.75em;
    border-radius: 999px;
    font-size: 0.8125rem;
    font-weight: 600;
    line-height: 1.5;
    white-space: nowrap;
}

.isbo-badge__dot {
    flex: none;
    width: 0.5em;
    height: 0.5em;
    border-radius: 50%;
    background: currentColor;
}

/* En una celda de grilla el badge se subordina a la fila: tamaño relativo a la
   fuente de la celda (así acompaña Compact/Standard en vez de quedar fijo en
   13px), padding vertical mínimo para no engordar la fila y peso medio. La
   versión del DetailView conserva la geometría de arriba. */
.dxbl-grid .isbo-badge {
    font-size: 0.9em;
    font-weight: 500;
    line-height: 1.4;
    padding: 0.1em 0.55em;
    vertical-align: middle;
}

/* Variantes por TONO (BadgesEstado.Variante): el estado no elige color, elige tono. */
.isbo-badge--neutro {
    color: var(--isbo-text-secondary);
    background: var(--isbo-surface-alt);
}

.isbo-badge--info {
    color: var(--isbo-info);
    background: var(--isbo-info-bg);
}

.isbo-badge--exito {
    color: var(--isbo-success);
    background: var(--isbo-success-bg);
}

.isbo-badge--advertencia {
    color: var(--isbo-warning);
    background: var(--isbo-warning-bg);
}

.isbo-badge--peligro {
    color: var(--isbo-danger);
    background: var(--isbo-danger-bg);
}

/* ------------------------------------------------------------
   List Views (isbo-design §7) — look "libro mayor" sobre el DxGrid Fluent.

   Todo por variables --dxbl-grid-* del tema (nombres verificados en
   devexpress.blazor.themes.fluent 26.1.4/core.min.css). Se declaran en el scope
   .dxbl-grid: en :root serían inertes porque DX las define ahí con (0,1,0).

   Decisiones:
   - Verticales como hairline al 40 % del borde (Aldo las pidió de vuelta, tenues); separador de fila al 55 %.
   - El header lleva la superficie alterna (apenas más oscura en claro, apenas más
     clara en oscuro), texto secundario semibold y una regla más firme debajo.
     Decisión de Aldo 2026-09-10 al comparar con HUB: el relleno sutil fija dónde
     termina el header en grillas anchas con scroll horizontal y es lo que el operador
     espera de una tabla (Primer, Lightning, Ant, HUB); Fluent 2 y Carbon van sin
     relleno. Nada de gris pleno ni borde exterior: la barra separa, no grita.
   - Hover = tinte del ACENTO al 6 %, no un gris: la marca aparece al pasar.
   - Selección = --isbo-accent-soft + marcador de 3 px a la izquierda
     (box-shadow inset para no correr el contenido). Con foco, lo mismo.
   - Cifras tabulares en TODA la grilla (no sólo en las celdas numéricas): fechas,
     códigos y contadores también alinean.
   - Grupos y footers en --isbo-surface-alt.
   Los tokens --isbo-* ya están remapeados en isbo-brand-dark.css: el oscuro sale solo.
   ------------------------------------------------------------ */
.dxbl-grid {
    --dxbl-grid-border-color: var(--isbo-border);
    --dxbl-grid-outer-border-color: var(--isbo-border);
    --dxbl-grid-h-line-color: color-mix(in srgb, var(--isbo-border) 55%, transparent);
    /* Verticales como hairline al 40 % (decisión de Aldo 2026-09-10 sobre la captura de
       Compra-Stock: sin nada, las columnas densas se leían pegadas). Más tenue que la de
       fila para que la lectura siga siendo horizontal. */
    --dxbl-grid-v-line-color: color-mix(in srgb, var(--isbo-border) 40%, transparent);
    /* Claro: la surface-alt plena "gritaba standard" (Aldo, 2026-09-10); a mitad de
       20 % hacia el blanco queda una banda apenas perceptible (50 % todavía era mucho). El oscuro fija su
       propio valor en isbo-brand-dark.css (surface-alt plena, que ahí sí funciona). */
    --dxbl-grid-header-bg: color-mix(in srgb, var(--isbo-surface-alt) 20%, var(--isbo-surface));
    --dxbl-grid-header-color: var(--isbo-text-secondary);
    --dxbl-grid-header-font-weight: 600;
    --dxbl-grid-hover-bg: color-mix(in srgb, var(--isbo-accent) 6%, var(--isbo-surface));
    --dxbl-grid-hover-color: var(--isbo-text);
    --dxbl-grid-selection-bg: var(--isbo-accent-soft);
    --dxbl-grid-selection-color: var(--isbo-text);
    --dxbl-grid-selection-focus-dark-bg: var(--isbo-accent-soft);
    --dxbl-grid-selection-focus-dark-color: var(--isbo-text);
    --dxbl-grid-selected-hover-bg: color-mix(in srgb, var(--isbo-accent) 18%, var(--isbo-surface));
    --dxbl-grid-focus-frame-color: var(--isbo-accent);
    --dxbl-grid-footer-bg: var(--isbo-surface-alt);
    --dxbl-grid-group-footer-bg: var(--isbo-surface-alt);
    font-variant-numeric: tabular-nums;
}

/* Lo que no es variable. Clases que DX emite en 26.1.4 (.dxbl-grid-selected-row,
   .dxbl-grid-group-row, .dxbl-grid-header-content): si cambian en un upgrade se
   pierde el detalle, no se rompe el layout. */
.dxbl-grid .dxbl-grid-table > thead > tr > th {
    border-bottom-color: var(--isbo-border);
}

.dxbl-grid .dxbl-grid-selected-row > td:first-child {
    box-shadow: inset 3px 0 0 0 var(--isbo-accent);
}

.dxbl-grid .dxbl-grid-group-row {
    background: var(--isbo-surface-alt);
    color: var(--isbo-text-secondary);
    font-weight: 600;
}

/* Header de columna numérica alineado a la derecha, como sus cifras. La clase la
   pone GrillaEncabezadoNumericoController (CustomizeElement) según TextAlignment. */
.dxbl-grid .isbo-th-num .dxbl-grid-header-content {
    justify-content: flex-end;
}

/* Códigos e identificadores en mono (§7): Documento, IdTributario, CDC, NroCheque…
   La clase la pone ColumnasMonoController sobre la celda; la lista de columnas es
   ISBO.Module/Editors/ColumnasMono.cs (compartida con Win). */
.dxbl-grid .dxbl-grid-table > tbody > tr > td.isbo-mono {
    /* Especificidad (0,3,3): la regla del tema `.dxbl-grid .dxbl-grid-table>tbody>tr>td`
       fija font-family con (0,2,3) y le ganaría a un simple `.dxbl-grid .isbo-mono`. */
    font-family: var(--isbo-font-mono);
    font-variant-numeric: tabular-nums;
}

/* Fechas de auditoría en relativo ("hace 3 días"), con el exacto en el title.
   La celda la arma FechasRelativasController (CustomizeCellDisplayTemplate) con
   Editors/FechaRelativaComponent.razor; las columnas son
   ISBO.Module/Editors/ColumnasFechaRelativa.cs (compartida con Win).
   El punteado del title avisa que hay más dato sin gritarlo. */
.isbo-fecha-rel {
    text-decoration: underline dotted var(--isbo-border);
    text-underline-offset: 0.2em;
    cursor: help;
}

/* Estado vacío de una grilla (componente propio: Editors/GrillaVaciaComponent.razor,
   montado por GrillaVaciaController vía EmptyDataAreaTemplate). Mensaje centrado y,
   sólo si la New action está disponible, un botón primario. */
.isbo-vacio {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.875rem;
    padding: 2.5rem 1rem;
    text-align: center;
}

.isbo-vacio__msg {
    color: var(--isbo-text-secondary);
    font-size: 0.9375rem;
}

/* ------------------------------------------------------------
   Pie de auditoría (componente propio: Editors/AuditoriaFooterComponent.razor).
   Línea de texto secundario al pie del formulario + "Detalles del sistema"
   colapsado con IDs técnicos en mono. §3 del sistema de diseño.
   ------------------------------------------------------------ */
.isbo-auditoria {
    font-size: 0.8125rem;
    color: var(--isbo-text-secondary);
    padding-top: 0.5rem;
    border-top: 1px solid var(--isbo-border);
}

.isbo-auditoria__detalles {
    margin-top: 0.25rem;
}

.isbo-auditoria__detalles summary {
    cursor: pointer;
    user-select: none;
    width: fit-content;
}

.isbo-auditoria__mono {
    font-family: var(--isbo-font-mono);
    font-size: 0.75rem;
    padding: 0.25rem 0 0 0.75rem;
}

/* ------------------------------------------------------------
   Documentos transaccionales (§5) — Factura_DetailView y siguientes.
   Componentes propios: Editors/TotalesFooterComponent.razor,
   Editors/ReceptorResumenComponent.razor; la clase de la grilla la asigna
   FacturaItemsInlineController vía GridModel.CssClass.
   ------------------------------------------------------------ */

/* Grilla de líneas: DxGrid no se estira solo dentro del form layout de XAF
   (la cadena de ancestros .nested-frame/.nested-content es display:block, no hay
   flex que absorba el sobrante y no se pueden pisar esas clases de XAF), así que
   la altura va relativa al viewport con scroll interno.

   La reserva es 100vh menos lo que ocupan cabecera + toolbars + footer, y ESO
   DEPENDE DE CUÁNTAS FILAS TIENE LA CABECERA DE CADA DOCUMENTO. Un único valor
   dejaba banda muerta abajo en los documentos de cabecera corta (medido en el
   smoke 2026-09-05 a 1440x900: Pedido y Presupuesto desperdiciaban 101 px,
   Remisión 51 px). Por eso el valor base cubre el caso de cabecera más alta y
   cada documento afina con su modificador; el controller de líneas de cada
   documento asigna "isbo-doc-lines isbo-doc-lines--<n>filas" vía GridModel.CssClass.

   Para re-medir tras cambiar una cabecera: en la vista, la reserva real es
   (top de la grilla + alto del footer + gap) / 16 = rem a restar. */
.isbo-doc-lines {
    height: calc(100vh - var(--isbo-doc-lines-reserva, 28rem));
    min-height: 12rem;
    /* XAF trae un tope propio para las grillas anidadas en virtual scrolling
       (.nested-content > .grid-content.grid-virtual-scrolling-mode dxbl-grid
       { max-height: 300px } en DevExpress.ExpressApp.Blazor/styles.css) que
       recortaba la altura calculada arriba sin ningún síntoma visible salvo la
       banda muerta al pie. Se levanta SOLO para la grilla de líneas del patrón
       3 zonas, que es la que debe ocupar el alto restante.

       Va con !important a propósito (decisión de Aldo, 2026-09-05): el selector
       de XAF es más específico y ganarle "limpio" obliga a replicar su estructura
       interna (.nested-content > .grid-content…), que se rompe en silencio si DX
       renombra esas clases. El !important aplica a una clase NUESTRA, no a una
       .dxbl-*, así que no pisa el theming del control. */
    max-height: none !important;
}

/* Cabecera de 3 filas sin línea de receptor (Pedido, Presupuesto). */
.isbo-doc-lines--3filas {
    --isbo-doc-lines-reserva: 26rem;
}

/* Cabecera de 3 filas + línea de receptor (Factura, NC/ND).
   Re-medido el 2026-09-16 a 1484x784 con la receta del encabezado
   (top de la grilla 431 + footer 62 + gap 12) / 16 = 31,6rem: con 28rem el
   bloque de totales quedaba a 779-841 px sobre un viewport de 784, o sea
   justo abajo del fold y había que scrollear para ver el TOTAL. */
.isbo-doc-lines--receptor {
    --isbo-doc-lines-reserva: 32rem;
}

/* Cabecera plana de 4 filas (Remisión). */
.isbo-doc-lines--4filas {
    --isbo-doc-lines-reserva: 29rem;
}

/* Orden de Compra: sus tres colecciones (Artículos, Gastos y Cuotas) viven en pestañas
   hermanas, así que solo una grilla se ve a la vez y puede tomar el alto restante como en
   cualquier documento de una sola grilla. Reserva medida a 1440x746 (smoke 2026-09-07):
   cabecera de 2 filas + línea de resumen del proveedor + la barra de pestañas.

   El max-height levanta el tope que XAF impone a las grillas anidadas en virtual scrolling
   (.nested-content > .grid-content.grid-virtual-scrolling-mode dxbl-grid { max-height: 300px }
   en DevExpress.ExpressApp.Blazor/styles.css), que si no recorta la altura calculada sin dar
   ningún síntoma salvo la banda muerta al pie. Va con !important por el mismo motivo que
   .isbo-doc-lines: el selector de XAF es más específico y aplica a una clase NUESTRA. */
.isbo-oc-lineas {
    height: calc(100vh - 30rem);
    min-height: 10rem;
    max-height: none !important;
}

/* Pedido de Compra: la zona de líneas es un maestro/detalle (ítems arriba, cotizaciones
   del ítem seleccionado abajo), así que las dos grillas se REPARTEN el alto en vez de
   tomarlo entera como en la OC. Alturas medidas en el smoke a 1440x746: la reserva es
   mayor que la de .isbo-oc-lineas porque además de cabecera y pestañas hay que descontar
   el encabezado del panel de detalle.

   Mismo max-height/!important que .isbo-oc-lineas y por el mismo motivo: levanta el tope
   de 300px que XAF impone a las grillas anidadas en virtual scrolling. Ver el comentario
   de esa regla. */
.isbo-pc-items {
    height: calc(100vh - 37.5rem);
    min-height: 9rem;
    max-height: none !important;
}

.isbo-pc-cotizaciones {
    height: calc(100vh - 41.5rem);
    min-height: 7.5rem;
    max-height: none !important;
}

/* Texto secundario del receptor bajo el lookup Cliente */
.isbo-receptor {
    display: flex;
    align-items: baseline;
    gap: 0.75rem;
    font-size: 0.75rem;
    line-height: 1.3;
    color: var(--isbo-text-secondary);
    padding: 0.125rem 0 0;
}

.isbo-receptor__texto {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.isbo-receptor__link {
    flex: none;
    color: var(--isbo-accent);
    text-decoration: none;
    cursor: pointer;
}

.isbo-receptor__link:hover { text-decoration: underline; }

/* Footer de totales: TOTAL (acento) · Total valores · Vuelto (success si > 0) */
.isbo-totales {
    display: flex;
    justify-content: flex-end;
    align-items: flex-end;
    gap: 1.5rem;
    padding: 0.25rem 0;
}

.isbo-totales__item {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.125rem;
}

.isbo-totales__cap {
    font-size: 0.6875rem;
    line-height: 1.2;
    color: var(--isbo-text-secondary);
}

.isbo-totales__val {
    font-family: var(--isbo-font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 1rem;
    font-weight: 500;
    line-height: 1.2;
    color: var(--isbo-text);
}

.isbo-totales__sep {
    align-self: stretch;
    width: 1px;
    background: var(--isbo-border);
}

.isbo-totales__item--accent,
.isbo-totales__item--success,
.isbo-totales__item--danger {
    border-radius: 4px;
    padding: 0.375rem 0.875rem;
    color: var(--isbo-on-accent);
}

.isbo-totales__item--accent { background: var(--isbo-accent); }
.isbo-totales__item--success { background: var(--isbo-success-strong); }
.isbo-totales__item--danger { background: var(--isbo-danger-strong); }

.isbo-totales__item--accent .isbo-totales__cap,
.isbo-totales__item--success .isbo-totales__cap,
.isbo-totales__item--danger .isbo-totales__cap {
    color: var(--isbo-on-accent);
    opacity: 0.75;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.isbo-totales__item--accent .isbo-totales__val,
.isbo-totales__item--success .isbo-totales__val,
.isbo-totales__item--danger .isbo-totales__val {
    color: var(--isbo-on-accent);
    font-weight: 700;
}

.isbo-totales__item--accent .isbo-totales__val { font-size: 1.375rem; }
.isbo-totales__item--success .isbo-totales__val,
.isbo-totales__item--danger .isbo-totales__val { font-size: 1.125rem; }

/* Par secundario que no cuadra contra el total del documento (plan de cuotas de una
   Orden de Compra a crédito). No es un bloque pintado como accent/success: solo tiñe
   el valor, para que el desbalance se lea sin competir con el TOTAL. */
.isbo-totales__item--alerta .isbo-totales__val { color: var(--isbo-danger); }

/* Par secundario de un circuito todavía en curso (ítems sin cotizar de un Pedido de
   Compra). Se distingue de --alerta a propósito: ámbar es "falta hacerlo", rojo es
   "no cuadra". Un pedido a medio cotizar es un estado normal, no un error. */
.isbo-totales__item--pendiente .isbo-totales__val { color: var(--isbo-warning); }

/* ------------------------------------------------------------
   Maestros (§4) — cabecera del registro de Artículo
   (componente propio: Editors/ArticuloResumenComponent.razor, Fase 4).
   Identificación a la izquierda (código mono · descripción · badge · chips)
   y KPIs de stock a la derecha, con Disponible sobre el tinte del acento.
   Solo tokens --isbo-*: el dark los resuelve isbo-brand-dark.css.
   ------------------------------------------------------------ */
.isbo-art-resumen {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1.5rem;
    padding: 0.25rem 0 0.625rem;
    border-bottom: 1px solid var(--isbo-border);
}

.isbo-art-resumen__id {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    min-width: 0;
}

.isbo-art-resumen__linea {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.75rem;
    min-width: 0;
}

.isbo-art-resumen__codigo {
    font-family: var(--isbo-font-mono);
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--isbo-accent-strong);
    background: var(--isbo-accent-soft);
    border-radius: 4px;
    padding: 0.15rem 0.5rem;
}

.isbo-art-resumen__desc {
    font-size: 1.375rem;
    font-weight: 600;
    line-height: 1.2;
    color: var(--isbo-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.isbo-art-resumen__sub {
    font-size: 0.8125rem;
    color: var(--isbo-text-secondary);
}

.isbo-art-resumen__chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.375rem;
}

.isbo-art-resumen__chip {
    font-size: 0.6875rem;
    font-weight: 600;
    color: var(--isbo-text-secondary);
    background: var(--isbo-surface-alt);
    border-radius: 999px;
    padding: 0.15rem 0.6rem;
    white-space: nowrap;
}

.isbo-art-resumen__kpis {
    display: flex;
    flex: none;
    border: 1px solid var(--isbo-border);
    border-radius: 6px;
    overflow: hidden;
}

.isbo-art-resumen__kpi {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.1rem;
    padding: 0.5rem 1.25rem;
    border-left: 1px solid var(--isbo-border);
}

.isbo-art-resumen__kpi:first-child { border-left: 0; }

.isbo-art-resumen__kpi--accent { background: var(--isbo-accent-soft); }

.isbo-art-resumen__cap {
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--isbo-text-secondary);
}

.isbo-art-resumen__val {
    font-family: var(--isbo-font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 1.25rem;
    font-weight: 600;
    line-height: 1.2;
    color: var(--isbo-text);
}

.isbo-art-resumen__kpi--accent .isbo-art-resumen__val { color: var(--isbo-accent-strong); }

.isbo-art-resumen__un {
    font-size: 0.625rem;
    color: var(--isbo-text-secondary);
}

/* Variante neutra del badge (Artículo inactivo): sin semántico de peligro, es un estado normal. */
.isbo-badge--inactivo {
    color: var(--isbo-text-secondary);
    background: var(--isbo-surface-alt);
}

/* ── Cabecera del registro de Cliente (Fase 4 maestros, ClienteResumenComponent.razor) ──
   Misma anatomía que .isbo-art-resumen: identidad a la izquierda, KPIs a la derecha.
   Los KPIs usan las clases genéricas .isbo-resumen__kpi* para que el próximo maestro
   (Proveedor) las reutilice sin duplicar. */
.isbo-cli-resumen {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 0.25rem 0 0.625rem;
    border-bottom: 1px solid var(--isbo-border);
}

.isbo-cli-resumen__avatar {
    flex: none;
    width: 3.5rem;
    height: 3.5rem;
    border-radius: 10px;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--isbo-accent-soft);
    color: var(--isbo-accent-strong);
    font-size: 1.25rem;
    font-weight: 700;
    letter-spacing: 0.02em;
}

.isbo-cli-resumen__avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.isbo-cli-resumen__id {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    flex: 1 1 auto;
    min-width: 0;
}

.isbo-cli-resumen__linea {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.75rem;
    min-width: 0;
}

.isbo-cli-resumen__codigo {
    font-family: var(--isbo-font-mono);
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--isbo-accent-strong);
    background: var(--isbo-accent-soft);
    border-radius: 4px;
    padding: 0.15rem 0.5rem;
}

.isbo-cli-resumen__nombre {
    font-size: 1.375rem;
    font-weight: 600;
    line-height: 1.2;
    color: var(--isbo-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
}

.isbo-cli-resumen__sub {
    font-size: 0.8125rem;
    color: var(--isbo-text-secondary);
}

.isbo-cli-resumen__chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.375rem;
}

.isbo-cli-resumen__chip {
    font-size: 0.6875rem;
    font-weight: 600;
    color: var(--isbo-text-secondary);
    background: var(--isbo-surface-alt);
    border-radius: 999px;
    padding: 0.15rem 0.6rem;
    white-space: nowrap;
}

/* KPIs genéricos de cabecera de maestro (valor · caption · texto secundario, a la derecha). */
.isbo-resumen__kpis {
    display: flex;
    flex: none;
    border: 1px solid var(--isbo-border);
    border-radius: 6px;
    overflow: hidden;
}

.isbo-resumen__kpi {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.1rem;
    padding: 0.5rem 1.25rem;
    border-left: 1px solid var(--isbo-border);
    min-width: 8.5rem;
}

.isbo-resumen__kpi:first-child { border-left: 0; }

.isbo-resumen__kpi--accent { background: var(--isbo-accent-soft); }

.isbo-resumen__cap {
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--isbo-text-secondary);
    white-space: nowrap;
}

.isbo-resumen__val {
    font-family: var(--isbo-font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 1.125rem;
    font-weight: 600;
    line-height: 1.2;
    color: var(--isbo-text);
    white-space: nowrap;
}

.isbo-resumen__kpi--accent .isbo-resumen__val { color: var(--isbo-accent-strong); }

.isbo-resumen__sub {
    font-size: 0.625rem;
    color: var(--isbo-text-secondary);
    white-space: nowrap;
}

/* Footer de totales de Compra (Fase 3, 2026-09-08) — variante compacta.
   Aldo pidió el bloque más chico que el de Orden de Compra / Factura, así que va como
   modificador propio en vez de tocar .isbo-totales, que comparten los otros documentos. */
.isbo-totales--sm .isbo-totales__val { font-size: 0.875rem; }
.isbo-totales--sm .isbo-totales__cap { font-size: 0.625rem; }
.isbo-totales--sm .isbo-totales__item--accent { padding: 0.25rem 0.625rem; }

/* Saldo: mismo bloque que el total, en tono secundario. Reemplaza al editor con
   BackColor Yellow del BO — decorado, no crudo. */
.isbo-totales__item--muted {
    border-radius: 4px;
    padding: 0.25rem 0.625rem;
    background: var(--isbo-surface-alt, rgba(127, 127, 140, 0.12));
}

.isbo-totales__item--muted .isbo-totales__cap {
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.isbo-totales__item--muted .isbo-totales__val { font-weight: 600; }


/* ------------------------------------------------------------
   Iconografía (isbo-design §2.3) — colores de marca.

   Los iconos de ImageName llegan como <img src="/IImageService/…">: el SVG se
   recolorea en el SERVIDOR (IconosDeMarca → SvgMarca, en el ImageLoader de XAF)
   porque el CSS del documento no entra en un <img>: azules DX → celeste,
   naranjas/amarillos/violetas → lila, grises/blancos/rojos/verdes intactos. Acá
   queda lo que sí es CSS:
   - Botón primario (Guardar): el icono lleva celeste/lila sobre el acento lila;
     se aclara para que contraste (verificado en el smoke).
   - El sprite propio de DX (funnel, chevrons, "más") sí usa variables públicas
     --dxds-icon-color-*: al secundario, así el chrome fino no lleva color ajeno.
   El tema oscuro sube el brillo de la img en isbo-brand-dark.css.
   Las <img> de XAF llevan dxbl-image + una clase xaf-* según el lugar
   (xaf-toolbar-item-icon, xaf-nav-menu-item-icon, xaf-caption-icon,
   xaf-layout-tab-icon): el atributo las cubre a todas sin enumerarlas.
   ------------------------------------------------------------ */
:root {
    --dxds-icon-color-red: var(--isbo-text-secondary);
    --dxds-icon-color-yellow: var(--isbo-text-secondary);
    --dxds-icon-color-green: var(--isbo-text-secondary);
    --dxds-icon-color-blue: var(--isbo-text-secondary);
    --dxds-icon-color-purple: var(--isbo-text-secondary);
}

.dxbl-btn-primary img.dxbl-image[class*="xaf-"] {
    filter: brightness(1.75) saturate(.55);
}

/* ------------------------------------------------------------
   Lookups (isbo-design §7) — texto plano en reposo, link al hover.

   XAF ya pone color: inherit fuera de hover en a.grid-cell-object-link (celda de
   grilla) y a.combo-box-object-link (DetailView en lectura); lo que quedaba era el
   subrayado permanente, que es el rasgo "XAF de fábrica". La navegación no cambia:
   el hover devuelve subrayado y acento. Mismo patrón que .isbo-receptor__link.
   Los ítems del árbol de navegación también salían subrayados: misma idea.
   ------------------------------------------------------------ */
a.grid-cell-object-link:not(:hover),
a.combo-box-object-link:not(:hover) {
    text-decoration: none;
}

a.grid-cell-object-link:hover,
a.combo-box-object-link:hover {
    text-decoration: underline;
    color: var(--isbo-accent);
}

/* XAF subraya el DIV .xaf-nav-link con (0,3,0) en dos variantes de árbol; :not(:hover)
   en el <a> suma una clase y gana en reposo, y el hover de XAF sigue subrayando. */
.clickable-xaf-nav-item > a:not(:hover) .xaf-nav-link,
.clickable-xaf-nav-item > div > a:not(:hover) .xaf-nav-link {
    text-decoration: none;
}

/* ------------------------------------------------------------
   Navegación sin carpetas (palanca 6 del dictamen 2026-09-10).

   El árbol traía 17 grupos de primer nivel + los anidados, todos con el MISMO
   icono BO_Folder que pone XAF por defecto: 18 carpetas idénticas que no
   informan nada (el chevron ya dice que expande) y que compiten con el icono
   del ítem hoja, que sí identifica la entidad. Es de los rasgos que leen como
   "XAF de fábrica". El grupo pasa a encabezado de sección (versalita, texto
   secundario) y la hoja conserva su icono: la jerarquía se lee sola.

   CÓMO SE DISTINGUE GRUPO DE HOJA (verificado en el DOM, Blazor 26.1):
   el accordion de XAF envuelve la cabecera de un grupo en un DIV
   .dxbl-accordion-item-content y la hoja en un <a href> con esa misma clase.
   Por eso el selector va por div/a y NO por .has-children: los hijos viven
   DENTRO del .xaf-nav-item.has-children, así que un selector por descendencia
   les borraba también su icono (ese fue el primer intento y se cayó en el
   smoke). El ancestro se usa en vez de hijo directo porque el grupo expandido
   mete un nivel intermedio.

   Aplica igual a los subgrupos anidados ("Listados" dentro de Archivo).
   ------------------------------------------------------------ */
div.dxbl-accordion-item-content img.dxbl-image.xaf-nav-menu-item-icon {
    display: none;
}

div.dxbl-accordion-item-content .xaf-nav-link {
    text-transform: uppercase;
    letter-spacing: .06em;
    font-size: 11px;
    color: var(--isbo-text-secondary);
}

/* ------------------------------------------------------------
   Documento Electrónico (Fase 5) — componentes propios:
   Editors/EstadoDEComponent.razor y Editors/TimelineComponent.razor.

   Todo con los tokens --isbo-* de arriba, así que el par claro/oscuro sale
   solo (isbo-brand-dark.css los redefine). Los badges reusan .isbo-badge:
   el estado no elige color, elige TONO — misma regla que las grillas.
   ------------------------------------------------------------ */

/* Cabecera: estado del DE + CDC. */
.isbo-de {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 1.5rem;
    padding: 0.5rem 0 0.75rem;
    border-bottom: 1px solid var(--isbo-border);
}

.isbo-de__estado {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
}

/* Chip de lo ORTOGONAL al ciclo ("Correo enviado"): contorno, sin relleno
   semántico, para que no compita con el badge de estado. */
.isbo-de__chip {
    display: inline-flex;
    align-items: center;
    padding: 0.15em 0.6em;
    border: 1px solid var(--isbo-border);
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--isbo-text-secondary);
    white-space: nowrap;
}

.isbo-de__campo {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    min-width: 0;
}

.isbo-de__cap {
    font-size: 0.75rem;
    color: var(--isbo-text-secondary);
    white-space: nowrap;
}

/* El CDC se parte en 11 bloques y va en mono: sin ancho fijo por carácter los
   bloques no se alinean y agruparlos no sirve de nada. Se deja seleccionable
   y con word-break para que no desborde en pantallas angostas. */
.isbo-de__cdc {
    font-size: 0.8125rem;
    letter-spacing: .02em;
    word-break: break-all;
    user-select: all;
}

/* Línea de tiempo: fusión de las colecciones hijas del documento. */
.isbo-timeline {
    list-style: none;
    margin: 0;
    padding: 0.5rem 0 0;
}

/* La guía vertical es un borde sobre la fila, no un pseudo-elemento sobre la
   lista: así arranca y termina con las filas y no sobra por debajo de la última. */
.isbo-timeline__fila {
    position: relative;
    display: flex;
    gap: 0.75rem;
    padding: 0 0 0.9rem 0;
}

.isbo-timeline__fila::before {
    content: "";
    position: absolute;
    left: 0.3125rem; /* centro del punto (0.625rem / 2) */
    top: 0.9rem;
    bottom: 0;
    width: 1px;
    background: var(--isbo-border);
}

.isbo-timeline__fila:last-child::before {
    display: none;
}

.isbo-timeline__punto {
    flex: none;
    width: 0.625rem;
    height: 0.625rem;
    margin-top: 0.3rem;
    border-radius: 50%;
    background: var(--isbo-text-secondary);
    /* Anillo del color del fondo para que el punto tape la guía vertical. */
    box-shadow: 0 0 0 2px var(--isbo-surface);
    z-index: 1;
}

.isbo-timeline__punto--info { background: var(--isbo-info); }
.isbo-timeline__punto--exito { background: var(--isbo-success); }
.isbo-timeline__punto--advertencia { background: var(--isbo-warning); }
.isbo-timeline__punto--peligro { background: var(--isbo-danger); }

.isbo-timeline__cuerpo {
    min-width: 0;
    flex: 1;
}

.isbo-timeline__cabecera {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem 0.6rem;
}

.isbo-timeline__titulo {
    font-weight: 600;
    color: var(--isbo-text);
}

.isbo-timeline__codigo {
    font-family: var(--isbo-font-mono);
    font-size: 0.75rem;
    color: var(--isbo-text-secondary);
}

.isbo-timeline__fecha {
    font-size: 0.75rem;
    color: var(--isbo-text-secondary);
    margin-left: auto;
    white-space: nowrap;
}

/* dMsgRes puede traer el mensaje crudo del web service, largo y sin cortes. */
.isbo-timeline__detalle {
    font-size: 0.8125rem;
    color: var(--isbo-text-secondary);
    margin-top: 0.15rem;
    overflow-wrap: anywhere;
}

.isbo-timeline__vacio {
    font-size: 0.8125rem;
    color: var(--isbo-text-secondary);
    padding: 1rem 0;
}
