/* WHY: paleta recalibrada 1:1 contra `frontend/src/index.css` del repo
   hermano pitstopIA (servicio de postventa/taller, mismo cliente CCV) —
   pedido explícito del usuario (ago 2026): que esta app se vea igual a
   esa. Se traducen las utilidades Tailwind v4 (`@theme`) de ese archivo a
   custom properties de CSS plano porque este proyecto sigue siendo
   Jinja2 + HTMX + CSS vanilla (ver ADR-001) — sin Tailwind ni build step.
   El contenido (tarjetas, tablas, formularios) es claro; la
   taskbar/start-menu estilo XP y el panel de marca del login se mantienen
   como "chrome" deliberadamente oscuro (mismo criterio que pitstopIA — ver
   WHY de `.xp-taskbar` en su index.css), usando variables `--corp-chrome-*`
   separadas de las de contenido. */
:root {
  --corp-dark: #ffffff;
  --corp-darker: #eceef1;
  --corp-gray: #5b6167;
  --corp-gray-dim: #6b7280;
  --corp-light: #f4f5f6;
  --corp-surface: #f1f3f5;
  --corp-border: rgba(120, 125, 130, 0.15);
  --corp-border-strong: rgba(120, 125, 130, 0.3);
  --corp-accent: #3b82f6;
  --corp-accent-hover: #2563eb;
  --corp-accent-dim: rgba(59, 130, 246, 0.15);
  --corp-success: #10b981;
  --corp-warning: #f59e0b;
  --corp-danger: #ef4444;
  --corp-info: #6366f1;
  --corp-text: #1a1d1f;
  /* WHY: "chrome" oscuro deliberado — taskbar/start-menu y panel de marca
     del login, ver comentario de arriba. Valores calcados de pitstopIA
     (.xp-taskbar/.xp-start-menu en su index.css: #2A2E32→#16181A y
     #202426 respectivamente). */
  --corp-chrome: #202426;
  --corp-chrome-2: #16181a;
  --corp-chrome-border: rgba(164, 165, 166, 0.15);
  --corp-chrome-muted: rgba(255, 255, 255, 0.65);
  --corp-chrome-dim: rgba(255, 255, 255, 0.45);
}

* {
  box-sizing: border-box;
}

html, body {
  margin: 0;
  padding: 0;
  min-height: 100%;
  overflow-x: hidden;
  background-color: var(--corp-darker);
  /* WHY: fondo parametrizable desde /parametrizacion (ver
     web/apariencia.py) — la URL real se inyecta inline en el `<body>` de
     base.html porque depende de datos (configuración en BD), no puede
     vivir en este archivo estático. `background-color` de arriba queda
     como respaldo mientras la imagen carga o si no hay ninguna
     configurada (páginas sin `usuario`, ej. login). `background-size:
     auto` (tamaño real, sin estirar/expandir a cubrir la pantalla) —
     pedido explícito del cliente, ago 2026: "centrado... tamaño real, NO
     expandido". */
  background-size: auto;
  background-position: center;
  background-repeat: no-repeat;
  background-attachment: fixed;
  color: var(--corp-text);
  /* WHY: "Inter" nunca se cargó en este proyecto (sin @font-face ni <link>,
     ver ADR-001 — nada de fuentes vía CDN) — quedaba cayendo en silencio a
     system-ui. Se declara honestamente la pila de sistema real (misma
     recomendación que el resto de la herramienta: tipografía de sistema es
     suficiente para una app B2B interna), en vez de nombrar una fuente que
     nunca se ve. */
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

html {
  scroll-behavior: smooth;
}

* {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: var(--corp-darker); }
::-webkit-scrollbar-thumb { background: rgba(120, 125, 130, 0.35); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: rgba(120, 125, 130, 0.55); }

h1, h2, h3 {
  margin: 0;
  font-weight: 600;
  color: var(--corp-text);
  text-wrap: balance;
}

a {
  color: inherit;
}

/* WHY: números de orden/chasis/motor/valores — fuente monoespaciada para
   que los dígitos se alineen en columna (docs/UI_DESIGN_SYSTEM.md §4). */
.mono {
  /* WHY: mismo problema que el font-family de arriba — "JetBrains Mono"/
     "Fira Code"/"Cascadia Code" no están vendorizadas, caían a
     `monospace` genérica. `ui-monospace` (soportada en Win/Mac/Linux
     modernos) resuelve a la monoespaciada nativa de mejor calidad de cada
     sistema antes de llegar al fallback genérico. */
  font-family: ui-monospace, "Cascadia Mono", "Segoe UI Mono", "Roboto Mono", Menlo, Consolas, monospace;
  font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
}

.meta {
  color: var(--corp-gray);
  font-size: 0.85rem;
}

/* ── Layout de admin + taskbar estilo Windows XP
   (ver docs/UI_ADMIN_LAYOUT_XP_TASKBAR.md) — reemplaza la barra superior por
   una barra de tareas fija abajo, con botón "Inicio" que despliega un menú
   hacia arriba. Mismo concepto que el documento (que asume React+Tailwind),
   traducido a CSS plano + Alpine.js (ver ADR-001).

   NOTE: el botón Inicio va abajo-a-la-izquierda (mismo lugar que el XP
   real y que el documento) — una conversación anterior lo había puesto a
   la derecha, se corrigió a pedido del cliente; la bandeja del sistema
   (systray) quedó del lado derecho. */

/* WHY: sin `background-color` propio — antes era opaco (`--corp-darker`)
   y tapaba por completo el fondo parametrizable de `<body>` (ver
   web/apariencia.py), que quedaba invisible detrás de este div de 100vh
   (pedido explícito del cliente, ago 2026: "el fondo no se está viendo"). */
.xp-shell {
  display: flex;
  flex-direction: column;
  height: 100vh;
}

.xp-main {
  flex: 1;
  overflow-y: auto;
}

.xp-start-menu-wrap {
  position: relative;
  flex-shrink: 0;
}

.xp-taskbar {
  flex-shrink: 0;
  height: 48px;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0 0.5rem;
  background: linear-gradient(180deg, var(--corp-chrome) 0%, var(--corp-chrome-2) 100%);
  border-top: 1px solid var(--corp-chrome-border);
  box-shadow: 0 -1px 6px rgba(0, 0, 0, 0.4);
}

.xp-spacer {
  flex: 1;
}

.xp-taskbar-sep {
  width: 1px;
  height: 24px;
  flex-shrink: 0;
  background: var(--corp-chrome-border);
}

.xp-taskbar-item {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.75rem;
  font-weight: 500;
  color: #ffffff;
  padding: 0.35rem 0.75rem;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--corp-chrome-border);
  min-width: 0;
  max-width: 220px;
}

.xp-taskbar-item span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.xp-taskbar-item.xp-active {
  background: rgba(59, 130, 246, 0.25);
  border: 1px solid rgba(59, 130, 246, 0.5);
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.5);
}

.xp-systray {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  font-size: 0.75rem;
  padding: 0.3rem 0.75rem;
  border-radius: 4px;
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid var(--corp-chrome-border);
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.5);
  flex-shrink: 0;
}

