/* =============================================================================
   STOCK GENERAL — identidad visual. Scope `.stk-ui`.
   =============================================================================
   docs/RUNBOOK-STOCK-GENERAL.md. Ronda de mockups cerrada el 23/08/2026: ganó
   la opción B, «tres preguntas».

   ── QUÉ DECIDIÓ LA RONDA, y por qué importa para leer esta hoja ──────────────
   Stock General no es una pantalla con tres secciones: son TRES RESPUESTAS A
   TRES PREGUNTAS DISTINTAS —de quién son los kilos (saldo comercial), dónde
   están (físico contado de los lotes) y qué hay arriba de un camión (la Playa,
   la única de las tres donde se ESCRIBE)—. Leen colecciones distintas y
   devuelven filas de otra especie: son pantallas, no un `where`, y por eso van
   en una barra de secciones y no en un segmento (manual §7).

   Lo que había: las tres APILADAS en un scroll de página, la primera adentro de
   una caja de `h-[80vh]` con scroll propio. O sea dos scrolls anidados, y la
   Playa —lo único que se opera— siempre debajo del pliegue. El teléfono, en
   cambio, ya las repartía en PESTAÑAS y no tenía Playa: dos formas distintas de
   la misma pantalla. La opción B las hace converger.

   ── EL TRATAMIENTO, y por qué ────────────────────────────────────────────────
   CABECERA LITE, la de Facturación, Remitos, Movimientos y Órdenes. Sale del
   árbol del §3 de RUNBOOK-NUEVA-IDENTIDAD: es una PANTALLA-TABLA de consulta
   —una grilla larga que se mira veinte minutos seguidos— y no un trabajo mixto
   de fichas y formularios. La única superficie navy rellena de la pantalla es
   el botón principal de la barra del armazón: acá abajo no hay ninguna
   (manual §1.2).

   ACENTO: NAVY Y NADA MÁS. La regla del acento dice que un color interactivo
   propio sólo se justifica cuando navy ya está gastado en la estructura, y este
   módulo no apila cuatro zonas: es una barra, una tira y una sección. No se
   inventa un segundo azul.

   CERO TOKENS PROPIOS. La paleta sale entera de core/tokens.css. Si algún día
   hace falta apartarse, se redeclara el token en este scope y SE ESCRIBE EL
   PORQUÉ al lado — hoy no hay ninguno.

   ── LOS DIEZ COLORES QUE MUEREN ──────────────────────────────────────────────
   El módulo tenía color = CATEGORÍA en diez familias, medidas sin un solo
   comentario: índigo (Por Propietario), ámbar (Por Depósito), rosa (la Playa),
   esmeralda (los dos «Excel»), más rojo, azul, verde, naranja, rose y cian
   repartidos. Ninguno decía nada del ESTADO de un dato: decían de qué sección
   era el botón. Se van etapa por etapa, y lo que queda es el vocabulario del
   manual §1.1 —ámbar lo que pide algo, verde lo cumplido, rojo lo que está
   mal—.

   ── ORDEN DE LAS SECCIONES ───────────────────────────────────────────────────
    1. EL ARMAZÓN — la tarjeta, la barra de secciones y el área de trabajo
    2. LA TIRA DE CONTROL — los kilos y de cuándo son          (ETAPA 1)
    3. DE QUIÉN ES — la tabla de cuentas                       (ETAPA 2)
    4. LA FICHA DE UNA CUENTA — la cabecera y los movimientos  (ETAPA 3)
    5. DÓNDE ESTÁ — los depósitos                              (ETAPA 4)
    6. EN LA PLAYA — los carteles y sus dos diálogos           (ETAPA 5)
   ============================================================================= */


/* =============================================================================
   1. EL ARMAZÓN — la tarjeta, la barra de secciones y el área de trabajo
   =============================================================================
   Portado de `ord-ui.css` §1, que es la implementación hermana más nueva de la
   cabecera lite y el módulo que está justo abajo en el rail. Mismo gesto,
   mismos tiempos, mismas trampas ya resueltas.

   POR QUÉ EL SCOPE VA EN UN <div> HIJO Y NO EN EL PROPIO `.page-content`.
   `#page-stock` oculta y muestra con el `.hidden` de Tailwind, que es UNA clase;
   si el armazón se escribiera sobre ese mismo elemento, cualquier regla del
   módulo que declarara `display` ahí le ganaría y la pantalla no se ocultaría
   NUNCA, tapando a las demás. En un hijo eso no puede pasar — es lo que hacen
   el ABM, Configuración, Movimientos, Órdenes y Ventas.
   ========================================================================== */

/* ── LA CADENA DE ALTO, y por qué hay un compuesto ─────────────────────────── */
/* `#page-stock` declara `data-shell="full"` desde la etapa 1, así que el armazón
   le da el alto entero y le saca el padding. De ahí para abajo el alto hay que
   PASARLO: sin esto la tarjeta mide lo que mide su contenido y queda flotando
   sobre medio lienzo.

   Y VA COMO COMPUESTO, `.stk-ui.stk-hub`, SIN ESPACIO: las dos clases están en
   el MISMO elemento. Con espacio no matchea nada y el bloque se cae EN SILENCIO
   (trampa del §4 del RUNBOOK-NUEVA-IDENTIDAD).

   EL CANDADO DE ABAJO NO ES PRECAUCIÓN: ES CARGA VIVA. La ficha de una cuenta
   —el detalle paginado de movimientos— esconde este `<div>` para mostrarse.
   `.stk-ui.stk-hub` son dos clases (0,2,0) y el `.hidden` de Tailwind es una
   (0,1,0): sin esta línea el armazón NO se esconde y el detalle se dibuja
   ENCIMA de la barra de secciones. */
.stk-ui.stk-hub {
    display: flex; flex-direction: column;
    flex: 1; min-height: 0; min-width: 0;
}
.stk-ui.stk-hub.hidden { display: none; }

.stk-ui .stk-shell {
    background: var(--canvas);
    border-radius: var(--r-card);
    overflow: hidden;
    box-shadow: var(--shadow);
    display: flex; flex-direction: column; flex: 1; min-height: 0;
}

/* ── La barra de secciones — subrayado que crece desde el centro ───────────── */
/* LAS TRES SECCIONES SON TRES PANTALLAS, y por eso `stkGo()` SÍ oculta y muestra
   contenedores — a diferencia de `ordGo()`, donde las tres bandejas comparten el
   render y sólo cambia un `where`. Acá cada una lee otra colección, tiene otras
   columnas y publica otras acciones.

   (Lo que había antes no era una barra: eran tres tarjetas de ancho completo
   apiladas una debajo de la otra, cada una con su ícono de color —índigo, ámbar,
   rosa— y su propio botón de exportar adentro.) */
.stk-ui .stk-secnav {
    background: var(--surface);
    border-bottom: 1px solid var(--hair);
    display: flex; gap: 2px; padding: 0 14px; flex-wrap: wrap;
}
.stk-ui .stk-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);
}
.stk-ui .stk-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. */
.stk-ui .stk-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);
}
.stk-ui .stk-secnav button:hover, .stk-ui .stk-secnav button:focus-visible {
    color: var(--navy); background: var(--navy-050); outline: none;
}
.stk-ui .stk-secnav button:hover::after,
.stk-ui .stk-secnav button:focus-visible::after { transform: scaleX(.55); }
.stk-ui .stk-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 se pueda olvidar en silencio. */
.stk-ui .stk-secnav button.on,
.stk-ui .stk-secnav button[aria-current="true"] { color: var(--navy); font-weight: 700; }
.stk-ui .stk-secnav button.on::after,
.stk-ui .stk-secnav button[aria-current="true"]::after { transform: scaleX(1); }
.stk-ui .stk-secnav .tail { margin-left: auto; display: flex; align-items: center; gap: 8px; }

/* ── El contador de cada sección ───────────────────────────────────────────── */
/* Cuántas cuentas con saldo, cuántos depósitos, cuántos carteles en uso. En
   reposo es navy tenue; en la sección activa se rellena, porque ahí el número es
   el de lo que se está mirando.

   NO LLEVA COLOR DE ESTADO. Un contador de depósitos no es ámbar por ser
   depósitos —eso sería categoría otra vez—. Lo que sí es estado, y lo que sí
   lleva ámbar, vive en la cola de la barra: los lotes PT sin ubicar. */
.stk-ui .stk-secnav .cnt {
    font-size: 11px; font-weight: 700; line-height: 1.6;
    background: var(--navy-050); color: var(--navy-500);
    border-radius: 999px; padding: 0 8px;
    font-variant-numeric: tabular-nums;
    transition: background .15s var(--curva), color .15s var(--curva);
}
.stk-ui .stk-secnav button.on .cnt,
.stk-ui .stk-secnav button[aria-current="true"] .cnt { background: var(--navy); color: #fff; }
/* Mientras no se sabe. Un contador que dice 0 antes de haber contado miente más
   que uno vacío — y este módulo tenía tres secciones que decían «Sincronizando
   saldos…» con un ícono `sync` girando, que es lo mismo en peor. */
.stk-ui .stk-secnav .cnt.esperando { color: transparent; min-width: 26px; }

/* ── El contador accionable, en la cola de la barra ────────────────────────── */
/* Los lotes PT que están hechos y no están en ninguna posición. Vive en la cola
   y no adentro de la Playa: desde ahí se ve al entrar, se ve desde las TRES
   secciones y no se va al hacer scroll. Es ámbar porque PIDE algo — eso sí es
   estado (manual §1.1).

   Con cero NO se dibuja NADA: un aviso que dice «0 sin ubicar» ocupa el mismo
   lugar que uno que dice 3 y entrena a no mirarlo.

   En la etapa 1 la cola queda VACÍA: la llena la etapa 4, cuando la Playa sepa
   contar sus lotes sin ubicar sin haberse dibujado. */
.stk-ui .stk-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);
}
.stk-ui .stk-alert:hover, .stk-ui .stk-alert:focus-visible {
    background: #fdf0d8; transform: translateY(-1px); box-shadow: var(--e1); outline: none;
}
.stk-ui .stk-alert .v {
    font-size: 15px; font-weight: 800; line-height: 1; font-variant-numeric: tabular-nums;
}
.stk-ui .stk-alert .k { font-weight: 700; letter-spacing: .06em; text-transform: uppercase; }
.stk-ui .stk-alert .material-symbols-outlined { font-size: 16px; color: var(--muted); }

/* ── El área de trabajo ───────────────────────────────────────────────────── */
/* Sin padding lateral: la sección 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.

   LA MULETA MURIÓ CON LA ÚLTIMA PANTALLA VIEJA (etapa 5). `.stk-provisorio` era
   el padding provisorio de los paneles que todavía estaban en Tailwind: la
   etapa 2 se llevó su modificador `.fijo` con la tabla de cuentas, y la 5 se
   llevó la clase entera con la Playa. Está anotado acá y no borrado en silencio
   porque una muleta que desaparece sin dejar rastro vuelve sola en la etapa
   siguiente. */
.stk-ui .stk-view {
    padding: 16px 0 22px; background: var(--canvas);
    flex: 1; min-height: 0; overflow: hidden;
    display: flex; flex-direction: column;
}
/* EL ENCABEZADO DE PANTALLA QUEDA VACÍO EN EL ESCRITORIO (24/08): ahí sólo vive
   el «Actualizar» propio del teléfono. Un div vacío con `margin-bottom` sigue
   empujando la tabla hacia abajo —que es justo lo que se vino a recuperar—,
   así que `:empty` lo saca del flujo. */
.stk-ui .stk-ph { margin: 0 var(--gutter) 14px; }
.stk-ui .stk-ph:empty { display: none; }
.stk-ui .stk-ph h3 { font-size: .95rem; font-weight: 700; color: var(--ink); margin: 0; }
.stk-ui .stk-ph p { font-size: 12px; color: var(--muted); margin: 2px 0 0; max-width: 78ch; }

/* EL QUE SCROLLEA ES EL PANEL, NO EL ÁREA. Si el scroll viviera en `.stk-view`,
   la cabecera `sticky` de la grilla que llega en la etapa 2 se pegaría a un
   contenedor que NO se mueve —o sea, no se pegaría a nada—. */
.stk-ui .stk-panel {
    flex: 1; min-height: 0; min-width: 0;
    display: flex; flex-direction: column;
}
/* `.stk-panel` declara `display`, que son dos clases (0,2,0) contra la sola del
   `.hidden` de Tailwind: sin este candado el panel escondido se sigue viendo y
   las tres secciones se dibujan una encima de otra. Es la misma trampa del §4
   del runbook, un nivel más abajo. */
