/* ============================================================
   AUTO TUNING SHOP CRM — Sistema de diseño
   Inspirado en los patrones de producto de los CRM SaaS modernos
   (sidebar clara, tarjetas con aire, tablas limpias, pipelines
   tipo tablero) con marca propia: grafito de taller + acento cobre.
   Tipografía: Oswald (títulos/cifras destacadas, estilo rotulado)
               Inter (cuerpo, legibilidad en tablas densas)
               JetBrains Mono (folios, montos, placas)
   Firma visual: "línea de corte" — regla con marcas tipo cinta
   métrica, referencia directa al oficio de medir/cortar vinil.
   ============================================================ */

@import url('https://fonts.googleapis.com/css2?family=Oswald:wght@500;600;700&family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@500;600&display=swap');

:root {
  /* Color — neutros fríos, marca cálida (cobre) como único acento */
  --ats-ink: #1A1C1F;
  --ats-ink-soft: #5B6069;
  --ats-ink-faint: #8B9099;
  --ats-graphite-900: #1E2023;
  --ats-graphite-800: #26292E;
  --ats-graphite-700: #34383F;
  --ats-surface: #F5F6F8;
  --ats-card: #FFFFFF;
  --ats-glass: rgba(255, 255, 255, 0.82);
  --ats-border: #E3E5EA;
  --ats-border-soft: #EEEFF2;
  --ats-copper: #2E333D;
  --ats-copper-dark: #20242C;
  --ats-copper-tint: #E4E6EA;
  --ats-copper-tint-soft: #F2F3F5;
  --ats-green: #256B47;
  --ats-green-tint: #DFF0E6;
  --ats-amber: #8F6015;
  --ats-amber-tint: #F6E9D2;
  --ats-red: #B23A3A;
  --ats-red-tint: #F5DEDE;
  --ats-blue: #33618E;
  --ats-blue-tint: #DCE7F0;
  --ats-teal: #1E6E64;
  --ats-teal-dark: #17554D;
  --ats-teal-tint: #DCEEEA;
  --ats-violet: #5B4B8A;
  --ats-violet-tint: #E7E2F2;
  --ats-green-ink: #1E5138;
  --ats-red-ink: #7A2626;
  --ats-blue-ink: #1F3E5C;
  --ats-amber-ink: #6B4A10;

  /* Tipografía */
  --font-display: 'Oswald', 'Arial Narrow', sans-serif;
  --font-body: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-mono: 'JetBrains Mono', 'SFMono-Regular', Consolas, monospace;

  /* Layout */
  --sidebar-width: 244px;
  --topbar-height: 64px;
  --test-banner-height: 0px;
  /* Offset compartido para cualquier barra sticky que deba pegarse justo
   * debajo del topbar (que ya de por sí está corrido hacia abajo por la
   * franja de "versión de prueba") — evita que cada barra sticky nueva
   * repita el mismo calc() y se le olvide sumar test-banner-height, como
   * ya le pasó a .ats-settings-nav (bug real, corregido 2026-09-08: seguía
   * con top: var(--topbar-height) de antes de que existiera la franja, así
   * que la barra de navegación de Configuración quedaba tapada 38px por el
   * topbar en vez de pegarse justo debajo). */
  --content-top-offset: calc(var(--test-banner-height) + var(--topbar-height));
  --radius: 10px;
  --radius-sm: 7px;
  --radius-lg: 14px;
  --shadow-card: 0 1px 2px rgba(16,24,32,0.04), 0 1px 4px rgba(16,24,32,0.05);
  --shadow-hover: 0 6px 20px rgba(16,24,32,0.10);
  --shadow-pop: 0 16px 40px rgba(16,24,32,0.18);
}

/* Modo oscuro real (Etapa 5 del plan VPS, 2026-09-06) — preferencia guardada
   por usuario en users.theme_preference (ver toggle_theme.php), no solo en
   este navegador. Redefine únicamente los tokens de color de arriba — cada
   componente del sistema ya lee color exclusivamente a través de var(--ats-*),
   así que ningún otro selector necesita tocarse para que el modo oscuro
   funcione en toda la app. Las dos excepciones deliberadas que NO cambian
   aquí: el fondo grafito del login (.ats-auth-screen) y del nav inferior
   móvil (.ats-bottom-nav) — ya son oscuros por diseño en ambos temas, son
   parte de la identidad de marca, no del contenido que el toggle controla. */
:root[data-theme="dark"] {
  --ats-ink: #EDEAE5;
  --ats-ink-soft: #B5AFA6;
  --ats-ink-faint: #837C72;
  --ats-surface: #16140F;
  --ats-card: #201D19;
  --ats-glass: rgba(32, 29, 25, 0.82);
  --ats-border: #37322B;
  --ats-border-soft: #2A2622;
  --ats-copper: #8A93A6;
  --ats-copper-dark: #6E7689;
  --ats-copper-tint: #2A2E36;
  --ats-copper-tint-soft: #23262C;
  --ats-green: #7FCBA0;
  --ats-green-tint: #1E3A2C;
  --ats-amber: #E0B563;
  --ats-amber-tint: #3D2F14;
  --ats-red: #E08585;
  --ats-red-tint: #3A1F1F;
  --ats-blue: #7EB3E8;
  --ats-blue-tint: #1E2E3F;
  --ats-teal: #5FBFB2;
  --ats-teal-dark: #7FD1C6;
  --ats-teal-tint: #16332F;
  --ats-violet: #A695D6;
  --ats-violet-tint: #2A2440;
  --ats-green-ink: #BFE8D3;
  --ats-red-ink: #F2C6C6;
  --ats-blue-ink: #C9E0F5;
  --ats-amber-ink: #F2DBA3;
  --shadow-card: 0 1px 2px rgba(0,0,0,0.3), 0 1px 4px rgba(0,0,0,0.25);
  --shadow-hover: 0 6px 20px rgba(0,0,0,0.4);
  --shadow-pop: 0 16px 40px rgba(0,0,0,0.55);
  color-scheme: dark;
}

* { box-sizing: border-box; }

html {
  /* Flujo de la orden de trabajo, rediseño de navegación (2026-09-06) — un
     salto instantáneo de #anchor a #anchor se sentía brusco justo en el
     escenario que más importa aquí (después de cada acción, la página
     redirige al siguiente paso); un desplazamiento suave se siente cuidado
     en vez de un "salto" — mejora global, no solo de esta página. */
  scroll-behavior: smooth;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

html, body {
  margin: 0;
  padding: 0;
  background: var(--ats-surface);
  color: var(--ats-ink);
  font-family: var(--font-body);
  /* 15px → 16px (rediseño de usabilidad 2026-10-21): la app se usa de pie, en el
     taller, muchas veces desde el celular — un punto más de letra en toda la app. */
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

/* Transición de entrada del armazón completo (rediseño visual, Fase 2) — el
   objetivo puntual es que abrir la app instalada (PWA) no se sienta como un
   "parpadeo" entre la pantalla de carga nativa del sistema operativo (armada
   sola por el navegador a partir de background_color/theme_color/ícono de
   manifest.json, no hay nada que tocar ahí) y el contenido real ya cargado
   — un fundido breve de toda la app, no solo del contenido principal
   (.ats-main ya tenía su propia entrada, ver más abajo), cierra ese salto. */
@keyframes ats-app-fade-in { from { opacity: 0; } to { opacity: 1; } }
.ats-app { animation: ats-app-fade-in 0.22s ease both; }
@media (prefers-reduced-motion: reduce) {
  .ats-app { animation: none; }
}

a { color: inherit; text-decoration: none; }
button { font-family: inherit; }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 600;
  margin: 0 0 4px;
  color: var(--ats-ink);
}
h1 { font-size: 1.5rem; letter-spacing: 0.005em; }
h2 { font-size: 1.15rem; }
h3 {
  font-family: var(--font-body);
  font-size: 0.92rem;
  font-weight: 700;
  text-transform: none;
  letter-spacing: normal;
  color: var(--ats-ink);
}

.ats-muted { color: var(--ats-ink-soft); }
.ats-mono { font-family: var(--font-mono); }

/* --- Firma visual: regla de corte (tick ruler), más discreta --- */
.cut-rule {
  position: relative;
  height: 7px;
  margin: 4px 0 16px;
  background-image: repeating-linear-gradient(
    to right,
    var(--ats-border) 0, var(--ats-border) 1px,
    transparent 1px, transparent 12px
  );
  background-position: bottom left;
  background-size: 100% 6px;
  background-repeat: repeat-x;
  border-bottom: 1.5px solid var(--ats-copper);
  opacity: 0.85;
}
.cut-rule.short { width: 56px; }

/* --- Layout general --- */
.ats-app { display: flex; min-height: 100vh; }

/* --- Sidebar clara --- */
.ats-sidebar {
  width: var(--sidebar-width);
  background: var(--ats-card);
  color: var(--ats-ink);
  border-right: 1px solid var(--ats-border);
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  position: fixed;
  top: var(--test-banner-height); bottom: 0; left: 0;
  z-index: 40;
  transition: transform 0.2s ease;
}

.ats-sidebar-brand {
  display: block;
  padding: 18px 20px 16px;
  border-bottom: 1px solid var(--ats-border);
  text-decoration: none;
}
.ats-sidebar-logo {
  max-width: 100%;
  height: auto;
  display: block;
  margin-bottom: 4px;
}
.ats-sidebar-brand .name {
  font-family: var(--font-display);
  font-size: 1.02rem;
  letter-spacing: 0.01em;
  color: var(--ats-ink);
}
.ats-sidebar-brand .name span { color: var(--ats-copper); }
.ats-sidebar-brand .tag {
  font-size: 0.72rem;
  color: var(--ats-ink-faint);
  letter-spacing: 0.03em;
}

.ats-nav { flex: 1; overflow-y: auto; padding: 10px 0 20px; }
.ats-nav-group { margin-top: 14px; }
.ats-nav-group-label {
  font-size: 0.68rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ats-ink-faint);
  padding: 4px 20px;
}
.ats-nav a {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 18px;
  margin: 1px 8px;
  border-radius: var(--radius-sm);
  font-size: 0.88rem;
  font-weight: 500;
  color: var(--ats-ink-soft);
  border-left: 3px solid transparent;
}
.ats-nav-icon { display: inline-flex; flex-shrink: 0; opacity: 0.75; }
.ats-nav a:hover { background: var(--ats-surface); color: var(--ats-ink); }
.ats-nav a:hover .ats-nav-icon, .ats-nav a.active .ats-nav-icon { opacity: 1; }
.ats-nav a.active {
  background: var(--ats-copper-tint-soft);
  color: var(--ats-copper-dark);
  font-weight: 600;
  border-left-color: var(--ats-copper);
}