.xp-systray-app {
  color: rgba(255, 255, 255, 0.75);
  text-decoration: none;
  font-weight: 600;
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@media (max-width: 640px) {
  .xp-systray-app {
    display: none;
  }
}

.xp-systray-app:hover {
  color: #ffffff;
}

.xp-systray-clock {
  color: rgba(255, 255, 255, 0.5);
  font-variant-numeric: tabular-nums;
}

.xp-avatar,
.xp-avatar-lg {
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  font-weight: 700;
  color: #ffffff;
  flex-shrink: 0;
}

.xp-avatar {
  width: 22px;
  height: 22px;
  font-size: 0.62rem;
  background: var(--corp-accent);
}

.xp-avatar-lg {
  width: 40px;
  height: 40px;
  font-size: 0.9rem;
  background: rgba(255, 255, 255, 0.25);
  border: 2px solid rgba(255, 255, 255, 0.6);
}

.xp-brand-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  line-height: 0;
}

/* WHY: badge flotante con el logo parametrizable (ver base.html) —
   `position: fixed` para no ocupar espacio en el flujo del documento
   (nunca empuja el contenido de cada módulo). El logo real
   (images/logo.png) es un wordmark alto con bastante margen interno
   alrededor del texto ("CCV" + subtítulo) — necesita una caja generosa
   (72px) para que el texto sea legible; en la taskbar de 48px quedaba
   ilegible/invisible (pedido explícito del cliente, ago 2026: "el logo
   sigue sin aparecer"). Fondo blanco + sombra para que se lea sobre
   cualquier fondo parametrizado (ver .table-dark/body). */
.app-logo-float {
  position: fixed;
  top: 14px;
  right: 18px;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 12px;
  background: #ffffff;
  border: 1px solid var(--corp-border-strong);
  border-radius: 10px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.18);
  padding: 8px 14px;
}

.app-logo-float img {
  height: 72px;
  width: auto;
  max-width: 220px;
  object-fit: contain;
}

/* WHY: separador entre el logo de la compañía y el logo adicional
   (images/logoadicional.jpeg, ago 2026: "agrega... junto al logo de CCV
   del front") — sin esto los dos logos se ven pegados. */
.app-logo-float-divisor {
  align-self: stretch;
  width: 1px;
  background: var(--corp-border-strong);
}

@media (max-width: 639px) {
  .app-logo-float {
    top: 10px;
    right: 10px;
    padding: 5px 9px;
  }

  .app-logo-float img {
    height: 44px;
    max-width: 140px;
  }
}

.xp-start-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 700;
  font-size: 0.85rem;
  color: #ffffff;
  cursor: pointer;
  user-select: none;
  /* WHY: silueta asimétrica calcada de pitstopIA (borde izquierdo recto,
     redondeado solo a la derecha) — más fiel al botón Inicio real de XP
     que un pill simétrico. */
  padding: 0.4rem 1.1rem 0.4rem 0.75rem;
  border-radius: 0 12px 12px 0;
  background: linear-gradient(180deg, #5b9dfb 0%, var(--corp-accent) 45%, var(--corp-accent-hover) 100%);
  border: 1px solid #1e3a8a;
  border-left: none;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 1px 2px rgba(0, 0, 0, 0.5);
  transition: filter 100ms ease-out;
}

.xp-start-btn:hover {
  filter: brightness(1.08);
}

.xp-start-btn.xp-pressed {
  background: linear-gradient(180deg, var(--corp-accent-hover) 0%, var(--corp-accent) 100%);
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.6);
}

.xp-start-btn:focus-visible {
  outline: 2px solid var(--corp-accent);
  outline-offset: 2px;
}

/* WHY: en angosto (<640px) "Inicio" se reemplaza por un ícono de hamburguesa
   — mismo criterio que pitstopIA (MenuIcon en vez del label en el botón
   Inicio cuando la pantalla es chica). */
.xp-start-icon-mobile {
  display: none;
}

@media (max-width: 639px) {
  .xp-start-label {
    display: none;
  }
  .xp-start-icon-mobile {
    display: inline-block;
  }
}

.xp-start-menu {
  position: fixed;
  bottom: 52px;
  left: 8px;
  z-index: 50;
  width: 288px;
  max-height: calc(100vh - 80px);
  display: flex;
  flex-direction: column;
  background: var(--corp-chrome);
  border: 1px solid var(--corp-accent);
  border-radius: 10px 10px 4px 4px;
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.45), 0 0 0 3px var(--corp-accent-dim);
  overflow: hidden;
}

.xp-start-menu-header {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.85rem 1rem;
  background: linear-gradient(90deg, var(--corp-accent-hover) 0%, var(--corp-accent) 60%, #5b9dfb 100%);
}

.xp-start-menu-user-info {
  min-width: 0;
}

.xp-start-menu-user {
  margin: 0;
  font-size: 0.9rem;
  font-weight: 700;
  color: #ffffff;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.xp-start-menu-rol {
  margin: 0;
  font-size: 0.68rem;
  color: rgba(255, 255, 255, 0.8);
}

.xp-start-menu-body {
  flex: 1;
  overflow-y: auto;
  padding: 0.25rem 0;
}

.xp-start-menu-item {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-size: 0.85rem;
  color: #ffffff;
  text-decoration: none;
  padding: 0.55rem 1rem;
  transition: background 100ms ease-out;
}

.xp-start-menu-item:hover,
.xp-start-menu-item.xp-active {
  background: linear-gradient(90deg, rgba(59, 130, 246, 0.35), rgba(59, 130, 246, 0.15));
}

.xp-menu-icon {
  width: 28px;
  height: 28px;
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(59, 130, 246, 0.18);
  color: #60a5fa;
  flex-shrink: 0;
}

.xp-start-menu-footer {
  background: rgba(0, 0, 0, 0.25);
  border-top: 1px solid var(--corp-chrome-border);
  padding: 0.4rem;
}

/* ── Tablero — embudo comercial vertical (solo lectura) ───────────────────
   WHY: pedido explícito del cliente (ago 2026) — el embudo se lee de
   arriba (Contactado, más volumen) hacia abajo (Entregado, menos volumen,
   más cerca del cierre), como un embudo de ventas real, en vez de columnas
   Kanban horizontales. Cada franja ocupa el ancho completo y sus tarjetas
   se desplazan en fila horizontal dentro de la franja — así una etapa con
   muchas tarjetas no estira la página verticalmente sin límite. Ver
   `.embudo-mini` más abajo para el diagrama decorativo (calcado de
   images/embudo.png) que corona la página. */

.tablero {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  padding: 1.5rem;
  flex: 1;
  min-width: 0;
}

.tablero-top {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 1.25rem 1.5rem 0.5rem;
}

/* WHY: envuelve `.tablero` (franjas + tarjetas, columna principal) y
   `.tablero-embudo-panel` (diagrama de referencia) lado a lado — el embudo
   ya no compite por espacio con el contenido real (ver .tablero-top de
   arriba: esa imagen de fondo quedaba tapada por las franjas) sino que
   vive en su propio carril angosto a la derecha, siempre visible mientras
   se hace scroll de las franjas. */
.tablero-layout {
  display: flex;
  align-items: flex-start;
  gap: 1rem;
}

.tablero-embudo-panel {
  flex-shrink: 0;
  width: 260px;
  position: sticky;
  top: 1.5rem;
  padding: 1.25rem 1.5rem;
  display: flex;
  justify-content: center;
}

.tablero-embudo-panel img {
  width: 100%;
  height: auto;
  object-fit: contain;
}

@media (max-width: 960px) {
  .tablero-layout {
    flex-direction: column;
  }

  .tablero-embudo-panel {
    width: 100%;
    position: static;
  }
}

/* WHY: 6 tarjetas reservadas para indicadores de seguimiento aún sin
   definir con el cliente — borde punteado y valor "Por definir" para que
   se lean como placeholder a propósito, no como un dato roto. */
.indicadores-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 0.85rem;
  padding: 0.5rem 1.5rem 0.5rem;
}

