/* Brújula · kit de UI estándar (adopción gradual)
   ─────────────────────────────────────────────────────────────────────────
   Reglas del kit:
   · Todo va con prefijo .ui-* → CERO colisión con el CSS inline de los
     módulos existentes. Un módulo "adopta" el kit usando estas clases.
   · Los tokens :root de abajo solo RELLENAN huecos: cada página define los
     suyos inline después de este archivo, y la cascada hace que ganen.
   · Hoy lo usan: bitácora y seguridad (topbar estándar). El resto de páginas
     no se ven afectadas. Migrar módulo a módulo comparando el render.
   · Es asset de /assets/ → al cambiarlo, subir VERSION en sw.js. */

/* La paleta NO se define aquí. Vive en assets/tokens.css, que es la fuente del
   portal. Esto era un "fallback" que, al cargarse DESPUÉS de los tokens, los
   anulaba: el gris de texto se quedaba en #7a6f55 (contraste 4.18:1) cuando
   tokens.css ya lo había subido a #6e6349 (4.99:1, cumple AA). Se comprobó que
   ninguna página carga ui.css sin tokens.css, así que el fallback no protegía
   de nada. */

/* ── Topbar estándar (variante A del portal) ────────────────────────────
   Los mismos valores que la barra `.topbar` de anim.css (22 sep 2026): las
   dos formas de escribir la barra tienen que verse igual. */
.ui-topbar{
  position:sticky; top:0; z-index:1000; background:var(--topbar);
  border-bottom:1px solid var(--border-2);
  display:grid; grid-template-columns:1fr auto 1fr; align-items:center;
  padding:calc(14px + env(safe-area-inset-top,0px)) var(--pad-x,12px) 14px; gap:20px;
  /* El vidrio lo pone anim.css para todas las barras (`--glass-blur-chrome`). */
}
.ui-brand{display:flex; align-items:center; justify-self:start}
.ui-brand-back{
  font-size:var(--text-mini); letter-spacing:var(--track-widest); text-transform:uppercase;
  color:var(--muted); text-decoration:none; transition:color var(--amr-dur-fast,.15s); font-weight:600;
}
@media (hover:hover){.ui-brand-back:hover{color:var(--ink)}}
.ui-brand-center{display:flex; align-items:center; gap:10px; justify-self:center}
.ui-brand-name{
  font-family:var(--font-sans);
  font-size:var(--text-cuerpo); letter-spacing:var(--track-widest); color:var(--ink);
  text-transform:uppercase; font-weight:600; padding-left:.18em; text-decoration:none;
}
.ui-brand-sep{width:1px; height:18px; background:var(--gold); opacity:.7}
.ui-brand-sub{font-size:var(--text-micro); letter-spacing:var(--track-widest); color:var(--muted); text-transform:uppercase; font-weight:600}
/* El nombre de la pantalla es su <h1> — mismo criterio que `h1.brand-sub` en
   nav.css, para las tres páginas que llevan la topbar del kit. Solo se apaga el
   margen del navegador: el tamaño y el interletraje los manda la clase, que
   tiene más especificidad que `h1`. */
h1.ui-brand-sub{margin:0}
.ui-topbar-actions{display:flex; gap:8px; align-items:center; justify-self:end}
.ui-theme-toggle{
  background:transparent; border:1px solid var(--border-2); color:var(--muted);
  width:36px; height:36px; cursor:pointer; display:inline-flex;
  align-items:center; justify-content:center; transition:background-color var(--amr-dur-fast,.15s),color var(--amr-dur-fast,.15s),border-color var(--amr-dur-fast,.15s); padding:0; position:relative;
  border-radius:var(--radius-sm,8px);
}
@media (hover:hover){.ui-theme-toggle:hover{background:var(--ink); color:var(--bg); border-color:var(--ink)}}
/* Talla táctil de la topbar del kit (Fase 2, ago 2026). Estas tres piezas
   medían 36×36 (toggle), 36 de alto (reintentar) y 52×12 (el «‹ Inicio»): con
   el pulgar, 12 px de alto es no acertar.

   Aquí se usa el ÁREA INVISIBLE y no el crecimiento del control, porque son
   piezas de barra: engordar el toggle a 44 sube la altura de la topbar en todas
   las pantallas. El botón del kit sí crece de verdad —es la acción principal de
   la vista— y esa diferencia es deliberada. La condición es el dedo
   (`pointer:coarse`), no un ancho: un iPad también se toca. */
@media (pointer:coarse){
  .ui-theme-toggle,
  .ui-brand-back,
  .ui-state-cta{ position:relative; }
  .ui-theme-toggle::after,
  .ui-brand-back::after,
  .ui-state-cta::after{
    content:""; position:absolute; left:0; right:0; top:50%;
    height:var(--tap-min,44px); transform:translateY(-50%);
    /* Ancho mínimo: un «‹ Inicio» de 52 px de ancho ya cumple, pero el toggle
       mide 36 y necesita los 8 que le faltan repartidos a los lados. */
    min-width:var(--tap-min,44px); margin-inline:auto;
  }
}
.ui-theme-toggle .icon-sun,
.ui-theme-toggle .icon-moon{
  position:absolute; top:50%; left:50%; width:18px; height:18px; margin:-9px 0 0 -9px;
  transition:opacity var(--amr-dur-view,.28s) ease,transform var(--amr-dur-lento,.34s) var(--amr-ease-spring,cubic-bezier(.34,1.56,.64,1));
}
.ui-theme-toggle .icon-sun{opacity:1; transform:rotate(0) scale(1)}
.ui-theme-toggle .icon-moon{opacity:0; transform:rotate(-180deg) scale(0.4); pointer-events:none}
[data-theme="dark"] .ui-theme-toggle .icon-sun{opacity:0; transform:rotate(180deg) scale(0.4); pointer-events:none}
[data-theme="dark"] .ui-theme-toggle .icon-moon{opacity:1; transform:rotate(0) scale(1); pointer-events:auto}
@media (max-width:520px){
  /* Header móvil ESTÁNDAR: solo el nombre del módulo (wordmark = escritorio),
     centrado por flex de lados iguales. */
  .ui-topbar{display:flex;align-items:center;padding:calc(env(safe-area-inset-top, 0px) + 8px) 10px 8px;gap:8px;min-height:46px}
  .ui-brand{flex:1 1 0;min-width:0}
  .ui-topbar-actions{flex:1 1 auto;min-width:fit-content;display:flex;justify-content:flex-end}
  .ui-brand-center{flex:0 1 auto;min-width:0}
  .ui-brand-name,.ui-brand-sep{display:none}
  .ui-brand-sub{font-size:13px;letter-spacing:.22em;padding-left:.22em;color:var(--ink);font-weight:var(--weight-extrabold,800);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:58vw}
  .ui-brand-back{font-size:10px; letter-spacing:.16em}
  /* Aquí venían dos reglas más que no se veían pero mandaban:
     `.ui-brand-name{font-size:15px}` sobre un elemento que la línea de
     arriba ya pone en `display:none` —muerta—, y un segundo
     `.ui-brand-sub{font-size:9px}` que pisaba en silencio los 12.5px de
     esta misma llave. Ganaba el 9px por ser el último, así que el NOMBRE
     DEL MÓDULO se leía en el teléfono a 9 píxeles. Medido en seguridad a
     375px: `font-size: 9px`. Afecta a las tres pantallas que usan el kit
     con esta topbar (seguridad, bitacora, tablas). */
}

