/* ═══════════════════════════════════════════════════════════════
   GLOBAL STYLESHEET — Gestión Logística Aquí Es
   Fuentes: IBM Plex Sans (UI) · IBM Plex Mono (datos/código)
   ═══════════════════════════════════════════════════════════════ */


/* ── 1. VARIABLES ─────────────────────────────────────────────── */
:root {
  /* Fondos */
  /* Un solo fondo neutro para body, sidebar, tablas y pop-ups: la separación
     entre superficies la dan los divisores (--border), no el escalón de tono. */
  --bg:        #151515;
  --surface:   #151515;
  --surface2:  #1c2030;

  /* Bordes — un solo gris neutro para todo borde en reposo (el de la sidebar).
     --border2 queda como alias para no tocar sus ~90 usos. --border-strong es
     el escalón neutro de hover/foco y de rellenos finos (scrollbars, spinner). */
  --border:    #2d2d2d;
  --border2:   var(--border);
  --border-strong: #3d3d3d;

  /* Texto — gris neutro, no blanco: 12.3:1 sobre --bg (#151515), sobrado para
     AAA sin el deslumbramiento del blanco puro sobre casi-negro. */
  --text:      #d4d4d4;
  --text2:     #8091b5;
  /* --text3 es el tono más callado (labels 11px, headers de tabla, placeholders).
     Sube medio escalón desde #6f7fa4, que daba 4.04:1 sobre --surface2 y dejaba
     los labels y los placeholders por debajo de AA justo en la fila en hover. */
  --text3:     #7a8ab0;

  /* Acento / semánticos */
  --accent:    #9b26b6;
  /* Acento cuando es TEXTO o ícono. #9b26b6 se diseñó para rellenar (botón
     primario, borde de foco), y como tinta sobre las superficies oscuras da
     2.6–3.0:1. Este tinte más claro es el que ya usaba .alert-info; ahora es un
     token para que todo el acento-como-texto lo comparta. En claro no hace falta
     (el acento pleno da 5.1–6.3:1) y el token colapsa al acento. */
  --accent-ink: #c87ae0;
  --danger:    #f87171;
  --warn:      #f5b942;
  --ok:        #4ade80;

  /* Radios: escala por tamaño de la pieza. --r-scale los agranda donde hay
     esquina continua (ver @supports corner-shape abajo): a igual cifra, la
     superelipse se ve más cerrada que el arco circular. Piezas anidadas:
     radio interior = exterior − padding (concéntricos). */
  --r-scale:   1;
  --r-xs:      calc(5.4px  * var(--r-scale));   /* chips, miniaturas, etiquetas */
  --r-sm:      calc(9px    * var(--r-scale));   /* botones, inputs, ítems de menú y sidebar */
  --r-md:      calc(12.6px * var(--r-scale));   /* tablas, tarjetas, popovers, dropdowns */
  --r-lg:      calc(18px   * var(--r-scale));   /* modales y paneles laterales */
  --r:         var(--r-sm);

  /* Controles flotantes al pie (paginación; en móvil también el botón del
     menú). Radio concéntrico: el de los botones de dentro más el padding.
     En móvil los dos comparten alto y línea base (§19 RESPONSIVE);
     --float-lift los sube sobre una barra de acción fija al pie. Se cambia
     SIEMPRE sobre :root (p. ej. `:root:has(.x.show)`): --float-bottom se
     resuelve aquí, y un --float-lift puesto en un hijo no lo movería. */
  --float-pad:    4px;
  --float-r:      calc(var(--r-sm) + var(--float-pad));
  --float-h:      40px;   /* = alto de un .btn en móvil: la fila del pie mide lo mismo que la de arriba */
  --float-inset:  12px;
  --float-lift:   0px;
  --float-bottom: calc(var(--float-inset) + env(safe-area-inset-bottom, 0px) + var(--float-lift));
  --bg-accent-muted: #9b26b622;
  /* Interacción: tinte del acento sobre el fondo. --hover para filas e ítems
     bajo el puntero; --active para el ítem seleccionado (sidebar, pestañas,
     segmentados). Translúcidos para que se sumen a cualquier fondo. */
  --hover:     #9b26b621;
  --active:    #9b26b633;
  /* Selección de la sidebar: relleno más tenue que --active y un borde del
     mismo morado, un poco más vivo que el relleno. */
  --nav-active:        #9b26b61a;
  --nav-active-border: #9b26b659;

  /* Data-viz — rampa categórica (solo para series/segmentos de gráficas;
     NO reemplaza los estados semánticos, que siguen bloqueados a los badges).
     Los deltas de tendencia reutilizan --ok / --danger / --text3. */
  --viz-1: #b06fd6;  --viz-2: #7c86f0;  --viz-3: #5aa7e0;
  --viz-4: #5cc0c9;  --viz-5: #d98fb0;  --viz-6: #d3a15c;
  --viz-grid:    rgba(255,255,255,.07);
  /* Sombra única de todo lo que se sobrepone (popovers, menús, modales, toasts,
     drawer, paginación flotante y botón del menú móvil). Base: la del flyout del sidebar, más tenue. */
  --shadow-overlay: 0 12px 32px rgb(0 0 0 / .345);
  /* Sombra leve de los botones con caja (principal, secundario, ícono, advertencia). */
  --shadow-btn: 0 1px 2px rgb(0 0 0 / .3);
  --viz-axis:    var(--text3);
  --viz-compare: var(--text3);

  /* Aliases (referenciados por componentes; se re-tematizan solos) */
  --bg2:       var(--surface2);
  --text1:     var(--text);

  /* Sugiere a los controles nativos (scrollbars, date/select) el esquema oscuro */
  color-scheme: dark;

  /* ── Tokens de estado ── */
  --c-borrador:   #9aa0be;  --bg-borrador:   #2a2d3a;
  --c-pendiente:  #a8aec9;  --bg-pendiente:  #3a3d50;
  --c-proceso:    #9b26b6;  --bg-proceso:    #200a25;
  --c-separando:  #5b9cf6;  --bg-separando:  #0d1a2f;
  --c-listo:      #38bdf8;  --bg-listo:      #0a2030;
  --c-espera:     #fbbf24;  --bg-espera:     #2a1f00;
  --c-facturado:  #2dd4bf;  --bg-facturado:  #0d2420;
  --c-empacado:   #a78bfa;  --bg-empacado:   #1e1535;
  --c-camino:     #fb8c3a;  --bg-camino:     #2a1810;
  --c-entregado:  #4ade80;  --bg-entregado:  #0d2818;
  --c-incompleto: #f87171;  --bg-incompleto: #2a1010;
  --c-parcial:    #f5b942;  --bg-parcial:    #2a1f00;
  /* Anulado: rojo desaturado. Es un cierre, no una alarma — tiene que leerse como
     "este pedido ya no cuenta" sin competir con Incompleto, que sí pide acción. */
  --c-anulado:    #b47e85;  --bg-anulado:    #241a1c;
}


/* ── 1b. TEMA CLARO ───────────────────────────────────────────────
   Activado con [data-theme="light"] en <html> (lo fija el selector de
   tema del menú de usuario). El oscuro de :root sigue siendo el default.
   ─────────────────────────────────────────────────────────────── */
:root[data-theme="light"] {
  /* Fondos — un solo blanco para body y superficies, como en oscuro */
  --bg:        #ffffff;
  --surface:   #ffffff;
  --surface2:  #e4e7ef;

  /* Bordes */
  --border:    #d7dbe5;
  --border2:   var(--border);
  --border-strong: #c2c8d6;

  /* Texto (todos verificados ≥4.5:1 sobre surface/surface2). --text es gris
     oscuro neutro, no negro: 12.6:1 sobre blanco, el espejo del 12.3:1 del oscuro. */
  --text:      #333333;
  --text2:     #474d61;
  --text3:     #5f6578;

  /* Acento / semánticos — sobre superficie clara el acento pleno ya pasa AA
     como texto (5.07–6.28:1), así que la tinta colapsa al acento (Mirror Rule). */
  --accent:    #9b26b6;
  --accent-ink: var(--accent);
  --danger:    #c12838;
  --warn:      #8a6300;
  --ok:        #16753f;

  --bg-accent-muted: #9b26b614;
  --hover:     #9b26b60f;
  --active:    #9b26b61f;
  --nav-active:        var(--active);
  --nav-active-border: #9b26b640;

  /* Data-viz (claro) — tonos más oscuros para contraste sobre superficie clara.
     --viz-axis / --viz-compare heredan el --text3 del tema claro. */
  --viz-1: #8d3fb8;  --viz-2: #4a57c9;  --viz-3: #2472b8;
  --viz-4: #17868f;  --viz-5: #b05481;  --viz-6: #9a6a1e;
  --viz-grid: rgba(0,0,0,.06);
  --shadow-overlay: 0 12px 32px rgb(0 0 0 / .115);
  --shadow-btn: 0 1px 2px rgb(0 0 0 / .08);

  color-scheme: light;

  /* ── Tokens de estado (texto saturado sobre tinte claro del mismo tono) ── */
  /* Todos ≥ 4,5:1 sobre su tinte, en los dos temas (medido el 2026-10-05). */
  --c-borrador:   #5a6076;  --bg-borrador:   #e7e9f1;
  --c-pendiente:  #5a6076;  --bg-pendiente:  #dfe2ec;
  --c-proceso:    #8d1ba6;  --bg-proceso:    #f3e4f7;
  --c-separando:  #2160c4;  --bg-separando:  #e3edfb;
  --c-listo:      #0b6890;  --bg-listo:      #def0fa;
  --c-espera:     #8a6300;  --bg-espera:     #faf0d2;
  --c-facturado:  #08705f;  --bg-facturado:  #d6f4ee;
  --c-empacado:   #6a39d1;  --bg-empacado:   #ece5fb;
  --c-camino:     #9e4f0a;  --bg-camino:     #fce8d8;
  --c-entregado:  #16753f;  --bg-entregado:  #daf3e1;
  --c-incompleto: #c12838;  --bg-incompleto: #fbe2e4;
  --c-parcial:    #8a6300;  --bg-parcial:    #faf0d2;
  --c-anulado:    #8a5860;  --bg-anulado:    #eee2e4;
}


/* ── 2. RESET & BASE ──────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* Esquinas continuas (superelipse, como en Apple): la curvatura crece poco a
   poco en vez de pasar de golpe de recta a arco. Donde el navegador no
   soporta corner-shape queda el border-radius circular de siempre. Círculos
   y píldoras (50% / 99px) declaran corner-shape: round para no deformarse. */
@supports (corner-shape: squircle) {
  :root { --r-scale: 1.5; }
  *, *::before, *::after { corner-shape: squircle; }
}
body {
  background: var(--bg);
  color: var(--text);
  font-family: 'IBM Plex Sans', sans-serif;
  font-size: 14px;
  min-height: 100vh;
  overflow-x: hidden;
}
.mono { font-family: 'IBM Plex Mono', monospace; }
/* Casillas y radios nativos en el acento del sistema, no en el azul del
   navegador. Con :where() no pesa nada: cualquier regla de un componente gana. */
:where(input[type="checkbox"], input[type="radio"], progress) { accent-color: var(--accent); }

/* App layout (páginas con sidebar) */
body.app-layout { overflow: hidden; height: 100vh; }
.main-layout    { display: flex; height: 100vh; }
.main-area      { flex: 1; display: flex; flex-direction: column; height: 100vh; overflow: hidden; min-width: 0; }
.main-content   { flex: 1; overflow-y: auto; min-height: 0; }

/* Áreas seguras del teléfono (atajo en la pantalla de inicio, viewport-fit=
   cover): la app se dibuja bajo la barra de estado y el indicador de inicio.
   En escritorio y en el navegador los env() valen 0 y nada de esto se ve.
   · Arriba, una franja FIJA y sólida del alto de la barra de estado. Sin ella
     iOS difumina lo que pasa por debajo, y lo que la quitaba al abrir el
     sidebar era justo eso: un elemento fijo pegado al borde. Va sobre la
     página y los paneles (100–120) y bajo el drawer (200), que trae la suya.
   · El contenido empieza bajo la franja: .main-area, el drawer y los modales
     a pantalla completa (§19 RESPONSIVE) le suman ese alto. */
body.app-layout::before {
  content: ''; position: fixed; top: 0; left: 0; right: 0; z-index: 150;
  height: env(safe-area-inset-top, 0px); background: var(--bg); pointer-events: none;
}
.main-area      { padding-top: env(safe-area-inset-top, 0px); }


/* ── 3. SIDEBAR ───────────────────────────────────────────────── */
/* Colapsar/expandir es UNA sola animación: el ancho del sidebar (tiene que
   mover el contenido, así que no puede ser transform). Etiquetas y datos del
   usuario solo se desvanecen con la misma duración y curva; su ancho cambia de
   golpe y el overflow del sidebar lo esconde. */