.ats-sidebar-footer {
  padding: 14px 20px;
  border-top: 1px solid var(--ats-border);
  font-size: 0.8rem;
  color: var(--ats-ink-faint);
}

/* --- Contenido --- */
.ats-content {
  margin-left: var(--sidebar-width);
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.ats-topbar {
  height: var(--topbar-height);
  background: var(--ats-card);
  border-bottom: 1px solid var(--ats-border);
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 0 24px;
  position: sticky;
  top: var(--test-banner-height);
  z-index: 30;
}

/* Aviso "VERSIÓN DE PRUEBA" — solo existe en esta copia (ats-crm-vps), la de
   práctica/desarrollo, nunca en la copia real. Pedido explícito del usuario,
   2026-09-07: confundía esta copia con la real que usa en local en vivo, y
   pidió que fuera más llamativa en un segundo pedido el mismo día. Rayas
   diagonales tipo "cinta de precaución" en TODO el ancho (no solo a los
   lados) — es la señal visual más reconocible de "cuidado/no es lo real"
   que existe, y un color (ámbar/negro) que no aparece en ningún otro lugar
   de la app (el acento normal es cobre). El texto va sobre una placa oscura
   con borde ámbar y un resplandor pulsante suave — separa el texto de las
   rayas para que sea legible sin perder el efecto de "cinta de advertencia".
   Pegajosa arriba de todo (z-index por encima del topbar y de cualquier
   menú desplegable) para que sea imposible de perder sin importar cuánto se
   haya bajado la página.

   Bug real corregido junto con este ajuste: el service worker (sw.js) sirve
   assets/css/app.css con "stale-while-revalidate" — la primera carga
   después de cualquier cambio a este archivo sigue mostrando la versión
   vieja en caché (se actualiza apenas en segundo plano, para la SIGUIENTE
   carga). Por eso el ajuste anterior del sidebar no se vio de inmediato y
   la franja tapó el logo. CACHE_NAME se subió a v3 para forzar la
   invalidación — cualquier cambio futuro a app.css/app.js necesita el mismo
   bump o el navegador seguirá sirviendo la versión vieja indefinidamente. */
.ats-test-banner {
  position: sticky;
  top: 0;
  z-index: 50;
  height: var(--test-banner-height);
  display: flex;
  align-items: center;
  justify-content: center;
  background: repeating-linear-gradient(135deg, #F5B942, #F5B942 18px, #1A1400 18px, #1A1400 36px);
  box-shadow: 0 2px 12px rgba(245, 185, 66, 0.55);
}
.ats-test-banner .label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: #1A1400;
  color: #F5B942;
  padding: 6px 18px;
  border-radius: 999px;
  border: 1.5px solid #F5B942;
  font-family: var(--font-display);
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  white-space: nowrap;
  animation: ats-test-banner-glow 2.2s ease-in-out infinite;
}
@keyframes ats-test-banner-glow {
  0%, 100% { box-shadow: 0 0 0 0 rgba(245, 185, 66, 0.55); }
  50% { box-shadow: 0 0 0 5px rgba(245, 185, 66, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .ats-test-banner .label { animation: none; }
}

.ats-search {
  flex: 1;
  max-width: 420px;
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--ats-surface);
  border: 1px solid var(--ats-border);
  border-radius: var(--radius-sm);
  padding: 8px 12px;
  color: var(--ats-ink-soft);
}
.ats-search:focus-within { border-color: var(--ats-copper); }
.ats-search input {
  border: none;
  background: transparent;
  outline: none;
  font-size: 0.9rem;
  width: 100%;
  color: var(--ats-ink);
}

.ats-menu-toggle {
  display: none;
  background: none;
  border: none;
  font-size: 1.3rem;
  cursor: pointer;
  color: var(--ats-ink);
}

.ats-user-chip {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 0.85rem;
}
.ats-user-chip .avatar {
  width: 32px; height: 32px;
  border-radius: 50%;
  background: var(--ats-copper);
  color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.85rem;
}

.ats-main { padding: 26px 30px 60px; }

/* Movimiento con propósito (rediseño visual, Fase 2) — el contenido entra con
   un fundido/deslizamiento breve en vez de aparecer de golpe. Respeta
   prefers-reduced-motion (abajo) para quien lo tenga activado a propósito. */
@keyframes ats-fade-in-up {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}
.ats-main > * { animation: ats-fade-in-up 0.32s ease both; }
.ats-main > *:nth-child(2) { animation-delay: 0.03s; }
.ats-main > *:nth-child(3) { animation-delay: 0.06s; }
.ats-main > *:nth-child(4) { animation-delay: 0.09s; }
.ats-main > *:nth-child(n+5) { animation-delay: 0.11s; }
/* Bug real, 2026-09-08: un elemento con `animation` (aunque ya haya
   terminado — animation-fill-mode:both deja la propiedad animation-name
   activa para siempre, no solo mientras se reproduce) queda promovido a su
   propio contexto de apilamiento. Eso aislaba el z-index:40 del menú
   "Documentos y enlaces" (adentro de .ats-page-header, el primer hijo de
   .ats-main) — no podía competir contra el contenido de CUALQUIER sección
   posterior de la página (ej. la rejilla de Precio/Anticipo/Saldo), sin
   importar el número, porque el z-index solo compite dentro del mismo
   contexto. Se quita la animación solo del encabezado (donde vive el único
   menú desplegable que necesita salirse de su propia sección) — el resto de
   secciones se quedan con su entrada normal. */
.ats-main > .ats-page-header { animation: none; }
@media (prefers-reduced-motion: reduce) {
  .ats-main > * { animation: none; }
}

.ats-section-label {
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ats-copper);
  margin-bottom: 6px;
}
.ats-breadcrumbs {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--ats-copper);
  margin-bottom: 10px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 5px;
}
.ats-breadcrumbs a { color: var(--ats-copper); text-decoration: none; }
.ats-breadcrumbs a:hover { text-decoration: underline; }
.ats-breadcrumbs .sep { color: var(--ats-ink-faint); font-weight: 400; }
.ats-breadcrumbs .current { color: var(--ats-ink-soft); font-weight: 400; }

.ats-page-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 4px;
}

/* Menú "Documentos" del encabezado de orden — auditoría de saturación de
   pantalla, 2026-09-07: el encabezado llegó a tener hasta 6 botones, 3 de
   ellos con el mismo texto "Enviar por WhatsApp" (seguimiento, comprobante de
   cita, comprobante de liquidación) — indistinguibles entre sí hasta hacer
   clic. Se agrupan en un solo menú desplegable con opciones ya diferenciadas
   por su propio texto. Es un <details> nativo (mismo patrón que el resto del
   proyecto usa para colapsables), no un componente JS nuevo — solo se le
   agrega el cierre al hacer clic afuera (assets/js/app.js). */
.ats-dropdown { position: relative; display: inline-block; }
.ats-dropdown > summary {
  list-style: none;
  cursor: pointer;
}
.ats-dropdown > summary::-webkit-details-marker { display: none; }
.ats-dropdown > summary::after { content: ' ▾'; }
.ats-dropdown[open] > summary::after { content: ' ▴'; }
.ats-dropdown-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  min-width: 260px;
  /* Profundidad sutil (glassmorphism), rediseño visual 2026-10-05 — fondo
     semitransparente + blur en vez del panel plano de siempre, mismo criterio
     que el lightbox más abajo. --ats-glass ya es opaco de sobra si el
     navegador no soporta backdrop-filter (Firefox < 103, navegadores viejos),
     así que esto degrada con gracia sin necesitar un @supports aparte. */
  background: var(--ats-glass);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid var(--ats-border);
  border-radius: var(--radius-sm);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.16);
  padding: 6px;
  z-index: 40;
}
.ats-dropdown-menu a {
  display: block;
  padding: 9px 12px;
  border-radius: 6px;
  color: var(--ats-ink);
  text-decoration: none;
  font-size: 0.85rem;
  white-space: nowrap;
}
.ats-dropdown-menu a:hover { background: var(--ats-surface); }
.ats-dropdown-menu .ats-dropdown-divider { height: 1px; background: var(--ats-border); margin: 6px 4px; }

/* Campanita de notificaciones como desplegable, no navegación de página
   completa (2026-09-26, real-usage: "solo abre una ventana"). Mismo
   componente .ats-dropdown de arriba, con su propio ancho/alto y sin la
   flechita ▾ (no tiene sentido en un icono solo). */
.ats-notif-dropdown > summary::after { content: none; }
.ats-notif-panel { width: 380px; max-width: calc(100vw - 32px); padding: 0; overflow: hidden; }
.ats-notif-panel-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 14px; border-bottom: 1px solid var(--ats-border);
}
.ats-notif-panel-header strong { font-size: 0.92rem; }
.ats-notif-mark-all {
  background: none; border: none; color: var(--ats-copper); font-size: 0.74rem;
  font-weight: 600; cursor: pointer; padding: 4px 7px; border-radius: 6px;
  transition: background 120ms ease;
}
.ats-notif-mark-all:hover { background: var(--ats-copper-tint-soft); }
.ats-notif-list { max-height: 380px; overflow-y: auto; }
/* Selector con más especificidad que ".ats-dropdown-menu a" (arriba) a
   propósito — bug real, 2026-09-26: sin esto, "white-space: nowrap" del
   dropdown genérico le ganaba a "white-space: normal" de aquí y el mensaje
   se cortaba a la mitad sin ningún punto suspensivo, en vez de ajustarse. */
.ats-notif-panel .ats-notif-item {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 11px 14px; border-bottom: 1px solid var(--ats-border);
  white-space: normal; color: var(--ats-ink); text-decoration: none;
  transition: background 120ms ease;
}
.ats-notif-panel .ats-notif-item:hover { background: var(--ats-surface); }
.ats-notif-item:last-child { border-bottom: none; }
.ats-notif-item .ats-notif-dot {
  flex-shrink: 0; width: 8px; height: 8px; border-radius: 50%;
  background: var(--ats-copper); margin-top: 5px; visibility: hidden;
}
.ats-notif-item.unread .ats-notif-dot { visibility: visible; }
.ats-notif-item.unread { font-weight: 600; }
.ats-notif-item .ats-notif-body { flex: 1; min-width: 0; }
.ats-notif-item .ats-notif-message {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; font-size: 0.83rem; line-height: 1.35;
}
.ats-notif-item .ats-notif-time { display: block; margin-top: 3px; font-size: 0.72rem; font-weight: 400; color: var(--ats-ink-faint); }
.ats-notif-viewall {
  display: block; text-align: center; padding: 10px 12px; font-size: 0.82rem;
  font-weight: 600; border-top: 1px solid var(--ats-border); color: var(--ats-copper); text-decoration: none;
  transition: background 120ms ease;
}
.ats-notif-viewall:hover { background: var(--ats-surface); }