.indicador-placeholder {
  padding: 1rem;
  border-style: dashed;
  border-color: var(--corp-border-strong);
  background-color: var(--corp-surface);
}

.indicador-placeholder-icon {
  width: 32px;
  height: 32px;
  border-radius: 0.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: rgba(120, 125, 130, 0.15);
  color: var(--corp-gray);
  margin-bottom: 0.6rem;
}

.indicador-placeholder-label {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--corp-text);
}

.indicador-placeholder-value {
  font-size: 0.78rem;
  color: var(--corp-gray-dim);
  margin-top: 0.15rem;
}

.columna {
  width: 100%;
}

.columna .card {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.lista-tarjetas {
  display: flex;
  flex-direction: row;
  overflow-x: auto;
  gap: 0.6rem;
  min-height: 40px;
  padding: 0.9rem;
}

/* WHY: la franja de cada etapa (`.columna .card-header`) ahora usa un
   color sólido (ver `.embudo-*` más abajo) — el título necesita texto
   blanco en vez del gris/oscuro que usa en el resto de la app (fondos
   claros). */
.columna .card-header .card-title {
  color: #ffffff;
  font-size: 0.95rem;
  /* WHY: la franja ahora es semitransparente sobre una imagen de fondo
     variable (ver .embudo-* y .tablero) — el texto blanco necesita algo
     de contraste garantizado que no dependa de qué haya detrás. */
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
}

/* WHY: contador de tarjetas por etapa — pedido explícito del cliente
   (ago 2026) de que sea visible como tal, no un número gris pegado al
   título (ver .card-title .count del resto de la app). Píldora blanca
   translúcida sobre el color sólido de la franja, número en mono para que
   no "salte" de ancho entre 1 y 2 dígitos. */
.embudo-counter {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.75rem;
  height: 1.75rem;
  padding: 0 0.5rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.28);
  border: 1px solid rgba(255, 255, 255, 0.4);
  color: #ffffff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
  font-family: ui-monospace, "Cascadia Mono", "Segoe UI Mono", "Roboto Mono", Menlo, Consolas, monospace;
  font-size: 0.85rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}

.mini-tarjeta {
  background-color: var(--corp-surface);
  border: 1px solid var(--corp-border);
  border-radius: 8px;
  padding: 0.7rem 0.8rem;
  cursor: pointer;
  transition: border-color 150ms ease-out;
  /* WHY: ahora es un ítem de una fila horizontal con scroll (antes ocupaba
     el ancho completo de una columna de 280px) — ancho fijo explícito. */
  width: 240px;
  flex: 0 0 240px;
}

.mini-tarjeta:hover {
  border-color: var(--corp-border-strong);
}

.mini-tarjeta .titulo {
  font-weight: 600;
  margin-bottom: 0.25rem;
}

.mini-tarjeta .meta {
  display: flex;
  gap: 0.4rem;
  flex-wrap: wrap;
  font-size: 0.78rem;
}

/* ── Badges de estado (docs/UI_DESIGN_SYSTEM.md §5.4) — recipe: fondo 12%,
   texto en un tono ~700 (suficientemente oscuro para fondo claro), borde
   25-30% (ver ADR-013, antes eran tonos claros pensados para fondo oscuro) ─ */

.badge {
  font-size: 0.75rem;
  padding: 0.125rem 0.5rem;
  border-radius: 4px;
  font-weight: 500;
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
  background-color: rgba(120, 125, 130, 0.12);
  color: var(--corp-gray);
  border: 1px solid rgba(120, 125, 130, 0.2);
}

.badge-success {
  background-color: rgba(16, 185, 129, 0.12);
  color: #047857;
  border: 1px solid rgba(16, 185, 129, 0.3);
}

.badge-warning {
  background-color: rgba(245, 158, 11, 0.12);
  color: #b45309;
  border: 1px solid rgba(245, 158, 11, 0.3);
}

.badge-danger {
  background-color: rgba(239, 68, 68, 0.12);
  color: #dc2626;
  border: 1px solid rgba(239, 68, 68, 0.3);
}

.badge-info {
  background-color: rgba(59, 130, 246, 0.12);
  color: #1d4ed8;
  border: 1px solid rgba(59, 130, 246, 0.3);
}

.badge-neutral {
  background-color: rgba(120, 125, 130, 0.12);
  color: #5b6167;
  border: 1px solid rgba(120, 125, 130, 0.25);
}

/* ── Embudo comercial (ver services/embudo_service.py, ADR-006) ───────────
   9 colores propios, sólidos, en degradado tipo arcoíris (azul→rojo) —
   pedido explícito del cliente (ago 2026). Volvieron a sólido tras quitar
   la imagen de fondo de `.tablero` (ver .tablero-top más abajo: el embudo
   de referencia ahora es un ícono fijo junto al título, no un fondo
   detrás de las franjas) — ya no hace falta atenuarlas para no competir
   con nada. Mismo orden que `EstadoEmbudo` (Nuevo → Entregado, ver
   services/embudo_service.py) — única superficie del proyecto que usa
   estas 9 clases (ver grep — nada más las consume). */

.embudo-nuevo {
  background-color: #1d4ed8;
  border-color: #1d4ed8;
}

.embudo-contactado {
  background-color: #0284c7;
  border-color: #0284c7;
}

.embudo-cotizado {
  background-color: #0891b2;
  border-color: #0891b2;
}

.embudo-test-drive {
  background-color: #0d9488;
  border-color: #0d9488;
}

.embudo-negociacion {
  background-color: #059669;
  border-color: #059669;
}

.embudo-credito {
  background-color: #65a30d;
  border-color: #65a30d;
}

.embudo-separado {
  background-color: #d97706;
  border-color: #d97706;
}

.embudo-listo-entrega {
  background-color: #ea580c;
  border-color: #ea580c;
}

.embudo-entregado {
  background-color: #dc2626;
  border-color: #dc2626;
}

