/* ============================================================================
   components.css — Capa de componentes (muniVM · marca cívica 2026)
   Carga DESPUÉS de tokens.css. Targetea selectores ya existentes en el HTML/JS
   para no recablear nada, y agrega componentes reutilizables nuevos
   (chips de estado, tarjetas de métrica, panel de telemetría, señal GSM, etc.).
   Solo usa tokens semánticos; sin hex crudos.
   ============================================================================ */

/* ============================================================================
   Header de marca cívica UNIFICADO (todas las páginas internas)
   Cubre .app-header (usuarios/vehiculos/profile/tutoriales) y .header
   (historial/alarms) — ambos pasan a ser una barra de marca con gradiente.
   ============================================================================ */
.app-header,
.app-container > .header {
  background: var(--brand-gradient) !important;
  border-bottom: none !important;
  box-shadow: var(--shadow-md);
  color: var(--text-on-brand);
  padding: var(--space-3) var(--space-5);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  position: relative;
  z-index: var(--z-sticky);
}
/* Título de página dentro del header de marca */
.app-header > h1,
.app-container > .header > h1,
.app-header .header-container > h1 {
  color: var(--text-on-brand);
  font-family: var(--font-sans);
  font-weight: var(--fw-semibold);
  font-size: var(--fs-xl);
  letter-spacing: -0.01em;
  margin: 0;
  text-wrap: balance;
}

/* ============================================================================
   Header del MAPA — barra de mando "consola de operaciones diurna"
   Solo afecta a .app-header--brand (página del mapa). El resto de páginas
   conserva su header con gradiente cívico. Se usa especificidad doble +
   !important para vencer el `background: var(--brand-gradient) !important`
   del .app-header genérico de arriba.
   ============================================================================ */
.app-header.app-header--brand {
  background: var(--console-bg) !important;
  border-bottom: 1px solid var(--hairline) !important;
  box-shadow: 0 1px 0 var(--hairline), 0 6px 18px -12px rgba(16,24,40,.28);
  color: var(--text-primary);
  padding: var(--space-3) var(--space-5);
  position: relative;
  z-index: var(--z-sticky);
}
/* filo de acento "en vivo" sobre el borde inferior */
.app-header.app-header--brand::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px;
  background: linear-gradient(90deg,
    var(--brand-blue) 0%,
    var(--accent-teal) 34%,
    color-mix(in srgb, var(--accent-teal) 0%, transparent) 72%);
  opacity: .9;
}
.app-header--brand .index-header-container {
  background: transparent;
  gap: var(--space-4);
  padding: 0;
  flex-wrap: wrap;   /* red de seguridad: si no entra en una fila, baja el filtro */
}
.brand-lockup { display: flex; align-items: center; gap: var(--space-3); min-width: 0; }
.brand-logo {
  height: 38px; width: auto; flex-shrink: 0;
  background: var(--surface-data);
  padding: 4px 8px; border-radius: var(--radius-sm);
  border: 1px solid var(--hairline);
}
.brand-text { display: flex; flex-direction: column; line-height: 1.2; min-width: 0; }
.brand-title {
  font-size: var(--fs-xs); font-weight: var(--fw-bold);
  text-transform: uppercase; letter-spacing: .14em;
  color: var(--brand-blue);
  font-family: var(--font-mono);
}
.app-header--brand .pet-name {
  display: inline-flex; align-items: center; gap: var(--space-2);
  color: var(--text-primary); font-weight: var(--fw-semibold);
  font-size: var(--fs-base); margin-left: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  cursor: pointer;
  max-width: 46vw;
}
/* caret que delata que pet-name es un selector (el texto lo setea el JS) */
.app-header--brand .pet-name::after {
  content: "\f078"; /* chevron-down */
  font-family: "Font Awesome 6 Free"; font-weight: 900;
  font-size: 10px; color: var(--text-muted);
  flex-shrink: 0; transition: transform var(--dur-fast) var(--ease-standard);
}
.app-header--brand .pet-name:hover { color: var(--brand-blue); }
.app-header--brand .pet-name:hover::after { color: var(--brand-blue); transform: translateY(1px); }
.app-header--brand .header-center { flex: 1; display: flex; justify-content: center; align-items: center; }

/* El header de consola ya muestra el vehículo en .brand-lockup; ocultamos el
   bloque .pet-info legado (avatar foto.png + #petName duplicado) que el JS del
   filtro de secretarías puede recrear. No se toca esa lógica: solo se oculta. */
.app-header--brand .pet-info { display: none !important; }