/* --- Navegación interna de página larga (ej. Configuración) ---
   Auditoría visual, 2026-08-31: Configuración tenía 7+ secciones apiladas en
   una sola columna de miles de px, sin ninguna forma de saltar directo a una —
   solo scroll a ciegas. Pegajosa justo debajo del topbar para que siga siendo
   útil aunque ya se haya bajado varias pantallas. Cualquier tarjeta que quiera
   ser un destino de esta nav necesita scroll-margin-top para no quedar tapada
   por el topbar + esta barra al saltar. */
.ats-settings-nav {
  position: sticky;
  top: var(--content-top-offset);
  z-index: 20;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  background: var(--ats-surface);
  padding: 10px 0;
  margin-bottom: 4px;
}
.ats-settings-nav a {
  font-size: 0.78rem;
  font-weight: 600;
  padding: 6px 12px;
  border-radius: 100px;
  background: var(--ats-card);
  border: 1px solid var(--ats-border);
  color: var(--ats-ink-soft);
  text-decoration: none;
  white-space: nowrap;
  transition: border-color 0.12s ease, color 0.12s ease, background 0.12s ease;
}
.ats-settings-nav a:hover { border-color: var(--ats-copper); color: var(--ats-copper-dark); background: var(--ats-copper-tint-soft); }
.ats-settings-nav ~ .ats-card[id] { scroll-margin-top: calc(var(--content-top-offset) + 56px); }