/* ── Toast estándar (para módulos que adopten el kit) ─────────────────── */
/* ── El toast · SE MUDÓ A assets/anim.css (1 sep 2026) ─────────────────────
   Mismo motivo que el esqueleto de carga y el estado vacío: aquí solo lo veían
   35 de los 52 archivos, y el aviso de «guardado» tiene que ser el mismo en
   todo el portal. Vive en `anim.css`, que sí cargan los 52, junto con el resto
   del rediseño (icono por tipo, se puede descartar, se anuncia). */

/* ── Estado unificado (vacío / error) · SE MUDÓ A assets/anim.css (ago 2026) ──
   Mismo motivo por el que se mudó el esqueleto de carga tres líneas más abajo:
   aquí solo lo veían 33 de las 50 páginas, y un estado vacío que falta en 17
   pantallas no es un estado unificado. Vive en `anim.css`, que cargan las 50, y
   se pone con `amrVacio()` (theme.js) en vez de escribir el markup a mano. */

/* ── Skeleton de carga · SE MUDÓ A assets/anim.css (jul 2026) ──────────────
   Vivía aquí, y aquí solo lo veían 26 de las 43 páginas: las otras 17 seguían
   con «Cargando…» de texto porque no cargan este kit. Como el estado de carga
   tiene que ser el MISMO en todo el portal (orden de Samuel), bajó a `anim.css`,
   que sí está en las 42 páginas operativas.

   Conserva el nombre `.ui-skel` a propósito: renombrarlo habría roto las cuatro
   pantallas que ya lo usaban sin darle nada a nadie. */

/* ── Botones del kit (roles estándar) ─────────────────────────────────────
   Espejo portable de la especificación .bds-btn del sistema de diseño
   (design-system/src/styles/components.css). Tres roles y una talla:
     .ui-btn            → primario (dorado): la acción principal de la vista
     .ui-btn--ghost     → secundario: acciones de apoyo
     .ui-btn--danger    → destructivo: borrar/rechazar (contorno, no grita)
     .ui-btn--sm        → compacto para barras y filas
   El hover del danger usa `--on-danger`, que en Modo mar es oscuro: ahí
   --danger es rosa claro y el blanco quedaba ilegible. */
/* Mismo botón que `.btn` de anim.css (22 sep 2026, diseño aprobado): 36 px,
   letra de 11 en mayúsculas, principal dorado y secundario con contorno de
   control. Lo cuida tests/un-solo-boton.test.mjs. */
