/* ══════════════════════════════════════════════════════════════════════════
   mapa.css — el portal del Mapa PMT.

   Lo sostienen dos reglas, y la primera es de seguridad, no de estética:

   1. LO REAL Y LO SIMULADO NO COMPARTEN NI UN COLOR. Un mapa público que
      muestra posiciones de agentes tiene que ser imposible de confundir con un
      sistema operativo. Lo real usa la paleta de ONDA; lo simulado usa un tono
      propio que no aparece en ninguna otra parte del sistema, y lo lleva en el
      borde, en la insignia y en el punto de cada capa.

   2. NINGUNA DURACIÓN LITERAL (sistema de diseño, regla 2). Todas salen de
      --onda-dur-*, que es lo que permite que prefers-reduced-motion apague el
      movimiento desde un solo lugar.

   El tono de «simulado» es local a propósito: el sistema de diseño no tiene un
   color para «sintético», y su regla 4 pide un segundo consumidor real antes de
   promover nada. El día que otro proyecto necesite distinguir dato simulado de
   dato real, este par de valores sube a tokens/onda.css.
   ══════════════════════════════════════════════════════════════════════════ */

:root {
  --pmt-sim:          #8b5cf6;
  --pmt-sim-fuerte:   #6d28d9;
  --pmt-sim-suave:    #f5f3ff;
  --pmt-sim-contorno: rgb(139 92 246 / 0.28);

  /* Jerarquía vial. Un gradiente de un solo tono: la jerarquía es una escala,
     no cinco categorías sin relación. */
  --pmt-via-1: #334155;   /* autopista y troncal */
  --pmt-via-2: #1e3a8a;   /* primaria */
  --pmt-via-3: #2563eb;   /* secundaria */
  --pmt-via-4: #60a5fa;   /* terciaria */
  --pmt-via-5: #9aa1ac;   /* vecinal */

  --pmt-alto-barra: 3.25rem;
  --pmt-ancho-panel: 21rem;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-tema="claro"]) {
    --pmt-sim:          #a78bfa;
    --pmt-sim-fuerte:   #c4b5fd;
    --pmt-sim-suave:    #2e1065;
    --pmt-sim-contorno: rgb(167 139 250 / 0.35);

    --pmt-via-1: #e2e8f0;
    --pmt-via-2: #93c5fd;
    --pmt-via-3: #60a5fa;
    --pmt-via-4: #3b82f6;
    --pmt-via-5: #6b7280;
  }
}

:root[data-tema="oscuro"] {
  --pmt-sim:          #a78bfa;
  --pmt-sim-fuerte:   #c4b5fd;
  --pmt-sim-suave:    #2e1065;
  --pmt-sim-contorno: rgb(167 139 250 / 0.35);

  --pmt-via-1: #e2e8f0;
  --pmt-via-2: #93c5fd;
  --pmt-via-3: #60a5fa;
  --pmt-via-4: #3b82f6;
  --pmt-via-5: #6b7280;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  overflow: hidden;
  font-family: var(--onda-fuente-sans);
  font-size: var(--onda-texto-base);
  color: var(--onda-texto);
  background: var(--onda-fondo);
  -webkit-text-size-adjust: 100%;
}

/* ───────────────────────────── el mapa ──────────────────────────────── */

#mapa {
  position: fixed;
  inset: 0;
  background: var(--onda-fondo);
  z-index: var(--onda-z-base);
}

/* Leaflet trae su propia tipografía y sus propios colores. Se los quitamos
   acá en vez de parchear leaflet.css, que es una copia de la biblioteca y se
   reemplaza al actualizar. */
.leaflet-container { font-family: var(--onda-fuente-sans); background: var(--onda-fondo); }

/* LOS CONTROLES DE ABAJO SUBEN POR ENCIMA DE LA BARRA.
   El mapa ocupa la pantalla entera, así que la esquina inferior derecha de
   Leaflet —el zoom y LA ATRIBUCIÓN— quedaba debajo de la barra del reloj. El
   zoom tapado es una molestia; la atribución tapada es un problema de
   licencia: los datos son ODbL y el crédito tiene que verse. */