/* Pestañas de periodo rápido (Día/Semana/Mes/Año — gráfica de Ventas del Dashboard) */
.ats-period-tabs { display: flex; gap: 4px; flex-wrap: wrap; }
.ats-period-tabs button {
  font-size: 0.74rem;
  font-weight: 600;
  padding: 5px 11px;
  border-radius: 100px;
  background: var(--ats-card);
  border: 1px solid var(--ats-border);
  color: var(--ats-ink-soft);
  cursor: pointer;
  transition: border-color 0.12s ease, color 0.12s ease, background 0.12s ease;
}
.ats-period-tabs button:hover:not(.active) { border-color: var(--ats-copper); color: var(--ats-copper-dark); }
.ats-period-tabs button.active { background: var(--ats-copper); border-color: var(--ats-copper); color: #fff; }

/* Banner "Siguiente paso" (rediseño del flujo de la orden, 2026-09-06) — ver
   la función nextStepFor() en modules/work_order_view.php. Resuelve el
   problema real encontrado: casi ninguna transición de la orden redirigía a
   un ancla, así que después de cada acción la página aterrizaba hasta arriba
   y había que buscar a mano qué seguía. Este banner siempre dice qué sigue,
   sin importar dónde aterrice la página — combinado con que ahora cada
   acción SÍ redirige al ancla correcta, cubre tanto "acabo de llegar a esta
   orden desde otro lado" como "acabo de completar un paso". */
.ats-next-step {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 16px 20px;
  border-radius: var(--radius);
  margin-bottom: 18px;
  border: 1px solid;
}
.ats-next-step .icon { font-size: 1.3rem; flex-shrink: 0; }
.ats-next-step .text { flex: 1; }
.ats-next-step .text .label { font-size: 0.7rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; opacity: 0.75; }
.ats-next-step .text .action { font-size: 1rem; font-weight: 600; margin-top: 2px; }
.ats-next-step.action { background: var(--ats-copper-tint-soft); border-color: var(--ats-copper-tint); color: var(--ats-copper-dark); }
/* Micro-retroalimentación con intención, rediseño visual 2026-10-05 — el
   ícono del único banner que de verdad pide una acción (nunca el de "waiting"
   ni "done", que no la piden) respira suavemente para que el ojo lo encuentre
   primero en la página, sin ser tan notorio que distraiga del texto. Se
   desactiva solo con la regla global de prefers-reduced-motion ya existente
   más abajo en este archivo — no necesita su propia excepción. */
.ats-next-step.action .icon { animation: ats-next-step-pulse 2.2s ease-in-out infinite; }
@keyframes ats-next-step-pulse {
  0%, 100% { transform: scale(1); opacity: 1; }
  50% { transform: scale(1.22); opacity: 0.65; }
}
.ats-next-step.waiting { background: var(--ats-border-soft); border-color: var(--ats-border); color: var(--ats-ink-soft); }
.ats-next-step.done { background: var(--ats-green-tint); border-color: var(--ats-green-tint); color: var(--ats-green-ink, var(--ats-green)); }
/* Rediseño 2026-09-08: reemplaza al riel horizontal sticky (quitado, ver
   nextStepFor() en work_order_view.php) como el único elemento pegado
   arriba de la orden mientras se hace scroll — ya trae su propio fondo
   opaco por severidad (arriba), así que no necesita uno extra para no
   transparentarse sobre el contenido. */
.ats-next-step-sticky { position: sticky; top: var(--content-top-offset); z-index: 15; }

/* Estado vacío con carácter (rediseño visual, Fase 2) — ver emptyStateHtml() en includes/functions.php */
.ats-empty-state {
  text-align: center;
  padding: 36px 20px;
  color: var(--ats-ink-faint);
}
.ats-empty-state svg { color: var(--ats-border); margin-bottom: 12px; }
.ats-empty-state p { margin: 0; font-size: 0.9rem; color: var(--ats-ink-soft); }

/* --- Tarjetas --- */
.ats-card {
  background: var(--ats-card);
  border: 1px solid var(--ats-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  padding: 22px;
  margin-bottom: 18px;
  transition: box-shadow 0.18s ease;
}

/* Línea de tiempo vertical de la orden de trabajo — rediseño 2026-09-08,
   real-usage report: "todos los botones los siento complejos... lo quiero
   todo más visual, un orden cronológico" — investigado contra Ant/Material
   Design steppers, rastreadores de envío y el "accordion checkout" de
   Baymard: el patrón real es UNA sola línea continua con el contenido de
   cada paso anidado junto a su punto, nunca un riel resumen + tarjetas
   sueltas por separado (que es justo lo que tenía esta página antes).
   Implementado 100% en CSS (::before + contador nativo) envolviendo la
   secuencia de tarjetas ya existente en work_order_view.php SIN mover ni
   modificar ninguna — cada tarjeta ya trae su propia clase .ats-card-done
   (o no) calculada por su propia lógica de negocio, así que el punto de
   cada una nunca puede quedar desincronizado del estado real de esa
   tarjeta (no hay una segunda fuente de verdad que mantener al día, a
   diferencia del riel horizontal que sí la necesitaba). Una tarjeta que
   solo existe mientras aplica y luego desaparece del todo (ej. "Iniciar
   trabajo") simplemente dejará de tener punto/línea en cuanto deje de
   renderizarse — la línea de cada tarjeta solo llega hasta su propio final
   (no hay una línea global de posición fija), así que esto nunca deja un
   hueco visual cuando una tarjeta va y viene. */
.ats-order-timeline {
  position: relative;
  counter-reset: ats-timeline;
}
.ats-order-timeline::before {
  content: '';
  position: absolute;
  left: 13px;
  top: 6px;
  bottom: 6px;
  width: 2px;
  background: var(--ats-border);
  z-index: 1;
}
/* #finanzas queda técnicamente adentro del contenedor por cómo anidan las
   condiciones de rol en work_order_view.php (ver el comentario ahí), pero
   no es un paso cronológico — se excluye del punto/línea a propósito. */
.ats-order-timeline > .ats-card:not(#finanzas) {
  position: relative;
  margin-left: 38px;
}
.ats-order-timeline > .ats-card:not(#finanzas)::before {
  counter-increment: ats-timeline;
  content: counter(ats-timeline);
  position: absolute;
  left: -38px;
  top: 20px;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-size: 0.76rem;
  font-weight: 700;
  background: var(--ats-card);
  border: 2px solid var(--ats-copper);
  color: var(--ats-copper-dark);
  z-index: 2;
}
.ats-order-timeline > .ats-card.ats-card-done::before {
  content: '✓';
  background: var(--ats-green-tint);
  border-color: var(--ats-green);
  color: var(--ats-green);
}

/* Spinner del botón "Procesando..." (rediseño visual, Fase 2) — se inyecta
   por JS (assets/js/app.js) junto al cambio de texto ya existente, nunca
   reemplaza esa lógica (el bug real documentado ahí sobre deshabilitar de
   forma síncrona sigue aplicando exactamente igual). */
@keyframes ats-spin { to { transform: rotate(360deg); } }
.ats-btn-spinner {
  display: inline-block;
  width: 13px; height: 13px;
  border: 2px solid rgba(255,255,255,0.4);
  border-top-color: #fff;
  border-radius: 50%;
  animation: ats-spin 0.6s linear infinite;
  margin-right: 7px;
  vertical-align: -2px;
}
.btn-secondary .ats-btn-spinner { border-color: var(--ats-border); border-top-color: var(--ats-ink-soft); }
@media (prefers-reduced-motion: reduce) {
  .ats-btn-spinner { animation-duration: 1.4s; }
}

/* Atenuado breve en una grafica de Chart.js mientras cambia de pestana de
   periodo (Dia/Semana/Mes/Ano) -- 2026-09-26, real-usage: sin esto no habia
   ninguna senal de que el clic registro en una conexion lenta. */
.ats-chart-loading { opacity: 0.35; transition: opacity 150ms ease-in-out; }

/* Esqueleto de carga ("skeleton"), rediseño visual 2026-10-05 — reemplaza el
   simple atenuado de opacidad que initLiveSearch() (app.js) usaba mientras
   esperaba la respuesta; a diferencia de la gráfica de arriba (que solo se
   actualiza, su forma ya se conoce), una búsqueda en tiempo real no sabe de
   antemano cuántos resultados va a traer, así que una silueta de carga
   comunica mejor "está buscando" que un simple parpadeo. Genérico a
   propósito (initLiveSearch() es compartida por cualquier futuro consumidor
   de data-live-search, no solo Clientes). */
.ats-skeleton-line {
  height: 14px;
  border-radius: 4px;
  margin: 10px 0;
  background: linear-gradient(90deg, var(--ats-border-soft) 25%, var(--ats-border) 37%, var(--ats-border-soft) 63%);
  background-size: 400% 100%;
  animation: ats-skeleton-shimmer 1.4s ease-in-out infinite;
}
.ats-skeleton-line:nth-child(2) { width: 85%; }
.ats-skeleton-line:nth-child(3) { width: 70%; }
@keyframes ats-skeleton-shimmer {
  0% { background-position: 100% 50%; }
  100% { background-position: 0 50%; }
}
@media (prefers-reduced-motion: reduce) {
  .ats-skeleton-line { animation-duration: 3s; }
}

/* Confirmacion inline al copiar un link (reemplaza un alert() bloqueante) --
   2026-09-26. */
.ats-copied { color: var(--ats-green-ink, #1E5138); font-weight: 600; }

.ats-grid { display: grid; gap: 16px; }
.ats-grid.cols-2 { grid-template-columns: repeat(2, 1fr); }
.ats-grid.cols-3 { grid-template-columns: repeat(3, 1fr); }
.ats-grid.cols-4 { grid-template-columns: repeat(4, 1fr); }

/* ============ Calendario: vista de semana (modules/calendar.php) ============
 * Rediseño 2026-09-16, pedido explícito del usuario ("es de las partes más
 * importantes del CRM, invertirle tiempo bien hecho y visual") tras DOS
 * intentos fallidos en el mismo día:
 *   1) Bug real original: encabezados de día y tarjetas vivían en dos <div
 *      class="ats-grid"> separadas con gaps distintos (6px vs 16px por
 *      default) — el desfase de ancho de columna se acumulaba de lunes a
 *      domingo. Solucionado uniéndolas en una sola cuadrícula (abajo).
 *   2) Bug real de mi propio primer arreglo: para que esa cuadrícula de 7
 *      columnas cupiera en celular, le puse min-width:max-content — eso hizo
 *      que cada columna se expandiera al contenido MÁS ancho posible (texto
 *      con white-space:nowrap dentro de las tarjetas), terminando en ~320px
 *      por columna en una pantalla de 375px — prácticamente solo se alcanzaba
 *      a ver un día, y con las tarjetas apiladas verticalmente adentro se
 *      sentía como "una lista", no como una semana. Confirmado con captura
 *      real + inspección de getComputedStyle(), no solo supuesto.
 *
 * La cuadrícula de 7 columnas lado a lado es un patrón real y correcto para
 * ESCRITORIO (Google Calendar/Outlook la usan igual) — el error de ambos
 * intentos fue tratar de forzar ese mismo patrón en una pantalla angosta.
 * Los calendarios móviles reales (Google Calendar, Apple Calendar) no hacen
 * eso: usan una tira compacta de días tocable + la agenda completa de un
 * solo día seleccionado, a todo el ancho. Esta es esa misma separación:
 * ambas vistas viven en el HTML (renderizadas por PHP), una sola se muestra
 * según el ancho de pantalla vía CSS puro — nunca dependen de JS para
 * decidir cuál se ve, JS solo hace interactiva la tira de días en móvil. */
.ats-cal-week-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(110px, 1fr));
  gap: 6px 8px;
  min-width: 100%;
}
.ats-cal-mobile-agenda { display: none; }

@media (max-width: 900px) {
  /* Mismo punto de quiebre que el resto de la app (colapso de sidebar,
   * barra inferior) — un calendario a medio camino entre estilos confunde
   * más que ayudar. */
  .ats-cal-week-desktop { display: none; }
  .ats-cal-mobile-agenda { display: block; }
}

/* Tira de 7 días tocables — compacta, siempre completa (nunca hay que hacer
 * scroll horizontal para ver toda la semana de un vistazo, a diferencia de
 * los dos intentos anteriores). */
.ats-cal-day-strip {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
  margin-bottom: 14px;
}
.ats-cal-day-pill {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 8px 2px 7px;
  border-radius: var(--radius);
  border: 1px solid var(--ats-border);
  background: var(--ats-card);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.ats-cal-day-pill .dow { font-size: 0.66rem; font-weight: 600; letter-spacing: 0.02em; color: var(--ats-ink-soft); text-transform: uppercase; }
.ats-cal-day-pill .dnum { font-family: var(--font-display); font-size: 1.05rem; line-height: 1.1; color: var(--ats-ink); }
.ats-cal-day-pill .dot { width: 5px; height: 5px; border-radius: 50%; background: var(--ats-copper); opacity: 0; margin-top: 1px; }
.ats-cal-day-pill.has-jobs .dot { opacity: 1; }
.ats-cal-day-pill.is-today .dnum { color: var(--ats-copper); }
.ats-cal-day-pill.is-selected { background: var(--ats-copper); border-color: var(--ats-copper); }
.ats-cal-day-pill.is-selected .dow,
.ats-cal-day-pill.is-selected .dnum { color: #fff; }
.ats-cal-day-pill.is-selected .dot { background: #fff; }

.ats-cal-agenda-day { display: none; }
.ats-cal-agenda-day.is-active { display: block; }
.ats-cal-agenda-empty { padding: 28px 12px; text-align: center; color: var(--ats-ink-soft); font-size: 0.86rem; }
.ats-cal-agenda-card {
  display: block;
  padding: 12px 14px;
  margin-bottom: 8px;
  border-radius: var(--radius);
  background: var(--ats-card);
  border: 1px solid var(--ats-border);
  border-left: 3px solid var(--ats-copper);
}
.ats-cal-agenda-card .row1 { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.ats-cal-agenda-card .service { font-weight: 600; font-size: 0.94rem; }
.ats-cal-agenda-card .dayof { font-size: 0.74rem; color: var(--ats-ink-soft); white-space: nowrap; }
.ats-cal-agenda-card .meta { font-size: 0.82rem; color: var(--ats-ink-soft); margin-top: 5px; overflow-wrap: anywhere; }
.ats-cal-agenda-card .badge-row { margin-top: 7px; }

/* Leyenda de categoría + filtros (instalador/categoría), 2026-09-26 — un
 * "chip" con casilla es más rápido de tocar que un <select multiple>, y se ve
 * de un vistazo cuáles filtros están activos sin abrir nada. */
.ats-filter-row { display: flex; flex-wrap: wrap; gap: 6px; }
.ats-filter-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 5px 10px;
  border-radius: 999px;
  border: 1px solid var(--ats-border);
  background: var(--ats-card);
  font-size: 0.78rem;
  color: var(--ats-ink-soft);
  cursor: pointer;
  user-select: none;
  transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}
.ats-filter-chip:hover { border-color: var(--ats-ink-faint); color: var(--ats-ink); }
.ats-filter-chip input[type="checkbox"] { display: none; }
.ats-filter-chip .dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.ats-filter-chip.is-active { background: var(--ats-copper-tint-soft); border-color: var(--ats-copper); color: var(--ats-copper-dark); font-weight: 600; }

/* Columna/celda de HOY resaltada en la semana, y domingo (taller cerrado)
 * visualmente apagado — 2026-09-26. */
.ats-cal-today { background: var(--ats-copper-tint-soft) !important; border-color: var(--ats-copper) !important; }
.ats-cal-sunday { opacity: 0.5; }
.ats-cal-day-pill.is-sunday:not(.is-selected) { opacity: 0.5; }

/* Avatares de instalador dentro de una tarjeta del calendario — mismo estilo
 * que .ats-kanban-avatar, en miniatura para que quepan en una tarjeta de 76px. */
.ats-cal-avatars { display: inline-flex; align-items: center; gap: 2px; flex-shrink: 0; }
.ats-cal-avatar {
  width: 15px; height: 15px; border-radius: 50%; flex-shrink: 0;
  background: var(--ats-copper-tint); color: var(--ats-copper-dark);
  font-family: var(--font-display); font-size: 0.6rem; font-weight: 600;
  display: flex; align-items: center; justify-content: center;
}

.ats-stat {
  padding: 16px 18px;
  border-radius: var(--radius);
  background: var(--ats-card);
  border: 1px solid var(--ats-border);
  box-shadow: var(--shadow-card);
  transition: box-shadow 0.18s ease, transform 0.18s ease;
}
.ats-stat:hover { box-shadow: var(--shadow-hover); transform: translateY(-1px); }
.ats-stat .label {
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--ats-ink-faint);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.ats-stat .value {
  font-family: var(--font-display);
  font-size: 1.9rem;
  margin-top: 6px;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
}
.ats-stat.accent { border-left: 3px solid var(--ats-copper); }
.ats-stat.accent-teal { border-left: 3px solid var(--ats-teal); }
.ats-stat.accent-violet { border-left: 3px solid var(--ats-violet); }
.ats-stat.accent-danger { border-left: 3px solid var(--ats-red); }

/* "Métrica estrella" de Inicio, rediseño visual 2026-10-05 — práctica 2026
   citada: la esquina superior izquierda debe reservarse para el único número
   que de verdad responde "¿todo bien hoy?", visiblemente más grande que el
   resto, no con el mismo peso que cualquier otra tarjeta de estadística. Se
   eligió "Saldo por cobrar" (ya era la tarjeta con más funcionalidad propia —
   pestañas de periodo — y el indicador más universal de salud financiera de
   un taller) en vez de inventar un cálculo nuevo. */
.ats-stat-hero { padding: 22px 26px; }
.ats-stat-hero .value { font-size: 2.6rem; }

/* Barra de capacidad (Calendario), 2026-09-26 — un número solo ("3 / 5") no dice
 * de un vistazo qué tan lleno está; la barra sí. Verde/cobre mientras hay
 * espacio, roja en cuanto se alcanza/supera el límite. */
.ats-capacity-bar {
  margin-top: 10px;
  height: 6px;
  border-radius: 999px;
  background: var(--ats-border);
  overflow: hidden;
}
.ats-capacity-bar-fill {
  height: 100%;
  border-radius: 999px;
  background: var(--ats-copper);
  transition: width 0.25s ease;
}
.ats-capacity-bar-fill.is-exceeded { background: var(--ats-red); }

/* Indicador de tendencia (rediseño visual, Fase 2) — comparación real contra
   el periodo anterior, no decorativo: dashboard.php calcula el % de verdad. */
.ats-sparkline { flex-shrink: 0; }
.ats-trend {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: 0.68rem;
  font-weight: 700;
  padding: 2px 7px;
  border-radius: 999px;
  font-variant-numeric: tabular-nums;
  text-transform: none;
  letter-spacing: 0;
}
.ats-trend.up { background: var(--ats-green-tint); color: var(--ats-green-ink, var(--ats-green)); }
.ats-trend.down { background: var(--ats-red-tint); color: var(--ats-red-ink, var(--ats-red)); }
.ats-trend.flat { background: var(--ats-border); color: var(--ats-ink-soft); }

/* --- Folio chip (placa tipo decal) --- */
.ats-folio {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: 0.78rem;
  letter-spacing: 0.03em;
  padding: 3px 9px;
  border-radius: 4px;
  background: var(--ats-graphite-900);
  color: #fff;
  border-left: 3px solid var(--ats-copper);
}

/* --- Badges de estado (pill) --- */
.ats-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 0.72rem;
  font-weight: 600;
  padding: 3px 10px;
  border-radius: 100px;
  letter-spacing: 0.01em;
}
.ats-badge.green { background: var(--ats-green-tint); color: var(--ats-green); }
.ats-badge.amber { background: var(--ats-amber-tint); color: var(--ats-amber); }
.ats-badge.red { background: var(--ats-red-tint); color: var(--ats-red); }
.ats-badge.blue { background: var(--ats-blue-tint); color: var(--ats-blue); }
.ats-badge.copper { background: var(--ats-copper-tint); color: var(--ats-copper-dark); }
.ats-badge.gray { background: var(--ats-border); color: var(--ats-ink-soft); }

/* --- Formularios --- */
.ats-field { margin-bottom: 16px; }
.ats-field label {
  display: block;
  font-size: 0.82rem;
  font-weight: 600;
  margin-bottom: 6px;
  color: var(--ats-ink);
}
.ats-field .hint { font-size: 0.76rem; color: var(--ats-ink-soft); margin-top: 4px; }

/* Campo específico marcado en rojo tras un error de validación — rediseño
   2026-09-08, punto 5: antes solo se veía el resumen de errores hasta arriba
   de la página ($errors[]); para un formulario largo (6-7 fotos en
   Recepción/Entrega) tocaba adivinar cuál campo era el que faltaba. Ver
   $errorFields en work_order_view.php — mismo patrón reutilizable para
   cualquier campo futuro que necesite esto, no solo fotos. */
.ats-field-error {
  border: 1px solid var(--ats-red);
  background: var(--ats-red-tint);
  border-radius: var(--radius-sm);
  padding: 10px 12px 12px;
  margin-left: -12px;
  margin-right: -12px;
}
.ats-field-error label { color: var(--ats-red-ink); }
.ats-field-error-text { font-weight: 600; }
.ats-field input[type="text"],
.ats-field input[type="email"],
.ats-field input[type="password"],
.ats-field input[type="number"],
.ats-field input[type="date"],
.ats-field input[type="datetime-local"],
.ats-field select,
.ats-field textarea {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--ats-border);
  border-radius: var(--radius-sm);
  font-size: 0.92rem;
  font-family: inherit;
  background: var(--ats-card);
  color: var(--ats-ink);
}
.ats-field input:focus,
.ats-field select:focus,
.ats-field textarea:focus {
  outline: none;
  border-color: var(--ats-copper);
  box-shadow: 0 0 0 3px var(--ats-copper-tint);
}

/* --- Checkboxes / radios nativos: teñidos de marca en vez de gris de sistema ---
   Auditoría visual, 2026-08-31: se veían "de fábrica" junto a inputs ya
   personalizados. accent-color es soporte nativo del navegador, sin necesidad
   de reconstruir el control (ni JS, ni markup adicional). */
input[type="checkbox"],
input[type="radio"] {
  accent-color: var(--ats-copper);
  width: 16px;
  height: 16px;
  cursor: pointer;
}

/* --- Input de archivo nativo, con el mismo look que .btn-secondary ---
   ::file-selector-button tiene soporte amplio (Chrome/Edge/Firefox/Safari 15.4+)
   y no requiere envolver el <input> en markup adicional en ninguna de las
   pantallas que ya lo usan (compras, recepción, entrega, diseños, comprobantes). */
input[type="file"] {
  font-size: 0.85rem;
  color: var(--ats-ink-soft);
}
input[type="file"]::file-selector-button {
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: 600;
  padding: 8px 14px;
  margin-right: 10px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--ats-border);
  background: var(--ats-card);
  color: var(--ats-ink);
  cursor: pointer;
  transition: border-color 0.12s ease, background 0.12s ease;
}
input[type="file"]::file-selector-button:hover {
  border-color: var(--ats-ink-faint);
  background: var(--ats-surface);
}

/* --- Columnas numéricas/monetarias en tablas: alineadas a la derecha ---
   Auditoría visual, 2026-08-31: los montos se alineaban como texto normal,
   dificultando comparar cifras de un vistazo. Aplicar esta clase al <th>/<td>
   de cualquier columna de dinero o cantidad. */
.ats-num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* --- Botones --- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 10px 18px;
  border-radius: var(--radius-sm);
  font-size: 0.88rem;
  font-weight: 600;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background 0.12s ease, border-color 0.12s ease, box-shadow 0.12s ease;
}
.btn-primary { background: var(--ats-copper); color: #fff; }
.btn-primary:hover { background: var(--ats-copper-dark); }
.btn-secondary { background: var(--ats-card); color: var(--ats-ink); border-color: var(--ats-border); }
.btn-secondary:hover { border-color: var(--ats-ink-faint); background: var(--ats-surface); }
.btn-danger { background: var(--ats-red); color: #fff; }
.btn-danger:hover { background: #8E2E2E; }
.btn-block { width: 100%; }

/* --- Acción secundaria compacta en tarjetas (Kanban, etc.) ---
   Auditoría visual, 2026-08-31: antes eran links de texto subrayado sueltos
   ("Archivar", "Marcar perdido") — se leían como enlaces de documento, no como
   acciones de un producto. Mismo espíritu que .btn-secondary pero más chico,
   pensado para vivir varias juntas dentro de una tarjeta angosta. */
.ats-chip-action {
  display: inline-flex;
  align-items: center;
  font-size: 0.72rem;
  font-weight: 600;
  padding: 3px 9px;
  border-radius: 100px;
  background: var(--ats-surface);
  border: 1px solid var(--ats-border);
  color: var(--ats-ink-soft);
  cursor: pointer;
  text-decoration: none;
  transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}
.ats-chip-action:hover { background: var(--ats-card); border-color: var(--ats-ink-faint); color: var(--ats-ink); }
.btn-lg { padding: 14px 20px; font-size: 1rem; }

/* --- Tablas --- */
.ats-table { width: 100%; border-collapse: collapse; font-size: 0.88rem; }
.ats-table th {
  text-align: left;
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ats-ink-faint);
  padding: 10px 12px;
  border-bottom: 1px solid var(--ats-border);
}
.ats-table td {
  padding: 13px 12px;
  border-bottom: 1px solid var(--ats-border-soft);
  vertical-align: middle;
}
/* Encabezado de columna ordenable (sortableColumnHeader() en functions.php),
   agregado 2026-09-29 — hereda el color/tamaño de .ats-table th en vez de
   verse como un link azul subrayado genérico; solo cambia de color al pasar
   el mouse, para que se note que es interactivo sin llamar más la atención
   que el resto del encabezado. */
.ats-sort-link {
  color: inherit;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
}
.ats-sort-link:hover {
  color: var(--ats-copper);
}
.ats-table tr:hover td { background: var(--ats-surface); }
.ats-table .row-actions { opacity: 0; transition: opacity 0.1s ease; }
.ats-table tr:hover .row-actions { opacity: 1; }
.ats-table tr.ats-row-link { cursor: pointer; }
.ats-row-chevron { width: 24px; text-align: right; color: var(--ats-ink-faint); }
.ats-table tr.ats-row-link:hover .ats-row-chevron { color: var(--ats-copper); }

/* Densidad de tabla ajustable, rediseño visual 2026-10-05 — práctica 2026
   citada para tablas de uso intensivo: la densidad es una preferencia, no un
   valor fijo (quien revisa Cobranza/Historial/Asistencia todos los días
   prefiere ver más filas sin desplazarse; alguien ocasional prefiere más
   aire). Global, vía una clase en <html> (ver initDensityToggle() en
   app.js) — afecta TODAS las tablas de la app a la vez, no una por página,
   para que la preferencia se sienta consistente en todos lados. */
html.ats-density-compact .ats-table th { padding: 6px 10px; font-size: 0.68rem; }
html.ats-density-compact .ats-table td { padding: 6px 10px; font-size: 0.82rem; }

/* --- Alertas / flash messages --- */
.ats-alert {
  padding: 12px 16px;
  border-radius: var(--radius-sm);
  margin-bottom: 14px;
  font-size: 0.88rem;
  border-left: 3px solid;
}
.ats-alert.success { background: var(--ats-green-tint); border-color: var(--ats-green); color: var(--ats-green-ink); }
.ats-alert.error { background: var(--ats-red-tint); border-color: var(--ats-red); color: var(--ats-red-ink); }
.ats-alert.info { background: var(--ats-blue-tint); border-color: var(--ats-blue); color: var(--ats-blue-ink); }
/* Auditoría visual, 2026-08-31: faltaba un nivel "aviso" entre info y error —
   las alertas del dashboard usaban rojo para todo, sin distinguir lo bloqueante
   (saldo vencido, capacidad excedida) de lo que solo hay que tener en la mira
   (material que aún no vence, diseño esperando aprobación). */
.ats-alert.warning { background: var(--ats-amber-tint); border-color: var(--ats-amber); color: var(--ats-amber-ink); }

/* --- Login / instalador --- */
.ats-auth-screen {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--ats-graphite-900);
  background-image:
    repeating-linear-gradient(45deg, rgba(255,255,255,0.02) 0, rgba(255,255,255,0.02) 1px, transparent 1px, transparent 14px);
  padding: 20px;
}
.ats-auth-card {
  width: 100%;
  max-width: 380px;
  background: var(--ats-card);
  border-radius: var(--radius-lg);
  padding: 32px 30px;
  box-shadow: var(--shadow-pop);
}
.ats-auth-brand {
  text-align: center;
  margin-bottom: 22px;
}
.ats-auth-logo {
  max-width: 220px;
  width: 100%;
  height: auto;
  margin: 0 auto 6px;
  display: block;
}
.ats-auth-brand .name {
  font-family: var(--font-display);
  font-size: 1.3rem;
  letter-spacing: 0.01em;
}
.ats-auth-brand .name span { color: var(--ats-copper); }

/* --- Pipeline / tablero tipo Deals --- */
.ats-pipeline-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  margin-bottom: 14px;
  flex-wrap: wrap;
}
/* --- Máscara de desvanecido para contenedores con scroll horizontal ---
   Auditoría visual, 2026-08-31: el tablero Kanban y el riel de etapas no daban
   ninguna pista de que había más contenido a los lados. Envolver el elemento
   con overflow-x:auto en un .ats-scroll-fade (position:relative) agrega un
   degradado en el borde derecho — puramente decorativo, no reemplaza barras de
   scroll ni cambia el comportamiento de arrastrar tarjetas. */
.ats-scroll-fade { position: relative; }
.ats-scroll-fade::after {
  content: '';
  position: absolute;
  top: 0; right: 0; bottom: 12px;
  width: 40px;
  background: linear-gradient(to right, transparent, var(--ats-surface) 80%);
  pointer-events: none;
}
.ats-kanban { display: flex; gap: 14px; overflow-x: auto; padding-bottom: 12px; align-items: flex-start; }
.ats-kanban-col {
  flex: 0 0 272px;
  background: var(--ats-surface);
  border-radius: var(--radius);
  padding: 4px;
  transition: background 0.12s ease, box-shadow 0.12s ease;
}
/* Swipe entre columnas en celular, rediseño visual 2026-10-05 — los tableros
   Kanban de admin (Leads/Cotizaciones/Órdenes) nunca tuvieron el gesto de
   deslizar que "Mis trabajos" (instalador) ya tiene entre sus 3 pestañas;
   acá, con 6-8 columnas reales por tablero, el equivalente correcto no es un
   swipe de JS entre pestañas fijas sino scroll-snap nativo — cada swipe
   avanza una columna completa y se detiene ahí, sin JS ni listeners de touch
   nuevos. Solo en mobile (mismo corte de 900px ya usado en todo este
   archivo): en escritorio el arrastre de tarjetas entre columnas ya es la
   interacción principal, y el scroll con mouse/trackpad no se beneficia de
   que el scroll "se trabe" en cada columna. */
@media (max-width: 900px) {
  .ats-kanban { scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; }
  .ats-kanban-col { scroll-snap-align: start; }
}
.ats-kanban-col.drag-over { background: var(--ats-copper-tint-soft); box-shadow: inset 0 0 0 2px var(--ats-copper); }
.ats-kanban-col-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 10px 10px 6px;
  border-top: 3px solid var(--stage-color, var(--ats-copper));
  border-radius: 4px 4px 0 0;
}
.ats-kanban-col-header .title {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.82rem;
  color: var(--ats-ink);
}
.ats-kanban-col-header .count { font-size: 0.72rem; color: var(--ats-ink-faint); }
.ats-kanban-col-value {
  padding: 0 10px 8px;
  font-family: var(--font-mono);
  font-size: 0.76rem;
  color: var(--ats-ink-soft);
}
/* Auditoría visual, 2026-08-31: una columna con muchas tarjetas hacía crecer
   toda la página mientras las columnas vecinas quedaban vacías arriba — altura
   máxima + scroll propio mantiene el tablero parejo sin importar cuántas
   tarjetas tenga una sola columna. */