/* Indicador ambiental "EN VIVO" (el sistema es tiempo real vía MQTT) */
.live-indicator {
  display: inline-flex; align-items: center; gap: var(--space-2);
  flex-shrink: 0;
  font-family: var(--font-mono); font-size: var(--fs-xs); font-weight: var(--fw-semibold);
  letter-spacing: .12em; text-transform: uppercase;
  color: color-mix(in srgb, var(--accent-teal) 72%, #000);  /* AA: ~5:1 sobre claro */
  padding: 5px var(--space-3);
  border: 1px solid color-mix(in srgb, var(--accent-teal) 35%, transparent);
  border-radius: var(--radius-pill);
  background: color-mix(in srgb, var(--accent-teal) 8%, transparent);
}
.live-indicator .live-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--accent-teal);
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent-teal) 60%, transparent);
  animation: livePulse 1.8s var(--ease-standard) infinite;
}
[data-theme="dark"] .live-indicator { color: var(--accent-teal); }
/* se oculta antes (≤768px) para no apretar el header en tablets angostas */
@media (max-width: 768px) { .live-indicator { display: none; } }

/* El input del filtro de secretarías dentro de la barra de mando clara */
.app-header--brand #secretarySearchInput {
  background: var(--surface-data);
  border: 1px solid var(--hairline);
  font-family: var(--font-mono); font-size: var(--fs-sm);
}
.app-header--brand #secretarySearchInput:focus {
  background: var(--surface-card);
  border-color: var(--brand-blue);
  box-shadow: var(--focus-ring);
}

/* Header del mapa en pantallas chicas: marca + perfil en una fila, y el filtro
   de secretarías ocupa una segunda fila a todo el ancho. Vence el
   `flex-direction: column !important` genérico de style.css por especificidad. */
@media (max-width: 600px) {
  .app-header.app-header--brand { padding: var(--space-3) var(--space-4); }
  .app-header--brand .index-header-container {
    flex-direction: row !important;
    flex-wrap: wrap;
    align-items: center !important;
    justify-content: space-between !important;
    gap: var(--space-2);
    width: 100%;
  }
  .app-header--brand .header-center { flex-basis: 100%; order: 3; }
  .app-header--brand .pet-name { max-width: 52vw; }
  /* el input del filtro (ancho fijo 350px seteado por JS) pasa a fluido */
  .app-header--brand #secretarySelectContainer { width: 100%; }
  #secretarySelectWrapper { width: 100% !important; max-width: 100% !important; }
  .app-header--brand #secretarySearchInput {
    flex: 1 1 auto; width: auto !important; min-width: 0; box-sizing: border-box;
  }
}

/* ============================================================================
   Resumen de flota (chips de estado sobre el mapa)
   ============================================================================ */
.fleet-summary {
  position: absolute;
  top: var(--space-4);
  left: 50%;
  transform: translateX(-50%) translateY(-10px);
  z-index: 600;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  max-width: min(94vw, 720px);
  gap: var(--space-1);
  padding: 6px;
  background: color-mix(in srgb, var(--console-bg) 94%, transparent);
  backdrop-filter: saturate(1.2) blur(8px);
  -webkit-backdrop-filter: saturate(1.2) blur(8px);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-md);
  box-shadow: var(--console-shadow);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-base) var(--ease-standard),
    transform var(--dur-slow) var(--ease-emphasized);
}
.fleet-summary.is-visible { opacity: 1; transform: translateX(-50%) translateY(0); pointer-events: auto; }
/* cada estado es un chip discreto → envuelve limpio en cualquier ancho */
.fleet-summary .fleet-stat {
  display: inline-flex; align-items: center; gap: var(--space-2);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
  background: var(--surface-data);
  border: 1px solid var(--hairline);
  font-size: var(--fs-xs); font-weight: var(--fw-semibold);
  text-transform: uppercase; letter-spacing: .03em;
  color: var(--text-muted);
  white-space: nowrap;
}
.fleet-summary .fleet-stat b {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: var(--fs-base); font-weight: var(--fw-bold);
  color: var(--text-primary); line-height: 1;
}
@media (max-width: 600px) {
  .fleet-summary {
    top: var(--space-3);
    padding: var(--space-2) var(--space-3);
    column-gap: var(--space-3); row-gap: var(--space-1);
    max-width: calc(100vw - var(--space-4));
  }
  /* en teléfono cada estado es una unidad compacta (sin pastilla propia) para
     que entren de a varios por fila y solo bajen de línea si no caben */
  .fleet-summary .fleet-stat {
    background: transparent; border: 0; padding: 0;
    font-size: 11px; gap: 5px; letter-spacing: 0;
  }
  .fleet-summary .fleet-stat b { font-size: var(--fs-sm); }
  .fleet-summary .fleet-stat:last-child { display: none; } /* "total" se omite en pantallas chicas */
}
/* pantallas muy chicas: compactar aún más para mantenerlos lado a lado */
@media (max-width: 380px) {
  .fleet-summary .fleet-stat { font-size: 10px; gap: 4px; }
  .fleet-summary { column-gap: var(--space-2); }
}

/* ---- Comportamiento táctil global de controles ---- */
button, a, [role="button"], input, select, label, .nav-item {
  touch-action: manipulation;
}