.stk-ui .stk-panel.hidden { display: none; }
/* Acá vivía `.stk-provisorio` —ver arriba—. Las tres secciones tienen hoy su
   propia caja y su propio scroll: no hay nada que apuntalar. */

/* ── A 640 px ─────────────────────────────────────────────────────────────── */
/* El TELÉFONO de este módulo está declarado fuera de alcance hasta la etapa 5 —
   lo dibuja `renderMobileStock()`, que es otro camino entero—. Lo de acá es sólo
   que el armazón de escritorio no se rompa en una ventana angosta: la barra de
   secciones envuelve en vez de recortarse, y la tarjeta pierde el radio porque
   ya no tiene a los lados de qué separarse. */
@media (max-width: 640px) {
    .stk-ui .stk-shell { border-radius: 0; box-shadow: none; }
    .stk-ui .stk-secnav { padding: 0 8px; }
    .stk-ui .stk-secnav button { padding: 10px 11px 11px; font-size: 12px; }
    .stk-ui .stk-secnav .tail { margin-left: 0; width: 100%; }
    .stk-ui .stk-ph { margin: 0 12px 12px; }
}


/* =============================================================================
   2. LA COLA DE LA BARRA — lo que se avisa, y de cuándo es el número (ETAPA 1)
   =============================================================================
   ACÁ VIVÍA LA TIRA DE CONTROL, y se fue el 24/08 a pedido de Hernán. Eran tres
   cifras en cajas de ancho completo —físico de lotes activos, comercial por
   cuenta, y la resta— entre la barra de secciones y la pantalla: unos 90 px que
   empujaban la tabla hacia abajo se mirara la sección que se mirara. Los dos
   totales ya se dicen en el renglón de la barra superior y en el pie de cada
   sección —que es de donde salen—, y la diferencia nunca llegó a tener una
   tolerancia con la que juzgarse, así que era un número que se miraba y no se
   podía usar. Con ella se fue el encabezado de pantalla (`.stk-ph`), que
   explicaba en dos renglones lo que la pestaña ya dice.

   LO QUE NO SE FUE VIVE EN LA COLA DE LA BARRA DE SECCIONES, que ya estaba
   dibujada y tenía ese costado vacío. Son tres cosas de tres pesos distintos, y
   la diferencia entre ellas ES el diseño:

   · `.stk-alert` — ÁMBAR Y BOTÓN. Pide algo: hay lotes hechos, en un depósito
     CON carteles, y no están arriba de ninguno. El color es de estado (manual
     §1.1) y el clic lleva a la playa, que es donde se resuelve.

   · `.stk-nota` — NEUTRA Y NO ES UN BOTÓN. Los lotes que están en un depósito
     que no trabaja por posiciones (Azucel 2, Azucel 4, Polvos…). Hasta el 24/08
     caían en el mismo ámbar y lo inflaban —la barra decía «18 SIN UBICAR» sobre
     una playa que sólo existe en Azucel 1—, o sea que el aviso pedía algo
     imposible para quince de esos dieciocho. Un aviso que pide lo imposible se
     aprende a ignorar, y se lleva puesto al que sí pide algo. Acá no hay nada
     que hacer, así que no hay color de estado ni cursor de clic.

   · `.stk-fresc` — DE CUÁNDO ES EL NÚMERO. El saldo por cuenta sale de tres
     caminos distintos —la suscripción viva a `stock_balance/clientes`, la foto
     que dejó el robot en `dashboard_kpis/main`, o la lectura completa de
     `stock_snapshots`— y los tres se veían IGUAL. El módulo tenía el texto
     escrito («En vivo» / «calculado a las 14:32») y lo metía en
     `#insumos-count-badge`, que es el contador de Producción → Insumos: un id
     que en esta pantalla no existe, así que la rama entera no corría y el dato
     se tiraba sin un error, sin un warning y sin un hueco visible.
     (identidad-visual.md §7, «un `getElementById` de un id que NO es tuyo».)
     El color es de ESTADO y no de categoría: verde el saldo vivo —se actualiza
     solo con cada movimiento—, ámbar la foto del robot, que tiene una hora y
     puede estar vieja.
   ========================================================================== */

/* La nota neutra. Misma silueta que `.stk-alert` para que se lean como parientes
   —son las dos cosas que la barra cuenta del piso— y ningún color de estado,
   porque no pide nada. NO es un `<button>`: no hay adónde llevar al que la lea. */
.stk-ui .stk-nota {
    display: inline-flex; align-items: center; gap: 9px;
    background: var(--canvas); border: 1px solid var(--hair);
    border-radius: 999px; padding: 5px 12px 5px 10px; margin: 6px 0;
    font-family: inherit; font-size: 11.5px; color: var(--muted);
}
.stk-ui .stk-nota .v {
    font-size: 15px; font-weight: 800; line-height: 1; font-variant-numeric: tabular-nums;
    color: var(--ink);
}
.stk-ui .stk-nota .k { font-weight: 600; }
.stk-ui .stk-nota .material-symbols-outlined { font-size: 16px; color: var(--faint); }

/* La frescura. Sin caja: es lo último de la fila y no compite con los dos
   contadores que sí son objetos. */
.stk-ui .stk-fresc {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 0 4px; font-size: 11px; color: var(--muted); white-space: nowrap;
}
.stk-ui .stk-fresc .material-symbols-outlined { font-size: 15px; }
.stk-ui .stk-fresc b { font-weight: 700; }
.stk-ui .stk-fresc.vivo .material-symbols-outlined,
.stk-ui .stk-fresc.vivo b { color: var(--ok); }
.stk-ui .stk-fresc.foto .material-symbols-outlined,
.stk-ui .stk-fresc.foto b { color: var(--warn); }

/* El cuadre (25/08). Misma silueta que la frescura —sin caja, es un dato de
   confianza y no un objeto— y color de ESTADO: verde si el físico y el comercial
   están dentro de la tolerancia del control nocturno, rojo si no. Con un lado
   sin leer no se dibuja. La tolerancia no vive acá: es `TOLERANCIA_CUADRE_KG`
   del servicio, la misma que `cuadrarStockTotal()` y `salud_stock`. */
.stk-ui .stk-cuadre {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 0 4px; font-size: 11px; color: var(--muted); white-space: nowrap;
    font-variant-numeric: tabular-nums;
}
.stk-ui .stk-cuadre .material-symbols-outlined { font-size: 15px; }
.stk-ui .stk-cuadre b { font-weight: 700; }
.stk-ui .stk-cuadre.ok .material-symbols-outlined,
.stk-ui .stk-cuadre.ok b { color: var(--ok); }
.stk-ui .stk-cuadre.mal .material-symbols-outlined,
.stk-ui .stk-cuadre.mal b { color: var(--crit); }


/* =============================================================================
   3. DE QUIÉN ES — la lista de cuentas (ETAPA 2)
   =============================================================================
   Portado de `ord-ui.css` §2, que es la implementación hermana de la cabecera
   lite. Cero tokens propios y cero valores nuevos.

   LO QUE ESTA SECCIÓN NO ES: «la tabla con estilo». La tabla vieja se veía bien.
   Lo que cambia es QUÉ DICE, y son cuatro cosas:

     · el buscador no declaraba su ÁMBITO. Filtra lo que se trajo, y lo que se
       trajo depende de «ver ceros»: una cuenta en cero contestaba «no se
       encontraron resultados», que se lee como «no existe»;
     · la REGLA MOYCO —todo lo que diga «MOYCO» cae en una sola fila— era
       invisible. Una fila decía 1.094.450 kg y no había forma de saber que eran
       cuatro cuentas de Flexxus sumadas;
     · el DESCUBIERTO se marcaba pintando la fila entera de rojo claro, que es
       la fila diciendo «soy roja» en vez de decir qué le pasa;
     · y el pie no existía: la pantalla no decía de dónde salía el número.

   LA REGLA DE COLOR: la fila NO es un color. Lo único que acá lleva color es el
   ESTADO del saldo —rojo el descubierto, gris el cero— y son estados del dato,
   no etiquetas de familia (manual §1.1).
   ========================================================================== */

/* ── La barra: el buscador y su ÁMBITO ─────────────────────────────────────── */
.stk-ui .stk-bar {
    display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
    padding: 0 var(--gutter) 12px;
}
.stk-ui .stk-search { position: relative; flex: 0 1 300px; min-width: 210px; }
.stk-ui .stk-search > .material-symbols-outlined {
    position: absolute; left: 11px; top: 50%; transform: translateY(-50%);
    font-size: 18px; color: var(--faint); pointer-events: none;
}
.stk-ui .stk-search input {
    width: 100%; font: inherit; font-size: 12.6px; color: var(--ink);
    background: var(--surface); border: 1px solid var(--hair-strong);
    border-radius: 9px; padding: 8px 12px 8px 36px;
    transition: border-color .15s var(--curva), box-shadow .15s var(--curva);
}
.stk-ui .stk-search input:focus {
    outline: none; border-color: var(--navy-300);
    box-shadow: 0 0 0 3px var(--navy-050);
}
/* EL ÁMBITO VA AL LADO DEL CAMPO Y SIEMPRE A LA VISTA, no en un `title`. */
.stk-ui .stk-ambito { font-size: 11.5px; color: var(--faint); line-height: 1.4; }
.stk-ui .stk-ambito b { color: var(--muted); font-weight: 700; }

/* «Ver ceros» deja de ser un interruptor pintado a mano con seis clases y una
   pastilla animada, y pasa a ser lo que es: una casilla con su rótulo. */
.stk-ui .stk-chk {
    display: inline-flex; align-items: center; gap: 7px; margin-left: auto;
    font-size: 11.5px; font-weight: 600; color: var(--muted); cursor: pointer;
    user-select: none;
}
.stk-ui .stk-chk input { width: 15px; height: 15px; accent-color: var(--navy); cursor: pointer; }
.stk-ui .stk-chk:hover { color: var(--navy); }

/* ── La tarjeta ────────────────────────────────────────────────────────────── */
/* De borde a borde: pierde el radio y los trazos laterales porque ya no tiene a
   los lados de qué separarse, y así el texto de la primera columna arranca en la
   misma columna que el título del módulo. */
.stk-ui .stk-caja {
    background: var(--surface);
    border-top: 1px solid var(--hair); border-bottom: 1px solid var(--hair);
    box-shadow: var(--e1);
    display: flex; flex-direction: column; flex: 1; min-height: 0;
}
/* `min-height: 0` no es decorativo: un item flex sin él estira en vez de
   scrollear, y con `overflow` distinto de `visible` se encoge hasta cero — se ve
   perfecto mientras recorta. */
.stk-ui .stk-scroll { overflow: auto; flex: 1; min-height: 0; }

/* ── La grilla ─────────────────────────────────────────────────────────────── */
.stk-ui table.stk-g { width: 100%; border-collapse: collapse; font-size: 12.8px; }
/* LA CABECERA SE ESCRIBE SOBRE `.stk-scroll th` Y NO SOBRE `table.stk-g th`, y
   es a propósito. El esqueleto de `gsZonaCargando()` dibuja SU tabla sin ninguna
   clase, justamente para heredar la cabecera del módulo y medir lo mismo que la
   de verdad (§5 del manual). Con el selector atado a `.stk-g` no heredaba nada:
   la cabecera del esqueleto salía sin versalitas y sin la regla de 2 px, o sea
   más baja, y la zona saltaba al llegar los datos — que es exactamente lo único
   que justifica el costo de un esqueleto. */
.stk-ui .stk-scroll th {
    /* EL ALTO VA DECLARADO, y es la otra mitad de que el esqueleto sirva. La
       cabecera de verdad lleva DOS renglones en la columna de bolsas —el nombre
       y el «estimadas»— y la del esqueleto lleva uno solo: sin un alto fijo,
       entra 17 px más baja y la tabla salta justo al llegar los datos. Medido
       con `--medir`, no elegido. */
    height: 50px;
    position: sticky; top: 0; z-index: 2;
    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;
}
.stk-ui table.stk-g td {
    padding: 8px 12px; border-bottom: 1px solid var(--hair);
    color: var(--ink); vertical-align: middle; white-space: nowrap;
}
/* El único que envuelve es el nombre: es texto de largo variable. Un número
   partido en dos renglones se lee como dos números. */
.stk-ui table.stk-g td.wrap, .stk-ui table.stk-g th.wrap { white-space: normal; min-width: 190px; }

/* LOS ANCHOS SE DECLARAN, Y SON LOS MISMOS QUE LOS DEL ESQUELETO. Sin esto el
   reparto automático le daba el sobrante a la última columna —la del chevrón—,
   así que «Estado» quedaba flotando en el medio de la fila a medio metro de su
   encabezado, y encima la tabla no coincidía con la forma de la espera, que sí
   declara sus anchos (`STK_FORMA_CUENTAS`). Si acá se cambia uno, se cambia
   allá: es el mismo reparto dicho dos veces, y el banco los compara. */