.leaflet-bottom {
  bottom: calc(var(--pmt-alto-barra) + env(safe-area-inset-bottom, 0px));
}
.leaflet-control-attribution {
  background: color-mix(in srgb, var(--onda-panel) 88%, transparent) !important;
  color: var(--onda-tenue) !important;
  font-size: var(--onda-texto-2xs) !important;
  padding: 1px var(--onda-esp-2) !important;
  border-radius: var(--onda-radio-sm) 0 0 0;
}
.leaflet-control-attribution a { color: var(--onda-tenue) !important; }
.leaflet-bar { border: none !important; box-shadow: var(--onda-sombra-flotante, 0 2px 8px rgb(16 20 26 / 0.16)) !important; }
.leaflet-bar a {
  background: var(--onda-panel) !important;
  color: var(--onda-texto) !important;
  border-bottom-color: var(--onda-borde) !important;
  width: 30px !important; height: 30px !important; line-height: 30px !important;
}
.leaflet-bar a:hover { background: var(--onda-panel-hover) !important; }

/* EL ASPECTO DEL MAPA BASE SE HACE ACA, con un filtro sobre las teselas
   estandar de OpenStreetMap. Es lo que reemplaza a un proveedor de mapas base
   con API key: una sola fuente de teselas, cuatro lecturas.

   El filtro se aplica SOLO al panel de teselas, nunca a los marcadores: si
   cayera sobre todo el mapa, las patrullas y el calor se irian en gris con el. */
.pmt-teselas-gris  { filter: grayscale(1) contrast(0.82) brightness(1.08); }
.pmt-teselas-color { filter: none; }

:root[data-tema="oscuro"] .pmt-teselas-gris {
  filter: grayscale(1) invert(1) contrast(0.78) brightness(0.92);
}
:root[data-tema="oscuro"] .pmt-teselas-color {
  filter: invert(1) hue-rotate(180deg) brightness(0.92) contrast(0.88) saturate(0.6);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-tema="claro"]) .pmt-teselas-gris {
    filter: grayscale(1) invert(1) contrast(0.78) brightness(0.92);
  }
  :root:not([data-tema="claro"]) .pmt-teselas-color {
    filter: invert(1) hue-rotate(180deg) brightness(0.92) contrast(0.88) saturate(0.6);
  }
}

/* ──────────────────────── superficies flotantes ─────────────────────── */

.tarjeta {
  background: color-mix(in srgb, var(--onda-panel) 94%, transparent);
  backdrop-filter: blur(var(--onda-blur-vidrio));
  -webkit-backdrop-filter: blur(var(--onda-blur-vidrio));
  border: var(--onda-borde-fino) solid var(--onda-borde);
  border-radius: var(--onda-radio-lg);
  box-shadow: 0 6px 24px -8px rgb(var(--onda-tinta) / 0.22),
              0 2px 6px -2px rgb(var(--onda-tinta) / 0.12);
}

/* ───────────────────────────── la marca ─────────────────────────────── */

.marca {
  position: fixed;
  top: var(--onda-esp-3);
  left: var(--onda-esp-3);
  z-index: var(--onda-z-nav);
  display: flex;
  align-items: center;
  gap: var(--onda-esp-3);
  padding: var(--onda-esp-2) var(--onda-esp-3);
}

.marca__escudo {
  width: 1.75rem; height: 1.75rem;
  flex: 0 0 auto;
  color: var(--onda-marca);
}

.marca__texto { display: flex; flex-direction: column; line-height: 1.15; }
.marca__nombre {
  font-size: var(--onda-texto-sm);
  font-weight: var(--onda-peso-fuerte);
  letter-spacing: var(--onda-track-suelto);
  text-transform: uppercase;
}
.marca__lugar { font-size: var(--onda-texto-2xs); color: var(--onda-tenue); }

/* ──────────────────────── aviso de simulación ───────────────────────── */
/* Fijo, no descartable y siempre visible. Es lo que impide que alguien llegue
   al portal por un enlace y lea las patrullas como posiciones reales. */

