/* =============================================================================
   IDENTIDAD VISUAL — EL FORMULARIO DE MOVIMIENTOS (MW)
   =============================================================================
   Manual: docs/identidad-visual.md. Proyecto: docs/RUNBOOK-FORM-MW.md, etapa 4.
   La forma está APROBADA y no se rediscute: es la **propuesta B, «los pasos»**
   del prototipo `docs/form-mw/02-prototipo-A.html` (Hernán, 09/08/2026, con la
   condición de la regla 11 — ir y volver sin perder nada).

   LA REGLA QUE ORDENA ESTE ARCHIVO: **el formulario tiene ocho caras y UNA sola
   espina**. Cinco pasos fijos —Contexto · Qué sale/entra · Cómo viaja ·
   Papeles · Confirmar— que no cambian en ninguna de las ocho; lo que cambia es
   cuáles vienen resueltos. Por eso acá no hay ni una regla que dependa del
   modo: no existe `.mw-ui.despacho` ni `.mw-paso.recepcion`. Si alguna vez hace
   falta una, la propuesta no se sostuvo y hay que parar (§ etapa 4 del runbook).

   EL COLOR ES DEL ESTADO, NUNCA DE LA CATEGORÍA (§1.1 del manual). Hasta hoy el
   modo se anunciaba con CINCO colores —índigo despacho, verde recepción, rosa
   devolución, esmeralda pre-lote, ámbar manual— que es exactamente lo que el
   manual prohíbe. Acá el modo se dice **con palabras**, en la cinta, y el verde
   / ámbar / rojo quedan para «resuelto», «falta» y «no se puede».

   ── POR QUÉ LOS CONTROLES SIGUEN LLAMÁNDOSE `.form-input` Y `.label-sm` ───────
   Son las clases que ya usan los 26 campos, y **once piezas de JS les agregan y
   les sacan utilitarias de Tailwind en caliente** (`bg-gray-100` al bloquear,
   `bg-amber-50` al vincular una factura de Flexxus, `text-blue-900` al liberar
   la cantidad). Renombrarlas obligaría a tocar esa lógica —que es justo lo que
   esta etapa promete no tocar—, así que se VISTEN donde están. Las reglas de
   acá llevan dos clases de especificidad (`.mw-ui .form-input`, 0,2,0) y le
   ganan a la utilitaria suelta (0,1,0), así que el gris del candado sigue
   diciendo «apagado» sin romper la identidad.

   `.label-sm` además no estaba en NINGÚN css: la inyectaba el módulo de
   Movimientos de Endulzantes. Los 26 rótulos del formulario dependían de que
   otro módulo se hubiera cargado antes. Acá deja de ser una casualidad.

   TODO va scopeado bajo `.mw-ui` y con prefijo `mw-` (§6 del manual).

   ── Y DESDE LA ETAPA 2 ESTA HOJA TAMBIÉN VISTE LA PANTALLA ───────────────────
   Este archivo nació para el FORMULARIO y decía acá que «el resto de
   Movimientos —la grilla, el detalle, acciones-stock— sigue en Tailwind y una
   clase suelta lo rompería». La etapa 2 de docs/RUNBOOK-MOVIMIENTOS-STOCK.md
   levanta esa advertencia a medias y a propósito: el ARMAZÓN de la pantalla
   (§13) entra acá, y la grilla que vive adentro sigue en Tailwind hasta la
   etapa 3. No nace una hoja nueva ni un scope nuevo — un `.mwg-ui` aparte para
   la grilla sería inventar un segundo dueño de la misma pantalla.

   ── Y DESDE LA ETAPA 8 LA ADVERTENCIA SE LEVANTA ENTERA ──────────────────────
   Ya no queda una superficie del módulo en Tailwind: las cuatro que faltaban
   —exportar, elegir la orden de carga, imputar un Líquido Producto y la cola de
   recepción— entraron en §20. La única excepción declarada es el MOBILE
   (`renderMobileMovimientos`), que está fuera de alcance como el de Facturación
   y el del Tarifario, y el formulario, que ya tenía su hoja: ésta.

   El índice, entonces: §1-12 el FORMULARIO · §13-17 la PANTALLA (armazón,
   desplegable, 390 px, planilla, Pendientes) · §18-20 los DIÁLOGOS (los tres de
   acción, la ficha en dos paneles, y las cuatro de la etapa 8).

   Lo que NO cambia: no existe ni una clase que dependa del modo. La grilla no
   puede traer un `.mw-ui.despacho` por la ventana.

   La paleta NO está acá: sale entera de core/tokens.css. Ningún token nuevo.
   ========================================================================== */

/* El `box-sizing` es PROPIO, no heredado del preflight de Tailwind: apoyarse en
   el reset de otro framework es una dependencia invisible, y esta migración va
   justamente hacia sacarlo. */
.mw-ui, .mw-ui *, .mw-ui *::before, .mw-ui *::after { box-sizing: border-box; }

.mw-ui .material-symbols-outlined { font-variation-settings: 'wght' 400; vertical-align: middle; }

/* Trampa §7 del manual para los ROOT de los modales, que llevan `.mw-ui` ellos
   mismos y por eso no los alcanza la regla agrupada de tokens.css. El
   desplegable «Registrar» de la barra es el mismo caso: cuelga del <body>, así
   que lleva el scope en su propio elemento (ver §13). */
.mw-ui.mw-velo.hidden { display: none; }
.mw-ui.mw-menu.hidden { display: none; }

/* Y LA MISMA TRAMPA CON EL ATRIBUTO `hidden`, que es la que usa el armazón para
   esconder los pasos que no están abiertos. `hidden` vale exactamente lo que
   `display:none` en la hoja del NAVEGADOR (especificidad cero), así que
   cualquier regla de autor que declare `display` le gana: `.mw-btn` es
   `inline-flex` y `.mw-resuelto` es `flex`, con lo que el botón «Guardar» se
   veía al lado de «Siguiente» y el renglón colapsado de un paso se veía encima
   del paso abierto. Lo destapó la foto de pantalla, no el banco de payloads.
   (feedback_atributo_hidden_pierde_contra_display_de_autor) */
.mw-ui [hidden] { display: none !important; }

/* =============================================================================
   1. EL CUERPO
   ========================================================================== */
.mw-ui { background: var(--canvas); }

.mw-ui .mw-body {
    padding: 14px var(--gutter) 30px;
    max-width: 1440px; margin: 0 auto;
    display: flex; flex-direction: column; gap: 13px;
    /* Los modales y los avisos van `absolute`: sin un ancestro posicionado se
       cuelgan del viewport y aparecen en cualquier lado. */
    position: relative;
}

/* Un dato ausente es información (§1.4): gris, más chico, y dice qué falta. */
.mw-ui .mw-vacio { color: var(--faint); font-style: italic; font-weight: 500; }

/* =============================================================================
   2. LA BARRA — volver, el título del movimiento y la carga múltiple
   -----------------------------------------------------------------------------
   A 390 px las acciones no entran al lado del título (crumb + dos botones de
   36 px se pisan): abajo se reparten en dos renglones.
   ========================================================================== */
.mw-ui .mw-top {
    display: flex; align-items: center; gap: 11px; flex-wrap: wrap;
    padding-bottom: 2px;
}
.mw-ui .mw-top h3 {
    margin: 0; font-size: 17px; font-weight: 700; letter-spacing: -.01em;
    color: var(--ink); display: flex; align-items: center; gap: 8px; min-width: 0;
}
.mw-ui .mw-top h3 .material-symbols-outlined { font-size: 20px; color: var(--navy-500); }
.mw-ui .mw-volver {
    flex: none; width: 34px; height: 34px; border-radius: 9px;
    border: 1px solid var(--hair-strong); background: var(--surface); color: var(--muted);
    display: grid; place-items: center; cursor: pointer;
    transition: background .15s var(--curva), color .15s var(--curva), transform .15s var(--curva);
}
.mw-ui .mw-volver:hover, .mw-ui .mw-volver:focus-visible {
    background: var(--navy-050); color: var(--navy); outline: none;
}
.mw-ui .mw-volver:active { transform: scale(.94); }

/* El interruptor de carga múltiple. Era una píldora azul con un switch pintado
   a mano en Tailwind; acá es una casilla, que es lo que es. */
.mw-ui .mw-multi {
    margin-left: auto; display: inline-flex; align-items: center; gap: 8px;
    border: 1px solid var(--hair-strong); background: var(--surface);
    border-radius: 10px; padding: 7px 12px; cursor: pointer; user-select: none;
    font-size: 12px; font-weight: 600; color: var(--muted);
    transition: border-color .15s var(--curva), color .15s var(--curva), background .15s var(--curva);
}
.mw-ui .mw-multi:hover { border-color: var(--navy-300); color: var(--navy); }
.mw-ui .mw-multi input { accent-color: var(--navy); width: 15px; height: 15px; cursor: pointer; }
.mw-ui .mw-multi:has(input:checked) {
    background: var(--navy-050); border-color: #cfdcef; color: var(--navy); font-weight: 700;
}

/* =============================================================================
   3. LA CINTA DE CONTEXTO — el modo dicho con PALABRAS
   -----------------------------------------------------------------------------
   `.mw-dir` es la dirección (INGRESO / EGRESO), que llega desde la puerta y no
   se elige adentro (regla 7). Es navy —marca, no estado— y es la misma caja en
   las ocho caras.
   ========================================================================== */
.mw-ui .mw-cinta {
    background: var(--surface); border: 1px solid var(--hair);
    border-radius: var(--r-card); box-shadow: var(--shadow);
    display: flex; align-items: center; gap: 12px; padding: 11px 16px; flex-wrap: wrap;
}
.mw-ui .mw-dir {
    display: inline-flex; align-items: center; gap: 7px; border-radius: 9px;
    padding: 5px 12px; font-weight: 700; font-size: 12px;
    letter-spacing: .08em; text-transform: uppercase;
    background: var(--navy-050); border: 1px solid #cfdcef; color: var(--navy); flex: none;
}
.mw-ui .mw-dir .material-symbols-outlined { font-size: 17px; }
.mw-ui .mw-qu { min-width: 0; flex: 1 1 240px; }
.mw-ui .mw-qu .t { display: block; font-size: 14px; font-weight: 700; letter-spacing: -.01em; line-height: 1.25; }
.mw-ui .mw-qu .d { display: block; font-size: 11.5px; color: var(--muted); }
/* Movimiento de terceros: no toca el stock contable de Moyco. Eso SÍ es estado. */
.mw-ui .mw-qu .d.terceros { color: var(--warn); font-weight: 600; }