.ui-btn{
  display:inline-flex; align-items:center; justify-content:center; gap:var(--space-2);
  min-height:var(--alto-control,36px); padding:0 var(--space-4,16px); box-sizing:border-box;
  /* En frase y con relieve, como `.btn` (plano con profundidad, 23 sep 2026:
     el porqué, en anim.css). */
  font-family:var(--font-sans,inherit); font-size:var(--text-apoyo,13px);
  font-weight:var(--weight-semibold,600); letter-spacing:0; line-height:1.1;
  text-transform:none; cursor:pointer; white-space:nowrap; text-decoration:none;
  border-radius:var(--radius-sm,8px);
  border:var(--stroke,1px) solid color-mix(in srgb,var(--gold,#3548ff) 82%,#000);
  background:var(--gold,#3548ff); color:var(--on-gold,#ffffff);
  box-shadow:var(--relieve,none);
  transition:filter var(--amr-dur-fast,.13s) var(--amr-ease,ease),
             background var(--amr-dur-fast,.13s) var(--amr-ease,ease),
             color var(--amr-dur-fast,.13s) var(--amr-ease,ease),
             border-color var(--amr-dur-fast,.13s) var(--amr-ease,ease),
             box-shadow var(--amr-dur,.2s) var(--amr-ease-out,ease-out),
             transform var(--amr-dur-fast,.13s) var(--amr-ease-out,ease-out);
}
/* Sin resplandor dorado al pasar el cursor: Samuel ya lo rechazó en las
   tarjetas y en los widgets, y un botón con relieve no lo necesita. */
@media (hover:hover){.ui-btn:hover:not(:disabled){ filter:brightness(1.05); }}
.ui-btn:active:not(:disabled){ transform:translateY(1px); box-shadow:var(--relieve-pulsado,none); }
.ui-btn:disabled{ opacity:.5; cursor:default; filter:none; transform:none; box-shadow:none; }
.ui-btn:focus-visible{ outline:2px solid var(--gold,#3548ff); outline-offset:2px; }
.ui-btn--ghost{ background:transparent; color:var(--ink,#1c1e21); border-color:var(--borde-control,rgba(10,31,51,.26)); box-shadow:none; }
@media (hover:hover){.ui-btn--ghost:hover:not(:disabled){ filter:none; box-shadow:none; background:var(--chip); border-color:var(--ink,#1c1e21); }}
.ui-btn--danger{ background:transparent; color:var(--danger,#a33a3a); border-color:color-mix(in srgb,var(--danger,#a33a3a) 55%,transparent); box-shadow:none; }
@media (hover:hover){.ui-btn--danger:hover:not(:disabled){ filter:none; box-shadow:none; background:var(--danger,#a33a3a); border-color:var(--danger,#a33a3a); color:var(--on-danger,#fff); }}
.ui-btn--sm{ min-height:28px; padding:0 var(--space-3, 12px); }
@media (max-width:760px){ .ui-btn{ min-height:var(--alto-control-movil,44px); } }
@media(prefers-reduced-motion:reduce){ .ui-btn,.ui-btn:active{ transform:none }
@media (hover:hover){.ui-btn:hover{ transform:none }} }
/* Talla táctil (defecto D-15). En escritorio el botón mide ~41 px y el compacto
   ~30: bien para el ratón. Con el dedo, el estándar del portal es 44 y hasta
   ahora `--alto-control-movil` no lo aplicaba ni un selector.
   Aquí SÍ crece el control —no un área invisible como en las pestañas—: un
   botón es la acción principal de la vista y merece el tamaño de verdad. La
   condición es el dedo (`pointer:coarse`), no el ancho: un iPad también se
   toca. `inline-flex` centra el texto dentro de la altura nueva. */
@media (pointer:coarse){
  .ui-btn{
    min-height:var(--alto-control-movil,44px);
    display:inline-flex; align-items:center; justify-content:center;
  }
}

/* ── Campo del kit (label + control) ──────────────────────────────────────
   Añadido en la Fase 2 de la remodernización (ago 2026). El kit tenía botón,
   topbar, toast, modal y estado vacío, y NO tenía campo — que es, con 624
   apariciones, el control más repetido del portal. Sin componente canónico,
   cada pantalla escribió el suyo: por eso hay 82 selectores que anulan el
   anillo de foco y 148 campos sin nombre accesible.

   Uso:
     <div class="ui-field">
       <label for="x">Kilos</label>
       <input class="ui-input" id="x" type="text">
     </div>

   Error (el mensaje se asocia, no solo se pinta):
     <div class="ui-field is-error">
       <label for="y">Kilos</label>
       <input class="ui-input" id="y" aria-invalid="true" aria-describedby="yErr">
       <p class="ui-field-msg" id="yErr">Los kilos no pueden ser negativos.</p>
     </div>

   El `<label for>` no es opcional: sin él el campo NO TIENE NOMBRE para un
   lector de pantalla, aunque se vea una etiqueta al lado. */
.ui-field{ display:flex; flex-direction:column; gap:var(--space-1,4px); }
.ui-field > label{
  font-size:var(--text-xs,10px); letter-spacing:var(--track-widest,.22em);
  text-transform:uppercase; color:var(--muted,#5a5e65);
  font-weight:var(--weight-semibold,600);
}
.ui-input{
  font-family:var(--font-sans,inherit); font-size:var(--text-base,14px);
  color:var(--ink,#1c1e21); background:var(--bg,#f4f5f7);
  border:var(--stroke,1px) solid var(--border,rgba(193,154,75,.4));
  border-radius:var(--radius-sm,8px);
  padding:var(--space-2,8px) var(--space-3,12px);
  min-height:var(--alto-control,36px);
  width:100%;
  transition:border-color var(--amr-dur-fast,130ms) var(--amr-ease,ease),
             background var(--amr-dur-fast,130ms) var(--amr-ease,ease);
}
/* El chevron del select se dibuja, no se hereda del sistema: así se ve igual
   en los dos temas y en los dos sistemas operativos. */
select.ui-input{
  appearance:none; -webkit-appearance:none;
  padding-right:var(--space-8,32px);
  background-image:linear-gradient(45deg,transparent 50%,currentColor 50%),
                   linear-gradient(135deg,currentColor 50%,transparent 50%);
  background-position:calc(100% - 16px) calc(50% + 1px), calc(100% - 11px) calc(50% + 1px);
  background-size:5px 5px, 5px 5px;
  background-repeat:no-repeat;
}
textarea.ui-input{ min-height:calc(var(--alto-control,36px) * 2); resize:vertical; }
.ui-input::placeholder{ color:var(--muted,#5a5e65); opacity:.75; }
.ui-input:focus{ border-color:var(--gold,#3548ff); background:var(--surface,#ffffff); }
/* El anillo NO se anula al enfocar: es la regla base de tokens.css la que
   manda, y aquí solo se refuerza. Anular el outline con `:focus` es lo que
   dejó a 82 selectores del portal sin señal de teclado. */
.ui-input:focus-visible{ outline:2px solid var(--gold,#3548ff); outline-offset:2px; }
.ui-input:disabled{ opacity:.55; cursor:default; background:var(--surface-sunken,#edeff2); }
.ui-field.is-error .ui-input,
.ui-input[aria-invalid="true"]{ border-color:var(--danger,#a33a3a); background:var(--danger-bg,rgba(163,58,58,.08)); }
.ui-field-msg{ font-size:var(--text-sm, 13px); color:var(--danger,#a33a3a); }
/* Con el dedo: 44 px de alto y 16 px de letra. Los 16 no son estética — por
   debajo de eso iOS hace zoom al enfocar el campo y descoloca la pantalla. */
@media (pointer:coarse){
  .ui-input{ min-height:var(--alto-control-movil,44px); font-size:var(--text-md,16px); }
}

/* ── Chip / etiqueta de estado ────────────────────────────────────────────
   El estado se comunica con chip, color de texto o punto — NUNCA con una
   barra lateral de acento (decisión de Samuel, jul 2026; se retiraron ~30).

     <span class="ui-chip">Neutro</span>
     <span class="ui-chip is-on">Activo</span>
     <span class="ui-chip ui-chip--ok">Entregado</span>   (--warn, --danger, --info) */
.ui-chip{
  display:inline-flex; align-items:center; gap:var(--space-1,4px);
  padding:var(--space-1,4px) var(--space-3,12px);
  border-radius:var(--radius-pill,999px);
  font-size:var(--text-xs,10px); font-weight:var(--weight-bold,700);
  letter-spacing:var(--track-wide,.06em); text-transform:uppercase;
  color:var(--muted,#5a5e65); background:var(--chip,rgba(193,154,75,.1));
  border:var(--stroke,1px) solid transparent; white-space:nowrap;
}
.ui-chip.is-on{ color:var(--on-gold,#ffffff); background:var(--gold,#3548ff); border-color:var(--gold,#3548ff); }
.ui-chip--ok{ color:var(--ok,#2f7d4f); background:var(--ok-bg,rgba(47,125,79,.1)); border-color:var(--ok,#2f7d4f); }
.ui-chip--warn{ color:var(--warn,#d97706); background:var(--warn-bg,rgba(217,119,6,.1)); border-color:var(--warn,#d97706); }
.ui-chip--danger{ color:var(--danger,#a33a3a); background:var(--danger-bg,rgba(163,58,58,.08)); border-color:var(--danger,#a33a3a); }
.ui-chip--info{ color:var(--info,#2f6d9e); background:var(--info-bg,rgba(47,109,158,.1)); border-color:var(--info,#2f6d9e); }
/* Un chip que se PULSA es un control y necesita talla táctil; uno que solo
   informa, no — inflar una etiqueta a 44 px rompe la densidad de una fila. */
@media (pointer:coarse){
  button.ui-chip, a.ui-chip{ min-height:var(--tap-min,44px); }
}

/* ── Modal base del kit ───────────────────────────────────────────────────
   Un solo lenguaje de diálogo para las ventanas que adopten el kit (los 9
   sistemas actuales conviven y migran de a poco). Estructura:
     <div class="ui-modal-backdrop" hidden>
       <div class="ui-modal" role="dialog" aria-modal="true" aria-labelledby="…">
         <div class="ui-modal__head">
           <h2 class="ui-modal__title" id="…">…</h2>
           <button class="ui-modal__close" type="button" aria-label="Cerrar">SVG ×</button>
         </div>
         <div class="ui-modal__body">…</div>
         [<div class="ui-modal__foot">botones</div>]
       </div>
     </div>
   Abrir/cerrar con window.uiModal (assets/ui.js): Esc, clic en backdrop,
   foco al abrir y restauración del foco al cerrar. Solo anima opacity y
   transform. En móvil (≤520px) baja como hoja anclada al fondo. */
.ui-modal-backdrop{
  position:fixed; inset:0; z-index:var(--z-modal,1200);
  display:flex; align-items:center; justify-content:center; padding:24px;
  background:color-mix(in srgb, var(--ink,#1c1e21) 45%, transparent);
  backdrop-filter:blur(3px); -webkit-backdrop-filter:blur(3px);
  opacity:0; transition:opacity var(--amr-dur,.2s) var(--amr-ease,ease);
}
.ui-modal-backdrop.is-open{ opacity:1; }
.ui-modal-backdrop[hidden]{ display:none; }
.ui-modal{
  width:min(560px, 100%); max-height:min(82dvh, 720px);
  display:flex; flex-direction:column;
  background:var(--surface,#ffffff); color:var(--ink,#1c1e21);
  border:1px solid var(--border,rgba(193,154,75,.4)); border-radius:var(--radius-lg, 24px);
  box-shadow:var(--elev-3);
  transform:translateY(14px) scale(.98);
  transition:transform var(--amr-dur,.2s) var(--amr-ease-out,ease-out);
}
.ui-modal-backdrop.is-open .ui-modal{ transform:none; }
.ui-modal__head{
  display:flex; align-items:center; gap:12px; flex-shrink:0;
  padding:16px 18px 12px; border-bottom:1px solid var(--border-2,rgba(10,31,51,.12));
}
.ui-modal__title{
  flex:1; min-width:0; font-size:var(--text-lg,18px);
  font-weight:var(--weight-semibold,600); letter-spacing:.02em;
}
.ui-modal__close{
  width:36px; height:36px; flex-shrink:0; display:inline-flex;
  align-items:center; justify-content:center; cursor:pointer; padding:0;
  background:transparent; border:1px solid var(--border-2,rgba(10,31,51,.12));
  border-radius:var(--radius-sm,8px); color:var(--muted,#5a5e65);
  transition:background var(--amr-dur-fast,.15s),color var(--amr-dur-fast,.15s),border-color var(--amr-dur-fast,.15s); position:relative;
}
.ui-modal__close::before{ content:""; position:absolute; inset:-6px }  /* táctil ≥44px */
@media (hover:hover){.ui-modal__close:hover{ background:var(--ink,#1c1e21); color:var(--bg,#f4f5f7); border-color:var(--ink,#1c1e21); }}
.ui-modal__close svg{ width:16px; height:16px }
.ui-modal__body{ flex:1; min-height:0; overflow-y:auto; -webkit-overflow-scrolling:touch; padding:16px 18px; }
.ui-modal__foot{
  display:flex; justify-content:flex-end; gap:10px; flex-shrink:0;
  padding:12px 18px 16px; border-top:1px solid var(--border-2,rgba(10,31,51,.12));
}
@media(max-width:520px){
  /* Hoja móvil: anclada abajo, ancho completo, respeta el home-indicator */
  .ui-modal-backdrop{ align-items:flex-end; padding:0; }
  .ui-modal{
    width:100%; max-height:88dvh; border-radius:var(--radius-lg, 24px) var(--radius-lg, 24px) 0 0;
    border-left:0; border-right:0; border-bottom:0;
  }
  .ui-modal__foot{ padding-bottom:calc(16px + env(safe-area-inset-bottom,0px)); }
}
@media(prefers-reduced-motion:reduce){
  .ui-modal-backdrop, .ui-modal{ transition:none }
}


/* ═══════════════════════════════════════════════════════════════════════════
   EVOLUCIÓN v4 — KIT DE MÓDULO (extraído de la plantilla Cuentas por pagar)
   Componentes estándar para TODOS los módulos: fila de herramientas, búsqueda
   tonal, filtro de estado, filtro de rango de fechas (chip+popover con atajos,
   default 2000→hoy vía assets/rango-fechas.js), botón latón, KPI-widget y
   lista-tabla. Un módulo ADOPTA usando este markup/clases y borrando sus
   estilos locales equivalentes (sin duplicados).
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Fila de herramientas (fuera del header): clúster centrado + utilidad al borde ── */
.filters{max-width:var(--maxw-frame);margin:20px auto 4px;padding:0 var(--pad-x,12px)}
.filters[hidden]{display:none}
.frow{position:relative;display:flex;gap:10px;align-items:center;justify-content:center;flex-wrap:wrap}
.futil{position:absolute;right:0;top:0}
@media(min-width:761px) and (max-width:1024px){
  .frow{flex-wrap:wrap;justify-content:center;row-gap:10px}
  .futil{position:static}
  .fsearch{width:min(300px,100%)}
}

/* ── Búsqueda TONAL ── */
.fsearch{position:relative;display:flex;align-items:center;width:min(320px,100%)}
.fsearch svg{position:absolute;left:12px;width:16px;height:16px;color:var(--muted);pointer-events:none}
.fsearch input{width:100%;font-family:inherit;font-size:15px;padding:10px 34px 10px 38px;border-radius:var(--radius-sm,8px);border:var(--stroke,1px) solid var(--borde-control);background:var(--surface);color:var(--ink);transition:box-shadow var(--amr-dur-fast,.15s),background-color var(--amr-dur-fast,.15s),border-color var(--amr-dur-fast,.15s);box-shadow:var(--hundido)}
.fsearch input::placeholder{color:var(--muted)}
.fsearch input:focus{outline:none;background:var(--surface);border-color:color-mix(in srgb,var(--gold) 45%,transparent);box-shadow:var(--hundido),var(--ring)}
.fclear{position:absolute;right:8px;width:24px;height:24px;border:none;background:transparent;color:var(--muted);font-size:20px;line-height:1;cursor:pointer;border-radius:var(--radius-sm)}
.fclear[hidden]{display:none}
@media (hover:hover){.fclear:hover{color:var(--ink)}}

/* ── Filtro de estado (select con chevron propio) — gemelo del chip de fechas ── */
.ffilter{display:inline-flex;align-items:center;gap:8px;height:42px;padding:0 12px;border:1px solid transparent;border-radius:var(--radius-sm,8px);background:var(--surface-sunken,var(--surface));flex-shrink:0;cursor:pointer;transition:border-color var(--amr-dur-fast,.15s),box-shadow var(--amr-dur-fast,.15s),background-color var(--amr-dur-fast,.15s)}
@media (hover:hover){.ffilter:hover{border-color:color-mix(in srgb,var(--gold) 40%,transparent)}}
.ffilter:focus-within{background:var(--surface);border-color:color-mix(in srgb,var(--gold) 45%,transparent);box-shadow:var(--ring)}
.ffilter.on{border-color:color-mix(in srgb,var(--gold) 45%,transparent);background:var(--chip)}
.ffilter>svg:first-child{width:15px;height:15px;color:var(--muted);flex-shrink:0}
.ffilter.on>svg:first-child{color:var(--gold)}
/* EL DESPLEGABLE LLENA LA PASTILLA, y no es cosmética: es el área que se puede
   pulsar. Medido en Existencias (12 sep 2026): la pastilla mide 38-42px y el
   <select> de dentro, sin borde ni relleno, se quedaba en los 16 de su renglón
   —`align-items:center` lo centraba y dejaba 22px MUERTOS—. Se comprobó con
   `elementFromPoint`: a 4px del borde superior o inferior el puntero aterrizaba
   en el `div`, no en el desplegable, así que un filtro que se ve de 38px solo
   respondía en su franja central. La pastilla ya declaraba `cursor:pointer`: la
   intención de que se pulsara entera estaba escrita, solo faltaba el estirón.
   `align-self:stretch` basta porque la pastilla NO tiene relleno vertical
   (`padding:0 12px`), así que el estirón llega hasta su borde. Alcanza a las 10
   pantallas que usan el kit. */
.ffilter select{border:none;background:transparent;color:var(--ink);font-family:inherit;font-size:13px;font-weight:600;padding:0;cursor:pointer;max-width:170px;color-scheme:light dark;-webkit-appearance:none;appearance:none;align-self:stretch}
.ffilter select:focus{outline:none}
.ff-chev{width:12px;height:12px;color:var(--muted);flex-shrink:0}
/* Toda la caja abre el desplegable, no solo la palabra: el <select> se estira por
   encima del icono y de la flecha (margen negativo = relleno, así no se mueve nada
   de sitio) y los dos SVG dejan pasar el clic. Las cuentas son las de la caja:
   12 de relleno + 15 del icono + 8 de hueco a la izquierda; 8 + 12 de la flecha
   + 12 de relleno a la derecha. content-box para que los width/max-width que cada
   pantalla le pone al select sigan midiendo el texto. */
.ffilter>svg{pointer-events:none}
.ffilter select{box-sizing:content-box;margin-right:-12px;padding-right:12px}
.ffilter>svg:first-child+select{margin-left:-35px;padding-left:35px}
.ffilter select:has(+.ff-chev){margin-right:-32px;padding-right:32px}

/* ── Filtro de rango de fechas ESTÁNDAR (chip + popover con atajos) ──
   Lógica compartida: assets/rango-fechas.js (AMRRango). Default 2000-01-01→hoy. */
.dr{position:relative;flex-shrink:0}
.dr-chip{display:inline-flex;align-items:center;gap:8px;height:42px;min-width:0;overflow:hidden;padding:0 12px;font-family:inherit;font-size:13px;font-weight:600;color:var(--ink);background:var(--surface-sunken,var(--surface));border:1px solid transparent;border-radius:var(--radius-sm,8px);cursor:pointer;transition:border-color var(--amr-dur-fast,.15s),box-shadow var(--amr-dur-fast,.15s),background-color var(--amr-dur-fast,.15s)}
.dr-chip svg{width:15px;height:15px;color:var(--muted);flex-shrink:0}
.dr-chip svg:last-child{width:12px;height:12px;transition:transform var(--amr-dur-fast,.15s)}
.dr-chip .dr-txt{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0;flex:1 1 auto}
.dr-chip b{color:var(--ink);font-weight:600}
.dr.on .dr-chip b{color:var(--gold-text);font-weight:700}
@media (hover:hover){.dr-chip:hover{border-color:color-mix(in srgb,var(--gold) 40%,transparent)}}
.dr.open .dr-chip{background:var(--surface);border-color:color-mix(in srgb,var(--gold) 45%,transparent);box-shadow:var(--ring)}
.dr.open .dr-chip svg:last-child{transform:rotate(180deg)}
.dr.on .dr-chip{border-color:color-mix(in srgb,var(--gold) 45%,transparent);background:var(--chip)}
.dr-pop{position:absolute;top:calc(100% + 8px);left:50%;transform:translateX(-50%);z-index:1200;width:324px;max-width:calc(100vw - 24px);padding:16px;background:var(--surface-raised,var(--surface));border:1px solid var(--border-2);border-radius:var(--radius-md,12px);box-shadow:var(--elev-2);display:none;flex-direction:column;gap:12px}
.dr.open .dr-pop,.dr-pop.open{display:flex}
@media (prefers-reduced-motion: no-preference){.dr.open .dr-pop,.dr-pop.open{animation:amr-drin var(--amr-dur,200ms) var(--amr-ease-press,cubic-bezier(.34,1.24,.64,1))}}
@keyframes amr-drin{from{opacity:0;transform:translateX(-50%) translateY(-6px) scale(.97)}to{opacity:1;transform:translateX(-50%)}}
@keyframes amr-drdrop{from{opacity:0;transform:translateY(-10px) scale(.98)}to{opacity:1;transform:none}}
@keyframes amr-drfade{from{opacity:0}to{opacity:1}}
.dr-backdrop{position:fixed;inset:0;z-index:4100;background:var(--velo-suave);animation:amr-drfade var(--amr-dur-fast,.15s) ease both}
.dr-group{display:flex;flex-direction:column;gap:8px}
.dr-group + .dr-group{margin-top:14px}
.dr-glabel{font-size:9px;letter-spacing:var(--track-widest);text-transform:uppercase;color:var(--muted);font-weight:700}
.dr-presets{display:flex;flex-wrap:wrap;gap:6px}
.dr-presets button{padding:8px 13px;font-family:inherit;font-size:12px;font-weight:700;color:var(--muted);background:var(--surface-sunken,var(--chip));border:none;border-radius:var(--radius-pill,999px);cursor:pointer;transition:color var(--amr-dur-fast,.15s),background-color var(--amr-dur-fast,.15s)}
@media (hover:hover){.dr-presets button:hover{color:var(--ink)}}
.dr-presets button.on{background:var(--chip);color:var(--gold-text)}
.dr-range{display:flex;align-items:stretch;background:var(--surface-sunken,var(--surface));border:1px solid transparent;border-radius:12px;transition:box-shadow var(--amr-dur-fast,.15s),background-color var(--amr-dur-fast,.15s),border-color var(--amr-dur-fast,.15s)}
.dr-range:focus-within{background:var(--surface);border-color:color-mix(in srgb,var(--gold) 45%,transparent);box-shadow:var(--ring)}
.dr-rf{flex:1 1 0;min-width:0;display:flex;flex-direction:column;gap:2px;padding:9px 12px;cursor:pointer}
.dr-rf>span{font-size:9px;letter-spacing:var(--track-wider);text-transform:uppercase;color:var(--muted);font-weight:700}
.dr-rf input{width:100%;min-width:0;border:none;background:transparent;color:var(--ink);font-family:inherit;font-size:13px;font-weight:600;padding:0;outline:none;color-scheme:light dark}
.dr-rf input::-webkit-calendar-picker-indicator{margin:0}
.dr-rsep{width:1px;align-self:stretch;margin:9px 0;background:var(--hairline,var(--border-2));flex:none}
.dr-apply{padding:10px;font-family:inherit;font-size:12px;font-weight:700;letter-spacing:.04em;color:var(--on-gold,#ffffff);background:var(--brass,var(--gold));border:none;border-radius:10px;cursor:pointer;box-shadow:var(--relieve);transition:transform var(--amr-dur-fast,.15s) var(--amr-ease-press,ease),filter var(--amr-dur-fast,.15s)}
@media (hover:hover){.dr-apply:hover{filter:brightness(1.05)}}
.dr-apply:active{transform:scale(.97)}

/* ── Botón LATÓN (acción primaria/utilidad: Excel, exportar, publicar) ── */
.btn-brass{display:inline-flex;align-items:center;gap:7px;height:42px;background:var(--brass,var(--gold));border:none;color:var(--on-gold,#ffffff);font-family:inherit;font-size:13px;font-weight:700;letter-spacing:.02em;padding:0 16px;border-radius:var(--radius-sm,8px);cursor:pointer;box-shadow:var(--relieve);transition:transform var(--amr-dur-fast,.15s) var(--amr-ease-press,ease),filter var(--amr-dur-fast,.15s);flex-shrink:0}
.btn-brass svg{width:17px;height:17px}
@media (hover:hover){.btn-brass:hover{filter:brightness(1.05)}}
.btn-brass:active{transform:scale(.96)}

/* ── KPI-WIDGET compacto ── */
.kpis-w{display:flex;justify-content:center}
.kpis-w[hidden]{display:none}
.kpiw{display:inline-flex;align-items:stretch;background:var(--surface);border:1px solid var(--border-2);border-radius:var(--radius-md,12px);box-shadow:var(--relieve-tarjeta);overflow:hidden}
.kpiw .kcell{display:flex;flex-direction:column;gap:2px;align-items:center;justify-content:center;padding:9px 22px;min-width:118px}
.kpiw .kcell + .kcell{border-left:1px solid var(--hairline,var(--border-2))}
.kpiw .kcell .n{font-size:15px;font-weight:700;color:var(--ink);font-variant-numeric:tabular-nums;letter-spacing:-.01em;white-space:nowrap}
.kpiw .kcell .l{font-size:9px;letter-spacing:var(--track-widest);text-transform:uppercase;color:var(--muted);font-weight:700}
.kpiw .kcell.gold .n{color:var(--gold)}
.kpiw .kcell.ok .n{color:var(--ok)}

/* ── LISTA-TABLA: rejilla compartida + filas-tarjeta ──
   El módulo define sus columnas: .tgrid{grid-template-columns:...} local. */
.tlist{display:flex;flex-direction:column;gap:6px}
.thead{padding:10px 18px 5px 22px}   /* +aire arriba: separa los nombres de columna de los KPIs */
.tnum{justify-self:start;text-align:left;font-size:13px;font-weight:600;color:var(--muted);font-variant-numeric:tabular-nums;white-space:nowrap}
/* Separadores de columna: SOLO en filas (no en los títulos), de ALTO FIJO (mismo
   largo siempre), centrados en el hueco entre columnas. Cada módulo los coloca en
   sus celdas (evitando las que recortan con overflow). Estilo base compartido: */
.col-sep{position:relative}
.col-sep::after,.col-sep-l::before{content:"";position:absolute;top:50%;transform:translateY(-50%);height:22px;width:1px;background:var(--border-2)}
.col-sep::after{right:-7px}
.col-sep-l::before{left:-7px}
@media(max-width:760px){.col-sep::after,.col-sep-l::before{display:none}}  /* en móvil la fila se reacomoda */
.avatar{width:36px;height:36px;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;font-size:12px;font-weight:700;letter-spacing:.04em;color:var(--gold);background:var(--chip);border:1px solid color-mix(in srgb,var(--gold) 25%,transparent);border-radius:11px}
.rowcard{position:relative;overflow:hidden;width:100%;text-align:left;background:var(--surface);border:1px solid var(--border-2);border-radius:var(--radius-md,12px);box-shadow:var(--relieve-tarjeta);padding:9px 18px 9px 22px;cursor:pointer;font-family:inherit;color:inherit;transition:transform var(--amr-dur-fast,.15s),border-color var(--amr-dur-fast,.15s),box-shadow var(--amr-dur-fast,.15s)}
@media (prefers-reduced-motion: no-preference){@media (hover:hover){.rowcard:hover{transform:translateY(-2px);box-shadow:var(--relieve-tarjeta)}}}
@media (hover:hover){.rowcard:hover{border-color:color-mix(in srgb,var(--gold) 45%,transparent)}}

/* ── MÓVIL (≤760): herramientas en dos filas + chips 16px + dropdown portado ── */
@media(max-width:760px){
  /* Layout móvil SCOPEADO a la fila de herramientas del kit (.filters) para no
     tocar buscadores/chips propios de páginas complejas que cargan ui.css. */
  .filters{max-width:none;margin:0;padding:12px var(--pad-x-movil,10px) 4px}
  .filters .frow{flex-wrap:wrap;gap:8px;justify-content:center}
  /* El hueco de 84 px es para el botón de Excel (`.futil`), y por eso se reserva
     SOLO si ese botón está. Se reservaba siempre, y en las páginas que no lo
     llevan —Recepción, sin ir más lejos— el buscador se quedaba igual con
     `100% - 84` y el sobrante caía en el chip de fechas de la fila: 75 px para
     «Todo» con icono, chevron y padding, o sea 20 px de texto. Se leía «T».
     Un ancho reservado para algo que no existe es de las cosas que nadie
     encuentra mirando el elemento que se ve mal. */
  .filters .fsearch{order:1;width:100%;flex:none}
  .filters .frow:has(> .futil) .fsearch{width:calc(100% - 84px)}
  .filters .fsearch input{font-size:16px}
  .filters .futil{order:2;position:static;flex:none;width:76px;align-self:stretch}
  .filters .btn-brass{width:76px;height:100%;align-self:stretch;padding:0;justify-content:center}
  .filters .btn-brass svg{width:26px;height:26px}
  .filters .btn-brass span{display:none}
  .filters .ffilter{order:3;flex:1 1 0;min-width:0;justify-content:center;padding:0 12px}
  .filters .ffilter select{max-width:calc(100% - 26px);font-size:16px}
  .filters .dr{order:4;flex:1 1 0;min-width:0}
  .filters .dr-chip{width:100%;justify-content:center;padding:0 12px}
  .filters .dr-chip,.filters .dr-chip b{font-size:16px}
  .dr-pre{display:none}
  .dr-chip,.dr-chip b{font-size:16px}
  /* El popover portado aplica SIEMPRE en móvil (vive en body) */
  .dr-pop{position:fixed;left:10px;right:10px;top:0;bottom:auto;width:auto;max-width:none;transform:none;z-index:4200;border-radius:var(--radius-lg, 24px);padding:16px}
  .dr-pop.open{animation:amr-drdrop 220ms var(--amr-ease-press,cubic-bezier(.34,1.24,.64,1)) both}
  .dr-rf input{font-size:16px}
}

/* ── LA SEMANA · navegación entre semanas ISO 8601 ──────────────────────────
   Nació en el inventario de Planta (ago 2026) y el 28 ago 2026 Samuel la pidió
   también para las Recepciones cerradas y el Histórico: «navegación entre
   semana iso 8601». Tres pantallas es una utilidad, así que el dibujo baja al
   kit y las cuentas a `theme.js` (`amrSemanaLunes` y compañía). Una copia de
   cada cosa.

   Navegación, no filtro: la semana manda sobre lo que la pantalla enseña, y por
   eso va arriba del todo y con su rango escrito. */
/* `position:relative` porque el menú de semanas cuelga de aquí: sin él se
   anclaba al viewport y caía fuera de la pantalla (medido: y=820 en un alto de
   812, o sea invisible). */
.sem{position:relative;flex:0 0 auto;display:flex;align-items:center;justify-content:center;gap:10px}
.sem[hidden]{display:none}
.sem-btn{width:34px;height:34px;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--border-2);border-radius:var(--radius-sm);background:var(--surface);color:var(--ink);cursor:pointer;transition:border-color var(--amr-dur-fast),color var(--amr-dur-fast);box-shadow:var(--relieve)}
.sem-btn svg{width:16px;height:16px}
@media (hover:hover){.sem-btn:hover{border-color:var(--gold);color:var(--gold)}}
/* El rango es un BOTÓN: abre el menú de semanas. Se pinta como texto —no como
   un control— porque sigue siendo el título de la barra; lo que dice que se
   puede tocar es el galón de al lado y, al pasar, el dorado. */
.sem-txt{position:relative;text-align:center;min-width:0;font-family:inherit;border:none;background:transparent;color:inherit;padding:2px 6px;border-radius:var(--radius-sm);cursor:pointer;display:flex;flex-direction:column;align-items:center;gap:1px}
.sem-txt .sem-tit{display:inline-flex;align-items:center;gap:6px}
.sem-txt .sem-tit::after{content:'';width:8px;height:8px;flex:0 0 auto;border-right:2px solid currentColor;border-bottom:2px solid currentColor;transform:translateY(-2px) rotate(45deg);opacity:.5}
@media (hover:hover){.sem-txt:hover{color:var(--gold)}}
.sem-txt:focus-visible{outline:2px solid var(--gold);outline-offset:2px}
.sem-txt[aria-expanded="true"] .sem-tit::after{transform:translateY(1px) rotate(-135deg);opacity:1}
/* El menú, colgado de la barra. Ancho fijo y centrado: la lista son rangos de
   largo parejo y perseguir el ancho del botón lo hacía bailar. */
.sem-menu{position:absolute;top:calc(100% + 8px);left:50%;transform:translateX(-50%);z-index:90;width:min(300px,calc(100vw - 28px));background:var(--surface);border:1px solid var(--border-2);border-radius:var(--radius-md);box-shadow:var(--elev-2);padding:8px;text-align:left}
.sem-menu-fecha{display:flex;flex-direction:column;gap:5px;padding:4px 6px 9px;border-bottom:1px solid var(--border-2);margin-bottom:6px}
.sem-menu-fecha span{font-size:var(--text-micro);letter-spacing:var(--track-wider);text-transform:uppercase;color:var(--muted);font-weight:var(--weight-bold)}
.sem-menu-fecha input{font-family:inherit;font-size:var(--text-apoyo);padding:9px 11px;border:var(--stroke,1px) solid var(--borde-control);border-radius:var(--radius-sm);background:var(--surface);color:var(--ink);width:100%;box-sizing:border-box;box-shadow:var(--hundido)}
.sem-menu-lista{max-height:min(46vh,300px);overflow-y:auto;overscroll-behavior:contain}
.sem-op{display:flex;align-items:baseline;justify-content:space-between;gap:10px;width:100%;font-family:inherit;text-align:left;padding:9px 10px;border:none;border-radius:var(--radius-sm);background:transparent;color:var(--ink);cursor:pointer}
@media (hover:hover){.sem-op:hover{background:var(--chip)}}
.sem-op.es-actual{background:var(--chip);color:var(--gold)}
.sem-op-t{font-size:var(--text-nota);font-weight:var(--weight-bold)}
.sem-op-n{font-size:var(--text-micro);letter-spacing:var(--track-wider);text-transform:uppercase;color:var(--muted);white-space:nowrap;flex:0 0 auto}
.sem-op.es-actual .sem-op-n{color:var(--gold)}
.sem-tit{font-family:var(--font-serif);font-size:var(--text-titulo3);font-weight:var(--weight-semibold);line-height:1.15;white-space:nowrap}
.sem-sub{font-size:var(--text-micro);letter-spacing:var(--track-wider);text-transform:uppercase;color:var(--muted);font-weight:var(--weight-bold)}
.sem-sub.ahora{color:var(--gold)}
.sem-hoy{height:28px;padding:0 11px;border:1px solid var(--border-2);border-radius:var(--radius-pill);background:transparent;color:var(--muted);font-family:inherit;font-size:var(--text-nota);font-weight:var(--weight-bold);letter-spacing:0;text-transform:none;cursor:pointer;white-space:nowrap}
.sem-hoy[hidden]{display:none}
@media (hover:hover){.sem-hoy:hover{border-color:var(--gold);color:var(--gold)}}
/* Buscando, la semana no manda: la búsqueda va sobre TODO el histórico
   (elección de Samuel). Se atenúa y se apaga, en vez de desaparecer — que la
   barra se fuera cambiaría el alto de la cabecera al escribir. */
.sem.sem-apagada{opacity:.42;pointer-events:none}
/* En el teléfono las flechas crecen a 44 px (área táctil de `app-ios.css`) y el
   título es una serif de dos líneas: con 10 px en medio, el rango quedaba
   pegado a los botones. El aire sube donde el bloque tiene sitio de sobra —a
   375 px, 44+204+44 son 292 de 355—, no donde falta. */
@media(max-width:640px){
  .sem{gap:14px}
}
/* En un teléfono la fila no siempre cabe: con «Esta semana» puesto —que solo
   aparece cuando NO estás en la semana de hoy— piden ‹34 + el rango + ›34 +
   114 del atajo, y medido a 393 se salían 16 px por la derecha. Se deja
   PARTIR: el atajo baja a su propio renglón y solo cuando hace falta. Encoger
   el rango no valía: «Del 3 al 9 de agosto» con puntos suspensivos no dice qué
   semana estás mirando. */
@media(max-width:640px){
  .sem{flex-wrap:wrap}
  .sem-hoy{order:9;margin:2px auto 0}
}