.aviso-sim {
  position: fixed;
  top: var(--onda-esp-3);
  left: 50%;
  transform: translateX(-50%);
  z-index: var(--onda-z-nav);
  display: flex;
  align-items: center;
  gap: var(--onda-esp-2);
  padding: var(--onda-esp-2) var(--onda-esp-4);
  font-size: var(--onda-texto-xs);
  font-weight: var(--onda-peso-medio);
  color: var(--pmt-sim-fuerte);
  background: color-mix(in srgb, var(--pmt-sim-suave) 92%, transparent);
  border: var(--onda-borde-fino) solid var(--pmt-sim-contorno);
  border-radius: var(--onda-radio-full);
  backdrop-filter: blur(var(--onda-blur-sutil));
  -webkit-backdrop-filter: blur(var(--onda-blur-sutil));
  white-space: nowrap;
  max-width: calc(100vw - var(--onda-esp-6));
  overflow: hidden;
  text-overflow: ellipsis;
}
.aviso-sim__punto {
  width: 7px; height: 7px; flex: 0 0 auto;
  border-radius: var(--onda-radio-full);
  background: var(--pmt-sim);
  animation: latido var(--onda-dur-cine) var(--onda-ease-estandar) infinite alternate;
}
@keyframes latido { from { opacity: 0.35; } to { opacity: 1; } }

/* ───────────────────────── botones flotantes ────────────────────────── */

.acciones {
  position: fixed;
  top: var(--onda-esp-3);
  right: var(--onda-esp-3);
  z-index: var(--onda-z-nav);
  display: flex;
  gap: var(--onda-esp-2);
}

.boton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--onda-esp-2);
  min-height: 2.25rem;
  padding: 0 var(--onda-esp-3);
  font: inherit;
  font-size: var(--onda-texto-xs);
  font-weight: var(--onda-peso-medio);
  color: var(--onda-texto);
  background: color-mix(in srgb, var(--onda-panel) 94%, transparent);
  backdrop-filter: blur(var(--onda-blur-vidrio));
  -webkit-backdrop-filter: blur(var(--onda-blur-vidrio));
  border: var(--onda-borde-fino) solid var(--onda-borde);
  border-radius: var(--onda-radio-md);
  cursor: pointer;
  transition: background var(--onda-dur-rapida) var(--onda-ease-estandar),
              border-color var(--onda-dur-rapida) var(--onda-ease-estandar),
              transform var(--onda-dur-instant) var(--onda-ease-salida);
}
.boton:hover { background: var(--onda-panel); border-color: var(--onda-borde-fuerte); }
.boton:active { transform: scale(0.97); }
.boton:focus-visible { outline: var(--onda-borde-grueso) solid var(--onda-foco); outline-offset: 2px; }
.boton--icono { width: 2.25rem; padding: 0; }
.boton--activo { color: var(--onda-marca); border-color: var(--onda-marca); background: var(--onda-marca-suave); }
.boton svg { width: 1rem; height: 1rem; flex: 0 0 auto; }

/* ─────────────────────────── panel de capas ─────────────────────────── */

