/*
 * @project     Prospekt-App
 * @file        app.css
 * @description Mobile App-Shell, Overlays, Dialoge, Formulare und Gebietsdarstellung
 * @author      Christian Rech
 * @copyright   2026 Christian Rech
 */

*,
*::before,
*::after {
    box-sizing: border-box;
}

html,
body,
#app {
    width: 100%;
    height: 100%;
    margin: var(--space-0);
}

body {
    overflow: hidden;
    color: var(--color-text);
    background: var(--color-map-fallback);
    font-family: var(--font-family);
    font-size: var(--font-size-base);
    line-height: var(--line-height);
}

button,
input,
select {
    color: inherit;
    font: inherit;
}

button,
input,
select {
    min-height: var(--size-touch-min);
}

button {
    border: var(--size-border) solid var(--color-border);
    border-radius: var(--radius-medium);
    background: var(--color-surface);
    cursor: pointer;
}

button:hover {
    background: var(--color-surface-muted);
}

button:disabled {
    cursor: not-allowed;
    opacity: var(--opacity-disabled);
}

:focus-visible {
    outline: var(--size-focus) solid var(--color-focus);
    outline-offset: var(--size-focus-offset);
}

[hidden] {
    display: none !important;
}

.karte {
    position: fixed;
    z-index: var(--z-map);
    inset: var(--space-0);
    background: var(--color-map-fallback);
}

.app-overlay {
    position: fixed;
    z-index: var(--z-overlay);
    inset: var(--space-3) var(--space-3) auto;
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-3);
    pointer-events: none;
}

.app-overlay > * {
    pointer-events: auto;
}

.gebiet-button,
.gebiet-menue,
.benutzer-button,
.benutzer-menue,
.app-status {
    border: var(--size-border) solid var(--color-border);
    border-radius: var(--radius-medium);
    background: var(--color-surface-overlay);
    box-shadow: var(--space-0) var(--size-shadow-y) var(--size-shadow-blur) var(--color-shadow);
}

.gebiet-bereich {
    position: relative;
    min-width: 0;
}

.gebiet-button {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    max-width: 60vw;
    min-height: var(--size-touch-min);
    padding: var(--space-3) var(--space-4);
    font-weight: var(--font-weight-strong);
    text-align: left;
}

.gebiet-button span {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.gebiet-menue {
    position: absolute;
    top: calc(100% + var(--space-2));
    left: var(--space-0);
    display: grid;
    width: max-content;
    max-width: min(80vw, var(--size-dialog));
    max-height: 60vh;
    padding: var(--space-2);
    overflow-y: auto;
    gap: var(--space-2);
}

.gebiet-liste,
.gebiet-strassen-liste,
.gebiet-verwaltung-liste {
    display: grid;
    margin: var(--space-0);
    padding: var(--space-0);
    gap: var(--space-2);
    list-style: none;
}

.gebiet-auswahl {
    width: 100%;
    padding: var(--space-2) var(--space-3);
    text-align: left;
}

.gebiet-auswahl[aria-current="true"] {
    border-color: var(--color-action);
    font-weight: var(--font-weight-strong);
}

.gebiet-schalter {
    display: flex;
    min-height: var(--size-touch-min);
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-0) var(--space-2);
}

.gebiet-schalter input {
    width: var(--space-5);
    height: var(--space-5);
    min-height: var(--space-5);
}

.gebiet-strassen {
    display: grid;
    padding-top: var(--space-2);
    border-top: var(--size-border) solid var(--color-border);
    gap: var(--space-2);
}

.gebiet-strassen h2 {
    font-size: var(--font-size-base);
}

.gebiet-strasse {
    display: flex;
    justify-content: space-between;
    gap: var(--space-4);
    padding: var(--space-1) var(--space-2);
}

.gebiet-strasse-zahlen,
.gebiet-details {
    color: var(--color-text-muted);
    font-size: var(--font-size-small);
}

.gebiet-zeile {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-2);
    border: var(--size-border) solid var(--color-border);
    border-radius: var(--radius-medium);
}

.gebiet-zeile[data-inaktiv="true"] {
    opacity: var(--opacity-disabled);
}

