* { -webkit-tap-highlight-color: transparent; }

/* Schalter-Optik für sämtliche Checkboxen der App (Ebenen, AE, Sonderlayer,
   Berichts-/Startbildschirm-Einstellungen usw.) statt der nativen eckigen
   Kästchen - eine rein optische Umgestaltung über appearance:none auf
   demselben <input type="checkbox">; Zustand, Events und Zugriffsschlüssel
   (checked, change-Listener, IDs) bleiben unverändert, nichts davon wird
   hier angefasst. Einzelne Kontexte (.layer-row, .report-weather-toggle,
   .group-checkbox) hatten zuvor eine feste 16x16px-Größe für das native
   Kästchen gesetzt - die wurde entfernt (siehe dort), diese Regel liefert
   jetzt einheitlich die Maße für alle. */
input[type=checkbox] {
  appearance:none; -webkit-appearance:none;
  width:36px; height:21px; border-radius:11px; flex:0 0 auto;
  background:var(--border-strong); border:none; position:relative; cursor:pointer;
  transition:background .15s ease;
}
input[type=checkbox]::before {
  content:''; position:absolute; top:2px; left:2px; width:17px; height:17px;
  border-radius:50%; background:#fff; box-shadow:0 1px 2px rgba(0,0,0,.25);
  transition:transform .15s ease;
}
input[type=checkbox]:checked { background:var(--link); }
input[type=checkbox]:checked::before { transform:translateX(15px); }
input[type=checkbox]:focus-visible { outline:2px solid var(--link); outline-offset:2px; }

/* Einheitliche Optik für Text-/Auswahlfelder (Drohnenauswahl, geplante
   Flugzeit, eigene Angaben im Bericht, Konto-/Geräte-Formulare, Feedback-
   Formular usw.) - bisher der letzte unangetastete Baustein aus der Zeit vor
   dem Redesign, überall noch die eckige Browser-Voreinstellung mit dünnem
   grauem Rahmen. appearance:none nur bei Datum/Zeit (deren native
   Kalender-/Uhr-Symbole bleiben über ::-webkit-calendar-picker-indicator
   erreichbar) - der native Pfeil von <select> bleibt bewusst stehen, ein
   plattformübergreifend einheitlicher Ersatzpfeil bräuchte eine eigene
   hell-/dunkelmodusfähige SVG und ist der Aufwand für ein reines
   Geschmacksdetail nicht wert. input[type=search] fehlt hier bewusst - die
   Suchleiste hat mit .search-control input bereits eine eigene, umfassendere
   Regel (siehe dort), die sonst durch Reihenfolge/Spezifität überschrieben
   werden könnte. Radius 14px nach dem Feld-Token aus dem Design-Paket. */
input[type=text],
input[type=email],
input[type=tel],
input[type=password],
input[type=date],
input[type=datetime-local],
input[type=number],
input[type=search],
select,
textarea {
  font-family:inherit; font-size:13.5px; color:var(--text-body);
  background:var(--bg-card); border:1px solid var(--border-strong); border-radius:14px;
  padding:9px 12px; box-sizing:border-box;
}
textarea { resize:vertical; line-height:1.45; }
input[type=text]:focus, input[type=email]:focus, input[type=tel]:focus,
input[type=password]:focus, input[type=date]:focus, input[type=datetime-local]:focus,
input[type=number]:focus, input[type=search]:focus, select:focus, textarea:focus {
  outline:2px solid var(--link); outline-offset:-1px;
}
input:disabled, select:disabled, textarea:disabled { opacity:.55; cursor:not-allowed; }
/* Kalender-/Uhr-Symbol von Datum/Zeit-Feldern folgt sonst weiterhin fest der
   Systemfarbe (meist Schwarz) - im Dunkelmodus auf dunklem Feld kaum sichtbar. */
input[type=date]::-webkit-calendar-picker-indicator,
input[type=datetime-local]::-webkit-calendar-picker-indicator { filter:var(--datepicker-icon-filter, none); }
:root[data-theme="dark"] input[type=date]::-webkit-calendar-picker-indicator,
:root[data-theme="dark"] input[type=datetime-local]::-webkit-calendar-picker-indicator { filter:invert(1); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) input[type=date]::-webkit-calendar-picker-indicator,
  :root:not([data-theme="light"]) input[type=datetime-local]::-webkit-calendar-picker-indicator { filter:invert(1); }
}
/* Reglern (Sonnenstand, Mindestlänge Schiffe) fehlte bisher jede Akzentfarbe -
   liefen komplett in Browser-Blau/-Grau statt im App-Blau. Sonnenregler
   behält seinen eigenen Orange-Ton (siehe .sun-slider), thematisch passender
   als das allgemeine Blau. */
.ship-length-row input[type=range] { accent-color:var(--link); }

/* Farb-Variablen für Hell-/Dunkelmodus. Folgt standardmäßig der Betriebssystem-
   Einstellung (prefers-color-scheme) und lässt sich zusätzlich im Panel fest
   auf hell/dunkel stellen (siehe js/theme.js, Attribut data-theme am <html>).
   Erfasst die App-eigene Oberfläche (Panel, Karten, Modals, Suchfeld,
   Leaflet-Bedienelemente) sowie seit 7.80 auch die Kartenkacheln selbst
   (Nachtansicht, siehe weiter unten). Bewusst NICHT erfasst bleibt, was
   inhaltlich zur Karte gehört und auf ihr sitzt: Marker-Popups, Tooltips und
   das Sonnenstand-Overlay - sie sollen auch auf der dunklen Karte hell und
   damit gut lesbar bleiben. */
:root {
  --bg-app: #F4F6F8;
  --bg-card: #FFFFFF;
  --bg-button: #F0F2F5;
  --bg-button-hover: #E2E3E6;
  --hover-tint: #EAF1FC;
  --border: #E4E8ED;
  --border-light: #EDF0F3;
  --border-strong: #D7DDE4;
  --text-heading: #0E141B;
  --text-body: #0E141B;
  /* Die gedämpften Grautöne lagen mit 4,2 bzw. 2,9 zu 1 unter der
     Lesbarkeitsschwelle von 4,5 (WCAG AA). Behutsam abgedunkelt, sodass sie
     weiterhin deutlich zurücktreten, aber lesbar bleiben - betrifft
     Sekundärtexte wie Ortsangaben, Fußzeilenlinks und die Objektzahl neben
     den Ebenen. */
  --text-muted: #5B6672;
  --text-faint: #8A94A0;
  --text-faint2: #8A94A0;
  --link: #1462CE;
  --link-hover: #0F4EA6;
  --shadow: rgba(14,20,27,.35);
  --dot-ring: rgba(14,20,27,.2);
  --donation-bg: #fff8e6;
  --donation-border: #f0c34d;
}

/* Dunkelmodus in zwei Varianten, weil das Farbschema seit Version 7.70 nicht
   mehr ausschließlich der Systemeinstellung folgt, sondern im Panel auch von
   Hand umgestellt werden kann (siehe js/theme.js):

   1. Systemeinstellung "dunkel" - gilt, solange NICHT ausdrücklich "hell"
      gewählt wurde (:not([data-theme="light"])).
   2. Ausdrücklich gewählter Dunkelmodus (:root[data-theme="dark"]) - gilt
      unabhängig von der Systemeinstellung.

   Die Werte sind in beiden Blöcken identisch und müssen zusammen gepflegt
   werden; CSS bietet leider keine Möglichkeit, denselben Variablensatz für
   zwei Bedingungen nur einmal zu notieren, ohne einen Build-Schritt
   einzuführen (den dieses Projekt bewusst nicht hat). Ohne data-theme-
   Attribut verhält sich alles exakt wie vorher. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg-app: #14171C;
    --bg-card: #1C2027;
    --bg-button: #232932;
    --bg-button-hover: #393E46;
    --hover-tint: #253040;
    --border: #2A3039;
    --border-light: #262B33;
    --border-strong: #50555D;
    --text-heading: #E8ECF1;
    --text-body: #E8ECF1;
    --text-muted: #98A2AE;
    --text-faint: #7C8794;
    --text-faint2: #7C8794;
    --link: #7FB6FF;
    --link-hover: #92C1FF;
    --shadow: rgba(0,0,0,.6);
    --dot-ring: rgba(255,255,255,.3);
    --donation-bg: #362b13;
    --donation-border: #a9822f;
  }
}

:root[data-theme="dark"] {
  --bg-app: #14171C;
  --bg-card: #1C2027;
  --bg-button: #232932;
  --bg-button-hover: #393E46;
  --hover-tint: #253040;
  --border: #2A3039;
  --border-light: #262B33;
  --border-strong: #50555D;
  --text-heading: #E8ECF1;
  --text-body: #E8ECF1;
  --text-muted: #98A2AE;
  --text-faint: #7C8794;
  --text-faint2: #7C8794;
  --link: #7FB6FF;
  --link-hover: #92C1FF;
  --shadow: rgba(0,0,0,.6);
  --dot-ring: rgba(255,255,255,.3);
  --donation-bg: #362b13;
  --donation-border: #a9822f;
}

/* --- Nachtansicht der Kartenkacheln (Dunkelmodus) ---
   Umgesetzt als CSS-Filter auf den Kachel-Ebenen statt über dunkle
   Kachel-Anbieter (CARTO, Stadia o.ä.). Gründe: kein weiterer externer Dienst,
   der in der Datenschutzerklärung stehen müsste und die IP der Nutzer erhält;
   keine zusätzlichen Nutzungsbedingungen; und vor allem funktioniert es mit
   dem vorgeladenen Offline-Paket weiter, das genau die OSM-/Esri-Kacheln
   enthält (siehe js/offlinePackage.js).

   Die beiden Basiskarten brauchen unterschiedliche Behandlung:
   - Gezeichnete OSM-Karte: invertieren und den Farbkreis um 180° drehen. Das
     ist der übliche Weg zu einer dunklen Straßenkarte - Flächen werden dunkel,
     Beschriftung hell, und die Drehung holt die Farben zurück (Wasser bliebe
     sonst orange statt blau). Etwas abgedunkelt und im Kontrast reduziert,
     damit das Ergebnis nicht grell wirkt.
   - Satellitenbild: NUR abdunkeln und leicht entsättigen. Ein invertiertes
     Luftbild ist völlig unbrauchbar (Vegetation würde violett, Wasser weiß).

   Wichtig: der Filter sitzt auf der jeweiligen Kachel-Ebene, nicht auf dem
   Kartencontainer - sonst würden Zonen-Polygone, Marker, Popups und das
   Sonnenstand-Overlay mitgefiltert und die Zonenfarben wären nicht mehr die
   amtlichen.

   Im Hellmodus bleiben beide Karten unberührt; die Filter greifen nur in den
   beiden Dunkel-Fällen (Systemwahl bzw. ausdrücklich gewählter Modus), analog
   zu den Farbvariablen weiter unten. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .map-tiles-street { filter: invert(1) hue-rotate(180deg) brightness(0.92) contrast(0.88); }
  :root:not([data-theme="light"]) .map-tiles-satellite { filter: brightness(0.62) saturate(0.8); }
}
:root[data-theme="dark"] .map-tiles-street { filter: invert(1) hue-rotate(180deg) brightness(0.92) contrast(0.88); }
:root[data-theme="dark"] .map-tiles-satellite { filter: brightness(0.62) saturate(0.8); }

/* Ausdrückliche Wahl in der Kartenauswahl sticht das Farbschema (siehe
   BasemapControl in js/main.js): Wer die helle Karte bei Sonne will, bekommt
   sie auch bei dunkel eingestelltem Gerät - und umgekehrt. Die Klassen sitzen
   am Kartencontainer, damit sie die :root-Regeln oben überschreiben. */
.basemap-force-light .map-tiles-street,
.basemap-force-light .map-tiles-satellite { filter: none; }
.basemap-force-dark .map-tiles-street { filter: invert(1) hue-rotate(180deg) brightness(0.92) contrast(0.88); }
.basemap-force-dark .map-tiles-satellite { filter: brightness(0.62) saturate(0.8); }

/* overflow:hidden, weil #app vom Startbildschirm aus höher sein kann als die
   von iOS gemeldete Seitenhöhe (siehe --sichtbare-hoehe). Ohne das ließe sich
   die ganze Seite um diesen Betrag verschieben. Gescrollt wird ohnehin nur in
   den inneren Bereichen (#panelScroll, Fensterinhalte), nie am Dokument. */
html, body { margin:0; padding:0; height:100%; overflow:hidden; font-family: 'Instrument Sans', Arial, Helvetica, sans-serif; overscroll-behavior:none; background:var(--bg-app); color:var(--text-body); }
/* Höhe aus --sichtbare-hoehe (gesetzt in js/main.js): vom Startbildschirm
   gestartet meldet iOS 100dvh um die Statusleistenhöhe zu klein, die Karte
   endete dadurch einen Streifen über dem unteren Bildschirmrand. */
#app { position:relative; height:100vh; height:var(--sichtbare-hoehe, 100dvh); width:100vw; overflow:hidden; }
#map { position:absolute; inset:0; height:100%; width:100%; }

/* Leaflet macht den Kartencontainer per tabindex fokussierbar (für
   Tastatur-Pan/Zoom) und setzt selbst outline-offset:1px, aber keine eigene
   outline-Farbe/-Breite (siehe leaflet.css) - der Browser zeigt dafür seinen
   nativen Fokus-Rahmen (meist blau), sobald die Karte z.B. nach einem Klick
   oder Drag den Fokus bekommt. !important, da leaflet.css nach dieser Datei
   verlinkt sein könnte und sonst je nach Ladereihenfolge gewinnen würde. */
#map.leaflet-container,
#map.leaflet-container:focus,
#map.leaflet-container:focus-visible { outline:none !important; }

/* Floating toggle button - war ursprünglich 46px, jetzt kleiner und (per
   top-Wert) vertikal auf Höhe des "DroneFlightCheck"-Titels/Logos in
   .panel-header zentriert (Zeilenmitte dort ≈ 27px: panelScroll
   padding-top 14px + halbe Logo-Höhe 26px/2 = 13px), damit beides ruhig
   nebeneinander wirkt statt der Button höher/tiefer als der Titel zu sitzen. */
#toggleBtn {
  position:fixed; top:12px; right:12px; z-index:1200;
  width:36px; height:36px; border-radius:50%; background:var(--bg-card); border:1px solid var(--border-strong);
  color:var(--text-heading);
  box-shadow:0 2px 8px var(--shadow); font-size:19px; line-height:1; cursor:pointer;
  display:flex; align-items:center; justify-content:center; padding:0;
}

/* Standort-, Distanzmess- & Satelliten-Buttons: eigenes Leaflet-Control (siehe
   js/main.js), direkt unter dem Zoom-Control mit identischem Abstand/derselben
   Breite - Leaflet übernimmt Positionierung/Stacking über die .leaflet-bar-Klasse. */
#locateBtn, #measureBtn, #satelliteBtn, #circleBtn, #polygonBtn, #layersBtn {
  font-size:16px; display:flex; align-items:center; justify-content:center;
}
#locateBtn.locating { animation: locate-pulse 1s ease-in-out infinite; }
@keyframes locate-pulse { 0%,100% { opacity:1; } 50% { opacity:.35; } }
#measureBtn.active, #circleBtn.active, #polygonBtn.active, #locateBtn.following { background:#1565c0; color:white; }

/* Leaflet-eigene Bedienelemente (Zoom +/- sowie obige Standort-/Mess-/
   Satelliten-/Kreis-/Polygon-Buttons, alle als .leaflet-bar gerendert) nutzen
   sonst Leaflets Standard-Weiß/Schwarz aus leaflet.css - hier an Hell-/
   Dunkelmodus angeglichen. Aktive Zustände (siehe oben) haben höhere
   Spezifität und überschreiben das weiterhin wie gehabt. */
.leaflet-bar a, .leaflet-bar a:hover {
  background:var(--bg-card); color:var(--text-heading); border-bottom-color:var(--border);
}

/* Einheitliche "Karten"-Optik für Zoom/Standort/Werkzeuge/Kartenauswahl -
   GILT FÜR MOBILE UND DESKTOP GLEICH (vorher nur innerhalb der Mobile-
   Media-Query, Desktop blieb beim eckigen Leaflet-Standardrahmen ohne
   Schatten - Nutzerwunsch: beide Ansichten sollen optisch zusammengehören).
   overflow:hidden auf dem Container schneidet Leaflets eigene eckige
   Rundung an den Rand-Buttons einfach ab, unabhängig von deren eigenem
   (kleineren) border-radius aus leaflet.css. */
.leaflet-bar:not(.basemap-control) {
  border:none; border-radius:14px; overflow:hidden;
  box-shadow:0 6px 20px -8px rgba(14,20,27,.35);
}
.basemap-toggle { border-radius:14px; box-shadow:0 6px 20px -8px rgba(14,20,27,.35); }

/* Leaflet-Hinweis (© OpenStreetMap-Mitwirkende) - Namensnennungspflicht
   bleibt unangetastet (siehe Kommentar weiter oben zur ODbL-Lizenz), nur die
   OPTIK an die übrige App angeglichen: vorher Leaflets Standard-Weiß, auch
   im Dunkelmodus, dazu unterschiedlich prominent zwischen Mobile (breiter
   Streifen unter der Suchleiste) und Desktop (kaum sichtbare Mini-Schrift).
   .leaflet-container davor nötig, um leaflet.css' eigene, gleich
   spezifische Hintergrundfarbe zu schlagen. */
.leaflet-container .leaflet-control-attribution {
  background:var(--bg-card); color:var(--text-faint);
  border-radius:8px; box-shadow:0 2px 8px -2px rgba(14,20,27,.3);
  font-size:10.5px; padding:2px 8px;
}
.leaflet-control-attribution a { color:var(--text-faint); }