.columna .card-header {
  border-bottom-width: 2px;
}

/* WHY: diagrama decorativo (no interactivo) calcado de images/embudo.png
   — corona la página como resumen visual del embudo; las franjas reales
   con las tarjetas van debajo (ver .tablero). Se mantiene aparte del dato
   real a propósito: angostar las franjas de datos geométricamente arriesga
   cortar tarjetas cuando una etapa tiene muchas (ver plan acordado). */
/* ── Inputs (§5.1) ────────────────────────────────────────────────────────  */

input[type="text"],
input[type="number"],
input[type="email"],
input[type="tel"],
input[type="password"],
select,
textarea {
  width: 100%;
  padding: 0.625rem 0.875rem;
  border-radius: 0.5rem;
  font-size: 0.875rem;
  color: var(--corp-text);
  background-color: var(--corp-surface);
  border: 1px solid var(--corp-border-strong);
  font-family: inherit;
  transition: all 200ms ease-out;
}

/* WHY: convención calcada de pitstopIA (pedido explícito del cliente ahí,
   ago 2026) — refuerzo visual inmediato de que el texto libre se guarda en
   mayúsculas, mientras se escribe. Se excluyen email/password (semántica
   distinta, nunca se fuerzan) — select conserva el texto tal cual está
   guardado en el catálogo (marcas, ciudades, etc.), igual que allá. */
input:not([type="email"]):not([type="password"]),
textarea {
  text-transform: uppercase;
}

/* WHY: el mensaje de WhatsApp de Feria es contenido real que se envía tal
   cual al prospecto (con placeholders {nombre}/{marca}/{modelo} en
   minúscula) — forzarlo a mayúsculas como el resto del texto libre de la
   app lo volvería ilegible como mensaje y rompería el reemplazo de
   placeholders (semántica distinta, mismo criterio que email/password de
   arriba). */
textarea[name="mensaje"] {
  text-transform: none;
}

input::placeholder,
textarea::placeholder {
  color: var(--corp-gray-dim);
}

input:focus,
select:focus,
textarea:focus {
  outline: none;
  box-shadow: 0 0 0 2px var(--corp-accent);
  border-color: transparent;
}

input:disabled,
select:disabled,
textarea:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

select option {
  background-color: var(--corp-dark);
  color: var(--corp-text);
}

/* ── Botones (§5.2) ───────────────────────────────────────────────────────  */

.btn-primary,
.btn-secondary,
.btn-ghost,
.btn-danger {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  border-radius: 0.5rem;
  font-size: 0.875rem;
  cursor: pointer;
  text-decoration: none;
  transition: all 200ms ease-out;
}

.btn-primary:disabled,
.btn-secondary:disabled,
.btn-ghost:disabled,
.btn-danger:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.btn-primary:active,
.btn-secondary:active,
.btn-ghost:active,
.btn-danger:active {
  transform: scale(0.98);
}

.btn-primary:focus-visible,
.btn-secondary:focus-visible,
.btn-ghost:focus-visible,
.btn-danger:focus-visible {
  outline: 2px solid var(--corp-accent);
  outline-offset: 2px;
}

.btn-primary {
  background-color: var(--corp-accent);
  color: #ffffff;
  font-weight: 600;
  padding: 0.625rem 1rem;
  border: none;
}

.btn-primary:hover {
  background-color: var(--corp-accent-hover);
}

.btn-secondary {
  color: var(--corp-text);
  font-weight: 600;
  padding: 0.625rem 1rem;
  background-color: var(--corp-surface);
  border: 1px solid var(--corp-border-strong);
}

.btn-secondary:hover {
  border-color: var(--corp-gray-dim);
}

.btn-ghost {
  color: var(--corp-gray);
  padding: 0.5rem 0.75rem;
  font-weight: 500;
  background: transparent;
  border: none;
}

.btn-ghost:hover {
  color: var(--corp-text);
  background-color: rgba(0, 0, 0, 0.05);
}

.btn-danger {
  background-color: var(--corp-danger);
  color: #ffffff;
  font-weight: 600;
  padding: 0.625rem 1rem;
  border: none;
}

.btn-danger:hover {
  background-color: #b91c1c;
}

.error,
.error-banner {
  font-size: 0.85rem;
  padding: 0.5rem 0.75rem;
  border-radius: 0.5rem;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  background: rgba(239, 68, 68, 0.1);
  color: #b91c1c;
}

.error-banner svg {
  flex-shrink: 0;
}

/* ── Cards (§5.3) ─────────────────────────────────────────────────────────  */

.card {
  border-radius: 10px;
  background-color: var(--corp-dark);
  border: 1px solid var(--corp-border);
  overflow: hidden;
}

/* WHY: las tarjetas de catálogo de Parametrización (Marcas/Modelos/Líneas/
   Concesionarios/Orígenes) con tabla `.table-dark` de ancho `auto` (ver
   arriba) dejaban un bloque blanco enorme sin nada — la tarjeta seguía
   estirada a los 1100px de `.page.ancho` aunque su contenido real fuera
   angosto (pedido explícito del cliente, ago 2026: "genera ruido"). La
   tarjeta ahora se ajusta al ancho real de su contenido en vez del ancho
   de la página. */
.card-compacta {
  width: fit-content;
  max-width: 100%;
  min-width: 320px;
}

/* WHY: `.page` tiene 1.25rem (20px) de padding a cada lado — en un
   viewport de 320-360px (celulares comunes) el ancho de contenido
   disponible queda en ~280-320px, menos que el `min-width: 320px` de
   arriba, y la tarjeta desbordaba el viewport (scroll horizontal de toda
   la página, no solo de la tabla — pedido explícito del cliente, ago
   2026: validar responsive en celulares). Por debajo de 480px, la
   tarjeta se ajusta al ancho disponible en vez de forzar un mínimo. */
@media (max-width: 480px) {
  .card-compacta {
    min-width: 0;
  }
}

.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 1rem 1.25rem;
  border-bottom: 1px solid var(--corp-border);
  flex-wrap: wrap;
}

.card-title {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--corp-text);
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.card-title .count {
  font-weight: 400;
  color: var(--corp-gray);
  font-size: 0.8rem;
}

.card-body {
  padding: 1.25rem;
}

/* ── Tabla (§5.5) ─────────────────────────────────────────────────────────  */

/* WHY: `width: auto` (no 100% + table-layout:fixed) — con solo 2-3 columnas
   de texto corto, forzar la tabla a ocupar todo el ancho de la tarjeta
   distribuye las columnas muy separadas entre sí (pedido explícito del
   cliente, ago 2026: "no es necesario distribuir sobre el ancho de la
   caja"). Las columnas se ajustan a su contenido y quedan juntas a la
   izquierda; el resto de la tarjeta simplemente queda en blanco. */
.table-dark {
  width: auto;
  font-size: 0.875rem;
  border-collapse: collapse;
}