.gebiet-aktionen {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

.gebiet-aktionen button {
    padding: var(--space-2) var(--space-3);
}

/* Der Fortschrittsring ist breiter als das Benutzer-Icon; beide stehen rechtsbuendig,
   damit nichts ueber den Bildschirmrand hinausragt. */
.benutzer-bereich {
    position: relative;
    display: grid;
    justify-items: end;
}

.benutzer-button {
    width: var(--size-user);
    height: var(--size-user);
    padding: var(--space-0);
    border-radius: var(--radius-round);
    color: var(--color-user-contrast);
    background: var(--color-user-default);
    font-weight: var(--font-weight-strong);
}

.benutzer-button:hover {
    background: var(--color-user-default);
}

.benutzer-menue {
    position: absolute;
    top: calc(100% + var(--space-2));
    right: var(--space-0);
    display: grid;
    min-width: max-content;
    padding: var(--space-2);
    gap: var(--space-1);
}

.benutzer-menue button {
    padding: var(--space-2) var(--space-3);
    text-align: left;
}

/* Das Sendeintervall hat vier Werte und bleibt deshalb ein Auswahlfeld, waehrend alle anderen
   Eintraege des Menues Schaltflaechen sind. */
.benutzer-menue-feld {
    display: grid;
    padding: var(--space-2) var(--space-3);
    gap: var(--space-1);
}

.benutzer-menue-feld label {
    color: var(--color-text-muted);
    font-size: var(--font-size-small);
}

/* Anzahl neben einer Ueberschrift. Bewusst kein Praefix icon-: den beansprucht Lucide. */
.listenzahl {
    display: inline-block;
    padding: var(--space-0) var(--space-2);
    border-radius: var(--radius-round);
    background: var(--color-surface-muted);
    color: var(--color-text-muted);
    font-size: var(--font-size-small);
    font-weight: var(--font-weight-strong);
    text-align: center;
}

.listenzahl:empty {
    display: none;
}

/* Beschriftung ohne eigenes Eingabefeld -- der Startansicht-Picker traegt seinen Wert als Text. */
.formular-beschriftung {
    color: var(--color-text-muted);
    font-size: var(--font-size-small);
}

.app-status {
    position: fixed;
    z-index: var(--z-message);
    right: var(--space-3);
    bottom: var(--space-3);
    left: var(--space-3);
    padding: var(--space-3) var(--space-4);
    color: var(--color-text);
}

.app-status[data-status="error"],
.formular-status[data-status="error"] {
    color: var(--color-danger);
}

dialog {
    width: min(calc(100% - var(--space-4)), var(--size-dialog));
    max-height: calc(100% - var(--space-4));
    padding: var(--space-0);
    overflow: auto;
    border: var(--size-border) solid var(--color-border);
    border-radius: var(--radius-medium);
    color: var(--color-text);
    background: var(--color-surface);
}

dialog::backdrop {
    background: var(--color-backdrop);
}

.dialog-inhalt {
    display: grid;
    padding: var(--space-5);
    gap: var(--space-4);
}

.dialog-kopf {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
}

h1,
h2,
h3,
p {
    margin: var(--space-0);
}

h1,
h2 {
    font-size: var(--font-size-title);
}

h3 {
    font-size: var(--font-size-large);
}

.dialog-schliessen {
    min-width: var(--size-touch-min);
    padding: var(--space-2);
}

.benutzer-liste {
    display: grid;
    padding: var(--space-0);
    gap: var(--space-2);
    list-style: none;
}

.benutzer-auswahl {
    display: flex;
    width: 100%;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3);
    text-align: left;
}

.benutzer-farbpunkt {
    flex: 0 0 var(--size-touch-min);
    width: var(--size-touch-min);
    height: var(--size-touch-min);
    display: grid;
    place-items: center;
    border-radius: var(--radius-round);
    color: var(--color-user-contrast);
    background: var(--color-user-default);
    font-size: var(--font-size-small);
    font-weight: var(--font-weight-strong);
}

.benutzer-zeile {
    display: grid;
    grid-template-columns: var(--size-touch-min) minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-2);
    border: var(--size-border) solid var(--color-border);
    border-radius: var(--radius-medium);
}

.benutzer-zeile[data-inaktiv="true"] {
    opacity: var(--opacity-disabled);
}