.sidebar            { --sb-ease: .22s cubic-bezier(.4,0,.2,1); width: 220px; height: 100vh; background: var(--surface); border-right: 1px solid var(--border); display: flex; flex-direction: column; flex-shrink: 0; transition: width var(--sb-ease); overflow: hidden; }
.sidebar-header     { min-height: 52px; margin: 0 8px; padding: 12px 13px; display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
.sidebar-logo       { width: 30px; height: 30px; border-radius: 50%; corner-shape: round; flex-shrink: 0; object-fit: cover; }
.sidebar-brand-wrap { min-width: 0; }
.sidebar-brand      { font-size: 12px; font-weight: 700; letter-spacing: -.01em; line-height: 1.2; transition: opacity .15s; white-space: nowrap; }
.sidebar-brand-sub  { font-size: 10px; color: var(--text3); letter-spacing: .02em; line-height: 1; white-space: nowrap; }
.sidebar-brand-empresa { margin-top: 4px; font-size: 10.5px; font-weight: 600; color: var(--text2); line-height: 1.2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 150px; }
.sidebar-nav        { flex: 1; padding: 0 0 8px; overflow-y: auto; overflow-x: hidden; }
.sidebar-item       { display: flex; align-items: center; gap: 9px; padding: 7px 12px; margin: 1px 8px; border-radius: var(--r); font-size: 13px; font-weight: 400; color: var(--text); text-decoration: none; cursor: default; transition: background .15s, border-color .15s, color .15s; border: 1px solid transparent; background: transparent; width: calc(100% - 16px); white-space: nowrap; }
.nav-label          { transition: opacity var(--sb-ease); overflow: hidden; }
a.sidebar-item      { cursor: pointer; }
a.sidebar-item:hover              { background: var(--hover); color: var(--text); }
.sidebar-item.active              { background: var(--nav-active); border-color: var(--nav-active-border); color: var(--text); }
.sidebar-item.disabled            { opacity: .35; pointer-events: none; }

/* ── Grupos de navegación (acordeón) ── */
.nav-group           { display: flex; flex-direction: column; }
.nav-group-head      { display: flex; align-items: center; margin: 1px 8px; border-radius: var(--r); border: 1px solid transparent; transition: background .15s, border-color .15s; }
.nav-group-head:hover { background: var(--hover); }
.nav-group-head.current { background: var(--nav-active); border-color: var(--nav-active-border); }
.nav-group-link      { flex: 1; min-width: 0; display: flex; align-items: center; gap: 9px; padding: 7px 12px; font-size: 13px; font-weight: 400; color: var(--text); text-decoration: none; border-radius: var(--r); white-space: nowrap; transition: color .15s; }
.nav-group-link svg  { flex-shrink: 0; }
.nav-group-head:hover .nav-group-link,
.nav-group-head.current .nav-group-link { color: var(--text); }

/* Sin animación de apertura a propósito: `open` la pone Jinja al renderizar
   según la sección en la que estás — no hay toggle en el cliente, así que la
   transición de max-height nunca corría, y su tope de 340px habría recortado el
   grupo en silencio al crecer. */
.nav-sub             { display: none; }
.nav-group.open .nav-sub { display: block; }
.nav-subitem         { display: flex; align-items: center; gap: 10px; padding: 6px 10px 6px 23px; margin: 1px 8px; border-radius: var(--r); font-size: 12.5px; font-weight: 400; color: var(--text); text-decoration: none; white-space: nowrap; border: 1px solid transparent; transition: background .15s, color .15s; }
.nav-subitem:first-child { margin-top: 2px; }
.nav-subitem:last-child  { margin-bottom: 4px; }
.nav-dot             { width: 5px; height: 5px; border-radius: 50%; corner-shape: round; background: var(--text); flex-shrink: 0; }
.nav-subitem:hover   { background: var(--hover); color: var(--text); }
.nav-subitem.active  { background: var(--nav-active); border-color: var(--nav-active-border); color: var(--text); }
.nav-subitem.disabled,
.nav-group-link.disabled { opacity: .35; pointer-events: none; cursor: default; }

/* Sidebar colapsado */
.sidebar.collapsed                { width: 52px; }
.sidebar.collapsed .sidebar-header { padding: 0; justify-content: center; }
.sidebar.collapsed .sidebar-brand-wrap { display: none; }
.sidebar.collapsed .sidebar-item  { justify-content: center; padding: 7px 0; margin: 1px 6px; width: calc(100% - 12px); gap: 0; }
.sidebar.collapsed .nav-label     { opacity: 0; max-width: 0; pointer-events: none; }
.sidebar.collapsed .nav-group-head { margin: 1px 6px; }
.sidebar.collapsed .nav-group-link { justify-content: center; padding: 7px 0; gap: 0; }
.sidebar.collapsed .nav-sub       { display: none; }
/* Colapsado no se ven las subsecciones: si la activa es una de ellas, el
   ícono del grupo se resalta en su lugar. */
.sidebar.collapsed .nav-group:has(.nav-subitem.active) .nav-group-head { background: var(--nav-active); border-color: var(--nav-active-border); }

/* ── Flyout de subsecciones (modo colapsado) ── */
.nav-flyout {
  position: fixed; z-index: 9998; min-width: 184px; padding: 6px;
  background: var(--surface); border: 1px solid var(--border2);
  border-radius: var(--r-md); box-shadow: var(--shadow-overlay);
  display: none; flex-direction: column;
  animation: fadeInFlyout .13s cubic-bezier(.4,0,.2,1);
}
.nav-flyout.open       { display: flex; }
.nav-flyout-head       { padding: 7px 10px; font-size: 12.5px; font-weight: 400; color: var(--text); text-decoration: none; border-radius: calc(var(--r-md) - 6px); white-space: nowrap; }
.nav-flyout-head:hover { background: var(--hover); }
.nav-flyout-head.active{ background: var(--nav-active); box-shadow: inset 0 0 0 1px var(--nav-active-border); }
.nav-flyout-list       { display: flex; flex-direction: column; gap: 1px; margin-top: 1px; }
.nav-flyout-item       { padding: 7px 10px; font-size: 12.5px; color: var(--text); text-decoration: none; border-radius: calc(var(--r-md) - 6px); white-space: nowrap; transition: background .12s, color .12s; }
.nav-flyout-item:hover { background: var(--hover); color: var(--text); }
.nav-flyout-item.active{ background: var(--nav-active); box-shadow: inset 0 0 0 1px var(--nav-active-border); color: var(--text); }
@keyframes fadeInFlyout { from { opacity: 0; transform: translateX(-5px); } to { opacity: 1; transform: none; } }

/* ── Footer del sidebar: control de usuario ── */
.sidebar-footer     { padding: 8px; flex-shrink: 0; }
.sidebar-user       { display: flex; align-items: center; gap: 9px; width: 100%; padding: 7px 8px; border-radius: var(--r); background: transparent; border: 1px solid transparent; color: inherit; font-family: inherit; text-align: left; cursor: pointer; transition: background .15s, border-color .15s; }
.user-avatar      { width: 26px; height: 26px; background: var(--accent); border-radius: 50%; corner-shape: round; display: grid; place-items: center; font-size: 11px; font-weight: 700; color: #fff; flex-shrink: 0; font-family: 'IBM Plex Mono', monospace; } /* Ya no hace parte del TOPBAR hace parte del NAVBAR - FOOTER */
.sidebar-user:hover { background: var(--hover); border-color: var(--border); }
.sidebar-user-meta  { display: flex; flex-direction: column; flex: 1; min-width: 0; line-height: 1.3; overflow: hidden; transition: opacity var(--sb-ease); }
.sidebar-user-name  { font-size: 12.5px; font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sidebar-user-sub   { font-size: 10.5px; color: var(--text3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-family: 'IBM Plex Mono', monospace; }
.sidebar-user-caret { color: var(--text3); flex-shrink: 0; transition: opacity .15s; }

.sidebar.collapsed .sidebar-footer { padding: 8px 6px; }
.sidebar.collapsed .sidebar-user   { justify-content: center; padding: 7px 0; gap: 0; }
.sidebar.collapsed .sidebar-user-meta,
.sidebar.collapsed .sidebar-user-caret { opacity: 0; max-width: 0; width: 0; overflow: hidden; pointer-events: none; }

/* ── Tarjeta de usuario (popover) ── */
.user-menu {
  position: fixed; z-index: 9999; width: 252px; padding: 6px;
  background: var(--surface); border: 1px solid var(--border2);
  border-radius: var(--r-md); box-shadow: var(--shadow-overlay);
  display: none; flex-direction: column; gap: 1px;
  animation: fadeInMenuUp .14s ease;
}
.user-menu.open      { display: flex; }
.user-menu-head      { display: flex; align-items: center; gap: 11px; padding: 9px 8px 11px; }
.user-avatar-lg      { width: 40px; height: 40px; font-size: 15px; }
.user-menu-id        { min-width: 0; flex: 1; }
.user-menu-name      { font-size: 14px; font-weight: 700; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.user-menu-line      { font-size: 12px; color: var(--text2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-top: 1px; }
.user-menu-aldikase  { display: flex; align-items: center; gap: 6px; margin-top: 6px; }
.user-menu-aldikase .mono { font-size: 12px; color: var(--text2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.user-menu-sep       { height: 1px; background: var(--border); margin: 5px 4px; }
.user-menu-label     { font-size: 10px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--text3); padding: 6px 8px 4px; }

/* Selector de empresa (multi-tenant) */
.user-menu-empresa-item      { display: flex; align-items: center; gap: 9px; padding: 8px; border-radius: calc(var(--r-md) - 6px); border: none; background: transparent; color: var(--text2); font-size: 13px; font-family: inherit; text-align: left; width: 100%; cursor: pointer; transition: background .12s, color .12s; }
.user-menu-empresa-item:hover     { background: var(--surface); color: var(--text); }
.user-menu-empresa-item.active    { color: var(--text); font-weight: 600; }
.user-menu-empresa-dot       { width: 7px; height: 7px; border-radius: 50%; corner-shape: round; flex-shrink: 0; background: var(--border-strong); }
.user-menu-empresa-item.active .user-menu-empresa-dot { background: var(--accent); }
.user-menu-empresa-name      { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.user-menu-empresa-check     { flex-shrink: 0; color: var(--accent-ink); }

/* Selector de tema (segmentado) */
.theme-seg           { display: flex; gap: 3px; padding: 3px; margin: 0 4px 4px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-sm); }
.theme-opt           { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; padding: 7px 2px; border: none; background: transparent; color: var(--text3); font-family: inherit; font-size: 11px; font-weight: 500; border-radius: calc(var(--r-sm) - 3px); cursor: pointer; transition: background .15s, color .15s, box-shadow .15s; }
.theme-opt svg       { width: 15px; height: 15px; }
.theme-opt:hover     { color: var(--text2); }
.theme-opt.active    { background: var(--active); color: var(--text); box-shadow: inset 0 0 0 1px var(--border); }
.user-menu-item      { display: flex; align-items: center; gap: 9px; padding: 8px; border-radius: calc(var(--r-md) - 6px); border: none; background: transparent; color: var(--text2); font-size: 13px; font-family: inherit; text-align: left; width: 100%; text-decoration: none; cursor: pointer; transition: background .12s, color .12s; }
.user-menu-item:hover     { background: var(--surface); color: var(--text); }
.user-menu-item svg       { flex-shrink: 0; color: var(--text3); transition: color .12s; }
.user-menu-item:hover svg { color: var(--text2); }
.user-menu-danger:hover,
.user-menu-danger:hover svg { color: var(--danger); }
.ctrl-menu-dot {
  width: 6px; height: 6px; border-radius: 50%; corner-shape: round;
  background: transparent; flex-shrink: 0; transition: background .15s;
}
.ctrl-menu-dot.active { background: var(--text2); }

@keyframes fadeInMenuUp {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ── Diálogo de confirmación: pérdida de datos ── */
.discard-backdrop {
  position: fixed; inset: 0; z-index: 10000;
  background: rgba(0,0,0,.45);
  display: none; align-items: center; justify-content: center;
  animation: fadeIn .12s ease;
}
.discard-backdrop.open { display: flex; }
.discard-box {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-md); padding: 24px 24px 20px;
  /* Ancho acotado al viewport: con 320px fijos el diálogo se salía de pantalla
     en un móvil de 320-360px, justo donde vive el flujo de bodega. */
  width: min(360px, calc(100vw - 32px));
  box-shadow: var(--shadow-overlay);
  animation: discardPop .15s cubic-bezier(.4,0,.2,1);
}
.discard-title { font-size: 15px; font-weight: 700; color: var(--text); margin-bottom: 6px; }
.discard-msg   { font-size: 13px; color: var(--text2); margin-bottom: 20px; line-height: 1.5; }
.discard-actions { display: flex; gap: 8px; justify-content: flex-end; }
@keyframes discardPop {
  from { opacity: 0; transform: scale(.92); }
  to   { opacity: 1; transform: scale(1); }
}


/* ── 4. TOPBAR ────────────────────────────────────────────────── */
.topbar             { background: transparent; border-bottom: none; padding: 0 20px; height: 52px; display: flex; align-items: center; justify-content: space-between; flex-shrink: 0;}
.topbar-left      { display: flex; align-items: center; gap: 12px; }
.topbar-right     { display: flex; align-items: center; gap: 8px; }
/* Menú ⋯ de acciones secundarias (components/topbar.html). En escritorio no
   existe: los envoltorios se disuelven y los botones quedan como siempre. En
   móvil es un popover (§19 RESPONSIVE). */
.topbar-more,
.topbar-more-menu,
.topbar-more-item                 { display: contents; }
.topbar-more > .topbar-more-btn   { display: none; }
.topbar-title       { display: inline-flex; align-items: center; gap: 8px; font-size: 15px; font-weight: 500; letter-spacing: -.01em; }
.topbar-title svg   { color: var(--text); }
/* Botón del menú (abre el sidebar como drawer) — solo en móvil, donde flota
   abajo a la izquierda (ver §19 RESPONSIVE). Misma caja que la paginación. */
.nav-toggle         { display: none; align-items: center; justify-content: center; width: var(--float-h); height: var(--float-h); padding: 0; background: var(--surface); border: 1px solid var(--border); border-radius: var(--float-r); box-shadow: var(--shadow-overlay); color: var(--text2); cursor: pointer; transition: border-color .15s, color .15s; }
.nav-toggle:hover   { border-color: var(--border-strong); color: var(--text); }
.sidebar-backdrop      { display: none; position: fixed; inset: 0; background: #0009; backdrop-filter: blur(2px); z-index: 199; }
.sidebar-backdrop.open { display: block; }
@keyframes ov-spin { to { transform: rotate(360deg); } }


/* ── 5. BOTONES ───────────────────────────────────────────────────
   Seis tipos y ni uno más (catálogo en .docs/PATRONES-UI.md §Botones):

     .btn-primary  ícono + texto, acento   → la acción principal de la vista
     .btn-ghost    ícono + texto, sin acento → acciones no principales
     .btn-more     texto + chevron          → abre más detalle u opciones
     .btn-text     solo texto               → acción menor en línea
     .btn-icon     solo ícono en un squircle → acción puntual (cerrar, navegar, quitar)
     .btn-danger   ícono + texto, rojo      → destructiva o de advertencia

   Todos van sobre .btn. Un solo modificador de tamaño, .btn-sm (filas,
   tarjetas densas). Un solo estado, .active / [aria-pressed="true"]
   (filtros aplicados, columnas abiertas, modo edición). Nada de colores
   de estado en botones: el estado se lee en el badge. Los que tienen caja
   llevan --shadow-btn; más y texto no tienen caja y van sin sombra. */
/* Cada tipo solo declara variables (--b-*): reposo, hover y, si hace falta,
   pulsado. Las reglas de estado de abajo son las únicas que pintan, así que un
   estado se define una vez para los seis tipos.

   Bootstrap 5 (base.html) también define .btn, .btn-primary y .btn-danger, y
   sus reglas de :hover, :focus-visible, :active y :disabled ganan por
   especificidad: sin esto un principal se ponía azul al pulsarlo o con foco de
   teclado, el hover de advertencia dejaba el texto blanco y el borde de un
   deshabilitado tomaba el color del texto. En vez de pelear regla por regla, sus
   variables apuntan a las nuestras: lo que pinte Bootstrap sale igual. */
.btn {
  --b-bg: transparent;  --b-border: transparent;  --b-fg: var(--text);  --b-shadow: none;
  --b-bg-h: var(--b-bg); --b-border-h: var(--b-border); --b-fg-h: var(--b-fg);
  --b-bg-a: var(--b-bg-h); --b-border-a: var(--b-border-h);

  --bs-btn-color: var(--b-fg);            --bs-btn-bg: var(--b-bg);            --bs-btn-border-color: var(--b-border);
  --bs-btn-hover-color: var(--b-fg-h);    --bs-btn-hover-bg: var(--b-bg-h);    --bs-btn-hover-border-color: var(--b-border-h);
  --bs-btn-active-color: var(--b-fg-h);   --bs-btn-active-bg: var(--b-bg-a);   --bs-btn-active-border-color: var(--b-border-a);
  --bs-btn-disabled-color: var(--b-fg);   --bs-btn-disabled-bg: var(--b-bg);   --bs-btn-disabled-border-color: var(--b-border);
  --bs-btn-disabled-opacity: .4;
  --bs-btn-box-shadow: var(--b-shadow);   --bs-btn-focus-box-shadow: var(--b-shadow);  --bs-btn-active-shadow: var(--b-shadow);

  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: 34px; padding: 0 12px; border-radius: var(--r-sm);
  font-family: 'IBM Plex Sans', sans-serif; font-size: 13px; font-weight: 500; line-height: 1.2;
  background: var(--b-bg); border: 1px solid var(--b-border); color: var(--b-fg); box-shadow: var(--b-shadow);
  cursor: pointer; white-space: nowrap; text-decoration: none;
  transition: background .15s, border-color .15s, color .15s;
}
.btn svg              { flex-shrink: 0; }
.btn-sm               { min-height: 28px; padding: 0 10px; gap: 5px; font-size: 12px; }

/* Tipos */
.btn-primary { --b-bg: var(--accent); --b-border: var(--accent); --b-fg: #fff; --b-shadow: var(--shadow-btn);
               --b-bg-h: #7d1f96; --b-border-h: #7d1f96; --b-bg-a: #5c186e; --b-border-a: #5c186e; }
.btn-ghost   { --b-border: var(--border); --b-fg: var(--text2); --b-shadow: var(--shadow-btn);
               --b-border-h: var(--border-strong); --b-fg-h: var(--text); }
.btn-more    { --b-fg: var(--text2); --b-bg-h: var(--hover); --b-fg-h: var(--text); padding: 0 8px; }
.btn-more::after { content: ''; width: 5px; height: 5px; margin: -3px 2px 0 2px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: rotate(45deg); transition: transform .15s; }
.btn-more[aria-expanded="true"]::after { margin-top: 3px; transform: rotate(-135deg); }
.btn-text    { --b-fg: var(--text3); --b-fg-h: var(--text);
               min-height: 0; padding: 4px 2px; font-size: 12px; text-decoration: underline; text-underline-offset: 3px; }
.btn-icon    { --b-border: var(--border); --b-fg: var(--text2); --b-shadow: var(--shadow-btn);
               --b-bg-h: var(--hover); --b-border-h: var(--border-strong); --b-fg-h: var(--text);
               width: 34px; padding: 0; }
.btn-icon.btn-sm { width: 28px; }
.btn-danger  { --b-bg: color-mix(in srgb, var(--danger) 12%, transparent); --b-border: color-mix(in srgb, var(--danger) 40%, transparent);
               --b-fg: var(--danger); --b-shadow: var(--shadow-btn);
               --b-bg-h: color-mix(in srgb, var(--danger) 20%, transparent); --b-border-h: var(--danger); }

/* Estado encendido (filtros aplicados, columnas, modo edición). has-filters es
   el nombre que ya usa el JS del botón de filtros. */
.btn.active, .btn[aria-pressed="true"], .btn-filter.has-filters {
  --b-bg: var(--bg-accent-muted); --b-border: var(--accent); --b-fg: var(--accent-ink);
  --b-bg-h: var(--bg-accent-muted); --b-border-h: var(--accent); --b-fg-h: var(--accent-ink);
}

/* No interactuable: siempre más tenue que su par activo. Sin sombra, y los
   tipos sin relleno bajan el texto a --text3 antes de la opacidad. */
.btn:is(:disabled, [aria-disabled="true"]) { --b-shadow: none; opacity: .4; cursor: not-allowed; }
.btn:is(.btn-ghost, .btn-icon, .btn-more, .btn-text):is(:disabled, [aria-disabled="true"]) { --b-fg: var(--text3); }

/* Las únicas reglas que pintan un estado */
.btn:hover:not(:disabled, [aria-disabled="true"])  { background: var(--b-bg-h); border-color: var(--b-border-h); color: var(--b-fg-h); }
.btn:active:not(:disabled, [aria-disabled="true"]) { background: var(--b-bg-a); border-color: var(--b-border-a); color: var(--b-fg-h); }
.btn:is(:disabled, [aria-disabled="true"])         { background: var(--b-bg); border-color: var(--b-border); color: var(--b-fg); box-shadow: none; }

/* Botones unidos (anterior/siguiente): una sola caja partida. No es un tipo
   más, es cómo se agrupan dos del mismo tipo. (No .btn-group: ese nombre es
   de Bootstrap, que sigue cargado.) */
.btn-join             { display: inline-flex; }
.btn-join > .btn:not(:first-child) { margin-left: -1px; border-top-left-radius: 0; border-bottom-left-radius: 0; }
.btn-join > .btn:not(:last-child)  { border-top-right-radius: 0; border-bottom-right-radius: 0; }
.btn-join > .btn:hover:not(:disabled) { position: relative; z-index: 1; }

/* Ganchos de layout sobre los tipos (sin color propio) */
.batch-count          { background: var(--bg-empacado); color: var(--c-empacado); border-radius: 99px; corner-shape: round; font-size: 10px; font-weight: 700; padding: 1px 6px; }
.btn-filter           { position: relative; }
.filter-badge         { position: absolute; top: -5px; right: -5px; background: var(--accent); color: #fff; border-radius: 99px; corner-shape: round; font-size: 9px; font-weight: 700; padding: 1px 5px; display: none; }
.btn-filter.has-filters .filter-badge { display: inline; }
.print-btn-row        { display: flex; gap: 8px; margin-bottom: 16px; }
.print-btn-row .btn   { flex: 1; }


/* ── 6. FORMULARIOS ───────────────────────────────────────────── */
.form-grid   { display: flex; flex-direction: column; gap: 14px; }
.form-row    { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.form-row-3  { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 14px; }
.v-field     { display: flex; flex-direction: column; gap: 5px; }

.v-field > label { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .07em; color: var(--text3); }

/* Radios y checkboxes quedan fuera: viven dentro de un campo (roles, tipo de
   cuadre) sin ser cajas de texto. */
.v-field input:not([type="checkbox"], [type="radio"]),
.v-field select,
.v-field textarea {
  background: var(--surface); border: 1px solid var(--border2); border-radius: var(--r);
  padding: 9px 12px; font-family: 'IBM Plex Sans', sans-serif; font-size: 13px;
  color: var(--text); outline: none; transition: border-color .15s; width: 100%;
}
/* Un diálogo recibe el foco al abrirse (modal.js) para que el lector de
   pantalla lo anuncie; la caja entera no necesita el anillo de foco. */
.mdl:focus, [role="dialog"]:focus { outline: none; }
/* Error en línea de un campo (`marcarCampo`, shared.js). El atributo sube la
   especificidad por encima de `.v-field input:not(…)` y de su :focus. */
.v-field .invalido[aria-invalid="true"],
.persona-field .invalido[aria-invalid="true"] { border-color: var(--danger); }
.campo-err { font-size: 11.5px; line-height: 1.4; color: var(--danger); }
.campo-err:empty { display: none; }
.v-field input:focus,
.v-field select:focus,
.v-field textarea:focus   { border-color: var(--accent); }
.v-field input::placeholder,
.v-field textarea::placeholder { color: var(--text3); }
.v-field input:disabled   { opacity: .45; cursor: not-allowed; }
.v-field select           { color-scheme: inherit; cursor: pointer; }
.v-field select option    { background: var(--surface2); }
.v-field textarea         { resize: none; min-height: 72px; line-height: 1.5; }

.field-hint       { font-size: 11px; color: var(--text3); margin-top: 3px; }
.section-divider  { border: none; border-top: 1px solid var(--border); margin: 16px 0; }

/* Búsqueda */
.search-wrap         { position: relative; flex: 1; max-width: 300px; }
/* Hijo directo: la lupa. El icono del botón de limpiar va anidado y no debe
   heredar este posicionamiento, que lo mandaría al borde izquierdo. */
.search-wrap > svg   { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); color: var(--text3); pointer-events: none; }
.search-input        { width: 100%; background: var(--surface2); border: 1px solid var(--border); border-radius: var(--r); padding: 7px 12px 7px 32px; font-family: 'IBM Plex Sans', sans-serif; font-size: 13px; color: var(--text); outline: none; transition: border-color .15s; }
.search-input::placeholder { color: var(--text3); }
.search-input:focus  { border-color: var(--accent); }

/* ── Limpiar lo escrito ──
   Va DENTRO de la caja: vaciar la búsqueda es parte de escribirla, no una
   acción más de la barra de controles. Aparece solo cuando hay algo que
   borrar, y **quien lo decide es el CSS**: `:placeholder-shown` es exactamente
   "el campo está vacío", así que ninguno de los diez módulos que usan este
   componente tiene que acordarse de encender ni apagar nada.
   El sitio se reserva solo cuando el botón existe — hay buscadores escritos a
   mano que no lo llevan y su texto no tiene por qué encogerse. */
.search-input:has(+ .search-clear) { padding-right: 30px; }
.search-clear        { position: absolute; right: 2px; top: 0; height: 100%; width: 28px;
                       display: flex; align-items: center; justify-content: center;
                       padding: 0; background: none; border: 0; color: var(--text3);
                       cursor: pointer; transition: color .15s; }
.search-clear:hover  { color: var(--text); }
.search-input:placeholder-shown + .search-clear { display: none; }

/* Firma */
.sig-group       { margin-bottom: 18px; }
.sig-label       { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: var(--text3); margin-bottom: 8px; }
.sig-wrap        { position: relative; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r); overflow: hidden; }
.sig-wrap.signed { border-color: #4ade8055; }
.sig-canvas      { display: block; width: 100%; height: 100px; cursor: crosshair; touch-action: none; }
.sig-hint        { position: absolute; bottom: 8px; right: 10px; font-size: 11px; color: var(--text3); pointer-events: none; }
.sig-toolbar     { display: flex; justify-content: space-between; align-items: center; padding: 6px 10px; border-top: 1px solid var(--border); }
.sig-status      { font-size: 11px; color: var(--text3); }
.sig-status.ok   { color: var(--ok); }
.sig-clear       { background: none; border: none; font-size: 11px; color: var(--text3); cursor: pointer; font-family: 'IBM Plex Sans', sans-serif; padding: 2px 6px; border-radius: var(--r-xs); }
.sig-clear:hover { color: var(--danger); background: var(--bg-incompleto); }

/* Upload */
.upload-area          { border: 1px dashed var(--border2); border-radius: var(--r); padding: 16px; text-align: center; cursor: pointer; transition: border-color .15s; position: relative; background: var(--surface); }
.upload-area:hover    { border-color: var(--accent); }
.upload-area-icon     { color: var(--text3); margin-bottom: 6px; }
.upload-area-text     { font-size: 12px; color: var(--text3); }
.upload-area-text strong { color: var(--accent-ink); }
.upload-preview       { display: flex; align-items: center; gap: 8px; padding: 8px 10px; background: var(--surface2); border: 1px solid var(--border); border-radius: var(--r); font-size: 12px; margin-top: 6px; }
.upload-preview-name  { flex: 1; color: var(--text); font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Checklist y confirmación */
.checklist        { display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px; }
.check-item       { display: flex; align-items: flex-start; gap: 10px; font-size: 13px; color: var(--text); line-height: 1.5; }
.check-icon       { width: 18px; height: 18px; background: var(--bg-entregado); border-radius: 50%; corner-shape: round; display: grid; place-items: center; flex-shrink: 0; margin-top: 1px; }
.confirm-row      { display: flex; align-items: flex-start; gap: 10px; padding: 14px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r); cursor: pointer; margin-bottom: 16px; }
.confirm-row input[type=checkbox] { width: 16px; height: 16px; flex-shrink: 0; accent-color: var(--accent); cursor: pointer; margin-top: 2px; }
.confirm-row label,
.confirm-row span  { font-size: 13px; line-height: 1.5; cursor: pointer; }
.divider          { border: none; border-top: 1px solid var(--border); margin: 18px 0; }


/* ── 7. TABLA PRINCIPAL ───────────────────────────────────────── */
.toolbar     { padding: 12px 28px; display: flex; align-items: center; gap: 10px; border-bottom: 1px solid var(--border); }
.table-wrap  { overflow-x: auto; padding: 0 28px 80px; }
table        { width: 100%; border-collapse: separate; border-spacing: 0; margin-top: 16px; }
/* Densidad vertical: la tabla es una herramienta de trabajo y cada fila que cabe
   en pantalla es una menos que buscar con scroll. El aire horizontal se conserva
   (16px) — es lo que separa columnas y hace legible la fila; el vertical se
   recorta. Fila resultante ≈ 42px con badge, ≈ 36px con texto plano. */
thead th     { text-align: left; padding: 7px 16px; font-size: 11px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--text3); border-bottom: 1px solid var(--border); white-space: nowrap; user-select: none; }
tbody tr     { transition: background .1s; cursor: pointer; }
tbody tr:hover td       { background: var(--hover); }
tbody tr.new-row        { animation: rowIn .35s ease-out both; }
tbody tr.updated-row td { animation: rowUpdated 2.2s ease-out both; }
tbody tr.active-row td  { background: var(--active); border-color: transparent; }
/* Pedido modificado por otro usuario y aún sin abrir (se quita al abrirlo) */
tbody tr.row-modified td             { background: var(--bg-incompleto); }
tbody tr.row-modified td:first-child { box-shadow: inset 3px 0 0 var(--c-incompleto); }
tbody tr.row-modified:hover td       { background: color-mix(in srgb, var(--bg-incompleto) 70%, var(--hover)); }
@keyframes rowIn      { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: translateY(0); } }
@keyframes rowUpdated { 0% { background: #2a1f00; } 60% { background: #2a1f00; } 100% { background: transparent; } }
td           { padding: 9px 16px; color: var(--text); vertical-align: middle; white-space: nowrap; border-bottom: 1px solid var(--border); transition: background .1s; }
.td-id       { font-family: 'IBM Plex Mono', monospace; font-size: 13px; font-weight: 500; color: var(--accent-ink); }
.td-cliente  { font-weight: 500; }
.td-date     { font-size: 12px; color: var(--text2); }
.row-chevron { color: var(--text3); transition: color .1s; }
tbody tr:hover .row-chevron { color: var(--text2); }
.empty-state      { text-align: center; padding: 40px 24px; color: var(--text3); }
.td-actions       { white-space: nowrap; vertical-align: middle; }
.td-actions-inner { display: flex; align-items: center; gap: 6px; }

/* Columna anclada a la derecha (la «Acción» de Pedidos). Con todas las columnas
   visibles la tabla mide más que la pantalla, y la acción —lo que se vino a
   hacer— quedaba fuera, a 1.777 px a 1440 de ancho. Fondo opaco, porque el de
   las filas (hover, activa, modificada) es translúcido y dejaría ver lo que
   pasa por debajo; `--tabla-fondo` es el fondo real de la tarjeta. */
th.th-anclada, td.td-anclada { position: sticky; right: 0; }
th.th-anclada { z-index: 3; }
tbody td.td-anclada { z-index: 1; background: var(--tabla-fondo, var(--surface)); box-shadow: inset 1px 0 0 var(--border); }
tbody tr:hover td.td-anclada        { background: var(--tabla-fondo, var(--surface)) linear-gradient(var(--hover), var(--hover)); }
tbody tr.active-row td.td-anclada   { background: var(--tabla-fondo, var(--surface)) linear-gradient(var(--active), var(--active)); }
tbody tr.row-modified td.td-anclada { background: var(--tabla-fondo, var(--surface)) linear-gradient(var(--bg-incompleto), var(--bg-incompleto)); }

/* Facturas (pills en tabla de pedidos) */
.td-facturas         { max-width: 160px; }
.fact-cell           { display: inline-flex; align-items: center; gap: 4px; }
.fact-pill           { display: inline-block; font-family: 'IBM Plex Mono', monospace; font-size: 11px; font-weight: 600; color: var(--accent-ink); background: var(--surface2); border: 1px solid var(--border2); border-radius: var(--r-sm); padding: 1px 6px; line-height: 1.5; }
.fact-pill--anulada  { color: var(--text3); background: transparent; text-decoration: line-through; }
.fact-more           { font-family: 'IBM Plex Sans', sans-serif; font-size: 10px; font-weight: 700; color: var(--text2); background: var(--surface2); border: 1px solid var(--border2); border-radius: var(--r-sm); padding: 1px 5px; cursor: default; white-space: nowrap; }
.items-count         { font-family: 'IBM Plex Mono', monospace; font-size: 12px; color: var(--text2); white-space: nowrap; }

/* Botón de acción compacto (solo en la columna de la tabla de pedidos) */
.td-actions .btn-sm svg  { width: 10px; height: 10px; }
.td-facturas, .items-count { cursor: default; }

/* Popover de celda (facturas / items) — fixed para no recortarse por overflow */
#cellPopover            { position: fixed; z-index: 9999; display: none; background: var(--surface); border: 1px solid var(--border2); border-radius: var(--r-md); padding: 9px 11px; box-shadow: var(--shadow-overlay); font-family: 'IBM Plex Sans', sans-serif; min-width: 170px; max-width: 300px; pointer-events: none; }
.cell-pop-title        { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--text3); margin-bottom: 7px; }
.pop-fac, .pop-item    { display: flex; align-items: center; gap: 10px; padding: 4px 0; font-size: 12px; border-top: 1px solid var(--border); }
.pop-fac:first-of-type, .pop-item:first-of-type { border-top: none; }
.pop-fac-num           { font-family: 'IBM Plex Mono', monospace; font-weight: 600; color: var(--accent-ink); }
.pop-fac--anulada .pop-fac-num { color: var(--text3); text-decoration: line-through; }
.pop-fac-est           { font-size: 10px; color: var(--text3); margin-left: auto; }
.pop-fac-total         { font-family: 'IBM Plex Mono', monospace; font-size: 11px; color: var(--text2); min-width: 56px; text-align: right; }
.pop-item-desc         { color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 210px; }
.pop-item-qty          { font-family: 'IBM Plex Mono', monospace; color: var(--text2); margin-left: auto; }

/* Cantidad separada en el empaque (la tabla es `.inv-table`, compartida con el detalle) */
.qty-input        { width: 64px; background: var(--surface); border: 1px solid var(--border2); border-radius: var(--r-sm); padding: 5px 8px; font-size: 13px; font-family: 'IBM Plex Mono', monospace; color: var(--text); text-align: center; outline: none; transition: border-color .15s; }
.qty-input:focus  { border-color: var(--accent); }
.qty-input.ok     { border-color: #4ade8055; background: var(--bg-entregado); }
.qty-input.short  { border-color: #f8717155; background: var(--bg-incompleto); }

/* Tabla de factura */
.inv-table                        { width: 100%; border-collapse: collapse; font-size: 13px; table-layout: fixed; }
.inv-table th                     { padding: 7px 0; text-align: left; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .07em; color: var(--text3); border-bottom: 1px solid var(--border); }
.inv-table th:last-child,
.inv-table td:last-child          { text-align: right; }
.inv-table td                     { padding: 9px 0; border-bottom: 1px solid var(--border); color: var(--text); }
.inv-table tr:last-child td       { border-bottom: none; }
.inv-table .col-img               { width: 44px; padding-right: 8px; }
.inv-table .col-desc              { overflow: hidden; }
.inv-table .col-qty               { width: 46px; text-align: right; }
.inv-table .col-unit              { width: 90px; text-align: right; }
.inv-table .col-tot               { width: 90px; text-align: right; }
.inv-prod-thumb                   { width: 32px; height: 32px; border-radius: var(--r-sm); object-fit: cover; border: 1px solid var(--border); display: block; }
.inv-prod-placeholder             { width: 32px; height: 32px; border-radius: var(--r-sm); border: 1px solid var(--border); background: var(--surface2); display: flex; align-items: center; justify-content: center; color: var(--text3); }
.inv-prod-name                    { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: block; cursor: default; }
.inv-totals                       { margin-top: 14px; display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
.inv-tot-row                      { display: flex; gap: 24px; justify-content: flex-end; font-size: 13px; }
.inv-tot-row span:first-child     { color: var(--text2); }
.inv-tot-row span:last-child      { font-weight: 600; min-width: 100px; text-align: right; font-family: 'IBM Plex Mono', monospace; }
.inv-tot-total                    { border-top: 1px solid var(--border); padding-top: 8px; margin-top: 4px; font-size: 15px; }
.inv-tot-total span:last-child    { font-size: 16px; font-weight: 700; }
/* Productos editables de un pedido de Shopify (modo edición del panel) */
.inv-table--edit .col-qty         { width: 76px; }
.inv-table--edit .col-del         { width: 30px; text-align: right; }
.inv-table--edit .qty-input       { width: 60px; padding: 4px 6px; }
/* Con el precio editable el unitario es un campo, con el base tachado encima. */
.inv-table--precio .col-unit      { width: 112px; }
.inv-table--edit .precio-input    { width: 96px; text-align: right; appearance: textfield; -moz-appearance: textfield; }
.precio-input::-webkit-inner-spin-button,
.precio-input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.precio-movil                     { display: none; }
.qty-input[aria-invalid="true"]   { border-color: var(--danger); }
/* Productos del pedido en móvil: el nombre se lee entero y cantidad × unitario
   bajan a una línea bajo él; las dos columnas estrechas desaparecen. */
.inv-prod-meta                    { display: none; }
/* Línea con descuento: qué descuento fue, bajo el nombre, y el precio base
   tachado sobre el unitario. En móvil la columna del unitario no está, así que
   lo que queda a la vista es la frase del descuento. */
.inv-prod-dcto                    { display: block; margin-top: 2px; font-size: 11px; color: var(--text2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.inv-precio-base                  { display: block; font-size: 11px; color: var(--text3); text-decoration: line-through; }
@media (max-width: 600px) {
  .inv-table--lineas .inv-prod-dcto       { white-space: normal; overflow-wrap: anywhere; }
  .inv-table--lineas .col-img             { width: 40px; }
  .inv-table--lineas .col-unit            { display: none; }
  .inv-table--lineas:not(.inv-table--edit) .col-qty { display: none; }
  .inv-table--lineas .col-desc            { padding-right: 8px; vertical-align: top; }
  .inv-table--lineas .col-img             { vertical-align: top; }
  .inv-table--lineas .inv-prod-name       { white-space: normal; overflow-wrap: anywhere; line-height: 1.35; }
  .inv-table--lineas .inv-prod-meta       { display: block; margin-top: 2px; font-size: 12px; color: var(--text2); font-family: 'IBM Plex Mono', monospace; }
  .inv-table--lineas .col-tot             { vertical-align: top; width: 88px; }
  .inv-table--precio .precio-movil        { display: block; margin-top: 4px; }
  .inv-table--precio .precio-movil .precio-input { width: 68px; padding: 4px 6px; }
}
.prod-buscar                      { margin-top: 14px; }
/* El buscador y la lista de precios, en la misma fila: la lista es con la que
   se precia lo que se agregue. */
.prod-buscar-fila                 { display: flex; align-items: center; gap: 8px; }
.prod-buscar-fila > .edit-input   { flex: 1; min-width: 0; }
.prod-lista-caja                  { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; }
.prod-buscar-fila .prod-lista     { width: auto; max-width: 190px; }
@media (max-width: 600px) {
  /* En móvil no caben los dos en una fila sin dejar el buscador ilegible. */
  .prod-buscar-fila               { flex-wrap: wrap; }
  .prod-buscar-fila > .edit-input,
  .prod-lista-caja                { flex: 1 1 100%; }
  .prod-buscar-fila .prod-lista   { flex: 1; max-width: none; }
}
.prod-buscar-lista                { list-style: none; margin: 6px 0 0; padding: 0; border: 1px solid var(--border); border-radius: var(--r-sm); max-height: 280px; overflow-y: auto; }
.prod-buscar-item                 { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-bottom: 1px solid var(--border); }
.prod-buscar-item:last-child      { border-bottom: none; }
.prod-buscar-info                 { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; font-size: 13px; }
.prod-buscar-cod                  { font-size: 11px; color: var(--text3); font-family: 'IBM Plex Mono', monospace; display: flex; align-items: center; gap: 6px; }
.prod-buscar-precio               { font-family: 'IBM Plex Mono', monospace; font-size: 12px; color: var(--text2); white-space: nowrap; }
.prod-buscar-nota                 { font-size: 12px; color: var(--text3); padding: 8px 10px; }


/* ── 8. BADGES DE ESTADO ──────────────────────────────────────── */
.badge      { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: 99px; corner-shape: round; font-size: 11.5px; font-weight: 600; pointer-events: none; user-select: none; }
.badge-dot  { width: 6px; height: 6px; border-radius: 50%; corner-shape: round; flex-shrink: 0; }

/* Badge neutral — para valores libres sin un estado semántico asociado (ej. Tipo de cliente) */
.badge-neutral           { background: var(--surface2); color: var(--text2); border: 1px solid var(--border); }
.badge-neutral .badge-dot{ background: var(--text3); }

.s-borrador   { background: var(--bg-borrador);   color: var(--c-borrador); }
.s-pendiente  { background: var(--bg-pendiente);  color: var(--c-pendiente); }
.s-proceso    { background: var(--bg-proceso);    color: var(--c-proceso); }
.s-separando  { background: var(--bg-separando);  color: var(--c-separando); }
.s-listo      { background: var(--bg-listo);      color: var(--c-listo); }
.s-espera     { background: var(--bg-espera);     color: var(--c-espera); }
.s-facturado  { background: var(--bg-facturado);  color: var(--c-facturado); }
.s-empacado   { background: var(--bg-empacado);   color: var(--c-empacado); }
.s-camino     { background: var(--bg-camino);     color: var(--c-camino); }
.s-entregado  { background: var(--bg-entregado);  color: var(--c-entregado); }
.s-incompleto { background: var(--bg-incompleto); color: var(--c-incompleto); }
.s-parcial    { background: var(--bg-parcial);    color: var(--c-parcial); }
.s-anulado    { background: var(--bg-anulado);    color: var(--c-anulado); }

/* Estado de pago — misma forma que .s-* pero sin dot */
.sp-pendiente { background: var(--bg-pendiente);  color: var(--c-pendiente); }
.sp-parcial   { background: var(--bg-incompleto); color: var(--c-incompleto); }
.sp-pagado    { background: var(--bg-entregado);  color: var(--ok); }
.sp-excedente { background: var(--bg-listo);      color: var(--c-listo); }

/* Canal de entrada — badge sutil con bolita de color por origen */
.chan            { display: inline-flex; align-items: center; gap: 6px; font-size: 11px; font-weight: 600; padding: 3px 9px; border-radius: 99px; corner-shape: round; border: 1px solid var(--border); background: var(--surface2); color: var(--text2); white-space: nowrap; }
.chan-dot        { width: 7px; height: 7px; border-radius: 50%; corner-shape: round; flex-shrink: 0; background: var(--text3); }
.chan-shopify .chan-dot, .chan-dot.chan-shopify { background: #4ade80; }
.chan-factura .chan-dot, .chan-dot.chan-factura { background: #60a5fa; }
.chan-api     .chan-dot, .chan-dot.chan-api     { background: #c084fc; }

/* Etiquetas semánticas inline */
.meta-label        { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; color: var(--text3); }
.meta-label.ok     { color: var(--ok); }
.meta-label.warn   { color: var(--warn); }
.meta-label.danger { color: var(--danger); }


/* ── 9. PILLS ─────────────────────────────────────────────────── */
/* UNA sola definición de pill para todo el proyecto: filtros rápidos de la
   statsbar, segmentos de vista, pestañas y chips del panel de filtros comparten
   tamaño, tipografía y estados. El markup tampoco se escribe a mano: sale de
   `pillHtml` (shared.js) o de la macro `tablecard.pill`. Si necesitas otro
   aspecto, no crees una clase nueva: probablemente no sea una pill.  */
/* Los filtros rápidos nunca saltan de línea: si no caben, la fila se desplaza en
   horizontal (sin barra visible, como en un carrusel). Igual en todas las tablas. */
.statsbar    { padding: 12px 28px; display: flex; gap: 8px; flex-wrap: nowrap; overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none; border-bottom: 1px solid var(--border); background: var(--surface); }
.statsbar::-webkit-scrollbar { display: none; }
.statsbar > * { flex-shrink: 0; }
/* Difuminado en el borde por el que sigue habiendo pills. Con scroll-driven
   animations, el de la derecha se apaga al llegar al final y aparece uno a la
   izquierda al desplazarse; sin soporte (o sin nada que desplazar) queda solo
   el de la derecha, que sobre una fila que cabe cae en espacio vacío. */
@property --sb-fade-l { syntax: '<length>'; inherits: false; initial-value: 0px; }
@property --sb-fade-r { syntax: '<length>'; inherits: false; initial-value: 40px; }
.statsbar {
  -webkit-mask-image: linear-gradient(to right, transparent, #000 var(--sb-fade-l), #000 calc(100% - var(--sb-fade-r)), transparent);
          mask-image: linear-gradient(to right, transparent, #000 var(--sb-fade-l), #000 calc(100% - var(--sb-fade-r)), transparent);
}
@supports (animation-timeline: scroll()) {
  .statsbar { animation: sb-fade linear both; animation-timeline: scroll(self inline); }
  @keyframes sb-fade {
    0%   { --sb-fade-l: 0px;  --sb-fade-r: 40px; }
    8%   { --sb-fade-l: 40px; }
    92%  { --sb-fade-r: 40px; }
    100% { --sb-fade-l: 40px; --sb-fade-r: 0px; }
  }
}

.pill {
  display: inline-flex; align-items: center; gap: 7px;
  background: transparent; border: 1px solid var(--border); border-radius: 99px; corner-shape: round;
  padding: 5px 12px; cursor: pointer; user-select: none;
  font-family: inherit; font-size: 12px; font-weight: 500; line-height: 1.4;
  color: var(--text2); white-space: nowrap; appearance: none; text-align: left;
  transition: border-color .15s, background .15s, color .15s;
}
.pill:hover { background: var(--hover); border-color: var(--border-strong); color: var(--text); }
/* Los tres estados son los de la barra lateral: transparente en reposo, --hover
   bajo el puntero y la marca de la sección activa al estar seleccionada. */
.pill.active,
.pill.active:hover { background: var(--nav-active); border-color: var(--nav-active-border); color: var(--text); }

.pill-dot    { width: 8px; height: 8px; border-radius: 50%; corner-shape: round; flex-shrink: 0; }
.pill-label  { color: inherit; }
/* Contador: mono y tabular para que la fila de pills no baile al actualizarse */
.pill-count  { font-size: 12px; font-family: 'IBM Plex Mono', monospace; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--text); margin-left: 2px; }


/* ── 10. PANEL DE FILTROS ─────────────────────────────────────── */
.filter-panel              { position: absolute; top: calc(100% + 6px); right: 0; width: 320px; max-width: calc(100vw - 24px); background: var(--surface); border: 1px solid var(--border2); border-radius: var(--r-md); padding: 0; z-index: 500; box-shadow: var(--shadow-overlay); display: none; overflow: hidden; }
/* Al abrir: columna con cuerpo scrollable para no exceder el alto de pantalla */
.filter-panel.open         { display: flex; flex-direction: column; max-height: calc(100vh - 200px); animation: mIn .15s ease-out; }
.filter-body               { overflow-y: auto; overscroll-behavior: contain; min-height: 0; }
.filter-section            { padding: 16px 16px 0; }
.filter-section:last-of-type { padding-bottom: 16px; }
.filter-label              { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .1em; color: var(--text3); margin-bottom: 8px; }
/* Chips del panel: son `.pill` (definidas en §9), aquí solo su contenedor. */
.filter-chips              { display: flex; flex-wrap: wrap; gap: 6px; }
/* Una sección cuyas opciones salen del dato (agente, método) puede quedarse sin
   ninguna: el hueco mudo se lee como "no cargó". */
.filter-chips-empty        { font-size: 12px; color: var(--text3); }
/* Select dentro del panel: los filtros que antes vivían sueltos en la toolbar
   (agente, punto de venta, método…) bajaron aquí. Ver §Barra de controles. */
.filter-select             { width: 100%; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r); padding: 7px 10px; font-size: 12.5px; color: var(--text); font-family: 'IBM Plex Sans', sans-serif; outline: none; cursor: pointer; transition: border-color .15s; }
.filter-select:focus       { border-color: var(--accent); }
.filter-select option      { background: var(--surface2); }
.filter-divider            { border: none; border-top: 1px solid var(--border); margin: 0; }
/* Inputs de fecha del panel — LEGACY. El panel de filtros ya no filtra por fecha
   (eso es el selector de fecha avanzado de la toolbar). Solo sobreviven para
   `templates/index.html`, que no tiene ruta. No los uses en vistas nuevas. */
.filter-date-row           { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.filter-date-label         { font-size: 10px; color: var(--text3); margin-bottom: 4px; }
.filter-date-input         { width: 100%; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-sm); padding: 6px 10px; font-size: 12px; color: var(--text); font-family: 'IBM Plex Sans', sans-serif; outline: none; transition: border-color .15s; color-scheme: inherit; }
.filter-date-input:focus   { border-color: var(--accent); }
.filter-footer             { padding: 12px 16px; display: flex; justify-content: space-between; align-items: center; background: var(--surface); border-top: 1px solid var(--border); flex-shrink: 0; }
.filter-active-count       { font-size: 11px; color: var(--accent-ink); font-weight: 600; }

/* Organizador de columnas (mostrar/ocultar + reordenar) */
.cols-panel                { position: absolute; top: calc(100% + 6px); right: 0; width: 240px; max-width: calc(100vw - 24px); background: var(--surface); border: 1px solid var(--border2); border-radius: var(--r-md); z-index: 500; box-shadow: var(--shadow-overlay); display: none; overflow: hidden; }
.cols-panel.open           { display: flex; flex-direction: column; max-height: calc(100vh - 200px); animation: mIn .15s ease-out; }
.cols-panel-head           { display: flex; align-items: center; justify-content: space-between; padding: 12px 14px 8px; flex-shrink: 0; }
.cols-list                 { padding: 4px 8px 8px; overflow-y: auto; overscroll-behavior: contain; flex: 1; min-height: 0; }
.cols-item                 { display: flex; align-items: center; gap: 8px; padding: 6px 8px; border-radius: var(--r-sm); cursor: grab; transition: background .12s; }
.cols-item:hover           { background: var(--surface); }
.cols-item.dragging        { opacity: .5; }
.cols-handle               { color: var(--text3); font-size: 13px; line-height: 1; cursor: grab; user-select: none; }
.cols-check                { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--text); cursor: pointer; flex: 1; }
.cols-check input          { accent-color: var(--accent); cursor: pointer; }
.cols-panel-hint           { padding: 8px 14px 12px; font-size: 10.5px; color: var(--text3); border-top: 1px solid var(--border); flex-shrink: 0; }


/* ── 11. MODALES ──────────────────────────────────────────────── */
@keyframes mIn { from { opacity: 0; transform: scale(.96) translateY(8px); } to { opacity: 1; transform: scale(1) translateY(0); } }

/* Modal centrado (empaques) */
.overlay        { display: none; position: fixed; inset: 0; background: #00000099; backdrop-filter: blur(4px); z-index: 200; align-items: center; justify-content: center; padding: 16px; }
.overlay.open   { display: flex; }
.step-modal     { width: 480px; max-width: 100%; max-height: calc(100vh - 32px); animation: mIn .2s ease-out; }

/* Modal de ventas (ancho mayor, scroll vertical) */
.v-overlay      { display: none; position: fixed; inset: 0; background: #00000099; backdrop-filter: blur(4px); z-index: 200; align-items: flex-start; justify-content: center; padding: 32px 16px; overflow-y: auto; }
.v-overlay.open { display: flex; }
.v-modal        { width: 680px; max-width: 100%; max-height: calc(100vh - 64px); margin: auto; animation: mIn .2s ease-out; }
/* Diálogos de confirmación a mano (resetear contraseña): no son .mdl, como
   confirmDialog; conservan su caja propia. */
.v-modal:not(.mdl)                { background: var(--surface); border: 1px solid var(--border2); border-radius: var(--r-lg); box-shadow: var(--shadow-overlay); }
.v-modal:not(.mdl) .modal-body    { padding: 20px 24px; }
.v-modal:not(.mdl) .modal-footer  { padding: 0 24px 24px; display: flex; justify-content: flex-end; gap: 8px; }
/* Variante ancha de dos columnas (nuevo pedido, corregir): solo cambia el ancho. */
.v-modal--wide  { width: min(1080px, 100%); }
/* La barra de pasos ya no se usa en este modal; oculta el borde residual al estar vacía. */
.step-bar:empty { display: none; }

/* Modal de novedades */
.missing-overlay        { display: none; position: fixed; inset: 0; background: #00000099; backdrop-filter: blur(4px); z-index: 300; align-items: center; justify-content: center; padding: 16px; }
.missing-overlay.open   { display: flex; }
.missing-modal          { width: 680px; max-width: 95vw; max-height: 90vh; animation: mIn .2s ease-out; }

/* Productos faltantes (pedidos.js · faltantesHtml): una tarjeta por cliente,
   un bloque por pedido. El aire va entre pedidos, no dentro de cada uno. */
.falt-cliente           { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; color: var(--text2); margin-bottom: 12px; }
.falt-ident, .falt-unid { font-family: 'IBM Plex Mono', monospace; font-weight: 400; letter-spacing: .04em; color: var(--text3); }
.falt-pedido + .falt-pedido { margin-top: 18px; }
.falt-pedido-head       { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; font-size: 12px; }
.falt-pedido .inv-table { margin-top: 4px; }   /* el table global trae 16px */
.falt-id                { font-family: 'IBM Plex Mono', monospace; font-size: 12.5px; font-weight: 600; color: var(--accent-ink); text-decoration: none; }
a.falt-id:hover         { text-decoration: underline; text-underline-offset: 2px; }
.falt-meta              { color: var(--text3); text-align: right; }
.inv-table td.falt-vacio { text-align: left; color: var(--text3); }
.missing-cols           { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.missing-col-title      { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .1em; margin-bottom: 10px; }
.missing-col-title.ok   { color: var(--ok); }
.missing-col-title.bad  { color: var(--danger); }
.missing-item           { display: flex; justify-content: space-between; align-items: center; padding: 8px 10px; border-radius: var(--r-xs); margin-bottom: 6px; font-size: 13px; }
.missing-item.ok        { background: var(--bg-entregado); color: var(--ok); }
.missing-item.bad       { background: var(--bg-incompleto); color: var(--danger); }
.missing-item-qty       { font-family: 'IBM Plex Mono', monospace; font-size: 12px; font-weight: 600; }


/* Modal de nuevo pedido: dos columnas 50/50, reutilizando el componente .psec
   (tarjeta) del Pop Up de detalle del pedido. */
.np-grid        { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: start; }
.np-col         { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.np-col .psec       { border-bottom: none; border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface); display: flex; flex-direction: column; gap: 14px; }
.np-col .psec-title { margin-bottom: 0; }
@media (max-width: 900px) {
  .np-grid      { grid-template-columns: 1fr; }
}


/* ── 12. PANELES LATERALES ────────────────────────────────────── */
.panel-backdrop       { display: none; position: fixed; inset: 0; background: #00000066; backdrop-filter: blur(2px); z-index: 100; }
.panel-backdrop.open  { display: block; }

/* Panel de detalle del pedido */
.detail-panel         { position: fixed; top: 0; right: 0; width: 40vw; min-width: 440px; max-width: 100vw; height: 100vh; background: var(--surface); border-left: 1px solid var(--border2); z-index: 101; display: flex; flex-direction: column; transform: translateX(100%); transition: transform .28s cubic-bezier(.4,0,.2,1); }
.detail-panel.open    { transform: translateX(0); }
.panel-header         { padding: 20px 24px 16px; border-bottom: 1px solid var(--border); flex-shrink: 0; }
.panel-header-top     { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 12px; }
.panel-id             { font-family: 'IBM Plex Mono', monospace; font-size: 13px; color: var(--accent-ink); font-weight: 500; }
.panel-cliente        { font-size: 18px; font-weight: 700; letter-spacing: -.02em; margin-top: 2px; }
.panel-header-meta    { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.panel-body           { flex: 1; overflow-y: auto; padding: 0; }
.panel-footer         { padding: 16px 24px; border-top: 1px solid var(--border); display: flex; gap: 8px; flex-shrink: 0; background: var(--surface); }
.panel-ov             { font-family: 'IBM Plex Mono', monospace; font-size: 13px; color: var(--accent-ink); font-weight: 500; }

/* Secciones dentro del panel */
.psec            { padding: 20px 24px; border-bottom: 1px solid var(--border); }
.psec-title      { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .1em; color: var(--text3); margin-bottom: 14px; }
.info-grid       { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.cli-block       { display: flex; flex-direction: column; align-items: flex-start; }
.cli-line        { font-size: 13px; font-weight: 500; line-height: 1.4; color: var(--text); }
.cli-line--empty { color: var(--text3); font-weight: 400; }
.cli-lbl         { color: var(--text3); font-weight: 600; }
.cli-conv-btn    { margin-top: 12px; }
.info-field label { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: .07em; color: var(--text3); }
.info-field p    { font-size: 13px; font-weight: 500; margin-top: 3px; color: var(--text); }

/* Panel de despacho por lote */
/* Despacho masivo: un .mdl que flota contra el borde derecho, despegado de la
   ventana con los insets de la página (16px 20px, los de .module-shell y del
   panel de Cuadres), y entra deslizándose. Con velo detrás (#batchBackdrop):
   es una tarea que se termina o se abandona. Conserva la sombra: flota sobre
   el velo. `visibility` conmuta al final de la salida para que, cerrado, no
   quede tabulable fuera de la pantalla. En móvil ocupa la pantalla. */
.batch-panel.mdl      { position: fixed; z-index: 150; top: 16px; bottom: 16px; right: 20px;
                        width: min(480px, calc(100vw - 40px));
                        transform: translateX(calc(100% + 20px)); visibility: hidden;
                        transition: transform .28s cubic-bezier(.4,0,.2,1), visibility 0s linear .28s; }
.batch-panel.mdl.open { transform: translateX(0); visibility: visible;
                        transition: transform .28s cubic-bezier(.4,0,.2,1), visibility 0s; }
/* El buscador se queda pegado bajo la barra al bajar por la lista; su fondo
   tapa las filas que pasan por detrás. --mdl-bar-h lo publica modal.js. */
.batch-search         { position: sticky; top: calc(var(--mdl-bar-h, 49px) - var(--mdl-pad) - 2px); z-index: 4;
                        margin: 0 0 12px; padding: 0 0 12px; background: var(--surface); }
.batch-search .search-wrap { max-width: none; }
.batch-foot-count     { font-size: 12px; color: var(--text2); }
@media (max-width: 600px) {
  .batch-panel.mdl    { top: env(safe-area-inset-top, 0px); bottom: 0; right: 0; width: 100vw;
                        border-radius: 0; border: none; transform: translateX(100%); }
}
.batch-item           { display: flex; align-items: center; gap: 12px; padding: 12px 14px; border: 1px solid var(--border); border-radius: var(--r); margin-bottom: 8px; cursor: pointer; transition: all .15s; user-select: none; }
.batch-item:hover     { border-color: var(--border-strong); background: var(--hover); }
.batch-item.selected  { border-color: var(--c-empacado); background: var(--bg-empacado); }
.batch-cb             { width: 16px; height: 16px; accent-color: var(--accent); cursor: pointer; flex-shrink: 0; }
.batch-item-info      { flex: 1; min-width: 0; }
.batch-item-id        { font-family: 'IBM Plex Mono', monospace; font-size: 12px; color: var(--accent-ink); }
.batch-item-cliente   { font-size: 13px; font-weight: 500; margin-top: 1px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.batch-item-meta      { font-size: 11px; color: var(--text2); margin-top: 2px; }
.batch-item-valor     { font-family: 'IBM Plex Mono', monospace; font-size: 12px; font-weight: 600; flex-shrink: 0; }
.batch-select-all     { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--text2); margin-bottom: 12px; cursor: pointer; user-select: none; }
.batch-select-all input { accent-color: var(--accent); width: 15px; height: 15px; }
.batch-empty          { text-align: center; padding: 40px 16px; color: var(--text3); font-size: 13px; }

/* Contador de cajas */
.box-input-row  { display: flex; align-items: center; gap: 10px; padding: 12px 14px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r); margin-bottom: 16px; }
.box-input-row label { font-size: 13px; color: var(--text); flex: 1; }
.box-input      { width: 72px; background: var(--surface2); border: 1px solid var(--border2); border-radius: var(--r-sm); padding: 6px 10px; font-size: 14px; font-family: 'IBM Plex Mono', monospace; font-weight: 600; color: var(--text); text-align: center; outline: none; transition: border-color .15s; }
.box-input:focus { border-color: var(--accent); }


/* ── 13. BARRA DE PASOS (STEP BAR) ───────────────────────────── */
.step-bar       { display: flex; border-bottom: 1px solid var(--border); margin-bottom: 16px; }
.step-item      { display: flex; align-items: center; gap: 8px; padding: 14px 12px; font-size: 12px; font-weight: 500; color: var(--text3); border-bottom: 2px solid transparent; white-space: nowrap; }
.step-item.active { color: var(--accent-ink); border-bottom-color: var(--accent); }
.step-item.done   { color: var(--ok); }
.step-num         { width: 20px; height: 20px; border-radius: 50%; corner-shape: round; background: var(--surface); border: 1px solid var(--border2); display: grid; place-items: center; font-size: 10px; font-weight: 700; flex-shrink: 0; font-family: 'IBM Plex Mono', monospace; }
.step-item.active .step-num { background: var(--accent); border-color: var(--accent); color: #fff; }
.step-item.done   .step-num { background: var(--bg-entregado); border-color: var(--ok); color: var(--ok); }


/* ── 14. ALERTAS ──────────────────────────────────────────────── */
.alert         { display: flex; align-items: flex-start; gap: 10px; padding: 14px 16px; border-radius: var(--r); margin-bottom: 16px; font-size: 13px; line-height: 1.6; }
.alert svg     { flex-shrink: 0; margin-top: 1px; }
.alert-warn    { background: var(--bg-espera);    border: 1px solid #f5b94244; color: var(--warn); }
.alert-danger  { background: var(--bg-incompleto); border: 1px solid #f8717144; color: var(--danger); }
.alert-info    { background: var(--bg-proceso);   border: 1px solid #9b26b644; color: var(--accent-ink); }


/* ── 15. TIMELINE ─────────────────────────────────────────────── */
.timeline           { display: flex; flex-direction: column; gap: 0; }
.tl-item            { display: flex; gap: 14px; position: relative; }
.tl-left            { display: flex; flex-direction: column; align-items: center; flex-shrink: 0; width: 20px; }
.tl-dot             { width: 12px; height: 12px; border-radius: 50%; corner-shape: round; flex-shrink: 0; margin-top: 3px; border: 2px solid var(--bg); box-shadow: 0 0 0 1px currentColor; position: relative; z-index: 1; }
.tl-line            { flex: 1; width: 2px; background: var(--border); margin: 4px 0; }
.tl-item:last-child .tl-line { display: none; }
.tl-content         { padding-bottom: 20px; flex: 1; }
.tl-estado          { font-size: 13px; font-weight: 600; }
.tl-time            { font-size: 11px; color: var(--text3); margin-top: 2px; font-family: 'IBM Plex Mono', monospace; }
.tl-note            { font-size: 12px; color: var(--text2); margin-top: 4px; line-height: 1.5; }
.tl-resp            { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; color: var(--text3); margin-top: 5px; background: var(--bg2); border: 1px solid var(--border); border-radius: var(--r-xs); padding: 2px 7px; width: fit-content; }
.tl-head            { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.tl-del             { opacity: 0; transition: opacity .12s, background .15s, color .15s; }
.tl-item:hover .tl-del, .tl-del:focus-visible { opacity: 1; }
.tl-item--comentario .tl-note { color: var(--text); background: var(--bg2); border: 1px solid var(--border); border-radius: var(--r-sm); padding: 8px 10px; }

/* Composer de comentarios del histórico */
.tl-composer        { margin-bottom: 18px; }
.tl-composer-input  { width: 100%; box-sizing: border-box; resize: vertical; min-height: 40px; background: var(--surface2); border: 1px solid var(--border); border-radius: var(--r); padding: 9px 11px; font-size: 13px; color: var(--text); font-family: inherit; line-height: 1.5; outline: none; transition: border-color .12s; }
.tl-composer-input:focus { border-color: var(--accent); }
.tl-composer-input::placeholder { color: var(--text3); }
.tl-composer-actions { display: flex; justify-content: flex-end; margin-top: 8px; }
.tl-composer-btn    { font-size: 12px; }


/* ── 16. VISTA PREVIA OV / REVIEW ────────────────────────────── */
.ov-search-wrap       { display: flex; gap: 8px; align-items: stretch; }
.ov-search-wrap input { flex: 1; }
.ov-result            { border: 1px solid var(--border); border-radius: var(--r); overflow: hidden; margin-top: 12px; display: none; }
.ov-result.visible    { display: block; animation: mIn .2s ease-out; }
.ov-result-header     { display: flex; align-items: center; justify-content: space-between; padding: 12px 14px; background: var(--surface); border-bottom: 1px solid var(--border); }
.ov-result-id         { font-family: 'IBM Plex Mono', monospace; font-size: 14px; font-weight: 600; color: var(--accent-ink); }
.ov-result-cliente    { font-size: 13px; font-weight: 600; margin-top: 1px; }
.ov-result-meta       { font-size: 11px; color: var(--text3); margin-top: 2px; }
.ov-items-list        { padding: 12px 14px; display: flex; flex-direction: column; gap: 6px; }
.ov-item-row          { display: flex; justify-content: space-between; align-items: center; font-size: 12px; padding: 6px 10px; border-radius: var(--r-xs); background: var(--surface2); }
.ov-item-desc         { color: var(--text); font-weight: 500; }
.ov-item-qty          { font-family: 'IBM Plex Mono', monospace; color: var(--text3); }
.ov-item-val          { font-family: 'IBM Plex Mono', monospace; color: var(--text); font-weight: 600; }
.ov-result-total      { padding: 10px 14px; border-top: 1px solid var(--border); display: flex; justify-content: space-between; align-items: center; font-size: 13px; }
.ov-result-total span:first-child { color: var(--text2); }
.ov-result-total span:last-child  { font-family: 'IBM Plex Mono', monospace; font-weight: 700; color: var(--accent-ink); }
.ov-confirm-row       { padding: 12px 14px; border-top: 1px solid var(--border); display: flex; align-items: center; gap: 10px; background: var(--bg); }
/* Selector de lista de precios de la importación de Shopify: elige con qué
   precios se va a facturar el pedido. Pills porque son cinco opciones cortas y
   el total de abajo cambia con la que esté activa. */
.ov-listas            { padding: 10px 14px; border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ov-listas-label      { font-size: 11px; color: var(--text3); text-transform: uppercase; letter-spacing: .04em; }
.ov-listas-pills      { display: flex; gap: 6px; flex-wrap: wrap; }
.ov-listas-nota       { font-size: 11.5px; color: var(--text3); }
.ov-item-unit         { display: block; font-size: 11px; color: var(--text3); font-family: 'IBM Plex Mono', monospace; margin-top: 2px; }
/* Líneas de apoyo del total (domicilio, total a cobrar): el que manda es el de
   la factura, que conserva el peso. */
.ov-result-total--sec { border-top: none; padding-top: 0; font-size: 12px; }
.ov-result-total--sec span:last-child { font-weight: 500; color: var(--text2); }
.ov-aviso             { padding: 0 14px 10px; font-size: 11.5px; color: var(--warn); line-height: 1.5; }
.ov-aviso--psec       { padding: 10px 0 0; }
.ov-not-found         { padding: 20px 16px; text-align: center; color: var(--danger); font-size: 13px; display: flex; flex-direction: column; align-items: center; gap: 6px; }

.review-block         { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r); padding: 14px 16px; margin-bottom: 10px; }
.review-block-title   { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .1em; color: var(--text3); margin-bottom: 10px; }
.review-kv            { display: grid; grid-template-columns: 1fr 1fr; gap: 6px 16px; }
.review-kv-item label { font-size: 10px; color: var(--text3); }
.review-kv-item p     { font-size: 13px; font-weight: 500; margin-top: 1px; color: var(--text); }

/* Preview de estado de pago */
.estado-pago-preview        { margin-top: 0; }
.estado-pago-row            { display: grid; grid-template-columns: 1fr 1fr auto; gap: 16px; padding: 14px 16px; background: var(--surface); border: 1.5px solid var(--border2); border-radius: var(--r); transition: border-color .25s, background .25s; }
.estado-pago-col            { display: flex; flex-direction: column; gap: 4px; }
.estado-pago-col:last-child { align-items: flex-end; justify-content: center; }
.estado-pago-col-label      { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: .07em; color: var(--text3); }
.estado-pago-col-val        { font-size: 15px; font-weight: 700; font-family: 'IBM Plex Mono', monospace; color: var(--text); }
.estado-pago-badge          { font-size: 12px; font-weight: 700; letter-spacing: .04em; border: 1.5px solid; border-radius: 99px; corner-shape: round; padding: 3px 12px; display: inline-block; }
.estado-pago-diff           { font-size: 11px; font-weight: 600; font-family: 'IBM Plex Mono', monospace; margin-top: 4px; }

/* Vista previa de etiqueta */
.label-preview        { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r); padding: 16px; margin-bottom: 16px; font-size: 12px; }
.label-preview-title  { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .1em; color: var(--text3); margin-bottom: 10px; }
.label-grid           { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.label-field label    { font-size: 10px; color: var(--text3); font-weight: 600; text-transform: uppercase; letter-spacing: .05em; }
.label-field p        { font-size: 13px; font-weight: 500; margin-top: 2px; }


/* ── 17. PÁGINA DE LOGIN ──────────────────────────────────────── */
body.login-page {
  overflow: auto;
  height: auto;
  display: grid;
  place-items: center;
  min-height: 100vh;
}
.login-card     { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); padding: 40px 36px; width: 100%; max-width: 380px; }
.login-brand    { display: flex; align-items: center; gap: 10px; margin-bottom: 32px; }
.login-brand-icon       { width: 36px; height: 36px; border-radius: 50%; corner-shape: round; flex-shrink: 0; overflow: hidden; }
.login-brand-icon img   { width: 100%; height: 100%; object-fit: cover; }
.login-brand-name       { font-size: 15px; font-weight: 600; letter-spacing: -.01em; }
.login-brand-sub        { font-size: 11px; color: var(--text2); font-family: 'IBM Plex Mono', monospace; margin-top: 1px; }
.login-title    { font-size: 20px; font-weight: 700; letter-spacing: -.02em; margin-bottom: 6px; }
.login-subtitle { font-size: 13px; color: var(--text2); margin-bottom: 28px; }
.login-field    { margin-bottom: 16px; }
.login-field:last-of-type { margin-bottom: 24px; }
.login-field label {
  display: block; font-size: 12px; font-weight: 500; color: var(--text2);
  margin-bottom: 6px; letter-spacing: .02em; text-transform: uppercase;
}
.login-field input[type="email"],
.login-field input[type="password"] {
  width: 100%; background: var(--surface2); border: 1px solid var(--border);
  border-radius: var(--r); padding: 9px 12px;
  font-family: 'IBM Plex Sans', sans-serif; font-size: 14px;
  color: var(--text); outline: none; transition: border-color .15s;
}
.login-field input::placeholder { color: var(--text3); }
.login-field input:focus        { border-color: var(--accent); }
.login-error    { background: var(--bg-incompleto); border: 1px solid color-mix(in srgb, var(--danger) 35%, transparent); border-radius: var(--r); color: var(--danger); font-size: 13px; padding: 10px 14px; margin-bottom: 20px; }
.login-ok       { background: var(--bg-entregado);  border: 1px solid color-mix(in srgb, var(--ok) 35%, transparent);     border-radius: var(--r); color: var(--ok);     font-size: 13px; padding: 10px 14px; margin-bottom: 20px; }
.login-submit   { width: 100%; min-height: 40px; font-size: 14px; }


/* ── 18. FORMULARIO DE PAGO (ventas) ─────────────────────────── */
.pago-section             { display: flex; flex-direction: column; gap: 10px; }
.pago-section-title       { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: var(--text3); display: flex; align-items: center; gap: 8px; }
.pago-section-title::after { content: ''; flex: 1; height: 1px; background: var(--border); }
.pago-row             { display: flex; align-items: center; gap: 10px; padding: 8px 0; }
.pago-row + .pago-row { border-top: 1px solid var(--border); }
.pago-metodo          { font-size: 12px; font-weight: 600; color: var(--text); min-width: 120px; flex: 1; }
.pago-fecha           { font-size: 11px; color: var(--text3); }
.pago-monto           { font-family: 'IBM Plex Mono', monospace; font-size: 13px; color: var(--text); margin-left: auto; }
.pago-comp            { font-size: 11px; color: var(--accent-ink); text-decoration: none; cursor: zoom-in; }
.pago-comp:hover      { text-decoration: underline; }
/* El archivo se eliminó a los 90 días: texto apagado donde estaba el enlace. */
.archivo-eliminado    { font-size: 11px; color: var(--text3); }
/* Visor del comprobante (shared.js): flota sobre cualquier modal o panel, por
   eso el z-index queda arriba de .missing-overlay (300) y debajo del toast. */
.comp-visor           { display: none; position: fixed; inset: 0; z-index: 400; background: #05070bcc; backdrop-filter: blur(5px); align-items: center; justify-content: center; padding: 24px; }
.comp-visor.open      { display: flex; }
.comp-visor-card      { width: min(760px, 100%); max-height: calc(100vh - 48px); animation: dmIn .22s cubic-bezier(.4,0,.2,1); }
.comp-visor-body      { display: flex; align-items: center; justify-content: center; }
.comp-visor-img       { max-width: 100%; max-height: calc(100vh - 160px); object-fit: contain; border-radius: var(--r-sm); }
.comp-visor-frame     { width: 100%; height: calc(100vh - 180px); border: none; border-radius: var(--r-sm); background: var(--surface2); }
.comp-visor-error     { font-size: 13px; color: var(--text3); padding: 32px 0; }
@media (max-width: 600px) {
  .comp-visor       { padding: 0; }
  .comp-visor-card      { width: min(760px, 100%); max-height: calc(100vh - 48px); animation: dmIn .22s cubic-bezier(.4,0,.2,1); }
  .comp-visor-img   { max-height: calc(100dvh - 110px); }
  .comp-visor-frame { height: calc(100dvh - 110px); }
}
/* Card view for read-only pago detail */
.pago-view-card           { background: var(--surface); border: 1px solid var(--border2); border-radius: var(--r); padding: 14px 16px; display: flex; align-items: center; gap: 12px; }
.pago-view-card + .pago-view-card { margin-top: 6px; }
.pago-view-card .pago-metodo  { font-size: 15px; }
.pago-view-card .pago-monto   { font-size: 15px; }
/* Detalle (read-only) pago: split tarjeta(s) + conciliación */
.psec-head                { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.psec-head .psec-title    { margin-bottom: 0; }
.pago-split               { display: flex; flex-direction: column; }
.pago-cards               { display: flex; flex-direction: column; gap: 6px; }
.pago-view-card--detail   { align-items: flex-start; flex-wrap: wrap; }
.pago-card-main           { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; flex: 1; min-width: 0; }
.pago-card-side           { display: flex; flex-direction: column; align-items: flex-end; gap: 3px; flex-shrink: 0; }
.pago-view-card--detail .pago-monto { margin-left: 0; }
.pago-concil              { display: flex; flex-direction: column; border-top: 1px solid var(--border); padding-top: 16px; margin-top: 16px; }
.concil-row               { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; padding: 7px 0; }
.concil-lbl               { font-size: 14px; color: var(--text2); }
.concil-val               { font-family: 'IBM Plex Mono', monospace; font-size: 14px; color: var(--text); white-space: nowrap; }
.concil-row--total        { border-bottom: 1px solid var(--border); padding-bottom: 11px; margin-bottom: 3px; }
.concil-row--total .concil-lbl,
.concil-row--total .concil-val,
.concil-row--diff .concil-lbl,
.concil-row--diff .concil-val { font-weight: 700; color: var(--text); }
.concil-extra             { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--border); display: flex; flex-direction: column; gap: 10px; }
/* Conciliación editable: input para Valor envío */
.concil-row--edit         { align-items: center; }
.concil-input             { width: 150px; max-width: 50%; text-align: right; background: var(--surface2); border: 1px solid var(--border2); border-radius: var(--r); padding: 7px 10px; font-family: 'IBM Plex Mono', monospace; font-size: 14px; color: var(--text); outline: none; transition: border-color .15s; }
.concil-input:focus       { border-color: var(--accent); }
/* Tarjeta de pago editable (modo edición) — espeja el estilo de .pago-view-card */
.pago-edit-card           { background: var(--surface); border: 1px solid var(--border2); border-radius: var(--r); padding: 14px 16px; display: flex; flex-direction: column; gap: 10px; }
.pago-edit-card + .pago-edit-card { margin-top: 6px; }
.pago-edit-card--locked   { opacity: .85; }
.pago-edit-head           { display: flex; align-items: center; gap: 8px; min-height: 24px; }
.pago-edit-rm             { margin-left: auto; }
.pago-edit-inputs         { display: flex; align-items: center; gap: 10px; }
.pago-edit-inputs select  { flex: 1; min-width: 0; background: var(--surface2); border: 1px solid var(--border2); border-radius: var(--r); padding: 8px 10px; font-size: 13px; color: var(--text); outline: none; color-scheme: inherit; cursor: pointer; transition: border-color .15s; }
.pago-edit-inputs select option { background: var(--surface2); }
.pago-edit-inputs select:focus { border-color: var(--accent); }
.pago-edit-inputs input[type=number] { flex: 1; min-width: 0; background: var(--surface2); border: 1px solid var(--border2); border-radius: var(--r); padding: 8px 10px; font-size: 13px; color: var(--text); outline: none; font-family: 'IBM Plex Sans', sans-serif; transition: border-color .15s; }
.pago-edit-inputs input[type=number]:focus { border-color: var(--accent); }
.pago-edit-inputs select:disabled,
.pago-edit-inputs input:disabled { opacity: .6; cursor: not-allowed; }
.pago-edit-foot           { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.pago-edit-fecha          { display: flex; align-items: center; gap: 6px; }
.pago-edit-fecha label    { font-size: 11px; color: var(--text3); white-space: nowrap; margin: 0; }
.pago-edit-fecha input[type=date] { font-size: 12px; border: 1px solid var(--border); border-radius: var(--r-xs); padding: 2px 6px; background: transparent; color: var(--text); max-width: 160px; }
.pago-edit-comp           { margin-left: auto; }
.info-stat            { font-size: 22px; font-weight: 700; margin-top: 4px; color: var(--text); }
.pago-row-card            { background: var(--surface); border: 1px solid var(--border2); border-radius: var(--r); padding: 10px 12px; display: flex; flex-direction: column; gap: 8px; }
.pago-row-card + .pago-row-card { margin-top: 6px; }
.pago-row-inputs          { display: flex; align-items: center; gap: 8px; }
.pago-row-inputs select   { flex: 1; min-width: 0; background: var(--surface2); border: 1px solid var(--border2); border-radius: var(--r); padding: 8px 10px; font-size: 13px; color: var(--text); outline: none; color-scheme: inherit; cursor: pointer; transition: border-color .15s; }
.pago-row-inputs select option { background: var(--surface2); }
.pago-row-inputs select:focus { border-color: var(--accent); }
.pago-row-inputs input[type=number] { width: 140px; flex-shrink: 0; background: var(--surface2); border: 1px solid var(--border2); border-radius: var(--r); padding: 8px 10px; font-size: 13px; color: var(--text); outline: none; font-family: 'IBM Plex Sans', sans-serif; transition: border-color .15s; }
.pago-row-inputs input[type=number]:focus { border-color: var(--accent); }
.pago-add-btn             { width: 100%; margin-top: 4px; }
.pago-field-group         { border: 1px solid var(--border2); border-radius: var(--r); padding: 12px 14px; background: var(--surface2); }

/* Cobro en etiqueta */
.cobrar-etiqueta-toggle   { display: flex; align-items: center; gap: 10px; cursor: pointer; margin: 0; }
.cobrar-etiqueta-toggle input[type=checkbox] { width: 16px; height: 16px; accent-color: var(--accent); cursor: pointer; flex-shrink: 0; }
.cobrar-etiqueta-toggle span { font-size: 13px; font-weight: 500; color: var(--text); }
.cobrar-etiqueta-monto    { display: flex; align-items: flex-end; gap: 8px; padding-top: 10px; margin-top: 10px; border-top: 1px solid var(--border); }
.cobrar-etiqueta-extra    { padding-top: 10px; margin-top: 10px; border-top: 1px solid var(--border); }


/* ── 19. RESPONSIVE ───────────────────────────────────────────── */
@media (max-width: 600px) {
  /* iOS hace zoom al enfocar un input con font-size < 16px. Todo ya está
     escalado, así que forzamos 16px en los controles para inhibir ese zoom. */
  input, select, textarea { font-size: 16px !important; }

  /* El shell se mide contra el viewport DINÁMICO. Con 100vh el navegador móvil
     reserva el alto SIN sus barras, así que la franja inferior del layout queda
     detrás de la barra de direcciones — y como el body no scrollea, lo que vive
     ahí (la actionbar "Poner en camino" de Domicilios, la paginación) no se
     alcanza nunca. Con 100dvh el alto sigue a la barra del navegador. */
  body.app-layout,
  .main-layout,
  .main-area    { height: 100dvh; }

  /* Objetivos táctiles: los botones de escritorio miden ~31px de alto. */
  .btn          { min-height: 40px; padding: 0 14px; }
  .btn-icon     { width: 40px; padding: 0; }
  .btn-sm       { min-height: 36px; padding: 0 12px; }
  .btn-icon.btn-sm { width: 36px; padding: 0; }
  .btn-text     { min-height: 36px; }

  /* Topbar: sin la hamburguesa, el título arranca en el mismo borde que las
     pills y la barra de la tabla. */
  .topbar       { padding: 0 var(--float-inset); gap: 8px; }
  /* El título cede el ancho y termina en «…»; las acciones no se encogen. */
  .topbar-left  { flex: 1 1 auto; min-width: 0; }
  .topbar-title { display: block; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .topbar-title svg { vertical-align: -3px; margin-right: 8px; }
  .topbar-right { flex-shrink: 0; position: relative; }

  /* Acciones del topbar (components/topbar.html): [⋯] [＋]. El principal, o
     la acción única, se queda en solo ícono (su texto va en .btn-label y el
     nombre en aria-label). */
  .topbar-right > .btn:has(> .btn-label) { width: 40px; padding: 0; }
  .topbar-right > .btn > .btn-label      { display: none; }

  .topbar-more                     { display: block; }
  .topbar-more > .topbar-more-btn  { display: inline-flex; position: relative; }
  /* Sin nada visible dentro (todo con display:none en línea), no hay ⋯. */
  .topbar-more:not(:has(.topbar-more-menu .btn:not([style*="none"]))) { display: none; }
  /* Una opción con algo esperando (Despacho masivo) marca el ⋯. */
  .topbar-more:has(.topbar-more-senal:not([style*="none"])) > .topbar-more-btn::after {
    content: ''; position: absolute; top: 6px; right: 6px; width: 7px; height: 7px;
    border-radius: 50%; corner-shape: round; background: var(--accent);
  }
  /* Popover: la misma pieza que la tarjeta de usuario, anclado bajo las
     acciones y alineado al borde derecho. Bajo los velos (200). */
  .topbar-more-menu {
    display: none; position: absolute; top: calc(100% + 6px); right: 0; z-index: 150;
    flex-direction: column; gap: 1px;
    min-width: 232px; max-width: calc(100vw - 2 * var(--float-inset)); padding: 6px;
    background: var(--surface); border: 1px solid var(--border2);
    border-radius: var(--r-md); box-shadow: var(--shadow-overlay);
  }
  .topbar-more.open .topbar-more-menu { display: flex; animation: fadeInMenuUp .14s ease; }
  /* Cada botón, fila de menú: se ajusta con las variables de .btn. */
  .topbar-more-menu .btn {
    --b-bg: transparent; --b-border: transparent; --b-shadow: none; --b-fg: var(--text2);
    --b-bg-h: var(--hover); --b-border-h: transparent; --b-fg-h: var(--text);
    justify-content: flex-start; gap: 9px; width: 100%; min-height: 44px; padding: 0 8px;
    border-radius: calc(var(--r-md) - 6px);
  }
  /* Acción + su dato (hora de la última carga): el dato, segunda línea. */
  .topbar-more-item                { display: flex; flex-direction: column; }
  .topbar-more-item > :is(:not(.btn), .topbar-more-dato) { order: 1; margin-top: -8px; padding: 0 8px 8px 30px; }
  /* El dato puede ser a su vez un botón (la hora abre el resumen de la carga):
     sigue siendo segunda línea, no otra fila de menú. */
  .topbar-more-menu .btn.topbar-more-dato { min-height: 0; width: auto; align-self: flex-start;
    --b-bg-h: transparent; }
  .topbar-more-menu .topbar-more-sep { display: block; width: auto; height: 1px; margin: 5px 4px; background: var(--border); align-self: stretch; }

  /* Botón del menú: flota abajo a la izquierda, par de la paginación (abajo a
     la derecha): mismo alto, misma línea base, misma superficie. Queda debajo
     de todo velo (el más bajo, .panel-backdrop, es 100) y del drawer, que lo
     tapa al abrirse; se cierra tocando el velo, con Esc o al navegar. */
  .nav-toggle   { display: inline-flex; position: fixed; left: var(--float-inset); bottom: var(--float-bottom); z-index: 90; }
  /* A 40px de alto, 4px de padding dejaría los chevrons en 30: con 2 quedan
     en 34, y el radio de la barra se queda a 2px del de los botones. */
  :root         { --float-pad: 2px; }

  /* Pantallas sin tabla de módulo: aire al pie para que el botón no tape lo
     último. Las tablas ya lo tienen (--tabla-fade). */
  .main-content:not(:has(.module-card > .card-scroll)) { padding-bottom: calc(var(--float-h) + 2 * var(--float-inset)); }

  /* Sidebar como drawer deslizable (se abre con la hamburguesa) */
  .sidebar             { position: fixed; top: 0; left: 0; z-index: 200; width: min(84vw, 300px); height: 100dvh; transform: translateX(-100%); transition: transform .25s cubic-bezier(.4,0,.2,1); box-shadow: var(--shadow-overlay); }
  /* Áreas seguras: el drawer va de borde a borde, así que arriba deja la
     barra de estado y abajo el indicador de inicio (y las esquinas
     redondeadas), donde quedaba el selector de cuenta. */
  .sidebar             { padding-top: env(safe-area-inset-top, 0px); }
  .sidebar-footer      { padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px)); }
  /* Los velos también van de borde a borde: su contenido arranca bajo la
     barra de estado. */
  .overlay, .missing-overlay { padding-top: calc(16px + env(safe-area-inset-top, 0px)); }
  .v-overlay                 { padding-top: calc(32px + env(safe-area-inset-top, 0px)); }
  .sidebar.mobile-open { transform: translateX(0); }
  /* En móvil el drawer siempre se muestra expandido (ignora el modo colapsado) */
  .sidebar.collapsed                     { width: min(84vw, 300px); }
  .sidebar.collapsed .sidebar-header     { padding: 12px 13px; justify-content: flex-start; }
  .sidebar.collapsed .sidebar-brand-wrap { display: block; }
  .sidebar.collapsed .nav-label          { opacity: 1; max-width: none; pointer-events: auto; }
  .sidebar.collapsed .sidebar-item       { justify-content: flex-start; padding: 7px 12px; margin: 1px 8px; width: calc(100% - 16px); gap: 9px; }
  .sidebar.collapsed .nav-group-head     { margin: 1px 8px; }
  .sidebar.collapsed .nav-group-link     { justify-content: flex-start; padding: 7px 12px; gap: 9px; }
  .sidebar.collapsed .nav-sub            { display: block; }
  .sidebar.collapsed .sidebar-footer     { padding: 8px 8px calc(8px + env(safe-area-inset-bottom, 0px)); }
  .sidebar.collapsed .sidebar-user       { justify-content: flex-start; padding: 7px 8px; gap: 9px; }
  .sidebar.collapsed .sidebar-user-meta,
  .sidebar.collapsed .sidebar-user-caret { opacity: 1; max-width: none; width: auto; pointer-events: auto; }

  /* Login */
  .login-card   { padding: 28px 16px; margin: 16px; max-width: calc(100% - 32px); }
  .login-field input[type="email"],
  .login-field input[type="password"] { font-size: 16px; padding: 11px 12px; }
  .login-submit { min-height: 46px; font-size: 15px; }

  /* Stats & tabla */
  .table-wrap   { padding: 0 0 60px; }
  td, th        { padding: 10px; }

  /* Vista card en vez de la tabla ancha (Pedidos). Selector con .card-scroll
     para ganar en especificidad a la regla base `.order-cards { display:none }`
     (que aparece más abajo en el archivo). */
  .card-scroll .table-wrap { display: none; }
  .card-scroll .order-cards { display: flex; flex-direction: column; gap: 10px; padding: 12px; }
  /* El organizador de columnas no aplica a la vista card */
  #colsBtn      { display: none; }

  /* Toolbar */
  .toolbar      { padding: 10px 14px; flex-wrap: wrap; gap: 8px; }
  .search-wrap  { max-width: none; }

  /* Tabs */
  .audit-tabs   { padding: 8px 14px; }

  /* Detail panel — min-width debe resetearse o sobrescribe el width */
  .detail-panel { width: 100vw; min-width: unset; }

  /* Step bar en modales */
  .step-bar     { padding: 0 14px; overflow-x: auto; }

  /* Formularios en modales: colapsar a 1 columna */
  .form-row     { grid-template-columns: 1fr; }
  .form-row-3   { grid-template-columns: 1fr; }

  /* Filter panel */
  .filter-panel { width: 290px; }

  /* Paginación: los chevrons medían ~24px de alto, la mitad del mínimo táctil.
     Es el control que más se pulsa en móvil (listas de 50 en 50). */
  .pg-btn      { min-width: 40px; min-height: 40px; font-size: 16px; padding: 0 12px; }
  .pg-size-sel { min-height: 40px; }
  .pagination-bar { gap: 10px; }
}


/* ── PAGINATION BAR ──────────────────────────────────────────── */
.pagination-bar          { display: none; padding: 8px 20px; align-items: center; gap: 12px; border-top: 1px solid var(--border); background: var(--surface); flex-wrap: wrap; position: sticky; bottom: 0; z-index: 20; }
.pagination-bar.visible  { display: flex; }
.pg-info                 { font-size: 12px; color: var(--text3); }
.pg-controls             { margin-left: auto; display: flex; align-items: center; gap: 8px; }
.pg-label                { font-size: 11px; color: var(--text3); }
.pg-size-sel             { background: var(--surface2); border: 1px solid var(--border); border-radius: var(--r); padding: 5px 8px; font-size: 12px; color: var(--text); outline: none; cursor: pointer; font-family: 'IBM Plex Sans', sans-serif; }
.pg-size-sel option      { background: var(--surface2); }
.pg-btn                  { background: var(--surface2); border: 1px solid var(--border); border-radius: var(--r); padding: 5px 10px; font-size: 13px; color: var(--text); cursor: pointer; line-height: 1; font-family: 'IBM Plex Sans', sans-serif; transition: border-color .15s; }
.pg-btn:hover:not(:disabled) { border-color: var(--border-strong); }
.pg-btn:disabled         { opacity: 0.35; cursor: not-allowed; }
.pg-num                  { font-size: 12px; color: var(--text2); white-space: nowrap; }

/* ── SORT INDICATORS ────────────────────────────────────────────── */
thead th.th-sort              { cursor: pointer; }
thead th.th-sort::after       { content: ' \21C5'; opacity: .3; font-size: 10px; }
thead th.th-sort--asc::after  { content: ' \2191'; opacity: .85; }
thead th.th-sort--desc::after { content: ' \2193'; opacity: .85; }

/* ── VISTA CARD (móvil, estilo Shopify) ─────────────────────────────
   Oculta en escritorio; el @media móvil oculta la tabla y muestra esto. */
.order-cards       { display: none; }
.order-card        { display: flex; flex-direction: column; gap: 8px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md); padding: 13px 14px; cursor: pointer; transition: border-color .15s; }
.order-card:active { border-color: var(--border-strong); }
/* Tarjeta de una fila que no abre nada (Facturas): sin mano ni reacción al toque. */
.order-card--static        { cursor: default; }
.order-card--static:active { border-color: var(--border); }
.order-card.row-modified { box-shadow: inset 3px 0 0 var(--c-incompleto); }
.order-card.skel-card { pointer-events: none; cursor: default; }
.oc-top            { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.oc-id             { font-family: 'IBM Plex Mono', monospace; font-size: 13px; font-weight: 600; color: var(--text2); }
.oc-cliente        { font-size: 15px; font-weight: 600; letter-spacing: -.01em; color: var(--text); line-height: 1.2; }
.oc-tags           { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.oc-total          { font-family: 'IBM Plex Mono', monospace; font-size: 14px; font-weight: 700; color: var(--text); margin-right: 2px; }
.oc-meta           { font-size: 12px; color: var(--text3); line-height: 1.4; }
.oc-action         { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 2px; }
.oc-action:empty   { display: none; }


/* ── 20. SKELETON LOADING ────────────────────────────────────── */
@keyframes shimmer {
  from { background-position: -200% 0; }
  to   { background-position:  200% 0; }
}
.skel-row td {
  border-bottom: 1px solid var(--border);
  padding: 14px 16px;
  pointer-events: none;
}
.skel-line {
  display: block;
  height: 12px;
  border-radius: var(--r-xs);
  background: linear-gradient(
    90deg,
    var(--surface2) 25%,
    var(--border-strong)  50%,
    var(--surface2) 75%
  );
  background-size: 200% 100%;
  animation: shimmer 1.4s ease-in-out infinite;
}

/* Carga fallida de una tabla (`showTableError`, shared.js). Ocupa el sitio de
   las filas y se distingue del vacío: el vacío afirma que no hay datos, esto
   dice que no se pudieron traer y ofrece volver a pedirlos. */
.tbl-error-row td { border-bottom: 0; padding: 0; }
.tbl-error {
  display: flex; align-items: center; justify-content: center;
  flex-wrap: wrap; gap: 10px;
  padding: 36px 24px; text-align: center;
  color: var(--text2); font-size: 13px;
}

/* Pills fantasma: una .statsbar vacía está cargando. Cada módulo la llena de
   una vez con innerHTML y, cuando no le tocan pills, la esconde con
   display:none — así que :empty solo se ve mientras llegan los conteos.
   Seis siluetas con dos pseudos: cada uno se repite dos veces con box-shadow
   (que copia su forma redondeada), alternando anchos de 92 y 104px con el
   mismo gap de 8px de las pills reales. Alto = el de una .pill (29px). */
.statsbar:empty::before,
.statsbar:empty::after {
  content: ''; flex: 0 0 auto; height: 29px;
  border-radius: 99px; corner-shape: round;
  background: var(--surface2);
  animation: pillGhost 1.4s ease-in-out infinite;
}
.statsbar:empty::before { width: 92px;  box-shadow: 212px 0 0 var(--surface2), 424px 0 0 var(--surface2); }
.statsbar:empty::after  { width: 104px; box-shadow: 212px 0 0 var(--surface2), 424px 0 0 var(--surface2); }
@keyframes pillGhost { 50% { opacity: .45; } }
@media (prefers-reduced-motion: reduce) {
  .statsbar:empty::before, .statsbar:empty::after { animation: none; }
}


/* ── 20b. TOAST ──────────────────────────────────────────────────
   Definición ÚNICA. Antes vivía duplicada en cuatro sitios (shared.js con
   estilos inline en hex, más tres copias de CSS en plantillas de Configuración),
   así que el mismo aviso se veía distinto según el módulo y el de shared.js
   quedaba como mancha oscura en tema claro. Lo pinta `showToast()` (shared.js).

   La caja es `.app-toast`, NO `.toast`: ese nombre es de Bootstrap (base.html
   lo sigue cargando) y trae `.toast:not(.show){display:none}`, que gana por
   especificidad. El nuestro aparece con `.toast-show`, nunca con `.show`, así
   que mientras se llamó `.toast` no se pintó ninguno. Los modificadores
   (`toast-ok`, `toast-show`…) no chocan con nada y conservan el nombre.
   ─────────────────────────────────────────────────────────────── */
.app-toast {
  position: fixed; bottom: 24px; left: 50%; z-index: 9999;
  transform: translateX(-50%) translateY(10px);
  /* max-content: con `left: 50%` el ancho automático se encoge a media
     pantalla, y en un teléfono un aviso de una línea salía en dos. */
  width: max-content; max-width: min(520px, calc(100vw - 32px));
  padding: 10px 18px; border-radius: var(--r-sm);
  background: var(--surface); border: 1px solid var(--border2);
  font-family: 'IBM Plex Sans', sans-serif; font-size: 13px; font-weight: 500;
  color: var(--text); line-height: 1.45;
  box-shadow: var(--shadow-overlay);
  opacity: 0; pointer-events: none;
  transition: opacity .22s ease, transform .22s cubic-bezier(.4,0,.2,1);
}
.toast-show    { opacity: 1; transform: translateX(-50%) translateY(0); }
/* El color vive en el borde y en el texto; el fondo se queda en --surface2 para
   que un aviso largo siga siendo legible y no dependa de un tinte por estado. */
.toast-ok      { border-color: color-mix(in srgb, var(--ok) 45%, transparent);     color: var(--ok); }
.toast-warn    { border-color: color-mix(in srgb, var(--warn) 45%, transparent);   color: var(--warn); }
.toast-err,
.toast-danger  { border-color: color-mix(in srgb, var(--danger) 45%, transparent); color: var(--danger); }
.toast-info    { border-color: color-mix(in srgb, var(--accent) 45%, transparent); color: var(--accent-ink); }

@media (max-width: 600px) {
  /* Sobre la fila flotante del pie (menú + paginación), y sobre la barra de
     acción cuando la hay: --float-bottom ya incluye --float-lift. */
  .app-toast { bottom: calc(var(--float-bottom) + var(--float-h) + 16px); }
}


/* ── 21. UTILIDADES DE TEXTO ─────────────────────────────────── */
.text-ok        { color: var(--ok); }
.text-muted     { color: var(--text3); }
.text-secondary { color: var(--text2); }

/* Estado inline: "Esperando factura" y "Pedido entregado" */
.panel-status-wait { font-size: 11px; color: var(--text3); display: flex; align-items: center; gap: 5px; }
.panel-status-done { font-size: 11px; color: var(--ok);   display: flex; align-items: center; gap: 4px; }
.panel-status-wait.lg,
.panel-status-done.lg { font-size: 12px; margin-left: auto; gap: 6px; }

/* Columna OV en tabla */
.td-ov { font-family: 'IBM Plex Mono', monospace; font-size: 11px; color: var(--text3); padding: 8px 14px !important; }

/* Hint de modal de un solo uso */
.modal-hint { font-size: 12px; color: var(--text3); margin-bottom: 14px; }

/* Modal de empaque unificado: productos a la izquierda, responsables a la derecha.
   Fusiona los dos modales que había (separación + empaque). En móvil se apila con
   los productos primero, que es lo que el empacador mira antes de firmar.

   Mismo modal estándar (.mdl) que el resto: los botones flotan al pie, así que
   "Confirmar empaque" siempre queda a la vista aunque haya 52 productos. */
.step-modal--empaque              { width: min(1200px, 100%); max-height: calc(100vh - 64px); }
/* Los productos mandan: la columna derecha son controles de ancho fijo, así que
   todo el espacio extra del modal ancho se lo lleva la lista. Las columnas son
   `.dm-col` — el mismo contenedor del detalle del pedido. */
.empaque-cols        { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: 16px; align-items: start; }

/* La lista puede ser larga (se han visto pedidos de 52 líneas): con scroll propio,
   los controles de la derecha siguen a la vista. */
.empaque-lista  { max-height: 52vh; overflow-y: auto; overflow-x: hidden; }

/* Cantidad separada: ancho fijo para que quepa el input sin apretar la descripción. */
.empaque-table .col-sep  { width: 84px; text-align: right; }
.empaque-table .qty-input { width: 72px; }

@media (max-width: 980px) {
  .empaque-cols  { grid-template-columns: 1fr; }
  /* Apilado, la lista no compite con nada: que use el scroll del body. */
  .empaque-lista { max-height: none; overflow-y: visible; }
}

/* Resumen de disponibilidad: el estado por defecto es "todo disponible" (lo es el
   ~99% de las veces), así que se muestra como lectura y solo se vuelve editable
   al pedir reportar un faltante. */
.disp-qty       { font-family: 'IBM Plex Mono', monospace; font-weight: 600; color: var(--ok); white-space: nowrap; }
.disp-toggle    { margin-top: 10px; }
.disp-aviso     { font-size: 12px; color: var(--warn); margin-top: 10px; }


/* ── 22. STEP WIZARD HEADER ──────────────────────────────────── */
.step-wizard-header  { display: flex; gap: 8px; align-items: center; margin-bottom: 16px; }
.step-node           { width: 28px; height: 28px; border-radius: 50%; corner-shape: round; display: grid; place-items: center; flex-shrink: 0; font-size: 12px; font-weight: 700; }
.step-node--active   { background: var(--accent); color: #fff; }
.step-node--idle     { background: var(--border-strong); color: var(--text3); font-weight: 600; }
.step-label--active  { font-size: 13px; font-weight: 600; }
.step-label--idle    { font-size: 13px; color: var(--text3); }
.step-connector--done    { flex: 1; border-top: 2px solid var(--accent); margin: 0 8px; }
.step-connector--pending { flex: 1; border-top: 2px dashed var(--border); margin: 0 8px; }

/* Agente inline en panel header */
.panel-agente { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; color: var(--text3); margin-top: 0; background: var(--bg2); border: 1px solid var(--border); border-radius: var(--r-xs); padding: 2px 7px; width: fit-content; }

/* ── 23. PERSONA FIELD (reemplaza campos de firma) ───────────── */
.persona-field      { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; }
.persona-label      { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--text3); }
.persona-select,
.persona-input,
.persona-other      { width: 100%; padding: 8px 10px; border-radius: var(--r-sm); border: 1px solid var(--border); background: var(--bg2); color: var(--text1); font-size: 13px; outline: none; transition: border-color .15s; }
.persona-select:focus,
.persona-input:focus,
.persona-other:focus { border-color: var(--accent); }

/* ── 24. FACTURA BADGES ───────────────────────────────────────── */
.factura-badge           { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; border-radius: var(--r-xs); padding: 2px 6px; flex-shrink: 0; border: 1px solid transparent; }
.factura-badge--anulada  { color: var(--danger);  background: var(--bg-incompleto); border-color: #f8717155; }
.factura-badge--solicitud{ color: var(--warn);    background: var(--bg-espera);     border-color: #f5b94255; }
.factura-badge--principal{ color: var(--accent-ink);  background: var(--bg-accent-muted); }
.factura-badge--adicional{ color: var(--text3);   border-color: var(--border); font-weight: 600; }

.factura-item-row         { display: flex; justify-content: space-between; align-items: center; padding: 8px 10px; background: var(--surface2); border-radius: var(--r-sm); margin-bottom: 6px; gap: 12px; }
.factura-item-row--anulada{ opacity: 0.55; }
.factura-item-num         { font-family: 'IBM Plex Mono', monospace; font-size: 13px; font-weight: 600; color: var(--accent-ink); }
.factura-item-num--anulada{ color: var(--danger); text-decoration: line-through; }
.factura-item-total       { font-family: 'IBM Plex Mono', monospace; font-size: 12px; color: var(--text2); white-space: nowrap; }
.persona-other      { margin-top: 4px; }

/* ── DETAIL POPUP OVERLAY ─────────────────────────────────────── */
/* ── MODAL ESTÁNDAR (.mdl) ─────────────────────────────────────────
   Una sola estructura para todos los modales (catálogo y reglas en
   .docs/PATRONES-UI.md §Modales; comportamiento en static/js/modal.js):

     .mdl-bar     flota arriba. Sin fondo mientras se ve el bloque de título:
                  solo los botones compactos a la derecha (cerrar al final), a
                  un margen del borde. Al pasar el título (.is-scrolled) se
                  compacta, toma fondo y muestra .mdl-line, el resumen en una
                  línea.
     .mdl-scroll  lo único que hace scroll. Arranca en la fila de la barra, con
                  un solo margen arriba y a los lados; abajo deja el alto del pie.
     .mdl-hero    el bloque de título, primero en el contenido y en la fila de
                  los botones: deja libre su ancho (--mdl-actions-w).
     .mdl-foot    los botones sueltos sobre un difuminado al pie, como la
                  píldora de la tabla: la principal a la derecha, el resto a
                  la izquierda. No hay footer fijo.

   El fondo es --surface en todo el modal (en los dos temas es el mismo tono que
   --bg); las secciones se separan con su borde. */
.mdl {
  --mdl-pad: 24px;
  position: relative; display: flex; flex-direction: column; overflow: hidden;
  background: var(--surface); border: 1px solid var(--border2); border-radius: var(--r-lg);
  box-shadow: var(--shadow-overlay);
}
.mdl-bar {
  position: absolute; top: 0; left: 0; right: 0; z-index: 6;
  display: flex; align-items: center; gap: 12px;
  padding: 10px var(--mdl-pad);   /* mismo margen lateral que el contenido */
  border-bottom: 1px solid transparent;
  pointer-events: none;
  transition: background .15s, border-color .15s;
}
.mdl-bar > *        { pointer-events: auto; }
/* Sin scroll, los botones quedan a un margen del borde de arriba, igual que del
   de la derecha, y el título comparte fila con ellos. */
.mdl:not(.is-scrolled, .mdl--compact) > .mdl-bar { padding-top: var(--mdl-pad); padding-bottom: 0; }
.mdl-line           { flex: 1; min-width: 0; display: flex; align-items: center; overflow: hidden; white-space: nowrap;
                      font-size: 13px; font-weight: 500; color: var(--text);
                      opacity: 0; visibility: hidden; transition: opacity .15s, visibility .15s; }
.mdl-line-item      { display: inline-flex; align-items: center; gap: 6px; min-width: 0; flex-shrink: 0; }
.mdl-line-item:last-child { flex-shrink: 1; overflow: hidden; text-overflow: ellipsis; }
.mdl-line-item + .mdl-line-item::before { content: '·'; margin: 0 9px; color: var(--text3); }
.mdl-line-item--id  { font-family: 'IBM Plex Mono', monospace; font-weight: 600; color: var(--accent-ink); }
.mdl-line .badge    { font-size: 10.5px; }
.mdl-actions        { margin-left: auto; display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
/* Los botones de la barra van en tamaño compacto (.btn-sm, 28px) con íconos de
   14px, sin importar el tamaño con que venga el SVG en el marcado. */
.mdl-actions .btn            { min-height: 28px; padding: 0 10px; gap: 5px; font-size: 12px; }
.mdl-actions .btn-icon       { width: 28px; padding: 0; }
.mdl-actions .btn-icon svg   { width: 14px; height: 14px; }
.mdl.is-scrolled > .mdl-bar,
.mdl--compact > .mdl-bar { background: var(--surface); border-bottom-color: var(--border); }
.mdl.is-scrolled .mdl-line,
.mdl--compact .mdl-line { opacity: 1; visibility: visible; }

.mdl-scroll {
  flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  /* El título arranca en la fila de los botones, centrado con ellos (X de 28px
     → centro a pad+14; primera línea de ~25px → arranca a pad+2). */
  padding: calc(var(--mdl-pad) + 2px) var(--mdl-pad) calc(var(--mdl-foot-h, 0px) + 18px);
}
/* El compacto no tiene bloque de título: el contenido va bajo la barra. */
.mdl--compact > .mdl-scroll { padding-top: calc(var(--mdl-bar-h, 49px) + 4px); }

/* Bloque de título: lo que era el header. Deja libre el ancho de los botones. */
.mdl-hero           { min-width: 0; margin-bottom: 22px; padding-right: calc(var(--mdl-actions-w, 28px) + 12px); }
.mdl-kicker         { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 6px; min-height: 22px; }
.mdl-id             { font-family: 'IBM Plex Mono', monospace; font-size: 12.5px; font-weight: 600; color: var(--accent-ink); }
.mdl-title          { font-size: 21px; font-weight: 700; letter-spacing: -.02em; line-height: 1.2; color: var(--text); overflow-wrap: anywhere; }
.mdl-sub            { margin-top: 4px; font-size: 12.5px; color: var(--text2); }
.mdl-hero--avatar   { display: flex; align-items: center; gap: 14px; }
.mdl-hero-main      { flex: 1; min-width: 0; }

.mdl-foot {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 5;
  display: flex; align-items: center; gap: 8px; row-gap: 8px; flex-wrap: wrap;
  padding: 40px var(--mdl-pad) calc(16px + env(safe-area-inset-bottom, 0px));
  background: linear-gradient(to bottom, transparent, var(--surface) 55%);
  pointer-events: none;
}
.mdl-foot > *       { pointer-events: auto; }
/* La acción principal siempre abajo a la derecha y todo lo demás a la izquierda,
   sin importar el orden del marcado: el ::before es un separador elástico entre
   los dos grupos (le gana a cualquier margin:auto que traiga el JS). Si el pie no
   tiene .btn-primary, la principal es la de advertencia (Marcar que no entró,
   Reportar incompleto). */
.mdl-foot::before   { content: ''; order: 1; flex: 1 1 0; }
.mdl-foot > .btn-primary,
.mdl-foot:not(:has(> .btn-primary)) > .btn-danger { order: 2; }
/* El ⋯ de móvil (modal.js) vive siempre en el pie: no cuenta como contenido. */
.mdl-foot:not(:has(> :not(.mdl-foot-more))) { display: none; }
/* Un indicador vacío en el pie (estado de guardado, hint que aún no aplica) no
   ocupa hueco: sin esto, el gap corre el primer botón. */
.mdl-foot > :empty:not(.btn) { display: none; }

/* Pie que no cabe en móvil (modal.js · ajustarPie): la principal y la de
   advertencia se quedan; el resto de botones se pliega en un ⋯ a la izquierda
   que abre un menú hacia arriba. En escritorio el ⋯ no existe. */
.mdl-foot > .mdl-foot-more                   { display: none; }
.mdl-foot--plegado > .mdl-foot-more          { display: inline-flex; }
.mdl-foot--plegado > .btn:not(.btn-primary, .btn-danger, .mdl-foot-more) { display: none; }
.mdl-foot-menu {
  position: absolute; z-index: 30; display: none; flex-direction: column; gap: 1px;
  min-width: 220px; max-width: calc(100% - 2 * var(--mdl-pad, 16px)); padding: 6px;
  background: var(--surface); border: 1px solid var(--border2);
  border-radius: var(--r-md); box-shadow: var(--shadow-overlay);
}
.mdl-foot-menu.open { display: flex; animation: fadeInMenuUp .14s ease; }
/* Cada opción, fila de menú: se ajusta con las variables de .btn (igual que
   el menú ⋯ del topbar). */
.mdl-foot-menu .btn {
  --b-bg: transparent; --b-border: transparent; --b-shadow: none; --b-fg: var(--text2);
  --b-bg-h: var(--hover); --b-border-h: transparent; --b-fg-h: var(--text);
  justify-content: flex-start; gap: 9px; width: 100%; min-height: 44px; padding: 0 8px;
  border-radius: calc(var(--r-md) - 6px);
}

/* Barra de scroll persistente en el estándar (el de acción casi nunca hace
   scroll y el visor desplaza su propio documento). En macOS la barra nativa se
   esconde al dejar de desplazar; una ::-webkit-scrollbar con ancho propio es
   clásica y queda siempre visible (Chrome y Safari; Firefox sigue con la suya).
   overflow-y:scroll reserva la canaleta aunque no haya scroll, así el contenido
   no salta; el padding derecho le resta ese ancho para que el borde del
   contenido siga alineado con los botones de la barra. La barra de arriba y el
   pie dejan libre esa columna (right: --mdl-sb), así la pista ocupa todo el
   alto del modal sin quedar tapada; solo se aparta 8px de las esquinas
   redondeadas, que recortarían el pulgar. */
.mdl:not(.mdl--accion, .mdl--compact)                { --mdl-sb: 10px; }
.mdl:not(.mdl--accion, .mdl--compact) > .mdl-scroll {
  overflow-y: scroll;
  padding-right: calc(var(--mdl-pad) - var(--mdl-sb));
}
.mdl:not(.mdl--accion, .mdl--compact) > :is(.mdl-bar, .mdl-foot) {
  right: var(--mdl-sb);
  padding-right: calc(var(--mdl-pad) - var(--mdl-sb));
}
.mdl:not(.mdl--accion, .mdl--compact) > .mdl-scroll::-webkit-scrollbar       { width: var(--mdl-sb); }
.mdl:not(.mdl--accion, .mdl--compact) > .mdl-scroll::-webkit-scrollbar-track { background: transparent; margin: 8px 0; }
.mdl:not(.mdl--accion, .mdl--compact) > .mdl-scroll::-webkit-scrollbar-thumb { background: var(--border-strong); border: 2px solid transparent; border-radius: 99px; background-clip: padding-box; min-height: 32px; }
.mdl:not(.mdl--accion, .mdl--compact) > .mdl-scroll::-webkit-scrollbar-thumb:hover { background-color: var(--text3); }

/* ── Variante de acción (.mdl--accion) ──
   Para una sola interacción (separar, enviar, entregar, cambiar contraseña):
   el contenido cabe sin scroll y hay una acción principal. Mismo marcado que el
   estándar; cambia cómo se pinta:
     - el título sube a la fila de la X (la barra no reserva su alto);
     - el pie queda en el flujo, bajo el contenido, sin difuminado.
   Si en una pantalla baja el contenido sí hace scroll, la barra se comporta como
   la del estándar (toma fondo y muestra el resumen) en cuanto el contenido sube.
   Un solo ancho para todos: gana al del contenedor (.v-modal, .step-modal…). */
.mdl.mdl--accion            { width: 460px; max-width: 100%; }
/* Un solo margen en los cuatro lados (--mdl-pad): la X queda a la misma
   distancia del borde de arriba que del de la derecha, y el título centrado con
   ella (28px de X → centro a pad+14; título de 20px de alto → arranca a pad+4). */
.mdl--accion > .mdl-bar     { padding: var(--mdl-pad) var(--mdl-pad) 0; }
.mdl--accion > .mdl-scroll  { padding: calc(var(--mdl-pad) + 4px) var(--mdl-pad) 4px; }
.mdl--accion .mdl-hero      { margin-bottom: 18px; padding-right: 40px; }   /* libre el ancho de la X */
.mdl--accion .mdl-title     { font-size: 17px; letter-spacing: -.01em; }
.mdl--accion > .mdl-foot    { position: static; background: none; padding: 16px var(--mdl-pad) calc(var(--mdl-pad) + env(safe-area-inset-bottom, 0px)); }
/* Con scroll la barra toma fondo: vuelve al alto de la barra estándar. */
.mdl--accion.is-scrolled > .mdl-bar { padding: 10px var(--mdl-pad); }

@media (max-width: 600px) {
  .mdl              { --mdl-pad: 16px; }
  .mdl-title        { font-size: 18px; }
}

.detail-overlay                   { display: none; position: fixed; inset: 0; background: #05070bcc; backdrop-filter: blur(5px); z-index: 120; align-items: flex-start; justify-content: center; padding: 32px 24px; overflow-y: auto; }
.detail-overlay.open              { display: flex; }
.detail-modal                     { width: min(1200px, 100%); max-height: calc(100vh - 64px); animation: dmIn .22s cubic-bezier(.4,0,.2,1); }
@keyframes dmIn                   { from { opacity: 0; transform: scale(.97) translateY(12px); } to { opacity: 1; transform: scale(1) translateY(0); } }

/* Detalle a dos columnas: el bloque de título encabeza la izquierda y comparte
   fila con los botones, que quedan sobre la derecha; la derecha arranca a la
   altura del contenido de la izquierda. El JS de cada módulo
   rellena .dm-col-left/.dm-col-right enteras, por eso el título es su hermano y
   no su primer hijo. */
.dm-body                          { display: grid; grid-template-columns: 2.1fr 1fr; grid-template-areas: "hero ." "left right"; grid-template-rows: auto 1fr;
                                    column-gap: 16px; row-gap: 16px; align-content: start; }
.dm-body > .mdl-hero              { grid-area: hero; margin-bottom: 6px; padding-right: 0; }   /* + row-gap 16 = 22, igual que fuera de la cuadrícula; los botones van sobre la otra columna */
.dm-col-left                      { grid-area: left; }
.dm-col-right                     { grid-area: right; }
.dm-body--single                  { grid-template-columns: 1fr; grid-template-areas: "hero" "left"; }
.dm-col                           { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.dm-col .psec                     { border-bottom: none; border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface); }
/* Columna plana (detalle de Pedidos, derecha): las secciones van sobre el fondo,
   sin tarjeta; las separa su subtítulo, el aire y un separador tenue (el borde
   al 55%, más suave que el de las tarjetas de al lado). */
.dm-col--plano                    { gap: 0; }
.dm-col.dm-col--plano .psec       { border: none; border-radius: 0; background: none; padding: 0; }
/* Sin tarjeta que la contenga, la columna plana se separa de la otra con aire. */
.dm-body:has(> .dm-col--plano)    { column-gap: 40px; }
.dm-col.dm-col--plano .psec + .psec { margin-top: 22px; padding-top: 22px; border-top: 1px solid color-mix(in srgb, var(--border) 55%, transparent); }
@media (max-width: 900px) {
  /* Una columna: título, luego lo que se lee primero (derecha), luego el resto. */
  .dm-body                        { grid-template-columns: 1fr; grid-template-areas: "hero" "right" "left"; grid-template-rows: auto; }
  .dm-body > .mdl-hero            { padding-right: calc(var(--mdl-actions-w, 28px) + 12px); }
  /* Cuando lo que se lee primero está a la izquierda (la ficha de Productos:
     la gráfica antes que las cifras), la izquierda va arriba. */
  .dm-body.dm-body--izq-primero   { grid-template-areas: "hero" "left" "right"; }
}
@media (max-width: 600px) {
  /* A pantalla completa, bajo la barra de estado (ver §Áreas seguras). */
  .detail-overlay  { padding: env(safe-area-inset-top, 0px) 0 0; }
  .detail-modal    { max-height: calc(100dvh - env(safe-area-inset-top, 0px)); height: calc(100dvh - env(safe-area-inset-top, 0px)); border-radius: 0; border: none; width: 100vw; }
  .dm-body         { column-gap: 12px; row-gap: 12px; }
}

/* ── DM OTROS DROPDOWN ───────────────────────────────────────── */
.dm-otros-wrap                    { position: relative; }
.dm-otros-menu                    { position: absolute; top: calc(100% + 6px); right: 0; background: var(--surface); border: 1px solid var(--border2); border-radius: var(--r-md); box-shadow: var(--shadow-overlay); min-width: 190px; z-index: 30; display: none; padding: 4px; }
.dm-otros-menu.open               { display: block; }
.dm-otros-item                    { padding: 9px 12px; font-size: 13px; color: var(--text); cursor: pointer; display: flex; align-items: center; gap: 10px; border-radius: var(--r-sm); transition: background .1s; }
.dm-otros-item:hover              { background: var(--hover); }
.dm-otros-item.danger             { color: var(--danger); }
.dm-otros-item.danger:hover       { background: #2a1010; }
.dm-otros-empty                   { padding: 10px 12px; font-size: 12px; color: var(--text3); }

/* ── DM EDIT MODE ────────────────────────────────────────────── */
.edit-input                       { width: 100%; background: var(--surface2); border: 1px solid var(--border); border-radius: var(--r-sm); padding: 7px 10px; font-size: 13px; color: var(--text); outline: none; font-family: inherit; transition: border-color .15s; box-sizing: border-box; }
.edit-input:focus                 { border-color: var(--accent); }
textarea.edit-input               { resize: vertical; min-height: 60px; }
select.edit-input                 { cursor: pointer; }
.inline-pagos-section             { display: flex; flex-direction: column; gap: 8px; }
.inline-pago-add                  { margin-top: 4px; }

/* ── DM LABEL WARNING OVERLAY ────────────────────────────────── */
.dm-warning                       { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; background: #05070be6; backdrop-filter: blur(6px); z-index: 25; border-radius: var(--r-lg); padding: 24px; }
.dm-warning-box                   { background: var(--surface); border: 1px solid #a1620844; border-radius: var(--r-lg); padding: 28px 32px; max-width: 400px; width: 100%; text-align: center; display: flex; flex-direction: column; align-items: center; gap: 14px; box-shadow: var(--shadow-overlay); }
.dm-warning-icon                  { width: 52px; height: 52px; border-radius: 50%; corner-shape: round; background: #2a1c0a; color: var(--warn); display: grid; place-items: center; }
.dm-warning-title                 { font-size: 16px; font-weight: 700; color: var(--text); line-height: 1.35; }
.dm-warning-desc                  { font-size: 13px; color: var(--text2); line-height: 1.55; }
.dm-warning-timer                 { font-family: 'IBM Plex Mono', monospace; font-size: 32px; font-weight: 700; color: var(--warn); line-height: 1; min-height: 38px; }
.dm-warning-actions               { display: flex; gap: 8px; width: 100%; margin-top: 4px; }

/* Variante destructiva del mismo aviso (anular / eliminar): el ámbar de la
   advertencia pasa a rojo, que es lo que ya significa "esto no se deshace". */
.dm-warning--danger .dm-warning-box  { border-color: #f8717144; }
.dm-warning--danger .dm-warning-icon { background: var(--bg-incompleto); color: var(--c-incompleto); }
.dm-warning-field                 { width: 100%; text-align: left; display: flex; flex-direction: column; gap: 6px; }
.dm-warning-field > span          { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .07em; color: var(--text3); }
.dm-warning-field textarea        { width: 100%; resize: vertical; background: var(--surface2); border: 1px solid var(--border); border-radius: var(--r-sm); padding: 8px 10px; color: var(--text); font-family: 'IBM Plex Sans', sans-serif; font-size: 13px; line-height: 1.5; }
.dm-warning-field textarea:focus  { outline: none; border-color: var(--accent); }


/* ── 25. AJUSTES DE TEMA CLARO ────────────────────────────────────
   Componentes que codifican un hex oscuro directo (no token) y que en
   claro romperían contraste o se verían como una mancha oscura.
   ─────────────────────────────────────────────────────────────── */
:root[data-theme="light"] .dm-otros-item.danger:hover { background: var(--bg-incompleto); }
:root[data-theme="light"] .dm-warning-icon    { background: #f7e9cc; }
:root[data-theme="light"] .dm-warning--danger .dm-warning-icon { background: var(--bg-incompleto); }
/* Glow del live-dot: en claro un halo verde sobre blanco se pierde */
:root[data-theme="light"] .live-dot           { box-shadow: 0 0 6px #1c8a4d66; }


/* ── 25b. MODAL DE AJUSTES (configuración del usuario) ────────────
   Reusa .overlay (backdrop) + .v-modal (chrome: surface2, borde,
   radio, sombra, animación mIn). Layout propio de dos columnas:
   nav de secciones + panel de contenido.
   ─────────────────────────────────────────────────────────────── */
.set-modal        { width: 720px; max-width: 100%; }

/* Cabecera: título + buscador (deshabilitado) + cerrar */
.set-head         { display: flex; align-items: center; gap: 12px; min-height: 59px; padding: 12px 12px 12px 24px; border-bottom: 1px solid var(--border); } /* = .mdl-bar compacta */
.set-title        { font-size: 16px; font-weight: 700; letter-spacing: -.02em; color: var(--text); margin: 0; flex-shrink: 0; }
.set-search       { display: flex; align-items: center; gap: 8px; min-width: 0; width: 280px; margin-left: auto; padding: 7px 11px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-sm); color: var(--text3); opacity: .5; cursor: not-allowed; }
.set-search svg   { flex-shrink: 0; }
.set-search input { flex: 1; min-width: 0; background: none; border: none; outline: none; color: var(--text3); font-family: inherit; font-size: 13px; cursor: not-allowed; pointer-events: none; }

/* Cuerpo: nav + contenido */
.set-body         { display: grid; grid-template-columns: 184px 1fr; }
.set-nav          { display: flex; flex-direction: column; gap: 2px; padding: 14px 12px; border-right: 1px solid var(--border); background: var(--surface); }
.set-nav-item     { display: flex; align-items: center; gap: 9px; padding: 8px 10px; border: none; border-radius: var(--r-sm); background: transparent; color: var(--text2); font-family: inherit; font-size: 13px; font-weight: 500; text-align: left; cursor: pointer; transition: background .12s, color .12s; }
.set-nav-item svg { flex-shrink: 0; color: var(--text3); transition: color .12s; }
.set-nav-item:hover     { background: var(--hover); color: var(--text); }
.set-nav-item:hover svg { color: var(--text2); }
.set-nav-item.active     { background: var(--bg-accent-muted); color: var(--text); box-shadow: inset 0 0 0 1px #9b26b655; }
.set-nav-item.active svg { color: var(--accent); }

.set-content      { padding: 22px 24px 24px; overflow-y: auto; max-height: min(78vh, 640px); }
.set-panel-title  { font-size: 15px; font-weight: 700; letter-spacing: -.01em; color: var(--text); margin: 0 0 16px; }

/* Filas de datos (tarjeta con divisores tonales) */
.set-fields       { display: grid; gap: 1px; background: var(--border); border: 1px solid var(--border); border-radius: var(--r-md); overflow: hidden; margin-bottom: 18px; }
.set-fields-2     { grid-template-columns: 1fr 1fr; }
.set-field        { display: flex; flex-direction: column; gap: 5px; padding: 12px 14px; background: var(--surface); min-width: 0; }
.set-label        { font-size: 10.5px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--text3); }
.set-val          { font-size: 13.5px; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.set-val.mono     { font-size: 13px; }
.set-val-muted    { color: var(--text3); }
.set-secret       { display: flex; align-items: center; gap: 8px; min-width: 0; }
.set-secret .set-val { flex: 1; min-width: 0; }
.set-reveal       { flex-shrink: 0; background: none; border: none; color: var(--text3); cursor: pointer; padding: 3px; border-radius: var(--r-xs); display: flex; transition: color .12s; }
.set-reveal:hover { color: var(--text); }

/* Bloques apilados (contraseña / tema / apariencia) */
.set-block        { display: flex; flex-direction: column; gap: 10px; padding: 16px 0; border-top: 1px solid var(--border); }
.set-pass-row     { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.set-link         { display: inline-flex; align-items: center; gap: 5px; font-size: 13px; color: var(--accent-ink); text-decoration: none; font-weight: 500; }
.set-link:hover   { text-decoration: underline; }
.set-block .theme-seg { margin: 0; max-width: 300px; }

/* Segmentado de apariencia (mismo lenguaje que .theme-seg; activo vía dot) */
.seg-pair         { display: inline-flex; gap: 3px; padding: 3px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-sm); max-width: 300px; }
.seg-btn          { flex: 1; display: flex; align-items: center; justify-content: center; gap: 7px; padding: 7px 12px; border: none; background: transparent; color: var(--text3); font-family: inherit; font-size: 12.5px; font-weight: 500; border-radius: var(--r-sm); cursor: pointer; transition: background .15s, color .15s; }
.seg-btn:hover    { color: var(--text2); }
.seg-btn:has(.ctrl-menu-dot.active) { background: var(--active); color: var(--text); box-shadow: inset 0 0 0 1px var(--border); }

/* (El anillo de foco de estos controles ya no vive aquí: lo da el sistema
   global de §27, que cubre todo botón y enlace de la app.) */

@media (max-width: 640px) {
  .set-body     { grid-template-columns: 1fr; }
  .set-nav      { flex-direction: row; border-right: none; border-bottom: 1px solid var(--border); overflow-x: auto; }
  .set-fields-2 { grid-template-columns: 1fr; }
  .set-search   { display: none; }
}

/* ── 26. MOVIMIENTO REDUCIDO ──────────────────────────────────────
   Respeta a quien pide menos animación: sin slides, sin shimmer, sin
   pulse. Todo pasa a transición instantánea / estática.
   ─────────────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}


/* ── 27. FOCO DE TECLADO (sistémico) ──────────────────────────────
   Una sola regla para toda la app, y la última del archivo a propósito: varios
   componentes declaran `outline: none` en su regla base, y a igual especificidad
   gana quien va después.

   `:focus-visible` y no `:focus`: el anillo aparece al navegar con teclado y no
   al hacer clic con el mouse.

   El anillo usa --accent-ink, no --accent: el acento pleno da 2.6:1 sobre
   --surface2 y WCAG 1.4.11 pide 3:1 para un indicador de foco. La tinta llega a
   5.6:1 y se lee igual en las tres capas de superficie.

   Los inputs de texto conservan su señal documentada — el borde cambia a acento,
   sin glow (DESIGN.md §Inputs). Esto cubre lo que hasta ahora no señalaba NADA
   al llegar por teclado: botones, enlaces, pills, checkboxes, selects, filas.
   ─────────────────────────────────────────────────────────────── */
/* El `:focus-visible` va repetido a propósito. Varias plantillas declaran
   `outline: none` en un `<style>` de extra_head, que carga después de este
   archivo; con una sola clase de especificidad ganarían ellas y el anillo no se
   pintaría. Repetir la pseudoclase sube a (0,2,0) sin acoplar la regla a ningún
   elemento — `:where()` mantiene en cero la parte del selector. */
:where(a[href], button, [role="button"], summary, [tabindex]:not([tabindex="-1"])):focus-visible:focus-visible,
:where(input[type="checkbox"], input[type="radio"], select):focus-visible:focus-visible {
  outline: 2px solid var(--accent-ink);
  outline-offset: 2px;
}

/* Piezas de borde a borde: el anillo va por dentro para no recortarse contra un
   contenedor con overflow (sidebar, header sticky de la tabla, paneles). */
.sidebar-item:focus-visible,
.nav-subitem:focus-visible,
.nav-group-link:focus-visible,
.sidebar-user:focus-visible,
.user-menu-item:focus-visible,
.user-menu-empresa-item:focus-visible,
.nav-flyout-head:focus-visible,
.nav-flyout-item:focus-visible,
.set-nav-item:focus-visible,
.cols-item:focus-visible,
.statsbar > .pill:focus-visible,
thead th.th-sort:focus-visible { outline-offset: -2px; }

/* La fila es la unidad de navegación (PATRONES-UI §Reglas de UX 6). El fondo
   acompaña al anillo porque un `outline` sobre `tr` depende del modelo de bordes
   de la tabla y no siempre se pinta completo. */
tbody tr:focus-visible     { outline: 2px solid var(--accent-ink); outline-offset: -2px; }
tbody tr:focus-visible td  { background: var(--hover); }
.order-card:focus-visible  { outline: 2px solid var(--accent-ink); outline-offset: 2px; }