/* WHY: modificador para tablas que sí deben ocupar todo el ancho de su
   tarjeta con columnas parejas (Feria — Fichas técnicas/Prospectos, ver
   ADR-015, pedido explícito del cliente: "de manera ecuánime y que ocupen
   el ancho de la caja"). `table-layout: fixed` sin anchos por columna
   reparte el espacio en partes iguales entre todas — a diferencia de
   `.table-dark` a secas (arriba), que se deja angosta a propósito para
   Parametrización. */
/* WHY: sin `min-width`, en pantallas angostas (celular) el navegador
   encoge la tabla completa para que quepa en el viewport — con
   `table-layout: fixed` eso aprieta cada columna hasta que los
   encabezados ("NOMBRE PROSPECTO", "USUARIO WHATSAPP", etc.) se parten
   letra por letra y quedan ilegibles (pedido explícito del cliente, ago
   2026: "que los nombres de las columnas no se vean afectadas"). Con un
   `min-width` la tabla conserva un ancho legible y el contenedor
   `overflow-x:auto` que ya la envuelve permite hacer scroll horizontal en
   vez de comprimirla. */
.table-dark.table-distribuida {
  width: 100%;
  min-width: 640px;
  table-layout: fixed;
}

.table-dark.table-distribuida th,
.table-dark.table-distribuida td {
  white-space: normal;
  word-break: break-word;
}

/* WHY: columnas con valores cortos y fijos que nunca deberían partirse
   (Feria: "Modelo" — BJ30/T5/S5/T1 — y "Marca" — BAIC/ARCFOX) — con
   `table-layout: fixed` + el `word-break` de arriba, al angostar la
   ventana esas columnas quedaban tan apretadas que hasta el encabezado
   "MODELO" se partía letra por letra (ver images/ajustesresponsive.PNG,
   pedido explícito del cliente, ago 2026). Ancho fijo en vez de `%` —
   nunca se comprime más allá de esto, y el resto de la tabla se ajusta
   alrededor. */
.table-dark.table-distribuida .col-angosta {
  width: 74px;
  white-space: nowrap;
  word-break: normal;
}

/* WHY: el `word-break: break-word` de arriba (para que nombres/celulares
   largos no desborden una columna angosta) partía también la etiqueta de
   los botones letra por letra dentro de columnas estrechas — quedaban
   ilegibles ("SUBIR" apilado verticalmente, ver images/feria.PNG, pedido
   explícito del cliente: "no se ve el texto del botón"). Los botones
   siempre en una sola línea, sin partirse. */
.table-dark.table-distribuida .btn-primary,
.table-dark.table-distribuida .btn-ghost,
.table-dark.table-distribuida .btn-secondary {
  white-space: nowrap;
  word-break: normal;
}

/* WHY: el formulario de subir/reemplazar ficha (input de archivo + botón)
   ya no intenta caber en una sola línea dentro de una columna angosta —
   si no alcanza el ancho, el botón pasa a la línea de abajo en vez de
   comprimirse hasta volverse ilegible. */
.table-dark.table-distribuida .form-agregar-compacto {
  flex-wrap: wrap;
}

/* WHY: el texto nativo del input de archivo ("Sin archivos
   seleccionados") hereda el tamaño de fuente normal del formulario y
   ocupaba casi toda la columna Acciones, empujando el botón fuera de
   vista (pedido explícito del cliente, ago 2026: "reduce el tamaño de
   letra de sin archivos seleccionados"). Más chico, solo en este
   contexto — no afecta otros inputs de archivo del resto de la app. */
.table-dark.table-distribuida input[type="file"] {
  font-size: 0.72rem;
  max-width: 100%;
}

/* WHY: botón de acción icon-only para filas de tabla angostas (Feria —
   Prospectos: "Enviar ficha técnica") — el texto completo forzaba la fila
   a dos líneas dentro de una columna estrecha, subiendo la altura de cada
   fila (pedido explícito del cliente, ago 2026: "la altura quedó alta...
   asigna una imagen alusiva al envío"). Tamaño fijo, sin depender del
   ancho de la columna. */
.btn-icono {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.1rem;
  height: 2.1rem;
  padding: 0;
  flex-shrink: 0;
}

.table-dark thead tr {
  background-color: rgba(120, 125, 130, 0.06);
  border-bottom: 1px solid var(--corp-border-strong);
}

.table-dark thead th {
  padding: 0.5rem 1.25rem 0.5rem 0.85rem;
  text-align: left;
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--corp-gray);
  white-space: nowrap;
}

.table-dark tbody tr {
  border-bottom: 1px solid var(--corp-border);
  transition: background-color 150ms ease-out;
}

.table-dark tbody tr:hover {
  background-color: rgba(0, 0, 0, 0.025);
}

.table-dark tbody tr:last-child {
  border-bottom: none;
}

.table-dark tbody td {
  padding: 0.3rem 1.25rem 0.3rem 0.85rem;
  color: var(--corp-text);
  vertical-align: middle;
  white-space: nowrap;
}

.table-dark tbody td.muted {
  color: var(--corp-gray);
  font-size: 0.78rem;
}

/* WHY: los inputs de edición inline (Parametrización) heredaban el padding
   de un input de formulario de página completa (0.625rem 0.875rem) — sumado
   al padding de la celda, las filas quedaban mucho más altas que una fila
   de datos normal (pedido explícito del cliente, ago 2026: "se ven
   demasiado grandes"). Más compactos, solo dentro de `.table-dark`. */
.table-dark input[type="text"] {
  width: auto;
  padding: 0.2rem 0.5rem;
  font-size: 0.85rem;
}

/* WHY: el formulario "Nueva marca... + Agregar" (y equivalentes de
   Modelos/Líneas/Concesionarios/Orígenes) heredaba el input/botón de
   tamaño de página completa — quedaba visiblemente más alto que las filas
   compactas de la tabla justo debajo (pedido explícito del cliente, ago
   2026: "sigue viéndose igual" tras un primer recorte de padding
   demasiado tímido — se fija una altura explícita para que el cambio sea
   inequívoco). Clase local, no toca `.btn-primary`/inputs del resto de la
   app. */
/* WHY: `flex-wrap: wrap` para todas las instancias — algunos formularios
   de "agregar" (ej. Marcas/Concesionarios de Parametrización) no traían
   `flex-wrap` en su estilo en línea y desbordaban horizontalmente en
   celular (pedido explícito del cliente, ago 2026: validar responsive).
   Centralizado acá en vez de repetirlo por template — no afecta el
   layout en desktop, donde nunca hace falta envolver. */
.form-agregar-compacto {
  align-items: center;
  flex-wrap: wrap;
}

.form-agregar-compacto input[type="text"],
.form-agregar-compacto select,
.form-agregar-compacto .btn-primary {
  height: 2rem;
  font-size: 0.8rem;
}

.form-agregar-compacto input[type="text"],
.form-agregar-compacto select {
  padding: 0 0.6rem;
}

.form-agregar-compacto .btn-primary {
  padding: 0 0.85rem;
}