.benutzer-aktionen {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

.benutzer-aktionen button,
.button-primaer,
.button-gefahr {
    padding: var(--space-2) var(--space-4);
}

.button-primaer {
    border-color: var(--color-action);
    color: var(--color-action-text);
    background: var(--color-action);
}

.button-primaer:hover {
    background: var(--color-action);
}

.button-gefahr {
    border-color: var(--color-danger);
    color: var(--color-danger-text);
    background: var(--color-danger);
}

.button-gefahr:hover {
    background: var(--color-danger);
}

.formular,
.formular-feld,
.einstellungen-abschnitt {
    display: grid;
    gap: var(--space-2);
}

.formular {
    gap: var(--space-4);
}

.formular label {
    font-weight: var(--font-weight-strong);
}

.formular input,
.formular select {
    width: 100%;
    padding: var(--space-2) var(--space-3);
    border: var(--size-border) solid var(--color-border);
    border-radius: var(--radius-small);
    background: var(--color-surface);
}

.formular-aktionen {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: var(--space-2);
}

.formular-status,
.leerzustand {
    color: var(--color-text-muted);
    font-size: var(--font-size-small);
}

.formular textarea,
.import-abschnitt textarea {
    width: 100%;
    min-height: calc(var(--size-touch-min) * 3);
    padding: var(--space-2) var(--space-3);
    border: var(--size-border) solid var(--color-border);
    border-radius: var(--radius-small);
    color: var(--color-text);
    background: var(--color-surface);
    font-family: var(--font-family);
    font-size: var(--font-size-small);
    resize: vertical;
}

.formular-feld input[type="file"] {
    padding: var(--space-2);
}

.hinweis {
    color: var(--color-text-muted);
    font-size: var(--font-size-small);
}

.import-abschnitt {
    display: grid;
    padding-top: var(--space-3);
    border-top: var(--size-border) solid var(--color-border);
    gap: var(--space-3);
}

.import-kennzahlen,
.import-meldungen,
.import-offene {
    display: grid;
    margin: var(--space-0);
    padding: var(--space-0);
    gap: var(--space-1);
    list-style: none;
    font-size: var(--font-size-small);
}

.import-bezeichnung {
    font-weight: var(--font-weight-strong);
}

.import-meldungen[data-art="fehler"] {
    color: var(--color-danger);
}

.import-meldungen[data-art="warnung"] {
    color: var(--color-status-highlighted);
}

.import-offene {
    gap: var(--space-3);
}

.import-adresse {
    display: grid;
    padding: var(--space-3);
    border: var(--size-border) solid var(--color-border);
    border-radius: var(--radius-medium);
    gap: var(--space-2);
}

.import-adresse input {
    width: 100%;
    padding: var(--space-2) var(--space-3);
    border: var(--size-border) solid var(--color-border);
    border-radius: var(--radius-small);
    background: var(--color-surface);
}

.koordinatenpicker {
    display: grid;
    gap: var(--space-3);
}

.koordinatenpicker[hidden],
.import-offene[hidden] {
    display: none;
}

.koordinatenpicker-kartenrahmen {
    position: relative;
    overflow: hidden;
    height: var(--size-picker-map);
    border: var(--size-border) solid var(--color-border);
    border-radius: var(--radius-medium);
}

.koordinatenpicker-karte {
    width: 100%;
    height: 100%;
}

.koordinatenpicker-fadenkreuz {
    position: absolute;
    z-index: var(--z-picker-crosshair);
    top: 50%;
    left: 50%;
    width: var(--size-picker-crosshair);
    height: var(--size-picker-crosshair);
    border: var(--size-border) solid var(--color-danger);
    border-radius: var(--radius-round);
    box-shadow: 0 0 0 var(--size-border) var(--color-surface);
    pointer-events: none;
    transform: translate(-50%, -50%);
}

.koordinatenpicker-fadenkreuz::before,
.koordinatenpicker-fadenkreuz::after {
    position: absolute;
    top: 50%;
    left: 50%;
    display: block;
    width: var(--size-picker-crosshair);
    height: var(--size-picker-crosshair-stroke);
    background: var(--color-danger);
    content: "";
    transform: translate(-50%, -50%);
}

.koordinatenpicker-fadenkreuz::after {
    transform: translate(-50%, -50%) rotate(90deg);
}

progress {
    width: 100%;
    height: var(--space-3);
}

.gebiet-flaeche {
    fill: var(--color-status-selection);
    fill-opacity: 0.25;
    stroke: var(--color-action);
    stroke-width: 2;
}

.gebiet-route {
    fill: none;
    stroke: var(--color-status-planned);
    stroke-width: 3;
    stroke-dasharray: 6 6;
}

.zustellpunkt {
    stroke: var(--color-surface);
    stroke-width: 1.5;
    fill-opacity: 1;
}

.zustellpunkt-verortet {
    fill: var(--color-zustellpunkt-verortet);
}

.zustellpunkt-pruefen {
    fill: var(--color-zustellpunkt-pruefen);
}

/* Ein noch nie gefragter Zustellpunkt bleibt hohl, statt farblos zu verschwinden. */
.zustellpunkt-offen {
    fill: var(--color-zustellpunkt-offen);
    stroke: var(--color-zustellpunkt-offen-rand);
}

.zustellpunkt-auswahl {
    fill: none;
    stroke: var(--color-zustellpunkt-aktiv);
    stroke-width: 3;
}

.leaflet-container {
    background: var(--color-map-fallback);
    font-family: var(--font-family);
    /* Die eine Zeile, die Leaflet fehlt: leaflet.css setzt user-select und
       -webkit-tap-highlight-color, aber nicht dies. Ohne sie zeigt Safari auf iOS beim
       Langdruck die Systemlupe ueber der Karte. */
    -webkit-touch-callout: none;
}

/* Die Zoom-Schaltflaechen beginnen unterhalb des Gebietswechslers, nicht darunter verdeckt. */
#karte .leaflet-top.leaflet-left {
    margin-top: calc(var(--size-touch-min) + var(--space-4));
}

/* Die Doppelklasse ist noetig, weil Leaflet die Schaltflaechen mit
   .leaflet-touch .leaflet-bar a auf 30 px festlegt. Touch-Ziele bleiben >= 48 px. */
.leaflet-control-zoom a,
.leaflet-touch .leaflet-control-zoom a {
    width: var(--size-touch-min);
    min-width: var(--size-touch-min);
    height: var(--size-touch-min);
    line-height: var(--size-touch-min);
}

/* Startfehlerseite: erscheint, wenn Konfiguration, Datenbank oder Schemastand fehlen.
   Sie ist die einzige Seite ohne Vollbildkarte und darf daher scrollen. */
.startfehler-seite {
    height: auto;
    min-height: 100%;
    overflow: auto;
    background: var(--color-surface-muted);
}

.startfehler {
    display: grid;
    gap: var(--space-4);
    max-width: var(--size-dialog);
    margin: var(--space-0) auto;
    padding: var(--space-5) var(--space-4);
}

.startfehler h1 {
    margin: var(--space-0);
    font-size: var(--font-size-title);
}

.startfehler-liste {
    display: grid;
    gap: var(--space-3);
    margin: var(--space-0);
    padding: var(--space-0);
    list-style: none;
}

.startfehler-befund {
    display: grid;
    gap: var(--space-2);
    padding: var(--space-4);
    border: var(--size-border) solid var(--color-border);
    border-radius: var(--radius-medium);
    background: var(--color-surface);
}

.startfehler-befund h2 {
    margin: var(--space-0);
    font-size: var(--font-size-large);
}

.startfehler-meldung,
.startfehler-hinweis {
    margin: var(--space-0);
}

.startfehler-hinweis {
    color: var(--color-text-muted);
    font-size: var(--font-size-small);
}

.startfehler-aktion {
    display: flex;
}

/* ---------------------------------------------------------------------------
   Version-Badge: unten rechts, knapp oberhalb der OpenStreetMap-Attribution
   --------------------------------------------------------------------------- */
