/* ============================================================================
   Majo web — EL MISMO ESTILO QUE MAJO WINDOWS (Diego, 22/09/2026: "no vamos a
   copiar a nadie, vamos a tener nuestro estilo").

   Los colores salen de ui/majo_theme.py, token por token, con los mismos
   nombres (bg_app, bg_header_card, bg_primary, pos_bg_panel, dash_bg_card…):
   si mañana cambia un color en Windows, se cambia acá el mismo nombre. Las
   formas (radios, altos, letra) salen de la hoja de estilos de Windows
   (_PLANTILLA_QSS): botones 10px/34px, campos 8px/36px, tarjetas 22px,
   tablas 12px, títulos 26px, Roboto.

   REGLA: ninguna vista usa un color o un tamaño suelto. Todo se toma de acá,
   así un cambio en un popup, un título o un botón se traslada a todos.
   ============================================================================ */

@font-face { font-family: "Roboto"; font-weight: 400; font-style: normal; src: url("/app/fonts/Roboto-Regular.ttf") format("truetype"); font-display: swap; }
@font-face { font-family: "Roboto"; font-weight: 500; font-style: normal; src: url("/app/fonts/Roboto-Medium.ttf") format("truetype"); font-display: swap; }

/* ---------- MARCA: igual en claro y oscuro (MARCA de majo_theme.py) ---------- */
:root {
  --familia-letra: "Roboto", "Segoe UI", Arial, sans-serif;
  /* EL AZUL DE MAJO WEB (25/09/2026). Estuvo a prueba contra el verde desde el
     22/09, con un interruptor en el menu del usuario, y Diego eligio el azul en
     el Word 8.1. Ahora es el color de fabrica y el interruptor no existe mas:
     una prueba que queda de opcion para siempre es una decision que nadie tomo.
     Es el azul de "Presupuesto" del POS (#2563eb) bajado de brillo, el mismo que
     habia elegido para los iconos en el Word 2.2. */
  --bg-primary: #3566cc;
  --bg-primary-hover: #4577dd;
  --texto-sobre-primario: #ffffff;
  /* El verde de Majo FIJO: no lo mueve el interruptor de la prueba de color.
     Diego, 22/09: *"el botón de cobrar del POS que quede siempre en verde, y
     las barras de los 3 cuadros del panel también"*. Cobrar es la acción que
     más se aprieta en el día y tiene que verse siempre igual. */
  --verde-majo: #16a34a;
  --verde-majo-claro: #22c55e;
  --bg-danger: #e11d48;
  --bg-danger-hover: #be123c;
  --bg-accent-selected: #0e7490;
  --bg-table-selection: #2563eb;
  --text-table-selection: #ffffff;
  /* EL NARANJA DE MAJO ES UNO SOLO (Diego, 24/09/2026: *"Sí, unificalo"*).
     Hasta ese día convivían dos: #d97706 en los botones (Cta. cte. del POS,
     .boton.advertencia) y este, un ámbar más claro, en los avisos, las
     pastillas, los puntitos y las marcas de atención del Inicio. En la misma
     pantalla se veían los dos y no se entendía por qué.

     Queda el de los BOTONES, que es el que Diego reconoce como "el naranja de
     Majo". OJO: Majo de Windows todavía tiene los dos (ui/main_window.py usa
     #f59e0b en los KPI del Inicio, ui/pos_window.py usa #d97706 en Cta. cte.)
     y NO se tocó, porque Windows está vendiendo y se retira cuando la web lo
     iguale. Mientras tanto, el naranja de atención del Inicio se ve un toque
     más oscuro en la web que en Windows. Es a propósito. */
  --bg-warning: #d97706;
  --bg-info: #3b82f6;              /* el "Presupuesto" azul del POS */
  /* LOS TAMAÑOS DE LETRA SON LOS DE MAJO WINDOWS, clavados.
     Diego, 22/09: *"Majo web tiene un tamaño de letra más grande que en
     Windows... ponelo en el mismo tamaño que Windows. Las grillas, los
     gráficos, los botones, los títulos, popups... todo"*.

     Salen de ui/majo_theme.py: TAMANO_DESTACADO_PX 26, TAMANO_TITULO_PX 18,
     TAMANO_SUBTITULO_PX 15, TAMANO_NORMAL_PX 12, TAMANO_CHICO_PX 11. El 12 es
     además la base de TODA la app de Windows: en el QSS,
     "QMainWindow, QWidget { font-size: 12px }", y ni las tablas ni los
     botones ni los campos lo pisan, así que heredan 12.

     Antes están 26/19/16/14/12,5: se habían subido por el Word 1.3 (*"sigo
     viendo muy pegadas las letras"*), pero el problema era el aire entre
     letras y renglones, no el cuerpo. El aire se conserva (letter-spacing y
     line-height más abajo); el cuerpo vuelve al de Windows. */
  --letra-destacado: 26px;
  --letra-titulo: 18px;
  --letra-subtitulo: 15px;
  --letra-normal: 12px;
  --letra-chica: 11px;
  /* formas de Windows */
  --radio-tarjeta: 16px;
  --radio-tabla: 14px;
  --radio-boton: 12px;
  --radio-campo: 10px;
  /* UNA sola altura para todo lo que se toca: 36 px (Diego, Word 4.4 del
     25/09/2026 — directiva 35: *"todos los botones y campos de Majo miden
     36 px de alto, salvo que pida algo particular"*). Antes los botones
     iban 34 y los campos 36, y se notaba justo donde conviven: "Guardar
     selección" y "Eliminar" al lado de su desplegable. El ancho NO entra
     en la regla: lo sigue poniendo el texto de cada botón. */
  --alto-boton: 36px;
  --alto-campo: 36px;
  /* Los íconos de los módulos, TODOS del mismo color, y es el mismo azul que los
     botones — Diego, 22/09: *"botones en azul e íconos en azul"*. Van juntos: si
     algún día se cambia uno, se cambia el otro.
     El token NO se llama "azul" a propósito: lo que nombra es su función.
     Los colores por módulo de Windows quedan acá abajo comentados por si se
     vuelve a ellos. */
  --mod-color: #3566cc;
  --bg-seleccion-modulo: rgba(53, 102, 204, 0.14);
  --mod-tablero: var(--mod-color); --mod-contactos: var(--mod-color); --mod-productos: var(--mod-color); --mod-proveedores: var(--mod-color);
  --mod-compras: var(--mod-color); --mod-stock: var(--mod-color); --mod-pos: var(--mod-color); --mod-ventas: var(--mod-color);
  --mod-presupuestos: var(--mod-color); --mod-cuenta_corriente: var(--mod-color); --mod-configuraciones: var(--mod-color);
  --mod-listas_precio: var(--mod-color); --mod-promociones: var(--mod-color); --mod-contabilidad: var(--mod-color); --mod-inicio: var(--mod-color);
  --ancho-accesos: 200px;
}

/* ---------- OSCURO (el estilo aprobado por Diego el 22/09, Word 1.3) ----------
   Salió de los tokens de ui/majo_theme.py y se corrigió lo que hacía que Majo
   web se viera "como un Excel lindo": las tarjetas ahora son MÁS CLARAS que el
   fondo y flotan con una sombra, los bordes duros se fueron y las pastillas son
   pastel. Diego: *"dejá como definitivo el nuevo que me pasaste, y lo que
   cambiemos lo contrastamos contra este"*. */
:root, :root[data-theme="oscuro"] {
  color-scheme: dark;
  --bg-app: #0b1220;
  /* Diego (22/09): *"en oscuro sacarle un poco de brillo a todo lo que está
     claro, porque resalta muchísimo"*. Los blancos bajan a un gris azulado
     claro: se sigue leyendo cómodo pero no vibra sobre el fondo oscuro. */
  --text-primary: #d7dfee;
  --text-secondary: #a2aec3;
  --text-title: #e6ecf7;
  --text-muted: #7d8aa0;
  --bg-header-card: #16203a;
  --border-header-card: rgba(148, 163, 184, 0.16);
  --bg-page-card: #131c30;
  --border-page-card: rgba(148, 163, 184, 0.12);
  --bg-button: #1b2439;
  --border-button: rgba(148, 163, 184, 0.18);
  --bg-button-hover: #243046;
  --bg-button-pressed: #2b3852;
  --text-toolbutton: #cbd5e1;
  --overlay-hover: rgba(255, 255, 255, 0.07);
  --bg-input: #101a2c;
  --border-input: rgba(148, 163, 184, 0.24);
  --border-input-focus: #38bdf8;
  --border-input-readonly: rgba(148, 163, 184, 0.14);
  --bg-table: #131c30;
  --text-table-header: #aeb9cd;
  --bg-table-header: #18233c;
  --bg-table-hover: #1c2740;
  --bg-seleccion-suave: rgba(56, 189, 248, 0.14);
  --bg-menu: #16203a;
  --checkbox-border: #64748b;
  --bg-banner-info: rgba(56, 189, 248, 0.10);
  --border-banner-info: rgba(56, 189, 248, 0.22);
  --text-banner-info-title: #bae6fd;
  --text-banner-info-valor: #38bdf8;
  --pos-bg-panel: #131c30;
  --pos-border-panel: rgba(148, 163, 184, 0.12);
  --pos-bg-surface: #18233c;
  --pos-bg-surface-hover: #202d4a;
  --pos-border-surface: rgba(148, 163, 184, 0.16);
  --pos-border-surface-alt: rgba(148, 163, 184, 0.12);
  --pos-border-accent: #38bdf8;
  --pos-text: #e6ecf7;
  --pos-text-muted: #7d8aa0;
  --pos-bg-selected: rgba(56, 189, 248, 0.14);
  --dash-bg-card: #18233c;
  --dash-border-card: rgba(148, 163, 184, 0.12);
  --dash-bg-card-soft: #16203a;
  --dash-border-card-soft: rgba(148, 163, 184, 0.10);
  --dash-bg-card-hover: #202d4a;
  --dash-text-title: #e6ecf7;
  --dash-text-muted: #7d8aa0;
  --dash-text-detail: #bcc7da;
  --dash-text-soft: #6b7a92;
  --dash-separator: rgba(148, 163, 184, 0.10);
  --sombra-popup: 0 24px 60px rgba(2, 6, 23, 0.62);
  --sombra-tarjeta: 0 1px 2px rgba(2, 6, 23, 0.18), 0 8px 24px rgba(2, 6, 23, 0.12);
  --sombra-flotante: 0 8px 24px rgba(2, 6, 23, 0.34);
  /* Pastel, pero sin el brillo que saltaba de la pantalla en oscuro. */
  --bg-aviso-amarillo: #e8d6a4; --text-aviso-amarillo: #6b3208; --border-aviso-amarillo: #c98a10;
  --pastilla-verde-bg: #93d3ad; --pastilla-verde-text: #0d3c20;
  --pastilla-gris-bg: #b4bece; --pastilla-gris-text: #232f42;
  --pastilla-naranja-bg: #dcb188; --pastilla-naranja-text: #5c220d;
  --pastilla-rojo-bg: #dda3ab; --pastilla-rojo-text: #74132c;
  --pastilla-azul-bg: #9bbbe2; --pastilla-azul-text: #16305e;
  /* los colores de los gráficos: celeste y verde, como pidió Diego */
  --grafico-1: #4aa8d8; --grafico-2: #5fbe86; --grafico-3: #9080cc; --grafico-4: #d6a53c;
  --foto-fondo: #dde4ee;
  --grafico-grilla: rgba(148, 163, 184, 0.10);
}

/* ---------- CLARO ---------- */
:root[data-theme="claro"] {
  color-scheme: light;
  /* Diego (22/09): *"está muy blanco el fondo en modo claro, sacarle un poco
     de brillo"*. El fondo baja un escalón y las tarjetas dejan de ser blanco
     puro: sigue habiendo diferencia entre la hoja y lo que está apoyado
     encima, pero no encandila. */
  --bg-app: #e6ebf3;
  --text-primary: #111827;
  --text-secondary: #5b6b85;
  --text-title: #0b1220;
  --text-muted: #7a8699;
  --bg-header-card: #fbfcfe;
  --border-header-card: rgba(15, 23, 42, 0.08);
  --bg-page-card: #fbfcfe;
  --border-page-card: rgba(15, 23, 42, 0.08);
  --bg-button: #f5f8fc;
  --border-button: rgba(15, 23, 42, 0.12);
  --bg-button-hover: #f1f5f9;
  --bg-button-pressed: #e6ecf4;
  --text-toolbutton: #475569;
  --overlay-hover: rgba(15, 23, 42, 0.05);
  --bg-input: #fdfeff;
  --border-input: rgba(15, 23, 42, 0.16);
  --border-input-focus: #2563eb;
  --border-input-readonly: rgba(15, 23, 42, 0.08);
  --bg-table: #fbfcfe;
  --text-table-header: #5b6b85;
  --bg-table-header: #eef2f8;
  --bg-table-hover: #f3f6fb;
  --bg-seleccion-suave: rgba(37, 99, 235, 0.10);
  --bg-menu: #fbfcfe;
  --checkbox-border: #94a3b8;
  --bg-banner-info: rgba(37, 99, 235, 0.07);
  --border-banner-info: rgba(37, 99, 235, 0.18);
  --text-banner-info-title: #1d4ed8;
  --text-banner-info-valor: #1d4ed8;
  --pos-bg-panel: #fbfcfe;
  --pos-border-panel: rgba(15, 23, 42, 0.08);
  --pos-bg-surface: #eef2f8;
  --pos-bg-surface-hover: #e3eaf4;
  --pos-border-surface: rgba(15, 23, 42, 0.10);
  --pos-border-surface-alt: rgba(15, 23, 42, 0.08);
  --pos-border-accent: #2563eb;
  --pos-text: #0b1220;
  --pos-text-muted: #7a8699;
  --pos-bg-selected: rgba(37, 99, 235, 0.10);
  --dash-bg-card: #fbfcfe;
  --dash-border-card: rgba(15, 23, 42, 0.08);
  --dash-bg-card-soft: #fbfcfe;
  --dash-border-card-soft: rgba(15, 23, 42, 0.07);
  --dash-bg-card-hover: #f3f6fb;
  --dash-text-title: #0b1220;
  --dash-text-muted: #7a8699;
  --dash-text-detail: #334155;
  --dash-text-soft: #94a3b8;
  --dash-separator: rgba(15, 23, 42, 0.08);
  --sombra-popup: 0 24px 60px rgba(15, 23, 42, 0.18);
  --sombra-tarjeta: 0 1px 2px rgba(15, 23, 42, 0.06), 0 8px 24px rgba(15, 23, 42, 0.07);
  --sombra-flotante: 0 8px 24px rgba(15, 23, 42, 0.14);
  --bg-aviso-amarillo: #fef3c7; --text-aviso-amarillo: #92400e; --border-aviso-amarillo: #d97706;
  --pastilla-verde-bg: #d1fae5; --pastilla-verde-text: #065f46;
  --pastilla-gris-bg: #e8edf5; --pastilla-gris-text: #334155;
  --pastilla-naranja-bg: #ffedd5; --pastilla-naranja-text: #9a3412;
  --pastilla-rojo-bg: #ffe4e6; --pastilla-rojo-text: #9f1239;
  --pastilla-azul-bg: #dbeafe; --pastilla-azul-text: #1e40af;
  --grafico-1: #0ea5e9; --grafico-2: #22c55e; --grafico-3: #8b5cf6; --grafico-4: #f59e0b;
  --foto-fondo: #ffffff;
  --grafico-grilla: rgba(15, 23, 42, 0.07);
}

/* ============================ base ============================ */
* { box-sizing: border-box; }
html, body { margin: 0; min-height: 100%; }
/* Diego (1.2): *"las letras de la palabra Alertas están muy juntas… la misma
   letra pero con una separación más entre letras, apenas"*. 0,2 px en todo el
   sistema y 0,3 px en botones y títulos, que es donde se notaba. */
body { font-family: var(--familia-letra); font-size: var(--letra-normal); color: var(--text-primary); background: var(--bg-app); -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; letter-spacing: 0.5px; line-height: 1.55; }
a { color: var(--text-banner-info-valor); text-decoration: none; }
button, input, select, textarea { font: inherit; color: inherit; }
h1, h2, h3 { margin: 0; }
.oculto { display: none !important; }
.num { font-variant-numeric: tabular-nums; }
.derecha { text-align: right; }
.centro { text-align: center; }
.suave { color: var(--text-secondary); }
.tenue { color: var(--text-muted); }
.chico { font-size: var(--letra-chica); }
.espaciado > * + * { margin-top: 12px; }

/* ============================ estructura (como MainWindow) ============================ */
.app { min-height: 100vh; }
.cargando-pantalla { min-height: 100vh; display: grid; place-items: center; }
.layout { display: grid; grid-template-rows: auto 1fr auto; height: 100vh; overflow: hidden; padding: 10px 12px; gap: 8px; }