.panel {
  position: fixed;
  z-index: var(--onda-z-drawer);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* Escritorio: columna a la izquierda, debajo de la marca. */
@media (min-width: 768px) {
  .panel {
    top: calc(var(--onda-esp-3) + 3.5rem);
    left: var(--onda-esp-3);
    width: var(--pmt-ancho-panel);
    max-height: calc(100vh - var(--pmt-alto-barra) - 5.5rem);
    transform: translateX(0);
    opacity: 1;
    transition: transform var(--onda-dur-normal) var(--onda-ease-expo),
                opacity var(--onda-dur-rapida) var(--onda-ease-estandar);
  }
  .panel[hidden] {
    display: flex;
    transform: translateX(calc(-1 * (var(--pmt-ancho-panel) + var(--onda-esp-4))));
    opacity: 0;
    pointer-events: none;
  }
  .panel__asa { display: none; }
}

/* Teléfono y tableta: hoja desde abajo, que es donde llega el pulgar. */
@media (max-width: 767px) {
  .panel {
    left: 0; right: 0;
    bottom: var(--pmt-alto-barra);
    max-height: 62vh;
    border-radius: var(--onda-radio-xl) var(--onda-radio-xl) 0 0;
    border-bottom: none;
    transform: translateY(0);
    transition: transform var(--onda-dur-normal) var(--onda-ease-expo);
  }
  .panel[hidden] { display: flex; transform: translateY(110%); pointer-events: none; }
  .panel__asa {
    width: 2.25rem; height: 4px;
    margin: var(--onda-esp-2) auto 0;
    flex: 0 0 auto;
    border-radius: var(--onda-radio-full);
    background: var(--onda-borde-fuerte);
  }
}

.panel__cuerpo { overflow-y: auto; overscroll-behavior: contain; padding: var(--onda-esp-2) 0 var(--onda-esp-3); }

.grupo__titulo {
  display: flex;
  align-items: center;
  gap: var(--onda-esp-2);
  padding: var(--onda-esp-3) var(--onda-esp-4) var(--onda-esp-2);
  font-size: var(--onda-texto-2xs);
  font-weight: var(--onda-peso-fuerte);
  letter-spacing: var(--onda-track-amplio);
  text-transform: uppercase;
  color: var(--onda-tenue);
}
.grupo--sim .grupo__titulo { color: var(--pmt-sim-fuerte); }

.insignia {
  padding: 1px var(--onda-esp-2);
  font-size: var(--onda-texto-2xs);
  font-weight: var(--onda-peso-negrita);
  letter-spacing: var(--onda-track-suelto);
  border-radius: var(--onda-radio-xs);
  color: var(--pmt-sim-fuerte);
  background: var(--pmt-sim-suave);
  border: var(--onda-borde-fino) solid var(--pmt-sim-contorno);
}

.grupo__nota {
  padding: 0 var(--onda-esp-4) var(--onda-esp-2);
  font-size: var(--onda-texto-2xs);
  line-height: var(--onda-alto-normal);
  color: var(--onda-tenue);
}

/* Una capa. Toda la fila es el interruptor: en un teléfono, apuntar a una
   casilla de 14 px es una prueba de pulso. */
.capa {
  display: flex;
  align-items: center;
  gap: var(--onda-esp-3);
  width: 100%;
  padding: var(--onda-esp-2) var(--onda-esp-4);
  min-height: 2.5rem;
  font: inherit;
  text-align: left;
  color: inherit;
  background: none;
  border: none;
  border-left: var(--onda-borde-acento) solid transparent;
  cursor: pointer;
  transition: background var(--onda-dur-rapida) var(--onda-ease-estandar),
              border-color var(--onda-dur-rapida) var(--onda-ease-estandar);
}
.capa:hover { background: var(--onda-suave); }
.capa:focus-visible { outline: var(--onda-borde-grueso) solid var(--onda-foco); outline-offset: -2px; }
.capa[aria-pressed="true"] { border-left-color: var(--onda-marca); background: var(--onda-marca-suave); }
.grupo--sim .capa[aria-pressed="true"] { border-left-color: var(--pmt-sim); background: var(--pmt-sim-suave); }

.capa__punto {
  width: 10px; height: 10px; flex: 0 0 auto;
  border-radius: var(--onda-radio-full);
  background: var(--marca-capa, var(--onda-borde-fuerte));
  transition: box-shadow var(--onda-dur-rapida) var(--onda-ease-estandar);
}
.capa[aria-pressed="true"] .capa__punto { box-shadow: 0 0 0 3px color-mix(in srgb, var(--marca-capa) 28%, transparent); }
.capa__punto--linea { width: 14px; height: 3px; border-radius: var(--onda-radio-xs); }

.capa__texto { flex: 1 1 auto; min-width: 0; }
.capa__nombre { display: block; font-size: var(--onda-texto-sm); line-height: 1.25; }
.capa__dato { display: block; font-size: var(--onda-texto-2xs); color: var(--onda-tenue); font-variant-numeric: tabular-nums; }
.capa__estado { flex: 0 0 auto; font-size: var(--onda-texto-2xs); color: var(--onda-tenue); }

/* El hilo de la carga diferida. Una capa de 1 MB tarda, y sin esto parece que
   el toque no hizo nada. */
.capa--cargando .capa__punto { animation: girando var(--onda-dur-lenta) linear infinite; }
@keyframes girando { to { transform: rotate(1turn); } }

/* ──────────────────────── barra inferior / reloj ─────────────────────── */

.barra {
  position: fixed;
  bottom: 0; left: 0; right: 0;
  z-index: var(--onda-z-pegado);
  height: var(--pmt-alto-barra);
  display: flex;
  align-items: center;
  gap: var(--onda-esp-3);
  padding: 0 var(--onda-esp-3);
  background: color-mix(in srgb, var(--onda-panel) 94%, transparent);
  backdrop-filter: blur(var(--onda-blur-vidrio));
  -webkit-backdrop-filter: blur(var(--onda-blur-vidrio));
  border-top: var(--onda-borde-fino) solid var(--onda-borde);
}

.reloj {
  display: flex;
  flex-direction: column;
  line-height: 1.1;
  flex: 0 0 auto;
  font-variant-numeric: tabular-nums;
}
.reloj__hora { font-size: var(--onda-texto-lg); font-weight: var(--onda-peso-semi); }
.reloj__dia { font-size: var(--onda-texto-2xs); color: var(--onda-tenue); text-transform: capitalize; }

.tiempo { flex: 1 1 auto; display: flex; align-items: center; gap: var(--onda-esp-3); min-width: 0; }

/* El deslizador de la hora. Sin apariencia nativa: en Android y en iOS son dos
   piezas distintas y ninguna se parece al resto del portal. */
.tiempo__rango {
  flex: 1 1 auto;
  min-width: 4rem;
  height: 1.5rem;
  margin: 0;
  background: none;
  -webkit-appearance: none;
  appearance: none;
  cursor: pointer;
}
.tiempo__rango::-webkit-slider-runnable-track {
  height: 4px; border-radius: var(--onda-radio-full); background: var(--onda-suave-hover);
}
.tiempo__rango::-moz-range-track {
  height: 4px; border-radius: var(--onda-radio-full); background: var(--onda-suave-hover);
}
.tiempo__rango::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 1.125rem; height: 1.125rem; margin-top: -0.4375rem;
  border-radius: var(--onda-radio-full);
  background: var(--pmt-sim);
  border: var(--onda-borde-grueso) solid var(--onda-panel);
  box-shadow: 0 1px 4px rgb(var(--onda-tinta) / 0.3);
}
.tiempo__rango::-moz-range-thumb {
  width: 1.125rem; height: 1.125rem;
  border: var(--onda-borde-grueso) solid var(--onda-panel);
  border-radius: var(--onda-radio-full);
  background: var(--pmt-sim);
}
.tiempo__rango:focus-visible { outline: var(--onda-borde-grueso) solid var(--onda-foco); outline-offset: 2px; }