.app-version {
    position: fixed;
    z-index: var(--z-overlay);
    right: var(--space-3);
    bottom: calc(var(--size-attribution) + var(--space-2));
    padding: var(--space-1) var(--space-2);
    border: var(--size-border) solid var(--color-border);
    border-radius: var(--radius-round);
    color: var(--color-text-muted);
    background: var(--color-surface-overlay);
    font-size: var(--font-size-mikro);
    line-height: 1;
    /* Zwingend: sonst entsteht ein toter Fleck ueber der Karte und die
       Attributionslinks darunter waeren nicht mehr erreichbar. */
    pointer-events: none;
}

/* ---------------------------------------------------------------------------
   Stoppnummern auf der Karte
   --------------------------------------------------------------------------- */
.stop-nummer {
    color: var(--color-text);
    background: var(--color-surface-overlay);
    border-radius: var(--radius-small);
    font-size: var(--font-size-mikro);
    font-weight: var(--font-weight-strong);
    line-height: 1;
    padding: var(--space-1);
    text-align: center;
    white-space: nowrap;
    pointer-events: none;
}

/* ---------------------------------------------------------------------------
   Gebietseditor
   --------------------------------------------------------------------------- */
.dialog-gross {
    width: calc(100% - var(--space-2));
    max-width: var(--size-dialog-gross);
    height: calc(100% - var(--space-2));
    max-height: none;
}

.dialog-inhalt-voll {
    height: 100%;
    padding: var(--space-4);
    grid-template-rows: auto auto minmax(0, 1fr) auto;
}

.editor-tabs {
    display: flex;
    gap: var(--space-2);
}

.editor-tab {
    flex: 1;
}

.editor-tab[aria-selected="true"] {
    border-color: var(--color-action);
    color: var(--color-action-text);
    background: var(--color-action);
}

.editor-layout {
    display: grid;
    gap: var(--space-4);
    min-height: 0;
}

.editor-panel {
    display: grid;
    gap: var(--space-3);
    align-content: start;
    min-height: 0;
}

.editor-kartenrahmen {
    position: relative;
}

.editor-karte {
    height: var(--size-editor-karte);
    border: var(--size-border) solid var(--color-border);
    border-radius: var(--radius-medium);
    background: var(--color-map-fallback);
}