/* ---- Botones primarios (marca) ---- */
.login-button,
.accept-button,
.add-device-btn,
.add-button,
.header-button.primary,
button[type="submit"]:not(.toggle-pass):not(.show-password) {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 44px;
  padding: var(--space-3) var(--space-5);
  background: var(--brand-gradient);
  color: var(--text-on-brand);
  border: none;
  border-radius: var(--radius-md);
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  font-weight: var(--fw-semibold);
  line-height: 1;
  cursor: pointer;
  transition: filter var(--dur-fast) var(--ease-standard),
    box-shadow var(--dur-fast) var(--ease-standard),
    transform var(--dur-fast) var(--ease-standard);
}

.login-button:hover,
.accept-button:hover,
.add-device-btn:hover,
.add-button:hover,
.header-button.primary:hover,
button[type="submit"]:not(.toggle-pass):not(.show-password):hover {
  filter: brightness(1.05);
  box-shadow: var(--shadow-brand);
  transform: translateY(-1px);
}

.login-button:active,
.accept-button:active,
.add-device-btn:active,
.add-button:active,
.header-button.primary:active,
button[type="submit"]:not(.toggle-pass):not(.show-password):active {
  transform: translateY(0);
  filter: brightness(0.97);
}

.login-button:disabled,
.accept-button:disabled,
button[type="submit"]:disabled {
  opacity: .55;
  filter: grayscale(.3);
  cursor: not-allowed;
  box-shadow: none;
  transform: none;
}

/* ---- Botones secundarios / ghost ---- */
.edit-btn,
.btn--ghost {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  background: transparent;
  color: var(--color-primary);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  font-family: var(--font-sans);
  font-weight: var(--fw-medium);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-standard),
    border-color var(--dur-fast) var(--ease-standard);
}

.edit-btn:hover,
.btn--ghost:hover {
  background: var(--color-hover);
  border-color: var(--color-primary);
}

/* ---- Botón danger ---- */
.delete-btn,
.btn--danger,
.header-button.danger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  background: var(--color-error);
  color: #fff;
  border: none;
  border-radius: var(--radius-md);
  font-family: var(--font-sans);
  font-weight: var(--fw-medium);
  cursor: pointer;
  transition: filter var(--dur-fast) var(--ease-standard);
}

.delete-btn:hover,
.btn--danger:hover,
.header-button.danger:hover {
  filter: brightness(1.08);
}

/* ---- Inputs / selects / textareas ---- */
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]),
select,
textarea {
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  color: var(--text-primary);
  background: var(--surface-card);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  padding: var(--space-3);
  transition: border-color var(--dur-fast) var(--ease-standard),
    box-shadow var(--dur-fast) var(--ease-standard);
}

input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):focus,
select:focus,
textarea:focus {
  outline: none;
  border-color: var(--brand-blue);
  box-shadow: var(--focus-ring);
}

::placeholder { color: var(--text-muted); opacity: 1; }

/* ---- Notificaciones / toasts ---- */
.notification-container {
  position: fixed;
  top: var(--space-4);
  right: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  z-index: var(--z-toast);
  max-width: min(92vw, 380px);
}

.notification {
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  background: var(--surface-card);
  color: var(--text-primary);
  box-shadow: var(--shadow-lg);
  border: 1px solid var(--border-subtle);
  border-left: 4px solid var(--color-info);
  animation: slideIn var(--dur-base) var(--ease-standard);
}

.notification.success { border-left-color: var(--color-success); }
.notification.error { border-left-color: var(--color-error); }
.notification.fade-out { animation: fadeOut var(--dur-base) var(--ease-standard) forwards; }

/* ---- Foco visible global ---- */
:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--radius-sm);
}

/* ---- Utilidad accesible: oculto visualmente, visible para lectores ---- */
.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0);
  white-space: nowrap; border: 0;
}

/* ---- Scrollbars ---- */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--color-scrollbar-thumb) var(--color-scrollbar-track);
}
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
  background: var(--border-strong);
  border-radius: var(--radius-pill);
  border: 2px solid transparent;
  background-clip: content-box;
}

/* ============================================================================
   COMPONENTES NUEVOS (reutilizables) — telemetría, estado, datos densos
   ============================================================================ */

/* ---- Chip / badge genérico ---- */
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 3px var(--space-2);
  border-radius: var(--radius-pill);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  line-height: 1.4;
  white-space: nowrap;
  background: var(--surface-sunken);
  color: var(--text-secondary);
  border: 1px solid var(--border-subtle);
}
.chip i { font-size: .9em; }
.chip--moving  { background: var(--color-success-bg); color: var(--color-success); border-color: transparent; }
.chip--idle    { background: var(--color-warning-bg); color: var(--color-warning); border-color: transparent; }
.chip--alarm   { background: var(--color-error-bg);   color: var(--color-error);   border-color: transparent; }
.chip--live    { background: var(--color-info-bg);    color: var(--accent-teal);   border-color: transparent; }
.chip--offline { background: var(--surface-sunken);   color: var(--status-offline); }