/* HeaderCard: logo + MAJO + subtítulo + Alertas + usuario (QFrame#HeaderCard) */
.cabecera { background: var(--bg-header-card); border: 1px solid var(--border-header-card); border-radius: var(--radio-tarjeta); padding: 10px 22px; display: flex; align-items: center; gap: 16px; min-height: 84px; box-shadow: var(--sombra-tarjeta); }
.cabecera.pruebas { border: 3px solid var(--bg-danger); }
.cabecera .logo { height: 58px; width: auto; flex: none; }
.cabecera .titulos { flex: 1; min-width: 0; }
.cabecera .titulo { font-size: var(--letra-destacado); font-weight: 700; color: var(--text-title); letter-spacing: 0.04em; line-height: 1.1; }
.cabecera.pruebas .titulo { color: var(--bg-danger); }
.cabecera .subtitulo { font-size: var(--letra-normal); color: var(--text-secondary); margin-top: 2px; }
.cabecera.pruebas .subtitulo { color: #4ade80; font-weight: 700; }
.cabecera .acciones { display: flex; align-items: center; gap: 10px; }
/* La ayuda estuvo acá, centrada en la cabecera, del 25/09 al 29/09 (#388).
   Diego la sacó en el Word 10.1 (*"no me gusta donde lo pusiste… dentro de la
   hoja de los módulos"*): ahora va en el medio de la barra de cada módulo —
   ver `.con-ayuda`, al lado de `.barra-herramientas`. En el celular, además,
   centrada en la cabecera se montaba encima de "MAJO". */
.badge { position: absolute; top: -6px; right: -6px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 10px; background: var(--bg-danger); color: #fff; font-size: 11px; font-weight: 800; display: grid; place-items: center; }
/* #659 punto 20: el segundo número del botón Alertas, VERDE y abajo, con las que ya miró y siguen pendientes.
   El rojo de arriba (las que no miró) no se toca. */
.badge.vistas { top: auto; bottom: -6px; background: var(--verde-majo); }
.boton.con-badge { position: relative; }
/* Diego (1.2): el ícono de alertas es amarillo en todos lados. */
.boton.alertas svg { color: var(--bg-warning); }

/* cuerpo: Accesos (rail de módulos) a la izquierda + contenido */
.cuerpo { display: grid; grid-template-columns: var(--ancho-accesos) 1fr; gap: 8px; align-items: stretch; min-height: 0; overflow: hidden; }
.accesos { background: var(--bg-page-card); border: 1px solid var(--border-page-card); border-radius: var(--radio-tarjeta); box-shadow: var(--sombra-tarjeta); padding: 12px 10px; display: flex; flex-direction: column; gap: 6px; min-height: 0; overflow: hidden; }
/* El encabezado reserva SIEMPRE su lugar (Diego, 1.3): antes desaparecía con
   el rail chico y, al abrirse, empujaba los módulos un renglón hacia abajo —
   apretabas sin mirar y entrabas al módulo de arriba. */
.accesos .encabezado { display: flex; align-items: center; justify-content: space-between; padding: 4px 6px 8px; min-height: 34px; }
.accesos .encabezado h2 { font-size: var(--letra-subtitulo); font-weight: 700; color: var(--text-title); }
.accesos .lista { display: flex; flex-direction: column; gap: 6px; flex: 1; min-height: 0; overflow-y: auto; }
/* Diego (1.3): *"pasame los botones sin recuadro, a ver cómo queda"*. Sin caja
   ni borde: sólo el ícono de color y el nombre. */
.acceso { display: flex; align-items: center; gap: 10px; min-height: 38px; padding: 4px 8px; border-radius: 12px; border: 1px solid transparent; background: transparent; color: var(--dash-text-title); font-size: var(--letra-normal); font-weight: 600; cursor: pointer; text-align: left; width: 100%; transition: background .12s; }
.acceso:hover { background: var(--overlay-hover); }
.acceso.activo { border-color: var(--mod-color); background: var(--bg-seleccion-modulo); color: var(--text-title); }
/* Diego (2.3): los íconos de los módulos, todos del mismo azul. El acento de
   cada módulo (--acento) sigue existiendo y se usa en sus pantallas. */
.acceso .icono { width: 28px; height: 28px; border-radius: 10px; display: grid; place-items: center; flex: none; background: var(--mod-color); color: #fff; }
.acceso .icono svg { width: 16px; height: 16px; }
.acceso .t { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acceso.pronto { opacity: 0.5; }
/* Diego (4.3): *"los accesos también deberían ocupar el alto de la página en lo
   posible sin perder la estética"*. Los botones reparten el alto sobrante hasta
   46 px (más que eso ya parecen globos) y se comprimen hasta 34 px antes de que
   aparezca el scroll del rail. OJO: esto se aparta de Windows A PROPÓSITO —allá
   el botón es fijo (38 compacto / 42 normal) y el rail scrollea— y va dentro de
   `min-width: 801px` porque en el celular la lista es horizontal y `flex: 1`
   les estiraría el ANCHO. */
@media (min-width: 801px) {
  .accesos .lista { gap: clamp(3px, 0.5vh, 6px); }
  .acceso { flex: 1 1 38px; min-height: 34px; max-height: 46px; }
}
/* El rail se despliega SOLO al pasar el mouse cuando hay un módulo abierto
   (Diego, 1.2: "en Windows no hay flechita"). Se abre por encima del módulo,
   sin correrle nada: es el flyout de MainWindow. */
.layout.modo-modulo .cuerpo { position: relative; }
.layout.modo-modulo .accesos { transition: width .16s ease; }
/* Se solapa SOBRE el módulo abierto, sin correrlo y sin oscurecer la pantalla
   (Diego, 1.3): la columna del rail sigue midiendo 56 px, así que nada se
   mueve, y la sombra es suave, no la del popup. */
.layout.modo-modulo .accesos.desplegado { position: absolute; left: 0; top: 0; bottom: 0; width: var(--ancho-accesos); z-index: 30; box-shadow: var(--sombra-flotante); }
.layout.modo-modulo .accesos.desplegado .encabezado h2, .layout.modo-modulo .accesos.desplegado .acceso .t { display: revert; }
.layout.modo-modulo .accesos.desplegado .pie-accesos { visibility: visible; }
.layout.modo-modulo .accesos.desplegado .acceso { justify-content: flex-start; padding: 4px 8px; }
.accesos .pie-accesos { display: flex; gap: 6px; padding-top: 6px; flex: none; flex-wrap: nowrap; overflow: hidden; }
/* Configuración, fija arriba de Uso y Restaurar (app.js::pintarAccesos, Word 10.2): fuera del scroll de la lista. */
.accesos .fijos-accesos { display: flex; flex-direction: column; gap: 6px; flex: none; }
.accesos .fijos-accesos:empty { display: none; }
/* Soporte (menú del usuario, app.js::mostrarSoporte): un solo alto para la
   lista, la consulta abierta y la nueva (#561). En la lista entran unas 10
   consultas y la grilla scrollea adentro (Word 10.2, punto 73); en la consulta
   abierta scrollea el hilo. */
/* Word 10.2, punto 73 (Diego): *"tiene que mostrar las últimas 10 consultas y
   luego meter scroll"*. La lista mide 10 renglones justos (el mismo alto que las
   grillas de diez de los popups del POS, .grilla-popup.diez-renglones) y la
   ventana mide lo que ocupa esa lista: el mismo alto sirve para la consulta
   abierta y la nueva (#561, directiva 37). */
.modal.soporte-alto-fijo { height: min(88vh, 554px); }
.modal.soporte-alto-fijo .soporte-lista { flex: none; height: 349px; overflow-y: auto; }
.modal.soporte-alto-fijo .soporte-lista table.tabla thead th { position: sticky; top: 0; z-index: 2; }
.modal.soporte-alto-fijo .cuerpo-modal { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.modal.soporte-alto-fijo .soporte-cuerpo { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: 12px; }
.modal.soporte-alto-fijo .soporte-cuerpo > .barra-herramientas, .modal.soporte-alto-fijo .soporte-cuerpo > h3,
.modal.soporte-alto-fijo .soporte-cuerpo > textarea, .modal.soporte-alto-fijo .soporte-cuerpo > button { flex: none; }
.modal.soporte-alto-fijo .soporte-desplaza { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
/* La columna 2 se fija a mano: cuando el rail se despliega pasa a estar
   "flotando" (position: absolute) y, sin esto, el módulo se corría a la
   primera columna — Diego lo vio como "se deja de ver el módulo". */
.contenido { grid-column: 2; min-width: 0; min-height: 0; display: flex; flex-direction: column; gap: 8px; overflow: hidden; }

/* zócalo (pie) */
.zocalo { background: var(--bg-page-card); border: 1px solid var(--border-page-card); border-radius: var(--radio-tarjeta); box-shadow: var(--sombra-tarjeta); padding: 10px 22px; display: flex; align-items: center; gap: 12px; color: var(--text-secondary); font-size: var(--letra-normal); }
.zocalo .espacio { flex: 1; }
.zocalo .version { color: var(--text-muted); font-weight: 400; }

/* título de módulo (la tarjeta "Ventas" de arriba de cada pantalla) */
.titulo-modulo { background: var(--bg-header-card); border: 1px solid var(--border-header-card); border-radius: var(--radio-tarjeta); padding: 12px 20px; display: flex; align-items: center; gap: 12px; }
.titulo-modulo h1 { font-size: var(--letra-destacado); font-weight: 700; color: var(--text-title); }
.titulo-modulo .ayuda { width: 20px; height: 20px; border-radius: 10px; background: var(--bg-button); border: 1px solid var(--border-button); color: var(--text-secondary); font-size: var(--letra-normal); font-weight: 800; display: grid; place-items: center; cursor: pointer; }
.titulo-modulo .ayuda:hover { background: var(--bg-button-hover); color: var(--text-primary); }
.titulo-modulo .espacio { flex: 1; }

/* ============================ tarjetas ============================ */
.tarjeta { background: var(--bg-page-card); border: 1px solid var(--border-page-card); border-radius: var(--radio-tarjeta); padding: 14px 16px; box-shadow: var(--sombra-tarjeta); }
.tarjeta > h2, .tarjeta .cabecera-tarjeta h2 { font-size: var(--letra-subtitulo); font-weight: 700; color: var(--text-title); }
.tarjeta > h2 { margin-bottom: 10px; }
.tarjeta .cabecera-tarjeta { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.tarjeta .cabecera-tarjeta h2 { flex: 1; }
.tarjeta-dash { background: var(--dash-bg-card); border: 1px solid var(--dash-border-card); border-radius: 16px; padding: 12px 14px; box-shadow: var(--sombra-tarjeta); }
.grilla { display: grid; gap: 12px; }
.grilla.dos { grid-template-columns: 1fr 1fr; }
.grilla.tres { grid-template-columns: repeat(3, 1fr); }
.grilla.cuatro { grid-template-columns: repeat(4, 1fr); }

/* KpiCard de Windows: barra de acento a la izquierda, título chico en mayúsculas, valor 15px/900 */
.kpi { position: relative; background: var(--dash-bg-card-soft); border: 1px solid var(--dash-border-card-soft); border-radius: 14px; padding: 10px 12px 10px 16px; overflow: hidden; box-shadow: var(--sombra-tarjeta); }
.kpi::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px; background: var(--acento, var(--bg-primary)); border-radius: 16px 0 0 16px; }
.kpi .titulo { font-size: var(--letra-chica); color: var(--dash-text-muted); font-weight: 800; letter-spacing: 0.6px; text-transform: uppercase; }
.kpi .valor { font-size: var(--letra-subtitulo); color: var(--dash-text-title); font-weight: 900; margin-top: 2px; }
.kpi .detalle { font-size: var(--letra-chica); color: var(--dash-text-detail); margin-top: 2px; }

/* ============================ botones (QPushButton) ============================ */
.boton { letter-spacing: 0.6px; font-weight: 600; display: inline-flex; align-items: center; justify-content: center; gap: 8px; background: var(--bg-button); color: var(--text-primary); border: 1px solid var(--border-button); border-radius: var(--radio-boton); padding: 6px 14px; font-weight: 600; min-height: var(--alto-boton); cursor: pointer; white-space: nowrap; transition: background .12s; }
.boton:hover { background: var(--bg-button-hover); }
.boton:active { background: var(--bg-button-pressed); }
.boton:disabled { opacity: 0.5; cursor: default; }
.boton.primario, .boton.exito { background: var(--bg-primary); color: var(--texto-sobre-primario, #fff); border: none; }
.boton.primario:hover, .boton.exito:hover { background: var(--bg-primary-hover); }
.boton.peligro { background: var(--bg-danger); color: #fff; border: none; }
.boton.peligro:hover { background: var(--bg-danger-hover); }
.boton.info { background: var(--bg-info); color: #fff; border: none; }
.boton.advertencia { background: #d97706; color: #fff; border: none; }
.boton.advertencia:hover { background: #b45309; }
.boton.herramienta { background: transparent; border: none; color: var(--text-toolbutton); padding: 6px 12px; font-weight: 500; border-radius: var(--radio-campo); }
.boton.herramienta:hover { background: var(--overlay-hover); }
.boton.icono { width: var(--alto-boton); padding: 0; }
/* "chico" es MENOS AIRE A LOS COSTADOS, no más bajo (25/09/2026, directiva 35).
   Tenía 28 px y convivía con botones de 34 y campos de 36 en el mismo renglón.
   El alto lo fija el token y es el mismo para todos; acá sólo queda el padding
   apretado y la letra normal, que es lo que lo hace angosto. */
.boton.chico { min-height: var(--alto-boton); padding: 4px 10px; font-size: var(--letra-normal); }
.boton.grande { min-height: 52px; font-size: var(--letra-subtitulo); font-weight: 700; }
.boton svg { width: 18px; height: 18px; }
.boton.activo { border-color: var(--border-input-focus); background: var(--bg-seleccion-suave); }
.grupo-botones { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }

/* ============================ campos (QLineEdit, QComboBox) ============================ */
.campo { display: flex; flex-direction: column; gap: 4px; }
.campo label, .etiqueta { font-size: var(--letra-chica); font-weight: 600; color: var(--text-secondary); letter-spacing: 0.6px; text-transform: uppercase; }
/* La aclaración de un título, en letra más chica y sin mayúsculas, en el mismo renglón ("sobre lo que queda"). */
.campo label .aclaracion-etiqueta { margin-left: 5px; font-size: 0.9em; font-weight: 500; letter-spacing: 0; text-transform: none; white-space: nowrap; }
/* #653: un icono de Majo al lado del texto de un boton (ui.js::conIcono). El SVG se alinea con la letra y no
   engorda el boton: hereda el color, y el tamano viene del propio svg. */
.boton-con-ico { display: inline-flex; align-items: center; gap: 6px; }
.boton-con-ico > .ico { display: inline-flex; flex: none; }
.entrada { width: 100%; background: var(--bg-input); color: var(--text-primary); border: 1px solid var(--border-input); border-radius: var(--radio-campo); padding: 6px 10px; min-height: var(--alto-campo); outline: none; transition: border-color .12s, background .12s; }
.entrada:hover:enabled { background: var(--bg-button-hover); border-color: var(--border-input-focus); }
.entrada:focus { border-color: var(--border-input-focus); box-shadow: 0 0 0 2px color-mix(in srgb, var(--border-input-focus) 30%, transparent); }
.entrada::placeholder { color: var(--text-muted); }
.entrada.chica { min-height: var(--alto-campo); padding: 3px 8px; }  /* idem: angosta, no baja */
/* Un campo de varios renglones CRECE CON LO QUE SE ESCRIBE. #651 (Diego, 13/10/2026, Word 12.2, punto 24, sobre las
   Observaciones que deja la compra inteligente): *"en las observaciones queda cortado el texto… ¿por qué? Si tiene
   lugar de sobra… aparte debajo de observaciones debería escribir también. Como que está con esa sangría que no sé
   por qué en la segunda línea"*. La "sangría" era el tercer renglón cortado al medio: el campo medía 49 px y el
   texto 142. Con esto el alto sale del contenido (los `rows` pasan a ser el MÍNIMO), hasta 220 px; de ahí en más
   se desplaza adentro, y se puede agrandar a mano arrastrando la esquina. En un navegador que todavía no entienda
   `field-sizing` queda exactamente como estaba. */
textarea.entrada { field-sizing: content; max-height: 220px; resize: vertical; }
select.entrada { appearance: none; padding-right: 30px; background-image: linear-gradient(45deg, transparent 50%, var(--text-secondary) 50%), linear-gradient(135deg, var(--text-secondary) 50%, transparent 50%); background-position: calc(100% - 16px) center, calc(100% - 11px) center; background-size: 5px 5px, 5px 5px; background-repeat: no-repeat; }
/* OJO, ESTA LÍNEA NO SOBRA (23/09/2026). `.entrada.chica` son DOS clases y
   `select.entrada` es una clase + un elemento: `.entrada.chica` pesa más, así
   que su `padding: 3px 8px` le pisaba el `padding-right: 30px` de arriba a
   TODOS los select con "entrada chica" — y la flechita, que se dibuja con
   background-image en los últimos 16 px, quedaba ENCIMA del texto. Se veía en
   el Inicio ("2026" salía como "20⌄6" y "Septiembre" con la flecha sobre la
   "e"). Si algún día se toca `.entrada.chica`, este renglón tiene que seguir
   después y con las dos clases, o el encimado vuelve.

   Y LA FLECHA VA MÁS CHICA Y MÁS AL BORDE (no alcanzaba con el padding): con
   los 30 px de padding de los select normales, los de mes y año del Inicio
   crecían 20 px cada uno y en 1280x800 el botón de refrescar ya no entraba en
   el renglón, se iba abajo y la cabecera de la tarjeta crecía 10 px — 10 px
   que le salían al gráfico (medido: 92 → 82). Con la flecha de 4 px pegada al
   borde alcanzan 16 px de padding: el texto termina 5 px antes de la flecha,
   los tres controles vuelven a entrar en un renglón y el gráfico conserva su
   alto. */
select.entrada.chica { padding-right: 16px; background-position: calc(100% - 11px) center, calc(100% - 7px) center; background-size: 4px 4px, 4px 4px; }
input[type="date"].entrada { width: auto; }
input[type="checkbox"] {
  appearance: none; -webkit-appearance: none;
  width: 16px; height: 16px; margin: 0; flex: none;
  border: 1px solid var(--checkbox-border); border-radius: 4px;
  background: transparent;
  display: inline-grid; place-content: center;
  cursor: pointer; vertical-align: middle;
  transition: background .12s, border-color .12s;
}
input[type="checkbox"]:hover:enabled { border-color: var(--border-input-focus); }
input[type="checkbox"]:checked, input[type="checkbox"]:indeterminate { background: var(--bg-primary); border-color: var(--bg-primary); }
input[type="checkbox"]:checked::after {
  content: ""; width: 4px; height: 8px;
  border: solid var(--texto-sobre-primario, #fff); border-width: 0 1.5px 1.5px 0;
  transform: translateY(-1px) rotate(45deg);
}
input[type="checkbox"]:indeterminate::after {
  content: ""; width: 8px; height: 0;
  border-bottom: 1.5px solid var(--texto-sobre-primario, #fff);
}
input[type="checkbox"]:focus-visible { outline: 2px solid var(--border-input-focus); outline-offset: 1px; }
input[type="checkbox"]:disabled { opacity: 0.45; cursor: default; }
.buscador { position: relative; flex: 1; min-width: 200px; }
.buscador svg { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); width: 16px; height: 16px; color: var(--text-muted); pointer-events: none; }
.buscador .entrada { padding-left: 32px; }
.barra-herramientas { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.barra-herramientas select.entrada { width: auto; min-width: 150px; }
/* ---------- #388: la ayuda, EN EL MEDIO de la barra de arriba de cada módulo ----------
   Diego, Word 10.1: *"hay que ponerlo arriba al centro pero dentro de la hoja
   de los módulos… Por ejemplo en el de proveedores iría en la misma línea del
   botón nuevo y acciones pero al centro del módulo"*.

   La barra la arma app.js::barraConAyuda en tres partes: izquierda · ayuda ·
   derecha. Los dos costados arrancan del mismo ancho (`flex: 1 1 0`) y se
   reparten lo que sobra en partes iguales, así el botón cae en el centro de la
   hoja aunque a un lado haya dos botones y al otro cinco (con un espaciador en
   el medio caería en el centro de lo que sobra, que es otra cosa).
   Cada costado mide como mínimo lo que ocupan sus botones (`min-width:
   fit-content`): si uno no entra en su mitad se lleva lo que necesita y el
   botón de la ayuda se corre un poco, en vez de partir ese costado en dos
   renglones o montarse encima de un botón (medido el 29/09: con dos mitades
   rígidas, Stock y Contabilidad pasaban a dos renglones en 1101 px). Si ni
   así entra todo en un renglón, la barra se parte como siempre (el costado
   derecho baja entero); y un costado más ancho que la hoja entera (los
   filtros del reporte de Stock en una pantalla chica) se parte adentro en
   vez de salirse de la tarjeta — eso es lo que hace `fit-content` y no haría
   `max-content`. */
.barra-herramientas.con-ayuda { flex-wrap: wrap; }
.barra-herramientas.con-ayuda > .lado { flex: 1 1 0; min-width: fit-content; display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.barra-herramientas.con-ayuda > .lado.derecha { justify-content: flex-end; }
.barra-herramientas.con-ayuda > .ayuda-del-modulo { flex: none; }
.ayuda-del-modulo { white-space: nowrap; font-weight: 600; }
.ayuda-del-modulo .texto-corto { display: none; }
/* En una pantalla mediana (una notebook chica, la ventana achicada) y en el
   celular el botón dice sólo "❔ Ayuda": el nombre completo son ~120 px más,
   y con eso las barras más cargadas (Contabilidad, Stock) pasaban a dos
   renglones. El nombre del módulo igual está en la pestaña.
   OJO con el orden: esto va DESPUÉS de las dos reglas de arriba, que tienen la
   misma fuerza; si quedara antes, ganarían ellas y no se vería ningún texto. */
/* (Revisión del 30/09: con 1250 todavía se partían Contabilidad a 1101 px y las
   solapas de Reportes hasta 1366; el corte pasa a 1440.) */
@media (max-width: 1440px) {
  .ayuda-del-modulo .texto-largo { display: none; }
  .ayuda-del-modulo .texto-corto { display: inline; }
}
/* En el celular no entran tres partes: la barra vuelve a ser una sola fila
   que se parte en renglones, con los botones en el mismo orden (los de la
   izquierda, la ayuda y los de la derecha). Los dos costados se "disuelven"
   (`display: contents`) para que la ayuda se acomode en el hueco que deja el
   último botón de la izquierda en vez de gastar un renglón propio. */
@media (max-width: 800px) {
  .barra-herramientas.con-ayuda > .lado { display: contents; }
}

/* ---------- el renglón de filtros: UNA sola altura en los 15 módulos ----------
   Diego, 22/09: *"Fijate que todos los módulos tengan los primeros botones, los
   buscadores y los desplegables del mismo tamaño y ubicación"* y *"hasta tienen
   distintos tamaños"*. Había TRES alturas conviviendo en el mismo renglón según
   el módulo: 30 px los filtros con "entrada chica" (8 módulos), 36 px los de
   Ventas y Stock, y 34 px los botones. Majo Windows los pone a todos en la
   misma altura con una función que "normaliza alturas de la fila de filtros"
   (ui/utils/navigation_helpers.py:612); acá lo hace esta regla.
   Va acotada a `.pantalla` a propósito: el panel de venta del POS no es una
   pantalla de lista y no entra. */
.pantalla .barra-herramientas .entrada,
.pantalla .barra-herramientas .boton { min-height: var(--alto-boton); height: var(--alto-boton); }
.pantalla .barra-herramientas textarea.entrada { height: auto; }

/* El campo para ir a una página: 56 px, texto centrado y la MISMA altura que
   las flechas de al lado. Sin flechitas: el QSpinBox de Windows las apaga
   (setButtonSymbols(NoButtons), ui/utils/table_helpers.py:297) y las del
   navegador además se comen la mitad del ancho. */
.entrada.pagina { width: 56px; text-align: center; min-height: var(--alto-boton); height: var(--alto-boton); -moz-appearance: textfield; }
.entrada.pagina::-webkit-inner-spin-button,
.entrada.pagina::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }

/* El popup de Columnas: tres columnas fijas como en Windows, una sola en el
   celular (regla fija del 22/09: todo tiene que entrar también en 390 px). */
.campos-en-columnas { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 2px 16px; }
@media (max-width: 800px) { .campos-en-columnas { grid-template-columns: 1fr; } }
.chips { display: flex; flex-wrap: wrap; gap: 6px; }
.chip { border: 1px solid var(--border-button); background: var(--bg-button); border-radius: 999px; padding: 4px 12px; cursor: pointer; font-size: var(--letra-normal); font-weight: 600; color: var(--text-secondary); }
.chip.activo { background: var(--bg-seleccion-suave); border-color: var(--border-input-focus); color: var(--text-primary); }
.solapas { display: flex; gap: 4px; border-bottom: 1px solid var(--dash-separator); overflow-x: auto; }
.solapa { background: transparent; border: none; border-bottom: 2px solid transparent; padding: 8px 12px; color: var(--text-secondary); font-weight: 600; cursor: pointer; white-space: nowrap; }
.solapa.activa { color: var(--text-primary); border-bottom-color: var(--border-input-focus); }
/* Las solapas van en MAYÚSCULA, como los títulos de los campos (Diego, 02/10/2026,
   al ver la ficha del contacto en pestañas: "Y las pestañas en mayúscula"). En
   todas las solapas de Majo web a la vez, para que no queden distintas; las de
   rubros del POS y las de los módulos de arriba son otra cosa y no cambian. */
.solapa { text-transform: uppercase; letter-spacing: 0.4px; }

/* ============================ tablas (QTableWidget) ============================ */
.tabla-contenedor { overflow-x: auto; border: 1px solid var(--border-page-card); border-radius: var(--radio-tabla); background: var(--bg-table); }
table.tabla { width: 100%; border-collapse: collapse; }
/* El renglon mide 30 px, como en Majo Windows (ventas_window.py:
   verticalHeader().setDefaultSectionSize(30)). Diego, 22/09: *"en la grilla de
   Windows entran mas de 20 filas y en la de web entran 14"*.
   La cuenta: line-height 1,5 sobre 12 px = 18, mas 6+6 de padding = 30. Por eso
   el interlineado de la tabla NO es el 1,55 del resto del sistema: ahi cada
   pixel se paga en filas que se ven. */
table.tabla th { text-align: left; font-size: var(--letra-chica); font-weight: 600; letter-spacing: 0.5px; text-transform: uppercase; color: var(--text-table-header); background: var(--bg-table-header); padding: 8px; line-height: 1.2; white-space: nowrap; }
table.tabla td { padding: 6px 8px; line-height: 1.5; border-bottom: 1px solid var(--dash-separator); vertical-align: middle; white-space: nowrap; }
table.tabla td .pastilla { max-width: 260px; overflow: hidden; text-overflow: ellipsis; vertical-align: middle; }
table.tabla td.envuelve { white-space: normal; }
table.tabla tr:last-child td { border-bottom: none; }
table.tabla tbody tr.clic { cursor: pointer; }
table.tabla tbody tr.clic:hover td { background: var(--bg-table-hover); }
table.tabla tbody tr.seleccionada td { background: var(--bg-table-selection); color: var(--text-table-selection); }
/* La fila TILDADA (con su casillero marcado) va en el celeste suave, como el
   CheckedRowDelegate de Windows (ui/utils/table_helpers.py:137). Es otra cosa
   que `.seleccionada`, que es la fila resaltada del POS: por eso son dos
   clases distintas y no se pisan. */
table.tabla tbody tr.tildada td { background: var(--bg-seleccion-suave); }
/* #601 (Word 11.2): con texto buscado, los EXACTOS en negrita y una línea fina debajo del último,
   que los separa de los que se encontraron por contenido. */
table.tabla tbody tr.fila-exacta td { font-weight: 700; }
table.tabla tbody tr.fin-exactos td { border-bottom: 2px solid color-mix(in srgb, var(--border-input-focus) 55%, transparent); }
table.tabla td.num { text-align: right; font-variant-numeric: tabular-nums; }
/* Word 11.2, marcas 8 y 14: los números que se cargan o se comparan, centrados (Sistema,
   Contado y Diferencia del Ajuste; los mínimos que se completan). */
table.tabla td.centrado, table.tabla td.num.centrado { text-align: center; }
/* Word 11.3, marca 7: los números que no son plata ni % (y los Sí/No), centrados en todas las grillas
   (ui.js::alinearNumerosDeGrilla decide columna por columna). */
table.tabla td.num-centrado, table.tabla td.num.num-centrado { text-align: center; }
table.tabla td.centrado .entrada { text-align: center; }
table.tabla th.num { font-variant-numeric: tabular-nums; }
/* Diego (4.2): los titulos de columna van centrados, y la celda que lleva una
   pildora tambien (la pildora se centra sola dentro de su celda). */
table.tabla th { text-align: center; }
/* Ojo con el `>`: centra la celda cuya UNICA cosa es una pildora, no cualquiera
   que tenga una adentro (una celda con texto + pildora no se centra).
   El segundo selector es por el D37 (25/09/2026): las filas que no estan
   abiertas envuelven su contenido en un `span.tenue` para apagarlas, y eso deja
   la pildora un nivel mas abajo. Sin este renglon, la columna Estado quedaba
   MITAD centrada y mitad a la izquierda, fila por fila, con el filtro en
   "Todos" -- justo la pantalla que hay que mirar para aprobar el D37. */
table.tabla td:has(> .pastilla),
table.tabla td:has(> .tenue > .pastilla) { text-align: center; }
/* La grilla de un popup que lista cosas (Word 6.2, marcas 8 y 9, y la regla
   #435 de Diego: *"si tengo un detalle de venta con 10 ventas y una con 1
   venta, ambos popup se ven iguales… y si es necesario 'agrandar', en vez de
   agrandar se mete un scroll solo en la grilla"*).

   Por eso es `height` y no `max-height`: con alto MÁXIMO el popup se achicaba
   cuando había pocas filas y crecía cuando había muchas, que es justo lo que
   él no quiere. Con alto fijo, el popup mide siempre lo mismo y la que
   scrollea es la grilla. Los títulos quedan pegados arriba mientras se baja. */
/* UN SOLO CUADRO PARA LAS DOS BARRAS (#660, Diego 14/10/2026, sobre el Historial de cajas): *"El problema del
   scroll en Historial de cajas lo sigo teniendo! de hecho si hago el scroll vertical también se van los títulos y
   baja al final donde recién ahí aparece el scroll… algo mal hay ahí!"*.

   Los dos síntomas eran UNA sola causa: había DOS cuadros, uno adentro del otro, y cada uno manejaba un eje. El
   de afuera (.grilla-popup) tenía `overflow-y: auto` y el de adentro (.tabla-contenedor) `overflow-x: auto`.

     · la barra de costado vivía en el borde de abajo del cuadro de ADENTRO, que mide lo que miden las 50 filas
       (unos 1.700 px): para alcanzarla había que bajar hasta el final;
     · y el título `sticky` se pega al cuadro que scrollea más cerca, que era el de adentro — el que NO se
       desplaza a lo alto. Por eso al bajar se iban los títulos.

   Ahora las dos barras son del MISMO cuadro, el de afuera: el título se pega a él y la barra de costado queda en
   su borde de abajo, siempre a la vista. El de adentro conserva el marco y deja de ser un cuadro que scrollea. */
.grilla-popup { height: 50vh; overflow: auto; }
.grilla-popup > .tabla-contenedor { overflow: visible; }
.grilla-popup table.tabla thead th { position: sticky; top: 0; z-index: 2; }
/* La columna de casilleros (Word 6.2, marcas 8, 9 y 18): ancho fijo, centrada,
   y no se mueve ni se ordena — es la misma columna de selección que tienen las
   grillas de Windows que dejan operar de a varios. */
table.tabla th.check-col, table.tabla td.check-col { width: 34px; min-width: 34px; text-align: center; padding-left: 6px; padding-right: 6px; }
table.tabla td.check-col input, table.tabla th.check-col input { cursor: pointer; }
table.tabla .principal { font-weight: 500; }
table.tabla .secundario { font-size: var(--letra-chica); color: var(--text-secondary); }
/* UN CAMPO CON UN DATO QUE NO SIRVE SE TIENE QUE VER (#659 punto 5, Diego 14/10/2026): *"Me deja escribir 110
   por ejemplo! Y cuando pasa eso no toma el descuento porque claramente es más del 100%… debería arrojar un
   error"*. La clase `invalido` se venía poniendo desde el 13/10 en el "% Desc." de la orden de compra, pero NO
   TENÍA CSS: el único aviso era el globo del mouse, que nadie mira mientras tipea. */
.entrada.invalido, input.invalido { border-color: var(--bg-danger); box-shadow: 0 0 0 2px rgba(225, 29, 72, 0.18); }
.vacio { padding: 32px; text-align: center; color: var(--text-muted); }
/* #471: la lista vacía por culpa del filtro dice qué probar y ofrece limpiarlo. */
.vacio .sugerencia-vacio { margin-top: 4px; font-size: var(--letra-chica); }
.vacio .limpiar-filtros { margin-top: 12px; }
/* #391: el destello de lo que se acaba de copiar (botón derecho o Ctrl+C). */
@keyframes majo-copiada { from { background: var(--bg-seleccion-suave); } to { background: transparent; } }
table.tabla td.copiada, table.tabla tr.copiada td { animation: majo-copiada 0.8s ease-out; }
/* Web 10.1 punto 77: el renglón marcado con las flechas (↓, AvPág…). El mismo
   pintado que el renglón marcado de los buscadores (.resaltado, más abajo). La
   grilla recibe el foco para escuchar las teclas: el recuadro del foco no
   hace falta, lo que se ve es el renglón. */
table.tabla tbody tr.fila-teclado td { background: var(--bg-seleccion-suave); }
table.tabla tbody tr.fila-teclado td:first-child { box-shadow: inset 3px 0 0 var(--border-input-focus); }
.tabla-contenedor:focus { outline: none; }

/* ============ columnas que se mueven, se agrandan y se achican (23/09) ============
   Diego: *"Los títulos de todas las grillas de módulos o grillas de pop ups
   tengo que poder ordenar, mover, agrandar, achicar, como funciona en win"*.
   El motor está en grilla_columnas.js; acá va nada más que cómo se ve.

   DOS COSAS QUE NO SE PUEDEN ROMPER DESDE ACÁ:
   - el renglón mide 30 px porque Diego contó las filas: la manija es ABSOLUTA
     adentro del título, así que no agrega ni un pixel de alto;
   - el encabezado va pegado arriba (position: sticky, más abajo) y los títulos
     van centrados (4.2): la manija no cambia ni una cosa ni la otra porque no
     ocupa lugar en el texto. */
table.tabla.columnas-interactivas { table-layout: fixed; }
/* Con el ancho fijo, un texto más largo que su columna se corta con puntitos
   en vez de empujar la grilla — igual que en Majo de Windows. */
table.tabla.columnas-interactivas th,
table.tabla.columnas-interactivas td { overflow: hidden; text-overflow: ellipsis; }
/* Las celdas de dos renglones (producto + SKU, rubro + categoría) tienen el
   texto adentro de un div: el corte con puntitos hay que pedírselo a ellos
   también, no alcanza con la celda. */
table.tabla.columnas-interactivas td div { overflow: hidden; text-overflow: ellipsis; }
table.tabla th.col-interactiva { user-select: none; -webkit-user-select: none; }
/* La sobra a la derecha de la última columna: la misma franja vacía que deja
   Qt cuando las columnas no llegan a tapar el ancho de la ventana. */
table.tabla th.relleno, table.tabla td.relleno { padding: 0; }
.manija-col { position: absolute; top: 0; right: 0; bottom: 0; width: 8px; cursor: col-resize; touch-action: none; z-index: 3; }
.manija-col::after { content: ""; position: absolute; top: 5px; bottom: 5px; right: 3px; width: 1px; background: var(--border-page-card); }
.manija-col:hover::after { width: 2px; background: var(--acento, var(--bg-primary)); }
/* En el celular el dedo no tiene la puntería del mouse: la manija se ensancha
   sola donde el apuntador es "grueso" (regla fija del 22/09: todo tiene que
   seguir siendo usable en 390 px). */
@media (pointer: coarse) { .manija-col { width: 14px; } }
table.tabla.redimensionando, table.tabla.redimensionando th { cursor: col-resize; }
table.tabla.moviendo-columna, table.tabla.moviendo-columna th { cursor: grabbing; }
table.tabla th.arrastrando { opacity: 0.4; }
/* Dónde va a caer la columna que se está arrastrando. Desde el 23/09 es el
   MISMO punteado de las pestañas (Diego: *"donde se pone aparece como
   punteado"*) y no una rayita de 3 px: el recuadro dice "va en el lugar de
   ésta" y la barra gruesa del costado, de qué lado. Las dos cosas hacen falta
   —el recuadro solo no distingue izquierda de derecha—, y con una columna de
   90 px la rayita finita directamente no se veía. */
table.tabla th.destino-izq, table.tabla th.destino-der { outline: 2px dashed var(--acento, var(--bg-primary)); outline-offset: -2px; }
table.tabla th.destino-izq { box-shadow: inset 4px 0 0 var(--acento, var(--bg-primary)); }
table.tabla th.destino-der { box-shadow: inset -4px 0 0 var(--acento, var(--bg-primary)); }
/* Acá estaba `.paginador`, la barra al PIE que usaba sólo Stock. Se borró el
   23/09/2026 junto con ui.js::paginador: la paginación de los 15 módulos va
   arriba, en el renglón de filtros, como en Majo Windows. */

/* ============================ pastillas de estado (las de Majo) ============================ */
/* Diego (1.2): *"se ven como medio pixeladas"*. Eran 11 px en negrita dentro
   de una cápsula chica: el texto quedaba apretado contra el borde. Ahora 12 px,
   peso 600, un poco más de aire y un borde suave que le da filo. */
/* ------------------------------------------------------- el popup del contacto
   Uno solo para el POS y la Orden de venta (views/_contacto.js). Alto FIJO para
   la lista: filtre lo que filtre, el popup no se mueve (Word 6.1). Los dos
   botones de abajo se reparten el ancho mitad y mitad, del alto de Majo. */
.lista-contactos { height: 320px; overflow-y: auto; }
.pie-contacto { display: flex; gap: 8px; width: 100%; }
.pie-contacto .boton { flex: 1 1 0; min-height: 40px; }
@media (max-height: 640px) { .lista-contactos { height: 240px; } }
/* La leyenda "Mostrando los primeros 80 de N contactos…" (#475). Su renglón
   está SIEMPRE reservado, con o sin texto: si apareciera y desapareciera, el
   popup se movería mientras se busca (directiva 37). */
.recorte-contactos { min-height: 2.6em; font-size: var(--letra-chica); }

/* ------------------------------------ la ficha de EDITAR contacto / proveedor
   Web 10.1, puntos 6, 20 y 33. Alto FIJO en la PC: al pasar de un contacto a
   otro con ‹ › el popup no se estira ni se encoge, así las flechas y Guardar
   no se mueven de lugar; lo que no entra se recorre adentro. En el celular
   queda elástico (ahí el popup ya ocupa casi toda la pantalla). */
@media (min-width: 700px) {
  .modal.ficha-editar-alto-fijo { height: min(92vh, 860px); }
  .modal.ficha-editar-alto-fijo .cuerpo-modal { flex: 1 1 auto; min-height: 0; }
}
.recorrer-ficha { display: flex; align-items: center; gap: 6px; margin-right: auto; }
.recorrer-ficha-numero { min-width: 70px; text-align: center; font-variant-numeric: tabular-nums; }
/* En el celular no entran las flechas, Cancelar y Guardar en un renglón: las
   flechas van en el suyo, arriba, y Cancelar y Guardar quedan juntos abajo. */
@media (max-width: 560px) { .recorrer-ficha { flex: 1 0 100%; justify-content: center; margin-right: 0; } }
.bloque-ficha-contacto { margin-top: 12px; }

/* La ficha del CONTACTO en pestañas (Word 10.2, hoja 9: *"pondría el título y al
   costado el campo para completar y separado como está en win por categoría…
   Separarlo en pestañas"*). Las pestañas son los grupos de Windows; en cada una,
   el título a la izquierda y el campo al lado. El popup mide lo mismo en todas
   las pestañas y lo que no entra se recorre adentro de la pestaña. */
.ficha-contenedor { display: flex; flex-direction: column; min-height: 0; }
.ficha-pestanas { display: flex; flex-direction: column; gap: 14px; min-height: 0; }
.ficha-pestanas > .solapas { flex: none; }
.ficha-pestanas .panel-pestana { display: flex; flex-direction: column; gap: 10px; min-height: 0; }
.ficha-pestanas .panel-pestana.oculto { display: none; }
.ficha-pestanas :is(.panel-pestana, .recuadro-pestana) > .campo {
  display: grid; grid-template-columns: minmax(150px, 220px) minmax(0, 1fr);
  column-gap: 16px; row-gap: 4px; align-items: center; margin: 0;
}
.ficha-pestanas :is(.panel-pestana, .recuadro-pestana) > .campo > :not(label) { grid-column: 2; }
.ficha-pestanas :is(.panel-pestana, .recuadro-pestana) > .campo > label { grid-column: 1; margin: 0; }
.ficha-pestanas :is(.panel-pestana, .recuadro-pestana) > .campo:has(> textarea), .ficha-pestanas .panel-pestana > .campo.bloque-ficha-contacto { align-items: start; }
.ficha-pestanas :is(.panel-pestana, .recuadro-pestana) > .campo > input[type="checkbox"] { justify-self: start; }
.ficha-pestanas :is(.panel-pestana, .recuadro-pestana) > .nota-pestana { margin-top: -4px; }
/* Los recuadros con título de una pestaña (la de Varios del contacto, 03/10):
   un tema por recuadro. Con un solo campo, el título es el rótulo y el campo va
   a lo ancho. Bordes y márgenes chicos: la pestaña tiene el alto de todas. */
.recuadro-pestana { display: flex; flex-direction: column; gap: 8px; min-width: 0; margin: 0; padding: 4px 12px 10px; border: 1px solid var(--border-page-card); border-radius: var(--radio-campo); }
.recuadro-pestana > legend { padding: 0 6px; font-size: var(--letra-chica); font-weight: 700; color: var(--text-secondary); letter-spacing: 0.6px; text-transform: uppercase; }
.ficha-pestanas .recuadro-pestana.un-solo-campo > .campo { grid-template-columns: minmax(0, 1fr); }
.ficha-pestanas .recuadro-pestana.un-solo-campo > .campo > label { display: none; }
.ficha-pestanas .recuadro-pestana.un-solo-campo > .campo > :not(label) { grid-column: 1; }
/* La guía del correo (Configuración → Correo): qué pide el proveedor y los pasos
   para sacar la contraseña de aplicación, en la misma pantalla (03/10). */
.guia-correo { display: flex; flex-direction: column; gap: 4px; margin-top: 10px; padding: 10px 12px; border: 1px solid var(--border-page-card); border-radius: var(--radio-campo); }
.guia-correo:empty { display: none; }
.pasos-correo { margin: 0; padding-left: 22px; display: flex; flex-direction: column; gap: 3px; }
/* Los tildes de stock y estado del producto, los tres en un renglón (03/10). */
.tildes-en-linea { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 22px; }
.tildes-en-linea > label.recordar { display: inline-flex; align-items: center; gap: 6px; margin: 0; }
/* Descuentos especiales ocupa su pestaña entera: sin título repetido (es el de la pestaña). */
.ficha-pestanas .panel-pestana.a-lo-ancho > .campo { display: block; }
.ficha-pestanas .panel-pestana.a-lo-ancho > .campo > label { display: none; }
@media (min-width: 700px) {
  .modal.ficha-editar-alto-fijo.ficha-en-pestanas { height: min(92vh, 640px); }
  /* La del producto tiene diez campos en "Datos generales": un poco más alta
     para que entren todos sin scroll (#572). */
  .modal.ficha-editar-alto-fijo.ficha-en-pestanas.ficha-producto { height: min(92vh, 720px); }
  /* Con el costo de lista y los tres descuentos (#637), "Compra y costo" se pasaba 16 px y aparecía el scroll.
     Los renglones de la ficha del producto, apenas más juntos (Diego, 11/10/2026: *"juntá apenas todo un poquito
     como para que entre sin el scroll"*): 7 px en vez de 10 entre campo y campo, en sus tres pestañas. */
  .modal.ficha-en-pestanas.ficha-producto .ficha-pestanas .panel-pestana { gap: 7px; }
  .modal.ficha-en-pestanas .cuerpo-modal { display: flex; flex-direction: column; overflow: hidden; }
  .modal.ficha-en-pestanas .ficha-contenedor, .modal.ficha-en-pestanas .ficha-pestanas { flex: 1 1 auto; }
  .modal.ficha-en-pestanas .panel-pestana { flex: 1 1 auto; overflow-y: auto; padding-right: 4px; }
}
/* En el celular, el título arriba del campo (no entran los dos en un renglón). */
@media (max-width: 560px) {
  .ficha-pestanas :is(.panel-pestana, .recuadro-pestana) > .campo { grid-template-columns: minmax(0, 1fr); }
  .ficha-pestanas :is(.panel-pestana, .recuadro-pestana) > .campo > :not(label), .ficha-pestanas :is(.panel-pestana, .recuadro-pestana) > .campo > label { grid-column: 1; }
}
/* Percepciones: la lista con un tilde por cada una, de alto fijo con scroll. */
.lista-percepciones { display: flex; flex-direction: column; gap: 4px; height: 110px; overflow-y: auto; border: 1px solid var(--border-page-card); border-radius: var(--radio-campo); padding: 6px 10px; }
/* Cada percepción es una opción para tildar, no un rótulo: sin las mayúsculas
   chicas de `.campo label`. */
.lista-percepciones label.recordar { font-size: var(--letra-normal); font-weight: 400; letter-spacing: normal; text-transform: none; color: var(--text-primary); }
/* #643: en la ficha del cliente, cada percepción con lo que dice el padrón (el ✓ y la fecha) y su campo "a mano". */
.lista-percepciones.con-padron { height: 160px; gap: 10px; }
.renglon-percepcion { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.renglon-percepcion-padron { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding-left: 26px; min-width: 0; }
.renglon-percepcion-padron > .suave { min-width: 0; }
.renglon-percepcion-padron > .entrada { flex: none; }
/* #644: en la ficha del proveedor, el ✓ y la fecha del padrón de cada impuesto de IIBB, debajo de su renglón. */
.renglon-impuesto-estado { flex: 1 0 100%; }
/* Descuentos especiales: la grilla tiene su alto y scrollea ADENTRO. */
.descuentos-contacto .tabla-contenedor { height: 170px; overflow: auto; }
/* Con la ficha de alto fijo (compu), la grilla ocupa TODO el alto libre de la
   pestaña, siempre el mismo, y lo que no entra se recorre adentro: el texto
   arriba y "Agregar descuento" abajo quedan a la vista (Diego, 02/10: "que
   tome todo el alto del popup, que sea fijo lo que entre y luego aplica
   scroll"). En el celular, los 170 px de arriba. */
@media (min-width: 700px) {
  .modal.ficha-en-pestanas .panel-pestana.a-lo-ancho:has(.descuentos-contacto) { overflow: hidden; }
  .modal.ficha-en-pestanas .panel-pestana.a-lo-ancho > .bloque-ficha-contacto:has(.descuentos-contacto) {
    display: flex; flex-direction: column; gap: 8px; flex: 1 1 auto; min-height: 0; margin: 0;
    /* a lo ancho: con el `align-items: start` de los bloques de la ficha, la
       grilla se medía al ancho de su contenido y las columnas quedaban angostas */
    align-items: stretch;
  }
  .modal.ficha-en-pestanas .descuentos-contacto { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
  .modal.ficha-en-pestanas .descuentos-contacto .tabla-contenedor { height: auto; flex: 1 1 auto; min-height: 120px; }
}
/* El cartel de "Descuento especial": el MISMO alto con "Toda la lista" que con
   "Un producto puntual" (directiva 37); si en el celular no entra, se recorre
   adentro. */
.dialogo-descuento-contacto { height: 460px; overflow-y: auto; }
/* Los productos encontrados, uno por renglón (como la lista de Windows): un
   nombre largo se corta con "…" en vez de salirse del popup. */
.lista-productos-descuento { display: flex; flex-direction: column; gap: 4px; height: 150px; overflow-y: auto; margin-top: 6px; }
.lista-productos-descuento .boton { flex: none; display: block; width: 100%; min-width: 0; text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; line-height: calc(var(--alto-boton) - 10px); }
/* El top 5 de productos de la ficha (#490). */
.top-productos-contacto .renglon-top { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 4px 12px; padding: 4px 0; border-bottom: 1px solid var(--dash-separator); }
.top-productos-contacto .renglon-top:last-of-type { border-bottom: none; }
.top-productos-contacto .renglon-top .num { font-weight: 700; white-space: nowrap; }

/* ------------------------------------------------- las PASTILLAS de un detalle
   pastillas.js. Un recuadro del alto de los botones, título chico en negrita
   y el valor al lado en una línea, cortado con "…" (ui/utils/pastilla_dato.py
   de Windows). Se acomodan solas según el ancho: 4 por renglón en el detalle
   de venta de una PC, 1 en el celular. Se arrastran para cambiarlas de orden. */
.grilla-pastillas { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 6px; }
.pastilla-dato { display: flex; align-items: center; gap: 6px; min-width: 0; min-height: var(--alto-boton); padding: 0 10px; border-radius: 10px; background: var(--bg-button); border: 1px solid var(--border-button); }
.pastilla-dato .titulo { font-size: var(--letra-chica); font-weight: 700; white-space: nowrap; color: var(--text-secondary); }
.pastilla-dato .valor { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.grilla-pastillas .pastilla-dato { cursor: grab; touch-action: pan-y; user-select: none; -webkit-user-select: none; }
/* #559: con el mouse, el valor se selecciona y se copia (se arrastra desde el título). */
@media (hover: hover) and (pointer: fine) {
  .grilla-pastillas .pastilla-dato .valor { cursor: text; user-select: text; -webkit-user-select: text; }
}
/* Modo compacto (el detalle de venta, Word 5.4): sin marco ni alto de botón,
   un renglón "Título: valor" por dato, más columnas. Se siguen ordenando
   arrastrando (mismo motor, pastillas.js). */
.grilla-pastillas.compacta { grid-template-columns: repeat(auto-fill, minmax(225px, 1fr)); gap: 3px 16px; }
.grilla-pastillas.compacta .pastilla-dato { min-height: 0; padding: 0; border: none; border-radius: 0; background: transparent; gap: 5px; line-height: 1.4; }
.grilla-pastillas.compacta .pastilla-dato .titulo::after { content: ":"; }
.grilla-pastillas .pastilla-dato.arrastrando { opacity: 0.4; }
.grilla-pastillas .pastilla-dato.destino-izq, .grilla-pastillas .pastilla-dato.destino-der { outline: 2px dashed var(--acento, var(--bg-primary)); outline-offset: -2px; }
.grilla-pastillas .pastilla-dato.destino-izq { box-shadow: inset 4px 0 0 var(--acento, var(--bg-primary)); }
.grilla-pastillas .pastilla-dato.destino-der { box-shadow: inset -4px 0 0 var(--acento, var(--bg-primary)); }
.fantasma-arrastre.de-pastilla { border-radius: 10px; }
/* En el celular van de a DOS por renglón: de a una, 13 pastillas apiladas
   empujaban la grilla de productos fuera de la pantalla. El valor se corta con
   "…" y se lee entero manteniendo el dedo (title). */
@media (max-width: 700px) {
  .grilla-pastillas { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 4px; }
  .pastilla-dato { padding: 0 6px; gap: 4px; }
}

/* El pie del detalle de venta: las observaciones (si las hay) a la izquierda y
   la caja de totales a la derecha, en la misma línea (Word 5.3, la captura de
   "cómo debería verse" de Diego). */
.pie-detalle { display: flex; gap: 16px; align-items: stretch; flex-wrap: wrap; margin-top: 12px; }
.pie-detalle .caja-totales { flex: 0 0 360px; max-width: 100%; margin-left: auto; }
/* #662 punto 9: el cuadro se estira al alto de su hermano (el de totales) y el texto lo llena — antes el
   texto cortaba a 4 renglones y abajo quedaba el hueco que Diego marcó en rojo. El alto lo sube
   ui.js::llenarCuadrosDeTexto después de que el navegador acomoda, porque acá no se puede saber. */
.caja-observaciones { flex: 1 1 260px; min-width: 0; display: flex; gap: 8px; align-items: stretch; padding: 8px 10px; border-radius: 10px; background: var(--bg-button); border: 1px solid var(--border-button); }
.caja-observaciones .titulo { font-size: var(--letra-chica); font-weight: 700; white-space: nowrap; color: var(--text-secondary); padding-top: 2px; }
/* #659 punto 9 (Diego, 14/10/2026): *"No sé dónde decís que hiciste el cambio, pero sigue igual… se puede
   agrandar cuando se hace la OC, pero en el detalle se sigue viendo cortado"*. Tenía razón: el arreglo del 13/10
   fue en el CAMPO donde se escriben (que crece con el texto), y el detalle es otra cosa — un cuadro de sólo
   lectura que recortaba a cuatro renglones con `-webkit-line-clamp` y escondía el resto sin decir nada.

   Ahora el cuadro mide siempre lo mismo (directiva 37: el popup no cambia de tamaño según lo que tenga adentro)
   y, si el texto no entra, SE DESPLAZA ADENTRO (directiva 39). Así no se esconde nada y el popup no se mueve. */
.caja-observaciones .texto { flex: 1; min-width: 0; max-height: calc(4 * 1.5em); overflow-y: auto; white-space: pre-wrap; overflow-wrap: anywhere; scrollbar-width: thin; }
/* Word 12.1, "Otros" del final (12/10/2026): el detalle de la compra como el de la venta. Productos: 6 renglones a la
   vista; comprobantes y pagos: 3; después, scroll ADENTRO de la grilla. Nunca a lo ancho: las columnas se reparten
   (grilla_columnas.js, con una columna flexible que corta con "…"). El renglón mide lo mismo que en el detalle de la
   venta (30 px y su línea); la cabecera, 31. Los cuadros de costos: 3 renglones que crecen hasta 6. */
.detalle-compra .titulo-grilla-detalle { margin: 10px 0 4px; font-size: var(--letra-normal); flex: none; }
/* #662 punto 15d (Diego, 15/10/2026): *"Si agrando por ejemplo la columna de Producto, TOTAL se va fuera del
   popup y no pone el scroll horizontal: simplemente se va de pantalla. Debería aparecer el scroll (como en
   ventas)"*. Era este `overflow-x: hidden`, puesto antes de la directiva 101 —la regla que él mismo corrigió
   el 14/10: primero se compacta, y si aun así no entra (o si él agranda una columna a mano), va la barra. */
.tabla-contenedor.detalle-compra-grilla { flex: none; overflow-x: auto; overflow-y: auto; }
/* #662 punto 15a: N renglones EXACTOS, ni uno más (Diego: *"6 renglones MÁXIMO, y luego si hay más, scroll"*).
   El renglón mide 43 px desde el punto 15b, que le devolvió el renglón chico de abajo (SKU · Cód. prov.). Es un
   alto FIJO a propósito y no medido: así el popup mide siempre lo mismo, tenga la compra 1 renglón o 30, y los
   botones de abajo no se mueven (lo que pidió el 13/10). */
.tabla-contenedor.detalle-compra-grilla.renglones-6 { height: calc(34px + 6 * 43px); }
.tabla-contenedor.detalle-compra-grilla.renglones-3 { height: calc(34px + 3 * 43px); }
.tabla-contenedor.detalle-compra-grilla.renglones-3-a-6 { min-height: calc(33px + 3 * 31px); max-height: calc(33px + 6 * 31px); }
.tabla-contenedor.detalle-compra-grilla thead th { position: sticky; top: 0; z-index: 1; }
table.tabla.tabla-sin-ancho { table-layout: fixed; }
table.tabla.tabla-sin-ancho td, table.tabla.tabla-sin-ancho th { overflow: hidden; text-overflow: ellipsis; }
/* Un "Ver" adentro de un renglón: con pinta de enlace, para que el renglón no crezca como con un botón. */
.enlace-en-grilla { border: none; background: none; padding: 0; margin: 0; color: var(--bg-primary); cursor: pointer; font: inherit; line-height: inherit; text-decoration: underline; }
.enlace-en-grilla:hover { opacity: 0.8; }
/* El detalle de la compra mide SIEMPRE lo mismo y sus botones quedan pegados abajo (Diego, 13/10/2026).

   CÓMO SE LOGRA ESO CAMBIÓ el 14/10 (#659 punto 13), porque la primera forma salió mal: *"El detalle de una OC
   ahora es enorme y tiene mucho aire entre comprobante y pagos y los botones de abajo. ¡Ese espacio no tiene que
   estar! ¡Juntar todo! La grilla tiene que tener lugar para 6 renglones (grilla fija). Sólo si el detalle supera
   los 6 renglones, recién ahí pone el scroll"*.

   Antes: el popup tenía un alto FIJO de 700 px y la grilla era elástica, para que se comiera lo que sobrara.
   Medido el 14/10 con una compra de un renglón: la grilla se quedaba en su mínimo de 3 renglones (126 px) y
   abajo quedaban **270 px de aire** hasta los botones. El elástico no funcionaba y el popup era enorme igual.

   Ahora al revés, que es lo que él pide: la grilla mide 6 renglones SIEMPRE (y de ahí en más se desplaza adentro)
   y el popup mide lo que mide su contenido, con el tope de la pantalla. Como la grilla —que era lo único que
   cambiaba de alto según la compra— ahora es fija, el popup sigue midiendo lo mismo de una compra a otra. */
/* #662 punto 15a (Diego, 15/10/2026, con su dibujo de "cómo debería quedar"): *"Que el espacio para grilla sea
   de 6 renglones MÁXIMO, y luego si hay más, scroll. Ahora hay espacio para muchos más"*. Es la respuesta a la
   pregunta que le hice en el 12.4: quería 6 FIJOS, no 6 de piso.

   Entonces el alto fijo del popup se va: ya no hace falta. Era lo que sostenía la grilla elástica, y la grilla
   elástica es justo lo que hacía que creciera hasta 11 renglones. Con la grilla clavada en 6, el popup mide lo
   que mide su contenido (con el tope de 92vh de cualquier popup) y los botones SIGUEN SIN MOVERSE entre una
   compra y otra. OJO, y por eso el alto fijo se queda: lo que cambia de alto entre una compra y otra NO es sólo
   la grilla — el cuadro de totales tiene más renglones cuando la compra tiene pagos (medido: 145 px contra 108),
   y el de Observaciones se estira con él. Con el popup al aire eso movía los botones 39 px al pasar de una
   compra a la siguiente con las flechitas, que es justo lo que él pidió que no pasara el 13/10. Así que el alto
   fijo sigue, y lo que cambió es que la grilla ya no es elástica: mide sus 6 renglones exactos y no se come el
   lugar que sobra. Medido: con 700 px el contenido entra casi justo y no queda el aire del #659 punto 13. */
/* SEGUNDA VUELTA (Diego, 16/10/2026, Word 12.5 con captura: *"El espacio marcado en rojo hay que sacarlo!
   tiene que quedar sin ese espacio vacio! pero todo lo demas respetalo! que no se agrande mas que eso! no
   entiendo porque no lo podes hacer si en ventas funciona igual que aca"*).

   Y la razón por la que no se podía es que ESTA REGLA NUNCA SE APLICABA. En views/compras.js había, desde el
   13/10, un alto puesto a mano sobre el popup (`m.caja.style.height = "min(94vh, 940px)"`), y un estilo en
   línea le gana siempre a la hoja de estilos: el popup medía 874 px (92vh) en vez de los 700 de acá. Medido en
   PRUEBAS: contenido 718, hueco 152. Ese 152 es exactamente lo que él marcó en rojo. El alto a mano ya se fue.

   Cómo queda, que es como funciona Ventas (lo que él dijo): alto fijo + la grilla ELÁSTICA. El alto se calculó
   con la medición (874 − 152 = 722), así que con la compra típica la grilla cae justo en sus 6 renglones y no
   sobra nada. Y si una compra tiene más renglones de totales (IIBB, otros impuestos, redondeo), el que cede es
   la grilla —muestra 5 y se desplaza adentro—, no los botones: siguen clavados abajo, que es lo del 13/10. */
.modal.detalle-compra-alto-fijo { height: min(92vh, 722px); }
.modal.detalle-compra-alto-fijo .cuerpo-modal { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
/* EL ESLABÓN QUE FALTABA, y es el que explica los 270 px de aire del #659 punto 13: entre `.cuerpo-modal` y
   `.detalle-compra` hay un DIV SIN CLASE (el que `modal()` recibe como cuerpo y después se rellena). Como no lo
   alcanzaba ninguna regla, se quedaba en `flex: 0 1 auto`, no crecía, y el alto que le sobraba al popup moría ahí
   adentro: medido, 509 px de contenido en un cuerpo de 700. Toda la cadena tiene que poder crecer. */
.modal.detalle-compra-alto-fijo .cuerpo-modal > div { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.modal.detalle-compra-alto-fijo .detalle-compra { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
/* La grilla de Productos se queda con lo que sobra, y su PISO son 6 renglones (antes 3). Ese 3 era el bug del
   #659 punto 13: con una compra de un renglón la grilla se plantaba en 126 px y quedaban 270 px de aire hasta los
   botones. Con 6 de piso no sobra nada, y si la compra tiene más renglones de los que entran, se desplaza adentro.

   Se probaron antes `height: auto` y `height: fit-content` en el popup para que midiera lo de su contenido: NO
   sirven, se estira igual hasta el tope (medido: 810 px de alto con 159 de aire). El alto fijo + la grilla
   elástica es lo que funciona, y de paso es lo que mantiene los botones quietos (pedido del 13/10). */
/* #662 punto 15a: la grilla NO es elástica. Mide sus 6 renglones y, con más, se desplaza adentro. */
/* La grilla vuelve a ser ELÁSTICA (como la del detalle de la venta), pero con TECHO de 6 renglones: es el
   "6 renglones máximo" que pidió en el 12.4 y, a la vez, lo que absorbe el espacio que sobre, para que no
   quede el hueco de abajo. El piso de 3 es para una pantalla baja, donde el popup no llega a los 722. */
.modal.detalle-compra-alto-fijo .detalle-compra > .tabla-contenedor.detalle-compra-grilla,
.modal.detalle-compra-alto-fijo .detalle-compra > div > .tabla-contenedor.detalle-compra-grilla {
  flex: 1 1 auto; height: auto;
  min-height: calc(34px + 3 * 43px); max-height: calc(34px + 6 * 43px);
}
/* Los renglones "Comprobantes  2  [Ver]" y "Pagos  —" del detalle de la compra (Diego, 13/10/2026): el lugar queda
   RESERVADO aunque no haya ninguno, así el popup mide siempre lo mismo y los botones de abajo no se mueven. */
.renglones-ver-mas { display: flex; gap: 10px; margin-top: 10px; flex: none; flex-wrap: wrap; }
.renglon-ver-mas { flex: 1 1 200px; min-width: 0; display: flex; gap: 8px; align-items: center; min-height: 36px;
  padding: 0 10px; border-radius: 10px; background: var(--bg-button); border: 1px solid var(--border-button); }
.renglon-ver-mas .titulo { font-size: var(--letra-chica); font-weight: 700; color: var(--text-secondary); }
.renglon-ver-mas .boton { margin-left: auto; }
/* La ficha de un comprobante o de un pago: datos en renglones "Título: valor", como el detalle de la venta. */
.datos-en-renglones { display: flex; flex-direction: column; gap: 2px; }
.renglon-dato { display: flex; gap: 8px; align-items: baseline; min-width: 0; }
.renglon-dato .titulo { font-size: var(--letra-chica); font-weight: 700; color: var(--text-secondary); white-space: nowrap; }
.renglon-dato .valor { min-width: 0; overflow-wrap: anywhere; }
/* En el celular la grilla se corre de costado ADENTRO de su recuadro (como la del detalle de la venta): la pantalla no. */
/* (La regla de celular que ponía overflow-x: auto se fue con el #662 punto 15d: ahora es auto siempre.) */
/* Los detalles con botones propios al pie (venta, compra): el "Cerrar" no se estira cuando esos botones bajan de renglón. */
.modal .pie-modal > .grupo-botones ~ .boton { align-self: flex-end; }

/* ---------------------------------------------- la GRILLA DE CARGA (Orden de venta)
   Word 5.3, Diego: *"este diseño de los campos a completar en modo pastilla no
   me gusta… si te fijás en el de Windows, muestra el recuadro del que está
   seleccionado solamente; una vez que salgo de ese campo se va y queda como
   grilla, sin separaciones ni nada (básicamente como muestra el detalle de
   venta, sin ningún recuadrito)"*. Los campos van sin marco; el marco aparece
   sólo en el que tiene el cursor (y apenas, al pasar el mouse). */
table.tabla.grilla-carga { table-layout: fixed; }
/* Si una celda no entra, TIENE QUE NOTARSE. Medido el 13/10/2026 en Chromium: una columna de plata apretada a 58 px
   mostraba "$ 1.234.5" en vez de "$ 1.234.567,89" — cortada a la derecha, sin ninguna marca, o sea un número creíble
   y falso. Con el apretado de columnas del #651 (punto 55) eso se puede dar más seguido, así que el corte ahora se
   ve (…) y el valor entero queda en el globo del mouse. */
table.tabla.grilla-carga td { padding: 2px 4px; overflow: hidden; text-overflow: ellipsis; }
/* Los renglones de carga, pegados como los de una grilla (Diego, Word 5.4:
   *"Juntar más los productos. Siguen muy separados! Que usen la misma
   distancia que hay entre los renglones en una grilla!"*): el campo mide 28
   px adentro de un renglón de 32, como el `.compacta` de la devolución. */
table.tabla.grilla-carga .entrada { border-color: transparent; background: transparent; box-shadow: none; padding: 2px 8px; min-height: 28px; }
/* La cruz de quitar un renglón: la MISMA de las pestañas de los módulos
   (Diego, Word 5.4), no un botón con marco. */
table.tabla.grilla-carga .cerrar-renglon { border: none; background: transparent; color: inherit; cursor: pointer; opacity: 0.55; font-size: var(--letra-subtitulo); line-height: 1; padding: 0 4px; border-radius: 6px; }
table.tabla.grilla-carga .cerrar-renglon:hover { opacity: 1; background: var(--bg-danger); color: #fff; }
/* La celda que SE EDITA adentro de una grilla de sólo lectura ("A devolver"):
   sin la pastilla, Diego no sabía cuál tocar (Word 5.4). Un fondo apenas
   teñido y una rayita abajo la distinguen sin volver a ponerle marco. */
table.tabla td.celda-editable { background: color-mix(in srgb, var(--bg-primary) 8%, transparent); }
table.tabla td.celda-editable .entrada { border-bottom-color: var(--border-input); border-radius: 0; }
table.tabla.grilla-carga .entrada:hover:enabled { border-color: var(--border-input); background: transparent; }
table.tabla.grilla-carga .entrada:focus { border-color: var(--border-input-focus); background: var(--bg-input); box-shadow: 0 0 0 2px color-mix(in srgb, var(--border-input-focus) 30%, transparent); }
table.tabla.grilla-carga .entrada:disabled { opacity: 0.85; }
table.tabla.grilla-carga .entrada.num { text-align: right; }
/* #662 punto 10c: la Cantidad de la orden de compra, centrada con su título. */
table.tabla.grilla-carga .entrada.num.centrada { text-align: center; }
table.tabla.grilla-carga th.centrada, table.tabla.grilla-carga td.centrada { text-align: center; }
/* La grilla de la Orden de venta (Word 10.1, punto 9): arranca con el alto de 6
   renglones, crece hasta 10 y de ahí se desplaza adentro. 34 px de títulos +
   32 px por renglón. */
.tabla-contenedor.grilla-orden-6-a-10 { flex: none; min-height: calc(34px + 6 * 32px); max-height: calc(34px + 10 * 32px); overflow: auto; }
/* Orden de venta: abajo del producto, el descuento especial del cliente si lo
   tomó el renglón (29/09/2026). Vacía no ocupa lugar. */
/* #659 punto 4 (Diego, 14/10/2026): *"¿Se puede achicar un poco la distancia entre la línea que agregamos y la
   del producto? Más que nada para que entren más renglones y no sean tan grandes"*. El renglón con la línea de
   abajo pasa de 48 px a 43: la línea se pega al nombre (sin el relleno de arriba, que era del campo) y va en
   line-height 1,1. */
.grilla-carga .nota-renglon { font-size: var(--letra-chica); line-height: 1.1; color: var(--text-secondary); padding: 0 9px 1px; margin-top: -3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Con la nota, el renglón es más alto: todo arriba, así los números quedan en
   la MISMA línea que el nombre del producto (centrados quedaban 9 px más
   abajo) y la nota cuelga sola. 28 px = el alto del campo. */
table.tabla.grilla-carga tr:has(.nota-renglon:not(:empty)) > td { vertical-align: top; }
table.tabla.grilla-carga tr:has(.nota-renglon:not(:empty)) > td.num { line-height: 28px; }
.grilla-carga .nota-renglon:empty { display: none; }
/* #662 punto 15b: el mismo renglón chico (SKU · Cód. prov.) en el DETALLE de la compra, que no es una
   grilla de carga. Mismo formato, sin el padding del campo editable. */
.detalle-compra-grilla .nota-renglon { font-size: var(--letra-chica); line-height: 1.1; color: var(--text-secondary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-height: 1.1em; }
.detalle-compra-grilla td .con-nota { min-width: 0; }
/* El renglón de la PROMO debajo del producto (Orden de venta y presupuesto
   desde el módulo, 29/09/2026): como el "↳ Promo" del carrito del POS — más
   tenue, pegado a su producto (sin la raya entre los dos) y con los números
   alineados con los de arriba (el texto del producto y la cantidad viven
   adentro de un campo con 8 px de margen). */
table.tabla.grilla-carga tr:has(+ tr.renglon-promo) td { border-bottom: none; }
table.tabla.grilla-carga tr.renglon-promo td { color: var(--text-secondary); font-size: var(--letra-chica); padding-top: 0; }
table.tabla.grilla-carga tr.renglon-promo .texto-promo { display: block; padding: 0 9px; overflow: hidden; text-overflow: ellipsis; }
/* #548: en el celular las columnas de números (674 px fijos) se comían TODO
   el ancho y Producto quedaba en 0 px: no se podía elegir un producto. La
   tabla toma un ancho mínimo (674 + ~200 para Producto) y la grilla se desliza
   de costado adentro de su recuadro (regla: el scroll vive en la grilla). En
   PC la ventana es más ancha y no cambia nada. */
@media (max-width: 800px) { table.tabla.grilla-carga.grilla-orden { min-width: 880px; } }
/* #653 (Diego, 14/10/2026): *"en el detalle de venta, tanto el descuento de cliente como la promo tienen que
   aparecer como cuando se hace la orden de venta, debajo del producto en cuestión, y sacar las dos columnas"*. Los
   dos renglones de arriba nacieron para la grilla de CARGA (la orden de venta, que tiene campos adentro); el
   detalle de la venta es una tabla común. Lo que cambia es el relleno: allá los 9 px compensan el margen del campo
   donde vive el nombre; acá el texto está pegado a la celda, así que alcanza con el padding de la celda.

   El `:not(.grilla-carga)` NO es decorativo: `table.tabla .nota-renglon` es MÁS específica que
   `.grilla-carga .nota-renglon` (un elemento más), así que sin eso estas reglas le pisarían el relleno a la orden
   de venta y le desalinearían la nota. */
table.tabla:not(.grilla-carga) .nota-renglon { font-size: var(--letra-chica); color: var(--text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
table.tabla:not(.grilla-carga) .nota-renglon:empty { display: none; }
table.tabla:not(.grilla-carga) tr:has(+ tr.renglon-promo) td { border-bottom: none; }
table.tabla:not(.grilla-carga) tr.renglon-promo td { color: var(--text-secondary); font-size: var(--letra-chica); padding-top: 0; }
table.tabla:not(.grilla-carga) tr.renglon-promo .texto-promo { display: block; overflow: hidden; text-overflow: ellipsis; }
table.tabla.grilla-carga tr.renglon-promo td:nth-child(2) { padding-right: 12px; }
/* Las observaciones de la Orden de venta ocupan el espacio que queda a la
   izquierda de los totales (Word 5.3: *"falta que se estire el campo a
   completar para ocupar el espacio vacío"*). */
.columna-izquierda-orden { flex: 1 1 320px; min-width: 0; display: flex; flex-direction: column; gap: 8px; }
.columna-izquierda-orden .campo:last-child { flex: 1 1 auto; }
/* Nunca más chico que el alto de un campo ni que la caja de totales de al lado (flex: 1 1 auto), y desde el #651
   tampoco más chico que su texto: el `field-sizing: content` de arriba lo hace crecer y la esquina lo agranda. */
.columna-izquierda-orden textarea.entrada { flex: 1 1 auto; min-height: var(--alto-campo); }
/* Una grilla COMPACTA (la devolución): renglones más juntos, Word 5.3 —
   *"el detalle de la grilla juntarlo más, porque si no se va muy abajo"*. */
table.tabla.compacta td { padding: 2px 6px; line-height: 1.3; }
table.tabla.compacta th { padding: 5px 6px; }
table.tabla.compacta .entrada { min-height: 28px; padding: 2px 6px; }
/* ---------------------------------------- los popups de Stock (Word 11.1, 05/10/2026)
   Una grilla con lugar FIJO para N renglones (ui.js::fijarFilasVisibles): el
   alto se lo pone el JS medido; acá, que scrollee adentro y no ceda en la
   columna del popup. Los títulos quedan pegados arriba. */
.tabla-contenedor.filas-fijas { flex: none; overflow: auto; }
.tabla-contenedor.filas-fijas table.tabla thead th { position: sticky; top: 0; z-index: 2; }
/* LOS TÍTULOS DE COLUMNA, EN TODO MAJO (Word 11.2, marcas 10 y 14). Diego, sobre el
   nombre del depósito que habíamos puesto "en hasta 3 líneas": *"La idea es que arranque en
   una sola línea predeterminado y se vaya estirando hacia abajo como lo hace ahora pero
   arrancando en una sola, no en 3… Por otro lado, si una mide 4 renglones y la otra 1 igual
   queda abajo, cuando debería ser siempre centrado"* y *"esto tiene que aplicar a todos los
   títulos del sistema"*.
   - Todo título va centrado también de arriba a abajo.
   - Arranca en UNA línea: el ancho de la columna se mide con el título entero en un renglón
     (antes el del depósito se medía con un tope de 112 px y cortándose en cualquier letra, y
     en la grilla de Stock quedaba "DISPO / NIBLE / SALO / N…").
   - En las grillas cuyas columnas se agrandan y achican, si se achica una columna el título
     baja de renglón (se estira hacia abajo) en vez de cortarse con "…". */
table.tabla th { vertical-align: middle; }
table.tabla th .titulo-corto { white-space: nowrap; line-height: 1.15; }
table.tabla.columnas-interactivas th { white-space: normal; overflow-wrap: normal; line-height: 1.15; }
table.tabla.columnas-interactivas th .titulo-corto { white-space: normal; }
/* La columna que NO se va al desplazarse de costado (el producto del
   movimiento interno con muchos destinos: *"el nombre por más que haga
   scroll horizontal debería mostrarlo siempre"*). */
table.tabla td.fija-izquierda, table.tabla th.fija-izquierda { position: sticky; left: 0; z-index: 1; background: var(--bg-table); }
table.tabla thead th.fija-izquierda { z-index: 3; background: var(--bg-table-header); }
table.tabla tbody tr.clic:hover td.fija-izquierda { background: var(--bg-table-hover); }
table.tabla tbody tr.tildada td.fija-izquierda { background: var(--bg-seleccion-suave); }
/* Ubicación + búsqueda + filtros en UNA línea en la computadora (Diego: *"fijate
   que ubicaciones, búsqueda y los filtros están todos en la misma línea"*): el
   buscador cede, los desplegables se cortan con puntos. En el celular envuelve. */
/* Word 11.2, marca 7: depósito a la izquierda; a la derecha los tres desplegables y el
   buscador SOLO, en la línea de abajo, con el mismo ancho que ellos. */
.barra-ubicacion-y-filtros { display: flex; flex-direction: column; gap: 8px; }
.barra-ubicacion-y-filtros .fila-arriba { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.barra-ubicacion-y-filtros .lado-deposito { display: flex; align-items: center; gap: 8px; min-width: 0; }
.barra-ubicacion-y-filtros .fila-combos { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; min-width: 0; }
.barra-ubicacion-y-filtros .fila-combos > select.entrada { width: auto; max-width: 200px; text-overflow: ellipsis; }
.barra-ubicacion-y-filtros > input.entrada { width: 100%; }
@media (max-width: 899px) { .barra-ubicacion-y-filtros .fila-combos { margin-left: 0; } }
@media (min-width: 900px) {
  .barra-herramientas.una-linea { flex-wrap: nowrap; }
  .barra-herramientas.una-linea > * { min-width: 0; flex: 0 1 auto; }
  .barra-herramientas.una-linea > input.entrada { flex: 1 1 140px; }
  .barra-herramientas.una-linea > select.entrada { max-width: 200px; text-overflow: ellipsis; }
  .barra-herramientas.una-linea > span { white-space: nowrap; }
}
/* El pie de los popups de Stock (y del detalle del producto): las flechas de
   página o las de pasar de producto a la IZQUIERDA, los botones a la derecha,
   todo en un mismo renglón (calco del footer de Windows). */
.pie-modal > .pie-izquierda { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-right: auto; }
@media (max-width: 560px) { .pie-modal > .pie-izquierda { flex: 1 0 100%; justify-content: center; margin-right: 0; } }
/* El movimiento interno, "un poco más ancho" (Diego, renglón 36). */
/* Word 11.4 (Diego: *"el popup de movimiento de stock tenemos margen para achicarlo un poco (el ancho)"*): de
   1240 a 1100. Con un destino sobraban unos 200 px a la derecha; con cuatro depósitos todavía entra (Producto es la
   columna que cede). Lo usa sólo el Movimiento interno. */
.modal.extra-ancho { max-width: min(96vw, 1100px); }

.pastilla { display: inline-block; padding: 2px 10px; border-radius: 999px; font-size: var(--letra-chica); font-weight: 600; letter-spacing: 0.3px; line-height: 1.2; white-space: nowrap; }
.pastilla.verde { background: var(--pastilla-verde-bg); color: var(--pastilla-verde-text); }
.pastilla.gris { background: var(--pastilla-gris-bg); color: var(--pastilla-gris-text); }
.pastilla.naranja { background: var(--pastilla-naranja-bg); color: var(--pastilla-naranja-text); }
.pastilla.rojo { background: var(--pastilla-rojo-bg); color: var(--pastilla-rojo-text); }
.pastilla.azul { background: var(--pastilla-azul-bg); color: var(--pastilla-azul-text); }
.pastilla.violeta { background: #6d28d9; color: #fff; }

/* ============================ avisos y banners ============================ */
.aviso { border-radius: var(--radio-campo); padding: 8px 12px; font-size: var(--letra-normal); }
.aviso.error { background: var(--pastilla-rojo-bg); color: var(--pastilla-rojo-text); }
.aviso.ok { background: var(--pastilla-verde-bg); color: var(--pastilla-verde-text); }
.aviso.info { background: var(--bg-banner-info); color: var(--text-banner-info-title); border: 1px solid var(--border-banner-info); }
.aviso.amarillo { background: var(--bg-aviso-amarillo); color: var(--text-aviso-amarillo); border: 1px solid var(--border-aviso-amarillo); font-weight: 400; }
.lista-limpia { list-style: none; margin: 0; padding: 0; }
.lista-limpia li { display: flex; align-items: center; gap: 10px; padding: 6px 0; border-bottom: 1px solid var(--dash-separator); }
.lista-limpia li:last-child { border-bottom: none; }
.lista-limpia .texto { flex: 1; min-width: 0; }
.lista-limpia .texto .t { font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lista-limpia .texto .d { font-size: var(--letra-chica); color: var(--text-secondary); }
.punto { width: 10px; height: 10px; border-radius: 50%; flex: none; }
.punto.rojo { background: var(--bg-danger); } .punto.naranja { background: var(--bg-warning); } .punto.verde { background: #22c55e; } .punto.azul { background: var(--bg-info); } .punto.gris { background: var(--text-muted); }
.barrita { height: 4px; border-radius: 2px; background: var(--dash-separator); overflow: hidden; }
.barrita > span { display: block; height: 100%; background: var(--verde-majo-claro); }

/* ============================ login (LoginDialog) ============================ */
.login { min-height: 100vh; display: grid; place-items: center; background: var(--bg-app); padding: 20px; }
.login .caja { width: 100%; max-width: 380px; display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 20px; }
.login .caja img.logo { height: 92px; width: auto; }
.login .caja h1 { font-size: var(--letra-titulo); font-weight: 700; color: var(--text-title); }
.login .caja .bajada { color: var(--text-secondary); margin-bottom: 8px; }
.login .caja form { width: 100%; display: flex; flex-direction: column; gap: 12px; }
.login .caja .boton.primario { min-height: 48px; font-size: var(--letra-subtitulo); font-weight: 700; margin-top: 6px; }
.login .pie { margin-top: 30px; font-size: var(--letra-chica); color: var(--text-muted); text-align: center; }
.login .franja { color: var(--bg-danger); font-weight: 700; font-size: var(--letra-chica); text-align: center; }
/* Word 10.6, "OTROS": el ojito adentro del campo de la contraseña. */
.login .campo-clave { position: relative; width: 100%; }
.login .campo-clave .entrada { width: 100%; padding-right: 44px; }
.login .campo-clave .ver-clave { position: absolute; right: 4px; top: 50%; transform: translateY(-50%); width: 36px; height: 36px; display: grid; place-items: center; border: 0; border-radius: 8px; background: transparent; color: var(--text-muted); cursor: pointer; padding: 0; }
.login .campo-clave .ver-clave:hover { color: var(--text-title); }
.login .campo-clave .ver-clave:focus-visible { outline: 2px solid var(--border-input-focus); }
.recordar { display: flex; align-items: center; gap: 8px; color: var(--text-primary); }

/* ============================ popups (QDialog) ============================ */
.fondo-modal { position: fixed; inset: 0; background: rgba(2, 8, 23, 0.55); display: grid; place-items: center; z-index: 50; padding: 20px; }
.modal { background: var(--bg-page-card); border: 1px solid var(--border-page-card); border-radius: var(--radio-tarjeta); box-shadow: var(--sombra-popup); width: 100%; max-width: 720px; max-height: 92vh; display: flex; flex-direction: column; min-width: 0; }
.modal.ancho { max-width: 1000px; }
/* El ancho de los diálogos de Windows que Diego marcó como "muy anchos sin
   sentido" (Word 6.2, marcas 14 y 27): allá CobroDialog hace `resize(820, 600)`
   y ProductoInfoDialog `resize(820, 500)` — 820 px, no 1000. */
.modal.medio { max-width: 820px; }
.modal.angosto { max-width: 440px; }
/* "ajustado": del ancho que ocupan sus botones y ni un píxel más (Diego, Word
   5.4, sobre el cartel de "Venta cobrada": *"dejalo del ancho que ocupan los
   botones… no más que eso!"*). En el celular el pie baja de renglón igual. */
.modal.ajustado { width: max-content; max-width: min(96vw, 960px); }
.modal .cabecera-modal { display: flex; align-items: center; gap: 12px; padding: 14px 18px; border-bottom: 1px solid var(--dash-separator); }
.modal .cabecera-modal h2 { flex: 1; font-size: var(--letra-titulo); font-weight: 700; color: var(--text-title); }
/* #473: el "❔ Ayuda" de un popup, entre el título y la cruz. No se estira ni
   se parte: en un celular el título es el que baja de renglón. */
.modal .cabecera-modal .ayuda-del-popup { flex: none; display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.modal .cuerpo-modal { padding: 14px 18px; overflow: auto; }
/* `flex-wrap`: Word 5.3, Diego, con la captura del cartel de "Venta cobrada":
   *"cuando se cobra la venta, los botones se salen del popup"*. Cinco botones
   en un cartel angosto se iban por la izquierda; ahora bajan de renglón. */
.modal .pie-modal { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; padding: 12px 18px; border-top: 1px solid var(--dash-separator); }
/* #662 punto 18: un popup que pregunta "¿a cuál querés ir?" — las opciones en UN renglón, repartidas, y
   Cancelar abajo, solo. Sin esto los tres botones se acomodaban como entraban y Cancelar quedaba arriba. */
/* #662 punto 18, SEGUNDA VUELTA (Diego, 16/10/2026, con captura): *"Así está bien, pero agrandá los botones
   para que el texto entre dentro"*. Con `flex: 1 1 0; min-width: 0` los dos quedaban del MISMO ancho aunque
   sus textos midieran distinto y, como un botón no parte el texto (`.boton` es `nowrap`), las letras se
   salían afuera del botón. Ahora cada uno mide al menos lo que mide su texto (`min-width: max-content`) y
   el popup pasó a "ajustado", que se acomoda al contenido. En un celular se apilan, en vez de salirse. */
.modal.elegir-a-donde-ir .pie-modal { justify-content: stretch; flex-wrap: wrap; }
.modal.elegir-a-donde-ir .pie-modal .boton { flex: 1 1 auto; min-width: max-content; }
.modal.elegir-a-donde-ir .pie-modal .boton.fantasma, .modal.elegir-a-donde-ir .pie-modal .boton.herramienta { flex: 1 1 100%; order: 2; }
/* Un popup "en columna" (el detalle de una venta, la devolución): el alto lo
   fija la pantalla y lo de adentro se reparte el espacio — la grilla es la
   que crece y la que se desplaza (Word 5.3: *"el espacio que va a ocupar la
   grilla como máximo tiene que estar definido"*). */
.modal .cuerpo-modal.en-columna { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.modal .cuerpo-modal.en-columna > div:first-child { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.crece-en-columna { flex: 1 1 auto; min-height: 150px; overflow: auto; }
.datos { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 8px 16px; }
.datos .dato .e { font-size: var(--letra-chica); color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.4px; font-weight: 800; }
.datos .dato .v { font-weight: 500; }

/* menú desplegable (QMenu) */
.menu-flotante { position: absolute; z-index: 60; background: var(--bg-menu); border: 1px solid var(--border-button); border-radius: var(--radio-campo); padding: 6px; min-width: 200px; box-shadow: var(--sombra-popup); }
.menu-flotante button { display: flex; align-items: center; gap: 10px; width: 100%; background: transparent; border: none; border-radius: 8px; padding: 9px 14px; color: var(--text-primary); text-align: left; cursor: pointer; }
.menu-flotante .ico-menu { display: inline-flex; width: 22px; color: var(--text-secondary); flex: none; }
.menu-flotante button:hover .ico-menu { color: var(--text-primary); }
.menu-flotante button:hover { background: var(--bg-button-hover); }
.menu-flotante hr { border: none; height: 1px; background: var(--border-button); margin: 5px 8px; }
/* El renglón MARCADO con el teclado (Word 5.3: moverse por las listas con las
   flechas). Vale para los tres tipos de lista que hay: las sugerencias de un
   buscador (.clic), las filas de una tabla y los botones de un menú. */
.menu-flotante button.resaltado, .clic.resaltado { background: var(--bg-seleccion-suave); outline: 2px solid var(--border-input-focus); outline-offset: -2px; }
table.tabla tbody tr.resaltado td { background: var(--bg-seleccion-suave); }
table.tabla tbody tr.resaltado td:first-child { box-shadow: inset 3px 0 0 var(--border-input-focus); }

/* ------------------------------------------------- el panel de AVISOS (#386)
   Como el centro de notificaciones de Windows que mandó Diego (Word 6.3): a
   la derecha, debajo de la cabecera, un renglón por aviso con su hora y una
   barrita de color (azul aviso, verde "listo", rojo error). */
.panel-avisos { position: fixed; top: 76px; right: 12px; width: 400px; max-width: calc(100vw - 24px); max-height: 72vh; overflow: auto; z-index: 45; background: var(--bg-menu); border: 1px solid var(--border-button); border-radius: var(--radio-tarjeta); box-shadow: var(--sombra-popup); padding: 10px 12px; }
.panel-avisos .cabecera-avisos { display: flex; align-items: center; gap: 8px; padding-bottom: 8px; border-bottom: 1px solid var(--dash-separator); }
.panel-avisos .lista-avisos { display: flex; flex-direction: column; gap: 6px; padding-top: 8px; }
.panel-avisos .aviso-item { display: grid; grid-template-columns: 4px minmax(0, 1fr) auto; gap: 10px; align-items: start; padding: 8px 10px; border-radius: 10px; background: var(--bg-page-card); border: 1px solid var(--border-page-card); }
.panel-avisos .aviso-item .barra { align-self: stretch; border-radius: 2px; background: var(--bg-primary); }
.panel-avisos .aviso-item.ok .barra { background: var(--bg-success); }
.panel-avisos .aviso-item.error .barra { background: var(--bg-danger); }
.panel-avisos .aviso-item .texto { overflow-wrap: anywhere; }
.panel-avisos .aviso-item .hora { color: var(--text-muted); font-size: var(--letra-chica); white-space: nowrap; }
.panel-avisos .vacio { padding: 18px; }
@media (max-width: 800px) { .panel-avisos { top: 70px; right: 8px; } }

/* --------------------------------------- un formulario "lateral" (Word 6.3)
   Diego, sobre el alta de un movimiento de caja: *"no me gusta cuando hay que
   completar y te ponen campos uno al lado del otro; vertical se evitan muchos
   errores. Fijate que en Win está todo vertical y el título del campo está
   puesto a la izquierda del campo"*. Un campo por renglón, el título a la
   izquierda; en el celular el título pasa arriba. */
.formulario-lateral { display: grid; grid-template-columns: 150px minmax(0, 1fr); gap: 8px 12px; align-items: center; }
.formulario-lateral > .etiqueta { margin: 0; }
.formulario-lateral > .par-lateral { display: contents; }
.formulario-lateral > .ancho-entero { grid-column: 1 / -1; }
@media (max-width: 700px) { .formulario-lateral { grid-template-columns: 1fr; } .formulario-lateral > .etiqueta { margin-top: 4px; } }

/* ============================ toasts y spinner ============================ */
/* ---------- los avisos: ABAJO AL CENTRO, subiendo, y apilados (#386) ----------
   Diego (Word 5.1, decidido en el 8.1): *"muestra una notificación muy abajo
   (abajo a la derecha)... tiene que aparecer en algún lugar que la vea!
   Podríamos ponerla al centro? O que abra como más grande, y con la animación
   como que aparece de debajo de la pantalla... y que vaya apilando"*.

   Abajo al CENTRO y no al centro de la pantalla: un cartel en el medio tapa
   justo lo que estás mirando, y en el POS eso cae en la mitad de un cobro.
   Abajo al centro se ve igual y no tapa nada.

   Se apilan con el ÚLTIMO ABAJO (`column-reverse`): el que acaba de pasar
   queda donde tu ojo ya estaba, y los anteriores suben. Al revés, cada aviso
   nuevo empujaría a los de abajo y tendrías que buscarlo.

   El historial del día que también pidió ahí queda para después: primero que
   se vean. */
.toasts {
  position: fixed; left: 50%; transform: translateX(-50%); bottom: 24px;
  display: flex; flex-direction: column-reverse; gap: 8px; z-index: 100;
  align-items: center; max-width: min(560px, calc(100vw - 32px));
}
.toast {
  background: var(--bg-menu); color: var(--text-primary);
  border: 1px solid var(--border-button);
  padding: 14px 22px; border-radius: var(--radio-boton);
  box-shadow: var(--sombra-popup);
  font-size: var(--letra-subtitulo); font-weight: 500;
  max-width: 100%; text-align: center;
  animation: toast-sube .22s ease-out;
}
/* Entra desde abajo de todo, como pidió Diego ("de debajo de la pantalla").
   Quien tenga el sistema puesto en "menos movimiento" lo ve aparecer y ya. */
@keyframes toast-sube {
  from { opacity: 0; transform: translateY(28px); }
  to { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .toast { animation: none; }
}
.toast.error { background: var(--bg-danger); color: #fff; border-color: transparent; }
.toast.ok { background: var(--bg-primary); color: #fff; border-color: transparent; }
.spinner { width: 28px; height: 28px; border: 3px solid var(--border-button); border-top-color: var(--border-input-focus); border-radius: 50%; animation: girar .8s linear infinite; }
@keyframes girar { to { transform: rotate(360deg); } }
.cargando { display: grid; place-items: center; padding: 40px; }
/* El cartel de "no se pudo bajar esta pantalla" (#538, Web 10.1 punto 46): va
   en el lugar del spinner, centrado y angosto; en el celular los dos botones
   bajan uno debajo del otro si no entran. */
.pantalla-sin-bajar { max-width: 520px; margin: 40px auto; padding: 18px 20px; border-radius: var(--radio-tarjeta); background: var(--bg-page-card); border: 1px solid var(--border-page-card); color: var(--text-primary); display: flex; flex-direction: column; gap: 10px; }
.pantalla-sin-bajar h3 { font-size: var(--letra-titulo); font-weight: 700; color: var(--text-title); }
.pantalla-sin-bajar p { margin: 0; font-size: var(--letra-normal); line-height: 1.45; }
.pantalla-sin-bajar p.chico { color: var(--text-secondary); }
.pantalla-sin-bajar .acciones { display: flex; gap: 8px; flex-wrap: wrap; }
@media (max-width: 600px) { .pantalla-sin-bajar { margin: 16px 0; } }
.grafico { position: relative; height: 240px; }
.grafico.chico { height: 200px; }

/* ============================ POS (la ventana de pos_window.py) ============================ */
/* Misma distribución que Windows: CARRITO a la izquierda, PRODUCTOS a la
   derecha. Los colores salen de los tokens pos_* de ui/majo_theme.py y las
   formas del QSS del POS (botón grande 14px/36px, carrito 16px, tarjeta de
   totales 18px, tarjeta de producto 16px, chip 12px/26px). */
.pos { display: grid; grid-template-columns: var(--ancho-carrito, 560px) 10px 1fr; gap: 8px; flex: 1; min-height: 0; }
/* la línea divisoria que se arrastra (el QSplitter del POS de Windows) */
.separador-pos { cursor: col-resize; border-radius: 6px; background: transparent; position: relative; touch-action: none; }
.separador-pos::before { content: ""; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); width: 4px; height: 56px; border-radius: 3px; background: var(--pos-border-surface); }
.separador-pos:hover::before { background: var(--pos-border-accent); }
/* min-width: 0 es obligatorio: sin él, un renglón largo del carrito o el texto
   de la barra de arriba le imponen su ancho a la columna entera y en el celular
   la pantalla se va de costado. */
.pos .panel { background: var(--pos-bg-panel); border: 1px solid var(--pos-border-panel); border-radius: var(--radio-tarjeta); box-shadow: var(--sombra-tarjeta); padding: 14px; color: var(--pos-text); display: flex; flex-direction: column; gap: 8px; min-height: 0; min-width: 0; }
.pos .panel > * { min-width: 0; }
/* 05/10/2026 (Diego, en pruebas: *"cuando se agrega el cartel se solapa, en vez
   de achicarse el carrito; y también pasa cuando en una pantalla más chica
   achico el carrito"*). La columna del carrito son DOS piezas (pos.js):
     · .pila-carrito: el cartel amarillo, la caja, el contacto, el carrito,
       los modos y los medios de pago. De todo eso, lo ÚNICO que cede es el
       carrito (lo demás, flex: none: si no, los totales y los botones se
       aplastaban); baja hasta 80 px y scrollea adentro. Si ni así entra (la
       pantalla es baja, o el carrito se angostó y los medios de pago pasaron
       a tres renglones), scrollea la pila, nunca se sale por abajo.
     · .pie-carrito: los totales y Presupuesto · Cta. cte. · Pago. SIEMPRE a
       la vista, pase lo que pase arriba: en un POS el botón de cobrar no
       puede quedar abajo del scroll ni tapar la barra de atajos.
   Sólo en la computadora: en la tablet y el celular (≤ 1100 px) la columna
   mide lo que trae y la que se desplaza es la hoja entera (pos.css); un
   overflow acá la achicaba a una tira de 28 px. */
.pos .pila-carrito, .pos .pie-carrito { display: flex; flex-direction: column; gap: inherit; min-width: 0; }
.pos .pila-carrito > *, .pos .pie-carrito > * { min-width: 0; }
@media (min-width: 1101px) {
  .pos .pos-izquierda { overflow-y: auto; }   /* último recurso: si ni el pie entra */
  .pos .pila-carrito { flex: 1 1 auto; min-height: 120px; overflow-y: auto; }
  .pos .pila-carrito > :not(.carrito-area) { flex: none; }
  .pos .pie-carrito { flex: none; }
}
/* ===================== #710 · LOS 8 RENGLONES DEL CARRITO =====================
   Diego (22/10/2026), con dos capturas del mismo POS en 14" y en 19":

     > Se lleva más del 60% del espacio el nombre de la caja, el botón de contacto,
     > el de agregar venta, los modos, los medios de pago, los totales y los pagos…
     > En la chica se ve solo uno. Como regla, MÍNIMO se tienen que ver 8 renglones
     > de grilla. Con esa premisa achicar o agrandar botones dejando últimos para
     > achicar los de pago, cta cte y presupuesto.

   Las clases las pone views/_pos_columna.js MIDIENDO: baja de escalón hasta que los
   8 entren. No son media queries porque lo que manda no es el alto de la ventana
   sino cuánto mide un renglón, y eso cambia con el nombre del producto, el zoom y
   la letra que el usuario eligió en Apariencia.

   DOS REGLAS QUE NO SE NEGOCIAN:
     · NADA se esconde. Diego: *"que quede lo más similar pero SIN OCULTAR
       BOTONES"*. Acá no hay un solo `display: none`: todo se achica y todo se
       sigue pudiendo apretar.
     · El escalón 0 —sin ninguna de estas clases— es el POS de siempre. Diego:
       *"que se vayan achicando con pantallas más chicas, NO que nazca así"*. En un
       monitor grande no se aplica ninguna y el carrito se queda con lo que sobra.

   El escalón 2 toca el RENGLÓN del carrito, y es lo que hace que esto funcione:
   achicarlo libera alto Y hace que entren más renglones en el mismo alto. Juntando
   sólo los botones no alcanza para pasar de 4 a 8 en una notebook de 14". */
@media (min-width: 1101px) {
  /* --- escalón 1: el aire --- */
  .pos .pos-izquierda.apretado-1 { gap: 6px; }
  .pos .pos-izquierda.apretado-1 .pila-carrito,
  .pos .pos-izquierda.apretado-1 .pie-carrito { gap: 6px; }
  .pos .pos-izquierda.apretado-1 .etiqueta { font-size: var(--letra-chica); letter-spacing: 0.2px; line-height: 1.15; }
  .pos .pos-izquierda.apretado-1 .caja-estado { font-size: var(--letra-subtitulo); }
  .pos .pos-izquierda.apretado-1 .totales { padding: 8px 12px; border-radius: 14px; }
  /* 22/10, Diego: *"creo que el botón para elegir el cliente, el de + Otra venta y la caja
     se pueden achicar"*. El de "+ Otra venta" manda el alto del renglón de CARRITO, así que
     bajarlo baja todo ese renglón. */
  .pos .pos-izquierda.apretado-1 .fila-ventas .boton { min-height: 30px; }
  .pos .pos-izquierda.apretado-1 .fila-contacto .contacto,
  .pos .pos-izquierda.apretado-1 .fila-contacto .lista { min-height: 34px; }

  /* --- escalón 2: el renglón del carrito y el contacto --- */
  .pos .pos-izquierda.apretado-2 .linea { padding: 2px 10px; }
  .pos .pos-izquierda.apretado-2 .linea .l1,
  .pos .pos-izquierda.apretado-2 .linea .l2 { line-height: 1.25; }
  .pos .pos-izquierda.apretado-2 .linea .l2 { font-size: var(--letra-chica); }
  .pos .pos-izquierda.apretado-2 .carrito-area { padding: 4px; border-radius: 12px; }
  .pos .pos-izquierda.apretado-2 .fila-contacto .contacto,
  .pos .pos-izquierda.apretado-2 .fila-contacto .lista { min-height: 32px; }
  /* 22/10, Diego: *"la leyenda que dice CONTACTO/LISTA, si se achica mucho, también podría
     irse para dar más lugar al carrito"*. Se va, y NO contradice lo de "sin ocultar
     botones": es un rótulo, no un botón, y abajo quedan "Consumidor Final" y "Minorista",
     que se explican solos. Se va sólo acá: en una pantalla holgada sigue estando. */
  .pos .pos-izquierda.apretado-2 .etiqueta-contacto { display: none; }

  /* --- escalón 3: los modos, los medios de pago y los totales --- */
  .pos .pos-izquierda.apretado-3 .modos .modo,
  .pos .pos-izquierda.apretado-3 .chip-medio { min-height: 30px; padding-top: 0; padding-bottom: 0; }
  .pos .pos-izquierda.apretado-3 .etiqueta-medios { display: none; }
  .pos .pos-izquierda.apretado-3 .totales { padding: 6px 12px; }
  .pos .pos-izquierda.apretado-3 .totales .total { font-size: var(--letra-titulo); margin-top: 0; }

  /* --- escalón 4: los ÚLTIMOS en ceder, como pidió Diego --- */
  .pos .pos-izquierda.apretado-4 .acciones-pos .boton { min-height: 32px; font-size: var(--letra-normal); border-radius: 12px; }
  .pos .pos-izquierda.apretado-4 .fila-contacto .contacto,
  .pos .pos-izquierda.apretado-4 .fila-contacto .lista { min-height: 30px; }
  .pos .pos-izquierda.apretado-4 .linea { padding: 1px 8px; }
}

/* El cartel de "5 minutos sin cobrar": el texto y "Entendido" en un renglón
   (abajo del texto se comía 40 px más de carrito); en una columna angosta el
   botón baja solo. */
.pos .aviso.carrito-quieto { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; }
.pos .aviso.carrito-quieto > div { flex: 1 1 260px; min-width: 0; }
.pos .aviso.carrito-quieto > .boton { flex: none; }
.pos .etiqueta { font-size: var(--letra-normal); font-weight: 800; letter-spacing: 0.4px; color: var(--pos-text-muted); text-transform: uppercase; }

/* --- arriba: CAJA + ⚙ Acciones --- */
.pos .fila-caja { display: flex; align-items: center; gap: 8px; }
.pos .caja-info { flex: 1; min-width: 0; display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.pos .caja-info .caja-estado { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* El aviso de terminal compartida: lo único que el rótulo "CAJA" aportaba de verdad. */
.pastilla.chica { font-size: var(--letra-chica); padding: 0 6px; }
.pos .caja-estado { font-size: var(--letra-titulo); font-weight: 500; color: var(--pos-text); }
.pos .caja-estado.cerrada { color: #f87171; }

/* --- contacto / lista --- */
.pos .fila-contacto { display: flex; gap: 8px; align-items: center; }
.pos .fila-contacto .contacto { flex: 1; min-width: 120px; min-height: 38px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: block; text-align: center; }
.pos .fila-contacto .lista { width: 120px; flex: none; min-height: 38px; }

/* --- el carrito --- */
.pos .carrito-area { flex: 1 1 auto; min-height: 80px; background: var(--pos-bg-surface); border: 1px solid var(--pos-border-surface); border-radius: 16px; padding: 6px; overflow-y: auto; display: flex; flex-direction: column; gap: 2px; }
.pos .carrito-vacio { margin: auto; text-align: center; color: var(--pos-text-muted); font-weight: 400; }
.pos .carrito-vacio .ico { font-size: 26px; }
.pos .linea { position: relative; border-radius: 10px; padding: 5px 10px; cursor: pointer; }
.pos .linea:hover { background: var(--pos-bg-surface-hover); }
.pos .linea.sel { background: var(--pos-bg-surface-hover); box-shadow: inset 0 0 0 1px var(--pos-border-accent); }
.pos .linea .l1 { font-size: var(--letra-normal); font-weight: 400; color: var(--pos-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pos .linea .l2 { font-size: var(--letra-normal); color: var(--pos-text-muted); white-space: pre; overflow: hidden; text-overflow: ellipsis; }
/* El lugar de los botones se reserva SOLO cuando se ven: si no, cada renglón
   perdía 130 px de texto por unos botones escondidos. */
.pos .linea:hover .l1, .pos .linea:hover .l2, .pos .linea.sel .l1, .pos .linea.sel .l2 { padding-right: 130px; }
.pos .linea.promo { cursor: default; opacity: 0.85; }
.pos .linea.promo:hover { background: transparent; }
.pos .linea.global .l1 { color: var(--bg-warning); }
.pos .linea .botones { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); display: none; gap: 4px; }
.pos .linea:hover .botones, .pos .linea.sel .botones { display: flex; }
.pos .linea .mini { width: 28px; height: 28px; border-radius: 8px; border: 1px solid var(--pos-border-surface); background: var(--pos-bg-panel); color: var(--pos-text); cursor: pointer; font-weight: 700; display: grid; place-items: center; }
.pos .linea .mini:hover { background: var(--pos-bg-surface-hover); border-color: var(--pos-border-accent); }

/* --- los 4 modos (Cantidad · % de descuento · Precio · Descuento global) --- */
.pos .modos { display: flex; gap: 8px; flex-wrap: wrap; }
.pos .modos .modo { flex: 1; min-width: 70px; }
.boton.secundario { background: var(--pos-bg-surface); color: var(--pos-text); border: 1px solid var(--pos-border-surface); border-radius: 12px; padding: 4px 8px; font-size: var(--letra-chica); font-weight: 700; min-height: var(--alto-boton); }
.boton.secundario:hover { background: var(--pos-bg-surface-hover); }
.boton.secundario.activo { background: var(--pos-bg-surface-hover); color: var(--pos-text); border-color: var(--pos-border-accent); box-shadow: inset 0 0 0 1px var(--pos-border-accent); }

/* --- medios de pago (PosChipButton): ninguno viene elegido (#284) --- */
.pos .medios-fila { display: flex; gap: 4px; flex-wrap: wrap; }
.chip-medio { background: var(--pos-bg-surface); color: var(--pos-text-muted); border: 1px solid var(--pos-border-surface); border-radius: 12px; padding: 1px 10px; font-size: var(--letra-chica); font-weight: 700; min-height: var(--alto-boton); cursor: pointer; white-space: nowrap; }
.chip-medio:hover { background: var(--pos-bg-surface-hover); }
.chip-medio.activo { background: var(--pos-bg-surface-hover); color: var(--pos-text); border-color: var(--pos-border-accent); box-shadow: inset 0 0 0 1px var(--pos-border-accent); }

/* --- totales (PosTotalsCard) --- */
.pos .totales { background: var(--pos-bg-surface); border: 1px solid var(--pos-border-surface); border-radius: 18px; padding: 12px 14px; }
.pos .totales .fila { font-size: var(--letra-normal); font-weight: 500; color: var(--pos-text-muted); }
.pos .totales .total { font-size: var(--letra-destacado); font-weight: 800; color: var(--pos-text); margin-top: 4px; }

/* --- Presupuesto · Cta. cte. · Pago (los mismos colores que Windows) --- */
.pos .acciones-pos { display: flex; gap: 8px; }
.pos .acciones-pos .boton { flex: 1; min-height: 38px; border-radius: 14px; font-size: var(--letra-subtitulo); font-weight: 800; color: #fff; border: none; }
.boton.pos-pago, .boton.cobrar { background: var(--verde-majo); color: #fff; border: none; }
.boton.pos-pago:hover:enabled, .boton.cobrar:hover:enabled { background: var(--verde-majo-claro); }
.boton.pos-presupuesto { background: #2563eb; color: #fff; border: none; }
.boton.pos-presupuesto:hover:enabled { background: #1d4ed8; }
.boton.pos-cuenta { background: #d97706; }
.boton.pos-cuenta:hover:enabled { background: #b45309; }

/* --- panel derecho: buscador, rubros y tarjetas --- */
.pos .buscar-titulo { font-size: var(--letra-destacado); font-weight: 800; color: var(--pos-text); }
/* los rubros: solapas como en Windows (PosTabButton), no pastillas */
.pos .rubros { flex: none; display: flex; gap: 2px; overflow-x: auto; border-bottom: 1px solid var(--pos-border-surface); }
.solapa-rubro { background: transparent; border: none; border-bottom: 2px solid transparent; color: var(--pos-text-muted); padding: 8px 10px; font-weight: 700; font-size: var(--letra-normal); cursor: pointer; white-space: nowrap; }
.solapa-rubro:hover { color: var(--pos-text); }
.solapa-rubro.activa { color: var(--pos-text); border-bottom-color: var(--pos-border-accent); }
/* Las tarjetas miden lo MISMO que en Windows (158 x 170, imagen de 58 y
   nombre de 40): con columnas elásticas, en una pantalla ancha la foto se
   estiraba y quedaba enorme (marca de Diego, 22/09). */
.pos .productos { display: grid; grid-template-columns: repeat(auto-fill, 158px); justify-content: center; gap: 6px; overflow-y: auto; align-content: start; flex: 1; min-height: 0; }
.pos .producto { width: 158px; height: 170px; background: var(--pos-bg-surface); border: 1px solid var(--pos-border-surface-alt); border-radius: 16px; padding: 6px 8px; cursor: pointer; display: flex; flex-direction: column; gap: 2px; overflow: hidden; transition: border-color .1s, background .1s; }
.pos .producto:hover { background: var(--pos-bg-surface-hover); border-color: var(--pos-border-accent); }
.pos .producto .stock-linea { display: flex; justify-content: flex-end; align-items: center; gap: 6px; font-size: var(--letra-chica); color: var(--pos-text-muted); }
.pos .producto .stock-linea .rojo { color: #f87171; }
.pos .producto .foto { height: 58px; flex: none; border-radius: 12px; background: var(--foto-fondo, #fff); border: 1px solid var(--pos-border-surface); display: grid; place-items: center; color: #6b7f95; font-size: var(--letra-chica); overflow: hidden; }
.pos .producto .foto img { width: 100%; height: 100%; object-fit: contain; }
.pos .producto .n { height: 40px; flex: none; font-weight: 400; font-size: var(--letra-normal); line-height: 1.2; color: var(--pos-text); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
/* #601 (Word 11.2): la tarjeta del producto EXACTO de la búsqueda, con el nombre en negrita. */
.pos .producto.exacto .n { font-weight: 700; }
.pos .producto .p { font-weight: 400; font-size: var(--letra-titulo); color: var(--pos-text); }
.pos .producto .stock-linea .variante { margin-right: auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 700; color: var(--pos-text); }
/* Word 10.3 (Diego, 04/10): el precio de antes en SU PROPIO renglón, arriba
   del precio, chico y gris: al lado no entraba ("si el número es $100.000 no
   va a entrar ni de casualidad"). */
.pos .producto .p .precio-antes { display: block; font-size: var(--letra-chica); font-weight: 400; line-height: 1.1; color: var(--pos-text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pos .info-i { width: 18px; height: 18px; border-radius: 9px; border: 1px solid var(--pos-border-surface); display: grid; place-items: center; font-size: 10px; font-weight: 800; cursor: pointer; }
.pos .info-i:hover { background: var(--pos-bg-surface-hover); border-color: var(--pos-border-accent); }

/* --- el HUB de Punto de venta (una tarjeta por terminal, como en Windows) --- */
.grilla-pos { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 12px; }
.tarjeta-pos { background: var(--dash-bg-card); border: 1px solid var(--dash-border-card); border-radius: 16px; box-shadow: var(--sombra-tarjeta); padding: 14px; display: flex; flex-direction: column; gap: 6px; cursor: pointer; transition: border-color .12s, background .12s; }
.tarjeta-pos:hover { background: var(--dash-bg-card-hover); border-color: var(--border-input-focus); }
.tarjeta-pos .cab { display: flex; align-items: flex-start; gap: 10px; }
.tarjeta-pos .nombre { flex: 1; font-size: var(--letra-subtitulo); font-weight: 400; color: var(--dash-text-title); }
.tarjeta-pos .renglon-plata { display: flex; justify-content: space-between; gap: 10px; padding-top: 2px; }
.tarjeta-pos .pie { display: flex; align-items: center; gap: 8px; margin-top: 8px; }

/* --- el editor de una terminal (#481, views/_terminal_pos.js) ---
   Vive acá y no en pos.css porque también lo abre Configuración → POS
   (terminales), y pos.css se carga recién al entrar al POS (views/pos.js,
   cargarEstilosPos): desde Configuración puede no estar. Los medios de pago van en una
   caja de alto fijo con scroll adentro: con muchos medios la ventana no crece
   (Diego: "ningún popup cambia de tamaño según lo que tenga adentro"). */
.editor-terminal .titulo-editor-terminal { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--dash-separator); font-weight: 700; color: var(--text-title); }
.editor-terminal .medios-terminal { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 6px 12px; max-height: 150px; overflow-y: auto; }
.editor-terminal .formulario-lateral { grid-template-columns: 230px minmax(0, 1fr); }
@media (max-width: 700px) { .editor-terminal .formulario-lateral { grid-template-columns: 1fr; } }

/* ============================ la ventana de cobro (pos_cobro.js) ============================ */
/* La misma para el POS y para Ventas, como armado_cobro.py en Windows. */
.cobro { display: flex; flex-direction: column; gap: 10px; }
.banner-cobro { background: var(--bg-banner-info); border: 1px solid var(--border-banner-info); border-radius: 18px; padding: 12px 18px; display: flex; align-items: center; gap: 18px; }
.banner-cobro .textos { flex: 1; display: flex; align-items: center; gap: 8px; }
.banner-cobro .titulo { font-size: var(--letra-titulo); font-weight: 700; color: var(--text-banner-info-title); }
.banner-cobro .ayuda { width: 20px; height: 20px; border-radius: 10px; background: var(--bg-button); border: 1px solid var(--border-button); color: var(--text-secondary); font-size: var(--letra-normal); font-weight: 800; display: grid; place-items: center; cursor: pointer; }
.banner-cobro .valor { font-size: var(--letra-destacado); font-weight: 800; color: var(--text-banner-info-valor); font-variant-numeric: tabular-nums; }
.filas-cobro { display: flex; flex-direction: column; gap: 8px; max-height: 44vh; overflow-y: auto; }
/* Word 6.3 (Diego), la ventana de cobro: *"donde se selecciona el medio de
   pago está dentro de una pastilla que está dentro de otra pastilla más
   grande… esta última sacala y achicá un poco el espacio entre los medios de
   pago, que usen un tamaño parecido a la grilla"* y *"hay que achicar el
   ancho de los títulos… no sé por qué hay tanto aire"*. Las filas son
   renglones de grilla (una rayita entre uno y otro), sin tarjeta; los
   títulos van en un renglón chico. */
.fila-cobro { display: grid; grid-template-columns: 1.3fr 1fr 1fr 0.9fr 1fr 34px; gap: 6px; align-items: center; background: transparent; border: none; border-bottom: 1px solid var(--dash-separator); border-radius: 0; padding: 3px 4px; }
.fila-cobro.cabecera { background: var(--bg-table-header); border: none; border-radius: 8px; padding: 4px 6px; min-height: 0; font-size: var(--letra-chica); font-weight: 700; color: var(--text-table-header); text-transform: uppercase; letter-spacing: 0.4px; line-height: 1.2; }
/* Los títulos centrados sobre su columna, como los de toda grilla de Majo (Word
   10.1, punto 12: su captura de cómo tiene que quedar). */
.fila-cobro.cabecera > div { text-align: center; }
/* *"Tiene que tener un alto fijo y tienen que entrar 3 medios de pago antes
   del scroll (sólo en los medios de pago)"* + *"podemos achicarla un poco
   más en ancho"*: 740 px (Windows tiene 820), alto fijo en la PC, y la zona
   de los medios se queda con lo que sobra — nunca menos de tres renglones;
   de ahí en más scrollea ELLA. En el celular se deja elástica. */
/* La caja del popup de cobro se llama "ventana-cobro", no "cobro": `.cobro`
   es el div de CONTENIDO (display flex, gap) y con el mismo nombre la caja
   heredaba su gap entre cabecera, cuerpo y pie (revisión del 26/09). */
.modal.ventana-cobro { max-width: 740px; }
/* Word 10.1, punto 12 (Diego, 29/09, con su captura): *"no entiendo por qué hay
   tanto aire entre el medio y el botón '+ agregar medio'… En este caso sí debería
   haber espacio para 1 y si se agrega uno o dos ir agrandando"*. Excepción suya,
   explícita, a la directiva 37: la ventana ya NO tiene alto fijo; la zona de los
   medios mide lo que ocupan (1, 2 o 3 — no hay más de 3) y la ventana crece con
   ellos. */
.filas-cobro { display: flex; flex-direction: column; gap: 0; }
.cuerpo-modal.en-columna .filas-cobro { flex: none; min-height: 0; overflow: visible; }
.fila-cobro .importe { font-size: var(--letra-subtitulo); font-weight: 400; text-align: right; }
.fila-cobro .invisible { visibility: hidden; }
.cobro-saldo { text-align: center; font-size: var(--letra-titulo); font-weight: 800; padding: 6px 0; }
.cobro-saldo.ok { color: #22c55e; }
.cobro-saldo.pendiente, .cobro-saldo.error { color: #ef4444; }
.cobro-chico { text-align: center; font-size: var(--letra-normal); font-weight: 700; }
.cobro-total { text-align: center; font-size: var(--letra-titulo); font-weight: 800; color: var(--text-banner-info-valor); padding: 2px 0; }
.cobro-vuelto { text-align: center; font-size: var(--letra-titulo); font-weight: 800; color: #22c55e; }
.comprobantes { display: flex; gap: 10px; }
.check-comprobante { display: inline-flex; align-items: center; gap: 8px; min-width: 135px; min-height: 38px; padding: 0 12px; border: 1px solid var(--border-button); border-radius: var(--radio-boton); background: var(--bg-button); cursor: pointer; font-weight: 600; }
.verde { color: #22c55e; }
.rojo { color: #ef4444; }

/* ============================ celular ============================ */
@media (max-width: 1100px) {
  .grilla.dos, .grilla.tres, .grilla.cuatro { grid-template-columns: 1fr; }
  .pos { grid-template-columns: 1fr; overflow-y: auto; }
  .separador-pos { display: none; }
  .pos .carrito-area { min-height: 180px; }
  .pos .productos { overflow: visible; }
}
@media (max-width: 800px) {
  .layout { padding: 8px; gap: 8px; }
  /* Diego (2.2): *"cuando abro la pantalla del cel aparece como ampliado;
     debería aparecer reducido al tamaño del cel"*. Era la CABECERA: tres
     botones con texto que no se dejan achicar (Alertas, Configuración,
     Usuario) medían 534 px y estiraban la hoja entera, así que el navegador
     la mostraba alejada. En el celular quedan sólo los íconos. */
  .layout > * { min-width: 0; }
  .cabecera { padding: 8px 10px; min-height: 60px; gap: 8px; min-width: 0; }
  .cabecera .logo { height: 36px; }
  .cabecera .titulo { font-size: var(--letra-titulo); }
  .cabecera .subtitulo { display: none; }
  .cabecera .acciones { gap: 6px; }
  .cabecera .acciones .boton { padding: 0; width: 40px; min-width: 40px; justify-content: center; }
  .cabecera .acciones .boton > span:nth-child(2) { display: none; }
  .cuerpo, .cuerpo.accesos-cerrados { grid-template-columns: 1fr; }
  .contenido { grid-column: 1; }
  .accesos { flex-direction: row; align-items: center; overflow-x: auto; padding: 6px; gap: 4px; min-height: auto; }
  .accesos .encabezado, .accesos .pie-accesos { display: none; }
  .accesos .lista { flex-direction: row; overflow: visible; }
  .accesos .fijos-accesos { flex-direction: row; }
  .acceso { min-height: 34px; padding: 4px; width: auto; }
  .acceso .t { display: none; }
  .titulo-modulo h1 { font-size: var(--letra-titulo); }
  .pos .acciones-pos { flex-wrap: wrap; }
  .pos .acciones-pos .boton { min-width: 45%; }
  .pos .linea .l1, .pos .linea .l2 { padding-right: 0; white-space: normal; }
  .pos .linea .botones { position: static; transform: none; display: flex; justify-content: flex-end; margin-top: 4px; }
  .pos .productos { grid-template-columns: repeat(auto-fill, 150px); }
  .pos .producto { width: 150px; }
  .pos .buscar-titulo { display: none; }
  .pos .barra-herramientas .buscador { flex: 1 1 100%; min-width: 0; }
  .pos .modos .modo { flex: 1 1 45%; }
  .pos .fila-contacto .contacto { min-width: 0; }
  .fila-cobro { grid-template-columns: 1fr 1fr; }
  .fila-cobro.cabecera { display: none; }
  .zocalo { font-size: var(--letra-chica); }
}

/* ============================ INICIO (la distribución de MainWindow) ============================ */
/* Diego (4.3): *"El inicio no tendría que tener scroll. Ahora tiene scroll hasta
   en una pantalla de 23 pulgadas"*, *"las tarjetas de la derecha siempre tienen
   que ocupar el alto de la pantalla; si se achica demasiado, ocultar info pero
   nunca superponer. Acá el gráfico se fue atrás de las tarjetas"* y *"si
   trabajamos con una pantalla más pequeña que haya mucho scroll es molesto, y si
   trabajamos con una pantalla muy grande los espacios vacíos también quedan
   raros"*.

   POR QUÉ scrolleaba: el Inicio tenía alto INTRÍNSECO. Ninguna pieza achicaba
   (gráficos clavados en 168 px, mini-barras que crecen con los renglones, 9 KPI
   apilados que sumaban ~964 px) y encima la grilla estaba en `align-items: start`,
   así que las dos columnas se quedaban en su alto de contenido y el sobrante se
   iba a un scroll. Medido en un monitor de 23" (1920x1080): centro ~867 px y
   columna de KPI ~964 px contra ~806 px disponibles.

   CÓMO SE ARREGLA, igual que Windows: el Inicio no tiene alto propio, REPARTE el
   que hay. En Windows cada tarjeta declara un rango y adentro se comprime (los
   gráficos 242..282, cada tarjeta de resumen 158..176, el asesor 128..168, cada
   KPI 66) — acá eso son filas `minmax()` y tarjetas que son contenedores flex
   con `min-height: 0`.

   REGLA AL TOCAR ESTO: el alto se gana con aire (gap y padding), con el alto de
   los gráficos y con el interlineado de las mini-barras. NUNCA bajando
   `font-size` ni el `line-height` del body: los tamaños son los de Windows y el
   aire entre renglones lo pidió Diego expresamente (Word 1.3). Si no entra, se
   esconde lo menos importante (ver la escalera de degradación al final del
   bloque), nunca se superpone. */
.inicio { display: grid; grid-template-columns: minmax(0, 1fr) 256px; grid-template-rows: auto minmax(0, 1fr); gap: clamp(6px, 0.9vh, 12px); align-items: stretch; min-height: 0; }
/* ---- LA BARRA DE ARRIBA DE TODO (Word 4.2, 23/09/2026) ----
   Diego: *"de dónde se acomodan quedó medio oculto, yo lo pondría arriba de
   todo al lado del seleccionador de las sucursales… La leyenda la pondría al
   lado del desplegable pero dentro del '?' así no se ve el texto enorme.
   Luego del '?' del seleccionador de sucursal, un espacio considerable y ahí
   sí va el botón de 'Acomodar inicio'"*.

   Queda: [Sucursal] [desplegable] [?]  ——espacio——  [✥ Acomodar el Inicio] [?]
   y, contra el borde derecho, el cartelito de estado del tablero.

   La barra cruza las DOS columnas (los gráficos y los indicadores) porque lo
   que tiene adentro manda sobre las dos. Desde el 23/09 a la tarde está
   SIEMPRE —antes sólo con dos o más sucursales—, porque ahora también vive
   acá el botón de acomodar, que estaba escondido abajo.

   EL ALTO ES EL PUNTO: son 26 px de alto + el aire, exactamente lo que ya
   medía la barra de sucursal. Medido a mano en 650 px de alto, que es el caso
   más apretado: la fila del Resumen operativo toca su mínimo (96 px) y la de
   los gráficos queda en 123, arriba de su mínimo de 120 — entra justo y sigue
   sin scroll. Si alguna vez hay que agrandar esta barra, hay que volver a
   medir en 650. Por eso también va `nowrap`: si se parte en dos renglones,
   mide el doble y el Inicio vuelve a scrollear. */
.inicio > .barra-inicio { grid-column: 1 / -1; }
.barra-inicio { display: flex; align-items: center; gap: 8px; min-width: 0; flex-wrap: nowrap; }
.barra-inicio .et { flex: none; font-size: var(--letra-chica); font-weight: 800; letter-spacing: 0.6px; text-transform: uppercase; color: var(--dash-text-muted); }
.barra-inicio select.entrada { width: auto; max-width: 260px; min-height: var(--alto-campo); padding: 1px 28px 1px 8px; flex: none; }
/* El "espacio considerable" que pidió Diego entre el "?" de la sucursal y el
   botón de acomodar: crece con la pantalla pero nunca desaparece. */
.barra-inicio .grupo-acomodar { flex: none; display: flex; align-items: center; gap: 6px; margin-left: clamp(18px, 4vw, 56px); }
/* Con un solo local no hay selector de sucursal y el grupo queda primero: ahí
   el espacio de separación no separa de nada y sólo se vería como un sangrado
   raro contra el borde izquierdo. */
.barra-inicio .lado > .grupo-acomodar:first-child { margin-left: 0; }
/* #388 (Word 10.1): la ayuda va EN EL MEDIO de esta barra, en tres columnas
   (izquierda · ayuda · derecha). Acá los costados NO se parten en renglones
   (el alto de esta barra está medido, ver arriba): si lo de la izquierda no
   entra en su mitad, el botón se corre a la derecha. El cartelito de estado
   del tablero es lo único que se deja recortar, como antes.
   `minmax(max-content, 1fr)` a la izquierda y no `1fr`: con `1fr`, en cuanto
   lo de la izquierda pasaba su mitad la grilla le daba su ancho MÍNIMO y el
   "actualizado 21:58" se partía en dos renglones (medido en 1366 con dos
   sucursales). Así se queda entero y es el botón el que se corre.
   Y como con el menú lateral abierto el Inicio es la hoja más angosta de
   Majo, cuando la barra mide menos de 1100 px el botón dice sólo "❔ Ayuda"
   (medido: en 1110 px de pantalla, con dos sucursales, "Cómo se usa Majo"
   entraba con 4 px de sobra). */
.barra-inicio.con-ayuda { display: grid; grid-template-columns: minmax(max-content, 1fr) auto minmax(0, 1fr); align-items: center; column-gap: 8px; container-type: inline-size; }
.barra-inicio.con-ayuda > .lado { display: flex; align-items: center; flex-wrap: nowrap; gap: 8px; }
.barra-inicio.con-ayuda > .lado.derecha { min-width: 0; overflow: hidden; }
@container (max-width: 1100px) {
  .barra-inicio .ayuda-del-modulo .texto-largo { display: none; }
  .barra-inicio .ayuda-del-modulo .texto-corto { display: inline; }
}
/* Apilado (abajo de 1100 px, celular incluido) el Inicio ya scrollea, así que
   el alto de la barra deja de importar: ahí sí se parte en renglones, igual
   que la barra de los otros módulos. Sin esto, en el celular la ayuda quedaba
   afuera de la pantalla, a la derecha. */
@media (max-width: 1100px) {
  .barra-inicio.con-ayuda { display: flex; flex-wrap: wrap; gap: 8px; }
  .barra-inicio.con-ayuda > .lado { display: contents; }
}
.barra-inicio .boton { min-height: var(--alto-boton); padding: 2px 10px; flex: none; }
/* El cartelito de estado ("Tu Inicio, a tu manera") es lo único que se deja
   recortar: es lo que menos importa de la barra. */
.barra-inicio .etiqueta-tablero { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--letra-chica); font-weight: 800; letter-spacing: 0.6px; text-transform: uppercase; color: var(--dash-text-muted); }
/* ---- el "?" con la explicación adentro (patrón del pendiente #111) ----
   Mismo redondelito que ya usan el título de módulo y el banner de cobro del
   POS. Va acá y no en una regla suelta `.ayuda` para no tocar de rebote las
   otras pantallas que ya lo tienen con su propio contexto. */
.barra-inicio .ayuda, .titulo-seccion .ayuda { flex: none; width: 20px; height: 20px; border-radius: 10px; background: var(--bg-button); border: 1px solid var(--border-button); color: var(--text-secondary); font-size: var(--letra-normal); font-weight: 800; display: grid; place-items: center; cursor: pointer; padding: 0; font-family: inherit; }
.barra-inicio .ayuda:hover, .titulo-seccion .ayuda:hover { background: var(--bg-button-hover); color: var(--text-primary); }
/* Ámbar cuando lo que guarda adentro no es una explicación sino un AVISO: con
   una sucursal elegida hay tarjetas que igual son de todo el negocio. Es el
   mismo ámbar de los puntitos de esas tarjetas, que siguen estando — el aviso
   no depende de que alguien abra el "?". Desde el Web 10.1 (punto 3, 29/09) se
   pone ámbar sólo si alguna tarjeta de la pantalla quedó con el puntito, no con
   sólo elegir una sucursal (inicio.js, después de `marcarGlobales`). */
.barra-inicio .ayuda.atencion { color: var(--bg-warning); border-color: var(--bg-warning); }
/* ---- el título de una sección del Inicio ("Resumen operativo") ----
   Es una pieza más del tablero (inicio.js, `titulo_resumen`) justamente para
   que no desaparezca al entrar al modo editar, que es lo que le pasaba. */
.titulo-seccion { display: flex; align-items: center; gap: 8px; min-width: 0; }
.titulo-seccion h2 { font-size: var(--letra-titulo); font-weight: 700; color: var(--dash-text-title); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* El puntito de "esto es de todo el negocio". Va ABSOLUTO: no empuja nada, así
   que no le saca alto a ninguna tarjeta. El texto completo está en el title de
   la tarjeta y en la leyenda de la barra de arriba.

   POR QUÉ ES ÁMBAR Y NO CELESTE, Y POR QUÉ MIDE 11 px (23/09/2026): en
   1366x768 y 1280x800 `acomodarKpis` esconde el renglón de detalle entero
   porque no entra, y ahí el "· todo el negocio" que se agrega al detalle
   DESAPARECE — la marca queda siendo lo único que avisa. Medido: con una
   sucursal elegida, en esas dos pantallas los 7 números globales (cuentas por
   cobrar, presupuestos, compras, caja, stock, alertas y los costos fijos de la
   rentabilidad) se leían como si fueran de la sucursal. Un punto celeste de
   9 px sobre tarjeta blanca no alcanzaba para eso. `pointer-events: auto` es
   para que el title del punto se pueda leer pasando el mouse por arriba. */
.es-global { position: relative; }
/* El naranja es el mismo que ya usan los KPI cuando algo pide atención
   (cuentas vencidas, stock bajo mínimo), así que no es un color nuevo. */
.marca-global { position: absolute; top: 3px; right: 5px; font-size: 11px; line-height: 1; color: var(--bg-warning); pointer-events: auto; cursor: help; }
/* Las cinco filas, en el mismo orden que arma inicio.js: gráficos, "Resumen
   operativo", las tarjetas de resumen, el Asesor y la de soporte. Las dos
   flexibles se llevan el alto sobrante (1,35 a 1, como en Windows los gráficos
   son más altos que el resumen); las otras tres valen lo que ocupan. */
.centro-inicio { display: grid; grid-template-rows: minmax(120px, 1.35fr) auto minmax(96px, 1fr) auto auto; gap: clamp(6px, 0.9vh, 12px); min-width: 0; min-height: 0; }
/* `min-width: 0` en los hijos y `overflow: hidden` en la fila: sin esto, Chart.js
   le escribe al <canvas> un ancho en PÍXELES, ese ancho pasa a ser el mínimo de
   la columna de la grilla, la tarjeta ya no puede achicarse, se desborda a la
   derecha y la columna de KPI (opaca y posterior en el DOM) le pasa por encima.
   Es el gráfico "que se fue atrás de las tarjetas" que vio Diego, y el mismo
   problema que el POS ya tenía documentado más arriba. */
/* Word 10.4, marca 5: un gráfico de ventas sin una sola venta no se muestra
   (views/inicio.js, clase sin-datos); el otro ocupa el ancho entero, y si los dos
   están vacíos la fila desaparece y el resumen de abajo se queda con el alto. */
/* #595: Configuración en 7 pestañas; adentro, una sección por página vieja,
   con su título y un índice arriba para ir derecho. */
.indice-config { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; }
.seccion-config { padding-top: 10px; border-top: 1px solid var(--dash-separator); }
.seccion-config:first-of-type { border-top: 0; padding-top: 0; }
.titulo-seccion-config { font-size: var(--letra-subtitulo); font-weight: 700; color: var(--text-title); margin: 0 0 8px; scroll-margin-top: 12px; }
/* #596: el Asesor arriba de la grilla de Reportes, en una línea (la respuesta
   aparece debajo sólo cuando la hay). */
.asesor-reportes { flex: none; display: flex; flex-direction: column; gap: 6px; }
.asesor-reportes .fila-asesor { display: flex; gap: 8px; align-items: center; }
.asesor-reportes .fila-asesor .entrada { flex: 1 1 200px; min-width: 0; }
.asesor-reportes .fila-asesor .ico { display: inline-flex; color: var(--text-toolbutton); }
.asesor-reportes .respuesta-asesor:empty { display: none; }
.asesor-reportes .respuesta-asesor { white-space: pre-wrap; max-height: 30vh; overflow: auto; padding: 8px 10px; border-radius: 10px; background: var(--bg-button); border: 1px solid var(--border-button); }
.fila-graficos { display: grid; grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); gap: clamp(8px, 1vh, 12px); min-width: 0; min-height: 0; overflow: hidden; }
.fila-graficos > .tarjeta-grafico.sin-datos { display: none; }
/* Word 10.5, marca 4: también en el Inicio acomodado a mano y mientras se acomoda. */
.grilla-tablero > .widget:has(> .tarjeta-grafico.sin-datos) { display: none; }
.fila-graficos:not(:has(> .tarjeta-grafico:not(.sin-datos))) { display: none; }
.centro-inicio:has(> .fila-graficos:not(:has(> .tarjeta-grafico:not(.sin-datos)))) { grid-template-rows: auto minmax(96px, 1fr) auto auto; }
.fila-graficos > *, .grilla-insights > * { min-width: 0; min-height: 0; }
.tarjeta-grafico { background: var(--dash-bg-card); border: 1px solid var(--dash-border-card); border-radius: 16px; padding: clamp(8px, 1.1vh, 14px) 16px; box-shadow: var(--sombra-tarjeta); display: flex; flex-direction: column; min-width: 0; min-height: 0; overflow: hidden; }
.tarjeta-grafico .cab { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; margin-bottom: 6px; }
.tarjeta-grafico .titulo, .tarjeta-insight .titulo { font-size: var(--letra-chica); color: var(--dash-text-muted); font-weight: 800; letter-spacing: 0.6px; text-transform: uppercase; }
.tarjeta-grafico .valor { font-size: var(--letra-titulo); font-weight: 900; color: var(--dash-text-title); }
.tarjeta-grafico .sub { font-size: var(--letra-chica); color: var(--dash-text-soft); }
.tarjeta-grafico .cab-der { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; text-align: right; }
/* El detalle de la derecha ("N ventas cobradas · mejor mes…") se topea en dos
   renglones: envuelto en tres empujaba la cabecera de la tarjeta 17 px hacia
   abajo y se los sacaba al gráfico. */
.tarjeta-grafico .detalle { font-size: var(--letra-chica); color: var(--dash-text-detail); max-width: 260px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
/* El gráfico ya no mide 168 px fijos: se queda con lo que sobra en la tarjeta
   (es lo PRIMERO que cede al achicar la ventana) y nunca baja de
   --alto-min-grafico, que la escalera del final va bajando. */
.tarjeta-grafico .grafico { flex: 1; height: auto; min-height: var(--alto-min-grafico, 84px); }
/* El renglón del título. Desde el 23/09 adentro va la MISMA pieza que dibuja
   el tablero (`.titulo-seccion`: el título + su "?"), así que el título no
   puede desaparecer al entrar al modo editar. El botón "Acomodar el Inicio"
   se fue a la barra de arriba y el subtítulo largo, adentro del "?". */
.resumen-cab { display: flex; align-items: center; gap: 12px; padding: 2px 4px 0; min-height: 0; }
.resumen-cab h2 { font-size: var(--letra-titulo); font-weight: 700; color: var(--dash-text-title); }
/* Diego (1.4): *"no quiero que en el inicio se escrolee; ¿podemos achicar los
   gráficos? O los 4 de resumen operativo ponerlos en una línea"*. Las dos:
   gráficos más bajos y las cuatro tarjetas en una sola fila. */
/* `auto-fit` en vez de los cortes de golpe en 1500 y 1250 px (Diego: *"los
   cambios entre pantalla y pantalla no sean tan drásticos"*). El mínimo es
   chico (140 px) A PROPÓSITO: así las cuatro tarjetas se quedan en UNA fila
   hasta los 1100 px de ancho y lo único que cambia es cuánto mide cada una. Con
   un mínimo grande caían en dos filas y, como el alto ya está repartido, cada
   tarjeta quedaba en 68 px y se le cortaban las barras (medido en 1366x768:
   50 px de recorte). Estrecharse se nota mucho menos que recortarse.
   `grid-auto-rows: minmax(0,1fr)` + `overflow: hidden` es el cinturón por si
   igual caen en dos filas: se reparten el alto en vez de desbordar sobre el
   Asesor. */
.grilla-insights { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); grid-auto-rows: minmax(0, 1fr); gap: 10px; min-width: 0; min-height: 0; overflow: hidden; }
.tarjeta-insight { background: var(--dash-bg-card); border: 1px solid var(--dash-border-card); border-top: 3px solid var(--acento, var(--bg-primary)); border-radius: 16px; padding: clamp(6px, 0.9vh, 10px) 12px; box-shadow: var(--sombra-tarjeta); display: flex; flex-direction: column; min-width: 0; min-height: 0; overflow: hidden; }
.tarjeta-insight .cab { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.tarjeta-insight .valor { font-size: var(--letra-subtitulo); font-weight: 900; color: var(--dash-text-title); }
.tarjeta-insight .detalle { font-size: var(--letra-chica); color: var(--dash-text-detail); margin: 2px 0 6px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
/* El cuerpo de la tarjeta (las mini-barras o el gráfico chico) se queda con lo
   que sobra, y nunca empuja: si no entra, recorta. */
.cuerpo-insight { flex: 1; min-height: 0; min-width: 0; overflow: hidden; display: flex; flex-direction: column; }
/* `min-height: 0` Y NO 52 px (23/09/2026). Con 52 px de piso, en 1366x768 el
   cuerpo de "VENTAS ÚLTIMOS 30 DÍAS" medía 18 px y el gráfico seguía midiendo
   52: los 34 px de abajo —justo donde va la curva— quedaban tapados por el
   `overflow: hidden` de la tarjeta, y lo que se veía era la franja de arriba,
   vacía. O sea: el gráfico no se "achicaba", se CORTABA, y cortado se leía
   como "no se vendió nada". Medido también en 1280x800: 22 px tapados en las
   dos tarjetas con gráfico.
   Ahora el gráfico se queda con el alto que haya y se dibuja ENTERO; cuando
   ese alto no alcanza para los ejes, `acomodarGraficoChico` (inicio.js) los
   apaga y deja sólo la curva, para que no quede media etiqueta cortada. */
.tarjeta-insight .grafico.chico { flex: 1; height: auto; min-height: 0; }
/* Las mini-barras, calcadas del canvas de Windows (MiniInsightCard): allá el
   alto de cada renglón se CALCULA con el alto disponible —
   `row_h = max(14, min(20, h / cantidad))`, ui/main_window.py:1704— así que
   primero se achica el renglón y recién después sobra alguno. Acá igual:
   inicio.js mide el cuerpo y escribe --alto-fila-barra (14 a 20 px); abajo de
   16 px se esconde la barrita (clase .apretadas) y el renglón queda sólo texto. */
.barras { display: flex; flex-direction: column; gap: 2px; min-height: 0; overflow: hidden; }
.fila-barra { display: grid; grid-template-columns: 1fr auto; grid-template-rows: 1fr auto; gap: 0 10px; height: var(--alto-fila-barra, 20px); line-height: 1.15; overflow: hidden; font-size: var(--letra-normal); color: var(--dash-text-detail); }
.fila-barra .et { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; align-self: center; }
.fila-barra .v { font-weight: 400; color: var(--dash-text-title); align-self: center; }
.fila-barra .barrita { grid-column: 1 / -1; height: 3px; align-self: end; }
.barras.apretadas .fila-barra { grid-template-rows: 1fr; }
.barras.apretadas .barrita { display: none; }
/* Los 9 KPI de la derecha (Diego: *"las tarjetas de la derecha siempre tienen
   que ocupar el alto de la pantalla"*). En Windows es una columna de 256 px con
   tarjetas de 66 px de mínimo pegadas arriba; acá se reparten el alto en partes
   iguales (`minmax(0, 1fr)`) y cada una va centrada en su lugar, para que la
   columna llegue abajo aunque la tarjeta tenga un tope (ver `.columna-kpi .kpi`). */
.columna-kpi { display: grid; grid-auto-rows: minmax(0, 1fr); align-items: center; gap: clamp(4px, 0.7vh, 8px); min-height: 0; }
.kpi { text-align: left; cursor: pointer; font-family: inherit; color: inherit; width: 100%; }
/* OJO: de acá para abajo todo va con `.columna-kpi` adelante. La clase `.kpi`
   suelta también la usan Reportes y Contabilidad, y un `max-height` ahí les
   cortaría las tarjetas. */
/* `height: 100%` + `max-height: min(150px, 100%)`: el 100% es el alto que le
   tocó en la columna, así que la tarjeta OCUPA su lugar (Diego: *"las tarjetas
   de la derecha siempre tienen que ocupar el alto de la pantalla"*) y NUNCA se
   sale de él —con `112px` a secas sobresalía 5 a 9 px y reaparecía el scroll en
   800 y 720 px de alto—; y el 150 es el tope para que con 5 tarjetas (sin el
   permiso de ver montos) no queden globos de 190 px: con 9 nunca llega a
   tocar (miden entre 50 y 95) y con 5 quedan casi tan juntas como con 9. */
.columna-kpi .kpi { display: flex; flex-direction: column; justify-content: center; height: 100%; max-height: min(150px, 100%); overflow: hidden; padding: clamp(4px, 0.8vh, 10px) 12px clamp(4px, 0.8vh, 10px) 16px; }
/* El detalle es lo primero que cede adentro de la tarjeta: dos renglones,
   después uno, y recién al final desaparece. Cuántos entran lo decide
   `acomodarKpis` en views/inicio.js, midiendo tarjeta por tarjeta — acá queda
   el valor de arranque. */
.columna-kpi .kpi .detalle { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
/* Los tres renglones no se dejan apretar por el flex: si el navegador podía
   achicarlos, el detalle quedaba cortado AL MEDIO (medido en 800 px de alto: el
   renglón medía 7 px con una línea de 17). O entra entero, o no se muestra. */
.columna-kpi .kpi .titulo, .columna-kpi .kpi .valor, .columna-kpi .kpi .detalle { flex: none; }
/* El título y el valor son de UNA sola línea: ahí el interlineado no se lee
   como aire entre renglones, y con el 1,55 del sistema la tarjeta no llegaba a
   entrar el renglón de detalle que Windows sí muestra (allá el KpiCard entero
   entra en 66 px). NO se toca el tamaño de la letra, y el detalle conserva el
   interlineado del sistema porque ése sí puede ser de dos renglones. */
.columna-kpi .kpi .titulo, .columna-kpi .kpi .valor { line-height: 1.25; }
.kpi:hover { background: var(--dash-bg-card-hover); }
.lista-alertas { display: flex; flex-direction: column; gap: 6px; }
.fila-alerta { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border: 1px solid var(--dash-border-card-soft); background: var(--dash-bg-card-soft); border-radius: 12px; }
.fila-alerta .punto-alerta { font-size: 15px; }
.fila-alerta .texto { flex: 1; min-width: 0; }
.fila-alerta .texto .t { font-weight: 600; }
.fila-alerta .texto .d { font-size: var(--letra-chica); color: var(--text-secondary); }
/* Las dos tandas de la ventana de Alertas (#651, Diego 13/10/2026): arriba las pendientes de ver, abajo las que
   ya miró y no descartó. El título lleva el color, no el fondo del renglón: la lista tiene que seguir leyéndose
   igual de tranquila con 80 alertas. */
.titulo-alertas { font-size: var(--letra-chica); font-weight: 700; text-transform: uppercase; letter-spacing: .4px; margin: 10px 0 4px; }
.titulo-alertas:first-child { margin-top: 0; }
.titulo-alertas.pendientes { color: #ef4444; }
.titulo-alertas.vistas { color: #22c55e; }
.fila-alerta.vista { border-color: color-mix(in srgb, #22c55e 35%, var(--dash-border-card-soft)); }
/* Asesor MAJO y la tarjeta de soporte del Inicio (AsesorIACard y
   SoporteDashboardCard de Windows) */
.tarjeta-asesor { display: flex; flex-direction: column; gap: 6px; padding: 10px 12px; }
.tarjeta-asesor .cab-asesor { display: flex; align-items: center; gap: 8px; }
.tarjeta-asesor .cab-asesor .ico { display: inline-flex; color: var(--grafico-1); }
.tarjeta-asesor .titulo { font-size: var(--letra-subtitulo); font-weight: 700; color: var(--dash-text-title); text-transform: none; letter-spacing: 0; }
.tarjeta-asesor .fila-asesor { display: flex; gap: 8px; }
.tarjeta-asesor .fila-asesor .entrada { flex: 1; }
/* La respuesta del asesor se topea con el alto de la ventana, no en 120 px
   fijos: una respuesta larga estiraba la tarjeta y le robaba el alto a los
   gráficos, que es lo que Diego mira primero. */
.respuesta-asesor { font-size: var(--letra-normal); color: var(--dash-text-detail); white-space: pre-wrap; max-height: clamp(38px, 11vh, 120px); overflow-y: auto; }
.tarjeta-soporte { display: grid; grid-template-columns: 3fr 2fr; gap: 20px; align-items: start; }
.tarjeta-soporte .titulo { display: flex; align-items: center; gap: 8px; font-size: var(--letra-subtitulo); font-weight: 700; color: var(--dash-text-title); margin-bottom: 8px; }
.tarjeta-soporte .titulo .ico { display: inline-flex; color: var(--grafico-2); }
/* #691: con el boton "Con usuarios" son tres. En una pantalla angosta pasan al renglon
   de abajo en vez de desbordar la tarjeta. */
.tarjeta-soporte .fila { display: flex; gap: 8px; flex-wrap: wrap; }
.tarjeta-soporte .col-consultas .boton { white-space: nowrap; }
.tarjeta-soporte .col-manual .entrada { flex: 1; }
@media (max-width: 800px) { .tarjeta-soporte { grid-template-columns: 1fr; gap: 12px; } }

.acceso.arrastrando { opacity: 0.5; }
.acceso.destino { outline: 2px dashed var(--border-input-focus); }
/* Abajo de 1100 px de ANCHO el Inicio se apila: el centro arriba y los KPI
   abajo en tres columnas. Ahí ya no hay manera de que entre todo sin scroll en
   una pantalla normal, así que se deja scrollear y cada fila vuelve a medir lo
   suyo: es mejor que recortarlo todo. (Antes el corte estaba en 1250 px y la
   pantalla se volvía casi el doble de alta de un píxel al otro.) */
@media (max-width: 1100px) {
  .inicio { grid-template-columns: minmax(0, 1fr); }
  /* Apilado manda `grid-auto-rows: max-content` (más abajo, en
     `.panel-modulo > .inicio`): si acá quedaran las dos filas explícitas, esa
     regla no aplicaría a la fila del contenido y el navegador volvería a
     aplastar las tarjetas — el mismo bug que ya estaba documentado ahí. Por
     eso se apagan. */
  .inicio { grid-template-rows: none; }
  /* Y en el celular la barra sí puede ocupar dos renglones: ahí el Inicio
     scrollea, así que no cuesta alto que no se tenga, y con los botones al
     lado del desplegable no entraba nada. */
  .barra-inicio { flex-wrap: wrap; }
  .barra-inicio .grupo-acomodar { margin-left: 0; }
  /* Apilado se vuelve a la PILA de siempre: cada tarjeta mide lo suyo y la hoja
     scrollea. Es importante que sea `flex` y no la grilla de filas de arriba:
     con la grilla, como el alto del Inicio ya no alcanza para nada, el navegador
     le da alto CERO a las filas flexibles y las tarjetas quedan aplastadas
     (medido en el celular: la tarjeta del gráfico quedaba en 21 px con el
     gráfico de 150 px adentro). */
  .centro-inicio { display: flex; flex-direction: column; }
  .tarjeta-grafico .grafico { flex: none; height: 150px; min-height: 0; }
  .grilla-insights { grid-auto-rows: auto; }
  .cuerpo-insight { flex: none; }
  .tarjeta-insight .grafico.chico { flex: none; height: 96px; }
  .columna-kpi { grid-template-columns: repeat(3, 1fr); grid-auto-rows: minmax(66px, auto); }
  .columna-kpi .kpi { max-height: none; height: auto; }
}
@media (max-width: 800px) { .fila-graficos, .grilla-insights { grid-template-columns: 1fr; } .columna-kpi { grid-template-columns: 1fr 1fr; } }

/* ---- la escalera de degradación por ALTO de ventana ----
   Diego: *"si se achica demasiado, ocultar info pero nunca superponer"*. El
   orden es: primero cede el AIRE (los clamp() de gap y padding de todo el
   bloque), después el ALTO DEL GRÁFICO, después el detalle de la tarjeta del
   gráfico (a un renglón), y recién al final se ESCONDE algo, de lo menos
   importante a lo más: el subtítulo del "Resumen operativo", el "Año actual" de
   los gráficos, la respuesta del Asesor y, última, la tarjeta de soporte
   (buscar en el manual + mis consultas). El detalle de los KPI y los renglones
   de las mini-barras no están acá: los decide inicio.js midiendo, tarjeta por
   tarjeta. Sólo aplica con el Inicio en dos columnas (arriba de 1100 px de
   ancho), porque apilado ya scrollea. */
@media (min-width: 1101px) and (max-height: 880px) {
  :root { --alto-min-grafico: 76px; }
  /* 5 px arriba y abajo en vez de los ~7 del clamp: con eso el renglón de
     detalle sigue entrando hasta los 800 px de alto (medido: necesita 54 px y
     la tarjeta da 54,4). Debajo de eso ya no entra y se esconde solo. */
  .columna-kpi .kpi { padding-block: 5px; }
}
@media (min-width: 1101px) and (max-height: 820px) {
  :root { --alto-min-grafico: 66px; }
  .tarjeta-grafico .detalle { -webkit-line-clamp: 1; }
  /* El subtítulo largo del "Resumen operativo" ya no está en el renglón: se
     fue adentro del "?" (Diego, 4.2), así que no hay nada que esconder acá. */
}
@media (min-width: 1101px) and (max-height: 700px) {
  :root { --alto-min-grafico: 58px; }
  .respuesta-asesor { display: none; }
  .tarjeta-grafico .sub { display: none; }
}
/* Un escalón más, agregado el 23/09/2026 con la barra de sucursal. Medido: la
   tarjeta del gráfico necesita 132 px por dentro (8 de padding + 52 de
   cabecera + 6 de margen + 58 de gráfico + 8) y entre 621 y 665 px de alto de
   ventana la fila le da 120..127 — o sea que le recortaba el eje de abajo 7 a
   14 px. Abajo de 621 se esconde la tarjeta de soporte y sobra de nuevo, así
   que es una franja angosta, pero es justo la de una notebook de 1366x768 con
   el navegador con barras. Baja el piso del gráfico a 46 px: 8+52+6+46+8 = 120,
   que es el mínimo de la fila, así que en toda la franja entra entero.
   No afecta a nadie más: `--alto-min-grafico` sólo manda cuando la tarjeta
   está apretada; sin la barra de sucursal, a 650 px el gráfico mide 72 y este
   piso ni se toca. */
@media (min-width: 1101px) and (max-height: 665px) { :root { --alto-min-grafico: 46px; } }
@media (min-width: 1101px) and (max-height: 620px) { .tarjeta-soporte { display: none; } }

/* El título no se deja achicar a la fuerza: si no entra, lo que se recorta con
   puntos suspensivos es el texto del propio título (`.titulo-seccion h2`), no
   el "?" que lo explica. */
.resumen-cab > * { min-width: 0; }

/* ============================ TABLERO EDITABLE DEL INICIO ============================ */
/* Diego (23/09): *"Hacelo editable en principio con lo que tenemos y con lo que
   hay en reportes… que pueda elegir qué poner y dónde. Se va a comportar como un
   espacio donde puedo poner un gráfico y agrandar, como si fuese un widget"*.

   TODO ESTE BLOQUE ES EL INICIO A MEDIDA, y se usa SÓLO si el usuario guardó su
   propia disposición o mientras la está acomodando. El Inicio de fábrica se
   sigue dibujando con `.inicio` / `.centro-inicio` / `.columna-kpi` de más
   arriba, sin pasar por acá: por eso, para el que nunca tocó el botón, no se
   puede correr ni un píxel de lugar.

   PARA VOLVER ATRÁS: borrar este bloque entero y el tramo marcado
   "▼▼▼ TABLERO EDITABLE" de views/inicio.js. */
.tablero-inicio { display: flex; flex-direction: column; gap: clamp(6px, 0.9vh, 12px); min-height: 0; }
/* UNA SOLA BARRA, la misma del Inicio de fábrica (`.barra-inicio`, más
   arriba). Antes el tablero tenía DOS renglones arriba —el de sucursal y el
   del tablero—: entrar al modo editar le comía un renglón entero de alto y
   todo lo de abajo se corría de lugar. Ahora pasar de fábrica a tablero no
   cambia ni el alto ni la posición de nada. */
.tablero-inicio > .barra-inicio { flex: none; }
/* La cuadrícula: 20 columnas iguales y filas que se reparten el alto que hay
   (`minmax(…, 1fr)`), igual que hace el Inicio de fábrica con sus filas.

   POR QUÉ 20 x 18 Y NO 6 x 4 (23/09/2026). Diego: *"cuando se agranda un
   widget se agranda mucho, la cuadrícula debería ser más chica"*. Con 6
   columnas un paso era el 17 % de la pantalla. Y además —esto es lo más
   importante— los números están elegidos para que el Inicio de fábrica se
   pueda dibujar con esta misma cuadrícula sin mover nada: 16 columnas para el
   centro + 4 para la columna de indicadores, y 18 filas donde cada indicador
   son 2 (los 83 px medidos), los gráficos 7 y el Resumen operativo 5. Está
   todo medido en views/inicio.js, arriba de COLUMNAS_TABLERO.

   LOS DOS AIRES SON DISTINTOS a propósito: el de las columnas es el del Inicio
   (9 px) y el de las filas es el de la columna de indicadores (7 px), que es
   la pieza más apretada y la que tiene que caer exacta.

   EL MÍNIMO DE FILA BAJÓ DE 58 A 18 px: con 18 filas, 58 px cada una daban
   1.100 px de alto mínimo y el tablero arrancaba scrolleando en cualquier
   pantalla. Con 18 px el piso total son 551 px, o sea que entra hasta en una
   ventana de 650. Sigue siendo el cinturón de siempre: si alguien amontona
   muchas filas, SU tablero scrollea en vez de aplastarse — el de fábrica no
   scrollea nunca, que es la regla que pidió Diego (4.3).

   SIN `dense` Y SIN AUTO-FLOW desde el 23/09. Antes era `grid-auto-flow: row
   dense`, que acomodaba los widgets uno atrás del otro y RELLENABA los huecos
   solo. Eso es exactamente lo que Diego no quería: *"no me permite dejar un
   hueco vacío porque tiende a reacomodarse y estirarse"*. Ahora cada widget
   dice en qué columna y en qué fila va (las variables --col y --fila, que
   escribe views/inicio.js), así que una celda vacía se queda vacía. Las filas
   siguen siendo implícitas: la cuadrícula crece hacia abajo sola hasta la fila
   más alta que alguien haya usado. */
.grilla-tablero { flex: 1; min-height: 0; display: grid; grid-template-columns: repeat(var(--cols-tablero, 20), minmax(0, 1fr)); grid-auto-rows: minmax(18px, 1fr); column-gap: clamp(6px, 0.9vh, 12px); row-gap: clamp(4px, 0.7vh, 8px); overflow-y: auto; align-content: stretch; }
/* #671 · Word 12.6 (Diego, 17/10/2026): *"como está lleno, si agrego algo, se compactan algunos y
   muestran menos información"*. Y es cierto: los renglones son `1fr`, así que siempre entran todos
   —achicándose— y la barra de `overflow-y` de arriba no llega a aparecer nunca. Con el alto fijo el
   renglón pasa a medir lo suyo y ahí sí scrollea. Es un interruptor del usuario: de fábrica, nada
   cambia. `align-content: start` es lo que evita que el sobrante se reparta entre las filas. */
.grilla-tablero.alto-fijo { grid-auto-rows: minmax(var(--alto-fila-tablero, 34px), auto); align-content: start; }
/* `var(--col, auto)` y no un número pelado: sin --col (el celular, donde el
   media query de abajo manda) se comporta como antes, `auto / span ancho`. */
/* `overflow: hidden` NO es decoración (23/09 a la tarde, medido): hay tarjetas
   cuyo contenido no se puede comprimir más allá de cierto alto —la de soporte,
   con sus dos cuadros de texto y sus botones, es la peor—. Sin esto, en una
   celda más baja que eso la tarjeta se desbordaba, y ese desborde le daba
   scroll a TODA la cuadrícula: entre 8 y 34 px medidos en 1440x900, 1366x800,
   1280x720 y 1280x650. O sea que el Inicio volvía a scrollear, que es
   justamente lo que Diego no quiere (4.3). Con el recorte, lo que no entra se
   oculta —nunca se superpone— y la cuadrícula entra entera en la pantalla en
   todos los tamaños probados. Si a alguien le queda una tarjeta cortada, la
   agranda o la saca: el tablero lo arma él. */
.widget { position: relative; grid-column: var(--col, auto) / span var(--ancho, 1); grid-row: var(--fila, auto) / span var(--alto, 1); min-width: 0; min-height: 0; overflow: hidden; display: flex; flex-direction: column; }
.widget > * { flex: 1; min-width: 0; min-height: 0; }
/* Las tarjetas de KPI se comportan igual que en la columna de la derecha del
   Inicio de fábrica: OCUPAN el lugar que les tocó (`flex: 1`, el `height:100%`
   de allá), con el mismo tope de 150 px para que en una celda muy alta no
   quede un globo, y centradas en lo que sobra.
   El `flex: 0 1 auto` de antes hacía que la tarjeta midiera lo que mide su
   contenido: en el tablero quedaban de 72 y 89 px donde en el de fábrica
   miden 83, y eso solo ya se veía como "se desacomodó". */
.widget > .kpi { flex: 1 1 auto; margin-block: auto; max-height: min(150px, 100%); overflow: hidden; padding: clamp(4px, 0.8vh, 10px) 12px clamp(4px, 0.8vh, 10px) 16px; }
.widget > .kpi .titulo, .widget > .kpi .valor, .widget > .kpi .detalle { flex: none; }
.widget > .kpi .titulo, .widget > .kpi .valor { line-height: 1.25; }
.widget > .kpi .detalle { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
/* Las tarjetas nuevas que llevan una tabla o una lista adentro (sugerencias,
   alertas): cabecera fija y cuerpo con su propio scroll, para que la tarjeta
   nunca empuje al resto del tablero. */
.tarjeta-widget { display: flex; flex-direction: column; min-height: 0; overflow: hidden; padding: 10px 12px; }
.cab-widget { flex: none; display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 6px; }
.cab-widget .titulo { font-size: var(--letra-chica); color: var(--dash-text-muted); font-weight: 800; letter-spacing: 0.6px; text-transform: uppercase; }
.cuerpo-widget { flex: 1; min-height: 0; overflow: auto; }
/* La escalera de degradación por alto de ventana (más arriba) esconde en
   pantallas bajas la tarjeta de soporte, la respuesta del Asesor y el "Año
   actual" de los gráficos. En el tablero a medida NO: ahí cada widget lo puso
   el usuario, y esconderle el contenido le dejaría un rectángulo vacío
   ocupando lugar. Si no le entra, lo saca él. */
.tablero-inicio .tarjeta-soporte { display: grid; }
.tablero-inicio .respuesta-asesor { display: block; }
.tablero-inicio .tarjeta-grafico .sub { display: block; }
/* --- modo editar --- */
.grilla-tablero.editando .widget { outline: 1px dashed var(--border-input-focus); outline-offset: 2px; border-radius: 16px; cursor: grab; }
/* Mientras se edita, la tarjeta no responde: un clic en un KPI abriría su
   módulo justo cuando lo estás agarrando para moverlo. El tirador de la esquina queda afuera de la
   regla (#685): si no, no se lo podría agarrar. */
.grilla-tablero.editando .widget > *:not(.editor-widget):not(.tirador-tamano) { pointer-events: none; }
/* ── EL TIRADOR DE LA ESQUINA (#685 · Word 12.9 punto 9) ──
   Diego: *"tiene que dejar agrandar las tarjetas arrastrando el borde, no con + y −"*. Va abajo a la
   derecha, como en cualquier ventana, y con las dos rayitas en diagonal de siempre, que es lo que lo
   hace reconocible sin que nadie lo explique. 18 px: más chico no se agarra con el mouse. */
.tirador-tamano { position: absolute; right: 0; bottom: 0; width: 18px; height: 18px; z-index: 3;
  cursor: nwse-resize; border-bottom-right-radius: 16px; opacity: 0.55; transition: opacity 0.12s ease;
  background:
    linear-gradient(135deg, transparent 0 46%, currentColor 46% 56%, transparent 56% 100%) no-repeat,
    linear-gradient(135deg, transparent 0 68%, currentColor 68% 78%, transparent 78% 100%) no-repeat;
  color: var(--dash-text-muted); }
.tirador-tamano:hover, .widget.redimensionando .tirador-tamano { opacity: 1; color: var(--border-input-focus); }
/* Mientras se estira, el cursor es el mismo en toda la pantalla: si no, al pasar por encima de otra
   tarjeta cambia a la manito de arrastrar y parece que se soltó. */
.grilla-tablero.redimensionando, .grilla-tablero.redimensionando .widget { cursor: nwse-resize; }
.grilla-tablero .widget.redimensionando { outline: 2px solid var(--border-input-focus); outline-offset: -1px; border-radius: 16px; }
/* El que estás moviendo queda bien atenuado: lo que tenés que mirar es el
   fantasma que va con el puntero, no el hueco que dejó. */
.grilla-tablero.editando .widget.arrastrando { opacity: 0.4; }
.grilla-tablero.moviendo, .grilla-tablero.moviendo .widget { cursor: grabbing; }
/* El que se va a intercambiar (mismo tamaño): se marca ÉL TAMBIÉN, porque se
   va a mover aunque nadie lo haya tocado. */
.grilla-tablero .widget.intercambio { outline: 2px dashed var(--verde-majo-claro, #22c55e); outline-offset: -2px; border-radius: 16px; }
/* ── DÓNDE VA A CAER: el recuadro punteado, el mismo gesto que las pestañas ──
   Diego (23/09): *"fijate en las pestañas: cuando se agarra se arrastra una
   sombra y donde se pone aparece como punteado. Algo así estaría bien"*. Es un
   elemento propio de la cuadrícula (no una rayita al costado del vecino), así
   que se ve la celda ENTERA que va a ocupar, del tamaño que va a tener. */
.celda-destino { grid-column: var(--col, 1) / span var(--ancho, 1); grid-row: var(--fila, 1) / span var(--alto, 1); border-radius: 16px; pointer-events: none; z-index: 1; }
.celda-destino.libre { outline: 2px dashed var(--border-input-focus); outline-offset: -2px; background: color-mix(in srgb, var(--border-input-focus) 12%, transparent); }
.celda-destino.intercambio { outline: 2px dashed var(--verde-majo-claro, #22c55e); outline-offset: -2px; background: color-mix(in srgb, var(--verde-majo-claro, #22c55e) 12%, transparent); }
/* Ocupado por algo de otro tamaño: no se puede soltar y se dice en rojo, con
   el cursor de prohibido. No se empuja a nadie (ver el comentario grande de
   "LA CELDA OCUPADA" en views/inicio.js). */
.celda-destino.ocupado { outline: 2px dashed var(--bg-danger); outline-offset: -2px; background: color-mix(in srgb, var(--bg-danger) 12%, transparent); }
.grilla-tablero.moviendo:has(.celda-destino.ocupado), .grilla-tablero.moviendo:has(.celda-destino.ocupado) .widget { cursor: not-allowed; }
/* La fila vacía de más: el renglón nuevo adonde se puede bajar un widget.
   Apenas insinuada, y SÓLO MIENTRAS ARRASTRÁS (23/09 a la tarde).
   Antes estaba puesta todo el tiempo que durara el modo editar, y eso tenía un
   costo que se vio recién al medir: una fila más son 19 en vez de 18, o sea
   que TODAS las tarjetas se achican un 5 % apenas apretás "Acomodar" (medido:
   los indicadores pasaban de 83 a 78 px y la última se corría 38 px). Era una
   parte de lo que Diego veía como *"se desacomoda todo"*.
   Mostrándola sólo con el widget en la mano, el modo editar en reposo queda
   calcado al Inicio de fábrica, que es lo que importa. El acomodamiento de esa
   fila de más pasa a ocurrir cuando ya tenés la tarjeta levantada y estás
   mirando el fantasma que sigue al puntero. */
.fila-extra { display: none; grid-column: 1 / -1; grid-row: var(--fila, 1) / span 1; border-radius: 16px; border: 1px dashed var(--dash-border-card-soft); opacity: 0.5; pointer-events: none; }
.grilla-tablero.moviendo .fila-extra { display: block; }
/* En el celular no hay celdas: ahí se sigue marcando arriba/abajo del vecino,
   pero con el mismo punteado y no con la rayita fina de antes. */
.grilla-tablero .widget.destino-antes { box-shadow: inset 0 4px 0 var(--border-input-focus); outline: 2px dashed var(--border-input-focus); outline-offset: -2px; border-radius: 16px; }
.grilla-tablero .widget.destino-despues { box-shadow: inset 0 -4px 0 var(--border-input-focus); outline: 2px dashed var(--border-input-focus); outline-offset: -2px; border-radius: 16px; }
/* ── LA BARRITA DE EDICIÓN: SÓLO EN LA TARJETA QUE APUNTÁS (23/09/2026) ──
   Diego: *"las tarjetas una vez que se presiona el botón para reordenar como
   que pierden información, no muestran lo mismo que mostraban al principio"*.
   Medido: esta barrita tapaba el título y el número grande de LAS 18 tarjetas
   ("VENTAS DEL AÑO 2026 / $ 58.841.728", el título de cada KPI, la cabecera de
   cada tarjeta del Resumen). Era el propio *"ocultar info pero nunca
   superponer"* roto.
   Ahora aparece sólo en la tarjeta que tenés debajo del mouse o enfocada con
   el tabulador: en reposo se ven las 18 enteras y la única que se tapa un
   momento es justo sobre la que vas a actuar. En pantalla táctil, donde no hay
   mouse que pasar, se muestra siempre (ver el `@media (hover: none)` de abajo);
   y mientras arrastrás se apagan todas, para ver dónde estás soltando.
   Que existe lo dice el "?" de la barra de arriba, con todas las letras. */
.editor-widget { position: absolute; left: 4px; right: 4px; top: 4px; z-index: 3; display: flex; align-items: center; gap: 4px; padding: 2px 4px; border-radius: 10px; background: var(--bg-menu); border: 1px solid var(--border-input-focus); font-size: var(--letra-chica); box-shadow: var(--sombra-popup); opacity: 0; pointer-events: none; transition: opacity 0.12s ease; }
.grilla-tablero.editando .widget:hover > .editor-widget,
.grilla-tablero.editando .widget:focus-within > .editor-widget { opacity: 1; pointer-events: auto; }
.grilla-tablero.moviendo .editor-widget { opacity: 0 !important; pointer-events: none !important; }
@media (hover: none) {
  .grilla-tablero.editando .editor-widget { opacity: 1; pointer-events: auto; }
}
.editor-widget .nombre { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 700; color: var(--text-primary); }
.editor-widget .grupo-medida { display: inline-flex; align-items: center; gap: 2px; color: var(--text-secondary); }
.editor-widget .grupo-medida .et { opacity: 0.7; }
.editor-widget .num { min-width: 10px; text-align: center; font-weight: 800; }
.editor-widget .mini { width: 20px; height: 20px; border-radius: 6px; border: 1px solid var(--border-button); background: var(--bg-button); color: var(--text-primary); font-weight: 800; line-height: 1; cursor: pointer; display: grid; place-items: center; padding: 0; }
.editor-widget .mini:hover { background: var(--bg-button-hover); }
.editor-widget .mini:disabled { opacity: 0.35; cursor: default; }
.editor-widget .mini.sacar { color: #fff; background: var(--bg-danger); border-color: transparent; }
/* la lista del popup "Agregar al Inicio" */
.fila-catalogo { display: flex; align-items: center; gap: 12px; padding: 6px 8px; border: 1px solid var(--dash-border-card-soft); background: var(--dash-bg-card-soft); border-radius: 12px; margin-top: 6px; }
.fila-catalogo .texto { flex: 1; min-width: 0; }
.fila-catalogo .texto .t { font-weight: 600; }
/* En el celular el tablero es UNA sola columna y vuelve a scrollear, igual que
   el Inicio de fábrica apilado. */
@media (max-width: 1100px) {
  /* `flex: none` es LO IMPORTANTE de este bloque: con `flex: 1` la grilla se
     queda con el alto que sobra de la pantalla y, como ahí ya no entra nada,
     el navegador le da casi cero a cada fila y las tarjetas se aplastan una
     arriba de otra (medido en 390 px: renglones de 30 px con el texto
     superpuesto). Apilado, la grilla mide lo que miden sus tarjetas y el
     scroll lo pone el contenedor de afuera — el mismo problema y el mismo
     arreglo que ya tenía `.centro-inicio`. */
  .grilla-tablero { flex: none; grid-template-columns: 1fr; grid-auto-rows: auto; overflow: visible; }
  .grilla-tablero .widget { grid-column: 1 / -1; grid-row: auto; }
  .widget > .kpi { max-height: none; margin-block: 0; }
  /* Las marcas de destino (arriba/abajo del vecino) ya están arriba con el
     punteado: acá no hace falta repetirlas. Lo que sí se apaga es la fila
     vacía de más, que en una sola columna no significa nada. */
  /* Con la misma fuerza que la regla de arriba que la enciende al arrastrar:
     en una sola columna la fila de más no significa nada y no tiene que
     aparecer ni con la tarjeta en la mano. */
  .grilla-tablero .fila-extra, .grilla-tablero.moviendo .fila-extra { display: none; }
  /* Y el tirador de la esquina tampoco (#685): apilado, el ancho y el alto de cada tarjeta los pone
     el teléfono, así que no habría nada que estirar. Los + y − de la barrita siguen estando. */
  .tirador-tamano { display: none; }
}

/* caja de totales de un comprobante (detalle de venta, cobro): la misma en todos los popups */
.caja-totales { background: var(--pos-bg-surface); border: 1px solid var(--pos-border-surface); border-radius: 12px; padding: 10px 14px; }
.caja-totales .fila { display: flex; justify-content: space-between; font-size: var(--letra-normal); color: var(--text-secondary); gap: 12px; }
.caja-totales .total { display: flex; justify-content: space-between; font-size: var(--letra-titulo); font-weight: 800; color: var(--text-title); margin-top: 4px; gap: 12px; }
/* Un renglón de la caja que SE ESCRIBE (hoy sólo el Redondeo de la carga de la factura). #651 (Diego, 13/10/2026,
   Word 12.2, punto 11): *"El campo de redondeo es más grande que el renglón y se ve mal… el importe tiene que quedar
   alineado con los números de arriba"*. El campo se disfraza de renglón: misma letra, mismo alto, pegado a la
   derecha como los demás números, y el marco sólo aparece al pasar por encima o al escribir — igual que en las
   grillas de carga. */
/* #659 punto 10 (Diego, 14/10/2026): *"Está bien en tamaño, pero ahora no tiene el «recuadrito» que antes
   tenía! Sin eso no se sabe si se puede editar o no"*. Las dos cosas son ciertas y no se pelean: el alto y la
   alineación del 13/10 se quedan, y para que SE NOTE que se escribe se usa la misma marca que ya tiene Majo en
   las grillas de sólo lectura (`td.celda-editable`, Word 5.4): un fondo apenas teñido y una rayita abajo. No es
   un marco nuevo — es el gesto que él ya aprobó para "esto se puede tocar". */
.caja-totales .fila .entrada {
  width: 130px; flex: none; text-align: right; font-size: var(--letra-normal); color: var(--text-secondary);
  min-height: 0; height: auto; padding: 0 4px; margin: -1px 0; border-color: transparent; box-shadow: none;
  background: color-mix(in srgb, var(--bg-primary) 8%, transparent);
  border-bottom-color: var(--border-input); border-radius: 4px 4px 0 0;
}
.caja-totales .fila .entrada:hover:enabled { border-color: var(--border-input); }
.caja-totales .fila .entrada:focus { border-color: var(--border-input-focus); background: var(--bg-input); color: var(--text-primary); box-shadow: 0 0 0 2px color-mix(in srgb, var(--border-input-focus) 30%, transparent); }

/* ============================ solapas de módulos (tabs_modulos de Windows) ============================ */
/* Diego, 22/09: no hay solapa de Inicio (a la derecha están Panel y Ampliar,
   como en Windows) y las solapas no pueden verse cortadas abajo — por eso la
   tira que hace scroll tiene aire abajo y cada solapa lleva su borde entero. */
.solapas-modulos { display: flex; align-items: center; gap: 8px; padding: 0 2px; }
.solapas-scroll { display: flex; align-items: center; gap: 6px; flex: 1; min-width: 0; overflow-x: auto; padding: 2px 2px 4px; }
.solapa-modulo { display: inline-flex; align-items: center; gap: 8px; background: var(--bg-button); color: var(--text-secondary); border: 1px solid var(--border-button); border-radius: var(--radio-boton); padding: 0 12px; font-weight: 600; cursor: pointer; white-space: nowrap; flex: none; }
/* Las pestañas y el botón "Panel" miden LO MISMO (Diego, 4.2), y desde el
   Word 6.3 es el alto de todos los botones de Majo (*"agrandá un poco el
   botón, usá el mismo tamaño que usan todos los botones"*). */
.solapa-modulo, .solapas-modulos .boton { min-height: var(--alto-boton); height: var(--alto-boton); line-height: 1; }
.solapa-modulo .ico { display: inline-flex; align-items: center; color: var(--mod-color); }
.solapa-modulo.activa .ico { color: var(--mod-color); }
.solapa-modulo:hover { background: var(--bg-button-hover); color: var(--text-primary); }
.solapa-modulo.activa { background: var(--bg-page-card); color: var(--text-title); border-color: var(--border-input-focus); box-shadow: 0 0 0 1px var(--border-input-focus); }
.solapa-modulo .cerrar { opacity: 0.55; font-size: var(--letra-subtitulo); line-height: 1; padding: 0 2px; border-radius: 6px; }
.solapa-modulo .cerrar:hover { opacity: 1; background: var(--bg-danger); color: #fff; }
/* Arrastrar la pestaña para cambiarle el lugar: los MISMOS nombres de clase
   que ya usa el rail de Accesos (.acceso.arrastrando / .acceso.destino), para
   no inventar un vocabulario nuevo. El outline va hacia adentro para que
   marcar el destino no mueva un pixel a las pestañas vecinas. */
.solapa-modulo[draggable="true"] { user-select: none; }
.solapa-modulo.arrastrando { opacity: 0.5; }
.solapa-modulo.destino { outline: 2px dashed var(--border-input-focus); outline-offset: -2px; }
.solapas-modulos #btn-panel { flex: none; }
.paneles-modulos { display: flex; flex-direction: column; min-width: 0; flex: 1; min-height: 0; }
/* La ventana aparte (botón derecho → "⧉ Abrir en ventana aparte", doble clic,
   o sacar la pestaña de la línea): SÓLO el módulo, a pantalla completa, con su
   propia barra. Sin cabecera de Majo, sin Accesos, sin pestañas y sin zócalo,
   igual que la ventana suelta de Majo Windows (_desacoplar_modulo).
   Se usa flex y no grid para que valga lo mismo con la franja de pruebas
   arriba y sin ella: el módulo se queda con todo el alto que sobra. */
.layout.solo { display: flex; flex-direction: column; padding: 8px; }
.franja-pruebas { flex: none; background: var(--bg-danger); color: #fff; font-weight: 800; font-size: var(--letra-chica); letter-spacing: 0.03em; text-align: center; border-radius: 8px; padding: 3px 8px; }
.panel-modulo { min-width: 0; flex: 1; min-height: 0; display: flex; flex-direction: column; }

/* El scroll va ADENTRO de la grilla, no en la hoja entera (Diego, 22/09): la
   cabecera de Majo, la barra del módulo y los accesos del costado quedan
   siempre a la vista, y lo único que se mueve es la lista. */
/* La tarjeta del modulo respira menos que una tarjeta comun: todo lo que se
   ahorra arriba de la grilla son filas que se ven. */
.pantalla { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.tarjeta.pantalla { padding: 10px 12px; }
.pantalla.espaciado > * + * { margin-top: 8px; }
.crece { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.crece > .tabla-contenedor { flex: 1; min-height: 0; overflow: auto; }
.crece > .cargando, .crece > .aviso { flex: none; }
/* El renglón de filtros + paginación y la grilla, juntos (#382). En la
   computadora es lo mismo que había: la paginación arriba y la grilla con el
   alto que sobra, 8 px entre las dos. Existe por el celular (ver el bloque de
   800 px): ahí este bloque mide una pantalla y la hoja frena en él. `gap` y no
   margen: con la paginación escondida (Reportes) no queda un hueco de más. */
.bloque-grilla { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 8px; }
table.tabla thead th { position: sticky; top: 0; z-index: 2; }
/* El Inicio NO scrollea (Diego, 4.3): ocupa el alto que hay y lo reparte entre
   sus tarjetas. `overflow: hidden` es el cinturón de seguridad: si con toda la
   escalera de degradación igual no entra, se recorta — nunca se superpone ni
   aparece la barra. */
.panel-modulo > .inicio { flex: 1; min-height: 0; overflow: hidden; align-content: stretch; padding-right: 2px; }
/* El Inicio A MEDIDA (tablero de widgets) se queda con el mismo alto: reparte
   lo que hay entre sus filas. El scroll, si hace falta, lo pone la grilla de
   adentro (.grilla-tablero), nunca la hoja. */
.panel-modulo > .tablero-inicio { flex: 1; min-height: 0; padding-right: 2px; }
/* Apilado (abajo de 1100 px de ancho, celular incluido) el Inicio SÍ scrollea y
   cada bloque vuelve a medir lo suyo. Va acá y no arriba, junto al resto del
   modo apilado, porque tiene que ganarle a la regla de la línea de arriba: las
   dos tienen la misma especificidad y manda la última.
   El `grid-auto-rows: max-content` es la clave: sin él, con las dos filas en
   `auto` el navegador les daba a las dos EXACTAMENTE la mitad del alto (313 px
   de 634) aunque el contenido pidiera 1578 y 493, y las tarjetas quedaban
   aplastadas — medido en el celular: la del gráfico en 21 px con el gráfico de
   150 px adentro. */
@media (max-width: 1100px) { .panel-modulo > .inicio { overflow-y: auto; align-content: start; grid-auto-rows: max-content; } }
/* Y lo mismo para el tablero a medida: apilado en una columna, el scroll vuelve
   a ser de la pantalla entera (adentro la grilla queda `overflow: visible`). */
@media (max-width: 1100px) { .panel-modulo > .tablero-inicio { overflow-y: auto; } }

@media (max-width: 800px) { .solapas-modulos { padding: 0; } .solapa-modulo { padding: 6px 10px; } }

/* ============================ modo módulo: cabecera compacta, sin zócalo, accesos en íconos (como Windows) ============================ */
.cabecera { transition: min-height .18s ease, padding .18s ease; }
.layout.modo-modulo .cabecera { min-height: 56px; padding: 6px 18px; gap: 10px; }
.layout.modo-modulo .cabecera .logo { height: 42px; }
.layout.modo-modulo .cabecera .titulo { font-size: var(--letra-titulo); }
.layout.modo-modulo .cabecera .subtitulo { display: none; }
.layout.modo-modulo .cabecera .acciones .boton { min-height: var(--alto-boton); padding: 4px 12px; }
.layout.modo-modulo .zocalo { display: none; }
.layout.modo-modulo .cuerpo { grid-template-columns: 56px 1fr; }
.layout.ampliado .accesos { display: none; }
.layout.ampliado .cuerpo, .layout.modo-modulo.ampliado .cuerpo { grid-template-columns: 1fr; }
/* Word 6.2, marcas 25 y 26, textual de Diego: *"error cuando presiono la tecla
   ampliar cuando estoy en el POS… como que se achica para un costado pero no
   amplía"*.

   Era esto, y se veía igual en TODOS los módulos, no sólo en el POS: la
   columna de accesos se esconde y `.cuerpo` pasa a UNA sola columna, pero
   `.contenido` seguía clavado en `grid-column: 2` (línea 352). Una grilla de
   una columna con un hijo pedido en la dos se inventa una segunda columna
   `auto`: el módulo se encogía al ancho de su contenido y el `1fr` de la
   columna uno —vacía, sin los accesos— se quedaba con todo el espacio libre a
   la izquierda. De ahí el módulo corrido a un costado y más angosto que antes
   de ampliar. Ahora, ampliado, el contenido ES la columna uno. */
.layout.ampliado .contenido { grid-column: 1; }
/* visibility, no display: el lugar queda reservado y nada se corre de sitio. */
.layout.modo-modulo .accesos .encabezado h2 { visibility: hidden; }
.layout.modo-modulo .acceso .t { display: none; }
/* Word 11.4 (Diego: *"cuando me posiciono y se estira, se levanta un poco porque aparecen los botones de uso y
   restaurar… se me mueve el botón! Tiene que estar fijo sin moverse"*): con los accesos en íconos, "Uso" y
   "Restaurar" no se ven pero SIGUEN OCUPANDO su lugar (visibility, no display), así Configuración queda a la
   misma altura con el panel achicado y desplegado. */
.layout.modo-modulo .accesos .pie-accesos { visibility: hidden; }
.layout.modo-modulo .accesos.desplegado .encabezado h2 { visibility: visible; }
.layout.modo-modulo .acceso { justify-content: center; padding: 4px; }
@media (max-width: 800px) { .layout.modo-modulo .cuerpo { grid-template-columns: 1fr; } }


/* ---------- #382: EN EL CELULAR la hoja sube entera y FRENA en la grilla ----------
   Hasta el 29/09 el celular copiaba a la computadora (Word 2.3: la hoja no se
   mueve, se mueve la grilla). En un teléfono eso dejaba la grilla en 6
   renglones, porque la cabecera, los módulos, la pestaña y las barras se
   comían más de media pantalla. Diego (Word Web 5.1, "Ok, hacelo!" en el
   10.1): *"que la página suba efectivamente toda, pero que tenga un freno en
   los títulos: entonces ahí, cuando frena sin ocultar los títulos y la
   paginación, es donde empieza a scrollear. Lo de arriba de la paginación se
   va todo para arriba"*.

   Cómo queda:
     · la hoja entera se desplaza (la cabecera, los módulos, la pestaña, la
       barra de ＋ Nuevo y el buscador se van para arriba);
     · la grilla de la hoja mide como mucho UNA pantalla, junto con su renglón
       de filtros y paginación (`.bloque-grilla`: el molde de las listas,
       Ventas y Reportes):
       cuando la hoja llega al fondo, ese renglón queda arriba de todo y los
       títulos de la grilla pegados abajo de él — ése es el freno;
     · desde ahí se desplazan los renglones, adentro de la grilla, con los
       títulos siempre a la vista (son `sticky`, como en la computadora);
     · la grilla no se desplaza sola ANTES del freno (el dedo apoyado en ella
       mueve la hoja): eso lo decide app.js::actualizarFrenoDeLaHoja con la
       marca `pagina-al-fondo`.
   En la computadora no cambia nada (directiva 39): todo esto vive en este
   corte de 800 px. */
@media (max-width: 800px) {
  .layout { height: auto; min-height: 100dvh; overflow-x: clip; overflow-y: visible; }
  .cuerpo, .contenido { overflow: visible; }
  /* Con una hoja más corta que la pantalla (una lista vacía) el alto que
     sobra va al módulo, nunca a la fila de íconos de los módulos: sin esto la
     fila de íconos se estiraba hasta 280 px (medido en Promociones vacío). */
  .cuerpo { grid-template-rows: auto 1fr; }
  /* El bloque de paginación + grilla: una pantalla menos lo que queda abajo
     de él (el relleno de la tarjeta y el de la hoja, ~27 px), así al llegar
     al fondo el renglón de la paginación queda arriba de todo. Sólo cuando
     adentro hay una grilla: con el "Cargando…" o un gráfico mide lo suyo. */
  .bloque-grilla:has(> .crece > .tabla-contenedor) { flex: none; max-height: calc(100dvh - 36px); }
  .bloque-grilla > .barra-herramientas { flex: none; }
  .bloque-grilla > .crece { flex: 1 1 auto; }
  /* Las grillas de la hoja que no tienen renglón de paginación arriba
     (las cinco solapas con grilla de Contabilidad, y Configuración →
     Seguridad, que también termina en una grilla suelta) frenan igual, con
     los títulos arriba de todo. */
  .pantalla > .crece > .tabla-contenedor,
  .pantalla > .crece > .espaciado > .tabla-contenedor:last-child { max-height: calc(100dvh - 36px); }
  /* Trabada hasta el freno, destrabada desde el freno. Son los MISMOS
     selectores de arriba y ninguno más: una grilla de otra parte (la de un
     popup, o una metida adentro de una tarjeta, como casi todas las de
     Configuración) sigue como siempre. */
  .bloque-grilla > .crece > .tabla-contenedor,
  .pantalla > .crece > .tabla-contenedor,
  .pantalla > .crece > .espaciado > .tabla-contenedor:last-child { overflow-y: hidden; }
  html.pagina-al-fondo .bloque-grilla > .crece > .tabla-contenedor,
  html.pagina-al-fondo .pantalla > .crece > .tabla-contenedor,
  html.pagina-al-fondo .pantalla > .crece > .espaciado > .tabla-contenedor:last-child { overflow-y: auto; }
  /* Lo mismo con la vista en TARJETAS de Productos y Contactos
     (views/productos.js::conmutadorDeVista), que reemplaza a la grilla adentro
     del mismo bloque. Su caja trae el scroll puesto en el propio elemento
     (style="overflow-y: auto"), y a eso sólo le gana un !important. */
  .bloque-grilla > .crece > .vista-tarjetas { overflow-y: hidden !important; }
  html.pagina-al-fondo .bloque-grilla > .crece > .vista-tarjetas { overflow-y: auto !important; }
  /* Con un popup abierto la hoja de atrás no se mueve: si no, al llegar al
     final de la lista del popup el dedo seguía desplazando la hoja. */
  html:has(.fondo-modal) { overflow: hidden; }
  /* OJO: los accesos siguen con su scroll de costado. Si se les pone
     "overflow: visible", los 15 íconos en fila le imponen su ancho a la hoja
     entera y el celular se va de costado (pasó el 22/09 con el POS). */
  .accesos { overflow-x: auto; overflow-y: hidden; min-width: 0; flex: none; }
  /* Y el rail NUNCA se despliega como ventana lateral en el celular (Diego,
     2.3: *"al presionar en un módulo se abre al costado una ventana"*): ahí
     los módulos son una fila de íconos arriba y se quedan así. */
  .layout.modo-modulo .accesos, .layout.modo-modulo .accesos.desplegado {
    position: static; width: auto; box-shadow: none; z-index: auto;
  }
  .layout.modo-modulo .acceso .t { display: none; }
  .layout.modo-modulo .accesos .encabezado, .layout.modo-modulo .accesos .pie-accesos { display: none; }
}

/* ============================ EL FANTASMA DE ARRASTRE ============================ */
/* Diego (23/09): *"no se nota que ya lo agarraste… fijate en las pestañas: vas
   a ver que cuando se agarra se arrastra una sombra"*.

   Las pestañas usan el drag-and-drop de HTML5 y esa sombra se la dibuja el
   NAVEGADOR solo. Los widgets del Inicio y los títulos de columna van por
   pointer events (el único que anda con el dedo), que no dibuja nada: acá está
   ese dibujo, hecho a mano. Lo arma arrastre.js y lo usan los dos.

   Está en <body> y no adentro de la grilla a propósito: con position: fixed no
   lo recorta el scroll de la tarjeta ni el de la grilla del Inicio, y con
   pointer-events: none no se mete en el camino de elementFromPoint (si no, el
   fantasma taparía siempre lo que hay abajo del puntero). */
.fantasma-arrastre {
  position: fixed; z-index: 2000; pointer-events: none; opacity: 0.85;
  border-radius: 14px; overflow: hidden; box-sizing: border-box;
  box-shadow: 0 18px 38px rgba(0, 0, 0, 0.45), 0 0 0 1px var(--border-input-focus);
  /* Sólo la opacidad hace transición: si se animara `transform`, el fantasma
     iría siempre unas décimas atrás del puntero y se sentiría pegajoso. */
  transition: opacity 0.16s ease;
  will-change: transform;
}
.fantasma-arrastre > * { display: block; margin: 0 !important; position: static !important; }
.fantasma-arrastre.soltando { opacity: 0; }
/* El de una columna es chiquito: menos sombra y menos redondeo, si no parece
   un cartel flotando. */
.fantasma-arrastre.de-columna { border-radius: 8px; box-shadow: 0 10px 22px rgba(0, 0, 0, 0.4), 0 0 0 1px var(--border-input-focus); }
/* "Reducir movimiento" del sistema: se va la inclinación (eso lo decide
   arrastre.js) y el desvanecido. El fantasma y el punteado del destino QUEDAN:
   no son adorno, son la única forma de saber qué agarraste y dónde cae. */
.fantasma-arrastre.sin-animacion, .fantasma-arrastre.sin-animacion.soltando { transition: none; }
@media (prefers-reduced-motion: reduce) {
  .fantasma-arrastre { transition: none; }
}

/* El aviso de "hay una versión nueva" (25/09/2026). Abajo a la derecha, por
   encima de todo pero sin tapar la barra de acciones de ningún módulo. */
/* #606 (06/10/2026): lo que pinta la guardia de arranque de index.html cuando
   Majo no arranca o está tardando. Va ANTES del layout: tiene que verse con
   sólo app.css cargado, centrado, en los dos temas. */
.majo-no-arranca, .majo-tardando { max-width: 520px; margin: 0 auto; padding: 24px 20px; text-align: center; color: var(--text-primary); }
.majo-no-arranca { min-height: 100vh; display: flex; flex-direction: column; justify-content: center; gap: 12px; }
.majo-no-arranca h1 { font-size: var(--letra-titulo); color: var(--text-title); }
.majo-no-arranca .detalle { font-family: ui-monospace, Consolas, monospace; font-size: var(--letra-chica); color: var(--text-muted); word-break: break-word; }
.majo-no-arranca .boton, .majo-tardando .boton { align-self: center; margin: 0 auto; }
.majo-tardando { display: flex; flex-direction: column; gap: 10px; margin-top: -30vh; }
.aviso-version-nueva {
  position: fixed; right: 16px; bottom: 16px; z-index: 9999;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  max-width: min(520px, calc(100vw - 32px));
  padding: 12px 14px; border-radius: var(--radio-tarjeta);
  background: var(--bg-page-card); color: var(--text-title);
  border: 1px solid var(--border-page-card); box-shadow: var(--sombra-popup);
  font-size: 13px;
}
.aviso-version-nueva span { flex: 1 1 260px; }


/* ============================================================================
   CUENTA CORRIENTE — el detalle con el formato de Windows (29/09/2026)
   Diego: "copiá el formato del detalle de cuentas corrientes que usa Windows".
   La tarjeta grande y las cuatro de la derecha son CcCard de Windows
   (ui/cuenta_corriente_window.py:1182-1197): fondo del encabezado de las
   tablas, radio 16, título chico gris y valor grande. En el celular se apila.
   ============================================================================ */
.cc-resumen { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; flex: none; }
@media (max-width: 700px) { .cc-resumen { grid-template-columns: 1fr; } }
.cc-tarjeta { background: var(--bg-table-header); border: 1px solid var(--border-button); border-radius: 16px; padding: 10px 14px; display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.cc-tarjeta .t { font-size: var(--letra-chica); font-weight: 600; color: var(--text-secondary); }
.cc-tarjeta .v { font-size: var(--letra-destacado); font-weight: 800; color: var(--text-title); line-height: 1.15; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cc-tarjeta-grande .cc-nombre, .cc-nombre { font-size: var(--letra-titulo); font-weight: 800; color: var(--text-title); line-height: 1.2; }
.cc-dato { font-size: var(--letra-normal); color: var(--text-secondary); display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.cc-saldo-grande { font-size: var(--letra-destacado); font-weight: 900; color: var(--text-title); line-height: 1.2; }
.cc-tarjetas { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
/* La ficha del movimiento: nueve datos de a tres, como Windows (:1034-1045). */
.cc-datos-movimiento { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; flex: none; }
@media (max-width: 700px) { .cc-datos-movimiento { grid-template-columns: 1fr 1fr; } }
.cc-tarjeta.chica { padding: 8px 12px; border-radius: 12px; }
.cc-tarjeta.chica .v { font-size: var(--letra-subtitulo); font-weight: 700; }
/* En el celular los importes grandes no entraban en las cuatro tarjetas ("$ 40.39…"). */
@media (max-width: 700px) { .cc-tarjetas .cc-tarjeta .v { font-size: var(--letra-titulo); white-space: normal; overflow-wrap: anywhere; } }

/* ------------------------------------------------- el comprobante generado
 * "En comprobante generado, donde dice el número de la venta y LISTO, ese
 *  campo es muy alto: achicar al tamaño que venimos usando." + "copiar este
 *  orden y cómo ocupan todo el ancho" (su captura de Windows).
 */
.comprobante-generado .banner-cobro { padding: 6px 14px; }
.comprobante-generado .envio .boton { width: 100%; margin-top: 8px; }
/* Web 10.1, punto 78 (Diego, con su dibujo): "achicar el botón más grande al
 * máximo y poner en los otros botones el mismo tamaño… Todos los botones del
 * mismo tamaño", y el cartel un poco más angosto. El popup es "ajustado" (mide
 * su contenido) y la fila es una grilla de columnas IGUALES: el ancho lo pone
 * views/ventas.js (cartelComprobanteGenerado, acomodarBotones) midiendo el botón MÁS LARGO, con la letra que
 * tenga el usuario, y según cuántos entran en la pantalla. Mientras mide, la
 * fila va en línea y sin cortar (.midiendo). El botón más largo va con el aire
 * mínimo (12 px por lado en vez de 14).
 * El cartel puede llegar al ancho de la pantalla (menos el margen del fondo):
 * el tope de 960 px de "ajustado" dejaba afuera la fila con la letra grande.
 * Las tarjetas de "Enviar" (width 0 + min-width 100%) no aportan ancho: se
 * estiran al de la fila, nunca lo agrandan. Con un botón por renglón
 * (celular), el cartel toma el ancho entero. */
.modal.comprobante-generado-popup { max-width: calc(100vw - 40px); }
/* Word 10.3 (Diego, 04/10): *"quedó muy chico; 1/3 más grande… 'enviar por
   whatsapp' debería verse en una sola línea"*. Un ancho mínimo: el cartel ya
   no se achica al de sus tres botones. */
.modal.comprobante-generado-popup:not(.un-boton-por-renglon) { min-width: min(calc(100vw - 40px), 600px); }
.modal.comprobante-generado-popup.un-boton-por-renglon { width: 100%; }
.comprobante-generado .grupo-botones { display: grid; gap: 8px; }
.comprobante-generado .grupo-botones.midiendo { display: flex; flex-wrap: nowrap; width: max-content; }
.comprobante-generado .grupo-botones.midiendo .boton { flex: none; }
.comprobante-generado .grupo-botones .boton { padding-left: 12px; padding-right: 12px; }
.comprobante-generado .envios { width: 0; min-width: 100%; }
/* Word 10.2 (punto 78): el botón de abajo ("Continuar próxima venta" en el POS,
   "Cerrar" en Ventas) toma todo el ancho del pie, donde antes iba "Cerrar". */
.modal.comprobante-generado-popup .pie-modal .boton { flex: 1 1 100%; }
/* Las dos tarjetas de "Enviar" miden lo mismo (la grilla las estira); el botón
   va abajo de todo en las dos, aunque "ENVIAR POR WHATSAPP" ocupe dos renglones. */
.comprobante-generado .envio { display: flex; flex-direction: column; }
.comprobante-generado .envio .boton { margin-top: auto; }
.comprobante-generado .envio .entrada { margin-bottom: 8px; }

/* #565 — "Elegí la variante" (views/_variantes.js): la lista con alto fijo y
   scroll adentro (directiva 37), un renglón por variante con su stock y precio. */
.elegir-variante .lista-variantes { height: 300px; overflow-y: auto; border: 1px solid var(--border-page-card); border-radius: var(--radio-tabla); padding: 4px; background: var(--bg-table); }
.elegir-variante .renglon-variante { display: flex; align-items: center; gap: 12px; padding: 8px 10px; border-radius: 8px; cursor: pointer; }
.elegir-variante .renglon-variante:hover, .elegir-variante .renglon-variante.resaltado { background: var(--bg-seleccion-suave); }
.elegir-variante .renglon-variante .nombre-variante { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Las flechas de página de una grilla con más de 50 renglones (tabla() con
   `porPagina`, directiva 96): al pie, fijas abajo aunque la grilla scrollee. */
.tabla-contenedor > .pie-tabla-paginas {
  position: sticky; bottom: 0; left: 0; z-index: 2;
  display: flex; align-items: center; justify-content: flex-end; gap: 8px;
  padding: 6px 8px; background: var(--bg-page-card); border-top: 1px solid var(--border-page-card);
}

/* El scroll en la grilla, no en todo el popup (Word 10.2, hoja 17; ver
   ui.js::acomodarEnElPopup). En la computadora: el cuerpo del popup se reparte
   en columna, lo de arriba queda quieto y la grilla se queda con lo que sobra.
   Si igual no entrara (muchísimo arriba), el cuerpo vuelve a desplazarse: nada
   queda cortado. En el celular, como siempre. */
@media (min-width: 700px) {
  .modal .cuerpo-modal.scroll-en-la-grilla { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
  .scroll-en-la-grilla > *, .scroll-en-la-grilla .cadena-de-la-grilla > * { flex: none; }
  .scroll-en-la-grilla .cadena-de-la-grilla { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
  .scroll-en-la-grilla .grilla-que-scrollea { flex: 1 1 auto; min-height: 160px; overflow: auto; }
  .scroll-en-la-grilla .grilla-que-scrollea table.tabla thead th { position: sticky; top: 0; z-index: 2; }
}

/* ============================================================================
   LA APARIENCIA QUE ELIGE CADA USUARIO (29/09/2026, #406 y #407)

   Diego, textual: *"que tanto el 1 y 2 sean opciones que estén en Configuración →
   Apariencia… para que cada usuario pueda elegir la letra y el tema"*. Se elige en
   Configuración → Apariencia y se guarda en SU usuario (views/configuraciones.js y
   apariencia.js ponen `data-letra` / `data-estilo` en <html>). Sin elegir nada, Majo
   se ve exactamente igual que antes: Roboto y el estilo clásico.

   LA LETRA NO PESA: un @font-face no baja nada hasta que alguien usa esa letra, y
   cada archivo pesa entre 28 y 48 KB (auto-alojados, como Roboto: Majo no depende de
   internet ni de Google para verse bien; las licencias libres están al lado, en
   fonts/LICENCIA-*.txt). Son "variables": un solo archivo trae todos los gruesos.
   El alto del renglón de las grillas (30 px) no se mueve: sale del interlineado
   (table.tabla td), no de la letra.
   ============================================================================ */
@font-face { font-family: "Inter"; font-weight: 100 900; font-style: normal; src: url("/app/fonts/Inter-Variable.woff2") format("woff2"); font-display: swap; }
@font-face { font-family: "Open Sans"; font-weight: 300 800; font-style: normal; src: url("/app/fonts/OpenSans-Variable.woff2") format("woff2"); font-display: swap; }
@font-face { font-family: "Source Sans 3"; font-weight: 200 900; font-style: normal; src: url("/app/fonts/SourceSans3-Variable.woff2") format("woff2"); font-display: swap; }
:root[data-letra="inter"] { --familia-letra: "Inter", "Roboto", "Segoe UI", Arial, sans-serif; }
:root[data-letra="open-sans"] { --familia-letra: "Open Sans", "Roboto", "Segoe UI", Arial, sans-serif; }
:root[data-letra="source-sans"] { --familia-letra: "Source Sans 3", "Roboto", "Segoe UI", Arial, sans-serif; }

/* EL ESTILO "VIDRIO" (vidrio esmerilado): superficies semitransparentes con lo de atrás
   desenfocado, bordes con brillo. En capas, de menos a más, y NUNCA en las grillas
   (.tabla-contenedor tiene su fondo propio y opaco): ahí se leen los importes.

     vidrio-suave     → popups, menús y avisos que flotan.
     vidrio           → lo anterior + las tarjetas del Inicio, sobre un fondo con un
                        degradé suave del azul y el verde de Majo (sobre un color
                        liso el vidrio no se ve).
     vidrio-completo  → lo anterior + la cabecera, el panel de Accesos y la barra de
                        pestañas.

   LO QUE CUESTA: el desenfoque (backdrop-filter) lo paga sólo el que lo prende, y
   sólo en esas superficies. Si en una PC vieja o en el celular se siente lento, se
   vuelve a "Clásico" en su usuario. Quien le pidió al sistema operativo menos
   transparencias (prefers-reduced-transparency) lo ve siempre opaco. */
:root {
  --vidrio-popup: rgba(22, 32, 58, 0.66);
  --vidrio-tarjeta: rgba(24, 35, 60, 0.46);
  --vidrio-borde: rgba(255, 255, 255, 0.14);
  --vidrio-brillo: rgba(255, 255, 255, 0.08);
  --vidrio-fondo-a: rgba(53, 102, 204, 0.55);
  --vidrio-fondo-b: rgba(22, 163, 74, 0.32);
}
:root[data-theme="claro"] {
  --vidrio-popup: rgba(251, 252, 254, 0.70);
  --vidrio-tarjeta: rgba(251, 252, 254, 0.52);
  --vidrio-borde: rgba(255, 255, 255, 0.80);
  --vidrio-brillo: rgba(255, 255, 255, 0.90);
  --vidrio-fondo-a: rgba(53, 102, 204, 0.40);
  --vidrio-fondo-b: rgba(22, 163, 74, 0.28);
}

/* capa 1: popups, menús y avisos */
:root[data-estilo^="vidrio"] .fondo-modal {
  background: rgba(2, 8, 23, 0.32);
  -webkit-backdrop-filter: blur(5px); backdrop-filter: blur(5px);
}
:root[data-estilo^="vidrio"] .modal,
:root[data-estilo^="vidrio"] .menu-flotante,
:root[data-estilo^="vidrio"] .toast:not(.error):not(.ok) {
  background: var(--vidrio-popup);
  -webkit-backdrop-filter: blur(22px) saturate(1.5); backdrop-filter: blur(22px) saturate(1.5);
  border-color: var(--vidrio-borde);
  box-shadow: var(--sombra-popup), inset 0 1px 0 var(--vidrio-brillo);
}

/* capa 2: el fondo con degradé y las tarjetas del Inicio */
:root[data-estilo="vidrio"] body,
:root[data-estilo="vidrio-completo"] body {
  background:
    radial-gradient(1000px 700px at 18% 28%, var(--vidrio-fondo-a), transparent 66%),
    radial-gradient(950px 680px at 84% 78%, var(--vidrio-fondo-b), transparent 64%),
    var(--bg-app);
  background-attachment: fixed;
}
:root[data-estilo="vidrio"] .tarjeta-dash,
:root[data-estilo="vidrio-completo"] .tarjeta-dash {
  background: var(--vidrio-tarjeta);
  -webkit-backdrop-filter: blur(16px) saturate(1.4); backdrop-filter: blur(16px) saturate(1.4);
  border-color: var(--vidrio-borde);
  box-shadow: var(--sombra-tarjeta), inset 0 1px 0 var(--vidrio-brillo);
}

/* capa 3: la cabecera, los Accesos y la barra de pestañas */
:root[data-estilo="vidrio-completo"] .cabecera:not(.pruebas),
:root[data-estilo="vidrio-completo"] .accesos,
:root[data-estilo="vidrio-completo"] .solapa-modulo {
  background: var(--vidrio-tarjeta);
  -webkit-backdrop-filter: blur(16px) saturate(1.4); backdrop-filter: blur(16px) saturate(1.4);
  border-color: var(--vidrio-borde);
}
/* El encabezado de PRUEBAS conserva su marco rojo: el vidrio no puede taparlo. */
:root[data-estilo="vidrio-completo"] .cabecera.pruebas {
  background: var(--vidrio-tarjeta);
  -webkit-backdrop-filter: blur(16px) saturate(1.4); backdrop-filter: blur(16px) saturate(1.4);
}

@media (prefers-reduced-transparency: reduce) {
  :root[data-estilo^="vidrio"] .fondo-modal,
  :root[data-estilo^="vidrio"] .modal,
  :root[data-estilo^="vidrio"] .menu-flotante,
  :root[data-estilo^="vidrio"] .toast,
  :root[data-estilo^="vidrio"] .tarjeta-dash,
  :root[data-estilo^="vidrio"] .cabecera,
  :root[data-estilo^="vidrio"] .accesos,
  :root[data-estilo^="vidrio"] .solapa-modulo { -webkit-backdrop-filter: none; backdrop-filter: none; }
  :root[data-estilo^="vidrio"] .modal, :root[data-estilo^="vidrio"] .menu-flotante { background: var(--bg-page-card); }
  :root[data-estilo^="vidrio"] .tarjeta-dash { background: var(--dash-bg-card); }
}

/* La vista previa de cada letra y de cada estilo en Configuración → Apariencia. */
.opciones-apariencia { display: flex; flex-wrap: wrap; gap: 8px; }
.opcion-apariencia { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; min-width: 150px; padding: 8px 12px; border-radius: var(--radio-boton); border: 1px solid var(--border-button); background: var(--bg-button); color: var(--text-primary); cursor: pointer; text-align: left; }
.opcion-apariencia:hover { background: var(--bg-button-hover); }
.opcion-apariencia.activo { border-color: var(--bg-primary); box-shadow: 0 0 0 1px var(--bg-primary) inset; }
.opcion-apariencia .muestra { font-size: var(--letra-subtitulo); line-height: 1.3; }
.opcion-apariencia .nota { font-size: var(--letra-chica); color: var(--text-secondary); }

/* #694 · Word 12.10: la línea de "Enviar por mail / WhatsApp", arriba de los botones de acción del
   detalle. Los botones se reparten el ancho en partes iguales —uno al lado del otro, sin huecos—
   así la fila mide siempre lo mismo tenga dos o tres. Va separada por una línea fina: lo de arriba
   es "mandar esto"; lo de abajo, "hacer algo con esto". */
.fila-envio { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 8px;
  padding: 0 0 10px; margin-bottom: 10px; border-bottom: 1px solid var(--linea-suave, var(--dash-border-card)); }
.fila-envio > .boton { width: 100%; justify-content: center; }

/* #702 · Word 14.1: los datos de un movimiento de cuenta corriente, como LISTA y no como nueve
   tarjetas. Diego: *"la ficha está horrible… mejor que los muestre uno debajo del otro como una
   lista y el detalle de lo que dice al lado"*. La etiqueta a la izquierda con ancho fijo, el valor
   al lado con todo el resto: así un importe largo entra entero en vez de cortarse con puntos
   suspensivos, que es lo que pasaba en la tarjeta. */
.cc-lista-datos { display: flex; flex-direction: column; gap: 2px; flex: none; }
.cc-renglon-dato { display: flex; align-items: baseline; gap: 10px; padding: 3px 4px; border-radius: 6px; }
.cc-renglon-dato:nth-child(odd) { background: var(--bg-table-header); }
.cc-renglon-dato > .t { flex: 0 0 150px; font-size: var(--letra-chica); font-weight: 600; color: var(--text-secondary); }
.cc-renglon-dato > .v { flex: 1 1 auto; min-width: 0; font-weight: 700; color: var(--text-title);
  overflow-wrap: anywhere; font-variant-numeric: tabular-nums; }
@media (max-width: 700px) { .cc-renglon-dato > .t { flex-basis: 110px; } }

/* #702 · Word 14.1: el detalle de un movimiento SIN comprobante (un pago, un anticipo, un ajuste a
   mano) no reserva el espacio de la grilla de ítems que nunca va a tener. Diego: *"se ve que entre
   los botones y las observaciones hay espacio vacío que nunca va a haber nada"*.
   El ANCHO no cambia: dos movimientos siguen alineando igual. Y todos los pagos miden lo mismo
   entre sí, que es lo que pide la directiva 37. */
.modal.sin-detalle-de-comprobante .cuerpo-modal { max-height: none; }
.modal.sin-detalle-de-comprobante .crece-en-columna { display: none; }

/* #703 · Word 14.1: el detalle de una cuenta corriente, con ALTO FIJO y el scroll adentro de la
   grilla. Diego: *"la grilla tiene que tener el alto máximo que tiene ahora el popup, y si se
   estira más, meter scroll dentro de la grilla"*.
   Toda la cadena tiene que poder crecer, no sólo el cuerpo: entre `.cuerpo-modal` y la grilla hay
   un div sin clase (el que recibe `modal()`), y si se queda en `flex: 0 1 auto` el alto que sobra
   muere ahí adentro. Es el mismo eslabón que costó 270 px de aire en el detalle de la compra. */
.modal.cc-detalle-alto-fijo { height: min(92vh, 722px); }
.modal.cc-detalle-alto-fijo .cuerpo-modal { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.modal.cc-detalle-alto-fijo .cuerpo-modal > div { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.modal.cc-detalle-alto-fijo .crece-en-columna { flex: 1 1 auto; min-height: 180px; overflow: auto; }

/* #705 · Word 14.1: el tilde "Aplicar descuento / recargo del medio de pago" comparte renglón con
   el medio y se va a la DERECHA. Diego: *"este tilde tiene que estar al lado del medio de pago, en
   la misma línea, bien tirado a la derecha… quiero que el popup se achique un poco en el largo"*.
   Se alinea abajo para que el casillero quede a la altura del desplegable, no de su etiqueta. */
.campo.tilde-a-la-derecha { justify-content: flex-end; }
.campo.tilde-a-la-derecha > label { justify-content: flex-end; text-align: right; }