.ats-kanban-body { padding: 4px 8px 8px; min-height: 40px; max-height: 600px; overflow-y: auto; }
.ats-kanban-card {
  background: var(--ats-card);
  border: 1px solid var(--ats-border);
  border-left: 3px solid var(--stage-color, var(--ats-copper));
  border-radius: var(--radius-sm);
  padding: 11px 12px;
  margin-bottom: 8px;
  font-size: 0.84rem;
  cursor: grab;
  box-shadow: var(--shadow-card);
  transition: box-shadow 0.12s ease, transform 0.12s ease, opacity 0.12s ease;
}
.ats-kanban-card:hover { box-shadow: var(--shadow-hover); transform: translateY(-1px); }
.ats-kanban-card.dragging { opacity: 0.4; }
.ats-kanban-card .deal-value {
  font-family: var(--font-mono);
  font-weight: 600;
  color: var(--ats-ink);
  margin-top: 4px;
}
/* Punto de color por categoría de servicio (PPF/WRAP/ROTULACION/...), agregado
   junto al borde izquierdo de la tarjeta (que ya marca la ETAPA/columna) —
   distingue el TIPO de trabajo dentro de una misma columna sin leer el texto. */
.ats-category-dot {
  display: inline-block;
  width: 7px; height: 7px;
  border-radius: 50%;
  margin-right: 2px;
  vertical-align: middle;
}
/* Tarjetas Kanban más ricas (rediseño visual, Fase 2) — iniciales del cliente
   como avatar (mismo look que .ats-user-chip .avatar de la barra superior,
   solo más pequeño) y una etiqueta de "cuánto lleva aquí" para distinguir de
   un vistazo una tarjeta recién movida de una que lleva semanas estancada. */