.tiempo__etiqueta {
  flex: 0 0 auto;
  font-size: var(--onda-texto-2xs);
  color: var(--onda-tenue);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ──────────────────────────── ficha de detalle ──────────────────────── */

.ficha {
  position: fixed;
  z-index: var(--onda-z-modal);
  padding: var(--onda-esp-4);
  overflow-y: auto;
  transition: transform var(--onda-dur-normal) var(--onda-ease-expo),
              opacity var(--onda-dur-rapida) var(--onda-ease-estandar);
}
@media (min-width: 768px) {
  .ficha {
    top: var(--onda-esp-3); right: var(--onda-esp-3);
    width: 19rem;
    max-height: calc(100vh - var(--pmt-alto-barra) - var(--onda-esp-8) - 3rem);
    margin-top: 3rem;
  }
  .ficha[hidden] { display: block; opacity: 0; transform: translateX(var(--onda-esp-6)); pointer-events: none; }
}
@media (max-width: 767px) {
  .ficha {
    left: var(--onda-esp-2); right: var(--onda-esp-2);
    bottom: calc(var(--pmt-alto-barra) + var(--onda-esp-2));
    max-height: 54vh;
  }
  .ficha[hidden] { display: block; opacity: 0; transform: translateY(var(--onda-esp-6)); pointer-events: none; }
}

.ficha__cerrar {
  position: absolute;
  top: var(--onda-esp-2); right: var(--onda-esp-2);
  width: 1.75rem; height: 1.75rem;
  display: grid; place-items: center;
  font: inherit; line-height: 1;
  color: var(--onda-tenue);
  background: none; border: none; border-radius: var(--onda-radio-sm);
  cursor: pointer;
  transition: background var(--onda-dur-rapida) var(--onda-ease-estandar);
}
.ficha__cerrar:hover { background: var(--onda-suave); color: var(--onda-texto); }

.ficha__tipo {
  font-size: var(--onda-texto-2xs);
  font-weight: var(--onda-peso-fuerte);
  letter-spacing: var(--onda-track-amplio);
  text-transform: uppercase;
  color: var(--onda-tenue);
}
.ficha--sim .ficha__tipo { color: var(--pmt-sim-fuerte); }
.ficha__titulo {
  margin: var(--onda-esp-1) 0 var(--onda-esp-3);
  padding-right: var(--onda-esp-6);
  font-size: var(--onda-texto-xl);
  font-weight: var(--onda-peso-semi);
  line-height: var(--onda-alto-ajustado);
}

.ficha__campos { display: grid; grid-template-columns: auto 1fr; gap: var(--onda-esp-1) var(--onda-esp-3); font-size: var(--onda-texto-xs); }
.ficha__campos dt { color: var(--onda-tenue); }
.ficha__campos dd { margin: 0; font-variant-numeric: tabular-nums; }

.ficha__pie {
  margin-top: var(--onda-esp-3);
  padding-top: var(--onda-esp-3);
  border-top: var(--onda-borde-fino) solid var(--onda-borde);
  font-size: var(--onda-texto-2xs);
  line-height: var(--onda-alto-normal);
  color: var(--onda-tenue);
}

/* ─────────────────────── marcadores e iconos ────────────────────────── */

/* La gorra de un agente. El anillo dice el estado y el tamaño no cambia con
   el zoom: un agente es un agente a cualquier escala. */
.agente {
  position: relative;
  width: 26px; height: 26px;
  display: grid; place-items: center;
}
.agente__disco {
  position: absolute; inset: 0;
  border-radius: var(--onda-radio-full);
  background: var(--pmt-sim);
  border: var(--onda-borde-grueso) solid var(--onda-panel);
  box-shadow: 0 2px 6px rgb(var(--onda-tinta) / 0.35);
  transition: background var(--onda-dur-rapida) var(--onda-ease-estandar);
}
.agente__gorra { position: relative; width: 16px; height: 16px; color: #fff; }
.agente--detenido .agente__disco { background: var(--onda-aviso); }
.agente--intervencion .agente__disco { background: var(--onda-peligro); }
.agente--fijo .agente__disco { background: var(--pmt-sim-fuerte); }

/* El halo de quien está interviniendo. Es un bucle, así que
   prefers-reduced-motion lo apaga entero (regla 3 del sistema). */
.agente--intervencion::before {
  content: "";
  position: absolute; inset: -6px;
  border-radius: var(--onda-radio-full);
  border: var(--onda-borde-grueso) solid var(--onda-peligro);
  animation: halo var(--onda-dur-cine) var(--onda-ease-salida) infinite;
}
@keyframes halo {
  from { transform: scale(0.72); opacity: 0.85; }
  to   { transform: scale(1.35); opacity: 0; }
}

/* Oculto por defecto: lo enciende `con-rotulos`, que portal.js pone en el
   contenedor del mapa a partir del zoom 15. */
.agente__nombre { display: none; }
.con-rotulos .agente__nombre { display: block; }

.agente__nombre {
  position: absolute;
  /* El rótulo lleva unidad y apellido, así que es más ancho que el disco:
     centrado y sin cortar, porque un nombre cortado se lee como otro nombre. */
  top: 100%; left: 50%;
  transform: translateX(-50%);
  margin-top: 2px;
  padding: 0 3px;
  font-size: var(--onda-texto-2xs);
  font-weight: var(--onda-peso-semi);
  white-space: nowrap;
  color: var(--pmt-sim-fuerte);
  background: color-mix(in srgb, var(--onda-panel) 85%, transparent);
  border-radius: var(--onda-radio-xs);
  font-variant-numeric: tabular-nums;
}

/* Un incidente simulado. */
.incidente { width: 26px; height: 26px; display: grid; place-items: center; }
.incidente__rombo {
  width: 18px; height: 18px;
  display: grid; place-items: center;
  color: #fff;
  background: var(--onda-aviso);
  border: var(--onda-borde-fino) solid var(--onda-panel);
  border-radius: var(--onda-radio-xs);
  transform: rotate(45deg);
  box-shadow: 0 2px 5px rgb(var(--onda-tinta) / 0.3);
}
.incidente__rombo > * { transform: rotate(-45deg); width: 12px; height: 12px; }
.incidente--grave .incidente__rombo { background: var(--onda-peligro); }

/* ─────────────────────────── leyenda del calor ──────────────────────── */

.leyenda {
  position: fixed;
  /* Por encima del zoom y de la atribución, que ocupan esa esquina. */
  bottom: calc(var(--pmt-alto-barra) + 7rem);
  right: var(--onda-esp-3);
  z-index: var(--onda-z-elevado);
  padding: var(--onda-esp-3);
  width: 11rem;
  transition: opacity var(--onda-dur-rapida) var(--onda-ease-estandar);
}
.leyenda[hidden] { display: block; opacity: 0; pointer-events: none; }
.leyenda__titulo {
  font-size: var(--onda-texto-2xs);
  font-weight: var(--onda-peso-fuerte);
  letter-spacing: var(--onda-track-suelto);
  text-transform: uppercase;
  color: var(--onda-tenue);
  margin-bottom: var(--onda-esp-2);
}
.leyenda__escala {
  height: 6px;
  border-radius: var(--onda-radio-full);
  background: linear-gradient(90deg, #2dd4bf 0%, #84cc16 25%, #fbbf24 50%, #f97316 72%, #dc2626 100%);
}
.leyenda__topes { display: flex; justify-content: space-between; margin-top: var(--onda-esp-1); font-size: var(--onda-texto-2xs); color: var(--onda-tenue); }
.leyenda__dato { margin-top: var(--onda-esp-2); font-size: var(--onda-texto-2xs); color: var(--onda-tenue); font-variant-numeric: tabular-nums; }

@media (max-width: 767px) { .leyenda { display: none; } }

/* ────────────────────── lista de patrullas (ficha) ──────────────────── */

.patrullas { margin: 0; padding: 0; list-style: none; }
.patrulla {
  display: flex;
  align-items: center;
  gap: var(--onda-esp-2);
  width: 100%;
  padding: var(--onda-esp-2) 0;
  font: inherit;
  text-align: left;
  color: inherit;
  background: none;
  border: none;
  border-bottom: var(--onda-borde-fino) solid var(--onda-borde);
  cursor: pointer;
}
.patrulla:last-child { border-bottom: none; }
.patrulla__luz { width: 8px; height: 8px; flex: 0 0 auto; border-radius: var(--onda-radio-full); background: var(--pmt-sim); }
.patrulla--detenido .patrulla__luz { background: var(--onda-aviso); }
.patrulla--intervencion .patrulla__luz { background: var(--onda-peligro); }
.patrulla--fijo .patrulla__luz { background: var(--pmt-sim-fuerte); }
.patrulla__id { font-size: var(--onda-texto-xs); font-weight: var(--onda-peso-semi); font-variant-numeric: tabular-nums; flex: 0 0 auto; }
.patrulla__donde { font-size: var(--onda-texto-2xs); color: var(--onda-tenue); flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.patrulla__estado { font-size: var(--onda-texto-2xs); color: var(--onda-tenue); flex: 0 0 auto; font-variant-numeric: tabular-nums; }

/* ──────────────────────────── texto corrido ─────────────────────────── */

.prosa { font-size: var(--onda-texto-xs); line-height: var(--onda-alto-amplio); color: var(--onda-texto); }
.prosa h3 { margin: var(--onda-esp-4) 0 var(--onda-esp-2); font-size: var(--onda-texto-sm); font-weight: var(--onda-peso-semi); }
.prosa h3:first-child { margin-top: 0; }
.prosa p { margin: 0 0 var(--onda-esp-3); }
.prosa ul { margin: 0 0 var(--onda-esp-3); padding-left: var(--onda-esp-5); }
.prosa li { margin-bottom: var(--onda-esp-1); }
.prosa a { color: var(--onda-marca); text-decoration-thickness: 1px; text-underline-offset: 2px; }
.prosa code { font-family: var(--onda-fuente-mono); font-size: 0.95em; background: var(--onda-suave); padding: 0 3px; border-radius: var(--onda-radio-xs); }

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

/* ───────────────── el encabezado en un teléfono ─────────────────────────
   A 390 px de ancho, la marca, el aviso de simulación y los cuatro botones no
   entran en la misma línea: se montaban uno sobre otro y el aviso —que es la
   pieza que no puede faltar— quedaba cortado debajo de un botón.

   Dos filas: identidad y controles arriba, el aviso a todo el ancho abajo. */
@media (max-width: 767px) {
  .marca { padding: var(--onda-esp-2); gap: var(--onda-esp-2); }
  .marca__lugar { display: none; }
  .marca__escudo { width: 1.375rem; height: 1.375rem; }
  .marca__nombre { font-size: var(--onda-texto-xs); }

  /* Sólo iconos: el texto de «Capas» es lo que empujaba la fila. */
  .acciones .boton span { display: none; }
  .acciones .boton { width: 2.25rem; padding: 0; }
  .acciones { gap: var(--onda-esp-1); }

  .aviso-sim {
    top: calc(var(--onda-esp-3) + 2.75rem);
    left: var(--onda-esp-2);
    right: var(--onda-esp-2);
    transform: none;
    max-width: none;
    justify-content: center;
    white-space: normal;
    text-align: center;
    line-height: var(--onda-alto-ajustado);
    padding: var(--onda-esp-2) var(--onda-esp-3);
    font-size: var(--onda-texto-2xs);
  }
}

/* ──────────────────── movimiento reducido ───────────────────────────── */
/* Los bucles se apagan; las transiciones se acortan, no se eliminan (sistema
   de diseño, regla 3): un portal sin ninguna transición se siente roto. */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: var(--onda-dur-instant) !important;
  }
}

/* ───────────────── piezas que dependen de la biblioteca ─────────────────── */

/* El mapa de calor va MEZCLADO con el mapa base, no encima.
   leaflet.heat pega su canvas directo en el panel de superposición y no acepta
   un panel propio, así que no se lo puede mandar al fondo: queda arriba de las
   calles. Con `multiply` el calor tiñe la ciudad en vez de taparla, y las
   calles y sus nombres se siguen leyendo debajo del punto más caliente. En
   oscuro la mezcla se invierte a `screen`, que es la que suma luz. */
.leaflet-heatmap-layer {
  mix-blend-mode: multiply;
  opacity: 0.74;
}
:root[data-tema="oscuro"] .leaflet-heatmap-layer { mix-blend-mode: screen; opacity: 0.82; }
@media (prefers-color-scheme: dark) {
  :root:not([data-tema="claro"]) .leaflet-heatmap-layer { mix-blend-mode: screen; opacity: 0.82; }
}

/* El rótulo del barrio: texto sobre el mapa, sin globo ni flecha. */
.pmt-rotulo.leaflet-tooltip {
  background: none;
  border: none;
  box-shadow: none;
  padding: 0;
  color: var(--onda-tenue);
  font-size: var(--onda-texto-2xs);
  font-weight: var(--onda-peso-semi);
  letter-spacing: var(--onda-track-suelto);
  text-transform: uppercase;
  text-shadow: 0 0 3px var(--onda-panel), 0 0 6px var(--onda-panel);
  white-space: nowrap;
}
.pmt-rotulo.leaflet-tooltip::before { display: none; }

/* Subtítulo dentro del grupo de capas reales: la sección («Red vial»,
   «Control de tránsito»). Más chico y sin el peso del título del grupo. */
.grupo__titulo--sub {
  padding-top: var(--onda-esp-3);
  padding-bottom: var(--onda-esp-1);
  letter-spacing: var(--onda-track-suelto);
  text-transform: none;
  font-weight: var(--onda-peso-semi);
  font-size: var(--onda-texto-2xs);
  color: var(--onda-texto);
  opacity: 0.72;
}

/* Las zonas seguras del teléfono. Sin esto la barra inferior queda debajo del
   indicador de inicio de un iPhone y el reloj se toca con la uña. */
@supports (padding: env(safe-area-inset-bottom)) {
  .barra {
    height: calc(var(--pmt-alto-barra) + env(safe-area-inset-bottom));
    padding-bottom: env(safe-area-inset-bottom);
  }
}