/* WHY: el formulario "Nuevo prospecto" de Feria (nombre/celular/usuario
   WhatsApp) heredaba el mismo tamaño de fuente que el resto de los
   formularios de alta — pedido explícito del cliente (ago 2026) de
   achicarlo más todavía, solo en estos 3 campos de texto. */
.form-prospecto-feria input[type="text"] {
  font-size: 0.72rem;
}

.table-dark tr.fila {
  cursor: pointer;
}

/* ── Encabezados de página y formularios (§5.6) ──────────────────────────  */

.page-header {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  margin-bottom: 1.5rem;
}

@media (min-width: 640px) {
  .page-header {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
  }
}

/* WHY: eyebrow "⚙ Administración" arriba del título — calcado 1:1 del
   encabezado de Parametrización en pitstopIA (pedido explícito del
   cliente, ago 2026: "ajústalo a como se ve en la imagen"). */
.page-eyebrow {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.85rem;
  color: var(--corp-gray);
  margin-bottom: 0.2rem;
}

.page-title {
  font-size: 1.25rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--corp-text);
  text-wrap: balance;
}

.page-subtitle {
  font-size: 0.85rem;
  margin-top: 0.15rem;
  color: var(--corp-gray);
}

/* WHY: navegación por pestañas agrupadas por dominio — calcada del patrón
   de Parametrización de pitstopIA (frontend/src/pages/Parametrizacion.tsx,
   ago 2026, pedido explícito del cliente de que este módulo se vea igual
   ahí). Ahí las pestañas cambian de sección con React state; acá, con
   Alpine (`x-show`) sobre las mismas secciones ya servidas por el backend
   — sin JSON ni fetch adicional, todo el contenido ya vino en el render
   inicial de /parametrizacion. */
.tabs-grupo {
  margin-bottom: 0.85rem;
}

.tabs-grupo-label {
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--corp-gray-dim);
  margin-bottom: 0.4rem;
}

.tabs-grupo-pills {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.tab-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.5rem 1rem;
  border-radius: 0.5rem;
  border: 1px solid var(--corp-border-strong);
  background: var(--corp-dark);
  color: var(--corp-gray);
  font-size: 0.85rem;
  font-weight: 500;
  cursor: pointer;
  transition: all 150ms ease-out;
}

.tab-pill:hover {
  border-color: var(--corp-gray-dim);
  color: var(--corp-text);
}

.tab-pill.activo {
  background: var(--corp-accent);
  color: #ffffff;
  border-color: var(--corp-accent);
}

.form-label {
  display: block;
  font-size: 0.72rem;
  font-weight: 500;
  margin-bottom: 0.4rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--corp-gray);
}

/* ── Modales (§5.7) ───────────────────────────────────────────────────────  */

.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  background-color: rgba(20, 22, 25, 0.6);
  backdrop-filter: blur(4px);
  overflow-y: auto;
}

.modal-box {
  width: 100%;
  max-width: 32rem;
  max-height: 90vh;
  overflow-y: auto;
  background-color: var(--corp-dark);
  border: 1px solid var(--corp-border-strong);
  border-radius: 12px;
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1rem 1.5rem;
  position: sticky;
  top: 0;
  background-color: var(--corp-dark);
  border-bottom: 1px solid var(--corp-border);
  border-radius: 12px 12px 0 0;
}

.modal-title {
  font-size: 1rem;
  font-weight: 600;
  color: var(--corp-text);
}

.modal-body {
  padding: 1.25rem 1.5rem;
}

/* ── Estado vacío (§5.8) ──────────────────────────────────────────────────  */

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 4rem 0;
  text-align: center;
}

.empty-state-icon {
  width: 3.5rem;
  height: 3.5rem;
  border-radius: 1rem;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto 1rem;
  background-color: rgba(120, 125, 130, 0.1);
  color: var(--corp-gray);
}

.empty-state-text {
  font-size: 0.875rem;
  color: var(--corp-gray);
}

/* ── Animaciones (§5.9) ───────────────────────────────────────────────────  */

@keyframes fadeIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }
.animate-fadeIn { animation: fadeIn 0.2s ease-out; }

@keyframes slideInLeft { from { transform: translateX(-100%); } to { transform: translateX(0); } }
.animate-slideInLeft { animation: slideInLeft 0.25s ease-out; }

@keyframes spin { to { transform: rotate(360deg); } }
.animate-spin { animation: spin 1s linear infinite; }

@media (prefers-reduced-motion: reduce) {
  .animate-fadeIn, .animate-slideInLeft, .animate-spin, html {
    animation: none !important;
    scroll-behavior: auto !important;
  }
}

/* ── Extensiones propias del proyecto (no forman parte del doc portado) ──  */
/* WHY: checklist de pasos, línea de tiempo de avance y lista de comentarios
   son específicos del dominio de este proyecto — no están en
   UI_DESIGN_SYSTEM.md, así que se construyen con los mismos tokens/spirit
   (superficie clara, acento único, texto gris para lo secundario, ver
   ADR-013) en vez de inventar una paleta paralela. */

.paso {
  display: flex;
  align-items: flex-start;
  gap: 0.7rem;
  padding: 0.65rem 0;
  border-bottom: 1px solid var(--corp-border);
}

.paso:last-child {
  border-bottom: none;
}

.paso .marker {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  margin-top: 0.15rem;
  border-radius: 5px;
  border: 1.5px solid var(--corp-border-strong);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #ffffff;
}

.paso.done .marker {
  background-color: var(--corp-success);
  border-color: var(--corp-success);
}

.paso .body {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}

.paso .texto {
  font-weight: 500;
}

.paso.done .texto {
  color: var(--corp-gray);
  text-decoration: line-through;
  text-decoration-color: var(--corp-border-strong);
  font-weight: 400;
}

.progreso-mini {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  min-width: 120px;
}

.progreso-mini .track {
  height: 6px;
  border-radius: 3px;
  background-color: rgba(120, 125, 130, 0.15);
  overflow: hidden;
}

.progreso-mini .fill {
  height: 100%;
  border-radius: 3px;
  background-color: var(--corp-accent);
}

.progreso-mini .frac {
  font-size: 0.76rem;
  color: var(--corp-gray);
}

.timeline {
  display: flex;
  flex-direction: column;
}

.timeline-item {
  display: flex;
  gap: 0.7rem;
  padding-bottom: 1rem;
  position: relative;
}

.timeline-item::before {
  content: "";
  position: absolute;
  left: 4px;
  top: 14px;
  bottom: 0;
  width: 1px;
  background: var(--corp-border-strong);
}

.timeline-item:last-child::before {
  display: none;
}

.timeline-item:last-child {
  padding-bottom: 0;
}

.timeline-item .dot {
  flex: 0 0 auto;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  margin-top: 4px;
  background-color: var(--corp-accent);
}

.timeline-item .texto {
  font-weight: 500;
}

.comentarios-lista {
  display: flex;
  flex-direction: column;
}