/* ---- Status dot (siempre acompañado de texto) ---- */
.status-dot {
  position: relative;
  width: 9px; height: 9px; border-radius: 50%;
  display: inline-block; flex-shrink: 0;
  background: var(--status-offline);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--status-offline) 22%, transparent);
}
.status-dot--live    { background: var(--status-live);   box-shadow: 0 0 0 3px color-mix(in srgb, var(--status-live) 22%, transparent); }
.status-dot--moving  { background: var(--status-moving); box-shadow: 0 0 0 3px color-mix(in srgb, var(--status-moving) 22%, transparent); }
.status-dot--idle    { background: var(--status-idle);   box-shadow: 0 0 0 3px color-mix(in srgb, var(--status-idle) 22%, transparent); }
.status-dot--alarm   { background: var(--status-alarm);  box-shadow: 0 0 0 3px color-mix(in srgb, var(--status-alarm) 22%, transparent); }
/* anillo de pulso para estados "vivos" (en marcha / en vivo / alarma) */
.status-dot--moving::after,
.status-dot--live::after,
.status-dot--alarm::after {
  content: ""; position: absolute; inset: 0; border-radius: 50%;
  pointer-events: none; color: var(--pulse-color);
  animation: dotPulse 1.8s var(--ease-standard) infinite;
}
.status-dot--moving { --pulse-color: var(--status-moving); }
.status-dot--live   { --pulse-color: var(--status-live); }
.status-dot--alarm  { --pulse-color: var(--status-alarm); }
.status-pill {
  display: inline-flex; align-items: center; gap: var(--space-2);
  font-size: var(--fs-sm); font-weight: var(--fw-medium); color: var(--text-secondary);
}

/* ---- Tarjeta de métrica / stat (bloque de dato inset, lectura de consola) ---- */
.metric-card {
  background: var(--surface-data);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  position: relative;
  overflow: hidden;
}
.metric-card::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--accent-teal); opacity: .5;
}
.metric-card__label {
  display: flex; align-items: center; gap: var(--space-2);
  font-size: 10px; font-weight: var(--fw-semibold);
  text-transform: uppercase; letter-spacing: .08em;
  color: var(--text-muted); margin: 0 0 var(--space-1);
}
.metric-card__label i { color: var(--accent-teal); font-size: 11px; }
.metric-card__value {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: var(--fs-2xl); font-weight: var(--fw-bold);
  color: var(--text-primary); line-height: 1.05; letter-spacing: -.01em;
}
.metric-card__value small { font-size: var(--fs-base); color: var(--text-muted); font-weight: var(--fw-medium); }
.metric-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--space-3);
}

/* ---- Fila de dato (label : valor) ---- */
.data-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-3); padding: var(--space-2) 0;
  border-bottom: 1px solid var(--border-subtle);
}
.data-row:last-child { border-bottom: 0; }
.data-row__label { display: flex; align-items: center; gap: var(--space-2); color: var(--text-muted); font-size: var(--fs-sm); }
.data-row__value { font-family: var(--font-mono); font-variant-numeric: tabular-nums; color: var(--text-primary); font-weight: var(--fw-medium); }

/* ---- Indicador de señal GSM (barras discretas) ---- */
.signal-bars { display: inline-flex; align-items: flex-end; gap: 2px; height: 16px; }
.signal-bars i {
  display: block; width: 4px; border-radius: 1px;
  background: var(--border-strong);
}
.signal-bars i:nth-child(1) { height: 25%; }
.signal-bars i:nth-child(2) { height: 50%; }
.signal-bars i:nth-child(3) { height: 75%; }
.signal-bars i:nth-child(4) { height: 100%; }
.signal-bars[data-level="0"] i { background: var(--status-offline); opacity: .4; }
.signal-bars[data-level="1"] i:nth-child(-n+1) { background: var(--status-alarm); }
.signal-bars[data-level="2"] i:nth-child(-n+2) { background: var(--status-idle); }
.signal-bars[data-level="3"] i:nth-child(-n+3) { background: var(--status-moving); }
.signal-bars[data-level="4"] i:nth-child(-n+4) { background: var(--status-moving); }

/* ---- Ignición chip ---- */
.ignition { display: inline-flex; align-items: center; gap: var(--space-2); font-weight: var(--fw-semibold); font-size: var(--fs-sm); }
.ignition--on  { color: var(--status-moving); }
.ignition--off { color: var(--status-offline); }