.stk-ui table.stk-g { table-layout: fixed; }
.stk-ui table.stk-g th:nth-child(1) { width: 44%; }
.stk-ui table.stk-g th:nth-child(2) { width: 18%; }
.stk-ui table.stk-g th:nth-child(3) { width: 16%; }
.stk-ui table.stk-g th:nth-child(4) { width: 16%; }
.stk-ui table.stk-g th:nth-child(5) { width: 6%; }
/* Con `table-layout: fixed` el texto que no entra se recorta en silencio, así
   que el nombre —lo único de largo impredecible— tiene que poder envolver. */
.stk-ui table.stk-g td.wrap .t { white-space: normal; overflow-wrap: anywhere; }
.stk-ui table.stk-g tbody tr { transition: background .13s var(--curva); cursor: pointer; }
.stk-ui table.stk-g tbody tr:hover { background: var(--navy-050); }
.stk-ui table.stk-g tbody tr:focus-visible {
    outline: 2px solid var(--navy-300); outline-offset: -2px; background: var(--navy-050);
}
.stk-ui table.stk-g .n { text-align: right; font-variant-numeric: tabular-nums; }
.stk-ui table.stk-g .c { text-align: center; }
.stk-ui table.stk-g .sub { display: block; font-size: 10.5px; color: var(--faint); font-weight: 400; margin-top: 1px; }
.stk-ui table.stk-g td.vacia { padding: 40px 16px; text-align: center; color: var(--faint); font-style: italic; white-space: normal; }
.stk-ui table.stk-g td:first-child { border-left: 3px solid transparent; padding-left: calc(var(--gutter) - 3px); }
.stk-ui table.stk-g th:first-child { padding-left: var(--gutter); }
.stk-ui table.stk-g th:last-child, .stk-ui table.stk-g td:last-child { padding-right: var(--gutter); }

/* ── La franja de estado, a la izquierda de la fila ────────────────────────── */
/* TRES PÍXELES, NO LA FILA ENTERA PINTADA. La pantalla vieja le ponía
   `bg-red-50` a la fila completa del descubierto: la fila decía «soy roja» en
   vez de decir qué le pasa, y encima el hover tenía que traer su propio rojo
   para no apagarse. Acá la fila es blanca y lo que habla es el trazo.
   Y el ESTADO no se guarda en la clase de color: lo decide el JS y la hoja sólo
   lo pinta (manual §7). */
.stk-ui table.stk-g tr.st-desc td:first-child { border-left-color: var(--crit); }
.stk-ui table.stk-g tr.st-cero td:first-child { border-left-color: var(--hair-strong); }
.stk-ui table.stk-g tr.st-desc .kg { color: var(--crit); }
.stk-ui table.stk-g tr.st-cero td { color: var(--faint); }

/* El kilo es el dato por el que se entra a esta pantalla. */
.stk-ui table.stk-g .kg {
    font-variant-numeric: tabular-nums; font-weight: 700; font-size: 13.4px;
    color: var(--ink); letter-spacing: -.01em;
}

/* La inicial de la cuenta. Era un círculo blanco con sombra y trazo; acá es
   navy tenue y no compite con el número, que es lo que se viene a leer. */
.stk-ui table.stk-g .ini {
    display: inline-flex; align-items: center; justify-content: center;
    width: 24px; height: 24px; border-radius: 50%; margin-right: 9px;
    background: var(--navy-050); color: var(--navy-500);
    font-size: 11px; font-weight: 700; vertical-align: middle; flex: none;
}
.stk-ui table.stk-g .nm { display: flex; align-items: center; min-width: 0; }
.stk-ui table.stk-g .nm .t { min-width: 0; }

/* El chevrón de la fila. No es un botón: la fila entera abre. */
.stk-ui table.stk-g .chev {
    color: var(--hair-strong); font-size: 18px;
    transition: color .13s var(--curva), transform .18s var(--curva);
}
.stk-ui table.stk-g tbody tr:hover .chev { color: var(--navy-300); transform: translateX(2px); }

