/* Blitzer-Warner – Oberfläche.

   Gestalterische Leitidee: ein Instrument für die Nachtfahrt. Die Farben sind
   die des deutschen Verkehrszeichens – Verkehrsgelb warnt, Signalrot ist akut,
   Verkehrsblau steht für die fest installierte Anlage –, gesetzt auf ein fast
   schwarzes Cockpit. Große schmale Ziffern wie auf einem Tacho, daneben winzige
   weit gesperrte Mono-Labels wie auf einer Telemetrie-Anzeige.

   Alles ist für das Handy im Hochformat gebaut und fürs Fahren: große
   Antippflächen, hoher Kontrast, das Wichtigste ohne Lesen erfassbar. */

:root {
  /* Grundflächen – kalt und dunkel, damit nachts nichts blendet */
  --ink: #06080b;
  --ink-2: #0a0e13;
  --ink-3: #111823;
  --ink-4: #18212e;
  --hair: rgba(150, 180, 210, 0.13);
  --hair-strong: rgba(150, 180, 210, 0.26);

  --chalk: #eaf0f7;
  --dim: #7c8ca0;
  --dimmer: #556375;

  /* Signalfarben nach Verkehrszeichen-Logik */
  --signal: #ffb400; /* Verkehrsgelb – gemeldet, Warnung */
  --signal-ink: #22180a;
  --alarm: #e8342a; /* Signalrot – akut, in Warndistanz */
  --alarm-ink: #fff6f5;
  --fixed: #2f86ff; /* Verkehrsblau – fest installierte Anlage */
  --fixed-ink: #04142e;
  --go: #35d67f; /* GPS steht */
  --me: #5ce1e6; /* eigene Position */

  --sans: "Saira Condensed", "Arial Narrow", system-ui, sans-serif;
  --mono: "Spline Sans Mono", ui-monospace, "SF Mono", monospace;

  --r-sm: 0.5rem;
  --r-md: 0.85rem;
  --r-lg: 1.25rem;

  --pad: 0.9rem;
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-t: env(safe-area-inset-top, 0px);

  color-scheme: dark;
}

* {
  box-sizing: border-box;
}

/* Muss vor den display-Regeln stehen: sonst überschreibt z. B. .start{display:flex}
   das hidden-Attribut und der Startschirm bliebe sichtbar. */
[hidden] {
  display: none !important;
}

html,
body {
  margin: 0;
  height: 100%;
  background: var(--ink);
  color: var(--chalk);
  font-family: var(--sans);
  font-size: 16px;
  -webkit-tap-highlight-color: transparent;
  overscroll-behavior: none;
  /* Keine Querbewegung – auf dem Handy soll nichts seitlich wackeln. */
  overflow-x: hidden;
}

/* Feines Korn über allem. Nimmt den Flächen das Sterile, ohne die Karte
   nennenswert aufzuhellen – deshalb so niedrig dosiert. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 9999;
  pointer-events: none;
  opacity: 0.05;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

::selection {
  background: var(--signal);
  color: var(--signal-ink);
}

/* Die hellen Standardbalken stechen in der dunklen Fläche heraus. */
.poi-list,
.results,
.settings__form {
  scrollbar-width: thin;
  scrollbar-color: var(--hair-strong) transparent;
}

.poi-list::-webkit-scrollbar,
.results::-webkit-scrollbar,
.settings__form::-webkit-scrollbar {
  width: 0.3rem;
}

.poi-list::-webkit-scrollbar-thumb,
.results::-webkit-scrollbar-thumb,
.settings__form::-webkit-scrollbar-thumb {
  background: var(--hair-strong);
  border-radius: 999px;
}

.poi-list::-webkit-scrollbar-track,
.results::-webkit-scrollbar-track,
.settings__form::-webkit-scrollbar-track {
  background: transparent;
}

/* Kleines Mono-Label, das überall wiederkehrt: Status, Listenkopf, Meta. */
.eyebrow,
.status__text,
.status__count,
.list__title,
.list__count,
.poi__meta,
.alert__type,
.alert__age,
.map-btn,
.field__label,
.results__detail,
.settings__note {
  font-family: var(--mono);
  font-weight: 400;
  letter-spacing: 0.02em;
}

/* ============================================================
   Startschirm
   ============================================================ */

.start {
  position: relative;
  min-height: 100dvh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: calc(2rem + var(--safe-t)) 1.4rem calc(2rem + var(--safe-b));
  text-align: center;
  overflow: hidden;
  background:
    radial-gradient(120% 80% at 50% 8%, rgba(47, 134, 255, 0.14), transparent 60%),
    radial-gradient(90% 60% at 50% 100%, rgba(255, 180, 0, 0.09), transparent 65%),
    var(--ink);
}

