/* =============================================================================
   PEDIDOS & VENTAS — identidad visual. Scope `.vt-ui`.
   =============================================================================
   docs/RUNBOOK-VENTAS.md. Dos rondas de mockups cerradas el 22/08/2026:
     · ronda 1: ganó la A, «el pedido, de punta a punta» — UNA mesa con tres
       segmentos (Pendientes · En carga · Cumplidos), una fila por pedido;
     · ronda 2: ganó la 1, «Capas con un solo azul».

   ── EL TRATAMIENTO, y por qué ────────────────────────────────────────────────
   CAPAS (manual §1.2), el del ABM: lienzo más oscuro que el del resto
   (#e6ebf3) y la jerarquía puesta por la ELEVACIÓN —tres sombras para tres
   planos— y no por el contraste ni por un segundo color. Lo pidió Hernán,
   textual: «es importante que tengan color las pantallas, los modales con
   jerarquías, que no queden "planos"; respetar también las animaciones de la
   identidad». Los tres planos:
       --e1  la barra de secciones, los segmentos, las cifras de la tira
       --e2  los grupos de NP (etapa 2)
       --e3  el modal sobre el velo (etapa 3)

   ACENTO: NAVY Y NADA MÁS. La ronda 2 puso a votar un `--azure` propio como el
   del ABM y perdió: navy es estructura Y acción, y lo que separa los planos es
   la sombra. Acá no se declara ningún token de acento. Si alguien lo agrega,
   está deshaciendo una decisión tomada.

   LOS DOS APARTAMIENTOS de core/tokens.css, con su porqué:
     · `--canvas` — el lienzo oscuro de Capas. Sin él ninguna de las tres
       sombras se ve, porque el blanco de una tarjeta no despega de #f1f2f5.
     · `--r-card: 12px` — como en el ABM: las tarjetas de acá son muchas y
       chicas (cifras, grupos de NP, chips). Con 14 se ven infladas.
   Todo lo demás sale de tokens.css.

   ── LO QUE MUERE ─────────────────────────────────────────────────────────────
   El módulo se saltaba el armazón entero: un `fixed inset-0` con un sidebar
   PROPIO de 256 px y seis botones, dos entradas del menú al mismo lugar, once
   familias de color en `ventas-pendientes.js` y un acento índigo que no es de
   GS. La etapa 1 lo mete adentro del armazón: el rail del sistema, la barra
   superior con contexto y acciones (`shell.js`), y una barra de secciones
   horizontal. El color de adentro (las once familias) se va pantalla por
   pantalla, etapas 2 a 8.

   ── ORDEN DE LAS SECCIONES ───────────────────────────────────────────────────
    1. EL ARMAZÓN — la raíz, la barra de secciones, los segmentos, el área
    2. EL MOVIMIENTO — el vocabulario del §5, construido acá y medido por el banco
    3. LOS BOTONES — `.vt-btn` (lo usan las etapas 2 a 8; acá se define una vez)
    4. LA ESPERA Y EL ERROR — lo que se ve mientras una vista carga o se cae
    5. EL TELÉFONO ANGOSTO — 390 px
    6. LA LISTA — la mesa única (etapa 2): tira, filtros, tabla, grupos por NP, pie
   ============================================================================= */

.vt-ui {
    --canvas: #e6ebf3;
    --r-card: 12px;
}

/* =============================================================================
   1. EL ARMAZÓN
   =============================================================================
   EL SCOPE VA EN UN <div> HIJO de `#page-ventas`, no en el propio `.page-content`
   (como Órdenes, el ABM y Configuración): `#page-ventas` se oculta con el
   `.hidden` de Tailwind, que es UNA clase, y cualquier regla del módulo que
   declarara `display` sobre ese mismo elemento le ganaría.

   Y VA COMO COMPUESTO, `.vt-ui.vt-shell`, SIN ESPACIO: las dos clases están en
   el MISMO elemento. Con espacio no matchea nada y el bloque se cae EN
   SILENCIO: el armazón mide lo que mide su contenido, flota sobre medio lienzo
   y no scrollea. Es la trampa del §4 del RUNBOOK-NUEVA-IDENTIDAD; el banco de
   navegación la reinyecta con `--romperlo`.

   EL CANDADO DE ABAJO SE QUEDA aunque hoy nadie esconda este <div>: dos clases
   (0,2,0) contra una (0,1,0). Protege al próximo que lo haga. */
.vt-ui.vt-shell {
    display: flex; flex-direction: column;
    height: 100%; min-height: 0; min-width: 0;
    background: var(--canvas);
}
.vt-ui.vt-shell.hidden { display: none; }

.vt-ui .material-symbols-outlined { font-size: 18px; line-height: 1; vertical-align: -4px; }
.vt-ui :focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; border-radius: 5px; }

/* ── La barra de secciones — plano 1 ──────────────────────────────────────────
   Pedidos · Pre-cargas (Importar OC murió en la etapa 2: «no se usa»). Son las
   DOS cosas distintas que hace el módulo; lo que NO es una sección son
   Pendientes / En carga / Cumplidos, que comparten documento y son un FILTRO
   (manual §7): viven en los segmentos de abajo.

   El rol decide cuántas se dibujan: Logística (2 y 3) ve sólo Pedidos. La
   barra se dibuja igual, con una, porque la cola de la derecha dice en qué
   ámbito estás y porque una barra que aparece y desaparece según el rol es
   estado invisible. */
.vt-ui .vt-secnav {
    background: var(--surface);
    box-shadow: var(--e1);
    position: relative; z-index: 1;
    display: flex; align-items: stretch; gap: 2px;
    padding: 0 var(--gutter); flex-wrap: wrap;
    flex: 0 0 auto;
}
.vt-ui .vt-secnav > button {
    position: relative; background: none; border: 0;
    font: inherit; font-size: 12.8px; font-weight: 600; color: var(--muted);
    padding: 12px 15px 13px; cursor: pointer;
    display: inline-flex; align-items: center; gap: 7px; white-space: nowrap;
    transition: color .14s ease, background .14s ease;
}
.vt-ui .vt-secnav > button .material-symbols-outlined {
    font-size: 18px; transition: transform .18s var(--curva);
}
/* Un `border-bottom` no se puede animar (manual §7): va un ::after con scaleX
   que CRECE DESDE EL CENTRO. El banco lo mide en el fotograma del medio. */
.vt-ui .vt-secnav > button::after {
    content: ''; position: absolute; left: 10px; right: 10px; bottom: 0;
    height: 2.5px; background: var(--navy); border-radius: 2px 2px 0 0;
    transform: scaleX(0); transform-origin: center;
    transition: transform .18s var(--curva);
}
.vt-ui .vt-secnav > button:hover,
.vt-ui .vt-secnav > button:focus-visible {
    color: var(--navy); background: var(--navy-050); outline: none;
}
.vt-ui .vt-secnav > button:hover::after,
.vt-ui .vt-secnav > button:focus-visible::after { transform: scaleX(.55); }
.vt-ui .vt-secnav > button:hover .material-symbols-outlined { transform: translateY(-2px); }
/* La sección activa se marca por `aria-current` Y por `.on`: el atributo lo
   leen el lector de pantalla y el banco; la clase, la que pinta. */
.vt-ui .vt-secnav > button.on,
.vt-ui .vt-secnav > button[aria-current="true"] { color: var(--navy); font-weight: 700; }
.vt-ui .vt-secnav > button.on::after,
.vt-ui .vt-secnav > button[aria-current="true"]::after { transform: scaleX(1); }

/* El contador de una sección (Importar OC: cuántas OC esperan). `null` NO ES
   CERO: mientras no se contó, se dibuja invisible pero ocupando su lugar. */