/* ── Pastillas de estado ───────────────────────────────────────────────────── */
.stk-ui .stk-b {
    display: inline-block; font-size: 10.5px; font-weight: 700; letter-spacing: .03em;
    padding: 1px 7px; border-radius: 5px; border: 1px solid; text-transform: uppercase;
    white-space: nowrap;
}
.stk-ui .stk-b.nav { background: var(--navy-050); color: var(--navy-500); border-color: #cfdcf1; }
.stk-ui .stk-b.wrn { background: var(--warn-050); color: var(--warn); border-color: var(--warn-hair); }
.stk-ui .stk-b.ok  { background: var(--ok-050);  color: var(--ok);  border-color: var(--ok-hair); }
.stk-ui .stk-b.mut { background: #f4f6f9; color: var(--faint); border-color: var(--hair-strong); }
/* `.neg` es lo ÚNICO de esta pantalla que dice que algo está MAL: se despachó
   más de lo que entró a nombre de esa cuenta. */
.stk-ui .stk-b.neg { background: var(--crit-050); color: var(--crit); border-color: var(--crit-hair); }

/* ── El pie que dice DE DÓNDE SALE EL NÚMERO ───────────────────────────────── */
/* Es la pieza más barata de esta etapa y una de las que más arregla: la pantalla
   mostraba un saldo por cuenta sin decir nunca de qué colección salía ni cuántas
   filas quedaron afuera del filtro. */
.stk-ui .stk-pie {
    display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
    padding: 9px var(--gutter); border-top: 1px solid var(--hair);
    background: #fafbfc; font-size: 11.5px; color: var(--muted);
}
.stk-ui .stk-pie b { color: var(--ink); font-variant-numeric: tabular-nums; }
.stk-ui .stk-pie .sp { flex: 1; }

/* ── El vacío ──────────────────────────────────────────────────────────────── */
/* Dice QUÉ está vacío y, si hay un filtro puesto, que el filtro puede ser la
   razón. «No se encontraron resultados» a secas es la respuesta que hacía que
   nadie notara que las cuentas en cero estaban escondidas. */
.stk-ui .stk-vacio { padding: 46px 26px; text-align: center; color: var(--faint); }
.stk-ui .stk-vacio .material-symbols-outlined { font-size: 32px; color: var(--hair-strong); }
.stk-ui .stk-vacio p { margin: 8px 0 0; font-size: 12.5px; }
.stk-ui .stk-vacio p b { color: var(--muted); }

/* ── A 640 px ─────────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
    .stk-ui .stk-bar { padding: 0 12px 10px; }
    .stk-ui .stk-search { flex: 1 1 100%; }
    .stk-ui .stk-chk { margin-left: 0; }
    .stk-ui table.stk-g th:first-child,
    .stk-ui table.stk-g td:first-child { padding-left: 12px; }
    .stk-ui table.stk-g th:last-child,
    .stk-ui table.stk-g td:last-child { padding-right: 12px; }
    .stk-ui .stk-pie { padding: 9px 12px; }
}


/* =============================================================================
   4. LA FICHA DE UNA CUENTA (ETAPA 3)
   =============================================================================
   Ronda de dos mockups cerrada el 23/08/2026: ganó la **A**, «la cuenta a
   pantalla completa». La ficha REEMPLAZA al armazón, como venía haciendo, pero
   ordenada: una cabecera propia que dice de quién es y cuánto tiene, y abajo el
   historial con todo el ancho.

   Es el único lugar del módulo donde el armazón desaparece, y por eso lo que lo
   reemplaza tiene que decir lo mismo que la barra decía: dónde estás y qué
   podés hacer. El crumb de la barra superior lo dice —«Stock General › De quién
   es › LODISER S.A.»— y esta cabecera lo repite con el número.

   ── LO QUE LA FICHA VIEJA NO DECÍA, y son cinco ──────────────────────────────
    1. EL SALDO DE LA CUENTA QUE ABRISTE. Tocabas una fila que decía 84.300 kg y
       la pantalla siguiente mostraba treinta movimientos y ningún total: el
       número por el que entraste desaparecía.
    2. QUE LA LISTA ESTÁ CORTADA. La consulta pide 30 y había un botón al final,
       pero nada decía cuántos son en total ni hasta qué fecha alcanza lo que se
       ve. Sumar la columna Kg daba un número que no significa nada.
    3. LA DIRECCIÓN DEL KILO, en el lugar correcto. «INGRESO» y «SALIDA» eran
       dos pastillas de color en una columna propia, mientras la columna de
       kilos —que es donde importa el signo— estaba en gris para las dos.
    4. La cabecera era una barra `bg-slate-800` con un buscador blanco sobre
       gris oscuro y un botón esmeralda: la única superficie oscura del módulo,
       y aparecía justo cuando el armazón desaparecía.
    5. Y si la consulta pedía un índice, el error decía «Haga clic en el link
       azul que aparece en la consola (F12)» — un mensaje para el que programó,
       en la pantalla del que trabaja.

   ── LO QUE LA CABECERA NO DICE, Y POR QUÉ ────────────────────────────────────
   El mockup dibujaba también «Entró» y «Salió» en kilos. NO ESTÁN, y no es un
   olvido: sumar los kilos de una cuenta exige `getAggregateFromServer` con
   `sum()` —que este proyecto no exporta— más dos índices compuestos nuevos
   (`propietarioId` + `servicio` + `fecha`), y los índices de este repo no los
   crea el deploy: van a mano con `gcloud`. «Desde cuándo» cuesta otro índice
   (`propietarioId` + `fecha` ASC).
   Lo que SÍ se pudo, y por eso está: el TOTAL de movimientos, que sale de
   `getCountFromServer()` sobre el mismo `where` de la lista —una lectura
   agregada y CERO índices nuevos, porque no lleva `orderBy`— y que además es lo
   que el pie necesita para poder decir «se ven 30 de 214».
   Está anotado en §7 del runbook del módulo con lo que costaría.
   ========================================================================== */

/* ── La cabecera de la ficha ───────────────────────────────────────────────── */
.stk-ui .stk-fcab {
    background: var(--surface); border-bottom: 1px solid var(--hair);
    display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
    padding: 12px var(--gutter);
}
/* El botón de volver, con RÓTULO. Era un ícono redondo sobre la barra oscura, y
   un glifo solo no dice a dónde vuelve. */
.stk-ui .stk-fvolver {
    display: inline-flex; align-items: center; gap: 6px;
    font: inherit; font-size: 12.4px; font-weight: 600; color: var(--navy);
    background: var(--surface); border: 1px solid var(--hair-strong);
    border-radius: 8px; padding: 6px 12px; cursor: pointer; white-space: nowrap;
    transition: background .13s var(--curva), border-color .13s var(--curva);
}
.stk-ui .stk-fvolver:hover, .stk-ui .stk-fvolver:focus-visible {
    background: var(--navy-050); border-color: var(--navy-300); outline: none;
}
.stk-ui .stk-fid { min-width: 0; }
.stk-ui .stk-fid h3 {
    margin: 0; font-size: 1.02rem; font-weight: 700; letter-spacing: -.012em;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.stk-ui .stk-fid p { margin: 1px 0 0; font-size: 11.5px; color: var(--muted); }

/* Las cifras de la cabecera. Van a la derecha y en versalita chica arriba del
   número, que es el orden en que se leen: primero qué es, después cuánto. */
.stk-ui .stk-fcifras { margin-left: auto; display: flex; gap: 26px; align-items: center; }
.stk-ui .stk-fcifras .c { text-align: right; }
.stk-ui .stk-fcifras .k {
    display: block; font-size: 9.4px; font-weight: 700; letter-spacing: .11em;
    text-transform: uppercase; color: var(--faint);
}
.stk-ui .stk-fcifras .v {
    font-size: 1.14rem; font-weight: 700; font-variant-numeric: tabular-nums;
    letter-spacing: -.018em; color: var(--ink); line-height: 1.25;
}
.stk-ui .stk-fcifras .v .u { font-size: .78rem; font-weight: 600; color: var(--faint); }
/* Un saldo en descubierto es lo único de esta cabecera que dice que algo está
   mal, y el color es del DATO y no de la caja. */
.stk-ui .stk-fcifras .c.neg .v { color: var(--crit); }
/* Y ACÁ EL ANCHO SE LE PONE A LA CAJA, NO A LA PIEZA. La etapa 3 escribía
   `.stk-fcifras .v .gs-sk { width: 74px }`, o sea redeclaraba la pieza compartida
   en la hoja de un módulo — que es justo lo que el §2 de acá arriba dice que no
   se hace y lo que el candado de `ejecutar-espera.js` viene a impedir. Nadie lo
   vio porque el runbook manda correr ese banco «si tocaste tokens.css o
   core/ui.js», y la etapa 3 no tocó ninguno de los dos. */
.stk-ui .stk-fcifras .v .sk-caja { display: block; width: 74px; margin: 4px 0 3px auto; }

/* El cuerpo, que hereda la cadena de alto igual que `.stk-view`. */
.stk-ui .stk-fcuerpo {
    flex: 1; min-height: 0; display: flex; flex-direction: column;
    padding: 16px 0 0; background: var(--canvas);
}

/* ── La grilla de MOVIMIENTOS ──────────────────────────────────────────────── */
/* Es la misma grilla del §3 con otras columnas: el vocabulario ya está y no se
   inventa nada. Lo único propio es la franja, que acá dice ENTRÓ o SALIÓ.

   Y ESO SÍ ES ESTADO. Verde y rojo no son «dos categorías de movimiento»: son
   la dirección del kilo, que es lo único que un movimiento tiene de estado
   desde esta pantalla. Por eso el color viaja con el NÚMERO —que es donde el
   signo importa— y no en una pastilla de una columna aparte (manual §1.1). */
.stk-ui table.stk-m { width: 100%; border-collapse: collapse; font-size: 12.4px; table-layout: fixed; }
/* EL ALTO DE LA CABECERA VA SOBRE EL SCROLL, NO SOBRE LA TABLA, y por la misma
   razón que en el §3: el esqueleto de `gsZonaCargando()` dibuja su tabla SIN
   clase, así que `table.stk-m th` no lo alcanza y heredaba los 50 px de la
   lista de cuentas —16 más que la fila real—. `.stk-scroll.movs` es la marca
   que el contenedor de la ficha lleva para decir qué grilla va adentro. */
.stk-ui .stk-scroll.movs th { height: 34px; font-size: .58rem; padding: 7px 10px; }
.stk-ui table.stk-m td {
    padding: 7px 10px; border-bottom: 1px solid var(--hair);
    white-space: nowrap; vertical-align: middle;
    overflow: hidden; text-overflow: ellipsis;
}
.stk-ui table.stk-m tbody tr { transition: background .13s var(--curva); }
.stk-ui table.stk-m tbody tr:hover { background: var(--navy-050); }
.stk-ui table.stk-m .n { text-align: right; font-variant-numeric: tabular-nums; }
.stk-ui table.stk-m .mono {
    font-family: Consolas, "SF Mono", "Roboto Mono", monospace;
    font-weight: 700; font-size: 11.5px; color: var(--navy);
}
.stk-ui table.stk-m .doc { font-size: 11px; color: var(--faint); font-variant-numeric: tabular-nums; }
.stk-ui table.stk-m .art { color: var(--muted); }
.stk-ui table.stk-m .kg { font-variant-numeric: tabular-nums; font-weight: 700; }
.stk-ui table.stk-m td:first-child { border-left: 3px solid transparent; padding-left: 11px; }
.stk-ui .stk-scroll table.stk-m th:first-child { padding-left: 14px; }
.stk-ui table.stk-m tr.ent td:first-child { border-left-color: var(--ok); }
.stk-ui table.stk-m tr.sal td:first-child { border-left-color: var(--crit); }
.stk-ui table.stk-m tr.ent .kg { color: var(--ok); }
.stk-ui table.stk-m tr.sal .kg { color: var(--crit); }
/* Un movimiento anulado no es una tercera dirección: es uno que ya no cuenta.
   Se apaga entero en vez de ganar un color propio. */
.stk-ui table.stk-m tr.anu td { color: var(--faint); }
.stk-ui table.stk-m tr.anu .kg { color: var(--faint); text-decoration: line-through; }
.stk-ui table.stk-m tr.anu td:first-child { border-left-color: var(--hair-strong); }

/* ── A 640 px ─────────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
    .stk-ui .stk-fcab { padding: 10px 12px; gap: 10px; }
    /* Las cifras pasan abajo y ocupan el ancho: en la cabecera, apretadas contra
       el nombre, se leían como parte del título. */
    .stk-ui .stk-fcifras { margin-left: 0; width: 100%; gap: 18px; justify-content: flex-start; }
    .stk-ui .stk-fcifras .c { text-align: left; }
}


/* =============================================================================
   5. DÓNDE ESTÁ — los depósitos y el diálogo de composición (ETAPA 4)
   =============================================================================
   Es la segunda de las tres preguntas: el físico REAL contado de los lotes
   activos, depósito por depósito y artículo por artículo. La sección de al lado
   dice a quién se le deben los kilos; ésta dice dónde están.

   ── LAS SIETE COSAS QUE ESTA SECCIÓN NO DECÍA ────────────────────────────────
    1. QUE EL DRILL-DOWN AL LOTE NO EXISTÍA. Cada fila del diálogo de composición
       llevaba `cursor-pointer`, subrayado al pasar y `title="Ver ficha del
       lote"`, y llamaba a `window.lotesAzucarVerLote`, QUE NO LA REGISTRA NADIE
       EN TODO EL REPO. O sea: siete filas que se ven clickeables y no hacen
       nada, siempre, sin un error en consola. La ficha de un lote de azúcar se
       abre con `navigateTo('lotes-azucar')` + `renderLotesAzucar()` +
       `abrirFichaLote(id)` —es lo que hace `mwdLote()` en Movimientos— y así
       está hecha ahora. (Familia «un botón mudo que se ve igual que uno vivo».)
    2. QUE PARTE DE ESOS KILOS NO PUEDE SALIR. `lotesDetalle` trae
       `estadoCalidad` desde siempre y la pantalla no lo mostraba en ninguna
       parte: un lote en CUARENTENA o RECHAZADO —los dos de CALIDAD_BLOQUEANTES—
       se listaba igual que uno aprobado. Y el candado que debería frenarlo en el
       servicio está COMENTADO (lotes-azucar-service.js, en el descuento de
       lotes), así que hoy lo único que puede avisar es la pantalla. Un número
       que no puede ser exacto tiene que decir de qué está hecho (manual §1.4).
    3. DE DÓNDE SALEN LOS BULTOS. La sección de al lado declara «Bolsas de 50 kg
       / estimadas» desde la etapa 2, porque las bolsas de una CUENTA no existen
       como dato. Acá pasa lo contrario y tampoco se decía: los bultos se CUENTAN
       de los lotes. Dos aritméticas para la misma palabra en la misma pantalla,
       y ahora las dos dicen cuál es la suya — por eso además se llaman distinto:
       allá «bolsas» (estimadas), acá «bultos» (contados).
    4. QUÉ ERA EL NÚMERO GRIS ENTRE PARÉNTESIS. El «(3)» al lado del artículo
       eran los lotes que lo componen, sin rótulo. Hoy es una columna con su
       nombre.
    5. UN LOTE SIN DEPÓSITO SE DIBUJABA COMO UN GALPÓN MÁS. El servicio agrupa lo
       que no tiene depositoId bajo la clave `sin_deposito`, y como el nombre cae
       al id, la pantalla mostraba una tarjeta titulada «sin_deposito». Un lote
       que no sabe dónde está es EXACTAMENTE lo que esta sección tiene que
       señalar, no un depósito más de la grilla.
    6. SOBRE QUÉ BUSCA. No había buscador: la pregunta «dónde está el
       impalpable» se contestaba leyendo las seis tarjetas una por una. Y un
       buscador sin su ámbito escrito al lado es el que hizo que en la sección de
       cuentas «no se encontraron resultados» se leyera como «no existe».
    7. DE DÓNDE SALE EL NÚMERO. No había pie. Los kilos de acá son otra cosa que
       los de la sección de al lado —físico contado contra saldo comercial— y
       nada lo decía.

   ── LOS COLORES QUE MUEREN ACÁ ───────────────────────────────────────────────
   La cabecera `bg-slate-800` de cada tarjeta —seis superficies oscuras en una
   pantalla-tabla de consulta, y la ficha ya había perdido la suya en la etapa
   3—, el esmeralda del total, el ámbar de los kilos, el índigo del código de
   lote, el rosa de la caja de posiciones, y el mapa de CINCO familias del origen
   del lote (verde INGRESO, azul PRODUCCION, ámbar ESTIBA, cian TRASLADO, gris
   INVENTARIO_INICIAL), que era color = categoría en su forma más pura: cinco
   colores para cinco palabras que no son estados de nada. El origen del lote es
   un DATO y va como dato, en gris, debajo del código.
   Lo único que queda con color es lo que la etapa compró: ámbar el lote que pide
   algo (pendiente de análisis, en cuarentena, sin depósito) y rojo el rechazado.
   ========================================================================== */

/* ── La grilla de tarjetas ─────────────────────────────────────────────────── */
/* Dos columnas mientras entren y una cuando no. `auto-fill` con un mínimo, y no
   un `lg:grid-cols-2` fijo: con tres depósitos y una pantalla de 1366 —el caso
   apretado que la ronda midió— dos columnas de 380 px entran y tres no. */
.stk-ui .stk-deps {
    display: grid; gap: 14px;
    grid-template-columns: repeat(auto-fill, minmax(380px, 1fr));
    padding: var(--gutter) var(--gutter) 18px;
    align-items: start;
}

.stk-ui .stk-dep {
    border: 1px solid var(--hair); border-radius: 12px;
    background: var(--surface); overflow: hidden;
}

/* La cabecera de la tarjeta. CLARA: acá vivían las seis superficies oscuras del
   módulo, cada una con su total en esmeralda. Una pantalla-tabla de consulta no
   tiene ninguna superficie llena que no sea el botón primario de la barra del
   armazón (manual §1.2). */
.stk-ui .stk-dep-h {
    display: flex; align-items: center; gap: 9px;
    padding: 10px 13px; border-bottom: 1px solid var(--hair);
    background: #fafbfd;
}
.stk-ui .stk-dep-h .material-symbols-outlined { font-size: 18px; color: var(--navy-300); }
.stk-ui .stk-dep-h .nm {
    font-size: 13px; font-weight: 700; color: var(--ink); min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.stk-ui .stk-dep-h .tot {
    margin-left: auto; font-size: 11.5px; color: var(--muted); white-space: nowrap;
    font-variant-numeric: tabular-nums;
}
.stk-ui .stk-dep-h .tot b { color: var(--ink); font-weight: 700; }

/* EL DEPÓSITO QUE NO ES UN DEPÓSITO. El servicio junta bajo `sin_deposito` todo
   lote sin depositoId, y el nombre cae al id: la pantalla mostraba una tarjeta
   que decía «sin_deposito» entre las demás. No es un galpón, es un pendiente, y
   ámbar es el color de lo que pide algo (manual §1.1). */
.stk-ui .stk-dep.huerfano { border-color: var(--warn-hair); }
.stk-ui .stk-dep.huerfano .stk-dep-h { background: var(--warn-050); }
.stk-ui .stk-dep.huerfano .stk-dep-h .material-symbols-outlined,
.stk-ui .stk-dep.huerfano .stk-dep-h .nm { color: var(--warn); }
.stk-ui .stk-dep .aviso {
    padding: 8px 13px; font-size: 11.5px; color: var(--warn);
    background: var(--warn-050); border-bottom: 1px solid var(--warn-hair);
}

/* EL DEPÓSITO QUE ES DE OTRO (25/08). El galpón de un distribuidor, con el tilde
   «externo» del ABM: lo que hay ahí ya se despachó y NO es stock propio, así
   que no suma al físico ni al cuadre. Se dibuja igual —hay que poder ver qué
   hay allá— pero al final de la grilla y en navy tenue, que es categoría y no
   estado: no pide nada, sólo es de otro. */
.stk-ui .stk-dep.tercero { border-color: #cfdcf1; }
.stk-ui .stk-dep.tercero .stk-dep-h { background: var(--navy-050); }
.stk-ui .stk-dep.tercero .stk-dep-h .material-symbols-outlined,
.stk-ui .stk-dep.tercero .stk-dep-h .nm { color: var(--navy-500); }
.stk-ui .stk-dep.tercero .aviso {
    color: var(--navy-500); background: var(--navy-050); border-bottom-color: #cfdcf1;
}

/* ── La tabla de artículos ─────────────────────────────────────────────────── */
/* Mismo vocabulario que la grilla del §3 con otras columnas: no nace nada nuevo.
   Los anchos van acá y en ningún otro lado. */
.stk-ui table.stk-d { width: 100%; border-collapse: collapse; font-size: 12.4px; table-layout: fixed; }
.stk-ui table.stk-d th {
    text-align: left; font-size: .55rem; font-weight: 700; letter-spacing: .09em;
    text-transform: uppercase; color: var(--faint);
    padding: 6px 9px; border-bottom: 1px solid var(--hair);
    white-space: nowrap; vertical-align: bottom;
}
.stk-ui table.stk-d th:nth-child(1) { width: 44%; }
.stk-ui table.stk-d th:nth-child(2) { width: 13%; }
.stk-ui table.stk-d th:nth-child(3) { width: 19%; }
.stk-ui table.stk-d th:nth-child(4) { width: 18%; }
.stk-ui table.stk-d th:nth-child(5) { width: 6%; }
/* La columna de bultos DICE que se cuentan, igual que la de la sección de al
   lado dice que estima. La bajada va en el encabezado y no en un `title`. */
.stk-ui table.stk-d th .sub {
    display: block; font-size: .52rem; font-weight: 600; letter-spacing: .04em;
    text-transform: none; color: var(--faint);
}
.stk-ui table.stk-d td {
    padding: 6px 9px; border-bottom: 1px solid var(--hair);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.stk-ui table.stk-d tbody tr:last-child td { border-bottom: 0; }
.stk-ui table.stk-d tbody tr { transition: background .13s var(--curva); cursor: pointer; }
.stk-ui table.stk-d tbody tr:hover { background: var(--navy-050); }
.stk-ui table.stk-d tbody tr:focus-visible {
    outline: 2px solid var(--navy-300); outline-offset: -2px; background: var(--navy-050);
}
.stk-ui table.stk-d .n { text-align: right; font-variant-numeric: tabular-nums; }
.stk-ui table.stk-d .c { text-align: center; }
.stk-ui table.stk-d .art { white-space: normal; overflow-wrap: anywhere; font-weight: 600; }
.stk-ui table.stk-d .kg { font-weight: 700; }
/* La nota de la fila: cuántos de esos kilos no pueden salir. Va debajo del
   nombre del artículo, que es donde se lee el número que la nota corrige. */
.stk-ui table.stk-d td .sub {
    display: block; font-size: 10.4px; font-weight: 400; color: var(--warn); margin-top: 1px;
}
.stk-ui table.stk-d td:first-child { border-left: 3px solid transparent; padding-left: 10px; }
/* Un artículo con lotes que no pueden salir. La franja es del DATO, no de la
   fila: la fila se queda blanca como todas (§3). */
.stk-ui table.stk-d tr.trabado td:first-child { border-left-color: var(--warn); }
.stk-ui table.stk-d .chev {
    font-size: 15px; color: var(--hair-strong);
    transition: transform .13s var(--curva), color .13s var(--curva);
}
.stk-ui table.stk-d tbody tr:hover .chev { color: var(--navy-300); transform: translateX(2px); }

/* ── LA TABLA DE «PRODUCTO TERMINADO» (15/09/2026) ─────────────────────────── */
/* La MISMA tabla de artículos de las tarjetas de arriba, sin la tarjeta: una
   sola, de borde a borde, con el gutter de la grilla. La fila confiesa debajo
   del nombre en qué depósitos está —en gris, es un dato— y lo que no puede
   salir o todavía no se vende —en ámbar, pide algo—. */
.stk-ui .stk-pt { padding: 0 var(--gutter) 18px; }
.stk-ui .stk-pt table.stk-d { font-size: 12.8px; }
.stk-ui .stk-pt table.stk-d td { padding: 8px 9px; }
.stk-ui table.stk-d td .sub.dep { color: var(--faint); white-space: normal; }
.stk-ui table.stk-d td .sub.dep b { color: var(--muted); font-weight: 600; }
.stk-ui table.stk-d td .sub.abierto { color: var(--navy-500); }
.stk-ui .stk-pie .tot { margin-left: 8px; }
.stk-ui table.stk-l .sub.abierto { color: var(--navy-500); }

/* ── EL DIÁLOGO ────────────────────────────────────────────────────────────── */
/* Portado de `ord-ui.css` §3, que es de donde salió la cabecera lite de este
   módulo. NO NACE UN VOCABULARIO NUEVO: el velo, el panel, la cabecera navy y
   el pie de una sola cosa son los mismos, y la ETAPA 5 los va a reusar para los
   dos diálogos de la playa en vez de escribir otros.

   EL VELO CUELGA DEL BODY —un diálogo adentro del área de trabajo se recorta
   contra su `overflow`— así que lleva el scope EN SU PROPIO ELEMENTO y escrito
   COMO COMPUESTO: `.stk-ui.stk-velo`, sin espacio. Con espacio no matchea nada,
   el diálogo sale sin velo, sin ancho y sin sombra, y NINGUNA aserción sobre el
   marcado se cae. Y por eso mismo hay que devolverle el `.hidden`: dos clases
   (0,2,0) contra una (0,1,0).

   Y SE LLAMA `.stk-dlg` Y NO `.stk-panel`: `.stk-panel` ya es el panel de una de
   las tres secciones, y lleva su propio `display` con el candado del `.hidden`.
   Dos cosas distintas con el mismo nombre adentro del mismo scope es el choque
   que se paga tres etapas después. */
.stk-ui.stk-velo {
    position: fixed; inset: 0; z-index: 200;
    background: rgba(15, 23, 42, .55);
    backdrop-filter: blur(2px);
    display: flex; align-items: center; justify-content: center;
    padding: 22px;
}
.stk-ui.stk-velo.hidden { display: none; }

.stk-ui .stk-dlg {
    background: var(--surface); border-radius: var(--r-card);
    box-shadow: var(--e3);
    width: min(920px, 100%); max-height: min(88vh, 760px);
    display: flex; flex-direction: column; min-height: 0; overflow: hidden;
}

/* La cabecera. Navy plena, y es la ÚNICA superficie llena del diálogo: el pie es
   claro y adentro no hay ninguna otra. Acá había una `bg-slate-800`. */
.stk-ui .stk-dlg-h {
    background: var(--navy); color: #fff;
    padding: 13px 20px; display: flex; align-items: center; gap: 14px;
}
.stk-ui .stk-dlg-h .id { min-width: 0; }
.stk-ui .stk-dlg-h .lb {
    font-size: .58rem; font-weight: 700; letter-spacing: .13em; text-transform: uppercase;
    color: #9fc0ee;
}
.stk-ui .stk-dlg-h h4 {
    margin: 1px 0 0; font-size: 1.02rem; font-weight: 700; letter-spacing: -.012em;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.stk-ui .stk-dlg-h .dep {
    display: flex; align-items: center; gap: 5px;
    margin-top: 2px; font-size: 11.5px; color: #b9cef0;
}
.stk-ui .stk-dlg-h .dep .material-symbols-outlined { font-size: 15px; }
.stk-ui .stk-dlg-h .sp { flex: 1; }
.stk-ui .stk-dlg-h .cerrar {
    background: transparent; border: 0; color: rgba(255, 255, 255, .75);
    cursor: pointer; border-radius: 8px; padding: 4px; line-height: 0;
}
.stk-ui .stk-dlg-h .cerrar:hover, .stk-ui .stk-dlg-h .cerrar:focus-visible {
    background: rgba(255, 255, 255, .14); color: #fff; outline: none;
}

.stk-ui .stk-dlg-b { flex: 1; min-height: 0; overflow: auto; }

/* El pie: el recuento a la izquierda, el total a la derecha, y UNA sola cosa que
   apretar. */
.stk-ui .stk-dlg-f {
    border-top: 1px solid var(--hair); background: #fafbfd;
    padding: 10px 20px; display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
    font-size: 11.5px; color: var(--faint);
}
.stk-ui .stk-dlg-f .sp { flex: 1; }
.stk-ui .stk-dlg-f .tot {
    font-variant-numeric: tabular-nums; font-size: 12.6px; font-weight: 700; color: var(--ink);
}
.stk-ui .stk-dlg-f .trabado { color: var(--warn); font-weight: 600; }
/* LA REGLA DEL TITULAR VA EN SU PROPIO RENGLON. Es la frase mas larga del pie y
   arrastrada por el `flex-wrap` empujaba al total y al boton abajo con ella: el
   pie quedaba con el recuento arriba y el total mezclado con la explicacion. */
.stk-ui .stk-dlg-f .nota { flex: 1 0 100%; order: 1; margin-top: 1px; }
.stk-ui .stk-btn {
    font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer;
    border-radius: 9px; padding: 7px 16px;
    background: var(--surface); color: var(--navy); border: 1px solid var(--hair-strong);
    transition: background .13s var(--curva), border-color .13s var(--curva);
}
.stk-ui .stk-btn:hover, .stk-ui .stk-btn:focus-visible {
    background: var(--navy-050); border-color: var(--navy-300); outline: none;
}

/* ── Los carteles que contienen este artículo ──────────────────────────────── */
/* Es el puente con la tercera pregunta: parte de estos kilos ya está arriba de un
   camión. Era una caja rosa con su título en versalita rosa; hoy es un renglón
   con las pastillas del sistema —verde lo cumplido, ámbar lo que todavía pide
   algo— que es el mismo vocabulario que usa la playa. */
.stk-ui .stk-pos {
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
    padding: 11px var(--gutter); border-bottom: 1px solid var(--hair);
    font-size: 11.5px; color: var(--muted);
}
.stk-ui .stk-pos .k {
    font-size: 9.6px; font-weight: 700; letter-spacing: .11em;
    text-transform: uppercase; color: var(--faint); margin-right: 2px;
}
.stk-ui .stk-pos .stk-b { font-variant-numeric: tabular-nums; }
.stk-ui .stk-pos .stk-b b { font-weight: 700; }

/* ── La tabla de lotes ─────────────────────────────────────────────────────── */
/* EL `min-width` NO ES DECORATIVO: sin el, a 390 px las siete columnas se
   reparten 55 px cada una y la tabla se ve completa mientras muestra tres letras
   por celda — una caja que se encoge mide bien y miente. Con el, la zona
   scrollea de costado y las celdas conservan su ancho.
   Y va sobre la TABLA y no sobre un envoltorio propio: el envoltorio se
   convertiria en el contenedor de scroll y el `position: sticky` de la cabecera
   dejaria de tener contra que pegarse. */
.stk-ui table.stk-l {
    width: 100%; min-width: 700px; border-collapse: collapse;
    font-size: 12.3px; table-layout: fixed;
}
.stk-ui table.stk-l th {
    position: sticky; top: 0; z-index: 1;
    text-align: left; font-size: .55rem; font-weight: 700; letter-spacing: .09em;
    text-transform: uppercase; color: var(--faint); background: var(--surface);
    padding: 8px 10px; border-bottom: 1px solid var(--hair-strong); white-space: nowrap;
}
.stk-ui table.stk-l th:nth-child(1) { width: 26%; }
.stk-ui table.stk-l th:nth-child(2) { width: 12%; }
.stk-ui table.stk-l th:nth-child(3) { width: 11%; }
.stk-ui table.stk-l th:nth-child(4) { width: 19%; }
.stk-ui table.stk-l th:nth-child(5) { width: 12%; }
.stk-ui table.stk-l th:nth-child(6) { width: 9%; }
.stk-ui table.stk-l th:nth-child(7) { width: 11%; }
.stk-ui table.stk-l td {
    padding: 7px 10px; border-bottom: 1px solid var(--hair);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; vertical-align: middle;
}
.stk-ui table.stk-l tbody tr { transition: background .13s var(--curva); }
.stk-ui table.stk-l .n { text-align: right; font-variant-numeric: tabular-nums; }
.stk-ui table.stk-l .kg { font-weight: 700; font-variant-numeric: tabular-nums; }
.stk-ui table.stk-l .sub {
    display: block; font-size: 10.4px; font-weight: 400; color: var(--faint);
    letter-spacing: .02em;
}
/* Lo que no está y lo que es NORMAL se dicen igual: en gris y sin pastilla. Un
   lote aprobado no lleva marca de color —lo normal no se marca— pero sí lleva
   palabra, porque una columna vacía en la mitad de las filas se lee como «no se
   sabe», que es otra cosa. */
.stk-ui table.stk-l .dim { color: var(--faint); }
.stk-ui table.stk-l td:first-child { border-left: 3px solid transparent; padding-left: 19px; }
.stk-ui table.stk-l th:first-child { padding-left: 22px; }
.stk-ui table.stk-l th:last-child, .stk-ui table.stk-l td:last-child { padding-right: 22px; }

/* EL CÓDIGO DEL LOTE ES UN ENLACE, y ahora lleva a algún lado. Era la fila
   ENTERA la que se veía clickeable —cursor, subrayado y un `title`— llamando a
   una función que no existe en ningún archivo del repo. Hoy el control es el
   código y nada más: si la puerta es una sola, se marca una sola. */
.stk-ui table.stk-l .lote {
    font: inherit; font-family: Consolas, "SF Mono", "Roboto Mono", monospace;
    font-size: 11.4px; font-weight: 700; color: var(--navy);
    background: none; border: 0; padding: 0; cursor: pointer; text-align: left;
    max-width: 100%; overflow: hidden; text-overflow: ellipsis;
}
.stk-ui table.stk-l .lote:hover, .stk-ui table.stk-l .lote:focus-visible {
    text-decoration: underline; outline: none; color: var(--navy-500);
}

/* LA CALIDAD, que es lo que no se decía. Los dos estados de CALIDAD_BLOQUEANTES
   —cuarentena y rechazado— son kilos que NO pueden salir; pendiente todavía no
   se analizó. El aprobado no dice nada: lo normal no lleva marca (manual §1.1). */
.stk-ui table.stk-l tr.cal-wrn td:first-child { border-left-color: var(--warn); }
.stk-ui table.stk-l tr.cal-neg td:first-child { border-left-color: var(--crit); }
.stk-ui table.stk-l tr.cal-neg .kg { color: var(--crit); }

.stk-ui .stk-dlg .stk-vacio { padding: 34px 22px; }

/* ── A 780 px y a 640 ─────────────────────────────────────────────────────── */
/* El diálogo pierde el margen: en una pantalla de 390 px, 22 px de velo a cada
   lado son 44 px que le faltan al contenido. */
@media (max-width: 780px) {
    .stk-ui.stk-velo { padding: 0; }
    .stk-ui .stk-dlg { max-height: 100vh; height: 100%; border-radius: 0; }
    /* La franja acompaña a la tabla cuando el cuerpo scrollea de costado: si se
       quedara al ancho de la pantalla, al correr la tabla la franja se
       despegaría y quedaría un hueco al lado. */
    .stk-ui .stk-pos { min-width: 700px; }
}
@media (max-width: 640px) {
    .stk-ui .stk-deps { grid-template-columns: 1fr; padding: 12px 12px 14px; gap: 12px; }
    .stk-ui .stk-pos { padding: 10px 12px; }
    .stk-ui table.stk-l td:first-child { padding-left: 11px; }
    .stk-ui table.stk-l th:first-child { padding-left: 14px; }
    .stk-ui table.stk-l th:last-child, .stk-ui table.stk-l td:last-child { padding-right: 14px; }
}


/* =============================================================================
   6. EN LA PLAYA — los carteles y sus dos diálogos (ETAPA 5)
   =============================================================================
   Ronda de dos mockups cerrada el 24/08/2026: ganó la **A**, «el tablero de
   camiones» —los carteles ocupan la pantalla y lo que está en el piso sin
   ubicar es trabajo pendiente, no una tarjeta más—, y con una instrucción que
   cambia de dónde sale el vocabulario:

   ── EL VOCABULARIO SE PORTA DE PRODUCCIÓN DEL DÍA, NO SE INVENTA ─────────────
   `produccion-dia-ui.css` §5 y §6 ya dibujan ESTE MISMO OBJETO —un cartel de la
   playa con su camión a medio armar— y están en producción hace semanas. Las dos
   pantallas miran los mismos `posiciones_deposito`: Producción del Día declara
   lo que produjo y lo pone en un cartel, y Stock General mira lo que hay arriba
   y lo mueve. Que se vieran distinto era el defecto, no la variedad.

   Se porta LITERAL: el filete de 3 px que dice el estado, la banda rellena verde
   de la posición completa, el número grande a la izquierda, la miniatura del
   artículo, la cifra de kg sobre el objetivo, la barra y la nota que explica en
   una línea qué le pasa a ese camión. Los nombres de clase se mantienen (`.pn`,
   `.st`, `.cuerpo`, `.art`, `.lote`, `.kg`, `.nota`) para que las dos hojas se
   puedan leer una al lado de la otra.

   ── LAS TRES COSAS QUE ACÁ SON DISTINTAS, Y POR QUÉ ──────────────────────────
    1. **LA BARRA TIENE UN SOLO TRAMO.** La de Producción del Día tiene dos —lo
       que quedó de días anteriores y lo que entró hoy— porque ahí existe un
       TURNO que parte el día en dos. Acá no hay turno: Stock General mira la
       playa entera, cualquier día, y «hoy» no significa nada. Dibujar dos
       tramos con los dos del mismo color sería una barra que promete una
       distinción que no puede hacer.
    2. **LA TARJETA NO ES UN BOTÓN.** En Producción del Día la tarjeta entera se
       toca y abre un modal. Acá la tarjeta CONTIENE controles —sacar un lote del
       cartel es un botón por lote— y un `<button>` adentro de otro no es HTML
       válido: el navegador lo desanida y el clic de adentro deja de existir. Por
       eso acá es un `<article>` y lo que se toca es cada cosa.
       Y es lo que la propuesta A vino a comprar: hasta hoy sacar un lote era una
       crucecita con `opacity-0` que aparecía al pasar el mouse — invisible con
       el teclado, imposible en la tablet donde se opera la playa, y **la única
       operación destructiva de la pantalla**.
    3. **EL CARTEL DICE SI PUEDE SALIR.** Es lo que destapó la etapa 4: un lote
       en CUARENTENA o RECHAZADO no es despachable, y el candado que debería
       frenarlo en el servicio está comentado. Un camión lleno de azúcar trabada
       está lleno y no es un camión listo, así que pierde la banda verde y lo
       dice con palabras.
   ========================================================================== */

/* ── La barra de la sección: el alcance y las dos vistas ───────────────────── */
/* El segmento es de Producción del Día (`.pd-seg`) y contesta la misma pregunta
   que allá: la playa tiene DOS vistas y un total que no se explica termina
   discrepando con el otro. Acá son «En armado» —los carteles con algo adentro,
   que es lo que la pantalla mostraba y lo único que se puede despachar— y «Toda
   la playa», que suma los vacíos, que son los DESTINOS posibles.

   El activo va por tinte y sombra, no por relleno navy: la única superficie
   navy rellena del módulo es el botón principal de la barra del armazón. */
.stk-ui .stk-seg {
    display: inline-flex; background: var(--surface);
    border: 1px solid var(--hair-strong); border-radius: 10px; padding: 2px;
    margin-left: auto;
}
.stk-ui .stk-seg button {
    padding: 4px 12px; font: inherit; font-size: 12px; font-weight: 600;
    border: 0; background: none; border-radius: 8px; color: var(--muted); cursor: pointer;
    transition: background .15s var(--curva), color .15s var(--curva);
}
.stk-ui .stk-seg button:hover { background: var(--navy-050); }
.stk-ui .stk-seg button.on {
    background: var(--navy-050); color: var(--navy);
    box-shadow: 0 1px 2px rgba(16, 32, 64, .10);
}
.stk-ui .stk-seg button:focus-visible { outline: 2px solid var(--navy-300); outline-offset: 1px; }
.stk-ui .stk-seg button .n { font-variant-numeric: tabular-nums; opacity: .7; margin-left: 4px; }

/* ── La grilla ─────────────────────────────────────────────────────────────── */
.stk-ui .stk-posgrid {
    display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px;
    padding: 0 var(--gutter) 18px; align-items: start;
}
.stk-ui .stk-posgrid > * { min-width: 0; }

/* ── La tarjeta de un cartel ───────────────────────────────────────────────── */
/* EL FILETE SUPERIOR DICE EL ESTADO, no la categoría (manual §1.1). Acá vivía
   una cabecera pintada ENTERA de verde o de ámbar según el estado, que es la
   caja diciendo «soy verde» en vez de decir qué le pasa al camión. */
.stk-ui .stk-pcard {
    background: var(--surface); border: 1px solid var(--hair);
    border-top: 3px solid var(--hair-strong);
    border-radius: var(--r-card); box-shadow: var(--shadow);
    padding: 14px 16px 13px; display: flex; flex-direction: column; gap: 8px;
    min-width: 0; text-align: left;
}
.stk-ui .stk-pcard.ok   { border-top-color: var(--ok); }
.stk-ui .stk-pcard.ab   { border-top-color: var(--navy-300); }
.stk-ui .stk-pcard.trab { border-top-color: var(--crit); }
.stk-ui .stk-pcard.vacia { opacity: .72; }

.stk-ui .stk-pcard .fila1 { display: flex; align-items: center; gap: 10px; }

/* LA POSICIÓN COMPLETA SE VE DE LEJOS, y la banda rellena es del ESTADO y no de
   una categoría: ninguna otra tarjeta se tiñe por lo que ES, sólo por cómo está.
   Blanco sobre `--ok` da 5,4 : 1, que pasa AA. (Portado literal de
   `produccion-dia-ui.css` §6, incluidos los márgenes negativos que la sacan del
   padding de la tarjeta.)
   Y UN CAMIÓN TRABADO NO LA LLEVA aunque esté al 100 %: lleno no es listo. */
.stk-ui .stk-pcard.ok .fila1 {
    margin: -14px -16px 0; padding: 11px 16px;
    background: var(--ok); border-radius: 11px 11px 0 0;
}
.stk-ui .stk-pcard.ok .fila1 .pn { color: #fff; }
.stk-ui .stk-pcard.ok .fila1 .st { color: #fff; opacity: .92; }
.stk-ui .stk-pcard.ok .fila1 .stk-b {
    background: rgba(255, 255, 255, .16); border-color: rgba(255, 255, 255, .38); color: #fff;
}
.stk-ui .stk-pcard .pn {
    font-size: 24px; font-weight: 700; letter-spacing: -.02em;
    color: var(--navy); line-height: 1;
}
.stk-ui .stk-pcard .st {
    font-size: 10px; font-weight: 700; text-transform: uppercase;
    letter-spacing: .07em; margin-left: auto; color: var(--faint); white-space: nowrap;
}
.stk-ui .stk-pcard .st.ok   { color: var(--ok); }
.stk-ui .stk-pcard .st.ab   { color: var(--navy-500); }
.stk-ui .stk-pcard .st.trab { color: var(--crit); }
.stk-ui .stk-pcard .lock { color: var(--navy-500); font-size: 15px; }

.stk-ui .stk-pcard .cuerpo { display: flex; gap: 12px; align-items: flex-start; }
.stk-ui .stk-pcard .cuerpo img,
.stk-ui .stk-pcard .cuerpo .noimg {
    width: 52px; height: 52px; flex: none; object-fit: contain;
    border-radius: 10px; border: 1px solid var(--hair); background: var(--surface);
}
.stk-ui .stk-pcard .cuerpo .noimg {
    display: flex; align-items: center; justify-content: center; color: var(--hair-strong);
}
.stk-ui .stk-pcard .cuerpo .id { min-width: 0; flex: 1; }
.stk-ui .stk-pcard .art  { font-size: 14px; font-weight: 700; line-height: 1.25; }
.stk-ui .stk-pcard .lote { font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.stk-ui .stk-pcard .kg   {
    font-size: 19px; font-weight: 700; letter-spacing: -.02em; line-height: 1.1;
    margin-top: 2px; font-variant-numeric: tabular-nums;
}
.stk-ui .stk-pcard .kg small { font-size: 11.5px; font-weight: 600; color: var(--muted); }
.stk-ui .stk-pcard .nota { font-size: 11px; color: var(--muted); line-height: 1.35; }
.stk-ui .stk-pcard .nota.warn { color: var(--warn); font-weight: 600; }
.stk-ui .stk-pcard .nota.crit { color: var(--crit); font-weight: 600; }
.stk-ui .stk-pcard .nota.nav  { color: var(--navy-500); font-weight: 600; }

/* LA BARRA, DE UN SOLO TRAMO. La de Producción del Día tiene dos porque allá hay
   un TURNO que parte el día; acá no hay turno y «hoy» no significa nada. Misma
   geometría para que las dos pantallas se lean igual. */
.stk-ui .stk-barra {
    height: 12px; border-radius: 6px; background: var(--canvas);
    border: 1px solid var(--hair); overflow: hidden; display: flex;
}
.stk-ui .stk-barra i { display: block; background: var(--navy); }
.stk-ui .stk-pcard.ok   .stk-barra i { background: var(--ok); }
.stk-ui .stk-pcard.trab .stk-barra i { background: var(--crit); }

/* ── LO QUE ACÁ SE AGREGA: los lotes de adentro, con su salida ─────────────── */
/* Producción del Día resume («2 lotes · 10x12») porque desde ahí no se saca
   ninguno. Acá sí, así que cada uno se nombra y lleva su botón — VISIBLE, no un
   `opacity-0` que aparece al pasar el mouse. */
.stk-ui .stk-pcard .lotes {
    list-style: none; margin: 0; padding: 8px 0 0;
    border-top: 1px solid var(--hair); display: flex; flex-direction: column; gap: 2px;
}
.stk-ui .stk-pcard .lotes li { display: flex; align-items: center; gap: 8px; }
.stk-ui .stk-pcard .lotes .cod {
    font-family: Consolas, "SF Mono", "Roboto Mono", monospace;
    font-size: 11.2px; font-weight: 700; color: var(--navy);
    flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.stk-ui .stk-pcard .lotes .lkg {
    font-size: 11.6px; font-weight: 700; color: var(--muted);
    font-variant-numeric: tabular-nums; white-space: nowrap;
}
.stk-ui .stk-pcard .lotes .marca { font-size: 14px; flex: 0 0 auto; }
.stk-ui .stk-pcard .lotes .marca.wrn { color: var(--warn); }
.stk-ui .stk-pcard .lotes .marca.neg { color: var(--crit); }
.stk-ui .stk-pcard .lotes .quitar {
    font: inherit; font-size: 10.6px; font-weight: 600; color: var(--muted);
    background: var(--surface); border: 1px solid var(--hair-strong);
    border-radius: 7px; padding: 2px 9px; cursor: pointer; white-space: nowrap; flex: 0 0 auto;
    transition: color .13s var(--curva), border-color .13s var(--curva), background .13s var(--curva);
}
.stk-ui .stk-pcard .lotes .quitar:hover,
.stk-ui .stk-pcard .lotes .quitar:focus-visible {
    color: var(--crit); border-color: var(--crit-hair); background: var(--crit-050); outline: none;
}

/* ── La tarjeta-aviso: lo que está en el piso y no tiene cartel ────────────── */
/* Va PRIMERA en la grilla, que es lo que hace Producción del Día con lo mismo:
   de toda la banda, es lo único que le pide algo a alguien. Con cero lotes no se
   dibuja — un aviso que dice «0 sin ubicar» ocupa el mismo lugar que uno que
   dice 3 y entrena a no mirarlo. */
.stk-ui .stk-pcard.aviso {
    border: 1px solid var(--warn-hair); border-top: 3px solid var(--warn);
    background: var(--warn-050); gap: 5px;
}
.stk-ui .stk-pcard.aviso .t { font-size: 13px; font-weight: 700; color: var(--warn); }
.stk-ui .stk-pcard.aviso .d { font-size: 12px; color: var(--warn); line-height: 1.4; }
.stk-ui .stk-pcard.aviso .ubicar {
    font: inherit; font-size: 12px; font-weight: 700; color: var(--warn);
    background: none; border: 0; padding: 0; cursor: pointer; text-align: left;
    align-self: flex-start; margin-top: 2px;
}
.stk-ui .stk-pcard.aviso .ubicar:hover,
.stk-ui .stk-pcard.aviso .ubicar:focus-visible { text-decoration: underline; outline: none; }

/* ── La tarjeta-dato: lo que está en un depósito sin posiciones ─────────── */
/* SE LLAMA `.info` Y NO `.nota` A PROPÓSITO: `.stk-pcard .nota` ya existe
   ADENTRO de un cartel —es el renglón que explica qué le pasa a ese camión— y
   dos clases con el mismo nombre en el mismo scope se pisan sin avisar. */
/* MISMA SILUETA QUE EL AVISO Y NINGÚN COLOR DE ESTADO, y esa es toda la
   diferencia. Sólo Azucel 1 trabaja por carteles; lo que está en Azucel 2, en
   Azucel 4 o en Polvos no tiene ni le falta una posición. Hasta el 24/08 estos
   lotes caían en el ámbar de arriba y lo inflaban —«18 SIN UBICAR» sobre una
   playa donde quince de ellos no tenían adónde ir—, o sea que el aviso pedía
   algo imposible. No lleva verbo porque no hay nada que hacer acá. */
.stk-ui .stk-pcard.info {
    border: 1px solid var(--hair-strong); border-top: 3px solid var(--hair-strong);
    background: var(--canvas); gap: 5px;
}
.stk-ui .stk-pcard.info .t { font-size: 13px; font-weight: 700; color: var(--muted); }
.stk-ui .stk-pcard.info .d { font-size: 12px; color: var(--faint); line-height: 1.4; }
.stk-ui .stk-pcard.info .d b { color: var(--muted); font-weight: 700; }

/* ── El vacío de la sección ────────────────────────────────────────────────── */
/* Y VA SOBRE `.stk-ui`, NO SOBRE `.stk-posgrid`: el camino del ERROR escribe su
   aviso directo en el contenedor, sin grilla alrededor, y atado a la grilla se
   quedaba sin estilo justo en el caso que menos se prueba. */
.stk-ui .stk-nada {
    text-align: center; padding: 26px 14px; margin: 16px var(--gutter);
    border: 1px dashed var(--hair-strong); border-radius: var(--r-card);
    background: var(--surface); color: var(--faint); font-size: 12.5px; line-height: 1.5;
}
.stk-ui .stk-nada b { color: var(--muted); }
.stk-ui .stk-posgrid .stk-nada { grid-column: 1 / -1; margin: 0; }

/* ── Los dos diálogos ──────────────────────────────────────────────────────── */
/* No estrenan vocabulario: el velo, el panel, la cabecera navy y el pie son los
   de la ETAPA 4 (`.stk-velo`, `.stk-dlg`, `.stk-dlg-h/-b/-f`, `.stk-btn`). Acá
   va sólo lo que un diálogo que ESCRIBE necesita y el de composición no tenía:
   campos, y una tira donde la validación se dice sin sacar un cartel. */
.stk-ui .stk-dlg-b .campos { padding: 16px 20px; display: flex; flex-direction: column; gap: 14px; }
.stk-ui .stk-campo { display: flex; flex-direction: column; gap: 5px; }
.stk-ui .stk-campo > label {
    font-size: 9.6px; font-weight: 700; letter-spacing: .11em;
    text-transform: uppercase; color: var(--faint);
}
.stk-ui .stk-campo select, .stk-ui .stk-campo input {
    width: 100%; font: inherit; font-size: 12.8px; color: var(--ink);
    background: var(--surface); border: 1px solid var(--hair-strong);
    border-radius: 9px; padding: 8px 11px;
    transition: border-color .15s var(--curva), box-shadow .15s var(--curva);
}
.stk-ui .stk-campo select:focus, .stk-ui .stk-campo input:focus {
    outline: none; border-color: var(--navy-300); box-shadow: 0 0 0 3px var(--navy-050);
}
.stk-ui .stk-campo input[type="number"] { text-align: right; font-variant-numeric: tabular-nums; }
.stk-ui .stk-campo .ayuda { font-size: 11px; color: var(--faint); line-height: 1.4; }
.stk-ui .stk-campo.mal select, .stk-ui .stk-campo.mal input { border-color: var(--crit); }
.stk-ui .stk-campo .mal-txt { font-size: 11px; color: var(--crit); font-weight: 600; }

/* La ficha del lote que se está ubicando: de qué estamos hablando, arriba de
   todo. Sin esto el diálogo pregunta «¿dónde?» sin decir «¿qué?». */
.stk-ui .stk-dlg-b .quees {
    display: flex; align-items: center; gap: 11px;
    padding: 12px 20px; border-bottom: 1px solid var(--hair); background: #fafbfd;
}
.stk-ui .stk-dlg-b .quees .cod {
    font-family: Consolas, "SF Mono", monospace; font-size: 12.4px;
    font-weight: 700; color: var(--navy);
}
.stk-ui .stk-dlg-b .quees .sub { display: block; font-size: 11px; color: var(--muted); margin-top: 1px; }
.stk-ui .stk-dlg-b .quees .kg {
    margin-left: auto; text-align: right; font-variant-numeric: tabular-nums;
}
.stk-ui .stk-dlg-b .quees .kg b { display: block; font-size: 15px; font-weight: 700; }
.stk-ui .stk-dlg-b .quees .kg span { font-size: 10px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--faint); }

/* LA TIRA DE VALIDACIÓN. Las ocho validaciones de la playa eran `alert()`: un
   cartel del sistema operativo que tapa el formulario que hay que corregir. Van
   acá, adentro del propio diálogo y al lado del botón, que es donde se lee el
   motivo por el que el botón no hizo nada (manual §7). */
.stk-ui .stk-dlg-f .validacion {
    display: flex; align-items: center; gap: 7px;
    color: var(--crit); font-size: 11.6px; font-weight: 600;
}
.stk-ui .stk-dlg-f .validacion .material-symbols-outlined { font-size: 16px; }
.stk-ui .stk-btn.primario {
    background: var(--navy); color: #fff; border-color: var(--navy);
}
.stk-ui .stk-btn.primario:hover, .stk-ui .stk-btn.primario:focus-visible {
    background: var(--navy-700); border-color: var(--navy-700);
}
.stk-ui .stk-btn[disabled] {
    background: var(--hair); color: var(--faint); border-color: var(--hair);
    cursor: default; box-shadow: none;
}

/* ── El diálogo de mover: dos lados y una flecha ───────────────────────────── */
.stk-ui .stk-mover {
    display: grid; grid-template-columns: 1fr 34px 1fr; gap: 12px; align-items: start;
    padding: 16px 20px;
}
.stk-ui .stk-mover > .flecha {
    align-self: center; text-align: center; color: var(--hair-strong);
}
.stk-ui .stk-mover > .flecha .material-symbols-outlined { font-size: 30px; }
.stk-ui .stk-mover .lado { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.stk-ui .stk-mover .lado > h5 {
    margin: 0; font-size: 9.6px; font-weight: 700; letter-spacing: .11em;
    text-transform: uppercase; color: var(--faint);
}
.stk-ui .stk-mover .caja {
    border: 1px solid var(--hair); border-radius: 10px; background: #fafbfd;
    min-height: 132px; max-height: 250px; overflow: auto; padding: 4px;
}
.stk-ui .stk-mover .caja .vacio {
    padding: 40px 12px; text-align: center; color: var(--faint);
    font-size: 11.5px; font-style: italic; line-height: 1.45;
}
.stk-ui .stk-mover .todo {
    display: flex; align-items: center; gap: 8px; padding: 6px 8px;
    border-bottom: 1px solid var(--hair); margin-bottom: 3px;
    font-size: 9.6px; font-weight: 700; letter-spacing: .1em;
    text-transform: uppercase; color: var(--faint); cursor: pointer;
}
.stk-ui .stk-mover .fila {
    display: flex; align-items: center; gap: 8px; padding: 5px 8px; border-radius: 7px;
}
.stk-ui .stk-mover .fila:hover { background: var(--surface); }
.stk-ui .stk-mover input[type="checkbox"] {
    width: 15px; height: 15px; accent-color: var(--navy); cursor: pointer; flex: 0 0 auto;
}
.stk-ui .stk-mover .fila .cod {
    font-family: Consolas, "SF Mono", monospace; font-size: 11.4px; font-weight: 700;
    color: var(--navy); flex: 1; min-width: 0; overflow: hidden;
    text-overflow: ellipsis; white-space: nowrap;
}
.stk-ui .stk-mover .fila input[type="number"] {
    width: 92px; font: inherit; font-size: 11.6px; text-align: right;
    font-variant-numeric: tabular-nums; padding: 3px 7px;
    border: 1px solid var(--hair-strong); border-radius: 6px; background: var(--surface);
}
.stk-ui .stk-mover .fila input[type="number"]:focus {
    outline: none; border-color: var(--navy-300); box-shadow: 0 0 0 3px var(--navy-050);
}
.stk-ui .stk-mover .fila .de { font-size: 10.4px; color: var(--faint); white-space: nowrap; }
.stk-ui .stk-mover .info { font-size: 11px; color: var(--muted); line-height: 1.4; }

@media (max-width: 780px) {
    .stk-ui .stk-mover { grid-template-columns: 1fr; }
    .stk-ui .stk-mover > .flecha { transform: rotate(90deg); }
}
@media (max-width: 1100px) { .stk-ui .stk-posgrid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 700px)  {
    .stk-ui .stk-posgrid { grid-template-columns: 1fr; padding: 0 12px 14px; }
    .stk-ui .stk-seg { margin-left: 0; }
}


/* =============================================================================
   7. EL TELÉFONO — la misma pantalla, sin scrolls anidados (ETAPA 6)
   =============================================================================
   Hasta la etapa 5 el teléfono era OTRA APLICACIÓN: 535 líneas, dos pestañas,
   otra consulta para el mismo saldo y sin playa. La etapa 6 lo hace converger —
   `renderMobileStock()` monta EL MISMO armazón en `#mobile-data-container`, que
   es lo que ya hacía Comerciales con `cmMobile()`— así que lo único que queda
   por escribir es cómo se acomoda esa pantalla en 390 px.

   ── LA DECISIÓN DE FONDO: EL TELÉFONO NO ANIDA SCROLLS ───────────────────────
   En el escritorio el módulo se queda quieto y lo que se mueve es la grilla:
   `.stk-hub` toma el alto entero, `.stk-view` no desborda y el scroll vive en
   `.stk-scroll`. Eso es lo correcto en una pantalla de veinte minutos, y es
   exactamente lo que NO se hace en un teléfono: un contenedor que scrollea
   adentro de la página que también scrollea se pelea con el gesto del dedo, y el
   que pierde es siempre el de adentro.

   Acá la cadena de alto se DESARMA a propósito: todo pasa a flujo natural y el
   que scrollea es el `<main>` del armazón móvil, que es el que el navegador ya
   maneja —con su rebote, su barra que se esconde y su «volver arriba»—.

   ── Y EL CANDADO DEL `.hidden` SE VUELVE A ESCRIBIR ──────────────────────────
   No hace falta por especificidad —`.stk-panel.hidden` son tres clases contra
   dos, y gana esté donde esté—, pero se escribe igual: este repo ya se comió dos
   veces la trampa de una regla declarada arriba y apagada abajo, y un `display`
   suelto adentro de un `@media` es exactamente la forma en que vuelve.
   ========================================================================== */
@media (max-width: 767px) {

    /* La cadena de alto, desarmada. */
    .stk-ui.stk-hub { display: block; flex: none; min-height: 0; }
    .stk-ui.stk-hub.hidden { display: none; }
    .stk-ui .stk-shell {
        display: block; flex: none; min-height: 0;
        border-radius: 0; box-shadow: none; background: transparent;
    }
    .stk-ui .stk-view {
        display: block; flex: none; min-height: 0; overflow: visible;
        padding: 12px 0 20px; background: transparent;
    }
    .stk-ui .stk-panel { display: block; flex: none; min-height: 0; }
    .stk-ui .stk-panel.hidden { display: none; }
    .stk-ui .stk-caja { display: block; flex: none; min-height: 0; }
    .stk-ui .stk-scroll { overflow: visible; flex: none; min-height: 0; }
    .stk-ui .stk-fcuerpo { display: block; flex: none; min-height: 0; padding: 12px 0 0; }

    /* La barra de secciones se pega arriba: es la navegación del módulo y en un
       scroll largo de teléfono, perderla es perder dónde estás. */
    .stk-ui .stk-secnav {
        position: sticky; top: 0; z-index: 3;
        padding: 0 6px; gap: 0; box-shadow: var(--e1);
    }
    .stk-ui .stk-secnav button { padding: 11px 9px 12px; font-size: 12px; gap: 5px; flex: 1; }
    .stk-ui .stk-secnav button .material-symbols-outlined { font-size: 17px; }
    .stk-ui .stk-secnav .cnt { padding: 0 6px; font-size: 10.5px; }
    /* La cola vuelve a su lugar: con `margin-left:auto` y la barra en tres
       botones que ya ocupan el ancho, quedaba empujada a un renglón propio con
       todo el hueco a la izquierda. */
    .stk-ui .stk-secnav .tail {
        width: 100%; margin: 0; padding: 0 0 8px;
        justify-content: center; flex-wrap: wrap; gap: 6px 10px;
    }
    /* En 390 px la nota neutra y la frescura se leen de un vistazo o no se leen:
       el rótulo largo se recorta antes que empujar la barra a un tercer renglón. */
    .stk-ui .stk-nota { max-width: 100%; }
    .stk-ui .stk-nota .k { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

    /* El verbo propio del teléfono: es lo único que queda en `.stk-ph`, y va
       pegado a la derecha. En el escritorio el div queda vacío y `:empty` lo
       saca del flujo. */
    .stk-ui .stk-ph { margin: 0 12px 10px; display: flex; justify-content: flex-end; }
    .stk-ui .stk-ph-verbo {
        flex: 0 0 auto; display: inline-flex; align-items: center; gap: 5px;
        font: inherit; font-size: 12.4px; font-weight: 600; color: #fff;
        background: var(--navy); border: 1px solid var(--navy); border-radius: 9px;
        padding: 7px 13px; cursor: pointer; box-shadow: var(--e1);
    }
    .stk-ui .stk-ph-verbo .material-symbols-outlined { font-size: 16px; }
    .stk-ui .stk-ph-verbo:active { background: var(--navy-700); }
    .stk-ui .stk-bar { padding: 0 12px 10px; }
    .stk-ui .stk-search { flex: 1 1 100%; }
    .stk-ui .stk-chk { margin-left: 0; }

    /* ── «De quién es»: la tabla deja de ser una tabla ──────────────────────
       Cinco columnas en 390 px dan 78 px cada una: la caja mide bien y miente.
       Cada fila pasa a ser una tarjeta de dos renglones, que es lo que un dedo
       puede tocar. Se hace con `display:block` sobre los mismos `<tr>` y `<td>`
       —no hay un segundo marcado— y por eso los rótulos de las columnas viajan
       en `data-k`, que el JS escribe una sola vez. */
    .stk-ui table.stk-g, .stk-ui table.stk-g tbody, .stk-ui table.stk-g tr,
    .stk-ui table.stk-g td { display: block; width: auto; }
    .stk-ui table.stk-g thead { display: none; }
    .stk-ui table.stk-g tbody tr {
        position: relative; padding: 11px 12px 10px;
        border-bottom: 1px solid var(--hair);
        display: grid; grid-template-columns: 1fr auto; gap: 2px 10px;
    }
    .stk-ui table.stk-g td {
        border-bottom: 0; padding: 0; white-space: normal;
        font-variant-numeric: tabular-nums;
    }
    .stk-ui table.stk-g td:first-child {
        grid-column: 1; grid-row: 1 / 3; border-left: 0; padding-left: 0;
        align-self: center;
    }
    /* La franja de estado pasa al borde IZQUIERDO de la fila entera, que es
       donde sigue queriendo estar: la celda ya no tiene lados propios. */
    .stk-ui table.stk-g tbody tr.st-desc { border-left: 3px solid var(--crit); padding-left: 9px; }
    .stk-ui table.stk-g tbody tr.st-cero { border-left: 3px solid var(--hair-strong); padding-left: 9px; }
    .stk-ui table.stk-g td:nth-child(2) { grid-column: 2; grid-row: 1; text-align: right; }
    .stk-ui table.stk-g td:nth-child(2) .kg { font-size: 1.05rem; font-weight: 700; }
    .stk-ui table.stk-g td:nth-child(3),
    .stk-ui table.stk-g td:nth-child(4) { grid-column: 2; grid-row: 2; text-align: right; }
    .stk-ui table.stk-g td:nth-child(3)::before {
        content: attr(data-k); color: var(--faint); font-size: 10.5px; margin-right: 5px;
    }
    .stk-ui table.stk-g td:nth-child(3) { font-size: 11px; color: var(--faint); }
    .stk-ui table.stk-g td:nth-child(4):empty { display: none; }
    /* El chevron no va: la fila ENTERA es el control y ya se toca. */
    .stk-ui table.stk-g td:nth-child(5) { display: none; }
    .stk-ui table.stk-g td.vacia { grid-column: 1 / -1; padding: 30px 0; }
    .stk-ui table.stk-g tbody tr:has(td.vacia) { display: block; }

    /* ── La ficha de una cuenta ─────────────────────────────────────────────
       La grilla de movimientos, igual: seis columnas no entran. Cada movimiento
       es una tarjeta con el documento arriba, la contraparte al medio y los
       kilos —con su signo— a la derecha. */
    .stk-ui table.stk-m, .stk-ui table.stk-m tbody, .stk-ui table.stk-m tr,
    .stk-ui table.stk-m td { display: block; width: auto; }
    .stk-ui table.stk-m thead { display: none; }
    .stk-ui table.stk-m tbody tr {
        padding: 10px 12px; border-bottom: 1px solid var(--hair);
        display: grid; grid-template-columns: 1fr auto; gap: 1px 10px;
    }
    .stk-ui table.stk-m td { border-bottom: 0; padding: 0; white-space: normal; }
    .stk-ui table.stk-m td:first-child { border-left: 0; padding-left: 0; }
    .stk-ui table.stk-m tbody tr.ent { border-left: 3px solid var(--ok); padding-left: 9px; }
    .stk-ui table.stk-m tbody tr.sal { border-left: 3px solid var(--crit); padding-left: 9px; }
    .stk-ui table.stk-m tbody tr.anu { border-left: 3px solid var(--hair-strong); padding-left: 9px; }
    .stk-ui table.stk-m td:nth-child(1) { grid-column: 1; grid-row: 1; }
    .stk-ui table.stk-m td:nth-child(2) { grid-column: 2; grid-row: 1; text-align: right; font-size: 11px; color: var(--faint); }
    .stk-ui table.stk-m td:nth-child(3) { grid-column: 1; grid-row: 2; font-weight: 600; }
    .stk-ui table.stk-m td:nth-child(4) { grid-column: 1; grid-row: 3; font-size: 11px; }
    .stk-ui table.stk-m td:nth-child(5) { grid-column: 2; grid-row: 2 / 4; align-self: center; text-align: right; }
    .stk-ui table.stk-m td:nth-child(5) .kg { font-size: 1rem; }
    .stk-ui table.stk-m td:nth-child(6) { grid-column: 1 / -1; grid-row: 4; font-size: 11px; }
    .stk-ui table.stk-m td:nth-child(6):empty { display: none; }
    .stk-ui table.stk-m td.vacia { grid-column: 1 / -1; padding: 30px 0; }

    /* La cabecera de la ficha: el botón de volver a la izquierda y el nombre
       abajo, porque a 390 px los tres en un renglón cortan el nombre a la
       mitad. */
    .stk-ui .stk-fcab { padding: 10px 12px; gap: 10px; }
    .stk-ui .stk-fid { width: 100%; order: 3; }
    .stk-ui .stk-fcifras { margin-left: 0; width: 100%; order: 4; gap: 18px; justify-content: flex-start; }
    .stk-ui .stk-fcifras .c { text-align: left; }
    .stk-ui .stk-fcifras .v .gs-sk { margin-left: 0; }

    /* ── «Dónde está» y la playa ────────────────────────────────────────────
       Las dos grillas de tarjetas ya bajan a una columna en sus propios
       `@media`; acá se reparten las columnas de la tabla del depósito y se
       acomodan el pie y el segmento.

       LOS ANCHOS DE LA TABLA DEL DEPÓSITO SE REPARTEN DE NUEVO, y no es un
       retoque: con los del escritorio, la columna de Kg queda en 64 px y
       «562.000» sale «562.0…». La tabla mide bien y recorta el único número por
       el que alguien entra. El chevrón se va —la fila entera ya es el control—
       y su lugar se lo lleva el número. */
    .stk-ui table.stk-d th:nth-child(1) { width: 40%; }
    .stk-ui table.stk-d th:nth-child(2) { width: 12%; }
    .stk-ui table.stk-d th:nth-child(3) { width: 22%; }
    .stk-ui table.stk-d th:nth-child(4) { width: 26%; }
    .stk-ui table.stk-d th:nth-child(5),
    .stk-ui table.stk-d td:nth-child(5) { display: none; }
    .stk-ui table.stk-d .art { white-space: normal; }
    .stk-ui .stk-pie {
        padding: 10px 12px; flex-direction: column; align-items: flex-start; gap: 4px;
    }
    .stk-ui .stk-pie .sp { display: none; }
    .stk-ui .stk-seg { margin-left: 0; width: 100%; }
    .stk-ui .stk-seg button { flex: 1; }
    .stk-ui .stk-ambito { line-height: 1.45; }

    /* Y LOS DOS DIÁLOGOS ocupan la pantalla entera: a 390 px, 22 px de velo a
       cada lado son 44 que le faltan al contenido. Ya está resuelto en el §5
       para 780 px; acá se agrega lo que el teclado del teléfono necesita. */
    .stk-ui .stk-dlg-f { padding: 10px 12px; }
    .stk-ui .stk-dlg-f .stk-btn { flex: 1; text-align: center; }
    .stk-ui .stk-dlg-b .campos { padding: 14px 12px; }
    .stk-ui .stk-dlg-b .quees { padding: 11px 12px; }
    /* El campo no puede medir menos de 16 px o Safari hace zoom al enfocarlo, y
       la pantalla queda corrida sin que nadie la haya movido. */
    .stk-ui .stk-campo select, .stk-ui .stk-campo input,
    .stk-ui .stk-mover .fila input[type="number"] { font-size: 16px; }
}