.ats-kanban-card-head { display: flex; align-items: center; gap: 8px; margin-bottom: 2px; }
.ats-kanban-avatar {
  width: 22px; height: 22px; border-radius: 50%; flex-shrink: 0;
  background: var(--ats-copper-tint); color: var(--ats-copper-dark);
  font-family: var(--font-display); font-size: 0.72rem; font-weight: 600;
  display: flex; align-items: center; justify-content: center;
}
.ats-kanban-days {
  font-size: 0.68rem; color: var(--ats-ink-faint); font-weight: 500;
  margin-left: auto; white-space: nowrap;
  display: flex; align-items: center; gap: 4px;
}
/* Semáforo de antigüedad, propuesta propia 2026-10-06 — daysSinceColor()
   (includes/functions.php) decide el color; el punto se ve de un vistazo
   sin tener que leer "3 días"/"2 semanas" en cada tarjeta una por una. */
.ats-age-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
.ats-kanban-empty { font-size: 0.78rem; color: var(--ats-ink-faint); padding: 10px 6px; text-align: center; }

/* --- Pasos ya completados que se colapsan (Preparación, Recepción, etc.) ---
   Fondo/borde distintos a propósito: dos tarjetas blancas consecutivas (una
   colapsada a una línea, la otra expandida justo debajo) se veían como un solo
   bloque continuo — real feedback de uso, se confundía con que el contenido de
   la siguiente tarjeta "seguía siendo parte" de la colapsada. */
.ats-card summary { list-style-position: outside; }
.ats-card summary::marker { color: var(--ats-copper); }
.ats-card summary:hover { color: var(--ats-copper); }
.ats-card details[open] summary { margin-bottom: 4px; }
.ats-card.ats-card-done {
  padding-top: 14px;
  padding-bottom: 14px;
  border-left: 3px solid var(--ats-green);
  background: var(--ats-green-tint);
}
.ats-card.ats-card-done details[open] {
  padding-bottom: 4px;
}

/* Riel pegado (sticky) al hacer scroll — rediseño 2026-09-08, punto 3 de la
   propuesta: al bajar a una tarjeta como Recepción, el riel de arriba ya no
   se veía, así que se perdía de vista en qué paso iba la orden. Se probó
   deliberadamente NO construir una segunda versión "compacta" separada del
   riel — ya es una sola fila razonablemente compacta, y una segunda copia
   sería exactamente la clase de "dos lugares derivando la misma cosa" que ya
   mordió a este archivo antes ($stageRail vs. $prepDone). Mismo patrón que
   .ats-settings-nav (Configuración): position:sticky, fondo sólido para que
   no se transparente el contenido al desplazarse debajo, pegado justo abajo
   del topbar (--content-top-offset ya incluye la franja de "versión de
   prueba" de esta copia de práctica). */
.ats-stage-rail-sticky {
  position: sticky;
  top: var(--content-top-offset);
  z-index: 15;
  background: var(--ats-surface);
}