.comentario-item {
  padding: 0.85rem 0;
  border-bottom: 1px solid var(--corp-border);
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.comentario-item:last-child {
  border-bottom: none;
}

.comentario-item .autor-linea {
  display: flex;
  justify-content: space-between;
  gap: 0.6rem;
  font-size: 0.8rem;
}

.comentario-item .autor {
  font-weight: 600;
}

/* WHY: patrón repetido en 9+ partials de alta rápida (fotos, documentos,
   gastos, descuentos, pagos, accesorios, trámites, retoma) — un formulario
   corto de una sola fila que envuelve en pantallas angostas. Antes vivía
   como `style="display:flex;gap:0.5rem;align-items:center;flex-wrap:wrap;"`
   repetido a mano en cada template (ver checklist "Código" del skill de
   rediseño). */
.form-inline {
  display: flex;
  gap: 0.6rem;
  align-items: center;
  flex-wrap: wrap;
}

.form-inline input,
.form-inline select {
  width: auto;
}

.form-comentario {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin-top: 1rem;
}

.form-comentario textarea {
  min-height: 4rem;
  resize: vertical;
}

.form-comentario .btn-primary {
  align-self: flex-start;
}

.spec-photo {
  aspect-ratio: 4 / 3;
  width: 100%;
  border-radius: 8px;
  border: 1px solid var(--corp-border);
  object-fit: cover;
  display: block;
}

.spec-photo.sin-foto {
  background-color: rgba(120, 125, 130, 0.08);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--corp-gray);
  font-size: 0.8rem;
  text-align: center;
  padding: 1rem;
}

.spec-facts {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.spec-fact {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}

.spec-fact .label {
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: 0.66rem;
  color: var(--corp-gray);
}

.spec-fact .value {
  font-weight: 600;
  font-size: 0.9rem;
}

.spec-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

/* ── Login — pantalla dividida (marca a la izquierda, formulario a la
   derecha) — ver imagen de referencia en la conversación de diseño. El
   panel de marca se mantiene como "chrome" oscuro deliberado (ver
   ADR-013), el panel de formulario es claro. ──────────────────────────── */

.login-split {
  min-height: 100dvh;
  display: flex;
}

.login-brand {
  flex: 1;
  display: flex;
  flex-direction: column;
  padding: 3rem 2.5rem;
  background:
    linear-gradient(rgba(255, 255, 255, 0.035) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.035) 1px, transparent 1px),
    linear-gradient(160deg, var(--corp-chrome) 0%, var(--corp-chrome-2) 100%);
  background-size: 32px 32px, 32px 32px, 100% 100%;
  border-right: 1px solid var(--corp-chrome-border);
}

.login-brand-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 0.9rem;
  max-width: 26rem;
  margin: 0 auto;
  text-align: left;
}

.login-logo-glow {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 88px;
  height: 88px;
  border-radius: 20px;
  margin-bottom: 0.5rem;
  background: var(--corp-accent);
  box-shadow: 0 0 40px 6px var(--corp-accent-dim), 0 8px 20px rgba(0, 0, 0, 0.5);
}

.login-logo-glow svg {
  border-radius: 10px;
}

.login-brand-title {
  margin: 0;
  font-size: 1.75rem;
  font-weight: 700;
  letter-spacing: -0.015em;
  color: #ffffff;
  text-wrap: balance;
}

.login-brand-subtitle {
  margin: 0;
  color: var(--corp-chrome-muted);
  font-size: 0.95rem;
}

.login-brand-company {
  margin: 0 0 0.5rem;
  color: var(--corp-chrome-dim);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.04em;
}

.login-brand-features {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.login-brand-features li {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  color: var(--corp-chrome-muted);
  font-size: 0.88rem;
}

.login-feature-dot {
  flex-shrink: 0;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--corp-accent);
}

.login-brand-footer {
  margin: 1.5rem 0 0;
  text-align: center;
  color: var(--corp-chrome-dim);
  font-size: 0.75rem;
}

.login-form-panel {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1.5rem;
  padding: 2rem 1.5rem;
}

.login-card {
  width: 100%;
  max-width: 23rem;
  background-color: var(--corp-dark);
  border: 1px solid var(--corp-border-strong);
  border-radius: 12px;
}

.login-card-header {
  padding: 1.25rem 1.5rem 1rem;
  border-bottom: 1px solid var(--corp-border);
}

.login-card-title {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 1rem;
  font-weight: 700;
  color: var(--corp-text);
}

.login-card-title svg {
  color: var(--corp-accent);
  flex-shrink: 0;
}

.login-card-subtitle {
  margin: 0.25rem 0 0 1.5rem;
  font-size: 0.8rem;
  color: var(--corp-gray);
}

.login-card-body {
  padding: 1.25rem 1.5rem 1.5rem;
}

.login-field {
  position: relative;
  display: flex;
  align-items: center;
}

.login-field-icon {
  position: absolute;
  left: 0.75rem;
  color: var(--corp-gray-dim);
  pointer-events: none;
}

.login-field input {
  padding-left: 2.25rem;
}

.login-field-toggle {
  position: absolute;
  right: 0.6rem;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  padding: 0.25rem;
  color: var(--corp-gray-dim);
  cursor: pointer;
}

.login-field-toggle:hover {
  color: var(--corp-gray);
}

.login-field:has(.login-field-toggle) input {
  padding-right: 2.25rem;
}

.login-form-footer {
  margin: 0;
  color: var(--corp-gray-dim);
  font-size: 0.78rem;
  text-align: center;
}

@media (max-width: 760px) {
  .login-split {
    flex-direction: column;
  }
  .login-brand {
    padding: 2.5rem 1.5rem;
    border-right: none;
    border-bottom: 1px solid var(--corp-chrome-border);
  }
  .login-brand-content {
    align-items: flex-start;
  }
  .login-form-panel {
    padding: 2.5rem 1.5rem 3rem;
  }
}

/* ── Páginas de gestión/inventario ────────────────────────────────────────  */

.page {
  padding: 1.5rem 1.25rem;
  max-width: 900px;
  margin: 0 auto;
}

.page.ancho {
  max-width: 1100px;
}

/* WHY: el badge flotante del logo (`.app-logo-float`, arriba-derecha,
   `position: fixed`) queda sobre el contenido si la página empieza justo
   debajo del padding normal de `.page` — varios módulos (Usuarios,
   Gestión, Inventario) tienen un botón "+ Nuevo..." también
   arriba-derecha en `.page-header`, y quedaba tapado por el logo al
   cargar la página sin haber hecho scroll (pedido explícito del cliente,
   ago 2026: validar que nada quede mal distribuido). Espacio extra
   arriba solo en páginas con `.xp-main` (autenticadas, donde vive el
   badge) — Tablero no lo necesita porque su encabezado (`.tablero-top`)
   no tiene nada a la derecha. */
.xp-main .page {
  padding-top: 6.5rem;
}

@media (max-width: 639px) {
  .xp-main .page {
    padding-top: 4.5rem;
  }
}

.detalle-grid {
  display: grid;
  grid-template-columns: 300px 1fr;
  gap: 1.25rem;
  align-items: start;
}

@media (max-width: 800px) {
  .detalle-grid {
    grid-template-columns: 1fr;
  }
}