.editor-werkzeuge {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

/* ---------------------------------------------------------------------------
   Zustellpunktliste im Editor
   --------------------------------------------------------------------------- */
.stop-werkzeuge {
    display: grid;
    gap: var(--space-2);
}

.stop-suche {
    display: grid;
    gap: var(--space-1);
}

.filter-chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

.chip[aria-pressed="true"] {
    border-color: var(--color-action);
    color: var(--color-action-text);
    background: var(--color-action);
}

.stop-liste {
    display: grid;
    gap: var(--space-2);
    overflow-y: auto;
    min-height: 0;
}

.stop-gruppe {
    border: var(--size-border) solid var(--color-border);
    border-radius: var(--radius-medium);
    background: var(--color-surface);
}

.stop-gruppe > summary {
    padding: var(--space-3);
    min-height: var(--size-touch-min);
    cursor: pointer;
}

.stop-zeile {
    border-top: var(--size-border) solid var(--color-border);
}

.stop-zeile[aria-current="true"] {
    background: var(--color-surface-muted);
}

.stop-kopf {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
    padding: var(--space-2) var(--space-3);
    border: 0;
    border-radius: var(--space-0);
    background: none;
    text-align: left;
}

.stop-nummer-badge {
    flex: 0 0 auto;
    min-width: var(--size-touch-min);
    padding: var(--space-1) var(--space-2);
    border-radius: var(--radius-round);
    background: var(--color-surface-muted);
    font-size: var(--font-size-small);
    font-weight: var(--font-weight-strong);
    text-align: center;
}

.stop-adresse {
    flex: 1 1 auto;
}

.stop-status {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    color: var(--color-text-muted);
    font-size: var(--font-size-small);
    white-space: nowrap;
}

.stop-status-punkt {
    width: var(--space-3);
    height: var(--space-3);
    border: var(--size-border) solid var(--color-border);
    border-radius: var(--radius-round);
}

.stop-status-punkt[data-status="verortet"] {
    background: var(--color-zustellpunkt-verortet);
}

.stop-status-punkt[data-status="zu_pruefen"] {
    background: var(--color-zustellpunkt-pruefen);
}

.stop-status-punkt[data-status="offen"] {
    background: var(--color-zustellpunkt-offen);
}

.stop-detail {
    padding: var(--space-3);
    border-top: var(--size-border) solid var(--color-border);
    background: var(--color-surface-muted);
}

.stop-mehr {
    justify-self: start;
}

.adresszeile {
    display: grid;
    gap: var(--space-2);
}

.adresszeile-kopf {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin: var(--space-0);
    font-weight: var(--font-weight-strong);
}

.adresszeile-meldung {
    margin: var(--space-0);
    font-size: var(--font-size-small);
}

/* ---------------------------------------------------------------------------
   Griffe der Gebietsflaeche
   --------------------------------------------------------------------------- */
.gebiet-flaeche-bearbeitung {
    stroke-dasharray: 4 3;
}

.gebiet-flaeche-ungueltig {
    stroke: var(--color-danger);
}

/* Das Touch-Ziel bleibt 48 px gross; sichtbar ist nur der kleine Punkt in der Mitte.
   touch-action und user-select verhindern, dass Android beim Halten eine
   Systemauswahl oeffnet oder die Karte mitzieht. */
.polygon-griff,
.polygon-griff-mitte {
    display: grid;
    place-items: center;
    touch-action: none;
    user-select: none;
    -webkit-user-select: none;
}

.polygon-griff::before,
.polygon-griff-mitte::before {
    content: "";
    display: block;
    border-radius: var(--radius-round);
    border: var(--size-border) solid var(--color-surface);
}

.polygon-griff::before {
    width: var(--size-polygon-griff);
    height: var(--size-polygon-griff);
    background: var(--color-editor-griff);
}

.polygon-griff-mitte::before {
    width: var(--size-polygon-griff-mitte);
    height: var(--size-polygon-griff-mitte);
    background: var(--color-surface);
    border-color: var(--color-editor-griff-mitte);
}

.polygon-griff[data-langdruck="true"]::before,
.polygon-griff-fokus::before {
    outline: var(--size-focus) solid var(--color-focus);
    outline-offset: var(--size-focus-offset);
}

/* Einziger Breakpoint der App: ab hier passen Liste und Karte nebeneinander.
   Media Queries koennen keine Custom Properties auswerten, darum steht der Wert
   hier ausnahmsweise als feste Groesse. */
@media (min-width: 60rem) {
    .editor-tabs {
        display: none;
    }

    .editor-layout {
        grid-template-columns: minmax(0, 22rem) minmax(0, 1fr);
    }

    .editor-karte {
        height: 100%;
        min-height: var(--size-editor-karte);
    }
}

/* ---------------------------------------------------------------------------
   Schaltflaechen mit Icon (lokale Lucide-Schrift, siehe public/vendor/lucide/)

   Wichtig: Die Klassen heissen bewusst NICHT icon-*. Lucide beansprucht diesen
   Praefix mit `[class^="icon-"] { font-family: 'lucide' !important }` — eine
   Schaltflaeche mit einer icon-*-Klasse bekaeme die Icon-Schrift fuer ihren
   gesamten Text.
   --------------------------------------------------------------------------- */
.aktionsknopf {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
}

/* Reine Icon-Schaltflaeche: quadratisch, damit das Touch-Ziel gross genug bleibt.
   Die Beschriftung steht ausschliesslich in aria-label und title. */
.aktionsknopf-nur {
    width: var(--size-touch-min);
    min-width: var(--size-touch-min);
    height: var(--size-touch-min);
    padding: var(--space-0);
    gap: var(--space-0);
}

/* Das Icon ist reines Schmuckelement und darf nie ein Zeigerereignis abfangen. */
i[class^="icon-"],
i[class*=" icon-"] {
    pointer-events: none;
}

/* Abstand zum Text nur, wenn ueberhaupt Text danebensteht. */
button > i[class^="icon-"] + span,
summary > i[class^="icon-"] + span,
label > i[class^="icon-"] + span {
    margin-left: var(--space-2);
}

/* Serverseitig gerendertes Markup: Icon und Text stehen dort direkt nebeneinander. */
button:not(.aktionsknopf) > i[class^="icon-"] {
    margin-right: var(--space-2);
}

.dialog-schliessen > i[class^="icon-"],
.aktionsknopf-nur > i[class^="icon-"] {
    margin-right: var(--space-0);
}

/* Reine Icon-Schaltflaechen der Gebietsleiste: quadratisch statt Textpadding. */
.gebiet-aktionen .aktionsknopf-nur {
    padding: var(--space-0);
}

/* ---------------------------------------------------------------------------
   Erledigt-Markierung, Pinselgeste und Fortschritt
   --------------------------------------------------------------------------- */

/* Merkregel: die Fuellung sagt *wer*, der Rand sagt *welcher Zustand*. Die Benutzerfarbe
   kommt zur Laufzeit als Custom Property an das einzelne Element. */
.zustellpunkt-erledigt {
    fill: var(--color-user-default, var(--color-erledigt-rueckfall));
}

/* Ein erledigter Punkt behaelt seinen Statusrand: beide Aussagen bleiben gleichzeitig
   ablesbar, ohne ein zweites Kartenelement zu brauchen. */
.zustellpunkt-erledigt.zustellpunkt-pruefen {
    stroke: var(--color-zustellpunkt-pruefen);
    stroke-width: 2;
}

/* Fernsicht nach Gesamtkonzept 11: duenn, halbtransparent, eine Linie je Strasse und Person. */
.erledigt-linie {
    fill: none;
    stroke: var(--color-user-default, var(--color-erledigt-rueckfall));
    stroke-width: var(--size-erledigt-linie);
    stroke-linecap: round;
    stroke-opacity: var(--opacity-erledigt-linie);
}

.pinsel-vorschau {
    fill: none;
    stroke: var(--color-pinsel-vorschau);
    stroke-width: var(--size-vorschau-rand);
}

.pinsel-vorschau-weg {
    stroke: var(--color-pinsel-radierer);
    stroke-dasharray: 4 3;
}

/* Leaflet nimmt bei dragging.disable() die Klasse leaflet-touch-drag vom Container; damit
   fiele touch-action auf "pan-x pan-y" zurueck und der Browser wollte selbst scrollen.
   Diese Zeile ist deshalb Voraussetzung der Geste und nicht Kosmetik. */
.leaflet-container.karte-pinselmodus {
    touch-action: none;
}

/* Zeigt, wie breit der Pinsel ist. Auf dem Handy ist das die einzige Rueckmeldung ueber die
   Trefferzone -- und die Quelle, aus der das JavaScript den Trefferradius liest. */
.pinsel-kreis {
    position: absolute;
    z-index: var(--z-pinsel);
    top: var(--space-0);
    left: var(--space-0);
    width: var(--size-pinsel);
    height: var(--size-pinsel);
    margin: calc(var(--size-pinsel) / -2) var(--space-0) var(--space-0)
        calc(var(--size-pinsel) / -2);
    border: var(--size-vorschau-rand) solid var(--color-pinsel-vorschau);
    border-radius: var(--radius-round);
    /* Zwingend: sonst faengt der Kreis seinen eigenen Zeiger ab. */
    pointer-events: none;
}

/* Unsichtbares Mass neben dem Pinselkreis: die Punktgeste braucht denselben Trefferradius,
   hat aber keinen sichtbaren Kreis, aus dem sie ihn ablesen koennte. Ein Parsen der Custom
   Property wuerde bei einem Wechsel der Einheit stillschweigend falsch. */
.punktziel-mass {
    position: absolute;
    top: var(--space-0);
    left: var(--space-0);
    width: var(--size-pinsel);
    height: var(--space-0);
    visibility: hidden;
    pointer-events: none;
}

/* Dieselbe Farbe wie der gedrueckte Radiererknopf: der Finger und die Schaltflaeche machen
   dieselbe Aussage. Der gestrichelte Vorschauring bleibt dagegen bewusst gedaempft. */
.karte-pinselmodus[data-pinsel="radieren"] .pinsel-kreis {
    border-color: var(--color-radierer-aktiv);
    border-style: dashed;
}

/* Unten links in Daumenreichweite; .app-version und die OSM-Attribution bleiben rechts frei.
   Waehrend des Markierens ist das nur eine 48 px schmale Saeule: die Erklaerung steht im Menue
   davor, und Verwerfen/Uebernehmen erscheinen erst, wenn etwas in der Vorschau liegt. */
.markieren-leiste {
    position: fixed;
    z-index: var(--z-overlay);
    bottom: calc(var(--size-attribution) + var(--space-6));
    left: var(--space-3);
    display: grid;
    justify-items: start;
    max-width: calc(100% - var(--space-6));
    gap: var(--space-2);
}

.markieren-rund,
.markieren-menue,
.markieren-aktionen {
    border: var(--size-border) solid var(--color-border);
    border-radius: var(--radius-medium);
    background: var(--color-surface-overlay);
    box-shadow: var(--space-0) var(--size-shadow-y) var(--size-shadow-blur) var(--color-shadow);
}

.markieren-rund {
    border-radius: var(--radius-round);
}

.markieren-rund[aria-pressed="true"] {
    border-color: var(--color-radierer-aktiv);
    color: var(--color-text);
    background: var(--color-radierer-aktiv);
}

/* Der scharfe Pinsel traegt die Farbe der markierenden Person; das Gruen ist nur der
   Rueckfall, wenn keine Benutzerfarbe vorliegt. Die beiden Eigenschaften werden zur Laufzeit
   am Element gesetzt und sind deshalb im :root bewusst nicht definiert. */
.markieren-umschalten-aktiv,
.markieren-umschalten-aktiv[aria-pressed="true"] {
    border-color: var(--color-markieren-knopf, var(--color-markieren-aktiv));
    color: var(--color-markieren-knopf-text, var(--color-markieren-aktiv-text));
    background: var(--color-markieren-knopf, var(--color-markieren-aktiv));
}

.markieren-menue {
    display: grid;
    width: max-content;
    max-width: min(80vw, var(--size-dialog));
    padding: var(--space-3);
    gap: var(--space-2);
}

.markieren-titel {
    margin: var(--space-0);
    font-size: var(--font-size-base);
}

.markieren-aktionen {
    display: flex;
    padding: var(--space-2);
    gap: var(--space-2);
}

.markieren-aktionen[aria-busy="true"] {
    opacity: var(--opacity-disabled);
}

/* Der Uebernehmen-Knopf traegt die Anzahl als Text; er bleibt trotzdem ein Touch-Ziel. */
.markieren-aktionen .button-primaer {
    min-width: var(--size-touch-min);
    padding: var(--space-0) var(--space-3);
    gap: var(--space-1);
}

/* ---------------------------------------------------------------------------
   Fortschrittsring unter dem Benutzer-Icon
   --------------------------------------------------------------------------- */
.fortschrittsring {
    position: relative;
    display: grid;
    width: var(--size-fortschrittsring);
    height: var(--size-fortschrittsring);
    margin-top: var(--space-2);
    padding: var(--space-0);
    border: var(--size-border) solid var(--color-border);
    border-radius: var(--radius-round);
    background: var(--color-surface-overlay);
    box-shadow: var(--space-0) var(--size-shadow-y) var(--size-shadow-blur) var(--color-shadow);
    place-items: center;
}

.fortschrittsring-grafik {
    position: absolute;
    inset: var(--space-0);
    /* Der Ring beginnt bei zwoelf Uhr statt bei drei. */
    transform: rotate(-90deg);
}

.fortschrittsring-bahn,
.fortschrittsring-wert {
    fill: none;
    stroke-width: var(--size-fortschrittsring-bahn);
}

.fortschrittsring-bahn {
    stroke: var(--color-border);
}

/* pathLength="100" macht den Umfang zu genau 100 Einheiten: der Offset ist damit
   unmittelbar 100 minus Prozent, ohne Radius- oder Pi-Rechnung im JavaScript. */
.fortschrittsring-wert {
    stroke: var(--color-markieren-aktiv);
    stroke-dasharray: 100;
    stroke-dashoffset: 100;
    stroke-linecap: round;
    transition: stroke-dashoffset var(--duration-fast) linear;
}

.fortschrittsring-zahl {
    position: relative;
    color: var(--color-text);
    font-size: var(--font-size-mikro);
    font-weight: var(--font-weight-strong);
}

/* Die absoluten Zahlen klappen links neben dem Ring auf, weil er am rechten Rand sitzt. */
.fortschritt-info {
    position: absolute;
    z-index: var(--z-overlay);
    top: calc(var(--size-user) + var(--space-2));
    right: calc(100% + var(--space-2));
    width: max-content;
    max-width: 60vw;
    margin: var(--space-0);
    padding: var(--space-2) var(--space-3);
    border: var(--size-border) solid var(--color-border);
    border-radius: var(--radius-medium);
    background: var(--color-surface-overlay);
    box-shadow: var(--space-0) var(--size-shadow-y) var(--size-shadow-blur) var(--color-shadow);
    color: var(--color-text-muted);
    font-size: var(--font-size-small);
}

/* ---------------------------------------------------------------------------
   Kurzlebige Meldungen
   --------------------------------------------------------------------------- */

/* Rechts neben der Knopfsaeule und oberhalb von Attribution und Versionsanzeige. */
.toast-bereich {
    position: fixed;
    z-index: var(--z-message);
    right: var(--space-3);
    bottom: calc(var(--size-attribution) + var(--space-5));
    left: calc(var(--space-3) + var(--size-touch-min) + var(--space-2));
    display: grid;
    justify-items: center;
    gap: var(--space-2);
    pointer-events: none;
}

.toast {
    width: max-content;
    max-width: min(100%, var(--size-toast));
    padding: var(--space-3) var(--space-4);
    border: var(--size-border) solid var(--color-border);
    border-radius: var(--radius-medium);
    background: var(--color-surface-overlay);
    box-shadow: var(--space-0) var(--size-shadow-y) var(--size-shadow-blur) var(--color-shadow);
    transition: opacity var(--duration-fast) ease-out;
    /* Antippen schliesst frueher; deshalb faengt der Toast selbst Zeigerereignisse ab. */
    pointer-events: auto;
    cursor: pointer;
}

/* Der Toast ist sofort sichtbar und blendet nur beim Verschwinden aus. */
.toast-geht {
    opacity: 0;
}

.toast-text {
    margin: var(--space-0);
    font-size: var(--font-size-small);
}

.toast-details {
    margin: var(--space-2) var(--space-0) var(--space-0);
    padding-left: var(--space-4);
    font-size: var(--font-size-small);
}

.toast[data-art="success"] {
    border-color: var(--color-erfolg);
    color: var(--color-erfolg);
}

.toast[data-art="error"] {
    border-color: var(--color-danger);
    color: var(--color-danger);
}

/* Sichtbar nur fuer Screenreader: die Wirkung der Geste wird vorgelesen, ohne Karte zu kosten. */
.nur-screenreader {
    position: absolute;
    width: var(--size-border);
    height: var(--size-border);
    margin: calc(var(--size-border) * -1);
    padding: var(--space-0);
    overflow: hidden;
    border: 0;
    clip-path: inset(50%);
    white-space: nowrap;
}

.gebiet-strasse-knopf {
    display: grid;
    width: 100%;
    min-height: var(--size-touch-min);
    padding: var(--space-2) var(--space-3);
    text-align: left;
    gap: var(--space-1);
}

.gebiet-strasse-knopf[aria-pressed="true"] {
    border-color: var(--color-action);
    font-weight: var(--font-weight-strong);
}

.gebiet-strasse-balken {
    width: 100%;
    height: var(--size-fortschritt-balken);
}


/* ---------------------------------------------------------------------------
   Standort, Verteiler und Faehnchen
   --------------------------------------------------------------------------- */

/* Unten rechts, spiegelbildlich zur Markierleiste: beide bleiben in Daumenreichweite, ohne
   sich zu ueberdecken, und die OSM-Attribution bleibt frei. */
.standort-bereich {
    position: fixed;
    z-index: var(--z-overlay);
    right: var(--space-3);
    bottom: calc(var(--size-attribution) + var(--space-6));
}

.standort-knopf {
    border: var(--size-border) solid var(--color-border);
    border-radius: var(--radius-round);
    background: var(--color-surface-overlay);
    box-shadow: var(--space-0) var(--size-shadow-y) var(--size-shadow-blur) var(--color-shadow);
}

/* Der Knopf wird nie disabled -- ein gesperrter Knopf kann seinen Sperrgrund nicht mehr
   erklaeren. Der Zustand ist deshalb rein optisch. */
.standort-knopf[data-zustand="aktiv"] {
    color: var(--color-standort);
}

.standort-knopf[data-zustand="sucht"] {
    opacity: var(--opacity-disabled);
}

.standort-punkt {
    fill: var(--color-standort);
    fill-opacity: 1;
    stroke: var(--color-standort-rand);
    stroke-width: var(--size-standort-rand);
}

.standort-genauigkeit {
    fill: var(--color-standort-genauigkeit);
    stroke: var(--color-standort);
    stroke-opacity: 0.4;
    stroke-width: var(--size-border);
}

/* Wie .benutzer-farbpunkt: rund, Initialen, Benutzerfarbe als Custom Property am Element.
   Damit ist ein Verteiler nie mit einem 6-px-Zustellpunkt und nie mit der eigenen Position
   zu verwechseln. */
.verteiler-marker-inhalt {
    display: flex;
    width: var(--size-verteiler);
    height: var(--size-verteiler);
    align-items: center;
    justify-content: center;
    border: var(--size-standort-rand) solid var(--color-verteiler-rand);
    border-radius: var(--radius-round);
    background: var(--color-user-default);
    box-shadow: var(--space-0) var(--size-shadow-y) var(--size-shadow-blur) var(--color-shadow);
    color: var(--color-user-contrast);
    font-size: var(--font-size-small);
    font-weight: var(--font-weight-strong);
}

/* Die Standort-Pane traegt pointer-events: none, damit der Pinselstrich an ihr vorbeigeht.
   Genau ein Objekt darin nimmt den Zeiger doch entgegen: der Verteilermarker, weil ein Klick
   darauf den Namen zeigt. Der Genauigkeitskreis daneben bleibt unberuehrt. */
.verteiler-marker {
    pointer-events: auto;
    cursor: pointer;
}

.verteilername .leaflet-popup-content {
    margin: var(--space-2) var(--space-3);
    font-size: var(--font-size-small);
}

/* Gefuellter Wimpel statt Umrisslinie: auf der Karte konkurriert das Faehnchen mit Haus- und
   Strassenlinien, und eine Kontur von einem Pixel geht darin unter. Bewusst ein Dreieck und
   keine wehende Rechteckfahne -- bei 20 px verliert jede Wellenlinie ihre Form.
   Der Schlagschatten uebernimmt die Aufgabe des frueheren text-shadow: er setzt die Fahne
   gegen dunkle Dachflaechen ab, ohne eine zweite Farbe einzufuehren. */
.faehnchen {
    color: var(--color-faehnchen);
    filter: drop-shadow(var(--space-0) var(--space-0) var(--size-border) var(--color-surface));
}

.faehnchen-form {
    position: relative;
    display: block;
    width: var(--size-faehnchen);
    height: var(--size-faehnchen);
}

/* Mast: sein Fuss sitzt auf der Koordinate des Zustellpunkts. */
.faehnchen-form::before {
    position: absolute;
    top: var(--space-0);
    left: var(--space-0);
    width: var(--size-faehnchen-mast);
    height: 100%;
    border-radius: var(--size-faehnchen-mast);
    background: currentColor;
    content: "";
}

/* Die Fahne selbst, vollflaechig. */
.faehnchen-form::after {
    position: absolute;
    top: var(--space-0);
    left: var(--size-faehnchen-mast);
    /* Die Fahne nimmt gut die Haelfte der Hoehe ein; der Rest bleibt Mast. Sein Fuss ist der
       Ankerpunkt auf der Karte und muss als solcher erkennbar bleiben. */
    width: calc(var(--size-faehnchen) * 0.7);
    height: calc(var(--size-faehnchen) * 0.52);
    background: currentColor;
    clip-path: polygon(0 0, 100% 0, 0 100%);
    content: "";
}

/* ---------------------------------------------------------------------------
   Infofeld am Zustellpunkt
   --------------------------------------------------------------------------- */

.punktinfo .leaflet-popup-content-wrapper,
.punktinfo .leaflet-popup-tip {
    border: var(--size-border) solid var(--color-border);
    background: var(--color-surface-overlay);
    color: var(--color-text);
}

.punktinfo .leaflet-popup-content-wrapper {
    border-radius: var(--radius-medium);
}

.punktinfo .leaflet-popup-content {
    width: var(--size-punktinfo) !important;
    margin: var(--space-2) var(--space-3);
    font-family: var(--font-family);
    font-size: var(--font-size-small);
    line-height: var(--line-height);
}

.punktinfo-kopf {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

.punktinfo-adresse {
    flex: 1;
    font-weight: var(--font-weight-strong);
}

/* "Dezent" entsteht ueber Farbe und Rahmenlosigkeit, nicht ueber eine kleine Flaeche: das
   Touch-Ziel bleibt quadratisch bei --size-touch-min. */
.punktinfo-stift {
    border-color: transparent;
    background: transparent;
    color: var(--color-text-muted);
}

.punktinfo-stift:hover,
.punktinfo-stift:focus-visible {
    color: var(--color-text);
}

.punktinfo-notiz {
    max-height: var(--size-punktinfo-notiz);
    margin: var(--space-1) var(--space-0) var(--space-0);
    overflow-y: auto;
    white-space: pre-line;
}

.punktinfo-leer {
    margin: var(--space-1) var(--space-0) var(--space-0);
    color: var(--color-text-muted);
}

.punktinfo-faehnchen {
    margin-top: var(--space-2);
    border-top: var(--size-border) solid var(--color-border);
    padding-top: var(--space-2);
}

.punktinfo-faehnchen-zeile {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
}

.punktinfo-faehnchen-notiz {
    flex: 1;
    max-height: var(--size-punktinfo-notiz);
    margin: var(--space-0);
    overflow-y: auto;
    color: var(--color-faehnchen);
    white-space: pre-line;
}

/* ---------------------------------------------------------------------------
   Faehnchenliste im Gebietsmenue -- der Tastaturweg zu einer Notiz auf der Karte
   --------------------------------------------------------------------------- */

.gebiet-faehnchen-liste {
    display: grid;
    margin: var(--space-0);
    padding: var(--space-0);
    list-style: none;
    gap: var(--space-1);
}

.gebiet-faehnchen-knopf {
    display: grid;
    width: 100%;
    min-height: var(--size-touch-min);
    padding: var(--space-2) var(--space-3);
    text-align: left;
    gap: var(--space-1);
}

.gebiet-faehnchen-notiz {
    overflow: hidden;
    color: var(--color-text-muted);
    font-size: var(--font-size-small);
    text-overflow: ellipsis;
    white-space: nowrap;
}

.notiz-adresse {
    margin: var(--space-0);
    font-weight: var(--font-weight-strong);
}