/* --- Riel de etapas de una orden de trabajo (work_order_view.php) --- */
.ats-stage-rail {
  display: flex;
  overflow-x: auto;
  gap: 0;
  padding: 4px 2px 14px;
  margin-bottom: 4px;
}
.ats-stage-rail-item { display: flex; align-items: center; flex: none; }
.ats-stage-rail-item:last-child .ats-stage-rail-connector { display: none; }
.ats-stage-rail-node {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  width: 96px;
  text-align: center;
  text-decoration: none;
  color: inherit;
}
.ats-stage-rail-dot {
  width: 26px; height: 26px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 600;
  border: 2px solid var(--ats-border);
  color: var(--ats-ink-faint);
  background: var(--ats-surface);
  flex: none;
}
.ats-stage-rail-label { font-size: 0.72rem; color: var(--ats-ink-faint); line-height: 1.25; }
.ats-stage-rail-item.done .ats-stage-rail-dot { background: var(--ats-green-tint); border-color: var(--ats-green); color: var(--ats-green); }
.ats-stage-rail-item.done .ats-stage-rail-label { color: var(--ats-ink-soft); }
.ats-stage-rail-item.current .ats-stage-rail-dot { background: var(--ats-copper); border-color: var(--ats-copper); color: #fff; box-shadow: 0 0 0 3px var(--ats-copper-tint); }
.ats-stage-rail-item.current .ats-stage-rail-label { color: var(--ats-ink); font-weight: 700; }
.ats-stage-rail-connector { width: 22px; height: 2px; background: var(--ats-border); flex: none; }
.ats-stage-rail-item.done .ats-stage-rail-connector { background: var(--ats-green); }

/* --- Responsive: móvil --- */
@media (max-width: 900px) {
  .ats-sidebar { transform: translateX(-100%); }
  .ats-sidebar.open { transform: translateX(0); }
  .ats-content { margin-left: 0; }
  .ats-menu-toggle { display: block; }
  .ats-main { padding: 16px 14px 90px; }
  .ats-grid.cols-2, .ats-grid.cols-3, .ats-grid.cols-4 { grid-template-columns: 1fr 1fr; }
  .ats-search { max-width: none; }
  h1 { font-size: 1.25rem; }

  /* Barra inferior compacta para instaladores en campo */
  .ats-bottom-nav {
    position: fixed;
    bottom: 0; left: 0; right: 0;
    background: var(--ats-graphite-900);
    display: flex;
    justify-content: space-around;
    padding: 8px 4px calc(8px + env(safe-area-inset-bottom));
    z-index: 45;
  }
  .ats-bottom-nav a {
    color: #C7C7C2;
    font-size: 0.68rem;
    text-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
  }
  .ats-bottom-nav a.active { color: var(--ats-copper); }
}

@media (max-width: 560px) {
  .ats-grid.cols-2, .ats-grid.cols-3, .ats-grid.cols-4 { grid-template-columns: 1fr; }
}

.ats-sidebar-overlay {
  display: none;
  position: fixed; inset: 0;
  background: rgba(16,18,20,0.4);
  z-index: 35;
}
.ats-sidebar-overlay.open { display: block; }

/* Foco visible para accesibilidad de teclado */
a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 2px solid var(--ats-copper);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* Visor de fotos ampliado (lightbox), rediseño visual 2026-09-25 — un solo
   overlay reutilizado por toda la app (ver initLightbox() en app.js), por
   encima de cualquier otro elemento sticky (franja de prueba z-index:50,
   menús desplegables z-index:40). */
.ats-lightbox-overlay {
  display: none;
  position: fixed; inset: 0;
  z-index: 100;
  background: rgba(10,11,13,0.92);
  /* Profundidad sutil (glassmorphism), rediseño visual 2026-10-05 — el fondo
     ya es casi opaco a propósito (evidencia fotográfica, nunca se quiere ver
     "a través"), así que el blur aquí solo suaviza el filo detrás de la
     ventana emergente, no revela nada del contenido de atrás. */
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  align-items: center;
  justify-content: center;
  padding: 40px;
  box-sizing: border-box;
}
.ats-lightbox-overlay.open { display: flex; }
.ats-lightbox-figure { margin: 0; display: flex; flex-direction: column; align-items: center; gap: 10px; max-width: 100%; max-height: 100%; position: relative; }
.ats-lightbox-img { max-width: 100%; max-height: 82vh; object-fit: contain; border-radius: 6px; box-shadow: 0 12px 40px rgba(0,0,0,0.5); transition: opacity 150ms ease-in-out; }
.ats-lightbox-caption { color: #E7E5E0; font-size: 0.85rem; text-align: center; }
/* Spinner mientras una foto (sobre todo una archivada en Drive, ver photo_view.php)
   carga dentro del visor -- 2026-09-26, real-usage: sin esto el visor se veia
   congelado durante la recuperacion desde Drive. Mismo giro (ats-spin) que el
   spinner de boton, a mayor tamano. */
.ats-lightbox-spinner { display: none; }
.ats-lightbox-overlay.loading .ats-lightbox-img { opacity: 0; }
.ats-lightbox-overlay.loading .ats-lightbox-spinner {
  display: block;
  position: absolute;
  top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 44px; height: 44px;
  border: 3px solid rgba(255,255,255,0.25);
  border-top-color: #fff;
  border-radius: 50%;
  animation: ats-spin 0.7s linear infinite;
}
@media (prefers-reduced-motion: reduce) {
  .ats-lightbox-overlay.loading .ats-lightbox-spinner { animation-duration: 1.6s; }
}
.ats-lightbox-close, .ats-lightbox-prev, .ats-lightbox-next {
  position: fixed;
  background: rgba(255,255,255,0.08);
  color: #fff;
  border: 1px solid rgba(255,255,255,0.2);
  border-radius: 50%;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.12s ease;
}
.ats-lightbox-close:hover, .ats-lightbox-prev:hover, .ats-lightbox-next:hover { background: rgba(255,255,255,0.2); }
.ats-lightbox-close { top: 20px; right: 20px; width: 40px; height: 40px; font-size: 1.6rem; line-height: 1; }
.ats-lightbox-prev, .ats-lightbox-next { top: 50%; transform: translateY(-50%); width: 48px; height: 48px; font-size: 1.8rem; line-height: 1; }
.ats-lightbox-prev { left: 20px; }
.ats-lightbox-next { right: 20px; }
@media (max-width: 640px) {
  .ats-lightbox-overlay { padding: 16px; }
  .ats-lightbox-prev, .ats-lightbox-next { width: 40px; height: 40px; font-size: 1.5rem; }
  .ats-lightbox-close { width: 34px; height: 34px; font-size: 1.3rem; }
}

/* Paleta de comandos (Ctrl+K), propuesta propia 2026-10-06 — mismo nivel (100)
   y mismo criterio de profundidad sutil (glassmorphism) que el lightbox de
   arriba, para que ambos overlays globales se sientan de la misma familia. */
.ats-command-palette {
  display: none;
  position: fixed; inset: 0;
  z-index: 100;
  background: rgba(10,11,13,0.5);
  align-items: flex-start;
  justify-content: center;
  padding: 90px 16px;
  box-sizing: border-box;
}
.ats-command-palette.open { display: flex; }
.ats-command-palette-box {
  width: 100%;
  max-width: 560px;
  background: var(--ats-glass);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border: 1px solid var(--ats-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-pop);
  overflow: hidden;
}
#ats-command-palette-input {
  width: 100%;
  box-sizing: border-box;
  border: none;
  background: transparent;
  padding: 18px 20px;
  font-size: 1.05rem;
  color: var(--ats-ink);
  border-bottom: 1px solid var(--ats-border);
}
#ats-command-palette-input:focus { outline: none; }
#ats-command-palette-results { max-height: 50vh; overflow-y: auto; padding: 6px; }
.ats-command-palette-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  text-decoration: none;
  color: inherit;
}
.ats-command-palette-row:hover, .ats-command-palette-row.active { background: var(--ats-copper-tint-soft); }
.ats-command-palette-row .type {
  font-size: 0.64rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ats-copper-dark);
  background: var(--ats-copper-tint);
  border-radius: 4px;
  padding: 2px 6px;
  flex-shrink: 0;
}
.ats-command-palette-row .label { font-weight: 600; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ats-command-palette-row .sublabel { font-size: 0.78rem; color: var(--ats-ink-faint); flex-shrink: 0; }
.ats-command-palette-empty { padding: 20px; text-align: center; color: var(--ats-ink-faint); font-size: 0.86rem; }
.ats-command-palette-hint { padding: 8px 16px; font-size: 0.7rem; color: var(--ats-ink-faint); border-top: 1px solid var(--ats-border); }
@media (max-width: 640px) {
  .ats-command-palette { padding: 16px; }
  .ats-command-palette-hint { display: none; }
}

/* Comparador antes/después con control deslizable, propuesta propia 2026-10-06
   — reemplaza las dos miniaturas lado a lado por un slider real (arrastrar
   revela antes/después sobre la misma área), mismo estándar que cualquier
   inspección digital de vehículo (DVI) real investigada para el comparador
   original. initCompareSliders() en app.js hace todo el cálculo de posición;
   esto solo define la apariencia. */
.ats-compare-slider {
  position: relative;
  width: 220px;
  height: 160px;
  border-radius: var(--radius-sm);
  overflow: hidden;
  border: 1px solid var(--ats-border);
  user-select: none;
  touch-action: none;
  cursor: ew-resize;
}
.ats-compare-slider .after,
.ats-compare-slider .before {
  position: absolute;
  top: 0; left: 0;
  width: 220px;
  height: 160px;
  object-fit: cover;
  pointer-events: none;
}
.ats-compare-slider .before-wrap {
  position: absolute;
  top: 0; left: 0;
  width: 50%;
  height: 100%;
  overflow: hidden;
}
.ats-compare-slider .handle {
  position: absolute;
  top: 0; bottom: 0;
  left: 50%;
  width: 3px;
  background: #fff;
  box-shadow: 0 0 0 1px rgba(0,0,0,0.25);
  transform: translateX(-50%);
  pointer-events: none;
}
.ats-compare-slider .handle::before {
  content: '⇔';
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 26px; height: 26px;
  border-radius: 50%;
  background: #fff;
  color: #1A1D21;
  display: flex; align-items: center; justify-content: center;
  font-size: 0.8rem;
  box-shadow: 0 1px 4px rgba(0,0,0,0.35);
}
.ats-compare-slider .compare-label {
  position: absolute;
  bottom: 6px;
  font-size: 0.64rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: #fff;
  background: rgba(0,0,0,0.45);
  padding: 2px 6px;
  border-radius: 3px;
  pointer-events: none;
}
.ats-compare-slider .label-before { left: 6px; }
.ats-compare-slider .label-after { right: 6px; }

/* ==========================================================================
   Rediseño de usabilidad, 2026-10-21 — pedido explícito: "fácil de usar para
   cualquier persona que no conozca el proceso, que no sea tedioso y
   visualmente atractivo". Todo lo de este bloque es presentación; ninguna
   regla de negocio depende de él.
   ========================================================================== */

/* Barra superior: acciones agrupadas a la derecha. */
.ats-topbar-actions { margin-left: auto; display: flex; align-items: center; gap: 10px; }
.ats-new-menu > summary.btn { display: inline-flex; align-items: center; gap: 2px; padding: 8px 14px; font-size: 0.85rem; }
.ats-new-menu > summary.btn::after { content: ' ▾'; font-size: 0.7rem; opacity: .8; }
.ats-user-menu > summary.ats-user-chip { margin-left: 0; padding: 4px 6px 4px 4px; border-radius: 999px; border: 1px solid transparent; }
.ats-user-menu > summary.ats-user-chip:hover { border-color: var(--ats-border); }
.ats-user-menu > summary::after { font-size: 0.7rem; color: var(--ats-ink-soft); }
.ats-user-menu-head { padding: 8px 12px 4px; font-size: 0.85rem; line-height: 1.4; }
.ats-dropdown-menu button {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 9px 12px; border: none; background: none; border-radius: 6px;
  color: var(--ats-ink); font: inherit; font-size: 0.85rem; text-align: left; cursor: pointer;
}
.ats-dropdown-menu button:hover { background: var(--ats-surface); }
.ats-dropdown-menu button svg { flex-shrink: 0; color: var(--ats-ink-soft); }

/* Pestañas de sección (Ventas, Taller, Dinero...). */
.ats-section-tabs {
  display: flex; gap: 4px; flex-wrap: nowrap; overflow-x: auto;
  margin: 0 0 16px; padding-bottom: 2px; border-bottom: 1px solid var(--ats-border);
  scrollbar-width: none;
}
.ats-section-tabs::-webkit-scrollbar { display: none; }
.ats-section-tabs a {
  flex: none; padding: 10px 14px; font-size: 0.9rem; font-weight: 500;
  color: var(--ats-ink-soft); text-decoration: none; white-space: nowrap;
  border-bottom: 2.5px solid transparent; margin-bottom: -1px;
  transition: color .15s, border-color .15s;
}
.ats-section-tabs a:hover { color: var(--ats-ink); }
.ats-section-tabs a.active { color: var(--ats-ink); font-weight: 700; border-bottom-color: var(--ats-copper); }

/* Línea de ayuda "¿qué hago aquí?". */
.ats-page-help {
  display: flex; align-items: center; gap: 10px; margin: 0 0 16px;
  padding: 10px 14px; border-radius: var(--radius-sm);
  background: var(--ats-blue-tint); color: var(--ats-blue-ink); font-size: 0.88rem;
}
.ats-page-help[hidden] { display: none; }
.ats-page-help > span:nth-child(2) { flex: 1; }
.ats-page-help-close {
  flex-shrink: 0; background: none; border: 1px solid currentColor; color: inherit;
  border-radius: 999px; padding: 4px 12px; font-size: 0.78rem; cursor: pointer; opacity: .85;
}
.ats-page-help-close:hover { opacity: 1; }

@media (max-width: 900px) {
  .ats-topbar { padding: 0 12px; gap: 8px; }
  .ats-user-name { display: none; }
}
@media (max-width: 560px) {
  .ats-new-label { display: none; }
  .ats-new-menu > summary.btn { padding: 8px 12px; font-size: 1rem; }
  .ats-search input::placeholder { color: transparent; }
}

/* Asistente de fotos (initPhotoWizards() en app.js). La cuadrícula sin JS ya
   no se sale de la pantalla: columnas que se acomodan solas y campos de
   archivo que no exigen su ancho nativo (~300px, causa del desborde a 1024px). */
.ats-photo-grid { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.ats-photo-grid input[type="file"] { width: 100%; max-width: 100%; min-width: 0; }
.ats-photo-wizard-on [data-photo-step] {
  position: absolute !important; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; margin: 0; padding: 0;
}
.ats-photo-wizard { border: 1px solid var(--ats-border); border-radius: var(--radius-sm); padding: 14px; margin: 8px 0 14px; background: var(--ats-surface); }
.ats-pw-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }
.ats-pw-chip {
  border: 1px solid var(--ats-border); background: var(--ats-card); color: var(--ats-ink-soft);
  border-radius: 999px; padding: 6px 12px; font-size: 0.8rem; cursor: pointer;
}
.ats-pw-chip.done { background: var(--ats-green-tint); color: var(--ats-green-ink); border-color: transparent; }
.ats-pw-chip.error { background: var(--ats-red-tint); color: var(--ats-red-ink); border-color: transparent; }
.ats-pw-chip.current { border-color: var(--ats-copper); color: var(--ats-ink); font-weight: 700; box-shadow: 0 0 0 2px var(--ats-copper-tint); }
.ats-pw-stage { display: flex; gap: 20px; align-items: center; flex-wrap: wrap; }
.ats-pw-art { flex: none; width: 140px; height: 110px; display: flex; align-items: center; justify-content: center; border-radius: 12px; background: var(--ats-card); color: var(--ats-copper); border: 1px dashed var(--ats-border); }
.ats-pw-body { flex: 1; min-width: 200px; display: flex; flex-direction: column; align-items: flex-start; gap: 8px; }
.ats-pw-count { font-size: 0.78rem; color: var(--ats-ink-soft); text-transform: uppercase; letter-spacing: .04em; }
.ats-pw-title { font-size: 1.15rem; font-weight: 700; }
.ats-pw-msg { color: var(--ats-red-ink); background: var(--ats-red-tint); padding: 6px 10px; border-radius: 6px; font-size: 0.85rem; }
.ats-pw-msg[hidden] { display: none; }
.ats-pw-shoot { font-size: 1rem; padding: 12px 22px; }
.ats-pw-thumbs { display: flex; gap: 8px; flex-wrap: wrap; }
.ats-pw-thumb { position: relative; width: 84px; height: 84px; padding: 0; border: 2px solid var(--ats-green); border-radius: 10px; overflow: hidden; cursor: pointer; background: none; }
.ats-pw-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ats-pw-thumb span { position: absolute; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,.55); color: #fff; font-size: 0.68rem; padding: 2px 0; text-align: center; }
.ats-pw-more[hidden], .ats-pw-shoot[hidden] { display: none; }
.ats-pw-nav { display: flex; justify-content: space-between; margin-top: 14px; }
.ats-pw-nav button:disabled { opacity: .4; cursor: default; }

/* Tablas anchas: el JS (initTableWraps) las envuelve en un contenedor que se
   desplaza solo él, en vez de empujar la página entera de lado. */
.ats-table-wrap { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* Cotización: en laptop (<1200px) la tabla de servicios y la columna de
   Contacto/Notas no caben lado a lado — se apilan en una sola columna. */
@media (max-width: 1200px) { .ats-grid.ats-quote-layout { grid-template-columns: 1fr; } }

/* Calendario semanal legible en laptop (rediseño de usabilidad 2026-10-21):
   el domingo (taller cerrado) se angosta para dar ancho a los 6 días de
   trabajo, y la tarjeta prioriza cliente/vehículo sobre el nombre del servicio. */
.ats-cal-week-grid { grid-template-columns: repeat(6, minmax(118px, 1fr)) minmax(64px, .5fr); }
.ats-cal-job {
  display: block; height: 76px; box-sizing: border-box; overflow: hidden; margin-bottom: 6px;
  padding: 5px 7px; border-left: 3px solid var(--ats-border); background: var(--ats-surface);
  border-radius: 4px; text-decoration: none; color: inherit; transition: background .15s;
}
.ats-cal-job:hover { background: var(--ats-copper-tint-soft); }
.ats-cal-job-top { display: flex; align-items: center; justify-content: space-between; gap: 4px; }
.ats-cal-job-who { font-size: 0.8rem; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ats-cal-job-line { font-size: 0.72rem; line-height: 1.35; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ats-cal-job-status { display: flex; align-items: center; gap: 5px; font-size: 0.68rem; color: var(--ats-ink-soft); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ats-cal-job-dot.ats-badge { flex: none; width: 8px; height: 8px; padding: 0; border-radius: 50%; min-width: 0; font-size: 0; }
.ats-cal-job-dot.gray { background: var(--ats-ink-faint); } .ats-cal-job-dot.blue { background: var(--ats-blue); } .ats-cal-job-dot.amber { background: var(--ats-amber); } .ats-cal-job-dot.red { background: var(--ats-red); } .ats-cal-job-dot.green { background: var(--ats-green); }
.ats-cal-week-grid > .ats-card { padding: 8px 6px !important; }
.ats-cal-week-grid { grid-template-columns: repeat(6, minmax(104px, 1fr)) minmax(60px, .45fr); gap: 6px; }

/* Franja de dinero de la orden (work_order_view.php). */
.ats-money-strip { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 24px; padding: 12px 16px; margin: 0 0 16px; background: var(--ats-card); border: 1px solid var(--ats-border); border-radius: var(--radius-sm, 10px); }
.ats-money-strip > div:not(.actions) { display: flex; flex-direction: column; }
.ats-money-strip .lbl { font-size: 0.72rem; text-transform: uppercase; letter-spacing: .05em; color: var(--ats-ink-soft); }
.ats-money-strip .val { font-family: var(--font-display); font-size: 1.25rem; font-weight: 600; font-variant-numeric: tabular-nums; }
.ats-money-strip .owes .val { color: var(--ats-red); }
.ats-money-strip .paid .val { color: var(--ats-green); }
.ats-money-strip .actions { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; }
@media (max-width: 560px) { .ats-money-strip .actions { margin-left: 0; width: 100%; } .ats-money-strip .actions .btn { flex: 1; text-align: center; } }

/* Los bloques que no son pasos (descripción, franja de dinero, avisos) tapan la
   línea vertical en vez de quedar tachados por ella (se veía cruzándolos,
   sobre todo en celular). */
.ats-order-timeline > :not(.ats-card) { position: relative; z-index: 2; }

/* Pestañas dentro de una pantalla (Configuración, Asistencia) — estilo de
   "botones segmentados" para distinguirlas de las pestañas de sección de arriba. */
.ats-inpage-tabs { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 16px; }
.ats-inpage-tabs button {
  border: 1px solid var(--ats-border); background: var(--ats-card); color: var(--ats-ink-soft);
  border-radius: 999px; padding: 8px 16px; font: inherit; font-size: 0.88rem; cursor: pointer;
  transition: background .15s, color .15s, border-color .15s;
}
.ats-inpage-tabs button:hover { color: var(--ats-ink); border-color: var(--ats-ink-faint); }
.ats-inpage-tabs button.active { background: var(--ats-copper); border-color: var(--ats-copper); color: #fff; font-weight: 600; }
[data-tab-panel][hidden] { display: none !important; }

/* Pulido visual (rediseño de usabilidad 2026-10-21). */
/* Al saltar a una tarjeta por ancla, que la barra superior fija no tape su título. */
.ats-main [id] { scroll-margin-top: calc(var(--content-top-offset) + 12px); }
/* Tarjetas del calendario en px fijos: viven en carriles de 76px de alto. */
.ats-cal-job-who { font-size: 12px; } .ats-cal-job-line { font-size: 11px; } .ats-cal-job-status { font-size: 10.5px; }
/* Celular: botones y campos de al menos 44px de alto (tamaño mínimo cómodo para el dedo). */
@media (max-width: 900px) {
  .btn { min-height: 44px; }
  .ats-main input:not([type="checkbox"]):not([type="radio"]):not([type="file"]), .ats-main select { min-height: 44px; }
  .ats-section-tabs a { padding: 12px 14px; }
}

/* Bienvenida de Inicio (mapa del proceso en 4 pasos). */
.ats-welcome { align-items: flex-start; padding: 16px 18px; }
.ats-welcome-steps { list-style: none; counter-reset: ats-welcome; display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin: 0; padding: 0; }
.ats-welcome-steps li { counter-increment: ats-welcome; }
.ats-welcome-steps a { display: block; height: 100%; padding: 10px 12px 10px 40px; position: relative; border-radius: 10px; background: var(--ats-card); color: var(--ats-ink); text-decoration: none; border: 1px solid transparent; }
.ats-welcome-steps a:hover { border-color: var(--ats-copper); }
.ats-welcome-steps a::before { content: counter(ats-welcome); position: absolute; left: 10px; top: 10px; width: 22px; height: 22px; border-radius: 50%; background: var(--ats-copper); color: #fff; font-size: 0.75rem; font-weight: 700; display: flex; align-items: center; justify-content: center; }
.ats-welcome-steps b { display: block; font-size: 0.88rem; }
.ats-welcome-steps span { display: block; font-size: 0.78rem; color: var(--ats-ink-soft); }
@media (max-width: 900px) { .ats-welcome-steps { grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px) { .ats-welcome-steps { grid-template-columns: 1fr; } }
.ats-welcome { position: relative; flex-direction: column; align-items: stretch; }
.ats-welcome > div { width: 100%; }
.ats-welcome .ats-page-help-close { position: absolute; top: 12px; right: 14px; }

/* Nada empuja la página de lado en celular: las columnas de rejilla pueden
   encogerse por debajo del ancho de su contenido (si no, una tabla o fila ancha
   ensancha toda la columna), y los campos de archivo nativos no exigen sus ~320px. */
.ats-grid > *, .ats-today-lists > * { min-width: 0; }
.ats-main input[type="file"] { max-width: 100%; }