.workspace {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

.form-centrado {
  display: flex;
  justify-content: center;
  padding: 3rem 1rem;
}

/* ── Calendario — grilla mes/semana/día (ver ADR-008) ──────────────────── */

.cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 1px;
  background: var(--corp-border);
}

.cal-grid-header {
  gap: 0;
  background: transparent;
  margin-bottom: 2px;
}

.cal-dia-header {
  padding: 0.5rem;
  text-align: center;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--corp-gray-dim);
}

.cal-celda {
  display: block;
  min-height: 6.5rem;
  padding: 0.4rem;
  background: var(--corp-dark);
  color: inherit;
  text-decoration: none;
  transition: background-color 150ms ease;
}

.cal-celda:hover {
  background: rgba(0, 0, 0, 0.03);
}

.cal-celda.fuera-de-mes {
  opacity: 0.4;
}

.cal-celda.hoy {
  box-shadow: inset 0 0 0 2px var(--corp-accent);
}

.cal-celda-numero {
  font-size: 0.8rem;
  font-weight: 600;
  margin-bottom: 0.3rem;
}

.cal-evento-pill {
  font-size: 0.7rem;
  padding: 0.1rem 0.4rem;
  border-radius: 4px;
  margin-bottom: 0.2rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cal-mas {
  font-size: 0.7rem;
  color: var(--corp-gray-dim);
}

.cal-grid-semana {
  min-height: 20rem;
}

.cal-columna-dia {
  background: var(--corp-dark);
  padding: 0.5rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.cal-columna-dia.hoy {
  box-shadow: inset 0 0 0 2px var(--corp-accent);
}

.cal-evento-item {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  padding: 0.4rem;
  border-radius: 6px;
  background: rgba(0, 0, 0, 0.03);
}

.cal-evento-titulo {
  font-size: 0.8rem;
  font-weight: 600;
}

/* ── Menú de navegación móvil (drawer) — calcado de pitstopIA
   (Layout.tsx) ───────────────────────────────────────────────────────────
   WHY: el menú "Inicio" estilo XP es un patrón de escritorio — en
   pantallas angostas (<640px, mismo breakpoint que pitstopIA) se
   reemplaza por un drawer lateral estándar con ítems grandes, fáciles de
   tocar. Comparte el estado `open` de Alpine con `.xp-start-menu` (ver
   base.html) — cuál de los dos se ve lo decide un media query, no JS,
   para no duplicar la lógica de apertura/cierre. */

.mobile-nav-overlay {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
}

@media (min-width: 640px) {
  .mobile-nav-overlay {
    display: none !important;
  }
}

@media (max-width: 639px) {
  .xp-start-menu {
    display: none !important;
  }
}

.mobile-nav-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
}

.mobile-nav-drawer {
  position: relative;
  z-index: 10;
  width: 82%;
  max-width: 20rem;
  height: 100%;
  display: flex;
  flex-direction: column;
  background: #151719;
  border-right: 1px solid var(--corp-chrome-border);
}

.mobile-nav-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 1rem;
  border-bottom: 1px solid var(--corp-chrome-border);
}

.mobile-nav-user {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-width: 0;
}

.mobile-nav-avatar {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1rem;
  font-weight: 700;
  color: #ffffff;
  background: var(--corp-accent);
  flex-shrink: 0;
}

.mobile-nav-user-name {
  margin: 0;
  font-size: 0.875rem;
  font-weight: 700;
  color: #ffffff;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.mobile-nav-user-rol {
  margin: 0;
  font-size: 0.75rem;
  color: #a4a5a6;
}

.mobile-nav-close {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0.5rem;
  border-radius: 0.5rem;
  background: transparent;
  border: none;
  color: #a4a5a6;
  cursor: pointer;
  transition: background-color 150ms ease-out;
}

.mobile-nav-close:hover {
  background-color: rgba(255, 255, 255, 0.1);
}

.mobile-nav-items {
  flex: 1;
  overflow-y: auto;
  padding: 0.5rem 0;
}

.mobile-nav-item {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.85rem 1rem;
  font-size: 1rem;
  color: #a4a5a6;
  text-decoration: none;
  transition: background-color 150ms ease-out;
}

.mobile-nav-item.xp-active {
  color: #ffffff;
  background: rgba(59, 130, 246, 0.15);
}

.mobile-nav-icon {
  width: 32px;
  height: 32px;
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(59, 130, 246, 0.18);
  color: #60a5fa;
  flex-shrink: 0;
}

.mobile-nav-footer {
  padding: 0.75rem;
  border-top: 1px solid var(--corp-border);
}

.mobile-nav-logout {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.85rem 1rem;
  border-radius: 0.5rem;
  font-size: 1rem;
  color: #f87171;
  background: transparent;
  border: none;
  cursor: pointer;
  text-decoration: none;
  transition: background-color 150ms ease-out;
}

.mobile-nav-logout:hover {
  background-color: rgba(255, 255, 255, 0.05);
}

.mobile-nav-logout .mobile-nav-icon {
  background: rgba(239, 68, 68, 0.15);
  color: #f87171;
}

/* ── Tarjetas KPI y de alerta (Reportes) — calcadas de pitstopIA
   (Dashboard.tsx: KpiCard/AlertCard) ───────────────────────────────────── */

.kpi-card {
  display: block;
  padding: 1.25rem;
  text-decoration: none;
  color: inherit;
  transition: box-shadow 200ms ease-out;
}

.kpi-card:hover {
  box-shadow: 0 4px 14px rgba(20, 22, 25, 0.08);
}

.kpi-card-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: 1rem;
}

.kpi-card-icon {
  width: 44px;
  height: 44px;
  border-radius: 0.75rem;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #ffffff;
}

.kpi-card-value {
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.kpi-card-label {
  font-size: 0.85rem;
  margin-top: 0.15rem;
  color: var(--corp-gray);
}

.kpi-card-link {
  margin-top: 0.75rem;
  display: flex;
  align-items: center;
  gap: 0.25rem;
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--corp-accent);
  opacity: 0;
  transition: opacity 150ms ease-out;
}

.kpi-card:hover .kpi-card-link {
  opacity: 1;
}

.alert-card {
  padding: 1.1rem 1.25rem;
  border-left: 4px solid var(--corp-warning);
}

.alert-card.alert-card-danger {
  border-left-color: var(--corp-danger);
}

.alert-card-head {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 0.85rem;
}

.alert-card-icon {
  width: 36px;
  height: 36px;
  border-radius: 0.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  background: rgba(245, 158, 11, 0.12);
  color: var(--corp-warning);
}

.alert-card-danger .alert-card-icon {
  background: rgba(239, 68, 68, 0.12);
  color: var(--corp-danger);
}

.alert-card-title {
  font-weight: 600;
  font-size: 0.875rem;
  color: var(--corp-text);
}

.alert-card-sub {
  font-size: 0.75rem;
  color: var(--corp-gray);
  margin-top: 0.1rem;
}

.alert-card-count {
  margin-left: auto;
}