/* ---- Sparkline (contenedor SVG) ---- */
.sparkline { display: block; width: 100%; height: 36px; }
.sparkline path { fill: none; stroke: var(--accent-teal); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.sparkline .spark-area { fill: color-mix(in srgb, var(--accent-teal) 14%, transparent); stroke: none; }

/* ---- Panel de telemetría flotante (sobre el mapa) — instrumento de consola ---- */
.telemetry-panel {
  background: var(--console-bg);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-lg);
  box-shadow: var(--console-shadow);
  overflow: hidden;
  position: relative;
  display: flex;
  flex-direction: column;
  max-height: 100%;
}
/* barra de acento superior (color según estado, vía --tp-accent) */
.telemetry-panel::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 3px;
  background: var(--tp-accent, var(--accent-teal));
}
.telemetry-panel__header {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-4) var(--space-4) var(--space-3);
  border-bottom: 1px solid var(--hairline);
  background: var(--surface-data);
  flex-shrink: 0;
}
.telemetry-panel__body {
  padding: var(--space-4); display: flex; flex-direction: column; gap: var(--space-3);
  overflow-y: auto; min-height: 0;   /* permite scroll interno en pantallas bajas */
}
/* etiqueta de sección dentro del panel */
.tp-section-label {
  font-size: 10px; font-weight: var(--fw-bold); text-transform: uppercase;
  letter-spacing: .1em; color: var(--text-muted);
  font-family: var(--font-mono);
  display: flex; align-items: center; gap: var(--space-2);
}
.tp-section-label::after { content: ""; flex: 1; height: 1px; background: var(--hairline); }

/* ---- Tablas densas ---- */
.data-table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.data-table thead th {
  position: sticky; top: 0; z-index: 1;
  background: var(--surface-sunken);
  color: var(--text-secondary);
  font-weight: var(--fw-semibold); text-align: left;
  padding: var(--space-3); white-space: nowrap;
  border-bottom: 1px solid var(--border-strong);
}
.data-table tbody td { padding: var(--space-3); border-bottom: 1px solid var(--border-subtle); color: var(--text-primary); }
.data-table tbody tr:hover { background: var(--color-hover); }

/* ---- Skeleton de carga ---- */
.skeleton {
  background: linear-gradient(90deg, var(--surface-sunken) 25%, var(--surface-raised) 37%, var(--surface-sunken) 63%);
  background-size: 400% 100%;
  border-radius: var(--radius-sm);
  animation: skeleton-shimmer 1.4s ease infinite;
}
@keyframes skeleton-shimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }

/* ---- Toggle switch (notificaciones, perfil, usuarios) ---- */
.toggle-switch { position: relative; display: inline-block; width: 44px; height: 24px; }
.toggle-switch input { opacity: 0; width: 0; height: 0; }
.toggle-slider {
  position: absolute; inset: 0; cursor: pointer;
  background: var(--border-strong); border-radius: var(--radius-pill);
  transition: background var(--dur-base) var(--ease-standard);
}
.toggle-slider::before {
  content: ""; position: absolute; height: 18px; width: 18px; left: 3px; top: 3px;
  background: #fff; border-radius: 50%; box-shadow: var(--shadow-sm);
  transition: transform var(--dur-base) var(--ease-standard);
}
.toggle-switch input:checked + .toggle-slider { background: var(--color-primary); }
.toggle-switch input:checked + .toggle-slider::before { transform: translateX(20px); }
.toggle-switch input:focus-visible + .toggle-slider { box-shadow: var(--focus-ring); }

/* ============================================================================
   MAPA (Leaflet) — theming con tokens + panel de telemetría
   ============================================================================ */

/* Marcador de vehículo — nodo de contacto (color por secretaría vía --c) */
.veh-marker { will-change: transform; }
.veh-marker .vm-pin {
  width: 24px; height: 24px; border-radius: 50%;
  background: radial-gradient(circle at 34% 30%,
    color-mix(in srgb, var(--c, var(--brand-blue)) 72%, #fff),
    var(--c, var(--brand-blue)) 76%);
  border: 3px solid #fff;
  box-shadow: 0 2px 7px -1px rgba(16,24,40,.45), 0 0 0 1px rgba(16,24,40,.10);
  position: relative; box-sizing: border-box;
  display: grid; place-items: center;
  transition: transform var(--dur-fast) var(--ease-emphasized),
    box-shadow var(--dur-fast) var(--ease-standard);
  animation: markerIn .42s var(--ease-emphasized) both;
}
.veh-marker .vm-pin::before { /* punto de contacto interno (target) */
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: #fff; opacity: .92;
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--c, var(--brand-blue)) 40%, transparent);
}
.veh-marker:hover .vm-pin { transform: scale(1.12); }

/* Vehículo EN MARCHA — halo verde pulsante para distinguirlo de un vistazo
   en la vista de toda la flota. Respaldo estático (núcleo verde) para cuando
   el usuario tiene prefers-reduced-motion y el pulso queda anulado. */
.veh-marker.is-moving { z-index: 700; }
.veh-marker.is-moving .vm-pin {
  animation: markerIn .42s var(--ease-emphasized) both,
             movingPulse 1.5s var(--ease-standard) .42s infinite;
}
.veh-marker.is-moving .vm-pin::before {
  background: var(--status-moving);
  box-shadow: 0 0 0 1.5px #fff;
}

/* SIN ACTIVIDAD (última posición < 7 días, dormido reciente) — leve atenuación */
.veh-marker.is-inactive .vm-pin { opacity: .82; }
/* SIN SEÑAL (última posición ≥ 7 días) — claramente atenuado y grisado */
.veh-marker.is-offline .vm-pin { opacity: .42; filter: grayscale(.65); }
.veh-marker.is-offline { z-index: 400; }