.mw-ui .mw-gates { margin-left: auto; display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.mw-ui .mw-gates .cap {
    font-size: 10px; font-weight: 700; letter-spacing: .09em;
    text-transform: uppercase; color: var(--faint);
}
.mw-ui .mw-chip {
    display: inline-flex; align-items: center; gap: 6px; border-radius: 999px;
    padding: 4px 11px; font-size: 11.5px; font-weight: 600;
    border: 1px solid var(--hair-strong); color: var(--muted);
    background: var(--surface); font-family: inherit;
}
.mw-ui .mw-chip .material-symbols-outlined { font-size: 14px; }
.mw-ui .mw-chip.ok   { background: var(--ok-050);   border-color: var(--ok-hair);   color: var(--ok); }
.mw-ui .mw-chip.warn { background: var(--warn-050); border-color: var(--warn-hair); color: var(--warn); }
.mw-ui .mw-chip.nav  { background: var(--navy-050); border-color: #cfdcef;          color: var(--navy); }
/* Las dos que agrega la ETAPA 3. La planilla necesitaba una pastilla para decir
   el ámbito del buscador y otra para un conteo apagado, y `.mw-chip` ya era la
   pastilla de este módulo: inventarle una `.mw-b` al lado habría dejado la hoja
   con DOS vocabularios de badge, que es exactamente lo que esta migración vino
   a sacar. Se le agregan las dos variantes que le faltaban y nada más. */
.mw-ui .mw-chip.mal  { background: var(--crit-050); border-color: var(--crit-hair); color: var(--crit); }
.mw-ui .mw-chip.mut  { background: #f4f6f9;         border-color: var(--hair);      color: var(--muted); }

/* =============================================================================
   4. LA ESPINA — los cinco pasos, y qué está resuelto
   -----------------------------------------------------------------------------
   Es la pieza que define la propuesta B. A la izquierda el mapa completo (nunca
   cambia); a la derecha el paso abierto y los demás colapsados en un renglón
   que dice lo que ya tienen adentro.
   ========================================================================== */
/* Las DOS columnas van con `minmax(0, …)` / `min-width:0`. Un item de grid mide
   `min-width:auto` por defecto, o sea que no baja de su contenido mínimo: con la
   espina acostada a 390 px (una fila de cinco botones) su mínimo son 554 px y
   estira la columna, y con ella el documento entero. El scroll lateral no se ve
   en una captura de pantalla completa — se mide, y por eso `--foto` lo mide.
   Es la trampa `feedback_grid_sin_minwidth_cero_se_estira`, otra vez. */
.mw-ui .mw-b2 { display: grid; grid-template-columns: 236px minmax(0, 1fr); gap: 13px; align-items: start; }
.mw-ui .mw-b2 > * { min-width: 0; }

.mw-ui .mw-spine {
    background: var(--surface); border: 1px solid var(--hair);
    border-radius: var(--r-card); box-shadow: var(--shadow);
    padding: 9px; display: flex; flex-direction: column; gap: 2px;
    position: sticky; top: 0;
}
.mw-ui .mw-step {
    display: flex; align-items: flex-start; gap: 10px; padding: 9px 10px;
    border-radius: 10px; border: 0; border-left: 3px solid transparent;
    text-align: left; width: 100%; font-family: inherit; background: none; cursor: pointer;
    transition: background .15s var(--curva), border-color .15s var(--curva);
}
.mw-ui .mw-step:hover:not(:disabled), .mw-ui .mw-step:focus-visible:not(:disabled) {
    background: var(--navy-050); outline: none;
}
.mw-ui .mw-step:disabled { cursor: not-allowed; opacity: .55; }
.mw-ui .mw-step .ico {
    width: 19px; height: 19px; flex: none; border-radius: 50%;
    border: 2px solid var(--hair-strong); display: flex; align-items: center;
    justify-content: center; font-size: 11px; font-weight: 700; color: var(--faint);
    margin-top: 1px; font-variant-numeric: tabular-nums;
}
.mw-ui .mw-step .ico .material-symbols-outlined { font-size: 12px; }
.mw-ui .mw-step .q { min-width: 0; }
.mw-ui .mw-step .t { display: block; font-size: 12.5px; font-weight: 700; color: var(--muted); line-height: 1.25; }
/* La bajada se corta a dos renglones: un faltante largo no puede empujar la
   espina y correr el paso de abajo. */
.mw-ui .mw-step .d {
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden; font-size: 11px; color: var(--faint); line-height: 1.3; margin-top: 1px;
}
.mw-ui .mw-step.ok   .ico { border-color: var(--ok); background: var(--ok); color: #fff; }
.mw-ui .mw-step.ok   .t   { color: var(--ink); }
.mw-ui .mw-step.ok   .d   { color: var(--ok); font-weight: 600; }
.mw-ui .mw-step.warn .ico { border-color: var(--warn); color: var(--warn); }
.mw-ui .mw-step.warn .d   { color: var(--warn); font-weight: 600; }
.mw-ui .mw-step.now       { background: var(--navy-050); border-left-color: var(--navy); }
.mw-ui .mw-step.now .t    { color: var(--navy); }
.mw-ui .mw-step.now .ico  { border-color: var(--navy); color: var(--navy); }
.mw-ui .mw-step.lock .ico { border-style: dashed; }

.mw-ui .mw-panel { display: flex; flex-direction: column; gap: 13px; min-width: 0; }

/* El paso colapsado: un renglón que dice qué quedó adentro. No es decorativo —
   es lo que hace que ir y volver no cueste nada (regla 11). */
.mw-ui .mw-resuelto {
    background: var(--surface); border: 1px solid var(--hair);
    border-radius: var(--r-card); box-shadow: var(--shadow);
    padding: 10px 16px; display: flex; align-items: center; gap: 11px; flex-wrap: wrap;
    width: 100%; font-family: inherit; text-align: left; cursor: pointer;
    transition: transform .15s var(--curva), box-shadow .15s var(--curva), border-color .15s var(--curva);
}
.mw-ui .mw-resuelto:hover, .mw-ui .mw-resuelto:focus-visible {
    transform: translateY(-1px); box-shadow: var(--e2); border-color: var(--navy-300); outline: none;
}
.mw-ui .mw-resuelto .ck { color: var(--ok); font-size: 18px; flex: none; }
.mw-ui .mw-resuelto.pend .ck { color: var(--warn); }
.mw-ui .mw-resuelto .q { min-width: 0; flex: 1; }
.mw-ui .mw-resuelto .t { display: block; font-size: 12.5px; font-weight: 700; }
.mw-ui .mw-resuelto .d { display: block; font-size: 11.5px; color: var(--muted); }
.mw-ui .mw-resuelto .ab {
    font-size: 11px; font-weight: 700; color: var(--navy-500); flex: none;
}

/* El paso que NO está abierto se OCULTA, no se desmonta — es la mitad de la
   regla 11 que decide dónde vive el estado. El guardado lee `#mov-remito-2`
   directo del DOM para el número legal del remito (form-mw-guardado.js): si el
   paso «Papeles» se desmontara al pasar al 4, el remito se grabaría vacío. Con
   los cinco pasos siempre montados no hay estado que mudar ni que restaurar, y
   el banco lo vigila con el escenario DESPACHO-OC-REMITO. */
.mw-ui .mw-paso[hidden] { display: none; }

/* =============================================================================
   5. LAS TARJETAS Y LOS CAMPOS
   ========================================================================== */
.mw-ui .mw-card {
    background: var(--surface); border: 1px solid var(--hair);
    border-radius: var(--r-card); box-shadow: var(--shadow); padding: 14px 16px 16px;
}
.mw-ui .mw-card + .mw-card { margin-top: 13px; }
.mw-ui .mw-card > h5 {
    margin: 0 0 12px; font-size: 10.5px; font-weight: 700; letter-spacing: .09em;
    text-transform: uppercase; color: var(--faint); display: flex; align-items: center;
    gap: 9px; border-bottom: 1px solid var(--hair); padding-bottom: 8px; flex-wrap: wrap;
}
.mw-ui .mw-card > h5 .n {
    margin-left: auto; font-size: 11px; letter-spacing: 0; text-transform: none;
    color: var(--muted); font-weight: 600;
}
.mw-ui .mw-card > h5 .n b { color: var(--ink); font-variant-numeric: tabular-nums; }

/* `min-width:0` en las celdas: sin eso un select largo estira la columna y la
   grilla desborda (trampa ya pagada, feedback_grid_sin_minwidth_cero_se_estira). */
.mw-ui .mw-grid { display: grid; gap: 13px; grid-template-columns: repeat(4, 1fr); }
.mw-ui .mw-grid > * { min-width: 0; }
.mw-ui .mw-grid.g5 { grid-template-columns: repeat(5, 1fr); }
.mw-ui .mw-grid.g3 { grid-template-columns: repeat(3, 1fr); }
.mw-ui .mw-grid.g2 { grid-template-columns: repeat(2, 1fr); }
.mw-ui .mw-grid .sp2 { grid-column: span 2; }

/* --- Los 26 controles: se visten donde están (ver la cabecera del archivo) --- */
.mw-ui .label-sm {
    display: flex; align-items: center; gap: 6px; font-size: 10px; font-weight: 700;
    letter-spacing: .09em; text-transform: uppercase; color: var(--faint);
    margin-bottom: 5px; min-height: 15px;
}
.mw-ui .label-sm .der { margin-left: auto; letter-spacing: 0; text-transform: none; font-size: 10.5px; }

.mw-ui .form-input {
    width: 100%; font-family: inherit; font-size: 13px; color: var(--ink);
    padding: 8px 10px; border-radius: 9px; border: 1px solid var(--hair-strong);
    background: var(--surface);
    transition: border-color .15s var(--curva), box-shadow .15s var(--curva);
}
.mw-ui textarea.form-input { resize: vertical; min-height: 38px; }
.mw-ui .form-input:focus {
    outline: none; border-color: var(--navy-500); box-shadow: 0 0 0 3px var(--navy-050);
}
/* Un campo apagado se ve apagado — y le gana a la utilitaria que le cuelga el
   JS de los candados, que es lo que hoy pinta el gris. */
.mw-ui .form-input:disabled,
.mw-ui .form-input[readonly] {
    background: var(--canvas); color: var(--muted); cursor: not-allowed; border-color: var(--hair);
}
.mw-ui .form-input:disabled:focus, .mw-ui .form-input[readonly]:focus { box-shadow: none; border-color: var(--hair); }

/* Los pares punto-de-venta / número (remito, factura). OJO: la estructura
   `<div><label></label><div><input id="mov-factura-1"></div></div>` la NAVEGA
   el cargador de devoluciones para renombrar «Factura» → «Nota de Crédito»
   (form-mw-cargadores.js, `relabel`): el label tiene que seguir siendo hijo del
   ABUELO del input. Cambiar este anidado rompe ese renombre en silencio. */
.mw-ui .mw-par { display: flex; }
.mw-ui .mw-par .form-input:first-child { width: 38%; text-align: center; border-radius: 9px 0 0 9px; border-right: 0; }
.mw-ui .mw-par .form-input:last-child  { width: 62%; border-radius: 0 9px 9px 0; }

/* Campo + botón pegado (chofer, tarifa). */
.mw-ui .mw-conbtn { display: flex; }
.mw-ui .mw-conbtn > .form-input { border-radius: 9px 0 0 9px; border-right: 0; }
.mw-ui .mw-mas {
    flex: none; width: 36px; border: 1px solid var(--hair-strong); border-radius: 0 9px 9px 0;
    background: var(--surface); color: var(--navy-500); cursor: pointer;
    display: grid; place-items: center;
    transition: background .15s var(--curva), color .15s var(--curva), transform .15s var(--curva);
}
.mw-ui .mw-mas:hover, .mw-ui .mw-mas:focus-visible { background: var(--navy-050); color: var(--navy); outline: none; }
.mw-ui .mw-mas:active { transform: scale(.94); }
.mw-ui .mw-mas .material-symbols-outlined { font-size: 18px; }
.mw-ui .mw-mas + .mw-mas { border-radius: 0 9px 9px 0; border-left: 0; }

.mw-ui .mw-check {
    display: inline-flex; align-items: center; gap: 7px; font-size: 11px; font-weight: 600;
    color: var(--muted); cursor: pointer; margin-top: 6px; user-select: none;
}
.mw-ui .mw-check input { accent-color: var(--navy); width: 14px; height: 14px; cursor: pointer; }
.mw-ui .mw-check:hover { color: var(--navy); }

.mw-ui .mw-ayuda { font-size: 11px; color: var(--muted); margin-top: 4px; }
.mw-ui .mw-ayuda.ok   { color: var(--ok);   font-weight: 600; }
.mw-ui .mw-ayuda.warn { color: var(--warn); font-weight: 600; }
.mw-ui .mw-ayuda.mal  { color: var(--crit); font-weight: 600; }

/* Dato decidido: lo que trae la OC / el MW origen / el pre-lote NO es un campo
   gris, es un dato (la pieza que la propuesta B conserva de la A). */
.mw-ui .mw-ro .k {
    display: block; font-size: 10px; font-weight: 700; letter-spacing: .09em;
    text-transform: uppercase; color: var(--faint); margin-bottom: 2px;
}
.mw-ui .mw-ro .v { display: block; font-size: 13.5px; font-weight: 600; line-height: 1.3; }
.mw-ui .mw-ro .v small { font-weight: 500; color: var(--muted); }
.mw-ui .mw-ro.vacio .v { color: var(--faint); font-style: italic; font-weight: 500; }
/* Un renglón que se vuelve CONTROL (la caja Logística abierta desde el Parte
   Diario de Planta, RUNBOOK-PARTE-DIARIO §3.4). El control ocupa el ancho del
   renglón y hereda su peso; la tarifa lleva el importe y la modalidad en una
   sola línea, y ninguna de las dos se encoge hasta cero. */
.mw-ui .mw-ro .v input, .mw-ui .mw-ro .v select {
    width: 100%; min-width: 0; padding: 4px 7px;
    border: 1px solid var(--hair-strong); border-radius: 7px;
    background: var(--surface); color: var(--ink); font: inherit; font-weight: 600;
}
.mw-ui .mw-ro .v input:focus, .mw-ui .mw-ro .v select:focus {
    outline: none; border-color: var(--navy); box-shadow: 0 0 0 3px var(--navy-050);
}
.mw-ui .mw-ro .v input:disabled { color: var(--muted); background: var(--canvas); }
.mw-ui .mw-ro .v .dos { display: flex; gap: 6px; min-width: 0; }
.mw-ui .mw-ro .v .dos input { flex: 1 1 0; }
.mw-ui .mw-ro .v .dos select { flex: 0 0 auto; width: auto; }
.mw-ui .mw-card.editando { border-color: var(--navy-300); box-shadow: 0 0 0 3px var(--navy-050); }
.mw-ui .mw-control-nota { margin-top: 10px; }

/* --- LA FICHA DEL ORIGEN (etapa 5) ------------------------------------------
   La caja donde el despacho / la recepción / la devolución / el pre-lote dicen
   lo que YA quedó decidido. Va en navy claro y no en blanco a propósito: no es
   una tarjeta más para completar, es contexto — el operario tiene que poder
   saltearla de un vistazo. Ese navy es MARCA, no estado (§1.1 del manual): el
   ámbar y el rojo siguen queriendo decir «falta» y «no se puede», acá y en
   todas las caras. Calcada del prototipo aprobado (`.mw-ficha`, propuesta B).
   ========================================================================== */
.mw-ui .mw-ficha {
    background: var(--navy-050); border: 1px solid #cfdcef;
    border-radius: var(--r-card); padding: 13px 16px 15px;
}
.mw-ui .mw-ficha > h5 {
    margin: 0 0 11px; font-size: 10.5px; font-weight: 700; letter-spacing: .09em;
    text-transform: uppercase; color: var(--navy); display: flex; align-items: center;
    gap: 8px; padding-bottom: 8px; border-bottom: 1px solid #cfdcef; flex-wrap: wrap;
}
.mw-ui .mw-ficha > h5 .material-symbols-outlined { font-size: 16px; }
.mw-ui .mw-ficha > h5 .ver {
    margin-left: auto; font-size: 11px; letter-spacing: 0; text-transform: none;
    color: var(--navy-500); font-weight: 700; background: none; border: 0;
    font-family: inherit; cursor: pointer; padding: 2px 6px; border-radius: 6px;
    transition: background .15s var(--curva);
}
.mw-ui .mw-ficha > h5 .ver:hover, .mw-ui .mw-ficha > h5 .ver:focus-visible { background: #dbe7f8; outline: none; }
/* Dentro de la ficha el dato se lee sobre navy claro: el rótulo baja un punto y
   el valor sube, para que la jerarquía siga siendo la misma que en blanco. */
.mw-ui .mw-ficha .mw-ro .k { color: var(--navy-500); opacity: .9; }
.mw-ui .mw-ficha .mw-ro .v { color: var(--navy-700); }
.mw-ui .mw-ficha .mw-ficha-det { margin-top: 12px; border-top: 1px solid #cfdcef; padding-top: 4px; }
.mw-ui .mw-ficha .mw-tabla th { border-bottom-color: #cfdcef; }
.mw-ui .mw-ficha .mw-tabla td { border-bottom-color: #cfdcef; }
.mw-ui .mw-ficha .mw-tabla tbody tr:hover { background: transparent; }

/* =============================================================================
   6. AVISOS — el cartel del modo y el desvío de la puerta manual
   -----------------------------------------------------------------------------
   `#mov-lock-msg` lo pintan los cuatro cargadores con su propia paleta. Acá se
   le da forma; el color lo sigue eligiendo quien avisa, pero ya sin los cinco
   colores de categoría (ver form-mw-armazon.js: `ponerContexto`).
   ========================================================================== */
.mw-ui .mw-aviso {
    border-radius: 10px; padding: 10px 13px; font-size: 12px; line-height: 1.45;
    border: 1px solid var(--hair); background: var(--canvas); color: var(--muted);
    display: flex; align-items: flex-start; gap: 9px;
}
.mw-ui .mw-aviso .material-symbols-outlined { font-size: 17px; flex: none; margin-top: 1px; }
.mw-ui .mw-aviso b, .mw-ui .mw-aviso strong { color: var(--ink); }
.mw-ui .mw-aviso .cuerpo { min-width: 0; flex: 1; }
.mw-ui .mw-aviso.warn { background: var(--warn-050); border-color: var(--warn-hair); color: var(--warn); }
.mw-ui .mw-aviso.warn b, .mw-ui .mw-aviso.warn strong { color: var(--warn); }
.mw-ui .mw-aviso.ok   { background: var(--ok-050);   border-color: var(--ok-hair);   color: var(--ok); }
.mw-ui .mw-aviso.ok b, .mw-ui .mw-aviso.ok strong { color: var(--ok); }
.mw-ui .mw-aviso.mal  { background: var(--crit-050); border-color: var(--crit-hair); color: var(--crit); }
.mw-ui .mw-aviso.mal b, .mw-ui .mw-aviso.mal strong { color: var(--crit); }
.mw-ui .mw-aviso.nav  { background: var(--navy-050); border-color: #cfdcef; color: var(--navy-700); }
.mw-ui .mw-aviso.nav b, .mw-ui .mw-aviso.nav strong { color: var(--navy); }

/* =============================================================================
   7. BOTONES
   -----------------------------------------------------------------------------
   Uno primario por pantalla. Los cinco botones de registrar pierden sus cinco
   colores (corrección que salió de la ronda, 09/08/2026).
   ========================================================================== */
.mw-ui .mw-btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 7px;
    height: 36px; padding: 0 14px; border-radius: 10px; border: 1px solid transparent;
    font-family: inherit; font-size: .82rem; font-weight: 600; white-space: nowrap;
    cursor: pointer; background: var(--navy); color: #fff;
    transition: background .15s var(--curva), transform .18s var(--curva), box-shadow .18s var(--curva), border-color .15s var(--curva);
}
.mw-ui .mw-btn:hover:not(:disabled)  { background: var(--navy-700); transform: translateY(-2px); box-shadow: 0 6px 16px rgba(0,43,107,.24); }
.mw-ui .mw-btn:active:not(:disabled) { transform: translateY(0); box-shadow: none; }
.mw-ui .mw-btn:focus-visible { outline: 2px solid var(--navy-500); outline-offset: 2px; }
.mw-ui .mw-btn:disabled { opacity: .45; cursor: not-allowed; }
.mw-ui .mw-btn.sec { background: var(--surface); color: var(--ink); border-color: var(--hair-strong); }
.mw-ui .mw-btn.sec:hover:not(:disabled) { background: var(--canvas); border-color: var(--muted); box-shadow: var(--e1); }
.mw-ui .mw-btn.chico { height: 30px; padding: 0 11px; font-size: .76rem; }
/* PELIGRO (14/08/2026). Es el secundario que destruye: el trazo y la palabra en
   rojo sobre blanco, y recién al apuntarlo se llena. NO es `.mw-btn.mal` (§18):
   aquél es el botón que CONFIRMA una anulación, en un diálogo donde la otra
   opción es irse, y por eso es sólido. Éste sólo ABRE el diálogo que va a
   preguntar, así que gritar en reposo lo pondría por encima del primario navy de
   la pantalla donde vive. Lo que tiene que hacer es distinguirse del botón gris
   de al lado, que es lo que faltaba: un ⃠ gris al lado de un 🖨 gris no dice
   cuál de los dos destruye algo. */
.mw-ui .mw-btn.sec.peligro { color: var(--crit); border-color: var(--crit-hair); }
.mw-ui .mw-btn.sec.peligro:hover:not(:disabled) {
    background: var(--crit); color: #fff; border-color: var(--crit); box-shadow: 0 6px 16px rgba(198,40,40,.22);
}
.mw-ui .mw-btn.sec.peligro:focus-visible { outline-color: var(--crit); }
/* PLANO (etapa 3). Para el «Cargar más antiguos» del pie de la planilla: es una
   acción que se aprieta veinte veces seguidas mirando una tabla, y un botón con
   trazo repetido al pie de cada carga pesa más que lo que carga. Se tiñe recién
   al apuntarlo. */
.mw-ui .mw-btn.ln { background: none; border-color: transparent; color: var(--muted); font-weight: 600; }
.mw-ui .mw-btn.ln:hover:not(:disabled), .mw-ui .mw-btn.ln:focus-visible {
    background: var(--navy-050); color: var(--navy); transform: none; box-shadow: none;
}
.mw-ui .mw-btn .material-symbols-outlined { font-size: 17px; }

/* Acción de ícono (quitar una fila, agregar un sub-lote). */
.mw-ui .mw-ico {
    background: none; border: 0; font: inherit; cursor: pointer; padding: 5px;
    border-radius: 8px; color: var(--muted); display: inline-flex; align-items: center; gap: 5px;
    transition: background .15s var(--curva), color .15s var(--curva), transform .15s var(--curva);
}
.mw-ui .mw-ico:hover, .mw-ui .mw-ico:focus-visible { background: var(--navy-050); color: var(--navy); transform: scale(1.18); outline: none; }
.mw-ui .mw-ico:active { transform: scale(.94); }
.mw-ui .mw-ico.del:hover, .mw-ui .mw-ico.del:focus-visible { background: var(--crit-050); color: var(--crit); }
.mw-ui .mw-ico .material-symbols-outlined { font-size: 17px; }

/* =============================================================================
   8. EL PIE — Σ kg, lo que falta y la acción
   -----------------------------------------------------------------------------
   Pegado abajo: en un formulario de cinco pasos la acción no puede depender de
   cuánto scroll quedó. A 390 px las acciones viven SÓLO acá (la barra de arriba
   se queda con la flecha de volver, que también avisa antes de salir).
   ========================================================================== */
.mw-ui .mw-pie {
    background: var(--surface); border: 1px solid var(--hair); border-radius: var(--r-card);
    box-shadow: var(--e2); display: flex; align-items: center; gap: 16px;
    padding: 11px 16px; flex-wrap: wrap; position: sticky; bottom: 0; z-index: 2;
}
.mw-ui .mw-pie .tot .k {
    display: block; font-size: 10px; font-weight: 700; letter-spacing: .09em;
    text-transform: uppercase; color: var(--faint);
}
.mw-ui .mw-pie .tot .v {
    display: block; font-size: 20px; font-weight: 700; letter-spacing: -.02em;
    line-height: 1.15; font-variant-numeric: tabular-nums;
}
.mw-ui .mw-pie .tot .v small { font-size: 11.5px; font-weight: 600; color: var(--muted); }
.mw-ui .mw-pie .sep { width: 1px; align-self: stretch; background: var(--hair); }
.mw-ui .mw-pie .nota { font-size: 11.5px; color: var(--muted); flex: 1; min-width: 140px; line-height: 1.4; }
.mw-ui .mw-pie .nota b.mal  { color: var(--crit); }
.mw-ui .mw-pie .nota b.wrn  { color: var(--warn); }
.mw-ui .mw-pie .nota b.bien { color: var(--ok); }
.mw-ui .mw-pie .der { margin-left: auto; display: flex; gap: 8px; }

/* =============================================================================
   9. TABLAS — la carga múltiple y el resumen
   -----------------------------------------------------------------------------
   `color` y `font-family` van DECLARADOS: sin `<!DOCTYPE>` el navegador entra en
   quirks mode y las tablas no los heredan del padre (trampa ya pagada en el
   prototipo). Y el contenedor scrollea solo: a 390 px la tabla de carga múltiple
   no entra, y hoy ni siquiera tiene dónde correrse.
   ========================================================================== */
.mw-ui .mw-scroll { overflow-x: auto; }
.mw-ui .mw-tabla {
    width: 100%; border-collapse: collapse; font-size: 12.5px;
    color: var(--ink); font-family: inherit;
}
.mw-ui .mw-tabla th {
    font-size: 9.5px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
    color: var(--faint); text-align: left; padding: 8px 10px;
    border-bottom: 2px solid var(--hair-strong); white-space: nowrap;
}
.mw-ui .mw-tabla td { padding: 9px 10px; border-bottom: 1px solid var(--hair); vertical-align: top; }
.mw-ui .mw-tabla tr:last-child td { border-bottom: none; }
.mw-ui .mw-tabla th.n, .mw-ui .mw-tabla td.n { text-align: right; font-variant-numeric: tabular-nums; }
.mw-ui .mw-tabla tbody tr td:first-child { border-left: 3px solid transparent; transition: border-color .15s var(--curva); }
.mw-ui .mw-tabla tbody tr:hover { background: var(--navy-050); }
.mw-ui .mw-tabla tbody tr:hover td:first-child { border-left-color: var(--navy); }

/* =============================================================================
   10. LA CONFIRMACIÓN — el paso 4, no un modal encima
   -----------------------------------------------------------------------------
   `#modal-confirmar-movimiento` conserva su id, su `.hidden` y su `.flex`
   porque form-mw-guardado.js los prende y los apaga tal cual (esta etapa no
   toca una línea de guardado). Lo que cambia es DÓNDE cae: deja de ser un
   overlay `fixed` y pasa a ser el contenido del paso 4. Con eso, el resumen que
   arma el guardado es lo que el operario ve en la pantalla, en su lugar.
   ========================================================================== */
.mw-ui .mw-conf { display: flex; flex-direction: column; gap: 0; }
.mw-ui .mw-conf .cab {
    display: flex; align-items: center; gap: 9px; padding: 11px 16px;
    border: 1px solid var(--hair); border-bottom: 0; border-radius: var(--r-card) var(--r-card) 0 0;
    background: var(--navy-050); color: var(--navy); font-weight: 700; font-size: 12.5px;
}
.mw-ui .mw-conf .cab .material-symbols-outlined { font-size: 18px; }
.mw-ui .mw-conf .cuerpo {
    border: 1px solid var(--hair); border-radius: 0 0 var(--r-card) var(--r-card);
    background: var(--surface); box-shadow: var(--shadow); padding: 14px 16px 16px;
}
.mw-ui .mw-conf .acciones { display: flex; justify-content: flex-end; gap: 8px; margin-top: 14px; }
/* El resumen que escribe el guardado viene con markup de Tailwind adentro: se
   le da el marco, y lo de adentro se deja como está hasta la etapa 5. */
.mw-ui #confirm-modal-content { font-size: 12.5px; line-height: 1.55; }

/* Un aviso de que todavía no hay nada que confirmar. */
.mw-ui .mw-conf-espera {
    border: 1px dashed var(--hair-strong); border-radius: var(--r-card);
    background: var(--surface); padding: 18px 16px; text-align: center;
    color: var(--muted); font-size: 12.5px;
}

/* =============================================================================
   11. LOS MODALES QUE SIGUEN SIENDO MODALES
   -----------------------------------------------------------------------------
   Factura pendiente, chofer rápido, tipo de azúcar e imputación. Los gates
   pasan a ser el paso 0 cuando se toque el guardado (etapa 5); por ahora se
   visten donde están.
   ========================================================================== */
/* EL VELO SE DECLARA DE LAS DOS FORMAS, y no es redundancia: es que tiene dos
   clases de dueño. Los modales del FORMULARIO viven adentro del marcado del
   formulario, así que el scope se lo presta un ancestro y basta el descendiente.
   Los TRES DIÁLOGOS DE ACCIÓN (etapa 5) los arma `initializeStockModals()` una
   sola vez y los cuelga del `<body>`: ahí no hay ningún ancestro del módulo, y
   además el pase lo abre Producción del Día desde SU pantalla. Con sólo el
   descendiente, esos tres perderían el `position:fixed`, el velo, el fondo y el
   centrado — y el defecto es MUDO, porque el elemento existe con todas sus
   clases. Es la misma razón por la que `.mw-ui.mw-menu` va pegado (§15). */
.mw-ui .mw-velo,
.mw-ui.mw-velo {
    position: fixed; inset: 0; background: rgba(10, 25, 60, .45);
    backdrop-filter: blur(2px); z-index: 70;
    display: flex; align-items: center; justify-content: center; padding: 16px;
}
.mw-ui .mw-modal {
    background: var(--surface); border-radius: var(--r-card); box-shadow: var(--e3);
    width: 100%; max-width: 430px; overflow: hidden; display: flex; flex-direction: column;
    max-height: calc(100vh - 32px);
}
.mw-ui .mw-modal > header {
    display: flex; align-items: center; gap: 9px; padding: 13px 16px;
    border-bottom: 1px solid var(--hair);
}
.mw-ui .mw-modal > header h3 {
    margin: 0; font-size: 14px; font-weight: 700; color: var(--ink);
    display: flex; align-items: center; gap: 8px;
}
.mw-ui .mw-modal > header .material-symbols-outlined { color: var(--navy-500); font-size: 19px; }
.mw-ui .mw-modal > header .cerrar { margin-left: auto; }
.mw-ui .mw-modal .cuerpo { padding: 16px; overflow-y: auto; }
.mw-ui .mw-modal .acciones {
    display: flex; justify-content: flex-end; gap: 8px;
    padding: 12px 16px; border-top: 1px solid var(--hair); background: var(--canvas);
}
.mw-ui .mw-modal .acciones.parejo { display: grid; grid-template-columns: 1fr 1fr; }
.mw-ui .mw-modal .acciones.parejo .mw-btn { width: 100%; }

/* =============================================================================
   12. A 390 px
   -----------------------------------------------------------------------------
   La espina se acuesta y pasa a ser una fila que scrollea; el mapa de los cinco
   pasos se sigue viendo entero, que es lo único que no se puede perder.
   ========================================================================== */
@media (max-width: 1100px) {
    .mw-ui .mw-grid, .mw-ui .mw-grid.g5, .mw-ui .mw-grid.g3 { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 760px) {
    .mw-ui .mw-body { padding: 12px 14px 26px; gap: 11px; }
    .mw-ui .mw-b2 { grid-template-columns: 1fr; }

    .mw-ui .mw-spine {
        position: sticky; top: 0; z-index: 3;
        flex-direction: row; gap: 6px; overflow-x: auto; padding: 8px;
        scrollbar-width: thin;
    }
    .mw-ui .mw-step { width: auto; flex: none; border-left: 0; border-bottom: 3px solid transparent; padding: 7px 9px; }
    .mw-ui .mw-step.now { border-bottom-color: var(--navy); }
    /* La bajada no entra acostada: queda el número y el nombre del paso. */
    .mw-ui .mw-step .d { display: none; }

    .mw-ui .mw-grid, .mw-ui .mw-grid.g5, .mw-ui .mw-grid.g3, .mw-ui .mw-grid.g2 { grid-template-columns: 1fr; }
    .mw-ui .mw-grid .sp2 { grid-column: span 1; }

    /* LA FICHA ES LA EXCEPCIÓN, y por una razón concreta: adentro no hay
       controles, hay DATOS. Un `<select>` no entra en 195 px —de ahí la columna
       única de arriba—, pero «TARIFA · $ 9.500» sí. Apilada de a uno, la ficha
       de un despacho son nueve renglones que se comen la primera pantalla
       entera antes de llegar a lo que hay que hacer, que es justo al revés de
       lo que la ficha viene a resolver. En dos columnas son cinco. */
    .mw-ui .mw-ficha .mw-grid, .mw-ui .mw-ficha .mw-grid.g5 { grid-template-columns: 1fr 1fr; }

    /* Las acciones viven sólo en el pie. Y tienen que poder ACHICARSE: el rótulo
       del botón principal lleva el nombre del paso siguiente («Siguiente: Cómo
       viaja»), que con `white-space:nowrap` fija un ancho mínimo de ~200 px por
       botón — dos botones y el documento se va a 545 px con la vista en 390. El
       nombre del paso se corta con puntos suspensivos antes que la pantalla.
       El `min-width:0` va en los DOS: en el botón porque es item de flex, y en
       el rótulo porque adentro del botón es item de flex otra vez. */
    .mw-ui .mw-top .mw-multi { margin-left: 0; }
    .mw-ui .mw-pie { gap: 10px; }
    .mw-ui .mw-pie .sep { display: none; }
    .mw-ui .mw-pie .der { width: 100%; min-width: 0; }
    .mw-ui .mw-pie .der .mw-btn { flex: 1 1 0; min-width: 0; }
    .mw-ui .mw-pie .der .mw-btn .et { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
}

/* =============================================================================
   13. LA PANTALLA — el armazón de la planilla y lo pendiente (ETAPA 2)
   =============================================================================
   Todo lo de acá abajo es de la PANTALLA de Movimientos de Stock, no del
   formulario: docs/RUNBOOK-MOVIMIENTOS-STOCK.md, etapa 2, opción B.

   ES LA CABECERA LITE, la de Facturación y Remitos, y no se discute: sale del
   árbol del §3 del RUNBOOK-NUEVA-IDENTIDAD —pantalla-tabla, una grilla larga
   que se mira 20 minutos seguidos— y además ya estaba elegido (regla 13 del
   RUNBOOK-FORM-MW, y Hernán el 12/08/2026: «me gusta la simpleza y la
   prolijidad que tienen Remitos y Facturas»). La única superficie navy rellena
   de la pantalla es el botón de acción principal, que vive en la barra del
   armazón — acá abajo no hay ninguna (manual §1.2).

   Portado de `facturas-ui.css`, que es la implementación hermana. Cero tokens
   propios: la paleta sale entera de core/tokens.css.
   ========================================================================== */
.mw-ui .mw-shell {
    background: var(--canvas);
    border-radius: var(--r-card);
    overflow: hidden;
    box-shadow: var(--shadow);
    display: flex; flex-direction: column; min-height: 0;
}

/* ── La barra de secciones — subrayado que crece desde el centro ───────────── */
.mw-ui .mw-secnav {
    background: var(--surface);
    border-bottom: 1px solid var(--hair);
    display: flex; gap: 2px; padding: 0 14px; flex-wrap: wrap;
}
.mw-ui .mw-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;
    transition: color .15s var(--curva), background .15s var(--curva);
}
.mw-ui .mw-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. */
.mw-ui .mw-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); transition: transform .18s var(--curva);
}
.mw-ui .mw-secnav button:hover, .mw-ui .mw-secnav button:focus-visible {
    color: var(--navy); background: var(--navy-050); outline: none;
}
.mw-ui .mw-secnav button:hover::after,
.mw-ui .mw-secnav button:focus-visible::after { transform: scaleX(.55); }
.mw-ui .mw-secnav button:hover .material-symbols-outlined { transform: scale(1.18); }
/* La sección activa se marca por `aria-current` Y por `.on`. El atributo es el
   que leen el lector de pantalla y el banco; la clase, la que pinta. Que la
   regla mire a los dos deja que ninguno de los dos se pueda olvidar en silencio. */
.mw-ui .mw-secnav button.on,
.mw-ui .mw-secnav button[aria-current="true"] { color: var(--navy); font-weight: 700; }
.mw-ui .mw-secnav button.on::after,
.mw-ui .mw-secnav button[aria-current="true"]::after { transform: scaleX(1); }
.mw-ui .mw-secnav .tail { margin-left: auto; display: flex; align-items: center; gap: 8px; }

/* ── El contador accionable, en la cola de la barra ────────────────────────── */
/* Vive acá y no en una tarjeta arriba de la grilla: desde la cola se ve al
   entrar, se ve desde las DOS secciones y no se va al hacer scroll. Es ámbar
   porque pide algo — eso SÍ es estado (manual §1.1). */
.mw-ui .mw-alert {
    display: inline-flex; align-items: center; gap: 9px;
    background: var(--warn-050); border: 1px solid var(--warn-hair);
    border-radius: 999px; padding: 5px 12px 5px 10px; margin: 6px 0;
    font-family: inherit; font-size: 11.5px; cursor: pointer; color: var(--warn);
    transition: background .15s var(--curva), transform .15s var(--curva), box-shadow .15s var(--curva);
}
.mw-ui .mw-alert:hover, .mw-ui .mw-alert:focus-visible {
    background: #fdf0d8; transform: translateY(-1px); box-shadow: var(--e1); outline: none;
}
.mw-ui .mw-alert .v {
    font-size: 15px; font-weight: 800; line-height: 1; font-variant-numeric: tabular-nums;
}
.mw-ui .mw-alert .k { font-weight: 700; letter-spacing: .06em; text-transform: uppercase; }
.mw-ui .mw-alert .material-symbols-outlined { font-size: 16px; color: var(--muted); }

/* ── El área de trabajo ───────────────────────────────────────────────────── */
/* Sin padding lateral: la grilla y su barra van de borde a borde y son ELLAS
   las que aplican `--gutter` a su contenido, así que el texto de la tabla
   arranca en la misma columna que el título del módulo. */
.mw-ui .mw-view { padding: 16px 0 22px; background: var(--canvas); flex: 1; min-height: 0; }
/* Lo que no es tarjeta se alinea con el mismo canal. */
.mw-ui .mw-view .mw-ph,
.mw-ui .mw-view .mw-obra,
.mw-ui .mw-view .mw-seg,
.mw-ui .mw-view .mw-nota,
.mw-ui .mw-view .mw-aviso { margin-left: var(--gutter); margin-right: var(--gutter); }

/* Y lo que SÍ es bloque va de borde a borde: pierde el radio y los trazos
   laterales porque ya no tiene a los lados de qué separarse. Es lo que hace que
   el texto de la primera columna de la tabla arranque en la misma columna que
   el título del módulo. (La etapa 2 tenía acá un `padding` provisorio sobre la
   sección entera, porque la grilla todavía era Tailwind y traía su propio
   margen. La etapa 3 se lo llevó junto con la tabla vieja.) */
.mw-ui .mw-view .mw-caja,
.mw-ui .mw-view .mw-bar { border-radius: 0; border-left-width: 0; border-right-width: 0; }

/* ── Encabezado de pantalla ────────────────────────────────────────────────── */
.mw-ui .mw-ph { margin-bottom: 14px; }
.mw-ui .mw-ph h3 { font-size: .95rem; font-weight: 700; color: var(--ink); margin: 0; }
.mw-ui .mw-ph p { font-size: 12px; color: var(--muted); margin: 2px 0 0; max-width: 78ch; }

/* ── El cartel de obra ─────────────────────────────────────────────────────── */
/* Un cartel de obra tiene que decir TRES cosas o no sirve: qué va a haber ahí,
   en qué etapa llega y dónde está escrito eso. Un «Próximamente» solo es una
   pared. En gris y no en ámbar: que una etapa futura no esté hecha no es una
   anomalía del sistema — el ámbar se reserva para lo que le pide algo al que
   está mirando. Calcado de `.cx-obra`. */
.mw-ui .mw-obra {
    margin-top: 13px; padding: 30px 26px;
    background: var(--surface); border-radius: var(--r-card);
    border: 1px dashed var(--hair-strong); box-shadow: var(--e1);
    text-align: center; color: var(--muted);
}
.mw-ui .mw-obra .material-symbols-outlined { font-size: 30px; color: var(--hair-strong); }
.mw-ui .mw-obra h4 { margin: 8px 0 0; font-size: .95rem; font-weight: 700; color: var(--ink); }
/* El párrafo va alineado a la IZQUIERDA aunque el cartel esté centrado: son
   cuatro o cinco renglones y centrados obligan a buscar dónde empieza cada uno.
   Se centra el BLOQUE (margin auto), no el texto. */
.mw-ui .mw-obra p { margin: 8px auto 0; font-size: .78rem; max-width: 58ch; line-height: 1.6; text-align: left; }
.mw-ui .mw-obra p.et {
    margin-top: 14px; font-size: .68rem; font-weight: 700; color: var(--faint);
    text-transform: uppercase; letter-spacing: .07em; text-align: center;
}
.mw-ui .mw-obra .acc { margin-top: 16px; display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; }

/* =============================================================================
   14. EL DESPLEGABLE «REGISTRAR» — las seis operaciones
   -----------------------------------------------------------------------------
   Cuelga del <body> para zafar del `overflow` de la barra del armazón (un
   desplegable adentro de un contenedor con overflow se recorta aunque tenga
   `z-index` — la trampa de las dos bandejas de flete), así que lleva el scope
   `.mw-ui` EN SU PROPIO ELEMENTO y las dos clases van PEGADAS: `.mw-ui.mw-menu`.
   Escrito con espacio no matchearía nada y el menú saldría sin forma, negro
   sobre la pantalla, sin que ninguna aserción sobre el marcado se cayera.

   Y NO TIENE CINCO COLORES. Las operaciones se distinguen por su nombre, su
   glifo y la línea que dice qué hacen — que es el dato que antes no estaba en
   ninguna parte (manual §1.1, y regla 4 del §2 del runbook del módulo).
   ========================================================================== */
.mw-ui.mw-menu {
    position: fixed; top: 0; left: 0; z-index: 90;
    width: min(320px, calc(100vw - 16px));
    background: var(--surface); border: 1px solid var(--hair);
    border-radius: var(--r-card); box-shadow: var(--e3);
    padding: 6px; display: flex; flex-direction: column; gap: 2px;
    max-height: calc(100vh - 24px); overflow-y: auto;
}
/* LOS SEIS RENGLONES SON `.mw-op` (§21) desde la etapa 9. Eran el mismo
   componente que las opciones del diálogo de tipo contable —glifo, nombre y la
   línea que dice qué hace— escrito dos veces, y el §5 de esta hoja pide
   preguntarse si son el mismo componente o sólo el mismo nombre: acá lo son.
   Lo único que queda propio del menú es que ADENTRO DE UN DESPLEGABLE la opción
   no lleva marco: son seis pegadas sobre una superficie flotante, y seis marcos
   apilados dibujan una reja. En un diálogo van sueltas y sí lo llevan. */
.mw-ui.mw-menu .mw-op {
    background: none; border: 0; padding: 9px 11px;
}
.mw-ui.mw-menu .mw-op:hover:not(:disabled), .mw-ui.mw-menu .mw-op:focus-visible:not(:disabled) {
    background: var(--navy-050); border-color: transparent;
}

/* =============================================================================
   15. LA PANTALLA A 390 px
   ========================================================================== */
@media (max-width: 760px) {
    /* La barra de secciones no se acuesta ni scrollea: son DOS y entran. Lo que
       sí se corrige es la cola, que con el contador al lado empuja el renglón:
       pasa abajo y ocupa el ancho. */
    .mw-ui .mw-secnav { padding: 0 10px; }
    .mw-ui .mw-secnav button { padding: 11px 11px 12px; font-size: 12px; }
    .mw-ui .mw-secnav .tail { margin-left: 0; width: 100%; padding-bottom: 6px; }
    .mw-ui .mw-view { padding: 12px 0 18px; }
    .mw-ui .mw-view .mw-ph, .mw-ui .mw-view .mw-obra,
    .mw-ui .mw-view .mw-seg, .mw-ui .mw-view .mw-nota,
    .mw-ui .mw-view .mw-aviso { margin-left: 12px; margin-right: 12px; }
    .mw-ui .mw-obra { padding: 22px 16px; }

    /* LA PLANILLA A 390 px (etapa 3). La tabla NO se reflowea a tarjetas: el
       mobile de este módulo está fuera de alcance a propósito —igual que el de
       Facturación y el del Tarifario— y lo tiene aparte
       (`renderMobileMovimientos`). Lo que se cuida acá es lo otro: que la tabla
       scrollee ADENTRO de su caja en vez de estirar la página, y que la barra y
       el segmento se apilen sin empujar. */
    .mw-ui .mw-bar { padding: 10px 12px; }
    .mw-ui .mw-search { flex: 1 1 100%; }
    /* El segmento no scrollea: se acomoda en dos renglones. Son cuatro pastillas
       cortas y el número de cada una es dato, no adorno — esconder la mitad
       detrás de un scroll lateral sería esconder cuántos anulados hay. */
    .mw-ui .mw-seg { width: 100%; justify-content: flex-start; }
    .mw-ui .mw-caja-h { padding: 10px 12px; }
    .mw-ui table.mw-g th:first-child { padding-left: 12px; }
    /* 9 + los 3 de la franja de estado = los mismos 12 que el resto. */
    .mw-ui table.mw-g td:first-child { padding-left: 9px; }
    .mw-ui table.mw-g th:last-child, .mw-ui table.mw-g td:last-child { padding-right: 12px; }
}

/* =============================================================================
   16. LA PLANILLA — la barra, el segmento, la tarjeta y la grilla (ETAPA 3)
   =============================================================================
   Portado de `facturas-ui.css`, que es la implementación hermana de la cabecera
   lite. Cero tokens propios y cero valores nuevos.

   LO QUE NO NACE ACÁ, Y ES LA MITAD DEL TRABAJO. La planilla no estrena una
   pastilla, ni un botón, ni un botón de ícono, ni un aviso: `.mw-chip`,
   `.mw-btn`, `.mw-ico`, `.mw-aviso`, `.mw-scroll` y `.mw-vacio` ya existían para
   el formulario y son los mismos. Un módulo que se repinta pantalla por pantalla
   termina con dos vocabularios para lo mismo si cada etapa se inventa el suyo, y
   entonces la hoja deja de poder leerse entera. Lo único que este bloque agrega
   son las piezas que el formulario no tenía porque no tiene tabla larga.

   Y UNA QUE PARECE REPETIDA Y NO LO ES: `.mw-sent` —el ING/SAL de la fila— NO es
   el `.mw-dir` del formulario. Son la misma idea a otra escala: `.mw-dir` es una
   pastilla navy que se ve UNA vez por pantalla, arriba de todo, y dice de qué
   lado entró uno al formulario. Cincuenta pastillas navy apiladas en una columna
   serían la superficie más fuerte de una pantalla que se mira 20 minutos
   (manual §1.2). En la fila el sentido es un glifo apagado con su palabra al
   lado: categoría, no estado, y sin color (regla 3 del §2 del runbook).
   ========================================================================== */

/* ── La barra de trabajo: el buscador y su ÁMBITO DECLARADO ────────────────── */
/* EL BUSCADOR ES DOS BUSCADORES y esto es lo que lo dice. Mientras se tipea
   filtra los que están cargados; con Enter —o con el botón— sale a buscar el
   histórico completo con otra consulta. La única pista de que eran dos cosas era
   un `title` escondido en un botón de lupa. Ahora el ámbito es una pastilla que
   está siempre a la vista y cambia cuando cambia. */
.mw-ui .mw-bar {
    background: var(--surface); border: 1px solid var(--hair);
    border-radius: 10px; box-shadow: var(--shadow);
    padding: 10px var(--gutter); margin-bottom: 12px;
    display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
}
.mw-ui .mw-search { position: relative; flex: 1 1 260px; min-width: 200px; }
.mw-ui .mw-search > .material-symbols-outlined {
    position: absolute; left: 11px; top: 50%; transform: translateY(-50%);
    color: var(--faint); font-size: 19px; pointer-events: none;
}
/* El control es el `.form-input` del módulo, no uno nuevo: lo único propio del
   buscador es dejarle lugar a la lupa. */
.mw-ui .mw-search .form-input { padding-left: 36px; }

/* ── El segmento de cuatro: Todos · Ingresos · Egresos · Anulados ──────────── */
/* Son CUATRO y no seis: «sin factura» y «sin tarifa firme» no son filtros de
   esta lista —son otra consulta y otras columnas— y viven en la sección
   Pendientes (opción B, 12/08/2026). Activo por TRAZO, nunca por relleno navy. */
.mw-ui .mw-seg {
    display: inline-flex; background: var(--surface);
    border: 1px solid var(--hair-strong); border-radius: 9px;
    padding: 3px; gap: 2px; margin-bottom: 14px; flex-wrap: wrap;
}
.mw-ui .mw-seg button {
    background: none; border: 0; font: inherit; font-size: 12.4px; font-weight: 600;
    color: var(--muted); padding: 7px 15px; border-radius: 6px; cursor: pointer;
    display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
    transition: color .15s var(--curva), background .15s var(--curva), box-shadow .15s var(--curva);
}
.mw-ui .mw-seg button .material-symbols-outlined { font-size: 17px; }
.mw-ui .mw-seg button:hover, .mw-ui .mw-seg button:focus-visible {
    color: var(--navy); background: var(--navy-050); outline: none;
}
.mw-ui .mw-seg button.on {
    color: var(--navy); font-weight: 700; background: var(--navy-050);
    box-shadow: inset 0 -2.5px 0 var(--navy);
}
.mw-ui .mw-seg .n { font-size: 11px; font-weight: 700; color: var(--faint); font-variant-numeric: tabular-nums; }
.mw-ui .mw-seg button.on .n { color: var(--navy-500); }

/* ── La tarjeta de la planilla ─────────────────────────────────────────────── */
/* Se llama `.mw-caja` y no `.mw-card` porque `.mw-card` ya es la tarjeta del
   FORMULARIO —otra estructura, con su `> h5`— y once archivos de JS la usan. Dos
   componentes distintos con el mismo nombre en la misma hoja es una mina: el día
   que alguien toque uno, el otro cambia sin que nadie lo mire. */
.mw-ui .mw-caja {
    background: var(--surface); border: 1px solid var(--hair);
    border-radius: var(--r-card); box-shadow: var(--shadow);
    overflow: hidden; margin-bottom: 14px;
}
.mw-ui .mw-caja-h {
    background: #fafbfc; border-bottom: 1px solid var(--hair);
    padding: 10px var(--gutter); display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
}
.mw-ui .mw-caja-h h4 {
    font-size: .68rem; text-transform: uppercase; letter-spacing: .11em;
    font-weight: 700; color: var(--muted); margin: 0;
}
.mw-ui .mw-caja-h .r { margin-left: auto; display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.mw-ui .mw-caja-f {
    padding: 10px var(--gutter); text-align: center;
    border-top: 1px solid var(--hair); background: #fafbfc;
}

/* ── La grilla ─────────────────────────────────────────────────────────────── */
.mw-ui table.mw-g { width: 100%; border-collapse: collapse; font-size: 12.8px; }
/* Encabezado BLANCO con regla de 2px, nunca una franja navy: es lo que más cansa
   cuando la tabla se mira 20 minutos seguidos (manual §1.2). */
.mw-ui table.mw-g th,
/* Y LA CABECERA DEL ESQUELETO, que es la misma cabecera. `gsZonaCargando()` arma
   su propia `<table>` SIN clase —el helper es de `core/` y no puede conocer el
   vocabulario de once módulos—, así que sus `<th>` heredaban lo que hubiera:
   centrados, negros y más grandes que los de verdad. Un esqueleto que no se
   parece a lo que viene es medio esqueleto — la cabecera SALTABA al llegar los
   datos, que es exactamente lo que un esqueleto existe para evitar. */
.mw-ui .mw-caja table:not(.mw-g) th {
    background: var(--surface); color: var(--muted);
    font-size: .6rem; text-transform: uppercase; letter-spacing: .09em; font-weight: 700;
    text-align: left; padding: 9px 12px;
    border-bottom: 2px solid var(--ink); white-space: nowrap;
}
/* NINGÚN valor se parte al medio: un «FC A» arriba y su número abajo no se leen
   como un dato, se leen como dos. Los únicos que envuelven son los nombres
   —propietario y destino—, que son texto de largo variable y llevan `.wrap`. */
.mw-ui table.mw-g td {
    padding: 9px 12px; border-bottom: 1px solid var(--hair);
    color: var(--ink); vertical-align: middle; white-space: nowrap;
}
.mw-ui table.mw-g td.wrap, .mw-ui table.mw-g th.wrap { white-space: normal; min-width: 170px; }
.mw-ui table.mw-g tbody tr { transition: background .13s var(--curva); }
.mw-ui table.mw-g tbody tr:hover { background: var(--navy-050); }
.mw-ui table.mw-g .n { text-align: right; font-variant-numeric: tabular-nums; }
.mw-ui table.mw-g .c { text-align: center; }
.mw-ui table.mw-g .mono {
    font-family: 'Consolas', 'SF Mono', 'Roboto Mono', monospace;
    font-weight: 700; font-variant-numeric: tabular-nums;
}
.mw-ui table.mw-g td.vacia { padding: 34px 16px; text-align: center; color: var(--faint); font-style: italic; white-space: normal; }
.mw-ui table.mw-g .acc { display: flex; justify-content: center; align-items: center; gap: 2px; }

/* FRANJA DE ESTADO a la izquierda de la fila. Es lo que reemplaza al fondo
   amarillo entero y a las pastillas de color: el ojo encuentra lo que pide
   acción sin leer la fila, y la fila sigue siendo legible. Los 3 px de la franja
   + 19 de relleno suman `--gutter`, así el ID queda a plomo con el título. */
.mw-ui table.mw-g td:first-child { border-left: 3px solid transparent; padding-left: calc(var(--gutter) - 3px); }
.mw-ui table.mw-g th:first-child { padding-left: var(--gutter); }
.mw-ui table.mw-g th:last-child,
.mw-ui table.mw-g td:last-child { padding-right: var(--gutter); }
.mw-ui table.mw-g tr.st-ok  td:first-child { border-left-color: var(--ok-hair); }
.mw-ui table.mw-g tr.st-wrn td:first-child { border-left-color: var(--warn); }
.mw-ui table.mw-g tr.st-neg td:first-child { border-left-color: var(--crit); }
/* El anulado es el único que además se apaga entero: no es que le falte un dato,
   es que ya no cuenta para nada. */
.mw-ui table.mw-g tr.st-neg { background: rgba(198,40,40,.035); color: var(--faint); }
.mw-ui table.mw-g tr.st-neg td { color: var(--faint); }

/* ── El sentido del movimiento y las marcas en línea ───────────────────────── */
.mw-ui .mw-sent {
    display: inline-flex; align-items: center; gap: 6px;
    font-size: 11px; font-weight: 700; letter-spacing: .08em;
    text-transform: uppercase; color: var(--muted); white-space: nowrap;
}
.mw-ui .mw-sent .material-symbols-outlined { font-size: 16px; color: var(--faint); }

/* Marca de estado en línea: ícono + texto, sin pastilla. Va donde el estado es
   el DATO de la celda (la columna Referencia) y no una etiqueta que se le cuelga
   al costado. */
.mw-ui .mw-mark { font-size: 11.5px; font-weight: 600; display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }
.mw-ui .mw-mark .material-symbols-outlined { font-size: 16px; }
.mw-ui .mw-mark.ok  { color: var(--ok); }
.mw-ui .mw-mark.wrn { color: var(--warn); }
.mw-ui .mw-mark.neg { color: var(--crit); }
.mw-ui .mw-mark.mut { color: var(--faint); }

.mw-ui .dim { color: var(--faint); }
.mw-ui .mw-nota { font-size: 11px; color: var(--faint); line-height: 1.55; max-width: 78ch; }
.mw-ui .mw-nota b { color: var(--muted); }

/* =============================================================================
   17. LA MESA DE PENDIENTES — las dos listas y su antigüedad (ETAPA 4)
   =============================================================================
   ESTE BLOQUE ES CORTO A PROPÓSITO, y ésa es la noticia. La sección Pendientes
   son DOS tarjetas con DOS tablas, y las dos son la `.mw-caja` y la `table.mw-g`
   que la etapa 3 dejó puestas para la planilla: mismo encabezado blanco con su
   regla de 2 px, misma franja de estado a la izquierda, mismo relleno, mismo
   `--gutter`. La acción de fila es el `.mw-btn.sec.chico` de siempre, la
   antigüedad es una `.mw-mark`, los conteos de la cabecera son `.mw-chip`, y el
   aviso de arriba es el `.mw-aviso.mal` del formulario.

   Es la prueba de que el vocabulario alcanzaba: una pantalla entera que no
   estrena ni una pastilla. Si esta sección hubiera necesitado su propia tabla,
   su propia tarjeta y su propio badge, la etapa 3 habría dejado un vocabulario
   que servía para una sola pantalla — y la hoja habría terminado con dos formas
   de dibujar lo mismo, que es lo que esta migración vino a sacar.

   LO ÚNICO QUE HAY ACÁ es la separación entre las piezas apiladas (que la
   planilla no necesitaba porque es UN bloque) y el ancho de la columna de la
   acción, que sí es propio: en la planilla las acciones son siete íconos de
   30 px y acá es UN botón con su rótulo escrito, que no se puede partir en dos
   renglones sin que la fila crezca al doble.
   ========================================================================== */

/* Las tres piezas apiladas de la sección. El aviso de riesgo va PRIMERO y sólo
   aparece cuando hay tarifas provisorias: no es decoración de la pantalla, es la
   consecuencia —bloquea la emisión de Líquidos Productos— y sin pendientes de
   ésos no hay nada que avisar. */
.mw-ui #mw-pend-riesgo:empty { display: none; }
.mw-ui #mw-pend-riesgo { margin-bottom: 14px; }

/* LA COLUMNA DE LA ACCIÓN. No hace falta pedirle `nowrap`: `.mw-g td` ya lo
   trae, y una regla que repite lo que ya está puesto es una que el día que
   alguien cambie la de arriba va a quedar mintiendo. Lo único propio es la
   EXCEPCIÓN: cuando el rol no puede vincular no hay botón sino una razón
   escrita, y ésa sí tiene que envolver — es texto, no una acción. */
.mw-ui table.mw-g td.acc-1 .sin {
    font-size: 11px; color: var(--faint); font-style: italic;
    white-space: normal; display: inline-block; max-width: 22ch; line-height: 1.35;
}

/* El pie de la tarjeta cuando lleva una nota y no un botón. `.mw-caja-f` viene
   centrado porque en la planilla contiene «Cargar más antiguos»; acá contiene un
   párrafo, y un párrafo centrado obliga a buscar dónde empieza cada renglón. */
.mw-ui .mw-caja-f.texto { text-align: left; }

/* =============================================================================
   18. LOS TRES DIÁLOGOS DE ACCIÓN — pase, cesión y anulación (ETAPA 5)
   =============================================================================
   Tres modales que hasta hoy se anunciaban con TRES COLORES DE CABECERA —azul
   el pase, púrpura la cesión, rojo la anulación—, que es color = categoría: la
   regla §1.1 del manual, y la misma corrección que este módulo ya se hizo dos
   veces (los cinco botones de registrar y el modo del formulario, que se decía
   con cinco colores y hoy se dice con palabras). La cabecera de los tres es
   ahora la del sistema: ícono navy, título, y el color reservado para el estado.

   Y NO ESTRENA CASI NADA. `.mw-velo`, `.mw-modal`, `.mw-ficha`, `.mw-ro`,
   `.mw-grid`, `.mw-card`, `.mw-tabla`, `.mw-chip`, `.mw-aviso`, `.mw-btn` y
   `.mw-ico` son los del formulario, y el modal de «Cargar tarifa firme» de la
   etapa 4 ya había probado que el conjunto alcanza para un diálogo entero. Lo
   de acá abajo son las cuatro cosas que un diálogo de 620 px con una tabla
   adentro necesita y una ficha de siete datos no.
   ========================================================================== */

/* EL `<form>` QUE ENVUELVE TIENE QUE REPARTIR EL ALTO. `.mw-modal` es una
   columna flex con `max-height`, y hasta acá sus hijos eran `header`, `.cuerpo`
   y `.acciones` directos. El pase y la cesión meten un `<form>` en el medio
   —para que el `required` y el submit nativo sigan andando— y un `<div>` común
   no reparte nada: la `.cuerpo` crece con su contenido, el `<form>` desborda y
   **el pie se sale del diálogo**, con «Cancelar» y «Siguiente» cortados abajo.

   Van las tres cosas juntas, y ninguna sobra: el `<form>` es la columna, la
   `.cuerpo` es la única que crece Y ESCROLLEA, y el `min-height: 0` es lo que
   permite que se encoja — un ítem flex no baja de su contenido sin eso, y el
   resultado es que scrollea la página en vez del cuerpo (la trampa del §4 del
   runbook de identidad, con otra cara). Lo agarró la FOTO, no una aserción; la
   aserción se escribió después, a propósito. */
.mw-ui .mw-modal > form {
    display: flex; flex-direction: column; min-height: 0; overflow: hidden;
}
.mw-ui .mw-modal .cuerpo { flex: 1 1 auto; min-height: 0; }
.mw-ui .mw-modal > form > .acciones { flex: none; }

/* EL ANCHO. `.mw-modal` mide 430 px, que es lo que necesita una pregunta con su
   ficha. El pase tiene ocho campos y una TABLA de lotes con cinco columnas: a
   430 px la columna de los kg queda en 60 y el código de lote se parte en dos
   renglones. Son dos escalones declarados y no un ancho por diálogo, porque tres
   anchos distintos es lo mismo que tres colores distintos. */
.mw-ui .mw-modal.ancho { max-width: 680px; }

/* El paso, en la cabecera. El pase y la cesión tienen DOS —llenar y confirmar— y
   hasta hoy la única pista de en cuál estabas era que el contenido cambiaba
   entero. Va en la cabecera, chico y apagado: es una posición, no un título. */
.mw-ui .mw-modal > header .paso {
    font-size: 10px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
    color: var(--faint); white-space: nowrap;
}
.mw-ui .mw-modal > header .paso + .cerrar { margin-left: 9px; }

/* La acción que vuelve, a la izquierda del pie. `.acciones` alinea a la derecha
   —es lo correcto cuando son «cancelar» y «hacer»—, y «Volver» no es ninguna de
   las dos: es la dirección contraria, y va del lado del que se vuelve. */
.mw-ui .mw-modal .acciones .izq { margin-right: auto; }

/* LA TABLA ADENTRO DE UN DIÁLOGO. `.mw-tabla` nació para el resumen de carga
   múltiple, que es de sólo lectura; acá cada fila tiene un `<input>` de kg y un
   botón de quitar, y con el relleno de 9 px la fila mide 56. Se ajusta acá y no
   tocando `.mw-tabla`, que la usan seis pantallas. */
.mw-ui .mw-modal .mw-tabla td { padding: 6px 8px; vertical-align: middle; }
.mw-ui .mw-modal .mw-tabla th { padding: 7px 8px; }

/* Y LA TABLA DE LOTES RECORTA DE VERDAD: `table-layout: fixed`. Sin eso el
   `width` de un `<th>` es una PISTA y nada más — la celda del lote crece con su
   contenido, le come el ancho a la de al lado y la pastilla de «qué queda» sale
   cortada por el borde de la tarjeta, con el diálogo pidiendo scroll horizontal.
   Es la trampa que el §4 del runbook de identidad ya tenía anotada al revés
   («una tabla sin table-layout no recorta nunca, así que la aserción que mide
   desborde da verde para siempre»). Con los anchos declarados, lo único que
   cede es el detalle del lote, que para eso lleva puntos suspensivos. */
.mw-ui .mw-modal #pase-lote-section .mw-tabla { table-layout: fixed; }
.mw-ui .mw-modal #pase-lote-section .mw-tabla th:nth-child(2) { width: 92px; }
.mw-ui .mw-modal #pase-lote-section .mw-tabla th:nth-child(3) { width: 116px; }
.mw-ui .mw-modal #pase-lote-section .mw-tabla th:nth-child(4) { width: 152px; }
.mw-ui .mw-modal #pase-lote-section .mw-tabla th:nth-child(5) { width: 38px; }
/* El código del lote también se corta antes que la columna: un código raro y
   largo no puede empujar la fila a dos renglones. */
.mw-ui .mw-modal .mw-lote-btn > span:first-child { overflow: hidden; }
.mw-ui .mw-modal .mw-lote-btn b { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mw-ui .mw-modal .mw-tabla .form-input { height: 32px; font-size: 12px; }
.mw-ui .mw-modal .mw-tabla tbody tr:hover { background: transparent; }
.mw-ui .mw-modal .mw-tabla tbody tr:hover td:first-child { border-left-color: transparent; }
/* El renglón de abajo del código: proveedor, remito y fecha de entrada. Es lo
   que distingue dos lotes del mismo artículo cuando el código no alcanza — y va
   en UN renglón con puntos suspensivos, no envuelto: envuelto parte el remito y
   la fecha por la mitad («2026-07-» / «14») y cada fila mide distinto, con lo
   cual dos lotes seguidos dejan de poder compararse de un vistazo. */
.mw-ui .mw-lote-det {
    display: block; font-size: 10.5px; color: var(--faint); line-height: 1.35;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Un lote sin elegir es un renglón que pide algo, no un dato vacío. */
.mw-ui .mw-lote-btn {
    width: 100%; text-align: left; background: var(--surface);
    border: 1px solid var(--hair-strong); border-radius: 9px; padding: 5px 9px;
    font: inherit; font-size: 12px; color: var(--ink); cursor: pointer;
    display: flex; align-items: center; gap: 7px;
    transition: border-color .15s var(--curva), background .15s var(--curva);
}
.mw-ui .mw-lote-btn:hover, .mw-ui .mw-lote-btn:focus-visible { border-color: var(--navy-300); outline: none; }
.mw-ui .mw-lote-btn .material-symbols-outlined { font-size: 16px; color: var(--faint); margin-left: auto; }

/* EL TOTAL DEL PASE. Es el `.mw-pie` del formulario sin el `sticky` y sin el
   marco: adentro de un diálogo el pie ya existe (`.acciones`), y dos pies
   apilados se leen como dos formularios. */
.mw-ui .mw-tot {
    display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
    padding: 9px 2px 0; border-top: 1px solid var(--hair); margin-top: 9px;
}
.mw-ui .mw-tot .k {
    display: block; font-size: 10px; font-weight: 700; letter-spacing: .09em;
    text-transform: uppercase; color: var(--faint);
}
.mw-ui .mw-tot .v {
    display: block; font-size: 19px; font-weight: 700; letter-spacing: -.02em;
    line-height: 1.15; font-variant-numeric: tabular-nums;
}
.mw-ui .mw-tot .v small { font-size: 11.5px; font-weight: 600; color: var(--muted); }
.mw-ui .mw-tot .der { margin-left: auto; }

/* LA PALABRA QUE HAY QUE ESCRIBIR PARA ANULAR. El botón se apagaba y se prendía
   con `bg-gray-400` ↔ `bg-red-600` escritos desde el JavaScript — la trampa de
   `auth.js`, que deja la pantalla hablando dos idiomas al primer estado. Hoy el
   JS pone y saca `disabled`, que es lo que el botón YA SABE decir (`.mw-btn:
   disabled` existe desde la etapa 2), y el campo se tiñe solo cuando la palabra
   está completa. Nadie escribe una clase de color en ningún lado. */
.mw-ui .mw-palabra {
    text-align: center; font-weight: 700; letter-spacing: .18em; text-transform: lowercase;
}
.mw-ui .mw-palabra.listo { border-color: var(--crit); color: var(--crit); background: var(--crit-050); }

/* El botón que CONFIRMA una anulación. Es el único SÓLIDO de la hoja que no es
   navy, y se justifica escrito: no es «el botón importante de la pantalla» —para
   eso está el primario navy— sino la acción que borra stock, en un diálogo donde
   la otra opción es irse. El manual §1.1 reserva el rojo para el estado, y acá el
   estado es lo que va a quedar el movimiento.
   *(El otro rojo de la hoja es `.mw-btn.sec.peligro` en §7, que sólo ABRE un
   diálogo así y por eso va de trazo y no lleno.)* */
.mw-ui .mw-btn.mal { background: var(--crit); }
.mw-ui .mw-btn.mal:hover:not(:disabled) { background: #a51f1f; box-shadow: 0 6px 16px rgba(198,40,40,.26); }

/* A 390 px. El diálogo ancho deja de serlo, la tabla de lotes scrollea adentro
   de la caja y las acciones del pie se reparten el ancho. */
@media (max-width: 760px) {
    .mw-ui .mw-modal.ancho { max-width: 100%; }
    .mw-ui .mw-modal .acciones { flex-wrap: wrap; }
    .mw-ui .mw-modal .acciones .mw-btn { flex: 1 1 auto; }
    .mw-ui .mw-modal .acciones .izq { margin-right: 0; flex-basis: 100%; }
}

/* =============================================================================
   19. LOS DOS PANELES — la ficha, el pase a Polvos y el protocolo (ETAPA 6)
   =============================================================================
   Ronda 3 de mockups (docs/movimientos/03-ronda3-etapa6.html): ganó la OPCIÓN B,
   «dos paneles, y la acción al lado del dato». Las tres superficies de la etapa
   son diálogos que hablan de UNA cosa y que mezclaban lo que hay que leer con lo
   que se puede hacer: la ficha de un movimiento tenía diez bloques de datos con
   cuatro botones de colores metidos entre medio, cada uno adentro de la caja del
   dato que le toca y ninguno donde uno los busca.

   La B parte el diálogo en dos: a la izquierda lo que la cosa ES, a la derecha
   lo que le PASÓ — y cada acción queda pegada al dato sobre el que actúa. Eso no
   es una preferencia de forma: el tacho de «anular» adentro de la fila del
   remito dice que anula el REMITO, y el mismo botón en un pie junto a «Imprimir
   COA» necesita que el rótulo lo aclare o alguien anula el movimiento.

   Y sigue sin estrenar casi nada: `.mw-card`, `.mw-ficha`, `.mw-ro`, `.mw-grid`,
   `.mw-tabla`, `.mw-chip`, `.mw-aviso`, `.mw-btn`, `.mw-ico` y `.mw-tot` son los
   de siempre. Lo propio son cinco cosas que UN DIÁLOGO DE DOS PANELES necesita.
   ========================================================================== */

/* 1 · EL TERCER ESCALÓN DE ANCHO, y no contradice lo que dice §18. Ahí el
   argumento es que no puede haber «un ancho por diálogo», y no lo hay: `.doble`
   no es más ancho porque su contenido sea más largo, es más ancho porque tiene
   DOS COLUMNAS. Es de la estructura, y por eso sólo lo puede usar un modal que
   lleve `.mw-dosp` adentro — un `.doble` con una sola columna son 880 px de
   renglones de 13 px, que es exactamente lo que el manual §1.2 no quiere. */
.mw-ui .mw-modal.doble { max-width: 880px; }

/* 2 · LOS DOS PANELES. LO QUE SOSTIENE ESTO ES EL `overflow-y: auto` DE CADA
   COLUMNA, y hay que decirlo porque es lo único que no se ve: sin él el diálogo
   queda idéntico —mide lo mismo, el pie en su lugar, los dos paneles enteros en
   el DOM— y la mitad de abajo de cada uno deja de poder alcanzarse. No hay barra
   y no hay rueda. Es la mitad de lo que la opción B vino a comprar: que la
   auditoría y las vinculaciones dejen de empujar los datos hacia abajo.

   El `min-height: 0` de la grilla es cinturón y tiradores, y también conviene
   decirlo: como la grilla lleva `overflow: hidden` ya es un contenedor de
   scroll, su mínimo automático vale cero y se encogería igual. Se descubrió
   rompiéndolo a propósito en el banco y viendo que no pasaba nada. */
.mw-ui .mw-modal .mw-dosp {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    flex: 1 1 auto; min-height: 0; overflow: hidden;
}
.mw-ui .mw-modal .mw-dosp > .col {
    min-width: 0; min-height: 0; overflow-y: auto;
    padding: 16px; display: flex; flex-direction: column; gap: 13px;
}
/* El segundo panel se distingue por la SUPERFICIE, no por un color propio: papel
   blanco lo que el movimiento es, lienzo lo que le pasó. Es la elevación del
   manual §1.3 puesta de costado. */
.mw-ui .mw-modal .mw-dosp > .col + .col {
    border-left: 1px solid var(--hair); background: var(--canvas);
}
/* El rótulo del panel. Es una posición, no un título: mismo tamaño y mismo peso
   que el `.paso` de la cabecera (§18), por lo mismo. */
.mw-ui .mw-modal .mw-dosp .pan-t {
    margin: 0; font-size: 10px; font-weight: 700; letter-spacing: .11em;
    text-transform: uppercase; color: var(--faint);
}
/* Lo que queda pegado abajo del panel (el id del documento). */
.mw-ui .mw-modal .mw-dosp .al-pie { margin-top: auto; }

/* 3 · LA CINTA DE IDENTIDAD DE LA FICHA. Y NO es `.mw-cinta`, que ya existe y es
   otra cosa: la del formulario es una barra horizontal con la pastilla de
   dirección y los gates (§3). Ésta son los kg en grande con el artículo debajo y
   el número a la derecha. Misma idea, otra estructura → nombre propio, que es el
   criterio del §5 del runbook del módulo (`.mw-card` vs `.mw-caja`).

   Los kg van en 30 px y el sentido va con GLIFO Y PALABRA, apagado, sin verde
   contra rojo: es una categoría (regla 3 del §2 del runbook), y es la misma
   `.mw-sent` de la fila de la planilla (§16) a otra escala. */
.mw-ui .mw-ident {
    display: flex; align-items: flex-end; gap: 18px; flex-wrap: wrap;
    padding-bottom: 12px; border-bottom: 1px solid var(--hair);
}
.mw-ui .mw-ident .kg {
    display: block; font-size: 30px; font-weight: 700; letter-spacing: -.03em;
    line-height: 1; font-variant-numeric: tabular-nums;
}
.mw-ui .mw-ident .kg small { font-size: 14px; font-weight: 600; color: var(--muted); letter-spacing: 0; }
.mw-ui .mw-ident .art { display: block; font-size: 12.5px; font-weight: 600; color: var(--muted); margin-top: 4px; }
.mw-ui .mw-ident .der { margin-left: auto; text-align: right; min-width: 0; }
.mw-ui .mw-ident .der .num {
    display: block; font-size: 14px; font-weight: 700; color: var(--navy);
    letter-spacing: -.01em; font-variant-numeric: tabular-nums;
}
.mw-ui .mw-ident .der .f { display: block; font-size: 11.5px; color: var(--muted); }

/* 4 · EL PIE DE UNA CAJA. Es donde vive la acción que actúa sobre lo que la caja
   muestra —«Imprimir COA» abajo de los lotes, «Generar carga F3000» abajo de los
   documentos—, con su aclaración al lado. Sin él, la única forma de poner una
   acción adentro de una caja es meterla en el encabezado, y ahí compite con el
   título. Que el texto NO vaya centrado es la misma corrección de §17. */
.mw-ui .mw-card .card-f {
    margin-top: 10px; padding-top: 9px; border-top: 1px solid var(--hair);
    display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
}
.mw-ui .mw-card .card-f .nota { font-size: 11px; color: var(--muted); line-height: 1.35; min-width: 0; }
/* La acción que va en el ENCABEZADO de la caja es la que actúa sobre la caja
   entera (el historial de auditoría), y se empuja al borde como el conteo. */
.mw-ui .mw-card > h5 > .mw-btn { margin-left: auto; }

/* 5 · EL PUENTE entre las dos puntas del pase. Una operación intersectorial son
   dos mitades que hay que comparar antes de firmar, y hasta hoy se decían con
   una tarjeta ROJA («sale») y una VERDE («entra»): color = categoría por quinta
   vez en este módulo, y encima con la semántica cambiada —el rojo era «sale»,
   no «mal»—. Lo que dice la dirección es una flecha. */
.mw-ui .mw-puente {
    display: flex; align-items: center; justify-content: center; color: var(--faint);
}
.mw-ui .mw-puente .material-symbols-outlined { font-size: 22px; }
.mw-ui .mw-dos-puntas {
    display: grid; grid-template-columns: minmax(0, 1fr) 40px minmax(0, 1fr);
    align-items: stretch;
}

/* 6 · LOS HITOS — el historial de auditoría y las vinculaciones de Flexxus.
   El de auditoría lo dibujaba `services/auditlog-service.js`: un SERVICIO
   decidiendo cómo se ve un pedazo de esta pantalla, con seis colores para siete
   tipos de acción —color = categoría, manual §1.1— y `renderAuditLogHTML()` sin
   otro llamador que este archivo. Es exactamente lo que la etapa 3 le encontró a
   `actualizarBannerPeriodo()`, y se arregla igual: el servicio contesta el dato,
   el módulo lo dibuja. El tipo de hito se dice con el GLIFO y con la palabra. */
.mw-ui .mw-hitos { display: flex; flex-direction: column; gap: 9px; }
.mw-ui .mw-hito {
    display: flex; align-items: flex-start; gap: 9px; font-size: 12px; color: var(--muted);
}
.mw-ui .mw-hito > .material-symbols-outlined { font-size: 17px; color: var(--faint); flex: none; margin-top: 1px; }
.mw-ui .mw-hito > div { min-width: 0; flex: 1; }
.mw-ui .mw-hito .t { display: block; font-size: 11.5px; font-weight: 700; color: var(--ink); }
.mw-ui .mw-hito .q { display: block; font-size: 11.5px; }
.mw-ui .mw-hito .d {
    display: block; font-size: 10.5px; color: var(--faint);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mw-ui .mw-hito .c { font-size: 10.5px; color: var(--faint); white-space: nowrap; flex: none; }

/* 7 · LAS TABLAS DE LOS PANELES RECORTAN DE VERDAD. Es la misma trampa que §18
   resolvió para la tabla de lotes del pase, y acá muerde en dos: el número de un
   remito y el código de un lote son cadenas largas que, sin `fixed`, le comen la
   columna a la de al lado y empujan los dos íconos de acción fuera del panel —
   que a 440 px de ancho no tiene de dónde sacar. La columna de acciones mide lo
   que miden dos `.mw-ico`, y lo que cede es el texto, que para eso lleva
   `.trunc`. */
.mw-ui .mw-dosp .mw-tabla { table-layout: fixed; }
.mw-ui .mw-dosp .mw-tabla th.acc, .mw-ui .mw-dosp .mw-tabla td.acc { width: 66px; text-align: right; white-space: nowrap; }
.mw-ui .mw-dosp .mw-tabla th.n, .mw-ui .mw-dosp .mw-tabla td.n { width: 84px; }
.mw-ui .mw-dosp .mw-tabla td.trunc { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mw-ui .mw-dosp .mw-tabla td .mw-chip { margin-left: 5px; }

/* 8 · EL RENGLÓN DE ACCIONES DE UNA FILA (14/08/2026). Es la salida a lo que la
   primera pasada en vivo dejó abierto: las dos acciones del remito vivían en la
   celda `.acc` —66 px, lo que miden dos íconos— y ahí un rótulo no entra, así que
   el ⃠ que anula el remito se veía igual que el 🖨 que lo imprime.

   No es un pie de caja (`.card-f`): el pie es de la CAJA entera —«Imprimir COA»
   abajo de los lotes— y estas dos actúan sobre UNA fila. Por eso cuelga de la
   fila, sin regla arriba, con la sangría que lo pega al renglón de al lado. La
   celda de la fila de arriba queda vacía a propósito: repetir los íconos sería
   dos puertas a lo mismo, una con nombre y otra sin.

   TRES COSAS QUE `.mw-tabla` OBLIGA A DESHACER, y las tres son de que la fila y
   su renglón son DOS `<tr>` para el navegador y UNA cosa para quien mira:
   la regla de abajo de la fila de arriba (`.con-acc`), que partiría el remito de
   sus propias acciones; el `:hover`, que si no ilumina la mitad de arriba y deja
   la de abajo apagada; y el `display: flex`, que va en un `<div>` adentro y no en
   el `<td>` — un `<td>` que deja de ser `table-cell` se sale de la tabla y el
   `colspan` no significa nada. */
.mw-ui .mw-dosp .mw-tabla tr.con-acc > td { border-bottom: none; padding-bottom: 2px; }
.mw-ui .mw-dosp .mw-tabla tr.acc-r > td { padding-top: 0; padding-bottom: 8px; padding-left: 11px; }
.mw-ui .mw-dosp .mw-tabla tr.acc-r .fila-acc {
    display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
}
.mw-ui .mw-dosp .mw-tabla tr.acc-r .nota {
    font-size: 11px; color: var(--muted); line-height: 1.35; min-width: 0;
}
.mw-ui .mw-dosp .mw-tabla tbody tr.acc-r:hover,
.mw-ui .mw-dosp .mw-tabla tbody tr.con-acc:hover { background: transparent; }
.mw-ui .mw-dosp .mw-tabla tbody tr.acc-r:hover td:first-child,
.mw-ui .mw-dosp .mw-tabla tbody tr.con-acc:hover td:first-child { border-left-color: transparent; }

/* Las tres columnas del protocolo: el valor lleva un `<input>` con su unidad al
   lado, así que se le da ancho y lo que cede es la especificación. */
.mw-ui .mw-dosp .mpr-t th:nth-child(2), .mw-ui .mw-dosp .mpr-t td:nth-child(2) { width: 34%; }
.mw-ui .mw-dosp .mpr-t th:nth-child(3), .mw-ui .mw-dosp .mpr-t td:nth-child(3) { width: 138px; }
.mw-ui .mw-dosp .mpr-t .form-input { width: 96px; height: 32px; text-align: right; display: inline-block; }

/* A 390 px LOS DOS PANELES NO EXISTEN, y hay que decirlo porque es la mitad de
   lo que la opción B pierde: se apilan y queda la columna de la opción A. Dos
   columnas de 195 px no son dos paneles, son dos listas rotas.

   Y NO ALCANZA CON `grid-template-columns: 1fr`. Apilados, cada `.col` sigue
   teniendo su `overflow-y: auto`, así que quedan DOS cajas de scroll de 200 px
   una arriba de otra dentro de un diálogo que no scrollea: el que scrollea pasa
   a ser el contenedor, y las columnas dejan de recortar. */
@media (max-width: 760px) {
    .mw-ui .mw-modal.doble { max-width: 100%; }
    .mw-ui .mw-modal .mw-dosp { display: block; overflow-y: auto; }
    .mw-ui .mw-modal .mw-dosp > .col { overflow: visible; min-height: 0; }
    .mw-ui .mw-modal .mw-dosp > .col + .col { border-left: 0; border-top: 1px solid var(--hair); }
    .mw-ui .mw-modal .mw-dosp .al-pie { margin-top: 0; }
    .mw-ui .mw-dos-puntas { grid-template-columns: 1fr; }
    .mw-ui .mw-puente { padding: 4px 0; }
    .mw-ui .mw-puente .material-symbols-outlined { transform: rotate(90deg); }
}

/* =============================================================================
   20. LAS CUATRO QUE QUEDABAN — y la cola de recepción (ETAPA 8)
   =============================================================================
   Las cuatro superficies que el módulo había dejado en Tailwind: exportar a
   Excel, elegir la orden de carga, imputar un Líquido Producto y confirmar una
   pre-recepción. Ganó la opción B de la ronda 4 (14/08/2026): «lo que tiene cola
   es una pantalla».

   Y ESTE BLOQUE ES CORTO, otra vez a propósito. La sección Recepción entera se
   dibuja con `.mw-bar`, `.mw-search`, `.mw-caja`, `table.mw-g`, `.mw-mark`,
   `.mw-chip` y `.mw-aviso` — las mismas piezas que la planilla y la mesa de
   Pendientes—, y el imputador de Líquido Producto usa `.mw-modal.doble` con
   `.mw-dosp`, que la etapa 6 construyó para la ficha. La superficie más cara del
   módulo —ocho familias de color— no estrenó ni una clase.

   LO QUE SÍ HAY ACÁ SON CUATRO COSAS, y las cuatro salen de lo mismo: un
   diálogo que ahora tiene una FRANJA DE TOTAL entre el cuerpo y el pie, y un
   campo numérico que vive adentro de una celda.
   ========================================================================== */

/* 1 · EL AVISO DE RIESGO DE LA SECCIÓN, igual que el de Pendientes: primero, y
   sólo si hay algo que tenga consecuencia. Sin ninguna vieja no hay nada que
   avisar, y un hueco vacío arriba de la lista corre todo hacia abajo. */
.mw-ui #mw-recep-riesgo:empty { display: none; }
.mw-ui #mw-recep-riesgo { margin-bottom: 14px; }

/* 2 · LA FRANJA DE TOTAL COMO HERMANA DEL PIE, no adentro del cuerpo.
   `.mw-tot` nació en §18 para el pase, donde vive ADENTRO de `.cuerpo` y por eso
   tiene sangría de 2 px y una regla de 9 px arriba. Acá cuelga directamente del
   `.mw-modal`, entre el cuerpo y las acciones, y tiene que comportarse como el
   pie: ancho completo, su propio relleno y el lienzo de fondo.

   NO ES EL PIE, Y NO SE PUEDE FUSIONAR CON ÉL. El pie tiene las dos acciones; la
   franja tiene los DOS NÚMEROS que deciden si se puede apretar una. Mezclados en
   un renglón —que es como estaban— el número compite con el botón y el que mira
   tiene que buscar cuál de las dos cosas está leyendo. Y hay un motivo más
   duro: la franja CAMBIA mientras se tipea y el pie no, así que repintar una
   repintaría la otra. */
.mw-ui .mw-modal > .mw-tot {
    margin-top: 0; padding: 10px 16px; background: var(--canvas);
    border-top: 1px solid var(--hair); flex: none;
}
/* El estado del reparto va a la derecha y no compite con los dos números: es
   una frase, no una cifra. Misma regla que la `.nota` del pie del formulario. */
.mw-ui .mw-tot .nota {
    margin-left: auto; font-size: 11.5px; color: var(--muted);
    line-height: 1.4; text-align: right;
}

/* 3 · EL CAMPO DE KG DE UNA FILA. Es el `.form-input` del módulo con el ancho de
   su número: 32 px de alto en vez de 38 —una fila de tabla con un control de 38
   crece un 40 % y la tabla deja de poder recorrerse— y alineado a la derecha,
   porque lo que hay que comparar de un renglón al otro es la última cifra.

   Y EL RECHAZO LO VISTE EL CSS, no el JavaScript. El `recompute()` escribía
   `border-red-500` y `bg-red-50` a mano sobre el control: es la trampa de
   `auth.js` —el JS decidiendo cómo se ve algo— y además dejaba dos clases de
   Tailwind vivas adentro de un módulo migrado. Hoy el JS pone `.mal` y
   `aria-invalid`, que es lo que además lo dice en voz alta. */
.mw-ui .form-input.kg {
    height: 32px; width: 104px; padding: 0 9px; text-align: right;
    font-variant-numeric: tabular-nums; font-weight: 600;
}
.mw-ui .form-input.mal,
.mw-ui .form-input[aria-invalid="true"] {
    border-color: var(--crit); background: var(--crit-050); color: var(--crit);
}

/* 4 · UNA TABLA ADENTRO DEL CUERPO DE UN DIÁLOGO TAMBIÉN RECORTA. Es la misma
   trampa que §18 resolvió para la tabla de lotes del pase y §19 para las de los
   paneles, y muerde por tercera vez en los mismos dos lugares: el nombre de un
   cliente y el número de un comprobante son cadenas largas que, sin `fixed`, le
   comen la columna a la de al lado y empujan el botón fuera del diálogo. Lo que
   cede es el texto, que para eso lleva `.trunc`.

   (Se declara por `.cuerpo >` y no sobre `.mw-tabla` a secas a propósito: la
   ficha del origen del formulario tiene una `.mw-tabla` adentro que mide por
   contenido desde la etapa 5, y ponerle `fixed` de arriba le cambiaría el ancho
   a once archivos sin que nadie lo pidiera.) */
.mw-ui .mw-modal .cuerpo > .mw-tabla { table-layout: fixed; }
.mw-ui .mw-modal .cuerpo .mw-tabla td.trunc {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Las celdas de estas tablas se leen en renglón, no apiladas: `vertical-align`
   de `.mw-tabla` es `top` porque en el pase una celda tiene una pastilla debajo
   del número. Acá hay un control de 32 px al lado de texto de 12,5. */
.mw-ui .mw-modal .cuerpo > .mw-tabla td { vertical-align: middle; }

/* 5 · EL ALTO FIJO DEL IMPUTADOR, y va en la HOJA porque tiene que poder
   levantarse a 390 px. Un diálogo de dos paneles necesita alto propio: con
   `height:auto` las dos columnas miden lo que mide la más larga y la otra queda
   con medio panel de aire, que es como se veía. Pero a 390 los dos paneles se
   APILAN (§19), y ahí un alto fijo deja el de abajo —el que tiene los campos de
   kg— fuera de la pantalla. Escrito inline en el JavaScript le ganaba a la media
   query y no había forma de soltarlo. LO AGARRÓ LA FOTO. */
.mw-ui .mw-modal.doble.alto { height: min(620px, 100% - 32px); }

/* 6 · A 390 px. */ El diálogo de dos paneles ya se apila solo (§19), y la franja de
   total tiene que dejar de ser un renglón de tres cosas: los dos números al lado
   y el estado abajo, ocupando el ancho. */
@media (max-width: 760px) {
    .mw-ui .mw-modal > .mw-tot { padding: 9px 12px; }
    .mw-ui .mw-tot .nota { margin-left: 0; width: 100%; text-align: left; }
    .mw-ui .form-input.kg { width: 88px; }
    /* El alto fijo se suelta: apilados, los dos paneles miden lo que miden. */
    .mw-ui .mw-modal.doble.alto { height: auto; }
    /* Y SCROLLEA EL CONJUNTO, NO CADA PANEL. Apilados, dos columnas con su
       propio `overflow-y` son dos barras de scroll una arriba de la otra: para
       llegar al campo de kg hay que descubrir que el panel de arriba se puede
       correr. En dos columnas el scroll por panel es lo correcto y §19 lo
       sostiene; en una sola, no. */
    .mw-ui .mw-modal .mw-dosp { overflow-y: auto; }
    .mw-ui .mw-modal .mw-dosp > .col { overflow-y: visible; }
}

/* =============================================================================
   21. LAS DOS QUE FALTABAN DE VERDAD — «Asignar tipo» (ETAPA 9)
   =============================================================================
   Los dos modales que se abren desde el botón «Asignar tipo» de la fila «Sin
   factura» de Pendientes, y que la etapa 8 no vio porque su alcance se heredó de
   una nota vieja en vez de medirse contra el archivo.

   EL PICKER DE OCAs NO ESTRENA NADA, y ésa es la mitad de la noticia: es la
   misma pregunta que el imputador de Líquido Producto —«¿entre cuáles reparto
   estos kilos?»— así que usa la misma `.mw-modal.ancho` con su `.mw-tabla`, el
   mismo `.form-input.kg` de §20, la misma `.mw-tot` y el mismo pie. Verlas
   distintas hacía pensar que una hacía algo que la otra no.

   LO ÚNICO PROPIO ES LA LISTA DE OPCIONES, y es una pieza que este módulo YA
   TENÍA escrita: los seis renglones del desplegable «Registrar» (§14) son
   exactamente esto —un glifo, un nombre y la línea que dice qué hace—. Estaban
   escritos como `.mw-ui.mw-menu button`, o sea atados al elemento que cuelga del
   <body>, así que no se podían usar adentro de un diálogo sin copiarlos.

   Se extrajeron a `.mw-op` y el desplegable pasa a usarla. Es el criterio del §5
   de este archivo aplicado al derecho: la pregunta no es si se llaman igual sino
   si SON el mismo componente, y acá lo son — se aprieta uno de varios y se
   elige. Dos vocabularios para «elegir una opción de una lista» es lo que esta
   migración vino a sacar.
   ========================================================================== */

/* La lista. Se apilan con `gap`, no con margen: un margen entre hermanos se
   colapsa o se duplica según quién quede primero. */
.mw-ui .mw-ops { display: flex; flex-direction: column; gap: 6px; }

/* La opción. Es el renglón del desplegable «Registrar» (§14) sin su scope. */
.mw-ui .mw-op {
    display: flex; align-items: flex-start; gap: 11px; width: 100%;
    background: var(--surface); border: 1px solid var(--hair-strong);
    border-radius: 10px; padding: 10px 12px;
    font: inherit; text-align: left; cursor: pointer; color: var(--ink);
    transition: background .15s var(--curva), border-color .15s var(--curva);
}
.mw-ui .mw-op > .material-symbols-outlined {
    font-size: 20px; color: var(--navy-500); flex: none; margin-top: 1px;
}
.mw-ui .mw-op .q { min-width: 0; flex: 1; }
.mw-ui .mw-op .t { display: block; font-size: 12.5px; font-weight: 700; line-height: 1.3; }
.mw-ui .mw-op .d { display: block; font-size: 11px; color: var(--muted); line-height: 1.35; margin-top: 1px; }
.mw-ui .mw-op:hover:not(:disabled), .mw-ui .mw-op:focus-visible:not(:disabled) {
    background: var(--navy-050); border-color: var(--navy-300); outline: none;
}

/* LA QUE CORRESPONDE. Trazo navy y lienzo navy claro: es DÓNDE ESTÁ LA ACCIÓN,
   no «esto es bueno». Lo que dice por qué corresponde es la pastilla verde de al
   lado, y ésa sí es un estado. Pintar el botón entero de verde sería decir dos
   veces lo mismo y dejar el ojo sin saber qué apretar. */
.mw-ui .mw-op.es { border-color: var(--navy); background: var(--navy-050); }
.mw-ui .mw-op.es .t { color: var(--navy-700); }
.mw-ui .mw-op .mw-chip { flex: none; align-self: center; }

/* LA BLOQUEADA. Apagada de verdad, con `disabled` — no con opacidad y un
   `cursor` que dicen que no se puede mientras el click igual hace algo. Es la
   fila 2 del manual §7, y en esta misma pantalla ya costó un cartel: el botón se
   veía bloqueado, la nota explicaba por qué, y apretarlo abría un modal a contar
   eso mismo. Lo que faltaba era el atributo. */
.mw-ui .mw-op:disabled {
    opacity: .5; cursor: not-allowed;
    background: var(--canvas); border-color: var(--hair);
}
.mw-ui .mw-op:disabled > .material-symbols-outlined { color: var(--faint); }

@media (max-width: 760px) {
    .mw-ui .mw-op { padding: 9px 10px; }
    .mw-ui .mw-op .mw-chip { align-self: flex-start; }
}