.vt-ui .vt-secnav .cnt {
    font-size: 11px; font-weight: 700; font-variant-numeric: tabular-nums;
    background: var(--navy-050); color: var(--navy-500);
    border-radius: 20px; padding: 1px 8px; min-width: 22px; text-align: center;
    transition: background .14s ease, color .14s ease, opacity .14s ease;
}
.vt-ui .vt-secnav > button.on .cnt { background: var(--navy); color: #fff; }
.vt-ui .vt-secnav .cnt.esperando { opacity: 0; }

/* La cola: el ámbito que el rol decidió. Texto, no un control. */
.vt-ui .vt-secnav .tail {
    margin-left: auto; display: flex; align-items: center; gap: 9px;
    font-size: 12px; color: var(--muted); white-space: nowrap;
}
.vt-ui .vt-secnav .tail b { font-weight: 700; color: var(--ink); }

/* ── Los segmentos — el filtro sobre la mesa única ────────────────────────────
   Pendientes · En carga · Cumplidos. Chips blancos en plano 1 que SUBEN 2 px al
   apuntarlos; el activo lleva borde y fondo navy-050. En la etapa 1 cada uno
   monta todavía la pantalla vieja que le corresponde; la etapa 2 los funde en
   un solo render.

   Se dibujan sólo cuando la vista ES uno de los tres: en «Nuevo pedido» y en
   Pre-cargas el contenedor lleva `.hidden`.

   OJO CON EL CANDADO DE ABAJO, QUE FALTABA. El `.hidden` global de tokens.css
   está scopeado a `.stk-ui` —el módulo de Stock—, y acá el scope es `.vt-ui`:
   no llegaba. Y aunque llegara, `.hidden` es UNA clase (0,1,0) contra
   `.vt-ui .vt-seg` (0,2,0), que declara `display: flex`. O sea que poner
   `.hidden` sobre este <div> no lo escondía: la barra se quedaba dibujada y
   nadie avisaba. Es la trampa §7 del manual, otra vez. */
.vt-ui .vt-seg {
    display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
    padding: 14px var(--gutter) 0;
    flex: 0 0 auto;
}
.vt-ui .vt-seg > button {
    display: inline-flex; align-items: center; gap: 6px;
    border: 1px solid var(--hair-strong); background: var(--surface);
    border-radius: 20px; padding: 6px 13px;
    font: inherit; font-size: 12px; font-weight: 600; color: var(--muted);
    cursor: pointer; white-space: nowrap;
    box-shadow: var(--e1);
    transition: color .14s ease, background .14s ease, border-color .14s ease,
                box-shadow .18s var(--curva), transform .18s var(--curva);
}
.vt-ui .vt-seg > button .cnt {
    font-size: 11px; color: var(--faint); font-variant-numeric: tabular-nums;
}
.vt-ui .vt-seg > button .cnt.esperando { display: none; }
.vt-ui .vt-seg > button:hover,
.vt-ui .vt-seg > button:focus-visible {
    color: var(--navy); border-color: var(--navy-300);
    transform: translateY(-2px); box-shadow: 0 5px 14px rgba(16, 32, 64, .14);
    outline: none;
}
.vt-ui .vt-seg > button:active { transform: translateY(0); box-shadow: var(--e1); }
.vt-ui .vt-seg > button.on,
.vt-ui .vt-seg > button[aria-pressed="true"] {
    color: var(--navy); border-color: var(--navy); background: var(--navy-050); font-weight: 700;
}
.vt-ui .vt-seg > button.on .cnt { color: var(--navy); }
/* El candado. Dos clases contra dos clases, y ésta va DESPUÉS: gana. */
.vt-ui .vt-seg.hidden { display: none; }

/* ── El área de trabajo ───────────────────────────────────────────────────────
   Lo que cada vista dibuja va acá adentro. Hasta que cada etapa la repinte, la
   vista vieja sigue con su Tailwind y con su `h-full`: por eso esto es un flex
   en columna con `min-height: 0` —un `flex: 1` sin él estira en vez de
   scrollear— y con `overflow: hidden`, para que el scroll lo maneje la vista.
   `position: relative` es para las superficies absolutas que la etapa 2 apoya
   acá (el esqueleto, la barra de selección). */
.vt-ui .vt-work {
    flex: 1; min-height: 0; min-width: 0;
    display: flex; flex-direction: column;
    overflow: hidden; position: relative;
}
/* Mientras las vistas sigan en Tailwind, su primer hijo lleva `h-full`; un
   flex en columna se lo resuelve. */
.vt-ui .vt-work > * { flex: 1; min-height: 0; }

/* =============================================================================
   2. EL MOVIMIENTO — §5 del manual, portado literal de rrhh-ui.css / abm-ui.css
   =============================================================================
     · una sola curva para todo lo que se desplaza — var(--curva);
     · .14s ease para color y fondo, .18s para transformaciones;
     · nada se mueve más de 2 px: el gesto confirma que apuntaste algo;
     · el botón sube 2 px con sombra; al presionar vuelve a cero;
     · el subrayado de una sección crece desde el centro;
     · prefers-reduced-motion lo apaga todo, de una.
   Las reglas viven al lado de cada pieza (arriba y abajo); acá sólo el
   interruptor. */
@media (prefers-reduced-motion: reduce) {
    .vt-ui * { transition: none !important; animation: none !important; }
}

/* =============================================================================
   3. LOS BOTONES — `.vt-btn`
   =============================================================================
   Se definen UNA vez, acá, para las etapas 2 a 8. Primario navy con sombra de
   plano 1; `sec` blanco con borde; `gh` fantasma; `ok` y `danger` sólo cuando el
   verbo es ése (despachar / anular), nunca para decorar. La etapa 1 no dibuja
   ninguno en pantalla: los botones de arriba son los de la barra del armazón
   (`shell-act`). */
.vt-ui .vt-btn {
    display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
    border-radius: 8px; padding: 7px 14px;
    font: inherit; font-size: .79rem; font-weight: 700; cursor: pointer;
    border: 1px solid var(--navy); background: var(--navy); color: #fff;
    box-shadow: var(--e1);
    transition: background .14s ease, border-color .14s ease, color .14s ease,
                box-shadow .18s var(--curva), transform .18s var(--curva);
}
.vt-ui .vt-btn .material-symbols-outlined { font-size: 17px; }
.vt-ui .vt-btn:hover:not(:disabled) {
    background: var(--navy-700); border-color: var(--navy-700);
    transform: translateY(-2px); box-shadow: 0 6px 16px rgba(0, 43, 107, .28);
}
.vt-ui .vt-btn:active:not(:disabled) { transform: translateY(0); box-shadow: var(--e1); }
.vt-ui .vt-btn:disabled { opacity: .45; cursor: default; transform: none; box-shadow: none; }

.vt-ui .vt-btn.sec { background: var(--surface); color: var(--navy); border-color: var(--hair-strong); }
.vt-ui .vt-btn.sec:hover:not(:disabled) { background: var(--navy-050); border-color: var(--navy-300); color: var(--navy); }

.vt-ui .vt-btn.gh { background: transparent; color: var(--muted); border-color: var(--hair); box-shadow: none; padding: 7px 11px; }
.vt-ui .vt-btn.gh:hover:not(:disabled) { background: var(--navy-050); border-color: var(--hair-strong); color: var(--navy); box-shadow: 0 4px 12px rgba(16, 32, 64, .10); }

.vt-ui .vt-btn.ok { background: var(--ok); border-color: var(--ok); }
.vt-ui .vt-btn.ok:hover:not(:disabled) { background: #0b5c3e; border-color: #0b5c3e; box-shadow: 0 6px 16px rgba(15, 122, 82, .28); }
.vt-ui .vt-btn.danger { background: var(--crit); border-color: var(--crit); }
.vt-ui .vt-btn.danger:hover:not(:disabled) { background: #a71f1f; border-color: #a71f1f; box-shadow: 0 6px 16px rgba(198, 40, 40, .28); }

/* Chico: el de una fila o de un pie. */
.vt-ui .vt-btn.chico { padding: 4px 10px; font-size: .74rem; border-radius: 7px; }

/* =============================================================================
   4. LA ESPERA Y EL ERROR
   =============================================================================
   La espera la dibuja `gsZonaCargando()` (core/ui.js): el anillo del sistema
   mientras la vista vieja trae lo suyo —no tiene forma previsible todavía; el
   esqueleto con la forma de la tabla entra con la etapa 2, cuando la lista sea
   una—. Acá sólo se centra en el área. */
.vt-ui .vt-work[aria-busy="true"] { align-items: center; justify-content: center; }
.vt-ui .vt-work[aria-busy="true"] > * { flex: 0 0 auto; }

/* Una vista que se cayó al montar. Dice qué pasó y qué hacer: el cartel viejo
   era texto rojo suelto en el medio. */
.vt-ui .vt-error {
    margin: var(--gutter); padding: 16px 18px;
    background: var(--surface); border-radius: var(--r-card);
    border: 1px solid var(--crit-hair); border-left: 3px solid var(--crit);
    box-shadow: var(--e1); color: var(--ink); font-size: 13px;
    flex: 0 0 auto;
}
.vt-ui .vt-error b { color: var(--crit); display: block; margin-bottom: 4px; }
.vt-ui .vt-error code { font-family: 'IBM Plex Mono', Consolas, monospace; font-size: 12px; color: var(--muted); }

/* =============================================================================
   5. EL TELÉFONO ANGOSTO — 390 px
   =============================================================================
   El teléfono de verdad entra por `ventas-mobile.js`, fuera de alcance. Esto es
   para que la foto del banco a 390 no mienta: la barra de secciones envuelve,
   la cola baja de renglón y los segmentos scrollean de costado en vez de
   apilarse. */
@media (max-width: 640px) {
    .vt-ui .vt-secnav { padding: 0 12px; }
    .vt-ui .vt-secnav > button { padding: 10px 10px 11px; font-size: 12.2px; }
    .vt-ui .vt-secnav .tail { margin-left: 0; flex-basis: 100%; padding: 0 4px 8px; }
    .vt-ui .vt-seg { padding: 10px 12px 0; flex-wrap: nowrap; overflow-x: auto; }
    .vt-ui .vt-seg .tail { flex: 0 0 auto; }
}

/* =============================================================================
   6. LA LISTA — la mesa única, etapa 2
   =============================================================================
   Un solo vocabulario para los tres segmentos: la tira de cifras (plano 1), la
   fila de filtros, la caja de la tabla (plano 1) o los grupos por NP (plano 2),
   el pie con conteo. El color dice ESTADO: navy lo vivo, ámbar lo que falta,
   rojo lo que frena, verde lo cumplido; y lo dice con PALABRA en el chip y con
   una franja de 3 px al margen de la fila.

   LA FILA MIDE 48 px, FIJO. No es capricho: el esqueleto de Pendientes declara
   ese alto (`formaPendientes()` en ventas-lista.js) y el manual §5 exige que sea
   el alto REAL de la fila que viene, medido y no estimado. Si una celda crece
   (dos renglones), la fila sigue midiendo 48: las dos líneas entran. */
/* EL SCROLL LO HACE LA LISTA, NO LA MESA. Y esto es un arreglo, no un gusto.
   Con `overflow: auto` acá la mesa parecia el scroller, pero no lo era: los
   cuatro hijos son flex y `.vt-lista` es el unico que encoge (`flex: 1 1 auto`
   con `min-height: 0`), asi que absorbia TODO el sobrante y los cuatro entraban
   justos. La mesa no tenia nada que scrollear... y la lista, sin `overflow`
   propio, derramaba su contenido FUERA de su caja. Medido el 24/08/2026 con la
   estructura real: caja de 376 px, contenido de 1920, y 32 filas pintadas por
   DEBAJO del pie —que es opaco y va despues en el DOM, asi que las tapa—.
   Se veia como que «el pie corta la lista y el scroll no baja mas».
   Con el scroll en la lista: la tira, los filtros y el pie se quedan quietos
   —que es lo que el pie quiere ser, un pie que cuenta lo que se ve— y solo las
   filas corren. Probado: la ultima fila entra entera. */
.vt-ui .vt-mesa {
    flex: 1; min-height: 0; min-width: 0;
    display: flex; flex-direction: column; gap: 13px;
    padding: 16px var(--gutter) 18px;
    overflow: hidden;
}
.vt-ui .sin { color: var(--faint); font-style: italic; font-weight: 400; }
.vt-ui .tnum { font-variant-numeric: tabular-nums; }

/* ── La tira de cifras — plano 1 ──────────────────────────────────────────────
   Cinco tarjetas, a tamaño ABM (25 px, no más: §3.8 del manual). La franja
   izquierda y el fondo teñido dicen de qué habla la cifra: navy lo vivo, ámbar
   lo que envejece, rojo lo que frena. Una cifra que todavía no se leyó se
   dibuja como «—» y baja la opacidad: null no es cero. */
.vt-ui .vt-tira {
    display: grid; grid-template-columns: repeat(5, 1fr); gap: 12px;
    flex: 0 0 auto;
}
.vt-ui .vt-kpi {
    background: var(--surface); border-radius: var(--r-card);
    padding: 12px 15px; position: relative; overflow: hidden;
    box-shadow: var(--e1); border: 1px solid rgba(16, 32, 64, .05);
    border-left: 3px solid var(--hair-strong);
    min-width: 0;
}
.vt-ui .vt-kpi .k { font-size: 10.5px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vt-ui .vt-kpi .v { font-size: 25px; font-weight: 700; letter-spacing: -.02em; margin-top: 4px; line-height: 1.1; color: var(--ink); transition: opacity .14s ease; }
.vt-ui .vt-kpi .v.esperando { opacity: .3; }
.vt-ui .vt-kpi .x { font-size: 11.5px; color: var(--muted); margin-top: 3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vt-ui .vt-kpi.nav { border-left-color: var(--navy); }
.vt-ui .vt-kpi.nav .v { color: var(--navy); }
.vt-ui .vt-kpi.wrn { border-left-color: var(--warn); background: linear-gradient(180deg, var(--warn-050), var(--surface) 62%); }
.vt-ui .vt-kpi.wrn .v { color: var(--warn); }
.vt-ui .vt-kpi.neg { border-left-color: var(--crit); }
.vt-ui .vt-kpi.neg .v { color: var(--crit); }

/* ── Los filtros ──────────────────────────────────────────────────────────────
   El buscador, los dos selectores inteligentes (cliente, artículo) y —sólo en
   Cumplidos— el rango de fechas. El selector inteligente es un servicio
   compartido con su propio Tailwind adentro (`.smart-container-styled`): acá
   sólo se le da su caja; repintarlo es de otro frente. */
.vt-ui .vt-filtros { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; flex: 0 0 auto; }
.vt-ui .vt-busca {
    display: flex; align-items: center; gap: 7px;
    background: var(--surface); border: 1px solid var(--hair-strong); border-radius: 8px;
    padding: 0 10px; min-width: 300px; flex: 1 1 300px; max-width: 520px;
    box-shadow: var(--e1); color: var(--muted);
    transition: border-color .14s ease, box-shadow .18s var(--curva);
}
.vt-ui .vt-busca:focus-within { border-color: var(--navy-300); box-shadow: 0 0 0 3px var(--navy-050); }
.vt-ui .vt-busca input {
    flex: 1; min-width: 0; border: 0; background: none; font: inherit; font-size: 12.8px; color: var(--ink);
    padding: 8px 0; outline: none;
}
.vt-ui .vt-busca input::placeholder { color: var(--faint); }
.vt-ui .vt-f-smart { flex: 0 1 240px; min-width: 180px; }
/* El rango de Cumplidos es UNA sola cosa: las dos fechas y sus verbos se
   mueven juntos. Sueltos dentro del flex de filtros se partian al medio
   (probado en vivo, 24/08/2026). */
.vt-ui .vt-f-rango { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.vt-ui .vt-fecha { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); }
.vt-ui .vt-fecha input {
    font: inherit; font-size: 12.5px; color: var(--ink);
    border: 1px solid var(--hair-strong); border-radius: 8px; padding: 6px 9px; background: var(--surface);
    box-shadow: var(--e1);
}
.vt-ui .vt-fecha input:focus { outline: none; border-color: var(--navy-300); box-shadow: 0 0 0 3px var(--navy-050); }

/* ── La caja y la tabla — plano 1 ─────────────────────────────────────────────
   La lista scrollea adentro de la mesa; la cabecera se queda pegada arriba. */
/* El `padding` horizontal con su `margin` negativo no mueve nada: le da 4 px de
   aire al recorte para que `--e1` (0 1px 2px) no salga cortada al ras en los
   costados de las tarjetas de grupo. Arriba y abajo no hace falta: ahi la
   sombra queda donde el contenido scrollea. */
.vt-ui .vt-desc { color: var(--muted); }
.vt-ui .vt-lista { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding-inline: 4px; margin-inline: -4px; }
.vt-ui .vt-lista[aria-busy="true"] { background: var(--surface); border-radius: var(--r-card); box-shadow: var(--e1); padding: 6px 0; }
.vt-ui .vt-lista[aria-busy="true"] th { font-size: 10.5px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--faint); padding: 11px 10px; border-bottom: 2px solid var(--hair-strong); text-align: left; }
.vt-ui .vt-lista[aria-busy="true"] th.num { text-align: right; }
.vt-ui .vt-caja {
    background: var(--surface); border-radius: var(--r-card);
    box-shadow: var(--e1); border: 1px solid rgba(16, 32, 64, .05);
    overflow: auto;
}
/* `separate` y no `collapse`: con bordes colapsados, el borde de 2 px de la
   cabecera se reparte con la primera fila y esa fila mide 49 en vez de 48 — un
   pixel que el esqueleto no prometio. Con `separate` cada celda es dueña de su
   borde y `height: 48px` con border-box es exacto. */
.vt-ui table.vt-tabla { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 12.5px; table-layout: fixed; color: var(--ink); }
.vt-ui table.vt-tabla th {
    text-align: left; font-size: 10.5px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
    color: var(--faint); background: var(--surface); padding: 11px 10px;
    border-bottom: 2px solid var(--hair-strong); white-space: nowrap;
    position: sticky; top: 0; z-index: 1;
}
.vt-ui table.vt-tabla td {
    padding: 4px 10px; height: 48px; box-sizing: border-box;
    border-bottom: 1px solid var(--hair); vertical-align: middle;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    line-height: 1.35;
}
.vt-ui table.vt-tabla tr:last-child td { border-bottom: 0; }
.vt-ui table.vt-tabla th.n, .vt-ui table.vt-tabla td.n { text-align: right; }
.vt-ui table.vt-tabla td.ord { font-weight: 700; color: var(--navy); font-family: 'IBM Plex Mono', Consolas, monospace; font-size: 12px; }
.vt-ui table.vt-tabla tbody tr { cursor: pointer; transition: background .14s ease; }
.vt-ui table.vt-tabla tbody tr:hover td { background: var(--navy-050); }
.vt-ui table.vt-tabla tbody tr.pausada td { opacity: .62; }
.vt-ui table.vt-tabla tbody tr.pausada td.vt-acr { opacity: 1; }
.vt-ui .vt-cli { display: flex; align-items: center; gap: 6px; min-width: 0; }
/* El número de pedido perdió su columna (24/08/2026): identifica al cliente, no
   es un dato para comparar entre filas. Va delante del nombre, en mono y navy,
   y NO se encoge —`flex: none`—: si el nombre es largo se corta el NOMBRE, que
   se lee entero en el `title`; el número nunca, porque es con lo que se busca. */
.vt-ui .vt-cli .vt-np { flex: none; font-weight: 700; color: var(--navy); font-size: 11.5px; }
.vt-ui .vt-cli b { font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vt-ui .vt-sub { display: block; font-size: 11px; line-height: 15px; height: 15px; color: var(--faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Los kilos, en el renglón de abajo de «Qué sale»: perdieron su columna pero
   NO su peso visual —son el número por el que se arma una carga—. */
.vt-ui .vt-sub .vt-kg { font-size: 12.5px; font-weight: 700; color: var(--ink); }
.vt-ui .vt-mas { font-size: 10px; font-weight: 700; color: var(--muted); background: var(--canvas); border: 1px solid var(--hair-strong); border-radius: 4px; padding: 0 5px; }
.vt-ui .vt-log { font-size: 12px; }

/* La franja de estado: 3 px al margen izquierdo de la fila, el mismo color que
   la palabra del chip. Una fila con ALERTA crítica lleva la franja roja aunque
   su estado sea otro: lo que frena gana. */
.vt-ui table.vt-tabla td.fr { position: relative; padding-left: 16px; }
.vt-ui table.vt-tabla td.fr::before {
    content: ''; position: absolute; left: 6px; top: 6px; bottom: 6px; width: 3px; border-radius: 2px;
    background: var(--hair-strong);
}
.vt-ui tr.e-aut td.fr::before     { background: var(--navy-300); }
.vt-ui tr.e-carga td.fr::before   { background: var(--navy); }
.vt-ui tr.e-cart td.fr::before    { background: var(--hair-strong); }
.vt-ui tr.e-pausado td.fr::before { background: var(--hair-strong); }
.vt-ui tr.e-fin td.fr::before     { background: var(--ok); }
.vt-ui tr.e-cargada td.fr::before { background: var(--warn); }
.vt-ui tr.alerta td.fr::before    { background: var(--crit); }

/* El chip de estado: palabra en mayúsculas chicas, borde del mismo tono. */
.vt-ui .vt-b {
    display: inline-block; font-size: 10.5px; font-weight: 700; letter-spacing: .03em;
    padding: 2px 8px; border-radius: 5px; border: 1px solid; text-transform: uppercase; white-space: nowrap;
    max-width: 100%; overflow: hidden; text-overflow: ellipsis; vertical-align: middle;
}
.vt-ui .vt-b.nav { background: var(--navy-050); color: var(--navy-500); border-color: #cfdcf1; }
/* `crit` FALTABA, y era el más urgente de todos. El chip «carga hoy» de la
   banda del día lo usaba desde la etapa 8 y caía al `.vt-b` pelado: borde gris
   y sin fondo, o sea que el estado MÁS urgente era el ÚNICO sin color. Se vio
   el 24/08/2026 al bajar ese chip a la fila, donde quedó al lado de «MAÑANA»
   —que sí era ámbar— y la comparación lo delató. */
.vt-ui .vt-b.crit { background: var(--crit-050); color: var(--crit); border-color: var(--crit-hair); }
.vt-ui .vt-b.wrn { background: var(--warn-050); color: var(--warn); border-color: var(--warn-hair); }
.vt-ui .vt-b.ok  { background: var(--ok-050);   color: var(--ok);   border-color: var(--ok-hair); }
.vt-ui .vt-b.mut { background: #f4f6f9; color: var(--faint); border-color: var(--hair-strong); }
/* En Pendientes, para el que puede cargar, el chip es un <button>: el
   interruptor de la pausa. Mismo dibujo; al apuntarlo se oscurece el borde. */
.vt-ui button.vt-b { font: inherit; font-size: 10.5px; font-weight: 700; letter-spacing: .03em; cursor: pointer; transition: border-color .14s ease, box-shadow .18s var(--curva); }
.vt-ui button.vt-b:hover { border-color: var(--navy); box-shadow: 0 2px 6px rgba(16, 32, 64, .14); }

/* La antigüedad: un número; pasado el umbral, ámbar y en negrita. */
.vt-ui .vt-edad { font-size: 11.5px; color: var(--muted); }
.vt-ui .vt-edad.vieja { color: var(--warn); font-weight: 700; }

/* La tarifa del flete: verde firme, ámbar falta, rojo falta y carga HOY. */
.vt-ui .vt-tar { font-weight: 700; }
.vt-ui .vt-tar.ok { color: var(--ok); }
.vt-ui .vt-tar.wrn { color: var(--warn); }
.vt-ui .vt-tar.crit { color: var(--crit); background: var(--crit-050); border: 1px solid var(--crit-hair); border-radius: 4px; padding: 0 5px; }

/* EL AVISO ES UNA MARCA, NO UN CARTEL (24/08/2026). Antes escribía «Alerta:»
   con el texto entero AL LADO del cliente y ocupando el renglón del destino: se
   cortaba a la mitad —«Alerta: ENVIAR 3 DIAS ANTES AL M…»— y encima dejaba al
   destino sin dónde decirse. Ahora dice «Aviso» y ya está: el texto entero se
   lee en el `title` y en la ficha, y el destino recupera su renglón. */
.vt-ui .vt-alerta {
    display: inline-flex; align-items: center; gap: 4px; vertical-align: top;
    height: 15px; line-height: 13px; box-sizing: border-box;
    font-size: 10.5px; font-weight: 700; color: var(--crit);
    background: var(--crit-050); border: 1px solid var(--crit-hair); border-radius: 4px; padding: 0 6px;
    flex: none; white-space: nowrap;
}
.vt-ui .vt-alerta .material-symbols-outlined { font-size: 13px; }

/* Las acciones de la fila: con rótulo, chicas, a la derecha. Suben 1 px al
   apuntarlas (el gesto del §5, a escala de fila). `peligro` para eliminar y
   anular, `cierre` para pausar y devolver, `ok` para despachar, `falta` para
   la logística que todavía no está. */
.vt-ui .vt-acr { display: flex; gap: 5px; justify-content: flex-end; align-items: center; flex-wrap: nowrap; }
.vt-ui td.vt-acr { overflow: visible; }
.vt-ui .vt-min {
    font: inherit; font-size: 11px; font-weight: 600; color: var(--navy); white-space: nowrap;
    border: 1px solid var(--hair-strong); border-radius: 6px; padding: 3px 7px; background: var(--surface);
    cursor: pointer; line-height: 1.3;
    transition: background .14s ease, border-color .14s ease, color .14s ease, transform .18s var(--curva), box-shadow .18s var(--curva);
}
.vt-ui .vt-min:hover { background: var(--navy-050); border-color: var(--navy-300); transform: translateY(-1px); box-shadow: 0 3px 8px rgba(16, 32, 64, .12); }
.vt-ui .vt-min:active { transform: translateY(0); box-shadow: none; }
.vt-ui .vt-min.peligro { color: var(--crit); border-color: var(--crit-hair); }
.vt-ui .vt-min.peligro:hover { background: var(--crit-050); border-color: var(--crit); }
.vt-ui .vt-min.cierre { color: var(--warn); border-color: var(--warn-hair); }
.vt-ui .vt-min.cierre:hover { background: var(--warn-050); border-color: var(--warn); }
.vt-ui .vt-min.falta { color: var(--warn); border-color: var(--warn-hair); background: var(--warn-050); }
.vt-ui .vt-min.falta:hover { border-color: var(--warn); }
.vt-ui .vt-min.ok { color: #fff; background: var(--ok); border-color: var(--ok); }
.vt-ui .vt-min.ok:hover { background: #0b5c3e; border-color: #0b5c3e; }

/* ── Los grupos por NP — plano 2 ──────────────────────────────────────────────
   Cada NP es una tarjeta con sombra de plano 2 (más alta que la caja de la
   tabla: es una cosa, con sus verbos), la cabecera del viaje arriba y los
   pedidos en una tabla adentro. A la que le falta algo para salir se le pinta
   la franja ámbar. */
.vt-ui .vt-grp {
    background: var(--surface); border-radius: 13px; overflow: hidden;
    box-shadow: var(--e2); border: 1px solid rgba(16, 32, 64, .05);
    border-left: 3px solid var(--navy);
}
.vt-ui .vt-grp + .vt-grp { margin-top: 10px; }
.vt-ui .vt-grp.falta { border-left-color: var(--warn); }
.vt-ui .vt-grp-h {
    display: flex; align-items: center; gap: 14px; padding: 12px 16px;
    background: #fafbfd; border-bottom: 1px solid var(--hair); flex-wrap: wrap;
}
.vt-ui .vt-grp-h .np { font-family: 'IBM Plex Mono', Consolas, monospace; font-weight: 700; color: var(--navy); font-size: 13px; min-width: 110px; }
.vt-ui .vt-grp-h .cli { flex: 1 1 220px; min-width: 0; display: flex; flex-direction: column; }
.vt-ui .vt-grp-h .cli b { font-size: 13.5px; font-weight: 700; letter-spacing: -.01em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vt-ui .vt-grp-h .cli small { font-size: 11px; color: var(--faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vt-ui .vt-grp-h .cli .vt-b { align-self: flex-start; margin: 2px 0; }
.vt-ui .vt-grp-h .dat { display: flex; gap: 18px; align-items: baseline; flex: 0 0 auto; }
.vt-ui .vt-grp-h .dat div { text-align: right; min-width: 0; }
.vt-ui .vt-grp-h .dat .k { font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--faint); display: block; }
.vt-ui .vt-grp-h .dat .v { font-size: 12.5px; font-weight: 600; white-space: nowrap; display: block; }
.vt-ui .vt-grp-h .dat .v.wrn { color: var(--warn); font-weight: 700; }
.vt-ui .vt-grp-h .dat .v.crit { color: var(--crit); font-weight: 700; }
.vt-ui .vt-grp-h .dat .v.falta { color: var(--warn); font-style: italic; }
.vt-ui .vt-grp-h .vt-acr { flex: 0 0 auto; margin-left: 6px; }
.vt-ui .vt-grp-b table.vt-tabla th { background: #fafbfd; border-bottom: 1px solid var(--hair-strong); font-size: 10px; position: static; }

/* Una patente: mono, con caja. Lo que falta, ámbar y con palabra. */
.vt-ui .vt-pat {
    font-family: 'IBM Plex Mono', Consolas, monospace; font-size: 11px; letter-spacing: .02em;
    background: #f4f6f9; border: 1px solid var(--hair-strong); border-radius: 4px; padding: 1px 6px; color: var(--ink); white-space: nowrap;
}
.vt-ui .vt-pat.falta { background: var(--warn-050); border-color: var(--warn-hair); color: var(--warn); font-family: inherit; letter-spacing: 0; font-weight: 600; font-style: italic; }

/* ── El pie y el vacío ────────────────────────────────────────────────────────
   El pie cuenta lo que se ve sobre lo que se leyó, dice el orden y, si la
   consulta tocó su techo, lo dice y ofrece más. */
.vt-ui .vt-pie {
    display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
    padding: 9px 14px; border-radius: 10px;
    background: var(--surface); box-shadow: var(--e1); border: 1px solid rgba(16, 32, 64, .05);
    font-size: 12px; color: var(--muted); flex: 0 0 auto;
}
.vt-ui .vt-pie b { color: var(--ink); font-variant-numeric: tabular-nums; }
.vt-ui .vt-pie .sp { flex: 1; }
.vt-ui .vt-techo { color: var(--warn); font-weight: 600; }
.vt-ui .vt-vacio {
    padding: 28px 18px; text-align: center; color: var(--muted); font-size: 13px;
    background: var(--surface); border-radius: var(--r-card); box-shadow: var(--e1); border: 1px dashed var(--hair-strong);
    display: flex; gap: 8px; justify-content: center; align-items: center; flex-wrap: wrap;
}

/* El teléfono angosto: la tira en dos columnas, los filtros apilados, la tabla
   scrollea de costado dentro de su caja. */
@media (max-width: 640px) {
    .vt-ui .vt-mesa { padding: 12px 12px 14px; gap: 10px; }
    .vt-ui .vt-tira { grid-template-columns: repeat(2, 1fr); gap: 8px; }
    .vt-ui .vt-kpi { padding: 10px 12px; }
    .vt-ui .vt-kpi .v { font-size: 21px; }
    .vt-ui .vt-busca { min-width: 0; flex-basis: 100%; max-width: none; }
    .vt-ui .vt-f-smart { flex: 1 1 45%; min-width: 0; }
    .vt-ui table.vt-tabla { min-width: 900px; }
    .vt-ui .vt-grp-b { overflow-x: auto; }
    .vt-ui .vt-grp-h .dat { flex-wrap: wrap; gap: 10px; }
}

/* =============================================================================
   7. LA FICHA DEL PEDIDO — plano 3, etapa 3
   =============================================================================
   Ronda 3: ganó la 1, «LA FICHA MANDA». Un solo modal (`#vt-ficha`) sobre el
   velo, dos columnas —lo que el pedido ES a la izquierda, lo que le PASÓ a la
   derecha— y las tres puertas (logística, alerta, eliminar) como HOJAS que
   ocupan la columna derecha sin mover la izquierda. Nunca dos velos.

   LA RAÍZ CUELGA DE <body> Y LLEVA `.vt-ui` ELLA MISMA (manual §7): por eso
   todo acá es `.vt-ui .vt-ficha-*` y el candado de `.hidden` va compuesto.

   EL MOVIMIENTO (ronda 2, tabla «gane la que gane»): el velo aparece en 160 ms;
   el panel asoma desde 10 px con la curva del sistema; una hoja que entra
   asoma igual; los botones del pie suben 2 px (`.vt-btn`). El banco fotografía
   a mitad de la animación. `prefers-reduced-motion` lo apaga todo (sección 2). */
.vt-ui.vt-ficha-velo {
    position: fixed; inset: 0; z-index: 200;
    display: flex; align-items: center; justify-content: center; padding: 22px;
    background: rgba(10, 20, 42, .5); backdrop-filter: blur(2px);
    font-family: 'Segoe UI', -apple-system, system-ui, Roboto, Arial, sans-serif;
    font-size: 13.5px; line-height: 1.5; color: var(--ink);
    animation: vtVelo .16s ease;
}
.vt-ui.vt-ficha-velo.hidden { display: none; }
@keyframes vtVelo { from { opacity: 0; } to { opacity: 1; } }
@keyframes vtSube { from { opacity: 0; transform: translateY(10px) scale(.985); } to { opacity: 1; transform: none; } }

.vt-ui .vt-ficha-panel {
    width: 100%; max-width: 880px; max-height: 90vh;
    display: flex; flex-direction: column; overflow: hidden;
    background: var(--surface); border-radius: 14px; box-shadow: var(--e3);
    animation: vtSube .2s var(--curva);
}
/* ── La cabecera ──────────────────────────────────────────────────────────── */
/* ── RANGO 0: LA BANDA — qué le pasa a este pedido AHORA ──────────────────
   Pintada con el color del estado, así que un pedido trabado se distingue de
   uno sano antes de leer una palabra. Reemplaza al borde navy de 3 px que
   tenía la cabecera: ese borde decía «esto es Ventas», que ya se sabe. */
.vt-ui .vt-ficha-banda { flex-shrink: 0; }
.vt-ui .vt-ficha-banda-i {
    display: flex; align-items: center; gap: 13px;
    padding: 12px 22px; border-bottom: 1px solid;
}
.vt-ui .vt-ficha-banda-i .m {
    width: 32px; height: 32px; border-radius: 9px; flex: none;
    display: grid; place-items: center; color: #fff;
}
.vt-ui .vt-ficha-banda-i .m .material-symbols-outlined { font-size: 20px; vertical-align: 0; }
.vt-ui .vt-ficha-banda-i .dice { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.vt-ui .vt-ficha-banda-i .dice b { font-size: 14.5px; font-weight: 800; letter-spacing: -.01em; }
.vt-ui .vt-ficha-banda-i .dice .d { font-size: 12px; opacity: .82; }
.vt-ui .vt-ficha-banda-i .cuando { text-align: right; flex: none; display: flex; flex-direction: column; }
.vt-ui .vt-ficha-banda-i .cuando b { font-size: 18px; font-weight: 700; line-height: 1.1; }
.vt-ui .vt-ficha-banda-i .cuando .l {
    font-size: 10px; font-weight: 800; letter-spacing: .07em; text-transform: uppercase; opacity: .8;
}
/* Los cuatro tonos son los MISMOS del sistema: el color sigue siendo el único
   con significado, y significa lo mismo que en la franja de la fila. */
.vt-ui .vt-ficha-banda-i.t-crit { background: var(--crit-050); border-bottom-color: var(--crit-hair); color: #7d1a1a; }
.vt-ui .vt-ficha-banda-i.t-crit .m { background: var(--crit); }
.vt-ui .vt-ficha-banda-i.t-crit .cuando b { color: var(--crit); }
.vt-ui .vt-ficha-banda-i.t-wrn { background: var(--warn-050); border-bottom-color: var(--warn-hair); color: #6b3d00; }
.vt-ui .vt-ficha-banda-i.t-wrn .m { background: var(--warn); }
.vt-ui .vt-ficha-banda-i.t-wrn .cuando b { color: var(--warn); }
.vt-ui .vt-ficha-banda-i.t-ok { background: var(--ok-050); border-bottom-color: var(--ok-hair); color: #0b5c3e; }
.vt-ui .vt-ficha-banda-i.t-ok .m { background: var(--ok); }
.vt-ui .vt-ficha-banda-i.t-ok .cuando b { color: var(--ok); }
.vt-ui .vt-ficha-banda-i.t-nav { background: var(--navy-050); border-bottom-color: #cfdcf1; color: var(--navy-700); }
.vt-ui .vt-ficha-banda-i.t-nav .m { background: var(--navy); }
.vt-ui .vt-ficha-banda-i.t-nav .cuando b { color: var(--navy); }

/* ── RANGO 1a: la cabecera — QUÉ ES este pedido ────────────────────── */
.vt-ui .vt-ficha-h {
    display: flex; align-items: center; gap: 13px; flex-shrink: 0;
    padding: 14px 22px 13px; border-bottom: 1px solid var(--hair);
}
.vt-ui .vt-ficha-t { min-width: 0; flex: 1; }
/* EL NOMBRE DEL ARTÍCULO NO SE CORTA. El más largo de los que se piden mide 40
   caracteres —227 px medidos con este tipo— y el panel tiene 880: entra
   entero. Si algún día no entrara, ENVUELVE en dos renglones; no se recorta.
   Es lo que Hernán vio el 24/08/2026: «ni en el modal se puede saber el
   producto», porque salía «11400 - Azucar CTA - …». */
.vt-ui .vt-ficha-h h3 {
    margin: 0; font-size: 17px; font-weight: 800; color: var(--navy-700); letter-spacing: -.015em;
    line-height: 1.2; white-space: normal; overflow-wrap: anywhere;
}
.vt-ui .vt-ficha-h h3 .vt-mas { vertical-align: 2px; }
.vt-ui .vt-ficha-h .senas { font-size: 12px; color: var(--muted); margin-top: 1px; }
.vt-ui .vt-ficha-h .s { font-size: 11.5px; font-weight: 500; color: var(--faint); margin-top: 3px; }
.vt-ui .vt-ficha-h .s b { color: var(--navy); font-weight: 700; }

/* La foto del producto (`articulos.imageUrl`). La caja se dibuja SIEMPRE y el
   respaldo —el código en mono— ocupa el mismo lugar, así que los 8 artículos
   sin foto no corren nada de sitio ni dejan un hueco gris. */
.vt-ui .vt-ficha-foto {
    width: 52px; height: 52px; flex: none; border-radius: 10px; overflow: hidden;
    border: 1px solid var(--hair-strong); background: var(--canvas);
    display: grid; place-items: center; position: relative;
}
.vt-ui .vt-ficha-foto img { width: 100%; height: 100%; object-fit: cover; display: block; grid-area: 1 / 1; }
.vt-ui .vt-ficha-foto .ini { grid-area: 1 / 1; font-size: 12px; font-weight: 700; color: var(--faint); }
.vt-ui .vt-ficha-foto:not(.vacia) .ini { display: none; }

/* ── RANGO 1b: los tres datos que se LEEN ─────────────────────────── */
.vt-ui .vt-ficha-clave { flex-shrink: 0; }
.vt-ui .vt-ficha-clave-i {
    display: grid; grid-template-columns: repeat(3, 1fr);
    border-bottom: 1px solid var(--hair);
}
.vt-ui .vt-ficha-dato { padding: 13px 22px; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.vt-ui .vt-ficha-dato + .vt-ficha-dato { border-left: 1px solid var(--hair); }
.vt-ui .vt-ficha-dato .l {
    font-size: 10px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--faint);
}
.vt-ui .vt-ficha-dato .v {
    font-size: 21px; font-weight: 700; color: var(--ink); letter-spacing: -.02em; line-height: 1.15;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.vt-ui .vt-ficha-dato .v small { font-size: 12.5px; font-weight: 600; color: var(--faint); }
.vt-ui .vt-ficha-dato .x {
    font-size: 11.5px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.vt-ui .vt-ficha-x {
    flex: 0 0 28px; width: 28px; height: 28px; border-radius: 7px; margin-left: auto;
    border: 1px solid var(--hair-strong); background: var(--surface); color: var(--muted); cursor: pointer;
    display: grid; place-items: center; padding: 0;
    transition: background .14s ease, border-color .14s ease, color .14s ease, transform .18s var(--curva);
}
.vt-ui .vt-ficha-x .material-symbols-outlined { font-size: 18px; vertical-align: 0; }
.vt-ui .vt-ficha-x:hover, .vt-ui .vt-ficha-x:focus-visible { background: var(--navy-050); border-color: var(--navy-300); color: var(--navy); transform: translateY(-1px); }

/* ── El cuerpo: dos columnas ──────────────────────────────────────────────── */
.vt-ui .vt-ficha-b {
    flex: 1; min-height: 0; overflow: auto;
    display: grid; grid-template-columns: 1.05fr 1fr; gap: 18px; padding: 18px 22px;
    align-items: start;
}
.vt-ui .vt-ficha-col { min-width: 0; }
.vt-ui .vt-ficha-card {
    background: var(--surface); border: 1px solid var(--hair); border-radius: var(--r-card); padding: 12px 14px;
}
.vt-ui .vt-ficha-card.tenida { background: var(--navy-050); border-color: #cfdcf1; }
.vt-ui .vt-ficha-card .k {
    font-size: 10px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--faint);
    display: flex; align-items: center; gap: 8px;
}
.vt-ui .vt-ficha-saldo { margin-top: 8px; font-size: 12px; color: var(--muted); }
.vt-ui .vt-ficha-saldo b { color: var(--ink); font-weight: 700; }
.vt-ui .vt-ficha-saldo b.wrn { color: var(--warn); }

/* Los artículos: una tabla chica con totales al pie. */
.vt-ui table.vt-ficha-items { width: 100%; border-collapse: collapse; font-size: 12px; margin-top: 8px; color: var(--ink); table-layout: fixed; }
.vt-ui table.vt-ficha-items th {
    font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--faint);
    text-align: left; padding: 4px 6px; border-bottom: 1px solid #cfdcf1; white-space: nowrap;
}
.vt-ui table.vt-ficha-items th:nth-child(2) { width: 64px; }
.vt-ui table.vt-ficha-items th:nth-child(3) { width: 78px; }
.vt-ui table.vt-ficha-items th:nth-child(4) { width: 104px; }
.vt-ui table.vt-ficha-items td { padding: 5px 6px; border-bottom: 1px solid rgba(16, 32, 64, .06); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: top; }
/* EL NOMBRE DEL ARTÍCULO TAMPOCO SE CORTA ACÁ. La columna es angosta —las
   otras tres son números con ancho fijo— así que ENVUELVE en vez de recortar:
   un pedido de varios artículos se compara renglón contra renglón, y para eso
   hay que poder leer cuál es cada uno. La fila crece; es lo correcto. */
.vt-ui table.vt-ficha-items tbody td:first-child {
    white-space: normal; overflow-wrap: anywhere; line-height: 1.35;
}
/* El acuerdo NO es un descuento aplicado: era rojo, como una resta, y no lo
   es. Va en el tono de lo secundario, que es lo que es: un pacto que todavía
   no pasó (24/08/2026). */
.vt-ui table.vt-ficha-items td small.vt-ficha-acuerdo { display: block; font-size: 10.5px; color: var(--muted); font-weight: 600; white-space: normal; }
/* La NC va DESPUES del total y separada: no es parte de la suma, es lo que
   valdria el acuerdo si se cumple. Probado en vivo el 24/08/2026: en la celda
   del articulo la frase entera salia CORTADA (246 px en 124). */
.vt-ui table.vt-ficha-items tfoot tr.nc td { color: var(--muted); font-weight: 600; font-size: 11.5px; padding-top: 6px; }
.vt-ui table.vt-ficha-items tfoot tr.nc td:first-child { padding-left: 6px; }
.vt-ui table.vt-ficha-items .n { text-align: right; }
.vt-ui table.vt-ficha-items tfoot td { font-weight: 600; color: var(--muted); border-bottom: 0; padding-top: 4px; padding-bottom: 2px; }
.vt-ui table.vt-ficha-items tfoot tr:first-child td { border-top: 1px solid #cfdcf1; padding-top: 7px; }
.vt-ui table.vt-ficha-items tfoot tr.tot td { color: var(--navy); font-weight: 800; font-size: 13px; }
.vt-ui table.vt-ficha-items tfoot small.sin { font-size: 10.5px; }

/* Los datos, en dos columnas rótulo · valor. */
.vt-ui .vt-ficha-dl { display: grid; grid-template-columns: auto 1fr; gap: 5px 14px; font-size: 12.5px; margin: 12px 0 0; }
.vt-ui .vt-ficha-dl dt { color: var(--muted); margin: 0; }
.vt-ui .vt-ficha-dl dd { margin: 0; font-weight: 600; color: var(--ink); min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/* ── RANGO 3: LA EXCEPCIÓN ─────────────────────────────────────────
   Lo que el cliente pidió una vez y vale para todos sus pedidos. Se lee cuando
   hace falta; no compite con los rangos de arriba. Por eso va en gris —salvo
   que la observación esté marcada como CRÍTICA, y entonces se queda ámbar—.

   Y VA CON ESTILO PROPIO, NO CON EL DE TAILWIND. `obsPanelHTML()` es un
   componente COMPARTIDO (lo usan Comerciales y el portal) y pinta con clases
   de Tailwind. Acá adentro se lo re-pinta: dos clases (0,2,0) contra una
   (0,1,0), así que estas reglas ganan. Es la misma aritmética que dejó la
   barra de segmentos sin esconder, usada a propósito esta vez. */
.vt-ui .vt-ficha-obs {
    margin-top: 12px;
    background: var(--canvas); border: 1px solid var(--hair-strong);
    border-radius: 10px; padding: 11px 13px;
}
.vt-ui .vt-ficha-obs .material-symbols-outlined { color: var(--faint); font-size: 17px; }
.vt-ui .vt-ficha-obs p:first-of-type {
    font-size: 10px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase;
    color: var(--faint); margin: 0 0 2px;
}
.vt-ui .vt-ficha-obs p:last-of-type { font-size: 12.5px; color: var(--muted); line-height: 1.45; margin: 0; }
/* La crítica SÍ levanta la voz: es lo único de este rango que puede frenar. */
.vt-ui .vt-ficha-obs.bg-red-50 {
    background: var(--warn-050); border-color: var(--warn-hair);
}
.vt-ui .vt-ficha-obs.bg-red-50 .material-symbols-outlined,
.vt-ui .vt-ficha-obs.bg-red-50 p:first-of-type { color: var(--warn); }
.vt-ui .vt-ficha-obs.bg-red-50 p:last-of-type { color: #6b3d00; }

/* La alerta crítica, abajo de lo que el pedido es: se queda a la vista
   mientras se carga la logística, que es para lo que está. */
.vt-ui .vt-ficha-alerta {
    margin-top: 12px; padding: 8px 11px; font-size: 12px; color: var(--ink);
    background: var(--crit-050); border: 1px solid var(--crit-hair); border-left: 3px solid var(--crit); border-radius: 8px;
    white-space: pre-line;
}
.vt-ui .vt-ficha-alerta b { display: block; color: var(--crit); font-size: 10px; letter-spacing: .08em; text-transform: uppercase; margin-bottom: 2px; }

/* ── La historia: la línea de tiempo ──────────────────────────────────────── */
.vt-ui .vt-ficha-hist { list-style: none; margin: 8px 0 0; padding: 0; position: relative; }
.vt-ui .vt-ficha-hist::before { content: ''; position: absolute; left: 5px; top: 6px; bottom: 6px; width: 2px; background: var(--hair); }
.vt-ui .vt-ficha-hist li { position: relative; padding: 0 0 10px 20px; font-size: 12.5px; color: var(--ink); }
.vt-ui .vt-ficha-hist li:last-child { padding-bottom: 2px; }
.vt-ui .vt-ficha-hist li::before {
    content: ''; position: absolute; left: 0; top: 5px; width: 12px; height: 12px; border-radius: 50%;
    background: var(--surface); border: 2px solid var(--navy); box-sizing: border-box;
}
.vt-ui .vt-ficha-hist li.ok::before   { border-color: var(--ok); background: var(--ok); }
.vt-ui .vt-ficha-hist li.nav::before  { border-color: var(--navy); background: var(--navy); }
.vt-ui .vt-ficha-hist li.wrn::before  { border-color: var(--warn); background: var(--warn); }
.vt-ui .vt-ficha-hist li.crit::before { border-color: var(--crit); background: var(--crit); }
.vt-ui .vt-ficha-hist li.next::before { border-color: var(--hair-strong); background: var(--surface); border-style: dashed; }
.vt-ui .vt-ficha-hist li.next { color: var(--faint); }
.vt-ui .vt-ficha-hist .f { display: block; font-size: 10.5px; color: var(--faint); }
.vt-ui .vt-ficha-hist b.ok { color: var(--ok); } .vt-ui .vt-ficha-hist b.wrn { color: var(--warn); } .vt-ui .vt-ficha-hist b.crit { color: var(--crit); } .vt-ui .vt-ficha-hist b.nav { color: var(--navy); }

/* Lo extra de Cumplidos (vínculo roto, fecha faltante, F3000): una caja por aviso. */
.vt-ui .vt-ficha-extra { margin-top: 10px; display: flex; flex-direction: column; gap: 8px; }
.vt-ui .vt-ficha-extra:empty { display: none; }
.vt-ui .vt-ficha-aviso {
    padding: 9px 11px; font-size: 12px; color: var(--ink); border-radius: 8px;
    background: var(--warn-050); border: 1px solid var(--warn-hair); border-left: 3px solid var(--warn);
    display: flex; flex-direction: column; gap: 6px;
}
.vt-ui .vt-ficha-aviso.crit { background: var(--crit-050); border-color: var(--crit-hair); border-left-color: var(--crit); }
.vt-ui .vt-ficha-aviso.nav { background: var(--navy-050); border-color: #cfdcf1; border-left-color: var(--navy); }
.vt-ui .vt-ficha-aviso b { font-size: 10px; letter-spacing: .08em; text-transform: uppercase; color: var(--warn); }
.vt-ui .vt-ficha-aviso.crit b { color: var(--crit); } .vt-ui .vt-ficha-aviso.nav b { color: var(--navy); }
.vt-ui .vt-ficha-aviso .vt-btn { align-self: flex-start; }
.vt-ui table.vt-ficha-movs { width: 100%; border-collapse: collapse; font-size: 11.5px; }
.vt-ui table.vt-ficha-movs td { padding: 2px 4px; border-bottom: 1px solid rgba(16, 32, 64, .08); }
.vt-ui table.vt-ficha-movs td.n { text-align: right; }

/* ── Las hojas ────────────────────────────────────────────────────────────── */
.vt-ui .vt-hoja {
    background: var(--surface); border: 1px solid var(--hair); border-radius: var(--r-card); padding: 12px 14px;
    box-shadow: var(--e2); animation: vtSube .2s var(--curva);
}
.vt-ui .vt-hoja .hk { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; padding-bottom: 8px; border-bottom: 1px solid var(--hair); }
.vt-ui .vt-hoja .hk b { font-size: 13px; font-weight: 800; color: var(--navy); }
.vt-ui .vt-hoja .hk .s { font-size: 11px; color: var(--faint); }
.vt-ui .vt-hoja.crit { border-color: var(--crit-hair); } .vt-ui .vt-hoja.crit .hk { border-bottom-color: var(--crit-hair); } .vt-ui .vt-hoja.crit .hk b { color: var(--crit); }
.vt-ui .vt-hoja.wrn  { border-color: var(--warn-hair); } .vt-ui .vt-hoja.wrn .hk  { border-bottom-color: var(--warn-hair); } .vt-ui .vt-hoja.wrn .hk b  { color: var(--warn); }

/* El formulario: rótulos en versalitas, campos con la caja del sistema. */
.vt-ui .vt-form { display: flex; flex-direction: column; gap: 10px; }
.vt-ui .vt-form label { display: block; min-width: 0; }
.vt-ui .vt-f2 { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.vt-ui .vt-f3 { display: grid; grid-template-columns: 96px 1fr auto; gap: 8px; align-items: end; }
.vt-ui .vt-lab { display: block; font-size: 10.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--faint); margin-bottom: 3px; }
.vt-ui .vt-lab b.crit { color: var(--crit); } .vt-ui .vt-lab b.wrn { color: var(--warn); }
.vt-ui .vt-in {
    width: 100%; box-sizing: border-box; min-height: 34px;
    font: inherit; font-size: 12.5px; color: var(--ink);
    background: var(--surface); border: 1px solid var(--hair-strong); border-radius: 8px; padding: 6px 10px;
    transition: border-color .14s ease, box-shadow .18s var(--curva);
}
.vt-ui .vt-in:focus { outline: none; border-color: var(--navy); box-shadow: 0 0 0 3px var(--navy-050); }
.vt-ui .vt-in::placeholder { color: var(--faint); }
.vt-ui .vt-in.mono { font-family: 'IBM Plex Mono', Consolas, monospace; font-weight: 600; }
.vt-ui select.vt-in { cursor: pointer; }
.vt-ui .vt-textarea { resize: vertical; min-height: 96px; line-height: 1.45; }
.vt-ui .vt-hoja.crit .vt-textarea { border-color: var(--crit-hair); color: var(--crit); font-weight: 600; }
.vt-ui .vt-hoja.crit .vt-textarea:focus { border-color: var(--crit); box-shadow: 0 0 0 3px var(--crit-050); }
.vt-ui .vt-nota { font-size: 11px; color: var(--faint); }
.vt-ui .vt-log-fila { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: 4px; }
.vt-ui .vt-log-patentes { display: flex; align-items: center; gap: 6px; margin-top: 6px; padding: 6px 9px; background: #fafbfd; border: 1px solid var(--hair); border-radius: 8px; }
.vt-ui .vt-log-patentes.hidden { display: none; }
.vt-ui .vt-log-patentes .sp, .vt-ui .vt-bloque .sp, .vt-ui .vt-ficha-f .sp { flex: 1; }
.vt-ui .vt-bloque { border: 1px solid var(--hair); border-radius: 10px; padding: 11px 12px; display: flex; flex-direction: column; gap: 8px; background: var(--surface); }
.vt-ui .vt-bloque .bt { display: flex; align-items: center; gap: 8px; font-size: 10.5px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: var(--navy); }
/* El estado de la tarifa exacta: lo escribe checkLogisticaTarifa. */
.vt-ui .vt-log-msg { font-size: 10.5px; font-weight: 700; letter-spacing: .03em; text-transform: uppercase; padding: 2px 8px; border-radius: 5px; border: 1px solid var(--hair-strong); color: var(--faint); background: var(--surface); }
.vt-ui .vt-log-msg.ok   { color: var(--ok);   background: var(--ok-050);   border-color: var(--ok-hair); }
.vt-ui .vt-log-msg.wrn  { color: var(--warn); background: var(--warn-050); border-color: var(--warn-hair); }
.vt-ui .vt-log-msg.crit { color: var(--crit); background: var(--crit-050); border-color: var(--crit-hair); }
.vt-ui .vt-log-msg.nav  { color: var(--navy); background: var(--navy-050); border-color: #cfdcf1; }
/* Las tarifas de referencia de otros transportes para la misma localidad. */
.vt-ui .vt-sug { border: 1px dashed #cfdcf1; border-radius: 8px; padding: 7px 10px; font-size: 11.5px; background: var(--navy-050); }
.vt-ui .vt-sug > b { display: block; font-size: 10px; letter-spacing: .08em; text-transform: uppercase; color: var(--navy); margin-bottom: 3px; }
.vt-ui .vt-sug button { display: flex; width: 100%; justify-content: space-between; gap: 8px; align-items: center; padding: 3px 4px; border: 0; border-radius: 5px; background: none; font: inherit; font-size: 11.5px; color: var(--ink); cursor: pointer; text-align: left; }
.vt-ui .vt-sug button:hover, .vt-ui .vt-sug button:focus-visible { background: var(--surface); }
.vt-ui .vt-sug button .v { font-family: 'IBM Plex Mono', Consolas, monospace; font-weight: 600; color: var(--navy); }
.vt-ui .vt-sug button small { color: var(--faint); }
.vt-ui .vt-sug button small.ok { color: var(--ok); } .vt-ui .vt-sug button small.wrn { color: var(--warn); } .vt-ui .vt-sug button small.crit { color: var(--crit); }
.vt-ui .vt-chk { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--ink); cursor: pointer; }
.vt-ui .vt-chk input { width: 14px; height: 14px; margin: 0; accent-color: var(--navy); }
.vt-ui .vt-chk.crit { color: var(--crit); } .vt-ui .vt-chk.crit input { accent-color: var(--crit); }
.vt-ui .vt-chk small { color: var(--faint); font-size: 11px; }

/* Eliminar con palabra: las consecuencias, y el campo que enciende el botón. */
.vt-ui .vt-ficha-cons { list-style: none; margin: 0 0 12px; padding: 0; display: flex; flex-direction: column; gap: 4px; font-size: 12.5px; color: var(--ink); }
.vt-ui .vt-ficha-cons li { padding-left: 14px; position: relative; }
.vt-ui .vt-ficha-cons li::before { content: ''; position: absolute; left: 0; top: .65em; width: 6px; height: 1.5px; background: var(--faint); }
.vt-ui .vt-palabra { font-family: 'IBM Plex Mono', Consolas, monospace; font-weight: 600; font-size: 16px; letter-spacing: .18em; text-align: center; text-transform: uppercase; min-height: 40px; }
.vt-ui .vt-palabra.crit:focus, .vt-ui .vt-palabra.crit.lista { border-color: var(--crit); color: var(--crit); box-shadow: 0 0 0 3px var(--crit-050); }
.vt-ui .vt-palabra.wrn:focus,  .vt-ui .vt-palabra.wrn.lista  { border-color: var(--warn); color: var(--warn); box-shadow: 0 0 0 3px var(--warn-050); }

/* ── El pie ───────────────────────────────────────────────────────────────── */
.vt-ui .vt-ficha-f {
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap; flex-shrink: 0;
    padding: 12px 22px; border-top: 1px solid var(--hair); background: #f7f9fc;
}
/* Dos tonos más para el pie de la ficha: `peligro` es un trazo rojo (el verbo
   que abre la puerta de eliminar); `warn` es ámbar lleno (anular el saldo,
   devolver). `danger` (rojo lleno) ya existía. */
.vt-ui .vt-btn.peligro { background: transparent; color: var(--crit); border-color: var(--crit-hair); box-shadow: none; }
.vt-ui .vt-btn.peligro:hover:not(:disabled) { background: var(--crit-050); border-color: var(--crit); color: var(--crit); box-shadow: 0 4px 12px rgba(198, 40, 40, .14); }
.vt-ui .vt-btn.warn { background: var(--warn); border-color: var(--warn); color: #fff; }
.vt-ui .vt-btn.warn:hover:not(:disabled) { background: #8a4900; border-color: #8a4900; box-shadow: 0 6px 16px rgba(168, 89, 0, .28); }

/* ── 640 px: las dos columnas se apilan, el panel ocupa la pantalla ───────── */
@media (max-width: 640px) {
    .vt-ui.vt-ficha-velo { padding: 0; }
    .vt-ui .vt-ficha-panel { max-width: none; max-height: none; height: 100%; border-radius: 0; }
    .vt-ui .vt-ficha-b { grid-template-columns: 1fr; gap: 12px; padding: 12px; }
    .vt-ui .vt-ficha-h { padding: 12px 14px 10px; }
    .vt-ui .vt-ficha-banda-i { padding: 10px 14px; gap: 10px; }
    /* LOS TRES DATOS SE APILAN. En tres columnas a 390 px el renglon de abajo
       se cortaba justo donde estaba el dato: «5 x 4 · 1.000 k...», «Bs. As. ·
       sucurs...», «sin turno de d...». Es la leccion de siempre: lo que
       distingue suele estar al FINAL. Apilados entran enteros, y la cifra de
       arriba se sigue leyendo de un vistazo. */
    .vt-ui .vt-ficha-clave-i { grid-template-columns: 1fr; }
    .vt-ui .vt-ficha-dato { padding: 10px 14px; }
    .vt-ui .vt-ficha-dato + .vt-ficha-dato { border-left: 0; border-top: 1px solid var(--hair); }
    .vt-ui .vt-ficha-dato .x { white-space: normal; }
    .vt-ui .vt-ficha-f { padding: 10px 12px; }
    .vt-ui .vt-ficha-f .vt-btn { flex: 1 1 auto; justify-content: center; }
    .vt-ui .vt-ficha-f .sp { flex-basis: 100%; }
    .vt-ui .vt-f3 { grid-template-columns: 1fr 1fr; }
    .vt-ui .vt-f3 .vt-btn { grid-column: 1 / -1; }
}

/* =============================================================================
   8. LA MESA DE CONTROL — plano 3, etapa 4
   =============================================================================
   Ronda 4: ganó la 2, «LA MESA COMO MODAL», hermana de la ficha: `#vt-mesa`
   reutiliza el velo, la cabecera, las dos columnas, las hojas y el pie de §7
   (`.vt-ficha-velo`, `.vt-ficha-panel`, `.vt-ficha-h/-b/-f`, `.vt-hoja`,
   `.vt-form`…). Acá va sólo lo que la Mesa tiene y la ficha no: el panel más
   ancho (lo que viaja necesita una tabla), la tabla de saldos con casilla y «a
   cargar», la marca del genérico bajo el artículo, el lugar de carga en dos
   segmentos con la caja del tercero, lo heredado dicho, y EL MEDIDOR del pie:
   kilos tildados contra el equipo (`VT_KG_EQUIPO`). */
.vt-ui .vt-ficha-panel.vt-mc-panel { max-width: 1040px; }
.vt-ui .vt-mc-b { grid-template-columns: 1.35fr 1fr; }
.vt-ui .vt-mc-b .vt-ficha-col { display: flex; flex-direction: column; gap: 10px; }
.vt-ui .vt-mc-b .vt-ficha-col > label { display: block; }
.vt-ui #vt-gen-viaje[hidden], .vt-ui #vt-gen-hoja[hidden] { display: none; }

/* ── Lo que viaja: la tabla de saldos ─────────────────────────────────────── */
.vt-ui .vt-gen-items-zona { min-width: 0; }
.vt-ui .vt-gen-items-zona .vt-caja { overflow: auto; max-height: 52vh; }
.vt-ui table.vt-gen-items { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 12.5px; table-layout: fixed; color: var(--ink); }
.vt-ui table.vt-gen-items th {
    text-align: left; font-size: 10px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--faint);
    padding: 8px 8px; border-bottom: 2px solid var(--hair-strong); white-space: nowrap; position: sticky; top: 0; background: var(--surface); z-index: 1;
}
.vt-ui table.vt-gen-items td { padding: 7px 8px; border-bottom: 1px solid var(--hair); vertical-align: top; transition: background .14s ease; }
.vt-ui table.vt-gen-items td.tx { white-space: normal; overflow-wrap: anywhere; }
.vt-ui table.vt-gen-items .n { text-align: right; }
.vt-ui table.vt-gen-items td.ord { font-family: 'IBM Plex Mono', Consolas, monospace; font-weight: 600; font-size: 12px; white-space: nowrap; }
.vt-ui table.vt-gen-items .sub { display: block; font-size: 11px; color: var(--faint); font-weight: 400; font-family: 'Segoe UI', system-ui, sans-serif; }
.vt-ui table.vt-gen-items .sub .ok { color: var(--ok); font-weight: 600; }
.vt-ui table.vt-gen-items .sub .wrn { color: var(--warn); font-weight: 600; }
/* La franja: navy cuando está tildada, roja si la fila tiene alerta (gana). */
.vt-ui table.vt-gen-items td.fr { position: relative; padding-left: 12px; width: 34px; }
.vt-ui table.vt-gen-items td.fr::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: transparent; transition: background .14s ease; }
.vt-ui table.vt-gen-items tr.tild td.fr::before { background: var(--navy); }
.vt-ui table.vt-gen-items tr.alerta td.fr::before { background: var(--crit); }
.vt-ui table.vt-gen-items tr.tild td { background: var(--navy-050); }
.vt-ui table.vt-gen-items input[type="checkbox"] { width: 15px; height: 15px; margin: 2px 0 0; accent-color: var(--navy); cursor: pointer; }
.vt-ui table.vt-gen-items td .vt-in.chica { min-height: 28px; padding: 3px 8px; font-size: 12px; text-align: right; }
.vt-ui table.vt-gen-items td .vt-in:disabled { background: #f4f6f9; color: var(--faint); border-color: var(--hair); }
.vt-ui table.vt-gen-items .vt-ficha-alerta { margin-top: 6px; font-size: 11.5px; padding: 6px 9px; white-space: normal; }
.vt-ui .vt-gen-marca { display: flex; align-items: center; gap: 8px; margin-top: 5px; }
.vt-ui .vt-gen-marca .vt-lab { margin: 0; }
.vt-ui .vt-gen-marca .vt-in { flex: 1; min-width: 0; text-align: left; }
.vt-ui .vt-in.wrn { border-color: var(--warn); background: var(--warn-050); }
.vt-ui .vt-in.wrn:focus { border-color: var(--warn); box-shadow: 0 0 0 3px var(--warn-050); }
.vt-ui .vt-gen-especie { display: block; margin-top: 4px; font-size: 11px; color: var(--crit); font-weight: 600; }
.vt-ui .vt-gen-especie.hidden { display: none; }
.vt-ui .vt-vacio.chico { padding: 26px 14px; font-size: 12.5px; }

/* ── El viaje ─────────────────────────────────────────────────────────────── */
.vt-ui .vt-dos { display: flex; border: 1px solid var(--hair-strong); border-radius: 8px; overflow: hidden; position: relative; }
.vt-ui .vt-dos label { flex: 1; text-align: center; padding: 7px 6px; font-size: 12px; font-weight: 600; color: var(--muted); background: var(--surface); cursor: pointer; transition: background .14s ease, color .14s ease; }
.vt-ui .vt-dos label + label { border-left: 1px solid var(--hair-strong); }
.vt-ui .vt-dos label:has(input:checked) { background: var(--navy); color: #fff; }
.vt-ui .vt-dos label:has(input:focus-visible) { box-shadow: inset 0 0 0 2px var(--navy-300); }
.vt-ui .vt-dos input { position: absolute; opacity: 0; width: 0; height: 0; }
.vt-ui .vt-terc { margin-top: 8px; border: 1px dashed #cfdcf1; border-radius: 8px; padding: 9px 10px; background: var(--navy-050); display: flex; flex-direction: column; gap: 8px; }
.vt-ui .vt-terc.hidden { display: none; }
.vt-ui .vt-terc p { margin: 0; font-size: 11.5px; color: var(--muted); line-height: 1.4; }
.vt-ui .vt-terc label { display: block; }
.vt-ui .vt-nota.ok { color: var(--ok); font-weight: 600; }
.vt-ui .vt-nota.wrn { color: var(--warn); font-weight: 600; }
.vt-ui .vt-nota.crit { color: var(--crit); font-weight: 600; }
/* Lo heredado, dicho al lado del rótulo. */
/* `nowrap` y `inline-block`: sin eso, «DEL P-1» se parte en dos renglones en
   cuanto el rotulo no entra —la trampa del flex que parte la oracion—. */
.vt-ui .vt-her { display: inline-block; white-space: nowrap; font-size: 10px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--navy); background: var(--navy-050); border: 1px solid #cfdcf1; border-radius: 5px; padding: 0 6px; margin-left: 4px; }
.vt-ui .vt-her.hidden { display: none; }
.vt-ui .vt-textarea.chica { min-height: 56px; }
.vt-ui #vt-gen-sin-pat { font-size: 11px; color: var(--warn); font-style: normal; font-weight: 600; }
.vt-ui #vt-gen-sin-pat.hidden { display: none; }

/* ── El pie: el medidor ───────────────────────────────────────────────────── */
.vt-ui .vt-med { display: flex; flex-direction: column; gap: 4px; min-width: 230px; }
.vt-ui .vt-med .ln { display: flex; align-items: baseline; gap: 6px; font-size: 12px; color: var(--muted); }
.vt-ui .vt-med .ln b { font-size: 17px; font-weight: 800; color: var(--navy); letter-spacing: -.01em; }
.vt-ui .vt-med .ln .eq { margin-left: auto; font-weight: 600; color: var(--ink); }
.vt-ui .vt-med .bar { height: 6px; border-radius: 4px; background: var(--hair); position: relative; overflow: hidden; }
.vt-ui .vt-med .bar i { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 4px; background: var(--navy); transition: width .18s var(--curva), background .14s ease; }
.vt-ui .vt-med .bar i.wrn { background: var(--warn); }
.vt-ui .vt-med .bar u { position: absolute; right: 0; top: -2px; bottom: -2px; width: 1px; background: var(--faint); opacity: .6; }
.vt-ui .vt-gen-falta { max-width: 300px; line-height: 1.3; }
.vt-ui .vt-gen-falta.wrn { color: var(--warn); font-weight: 600; }

/* ── El toast no puede taparle el clic al verbo primario ──────────────────────
   El toast del sistema vive abajo a la DERECHA (`core/toast.css`), y eso se
   eligió para no pisar los botones de un modal, que suelen ir CENTRADOS abajo.
   Los de GS no: el pie de la ficha y el de la Mesa ponen el verbo primario
   abajo a la derecha, justo donde aterriza la pila. Y el toast es clickeable
   (se cierra al tocarlo), así que durante sus tres segundos se COME el clic de
   «Generar NP» o «Despachar saldo». Lo destapó el banco de la etapa 4
   midiendo quién recibe el punto central del botón: `gs-toast ok`.

   Mientras uno de estos dos modales está abierto, la pila sube por encima del
   pie. El cálculo es para el peor caso: el panel llega a `90vh` —su borde
   inferior queda a `5vh` del fondo— y el pie mide ~60 px.

   ES DEL SISTEMA, no sólo de Ventas: cualquier modal con el verbo abajo a la
   derecha tiene el mismo problema. Se arregla acá porque acá está probado;
   queda anotado en el runbook (§6) para el resto. */
body:has(.vt-ui.vt-ficha-velo:not(.hidden)) #gs-toasts { bottom: calc(5vh + 72px); }

/* ── 640 px ───────────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
    .vt-ui .vt-mc-b { grid-template-columns: 1fr; }
    .vt-ui .vt-gen-items-zona .vt-caja { max-height: none; }
    .vt-ui .vt-med { min-width: 0; flex: 1 1 100%; }
    .vt-ui .vt-gen-falta { max-width: none; flex-basis: 100%; }
    /* La tabla NO se comprime: con `fixed` y las columnas de la izquierda
       fijas, al artículo le quedaban 50 px y el nombre salía partido letra por
       letra —«Transpor tes Del Valle»— (la foto del banco a 390 lo mostró).
       Acá manda el ancho del contenido y la caja scrollea de costado, que es
       lo que el manual pide para lo ancho (§7). */
    .vt-ui table.vt-gen-items { table-layout: auto; min-width: 480px; }
    .vt-ui table.vt-gen-items col { width: auto !important; }
    .vt-ui table.vt-gen-items td.tx { min-width: 200px; }
    .vt-ui .vt-gen-marca { flex-direction: column; align-items: stretch; gap: 3px; }
}

/* =============================================================================
   9. LA FICHA DEL NP — la Salida, plano 3, etapa 5
   =============================================================================
   Ronda 5: ganó la 1, «LA FICHA DEL NP». Tercer hermano del molde de §7:
   `#vt-sal` reutiliza el velo, la cabecera, las dos columnas, las hojas y el
   pie. Acá va sólo lo suyo: el panel ancho (el viaje lleva una tabla de ítems
   con precios), EL CARRIL DE LA PLAYA —los cuatro pasos leídos de
   `preparaciones_carga`—, los chips de los pedidos del viaje, y el pie que en
   vez de medir kilos DICE EN QUÉ ANDA LA SALIDA y por qué el verbo está
   apagado.

   El verbo primario es «Confirmar despacho» y lleva a Despachos en Curso
   (decisión de Hernán, 24/08/2026): un solo lugar donde se confirma. */
.vt-ui .vt-ficha-panel.vt-sal-panel { max-width: 1040px; }
.vt-ui .vt-sal-b { grid-template-columns: 1.25fr 1fr; }
.vt-ui .vt-sal-b .vt-ficha-col { display: flex; flex-direction: column; gap: 10px; }

/* ── El carril de la playa ────────────────────────────────────────────────────
   Cuatro pasos: Generada · En la playa · Lista · Despachada. El que ocurre
   lleva la PALABRA del estado (no la del paso): «Devuelta a Producción» dice
   más que «En la playa». La carga en tercero tiene su propio carril de dos
   pasos, porque no pasa por la playa y dibujarla «sin tomar» sería mentir. */
.vt-ui .vt-sal-carril {
    display: flex; align-items: center; gap: 0; flex-wrap: wrap;
    padding: 9px 12px; border: 1px solid var(--hair); border-radius: 10px;
    background: var(--surface); box-shadow: var(--e1);
}
.vt-ui .vt-sal-carril span {
    display: flex; align-items: center; gap: 5px; white-space: nowrap;
    font-size: 10.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--faint);
}
.vt-ui .vt-sal-carril span i { width: 9px; height: 9px; border-radius: 50%; background: var(--hair-strong); flex: 0 0 9px; }
.vt-ui .vt-sal-carril span.hecho { color: var(--muted); }
.vt-ui .vt-sal-carril span.hecho i { background: var(--navy-300); }
.vt-ui .vt-sal-carril span.aqui { color: var(--navy); }
.vt-ui .vt-sal-carril span.aqui i { background: var(--navy); box-shadow: 0 0 0 3px var(--navy-050); }
.vt-ui .vt-sal-carril span.aqui.ok { color: var(--ok); }
.vt-ui .vt-sal-carril span.aqui.ok i { background: var(--ok); box-shadow: 0 0 0 3px var(--ok-050); }
.vt-ui .vt-sal-carril span.aqui.wrn { color: var(--warn); }
.vt-ui .vt-sal-carril span.aqui.wrn i { background: var(--warn); box-shadow: 0 0 0 3px var(--warn-050); }
.vt-ui .vt-sal-carril span.aqui.nav { color: var(--navy); }
.vt-ui .vt-sal-carril u { width: 14px; height: 1.5px; background: var(--hair-strong); text-decoration: none; margin: 0 6px; flex: 0 0 14px; }
.vt-ui .vt-sal-carril u.hecho { background: var(--navy-300); }

/* ── Quién la tiene, en la cabecera de la tarjeta ─────────────────────────── */
.vt-ui .vt-sal-quien { font-size: 11px; font-weight: 500; letter-spacing: 0; text-transform: none; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vt-ui .vt-sal-quien b { color: var(--ink); font-weight: 700; }

/* ── Los pedidos del viaje, como chips que abren su ficha ─────────────────── */
.vt-ui .vt-sal-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.vt-ui .vt-min.nav { color: var(--navy); border-color: var(--navy-hair); }
.vt-ui .vt-min.nav:hover { background: var(--navy-050); border-color: var(--navy); }

/* ── El ajuste de la cantidad cargada ─────────────────────────────────────── */
/* EL ATRIBUTO `hidden` NO ALCANZA (trampa §7 del manual, la misma que la Mesa
   paga con `#vt-gen-viaje[hidden]`): `.vt-bloque` declara `display: flex` y le
   gana a la regla del navegador, así que la pregunta del saldo se veía SIEMPRE
   —con «sin cambios» arriba— y ofrecía elegir qué hacer con un saldo que no
   existe. Lo destapó la foto a 390 px; el banco medía la propiedad `hidden`,
   que era `true`, y no lo que se ve. */
.vt-ui #vt-sal-ajuste-que[hidden] { display: none; }
.vt-ui table.vt-ficha-items .vt-sal-qty { width: 108px; text-align: right; min-height: 28px; padding: 3px 8px; font-size: 12px; }
.vt-ui table.vt-ficha-items .vt-sal-orig { color: var(--faint); }
.vt-ui table.vt-ficha-items .vt-sal-saldo.wrn { color: var(--warn); font-weight: 700; }

/* ── El pie: en qué anda la salida, y por qué el verbo está apagado ────────── */
.vt-ui .vt-sal-med { min-width: 0; flex: 1; gap: 2px; }
.vt-ui .vt-sal-med .l1 { font-size: 12.5px; font-weight: 700; color: var(--ink); }
.vt-ui .vt-sal-med .l2 { font-size: 11.5px; font-weight: 600; color: var(--warn); line-height: 1.3; }
.vt-ui .vt-sal-med .l2.ok { color: var(--ok); }
/* El verbo apagado NO se esconde: se ve, dice qué es, y el renglón de al lado
   dice por qué no se puede todavía. Un botón que desaparece obliga a adivinar
   si el permiso falta o la pantalla se rompió. */
.vt-ui .vt-btn.apagado { background: var(--hair); color: var(--faint); box-shadow: none; cursor: not-allowed; }
.vt-ui .vt-btn.apagado:hover { background: var(--hair); transform: none; box-shadow: none; }
.vt-ui .vt-btn.ok { background: var(--ok); color: #fff; }
.vt-ui .vt-btn.ok:hover { background: #0b5c3e; }

/* ── 640 px ───────────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
    .vt-ui .vt-sal-b { grid-template-columns: 1fr; }
    /* El nombre del artículo ENVUELVE en vez de cortarse con puntos suspensivos:
       en el viaje lo que distingue dos renglones suele estar al final («Tipo A ·
       bolsa 50 kg»), y «Azúcar Com…» no dice nada. Es la misma lección que la
       tabla de saldos de la Mesa, con otra cara. */
    .vt-ui .vt-sal-panel table.vt-ficha-items td:first-child { white-space: normal; overflow-wrap: anywhere; }
    /* CON UNA HOJA ABIERTA, LA HOJA VA PRIMERO. Apiladas, la columna izquierda
       del NP mide una tabla de ítems, los chips de los pedidos y el lugar de
       carga: la hoja que se acaba de abrir quedaba tres pantallas más abajo y
       parecía que el botón no había hecho nada. En 1440 no pasa —la izquierda
       está al lado y por eso no se mueve— y por eso la regla vive sólo acá. */
    .vt-ui .vt-sal-panel:not([data-hoja="historia"]) #vt-sal-der { order: -1; }
    /* El campo de kilos no puede quedar más ancho que su columna: a 390 px
       «15.000» se leía «150». */
    .vt-ui table.vt-ficha-items .vt-sal-qty { width: 100%; min-width: 0; }
    .vt-ui .vt-sal-med { flex: 1 1 100%; }
    /* El carril scrollea de costado antes que partir las palabras (la trampa
       que la etapa 4 pagó con la tabla de saldos a 390 px). */
    .vt-ui .vt-sal-carril { flex-wrap: nowrap; overflow-x: auto; }
}

/* =============================================================================
   10. EL FORMULARIO DE NUEVO PEDIDO — plano 1 y 2, etapa 6
   =============================================================================
   Ronda 6: ganó la 1, «EL MISMO PEDIDO» (Hernán, 24/08/2026), y con ella que
   administración cargue un pedido con LA MISMA FORMA que el comercial. El
   molde es `.cm-pc` de `comerciales-ui.css` (la pre-carga, en producción desde
   el 16/08): tres tarjetas apiladas en una columna que scrollea —el pedido,
   agregar artículos, el pedido armado—, las acciones arriba en la barra del
   armazón, y el mismo renglón (miniatura · EAN/DUN · palletizado del ABM · la
   cuenta de bultos y pallets con sus atajos).

   PERO NO SE PIERDE NADA DE LO QUE VENTAS TENÍA (pedido de Hernán, textual:
   «obviamente con todas las funciones tal cual hoy tiene ventas»). Lo que el
   molde de Comerciales no previó y acá vive igual:
     · la PRE-LOGÍSTICA, como cuarta tarjeta plegable;
     · el ACUERDO por línea, una columna más de la tabla;
     · el FORMATO DE PALLET elegido POR RENGLÓN (Comerciales usa el del ABM y
       no deja elegir): el `<select>` de la fila, y la cuenta habla de ÉL;
     · los TRES MODOS —nuevo, editar, copiar—, que ahora se DICEN en una franja;
     · el bloqueo del pedido con entregas parciales, que ahora explica por qué.

   POR QUÉ ACÁ NO HAY VELO NI PANEL. Es la única pantalla de las etapas 3 a 6
   que NO es un modal: la ficha, la Mesa y la Salida se abren SOBRE la lista
   porque hablan de algo que ya existe. Un pedido nuevo todavía no existe, y es
   la vista `NUEVO` de la barra de secciones desde la etapa 1. Así que las
   piezas que se reusan de §7 son las CHICAS —`.vt-btn`, `.vt-in`, `.vt-lab`,
   `.vt-chk`— y no el armazón del modal.

   LOS TRES PLANOS, y por qué así (es el reparto de Comerciales, §9 de su
   runbook): la tarjeta del pedido va en `--e1` —es el «sobre qué», no el «qué
   se hace»—, y el buscador y el carrito en `--e2`. La tarjeta del buscador va
   además `.suave`: es la HERRAMIENTA que opera sobre el pedido, no una parte
   de él. Con las tres al mismo peso, el tratamiento dejaría de ser jerarquía.
   ============================================================================= */

/* La columna. El scroll lo maneja ESTA caja y no `.vt-work` (que es
   `overflow: hidden`): así la barra de secciones no se mueve. */
.vt-ui .vt-nv {
    flex: 1; min-height: 0; min-width: 0;
    overflow-y: auto; overflow-x: hidden;
    padding: 0 var(--gutter) 24px;
}
.vt-ui .vt-nv-col { max-width: 1100px; margin: 0 auto; }

/* ── La franja del modo — sólo en editar y copiar ──────────────────────────
   Un formulario que se abre CON DATOS ADENTRO tiene que decir de dónde
   salieron. Antes el modo vivía en una chapa de 11 px arriba a la derecha y en
   el rótulo del botón; copiar y editar se veían casi igual, y editar toca un
   documento que ya existe. */
.vt-ui .vt-nv-modo {
    display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
    margin: 13px 0 0; padding: 10px 16px;
    background: var(--navy); color: #fff; border-radius: var(--r-card); box-shadow: var(--e2);
}
.vt-ui .vt-nv-modo .t { font-size: 13.5px; font-weight: 700; min-width: 0; }
.vt-ui .vt-nv-modo .t small { display: block; font-size: 11.5px; font-weight: 500; opacity: .78; line-height: 1.4; }
.vt-ui .vt-nv-modo .sp { flex: 1; }
.vt-ui .vt-nv-modo .chapa {
    font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
    padding: 3px 9px; border-radius: 6px; white-space: nowrap;
    background: rgba(255, 255, 255, .14); border: 1px solid rgba(255, 255, 255, .28);
}

/* ── La tarjeta de una sección ─────────────────────────────────────────────── */
.vt-ui .vt-nv-card {
    margin: 13px 0 0; background: var(--surface);
    border: 1px solid rgba(16, 32, 64, .05); border-radius: var(--r-card);
    box-shadow: var(--e2); overflow: hidden;
}
.vt-ui .vt-nv-card.cab { box-shadow: var(--e1); }
/* EL DESPLEGABLE QUE SE CORTA. `.vt-nv-card` lleva `overflow: hidden` para que
   la banda de la cabecera no se salga por las esquinas redondeadas, y eso
   RECORTA el desplegable del cliente —que es `position: absolute` y vive
   adentro—. No se arregla con `z-index`: lo recortado por el `overflow` de un
   ancestro se recorta ANTES de apilarse. Lo pagó Comerciales en su etapa 9 y
   la salida es la misma: sueltan el recorte SÓLO las tarjetas que tienen un
   flotante adentro, y las esquinas se las redondea la cabecera por su cuenta. */
.vt-ui .vt-nv-card.abierta { overflow: visible; position: relative; }
.vt-ui .vt-nv-card.cab { z-index: 3; }
.vt-ui .vt-nv-card.busca { z-index: 2; }
.vt-ui .vt-nv-card.abierta > .vt-nv-card-h { border-radius: calc(var(--r-card) - 1px) calc(var(--r-card) - 1px) 0 0; }
.vt-ui .vt-nv-card-h {
    display: flex; align-items: baseline; gap: 6px 10px; flex-wrap: wrap;
    padding: 10px 16px; border-bottom: 1px solid var(--hair); background: #fafbfd;
}
.vt-ui .vt-nv-card-h h4 {
    margin: 0; font-size: 10.5px; font-weight: 800; text-transform: uppercase;
    letter-spacing: .08em; color: var(--muted);
}
.vt-ui .vt-nv-card-h .s { font-size: 11px; color: var(--faint); }
.vt-ui .vt-nv-card-h .der { margin-left: auto; font-size: 11px; color: var(--faint); font-variant-numeric: tabular-nums; }
.vt-ui .vt-nv-card.suave > .vt-nv-card-h { background: var(--navy-050); border-bottom-color: #cfdcf1; }
.vt-ui .vt-nv-card.suave > .vt-nv-card-h h4 { color: var(--navy-500); }

/* ── Los campos: una fila que ENVUELVE, sin grilla de columnas fijas ────────
   En angosto los campos bajan de renglón solos: lo decide el `flex-wrap`, no
   una media query. */
.vt-ui .vt-nv-campos { display: flex; flex-wrap: wrap; gap: 10px; padding: 12px 16px 4px; }
.vt-ui .vt-nv-campos .f { flex: 1 1 155px; min-width: 0; }
.vt-ui .vt-nv-campos .f.ancho { flex: 2 1 240px; }
.vt-ui .vt-nv-campos .f.corto { flex: 0 1 135px; }
.vt-ui .vt-nv-hint { display: block; font-size: 10.5px; color: var(--faint); margin-top: 3px; line-height: 1.35; }
.vt-ui .vt-nv-hint.wrn { color: var(--warn); font-weight: 600; }
.vt-ui .vt-lab .req { color: var(--crit); }

/* ── El buscador: la lupa adentro, el desplegable debajo ───────────────────── */
.vt-ui .vt-nv-smart { position: relative; }
.vt-ui .vt-nv-smart > .material-symbols-outlined {
    position: absolute; left: 9px; top: 8px; font-size: 17px; color: var(--faint); pointer-events: none;
}
.vt-ui .vt-nv-smart .vt-in { padding-left: 32px; }
.vt-ui .vt-nv-drop {
    position: absolute; left: 0; right: 0; top: 100%; z-index: 30;
    margin: 5px 0 0; padding: 4px; list-style: none;
    background: var(--surface); border: 1px solid var(--hair-strong);
    border-radius: 10px; box-shadow: var(--e2);
    max-height: 320px; overflow-y: auto;
}
.vt-ui .vt-nv-drop[hidden] { display: none; }
.vt-ui .vt-nv-opt {
    display: flex; align-items: center; gap: 10px; width: 100%;
    padding: 6px 9px; border: 0; background: none; font: inherit;
    text-align: left; border-radius: 7px; cursor: pointer;
}
.vt-ui .vt-nv-opt:hover, .vt-ui .vt-nv-opt:focus-visible, .vt-ui .vt-nv-opt.foco { background: var(--navy-050); outline: none; }
.vt-ui .vt-nv-opt .nom { min-width: 0; flex: 1; }
.vt-ui .vt-nv-opt .nom b { display: block; font-size: 12.5px; font-weight: 600; color: var(--ink); }
.vt-ui .vt-nv-opt .nom small { display: block; font-size: 11px; color: var(--muted); }
.vt-ui .vt-nv-opt .cod {
    margin-left: auto; font-family: 'IBM Plex Mono', Consolas, monospace;
    font-size: 10.5px; color: var(--faint); white-space: nowrap;
}
.vt-ui .vt-nv-nada { padding: 8px 10px; font-size: 11.5px; color: var(--faint); font-style: italic; line-height: 1.45; }

/* ── «Cómo se cobra»: los tres tiempos, SIEMPRE los tres a la vista ─────────
   El tercero no se esconde cuando no aplica: se apaga y dice cuándo aplica.
   Un campo que aparece y desaparece obliga a descubrir que existe. */
.vt-ui .vt-nv-pago {
    margin: 11px 16px 0; padding: 11px 13px 12px; border-radius: 11px;
    background: #f7f9fc; border: 1px solid var(--hair);
}
.vt-ui .vt-nv-pago > .h { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin-bottom: 9px; }
.vt-ui .vt-nv-pago > .h b { font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .07em; color: var(--navy); }
.vt-ui .vt-nv-pago > .h span { font-size: 11px; color: var(--faint); }
.vt-ui .vt-nv-tiempos { display: flex; align-items: stretch; gap: 8px; flex-wrap: wrap; }
.vt-ui .vt-nv-t { flex: 1 1 170px; min-width: 0; }
.vt-ui .vt-nv-t.ancho { flex: 1.6 1 240px; }
.vt-ui .vt-nv-t > .lbl { display: flex; align-items: center; gap: 6px; margin-bottom: 5px; }
.vt-ui .vt-nv-t .ord {
    width: 15px; height: 15px; flex: 0 0 15px; border-radius: 50%;
    background: var(--navy); color: #fff; font-size: 9.5px; font-weight: 700;
    display: grid; place-items: center; font-style: normal;
}
.vt-ui .vt-nv-t .lbl b { font-size: 11px; font-weight: 700; color: var(--ink); }
.vt-ui .vt-nv-t .por { display: block; font-size: 10px; color: var(--faint); margin-top: 3px; line-height: 1.35; }
.vt-ui .vt-nv-t .por.wrn { color: var(--warn); font-weight: 600; }
.vt-ui .vt-nv-t .vt-in:disabled { background: #f4f6f9; color: var(--faint); cursor: not-allowed; }
.vt-ui .vt-nv-cierre { margin: 9px 0 0; font-size: 11.5px; color: var(--muted); line-height: 1.45; }
.vt-ui .vt-nv-cierre b { color: var(--ink); }

/* Los dos tipos de pago como segmentos: son DOS y excluyentes, así que el
   `<select>` de dos opciones escondía una de ellas detrás de un clic. */
.vt-ui .vt-nv-seg { display: flex; border: 1px solid var(--hair-strong); border-radius: 8px; overflow: hidden; background: var(--surface); }
.vt-ui .vt-nv-seg button {
    flex: 1; padding: 7px 6px; font: inherit; font-size: 11.5px; font-weight: 600;
    color: var(--muted); background: var(--surface); border: 0; cursor: pointer;
    transition: background .14s ease, color .14s ease;
}
.vt-ui .vt-nv-seg button + button { border-left: 1px solid var(--hair-strong); }
.vt-ui .vt-nv-seg button:hover:not(.on) { background: var(--navy-050); color: var(--navy); }
.vt-ui .vt-nv-seg button.on { background: var(--navy); color: #fff; }

/* ── El aviso al margen: entrega incompleta, observación del cliente ───────── */
.vt-ui .vt-nv-risk {
    display: flex; gap: 9px; align-items: flex-start;
    padding: 9px 12px; border-radius: 9px; font-size: 12px; line-height: 1.45; color: var(--ink);
    background: #f7f9fc; border: 1px solid var(--hair-strong); border-left: 3px solid var(--muted);
}
.vt-ui .vt-nv-risk .material-symbols-outlined { flex: 0 0 auto; font-size: 16px; color: var(--muted); }
.vt-ui .vt-nv-risk p { margin: 0; min-width: 0; }
.vt-ui .vt-nv-risk b { font-weight: 700; }
.vt-ui .vt-nv-risk.alerta { background: var(--warn-050); border-color: var(--warn-hair); border-left-color: var(--warn); }
.vt-ui .vt-nv-risk.alerta .material-symbols-outlined, .vt-ui .vt-nv-risk.alerta b { color: var(--warn); }
.vt-ui .vt-nv-risk.critico { background: var(--crit-050); border-color: var(--crit-hair); border-left-color: var(--crit); }
.vt-ui .vt-nv-risk.critico .material-symbols-outlined, .vt-ui .vt-nv-risk.critico b { color: var(--crit); }
.vt-ui .vt-nv-piecab { display: flex; flex-direction: column; gap: 9px; padding: 11px 16px 13px; }
.vt-ui .vt-nv-piecab:empty { display: none; }

/* ── El buscador de artículos y la ficha del APUNTADO ──────────────────────
   La ficha muestra el artículo que está bajo el mouse o con el foco, no el
   elegido: sirve para decidir CUÁL elegir, que es el momento en que hacen
   falta el EAN, el RNPA y el palletizado. */
.vt-ui .vt-nv-buscar { display: flex; gap: 14px; padding: 12px 16px 14px; align-items: flex-start; flex-wrap: wrap; }
.vt-ui .vt-nv-buscar > .caja { flex: 1 1 420px; max-width: 480px; min-width: 0; }
.vt-ui .vt-nv-ficha {
    flex: 1 1 300px; min-width: 0; padding: 10px 12px;
    border: 1px solid var(--hair); border-radius: 10px; background: #fafbfd;
    display: flex; flex-direction: column; gap: 7px;
}
.vt-ui .vt-nv-ficha .fh { display: flex; gap: 9px; align-items: center; }
.vt-ui .vt-nv-ficha .fh b { display: block; font-size: 12.5px; font-weight: 700; color: var(--ink); }
.vt-ui .vt-nv-ficha .fh small { display: block; font-size: 10.5px; color: var(--faint); }
.vt-ui .vt-nv-ficha dl { margin: 0; display: grid; grid-template-columns: auto 1fr; gap: 3px 12px; font-size: 11px; }
.vt-ui .vt-nv-ficha dt { font-size: 9.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--faint); align-self: center; }
.vt-ui .vt-nv-ficha dd { margin: 0; color: var(--ink); font-variant-numeric: tabular-nums; }
.vt-ui .vt-nv-ficha dd .sin { color: var(--warn); font-style: italic; }
.vt-ui .vt-nv-ficha .apunta { font-size: 11px; color: var(--faint); font-style: italic; }

/* ── La miniatura y el nombre del artículo ─────────────────────────────────
   LA FOTO DEL ABM cuando la hay, y el ícono por presentación cuando no — que
   es el caso normal, no el de borde: sólo 16 de los 45 artículos de azúcar
   activos tienen `imageUrl`. Si la foto NO CARGA (borrada del Storage, o de
   antes de un cambio de bucket) el navegador dibuja su ícono de imagen rota,
   que en una lista de artículos se lee como un defecto del pedido: se cae al
   ícono, que es el mismo respaldo de los 6 de cada 10 sin foto. */
.vt-ui .vt-nv-mini {
    flex: 0 0 auto; width: 30px; height: 30px; border-radius: 6px;
    background: var(--navy-050); color: var(--navy-500);
    display: grid; place-items: center; overflow: hidden;
}
.vt-ui .vt-nv-mini .material-symbols-outlined { font-size: 19px; }
.vt-ui .vt-nv-mini img { width: 100%; height: 100%; object-fit: cover; display: block; }
.vt-ui .vt-nv-mini.grande { width: 44px; height: 44px; }
.vt-ui .vt-nv-mini.grande .material-symbols-outlined { font-size: 26px; }

.vt-ui .vt-nv-art { display: flex; align-items: flex-start; gap: 9px; }
.vt-ui .vt-nv-art .nom { min-width: 0; }
/* El nombre ENVUELVE y no se corta con puntos suspensivos: lo que distingue
   dos renglones suele estar al final («Tipo A · bolsa 50 kg»), y «Azúcar
   Com…» no dice nada. Es la lección de la Salida a 390 px, acá en todo ancho. */
.vt-ui .vt-nv-art .nom b { display: block; font-size: 12.5px; font-weight: 600; color: var(--ink); white-space: normal; overflow-wrap: anywhere; }
.vt-ui .vt-nv-art .cods { display: block; font-family: 'IBM Plex Mono', Consolas, monospace; font-size: 10.5px; color: var(--faint); margin-top: 1px; }
.vt-ui .vt-nv-art .cods .sin { font-family: inherit; color: var(--warn); font-style: italic; }
.vt-ui .vt-nv-pallet { display: block; font-size: 10.5px; color: var(--muted); margin-top: 2px; line-height: 1.4; }
.vt-ui .vt-nv-pallet b { color: var(--ink); font-weight: 600; }
.vt-ui .vt-nv-pallet.sin { color: var(--warn); font-style: italic; }
/* Las marcas del renglón: el genérico sin marca y el exclusivo de otro. */
.vt-ui .vt-nv-marca {
    display: inline-flex; align-items: center; gap: 5px; margin-top: 4px;
    font-size: 9.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
    padding: 2px 7px; border-radius: 5px;
    color: var(--warn); background: var(--warn-050); border: 1px solid var(--warn-hair);
}
.vt-ui .vt-nv-marca .material-symbols-outlined { font-size: 12px; }

/* ── LA CUENTA DEL RENGLÓN — qué es esa cantidad en bultos y en pallets ─────
   Cuatro niveles y sólo dos frenan:
     · `rota`    — medio bulto no se despacha. FRENA (nuevo en la etapa 6).
     · `parcial` — eligió un formato de pallet fijo y la cantidad no es
                   múltiplo. FRENA, como frenaba antes con un `alert`.
     · `suelta`  — no cierra pallet entero y NO frena: uno de cada cuatro
                   renglones reales está así y el pedido sale igual.
     · `cierra` / `entera` — está bien; se dice en verde o en gris.
   Los atajos son las cantidades vecinas que SÍ valen: se aprietan y listo. */
.vt-ui .vt-nv-cuenta {
    display: block; margin: 4px 0 0 auto; max-width: 190px;
    font-size: 10.5px; line-height: 1.4; text-align: right; color: var(--muted);
}
.vt-ui .vt-nv-cuenta b { color: var(--ink); font-weight: 700; }
.vt-ui .vt-nv-cuenta.cierra { color: var(--ok); } .vt-ui .vt-nv-cuenta.cierra b { color: var(--ok); }
.vt-ui .vt-nv-cuenta.suelta { color: var(--warn); } .vt-ui .vt-nv-cuenta.suelta b { color: var(--warn); }
.vt-ui .vt-nv-cuenta.rota, .vt-ui .vt-nv-cuenta.parcial { color: var(--crit); }
.vt-ui .vt-nv-cuenta.rota b, .vt-ui .vt-nv-cuenta.parcial b { color: var(--crit); }
.vt-ui .vt-nv-paso { display: flex; gap: 4px; justify-content: flex-end; margin-top: 4px; flex-wrap: wrap; }
.vt-ui .vt-nv-paso button {
    font: inherit; font-size: 10.5px; font-weight: 600; cursor: pointer;
    color: var(--navy); background: var(--navy-050); border: 1px solid #cfdcf1;
    border-radius: 5px; padding: 1px 6px; white-space: nowrap; font-variant-numeric: tabular-nums;
    transition: background .14s ease, color .14s ease;
}
.vt-ui .vt-nv-paso button:hover, .vt-ui .vt-nv-paso button:focus-visible { background: var(--navy); color: #fff; outline: none; }

/* El campo numérico de una celda. Es `type="text"` con `inputmode`: el
   `type="number"` nativo RECHAZA la coma con el teclado castellano. */
.vt-ui .vt-nv-num {
    width: 96px; padding: 4px 8px; font: inherit; font-size: 12.5px;
    text-align: right; color: var(--ink); background: var(--surface);
    border: 1px solid var(--hair-strong); border-radius: 7px;
    font-variant-numeric: tabular-nums;
    transition: border-color .14s ease, box-shadow .18s var(--curva);
}
.vt-ui .vt-nv-num:focus { outline: none; border-color: var(--navy); box-shadow: 0 0 0 3px var(--navy-050); }
.vt-ui .vt-nv-num.rota { border-color: var(--crit); background: var(--crit-050); }
.vt-ui select.vt-nv-fmt {
    margin: 4px 0 0 auto; width: 100%; max-width: 190px; display: block;
    font: inherit; font-size: 10.5px; color: var(--muted); cursor: pointer;
    background: var(--surface); border: 1px solid var(--hair); border-radius: 6px; padding: 2px 4px;
}
.vt-ui select.vt-nv-fmt:focus { outline: none; border-color: var(--navy); box-shadow: 0 0 0 3px var(--navy-050); }
.vt-ui .vt-nv-quitar {
    background: none; border: 1px solid transparent; border-radius: 7px;
    padding: 3px 4px; cursor: pointer; color: var(--faint); line-height: 0;
    transition: background-color .14s ease, color .14s ease;
}
.vt-ui .vt-nv-quitar .material-symbols-outlined { font-size: 17px; }
.vt-ui .vt-nv-quitar:hover, .vt-ui .vt-nv-quitar:focus-visible { background: var(--crit-050); color: var(--crit); border-color: var(--crit-hair); outline: none; }

/* ── La tabla del carrito ──────────────────────────────────────────────────
   `min-width` y la caja scrollea de costado: sin él, en angosto la columna del
   artículo se aplasta hasta partir el nombre letra por letra. Es la trampa que
   la Mesa pagó a 390 px («Transpor tes Del Valle»). */
.vt-ui .vt-nv-tbl { padding: 0 16px; overflow-x: auto; }
.vt-ui table.vt-nv-g { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 12.5px; color: var(--ink); margin-top: 4px; min-width: 620px; }
.vt-ui table.vt-nv-g th {
    text-align: left; font-size: 10px; font-weight: 700; letter-spacing: .07em;
    text-transform: uppercase; color: var(--faint); padding: 9px; white-space: nowrap;
    border-bottom: 2px solid var(--hair-strong);
}
.vt-ui table.vt-nv-g td { padding: 9px; border-bottom: 1px solid var(--hair); vertical-align: top; }
.vt-ui table.vt-nv-g tr:last-child td { border-bottom: none; }
.vt-ui table.vt-nv-g .n { text-align: right; font-variant-numeric: tabular-nums; }
.vt-ui table.vt-nv-g td.imp { font-weight: 700; padding-top: 13px; }
/* EL PIE DE LA PARTE VA AFUERA de la caja que scrollea: la tabla se corre de
   costado en angosto y un total adentro quedaría a la derecha del borde — la
   cifra que cierra el pedido sería justo la que hay que ir a buscar. */
.vt-ui .vt-nv-pie {
    display: flex; align-items: baseline; gap: 6px 16px; flex-wrap: wrap;
    padding: 9px 16px 12px; font-size: 12px; color: var(--muted);
}
.vt-ui .vt-nv-pie b { font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.vt-ui .vt-nv-pie .tot { margin-left: auto; font-weight: 700; color: var(--ink); }
/* El total del pedido. Regla dura arriba: es la única cifra que cierra todo, y
   no compite con nada por tamaño (nada de números gigantes). */
.vt-ui .vt-nv-total { display: flex; align-items: baseline; gap: 12px; padding: 11px 18px; border-top: 2px solid var(--ink); }
.vt-ui .vt-nv-total .t { font-size: 10.5px; font-weight: 800; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); }
.vt-ui .vt-nv-total .v { margin-left: auto; font-size: 17px; font-weight: 800; font-variant-numeric: tabular-nums; }
.vt-ui .vt-nv-vacio { padding: 26px 16px; text-align: center; font-size: 12px; color: var(--faint); font-style: italic; line-height: 1.5; }

/* ── La pre-logística: una tarjeta que se pliega ───────────────────────────── */
.vt-ui .vt-nv-acor {
    display: flex; align-items: center; gap: 10px; width: 100%;
    padding: 10px 16px; background: #fafbfd; border: 0; border-bottom: 1px solid var(--hair);
    font: inherit; font-size: 12px; color: var(--muted); cursor: pointer; text-align: left;
    transition: background .14s ease;
}
.vt-ui .vt-nv-acor:hover { background: var(--navy-050); }
.vt-ui .vt-nv-acor b { font-size: 10.5px; font-weight: 800; text-transform: uppercase; letter-spacing: .08em; color: var(--navy); }
.vt-ui .vt-nv-acor .sp { flex: 1; }
.vt-ui .vt-nv-acor .res { font-size: 11px; color: var(--faint); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vt-ui .vt-nv-acor .material-symbols-outlined { color: var(--navy-300); transition: transform .18s var(--curva); }
.vt-ui .vt-nv-acor[aria-expanded="true"] .material-symbols-outlined { transform: rotate(180deg); }
.vt-ui .vt-nv-log[hidden] { display: none; }

/* ── 390 px ────────────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
    .vt-ui .vt-nv { padding: 0 12px 20px; }
    .vt-ui .vt-nv-buscar > .caja { flex: 1 0 100%; max-width: none; }
    .vt-ui .vt-nv-ficha { flex: 1 0 100%; }
    .vt-ui .vt-nv-modo { gap: 8px; }
    .vt-ui .vt-nv-modo .t { flex: 1 0 100%; }
    /* La cuenta se angosta con su columna: a 390 px, con 190 px de ancho, se
       montaba sobre el precio. */
    .vt-ui .vt-nv-cuenta, .vt-ui select.vt-nv-fmt { max-width: 128px; }
    .vt-ui .vt-nv-num { width: 84px; }
    .vt-ui .vt-nv-total .v { font-size: 15px; }
}

/* =============================================================================
   11. LOS PAPELES — la banda del día en Pendientes, etapa 8
   =============================================================================
   Ronda 7: ganó la 1, «lo que se ve es lo que sale», con una corrección de
   Hernán que cambió el diseño y hay que dejar escrita: en Pendientes **no se
   filtra por fecha, se AGRUPA**. La lámina dibujaba un filtro que dejaba 6 de
   89 a la vista; lo que va es una banda que separa cada día de carga, con
   TODOS los pedidos adentro, el mismo orden y la misma paginación. El verbo de
   la banda imprime EXACTAMENTE ese grupo.

   POR QUÉ UNA BANDA Y NO UNA TARJETA. «En carga» agrupa por NP con una tarjeta
   de plano 2 (§6), y ahí funciona: son pocos grupos y cada uno es un viaje con
   su propia logística. Acá el diagnóstico contra producción dio **17 grupos
   para 52 pedidos, 9 de ellos de un solo pedido** —los días cercanos son densos
   (11, 8, 7, 7) y los lejanos son sueltos—. Diecisiete marcos alrededor de 52
   filas es más marco que lista. Una banda de una línea cuesta casi nada.

   Y ES UNA FILA DE LA MISMA TABLA (`<td colspan>`), no una tabla por día: con
   una tabla por grupo cada una calcularía sus propios anchos y las columnas
   dejarían de estar alineadas entre días, que es justo lo que hace legible una
   lista larga.

   ADENTRO DEL `<td>` NO HAY FLEX. Un `display: flex` sobre la celda la saca del
   modelo de tabla y el `colspan` deja de valer: la banda mediría una columna.
   Así que los hijos son inline-block y el verbo va con `float: right`, que es
   lo que sí funciona adentro de una celda.
   ============================================================================= */

.vt-ui tr.vt-dia > td {
    position: relative;
    padding: 0 0 0 14px;
    background: #eef2f8;
    border-bottom: 1px solid var(--hair-strong);
    white-space: nowrap;
}
/* La franja al margen, del mismo vocabulario que la de las filas (§6): 3 px, y
   el color dice cuándo. */
.vt-ui tr.vt-dia > td::before {
    content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
    background: var(--navy-300);
}
.vt-ui tr.vt-dia b.dia {
    display: inline-block; padding: 7px 0;
    font-size: 11.5px; font-weight: 800; letter-spacing: .04em;
    text-transform: uppercase; color: var(--navy);
}
.vt-ui tr.vt-dia .n {
    display: inline-block; margin-left: 12px;
    font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums;
}
.vt-ui tr.vt-dia .vt-b { margin-left: 10px; vertical-align: 1px; }
.vt-ui tr.vt-dia .vt-min { float: right; margin: 4px 12px 4px 0; }

/* Los tres momentos de un día de carga. HOY es el único que no se puede pasar
   por alto, así que es el único en rojo. */
.vt-ui tr.vt-dia.hoy > td { background: var(--crit-050); }
.vt-ui tr.vt-dia.hoy > td::before { background: var(--crit); }
.vt-ui tr.vt-dia.hoy b.dia { color: var(--crit); }
.vt-ui tr.vt-dia.manana > td { background: var(--warn-050); }
.vt-ui tr.vt-dia.manana > td::before { background: var(--warn); }
.vt-ui tr.vt-dia.manana b.dia { color: var(--warn); }
/* Un día de carga YA PASADO con el pedido todavía pendiente no es un error de
   la pantalla: es un pedido que se quedó. Se dice, no se esconde. */
.vt-ui tr.vt-dia.vencido > td::before { background: var(--warn); }
.vt-ui tr.vt-dia.vencido b.dia { color: var(--warn); }

/* Los dos grupos que NO son un día —«con turno de descarga, sin fecha de carga»
   y «sin turno»— van en gris y sin verbo: no tienen cronograma que imprimir. */
.vt-ui tr.vt-dia.suelto > td { background: #f4f6f9; }
.vt-ui tr.vt-dia.suelto > td::before { background: var(--hair-strong); }
.vt-ui tr.vt-dia.suelto b.dia { color: var(--muted); }

/* ── 640 px: la banda envuelve y el verbo baja de renglón ──────────────────── */
@media (max-width: 640px) {
    .vt-ui tr.vt-dia > td { white-space: normal; padding-left: 10px; }
    .vt-ui tr.vt-dia .vt-min { float: none; display: inline-block; margin: 0 0 7px 10px; }
}