.veh-marker.is-selected { z-index: 1000 !important; }
/* el seleccionado siempre se ve nítido aunque esté inactivo/sin señal */
.veh-marker.is-selected .vm-pin { opacity: 1; filter: none; }
.veh-marker.is-selected .vm-pin {
  transform: scale(1.2);
  border-color: var(--accent-teal);
  box-shadow: var(--glow-live-soft), 0 3px 10px -1px rgba(16,24,40,.5);
}
.veh-marker.is-selected .vm-pin::after { /* anillo de barrido del seleccionado */
  content: ""; position: absolute; inset: -7px; border-radius: 50%;
  border: 2px solid var(--accent-teal); opacity: .9;
  animation: markerRing 1.7s var(--ease-standard) infinite;
}

/* Popups Leaflet */
.leaflet-popup-content-wrapper {
  background: var(--console-bg);
  color: var(--text-primary);
  border-radius: var(--radius-md);
  box-shadow: var(--console-shadow);
  border: 1px solid var(--hairline);
  padding: 0; overflow: hidden;
}
.leaflet-popup-content { margin: 0; font-family: var(--font-sans); width: 232px !important; max-width: calc(100vw - 48px) !important; }
.leaflet-popup-tip { background: var(--console-bg); box-shadow: var(--shadow-md); }
.leaflet-popup-close-button { color: var(--text-muted) !important; z-index: 2; }
.leaflet-popup-content .popup { font-family: var(--font-sans); font-size: var(--fs-sm); line-height: 1.5; }
.leaflet-popup-content .popup strong { color: var(--text-primary); font-size: var(--fs-base); }

/* Popup estructurado de vehículo (consola) */
.veh-popup { font-family: var(--font-sans); color: var(--text-primary); }
.veh-popup .vp-head {
  display: flex; flex-direction: column; gap: 1px;
  padding: var(--space-3) var(--space-4) var(--space-2);
  border-bottom: 1px solid var(--hairline);
  background: var(--surface-data);
  position: relative;
}
.veh-popup .vp-head::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--accent-teal);
}
.veh-popup .vp-plate {
  font-family: var(--font-mono); font-weight: var(--fw-bold);
  font-size: var(--fs-lg); letter-spacing: .02em; color: var(--text-primary);
}
.veh-popup .vp-veh {
  font-size: var(--fs-xs); color: var(--text-muted);
  text-transform: uppercase; letter-spacing: .06em;
}
.veh-popup .vp-grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 1px;
  background: var(--hairline);
}
.veh-popup .vp-cell {
  background: var(--console-bg);
  padding: var(--space-2) var(--space-4);
  display: flex; flex-direction: column; gap: 2px;
}
.veh-popup .vp-cell .vp-k {
  display: flex; align-items: center; gap: 6px;
  font-size: 10px; text-transform: uppercase; letter-spacing: .07em;
  color: var(--text-muted); font-weight: var(--fw-semibold);
}
.veh-popup .vp-cell .vp-k i { color: var(--accent-teal); font-size: 10px; }
.veh-popup .vp-cell .vp-v {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: var(--fs-base); font-weight: var(--fw-semibold); color: var(--text-primary);
}
.veh-popup .vp-cell .vp-v small { font-size: var(--fs-xs); color: var(--text-muted); font-weight: var(--fw-regular); }
.veh-popup .vp-coords {
  display: flex; align-items: center; gap: 6px;
  padding: var(--space-2) var(--space-4);
  border-top: 1px solid var(--hairline);
  font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--text-secondary);
}
.veh-popup .vp-coords i { color: var(--accent-teal); }