.leaflet-tooltip.measure-tooltip {
  background:white; border:1px solid #1565c0; color:#1565c0; font-weight:700; font-size:11px;
  padding:2px 6px; box-shadow:0 1px 3px rgba(0,0,0,.3);
}
.leaflet-tooltip.measure-tooltip::before { border-top-color:#1565c0; }

/* Radius-Vorschau beim Zeichnen einer Kreisfläche (js/areaCheck.js) - wie
   .measure-tooltip, aber in der Flächenfarbe statt Mess-Blau. */
.leaflet-tooltip.area-tooltip {
  background:white; border:1px solid #6a1b9a; color:#6a1b9a; font-weight:700; font-size:11px;
  padding:2px 6px; box-shadow:0 1px 3px rgba(0,0,0,.3);
}
.leaflet-tooltip.area-tooltip::before { border-top-color:#6a1b9a; }

/* Ziehbarer Mittelpunkt-Marker beim Kreis-Zeichnen (js/areaCheck.js,
   CIRCLE_CENTER_ICON) - überschreibt Leaflets Default-divIcon-Look (weißer
   Kasten mit dünnem grauem Rand). Bewusst größer als die violetten
   Eckpunkt-Marker (10px Ø), damit er als Ziehgriff gut zu treffen ist. */
.area-drag-handle {
  width:26px; height:26px; border-radius:50%; background:#fff; border:3px solid #6a1b9a;
  box-sizing:border-box; box-shadow:0 1px 4px rgba(0,0,0,.35); cursor:grab;
}

/* Orts-/Adresssuche: eigenes Leaflet-Control (siehe js/main.js). Gleiche
   Karten-Optik wie Zoom/Werkzeuge/Kartenauswahl (abgerundet, weicher
   Schatten) UND gleiche Symbol-links-Anordnung wie die Mobile-Ansicht -
   vorher hatte der Desktop hier den alten eckigen Leaflet-Look mit
   vollflächigem blauem Such-Knopf rechts, während Mobile schon die neue
   Optik mit Lupe links hatte (Nutzerwunsch: beide sollen gleich aussehen).
   position:relative auf dem äußeren Element (statt overflow:hidden direkt
   hier) - Rundung/Clipping sitzen stattdessen am <form>, damit die
   Vorschlagsliste (.search-results) als Geschwister-Element frei darüber
   herausragen kann. */
.search-control { background:none; border-radius:14px; box-shadow:none; position:relative; }
.search-control form {
  display:flex; align-items:center; border-radius:14px; overflow:hidden; transition:outline .15s;
  background:var(--bg-card); box-shadow:0 6px 20px -8px rgba(14,20,27,.35);
}
.search-control input {
  border:none; outline:none; padding:7px 4px 7px 0; font-size:13px; width:170px; font-family:inherit;
  background:none; color:var(--text-body);
}
.search-control input::-webkit-search-cancel-button { cursor:pointer; }
.search-control button {
  order:-1; border:none; background:none; color:var(--text-faint); padding:0 8px 0 10px;
  cursor:pointer; flex:0 0 auto; display:flex; align-items:center;
}
.search-control button:hover { color:var(--text-heading); }
.search-control form.searching { opacity:.6; }
.search-control form.search-error { outline:2px solid #d32f2f; outline-offset:-2px; }

/* Vorschlagsliste der Live-Suche (ab 3 Zeichen, siehe js/main.js) - wächst
   nach oben über das Suchfeld, da dieses unten links am Kartenrand sitzt. */
.search-results {
  display:none; position:absolute; bottom:100%; left:0; margin-bottom:6px;
  background:var(--bg-card); border-radius:6px; box-shadow:0 2px 10px rgba(0,0,0,.35);
  max-height:260px; overflow-y:auto; width:260px; max-width:min(80vw, 320px);
}
.search-results.show { display:block; }
.search-result-item { padding:7px 10px; cursor:pointer; border-bottom:1px solid var(--border-light); }
.search-result-item:last-child { border-bottom:none; }
.search-result-item:hover, .search-result-item.active { background:var(--hover-tint); }
.search-result-main { font-size:12.5px; color:var(--text-heading); }
.search-result-sub { font-size:11px; color:var(--text-faint2); margin-top:1px; }

/* Backdrop shown behind panel on narrow screens */
#backdrop { position:fixed; inset:0; background:rgba(0,0,0,.35); z-index:1090; display:none; }
#backdrop.show { display:block; }

/* #panel ist ein Flex-Container mit zwei Bereichen: #panelScroll (scrollt,
   alle Karten) und .legal-footer (fix am unteren Rand, scrollt nie mit) -
   Impressum & Datenschutz müssen aus rechtlichen Gründen immer erreichbar
   bleiben, unabhängig vom Scroll-Zustand der Karten darüber. */
#panel {
  position:fixed; top:0; right:0; height:100%; width:340px; max-width:88vw;
  background:var(--bg-app); border-left:1px solid var(--border-strong);
  box-sizing:border-box; z-index:1100;
  display:flex; flex-direction:column;
  transform:translateX(0); transition:transform .25s ease;
}
#panel.closed { transform:translateX(100%); }

/* Ziehgriff für die Panel-Breite (nur Desktop, siehe @media unten und
   initPanelResize in js/main.js) - ein schmaler, unsichtbarer Streifen am
   linken Panel-Rand, der beim Ziehen etwas breiter wird als sein optisch
   sichtbares Pseudo-Element, damit die Trefffläche nicht zu knapp ausfällt.
   position:absolute wirkt relativ zu #panel (position:fixed), kein eigenes
   position:relative dafür nötig. */
#panelResizeHandle { display:none; }
#panel.panel-resizing { transition:none; }

#panelScroll {
  flex:1 1 auto; min-height:0; overflow-y:auto; box-sizing:border-box;
  padding:14px 16px 16px 16px;
  /* Der Sicherheitsabstand oben wird hier wirklich gebraucht: vom
     Startbildschirm gestartet beginnt der Inhalt bei Null und läuft unter die
     Statusleiste. In 9.17 stand hier eine Erkennung, die ihn wegließ - dadurch
     lag die Überschrift unter der Uhrzeit. Wieder zurückgenommen. */
  padding-top:max(14px, env(safe-area-inset-top));
  padding-right:max(16px, env(safe-area-inset-right));
}

/* flex-wrap, damit Titel+Logo und die Bedienelemente (Sprache/Zoom) bei zu
   schmalem Panel auf zwei Zeilen umbrechen statt seitlich herauszulaufen:
   der Titel "DroneFlightCheck" ist ein einzelnes, nicht umbrechbares Wort und
   kann nicht schrumpfen, wodurch die Zeile sonst breiter wird als das Panel.
   Das erzeugte horizontale Scrollen von #panelScroll liess sich seitlich
   verschieben und schnitt dabei Text im Pruefergebnis ab. */
.panel-header { display:flex; align-items:center; gap:8px; margin:0 0 12px 0; flex-wrap:wrap; }
/* Passend zur Wortmarke im Logo: Space Grotesk Bold statt der sonst im UI
   genutzten Arial/Helvetica - .app-name auf jedes Vorkommen "DroneFlightCheck"
   im Fliesstext angewendet (siehe index.html/js/main.js), #panel h2 nur fuer
   die Panel-Ueberschrift zusaetzlich. "Drone" immer blau, der Rest in der
   jeweiligen Textfarbe (schwarz im Light Mode) - .app-name-drone/-rest sind
   theme-faehig (var()), fuer die fest hell hinterlegten Logo-Lockups
   (.map-brand/.brand-lockup, immer auf weiss) gelten stattdessen die fixen
   Farben .brand-drone/.brand-rest weiter unten. */
.app-name, #panel h2 { font-family:'Space Grotesk', Arial, Helvetica, sans-serif; font-weight:700; }
#panel h2 { font-size:17px; margin:0; color:var(--text-heading); }
.app-name-drone { color:var(--link); }
.app-name-rest { color:var(--text-heading); }
.panel-logo { width:26px; height:26px; border-radius:6px; flex:0 0 auto; box-shadow:0 1px 3px rgba(0,0,0,.25); }

/* DE/EN als Segment-Pille statt zweier eckiger Einzelknöpfe - fasst
   Sprache/Farbschema/Konto optisch als eine kleine "Konfig"-Gruppe neben dem
   Logo zusammen, wie im Design-Paket (d1-desktop). Aktives Segment über
   eigenes weißes/dunkles Feld statt Farbfläche - dieselbe ruhige Optik wie
   die Panel-Reiter. */
.panel-lang { display:flex; align-items:center; gap:2px; flex:0 0 auto; background:var(--bg-button); border-radius:10px; padding:3px; }
.panel-lang button {
  border:none; border-radius:7px; background:none; color:var(--text-muted); font-size:12px; font-weight:600;
  cursor:pointer; line-height:1; padding:5px 9px; display:flex; align-items:center; justify-content:center;
  font-family:inherit;
}
.panel-lang button:hover { color:var(--text-heading); }
.panel-lang button.active { background:var(--bg-card); color:var(--text-heading); box-shadow:0 1px 2px var(--shadow); }

/* Farbschema-Umschalter (Automatisch/Hell/Dunkel, js/theme.js): drei feste
   Segmente in derselben Pille wie die Sprachauswahl (.panel-lang) statt
   eines einzelnen Knopfs, der bei jedem Klick weiterspringt - damit bleibt
   immer sichtbar, welcher Modus gerade aktiv ist (die .active-Fläche),
   statt es nur am wechselnden Symbol erkennen zu müssen. */
.panel-theme-group button { padding:6px 8px; }

/* Von der Kopfzeile hierher verschoben (siehe index.html) - zentriert direkt
   unter der Reiterleiste statt rechts neben Logo/Titel. Zoom skaliert
   #panelScroll per CSS zoom (nicht nur font-size), damit wirklich alles
   darin proportional mitwächst/-schrumpft. */
.panel-zoom { display:flex; align-items:center; justify-content:center; gap:6px; margin:0 0 12px 0; }
.panel-zoom button {
  width:22px; height:22px; border:1px solid var(--border-strong); border-radius:5px;
  background:var(--bg-button); color:var(--text-body); font-size:14px; font-weight:700;
  cursor:pointer; line-height:1; padding:0; display:flex; align-items:center; justify-content:center;
  font-family:inherit;
}
.panel-zoom button:hover:not(:disabled) { background:var(--bg-button-hover); }
.panel-zoom button:disabled { opacity:.4; cursor:default; }
#panelZoomLabel { font-size:10.5px; color:var(--text-muted); min-width:30px; text-align:center; }
/* Trennstrich vor #resetQuickBtn (siehe index.html) - optisch von der
   Textgrößen-Zoom-Gruppe abgesetzt, damit "Alles zurücksetzen" nicht wie ein
   vierter, gleichwertiger Zoom-Knopf wirkt. */
.panel-zoom-sep { width:1px; height:16px; background:var(--border-strong); margin:0 2px; }
.card { background:var(--bg-card); border:1px solid var(--border); border-radius:8px; padding:10px 12px; margin-bottom:12px; font-size:13px; line-height:1.5; }
.card b { color:var(--text-heading); }

/* Panel-Karten als <details> (js/collapsible.js merkt sich auf-/zugeklappt
   je Karte geräteweit in localStorage) - Titel wandert vom bisherigen <b> in
   <summary>, Pfeil-Indikator wie schon bei den Ebenen-Gruppen (details.grp). */
/* flex-wrap, damit lange Kartentitel umbrechen statt seitlich herauszulaufen:
   der Titel besteht aus mehreren Flex-Items (z.B. "💛", Wortmarke, Resttext)
   und die Wortmarke "DroneFlightCheck" ist ein nicht umbrechbares Wort - ohne
   Umbruch wurde die Karte dadurch breiter als das Panel (fiel bei groesserer
   Menue-Schrift auf). Der Pfeil wird per margin-left:auto rechts gehalten
   statt per justify-content:space-between, das die Titel-Items bei mehreren
   Zeilen sonst unschoen auseinanderziehen wuerde. */
details.card > summary {
  cursor:pointer; font-weight:700; color:var(--text-heading); list-style:none;
  display:flex; align-items:center; gap:8px; flex-wrap:wrap;
}
details.card > summary::-webkit-details-marker { display:none; }
details.card > summary::after {
  content:'▶'; font-size:10px; color:var(--text-faint); flex:0 0 auto; transition:transform .15s;
  margin-left:auto;
}
details.card[open] > summary::after { transform:rotate(90deg); }
details.card > .card-body { margin-top:8px; }

/* Panel-Reiter (Ergebnis/Kartenebenen/Wetter, siehe index.html/js/main.js
   setActiveTab). .panel-tabgroup bündelt Leiste + alle drei Panels zu einem
   einzigen Flex-Kind von #panelScroll - nur so lässt sich die mobile
   Priorisierung (siehe @media unten, vorher direkt auf #resultCard) auf die
   ganze Gruppe anwenden, unabhängig davon, welcher Reiter gerade sichtbar ist.

   Ursprünglich eine dezente Unterstrich-Optik wie die Hilfe-Reiter
   (.legal-tabs/.legal-tab), dann eine flächig blau hinterlegte
   Segment-Leiste. Jetzt Pills: aktiver Reiter mit heller Akzent-Fläche
   (--hover-tint) und Akzenttext statt vollflächigem Blau mit weißer
   Schrift - wirkt ruhiger und braucht dadurch auch keine eigene
   Dunkelmodus-Textfarbe mehr (--hover-tint/--link liefern in beiden
   Farbschemata von sich aus genug Kontrast zueinander). */
/* Icon über Label je Reiter statt Pills mit Emoji+Text - vier statt drei
   Einträge (Konto ist seit dem Design-Update ein vierter, immer sichtbarer
   Reiter statt eines reinen Kopfzeilen-Icons, siehe #accountTabBtn), dafür
   ist eine ganze Zeile knapper als eine Pille pro Reiter. Aktiv wird über
   Farbe UND eine leicht eingefärbte Fläche gezeigt (wie im Design-Paket,
   d1-desktop) - jeder Reiter bleibt zusätzlich über role="tab"/
   aria-selected eindeutig. */
.panel-tabs {
  display:flex; justify-content:space-between; gap:2px;
  margin-bottom:14px; padding:8px 0 4px 0; border-bottom:1px solid var(--border-light);
}
.panel-tab {
  display:flex; flex-direction:column; align-items:center; gap:4px;
  border:none; background:none; cursor:pointer; font-size:11px; font-weight:600;
  color:var(--text-faint); padding:6px 4px; border-radius:11px; font-family:inherit; flex:1 1 0; min-width:0;
}
.panel-tab-icon { flex:0 0 auto; }
.panel-tab:hover { color:var(--text-heading); }
.panel-tab.active { color:var(--link); background:var(--hover-tint); }
/* Jedes Panel bleibt für sich ein Block aus einer oder mehreren <details
   class="card">, wie zuvor direkt im Hauptfluss - [hidden] mit eigener Regel
   abgesichert, falls hier künftig einmal display auf .panel-tabpanel gesetzt
   wird (Autoren-CSS würde die UA-Regel [hidden]{display:none} sonst je nach
   Spezifität überschreiben). */
.panel-tabpanel[hidden] { display:none; }
.result-big { font-family:'Space Grotesk', Arial, Helvetica, sans-serif; font-size:22px; font-weight:700; letter-spacing:-.02em; margin:4px 0; }
.zone1 { color:#b71c1c; }
/* Hinweis "Ein Flug ist nur zulässig, wenn ... alle Zonen/Verbote beachtet
   werden" (js/main.js) - bewusst in Rot statt nur gedämpftem .muted-Grau,
   da diese rechtliche Einschränkung für jedes Ergebnis gilt und nicht
   übersehen werden soll. Seit Version 11.9x eine kompakte, einzeilig
   zugeklappte Warnfläche statt eines durchgehenden Textblocks (siehe
   legalNoteCompactHtml in js/main.js) - der volle Text bleibt per Klick
   vollständig erreichbar, drängt sich aber nicht mehr zwischen die
   Zonenzeilen und die Drohnenklassen-Auswahl. */
.legal-note-compact {
  margin-top:10px; border-radius:8px; background:var(--rating-bg); border:1px solid var(--rating-border);
}
.legal-note-compact summary {
  display:flex; align-items:center; gap:6px; padding:7px 10px; cursor:pointer;
  color:var(--rating-text); font-size:12.5px; line-height:1.4; list-style:none;
}
.legal-note-compact summary::-webkit-details-marker { display:none; }
.legal-note-compact summary::after {
  content:'›'; margin-left:auto; flex:0 0 auto; font-size:16px; line-height:1;
  transform:rotate(90deg); transition:transform .15s ease;
}
.legal-note-compact[open] summary::after { transform:rotate(-90deg); }
.legal-note-icon { flex:0 0 auto; color:var(--rating-border); }
.legal-note-link { text-decoration:underline; text-decoration-style:dotted; text-underline-offset:2px; white-space:nowrap; }
.legal-note-full { margin:0; padding:0 10px 9px 31px; font-size:12px; line-height:1.45; color:var(--rating-text); }
.zone2 { color:#d32f2f; }
.zone3 { color:#f44336; }
.zone4 { color:#e57373; }
.zoneNone { color:var(--text-muted); }

/* Im Dunkelmodus sind die kräftigen Rottöne der Zonen 1/2 auf dem dunklen
   Kartenhintergrund kaum noch zu lesen (gemessener Kontrast 2,2 zu 1).
   Aufgehellte Varianten desselben Farbtons, damit die Signalwirkung erhalten
   bleibt - die Zonen 3/4 sind bereits hell genug und bleiben unverändert,
   sonst verlöre die Abstufung ihre Aussage. Der Haftungshinweis (siehe
   .legal-note-compact oben) hängt bereits an den --rating-*-Variablen und
   braucht hier keine eigene Regel mehr. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .zone1 { color:#ff8a80; }
  :root:not([data-theme="light"]) .zone2 { color:#ff7961; }
}
:root[data-theme="dark"] .zone1 { color:#ff8a80; }
:root[data-theme="dark"] .zone2 { color:#ff7961; }
button.wide { width:100%; box-sizing:border-box; padding:9px 6px; margin-bottom:8px; font-size:14px; }

/* "Jetzt veröffentlichen" (js/publish.js, nur lokal sichtbar - siehe
   #publishCard[hidden] in index.html). */
#publishBtn { background:#1565c0; color:white; border:none; border-radius:6px; cursor:pointer; }
#publishBtn:hover { background:#0d47a1; }
#publishBtn:disabled { background:#90a4ae; cursor:not-allowed; }
/* Ursprünglich der Verweis unter dem Veröffentlichen-Knopf zur lokalen
   Admin-Seite (scripts/admin/ - inzwischen komplett entfernt, siehe DRO-12,
   FTP/Unterstützen-Link liegen zentral in Supabase). Die Optik lebt weiter:
   seit DRO-9 nutzt sie der Nutzungsauswertung-Link im Admin-Reiter des
   Kontos (js/account.js adminTabHtml), mit eigener laeuftLokal()-Prüfung
   dort, weil der Admin-Reiter (anders als die frühere Karte hier) auch auf
   der veröffentlichten Seite sichtbar ist. */
.publish-links { display:flex; flex-wrap:wrap; gap:8px; margin-top:8px; }
.publish-links a {
  flex:1 1 auto; text-align:center; padding:7px 10px; border-radius:6px;
  border:1px solid var(--border-strong); background:var(--bg-button);
  color:var(--text-body); text-decoration:none; font-size:12.5px; font-weight:600;
}
.publish-links a:hover { background:var(--bg-button-hover); color:var(--text-heading); }
.log {
  margin-top:10px; background:#1c1c1c; color:#d4d4d4; padding:10px; border-radius:6px;
  font-size:12.5px; line-height:1.5; white-space:pre-wrap; word-break:break-word; max-height:260px; overflow-y:auto;
}
.warn { background:#fff8e1; border:1px solid #ffca28; border-radius:6px; padding:8px 10px; font-size:12.5px; color:#7a5b00; margin-top:10px; }
.muted { color:var(--text-muted); font-size:12.5px; }
.placeholder { color:var(--text-faint2); font-style:italic; }
#loading { font-size:12px; color:var(--text-faint); }
a { color:var(--link); }

/* Betroffene Zonen: eine Zeile je Zone (CTR-Zone + DIPUL-Treffer) mit
   farbigem Punkt, Kurzerklärung der Einschränkung und Links. Als <details> -
   zugeklappt (Regelfall ab der zweiten Zone, siehe renderZoneLines) nur Punkt,
   Zonenname und eine einzeilig abgeschnittene Kurzfassung derselben
   Beschreibung; aufgeklappt der volle Text mit Links und AE-Erleichterung.
   Kein separat gepflegter Kurztext nötig - .zone-line-short zeigt denselben
   description-String wie .zone-line-body, nur per text-overflow abgeschnitten. */
.zone-lines { display:flex; flex-direction:column; gap:2px; margin-top:8px; }
.zone-line { font-size:12px; line-height:1.5; }
.zone-line summary {
  cursor:pointer; list-style:none; display:flex; align-items:baseline; gap:7px; padding:3px 0;
  min-width:0; /* nötig, damit das nachfolgende min-width:0 der Kurzfassung greift */
}
.zone-line summary::-webkit-details-marker { display:none; }
.zone-line summary b { color:var(--text-heading); flex:0 0 auto; }
/* white-space:nowrap + Ellipsis nur in der Kurzfassung - dort ersetzt das
   Abschneiden am Zeilenende die frühere Umbruch-Absicherung für lange
   DIPUL-Namen: ein zu langes Wort wird sichtbar gekürzt statt das Panel seitlich
   zu sprengen. Aufgeklappt (.zone-line-body) gilt weiterhin overflow-wrap. */
.zone-line-short {
  color:var(--text-muted); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0; flex:1 1 auto;
}
.zone-line[open] .zone-line-short { display:none; }
.zone-line summary::after {
  content:'▶'; font-size:9px; color:var(--text-faint); flex:0 0 auto; margin-left:auto; transition:transform .15s;
}
.zone-line[open] summary::after { transform:rotate(90deg); }
.zone-line-body { margin:0 0 4px 16px; overflow-wrap:anywhere; }
/* Frueher white-space:nowrap auf dem ganzen Container - damit war die
   Linkzeile ("§ 21h LuftVO (EU-Drohnenregelung) · offizielles Maptool") EINE
   unumbrechbare Zeile mit fester Mindestbreite, unabhaengig von der Menue-
   Schriftgroesse. Dadurch lief das Pruefergebnis seitlich aus dem Panel und
   Text wirkte abgeschnitten. Jetzt bleibt nur die einzelne Linkbeschriftung
   zusammen, umgebrochen wird zwischen den Links. Bei sehr grosser Menue-
   Schrift reicht selbst das nicht (eine einzelne Beschriftung wie
   "§ 21h LuftVO (EU-Drohnenregelung)" ist dann breiter als das Panel) -
   deshalb bricht sie dort notfalls auch innerhalb um, statt das Layout zu
   sprengen. */
.zone-line-links { font-size:12px; }
.zone-line-links a { margin-left:2px; }

.zone-dot { width:9px; height:9px; border-radius:50%; flex:0 0 auto; box-shadow:inset 0 0 0 1px var(--dot-ring); position:relative; top:2px; }

/* Erleichterung durch eine Allgemeinerlaubnis - eigene Zeile unter der
   jeweiligen Einschränkung, damit erkennbar bleibt, worauf sie sich bezieht.
   Grün und mit Kennzeichnung abgesetzt, weil sie als einzige Angabe in dieser
   Liste etwas erlaubt statt einzuschränken; als angehängter Satz im
   Fließtext ging das unter. */
.zone-line-permit {
  display:flex; align-items:flex-start; gap:10px; margin-top:8px; padding:11px 12px;
  font-size:13px; line-height:1.45; border-radius:12px; background:var(--permit-bg); color:var(--permit-fg);
}
.zone-line-permit-tag {
  flex:0 0 auto; font-weight:700; text-transform:uppercase; font-size:10px; letter-spacing:.08em;
  padding:3px 6px; border-radius:6px; background:var(--permit-tag-bg); color:var(--permit-fg);
}
:root { --permit-bg:#E9F6EF; --permit-tag-bg:#CFEBDC; --permit-fg:#0B6B3E; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { --permit-bg:#1b2c1c; --permit-tag-bg:#284a2b; --permit-fg:#8FD6A8; }
}
:root[data-theme="dark"] { --permit-bg:#1b2c1c; --permit-tag-bg:#284a2b; --permit-fg:#8FD6A8; }

/* Aktionsleiste im Ergebnis-Card: Teilen-Link + Spot speichern (js/main.js).
   Trennlinie wie .drone-class-area weiter oben - macht die Zeile als eigenen
   Abschnitt "Aktionen" innerhalb der Karte erkennbar statt nahtlos an die
   Drohnenklassen-/AE-Auswahl anzuschließen. */
.result-actions { display:flex; gap:8px; margin-top:12px; padding-top:10px; border-top:1px solid var(--border); }
.result-actions button {
  flex:1 1 auto; font-size:13px; font-weight:600; padding:9px 4px; border:1px solid var(--border-strong); border-radius:14px;
  background:var(--bg-button); cursor:pointer; font-family:inherit; color:var(--text-body);
}
.result-actions button:hover { background:var(--bg-button-hover); }

/* Druckansicht für den PDF-Prüfbericht (js/main.js openReport()): standardmäßig
   unsichtbar, im Druckdialog wird stattdessen ausschließlich sie gezeigt und
   der Rest der App ausgeblendet - kein zusätzliches PDF-Modul nötig, nutzt den
   nativen "Als PDF sichern"-Druckdialog des Browsers. Bewusst nicht an den
   Dark-Mode-Variablen beteiligt: gedruckt wird immer auf weißes Papier,
   unabhängig von der Bildschirm-Theme-Einstellung. */
#reportView { display:none; }
/* Aufbau des Kartenausschnitts im Bericht - bewusst AUSSERHALB des
   @media-print-Blocks, damit die Kacheln schon beim Zusammenbauen richtig
   positioniert sind und ihre Ladezustände stimmen (siehe
   waitForReportMapTiles). Im Druckblock stehen nur die Druck-Eigenheiten. */
.report-map-frame { position:relative; overflow:hidden; }
.report-map-tile { position:absolute; display:block; }
.report-map-overlay { position:absolute; left:0; top:0; }
@media print {
  /* html/body stehen seit 9.18 auf height:100%; overflow:hidden - eine
     Korrektur fürs iPhone (dort kann #app höher sein als die von iOS
     gemeldete Seitenhöhe, siehe --sichtbare-hoehe), die aber unbeschränkt für
     jedes Medium gilt. Beim Drucken klemmte das den ganzen Bericht auf die
     Höhe eines Bildschirms fest - alles, was auf die erste Seite nicht mehr
     passte (die rechtliche Bewertung bei "Betroffene Zonen" eingeschlossen),
     wurde nicht abgeschnitten dargestellt, sondern schlicht nie gedruckt.
     Für den Druck muss der Fluss wieder normal über mehrere Seiten laufen. */
  html, body { height:auto !important; overflow:visible !important; }
  body.printing-report > *:not(#reportView) { display:none !important; }
  body.printing-report #reportView { display:block !important; }
  /* Der Bericht wird immer auf weißem Papier gedruckt/als PDF gespeichert,
     unabhängig vom auf dem Bildschirm gerade gewählten Farbschema (hell/
     dunkel/automatisch) - html/body selbst brauchten bisher keine feste
     Hintergrundfarbe (die dunkle var(--bg-app) schimmerte im Dunkelmodus
     durch die Ränder des Berichts). Schwerer wog: die Wetterkarte
     (.report-weather, siehe weatherReportHtml in js/main.js) übernimmt
     unverändert dieselben Theme-abhängigen Klassen wie das Panel
     (.weather-tile, .weather-table, .wind-value, ...) - im Dunkelmodus wäre
     deren Text auf Papier hell auf hellem Grund und damit unlesbar
     gewesen, obwohl die Fläche selbst schon korrekt weiß war. Statt jede
     einzelne Klasse einzeln für den Druck zu überschreiben (fehleranfällig,
     wächst mit jeder künftigen Klasse in .report-page mit), werden hier
     EINMAL alle Theme-Variablen auf .report-page fest auf ihre hellen
     :root-Werte gesetzt - jede Nachfahren-Regel, die var(--text-body) & Co.
     nutzt, löst dadurch automatisch wieder korrekt hell/lesbar auf. Die
     Variablen --rating-... und --permit-... (Ampel-Boxen, AE-Hinweis) sind
     davon unabhängig und bleiben wie gehabt einzeln weiter unten
     überschrieben. */
  html, body { background:#fff !important; }
  .report-page {
    --bg-app:#F4F6F8; --bg-card:#FFFFFF; --bg-button:#F0F2F5; --bg-button-hover:#E2E3E6;
    --border:#E4E8ED; --border-light:#EDF0F3; --border-strong:#D7DDE4;
    --text-heading:#0E141B; --text-body:#0E141B; --text-muted:#5B6672; --text-faint:#8A94A0; --text-faint2:#8A94A0;
    --link:#1462CE; --link-hover:#0F4EA6; --dot-ring:rgba(14,20,27,.2);
  }
  /* Schriftgrößen durchgängig angehoben: Der Bericht wird ausgedruckt und im
     Zweifel bei einer Kontrolle gelesen - 10 bis 12 px auf Papier waren dafür
     zu klein. Grundgröße jetzt 13,5 px, Nebenangaben nicht unter 11 px. */
  .report-page { font-family:'Instrument Sans',Arial,Helvetica,sans-serif; color:#111; padding:16px; font-size:13.5px; line-height:1.5; }
  .report-page h1 { font-size:19px; margin:0 0 4px 0; }
  .report-meta-block { margin-bottom:18px; }
  .report-meta { color:#888; font-size:10.5px; margin-bottom:3px; }

  /* Abschnittsüberschriften gliedern den Bericht (Gesamteinschätzung,
     Geprüfter Ort, Betroffene Zonen, Drohne und Erlaubnis) - vorher lief
     alles als eine durchgehende Folge von Tabellen und Listen. */
  .report-section {
    font-size:13px; text-transform:uppercase; letter-spacing:.05em; color:#333;
    margin:20px 0 7px 0; padding-bottom:3px; border-bottom:1.5px solid #333;
    break-after:avoid; page-break-after:avoid;
  }
  .report-page > .report-section:first-of-type { margin-top:14px; }

  /* break-inside:avoid auf der ganzen Tabelle statt nur auf einzelnen Zeilen -
     beides sind kurze, wenige-Zeilen-Blöcke (Geprüfter Ort: 3 Zeilen, eigene
     Angaben: bis zu 6), bei denen eine mitten hindurch laufende Seitengrenze
     schlimmer aussieht als der Block einfach als Ganzes auf die nächste Seite
     zu schieben. */
  .report-table { border-collapse:collapse; width:100%; margin-bottom:14px; break-inside:avoid; page-break-inside:avoid; }
  .report-table th, .report-table td { text-align:left; padding:6px 8px; border-bottom:1px solid #ddd; font-size:13.5px; }
  .report-table th { width:180px; color:#555; font-weight:600; }
  .report-notes { font-size:12.5px; margin:0 0 14px 18px; }
  .report-notes li { break-inside:avoid; page-break-inside:avoid; }
  .report-footer { font-size:11px; color:#666; margin-top:24px; border-top:1px solid #ddd; padding-top:8px; }

  /* Betroffene Zonen: jede einzelne Zeile (Farbpunkt, Kurzerklärung, Links,
     ggf. AE-Erleichterung - zusammen oft 2-3 Zeilen) bleibt beim Drucken
     zusammen. Der umgebende .zone-lines-Block selbst bekommt bewusst KEIN
     break-inside:avoid - zwischen zwei Zonen darf die Seite weiterhin
     umbrechen, nur nicht innerhalb einer einzelnen Zone. Jede Zeile steht im
     Bericht immer aufgeklappt (renderZoneLines mit allOpen:true, siehe
     openReport) - der Aufklapp-Pfeil aus dem Panel ist hier ohne Funktion und
     wird entfernt, wie beim Vorhersage-Aufklapper der Wetterlage. */
  .zone-line { break-inside:avoid; page-break-inside:avoid; }
  .zone-line summary { cursor:default; }
  .zone-line summary::after { display:none; }

  /* Gesamteinschätzung: Stufe als Aussage oben, Begründungen darunter.
     Feste helle --rating-*-Werte wie bei .report-weather weiter unten -
     ohne die würde ein am Gerät gewähltes dunkles Farbschema den Punkt vor
     der Überschrift auf Papier in seiner (hellen) Dunkelmodus-Farbe drucken. */
  .report-verdict {
    --rating-fg:#333 !important; --rating-border:#333 !important;
    margin:0 0 14px 0; break-inside:avoid; page-break-inside:avoid;
    -webkit-print-color-adjust:exact; print-color-adjust:exact;
  }
  .report-verdict.rating-good    { --rating-fg:#0B6B3E !important; --rating-border:#0E8A4F !important; }
  .report-verdict.rating-caution { --rating-fg:#8A5200 !important; --rating-border:#B36A00 !important; }
  .report-verdict.rating-bad     { --rating-fg:#9E2015 !important; --rating-border:#C42B1C !important; }
  .report-verdict.rating-unknown { --rating-fg:#5B6672 !important; --rating-border:#6B7683 !important; }
  .report-verdict-head { display:flex; align-items:center; gap:7px; font-family:'Space Grotesk',Arial,Helvetica,sans-serif; font-size:15px; font-weight:700; letter-spacing:-.01em; margin-bottom:5px; color:var(--rating-fg); }
  .report-verdict-dot { width:10px; height:10px; border-radius:50%; flex:0 0 auto; background:var(--rating-border); }
  .report-verdict-list { margin:0 0 0 18px; padding:0; font-size:13px; }
  .report-verdict-list li { margin-bottom:3px; }
  /* Kurzer Warnhinweis bei negativem Wetter, direkt unter der
     Gesamteinschätzung (siehe weatherWarningReportHtml) - .warn selbst nutzt
     bereits feste, druckfeste Farben (keine CSS-Variablen), hier nur der
     Abstand zum vorhergehenden Block passend zu den übrigen Abschnitten. */
  .report-weather-warning { margin:0 0 14px 0; break-inside:avoid; page-break-inside:avoid; }
  /* Hinweisbanner über einem aus einem Spot-Snapshot wiederhergestellten
     Bericht (siehe openReportFromSnapshot in js/main.js) - sitzt vor dem
     .report-page-Grundgerüst, deshalb hier eigene Außenabstände statt sich
     auf dessen Kontext zu verlassen. */
  .report-historical-notice { margin:0 16px 12px 16px; break-inside:avoid; page-break-inside:avoid; }

  /* Drohne und Erlaubnis: je Angabe ein Block mit eigener Erklärung, damit
     zusammenbleibt, was zusammengehört. */
  .report-entry { margin-bottom:12px; break-inside:avoid; page-break-inside:avoid; }
  .report-entry-head { font-size:13.5px; margin-bottom:3px; }
  .report-entry-label { font-size:11px; text-transform:uppercase; letter-spacing:.04em; color:#666; margin:5px 0 2px 0; }
  .report-entry-list { margin:0 0 0 18px; padding:0; font-size:13px; }
  .report-entry-list li { margin-bottom:2px; }
  .report-entry-text { font-size:12.5px; margin:0 0 5px 0; line-height:1.5; }
  /* Eingebettete Konto-Dokumente (AE-Erlaubnis/Scheine/Versicherung "komplett",
     siehe js/reportOptions.js docEmbedHtml) - eigener Block statt in
     .report-entry, da Fotos/PDFs oft eine ganze Seite füllen und deshalb
     immer auf einer neuen Seite beginnen sollen statt mitten in den Text
     hineinzulaufen. */
  .report-doc-image, .report-doc-pdf { display:block; max-width:100%; margin:8px 0 14px 0; break-before:page; page-break-before:always; }
  .report-doc-image { max-height:100vh; object-fit:contain; }
  .report-doc-pdf { width:100%; height:90vh; border:1px solid #ddd; }
  /* Lageskizze (siehe js/reportMap.js) - break-inside verhindert, dass der
     Ausschnitt beim Druck über zwei Seiten zerrissen wird.
     aspect-ratio statt height:auto ist hier entscheidend: #reportView steht bis
     zum Druck auf display:none, und Chrome leitet für ein SVG in einem nie
     dargestellten Container keine intrinsische Höhe ab - die Skizze kam
     dadurch mit 0 Pixeln Höhe heraus und fehlte im PDF vollständig. Mit einem
     festen Seitenverhältnis steht die Höhe unabhängig davon fest.
     print-color-adjust erzwingt zusätzlich, dass die Zonenflächen mitgedruckt
     werden - Browser lassen Flächenfarben beim Drucken sonst gern weg. */
  .report-map { margin:0 0 14px 0; break-inside:avoid; page-break-inside:avoid; }
  /* Kartenausschnitt: Kacheln als absolut positionierte <img> im Rahmen, die
     Zonen als SVG darüber. print-color-adjust ist hier entscheidend - ohne die
     Angabe druckt Chrome die Kacheln und Zonenflächen nicht mit. */
  .report-map-frame {
    border:1px solid #999;
    -webkit-print-color-adjust:exact; print-color-adjust:exact;
  }
  .report-map figcaption { font-size:10px; color:#777; margin-top:4px; line-height:1.35; }

  /* Wetterabschnitt im Bericht (siehe weatherReportHtml in js/main.js): nutzt
     dieselben Klassen wie die Wetterkarte im Panel, deren Farben aber über
     CSS-Variablen dem App-Farbschema folgen (var(--text-muted), var(--link),
     .rating-* je nach hell/dunkel). Auf Papier bzw. im PDF gibt es kein
     Dunkelmodus - ein im Gerät gewähltes dunkles Schema würde sonst z.B.
     helle Schrift auf weißem Papier erzeugen. !important, weil die
     Dunkelmodus-Regeln oben (:root[data-theme="dark"] u.ä.) dieselben
     Variablen mit gleicher oder höherer Spezifität setzen - ohne !important
     entscheidet sonst zufällig die Reihenfolge im Stylesheet statt die
     Absicht hier. print-color-adjust sorgt dafür, dass die Ampel-Hintergründe
     überhaupt mitgedruckt werden (Browser lassen Flächenfarben sonst weg,
     siehe .report-map-frame oben zum selben Thema). */
  /* KEIN break-inside:avoid auf dem ganzen Block (anders als .report-verdict,
     .report-entry & Co.): die Wetterlage - Ampel-Kasten, Werte, Wind, Kp UND
     die 12-Zeilen-Vorhersagetabelle - ist zu lang, um als Ganzes garantiert
     auf eine Seite zu passen. Ein pauschales break-inside:avoid zwang den
     kompletten Block auf eine neue Seite, sobald er auf der aktuellen nicht
     mehr vollständig hinpasste - die Fusszeile danach hatte dann oft keinen
     Platz mehr und landete allein auf einer dritten, fast leeren Seite. Die
     einzelnen KURZEN Bestandteile (Ampel-Kasten, Aktuell-Block, Windtabelle,
     Kp-Zeile) bekommen ihren eigenen Schutz weiter unten; die lange
     Vorhersagetabelle darf dagegen wie jede normale Tabelle zwischen Zeilen
     umbrechen (thead wiederholt sich dabei automatisch). */
  .report-weather {
    --text-heading:#0E141B !important; --text-body:#0E141B !important; --text-muted:#5B6672 !important;
    --border-light:#EDF0F3 !important; --link:#1462CE !important; --dot-ring:rgba(14,20,27,.2) !important;
    margin-bottom:14px;
    -webkit-print-color-adjust:exact; print-color-adjust:exact;
  }
  .report-weather .flight-rating,
  .report-weather .weather-now,
  .report-weather .weather-wind-table,
  .report-weather .weather-kp { break-inside:avoid; page-break-inside:avoid; }
  .report-weather .rating-good    { --rating-bg:#E9F6EF !important; --rating-border:#0E8A4F !important; --rating-fg:#0B6B3E !important; --rating-text:#0B6B3E !important; --rating-muted:#68A588 !important; }
  .report-weather .rating-caution { --rating-bg:#FDF2E0 !important; --rating-border:#B36A00 !important; --rating-fg:#8A5200 !important; --rating-text:#8A5200 !important; --rating-muted:#BA955E !important; }
  .report-weather .rating-bad     { --rating-bg:#FCEAE8 !important; --rating-border:#C42B1C !important; --rating-fg:#9E2015 !important; --rating-text:#9E2015 !important; --rating-muted:#C5756E !important; }
  .report-weather .rating-unknown { --rating-bg:#F0F2F5 !important; --rating-border:#6B7683 !important; --rating-fg:#5B6672 !important; --rating-text:#5B6672 !important; --rating-muted:#9AA1A9 !important; }
  .report-weather .rating-dot-good    { background:#0E8A4F !important; }
  .report-weather .rating-dot-caution { background:#B36A00 !important; }
  .report-weather .rating-dot-bad     { background:#C42B1C !important; }
  .report-weather .rating-dot-unknown { background:#6B7683 !important; }
  /* weather-forecast steht im Bericht immer offen (siehe weatherReportHtml) -
     der Aufklapp-Pfeil aus dem Panel ist hier ohne Funktion und wird
     entfernt, damit er nicht wie ein toter Bedienhinweis auf Papier wirkt. */
  .report-weather .weather-forecast summary::-webkit-details-marker,
  .report-weather .weather-forecast summary { cursor:default; }
  .report-weather .weather-table-wrap { overflow-x:visible; }
}

details.grp { margin-bottom:6px; }
details.grp summary { cursor:pointer; font-size:13px; font-weight:600; padding:6px 4px; list-style:none; display:flex; align-items:center; gap:6px; color:var(--text-heading); }
details.grp summary::-webkit-details-marker { display:none; }
details.grp summary .group-checkbox { margin:0; }
details.grp summary .grp-label { display:flex; align-items:center; flex:1 1 auto; min-width:0; }
details.grp summary .dot { width:11px; height:11px; border-radius:50%; margin-right:7px; flex:0 0 auto; }
details.grp summary .arrow { margin-left:auto; font-size:11px; color:var(--text-faint); transition:transform .15s; }
details.grp[open] summary .arrow { transform:rotate(90deg); }
/* Ergebnisliste von loadPhotoSpots() in js/main.js (Wikipedia-Geosuche). */
.photo-spots-list { list-style:none; margin:8px 0 0; padding:0; display:flex; flex-direction:column; gap:6px; }
.photo-spots-list li { display:flex; justify-content:space-between; align-items:baseline; gap:8px; font-size:12.5px; }
.photo-spots-list li a { flex:1 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.photo-spots-list li .muted { flex:0 0 auto; font-size:11px; }

/* Statische Tipp-Liste in photoTipsCard (index.html) - eigene, kompaktere
   Aufzählung statt Browser-Standard (zu große Abstände/Punktgröße für den
   sonst durchgängig kompakten Kartenstil). */
/* Tagesverlaufsband "Beste Zeit heute" (js/main.js lightBandHtml) - Nacht ->
   goldene Stunde -> Tag -> goldene -> blaue -> Nacht als Gradient, "Jetzt"
   als schmaler Strich. Farben bewusst fest (nicht themeabhängig, wie die
   Kartenkacheln auch): sie stellen echtes Tageslicht dar, kein UI-Element,
   das sich ans Farbschema anpassen sollte. */
.light-band { position:relative; height:34px; border-radius:10px; margin-top:4px; }
.light-band-now { position:absolute; top:-4px; bottom:-4px; width:3px; border-radius:2px; background:#0E141B; box-shadow:0 0 0 1px rgba(255,255,255,.6); }
.light-band-labels { display:flex; justify-content:space-between; margin-top:6px; font-size:12px; color:var(--text-faint); }
.light-tiles { display:flex; gap:9px; margin-top:10px; }
.light-tile { flex:1 1 0; padding:11px 13px; border-radius:13px; }
.light-tile-label { font-size:12px; font-weight:600; }
.light-tile-value { font-size:14px; font-weight:600; color:var(--text-heading); margin-top:2px; }
.light-tile-golden { background:#FDF6EA; }
.light-tile-golden .light-tile-label { color:#8A5200; }
.light-tile-blue { background:#EEF2FA; }
.light-tile-blue .light-tile-label { color:#2C4E86; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .light-tile-golden { background:#332918; }
  :root:not([data-theme="light"]) .light-tile-golden .light-tile-label { color:#E9A23B; }
  :root:not([data-theme="light"]) .light-tile-blue { background:#1c2636; }
  :root:not([data-theme="light"]) .light-tile-blue .light-tile-label { color:#7FB6FF; }
}
:root[data-theme="dark"] .light-tile-golden { background:#332918; }
:root[data-theme="dark"] .light-tile-golden .light-tile-label { color:#E9A23B; }
:root[data-theme="dark"] .light-tile-blue { background:#1c2636; }
:root[data-theme="dark"] .light-tile-blue .light-tile-label { color:#7FB6FF; }

.photo-tips-list { margin:8px 0 0; padding-left:18px; display:flex; flex-direction:column; gap:5px; font-size:12.5px; color:var(--text-body); }
.photo-tips-list li { line-height:1.4; }
/* Vier Themengruppen (Uhrzeit/Perspektive/Einstellungen/Video) statt einer
   einzigen langen Liste - .result-section-label sitzt sonst nur einmal pro
   Karte (siehe dort), hier mehrfach hintereinander, daher zusätzlicher
   Abstand nach oben zur vorherigen Gruppe. */
#photoTipsCard .result-section-label { margin-top:12px; }

.layer-row { display:flex; align-items:center; padding:3px 0 3px 18px; font-size:12.5px; gap:6px; color:var(--text-body); }
.layer-row label { flex:1 1 auto; cursor:pointer; display:flex; align-items:center; }
.layer-row input[type=checkbox] { margin:0; }
/* Kleines "?" neben einer Zeile, das ein Erklär-Popup öffnet (aktuell die
   Allgemeinerlaubnis, siehe js/generalPermit.js) - bewusst als runder Button
   statt als Fließtext-Link, damit es die Zeile nicht verlängert und auf dem
   Smartphone gross genug zum Antippen bleibt. */
.info-link {
  flex:0 0 auto; width:16px; height:16px; border-radius:50%;
  border:1px solid var(--border-strong); background:var(--bg-button); color:var(--text-muted);
  font-size:10.5px; font-weight:700; line-height:1; text-decoration:none;
  display:flex; align-items:center; justify-content:center;
}
.info-link:hover { background:var(--bg-button-hover); color:var(--text-heading); }
.layer-status { font-size:12px; color:var(--text-faint); flex:0 0 auto; min-width:14px; text-align:right; }
.layer-dot { width:9px; height:9px; border-radius:50%; margin-right:6px; flex:0 0 auto; box-shadow:inset 0 0 0 1px var(--dot-ring); }

/* Mindestlängen-Regler der Schiffs-Sonderlayer (js/shipTracker.js) - rückt wie
   die Checkbox-Reihen selbst ein, damit er optisch als deren Untereintrag lesbar ist. */
.ship-length-row { display:flex; align-items:center; padding:0 0 4px 18px; gap:8px; }
.ship-length-row input[type=range] { flex:1 1 auto; }
.ship-length-value { font-size:12.5px; color:var(--text-muted); flex:0 0 auto; min-width:38px; text-align:right; }

/* Beispiel-Mockup "App-Icon auf dem Startbildschirm" (Hilfe-Reiter
   "Startbildschirm") - dunkler Hintergrund simuliert einen Homescreen-
   Hintergrund, die Icons daneben sind reine Platzhalter (Emoji auf
   Farbfläche), nur das hervorgehobene Icon ist das echte App-Icon. Bewusst
   fest (nicht theme-abhängig) - simuliert immer ein typisches dunkles
   Smartphone-Homescreen-Hintergrundbild, unabhängig von der App-eigenen Theme. */
.homescreen-mockup { background:linear-gradient(160deg,#2c3e63,#1a2038); border-radius:14px; padding:16px 10px; }
.homescreen-mockup-grid { display:grid; grid-template-columns:repeat(3,1fr); gap:14px 6px; max-width:260px; margin:0 auto; }
.homescreen-mockup-app { display:flex; flex-direction:column; align-items:center; gap:4px; }
.homescreen-mockup-icon { width:46px; height:46px; border-radius:12px; display:flex; align-items:center; justify-content:center; font-size:22px; box-shadow:0 1px 3px rgba(0,0,0,.4); overflow:hidden; }
.homescreen-mockup-icon img { width:100%; height:100%; object-fit:cover; }
.homescreen-mockup-app span { font-size:9.5px; color:#fff; text-shadow:0 1px 2px rgba(0,0,0,.5); text-align:center; }
.homescreen-mockup-app.highlight .homescreen-mockup-icon { box-shadow:0 0 0 2px #fff, 0 2px 6px rgba(0,0,0,.5); background:#fff; }
.homescreen-mockup-app.highlight span { font-weight:600; }

/* Eigene Drohnenspots (Google My Maps, siehe js/mySpots.js): Leaflet-DivIcon
   ohne den weißen Standard-Rahmen/Hintergrund, stattdessen nur das SVG-Symbol
   mit weißem Halo + Schlagschatten zur besseren Lesbarkeit auf jedem
   Kartenuntergrund (auch auf der Satellitenansicht). */
.my-spot-icon { background:transparent; border:none; }
.my-spot-marker { display:flex; filter:drop-shadow(0 1px 3px rgba(0,0,0,.45)); }

/* Live-Schiffspositionen (Kreuzfahrt/Fracht, siehe js/shipTracker.js): wie
   my-spot-icon ohne Standard-Rahmen, die SVG-Rumpf-Silhouette wird per
   transform:rotate auf den Kurs/Heading des Schiffs ausgerichtet. */
.ship-icon { background:transparent; border:none; }
.ship-marker { display:flex; filter:drop-shadow(0 1px 2px rgba(0,0,0,.5)); transition:transform .3s linear; }

/* Polizeistationen (js/policeStations.js): gleiches Prinzip wie
   ship-icon/my-spot-icon oben - kein Leaflet-Standardrahmen, nur das
   Schild-SVG mit Schlagschatten. */
.police-marker-wrap { background:transparent; border:none; }
.police-marker { display:flex; filter:drop-shadow(0 1px 2px rgba(0,0,0,.5)); }
.police-popup { display:flex; flex-direction:column; gap:2px; }
.police-popup-route { margin-top:4px; font-weight:600; }

.hpa-popup p { margin:4px 0; font-size:12.5px; line-height:1.4; }

/* Textlink unterhalb einer .layer-row-Checkbox statt eines eigenen Buttons -
   "Nächste Polizeistation" (siehe policeNearestLink in index.html) betrifft
   nicht die Ebene selbst, sondern eine Einzelsuche zum zuletzt geprüften
   Punkt, deshalb bewusst kein weiteres Kästchen. */
.layer-action-link { display:block; padding:2px 0 4px 18px; font-size:12px; color:var(--link); text-decoration:none; }
.layer-action-link:hover { text-decoration:underline; }
.layer-action-link.is-loading { opacity:.6; pointer-events:none; }

/* Popup-Inhalt der Flug-Spots (js/flightSpots.js) - Verschieben/Bericht/
   Löschen-Knöpfe klein und nebeneinander, wie die übrigen Knopfgruppen im
   Panel, nicht wie die großen, vollbreiten Formular-Knöpfe. */
.spot-popup { min-width:170px; max-width:230px; }
/* Spot-Foto im Karten-Popup (js/flightSpots.js popupPhotoHtml, siehe
   supabase/migration_013_spot_foto.sql) - volle Popup-Breite, feste
   Ziel-Höhe mit object-fit:cover statt der jeweiligen Bildproportion, damit
   Popups untereinander gleich hoch bleiben, unabhängig vom Seitenverhältnis
   des hochgeladenen Fotos. */
.spot-popup-photo { display:block; width:100%; height:120px; object-fit:cover; border-radius:8px; margin-top:6px; }
.spot-popup-actions { display:flex; flex-wrap:wrap; gap:5px; margin-top:6px; }
.spot-popup-actions button {
  font-size:11.5px; padding:4px 8px; border-radius:5px; border:1px solid var(--border-strong);
  background:var(--bg-button); color:var(--text-body); cursor:pointer; font-family:inherit;
}
.spot-popup-actions button:hover { background:var(--bg-button-hover); }
.spot-shared-badge {
  display:inline-block; font-size:10px; font-weight:700; padding:1px 6px; border-radius:8px;
  background:#00897B; color:#fff; vertical-align:middle;
}
/* Art-Badge (geplant/erledigt) - seit "Meine Spots" beide Arten in
   derselben Ebene zeigt, reicht die Markerfarbe allein nicht mehr als
   eindeutiges Unterscheidungsmerkmal, siehe ownSpotPopupHtml in
   js/flightSpots.js. Dieselben Farben wie die Marker-Icons dort. */
.spot-kind-badge {
  display:inline-block; font-size:10px; font-weight:700; padding:1px 6px; border-radius:8px;
  color:#fff; vertical-align:middle; margin-right:3px;
}
.spot-kind-want { background:#1565C0; }
.spot-kind-flown { background:#2E7D32; }

/* Hauptmenü-Reiter "Spots" (js/spotsPanel.js) - Ergebnis-Badge (rating-good/
   -caution/-bad/-unknown liefern die Custom Properties, siehe die
   allgemeinen .rating-*-Regeln weiter unten) und ein "Privat"-Gegenstück zum
   bestehenden .spot-shared-badge (Nutzer-Feedback: "man sieht kaum ob ein
   Spot geteilt ist" - beide Zustände jetzt gleich auffällig als Pille). */
.spots-panel-badge {
  display:inline-block; font-size:10px; font-weight:700; padding:1px 6px; border-radius:8px;
  background:var(--rating-bg); color:var(--rating-fg); border:1px solid var(--rating-border);
  vertical-align:middle; margin-right:3px;
}
.spots-panel-private-badge {
  display:inline-block; font-size:10px; font-weight:700; padding:1px 6px; border-radius:8px;
  background:var(--bg-button); color:var(--text-muted); border:1px solid var(--border-strong);
  vertical-align:middle;
}
.spots-panel-edit-row { display:block; }
.spots-panel-edit-form { flex:1 1 auto; }
/* Such-Feld je Liste (Spots/Fluglog, js/spotsPanel.js) - beide Listen können
   auf über 100 Einträge wachsen, seitenweises Laden allein reicht dann nicht
   mehr, um einen bestimmten Eintrag wiederzufinden. */
.spots-panel-search { display:block; width:100%; margin-bottom:8px; }
/* Sortier-Auswahl + "Alle auswählen" über der Liste (js/spotsPanel.js
   sortSelectHtml/listHtml). */
.spots-panel-controls { display:flex; align-items:center; justify-content:space-between; gap:8px; margin-bottom:6px; flex-wrap:wrap; }
.spots-panel-sort { flex:0 0 auto; }

/* "Als Spot speichern"-Modal (index.html #spotSaveModal) - Art-Auswahl als
   zwei nebeneinanderstehende Radio-Labels statt Dropdown, da nur zwei feste
   Optionen. */
.spot-save-kind-row { display:flex; gap:14px; margin-bottom:4px; font-weight:600; }
.spot-save-kind-row label { display:flex; align-items:center; gap:5px; cursor:pointer; font-weight:400; }
.spot-shared-checkbox { display:flex; align-items:center; gap:7px; margin-top:10px; cursor:pointer; }
.spot-shared-hint { margin-top:4px; }

/* "Bericht erstellen"-Modal (index.html #reportOptionsModal, js/reportOptions.js):
   Unteroptionen (AE-Dokument, Detailgrad Scheine/Versicherung) hängen von der
   jeweils darüberstehenden Checkbox ab - Einrückung statt eigener Karte macht
   die Zugehörigkeit auf den ersten Blick klar. disabled statt hidden, wenn die
   übergeordnete Checkbox aus ist, damit die Formularstruktur beim Umschalten
   nicht springt. */
.report-opt-sub { margin-left:26px; margin-top:4px; }
.report-opt-radio-row { display:flex; flex-wrap:wrap; gap:6px 16px; font-weight:400; }
.report-opt-radio-row label { display:flex; align-items:center; gap:5px; cursor:pointer; }
.report-opt-sub:has(input:disabled) { opacity:.5; }

/* "Aktueller Standort"-Symbol (js/main.js CURRENT_POSITION_ICON): blauer
   Punkt mit auslaufendem Puls-Ring, wie bei gängigen Standortanzeigen üblich -
   unterscheidet den GPS-Punkt optisch klar vom normalen Pin-Marker eines
   manuell geprüften Punkts. */
.current-pos-icon { background:transparent; border:none; }
.current-pos-dot {
  width:16px; height:16px; border-radius:50%; background:#1565c0;
  border:3px solid #fff; box-shadow:0 1px 4px rgba(0,0,0,.45); position:relative;
}
.current-pos-pulse {
  position:absolute; inset:-8px; border-radius:50%; background:rgba(21,101,192,.35);
  animation: current-pos-pulse 2s ease-out infinite;
}
@keyframes current-pos-pulse {
  0% { transform:scale(0.6); opacity:.8; }
  100% { transform:scale(1.9); opacity:0; }
}

/* "Ungefährer Standort"-Symbol (js/main.js APPROX_POSITION_ICON): wie
   current-pos-*, aber bernsteinfarben statt blau - signalisiert optisch klar
   "nur ungefähr" (IP-Ortung als Fallback, keine echte GPS-Messung). */
.approx-pos-icon { background:transparent; border:none; }
.approx-pos-dot {
  width:16px; height:16px; border-radius:50%; background:#e65100;
  border:3px solid #fff; box-shadow:0 1px 4px rgba(0,0,0,.45); position:relative;
}
.approx-pos-pulse {
  position:absolute; inset:-8px; border-radius:50%; background:rgba(230,81,0,.35);
  animation: current-pos-pulse 2s ease-out infinite;
}


/* Release-Notes-Modal (js/changelog.js): nutzt dieselbe Modal-Hülle wie
   Impressum/Datenschutz (.legal-modal/.legal-backdrop), eigener Inhalt. */
.changelog-modal-title { font-size:15px; font-weight:700; color:var(--text-heading); padding:10px 4px 10px 14px; }
.changelog-list { display:flex; flex-direction:column; gap:12px; }
.changelog-row { border-bottom:1px solid var(--border-light); padding-bottom:10px; }
.changelog-row:last-child { border-bottom:none; padding-bottom:0; }
.changelog-row-head { display:flex; align-items:center; gap:8px; margin-bottom:3px; }
.changelog-version { font-weight:700; font-size:14px; color:var(--text-heading); }
.changelog-date { font-size:11px; color:var(--text-faint); margin-left:auto; }
.changelog-badge { font-size:10px; font-weight:700; padding:1px 7px; border-radius:10px; text-transform:uppercase; letter-spacing:.3px; }
.changelog-badge-feature { background:#e3f2fd; color:#1565c0; }
.changelog-badge-patch { background:#f1f1f1; color:#777; }
.changelog-notes { font-size:12.5px; line-height:1.5; color:var(--text-body); }
/* Release Notes als Aufstellung statt Fließtext: Ein Textblock zwingt dazu,
   jeden Satz zu lesen, um zu sehen, ob etwas Relevantes dabei ist - eine Liste
   lässt sich überfliegen. Der fett gesetzte Anfang jedes Punktes dient dabei
   als Stichwort zum Anspringen. */
.changelog-list-items { margin:0; padding-left:17px; display:flex; flex-direction:column; gap:5px; }
.changelog-list-items li { padding-left:1px; }
.changelog-list-items li::marker { color:var(--text-faint); }
/* Fließtext-Fassung (frisch angehängte Einträge vor dem Verdichten) */
.changelog-notes p { margin:0 0 7px 0; }
.changelog-notes p:last-child { margin-bottom:0; }

/* Kleine Abschnittsüberschrift innerhalb der Prüfergebnis-Karte (aktuell nur
   vor .drone-class-area) - macht "Deine Angaben" als eigenen Abschnitt
   erkennbar, statt dass Drohnenklasse/AE nahtlos an die Zonen-Details
   anschließen. Gleiche Optik wie .basemap-group (kleine, gedämpfte
   Kapitälchen-Zeile als Gruppierung). */
.result-section-label {
  font-size:10.5px; font-weight:700; text-transform:uppercase; letter-spacing:.05em;
  color:var(--text-faint); margin:0 0 4px 0;
}

/* Drohnenklassen-Auswahl (js/droneClass.js) - Teil der Prüfergebnis-Karte
   statt eigener Karte, um eine Karten-/Klapp-Ebene zu sparen. */
.drone-class-area { margin-top:10px; padding-top:10px; border-top:1px solid var(--border); }
#droneClassSelect {
  width:100%; box-sizing:border-box; font-family:inherit; font-size:13px; padding:7px 8px;
  border:1px solid var(--border-strong); border-radius:6px; background:var(--bg-card); color:var(--text-body);
}
.drone-class-info { margin-top:6px; line-height:1.5; }

/* Feedback-Modal (js/feedback.js): nutzt ebenfalls die .legal-modal-Hülle. */
#feedbackForm { display:flex; flex-direction:column; gap:4px; }
#feedbackForm label { font-weight:600; margin-top:8px; }
#feedbackForm label:first-child { margin-top:0; }
#feedbackForm textarea,
#feedbackForm input[type=email],
#feedbackForm input[type=tel] {
  font-family:inherit; font-size:13px; padding:8px 10px; border:1px solid var(--border-strong);
  border-radius:6px; background:var(--bg-card); color:var(--text-body); resize:vertical;
}
#feedbackForm textarea:focus,
#feedbackForm input[type=email]:focus,
#feedbackForm input[type=tel]:focus { outline:2px solid var(--text-muted); outline-offset:1px; }
#feedbackForm button.wide { margin-top:12px; margin-bottom:0; }

/* Honeypot: visuell und für Screenreader verborgen, aber weiterhin im DOM
   vorhanden und ausfüllbar - display:none wird von manchen Bots erkannt und
   umgangen, diese Off-Screen-Technik ist zuverlässiger. */
.feedback-honeypot {
  position:absolute; left:-9999px; top:-9999px; width:1px; height:1px; overflow:hidden;
}

.feedback-diagnostics { margin-top:14px; padding-top:10px; border-top:1px solid var(--border-light); }
.feedback-diag-list { list-style:none; margin:8px 0 0 0; padding:0; font-size:11.5px; line-height:1.6; color:var(--text-muted); }
.feedback-diag-list b { color:var(--text-heading); font-weight:600; }

#feedbackStatus.feedback-status-ok { background:#e8f5e9; border-color:#66bb6a; color:#1b5e20; }

/* Konto-Modal (js/account.js): nutzt ebenfalls die .legal-modal-Hülle,
   Formularfelder analog zu #feedbackForm. */

/* Am Desktop in beide Richtungen frei größenveränderbar (Nutzerwunsch) -
   gilt für Konto- UND Hilfe-Fenster (siehe .resizable-modal-desktop unten),
   die übrigen .legal-modal-Fenster (Impressum/Datenschutz/Feedback/"Was ist
   neu") bleiben unverändert fest. Eigene Rand-Ziehgriffe (rechts/unten/
   Ecke, siehe z.B. accountModalResizeE/S/SE bzw. helpModalResizeE/S/SE in
   index.html und initModalResize in js/resizableModal.js), gleiche Pointer-
   Event-Technik wie beim Panel (#panelResizeHandle) - ERSETZT die zuerst
   beim Konto-Fenster verwendete native CSS-resize-Eigenschaft: deren
   Ziehgriff saß nur in der Ecke und wurde als "nicht sehr deutlich"
   zurückgemeldet, ein Ziehen an einer ganzen Seite war erwartet worden.
   Persistierte Maße kommen als Inline-Style (höchste Priorität, schlägt
   jede Media Query) - deshalb NUR am Desktop wiederherstellen, sonst würde
   eine am Desktop gespeicherte Breite auf einem Handy die eigentlich
   gewollte Vollbild-Regel weiter unten überschreiben. */
/* Selektor mit .legal-modal kombiniert (höhere Spezifität als .legal-modal
   allein), sonst gewinnt dessen eigenes max-height:640px (siehe dort) gegen
   das hier gewollte 92vh, unabhängig von der Reihenfolge im Stylesheet -
   gefunden beim Testen der Hilfe-Fenster-Größenänderung: Ziehen an der
   Unterkante hatte oberhalb von 640px keine Wirkung mehr. */
.legal-modal.resizable-modal-desktop { min-width:360px; min-height:340px; max-width:92vw; max-height:92vh; }

/* Trefffläche je 10px breit/hoch, deutlich größer als der einzelne native
   Ecken-Griff vorher - sichtbarer Strich (4px) erscheint erst bei Hover/
   Fokus/Ziehen, ein dauerhaft sichtbarer Rahmen wäre unnötig aufdringlich.
   Gleiches Muster wie #panelResizeHandle oben. */
@media (min-width: 769px) {
  .resizable-modal-resize { position:absolute; z-index:2; touch-action:none; }
  .resizable-modal-resize::before {
    content:''; position:absolute; border-radius:2px; background:var(--border-strong);
    opacity:0; transition:opacity .15s ease;
  }
  .resizable-modal-resize:hover::before,
  .resizable-modal-resize:focus-visible::before,
  .resizable-modal-resize.dragging::before { opacity:1; }
  .resizable-modal-resize:focus-visible { outline:2px solid var(--link); outline-offset:-2px; }

  .resizable-modal-resize-e { top:0; right:-5px; width:10px; height:100%; cursor:ew-resize; }
  .resizable-modal-resize-e::before { top:50%; left:50%; width:4px; height:38px; transform:translate(-50%,-50%); }

  .resizable-modal-resize-s { bottom:-5px; left:0; width:100%; height:10px; cursor:ns-resize; }
  .resizable-modal-resize-s::before { top:50%; left:50%; width:38px; height:4px; transform:translate(-50%,-50%); }

  /* Über den Kanten (höherer z-index), damit die Ecke beim Überlappen
     gewinnt statt zufällig E oder S. */
  .resizable-modal-resize-se { bottom:-6px; right:-6px; width:16px; height:16px; cursor:nwse-resize; z-index:3; }
  .resizable-modal-resize-se::before { inset:3px; width:auto; height:auto; border-radius:3px; }
}
@media (max-width: 768px) {
  /* Am Handy wie bisher: fester Vollbild-Zuschnitt, keine Ziehgriffe. */
  .resizable-modal-resize { display:none; }
}
body.resizable-modal-resizing { user-select:none; }
body.resizable-modal-resizing.resizing-e { cursor:ew-resize; }
body.resizable-modal-resizing.resizing-s { cursor:ns-resize; }
body.resizable-modal-resizing.resizing-se { cursor:nwse-resize; }

/* Sprache/Farbschema, aus der Panel-Kopfzeile hierher verschoben (siehe
   Kommentar in index.html) - eigener Block über dem eigentlichen
   Login-/Stammdaten-Bereich, per Trennlinie abgesetzt, damit klar bleibt:
   das hier gilt unabhängig vom Anmeldezustand. */
.account-settings { padding-bottom:14px; margin-bottom:14px; border-bottom:1px solid var(--border-light); }
.account-settings-row { display:flex; align-items:center; justify-content:space-between; gap:10px; margin-top:8px; font-size:13.5px; }

/* Konto-Reiter: Profil-/E-Mail-Formulare bekommen einen Trennstrich
   zueinander, "Konto löschen" steht als eigener, deutlich abgesetzter
   Bereich am Ende (js/account.js accountTabHtml). */
.account-form + .account-form { margin-top:18px; padding-top:16px; border-top:1px solid var(--border-light); }
.account-danger-zone { margin-top:18px; padding-top:16px; border-top:1px solid var(--border-light); }
.account-delete-btn { background:none; border-color:#C42B1C; color:#C42B1C; }
.account-delete-btn:hover { background:#FCEAE8; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .account-delete-btn { border-color:#FF6E5E; color:#FF6E5E; }
  :root:not([data-theme="light"]) .account-delete-btn:hover { background:#2f1a1c; }
}
:root[data-theme="dark"] .account-delete-btn { border-color:#FF6E5E; color:#FF6E5E; }
:root[data-theme="dark"] .account-delete-btn:hover { background:#2f1a1c; }
.account-delete-confirm-text { padding:9px 11px; border-radius:8px; background:var(--rating-bg); color:var(--rating-fg); border:1px solid var(--rating-border); font-size:13px; margin:0 0 10px 0; }
.account-form { display:flex; flex-direction:column; gap:4px; }
.account-form label { font-weight:600; margin-top:8px; }
.account-form label:first-child { margin-top:0; }
/* Rahmen/Radius/Farben/Fokuszustand kommen von der allgemeinen
   input[type=text]-Regel ganz oben in der Datei - hier nur noch das für
   dieses schmale Modal passende, etwas kompaktere Innenmaß und die
   Mindesthöhe der Notizfelder. */
.account-form textarea { resize:vertical; min-height:50px; }
.account-form button.wide { margin-top:12px; margin-bottom:0; }
.account-links { display:flex; justify-content:space-between; margin-top:10px; font-size:12.5px; }
#accountStatus.account-status-ok { background:#e8f5e9; border-color:#66bb6a; color:#1b5e20; }
/* Knopf "Bestätigungsmail erneut senden" innerhalb der Login-Fehlermeldung
   (siehe showEmailNotConfirmedStatus in js/account.js) - #accountStatus ist
   normalerweise reiner Text (showStatus setzt textContent), dieser eine Fall
   braucht innerHTML für den eingebetteten Knopf. */
.account-resend-btn {
  margin-top:8px; padding:6px 10px; font-size:12px; font-weight:600;
  border:1px solid currentColor; border-radius:5px; background:transparent; color:inherit; cursor:pointer;
}
.account-resend-btn:hover { background:rgba(0,0,0,.06); }
.account-resend-btn:disabled { opacity:.6; cursor:default; }
/* Login-Status (E-Mail + Abmelden) sitzt ganz unten im Konto-Fenster, als
   ruhige Fußzeile statt einer grossen Schaltfläche oben (siehe
   screenAccountHtml) - klein, gedämpfte Farbe, kein "wide"-Knopf. Die
   Stammdaten-Tabs/-Liste sind der eigentliche Fensterinhalt und sollen
   direkt beim Öffnen im Blick sein. */
.account-footer {
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  margin-top:16px; padding-top:10px; border-top:1px solid var(--border);
  font-size:11.5px; color:var(--text-faint);
}
.account-footer-email { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.account-footer-logout {
  flex:0 0 auto; font-family:inherit; font-size:11.5px; padding:4px 9px; border:1px solid var(--border-strong);
  border-radius:5px; background:var(--bg-button); color:var(--text-body); cursor:pointer;
}
.account-footer-logout:hover { background:var(--bg-button-hover); }

/* Stammdaten-/Einstellungs-Tabs (Drohnen/AE/Drohnenscheine/Versicherungen/
   Einstellungen/Konto, js/account.js) - Icon oben, kurze Beschriftung
   darunter (ENTITY_TAB_ICONS/ENTITY_TAB_LABEL_KEYS), gleiches Muster wie die
   Hauptreiter .panel-tab: bei sechs Einträgen brach eine reine Textpille bei
   "Konto" regelmäßig in eine eigene Zeile um, ein reines Icon (z.B. beim
   Versicherung-Symbol) war nicht immer eindeutig genug. Kleine Schrift +
   flex:1 1 0 (gleich breite Spalten) halten trotzdem alle sechs in einer
   Zeile. */
.account-entity-tabs { display:flex; gap:2px; padding-bottom:8px; margin-bottom:10px; border-bottom:1px solid var(--border-light); }
.account-entity-tab {
  display:flex; flex-direction:column; align-items:center; gap:3px;
  flex:1 1 0; min-width:0; border:none; border-radius:9px; padding:5px 2px;
  background:none; color:var(--text-faint); cursor:pointer; font-family:inherit;
}
.account-entity-tab span { font-size:9.5px; font-weight:600; line-height:1.1; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:100%; }
.account-entity-tab:hover { color:var(--text-heading); }
.account-entity-tab.active { color:var(--link); background:var(--hover-tint); }
.account-entity-body { margin-top:10px; }
.account-entity-empty { margin:0 0 10px 0; }
/* Bei vielen Einträgen (Admin-Nutzerliste, Spots/Fluglog, aber auch
   Drohnen/AE-Erlaubnisse/Scheine/Versicherungen) scrollt nur diese Liste
   selbst statt des ganzen Panels/Modals - Suche/Filter/Mehrfachauswahl
   davor bleiben dadurch immer sichtbar. Bei wenigen Einträgen bleibt der
   Kasten so hoch wie der Inhalt (max-height greift erst, wenn er überschritten
   wird), also keine Änderung für kurze Listen. */
.account-entity-list { display:flex; flex-direction:column; gap:6px; max-height:min(48vh, 420px); overflow-y:auto; overflow-x:hidden; }
.account-entity-row {
  display:flex; align-items:center; justify-content:space-between; gap:8px;
  padding:8px 10px; border:1px solid var(--border); border-radius:6px; background:var(--bg-button);
}
.account-entity-row-main { flex:1 1 auto; display:flex; flex-direction:column; gap:2px; min-width:0; font-size:13px; }
/* Landeswappen bei AE-Erlaubnissen (js/account.js bundeslandWappenHtml,
   Bilddateien in brand/wappen/) - leicht abgerundete Ecken statt Kreis, da ein
   Wappenschild in einem Kreis beschnitten wirkt; helle Fläche dahinter, weil
   einzelne Wappen (z.B. Sachsen) auf transparentem Grund helle/weiße Elemente
   am Rand haben, die im Dark Mode sonst verschwimmen würden. */
.account-bundesland-badge {
  flex:0 0 auto; width:28px; height:28px; border-radius:5px; overflow:hidden;
  background:#fff; border:1px solid var(--border);
}
.account-bundesland-badge img { width:100%; height:100%; object-fit:contain; display:block; }
/* Bauform-Symbol in der Drohnenliste (js/account.js droneShapeIconHtml,
   DRONE_SHAPE_ICONS) statt eines Fotos. */
.account-drone-icon {
  display:flex; align-items:center; justify-content:center;
  flex:0 0 auto; width:32px; height:32px; border-radius:6px;
  background:var(--bg-app); border:1px solid var(--border); color:var(--text-muted);
}
.account-entity-row-main span { font-size:11.5px; }
.account-entity-row-actions { display:flex; gap:2px; flex:0 0 auto; }
/* Spots/Fluglog haben bis zu 5 Aktions-Buttons pro Zeile (Orten, Bericht,
   Teilen/Verschieben, Bearbeiten, Löschen) - auf Telefonbreite reichte dafür
   selbst nach der Titel/Badge-Korrektur (siehe .account-entity-row-line
   weiter oben) der verbleibende Platz nicht mehr, die Buttons liefen über
   den Rand hinaus statt umzubrechen (DRO-8). max-width erzwingt einen
   Umbruch auf zwei kurze Zeilen (die Grid-Spalte "auto" würde sich sonst
   weiterhin an der vollen, unumbrochenen Breite orientieren) statt einer
   einzelnen, zu breiten Zeile - macht die Spalte insgesamt schmaler und
   damit mehr Platz für Titel/Badges/Ort in der Mitte frei. */
@media (max-width: 480px) {
  .spots-panel-row .account-entity-row-actions {
    flex-wrap:wrap; justify-content:flex-end; row-gap:2px; max-width:82px;
  }
  .spots-panel-row .account-entity-row-actions button { padding:4px; }
}
.account-entity-row-actions button {
  display:flex; align-items:center; justify-content:center;
  padding:6px; border:1px solid var(--border-strong); border-radius:5px;
  background:var(--bg-card); color:var(--text-body); cursor:pointer;
}
.account-entity-add-btn { margin-top:10px; }
.account-entity-form-actions { display:flex; gap:8px; margin-top:12px; }
.account-entity-form-actions button.wide { margin-top:0; flex:1 1 auto; }
.account-entity-form-actions button[data-entity-cancel] { background:var(--bg-button); }

/* Admin-Nutzerzeile UND Spots-/Fluglog-Zeile (js/account.js adminUserRowHtml,
   js/spotsPanel.js wantRowHtml/flownRowHtml): Checkbox + Inhalt (max. 2
   Zeilen, siehe .account-entity-row-title/-line unten) + schmale
   Icon-Buttons (.account-entity-row-actions, gleicher Stil wie Drohnen-/
   AE-Listen) statt vorher breiter beschrifteter Knöpfe bzw. bis zu 4
   Textzeilen - bei mehreren tausend Einträgen muss jede Zeile knapp und
   einheitlich hoch bleiben. Grid statt Flex, damit Checkbox/Aktionen über
   die volle (ggf. zweizeilige) Höhe der mittleren Spalte vertikal zentriert
   bleiben, unabhängig vom umgebenden Fenster (Konto-Modal vs. schmales
   Hauptmenü-Panel).*/
.account-admin-user-row,
.spots-panel-row {
  display:grid; grid-template-columns:auto 1fr auto; align-items:center; column-gap:8px;
}
.account-admin-user-row .account-entity-row-main,
.spots-panel-row .account-entity-row-main {
  min-width:0;
}
/* flex-wrap+overflow:hidden statt nowrap: Titel schrumpft zwar per
   min-width:0/Ellipsis, die Status-Pillen daneben (flex-shrink:0, siehe
   .spots-panel-badge/-private-badge/.spot-shared-badge) aber nicht - bei
   zwei Pillen gleichzeitig (Fluglog-Zeile: Ergebnis- UND Geteilt/Privat-
   Badge) reichte der geschrumpfte Titel allein irgendwann nicht mehr, der
   Zeileninhalt lief dann sichtbar in die Aktions-Buttons daneben hinein
   (DFC-7) - jetzt rutscht eine nicht mehr passende Pille in eine zweite
   Zeile statt zu überlappen, overflow:hidden fängt den (kaum noch
   vorkommenden) Rest ab. */
.account-entity-row-line { display:flex; flex-wrap:wrap; align-items:center; gap:4px; min-width:0; overflow:hidden; }
.account-entity-row-title { flex:1 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* Kleine Vorschau eines hochgeladenen Spot-Fotos (siehe js/spotsPanel.js
   photoFieldHtml/migration_013_spot_foto.sql) - in der Liste nur ein
   winziger Indikator vor dem Titel, die eigentliche Größe zeigt erst das
   Bearbeiten-Formular (.spots-panel-photo-preview) bzw. das Karten-Popup. */
.spots-panel-row-thumb { flex:0 0 auto; width:22px; height:22px; border-radius:5px; object-fit:cover; }
.spots-panel-photo-preview { display:flex; align-items:flex-end; gap:10px; margin:4px 0 8px 0; }
.spots-panel-photo-preview img { width:100px; height:75px; border-radius:8px; object-fit:cover; border:1px solid var(--border); }
.spots-panel-photo-hint { margin:4px 0 0 0; font-size:11px; }
.account-admin-user-row .account-entity-row-main > span.muted,
.spots-panel-row .account-entity-row-main > span.muted {
  display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.spots-panel-badge, .spots-panel-private-badge, .spot-shared-badge { flex-shrink:0; }
/* Eigene, deutlich kompaktere Optik statt des app-weiten 36px breiten
   Schalter-Looks (siehe input[type=checkbox] oben) - hier geht es um
   Mehrfachauswahl in einer dichten Liste (Admin-Nutzer, Spots/Fluglog,
   Drohnen/AE/Scheine/Versicherungen), nicht um eine Einstellung, ein
   kleines Häkchen-Kästchen spart auf schmalen Bildschirmen spürbar Platz
   für Titel/Badges/Ort daneben (DRO-8). content:none auf ::before hebt den
   ererbten Schalter-Punkt wieder auf, ::after zeichnet stattdessen das
   Häkchen nur im angehakten Zustand. Selektor bewusst mit vorangestelltem
   input[type=checkbox] (nicht nur .account-entity-select) - die allgemeine
   Schalter-Regel oben hat sonst durch die Attribut-Selektor-Kombination
   höhere Spezifität und würde diese Überschreibung sonst ignorieren. */
input[type=checkbox].account-entity-select {
  appearance:none; -webkit-appearance:none;
  width:18px; height:18px; border-radius:4px; flex:0 0 auto; margin:0; cursor:pointer;
  border:1.5px solid var(--border-strong); background:var(--bg-card); position:relative;
}
input[type=checkbox].account-entity-select::before { content:none; }
input[type=checkbox].account-entity-select:checked { background:var(--link); border-color:var(--link); }
input[type=checkbox].account-entity-select:checked::after {
  content:''; position:absolute; left:5px; top:2px; width:5px; height:9px;
  border:solid #fff; border-width:0 2px 2px 0; transform:rotate(45deg);
}
.account-admin-btn {
  padding:6px 9px; font-size:11px; font-weight:600; white-space:nowrap;
  border:1px solid var(--border-strong); border-radius:5px;
  background:var(--bg-card); color:var(--text-body); cursor:pointer;
}
.account-admin-btn:hover { background:var(--bg-button-hover); }
/* "Alle auswählen"-Zeile + Bulk-Aktionsleiste, sobald mindestens ein
   Eintrag ausgewählt ist (js/account.js adminBulkBarHtml, js/spotsPanel.js
   bulkBarHtml) - sonst kein optischer Mehraufwand gegenüber vorher. */
.account-select-all-row { display:flex; align-items:center; gap:6px; font-size:12px; margin-bottom:6px; cursor:pointer; }
.account-bulk-bar {
  display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:8px;
  padding:6px 10px; margin-bottom:8px; border-radius:6px;
  background:var(--hover-tint); border:1px solid var(--border-strong); font-size:12px; font-weight:600;
}
.account-bulk-bar-actions { display:flex; flex-wrap:wrap; gap:5px; }
/* Rollen-/Status-/Sortier-Filter über der Nutzerliste (js/account.js
   adminUsersFilterBarHtml) - kann auf mehrere tausend Nutzer wachsen, Suche
   allein reicht dann nicht immer, um schnell z.B. nur die deaktivierten
   Konten zu sehen oder nach Rolle/Datum sortiert zu sichten. */
.admin-users-filter-row { display:flex; gap:8px; margin-bottom:8px; }
.admin-users-filter-row select { flex:1 1 0; min-width:0; }

/* Dokument-Feld (PDF/Foto, js/account.js entityDocumentFieldHtml) für
   AE-Erlaubnisse, Drohnenscheine und Versicherungen. Vorhandenes Dokument
   als eigene, deutlich abgesetzte Zeile mit Datei-Icon, Dateiname sowie
   Anzeigen-/Entfernen-Knopf - direkt darunter das Auswahlfeld für eine neue
   (Ersatz-)Datei, damit auf einen Blick klar ist, was schon hinterlegt ist
   und wie es sich ändern lässt. */
.account-entity-doc-current {
  display:flex; align-items:center; gap:7px; margin-top:6px; padding:7px 9px;
  border:1px solid var(--border-strong); border-radius:6px; background:var(--bg-button);
}
.account-entity-doc-icon { font-size:16px; flex:0 0 auto; }
.account-entity-doc-name { flex:1 1 auto; min-width:0; font-size:12.5px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.account-entity-doc-current button {
  flex:0 0 auto; display:flex; align-items:center; justify-content:center;
  padding:6px; border:1px solid var(--border-strong);
  border-radius:5px; background:var(--bg-card); color:var(--text-body); cursor:pointer;
}
.account-entity-doc-hint { font-size:11px; margin-top:3px; }
.account-form input[type=file] {
  font-family:inherit; font-size:12px; margin-top:6px; padding:6px 0; color:var(--text-body);
}
/* Datei-Symbol in der Listenzeile (entityListHtml) - zeigt schon dort, ohne
   das Formular zu öffnen, dass ein Dokument hinterlegt ist, UND öffnet es
   direkt per Klick (wichtig z.B. bei einer Kontrolle vor Ort) - deshalb ein
   <button> mit zurückgesetzten Button-Standardstilen statt eines <span>.
   Selektor bewusst mit .account-entity-row-actions davor (statt nur die
   Klasse) - sonst gewinnt die allgemeine, gerahmte Knopf-Optik von
   ".account-entity-row-actions button" (höhere Spezifität durch den
   zusätzlichen Element-Teil) und das Symbol bekäme ungewollt Rahmen/
   Hintergrund wie Stift/Papierkorb daneben. */
.account-entity-row-actions .account-entity-doc-badge {
  display:flex; align-items:center; justify-content:center;
  flex:0 0 auto; border:none; background:none; padding:4px; cursor:pointer;
  border-radius:4px; color:var(--text-muted);
}
.account-entity-row-actions .account-entity-doc-badge:hover { background:var(--bg-button-hover); }

/* Info-Kasten unter der EU-Klassen-Auswahl (js/account.js
   droneKlasseFieldHtml/droneKlasseInfoHtml) - zeigt Unterkategorie und
   Kurzregeln bzw. bei "Bestandsdrohne" die aus der Startmasse ermittelte
   Einstufung. Gleiche ruhige Optik wie der Dokument-Bereich, damit beide
   automatisch befüllten Infoflächen im Formular als zusammengehöriges
   Muster erkennbar sind. */
.account-entity-klasse-info { margin-top:6px; }
.account-entity-klasse-info:empty { margin-top:0; }
.account-entity-klasse-info p { margin:0 0 4px 0; font-size:12px; }
.account-entity-klasse-info p:last-child { margin-bottom:0; }
/* Hinweis nach automatisch übernommenem Klassen-Vorschlag (js/droneCatalog.js) -
   dieselbe Warnfarbe wie die Ampel-Stufe "caution", damit auf einen Blick
   klar ist: das ist eine Annahme, keine geprüfte Angabe. */
.account-klasse-vorschlag { color:var(--rating-fg); background:var(--rating-bg); border-radius:6px; padding:4px 7px; }

/* Spenden-Karte (js/donation.js): Link-URL kommt aus data/donation.json,
   Pflege über die lokale Admin-Seite. PayPal-typisches Gelb als Button.
   Karte selbst bewusst prominent statt wie die übrigen, neutralen Karten:
   warmer Gold-Rahmen/-Hintergrundton statt var(--bg-card)/var(--border),
   steht direkt oben im Panel (siehe index.html) statt weiter unten. */
.donation-card {
  background:var(--donation-bg); border-color:var(--donation-border);
}
.donation-card > summary { font-size:14px; }
.donation-btn {
  display:block; text-align:center; text-decoration:none; font-weight:700; font-size:14px;
  padding:9px 6px; border-radius:6px; background:#ffc439; color:#111; margin-top:4px;
}
.donation-btn:hover { background:#f2b636; }

/* Sicherheitsabstand zur Home-Indicator-Leiste im iOS-Vollbildmodus, damit
   Suchfeld/Versionsanzeige unten links dort nicht unerreichbar werden.
   z-index über #panel (1100) - auf schmalen Bildschirmen ist #panel ein von
   unten hochgezogenes Sheet (siehe weiter unten) und würde die Suche im
   Peek-/Halb-Zustand sonst verdecken, ohne sie erst zuzuklappen. Am Desktop
   wirkungslos, da #panel dort als rechte Seitenspalte nie über der Karte
   liegt. */
.leaflet-bottom.leaflet-left { padding-bottom: env(safe-area-inset-bottom); z-index:1150; }

/* Marken-Wasserzeichen unten rechts auf der Karte (js/main.js). Bleibt wie
   alles direkt auf der Karte (Popups, Tooltips, Sonnenstand-Overlay) bewusst
   hell/fest eingefaerbt statt an die Dark-Mode-Variablen gekoppelt, da die
   Kartenkacheln selbst auch im Dark Mode hell bleiben.
   Bottom-Offset UND Hoehe bewusst auf das Leaflet-Suchfeld unten links
   abgestimmt (dort: margin-bottom:10px per Leaflet-Default + das
   safe-area-inset-bottom-Padding auf .leaflet-bottom.leaflet-left oben,
   Input-Hoehe durch padding:6px 8px bei font-size:13px) - vorher nutzten
   beide unterschiedliche Formeln (max() hier vs. additiv dort), auf Geraeten
   mit Home-Indicator (grosses safe-area-inset-bottom) klafften sie dadurch
   sichtbar auseinander statt auf gleicher Hoehe zu sitzen. */
.map-brand {
  position:absolute; right:10px; bottom:calc(10px + env(safe-area-inset-bottom)); z-index:650;
  display:flex; align-items:center; gap:5px; pointer-events:none;
  background:rgba(255,255,255,.85); padding:6px 4px 6px 9px; border-radius:20px;
  box-shadow:0 1px 3px rgba(0,0,0,.25);
  transition:right .25s ease;
}
/* #panel liegt rechts über der Karte (position:fixed, standardmäßig 340px
   breit, am Desktop per Ziehgriff verstellbar - siehe initPanelResize in
   js/main.js) und würde das Wasserzeichen sonst verdecken - bei offenem
   Panel nach links ausweichen (Klasse wird in setPanelOpen() gesetzt).
   --panel-width wird von initPanelResize() auf #panel gesetzt, sobald die
   Breite vom Standard abweicht - der Fallback hier deckt sowohl den
   Auslieferungszustand als auch schmalere Bildschirme ab (max-width:88vw
   auf #panel, dort ist --panel-width nicht gesetzt). */
.map-brand.panel-open { right:calc(var(--panel-width, 340px) + 16px); }
.map-brand img { width:16px; height:16px; border-radius:4px; display:block; flex:0 0 auto; }
.map-brand span { font-size:10.5px; letter-spacing:-0.01em; white-space:nowrap; opacity:.85; }
/* Einziger klickbarer Teil des sonst rein dekorativen Wasserzeichens
   (pointer-events:none auf .map-brand) - öffnet die Release Notes, siehe
   js/changelog.js Delegation auf #mapBrandVersion. */
.map-brand-version { pointer-events:auto; cursor:pointer; text-decoration:underline; text-decoration-style:dotted; text-underline-offset:2px; }
.map-brand-version:hover { opacity:1; }

/* Ziehgriff des mobilen Bottom-Sheets - am Desktop ausgeblendet, dort bleibt
   das Panel unverändert eine feste Seitenspalte. */
#sheetHandle { display:none; }

/* Ziehgriff für die Panel-Breite - nur Desktop (gleiche Schwelle wie
   isNarrow() in js/main.js), auf schmalen Bildschirmen bleibt es beim
   mobilen Bottom-Sheet oben. Trefffläche (10px) breiter als der sichtbare
   Strich (4px), der erst bei Hover/Fokus/Ziehen erscheint - ein dauerhaft
   sichtbarer Strich am Panel-Rand wäre unnötig aufdringlich. */
@media (min-width: 769px) {
  #panelResizeHandle {
    display:block; position:absolute; top:0; left:-5px; width:10px; height:100%;
    cursor:col-resize; z-index:1101; touch-action:none;
  }
  #panelResizeHandle::before {
    content:''; position:absolute; top:50%; left:50%; width:4px; height:38px;
    transform:translate(-50%,-50%); border-radius:2px; background:var(--border-strong);
    opacity:0; transition:opacity .15s ease;
  }
  #panelResizeHandle:hover::before,
  #panelResizeHandle:focus-visible::before,
  #panelResizeHandle.dragging::before { opacity:1; }
  #panelResizeHandle:focus-visible { outline:2px solid var(--link); outline-offset:-2px; }
}
/* Während des Ziehens Cursor/Textauswahl für die ganze Seite sperren statt
   nur den schmalen Griff - sonst "entkommt" die Auswahl, sobald der Zeiger
   beim schnellen Ziehen kurz den Griff verlässt. */
body.panel-resizing { cursor:col-resize; user-select:none; }

@media (max-width: 768px) {
  /* --- Bottom-Sheet statt Vollbild-Panel ---
     Vorher schob sich das Panel als 100 % breite Fläche von rechts über die
     Karte: entweder man sah das Ergebnis oder die Karte, nie beides. Genau
     beim Prüfen eines Punktes will man aber sehen, wo er liegt. Als
     Bottom-Sheet mit drei Rastpunkten (peek/half/full) bleibt die Karte
     sichtbar, und der Weg zu den unteren Karten (Wetter) ist trotzdem kurz.

     Verschoben wird ausschließlich per transform (translateY), nicht über die
     Höhe: eine Höhen-Animation würde bei jedem Frame das komplette Panel neu
     umbrechen und auf schwächeren Geräten sichtbar ruckeln. Das Sheet ist
     deshalb immer gleich hoch und wird nur unterschiedlich weit
     herausgefahren. */
  #panel {
    width:100%; max-width:100vw;
    /* Höhe und Unterkante kommen aus window.visualViewport (gesetzt von
       aktualisiereSichtbarenBereich() in js/main.js), weil sie als einzige den
       tatsächlich sichtbaren Ausschnitt treffen. Vorher war das Sheet über
       top:0/bottom:0 am Layout-Viewport aufgehängt; auf einem iPhone rechnet
       Safari dafür mit der Höhe ohne seine ein- und ausfahrenden Leisten, und
       die Fußzeile mit den Impressum-Links saß dann nicht am Bildschirmende -
       darunter blieb ein leerer Streifen von mehreren Zeilen Höhe. Davor stand
       hier 100dvh, was am selben Punkt scheiterte. Die Rückfallwerte gelten
       für Browser ohne visualViewport. */
    top:auto; right:0; left:0;
    bottom:var(--sichtbarer-abstand-unten, 0px);
    height:var(--sichtbare-hoehe, 100dvh);
    border-left:none;
    border-top:1px solid var(--border-strong);
    border-radius:14px 14px 0 0;
    box-shadow:0 -3px 16px var(--shadow);
    /* Rastpunkt-unabhängiger Grundzustand; die Klassen unten setzen die
       konkrete Verschiebung. */
    transform:translateY(72%);
  }
  #panel.sheet-peek { transform:translateY(72%); }
  #panel.sheet-half { transform:translateY(42%); }
  /* Vollbild: oben bündig mit dem Bildschirmrand. Die abgerundeten Ecken
     entfallen dabei, sonst blitzt dort der Kartenhintergrund durch. */
  #panel.sheet-full { transform:translateY(0); border-radius:0; }
  /* .closed bleibt der Zustand "ganz eingefahren" und muss die Rastpunkt-
     Klassen überstimmen - deshalb hier nach ihnen notiert. */
  #panel.closed { transform:translateY(100%); }
  /* Während des Ziehens folgt das Sheet dem Finger; eine Übergangsanimation
     würde dabei hinterherlaufen. */
  #panel.sheet-dragging { transition:none; }

  #sheetHandle {
    display:block; flex:0 0 auto; padding:7px 0 3px 0; cursor:grab;
    touch-action:none; /* sonst scrollt/zoomt der Browser statt zu ziehen */
    background:var(--bg-app); border-radius:14px 14px 0 0;
  }
  /* Im Vollbild stößt der Griff an den oberen Bildschirmrand - auf Geräten mit
     Notch/Statusleiste läge er sonst darunter und wäre nicht greifbar. */
  #panel.sheet-full #sheetHandle {
    padding-top:max(7px, env(safe-area-inset-top));
    border-radius:0;
  }
  #sheetHandle::before {
    content:''; display:block; width:38px; height:4px; margin:0 auto;
    border-radius:2px; background:var(--border-strong);
  }
  #sheetHandle:active { cursor:grabbing; }

  /* Im eingefahrenen/halben Zustand darf der Inhalt nicht scrollen, sonst
     "verschluckt" der Scrollbereich die Ziehgeste, die das Sheet öffnen soll. */
  #panel:not(.sheet-full) #panelScroll { overflow-y:hidden; }

  /* Im Sheet zählt die Reihenfolge stärker als am Desktop: im kleinsten
     Rastpunkt ist nur der oberste Bereich zu sehen, und das muss das
     Prüfergebnis mit der Gesamt-Ampel sein - nicht die Spendenkarte, die im
     DOM davor steht (sie bleibt am Desktop ganz oben, siehe index.html).
     Per order verschoben statt im HTML umsortiert, damit die Desktop-
     Reihenfolge unverändert bleibt. Die Spendenkarte rutscht dadurch direkt
     hinter das Ergebnis, bleibt also weiterhin gut sichtbar. Seit den
     Panel-Reitern gilt das der ganzen .panel-tabgroup statt nur #resultCard -
     im Peek-Zustand zeigt sich dadurch die Reiterleiste plus der Anfang des
     (standardmäßig aktiven) Ergebnis-Reiters. */
  #panelScroll { padding-top:6px; display:flex; flex-direction:column; }
  .panel-header { order:-2; } /* Titel/Logo bleiben ganz oben */
  .panel-tabgroup { order:-1; }

  #toggleBtn { top:max(12px, env(safe-area-inset-top)); }
  /* Wasserzeichen sitzt unten rechts - genau dort, wo jetzt das Sheet
     hochkommt. Bei geöffnetem Sheet ausblenden (wie zuvor beim Vollbild-Panel). */
  .map-brand.panel-open { display:none; }
  /* Backdrop nur im Vollbild-Rastpunkt: bei peek/half soll die Karte
     ausdrücklich sichtbar UND bedienbar bleiben. */
  #backdrop.show { display:none; }
  #backdrop.show.sheet-full-backdrop { display:block; }
}

/* --- Kartenwerkzeuge: gleiche Ecke wie am Desktop ---
   Frühere Fassung positionierte die Werkzeuge (Standort/Ebenen/Messen/
   Fläche/Kartenauswahl) auf schmalen Bildschirmen fest rechts statt wie am
   Desktop oben links - jetzt dieselbe Ecke, nur Karten-Optik (Rundung/
   Schatten) und größere Touch-Ziele bleiben mobile-spezifisch. */
@media (max-width: 768px) {
  .search-control form { height:46px; padding:0 12px 0 14px; }
  .search-control input { font-size:15px; }
}

/* --- Suche, Name+Version und Leaflet-Hinweis: ein zentrierter Stapel ---
   Auf schmalen Bildschirmen saßen diese drei bisher an drei verschiedenen
   Stellen (Suche/Hinweis unten links übereinander, Name+Version unten
   rechts separat) - wirkte unruhig, gerade weil die Suche unten links neben
   dem seitlich einfahrenden Bottom-Sheet leicht verdeckt/beengt aussah.
   Jetzt ein gemeinsamer, horizontal zentrierter Stapel unten (Suche oben,
   Name+Version darunter, Leaflet-Hinweis unten). Bewusst NICHT als
   gemeinsamer Flex-Container umgesetzt (dafür müssten .search-control und
   .map-brand denselben DOM-Elternknoten teilen, tun sie aber nicht - Leaflet
   verwaltet die Suche als eigenes Control, .map-brand ist ein normales
   Div direkt im Kartenbereich) - stattdessen bekommt jedes der drei
   Elemente einzeln denselben zentrierten X-Offset sowie einen anhand der
   tatsächlich gemessenen Höhen (Suchfeld 46px, Marke 28px, Hinweis 19px,
   je 8px Abstand) berechneten Y-Offset, sodass sie optisch wie eine Einheit
   wirken. Nur auf dem Smartphone - am Desktop bleibt die bisherige
   Eck-Aufteilung (genug Platz, kein Gedränge). */
@media (max-width: 768px) {
  /* --stack-search-bottom/--stack-brand-bottom werden von
     aktualisiereMobilerStapel() in js/main.js aus den TATSÄCHLICH
     gerenderten Höhen berechnet (Textgröße kann je nach Betriebssystem-/
     Browser-Einstellung von den hier hinterlegten Fallback-Werten
     63px/27px abweichen, z.B. bei aktiviertem Nur-Text-Zoom - dann rutschten
     Suche/Marke unter die jeweils nächste Zeile). Die Fallback-Werte greifen
     nur, bevor JS zum ersten Mal gemessen hat. */
  .search-control {
    position:fixed; left:50%; transform:translateX(-50%);
    bottom:calc(12px + env(safe-area-inset-bottom) + var(--stack-search-bottom, 63px));
    z-index:1150;
  }
  .map-brand {
    left:50%; right:auto; transform:translateX(-50%);
    bottom:calc(12px + env(safe-area-inset-bottom) + var(--stack-brand-bottom, 27px));
    z-index:1150;
  }
  .map-brand.panel-open { left:50%; right:auto; } /* Desktop-Ausweichregel (right:356px) hier nicht nötig - Suche/Hinweis liegen ohnehin unter dem Bottom-Sheet, nicht neben einer Seitenspalte */
  .leaflet-control-attribution {
    position:fixed; left:50%; transform:translateX(-50%);
    bottom:calc(12px + env(safe-area-inset-bottom));
    margin:0 !important; z-index:1150;
    /* white-space:nowrap statt der Standard-Umbruchbreite: "left:50%" allein
       (ohne "right") lässt den Browser die verfügbare Breite für die
       automatische shrink-to-fit-Breite ab der 50%-Marke bis zum rechten
       Viewport-Rand berechnen, VOR der optischen Korrektur durch
       transform:translateX(-50%) - bei diesem Text (~217px) reicht die
       rechte Hälfte auf einem 414px-Schirm (207px) knapp nicht, es bricht
       um. nowrap erzwingt eine Zeile unabhängig von dieser Vorab-Breite. */
    white-space:nowrap;
  }
  /* body.sheet-full-active wird bereits in applySheetState() (js/main.js)
     gesetzt, sobald das Bottom-Sheet voll ausgezogen den ganzen Bildschirm
     abdeckt - die zugehörige CSS-Regel dafür fehlte bisher komplett, der
     dort dokumentierte Zweck ("sie müssten sonst durch dessen Inhalt
     hindurchscheinen") griff deshalb nie: alle drei schwebenden Elemente
     liegen mit z-index:1150 tatsächlich ÜBER dem Panel (z-index:1100) und
     schienen dadurch übers Menü hinweg sichtbar. .map-brand hat mit
     .panel-open (oben) zufällig schon eine eigene, etwas breiter greifende
     Ausblendung (jeder offene Zustand, nicht nur "full") - Suchleiste/
     Leaflet-Hinweis bekommen hier dieselbe Wirkung gezielt nur für den
     Vollbild-Rastpunkt, wo die Karte ohnehin nicht bedienbar ist. */
  body.sheet-full-active .search-control,
  body.sheet-full-active .leaflet-control-attribution { display:none; }
}

/* Kartenauswahl auf der Karte (siehe BasemapControl in js/main.js). Zeigt
   beide Karten nebeneinander mit Markierung der aktiven - der frühere
   Umschalt-Knopf zeigte immer die jeweils andere an und führte damit
   regelmäßig in die Irre. Beschriftung statt nur Symbol, weil ein Satelliten-
   Emoji allein nicht erkennen lässt, was passiert. */
/* Knopf wie die übrigen Kartenwerkzeuge; die Auswahl klappt erst auf Klick
   auf - vier ständig sichtbare Einträge nähmen der Karte Platz und Ruhe. */
.basemap-control { position:relative; }
.basemap-toggle { display:flex !important; align-items:center; justify-content:center; }
.basemap-menu {
  display:none; position:absolute; top:0; left:calc(100% + 6px);
  background:var(--bg-card); border:1px solid var(--border-strong); border-radius:6px;
  box-shadow:0 2px 10px var(--shadow); overflow-x:hidden; overflow-y:auto;
  min-width:150px; z-index:1000;
}
.basemap-control.open .basemap-menu { display:block; }
/* !important, weil leaflet.css den Elementen einer .leaflet-bar eine feste
   Breite von 26 px gibt - die Beschriftung wäre sonst abgeschnitten. */
.basemap-menu .basemap-option {
  display:flex !important; align-items:center; gap:7px; padding:0 10px;
  width:auto !important; height:30px; line-height:30px; border:none;
  font-size:12px; color:var(--text-body); background:var(--bg-card);
  text-decoration:none; white-space:nowrap;
}
/* Zwei Bereiche im Menü: erst welche Karte, dann hell/dunkel. Fünf Karten mal
   drei Darstellungen wären als Einzelkombinationen fünfzehn Einträge. */
.basemap-group {
  padding:6px 10px 3px 10px; font-size:9.5px; text-transform:uppercase;
  letter-spacing:.05em; color:var(--text-faint); background:var(--bg-app);
  border-top:1px solid var(--border-light);
}
.basemap-group:first-child { border-top:none; }
.basemap-menu .basemap-option + .basemap-option { border-top:1px solid var(--border-light); }
.basemap-group + .basemap-option { border-top:none; }
.basemap-menu .basemap-option:hover { background:var(--hover-tint); }
.basemap-menu .basemap-option.active { background:var(--link); color:#fff; font-weight:700; }
.basemap-icon { font-size:13px; line-height:1; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .basemap-menu .basemap-option.active { color:#10243a; }
}
:root[data-theme="dark"] .basemap-menu .basemap-option.active { color:#10243a; }

/* Auf schmalen Bildschirmen klappt das Menü UNTER den Knopf statt daneben.
   Seitlich ginge es in beide Richtungen daneben: nach rechts reicht der Platz
   nicht, und nach links liegt der Bildschirmrand - der Knopf sitzt ja bereits
   ganz links (gemessen: das Menü ragte 188 px aus dem Bild). */
@media (max-width: 768px) {
  .basemap-menu {
    left:0; right:auto; top:calc(100% + 4px);
    max-width:calc(100vw - 20px);
  }
}

/* Nur für Screenreader: Überschrift, auf die aria-labelledby des Popups zeigt,
   ohne sie doppelt zum sichtbaren Titel in der Kopfzeile anzuzeigen. */
.visually-hidden {
  position:absolute; width:1px; height:1px; margin:-1px; padding:0;
  overflow:hidden; clip:rect(0 0 0 0); clip-path:inset(50%); white-space:nowrap; border:0;
}

/* Zweispaltig, damit die acht Felder auch auf einem Smartphone ohne Scrollen
   ins Fenster passen - untereinander ragten sie unten heraus und wirkten
   abgeschnitten. Straße und Betreiber-Nummer bekommen die volle Breite, weil
   ihre Werte lang werden; PLZ bleibt schmal, der Ort füllt daneben auf. */
.profile-grid { display:flex; flex-wrap:wrap; gap:7px 8px; }
.profile-field { display:flex; flex-direction:column; gap:2px; font-size:11.5px; min-width:0; }
.profile-field-full { flex:1 1 100%; }
.profile-field-half { flex:1 1 calc(50% - 4px); }
.profile-field-short { flex:0 0 84px; }
.profile-field-rest { flex:1 1 calc(50% - 4px); }
/* Rahmen/Radius/Farben kommen von der allgemeinen input[type=text]-Regel
   weiter oben - hier nur die für das enge Zweispalten-Raster nötigen
   Abweichungen (volle Feldbreite, kompaktere Innenabstände). */
.profile-field input { width:100%; padding:7px 9px; font-size:13px; }

@media print {
  /* Angaben zum Betreiber stehen als eigener Block über der Ergebnistabelle;
     die Kopfzeile hebt ihn ab, ohne wie eine zweite Überschrift zu wirken. */
  .report-profile-table { margin-bottom:14px; }
  .report-profile-head { font-size:11px; text-transform:uppercase; letter-spacing:.04em; color:#666; padding-top:0; }
  /* Auflagen zur gewählten Drohnenklasse als Fußnoten unter der Tabelle -
     etwas kleiner, damit sie die Angaben darüber nicht überlagern. */
  .report-assumption-notes { font-size:11.5px; color:#444; margin-top:-8px; }
  /* Im Druck ohne Farbfläche, aber weiterhin abgesetzt - so bleibt die
     Erleichterung auch im Schwarzweißausdruck als solche erkennbar. */
  .zone-line-permit {
    background:none; border-left:2px solid #4c9a51; color:#1f3a1c;
    padding:1px 0 1px 6px; margin-top:2px; font-size:11px;
    -webkit-print-color-adjust:exact; print-color-adjust:exact;
  }
  .zone-line-permit-tag { font-weight:700; }
}

/* Offline-Paket (siehe js/offlinePackage.js) */
.offline-status { font-size:12px; color:var(--text-body); background:var(--bg-card); border:1px solid var(--border); border-radius:6px; padding:7px 9px; line-height:1.45; }
.offline-progress { height:8px; border-radius:4px; background:var(--bg-button); overflow:hidden; margin:8px 0 4px 0; }
.offline-progress-bar { height:100%; background:var(--link); transition:width .2s linear; }
.offline-delete { margin-top:8px; }
#offlineRadius { width:100%; }

/* Gesamteinschätzung "Kann ich hier fliegen?" ganz oben im Prüfergebnis
   (siehe js/verdict.js). Optisch bewusst der Flugbedingungen-Ampel der
   Wetterkarte nachempfunden - gleiche Sprache für die gleiche Art Aussage -,
   aber etwas kräftiger, da sie das Ergebnis anführt. Farben über Variablen,
   damit der Dunkelmodus eigene, gedämpfte Töne setzen kann. */
.verdict { border:2px solid; border-radius:8px; padding:9px 11px; margin:0 0 12px 0; background:var(--rating-bg); border-color:var(--rating-border); }
/* Schriftgröße bewusst nah an .result-big (22px, siehe dort) statt der
   ursprünglichen 15px - bei größer/präsenter dargestellter Flughöhe (Nutzer-
   Ticket "Anzeige Höhe") stach die Zahl optisch stärker hervor als die
   Ampel-Überschrift, obwohl diese die wichtigere, einordnende Aussage trägt
   ("Flug nur mit Auflagen" o.ä.) - jetzt vorne. */
.verdict-headline { display:flex; align-items:center; gap:8px; font-family:'Space Grotesk', Arial, Helvetica, sans-serif; font-weight:700; font-size:19px; letter-spacing:-.01em; line-height:1.25; margin-bottom:6px; color:var(--rating-fg); }
.verdict-headline-dot { width:13px; height:13px; border-radius:50%; flex:0 0 auto; background:var(--rating-border); box-shadow:inset 0 0 0 1px var(--dot-ring); }
.verdict-rows { display:flex; flex-direction:column; gap:4px; }
.verdict-row { display:flex; align-items:flex-start; gap:6px; font-size:12.5px; line-height:1.45; color:var(--rating-text); }
.verdict-row-dot { width:9px; height:9px; border-radius:50%; margin-top:4px; flex:0 0 auto; box-shadow:inset 0 0 0 1px var(--dot-ring); }
/* Link zum Reiter "Wetter & Cam" in der Wetter-Begründungszeile (siehe
   verdict.weatherDetailHint in js/i18n.js, verdictHtml in js/verdict.js) -
   erbt die gedämpfte Zeilenfarbe statt dem globalen Link-Blau, das auf der
   roten/orangen Ampelfläche unpassend hervorstechen würde; die gepunktete
   Unterstreichung macht trotzdem klar, dass es klickbar ist (gleiches Muster
   wie .legal-note-link). */
.verdict-weather-link { color:inherit; text-decoration:underline; text-decoration-style:dotted; text-underline-offset:2px; }

/* Eigene Zeile mit der Ampel-Überschrift (Symbol + Text, siehe
   verdict.headline.* - dasselbe wie im Panel) vor dem restlichen
   Popup-Text. Bewusst die auffälligste Zeile der Karte (Nutzerwunsch: "die
   Auflagen deutlich") - die Flughöhe darunter (.popup-height, 16px) bleibt
   kleiner. War zwischenzeitlich (Kompaktierung, "braucht zu viel Platz")
   auf 13.5px verkleinert worden und damit unbeabsichtigt kleiner als die
   Flughöhe - beim Nutzer-Ticket "Anzeige Höhe" aufgefallen, jetzt wieder
   klar die größte Zeile der Karte. */
.popup-verdict-line { display:flex; align-items:center; gap:6px; font-size:17px; font-weight:700; font-family:'Space Grotesk', Arial, Helvetica, sans-serif; color:var(--rating-fg); }
.popup-verdict-dot { width:11px; height:11px; border-radius:50%; flex:0 0 auto; background:var(--rating-border); box-shadow:inset 0 0 0 1px var(--dot-ring); }

/* Kartenpopup-Karte im MockUp-Stil: Ampel-Überschrift, Flughöhe, Ort mit
   Pin-Symbol, dann je eine Chip pro betroffener Zone sowie eine Wetter-Chip
   (renderPopupText/popupZoneChipsHtml/popupWeatherChipHtml in js/main.js).
   gap seit der Kompaktierung (Nutzerwunsch) enger als ursprünglich (8px). */
.popup-card { display:flex; flex-direction:column; gap:5px; }
.popup-height { font-family:'Space Grotesk', Arial, Helvetica, sans-serif; font-size:16px; font-weight:700; letter-spacing:-.01em; color:var(--text-heading); }
.popup-place { display:flex; align-items:flex-start; gap:5px; font-size:12px; color:var(--text-body); }
.popup-place svg { flex:0 0 auto; margin-top:2px; color:var(--text-faint); }
.popup-place-text { display:flex; flex-direction:column; gap:1px; min-width:0; }
/* Koordinaten/Flächenangabe (renderPopupText extraLine) dezent unter der
   Adresse statt in der Fußzeile - Nutzerwunsch. */
.popup-coords { font-size:10px; }
.popup-chips { display:flex; flex-wrap:wrap; gap:4px; }
/* .popup-chips .popup-chip statt nur .popup-chip: die Chips sind <a>-Links,
   .leaflet-popup-content a (weiter unten) setzt Links sonst mit höherer
   Spezifität auf die globale blaue Linkfarbe statt der Ampel-/Neutralfarbe. */
.popup-chips .popup-chip { display:inline-flex; align-items:center; gap:4px; padding:3px 8px; border-radius:999px; font-size:11px; font-weight:600; text-decoration:none; background:var(--rating-bg); color:var(--rating-fg); }
.popup-chip:hover { filter:brightness(0.96); }
.popup-chip-dot { width:6px; height:6px; border-radius:50%; flex:0 0 auto; }
/* Chip-Grund bewusst neutral statt der rohen DIPUL-Zonenfarbe als Fläche -
   die hellen Zone-4-/AE-Töne wären als Text-/Flächenfarbe im Dunkelmodus
   teils kaum lesbar. Die Zonenfarbe steckt stattdessen nur im Punkt
   (.popup-chip-dot, Inline-Style), identisch zur Zonenliste im Panel. */
/* .popup-chip.popup-zone-chip statt nur .popup-zone-chip: die Chip ist ein
   <a>-Link, .leaflet-popup-content a (Zeile weiter oben) setzt sonst mit
   höherer Spezifität die globale Linkfarbe statt der neutralen Textfarbe. */
.popup-chip.popup-zone-chip { background:var(--bg-button); color:var(--text-body); }
/* "Spot speichern" und "Punkt teilen" (früher eigene, breite Knöpfe in der
   Ergebnis-Aktionsleiste, siehe git-Historie #spotSaveBtn/#shareBtn) -
   Nutzerwunsch: passen besser direkt ins Popup am geprüften Punkt, dafür als
   kompakte Chips statt voller Knöpfe. Einzige gefüllte Chip-Farbe
   (Akzentblau) in der Reihe, weil es anders als die übrigen Chips (reine
   Navigation zu Panel-Abschnitten) echte Aktionen sind. Eigene Regel statt
   nur .popup-chip, weil es (anders als die Zonen-/Wetter-Chips) <button>
   statt <a>-Links sind - Buttons bringen eigene
   Rand-/Hintergrund-/Cursor-Vorgaben mit, die hier zurückgesetzt werden. */
.popup-chip.popup-chip-action {
  border:none; cursor:pointer; font-family:inherit;
  background:var(--link); color:#fff;
}
.popup-chip-action:hover { background:var(--link-hover); filter:none; }
.popup-footer { font-size:10.5px; }

/* Kartenpopup direkt am geprüften Punkt (renderPopupText in js/main.js) -
   bisher unverändertes Leaflet-Standardaussehen (weißer Kasten, feste
   Systemschrift, festes Blau für Links), das gegen die übrigen neu
   gestalteten Flächen alt wirkte und im Dunkelmodus immer hell blieb.
   Radius/Schatten/Typografie an die übrigen schwebenden Karten angeglichen,
   Farben über dieselben --bg-card/--text-*-Variablen wie der Rest der App. */
.leaflet-popup-content-wrapper {
  background:var(--bg-card); color:var(--text-body); border-radius:16px;
  box-shadow:0 6px 24px -6px rgba(14,20,27,.4);
}
.leaflet-popup-content { font-family:'Instrument Sans', Arial, Helvetica, sans-serif; font-size:13px; line-height:1.4; margin:11px 13px; }
.leaflet-popup-tip { background:var(--bg-card); }
.leaflet-container a.leaflet-popup-close-button { color:var(--text-faint); font:20px/24px Arial, Helvetica, sans-serif; top:2px; right:2px; }
.leaflet-container a.leaflet-popup-close-button:hover { color:var(--text-heading); }
.leaflet-popup-content a { color:var(--link); }

/* Gemeinsame Ampel-Farben für die Gesamteinschätzung (js/verdict.js) UND die
   Flugbedingungen-Ampel der Wetterkarte (flightRatingHtml in js/main.js).
   Beide zeigen dieselbe Art Aussage und hatten vorher getrennte Farbwege - die
   Wetter-Ampel setzte ihren hellen Pastellgrund per Inline-Style aus dem
   JavaScript. Im Dunkelmodus stand deshalb heller Fließtext auf hellgrünem
   Grund: gemessener Kontrast 1,03 zu 1, also praktisch unlesbar. Über
   gemeinsame Klassen lässt sich beides an einer Stelle dunkelmodus-tauglich
   halten.
   --rating-text/-muted sind bewusst eigene Werte statt --text-body: auf der
   getönten Fläche braucht der Text einen anderen Ton als auf dem Kartengrund. */
.rating-good     { --rating-bg:#E9F6EF; --rating-border:#0E8A4F; --rating-fg:#0B6B3E; --rating-text:#0B6B3E; --rating-muted:#68A588; }
.rating-caution  { --rating-bg:#FDF2E0; --rating-border:#B36A00; --rating-fg:#8A5200; --rating-text:#8A5200; --rating-muted:#BA955E; }
.rating-bad      { --rating-bg:#FCEAE8; --rating-border:#C42B1C; --rating-fg:#9E2015; --rating-text:#9E2015; --rating-muted:#C5756E; }
.rating-unknown  { --rating-bg:#F0F2F5; --rating-border:#6B7683; --rating-fg:#5B6672; --rating-text:#5B6672; --rating-muted:#9AA1A9; }
.rating-dot-good     { background:#0E8A4F; }
.rating-dot-caution  { background:#B36A00; }
.rating-dot-bad      { background:#C42B1C; }
.rating-dot-unknown  { background:#6B7683; }

/* Dunkle, entsättigte Flächen statt der hellen Pastelltöne: Letztere leuchten
   auf dunklem Grund und lassen dunkle Schrift darauf unlesbar werden. Rahmen
   und Überschrift bleiben farbig, damit die Ampel-Wirkung erhalten bleibt.
   Zwei Blöcke aus demselben Grund wie oben bei den Grundfarben (Systemwahl
   bzw. ausdrücklich gewählter Dunkelmodus) - zusammen pflegen. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .rating-good    { --rating-bg:#1b2c1c; --rating-border:#3FBF7F; --rating-fg:#3FBF7F; --rating-text:#3FBF7F; --rating-muted:#379166; }
  :root:not([data-theme="light"]) .rating-caution { --rating-bg:#2e2313; --rating-border:#E9A23B; --rating-fg:#E9A23B; --rating-text:#E9A23B; --rating-muted:#AE7D36; }
  :root:not([data-theme="light"]) .rating-bad     { --rating-bg:#2f1a1c; --rating-border:#FF6E5E; --rating-fg:#FF6E5E; --rating-text:#FF6E5E; --rating-muted:#BD594E; }
  :root:not([data-theme="light"]) .rating-unknown { --rating-bg:#23272a; --rating-border:#8C97A4; --rating-fg:#8C97A4; --rating-text:#8C97A4; --rating-muted:#6C757F; }
  :root:not([data-theme="light"]) .rating-dot-good    { background:#3FBF7F; }
  :root:not([data-theme="light"]) .rating-dot-caution { background:#E9A23B; }
  :root:not([data-theme="light"]) .rating-dot-bad     { background:#FF6E5E; }
  :root:not([data-theme="light"]) .rating-dot-unknown { background:#8C97A4; }
}
:root[data-theme="dark"] .rating-good    { --rating-bg:#1b2c1c; --rating-border:#3FBF7F; --rating-fg:#3FBF7F; --rating-text:#3FBF7F; --rating-muted:#379166; }
:root[data-theme="dark"] .rating-caution { --rating-bg:#2e2313; --rating-border:#E9A23B; --rating-fg:#E9A23B; --rating-text:#E9A23B; --rating-muted:#AE7D36; }
:root[data-theme="dark"] .rating-bad     { --rating-bg:#2f1a1c; --rating-border:#FF6E5E; --rating-fg:#FF6E5E; --rating-text:#FF6E5E; --rating-muted:#BD594E; }
:root[data-theme="dark"] .rating-unknown { --rating-bg:#23272a; --rating-border:#8C97A4; --rating-fg:#8C97A4; --rating-text:#8C97A4; --rating-muted:#6C757F; }
:root[data-theme="dark"] .rating-dot-good    { background:#3FBF7F; }
:root[data-theme="dark"] .rating-dot-caution { background:#E9A23B; }
:root[data-theme="dark"] .rating-dot-bad     { background:#FF6E5E; }
:root[data-theme="dark"] .rating-dot-unknown { background:#8C97A4; }

/* Wetterkarte (nach den NOTAMs): aktuelle Bedingungen, Wind auf 10/80/120 m,
   Kp-Index und aufklappbare 12h-Vorhersage-Tabelle. */
/* Gesamteinschätzung (Punkt + Überschrift + große 10-m-Windzahl) plus die
   Kennzahl-Kacheln direkt darunter - EIN weißer Kartenrahmen statt der
   früheren farbigen Pastellfläche mit ausformulierter Kriterienliste
   (Wind/Sicht/Taupunkt/Niederschlag/Kp als Fließtext): dieselben fünf Werte
   stehen jetzt schon als Windzahl bzw. Kachel darunter, die Textliste war
   eine reine Dopplung. Farbe steckt nur noch im Punkt und der
   Überschriftfarbe (--rating-fg/-dot), nie alleine - die Überschrift selbst
   benennt die Einschätzung immer auch in Worten. */
.flight-rating { border:1px solid var(--border-light); border-radius:18px; padding:16px; margin:10px 0; background:var(--bg-card); }
.flight-rating-head { display:flex; align-items:center; gap:10px; margin-bottom:13px; }
.flight-rating-headline { font-family:'Space Grotesk', Arial, Helvetica, sans-serif; font-weight:700; font-size:17px; letter-spacing:-.01em; color:var(--rating-fg); }
.flight-rating-dot { width:12px; height:12px; border-radius:50%; flex:0 0 auto; background:var(--rating-border); box-shadow:inset 0 0 0 1px var(--dot-ring); }
.flight-rating-wind { display:flex; align-items:flex-end; gap:14px; margin-bottom:13px; }
.flight-rating-wind-value { font-family:'Space Grotesk', Arial, Helvetica, sans-serif; font-weight:700; font-size:36px; line-height:1; letter-spacing:-.03em; color:var(--text-heading); }
.flight-rating-wind-unit { font-size:16px; font-weight:600; letter-spacing:0; }
.flight-rating-disclaimer { font-size:11px; margin-top:11px; }
.flight-rating .weather-tiles { margin:0; }
.weather-now { margin:6px 0; font-size:12px; line-height:1.6; }
.weather-condition { display:flex; align-items:center; gap:6px; margin-bottom:2px; }
.weather-condition-icon { font-size:26px; line-height:1; }
.weather-condition-label { font-size:14px; font-weight:700; color:var(--text-heading); }
.weather-tiles { display:grid; grid-template-columns:1fr 1fr; gap:9px; margin:10px 0; }
.weather-tile { padding:11px 13px; border-radius:13px; background:var(--bg-button); }
.weather-tile-label { font-size:11px; font-weight:700; letter-spacing:.1em; text-transform:uppercase; color:var(--text-faint); }
.weather-tile-value { font-size:17px; font-weight:600; color:var(--text-heading); margin-top:3px; }
/* Kachel nach ihrer eigenen Kriteriums-Stufe einfärben (siehe critLevel() in
   js/main.js renderWeatherHtml, Stufen aus assessFlightConditions in
   js/weather.js) statt immer neutral grau - sonst blieb unsichtbar, WELCHE
   einzelne Angabe (Sicht/Taupunkt-Spread/Niederschlag/Kp) eine insgesamt
   "nicht empfehlenswert"-Ampel oben auslöst, wenn die übrigen Werte gut
   sind. .rating-good/-caution/-bad liefern --rating-bg/--rating-fg bereits
   dunkelmodus-tauglich (siehe weiter unten in dieser Datei). */
.weather-tile.rating-good, .weather-tile.rating-caution, .weather-tile.rating-bad { background:var(--rating-bg); }
.weather-tile.rating-good .weather-tile-value, .weather-tile.rating-caution .weather-tile-value, .weather-tile.rating-bad .weather-tile-value { color:var(--rating-fg); }
.weather-wind-table { display:flex; flex-direction:column; gap:8px; margin:8px 0; font-size:12px; }
.weather-wind-row { display:flex; align-items:center; gap:10px; }
.wind-label { width:34px; flex:0 0 auto; color:var(--text-muted); font-size:13px; }
.wind-bar-track { flex:1 1 auto; height:8px; border-radius:4px; background:var(--border-light); overflow:hidden; }
.wind-bar-fill { display:block; height:8px; border-radius:4px; }
.wind-value { width:62px; flex:0 0 auto; text-align:right; font-size:14px; font-weight:600; color:var(--text-heading); }
.weather-kp { margin-top:8px; font-size:12px; }
.kp-dot { display:inline-block; width:9px; height:9px; border-radius:50%; margin:0 3px; position:relative; top:-1px; box-shadow:inset 0 0 0 1px var(--dot-ring); }
/* Farbe des Kp-Textes über Klassen statt inline (siehe kpLevel in
   js/weather.js) - der dunkle Grünton war auf dunklem Grund nicht lesbar. */
.kp-label { font-weight:600; }
.kp-label-good    { color:#2e7d32; }
.kp-label-caution { color:#b07700; }
.kp-label-bad     { color:#c62828; }
.kp-label-unknown { color:var(--text-muted); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .kp-label-good    { color:#7ed184; }
  :root:not([data-theme="light"]) .kp-label-caution { color:#ffca28; }
  :root:not([data-theme="light"]) .kp-label-bad     { color:#ff8a80; }
}
:root[data-theme="dark"] .kp-label-good    { color:#7ed184; }
:root[data-theme="dark"] .kp-label-caution { color:#ffca28; }
:root[data-theme="dark"] .kp-label-bad     { color:#ff8a80; }
.weather-forecast { margin-top:8px; }
.weather-forecast summary { cursor:pointer; font-size:12px; font-weight:600; color:var(--link); padding:4px 0; list-style:none; }
.weather-forecast summary::-webkit-details-marker { display:none; }
.weather-table-wrap { overflow-x:auto; margin-top:4px; }
.weather-table { border-collapse:collapse; font-size:12px; width:100%; white-space:nowrap; color:var(--text-body); }
.weather-table th, .weather-table td { padding:3px 6px; text-align:left; border-bottom:1px solid var(--border-light); }
.weather-table th { color:var(--text-muted); font-weight:600; }
.weather-table-icon { font-size:21px; vertical-align:middle; }

/* Sonnenstand-Karte (nach dem Wetter, js/main.js): im Panel nur noch Titel,
   aktuelle Uhrzeit und der Regler zwischen Sonnenauf- und -untergang
   (30-Min-Schritte) - die eigentliche Visualisierung sitzt als Overlay
   direkt am markierten Punkt auf der Karte (siehe .sun-map-* unten). */
.sun-time-row { display:flex; align-items:center; justify-content:space-between; gap:8px; }
.sun-time-label { font-size:20px; font-weight:700; color:var(--text-heading); margin:4px 0 2px 0; }
.sun-now-btn {
  font-size:12px; padding:4px 8px; border:1px solid var(--border-strong); border-radius:6px;
  background:var(--bg-button); cursor:pointer; font-family:inherit; flex:0 0 auto; color:var(--text-body);
}
.sun-now-btn:hover { background:var(--bg-button-hover); }
.sun-slider { width:100%; margin:4px 0 2px 0; accent-color:#ff8c00; }
.sun-slider-labels { display:flex; justify-content:space-between; font-size:12px; color:var(--text-faint2); }

/* Sonnenverlauf-Overlay am geprüften Punkt (js/main.js sunMarker): Ring in
   fixen Bildschirm-Pixeln (nicht geografisch) rund um den Punkt, damit die
   Größe unabhängig vom Zoomlevel gleich bleibt. Negativer zIndexOffset hält
   das Overlay hinter dem eigentlichen Pin-/GPS-Marker. Bewusst nicht
   theme-abhängig (siehe Kommentar oben am Datei-Anfang) - sitzt direkt auf
   der unverändert hellen Karte, nicht im Panel. */
.sun-map-icon { background:transparent; border:none; pointer-events:none; }
.sun-map-ring { fill:rgba(255,255,255,.5); stroke:rgba(70,70,70,.55); stroke-width:1; }
.sun-map-n-label { font-size:9px; font-weight:700; fill:#555; text-anchor:middle; }
.sun-map-path { fill:none; stroke:#ffb300; stroke-width:1.3; stroke-dasharray:2,3; opacity:.75; }
.sun-map-ray { stroke:#ffd700; stroke-width:2; }
.sun-map-dot { fill:#ffd700; stroke:#fff; stroke-width:1.5; filter:drop-shadow(0 0 3px rgba(0,0,0,.4)); }
.sun-map-label {
  background:rgba(255,255,255,.92); border-radius:10px; padding:2px 7px;
  font:600 11px Arial, Helvetica, sans-serif; color:#333; text-align:center;
  white-space:nowrap; box-shadow:0 1px 3px rgba(0,0,0,.3); display:inline-block;
}

/* Hilfe, Impressum & Datenschutz, Version/Release Notes: Links am Ende des
   Panels, jeweiliger Inhalt als Popup - etwas größer als vorher, da hier
   jetzt drei statt zwei Links stehen und das Antippen leichter fallen soll. */
.legal-footer {
  flex:0 0 auto; text-align:center; font-size:12.5px; line-height:1.7; box-sizing:border-box;
  padding:10px 16px max(10px, env(safe-area-inset-bottom)) 16px;
  border-top:1px solid var(--border); background:var(--bg-app);
}
.legal-footer a { color:var(--text-muted); font-weight:600; }

/* Hinweis auf eine vor 9.19 angelegte Verknüpfung (siehe index.html). Kürzer
   als die übrigen Fenster - es sind drei Schritte, kein Fließtext.
   Doppelte Klasse im Selektor, damit die Höhe die von .legal-modal schlägt,
   ohne dass es auf die Reihenfolge im Stylesheet ankommt. */
.legal-modal.reinstall-modal { height:auto; max-height:min(88dvh, 520px); }
.reinstall-schritte { margin:10px 0; padding-left:22px; font-size:13.5px; line-height:1.6; }
.reinstall-schritte li { margin-bottom:6px; }
.reinstall-aktionen { display:flex; flex-wrap:wrap; align-items:center; gap:10px; margin-top:14px; }
@media (max-width: 768px) {
  /* Auch auf dem Handy ein Fenster in Fenstergröße, nicht auf Vollbild
     aufgezogen wie die Hilfe: der Hinweis ist kurz und soll nicht wirken, als
     hätte sich die App vor die Karte geschoben. */
  .legal-modal.reinstall-modal {
    top:50%; left:50%; transform:translate(-50%,-50%);
    width:min(92vw, 420px); max-width:92vw; height:auto;
    max-height:min(80dvh, 520px); border-radius:10px;
  }
}

/* "Was ist neu"-Hinweis (js/main.js zeigeWasIstNeu(), siehe index.html) -
   inzwischen vier Abschnitte plus Startbildschirm-Beispiel, also spürbar
   mehr Inhalt als beim ursprünglichen "kurzer Inhalt"-Zuschnitt (620px) -
   mit dem musste er auf vielen Bildschirmen gescrollt werden. Etwas höher
   als der Standard-Zuschnitt der übrigen .legal-modal-Fenster (640px). */
.legal-modal.whatsnew-modal { height:auto; max-height:min(90dvh, 700px); }
/* Body soll den Rest der (jetzt festen statt inhaltsabhängigen) Höhe
   ausfüllen und intern scrollen, statt dass der feste Fußbereich
   (.whatsnew-footer) je nach Inhaltslänge mal direkt darunter, mal mit
   Lücke zum unteren Fensterrand steht - betrifft v.a. den Vollbild-Zuschnitt
   unter 768px (siehe media query unten), wo die Fensterhöhe fix ist. */
.whatsnew-modal .legal-modal-body { flex:1 1 auto; min-height:0; }
.whatsnew-modal h4 { font-size:13.5px; margin:14px 0 4px; color:var(--text-heading); }
.whatsnew-modal h4:first-child { margin-top:0; }
.whatsnew-modal p { margin:0 0 4px; font-size:13px; line-height:1.5; color:var(--text-body); }
/* Verkleinerte Fassung des Startbildschirm-Beispiels aus dem Hilfe-Reiter
   (.homescreen-mockup, siehe dort) - kleinerer Innenabstand und nur drei statt
   sechs Symbole, damit es ins kompakte Popup passt, sonst identische Optik. */
.whatsnew-mockup { padding:12px 8px; margin-top:6px; }
.whatsnew-mockup .homescreen-mockup-grid { max-width:180px; }
.whatsnew-mockup-caption { text-align:center; font-size:11px; margin:6px 0 8px; }
.whatsnew-home-link { display:block; font-size:12.5px; font-weight:600; color:var(--link); text-decoration:none; margin-bottom:4px; }
.whatsnew-home-link:hover { text-decoration:underline; }
/* Fußbereich (Checkbox + Button) sitzt außerhalb von .legal-modal-body und
   bleibt dadurch immer sichtbar, egal wie weit der Inhalt darüber gescrollt
   ist - flex:0 0 auto wie .legal-modal-header, siehe .legal-modal-footer. */
.whatsnew-footer { border-top:1px solid var(--border); }
.whatsnew-again {
  display:flex; align-items:center; gap:7px; font-size:12.5px; color:var(--text-body); cursor:pointer;
}
/* KEINE feste 16x16px-Größe hier (die gab es früher, siehe Kommentar bei
   input[type=checkbox] oben in dieser Datei) - die zwang den Schalter-Knopf
   (17x17px, siehe dort) in einen kleineren Rahmen als er selbst ist, wodurch
   er über den Text daneben hinausragte. margin:0 bleibt nötig, sonst setzt
   das Browser-Standardformular seinen üblichen Checkbox-Außenabstand. */
.whatsnew-again input { margin:0; }
/* Gleiche Blau-Fläche wie #publishBtn, aber über var(--link) statt fester
   Farbe, damit sie im Dunkelmodus dessen helleres Blau mitnimmt. */
.whatsnew-ok-btn {
  display:block; width:100%; text-align:center; font-weight:700; font-size:14px;
  padding:9px 6px; border-radius:6px; border:none; background:var(--link); color:#fff;
  margin-top:12px; cursor:pointer; font-family:inherit;
}
.whatsnew-ok-btn:hover { opacity:.9; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .whatsnew-ok-btn { color:#10243a; }
}
:root[data-theme="dark"] .whatsnew-ok-btn { color:#10243a; }
/* Auf dem Handy KEIN eigener kompakter Zuschnitt mehr (früher: schwebendes
   Fenster mit max. 620px statt Vollbild) - bei vier Abschnitten plus
   Startbildschirm-Beispiel reichte das nicht mehr aus, ohne zu scrollen.
   Läuft jetzt stattdessen mit in die allgemeine Vollbild-Regel für
   .legal-modal unter 768px (siehe unten), wie Hilfe/Konto/Datenschutz auch. */

.legal-backdrop { position:fixed; inset:0; background:rgba(0,0,0,.5); z-index:1290; display:none; }
.legal-backdrop.show { display:block; }

.legal-modal {
  position:fixed; top:50%; left:50%; transform:translate(-50%,-50%);
  width:560px; max-width:92vw; height:80dvh; max-height:640px;
  background:var(--bg-card); color:var(--text-body); border-radius:10px; box-shadow:0 8px 30px rgba(0,0,0,.4);
  z-index:1300; display:none; flex-direction:column; overflow:hidden;
  padding-top:env(safe-area-inset-top); padding-bottom:env(safe-area-inset-bottom);
}
.legal-modal.show { display:flex; }

/* gap zwischen Reiterleiste und Schließen-Kreuz, damit beide auch dann nicht
   aneinanderkleben, wenn die Reiter die volle Restbreite ausnutzen. */
.legal-modal-header {
  display:flex; align-items:center; justify-content:space-between; gap:4px;
  border-bottom:1px solid var(--border); padding:8px 8px 0 14px; flex:0 0 auto;
}
/* min-width:0 + overflow-x:auto sind hier sicherheitsrelevant, nicht Kosmetik:
   das Hilfe-Modal hat fünf Reiter, die auf Handybreite zusammen breiter sind
   als der Bildschirm. Ohne diese beiden Angaben schiebt die Reiterleiste das
   Schließen-Kreuz aus dem sichtbaren Bereich (gemessen: 482 px Header-Inhalt
   bei 400 px Viewport, Kreuz ab x=450) - und da das Modal unter 768 px im
   Vollbild liegt, ist dann auch der Hintergrund nicht mehr anklickbar und
   eine Esc-Taste gibt es auf dem Handy nicht: das Fenster ließe sich gar
   nicht mehr schließen. Jetzt scrollt stattdessen die Reiterleiste, das
   Kreuz bleibt immer am rechten Rand stehen. */
.legal-tabs { display:flex; gap:4px; min-width:0; overflow-x:auto; scrollbar-width:none; }
.legal-tabs::-webkit-scrollbar { display:none; }
.legal-tab {
  border:none; background:none; cursor:pointer; font-size:13px; font-weight:600;
  color:var(--text-muted); padding:10px 12px; border-bottom:2px solid transparent;
  /* nicht stauchen und nicht umbrechen - sonst quetscht der Flex-Container die
     Reiter zu mehrzeiligen Textklötzen, statt sie scrollen zu lassen. */
  flex:0 0 auto; white-space:nowrap;
}
.legal-tab.active { color:var(--link); border-bottom-color:var(--link); }
.legal-close {
  border:none; background:none; cursor:pointer; font-size:18px; color:var(--text-muted);
  width:32px; height:32px; flex:0 0 auto; margin-bottom:4px;
}
.legal-close:hover { color:var(--text-heading); }

.legal-modal-body { overflow-y:auto; padding:14px 18px 20px 18px; font-size:13px; line-height:1.55; }
/* Fester Fußbereich unterhalb des scrollenden Bodys (siehe .whatsnew-footer) -
   flex:0 0 auto wie .legal-modal-header, damit er nicht mitscrollt. */
.legal-modal-footer { flex:0 0 auto; padding:12px 18px; }
/* Logo-Lockup als echtes HTML statt Bild (ehem. logo-lockup.png) - dadurch
   frei steuerbar: erst Text, dann Icon, "Drone" fest blau/Rest fest dunkel.
   Bleibt bewusst immer hell hinterlegt (wie Kartenkacheln/Popups), statt im
   Dark Mode zu wechseln - .brand-drone/.brand-rest sind daher FESTE Farben,
   nicht die theme-fähigen .app-name-drone/-rest weiter oben. */
.brand-lockup {
  display:flex; align-items:center; gap:14px; width:fit-content; max-width:100%; box-sizing:border-box;
  background:#fff; padding:12px 18px; border-radius:10px; margin:2px 0 18px 0;
}
.brand-lockup-text { display:flex; flex-direction:column; gap:2px; min-width:0; }
.brand-lockup-name { font-family:'Space Grotesk', Arial, Helvetica, sans-serif; font-weight:700; font-size:25px; line-height:1.15; white-space:nowrap; }
.brand-lockup-tagline { font-family:'Instrument Sans', Arial, Helvetica, sans-serif; font-weight:700; font-size:14px; color:#5a6b7a; white-space:nowrap; }
.brand-lockup-icon { width:52px; height:52px; border-radius:12px; flex:0 0 auto; }
.brand-drone { color:#1565c0; }
.brand-rest { color:#1a1a2e; }
.legal-section { display:none; }
.legal-section.active { display:block; }
.legal-section h3 { font-size:15px; margin:0 0 10px 0; color:var(--text-heading); }
.legal-section h4 { font-size:12.5px; margin:16px 0 4px 0; color:var(--text-heading); }
.legal-section h4:first-of-type { margin-top:0; }
.help-toc { display:flex; flex-wrap:wrap; gap:10px 16px; margin:0 0 16px 0; padding:10px 12px; background:var(--bg-button); border:1px solid var(--border); border-radius:10px; }
.help-toc-group { display:flex; flex-direction:column; gap:3px; min-width:150px; flex:1 1 150px; }
.help-toc-group-label { font-size:10.5px; font-weight:700; text-transform:uppercase; letter-spacing:.02em; color:var(--text-muted); }
.help-toc-links { display:flex; flex-direction:column; gap:2px; }
.help-toc-links a { font-size:12px; color:var(--link); text-decoration:none; }
.help-toc-links a:hover { text-decoration:underline; color:var(--link-hover); }
.legal-section p, .legal-section ul { margin:4px 0; }
.legal-section ul { padding-left:20px; }
.legal-section li { margin-bottom:4px; }

@media (max-width: 768px) {
  /* Höhe aus der gemessenen Sichtfläche statt aus 100vh: auf einem iPhone im
     Startbildschirm-Betrieb meldet vh die volle Bildschirmhöhe (gemessen 874),
     der Bereich der App beginnt aber erst unter der Statusleiste und ist nur
     812 hoch. Das Fenster war damit 62 px zu hoch, sein unteres Ende lag
     außerhalb - der Text ließ sich nicht bis zum Schluss lesen. */
  .legal-modal {
    width:100vw; max-width:100vw; top:0; left:0; transform:none; border-radius:0;
    /* box-sizing, weil das Fenster oben und unten den Sicherheitsabstand als
       Innenabstand trägt: ohne das kam er zur Höhe hinzu und das Fenster reichte
       gemessene 846 px weit bei 812 px Höhe - die letzten Zeilen lagen außerhalb. */
    box-sizing:border-box;
    height:var(--sichtbare-hoehe, 100dvh); max-height:var(--sichtbare-hoehe, 100dvh);
  }
}

/* Hinweis-Popups (js/toast.js) - z.B. "keine Daten" bei den Sonderlayern.
   Bottom-center statt bottom-left, damit es sich nicht mit dem Suchfeld
   (siehe SearchControl in main.js) überschneidet. Bewusst fest dunkel
   gestylt (nicht theme-abhängig) - ein Toast/Snackbar in dunklem Look ist
   ein etabliertes, themeunabhängiges UI-Muster (ähnlich z.B. Android). */
#toastContainer { position:fixed; left:50%; bottom:18px; transform:translateX(-50%); z-index:2000; display:flex; flex-direction:column-reverse; gap:8px; align-items:center; pointer-events:none; max-width:92vw; }
.toast { pointer-events:auto; max-width:min(92vw,420px); background:#2c2c2c; color:#fff; padding:10px 12px 10px 14px; border-radius:8px; box-shadow:0 4px 14px rgba(0,0,0,.35); display:flex; align-items:center; gap:10px; font-size:12.5px; line-height:1.4; opacity:0; transform:translateY(10px); animation:toast-in .2s ease forwards; }
.toast-warn { border-left:4px solid #f6c343; }
.toast-error { border-left:4px solid #e57373; }
.toast-msg { flex:1 1 auto; }
.toast-close { background:none; border:none; color:#fff; opacity:.65; cursor:pointer; font-size:13px; line-height:1; padding:2px; flex:0 0 auto; }
.toast-close:hover { opacity:1; }
.toast-out { opacity:0!important; transform:translateY(10px)!important; transition:opacity .2s,transform .2s; }
@keyframes toast-in { to { opacity:1; transform:translateY(0); } }
