/* ===== static/css/app/base/tokens.css ===== */
/* ------------------------------------------------------------------ */
/* Design tokens                                                       */
/* ------------------------------------------------------------------ */
:root {
  /* Curvas de movimiento: ease-out fuerte para entrar/responder, cajón
     tipo iPhone para el menú lateral. Usar estas, no curvas sueltas. */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);
  --main: #084383;
  --main-dark: #062f5e;
  --secondary: #35a2db;
  --secondary-light: #e7f4fb;

  --bg: #f4f6f9;
  --surface: #ffffff;
  --border: #e2e7ee;
  --text: #16233a;
  --text-muted: #62728a;
  --text-faint: #66758b;

  --success: #1b8a5a;
  --success-bg: #e7f6ee;
  --success-border: #cdeadd;
  --danger: #c23a3a;
  --danger-bg: #fbeaea;
  --danger-border: #f0b7b7;
  --warn-bg: #fff6e0;
  --warn-text: #8a6a10;
  /* "En Espera" de una OT — amarillo propio, distinto del ámbar de --warn */
  --hold: #f2c200;
  --hold-bg: #fff9dc;
  --hold-border: #f3dc7a;
  --hold-text: #a37800;

  /* Color de acento para TEXTO/íconos sobre el fondo propio de la app
     (--bg/--surface) — en modo claro es igual a --main, pero en modo
     oscuro se vuelve más brillante para seguir siendo legible. --main y
     --main-dark en cambio NUNCA cambian entre temas: son el azul de marca
     usado como relleno sólido (sidebar, botones, avatares) con texto
     blanco encima, y ese combo se ve bien en ambos temas sin tocarlo. */
  --accent-text: #084383;

  --input-bg: #ffffff;
  --group-row-bg: #e4ecf8;
  --row-alt-bg: #f8fbfd;
  --row-hover-bg: #eef5fa;
  --row-border: #eef1f5;
  --subtle-bg: #eef1f5;
  --badge-purple-bg: #f1ecfa;
  --badge-purple-text: #6b3fb0;
  --pie-swatch-ring: rgba(11, 11, 11, .08);
  /* Paleta de gráficas (2026-10-15, nucleo/graficas.js): la misma en todas
     las pestañas. 1 = azul de la marca; el resto se distingue a simple vista. */
  --chart-1: #0b5cad;
  --chart-2: #35a2db;
  --chart-3: #1b8a5a;
  --chart-4: #e0a106;
  --chart-5: #d4622a;
  --chart-6: #7a4cc2;
  --chart-7: #c2407e;
  --chart-8: #138f8f;
  --chart-9: #4f6a8f;
  --chart-10: #8a9a1f;
  --chart-other: #9aa7b8;
  --chart-grid: #e6ebf2;
  --chart-tip-bg: rgba(255, 255, 255, .86);

  --radius: 10px;
  --radius-sm: 6px;
  --shadow: 0 1px 2px rgba(16, 34, 64, 0.06), 0 4px 16px rgba(16, 34, 64, 0.05);

  --gap-sm: 8px;
  --gap-md: 12px;
  --gap-lg: 16px;
  --pad-card: 20px;

  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", "Inter", Roboto, Helvetica, Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  --barcode-ink: #000;

  /* Espacio reservado arriba de .main para la campana/chip de usuario
     (position:fixed) — reutilizado por los elementos "pegajosos" (sticky)
     para que no se solapen con esa barra al hacer scroll. */
  --content-top-offset: 70px;
}

/* ------------------------------------------------------------------ */
/* Modo oscuro — toggle manual (menú del chip de usuario), no sigue la
   preferencia del sistema. --main/--main-dark se dejan igual a propósito
   (ver comentario de --accent-text arriba). */
/* ------------------------------------------------------------------ */
:root[data-theme="dark"] {
  --secondary-light: rgba(53, 162, 219, .16);

  --bg: #0e1520;
  --surface: #172130;
  --border: #2a3648;
  --text: #e6ecf6;
  --text-muted: #8b9ab2;
  --text-faint: #7d8aa3;

  --success: #3ecf8e;
  --success-bg: #113325;
  --success-border: #1f5c3f;
  --danger: #f0716f;
  --danger-bg: #3a1717;
  --danger-border: #6b2b2b;
  --warn-bg: #3a2f10;
  --warn-text: #e8b84b;
  --hold: #f2c94c;
  --hold-bg: #36300f;
  --hold-border: #6b5a1a;
  --hold-text: #f2c94c;

  --accent-text: #5aa9e6;

  --input-bg: #101a28;
  --group-row-bg: rgba(90, 169, 230, .14);
  --row-alt-bg: #141d2b;
  --row-hover-bg: #1c283a;
  --row-border: #232e40;
  --subtle-bg: #202b3d;
  --badge-purple-bg: #2a2140;
  --badge-purple-text: #c3adf5;
  --pie-swatch-ring: rgba(255, 255, 255, .15);
  --chart-1: #5aa9e6;
  --chart-2: #8fd3f7;
  --chart-3: #3ecf8e;
  --chart-4: #f2c94c;
  --chart-5: #f08a4b;
  --chart-6: #b69cf2;
  --chart-7: #f28cb8;
  --chart-8: #4fd1c5;
  --chart-9: #9fb4d4;
  --chart-10: #c9d65a;
  --chart-other: #6b7a90;
  --chart-grid: #263243;
  --chart-tip-bg: rgba(23, 33, 48, .86);
}
@media (hover: hover) and (pointer: fine) { :root[data-theme="dark"] .btn-danger:hover { background: #4a1f1f; } }
:root[data-theme="dark"] input[type=text], :root[data-theme="dark"] input[type=number],
:root[data-theme="dark"] input[type=search], :root[data-theme="dark"] input[type=email],
:root[data-theme="dark"] input[type=password], :root[data-theme="dark"] input[type=time],
:root[data-theme="dark"] select,
:root[data-theme="dark"] textarea { color-scheme: dark; }
:root[data-theme="dark"] * { scrollbar-color: var(--border) var(--bg); }
:root[data-theme="dark"] ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 999px; }
:root[data-theme="dark"] ::-webkit-scrollbar-track { background: transparent; }

/* Las etiquetas de código de barras se imprimen siempre en papel blanco,
   sin importar el tema activo en pantalla al momento de imprimir. */
@media print {
  :root, :root[data-theme="dark"] {
    --bg: #f4f6f9; --surface: #ffffff; --border: #e2e7ee;
    --text: #16233a; --text-muted: #62728a; --text-faint: #93a1b5;
  }
}

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  font-family: var(--font);
  background: var(--bg);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
  transition: background-color .15s ease, color .15s ease;
  /* Fuente tabular para todo número en la app (monto, cantidad, fecha) —
     se hereda a toda la página, así que cada tabla de dinero alinea sus
     columnas sin tener que tocar cada `fmtPrice(...)` uno por uno (son
     decenas de sitios, varios de ellos usan `.textContent` directo, que
     se rompería si `fmtPrice` empezara a devolver HTML con una clase). */
  font-variant-numeric: tabular-nums;
}
.card, .stat-tile, .modal-card, input, select, textarea, .sidebar, table {
  transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
button, input, select, textarea { font-family: inherit; font-size: inherit; color: inherit; }
h1, h2, h3, h4 { margin: 0; }
p { margin: 0; }


/* ===== static/css/app/base/estructura.css ===== */
/* ------------------------------------------------------------------ */
/* Shell layout                                                        */
/* ------------------------------------------------------------------ */
.app-shell { display: flex; min-height: 100vh; min-height: 100dvh; }

.sidebar {
  width: 232px;
  flex-shrink: 0;
  background: linear-gradient(180deg, var(--main) 0%, var(--main-dark) 100%);
  color: #eaf2fb;
  display: flex;
  flex-direction: column;
  padding: 20px 14px;
  padding-top: calc(20px + env(safe-area-inset-top));
  padding-bottom: calc(20px + env(safe-area-inset-bottom));
  padding-left: calc(14px + env(safe-area-inset-left));
  position: fixed;
  top: 0;
  left: 0;
  height: 100vh;
  height: 100dvh;
  overflow-y: auto;
  /* Reserva el espacio de la barra de scroll SIEMPRE, aparezca o no —
     si no, cada vez que colapsar/desplegar un grupo cruza el punto donde
     el menú deja de (o empieza a) necesitar scroll, el ancho del
     contenido interno cambia por el ancho de esa barra (~15-17px) y todo
     el menú se ve "temblar" un poco de tamaño. */
  scrollbar-gutter: stable;
  transition: transform .28s var(--ease-drawer);
}

.brand { padding: 6px 8px 22px; cursor: pointer; }
.brand-logo {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 6px 8px;
}
.brand-logo img { display: block; width: 100%; max-width: 170px; height: auto; }

.nav { display: flex; flex-direction: column; gap: 2px; flex: 1; }
.nav-item {
  display: flex; align-items: center; gap: 11px;
  background: none; border: none; text-align: left;
  color: #cfe1f4;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: calc(14.5px * var(--fs, 1));
  font-weight: 600;
  transition: background .12s ease, color .12s ease;
}
.nav-icon { width: 18px; height: 18px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; opacity: .9; }
.nav-icon svg { width: 18px; height: 18px; }
@media (hover: hover) and (pointer: fine) { .nav-item:hover { background: rgba(255,255,255,.08); color: #fff; } }

.nav-group-toggle {
  display: flex; align-items: center; gap: 6px;
  width: 100%; background: none; border: none; text-align: left;
  color: #82a4c6; padding: 16px 12px 6px;
  cursor: pointer; font-size: calc(10.5px * var(--fs, 1)); font-weight: 800;
  text-transform: uppercase; letter-spacing: .07em;
  transition: color .12s ease;
}
.nav-group-toggle:first-child { padding-top: 2px; }
@media (hover: hover) and (pointer: fine) { .nav-group-toggle:hover { color: #cfe1f4; } }
.nav-group-label { flex: 1; }
.nav-group-chevron { width: 12px; height: 12px; flex-shrink: 0; transition: transform .18s var(--ease-out); opacity: .7; }
.nav-group-toggle.collapsed .nav-group-chevron { transform: rotate(-90deg); }
/* .nav-group se abre/cierra con animación: ver "Sidebar Glide" en fx.css. */
.nav-group { display: grid; }
.nav-item.active { background: var(--secondary); color: #06263f; font-weight: 700; }

.sidebar-footer { font-size: calc(10.5px * var(--fs, 1)); color: #82a4c6; padding: 10px 8px 0; line-height: 1.4; }
.sidebar-credit {
  background: none; border: none; padding: 0; margin: 0; width: 100%; text-align: left;
  font: inherit; color: inherit; cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .sidebar-credit:hover { color: #cfe1f4; text-decoration: underline; } }

/* Easter egg — clic en "Desarrollado por Ari Ramos" — ver openDevEasterEgg()
   en app.js. Puramente decorativo, se cierra solo a los 3 segundos.
   dev-easter-egg.webp es una animación real de 12 cuadros (no dibujada a
   mano), por eso solo hace falta el pop-in de la tarjeta acá. */
.dev-egg-overlay { background: rgba(15, 26, 45, .7); cursor: pointer; }
.dev-egg-card {
  width: 320px; height: 320px; max-width: 82vw; max-height: 82vw;
  border-radius: var(--radius); overflow: hidden;
  animation: eggPopIn .25s var(--ease-out);
}
.dev-egg-card img { width: 100%; height: 100%; display: block; object-fit: cover; }
@keyframes eggPopIn { from { transform: scale(.85); opacity: 0; } to { transform: scale(1); opacity: 1; } }


/* ===== static/css/app/base/inicio-de-sesion.css ===== */
/* ------------------------------------------------------------------ */
/* Pantallas de autenticación (login / configuración inicial)          */
/* ------------------------------------------------------------------ */
#auth-screen:empty { display: none; }
.auth-wrap {
  min-height: 100vh; min-height: 100dvh;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  background: linear-gradient(180deg, var(--main) 0%, var(--main-dark) 100%);
}
.auth-card {
  width: 100%; max-width: 400px;
  background: var(--surface);
  border-radius: var(--radius);
  box-shadow: 0 24px 64px rgba(8, 16, 32, .35); padding: 28px 26px;
}
.auth-logo { display: flex; justify-content: center; margin-bottom: 18px; }
.auth-logo img { width: 100%; max-width: 190px; height: auto; }

.auth-card a { color: var(--secondary); font-weight: 600; }

/* Overlay de acento azul (misma familia visual que el sidebar), usado en
   los modales de contraseña — la tarjeta adentro se queda blanca normal */
.modal-overlay.modal-overlay-navy { background: linear-gradient(180deg, var(--main) 0%, var(--main-dark) 100%); }

.main { flex: 1; min-width: 0; padding: var(--content-top-offset) 34px 60px; margin-left: 232px; }
.view { max-width: 1180px; margin: 0 auto; min-height: calc(100dvh - 100px); }

/* Colapsar el menú izquierdo también en PC (no solo en mobile) — mismo
   botón/animación hamburguesa -> X que ya existía solo para mobile. */
@media (min-width: 861px) {
  .sidebar { transition: transform .28s var(--ease-drawer); }
  body.sidebar-collapsed .sidebar { transform: translateX(-100%); }
  body.sidebar-collapsed .main { margin-left: 0; }
  /* El contenido se acomoda al instante y se desliza con transform (barato) desde donde estaba. */
  .main.is-sliding { transition: transform .28s var(--ease-drawer); }
}
@media (prefers-reduced-motion: reduce) { .sidebar, .main.is-sliding { transition: none; } }

.mobile-menu-toggle {
  display: flex;
  position: fixed;
  top: calc(14px + env(safe-area-inset-top));
  left: calc(14px + env(safe-area-inset-left));
  z-index: 220;
  width: 40px; height: 40px; align-items: center; justify-content: center;
  background: var(--main); color: #fff; border: none; border-radius: var(--radius-sm);
  box-shadow: var(--shadow); cursor: pointer;
}
.mobile-menu-toggle svg { width: 20px; height: 20px; }
.menu-line { transition: transform .22s var(--ease-out), opacity .15s ease; transform-box: fill-box; transform-origin: center; }
.mobile-menu-toggle.open .menu-line-top { transform: translateY(6px) rotate(45deg); }
.mobile-menu-toggle.open .menu-line-mid { opacity: 0; }
.mobile-menu-toggle.open .menu-line-bottom { transform: translateY(-6px) rotate(-45deg); }
.sidebar-backdrop {
  display: none;
  position: fixed; inset: 0; z-index: 190;
  background: rgba(10, 20, 38, .5);
}
.sidebar-backdrop.visible { display: block; }

/* Campana de notificaciones + chip de usuario, arriba a la derecha en todo momento */
.topbar-actions {
  position: fixed;
  top: calc(14px + env(safe-area-inset-top));
  right: calc(14px + env(safe-area-inset-right));
  z-index: 220;
  display: flex; align-items: center; gap: 8px;
}
.user-chip { position: relative; }
.user-chip-btn {
  display: flex; align-items: center; gap: 8px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 999px;
  padding: 5px 12px 5px 5px; cursor: pointer; box-shadow: var(--shadow);
}
.user-chip-avatar {
  width: 30px; height: 30px; border-radius: 50%; flex-shrink: 0;
  background: linear-gradient(180deg, var(--main) 0%, var(--main-dark) 100%);
  color: #fff; font-size: calc(12px * var(--fs, 1)); font-weight: 800;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
}
.avatar-img { width: 100%; height: 100%; object-fit: cover; border-radius: inherit; display: block; }
.avatar-table-thumb {
  width: 32px; height: 32px; border-radius: 50%; flex-shrink: 0; overflow: hidden;
  background: linear-gradient(180deg, var(--main) 0%, var(--main-dark) 100%);
  color: #fff; font-size: calc(12px * var(--fs, 1)); font-weight: 800;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
}
.avatar-lg {
  width: 96px; height: 96px; border-radius: 50%; flex-shrink: 0; overflow: hidden;
  background: linear-gradient(180deg, var(--main) 0%, var(--main-dark) 100%);
  color: #fff; font-size: calc(32px * var(--fs, 1)); font-weight: 800;
  display: flex; align-items: center; justify-content: center; margin: 0 auto 10px;
}
.avatar-xl {
  width: 128px; height: 128px; border-radius: 50%; flex-shrink: 0; overflow: hidden;
  background: linear-gradient(180deg, var(--main) 0%, var(--main-dark) 100%);
  color: #fff; font-size: calc(42px * var(--fs, 1)); font-weight: 800;
  display: flex; align-items: center; justify-content: center;
}
/* Foto de un documento (ej. permiso firmado) — a diferencia de avatar-xl,
   NO es circular: recortar un documento en círculo le corta información. */
.photo-doc-preview {
  width: 100%; max-width: 480px; aspect-ratio: 4 / 3; border-radius: var(--radius-sm);
  flex-shrink: 0; overflow: hidden; background: var(--subtle-bg);
  border: 1px solid var(--border); color: var(--text-faint); font-size: calc(13px * var(--fs, 1));
  display: flex; align-items: center; justify-content: center;
}
.perm-photo-thumb {
  width: 130px; height: 96px; object-fit: cover; border-radius: var(--radius-sm);
  border: 1px solid var(--border); cursor: pointer; display: block;
}
.perm-photo-missing {
  width: 130px; height: 96px; border-radius: var(--radius-sm); border: 1px dashed var(--border);
  display: flex; align-items: center; justify-content: center;
  color: var(--text-faint); font-size: calc(11px * var(--fs, 1)); cursor: pointer; text-align: center;
}
.user-chip-text { display: flex; flex-direction: column; align-items: flex-start; max-width: 150px; line-height: 1.25; }
.user-chip-name { font-size: calc(13px * var(--fs, 1)); font-weight: 700; color: var(--text); text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.user-chip-username { font-size: calc(10.5px * var(--fs, 1)); font-weight: 500; color: var(--text-faint); text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.user-chip-chevron { width: 15px; height: 15px; color: var(--text-muted); transition: transform .15s var(--ease-out); flex-shrink: 0; }
.user-chip.open .user-chip-chevron { transform: rotate(180deg); }
.user-chip-backdrop {
  display: none;
  position: fixed; inset: 0; z-index: 215;
  background: rgba(10, 20, 38, .35);
}
.user-chip-backdrop.visible { display: block; }
.user-chip-menu {
  display: none; position: absolute; top: calc(100% + 8px); right: 0;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: 0 16px 40px rgba(8, 16, 32, .22); min-width: 300px; padding: 8px; z-index: 221;
}
.user-chip.open .user-chip-menu { display: block; }
.user-chip-menu-header { padding: 8px 10px 10px; border-bottom: 1px solid var(--border); margin-bottom: 6px; }
.user-chip-menu-name { font-size: calc(13.5px * var(--fs, 1)); font-weight: 700; color: var(--text); }
.user-chip-menu-role { font-size: calc(11px * var(--fs, 1)); color: var(--text-muted); text-transform: uppercase; letter-spacing: .04em; margin-top: 2px; }
/* Animated List (React Bits): las opciones entran una tras otra con un
   rebote, cada una es una ficha con su ícono, y un aro se desliza hasta la
   opción señalada (mouse o flechas). */
.al-list { position: relative; display: flex; flex-direction: column; gap: 4px; }
.user-chip-menu .al-list > button {
  position: relative; z-index: 1; display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  background: none; border: none; padding: 7px 10px 7px 7px; border-radius: var(--radius-sm);
  font-size: calc(13.5px * var(--fs, 1)); font-weight: 600; color: var(--text); cursor: pointer;
}
.user-chip-menu .al-list > button[hidden] { display: none; }
.al-lead { display: grid; place-items: center; flex: none; width: 30px; height: 30px; border-radius: 9px; background: var(--subtle-bg); color: var(--accent-text); transition: background .2s ease, color .2s ease; }
.al-lead svg { width: 16px; height: 16px; }
.al-title { flex: 1; min-width: 0; line-height: 1.25; }
#btn-logout .al-lead, #btn-logout-all .al-lead { color: var(--danger); }
.al-ring {
  position: absolute; left: 0; top: 0; width: 100%; height: 0; z-index: 0; border-radius: var(--radius-sm); pointer-events: none;
  background: color-mix(in srgb, var(--main) 7%, transparent); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--main) 28%, transparent);
  opacity: 0; transform: translateY(0); transition: transform .26s cubic-bezier(.34, 1.3, .64, 1), height .2s var(--ease-out), opacity .18s ease;
}
.al-ring.on { opacity: 1; }
.user-chip.open .al-list > button { animation: al-in .62s cubic-bezier(.34, 1.35, .64, 1) backwards; animation-delay: calc(var(--al-i, 0) * 50ms + 60ms); }
@keyframes al-in { from { opacity: 0; transform: translate3d(0, 12px, 0) scale(.8); } }
@media (prefers-reduced-motion: reduce) { .user-chip.open .al-list > button { animation: none; } .al-ring { transition: opacity .1s; } }

.global-search { position: relative; }
.global-search-btn {
  position: relative; width: 40px; height: 40px; border-radius: 50%;
  background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shadow);
  display: flex; align-items: center; justify-content: center; cursor: pointer; color: var(--text-muted);
}
@media (hover: hover) and (pointer: fine) { .global-search-btn:hover { color: var(--text); } }
.global-search-btn svg { width: 18px; height: 18px; }
.global-search-panel {
  display: none; position: absolute; top: calc(100% + 8px); right: 0;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: 0 16px 40px rgba(8, 16, 32, .22); width: 360px; max-width: 88vw; z-index: 221; overflow: hidden;
}
.global-search.open .global-search-panel { display: block; }
#global-search-input {
  width: 100%; border: none; border-bottom: 1px solid var(--border); border-radius: 0;
  padding: 12px 14px; font-size: calc(13.5px * var(--fs, 1)); background: var(--surface); color: var(--text);
}
#global-search-input:focus { outline: none; }
.global-search-results { max-height: 400px; overflow-y: auto; }
.global-search-hint { padding: 16px 14px; font-size: calc(12.5px * var(--fs, 1)); color: var(--text-faint); text-align: center; }
.global-search-group-title {
  padding: 9px 14px 5px; font-size: calc(10.5px * var(--fs, 1)); font-weight: 800; text-transform: uppercase;
  letter-spacing: .04em; color: var(--accent-text);
}
.global-search-item {
  display: block; width: 100%; text-align: left; padding: 9px 14px; cursor: pointer;
  background: none; border: none; font-size: calc(13px * var(--fs, 1)); color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
@media (hover: hover) and (pointer: fine) { .global-search-item:hover { background: var(--bg); } }

.notif-bell { position: relative; }
.notif-bell-btn {
  position: relative; width: 40px; height: 40px; border-radius: 50%;
  background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shadow);
  display: flex; align-items: center; justify-content: center; cursor: pointer; color: var(--text-muted);
}
@media (hover: hover) and (pointer: fine) { .notif-bell-btn:hover { color: var(--text); } }
.notif-bell-btn svg { width: 19px; height: 19px; }
@keyframes bell-ring {
  0%, 100% { transform: rotate(0deg); }
  15% { transform: rotate(16deg); }
  30% { transform: rotate(-13deg); }
  45% { transform: rotate(10deg); }
  60% { transform: rotate(-6deg); }
  75% { transform: rotate(3deg); }
}
.notif-bell-btn svg.ringing { animation: bell-ring .6s ease; transform-origin: 50% 15%; }
.notif-badge {
  position: absolute; top: -3px; right: -3px; min-width: 17px; height: 17px; padding: 0 4px;
  background: var(--danger); color: #fff; font-size: calc(10px * var(--fs, 1)); font-weight: 800; border-radius: 999px;
  display: flex; align-items: center; justify-content: center; border: 2px solid var(--bg);
}
.notif-panel {
  display: none; position: absolute; top: calc(100% + 8px); right: 0;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: 0 16px 40px rgba(8, 16, 32, .22); width: 300px; max-width: 85vw; z-index: 221; overflow: hidden;
}
.notif-bell.open .notif-panel { display: block; }
.notif-panel-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 14px; border-bottom: 1px solid var(--border); font-size: calc(13px * var(--fs, 1)); font-weight: 700;
}
.notif-panel-header button {
  background: none; border: none; color: var(--accent-text); font-size: calc(11.5px * var(--fs, 1)); font-weight: 700; cursor: pointer; padding: 0;
}
.notif-list { max-height: 320px; overflow-y: auto; }
.notif-item {
  display: flex; align-items: flex-start; gap: 8px; padding: 11px 14px; cursor: pointer;
  border-bottom: 1px solid var(--border); font-size: calc(12.5px * var(--fs, 1)); color: var(--text);
}
.notif-item:last-child { border-bottom: none; }
@media (hover: hover) and (pointer: fine) { .notif-item:hover { background: var(--bg); } }
.notif-item-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--secondary); margin-top: 5px; flex-shrink: 0; }
.notif-item-text { flex: 1; line-height: 1.4; }
.notif-item-time { display: block; color: var(--text-faint); font-size: calc(10.5px * var(--fs, 1)); margin-top: 2px; }
.notif-item-read { color: var(--text-muted); }
.notif-item-read .notif-item-dot { background: var(--border); }
.notif-empty { padding: 24px 14px; text-align: center; color: var(--text-faint); font-size: calc(12.5px * var(--fs, 1)); }

@media (max-width: 860px) {
  .mobile-menu-toggle { display: flex; }
  .user-chip-text { display: none; }
  .user-chip-btn { padding: 5px; }
  .sidebar {
    transform: translateX(-100%);
    transition: transform .28s var(--ease-drawer);
    z-index: 200;
    width: 240px;
  }
  .sidebar.open { transform: translateX(0); }
  .main {
    --content-top-offset: calc(66px + env(safe-area-inset-top));
    margin-left: 0;
    padding: var(--content-top-offset) calc(16px + env(safe-area-inset-right)) calc(40px + env(safe-area-inset-bottom)) calc(16px + env(safe-area-inset-left));
  }
  .page-title { font-size: calc(24px * var(--fs, 1)); }
  .card { padding: 14px; }
}

/* El buscador global y las notificaciones se posicionan con `right: 0`
   relativo a su propio botón (no al borde de la pantalla) — en celular el
   ícono de búsqueda queda lejos del borde derecho (a la izquierda de
   notificaciones + usuario), así que ese panel de 360px se salía por
   completo del lado izquierdo de la pantalla (hasta 90px invisibles/fuera
   de alcance). En vez de depender de esa posición relativa al ícono, se
   ancla directo a los bordes del viewport. */
@media (max-width: 520px) {
  .global-search-panel, .notif-panel {
    position: fixed;
    top: calc(62px + env(safe-area-inset-top));
    left: calc(12px + env(safe-area-inset-left));
    right: calc(12px + env(safe-area-inset-right));
    width: auto;
    max-width: none;
  }
}


/* ===== static/css/app/base/paginas-y-formularios.css ===== */
/* ------------------------------------------------------------------ */
/* Header / page structure                                             */
/* ------------------------------------------------------------------ */
.page-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--gap-lg); margin-bottom: 22px; flex-wrap: wrap; }
.page-title { font-size: calc(30px * var(--fs, 1)); font-weight: 700; letter-spacing: -.01em; }
.page-desc { color: var(--text-muted); font-size: calc(13.5px * var(--fs, 1)); margin-top: 4px; max-width: 560px; }

.grid { display: grid; gap: var(--gap-lg); }
.grid > * { min-width: 0; }
.grid > .card + .card { margin-top: 0; }

.grid-4 { grid-template-columns: repeat(4, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-2 { grid-template-columns: 1fr 1fr; }
@media (max-width: 900px) {
  
  .grid-4 { grid-template-columns: repeat(2,1fr); }
  .grid-3 { grid-template-columns: repeat(2,1fr); }
  .grid-2 { grid-template-columns: 1fr; }
}
@media (max-width: 700px) { .grid-2 { grid-template-columns: 1fr; } }

/* Sistema: las tarjetas "Respaldo de la base de datos" y "Actualizar la aplicacion" van lado a lado
   (solo cuando hay 2 columnas, en pantallas anchas). Comparten las mismas 4 filas (titulo, texto,
   boton, resultado) con subgrid, asi los botones quedan al MISMO nivel aunque un texto sea mas
   largo que el otro, tambien cuando aparece el resultado de una de ellas. */
@media (min-width: 901px) {
  #system-top-cards { grid-template-rows: repeat(4, auto); row-gap: 0; }
  #system-top-cards > .card { display: grid; grid-row: span 4; grid-template-rows: subgrid; row-gap: 0; }
  #system-top-cards > .card > .btn { justify-self: start; }  /* que el boton no se estire a todo el ancho */
}
@media (max-width: 560px) { .grid-3 { grid-template-columns: 1fr; }  }

/* hidden siempre oculta, aunque la clase ponga display (ej. .stack en Sistema). */
[hidden] { display: none !important; }
.stack { display: flex; flex-direction: column; gap: var(--gap-lg); }

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: var(--pad-card);
}
.card + .card { margin-top: var(--gap-lg); }
.card-title { font-size: calc(16px * var(--fs, 1)); font-weight: 700; margin-bottom: 2px; }
.card-head-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.card-desc { font-size: calc(12.5px * var(--fs, 1)); color: var(--text-muted); margin-bottom: var(--gap-md); }

/* Stat tiles */
.stat-tile { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow); padding: 16px 18px; }

/* overflow-wrap: un monto largo (ej. "L 51,052,368.90") es una sola
   palabra sin espacios — sin esto no puede partirse en dos líneas y en
   celular (tarjetas de ~164px en un grid de 4) se sale del recuadro,
   agrandando el ancho de toda la página en vez de quedarse contenido. */
.stat-num { font-size: calc(26px * var(--fs, 1)); font-weight: 800; color: var(--accent-text); letter-spacing: -.02em; overflow-wrap: break-word; }
.stat-tile-compact .stat-num { font-size: calc(18px * var(--fs, 1)); }
/* Montos en una sola línea; si no caben, nucleo/ajustar-montos.js baja la letra. */
.fit-money { white-space: nowrap; overflow-wrap: normal; word-break: normal; min-width: 0; max-width: 100%; }
.stat-label { font-size: calc(12px * var(--fs, 1)); color: var(--text-muted); margin-top: 2px; font-weight: 600; text-transform: uppercase; letter-spacing: .03em; }

/* ------------------------------------------------------------------ */
/* Forms                                                                */
/* ------------------------------------------------------------------ */
.field { margin-bottom: var(--gap-md); }
.field label { display: block; font-size: calc(12.5px * var(--fs, 1)); font-weight: 700; color: var(--text); margin-bottom: 5px; }
.field .hint, .hint { font-size: calc(11.5px * var(--fs, 1)); color: var(--text-faint); margin-top: 4px; margin-bottom: 4px; }
.req { color: var(--danger); margin-left: 2px; }
input[type=text], input[type=number], input[type=search], input[type=email], input[type=password], input[type=time], select, textarea {
  width: 100%;
  padding: 9px 11px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--input-bg);
  color: var(--text);
  outline: none;
  transition: border-color .12s ease, box-shadow .12s ease;
}
/* input[type=time] sin esta regla se queda con el estilo crudo del
   navegador (borde fino gris, alto distinto al resto de campos) — se ve
   fuera de lugar junto al botón de fecha (que sí está diseñado a mano).
   El selector de hora sigue siendo el nativo del navegador (reloj al
   hacer clic) — pedido explícito — solo se le pareja el marco al resto
   de inputs de la app. */
input[type=time] { font-family: inherit; font-size: calc(14px * var(--fs, 1)); }
input:focus, select:focus, textarea:focus {
  border-color: var(--secondary);
  box-shadow: 0 0 0 3px var(--secondary-light);
}

/* Text input backed by a <datalist> — looks like a select (dropdown arrow)
   but still supports typing to filter/autocomplete. */
input.combo-input {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2362728a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 14px;
  padding-right: 32px;
  cursor: pointer;
}
.row { display: flex; gap: var(--gap-md); flex-wrap: wrap; }
.row > * { flex: 1; min-width: 160px; }

.scan-input {
  font-family: var(--mono);
  letter-spacing: .04em;
  font-size: calc(14px * var(--fs, 1));
  border-width: 2px !important;
}
.scan-input.armed { border-color: var(--secondary) !important; box-shadow: 0 0 0 3px var(--secondary-light); }

/* Buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  padding: 9px 15px;
  font-weight: 700;
  font-size: calc(13px * var(--fs, 1));
  cursor: pointer;
  transition: filter .12s ease, background .12s ease, transform .16s var(--ease-out);
  white-space: nowrap;
}
/* Un .btn sin variante (Salir, Cerrar, Volver a lo normal…) no traía fondo ni color
   propios: en modo oscuro salía blanco con letra blanca. Se ve como "ghost";
   :where() lo deja sin peso para que cualquier regla propia lo siga ganando. */
.btn:where(:not(.btn-primary, .btn-secondary, .btn-ghost, .btn-danger, .btn-hold, .btn-whatsapp, .btn-send)) { background: transparent; color: var(--accent-text); border-color: var(--border); }
@media (hover: hover) and (pointer: fine) { .btn:where(:not(.btn-primary, .btn-secondary, .btn-ghost, .btn-danger, .btn-hold, .btn-whatsapp, .btn-send)):hover { background: var(--secondary-light); } }
.btn-primary { background: var(--main); color: #fff; }
@media (hover: hover) and (pointer: fine) { .btn-primary:hover { filter: brightness(1.1); } }
.btn-secondary { background: var(--secondary); color: #062f5e; }
@media (hover: hover) and (pointer: fine) { .btn-secondary:hover { filter: brightness(1.05); } }
.btn-ghost { background: transparent; color: var(--accent-text); border-color: var(--border); }
@media (hover: hover) and (pointer: fine) { .btn-ghost:hover { background: var(--secondary-light); } }
.btn-danger { background: var(--danger-bg); color: var(--danger); }
@media (hover: hover) and (pointer: fine) { .btn-danger:hover { background: #f6d9d9; } }
.btn-hold { background: var(--hold-bg); color: var(--hold-text); border-color: var(--hold-border); }
@media (hover: hover) and (pointer: fine) { .btn-hold:hover { filter: brightness(.97); } }
.btn-hold.active { background: var(--hold); color: #3d2e00; border-color: var(--hold); }
.btn-sm { padding: 5px 10px; font-size: calc(12px * var(--fs, 1)); }
.btn[disabled] { opacity: .5; cursor: not-allowed; }
.btn-row { display: flex; gap: var(--gap-sm); flex-wrap: wrap; margin-top: 6px; }

/* Botones de solo ícono (editar/eliminar/imprimir) — filas de tabla y
   tarjetas donde el espacio es limitado. Mismo color por variante
   (btn-ghost/btn-danger) que ya tenían las versiones con texto. */
.btn-icon { padding: 0; width: 30px; height: 30px; gap: 0; flex-shrink: 0; }
.btn-icon svg { width: 15px; height: 15px; }
.btn .btn-ico { width: 15px; height: 15px; flex: none; }
.btn-sm .btn-ico { width: 14px; height: 14px; }

/* Tables */
table { width: 100%; border-collapse: collapse; font-size: calc(13px * var(--fs, 1)); color: var(--text); }
thead th {
  text-align: left; font-size: calc(11px * var(--fs, 1)); text-transform: uppercase; letter-spacing: .04em;
  color: var(--text-muted); font-weight: 700; padding: 8px 10px; border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

/* Sortable column headers (Panel) */
.sort-arrows { display: inline-flex; flex-direction: column; gap: 1px; vertical-align: middle; margin-left: 3px; }
.sort-arrow {
  background: none; border: none; cursor: pointer; padding: 0; margin: 0;
  color: var(--text-faint); font-size: calc(8px * var(--fs, 1)); line-height: 8px;
}
@media (hover: hover) and (pointer: fine) { .sort-arrow:hover { color: var(--secondary); } }
.sort-arrow.active { color: var(--accent-text); }
.sortable-label { cursor: pointer; }
@media (hover: hover) and (pointer: fine) { .sortable-label:hover { color: var(--accent-text); text-decoration: underline; } }

/* Dual-thumb price range slider: two range inputs stacked on one visual track */
.dual-slider { position: relative; height: 22px; margin-top: 8px; }
.dual-slider-track {
  position: absolute; top: 50%; left: 0; right: 0; height: 4px;
  transform: translateY(-50%);
  background: var(--border); border-radius: 999px;
}
.dual-slider-fill {
  position: absolute; top: 50%; height: 4px;
  transform: translateY(-50%);
  background: var(--accent-text); border-radius: 999px;
}
.dual-range {
  position: absolute; top: 0; left: 0; width: 100%; height: 22px; margin: 0;
  appearance: none; -webkit-appearance: none; background: transparent; pointer-events: none;
}
.dual-range::-webkit-slider-runnable-track { background: transparent; height: 4px; }
.dual-range::-moz-range-track { background: transparent; height: 4px; border: none; }
.dual-range::-webkit-slider-thumb {
  appearance: none; -webkit-appearance: none; pointer-events: auto;
  width: 16px; height: 16px; border-radius: 50%;
  background: var(--accent-text); border: 2px solid #fff;
  box-shadow: 0 0 0 1px var(--border), var(--shadow);
  cursor: pointer; margin-top: -6px;
}
.dual-range::-moz-range-thumb {
  pointer-events: auto; width: 16px; height: 16px; border-radius: 50%;
  background: var(--accent-text); border: 2px solid #fff;
  box-shadow: 0 0 0 1px var(--border), var(--shadow);
  cursor: pointer;
}
.price-range-ticks {
  display: flex; justify-content: space-between; margin-top: 8px;
  font-size: calc(11px * var(--fs, 1)); color: var(--text-faint);
}

/* Supplier chips */

.chip {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--secondary-light); color: var(--accent-text);
  padding: 5px 8px 5px 12px; border-radius: 999px; font-size: calc(12.5px * var(--fs, 1)); font-weight: 600;
}
.chip button {
  background: none; border: none; color: var(--accent-text); cursor: pointer;
  font-weight: 800; font-size: calc(14px * var(--fs, 1)); padding: 0 2px; line-height: 1; opacity: .6;
}
@media (hover: hover) and (pointer: fine) { .chip button:hover { opacity: 1; } }
tbody td { padding: 10px; border-bottom: 1px solid var(--row-border); vertical-align: middle; white-space: nowrap; }
tbody td.wrap { white-space: normal; max-width: 240px; }
tbody tr:nth-child(even) { background: var(--row-alt-bg); }
@media (hover: hover) and (pointer: fine) { tbody tr:hover { background: var(--row-hover-bg); } }
tbody tr.clickable-row, tbody td.clickable-row { cursor: pointer; }
/* Tablas más cómodas (estilo Magic UI): encabezado en banda suave con
   esquinas redondas, filas más altas con números alineados, y al pasar el
   mouse la fila se ilumina con una barra de color a la izquierda. */
table { font-variant-numeric: tabular-nums; }
thead th { background: var(--subtle-bg); border-bottom: none; padding: 10px 12px; }
thead th:first-child { border-radius: 8px 0 0 8px; }
thead th:last-child { border-radius: 0 8px 8px 0; }
tbody td { padding: 11px 12px; transition: background-color .15s ease; }
tbody tr:last-child td { border-bottom: none; }
tbody tr { transition: background-color .15s ease; }
@media (hover: hover) and (pointer: fine) {
  tbody tr:hover > td:first-child { box-shadow: inset 3px 0 0 var(--main); }
}
.client-group-row { background: var(--bg); }
.group-expand-arrow { display: inline-block; width: 12px; color: var(--text-faint); }
.table-wrap { overflow-x: auto; }
.table-scroll-mirror { overflow-x: auto; overflow-y: hidden; height: 16px; margin-bottom: 6px; }
.table-scroll-mirror-inner { height: 1px; }
.table-wrap-v-scroll { max-height: 480px; overflow-y: auto; }
.table-wrap-v-scroll thead th { position: sticky; top: 0; background: var(--subtle-bg); z-index: 1; }
/* Productos (pestaña Productos y Panel) tienen muchas más filas que el
   resto de las tablas — les damos más alto antes de necesitar scroll. */
.table-wrap-v-scroll-tall { max-height: 1100px; }
.btn[aria-disabled="true"] { opacity: .55; }
/* Novedades: separador entre tandas del mismo día. */
/* Título de cada tanda: una franja con la fecha, la tanda y cuántos cambios trae (2026-11-03). */
.changelog-body .changelog-batch {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin: 20px 0 8px; padding: 9px 12px; border-radius: var(--radius-sm);
  background: var(--subtle-bg); border-left: 4px solid var(--secondary);
  font-size: calc(15px * var(--fs, 1)); font-weight: 800; color: var(--accent-text);
}
.changelog-batch-tag { padding: 2px 9px; border-radius: 999px; background: var(--main); color: #fff; font-size: calc(12px * var(--fs, 1)); font-weight: 700; }
.changelog-batch-count { margin-left: auto; font-size: calc(12px * var(--fs, 1)); font-weight: 600; color: var(--text-muted); }
.changelog-body .changelog-batch:first-child { margin-top: 0; }
/* OT de pago Especial (2026-11-03): estado del pago y su botón, alineados. */
.wo-special-pay { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; }
.wo-special-pay-info { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
.wo-special-pay .badge { margin: 0; white-space: nowrap; }
.wo-special-pay-btn { padding: 5px 12px; white-space: nowrap; }
/* Planilla: incapacidad del IHSS (2026-11-03) */
.payroll-inc-box { border: 1px solid var(--border); border-radius: 12px; padding: 12px; margin-bottom: 12px; background: var(--subtle-bg); }
.payroll-inc-item { font-size: 14px; display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 6px 0; border-bottom: 1px solid var(--border); margin-bottom: 8px; }
.payroll-inc-tag { display: inline-block; font-size: 11px; font-weight: 700; padding: 1px 6px; border-radius: 999px; background: var(--warn-bg); color: var(--warn-text); white-space: nowrap; }
/* Desarrollo → tickets (2026-11-03): casi toda la pantalla, para ver más reportes sin scroll doble. */
#dev-table-scroll { max-height: max(520px, calc(100vh - 230px)); max-height: max(520px, calc(100dvh - 230px)); }
/* Columnas redimensionables (como Excel) — ver makeTableResizable() en
   app.js. table-layout:fixed es necesario para que los anchos manuales se
   respeten; sin él el navegador vuelve a acomodar según el contenido. */
.resizable-table { table-layout: fixed; }
.resizable-table th, .resizable-table td { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.resizable-table th { position: relative; }
/* Tablas que reciben el ajuste solas (nucleo/tablas.js): el texto sigue
   bajando de renglón y nada se recorta (menús y listas dentro de una celda). */
.resizable-table.resizable-wrap td { white-space: normal; overflow: visible; overflow-wrap: anywhere; }
.col-resize-handle {
  position: absolute; top: 0; right: -4px; width: 8px; height: 100%; cursor: col-resize; z-index: 2;
}
.col-resize-handle::after {
  content: ""; position: absolute; top: 15%; bottom: 15%; left: 50%; width: 2px;
  transform: translateX(-50%); background: var(--border); border-radius: 1px;
}
.col-resizing .col-resize-handle::after { background: var(--main); width: 3px; }
@media (hover: hover) and (pointer: fine) { .col-resize-handle:hover::after { background: var(--main); width: 3px; } }
.col-resizing .col-resize-handle { background: rgba(8, 67, 131, .12); }
@media (hover: hover) and (pointer: fine) { .col-resize-handle:hover { background: rgba(8, 67, 131, .12); } }
body.col-resizing { cursor: col-resize; user-select: none; }
/* Productos/Panel tienen muchas columnas (incluyendo dos precios extra) —
   un poco menos de padding por celda ayuda a que quepan sin scroll
   horizontal en pantallas anchas, sin afectar el resto de las tablas. */
.table-wrap-v-scroll-tall table th, .table-wrap-v-scroll-tall table td { padding-left: 7px; padding-right: 7px; }
.mono { font-family: var(--mono); font-size: calc(12.5px * var(--fs, 1)); }

.badge {
  display: inline-flex; align-items: center; gap: 4px;
  background: var(--secondary-light); color: var(--accent-text);
  font-size: calc(11px * var(--fs, 1)); font-weight: 700; padding: 3px 8px; border-radius: 999px;
}
.badge-nowrap { white-space: nowrap; line-height: 1.3; }
.badge-muted { background: var(--subtle-bg); color: var(--text-muted); }
.badge-warn { background: var(--warn-bg); color: var(--warn-text); }
.badge-danger { background: var(--danger-bg); color: var(--danger); }
.badge-success { background: var(--success-bg); color: var(--success); }
.badge-purple { background: var(--badge-purple-bg); color: var(--badge-purple-text); }

/* V21 — círculo chico a la izquierda del precio en la tabla de Productos,
   cuando el producto tiene precio de más de un proveedor registrado. Solo
   informativo, sin clic — por eso no usa .badge (que sugiere interacción
   en otros lados de la app) sino su propia clase minimalista. */
.alt-price-badge {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 17px; height: 17px; padding: 0 4px; margin-right: 6px;
  border-radius: 999px; background: var(--main); color: #fff;
  font-size: calc(10px * var(--fs, 1)); font-weight: 700; line-height: 1; vertical-align: middle;
}

.status-select {
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  width: auto; border: none; cursor: pointer;
  font-size: calc(11px * var(--fs, 1)); font-weight: 700; padding: 3px 20px 3px 9px; border-radius: 999px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 6px center; background-size: 10px;
  flex-shrink: 0;
}
@media (hover: hover) and (pointer: fine) { .status-select:hover { filter: brightness(.95); } }
.status-select:focus { outline: 2px solid var(--secondary); outline-offset: 1px; }

.empty-state { text-align: center; padding: 40px 20px; color: var(--text-muted); }
.empty-state .big { font-size: calc(30px * var(--fs, 1)); margin-bottom: 8px; }
.empty-state-action { margin-top: 14px; }
.empty-state-art { display: flex; justify-content: center; margin-bottom: 10px; color: var(--text-faint); }

.upcoming-dates-list { display: flex; flex-direction: column; gap: 2px; }
.upcoming-date-row {
  display: flex; align-items: center; gap: 10px; padding: 8px 6px;
  border-bottom: 1px solid var(--border);
}
.upcoming-date-row:last-child { border-bottom: none; }
.upcoming-date-icon {
  width: 28px; height: 28px; flex-shrink: 0; border-radius: 50%;
  display: inline-grid; place-items: center;
  background: var(--secondary-light); color: var(--accent-text);
}
.upcoming-date-icon svg { width: 15px; height: 15px; }
.upcoming-date-name { font-weight: 700; color: var(--text); flex: 0 0 auto; }
.upcoming-date-detail { color: var(--text-muted); font-size: calc(12.5px * var(--fs, 1)); flex: 1 1 auto; }
.upcoming-date-when { font-weight: 700; font-size: calc(12.5px * var(--fs, 1)); color: var(--text-muted); flex-shrink: 0; }
.upcoming-date-today { color: var(--main); }

/* Toast — arriba a la derecha en login/registro (sin chip encima); arriba
   al centro, con texto centrado, para los mensajes generales dentro de la
   app; arriba a la derecha de nuevo para pantallas de cuenta (toast-stack-top,
   ej. "Crear usuario"), igual que login. Cada contenedor apila varios
   toasts a la vez (uno debajo del otro) si se disparan casi juntos. */
.toast-stack, .toast-stack-top {
  position: fixed;
  z-index: 1200;
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: flex-end;
  pointer-events: none;
}
.toast-stack {
  top: calc(24px + env(safe-area-inset-top));
  right: calc(20px + env(safe-area-inset-right));
}
.toast-stack-top {
  top: calc(64px + env(safe-area-inset-top));
  right: calc(20px + env(safe-area-inset-right));
}

body.app-mode .toast-stack {
  top: calc(64px + env(safe-area-inset-top));
  right: auto;
  left: 50%;
  align-items: center;
  transform: translateX(-50%);
}

.toast-item {
  background: var(--main); color: #fff; padding: 11px 16px; border-radius: var(--radius-sm);
  font-size: calc(13px * var(--fs, 1)); font-weight: 600; box-shadow: var(--shadow);
  max-width: min(360px, calc(100vw - 40px));
  opacity: 0; transform: translateY(-8px);
  transition: opacity .18s var(--ease-out), transform .18s var(--ease-out);
  pointer-events: auto;
}
.toast-item.show { opacity: 1; transform: translateY(0); }
.toast-item.error { background: var(--danger); }
/* Los de éxito ya no llevan verde — se quedan con el azul de marca por
   defecto de .toast-item (var(--main)), para que se sientan más nativos
   de la app en vez de un semáforo genérico rojo/verde. */

.toast-item-undo {
  display: flex; align-items: center; gap: 12px; position: relative;
  padding-bottom: 14px; overflow: hidden; max-width: min(400px, calc(100vw - 40px));
}
.toast-undo-text { flex: 1; }
.toast-undo-btn {
  background: none; border: 1px solid rgba(255,255,255,.4); color: #fff; border-radius: var(--radius-sm);
  padding: 4px 10px; font-size: calc(12px * var(--fs, 1)); font-weight: 700; cursor: pointer; flex-shrink: 0;
}
@media (hover: hover) and (pointer: fine) { .toast-undo-btn:hover { background: rgba(255,255,255,.15); } }
.toast-undo-bar {
  position: absolute; left: 0; bottom: 0; height: 3px; width: 100%;
  background: rgba(255,255,255,.5); transform-origin: left;
  animation: toast-undo-shrink 3s linear forwards;
}
@keyframes toast-undo-shrink { from { transform: scaleX(1); } to { transform: scaleX(0); } }

/* Scan list (serialization) */

/* Barcode chip in tables/results */
.barcode-chip { display: inline-flex; align-items: center; background: #fff; border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 4px; }
.barcode-chip svg { display: block; }
/* Locaciones: buscador + "Imprimir todas" en una fila; en el modal de una
   locación, su código de barras junto al botón de imprimir la etiqueta. */
.loc-toolbar { display: flex; align-items: flex-end; gap: 12px; flex-wrap: wrap; margin-bottom: 14px; }
.loc-toolbar-search { flex: 1 1 260px; max-width: 360px; margin-bottom: 0; }
.loc-barcode-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 14px; }
.loc-barcode-row .btn svg { width: 15px; height: 15px; flex-shrink: 0; }

.product-result {
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  padding: 16px 0 6px; text-align: center;
}
.product-result .model { font-size: calc(13px * var(--fs, 1)); font-weight: 600; color: var(--text); }


/* ===== static/css/app/base/ventanas.css ===== */
/* ------------------------------------------------------------------ */
/* Stock modal (entrada/salida, caja registradora)                     */
/* ------------------------------------------------------------------ */
.modal-overlay {
  position: fixed; inset: 0; z-index: 1000;
  background: rgba(15, 26, 45, .55);
  /* Fondo borroso detrás de toda ventana (OT, producto, avisos…): de Spring Modal. */
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
}
.modal-card {
  background: var(--surface);
  border-radius: var(--radius);
  box-shadow: 0 24px 64px rgba(8, 16, 32, .35);
  width: 100%; max-width: 420px;
  max-height: 90vh; overflow-y: auto;
  padding: 22px;
}
.modal-card-wide { max-width: 560px; }
.modal-card-xwide { max-width: 760px; }
.modal-card-wo { max-width: 1400px; }

/* Título de sección dentro de un formulario largo (ej. Empleados) — debe
   distinguirse claramente tanto del título de la tarjeta como de las
   etiquetas de cada campo. */
.form-section-title {
  font-size: calc(15px * var(--fs, 1)); font-weight: 800; color: var(--accent-text);
  margin: 22px 0 12px; padding-bottom: 6px; border-bottom: 2px solid var(--secondary-light);
}
.form-section-title:first-of-type { margin-top: 2px; }

/* Popup de detalle de empleado */
.modal-title.emp-modal-name { font-size: calc(24px * var(--fs, 1)); font-weight: 800; color: var(--accent-text); }
.emp-detail-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 10px 20px; }
/* Variante compacta — valores cortos (Sí/No, un estatus, un número de
   días) que deben caber en una sola fila aunque haya varios. */
.emp-detail-grid-tight { grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); }

/* Lista de servicios externos de una orden, cuando hay más de uno */
.es-order-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 10px; }
.es-order-item { border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 8px 12px; background: var(--bg); }
.es-order-item-name { font-weight: 700; font-size: calc(13.5px * var(--fs, 1)); color: var(--text); margin-bottom: 3px; }
.es-order-item-contacts { font-size: calc(12px * var(--fs, 1)); color: var(--text-muted); }
.es-order-item-contact { margin-bottom: 5px; }
.es-order-item-contact:last-child { margin-bottom: 0; }
.es-order-item-contact-name { display: block; font-weight: 600; color: var(--text); }
.es-order-item-contact-meta { display: block; word-break: break-word; line-height: 1.4; }
.emp-detail-row { display: flex; flex-direction: column; gap: 2px; }
.emp-detail-label { font-size: calc(11px * var(--fs, 1)); color: var(--text-faint); }
.emp-detail-value { font-size: calc(14px * var(--fs, 1)); color: var(--text); font-weight: 600; }

/* Input con un prefijo visual fijo pegado a la izquierda (ej. "+504", "L") */
.input-prefix-group { display: flex; align-items: stretch; }
.input-prefix {
  display: flex; align-items: center; padding: 0 10px; background: var(--bg);
  border: 1px solid var(--border); border-right: none;
  border-radius: var(--radius-sm) 0 0 var(--radius-sm);
  font-size: calc(13px * var(--fs, 1)); color: var(--text-muted); font-weight: 700; white-space: nowrap;
}
.input-prefix-group input { border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }

/* Campo de contraseña con botón de "ojo" para mostrar/ocultar lo escrito */
.password-field-wrap { position: relative; }
.password-field-wrap input { width: 100%; padding-right: 40px; }
.password-toggle-btn {
  position: absolute; top: 0; right: 0; bottom: 0; width: 40px;
  display: flex; align-items: center; justify-content: center;
  background: none; border: none; padding: 0; cursor: pointer; color: var(--text-faint);
}
@media (hover: hover) and (pointer: fine) { .password-toggle-btn:hover { color: var(--text-muted); } }
.password-toggle-btn svg { width: 18px; height: 18px; }
.password-toggle-btn .eye-off-icon { display: none; }
.password-toggle-btn.showing .eye-icon { display: none; }
.password-toggle-btn.showing .eye-off-icon { display: block; }

/* Botón de "escanear con la cámara" junto a un campo de texto — mismo
   patrón que .password-field-wrap/.password-toggle-btn de arriba. */
.scan-camera-wrap { position: relative; }
.scan-camera-wrap input { width: 100%; padding-right: 38px; }
.scan-camera-btn {
  position: absolute; top: 0; right: 0; bottom: 0; width: 36px;
  display: flex; align-items: center; justify-content: center;
  background: none; border: none; padding: 0; cursor: pointer; color: var(--text-faint);
}
@media (hover: hover) and (pointer: fine) { .scan-camera-btn:hover { color: var(--secondary); } }
.scan-camera-btn svg { width: 18px; height: 18px; }
#camera-scan-region { min-height: 260px; border-radius: var(--radius-sm); overflow: hidden; background: #000; }
#camera-scan-region video { width: 100%; border-radius: var(--radius-sm); }
.confirm-overlay { z-index: 1100; }
.confirm-card { max-width: 380px; }
.confirm-message { color: var(--text-muted); font-size: calc(13.5px * var(--fs, 1)); line-height: 1.5; margin: 4px 0 18px; }
.modal-footer { display: flex; align-items: center; justify-content: flex-end; margin-top: 6px; }
/* Deslizar para guardar: al centro de la ventana (menos en la OT, que lleva Cancelar al lado). */
/* Botones del diálogo en una sola fila (en celular sí se acomodan en varias). */
.modal-footer.modal-footer-row { justify-content: flex-end; gap: 10px; flex-wrap: nowrap; }
.modal-footer.modal-footer-row > .btn { white-space: nowrap; }
@media (max-width: 560px) { .modal-footer.modal-footer-row { flex-wrap: wrap; } }
.modal-footer:has(> .slide-commit-host):not(.wo-edit-footer) { justify-content: center !important; gap: 10px; flex-wrap: wrap; }
.btn-send { display: inline-grid; place-items: center; flex: none; width: 46px; height: 46px; padding: 0; border-radius: 50%; }
.btn-with-icon { display: inline-flex; align-items: center; gap: 8px; }
.btn-with-icon svg { width: 16px; height: 16px; }
/* Vista de una orden: acciones de la orden a la izquierda; a la derecha WhatsApp y Editar, parejos. */
.wo-view-footer .wo-view-main-actions { display: flex; align-items: stretch; gap: 8px; }
.wo-view-footer .wo-view-main-actions .btn { height: 42px; min-width: 42px; }
.wo-view-footer #wo-view-edit-btn { padding: 0 22px; }
.btn-send svg { transition: transform .2s var(--ease-out); }
@media (hover: hover) and (pointer: fine) { .btn-send:hover svg { transform: translate(2px, -2px); } }
.wo-comment-composer { align-items: flex-end; }
.wo-comment-composer .btn-send { margin-bottom: 1px; }
.modal-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 16px; }
.modal-title { font-size: calc(17px * var(--fs, 1)); font-weight: 700; letter-spacing: -.01em; }
.modal-close {
  background: none; border: none; font-size: calc(22px * var(--fs, 1)); line-height: 1;
  color: var(--text-muted); cursor: pointer; padding: 2px 4px; flex-shrink: 0;
}
@media (hover: hover) and (pointer: fine) { .modal-close:hover { color: var(--text); } }
.copy-inline-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; margin-left: 6px; vertical-align: middle;
  background: none; border: none; border-radius: var(--radius-sm); cursor: pointer;
  color: var(--text-faint); padding: 0;
}
@media (hover: hover) and (pointer: fine) { .copy-inline-btn:hover { color: var(--accent-text); background: var(--secondary-light); } }
.copy-inline-btn svg { width: 14px; height: 14px; }
/* Variante chica — junto al código en tarjetas/filas (Kanban, Cuadrícula,
   Tabla), donde el botón de 22px del modal se ve desproporcionado. */
.copy-inline-btn-sm { width: 16px; height: 16px; margin-left: 4px; }
.copy-inline-btn-sm svg { width: 10px; height: 10px; }

/* Ícono de ayuda "?" junto al título de cada pestaña — ver helpIconHTML()/
   openHelpModal() en app.js. */
/* "?" y brújula del tour: azul principal con ícono blanco (2026-10-04). */
.help-btns { display: inline-flex; align-items: center; gap: 6px; margin-left: 10px; vertical-align: middle; }
.help-icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; flex-shrink: 0;
  border-radius: 50%; border: none; background: var(--main);
  color: #fff; font-size: calc(13.5px * var(--fs, 1)); font-weight: 800; line-height: 1;
  cursor: pointer; padding: 0; box-shadow: 0 1px 3px rgba(8, 67, 131, .25);
  transition: background .12s ease, transform .12s ease;
}
@media (hover: hover) and (pointer: fine) { .help-icon-btn:hover { background: var(--main-dark); transform: translateY(-1px); } }
.tour-icon-btn svg { width: 15px; height: 15px; }
.help-modal-card { max-width: 600px; }
.help-modal-body h4 { font-size: calc(14px * var(--fs, 1)); font-weight: 800; color: var(--accent-text); margin: 16px 0 6px; }
.help-modal-body h4:first-child { margin-top: 0; }
.help-modal-body p { font-size: calc(13.5px * var(--fs, 1)); color: var(--text-muted); line-height: 1.55; margin: 0 0 10px; }
.help-modal-body ul { margin: 0 0 10px; padding-left: 20px; display: flex; flex-direction: column; gap: 7px; }
.help-modal-body li { font-size: calc(13px * var(--fs, 1)); color: var(--text); line-height: 1.5; }
.help-tip {
  display: flex; gap: 9px; align-items: flex-start;
  background: var(--secondary-light); border-radius: var(--radius-sm);
  padding: 10px 12px; font-size: calc(12.5px * var(--fs, 1)); color: var(--text-muted); margin-top: 6px;
}
.help-tip svg { width: 16px; height: 16px; flex-shrink: 0; color: var(--secondary); margin-top: 1px; }

/* Movimiento de existencias — panel del producto (Magic UI: Number Ticker,
   Magic Card, Border Beam; ver inventario/productos.js). */
.stock-panel { margin-bottom: 20px; }
.stock-hero {
  position: relative; display: flex; align-items: center; justify-content: center; gap: 22px;
  padding: 18px 16px; border-radius: 14px; border: 1px solid var(--border);
  background: linear-gradient(180deg, var(--surface) 0%, var(--bg) 100%);
}
.stock-hero-col { text-align: center; min-width: 96px; }
.stock-hero-label { font-size: calc(11px * var(--fs, 1)); font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--text-muted); }
.stock-hero-num { font-size: calc(38px * var(--fs, 1)); font-weight: 800; letter-spacing: -.03em; color: var(--accent-text); font-variant-numeric: tabular-nums; line-height: 1.15; }
.stock-hero-unit { font-size: calc(12.5px * var(--fs, 1)); color: var(--text-muted); }
.stock-hero-arrow { color: var(--text-faint); display: grid; place-items: center; }
.stock-hero-arrow svg { width: 26px; height: 26px; }
.stock-hero-col.is-after .stock-hero-num { color: var(--text-faint); transition: color .25s ease; }
.stock-hero.is-live .stock-hero-col.is-after .stock-hero-num { color: var(--accent-text); }
.stock-hero-col.is-up .stock-hero-num { color: var(--success) !important; }
.stock-hero-col.is-down .stock-hero-num { color: #d97706 !important; }
.stock-hero-col.is-negative .stock-hero-num { color: var(--danger) !important; }
.stock-hero-meta { display: flex; justify-content: center; flex-wrap: wrap; gap: 6px 16px; font-size: calc(12.5px * var(--fs, 1)); color: var(--text-muted); margin: 8px 0 14px; }
/* Border Beam: un rayo de luz recorre el borde mientras hay un cambio pendiente. */
.stock-beam { position: absolute; inset: 0; border-radius: inherit; pointer-events: none; opacity: 0; transition: opacity .3s ease; overflow: hidden;
  border: 2px solid transparent; -webkit-mask: linear-gradient(transparent, transparent), linear-gradient(#000, #000); -webkit-mask-clip: padding-box, border-box; -webkit-mask-composite: xor;
  mask: linear-gradient(transparent, transparent), linear-gradient(#000, #000); mask-clip: padding-box, border-box; mask-composite: intersect; }
.stock-beam::after { content: ""; position: absolute; width: 90px; aspect-ratio: 1; offset-path: rect(0 auto auto 0 round 90px);
  background: linear-gradient(to left, #35a2db, #8b5cf6, transparent); animation: stock-beam 3.2s linear infinite; }
.stock-hero.is-live .stock-beam { opacity: 1; }
@keyframes stock-beam { from { offset-distance: 0%; } to { offset-distance: 100%; } }

.stock-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
/* Magic Card: borde con degradado que sigue al mouse + resplandor suave. */
.stock-card {
  --mx: -300px; --my: -300px; --c1: #16a34a; --c2: #86efac;
  position: relative; isolation: isolate; padding: 12px 14px 14px; border-radius: 12px; border: 1px solid transparent;
  background:
    linear-gradient(var(--surface), var(--surface)) padding-box,
    radial-gradient(160px circle at var(--mx) var(--my), var(--c1), var(--c2), var(--border) 100%) border-box;
}
.stock-card::before { content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; pointer-events: none;
  background: radial-gradient(180px circle at var(--mx) var(--my), color-mix(in srgb, var(--c1) 14%, transparent), transparent 100%); }
.stock-action-out { --c1: #dc2626; --c2: #fca5a5; }
.stock-card-head { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.stock-card-head label { margin: 0; font-size: calc(13px * var(--fs, 1)); font-weight: 700; color: var(--text); }
.stock-card-ico { display: grid; place-items: center; width: 26px; height: 26px; border-radius: 8px; color: #fff; background: var(--c1); }
.stock-card-ico svg { width: 15px; height: 15px; }
.stock-stepper { display: flex; align-items: stretch; gap: 8px; }
.stock-stepper input { flex: 1 1 auto; min-width: 0; text-align: center; font-size: calc(18px * var(--fs, 1)); font-weight: 700; padding: 8px 6px; font-variant-numeric: tabular-nums; }
.stock-step { flex: 0 0 38px; border-radius: 10px; border: 1px solid var(--border); background: var(--bg); color: var(--text); font-size: calc(20px * var(--fs, 1)); font-weight: 700; line-height: 1; cursor: pointer; transition: transform .15s var(--ease-out), background .15s ease; }
.stock-step:active { transform: scale(.92); }
@media (hover: hover) and (pointer: fine) { .stock-step:hover { background: var(--subtle-bg); } }
@media (max-width: 520px) { .stock-hero { gap: 12px; } .stock-hero-num { font-size: calc(30px * var(--fs, 1)); } .stock-actions { grid-template-columns: 1fr; } }
@media (prefers-reduced-motion: reduce) { .stock-beam::after { animation: none; } }

.no-spinner::-webkit-inner-spin-button,
.no-spinner::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.no-spinner { -moz-appearance: textfield; }


/* ===== static/css/app/ordenes/ordenes.css ===== */
/* ------------------------------------------------------------------ */
/* Órdenes de Trabajo                                                  */
/* ------------------------------------------------------------------ */

.wo-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 14px; }
/* La regla general ".card + .card" le ponía margen arriba a todas las fichas menos
   la primera, que por eso se veía más alta. En una cuadrícula el gap ya separa. */
.wo-grid > .card + .card { margin-top: 0; }
.wo-card { cursor: pointer; display: flex; flex-direction: column; min-height: 176px; min-width: 0; }
.wo-card-overdue {
  border-color: var(--danger-border); background: var(--danger-bg); border-left: 4px solid var(--danger);
  box-shadow: 0 1px 2px rgba(194,58,58,.1), 0 5px 16px rgba(194,58,58,.12);
}
.wo-card-overdue .wo-code { color: var(--danger); font-weight: 800; }
.wo-overdue-text { color: var(--danger); font-weight: 800; }
/* OT "En Espera": mismo formato que atrasada (arriba) pero en amarillo. */
.wo-card-onhold {
  border-color: var(--hold-border); background: var(--hold-bg); border-left: 4px solid var(--hold);
  box-shadow: 0 1px 2px rgba(242,194,0,.12), 0 5px 16px rgba(242,194,0,.16);
}
.wo-card-onhold .wo-code { color: var(--hold-text); font-weight: 800; }
.wo-onhold-text { color: var(--hold-text); font-weight: 800; }
.wo-hold-badge {
  display: inline-flex; align-items: center; align-self: flex-start; gap: 4px; margin: 4px 6px 4px 0;
  font-size: calc(11px * var(--fs, 1)); font-weight: 700; color: #3d2e00; background: var(--hold); border-radius: 999px; padding: 2px 8px;
}
/* Circulito amarillo con "!" — Calendario, leyenda y título del modal. */
.wo-hold-dot {
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 15px; height: 15px; border-radius: 50%; background: var(--hold); color: #3d2e00;
  font-size: calc(10.5px * var(--fs, 1)); font-weight: 900; line-height: 1; font-family: var(--font, inherit); cursor: default;
  vertical-align: middle; margin-left: 6px;
}
.wo-cal-legend-item .wo-hold-dot { margin-left: 0; width: 12px; height: 12px; font-size: calc(9px * var(--fs, 1)); }
.wo-modal-title .wo-hold-dot { width: 20px; height: 20px; font-size: calc(13px * var(--fs, 1)); margin-left: 8px; }
.wo-hold-note {
  background: var(--hold-bg); border: 1px solid var(--hold-border); border-left: 4px solid var(--hold);
  border-radius: var(--radius-sm); padding: 10px 12px; margin-bottom: 10px;
}
.wo-hold-note-head { display: flex; align-items: center; gap: 6px; font-weight: 800; color: var(--hold-text); font-size: calc(13px * var(--fs, 1)); }
.wo-hold-note-head .wo-hold-dot { margin-left: 0; }
.wo-hold-note-reason { margin-top: 4px; color: var(--text); white-space: pre-wrap; overflow-wrap: anywhere; }
.wo-hold-note-meta { margin-top: 4px; font-size: calc(11.5px * var(--fs, 1)); color: var(--text-muted); }
/* "Orden sin movimiento" — ver isWorkOrderStale()/woStaleBadgeHTML() en
   app.js. Azul secundario (no rojo/ámbar) a propósito: no es un error como
   "atrasada", solo una señal de que nadie la ha tocado en varios días.
   margin simétrico (no solo margin-top) para que quede centrado entre el
   texto de arriba y el de abajo en Kanban/Cuadrícula, en vez de pegado
   hacia abajo. align-self:flex-start porque .wo-card (Cuadrícula) es un
   flex column con el stretch por defecto — sin esto el badge se estira al
   ancho completo de la tarjeta en vez de quedar como una píldora chica
   igual que en Kanban. */
.wo-stale-badge {
  display: inline-flex; align-items: center; align-self: flex-start; gap: 4px; margin: 4px 0;
  font-size: calc(11px * var(--fs, 1)); font-weight: 700; color: var(--accent-text);
  background: var(--secondary-light); border-radius: 999px; padding: 2px 8px;
}

.wo-header-actions { align-items: center; gap: 10px; }
.wo-new-col { display: flex; flex-direction: column; gap: 6px; }
.wo-new-col .btn { width: 100%; justify-content: center; }

/* Tablero "Hoy" */
.wo-today-card { max-width: 640px; width: 100%; max-height: 86vh; overflow-y: auto; overflow-x: hidden; }
.wo-today-group { margin-bottom: 14px; }
.wo-today-group-head { display: flex; align-items: center; justify-content: space-between; font-size: calc(12px * var(--fs, 1)); font-weight: 800; text-transform: uppercase; letter-spacing: .05em; padding: 6px 8px; border-radius: var(--radius-sm); margin-bottom: 4px; }
.wo-today-late .wo-today-group-head { color: var(--danger, #b23b3b); background: color-mix(in srgb, var(--danger, #b23b3b) 12%, transparent); }
.wo-today-now .wo-today-group-head { color: var(--accent-text); background: var(--secondary-light); }
.wo-today-next .wo-today-group-head { color: var(--text-muted); background: var(--bg); }
.wo-today-count { font-variant-numeric: tabular-nums; }
.wo-today-row { display: flex; align-items: center; gap: 10px; padding: 9px 6px; border-bottom: 1px solid var(--row-border); cursor: pointer; border-radius: var(--radius-sm); }
@media (hover: hover) and (pointer: fine) { .wo-today-row:hover { background: var(--bg); } }
.wo-today-main { flex: 1; min-width: 0; }
.wo-today-main > div { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wo-today-side { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; flex-shrink: 0; }
.wo-today-when { font-size: calc(11.5px * var(--fs, 1)); font-weight: 700; color: var(--text-muted); }
.wo-today-late .wo-today-when { color: var(--danger, #b23b3b); }
.btn-row-divider { width: 1px; height: 22px; background: var(--border); flex-shrink: 0; }
/* En celular los botones de la cabecera se parten en dos líneas y el
   divisor quedaba solito al inicio de la segunda. */
@media (max-width: 640px) { .btn-row-divider { display: none; } }
.view-toggle { display: inline-flex; border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden; }
.view-toggle-btn {
  background: var(--surface); border: none; padding: 9px 16px; font-size: calc(13px * var(--fs, 1)); font-weight: 600;
  cursor: pointer; color: var(--text-muted);
}
.view-toggle-btn + .view-toggle-btn { border-left: 1px solid var(--border); }
.view-toggle-btn.active { background: var(--main); color: #fff; }

.view-wide { max-width: none; }
/* Dentro de una .view-wide, la mayoría del contenido (título, tabs,
   formularios, tarjeta de filtro) debe seguir viéndose angosto y
   centrado como antes — solo la tabla/grid donde realmente aparecen los
   productos debe usar el ancho completo. */
.narrow-block { max-width: 1180px; margin-left: auto; margin-right: auto; }

/* Vista de Calendario (Órdenes de Trabajo) */
.wo-cal-head { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; flex-wrap: wrap; }
.wo-cal-month-label { font-size: calc(16px * var(--fs, 1)); font-weight: 800; color: var(--text); text-transform: capitalize; min-width: 150px; text-align: center; }
/* minmax(0, 1fr), NO 1fr: con 1fr cada columna no puede ser más angosta que
   el nombre de cliente más largo de ese día (texto nowrap = su ancho
   completo), así que en celular o ventanas angostas el calendario se
   ensanchaba más que la pantalla y toda la página quedaba con scroll
   horizontal (y el menú/barra superior se descuadraban al moverla). Así las
   7 columnas siempre caben y los nombres se recortan con "…". */
.wo-cal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 6px; }
.wo-cal-dow-row { margin-bottom: 4px; }
.wo-cal-dow { text-align: center; font-size: calc(11px * var(--fs, 1)); font-weight: 700; color: var(--text-faint); text-transform: uppercase; padding: 4px 0; }
.wo-cal-cell {
  min-width: 0; min-height: 104px; border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 6px; display: flex; flex-direction: column; gap: 4px; background: var(--surface);
}
.wo-cal-cell-other { background: var(--bg); border-style: dashed; opacity: .5; }
.wo-cal-cell-today { border-color: var(--accent-text); border-width: 2px; }
.wo-cal-daynum { font-size: calc(12px * var(--fs, 1)); font-weight: 700; color: var(--text-muted); }
.wo-cal-cell-today .wo-cal-daynum { color: var(--accent-text); }
.wo-cal-chips { display: flex; flex-direction: column; gap: 3px; overflow: hidden; }
.wo-cal-chip {
  display: flex; align-items: center; min-width: 0;
  font-size: calc(11px * var(--fs, 1)); font-weight: 600; padding: 2px 6px; border-radius: 4px; cursor: pointer;
  background: var(--subtle-bg);
  background: color-mix(in srgb, var(--chip-accent, var(--text-faint)) 16%, var(--surface));
  color: var(--chip-accent, var(--text-muted)); border-left: 3px solid var(--chip-accent, var(--text-faint));
  overflow: hidden; white-space: nowrap;
}
.wo-cal-chip-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.wo-cal-chip .wo-hold-dot { width: 13px; height: 13px; font-size: calc(9px * var(--fs, 1)); margin-left: 4px; }
@media (hover: hover) and (pointer: fine) { .wo-cal-chip:hover { filter: brightness(1.12); } }
.wo-cal-chip-overdue { box-shadow: 0 0 0 1px var(--danger) inset; }
.wo-cal-more { font-size: calc(10.5px * var(--fs, 1)); font-weight: 700; color: var(--text-faint); cursor: pointer; padding: 1px 6px; }
@media (hover: hover) and (pointer: fine) { .wo-cal-more:hover { color: var(--accent-text); text-decoration: underline; } }

.wo-cal-legend { display: flex; flex-wrap: wrap; gap: 6px 16px; margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border); }
.wo-cal-legend-item { display: flex; align-items: center; gap: 6px; font-size: calc(12px * var(--fs, 1)); color: var(--text-muted); }
.wo-cal-legend-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; }
.wo-cal-legend-overdue-swatch { background: transparent; box-shadow: 0 0 0 2px var(--danger) inset; }

.wo-cal-day-list { display: flex; flex-direction: column; gap: 2px; max-height: 360px; overflow-y: auto; }
.wo-cal-day-item { display: flex; align-items: center; gap: 10px; padding: 9px 6px; border-bottom: 1px solid var(--row-border); cursor: pointer; border-radius: var(--radius-sm); }
@media (hover: hover) and (pointer: fine) { .wo-cal-day-item:hover { background: var(--bg); } }
.wo-cal-day-item:last-child { border-bottom: none; }
.wo-cal-chip-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; }
.wo-cal-day-item-client { font-weight: 700; font-size: calc(13px * var(--fs, 1)); color: var(--text); }
.wo-cal-day-item-meta { font-size: calc(11.5px * var(--fs, 1)); color: var(--text-muted); }

@media (max-width: 860px) {
  .wo-cal-cell { min-height: 66px; padding: 4px; }
  .wo-cal-chip .wo-hold-dot { width: 11px; height: 11px; font-size: calc(8px * var(--fs, 1)); margin-left: 2px; }
  .wo-cal-daynum { font-size: calc(11px * var(--fs, 1)); }
  .wo-cal-chip { font-size: calc(9.5px * var(--fs, 1)); padding: 1px 4px; }
  .wo-cal-month-label { min-width: 0; font-size: calc(14px * var(--fs, 1)); }
  .wo-cal-grid { gap: 3px; }
}

/* Pantalla de bienvenida (Home) al iniciar la app */
.home-welcome {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; height: 100%; min-height: calc(100dvh - 200px); gap: 6px;
}
.home-welcome-logo { width: 100%; max-width: 220px; height: auto; margin-bottom: 18px; }
.home-welcome-title { font-size: calc(24px * var(--fs, 1)); font-weight: 700; color: var(--text); }
.home-welcome-sub { font-size: calc(14px * var(--fs, 1)); color: var(--text-muted); }
.home-birthdays-card { width: 100%; max-width: 640px; margin-top: 14px; text-align: left; }

@media (max-width: 560px) {
  .upcoming-date-row { flex-wrap: wrap; row-gap: 2px; }
  .upcoming-date-detail { flex: 1 1 100%; order: 3; }
}

/* Menu de filtros de Ordenes de Trabajo: se queda fijo al hacer scroll,
   en las 4 vistas (Kanban, Lista, Tabla, Calendario). El offset coincide con
   el espacio reservado arriba de .main para no taparse con la campana/chip
   de usuario. z-index 17 (por encima del 16 de .kanban-header-row): el
   popover de "Filtros" vive DENTRO de esta tarjeta, así que su z-index
   propio solo cuenta dentro de ella — con 15 el menú salía detrás de los
   títulos de estatus del Kanban. */
#wo-filters-card { position: sticky; top: var(--content-top-offset); z-index: 17; margin-bottom: 14px; }
/* Filtro fijo como "punto de escondite": cuando ya quedó pegado arriba
   (.is-stuck, lo pone stickyShield() en ordenes/comunes.js), una sombra
   enorme del color del fondo tapa la franja de ARRIBA del menú (y los 14px
   de abajo), así las filas/fichas desaparecen al pasar por debajo en vez de
   verse encima. Es box-shadow (no un bloque ancho) para no crear scroll
   horizontal; clip-path la recorta a la franja y a lo ancho del contenido
   (--shield-l/--shield-r en px, sin tapar el menú lateral). La primera
   sombra es la de siempre de la tarjeta, que así queda encima. */
.sticky-shield.is-stuck::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  border-radius: inherit;
  box-shadow: var(--shadow), 0 0 0 100vmax var(--bg);
  clip-path: inset(calc(-1 * var(--content-top-offset) - 2px) calc(-1 * var(--shield-r, 0px)) -14px calc(-1 * var(--shield-l, 0px)));
}
#wo-table-view-scroll { max-height: 960px; }
/* Sin esto, filtrar a pocos (o cero) resultados en Tabla/Calendario podía
   encoger tanto la página que el navegador recorta el scroll automático a
   la nueva altura máxima — un salto brusco hacia arriba que hacía sentir
   que el menú "fijo" de arriba en realidad se movía con la página. */
#wo-results { min-height: 100vh; }
/* En Kanban las columnas ya tienen un alto fijo (resizeKanbanColumns), así
   que filtrar no cambia el alto de la página y el min-height no hace falta.
   En celular sobraba: dejaba bajar la página de más y las columnas se
   metían detrás de los títulos pegados, mostrando solo un pedazo. */
@media (max-width: 768px) { #wo-results.wo-results-kanban { min-height: 0; } }
/* Mismo criterio en Productos: la barra de búsqueda se queda fija arriba en
   ambas vistas (Tabla y Grid). */
#products-filter-card { position: sticky; top: var(--content-top-offset); z-index: 15; margin-bottom: 14px; }
#products-grid-wrap { min-height: 60vh; }

/* Vista Grid de Productos — una sección colapsable por categoría; la foto
   se ve directo en la tarjeta (sin clic), a diferencia del modal de foto de
   Empleados/Usuarios que si exige un clic. */
.product-grid-sections { display: flex; flex-direction: column; gap: 4px; }
.product-grid-section + .product-grid-section { border-top: 1px solid var(--border); padding-top: 10px; margin-top: 6px; }
.product-grid-section-head {
  display: flex; align-items: center; gap: 8px; width: 100%; padding: 8px 4px; color: var(--text);
}
.product-grid-section-toggle {
  display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0;
  background: none; border: none; cursor: pointer; text-align: left; color: inherit; padding: 0;
}
.product-grid-section-chevron { transition: transform .15s var(--ease-out); font-size: calc(11px * var(--fs, 1)); color: var(--text-faint); }
.product-grid-section-chevron.collapsed { transform: rotate(-90deg); }
.product-grid-section-title { font-weight: 700; font-size: calc(14px * var(--fs, 1)); }
.product-grid-section-count {
  background: var(--bg); border: 1px solid var(--border); border-radius: 999px;
  padding: 1px 8px; font-size: calc(11.5px * var(--fs, 1)); color: var(--text-muted); margin-left: 2px;
}
.product-grid-section-body:not([hidden]) {
  display: grid; gap: 14px; padding: 10px 4px 4px;
  /* Máximo 8 tarjetas por fila: el mínimo de cada columna es lo que
     necesitarían 8 columnas iguales, así auto-fill nunca mete una 9na,
     pero sigue bajando a menos columnas (más anchas) en pantallas
     angostas — nunca menos de 130px de ancho por tarjeta. */
  grid-template-columns: repeat(auto-fill, minmax(max(130px, calc((100% - 7 * 14px) / 8)), 1fr));
}
.product-grid-card {
  border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden;
  cursor: pointer; background: var(--surface); transition: box-shadow .15s ease, border-color .15s ease;
}
@media (hover: hover) and (pointer: fine) { .product-grid-card:hover { box-shadow: var(--shadow); border-color: var(--main); } }
.product-grid-photo {
  width: 100%; aspect-ratio: 1 / 1; background: var(--bg); display: flex; align-items: center;
  justify-content: center; overflow: hidden;
}
.product-grid-photo img { width: 100%; height: 100%; object-fit: cover; }
.product-grid-photo-placeholder { font-size: calc(26px * var(--fs, 1)); color: var(--text-faint); }
.product-grid-body { padding: 8px 10px 10px; }
.product-grid-name { font-weight: 700; font-size: calc(13px * var(--fs, 1)); line-height: 1.3; margin-bottom: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.product-grid-code { font-size: calc(11px * var(--fs, 1)); color: var(--text-faint); margin-bottom: 4px; }
.product-grid-meta { display: flex; justify-content: space-between; font-size: calc(12px * var(--fs, 1)); color: var(--text-muted); margin-bottom: 2px; }
.product-grid-location { font-size: calc(11.5px * var(--fs, 1)); color: var(--text-faint); }

/* Mantenimiento (V24) — tarjetas más grandes que las de Productos (esas son
   miniaturas de catálogo; acá cada tarjeta es una máquina/vehículo/equipo
   individual, la foto debe verse bien, no solo como referencia rápida). */
.maint-grid {
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
.maint-card {
  border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden;
  cursor: pointer; background: var(--surface); transition: box-shadow .15s ease, border-color .15s ease;
}
@media (hover: hover) and (pointer: fine) { .maint-card:hover { box-shadow: var(--shadow); border-color: var(--main); } }
.maint-card-photo {
  width: 100%; aspect-ratio: 4 / 3; background: var(--bg); display: flex; align-items: center;
  justify-content: center; overflow: hidden;
}
.maint-card-photo img { width: 100%; height: 100%; object-fit: cover; }
.maint-card-photo-placeholder { font-size: calc(34px * var(--fs, 1)); color: var(--text-faint); }
.maint-card-body { padding: 10px 12px 12px; }
.maint-card-title { font-weight: 700; font-size: calc(14px * var(--fs, 1)); line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.maint-card-subtitle { font-size: calc(12px * var(--fs, 1)); color: var(--text-muted); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Datos de una instancia de Mantenimiento (Nombre/Modelo/Placa/...) como
   tags en una fila, en vez de una tabla de dos columnas — más limpio para
   3-4 datos cortos. */
.maint-field-tags { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin-bottom: var(--gap-md); }
.maint-field-tag {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--bg); border: 1px solid var(--border); border-radius: 999px;
  padding: 6px 12px; font-size: calc(12.5px * var(--fs, 1)); line-height: 1.3;
}
.maint-field-tag-label { font-weight: 700; color: var(--text-muted); }
.maint-field-tag-value { color: var(--text); }

/* ===== static/css/app/ordenes/filtros-y-kanban.css ===== */
/* Órdenes: barra de filtros, Kanban, grupos y stacks. El orden en APP_CSS_ORDER (jp/routes/pages.py) es la cascada. */

/* Barra de filtros de Órdenes — una sola fila compacta en las 4 vistas.
   Cliente/Grupo/Usuario/Estatus/Mes viven en un popover aparte (no en la
   fila) para que la altura de la barra nunca dependa de cuántos campos
   aplican a cada vista — así las 4 vistas miden exactamente lo mismo y la
   fila nunca necesita más de una línea salvo en pantallas muy angostas. */
.wo-filters-card { padding: 10px 14px; }
.wo-filters-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.wo-filters-search { flex: 1 1 110px; max-width: 480px; }
.wo-filters-search input { width: 100%; height: 33px; }
.wo-filters-popover-wrap { position: relative; flex-shrink: 0; }
.wo-filters-toggle-btn { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.wo-filter-count-badge:not([hidden]) {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 17px; height: 17px; padding: 0 4px; border-radius: 999px;
  background: var(--main); color: #fff; font-size: calc(10.5px * var(--fs, 1)); font-weight: 700; line-height: 1;
}
.wo-filters-popover:not([hidden]) {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 20;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: 14px; width: 260px;
  display: flex; flex-direction: column; gap: 10px;
}
/* Filtro "Entrega desde/hasta" (solo Kanban y Cuadrícula) — dos selectores
   de fecha apilados dentro del popover de Filtros. */
.wo-due-filter { display: flex; flex-direction: column; gap: 10px; }
.wo-due-filter .field { margin-bottom: 0; }
.wo-filters-overdue { flex-shrink: 0; white-space: nowrap; height: 38px; }
.wo-filters-actions { flex-shrink: 0; flex-wrap: nowrap; }
@media (max-width: 480px) {
  /* Misma especificidad que ".wo-filters-popover:not([hidden])" de arriba
     (una clase + un pseudo-selector) — si no, esa regla base gana sin
     importar el orden ni el media query, y este ajuste nunca se aplica.
     `position: fixed` + posición relativa al viewport (no al botón que lo
     abre) porque el botón "Filtros" no siempre queda cerca del borde
     derecho — anclarlo con `right: 0` a SU PROPIO contenedor lo mandaba
     fuera de la pantalla por la izquierda (mismo tipo de bug que el buscador
     global y las notificaciones, ver esas reglas más arriba). */
  .wo-filters-popover:not([hidden]) {
    /* `top` se fija por JS al abrirlo (ver wo-filters-toggle-btn en app.js)
       porque acá sí depende de dónde esté el botón en la pantalla en ese
       momento — pero izquierda/derecha quedan fijas al viewport siempre. */
    position: fixed; left: calc(12px + env(safe-area-inset-left));
    right: calc(12px + env(safe-area-inset-right)); width: auto; max-width: none;
  }
}

.kanban-scroll-mirror { overflow-x: auto; overflow-y: hidden; height: 16px; margin-bottom: 6px; }
/* Barra + botones ‹ › para moverse de lado (2026-10-13). La barra lleva estilo
   propio para que SIEMPRE se vea (las barras "superpuestas" de Windows/Edge
   solo aparecían al pasar el mouse y un usuario no encontraba cómo moverse). */
.kanban-nav { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.kanban-nav .kanban-scroll-mirror { flex: 1; min-width: 0; margin: 0; height: 14px; scrollbar-width: auto; scrollbar-color: color-mix(in srgb, var(--main) 55%, transparent) color-mix(in srgb, var(--text) 8%, transparent); }
.kanban-nav .kanban-scroll-mirror::-webkit-scrollbar { height: 12px; }
.kanban-nav .kanban-scroll-mirror::-webkit-scrollbar-track { background: color-mix(in srgb, var(--text) 7%, transparent); border-radius: 999px; }
.kanban-nav .kanban-scroll-mirror::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--main) 55%, transparent); border-radius: 999px; border: 2px solid transparent; background-clip: padding-box; }
/* Celular: la barra de 12px casi no se agarra con el dedo; más gruesa. */
@media (pointer: coarse), (max-width: 760px) {
  .kanban-nav .kanban-scroll-mirror { height: 30px; }
  .kanban-nav .kanban-scroll-mirror::-webkit-scrollbar { height: 28px; }
  .kanban-nav .kanban-scroll-mirror::-webkit-scrollbar-thumb { border-width: 3px; min-width: 64px; }
}
.kanban-nav-btn { flex: none; width: 34px; height: 34px; border-radius: 50%; border: 1px solid var(--border); background: var(--surface); color: var(--text); display: grid; place-items: center; cursor: pointer; box-shadow: var(--shadow); transition: transform .15s var(--ease-out), opacity .15s var(--ease-out), border-color .15s var(--ease-out); }
.kanban-nav-btn svg { width: 18px; height: 18px; }
.kanban-nav-btn:active:not(:disabled) { transform: scale(.92); }
.kanban-nav-btn:disabled { opacity: .35; cursor: default; box-shadow: none; }
@media (hover: hover) and (pointer: fine) {
  .kanban-nav-btn:hover:not(:disabled) { border-color: var(--main); color: var(--main); }
  .kanban-board { cursor: grab; }
  .kanban-board button, .kanban-board select { cursor: pointer; }
}
.kanban-board.is-panning, .kanban-board.is-panning * { cursor: grabbing !important; user-select: none; }
@media (pointer: coarse) { .kanban-nav-btn { display: none; } }
.kanban-scroll-mirror-inner { height: 1px; }
/* Los títulos de columna viven en una fila APARTE (.kanban-header-row),
   hermana de .kanban-board en vez de estar dentro de cada .kanban-col — así
   se puede volver esta fila sticky RESPECTO A LA PÁGINA (igual que
   #wo-filters-card) sin pelear con .kanban-board, que necesita su propio
   overflow-x:auto para el scroll horizontal entre columnas y por lo tanto
   (aunque solo se declare overflow-x) siempre termina siendo el contenedor
   de referencia para cualquier `position: sticky` de SUS descendientes — si
   el título estuviera adentro, quedaría pegado al scroll del board en vez
   del de la página. El `top` de esta fila se fija por JS
   (positionKanbanHeaderRow) al alto real de #wo-filters-card, que puede
   cambiar (una o dos líneas según el ancho de pantalla), y su scroll
   horizontal se sincroniza con .kanban-board por JS. */
.kanban-header-row { position: sticky; z-index: 16; overflow: hidden; background: var(--bg); margin-bottom: 10px; }
.kanban-header-row-inner { display: flex; gap: 18px; width: max-content; }
.kanban-board { display: flex; gap: 18px; overflow-x: auto; padding: 2px 2px 16px; align-items: flex-start; }
/* Scroll horizontal fluido: los títulos se mueven con una animación ligada al
   scroll del tablero (en la tarjeta gráfica, sin esperar a JS), y las fichas
   que no se ven no se dibujan (content-visibility). */
@supports (animation-timeline: --kb) {
  :has(> .kanban-board) { timeline-scope: --kb; }
  .kanban-board { scroll-timeline: --kb x; }
  .kanban-header-row.kb-linked .kanban-header-row-inner { animation: kb-follow linear both; animation-timeline: --kb; will-change: transform; }
}
@keyframes kb-follow { from { transform: translateX(0); } to { transform: translateX(calc(-1px * var(--kb-max, 0))); } }
.kanban-col-body .kanban-card { content-visibility: auto; contain-intrinsic-size: auto 170px; }
/* La altura (no max-height) se fija por JS (resizeKanbanColumns) al espacio
   real que queda debajo de .kanban-header-row — TODAS las columnas quedan a
   esa misma altura exacta sin importar cuántas órdenes tenga cada una (un
   max-height dejaría a las columnas con pocas órdenes más cortas que las
   demás). Cada columna scrollea sus propias tarjetas por dentro
   (.kanban-col-body) en vez de crecer sin límite; así no hay que scrollear
   media pantalla para ver "Diseño" solo porque "Cotización" tiene 28
   órdenes, y el resaltado de "drag-over" (ver abajo) cubre el mismo área en
   cualquier columna, tenga 2 órdenes o 28. */
.kanban-col { flex: 0 0 310px; background: var(--bg); border-radius: var(--radius); display: flex; flex-direction: column; }
.kanban-col-head {
  flex: 0 0 310px; display: flex; align-items: center; justify-content: space-between; padding: 14px 14px 10px;
  background: var(--bg); border-radius: var(--radius); border-top: 4px solid var(--accent, var(--text-faint));
}
.kanban-col-title { font-size: calc(14.5px * var(--fs, 1)); font-weight: 800; letter-spacing: -.01em; color: var(--accent, var(--text)); }
.kanban-col-count {
  font-size: calc(11px * var(--fs, 1)); color: var(--text-muted); font-weight: 700; background: var(--surface);
  border-radius: 999px; padding: 2px 8px; flex-shrink: 0;
}
.kanban-col-body {
  padding: 10px 12px 12px; overflow-y: auto; flex: 1; display: flex; flex-direction: column; gap: 10px;
  min-height: 90px; transition: background .12s ease; border-radius: var(--radius-sm);
}
.kanban-col-body.drag-over {
  background: var(--secondary-light);
  outline: 2px dashed var(--secondary);
  outline-offset: -4px;
}
.kanban-card {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 13px 14px; cursor: grab; box-shadow: var(--shadow);
}
.kanban-card.wo-card-overdue {
  border-color: var(--danger-border); background: var(--danger-bg); border-left: 4px solid var(--danger);
  box-shadow: 0 1px 2px rgba(194,58,58,.1), 0 5px 16px rgba(194,58,58,.12);
}
.kanban-card.wo-card-overdue .kanban-card-code { color: var(--danger); font-weight: 800; }
.kanban-card.wo-card-onhold {
  border-color: var(--hold-border); background: var(--hold-bg); border-left: 4px solid var(--hold);
  box-shadow: 0 1px 2px rgba(242,194,0,.12), 0 5px 16px rgba(242,194,0,.16);
}
.kanban-card.wo-card-onhold .kanban-card-code { color: var(--hold-text); font-weight: 800; }
.kanban-card:active { cursor: grabbing; }
.kanban-card.dragging { opacity: .4; }
.kanban-card-code { font-family: var(--mono); font-size: calc(10.5px * var(--fs, 1)); color: var(--text-faint); font-weight: 700; margin-bottom: 4px; }
/* Ícono de "grupo de OT" — mismo botón redondo en Kanban, Cuadrícula, Tabla
   y el modal de detalle de una orden; abre el visor del grupo (ver
   openWorkOrderGroupModal). Ícono de capas apiladas en vez de un efecto de
   sombra "apilada" sobre la tarjeta misma — ese efecto choca con el
   box-shadow que .kanban-card ya usa para overdue/drag, y un ícono claro es
   más confiable entre vistas que un truco de CSS por tarjeta. */
.wo-group-badge {
  display: inline-flex; align-items: center; justify-content: center; vertical-align: middle;
  width: 18px; height: 18px; margin-left: 6px; padding: 0; border-radius: 50%; flex-shrink: 0;
  background: var(--secondary-light); color: var(--secondary); border: none; cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .wo-group-badge:hover { background: var(--secondary); color: #fff; } }
.wo-group-badge svg { width: 11px; height: 11px; }
.wo-group-selection-bar {
  display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
  padding: 10px 14px; margin-bottom: 12px; background: var(--secondary-light);
  border-radius: var(--radius-sm); font-size: calc(13px * var(--fs, 1)); font-weight: 600;
}
/* "Stack" de tarjetas — cuando 2+ órdenes del mismo grupo caen en la misma
   columna del Kanban o en la Cuadrícula, se colapsan (ver collapseWoGroups
   en app.js) en una sola tarjeta con este efecto de cartas apiladas y un
   contador arriba a la derecha que reemplaza el ícono normal de grupo. Clic
   en cualquier parte de la tarjeta abre el grupo completo.
   El asomo es un pedacito angosto del BORDE inferior de cada tarjeta "de
   atrás" (alto fijo de unos 6px, no toda la tarjeta duplicada) — mucho más
   liviano y prolijo que un fantasma de la tarjeta completa, y cada capa
   siguiente se angosta un poco más para dar sensación de perspectiva/
   abanico. Sale solo hacia abajo, nunca a los lados, y con tan pocos px le
   sobra espacio dentro del gap normal entre tarjetas — el tamaño de la
   tarjeta y la separación entre fichas quedan intactos. */
.wo-stack-card { position: relative; z-index: 0; cursor: pointer; }
.wo-stack-card::before, .wo-stack-card::after {
  content: ""; position: absolute; bottom: -5px; height: 6px;
  border: 1px solid var(--border); border-top: none;
  border-radius: 0 0 var(--radius) var(--radius);
  background: var(--bg);
}
.wo-stack-card::before { left: 8px; right: 8px; z-index: -1; }
.wo-stack-card::after { left: 15px; right: 15px; bottom: -9px; opacity: .7; z-index: -2; }
.wo-stack-count {
  position: absolute; top: -8px; right: -8px; z-index: 2;
  display: inline-flex; align-items: center; justify-content: center; gap: 3px;
  min-width: 24px; height: 22px; padding: 0 7px; border-radius: 11px;
  background: var(--secondary); color: #fff; font-size: calc(11px * var(--fs, 1)); font-weight: 800;
  border: 2px solid var(--surface); box-shadow: 0 1px 3px rgba(0,0,0,.18); cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .wo-stack-count:hover { filter: brightness(1.12); } }

/* Fila "padre" desplegable de un grupo en vista Tabla/Panel de OT — ver
   woTableGroupRowHTML/otpTableGroupRowHTML en app.js. */
.wo-group-row { cursor: pointer; background: var(--secondary-light); font-weight: 700; }
@media (hover: hover) and (pointer: fine) { .wo-group-row:hover { background: var(--secondary-light); filter: brightness(0.97); } }
.wo-group-row-chevron {
  display: inline-flex; align-items: center; justify-content: center; vertical-align: middle;
  width: 18px; height: 18px; margin-right: 4px; padding: 0; border: none; background: none;
  color: var(--secondary); cursor: pointer; transition: transform .15s ease;
}
.wo-group-row-chevron svg { width: 14px; height: 14px; }
.wo-group-row-chevron.expanded { transform: rotate(90deg); }
.wo-table-child-row td:first-child { padding-left: 32px; }
.wo-table-child-row { background: var(--bg); }
.kanban-card-title { font-weight: 700; font-size: calc(13.5px * var(--fs, 1)); margin-bottom: 4px; }
.kanban-card-desc {
  font-size: calc(12.5px * var(--fs, 1)); color: var(--text-muted); margin-bottom: 8px; line-height: 1.4;
  overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.kanban-card-due { font-size: calc(11.5px * var(--fs, 1)); color: var(--text-faint); margin-bottom: 8px; }
.kanban-card-due.overdue-text { color: var(--danger); font-weight: 800; }
.kanban-card-due.onhold-text { color: var(--hold-text); font-weight: 800; }
/* Celular/tablet: arrastrar tarjetas (drag & drop HTML5) no funciona con el
   dedo, así que en pantallas táctiles cada tarjeta trae su propio selector
   de estatus (el mismo de Cuadrícula). Con mouse sigue oculto: se arrastra. */
.kanban-card-status { display: none; }
@media (pointer: coarse) {
  .kanban-card-status { display: inline-block; margin: 6px 0 2px; max-width: 100%; }
}
.kanban-empty { text-align: center; color: var(--text-faint); font-size: calc(11.5px * var(--fs, 1)); padding: 20px 8px; }
.wo-card .assignee-list { margin-top: auto; padding-top: 8px; }
.wo-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; margin-bottom: 6px; }
.wo-code { font-family: var(--mono); font-size: calc(12px * var(--fs, 1)); color: var(--text-faint); font-weight: 700; }
.wo-desc { color: var(--text-muted); font-size: calc(13px * var(--fs, 1)); margin: 6px 0 10px; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.wo-meta { display: flex; flex-wrap: wrap; gap: 6px 14px; font-size: calc(12px * var(--fs, 1)); color: var(--text-faint); margin-bottom: 10px; }
.wo-meta strong { color: var(--text-muted); font-weight: 600; }

.assignee-list { display: flex; flex-wrap: wrap; gap: 6px; }
.wo-readonly {
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 9px 11px; font-size: calc(13.5px * var(--fs, 1)); color: var(--text); white-space: pre-wrap;
}
.wo-modal-title { font-size: calc(21px * var(--fs, 1)); font-weight: 800; color: var(--accent-text); }
.textarea-autosize { resize: none; overflow: hidden; }

.product-photo-large {
  width: 100%; height: 260px; border-radius: var(--radius-sm); overflow: hidden;
  background: var(--bg); border: 1px solid var(--border); cursor: zoom-in;
  display: flex; align-items: center; justify-content: center;
}
.product-photo-large img { width: 100%; height: 100%; object-fit: contain; display: block; }
.product-photo-large.empty { cursor: default; color: var(--text-faint); font-size: calc(13px * var(--fs, 1)); }

/* ===== static/css/app/ordenes/ficha-y-campos.css ===== */
/* Órdenes: mapa, fotos, campos de la ventana y selección múltiple. El orden en APP_CSS_ORDER (jp/routes/pages.py) es la cascada. */

/* "Ubicación" de una OT: mapa de Google a todo el ancho del modal, con el
   botón "¿Cómo llegar?" encima. width:100% + min-width:0 para que nunca
   empuje el ancho del modal (sin scroll horizontal). */
.wo-map {
  position: relative; width: 100%; min-width: 0; height: 280px; margin-bottom: var(--gap-md);
  border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--bg);
}
.wo-map-small { height: 200px; margin: 8px 0 0; }
.wo-map-frame { display: block; width: 100%; height: 100%; border: 0; }
.wo-map-directions {
  position: absolute; right: 10px; bottom: 26px; z-index: 1;
  background: var(--main); color: #fff; font-weight: 700; box-shadow: 0 2px 10px rgba(0,0,0,.25);
  text-decoration: none;
}
@media (hover: hover) and (pointer: fine) { .wo-map-directions:hover { filter: brightness(1.1); } }
.wo-map-directions svg { width: 15px; height: 15px; }
.wo-location-error { margin-top: 6px; font-size: calc(12.5px * var(--fs, 1)); color: var(--danger); font-weight: 600; }
@media (max-width: 480px) {
  .wo-map { height: 220px; }
}

.wo-photo-grid {
  display: grid; grid-template-columns: repeat(8, 1fr); gap: 8px;
  margin-bottom: 8px;
}
/* 8 columnas en un modal de 1320px dan miniaturas de sobra, pero en celular
   (modal angosto de ~290px de contenido) quedan de ~30px — ilegibles. */
@media (max-width: 520px) {
  .wo-photo-grid { grid-template-columns: repeat(4, 1fr); }
}
.wo-photo-thumb {
  position: relative; aspect-ratio: 1; border-radius: var(--radius-sm);
  overflow: hidden; cursor: zoom-in; background: var(--bg); border: 1px solid var(--border);
}
.wo-photo-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.wo-photo-delete {
  position: absolute; top: 4px; right: 4px; width: 22px; height: 22px;
  border-radius: 50%; border: none; background: rgba(0, 0, 0, .6); color: #fff;
  font-size: calc(15px * var(--fs, 1)); line-height: 1; cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .wo-photo-delete:hover { background: var(--danger); } }
.wo-photo-thumb[draggable="true"] { cursor: grab; }
.wo-photo-thumb.dragging { opacity: .4; }
.wo-photo-thumb.drag-over { outline: 2px dashed var(--secondary); outline-offset: 2px; }
/* Foto de Montaje capturada sin señal, guardada en el celular y esperando
   a enviarse sola cuando vuelva la conexión (N42, cola sin internet). */
.wo-photo-thumb-pending { opacity: .55; cursor: default; }
.wo-photo-pending-badge {
  position: absolute; left: 0; right: 0; bottom: 0; text-align: center;
  background: rgba(0, 0, 0, .65); color: #fff; font-size: calc(9.5px * var(--fs, 1)); padding: 2px 0;
}

.wo-lightbox-overlay { z-index: 1000; }
.wo-lightbox-inner { position: relative; max-width: 90vw; max-height: 90vh; }
.wo-lightbox-img { max-width: 90vw; max-height: 90vh; display: block; border-radius: var(--radius-sm); }
.wo-lightbox-close {
  position: absolute; top: -14px; right: -14px; width: 32px; height: 32px;
  border-radius: 50%; background: #fff; color: #16233a; border: none;
  font-size: calc(20px * var(--fs, 1)); line-height: 1; cursor: pointer; box-shadow: 0 2px 8px rgba(0, 0, 0, .3);
}

.wo-items-table-wrap { margin-bottom: 8px; }
.wo-items-table { width: 100%; min-width: 1220px; border-collapse: collapse; }
.wo-items-table thead th {
  background: var(--main); color: #fff; font-size: calc(11.5px * var(--fs, 1)); font-weight: 700;
  text-align: left; padding: 8px 8px; white-space: nowrap;
}
.wo-items-table tbody td { padding: 5px 6px; border-bottom: 1px solid var(--border); font-size: calc(13px * var(--fs, 1)); vertical-align: middle; }
.wo-items-table tbody tr:last-child td { border-bottom: none; }
.wo-items-table input[type=text], .wo-items-table input[type=number] { padding: 6px 8px; font-size: calc(13px * var(--fs, 1)); }
.wo-items-table select.wo-item-input { padding: 6px 6px; font-size: calc(13px * var(--fs, 1)); }

.wo-totals-row-wrap {
  display: flex; align-items: center; justify-content: space-between;
  gap: 20px; margin-top: 10px; flex-wrap: wrap;
}
.wo-totals-side { flex: 1 1 300px; min-width: 0; }
.wo-totals-side .emp-detail-grid { margin: 0; }
.wo-status-cols { align-items: start; }
/* Un <select> normal nunca ensancha su columna del grid porque el texto de
   la opción elegida no cuenta para su ancho mínimo — pero un botón con texto
   normal (como el toggle del dropdown de Servicios externos) sí, aunque
   tenga overflow:hidden + text-overflow:ellipsis: en un grid, el ancho
   mínimo de una columna se calcula por el contenido de sus descendientes, y
   ese min-width:auto por defecto ignora el overflow de un hijo que no sea
   directamente el item del grid. Este min-width:0 en el item mismo (los dos
   <div> de esta fila) es lo que de verdad deja que la columna se achique y
   el ellipsis del botón funcione, en vez de estirar la fila entera cuando
   hay varios servicios externos seleccionados. */
.wo-status-cols > div { min-width: 0; }
.wo-totals-box {
  margin: 4px 0; width: 260px; max-width: 100%; flex-shrink: 0;
  border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden;
}
.wo-totals-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: 7px 14px; font-size: calc(13px * var(--fs, 1)); color: var(--text-muted); background: var(--bg);
  border-bottom: 1px solid var(--border);
}
.wo-totals-row-total {
  background: var(--main); color: #fff; font-weight: 800; font-size: calc(15px * var(--fs, 1));
  padding: 11px 14px; border-bottom: none;
}

.assignee-table-wrap { margin-bottom: 8px; }
.assignee-table-wrap table { width: 100%; }
.assignee-table-wrap td { padding: 7px 8px; border-bottom: 1px solid var(--border); }
.assignee-table-wrap tr:last-child td { border-bottom: none; }

.assignee-chip {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--bg); border: 1px solid var(--border); border-radius: 999px;
  padding: 3px 10px 3px 3px; font-size: calc(12px * var(--fs, 1)); font-weight: 600; color: var(--text);
}
.assignee-chip .av {
  width: 20px; height: 20px; border-radius: 50%; background: var(--main);
  color: #fff; font-size: calc(9.5px * var(--fs, 1)); font-weight: 800; display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.assignee-chip button {
  background: none; border: none; color: var(--text-faint); cursor: pointer;
  font-size: calc(14px * var(--fs, 1)); line-height: 1; padding: 0 0 0 2px;
}
@media (hover: hover) and (pointer: fine) { .assignee-chip button:hover { color: var(--danger); } }
.assignee-chip-inactive { opacity: .55; }
.assignee-chip-inactive em, span.assignee-chip-inactive em { font-style: normal; color: var(--danger); font-weight: 700; }

.inline-toggle-link {
  background: none; border: none; padding: 0; margin-top: 4px;
  color: var(--accent-text); font-size: calc(12.5px * var(--fs, 1)); font-weight: 700; cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .inline-toggle-link:hover { text-decoration: underline; } }
.inline-client-box {
  border: 1px dashed var(--border); border-radius: var(--radius-sm);
  padding: 12px; margin-top: 8px; background: var(--bg);
}
.inline-client-box .field { margin-bottom: 10px; }
.inline-client-box .field:last-child { margin-bottom: 0; }

.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
@media (max-width: 640px) { .field-row { grid-template-columns: 1fr; } }
.field-row-wide { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.file-input-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

.filter-checkbox {
  display: flex; align-items: center; gap: 8px; height: 38px;
  font-size: calc(13px * var(--fs, 1)); color: var(--text); cursor: pointer; white-space: nowrap;
}
.filter-checkbox input { width: 16px; height: 16px; cursor: pointer; margin: 0; }

/* Dropdown genérico de selección múltiple: cerrado se ve y se comporta como
   un <select> normal (mismo borde, flechita, texto truncado), y al hacer
   clic despliega un panel con checkboxes en vez de abrir el <select> nativo
   del navegador (que no soporta multi-selección con checkboxes). */
.ms-dropdown { position: relative; }
.ms-dropdown-toggle {
  width: 100%; padding: 9px 32px 9px 11px; border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--input-bg); color: var(--text); font-size: calc(13.5px * var(--fs, 1)); text-align: left; cursor: pointer;
  font-family: inherit; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2362728a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center; background-size: 14px;
  transition: border-color .12s ease, box-shadow .12s ease;
}
.ms-dropdown-toggle.placeholder { color: var(--text-faint); }
.ms-dropdown-toggle:focus { outline: none; border-color: var(--secondary); box-shadow: 0 0 0 3px var(--secondary-light); }
.ms-dropdown-panel:not([hidden]) {
  position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 20;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: 6px; max-height: 220px; overflow-y: auto;
}
.ms-dropdown-item {
  display: flex; align-items: center; gap: 8px; padding: 8px; border-radius: var(--radius-sm);
  font-size: calc(13px * var(--fs, 1)); cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .ms-dropdown-item:hover { background: var(--bg); } }
.ms-dropdown-item input { width: 16px; height: 16px; cursor: pointer; margin: 0; flex-shrink: 0; }

/* ===== static/css/app/ordenes/selector-fecha.css ===== */
/* Selector de fecha estilo calendario y de mes. El orden en APP_CSS_ORDER (jp/routes/pages.py) es la cascada. */

/* Selector de fecha estilo calendario */
.date-field { position: relative; }
.date-input-btn {
  width: 100%; text-align: left; background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 9px 11px; font-size: calc(14px * var(--fs, 1)); min-height: 41px; font-family: inherit; cursor: pointer;
  display: flex; align-items: center; justify-content: space-between; gap: 8px; color: var(--text);
}
@media (hover: hover) and (pointer: fine) { .date-input-btn:hover { border-color: var(--secondary); } }
.date-input-btn .placeholder { color: var(--text-faint); }
.date-input-btn span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.date-input-btn .cal-icon { color: var(--text-faint); flex-shrink: 0; }
.date-popover-backdrop {
  position: fixed; inset: 0; z-index: 1005;
  background: rgba(10, 20, 38, .35);
  display: flex; align-items: center; justify-content: center;
}
/* Calendario estilo coss UI (p-calendar-6): flechas a los lados, mes y año
   como combobox (el <select> abre el menú Glide), días de 36px redondeados,
   "hoy" con un puntito abajo, días de otro mes tenues, fechas no válidas
   tachadas. Mismo look en los selectores de mes (.month-popover). */
.date-popover {
  position: relative; z-index: 1006;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: 0 24px 56px rgba(8, 16, 32, .32); padding: 12px; width: max-content; max-width: calc(100vw - 24px);
}
.date-popover-head { display: flex; align-items: center; justify-content: space-between; gap: 6px; height: 36px; margin-bottom: 6px; }
.date-popover-head .label { font-weight: 600; font-size: calc(14px * var(--fs, 1)); text-transform: capitalize; display: flex; align-items: center; gap: 4px; }
.date-caption { display: flex; align-items: center; justify-content: center; gap: 6px; flex: 1; }
select.date-cb {
  -webkit-appearance: none; appearance: none;
  width: auto; height: 32px; padding: 0 28px 0 10px; border-radius: 8px;
  font-size: calc(13.5px * var(--fs, 1)); font-weight: 600; color: var(--text); cursor: pointer;
  background-color: var(--surface); border: 1px solid var(--border);
  box-shadow: 0 1px 2px rgba(16, 34, 64, .05);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%237b8798' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m7 15 5 5 5-5'/%3E%3Cpath d='m7 9 5-5 5 5'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 8px center; background-size: 14px;
}
select.date-cb:focus-visible { outline: none; border-color: var(--secondary); box-shadow: 0 0 0 3px color-mix(in srgb, var(--secondary) 35%, transparent); }
.date-nav-btn {
  background: none; border: none; cursor: pointer; color: var(--text); flex: none;
  width: 36px; height: 36px; border-radius: 8px; display: flex; align-items: center; justify-content: center;
}
.date-nav-btn svg { opacity: .8; }
@media (hover: hover) and (pointer: fine) { .date-nav-btn:hover { background: var(--secondary-light); } }
.date-nav-btn:focus-visible { outline: none; box-shadow: 0 0 0 3px color-mix(in srgb, var(--secondary) 45%, transparent); }
.date-grid { display: grid; grid-template-columns: repeat(7, 36px); row-gap: 2px; }
.date-dow {
  height: 36px; display: flex; align-items: center; justify-content: center;
  font-size: calc(12px * var(--fs, 1)); font-weight: 500; color: var(--text-muted); opacity: .8;
}
.date-day {
  position: relative; width: 36px; height: 36px; padding: 0; display: flex; align-items: center; justify-content: center;
  font-size: calc(13.5px * var(--fs, 1)); border-radius: 8px; cursor: pointer; background: none; border: none; color: var(--text);
  transition: background-color .15s ease, box-shadow .15s ease;
}
@media (hover: hover) and (pointer: fine) { .date-day:not(.selected):hover { background: var(--secondary-light); } }
.date-day:focus-visible { outline: none; z-index: 1; box-shadow: 0 0 0 3px color-mix(in srgb, var(--secondary) 45%, transparent); }
.date-day.other-month { color: var(--text-muted); opacity: .72; }
.date-day.disabled, .date-day:disabled { color: var(--text-faint); text-decoration: line-through; cursor: not-allowed; opacity: .72; }
@media (hover: hover) and (pointer: fine) { .date-day.disabled:hover, .date-day:disabled:hover { background: none; } }
.date-day.today::after {
  content: ""; position: absolute; bottom: 5px; left: 50%; width: 3px; height: 3px; border-radius: 50%;
  transform: translateX(-50%); background: var(--main); pointer-events: none;
}
:root[data-theme="dark"] .date-day.today::after { background: var(--secondary); }
.date-day.selected { background: var(--main); color: #fff; font-weight: 600; opacity: 1; }
:root[data-theme="dark"] .date-day.selected { background: #2d6fc0; }
.date-day.selected.today::after { background: #fff; }
.date-popover-foot { display: flex; justify-content: space-between; margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--border); }
.date-popover-foot button {
  background: none; border: none; color: var(--accent-text); font-size: calc(12.5px * var(--fs, 1)); font-weight: 600; cursor: pointer;
  padding: 6px 10px; border-radius: 8px;
}
@media (hover: hover) and (pointer: fine) { .date-popover-foot button:hover { background: var(--secondary-light); } }
.month-popover { width: 240px; }
.month-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; }
.month-cell {
  height: 36px; padding: 0 4px; border-radius: 8px; cursor: pointer; background: none; border: none;
  font-size: calc(13.5px * var(--fs, 1)); color: var(--text); text-transform: capitalize;
}
@media (hover: hover) and (pointer: fine) { .month-cell:not(.selected):hover { background: var(--secondary-light); } }
.month-cell.selected { background: var(--main); color: #fff; font-weight: 600; }
:root[data-theme="dark"] .month-cell.selected { background: #2d6fc0; }
#wo-month-filter-wrap .inline-toggle-link { margin-top: 6px; }

/* ===== static/css/app/ordenes/senales.css ===== */
/* Órdenes: barra de tiempo, semáforo, mapa de calor y selección en Tabla. El orden en APP_CSS_ORDER (jp/routes/pages.py) es la cascada. */

/* N03: barra de tiempo al pie de la ficha (ver woTimeBarHTML). */
.kanban-card .wo-time-bar, .wo-card .wo-time-bar { height: 4px; margin: 10px -2px -4px; border-radius: 999px; background: var(--border); overflow: hidden; }
.kanban-card .wo-time-bar > span, .wo-card .wo-time-bar > span { display: block; height: 100%; border-radius: inherit; transition: width .4s var(--ease-out, ease); }
.wo-time-bar.is-ok > span { background: var(--success, #2e9d5b); }
.wo-time-bar.is-warn > span { background: var(--warn, #e0a100); }
.wo-time-bar.is-late > span { background: var(--danger, #d64545); }

/* Semáforo de columnas del Kanban (N35) y mapa de calor del Calendario (N34). */
.kanban-col-head { position: relative; flex-wrap: wrap; }
.kanban-col-health { position: absolute; left: 14px; right: 14px; bottom: 4px; display: flex; gap: 2px; height: 4px; }
.kanban-col-health i { display: block; min-width: 4px; border-radius: 2px; }
.kanban-col-health .is-ok { background: var(--success); }
.kanban-col-health .is-soon { background: #e0a100; }
.kanban-col-health .is-late { background: var(--danger); }
.wo-cal-limit { display: inline-flex; align-items: center; gap: 6px; font-size: calc(12.5px * var(--fs, 1)); color: var(--text-muted); font-weight: 600; }
.wo-cal-limit select { width: auto; padding: 4px 8px; }
.wo-cal-daynum { display: flex; align-items: center; justify-content: space-between; gap: 4px; }
.wo-cal-count { font-size: calc(11px * var(--fs, 1)); font-weight: 800; color: var(--text); font-variant-numeric: tabular-nums; }
.wo-cal-cell.wo-cal-heat { background: color-mix(in srgb, var(--main) var(--heat, 10%), var(--surface)); }
.wo-cal-cell.wo-cal-heat-over { background: color-mix(in srgb, var(--danger) 26%, var(--surface)); border-color: var(--danger); }
.wo-cal-heat-over .wo-cal-count { color: var(--danger); }
.wo-cal-heat-scale { display: inline-block; width: 44px; height: 10px; border-radius: 3px; background: linear-gradient(90deg, color-mix(in srgb, var(--main) 10%, var(--surface)), color-mix(in srgb, var(--main) 44%, var(--surface))); }
.wo-cal-heat-over-swatch { background: var(--danger); }

/* Selección múltiple en la Tabla (N52). */
.wo-bulk-bar {
  position: sticky; bottom: 12px; z-index: 6; display: flex; align-items: center; gap: 10px 16px; flex-wrap: wrap;
  margin-top: 12px; padding: 10px 14px; background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-sm); box-shadow: 0 6px 20px rgba(0, 0, 0, .14); font-size: calc(13px * var(--fs, 1));
}
.wo-bulk-count { font-weight: 700; }
.wo-bulk-field { display: inline-flex; align-items: center; gap: 6px; color: var(--text-muted); font-weight: 600; }
.wo-bulk-field select { width: auto; max-width: 180px; padding: 4px 8px; }
.wo-bulk-actions { margin: 0 0 0 auto; }
.wo-photo-paste-hint { display: inline-block; margin: 0 0 0 8px; }
@media (max-width: 640px) {
  .wo-bulk-field, .wo-bulk-field select { width: 100%; max-width: none; }
  .wo-bulk-actions { margin-left: 0; }
  .wo-photo-paste-hint { display: none; }
}

/* ===== static/css/app/base/tablas-y-paginacion.css ===== */
/* ------------------------------------------------------------------ */
/* Barra de selección masiva (Productos)                               */
/* ------------------------------------------------------------------ */
.bulk-bar {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap;
  gap: 10px; background: var(--secondary-light); border: 1px solid var(--secondary);
  border-radius: var(--radius-sm); padding: 10px 14px; margin-bottom: 14px;
  font-size: calc(13.5px * var(--fs, 1)); font-weight: 600; color: var(--accent-text);
}

/* ------------------------------------------------------------------ */
/* Pagination (Panel table)                                            */
/* ------------------------------------------------------------------ */
.pagination {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap;
  gap: 10px; margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--border);
}
.pagination-top {
  margin-top: 0; padding-top: 0; border-top: none;
  margin-bottom: 14px; padding-bottom: 14px; border-bottom: 1px solid var(--border);
}
.pagination-size { display: flex; align-items: center; gap: 8px; font-size: calc(12.5px * var(--fs, 1)); color: var(--text-muted); }
.pagination-size select { width: auto; padding: 5px 8px; }
/* Pagination de Watermelon UI (ver paginationHTML en app.js): una píldora con
   flechas redondas y "N de M"; los dígitos que cambian ruedan. */
.pagination-nav {
  display: inline-flex; align-items: center; gap: 8px; padding: 4px;
  background: var(--bg); border: 1px solid var(--border); border-radius: 999px;
}
.pg-arrow {
  width: 34px; height: 34px; flex: none; display: inline-flex; align-items: center; justify-content: center;
  border: none; border-radius: 50%; background: var(--surface); color: var(--text); cursor: pointer;
  box-shadow: 0 1px 3px rgba(16, 34, 64, .14), 0 1px 2px rgba(16, 34, 64, .08);
  transition: background-color .2s ease, color .2s ease, transform .16s var(--ease-out);
  -webkit-tap-highlight-color: transparent;
}
@media (hover: hover) and (pointer: fine) { .pg-arrow:not(:disabled):hover { background: var(--main); color: #fff; } }
.pg-arrow:not(:disabled):active { transform: scale(.9); }
.pg-arrow:disabled { opacity: .5; cursor: not-allowed; }
.pg-arrow:focus-visible { outline: 2px solid var(--secondary); outline-offset: 2px; }
:root[data-theme="dark"] .pg-arrow { box-shadow: 0 1px 3px rgba(0, 0, 0, .5); }
@media (hover: hover) and (pointer: fine) { :root[data-theme="dark"] .pg-arrow:not(:disabled):hover { background: #2d6fc0; } }
.pagination-info {
  display: inline-flex; align-items: center; gap: 5px; padding: 0 4px;
  font-size: calc(14px * var(--fs, 1)); font-weight: 700; color: var(--text-muted); user-select: none;
}
.pg-digits { display: inline-flex; height: 22px; font-variant-numeric: tabular-nums; color: var(--text); }
.pg-digit { position: relative; display: inline-block; width: 1ch; height: 22px; overflow: hidden; }
.pg-d { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; }
.pg-enter { animation: pg-enter 280ms cubic-bezier(.34, 1.15, .64, 1) both; }
.pg-exit { animation: pg-exit 220ms var(--ease-out) both; }
.pg-enter.pg-down { animation-name: pg-enter-down; }
.pg-exit.pg-down { animation-name: pg-exit-down; }
@keyframes pg-enter { from { transform: translateY(18px) scale(.5); opacity: 0; filter: blur(2px); } to { transform: none; opacity: 1; filter: none; } }
@keyframes pg-enter-down { from { transform: translateY(-18px) scale(.5); opacity: 0; filter: blur(2px); } to { transform: none; opacity: 1; filter: none; } }
@keyframes pg-exit { to { transform: translateY(-18px) scale(.5); opacity: 0; filter: blur(2px); } }
@keyframes pg-exit-down { to { transform: translateY(18px) scale(.5); opacity: 0; filter: blur(2px); } }
@media (prefers-reduced-motion: reduce) { .pg-enter { animation: none; } .pg-exit { display: none; } }

/* ------------------------------------------------------------------ */
/* Pie charts (Panel)                                                   */
/* ------------------------------------------------------------------ */
.pie-wrap { display: flex; align-items: flex-start; gap: 20px; flex-wrap: nowrap; min-height: 230px; overflow: hidden; }
.pie-svg-wrap { flex: 0 0 auto; width: 190px; }
.pie-svg { width: 100%; height: auto; display: block; overflow: visible; }
.pie-center-value { font-weight: 800; fill: var(--accent-text); font-family: var(--font); }
.pie-center-label { font-size: calc(7.5px * var(--fs, 1)); font-weight: 700; fill: var(--text-muted); text-transform: uppercase; letter-spacing: .02em; font-family: var(--font); }
.pie-legend { flex: 1 1 170px; min-width: 150px; max-height: 230px; overflow-y: auto; display: flex; flex-direction: column; gap: 4px; padding-right: 4px; }
.pie-legend-item { display: flex; align-items: center; gap: 9px; font-size: calc(12.5px * var(--fs, 1)); padding: 6px 7px; border-radius: 6px; }
@media (hover: hover) and (pointer: fine) { .pie-legend-item:hover { background: var(--bg); } }
.pie-swatch { width: 11px; height: 11px; border-radius: 3px; flex-shrink: 0; box-shadow: 0 0 0 1px var(--pie-swatch-ring); }
.pie-legend-label { flex: 1; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pie-legend-value { flex: 0 0 auto; min-width: 64px; text-align: right; color: var(--text); font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
@media (max-width: 700px) {
  .pie-wrap { min-height: 0; flex-wrap: wrap; }
  .pie-legend { max-height: 260px; }
}

/* Comparación año contra año (tabla con mini-barras) */
.yoy-bar-row { position: relative; display: flex; align-items: center; min-width: 130px; height: 20px; }
.yoy-bar { position: absolute; left: 0; top: 0; height: 100%; border-radius: 5px; opacity: .3; z-index: 0; transform-origin: left; animation: chart-grow-x .7s var(--ease-out) backwards; }
.yoy-bar-0 { background: var(--chart-1); }
.yoy-bar-1 { background: var(--chart-3); }
.yoy-bar-2 { background: var(--chart-4); }
.yoy-bar-3 { background: var(--chart-5); }
.yoy-bar-4 { background: var(--chart-6); }
.yoy-bar-row span { position: relative; z-index: 1; padding-left: 6px; font-variant-numeric: tabular-nums; }
.yoy-legend-dot { display: inline-block; width: 8px; height: 8px; border-radius: 2px; margin-right: 4px; opacity: .7; }
.yoy-up { color: var(--success); font-weight: 700; }
.yoy-down { color: var(--danger); font-weight: 700; }
.yoy-year-picker { display: flex; flex-wrap: wrap; gap: 6px; }
.yoy-year-chip {
  display: inline-flex; align-items: center; gap: 5px; cursor: pointer; user-select: none;
  border: 1px solid var(--border); border-radius: 999px; padding: 5px 12px; font-size: calc(12.5px * var(--fs, 1)); font-weight: 600;
  transition: border-color .12s ease, background .12s ease;
}
.yoy-year-chip input { margin: 0; }
.yoy-year-chip.checked { border-color: var(--secondary); background: var(--secondary-light); }



/* N05: densidad de tablas (ver tableDensityToggleHTML en nucleo/tablas.js). */
.tbl-density { display: inline-flex; gap: 2px; padding: 3px; border: 1px solid var(--border); border-radius: 999px; background: var(--bg); order: 3; }
.tbl-density-btn {
  width: 28px; height: 26px; display: inline-grid; place-items: center; padding: 0;
  border: 0; border-radius: 999px; background: transparent; color: var(--text-faint); cursor: pointer;
}
.tbl-density-btn svg { width: 15px; height: 15px; }
.tbl-density-btn.is-active { background: var(--surface); color: var(--main); box-shadow: 0 1px 2px rgba(16, 34, 64, .14); }
@media (hover: hover) and (pointer: fine) { .tbl-density-btn:not(.is-active):hover { color: var(--text); } }
.tbl-density-btn:focus-visible { outline: 2px solid var(--secondary); outline-offset: 1px; }
:root[data-theme="dark"] .tbl-density-btn.is-active { color: #8fbfff; }
.pagination-top.tbl-dens-compact ~ * tbody td, .pagination-top.tbl-dens-compact ~ table tbody td { padding-top: 4px; padding-bottom: 4px; font-size: calc(12.5px * var(--fs, 1)); }
.pagination-top.tbl-dens-compact ~ * thead th { padding-top: 6px; padding-bottom: 6px; }
.pagination-top.tbl-dens-comfy ~ * tbody td, .pagination-top.tbl-dens-comfy ~ table tbody td { padding-top: 16px; padding-bottom: 16px; }
.pagination-top.tbl-dens-comfy ~ * thead th { padding-top: 12px; padding-bottom: 12px; }

/* ===== static/css/app/modulos/componentes.css ===== */
/* ------------------------------------------------------------------ */
/* Print stage — fuera de pantalla (no display:none) para que el layout
   de las etiquetas se calcule siempre, incluso sin estar imprimiendo.
   Así el JS puede medir el texto (para achicar la categoría si no cabe
   en una línea) antes de llamar a window.print(). Al imprimir, @media
   print solo lo reposiciona a la página visible.                      */
/* ------------------------------------------------------------------ */
.print-stage {
  position: absolute;
  left: -9999px;
  top: 0;
  width: 7.8in; /* igual al área imprimible real: 8.5in de hoja menos 0.35in de margen en cada lado */
}

/* Etiquetas de producto: hoja carta normal (8.5in x 11in), 12 etiquetas por
   página en una cuadrícula de 3 columnas x 4 filas — se llenan fila por
   fila (toda la fila 1 de izquierda a derecha, luego la 2, etc.), sin
   importar si se imprimen menos o más de 12 en total.

   Importante: esta @page NO lleva nombre (ni "page:" en .label-page) a
   propósito — asignarle un nombre fuerza un salto de página en el navegador
   apenas cambia de una página sin nombre a una con nombre, lo que dejaba
   una primera hoja en blanco antes de las etiquetas. */
@page {
  size: 8.5in 11in;
  margin: 0.35in;
}

.label-sheet { display: block; }
.label-page {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(4, 1fr);
  grid-auto-flow: row;
  width: 7.8in;
  height: 10.3in;
}
.label {
  position: relative;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.label-body {
  flex: 1;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center;
  padding: 0.12in 0.16in 0.08in;
  gap: 14px;
  min-height: 0;
}
.label .label-title {
  font-size: calc(15px * var(--fs, 1));
  font-weight: 600;
  line-height: 1.2;
  max-width: 100%;
  word-break: break-word;
}
.label svg { max-width: 2.3in; width: 100%; height: auto; }
.label-footer {
  flex-shrink: 0;
  height: 46px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--main);
  color: #fff;
  -webkit-print-color-adjust: exact;
  print-color-adjust: exact;
  color-adjust: exact;
  font-weight: 700;
  font-size: calc(16px * var(--fs, 1));
  padding: 0 10px;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
}

@media print {
  .app-shell { display: none !important; }
  .toast-stack, .toast-stack-top { display: none !important; }
  .print-stage {
    position: static;
    left: auto;
    width: 100%;
  }
  .label-page {
    page-break-after: always;
    break-after: page;
  }
  .label-page:last-child { page-break-after: auto; break-after: auto; }
}

/* Confeti discreto al cerrar una Orden de Trabajo — ver celebrateOrderClosed()
   en app.js. Piezas fijas (no afectan el layout), se autodestruyen solas. */
.confetti-piece {
  position: fixed; width: 8px; height: 12px; z-index: 1400; pointer-events: none;
  opacity: .95; animation: confetti-fall 1s linear forwards;
}
@keyframes confetti-fall {
  to { transform: translateY(130px) rotate(var(--rot)); opacity: 0; }
}

/* Editar grupo de clientes: cada cliente miembro con su botón "Sacar del
   grupo" (antes solo eran chips de nombre, sin acción). */
.group-member-list { display: flex; flex-direction: column; border: 1px solid var(--border); border-radius: var(--radius-sm); }
.group-member-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 7px 10px; }
.group-member-row + .group-member-row { border-top: 1px solid var(--row-border); }
.group-member-row span { min-width: 0; overflow-wrap: anywhere; font-size: calc(13px * var(--fs, 1)); }
.group-member-row .btn svg { width: 14px; height: 14px; }

/* Botones que solo tienen sentido con pantalla táctil (ej. "Tomar foto" con
   la cámara del celular en Mantenimiento) — en compu con mouse no salen. */
.touch-only { display: none !important; }
@media (pointer: coarse) { .touch-only { display: inline-flex !important; } }
.btn.touch-only svg { width: 15px; height: 15px; }

/* Sistema → Salud del servidor */
.server-health-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; margin-bottom: 14px; }
.server-health-meta { display: flex; align-items: center; gap: 10px; font-size: calc(12px * var(--fs, 1)); color: var(--text-muted); }
.health-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 210px), 1fr)); gap: 12px; }
.health-tile { border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 12px 14px; background: var(--bg); min-width: 0; }
.health-tile-label { font-size: calc(11.5px * var(--fs, 1)); font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: .03em; }
.health-tile-value { font-size: calc(22px * var(--fs, 1)); font-weight: 800; color: var(--text); margin-top: 4px; overflow-wrap: anywhere; }
.health-tile-detail { font-size: calc(12px * var(--fs, 1)); color: var(--text-muted); margin-top: 6px; overflow-wrap: anywhere; }
.health-bar { height: 7px; border-radius: 999px; background: var(--border); margin-top: 8px; overflow: hidden; }
.health-bar-fill { height: 100%; border-radius: 999px; background: var(--text-faint); }
.health-ok { color: var(--success); } .health-warn { color: var(--warn-text); } .health-danger { color: var(--danger); }
.health-bg-ok { background: var(--success); } .health-bg-warn { background: var(--warn-text); } .health-bg-danger { background: var(--danger); }

/* OT → Conversación (comentarios con @menciones) e Historial (línea de
   tiempo), al final de la vista de la orden. */
.wo-activity { margin-top: 20px; border-top: 1px solid var(--border); padding-top: 16px; }
.wo-activity-tabs { margin-bottom: 12px; }
.wo-comments { display: flex; flex-direction: column; gap: 12px; max-height: 360px; overflow-y: auto; padding-right: 4px; }
.wo-comment { display: flex; gap: 10px; align-items: flex-start; }
.wo-comment-avatar { flex-shrink: 0; width: 32px; height: 32px; border-radius: 50%; overflow: hidden; background: var(--secondary-light);
  display: flex; align-items: center; justify-content: center; font-size: calc(11.5px * var(--fs, 1)); font-weight: 800; color: var(--accent-text); }
.wo-comment-avatar img { width: 100%; height: 100%; object-fit: cover; }
.wo-comment-main { min-width: 0; flex: 1; background: var(--bg); border: 1px solid var(--border); border-radius: 4px 12px 12px 12px; padding: 8px 12px; }
.wo-comment.mine .wo-comment-main { background: var(--secondary-light); border-color: transparent; }
.wo-comment-head { display: flex; align-items: center; gap: 8px; font-size: calc(12.5px * var(--fs, 1)); }
.wo-comment-time { color: var(--text-faint); font-size: calc(11.5px * var(--fs, 1)); }
.wo-comment-delete { margin-left: auto; background: none; border: none; padding: 2px; cursor: pointer; color: var(--text-faint); display: inline-flex; }
@media (hover: hover) and (pointer: fine) { .wo-comment-delete:hover { color: var(--danger); } }
.wo-comment-delete svg { width: 14px; height: 14px; }
/* Nota fijada (N08, 2026-11-03) */
.wo-comment-pin { background: none; border: none; padding: 2px; cursor: pointer; color: var(--text-faint); display: inline-flex; margin-left: auto; }
.wo-comment-pin + .wo-comment-delete { margin-left: 4px; }
.wo-comment-pin svg { width: 14px; height: 14px; }
.wo-comment-pin.is-pinned { color: var(--main); }
@media (hover: hover) and (pointer: fine) { .wo-comment-pin:hover { color: var(--main); } }
.wo-pinned-note { display: flex; gap: 10px; align-items: flex-start; padding: 10px 14px; margin: 0 0 14px; border-radius: var(--radius-sm);
  background: var(--warn-bg); color: var(--warn-text); border: 1px solid color-mix(in srgb, var(--warn-text) 25%, transparent); font-size: calc(13.5px * var(--fs, 1)); line-height: 1.45; }
.wo-pinned-note svg { width: 16px; height: 16px; flex: none; margin-top: 2px; }
.wo-pinned-note b { display: block; font-size: calc(11px * var(--fs, 1)); text-transform: uppercase; letter-spacing: .04em; margin-bottom: 1px; }
.kanban-pin { display: inline-flex; color: var(--warn-text); margin-left: 4px; vertical-align: -2px; }
.kanban-pin svg { width: 13px; height: 13px; }
.wo-comment-body { margin-top: 3px; font-size: calc(13.5px * var(--fs, 1)); line-height: 1.45; color: var(--text); overflow-wrap: anywhere; }
.wo-mention { color: var(--accent-text); font-weight: 700; background: color-mix(in srgb, var(--secondary) 18%, transparent); border-radius: 4px; padding: 0 3px; }
.wo-comment-composer { display: flex; gap: 10px; align-items: flex-end; margin-top: 14px; }
.wo-comment-input-wrap { position: relative; flex: 1; min-width: 0; }
#wo-comment-input { width: 100%; resize: vertical; min-height: 44px; }
.wo-mention-menu:not([hidden]) {
  position: absolute; left: 0; bottom: calc(100% + 4px); z-index: 30; min-width: 220px; max-width: 100%;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm); box-shadow: var(--shadow);
  display: flex; flex-direction: column; padding: 4px; max-height: 240px; overflow-y: auto;
}
.wo-mention-option { display: flex; flex-direction: column; align-items: flex-start; gap: 1px; text-align: left; background: none; border: none;
  border-radius: 6px; padding: 6px 8px; cursor: pointer; color: var(--text); font-size: calc(13px * var(--fs, 1)); }
.wo-mention-option span { font-size: calc(11.5px * var(--fs, 1)); color: var(--text-muted); }
.wo-mention-option.active { background: var(--secondary-light); }
@media (hover: hover) and (pointer: fine) { .wo-mention-option:hover { background: var(--secondary-light); } }

.wo-timeline { list-style: none; margin: 4px 0 0; padding: 0 0 0 4px; max-height: 420px; overflow-y: auto; }
.wo-timeline-item { position: relative; display: flex; gap: 12px; padding-bottom: 16px; }
.wo-timeline-item:not(:last-child)::before { content: ""; position: absolute; left: 12px; top: 26px; bottom: 0; width: 2px; background: var(--border); }
.wo-timeline-dot { flex-shrink: 0; width: 26px; height: 26px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
  font-size: calc(12px * var(--fs, 1)); font-weight: 800; color: #fff; background: var(--text-faint); border: 2px solid var(--text-faint); z-index: 1; }
.wo-tl-ok .wo-timeline-dot { background: var(--success); border-color: var(--success); }
.wo-tl-status .wo-timeline-dot { background: var(--main); border-color: var(--main); }
.wo-tl-hold .wo-timeline-dot { background: var(--hold); border-color: var(--hold); color: #3d2e00; }
.wo-tl-comment .wo-timeline-dot { background: var(--secondary-light); border-color: var(--secondary); font-size: calc(11px * var(--fs, 1)); }
.wo-tl-info .wo-timeline-dot { background: var(--accent-text); border-color: var(--accent-text); }
.wo-tl-money .wo-timeline-dot { background: #6b3fb0; border-color: #6b3fb0; }
.wo-tl-danger .wo-timeline-dot { background: var(--danger); border-color: var(--danger); }
.wo-timeline-content { min-width: 0; padding-top: 3px; }
.wo-timeline-title { font-size: calc(13.5px * var(--fs, 1)); font-weight: 700; color: var(--text); overflow-wrap: anywhere; }
.wo-timeline-detail { font-weight: 500; color: var(--text-muted); }
.wo-timeline-meta { font-size: calc(11.5px * var(--fs, 1)); color: var(--text-faint); margin-top: 2px; }
@media (max-width: 480px) {
  .wo-comment-composer { flex-direction: column; align-items: stretch; }
}

/* Salud del servidor → "¿En qué se usa el disco?" */
.disk-breakdown { margin-top: 14px; border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 12px 14px; }
.disk-breakdown-title { font-size: calc(13px * var(--fs, 1)); font-weight: 800; color: var(--text); }
.disk-breakdown-title span { font-weight: 500; color: var(--text-muted); margin-left: 6px; }
.disk-breakdown-bar { display: flex; height: 14px; border-radius: 999px; overflow: hidden; background: var(--border); margin: 10px 0 12px; }
.disk-breakdown-bar > div { height: 100%; }
.disk-legend { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); gap: 6px 24px; }
.disk-legend-head { font-size: calc(11.5px * var(--fs, 1)); font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: .03em; margin-bottom: 4px; }
.disk-legend-row { display: flex; align-items: center; gap: 8px; font-size: calc(12.5px * var(--fs, 1)); padding: 2px 0; }
.disk-legend-dot { width: 10px; height: 10px; border-radius: 3px; flex-shrink: 0; }
.disk-legend-label { flex: 1; min-width: 0; color: var(--text); }
.disk-legend-value { font-variant-numeric: tabular-nums; color: var(--text-muted); white-space: nowrap; }

/* Ventana "PDF listo" en el celular (ver openPdf en app.js) */
.pdf-ready-file { display: flex; align-items: center; gap: 12px; padding: 12px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--bg); }
.pdf-ready-icon { flex-shrink: 0; width: 40px; height: 48px; border-radius: 6px; background: var(--danger); color: #fff; font-size: calc(11px * var(--fs, 1)); font-weight: 800; display: flex; align-items: center; justify-content: center; }
.pdf-ready-name { font-weight: 700; font-size: calc(13.5px * var(--fs, 1)); overflow-wrap: anywhere; }
.pdf-ready-actions { display: flex; flex-direction: column; gap: 8px; margin-top: 16px; }
.pdf-ready-actions .btn { width: 100%; justify-content: center; text-decoration: none; }

/* WhatsApp (botón en la vista de una orden y en su diálogo) */
.btn-whatsapp { background: #25d366; color: #fff; border-color: #25d366; }
@media (hover: hover) and (pointer: fine) { .btn-whatsapp:hover { filter: brightness(.95); } }
.btn-whatsapp-icon { padding: 0 10px; align-self: stretch; }
.btn-whatsapp-icon svg { width: 19px; height: 19px; }

/* Menú de usuario: botones deshabilitados (ej. avisos no disponibles) */
.user-chip-menu button[disabled] { opacity: .55; cursor: default; }

/* Reportar un problema o sugerencia */

/* Configuración → Desarrollo */
.nav-badge { margin-left: auto; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 999px; background: #d93025; color: #fff;
  font-size: calc(11px * var(--fs, 1)); font-weight: 800; display: inline-flex; align-items: center; justify-content: center; }
.nav-badge[hidden] { display: none; }
.dev-kind { display: inline-block; font-size: calc(11.5px * var(--fs, 1)); font-weight: 700; border-radius: 999px; padding: 2px 9px; white-space: nowrap; }
.dev-kind-bug { background: var(--danger-bg); color: var(--danger); }
.dev-kind-idea { background: var(--secondary-light); color: var(--accent-text); }
.dev-kind-question { background: var(--warn-bg); color: var(--warn-text); }
.dev-priority { font-size: calc(12px * var(--fs, 1)); font-weight: 800; }
.dev-priority-alta { color: var(--danger); } .dev-priority-media { color: var(--warn-text); } .dev-priority-baja { color: var(--text-muted); }
.dev-report-grid { display: grid; grid-template-columns: minmax(0, 1fr) 280px; gap: 20px; }
.dev-report-side { border-left: 1px solid var(--border); padding-left: 18px; }
.dev-report-text { white-space: pre-wrap; overflow-wrap: anywhere; font-size: calc(13.5px * var(--fs, 1)); line-height: 1.5; background: var(--bg);
  border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 10px 12px; }
.dev-report-photo { max-width: 100%; border-radius: var(--radius-sm); border: 1px solid var(--border); cursor: zoom-in; }
.dev-report-tech { margin-top: 14px; font-size: calc(12px * var(--fs, 1)); color: var(--text-muted); }
.dev-report-tech summary { cursor: pointer; font-weight: 700; }
.dev-report-tech .mono { margin-top: 6px; overflow-wrap: anywhere; line-height: 1.6; }
@media (max-width: 760px) {
  .dev-report-grid { grid-template-columns: 1fr; }
  .dev-report-side { border-left: none; padding-left: 0; border-top: 1px solid var(--border); padding-top: 14px; }
}

/* Tour guiado (botón "?" de cada pestaña → "Ver tour guiado"). La capa
   tapa toda la app (no se puede hacer clic debajo) y el "hueco" iluminado
   es una caja con una sombra gigante alrededor. */
.tour-layer { position: fixed; inset: 0; z-index: 1150; }
.tour-spot {
  position: fixed; top: 0; left: 0; border-radius: 10px; box-shadow: 0 0 0 9999px rgba(8, 16, 32, .66);
  outline: 2px solid rgba(255, 255, 255, .85); outline-offset: 0; pointer-events: none;
  transition: transform .25s var(--ease-out), width .25s var(--ease-out), height .25s var(--ease-out);
}
.tour-card {
  position: fixed; background: var(--surface); color: var(--text); border-radius: var(--radius);
  top: 0; left: 0; box-shadow: 0 18px 50px rgba(0, 0, 0, .35); padding: 14px 16px; transition: transform .25s var(--ease-out);
}
.tour-layer.is-busy .tour-card { opacity: .55; }
.tour-card-head { display: flex; align-items: center; justify-content: space-between; }
.tour-step-count { font-size: calc(11.5px * var(--fs, 1)); font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: .04em; }
.tour-close { background: none; border: none; font-size: calc(22px * var(--fs, 1)); line-height: 1; color: var(--text-muted); cursor: pointer; padding: 0 2px; }
.tour-title { font-size: calc(15px * var(--fs, 1)); font-weight: 800; margin-top: 4px; }
.tour-text { font-size: calc(13.5px * var(--fs, 1)); line-height: 1.5; margin-top: 4px; color: var(--text); }
.tour-actions { display: flex; justify-content: space-between; align-items: center; margin-top: 12px; }
@media (prefers-reduced-motion: reduce) { .tour-spot, .tour-card { transition: none; } }

/* Facturación → Agregar órdenes a una factura (sobre todo a una vacía) */
.inv-empty-note { border: 1px dashed var(--border); border-radius: var(--radius-sm); background: var(--bg);
  padding: 12px 14px; font-size: calc(13.5px * var(--fs, 1)); line-height: 1.5; color: var(--text-muted); }
.inv-empty-note strong { color: var(--text); }
.inv-add-subtitle { font-size: calc(12.5px * var(--fs, 1)); color: var(--text-muted); margin-top: 2px; }
.inv-add-toolbar { display: flex; flex-wrap: wrap; gap: 10px 16px; align-items: center; margin-bottom: 12px; }
.inv-add-toolbar #inv-add-search { flex: 1 1 260px; min-width: 0; }
.inv-add-include { display: inline-flex; align-items: center; gap: 6px; font-size: calc(13px * var(--fs, 1)); color: var(--text-muted); cursor: pointer; }
.inv-add-include input { margin: 0; }
tr.inv-add-selected td { background: var(--secondary-light); }

/* Botón flotante para reportar (abajo a la derecha, 2026-10-04) */
.fb-fab {
  position: fixed; right: calc(20px + env(safe-area-inset-right)); bottom: calc(20px + env(safe-area-inset-bottom));
  z-index: 900; width: 52px; height: 52px; border-radius: 50%; border: none; cursor: pointer;
  background: var(--main); color: #fff; display: none; align-items: center; justify-content: center;
  box-shadow: 0 6px 18px rgba(8, 67, 131, .35), 0 2px 4px rgba(0, 0, 0, .12);
  transition: transform .15s ease, background .15s ease;
}
body.app-mode .fb-fab { display: inline-flex; }
@media (hover: hover) and (pointer: fine) { .fb-fab:hover { background: var(--main-dark); transform: translateY(-2px); } }
.fb-fab svg { width: 24px; height: 24px; }
@media (max-width: 768px) {
  .fb-fab { width: 46px; height: 46px; right: calc(14px + env(safe-area-inset-right)); bottom: calc(14px + env(safe-area-inset-bottom)); }
  .fb-fab svg { width: 21px; height: 21px; }
}
@media print { .fb-fab { display: none !important; } }

/* Formulario de reportes (2026-10-04): secciones numeradas, rejillas fijas */
.fb-card { max-width: 720px; }
.fb-head { display: flex; align-items: center; gap: 12px; }
.fb-head-icon { width: 40px; height: 40px; border-radius: 12px; background: var(--main); color: #fff; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center; }
.fb-head-icon svg { width: 22px; height: 22px; }
.fb-head-sub { font-size: calc(12.5px * var(--fs, 1)); color: var(--text-muted); margin-top: 2px; }
.fb-section { padding: 14px 0; border-top: 1px solid var(--border); }
.fb-section:first-of-type { border-top: none; padding-top: 4px; }
.fb-section-title { display: flex; align-items: center; gap: 8px; font-size: calc(14px * var(--fs, 1)); font-weight: 800; color: var(--text); margin-bottom: 12px; }
.fb-step { width: 22px; height: 22px; border-radius: 50%; background: var(--secondary-light); color: var(--accent-text);
  font-size: calc(12px * var(--fs, 1)); font-weight: 800; display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; }
.fb-optional { font-size: calc(11.5px * var(--fs, 1)); font-weight: 600; color: var(--text-faint); }
.fb-kinds { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.fb-kind { display: flex; align-items: center; gap: 12px; text-align: left; padding: 12px 14px; min-height: 68px;
  border: 1.5px solid var(--border); border-radius: var(--radius); background: var(--surface); color: var(--text);
  cursor: pointer; transition: border-color .12s ease, background .12s ease, box-shadow .12s ease; }
@media (hover: hover) and (pointer: fine) { .fb-kind:hover { border-color: var(--secondary); } }
.fb-kind.active { border-color: var(--main); background: var(--secondary-light); box-shadow: 0 0 0 3px rgba(53, 162, 219, .18); }
.fb-kind-icon { width: 38px; height: 38px; border-radius: 10px; flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; }
.fb-kind-icon svg { width: 20px; height: 20px; }
.fb-kind-icon-bug { background: var(--danger-bg); color: var(--danger); }
.fb-kind-icon-mejora { background: var(--secondary-light); color: var(--accent-text); }
.fb-kind-icon-idea { background: var(--hold-bg); color: var(--hold-text); }
.fb-kind-icon-pregunta { background: var(--success-bg); color: var(--success); }
.fb-kind-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.fb-kind-title { font-size: calc(14px * var(--fs, 1)); font-weight: 800; }
.fb-kind-desc { font-size: calc(12px * var(--fs, 1)); color: var(--text-muted); line-height: 1.35; }
.fb-grid { display: grid; gap: 12px; }
.fb-grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.fb-grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.fb-grid > .field { min-width: 0; margin-bottom: 0; }
.fb-section > .field:last-child { margin-bottom: 0; }
.fb-segment { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); border: 1.5px solid var(--border); border-radius: var(--radius-sm); overflow: hidden; }
.fb-segment-btn { display: inline-flex; align-items: center; justify-content: center; gap: 7px; padding: 10px 8px; border: none;
  border-left: 1.5px solid var(--border); background: var(--surface); color: var(--text); font-size: calc(12.5px * var(--fs, 1)); font-weight: 700; cursor: pointer; }
.fb-segment-btn:first-child { border-left: none; }
.fb-segment-btn.active { background: var(--main); color: #fff; }
.fb-dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }
.fb-dot-0 { background: #d93025; }
.fb-dot-1 { background: #f0a020; }
.fb-dot-2 { background: #8b9ab2; }
.fb-segment-btn.active .fb-dot { box-shadow: 0 0 0 2px #fff; }
.fb-drop { display: flex; align-items: center; gap: 14px; padding: 14px 16px; border: 1.5px dashed var(--border);
  border-radius: var(--radius); background: var(--bg); }
.fb-drop.has-file { border-style: solid; }
.fb-drop-thumb { width: 64px; height: 48px; object-fit: cover; border-radius: 6px; border: 1px solid var(--border); flex-shrink: 0; }
.fb-drop-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; font-size: calc(13px * var(--fs, 1)); }
.fb-drop-text strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fb-drop-text span { font-size: calc(12px * var(--fs, 1)); color: var(--text-muted); }
.fb-context { display: flex; align-items: flex-start; gap: 8px; margin-top: 4px; padding: 10px 12px; border-radius: var(--radius-sm);
  background: var(--subtle-bg); font-size: calc(12px * var(--fs, 1)); color: var(--text-muted); line-height: 1.45; }
.fb-context svg { width: 15px; height: 15px; flex-shrink: 0; margin-top: 1px; }
.fb-empty-hint { text-align: center; font-size: calc(12.5px * var(--fs, 1)); color: var(--text-faint); padding: 6px 0 2px; }
@media (max-width: 560px) {
  .fb-kinds, .fb-grid-2, .fb-grid-3 { grid-template-columns: minmax(0, 1fr); }
  .fb-segment { grid-template-columns: minmax(0, 1fr); }
  .fb-segment-btn { border-left: none; border-top: 1.5px solid var(--border); justify-content: flex-start; padding-left: 14px; }
  .fb-segment-btn:first-child { border-top: none; }
}

/* WhatsApp: mensajes según el estatus de la orden */
.wa-card { max-width: 520px; }
.wa-head { display: flex; align-items: center; gap: 10px; }
.wa-head-icon { width: 36px; height: 36px; border-radius: 10px; background: #25d366; color: #fff; display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; }
.wa-head-icon svg { width: 20px; height: 20px; }
.wa-head-sub { font-size: calc(12px * var(--fs, 1)); color: var(--text-muted); margin-top: 2px; }
.wa-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.wa-chip { border: 1.5px solid var(--border); background: var(--surface); color: var(--text); border-radius: 999px;
  padding: 6px 12px; font-size: calc(12.5px * var(--fs, 1)); font-weight: 700; cursor: pointer; }
@media (hover: hover) and (pointer: fine) { .wa-chip:hover { border-color: #25d366; } }
.wa-chip.active { background: #25d366; border-color: #25d366; color: #fff; }
#wa-open svg { width: 17px; height: 17px; }

/* Sistema → Notificaciones push */
.push-error-cell { max-width: 260px; white-space: normal; font-size: calc(12px * var(--fs, 1)); color: var(--danger); }

/* Administración → Planilla */
.stat-num-money { font-size: calc(21px * var(--fs, 1)); }
.stat-num-small { font-size: calc(17px * var(--fs, 1)); }
.payroll-legal { margin: 6px 0 0; padding-left: 18px; display: flex; flex-direction: column; gap: 7px; font-size: calc(13px * var(--fs, 1)); color: var(--text-muted); line-height: 1.45; }
.payroll-legal strong { color: var(--text); }
.payroll-settings-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.payroll-settings-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 24px; margin-top: 14px; }
.payroll-settings-group { min-width: 0; }
.payroll-setting-field { margin-bottom: 8px; }
.input-with-unit { display: flex; align-items: stretch; }
.input-with-unit input { flex: 1; min-width: 0; border-top-right-radius: 0 !important; border-bottom-right-radius: 0 !important; }
.input-with-unit span { display: inline-flex; align-items: center; padding: 0 10px; font-size: calc(12px * var(--fs, 1)); font-weight: 700; color: var(--text-muted);
  background: var(--subtle-bg); border: 1px solid var(--border); border-left: none; border-radius: 0 var(--radius-sm) var(--radius-sm) 0; white-space: nowrap; }
.payroll-isr-table { width: 100%; }
.payroll-isr-table td, .payroll-isr-table th { padding: 4px 6px 4px 0; border: none; }
.payroll-sources { margin: 14px 0 10px; padding: 10px 12px; border-radius: var(--radius-sm); background: var(--subtle-bg); font-size: calc(12px * var(--fs, 1)); color: var(--text-muted); line-height: 1.5; }
.payroll-actions { justify-content: flex-end; }
/* Barra de la planilla (2026-11-03): herramientas a la izquierda, estatus a la derecha. */
.payroll-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 10px 16px; flex-wrap: wrap;
  margin: -6px 0 16px; padding: 8px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); }
.payroll-toolbar-tools, .payroll-toolbar-status { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.payroll-toolbar-status { gap: 8px; margin-left: auto; }
.payroll-toolbar .btn { display: inline-flex; align-items: center; gap: 6px; }
.payroll-toolbar-sep { width: 1px; align-self: stretch; margin: 4px 6px; background: var(--border); }
.payroll-delete-btn { color: var(--danger); }
.payroll-row-actions { white-space: nowrap; width: 1%; padding-right: 0 !important; }
.payroll-row-actions .btn-icon { width: 30px; height: 30px; }
.payroll-row-actions .btn-icon svg { width: 15px; height: 15px; }
.payroll-remove-btn { color: var(--text-muted); }
.payroll-remove-btn:hover { color: var(--danger); }
.payroll-row-changed > td { background: var(--warn-bg); }
.psim-hero { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; margin: 4px 0 16px; }
.psim-hero > div { display: flex; flex-direction: column; gap: 4px; padding: 12px 14px; border-radius: var(--radius-sm); background: var(--subtle-bg); }
.psim-hero > div:first-child { background: var(--secondary-light); }
.psim-hero span { font-size: calc(12px * var(--fs, 1)); color: var(--text-muted); font-weight: 600; }
.psim-hero strong { font-size: calc(20px * var(--fs, 1)); font-weight: 800; }
@media (max-width: 700px) { .psim-hero { grid-template-columns: minmax(0, 1fr); } }
.payroll-diff { font-size: calc(12px * var(--fs, 1)); font-weight: 700; white-space: nowrap; }
.payroll-diff.up { color: var(--success); }
.payroll-diff.down { color: var(--danger); }
.payroll-diff.same, .payroll-diff.new { color: var(--text-faint); font-weight: 600; }
.payroll-warnings { margin-top: 16px; padding: 12px 14px; border: 1px solid var(--hold-border); background: var(--hold-bg); color: var(--hold-text);
  border-radius: var(--radius); display: flex; flex-direction: column; gap: 6px; font-size: calc(13px * var(--fs, 1)); }
.payroll-warnings > div { display: flex; gap: 8px; align-items: flex-start; }
.payroll-warnings svg { width: 15px; height: 15px; flex-shrink: 0; margin-top: 2px; }
.payroll-table tfoot td { font-weight: 800; border-top: 2px solid var(--border); padding: 10px; white-space: nowrap; }
.payroll-absence { font-size: calc(11px * var(--fs, 1)); font-weight: 800; color: var(--danger); }
.payroll-manual { font-size: calc(11px * var(--fs, 1)); color: var(--accent-text); }
.payroll-employer-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; margin-top: 10px; }
.payroll-employer-item { display: flex; justify-content: space-between; gap: 10px; padding: 10px 12px; border: 1px solid var(--border); border-radius: var(--radius-sm); font-size: calc(13px * var(--fs, 1)); }
.payroll-employer-item span { color: var(--text-muted); }
.payroll-employer-total { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin-top: 10px; }
.payroll-employer-total > div { display: flex; justify-content: space-between; gap: 10px; padding: 12px 14px; border-radius: var(--radius-sm); background: var(--secondary-light); font-size: calc(13.5px * var(--fs, 1)); }
.payroll-line-grid { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); gap: 22px; }
.payroll-breakdown { display: flex; flex-direction: column; border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden; margin-bottom: 8px; }
.payroll-breakdown > div { display: flex; justify-content: space-between; gap: 10px; padding: 8px 12px; font-size: calc(13px * var(--fs, 1)); border-top: 1px solid var(--row-border); }
.payroll-breakdown > div:first-child { border-top: none; }
.payroll-breakdown > div.strong { font-weight: 800; background: var(--subtle-bg); }
/* El monto nunca se parte en dos líneas ("L" arriba y la cifra abajo). */
.payroll-breakdown > div > .mono { white-space: nowrap; }
@media (max-width: 768px) {
  .payroll-settings-grid, .payroll-line-grid, .payroll-employer-total { grid-template-columns: minmax(0, 1fr); }
  .payroll-employer-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .payroll-actions { justify-content: flex-start; }
  .payroll-toolbar-status { margin-left: 0; width: 100%; }
  .payroll-toolbar-status .btn-primary { flex: 1; justify-content: center; }
  .payroll-toolbar-sep { display: none; }
}


/* Minigráficas de 12 meses en tablas (N38). */
.spark { display: block; overflow: visible; }
.spark polyline { fill: none; stroke: var(--chart-1); stroke-width: 1.5; stroke-linejoin: round; stroke-linecap: round; }
.spark circle { fill: var(--chart-1); }
.spark-empty { color: var(--text-faint); }
.trend-cell { min-width: 92px; }
/* Fechas rápidas del calendario (N46). */
.date-quick { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; margin-top: 8px; }
.date-quick-btn { padding: 6px 8px; border: 1px solid var(--border); border-radius: 8px; background: var(--surface); color: var(--text); font: inherit; font-size: calc(12.5px * var(--fs, 1)); font-weight: 600; cursor: pointer; }
.date-quick-btn:hover:not(:disabled) { border-color: var(--main); color: var(--main); }
.date-quick-btn:disabled { opacity: .45; cursor: not-allowed; }

/* ===== static/css/app/base/pulido-y-movimiento.css ===== */
/* ================================================================== */
/* Auditoría de UI (2026-10-10) — skills mobile-native, emil-design-eng, */
/* improve-animations y break-ui. Ver reference/modulos.md → "Pulido".  */
/* ================================================================== */

/* --- Celular: que se sienta app instalada, no página web --- */
html { -webkit-tap-highlight-color: transparent; -webkit-text-size-adjust: 100%; }
button, a, [role="button"], label, summary { touch-action: manipulation; }
/* Mantener presionado un CONTROL no selecciona su texto (el contenido sí
   se puede seguir seleccionando y copiando). */
.btn, .view-toggle-btn, .nav-item, .nav-group-toggle, .fb-kind, .fb-segment-btn, .wa-chip,
.yoy-year-chip, .help-icon-btn, .fb-fab, .user-chip-btn, .modal-close, .notif-bell-btn, .tour-close {
  -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
}
/* iPhone hace zoom (y no regresa) al tocar un campo de menos de 16px. */
@media (pointer: coarse) {
  input[type=time], .wo-items-table input[type=text], .wo-items-table input[type=number],
  .wo-items-table select.wo-item-input { font-size: calc(16px * var(--fs, 1)); }
}
/* El scroll de adentro (columna del Kanban, ventana, tabla, menú) no se
   pasa a la página: así no se dispara "jalar para recargar". */
.kanban-col-body, .modal-card, .table-wrap-v-scroll, .notif-panel, .user-chip-menu,
.global-search-panel, .wo-filters-popover, .ms-dropdown-panel { overscroll-behavior: contain; }
/* Área para tocar de al menos ~40px en botones chiquitos (solo con dedo). */
@media (pointer: coarse) {
  .help-btns { gap: 12px; }
  .help-icon-btn, .copy-inline-btn, .btn-icon { position: relative; }
  .help-icon-btn::after, .btn-icon::after, .copy-inline-btn::after { content: ""; position: absolute; inset: -8px; }
  .copy-inline-btn-sm::after { inset: -12px; }
}
/* El botón del bichito no tapa lo último de la página ni de una columna. */
@media (max-width: 860px) {
  .main { padding-bottom: calc(88px + env(safe-area-inset-bottom, 0px)); }
  .kanban-col-body { padding-bottom: 64px; }
}

/* --- Contraste --- */
/* En modo oscuro el azul principal casi desaparecía sobre el fondo (1.9:1). */
:root[data-theme="dark"] .help-icon-btn, :root[data-theme="dark"] .fb-fab { background: #2d6fc0; }
@media (hover: hover) and (pointer: fine) {
  :root[data-theme="dark"] .help-icon-btn:hover, :root[data-theme="dark"] .fb-fab:hover { background: #3478c8; }
}

/* --- Movimiento --- */
/* Presionar un botón responde de inmediato, en cualquier dispositivo. */
.btn:active { transform: scale(.97); }
.view-toggle-btn, .fb-kind, .wa-chip, .fb-segment-btn { transition: background .12s ease, border-color .12s ease, color .12s ease, box-shadow .12s ease, transform .16s var(--ease-out); }
.view-toggle-btn:active, .fb-kind:active, .wa-chip:active, .fb-segment-btn:active, .kanban-card:active { transform: scale(.98); }
.help-icon-btn:active, .fb-fab:active { transform: scale(.94); }

/* Menús que salen de un botón: aparecen desde ese botón (150ms). Al
   cerrar se van de una vez — salir siempre es más rápido que entrar. */
.user-chip-menu, .notif-panel, .global-search-panel {
  transform-origin: top right;
  transition: opacity 150ms var(--ease-out), transform 150ms var(--ease-out);
}
.wo-filters-popover:not([hidden]) {
  transform-origin: top right;
  transition: opacity 150ms var(--ease-out), transform 150ms var(--ease-out);
}
@starting-style {
  .user-chip.open .user-chip-menu, .notif-bell.open .notif-panel, .global-search.open .global-search-panel,
  .wo-filters-popover:not([hidden]) { opacity: 0; transform: translateY(-4px) scale(.97); }
}

/* Ventanas: entrada de 200ms la PRIMERA vez que se abren (la clase la pone
   watchModalRoots() en app.js; los re-dibujos internos no la repiten). */
@keyframes jp-fade-in { from { opacity: 0; } }
@keyframes jp-modal-in { from { opacity: 0; transform: scale(.97); } }
.modal-overlay.modal-enter { animation: jp-fade-in 180ms var(--ease-out); }
.modal-overlay.modal-enter > * { animation: jp-modal-in 200ms var(--ease-out); }
/* Salida (2026-11-03): la pone playModalExit() en app.js al cerrar. */
@keyframes jp-fade-out { to { opacity: 0; } }
@keyframes jp-modal-out { to { opacity: 0; transform: scale(.97); } }
#modal-exit-layer { position: fixed; inset: 0; z-index: 1000; pointer-events: none; }
#modal-exit-layer:empty { display: none; }
.modal-overlay.modal-exit { pointer-events: none; animation: jp-fade-out 150ms ease-in forwards; }
.modal-overlay.modal-exit > * { animation: jp-modal-out 150ms ease-in forwards; }

/* Menos movimiento para quien lo pidió en su sistema: se queda lo que
   aclara (aparecer y desaparecer), se quita lo que se mueve. */
@media (prefers-reduced-motion: reduce) {
  .confetti-piece { display: none; }
  .notif-bell-btn svg.ringing { animation: none; }
  .dev-egg-card, .modal-overlay.modal-enter > * { animation-name: jp-fade-in; }
  .modal-overlay.modal-exit > * { animation-name: jp-fade-out; }
  .btn:active, .view-toggle-btn:active, .fb-kind:active, .wa-chip:active, .fb-segment-btn:active,
  .kanban-card:active, .help-icon-btn:active, .fb-fab:active { transform: none; }
  .sidebar, .menu-line, .nav-group-chevron, .user-chip-chevron, .toast-item { transition-duration: 0ms; }
  @starting-style {
    .user-chip.open .user-chip-menu, .notif-bell.open .notif-panel, .global-search.open .global-search-panel,
    .wo-filters-popover:not([hidden]) { transform: none; }
  }
}

/* --- Celular: Órdenes de Trabajo sin una cabecera que ocupe media pantalla --- */
@media (max-width: 768px) {
  .wo-page-head { position: relative; margin-bottom: 12px; gap: 10px; }
  .wo-page-head .page-title { font-size: calc(22px * var(--fs, 1)); padding-right: 50px; }
  .wo-header-actions { width: 100%; margin-top: 0; }
  .wo-header-actions .view-toggle { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); width: 100%; }
  .wo-header-actions .view-toggle-btn { padding: 8px 0; font-size: calc(10.5px * var(--fs, 1)); letter-spacing: -.02em; white-space: nowrap; }
  .wo-header-actions .btn-row-divider { display: none; }
  /* "+ Nueva orden" como botón redondo "+" en la fila del título */
  .wo-new-col { display: contents; }
  #wo-today-btn { position: absolute; top: 0; right: 50px; height: 38px; width: auto; padding: 0 14px; border-radius: 999px; }
  #new-wo-btn { position: absolute; top: -2px; right: 0; width: 42px; height: 42px; padding: 0; border-radius: 50%; font-size: 0; gap: 0; }
  #new-wo-btn::before { content: "+"; font-size: calc(26px * var(--fs, 1)); font-weight: 500; line-height: 1; }
  .view-toggle:has(#module-tab-main) { margin-bottom: 10px !important; }
  .wo-filters-card { padding: 8px 10px; }
  .wo-filters-bar { gap: 6px 8px; }
  .wo-filters-search { flex: 1 1 55%; }
  .wo-filters-bar .filter-checkbox { gap: 5px; }
  .wo-filters-bar .filter-checkbox span { font-size: calc(12.5px * var(--fs, 1)); }
  .wo-filters-actions { margin-top: 0; margin-left: auto; gap: 6px; flex-wrap: nowrap; }
  .wo-filters-actions .btn { font-size: calc(12px * var(--fs, 1)); padding: 5px 8px; }
  .kanban-scroll-top { margin-top: 2px; }
}

/* --- Celular: botones de cada ventana siempre a la vista, abajo --- */
@media (max-width: 768px) {
  .modal-card { max-height: 90vh; max-height: 90dvh; }
  .modal-card > .modal-footer {
    position: sticky; bottom: -22px; z-index: 3; flex-wrap: wrap; gap: 8px;
    margin: 14px -22px -22px; padding: 12px 22px calc(12px + env(safe-area-inset-bottom, 0px));
    background: var(--surface); border-top: 1px solid var(--border);
  }
  /* Vista de una orden: "Editar" grande abajo (donde llega el pulgar),
     las demás acciones en una rejilla pareja y "Eliminar" al final. */
  /* 2026-10-11: las acciones son íconos en una fila; abajo WhatsApp + "Editar" grande. */
  .wo-view-footer { flex-direction: column; align-items: stretch; gap: 10px; }
  .wo-view-footer > .wo-view-icon-actions { display: flex; justify-content: space-between; gap: 8px; margin: 0; }
  .wo-view-footer > .wo-view-icon-actions > .btn { flex: 1 1 0; width: auto; height: 42px; }
  .wo-view-footer > .wo-view-main-actions { display: flex; gap: 8px; margin: 0; }
  .wo-view-footer #wo-view-edit-btn { flex: 1 1 auto; justify-content: center; padding: 12px; font-size: calc(14px * var(--fs, 1)); }
  .wo-view-footer #wo-whatsapp-btn { width: 52px; justify-content: center; }
}


/* ===== static/css/app/sistema/registro-de-cambios.css ===== */
/* ------------------------------------------------------------------ */
/* Sistema → Registro de cambios: línea de tiempo vertical. La fecha de  */
/* cada día queda pegada arriba (sticky) hasta que llega el siguiente;   */
/* cada cambio entra con Blur Fade (Magic UI).                           */
/* ------------------------------------------------------------------ */
.chg-card { padding: 20px 22px; }
.chg-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 18px; }
.chg-timeline { position: relative; }
.chg-day { position: relative; display: grid; grid-template-columns: 170px 1fr; gap: 0 28px; padding-bottom: 26px; }
.chg-day::before { content: ""; position: absolute; left: 182px; top: 6px; bottom: 0; width: 2px; background: var(--border); }
.chg-day:last-child::before { bottom: auto; height: 18px; }
.chg-date { position: sticky; top: calc(var(--content-top-offset) + 14px); align-self: start; display: flex; align-items: flex-start; justify-content: flex-end; gap: 12px; text-align: right; z-index: 1; }
.chg-dot { order: 2; flex: none; width: 12px; height: 12px; margin: 6px -21px 0 0; border-radius: 50%; background: var(--main); box-shadow: 0 0 0 4px var(--surface), 0 0 0 6px color-mix(in srgb, var(--main) 25%, transparent); }
.chg-date-main { font-size: calc(15px * var(--fs, 1)); font-weight: 800; color: var(--text); text-transform: capitalize; }
.chg-date-day { font-size: calc(22px * var(--fs, 1)); letter-spacing: -.02em; color: var(--accent-text); }
.chg-date-sub { font-size: calc(12px * var(--fs, 1)); color: var(--text-muted); margin-top: 2px; }
.chg-list { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.chg-commit {
  position: relative; padding: 12px 14px 10px; border: 1px solid var(--border); border-radius: 12px; background: var(--surface);
  box-shadow: 0 1px 2px rgba(8, 16, 32, .04);
  opacity: 0; filter: blur(6px); transform: translateY(8px);
  transition: opacity .45s ease, filter .45s ease, transform .45s cubic-bezier(.22, 1, .36, 1);
}
.chg-commit.is-in { opacity: 1; filter: none; transform: none; }
.chg-commit ul { margin: 0; padding-left: 18px; }
.chg-commit li { font-size: calc(13.5px * var(--fs, 1)); line-height: 1.5; color: var(--text); overflow-wrap: anywhere; }
.chg-commit li + li { margin-top: 3px; }
.chg-commit li::marker { color: var(--main); }
.chg-hash { display: inline-block; margin-top: 6px; font-size: calc(11px * var(--fs, 1)); color: var(--text-faint); }
@media (max-width: 720px) {
  .chg-card { padding: 16px 14px; }
  .chg-day { grid-template-columns: 1fr; padding-left: 22px; }
  .chg-day::before { left: 5px; }
  .chg-date { justify-content: flex-start; text-align: left; top: var(--content-top-offset); padding: 6px 0 10px; background: var(--surface); }
  .chg-dot { order: 0; margin: 6px 0 0 -22px; }
}
@media (prefers-reduced-motion: reduce) { .chg-commit { opacity: 1; filter: none; transform: none; transition: none; } }


/* ===== static/css/app/base/celular.css ===== */
/* ------------------------------------------------------------------ */
/* Celular (2026-10-12)                                                 */
/* ------------------------------------------------------------------ */
.kanban-card-code { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
/* Número de factura (en Cobro): mismo formato que el código de la OT, abajo a la derecha. */
.kanban-card-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.wo-invoice-tag { font-family: var(--mono); font-size: calc(10.5px * var(--fs, 1)); font-weight: 700; color: var(--text-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; text-align: right; }
/* La pila de un grupo: sin content-visibility (recortaba el "×N" y las hojas de abajo). */
.kanban-col-body .kanban-card.wo-stack-card { content-visibility: visible; }
/* Al revelar la ficha recién movida (renderKanbanAndReveal): medir con todas dibujadas. */
.kanban-col-body.kanban-measure .kanban-card { content-visibility: visible; }
/* Buscador global y campos chicos: 16px en celular para que iOS no haga zoom. */
@media (pointer: coarse) {
  #global-search-input, .input-with-unit input, .wo-items-table textarea { font-size: calc(16px * var(--fs, 1)); }
  /* Al llegar al final del scroll de una tabla, sigue la página. */
  .table-wrap-v-scroll { overscroll-behavior-y: auto; }
  .avatar-circle:active { transform: translateY(-5px) scale(1.06); z-index: 30; }
  .avatar-circle:active::after, .avatar-circle.show-name::after { opacity: 1; transform: translate(-50%, 0) scale(1); }
}
/* En computadora también: el final de la tabla pasa el scroll a la página. */
.table-wrap-v-scroll { overscroll-behavior-y: auto; }
#wo-results { min-height: 100dvh; }
@media (max-width: 860px) { .main { padding-bottom: calc(80px + env(safe-area-inset-bottom, 0px)); } }
@media (max-width: 520px) { .user-chip-menu { min-width: 0; width: 300px; max-width: calc(100vw - 24px); } }
/* Avisos rojos/azules (Spring Modal) en celular: sin pie pegajoso, más compactos. */
@media (max-width: 768px) {
  .spring-card { padding: 20px 16px 16px !important; max-height: 90dvh; overflow-y: auto; }
  .spring-card > .modal-footer { position: static !important; margin: 0 !important; padding: 0 !important; background: none !important; border-top: none !important; flex-direction: column-reverse; gap: 8px; }
  .spring-card > .modal-footer > * { width: 100%; flex: none !important; }
  .spring-card .sm-bg-icon { width: 150px; height: 150px; }
  .spring-card .modal-title { font-size: calc(19px * var(--fs, 1)); }
  /* Menos memoria en celular: sin desenfoque detrás de las ventanas. */
  .modal-overlay { backdrop-filter: none; -webkit-backdrop-filter: none; background: rgba(15, 26, 45, .6); }
}
@media (max-width: 600px) { .user-chip-menu .al-list > button { padding-top: 9px; padding-bottom: 9px; } }
.tour-card { max-width: calc(100vw - 24px); }
.tour-close { padding: 8px 12px; margin: -8px; }

.kanban-more { width: 100%; margin-top: 4px; justify-content: center; }
.kanban-col-body .kanban-card.touch-armed { box-shadow: 0 10px 30px rgba(8, 16, 32, .25); transform: scale(1.02); }


/* ===== static/css/app/finanzas/cuentas-y-cumplimiento.css ===== */
/* ------------------------------------------------------------------ */
/* Finanzas: Cuentas por cobrar / pagar y Consumo de productos         */
/* (fichas con Spotlight/Count Up, barra de antigüedad, Border Beam en */
/* lo vencido, filas con Blur Fade — Magic UI).                         */
/* ------------------------------------------------------------------ */
.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 14px; margin-bottom: 16px; }
.acc-card { margin-bottom: 16px; }
/* La barra de scroll de lado se queda pegada bajo la barra superior mientras
   la tabla está en pantalla (se perdía al bajar por la tabla). */
.acc-card .table-scroll-mirror {
  position: sticky; top: var(--content-top-offset); z-index: 6;
  height: 18px; margin-bottom: 0; background: var(--surface);
}
.acc-tile { position: relative; overflow: hidden; }
.acc-tile.is-alert .stat-num { color: var(--danger); }
.acc-tile .acc-beam { opacity: 1; border-radius: var(--radius); }
.acc-tile .acc-beam::after { background: linear-gradient(to left, #e5484d, #f59e0b, transparent); }
.acc-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 12px; }
.acc-toolbar input[type=search] { max-width: 320px; }
.acc-sub { font-size: calc(12px * var(--fs, 1)); color: var(--text-muted); font-weight: 500; margin-top: 2px; }
.aging-bar { display: flex; height: 14px; border-radius: 999px; overflow: hidden; gap: 3px; background: var(--subtle-bg); margin: 6px 0 14px; }
.aging-bar > span { min-width: 6px; animation: aging-grow .7s cubic-bezier(.22, 1, .36, 1) both; transform-origin: left; }
@keyframes aging-grow { from { transform: scaleX(0); } }
.aging-ok { background: #16a34a; } .aging-warn { background: #f59e0b; } .aging-late { background: #ea580c; } .aging-danger { background: #dc2626; }
.aging-empty { background: var(--subtle-bg); }
.aging-legend { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; }
.aging-legend-item { display: flex; gap: 8px; align-items: flex-start; }
.aging-dot { width: 10px; height: 10px; border-radius: 50%; margin-top: 4px; flex: none; }
.aging-legend-label { font-size: calc(12px * var(--fs, 1)); color: var(--text-muted); font-weight: 600; }
.aging-legend-value { font-size: calc(14px * var(--fs, 1)); font-weight: 800; color: var(--text); font-variant-numeric: tabular-nums; }
.aging-legend-value span { font-weight: 600; color: var(--text-muted); font-size: calc(12px * var(--fs, 1)); }
.aging-pill { display: inline-block; min-width: 42px; text-align: center; border-radius: 999px; padding: 1px 8px; font-size: calc(12px * var(--fs, 1)); font-weight: 700; color: #fff; }
.bf-row { animation: bf-in .5s cubic-bezier(.22, 1, .36, 1) both; animation-delay: calc(var(--bf-i, 0) * 35ms); }
@keyframes bf-in { from { opacity: 0; filter: blur(6px); transform: translateY(6px); } }
@media (prefers-reduced-motion: reduce) { .bf-row, .aging-bar > span { animation: none; } }
.cons-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 14px; }
.cons-controls { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.cons-controls input[type=date] { width: auto; }
.cons-in { color: var(--success) !important; }
.cons-out { color: var(--danger) !important; }
@media (max-width: 600px) { .stat-grid { grid-template-columns: 1fr 1fr; } .cons-controls { width: 100%; } }

/* Mantenimiento: 5 fichas (Vehículos) en una fila de 3 y otra de 2, igual de anchas que en los otros paneles. */
.grid-5 { grid-template-columns: repeat(6, 1fr); }
.grid-5 > :nth-child(-n+3) { grid-column: span 2; }
.grid-5 > :nth-child(n+4) { grid-column: span 3; }
@media (max-width: 700px) { .grid-5 { grid-template-columns: 1fr 1fr; } .grid-5 > * { grid-column: auto !important; } }
.maint-table-title { margin-bottom: 14px !important; }
/* Historial: "Limpiar filtros" en la misma fila que los filtros (no agranda la tarjeta). */
.ah-clear-field { flex: 0 0 auto; justify-content: flex-end; align-self: flex-end; }
.split-inv-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 4px 14px; }
/* Reparto de renglones entre facturas (finanzas/reparto-facturas.js) */
.split-inv-count { margin-left: 6px; font-size: calc(11.5px * var(--fs, 1)); font-weight: 600; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.split-inv-count.is-bad { color: var(--danger); }
.split-inv-input-wrap { display: flex; gap: 6px; align-items: center; }
.split-inv-input-wrap input { flex: 1; min-width: 0; }
.split-inv-tools { display: flex; gap: 8px; flex-wrap: wrap; margin: 4px 0 10px; }
.split-rows { max-height: min(46vh, 420px); overflow-y: auto; border: 1px solid var(--border); border-radius: 10px; margin-bottom: 4px; }
.split-row { display: flex; align-items: center; gap: 10px; padding: 7px 10px; border-bottom: 1px solid var(--border); }
.split-row:last-child { border-bottom: none; }
.split-row-num { flex: none; width: 24px; text-align: right; color: var(--text-faint); font-size: calc(12px * var(--fs, 1)); font-variant-numeric: tabular-nums; }
.split-row-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: calc(13.5px * var(--fs, 1)); color: var(--text); }
.split-row-code { font-family: var(--mono); font-size: calc(11px * var(--fs, 1)); color: var(--text-muted); margin-right: 8px; }
.split-row-picks { flex: none; display: flex; gap: 4px; }
.split-pick { width: 30px; height: 28px; border-radius: 8px; border: 1px solid var(--border); background: var(--input-bg); color: var(--text-muted); font-weight: 700; font-size: calc(13px * var(--fs, 1)); cursor: pointer; transition: background-color .15s var(--ease-out), color .15s var(--ease-out), border-color .15s var(--ease-out); }
.split-pick.is-on { background: var(--main); border-color: var(--main); color: #fff; }
.split-pick:active { transform: scale(.94); }
@media (hover: hover) and (pointer: fine) { .split-pick:not(.is-on):hover { border-color: var(--main); color: var(--text); } }
@media (pointer: coarse) { .split-pick { width: 36px; height: 34px; } }

/* Sistema → prueba de restauración del respaldo */
.backup-verify { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--border); }
.bv-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.bv-title { font-weight: 800; color: var(--text); display: flex; align-items: center; gap: 8px; }
.bv-dot { width: 10px; height: 10px; border-radius: 50%; flex: none; }
.bv-dot.is-ok { background: var(--success); box-shadow: 0 0 0 4px color-mix(in srgb, var(--success) 18%, transparent); }
.bv-dot.is-bad { background: var(--danger); box-shadow: 0 0 0 4px color-mix(in srgb, var(--danger) 18%, transparent); }
.bv-problems { margin: 10px 0 0; color: var(--danger); font-size: calc(13px * var(--fs, 1)); }
.bv-tables { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.bv-chip { display: flex; align-items: baseline; gap: 6px; padding: 5px 10px; border-radius: 8px; background: var(--subtle-bg); font-size: calc(12.5px * var(--fs, 1)); }
.bv-chip span { color: var(--text-muted); } .bv-chip b { color: var(--text); font-variant-numeric: tabular-nums; } .bv-chip em { color: var(--text-faint); font-style: normal; font-size: calc(11.5px * var(--fs, 1)); }

/* ---------------------------------------------------------------------
   Panel de OT → Cumplimiento de entrega (ordenes/cumplimiento.js) y
   Ventas → "¿Cómo va este mes?" (ordenes/ventas-comparativo.js), 2026-10-13.
   Colores solo con tokens de :root (cambian solos en modo oscuro).
   --------------------------------------------------------------------- */
.ontime-controls { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ontime-controls .view-toggle-btn { padding: 7px 12px; }
.ontime-tile .ontime-sub, .mom-line { font-size: calc(12px * var(--fs, 1)); color: var(--text-muted); margin-top: 6px; line-height: 1.4; }
.mom-line + .mom-line { margin-top: 2px; }
.mom-line b { color: var(--text); font-variant-numeric: tabular-nums; }
.ontime-tile.is-good .stat-num { color: var(--success); }
.ontime-tile.is-warn .stat-num { color: var(--hold-text); }
.ontime-tile.is-bad .stat-num { color: var(--danger); }
.ontime-tile.is-none .stat-num, .mom-tile.is-empty .stat-num { color: var(--text-faint); }
.ontime-delta { font-weight: 700; color: var(--text-muted); white-space: nowrap; }
.ontime-delta.is-up { color: var(--success); }
.ontime-delta.is-down { color: var(--danger); }
.ontime-section-title, .mom-chart-title { font-size: calc(13px * var(--fs, 1)); font-weight: 800; color: var(--text); margin: 18px 0 8px; }
.ontime-chart, .mom-chart { width: 100%; overflow: hidden; }
.ontime-chart svg, .mom-chart svg { display: block; max-width: 100%; }
.ontime-grid, .mom-grid { stroke: var(--border); stroke-width: 1; }
.ontime-grid.is-base, .mom-grid.is-base { stroke: var(--text-faint); opacity: .5; }
.ontime-legend .is-good { background: var(--success); }
.ontime-legend .is-warn { background: var(--hold); }
.ontime-legend .is-bad { background: var(--danger); }
.ontime-legend, .mom-legend { display: flex; flex-wrap: wrap; gap: 6px 14px; font-size: calc(12px * var(--fs, 1)); color: var(--text-muted); margin-top: 6px; }
.ontime-legend span, .mom-legend-item { display: inline-flex; align-items: center; gap: 6px; }
.ontime-legend i { width: 10px; height: 10px; border-radius: 3px; display: inline-block; }
.ontime-legend i.is-goal { height: 0; border-top: 2px dashed var(--success); border-radius: 0; background: none; }
.ontime-people { display: flex; flex-direction: column; }
.ontime-person { display: grid; grid-template-columns: auto minmax(0, 1fr) minmax(96px, 32%); align-items: center; gap: 12px; padding: 10px 2px; border-bottom: 1px solid var(--row-border); }
.ontime-person:last-child { border-bottom: none; }
.ontime-avatar { display: inline-flex; }
.ontime-person-main { min-width: 0; }
.ontime-person-name { font-weight: 700; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ontime-inactive { font-weight: 500; color: var(--text-faint); font-style: normal; font-size: calc(12px * var(--fs, 1)); }
.ontime-person-sub { font-size: calc(12px * var(--fs, 1)); color: var(--text-muted); }
.ontime-person-pct { display: flex; align-items: center; gap: 8px; }
.ontime-person-pct b { min-width: 38px; text-align: right; font-variant-numeric: tabular-nums; color: var(--text); }
.ontime-progress { flex: 1; height: 8px; border-radius: 999px; background: var(--subtle-bg); overflow: hidden; }
.ontime-progress > span { display: block; height: 100%; border-radius: inherit; background: var(--text-faint); transform-origin: left; animation: aging-grow .8s var(--ease-out) both; }
.ontime-person-pct.is-good .ontime-progress > span { background: var(--success); }
.ontime-person-pct.is-warn .ontime-progress > span { background: var(--hold); }
.ontime-person-pct.is-bad .ontime-progress > span { background: var(--danger); }
.ontime-person-pct.is-good b { color: var(--success); }
.ontime-person-pct.is-bad b { color: var(--danger); }
@media (prefers-reduced-motion: reduce) { .ontime-bar, .ontime-progress > span { animation: none; } }
@media (max-width: 480px) {
  .ontime-person { grid-template-columns: auto minmax(0, 1fr); row-gap: 6px; }
  .ontime-person-pct { grid-column: 2; }
  .ontime-controls { width: 100%; justify-content: space-between; }
}
/* Ventas: este mes contra el anterior y el del año pasado */
.mom-tile.is-up .stat-num, .mom-diff.is-up { color: var(--success); }
.mom-tile.is-down .stat-num, .mom-diff.is-down { color: var(--danger); }
.mom-diff { font-size: calc(13px * var(--fs, 1)); font-weight: 700; margin-top: 6px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.mom-axis { font-size: calc(10.5px * var(--fs, 1)); fill: var(--text-muted); font-variant-numeric: tabular-nums; }
.mom-today { stroke: var(--text-faint); stroke-width: 1; stroke-dasharray: 3 3; }
.mom-cursor { stroke: var(--text-muted); stroke-width: 1; }
.mom-hit { fill: transparent; cursor: crosshair; }
.mom-line-cur { stroke: var(--chart-1); stroke-width: 2.75; stroke-linejoin: round; stroke-linecap: round; }
.mom-line-prev { stroke: var(--chart-6); stroke-width: 2; stroke-linejoin: round; }
.mom-line-ly { stroke: var(--text-faint); stroke-width: 2; stroke-dasharray: 5 4; stroke-linejoin: round; }
.mom-dot-cur { fill: var(--chart-1); } .mom-dot-prev { fill: var(--chart-6); } .mom-dot-ly { fill: var(--text-faint); }
.mom-legend-item i { width: 16px; height: 0; border-top: 3px solid; display: inline-block; }
.mom-legend-item i.mom-swatch-cur { border-color: var(--chart-1); } .mom-legend-item i.mom-swatch-prev { border-color: var(--chart-6); }
.mom-legend-item i.mom-swatch-ly { border-top-style: dashed; border-color: var(--text-faint); }
.mom-legend-item.is-off { opacity: .55; }
.mom-readout { font-size: calc(12.5px * var(--fs, 1)); color: var(--text-muted); margin-top: 8px; min-height: 18px; line-height: 1.5; }
.mom-readout b { color: var(--text); font-variant-numeric: tabular-nums; }
.mom-readout-day { font-weight: 800; color: var(--text); margin-right: 4px; }
/* Año contra año: meses y años sin datos */
.yoy-nodata { color: var(--text-faint); font-size: calc(12px * var(--fs, 1)); font-style: italic; }
.yoy-notes { margin-top: 8px; }

/* Facturación → CAI y rango de facturas (SAR, 2026-10-13 — static/js/app/finanzas/cai.js) */
.cai-card { margin-top: 16px; margin-bottom: 16px; border-left: 4px solid var(--border); }
.cai-card.cai-ok { border-left-color: var(--success); }
.cai-card.cai-soon { border-left-color: var(--warn-text); }
.cai-card.cai-urgent, .cai-card.cai-danger { border-left-color: var(--danger); }
.cai-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
.cai-head-actions { gap: 8px; margin: 0; }
.cai-empty { margin: 0; color: var(--text-muted); font-size: calc(13.5px * var(--fs, 1)); line-height: 1.5; }
.cai-summary { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; min-width: 0; }
.cai-code { color: var(--text); overflow-wrap: anywhere; min-width: 0; }
.cai-level { display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px; border-radius: 999px; font-size: calc(12px * var(--fs, 1)); font-weight: 700; white-space: nowrap; }
.cai-level::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: currentColor; }
.cai-level.cai-ok { background: var(--success-bg); color: var(--success); }
.cai-level.cai-soon { background: var(--warn-bg); color: var(--warn-text); }
.cai-level.cai-urgent { background: var(--danger-bg); color: var(--danger); }
.cai-level.cai-danger { background: var(--danger); color: #fff; }
.cai-level.cai-none { background: var(--subtle-bg); color: var(--text-muted); }
.cai-range-line { margin-top: 6px; font-size: calc(13px * var(--fs, 1)); color: var(--text-muted); overflow-wrap: anywhere; }
.cai-range-line .mono { color: var(--text); }
.cai-progress { margin-top: 12px; height: 10px; border-radius: 999px; background: var(--subtle-bg); overflow: hidden; }
.cai-progress > span { display: block; height: 100%; border-radius: inherit; background: var(--success); transition: width .4s var(--ease-out); }
.cai-card.cai-soon .cai-progress > span { background: var(--warn-text); }
.cai-card.cai-urgent .cai-progress > span, .cai-card.cai-danger .cai-progress > span { background: var(--danger); }
.cai-progress-label { margin-top: 5px; font-size: calc(12px * var(--fs, 1)); color: var(--text-faint); }
.cai-stats { margin-top: 12px; gap: 10px; }
.cai-stats .stat-num { font-size: calc(18px * var(--fs, 1)); }
.cai-stats .stat-num.cai-next { font-size: calc(14px * var(--fs, 1)); line-height: 1.6; overflow-wrap: anywhere; }
.cai-message { margin-top: 12px; padding: 9px 12px; border-radius: 8px; background: var(--warn-bg); color: var(--warn-text); font-size: calc(13px * var(--fs, 1)); font-weight: 600; }
.cai-card.cai-urgent .cai-message, .cai-card.cai-danger .cai-message { background: var(--danger-bg); color: var(--danger); }
.cai-range-list { display: flex; flex-direction: column; gap: 10px; }
.cai-range-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 14px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); transition: border-color .15s var(--ease-out); }
.cai-range-row.is-active { border-color: var(--success-border); background: color-mix(in srgb, var(--success-bg) 45%, var(--surface)); }
.cai-range-main { min-width: 0; flex: 1; }
.cai-range-top { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.cai-range-sub { margin-top: 4px; font-size: calc(12px * var(--fs, 1)); color: var(--text-faint); overflow-wrap: anywhere; }
.cai-range-actions { display: flex; align-items: center; gap: 6px; flex: none; }
.cai-preview { margin: -4px 0 12px; font-size: calc(12.5px * var(--fs, 1)); color: var(--text-muted); overflow-wrap: anywhere; }
.cai-active-toggle { display: flex; align-items: center; gap: 10px; margin: 4px 0 14px; font-size: calc(13.5px * var(--fs, 1)); color: var(--text); cursor: pointer; }
@media (hover: hover) and (pointer: fine) { .cai-range-row:hover { border-color: var(--secondary); } }
@media (max-width: 560px) {
  .cai-range-row { flex-direction: column; align-items: stretch; }
  .cai-range-actions { justify-content: flex-end; }
  .cai-head-actions { width: 100%; }
}


/* ===== static/css/app/finanzas/pronostico.css ===== */
/* Ventas → Pronóstico del mes (N15, 2026-11-04). Ver finanzas/pronostico.js. */
.fc-card { --fc-actual: var(--chart-1); --fc-proj: #2d6fc0; --fc-goal: var(--success); --fc-band: rgba(45, 111, 192, .14); }
:root[data-theme="dark"] .fc-card { --fc-proj: #6aa8ff; --fc-band: rgba(106, 168, 255, .16); }
.fc-live { font-size: calc(11px * var(--fs, 1)); }

.fc-hero { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: 18px 28px; align-items: center; margin: 12px 0 16px; }
.fc-hero-label { font-size: calc(13px * var(--fs, 1)); color: var(--text-muted); font-weight: 600; }
.fc-hero-num { font-size: clamp(26px, 4.2vw, 40px); font-weight: 850; line-height: 1.1; color: var(--text); letter-spacing: -.01em; margin: 2px 0 4px; overflow-wrap: anywhere; }
.fc-hero-range { font-size: calc(12.5px * var(--fs, 1)); color: var(--text-muted); }
.fc-hero-range b { color: var(--text); font-variant-numeric: tabular-nums; }
.fc-goal { margin-top: 10px; padding: 8px 12px; border-radius: 10px; font-size: calc(13px * var(--fs, 1)); line-height: 1.45; }
.fc-goal.is-ok { background: color-mix(in srgb, var(--success) 12%, transparent); color: var(--success); }
.fc-goal.is-short { background: var(--warn-bg); color: var(--warn-text); }
.fc-goal.is-none { background: var(--subtle-bg); color: var(--text-muted); }
.fc-goal b { font-variant-numeric: tabular-nums; }

.fc-meter-track { position: relative; height: 18px; border-radius: 999px; background: var(--subtle-bg); overflow: visible; }
.fc-meter-range { position: absolute; top: 0; bottom: 0; border-radius: 999px; background: var(--fc-band); outline: 1px dashed color-mix(in srgb, var(--fc-proj) 55%, transparent); }
.fc-meter-sold { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 999px; background: var(--fc-actual); transition: width .45s var(--ease-out, ease); }
.fc-meter-mark, .fc-meter-goal { position: absolute; top: -5px; bottom: -5px; width: 3px; margin-left: -1.5px; border-radius: 2px; transition: left .45s var(--ease-out, ease); }
.fc-meter-mark { background: var(--fc-proj); box-shadow: 0 0 0 2px var(--surface); }
.fc-meter-goal { background: var(--fc-goal); }
.fc-meter-legend { display: flex; flex-wrap: wrap; gap: 4px 12px; margin-top: 10px; font-size: calc(11.5px * var(--fs, 1)); color: var(--text-muted); }
.fc-meter-legend span { display: inline-flex; align-items: center; gap: 5px; }
.fc-meter-legend i, .fc-card .mom-legend i { display: inline-block; width: 14px; height: 8px; border-radius: 3px; }
.fc-sw-sold, .fc-sw-actual { background: var(--fc-actual); }
.fc-sw-range, .fc-sw-band { background: var(--fc-band); outline: 1px dashed var(--fc-proj); }
.fc-sw-mark { background: var(--fc-proj); width: 4px !important; }
.fc-sw-goal { background: var(--fc-goal); width: 4px !important; }
.fc-sw-proj { background: repeating-linear-gradient(90deg, var(--fc-proj) 0 4px, transparent 4px 7px); height: 3px !important; }
.fc-sw-prev { background: var(--text-faint); height: 2px !important; }
.fc-sw-goalline { background: repeating-linear-gradient(90deg, var(--fc-goal) 0 5px, transparent 5px 8px); height: 2px !important; }

.fc-tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; }
.fc-tile { padding: 12px 14px; border: 1px solid var(--border); border-radius: 12px; background: var(--surface); min-width: 0; }
.fc-tile span { display: block; font-size: calc(11.5px * var(--fs, 1)); color: var(--text-muted); font-weight: 700; text-transform: uppercase; letter-spacing: .03em; }
.fc-tile b { display: block; font-size: clamp(15px, 1.7vw, 19px); font-weight: 800; color: var(--text); margin: 4px 0 2px; overflow-wrap: anywhere; }
.fc-tile b i { font-style: normal; color: var(--text-faint); font-weight: 400; }
.fc-tile small { font-size: calc(11.5px * var(--fs, 1)); color: var(--text-faint); }

.fc-controls { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 12px 26px; align-items: end; margin: 16px 0 6px; }
.fc-control-label { font-size: calc(12.5px * var(--fs, 1)); color: var(--text-muted); font-weight: 600; margin-bottom: 6px; }
.fc-control-label b { color: var(--main); }
:root[data-theme="dark"] .fc-control-label b { color: #8fbfff; }
.fc-rate-row { display: flex; align-items: center; gap: 10px; }
.fc-rate-row input[type="range"] { flex: 1; min-width: 120px; accent-color: var(--main); }

.fc-chart { width: 100%; overflow: hidden; margin-top: 10px; }
.fc-chart svg { display: block; max-width: 100%; }
.fc-actual-line { stroke: var(--fc-actual); stroke-width: 2.6; stroke-linejoin: round; stroke-linecap: round; }
.fc-proj-line { stroke: var(--fc-proj); stroke-width: 2.4; stroke-dasharray: 6 5; stroke-linecap: round; }
.fc-band { fill: var(--fc-band); }
.fc-prev-line { stroke: var(--text-faint); stroke-width: 1.6; opacity: .7; }
.fc-goal-line { stroke: var(--fc-goal); stroke-width: 1.5; stroke-dasharray: 5 4; }
.fc-goal-text { font-size: calc(11px * var(--fs, 1)); fill: var(--fc-goal); font-weight: 700; }
.fc-today-dot { fill: var(--surface); stroke: var(--fc-actual); stroke-width: 2.5; }
.fc-end-dot { fill: var(--fc-proj); stroke: var(--surface); stroke-width: 2; }
.fc-band, .fc-proj-line, .fc-end-dot { transition: opacity .2s ease; }

.fc-sellers { margin-top: 16px; }
.fc-sellers-title { font-size: calc(13px * var(--fs, 1)); font-weight: 800; margin-bottom: 8px; }
.fc-sellers-table tr.is-off td { opacity: .5; }
.fc-sellers-table tr.is-off td:first-child { opacity: 1; }
.fc-seller-name { all: unset; cursor: pointer; font-weight: 700; color: var(--accent-text); border-bottom: 1px dashed currentColor; }
.fc-seller-name:focus-visible { outline: 2px solid var(--secondary); outline-offset: 2px; }
.fc-rate-pill { display: inline-block; padding: 2px 8px; border-radius: 999px; background: var(--subtle-bg); font-weight: 700; font-variant-numeric: tabular-nums; }
.fc-quotes-row td { background: var(--subtle-bg); white-space: normal; }
.fc-quote { all: unset; box-sizing: border-box; display: grid; grid-template-columns: 110px minmax(0, 1fr) auto auto; gap: 10px; align-items: center; width: 100%; padding: 6px 8px; border-radius: 8px; cursor: pointer; font-size: calc(12.5px * var(--fs, 1)); }
.fc-quote:hover, .fc-quote:focus-visible { background: var(--surface); }
.fc-quote small { color: var(--text-faint); }

.fc-how { margin-top: 14px; font-size: calc(12.5px * var(--fs, 1)); color: var(--text-muted); }
.fc-how summary { cursor: pointer; font-weight: 700; color: var(--accent-text); }
.fc-how ul { margin: 8px 0 0; padding-left: 18px; line-height: 1.55; }

@media (max-width: 900px) {
  .fc-hero { grid-template-columns: 1fr; }
  .fc-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .fc-controls { grid-template-columns: 1fr; }
}
@media (max-width: 480px) {
  .fc-tile { padding: 10px; }
  .fc-tile b { font-size: calc(14px * var(--fs, 1)); }
  .fc-quote { grid-template-columns: 1fr auto; }
  .fc-quote small { grid-column: 1 / -1; }
}

/* ===== static/css/app/finanzas/flujo-caja.css ===== */
/* Finanzas → Flujo de Caja (N21, 2026-11-06). Ver finanzas/flujo-caja.js. */
.cj-top { display: grid; grid-template-columns: minmax(220px, 280px) minmax(0, 1fr); gap: 16px; align-items: start; }
.cj-bank-row { display: flex; gap: 8px; align-items: center; }
.cj-bank-row .input-prefix-group { flex: 1; min-width: 0; }
.cj-stale { color: var(--warn-text); font-weight: 600; }
.cj-top-main { min-width: 0; }
.cj-tile-bad b { color: var(--danger); }
.fc-goal.cj-verdict-bad { background: color-mix(in srgb, var(--danger) 12%, transparent); color: var(--danger); }

.cj-controls { margin-top: 0; }
.cj-controls input[type="range"] { width: 100%; }
.cj-switches { display: flex; flex-wrap: wrap; gap: 10px 20px; align-items: center; margin-top: 12px; }
.cj-switches .inv-add-include { margin: 0; }

.cj-chart svg { display: block; width: 100%; height: auto; }
.cj-grid { stroke: var(--border); stroke-width: 1; }
.cj-zero { stroke: var(--text-faint); stroke-width: 1; }
.cj-axis { fill: var(--text-faint); font-size: 11px; font-variant-numeric: tabular-nums; }
.cj-line { fill: none; stroke: var(--chart-1); stroke-width: 2; stroke-linejoin: round; }
.cj-area { fill: var(--chart-1); opacity: .1; }
.cj-dot { fill: var(--chart-1); stroke: var(--surface); stroke-width: 2; }
.cj-dot.is-short { fill: var(--danger); }
.cj-low-label { fill: var(--text); font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums; }
.cj-hit { fill: transparent; cursor: pointer; }
.cj-hit:hover { fill: color-mix(in srgb, var(--text) 5%, transparent); }
.cj-legend { display: flex; flex-wrap: wrap; gap: 4px 14px; margin-bottom: 8px; font-size: calc(12px * var(--fs, 1)); color: var(--text-muted); }
.cj-legend span { display: inline-flex; align-items: center; gap: 6px; }
.cj-legend i { width: 10px; height: 10px; border-radius: 3px; }

.cj-num { text-align: right !important; white-space: nowrap; }
.cj-week-row { cursor: pointer; }
.cj-week-row.is-open td { background: var(--subtle-bg); }
.cj-week-row.is-short .cj-bal { color: var(--danger); font-weight: 700; }
.cj-week-row .cj-bal { font-weight: 700; }
.cj-week-row:focus-visible { outline: 2px solid var(--main); outline-offset: -2px; }
.cj-detail-row > td { background: var(--subtle-bg); padding: 8px 12px 12px; white-space: normal; }
.cj-table { min-width: 600px; }
.cj-eye-cell { width: 44px; text-align: right !important; padding-right: 8px !important; }
.cj-eye { color: var(--text-muted); }
.cj-week-row:hover .cj-eye, .cj-eye.is-open { color: var(--main); background: var(--secondary-light); }
.hint svg { vertical-align: -2px; }

/* Otros movimientos (2026-11-07): más aire a los lados y acciones juntas a la derecha. */
#cj-manual .card-head-row { margin-bottom: 12px; }
.cj-manual-table { min-width: 560px; }
.cj-manual-table th, .cj-manual-table td { padding-left: 16px; padding-right: 16px; }
.cj-manual-table td { padding-top: 10px; padding-bottom: 10px; vertical-align: middle; }
.cj-manual-table td:first-child { font-weight: 600; }
.cj-manual-table td:nth-child(2), .cj-manual-table td:nth-child(3) { white-space: nowrap; }
.cj-actions-th, .cj-actions { width: 1%; text-align: right; white-space: nowrap; }
.cj-actions { padding-right: 12px !important; }
.cj-actions .btn + .btn { margin-left: 6px; }

.cj-events { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; max-height: 380px; overflow-y: auto; }
.cj-event { display: flex; align-items: center; gap: 10px; padding: 6px 8px; border-radius: 8px; background: var(--surface); min-width: 0; }
.cj-event.is-off { opacity: .55; }
.cj-event.is-off b { text-decoration: line-through; }
.cj-event-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.cj-event-main small { color: var(--text-faint); font-size: calc(11.5px * var(--fs, 1)); }
.cj-event-link { all: unset; cursor: pointer; color: var(--main); font-weight: 600; overflow-wrap: anywhere; }
.cj-event-link:hover { text-decoration: underline; }
.cj-event-link:focus-visible { outline: 2px solid var(--main); border-radius: 3px; }
.cj-event > b { white-space: nowrap; font-size: calc(13px * var(--fs, 1)); }
.cj-in { color: var(--success); }
.cj-out { color: var(--text); }
.cj-late { color: var(--warn-text); background: var(--warn-bg); }
.cj-inactive { opacity: .55; }

@media (max-width: 900px) {
  .cj-top { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 640px) {
  .cj-axis { font-size: 16px; }
  .cj-low-label { font-size: 17px; }
  .cj-event { flex-wrap: wrap; }
  .cj-event-main { flex-basis: calc(100% - 60px); }
  .cj-event > b { margin-left: auto; }
}

/* ===== static/css/app/clientes/ficha-360.css ===== */
/* ------------------------------------------------------------------ */
/* Clientes → Ficha 360 y Estado de cuenta (clientes/cliente-360.js,        */
/* 2026-10-13). Fichas con Spotlight/Count Up (.spotlight-page en la   */
/* ventana), filas con Blur Fade (.bf-row) y colores de estatus de     */
/* siempre. Solo tokens de :root, así el modo oscuro sale solo.        */
/* ------------------------------------------------------------------ */
.c360-title-wrap { min-width: 0; }
.c360-title-wrap .modal-title { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; overflow-wrap: anywhere; }
.c360-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px 16px; flex-wrap: wrap; margin-bottom: 14px; }
.c360-head-info { flex: 1 1 260px; min-width: 0; }
.c360-tags { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; font-size: calc(12.5px * var(--fs, 1)); }
.c360-meta { display: flex; flex-wrap: wrap; gap: 4px 16px; margin-top: 8px; font-size: calc(13px * var(--fs, 1)); color: var(--text); }
.c360-muted { color: var(--text-muted); font-size: calc(12.5px * var(--fs, 1)); font-weight: 500; }
.c360-notes { margin-top: 6px; font-size: calc(12.5px * var(--fs, 1)); color: var(--text-muted); overflow-wrap: anywhere; }
.c360-actions { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; }
.c360-contacts { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 250px), 1fr)); gap: 8px; margin-bottom: 14px; }
.c360-contacts-empty { display: block; font-size: calc(12.5px * var(--fs, 1)); color: var(--text-muted); }
.c360-contact {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "name btns" "sub btns";
  gap: 2px 8px; align-items: center; padding: 8px 8px 8px 12px;
  border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--bg);
}
.c360-contact-name { grid-area: name; font-weight: 700; font-size: calc(13px * var(--fs, 1)); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.c360-contact-sub { grid-area: sub; min-width: 0; font-size: calc(12px * var(--fs, 1)); color: var(--text-muted); overflow-wrap: anywhere; }
.c360-contact-btns { grid-area: btns; display: flex; gap: 2px; }
.c360-contact-btns .btn-icon svg { width: 15px; height: 15px; }
.c360-wa { color: #1fa855; }
.c360-chip-tag { font-size: calc(10.5px * var(--fs, 1)); font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--badge-purple-text); background: var(--badge-purple-bg); border-radius: 999px; padding: 1px 6px; margin-right: 2px; }
.c360-contact-mail { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.c360-stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; margin-bottom: 14px; }
.c360-tile { padding: 12px 14px; }
.c360-tile .stat-num { font-size: calc(19px * var(--fs, 1)); }
.c360-tile .stat-num.c360-last { font-size: calc(17px * var(--fs, 1)); }
.c360-tile .stat-label { font-size: calc(11px * var(--fs, 1)); }
.c360-tile-sub { font-size: calc(11.5px * var(--fs, 1)); color: var(--text-muted); margin-top: 2px; }
.c360-tabs-row { display: flex; margin-bottom: 12px; }
.c360-section { margin-bottom: 12px; padding: 14px 16px; }
.c360-section .card-title { margin-bottom: 10px; }
.c360-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; align-items: start; margin-bottom: 12px; }
.c360-card .c360-section, .c360-card .c360-section + .c360-section { margin-top: 0; }
.c360-grid > .c360-section { margin-bottom: 0; }
.c360-status-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.c360-status-chip {
  display: inline-flex; align-items: center; gap: 8px; padding: 3px 12px 3px 3px; font: inherit; font-size: calc(13px * var(--fs, 1));
  border: 1px solid var(--border); border-radius: 999px; background: var(--surface); color: var(--text); cursor: pointer;
  transition: border-color .15s var(--ease-out), transform .16s var(--ease-out);
}
.c360-status-chip:active { transform: scale(.97); }
.c360-top { list-style: none; margin: 0; padding: 0; counter-reset: c360top; }
.c360-top li { display: flex; align-items: center; gap: 10px; padding: 6px 0; border-bottom: 1px solid var(--row-border); font-size: calc(13px * var(--fs, 1)); counter-increment: c360top; }
.c360-top li:last-child { border-bottom: none; }
.c360-top li::before {
  content: counter(c360top); flex: none; width: 20px; height: 20px; border-radius: 50%; display: grid; place-items: center;
  font-size: calc(11px * var(--fs, 1)); font-weight: 800; background: var(--secondary-light); color: var(--accent-text);
}
.c360-top-desc { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.c360-top-n { color: var(--text-muted); font-size: calc(12px * var(--fs, 1)); white-space: nowrap; }
.c360-empty { color: var(--text-muted); font-size: calc(13px * var(--fs, 1)); padding: 4px 0; }
.c360-tl { list-style: none; margin: 0; padding: 0; position: relative; }
.c360-tl::before { content: ""; position: absolute; left: 5px; top: 10px; bottom: 10px; width: 2px; background: var(--border); border-radius: 2px; }
.c360-tl-item { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 2px 10px; padding: 6px 0 6px 22px; font-size: calc(13px * var(--fs, 1)); }
.c360-tl-dot { position: absolute; left: 0; top: 10px; width: 12px; height: 12px; border-radius: 50%; background: var(--surface); border: 2px solid var(--accent-text); }
.c360-tl-new .c360-tl-dot { border-color: var(--secondary); }
.c360-tl-invoice .c360-tl-dot { border-color: var(--badge-purple-text); }
.c360-tl-paid .c360-tl-dot { border-color: var(--success); background: var(--success); }
.c360-tl-text { min-width: 0; overflow-wrap: anywhere; }
.c360-tl-date { color: var(--text-muted); font-size: calc(12px * var(--fs, 1)); white-space: nowrap; }
.c360-link { background: none; border: none; padding: 0; font: inherit; color: var(--text); text-align: left; cursor: pointer; }
.c360-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
.c360-toolbar select { width: auto; min-width: 150px; }
.c360-table th, .c360-table td { white-space: nowrap; }
.c360-table td.c360-desc { max-width: 220px; overflow: hidden; text-overflow: ellipsis; }
.c360-sub { font-size: calc(11.5px * var(--fs, 1)); color: var(--text-muted); font-family: var(--font); }
.c360-more { margin-top: 10px; width: 100%; justify-content: center; }
.c360-contacts-more { margin: -6px 0 14px; }
.c360-inv-status .aging-pill { margin-left: 4px; }
.c360-show-sm { display: none; }
.c360-show-sm.c360-inv-status { margin-top: 4px; font-family: var(--font); }
.c360-stmt-card { max-width: 520px; }
.c360-stmt-modes { display: grid; gap: 8px; margin-bottom: 14px; }
.c360-stmt-mode {
  display: flex; gap: 12px; align-items: flex-start; text-align: left; padding: 12px 14px; font: inherit;
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); color: var(--text); cursor: pointer;
  transition: border-color .15s var(--ease-out), background-color .15s var(--ease-out), transform .16s var(--ease-out);
}
.c360-stmt-mode:active { transform: scale(.99); }
.c360-stmt-mode.is-on { border-color: var(--accent-text); background: var(--secondary-light); box-shadow: inset 0 0 0 1px var(--accent-text); }
.c360-stmt-radio { flex: none; position: relative; width: 18px; height: 18px; margin-top: 1px; border-radius: 50%; border: 2px solid var(--border); transition: border-color .15s var(--ease-out); }
.c360-stmt-mode.is-on .c360-stmt-radio { border-color: var(--accent-text); }
.c360-stmt-mode.is-on .c360-stmt-radio::after { content: ""; position: absolute; inset: 3px; border-radius: 50%; background: var(--accent-text); }
.c360-stmt-title { display: block; font-weight: 700; font-size: calc(14px * var(--fs, 1)); }
.c360-stmt-desc { display: block; margin-top: 2px; font-size: calc(12.5px * var(--fs, 1)); line-height: 1.4; color: var(--text-muted); }
.c360-stmt-period[hidden] { display: none; }
@media (hover: hover) and (pointer: fine) {
  .c360-status-chip:hover { border-color: var(--accent-text); }
  .c360-link:hover { color: var(--accent-text); text-decoration: underline; }
  .c360-stmt-mode:not(.is-on):hover { border-color: var(--accent-text); }
}
@media (max-width: 700px) {
  .c360-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .c360-grid { grid-template-columns: minmax(0, 1fr); }
  .c360-actions { align-items: stretch; width: 100%; }
  .c360-scope, .c360-tabs-row .view-toggle { display: flex; width: 100%; }
  .c360-scope .view-toggle-btn, .c360-tabs-row .view-toggle-btn { flex: 1; padding-left: 6px; padding-right: 6px; }
  .c360-hide-sm { display: none; }
  .c360-show-sm { display: block; }
  .c360-table th, .c360-table td { white-space: normal; padding-left: 8px; padding-right: 8px; }
  .c360-table td.mono { overflow-wrap: anywhere; }
  .c360-table td.c360-money, .c360-table td.c360-code { white-space: nowrap; overflow-wrap: normal; }
  .c360-table td.c360-code .c360-sub { white-space: normal; }
  .c360-section { padding: 12px; }
  .c360-tile { padding: 10px 10px 10px 12px; }
  .c360-tile .stat-num { font-size: clamp(13px, 4vw, 19px); overflow-wrap: normal; white-space: nowrap; }
  .c360-tile .stat-num.c360-last { font-size: calc(15px * var(--fs, 1)); }
  .c360-tabs-row .view-toggle-btn { font-size: calc(12.5px * var(--fs, 1)); }
}


/* ===== static/css/app/ordenes/tabla-agrupada.css ===== */
/* ------------------------------------------------------------------ */
/* Órdenes → Tabla agrupada por cliente, columna Factura y Total        */
/* (2026-10-13, mismo estilo que Cuentas por cobrar)                    */
/* ------------------------------------------------------------------ */
.wo-table-toolbar { display: flex; justify-content: flex-end; align-items: center; gap: 12px; margin-bottom: 6px; }
.wo-table-byclient { display: inline-flex; align-items: center; gap: 8px; font-size: calc(13px * var(--fs, 1)); font-weight: 600; color: var(--text-muted); cursor: pointer; }
.wo-client-row td { background: color-mix(in srgb, var(--main) 6%, var(--surface)); border-top: 1px solid var(--border); padding-top: 10px; padding-bottom: 10px; }
.wo-client-row-inner { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.wo-client-row-name { font-weight: 800; color: var(--text); font-size: calc(14px * var(--fs, 1)); }
.wo-client-row-group { font-size: calc(12px * var(--fs, 1)); color: var(--text-muted); background: var(--subtle-bg); border-radius: 999px; padding: 1px 8px; }
.wo-client-row-meta { font-size: calc(12px * var(--fs, 1)); color: var(--text-muted); }
.wo-client-row-total { font-weight: 800; color: var(--text); font-variant-numeric: tabular-nums; background: color-mix(in srgb, var(--main) 10%, transparent); border-radius: 6px; padding: 1px 8px; }
.wo-table-by-client .wo-table-in-client td:first-child { box-shadow: inset 3px 0 0 color-mix(in srgb, var(--main) 35%, transparent); }
.wo-table-money { text-align: right; font-weight: 700; white-space: nowrap; }
.wo-table-muted { color: var(--text-faint); font-size: calc(12.5px * var(--fs, 1)); }
.wo-table-inv { font-size: calc(12.5px * var(--fs, 1)); white-space: nowrap; }
.wo-split-badge { display: inline-flex; align-items: center; font-size: calc(11px * var(--fs, 1)); font-weight: 800; color: var(--main); background: color-mix(in srgb, var(--main) 12%, transparent); border-radius: 999px; padding: 0 7px; line-height: 18px; vertical-align: 1px; cursor: help; }
:root[data-theme="dark"] .wo-split-badge { color: var(--secondary-light, #9cc8ff); }

/* Cuentas por cobrar: factura(s) de cada orden; "Repartida en N" (2026-10-13) */
.rec-invs { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; }
.rec-split-tag { font-size: calc(10.5px * var(--fs, 1)); font-weight: 800; letter-spacing: .02em; text-transform: uppercase; color: var(--main); background: color-mix(in srgb, var(--main) 11%, transparent); border-radius: 999px; padding: 1px 8px; }
.rec-inv-chip { display: inline-flex; flex-wrap: wrap; align-items: baseline; gap: 2px 6px; text-align: left; font-size: calc(12.5px * var(--fs, 1)); color: var(--text); background: var(--subtle-bg); border: 1px dashed color-mix(in srgb, var(--warn-text) 45%, transparent); border-radius: 8px; padding: 3px 8px; cursor: pointer; transition: border-color .15s var(--ease-out), background-color .15s var(--ease-out), transform .12s var(--ease-out); }
.rec-inv-chip:disabled { cursor: default; }
.rec-inv-chip.is-paid { border-style: solid; border-color: color-mix(in srgb, var(--success) 45%, transparent); }
.rec-inv-chip:active:not(:disabled) { transform: scale(.97); }
.rec-inv-ok { color: var(--success); font-weight: 800; }
.rec-inv-part { flex-basis: 100%; font-family: var(--font); font-size: calc(11px * var(--fs, 1)); color: var(--text-muted); }
@media (hover: hover) and (pointer: fine) { .rec-inv-chip:not(:disabled):not(.is-paid):hover { border-style: solid; border-color: var(--main); background: color-mix(in srgb, var(--main) 7%, var(--subtle-bg)); } }

/* Ventana de número de factura: sugerencia y aviso del CAI (2026-10-13) */
.split-inv-suggest { margin-top: 5px; display: inline-flex; gap: 6px; align-items: baseline; font-size: calc(12px * var(--fs, 1)); color: var(--main); background: color-mix(in srgb, var(--main) 8%, transparent); border: 1px dashed color-mix(in srgb, var(--main) 40%, transparent); border-radius: 8px; padding: 3px 9px; cursor: pointer; max-width: 100%; flex-wrap: wrap; text-align: left; }
.split-inv-suggest:active { transform: scale(.97); }
:root[data-theme="dark"] .split-inv-suggest { color: var(--secondary-light, #9cc8ff); }
.split-inv-warn { margin: 6px 0 10px; padding: 9px 12px; border-radius: 10px; background: var(--warn-bg); color: var(--warn-text); font-size: calc(13px * var(--fs, 1)); line-height: 1.4; }
@media (hover: hover) and (pointer: fine) { .split-inv-suggest:hover { border-style: solid; } }
:root[data-theme="dark"] .rec-split-tag { color: var(--secondary-light, #9cc8ff); background: color-mix(in srgb, var(--secondary-light, #9cc8ff) 14%, transparent); }
/* Datos de la factura al pasar a Cobro (2026-10-15): fecha real, SOLPE y Solicitó. */
.inv-extras { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0 14px; margin: 4px 0 6px; }
.inv-extras .field { min-width: 0; }
.inv-extras-title { margin-top: 6px; }
.hint-inline { font-weight: 400; color: var(--text-muted); font-size: calc(12px * var(--fs, 1)); }
@media (max-width: 640px) { .inv-extras { grid-template-columns: 1fr; } }


/* ===== static/css/app/ordenes/linea-tiempo.css ===== */
/* Órdenes → Línea de tiempo (N02, 2026-11-11). Una fila por orden: la
   etiqueta fija a la izquierda y la pista con una columna por día. */
.wo-gantt-head { flex-wrap: wrap; row-gap: 8px; }
.wo-gantt-head #wo-gantt-today { margin-left: auto; }
.wo-gantt-range { margin: 0; }
.wo-gantt-closed { margin: 0; white-space: nowrap; }
.wo-gantt-scroll { overflow-x: auto; margin-top: 10px; border: 1px solid var(--border); border-radius: var(--radius-sm); }
.wo-gantt { --label-w: 190px; --day-w: 34px; min-width: calc(var(--label-w) + var(--days) * var(--day-w)); }
.wo-gantt-row { display: grid; grid-template-columns: var(--label-w) minmax(0, 1fr); border-top: 1px solid var(--row-border); }
.wo-gantt-row:first-child { border-top: none; }
.wo-gantt-row[data-wo-id] { cursor: pointer; }
.wo-gantt-row[data-wo-id]:hover, .wo-gantt-row[data-wo-id]:focus-visible { background: var(--row-hover-bg, var(--subtle-bg)); outline: none; }
.wo-gantt-row[data-wo-id]:focus-visible .wo-gantt-label { box-shadow: inset 3px 0 0 var(--accent); }
.wo-gantt-label { position: sticky; left: 0; z-index: 2; background: var(--surface); display: flex; flex-direction: column; justify-content: center; gap: 1px; padding: 5px 10px; min-width: 0; border-right: 1px solid var(--border); font-size: calc(12px * var(--fs, 1)); }
.wo-gantt-row[data-wo-id]:hover .wo-gantt-label { background: var(--row-hover-bg, var(--subtle-bg)); }
.wo-gantt-label .mono { font-weight: 700; }
.wo-gantt-client { color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wo-gantt-track { position: relative; display: grid; grid-template-columns: repeat(var(--days), minmax(var(--day-w), 1fr)); align-items: center; min-height: 38px; }
.wo-gantt-track > i { grid-row: 1; height: 100%; border-left: 1px solid var(--row-border); }
.wo-gantt-track > i:first-child { border-left: none; }
.wo-gantt-track > i.is-today { background: color-mix(in srgb, var(--accent) 8%, transparent); }
.wo-gantt-now { grid-row: 1; justify-self: center; width: 2px; height: 100%; background: var(--accent); opacity: .55; z-index: 1; pointer-events: none; }
.wo-gantt-bar { grid-row: 1; height: 16px; margin: 0 2px; border-radius: 8px; background: color-mix(in srgb, var(--bar) 70%, transparent); border: 1px solid var(--bar); z-index: 1; }
.wo-gantt-bar.cut-l { border-top-left-radius: 0; border-bottom-left-radius: 0; margin-left: 0; border-left-style: dashed; }
.wo-gantt-bar.cut-r { border-top-right-radius: 0; border-bottom-right-radius: 0; margin-right: 0; border-right-style: dashed; }
.wo-gantt-bar.is-hold { background: repeating-linear-gradient(135deg, color-mix(in srgb, var(--bar) 70%, transparent) 0 6px, color-mix(in srgb, var(--bar) 30%, transparent) 6px 12px); }
.wo-gantt-late, .wo-gantt-late-key { grid-row: 1; height: 8px; margin: 0 2px; border-radius: 4px; background: repeating-linear-gradient(90deg, var(--danger) 0 6px, transparent 6px 10px); z-index: 1; }
.wo-gantt-scroll.is-slide-next .wo-gantt { animation: wo-gantt-next 200ms var(--ease-out); }
.wo-gantt-scroll.is-slide-prev .wo-gantt { animation: wo-gantt-prev 200ms var(--ease-out); }
@keyframes wo-gantt-next { from { opacity: 0; transform: translateX(24px); } }
@keyframes wo-gantt-prev { from { opacity: 0; transform: translateX(-24px); } }
@media (prefers-reduced-motion: reduce) { .wo-gantt-scroll .wo-gantt { animation: none !important; } }
.wo-gantt-legend { margin: 10px 0 0; }
.wo-gantt-hold-key, .wo-gantt-load-key { display: inline-block; width: 26px; height: 10px; border-radius: 5px; margin-right: 6px; vertical-align: middle; }
.wo-gantt-hold-key { background: repeating-linear-gradient(135deg, var(--text-faint) 0 4px, transparent 4px 8px); border: 1px solid var(--text-faint); }
.wo-gantt-load-key { border-radius: 3px; background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--danger) 38%, transparent)); border: 1px solid var(--row-border); }
.wo-gantt-late-key { display: inline-block; width: 26px; margin: 0 6px 0 0; vertical-align: middle; }
/* Encabezado de días y fila de carga */
.wo-gantt-headrow, .wo-gantt-loadrow { cursor: default; }
.wo-gantt-headrow .wo-gantt-label, .wo-gantt-loadrow .wo-gantt-label { font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: .03em; font-size: calc(11px * var(--fs, 1)); }
.wo-gantt-day { display: flex; flex-direction: column; align-items: center; padding: 4px 0; font-size: calc(10px * var(--fs, 1)); color: var(--text-muted); border-left: 1px solid var(--row-border); }
.wo-gantt-day:first-child { border-left: none; }
.wo-gantt-day b { font-size: calc(13px * var(--fs, 1)); color: var(--text); }
.wo-gantt-day.is-weekend { background: var(--subtle-bg); }
.wo-gantt-day.is-today { background: color-mix(in srgb, var(--accent) 16%, transparent); }
.wo-gantt-day.is-today b { color: var(--accent-text); }
.wo-gantt-load { align-self: stretch; display: grid; place-items: center; font-size: calc(11px * var(--fs, 1)); font-weight: 800; font-variant-numeric: tabular-nums; color: var(--text); border-left: 1px solid var(--row-border); background: color-mix(in srgb, var(--danger) calc(var(--heat) * 38%), transparent); min-height: 26px; }
.wo-gantt-load:first-child { border-left: none; }
@media (max-width: 640px) {
  .wo-gantt { --label-w: 112px; --day-w: 30px; }
  .wo-gantt-head #wo-gantt-today { margin-left: 0; }
}

/* ===== static/css/app/ordenes/vista-rapida.css ===== */
/* Vista rápida de la ficha del Kanban (N31, 2026-11-11). */
.wo-peek { position: fixed; top: 0; left: 0; z-index: 900; width: 300px; max-width: calc(100vw - 16px); max-height: 70vh; overflow: hidden; padding: 12px 14px; border-radius: var(--radius); background: var(--surface); border: 1px solid var(--border); box-shadow: 0 12px 32px rgba(0, 0, 0, .18); pointer-events: none; opacity: 0; transition: opacity .14s ease; font-size: calc(12.5px * var(--fs, 1)); }
.wo-peek.is-in { opacity: 1; }
.wo-peek.no-fade { transition: none; }
.wo-peek-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-weight: 700; }
.wo-peek-status { font-size: calc(11px * var(--fs, 1)); font-weight: 700; padding: 2px 8px; border-radius: 999px; color: var(--text); background: color-mix(in srgb, var(--st) 22%, transparent); border: 1px solid color-mix(in srgb, var(--st) 55%, transparent); white-space: nowrap; }
.wo-peek-client { font-weight: 700; font-size: calc(14px * var(--fs, 1)); margin: 2px 0 6px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wo-peek-note { display: flex; gap: 6px; align-items: flex-start; padding: 6px 8px; border-radius: var(--radius-sm); background: var(--warning-bg, var(--subtle-bg)); margin-bottom: 6px; }
.wo-peek-note svg { width: 14px; height: 14px; flex: none; margin-top: 1px; }
.wo-peek-hold { color: var(--warning-text, var(--text-muted)); font-weight: 600; margin-bottom: 6px; }
.wo-peek-label { margin-top: 8px; font-size: calc(10.5px * var(--fs, 1)); font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: .04em; }
.wo-peek-items { list-style: none; margin: 4px 0 0; padding: 0; display: flex; flex-direction: column; gap: 3px; }
.wo-peek-items li { display: grid; grid-template-columns: 34px minmax(0, 1fr); gap: 6px; }
.wo-peek-items li b { text-align: right; }
.wo-peek-items em { font-style: normal; color: var(--text-muted); }
.wo-peek-more { color: var(--text-muted); margin-top: 3px; }
.wo-peek-who { margin-top: 3px; }
@media (prefers-reduced-motion: reduce) { .wo-peek { transition: none; } }

/* ===== static/css/app/base/graficas.css ===== */
/* ------------------------------------------------------------------ */
/* Gráficas — un solo estilo en toda la app (2026-10-15, nucleo/graficas.js) */
/* ------------------------------------------------------------------ */
.chart-frame { width: 100%; overflow: hidden; }
.chart-frame.chart-scroll { overflow-x: auto; padding-bottom: 4px; scrollbar-width: thin; display: flex; }
.chart-axis-sticky { position: sticky; left: 0; z-index: 1; flex: 0 0 auto; background: linear-gradient(90deg, var(--surface) 82%, transparent); }
.chart-scroll .chart-svg { flex: 0 0 auto; }
.chart-svg { display: block; overflow: visible; font-family: var(--font); }
.chart-empty { padding: 20px 10px; }
.chart-grid { stroke: var(--chart-grid); stroke-width: 1; stroke-dasharray: 3 4; }
.chart-grid.is-base { stroke: var(--border); stroke-dasharray: none; }
.chart-axis { font-size: calc(10.5px * var(--fs, 1)); fill: var(--text-muted); font-variant-numeric: tabular-nums; }
.chart-x { font-size: calc(11px * var(--fs, 1)); fill: var(--text-muted); }
.chart-x.is-sub { font-size: calc(10px * var(--fs, 1)); fill: var(--text-faint); }
.chart-val { font-size: calc(11px * var(--fs, 1)); font-weight: 700; fill: var(--text); font-variant-numeric: tabular-nums; pointer-events: none; }
.chart-val.is-muted { fill: var(--text-faint); font-weight: 600; }
.chart-goal { stroke: var(--success); stroke-width: 1.5; stroke-dasharray: 5 4; opacity: .8; }
.chart-zero { stroke: var(--border); stroke-width: 2; stroke-linecap: round; }
.chart-hit { fill: transparent; cursor: pointer; }
.chart-bar { transform-box: fill-box; transform-origin: bottom; animation: chart-grow-y .65s var(--ease-out) backwards; animation-delay: var(--d, 0ms); transition: opacity .15s ease, filter .15s ease; }
.chart-bar-empty { fill: none; stroke: var(--border); stroke-dasharray: 3 3; }
.chart-bar-g.is-dim .chart-bar { opacity: .45; }
@media (hover: hover) and (pointer: fine) {
  .chart-svg:has(.chart-bar-g:hover) .chart-bar-g:not(:hover) .chart-bar { opacity: .35; }
  .chart-bar-g:hover .chart-bar { opacity: 1; filter: brightness(1.08) saturate(1.1); }
}
.chart-line { stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 1; animation: chart-draw .9s var(--ease-out) backwards; }
.mom-line-cur, .mom-line-prev, .mom-line-ly { animation: chart-fade .7s var(--ease-out) backwards; }
.chart-area { animation: chart-fade .9s var(--ease-out) backwards; }
.chart-dot { stroke-width: 2; transition: r .15s ease; }
.chart-dot.is-on { r: 5.5; }
.chart-dot-last { filter: drop-shadow(0 0 6px color-mix(in srgb, var(--chart-1) 60%, transparent)); }
.chart-cursor { stroke: var(--text-faint); stroke-width: 1; stroke-dasharray: 3 3; pointer-events: none; }
/* Dona */
.chart-donut-track { fill: none; stroke: var(--subtle-bg, var(--bg)); }
.chart-slice { stroke: var(--surface); stroke-width: 1.5; transform-box: view-box; transform-origin: 50% 50%; transition: transform .18s var(--ease-out), opacity .18s ease, filter .18s ease; animation: chart-pop .6s var(--ease-out) backwards; animation-delay: var(--d, 0ms); }
.pie-svg.has-active .chart-slice:not(.is-active) { opacity: .4; }
.chart-slice.is-active { filter: brightness(1.08) saturate(1.1); }
.chart-slice-hit { fill: transparent; cursor: pointer; }
.pie-legend-item { cursor: pointer; transition: background .15s ease; }
.pie-legend-item.is-active { background: var(--bg); }
.pie-legend-pct { flex: 0 0 auto; font-size: calc(11.5px * var(--fs, 1)); color: var(--text-muted); font-variant-numeric: tabular-nums; min-width: 32px; text-align: right; }
/* Globo (tooltip) — vidrio esmerilado, como las tarjetas de Magic UI */
.chart-tip {
  position: fixed; left: 0; top: 0; z-index: 9999; pointer-events: none; min-width: 120px; max-width: 260px;
  padding: 8px 11px; border-radius: 10px; font-size: calc(12.5px * var(--fs, 1)); color: var(--text);
  background: var(--chart-tip-bg); border: 1px solid var(--border);
  -webkit-backdrop-filter: blur(10px) saturate(1.4); backdrop-filter: blur(10px) saturate(1.4);
  box-shadow: 0 8px 28px rgba(16, 34, 64, .16); opacity: 0; transition: opacity .12s ease;
}
.chart-tip.is-on { opacity: 1; }
.chart-tip-title { font-weight: 800; margin-bottom: 3px; }
.chart-tip-row { display: flex; align-items: center; gap: 7px; white-space: nowrap; color: var(--text-muted); }
.chart-tip-row i { width: 9px; height: 9px; border-radius: 3px; flex-shrink: 0; }
.chart-tip-row b { margin-left: auto; padding-left: 10px; color: var(--text); font-variant-numeric: tabular-nums; }
@keyframes chart-grow-y { from { transform: scaleY(0); } }
@keyframes chart-grow-x { from { transform: scaleX(0); } }
@keyframes chart-draw { from { stroke-dashoffset: 1; } }
@keyframes chart-fade { from { opacity: 0; } }
@keyframes chart-pop { from { opacity: 0; transform: scale(.82) rotate(-8deg); } }
@media (prefers-reduced-motion: reduce) {
  .chart-bar, .chart-line, .chart-area, .chart-slice, .yoy-bar, .mom-line-cur, .mom-line-prev, .mom-line-ly { animation: none; }
}

/* Pantalla del taller (TV): tablero "Hoy" a pantalla completa, letra grande */
body.wo-tv-open { overflow: hidden; }
.wo-tv { position: fixed; inset: 0; z-index: 4000; background: var(--bg); color: var(--text); display: flex; flex-direction: column; padding: 2vmin 2.5vmin; gap: 2vmin; }
.wo-tv-head { display: flex; align-items: center; justify-content: space-between; gap: 2vmin; }
.wo-tv-title { font-size: clamp(22px, 4.2vmin, 64px); font-weight: 800; display: flex; flex-direction: column; line-height: 1.1; }
.wo-tv-title span { font-size: .5em; font-weight: 600; color: var(--text-muted); }
.wo-tv-clock-box { margin-left: auto; text-align: right; }
.wo-tv-clock { font-size: clamp(28px, 6vmin, 96px); font-weight: 800; font-variant-numeric: tabular-nums; line-height: 1; }
.wo-tv-status { font-size: clamp(11px, 1.8vmin, 24px); color: var(--text-muted); margin-top: .4vmin; }
.wo-tv-exit { width: 5vmin; height: 5vmin; min-width: 34px; min-height: 34px; border-radius: 50%; border: 1px solid var(--border); background: var(--surface); color: var(--text-muted); font-size: 3vmin; cursor: pointer; opacity: .55; }
.wo-tv-exit { display: grid; place-items: center; padding: 0; line-height: 0; flex: none; }
.wo-tv-exit svg { width: 50%; height: 50%; display: block; }
.wo-tv-exit:hover { opacity: 1; }
.wo-tv-grid { flex: 1; min-height: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 2vmin; }
.wo-tv-col { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); display: flex; flex-direction: column; min-height: 0; overflow: hidden; }
.wo-tv-col-head { display: flex; justify-content: space-between; align-items: center; font-size: clamp(16px, 3vmin, 44px); font-weight: 800; text-transform: uppercase; letter-spacing: .04em; padding: 1.2vmin 1.6vmin; font-variant-numeric: tabular-nums; }
.wo-today-late.wo-tv-col .wo-tv-col-head { color: var(--danger, #b23b3b); background: color-mix(in srgb, var(--danger, #b23b3b) 14%, transparent); }
.wo-today-now.wo-tv-col .wo-tv-col-head { color: var(--accent-text); background: var(--secondary-light); }
.wo-today-next.wo-tv-col .wo-tv-col-head { color: var(--text-muted); background: var(--bg); }
.wo-tv-col-body { flex: 1; min-height: 0; overflow-y: auto; padding: .6vmin 1.2vmin; }
.wo-tv-row { display: flex; align-items: center; gap: 1.2vmin; padding: 1.1vmin .4vmin; border-bottom: 1px solid var(--row-border); cursor: pointer; border-radius: var(--radius-sm); }
.wo-tv-row:hover { background: var(--row-hover-bg, var(--subtle-bg)); }
.wo-tv-row:focus-visible { outline: 2px solid var(--focus-ring, var(--accent)); outline-offset: 1px; }
/* Renglones desplegados al tocar una orden (2026-11-11). */
.wo-tv-chevron { width: 1.4vmin; height: 1.4vmin; min-width: 9px; min-height: 9px; flex-shrink: 0; border-right: 2px solid var(--text-muted); border-bottom: 2px solid var(--text-muted); transform: rotate(45deg) translateY(-25%); transition: transform .18s ease; }
.wo-tv-order.is-open .wo-tv-chevron { transform: rotate(225deg) translateY(-25%); }
.wo-tv-order.is-open .wo-tv-row { background: var(--subtle-bg); border-bottom-color: transparent; }
.wo-tv-items { overflow-x: auto; margin: .4vmin 0 1vmin; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--bg); }
.wo-tv-items table { width: 100%; border-collapse: collapse; font-size: clamp(11px, 1.7vmin, 24px); }
.wo-tv-items th { text-align: left; font-weight: 700; color: var(--text-muted); padding: .6vmin .8vmin; border-bottom: 1px solid var(--border); white-space: nowrap; }
.wo-tv-items td { padding: .6vmin .8vmin; border-bottom: 1px solid var(--row-border); vertical-align: top; }
.wo-tv-items tr:last-child td { border-bottom: none; }
.wo-tv-items.is-opening { animation: wo-tv-open 200ms var(--ease-out); transform-origin: top; }
@keyframes wo-tv-open { from { opacity: 0; transform: translateY(-6px) scaleY(.96); } }
@media (prefers-reduced-motion: reduce) { .wo-tv-items.is-opening { animation: none; } }
.wo-tv-items-empty { font-size: clamp(11px, 1.7vmin, 24px); color: var(--text-muted); padding: .8vmin; }
.wo-tv-row .wo-cal-chip-dot { width: 1.6vmin; height: 1.6vmin; min-width: 10px; min-height: 10px; flex-shrink: 0; }
.wo-tv-main { flex: 1; min-width: 0; }
.wo-tv-client { font-size: clamp(15px, 2.6vmin, 40px); font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wo-tv-meta { font-size: clamp(11px, 1.8vmin, 26px); color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wo-tv-when { font-size: clamp(12px, 2vmin, 30px); font-weight: 800; color: var(--text-muted); flex-shrink: 0; }
.wo-today-late .wo-tv-when { color: var(--danger, #b23b3b); }
.wo-tv-empty, .wo-tv-more { font-size: clamp(14px, 2.2vmin, 32px); color: var(--text-muted); text-align: center; padding: 2vmin 0; font-weight: 600; }
@media (max-width: 900px) { .wo-tv { overflow-y: auto; } .wo-tv-grid { grid-template-columns: 1fr; } }

/* Menú de la factura: acciones en una fila ordenada, divididas por grupo */
.inv-actions-row { align-items: center; }

/* Calculadora de tinta */
.ink-extras { margin-top: 4px; }
.ink-extras summary { cursor: pointer; font-size: calc(13px * var(--fs, 1)); font-weight: 700; color: var(--accent-text); padding: 6px 0; }
.ink-row-current td { background: var(--secondary-light); font-weight: 700; }
#ink-results .stat-grid { margin-bottom: 8px; }
#ink-results .stat-tile .hint { margin-top: 6px; }

/* Espejo automático: más finito que el manual y sin hueco cuando no se usa */
.table-scroll-mirror-auto { margin-bottom: 4px; }
.table-scroll-mirror[hidden] { display: none; }


/* ===== static/css/app/clientes/rfm.css ===== */
/* ------------------------------------------------------------------ */
/* Clientes → Dashboard RFM (2026-10-16)                               */
/* ------------------------------------------------------------------ */
:root { --rfm-vip: #c9971a; --rfm-leal: #16a34a; --rfm-riesgo: #dc2626; --rfm-nuevo: #2563eb; } /* mismos colores que las medallas (N37) */
.rfm-controls { margin-bottom: 12px; padding: 14px 16px; }
.rfm-controls-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px; }
.rfm-filters { justify-content: flex-start; align-items: flex-end; margin-top: 12px; }
.rfm-field { display: flex; flex-direction: column; gap: 4px; font-size: calc(12px * var(--fs, 1)); color: var(--text-muted); font-weight: 600; }
.rfm-field select, .rfm-field input { min-width: 170px; }
.rfm-search { flex: 1; min-width: 180px; }
.rfm-search input { width: 100%; }
.rfm-cards { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; margin-bottom: 10px; }
.rfm-cards > .rfm-card { margin: 0; }
.rfm-card {
  display: flex; flex-direction: column; align-items: flex-start; gap: 4px; text-align: left; cursor: pointer;
  font: inherit; color: var(--text); border-top: 4px solid var(--seg); padding: 14px 16px; margin: 0;
  transition: transform .16s var(--ease-out), box-shadow .16s var(--ease-out), border-color .16s var(--ease-out);
}
@media (hover: hover) and (pointer: fine) { .rfm-card:hover { transform: translateY(-2px); } }
.rfm-card:active { transform: scale(.98); }
.rfm-card.active { border-color: var(--seg); box-shadow: 0 0 0 2px var(--seg), var(--shadow); }
.rfm-card-top { display: flex; align-items: center; gap: 8px; font-weight: 700; font-size: calc(14px * var(--fs, 1)); }
.rfm-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--seg); flex: none; }
.rfm-card-num { font-size: calc(28px * var(--fs, 1)); font-weight: 800; line-height: 1.1; }
.rfm-card-sub { font-size: calc(12.5px * var(--fs, 1)); color: var(--text-muted); font-variant-numeric: tabular-nums; }
.rfm-card-who { font-size: calc(12.5px * var(--fs, 1)); margin-top: 4px; }
.rfm-card-action { font-size: calc(12.5px * var(--fs, 1)); color: var(--text-muted); }
.rfm-dist { display: flex; height: 10px; border-radius: 999px; overflow: hidden; gap: 2px; margin-bottom: 12px; background: var(--subtle-bg); }
.rfm-dist span { min-width: 4px; }
.rfm-how { margin-bottom: 12px; padding: 12px 16px; }
.rfm-how summary { cursor: pointer; font-weight: 700; }
.rfm-how-list { margin: 10px 0 6px 18px; padding: 0; display: grid; gap: 4px; }
.rfm-table-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 8px; margin-bottom: 10px; }
.rfm-table td { vertical-align: middle; }
.rfm-badge {
  display: inline-block; padding: 3px 10px; border-radius: 999px; font-size: calc(12px * var(--fs, 1)); font-weight: 700; white-space: nowrap;
  color: var(--seg); background: color-mix(in srgb, var(--seg) 14%, transparent); border: 1px solid color-mix(in srgb, var(--seg) 35%, transparent);
}
@media (max-width: 900px) { .rfm-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px) {
  .clients-tabs { display: flex; width: 100%; }
  .clients-tabs .view-toggle-btn { flex: 1; padding-left: 4px; padding-right: 4px; }
  .rfm-field, .rfm-field select, .rfm-field input { width: 100%; min-width: 0; }
  .rfm-filters > .view-toggle { display: flex; width: 100%; }
  .rfm-filters > .view-toggle .view-toggle-btn { flex: 1; }
  .rfm-cards { gap: 8px; }
  .rfm-card { padding: 12px; }
  .rfm-card-num { font-size: calc(22px * var(--fs, 1)); }
  .rfm-card-who { display: none; }
}
@media (prefers-reduced-motion: reduce) { .rfm-card { transition: none; } }

/* Cuentas por cobrar → Por vendedor (2026-10-22): barra de saldo por vendedor. */
.rec-seller-bars { display: grid; gap: 8px; }
.rec-seller-row { display: grid; grid-template-columns: minmax(110px, 200px) 1fr auto; align-items: center; gap: 12px; }
.rec-seller-name { font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rec-seller-track { height: 10px; border-radius: 999px; background: var(--border); overflow: hidden; }
.rec-seller-track > span { display: block; height: 100%; border-radius: inherit; background: linear-gradient(90deg, var(--main), var(--secondary)); transition: width .5s cubic-bezier(.22,1,.36,1); }
.rec-seller-amt { font-weight: 700; white-space: nowrap; }
@media (max-width: 560px) {
  .rec-seller-row { grid-template-columns: 1fr auto; }
  .rec-seller-track { grid-column: 1 / -1; grid-row: 2; }
}

/* Cuentas por pagar → Tarjetas de la empresa (2026-10-22). Cada tarjeta se
   ve como una tarjeta de plástico con un brillo que cruza al pasar el mouse
   (Shine de Magic UI) y, si el pago está vencido, el Border Beam rojo. */
.cc-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 16px; }
.cc-item { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.cc-plastic { position: relative; overflow: hidden; display: grid; grid-template-rows: auto 1fr auto auto; gap: 6px; aspect-ratio: 1.586; width: 100%; padding: 16px 18px; border: 0; border-radius: 16px; color: #fff; text-align: left; cursor: pointer; font: inherit;
  box-shadow: 0 10px 24px -12px rgba(8, 30, 70, .55); transition: transform .25s var(--ease-out), box-shadow .25s var(--ease-out); }
@media (hover: hover) and (pointer: fine) { .cc-plastic:hover { transform: translateY(-3px); box-shadow: 0 16px 30px -14px rgba(8, 30, 70, .6); } }
.cc-plastic:focus-visible { outline: 3px solid var(--secondary); outline-offset: 3px; }
/* Todas las tarjetas en negro, con un glow azul al pasar el mouse. */
.cc-black { background: linear-gradient(135deg, #050505 0%, #1c1c1e 55%, #2c2c2e 100%); }
.cc-black:hover { box-shadow: 0 0 0 1px rgba(53,162,219,.45), 0 0 26px 2px rgba(53,162,219,.45), 0 16px 30px -14px rgba(0,0,0,.7); }
.cc-tone-1 { background: linear-gradient(135deg, #084383 0%, #35a2db 100%); }
.cc-tone-2 { background: linear-gradient(135deg, #1f2937 0%, #4b5563 100%); }
.cc-tone-3 { background: linear-gradient(135deg, #5b21b6 0%, #db2777 100%); }
.cc-tone-4 { background: linear-gradient(135deg, #065f46 0%, #10b981 100%); }
.cc-shine { position: absolute; inset: 0; background: linear-gradient(115deg, transparent 30%, rgba(255,255,255,.28) 48%, transparent 66%); transform: translateX(-100%); transition: transform .9s var(--ease-out); pointer-events: none; }
@media (hover: hover) and (pointer: fine) { .cc-plastic:hover .cc-shine { transform: translateX(100%); } }
.cc-bank { font-size: calc(12px * var(--fs, 1)); font-weight: 800; letter-spacing: .06em; text-transform: uppercase; opacity: .9; }
.cc-chip { width: 38px; height: 28px; border-radius: 6px; align-self: center; background: linear-gradient(135deg, #f6e27a, #c9a227); box-shadow: inset 0 0 0 1px rgba(0,0,0,.15); }
.cc-number { font-size: calc(15px * var(--fs, 1)); letter-spacing: .12em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cc-bottom { display: flex; justify-content: space-between; gap: 8px; font-size: calc(12px * var(--fs, 1)); font-weight: 700; min-width: 0; }
.cc-bottom span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cc-plastic .acc-beam { opacity: 1; border-radius: 16px; }
.cc-plastic .acc-beam::after { background: linear-gradient(to left, #ff6b6b, #fbbf24, transparent); }
.cc-facts { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 12px; }
.cc-fact { display: flex; flex-direction: column; min-width: 0; }
.cc-fact > span { font-size: calc(11.5px * var(--fs, 1)); color: var(--text-muted); font-weight: 700; }
.cc-fact strong { font-size: calc(14px * var(--fs, 1)); }
.cc-fact em { font-style: normal; font-size: calc(11.5px * var(--fs, 1)); color: var(--text-muted); }
.cc-fact.is-alert strong, .cc-fact.is-alert em { color: var(--danger); }
.cc-fact-wide { grid-column: 1 / -1; }
.cc-limit { display: block; height: 6px; border-radius: 999px; background: var(--border); overflow: hidden; margin-top: 4px; }
.cc-limit > span { display: block; height: 100%; border-radius: inherit; background: var(--success); transition: width .5s var(--ease-out); }
.cc-limit > span.is-high { background: var(--danger); }
.cc-actions { margin-top: 0; flex-wrap: wrap; }
.cc-inactive-row { display: flex; justify-content: space-between; align-items: center; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--row-border); }
.link-btn { background: none; border: 0; padding: 0; color: var(--accent-text); font: inherit; font-weight: 700; text-decoration: underline; cursor: pointer; }
.pay-method-pill { display: inline-block; font-size: calc(12px * var(--fs, 1)); font-weight: 700; border-radius: 999px; padding: 2px 9px; white-space: nowrap; background: var(--subtle-bg); color: var(--text); }
.pay-method-pill.pm-tarjeta { background: color-mix(in srgb, var(--secondary) 16%, transparent); }
.pay-method-pill.pm-cheque { background: color-mix(in srgb, #f59e0b 18%, transparent); }
.pay-method-pill.pm-transferencia { background: color-mix(in srgb, var(--success) 16%, transparent); }
.pay-card-filter { display: inline-flex; align-items: center; gap: 6px; }
.pay-card-filter button { background: none; border: 0; color: inherit; font-weight: 800; cursor: pointer; font-size: 14px; line-height: 1; padding: 0 2px; }
@media (prefers-reduced-motion: reduce) { .cc-shine, .cc-plastic { transition: none; } }

/* Planilla → ficha del empleado (2026-10-22): cada hora extra con su monto,
   y el préstamo aparte del anticipo con su saldo a la fecha. */
.payroll-ot-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 12px; }
.payroll-ot-item { position: relative; min-width: 0; }
.payroll-ot-amount { position: absolute; top: 0; right: 0; font-size: calc(12px * var(--fs, 1)); font-weight: 800; color: var(--accent-text); }
.payroll-loan-box { border: 1px dashed var(--border); border-radius: var(--radius-sm); padding: 10px 12px 0; margin-bottom: 12px; background: var(--row-alt-bg); }
.payroll-loan-balance { display: flex; align-items: center; min-height: 40px; padding: 0 12px; border-radius: var(--radius-sm); background: var(--subtle-bg); font-weight: 800; }
.payroll-breakdown > div.info { color: var(--text-muted); font-style: italic; }
@media (max-width: 560px) { .payroll-ot-grid { grid-template-columns: 1fr; } }

/* Calculadoras (2026-10-22): sub-pestañas y la calculadora de vinil. */
.calc-tabs { margin-bottom: 16px; }
.vinyl-layout { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); gap: 16px; align-items: start; }
.vinyl-layout > .card { margin: 0; }
.vinyl-result-card { position: sticky; top: 12px; }
.vinyl-piece-row { display: grid; grid-template-columns: 10px minmax(0, 1fr) auto minmax(0, 1fr) 76px 36px; align-items: end; gap: 8px; }
.vinyl-piece-row .field { margin-bottom: 10px; min-width: 0; }
.vinyl-swatch { width: 10px; height: 38px; border-radius: 4px; margin-bottom: 10px; opacity: .8; }
.vinyl-times { padding-bottom: 20px; color: var(--text-muted); font-weight: 700; }
.vinyl-piece-row .btn-icon { margin-bottom: 10px; }
.vinyl-headline { font-size: calc(15px * var(--fs, 1)); font-weight: 700; }
.vinyl-big { font-size: calc(34px * var(--fs, 1)); font-weight: 800; color: var(--accent-text); line-height: 1; margin-right: 4px; }
.vinyl-facts { display: flex; flex-direction: column; border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden; margin-bottom: 14px; }
.vinyl-facts > div { display: flex; justify-content: space-between; gap: 10px; padding: 7px 12px; border-top: 1px solid var(--row-border); font-size: calc(13px * var(--fs, 1)); }
.vinyl-facts > div:first-child { border-top: none; }
.vinyl-facts span { color: var(--text-muted); }
.vinyl-roll-scroll { max-height: 520px; overflow: auto; display: flex; justify-content: center; padding: 8px; border-radius: var(--radius-sm); background: var(--subtle-bg); }
.vinyl-roll { fill: var(--surface); stroke: var(--border); }
.vinyl-edge { stroke: var(--text-muted); opacity: .6; }
.vinyl-tick { stroke: var(--text-muted); }
.vinyl-tick-label { fill: var(--text-muted); font-family: inherit; }
/* Láminas (2026-11-11): medida W × H y un dibujo por lámina. */
.vinyl-sheet-size { display: flex; align-items: center; gap: 6px; }
.vinyl-sheet-size input { min-width: 0; flex: 1; }
.vinyl-sheet-size span { color: var(--text-muted); font-weight: 700; }
.vinyl-sheets { display: grid; grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); gap: 10px; padding: 8px; border-radius: var(--radius-sm); background: var(--subtle-bg); max-height: 520px; overflow: auto; }
.vinyl-sheet { margin: 0; text-align: center; }
.vinyl-sheet svg { width: 100%; height: auto; display: block; }
.vinyl-sheet figcaption { font-size: calc(12px * var(--fs, 1)); color: var(--text-muted); margin-top: 4px; }
.vinyl-warn { padding: 10px 12px; border-radius: var(--radius-sm); background: var(--danger-bg); color: var(--danger); border: 1px solid var(--danger-border); font-weight: 600; }
@media (max-width: 900px) {
  .vinyl-layout { grid-template-columns: 1fr; }
  .vinyl-result-card { position: static; }
}
@media (max-width: 480px) {
  .vinyl-piece-row { grid-template-columns: 8px minmax(0, 1fr) minmax(0, 1fr) 58px 32px; }
  .vinyl-times { display: none; }
}

/* Sistema: estado de Drive y prueba de restauración, más simples (2026-10-27) */
.sys-status { display: flex; align-items: center; gap: 12px; padding: 12px 14px; margin: 12px 0; border-radius: var(--radius-sm); background: var(--subtle-bg); border: 1px solid var(--border); flex-wrap: wrap; }
.sys-status-icon { width: 30px; height: 30px; flex: none; display: grid; place-items: center; border-radius: 50%; font-weight: 800; color: #fff; background: var(--text-muted); }
.sys-status[data-tone="ok"] .sys-status-icon { background: var(--success); }
.sys-status[data-tone="warn"] .sys-status-icon { background: #f59e0b; }
.sys-status[data-tone="danger"] .sys-status-icon { background: var(--danger); }
.sys-status-text { display: flex; flex-direction: column; flex: 1; min-width: 180px; }
.sys-status-text b { color: var(--text); }
.sys-status-text span { font-size: calc(13px * var(--fs, 1)); color: var(--text-muted); }
.sys-kv { display: grid; gap: 6px; margin-top: 4px; }
.sys-kv > div { display: flex; gap: 10px; font-size: calc(13px * var(--fs, 1)); }
.sys-kv span { color: var(--text-muted); min-width: 100px; flex: none; }
.sys-kv b { font-weight: 600; overflow-wrap: anywhere; }
.sys-links { display: flex; gap: 16px; flex-wrap: wrap; margin-top: 12px; font-size: calc(13px * var(--fs, 1)); }
.sys-help { margin-top: 10px; font-size: calc(13px * var(--fs, 1)); color: var(--text-muted); }
.sys-help summary { cursor: pointer; font-weight: 700; color: var(--accent-text); }
.sys-help p { margin: 6px 0 0; }
.sys-creds { margin-top: 14px; padding: 12px 14px; border-radius: var(--radius-sm); background: var(--bg); border: 1px solid var(--border); }
.sys-kv a { color: var(--accent-text); }


/* Medalla del tipo de cliente en la OT (N37, 2026-11-11). */
.client-medal { display: inline-grid; place-items: center; flex: none; width: 20px; height: 20px; margin-left: 6px; padding: 0; vertical-align: -4px; border-radius: 50%; border: 1px solid color-mix(in srgb, var(--medal) 55%, transparent); background: color-mix(in srgb, var(--medal) 16%, var(--surface)); color: var(--medal); cursor: pointer; transition: transform .15s ease, box-shadow .15s ease; }
.client-medal svg { width: 12px; height: 12px; }
/* Sin zoom (2026-11-11: el nombre del cliente recortaba lo que sobresalía): solo se pinta más fuerte. */
.client-medal:hover, .client-medal:focus-visible { background: color-mix(in srgb, var(--medal) 30%, var(--surface)); box-shadow: 0 0 0 2px color-mix(in srgb, var(--medal) 35%, transparent); outline: none; }
.client-medal.is-static { cursor: default; margin-left: 0; }
.client-medal.is-static:hover { background: color-mix(in srgb, var(--medal) 16%, var(--surface)); box-shadow: none; }
.rfm-card-medal { margin-right: 6px; width: 22px; height: 22px; }
.rfm-card-medal svg { width: 13px; height: 13px; }
.rfm-badge-medal { width: 16px; height: 16px; margin-right: 5px; vertical-align: -3px; border: none; background: transparent; color: var(--seg); }
.rfm-badge-medal svg { width: 12px; height: 12px; }
.wo-meta-client-wrap { display: inline-flex; align-items: center; min-width: 0; max-width: 100%; }
.client-medal-slot { display: inline-block; width: 20px; height: 20px; margin-left: 6px; vertical-align: -4px; }
.client-medal-pop { position: fixed; top: 0; left: 0; z-index: 1000; width: 250px; max-width: calc(100vw - 16px); padding: 10px 12px; border-radius: var(--radius); background: var(--surface); border: 1px solid var(--border); border-top: 3px solid var(--medal); box-shadow: 0 10px 28px rgba(0, 0, 0, .18); font-size: calc(12.5px * var(--fs, 1)); }
.client-medal-pop-title { font-weight: 800; color: var(--medal); }
.client-medal-pop-text { margin-top: 3px; }
.client-medal-pop-tip { margin-top: 4px; color: var(--text-muted); }
.client-medal-pop-go { margin-top: 8px; padding: 0; border: none; background: none; color: var(--accent-text); font-weight: 700; cursor: pointer; font-size: inherit; }
.client-medal-pop-go:hover { text-decoration: underline; }
@media (prefers-reduced-motion: reduce) { .client-medal { transition: none; } }

/* ===== static/css/app/base/resumen-y-esqueletos.css ===== */
/* ------------------------------------------------------------------ */
/* Barra de resumen vivo (2026-11-03): debajo del título de la pestaña. */
/* ------------------------------------------------------------------ */
.live-summary { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 2px; margin: 8px 0 0 -11px; }
.ls-chip { display: inline-flex; align-items: baseline; gap: 5px; padding: 5px 11px; border-radius: 999px; border: 1px solid transparent;
  background: none; color: var(--text-muted); font: inherit; font-size: calc(13.5px * var(--fs, 1)); line-height: 1.3; }
.ls-chip b { color: var(--text); font-weight: 800; font-size: calc(14.5px * var(--fs, 1)); }
button.ls-chip { cursor: pointer; transition: background-color 150ms ease, border-color 150ms ease, transform 100ms ease-out; }
button.ls-chip:hover { background: var(--subtle-bg); }
button.ls-chip:active { transform: scale(.97); }
button.ls-chip:focus-visible { outline: 2px solid var(--main); outline-offset: 1px; }
.ls-chip.ls-danger b { color: var(--danger); }
.ls-chip.ls-warn b { color: var(--warn-text); }
.ls-chip.ls-ok b { color: var(--success); }
.ls-chip.is-active { background: var(--subtle-bg); border-color: var(--border); color: var(--text); }
.ls-chip.is-active::after { content: "×"; margin-left: 2px; font-weight: 700; color: var(--text-muted); }
.ls-sep { color: var(--text-faint); user-select: none; }
@media (max-width: 600px) {
  .live-summary { margin-left: 0; }
  .ls-sep { display: none; }
  .ls-chip { padding: 4px 9px; border-color: var(--border); }
}

/* ------------------------------------------------------------------ */
/* Esqueletos de carga (2026-11-03): reemplazan al orbe "Cargando…".    */
/* ------------------------------------------------------------------ */
@keyframes skel-shimmer { from { background-position: 150% 0; } to { background-position: -50% 0; } }
@keyframes skel-appear { from { opacity: 0; } to { opacity: 1; } }
.skel {
  display: block; border-radius: 8px;
  background: linear-gradient(100deg, var(--subtle-bg) 35%, var(--surface) 50%, var(--subtle-bg) 65%) var(--subtle-bg);
  background-size: 200% 100%; animation: skel-shimmer 1.4s ease-in-out infinite;
}
.skel-page, .skel-inline { animation: skel-appear 200ms ease-out 120ms both; }
.skel-title { width: min(280px, 60%); height: 30px; margin-bottom: 10px; }
.skel-sub { width: min(440px, 85%); height: 14px; margin-bottom: 22px; }
.skel-tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--gap-lg, 16px); margin-bottom: 16px; }
.skel-tile { height: 86px; border-radius: var(--radius, 14px); }
.skel-card { padding: 18px; }
.skel-table { display: flex; flex-direction: column; }
.skel-row { display: grid; grid-template-columns: 2fr 1fr 1fr 1fr 1fr; gap: 16px; align-items: center; padding: 13px 0; border-top: 1px solid var(--row-border); }
.skel-row:first-child { border-top: none; }
.skel-inline .skel-row { grid-template-columns: 2fr 1fr 1fr; }
.skel-cell { height: 12px; }
@media (max-width: 700px) {
  .skel-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .skel-row { grid-template-columns: 2fr 1fr 1fr; }
  .skel-row > .skel-cell:nth-child(n+4) { display: none; }
}
@media (prefers-reduced-motion: reduce) { .skel { animation: none; } }

/* Tasa de cierre de cotizaciones (N24, 2026-11-03) */
.close-of { font-size: .55em; color: var(--text-muted); font-weight: 700; }
.close-table td, .close-table th { white-space: nowrap; }
.close-table th, .close-table td { padding-left: 6px; padding-right: 6px; }
.close-rate-cell { display: flex; align-items: center; gap: 6px; }
.close-rate-bar { flex: 0 0 48px; height: 6px; border-radius: 999px; background: var(--subtle-bg); overflow: hidden; }
.close-rate-bar > span { display: block; height: 100%; border-radius: inherit; background: var(--main); }

/* Desarrollo: tickets resueltos por mes (2026-11-03) */
.dev-dash-grid { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); gap: 20px; align-items: start; margin-top: 10px; }
.dev-dash-side { display: flex; flex-direction: column; gap: 10px; }
.dev-dash-kpi { display: flex; flex-direction: column; gap: 2px; padding: 12px 14px; border-radius: var(--radius-sm); background: var(--subtle-bg); }
.dev-dash-kpi span { font-size: calc(12px * var(--fs, 1)); font-weight: 600; color: var(--text-muted); }
.dev-dash-kpi strong { font-size: calc(24px * var(--fs, 1)); font-weight: 800; line-height: 1.15; }
.dev-dash-kpi small { font-size: calc(12px * var(--fs, 1)); color: var(--text-faint); }
.dev-dash-kinds { display: flex; flex-direction: column; gap: 8px; padding: 4px 2px; }
.dev-dash-kind { display: grid; grid-template-columns: 18px 1fr auto; align-items: center; gap: 4px 8px; font-size: calc(13px * var(--fs, 1)); }
.dev-dash-kind-ico svg { width: 15px; height: 15px; display: block; }
.dev-dash-kind-bar { grid-column: 2 / -1; height: 5px; border-radius: 999px; background: var(--subtle-bg); overflow: hidden; }
.dev-dash-kind-bar > span { display: block; height: 100%; border-radius: inherit; background: currentColor; opacity: .7; }
@media (max-width: 800px) { .dev-dash-grid { grid-template-columns: minmax(0, 1fr); } }
.dev-dash-kind[class*="dev-kind-"] { background: none; }
.dev-dash-kind.dev-kind-mejora { color: var(--success); }
.dev-dash-kind.dev-kind-pregunta { color: var(--warn-text); }
.dev-dash-kind > span:not(.dev-dash-kind-ico):not(.dev-dash-kind-bar) { color: var(--text); }

/* ===== static/css/app/base/efectos.css ===== */
/* =====================================================================
   Just Print — estilos de los efectos de interfaz de static/js/fx.js
   (adaptados de React Bits — MIT + Commons Clause, (c) 2026 David Haz —
   y de Thinking Orbs). Se carga después de style.css.
   ===================================================================== */

.jp-sr { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* ------------------------------------------------------------------ */
/* Orbe "Searching" — Cargando…                                         */
/* ------------------------------------------------------------------ */
.jp-orb { display: block; flex: none; }
.jp-loader {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px;
  min-height: calc(100dvh - 220px); padding: 40px 20px; text-align: center;
}
.jp-loader-inline { display: flex; align-items: center; justify-content: center; gap: 10px; padding: 18px 10px; }
.jp-shimmer {
  position: relative; display: inline-block; font-size: calc(15px * var(--fs, 1)); font-weight: 600; letter-spacing: .01em;
  color: var(--text-muted);
}
.jp-loader-inline .jp-shimmer { font-size: calc(13px * var(--fs, 1)); }
.jp-shimmer::after {
  content: attr(data-text); position: absolute; inset: 0; color: transparent;
  background: linear-gradient(100deg, transparent 0%, transparent 35%, var(--accent-text) 50%, transparent 65%, transparent 100%);
  background-size: 250% 100%; -webkit-background-clip: text; background-clip: text;
  animation: jp-shimmer 1.8s linear infinite;
}
@keyframes jp-shimmer { from { background-position: 125% 0; } to { background-position: -125% 0; } }

/* ------------------------------------------------------------------ */
/* Plasma — fondo de Inicio y de Iniciar sesión                         */
/* ------------------------------------------------------------------ */
.jp-plasma-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; pointer-events: none; }
.home-plasma { position: fixed; inset: 0; z-index: 0; pointer-events: none; }
.home-welcome { position: relative; z-index: 1; }
.auth-wrap { position: relative; overflow: hidden; isolation: isolate; }
.auth-plasma { position: absolute; inset: 0; z-index: -1; pointer-events: none; }
.home-welcome-logo { filter: drop-shadow(0 6px 24px rgba(8, 67, 131, .12)); }

/* ------------------------------------------------------------------ */
/* Specular Button                                                      */
/* ------------------------------------------------------------------ */
.btn-specular.specular-on { position: relative; isolation: isolate; }
.specular-light { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 0; border-radius: inherit; }
.specular-label { position: relative; z-index: 1; display: inline-flex; align-items: center; justify-content: center; gap: inherit; }
.btn-specular { box-shadow: 0 10px 24px -14px rgba(8, 47, 94, .55); }
.btn-specular.specular-fallback { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 10px 24px -14px rgba(8, 47, 94, .55); }
/* Botones claros (btn-ghost, como "Exportar"): el filo de luz es azul en
   vez de blanco, para que se vea sobre fondo claro (fx.js lee --spec-line). */
.btn-ghost.btn-specular { --spec-line: #35a2db; box-shadow: 0 8px 20px -14px rgba(8, 47, 94, .45); }
:root[data-theme="dark"] .btn-ghost.btn-specular { --spec-line: #8fd0ff; }
/* El "+" redondo de Nueva orden en el celular sale de ::before del botón. */
@media (max-width: 768px) { #new-wo-btn.specular-on .specular-label { display: none; } }

/* ------------------------------------------------------------------ */
/* Shiny Text (React Bits) — "Desarrollado por Ari Ramos": un brillo    */
/* cruza el texto al cargar y al pasar el mouse. No en bucle: una       */
/* animación infinita repintaba la página en cada cuadro y trababa el   */
/* scroll (sobre todo el horizontal del Kanban).                        */
/* ------------------------------------------------------------------ */
.shiny-text {
  display: inline-block;
  color: rgba(130, 164, 198, .78);
  background: linear-gradient(120deg, rgba(255, 255, 255, 0) 40%, rgba(255, 255, 255, .9) 50%, rgba(255, 255, 255, 0) 60%);
  background-size: 200% 100%;
  -webkit-background-clip: text; background-clip: text;
  background-position: -100%;
  animation: jp-shine 2.2s linear 1 both;
}
@keyframes jp-shine { 0% { background-position: 100%; } 100% { background-position: -100%; } }
@keyframes jp-shine-hover { 0% { background-position: 100%; } 100% { background-position: -100%; } }
@media (hover: hover) and (pointer: fine) { .sidebar-credit:hover .shiny-text { color: #cfe1f4; animation: jp-shine-hover 1.6s linear 1 both; } }

/* ------------------------------------------------------------------ */
/* Hold Button — mantener presionado para eliminar                      */
/* ------------------------------------------------------------------ */
.hold-button {
  --hb-radius: var(--radius-sm);
  --hb-bg: var(--danger-bg);
  --hb-fill: var(--danger);
  --hb-text: var(--danger);
  --hb-fill-text: #ffffff;
  --hb-hold: 1100ms;
  --hb-release: 200ms;
  --hb-press: 0.97;
  --hb-wave: 6px;
  --hb-w: 0px;
  --hb-h: 0px;
  --hb-cycles: 1;
  --hb-p: 0;
  --hb-glow: 0 10px 28px -8px color-mix(in srgb, var(--hb-fill) 65%, transparent);
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  height: 40px; padding: 0 18px; margin: 0;
  border: 1px solid var(--danger-border); border-radius: var(--hb-radius);
  background: var(--hb-bg); color: var(--hb-text);
  font: inherit; font-size: calc(14px * var(--fs, 1)); font-weight: 700; line-height: 1; white-space: nowrap;
  cursor: pointer; outline: none; isolation: isolate;
  user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
  transition: transform 160ms var(--ease-out), background-color 160ms ease, box-shadow var(--hb-release) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) { .hold-button:not(:disabled):hover { background: color-mix(in srgb, var(--hb-bg) 85%, var(--hb-fill)); } }
.hold-button[data-phase="holding"][data-input="pointer"] { transform: scale(var(--hb-press)); }
.hold-button[data-phase="holding"], .hold-button[data-phase="done"] { box-shadow: var(--hb-glow); }
.hold-button[data-phase="holding"] { transition: transform 160ms var(--ease-out), background-color 160ms ease, box-shadow var(--hb-hold) linear; }
.hold-button:focus-visible { outline: 2px solid var(--hb-fill); outline-offset: 3px; }
.hold-button:disabled { opacity: .5; cursor: default; pointer-events: none; }
.hold-button.hold-button--hint { animation: hb-hint 420ms var(--ease-out); }
@keyframes hb-hint { 0%, 100% { transform: translateX(0); } 25% { transform: translateX(-4px); } 50% { transform: translateX(4px); } 75% { transform: translateX(-2px); } }
.hold-button__pulse { position: absolute; inset: 0; z-index: 0; border-radius: var(--hb-radius); pointer-events: none; opacity: 0; }
.hold-button[data-phase="done"] .hold-button__pulse { animation: hb-pulse 600ms var(--ease-out) forwards; }
@keyframes hb-pulse {
  from { opacity: 1; box-shadow: 0 0 0 0 color-mix(in srgb, var(--hb-fill) 55%, transparent); }
  to { opacity: 0; box-shadow: 0 0 0 14px color-mix(in srgb, var(--hb-fill) 0%, transparent); }
}
.hold-button__label { position: relative; z-index: 2; display: grid; place-items: center; }
.hold-button__label > span { grid-area: 1 / 1; display: inline-flex; align-items: center; gap: 8px; white-space: nowrap; transition: opacity 200ms ease, filter 200ms ease; }
.hold-button__icon { display: inline-flex; flex: none; }
.hold-button__icon > svg { display: block; }
.hold-button__done { opacity: 0; filter: blur(2px); }
.hold-button[data-phase="done"] .hold-button__idle { opacity: 0; filter: blur(2px); }
.hold-button[data-phase="done"] .hold-button__done { opacity: 1; filter: blur(0); }
.hold-button__clip { position: absolute; inset: -1px; z-index: 3; clip-path: inset(0 round var(--hb-radius)); pointer-events: none; }
.hold-button__fill {
  position: absolute; inset: 0; display: grid; place-items: center;
  background: var(--hb-fill); color: var(--hb-fill-text);
  clip-path: inset(0 calc((1 - var(--hb-p)) * (100% + 0.75 * var(--hb-wave)) - var(--hb-p) * 0.25 * var(--hb-wave)) 0 0);
}
.hold-button__crest {
  position: absolute; inset: 0; display: grid; place-items: center;
  background: var(--hb-fill); color: var(--hb-fill-text);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='200' viewBox='0 0 20 200' preserveAspectRatio='none'%3E%3Cpath d='M0 0H10C18 8 18 25.3 10 33.3S2 58.7 10 66.7S18 92 10 100S2 125.3 10 133.3S18 158.7 10 166.7S2 192 10 200H0Z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='200' viewBox='0 0 20 200' preserveAspectRatio='none'%3E%3Cpath d='M0 0H10C18 8 18 25.3 10 33.3S2 58.7 10 66.7S18 92 10 100S2 125.3 10 133.3S18 158.7 10 166.7S2 192 10 200H0Z'/%3E%3C/svg%3E");
  -webkit-mask-repeat: repeat-y; mask-repeat: repeat-y;
  -webkit-mask-size: var(--hb-wave) calc(var(--hb-h) * 2); mask-size: var(--hb-wave) calc(var(--hb-h) * 2);
  -webkit-mask-position-x: calc(-1 * var(--hb-wave) + var(--hb-p) * (var(--hb-w) + var(--hb-wave)));
  mask-position-x: calc(-1 * var(--hb-wave) + var(--hb-p) * (var(--hb-w) + var(--hb-wave)));
  -webkit-mask-position-y: calc(-1 * var(--hb-p) * var(--hb-cycles) * var(--hb-h));
  mask-position-y: calc(-1 * var(--hb-p) * var(--hb-cycles) * var(--hb-h));
}
.hold-button__label--fill { z-index: auto; }
.confirm-card .hold-button { min-width: 200px; }

/* ------------------------------------------------------------------ */
/* Squish Switch — checkboxes de sí/no                                  */
/* ------------------------------------------------------------------ */
input[type="checkbox"].sw {
  --sw-w: 32px; --sw-h: 18px; --sw-in: 2px; --sw-t: 14px;
  --sw-x-rest: 0px;
  -webkit-appearance: none; appearance: none;
  flex: none; margin: 0; padding: 0;
  width: var(--sw-w); height: var(--sw-h); border-radius: 999px; border: 0;
  background-color: #c4ceda;
  background-image: radial-gradient(ellipse closest-side, #ffffff calc(100% - 1.2px), rgba(255, 255, 255, 0) 100%);
  background-repeat: no-repeat;
  background-size: calc(var(--sw-t) * var(--sw-sx, 1)) calc(var(--sw-t) * var(--sw-sy, 1));
  background-position: calc(var(--sw-in) + var(--sw-x, var(--sw-x-rest)) + var(--sw-t) * (1 - var(--sw-sx, 1)) / 2) 50%;
  box-shadow: inset 0 1px 2px rgba(8, 25, 50, .12);
  cursor: pointer; vertical-align: middle;
  transition: background-color .32s ease, transform .2s var(--ease-out);
  -webkit-tap-highlight-color: transparent;
}
input[type="checkbox"].sw:checked { background-color: var(--main); --sw-x-rest: 14px; }
input[type="checkbox"].sw:disabled { opacity: .5; cursor: not-allowed; }
input[type="checkbox"].sw:focus-visible { outline: 2px solid var(--secondary); outline-offset: 2px; }
@media (hover: hover) and (pointer: fine) { input[type="checkbox"].sw:not(:disabled):hover { transform: scale(1.035); } }
:root[data-theme="dark"] input[type="checkbox"].sw:not(:checked) { background-color: #3a475b; }
:root[data-theme="dark"] input[type="checkbox"].sw:checked { background-color: #2d6fc0; }
.filter-checkbox input[type="checkbox"].sw { width: var(--sw-w); height: var(--sw-h); }
/* Estatus de Ventas: un interruptor por estatus, casillas iguales
   (checkboxChipsHTML con { switches: true }). Todas en una fila si caben;
   si no, cuadrícula de 3 columnas (los 9 estatus quedan en 3×3). */
.status-switch-row { container-type: inline-size; }
.status-switch-grid { display: grid; grid-template-columns: repeat(var(--n, 9), minmax(0, 1fr)); gap: 8px; }
@container (max-width: 820px) { .status-switch-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.field .status-switch-row label.status-switch {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 7px;
  margin: 0; padding: 10px 6px 9px; min-width: 0;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface); cursor: pointer; user-select: none; text-align: center;
  font-size: calc(12.5px * var(--fs, 1)); font-weight: 600; color: var(--text-muted); line-height: 1.2;
  transition: border-color .2s ease, background-color .2s ease, color .2s ease;
}
.field .status-switch-row label.status-switch.checked { border-color: var(--secondary); background: var(--secondary-light); color: var(--text); }
@media (hover: hover) and (pointer: fine) { .field .status-switch-row label.status-switch:hover { border-color: var(--secondary); } }

/* Interruptor de 3 posiciones (No · sin elegir · Sí) para los selects obligatorios */
.sw3-native { display: none !important; }
.sw3 {
  display: inline-flex; align-items: center; gap: 10px; padding: 3px 0; margin: 0;
  background: none; border: 0; cursor: pointer; font: inherit; color: var(--text);
  -webkit-tap-highlight-color: transparent; user-select: none; -webkit-user-select: none;
}
.sw3:disabled { opacity: .5; cursor: not-allowed; }
.sw3-track {
  position: relative; display: block; width: 58px; height: 24px; border-radius: 999px;
  background: var(--subtle-bg); border: 1px dashed var(--text-faint);
  transition: background-color .32s ease, border-color .32s ease;
}
.sw3[data-state="false"] .sw3-track { background: #c4ceda; border: 1px solid transparent; }
.sw3[data-state="true"] .sw3-track { background: var(--main); border: 1px solid transparent; }
:root[data-theme="dark"] .sw3[data-state="false"] .sw3-track { background: #3a475b; }
:root[data-theme="dark"] .sw3[data-state="true"] .sw3-track { background: #2d6fc0; }
.sw3-thumb {
  position: absolute; top: 2px; left: 3px; width: 18px; height: 18px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 3px rgba(8, 25, 50, .3);
}
.sw3[data-state="mixed"] .sw3-thumb { background: var(--surface); box-shadow: 0 0 0 1px var(--border), 0 1px 3px rgba(8, 25, 50, .2); }
.sw3-no, .sw3-yes {
  position: absolute; top: 0; bottom: 0; display: flex; align-items: center;
  font-size: calc(9.5px * var(--fs, 1)); font-weight: 800; letter-spacing: .02em; pointer-events: none; transition: opacity .2s ease;
}
.sw3-no { left: 6px; }
.sw3-yes { right: 7px; }
.sw3-no, .sw3-yes { color: var(--text-faint); opacity: 0; }
.sw3[data-state="mixed"] .sw3-no, .sw3[data-state="mixed"] .sw3-yes { opacity: 1; }
.sw3-text { font-size: calc(13px * var(--fs, 1)); font-weight: 700; min-width: 60px; text-align: left; }
.sw3[data-state="mixed"] .sw3-text { color: var(--text-faint); font-weight: 600; }
.sw3:focus-visible { outline: none; }
.sw3:focus-visible .sw3-track { outline: 2px solid var(--secondary); outline-offset: 2px; }
@media (hover: hover) and (pointer: fine) { .sw3:not(:disabled):hover .sw3-track { filter: brightness(1.04); } }

/* Interruptor de modo oscuro del menú del usuario: la bolita se aplasta (JS) */

/* ------------------------------------------------------------------ */
/* Elastic Slider — rango de precio del Panel                           */
/* ------------------------------------------------------------------ */
.dual-slider.elastic-host { height: auto; margin-top: 4px; }
.elastic-host > .dual-slider-track, .elastic-host > .dual-slider-fill, .elastic-host > .dual-range { display: none !important; }
.elastic-slider {
  display: flex; align-items: center; gap: 12px; width: 100%;
  touch-action: none; user-select: none; -webkit-user-select: none;
  opacity: .78; transform: scale(1); transition: transform .25s var(--ease-out), opacity .25s ease;
}
@media (hover: hover) and (pointer: fine) { .elastic-slider:hover { transform: scale(1.02); opacity: 1; } }
.elastic-slider.is-active { opacity: 1; }
.elastic-icon { display: inline-flex; flex: none; color: var(--text-muted); }
.elastic-icon svg { display: block; }
.elastic-root { position: relative; display: flex; align-items: center; flex: 1 1 auto; padding: 14px 0; cursor: grab; touch-action: none; }
.elastic-root:active { cursor: grabbing; }
.elastic-track-wrap { display: flex; flex: 1 1 auto; height: 6px; transition: height .25s var(--ease-out); }
@media (hover: hover) and (pointer: fine) { .elastic-slider:hover .elastic-track-wrap { height: 10px; } }
.elastic-slider.is-active .elastic-track-wrap { height: 10px; }
.elastic-track { position: relative; flex: 1 1 auto; height: 100%; overflow: hidden; border-radius: 999px; background: color-mix(in srgb, var(--text-faint) 30%, transparent); }
.elastic-range { position: absolute; top: 0; bottom: 0; border-radius: 999px; background: var(--main); }
:root[data-theme="dark"] .elastic-range { background: #2d6fc0; }
.elastic-knob {
  position: absolute; top: 50%; width: 16px; height: 16px; margin: -8px 0 0 -8px; padding: 0; border-radius: 50%;
  border: 2px solid var(--main); background: var(--surface); box-shadow: 0 1px 4px rgba(8, 25, 50, .25);
  pointer-events: none; opacity: 0; transform: scale(.6); transition: opacity .2s ease, transform .2s var(--ease-out);
}
@media (hover: hover) and (pointer: fine) { .elastic-slider:hover .elastic-knob { opacity: 1; transform: scale(1); } }
.elastic-slider.is-active .elastic-knob, .elastic-knob:focus-visible { opacity: 1; transform: scale(1); }
.elastic-knob:focus-visible { outline: 2px solid var(--secondary); outline-offset: 2px; }
@media (pointer: coarse) { .elastic-knob { opacity: 1; transform: scale(1); } .elastic-track-wrap { height: 8px; } }

/* ------------------------------------------------------------------ */
/* Paper Crumple — arrastrar una orden en el Kanban (ver fx.js)         */
/* La copia plana (.crumple-ghost) se ve mientras carga la hoja 3D.     */
/* ------------------------------------------------------------------ */
.crumple-ghost { position: fixed; left: 0; top: 0; z-index: 990; pointer-events: none; will-change: transform; }
.crumple-ghost .kanban-card.crumple-paper { position: relative; margin: 0; cursor: grabbing; }
/* La hoja 3D (canvas de three.js) con el punto agarrado bajo el cursor. */
.crumple-3d { position: fixed; left: 0; top: 0; z-index: 990; pointer-events: none; will-change: transform; }
/* Arrastre con el puntero: sin selección de texto y con la mano cerrada. */
.kanban-col-body .kanban-card[draggable="true"] { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
/* Arrastre con el dedo: se arma tras mantener presionado; mientras, la ficha no deja que la página se desplace. */
.kanban-col-body .kanban-card.touch-armed { touch-action: none; }
/* (sin reglas sobre todo el body: cambiarlas al empezar a arrastrar recalculaba los estilos de toda la página) */
.kanban-col-body .kanban-card.dragging { cursor: grabbing; }
/* El lugar que dejó la ficha: vacío, solo con su contorno punteado. */
.kanban-col-body .kanban-card.drag-origin {
  opacity: 1; background: transparent; box-shadow: none; cursor: grabbing;
  border: 2px dashed var(--border); transform: none;
}
.kanban-col-body .kanban-card.drag-origin > *,
.kanban-col-body .kanban-card.drag-origin::before,
.kanban-col-body .kanban-card.drag-origin::after { visibility: hidden; }
/* Mientras la bolita aterriza encima, la ficha real no se ve. */
.kanban-col-body .kanban-card.crumple-landing { visibility: hidden; }

/* ------------------------------------------------------------------ */
/* Glide Select — lista de cualquier <select>                           */
/* ------------------------------------------------------------------ */
select.glide-swap { animation: gs-swap 160ms ease; }
@keyframes gs-swap { from { filter: blur(1.5px); opacity: .6; } }
.glide-menu {
  position: fixed; z-index: 1300; display: flex; flex-direction: column;
  padding: 4px; border-radius: var(--radius); background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: 0 10px 30px rgba(8, 25, 50, .18), 0 2px 6px rgba(8, 25, 50, .08);
  opacity: 0; transform: scale(.95);
  transition: opacity 180ms var(--ease-out), transform 180ms var(--ease-out);
  overflow: hidden;
}
.glide-menu[data-state="open"] { opacity: 1; transform: none; }
.glide-menu[data-state="closing"] { opacity: 0; transform: scale(.97); transition-duration: 120ms; pointer-events: none; }
.glide-search { padding: 2px 2px 6px; flex: none; }
.glide-search input[type="search"] { width: 100%; height: 34px; padding: 6px 10px; font-size: calc(13.5px * var(--fs, 1)); }
.glide-list { position: relative; display: grid; gap: 1px; overflow-y: auto; overscroll-behavior: contain; flex: 1 1 auto; min-height: 0; }
.glide-pill {
  position: absolute; top: 0; left: 0; right: 0; height: 32px; border-radius: var(--radius-sm);
  background: var(--secondary-light); opacity: 0; pointer-events: none;
  transition: transform 220ms var(--ease-out), opacity 150ms ease;
}
.glide-option {
  position: relative; z-index: 1; display: flex; align-items: center; gap: 8px; min-height: 32px;
  padding: 6px 8px 6px 10px; border-radius: var(--radius-sm); color: var(--text); font-size: calc(13.5px * var(--fs, 1));
  cursor: pointer; user-select: none; -webkit-user-select: none; -webkit-tap-highlight-color: transparent;
}
.glide-option[aria-selected="true"] { background: color-mix(in srgb, var(--secondary-light) 70%, transparent); font-weight: 700; }
.glide-list[data-live] .glide-option[aria-selected="true"] { background: transparent; }
.glide-option.is-disabled { color: var(--text-faint); cursor: default; }
.glide-option[hidden], .glide-group[hidden] { display: none; }
.glide-name { flex: 1 1 auto; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.glide-check { display: inline-flex; flex: none; color: var(--accent-text); visibility: hidden; }
.glide-option[aria-selected="true"] .glide-check { visibility: visible; }
.glide-group { padding: 8px 10px 4px; font-size: calc(11px * var(--fs, 1)); font-weight: 800; text-transform: uppercase; letter-spacing: .04em; color: var(--text-faint); }
@media (pointer: coarse) { .glide-option { min-height: 40px; font-size: calc(15px * var(--fs, 1)); } .glide-search input[type="search"] { font-size: calc(16px * var(--fs, 1)); } }
/* Glide en el buscador global (mountGlideList): la píldora reemplaza el
   fondo de hover de cada resultado. */
.glide-results { position: relative; padding: 4px; }
.glide-results > .glide-pill { left: 4px; right: 4px; }
.glide-results .global-search-item { position: relative; z-index: 1; border-radius: var(--radius-sm); padding: 9px 10px; }
.glide-results .global-search-group-title { padding-left: 10px; }
@media (hover: hover) and (pointer: fine) { .glide-results .global-search-item:hover { background: none; } }

/* ------------------------------------------------------------------ */
/* Slide Commit — deslizar para guardar una orden                       */
/* ------------------------------------------------------------------ */
.slide-commit-host { flex: 1 1 260px; max-width: 340px; min-width: 220px; }
.slide-commit { position: relative; display: block; width: 100%; font-family: inherit; }
.slide-commit__track {
  position: relative; width: 100%; height: 100%; border-radius: 999px; background: var(--subtle-bg);
  border: 1px solid var(--border);
  cursor: default; touch-action: none; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent;
}
.slide-commit__label {
  position: absolute; inset: 0; display: grid; place-items: center; padding-left: 40px; pointer-events: none;
  font-size: calc(13.5px * var(--fs, 1)); font-weight: 700; line-height: 1; white-space: nowrap;
}
/* line-height y padding: con background-clip:text, la "g" y la "p" de
   "guardar" se cortaban abajo (el degradado solo pinta la caja de la línea). */
.slide-commit__text { grid-area: 1 / 1; line-height: 1.35; padding: 0 2px 0.12em; color: var(--text-muted); transition: opacity 200ms ease, filter 200ms ease; }
.slide-commit__text--plain { background: linear-gradient(100deg, var(--text-muted) 40%, var(--accent-text) 50%, var(--text-muted) 60%); background-size: 250% 100%; -webkit-background-clip: text; background-clip: text; color: transparent; animation: jp-shimmer 2.4s linear infinite; }
.slide-commit__text--error { color: var(--danger); opacity: 0; filter: blur(2px); }
.slide-commit[data-phase="error"] .slide-commit__text--plain { opacity: 0; filter: blur(2px); }
.slide-commit[data-phase="error"] .slide-commit__text--error { opacity: 1; filter: none; }
.slide-commit__capsule {
  position: absolute; top: 3px; left: 3px; width: calc(100% - 6px); height: calc(100% - 6px);
  background: var(--main); color: #fff; outline: none; cursor: grab; touch-action: none;
  transition: background-color 200ms ease, color 200ms ease;
}
.slide-commit[data-held] .slide-commit__capsule { cursor: grabbing; }
.slide-commit[data-phase="pending"] .slide-commit__capsule, .slide-commit[data-phase="done"] .slide-commit__capsule { cursor: default; }
.slide-commit[data-phase="done"] .slide-commit__capsule { background: var(--success); }
.slide-commit[data-phase="error"] .slide-commit__capsule { background: var(--danger); }
.slide-commit__capsule:focus-visible { box-shadow: inset 0 0 0 2px var(--secondary); }
.slide-commit__content { position: absolute; inset: 0; }
.slide-commit__arrow, .slide-commit__spin, .slide-commit__done {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; gap: 8px;
  pointer-events: none; font-size: calc(14px * var(--fs, 1)); font-weight: 700; line-height: 1; white-space: nowrap;
}
.slide-commit__arrow svg, .slide-commit__done svg, .slide-commit__spinner { display: block; }
.slide-commit__arrow, .slide-commit__spin { transition: filter 200ms ease; }
.slide-commit[data-phase="pending"] .slide-commit__arrow { filter: blur(2px); }
.slide-commit:not([data-phase="pending"]) .slide-commit__spin { filter: blur(2px); }
.slide-commit__done { opacity: 0; transform: scale(.95); transition: opacity 200ms var(--ease-out), transform 200ms var(--ease-out); }
.slide-commit[data-phase="done"] .slide-commit__done { opacity: 1; transform: none; }
.slide-commit__spinner { animation: slide-commit-spin 1s linear infinite; animation-play-state: paused; }
.slide-commit[data-phase="pending"] .slide-commit__spinner { animation-play-state: running; }
@keyframes slide-commit-spin { to { transform: rotate(360deg); } }
.wo-edit-footer { display: flex; align-items: center; justify-content: flex-end; gap: 10px; flex-wrap: wrap; }
@media (max-width: 768px) {
  .modal-card > .modal-footer.wo-edit-footer { flex-wrap: nowrap; }
  .wo-edit-footer #wo-cancel-btn { flex: none; }
  .wo-edit-footer .slide-commit-host { max-width: none; min-width: 0; }
}

/* ------------------------------------------------------------------ */
/* Tabs (Animate UI) — .view-toggle: riel gris, pastilla clara que se   */
/* desliza con resorte a la pestaña activa; el panel nuevo entra con un */
/* fundido y desenfoque cortos.                                          */
/* ------------------------------------------------------------------ */
.view-toggle.rs-on {
  position: relative; isolation: isolate; gap: 2px; padding: 3px;
  background: var(--subtle-bg); border: none; border-radius: 10px; overflow: visible;
}
.view-toggle.rs-on > .view-toggle-btn {
  position: relative; z-index: 1; background: transparent; border: none; border-radius: 7px;
  padding: 7px 14px; transition: color .16s ease, transform .16s var(--ease-out);
}
.view-toggle.rs-on > .view-toggle-btn + .view-toggle-btn { border-left: none; }
.view-toggle.rs-on > .view-toggle-btn.active { background: transparent; color: var(--text); }
@media (hover: hover) and (pointer: fine) {
  .view-toggle.rs-on > .view-toggle-btn:not(.active):hover { background: transparent; color: var(--text); }
}
.rs-thumb {
  position: absolute; left: 0; top: 0; height: 100%; z-index: 0; pointer-events: none; will-change: transform, width;
  background: var(--surface); border-radius: 7px;
  box-shadow: 0 1px 2px rgba(8, 16, 32, .10), 0 1px 1px rgba(8, 16, 32, .06);
}
:root[data-theme="dark"] .rs-thumb { background: #2a3546; box-shadow: 0 1px 2px rgba(0, 0, 0, .4); }
#module-main-view, #module-history-view { animation: jp-tab-in 200ms var(--ease-out); }
@keyframes jp-tab-in { from { opacity: 0; transform: translateY(6px); } }
@media (prefers-reduced-motion: reduce) { #module-main-view, #module-history-view { animation: none; } }

/* ------------------------------------------------------------------ */
/* Spotlight Card — fichas de números de los paneles                   */
/* ------------------------------------------------------------------ */
.spot-card { position: relative; isolation: isolate; overflow: hidden; }
.spot-light, .spot-edge { position: absolute; inset: 0; border-radius: inherit; pointer-events: none; opacity: 0; }
.spot-light { z-index: -1; }
.spot-edge {
  z-index: 1; padding: 1px;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
}

/* ------------------------------------------------------------------ */
/* Lanyard — gafetes de empleados                                       */
/* ------------------------------------------------------------------ */
.lanyard-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 0 12px;
  padding: 0 4px 8px; overflow: hidden; border-top: 6px solid var(--border); border-radius: 4px 4px 0 0;
}
.lanyard-cell { position: relative; height: 410px; touch-action: pan-y; }
.lanyard-cell.is-dragging { z-index: 5; }
.lanyard-hook {
  position: absolute; left: 50%; top: -4px; width: 18px; height: 10px; margin-left: -9px; border-radius: 0 0 6px 6px;
  background: linear-gradient(#aab5c4, #7d8aa0); z-index: 2;
}
.lanyard-band { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; z-index: 1; }
.lanyard-band .band { fill: none; stroke: var(--main); stroke-width: 15; stroke-linecap: round; stroke-linejoin: round; }
.lanyard-band .band-weave { fill: none; stroke: rgba(255, 255, 255, .28); stroke-width: 9; stroke-dasharray: 2 4; stroke-linecap: butt; }
.lanyard-badge {
  position: absolute; left: 0; top: 0; width: 168px; height: 236px; z-index: 3;
  transform-origin: 50% 0; perspective: 900px; cursor: grab; touch-action: none; outline: none;
  user-select: none; -webkit-user-select: none; -webkit-tap-highlight-color: transparent;
}
.lanyard-cell.is-dragging .lanyard-badge { cursor: grabbing; }
.lanyard-clip {
  position: absolute; left: 50%; top: -10px; width: 26px; height: 18px; margin-left: -13px; z-index: 4;
  border-radius: 5px; background: linear-gradient(#dfe5ec, #9aa6b6); box-shadow: 0 1px 2px rgba(0, 0, 0, .25);
}
.lanyard-flip {
  position: relative; width: 100%; height: 100%; transform-style: preserve-3d;
  transform: rotateY(var(--tilt, 0deg)); transition: transform .6s var(--ease-out);
}
.lanyard-cell.is-dragging .lanyard-flip { transition-duration: .2s; }
.lanyard-face {
  position: absolute; inset: 0; border-radius: 14px; overflow: hidden; backface-visibility: hidden; -webkit-backface-visibility: hidden;
  background: #ffffff; color: #16233a; border: 1px solid rgba(8, 25, 50, .1);
  box-shadow: 0 14px 30px -10px rgba(8, 25, 50, .45), inset 0 1px 0 rgba(255, 255, 255, .8);
  display: flex; flex-direction: column; align-items: center;
}
.lanyard-face::before { /* agujero de la cinta */
  content: ""; position: absolute; top: 8px; left: 50%; width: 30px; height: 6px; margin-left: -15px; border-radius: 999px;
  background: #d8dee7; box-shadow: inset 0 1px 2px rgba(0, 0, 0, .25);
}
.lanyard-front { padding: 22px 10px 0; }
.lanyard-logo { width: 100%; display: flex; justify-content: center; margin-bottom: 8px; }
.lanyard-logo img { max-width: 92px; max-height: 32px; object-fit: contain; pointer-events: none; }
.lanyard-photo {
  width: 64px; height: 64px; border-radius: 50%; overflow: hidden; display: grid; place-items: center;
  background: var(--main); color: #fff; font-size: calc(22px * var(--fs, 1)); font-weight: 800; border: 3px solid #e7f4fb; flex: none;
}
.lanyard-photo img { width: 100%; height: 100%; object-fit: cover; pointer-events: none; }
.lanyard-name { margin-top: 8px; font-size: calc(12.5px * var(--fs, 1)); line-height: 1.2; font-weight: 800; word-break: break-word; text-align: center; line-height: 1.2; padding: 0 4px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.lanyard-role { margin-top: 3px; font-size: calc(11.5px * var(--fs, 1)); font-weight: 700; color: #35a2db; text-transform: uppercase; letter-spacing: .04em; text-align: center; }
.lanyard-strip { margin-top: auto; width: calc(100% + 24px); padding: 8px 0; background: linear-gradient(90deg, #084383, #35a2db); color: #fff; font-size: calc(11px * var(--fs, 1)); font-weight: 800; text-align: center; letter-spacing: .14em; text-transform: uppercase; }
.lanyard-back { transform: rotateY(180deg); padding: 26px 14px 12px; gap: 6px; justify-content: flex-start; background: linear-gradient(160deg, #ffffff 0%, #eef5fb 100%); }
.lanyard-back-title { font-size: calc(13px * var(--fs, 1)); font-weight: 800; text-align: center; margin-bottom: 4px; }
.lanyard-back-row { width: 100%; display: flex; justify-content: space-between; gap: 6px; font-size: calc(11.5px * var(--fs, 1)); border-bottom: 1px dashed #d5dde8; padding: 3px 0; }
.lanyard-back-row span { color: #62728a; }
.lanyard-back-row strong { text-align: right; line-height: 1.25; }
.lanyard-back-logo { margin-top: auto; max-width: 70px; opacity: .35; pointer-events: none; }
.lanyard-badge:focus-visible .lanyard-front, .lanyard-badge:focus-visible .lanyard-back { outline: 2px solid var(--secondary); outline-offset: 2px; }
.lanyard-cell.is-inactive .lanyard-face { filter: grayscale(.8); opacity: .8; }
@media (max-width: 560px) { .lanyard-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } .lanyard-badge { width: 150px; height: 220px; } .lanyard-cell { height: 390px; } }

/* ------------------------------------------------------------------ */
/* Botones de ícono nuevos (orden, usuarios, locaciones)                */
/* ------------------------------------------------------------------ */
.btn-icon-lg { width: 40px; height: 40px; padding: 0; }
.btn-icon-lg svg { width: 18px; height: 18px; }
.assignee-add-btn {
  display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px; padding: 0;
  border-radius: 50%; border: 1px dashed var(--accent-text); background: transparent; color: var(--accent-text); cursor: pointer; flex: none;
}
.assignee-add-btn svg { width: 16px; height: 16px; }
@media (hover: hover) and (pointer: fine) { .assignee-add-btn:hover { background: var(--secondary-light); border-style: solid; } }
.assignee-add-btn:active { transform: scale(.94); }
.assignee-list-row { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.assignee-add-panel { margin-top: 8px; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.assignee-add-panel select { flex: 1 1 220px; max-width: 360px; }

/* ------------------------------------------------------------------ */
/* Sidebar Glide — menú lateral (App Sidebar 6 de React Bits, adaptado) */
/* Las píldoras (fx.js) hacen el fondo del hover y del activo; los      */
/* grupos se abren/cierran animando grid-template-rows.                 */
/* ------------------------------------------------------------------ */
.nav.nav-glide { position: relative; isolation: isolate; }
.nav-pill {
  position: absolute; top: 0; left: 0; right: 0; z-index: 0; border-radius: var(--radius-sm);
  opacity: 0; pointer-events: none;
  transition: transform 300ms var(--ease-out), height 300ms var(--ease-out), opacity 160ms ease;
}
.nav-pill-hover { background: rgba(255, 255, 255, .09); }
.nav-pill-active {
  background: var(--secondary);
  box-shadow: 0 6px 18px -8px rgba(53, 162, 219, .7), inset 0 1px 0 rgba(255, 255, 255, .25);
}
.nav-glide .nav-item { position: relative; z-index: 1; }
.nav-glide .nav-item.active { background: transparent; }
@media (hover: hover) and (pointer: fine) { .nav-glide .nav-item:hover { background: transparent; } }
.nav-glide .nav-item { transition: color .2s ease; }
.nav-glide .nav-icon { transition: transform .3s var(--ease-out); }
@media (hover: hover) and (pointer: fine) { .nav-glide .nav-item:hover .nav-icon { transform: translateX(2px) scale(1.08); } }
.nav-glide .nav-item:active .nav-icon { transform: scale(.9); }

/* Abrir/cerrar grupos con animación (antes era display:none de golpe). */
.nav-group {
  grid-template-rows: 1fr; opacity: 1; overflow: visible;
  transition: grid-template-rows .32s var(--ease-out), opacity .22s ease;
}
.nav-group.collapsed { grid-template-rows: 0fr; opacity: 0; }
.nav-group-inner { min-height: 0; overflow: hidden; display: flex; flex-direction: column; gap: 2px; }
.nav-group.collapsed .nav-group-inner { visibility: hidden; transition: visibility 0s .32s; }

@media (prefers-reduced-motion: reduce) {
  .nav-pill, .nav-group, .nav-glide .nav-icon { transition-duration: 0ms !important; }
}

/* ------------------------------------------------------------------ */
/* Menos movimiento                                                     */
/* ------------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  .jp-shimmer::after, .slide-commit__text--plain, .shiny-text { animation: none; }
  .shiny-text { background: none; color: #82a4c6; }
  .slide-commit__text--plain { color: var(--text-muted); background: none; }
  .glide-menu { transform: none !important; transition: opacity 150ms ease; }
  .glide-pill { transition: opacity 150ms ease; }
  .hold-button { transform: none !important; }
  .hold-button__crest { display: none; }
  .hold-button__pulse { animation: none !important; }
  .hold-button.hold-button--hint { animation: none; }
  .lanyard-flip { transition-duration: 0ms; }
  .elastic-slider, .elastic-track-wrap { transition: none; }
  .slide-commit__spinner { animation: none; }
}

/* ------------------------------------------------------------------ */
/* Avatar Circles (Magic UI) — asignados de cada orden                  */
/* ------------------------------------------------------------------ */
/* isolation: los z-index de cada círculo (para encimarse entre ellos) quedan
   dentro del grupo; sin esto pasaban por encima de la barra de filtros fija
   del Kanban (z-index 17) al hacer scroll. */
.avatar-circles { display: inline-flex; align-items: center; flex-direction: row; vertical-align: middle; isolation: isolate; }
.avatar-circle {
  position: relative; z-index: calc(20 - var(--ac-i, 0));
  display: inline-grid; place-items: center; flex: none;
  width: var(--ac-size, 28px); height: var(--ac-size, 28px); border-radius: 50%;
  margin-left: calc(var(--ac-size, 28px) * -0.32);
  border: 2px solid var(--surface); background: var(--main); color: #fff;
  font-size: calc(var(--ac-size, 28px) * 0.36); font-weight: 800; line-height: 1; overflow: hidden;
  transition: transform .18s var(--ease-out);
}
.avatar-circle:first-child { margin-left: 0; }
.avatar-circle img { width: 100%; height: 100%; object-fit: cover; display: block; }
.avatar-circle.is-inactive { filter: grayscale(1); opacity: .6; }
.avatar-circle--more { z-index: 0; background: var(--text); color: var(--surface); font-size: calc(var(--ac-size, 28px) * 0.34); }
:root[data-theme="dark"] .avatar-circle--more { background: #e6ecf6; color: #0e1520; }
/* Avatar Group (Animate UI): al pasar el mouse, la cara se levanta con
   resorte y muestra el nombre arriba. */
.avatar-circle { transition: transform .38s cubic-bezier(.34, 1.56, .64, 1); overflow: visible; }
.avatar-circle img { position: absolute; inset: 0; width: 100%; height: 100%; max-width: none; object-fit: cover; border-radius: 50%; }
.avatar-circle[data-name]::after {
  content: attr(data-name); position: absolute; left: 50%; bottom: calc(100% + 6px);
  transform: translate(-50%, 4px) scale(.9); opacity: 0; pointer-events: none;
  padding: 3px 8px; border-radius: 6px; white-space: nowrap;
  background: var(--text); color: var(--surface); font-size: calc(11.5px * var(--fs, 1)); font-weight: 600;
  transition: opacity .14s ease, transform .2s var(--ease-out);
}
:root[data-theme="dark"] .avatar-circle[data-name]::after { background: #e6ecf6; color: #0e1520; }
@media (hover: hover) and (pointer: fine) {
  .avatar-circle:hover { transform: translateY(-5px) scale(1.06); z-index: 30; }
  .avatar-circle:hover::after { opacity: 1; transform: translate(-50%, 0) scale(1); }
}
.wo-view-assignee-names { font-size: calc(13px * var(--fs, 1)); color: var(--text-muted); }

/* ------------------------------------------------------------------ */
/* Theme Toggler (Magic UI) — botón de sol/luna junto al buscador       */
/* ------------------------------------------------------------------ */
.theme-toggle-btn { position: relative; overflow: hidden; }
.theme-toggle-btn svg { width: 18px; height: 18px; transition: transform .45s var(--ease-out), opacity .25s ease; }
.theme-toggle-btn .tt-sun, .theme-toggle-btn .tt-moon { position: absolute; inset: 0; margin: auto; }
.theme-toggle-btn .tt-moon { opacity: 0; transform: rotate(-90deg) scale(.5); }
:root[data-theme="dark"] .theme-toggle-btn .tt-sun { opacity: 0; transform: rotate(90deg) scale(.5); }
:root[data-theme="dark"] .theme-toggle-btn .tt-moon { opacity: 1; transform: none; }
html.theme-vt::view-transition-old(root), html.theme-vt::view-transition-new(root) { animation: none; mix-blend-mode: normal; }

/* Botón de tema, buscador y campanita: crecen un poco al pasar el puntero */
@media (hover: hover) and (pointer: fine) {
  .global-search-btn, .theme-toggle-btn, .notif-bell-btn { transition: transform .18s var(--ease-out), color .15s ease, background-color .15s ease; }
  .global-search-btn:hover, .theme-toggle-btn:hover, .notif-bell-btn:hover { transform: scale(1.1); }
}

/* Botones de "Actualizar" / "Probar" con ícono */


/* ------------------------------------------------------------------ */
/* Spring Modal (hover.dev) para los avisos de confirmar: entra con     */
/* rebote. El fondo borroso es de todas las ventanas (.modal-overlay).  */
/* ------------------------------------------------------------------ */
/* 2026-11-03: más fluido. Antes la tarjeta salía de scale(0) con 0,5 s y el
   fondo borroso de 6 px se calculaba en el primer cuadro: se veía un
   instante "trabado". Ahora la tarjeta parte de 0,6 (ya visible), con un
   resorte de verdad (linear()), en su propia capa, y el borroso es más liviano. */
.spring-overlay { overflow: hidden; animation: jp-sm-fade .16s ease-out; backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px); }
.spring-overlay.is-closing { animation: jp-sm-fade 150ms var(--ease-out) reverse forwards; }
.confirm-card.spring-card {
  position: relative; z-index: 1; overflow: hidden; isolation: isolate;
  background: linear-gradient(135deg, #35a2db, #1f4f8f); color: #fff; text-align: center;
  max-width: 430px; padding: 26px 24px 22px; border-radius: 14px;
  box-shadow: 0 30px 80px rgba(4, 10, 24, .5);
  animation: jp-sm-in .42s var(--spring-pop, cubic-bezier(.34, 1.4, .64, 1)) both;
  will-change: transform, opacity; backface-visibility: hidden;
}
@supports (animation-timing-function: linear(0, 1)) {
  .confirm-card.spring-card { --spring-pop: linear(0, .21 7%, .62 15%, .96 24%, 1.1 31%, 1.12 35%, 1.08 42%, 1 52%, .98 60%, 1 76%, 1); }
}
.confirm-card.spring-card.is-danger { background: linear-gradient(135deg, #e5484d, #8e1f3a); }
.spring-overlay.is-closing .spring-card { animation: jp-sm-out 150ms var(--ease-out) forwards; }
.spring-card .sm-bg-icon { position: absolute; z-index: -1; left: -28px; top: -26px; width: 230px; height: 230px; color: rgba(255, 255, 255, .1); transform: rotate(12deg); pointer-events: none; }
.spring-card .sm-icon { display: grid; place-items: center; width: 54px; height: 54px; margin: 0 auto 12px; border-radius: 50%; background: #fff; color: #1f4f8f; }
.spring-card.is-danger .sm-icon { color: #c62a3a; }
.spring-card .sm-icon svg { width: 28px; height: 28px; }
.spring-card .modal-title { color: #fff; font-size: calc(22px * var(--fs, 1)); font-weight: 800; margin-bottom: 6px; }
.spring-card .confirm-message { color: rgba(255, 255, 255, .88); margin: 0 0 20px; }
.spring-card .modal-footer { display: flex; gap: 10px; justify-content: center !important; }
.spring-card .modal-footer > * { flex: 1 1 0; min-width: 0; }
.spring-card .modal-footer > .hold-button { flex: 1.4 1 0; }
.spring-card .sm-btn-cancel { background: transparent; color: #fff; border: 1px solid rgba(255, 255, 255, .45); }
.spring-card .sm-btn-cancel:hover { background: rgba(255, 255, 255, .12); }
.spring-card .sm-btn-ok { background: #fff; color: #1f4f8f; border: none; font-weight: 700; }
.spring-card.is-danger .sm-btn-ok { color: #c62a3a; }
.spring-card .sm-btn-ok:hover { background: rgba(255, 255, 255, .9); }
.spring-card .hold-button { min-width: 0; }
@keyframes jp-sm-fade { from { opacity: 0; } }
@keyframes jp-sm-in { from { transform: scale(.6) rotate(8deg); opacity: 0; } 30% { opacity: 1; } }
@keyframes jp-sm-out { to { transform: scale(.95); opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .spring-overlay, .confirm-card.spring-card, .spring-overlay.is-closing, .spring-overlay.is-closing .spring-card { animation-duration: .01s; }
}

/* ===== static/css/app/ordenes/ventana-ot.css ===== */
/* ------------------------------------------------------------------ */
/* Ventana de la OT por pestañas (N30, 2026-11-03)                     */
/* Cabecera fija (título, cliente, estatus, nota fijada y pestañas),   */
/* cuerpo que se desplaza y botones siempre abajo. En PC tiene alto    */
/* fijo para que no "brinque" al cambiar de pestaña; en el celular     */
/* ocupa toda la pantalla como una app.                                */
/* ------------------------------------------------------------------ */
.modal-card-wo.wo-shell {
  display: flex; flex-direction: column; padding: 0; overflow: hidden;
  max-width: 1180px; height: min(900px, calc(100vh - 40px)); height: min(900px, calc(100dvh - 40px)); max-height: none;
}
.wo-shell-head { flex: none; padding: 18px 22px 0; background: var(--surface); border-bottom: 1px solid var(--border); position: relative; z-index: 2; }
.wo-shell-head .modal-header { margin-bottom: 8px; }
.wo-shell-titles { min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.wo-shell-head .modal-title { font-size: calc(20px * var(--fs, 1)); font-weight: 800; }
.wo-shell-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; font-size: calc(13px * var(--fs, 1)); color: var(--text-muted); }
.wo-meta-client { font-weight: 700; color: var(--text); max-width: 46ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wo-meta-sep { color: var(--text-faint); }
.wo-shell-head .wo-pinned-note { margin: 4px 0 10px; }

.wo-due-chip {
  display: inline-flex; align-items: center; padding: 2px 8px; border-radius: 999px; margin-left: 4px;
  font-size: calc(11.5px * var(--fs, 1)); font-weight: 700; background: var(--subtle-bg); color: var(--text-muted); white-space: nowrap;
}
.wo-due-chip.is-late { background: color-mix(in srgb, var(--danger) 14%, transparent); color: var(--danger); }
.wo-due-chip.is-today { background: color-mix(in srgb, var(--warn-text, #b7791f) 16%, transparent); color: var(--warn-text, #b7791f); }
.wo-due-chip.is-soon { background: color-mix(in srgb, var(--secondary) 15%, transparent); color: var(--accent-text); }

/* --- Pestañas: barra con una rayita que se desliza (Animated Tabs) --- */
.wo-tabs {
  position: relative; display: flex; gap: 2px; margin: 0 -8px; padding: 0 8px;
  overflow-x: auto; overflow-y: hidden; scrollbar-width: none; -webkit-overflow-scrolling: touch;
  scroll-snap-type: x proximity; overscroll-behavior-x: contain;
}
.wo-tabs::-webkit-scrollbar { display: none; }
.wo-tab {
  position: relative; flex: none; display: inline-flex; align-items: center; gap: 7px;
  padding: 10px 14px 12px; border: none; background: none; border-radius: 8px 8px 0 0; cursor: pointer;
  font: inherit; font-size: calc(13.5px * var(--fs, 1)); font-weight: 600; color: var(--text-muted);
  scroll-snap-align: center; -webkit-tap-highlight-color: transparent; user-select: none;
  transition: color .15s ease, background-color .15s ease;
}
.wo-tab-ico { display: inline-flex; }
.wo-tab-ico svg { width: 16px; height: 16px; }
.wo-tab.is-active { color: var(--accent-text); font-weight: 750; }
@media (hover: hover) and (pointer: fine) { .wo-tab:not(.is-active):hover { color: var(--text); background: var(--subtle-bg); } }
.wo-tab:focus-visible { outline: 2px solid var(--secondary); outline-offset: -2px; }
.wo-tab-badge {
  min-width: 18px; height: 18px; padding: 0 5px; border-radius: 999px; display: inline-grid; place-items: center;
  font-size: calc(11px * var(--fs, 1)); font-weight: 700; background: var(--subtle-bg); color: var(--text-muted); font-variant-numeric: tabular-nums;
}
.wo-tab.is-active .wo-tab-badge { background: color-mix(in srgb, var(--secondary) 18%, transparent); color: var(--accent-text); }
.wo-tab-badge.is-alert { background: var(--danger) !important; color: #fff !important; animation: wo-badge-pop .35s var(--ease-out); }
@keyframes wo-badge-pop { from { transform: scale(.4); } }
.wo-tabs-pill {
  position: absolute; left: 0; bottom: 0; height: 3px; width: 0; border-radius: 3px 3px 0 0; pointer-events: none;
  background: linear-gradient(90deg, var(--main), var(--secondary));
  transition: transform .32s var(--ease-out), width .32s var(--ease-out);
}
.wo-tabs-pill.no-anim { transition: none; }

/* --- Cuerpo y pestañas --- */
.wo-shell-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 18px 22px 26px; overscroll-behavior: contain; scroll-padding-top: 12px; }
.wo-pane:focus { outline: none; }
.wo-pane.is-entering { animation: wo-pane-in 120ms var(--ease-out); }
@keyframes wo-pane-in { from { opacity: 0; } }
.wo-pane-title { font-size: calc(12px * var(--fs, 1)); font-weight: 800; letter-spacing: .05em; text-transform: uppercase; color: var(--text-faint); margin: 0 0 10px; }
.wo-pane-section { margin-bottom: 20px; }
.wo-pane-hint { margin-top: 4px; }
.wo-pane-next { display: flex; justify-content: flex-end; margin-top: 18px; }
.wo-form-section { padding-bottom: 16px; margin-bottom: 16px; border-bottom: 1px solid var(--border); }
.wo-form-section:last-of-type { border-bottom: none; }
.wo-form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 0 16px; }
.wo-shell > .modal-footer { flex: none; margin: 0; padding: 12px 22px; border-top: 1px solid var(--border); background: var(--surface); }

/* --- Avance de la orden (estatus en una línea) --- */
.wo-steps { list-style: none; display: flex; align-items: flex-start; margin: 0 0 18px; padding: 4px 0 2px; overflow-x: auto; scrollbar-width: none; }
.wo-steps::-webkit-scrollbar { display: none; }
.wo-step {
  --wo-step: var(--secondary);
  position: relative; flex: 1 0 74px; display: flex; flex-direction: column; align-items: center; gap: 7px; min-width: 0;
  font-size: calc(11.5px * var(--fs, 1)); color: var(--text-faint); text-align: center; line-height: 1.2;
}
.wo-step::before { content: ""; position: absolute; top: 7px; right: 50%; width: 100%; height: 3px; background: var(--border); border-radius: 2px; }
.wo-step:first-child::before { display: none; }
.wo-step.is-done::before, .wo-step.is-current::before { background: var(--wo-step); }
.wo-step-dot { position: relative; z-index: 1; width: 17px; height: 17px; border-radius: 50%; background: var(--surface); border: 3px solid var(--border); box-sizing: border-box; }
.wo-step.is-done .wo-step-dot { background: var(--wo-step); border-color: var(--wo-step); }
.wo-step.is-current .wo-step-dot { border-color: var(--wo-step); background: var(--surface); box-shadow: 0 0 0 5px color-mix(in srgb, var(--wo-step) 22%, transparent); animation: wo-step-glow 2.4s ease-in-out infinite; }
.wo-step.is-current { color: var(--text); font-weight: 750; }
.wo-step.is-done { color: var(--text-muted); }
@keyframes wo-step-glow { 50% { box-shadow: 0 0 0 8px color-mix(in srgb, var(--wo-step) 8%, transparent); } }

/* --- Tarjetas del Resumen (estilo Magic Card: borde fino, se ilumina al pasar) --- */
.wo-sum-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 14px; margin-bottom: 16px; }
.wo-sum-card {
  position: relative; border: 1px solid var(--border); border-radius: var(--radius); padding: 14px 16px; background: var(--surface);
  transition: border-color .2s ease, box-shadow .2s ease; min-width: 0;
}
@media (hover: hover) and (pointer: fine) { .wo-sum-card:hover { border-color: color-mix(in srgb, var(--secondary) 45%, var(--border)); box-shadow: 0 6px 22px rgba(16, 34, 64, .07); } }
.wo-sum-card.is-wide { grid-column: 1 / -1; }
.wo-sum-card-title { display: flex; align-items: center; gap: 6px; margin-bottom: 10px; font-size: calc(11.5px * var(--fs, 1)); font-weight: 800; letter-spacing: .05em; text-transform: uppercase; color: var(--text-faint); }
.wo-sum-count { padding: 1px 7px; border-radius: 999px; background: var(--subtle-bg); color: var(--text-muted); letter-spacing: 0; }
.wo-sum-link { margin-left: auto; border: none; background: none; padding: 2px 4px; cursor: pointer; font: inherit; font-size: calc(12px * var(--fs, 1)); font-weight: 700; color: var(--accent-text); text-transform: none; letter-spacing: 0; }
@media (hover: hover) and (pointer: fine) { .wo-sum-link:hover { text-decoration: underline; } }
.wo-sum-big { font-size: calc(17px * var(--fs, 1)); font-weight: 800; color: var(--text); line-height: 1.25; overflow-wrap: anywhere; }
.wo-sum-sub { font-size: calc(12.5px * var(--fs, 1)); color: var(--text-muted); margin-top: 2px; }
.wo-sum-contacts { margin-top: 10px; padding-top: 8px; border-top: 1px dashed var(--border); font-size: calc(12.5px * var(--fs, 1)); overflow-wrap: anywhere; }
.wo-sum-row { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 7px 0; border-top: 1px dashed var(--border); font-size: calc(13px * var(--fs, 1)); }
.wo-sum-row:first-of-type { border-top: none; padding-top: 0; }
.wo-sum-row > span { color: var(--text-muted); }
/* Fecha con su etiqueta (Atrasada, Vence hoy…): la etiqueta baja a su propia línea, a la derecha y con aire. */
.wo-sum-row > b:has(.wo-due-chip) { display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: 6px 8px; }
.wo-sum-row > b:has(.wo-due-chip) .wo-due-chip { margin-left: 0; }
.wo-sum-row:has(.wo-due-chip) { padding-bottom: 2px; }
.wo-sum-row > b { text-align: right; font-weight: 700; color: var(--text); overflow-wrap: anywhere; }
.wo-yes-danger { color: var(--danger); }
.wo-sum-items { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.wo-sum-items li { display: flex; align-items: baseline; gap: 8px; font-size: calc(13px * var(--fs, 1)); min-width: 0; }
.wo-sum-qty { flex: none; color: var(--text-muted); font-weight: 700; }
.wo-sum-desc { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wo-sum-size { flex: none; color: var(--text-faint); font-size: calc(12px * var(--fs, 1)); }
.wo-sum-more { margin-top: 6px; font-size: calc(12px * var(--fs, 1)); color: var(--text-faint); }
.wo-sum-total { font-size: calc(26px * var(--fs, 1)); font-weight: 800; color: var(--accent-text); letter-spacing: -.01em; }
.wo-sum-note { white-space: pre-wrap; font-size: calc(13.5px * var(--fs, 1)); line-height: 1.5; overflow-wrap: anywhere; }

/* --- Dinero --- */
.wo-money-tiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin-bottom: 16px; }
.wo-money-tile { display: flex; flex-direction: column; gap: 4px; padding: 14px 16px; border-radius: var(--radius); background: var(--subtle-bg); min-width: 0; }
.wo-money-tile > span { font-size: calc(12px * var(--fs, 1)); font-weight: 700; color: var(--text-muted); }
.wo-money-tile > b { font-size: calc(19px * var(--fs, 1)); font-weight: 800; overflow-wrap: anywhere; }
.wo-money-tile.is-total { background: linear-gradient(135deg, var(--main), color-mix(in srgb, var(--main) 55%, var(--secondary))); color: #fff; }
.wo-money-tile.is-total > span { color: rgba(255, 255, 255, .82); }
.wo-money-tile.is-total > b { font-size: calc(23px * var(--fs, 1)); }
.wo-sum-row .wo-special-pay { justify-content: flex-end; }

/* --- Celular: pantalla completa, pestañas deslizables --- */
@media (max-width: 768px) {
  .wo-shell-overlay { padding: 0; }
  .modal-card-wo.wo-shell { max-width: none; width: 100%; height: 100vh; height: 100dvh; border-radius: 0; }
  .wo-shell-head { padding: calc(12px + env(safe-area-inset-top, 0px)) 16px 0; }
  .wo-shell-head .modal-title { font-size: calc(17px * var(--fs, 1)); }
  .wo-meta-sep { display: none; }
  .wo-shell-meta { gap: 6px 10px; }
  .wo-shell-body { padding: 14px 16px 22px; }
  .modal-card.wo-shell > .modal-footer { position: static; margin: 0; padding: 10px 16px calc(10px + env(safe-area-inset-bottom, 0px)); }
  .wo-tab { padding: 10px 11px 12px; font-size: calc(13px * var(--fs, 1)); }
  .wo-sum-grid { grid-template-columns: minmax(0, 1fr); gap: 10px; }
  .wo-money-tiles { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .wo-money-tile.is-total { grid-column: 1 / -1; }
  .wo-step { flex-basis: 64px; font-size: calc(10.5px * var(--fs, 1)); }
  .wo-step:not(.is-current) .wo-step-label { opacity: .85; }
}
@media (prefers-reduced-motion: reduce) {
  .wo-pane.is-entering, .wo-step.is-current .wo-step-dot, .wo-tab-badge.is-alert { animation: none; }
  .wo-tabs-pill { transition: none; }
}

/* N07 (2026-11-04): manija para reordenar renglones y botón Duplicar. */
.wo-contact-list { display: grid; gap: 2px; margin-bottom: 4px; }
.wo-contact-pick { justify-content: flex-start; gap: 8px; height: auto; padding: 4px 0; white-space: normal; overflow-wrap: anywhere; }
.wo-contact-extra { color: var(--text-faint); font-weight: 400; }
.wo-contact-form-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.wo-sum-more { margin-top: 4px; }
.wo-sum-more summary { cursor: pointer; color: var(--main); font-weight: 600; margin-bottom: 4px; }
.wo-item-num { white-space: nowrap; }
.wo-item-num span { vertical-align: middle; }
.wo-item-grip {
  display: inline-grid; place-items: center; width: 22px; height: 28px; margin-right: 4px; padding: 0;
  border: 0; border-radius: 6px; background: transparent; color: var(--text-faint); cursor: grab;
  touch-action: none; vertical-align: middle;
}
.wo-item-grip:hover, .wo-item-grip:focus-visible { background: var(--subtle-bg); color: var(--main); }
.wo-item-grip:active { cursor: grabbing; }
.wo-item-dup, .wo-item-remove {
  display: inline-grid; place-items: center; width: 24px; height: 28px; margin-right: 4px; padding: 0;
  border: 0; border-radius: 6px; background: transparent; color: var(--text-faint); cursor: pointer; vertical-align: middle;
}
.wo-item-dup svg, .wo-item-remove svg { width: 15px; height: 15px; }
.wo-item-dup:hover, .wo-item-dup:focus-visible { background: var(--subtle-bg); color: var(--main); }
.wo-item-remove:hover, .wo-item-remove:focus-visible { background: var(--subtle-bg); color: var(--danger); }
.wo-item-remove:disabled { opacity: .35; cursor: not-allowed; background: transparent; color: var(--text-faint); }
tr.wo-item-row.is-dragging { opacity: .55; background: var(--subtle-bg); }
tr.wo-item-row.drop-before > td { box-shadow: inset 0 3px 0 var(--secondary); }
tr.wo-item-row.drop-after > td { box-shadow: inset 0 -3px 0 var(--secondary); }
.wo-items-section { margin-top: 6px; }

/* N09: la línea de avance se toca para cambiar el estatus. */
.wo-steps.is-clickable .wo-step-dot { transition: transform .15s ease, box-shadow .15s ease; }
.wo-steps.is-clickable .wo-step { cursor: pointer; border-radius: 8px; }
@media (hover: hover) and (pointer: fine) {
  .wo-steps.is-clickable .wo-step:not(.is-current):not(.is-disabled):hover .wo-step-dot { transform: scale(1.25); box-shadow: 0 0 0 4px rgba(42, 109, 192, .18); }
}
.wo-steps.is-clickable .wo-step:not(.is-current):not(.is-disabled):hover .wo-step-label { color: var(--main); text-decoration: underline; }
.wo-steps .wo-step.is-disabled { opacity: .45; cursor: not-allowed; }
.wo-steps .wo-step:focus-visible { outline: 2px solid var(--secondary); outline-offset: 2px; }
.wo-steps-hint { margin: -4px 0 10px; font-size: calc(12px * var(--fs, 1)); color: var(--text-faint); }
.wo-steps-hint kbd { font: inherit; font-weight: 700; padding: 0 5px; border: 1px solid var(--border); border-radius: 4px; background: var(--subtle-bg); }
.wo-art-divider { height: 1px; margin: 18px 0; background: var(--border); }

/* Aviso "otra persona está editando" (N08) */
.wo-presence-banner {
  margin: 8px 0 2px; padding: 7px 12px; border-radius: var(--radius-sm); font-size: calc(12.5px * var(--fs, 1));
  background: var(--warn-bg); color: var(--warn-text); border: 1px solid currentColor;
}
.wo-presence-banner[hidden] { display: none; }
.wo-conflict-table td { overflow-wrap: anywhere; }
.wo-conflict-footer { flex-wrap: wrap; justify-content: flex-end; gap: 8px; }

/* ===== static/css/app/base/conexion-y-visor.css ===== */
/* Aviso de sin conexión (V12) y visor de fotos a pantalla completa (V13), 2026-11-12. */

/* --- Franja de conexión: arriba al centro, encima de todo menos los toasts --- */
.conn-banner {
  position: fixed; left: 50%; top: calc(10px + env(safe-area-inset-top)); z-index: 1150;
  display: flex; align-items: center; gap: 10px; max-width: min(560px, calc(100vw - 32px));
  padding: 9px 16px; border-radius: 999px; font-size: calc(13.5px * var(--fs, 1)); line-height: 1.35;
  box-shadow: 0 8px 28px rgba(0, 0, 0, .18); pointer-events: none;
  transform: translate(-50%, -140%); opacity: 0;
  transition: transform .32s var(--ease-out, ease-out), opacity .24s ease;
}
.conn-banner.is-shown { transform: translate(-50%, 0); opacity: 1; }
.conn-banner.is-off { background: var(--danger); color: #fff; }
.conn-banner.is-on { background: var(--success); color: #fff; }
.conn-dot { flex-shrink: 0; width: 9px; height: 9px; border-radius: 50%; background: #fff; }
.conn-banner.is-off .conn-dot { animation: conn-pulse 1.4s ease-in-out infinite; }
@keyframes conn-pulse { 50% { opacity: .35; transform: scale(.75); } }
@media (max-width: 860px) {
  .conn-banner { border-radius: 14px; top: calc(8px + env(safe-area-inset-top)); width: calc(100vw - 32px); }
}

/* --- Visor de fotos --- */
.photo-viewer {
  position: fixed; inset: 0; z-index: 1300; background: rgba(6, 10, 18, calc(.94 * var(--fade, 1)));
  opacity: 0; transition: opacity .2s ease; touch-action: none; user-select: none; -webkit-user-select: none;
}
.photo-viewer.is-open { opacity: 1; }
body.photo-viewer-open { overflow: hidden; }
.photo-viewer-stage { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; overflow: hidden; cursor: zoom-in; }
.photo-viewer.is-zoomed .photo-viewer-stage { cursor: grab; }
.photo-viewer.is-zoomed .photo-viewer-stage:active { cursor: grabbing; }
.photo-viewer-img {
  max-width: 100vw; max-height: 100vh; object-fit: contain; transform-origin: center center;
  will-change: transform; -webkit-user-drag: none; pointer-events: auto;
}
@media (min-width: 861px) { .photo-viewer-img { max-width: 92vw; max-height: 90vh; border-radius: 6px; } }
.photo-viewer-img.is-animating { transition: transform .26s var(--ease-out, ease-out); }
.photo-viewer-img.is-from-next { animation: pv-in-next .26s var(--ease-out, ease-out); }
.photo-viewer-img.is-from-prev { animation: pv-in-prev .26s var(--ease-out, ease-out); }
@keyframes pv-in-next { from { opacity: 0; translate: 40px 0; } }
@keyframes pv-in-prev { from { opacity: 0; translate: -40px 0; } }
.photo-viewer-top {
  position: absolute; top: 0; left: 0; right: 0; display: flex; align-items: center; justify-content: space-between;
  padding: calc(10px + env(safe-area-inset-top)) 14px 10px; pointer-events: none;
}
.photo-viewer-count { color: rgba(255, 255, 255, .85); font-size: 14px; font-weight: 700; font-variant-numeric: tabular-nums;
  background: rgba(0, 0, 0, .35); padding: 4px 10px; border-radius: 999px; }
.photo-viewer-btn {
  pointer-events: auto; border: none; color: #fff; background: rgba(255, 255, 255, .14); cursor: pointer;
  width: 44px; height: 44px; padding: 0; border-radius: 50%; line-height: 0; display: grid; place-items: center;
  transition: background .15s ease;
}
.photo-viewer-btn svg { display: block; }
.photo-viewer-btn:hover { background: rgba(255, 255, 255, .26); }
.photo-viewer-btn:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.photo-viewer-close { margin-left: auto; }
.photo-viewer-nav { position: absolute; top: 50%; translate: 0 -50%; width: 52px; height: 52px; }
.photo-viewer-nav.is-prev { left: 14px; }
.photo-viewer-nav.is-next { right: 14px; }
.photo-viewer-hint {
  position: absolute; left: 50%; bottom: calc(14px + env(safe-area-inset-bottom)); translate: -50% 0;
  color: rgba(255, 255, 255, .7); font-size: 12.5px; background: rgba(0, 0, 0, .35); padding: 5px 12px; border-radius: 999px;
  white-space: nowrap; pointer-events: none; animation: pv-hint 4s ease forwards;
}
@keyframes pv-hint { 0%, 70% { opacity: 1; } 100% { opacity: 0; } }
/* En el celular las flechas estorban: se cambia deslizando. */
@media (max-width: 860px) { .photo-viewer-nav { display: none; } }
@media (prefers-reduced-motion: reduce) {
  .photo-viewer-img.is-animating, .photo-viewer, .conn-banner { transition: none; }
  .photo-viewer-img.is-from-next, .photo-viewer-img.is-from-prev { animation: none; }
}

/* ===== static/css/app/ordenes/gestos-y-progreso.css ===== */
/* Órdenes, ronda del 2026-11-12: línea de "ahora" (V07), orden que vuela a
   su columna (V06), deslizar fichas (V10), botón flotante (V11), anillo del
   día (V16) y "Visto por" en el chat (V24). */

/* --- V07: línea de "ahora" en el Gantt --- */
.wo-gantt-track > .wo-gantt-now {
  position: absolute; top: 0; bottom: 0; left: var(--now-pct, 0%); width: 2px; margin-left: -1px;
  justify-self: auto; grid-row: auto; height: auto; opacity: 1; z-index: 3;
  background: var(--danger); box-shadow: 0 0 0 1px color-mix(in srgb, var(--danger) 25%, transparent);
}
.wo-gantt-row:not(.wo-gantt-headrow):not(.wo-gantt-loadrow) + .wo-gantt-row .wo-gantt-now { top: -1px; }
.wo-gantt-past {
  position: absolute; top: 0; bottom: 0; left: 0; width: var(--now-pct, 0%); z-index: 2; pointer-events: none;
  background: color-mix(in srgb, var(--surface) 48%, transparent);
}
/* La bolita roja de "ahora" arriba, en la fila de los días. */
.wo-gantt-headrow .wo-gantt-days { position: relative; }
.wo-gantt-headrow .wo-gantt-days::after {
  content: ""; position: absolute; bottom: -4px; left: var(--now-pct, -20px); width: 8px; height: 8px; margin-left: -4px;
  border-radius: 50%; background: var(--danger); z-index: 3;
}
.wo-gantt[style*="--now-pct:0%"] .wo-gantt-headrow .wo-gantt-days::after,
.wo-gantt[style*="--now-pct:100%"] .wo-gantt-headrow .wo-gantt-days::after { display: none; }

/* --- V07: Calendario: los días pasados, más apagados (sin línea de "ahora") --- */
.wo-cal-cell-past > * { opacity: .55; }
.wo-cal-cell-past { background: color-mix(in srgb, var(--bg) 55%, var(--surface)); }

/* --- V06: la orden nueva vuela a su columna --- */
.wo-fly-ghost {
  position: fixed !important; margin: 0 !important; z-index: 1250; pointer-events: none;
  content-visibility: visible !important; transform-origin: center center; will-change: transform, opacity;
  box-shadow: 0 18px 50px rgba(0, 0, 0, .28);
}
.kanban-card.wo-arrived { animation: wo-arrive 2.6s ease-out; }
@keyframes wo-arrive {
  0% { box-shadow: 0 0 0 3px var(--main), 0 0 26px 4px color-mix(in srgb, var(--main) 55%, transparent); }
  12% { transform: scale(1.03); }
  25% { transform: scale(1); }
  70% { box-shadow: 0 0 0 3px var(--main), 0 0 18px 2px color-mix(in srgb, var(--main) 35%, transparent); }
  100% { box-shadow: 0 0 0 0 transparent; }
}

/* --- V10: deslizar una ficha de la Cuadrícula --- */
.wo-grid { position: relative; }
@media (hover: none), (pointer: coarse) {
  .wo-grid .wo-card[data-id] { touch-action: pan-y; }
}
.wo-card.is-swiping { position: relative; z-index: 1; transition: none; }
.wo-card[data-id]:not(.is-swiping) { transition: transform .24s var(--ease-out, ease-out); }
.wo-swipe-bg {
  position: absolute; z-index: 0; border-radius: var(--radius); overflow: hidden; display: flex; align-items: center;
  justify-content: space-between; padding: 0 18px; font-weight: 800; font-size: calc(14px * var(--fs, 1));
  background: color-mix(in srgb, var(--accent-text) 18%, var(--surface)); color: var(--accent-text);
}
.wo-swipe-bg.is-right { background: color-mix(in srgb, var(--success) 22%, var(--surface)); color: var(--success); }
.wo-swipe-bg .wo-swipe-act-next { opacity: 0; }
.wo-swipe-bg .wo-swipe-act-more { opacity: 1; margin-left: auto; }
.wo-swipe-bg.is-right .wo-swipe-act-next { opacity: 1; }
.wo-swipe-bg.is-right .wo-swipe-act-more { opacity: 0; }
.wo-swipe-act { transition: transform .18s ease; }
.wo-swipe-bg.is-armed .wo-swipe-act { transform: scale(1.12); }
.wo-swipe-bg.is-armed { background: var(--accent-text); color: #fff; }
.wo-swipe-bg.is-armed.is-right { background: var(--success); }

/* Menú de opciones (al deslizar a la izquierda): hoja que sube desde abajo. */
.wo-swipe-sheet-overlay { align-items: flex-end; justify-content: center; padding: 0; background: rgba(0, 0, 0, 0); transition: background .2s ease; }
.wo-swipe-sheet-overlay.is-open { background: rgba(0, 0, 0, .4); }
.wo-swipe-sheet {
  width: 100%; max-width: 520px; background: var(--surface); color: var(--text); border-radius: 18px 18px 0 0;
  padding: 16px 16px calc(16px + env(safe-area-inset-bottom)); box-shadow: 0 -10px 40px rgba(0, 0, 0, .25);
  transform: translateY(100%); transition: transform .28s var(--ease-drawer, ease-out);
}
.wo-swipe-sheet-overlay.is-open .wo-swipe-sheet { transform: translateY(0); }
.wo-swipe-sheet-head { font-weight: 800; margin-bottom: 12px; }
.wo-swipe-sheet-label { font-size: 12px; font-weight: 700; color: var(--text-faint); text-transform: uppercase; letter-spacing: .04em; margin-bottom: 8px; }
.wo-swipe-sheet-statuses { display: grid; grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: 8px; }
.wo-swipe-status {
  min-height: 44px; border-radius: 12px; border: 1px solid var(--border); background: var(--input-bg, var(--surface));
  color: var(--text); font: inherit; font-weight: 700; cursor: pointer; border-left: 5px solid var(--st);
}
.wo-swipe-status:disabled { opacity: .45; cursor: default; }
.wo-swipe-status.is-current { outline: 2px solid var(--st); outline-offset: -2px; }
.wo-swipe-sheet-foot { display: flex; justify-content: flex-end; gap: 8px; margin-top: 14px; }

/* --- V11: botón flotante "+ Nueva orden" (solo celular) --- */
.wo-fab {
  position: fixed; right: calc(18px + env(safe-area-inset-right)); bottom: calc(20px + env(safe-area-inset-bottom)); z-index: 900;
  width: 58px; height: 58px; border-radius: 50%; border: none; cursor: pointer; display: none; place-items: center;
  background: var(--main); color: #fff; box-shadow: 0 10px 26px color-mix(in srgb, var(--main) 45%, rgba(0, 0, 0, .25));
  transition: transform .26s var(--ease-out, ease-out), opacity .2s ease;
  -webkit-tap-highlight-color: transparent;
}
.wo-fab:active { transform: scale(.92); }
.wo-fab.is-hidden { transform: translateY(110px); opacity: 0; pointer-events: none; }
@media (max-width: 860px) { body.app-mode .wo-fab { display: grid; } }
body:has(.modal-overlay) .wo-fab, body.wo-tv-open .wo-fab, body.photo-viewer-open .wo-fab { display: none !important; }

/* --- V16: anillo del progreso del día --- */
.day-ring { position: relative; width: 132px; height: 132px; flex-shrink: 0; }
.day-ring svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.day-ring circle { fill: none; stroke-width: 11; }
.day-ring-track { stroke: color-mix(in srgb, var(--main) 14%, transparent); }
.day-ring-fill { stroke: var(--main); stroke-linecap: round; transition: stroke-dashoffset 1.1s cubic-bezier(.25, .8, .25, 1); }
.day-ring.is-done .day-ring-fill { stroke: var(--success); }
.day-ring.is-empty .day-ring-fill { stroke: transparent; }
.day-ring-text { position: absolute; inset: 22px; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; line-height: 1.15; }
.day-ring-text b { font-size: 22px; font-weight: 800; font-variant-numeric: tabular-nums; white-space: nowrap; }
.day-ring-text span { font-size: 10px; color: var(--text-muted); margin-top: 2px; text-wrap: balance; }
.day-ring.is-done .day-ring-text b { color: var(--success); }

/* Inicio: debajo de "Próximos cumpleaños" y del mismo ancho, más bajita. */
#home-birthdays-slot, #home-progress-slot { width: 100%; max-width: 640px; }
#home-progress-slot:empty { display: none; }
.home-progress-card {
  display: flex; align-items: center; gap: 16px; box-sizing: border-box; padding-top: 12px; padding-bottom: 12px;
  font: inherit; color: inherit; cursor: pointer; border: 1px solid var(--border);
  transition: transform .2s var(--ease-out, ease-out), box-shadow .2s ease;
}
@media (hover: hover) { .home-progress-card:hover { transform: translateY(-2px); box-shadow: var(--shadow); } }
.home-progress-card .day-ring { width: 84px; height: 84px; }
.home-progress-card .day-ring-text { inset: 12px; }
.home-progress-card .day-ring-text b { font-size: 15px; }
.home-progress-card .day-ring-text span { display: none; }
.home-progress-label { display: flex; flex-direction: column; font-size: 16px; font-weight: 800; }
.home-progress-label small { font-size: 13px; font-weight: 500; color: var(--text-muted); margin-top: 2px; }

/* En la pantalla del taller, más grande y junto al reloj. */
.wo-tv-ring { margin-left: auto; }
.wo-tv-ring + .wo-tv-clock-box { margin-left: 2vmin; }
.day-ring.is-tv { width: clamp(110px, 17vmin, 240px); height: clamp(110px, 17vmin, 240px); }
.day-ring.is-tv .day-ring-text { inset: 12%; }
.day-ring.is-tv .day-ring-text b { font-size: clamp(18px, 2.7vmin, 40px); }
.day-ring.is-tv .day-ring-text span { font-size: clamp(10px, 1.4vmin, 20px); }

/* --- V24: "Visto por" debajo del último mensaje --- */
.wo-seen-by { display: flex; align-items: center; gap: 6px; margin: -4px 0 0 42px; font-size: 11.5px; color: var(--text-faint); }
.wo-seen-by.is-mine { justify-content: flex-end; margin: -4px 0 0 0; }
.wo-seen-by-faces { display: inline-flex; flex-direction: row; }
.wo-seen-face {
  width: 18px; height: 18px; border-radius: 50%; overflow: hidden; display: inline-grid; place-items: center;
  background: var(--secondary-light); color: var(--accent-text); font-size: 8px; font-weight: 800;
  border: 1.5px solid var(--surface); margin-left: -5px; animation: wo-seen-in .3s var(--ease-out, ease-out) backwards;
}
.wo-seen-face:first-child { margin-left: 0; }
.wo-seen-face img { width: 100%; height: 100%; object-fit: cover; }
.wo-seen-more { font-size: 8.5px; }
@keyframes wo-seen-in { from { opacity: 0; transform: scale(.6); } }

@media (prefers-reduced-motion: reduce) {
  .kanban-card.wo-arrived { animation-duration: .01s; box-shadow: 0 0 0 3px var(--main); }
  .day-ring-fill, .wo-fab, .wo-swipe-sheet, .wo-card[data-id]:not(.is-swiping) { transition: none; }
  .wo-seen-face { animation: none; }
}

/* ===== static/css/app/rrhh/rrhh.css ===== */
/* ------------------------------------------------------------------ */
/* RR. HH.: Aportes IHSS/RAP (N16) y Calendario del equipo (N18)       */
/* ------------------------------------------------------------------ */
.aportes-card { max-width: 1100px; }
.aportes-toolbar { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px 16px; margin-bottom: 14px; }
.aportes-toolbar select { min-width: 170px; text-transform: capitalize; }
.aportes-runs { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; padding-bottom: 6px; }
.aportes-warn { margin-bottom: 12px; }
.aportes-tiles { margin-bottom: 14px; }
.aportes-tiles .stat-num { white-space: nowrap; }
@media (max-width: 768px) {
  .aportes-tiles .stat-num { font-size: calc(19px * var(--fs, 1)); }
  .aportes-tiles .stat-label { font-size: calc(11px * var(--fs, 1)); }
}
.aportes-table-wrap { max-height: 46vh; }
.aportes-table th, .aportes-table td { white-space: nowrap; }
.aportes-table thead th.aportes-group { text-align: center; border-bottom: 2px solid var(--secondary); }
.aportes-table tfoot td { font-weight: 800; background: var(--subtle-bg); position: sticky; bottom: 0; padding: 10px 16px; white-space: nowrap; }
.aportes-table td:nth-child(n+3), .aportes-table th:nth-child(n+3) { text-align: right; }

/* Calendario del equipo: nombre fijo a la izquierda, días con scroll. */
.tcal-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 18px; margin-bottom: 10px; }
.tcal-nav { display: flex; align-items: center; gap: 6px; }
.tcal-title { min-width: 150px; text-align: center; font-size: calc(16px * var(--fs, 1)); font-weight: 800; text-transform: capitalize; }
.tcal-range { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; font-size: calc(12.5px * var(--fs, 1)); color: var(--text-muted); }
.tcal-range label { display: inline-flex; align-items: center; gap: 6px; }
.tcal-range input[type="date"] { padding: 4px 8px; min-height: 32px; width: auto; background: var(--surface); color: var(--text); border: 1px solid var(--border); border-radius: 8px; }
:root[data-theme="dark"] .tcal-range input[type="date"] { color-scheme: dark; }
.tcal-error { color: var(--danger, #c0392b); margin: 0 0 8px; }
.tcal-day.is-month-start, .tcal-cell.is-month-start { border-left: 2px solid var(--border-strong, #9aa7b8); }
.tcal-legend { display: flex; flex-wrap: wrap; gap: 6px 12px; margin-left: auto; font-size: calc(12px * var(--fs, 1)); color: var(--text-muted); }
.tcal-legend span { display: inline-flex; align-items: center; gap: 5px; }
.tcal-legend .tcal-block { width: 14px; height: 12px; }
.tcal-holidays { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
.tcal-hol-chip { padding: 2px 9px; border-radius: 999px; font-size: calc(12px * var(--fs, 1)); background: color-mix(in srgb, var(--warn-text) 14%, transparent); color: var(--warn-text); font-weight: 600; }
.tcal-wrap { max-height: 64vh; }
.tcal-table { border-collapse: separate; border-spacing: 0; width: max-content; min-width: 100%; }
.tcal-table th, .tcal-table td { padding: 0; border-bottom: 1px solid var(--border); }
.tcal-table thead th { position: sticky; top: 0; z-index: 2; background: var(--surface); }
.tcal-name { position: sticky; left: 0; z-index: 1; background: var(--surface); text-align: left; padding: 6px 12px 6px 4px !important; min-width: 170px; max-width: 220px; border-right: 1px solid var(--border); }
.tcal-table thead .tcal-name { z-index: 3; }
.tcal-name span { display: block; font-weight: 600; font-size: calc(13px * var(--fs, 1)); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tcal-name small { display: block; font-size: calc(11px * var(--fs, 1)); color: var(--text-faint); font-weight: 400; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tcal-day { width: 30px; min-width: 30px; text-align: center; padding: 4px 0 !important; font-weight: 600; }
.tcal-wd { display: block; font-size: calc(10px * var(--fs, 1)); color: var(--text-faint); }
.tcal-num { display: block; font-size: calc(12.5px * var(--fs, 1)); }
.tcal-count { display: block; height: 15px; font-size: calc(10px * var(--fs, 1)); color: transparent; }
.tcal-count.has { color: var(--danger); font-weight: 800; }
.tcal-cell { height: 30px; text-align: center; vertical-align: middle; }
.tcal-cell.is-sunday, .tcal-day.is-sunday { background: var(--subtle-bg); }
.tcal-cell.is-holiday, .tcal-day.is-holiday { background: color-mix(in srgb, var(--warn-text) 10%, transparent); }
.tcal-day.is-today .tcal-num { display: inline-grid; place-items: center; width: 22px; height: 22px; border-radius: 50%; background: var(--main); color: #fff; }
.tcal-cell.is-today { box-shadow: inset 1px 0 0 var(--secondary), inset -1px 0 0 var(--secondary); }
.tcal-block { display: inline-block; width: 24px; height: 18px; border-radius: 5px; vertical-align: middle; cursor: help; transition: transform .15s var(--ease-out); }
@media (hover: hover) and (pointer: fine) { .tcal-cell .tcal-block:hover { transform: scale(1.15); } }
.tcal-vacaciones { background: #35a2db; }
.tcal-permiso { background: #8b6fd6; }
.tcal-medica { background: #2fa37a; }
.tcal-incapacidad { background: #e5484d; }
.tcal-falta { background: #8a96a8; background-image: repeating-linear-gradient(45deg, rgba(255, 255, 255, .35) 0 3px, transparent 3px 6px); }
.tcal-hol { background: color-mix(in srgb, var(--warn-text) 35%, transparent); }
.tcal-total { min-width: 42px; text-align: center; font-weight: 800; color: var(--text-muted); padding: 0 6px !important; }
@media (max-width: 768px) {
  .tcal-legend { margin-left: 0; }
  .tcal-name { min-width: 120px; max-width: 140px; }
}

/* ===== static/css/app/base/accesibilidad.css ===== */
/* ------------------------------------------------------------------ */
/* Accesibilidad (2026-10-16): letra más grande, alto contraste,        */
/* botones grandes y menos animaciones. Se eligen en menú del usuario → */
/* Accesibilidad y se guardan en este dispositivo (localStorage         */
/* "jp-a11y"); el <script> del <head> los pone en <html> antes de       */
/* pintar: data-text, data-contrast, data-touch, data-motion.           */
/* Todo font-size de style.css/fx.css va multiplicado por --fs.         */
/* También: la paleta Ctrl+K, la ventana de atajos y la de términos.    */
/* ------------------------------------------------------------------ */
:root { --fs: 1; }
:root[data-text="lg"] { --fs: 1.12; }
:root[data-text="xl"] { --fs: 1.25; }
body { font-size: calc(16px * var(--fs, 1)); }
@media print { :root, :root[data-text] { --fs: 1; } }

/* Solo para lectores de pantalla. */
.sr-only {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
/* "Saltar al contenido": aparece solo al llegar con Tab. */
.skip-link {
  position: fixed; top: 8px; left: 8px; z-index: 3000;
  background: var(--main); color: #fff; font-weight: 700; padding: 10px 16px; border-radius: 8px;
  transform: translateY(-160%); transition: transform .15s ease;
}
.skip-link:focus { transform: none; outline: 3px solid var(--secondary); outline-offset: 2px; }
#view:focus { outline: none; }

/* Anillo de foco visible al usar el teclado (no al hacer clic). */
:where(button, a, [role="button"], [tabindex]:not([tabindex="-1"])):focus-visible {
  outline: 2px solid var(--secondary); outline-offset: 2px;
}

/* --- Alto contraste --- */
:root[data-contrast="high"] {
  --text: #000; --text-muted: #1f2a3a; --text-faint: #2c3a4e;
  --border: #5b6b80; --row-border: #9aa7b8; --accent-text: #00306b;
  --bg: #ffffff; --surface: #ffffff; --subtle-bg: #e6eaf0;
}
:root[data-contrast="high"][data-theme="dark"] {
  --text: #fff; --text-muted: #dbe4f0; --text-faint: #c9d4e3;
  --border: #9fb0c8; --row-border: #5d6d85; --accent-text: #9cc8ff;
  --bg: #000; --surface: #0b1018; --subtle-bg: #1b2433;
}
:root[data-contrast="high"] a:not(.btn):not(.skip-link) { text-decoration: underline; }
:root[data-contrast="high"] .btn, :root[data-contrast="high"] input,
:root[data-contrast="high"] select, :root[data-contrast="high"] textarea,
:root[data-contrast="high"] .card { border-width: 2px; }
:root[data-contrast="high"] .nav-item { color: #fff; }
:root[data-contrast="high"] :where(button, a, input, select, textarea, [tabindex]:not([tabindex="-1"])):focus-visible {
  outline: 3px solid #ffbf00; outline-offset: 2px;
}
:root[data-contrast="high"] .modal-overlay { backdrop-filter: none; -webkit-backdrop-filter: none; background: rgba(0, 0, 0, .75); }

/* --- Botones grandes ---
   Con dedo (pointer: coarse) siempre un mínimo cómodo; con la opción
   "Botones grandes", más. Se agranda con RELLENO (no con alturas fijas):
   así los botones, casillas y filtros de una misma fila crecen parejo y no se
   desalinean ni se salen de su tarjeta. Los botones de solo ícono pasan a
   ser cuadrados más grandes. */
@media (pointer: coarse) {
  .btn:where(:not(.btn-icon, .btn-send, .btn-sm)) { min-height: 40px; }
  .nav-item, .global-search-btn, .notif-bell-btn { min-height: 40px; }
}
:root[data-touch="big"] .btn { padding: 13px 20px; }
:root[data-touch="big"] .btn-sm { padding: 10px 15px; }
:root[data-touch="big"] .btn-icon { width: 42px; height: 42px; padding: 0; }
:root[data-touch="big"] .btn-icon svg { width: 19px; height: 19px; }
:root[data-touch="big"] .btn .btn-ico { width: 18px; height: 18px; }
:root[data-touch="big"] .view-toggle-btn { padding: 12px 18px; }
:root[data-touch="big"] .nav-item { padding-top: 14px; padding-bottom: 14px; }
:root[data-touch="big"] .nav-group-toggle { padding-top: 14px; padding-bottom: 14px; }
:root[data-touch="big"] .modal-close { min-width: 44px; min-height: 44px; font-size: calc(26px * var(--fs, 1)); }
:root[data-touch="big"] .global-search-btn, :root[data-touch="big"] .notif-bell-btn { width: 44px; height: 44px; }
:root[data-touch="big"] .field input[type=text], :root[data-touch="big"] .field input[type=number],
:root[data-touch="big"] .field input[type=search], :root[data-touch="big"] .field input[type=email],
:root[data-touch="big"] .field input[type=password], :root[data-touch="big"] .field select { padding-top: 12px; padding-bottom: 12px; }
:root[data-touch="big"] input[type=checkbox], :root[data-touch="big"] input[type=radio] { width: 22px; height: 22px; }
:root[data-touch="big"] .pg-arrow, :root[data-touch="big"] .date-nav-btn { min-width: 42px; min-height: 42px; }

/* --- Menos animaciones --- */
:root[data-motion="reduce"] *, :root[data-motion="reduce"] *::before, :root[data-motion="reduce"] *::after {
  animation-duration: 1ms !important; animation-iteration-count: 1 !important;
  transition-duration: 1ms !important; scroll-behavior: auto !important;
}

/* --- Ventana de Accesibilidad --- */
.a11y-row { display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 12px 0; border-bottom: 1px solid var(--row-border); }
.a11y-row:last-child { border-bottom: none; }
.a11y-row-text strong { display: block; color: var(--text); }
.a11y-row-text span { color: var(--text-muted); font-size: calc(13px * var(--fs, 1)); }
.a11y-switch { width: 22px; height: 22px; flex-shrink: 0; accent-color: var(--main); }
.a11y-preview { margin-top: 6px; padding: 10px 12px; border-radius: 8px; background: var(--subtle-bg); color: var(--text); }

/* --- Paleta Ctrl+K --- */
.cmdk-overlay { align-items: flex-start; padding-top: min(12vh, 110px); }
.cmdk-card { width: min(620px, 100%); padding: 0; overflow: hidden; display: flex; flex-direction: column; max-height: min(70vh, 560px); }
.cmdk-input-wrap { display: flex; align-items: center; gap: 10px; padding: 12px 16px; border-bottom: 1px solid var(--border); }
.cmdk-input-wrap svg { width: 18px; height: 18px; color: var(--text-muted); flex-shrink: 0; }
.cmdk-input-wrap input { flex: 1; min-width: 0; border: none !important; box-shadow: none !important; background: transparent !important; padding: 6px 0 !important; font-size: calc(16px * var(--fs, 1)); }
.cmdk-list { flex: 1; min-width: 0; overflow-y: auto; padding: 6px; overscroll-behavior: contain; }
.cmdk-group { font-size: calc(11px * var(--fs, 1)); font-weight: 800; letter-spacing: .04em; text-transform: uppercase; color: var(--text-faint); padding: 10px 10px 4px; }
.cmdk-item {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  background: none; border: none; color: var(--text); padding: 9px 10px; border-radius: 8px;
  font: inherit; font-size: calc(14px * var(--fs, 1)); cursor: pointer;
}
.cmdk-item[aria-selected="true"] { background: var(--secondary-light); color: var(--accent-text); }
.cmdk-item-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cmdk-item-hint { color: var(--text-faint); font-size: calc(12px * var(--fs, 1)); flex-shrink: 0; }
.cmdk-empty { padding: 18px; text-align: center; color: var(--text-muted); }
.cmdk-foot { display: flex; gap: 14px; flex-wrap: wrap; padding: 8px 14px; border-top: 1px solid var(--border); color: var(--text-faint); font-size: calc(12px * var(--fs, 1)); }
kbd {
  display: inline-block; min-width: 1.6em; padding: 1px 6px; border-radius: 5px; text-align: center;
  border: 1px solid var(--border); border-bottom-width: 2px; background: var(--subtle-bg); color: var(--text);
  font-family: inherit; font-size: .85em; font-weight: 700; line-height: 1.5;
}
.shortcuts-table { width: 100%; border-collapse: collapse; }
.shortcuts-table td { padding: 8px 6px; border-bottom: 1px solid var(--row-border); vertical-align: top; color: var(--text); }
.shortcuts-table td:first-child { white-space: nowrap; width: 1%; }
.shortcuts-table h4 { margin: 14px 0 4px; }

/* --- Términos y privacidad --- */
.legal-overlay { z-index: 1200; }
.legal-card { display: flex; flex-direction: column; max-height: min(88vh, 820px); }
.legal-tabs { align-self: flex-start; margin-bottom: 10px; flex-wrap: wrap; }
.legal-body { flex: 1; min-height: 180px; overflow-y: auto; padding: 4px 12px 4px 2px; border-top: 1px solid var(--row-border); border-bottom: 1px solid var(--row-border); }
.legal-body h2 { font-size: calc(15px * var(--fs, 1)); color: var(--accent-text); margin: 18px 0 6px; }
.legal-body p, .legal-body li { font-size: calc(13.5px * var(--fs, 1)); color: var(--text); line-height: 1.55; }
.legal-body .muted { color: var(--text-muted); }
.legal-body a { color: var(--accent-text); }
.legal-check { display: flex; gap: 10px; align-items: flex-start; margin: 14px 0 4px; font-weight: 600; color: var(--text); cursor: pointer; }
.legal-check input { width: 20px; height: 20px; flex-shrink: 0; margin-top: 1px; accent-color: var(--main); }
.auth-legal-note { margin-top: 14px; font-size: calc(12px * var(--fs, 1)); color: var(--text-muted); text-align: center; line-height: 1.5; }
.auth-legal-note a { color: var(--accent-text); }

/* Letra grande en pantallas angostas: los encabezados y las barras de
   vistas (Kanban/Cuadrícula/Tabla/Calendario) bajan de renglón en vez de
   cortarse o salirse. */
@media (max-width: 860px) {
  :root[data-text] .page-head { flex-wrap: wrap; }
  :root[data-text] .page-title { overflow-wrap: anywhere; }
  :root[data-text] .view-toggle { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; flex-wrap: wrap; height: auto; }
  :root[data-text] .view-toggle-btn { white-space: normal; }
  /* Órdenes: el título no se mete debajo de los botones "Hoy" y "+". */
  .wo-page-head .page-title { padding-right: 150px; }
}

/* --- Casillas legibles en modo oscuro (2026-10-16) ---
   (el .btn simple sin variante se arregla en style.css, junto a .btn.) */
.btn.btn-primary[disabled] { opacity: .55; }

/* Casillas propias: legibles en claro y oscuro (la del navegador sale blanca). */
.a11y-switch, .legal-check input[type="checkbox"], .users-legal-check {
  -webkit-appearance: none; appearance: none; flex-shrink: 0;
  width: 22px; height: 22px; border: 2px solid var(--text-muted); border-radius: 6px;
  background: var(--input-bg, var(--surface)); cursor: pointer; display: inline-grid; place-content: center;
  transition: background .12s ease, border-color .12s ease;
}
.a11y-switch::after, .legal-check input[type="checkbox"]::after {
  content: ""; width: 12px; height: 7px; border-left: 3px solid #fff; border-bottom: 3px solid #fff;
  transform: rotate(-45deg) scale(0); margin-top: -3px; transition: transform .12s ease;
}
.a11y-switch:checked, .legal-check input[type="checkbox"]:checked { background: var(--main); border-color: var(--main); }
:root[data-theme="dark"] .a11y-switch:checked, :root[data-theme="dark"] .legal-check input[type="checkbox"]:checked { background: var(--secondary); border-color: var(--secondary); }
:root[data-theme="dark"] .a11y-switch:checked::after, :root[data-theme="dark"] .legal-check input[type="checkbox"]:checked::after { border-color: #062f5e; }
.a11y-switch:checked::after, .legal-check input[type="checkbox"]:checked::after { transform: rotate(-45deg) scale(1); }
.a11y-switch:focus-visible, .legal-check input[type="checkbox"]:focus-visible { outline: 3px solid var(--secondary); outline-offset: 2px; }

/* Destello del formulario al llegar con un atajo (Alt+C, Alt+P…). */
@keyframes shortcut-flash { 0% { box-shadow: 0 0 0 0 var(--secondary); } 30% { box-shadow: 0 0 0 5px var(--secondary); } 100% { box-shadow: 0 0 0 0 transparent; } }
.shortcut-flash { animation: shortcut-flash 1.3s ease-out; }

/* Si el sistema pide "Reducir transparencia" (macOS/iOS/Windows), el fondo
   de las ventanas va sólido y sin desenfoque, igual que en alto contraste. */
@media (prefers-reduced-transparency: reduce) {
  .modal-overlay { backdrop-filter: none; -webkit-backdrop-filter: none; background: rgba(0, 0, 0, .7); }
}

/* Vista previa del buscador (N04): columna a la derecha de la paleta y de la lupa. */
.cmdk-body, .search-with-preview { display: flex; min-height: 0; flex: 1; }
.cmdk-card:has(.cmdk-body.has-preview) { width: min(880px, 100%); max-width: none; }
.cmdk-card { max-width: none; }
.global-search-panel:has(.search-with-preview.has-preview) { width: 660px; }
.search-with-preview > .global-search-results { flex: 1; min-width: 0; }
.search-preview {
  flex: 0 0 300px; min-width: 0; padding: 14px 16px; border-left: 1px solid var(--border);
  background: var(--bg); overflow-y: auto; display: flex; flex-direction: column; gap: 10px;
  font-size: calc(12.5px * var(--fs, 1));
}
.search-preview[hidden] { display: none; }
.sp-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
.sp-title { font-size: calc(14px * var(--fs, 1)); color: var(--text); overflow-wrap: anywhere; }
.sp-badge { flex-shrink: 0; }
.sp-rows { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 5px 12px; margin: 0; }
.sp-rows dt { color: var(--text-muted); }
.sp-rows dd { margin: 0; color: var(--text); text-align: right; overflow-wrap: anywhere; font-variant-numeric: tabular-nums; }
.sp-note { padding: 8px 10px; border-radius: var(--radius-sm); background: var(--surface); border: 1px solid var(--border); color: var(--text); overflow-wrap: anywhere; }
.sp-note span { display: block; font-size: calc(10.5px * var(--fs, 1)); font-weight: 800; text-transform: uppercase; letter-spacing: .04em; color: var(--accent-text); margin-bottom: 3px; }
.sp-foot { margin-top: auto; color: var(--text-faint); font-size: calc(11.5px * var(--fs, 1)); }
@media (max-width: 760px) { .search-preview { display: none; } }

/* Mini retoques 2026-11-06 */
/* Las cifras y fechas de las tablas quedan alineadas en columna. */
table td { font-variant-numeric: tabular-nums; }
/* Historial: el detalle largo baja de renglón en vez de empujar la fecha fuera de la pantalla. */
td.cell-detail { white-space: normal; min-width: 200px; max-width: 420px; overflow-wrap: anywhere; }
td.cell-date { white-space: nowrap; }
/* La vista previa aparece suave, sin saltar. */
.search-preview:not([hidden]) { animation: sp-in .14s var(--ease-out); }
@keyframes sp-in { from { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .search-preview:not([hidden]) { animation: none; } }