/* Portada con FOTO del vehículo (datos sobre la foto con fondo etiqueta) */
.veh-popup .vp-cover {
  position: relative;
  height: 126px;
  background: var(--surface-data) center/cover no-repeat;
  border-bottom: 1px solid var(--hairline);
  cursor: pointer;
  overflow: hidden;
}
.veh-popup .vp-cover--empty {
  cursor: default;
  background: linear-gradient(135deg, var(--surface-data), var(--brand-blue-wash));
}
.veh-popup .vp-cover__ico {
  position: absolute; top: 38%; left: 50%; transform: translate(-50%, -50%);
  color: color-mix(in srgb, var(--brand-blue) 42%, transparent); font-size: 40px;
}
.veh-popup .vp-cover__scrim {
  position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(10,16,24,.82) 0%, rgba(10,16,24,.30) 44%, rgba(10,16,24,0) 74%);
}
.veh-popup .vp-cover__labels {
  position: absolute; left: var(--space-3); right: var(--space-3); bottom: var(--space-2);
  display: flex; flex-direction: column; gap: 4px; align-items: flex-start;
  max-width: calc(100% - var(--space-5));
}
.veh-popup .vp-cover .vp-plate {
  font-family: var(--font-mono); font-weight: var(--fw-bold); font-size: var(--fs-base);
  letter-spacing: .03em; color: #fff; line-height: 1.3;
  background: rgba(10,16,24,.72); -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
  padding: 2px 8px; border-radius: var(--radius-sm); max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.veh-popup .vp-cover .vp-veh {
  font-family: var(--font-mono); font-size: 10px; text-transform: uppercase; letter-spacing: .06em;
  color: #fff; line-height: 1.4;
  background: rgba(10,16,24,.62); -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
  padding: 1px 7px; border-radius: var(--radius-sm); max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.veh-popup .vp-zoom {
  position: absolute; top: var(--space-2); right: var(--space-2);
  width: 26px; height: 26px; display: grid; place-items: center;
  background: rgba(10,16,24,.55); color: #fff; border-radius: var(--radius-sm);
  font-size: 12px; -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
  transition: background var(--dur-fast) var(--ease-standard);
}
.veh-popup .vp-cover:hover .vp-zoom { background: rgba(10,16,24,.85); }

/* Lightbox: foto del vehículo en pantalla completa */
.photo-lightbox {
  position: fixed; inset: 0; z-index: var(--z-toast);
  display: flex; align-items: center; justify-content: center;
  padding: var(--space-5);
  background: rgba(8,12,18,.86); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
  animation: modalFade var(--dur-base) var(--ease-standard);
}
.photo-lightbox[hidden] { display: none; }
.photo-lightbox__img {
  max-width: min(96vw, 1100px); max-height: 88vh;
  border-radius: var(--radius-md); box-shadow: var(--shadow-xl);
  border: 1px solid rgba(255,255,255,.14); background: #0b1018;
  object-fit: contain; animation: modalPop var(--dur-base) var(--ease-emphasized);
}
.photo-lightbox__close {
  position: absolute; top: var(--space-4); right: var(--space-4);
  width: 44px; height: 44px; border-radius: 50%;
  background: rgba(255,255,255,.12); color: #fff; border: 1px solid rgba(255,255,255,.28);
  font-size: 24px; line-height: 1; cursor: pointer; display: grid; place-items: center;
  transition: background var(--dur-fast) var(--ease-standard);
}
.photo-lightbox__close:hover { background: rgba(255,255,255,.24); }

/* Campo de subida de foto (modal editar / alta de vehículo) */
.photo-field { display: flex; gap: var(--space-3); align-items: center; flex-wrap: wrap; }
.photo-field__preview {
  width: 104px; height: 76px; object-fit: cover; display: none;
  border-radius: var(--radius-md); border: 1px solid var(--border-subtle);
  background: var(--surface-data);
}
.photo-field__actions { display: flex; gap: var(--space-2); align-items: center; flex-wrap: wrap; }
.photo-field__btn {
  display: inline-flex; align-items: center; gap: var(--space-2);
  padding: 8px var(--space-4); border-radius: var(--radius-md);
  background: var(--surface-data); border: 1px solid var(--border-strong);
  color: var(--text-primary); font-size: var(--fs-sm); font-weight: var(--fw-medium);
  cursor: pointer; transition: background var(--dur-fast) var(--ease-standard), border-color var(--dur-fast) var(--ease-standard);
}
.photo-field__btn:hover { background: var(--color-hover); border-color: var(--brand-blue); }
.photo-field__btn i { color: var(--brand-blue); }
.photo-field__clear {
  background: transparent; border: 0; color: var(--color-error);
  font-size: var(--fs-sm); cursor: pointer; padding: 6px 8px;
}
.photo-field__clear[hidden] { display: none; }

/* Controles Leaflet — botones de consola */

/* Controles Leaflet (zoom, etc.) — botones de instrumento */
.leaflet-bar {
  border: 1px solid var(--hairline) !important;
  border-radius: var(--radius-md) !important;
  box-shadow: var(--console-shadow) !important;
  overflow: hidden;
}
.leaflet-bar a {
  background: var(--console-bg);
  color: var(--text-secondary);
  border-color: var(--hairline) !important;
  font-weight: var(--fw-semibold);
  transition: background var(--dur-fast) var(--ease-standard), color var(--dur-fast) var(--ease-standard);
}
.leaflet-bar a:hover { background: var(--surface-data); color: var(--brand-blue); }
.leaflet-control-attribution {
  background: color-mix(in srgb, var(--console-bg) 90%, transparent) !important;
  color: var(--text-muted) !important;
  font-size: 10px;
}
.leaflet-control-attribution a { color: var(--brand-blue-soft) !important; }

/* Zoom reubicado abajo-derecha: elevarlo sobre la barra de navegación inferior */
.leaflet-bottom.leaflet-right { bottom: var(--space-6); right: var(--space-2); }
@media (max-width: 600px) { .leaflet-bottom.leaflet-right { bottom: var(--space-5); } }

/* Basemap que acompaña el tema oscuro (tiles atenuados/invertidos) */
[data-theme="dark"] .leaflet-tile-pane {
  filter: brightness(.78) contrast(1.06) hue-rotate(180deg) invert(1);
}

/* Panel de telemetría flotante sobre el mapa */
#telemetryPanel {
  position: absolute;
  left: var(--space-4);
  bottom: var(--space-6);   /* despeja la barra de navegación inferior fija */
  width: min(340px, calc(100vw - var(--space-8)));
  max-height: calc(100% - var(--space-8));
  z-index: 600;
  opacity: 0;
  transform: translateY(12px);
  pointer-events: none;
  transition: opacity var(--dur-base) var(--ease-standard),
    transform var(--dur-base) var(--ease-emphasized);
}
#telemetryPanel.is-visible { opacity: 1; transform: translateY(0); pointer-events: auto; }
#telemetryPanel .tp-title { font-family: var(--font-mono); font-weight: var(--fw-bold); font-size: var(--fs-lg); letter-spacing: .02em; color: var(--text-primary); line-height: 1.15; }
#telemetryPanel .tp-sub { font-size: var(--fs-xs); color: var(--text-muted); text-transform: uppercase; letter-spacing: .05em; }
#telemetryPanel .tp-close {
  margin-left: auto; background: transparent; border: none; cursor: pointer;
  color: var(--text-muted); font-size: 18px; line-height: 1;
  width: 28px; height: 28px; display: grid; place-items: center;
  border-radius: var(--radius-sm); align-self: flex-start;
}
#telemetryPanel .tp-close:hover { background: var(--color-hover); color: var(--text-primary); }
/* Lectura de velocidad — protagonista mono con glow al estar en marcha */
#telemetryPanel .tp-speed {
  display: flex; align-items: baseline; gap: var(--space-2);
  background: var(--surface-data); border: 1px solid var(--hairline);
  border-radius: var(--radius-md); padding: var(--space-3) var(--space-4);
}
#telemetryPanel .tp-speed b {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: 34px; font-weight: var(--fw-bold); color: var(--text-primary);
  line-height: 1; letter-spacing: -.02em;
}
#telemetryPanel .tp-speed.is-moving b { color: var(--status-moving); text-shadow: 0 0 16px color-mix(in srgb, var(--status-moving) 45%, transparent); }
#telemetryPanel .tp-speed span { font-size: var(--fs-sm); color: var(--text-muted); font-family: var(--font-mono); }