/* Radarkegel: drei Ringe und ein umlaufender Sektor. Läuft langsam, damit er
   im Hintergrund atmet statt zu flackern. */
.start__scope {
  position: absolute;
  top: 50%;
  left: 50%;
  width: min(148vw, 40rem);
  aspect-ratio: 1;
  translate: -50% -50%;
  pointer-events: none;
  opacity: 0.55;
}

.scope__ring {
  position: absolute;
  inset: 0;
  margin: auto;
  border: 1px solid var(--hair);
  border-radius: 50%;
}

.scope__ring--1 {
  width: 34%;
  height: 34%;
}

.scope__ring--2 {
  width: 64%;
  height: 64%;
  border-color: rgba(150, 180, 210, 0.09);
}

.scope__ring--3 {
  width: 94%;
  height: 94%;
  border-color: rgba(150, 180, 210, 0.06);
}

.scope__sweep {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: conic-gradient(
    from 0deg,
    rgba(92, 225, 230, 0.24) 0deg,
    rgba(92, 225, 230, 0.06) 26deg,
    transparent 62deg,
    transparent 360deg
  );
  mask: radial-gradient(circle, #000 0 47%, transparent 47.5%);
  animation: sweep 7s linear infinite;
}

@keyframes sweep {
  to {
    rotate: 360deg;
  }
}

/* Zwei Echos auf dem Schirm – der Hinweis darauf, worum es geht. */
.scope__blip {
  position: absolute;
  width: 0.42rem;
  height: 0.42rem;
  border-radius: 50%;
  background: var(--signal);
  box-shadow: 0 0 0.7rem var(--signal);
  animation: blip 7s ease-in-out infinite;
}

/* Bewusst in die Ecken gelegt: mittig säßen sie hinter Suchfeld und Knopf und
   sähen dort wie ein Darstellungsfehler aus. */
.scope__blip--a {
  top: 22%;
  left: 74%;
  animation-delay: 1.1s;
}

.scope__blip--b {
  top: 77%;
  left: 24%;
  background: var(--fixed);
  box-shadow: 0 0 0.7rem var(--fixed);
  animation-delay: 4.4s;
}

@keyframes blip {
  0%,
  100% {
    opacity: 0;
    scale: 0.6;
  }
  4% {
    opacity: 1;
    scale: 1;
  }
  36% {
    opacity: 0;
    scale: 1;
  }
}

.start__inner {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  width: min(100%, 24rem);
}

/* Gestaffelter Auftritt beim Laden – ein bewusster Moment, danach Ruhe. */
.start__inner > * {
  animation: rise 0.7s cubic-bezier(0.2, 0.7, 0.2, 1) backwards;
}

.start__inner > :nth-child(1) {
  animation-delay: 0.05s;
}
.start__inner > :nth-child(2) {
  animation-delay: 0.13s;
}
.start__inner > :nth-child(3) {
  animation-delay: 0.21s;
}
.start__inner > :nth-child(4) {
  animation-delay: 0.29s;
}
.start__inner > :nth-child(5) {
  animation-delay: 0.37s;
}

@keyframes rise {
  from {
    opacity: 0;
    translate: 0 0.9rem;
  }
}

.eyebrow {
  margin: 0;
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.34em;
  color: var(--me);
  text-indent: 0.34em; /* gleicht die Sperrung am rechten Rand aus */
}

/* Zweizeilig gesetzt: „Blitzer-Warner" am Stück passt in dieser Größe auf kein
   Hochformat, und gestapelt tragen die schmalen Versalien den Schirm besser. */
.start__title {
  position: relative;
  margin: 0 0 0.55rem;
  padding-bottom: 0.55rem;
  font-size: clamp(3rem, 18vw, 4.6rem);
  font-weight: 800;
  line-height: 0.84;
  letter-spacing: -0.015em;
  text-transform: uppercase;
}

.start__title-line {
  display: block;
  background: linear-gradient(176deg, var(--chalk) 35%, #8798ab);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* Signalstrich als Abschluss – die Instrumentenmarke des Schirms. */
.start__title::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 0;
  width: 2.6rem;
  height: 0.2rem;
  translate: -50% 0;
  border-radius: 999px;
  background: var(--signal);
  box-shadow: 0 0 0.8rem rgba(255, 180, 0, 0.6);
}

.start__hint {
  margin: 0;
  max-width: 30ch;
  color: var(--dim);
  font-size: 1.02rem;
  line-height: 1.45;
}

.btn-start {
  position: relative;
  width: 100%;
  margin-top: 0.2rem;
  padding: 1.15rem 2rem;
  border: 0;
  border-radius: var(--r-md);
  background: linear-gradient(180deg, #ffc42e, var(--signal));
  color: var(--signal-ink);
  font-family: var(--sans);
  font-size: 1.3rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  box-shadow:
    0 0.6rem 1.6rem rgba(255, 180, 0, 0.24),
    inset 0 1px 0 rgba(255, 255, 255, 0.45);
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}

.btn-start:active {
  transform: translateY(2px);
  box-shadow:
    0 0.2rem 0.7rem rgba(255, 180, 0, 0.2),
    inset 0 1px 0 rgba(255, 255, 255, 0.35);
}

.start__error {
  margin: 0;
  max-width: 34ch;
  padding: 0.6rem 0.8rem;
  border-left: 3px solid var(--alarm);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  background: rgba(232, 52, 42, 0.12);
  color: #ff9d96;
  font-size: 0.92rem;
  line-height: 1.4;
  text-align: left;
}

/* ============================================================
   Ortssuche
   ============================================================ */

.search {
  position: relative;
  width: 100%;
}

/* Lupe als reine CSS-Form – kein weiteres Bild nötig. */
.search__icon {
  position: absolute;
  left: 0.95rem;
  top: 50%;
  width: 0.72rem;
  height: 0.72rem;
  translate: 0 -50%;
  border: 1.6px solid var(--dimmer);
  border-radius: 50%;
  pointer-events: none;
}

.search__icon::after {
  content: "";
  position: absolute;
  right: -0.32rem;
  bottom: -0.28rem;
  width: 0.42rem;
  height: 1.6px;
  background: var(--dimmer);
  rotate: 45deg;
  border-radius: 2px;
}

.search__input {
  width: 100%;
  padding: 0.85rem 0.9rem 0.85rem 2.3rem;
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  background: rgba(17, 24, 35, 0.85);
  color: var(--chalk);
  font-family: var(--sans);
  /* 16px verhindert, dass iOS beim Fokus in das Feld hineinzoomt. */
  font-size: 1rem;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.search__input:focus {
  outline: 0;
  border-color: var(--me);
  box-shadow: 0 0 0 3px rgba(92, 225, 230, 0.16);
}

/* Über den Container, nicht über Geschwister: die Lupe steht im Markup vor
   dem Feld, ein "+"-Selektor träfe sie nie. */
.search:focus-within .search__icon {
  border-color: var(--me);
}

.search:focus-within .search__icon::after {
  background: var(--me);
}

.search__input::placeholder {
  color: var(--dimmer);
}

.search__input::-webkit-search-cancel-button {
  filter: invert(0.6);
}

/* Die Liste schwebt über dem Inhalt, damit der Startschirm nicht springt,
   während die Vorschläge beim Tippen weniger werden. */
.results {
  position: absolute;
  z-index: 20;
  top: calc(100% + 0.4rem);
  left: 0;
  right: 0;
  list-style: none;
  margin: 0;
  padding: 0.3rem;
  text-align: left;
  max-height: 15rem;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: rgba(17, 24, 35, 0.97);
  backdrop-filter: blur(12px);
  border: 1px solid var(--hair-strong);
  border-radius: var(--r-md);
  box-shadow: 0 1.2rem 2.4rem rgba(0, 0, 0, 0.6);
}

.results li button {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.6rem;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--chalk);
  text-align: left;
  cursor: pointer;
  font: inherit;
}

.results li button:hover,
.results li button[aria-selected="true"] {
  background: rgba(92, 225, 230, 0.14);
}

.results__plz {
  flex: none;
  min-width: 3.4rem;
  font-family: var(--mono);
  font-size: 0.8rem;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  color: var(--me);
}

.results__body {
  min-width: 0;
}

.results__label {
  display: block;
  font-size: 1.02rem;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.results__detail {
  display: block;
  margin-top: 0.1rem;
  font-size: 0.7rem;
  color: var(--dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.results__msg {
  padding: 0.6rem;
  color: var(--dim);
  font-family: var(--mono);
  font-size: 0.78rem;
}

.btn-secondary {
  padding: 0.8rem;
  border: 1px solid var(--hair-strong);
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--chalk);
  font-family: var(--sans);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  cursor: pointer;
}

.btn-secondary:active {
  background: var(--ink-4);
}

/* ============================================================
   Anwendungsgerüst und Statuszeile
   ============================================================ */

main {
  min-height: 100dvh;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  padding-bottom: var(--safe-b);
  background: var(--ink);
}

.status {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  flex: none;
  padding: calc(0.55rem + var(--safe-t)) var(--pad) 0.55rem;
  background: var(--ink-2);
  border-bottom: 1px solid var(--hair);
  font-size: 0.72rem;
}

.status__text {
  color: var(--dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.status__spacer {
  flex: 1;
}

.status__count {
  flex: none;
  color: var(--chalk);
  font-variant-numeric: tabular-nums;
}

/* Kontrollleuchte wie am Armaturenbrett. */
.dot {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  flex: none;
}

.dot--off {
  background: var(--dimmer);
}

.dot--ok {
  background: var(--go);
  box-shadow: 0 0 0.5rem var(--go);
}

.dot--stale {
  background: var(--signal);
  box-shadow: 0 0 0.5rem rgba(255, 180, 0, 0.55);
}

.icon-btn {
  display: grid;
  place-items: center;
  /* 44px Mindestgröße, damit der Knopf während der Fahrt zu treffen ist. */
  width: 2.75rem;
  height: 2.75rem;
  margin: -0.6rem -0.45rem -0.6rem 0;
  border: 0;
  background: transparent;
  color: var(--dim);
  cursor: pointer;
}

.icon-btn:active {
  color: var(--chalk);
}

/* ============================================================
   Warnbanner – die Kontrollleuchte der App
   ============================================================ */

.alert {
  position: relative;
  flex: none;
  margin: 0.6rem var(--pad) 0;
  padding: 0.85rem 1rem 0.85rem 1.35rem;
  border-radius: var(--r-md);
  overflow: hidden;
  background: linear-gradient(165deg, #ffc734, var(--signal));
  color: var(--signal-ink);
  box-shadow: 0 0.5rem 1.5rem rgba(255, 180, 0, 0.22);
  animation:
    alert-in 0.32s cubic-bezier(0.2, 0.9, 0.25, 1),
    lamp 1.5s ease-in-out 0.32s infinite;
}

.alert[data-level="near"] {
  background: linear-gradient(165deg, #f4453a, var(--alarm));
  color: var(--alarm-ink);
  box-shadow: 0 0.5rem 1.5rem rgba(232, 52, 42, 0.3);
  animation-duration: 0.32s, 0.7s;
}

@keyframes alert-in {
  from {
    opacity: 0;
    transform: scale(0.97) translateY(-0.4rem);
  }
}

/* Kein Blinken, sondern ein Pulsieren der Helligkeit: fällt im Augenwinkel
   auf, ohne beim Fahren zu stören. */
@keyframes lamp {
  50% {
    filter: brightness(0.84);
  }
}

/* Warnschraffur an der Kante – Gefahrenstelle. */
.alert__hazard {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 0.55rem;
  background: repeating-linear-gradient(
    -45deg,
    rgba(0, 0, 0, 0.62) 0 0.3rem,
    transparent 0.3rem 0.6rem
  );
}

.alert__grid {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: 0 0.9rem;
}

.alert__readout {
  display: flex;
  align-items: baseline;
  gap: 0.1em;
}

.alert__distance {
  font-size: clamp(3rem, 15vw, 4.2rem);
  font-weight: 800;
  line-height: 0.82;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

.alert__unit {
  font-size: 0.95rem;
  font-weight: 600;
  opacity: 0.7;
}

.alert__info {
  min-width: 0;
}

.alert__street {
  font-size: 1.22rem;
  font-weight: 700;
  line-height: 1.15;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.alert__meta {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  margin-top: 0.2rem;
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  opacity: 0.85;
}

.alert__type {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.badge {
  flex: none;
  padding: 0.12rem 0.4rem;
  border-radius: 0.3rem;
  background: rgba(0, 0, 0, 0.28);
  font-family: var(--mono);
  font-weight: 500;
  letter-spacing: 0.04em;
}

.alert__age {
  margin-top: 0.15rem;
  font-size: 0.64rem;
  opacity: 0.62;
}

/* ============================================================
   Karte
   ============================================================ */

.map-wrap {
  position: relative;
  flex: 1;
  min-height: 8rem;
  margin: 0.6rem var(--pad) 0;
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--ink-2);
}

.map {
  position: absolute;
  inset: 0;
  background: var(--ink-2);
}

/* Instrumentenfassung: Haarlinie und abgedunkelte Ränder, damit die Karte in
   der Fläche liegt statt bis an die Kante zu laufen.

   Hier standen zuerst vier Eckmarken. Sie mussten weichen: in jeder Ecke sitzt
   schon ein Bedienelement – Zoom, Ansichtsknöpfe, Tacho, Kartenhinweis – und
   die Marke oben links legte sich wie ein Kasten um den Zoomknopf. */
.map-bezel {
  position: absolute;
  inset: 0;
  z-index: 450;
  pointer-events: none;
  border: 1px solid var(--hair-strong);
  border-radius: var(--r-md);
  box-shadow: inset 0 0 2.5rem rgba(0, 0, 0, 0.55);
}

/* Über der hellen Karte macht der kräftige Innenschatten die Ränder schmutzig. */
.map--light + .map-bezel {
  box-shadow: inset 0 0 2rem rgba(0, 0, 0, 0.18);
}

/* Die OSM-Standardkacheln sind hell. Umkehren plus Farbdrehung ergibt eine
   dunkle Karte, ohne dass ein zweiter Kachelsatz nötig wäre. */
/* Hier stand einmal ein invert()-Filter über den hellen OSM-Kacheln. Das war
   ein Notbehelf: Umkehren verdreht jede Farbe mit, Wald wurde violett und
   Autobahnen giftgrün. Jetzt kommt der dunkle Stil fertig gezeichnet vom
   Server, und der Filter hebt ihn nur noch an — Dark Matter ist roh so dunkel,
   dass Straßen beim Fahren kaum zu erkennen wären.

   Welcher Filter und welcher Hintergrund gilt, setzt app.js als Variable am
   Kartenelement; das Stylesheet muss die Stilnamen dadurch nicht kennen. */
.map .leaflet-tile-pane {
  filter: var(--tile-filter, none);
}

.leaflet-container {
  background: var(--map-bg, var(--ink-2));
  font-family: var(--sans);
}

.leaflet-control-attribution {
  background: rgba(6, 8, 11, 0.8) !important;
  color: var(--dimmer) !important;
  font-family: var(--mono);
  font-size: 0.58rem !important;
  padding: 0 0.35rem !important;
}

.leaflet-control-attribution a {
  color: var(--dim) !important;
}

/* Auf der hellen Karte muss die Angabe mitdrehen – dunkle Schrift auf hellem
   Grund, sonst ist die Pflichtangabe faktisch nicht lesbar. */
.map--light .leaflet-control-attribution {
  background: rgba(255, 255, 255, 0.82) !important;
  color: #4a5460 !important;
}

.map--light .leaflet-control-attribution a {
  color: #2b3642 !important;
}

/* Leaflet bringt eigene Rahmen und Maße mit; die Touch-Variante hat nochmal
   andere. Beide müssen überschrieben werden, sonst bleibt ein heller Rest. */
.leaflet-bar,
.leaflet-touch .leaflet-bar {
  border: 0 !important;
  border-radius: var(--r-sm) !important;
  overflow: hidden;
  box-shadow: 0 0.3rem 0.9rem rgba(0, 0, 0, 0.5) !important;
}

.leaflet-bar a,
.leaflet-touch .leaflet-bar a {
  width: 2.3rem !important;
  height: 2.3rem !important;
  line-height: 2.3rem !important;
  background: rgba(6, 8, 11, 0.86) !important;
  color: var(--chalk) !important;
  border: 0 !important;
  border-bottom: 1px solid var(--hair) !important;
  border-radius: 0 !important;
  font-family: var(--sans);
  font-size: 1.15rem !important;
  font-weight: 700;
  backdrop-filter: blur(3px);
}

.leaflet-bar a:last-child,
.leaflet-touch .leaflet-bar a:last-child {
  border-bottom: 0 !important;
}

.leaflet-bar a:hover,
.leaflet-bar a:active {
  background: var(--ink-4) !important;
  color: var(--me) !important;
}

.leaflet-bar a.leaflet-disabled {
  color: var(--dimmer) !important;
}

/* Tachoscheibe unten links – die Zoomknöpfe bleiben oben links frei. */
.speed-badge {
  position: absolute;
  z-index: 500;
  left: 0.7rem;
  bottom: 0.7rem;
  display: grid;
  place-items: center;
  width: 4.1rem;
  height: 4.1rem;
  border-radius: 50%;
  background:
    radial-gradient(circle at 50% 32%, rgba(92, 225, 230, 0.11), transparent 62%),
    rgba(6, 8, 11, 0.86);
  border: 1px solid var(--hair-strong);
  box-shadow: inset 0 0 1.2rem rgba(0, 0, 0, 0.8);
  pointer-events: none;
  backdrop-filter: blur(3px);
}

.speed-badge__value {
  font-size: 1.75rem;
  font-weight: 800;
  line-height: 0.9;
  font-variant-numeric: tabular-nums;
}

.speed-badge__unit {
  font-family: var(--mono);
  font-size: 0.5rem;
  letter-spacing: 0.1em;
  color: var(--dim);
}

.speed--unknown {
  color: var(--dimmer);
}

.map-tools {
  position: absolute;
  z-index: 500;
  right: 0.7rem;
  top: 0.7rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.map-btn {
  min-height: 2.3rem;
  padding: 0 0.8rem;
  border: 1px solid var(--hair-strong);
  border-radius: var(--r-sm);
  background: rgba(6, 8, 11, 0.86);
  color: var(--chalk);
  font-size: 0.66rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  cursor: pointer;
  backdrop-filter: blur(3px);
}

.map-btn[aria-pressed="true"] {
  border-color: var(--me);
  color: var(--me);
  box-shadow: 0 0 0.8rem rgba(92, 225, 230, 0.2);
}

/* Kompassknopf. Erscheint nur, wenn die Karte gedreht ist – im Normalfall
   nimmt er keinen Platz weg. */
.map-btn--compass {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  padding: 0 0.6rem;
}

.map-btn--compass svg {
  /* Dreht sich gegen die Karte, zeigt also immer nach Norden. */
  transition: transform 0.15s ease;
  color: var(--alarm);
}

.map-btn__label {
  font-size: 0.6rem;
}

/* Tag/Nacht-Umschalter: beide Möglichkeiten nebeneinander sichtbar, damit
   beim Vergleichen klar ist, was gerade läuft und was der andere Zustand ist. */
.daynight {
  display: flex;
  overflow: hidden;
  border: 1px solid var(--hair-strong);
  border-radius: var(--r-sm);
  background: rgba(6, 8, 11, 0.86);
  backdrop-filter: blur(3px);
}

.daynight__opt {
  min-height: 2.3rem;
  padding: 0 0.7rem;
  border: 0;
  background: transparent;
  color: var(--dim);
  font-family: var(--mono);
  font-size: 0.62rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  cursor: pointer;
}

.daynight__opt + .daynight__opt {
  border-left: 1px solid var(--hair-strong);
}

.daynight__opt[aria-pressed="true"] {
  background: var(--signal);
  color: var(--signal-ink);
}

/* Eigene Position: Pfeil, der sich mit dem Kurs dreht. */
.me-arrow {
  width: 1.5rem;
  height: 1.5rem;
  transform-origin: 50% 50%;
  filter: drop-shadow(0 0 0.4rem rgba(92, 225, 230, 0.75));
}

/* Auf heller Karte trägt ein Leuchten nichts – dort braucht der Pfeil einen
   Schlagschatten, um sich von der Fläche abzuheben. */
.map--light .me-arrow {
  filter: drop-shadow(0 0.1rem 0.3rem rgba(0, 0, 0, 0.5));
}

.me-arrow svg {
  display: block;
}

.poi-pin {
  display: grid;
  place-items: center;
  width: 1.7rem;
  height: 1.7rem;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.92);
  background: var(--signal);
  color: var(--signal-ink);
  font-family: var(--sans);
  font-size: 0.68rem;
  font-weight: 800;
  /* Erst eine harte dunkle Kante, dann der weiche Schatten: der weiße Rand
     allein verschwindet auf der hellen Karte in der Fläche. */
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.45),
    0 0.15rem 0.5rem rgba(0, 0, 0, 0.5);
}

.poi-pin--near {
  background: var(--alarm);
  color: #fff;
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.35),
    0 0 0.7rem rgba(232, 52, 42, 0.8);
}

.poi-pin--behind {
  background: var(--ink-4);
  border-color: var(--hair-strong);
  color: var(--dim);
  box-shadow: none;
}

/* Feste Anlagen: eckig statt rund, damit sie sich auch ohne Farbe von den
   gemeldeten mobilen Blitzern unterscheiden. */
.poi-pin--fixed {
  border-radius: 0.32rem;
  background: var(--fixed);
  color: #fff;
}

.poi-pin--fixed.poi-pin--near {
  background: var(--alarm);
}

.map-popup {
  font-family: var(--sans);
  font-size: 0.92rem;
  line-height: 1.35;
  color: var(--dim);
}

.map-popup strong {
  display: block;
  margin-bottom: 0.1rem;
  font-size: 1.05rem;
  color: var(--chalk);
}

.leaflet-popup-content-wrapper,
.leaflet-popup-tip {
  background: var(--ink-3) !important;
  color: var(--chalk) !important;
  border: 1px solid var(--hair-strong);
  box-shadow: 0 0.8rem 2rem rgba(0, 0, 0, 0.6) !important;
}

.leaflet-popup-content-wrapper {
  border-radius: var(--r-sm) !important;
}

.leaflet-popup-close-button {
  color: var(--dim) !important;
}

.radar {
  position: absolute;
  inset: 0;
  margin: auto;
  width: min(78%, 320px);
  height: auto;
  aspect-ratio: 1;
}

/* ============================================================
   Liste
   ============================================================ */

.list {
  flex: none;
  display: flex;
  flex-direction: column;
  /* Deckel statt fester Höhe: die Karte behält den Rest. */
  max-height: 42dvh;
  min-height: 0;
  padding: 0 var(--pad);
}

.list__head {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex: none;
  width: 100%;
  /* 44px hoch – während der Fahrt zu treffen. */
  min-height: 2.9rem;
  padding: 0.2rem 0.15rem;
  border: 0;
  background: transparent;
  color: var(--dim);
  cursor: pointer;
  font: inherit;
}

.list__title {
  flex: none;
  font-size: 0.63rem;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--dimmer);
}

.list__count {
  flex: 1;
  text-align: left;
  font-size: 0.68rem;
  color: var(--chalk);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.list__chevron {
  flex: none;
  display: grid;
  place-items: center;
  color: var(--dim);
  transition: rotate 0.2s ease;
}

main.list-collapsed .list__chevron {
  rotate: -90deg;
}

main.list-collapsed .poi-list {
  display: none;
}

.poi-list {
  list-style: none;
  margin: 0;
  padding: 0 0 0.7rem;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  overflow-y: auto;
  overscroll-behavior: contain;
  min-height: 0;
}

.poi-list li {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  flex: none;
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--hair);
  border-radius: var(--r-sm);
  background: var(--ink-3);
}

.poi-list__empty {
  justify-content: center;
  color: var(--dimmer);
  font-family: var(--mono);
  font-size: 0.74rem;
  background: transparent !important;
  border-style: dashed !important;
}

.poi__dist {
  flex: none;
  min-width: 3.9rem;
  font-size: 1.28rem;
  font-weight: 800;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--dim);
}

/* Voraus liegende Blitzer sind die, auf die es ankommt. */
.poi__dist--ahead {
  color: var(--signal);
}

.poi__body {
  flex: 1;
  min-width: 0;
}

/* Der Straßenname darf kürzen, die Plakette daneben nicht: auf schmalen
   Geräten wurde sie sonst vom Ellipsis mit abgeschnitten – und mit ihr die
   einzige Angabe, ob die Anlage fest steht oder nur gemeldet ist. */
.poi__street {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
  font-size: 1.02rem;
  font-weight: 600;
  line-height: 1.2;
}

.poi__name {
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.poi__meta {
  display: block;
  margin-top: 0.1rem;
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--dimmer);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.poi__age {
  color: var(--dim);
}

.poi__badge {
  flex: none;
  padding: 0 0.3rem;
  border-radius: 0.22rem;
  background: var(--fixed);
  color: #fff;
  font-family: var(--mono);
  font-size: 0.56rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  vertical-align: 0.12em;
}

/* Tempolimit als Verkehrszeichen – das stärkste Bild, das die App hat. */
.poi__vmax {
  flex: none;
  display: grid;
  place-items: center;
  width: 2.4rem;
  height: 2.4rem;
  border: 0.2rem solid var(--alarm);
  border-radius: 50%;
  background: #fff;
  color: #0d0d0d;
  font-size: 0.92rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

.poi__vmax--fixed {
  border-color: var(--fixed);
}

/* ============================================================
   Einstellungen – auf dem Handy ein Blatt von unten
   ============================================================ */

.settings {
  width: 100%;
  max-width: 30rem;
  margin: auto auto 0;
  padding: 0;
  border: 0;
  border-top: 1px solid var(--hair-strong);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  background: var(--ink-2);
  color: var(--chalk);
  box-shadow: 0 -1rem 3rem rgba(0, 0, 0, 0.7);
  animation: sheet-up 0.28s cubic-bezier(0.2, 0.9, 0.25, 1);
}

@keyframes sheet-up {
  from {
    translate: 0 100%;
  }
}

.settings::backdrop {
  background: rgba(2, 4, 6, 0.72);
  backdrop-filter: blur(4px);
}

.settings__form {
  display: flex;
  flex-direction: column;
  gap: 1.05rem;
  padding: 1.1rem var(--pad) calc(1.1rem + var(--safe-b));
  max-height: 88dvh;
  overflow-y: auto;
}

/* Greifleiste wie bei einem Bottom Sheet. */
.settings__form::before {
  content: "";
  width: 2.4rem;
  height: 0.22rem;
  margin: 0 auto 0.2rem;
  border-radius: 999px;
  background: var(--hair-strong);
}

.settings__title {
  margin: 0;
  font-size: 0.68rem;
  font-family: var(--mono);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.2em;
  color: var(--dim);
}

.field {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.field__label {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.6rem;
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--dim);
}

.field__value {
  font-family: var(--sans);
  font-size: 1.1rem;
  font-weight: 700;
  letter-spacing: 0;
  text-transform: none;
  color: var(--chalk);
  font-variant-numeric: tabular-nums;
}

.field--row {
  flex-direction: row;
  align-items: center;
  gap: 0.75rem;
  /* Die ganze Zeile ist Antippfläche, nicht nur das Kästchen. */
  min-height: 2.75rem;
  font-size: 1.02rem;
}

.field__select {
  width: 100%;
  min-height: 2.9rem;
  padding: 0 2.2rem 0 0.8rem;
  border: 1px solid var(--hair);
  border-radius: var(--r-sm);
  background-color: var(--ink-3);
  color: var(--chalk);
  font-family: var(--sans);
  font-size: 1.02rem;
  font-weight: 600;
  cursor: pointer;
  /* Eigener Pfeil: der eingebaute ist auf jedem System anders und passt
     nirgends zum Rest. */
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--dim) 50%),
    linear-gradient(135deg, var(--dim) 50%, transparent 50%);
  background-position: right 1.05rem center, right 0.75rem center;
  background-size: 0.32rem 0.32rem, 0.32rem 0.32rem;
  background-repeat: no-repeat;
}

.field__select:focus-visible {
  outline: 0;
  border-color: var(--me);
  box-shadow: 0 0 0 3px rgba(92, 225, 230, 0.16);
}

.field input[type="range"] {
  width: 100%;
  height: 1.5rem;
  accent-color: var(--signal);
}

.field input[type="checkbox"] {
  flex: none;
  width: 1.35rem;
  height: 1.35rem;
  accent-color: var(--signal);
}

.settings__note {
  margin: 0;
  padding-top: 0.85rem;
  border-top: 1px solid var(--hair);
  font-size: 0.68rem;
  line-height: 1.6;
  color: var(--dimmer);
}

.settings__note strong {
  color: var(--dim);
  font-weight: 500;
}

.btn-close {
  margin-top: 0.1rem;
  padding: 0.95rem;
  border: 0;
  border-radius: var(--r-sm);
  background: var(--chalk);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
}

.btn-close:active {
  background: var(--dim);
}

/* Beenden: bewusst als rote Randhandlung, nicht als zweiter Hauptknopf. */
.btn-quit {
  padding: 0.8rem;
  border: 1px solid rgba(232, 52, 42, 0.5);
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--alarm);
  font-family: var(--sans);
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  cursor: pointer;
}

.btn-quit:active {
  background: rgba(232, 52, 42, 0.15);
}

/* ============================================================
   Querformat: die Karte darf nicht zum Streifen werden
   ============================================================ */

@media (orientation: landscape) and (max-height: 30rem) {
  .list {
    max-height: 38dvh;
  }

  .alert {
    padding-block: 0.6rem;
  }

  .alert__distance {
    font-size: 2.6rem;
  }

  .speed-badge {
    width: 3.4rem;
    height: 3.4rem;
  }

  .speed-badge__value {
    font-size: 1.4rem;
  }
}

/* Ab Tablet-Breite mittig begrenzen, statt in die Breite zu laufen. */
@media (min-width: 46rem) {
  main {
    max-width: 46rem;
    margin: 0 auto;
    border-inline: 1px solid var(--hair);
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    /* Die Verzögerung muss mit weg: der gestaffelte Auftritt läuft mit
       fill-mode "backwards", sonst bliebe der Startschirm eine knappe halbe
       Sekunde leer, obwohl gar nichts mehr animiert wird. */
    animation-delay: 0.001ms !important;
  }
}