@media (max-width: 600px) {
  #telemetryPanel {
    left: var(--space-3); right: var(--space-3);
    bottom: calc(var(--space-5) + 4px);   /* despeja la nav inferior en mobile */
    width: auto;
    max-height: calc(100% - var(--space-6));
  }
}

/* ============================================================================
   Animaciones de consola — pulso en vivo, entrada de markers, reveal de carga
   (todas se anulan vía el bloque prefers-reduced-motion de tokens.css)
   ============================================================================ */
@keyframes livePulse {
  0%   { box-shadow: 0 0 0 0   color-mix(in srgb, var(--accent-teal) 55%, transparent); }
  70%  { box-shadow: 0 0 0 7px color-mix(in srgb, var(--accent-teal) 0%, transparent); }
  100% { box-shadow: 0 0 0 0   color-mix(in srgb, var(--accent-teal) 0%, transparent); }
}
@keyframes dotPulse {
  0%   { box-shadow: 0 0 0 0   currentColor; opacity: .55; }
  70%  { box-shadow: 0 0 0 8px transparent; opacity: 0; }
  100% { box-shadow: 0 0 0 0   transparent; opacity: 0; }
}
@keyframes markerIn {
  0%   { opacity: 0; transform: scale(.2) translateY(-6px); }
  60%  { opacity: 1; transform: scale(1.08); }
  100% { opacity: 1; transform: scale(1); }
}
@keyframes markerRing {
  0%   { transform: scale(.85); opacity: .9; }
  70%  { transform: scale(1.5); opacity: 0; }
  100% { transform: scale(1.5); opacity: 0; }
}
@keyframes movingPulse {
  0% {
    box-shadow: 0 2px 7px -1px rgba(16,24,40,.45), 0 0 0 1px rgba(16,24,40,.10),
      0 0 0 0 color-mix(in srgb, var(--status-moving) 65%, transparent);
  }
  70% {
    box-shadow: 0 2px 7px -1px rgba(16,24,40,.45), 0 0 0 1px rgba(16,24,40,.10),
      0 0 0 11px color-mix(in srgb, var(--status-moving) 0%, transparent);
  }
  100% {
    box-shadow: 0 2px 7px -1px rgba(16,24,40,.45), 0 0 0 1px rgba(16,24,40,.10),
      0 0 0 0 color-mix(in srgb, var(--status-moving) 0%, transparent);
  }
}
@keyframes consoleReveal {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes mapReveal {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* Reveal de carga escalonado (CSS puro, corre una vez al pintar) */
.app-header.app-header--brand { animation: consoleReveal .5s var(--ease-emphasized) both; }
.map-container #map { animation: mapReveal .8s var(--ease-standard) both; animation-delay: .08s; }
