/* =====================================================================
 Geolyser-MapApp - Geolyser Brand Base
 + linke Sidebar (OneNote-Style)
 ===================================================================== */

/* ---- Web-Fonts (self-hosted) ---- */
@font-face { font-family: "IBM Plex Sans"; font-weight: 300; font-style: normal; font-display: swap;
    src: url("/fonts/IBMPlexSans-Light.ttf") format("truetype"); }
@font-face { font-family: "IBM Plex Sans"; font-weight: 400; font-style: normal; font-display: swap;
    src: url("/fonts/IBMPlexSans-Regular.ttf") format("truetype"); }
@font-face { font-family: "IBM Plex Sans"; font-weight: 500; font-style: normal; font-display: swap;
    src: url("/fonts/IBMPlexSans-Medium.ttf") format("truetype"); }
@font-face { font-family: "IBM Plex Sans"; font-weight: 600; font-style: normal; font-display: swap;
    src: url("/fonts/IBMPlexSans-SemiBold.ttf") format("truetype"); }
@font-face { font-family: "Space Grotesk"; font-weight: 300 700; font-style: normal; font-display: swap;
    src: url("/fonts/SpaceGrotesk-VariableFont_wght.ttf") format("truetype-variations"); }

/* ---- Brand-Tokens ---- */
:root {
    --c-dark:        #181B1D;
    --c-dark-soft:   #1f2426;
    --c-graphite:    #394043;
    --c-light:       #FFFFFF;

    --c-primary:     #007FB4;
    --c-primary-hi:  #00A0D2;
    --c-cyan:        #3BBDE8;
    --c-cyan-soft:   #9BD9F5;
    --c-primary-dk:  #00608D;
    --c-primary-xdk: #004161;

    --c-signal:      #02FE89;
    --c-signal-dim:  rgba(2, 254, 137, 0.18);
    --c-signal-dk:   #00c76a;

    --c-error:       #ff5c65;
    --c-error-bg:    rgba(255, 92, 101, 0.08);
    --c-warn:        #ffc04a;

    --bg:            var(--c-dark);
    --bg-elevated:   #20262a;
    --bg-panel:      #1c2126;       /* Sidebars / Topbar-Body */
    --bg-card:       rgba(255, 255, 255, 0.03);
    --border:        rgba(155, 217, 245, 0.10);
    --border-hi:     rgba(59, 189, 232, 0.35);
    --fg:            #eef3f6;
    --muted:         #8a979e;
    --muted-hi:      #b8c3c9;
    --input-bg:      #0d1214;
    --input-bg-ro:   #0a0d0f;
    --map-info-bg:   rgba(24, 27, 29, 0.82);

    --radius-sm:     6px;
    --radius:        10px;
    --radius-lg:     16px;

    --shadow-card:   0 10px 40px rgba(0,0,0,0.45), 0 1px 0 rgba(255,255,255,0.02) inset;
    --shadow-lift:   0 14px 50px rgba(0, 127, 180, 0.18);

    --map-surface:       #0a0d0f;
    --map-control-bg:    rgba(24, 27, 29, 0.85);
    --map-control-bg-lo: rgba(24, 27, 29, 0.82);
    --topbar-bg:         rgba(24, 27, 29, 0.7);

    --sidebar-rail-w:    52px;
    --sidebar-w:         300px;
    --topbar-h:          56px;

    --body-gradient:
        radial-gradient(1200px 600px at 80% -10%, rgba(0, 127, 180, 0.14), transparent 60%),
        radial-gradient(900px 500px at -10% 110%, rgba(2, 254, 137, 0.06), transparent 60%),
        var(--bg);

    --font-ui:       "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    --font-display:  "Space Grotesk", "IBM Plex Sans", sans-serif;

    color-scheme: dark;
}

:root[data-theme="light"] {
    /* Tuning + polish runde 9: bluer-grey-Palette
 * (frueher zu neutral-grau, JP wollte den waermeren blau-grau-
 * Eindruck, den die rechte Sidebar in Runde 7 bekommen hat,
 * App-weit). Skala (von dunkel nach hell):
 * --bg : Body-Hintergrund (blau-grau)
 * --bg-card : Sidebar-Innenhuelle (etwas heller als --bg)
 * --bg-elevated : Modal-Card / Topbar (weiss + leichte Tönung)
 * --input-bg : Inputs / Selects (rein weiss) */
    --bg:            #e3ecf4;
    --bg-elevated:   #ffffff;
    --bg-panel:      #eaf1f8;       /* Sidebars: leicht bluer als Modal-Card */
    --bg-card:       #eaf1f8;
    --border:        #c1ced9;       /* solider blau-grau-Rand */
    --border-hi:     #8fa6b8;
    --fg:            #161b1e;
    --muted:         #566168;
    --muted-hi:      #2a3438;
    --input-bg:      #ffffff;
    --input-bg-ro:   #e8eef4;
    --map-info-bg:   rgba(255, 255, 255, 0.88);
    --c-signal:      #00b368;
    --c-signal-dim:  rgba(0, 179, 104, 0.14);
    --c-signal-dk:   #009458;
    --shadow-card:   0 10px 30px rgba(0, 40, 60, 0.08), 0 1px 0 rgba(255, 255, 255, 0.6) inset;
    --shadow-lift:   0 14px 50px rgba(0, 127, 180, 0.15);
    --map-surface:       #e4ecf0;
    --map-control-bg:    rgba(255, 255, 255, 0.92);
    --map-control-bg-lo: rgba(255, 255, 255, 0.88);
    --topbar-bg:         rgba(255, 255, 255, 0.85);
    --body-gradient:
        radial-gradient(1200px 600px at 80% -10%, rgba(0, 127, 180, 0.08), transparent 60%),
        radial-gradient(900px 500px at -10% 110%, rgba(0, 179, 104, 0.05), transparent 60%),
        var(--bg);
    color-scheme: light;
}

/* ---- Reset / Base ---- */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; height: 100%; }
body {
    font-family: var(--font-ui);
    color: var(--fg);
    background: var(--body-gradient);
    -webkit-font-smoothing: antialiased;
    line-height: 1.4;
}
h1, h2, h3, h4 { font-family: var(--font-display); font-weight: 600; margin: 0 0 .4em 0; }
a { color: var(--c-primary-hi); text-decoration: none; }
a:hover { text-decoration: underline; }

button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }
button:disabled { cursor: not-allowed; opacity: .55; }

/* ---- Topbar ---- */
.topbar {
    height: var(--topbar-h);
    display: flex; align-items: center; justify-content: space-between;
    padding: 0 16px;
    background: var(--topbar-bg);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border-bottom: 1px solid var(--border);
    position: sticky; top: 0; z-index: 50;
}
.brand { display: flex; align-items: center; gap: 10px; color: var(--fg); }
.brand:hover { text-decoration: none; }
.customer-logo { height: 28px; width: auto; display: block; }
.wordmark { font-family: var(--font-display); font-weight: 600; letter-spacing: .01em; }
.topbar-right { display: flex; align-items: center; gap: 10px; flex: 1 1 auto; justify-content: flex-end; }
#user-pill {
    color: var(--muted-hi);
    font-size: .85em;
    /* polish runde 4: gleiche Hoehe wie die Icon-Buttons in der
 Topbar (36px), damit der Pill optisch in einer Linie sitzt. */
    height: 36px;
    padding: 0 14px;
    border-radius: 999px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    /* b: jetzt klickbarer Button (Profil-Modal). */
    cursor: pointer;
    font-family: inherit;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    transition: border-color .12s, background .12s, color .12s;
}
#user-pill:hover {
    border-color: var(--c-primary-hi);
    color: var(--c-primary-hi);
}
#user-pill:focus-visible {
    outline: 2px solid var(--c-primary-hi);
    outline-offset: 2px;
}
#user-pill.role-admin       { color: var(--c-signal); border-color: var(--c-signal-dim); }
#user-pill.role-editor      { color: var(--c-primary-hi); border-color: var(--border-hi); }
#user-pill.role-contributor { color: var(--c-cyan); }
#user-pill.role-viewer      { color: var(--muted); }

/* User-Pill auf map.html ist jetzt ein
 quadratischer Avatar-Icon-Btn statt einer Username-Text-Pille. Damit
 hat der Button immer die gleiche Groesse wie die anderen Topbar-Icon-
 Btns (36x36), unabhaengig von Username-Laenge. Dashboard/Trash haben
 weiterhin die Text-Pille (kein .icon-btn), also bleiben deren Styles
 in der Regel oben unangetastet — die folgenden Overrides greifen nur
 auf #user-pill.icon-btn. */
#user-pill.icon-btn {
    /* JP-Fix : explizit 36x36 + padding:0 (Specificity-Override
 gegen den Default-`#user-pill { height:36px; padding:0 14px }`-
 Block oben). Vorher stand hier `height:auto`, was den Button auf
 die Hoehe des Avatar-Innenslots (26px) kollabieren liess. Mobile-
 Override (44x44) folgt im @media-(max-width:600px)-Block. */
    width: 36px;
    height: 36px;
    padding: 0;
    /* Ghost-Tint analog zu `.ghost` (Specificity-Hack: #user-pill ueber-
       schreibt sonst den Ghost-Background). Dark-Mode override unten. */
    background: rgba(0, 0, 0, 0.04);
    border-radius: var(--radius);
    overflow: hidden;
    line-height: 0;
    justify-content: center;
}
#user-pill.icon-btn:hover {
    background: rgba(0, 0, 0, 0.10);
}
[data-theme="dark"] #user-pill.icon-btn {
    background: rgba(255, 255, 255, 0.06);
}
[data-theme="dark"] #user-pill.icon-btn:hover {
    background: rgba(255, 255, 255, 0.12);
}
#user-pill.icon-btn .user-pill-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    overflow: hidden;
    background: var(--bg-card);
    flex: 0 0 auto;
}
#user-pill.icon-btn .user-pill-avatar > svg,
#user-pill.icon-btn .user-pill-avatar > img {
    width: 100%;
    height: 100%;
    display: block;
    object-fit: cover;
}

/* ---- Buttons ---- */
.primary, .ghost {
    border-radius: var(--radius);
    padding: 8px 14px;
    font-weight: 500;
    border: 1px solid transparent;
    transition: background .12s ease, border-color .12s ease, color .12s ease;
    text-align: center;
    text-decoration: none;
    display: inline-flex; align-items: center; justify-content: center; gap: 6px;
}
.primary {
    background: var(--c-primary);
    color: var(--c-light);
    border-color: var(--c-primary-dk);
}
.primary:hover { background: var(--c-primary-hi); }
.primary:disabled { background: var(--c-primary-dk); }
.ghost {
    /* "transparent" laesst .ghost-Buttons in
 vielen Modals identisch zur Karten-Card aussehen (--bg-card ist im
 Dark-Mode quasi transparent). Wir setzen einen dezenten Tint, der
 die Buttons gegen den Modal-Bg abhebt aber kein Brand-Akzent ist. */
    background: rgba(0, 0, 0, 0.04);
    color: var(--fg);
    border-color: var(--border);
}
.ghost:hover {
    background: rgba(0, 0, 0, 0.10);
    border-color: var(--border-hi);
}
[data-theme="dark"] .ghost {
    background: rgba(255, 255, 255, 0.06);
    border-color: rgba(255, 255, 255, 0.14);
}
[data-theme="dark"] .ghost:hover {
    background: rgba(255, 255, 255, 0.12);
    border-color: rgba(255, 255, 255, 0.24);
}
.icon-btn { padding: 6px; line-height: 0; }
.icon-btn .icon { display: block; }
/* Footer-Icon-Btns einheitlich 48x34 — gilt fuer alle
 modal-footer--compact (Layers-Modal + DB-Modal) damit Import, Bulk-
 Load, Bulk-Delete (und im DB-Modal auch Edit, Add, Export) optisch
 identisch ausgerichtet sind. Image- und SVG-Inhalte werden zentriert. */
.modal-footer--compact .icon-btn {
    width: 48px;
    height: 34px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.modal-footer--compact .icon-btn img,
.modal-footer--compact .icon-btn svg {
    display: block;
}

/* Theme toggle - Fix: beide Modi explizit, damit nicht im Dark-Mode
 * beide Icons sichtbar sind, wenn data-theme noch nicht gesetzt ist. */
.theme-toggle .icon-sun  { display: block; }
.theme-toggle .icon-moon { display: none; }
:root[data-theme="light"] .theme-toggle .icon-sun  { display: none; }
:root[data-theme="light"] .theme-toggle .icon-moon { display: block; }
:root[data-theme="dark"]  .theme-toggle .icon-sun  { display: block; }
:root[data-theme="dark"]  .theme-toggle .icon-moon { display: none; }

/* ---- Map shell layout ---- */
.page--map { overflow: hidden; }
.map-shell {
    position: relative;
    display: flex;
    height: calc(100vh - var(--topbar-h));
    min-height: 0;
}
.map-canvas {
    flex: 1 1 auto;
    min-width: 0;
    background: var(--map-surface);
}

/* ---- Sidebar (OneNote-Style) -------------------------------------- */
.sidebar {
    position: relative;
    flex: 0 0 var(--sidebar-w);
    width: var(--sidebar-w);
    display: flex;
    flex-direction: row;
    background: var(--bg-panel);
    border-right: 1px solid var(--border);
    /* laengere + weichere Transition (cubic-
 * bezier ease-out) damit das Expand/Collapse fluessig wirkt. JS
 * defert den schweren renderList-Call passend zur Animations-
 * dauer (siehe sidebar.js + features-panel.js). */
    transition: width .26s cubic-bezier(0.22, 0.61, 0.36, 1),
                flex-basis .26s cubic-bezier(0.22, 0.61, 0.36, 1);
    will-change: width, flex-basis;
    overflow: hidden;
    /* ueber Leaflet-Controls (z 1000), damit der Mobile-Overlay-Modus
       (siehe @media unten) die Karten-Controls korrekt verdeckt. */
    z-index: 1100;
}
.sidebar--collapsed {
    flex-basis: var(--sidebar-rail-w);
    width: var(--sidebar-rail-w);
}
.sidebar-rail {
    flex: 0 0 var(--sidebar-rail-w);
    width: var(--sidebar-rail-w);
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 8px 0;
    gap: 4px;
    border-right: 1px solid var(--border);
}
.sidebar:not(.sidebar--collapsed) .sidebar-rail { display: none; }
.sidebar-rail-toggle, .sidebar-rail-add {
    width: 36px; height: 36px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: var(--radius-sm);
    background: transparent; border: 1px solid transparent;
    color: var(--fg);
}
.sidebar-rail-toggle:hover, .sidebar-rail-add:hover {
    background: var(--bg-card); border-color: var(--border-hi);
}
.sidebar-rail-count {
    margin-top: auto;
    font-size: .75em;
    color: var(--muted);
    padding: 4px 0;
}
.sidebar-body {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
}
.sidebar--collapsed .sidebar-body { display: none; }

.sidebar-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 10px 12px;
    border-bottom: 1px solid var(--border);
}
.sidebar-title { font-size: .95rem; margin: 0; font-family: var(--font-display); }
.sidebar-head-actions { display: flex; gap: 4px; }

.sidebar-list {
    list-style: none;
    margin: 0; padding: 4px 0;
    flex: 1 1 auto;
    overflow-y: auto;
    overflow-x: hidden;
}
.sidebar-empty {
    margin: 16px 12px;
    color: var(--muted);
    font-size: .9rem;
    text-align: center;
    line-height: 1.5;
}
.sidebar-empty-plus {
    display: inline-flex;
    width: 22px; height: 22px;
    align-items: center; justify-content: center;
    border-radius: 6px;
    background: var(--bg-card);
    color: var(--c-primary-hi);
    vertical-align: -5px;
}

/* Layer-Row */
.layer-row {
    position: relative;
    display: grid;
    grid-template-columns: 14px 1fr auto auto;
    gap: 6px;
    align-items: center;
    padding: 6px 10px 6px 8px;
    border-left: 3px solid transparent;
    cursor: default;
}
.layer-row + .layer-row { border-top: 1px solid var(--border); }
.layer-row:hover { background: var(--bg-card); }
.layer-row--draw { border-left-color: var(--c-signal); background: var(--c-signal-dim); }
.layer-row--draft .layer-name-text { font-style: italic; }
.layer-row.is-flash { animation: flash-row .8s ease; }
@keyframes flash-row {
    0%   { background: var(--c-signal-dim); }
    100% { background: transparent; }
}

.layer-swatch {
    width: 12px; height: 12px;
    border-radius: 3px;
    background: var(--swatch, var(--c-primary));
    box-shadow: 0 0 0 1px rgba(0,0,0,0.25) inset;
}
.layer-name {
    text-align: left;
    background: transparent; border: 0; padding: 2px 0;
    color: var(--fg);
    font-size: .92rem;
    overflow: hidden;
    display: flex; align-items: center; gap: 6px;
    min-width: 0;
}
.layer-name-text {
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    flex: 1 1 auto;
}
.layer-name-edit {
    /* Inline-Rename-Input war im Dark-Mode
 weiß-auf-weiß. Ursache: das outerHTML-replace ersetzt den
 .layer-name-Button durch ein .layer-name-edit-Input, das aber
 (a) nicht im grid-area 'name' landete und (b) durch Browser-
 Default-Style ein weißes Hintergrund-Rendering bekam, das die
 var(--input-bg)-Regel nicht zuverlässig überschrieb. Fix:
 explizit grid-area + !important auf bg/color, damit der Dark-
 Theme-Wert sicher gewinnt. */
    grid-area: name;
    width: 100%;
    background: var(--input-bg) !important;
    color: var(--fg) !important;
    border: 1px solid var(--border-hi);
    border-radius: var(--radius-sm);
    padding: 2px 6px;
    font-size: .9rem;
}
.layer-badge {
    font-size: .7em;
    background: var(--c-warn);
    color: #1f1500;
    padding: 1px 6px;
    border-radius: 999px;
    font-weight: 600;
}
/* geaenderte Layer bekommen einen "Editiert"-
 Badge in amber statt einem alleinstehenden "*"-Marker. Selber Pill-
 Stil wie der Draft-Badge (var(--c-warn)), aber andere Hintergrund-
 Farbe damit Draft und Editiert visuell unterscheidbar bleiben. */
.layer-badge--dirty {
    background: var(--c-amber, #c98a00);
    color: #1f1500;
}
[data-theme="dark"] .layer-badge--dirty {
    background: #f0c270;
    color: #2a1f00;
}
/* Stats-Farbsystem app-weit.
 Jede Stat-Klasse hat einen leichten Pastell-Hintergrund + Border in der
 Farb-Familie. Der TEXT bleibt in der jeweiligen Mode-Schriftfarbe
 (var(--fg)) — keine farbigen Texte. Dark-Mode bekommt etwas mehr
 Background-Alpha damit der Effekt sichtbar bleibt.
 Gilt fuer popup-stat egal wo: Map-Popup, Feature-Modal, DB-Sidepanel,
 Layer-Aggregat. */
.popup-stat--vol {
    background: rgba(139, 92, 246, 0.14);
    border: 1px solid rgba(139, 92, 246, 0.45);
    color: var(--fg);
    font-weight: 600;
}
.popup-stat--cut {
    background: rgba(220, 80, 80, 0.14);
    border: 1px solid rgba(220, 80, 80, 0.45);
    color: var(--fg);
}
.popup-stat--fill {
    background: rgba(70, 170, 90, 0.14);
    border: 1px solid rgba(70, 170, 90, 0.45);
    color: var(--fg);
}
.popup-stat--net {
    background: rgba(70, 130, 200, 0.12);
    border: 1px solid rgba(70, 130, 200, 0.45);
    color: var(--fg);
    font-weight: 600;
}
.popup-stat--length {
    background: rgba(244, 114, 182, 0.14);
    border: 1px solid rgba(244, 114, 182, 0.45);
    color: var(--fg);
}
.popup-stat--area {
    background: rgba(16, 185, 129, 0.14);
    border: 1px solid rgba(16, 185, 129, 0.45);
    color: var(--fg);
}
.popup-stat--perim {
    background: rgba(255, 127, 80, 0.16);
    border: 1px solid rgba(255, 127, 80, 0.50);
    color: var(--fg);
}
.popup-stat--elev {
    background: rgba(245, 158, 11, 0.16);
    border: 1px solid rgba(245, 158, 11, 0.50);
    color: var(--fg);
}
/* GPS-Z-Chips (GPS-Z-Trennung 2026-06-12): direkt gemessene Hoehen
 leicht tuerkis abgesetzt, damit sie nicht mit der DSM-Hoehe (--elev)
 verwechselt werden. */
.popup-stat--gpsz {
    border-color: rgba(6, 130, 156, 0.55);
    color: var(--c-primary-hi, #06829c);
}
/* SuperAdmin: GPS-Hoehe im Popup klickbar (Edit). Button sieht aus wie
 * der Pill-Stat, mit dezentem Stift-Hinweis. */
.popup-stat--editable {
    cursor: pointer;
    font: inherit;
    line-height: inherit;
}
.popup-stat--editable::after { content: " \270E"; opacity: 0.7; }
.popup-stat--editable:hover {
    border-color: var(--c-primary, #007FB4);
    filter: brightness(1.06);
}

/* --- Fuelleffekte (2026-06-12, JP-Request) --------------------------- */
/* Breite Kachel im Feature-Farb-Picker: volle Zeile unter den
 Reinfarben, damit der Unterschied zu den Farb-Tiles sichtbar ist. */
.feature-fill-effect-btn {
    flex-basis: 100%;
    width: 100%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    margin-top: 6px;
    padding: 8px 10px;
    /* JP-Request: in beiden Designs deutlich vom Farb-Raster
     abgehoben — tuerkiser Verlauf + kraeftige Border + Hover-Lift. */
    border: 1.5px solid rgba(0, 127, 180, 0.55);
    border-radius: var(--radius-sm, 6px);
    background: linear-gradient(135deg,
        rgba(0, 127, 180, 0.16), rgba(0, 179, 104, 0.12));
    color: var(--c-primary-hi, #06829c);
    font-weight: 600;
    cursor: pointer;
    font-size: 0.88em;
    transition: border-color .15s, background .15s,
                box-shadow .15s, transform .12s;
}
.feature-fill-effect-btn:hover {
    border-color: var(--c-primary, #007FB4);
    background: linear-gradient(135deg,
        rgba(0, 127, 180, 0.28), rgba(0, 179, 104, 0.20));
    box-shadow: 0 2px 10px rgba(0, 127, 180, 0.30);
    transform: translateY(-1px);
}
.feature-fill-effect-btn:active { transform: translateY(0); }
[data-theme="light"] .feature-fill-effect-btn {
    background: linear-gradient(135deg,
        rgba(0, 127, 180, 0.10), rgba(0, 179, 104, 0.08));
    color: var(--c-primary, #007FB4);
}
[data-theme="light"] .feature-fill-effect-btn:hover {
    background: linear-gradient(135deg,
        rgba(0, 127, 180, 0.18), rgba(0, 179, 104, 0.14));
    box-shadow: 0 2px 10px rgba(0, 127, 180, 0.22);
}
.feature-fill-effect-btn.is-active {
    border-color: var(--c-primary);
    box-shadow: inset 0 0 0 1px rgba(0, 127, 180, 0.45);
}

/* 2026-06-26 (JP-Request): Fuelleffekt-Button halbiert, rechts daneben
 der Muster-Button. Beide teilen sich die Zeile mit Abstand dazwischen. */
.feature-fill-row {
    flex-basis: 100%;
    width: 100%;
    display: flex;
    gap: 8px;
    margin-top: 6px;
}
.feature-fill-effect-btn--half {
    flex: 1 1 0;
    width: auto;
    min-width: 0;
    margin-top: 0;        /* Abstand kommt jetzt vom .feature-fill-row */
}
/* Muster-Button: gleiche Form wie der Fuelleffekt-Button, eigener
 violett-getoenter Akzent zur optischen Trennung. */
.feature-pattern-btn {
    flex: 1 1 0;
    min-width: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    padding: 8px 10px;
    border: 1.5px solid rgba(124, 92, 255, 0.55);
    border-radius: var(--radius-sm, 6px);
    background: linear-gradient(135deg,
        rgba(124, 92, 255, 0.16), rgba(0, 127, 180, 0.10));
    color: var(--c-primary-hi, #6f5cff);
    font-weight: 600;
    cursor: pointer;
    font-size: 0.88em;
    transition: border-color .15s, background .15s, box-shadow .15s, transform .12s;
}
.feature-pattern-btn:hover {
    border-color: #7c5cff;
    background: linear-gradient(135deg,
        rgba(124, 92, 255, 0.28), rgba(0, 127, 180, 0.16));
    box-shadow: 0 2px 10px rgba(124, 92, 255, 0.30);
    transform: translateY(-1px);
}
.feature-pattern-btn:active { transform: translateY(0); }
.feature-pattern-btn.is-active {
    border-color: #7c5cff;
    box-shadow: inset 0 0 0 1px rgba(124, 92, 255, 0.45);
}
[data-theme="light"] .feature-pattern-btn {
    background: linear-gradient(135deg,
        rgba(124, 92, 255, 0.10), rgba(0, 127, 180, 0.06));
    color: #5a45d8;
}

/* --- Audioaufnahmen pro Feature (2026-06-26, JP-Request; Slot-Rework) */
.feature-audio-status {
    display: block;
    margin-top: 4px;
    font-size: 0.82em;
    color: var(--muted-hi);
}
/* 5 flache Slots in einer Reihe — wie die Bilder-Reihe, aber niedriger
 (40px hoch statt quadratisch). */
.audio-slots {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 6px;
    margin-top: 4px;
}
.audio-slot {
    position: relative;
    /* etwas hoeher als 40px, damit unter dem Avatar das Aufnahme-Datum
     Platz hat (2026-06-26). Leere/Record-Slots zentrieren das Mic. */
    height: 54px;
    border: 1px dashed var(--border);
    border-radius: var(--radius-sm, 6px);
    background: var(--input-bg);
    overflow: hidden;
    display: flex; align-items: center; justify-content: center;
}
.audio-slot.is-filled { border-style: solid; }
.audio-slot--recording {
    border-color: var(--c-error, #d7301f);
    border-style: solid;
}
.audio-slot--disabled { opacity: 0.45; }
.audio-slot--loading {
    grid-column: 1 / -1;
    height: auto;
    border: 0;
    background: transparent;
    color: var(--muted-hi);
}
/* Klick-Button fuellt den ganzen Slot. */
.audio-slot-btn {
    width: 100%; height: 100%;
    border: 0; background: transparent;
    display: flex; align-items: center; justify-content: center;
    cursor: pointer;
    color: var(--c-primary, #007FB4);
    padding: 0;
}
.audio-slot-btn:disabled { cursor: not-allowed; }
.audio-slot-btn:hover:not(:disabled) { background: var(--bg-card); }
.audio-slot-btn .audio-ico { fill: currentColor; }
/* Gefuellter Slot: Avatar oben, Datum darunter. */
.audio-slot-play {
    flex-direction: column;
    gap: 3px;
}
.audio-avatar {
    position: relative;
    width: 26px; height: 26px;
    flex: 0 0 auto;
}
.audio-avatar svg {
    width: 100%; height: 100%;
    display: block;
    border-radius: 50%;
}
.audio-play-badge {
    position: absolute;
    bottom: -3px; right: -3px;
    width: 14px; height: 14px;
    border-radius: 50%;
    background: var(--c-primary, #007FB4);
    color: #fff;
    display: flex; align-items: center; justify-content: center;
    box-shadow: 0 0 0 1.5px var(--input-bg);
}
.audio-play-badge svg { width: 9px; height: 9px; }
.audio-slot-play.is-playing .audio-play-badge {
    background: var(--c-error, #d7301f);
}
.audio-date {
    font-size: 0.6em;
    line-height: 1.1;
    color: var(--muted-hi);
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.audio-slot-btn.is-recording {
    color: var(--c-error, #d7301f);
    animation: geolyser-audio-pulse 1s ease-in-out infinite;
}
@keyframes geolyser-audio-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.4; }
}
/* Mikrofon-Icon (schwarzes SVG via <img>) — im Dark Mode hell faerben. */
.audio-ico-mic { display: block; opacity: 0.85; }
[data-theme="dark"] .audio-ico-mic { filter: invert(1); }
/* Kleines rotes Loesch-X oben rechts (wie bei den Bildern). */
.audio-slot-remove {
    position: absolute;
    top: 2px; right: 2px;
    width: 18px; height: 18px;
    border-radius: 999px;
    border: 0;
    background: var(--c-error, #d7301f);
    color: #fff;
    cursor: pointer;
    line-height: 1;
    font-size: 0.8em;
    padding: 0;
    display: flex; align-items: center; justify-content: center;
}
.audio-slot-remove:hover { filter: brightness(1.12); }

/* --- Muster-Generator-Modal (2026-06-26, JP-Request) --------------- */
.pattern-body { display: flex; flex-direction: column; gap: 12px; }
.pattern-preview-wrap {
    border: 1px solid var(--border);
    border-radius: var(--radius-sm, 6px);
    overflow: hidden;
    line-height: 0;
}
.pattern-preview-canvas {
    width: 100%;
    height: 120px;
    display: block;
}
.pattern-field { display: flex; flex-direction: column; gap: 6px; }
.pattern-field .field-label { font-weight: 600; font-size: 0.86em; }
.pattern-bg-row { display: flex; align-items: center; gap: 12px; }
.pattern-check { display: inline-flex; align-items: center; gap: 6px; }
.pattern-bg-row input[type="color"],
.pattern-line-row input[type="color"] {
    width: 38px; height: 30px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm, 4px);
    background: transparent;
    cursor: pointer;
    padding: 0;
}
.pattern-lines { display: flex; flex-direction: column; gap: 6px; }
.pattern-line-row {
    display: flex;
    align-items: flex-end;
    gap: 8px;
    flex-wrap: wrap;
    padding: 6px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm, 6px);
    /* Hellblauer Zeilen-Hintergrund (JP); im Dark Mode dunkel. */
    background: #E3ECF4;
}
[data-theme="dark"] .pattern-line-row {
    background: #272D31;
}
/* Eingabefelder im Muster-Modal: Name-Feld + die Mini-Zahlenfelder
 * bekommen den App-Input-Farbton (hell #F0F3F6 / dunkel #0D1214) sowie
 * denselben Rahmen + die gleiche Abrundung + den gleichen Focus-Ring wie
 * die uebrigen App-Inputs (.field input). */
.pattern-save-row input,
.pattern-mini input {
    background: #F0F3F6;
    color: var(--fg);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    box-sizing: border-box;
}
.pattern-save-row input:focus,
.pattern-mini input:focus {
    outline: none;
    border-color: var(--border-hi);
    box-shadow: 0 0 0 3px rgba(0, 127, 180, 0.18);
}
[data-theme="dark"] .pattern-save-row input,
[data-theme="dark"] .pattern-mini input {
    background: #0D1214;
}
.pattern-mini {
    display: flex;
    flex-direction: column;
    font-size: 0.72em;
    color: var(--muted-hi);
    gap: 2px;
}
.pattern-mini input {
    width: 58px;
    padding: 4px 6px;
}
.pattern-line-del {
    margin-left: auto;
    width: 26px; height: 26px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm, 6px);
    background: var(--bg-card);
    color: var(--c-error, #d7301f);
    cursor: pointer;
    font-size: 16px; line-height: 1;
}
.pattern-line-del:hover {
    background: var(--c-error, #d7301f);
    color: #fff; border-color: var(--c-error, #d7301f);
}
.pattern-add-line {
    align-self: flex-start;
    font-size: 0.82em;
    padding: 4px 10px;
}
.pattern-swatches {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.pattern-swatch-wrap { position: relative; }
.pattern-swatch {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    padding: 4px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm, 6px);
    background: var(--bg-card);
    cursor: pointer;
    font-size: 0.72em;
    color: var(--muted-hi);
    width: 78px;
}
.pattern-swatch:hover { border-color: var(--c-primary, #007FB4); }
.pattern-swatch img {
    width: 100%;
    height: 38px;
    object-fit: cover;
    border-radius: 3px;
    background:
        repeating-conic-gradient(#e9edf1 0% 25%, #cdd5dd 0% 50%) 0 / 12px 12px;
}
.pattern-saved-del {
    position: absolute;
    top: -6px; right: -6px;
    width: 20px; height: 20px;
    border-radius: 50%;
    border: 1px solid var(--border);
    background: var(--bg-card);
    color: var(--c-error, #d7301f);
    cursor: pointer;
    font-size: 13px; line-height: 1;
}
.pattern-save-row { display: flex; gap: 8px; }
.pattern-save-row input { flex: 1 1 auto; padding: 8px 10px; }
.pattern-footer { display: flex; justify-content: space-between; gap: 8px; }
/* Quadratische 40x40-Icon-Buttons im Muster-Modal: Footer
 * (Speichern-Checkmark + Kein-Muster-clear) UND der Speichern-Button
 * in der Eigene-Muster-Zeile (Disk-Icon). */
.pattern-icon-btn {
    width: 40px;
    height: 40px;
    min-width: 40px;
    min-height: 40px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
}
.pattern-icon-btn img,
.pattern-icon-btn svg { display: block; }
/* Fuelleffekt-Modal: Apply-Button (Checkmark) ebenfalls quadratisch 40x40.
 * Hoehere Spezifitaet (.filleffect-save-btn.filleffect-apply-btn) als die
 * Basis-Regel .filleffect-save-btn { padding:8px 20px }, damit die 40x40
 * tatsaechlich greifen. */
.filleffect-save-btn.filleffect-apply-btn {
    width: 40px;
    height: 40px;
    min-width: 40px;
    padding: 0;
}
/* Fuelleffekt-Footer: Clear-Button links, Apply (Checkmark) rechts —
 * gleiche Anordnung wie der Muster-Modal-Footer. */
.filleffect-footer {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 8px;
}
/* clear-Icon (schwarze Linien) auf dem amber Button in beiden Themes
 * sichtbar halten. */
.pattern-clear-icon { width: 18px; height: 18px; }
[data-theme="dark"] .pattern-clear-icon { filter: invert(1); }
/* Speichern-Icon-Button (Fuelleffekt-Dialog + Setup-Fenster). */
.filleffect-save-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 8px 20px;
}
/* Setup-Fenster: ruhiges, einheitliches Spacing (JP: "gequetscht"). */
.filleffect-setup .filleffect-field { margin: 0 0 14px; display: block; }
.filleffect-setup .filleffect-field .field-label {
    display: block;
    margin-bottom: 6px;
    white-space: nowrap;
}
.filleffect-row {
    display: flex;
    align-items: flex-start;
    gap: 18px;
    flex-wrap: wrap;
    margin-bottom: 14px;
}
.filleffect-row .filleffect-field { margin: 0; }
/* R6 (JP): alle Eingabefelder im Setup einheitlich gross + gleiche
 Hintergrundfarbe wie der Rest der App (hell #F0F3F6 / dunkel #0D1214). */
.filleffect-setup input[type="number"],
.filleffect-setup select {
    width: 150px;
    height: 36px;
    box-sizing: border-box;
    padding: 6px 10px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm, 6px);
    background: var(--input-bg, #0d1214);
    color: var(--fg);
    font-size: 0.92em;
}
[data-theme="light"] .filleffect-setup input[type="number"],
[data-theme="light"] .filleffect-setup select {
    background: #f0f3f6;
}
.filleffect-setup input[type="number"]:focus,
.filleffect-setup select:focus {
    outline: none;
    border-color: var(--c-primary, #007FB4);
}
/* Feld nur fuer eine Checkbox (Fett / Schattierung) — Label-Hoehe
 gleich wie die Eingabefelder daneben, damit die Reihe sauber sitzt. */
.filleffect-field--check .filleffect-checkline {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    height: 36px;
    cursor: pointer;
    user-select: none;
}
.filleffect-field--check input[type="checkbox"] { margin: 0; }
.filleffect-check {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    cursor: pointer;
    padding-bottom: 6px;
    user-select: none;
}
.filleffect-setup > .filleffect-check { margin: 0 0 14px; padding-bottom: 0; }
/* Farb-Swatches: abgerundete Quadrate wie die uebrigen Farb-Picker
 der App (JP-Request, vorher Kreise). */
.filleffect-swatches {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.filleffect-swatch {
    width: 26px; height: 26px;
    border-radius: 6px;
    border: 2px solid var(--border);
    background: var(--sw);
    cursor: pointer;
    transition: transform .1s, box-shadow .15s, border-color .15s;
}
.filleffect-swatch:hover { transform: scale(1.1); }
.filleffect-swatch.is-active {
    border-color: var(--c-primary, #007FB4);
    box-shadow: 0 0 0 2px rgba(0, 127, 180, 0.35);
}
/* Verlauf-Swatch: Terrain-Farbskala als Mini-Gradient. */
.filleffect-swatch--gradient {
    background: linear-gradient(135deg,
        rgb(44,127,184) 0%, rgb(127,205,187) 33%,
        rgb(237,248,177) 66%, rgb(215,48,31) 100%);
}
/* Vorschau-Bereiche der Setup-Fenster. */
.filleffect-preview {
    margin-top: 2px;
    min-height: 110px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm, 6px);
    background: rgba(127, 127, 127, 0.06);
    overflow: hidden;
}
.filleffect-preview-img,
.filleffect-preview-svg {
    display: block;
    max-width: 100%;
    max-height: 280px;
    width: auto;
}
/* Gelaende-Vorschau bewusst flacher, damit das Fenster ohne
 Scrollbalken auskommt. */
.filleffect-preview--terrain .filleffect-preview-img { max-height: 200px; }
/* Dual-Slider im Setup: Platz fuer die Wert-Labels unter den Handles
 und den Reset-Knopf rechts — sonst erzeugt der absolute Overflow eine
 dauerhafte Scrollbar im Modal-Body. */
.filleffect-setup .dsm-legend-slider {
    margin: 10px 34px 34px 8px;
}
.filleffect-setup { overflow-x: hidden; }
/* Gefaelle-Skalen-Auswahl. */
.filleffect-slope-choices {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.filleffect-slope-choice {
    padding: 6px 14px;
    border: 1.5px solid var(--border);
    border-radius: var(--radius-sm, 6px);
    background: var(--bg-page);
    color: var(--fg);
    cursor: pointer;
    font-size: 0.9em;
    transition: border-color .15s, background .15s;
}
.filleffect-slope-choice:hover { border-color: var(--c-primary-hi); }
.filleffect-slope-choice.is-active {
    border-color: var(--c-primary, #007FB4);
    background: rgba(0, 127, 180, 0.14);
    font-weight: 600;
}
.filleffect-preview-svg { width: 100%; height: auto; }
.filleffect-info { margin: 8px 0 0; }
.filleffect-source { width: 100%; }
/* Zusammenfassung im Haupt-Dialog: Farb-Chip + Mini-Vorschau. */
.filleffect-summary {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    min-height: 28px;
}
.filleffect-chip {
    display: inline-block;
    width: 18px; height: 18px;
    border-radius: 5px;
    border: 1.5px solid var(--border);
    background: var(--sw);
    vertical-align: middle;
}
.filleffect-mini {
    display: inline-block;
    border: 1px solid var(--border);
    border-radius: 5px;
    background: rgba(127, 127, 127, 0.10);
    vertical-align: middle;
}
/* Hoehenlinien-Label: dunkler Halo fuer helle Linienfarben. */
.geolyser-contour-label--dark-halo {
    text-shadow:
        -1px -1px 0 #333, 1px -1px 0 #333,
        -1px 1px 0 #333, 1px 1px 0 #333;
}
/* Typ-Kacheln im Fuelleffekt-Dialog. */
.filleffect-types {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 8px;
    margin: 10px 0 14px;
}
.filleffect-type {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 10px;
    border: 1.5px solid var(--border);
    border-radius: var(--radius-sm, 6px);
    background: var(--bg-page);
    color: var(--fg);
    cursor: pointer;
    font-size: 0.9em;
}
.filleffect-type:hover { border-color: var(--c-primary-hi); }
.filleffect-type.is-active {
    border-color: var(--c-primary);
    background: rgba(0, 127, 180, 0.10);
}
/* Hoehenlinien-Beschriftung auf der Karte: kleiner Text mit
 weissem Halo, nicht klickbar. */
.geolyser-contour-label {
    font-size: 10px;
    font-weight: 700;
    color: #5d3a10;
    text-shadow:
        -1px -1px 0 #fff, 1px -1px 0 #fff,
        -1px 1px 0 #fff, 1px 1px 0 #fff;
    white-space: nowrap;
    pointer-events: none;
    transform: translate(-50%, -50%);
    /* JP-Fix: Labels lagen je nach DOM-Reihenfolge HINTER dem
     SVG-Vektor-Container des Panes — explizit drueber heben. */
    z-index: 600 !important;
}
.geolyser-fill-overlay { pointer-events: none; }
/* Farbverlauf-Picker (R5): Fuelleffekt-Setups + DSM-Modal-Legenden. */
.filleffect-swatch--wide { width: 44px; }
.filleffect-row--shade { align-items: flex-start; }
/* R6.2 (JP): Schriftgroesse+Fett-Gruppe flowt in der Beschriftungs-
 Zeile (kein eigener Block). */
.filleffect-optgroup {
    display: contents;
}
/* Author-Regel display:contents wuerde sonst das UA [hidden]{display:none}
 ueberstimmen — Optgroup liesse sich nicht ausblenden. */
.filleffect-optgroup[hidden] {
    display: none;
}
/* Schatten-Eingaben etwas kuerzer, damit Staerke + Laenge sauber
 neben die Schattierungs-Checkbox passen. */
.filleffect-row--shade select,
.filleffect-row--shade input[type="number"] { width: 118px; }
.dsm-ramp-picker {
    display: flex;
    flex-wrap: wrap;
    gap: 7px;
    /* R6.2 (JP): mehr Luft zwischen Picker, Slider + Hint im DSM-
     Modal — war zu gequetscht. */
    margin: 14px 0 12px;
}
.dsm-ramp-swatch {
    width: 40px; height: 18px;
    border-radius: 5px;
    border: 2px solid var(--border);
    cursor: pointer;
    transition: transform .1s, box-shadow .15s, border-color .15s;
}
.dsm-ramp-swatch:hover { transform: scale(1.08); }
.dsm-ramp-swatch.is-active {
    border-color: var(--c-primary, #007FB4);
    box-shadow: 0 0 0 2px rgba(0, 127, 180, 0.35);
}
.dsm-slope-ramp-bar {
    height: 12px;
    border-radius: 3px;
    border: 1px solid var(--border);
    margin: 4px 24px 2px;
}
.dsm-slope-ramp-labels {
    display: flex;
    justify-content: space-between;
    margin: 0 24px;
    font-size: 0.78em;
    opacity: 0.75;
}

/* Kreis-Radius-Chip — gleicher Stil
 wie Area (gruen), leicht blaustichig um ihn visuell zu unterscheiden. */
.popup-stat--radius {
    background: rgba(14, 165, 233, 0.14);
    border: 1px solid rgba(14, 165, 233, 0.45);
    color: var(--fg);
}
[data-theme="dark"] .popup-stat--vol    { background: rgba(139, 92, 246, 0.22); }
[data-theme="dark"] .popup-stat--cut    { background: rgba(220, 80, 80, 0.22); }
[data-theme="dark"] .popup-stat--fill   { background: rgba(70, 170, 90, 0.22); }
[data-theme="dark"] .popup-stat--net    { background: rgba(70, 130, 200, 0.22); }
[data-theme="dark"] .popup-stat--length { background: rgba(244, 114, 182, 0.22); }
[data-theme="dark"] .popup-stat--area   { background: rgba(16, 185, 129, 0.22); }
[data-theme="dark"] .popup-stat--perim  { background: rgba(255, 127, 80, 0.24); }
[data-theme="dark"] .popup-stat--elev   { background: rgba(245, 158, 11, 0.24); }
[data-theme="dark"] .popup-stat--radius { background: rgba(14, 165, 233, 0.22); }
/* Auch im Layer-Aggregat (Sidepanel-Expand) die farbigen Backgrounds
   verwenden — overrided das neutrale bg-card-Default. */
.layer-features-aggregate--rich .popup-stat--vol    { background: rgba(139, 92, 246, 0.14); border-color: rgba(139, 92, 246, 0.45); color: var(--fg); font-weight: 600; }
.layer-features-aggregate--rich .popup-stat--cut    { background: rgba(220, 80, 80, 0.14); border-color: rgba(220, 80, 80, 0.45); color: var(--fg); }
.layer-features-aggregate--rich .popup-stat--fill   { background: rgba(70, 170, 90, 0.14); border-color: rgba(70, 170, 90, 0.45); color: var(--fg); }
.layer-features-aggregate--rich .popup-stat--net    { background: rgba(70, 130, 200, 0.12); border-color: rgba(70, 130, 200, 0.45); color: var(--fg); font-weight: 600; }
.layer-features-aggregate--rich .popup-stat--length { background: rgba(244, 114, 182, 0.14); border-color: rgba(244, 114, 182, 0.45); color: var(--fg); }
.layer-features-aggregate--rich .popup-stat--area   { background: rgba(16, 185, 129, 0.14); border-color: rgba(16, 185, 129, 0.45); color: var(--fg); }
.layer-features-aggregate--rich .popup-stat--perim  { background: rgba(255, 127, 80, 0.16); border-color: rgba(255, 127, 80, 0.50); color: var(--fg); }
.layer-features-aggregate--rich .popup-stat--elev   { background: rgba(245, 158, 11, 0.16); border-color: rgba(245, 158, 11, 0.50); color: var(--fg); }
[data-theme="dark"] .layer-features-aggregate--rich .popup-stat--vol    { background: rgba(139, 92, 246, 0.22); }
[data-theme="dark"] .layer-features-aggregate--rich .popup-stat--cut    { background: rgba(220, 80, 80, 0.22); }
[data-theme="dark"] .layer-features-aggregate--rich .popup-stat--fill   { background: rgba(70, 170, 90, 0.22); }
[data-theme="dark"] .layer-features-aggregate--rich .popup-stat--net    { background: rgba(70, 130, 200, 0.22); }
[data-theme="dark"] .layer-features-aggregate--rich .popup-stat--length { background: rgba(244, 114, 182, 0.22); }
[data-theme="dark"] .layer-features-aggregate--rich .popup-stat--area   { background: rgba(16, 185, 129, 0.22); }
[data-theme="dark"] .layer-features-aggregate--rich .popup-stat--perim  { background: rgba(255, 127, 80, 0.24); }
[data-theme="dark"] .layer-features-aggregate--rich .popup-stat--elev   { background: rgba(245, 158, 11, 0.24); }
.popup-stat.has-vol-tooltip {
    position: relative;
    cursor: help;
}
.popup-stat.has-vol-tooltip > .vol-chip-tooltip {
    display: none;
    position: absolute;
    bottom: calc(100% + 6px);
    left: 0;
    z-index: 1300;
    background: var(--bg-card, #fff);
    color: var(--fg);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 8px 10px;
    box-shadow: 0 6px 18px rgba(0,0,0,0.20);
    width: 240px;
    font-size: 0.82em;
    line-height: 1.45;
    white-space: normal;
}
.popup-stat.has-vol-tooltip:hover > .vol-chip-tooltip,
.popup-stat.has-vol-tooltip:focus > .vol-chip-tooltip,
.popup-stat.has-vol-tooltip:focus-within > .vol-chip-tooltip {
    display: block;
}
.popup-stat.has-vol-tooltip .vol-tooltip-svg {
    display: block;
    margin-top: 6px;
    width: 220px;
    height: auto;
    border-radius: 4px;
}
[data-theme="dark"] .popup-stat.has-vol-tooltip > .vol-chip-tooltip {
    background: #1f2024;
    color: #eee;
    border-color: rgba(255,255,255,0.18);
}

/* Sidebar-Footer. Reine Presence-Zeile, KEIN Undo mehr.
 Hintergrund + Borders transparent, soll sich nicht von der Sidebar
 abheben. Label "Online:" links, dann Avatare. Empty-Hint zeigt ein
 Incognito-Icon in coral. */
.sidebar-foot {
    margin-top: auto;
    padding: 6px 12px 10px;
    border-top: 0;
    background: transparent;
    display: flex;
    flex-direction: column;
    gap: 6px;
    flex: 0 0 auto;
}
.sidebar-foot-row {
    display: flex;
    align-items: center;
    gap: 6px;
    min-height: 30px;
}
.sidebar-foot-row--presence {
    flex-wrap: wrap;
    align-items: center;
}
.sidebar-presence-label {
    font-size: 0.78em;
    color: var(--muted-hi);
    margin-right: 4px;
    flex: 0 0 auto;
}
.sidebar-presence-list {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    align-items: center;
    flex: 1 1 auto;
    min-width: 0;
}
.presence-empty-hint--incognito {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: 999px;
    color: #ff7f7f;            /* coral */
    background: rgba(255, 127, 80, 0.12);
    border: 1px solid rgba(255, 127, 80, 0.45);
    box-shadow: 0 0 0 0 rgba(255, 127, 80, 0.4);
    animation: presence-empty-pulse 2.4s ease-in-out infinite;
}
@keyframes presence-empty-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(255, 127, 80, 0.35); }
    50%      { box-shadow: 0 0 0 5px rgba(255, 127, 80, 0); }
}
[data-role="sidebar-presence-host"]:empty::before {
    content: "—";
    color: var(--muted);
    font-size: 0.78em;
    opacity: 0.5;
}

/* Layer-Aggregat-Anzeige unter der ausgeklappten
 Features-Liste. Zeigt Σ Flaeche / Σ Laenge / Σ Umfang. */
.layer-features-aggregate {
    padding: 4px 12px 6px;
    margin: -2px 0 6px;
    color: var(--muted-hi);
    font-size: 0.78em;
    font-style: italic;
    border-bottom: 1px dotted var(--border);
}
/* Rich-Aggregate als Chip-Reihe statt Plain-String. */
.layer-features-aggregate--rich {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    font-style: normal;
}
.layer-features-aggregate--rich .popup-stat {
    background: var(--bg-card);
    color: var(--muted-hi);
    border: 1px solid var(--border);
    padding: 2px 6px;
    border-radius: 999px;
    font-size: 1em;
}

/* Feature-Checkbox in der Layer-Liste + ausgegraute
 Items wenn Feature unchecked. */
.layer-feature-checkbox {
    margin: 0 4px 0 0;
    cursor: pointer;
    flex-shrink: 0;
}
.layer-feature.is-off .layer-feature-name {
    text-decoration: line-through;
    opacity: 0.5;
}

/* Geteilt-Badge (Layer von anderem User per Invitation). */
.layer-badge--shared {
    background: #6c8cff;
    color: #fff;
}
[data-theme="dark"] .layer-badge--shared {
    background: #8da5ff;
    color: #1a1f3a;
}
.layer-meta {
    color: var(--muted);
    font-size: .75em;
    min-width: 1.5em;
    text-align: right;
}
.layer-toggles {
    display: flex; gap: 2px;
    align-items: center;
}
.layer-toggle {
    width: 26px; height: 26px;
    display: inline-flex; align-items: center; justify-content: center;
    background: transparent; border: 1px solid transparent;
    border-radius: var(--radius-sm);
    color: var(--muted);
}
.layer-toggle:hover { color: var(--fg); background: var(--bg-card); border-color: var(--border); }
.layer-toggle.is-on { color: var(--c-primary-hi); background: rgba(0, 160, 210, 0.10); border-color: var(--border-hi); }
.layer-row--draw .layer-toggle[data-action="toggle-draw"].is-on {
    color: var(--c-signal); background: var(--c-signal-dim); border-color: var(--c-signal-dim);
}

/* Layer-Menu (dropdown) */
.layer-menu {
    grid-column: 1 / -1;
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 6px;
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    margin: 4px 0 6px 0;
    box-shadow: var(--shadow-card);
}
.layer-menu hr {
    border: 0; border-top: 1px solid var(--border);
    margin: 4px 0;
}
.layer-menu button[role="menuitem"] {
    display: flex; align-items: center; gap: 8px;
    padding: 6px 8px;
    background: transparent; border: 0; color: var(--fg);
    border-radius: var(--radius-sm);
    text-align: left;
    font-size: .9rem;
}
.layer-menu button[role="menuitem"]:hover { background: var(--bg-card); }
.layer-menu button[role="menuitem"].is-destructive { color: var(--c-error); }
.layer-menu button[role="menuitem"].is-destructive:hover { background: var(--c-error-bg); }
/* Disabled menu item: visible but greyed and unclickable. */
.layer-menu button[role="menuitem"]:disabled,
.layer-menu button[role="menuitem"].is-disabled {
    opacity: 0.42;
    cursor: not-allowed;
    pointer-events: none;
}
.layer-menu-colors {
    display: flex; flex-wrap: wrap; gap: 4px;
    padding: 4px 6px 6px 6px;
}
.layer-color-pick {
    width: 18px; height: 18px;
    border-radius: 4px;
    background: var(--swatch, var(--c-primary));
    border: 2px solid transparent;
    box-shadow: 0 0 0 1px rgba(0,0,0,0.20) inset;
}
.layer-color-pick.is-on { border-color: var(--fg); }
.layer-color-pick:hover { transform: scale(1.06); }

/* ---- Features-Panel (rechte Sidebar) -------------------------------- */
/* Spiegelbild zur linken Sidebar - dieselben Tokens (--sidebar-w,
   --sidebar-rail-w), Border auf der LINKEN statt rechten Kante. */
.features-panel {
    position: relative;
    flex: 0 0 var(--sidebar-w);
    width: var(--sidebar-w);
    display: flex;
    flex-direction: row-reverse;
    background: var(--bg-panel);
    border-left: 1px solid var(--border);
    /* smoothere Expand/Collapse-Transition,
 * gleiche Werte wie .sidebar. JS-Seite (features-panel.js expand)
 * defert den teuren renderList nach Transition-Ende. */
    transition: width .26s cubic-bezier(0.22, 0.61, 0.36, 1),
                flex-basis .26s cubic-bezier(0.22, 0.61, 0.36, 1);
    will-change: width, flex-basis;
    overflow: hidden;
    z-index: 1100;
}
.features-panel--collapsed {
    flex-basis: var(--sidebar-rail-w);
    width: var(--sidebar-rail-w);
}
.features-panel-rail {
    flex: 0 0 var(--sidebar-rail-w);
    width: var(--sidebar-rail-w);
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 8px 0;
    gap: 4px;
    border-left: 1px solid var(--border);
}
.features-panel:not(.features-panel--collapsed) .features-panel-rail { display: none; }
.features-panel-rail-toggle, .features-panel-rail-db {
    width: 36px; height: 36px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: var(--radius-sm);
    background: transparent; border: 1px solid transparent;
    color: var(--fg);
}
.features-panel-rail-toggle:hover, .features-panel-rail-db:hover {
    background: var(--bg-card); border-color: var(--border-hi);
}
.features-panel-rail-count {
    margin-top: auto;
    font-size: .75em;
    color: var(--muted);
    padding: 4px 0;
}
.features-panel-body {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
}
.features-panel--collapsed .features-panel-body { display: none; }

.features-panel-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 10px 12px;
    border-bottom: 1px solid var(--border);
}
.features-panel-title { font-size: .95rem; margin: 0; font-family: var(--font-display); }
.features-panel-collapse {
    width: 28px; height: 28px;
    display: inline-flex; align-items: center; justify-content: center;
    background: transparent; border: 1px solid transparent;
    border-radius: var(--radius-sm);
    color: var(--fg);
}
.features-panel-collapse:hover {
    background: var(--bg-card); border-color: var(--border-hi);
}

.features-panel-search {
    position: relative;
    margin: 8px 10px;
}
.features-panel-search-icon {
    position: absolute; top: 50%; left: 8px;
    transform: translateY(-50%);
    color: var(--muted);
    pointer-events: none;
    line-height: 0;
}
.features-panel-search-input {
    width: 100%;
    background: var(--input-bg);
    color: var(--fg);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 6px 28px 6px 30px;
    font-size: .9rem;
}
.features-panel-search-input:focus {
    border-color: var(--border-hi); outline: none;
}
.features-panel-search-clear {
    position: absolute; top: 50%; right: 4px;
    transform: translateY(-50%);
    width: 22px; height: 22px;
    display: inline-flex; align-items: center; justify-content: center;
    background: transparent; border: 0;
    color: var(--muted);
    border-radius: 999px;
}
.features-panel-search-clear:hover { color: var(--fg); background: var(--bg-card); }

.features-panel-filterbar {
    position: relative;
    display: flex; flex-wrap: wrap; gap: 4px;
    padding: 0 10px 8px 10px;
    border-bottom: 1px solid var(--border);
}
.features-panel-chip {
    display: inline-flex; align-items: center; gap: 4px;
    padding: 3px 8px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: 999px;
    color: var(--muted-hi);
    font-size: .8rem;
}
.features-panel-chip:hover { color: var(--fg); border-color: var(--border-hi); }
.features-panel-chip.is-active {
    color: var(--c-primary-hi);
    border-color: var(--border-hi);
    background: rgba(0, 160, 210, 0.10);
}
.features-panel-popover {
    position: absolute;
    top: calc(100% - 4px);
    left: 10px; right: 10px;
    z-index: 5;
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-card);
    max-height: 280px;
    display: flex; flex-direction: column;
    overflow: hidden;
}
/* Autocomplete-Search-Box ueber der Tristate-Liste. */
.features-panel-popover-search {
    flex: 0 0 auto;
    padding: 6px 8px;
    border-bottom: 1px solid var(--border);
    background: var(--bg-card);
}
.features-panel-popover-search input {
    width: 100%;
    padding: 5px 8px;
    border: 1px solid var(--border);
    border-radius: 4px;
    background: var(--bg, #fff);
    color: var(--text);
    font-size: .85rem;
    box-sizing: border-box;
}
.features-panel-popover-search input:focus {
    outline: none;
    border-color: var(--c-primary);
}
.features-panel-popover-list {
    list-style: none; margin: 0; padding: 4px 0;
    overflow-y: auto;
    flex: 1 1 auto;
}
.features-panel-popover-row {
    display: flex; align-items: center; gap: 8px;
    padding: 6px 10px;
    cursor: pointer;
    font-size: .85rem;
}
.features-panel-popover-row:hover { background: var(--bg-card); }
.features-panel-popover-row.is-highlight {
    background: rgba(0, 160, 210, 0.10);
    box-shadow: inset 3px 0 0 var(--c-primary, #007FB4);
}
.features-panel-popover-row input { accent-color: var(--c-primary); }
.features-panel-popover-empty {
    padding: 10px; color: var(--muted); font-size: .85rem; text-align: center;
}
.features-panel-popover-foot {
    border-top: 1px solid var(--border);
    padding: 4px;
    display: flex; justify-content: flex-end;
}
.ghost-btn {
    background: transparent; border: 0;
    color: var(--muted-hi);
    padding: 4px 8px;
    border-radius: var(--radius-sm);
    font-size: .8rem;
}
.ghost-btn:hover { color: var(--fg); background: var(--bg-card); }

.features-panel-status {
    padding: 6px 12px;
    font-size: .75em;
    color: var(--muted);
    border-bottom: 1px solid var(--border);
}
.features-panel-list {
    list-style: none;
    margin: 0; padding: 0;
    flex: 1 1 auto;
    overflow-y: auto;
    overflow-x: hidden;
}
/* Lazy-Hint-Variante — gleiche Optik, leicht
 * italic + etwas mehr padding damit es als bewusster Hinweis lesbar
 * ist und nicht als "leeres Filter-Ergebnis" verwechselt wird. */
.features-panel-empty--lazy {
    font-style: italic;
    line-height: 1.5;
    padding: 24px 16px !important;
}
.features-panel-empty {
    padding: 16px 12px;
    color: var(--muted);
    font-size: .85rem;
    text-align: center;
}
.features-panel-item {
    display: grid;
    grid-template-columns: 10px 1fr;
    gap: 8px;
    padding: 8px 12px;
    border-bottom: 1px solid var(--border);
    cursor: pointer;
    align-items: start;
}
.features-panel-item:hover { background: var(--bg-card); }
.features-panel-item.is-active {
    background: rgba(0, 160, 210, 0.10);
    border-left: 3px solid var(--c-primary-hi);
    padding-left: 9px;
}
.features-panel-dot {
    width: 10px; height: 10px;
    border-radius: 50%;
    margin-top: 5px;
    box-shadow: 0 0 0 1px rgba(0,0,0,0.30) inset;
}
.features-panel-item-body { min-width: 0; }
.features-panel-name {
    font-size: .92rem; color: var(--fg);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.features-panel-meta {
    margin-top: 2px;
    display: flex; flex-wrap: wrap; gap: 6px;
    font-size: .72em; color: var(--muted);
}
.features-panel-cat { color: var(--muted-hi); }
.features-panel-layer::before { content: "@ "; opacity: .6; }
.features-panel-tags {
    margin-top: 4px;
    display: flex; flex-wrap: wrap; gap: 3px;
}
.features-panel-tag, .features-panel-tag-more {
    font-size: .7em;
    background: var(--bg-card);
    border: 1px solid var(--border);
    color: var(--muted-hi);
    padding: 1px 5px;
    border-radius: 999px;
}
.features-panel-tag-more { color: var(--muted); font-style: italic; }

/* Mobile-Overlay-Modus */
@media (max-width: 700px) {
    .sidebar:not(.sidebar--collapsed) {
        position: absolute;
        top: 0; bottom: 0; left: 0;
        width: min(86vw, 340px);
        flex-basis: min(86vw, 340px);
        box-shadow: 8px 0 32px rgba(0,0,0,0.35);
    }
    .sidebar--collapsed .sidebar-rail { background: var(--bg-elevated); }

    .features-panel:not(.features-panel--collapsed) {
        position: absolute;
        top: 0; bottom: 0; right: 0;
        width: min(86vw, 340px);
        flex-basis: min(86vw, 340px);
        box-shadow: -8px 0 32px rgba(0,0,0,0.35);
    }
    .features-panel--collapsed .features-panel-rail { background: var(--bg-elevated); }
}

/* ---- Loading-Overlay ---- */
.map-loading {
    position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    background: rgba(0,0,0,0.25);
    backdrop-filter: blur(2px);
    /* ueber Leaflet-Controls (z 1000), aber unter dem Modal (z 2000). */
    z-index: 1200;
    pointer-events: none;
}
.map-loading[hidden] { display: none; }
.map-loading-card {
    pointer-events: auto;
    background: var(--map-info-bg);
    border: 1px solid var(--border);
    color: var(--fg);
    padding: 14px 22px;
    border-radius: var(--radius);
    display: flex; gap: 12px; align-items: center;
    box-shadow: var(--shadow-card);
}
.spinner {
    width: 18px; height: 18px;
    border: 2px solid var(--border-hi);
    border-top-color: var(--c-primary-hi);
    border-radius: 50%;
    animation: spin .9s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ---- Error-Banner / Toast ---- */
/*
 * Wichtig zur z-index-Ordnung: Leaflet setzt .leaflet-top und .leaflet-bottom
 * (Container fuer Zoom, Layer-Control, Geoman-Toolbar etc.) auf z-index 1000.
 * Damit unsere Overlays nicht von der Geoman-Toolbar oder dem Layer-Control
 * verdeckt werden, liegen sie hoeher.
 */
.map-error {
    position: absolute; top: 12px; left: 50%; transform: translateX(-50%);
    background: var(--c-error-bg);
    color: var(--c-error);
    border: 1px solid var(--c-error);
    padding: 8px 14px;
    border-radius: var(--radius-sm);
    z-index: 1500;
    font-size: .9rem;
    max-width: 80%;
}
.map-toast {
    position: absolute; bottom: 80px; left: 50%; transform: translateX(-50%);
    background: var(--map-info-bg);
    color: var(--fg);
    border: 1px solid var(--border-hi);
    padding: 8px 14px;
    border-radius: var(--radius);
    z-index: 1500;
    font-size: .9rem;
    box-shadow: var(--shadow-card);
}
.map-toast[hidden] { display: none; }

/* ---- Modal (generisch) ---- */
/* z-index 2000: ueber Leaflet-Controls (z 1000) und ueber unseren toasts.
 * backdrop-filter blur, damit Karte/UI hinter dem Modal weich
 * unscharf wird ("aus, aber sichtbar"). */
.modal {
    position: fixed; inset: 0;
    background: rgba(0,0,0,0.45);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    /* safe center statt center, damit ein Modal
 das groesser als der Viewport ist nicht oben aus dem sichtbaren
 Bereich heraus zentriert wird. Wenn der Inhalt zu hoch ist, faellt
 es auf flex-start zurueck und kann von oben nach unten gescrollt
 werden. Greift insbesondere im Tablet-Bereich (769-1024 px), wo
 die Mobile-Fullscreen-Regel (siehe @media (max-width:768px)) noch
 nicht greift. */
    display: flex; align-items: safe center; justify-content: center;
    z-index: 2000;
    padding: 24px;
}
.modal[hidden] { display: none; }
.modal-card {
    background: var(--bg-elevated);
    color: var(--fg);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-card);
    max-width: 460px; width: 100%;
    padding: 22px 24px;
    position: relative;
    /* 100dvh statt 100vh. Auf Tablets/Mobile
 mit dynamischer Browser-URL-Leiste ist 100vh groesser als der
 tatsaechlich sichtbare Bereich, dann steht der obere Modal-Rand
 hinter der URL-Leiste. dvh trackt den realen Viewport. */
    max-height: calc(100dvh - 48px);
    display: flex;
    flex-direction: column;
}
.modal-card--wide  { max-width: 760px; }
.modal-card--wider { max-width: 980px; }

/* scrollbares Inneres fuer das External-Tileset-Form,
 * damit der Speichern-Button auch im WMS-Modus mit allen Feldern
 * (inkl. Spring-Punkt + Auth-Akkordeon) immer sichtbar bleibt. */
.xt-create-form {
    flex: 1 1 auto;
    overflow-y: auto;
    min-height: 0;
    /* Etwas Innenabstand damit Form nicht direkt an der Scroll-Edge klebt. */
    padding-right: 4px;
}

/* Fly-to-Pfeil-Knopf im Layer-Control (.geolyser-fly-to). */
/* Layer-Control-Labels als flex-Container,
 damit der Fly-to-Button per margin-left:auto an den rechten Rand der
 Layer-Box rutscht statt direkt am Layer-Namen zu kleben. Leaflet rendert
 ein <div> (Input + Span) als ersten Child und unser Button (via
 label.appendChild) als zweiten - die werden damit links/rechts
 verteilt. Das innere <div> behaelt sein eigenes Layout. */
.leaflet-control-layers-base label {
    display: flex;
    align-items: center;
    gap: 4px;
}
/* Overlay-Labels als 3-Spalten-Grid:
 ┌─────────┬───────────────────────┬──────────┐
 │ pan-to │ checkbox + name (Z1) │ sort │
 │ (2 row) │ opacity-slider (Z2) │ (2 row) │
 └─────────┴───────────────────────┴──────────┘
 Pan-to + Sort-Arrows ueberspannen beide Zeilen ueber grid-row.
 Der innere Leaflet-Container <div> (Checkbox + Name) ist Z1,
 die Opacity-Slider-Row ist Z2. */
/* vereinfachtes Layout - Label als position:relative,
 Sort-Arrows absolut am rechten Rand ueber beide Zeilen. Innerhalb
 des Labels normaler Flow (input + flyTo + span im inneren div, dann
 opacity-slider-row darunter), mit padding-right damit nichts unter
 die Sort-Arrows rutscht. */
.leaflet-control-layers-overlays label {
    display: block;
    position: relative;
    padding: 2px 36px 2px 4px;  /* rechts Platz fuer Sort-Arrows */
}
.leaflet-control-layers-overlays label > div {
    /* Leaflets eingefuegtes div mit input+span (+ flyTo via insertBefore). */
    display: flex;
    align-items: center;
    gap: 4px;
    min-width: 0;
}
.leaflet-control-layers-overlays label > .geolyser-opacity-slider-row {
    margin-top: 2px;
    padding-left: 24px;
}
.leaflet-control-layers-overlays label > .geolyser-layer-sort-arrows {
    position: absolute;
    right: 4px;
    top: 50%;
    transform: translateY(-50%);
    margin: 0;
}
.geolyser-fly-to {
    border: none;
    background: transparent;
    cursor: pointer;
    /* Button sitzt zwischen Checkbox und Text -
 margin-left:auto braucht's nicht mehr, weil insertBefore den Btn
 direkt nach dem input-Element einfuegt. */
    margin-left: 4px;
    margin-right: 4px;
    padding: 2px 4px;
    color: var(--accent, #3BBDE8);
    vertical-align: middle;
    line-height: 1;
    border-radius: 4px;
    transition: background 0.12s ease, transform 0.12s ease;
}
.geolyser-fly-to:hover {
    background: rgba(59, 189, 232, 0.12);
    transform: translateY(-1px);
}
.geolyser-fly-to img,
.geolyser-fly-to svg {
    display: block;
    width: 18px;
    height: 18px;
}
/* Disabled-State fuer Tilesets ohne Spring-
 Punkt. Btn bleibt sichtbar (gleicher Slot wie aktive Btns), aber
 ausgegraut und ohne Hover-Lift. cursor:help signalisiert dass der
 Tooltip Information liefert (statt der "verboten"-Zeiger). */
.geolyser-fly-to.is-disabled,
.geolyser-fly-to:disabled {
    color: var(--muted, #8a979e);
    opacity: 0.45;
    cursor: help;
}
.geolyser-fly-to.is-disabled:hover,
.geolyser-fly-to:disabled:hover {
    background: transparent;
    transform: none;
}
.modal-header {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px;
    margin: -22px -24px 12px -24px;
    padding: 14px 18px;
    border-bottom: 1px solid var(--border);
}
.modal-header .modal-title { margin: 0; }
.modal-header-tabs {
    display: flex; gap: 4px;
}
.modal-header-tab {
    border: 1px solid transparent;
    background: transparent;
    color: var(--muted-hi);
    padding: 6px 14px;
    border-radius: var(--radius-sm);
    cursor: pointer;
    font: inherit;
    transition: background .12s ease, color .12s ease, border-color .12s ease;
}
.modal-header-tab:hover {
    background: var(--bg-card);
    color: var(--fg);
}
/* aktiver Tab klar erkennbar im Light- UND Dark-Mode. */
.modal-header-tab.is-active {
    background: var(--c-primary);
    color: var(--c-light);
    border-color: var(--c-primary-dk);
    font-weight: 500;
}
.modal-close-btn {
    border: 0;
    background: transparent;
    color: var(--muted-hi);
    cursor: pointer;
    padding: 4px 6px;
    border-radius: var(--radius-sm);
    line-height: 0;
}
.modal-close-btn:hover { background: var(--input-bg); color: var(--fg); }
/* Action-Button mit fuehrendem Icon (z.B. "Speichern", "Verwerfen",
   "Widerrufen" in den Confirm-Dialogs). SVG links, Label rechts. */
.btn-with-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
}
.btn-with-icon svg {
    flex-shrink: 0;
}
.btn-with-icon > span {
    line-height: 1;
}
.modal-body {
    overflow-y: auto;
    margin: 0 -8px;
    padding: 0 8px;
}
.modal-footer {
    display: flex; gap: 8px; justify-content: flex-end;
    border-top: 1px solid var(--border);
    margin: 16px -24px -22px -24px;
    padding: 12px 18px;
}
.modal-title { margin: 0 0 12px 0; }
.modal-text { margin: 0 0 16px 0; color: var(--muted-hi); }
.modal-form {
    display: flex;
    flex-direction: column;
    gap: 12px;
}
/* Nur die TOP-LEVEL-Form (direktes Kind von .modal-card) bekommt
 flex:1 + overflow:auto. Geschachtelte Forms (Profil-Modal hat 2-3 Forms
 nebeneinander im Body) wuerden sich sonst gegenseitig auf height:0
 druecken (timezone-form, password-form Bug). */
.modal-card > .modal-form {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
}
.field { display: flex; flex-direction: column; gap: 4px; }
/* .field hat display:flex — das
 ueberschreibt den UA-Default display:none fuer [hidden]. Explizit
 erzwingen damit der Avatar-Picker im Bug-Modal korrekt
 aus-/eingeblendet werden kann. */
.field[hidden] { display: none !important; }
.field-label { font-size: .8em; color: var(--muted); }
.field input, .field select, .field textarea {
    background: var(--input-bg);
    color: var(--fg);
    border: 1px solid var(--border);
    padding: 8px 10px;
    border-radius: var(--radius-sm);
}
.field input:focus, .field select:focus, .field textarea:focus {
    outline: none; border-color: var(--border-hi);
    box-shadow: 0 0 0 3px rgba(0, 127, 180, 0.18);
}
.form-error { color: var(--c-error); margin: 0; font-size: .85em; }

/* a-Hotfix: Status-Linie im Bug-Report- und aehnlichen Modals.
 * data-kind = info | ok | error setzt die Farbe. */
.modal-status {
    margin: 6px 0 0;
    font-size: .88em;
    padding: 6px 10px;
    border-radius: var(--radius-sm, 6px);
    background: var(--bg-card);
    color: var(--fg);
}
.modal-status[data-kind="info"]  { color: var(--muted-hi); }
.modal-status[data-kind="ok"]    { color: var(--c-signal-dk, #00a04f); }
.modal-status[data-kind="error"] { color: var(--c-error); background: var(--c-error-bg); }
.modal-actions {
    display: flex; gap: 8px; justify-content: flex-end;
    margin-top: 8px;
}
.modal-actions--stack { flex-direction: column; }
.modal-actions--stack .primary, .modal-actions--stack .ghost {
    width: 100%; padding: 12px 14px;
    flex-direction: column; align-items: flex-start;
}
.modal-action-hint {
    font-size: .8em;
    color: var(--muted-hi);
    font-weight: 400;
    margin-top: 2px;
}

/* ---- Login / Dashboard / Trash / Index (gemeinsame Hilfsklassen) ---- */
.page--center {
    min-height: 100%;
    display: flex; align-items: center; justify-content: center;
    padding: 32px 16px;
}
.card {
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-card);
    padding: 24px;
    max-width: 460px;
    width: 100%;
}
.dashboard, .trash {
    max-width: 1100px;
    margin: 24px auto;
    padding: 0 16px;
}
table.simple {
    width: 100%; border-collapse: collapse;
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
}
table.simple th, table.simple td {
    padding: 8px 10px; text-align: left;
    border-bottom: 1px solid var(--border);
}
table.simple tr:last-child td { border-bottom: 0; }
table.simple th { color: var(--muted); font-weight: 500; font-size: .85em; }

/* ---- Leaflet-Anpassungen ---- */
.leaflet-container { background: var(--map-surface); font-family: var(--font-ui); }
.leaflet-control-attribution {
    background: var(--map-info-bg) !important;
    color: var(--muted-hi) !important;
    border-radius: 6px 6px 0 0;
    font-size: 11px;
}
.leaflet-control-attribution a { color: var(--c-primary-hi) !important; }
/* Attribution wird per JS aus dem leaflet-bottom-right
 * Container raus geloest und direkt in #map gehaengt - dann positioniert
 * sie sich relativ zur ganzen Karte und kann unten mittig stehen. */
.leaflet-control-attribution.attribution-bottom-center {
    position: absolute;
    left: 50%;
    bottom: 0;
    transform: translateX(-50%);
    margin: 0 !important;
    z-index: 600;
    pointer-events: auto;
    padding: 2px 8px;
    border-radius: 6px 6px 0 0;
    max-width: calc(100% - 40px);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Leaflet-Bar-Buttons (Zoom +/-, Locate) analog zu GPS-Tools:
 * solider dunkler Hintergrund, weisses Icon im Dark-Mode, beim Hover
 * Icon + Border in Tuerkis (c-primary-hi). Default (Light) bleibt ein
 * heller Card-Hintergrund. */
/* e: Buttons in Zoom-Control + Geoman-Toolbar 4px auseinander
 * ziehen, damit die Border (besonders der tuerkise Hover/Aktiv-Border)
 * sauber rund um jeden einzelnen Button sichtbar ist. Default-Leaflet
 * stackt sie sonst direkt aneinander mit Shared-Border. */
.leaflet-bar {
    background: transparent !important;
    box-shadow: none !important;
    border: 0 !important;
}
.leaflet-bar a {
    background: var(--bg-elevated);
    color: var(--fg);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm, 6px) !important;
    margin-bottom: 4px;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
}
.leaflet-bar a:last-child {
    margin-bottom: 0;
}
.leaflet-bar a:hover {
    background: var(--bg-elevated);
    color: var(--c-primary-hi);
    border-bottom-color: var(--c-primary-hi);
    border-color: var(--c-primary-hi);
}
.leaflet-bar a.leaflet-disabled {
    background: var(--bg-elevated);
    color: var(--muted);
    opacity: 0.55;
}
[data-theme="dark"] .leaflet-bar a {
    background: #20262a;
    color: #ffffff;
    border-color: var(--border);
}
[data-theme="dark"] .leaflet-bar a:hover {
    background: #2b3338;
    color: var(--c-primary-hi);
    border-color: var(--c-primary-hi);
    border-bottom-color: var(--c-primary-hi);
}
.leaflet-control-scale-line {
    background: var(--map-control-bg-lo) !important;
    color: var(--fg) !important;
    border-color: var(--border) !important;
    /* Leaflet-Default packt einen weissen Text-Shadow drum,
 * der im Dark-Mode wie ein Glow wirkt. Plain Text ohne Schatten. */
    text-shadow: none !important;
}
[data-theme="dark"] .leaflet-control-scale-line {
    color: #ffffff !important;
}
/* i: Scale-Line muss ueber den Legal-Links (.map-legal-links)
 * sitzen, sonst ueberdeckt sie unten rechts den Datenschutz/Impressum-
 * Hinweis. Etwa 26px Reserve = Hoehe der Legal-Pill + 4px Luft. */
.leaflet-control-scale {
    margin-bottom: 28px !important;
}

/* ============================================================
 * b — Locate-Plugin + Layers-Control im Dark-Mode
 * ============================================================ */

/* Locate-Icon: Default-Sprite ist schwarz. Im Dark-Mode wollen wir es
 * weiss; im Hover tuerkis. Beim Aktiv-State eingebauter Pulse-Effekt
 * (siehe .gps-tools-btn.is-recording als Vorlage). */
[data-theme="dark"] .leaflet-control-locate a .leaflet-control-locate-location-arrow {
    background-image: url('data:image/svg+xml;charset=UTF-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="white" d="M445 4 29 195c-48 23-32 93 19 93h176v176c0 51 70 67 93 19L508 67c16-38-25-79-63-63z"/></svg>');
}
/* c: Hover -> Icon tuerkis, in beiden Themes. */
.leaflet-control-locate a:hover .leaflet-control-locate-location-arrow {
    background-image: url('data:image/svg+xml;charset=UTF-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="%2300A0D2" d="M445 4 29 195c-48 23-32 93 19 93h176v176c0 51 70 67 93 19L508 67c16-38-25-79-63-63z"/></svg>') !important;
}
/* Aktiv-State (Locate eingeschaltet): tuerkiser Hintergrund, dunkles
 * Icon, pulsierende tuerkise Border - aehnlich .gps-tools-btn.is-
 * recording. Wirkt in Light + Dark konsistent. */
.leaflet-control-locate.active a {
    background: var(--c-primary-hi) !important;
    border-color: var(--c-primary-hi) !important;
    animation: locate-pulse 1.4s ease-in-out infinite;
}
.leaflet-control-locate.active a .leaflet-control-locate-location-arrow {
    /* Plugin-Default faerbt das Icon im aktiv-State blau (rgb 32,116,182).
     * Wir ueberschreiben auf Dunkelgrau, damit es auf der tuerkisen
     * Flaeche gut lesbar ist. */
    background-image: url('data:image/svg+xml;charset=UTF-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="%23222a30" d="M445 4 29 195c-48 23-32 93 19 93h176v176c0 51 70 67 93 19L508 67c16-38-25-79-63-63z"/></svg>') !important;
}
@keyframes locate-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(0, 160, 210, 0.55); }
    50%      { box-shadow: 0 0 0 7px rgba(0, 160, 210, 0); }
}
/* location-arrow im Locate-Btn zentriert ausrichten.
 Default-Plugin setzt das Icon mit fixer Breite/Hoehe; bei groesseren
 Buttons (Touch-Target 30+px) ergibt das ein verschobenes Sprite. */
.leaflet-control-locate a {
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
}
.leaflet-control-locate a .leaflet-control-locate-location-arrow {
    margin: auto !important;
    display: block !important;
}

/* Aktiv-Default fuer alle leaflet-bar-Buttons (Zoom, etc): heller grauer
 * Hintergrund + dunkles Icon. Locate-Active hat oben Vorrang via Spezi-
 * fitaet. */
.leaflet-bar a.active {
    background: #d6dee3;
    color: #222a30;
    border-color: #d6dee3;
}

/* Layers-Control (Basemap-Switcher) - im Vendor-CSS Default weiss; wir
 * faerben Light + Dark passend zum Rest der UI ein. */
.leaflet-control-layers {
    background: var(--bg-elevated) !important;
    color: var(--fg) !important;
    border: 1px solid var(--border) !important;
    border-radius: var(--radius-sm, 6px) !important;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25) !important;
}
.leaflet-control-layers-toggle {
    background-color: var(--bg-elevated) !important;
}
.leaflet-control-layers-list,
.leaflet-control-layers label {
    color: var(--fg);
}
.leaflet-control-layers-separator {
    border-top-color: var(--border) !important;
}
.leaflet-control-layers:hover {
    border-color: var(--border-hi) !important;
}
[data-theme="dark"] .leaflet-control-layers,
[data-theme="dark"] .leaflet-control-layers-expanded {
    background: #20262a !important;
    color: #ffffff !important;
}
[data-theme="dark"] .leaflet-control-layers-toggle {
    background-color: #20262a !important;
    /* f: Filter:invert wuerde auch den Hintergrund umdrehen
 * (heller statt dunkler), deshalb tauschen wir lieber direkt das
 * Sprite gegen eine weisse Inline-SVG aus. */
    background-image: url('data:image/svg+xml;charset=UTF-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26"><path fill="white" d="M13 3 L23 8 L13 13 L3 8 Z"/><path d="M3 12 L13 17 L23 12 M3 16 L13 21 L23 16" stroke="white" stroke-width="1.5" fill="none" stroke-linejoin="round"/></svg>') !important;
    background-size: 22px 22px !important;
}
/* Hover: gleiches Sprite, aber tuerkis. */
[data-theme="dark"] .leaflet-control-layers-toggle:hover {
    background-image: url('data:image/svg+xml;charset=UTF-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26"><path fill="%2300A0D2" d="M13 3 L23 8 L13 13 L3 8 Z"/><path d="M3 12 L13 17 L23 12 M3 16 L13 21 L23 16" stroke="%2300A0D2" stroke-width="1.5" fill="none" stroke-linejoin="round"/></svg>') !important;
    background-color: #2b3338 !important;
    border-color: var(--c-primary-hi) !important;
}
/* Auch im Light-Mode wollen wir Hover-Tuerkis fuers Toggle-Icon. */
.leaflet-control-layers-toggle:hover {
    background-image: url('data:image/svg+xml;charset=UTF-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26"><path fill="%2300A0D2" d="M13 3 L23 8 L13 13 L3 8 Z"/><path d="M3 12 L13 17 L23 12 M3 16 L13 21 L23 16" stroke="%2300A0D2" stroke-width="1.5" fill="none" stroke-linejoin="round"/></svg>') !important;
    background-size: 22px 22px !important;
    border-color: var(--c-primary-hi) !important;
}
[data-theme="dark"] .leaflet-control-layers-list,
[data-theme="dark"] .leaflet-control-layers label {
    color: #ffffff !important;
}
[data-theme="dark"] .leaflet-control-layers-separator {
    border-top-color: rgba(155, 217, 245, 0.18) !important;
}

/* Geoman-Toolbar analog zu Zoom/Locate/GPS-Tools.
 * Geoman benutzt PNG-Sprites als Icons; im Dark-Mode invertieren wir die
 * dunklen Icons zu hell. Beim Hover wird die Border tuerkis. */
.leaflet-pm-toolbar {
    background: transparent !important;
    box-shadow: none !important;
    border: 0 !important;
}
.leaflet-pm-toolbar a {
    background-color: var(--bg-elevated);
    color: var(--fg);
    /* e: 4px Abstand + volle Border + eigene Box-Shadow je
 * Button, damit der tuerkise Hover-Border sauber rund um jeden
 * einzelnen Button sichtbar ist. */
    border: 1px solid var(--border) !important;
    border-radius: var(--radius-sm, 6px) !important;
    margin-bottom: 4px !important;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
}
.leaflet-pm-toolbar a:last-child {
    margin-bottom: 0 !important;
}
.leaflet-pm-toolbar a:hover {
    background-color: var(--bg-elevated);
    color: var(--c-primary-hi);
    border-color: var(--c-primary-hi) !important;
}
.leaflet-pm-toolbar a.active,
.leaflet-pm-toolbar a.active:hover {
    background-color: var(--c-primary);
    color: var(--c-light);
    border-color: var(--c-primary) !important;
}
[data-theme="dark"] .leaflet-pm-toolbar a {
    background-color: #20262a;
}
[data-theme="dark"] .leaflet-pm-toolbar a:hover {
    background-color: #2b3338;
    border-color: var(--c-primary-hi) !important;
}
/* Geoman-Icons sind dunkle PNG-Sprites - im Dark-Mode invertieren, damit
 * sie auf dem dunklen Button-Hintergrund sichtbar werden. */
[data-theme="dark"] .leaflet-pm-toolbar a .control-icon,
[data-theme="dark"] .leaflet-pm-toolbar a > .control-icon,
[data-theme="dark"] .leaflet-pm-icon-marker,
[data-theme="dark"] .leaflet-pm-icon-polyline,
[data-theme="dark"] .leaflet-pm-icon-rectangle,
[data-theme="dark"] .leaflet-pm-icon-polygon,
[data-theme="dark"] .leaflet-pm-icon-circle,
[data-theme="dark"] .leaflet-pm-icon-circle-marker,
[data-theme="dark"] .leaflet-pm-icon-edit,
[data-theme="dark"] .leaflet-pm-icon-drag,
[data-theme="dark"] .leaflet-pm-icon-cut,
[data-theme="dark"] .leaflet-pm-icon-rotate,
[data-theme="dark"] .leaflet-pm-icon-delete,
/* Custom Scale + PolyOps Icons in den
 Dark-Mode-Invert-Filter mit aufnehmen — sonst bleiben sie dunkel
 auf dunklem Hintergrund. */
[data-theme="dark"] .leaflet-pm-icon-scale,
[data-theme="dark"] .leaflet-pm-icon-polyops {
    filter: invert(1) hue-rotate(180deg) brightness(1.05);
}
/* Active-State: Icon bleibt invertiert (weiss auf c-primary-Hintergrund). */

/* c: Hover -> Geoman-Icons werden tuerkis. Da die Icons PNG-
 * Sprites sind, faerben wir sie via Filter ein (Approximation an
 * #00A0D2 = c-primary-hi). Funktioniert in Light + Dark, weil die
 * Filterkette vom schwarzen Quell-PNG ausgeht und unsere Dark-Mode-
 * Inversion via !important uebersteuert. */
.leaflet-pm-toolbar a:hover .control-icon,
.leaflet-pm-toolbar a:hover > .control-icon,
.leaflet-pm-toolbar a:hover [class*="leaflet-pm-icon"],
[data-theme="dark"] .leaflet-pm-toolbar a:hover .control-icon,
[data-theme="dark"] .leaflet-pm-toolbar a:hover > .control-icon,
[data-theme="dark"] .leaflet-pm-toolbar a:hover [class*="leaflet-pm-icon"] {
    filter: brightness(0) saturate(100%) invert(54%) sepia(80%) saturate(2240%) hue-rotate(170deg) brightness(95%) contrast(101%) !important;
}

/* ---- Feature-Popup (Leaflet-Popup, gestylt) ----------------------- */
.leaflet-popup-content-wrapper {
    background: var(--bg-elevated) !important;
    color: var(--fg) !important;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm) !important;
    box-shadow: var(--shadow-card);
}
.leaflet-popup-tip { background: var(--bg-elevated) !important; }
.feature-popup-card { font-family: var(--font-ui); min-width: 180px; }
.feature-popup-name { font-weight: 600; margin-bottom: 4px; }
.feature-popup-meta { display: flex; flex-wrap: wrap; gap: 4px; margin: 4px 0; }
/* Avatar-Sektion im Profil-Modal. */
.avatar-row {
    display: flex;
    align-items: center;
    gap: 16px;
    margin: 8px 0 18px;
}
.avatar-preview {
    width: 80px;
    height: 80px;
    border-radius: 50%;
    overflow: hidden;
    background: var(--bg-elevated, rgba(0,0,0,0.06));
    border: 2px solid var(--border, rgba(0,0,0,0.12));
    display: flex; align-items: center; justify-content: center;
    color: var(--c-primary-hi, #06829c);
    font-weight: 600;
    font-size: 1.6em;
    flex-shrink: 0;
}
.avatar-preview.has-image {
    border-color: var(--c-primary-hi, #06829c);
}
.avatar-preview img,
.avatar-preview svg {
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
}
.avatar-preview-initials { letter-spacing: 0.04em; }
.avatar-actions {
    display: flex;
    flex-direction: column;
    gap: 6px;
    align-items: flex-start;
}
[data-theme="dark"] .avatar-preview {
    background: rgba(255,255,255,0.06);
    color: var(--c-primary-hi, #06829c);
}

/* Presence-Bar in der Topbar (Avatar-Chips der online User). */
.presence-bar {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-right: 6px;
    padding-right: 8px;
    border-right: 1px solid var(--border, rgba(0,0,0,0.12));
}
.presence-bar:empty,
.presence-bar[hidden] {
    display: none;
}
.presence-chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--bg-card, #fff);
    border: 2px solid var(--user-color, #06829c);
    overflow: hidden;
    flex-shrink: 0;
    box-sizing: border-box;
    font-size: 11px;
    font-weight: 600;
    color: var(--user-color, #06829c);
    cursor: default;
    line-height: 1;
}
.presence-chip img {
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
}
.presence-chip-initials {
    font-size: 0.78em;
    letter-spacing: 0.02em;
    text-transform: uppercase;
}
.presence-chip--initials {
    background: var(--user-color, #06829c);
    color: #fff;
}
/* Auto-Avatar (SVG mit Initialen + zufaelliger Farbe).
 Border weg da das SVG schon eine eigene Background-Form hat. */
.presence-chip--auto {
    border: none;
    background: transparent;
    padding: 0;
}
.presence-chip--auto svg {
    width: 100%;
    height: 100%;
    display: block;
}
.presence-chip--more {
    background: var(--bg-elevated, rgba(0,0,0,0.08));
    color: var(--muted-hi);
    border-color: var(--border, rgba(0,0,0,0.12));
    font-size: 11px;
    width: 26px; height: 26px;
}
[data-theme="dark"] .presence-chip {
    background: var(--surface-elevated, #2a2a2a);
}

/* Aggregations-Pille mit Hover-Popover.
 Zeigt nur die Anzahl der aktiven Coworker; im Hover die volle Liste
 mit Avatar + Username pro Eintrag. */
.presence-chip--count {
    width: 26px; height: 26px;
    background: rgba(0, 204, 255, 0.20);
    color: #003848;
    border-color: rgba(0, 204, 255, 0.55);
    font-size: 12px;
    font-weight: 700;
    cursor: help;
}
[data-theme="dark"] .presence-chip--count {
    background: rgba(0, 204, 255, 0.28);
    color: #b8edff;
}
.presence-chip--count.has-popover {
    position: relative;
}
.presence-popover {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    z-index: 1300;
    margin: 0;
    padding: 6px;
    list-style: none;
    background: var(--bg-card, #fff);
    border: 1px solid var(--border, #ccc);
    border-radius: 8px;
    box-shadow: 0 8px 22px rgba(0,0,0,0.22);
    min-width: 180px;
    max-height: 60vh;
    overflow-y: auto;
    display: none;
    pointer-events: none;
}
.presence-chip--count.has-popover:hover .presence-popover,
.presence-chip--count.has-popover:focus .presence-popover,
.presence-chip--count.has-popover:focus-within .presence-popover {
    display: block;
}
.presence-popover-item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 6px;
    border-radius: 6px;
}
.presence-popover-item:hover {
    background: var(--bg-elevated, rgba(0,0,0,0.04));
}
.presence-popover-name {
    font-size: 0.92em;
    color: var(--text);
    font-weight: 500;
}
[data-theme="dark"] .presence-popover {
    background: var(--surface-elevated, #1f2024);
    border-color: rgba(255,255,255,0.14);
}

/* Live-Cursor-Marker (Geist-Cursor anderer User auf der Karte). */
.cursor-marker-wrap {
    pointer-events: none;
    background: transparent !important;
    border: none !important;
}
.cursor-marker {
    position: relative;
    display: inline-block;
    pointer-events: none;
}
.cursor-marker-label {
    position: absolute;
    left: 18px; top: 14px;
    background: var(--cursor-color, #06829c);
    color: #fff;
    font-size: 11px;
    font-weight: 500;
    padding: 1px 6px;
    border-radius: 4px;
    white-space: nowrap;
    box-shadow: 0 2px 4px rgba(0,0,0,0.25);
}

/* Mobile: Presence-Bar etwas kompakter. */
@media (max-width: 768px) {
    .presence-bar {
        margin-right: 2px;
        padding-right: 4px;
    }
    .presence-chip {
        width: 22px !important;
        height: 22px !important;
    }
    .presence-chip--more {
        font-size: 10px;
    }
}

/* Feature ist von anderem User gesperrt. */
.layer-feature-row.is-locked {
    opacity: 0.7;
}
.lock-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    background: var(--bg-elevated, rgba(0,0,0,0.06));
    border: 1px solid var(--user-color, var(--border));
    color: var(--user-color, var(--muted-hi));
    border-radius: 999px;
    padding: 1px 6px;
    font-size: 0.78em;
    margin-left: 6px;
}

/* Sidebar-Bulk-Action-Popover */
.sidebar-bulk-menu {
    background: var(--surface, #fff);
    color: var(--text, #222);
    border: 1px solid var(--border, #d0d0d0);
    border-radius: 6px;
    box-shadow: 0 6px 16px rgba(0,0,0,0.18);
    padding: 4px;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.sidebar-bulk-menu-item {
    background: transparent;
    border: none;
    padding: 8px 10px;
    text-align: left;
    cursor: pointer;
    border-radius: 4px;
    font-size: 0.92em;
    color: inherit;
    display: flex;
    align-items: center;
    gap: 8px;
}
.sidebar-bulk-menu-item:hover {
    background: var(--hover-bg, rgba(0,0,0,0.06));
}
.sidebar-bulk-menu-item.ghost-danger {
    color: var(--c-danger, #c44);
}
.sidebar-bulk-menu-item.ghost-danger:hover {
    background: rgba(196, 68, 68, 0.10);
}
[data-theme="dark"] .sidebar-bulk-menu {
    background: var(--surface-elevated, #2a2a2a);
    border-color: rgba(255,255,255,0.12);
}

/* Mess-Tool */
.geolyser-measure-cursor #map,
.geolyser-measure-cursor.leaflet-container,
#map.geolyser-measure-cursor,
.geolyser-measure-cursor {
    cursor: crosshair !important;
}
/* Polish: DSM-Picker-Optionen mit Hintergrund-Hervorhebung,
 damit sie sich vom Modal-Hintergrund abheben (analog zu Buttons). */
.dsm-pick-option {
    display: flex;
    gap: 10px;
    align-items: flex-start;
    padding: 10px 12px;
    border: 1px solid var(--border, rgba(0,0,0,0.12));
    border-radius: 7px;
    margin-bottom: 8px;
    cursor: pointer;
    background: var(--bg-elevated, rgba(0,0,0,0.04));
    transition: background 0.12s ease, border-color 0.12s ease, box-shadow 0.12s ease;
}
.dsm-pick-option:hover {
    background: var(--hover-bg, rgba(0,0,0,0.08));
    border-color: rgba(6, 130, 156, 0.45);
}
.dsm-pick-option.is-checked {
    background: rgba(6, 130, 156, 0.10);
    border-color: rgba(6, 130, 156, 0.65);
    box-shadow: inset 0 0 0 1px rgba(6, 130, 156, 0.25);
}
.dsm-pick-option input[type="radio"] {
    margin-top: 3px;
    flex-shrink: 0;
}
.dsm-pick-option-text {
    display: flex;
    flex-direction: column;
    gap: 3px;
    flex: 1;
    min-width: 0;
}
.dsm-pick-title {
    font-weight: 600;
    font-size: 13.5px;
    overflow-wrap: anywhere;
}
.dsm-pick-meta {
    font-size: 0.85em;
    opacity: 0.78;
    overflow-wrap: anywhere;
}
[data-theme="dark"] .dsm-pick-option {
    background: rgba(255,255,255,0.05);
    border-color: rgba(255,255,255,0.10);
}
[data-theme="dark"] .dsm-pick-option:hover {
    background: rgba(255,255,255,0.08);
}
[data-theme="dark"] .dsm-pick-option.is-checked {
    background: rgba(6, 130, 156, 0.20);
    border-color: rgba(6, 130, 156, 0.70);
}

/* Save-Options-Modal Polish - vertikale Karten-Optionen. */
.save-options-list {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin: 14px 0 6px;
}
.save-options-card {
    /* .primary/.ghost setzen display:inline-flex + center; wir muessen
       das fuer das links-buendige Karten-Layout ueberschreiben. */
    display: flex !important;
    align-items: flex-start !important;
    justify-content: flex-start !important;
    gap: 12px;
    padding: 12px 14px;
    text-align: left;
    width: 100%;
    border-radius: 8px;
    cursor: pointer;
    border: 1px solid transparent;
    transition: transform 0.08s ease, box-shadow 0.12s ease, border-color 0.12s ease;
    line-height: 1.3;
}
.save-options-card:hover {
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(0,0,0,0.08);
}
.save-options-card-icon {
    flex: 0 0 32px;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-top: 2px;
}
.save-options-card-text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    flex: 1;
}
.save-options-card-title {
    font-weight: 600;
    font-size: 14px;
}
.save-options-card-desc {
    font-size: 12.5px;
    opacity: 0.78;
}
.save-options-card-extra {
    margin-top: 6px;
    font-size: 12px;
    display: flex;
    gap: 6px;
    align-items: center;
    cursor: pointer;
}
/* Klick auf das Checkbox-Label soll NICHT die Karte aktivieren. */
.save-options-card-extra input[type="checkbox"] {
    pointer-events: auto;
}

/* Live-Drawing-Tooltip neben dem Cursor. */
.geolyser-measure-live-tooltip {
    background: rgba(20, 30, 40, 0.92);
    color: #fff;
    padding: 6px 8px;
    border-radius: 5px;
    font-size: 12px;
    line-height: 1.25;
    box-shadow: 0 4px 10px rgba(0,0,0,0.20);
    white-space: nowrap;
}
.geolyser-measure-live-tooltip .sub {
    opacity: 0.78;
    font-size: 11px;
}
[data-theme="dark"] .geolyser-measure-live-tooltip {
    background: rgba(0, 0, 0, 0.85);
}

/* Scale-Mode-Toolbar-Btn + Handles. Wir nehmen
 !important fuer das background-image, weil Geoman selbst per JS
 inline-Background-Images setzt — ohne !important ueberschreibt
 Geoman unsere Definition. Dark-Mode-Override mit hoeherer
 Spezifizitaet (body[data-theme]-Vorfahre + Klassen-Match). */
.leaflet-pm-icon-scale {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23333' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='15 3 21 3 21 9'/><polyline points='9 21 3 21 3 15'/><line x1='21' y1='3' x2='14' y2='10'/><line x1='3' y1='21' x2='10' y2='14'/></svg>") !important;
    background-position: center !important;
    background-repeat: no-repeat !important;
    background-size: 18px 18px !important;
}
/* eigener Dark-Mode-Override fuer scale-icon entfernt —
 wird jetzt von der globalen invert(1)-Filter-Regel oben behandelt. */
.geolyser-scale-handle {
    pointer-events: auto;
    cursor: nwse-resize;
}
.geolyser-scale-handle-inner {
    display: block;
    width: 12px;
    height: 12px;
    border: 2px solid #1a73e8;
    background: #fff;
    border-radius: 2px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
}
[data-theme="dark"] .geolyser-scale-handle-inner {
    background: #d8dee5;
    border-color: #4f9eff;
}
.geolyser-scale-handle.is-other-dragging .geolyser-scale-handle-inner {
    opacity: 0.35;
}
body[data-geolyser-scale-active="true"] .leaflet-pm-icon-scale {
    background-color: rgba(26, 115, 232, 0.18) !important;
}

/* Polygon-Ops-Mode (Vereinigung/Schnitt/Differenz). */
.leaflet-pm-icon-polyops {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23333' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='9' cy='12' r='6'/><circle cx='15' cy='12' r='6'/></svg>") !important;
    background-position: center !important;
    background-repeat: no-repeat !important;
    background-size: 20px 20px !important;
}
/* eigener Dark-Mode-Override fuer polyops-icon entfernt —
 globale invert(1)-Filter-Regel oben uebernimmt. */
body[data-geolyser-polyops-active="true"] .leaflet-pm-icon-polyops {
    background-color: rgba(26, 115, 232, 0.18) !important;
}

/* Geoman-Action-Buttons (Beenden / Letzten Vertex loeschen
 / Abbrechen) + Mess-Tool-Action-Button. Geoman's Default-Style sieht
 sehr generisch aus (graues #666 mit weissem Trenn-Strich), passt nicht
 zum App-Theme. Wir bringen die Buttons auf:
 - kleinere Hoehe (26 px statt 29 px) -> wirkt aufgeraeumter.
 - App-Theme-Farben (dark/light) statt #666.
 - sauberer Trenner zwischen den Buttons (var(--border-hi)).
 - Hover -> --c-primary-hi.
 - Abstand vom Toolbar-Btn ueber margin-left am Actions-Container. */

/* Geoman-Default-Overrides. Wir vermeiden !important auf border-right,
   damit Geoman's :last-child-Regel weiterhin den Trenn-Strich am
   letzten Button entfernen kann (sonst sieht man den weissen Rand
   rechts vom "Abbrechen"-Button). */
.leaflet-pm-toolbar .button-container .leaflet-pm-actions-container {
    /* Abstand vom Toolbar-Btn zum ersten Action-Btn. */
    margin-left: 4px;
    /* Action-Btns vertikal zum Toolbar-Btn
 zentrieren. Geoman setzt top:0 was die Btns oben buendig macht;
 da unsere Btns 26 px hoch sind und die Toolbar-Btns 30 px, wirken
 sie sonst leicht nach oben verschoben. translateY(-50%) auf top:50%
 zentriert unabhaengig von den genauen Hoehen.
 Mobile-FF-Fix : position:absolute explizit gesetzt damit
 top:50% verankert.
 Mobile-II-Fix : KEIN display:inline-flex hier — das hat
 Geomans display:none-Steuerung fuer inaktive Tools ueberschrieben
 und alle Beenden/Abbrechen-Buttons gleichzeitig sichtbar gemacht.
 Geoman managed das selber, wir greifen nicht ein. */
    position: absolute !important;
    top: 50% !important;
    transform: translateY(-50%);
    /* Mobile-L-Fix : Actions-Container ("Beenden", "Abbrechen",
 * "Loeschen letzter Vertex") muss IMMER vor allen Karten-Overlays
 * und anderen Geoman-Buttons liegen. */
    z-index: 1100 !important;
}
/* Mobile-LL-Fix Defensiv-Regel —
 * EXPLIZIT verstecken wenn das Parent-Button-Container NICHT .active
 * ist. Geoman's default ".leaflet-pm-actions-container { display: none }"
 * hat im aktuellen Setup nicht mehr gegriffen (vermutlich durch andere
 * CSS-Regeln in der App oder einen Stale-SW-Cache). Mit !important +
 * :not(.active)-Specificity (0,4,0) gewinnen wir definitiv ueber alle
 * konkurrierenden Regeln. */
.leaflet-pm-toolbar .button-container:not(.active) .leaflet-pm-actions-container {
    display: none !important;
}
/* Mess-Tool-Actions-Container hat KEINE .button-container.active-
 * Steuerung, sondern wird programmatisch via _setActionsVisible() in
 * measurement-tool.js per inline style.display gesteuert. Die obige
 * :not(.active)-Regel wuerde ihn faelschlicherweise ausblenden weil
 * sein Parent .geolyser-measure-control nicht .button-container ist
 * — er ist daher nicht betroffen (Selektor zielt auf
 * .button-container, nicht auf .geolyser-measure-control). */
/* Mobile-II-Fix : 4px Gap zwischen Action-Btns nicht via
 * flex-gap (wuerde display:flex erzwingen), sondern via margin-left
 * auf alle bis auf den ersten. Funktioniert mit Geomans Default
 * inline-block-Layout. */
.leaflet-pm-toolbar .button-container .leaflet-pm-actions-container
    .leaflet-pm-action + .leaflet-pm-action {
    margin-left: 4px;
}
/* Mobile-X/QQ-Fix : Auf Smartphone sollen die pm-action-Buttons
 * (Beenden / Abbrechen / Letzten Vertex loeschen) die volle Text-
 * Breite haben (kein Truncate, kein abgeschnittenes "Letzten Vertex
 * loesch..."). JP-Iteration: BUTTONS VERTIKAL untereinander stapeln —
 * nebeneinander wurden sie zu schmal und der Text war abgeschnitten.
 * Container als flex-column, Btns mit fester Mindestbreite. */
@media (max-width: 768px) {
    .leaflet-pm-toolbar .button-container .leaflet-pm-actions-container {
        display: flex !important;
        flex-direction: column !important;
        align-items: stretch;
        gap: 4px;
    }
    .leaflet-pm-toolbar .button-container.active .leaflet-pm-actions-container {
        display: flex !important;
    }
    .leaflet-pm-toolbar .button-container .leaflet-pm-actions-container
        .leaflet-pm-action {
        display: block !important;
        white-space: nowrap;
        padding: 0 12px !important;
        font-size: 0.86em !important;
        height: 30px !important;
        line-height: 30px !important;
        min-width: 160px;
        text-align: center;
        margin: 0 !important;
        box-sizing: border-box;
        border-radius: 3px !important;
        border-right: 1px solid var(--border) !important;
    }
}

/* Mobile-M/U/CC/MM-Fix : Maximize-Btn ("Vollbild") neben
 * "Beenden" im Mess-Tool pm-actions-container. Default: NICHT
 * SICHTBAR (display: none !important — auf Desktop und Tablet
 * permanent verborgen). Nur im 768px-Block per !important auf
 * inline-block.
 * Mobile-MM-Fix Selektor korrigiert.
 * Der Mess-Tool-Maximize-Btn liegt in .geolyser-measure-control, NICHT
 * in .leaflet-pm-toolbar — deshalb hatte mein vorheriger Selektor
 * `.leaflet-pm-toolbar ... .geolyser-measure-maximize-action` nicht
 * gegriffen, und der Btn war auf Desktop sichtbar. Neuer Selektor
 * nutzt direkt die Klasse — die ist eindeutig. */
.geolyser-measure-maximize-action {
    display: none !important;
}
.geolyser-measure-maximize-action.is-active {
    background-color: var(--c-cyan, #3BBDE8);
    color: #fff;
}
[data-theme="dark"] .geolyser-measure-maximize-action.is-active {
    background-color: var(--c-cyan, #3BBDE8);
    color: #052e16;
}
/* Mobile-U/CC-Fix: Maximize-Btn ("Vollbild") + Minimize-Btn im Panel-
 * Header nur auf Smartphone sichtbar — Tablet/Desktop haben das Panel
 * sowieso permanent dargestellt, brauchen keinen Min/Max-Toggle.
 * Mobile-CC-Fix: gleiche Hoehe + Mindestbreite wie "Beenden" damit
 * sie nebeneinander optisch sauber wirken. 6px Abstand dazwischen. */
@media (max-width: 768px) {
    /* Mobile-PP/RR-Fix Auf Smartphone Vollbild-
 * Btn UNTER dem Beenden-Btn stapeln. Beide EXAKT 160x30 wie die
 * Geoman-pm-action-Btns. Specificity hochziehen mit .leaflet-bar a.…
 * + !important damit die Phase-113.26-Regel (height: 26px !important)
 * an Zeile 2397 ueberschrieben wird. */
    /* Mobile-SS-Fix : KEIN !important auf display — damit
 * measurement-tool.js _setActionsVisible via inline-style die
 * Sichtbarkeit weiter steuern kann. Vorher hat !important die
 * JS-Hide blockiert → Btns permanent sichtbar. End-of-file-Block
 * uebernimmt die finale Geometrie. */
    .geolyser-measure-actions-container {
        display: flex;
        flex-direction: column;
        align-items: stretch;
        gap: 4px;
    }
    /* Konkrete Btn-Geometrie ist im End-of-file Mobile-SS-Block — hier
     * nur Layout-Container. Doppelte Definition entfernt. */
    /* Mobile-RR-Fix (JP): Hover-Effekt fuer den Vollbild-Btn
 * (Beenden hatte schon einen aus ). Touch-aktiv fuer
 * beide damit auf Smartphone klar erkennbar dass es klickbar ist. */
    .leaflet-bar a.geolyser-measure-maximize-action:hover,
    .leaflet-bar a.geolyser-measure-maximize-action:focus,
    a.geolyser-measure-maximize-action:hover,
    a.geolyser-measure-maximize-action:focus {
        background-color: var(--bg-card) !important;
        color: var(--c-primary-hi) !important;
        border-color: var(--c-primary-hi) !important;
        cursor: pointer;
    }
    .leaflet-bar a.geolyser-measure-end-action:active,
    .leaflet-bar a.geolyser-measure-maximize-action:active,
    a.geolyser-measure-end-action:active,
    a.geolyser-measure-maximize-action:active {
        background-color: var(--c-cyan, #3BBDE8) !important;
        color: #fff !important;
        border-color: var(--c-cyan, #3BBDE8) !important;
    }
    /* Mobile-RR-Fix (JP): Hover- + Active-State fuer die
 * Geoman-pm-action-Buttons (Beenden / Letzten Vertex / Abbrechen)
 * im Smartphone-Vertikal-Stapel. Die alte Hover-Regel an Zeile 2347
 * existiert weiterhin (Specificity 0,4,1) — sie greift, aber auf
 * Touch-Geraeten fehlt :hover; daher zusaetzlich :active mit
 * staerkerer visueller Rueckmeldung. */
    .leaflet-pm-toolbar .button-container .leaflet-pm-actions-container
        .leaflet-pm-action:active {
        background-color: var(--c-cyan, #3BBDE8) !important;
        color: #fff !important;
        border-color: var(--c-cyan, #3BBDE8) !important;
    }
}
@media (min-width: 769px) {
    .geolyser-measure-panel .measure-minimize-btn {
        display: none !important;
    }
}
/* Mess-Panel minimiert: komplett ausgeblendet, Mess-Session laeuft im
 * Hintergrund. Maximize-Btn wird zur einzigen Schnittstelle.
 * is-maximized: Default-Visibility (Panel sichtbar). Auf Mobile bekommt
 * is-maximized zusaetzlich Fullscreen-Look. */
.geolyser-measure-panel.is-minimized {
    display: none !important;
}
@media (max-width: 768px) {
    .geolyser-measure-panel.is-maximized {
        position: fixed !important;
        inset: 0 !important;
        width: 100vw !important;
        max-width: 100vw !important;
        height: 100dvh !important;
        max-height: 100dvh !important;
        border-radius: 0 !important;
        margin: 0 !important;
        z-index: 2050 !important;
        display: flex !important;
        flex-direction: column;
    }
    .geolyser-measure-panel.is-maximized .geolyser-measure-head {
        padding: 12px 16px !important;
        padding-top: calc(env(safe-area-inset-top, 0px) + 12px) !important;
        background: var(--bg-elevated) !important;
        border-bottom: 1px solid var(--border);
        flex-shrink: 0;
    }
    .geolyser-measure-panel.is-maximized .geolyser-measure-body,
    .geolyser-measure-panel.is-maximized .geolyser-measure-tools,
    .geolyser-measure-panel.is-maximized .geolyser-picker-group {
        padding: 12px 16px !important;
        overflow-y: auto;
    }
}

/* Mobile-L/GG-Fix : Wenn ein Draw-Tool gerade aktiv ist,
 * werden alle anderen Tool-Buttons greyed-out + nicht-klickbar.
 * Mobile-GG-Fix: statt :has (auf Smartphone unzuverlaessig) nutzen
 * wir jetzt eine globale Klasse `body.geolyser-pm-drawing`, die per JS
 * im pm:drawstart-Handler (map.js) gesetzt wird. So funktioniert es
 * konsistent auf allen Browsern + Devices. Die :has-Variante bleibt
 * als Belt-und-Hosentraeger zusaetzlich aktiv. */
body.geolyser-pm-drawing .leaflet-pm-toolbar .button-container > a:not(.active),
body.geolyser-pm-drawing .leaflet-pm-toolbar .button-container > a:not(.active):hover,
.leaflet-pm-toolbar:has(.button-container > a.active) .button-container:not(:has(> a.active)) > a,
.leaflet-pm-toolbar:has(.button-container > a.active) .button-container:not(:has(> a.active)) > a:hover {
    opacity: 0.35 !important;
    pointer-events: none !important;
    filter: grayscale(1);
    cursor: not-allowed;
}
/* Auch die GPS-Tools (Locate/Location-Draw) waehrend einer Draw-Aktion
 * greyen — sonst loest ein versehentlicher Touch auf Locate die
 * Geo-Positionierung mit Karten-Pan aus und der laufende Draw bricht
 * unter dem Daumen weg. */
body.geolyser-pm-drawing .leaflet-control-locate a,
body.geolyser-pm-drawing .gps-tools-bar .gps-tools-btn:not(.is-active),
.map-shell:has(.leaflet-pm-toolbar .button-container > a.active) .leaflet-control-locate a,
.map-shell:has(.leaflet-pm-toolbar .button-container > a.active) .gps-tools-bar .gps-tools-btn:not(.is-active) {
    opacity: 0.35;
    pointer-events: none;
    filter: grayscale(1);
}
.leaflet-pm-toolbar .button-container .leaflet-pm-actions-container
    .leaflet-pm-action {
    padding: 0 10px;
    height: 26px;
    line-height: 26px;
    font-size: 0.82em;
    vertical-align: top;
    background-color: var(--bg-elevated);
    color: var(--text);
    border-right: 1px solid var(--border);
    border-top: 1px solid var(--border);
    border-bottom: 1px solid var(--border);
    box-sizing: border-box;
}
/* Erster Btn: Linke Border + Rounded-Corners links. */
.leaflet-pm-toolbar .button-container .leaflet-pm-actions-container
    .leaflet-pm-action:first-child {
    border-left: 1px solid var(--border);
    border-radius: 3px 0 0 3px;
}
/* Letzter Btn: Rounded-Corners rechts, KEIN Trenn-Strich rechts (das
   ist der "weisse Rand rechts" aus dem Screenshot — der Default-Wert
   ist 'border-right: 1px solid #eee' und der :last-child-Selector
   setzt das auf 0; wir muessen die App-Theme-Farbe NICHT mit !important
   ueberschreiben). */
.leaflet-pm-toolbar .button-container .leaflet-pm-actions-container
    .leaflet-pm-action:last-child {
    border-right: 0;
    border-radius: 0 3px 3px 0;
}
/* Einzelner Btn (z. B. nur "Beenden"): Rundung auf beiden Seiten. */
.leaflet-pm-toolbar .button-container .leaflet-pm-actions-container
    .leaflet-pm-action:first-child:last-child {
    border-radius: 3px;
    border-right: 1px solid var(--border);
}
.leaflet-pm-toolbar .button-container .leaflet-pm-actions-container
    .leaflet-pm-action:hover,
.leaflet-pm-toolbar .button-container .leaflet-pm-actions-container
    .leaflet-pm-action:focus {
    background-color: var(--bg-card);
    color: var(--c-primary-hi);
    cursor: pointer;
    text-decoration: none;
}
/* Dark-Mode-Variante: dunkleres Bg, helle Schrift — wirkt wie das
   Mess-Tool-Beenden im 2. Screenshot, welches der User als "bessere
   Farbe" bezeichnet hat. */
[data-theme="dark"] .leaflet-pm-toolbar .button-container
    .leaflet-pm-actions-container .leaflet-pm-action {
    background-color: #2c2f33;
    color: #eaeaea;
    border-color: rgba(255, 255, 255, 0.10);
}
[data-theme="dark"] .leaflet-pm-toolbar .button-container
    .leaflet-pm-actions-container .leaflet-pm-action:hover,
[data-theme="dark"] .leaflet-pm-toolbar .button-container
    .leaflet-pm-actions-container .leaflet-pm-action:focus {
    background-color: #3b3f44;
    color: var(--c-primary-hi);
}

/* Mess-Tool Beenden-Action exakt gleich gross
 wie die Geoman-Draw-Action-Buttons (26 px hoch, Auto-Breite).
 Wichtig: Leaflet hat fuer .leaflet-touch .leaflet-bar a hartcodiert
 width: 30px; height: 30px; line-height: 30px; Das ist spezifischer
 als nur '.geolyser-measure-end-action' — wir muessen mit eigenem
 Selector .leaflet-bar a.geolyser-measure-end-action ueberlagern + die
 Leaflet-Properties explizit zurueck-ueberschreiben. */
.geolyser-measure-control {
    position: relative;
}
.geolyser-measure-actions-container {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    left: 100%;
    margin-left: 4px;
    z-index: 2;
    white-space: nowrap;
    direction: ltr;
}
/* Wenn der <a> innerhalb von .leaflet-bar haengt, ueberschreiben wir
   alle Default-Leaflet-Bar-Eigenschaften. !important auf width / height
   / line-height notwendig wegen Leaflet's eigenem !important-freien
   aber spezifischeren Default. */
.leaflet-bar a.geolyser-measure-end-action,
.leaflet-touch .leaflet-bar a.geolyser-measure-end-action,
a.geolyser-measure-end-action {
    width: auto !important;
    min-width: 0;
    height: 26px !important;
    line-height: 24px !important;   /* 26 - 2*1px Border */
    padding: 0 10px !important;
    font-size: 0.82em;
    background-color: var(--bg-elevated);
    color: var(--text);
    border: 1px solid var(--border) !important;
    /* die Geoman-Action-Btns erben
 border-radius: var(--radius-sm)=6px aus '.leaflet-bar a' !important.
 Damit der Mess-Beenden gleich rund wirkt, hier ebenfalls 6 px. */
    border-radius: var(--radius-sm, 6px) !important;
    box-shadow: none !important;
    display: inline-block !important;
    vertical-align: top;
    user-select: none;
    text-decoration: none;
    box-sizing: border-box;
    margin-bottom: 0 !important;
    text-align: center;
}
.leaflet-bar a.geolyser-measure-end-action:hover,
.leaflet-bar a.geolyser-measure-end-action:focus,
a.geolyser-measure-end-action:hover,
a.geolyser-measure-end-action:focus {
    background-color: var(--bg-card);
    color: var(--c-primary-hi);
    border-color: var(--c-primary-hi) !important;
    cursor: pointer;
    text-decoration: none;
}
[data-theme="dark"] .leaflet-bar a.geolyser-measure-end-action,
[data-theme="dark"] a.geolyser-measure-end-action {
    background-color: #2c2f33;
    color: #eaeaea;
    border-color: rgba(255, 255, 255, 0.10) !important;
}
[data-theme="dark"] .leaflet-bar a.geolyser-measure-end-action:hover,
[data-theme="dark"] .leaflet-bar a.geolyser-measure-end-action:focus,
[data-theme="dark"] a.geolyser-measure-end-action:hover,
[data-theme="dark"] a.geolyser-measure-end-action:focus {
    background-color: #3b3f44;
    color: var(--c-primary-hi);
    border-color: var(--c-primary-hi) !important;
}
.geolyser-polyops-picker {
    position: fixed;
    left: 50%;
    bottom: 24px;
    transform: translateX(-50%);
    z-index: 8000;
    background: var(--bg-elevated, #fff);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 10px 14px;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.28);
    min-width: 320px;
    text-align: center;
}
.gpop-title {
    font-size: 0.85em;
    font-weight: 600;
    color: var(--text);
    margin-bottom: 8px;
}
.gpop-row {
    display: flex;
    gap: 8px;
    justify-content: center;
    margin-bottom: 6px;
}
.gpop-btn {
    flex: 1;
    padding: 8px 6px;
    background: var(--input-bg);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: 6px;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    font-size: 0.85em;
}
.gpop-btn:hover {
    border-color: var(--accent, #1d72b8);
    color: var(--accent, #1d72b8);
}
.gpop-glyph {
    font-size: 1.4em;
    line-height: 1;
    font-weight: bold;
    font-variant-numeric: tabular-nums;
}
.gpop-label {
    font-size: 0.85em;
}
.gpop-hint {
    font-size: 0.78em;
    color: var(--muted-hi);
    opacity: 0.85;
}

/* Text-Styling-Popover fuer Geoman-Text-Layer. */
.geolyser-text-popover {
    position: absolute;
    z-index: 700;
    background: var(--bg-elevated, #fff);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 8px 8px 10px;
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.22);
    font-size: 0.85em;
    min-width: 220px;
}
.geolyser-text-popover .gtp-row {
    display: flex;
    gap: 6px;
    margin-bottom: 6px;
}
.geolyser-text-popover .gtp-row:last-child { margin-bottom: 0; }
.geolyser-text-popover .gtp-row--inline {
    align-items: center;
}
.geolyser-text-popover .gtp-input {
    background: var(--input-bg);
    color: var(--fg);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 4px 6px;
    font-size: 0.92em;
}
.geolyser-text-popover .gtp-input--text { flex: 1; min-width: 0; }
.geolyser-text-popover .gtp-input--font { flex: 1; min-width: 80px; }
.geolyser-text-popover .gtp-input--color {
    width: 30px;
    height: 26px;
    padding: 1px 2px;
    cursor: pointer;
}
.geolyser-text-popover .gtp-input--size {
    width: 56px;
    font-variant-numeric: tabular-nums;
}
.geolyser-text-popover .gtp-close {
    width: 26px;
    height: 26px;
    background: transparent;
    border: 1px solid var(--border);
    border-radius: 4px;
    color: var(--muted-hi);
    cursor: pointer;
    line-height: 22px;
    font-size: 1.1em;
}
.geolyser-text-popover .gtp-close:hover {
    color: var(--text);
    border-color: var(--text);
}

/* Live-Mess-Tooltip waehrend Geoman-Drawing. */
.geoman-live-tooltip {
    background: rgba(20, 30, 40, 0.92);
    color: #fff;
    padding: 6px 9px;
    border-radius: 5px;
    font-size: 12px;
    line-height: 1.45;
    box-shadow: 0 4px 10px rgba(0,0,0,0.25);
    min-width: 130px;
    font-variant-numeric: tabular-nums;
}
.geoman-live-tooltip .glt-line {
    display: flex;
    justify-content: space-between;
    gap: 10px;
    white-space: nowrap;
}
.geoman-live-tooltip .glt-key {
    color: rgba(255, 255, 255, 0.65);
    font-weight: normal;
    margin-right: 4px;
}
[data-theme="dark"] .geoman-live-tooltip {
    background: rgba(0, 0, 0, 0.85);
}
/* Waehrend Mess-Session sind Geoman + Locate + GPS-Tools
 nicht-anklickbar gesperrt (statt die Messung beim Klick darauf zu
 canceln). Greyed-Out + pointer-events:none, der User soll nicht in
 die Versuchung geraten ein konkurrierendes Tool zu starten. */
.geolyser-measure-active .leaflet-pm-toolbar,
.geolyser-measure-active .leaflet-control-locate,
.geolyser-measure-active #gps-tools {
    opacity: 0.35;
    pointer-events: none;
    filter: grayscale(0.6);
    transition: opacity 0.15s ease, filter 0.15s ease;
}
.geolyser-measure-active .leaflet-pm-toolbar::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: repeating-linear-gradient(
        45deg,
        transparent 0 8px,
        rgba(0,0,0,0.04) 8px 12px
    );
}
.geolyser-measure-panel {
    position: fixed;
    right: 16px;
    bottom: 16px;
    z-index: 1100;
    /* breiter weil der groessere Text mehr
 Platz braucht. */
    width: 340px;
    max-width: calc(100vw - 32px);
    background: var(--bg-card, #fff);
    border: 1px solid var(--border, #ccc);
    border-radius: 10px;
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);
    font-family: var(--font-ui);
    color: var(--text);
    overflow: hidden;
}
/* In-Map-Variante. Liegt oben rechts in der Karte.
 Transparenz-Effekt entfernt (JP 77.15) - voll opaque. */
.geolyser-measure-panel--in-map {
    position: absolute;
    top: 70px;
    right: 12px;
    bottom: auto;
    width: 340px;
    max-width: min(340px, calc(100% - 24px));
    z-index: 850;     /* unterhalb leaflet-control (1000), ueber map-tiles */
    opacity: 1;
}
/* Im Dark-Mode war der Mess-Panel-Hintergrund
 noch transparent (default --bg-card ist im Dark-Mode rgba(255,255,255,0.03)).
 Dadurch sah man die Karte durchscheinen und konnte den Text kaum lesen.
 Wir setzen hier einen solid dunklen Hintergrund inkl. dezentem Border und
 tieferen Shadow, sowie das in-map-Variant-Override. */
[data-theme="dark"] .geolyser-measure-panel,
[data-theme="dark"] .geolyser-measure-panel--in-map {
    background: var(--surface-elevated, #1f2024);
    border-color: rgba(255,255,255,0.14);
    box-shadow: 0 8px 22px rgba(0, 0, 0, 0.55);
}
[data-theme="dark"] .geolyser-measure-head {
    background: rgba(255,255,255,0.05);
    border-bottom-color: rgba(255,255,255,0.10);
}
[data-theme="dark"] .geolyser-measure-tools {
    background: rgba(255,255,255,0.04);
    border-top-color: rgba(255,255,255,0.10);
}
[data-theme="dark"] .geolyser-measure-actions {
    border-top-color: rgba(255,255,255,0.10);
}
/* Tool-Btn als Leaflet-Control (oben links unter Geoman). Icon-Farbe analog Geoman/GPS-Tools - im Dark-Mode hell, im Hover
 tuerkis. img.svg wird per filter-recolor eingefaerbt. */
.geolyser-measure-control .geolyser-measure-toolbtn {
    display: block;
    width: 30px;
    height: 30px;
    color: var(--text);
    text-align: center;
    cursor: pointer;
    background: var(--bg-card, #fff);
}
/* Light-Mode default: Icon dunkel (war SVG default). */
.geolyser-measure-control .geolyser-measure-toolbtn img {
    transition: filter .12s;
}
[data-theme="dark"] .geolyser-measure-control .geolyser-measure-toolbtn img {
    /* Dark-Mode: schwarzes Icon -> weiss invertieren. */
    filter: invert(1) brightness(2);
}
.geolyser-measure-control .geolyser-measure-toolbtn:hover img {
    /* Hover (beide Modes): Icon tuerkis. CSS-Filter-Trick um schwarzes
       SVG in c-primary einzufaerben. invert(31%) sepia(95%) saturate(...)
       hex-rgb 0,160,210 = #00A0D2.  */
    filter: brightness(0) saturate(100%) invert(45%) sepia(94%)
            saturate(2050%) hue-rotate(166deg) brightness(95%) contrast(101%);
}
.geolyser-measure-control .geolyser-measure-toolbtn.is-active {
    background: var(--c-primary-hi, #00B7E8);
}
.geolyser-measure-control .geolyser-measure-toolbtn.is-active img {
    /* Active-State: Icon dunkel auf tuerkis-Background (analog locate.active). */
    filter: brightness(0);
}
.geolyser-measure-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 12px 14px;
    background: var(--bg-elevated, rgba(0,0,0,0.04));
    border-bottom: 1px solid var(--border);
    font-size: 1.12em;
    font-weight: 600;
}
.geolyser-measure-body { padding: 14px 16px; font-size: 1.05em; }
/* Mess-Panel-Schrift weiter rauf -
 's 0.92/0.98/1.02em war immer noch zu klein zum lesen. */
.geolyser-measure-hint { margin: 0 0 12px; font-size: 1.0em; line-height: 1.5; }
.geolyser-measure-stats { display: grid; gap: 8px; font-size: 1.08em; }
.geolyser-measure-stats > div { line-height: 1.5; }
.geolyser-measure-stats b { font-weight: 600; }
.geolyser-measure-volume {
    margin-top: 6px; padding-top: 6px;
    border-top: 1px dashed var(--border);
    color: var(--c-accent, #06829c);
    font-weight: 600;
}
/* Cut/Fill-Volumen-Split. */
.geolyser-measure-volume-split {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin: 4px 0 0;
    font-size: 0.78em;
}
.vol-chip {
    padding: 2px 6px;
    border-radius: 4px;
    border: 1px solid var(--border);
    background: var(--bg-elevated, rgba(0,0,0,0.04));
    white-space: nowrap;
}
.vol-chip--cut {
    background: rgba(220, 80, 80, 0.14);
    border-color: rgba(220, 80, 80, 0.45);
    color: #993030;
}
.vol-chip--fill {
    background: rgba(70, 170, 90, 0.14);
    border-color: rgba(70, 170, 90, 0.45);
    color: #1d6a30;
}
.vol-chip--net {
    background: rgba(70, 130, 200, 0.12);
    border-color: rgba(70, 130, 200, 0.45);
    color: #1f5485;
    font-weight: 600;
}
[data-theme="dark"] .vol-chip--cut { color: #ee9090; }
[data-theme="dark"] .vol-chip--fill { color: #88dca0; }
[data-theme="dark"] .vol-chip--net { color: #88c0e8; }

/* Tooltip auf Cut/Fill/Net-Chips mit Erklaer-SVG. */
.vol-chip.has-tooltip {
    position: relative;
    cursor: help;
}
.vol-chip-tooltip {
    display: none;
    position: absolute;
    bottom: 100%;
    left: 0;
    margin-bottom: 6px;
    z-index: 1200;
    width: 240px;
    padding: 8px 10px;
    background: var(--bg-card, #fff);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: 6px;
    box-shadow: 0 6px 14px rgba(0,0,0,0.25);
    font-size: 0.78em;
    font-weight: 400;
    line-height: 1.4;
    white-space: normal;
    pointer-events: none;
}
.vol-chip.has-tooltip:hover .vol-chip-tooltip,
.vol-chip.has-tooltip:focus .vol-chip-tooltip,
.vol-chip.has-tooltip:focus-within .vol-chip-tooltip {
    display: block;
}
.vol-tooltip-svg {
    display: block;
    width: 100%;
    height: auto;
    margin-top: 6px;
    color: var(--text);
}
[data-theme="dark"] .vol-chip-tooltip {
    background: var(--surface-elevated, #1f2024);
    border-color: rgba(255,255,255,0.12);
}

/* Profilschnitt-Chart. */
.geolyser-profile-chart {
    background: var(--bg-elevated, rgba(0,0,0,0.04));
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 8px;
    overflow-x: auto;
}
.geolyser-profile-chart svg {
    display: block;
    width: 100%;
    height: auto;
    max-height: 360px;
    color: var(--fg);
}
[data-theme="dark"] .geolyser-profile-chart {
    background: rgba(255,255,255,0.04);
}
.geolyser-measure-actions {
    display: flex; flex-wrap: wrap; gap: 6px; justify-content: space-between;
    align-items: center;
    padding: 8px 10px;
    border-top: 1px solid var(--border);
}
/* Mess-Modal Button-Layout-Rework.
 Tools-Reihe (Volume+Profile) zwischen body und actions, Discard mit
 roter BG links, Save kompakt rechts, Undo als kleiner Chip hinter
 Pfadlaenge in renderStats. */
.geolyser-measure-tools {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    padding: 6px 12px 8px;
    border-top: 1px solid var(--border);
    background: var(--bg-elevated, rgba(0,0,0,0.02));
}
.measure-tool-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 10px;
    border-radius: 6px;
    border: 1px solid var(--border);
    background: var(--bg-card);
    color: var(--text);
    font-size: 0.85em;
    font-weight: 500;
    cursor: pointer;
    transition: background .15s, border-color .15s, color .15s;
}
.measure-tool-btn img,
.measure-tool-btn svg {
    width: 16px; height: 16px;
    display: block;
    flex: 0 0 auto;
}
.measure-tool-btn:hover {
    background: var(--bg-hover, rgba(0,0,0,0.05));
    border-color: var(--c-accent, #06829c);
    color: var(--c-accent, #06829c);
}
.measure-tool-btn:disabled,
.measure-tool-btn[disabled] {
    opacity: 0.5;
    cursor: not-allowed;
}
.measure-tool-btn--volume.is-active,
.measure-tool-btn--profile.is-active {
    border-color: var(--c-accent, #06829c);
    color: var(--c-accent, #06829c);
    background: rgba(6, 130, 156, 0.12);
}
[data-theme="dark"] .measure-tool-btn:hover {
    background: rgba(255,255,255,0.05);
}
/* Volumen + Profil-Icons sind PNG/SVG die im Dark-Mode dunkel
 bleiben. Wir invertieren sie via filter, damit sie auf dunklem Background
 sichtbar werden (gleiche Behandlung wie die Sidebar-Icons). */
[data-theme="dark"] .measure-tool-btn img.measure-tool-icon,
[data-theme="dark"] .measure-tool-btn--volume img,
[data-theme="dark"] .measure-tool-btn--profile img,
[data-theme="dark"] .measure-tool-btn--surface img {
    filter: invert(0.9) hue-rotate(180deg);
}
/* Discard-Button mit roter BG, links neben Save. */
.measure-discard-btn {
    background: rgba(220, 80, 80, 0.14) !important;
    border-color: rgba(220, 80, 80, 0.45) !important;
    color: #993030 !important;
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
.measure-discard-btn:hover {
    background: rgba(220, 80, 80, 0.22) !important;
    border-color: rgba(220, 80, 80, 0.65) !important;
}
.measure-discard-btn svg {
    width: 14px; height: 14px;
    flex: 0 0 auto;
}
[data-theme="dark"] .measure-discard-btn {
    color: #ee9090 !important;
}
/* Stats-Reihe mit inline-Undo-Chip hinter Pfadlaenge. */
.measure-stat-row {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}
.measure-stat-row > .measure-stat-text {
    flex: 1 1 auto;
    min-width: 0;
}
.measure-undo-chip {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px; height: 22px;
    padding: 0;
    border-radius: 50%;
    border: 1px solid var(--border);
    background: var(--bg-card);
    color: var(--muted-hi, #555);
    cursor: pointer;
    transition: background .15s, color .15s, border-color .15s;
}
.measure-undo-chip:hover {
    background: var(--bg-hover, rgba(0,0,0,0.06));
    color: var(--c-accent, #06829c);
    border-color: var(--c-accent, #06829c);
}
.measure-undo-chip svg {
    width: 13px; height: 13px;
    display: block;
    color: currentColor;
}
[data-theme="dark"] .measure-undo-chip:hover {
    background: rgba(255,255,255,0.06);
}
/* polish: Mess-Tool Vertex (verschiebbarer Stuetzpunkt). Wir
 nutzen eine divIcon - das Markup kommt aus Leaflet als <div class=
 "geolyser-measure-vertex">, wir rendern den sichtbaren Kreis per
 ::before (statt einer Hintergrundfarbe), damit das Hover-Highlight
 und der Cursor-Style getrennt vom Body laufen. */
.geolyser-measure-vertex {
    cursor: move;
    /* unsichtbare Hit-Box etwas groesser fuer Touch (44px). */
    width: 16px !important;
    height: 16px !important;
    background: transparent !important;
    border: none !important;
    transition: transform .12s;
}
.geolyser-measure-vertex::before {
    content: "";
    position: absolute;
    top: 50%; left: 50%;
    width: 14px; height: 14px;
    transform: translate(-50%, -50%);
    background: #fff;
    border: 2px solid #06829c;
    border-radius: 50%;
    box-shadow: 0 1px 3px rgba(0,0,0,0.4);
    pointer-events: none;
}
.geolyser-measure-vertex:hover {
    transform: scale(1.18);
    z-index: 1000;
}
.geolyser-measure-vertex.leaflet-drag-target::before,
.leaflet-drag-target.geolyser-measure-vertex::before {
    background: #06829c;
}
/* Touch-Geraete: groessere Hit-Box fuer Stuetzpunkte. */
@media (hover: none) and (pointer: coarse) {
    .geolyser-measure-vertex {
        width: 26px !important;
        height: 26px !important;
    }
    .geolyser-measure-vertex::before {
        width: 18px; height: 18px;
        border-width: 3px;
    }
}

.geolyser-measure-actions button { font-size: 0.85em; }
#measure-btn.is-active { color: var(--c-accent, #06829c); }
#measure-btn.is-active svg { color: var(--c-accent, #06829c); }

/* Auto-Geometry-Stats unter dem Namen, vor Bildern. */
.feature-popup-stats {
    display: flex; flex-wrap: wrap; gap: 6px;
    font-size: .82em;
    color: var(--muted-hi);
    margin: 2px 0 6px;
}
/* popup-stat Hintergrund deutlicher,
 weil --bg-card im Dark-Mode quasi transparent ist und die Stats sich
 nicht vom Popup abgehoben haben. Wir nehmen einen tuerkis-Tint
 (Geolyser-Akzent), so wird klar dass das die "Auto-Capture"-Werte
 sind die zur Geometrie gehoeren. */
.popup-stat {
    background: rgba(0, 204, 255, 0.12);
    border: 1px solid rgba(0, 204, 255, 0.40);
    color: var(--text);
    border-radius: 6px;
    padding: 2px 8px;
    white-space: nowrap;
    font-weight: 500;
}
[data-theme="dark"] .popup-stat {
    background: rgba(0, 204, 255, 0.16);
    border-color: rgba(0, 204, 255, 0.50);
}
.popup-tag {
    background: var(--bg-card);
    border: 1px solid var(--border);
    color: var(--muted-hi);
    font-size: .75em;
    padding: 2px 6px;
    border-radius: 999px;
    display: inline-block;
    vertical-align: middle;
}
/* Tag-Klassifizierung mit Farben pro Tag-Typ. */
.popup-tag.tag--user {
    background: rgba(232, 175, 64, 0.18);
    border-color: rgba(232, 175, 64, 0.55);
    color: #8a5d10;
    font-weight: 600;
}
[data-theme="dark"] .popup-tag.tag--user {
    background: rgba(232, 175, 64, 0.20);
    color: #f0c270;
}
.popup-tag.tag--gcp,
.popup-tag.tag--aruco {
    background: rgba(80, 150, 220, 0.16);
    border-color: rgba(80, 150, 220, 0.55);
    color: #1f5485;
}
[data-theme="dark"] .popup-tag.tag--gcp,
[data-theme="dark"] .popup-tag.tag--aruco {
    color: #88c0e8;
}
.popup-tag.tag--imported {
    background: rgba(70, 170, 90, 0.16);
    border-color: rgba(70, 170, 90, 0.55);
    color: #1d6a30;
}
[data-theme="dark"] .popup-tag.tag--imported {
    color: #88dca0;
}
.popup-tag.tag--temp {
    background: rgba(180, 90, 200, 0.16);
    border-color: rgba(180, 90, 200, 0.55);
    color: #6b1f7d;
}
[data-theme="dark"] .popup-tag.tag--temp {
    color: #d088e0;
}
.popup-tag.tag--measure {
    background: rgba(6, 130, 156, 0.16);
    border-color: rgba(6, 130, 156, 0.55);
    color: #045b6e;
}
[data-theme="dark"] .popup-tag.tag--measure {
    color: #6fc4d8;
}
.popup-tag.tag--more {
    background: var(--bg-elevated, rgba(0,0,0,0.06));
    color: var(--muted-hi);
    cursor: help;
    font-style: italic;
    border-style: dashed;
}
[data-theme="dark"] .popup-tag.tag--more {
    background: rgba(255,255,255,0.06);
}
.feature-popup-actions {
    display: flex; gap: 6px;
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px solid var(--border);
}
.feature-popup-actions button {
    flex: 1 1 auto;
    background: transparent; color: var(--fg);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 4px 8px;
    font-size: .85em;
}
.feature-popup-actions button:hover { background: var(--bg-card); border-color: var(--border-hi); }
.feature-popup-actions button.is-destructive { color: var(--c-error); border-color: var(--c-error-bg); }
.feature-popup-actions button.is-destructive:hover { background: var(--c-error-bg); }

/* === Tag-Picker (Feature-Modal, ) ============================ */
.tag-picker {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 6px;
    border: 1px solid var(--c-border);
    border-radius: 8px;
    padding: 8px;
    background: var(--c-bg-input, var(--c-bg-elev));
    min-height: 42px;
}
.tag-picker:focus-within {
    border-color: var(--c-accent);
    box-shadow: 0 0 0 2px var(--c-accent-soft, rgba(0,120,212,.18));
}
.tag-picker-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.tag-picker-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 2px 8px;
    border-radius: 999px;
    background: var(--c-accent-soft, rgba(0,120,212,.14));
    color: var(--c-accent, currentColor);
    font-size: 0.85rem;
    line-height: 1.6;
}
.tag-picker-chip-remove {
    border: 0;
    background: transparent;
    color: inherit;
    cursor: pointer;
    padding: 0;
    font-size: 1rem;
    line-height: 1;
    opacity: 0.7;
}
.tag-picker-chip-remove:hover { opacity: 1; }
.tag-picker-input {
    border: 0;
    outline: 0;
    background: transparent;
    color: inherit;
    width: 100%;
    min-height: 24px;
    font: inherit;
}

/* === Tag-Picker (continued) ========================================== */
.tag-picker-suggestions {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    margin: 0;
    padding: 4px 0;
    list-style: none;
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: 8px;
    box-shadow: 0 6px 20px rgba(0,0,0,.18);
    max-height: 220px;
    overflow-y: auto;
    z-index: 30;
}
.tag-picker-suggestion {
    padding: 6px 10px;
    cursor: pointer;
    font-size: 0.9rem;
}
.tag-picker-suggestion:hover,
.tag-picker-suggestion.is-active {
    background: var(--input-bg);
    color: var(--fg);
}
.tag-picker-suggestion .hint {
    opacity: 0.6;
    font-style: italic;
    margin-left: 6px;
}

/* === Trash-Modal-Tabelle ================================= */
.trash-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.9rem;
}
.trash-table th,
.trash-table td {
    text-align: left;
    padding: 6px 10px;
    border-bottom: 1px solid var(--border);
    vertical-align: top;
}
.trash-table th {
    background: var(--input-bg);
    color: var(--muted-hi);
    font-weight: 600;
}
.trash-table tbody tr:hover td {
    background: var(--input-bg);
}
.trash-table .popup-tag {
    display: inline-block;
    padding: 1px 6px;
    border-radius: 999px;
    background: var(--input-bg);
    font-size: 0.78rem;
    color: var(--muted-hi);
    margin-right: 4px;
}
/* polish runde 4: kleiner Farbpunkt vor dem Layer-Namen im
 Layer-Trash-Tab. */
.trash-table .layer-color-dot {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    margin-right: 8px;
    vertical-align: middle;
    border: 1px solid var(--border);
}

/* "Layerliste leeren"-Dialog mit Tabelle und Per-Layer-Auswahl. Wird
   nur gezeigt wenn es editierte Layer oder Drafts mit Inhalten gibt. */
.clear-layers-card {
    display: flex;
    flex-direction: column;
}
.clear-layers-body {
    padding: 14px 18px 6px;
    overflow: auto;
}
.clear-layers-intro {
    margin: 0 0 12px 0;
    font-size: 0.94em;
    line-height: 1.5;
    color: var(--fg);
}
.clear-layers-table-wrap {
    border: 1px solid var(--border);
    border-radius: 6px;
    overflow: hidden;
}
.clear-layers-table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    font-size: 0.93em;
}
.clear-layers-table thead th {
    background: var(--input-bg);
    color: var(--muted-hi);
    font-weight: 600;
    text-align: left;
    padding: 8px 10px;
    border-bottom: 1px solid var(--border);
    white-space: nowrap;
}
.clear-layers-table .clear-th-color { width: 22px; padding-right: 0; }
.clear-layers-table .clear-th-name  { width: auto; }
.clear-layers-table .clear-th-cb    { width: 110px; text-align: center; }
.clear-layers-table tbody tr + tr td {
    border-top: 1px solid var(--border);
}
.clear-layers-table tbody td {
    padding: 8px 10px;
    vertical-align: middle;
}
.clear-layers-table .clear-cell-color { padding-right: 0; }
.clear-layers-table .clear-cell-color .layer-color-dot {
    display: inline-block;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    border: 1px solid var(--border);
    vertical-align: middle;
}
.clear-layers-table .clear-cell-name-line {
    font-weight: 600;
    color: var(--fg);
    line-height: 1.3;
}
.clear-layers-table .clear-cell-name-meta {
    margin-top: 2px;
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.85em;
}
.clear-layers-table .clear-cell-feat {
    color: var(--muted-hi);
}
.clear-layers-table .clear-cell-cb {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    width: 100%;
    height: 100%;
    padding: 4px 0;
}
.clear-layers-table .clear-cell-cb input[type="checkbox"] {
    width: 18px;
    height: 18px;
    accent-color: var(--accent, #06829c);
    cursor: pointer;
    margin: 0;
}
.clear-layers-table th.clear-th-cb,
.clear-layers-table td:nth-child(3),
.clear-layers-table td:nth-child(4) {
    text-align: center;
}
.clear-layers-table .clear-cell-disabled {
    color: var(--muted);
    text-align: center;
    user-select: none;
}
.clear-layers-table .layer-badge.badge--dirty {
    background: var(--c-amber, #d28b22);
    color: #fff;
    padding: 1px 8px;
    border-radius: 999px;
    font-size: 0.75em;
    font-weight: 600;
    line-height: 1.4;
}
.clear-layers-table .layer-badge.badge--draft {
    background: var(--input-bg);
    color: var(--muted-hi);
    padding: 1px 8px;
    border-radius: 999px;
    font-size: 0.75em;
    font-weight: 600;
    line-height: 1.4;
    border: 1px dashed var(--border);
}
.clear-layers-hint {
    margin: 10px 2px 0 2px;
    font-size: 0.86em;
    color: var(--muted-hi);
}

/* Status-Zeile in Modals (info / error). */
.form-info {
    margin: 0 0 8px 0;
    font-size: 0.85em;
    color: var(--muted-hi);
}
.form-info[data-kind="error"] { color: var(--c-error); }
.form-info[hidden] { display: none; }

/* === Topbar =============================================== */
.topbar-spacer {
    flex: 1 1 auto;
    min-width: 12px;
}
.topbar-right .icon-btn {
    width: 36px;
    height: 36px;
    padding: 0;
}
.topbar-right .icon-btn svg { display: block; }

/* === Admin-Users-Pane ==================================== */
.admin-users-actions {
    display: flex;
    justify-content: flex-end;
    margin-bottom: 12px;
}
.admin-users-table select {
    background: var(--input-bg);
    color: var(--fg);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 4px 6px;
}
.admin-users-row-actions {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
}
.admin-users-row-actions .ghost {
    padding: 4px 8px;
    font-size: 0.85rem;
}
.admin-users-row-actions .danger {
    color: var(--c-error);
    border-color: var(--c-error-bg);
}

.admin-kv th {
    text-align: left;
    font-weight: 500;
    color: var(--muted);
    width: 160px;
    padding: 4px 8px;
}
.admin-kv td {
    padding: 4px 8px;
}

/* === Resizable Sidebar Handles =========================== */
.resizable-handle {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 6px;
    cursor: col-resize;
    background: transparent;
    z-index: 5;
    transition: background 0.15s ease;
}
.resizable-handle--right { right: -3px; }
.resizable-handle--left  { left:  -3px; }
.resizable-handle:hover,
.resizable-handle:focus-visible {
    background: var(--border-hi);
    outline: none;
}
body.is-resizing { cursor: col-resize; user-select: none; }
body.is-resizing iframe { pointer-events: none; }
/* Mobile-E-Fix : alte 720px-Schwelle (Hide-Handle) auf 540px
 * verschoben. So bleibt im Tablet-Range (541-1024px) der Handle aktiv;
 * nur echte Smartphones haben kein Resize. Die spezifische Tablet-
 * Touch-Anpassung liegt im 541-1024px-Block weiter unten. */
@media (max-width: 540px) {
    .resizable-handle { display: none; }
}

/* === Help-Modal =========================================== */
.help-modal-card {
    height: calc(100vh - 96px);
    max-height: 720px;
}
.help-shell {
    flex: 1 1 auto;
    display: flex;
    gap: 16px;
    margin: 8px -8px 0 -8px;
    padding: 0 8px 8px 8px;
    min-height: 0;
}
.help-toc {
    flex: 0 0 200px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    overflow-y: auto;
    padding-right: 8px;
    border-right: 1px solid var(--border);
}
.help-toc-item {
    text-align: left;
    border: 0;
    background: transparent;
    color: var(--muted-hi);
    padding: 8px 12px;
    border-radius: var(--radius-sm);
    cursor: pointer;
    font: inherit;
}
.help-toc-item:hover {
    background: var(--bg-card);
}
.help-toc-item.is-active {
    background: var(--bg-card);
    color: var(--fg);
    font-weight: 500;
}
.help-content {
    flex: 1 1 auto;
    overflow-y: auto;
    padding-right: 8px;
}
/* Liste→Detail-Pattern auf Mobile (max-width: 768px).
 Standardmaessig sieht man die Kapitel-Liste, ein Klick auf ein
 Kapitel zeigt den Inhalt + "Zurueck"-Button. Auf Desktop bleibt
 das gewohnte Side-by-Side-Layout. */
.help-back-btn {
    display: none;
    align-items: center;
    gap: 6px;
    margin: 0 0 8px;
    background: var(--bg-elevated, rgba(0,0,0,0.04));
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 6px 10px;
    cursor: pointer;
    font: inherit;
    color: var(--fg);
}
.help-back-btn:hover { background: var(--bg-card); }
@media (max-width: 768px) {
    .help-shell {
        gap: 0;
        margin: 8px 0 0;
        padding: 0;
        position: relative; /* Anker fuer absolut positionierten back-btn */
    }
    .help-toc {
        flex: 1 1 auto;
        border-right: 0;
        padding-right: 0;
    }
    .help-content {
        flex: 1 1 auto;
        padding: 0;
        position: relative;
    }
    /* Mobile-UI-Refresh : Kapitel-Liste-Items grosser + mehr
 * Touch-Padding . */
    .help-toc-item {
        font-size: 1.05em !important;
        padding: 14px 16px !important;
        min-height: 40px;
    }
    /* Liste→Detail-Toggle ueber .help-shell.is-detail-mode. */
    .help-shell:not(.is-detail-mode) .help-content {
        display: none;
    }
    .help-shell.is-detail-mode .help-toc {
        display: none;
    }
    .help-shell.is-detail-mode .help-back-btn {
        /* Mobile-UI-Refresh : Zurueck-Btn im Detail-View jetzt
 * OBEN RECHTS als kompakter Pfeil-Icon-Button ,
 * statt Block-Element links oben. */
        display: inline-flex !important;
        position: absolute;
        top: 4px;
        right: 4px;
        z-index: 5;
        width: 40px;
        height: 40px;
        padding: 0;
        margin: 0;
        border-radius: 50%;
        justify-content: center;
        align-items: center;
        background: var(--bg-card);
        box-shadow: 0 2px 6px rgba(0,0,0,0.15);
    }
    /* Label-Text im Btn verstecken — nur Pfeil. */
    .help-shell.is-detail-mode .help-back-btn > span:nth-child(2) {
        display: none;
    }
    .help-shell.is-detail-mode .help-back-btn > span:nth-child(1) {
        font-size: 1.5em;
        line-height: 1;
    }
    /* Detail-Content braucht Top-Padding damit der Back-Btn ueber dem
     * Chapter-Titel nicht ueberlagert. */
    .help-shell.is-detail-mode .help-content {
        padding-top: 8px;
    }
    .help-shell.is-detail-mode .help-content .help-chapter-title {
        padding-right: 48px;  /* Platz fuer Back-Btn rechts */
    }
    /* Mobile-EE-Fix Bug+Feedback-Btn jetzt
 * AUCH im Detail-Mode sichtbar (frueher Mobile-UI-Refresh ausgeblendet).
 * JP-Begruendung: User soll waehrend des Lesens einer Anleitung
 * direkt Feedback geben koennen, ohne erst zur Liste zurueck.
 * Alte display:none-Regel auskommentiert / entfernt. */
}

/* Mobile-H-Fix : Help-Modal auf Smartphone/Tablet bulletproof
 * machen. JP-Beschwerde: TOC nicht scrollbar, Footer/Header nicht ueber
 * volle Breite, transparenter Footer (Text vom Listen-Item "halte"
 * bleed-through). Loesung:
 * 1. .help-modal-card auf padding:0 + overflow:hidden setzen, damit
 * Header/Footer von alleine edge-to-edge sitzen und nichts ausser
 * dem Scroll-Container scrollt.
 * 2. Header- und Footer-Negativ-Margins zurueck auf 0 setzen (sonst
 * wuerden sie BEI padding:0 ausserhalb der Card landen).
 * 3. Header + Footer mit explizitem opaken --bg-elevated als
 * Hintergrund (gilt in Light UND Dark, weil --bg-elevated im
 * Gegensatz zu --bg-card nie semi-transparent ist).
 * 4. .help-shell als alleinigen flex-Grow-Container im Card-Body mit
 * overflow:hidden, damit die inneren .help-toc / .help-content
 * sauber scrollen koennen (sonst rutschen sie unter den Footer
 * raus, wenn min-height: 0 in der Flex-Chain nicht durchgereicht
 * wird).
 * 5. .help-toc + .help-content bekommen explizit overflow-y:auto +
 * -webkit-overflow-scrolling:touch + min-height:0, damit iOS-
 * Safari sie auch wirklich scrollt. */
@media (max-width: 768px) {
    .help-modal-card {
        padding: 0 !important;
        overflow: hidden !important;
        height: 100dvh !important;
        max-height: 100dvh !important;
    }
    .help-modal-card > .modal-header {
        margin: 0 !important;
        padding: 12px 16px !important;
        background: var(--bg-elevated) !important;
        border-bottom: 1px solid var(--border);
        flex-shrink: 0;
        position: relative;
        z-index: 2;
    }
    .help-modal-card > .help-shell {
        margin: 0 !important;
        padding: 0 !important;
        flex: 1 1 auto !important;
        min-height: 0 !important;
        overflow: hidden !important;
        display: flex !important;
        flex-direction: column;
    }
    .help-modal-card > .help-shell .help-toc,
    .help-modal-card > .help-shell .help-content {
        overflow-y: auto !important;
        overflow-x: hidden !important;
        -webkit-overflow-scrolling: touch;
        min-height: 0 !important;
        max-height: 100%;
        padding: 8px 12px !important;
        border-right: 0 !important;
    }
    /* Mobile-H2-Fix : Kapitel-Items strikt untereinander.
 * Verhindert, dass ein alterer 720px-Row-Wrap-Regel oder ein
 * Default-Flex-Row die TOC-Items horizontal nebeneinander zieht. */
    .help-modal-card > .help-shell .help-toc {
        display: flex !important;
        flex-direction: column !important;
        flex-wrap: nowrap !important;
        align-items: stretch;
        gap: 4px;
    }
    .help-modal-card > .help-shell .help-toc > .help-toc-item,
    .help-modal-card > .help-shell .help-toc > button[data-chapter] {
        width: 100% !important;
        flex: 0 0 auto !important;
        display: block !important;
    }
    /* Mobile-H3-Fix : Detail-Mode Toggle wiederherstellen.
 * Mein vorheriges `display: flex !important` auf .help-toc hat das
 * `display: none` aus `.help-shell.is-detail-mode .help-toc`
 * komplett ueberschrieben — Klick auf Kapitel hat die TOC sichtbar
 * gelassen und der Detail-View kam nicht hoch. Hier explizit
 * gewinnen lassen. */
    .help-modal-card > .help-shell:not(.is-detail-mode) .help-content {
        display: none !important;
    }
    .help-modal-card > .help-shell.is-detail-mode .help-toc {
        display: none !important;
    }
    .help-modal-card > .help-shell.is-detail-mode .help-content {
        display: block !important;
        flex: 1 1 auto !important;
        overflow-y: auto !important;
        overflow-x: hidden !important;
        min-height: 0 !important;
        max-height: 100%;
        padding: 8px 12px !important;
        position: relative;
    }
    /* Mobile-V-Fix : Den alten inline-Back-Btn (.help-back-btn
 * im content, war absolute oben rechts) auf Smartphone NICHT mehr
 * zeigen — wir nutzen den neuen .modal-back-btn im Header. Auch den
 * .help-chapter-title (doppelte Headline im Body) im Detail-Mode
 * auf Mobile ausblenden, weil der Kapitel-Name jetzt schon im
 * modal-title oben steht. */
    .help-modal-card .help-shell.is-detail-mode .help-back-btn {
        display: none !important;
    }
    .help-modal-card .help-shell.is-detail-mode .help-content .help-chapter-title {
        display: none !important;
    }
    /* Mobile-H3-Fix: Scrollbar im Help-Modal deutlich tuerkis (CI-Cyan
     * #3BBDE8 = --c-cyan), damit JP auf dem Smartphone sofort sieht,
     * dass es noch was zu scrollen gibt. */
    .help-modal-card .help-toc,
    .help-modal-card .help-content {
        scrollbar-color: var(--c-cyan, #3BBDE8) transparent;
        scrollbar-width: thin;
    }
    .help-modal-card .help-toc::-webkit-scrollbar,
    .help-modal-card .help-content::-webkit-scrollbar {
        width: 10px;
        height: 10px;
    }
    .help-modal-card .help-toc::-webkit-scrollbar-track,
    .help-modal-card .help-content::-webkit-scrollbar-track {
        background: transparent;
    }
    .help-modal-card .help-toc::-webkit-scrollbar-thumb,
    .help-modal-card .help-content::-webkit-scrollbar-thumb {
        background: var(--c-cyan, #3BBDE8);
        border-radius: 5px;
        border: 2px solid var(--bg-elevated);
    }
    .help-modal-card .help-toc::-webkit-scrollbar-thumb:hover,
    .help-modal-card .help-content::-webkit-scrollbar-thumb:hover {
        background: #2aa6cf;
    }
    .help-modal-card > .help-modal-footer,
    .help-modal-card > .modal-footer.help-modal-footer {
        margin: 0 !important;
        padding: 10px 12px !important;
        background: var(--bg-elevated) !important;
        border-top: 1px solid var(--border);
        flex-shrink: 0;
        position: relative;
        z-index: 2;
        width: 100%;
    }
}
.help-content h4 {
    margin-top: 22px;
    margin-bottom: 8px;
    font-size: 1.05em;
}
.help-content h4:first-child {
    margin-top: 0;
}
.help-content ul {
    margin: 8px 0 16px 0;
    padding-left: 20px;
}
.help-content li {
    margin-bottom: 6px;
    line-height: 1.5;
}
.help-content p {
    margin: 0 0 14px 0;
    line-height: 1.55;
}
.help-content code {
    background: var(--input-bg);
    padding: 1px 6px;
    border-radius: 3px;
    font-size: 0.92em;
}

/* Inline button styled as link — fuer "Vollen Lizenztext anzeigen" o.ae.
   Sieht aus wie ein <a>, oeffnet aber ein Popup-Modal statt einer
   Plain-Text-Seite in einem neuen Tab. */
.link-like {
    background: none;
    border: 0;
    padding: 0;
    margin: 0;
    color: var(--accent, #06829c);
    text-decoration: underline;
    cursor: pointer;
    font: inherit;
    display: inline;
}
.link-like:hover,
.link-like:focus-visible {
    color: var(--accent-hover, #08a0c0);
    text-decoration: underline;
    outline: none;
}

/* Polished permissions table — used in the "roles" chapter of the
   in-app help. Sticky header, alternating rows, soft borders, and
   highlighted "alle / nur eigene" cells via column-keyword styling. */
.help-content .perm-table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    margin: 12px 0 18px;
    font-size: 0.93em;
    border: 1px solid var(--border);
    border-radius: 6px;
    overflow: hidden;
}
.help-content .perm-table thead th {
    background: var(--input-bg);
    color: var(--muted-hi);
    text-align: left;
    padding: 8px 10px;
    font-weight: 600;
    border-bottom: 1px solid var(--border);
}
.help-content .perm-table thead th:not(:first-child) {
    text-align: center;
    font-size: 0.92em;
}
.help-content .perm-table tbody td {
    padding: 7px 10px;
    border-bottom: 1px solid var(--border);
    vertical-align: middle;
}
.help-content .perm-table tbody tr:last-child td {
    border-bottom: none;
}
.help-content .perm-table tbody tr:nth-child(even) td {
    background: rgba(0, 0, 0, 0.025);
}
[data-theme="dark"] .help-content .perm-table tbody tr:nth-child(even) td {
    background: rgba(255, 255, 255, 0.025);
}
.help-content .perm-table tbody td:not(:first-child) {
    text-align: center;
    color: var(--muted-hi);
}
.help-content .perm-yes {
    color: #4CAF50;
    font-weight: 600;
}
.help-content .perm-no {
    color: var(--muted, #888);
}
.help-content .perm-partial {
    color: #d99a3a;
    font-style: italic;
}

/* Mobile-H2-Fix : Frueher waren die Kapitel im Help-TOC
 * auf ≤720px als horizontale Chip-Reihe (flex-direction: row + wrap)
 * dargestellt — JP will sie aber rein vertikal untereinander, damit
 * man nur vertikal scrollt. row → column. */
@media (max-width: 720px) {
    .help-shell {
        flex-direction: column;
    }
    .help-toc {
        flex: 0 0 auto;
        flex-direction: column;
        flex-wrap: nowrap;
        border-right: 0;
        border-bottom: 1px solid var(--border);
        padding-bottom: 8px;
    }
}

/* === Tristate-Filter ===================================== */
.features-panel-popover-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 4px 6px;
}
.features-panel-popover-label {
    flex: 1 1 auto;
    font-size: 0.9em;
    overflow: hidden;
    text-overflow: ellipsis;
}
.features-panel-tristate {
    display: inline-flex;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    overflow: hidden;
    flex: 0 0 auto;
}
.features-panel-tristate-btn {
    border: 0;
    background: transparent;
    color: var(--muted-hi);
    padding: 2px 8px;
    font: inherit;
    font-weight: 600;
    line-height: 1.4;
    cursor: pointer;
    min-width: 24px;
    border-right: 1px solid var(--border);
}
.features-panel-tristate-btn:last-child { border-right: 0; }
.features-panel-tristate-btn:hover { background: var(--bg-card); }
.features-panel-tristate-btn.is-active {
    background: var(--c-primary);
    color: var(--c-light);
}
.features-panel-tristate-btn.is-active[data-state="not"] {
    background: var(--c-error);
}

/* === Resizable-Grip ===================================== */
.resizable-handle {
    display: flex;
    align-items: center;
    justify-content: center;
}
.resizable-grip {
    display: flex;
    flex-direction: column;
    gap: 3px;
    opacity: 0.35;       /* permanent dezent sichtbar */
    transition: opacity 0.2s ease;
}
.resizable-handle:hover .resizable-grip,
.resizable-handle:focus-visible .resizable-grip {
    opacity: 0.85;
}
.resizable-grip span {
    width: 4px;
    height: 4px;
    border-radius: 50%;
    background: var(--fg);
}

/* === Layer-Tree ========================================= */
.layer-expand {
    border: 0;
    background: transparent;
    color: var(--muted-hi);
    cursor: pointer;
    padding: 4px;
    line-height: 0;
    flex: 0 0 24px;
    border-radius: var(--radius-sm);
    transition: background .12s ease, color .12s ease;
}
.layer-expand:hover {
    color: var(--fg);
    background: var(--bg-card);
}

/* === Feature-Bilder ====================================== */
.image-slots {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 6px;
}
.image-slot {
    position: relative;
    aspect-ratio: 1 / 1;
    border: 1px dashed var(--border);
    border-radius: var(--radius-sm);
    background: var(--input-bg);
    cursor: pointer;
    overflow: hidden;
    color: var(--muted-hi);
    display: flex; align-items: center; justify-content: center;
    font-size: 1.4em;
}
.image-slot:hover { background: var(--bg-card); border-color: var(--border-hi); }
.image-slot.is-filled { cursor: default; border-style: solid; }
/* Bild ist zur Loeschung markiert (wird beim Save geloescht).
 Visuell: roter Border + halb-transparent + diagonale Streifen-Overlay. */
.image-slot.is-pending-delete {
    border-color: var(--c-danger, #c44) !important;
    border-style: solid;
    box-shadow: inset 0 0 0 2px rgba(196, 68, 68, 0.45);
}
.image-slot.is-pending-delete img {
    opacity: 0.45;
    filter: grayscale(0.6);
}
.image-slot.is-pending-delete::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: repeating-linear-gradient(
        45deg,
        transparent 0 8px,
        rgba(196, 68, 68, 0.18) 8px 14px
    );
}
.image-slot.is-pending-delete .image-slot-remove {
    background: var(--c-amber, #c98a00);
    color: #fff;
    font-size: 1.05em;
}
.image-slot img {
    width: 100%; height: 100%; object-fit: cover; display: block;
}
.image-slot-remove {
    position: absolute;
    top: 2px; right: 2px;
    width: 22px; height: 22px;
    border-radius: 999px;
    border: 0;
    background: rgba(0,0,0,0.55);
    color: white;
    cursor: pointer;
    line-height: 1;
    font-size: 0.85em;
    padding: 0;
}

/* Popup: Thumbnail-Reihe unter description */
.feature-popup-images {
    display: flex; gap: 4px; flex-wrap: wrap;
    margin-top: 8px;
}
.feature-popup-images img {
    width: 48px; height: 48px;
    object-fit: cover;
    border-radius: 4px;
    cursor: pointer;
    border: 1px solid var(--border);
}

/* Lightbox */
/* !important + id-Spezifitaet, weil eine generische Mobile-Regel
 * `@media (max-width:1024px) .modal { background: transparent !important }`
 * sonst den dunklen Backdrop der Lightbox entfernt (greift in Hoch- UND
 * Querformat auf Tablet/Smartphone). -webkit-Prefix fuer iOS-Safari. */
#image-lightbox.modal {
    background: rgba(0, 0, 0, 0.88) !important;
    -webkit-backdrop-filter: blur(5px) !important;
    backdrop-filter: blur(5px) !important;
    /* Generische Mobile-Regeln setzen `.modal { align-items: stretch }`
     * (fuer Vollbild-modal-cards). Das wuerde die Lightbox-Card auf volle
     * Hoehe ziehen und die Buttons an den Screen-Rand statt an die
     * Bildecken schieben. Daher hier zentrieren erzwingen. */
    align-items: center !important;
    justify-content: center !important;
}
.lightbox-card {
    position: relative;
    max-width: 95vw;
    /* dvh statt vh: auf Mobile (Portrait) ist die mobile Browser-URL-
     * Leiste in `vh` NICHT eingerechnet — ein 95vh-hohes Bild wurde
     * dadurch hoeher als der sichtbar nutzbare Bereich und zentrierte
     * sich teilweise HINTER die URL-Leiste/Notch. Die absolut
     * positionierten Buttons (top:8px) wanderten so aus dem sichtbaren
     * Viewport. `dvh` rechnet die dynamische Browser-Chrome ein. */
    max-height: 95dvh;
    display: flex; align-items: center; justify-content: center;
}
.lightbox-card img {
    max-width: 95vw;
    max-height: 95dvh;
    object-fit: contain;
    border-radius: var(--radius-sm);
    box-shadow: 0 20px 80px rgba(0,0,0,0.7);
}
.lightbox-close {
    position: absolute;
    top: 8px;
    right: 8px;
    z-index: 10;
}
/* Schliessen-Button: in BEIDEN Themes dunkelroter Hintergrund mit
 * weissem X; beim Hover leuchtet er hellrot auf. Frueher hat die
 * globale .modal-close-btn-!important-Regel den Button im Hellmodus
 * hellrosa und im Darkmodus quasi transparent gemacht (rotes X ueber
 * dunklem Bild = unsichtbar). Der #image-lightbox-Scope (Spezifitaet
 * 1,1,0 bzw. mit [data-theme] 1,2,0) gewinnt gegen die globalen
 * .modal-close-btn-Regeln und deren Theme-Varianten. */
#image-lightbox .lightbox-close,
[data-theme="light"] #image-lightbox .lightbox-close,
[data-theme="dark"] #image-lightbox .lightbox-close {
    background: #8a1414 !important;
    color: #fff !important;
    border: 1px solid rgba(255, 255, 255, 0.25) !important;
}
#image-lightbox .lightbox-close:hover,
[data-theme="light"] #image-lightbox .lightbox-close:hover,
[data-theme="dark"] #image-lightbox .lightbox-close:hover {
    background: #e23b2e !important;
    border-color: #ff8088 !important;
    color: #fff !important;
    box-shadow: 0 0 14px rgba(226, 59, 46, 0.8) !important;
}

/* a: Inhalt-melden-Button im Lightbox - links oben, dezent rot. */
.lightbox-report {
    position: absolute;
    top: 8px;
    left: 8px;
    background: rgba(0, 0, 0, 0.55);
    color: white;
    border: 1px solid rgba(255, 92, 101, 0.7);
    border-radius: var(--radius-sm, 6px);
    padding: 6px 12px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 0.85em;
    cursor: pointer;
    z-index: 10;
}
.lightbox-report:hover {
    background: var(--c-error, #ff5c65);
    border-color: var(--c-error, #ff5c65);
}
.lightbox-report svg { display: block; }
/* a-Hotfix2: Visueller Lock-State, wenn das Bild bereits gemeldet
 * ist. Der Button bleibt sichtbar, aber gruengrau und nicht klickbar. */
.lightbox-report.is-reported,
.lightbox-report.is-reported:hover {
    background: rgba(0, 0, 0, 0.5);
    border-color: rgba(255, 255, 255, 0.3);
    color: rgba(255, 255, 255, 0.7);
    cursor: default;
}
.lightbox-report.is-sending,
.lightbox-report.is-sending:hover {
    background: rgba(0, 0, 0, 0.55);
    border-color: rgba(255, 255, 255, 0.3);
    cursor: wait;
}

/* Mobile (Portrait): Bug-Fix — Schliessen- + Melden-Button waren bei
 * hochkant gehaltenem Smartphone nicht sichtbar (das vollstaendige
 * Bild aber schon). Ursache: das Bild wurde 95vh hoch zentriert und
 * lag mit seinem oberen Rand teils hinter Notch/URL-Leiste; die
 * Buttons sassen dadurch ausserhalb des sichtbaren Viewports. Fix:
 * die Card nimmt die volle sichere Hoehe ein, das Bild bekommt oben
 * einen reservierten Streifen (Safe-Area + Button-Hoehe), und die
 * Buttons werden mit env(safe-area-inset-*) nach innen versetzt. So
 * liegen sie garantiert im sichtbaren Bereich, ueber dem Bild. */
/* Mobile (Portrait): Die Card umschliesst weiterhin nur das Bild und
 * wird im (dunklen) Backdrop zentriert — so sitzen Schliessen- und
 * Melden-Button an den oberen BILD-Ecken (nicht am Screen-Rand). Das
 * Bild wird etwas niedriger gehalten (88dvh) und die Buttons bekommen
 * eine Safe-Area-Reserve, damit sie auf Notch-Geraeten frei liegen. */
@media (max-width: 768px) {
    .lightbox-card {
        max-width: 96vw;
        max-height: 88dvh;
    }
    .lightbox-card img {
        max-width: 96vw;
        max-height: 88dvh;
    }
    .lightbox-close {
        top: calc(6px + env(safe-area-inset-top, 0px));
        right: 6px;
    }
    .lightbox-report {
        top: calc(6px + env(safe-area-inset-top, 0px));
        left: 6px;
    }
}

/* === Polish ============================================== */

/* Login: Submit-Button mehr Abstand zum Passwort-Feld */
.login-actions {
    margin-top: 18px;
    display: flex;
    justify-content: stretch;
}
.login-actions .primary { width: 100%; padding: 12px 18px; }

/* Map-Error: fester Hintergrund (war transparent durch backdrop-blur) */
.map-error {
    background: var(--bg-elevated) !important;
    color: var(--c-error);
    border: 1px solid var(--c-error);
    padding: 8px 14px;
    border-radius: var(--radius);
    box-shadow: var(--shadow-card);
}

/* Features-Panel: Header-Buttons gleich gross + collapse links statt rechts */
.features-panel-head {
    display: flex;
    align-items: center;
    gap: 6px;
}
.features-panel-collapse,
.features-panel-fullscreen,
.features-panel-rail-toggle,
.features-panel-rail-db {
    width: 32px;
    height: 32px;
    padding: 0;
    line-height: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--muted-hi);
    cursor: pointer;
}
.features-panel-collapse:hover,
.features-panel-fullscreen:hover,
.features-panel-rail-toggle:hover,
.features-panel-rail-db:hover {
    background: var(--bg-card);
    color: var(--fg);
}
/* collapse links vom Title platzieren (per order) */
.features-panel-head .features-panel-collapse { order: -1; }
.features-panel-head .features-panel-title { flex: 1 1 auto; }

/* Filter-Bar mehr Abstand zum Rand */
.features-panel-filters {
    padding: 0 12px 8px 12px;
}

/* Resize-Grip: ein paar Pixel weiter weg vom Rand */
.resizable-handle--right { right: -5px; }
.resizable-handle--left  { left:  -5px; }

/* Datenbank-List-Item: Layout fix - Punkt + Vollname + Tags inline */
.features-panel-item {
    display: grid;
    grid-template-columns: auto auto 1fr;
    align-items: center;
    gap: 8px;
    padding: 6px 12px;
    cursor: pointer;
    border-bottom: 1px solid var(--border);
}
.features-panel-item:hover { background: var(--bg-card); }
.features-panel-item.is-active { background: var(--bg-card); border-left: 2px solid var(--c-primary-hi); }
.features-panel-checkbox { margin: 0; }
.features-panel-dot {
    width: 12px; height: 12px;
    border-radius: 50%;
    flex: 0 0 auto;
}
.features-panel-item-body {
    min-width: 0;
}
.features-panel-name {
    font-size: 0.95em;
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Layer/@-Zeile bleibt in der DOM aber ist optional sichtbar - JP wollte sie weg */
.features-panel-item .features-panel-meta { display: none; }
/* Tags im DB-Sidepanel sind strikt einzeilig. Was nicht
 reinpasst, wandert in einen +N-Chip (siehe fitTagsOneLine in
 features-panel.js). Daher flex-wrap:nowrap + overflow:hidden. */
.features-panel-tags {
    display: flex;
    flex-wrap: nowrap;
    overflow: hidden;
    gap: 4px;
    margin-top: 2px;
    min-width: 0;
    max-width: 100%;
}
.features-panel-tag {
    font-size: 0.75em;
    padding: 1px 6px;
    border-radius: 999px;
    background: var(--bg-card);
    color: var(--muted-hi);
    white-space: nowrap;
    flex: 0 0 auto;
}
.features-panel-tag[hidden] { display: none !important; }
.features-panel-tag-more {
    font-size: 0.75em;
    color: var(--muted);
    font-style: italic;
    flex: 0 0 auto;
    white-space: nowrap;
}

/* Layer-Tree: expandierte Sub-Liste nicht ueber den Buttons - Layer-Row als
 * grid mit klar getrennten Zeilen (Toggle-Reihe oben, Sub-Liste darunter).
 * l: zusaetzliche Spalte ganz links fuer den Drag-Handle. */
.layer-row {
    display: grid;
    /* zusaetzliche Spalte "presence" zwischen meta
 und toggles fuer den Avatar-Stack der Coworker, die diesen Layer
 offen haben. Spalte ist "auto" - leer = 0 px breit, mit Inhalt
 waechst sie auf Stack-Breite. */
    grid-template-columns: auto auto auto 1fr auto auto auto;
    /* zusaetzliche Reihe "agg" fuer das Layer-Aggregat
 (Σ Flaeche, Σ Volumen ...). Ohne diese Reihe wandert das Aggregat
 per Auto-Placement in den ersten freien Slot und schiebt Expand-
 Btn + Name aus der ersten Zeile raus. */
    /* menu DIREKT unter dem Header-Row, vor
 * der features-Liste — sonst muss man bei expanded Layer durch die
 * gesamte Feature-Liste scrollen um zum Menu zu kommen. Reihen-
 * folge: header → menu → features → agg. */
    grid-template-areas:
        "drag expand swatch name meta presence toggles"
        "menu   menu   menu   menu   menu   menu   menu"
        "features features features features features features features"
        "agg    agg    agg    agg    agg    agg    agg";
    align-items: center;
    gap: 4px;
    padding: 4px 6px;
    position: relative;
}
.layer-row .layer-drag-handle { grid-area: drag; }
.layer-row .layer-expand   { grid-area: expand; }
.layer-row .layer-swatch   { grid-area: swatch; }
.layer-row .layer-name     { grid-area: name; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: left; background: transparent; border: 0; color: inherit; padding: 0; cursor: pointer; }
.layer-row .layer-meta     { grid-area: meta; color: var(--muted); font-size: 0.85em; }
.layer-row .layer-presence-stack { grid-area: presence; }
.layer-row .layer-toggles  { grid-area: toggles; display: inline-flex; gap: 2px; }
.layer-row .layer-menu     { grid-area: menu; }
.layer-row .layer-features { grid-area: features; margin: 4px 0 6px 28px; }
.layer-row .layer-features-aggregate { grid-area: agg; }
.layer-row .layer-active-users        { grid-area: agg; }

/* Avatar-Stack der Coworker, die einen Layer
 aktuell geoeffnet haben. Verwendet in der Sidebar (.layer-row) UND
 im Lade-Modal (.load-modal-row). Chips ueberlappen um -6px (gestapelt
 mit zarter weisser Border, OneNote-Style). Bei mehr als drei aktiven
 Coworkern wird ein "+N"-Pille angehaengt. */
.layer-presence-stack {
    display: inline-flex;
    flex-direction: row;
    align-items: center;
    padding: 0 2px 0 4px;
    margin: 0;
    /* Stack-Optik: jeder Chip nach dem ersten haengt -6px in den
       vorherigen rein. */
}
.layer-presence-stack:empty { display: none; }
.layer-presence-chip {
    width: 22px; height: 22px;
    border-width: 2px;
    /* OneNote-Stack-Look: kleine weisse Border um den Chip, damit der
       Overlap als sauberer Stack lesbar bleibt - auch im Dark-Theme. */
    box-shadow: 0 0 0 1.5px var(--bg-card, #fff);
    margin-left: -6px;
    transition: transform 0.12s ease;
}
.layer-presence-chip:first-child { margin-left: 0; }
.layer-presence-chip:hover {
    transform: translateY(-1px) scale(1.06);
    z-index: 2;
}
.layer-presence-more {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-left: -6px;
    min-width: 22px; height: 22px;
    padding: 0 6px;
    border-radius: 11px;
    background: var(--bg-elevated, rgba(0, 0, 0, 0.08));
    color: var(--muted-hi, #555);
    font-size: 10px;
    font-weight: 700;
    line-height: 1;
    border: 1.5px solid var(--bg-card, #fff);
    box-shadow: 0 0 0 1px var(--border, rgba(0, 0, 0, 0.12));
    cursor: help;
}
[data-theme="dark"] .layer-presence-chip {
    box-shadow: 0 0 0 1.5px var(--surface-elevated, #2a2a2a);
}
[data-theme="dark"] .layer-presence-more {
    background: var(--surface-elevated, #2a2a2a);
    color: #b8c0c8;
    border-color: var(--surface-elevated, #2a2a2a);
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.18);
}
/* Mobile: schmalere Chips (analog zur Topbar-Presence-Bar). */
@media (max-width: 768px) {
    .layer-presence-chip,
    .layer-presence-more {
        width: 18px; height: 18px;
        min-width: 18px;
        font-size: 9px;
    }
    .layer-presence-chip { margin-left: -5px; }
    .layer-presence-more { margin-left: -5px; padding: 0 5px; }
}

/* Sprach-Toggle in der Topbar. Zeigt die Flagge der
 * aktuell aktiven Sprache; Klick toggelt. */
.lang-toggle .lang-flag {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 0;
}
.lang-toggle .lang-flag svg {
    border-radius: 2px;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.18);
}

/* o: Service-Worker-Update-Toast. */
.sw-update-toast {
    position: fixed;
    left: 50%;
    bottom: 24px;
    transform: translateX(-50%);
    z-index: 1900;
    background: var(--bg-elevated);
    color: var(--fg);
    border: 1px solid var(--border-hi);
    border-radius: 999px;
    padding: 8px 8px 8px 18px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
    display: flex;
    align-items: center;
    gap: 10px;
    animation: sw-update-toast-in .25s ease-out;
}
.sw-update-toast.is-leaving {
    animation: sw-update-toast-out .22s ease-in forwards;
}
@keyframes sw-update-toast-in {
    from { opacity: 0; transform: translate(-50%, 12px); }
    to   { opacity: 1; transform: translate(-50%, 0); }
}
@keyframes sw-update-toast-out {
    from { opacity: 1; transform: translate(-50%, 0); }
    to   { opacity: 0; transform: translate(-50%, 12px); }
}
.sw-update-toast-text { font-size: 0.95em; }
.sw-update-toast-action {
    border: 0;
    background: var(--c-primary, #2c8ee0);
    color: var(--c-light, #fff);
    border-radius: 999px;
    padding: 6px 14px;
    font-size: 0.92em;
    font-weight: 500;
    cursor: pointer;
}
.sw-update-toast-action:hover { filter: brightness(1.07); }
.sw-update-toast-close {
    border: 0;
    background: transparent;
    color: var(--muted-hi);
    cursor: pointer;
    padding: 4px 8px;
    font-size: 1.2em;
    line-height: 1;
}
.sw-update-toast-close:hover { color: var(--fg); }

/* n: Touch-Marker-Helper. Crosshair wird genau ueber der Karten-
 * Mitte fixiert; das Pin-Icon-Anchor des Markers landet dann genau auf
 * dem Karten-Center, das via map.getCenter abgeholt wird. */
.touch-marker-helper {
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 650;       /* ueber den Tiles, unter Modals (2000). */
}
.touch-marker-crosshair {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    color: var(--c-error, #d8493b);
    pointer-events: none;
    filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.45));
}
.touch-marker-place-btn {
    position: absolute;
    left: 50%;
    bottom: 24px;
    transform: translateX(-50%);
    padding: 12px 22px;
    border: 1px solid var(--c-error, #d8493b);
    background: var(--c-error, #d8493b);
    color: var(--c-light, #fff);
    border-radius: 999px;
    font-size: 1em;
    font-weight: 500;
    cursor: pointer;
    pointer-events: auto;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.35);
    -webkit-tap-highlight-color: transparent;
}
.touch-marker-place-btn:active { transform: translateX(-50%) scale(0.97); }

/* l: Drag-Handle + Drop-Indikator. */
.layer-drag-handle {
    background: transparent;
    border: 0;
    color: var(--muted);
    width: 18px;
    height: 22px;
    padding: 0;
    cursor: grab;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    opacity: 0.55;
    touch-action: none;   /* Pointer-Events sollen NICHT als Scroll gewertet werden. */
}
.layer-row:hover .layer-drag-handle,
.layer-drag-handle:focus-visible { opacity: 1; }
.layer-drag-handle:active { cursor: grabbing; }

.layer-row.is-dragging {
    opacity: 0.55;
    background: var(--bg-card);
}
.sidebar-list.is-reordering { user-select: none; }
.layer-row.is-drop-before::before,
.layer-row.is-drop-after::after {
    content: "";
    position: absolute;
    left: 6px;
    right: 6px;
    height: 2px;
    background: var(--c-primary, #2c8ee0);
    border-radius: 2px;
    pointer-events: none;
}
.layer-row.is-drop-before::before { top: -1px; }
.layer-row.is-drop-after::after   { bottom: -1px; }

/* Drag&Drop fuer Features in der Sidebar. Drag-Handle
 pro Feature-Item; Drop-Indikatoren in der Feature-Liste; Hervorhebung
 des Ziel-Layers wenn ein Feature in einen anderen Layer gezogen wird;
 Cursor + Copy-Indikator wenn Strg/Cmd gedrueckt ist. */
.layer-feature-drag-handle {
    background: transparent;
    border: 0;
    color: var(--muted, #888);
    cursor: grab;
    padding: 2px;
    margin-right: 2px;
    line-height: 0;
    border-radius: var(--radius-sm);
    flex: 0 0 auto;
}
.layer-feature-drag-handle:hover { color: var(--fg); background: var(--bg-card); }
.layer-feature.is-feat-dragging {
    opacity: 0.55;
    cursor: grabbing;
}
.layer-features.is-feat-reordering .layer-feature { transition: transform 0.08s ease; }
.layer-feature.is-drop-before { box-shadow: 0 -2px 0 var(--c-primary, #06829c) inset; }
.layer-feature.is-drop-after  { box-shadow: 0 2px 0 var(--c-primary, #06829c) inset; }
.layer-row.is-drop-feature-target {
    outline: 2px dashed var(--c-primary, #06829c);
    outline-offset: -2px;
    background: rgba(0, 204, 255, 0.06);
}
body.is-feat-reordering,
.layer-features.is-feat-reordering.is-feat-copy {
    cursor: copy;
}
/* Immortal-Checkbox + Clone-Btn-Zeile im Feature-Modal. */
.feature-modal-immortal-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 6px 0;
    border-top: 1px dashed var(--border, rgba(0, 0, 0, 0.12));
    border-bottom: 1px dashed var(--border, rgba(0, 0, 0, 0.12));
    margin: 8px 0;
}
.feature-modal-immortal-label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    color: var(--muted-hi, #555);
    font-size: 0.9em;
}
.feature-modal-immortal-label input[type="checkbox"]:checked + span {
    color: var(--c-primary, #06829c);
    font-weight: 600;
}
#feature-modal-clone-btn {
    /* KEIN margin-left:auto mehr — der Btn ist jetzt im
 Footer und soll direkt neben dem Cancel-Btn stehen, nicht durch
 einen auto-margin nach ganz rechts geschoben. */
    display: inline-flex;
    gap: 6px;
    align-items: center;
    width: auto;
    height: auto;
}

.layer-features.is-feat-copy::after {
    content: "+ Kopieren (Strg/Cmd)";
    position: fixed;
    bottom: 16px; left: 50%;
    transform: translateX(-50%);
    background: var(--c-primary, #06829c);
    color: #fff;
    font-size: 11px;
    font-weight: 600;
    padding: 3px 8px;
    border-radius: 999px;
    z-index: 1500;
    pointer-events: none;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
}

/* ---- Confirm-Dialog im App-Design ---- */
.modal-card--sm {
    width: min(420px, 92vw);
}
/* Konflikt-Modal — etwas breiter als confirm, damit
 die Diff-Tabelle zwei Spalten (lokal / Server) sauber nebeneinander
 bekommt. */
.modal-card--md {
    width: min(640px, 96vw);
}
.modal--conflict .conflict-card {
    padding: 22px 22px 18px;
    position: relative;
}
.modal--conflict .conflict-subtitle {
    margin-top: 2px;
    color: var(--muted-hi, #555);
}
.modal--conflict .conflict-version {
    margin: 6px 0 12px;
    font-size: 0.85em;
    color: var(--muted);
}
.modal--conflict .conflict-diff-table {
    width: 100%;
    border-collapse: collapse;
    margin: 8px 0 14px;
    font-size: 0.92em;
}
.modal--conflict .conflict-diff-table th,
.modal--conflict .conflict-diff-table td {
    text-align: left;
    padding: 6px 8px;
    border-bottom: 1px solid var(--border, rgba(0, 0, 0, 0.08));
    vertical-align: top;
    word-break: break-word;
}
.modal--conflict .conflict-diff-table thead th {
    font-size: 0.75em;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--muted-hi);
    background: var(--bg-elevated, rgba(0, 0, 0, 0.04));
}
.modal--conflict .conflict-diff-row.is-same .conflict-diff-local,
.modal--conflict .conflict-diff-row.is-same .conflict-diff-server {
    color: var(--muted);
}
.modal--conflict .conflict-diff-local {
    background: rgba(255, 200, 80, 0.10);
}
.modal--conflict .conflict-diff-server {
    background: rgba(80, 180, 255, 0.10);
}
[data-theme="dark"] .modal--conflict .conflict-diff-local {
    background: rgba(255, 200, 80, 0.16);
}
[data-theme="dark"] .modal--conflict .conflict-diff-server {
    background: rgba(80, 180, 255, 0.16);
}
.modal--conflict .conflict-diff-null {
    color: var(--muted);
    font-style: italic;
}
.modal--conflict .conflict-actions {
    display: flex;
    gap: 8px;
    justify-content: flex-end;
    flex-wrap: wrap;
}
.modal--conflict .conflict-actions .conflict-btn-cancel {
    margin-right: auto;
}
@media (max-width: 540px) {
    .modal--conflict .conflict-actions {
        flex-direction: column-reverse;
        align-items: stretch;
    }
    .modal--conflict .conflict-actions .conflict-btn-cancel {
        margin-right: 0;
    }
}
.confirm-card {
    padding: 22px 24px 18px;
}
.confirm-card .modal-title {
    font-size: 1.08em;
    margin-bottom: 0;
}
/* Modal-Header in .confirm-card: kein doppeltes Margin (.modal-header
   pullt sich schon -22px hoch, das reicht). */
.confirm-card .modal-header {
    margin-bottom: 14px;
}
.confirm-card .confirm-message {
    color: var(--muted-hi);
    margin: 0 0 18px 0;
    line-height: 1.45;
    white-space: pre-wrap;
}
.confirm-card .modal-actions {
    margin-top: 0;
}
/* c-rev: optionale Bestaetigungs-Checkbox im Confirm-Dialog. */
.confirm-checkbox {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    margin: 0 0 14px 0;
    color: var(--fg);
    font-size: 0.92em;
    line-height: 1.4;
    cursor: pointer;
}
.confirm-checkbox input[type="checkbox"] {
    margin-top: 3px;
    accent-color: var(--c-error, #d8493b);
    flex-shrink: 0;
}
/* Danger-Variante (rot) fuer destruktive Bestaetigungen.
 * Greift auf .primary, damit die Hover/Disabled-Logik bestehen bleibt. */
.primary.danger {
    background: var(--c-error);
    border-color: var(--c-error);
    color: var(--c-light);
}
.primary.danger:hover {
    background: var(--c-error-bg, var(--c-error));
    filter: brightness(1.1);
}
.primary.danger:disabled {
    background: var(--c-error);
    opacity: 0.6;
}

/* ---- DB-Modal-Filter-Bar ---- */
/* kein eigener background mehr — die Filter-Bar liegt
 bewusst transparent ueber dem Modal-Hintergrund. Padding links/rechts
 raus, damit das Such-Input direkt an die Modal-Card-Innenkante schliesst
 (= buendig mit der Tabelle darunter). */
.db-filter-bar {
    position: relative;
    padding: 8px 0;
    border-bottom: 1px solid var(--border);
    background: transparent;
}
.db-filter-row {
    display: flex;
    gap: 8px;
    align-items: center;
    flex-wrap: wrap;
}
.db-filter-search {
    flex: 1 1 220px;
    background: var(--input-bg);
    color: var(--fg);
    border: 1px solid var(--border);
    padding: 6px 10px;
    border-radius: var(--radius-sm);
    font: inherit;
}
.db-filter-search:focus {
    outline: none; border-color: var(--border-hi);
    box-shadow: 0 0 0 3px rgba(0, 127, 180, 0.18);
}
.db-filter-popover {
    position: absolute;
    top: calc(100% - 4px);
    left: 16px;
    right: 16px;
    z-index: 50;
    max-height: 360px;
    overflow: auto;
}

/* ---- Features-Panel Item-Actions + Popover-Suche ---- */
.features-panel-item-actions {
    display: inline-flex;
    gap: 2px;
    align-self: start;
}
.features-panel-item-edit, .features-panel-item-delete {
    padding: 4px;
    line-height: 0;
    border-radius: var(--radius-sm);
    border: 1px solid transparent;
    background: transparent;
    color: var(--muted-hi);
    cursor: pointer;
}
.features-panel-item-edit:hover, .features-panel-item-delete:hover {
    background: var(--bg-card);
    color: var(--fg);
    border-color: var(--border);
}
.features-panel-item-delete:hover { color: var(--c-error); }
.features-panel-popover-search {
    width: 100%;
    box-sizing: border-box;
    background: var(--input-bg);
    color: var(--fg);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 6px 10px;
    margin-bottom: 8px;
    font: inherit;
}
.features-panel-popover-search:focus {
    outline: none; border-color: var(--border-hi);
    box-shadow: 0 0 0 3px rgba(0, 127, 180, 0.18);
}

/* DB-Item-Layout (erweitert): Actions am Ende der Zeile */
.features-panel-item {
    grid-template-columns: auto auto 1fr auto;
}

/* ---- + 67: Map-Status-Leiste (Cursor-Coords + GPS-Genauigkeit)
 * oben mittig statt unten (unten ist jetzt die Attribution). */
.map-status {
    position: absolute;
    left: 50%;
    top: 8px;
    transform: translateX(-50%);
    z-index: 600;
    display: flex;
    gap: 12px;
    align-items: center;
    padding: 4px 10px;
    background: var(--bg-elevated, var(--bg-card));
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    color: var(--muted-hi);
    font-size: 0.8em;
    font-variant-numeric: tabular-nums;
    pointer-events: none;
    opacity: 0.9;
    box-shadow: var(--shadow-card);
}
.map-status-coords:empty { display: none; }
.map-status-accuracy { color: var(--c-primary-hi); }

/* ============================================================
 — UI-Polish-Batch
 ============================================================ */

/* ---- Modal-Kontrast: Header + Footer haben anderen Hintergrund als Body */
.modal-header {
    background: var(--bg-card);
}
.modal-footer {
    background: var(--bg-card);
    align-items: center;
}
[data-theme="light"] .modal-header,
[data-theme="light"] .modal-footer {
    background: var(--bg);
}

/* Modal-Footer: Auswaehl-Counter rechtsbuendig + vertikal zentriert */
.modal-footer [data-role="sel-count"] {
    margin-left: auto;
    margin-right: 4px;
    align-self: center;
    font-size: 0.85em;
    color: var(--muted-hi);
}
.modal-footer [data-role="row-count"] {
    align-self: center;
    font-size: 0.85em;
    color: var(--muted);
}

/* Modal-Buttons: Default zentriert; Footer-Buttons rechts mit Trenner */
.modal-actions { justify-content: center; }
.modal-actions--stack { align-items: stretch; }
.modal-card .modal-form > .modal-actions {
    /* Submit-Form-Buttons bleiben zentriert (Standard von ) */
}

/* Buttons im Modal-Footer/Actions: kleine Bg-Differenzierung (ghost
 * sichtbarer auf dem hellen Footer-Hintergrund) */
.modal-footer .ghost {
    background: var(--bg-elevated);
}
.modal-footer .ghost:hover {
    background: var(--bg-card);
}

/* ---- Active-Layer Toggle: GRUEN (signal) statt blau ---- */
.layer-row .layer-toggle[data-action="toggle-active"].is-on {
    color: var(--c-signal-dk);
    background: var(--c-signal-dim);
    border-color: var(--c-signal-dk);
}
[data-theme="light"] .layer-row .layer-toggle[data-action="toggle-active"].is-on {
    color: #007a3a;
    background: rgba(2, 254, 137, 0.18);
    border-color: #007a3a;
}
.layer-row.layer-row--active {
    background: rgba(2, 254, 137, 0.06);
}

/* ---- Empty-Trash Button HERVORGEHOBEN rot/pink ---- */
[data-action="empty-trash"] {
    background: var(--c-error) !important;
    color: var(--c-light) !important;
    border-color: var(--c-error) !important;
    font-weight: 500;
}
[data-action="empty-trash"]:hover {
    filter: brightness(1.12);
}

/* ---- DB Bulk-Delete Button rot wenn aktiv ---- */
[data-action="bulk-delete"]:not(:disabled) {
    background: var(--c-error) !important;
    color: var(--c-light) !important;
    border-color: var(--c-error) !important;
}
[data-action="bulk-delete"]:not(:disabled):hover {
    filter: brightness(1.12);
}

/* ---- Resize-Indikator: doppelte Linie, dezent permanent sichtbar ---- */
.resizable-handle--right { right: -6px; }
.resizable-handle--left  { left:  -6px; }
.resizable-handle::before,
.resizable-handle::after {
    content: "";
    position: absolute;
    top: 35%; bottom: 35%;
    width: 2px;
    border-radius: 1px;
    background: var(--border-hi);
    opacity: 0.55;
    transition: opacity .12s ease;
}
.resizable-handle::before { left: 50%; transform: translateX(-3px); }
.resizable-handle::after  { left: 50%; transform: translateX(1px); }
.resizable-handle:hover::before,
.resizable-handle:hover::after,
.resizable-handle:focus-visible::before,
.resizable-handle:focus-visible::after {
    opacity: 1;
    background: var(--c-primary-hi);
}

/* ---- Image-Slot-Remove: roter Kreis, oben rechts, mittig ---- */
.image-slot-remove {
    position: absolute;
    top: 4px;
    right: 4px;
    width: 22px;
    height: 22px;
    padding: 0;
    border-radius: 50%;
    background: var(--c-error);
    color: var(--c-light);
    border: 1px solid var(--c-error);
    font-size: 14px;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
}
.image-slot-remove:hover { filter: brightness(1.1); }

/* ---- Login-Form: mehr Abstand zwischen Eingabefeldern ---- */
.login-form { gap: 14px; }
.login-form .field + .field { margin-top: 4px; }

/* ---- Features-Panel: Action-Bar nach unten, kleiner ---- */
.features-panel-body {
    display: flex;
    flex-direction: column;
    min-height: 0;
}
.features-panel-list {
    flex: 1 1 auto;
    overflow-y: auto;
    min-height: 0;
}
.features-panel-actionbar {
    order: 99;
    position: sticky;
    bottom: 0;
    flex: 0 0 auto;
    background: var(--bg-panel);
    border-top: 1px solid var(--border);
    padding: 6px 10px;
    margin: 0 -10px -8px -10px;
    display: flex;
    gap: 6px;
    align-items: center;
    flex-wrap: wrap;
    font-size: 0.85em;
    z-index: 5;
}
.features-panel-actionbar [data-role="action-count"] {
    font-size: 0.85em;
    color: var(--muted-hi);
}
.features-panel-actionbar .primary,
.features-panel-actionbar .ghost {
    padding: 4px 10px;
    font-size: 0.85em;
}

/* ---- Bug/Feedback Btn ---
 Vorher orange (var(--c-warn)), aber das matcht nicht mit dem
 geolyser-tuerkis-Brand. Jetzt #00CCFF (Geolyser-Akzent) damit der
 Button sich ins Restdesign einreiht. */
.help-modal-bug-btn {
    background: #00CCFF;
    color: #002b3d;
    border: 1px solid #00bfee;
    font-weight: 600;
}
.help-modal-bug-btn:hover {
    background: #1ad6ff;
    border-color: #00a8d4;
    color: #001a26;
}
[data-theme="dark"] .help-modal-bug-btn {
    background: #00bfee;
    color: #001a26;
    border-color: #009ec7;
}
[data-theme="dark"] .help-modal-bug-btn:hover {
    background: #1ad6ff;
    color: #00131c;
}

/* ---- Hard-Reload-Button : rose, 40×40 px ----
 Sitzt im help-modal-footer neben dem Feedback-Btn. Rose signalisiert
 "letzter Ausweg / Reset" ohne destruktiv (rot/danger) zu wirken. */
#hard-reload-btn {
    width: 40px;
    height: 40px;
    min-width: 40px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 8px;
    background: rgba(244, 63, 94, 0.12);
    border: 1px solid rgba(244, 63, 94, 0.45);
    color: #f43f5e;
    flex-shrink: 0;
}
#hard-reload-btn:hover {
    background: rgba(244, 63, 94, 0.22);
    border-color: rgba(244, 63, 94, 0.7);
    color: #fb7185;
}
[data-theme="dark"] #hard-reload-btn {
    background: rgba(244, 63, 94, 0.18);
    border-color: rgba(244, 63, 94, 0.5);
    color: #fb7185;
}
[data-theme="dark"] #hard-reload-btn:hover {
    background: rgba(244, 63, 94, 0.30);
    border-color: #f43f5e;
    color: #fda4af;
}

/* ---- Geolyser-Logo im Login (Vorbereitung ) ---- */
.login-shell .login-logo {
    display: block;
    margin: 0 auto 16px auto;
    max-width: 120px;
    height: auto;
}

/* ============================================================
 — Bugfixes: Modal-Ecken + Button-Differenzierung
 ============================================================ */

/* Modal-Card: overflow:hidden damit Header/Footer-Backgrounds an die
 * abgerundeten Ecken angepasst werden. */
.modal-card {
    overflow: hidden;
}
/* Header und Footer brauchen oben/unten gerundete Ecken, damit ihre
 * Hintergrundfarbe nicht ueber die Card-Rundung hinausragt. */
.modal-header {
    border-top-left-radius: var(--radius-lg);
    border-top-right-radius: var(--radius-lg);
}
.modal-footer {
    border-bottom-left-radius: var(--radius-lg);
    border-bottom-right-radius: var(--radius-lg);
}

/* ---- Buttons mit Differenzierung gegen den Container-Hintergrund ---- */

/* Features-Panel Rail-Toggle + Search-Btn (sind in der Rail) */
.features-panel-rail-toggle,
.features-panel-rail-db {
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    color: var(--muted-hi);
    border-radius: var(--radius-sm);
}
.features-panel-rail-toggle:hover,
.features-panel-rail-db:hover {
    background: var(--bg-card);
    color: var(--fg);
    border-color: var(--border-hi);
}

/* Sidebar-Rail-Toggles + Add */
.sidebar-rail-toggle,
.sidebar-rail-add,
.sidebar-rail-gcp,
.sidebar-rail-aruco {
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    color: var(--muted-hi);
    border-radius: var(--radius-sm);
}
.sidebar-rail-toggle:hover,
.sidebar-rail-add:hover,
.sidebar-rail-gcp:hover,
.sidebar-rail-aruco:hover {
    background: var(--bg-card);
    color: var(--fg);
    border-color: var(--border-hi);
}
/* GCP/ArUco-Btns im Rail — gleiche Geometrie
 * wie sidebar-rail-add. Buttons sind nur sichtbar wenn feature_*-
 * Flags an sind und werden via Cursor-Mode "im rail" gerendert. */
.sidebar-rail-gcp,
.sidebar-rail-aruco {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    padding: 0;
    /* kein extra margin-top — .sidebar-rail hat
 * bereits `gap: 4px` zwischen allen Kindern. Vorher fielen GCP/ArUco
 * mit 4px gap + 4px margin = 8px aus dem Raster der anderen Buttons
 * raus. */
    margin-top: 0;
    cursor: pointer;
}
.sidebar-rail-gcp img,
.sidebar-rail-aruco img {
    display: block;
}

/* Pulsations-Effekt fuer GCP/ArUco-Btns
 * wenn ein Capture-State minimiert ist (siehe sidebar.js
 * setGcpMinimizedState). Cyan-Outline-Glow analog zu Location-Share-
 * Pulse aber etwas dezenter. Wirkt sowohl im expanded Sidebar-Header
 * als auch im collapsed Rail. */
.is-state-pulse {
    position: relative;
    animation: geolyser-state-pulse 1.8s ease-in-out infinite;
    box-shadow: 0 0 0 0 rgba(59, 189, 232, 0.6);
    border-color: var(--c-cyan, #3BBDE8) !important;
}
@keyframes geolyser-state-pulse {
    0%, 100% {
        box-shadow: 0 0 0 0 rgba(59, 189, 232, 0.55);
    }
    50% {
        box-shadow: 0 0 0 6px rgba(59, 189, 232, 0);
    }
}

/* Features-Panel Filter-Chips (Layer/Tags) */
.features-panel-chip {
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    color: var(--fg);
}
.features-panel-chip:hover {
    background: var(--bg-card);
    border-color: var(--border-hi);
}
.features-panel-chip.is-active {
    background: rgba(0, 127, 180, 0.18);
    border-color: var(--c-primary-hi);
    color: var(--c-primary-hi);
}

/* Features-Panel Header-Buttons (collapse / fullscreen) */
.features-panel-collapse,
.features-panel-fullscreen {
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    color: var(--muted-hi);
    border-radius: var(--radius-sm);
}
.features-panel-collapse:hover,
.features-panel-fullscreen:hover {
    background: var(--bg-card);
    color: var(--fg);
    border-color: var(--border-hi);
}

/* Sidebar-Head Aktion-Buttons (Plus / Pfeil) */
.sidebar-head-actions .ghost {
    background: var(--bg-elevated);
}
.sidebar-head-actions .ghost:hover {
    background: var(--bg-card);
    border-color: var(--border-hi);
}

/* Tristate-Buttons im Filter-Popover differenziert */
.features-panel-tristate-btn {
    background: var(--bg-elevated);
    border: 1px solid var(--border);
}
.features-panel-tristate-btn:hover {
    background: var(--bg-card);
    border-color: var(--border-hi);
}
.features-panel-tristate-btn.is-active {
    background: rgba(0, 127, 180, 0.22);
    border-color: var(--c-primary-hi);
    color: var(--c-primary-hi);
}

/* Topbar-Icon-Buttons */
.topbar .icon-btn,
.topbar .ghost {
    background: var(--bg-elevated);
    border: 1px solid var(--border);
}
.topbar .icon-btn:hover,
.topbar .ghost:hover {
    background: var(--bg-card);
    border-color: var(--border-hi);
}

/* Modal-Header Close-Button: subtle differenziert */
.modal-header .modal-close-btn {
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
}
.modal-header .modal-close-btn:hover {
    background: var(--bg-card);
    border-color: var(--border-hi);
}

/* DB-Filter-Bar Search + Chips ebenfalls sichtbar */
.db-filter-search {
    /* schon definiert; hier nur die Border anheben damit sichtbar */
    border-color: var(--border-hi);
}
/* Light-Mode-Search-Background analog zum Layers-Modal
 (#F1F4F7) — vorher war's var(--input-bg) was im Light-Theme auf #fff
 landete und damit sich kaum von der Modal-Card abhob. */
[data-theme="light"] .db-filter-search {
    background: #F1F4F7;
    border-color: #c8cfd6;
}
[data-theme="light"] .db-filter-search:focus {
    background: #fff;
}
.db-filter-bar .features-panel-chip {
    background: var(--bg-elevated);
}

/* Light-Mode-Adjustments: bg-elevated ist hier #ffffff, was auf weisser
 * modal-card unsichtbar ist. Nehme bg-card statt elevated. */
[data-theme="light"] .features-panel-rail-toggle,
[data-theme="light"] .features-panel-rail-db,
[data-theme="light"] .sidebar-rail-toggle,
[data-theme="light"] .sidebar-rail-add,
[data-theme="light"] .features-panel-chip,
[data-theme="light"] .features-panel-collapse,
[data-theme="light"] .features-panel-fullscreen,
[data-theme="light"] .sidebar-head-actions .ghost,
[data-theme="light"] .features-panel-tristate-btn,
[data-theme="light"] .topbar .icon-btn,
[data-theme="light"] .topbar .ghost,
[data-theme="light"] .modal-header .modal-close-btn {
    background: var(--bg);
    border-color: var(--border);
}
[data-theme="light"] .features-panel-rail-toggle:hover,
[data-theme="light"] .features-panel-rail-db:hover,
[data-theme="light"] .sidebar-rail-toggle:hover,
[data-theme="light"] .sidebar-rail-add:hover,
[data-theme="light"] .features-panel-chip:hover,
[data-theme="light"] .features-panel-collapse:hover,
[data-theme="light"] .features-panel-fullscreen:hover,
[data-theme="light"] .sidebar-head-actions .ghost:hover,
[data-theme="light"] .features-panel-tristate-btn:hover,
[data-theme="light"] .topbar .icon-btn:hover,
[data-theme="light"] .topbar .ghost:hover,
[data-theme="light"] .modal-header .modal-close-btn:hover {
    background: var(--bg-card);
    border-color: var(--c-primary-hi);
}

/* ============================================================
 — Detach-Button + Button-Polish-Runde 2
 ============================================================ */

/* ---- Layer-Feature Sub-Liste: Item ist Flex mit Detach-Button rechts ---- */
.layer-features {
    list-style: none;
    margin: 4px 0 6px 28px;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.layer-feature {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 0;
    background: transparent;
}
.layer-feature-name {
    flex: 1 1 auto;
    text-align: left;
    background: transparent;
    border: 0;
    color: var(--muted-hi);
    padding: 4px 8px;
    border-radius: var(--radius-sm);
    cursor: pointer;
    font: inherit;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.layer-feature-name:hover {
    background: var(--bg-card);
    color: var(--fg);
}
.layer-feature-detach {
    flex: 0 0 auto;
    background: transparent;
    border: 1px solid transparent;
    color: var(--muted);
    cursor: pointer;
    padding: 3px;
    border-radius: var(--radius-sm);
    line-height: 0;
    opacity: 0.6;
    transition: opacity .12s, background .12s, color .12s;
}
.layer-feature:hover .layer-feature-detach { opacity: 1; }
.layer-feature-detach:hover {
    background: var(--c-error-bg);
    color: var(--c-error);
    border-color: var(--c-error);
}
/* Edit-Btn in der Sidebar-Feature-Liste, links neben Detach.
 Gleiche Geometrie wie .layer-feature-detach, aber Hover in Primary-Blau
 (analog zum Pencil-Btn im rechten Datenbank-Panel) statt in Error-Rot. */
.layer-feature-edit {
    flex: 0 0 auto;
    background: transparent;
    border: 1px solid transparent;
    color: var(--muted);
    cursor: pointer;
    padding: 3px;
    border-radius: var(--radius-sm);
    line-height: 0;
    opacity: 0.6;
    transition: opacity .12s, background .12s, color .12s;
}
.layer-feature:hover .layer-feature-edit { opacity: 1; }
.layer-feature-edit:hover {
    background: rgba(0, 127, 180, 0.14);
    color: var(--c-primary-hi);
    border-color: var(--c-primary-hi);
}
/* Pencil-Icon ist im ICONS-Objekt mit 16x16 definiert — wir skalieren es
   hier auf 14x14 runter, damit Edit + Detach exakt gleich gross wirken. */
.layer-feature-edit svg { width: 14px; height: 14px; }

/* Eye-Toggle pro Feature in der Sidebar-Liste. Hat zwei
 Zustaende: sichtbar (eye_on, dezent) und versteckt (eye_off, amber).
 Geometrie deckt sich mit den anderen layer-feature-Action-Btns. */
.layer-feature-visible {
    flex: 0 0 auto;
    background: transparent;
    border: 1px solid transparent;
    color: var(--muted);
    cursor: pointer;
    padding: 3px;
    border-radius: var(--radius-sm);
    line-height: 0;
    opacity: 0.7;
    transition: opacity .12s, background .12s, color .12s;
}
.layer-feature:hover .layer-feature-visible { opacity: 1; }
.layer-feature-visible:hover {
    background: rgba(0, 127, 180, 0.10);
    color: var(--c-primary-hi);
}
/* Wenn das Feature ausgeblendet ist (data-checked=0), nimmt der Btn die
   Amber-Optik an — analog zum Layer-Eye-Off Pattern. */
.layer-feature-visible[data-checked="0"] {
    color: var(--c-amber, #c98a00);
    opacity: 1;
}
.layer-feature-visible[data-checked="0"]:hover {
    background: rgba(201, 138, 0, 0.14);
}
.layer-feature-visible svg { width: 14px; height: 14px; }

/* Hot-Spot zum Entfernen des letzten Vertex waehrend
 Geoman-Drawing. Wird vom geoman-vertex-remove.js absolute im
 map-container positioniert (left/top per JS gesetzt, 14 px Offset
 schon eingerechnet). pointer-events:auto damit der Klick uns trifft
 und nicht direkt an Leaflet-Map durchfaellt. */
.geolyser-vertex-remove-hot {
    position: absolute;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: #ef3b3b;
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 0 0 3px rgba(239, 59, 59, 0.32),
                0 2px 6px rgba(0, 0, 0, 0.35);
    border: 2px solid #fff;
    cursor: pointer;
    z-index: 1100;
    pointer-events: auto;
    transition: transform .12s ease-out;
    /* Leichtes Pulsieren, damit das Element als "klickbar" auffaellt. */
    animation: geolyser-vertex-remove-pulse 1.4s ease-in-out infinite;
}
.geolyser-vertex-remove-hot:hover {
    transform: scale(1.12);
}
.geolyser-vertex-remove-hot svg { display: block; }
@keyframes geolyser-vertex-remove-pulse {
    0%, 100% {
        box-shadow: 0 0 0 3px rgba(239, 59, 59, 0.32),
                    0 2px 6px rgba(0, 0, 0, 0.35);
    }
    50% {
        box-shadow: 0 0 0 7px rgba(239, 59, 59, 0.20),
                    0 2px 6px rgba(0, 0, 0, 0.35);
    }
}
/* User mit prefers-reduced-motion bekommen das Pulse nicht — der rote
   Marker mit Minus reicht da alleine als Hinweis. */
@media (prefers-reduced-motion: reduce) {
    .geolyser-vertex-remove-hot { animation: none; }
}

/* Drag-Handle ueber alten Vertices (alle ausser dem
 letzten). Blau, mit Move-Cursor, kein Pulse — der Drag ist eine
 ruhige Aktion (im Gegensatz zu "Delete"). */
.geolyser-vertex-drag-hot {
    position: absolute;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: #3b8eef;
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 0 0 3px rgba(59, 142, 239, 0.32),
                0 2px 6px rgba(0, 0, 0, 0.35);
    border: 2px solid #fff;
    cursor: move;
    z-index: 1099;
    pointer-events: auto;
    transition: transform .12s ease-out;
}
.geolyser-vertex-drag-hot:hover { transform: scale(1.12); }
.geolyser-vertex-drag-hot svg { display: block; }

/* ---- Allgemeine Button-Differenzierung gegen Container-Hintergrund ---- */
/* Catchall fuer alle .ghost / .ghost-btn / .icon-btn ohne explizite bg.
 * Nimmt --bg-elevated im Dark, --bg im Light (siehe oben). */
.ghost-btn {
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    color: var(--muted-hi);
    padding: 4px 10px;
    border-radius: var(--radius-sm);
    cursor: pointer;
    font: inherit;
    transition: background .12s, border-color .12s, color .12s;
}
.ghost-btn:hover {
    background: var(--bg-card);
    color: var(--fg);
    border-color: var(--border-hi);
}
[data-theme="light"] .ghost-btn {
    background: var(--bg);
}
[data-theme="light"] .ghost-btn:hover {
    background: var(--bg-card);
}

/* Layer-Toggles und Layer-Color-Pick ebenfalls heller als Row */
.layer-toggle:not(.is-on) {
    background: var(--bg-elevated);
    border-color: var(--border);
}
[data-theme="light"] .layer-toggle:not(.is-on) {
    background: var(--bg);
}

/* Tag-Picker im Feature-Modal: Chip + Suggestions */
.tag-picker {
    background: var(--input-bg);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 4px;
}
[data-theme="light"] .tag-picker {
    background: var(--bg);
}
.tag-picker-chip {
    background: var(--bg-elevated);
    border: 1px solid var(--border);
}
[data-theme="light"] .tag-picker-chip {
    background: var(--bg-card);
}

/* Trash-Modal Tabelle: Zeilen-Hover bg-card */
.trash-table tbody tr:hover {
    background: var(--bg-card);
}

/* Image-Slot: leerer Slot (data-action="img-add") sichtbar gegen modal-bg */
.image-slot {
    background: var(--bg-card);
    border: 1px dashed var(--border);
}
.image-slot.is-filled {
    background: transparent;
    border-style: solid;
}

/* Field-Label-Spans heller fuer Light-Mode-Lesbarkeit */
[data-theme="light"] .field-label { color: var(--muted-hi); }

/* Sidebar-Empty: Plus-Indicator-Box */
.sidebar-empty-plus {
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 2px 4px;
    margin: 0 2px;
}

/* ============================================================
 — Bugfixes Resize-Handle + Filter-Click + Aria
 ============================================================ */

/* Resize-Handle wieder bedienbar: nicht mehr rein nach aussen, sondern
 * grossteils im Panel. Width 8px, half-overlap nur 2px. */
.resizable-handle--right { right: -2px !important; }
.resizable-handle--left  { left:  -2px !important; }
.resizable-handle {
    width: 8px !important;
}

/* Sidebar-Paddings aus zurueckgenommen, sonst klebt der Inhalt
 * nicht mehr am Resize-Bereich und der Klick wird abgefangen. */
.sidebar { padding-right: 0 !important; }
.features-panel { padding-left: 0 !important; }

/* Doppellinie etwas duenner und hoeher z-index, damit sie auch ueber
 * dem ::before des Panels nicht klemmt. */
.resizable-handle { z-index: 6 !important; }

/* Klicks auf Tristate-Buttons + Popover-Inhalt MUESSEN durch sein, damit
 * der Filter-Klick wirklich den Listener erreicht. */
.features-panel-popover,
.features-panel-popover * {
    pointer-events: auto;
}
.features-panel-tristate-btn { cursor: pointer; }
/* SVG-Icons in Tristate-Buttons sauber zentrieren. */
.features-panel-tristate-btn { display: inline-flex; align-items: center; justify-content: center; }
.features-panel-tristate-btn svg { display: block; }

/* Bug-Modal: Focus weg vom Senden-Button beim Schliessen, sonst
 * "Blocked aria-hidden on focused element"-Warnung. */
#bug-modal:not([hidden]) [data-action="bug-send"]:focus { outline: none; }

/* Sidebar-Plus-Button: + zentrieren in der Rail */
.sidebar-rail-add {
    display: inline-flex !important;
    align-items: center;
    justify-content: center;
    padding: 4px;
}

/* ---- Image-Slot-Placeholder fuer noch-nicht-gespeicherte Features ---- */
.image-slot.is-placeholder {
    background: var(--bg-card);
    border: 1px dashed var(--border);
    cursor: not-allowed;
    color: var(--muted);
    font-size: 0.7em;
    text-align: center;
    display: flex;
    align-items: center;
    justify-content: center;
}
.image-slot-hint {
    opacity: 0.6;
}

/* ============================================================
 — Resize-Innenabstand + Temp-Feature
 ============================================================ */

/* Innenabstand zum Resize-Handle: Content der Sidebar nicht direkt am Rand. */
.sidebar .sidebar-body {
    padding-right: 12px;
}
.features-panel .features-panel-body {
    padding-left: 12px;
}
[data-theme="light"] .sidebar .sidebar-body { padding-right: 12px; }
[data-theme="light"] .features-panel .features-panel-body { padding-left: 12px; }

/* ============================================================
 — Login-Screen Redesign (Logo + blurred Hintergrund-Karte)
 ============================================================ */

.login-page {
    position: relative;
    overflow: hidden;
    min-height: 100vh;
}
.login-bg {
    position: fixed;
    inset: 0;
    z-index: 0;
    filter: blur(8px) brightness(0.45) saturate(0.85);
    pointer-events: none;
    /* Etwas ueber den Viewport hinaus, damit der Blur-Rand nicht hineinragt. */
    margin: -20px;
}
.login-bg-tint {
    position: fixed;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    background:
        radial-gradient(ellipse at center, rgba(0, 127, 180, 0.10) 0%, rgba(0, 0, 0, 0.55) 70%),
        linear-gradient(180deg, rgba(24, 27, 29, 0.35) 0%, rgba(24, 27, 29, 0.65) 100%);
}
.login-page main {
    position: relative;
    z-index: 2;
}
.login-card {
    background: rgba(24, 27, 29, 0.78) !important;
    backdrop-filter: blur(14px) saturate(1.1);
    -webkit-backdrop-filter: blur(14px) saturate(1.1);
    border: 1px solid rgba(255, 255, 255, 0.08) !important;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.55), 0 1px 0 rgba(255, 255, 255, 0.04) inset !important;
    color: var(--c-light);
    width: min(420px, 90vw);
    padding: 28px 28px 22px !important;
}
[data-theme="light"] .login-card {
    background: rgba(255, 255, 255, 0.92) !important;
    border-color: rgba(0, 96, 141, 0.18) !important;
    color: var(--fg);
}
.login-card .login-logo {
    display: block;
    margin: 0 auto 14px auto;
    width: 96px;
    height: auto;
    max-height: 96px;
    filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.45));
}
.login-card h1 {
    text-align: center;
    margin: 0 0 6px 0;
    font-family: var(--font-display);
    font-size: 1.35rem;
}
.login-card .sub {
    text-align: center;
    margin: 0 0 18px 0;
    font-size: 0.9em;
}
.login-card .field {
    margin-bottom: 14px;
}
.login-card .field label {
    display: block;
    margin-bottom: 4px;
    font-size: .85em;
    color: var(--muted-hi);
}
.login-card .field input {
    width: 100%;
    box-sizing: border-box;
    background: var(--input-bg);
    color: var(--fg);
    border: 1px solid var(--border);
    padding: 10px 12px;
    border-radius: var(--radius-sm);
    font: inherit;
}
.login-card .field input:focus {
    outline: none;
    border-color: var(--c-primary-hi);
    box-shadow: 0 0 0 3px rgba(0, 127, 180, 0.18);
}
[data-theme="light"] .login-card .field input {
    background: var(--bg);
    color: var(--fg);
}
.login-card .login-actions {
    margin-top: 20px;
    display: flex;
    justify-content: stretch;
}
.login-card .login-actions .primary {
    width: 100%;
    padding: 12px 18px;
    font-size: 1rem;
}
.login-card .login-footer {
    margin-top: 18px;
    text-align: center;
    color: var(--muted);
    font-size: .8em;
}
.login-card .login-footer a {
    color: var(--c-primary-hi);
    text-decoration: none;
}

/* Leaflet-Default-Tiles in der bg-Karte: Kontroll-Elemente ganz weg. */
.login-bg .leaflet-control-container,
.login-bg .leaflet-control-attribution {
    display: none !important;
}
.login-bg .leaflet-tile-pane {
    /* etwas zusaetzlicher Tint ueber den Tiles selbst */
    filter: contrast(1.1);
}

/* ============================================================
 — GPS-Draw-Tools (links unten, ueber Locate)
 ============================================================ */

.gps-tools {
    position: absolute;
    /* Locate-Plugin hat seinen Knopf bottomleft - wir sitzen direkt darueber.
     * Standard-Leaflet-Bottomleft-Container ist ca 30px hoch + 10px Abstand. */
    left: 10px;
    bottom: 56px;
    z-index: 700;
    display: flex;
    flex-direction: column;
    gap: 4px;
    align-items: flex-start;
}
.gps-tools-btn {
    width: 34px;
    height: 34px;
    padding: 0;
    background: var(--bg-elevated);
    color: var(--fg);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
}
.gps-tools-btn:hover:not(:disabled) {
    /* solider Hover-Hintergrund - var(--bg-card) ist im Dark-
 * Mode fast transparent (3% Weiss), das blutet ueber der Karte aus. */
    background: var(--bg-elevated);
    border-color: var(--c-primary-hi);
    color: var(--c-primary-hi);
}
[data-theme="dark"] .gps-tools-btn:hover:not(:disabled) {
    background: #2b3338;
    border-color: var(--c-primary-hi);
    color: var(--c-primary-hi);
}
.gps-tools-btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}
.gps-tools-btn.is-recording {
    background: var(--c-error);
    color: var(--c-light);
    border-color: var(--c-error);
    animation: gps-pulse 1.2s ease-in-out infinite;
}
@keyframes gps-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(255, 92, 101, 0.55); }
    50%      { box-shadow: 0 0 0 6px rgba(255, 92, 101, 0); }
}
/* Location-Share-Btn pulsiert pink/rose und ist sehr deutlich
 sichtbar wenn aktiv. Vorher war der Hintergrund nur transparent. */
.gps-tools-btn.is-active[data-action="gps-share-location"] {
    background: #e84d8a !important;     /* pink/rose */
    color: #fff !important;
    border-color: #c43671 !important;
    animation: gps-share-pulse 1.4s ease-in-out infinite;
}
@keyframes gps-share-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(232, 77, 138, 0.6); }
    50%      { box-shadow: 0 0 0 8px rgba(232, 77, 138, 0); }
}
[data-theme="dark"] .gps-tools-btn.is-active[data-action="gps-share-location"] {
    background: #ff66a3 !important;
    border-color: #e84d8a !important;
}
.gps-tools-status {
    /* Status-Badge horizontal RECHTS neben dem aktiven Button - per absolute
     * Positionierung abseits vom Button-Stack. */
    position: absolute;
    left: 44px;
    bottom: 0;
    white-space: nowrap;
    background: var(--bg-elevated);
    color: var(--fg);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 4px 8px;
    font-size: 0.78em;
    font-variant-numeric: tabular-nums;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
    pointer-events: none;
    max-width: 240px;
}
.gps-tools-status[data-level="warn"] {
    background: var(--c-error-bg);
    color: var(--c-error);
    border-color: var(--c-error);
}
.gps-tools-status[data-level="ok"] {
    color: var(--c-signal-dk, #00c76a);
    border-color: var(--border-hi);
}

/* Wenn der Status per JS direkt in #map gehangen wird, zeigen
 * wir ihn gross + mittig im unteren Viertel der Karte. Eigene Klasse
 * damit die alten Stack-Regeln (left:44px etc) nicht greifen. */
.gps-tools-status.gps-tools-status--center {
    position: absolute;
    left: 50%;
    bottom: 22%;
    transform: translateX(-50%);
    /* die alten Regeln aushebeln */
    top: auto;
    right: auto;
    /* Groesse + Lesbarkeit */
    font-size: 1.05em;
    padding: 10px 18px;
    border-radius: var(--radius-md, 8px);
    border-width: 2px;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);
    /* ueber Leaflet-Tooltip (650) und -Popup (700), unter
 * Modals (1000+). Leaflet-Controls liegen bei 800-1000, daher 1000. */
    z-index: 1000;
    max-width: min(80%, 540px);
    text-align: center;
    font-weight: 500;
    letter-spacing: 0.01em;
}

[data-theme="light"] .gps-tools-btn {
    background: var(--bg-elevated);
    color: var(--fg);
}
/* d: Aktiv-State (Tracking laeuft) muss in Light + Dark rot sein.
 * Die generische [data-theme="light"] .gps-tools-btn-Regel oben ueber-
 * schrieb sonst den is-recording-Hintergrund auf var(--bg-elevated).
 * Hoehere Spezifitaet via .is-recording macht das Rot wieder sichtbar. */
[data-theme="light"] .gps-tools-btn.is-recording,
[data-theme="dark"] .gps-tools-btn.is-recording {
    background: var(--c-error);
    color: var(--c-light);
    border-color: var(--c-error);
}

/* Map-Status ist jetzt oben mittig (siehe +67-Regel),
 * Bottom-Override gestrichen. */

/* ============================================================
 — Filter-Popover-Bug + GPS-Tools-Sichtbarkeit
 ============================================================ */

/* Popover wird mit position:absolute + top:100% gerendert. Anker MUSS
 * .features-panel-filters sein (nicht .features-panel, sonst wird er
 * durch overflow:hidden weggeclippt). */
.features-panel-filters {
    position: relative;
    /* Popover darf nach unten ueber die Chips raushaengen, nicht clippen. */
    overflow: visible;
}
/* Auch das Body darf den Popover nach unten zeigen lassen. */
.features-panel:not(.features-panel--collapsed) {
    overflow: visible;
}
/* Aber Liste selbst soll scrollbar bleiben - das macht .features-panel-list
 * weiter unten sowieso schon. */

/* Popover bekommt jetzt klaren z-index und Schatten, damit er ueber der
 * Liste liegt. */
.features-panel-popover {
    z-index: 50 !important;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.45);
    /* Auf Top der gesamten Filter-Bar verankert, nicht bottom. */
    top: 100% !important;
    margin-top: 4px;
}

/* GPS-Tools-Sichtbarkeit: Container mit display + position relativ
 * sicherstellen, falls overflow oder z-index ihn versteckt. */
#gps-tools.gps-tools {
    display: flex !important;
    z-index: 1500 !important;
}

/* ============================================================
 b — GPS-Tools jetzt als L.Control im leaflet-bottom-left
 ============================================================ */

/* Innerhalb des Leaflet-Bottom-Left-Containers braucht .gps-tools KEIN
 * absolute mehr - der Leaflet-Container stackt seine Children selbst. */
.leaflet-bottom .gps-tools {
    position: static !important;
    left: auto !important;
    bottom: auto !important;
    margin: 0 0 6px 0;
    flex-direction: column;
    pointer-events: auto;
}
.leaflet-bottom .gps-tools .gps-tools-status {
    position: absolute;
    left: calc(100% + 6px);
    bottom: 0;
    /* der Status-Badge bleibt absolut, damit er nicht in den Stack
     * integriert ist - die Tools-Box behaelt feste Hoehe. */
}
/* Standard-Leaflet-Bottom-Container hat margin von 10px - GPS-Tools liegen
 * dann ca 70-90px ueber dem unteren Rand (Locate + Scale dazwischen). */
.leaflet-bottom.leaflet-left {
    display: flex;
    flex-direction: column-reverse;
    align-items: flex-start;
}
.leaflet-bottom.leaflet-left .leaflet-control {
    margin: 4px 10px 0 10px;
}

/* Die Buttons selbst nicht zu klein, ueberlappen Locate-Plugin nicht. */
.leaflet-bottom .gps-tools-btn {
    /* Leaflet-typischer Schatten / Border passend zu anderen Controls. */
    box-shadow: 0 1px 5px rgba(0, 0, 0, 0.4);
}

/* ============================================================
 b — GPS-Tools Visibility-Toggle + Stack-Reihenfolge
 ============================================================ */

/* Default unsichtbar, nur wenn Locate-Plugin aktiv ist anzeigen.
 * Vorher hatten wir "display:flex !important" was das Verstecken brach. */
#gps-tools.gps-tools {
    display: flex !important;
    z-index: 1500 !important;
}
#gps-tools.gps-tools.is-hidden {
    display: none !important;
}

/* Stack-Reihenfolge im leaflet-bottom-left:
 * Wir wollen von UNTEN nach OBEN: scale-line, locate-arrow, gps-tools.
 * Standard-Leaflet-Insertion mit position:bottomleft ist:
 *   scale (added 1st)  -> data-rolle in normaler Reihenfolge
 *   locate (added 2nd) -> darueber
 *   gps-tools (added 3rd, post-boot) -> ganz oben
 * Mit normaler flex-direction (column) waere insertion-order = vertical.
 * Default Leaflet hat KEIN flex auf dem Container, sondern stackt block.
 * Block-Layout: scale oben, locate mittig, gps-tools unten. Falsch.
 * Daher: flex-column-reverse erzwingen. */
.leaflet-bottom.leaflet-left {
    display: flex !important;
    flex-direction: column-reverse !important;
    align-items: flex-start;
}

/* ============================================================
 — Stack-Reihenfolge der Leaflet-Controls
 ============================================================ */

/* LINKS UNTEN (von unten nach oben):
 *   1. leaflet-control-locate  (location-arrow)
 *   2. gps-tools               (Punkt / Linie / Polygon)
 * Insertion-order: locate (in setupMap), dann gps-tools (post-boot).
 * column-reverse macht "first inserted = bottom" → locate unten, GPS oben. */
.leaflet-bottom.leaflet-left {
    display: flex !important;
    flex-direction: column-reverse !important;
    align-items: flex-start;
}

/* RECHTS UNTEN (von oben nach unten):
 *   1. leaflet-control-zoom    (Zoom +/-)
 *   2. leaflet-control-scale   (Massstab darunter)
 * Default-Block-Layout reicht hier - zoom (1st) oben, scale (2nd) darunter.
 * KEINE flex-direction-reverse, sonst dreht sich das wieder um. */
.leaflet-bottom.leaflet-right {
    display: flex !important;
    flex-direction: column !important;
    align-items: flex-end;
}
.leaflet-bottom.leaflet-right .leaflet-control {
    margin: 4px 10px;
}

/* ============================================================
 b — Leaflet-Default-Stack zurueck, GPS-Tools absolut
 ============================================================ */

/* Flex-Hacks auf den Leaflet-Bottom-Containern komplett zuruecknehmen.
 * Leaflet stackt seine Controls per Default sauber via block - das war ok. */
.leaflet-bottom.leaflet-left,
.leaflet-bottom.leaflet-right {
    display: block !important;
    flex-direction: unset !important;
    align-items: unset !important;
}
.leaflet-bottom.leaflet-left .leaflet-control,
.leaflet-bottom.leaflet-right .leaflet-control {
    margin: 10px;
}

/* GPS-Tools werden NICHT in den Leaflet-Container gesteckt, sondern
 * als absolut positioniertes Overlay im map-shell, sodass der Locate-Button
 * seine feste Position behaelt. */
#gps-tools.gps-tools {
    position: absolute !important;
    left: 10px !important;
    bottom: 90px !important;   /* ueber dem Locate-Button (~30px hoch + 10px margin + Luft) */
    top: auto !important;
    z-index: 1500 !important;
    display: flex !important;
    flex-direction: column;
    gap: 4px;
    align-items: flex-start;
    pointer-events: auto;
}
#gps-tools.gps-tools.is-hidden {
    display: none !important;
}
#gps-tools .gps-tools-status {
    position: absolute !important;
    left: calc(100% + 6px);
    bottom: 0;
}

/* ============================================================
 c — GPS-Tools im #map-Element + Position relativ dazu
 ============================================================ */

/* #gps-tools wird per JS in #map verschoben, damit absolute positioning
 * relativ zum Karten-Container ist (#map hat position:relative durch Leaflet).
 * left:10px liegt damit am linken Karten-Rand, nicht am linken Bildrand.
 * bottom:56px platziert die Tools ueber dem Locate-Button (Locate ~40px hoch
 * + 10px margin-bottom, also Top-Edge bei ~50px von Karte-Bottom). */
#map > #gps-tools.gps-tools {
    position: absolute !important;
    left: 10px !important;
    bottom: 56px !important;
    top: auto !important;
    z-index: 1500 !important;
    display: flex !important;
    flex-direction: column;
    gap: 4px;
    align-items: flex-start;
    pointer-events: auto;
}
#map > #gps-tools.gps-tools.is-hidden {
    display: none !important;
}

/* Mobile-NN-Fix Auf Smartphone
 * (max-width: 768px) schoben sich die GPS-Tools-Buttons + Locate
 * ueber das aufgeklappte Sidepanel (Sidebar/Features-Panel sind auf
 * z-index: 1200 in der Mobile-Spec). Analog zu Mobile-N (map-status)
 * jetzt unter Sidebar-Level absenken: Sidepanel offen → GPS-Tools
 * verdeckt. !important + ID-Selektor (Spezifitaet 1,2,1) gewinnt
 * gegen die mehrfachen `z-index: 1500 !important`-Regeln oben. */
@media (max-width: 768px) {
    #gps-tools.gps-tools,
    #map > #gps-tools.gps-tools,
    .leaflet-bottom .gps-tools,
    .leaflet-bottom .leaflet-control-locate,
    .leaflet-bottom.leaflet-left {
        z-index: 1100 !important;
    }
}

/* ============================================================
 — Komplettes Farbschema fuer Buttons (Light + Dark)
 ============================================================ */

/* ---- Sidebar links: Neuer Layer (Plus) ---- */
.sidebar-rail-add,
.sidebar-head-actions [data-action="create"] {
    background: rgba(2, 254, 137, 0.18) !important;
    color: #007a3a !important;
    border-color: rgba(2, 254, 137, 0.45) !important;
}
.sidebar-rail-add:hover,
.sidebar-head-actions [data-action="create"]:hover {
    background: rgba(2, 254, 137, 0.30) !important;
    color: #006a2c !important;
}

/* ---- Sidebar links: Einklappen / Aufklappen (Pfeile) - hellblau ---- */
.sidebar-rail-toggle,
.sidebar-head-actions [data-action="toggle"] {
    background: rgba(0, 160, 210, 0.16) !important;
    color: #006a8d !important;
    border-color: rgba(0, 160, 210, 0.45) !important;
}
.sidebar-rail-toggle:hover,
.sidebar-head-actions [data-action="toggle"]:hover {
    background: rgba(0, 160, 210, 0.28) !important;
    color: #004161 !important;
}

/* ---- Features-Panel rechts: gleiche Pfeil-Buttons hellblau ---- */
.features-panel-rail-toggle,
.features-panel-collapse {
    background: rgba(0, 160, 210, 0.16) !important;
    color: #006a8d !important;
    border-color: rgba(0, 160, 210, 0.45) !important;
}
.features-panel-rail-toggle:hover,
.features-panel-collapse:hover {
    background: rgba(0, 160, 210, 0.28) !important;
    color: #004161 !important;
}

/* Rail-DB-Button im selben Gruen wie der
 * expandierte .features-panel-fullscreen-Btn — konsistente Visual-Sprache
 * fuer "DB-Vollansicht oeffnen", egal ob collapsed oder expanded. */
.features-panel-rail-db {
    background: rgba(2, 254, 137, 0.18) !important;
    color: #007a3a !important;
    border-color: rgba(2, 254, 137, 0.45) !important;
}
.features-panel-rail-db:hover {
    background: rgba(2, 254, 137, 0.30) !important;
    color: #006a2c !important;
}

/* ---- Features-Panel: Datenbank-Vollansicht-Button gruen (analog Plus links) ---- */
.features-panel-fullscreen {
    background: rgba(2, 254, 137, 0.18) !important;
    color: #007a3a !important;
    border-color: rgba(2, 254, 137, 0.45) !important;
}
.features-panel-fullscreen:hover {
    background: rgba(2, 254, 137, 0.30) !important;
    color: #006a2c !important;
}

/* ---- Filter-Chips im rechten Panel: Layer = grün, Tags = blau ---- */
.features-panel-chip[data-popover="layers"] {
    background: rgba(2, 254, 137, 0.14) !important;
    color: #007a3a !important;
    border-color: rgba(2, 254, 137, 0.40) !important;
}
.features-panel-chip[data-popover="layers"]:hover,
.features-panel-chip[data-popover="layers"].is-active {
    background: rgba(2, 254, 137, 0.30) !important;
    border-color: #00c76a !important;
}
.features-panel-chip[data-popover="tags"] {
    background: rgba(0, 160, 210, 0.14) !important;
    color: #006a8d !important;
    border-color: rgba(0, 160, 210, 0.40) !important;
}
.features-panel-chip[data-popover="tags"]:hover,
.features-panel-chip[data-popover="tags"].is-active {
    background: rgba(0, 160, 210, 0.28) !important;
    border-color: #00A0D2 !important;
}

/* ---- Action-Bar: Auswahl leeren = weisser Hintergrund ---- */
.features-panel-actionbar [data-action="clear-selection"] {
    background: var(--c-light) !important;
    color: var(--fg) !important;
    border: 1px solid var(--border) !important;
}
[data-theme="light"] .features-panel-actionbar [data-action="clear-selection"] {
    background: var(--c-light) !important;
    color: #2a2f33 !important;
    border-color: rgba(0, 96, 141, 0.30) !important;
}
.features-panel-actionbar [data-action="clear-selection"]:hover {
    background: var(--bg-card) !important;
}

/* ---- Per-Item-Action-Buttons im rechten Panel ---- */
/* Plus-Variante (add-to-layer) bleibt im Standard-Gruen. Wenn das Feature
   schon im aktiven Layer haengt, kommt zusaetzlich .btn-amber drauf —
   der Selektor weiter unten dreht dann auf Amber/Minus. */
.features-panel-item-add {
    background: rgba(2, 254, 137, 0.14) !important;
    color: #007a3a !important;
    border-color: rgba(2, 254, 137, 0.40) !important;
    /* Fix: + zentrieren */
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
}
.features-panel-item-add:hover {
    background: rgba(2, 254, 137, 0.28) !important;
}
/* Toggle-Override fuer den Remove-Btn (Minus). Wenn das
 Feature schon im aktiven Layer ist, traegt der Btn zusaetzlich
 .btn-amber — wir uebersteuern dann die Gruen-Werte aus dem Basis-
 Style auf Amber, behalten aber die identische Geometrie. */
.features-panel-item-add.btn-amber {
    background: rgba(201, 138, 0, 0.14) !important;
    color: var(--c-amber, #c98a00) !important;
    border-color: rgba(201, 138, 0, 0.40) !important;
}
.features-panel-item-add.btn-amber:hover {
    background: rgba(201, 138, 0, 0.28) !important;
}
.features-panel-item-edit {
    background: rgba(0, 160, 210, 0.14) !important;
    color: #006a8d !important;
    border-color: rgba(0, 160, 210, 0.40) !important;
}
.features-panel-item-edit:hover {
    background: rgba(0, 160, 210, 0.28) !important;
}
.features-panel-item-delete {
    background: var(--c-error-bg) !important;
    color: var(--c-error) !important;
    border-color: rgba(255, 92, 101, 0.40) !important;
}
.features-panel-item-delete:hover {
    background: rgba(255, 92, 101, 0.30) !important;
}

/* ---- Modal-Buttons (polish runde 5) ----------------------
 Cancel/Close: NEUTRAL grau, damit sie sich deutlich von destruktiven
 Aktionen (Verwerfen, Loeschen) abheben. Frueher waren beide rot und
 sahen identisch aus. Das X im Modal-Header bleibt im neutralen Stil.
 Destruktive Aktionen (.ghost.danger oder data-action=discard/delete)
 sind im naechsten Block solid-rot definiert. ----------------------- */
.modal-actions [data-action="cancel"],
.modal-footer [data-action="cancel"],
.modal-actions [data-action="close-modal"],
.modal-footer [data-action="close-modal"],
.modal-close-btn {
    background: var(--bg-elevated) !important;
    color: var(--muted-hi) !important;
    border: 1px solid var(--border) !important;
}
.modal-actions [data-action="cancel"]:hover,
.modal-footer [data-action="cancel"]:hover,
.modal-actions [data-action="close-modal"]:hover,
.modal-footer [data-action="close-modal"]:hover,
.modal-close-btn:hover {
    background: var(--bg-card) !important;
    color: var(--fg) !important;
    border-color: var(--border-hi) !important;
}

/* Destruktive Aktionen: solid-rot, klar als "Achtung" markiert. */
.modal-actions .ghost.danger,
.modal-footer .ghost.danger,
.modal-actions [data-action="discard"],
.modal-actions [data-action="delete"],
.modal-actions [data-action="bulk-delete"] {
    background: var(--c-error) !important;
    color: var(--c-light) !important;
    border: 1px solid var(--c-error) !important;
    font-weight: 500;
}
.modal-actions .ghost.danger:hover,
.modal-footer .ghost.danger:hover,
.modal-actions [data-action="discard"]:hover,
.modal-actions [data-action="delete"]:hover,
.modal-actions [data-action="bulk-delete"]:hover {
    filter: brightness(1.1);
}

/* ---- Modal-Inputs im hellen Modus: heller Grau-Hintergrund ---- */
[data-theme="light"] .modal-card .field input,
[data-theme="light"] .modal-card .field select,
[data-theme="light"] .modal-card .field textarea,
[data-theme="light"] .login-card .field input {
    background: #f0f3f6 !important;
    color: var(--fg) !important;
    border: 1px solid rgba(0, 96, 141, 0.18) !important;
}
[data-theme="light"] .modal-card .field input:focus,
[data-theme="light"] .modal-card .field select:focus,
[data-theme="light"] .modal-card .field textarea:focus,
[data-theme="light"] .login-card .field input:focus {
    border-color: var(--c-primary-hi) !important;
}

/* ---- Tristate-Buttons ---- */
.features-panel-tristate-btn[data-state="all"] {
    color: #007a3a;
    border-color: rgba(2, 254, 137, 0.40);
}
.features-panel-tristate-btn[data-state="all"]:hover,
.features-panel-tristate-btn[data-state="all"].is-active {
    background: rgba(2, 254, 137, 0.28) !important;
    color: #006a2c;
    border-color: var(--c-signal-dk);
}
.features-panel-tristate-btn[data-state="any"] {
    color: #006a8d;
    border-color: rgba(0, 160, 210, 0.40);
}
.features-panel-tristate-btn[data-state="any"]:hover,
.features-panel-tristate-btn[data-state="any"].is-active {
    background: rgba(0, 160, 210, 0.28) !important;
    color: #004161;
    border-color: var(--c-primary-hi);
}
.features-panel-tristate-btn[data-state="not"] {
    color: var(--c-error);
    border-color: rgba(255, 92, 101, 0.40);
}
.features-panel-tristate-btn[data-state="not"]:hover,
.features-panel-tristate-btn[data-state="not"].is-active {
    background: rgba(255, 92, 101, 0.22) !important;
    border-color: var(--c-error);
}

/* ---- Topbar-Icons: jeder Knopf eine eigene Farbe ---- */
.topbar #admin-btn {
    background: rgba(59, 189, 232, 0.18) !important;
    color: #06829c !important;
    border-color: rgba(59, 189, 232, 0.45) !important;
}
.topbar #admin-btn:hover {
    background: rgba(59, 189, 232, 0.32) !important;
    color: #034f5f !important;
}
.topbar #trash-btn {
    background: rgba(255, 192, 74, 0.18) !important;
    color: #b87a00 !important;
    border-color: rgba(255, 192, 74, 0.55) !important;
}
.topbar #trash-btn:hover {
    background: rgba(255, 192, 74, 0.34) !important;
    color: #8a5a00 !important;
}
.topbar #help-btn {
    background: rgba(0, 160, 210, 0.16) !important;
    color: #006a8d !important;
    border-color: rgba(0, 160, 210, 0.45) !important;
}
.topbar #help-btn:hover {
    background: rgba(0, 160, 210, 0.30) !important;
    color: #004161 !important;
}
/* polish runde 9: Theme-Toggle visuell als Vorschau auf das
 Ziel-Theme. Im hellen Modus zeigt der Btn das Mond-Icon (Klick =
 dunkles Theme aktivieren) und ist dunkel mit hellem Icon. Im dunklen
 Modus zeigt der Btn das Sonnen-Icon (Klick = helles Theme aktivieren)
 und ist hell mit dunklem Icon. So sieht der User schon vor dem Klick
 was passiert. */
.topbar #theme-toggle {
    border-color: var(--border-hi) !important;
}
:root[data-theme="light"] .topbar #theme-toggle {
    /* Klick aktiviert dunkles Theme -> Btn-Vorschau: dunkel + hell */
    background: #1f2428 !important;
    color: #f1f4f7 !important;
    border-color: #1f2428 !important;
}
:root[data-theme="light"] .topbar #theme-toggle:hover {
    background: #2c3439 !important;
}
:root[data-theme="dark"] .topbar #theme-toggle {
    /* Klick aktiviert helles Theme -> Btn-Vorschau: hell + dunkel */
    background: #f1f4f7 !important;
    color: #1f2428 !important;
    border-color: #d0d7de !important;
}
:root[data-theme="dark"] .topbar #theme-toggle:hover {
    background: #ffffff !important;
}
.topbar #logout-btn {
    background: rgba(155, 90, 200, 0.20) !important;
    color: #6a3aa0 !important;
    border-color: rgba(155, 90, 200, 0.50) !important;
}
.topbar #logout-btn:hover {
    background: rgba(155, 90, 200, 0.36) !important;
    color: #4a2a78 !important;
}

/* Dark-Mode-Adjustments fuer alle obigen Color-Buttons: Hintergruende
 * etwas heller, Schriftfarbe Pastell statt dunkel. */
[data-theme="dark"] .sidebar-rail-add,
[data-theme="dark"] .sidebar-head-actions [data-action="create"],
[data-theme="dark"] .features-panel-fullscreen,
[data-theme="dark"] .features-panel-item-add,
[data-theme="dark"] .features-panel-chip[data-popover="layers"] {
    color: #6dffb4 !important;
}
/* Remove-Variante (Minus) bleibt auch im Dark-Mode
 amber-pastell — uebersteuert die gemeinsame Gruen-Regel oben. */
[data-theme="dark"] .features-panel-item-add.btn-amber {
    color: #f5c869 !important;
}
[data-theme="dark"] .sidebar-rail-toggle,
[data-theme="dark"] .sidebar-head-actions [data-action="toggle"],
[data-theme="dark"] .features-panel-rail-toggle,
[data-theme="dark"] .features-panel-collapse,
[data-theme="dark"] .features-panel-item-edit,
[data-theme="dark"] .features-panel-chip[data-popover="tags"],
[data-theme="dark"] .topbar #help-btn {
    color: #9bd9f5 !important;
}
/* Dark-Mode pastel-Gruen analog
 * .features-panel-fullscreen (Zeile 6321), damit Light + Dark identische
 * Visual-Sprache haben. */
[data-theme="dark"] .features-panel-rail-db {
    color: #6dffb4 !important;
}
[data-theme="dark"] .topbar #admin-btn { color: #6ed6f4 !important; }
[data-theme="dark"] .topbar #trash-btn { color: #ffc04a !important; }
[data-theme="dark"] .topbar #logout-btn { color: #c79be3 !important; }

/* ============================================================
 b — Profil-Modal (Self-Service-Account-Daten + Export)
 ============================================================ */

.profile-modal-body { display: flex; flex-direction: column; gap: 14px; }
.profile-modal-body h4 {
    margin: 8px 0 4px;
    font-size: 1em;
    font-weight: 500;
    color: var(--c-primary-hi);
}
.profile-modal-body h4:first-child { margin-top: 0; }

.profile-data {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 4px 14px;
    margin: 0;
    font-size: 0.92em;
}
.profile-data dt {
    color: var(--muted-hi);
    font-weight: 400;
}
.profile-data dd {
    margin: 0;
    color: var(--fg);
    word-break: break-all;
}
.profile-data code {
    font-size: 0.88em;
    color: var(--muted-hi);
}

/* c: Quota-Anzeige + Self-Service-Loeschung. */
.quota-box {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.quota-bar {
    width: 100%;
    height: 8px;
    background: var(--bg-deep, rgba(0, 0, 0, 0.18));
    border-radius: 4px;
    overflow: hidden;
}
.quota-bar > span {
    display: block;
    height: 100%;
    background: var(--c-primary, #2c8ee0);
    transition: width .3s ease;
}
.quota-bar > span[data-warn="true"] {
    background: var(--c-error, #d8493b);
}
.quota-label { margin: 0; }

.delete-account-form {
    border: 1px solid var(--c-error);
    background: var(--c-error-bg, rgba(216, 73, 59, 0.06));
    border-radius: var(--radius-md, 8px);
    padding: 12px 14px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.delete-account-form .form-warning {
    margin: 0;
    color: var(--c-error);
}
.delete-account-form .field { margin: 0; }

.form-ok {
    color: var(--c-signal-dk, #00a04f);
    font-size: 0.92em;
    margin: 4px 0 0;
}
.ghost.danger {
    color: var(--c-error);
    border-color: var(--c-error);
}
.ghost.danger:hover {
    background: var(--c-error-bg);
}

/* ============================================================
 g — DSGVO-Cookie-Banner + Legal-Links
 ============================================================ */

/* Mehrfach-Nutzungs-Badge in "Tilesets von anderen Nutzern". */
.from-others-badge {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 6px;
    border-radius: 999px;
    background: rgba(0, 160, 210, 0.18);
    color: var(--c-primary, #007FB4);
    font-size: 0.78em;
    font-weight: 600;
    cursor: help;
    border: 1px solid rgba(0, 160, 210, 0.4);
}
[data-theme="dark"] .from-others-badge {
    background: rgba(59, 189, 232, 0.2);
    color: #3BBDE8;
}

/* Import-Compare-Modal (Duplikat-Pruefung beim Layer-Import). */
.import-compare-card {
    width: min(960px, 100vw);
    max-width: 100vw;
    max-height: 90vh;
    display: flex;
    flex-direction: column;
}
.import-compare-card .modal-body {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 12px 16px;
}
.cmp-toolbar {
    display: flex;
    /* War flex-end -> die zweite Spalte hat ein
 sub-Hint UNTER dem Input, was den Label-Container höher macht; bei
 flex-end werden die Boxen am unteren Rand ausgerichtet und der
 Input der zweiten Spalte rutscht NACH OBEN gegenüber dem ersten
 Input. flex-start richtet die Boxen oben aus, die Inputs landen
 auf derselben Y-Achse, der sub-Hint hängt sauber unten dran. */
    align-items: flex-start;
    gap: 16px;
    flex-wrap: wrap;
    margin-bottom: 12px;
    padding: 10px;
    background: var(--bg-elevated, rgba(0, 0, 0, 0.04));
    border-radius: 6px;
}
.cmp-toolbar .field { flex: 1 1 200px; }
.cmp-bulk {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}
.cmp-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.cmp-row {
    border: 1px solid var(--border, #ddd);
    border-radius: 6px;
    background: var(--bg-card, #fff);
}
.cmp-row-head {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    cursor: pointer;
    user-select: none;
}
.cmp-row-head:hover {
    background: var(--bg-elevated, rgba(0, 0, 0, 0.03));
}
.cmp-row-name {
    font-weight: 500;
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.cmp-row-meta { font-size: 0.85em; }
.cmp-row-toggle {
    color: var(--muted, #6b7280);
    font-size: 1.1em;
}
.cmp-row-body {
    padding: 12px 16px;
    border-top: 1px solid var(--border);
    background: var(--bg, #fafafa);
}
[data-theme="dark"] .cmp-row-body { background: rgba(255, 255, 255, 0.02); }
.cmp-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
    margin-bottom: 10px;
}
.cmp-side {
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 10px;
    background: var(--bg-card, #fff);
}
.cmp-side h4 {
    margin: 0 0 8px;
    font-size: 0.95em;
    color: var(--muted-hi, #4b5563);
}
.cmp-side--old h4 { color: #b91c1c; }
.cmp-side--new h4 { color: #166534; }
.cmp-props { margin-top: 6px; }
.cmp-props summary { cursor: pointer; font-size: 0.85em; }
.cmp-props pre {
    max-height: 180px;
    overflow: auto;
    font-size: 0.8em;
    background: var(--bg-elevated, rgba(0, 0, 0, 0.04));
    padding: 6px;
    border-radius: 4px;
    margin: 6px 0 0;
}
.cmp-minimap {
    height: 200px;
    border: 1px solid var(--border);
    border-radius: 4px;
    margin-bottom: 10px;
    background: #eef;
}
.cmp-actions {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 8px;
    background: var(--bg-elevated, rgba(0, 0, 0, 0.04));
    border-radius: 4px;
}
.cmp-actions label {
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}
.cmp-badge {
    display: inline-block;
    font-size: 0.72em;
    padding: 1px 8px;
    border-radius: 999px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.cmp-badge--dup {
    background: rgba(239, 68, 68, 0.15);
    color: #b91c1c;
    border: 1px solid rgba(239, 68, 68, 0.4);
}
.cmp-badge--new {
    background: rgba(22, 101, 52, 0.12);
    color: #166534;
    border: 1px solid rgba(22, 101, 52, 0.35);
}
@media (max-width: 700px) {
    .cmp-grid {
        grid-template-columns: 1fr;
    }
}

/* + 81.0.13: Toast-Notifikation. Toasts werden jetzt in
 einem Stack-Container untereinander gerendert (statt sich zu
 ueberlagern). Neue Toasts kommen oben rein, aeltere ruecken nach;
 das Fade-out laeuft ueber 1s (vorher 0.35s, zu abrupt). */
.geolyser-toast-stack {
    position: fixed;
    top: 64px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 2200;
    display: flex;
    flex-direction: column;
    gap: 8px;
    pointer-events: none;        /* Container fangt keine Klicks */
    max-width: min(520px, 92vw);
    width: max-content;
}
.geolyser-toast {
    pointer-events: auto;        /* Einzelner Toast schon */
    background: var(--bg-card, #fff);
    color: var(--text);
    border: 1px solid var(--border);
    border-left: 4px solid var(--c-primary, #007FB4);
    padding: 10px 16px;
    border-radius: 8px;
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.22);
    font-size: 0.92em;
    animation: geolyser-toast-in .25s ease-out;
}
.geolyser-toast--success { border-left-color: #10B981; }
.geolyser-toast--error   { border-left-color: #ef4444; }
.geolyser-toast--info    { border-left-color: var(--c-primary, #007FB4); }
/* Toast-Avatar-Variante (Coworker-Aenderungs-Toasts).
 Avatar links neben Text, Maske bei Incognito. */
.geolyser-toast--with-avatar {
    display: flex;
    align-items: center;
    gap: 10px;
}
.geolyser-toast-avatar {
    flex: 0 0 auto;
    width: 26px; height: 26px;
    border-radius: 50%;
    background: var(--user-color, #06829c);
    color: var(--user-color, #06829c);
    border: 2px solid var(--user-color, #06829c);
    overflow: hidden;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.geolyser-toast-avatar img {
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
}
.geolyser-toast-avatar--incognito {
    background: rgba(125, 129, 138, 0.18);
    color: #7d818a;
    border-color: rgba(125, 129, 138, 0.55);
}
.geolyser-toast-initial {
    color: #fff;
    font-size: 13px;
    font-weight: 700;
    line-height: 1;
}
.geolyser-toast-text {
    flex: 1 1 auto;
}
.geolyser-toast.is-leaving {
    animation: geolyser-toast-out 1s ease-in forwards;
}
@keyframes geolyser-toast-in {
    from { opacity: 0; transform: translateY(-12px); }
    to   { opacity: 1; transform: translateY(0); }
}
@keyframes geolyser-toast-out {
    from { opacity: 1; max-height: 200px; padding: 10px 16px;
           margin-top: 0; margin-bottom: 0; }
    to   { opacity: 0; max-height: 0; padding-top: 0; padding-bottom: 0;
           margin-top: 0; margin-bottom: -8px; }
}
[data-theme="dark"] .geolyser-toast {
    background: #1f242b;
    color: #e5e7eb;
}

/* Passwort-Toggle (Klartext-Eye). */
.geolyser-pw-wrap {
    position: relative;
    display: flex;
    align-items: stretch;
    width: 100%;
}
.geolyser-pw-wrap > input[type="password"],
.geolyser-pw-wrap > input[type="text"] {
    flex: 1;
    padding-right: 38px !important;
}
.geolyser-pw-toggle {
    position: absolute;
    right: 4px;
    top: 50%;
    transform: translateY(-50%);
    width: 30px;
    height: 30px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 0;
    color: var(--muted, #6b7280);
    cursor: pointer;
    padding: 0;
    border-radius: 4px;
}
.geolyser-pw-toggle:hover {
    color: var(--text, #111);
    background: rgba(0, 0, 0, 0.04);
}
[data-theme="dark"] .geolyser-pw-toggle:hover {
    background: rgba(255, 255, 255, 0.08);
}

/* Random-Icon im uc-generate-password-Btn
 * (User-Create-Modal). Per CSS mask getintet, damit es den Btn-Color
 * (currentColor) traegt — in Light-Mode dunkel, in Dark-Mode hell. */
.uc-random-btn .uc-random-icon {
    display: inline-block;
    width: 20px;
    height: 20px;
    background-color: currentColor;
    -webkit-mask: url("/img/icons/random-svgrepo-com.svg") center / contain no-repeat;
    mask: url("/img/icons/random-svgrepo-com.svg") center / contain no-repeat;
}

.legal-notice {
    position: fixed;
    left: 16px;
    right: 16px;
    bottom: 16px;
    /* Wenn das Notice aus dem Help-Modal heraus geoeffnet
 * wird, soll es DARUEBER liegen damit der User es lesen kann.
 * Modals haben z-index 2000, also setzen wir 2100. */
    z-index: 2100;
    display: flex;
    justify-content: center;
    pointer-events: none;
    animation: legal-notice-in .25s ease-out;
}
.legal-notice.is-leaving {
    animation: legal-notice-out .22s ease-in forwards;
}
@keyframes legal-notice-in {
    from { opacity: 0; transform: translateY(20px); }
    to   { opacity: 1; transform: translateY(0); }
}
@keyframes legal-notice-out {
    from { opacity: 1; transform: translateY(0); }
    to   { opacity: 0; transform: translateY(20px); }
}
.legal-notice-card {
    pointer-events: auto;
    max-width: 720px;
    width: 100%;
    background: var(--bg-elevated);
    color: var(--fg);
    border: 1px solid var(--border-hi);
    border-radius: var(--radius-md, 8px);
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.35);
    padding: 14px 18px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.legal-notice-text {
    font-size: 0.92em;
    line-height: 1.5;
    color: var(--fg);
}
.legal-notice-text strong { font-weight: 500; }
.legal-notice-text a {
    color: var(--c-primary-hi);
    text-decoration: underline;
}
.legal-notice-text a:hover { color: var(--c-primary); }
.legal-notice-actions {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    gap: 10px;
}
.legal-notice-btn {
    padding: 8px 16px;
    border-radius: var(--radius-sm, 6px);
    border: 1px solid transparent;
    font: inherit;
    cursor: pointer;
}
.legal-notice-btn.primary {
    background: var(--c-primary);
    color: var(--c-light, #ffffff);
    border-color: var(--c-primary);
}
.legal-notice-btn.primary:hover {
    background: var(--c-primary-hi);
    border-color: var(--c-primary-hi);
}

/* Permanente Legal-Links (Login-Footer + Map-Bottom-Bar). */
.legal-links {
    display: inline-flex;
    gap: 10px;
    align-items: center;
    font-size: 0.85em;
    color: var(--muted-hi);
}
.legal-links a {
    color: var(--muted-hi);
    text-decoration: none;
}
.legal-links a:hover {
    color: var(--c-primary-hi);
    text-decoration: underline;
}
.legal-links .sep {
    opacity: 0.55;
    user-select: none;
}

/* Auf der Map sitzen die Legal-Links rechts neben der Attribution
 * unten mittig, in der gleichen Zeile. */
.map-legal-links {
    position: absolute;
    right: 8px;
    bottom: 0;
    z-index: 600;
    background: var(--map-info-bg);
    color: var(--muted-hi);
    border-radius: 6px 6px 0 0;
    padding: 2px 8px;
    font-size: 11px;
    pointer-events: auto;
}
.map-legal-links a {
    color: var(--c-primary-hi);
    text-decoration: none;
}
.map-legal-links a:hover { text-decoration: underline; }

/* Mobile: Banner laesst Schaltflaechen unter dem Text einrasten. */
@media (max-width: 540px) {
    .legal-notice { left: 8px; right: 8px; bottom: 8px; }
    .legal-notice-card { padding: 12px; }
    .legal-notice-actions { justify-content: stretch; }
    .legal-notice-btn.primary { width: 100%; }
}

/* ============================================================
 — Tristate-BG-Tint, Center-Inputs links, Clear-Selection-Dark,
 Login-Topbar-Buttons
 ============================================================ */

/* Tristate: Hintergrund-Tint statt Text-Tint */
.features-panel-tristate-btn[data-state="all"] {
    background: rgba(2, 254, 137, 0.18) !important;
    color: var(--fg) !important;
    border-color: rgba(2, 254, 137, 0.45) !important;
}
.features-panel-tristate-btn[data-state="all"]:hover,
.features-panel-tristate-btn[data-state="all"].is-active {
    background: rgba(2, 254, 137, 0.42) !important;
    border-color: var(--c-signal-dk) !important;
    color: var(--fg) !important;
}
.features-panel-tristate-btn[data-state="any"] {
    background: rgba(0, 160, 210, 0.18) !important;
    color: var(--fg) !important;
    border-color: rgba(0, 160, 210, 0.45) !important;
}
.features-panel-tristate-btn[data-state="any"]:hover,
.features-panel-tristate-btn[data-state="any"].is-active {
    background: rgba(0, 160, 210, 0.40) !important;
    border-color: var(--c-primary-hi) !important;
    color: var(--fg) !important;
}
.features-panel-tristate-btn[data-state="not"] {
    background: rgba(255, 92, 101, 0.18) !important;
    color: var(--fg) !important;
    border-color: rgba(255, 92, 101, 0.45) !important;
}
.features-panel-tristate-btn[data-state="not"]:hover,
.features-panel-tristate-btn[data-state="not"].is-active {
    background: rgba(255, 92, 101, 0.42) !important;
    border-color: var(--c-error) !important;
    color: var(--fg) !important;
}

/* Default-Center-Inputs (im Admin-Modal) linksbuendig - per default
 * sind type=number rechtsbuendig in vielen Browsern. */
.modal-card .field input[type="number"] {
    text-align: left !important;
}

/* Clear-Selection im Dark-Mode: dunkler Grauton statt weiss */
[data-theme="dark"] .features-panel-actionbar [data-action="clear-selection"] {
    background: #2a3036 !important;
    color: var(--fg) !important;
    border-color: var(--border) !important;
}
[data-theme="dark"] .features-panel-actionbar [data-action="clear-selection"]:hover {
    background: #353c43 !important;
    border-color: var(--border-hi) !important;
}

/* Login-Topbar-Buttons (Help + Theme rechts oben) */
.login-topbar {
    position: absolute;
    top: 16px;
    right: 16px;
    z-index: 10;
    display: flex;
    gap: 8px;
}
.login-topbar .icon-btn {
    width: 36px; height: 36px;
    background: rgba(24, 27, 29, 0.55);
    color: var(--c-light);
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: var(--radius-sm);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.login-topbar .icon-btn:hover {
    background: rgba(0, 160, 210, 0.32);
    border-color: var(--c-primary-hi);
}
[data-theme="light"] .login-topbar .icon-btn {
    background: rgba(255, 255, 255, 0.85);
    color: #2a2f33;
    border-color: rgba(0, 96, 141, 0.18);
}

/* ============================================================
 + 65 — Marker-Icon-Picker im Feature-Modal
 Jedes Icon ist eigenstaendig (24x32) in der Layer-Farbe,
 ${COLOR} -> currentColor fuer die Vorschau im Picker.
 ============================================================ */

.marker-icon-picker {
    display: grid;
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: 6px;
    padding: 4px 0;
}
.marker-icon-pick {
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 4px;
    color: var(--c-primary);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background .12s, border-color .12s;
}
.marker-icon-pick:hover {
    background: var(--bg-card);
    border-color: var(--border-hi);
}
.marker-icon-pick.is-active {
    background: rgba(0, 127, 180, 0.18);
    border-color: var(--c-primary-hi);
}
[data-theme="light"] .marker-icon-pick {
    background: var(--bg);
    color: var(--c-primary-dk);
}
[data-theme="light"] .marker-icon-pick.is-active {
    background: rgba(0, 127, 180, 0.20);
}
.marker-icon-pick svg { display: block; }

/* 2026-06-30 (JP): kompakter Icon-Picker + Custom-Icon-Vollmenue. */
.marker-icon-pick--more { color: var(--text-muted); font-weight: 700; }
.marker-icon-pick--custom img { width: 26px; height: 26px; object-fit: contain; }
.icon-menu-section-label {
    font-size: 12px;
    color: var(--text-muted);
    margin: 10px 0 6px;
    text-transform: uppercase;
    letter-spacing: .04em;
}
.icon-menu-grid {
    display: grid;
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: 6px;
}
.icon-menu-grid--custom { grid-template-columns: repeat(6, minmax(0, 1fr)); }
.icon-menu-custom-tile { position: relative; display: inline-flex; }
.icon-menu-custom-tile .marker-icon-pick { width: 100%; }
.icon-menu-del {
    position: absolute;
    top: -6px;
    right: -6px;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    border: 1px solid var(--border);
    background: var(--c-danger, #b91c1c);
    color: #fff;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    line-height: 0;
}
.icon-menu-del:hover { filter: brightness(1.1); }
.icon-menu-empty, .icon-menu-loading {
    grid-column: 1 / -1;
    color: var(--text-muted);
    font-size: 13px;
    padding: 6px 2px;
}
.icon-menu-upload {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-top: 12px;
    padding: 8px 12px;
    border: 1px dashed var(--border-hi);
    border-radius: var(--radius-sm);
    color: var(--c-primary);
    cursor: pointer;
    transition: background .12s, border-color .12s;
}
.icon-menu-upload:hover { background: var(--bg-card); border-color: var(--c-primary); }
.geolyser-custom-pin img { width: 30px; height: 30px; object-fit: contain; display: block; }

/* ============================================================
 — Help-Btn gruen, brand-name groesser, etc.
 ============================================================ */

/* Help-Button gruen statt blau */
.topbar #help-btn {
    background: rgba(2, 254, 137, 0.18) !important;
    color: #007a3a !important;
    border-color: rgba(2, 254, 137, 0.45) !important;
}
.topbar #help-btn:hover {
    background: rgba(2, 254, 137, 0.32) !important;
    color: #006a2c !important;
}
[data-theme="dark"] .topbar #help-btn {
    color: #6dffb4 !important;
}

/* brand-name etwas groesser */
.topbar .wordmark, #brand-name {
    font-size: 1.18em;
    font-weight: 600;
    letter-spacing: 0.01em;
}

/* Login-Topbar Help-Btn ist raus - nur Theme bleibt. Falls noch im DOM,
 * ausblenden. */
#login-help-btn { display: none !important; }

/* ============================================================
 k — Mobile- und Tablet-Optimierung
 Hauptziel Tablet (≤ 1024 px), Smartphone (≤ 540 px) als
 "Funktioniert auch". Sidebars werden automatisch collapsed,
 Modals nutzen mehr Bildschirm, Touch-Targets vergroessert.
 ============================================================ */

/* Tablet-Range: 540 - 1024 px */
@media (max-width: 1024px) {
    /* Sidebar-Defaults auf "collapsed" - User kann sie aufklappen wenn
     * gebraucht, aber Karte hat erstmal Vorrang. */
    .sidebar { flex-basis: var(--sidebar-rail-w); width: var(--sidebar-rail-w); }
    .features-panel { flex-basis: var(--sidebar-rail-w); width: var(--sidebar-rail-w); }
    .sidebar:not(.sidebar--collapsed),
    .features-panel:not(.features-panel--collapsed) {
        /* Wenn der User explizit aufklappt, soll die Sidebar mehr Platz
         * fressen (~40% statt 25%) damit der Inhalt lesbar ist. */
        width: 40% !important;
        flex-basis: 40% !important;
        max-width: 360px;
    }

    /* Mobile-UI-Refresh : Modals im Mobile auf echtem Vollbild
 * ohne abgerundete Ecken. Vorher 96vw mit 16px Margin -> "halb-
 * abgerundet" mit Schwebe-Effekt, der bei Touch-Bedienung im Weg ist.
 * Jetzt: 100vw x 100dvh, border-radius: 0, kein margin. modal-body
 * scrollt intern, damit Header + Footer-Buttons immer sichtbar bleiben.
 *
 * Mobile-D-Fix : `.modal`-Wrapper hatte noch `padding: 24px`
 * + Backdrop, dadurch war die Modal-Card nicht direkt am Screen-Rand
 * sondern hatte 24px-Outer-Margin. Modal soll den Screen
 * direkt ausfuellen, kein sichtbarer Backdrop-Ring. */
    .modal {
        padding: 0 !important;
        background: transparent !important;
        backdrop-filter: none !important;
        -webkit-backdrop-filter: none !important;
    }
    .modal-card {
        max-width: 100vw !important;
        width: 100vw !important;
        max-height: 100dvh !important;
        height: 100dvh !important;
        margin: 0 !important;
        border-radius: 0 !important;
        display: flex !important;
        flex-direction: column !important;
    }
    .modal-card > .modal-header,
    .modal-card > .modal-footer {
        flex-shrink: 0;
    }
    .modal-card > .modal-body,
    .modal-card > .modal-form {
        flex: 1 1 auto;
        overflow-y: auto;
        padding: 14px;
    }

    /* Topbar: schmaler, Brand-Wordmark gekuerzt. */
    .topbar { padding: 6px 10px; }
    .topbar #brand-name { font-size: 1em; }

    /* Mobile-UI-Refresh * Touch-Target-Werte von 40/44 px auf 32 px reduziert. Knapp unter
 * Apple-Empfehlung 44pt, aber fuer den taeglichen Daumen-Tap
 * komfortabel. Falls zu klein -> Wert pro Klasse erhoehen, ohne den
 * ganzen Block zu invalidieren. */
    .leaflet-bar a {
        width: 32px !important;
        height: 32px !important;
        line-height: 32px !important;
        font-size: 18px !important;
    }
    .gps-tools-btn {
        width: 32px;
        height: 32px;
    }
    .leaflet-control-locate a .leaflet-control-locate-location-arrow {
        width: 18px; height: 18px; margin: 7px;
    }

    /* Geoman-Toolbar: kleinere Buttons. */
    .leaflet-pm-toolbar a {
        width: 32px !important;
        height: 32px !important;
    }

    /* Layers-Toggle: kleiner. */
    .leaflet-control-layers-toggle {
        width: 32px !important;
        height: 32px !important;
        background-size: 20px 20px !important;
    }
}

/* Smartphone-Range: ≤ 540 px */
@media (max-width: 540px) {
    /* Sidebars auf 90% wenn aufgeklappt (verdrucken die Karte komplett -
     * das ist Absicht, weil sonst nichts mehr lesbar ist). */
    .sidebar:not(.sidebar--collapsed),
    .features-panel:not(.features-panel--collapsed) {
        width: 92% !important;
        flex-basis: 92% !important;
        max-width: none;
        position: absolute;
        top: 0;
        bottom: 0;
        z-index: 1200;
    }
    .sidebar:not(.sidebar--collapsed) { left: 0; }
    .features-panel:not(.features-panel--collapsed) { right: 0; }

    /* Mobile-UI-Refresh : <=540px erbt jetzt die Vollbild-
 * Werte aus dem 768px-Block (oben). Hier nur noch Touch-spezifische
 * Anpassungen. */

    /* Topbar: Logo + Wordmark + minimaler Abstand. Username-Pill muss
     * trotzdem klickbar bleiben. */
    .topbar { padding: 4px 6px; gap: 4px; }
    .topbar #brand-name { display: none; }
    .topbar .icon-btn {
        width: 36px; height: 36px;
    }

    /* Login-Card padding auf Smartphone reduzieren. */
    .login-card {
        max-width: 92vw;
        padding: 24px 18px;
    }

    /* GPS-Status oberhalb statt unteres Viertel mittig - damit kein
     * Overlap mit den GPS-Tools links unten. */
    .gps-tools-status.gps-tools-status--center {
        bottom: 28%;
        max-width: 92%;
        font-size: 0.95em;
        padding: 8px 12px;
    }

    /* Mobile-F-Fix : Map-Status (Coords + GPS-Accuracy) wieder
 * an die ORIGINAL-Position oben mittig — die Mobile-D-Variante
 * "rechts unten" wurde im Portrait von der Scale-Bar / niedrigem
 * z-index ueberdeckt. Konsistenter ist die Original-Top-Center-
 * Position, hier mit dunklerem Background fuer Lesbarkeit + hoher
 * z-Index damit es ueber Leaflet-Controls liegt. */
    .map-status {
        font-size: 11px !important;
        padding: 3px 10px !important;
        top: 8px !important;
        left: 50% !important;
        right: auto !important;
        bottom: auto !important;
        transform: translateX(-50%) !important;
        background: rgba(0, 0, 0, 0.65) !important;
        color: #fff !important;
        border: 1px solid rgba(255, 255, 255, 0.15) !important;
        border-radius: 6px !important;
        pointer-events: none !important;
        /* Mobile-N-Fix : z-index unter den auf 1200 sitzenden
 * Sidebars (.sidebar / .features-panel) — JP sah die GPS-Status-
 * Pille vorher durch das aufgeklappte Sidepanel durchscheinen. */
        z-index: 1100 !important;
    }
    .map-status-coords { color: #fff !important; }
    .map-status-accuracy { color: #4cd2ff !important; }

    /* Image-Slots (Feature-Edit-Modal) auf Smartphone in 3 Spalten,
     * sonst zu schmal. */
    .image-slots {
        grid-template-columns: repeat(3, 1fr) !important;
    }

    /* Marker-Icon-Picker: 4 Spalten statt 6. */
    .marker-icon-picker {
        grid-template-columns: repeat(4, minmax(0, 1fr)) !important;
    }

    /* Mobile-E-Fix * Circle-Button-Versuch zurueckgenommen — sah komisch aus, war
 * dauer-eingeblendet, und Drag funktionierte trotzdem nicht.
 * Im 768px-Block bewusst KEINE .resizable-handle-Regel mehr —
 * Default-Style greift (kleiner Original-Handle mit 3-Punkten).
 * Tablet-Anpassung (groessere Touch-Zone): siehe @media-Block
 * (min-width:541px) and (max-width:1024px) weiter unten.
 * Smartphone (<540px) Handle-Hide: separater Block weiter unten. */

    /* Datenschutz/Impressum-Pill rechts unten: kleiner, weiter weg. */
    .map-legal-links {
        font-size: 10px;
        padding: 1px 6px;
    }
}

/* Touch-spezifische Tweaks (kein Hover) */
@media (hover: none) {
    /* Hover-States verwirren auf Touch-Geraeten oft - reduzieren. */
    .leaflet-bar a:hover { background: var(--bg-elevated); }
    .gps-tools-btn:hover:not(:disabled) { background: var(--bg-elevated); }

    /* Mobile-E-Fix : Resize-Handle-Circle-Btn aus Mobile-D
 * rueckgaengig gemacht (sah komisch aus). Kein ::before-Override
 * mehr noetig. Tablet-Touch-Resize wird unten in
 * (min-width:541px) and (max-width:1024px) Touch-tauglich gemacht;
 * Smartphone-Range (<540px) wird Resize komplett deaktiviert. */
}

/* Mobile-E-Fix : Smartphone (<540px) — Resize-Handle komplett
 * aus, spart den 24px-Rand. Drag wird sowieso vom Daumen oft falsch
 * getriggert; Sidebars haben auf Smartphones eh feste Width (siehe
 * 540px-Block, .sidebar:not(.sidebar--collapsed) { width: 92% }).
 * Mobile-G3-Fix : zusaetzlich Map-Search-Toggle auf 28px
 * verkleinert (Desktop/Tablet bleibt 32, Smartphone braucht es kompakter). */
@media (max-width: 540px) {
    .resizable-handle {
        display: none !important;
    }
    /* Mobile-G5-Fix : Smartphone-Override fuer Map-Search-Toggle
 * wurde rueckgaengig gemacht — Default-Groesse 32x32 gilt jetzt
 * ueberall (siehe Default-Block der `.map-search-toggle`). */
}

/* Mobile-E-Fix : Tablet-Range (541-1024px) — Resize-Handle
 * sichtbar, etwas breiter als Desktop-Default fuer Touch-Treffer mit
 * dem Finger. Die ORIGINAL .resizable-grip mit den 3 Punkten bleibt
 * sichtbar als visuelles Signal. */
@media (min-width: 541px) and (max-width: 1024px) {
    .resizable-handle {
        width: 16px !important;
        right: -8px !important;
        touch-action: none;
    }
    .resizable-handle--left {
        right: auto !important;
        left: -8px !important;
    }
    .resizable-grip {
        opacity: 0.55 !important;
    }
}

/* ---------------------------------------------------------------------
 * Layer-Lade-Modal
 * ------------------------------------------------------------------- */
.load-modal-toolbar {
    display: flex; align-items: center; gap: 12px;
    padding: 8px 0 12px;
    /* position:relative, damit die absolut positionierten
 Filter-Popover (.lm-filter-popover) sich auf die Toolbar als
 containing block beziehen — nicht aufs naechste position:relative
 Eltern-Element irgendwo weiter oben. */
    position: relative;
}
/* Lade-Modal-Filter-Popover unterhalb des Chips,
 ueber der Liste schwebend. */
.lm-filter-popover {
    position: absolute;
    top: calc(100% - 4px);
    right: 0;
    z-index: 1300;
    min-width: 380px;
    background: var(--bg-card, #fff);
    border: 1px solid var(--border, #ccc);
    border-radius: 6px;
    box-shadow: 0 8px 22px rgba(0, 0, 0, 0.30);
    padding: 12px;
}
/* Dark-Mode-Hintergrund fuer Filter-Popover analog zum
 Modal-Header/Footer . Gilt sowohl fuer das Layers-Modal-
 Filter-Popover als auch das DB-Modal-Filter-Popover, damit das Layout
 ueberall einheitlich ist. var(--bg-card) ist im Dark-Mode oft semi-
 transparent — das wirkte hier mit der semi-transparenten Modal-Card
 doppelt durchscheinend. */
[data-theme="dark"] .lm-filter-popover,
[data-theme="dark"] .features-panel-popover.db-filter-popover {
    background: #272D31;
    border-color: rgba(255, 255, 255, 0.12);
}
/* polish runde 5: Search-Input hatte den selben BG wie das
 Modal - das war im hellen UND dunklen Theme schwer zu unterscheiden.
 Jetzt ein Tick dunkler/heller als die Modal-Card, damit das Input
 visuell klar als interaktives Element auftaucht. */
.load-modal-search {
    flex: 1 1 auto;
    height: 36px;
    padding: 0 12px;
    border: 1px solid var(--border-hi);
    border-radius: 6px;
    background: var(--bg-page);
    color: var(--fg);
    font-size: 14px;
    transition: border-color .12s ease, background .12s ease;
}
.load-modal-search:hover { border-color: var(--c-primary-hi); }
.load-modal-search:focus {
    outline: 2px solid var(--c-primary);
    outline-offset: -1px;
    border-color: var(--c-primary);
}
[data-theme="light"] .load-modal-search {
    background: #f1f4f7;
    border-color: #c8cfd6;
}
[data-theme="light"] .load-modal-search:focus {
    background: #fff;
}
/* Dark-Mode-Background analog DB-Modal-Search-Input
 im Dark-Mode . var(--bg-page) wirkte vorher zu transparent
 gegenueber der Modal-Card. */
[data-theme="dark"] .load-modal-search {
    background: #0D1214;
    border-color: rgba(255, 255, 255, 0.18);
}
.load-modal-count { white-space: nowrap; }
.load-modal-list {
    list-style: none; margin: 0; padding: 0;
    max-height: 60vh; overflow-y: auto;
    border-top: 1px solid var(--c-border);
}
.load-modal-row {
    display: grid;
    /* alle Spalten ausser Name auf FIXE px-Breite, damit
 die Action-Buttons und das Datum ueber alle Zeilen exakt vertikal
 ausgerichtet sind — egal ob die Zeile Coworker-Avatare hat, ob
 der Layer-Name lang oder kurz ist, oder ob das Feature-Count eine
 oder mehrere Stellen hat. fr-Spalten waren das Problem: ihr
 min-content vergroessert die Spalte automatisch, was die
 nachfolgenden Spalten verschoben hat.
 Spalten: checkbox / swatch / name (flex) / creator / meta(N
 Features) / datum / presence / actions. */
    grid-template-columns: 18px 14px minmax(140px, 1fr) 100px 100px 140px 96px 80px;
    gap: 10px; align-items: center;
    padding: 6px 10px;
    border-bottom: 1px solid var(--border);
    font-size: 0.9rem;
}
.load-modal-row:not(.load-modal-row--header):hover {
    background: var(--input-bg);
}
.load-modal-row .layer-presence-stack {
    justify-self: start;
    overflow: hidden;
    max-width: 100%;
}
/* globaler `:empty { display: none }` (Z3270) wuerde
 den leeren Presence-Placeholder im Layers-Modal unsichtbar machen,
 wodurch die Grid-Spalte zusammenbricht und die Action-Buttons in
 die Presence-Spalte rutschen. Im Layers-Modal-Kontext ueberschreiben
 wir das, sodass auch leere Placeholder ihren Spalten-Slot halten. */
.load-modal-row .layer-presence-stack:empty {
    display: inline-flex;
    min-width: 1px;
}
/* Action-Spalte ist 80px breit, beide 28x28-Btns + 4px Gap
 passen gerade rein. Rechtsbuendig damit der Trash- bzw. Cloud-Btn
 immer am rechten Rand der Spalte sitzt. */
.load-modal-row .load-modal-actions {
    display: inline-flex;
    gap: 4px;
    justify-self: end;
}
.load-modal-name-cell {
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
}
.load-modal-name-cell .load-modal-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.load-modal-date {
    font-size: 0.85em;
    color: var(--muted, #888);
    white-space: nowrap;
}
/* Per-Row-Action-Buttons im Layer-Modal — kompakte
 28x28 Icon-Btns, einheitliche Optik (Load=+, Unload=-, Export=Cloud-
 Download). Damit ist die Action-Spalte schmal und stoert das Spalten-
 Layout nicht. !important weil .ghost und .icon-btn-Pads sonst die
 Box durch hohe Spezifizierungs-Konkurrenz vergroessern. */
.load-modal-row-btn,
.load-modal-actions .load-modal-row-btn,
button.load-modal-row-btn.ghost.icon-btn {
    width: 28px !important;
    height: 28px !important;
    padding: 0 !important;
    min-width: 28px !important;
    min-height: 28px !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    line-height: 0 !important;
}
.load-modal-row-btn img,
.load-modal-row-btn svg {
    display: block;
}
/* Button-Farb-Modifier. is-success = grünlich,
 is-coral = orangerot. Werden u.a. fuer Load (gruen) und Unload (coral)
 im Layers-Modal sowie row-attach-active (gruen) im DB-Modal genutzt. */
.btn-success,
button.btn-success.ghost.icon-btn {
    background: rgba(76, 175, 80, 0.15);
    color: #4CAF50;
    border-color: rgba(76, 175, 80, 0.55);
}
.btn-success:hover,
button.btn-success.ghost.icon-btn:hover {
    background: rgba(76, 175, 80, 0.28);
    border-color: rgba(76, 175, 80, 0.80);
    color: #67c66a;
}
/* Amber-Variante (Remove-from-Layer im DB-Panel) analog
 zu btn-success. Gleicher Amber-Ton wie bei layer-badge--dirty. */
.btn-amber,
button.btn-amber.ghost.icon-btn {
    background: rgba(201, 138, 0, 0.15);
    color: var(--c-amber, #c98a00);
    border-color: rgba(201, 138, 0, 0.55);
}
.btn-amber:hover,
button.btn-amber.ghost.icon-btn:hover {
    background: rgba(201, 138, 0, 0.28);
    border-color: rgba(201, 138, 0, 0.80);
    color: #e6a627;
}
.btn-coral,
button.btn-coral.ghost.icon-btn {
    background: rgba(255, 127, 80, 0.15);
    color: #ff7f50;
    border-color: rgba(255, 127, 80, 0.55);
}
.btn-coral:hover,
button.btn-coral.ghost.icon-btn:hover {
    background: rgba(255, 127, 80, 0.28);
    border-color: rgba(255, 127, 80, 0.80);
    color: #ff9670;
}
/* Cyan-Variante (Edit/BulkEdit im DB-Modal)
 * analog zu btn-success/btn-amber. Geolyser-CI-Cyan #3BBDE8. Wird
 * fuer Edit-Aktionen genutzt — Konsistenz mit Sidebar/Sidepanel. */
.btn-cyan,
button.btn-cyan.ghost.icon-btn {
    background: rgba(59, 189, 232, 0.15);
    color: var(--c-cyan, #3BBDE8);
    border-color: rgba(59, 189, 232, 0.55);
}
.btn-cyan:hover,
button.btn-cyan.ghost.icon-btn:hover {
    background: rgba(59, 189, 232, 0.28);
    border-color: rgba(59, 189, 232, 0.80);
    color: #5acef0;
}
/* klickbare Variante des Color-Swatch im Lade-Modal. */
.load-modal-swatch--btn {
    border: 0;
    cursor: pointer;
    padding: 0;
    position: relative;
}
.load-modal-swatch--btn:hover { outline: 2px solid var(--c-primary, #06829c); }
.load-modal-recolor-pop {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    z-index: 1500;
    display: flex;
    gap: 4px;
    padding: 6px;
    border-radius: 6px;
    background: var(--bg-card, #fff);
    border: 1px solid var(--c-border, #ccc);
    box-shadow: 0 6px 18px rgba(0,0,0,0.20);
}
.load-modal-recolor-pick {
    width: 18px; height: 18px;
    border-radius: 3px;
    border: 2px solid transparent;
    cursor: pointer;
    padding: 0;
}
.load-modal-recolor-pick.is-active { border-color: #000; }
[data-theme="dark"] .load-modal-recolor-pick.is-active { border-color: #fff; }
/* Klickbarer Name -> Inline-Rename. */
.load-modal-name--btn {
    background: transparent;
    border: 0;
    text-align: left;
    color: inherit;
    cursor: pointer;
    padding: 2px 4px;
    border-radius: 3px;
}
.load-modal-name--btn:hover {
    background: rgba(0,0,0,0.05);
}
[data-theme="dark"] .load-modal-name--btn:hover {
    background: rgba(255,255,255,0.06);
}
.load-modal-name-edit {
    /* War weiss-auf-weiss im Dark-Mode.
 Root-cause: --bg-input existiert nicht (richtiger Name ist
 --input-bg), also griff der Fallback #fff. Und color war
 nicht gesetzt, daher inheritance vom Parent (light text im
 dark theme) -> weiss auf weiss. Fix: korrekter Variable-Name
 + expliziter Fallback #0d1214, plus color: var(--fg). */
    font: inherit;
    padding: 2px 4px;
    border: 1px solid var(--c-primary, #06829c);
    border-radius: 3px;
    background: var(--input-bg, #0d1214) !important;
    color: var(--fg, #eef3f6) !important;
}
/* Creator-Name als kleine Spalte. */
.load-modal-creator {
    font-size: 0.85em;
    color: var(--muted, #888);
    white-space: nowrap;
    max-width: 14ch;
    overflow: hidden;
    text-overflow: ellipsis;
}
.load-modal-row.is-checked {
    background: rgba(0, 204, 255, 0.10);
}
/* Header-Row mit sortierbaren Spalten — Background +
 Color angeglichen an .trash-table th. Sticky bleibt, damit beim
 Scrollen die Spalten-Header sichtbar bleiben. */
.load-modal-row--header {
    background: var(--input-bg);
    color: var(--muted-hi);
    font-weight: 600;
    position: sticky;
    top: 0;
    z-index: 2;
}
.load-modal-row--header .load-modal-swatch--header {
    background: transparent;
    border: none;
}
.load-modal-sort-btn {
    background: transparent;
    border: 0;
    text-align: left;
    color: inherit;
    cursor: pointer;
    padding: 2px 4px;
    border-radius: 3px;
    font: inherit;
    font-weight: 600;
}
.load-modal-sort-btn:hover {
    background: rgba(0,0,0,0.05);
}
[data-theme="dark"] .load-modal-sort-btn:hover {
    background: rgba(255,255,255,0.06);
}
/* Lade-Modal-Variante des Avatar-Stacks: gleiche Chip-Optik, nur ohne
   den linken Innenabstand der Sidebar (Grid-Gap reicht hier). */
.load-modal-row .load-modal-presence {
    padding: 0;
    margin: 0;
}
.load-modal-row:last-child { border-bottom: none; }
.load-modal-swatch {
    width: 14px; height: 14px;
    border-radius: 3px;
    background: var(--swatch, var(--c-primary));
    box-shadow: inset 0 0 0 1px rgba(0,0,0,.2);
}
.load-modal-name {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font-weight: 600;
}
.load-modal-meta { font-size: 12px; color: var(--c-fg-muted); white-space: nowrap; }
.load-modal-badge {
    font-size: 11px; padding: 2px 8px;
    border-radius: 999px;
    background: var(--c-success-bg, rgba(46, 160, 67, .15));
    color: var(--c-success-fg, #2ea043);
    font-weight: 600;
    /* polish runde 9: feste Breite damit das Layout beim
 Toggle stabil bleibt - "geladen" ist 7 Zeichen, ~64px reicht. */
    min-width: 64px; text-align: center;
}
.load-modal-badge.is-hidden {
    visibility: hidden;
}
/* "fremd"-Badge fuer Workspace-Layer anderer User. */
.load-modal-badge.load-modal-badge--foreign {
    background: var(--bg-elevated, rgba(0, 0, 0, 0.08));
    color: var(--muted-hi, #666);
    margin-left: 6px;
    font-style: italic;
    font-weight: 500;
}
[data-theme="dark"] .load-modal-badge.load-modal-badge--foreign {
    background: rgba(255, 255, 255, 0.12);
    color: #ccc;
}
.load-modal-row--foreign .load-modal-swatch {
    opacity: 0.7;
}
.load-modal-actions { display: flex; gap: 6px; align-items: center; }
/* polish runde 8: Laden- und Entfernen-Btn auf identische
 Breite + Hoehe normieren, damit der Layer-Eintrag beim Toggle
 nicht visuell springt. */
.load-modal-actions [data-action="load"],
.load-modal-actions [data-action="unload"] {
    min-width: 110px;
    height: 32px;
    padding: 0 12px;
    justify-content: center;
}
.load-modal-empty { padding: 20px; text-align: center; }

.modal-actions--column {
    flex-direction: column !important;
    align-items: stretch;
    gap: 8px;
}
.modal-actions--column > button { width: 100%; }

/* Export-Format-Modal: Buttons (".geolyser ZIP", "GeoJSON", "GPKG"
   etc.) sollen in Dark- und Light-Mode klar lesbar sein. .primary hat
   bereits color: var(--c-light) (weiss), aber wir setzen es explizit
   damit kein anderer Selektor das ueberschreibt. */
#export-format-modal .modal-actions button.primary {
    color: var(--c-light, #fff);
}
#export-format-modal .modal-actions button.primary:hover {
    color: var(--c-light, #fff);
}

/* Sidebar-Rail "Layer laden"-Button. */
.sidebar-rail-load {
    border: none; background: transparent; cursor: pointer;
    color: var(--c-fg-muted);
    width: 32px; height: 32px;
    display: flex; align-items: center; justify-content: center;
    border-radius: 6px;
    margin-top: 4px;
}
.sidebar-rail-load:hover { background: var(--bg-elevated); color: var(--c-fg); }

/* Layer-Sharing-Tab (Admin-Modal): "schon vorhanden" abgedimmt. */
.trash-table tr.is-disabled { opacity: 0.55; }

/* Bulk-Tags-Bar im DB-Modal-Footer. */
.db-bulk-tags-bar {
    display: flex; flex-wrap: wrap; gap: 12px;
    align-items: center;
    padding: 10px 16px;
    border-top: 1px solid var(--c-border);
    background: var(--bg-elevated);
}
.db-bulk-tags-bar label {
    display: flex; flex-direction: column; gap: 4px;
    font-size: 12px; color: var(--c-fg-muted);
}
.db-bulk-tags-bar input[type="text"] {
    height: 32px; padding: 0 10px;
    border: 1px solid var(--c-border); border-radius: 4px;
    background: var(--bg-input, var(--bg-elevated)); color: var(--c-fg);
    font-size: 13px; min-width: 220px;
}
.db-export-format {
    height: 32px; padding: 0 8px;
    border: 1px solid var(--c-border); border-radius: 4px;
    background: var(--bg-input, var(--bg-elevated)); color: var(--c-fg);
    font-size: 13px;
}
.db-import-tags {
    height: 32px; padding: 0 10px;
    border: 1px solid var(--c-border); border-radius: 4px;
    background: var(--bg-input, var(--bg-elevated)); color: var(--c-fg);
    font-size: 13px;
}

/* ---------------------------------------------------------------------
 * Polish: Admin-Tabellen vertikal zentriert, Profile-Modal
 * breiter, Buttons in den Tabellen kompakter.
 * ------------------------------------------------------------------- */

/* Profile-Modal default so breit wie das Admin-Einstellungen-Modal. */
#profile-modal .modal-card {
    max-width: 980px;
    width: 95%;
}

/* Admin-Tabellen: alle Zellen vertikal mittig, gleiche Hoehe ueber
   Text/Icons/Buttons/Checkboxes/Selects. */
#admin-modal .trash-table th,
#admin-modal .trash-table td,
#admin-modal .admin-users-table th,
#admin-modal .admin-users-table td {
    vertical-align: middle;
    padding: 8px 10px;
    line-height: 1.4;
}
#admin-modal .trash-table td button,
#admin-modal .trash-table td select,
#admin-modal .trash-table td input[type="checkbox"],
#admin-modal .admin-users-table td button,
#admin-modal .admin-users-table td select,
#admin-modal .admin-users-table td input[type="checkbox"] {
    vertical-align: middle;
}

/* Tabellen-Buttons kompakter: nur das wichtigste, kein riesiges Padding. */
#admin-modal .trash-table td .ghost,
#admin-modal .trash-table td .primary,
#admin-modal .trash-table td .ghost.danger,
#admin-modal .admin-users-table td .ghost,
#admin-modal .admin-users-table td .primary,
#admin-modal .admin-users-table td .ghost.danger {
    height: 32px;
    padding: 0 12px;
    font-size: 13px;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

/* Action-Cell mit mehreren Buttons: gleichmaessiger Abstand, kein Wrap. */
.admin-users-row-actions {
    display: flex;
    gap: 6px;
    flex-wrap: nowrap;
    align-items: center;
}

/* Code-URL nicht ueberlaufen. */
#admin-modal .trash-table td code {
    font-size: 12px;
    word-break: break-all;
}

/* Active-Checkbox in Users-Tabelle in der Mitte zentrieren. */
.admin-users-table td:has(input[type="checkbox"]) {
    text-align: center;
}

/* ---------------------------------------------------------------------
 * polish: DB-Modal-Refactor (3 Buttons unter Liste, Import
 * separat, Auswahl-editieren / Export / Import als eigene Modals).
 * ------------------------------------------------------------------- */

.db-import-row {
    display: flex; align-items: center; gap: 12px;
    padding: 6px 16px;
    border-bottom: 1px solid var(--c-border);
}
.modal-footer--compact {
    padding: 10px 16px;
    gap: 8px;
}
.modal-footer--compact .ghost,
.modal-footer--compact .primary {
    height: 34px;
    padding: 0 14px;
    font-size: 13px;
}

.bulk-edit-toolbar {
    display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end;
    padding: 10px 16px;
    border-bottom: 1px solid var(--c-border);
}
.bulk-edit-toolbar label {
    display: flex; flex-direction: column; gap: 4px;
    font-size: 12px; color: var(--c-fg-muted);
}
.bulk-edit-toolbar input[type="text"],
.bulk-edit-toolbar select,
.bulk-edit-toolbar input[type="date"] {
    height: 32px; padding: 0 10px;
    border: 1px solid var(--border); border-radius: 4px;
    /* explizit input-bg + fg, sonst hatten Inputs im
 Dark-Mode fast denselben Hintergrund wie der Body und waren
 schwer lesbar. */
    background: var(--input-bg, var(--bg-elevated, #fff));
    color: var(--fg, #111);
    font-size: 13px; min-width: 220px;
}
.bulk-edit-toolbar button.ghost,
.bulk-edit-toolbar button.primary {
    background: var(--bg-card);
    color: var(--fg);
    border: 1px solid var(--border);
}
.bulk-edit-toolbar button.primary {
    background: var(--c-primary, #007fb4);
    color: #fff;
    border-color: var(--c-primary, #007fb4);
}
.bulk-edit-color-tiles {
    display: flex; flex-wrap: wrap; gap: 4px;
    margin-top: 4px;
}
/* Bulk-Add-Block symmetrisch zum Remove-Block - Chips
 oben, Input-Feld darunter. */
.bulk-edit-add-block {
    display: flex;
    flex-direction: column;
    gap: 4px;
    flex: 1 1 220px;
    min-width: 200px;
}
.bulk-edit-add-chips {
    display: flex; flex-wrap: wrap; gap: 4px;
    min-height: 32px;
    padding: 4px;
    border: 1px dashed var(--border);
    border-radius: 4px;
    background: var(--input-bg, var(--bg-elevated, #fff));
}
.bulk-edit-add-chip {
    display: inline-flex;
    align-items: stretch;
    background: var(--c-primary, #007fb4);
    color: #fff;
    border-radius: 999px;
    font-size: 0.85em;
    overflow: hidden;
}
.bulk-edit-add-chip-body {
    background: transparent;
    color: inherit;
    border: none;
    padding: 2px 4px 2px 8px;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.bulk-edit-add-chip-body:hover { filter: brightness(1.1); }
.bulk-edit-add-chip-x {
    background: rgba(0, 0, 0, 0.18);
    color: inherit;
    border: none;
    padding: 2px 8px;
    cursor: pointer;
    font-weight: bold;
}
.bulk-edit-add-chip-x:hover { background: rgba(0, 0, 0, 0.32); }
.bulk-edit-add-chip-swatch {
    display: inline-block;
    width: 10px; height: 10px;
    border-radius: 50%;
    border: 1px solid rgba(255,255,255,0.5);
}
.bulk-edit-add-chip-swatch--none {
    background:
        repeating-linear-gradient(45deg,
            rgba(255,255,255,0.3) 0 2px,
            rgba(0,0,0,0.0) 2px 4px);
}
.bulk-edit-add-input {
    height: 32px;
    padding: 0 10px;
    border: 1px solid var(--border);
    border-radius: 4px;
    background: var(--input-bg, var(--bg-elevated, #fff));
    color: var(--fg, #111);
    font-size: 13px;
}
.bulk-edit-list,
.import-preview-list {
    list-style: none; margin: 0; padding: 0;
    max-height: 60vh; overflow-y: auto;
}
.bulk-edit-list li,
.import-preview-list li {
    display: grid;
    grid-template-columns: 1fr auto auto auto;
    gap: 10px; align-items: center;
    padding: 10px 16px;
    border-bottom: 1px solid var(--c-border);
}
.bulk-edit-list li:last-child,
.import-preview-list li:last-child { border-bottom: none; }
.import-preview-name {
    display: inline-flex; align-items: center; gap: 8px;
    font-weight: 500;
}
.import-preview-name input[type="text"] {
    flex: 1; min-width: 240px;
    height: 28px; padding: 0 8px;
    border: 1px solid transparent; border-radius: 4px;
    background: transparent; color: var(--c-fg);
    font-size: 14px;
}
.import-preview-name input[type="text"]:hover,
.import-preview-name input[type="text"]:focus {
    border-color: var(--c-border);
    background: var(--bg-input, var(--bg-elevated));
    outline: none;
}
.import-preview-tags {
    display: flex; flex-wrap: wrap; gap: 4px;
    font-size: 12px;
}
.import-modal-settings {
    padding: 12px 16px;
    border-bottom: 1px solid var(--c-border);
}
.import-modal-settings label {
    display: flex; flex-direction: column; gap: 4px;
    font-size: 12px; color: var(--c-fg-muted);
}
.import-modal-settings input[type="text"] {
    height: 32px; padding: 0 10px;
    border: 1px solid var(--c-border); border-radius: 4px;
    background: var(--bg-input, var(--bg-elevated)); color: var(--c-fg);
    font-size: 13px; max-width: 320px;
}

/* ============================================================
 polish runde 7 - Design-Polish-Sammelblock
 ============================================================ */

/* Bulk-Edit "Tags entfernen" als Chip-Picker (statt Free-Text). */
.bulk-edit-remove-block {
    display: flex; flex-direction: column; gap: 6px;
    flex: 1 1 220px;
}
.bulk-edit-remove-block > span {
    font-size: 0.85em; color: var(--muted-hi);
}
.bulk-edit-remove-chips {
    display: flex; flex-wrap: wrap; gap: 6px;
    min-height: 36px;
    padding: 6px 8px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--bg-page);
    align-items: center;
}
[data-theme="light"] .bulk-edit-remove-chips {
    background: #f1f4f7;
    border-color: #c8cfd6;
}
.bulk-edit-remove-chip {
    background: var(--bg-elevated);
    color: var(--fg);
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 3px 10px;
    font-size: 0.85em;
    cursor: pointer;
    transition: background .12s, border-color .12s, color .12s;
}
.bulk-edit-remove-chip:hover {
    border-color: var(--c-error);
    color: var(--c-error);
}
.bulk-edit-remove-chip.is-active {
    background: var(--c-error);
    color: var(--c-light);
    border-color: var(--c-error);
}

/* Modal-Close-Btn (X oben rechts): klar als Button hervorgehoben in
 beiden Themes - frueher unauffaellig grau.
 polish runde 9: ROT-Outline schon im Ruhezustand damit der
 Btn eindeutig als "Schliessen"-Aktion lesbar ist. */
.modal-close-btn {
    width: 32px; height: 32px;
    border-radius: var(--radius-sm);
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--c-error-bg) !important;
    color: var(--c-error) !important;
    border: 1px solid var(--c-error) !important;
    transition: background .12s, color .12s, border-color .12s;
}
.modal-close-btn:hover {
    background: var(--c-error) !important;
    color: var(--c-light) !important;
    border-color: var(--c-error) !important;
}
[data-theme="light"] .modal-close-btn {
    background: #ffe5e7 !important;
    color: #b00020 !important;
    border-color: #b00020 !important;
}
[data-theme="light"] .modal-close-btn:hover {
    background: #b00020 !important;
    color: #fff !important;
    border-color: #b00020 !important;
}

/* Import-Modal Inputs: deutlich anderer BG als das Modal selbst -
   gleich wie der Lade-Modal-Search-Input aus Runde 5. */
.import-modal-settings input[type="text"] {
    border: 1px solid var(--border-hi);
    background: var(--bg-page);
}
.import-modal-settings input[type="text"]:focus {
    outline: 2px solid var(--c-primary);
    outline-offset: -1px;
    border-color: var(--c-primary);
}
[data-theme="light"] .import-modal-settings input[type="text"] {
    background: #f1f4f7;
    border-color: #c8cfd6;
}
[data-theme="light"] .import-modal-settings input[type="text"]:focus {
    background: #fff;
}
/* Dark-Mode-Background analog zu den anderen
 Input-Feldern im Dark-Mode . var(--bg-page) wirkte vorher
 inkonsistent gegenueber den uebrigen Modal-Inputs. */
[data-theme="dark"] .import-modal-settings input[type="text"] {
    background: #0D1214;
    border-color: rgba(255, 255, 255, 0.18);
}

/* Save-Options-Modal: Buttons in column-layout sind alle konsistent
   gross + zentriert. Die Discard-Action liegt visuell separiert vom
   Speichern-Block durch margin-top. Die "Original verwerfen"-Checkbox
   sitzt direkt unter den Save-Buttons als Modifier. */
#save-options-modal .modal-actions--column { gap: 8px; }
#save-options-modal .modal-actions--column > button {
    height: 40px;
    width: 100%;
    justify-content: center;
    padding: 0 14px;
}
#save-options-modal #save-options-discard-original-row {
    margin: 4px 0 4px 4px;
    font-size: 0.9em;
    color: var(--muted-hi);
    display: flex; align-items: center; gap: 6px;
}
/* Verwerfen-Button durch Margin-Abstand separiert (nicht durch
   border auf dem Btn selbst, das macht das Padding kaputt). */
#save-options-modal [data-action="discard"] {
    margin-top: 14px;
    position: relative;
}
#save-options-modal [data-action="discard"]::before {
    content: "";
    position: absolute;
    top: -8px; left: 0; right: 0;
    border-top: 1px solid var(--border);
}

/* Confirm-Card (zB "Nutzer loeschen?", "Papierkorb leeren?"): Buttons
 zentriert, etwas groesser - JP wollte sie weg vom rechten Rand.
 polish runde 9: justify-content: center statt flex-end. */
.confirm-card .modal-actions {
    margin-top: 20px;
    gap: 12px;
    justify-content: center;
}
.confirm-card .modal-actions button {
    min-width: 120px;
    height: 38px;
}

/* Right Sidepanel (Datenbank) im Light-Mode etwas blauer, damit
   sich die Sidebar visuell vom Map-Hintergrund abhebt. */
[data-theme="light"] .features-panel {
    background: linear-gradient(180deg, #eaf1f8 0%, #e3ecf4 100%);
    border-left: 1px solid #c1ced9;
}
[data-theme="light"] .features-panel-rail {
    background: #dde7f0;
    border-left: 1px solid #c1ced9;
}
[data-theme="light"] .features-panel-head {
    border-bottom: 1px solid #c1ced9;
}

/* polish runde 9: Mini-Map fuer Geometrie-Edit im Feature-
 Modal. Aspect-Ratio + dunklerer Border damit der Map-Block sich
 klar von den anderen Form-Feldern absetzt. Geoman-Toolbar wird
 ueber pmIgnore/Klick-Toggle gesteuert (siehe map.js). */
.feature-geomedit-mini {
    width: 100%;
    height: 220px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-hi);
    background: var(--bg-page);
    overflow: hidden;
    margin-top: 4px;
}
.feature-geomedit-toggle {
    background: transparent;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    color: var(--muted-hi);
    padding: 2px 8px;
    cursor: pointer;
    transition: background .12s, color .12s, border-color .12s;
}
.feature-geomedit-toggle:hover {
    background: var(--bg-card);
    color: var(--fg);
    border-color: var(--border-hi);
}
.feature-geomedit-toggle.is-active {
    background: var(--c-primary);
    color: var(--c-light);
    border-color: var(--c-primary-dk);
}
.feature-geomedit-hint { color: var(--muted); }

/* DB-Vollansicht "Mehr laden"-Btn am Tabellenende. */
.db-load-more-wrap {
    display: flex; justify-content: center;
    padding: 14px 0 6px;
}
.db-load-more {
    min-width: 200px;
}

/* ============================================================
 — GCP- + ArUco-Capture-Modal
 ============================================================ */
.gcp-capture-body {
    display: flex; flex-direction: column; gap: 14px;
    padding: 12px 0;
}
.gcp-capture-list {
    list-style: none; margin: 0; padding: 0;
    max-height: 50vh; overflow-y: auto;
    border-top: 1px solid var(--border);
}
/* GCP-Live-Layer (2026-06-11): Zeile von 3-Spalten-Grid auf Flex
 umgestellt - es gibt jetzt optional ein ArUco-Thumb vor der Nummer,
 einen Name+Koordinaten-Block und rechts die Aktions-Buttons
 (Edit / Quick-Foto / Entfernen). */
.gcp-list-row {
    display: flex;
    gap: 10px; align-items: center;
    padding: 8px 4px;
    border-bottom: 1px solid var(--border);
}
.gcp-list-row:last-child { border-bottom: none; }
.gcp-list-num {
    flex: 0 0 auto;
    font-weight: 600;
    font-size: 1.05em;
    color: var(--c-primary-hi);
}
.gcp-list-main {
    flex: 1 1 auto;
    min-width: 0;
    display: flex; flex-direction: column; gap: 2px;
}
.gcp-list-name {
    font-weight: 600;
    font-size: 0.92em;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.gcp-list-coords {
    font-family: var(--font-mono, ui-monospace, "SF Mono", monospace);
    font-size: 0.85em;
}
.gcp-list-actions {
    flex: 0 0 auto;
    display: flex; align-items: center; gap: 2px;
}
/* Mini-ArUco-Vorschau in der Listen-Zeile (nur ArUco-Modus). */
.gcp-list-aruco {
    flex: 0 0 auto;
    width: 28px; height: 28px;
    background: #fff;
    padding: 2px; box-sizing: border-box;
    border: 1px solid var(--border);
    border-radius: 3px;
}
/* Quick-Foto-Btn: Badge mit Bild-Anzahl oben rechts am Button. */
.gcp-photo-btn { position: relative; }
.gcp-photo-badge {
    position: absolute;
    top: -4px; right: -4px;
    background: var(--c-primary);
    color: #fff;
    border-radius: 999px;
    min-width: 15px; height: 15px;
    padding: 0 3px;
    display: flex; align-items: center; justify-content: center;
    font-size: 10px; font-weight: 700;
    pointer-events: none;
}
/* ArUco-Map-Marker (features.js dropPinIcon, slug "aruco-N"):
 Mini-Version des echten ArUco-Markers, weisser Rand als Quiet-Zone,
 zentriert auf dem Messpunkt. */
.geolyser-aruco-pin img {
    display: block;
    width: 26px; height: 26px;
    background: #fff;
    padding: 2px; box-sizing: border-box;
    border-radius: 3px;
    box-shadow: 0 0 0 1px rgba(0,0,0,0.4), 0 1px 3px rgba(0,0,0,0.3);
    image-rendering: pixelated;
}
.gcp-capture-empty {
    text-align: center;
    padding: 24px 16px;
    color: var(--muted);
    font-style: italic;
}

/* ArUco-Slot-Grid: 3 Spalten x 2 Zeilen, klickbare Bilder. */
.aruco-slots {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 12px;
    padding: 4px;
}
/* Das display:grid oben hat sonst das
 hidden-Attribut ueberstimmt — nach einer ArUco-Session blieben die
 Slots beim Re-Open in GCP-Modus sichtbar. */
.aruco-slots[hidden] { display: none; }
.aruco-slot {
    position: relative;
    background: var(--bg-page);
    border: 2px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 8px;
    cursor: pointer;
    transition: border-color .12s, transform .08s;
}
.aruco-slot:hover { border-color: var(--c-primary-hi); }
.aruco-slot:active { transform: scale(0.97); }
.aruco-slot.is-filled {
    border-color: var(--c-primary);
    background: rgba(0, 179, 104, 0.10);
}
.aruco-slot img {
    display: block;
    width: 100%; height: auto;
    pointer-events: none;
}
.aruco-slot-num {
    position: absolute;
    top: 4px; left: 6px;
    background: var(--bg-elevated);
    color: var(--fg);
    border-radius: 50%;
    width: 22px; height: 22px;
    display: flex; align-items: center; justify-content: center;
    font-size: 12px; font-weight: 700;
    box-shadow: 0 1px 3px rgba(0,0,0,0.2);
}
.aruco-slot-check {
    position: absolute;
    bottom: 4px; right: 6px;
    background: var(--c-primary);
    color: #fff;
    border-radius: 50%;
    width: 22px; height: 22px;
    display: flex; align-items: center; justify-content: center;
    font-size: 14px; font-weight: 700;
}
[data-theme="light"] .aruco-slot {
    background: #f1f4f7;
}
.gcp-capture-add {
    border-color: var(--c-primary) !important;
    color: var(--c-primary-hi) !important;
}
.gcp-capture-add:hover {
    background: rgba(0, 179, 104, 0.10) !important;
}
/* 2026-06-29 (JP): Footer-Layout. Aufnahme-Button links (gross), rechts
 * die Icon-Buttons Export + Speichern (je 40x40). */
.gcp-capture-footer {
    display: flex;
    align-items: center;
    gap: 8px;
}
.gcp-capture-footer-right {
    display: flex;
    align-items: center;
    gap: 8px;
    /* immer rechtsbuendig — auch wenn der Aufnahme-Button (GCP) fehlt,
     * weil er im ArUco-Modus ausgeblendet ist. */
    margin-left: auto;
}
.gcp-capture-add {
    width: 80px;
    height: 40px;
    min-width: 80px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
}
.gcp-capture-export,
.gcp-capture-save {
    width: 40px;
    height: 40px;
    min-width: 40px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
}
.gcp-capture-export svg,
.gcp-capture-save svg { display: block; }
/* X-Schliessen-Button im GCP/ArUco-Modal vereinheitlicht (dunkelrot,
 * weisses X, Hover leuchtet auf) — analog zur Lightbox. id-Scope schlaegt
 * die globalen .modal-close-btn-!important-Regeln. */
#gcp-capture-modal .modal-close-btn {
    background: #8a1414 !important;
    color: #fff !important;
    border: 1px solid rgba(255, 255, 255, 0.25) !important;
}
#gcp-capture-modal .modal-close-btn:hover {
    background: #e23b2e !important;
    border-color: #ff8088 !important;
    color: #fff !important;
    box-shadow: 0 0 12px rgba(226, 59, 46, 0.7) !important;
}

/* Sidebar-Buttons fuer GCP + ArUco-Capture-Modi.
 Farben matched die Layer-Farben der angelegten Sets (siehe
 gcp-capture-modal.js): rose fuer GCP, teal fuer ArUco. */
.sidebar-gcp-accent {
    /* rose / pink - matched Palette-Slug "rose" #EC4899 */
    background: rgba(236, 72, 153, 0.16) !important;
    color: #be185d !important;
    border-color: rgba(236, 72, 153, 0.45) !important;
}
.sidebar-gcp-accent:hover {
    background: rgba(236, 72, 153, 0.28) !important;
    color: #9d174d !important;
}
[data-theme="dark"] .sidebar-gcp-accent {
    color: #f9a8d4 !important;
}
[data-theme="dark"] .sidebar-gcp-accent:hover {
    color: #fbcfe8 !important;
}
/* Das marker-pin-Icon im GCP-Btn hat
 inline filter:invert(40%) — im Dark-Mode wird daraus dunkles Grau
 auf dunklem Hintergrund. Hier hellen wir das Icon explizit auf. */
[data-theme="dark"] .sidebar-gcp-accent img {
    filter: invert(82%) sepia(20%) saturate(800%) hue-rotate(280deg) !important;
}
.sidebar-aruco-accent {
    /* teal - matched Palette-Slug "teal" #14B8A6 */
    background: rgba(20, 184, 166, 0.16) !important;
    color: #0f766e !important;
    border-color: rgba(20, 184, 166, 0.45) !important;
}
.sidebar-aruco-accent:hover {
    background: rgba(20, 184, 166, 0.28) !important;
    color: #115e59 !important;
}
[data-theme="dark"] .sidebar-aruco-accent {
    color: #5eead4 !important;
}
[data-theme="dark"] .sidebar-aruco-accent:hover {
    color: #99f6e4 !important;
}

/* polish runde 9: "Gespeicherte Layer laden"-Btn (Folder-Icon
 in der Sidebar + im collapsed Rail) violett akzentuiert, damit er
 sich vom Plus-Btn (Layer erstellen, gruen-neutral) klar abhebt.
 Der Klick oeffnet das Lade-Modal mit allen DB-Layern. */
.sidebar-load-accent {
    background: rgba(155, 90, 200, 0.16) !important;
    color: #6a3aa0 !important;
    border-color: rgba(155, 90, 200, 0.45) !important;
}
.sidebar-load-accent:hover {
    background: rgba(155, 90, 200, 0.32) !important;
    border-color: rgba(155, 90, 200, 0.75) !important;
    color: #5a2a90 !important;
}
[data-theme="light"] .sidebar-load-accent {
    background: #efe2fa !important;
    color: #5a2a90 !important;
    border-color: #b58fdc !important;
}
[data-theme="light"] .sidebar-load-accent:hover {
    background: #e0caf5 !important;
    color: #401a78 !important;
    border-color: #8a55c8 !important;
}
/* Im Dark-Mode war die Font-Farbe zu dunkel — Icon im Folder-SVG nutzt currentColor und verschwand
 fast auf dem dunklen Hintergrund. */
[data-theme="dark"] .sidebar-load-accent {
    color: #c4a5e8 !important;
}
[data-theme="dark"] .sidebar-load-accent:hover {
    color: #ddc7f3 !important;
}

/* DSM-Surface-Modal mit Heatmap + 3D-Iso. */
.dsm-surface-tabs {
    display: flex;
    gap: 6px;
    border-bottom: 1px solid var(--border);
    margin-bottom: 8px;
}
/* Tab-Bar komplett wegblenden wenn nur ein
 einzelner Tab sichtbar ist (z. B. "Interpolierte 3D Flaeche"). Das
 hidden-Attribut auf dem Element wird vom Browser per User-Agent CSS
 auf display:none gesetzt — explizit deklarieren, falls eine Spezi-
 fizitaetsregel oben das override. */
.dsm-surface-tabs[hidden] {
    display: none;
}
.dsm-surface-tab {
    background: transparent;
    border: 1px solid transparent;
    border-bottom: none;
    padding: 6px 14px;
    border-radius: 8px 8px 0 0;
    cursor: pointer;
    font-size: 0.92em;
    color: var(--muted-hi);
}
.dsm-contours-controls {
    display: flex; align-items: center; gap: 10px;
    flex-wrap: wrap;
    margin-top: 8px;
}
.dsm-contours-label {
    display: inline-flex; align-items: center; gap: 6px;
    font-size: 0.9em;
}
.dsm-contours-label input {
    width: 84px;
    padding: 4px 6px;
}
.dsm-contours-apply { padding: 5px 14px; }
.dsm-surface-tab.is-active {
    background: var(--bg-card);
    border-color: var(--border);
    color: var(--text);
    font-weight: 600;
    margin-bottom: -1px;
}
.dsm-surface-tab:hover { color: var(--text); }
.dsm-surface-view {
    border: 1px solid var(--border);
    border-radius: 6px;
    overflow: hidden;
    background: var(--bg-elevated, rgba(0,0,0,0.04));
}
/* Footer-Bg fuer DSM-Oberflaeche +
 * Interpolierte 3D Flaeche analog Public-Help-Modal:
 * Dark : #272D31
 * Light: #E3ECF4
 * Border-top + Padding kommen ueber .modal-footer aus base.css schon
 * mit, wir ueberschreiben nur die Farbe (und die Default-Bgs aus den
 * generischen .modal-footer-Rules darueber). */
.dsm-surface-footer {
    display: flex !important;
    justify-content: flex-end;
    padding: 10px 14px !important;
    background: #E3ECF4 !important;
}
[data-theme="dark"] .dsm-surface-footer {
    background: #272D31 !important;
}
.dsm-surface-svg {
    display: block;
    width: 100%;
    height: auto;
    max-height: 60vh;
}
/* 3D-Mesh-Modus braucht explizite Hoehe, damit
 Three.js die Canvas-Groesse aus clientWidth/clientHeight liest.
 Etwas hoeher als die alte SVG-View (420 -> 460), damit die
 OrbitControls-Interaktion klar lesbar bleibt. */
.dsm-surface-view--mesh {
    width: 100%;
    height: 460px;
    max-height: 60vh;
    position: relative;
    user-select: none;
    touch-action: none;
    cursor: grab;
}
.dsm-surface-view--mesh:active { cursor: grabbing; }
.dsm-surface-view--mesh canvas {
    display: block;
    width: 100%;
    height: 100%;
}
/* Nordpfeil-Overlay im 3D-Mesh-Canvas. Rotation
 per JS auf das innere <svg>. Touch/Maus geht durch zur Canvas. */
.dsm-mesh-compass {
    position: absolute;
    top: 10px;
    right: 10px;
    width: 42px;
    height: 42px;
    pointer-events: none;
    z-index: 5;
    filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.35));
}
.dsm-mesh-compass svg {
    width: 100%;
    height: 100%;
    transform-origin: 50% 50%;
    transition: transform 0.05s linear;
}
.dsm-surface-loading {
    margin: 0;
    padding: 24px;
    text-align: center;
    color: var(--muted-hi);
    font-size: 0.92em;
    opacity: 0.8;
}

/* Stats-/Reporting-Panel unter den Tabs. */
.dsm-surface-stats {
    margin-top: 10px;
    padding: 10px 12px;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--bg-elevated, rgba(0,0,0,0.025));
    font-size: 0.85em;
}
.dsm-stats-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 6px;
    color: var(--text);
}
.dsm-stats-cache-chip {
    font-size: 0.78em;
    padding: 2px 8px;
    border-radius: 999px;
    background: rgba(127, 205, 187, 0.22);
    color: var(--muted-hi);
    border: 1px solid rgba(127, 205, 187, 0.45);
    cursor: help;
}
/* Reporting-Sektionen (Volumen / Spitzen / Meta). */
.dsm-stats-section {
    margin-top: 6px;
}
.dsm-stats-section + .dsm-stats-section {
    margin-top: 10px;
    border-top: 1px dashed rgba(127, 127, 127, 0.22);
    padding-top: 6px;
}
.dsm-stats-section-title {
    font-size: 0.78em;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--muted-hi);
    opacity: 0.85;
    margin-bottom: 4px;
}
.dsm-stats-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 4px 16px;
}
.dsm-stats-item {
    display: flex;
    justify-content: space-between;
    gap: 8px;
    padding: 2px 0;
    border-bottom: 1px dashed rgba(127, 127, 127, 0.18);
}
.dsm-stats-label {
    color: var(--muted-hi);
    opacity: 0.85;
}
.dsm-stats-value {
    font-variant-numeric: tabular-nums;
    color: var(--text);
    font-weight: 500;
}
.dsm-stats-value--cut {
    color: #c0392b;
}
.dsm-stats-value--fill {
    color: #2980b9;
}
[data-theme="dark"] .dsm-stats-value--cut {
    color: #ff7e6a;
}
[data-theme="dark"] .dsm-stats-value--fill {
    color: #6bb5e6;
}

/* Dual-Slider-Legende. Track = volle Daten-Range, zwei
 Handles flankieren die aktive Pseudocolor-Fuellung; ziehst du den
 linken nach rechts, schrumpft das Minimum nach. Reset rechts daneben. */
.dsm-legend-slider {
    position: relative;
    /* R6.2 (JP): mehr Abstand oben/unten — Picker, Slider + Hint im
     DSM-Modal waren zu gequetscht. */
    margin: 18px 28px 26px 8px;
    user-select: none;
    touch-action: none;
}
.dsm-legend-slider-track {
    position: relative;
    height: 14px;
    background: rgba(127, 127, 127, 0.18);
    border: 1px solid var(--border);
    border-radius: 3px;
}
.dsm-legend-slider-fill {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    border-radius: 2px;
    pointer-events: none;
}
.dsm-legend-slider-handle {
    position: absolute;
    top: -4px;
    width: 12px;
    height: 22px;
    margin-left: -6px;
    /* --bg-card ist im Dark-Mode rgba mit
 3% Alpha → Handles waren durchsichtig. Solide Farben jetzt fest,
 Dark-Mode-Override darunter. */
    background: #ffffff;
    border: 1.5px solid #2b3845;
    border-radius: 3px;
    cursor: ew-resize;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
    z-index: 2;
}
.dsm-legend-slider-handle::after {
    content: "";
    position: absolute;
    top: 4px;
    bottom: 4px;
    left: 50%;
    width: 1px;
    background: #2b3845;
    opacity: 0.65;
    margin-left: -0.5px;
}
[data-theme="dark"] .dsm-legend-slider-handle {
    background: #d8dee5;
    border-color: #0a0d10;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.7);
}
[data-theme="dark"] .dsm-legend-slider-handle::after {
    background: #0a0d10;
    opacity: 0.7;
}
.dsm-legend-slider-handle:hover,
.dsm-legend-slider-handle:focus {
    border-color: var(--accent, #1d72b8);
    outline: none;
}
.dsm-legend-slider-value {
    position: absolute;
    top: 100%;
    left: 50%;
    margin-top: 4px;
    transform: translateX(-50%);
    font-size: 0.78em;
    color: var(--text);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
    pointer-events: none;
    opacity: 0.92;
}
.dsm-legend-slider-reset {
    position: absolute;
    top: -4px;
    right: -26px;
    width: 22px;
    height: 22px;
    padding: 0;
    background: transparent;
    color: var(--muted-hi);
    border: 1px solid var(--border);
    border-radius: 3px;
    cursor: pointer;
    line-height: 20px;
    font-size: 0.95em;
}
.dsm-legend-slider-reset:hover {
    color: var(--text);
    border-color: var(--text);
}

/* Volume-Bodies-Legende (Cut/Fill als Chips). */
.dsm-volumes-legend {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 12px;
    padding: 8px 4px;
    font-size: 0.85em;
    color: var(--text);
}
.dsm-volumes-chip {
    display: inline-block;
    width: 14px;
    height: 14px;
    border-radius: 3px;
    flex: 0 0 auto;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1) inset;
}
.dsm-volumes-chip--cut  { background: rgb(200, 55, 40); }
.dsm-volumes-chip--fill { background: rgb(40, 128, 200); }
.dsm-volumes-sep {
    width: 1px;
    height: 14px;
    background: var(--border);
    flex: 0 0 auto;
}

/* Server-abhaengige Buttons im Offline-Modus sperren.
 body[data-offline] wird von js/online-status.js gesetzt. Volumen,
 DSM-Profil, DSM-Surface, Sample-Z brauchen alle den Server — ohne
 Verbindung lassen wir sie sichtbar (User sieht weiter dass die
 Funktion existiert) aber inaktiv mit Tooltip. */
body[data-offline="true"] [data-action="volume"],
body[data-offline="true"] [data-action="surface"],
body[data-offline="true"] [data-action="surface-plane"],
body[data-offline="true"] [data-action="profile"],
body[data-offline="true"] [data-action="retro-volume"],
body[data-offline="true"] [data-action="retro-surface"],
body[data-offline="true"] [data-action="retro-surface-plane"],
body[data-offline="true"] [data-action="retro-sample-z"],
body[data-offline="true"] [data-action="retro-profile"] {
    pointer-events: none;
    opacity: 0.45;
    cursor: not-allowed;
}
/* Visueller Marker — kleines Cloud-Off-Icon rechts neben dem disabled
   Button, damit der User versteht warum das ausgegraut ist. */
body[data-offline="true"] [data-action="volume"]::after,
body[data-offline="true"] [data-action="surface"]::after,
body[data-offline="true"] [data-action="surface-plane"]::after,
body[data-offline="true"] [data-action="profile"]::after,
body[data-offline="true"] [data-action="retro-volume"]::after,
body[data-offline="true"] [data-action="retro-surface"]::after,
body[data-offline="true"] [data-action="retro-surface-plane"]::after,
body[data-offline="true"] [data-action="retro-sample-z"]::after,
body[data-offline="true"] [data-action="retro-profile"]::after {
    content: "⌀";
    margin-left: 0.35em;
    font-size: 0.92em;
    opacity: 0.7;
}
.dsm-surface-legend {
    display: block;
    width: 100%;
    height: 28px;
    margin-top: 6px;
    color: var(--text);
}
.measure-tool-btn--surface.is-active,
.measure-tool-btn--surface:hover,
.measure-tool-btn--surface-plane.is-active,
.measure-tool-btn--surface-plane:hover {
    border-color: rgba(0, 204, 255, 0.55) !important;
    color: #003848 !important;
}
[data-theme="dark"] .measure-tool-btn--surface:hover,
[data-theme="dark"] .measure-tool-btn--surface-plane:hover {
    color: #b8edff !important;
}

/* c Tag-Color-Picker-Popup beim Klick auf
 einen Tag-Chip im Feature-Edit. */
.tag-picker-chip-color {
    background: transparent;
    border: none;
    color: inherit;
    cursor: pointer;
    padding: 0;
    font: inherit;
}
.tag-picker-chip-color:hover { text-decoration: underline; }
.tag-color-popup {
    position: fixed;
    z-index: 2300;
    background: var(--bg-card, #fff);
    border: 1px solid var(--border, #ccc);
    border-radius: 8px;
    box-shadow: 0 8px 22px rgba(0,0,0,0.25);
    padding: 10px;
    min-width: 180px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.tag-color-popup-title {
    font-size: 0.84em;
    font-weight: 600;
    color: var(--muted-hi);
    text-transform: lowercase;
}
/* Direkter Swatch-Picker ohne Speichern-Buttons. */
.tag-color-swatches {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 6px;
}
.tag-color-swatch {
    width: 26px;
    height: 26px;
    border-radius: 6px;
    border: 2px solid transparent;
    background: var(--swatch, #888);
    cursor: pointer;
    padding: 0;
    transition: transform .12s ease, border-color .12s ease;
}
.tag-color-swatch:hover { transform: scale(1.10); }
.tag-color-swatch.is-on {
    border-color: var(--text);
    box-shadow: 0 0 0 1px var(--bg-card) inset;
}
/* Clear-Swatch — leeres Farbfeld + Clear-Icon. */
.tag-color-swatch--clear {
    background: var(--input-bg, #fff);
    border: 2px dashed var(--border);
    display: flex;
    align-items: center;
    justify-content: center;
}
.tag-color-swatch--clear img {
    opacity: 0.6;
    pointer-events: none;
}
[data-theme="dark"] .tag-color-swatch--clear img {
    filter: invert(1);
}
.tag-color-swatch--clear.is-on {
    border-style: solid;
    border-color: var(--text);
}

/* Experimentelle Features – CSS-Suppression. SuperAdmin
 schaltet im Stammdaten-Tab ein/aus, das setzt body[data-exp-...]. */
body[data-exp-layer-share="off"] #invitations-bell,
body[data-exp-layer-share="off"] [data-action="share-layer"],
body[data-exp-layer-share="off"] [data-exp-feature="layer_share"] {
    display: none !important;
}
body[data-exp-location-share="off"] [data-action="toggle-location-share"],
body[data-exp-location-share="off"] [data-exp-feature="location_share"] {
    display: none !important;
}
body[data-exp-dsm-surface="off"] [data-action="retro-surface"],
body[data-exp-dsm-surface="off"] #measure-surface-btn,
body[data-exp-dsm-surface="off"] [data-exp-feature="dsm_surface"] {
    display: none !important;
}
[data-theme="dark"] .tag-color-popup {
    background: var(--surface-elevated, #1f2024);
    border-color: rgba(255,255,255,0.14);
}

/* Invitations-Liste im Modal. */
.invitations-list {
    list-style: none;
    margin: 0;
    padding: 0;
}
.invitations-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 4px;
    border-bottom: 1px solid var(--border);
}
.invitations-row:last-child { border-bottom: none; }
.invitations-row-info {
    flex: 1 1 auto;
    min-width: 0;
}
.invitations-row-info strong {
    display: block;
    font-size: 1em;
    color: var(--text);
}
.invitations-row-info .sub {
    font-size: 0.84em;
    color: var(--muted-hi);
}
.invitations-row-actions {
    display: flex;
    gap: 6px;
    flex-shrink: 0;
}

/* Feature-Modal-Footer-Buttons als kompakte 40x40 Icon-Btns
 (Loeschen, Cancel, Klonen, Speichern). Ersetzt die vorigen Text-
 Buttons. */
.feature-modal-footer { gap: 6px; align-items: center; }
.feature-modal-icon-btn {
    width: 40px !important;
    height: 40px !important;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 40px;
    border-radius: var(--radius-sm);
    cursor: pointer;
    border: 1px solid var(--border);
}
.feature-modal-icon-btn svg { display: block; }
/* rev 3: Loeschen bleibt ghost.danger (rot). Cancel ist
 jetzt amber, Save bleibt blau (Primary), Klon ist violett. */
.feature-modal-icon-btn.ghost.danger {
    background: var(--c-error-bg, rgba(220, 53, 69, 0.10));
    color: var(--c-error, #dc3545);
    border-color: var(--c-error, #dc3545);
}
.feature-modal-icon-btn.ghost.danger:hover {
    background: var(--c-error-bg, rgba(220, 53, 69, 0.20));
    color: var(--c-error, #dc3545);
}
/* Save-Btn (Primary) behaelt die globale .primary-Farbe (Cyan/Blau).
   Die .primary-Regel im Stylesheet setzt background+color — wir
   verstaerken das hier nur defensiv, weil .feature-modal-icon-btn
   sonst keine eigene Background-Definition mehr hat. */
.feature-modal-icon-btn.primary {
    background: var(--c-primary, #007FB4);
    color: #fff;
    border-color: transparent;
}
.feature-modal-icon-btn.primary:hover {
    background: var(--c-primary-hi, #00A0D2);
    color: #fff;
}
/* Cancel-Btn: amber (reversible Aktion), gleiche Geometrie.
   !important schuetzt gegen .modal-actions > button und .ghost-Default-
   Styles aus tieferen Layern. */
.feature-modal-icon-btn.btn-amber {
    background: rgba(201, 138, 0, 0.15) !important;
    color: var(--c-amber, #c98a00) !important;
    border-color: rgba(201, 138, 0, 0.55) !important;
}
.feature-modal-icon-btn.btn-amber:hover {
    background: rgba(201, 138, 0, 0.28) !important;
    border-color: rgba(201, 138, 0, 0.80) !important;
    color: #e6a627 !important;
}
/* Klon-Btn: violett. Konvention analog zu btn-success / btn-amber. */
.feature-modal-icon-btn.btn-violet,
.btn-violet {
    background: rgba(155, 89, 182, 0.15);
    color: #9b59b6;
    border-color: rgba(155, 89, 182, 0.55);
}
.feature-modal-icon-btn.btn-violet {
    /* Explizit nochmal Geometrie, damit btn-violet ohne irgendeine
       andere Klasse trotzdem genau 40x40 bleibt — Defensive gegen
       Browser-Default-Padding und etwaige Drittsysteme. */
    width: 40px !important;
    height: 40px !important;
    padding: 0 !important;
}
.feature-modal-icon-btn.btn-violet:hover,
.btn-violet:hover {
    background: rgba(155, 89, 182, 0.28);
    border-color: rgba(155, 89, 182, 0.80);
    color: #b478d0;
}
[data-theme="dark"] .feature-modal-icon-btn.btn-violet,
[data-theme="dark"] .btn-violet {
    color: #c89be0;
}

/* Pending-Invitations-Glocke in der Topbar. */
.invitations-bell {
    position: relative;
}
/* hidden-Attribut hart durchsetzen — der Btn ist im Topbar-
 Flex-Container, und ohne !important reicht ein .topbar-right .icon-btn
 width:36px;height:36px aus, um trotz [hidden] eine 36x36 Box zu
 reservieren. */
#invitations-bell[hidden] { display: none !important; }

/* Z: Onboarding-Tour. Spotlight + Tooltip-Overlay.
 Rev 2: Statt einem grossen box-shadow-Backdrop verwenden wir vier
 separate Overlay-Boxen (oben/unten/links/rechts vom Spotlight-Loch).
 Jede Box hat backdrop-filter:blur(3px) + Dunkelung — dadurch ist
 alles ausserhalb des Spotlights weichgezeichnet UND dunkler, das
 Spotlight-Element selber bleibt scharf. Vorteil gegenueber box-
 shadow: backdrop-filter funktioniert nur wenn das Element wirklich
 ueber dem zu filternden Inhalt liegt — geht mit separaten Divs
 perfekt, mit einem fullscreen-Loch-Trick nicht. */
#geolyser-tutorial-backdrop {
    position: fixed; inset: 0;
    z-index: 9000;
    background: transparent;
    /* Backdrop selbst transparent + pointer-events auf den Kindern. */
    pointer-events: none;
    display: none;
}
.geolyser-tutorial-mask {
    position: fixed;
    z-index: 9000;
    background: rgba(15, 18, 22, 0.55);
    backdrop-filter: blur(3px) saturate(0.85);
    -webkit-backdrop-filter: blur(3px) saturate(0.85);
    pointer-events: auto;
    transition: left .14s ease, top .14s ease,
                width .14s ease, height .14s ease;
}
/* Wenn der Browser kein backdrop-filter kennt (sehr alte Builds),
   fallback auf reine Verdunkelung — User-Wunsch "blurry" geht
   verloren aber Tour funktioniert noch. */
@supports not (backdrop-filter: blur(1px)) {
    .geolyser-tutorial-mask {
        background: rgba(15, 18, 22, 0.72);
    }
}
#geolyser-tutorial-spotlight {
    position: fixed;
    z-index: 9001;
    border-radius: 8px;
    background: transparent;
    /* Leichter Rahmen damit das Spotlight als Fokus erkennbar bleibt. */
    box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.55),
                0 4px 24px rgba(0, 0, 0, 0.45);
    pointer-events: none;
    transition: left .18s ease, top .18s ease,
                width .18s ease, height .18s ease;
    display: none;
}
#geolyser-tutorial-tooltip {
    position: fixed;
    z-index: 9100;
    background: var(--bg-card, #fff);
    color: var(--fg, #111);
    border: 1px solid var(--border, rgba(0,0,0,0.12));
    border-radius: 10px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.30);
    padding: 14px 14px 12px;
    width: 360px;
    max-width: calc(100vw - 24px);
    font-size: 14px;
    line-height: 1.45;
    pointer-events: auto;
    display: none;
}
[data-theme="dark"] #geolyser-tutorial-tooltip {
    background: #1f2024;
    color: #e8e8e8;
    border-color: rgba(255, 255, 255, 0.10);
}
.geolyser-tutorial-tip-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 6px;
}
.geolyser-tutorial-tip-progress {
    font-size: 11px;
    opacity: 0.65;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
.geolyser-tutorial-tip-skip {
    background: transparent;
    border: none;
    color: var(--muted, #888);
    font-size: 22px;
    line-height: 1;
    cursor: pointer;
    padding: 0 4px;
}
.geolyser-tutorial-tip-skip:hover { color: var(--fg, #111); }
.geolyser-tutorial-tip-title {
    margin: 0 0 6px;
    font-size: 16px;
    font-weight: 600;
}
.geolyser-tutorial-tip-body {
    margin: 0 0 14px;
    font-size: 13.5px;
    line-height: 1.5;
}
.geolyser-tutorial-tip-nav {
    display: flex;
    gap: 8px;
    justify-content: flex-end;
}
.geolyser-tutorial-btn {
    padding: 7px 14px;
    border-radius: 6px;
    border: 1px solid var(--border, rgba(0,0,0,0.18));
    background: var(--bg-elevated, #f0f3f6);
    color: var(--fg, #111);
    cursor: pointer;
    font-size: 13px;
}
.geolyser-tutorial-btn:hover:not(:disabled) {
    background: var(--input-bg, #e6ebef);
}
.geolyser-tutorial-btn:disabled {
    opacity: 0.45;
    cursor: not-allowed;
}
.geolyser-tutorial-btn.primary {
    background: var(--c-primary, #007FB4);
    color: #fff;
    border-color: transparent;
}
.geolyser-tutorial-btn.primary:hover:not(:disabled) {
    background: var(--c-primary-hi, #00A0D2);
}
.invitations-bell-badge {
    position: absolute;
    top: 2px;
    right: 2px;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: 9px;
    background: #ef4444;
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    line-height: 16px;
    text-align: center;
    box-shadow: 0 0 0 2px var(--bg, #fff);
}
[data-theme="dark"] .invitations-bell-badge {
    box-shadow: 0 0 0 2px var(--bg, #181818);
}

/* Location-Share-Btn + Avatar-Marker. */
[data-action="gps-share-location"].is-active {
    background: rgba(0, 204, 255, 0.20);
    color: #003848;
    border-color: rgba(0, 204, 255, 0.55);
}
[data-theme="dark"] [data-action="gps-share-location"].is-active {
    background: rgba(0, 204, 255, 0.30);
    color: #b8edff;
}
.user-location-marker-wrap {
    background: transparent !important;
    border: none !important;
    pointer-events: auto;
}
.user-location-marker {
    width: 28px; height: 28px;
    border-radius: 50%;
    overflow: hidden;
    box-shadow: 0 2px 6px rgba(0,0,0,0.4),
                0 0 0 2px #00CCFF;
    background: #fff;
    position: relative;
}
.user-location-marker svg {
    width: 100%; height: 100%;
    display: block;
}
/* hochgeladener Avatar bevorzugt; der Initialen-Fallback-SVG
 liegt darunter und wird sichtbar, falls das Bild nicht laedt
 (onerror -> img.display:none). */
.user-location-marker .user-location-avatar {
    position: absolute;
    inset: 0;
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
    z-index: 2;
    background: #fff;
}
.user-location-marker .user-location-avatar-fallback {
    position: absolute;
    inset: 0;
    width: 100%; height: 100%;
    z-index: 1;
}
.user-location-marker .user-location-avatar-fallback svg {
    width: 100%; height: 100%;
    display: block;
}

/* Sidebar-Presence-Liste Ladeanimation. Wird gerendert
 solange der presence-WS noch keinen ersten Snapshot geliefert hat —
 verhindert das irrefuehrende "0 weitere online" beim Pageload. */
.sidebar-presence-list .presence-loading,
[data-role="sidebar-presence-host"] .presence-loading {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 0 4px;
    color: var(--muted-hi, #666);
    font-size: 12px;
}
.presence-loading-spinner {
    display: inline-block;
    width: 14px; height: 14px;
    border: 2px solid var(--border, rgba(0,0,0,0.14));
    border-top-color: var(--c-primary, #06829c);
    border-radius: 50%;
    animation: presence-loading-spin 0.9s linear infinite;
}
@keyframes presence-loading-spin {
    to { transform: rotate(360deg); }
}
[data-theme="dark"] .presence-loading-spinner {
    border-color: rgba(255,255,255,0.18);
    border-top-color: var(--c-primary, #4dd5ee);
}

/* Layer-Share-Modal Layout. */
.share-invite-form {
    display: flex;
    gap: 8px;
    align-items: stretch;
    margin-bottom: 8px;
}
.share-invite-form input,
.share-invite-form select {
    flex: 1 1 auto;
    min-width: 0;
    /* heller Sidepanel-Blauton (--bg-card = #eaf1f8 light)
 statt pure white. Hebt sich vom Modal-Hintergrund (--bg-elevated
 = #fff) ab. */
    background: var(--bg-card, #eaf1f8) !important;
    color: var(--fg, #111) !important;
    border: 1px solid var(--border) !important;
    border-radius: 4px;
    padding: 6px 10px;
}
[data-theme="dark"] .share-invite-form input,
[data-theme="dark"] .share-invite-form select {
    background: #2a2c30 !important;
    color: #eee !important;
    border-color: rgba(255,255,255,0.18) !important;
    color-scheme: dark;
}
.share-list {
    list-style: none;
    margin: 0;
    padding: 0;
    border-top: 1px solid var(--border);
}
.share-row {
    display: grid;
    grid-template-columns: 1fr auto auto auto;
    gap: 10px;
    align-items: center;
    padding: 8px 4px;
    border-bottom: 1px solid var(--border);
    font-size: 0.92em;
}
.share-row-name {
    font-weight: 600;
    color: var(--text);
}
.share-row-role {
    text-transform: uppercase;
    font-size: 0.78em;
    letter-spacing: 0.06em;
    opacity: 0.7;
}
.share-row-status {
    font-size: 0.84em;
    color: var(--muted-hi);
}
.share-row-status.is-pending {
    color: var(--c-amber, #c98a00);
    font-style: italic;
}
/* Share-Modal-Umbau — Edit-Checkbox als Icon-Toggle. */
.share-invite-form .share-edit-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px; height: 36px;
    border: 1px solid var(--border);
    border-radius: 4px;
    cursor: pointer;
    background: var(--bg-card, #eaf1f8);
    color: var(--muted-hi, #777);
    flex: 0 0 auto;
    transition: background 0.12s ease, color 0.12s ease;
}
.share-invite-form .share-edit-toggle input[type="checkbox"] {
    /* Visually hidden, semantisch nutzbar fuer Screen-Reader + Click-Hit. */
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0;
    overflow: hidden; clip: rect(0 0 0 0);
    border: 0;
}
.share-invite-form .share-edit-toggle:has(input:checked) {
    background: var(--c-primary, #06829c);
    color: #fff;
    border-color: var(--c-primary, #06829c);
}
.share-invite-form .share-edit-toggle:hover { filter: brightness(1.08); }
.share-invite-form .share-invite-btn {
    width: 36px; height: 36px;
    padding: 0;
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
[data-theme="dark"] .share-invite-form .share-edit-toggle {
    background: #2a2c30;
    border-color: rgba(255,255,255,0.18);
    color: #ccc;
}

/* Edit-Indikator im Member-Listeintrag — gefuellt wenn Editor, dezent
   wenn Viewer. */
/* share-row-edit ist jetzt ein <button> (Toggle), also
 Browser-Defaults neutralisieren + Hover-Affordance. */
.share-row .share-row-edit {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px; height: 24px;
    border-radius: 4px;
    color: var(--muted, #888);
    background: transparent;
    border: 0;
    padding: 0;
    cursor: pointer;
    transition: background 120ms ease, color 120ms ease;
}
.share-row .share-row-edit:hover {
    background: rgba(0, 0, 0, 0.06);
}
[data-theme="dark"] .share-row .share-row-edit:hover {
    background: rgba(255, 255, 255, 0.08);
}
.share-row .share-row-edit.is-on {
    color: var(--c-primary, #06829c);
}
.share-row.share-row--viewer .share-row-name { color: var(--muted-hi); }

/* Layer-Snapshots / Versionen-Modal. Liste von Snapshots mit
 Notiz, Anzahl-Features, Actions (Restore + Loeschen). */
.snap-create-form {
    display: flex;
    gap: 8px;
    margin: 4px 0 12px;
}
.snap-create-form input[type="text"],
.snap-filter-row input[type="date"] {
    flex: 1 1 auto;
    min-width: 0;
    /* Sidepanel-Blauton (--bg-card) statt pure white. */
    background: var(--bg-card, #eaf1f8) !important;
    color: var(--fg, #111) !important;
    border: 1px solid var(--border) !important;
    border-radius: 4px;
    padding: 6px 10px;
}
[data-theme="dark"] .snap-create-form input[type="text"],
[data-theme="dark"] .snap-filter-row input[type="date"] {
    background: #2a2c30 !important;
    color: #eee !important;
    border-color: rgba(255,255,255,0.18) !important;
    color-scheme: dark;
}
.snap-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
    max-height: 50vh;
    overflow-y: auto;
}
.snap-row {
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 10px 12px;
    background: var(--card-bg, var(--panel-bg));
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.snap-head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    font-size: 0.95em;
}
.snap-color {
    display: inline-block;
    width: 14px;
    height: 14px;
    border-radius: 4px;
    border: 1px solid var(--border);
    flex: 0 0 auto;
}
.snap-name {
    font-weight: 600;
}
.snap-meta {
    font-size: 0.82em;
}
.snap-note {
    font-size: 0.9em;
    background: var(--input-bg, var(--panel-bg));
    border-radius: 6px;
    padding: 6px 8px;
    border-left: 3px solid var(--accent, #4a90e2);
    white-space: pre-wrap;
}
.snap-actions {
    display: flex;
    gap: 8px;
    justify-content: flex-end;
    flex-wrap: wrap;
}
.snap-actions button {
    font-size: 0.85em;
    padding: 4px 10px;
}

/* Audit-Log-Tabelle. */
.audit-toolbar {
    display: flex;
    gap: 8px;
    align-items: flex-end;
    margin-bottom: 8px;
}
.audit-table-wrap {
    overflow-x: auto;
    max-height: 60vh;
    overflow-y: auto;
}
.audit-table {
    font-size: 0.82em;
    width: 100%;
}
.audit-table th, .audit-table td {
    padding: 4px 6px;
    border-bottom: 1px solid var(--border);
    vertical-align: top;
}
.audit-data {
    font-size: 0.78em;
    word-break: break-all;
    white-space: pre-wrap;
    display: block;
    max-width: 220px;
    color: var(--muted-hi, #666);
}

/* Mobile Bottom-Cutoff auf Samsung S24U + alle
 Smartphone-Browser mit dynamischer URL-Bar. Wir nutzen 100dvh statt
 100vh + safe-area-inset-bottom fuer Geraete mit Notch/Home-Indicator.
 Die JS-Hook setzt --vp-bottom-px auf window.visualViewport.height-
 diff, sodass das Map-Container-Layout exakt zur SICHTBAREN Hoehe
 passt - Locate/GPS-Tools/Status-Bar werden nicht mehr von der URL-
 Bar bzw. Tab-Bar abgeschnitten. */
:root {
    --vp-bottom-px: 0px;
}
html, body {
    /* dvh = dynamic viewport height (echte Hoehe ohne URL-Bar) */
    min-height: 100vh;
    min-height: 100dvh;
}
.map-shell {
    /* Topbar-Hoehe explizit abziehen, sonst rutscht die
 Karte ueber die Topbar drueber und der untere Kartenrand wird
 abgeschnitten. Beide Hoehenangaben (vh-Fallback + dvh) muessen
 --topbar-h abziehen. */
    height: calc(100vh - var(--topbar-h) - var(--vp-bottom-px));
    height: calc(100dvh - var(--topbar-h));
    padding-bottom: env(safe-area-inset-bottom, 0px);
}
@media (max-width: 768px) {
    .leaflet-bottom {
        /* Locate/GPS-Tools/Scale-Bar nach oben schieben um die
           safe-area + die VP-Bottom-Differenz, sonst sitzen sie
           hinter der Tab-Bar von Chrome Mobile. */
        bottom: calc(env(safe-area-inset-bottom, 0px)
                     + var(--vp-bottom-px)) !important;
    }
    /* Mobile-F-Fix : Map-Status NICHT mehr komplett ausblenden.
 * Auf Touch-Devices gibt es keinen Mouse-Cursor (Mausbewegung-Coords
 * erscheinen nicht), aber GPS-Accuracy vom Locate-Btn wird via
 * `map.on('locationfound', ...)` in `#map-status [data-role="accuracy"]`
 * gerendert und der User will den sehen.
 *
 * Position konfiguriert im 768px-Block weiter oben (oben mittig,
 * dunkler Hintergrund, hoher z-index). KEIN top:auto-Override mehr —
 * der hat zuvor die Top-Center-Position kaputt gemacht. */
    /* (Default-Position aus 768px-Block greift.) */
    /* Modals als echter Vollbild auf Mobile.
 100vw x 100dvh statt floating-Card. Header sticky damit das
 X-Schliessen immer sichtbar bleibt, egal wie weit der User
 scrollt. Scrollbar ohne maximale Hoehe (.modal-card hat sonst
 max-height: 90vh und versteckt Inhalte unter dem Scroll-Buffer). */
    .modal {
        align-items: stretch;
        padding: 0 !important;
    }
    .modal-card {
        width: 100vw !important;
        max-width: 100vw !important;
        height: 100dvh !important;
        max-height: 100dvh !important;
        border-radius: 0 !important;
        margin: 0 !important;
        display: flex;
        flex-direction: column;
    }
    .modal-card > .modal-header,
    .modal-card > h3.modal-title {
        position: sticky;
        top: 0;
        z-index: 10;
        background: var(--bg-card, #fff);
        border-bottom: 1px solid var(--border);
        padding-top: env(safe-area-inset-top, 12px);
    }
    [data-theme="dark"] .modal-card > .modal-header,
    [data-theme="dark"] .modal-card > h3.modal-title {
        background: var(--surface-elevated, #1f2024);
    }
    .modal-card > .modal-body,
    .modal-card > .modal-form,
    .modal-card > [data-role="body"] {
        flex: 1 1 auto;
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
    }
    .modal-card > .modal-footer,
    .modal-card > .modal-actions {
        position: sticky;
        bottom: 0;
        background: var(--bg-card, #fff);
        border-top: 1px solid var(--border);
        padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 12px);
    }
    [data-theme="dark"] .modal-card > .modal-footer,
    [data-theme="dark"] .modal-card > .modal-actions {
        background: var(--surface-elevated, #1f2024);
    }
    /* Listen mit langem Scroll: prominenter Scroll-Indikator, sonst
       merken Mobile-User nicht dass sie scrollen koennen. */
    .modal-body::-webkit-scrollbar,
    .modal-form::-webkit-scrollbar,
    [data-role="body"]::-webkit-scrollbar,
    .load-modal-list::-webkit-scrollbar,
    .bulk-edit-list::-webkit-scrollbar {
        width: 12px;
    }
    .modal-body::-webkit-scrollbar-thumb,
    .modal-form::-webkit-scrollbar-thumb,
    [data-role="body"]::-webkit-scrollbar-thumb,
    .load-modal-list::-webkit-scrollbar-thumb,
    .bulk-edit-list::-webkit-scrollbar-thumb {
        background: rgba(0, 204, 255, 0.40);
        border-radius: 6px;
        border: 2px solid transparent;
        background-clip: padding-box;
    }
    .modal-body::-webkit-scrollbar-track,
    .modal-form::-webkit-scrollbar-track,
    [data-role="body"]::-webkit-scrollbar-track,
    .load-modal-list::-webkit-scrollbar-track,
    .bulk-edit-list::-webkit-scrollbar-track {
        background: rgba(0,0,0,0.04);
    }

    /* ============================================================
 * Mobile-I-Fix — Universelles Fullscreen-Modal-Pattern
 * ------------------------------------------------------------
 * nach Mobile-H/H2/H3 (Help-Modal als Vorlage): das
 * gleiche Pattern auf ALLE Mobile-Fullscreen-Modals anwenden.
 * - Card mit padding:0 + overflow:hidden, damit Header/Footer
 * von alleine edge-to-edge ohne negative Margins sitzen.
 * - Header und Footer mit explizit opaker var(--bg-elevated)
 * (das aeltere Sticky-Pattern oben nutzte --bg-card, das in
 * Dark-Theme nahezu transparent war → Text-Bleed-Through).
 * - Body/Form/Help-Shell uebernehmen den scrollbaren Mittel-
 * bereich mit min-height:0 + overflow-y:auto.
 * - Scrollbar auf ALLE scrollbaren Bereiche im Modal tuerkis
 * (--c-cyan #3BBDE8) und deutlich sichtbar.
 * Specificity hoch genug (!important) damit es die aelteren
 * Mobile-Regeln im selben @media-Block ueberlaeuft (CSS-Order
 * + !important). */
    .modal-card {
        padding: 0 !important;
        overflow: hidden !important;
    }
    .modal-card > .modal-header,
    .modal-card > h3.modal-title {
        margin: 0 !important;
        padding: 12px 16px !important;
        padding-top: calc(env(safe-area-inset-top, 0px) + 12px) !important;
        background: var(--bg-elevated) !important;
        border-bottom: 1px solid var(--border);
        flex-shrink: 0;
        position: relative;
        z-index: 3;
        width: 100%;
    }
    .modal-card > .modal-footer,
    .modal-card > .modal-actions {
        /* Mobile-OO-Fix * margin-top: auto schiebt den Footer ans untere Ende des
 * Flex-Container — auch wenn das Body-Content (z.B. .gcp-
 * capture-body, .load-modal-list) KEINE flex:1-Regel hat und
 * der Footer sonst mitten im Modal haengt. Sides + Bottom
 * bleiben 0. */
        margin: auto 0 0 0 !important;
        padding: 10px 12px !important;
        padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 10px) !important;
        background: var(--bg-elevated) !important;
        border-top: 1px solid var(--border);
        flex-shrink: 0;
        position: relative;
        z-index: 3;
        width: 100%;
    }
    .modal-card > .modal-body,
    .modal-card > .modal-form,
    .modal-card > [data-role="body"] {
        margin: 0 !important;
        padding: 12px 16px !important;
        flex: 1 1 auto !important;
        overflow-y: auto !important;
        overflow-x: hidden !important;
        -webkit-overflow-scrolling: touch;
        min-height: 0 !important;
    }
    /* Tuerkise Scrollbar auf ALLEN scrollbaren Bereichen innerhalb
     * eines Modals (egal ob standard-Body/-Form, [data-role="body"],
     * Help-TOC, Lade-Modal-Liste, Bulk-Tag-Liste oder eine custom
     * Table-Wrap-Klasse). */
    .modal-card,
    .modal-card * {
        /* scrollbar-color mit sichtbarem Track. */
        scrollbar-color: var(--c-cyan, #3BBDE8) rgba(0,0,0,0.10);
        scrollbar-width: thin;
    }
    .modal-card ::-webkit-scrollbar,
    .modal-card::-webkit-scrollbar {
        /* etwas breiter fuer bessere Touch-Greifbarkeit. */
        width: 12px;
        height: 12px;
    }
    .modal-card ::-webkit-scrollbar-track,
    .modal-card::-webkit-scrollbar-track {
        /* Sichtbarer Track damit User erkennen
 dass Content scrollbar ist. Subtile Faerbung statt transparent. */
        background: rgba(0, 0, 0, 0.10);
        border-radius: 6px;
    }
    [data-theme="dark"] .modal-card ::-webkit-scrollbar-track,
    [data-theme="dark"] .modal-card::-webkit-scrollbar-track {
        background: rgba(255, 255, 255, 0.08);
    }
    .modal-card ::-webkit-scrollbar-thumb,
    .modal-card::-webkit-scrollbar-thumb {
        background: var(--c-cyan, #3BBDE8) !important;
        border-radius: 5px;
        /* Kein border-gap mehr — Thumb soll direkt sichtbar sein ohne
           2px-Rand der ihn optisch dünner macht. */
        min-height: 40px;
    }
    .modal-card ::-webkit-scrollbar-thumb:hover,
    .modal-card::-webkit-scrollbar-thumb:hover {
        background: #2aa6cf !important;
    }
    .modal-card ::-webkit-scrollbar-corner,
    .modal-card::-webkit-scrollbar-corner {
        background: rgba(0, 0, 0, 0.05);
    }

    /* ============================================================
 * Mobile-K-Fix — Tab→Kapitel-Detail-Pattern fuer
 * Modals mit ueberlaufender Tab-Bar (aktuell admin-modal).
 * ------------------------------------------------------------
 * Anstatt die Tab-Bar im Header auf Mobile zu zeigen (wo sie
 * ueberlaeuft und Tabs unklickbar werden), rendern wir die Tabs
 * als grosse vertikale Kapitel-Liste in der Body-Area. Klick
 * triggert is-mobile-detail-mode auf .modal-card — dann sind die
 * Kapitel ausgeblendet und nur das aktive Pane sichtbar, plus
 * ein Zurueck-Pfeil oben links im Header.
 *
 * Standardmaessig (kein is-mobile-detail-mode): Kapitel-Liste,
 * keine Tab-Bar, keine Panes. is-mobile-detail-mode: Panes
 * sichtbar, Kapitel-Liste aus, Zurueck-Pfeil ein. */
    .modal-card .modal-header-tabs {
        display: none !important;
    }
    .modal-card .modal-mobile-chapter-list {
        display: flex;
        flex-direction: column;
        gap: 6px;
        padding: 8px 4px;
    }
    .modal-card.is-mobile-detail-mode .modal-mobile-chapter-list {
        display: none !important;
    }
    .modal-card:not(.is-mobile-detail-mode) [data-pane] {
        display: none !important;
    }
    .modal-card .modal-chapter-item {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 12px;
        padding: 14px 16px;
        background: var(--bg-card, rgba(255,255,255,0.04));
        border: 1px solid var(--border);
        border-radius: 8px;
        color: var(--fg);
        font: inherit;
        font-size: 1.05em;
        text-align: left;
        cursor: pointer;
        min-height: 48px;
    }
    .modal-card .modal-chapter-item:hover,
    .modal-card .modal-chapter-item:focus-visible {
        background: var(--bg-elevated);
        border-color: var(--c-cyan, #3BBDE8);
        outline: none;
    }
    .modal-card .modal-chapter-item.is-active {
        border-color: var(--c-cyan, #3BBDE8);
        color: var(--c-cyan, #3BBDE8);
        font-weight: 500;
    }
    .modal-card .modal-chapter-chevron {
        font-size: 1.6em;
        line-height: 0.9;
        opacity: 0.6;
        flex-shrink: 0;
    }
    /* Zurueck-Pfeil im Header (nur sichtbar via [hidden=false] aus JS). */
    .modal-card > .modal-header > .modal-back-btn {
        border: 0;
        background: transparent;
        color: var(--muted-hi);
        cursor: pointer;
        padding: 4px 8px;
        margin-right: 4px;
        border-radius: var(--radius-sm);
        line-height: 0;
        flex-shrink: 0;
    }
    .modal-card > .modal-header > .modal-back-btn:hover {
        background: var(--input-bg);
        color: var(--fg);
    }
    /* Wenn Kapitel-Liste sichtbar ist, soll der modal-body keinen
     * unnoetigen Top-Padding haben — Kapitel sitzen schon mit ihrem
     * Eigen-Padding richtig. */
    .modal-card:not(.is-mobile-detail-mode) > .modal-body {
        padding: 8px 12px !important;
    }
    /* Mobile-DD-Fix Admin-Pane-Header (h3 oder h4)
 * NICHT mehr doppelt zeigen. Modal-Titel oben enthaelt schon den
 * Kapitel-Namen (siehe Mobile-V Title-Swap in admin-modal.js). Das
 * erste h3/h4 am Anfang jedes [data-pane] und auch im help-content
 * im Detail-Mode wird ausgeblendet. */
    .modal-card.is-mobile-detail-mode [data-pane] > h3:first-child,
    .modal-card.is-mobile-detail-mode [data-pane] > h4:first-child,
    .modal-card.is-mobile-detail-mode [data-pane] > p:first-child + h4,
    .modal-card.is-mobile-detail-mode [data-pane] > section > h4:first-child {
        display: none !important;
    }
}

/* Mobile-T/BB-Fix : Einheitlicher Minimize-Btn-Style fuer alle
 * Modals und Panels (gcp-capture-modal, measurement-panel). Cyan
 * (Geolyser-CI) damit man ihn vom roten Close-X unterscheidet.
 * Mobile-BB: nicht mehr .modal-close-btn als Basis (die zwingt rote
 * Border + roten Hintergrund via !important). Stattdessen kompletter
 * Standalone-Style — 32x32, cyan Border, cyan SVG. */
.modal-minimize-btn {
    width: 32px;
    height: 32px;
    border-radius: var(--radius-sm);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-elevated) !important;
    color: var(--c-cyan, #3BBDE8) !important;
    border: 1px solid var(--c-cyan, #3BBDE8) !important;
    cursor: pointer;
    padding: 0;
    flex-shrink: 0;
    transition: background .12s, color .12s, border-color .12s;
}
.modal-minimize-btn:hover,
.modal-minimize-btn:focus-visible {
    background: var(--c-cyan, #3BBDE8) !important;
    color: #fff !important;
    border-color: var(--c-cyan, #3BBDE8) !important;
    outline: none;
}
[data-theme="light"] .modal-minimize-btn {
    background: #e8f7fc !important;
    color: var(--c-cyan, #3BBDE8) !important;
    border-color: var(--c-cyan, #3BBDE8) !important;
}
[data-theme="light"] .modal-minimize-btn:hover {
    background: var(--c-cyan, #3BBDE8) !important;
    color: #fff !important;
}
.modal-minimize-btn svg {
    display: block;
    width: 18px;
    height: 18px;
}
/* Mobile-BB-Fix: Minimize + Close-X immer am rechten Rand zusammen,
 * mit kleinem Gap. margin-left:auto schiebt die erste Right-Action
 * an den rechten Rand, alle nachfolgenden Buttons reihen sich
 * adjacent rechts an. */
.modal-header > .modal-minimize-btn {
    margin-left: auto;
}
.modal-header > .modal-minimize-btn + .modal-close-btn,
.modal-header > .modal-close-btn + .modal-minimize-btn {
    margin-left: 6px;
}
/* Wenn kein Minimize-Btn da ist, sitzt der Close-Btn alleine rechts. */
.modal-header > .modal-close-btn {
    margin-left: auto;
}
.modal-header > .modal-minimize-btn + .modal-close-btn {
    margin-left: 6px;
}
/* In-map-Panel (Mess-Tool) hat einen flex-Header (.geolyser-measure-
 * head) — gleicher Push-to-right-Trick. */
.geolyser-measure-head > .modal-minimize-btn {
    margin-left: auto;
}
.geolyser-measure-head > .modal-minimize-btn + .icon-btn,
.geolyser-measure-head > .icon-btn[data-action="close"] {
    margin-left: 6px;
}

/* Mobile-Y-Fix : .modal-mobile-chapter-list ist nur das
 * Smartphone-Pendant zur Header-Tab-Bar. Default GLOBAL ausblenden,
 * sonst rendert sie auch auf Tablet/Desktop sichtbar im modal-body
 * (Browser-Default fuer div = block). Die Mobile-K-Regel im 768px-
 * Block ueberschreibt sie dort wieder auf display:flex. */
.modal-mobile-chapter-list {
    display: none;
}
/* Mobile-Y-Fix : Back-Pfeil im Modal-Header analog — nur
 * via JS auf Mobile sichtbar gemacht. Default: hidden-Attribut sitzt
 * im HTML, plus dieses CSS als Safety-Net falls das Attribut mal
 * verloren geht. */
.modal-back-btn[hidden] {
    display: none !important;
}

/* +N-Tag-Chip mit Hover-Popover, der alle
 versteckten Tags inkl. Farben als Liste zeigt. Vorher nur title-
 Tooltip ohne Tag-Farben. */
.popup-tag.tag--more.has-tag-popover {
    position: relative;
    cursor: help;
}
.tag-popover {
    display: none;
    position: absolute;
    bottom: calc(100% + 6px);
    left: 0;
    z-index: 1300;
    padding: 6px 8px;
    background: var(--bg-card, #fff);
    border: 1px solid var(--border, #ccc);
    border-radius: 8px;
    box-shadow: 0 6px 18px rgba(0,0,0,0.20);
    max-width: 280px;
    white-space: normal;
    line-height: 1.7;
    /* Text-Groesse an die "echten" Listen-Tags angleichen,
 sonst wirkt das Hover-Popup wie ein abgeschnittener Tooltip. */
    font-size: 0.92em;
}
.tag-popover .popup-tag {
    font-size: 1em;
}
.popup-tag.tag--more.has-tag-popover:hover .tag-popover,
.popup-tag.tag--more.has-tag-popover:focus .tag-popover,
.popup-tag.tag--more.has-tag-popover:focus-within .tag-popover {
    display: block;
}
[data-theme="dark"] .tag-popover {
    background: var(--surface-elevated, #1f2024);
    border-color: rgba(255,255,255,0.14);
}

/* Retroaktive Mess-Tools im Feature-Edit-Modal.
 Liegt zwischen Form und Action-Bar, scaled per Buttons (sichtbar wenn
 data-action="retro-*" passt zum Geometrie-Typ). */
.feature-modal-retro-tools {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding: 10px 0 6px;
    border-top: 1px dashed var(--border);
    margin-top: 12px;
    /* align Items damit Retro-Btns + DSM-Source-Select
 auf gleicher Hoehe sitzen. */
    align-items: center;
}
.feature-modal-retro-tools[hidden] { display: none; }
/* Strikte Geometrie-Filter — Retro-Buttons sind je nach
 Geometrie-Typ ENTWEDER sichtbar ODER vollstaendig entfernt (keine
 leeren Slots). Funktioniert mit hidden-Attribut UND inline display. */
.retro-tool-btn[hidden],
.retro-tool-btn[style*="display: none"] { display: none !important; }
.retro-tool-btn {
    background: rgba(0, 204, 255, 0.10) !important;
    color: #003848 !important;
    border-color: rgba(0, 204, 255, 0.40) !important;
    font-size: 0.88em;
    padding: 6px 10px;
}
.retro-tool-btn:hover {
    background: rgba(0, 204, 255, 0.22) !important;
    border-color: rgba(0, 204, 255, 0.65) !important;
}
[data-theme="dark"] .retro-tool-btn {
    background: rgba(0, 204, 255, 0.16) !important;
    color: #b8edff !important;
    border-color: rgba(0, 204, 255, 0.50) !important;
}

/* Layer-Import-Btn nur Icon (analog DB-Import).
 Icon-Tinting via filter, kein Text-Span mehr. */
.layer-import-btn {
    padding: 6px;
    width: 34px; height: 34px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.layer-import-btn img {
    transition: filter .12s;
}
[data-theme="dark"] .layer-import-btn img {
    filter: invert(1) brightness(2);
}
.layer-import-btn:hover img {
    filter: brightness(0) saturate(100%) invert(45%) sepia(94%)
            saturate(2050%) hue-rotate(166deg) brightness(95%) contrast(101%);
}

/* Bulk-Export-Btn analog zum Import-Btn. Das
 cloud-download-Icon hat im SVG hart fill=#000000, dadurch waere es
 im Dark-Mode unsichtbar. Filter dreht die Farbe pro Theme, Hover
 bekommt den gleichen Cyan-Tint wie der Import-Btn. */
.layer-export-btn {
    padding: 6px;
    width: 34px; height: 34px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.layer-export-btn img {
    transition: filter .12s;
}
[data-theme="dark"] .layer-export-btn img {
    filter: invert(1) brightness(2);
}
.layer-export-btn:hover img {
    filter: brightness(0) saturate(100%) invert(45%) sepia(94%)
            saturate(2050%) hue-rotate(166deg) brightness(95%) contrast(101%);
}

/* 2026-06-14 (JP-Request): Cloud-Download-Icon der neuen Einzel-Export-
   Buttons (DB-Zeile, Feature-Edit-Modal, Public-View). Das SVG hat hart
   fill=#000000 -> im Dark-Mode invertieren, sonst unsichtbar. Neutral,
   keine eigene Akzentfarbe. */
.dl-cloud-icon { transition: filter .12s; }
[data-theme="dark"] .dl-cloud-icon { filter: invert(1) brightness(2); }

/* Per-Row Export-Cloud-Icon im Load-Layer-Modal ("Layers"-Modal) war im
   Dark-Mode dunkel — anders als der Bulk-Export-Btn (.layer-export-btn)
   hatte .load-modal-row-btn keinen Invert-Filter. */
[data-theme="dark"] .load-modal-row-btn img { filter: invert(1) brightness(2); }

/* Generische Bulk-/Cancel-Akzente
 fuer Modal-Buttons die sonst alle die gleiche ghost-Farbe wie der
 Hintergrund hatten. Werden in Tile-Export-Modal und Layer-Import-
 Duplikate-Modal genutzt. */
.bulk-select-accent {
    background: rgba(70, 170, 90, 0.16) !important;
    color: #1d6a30 !important;
    border-color: rgba(70, 170, 90, 0.55) !important;
}
.bulk-select-accent:hover {
    background: rgba(70, 170, 90, 0.30) !important;
    border-color: rgba(70, 170, 90, 0.80) !important;
}
[data-theme="dark"] .bulk-select-accent {
    background: rgba(70, 170, 90, 0.20) !important;
    color: #88dca0 !important;
}
.bulk-deselect-accent {
    background: rgba(150, 150, 160, 0.16) !important;
    color: #555 !important;
    border-color: rgba(120, 120, 130, 0.45) !important;
}
.bulk-deselect-accent:hover {
    background: rgba(150, 150, 160, 0.28) !important;
    border-color: rgba(120, 120, 130, 0.70) !important;
}
[data-theme="dark"] .bulk-deselect-accent {
    background: rgba(180, 180, 190, 0.10) !important;
    color: #c0c0c8 !important;
    border-color: rgba(180, 180, 190, 0.30) !important;
}
.cancel-accent {
    background: rgba(180, 80, 80, 0.10) !important;
    color: #884444 !important;
    border-color: rgba(180, 80, 80, 0.40) !important;
}
.cancel-accent:hover {
    background: rgba(180, 80, 80, 0.20) !important;
    border-color: rgba(180, 80, 80, 0.65) !important;
}
[data-theme="dark"] .cancel-accent {
    background: rgba(220, 130, 130, 0.10) !important;
    color: #d49b9b !important;
    border-color: rgba(220, 130, 130, 0.32) !important;
}
/* Compare-Modal Bulk-Aktionen als Radio-Pill-
 * Group statt 3 separater Buttons. Hidden native Radios, gestylte Labels
 * als pill-Segmente. Neutraler Default + getintete Accent-Farbe (grau/
 * blau/amber) wenn selected. Hover hebt den Tint dezent an. */
.cmp-bulk-radios {
    border: 0;
    margin: 0;
    padding: 0;
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}
.cmp-bulk-legend {
    color: var(--muted-hi, var(--muted));
    font-size: 0.85em;
    margin-right: 6px;
    padding: 0;
    float: left;
    line-height: 30px;
}
.cmp-bulk-pill {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--bg-card);
    color: var(--fg);
    font-size: 0.88em;
    cursor: pointer;
    user-select: none;
    transition: background 0.15s ease, border-color 0.15s ease,
                color 0.15s ease, box-shadow 0.15s ease,
                transform 0.08s ease;
}
.cmp-bulk-pill:hover {
    border-color: var(--border-hi, var(--border));
    background: var(--bg-elevated);
}
.cmp-bulk-pill:active {
    transform: translateY(1px);
}
/* Native Radio versteckt, Pill ist die Hitbox. */
.cmp-bulk-pill input[type="radio"] {
    position: absolute;
    opacity: 0;
    width: 1px;
    height: 1px;
    pointer-events: none;
}
.cmp-bulk-pill input[type="radio"]:focus-visible + .cmp-bulk-pill-dot {
    outline: 2px solid var(--c-cyan, #3BBDE8);
    outline-offset: 2px;
}
/* Mini-Dot links vom Label, signalisiert Radio-Charakter; fuellt sich
 * bei :checked mit der Pill-Akzent-Farbe. */
.cmp-bulk-pill-dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    border: 1.5px solid currentColor;
    background: transparent;
    flex: 0 0 auto;
    transition: background 0.12s ease, transform 0.12s ease;
}
.cmp-bulk-pill input[type="radio"]:checked ~ .cmp-bulk-pill-dot {
    background: currentColor;
    transform: scale(1.08);
}
.cmp-bulk-pill-label { white-space: nowrap; }

/* Skip (grau, neutral) */
.cmp-bulk-pill--skip {
    color: #555;
}
.cmp-bulk-pill--skip:has(input:checked),
.cmp-bulk-pill--skip.is-checked {
    background: rgba(150, 150, 160, 0.22);
    border-color: rgba(120, 120, 130, 0.55);
    color: #444;
    box-shadow: 0 0 0 1px rgba(120, 120, 130, 0.18) inset;
}
[data-theme="dark"] .cmp-bulk-pill--skip {
    color: #c0c0c8;
}
[data-theme="dark"] .cmp-bulk-pill--skip:has(input:checked) {
    background: rgba(180, 180, 190, 0.20);
    border-color: rgba(180, 180, 190, 0.45);
    color: #e0e0e8;
}

/* Rename / Beide behalten (blau) */
.cmp-bulk-pill--rename {
    color: #1f5485;
}
.cmp-bulk-pill--rename:has(input:checked),
.cmp-bulk-pill--rename.is-checked {
    background: rgba(80, 130, 200, 0.22);
    border-color: rgba(80, 130, 200, 0.65);
    color: #1f5485;
    box-shadow: 0 0 0 1px rgba(80, 130, 200, 0.20) inset;
}
[data-theme="dark"] .cmp-bulk-pill--rename {
    color: #88c0e8;
}
[data-theme="dark"] .cmp-bulk-pill--rename:has(input:checked) {
    background: rgba(80, 130, 200, 0.26);
    border-color: rgba(120, 170, 230, 0.70);
    color: #b3d8f5;
}

/* Replace / Ersetzen (amber, leicht warnend) */
.cmp-bulk-pill--replace {
    color: #8a5d10;
}
.cmp-bulk-pill--replace:has(input:checked),
.cmp-bulk-pill--replace.is-checked {
    background: rgba(232, 175, 64, 0.26);
    border-color: rgba(232, 175, 64, 0.75);
    color: #8a5d10;
    box-shadow: 0 0 0 1px rgba(232, 175, 64, 0.25) inset;
}
[data-theme="dark"] .cmp-bulk-pill--replace {
    color: #f0c270;
}
[data-theme="dark"] .cmp-bulk-pill--replace:has(input:checked) {
    background: rgba(232, 175, 64, 0.30);
    border-color: rgba(248, 200, 100, 0.80);
    color: #ffd58a;
}

/* clear-layers Btn ROT damit die destruktive
 Aktion (Drafts verwerfen + alle Layer aus Ansicht entfernen) sich klar
 vom Plus-Btn (gruen) und Load-Btn (lila) absetzt. */
.sidebar-clear-accent {
    background: rgba(220, 80, 80, 0.16) !important;
    color: #993030 !important;
    border-color: rgba(220, 80, 80, 0.45) !important;
}
.sidebar-clear-accent:hover {
    background: rgba(220, 80, 80, 0.32) !important;
    border-color: rgba(220, 80, 80, 0.75) !important;
    color: #7a1f1f !important;
}
.sidebar-clear-accent img {
    filter: brightness(0) saturate(100%) invert(20%) sepia(80%) saturate(2400%) hue-rotate(345deg) brightness(95%) contrast(95%);
}
[data-theme="dark"] .sidebar-clear-accent {
    background: rgba(220, 80, 80, 0.20) !important;
    color: #ee9090 !important;
    border-color: rgba(220, 80, 80, 0.55) !important;
}
[data-theme="dark"] .sidebar-clear-accent:hover {
    background: rgba(220, 80, 80, 0.36) !important;
    color: #ffaaaa !important;
}
[data-theme="dark"] .sidebar-clear-accent img {
    filter: brightness(0) saturate(100%) invert(72%) sepia(45%) saturate(580%) hue-rotate(310deg) brightness(102%) contrast(95%);
}

/* "Entfernen" im Lade-Modal: amber-getoenter Akzent damit die Aktion
   klar von "Laden" (gruen/primary) und "Loeschen" (rot/danger)
   abgegrenzt ist - "remove from view" ist reversibel, kein Loeschen.
   Im Hover wird das Amber kraeftiger. */
.load-modal-unload {
    color: var(--c-amber, #c98a00) !important;
    border-color: rgba(201, 138, 0, 0.45) !important;
    background: rgba(201, 138, 0, 0.08) !important;
}
.load-modal-unload:hover {
    background: rgba(201, 138, 0, 0.18) !important;
    border-color: rgba(201, 138, 0, 0.75) !important;
    color: #b07900 !important;
}
[data-theme="light"] .load-modal-unload {
    color: #8a5d00 !important;
    border-color: #d8b15c !important;
    background: #fff4dc !important;
}
[data-theme="light"] .load-modal-unload:hover {
    background: #ffe7b3 !important;
    border-color: #b48430 !important;
    color: #6a4500 !important;
}

/* Trash-Modal Multi-Select Header-Checkbox + Hover-Optik. */
.trash-table thead th .trash-select-all {
    cursor: pointer;
    accent-color: var(--c-primary);
}
.trash-table tbody tr.is-selected td {
    background: rgba(0, 160, 210, 0.10);
}
[data-theme="light"] .trash-table tbody tr.is-selected td {
    background: rgba(0, 160, 210, 0.16);
}

/* ===================================================================
 Sync-Pill in der Topbar + Sync-Modal.
 Pill ist sichtbar nur wenn pending>0 (hidden=true via JS sonst).
 Counter-Badge sitzt rechts oben am Icon. Bei failed-Items kriegt
 die Pill einen Amber-Tint, damit der User merkt "da ist was".
 =================================================================== */
/* polish: coral als Akzentfarbe (Wunsch JP) - hebt sich von
 den anderen Topbar-Icons (neutral/gruen/violett/amber) klar ab.
 [hidden] muss explizit erzwungen werden weil .icon-btn ein
 display: inline-flex setzt das den User-Agent-Default
 display: none ueberschreibt - ohne diese Regel waere der Pill
 sichtbar obwohl JS hidden=true gesetzt hat. */
.sync-pill[hidden] {
    display: none !important;
}
.sync-pill {
    position: relative;
    color: #ff7f50 !important;
}
.sync-pill:hover {
    color: #e55934 !important;
    background: rgba(255, 127, 80, 0.14);
}
[data-theme="dark"] .sync-pill { color: #ff8c66 !important; }
[data-theme="dark"] .sync-pill:hover { color: #ffaa88 !important; }

.sync-pill--has-failed {
    /* Bei Failures kraeftiger und pulsierend, damit der User die
       Aufmerksamkeit kriegt - immer noch im Coral-Spektrum statt
       hartem rot. */
    color: #d8421e !important;
    animation: sync-pulse 2s ease-in-out infinite;
}
[data-theme="dark"] .sync-pill--has-failed { color: #ff6a3a !important; }

@keyframes sync-pulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.55; }
}

.sync-pill-count {
    position: absolute;
    top: 1px;
    right: 1px;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: 999px;
    /* Counter-Hintergrund explizit dunkelrot statt
 currentColor (war bei Coral-Foreground unleserlich), Text weiss. */
    background: #b71c1c !important;
    color: #fff !important;
    font-size: 11px;
    font-weight: 700;
    line-height: 16px;
    text-align: center;
    box-shadow: 0 0 0 1.5px var(--bg, #1a1d21);
    pointer-events: none;
}
[data-theme="light"] .sync-pill-count {
    box-shadow: 0 0 0 1.5px var(--bg-elevated, #fff);
}
.sync-pill-count::after {
    /* Damit der Counter-Text in der akzentfarbe der Pill bleibt aber
       die Schrift im Counter weiss ist - currentColor wird hier
       als Hintergrund genommen. */
    content: "";
}

/* Sync-Modal Body + Liste. */
.sync-modal-body {
    padding: 0 18px 12px;
    max-height: 60vh;
    overflow-y: auto;
}
.sync-modal-status {
    margin: 4px 0 12px;
    font-size: 0.92em;
}
.sync-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.sync-list-row {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 10px 12px;
    background: var(--bg-elevated, #20242a);
    border: 1px solid var(--border, #2c333c);
    border-radius: 8px;
}
.sync-list-row-main {
    flex: 1;
    min-width: 0;
}
.sync-list-row-label {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    font-weight: 500;
    word-break: break-word;
}
.sync-list-row-meta {
    margin-top: 2px;
    font-size: 0.85em;
}
.sync-list-row-err {
    margin-top: 4px;
    font-size: 0.85em;
    color: #ef4444;
    word-break: break-word;
}
[data-theme="dark"] .sync-list-row-err { color: #fca5a5; }
.sync-list-row-actions {
    display: flex;
    flex-shrink: 0;
    gap: 6px;
}
/* Discard/Retry-Buttons im Sync-Modal groesser & klarer
 beschriftet. Touch-Targets >= 36px. */
.sync-list-row-actions .icon-btn,
.sync-list-row-actions button {
    min-width: 38px;
    min-height: 38px;
    padding: 6px 10px;
    font-size: 0.9em;
}
.sync-empty {
    text-align: center;
    padding: 20px 0 8px;
    opacity: 0.7;
}

/* Status-Badges in der Liste: queued (grau), sending (blau), failed (rot). */
.sync-badge {
    display: inline-block;
    padding: 1px 8px;
    border-radius: 999px;
    font-size: 0.72em;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    line-height: 1.6;
    border: 1px solid transparent;
    white-space: nowrap;
}
.sync-badge--queued {
    background: rgba(148, 163, 184, 0.18);
    color: #94a3b8;
    border-color: rgba(148, 163, 184, 0.4);
}
.sync-badge--sending {
    background: rgba(59, 130, 246, 0.18);
    color: #60a5fa;
    border-color: rgba(59, 130, 246, 0.4);
}
.sync-badge--failed {
    background: rgba(239, 68, 68, 0.18);
    color: #ef4444;
    border-color: rgba(239, 68, 68, 0.45);
}
[data-theme="light"] .sync-badge--queued { color: #475569; }
[data-theme="light"] .sync-badge--sending { color: #1d4ed8; }
[data-theme="light"] .sync-badge--failed { color: #b91c1c; }

/* =====================================================================
 — Mobile Responsive Pass.
 Ziel:
 - Modals werden auf <=600px zu Bottom-Sheets / Vollbild
 - Topbar-Buttons bekommen min. 44x44 Touch-Target
 - Mess-Panel als Bottom-Sheet
 - Tabellen scrollen horizontal
 - Geom-Mini-Map kleiner
 ===================================================================== */
@media (max-width: 600px) {
    /* --- Topbar: Tighter spacing, scrollable wenn zu viele Icons. --- */
    .topbar {
        gap: 4px;
        padding: 6px 8px;
        flex-wrap: nowrap;
        overflow-x: auto;
    }
    .topbar-right {
        gap: 2px;
        flex-wrap: nowrap;
    }
    /* Topbar-Icon-Btns bleiben auf Mobile bei
 36x36 (genau wie der Desktop-Default `.topbar-right .icon-btn`),
 statt vorher auf 44x44 hochzuschalten. Grund: bei vielen Icons
 wurde die Topbar sonst zu breit + die Buttons wirkten ungleich
 gross gegenueber dem 36x36-User-Pill und der view-switcher-Spacer
 passte nicht mehr exakt unter den floating view-stack. */
    .topbar .icon-btn,
    .topbar .ghost {
        min-width: 36px;
        min-height: 36px;
        padding: 0;
    }
    /* View-Switcher (Header-Spacer) + Stack-Items folgen demselben
       36x36-Grid wie alle anderen Topbar-Icons — sonst sitzt der
       floating view-stack nicht exakt im Spacer-Slot und wirkt nach
       links/oben versetzt. */
    .topbar .view-switcher {
        width: 36px;
        height: 36px;
        flex: 0 0 36px;
    }
    .view-stack-item {
        width: 36px;
        height: 36px;
        min-width: 36px;
        max-width: 36px;
        min-height: 36px;
        max-height: 36px;
        flex: 0 0 36px;
    }
    /* User-Pill folgt dem 36x36-Default (siehe #user-pill.icon-btn
       oben), kein Mobile-Override mehr. */
    #user-pill.icon-btn {
        width: 36px;
        height: 36px;
    }
    .user-pill {
        font-size: 0.85em;
        max-width: 110px;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    /* --- Modals: Vollbild auf Mobile. --- */
    .modal-card,
    .modal-card--wide,
    .modal-card--wider {
        max-width: 100vw !important;
        width: 100vw !important;
        max-height: 100dvh;
        height: 100dvh;
        border-radius: 0 !important;
        margin: 0 !important;
        display: flex;
        flex-direction: column;
    }
    .modal-card--sm {
        max-width: 92vw !important;
        width: 92vw !important;
        max-height: calc(100dvh - 48px);
        height: auto;
    }
    /* Mobile-W-Fix Confirm-Dialoge (.modal--confirm) auf Mobile
 * dann doch in Vollbild — sonst wirkt der Abmelden-Confirm wie
 * ein zufaelliges Pop-up auf der Karte. Andere Klein-Modals
 * (bug-modal, image-lightbox) sind nicht .modal--confirm und
 * bleiben damit unangefasst (Lightbox haengt sowieso eigene
 * Fullscreen-Regel). */
    .modal.modal--confirm .modal-card.modal-card--sm {
        max-width: 100vw !important;
        width: 100vw !important;
        height: 100dvh !important;
        max-height: 100dvh !important;
        border-radius: 0 !important;
        margin: 0 !important;
    }
    .modal.modal--confirm .modal-card.modal-card--sm > .modal-text,
    .modal.modal--confirm .modal-card.modal-card--sm > .confirm-checkbox {
        padding: 12px 16px;
        margin: 0;
        flex: 1 1 auto;
        align-self: flex-start;
        font-size: 1rem;
    }
    /* Mobile-AA-Fix * Vorher hat diese Regel JEDE .modal-form mit flex:1 1 auto +
 * overflow-y:auto belegt — auch geschachtelte Forms im profile-
 * modal-body (timezone-form, password-form). Die wurden als Flex-
 * Items zwischen den anderen Body-Childs auf ~12px gequetscht und
 * scrollten dann ihren gesamten Inhalt innerhalb dieser 12px.
 * Selektor jetzt auf DIREKTE Modal-Card-Kinder eingeschraenkt
 * (".modal-card > .modal-form" etc.), genau so wie Mobile-I es
 * macht. Geschachtelte Forms bekommen ihre natuerliche Hoehe und
 * scrollen nicht selbst — der Body scrollt. */
    .modal-card > .modal-body,
    .modal-card > .modal-form,
    .modal-card > .profile-modal-body,
    .modal-card > .pane,
    .modal-card > .xt-create-form {
        flex: 1 1 auto;
        overflow-y: auto !important;
        -webkit-overflow-scrolling: touch;
        padding-bottom: 12px;
    }
    /* Mobile-AA-Fix: innere Forms im Profil-Modal explizit zurueck auf
     * natuerliche Hoehe + sichtbares Overflow (Safety-Net, falls
     * andere alte Regeln per Spezifitaet noch zugreifen). */
    #profile-modal .profile-modal-body > form.modal-form,
    #profile-modal .modal-body > form.modal-form {
        flex: 0 0 auto !important;
        overflow: visible !important;
        height: auto !important;
        min-height: 0 !important;
    }
    .modal-header {
        position: sticky;
        top: 0;
        z-index: 2;
        background: var(--bg-card, #fff);
        border-bottom: 1px solid var(--border);
    }
    .modal-footer {
        position: sticky;
        bottom: 0;
        background: var(--bg-card, #fff);
        border-top: 1px solid var(--border);
        padding: 8px 10px;
    }
    .modal-actions {
        flex-wrap: wrap;
        gap: 6px;
    }
    .modal-actions button {
        min-height: 44px;
        flex: 1 1 auto;
    }

    /* --- Tabellen scrollen horizontal statt zu zerquetschen. --- */
    .trash-table,
    .modal-card table {
        display: block;
        overflow-x: auto;
        white-space: nowrap;
    }

    /* --- Geom-Edit-Mini auf Mobile: kompakter. --- */
    .feature-geomedit-mini {
        height: 160px !important;
    }

    /* --- Mess-Panel als Bottom-Sheet. --- */
    .geolyser-measure-panel {
        right: 0;
        bottom: 0;
        width: 100vw;
        max-width: 100vw;
        border-radius: 12px 12px 0 0;
    }

    /* --- Sync-Modal-Liste: Items vertikal stapeln. --- */
    .sync-list-row {
        flex-wrap: wrap;
        gap: 4px;
    }

    /* --- Login-Card: weniger Padding. --- */
    .login-card {
        padding: 16px !important;
    }

    /* --- Marker-Icon-Picker: kleinere Buttons. --- */
    .marker-icon-picker {
        gap: 4px;
    }
    .marker-icon-picker button {
        min-width: 44px;
        min-height: 44px;
    }

    /* --- Tag-Picker-Suggestions als Dropdown statt absoluter Overlay. --- */
    .tag-suggestions {
        max-height: 50vh;
    }

    /* --- DB-Modal: Filter-Bar auf zwei Zeilen wenn zu eng. --- */
    .db-filter-bar {
        flex-wrap: wrap;
        gap: 6px;
    }
    .db-filter-search {
        flex: 1 1 100% !important;
    }

    /* --- Layer-Control auf Mobile etwas groesser fuer Touch. --- */
    .leaflet-control-layers-expanded label {
        padding: 6px 4px;
        min-height: 32px;
        display: flex;
        align-items: center;
    }

    /* --- Image-Slots auf Mobile in 2 Spalten. --- */
    .image-slots {
        grid-template-columns: repeat(2, 1fr) !important;
    }

    /* --- GPS-Tools-Stack: kleiner und weiter rechts vom Locate-Btn. --- */
    .gps-tools {
        right: 8px;
        bottom: 70px;
    }
}

/* Sehr schmale Mobile (z. B. iPhone SE): noch dichter. */
@media (max-width: 380px) {
    .topbar h1, .topbar .brand-text {
        display: none;
    }
    .modal-title {
        font-size: 1em;
    }
    .feature-geomedit-mini {
        height: 130px !important;
    }
}

/* Touch-only-Geraete: Hover-Effekte reduzieren, Buttons groesser. */
@media (hover: none) and (pointer: coarse) {
    button, .icon-btn, .ghost, .primary {
        min-height: 40px;
    }
    /* Karte: Tap-Highlight von iOS abschalten. */
    #map, .leaflet-container {
        -webkit-tap-highlight-color: transparent;
    }
}

/* =====================================================================
 — Komplette Mobile-Ueberholung (zusaetzlich zur Phase-76-
 Basis oben). Zusaetzliche Fixes:
 - Body kein horizontales Scrolling (Karte wirkte abgeschnitten weil
 eine zu breite Sidebar das viewport scrolling triggerte)
 - Tablet-Breakpoint 768px
 - Sidebars als full-screen-overlays auf Mobile
 - Mess-Panel auf Mobile als Bottom-Sheet, nicht in-map
 - Locate/Geoman/Mess controls bekommen 36-40px touch-targets
 ===================================================================== */
html, body {
    overflow-x: hidden;
}
@media (max-width: 768px) {
    /* Sidebars als slide-in-Overlay statt feste Spalte. Das app-shell
       grid wird zu einem 1-Spalten-Layout, die Sidebars liegen darueber
       wenn sie geoeffnet sind. */
    .app-shell {
        grid-template-columns: 1fr !important;
        grid-template-areas: "main" !important;
    }
    .sidebar-left,
    .sidebar-right {
        position: fixed;
        top: 0;
        height: 100dvh;
        z-index: 1700;
        width: min(86vw, 360px);
        max-width: 86vw;
        background: var(--bg-card, #fff);
        box-shadow: 0 0 24px rgba(0, 0, 0, 0.4);
        transition: transform .22s ease;
    }
    .sidebar-left {
        left: 0;
        transform: translateX(-101%);
    }
    .sidebar-right {
        right: 0;
        transform: translateX(101%);
    }
    .sidebar-left.is-open-mobile { transform: translateX(0); }
    .sidebar-right.is-open-mobile { transform: translateX(0); }
    /* Resizer-Indikatoren ausblenden auf Mobile - Sidebars sind
       Overlays, nicht resizable. */
    .resize-handle, .resize-indicator { display: none !important; }
    /* Mess-Panel: auf Mobile NICHT als in-map-Sticker, sondern wieder
       als Bottom-Sheet damit es nicht halb auf der Karte wegfaellt. */
    .geolyser-measure-panel--in-map {
        position: fixed !important;
        top: auto !important;
        right: 0 !important;
        bottom: 0 !important;
        width: 100vw !important;
        max-width: 100vw !important;
        border-radius: 12px 12px 0 0;
        opacity: 1 !important;
    }
    /* Topbar: Logo verkleinern, Username darf umgebrochen werden. */
    .topbar .brand-logo, .topbar img.logo {
        max-height: 32px !important;
    }
    /* Geoman-Toolbar etwas weiter unten damit sie nicht hinter der
       Topbar liegt. */
    .leaflet-top.leaflet-left {
        top: 8px;
    }
    /* Modals auf Mobile (<= 768px) als Fullscreen-Sheet.
 So ist der Inhalt mit dem 100dvh-Viewport sichtbar (mobile
 Browser-URL-Leiste!) und der Footer mit Aktionen klebt unten,
 statt dass das Modal halb hinter dem Tastatur-Bereich
 verschwindet. .modal-card--sm Modals duerfen trotzdem klein
 bleiben (sind kurze Confirm-Dialoge). */
    .modal {
        align-items: stretch;
        padding: 0;
    }
    .modal .modal-card:not(.modal-card--sm) {
        width: 100vw;
        max-width: 100vw;
        height: 100dvh;
        max-height: 100dvh;
        border-radius: 0;
        display: flex;
        flex-direction: column;
    }
    .modal .modal-card:not(.modal-card--sm) .modal-body {
        flex: 1 1 auto;
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
    }
    .modal .modal-card:not(.modal-card--sm) .modal-footer {
        position: sticky;
        bottom: 0;
        background: var(--bg-card, #fff);
        border-top: 1px solid var(--border);
        padding: 10px 14px;
        margin: 0;
        z-index: 2;
    }
    /* Save-Options-Karten: Beschreibungstext wrappen erlauben. */
    .save-options-card-desc {
        white-space: normal;
    }
    /* DSM-Picker und vergleichbare dynamische Modals: max-width
       cap weg fuer Mobile damit sie auch fullscreen sind. */
    .modal .modal-card[style*="max-width"] {
        max-width: 100vw !important;
    }
}

/* Viewport-Fix fuer mobile Browser-URL-Leiste. Auf
 Geraeten ohne 100dvh-Support (alte iOS/Android-Browser) bleibt
 100vh als Fallback - dort kann's vorkommen dass die Bottom-Sheet
 leicht hinter der URL-Leiste liegt, ist aber lebbar. */
@supports not (height: 100dvh) {
    @media (max-width: 768px) {
        .modal .modal-card:not(.modal-card--sm) {
            height: 100vh;
            max-height: 100vh;
        }
        .sidebar-left, .sidebar-right { height: 100vh; }
    }
}

@media (max-width: 600px) {
    /* Mobile-O-Fix : image-Slots fuellen die verfuegbare Breite
 * auto-fit (mind. 80px pro Slot). Vorher 1 Spalte (also
 * untereinander), was viel zu viel vertikalen Platz brauchte.
 * Mit auto-fit + minmax(80px, 1fr) sitzen sie nebeneinander wo Platz
 * ist und brechen erst um wenn Slots sonst kleiner als 80px wuerden. */
    @supports (display: grid) {
        .image-slots {
            grid-template-columns: repeat(auto-fit, minmax(80px, 1fr)) !important;
        }
    }
    /* Topbar Brand-Text/Untertitel ausblenden, nur das Logo behalten. */
    .topbar .brand-sub {
        display: none;
    }
    /* Sync-Pill-Counter etwas groesser damit Touch-Tap zielt. */
    .sync-pill-count {
        min-width: 18px;
        height: 18px;
        font-size: 11px;
        line-height: 18px;
    }
    /* DB-Modal: Filter-Bar als Akkordeon-Button (Wrap) damit sie nicht
       die ganze Breite stiehlt. */
    .db-modal-filters {
        flex-wrap: wrap;
    }
}

/* sortierbare Tabellen-Header. Cursor + Hover-Hint.
 Wird im Admin-Modal von audit-table, admin-users-table, admin-xt-table
 und admin-fromothers-table genutzt. Bewusst dezenter als Buttons -
 Klick-Sort soll nicht wie eine primary action wirken. */
.trash-table th.is-sortable {
    cursor: pointer;
    user-select: none;
}
.trash-table th.is-sortable:hover {
    background: var(--bg-elevated, var(--input-bg));
}

/* DSM-Source-Dropdown unter den Mess-Tool-Buttons
 (Volumen/Profil) und unter den Retro-Tool-Buttons im Feature-Edit-
 Modal. Ersetzt das alte modal-basierte pickDsmSource (78.32). */
/* DSM-Source + Volume-Ref als einheitliches
 Picker-Block. Beide Rows im selben Grid mit fester Label-Spalte,
 sodass die Dropdowns vertikal fluchten. Wird im Mess-Tool und im
 Feature-Modal verwendet. */
.geolyser-picker-group {
    margin-top: 6px;
    border-top: 1px solid var(--border);
    padding-top: 2px;
}
.geolyser-picker-row {
    display: grid;
    grid-template-columns: 78px 1fr;
    gap: 8px;
    align-items: center;
    padding: 4px 8px;
}
.geolyser-picker-row[hidden] {
    display: none;
}
.geolyser-picker-row--ref {
    /* Wenn der Custom-Z-Input sichtbar ist, bekommen wir eine dritte
       Spalte. Ist er hidden (Default), greift die zweite Regel weiter
       unten und das Select fuellt die ganze Spalte (wie bei der
       DSM-Source-Row). */
    grid-template-columns: 78px 1fr 80px;
}
.geolyser-picker-row--ref:has(.geolyser-picker-customz[hidden]) {
    grid-template-columns: 78px 1fr;
}
.geolyser-picker-label {
    font-size: 0.78em;
    color: var(--muted-hi);
    justify-self: start;
    align-self: center;
}
.geolyser-picker-select {
    width: 100%;
    padding: 4px 6px;
    font-size: 0.85em;
    background: var(--input-bg);
    color: var(--fg);
    border: 1px solid var(--border);
    border-radius: 4px;
}
.geolyser-picker-customz {
    width: 100%;
    padding: 4px 6px;
    font-size: 0.85em;
    background: var(--input-bg);
    color: var(--fg);
    border: 1px solid var(--border);
    border-radius: 4px;
    font-variant-numeric: tabular-nums;
}
.geolyser-picker-customz[hidden] {
    display: none;
}

/* v2: Beschreibung + Geometrie-Mini-Vorschau nebeneinander
 als feste 260x260px-Quadrate. Description-Textarea fuellt den
 verfuegbaren Platz im Quadrat aus. Wenn keine Geometrie da ist
 (Create-Pfad), bleibt nur die Description-Box stehen, immer noch
 260x260. */
.feature-modal-desc-row {
    display: flex;
    gap: 12px;
    /* 2026-06-26 (JP-Request): flex-start statt stretch, damit die
     etwas niedrigere Beschreibung NICHT auf die 260px-Hoehe der
     Mini-Map hochgezogen wird — darunter ist jetzt Platz fuer den
     Audioaufnahme-Button. */
    align-items: flex-start;
    flex-wrap: wrap;          /* bei sehr schmalem Modal Umbruch */
    margin: 4px 0;
}
.feature-modal-desc-row .feature-modal-desc-field {
    /* Description ist flexibel — sie nimmt den
 verbleibenden Platz zwischen linker Modal-Edge und der 260px
 breiten Mini-Map. 2026-06-26: Hoehe von 260 auf 200 reduziert,
 damit darunter der Audioaufnahme-Button Platz hat. */
    flex: 1 1 0;
    min-width: 220px;
    height: 238px;
    margin: 0;
    display: flex;
    flex-direction: column;
}
.feature-modal-desc-row .feature-modal-desc-field textarea {
    flex: 1 1 auto;
    min-height: 0;
    width: 100%;
    resize: none;             /* feste Box, kein User-Resize */
}
.feature-modal-desc-row .feature-modal-geom-preview {
    flex: 0 0 260px;
    width: 260px;
    /* 2026-06-26 (JP): Hoehe an die Beschreibung (238px) angeglichen. */
    height: 238px;
}
.feature-modal-desc-row .feature-modal-geom-preview[hidden] {
    display: none;
}
.feature-modal-desc-row .feature-modal-geom-preview .feature-geomedit-mini {
    width: 100%;
    height: 100%;
    border-radius: var(--radius-sm, 4px);
    overflow: hidden;
    border: 1px solid var(--border);
}
/* Smartphone: Mini-Karte breiter (378px) aber flacher (160px). */
@media (max-width: 768px) {
    .feature-modal-desc-row .feature-modal-geom-preview {
        flex: 0 0 auto;
        width: 378px;
        max-width: 100%;
        height: 160px;
    }
}

/* Picker-Block sitzt jetzt unter den Retro-Tools-Buttons
 (DSM-Quelle ist nicht mehr inline in der Buttons-Zeile). Keine
 spezielle Regel mehr noetig — die .geolyser-picker-group-Klasse
 stylet beide Rows einheitlich. */


/* Flash-Highlight auf das Geometrie-Werte-Feld nach
 einer erfolgreichen Retro-Aktion (sample-z / profile / volume). Soll
 nur kurz aufflashen, nicht als persistent gruen-getoenetes Feld stehen
 bleiben. Animation 800ms, danach automatisch zurueck. */
.feature-geom-stats.is-flash {
    animation: geolyser-stats-flash 0.8s ease-out;
}
@keyframes geolyser-stats-flash {
    0%   { background: var(--c-signal-dim, rgba(36, 200, 130, 0.35));
           box-shadow: 0 0 0 4px var(--c-signal-dim, rgba(36, 200, 130, 0.25)); }
    100% { background: transparent; box-shadow: 0 0 0 0 transparent; }
}

/* Profil-Icon-Span in den Geometrie-Werten. Klick
 oeffnet das Profil-Chart-Modal (showProfileChart aus measurement-tool). */
.feature-profile-stat {
    cursor: pointer;
    transition: background 0.12s ease;
}
.feature-profile-stat:hover,
.feature-profile-stat:focus {
    background: var(--bg-elevated, var(--input-bg));
    outline: none;
}

/* Progress-Toast fuer DSM-Sampling-Loops.
 Eine eigene Klasse oben auf .geolyser-toast - bekommt eine Progress-
 Bar darunter die ueber die Lebenszeit von 0% auf 100% wandert. */
.geolyser-progress-toast {
    min-width: 240px;
}
.geolyser-progress-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 8px;
    margin-bottom: 4px;
}
.geolyser-progress-label {
    font-size: 0.9em;
    font-weight: 600;
}
.geolyser-progress-count {
    font-size: 0.78em;
    color: var(--muted-hi);
    font-variant-numeric: tabular-nums;
}
.geolyser-progress-bar {
    height: 4px;
    background: rgba(255, 255, 255, 0.16);
    border-radius: 2px;
    overflow: hidden;
}
.geolyser-progress-bar-fill {
    height: 100%;
    background: var(--accent, #3BBDE8);
    width: 0%;
    transition: width 0.18s ease-out;
}

/* Spinner im Progress-Toast. Sichtbar solange noch keine
 Phasen-Updates eingelaufen sind (Bar bei 0%). Verschwindet sobald
 setPercent(>0) feuert. */
.geolyser-progress-spinner {
    display: none;
    width: 14px;
    height: 14px;
    flex-shrink: 0;
    border: 2px solid rgba(255, 255, 255, 0.25);
    border-top-color: var(--accent, #3BBDE8);
    border-radius: 50%;
    animation: geolyser-progress-spin 0.8s linear infinite;
}
.geolyser-progress-toast.is-pending .geolyser-progress-spinner {
    display: inline-block;
}
.geolyser-progress-toast.is-pending .geolyser-progress-bar {
    /* Indeterminate-Stripe-Effekt waehrend der Bar bei 0 steht. */
    background: linear-gradient(
        90deg,
        rgba(255, 255, 255, 0.12) 0%,
        rgba(255, 255, 255, 0.22) 50%,
        rgba(255, 255, 255, 0.12) 100%
    );
    background-size: 200% 100%;
    animation: geolyser-progress-shimmer 1.4s linear infinite;
}
@keyframes geolyser-progress-spin {
    to { transform: rotate(360deg); }
}
@keyframes geolyser-progress-shimmer {
    0%   { background-position: -200% 0; }
    100% { background-position: 200% 0; }
}

/* Per-Feature Color-Picker im Feature-Edit-Modal.
 Pattern: 8x4 Grid mit Square-Tiles. Erstes Tile = "Auto" (= Layer-Farbe). */
.feature-color-picker {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.feature-color-pick {
    width: 28px;
    height: 28px;
    border-radius: 6px;
    border: 2px solid transparent;
    cursor: pointer;
    padding: 0;
    transition: transform 0.1s ease, border-color 0.12s ease;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.feature-color-pick:hover {
    transform: scale(1.08);
}
.feature-color-pick.is-active {
    border-color: var(--fg);
    box-shadow: 0 0 0 1px var(--bg-card);
}
.feature-color-pick-auto {
    font-size: 0.78em;
    font-weight: 600;
    color: var(--muted-hi);
    background: var(--input-bg);
    width: 100%;
    height: 100%;
    border-radius: 4px;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Opacity-Slider unter jedem Overlay-Layer im
 Leaflet-Layer-Control. Slider full-width, Wert rechts. */
.geolyser-opacity-slider-row {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 2px 4px 4px 24px;
    flex-basis: 100%;
}
.geolyser-opacity-icon {
    color: var(--muted-hi);
    font-size: 0.85em;
    flex-shrink: 0;
}
.geolyser-opacity-slider {
    flex: 1;
    min-width: 0;
    height: 14px;
    cursor: pointer;
}
.geolyser-opacity-val {
    font-size: 0.72em;
    color: var(--muted-hi);
    min-width: 32px;
    text-align: right;
    font-variant-numeric: tabular-nums;
    flex-shrink: 0;
}

/* zusaetzliche Modal-Footer-Modifier. */
.modal-footer--center {
    justify-content: center;
}
.modal-footer--split {
    justify-content: space-between;
}
.primary.primary-wide {
    min-width: 220px;
    padding: 10px 24px;
    font-size: 1em;
}

/* Audit-Toolbar vertikal zentrieren. */
.audit-toolbar.audit-toolbar--centered {
    display: flex;
    align-items: end;
    gap: 12px;
}
.audit-toolbar.audit-toolbar--centered .audit-toolbar-filter {
    display: flex;
    flex-direction: column;
    gap: 2px;
}
/* Refresh-Btn vertikal mit dem select-Element des Filters
 alignen, nicht mit der Label-Zeile darueber. */
.audit-toolbar.audit-toolbar--centered [data-action="audit-refresh"] {
    align-self: end;
    margin-bottom: 0;
}

/* =====================================================================
 - Mobile UI Refresh
 ----------------------------------------------------------------------
 Sammlung aller Mobile-Polish-Punkte aus Batch 8. Greift on top der
 bestehenden Phase-77.9- und Phase-78.20-Mobile-Regeln. Bewusst als
 eigener Block am Ende der Datei, damit die Spezifitaet greift ohne
 bestehende Regeln zu touchieren.
 ===================================================================== */

/* 8.1 — UI-Elemente kleiner. Topbar-Buttons hatten 44px-Touch-Targets,
   das ist auf modernen Geraeten oft uebertrieben. 36px reicht und gibt
   mehr horizontalen Platz. */
@media (max-width: 768px) {
    .topbar .icon-btn,
    .topbar .ghost {
        min-width: 36px !important;
        min-height: 36px !important;
        padding: 6px !important;
    }
    .topbar h1, .topbar .brand-text {
        font-size: 1em;
    }
    /* Sidebar-Header etwas kompakter. */
    .sidebar-header .icon-btn,
    .features-panel-rail .icon-btn {
        min-width: 36px;
        min-height: 36px;
    }
    /* Layer-Row-Buttons kompakter. */
    .layer-row .icon-btn,
    .layer-row .layer-toggle {
        min-width: 30px;
        min-height: 30px;
        padding: 4px;
    }
}

/* 8.2 — Modal-Stil im Mobile eigen. Im Fullscreen-Mode keine
 "halb-abgerundeten" Ecken (border-radius war 12px aussen, im Vollbild
 das ist kein Vollbild-Look). Eckig + bestaendig. setzte
 border-radius:0 auf .modal-card:not(.modal-card--sm), wir ziehen das
 konsequent durch. */
@media (max-width: 768px) {
    .modal .modal-card:not(.modal-card--sm) {
        border-radius: 0 !important;
        box-shadow: none !important;
    }
    .modal .modal-card:not(.modal-card--sm) .modal-header,
    .modal .modal-card:not(.modal-card--sm) .modal-footer {
        border-radius: 0 !important;
    }
}

/* 8.3 — Anleitung (Help-Modal) Mobile-Anpassung.
   - Zurueck-Pfeil im Detail-View nach oben RECHTS verschieben (war
     standard links).
   - Bug-Melden-Btn nur in der Kapitel-Uebersicht (Liste), nicht im
     Detail-Mode.
   - Kapitel-Liste vertikal mit groesserem Text. */
@media (max-width: 768px) {
    .help-shell.is-detail-mode .help-back-btn {
        position: absolute;
        top: 12px;
        right: 12px;
        left: auto;
    }
    .help-shell.is-detail-mode .help-bug-report-btn {
        display: none !important;
    }
    .help-shell .help-toc {
        display: flex;
        flex-direction: column;
        gap: 8px;
    }
    .help-shell .help-toc button[data-chapter] {
        padding: 12px 14px;
        font-size: 1.05em;
        text-align: left;
        border-radius: 6px;
    }
}

/* 8.4 — Settings / Admin-Einstellungen im selben Stil wie das Help-Modal:
   eckig, sticky-Header, Tab-Bar groesser fuer Touch. */
@media (max-width: 768px) {
    #admin-modal .modal-card,
    #profile-modal .modal-card {
        border-radius: 0 !important;
    }
    #admin-modal .modal-header-tabs button,
    #profile-modal .modal-header-tabs button {
        min-height: 40px;
        padding: 8px 12px;
        font-size: 0.95em;
    }
    /* Admin-Tabellen breiter scrollbar damit Action-Buttons rechts
       erreichbar sind ohne dass die Inputs aus der Zeile rauspoppen. */
    #admin-modal .trash-table {
        font-size: 0.85em;
    }
}

/* Mobile-UI-Refresh Image-Slot von 110px auf 70px Hoehe, action-Buttons
 von 32px auf 24px. Bild-Thumbnails bleiben quadratisch via aspect-ratio
 und nutzen den verfuegbaren Grid-Slot. */
@media (max-width: 768px) {
    .image-slots .image-slot {
        min-height: 70px !important;
        max-height: 90px;
    }
    .image-slot .image-slot-action,
    .image-slot button {
        min-width: 24px !important;
        min-height: 24px !important;
        padding: 2px;
    }
    /* Remove-Btn am Slot bleibt erkennbar gross genug fuer Touch (24px). */
    .image-slot-remove {
        width: 24px !important;
        height: 24px !important;
        font-size: 14px;
    }
    /* Hint-Text auf Mobile sehr kompakt. */
    .image-slot-hint {
        font-size: 10px !important;
        line-height: 1.1;
    }
}

/* 8.6 — DB-Vollansicht: Toolbar mit zweiter Reihe wenn zu viele Buttons.
   Bisher schoben sich die Buttons (Import / Export / Bulk-Edit / Attach /
   Delete) bei kleinem Viewport ueber den Rand. Wir wrappen jetzt in eine
   zweite Reihe. */
@media (max-width: 768px) {
    /* Mobile-UI-Refresh : alte Regel zielte auf `.db-toolbar`,
 * eine Klasse die im aktuellen HTML nicht existiert. Tatsaechlich
 * heisst die Toolbar im DB-Modal jetzt `.db-filter-bar` (oben)
 * + `.modal-footer.modal-footer--compact` (unten mit Import-Btn).
 * Der Import-Btn-Cutoff sitzt im Footer; wir wrappen den im Mobile. */
    .db-filter-bar,
    #db-modal .modal-footer.modal-footer--compact,
    .db-bulk-bar {
        flex-wrap: wrap !important;
        gap: 6px !important;
    }
    /* Buttons im DB-Modal-Footer behalten ihre Breite (kein flex-shrink),
     * aber duerfen in zweite Reihe wrappen. */
    #db-modal .modal-footer.modal-footer--compact > * {
        flex-shrink: 0;
    }
    /* Sel-Count + Import-Btn-Trenner in eigene Zeile damit nichts
     * abgeschnitten wird. */
    #db-modal [data-role="sel-count"] {
        margin-left: 0 !important;
        flex-basis: 100%;
        order: -1;
        font-size: 0.85em;
    }
    /* DB-Modal-Card im Mobile breiter als der Default `modal-card`,
     * sonst landet die Toolbar mit ihren Wraps unter dem Footer-Edge. */
    #db-modal .modal-card.modal-card--wider {
        max-width: 100vw;
        width: 100vw;
    }
    /* DB-Vollansicht Scrollbalken
 auf Smartphone: dicker, tuerkis, immer sichtbar — vertikal + horizontal. */
    #db-modal .modal-body {
        scrollbar-color: var(--c-cyan, #3BBDE8) rgba(0,0,0,0.08);
        scrollbar-width: auto;
        overflow-y: scroll;
        overflow-x: auto;
    }
    #db-modal .modal-body::-webkit-scrollbar {
        width: 8px;   /* vertikal */
        height: 8px;  /* horizontal */
    }
    #db-modal .modal-body::-webkit-scrollbar-track {
        background: rgba(0,0,0,0.06);
        border-radius: 4px;
    }
    #db-modal .modal-body::-webkit-scrollbar-thumb {
        background: var(--c-cyan, #3BBDE8);
        border-radius: 4px;
        min-width: 32px;  /* verhindert zu schmales Thumb bei kurzem Inhalt */
        min-height: 32px;
    }
    #db-modal .modal-body::-webkit-scrollbar-thumb:hover {
        background: #2aa6cf;
    }
    #db-modal .modal-body::-webkit-scrollbar-corner {
        background: rgba(0,0,0,0.06);
    }
}

/* 8.7 — Mein-Konto: Passwort + Zeitzone vollständig sichtbar im Mobile.
 Inputs full-width, Labels/Hint-Text wrappen. Kein horizontales Scrollen.
 Submit-Button vollbreit damit er erreichbar bleibt.
 Mobile-UI-Refresh : zusaetzlich modal-Card auf 100vw damit
 die Inputs nicht ueber das Card-Edge ragen. Plus alle Input-Typen
 (nicht nur password/text/select) abdecken — die alte Regel hatte
 `email`, `number`, `tel` nicht drin. */
@media (max-width: 768px) {
    #profile-modal .modal-card {
        max-width: 100vw !important;
        width: 100vw !important;
    }
    #profile-modal .field input,
    #profile-modal .field select,
    #profile-modal .field textarea {
        width: 100%;
        max-width: 100%;
        box-sizing: border-box;
    }
    #profile-modal .field {
        width: 100%;
        box-sizing: border-box;
    }
    #profile-modal .form-row {
        flex-wrap: wrap;
    }
    #profile-modal .modal-actions button.primary {
        width: 100%;
    }
    /* Modal-Body innen mit Padding, sonst kleben Inputs am Card-Edge. */
    #profile-modal .modal-body {
        padding-left: 12px !important;
        padding-right: 12px !important;
    }

    /* Mobile-J-Fix timezone-Select sah extrem
 * flach + abgeschnitten aus, Passwort-Inputs ebenso. Ursache: keine
 * explizite min-height fuer Inputs/Selects auf Mobile, plus die
 * native iOS-Select-Hoehe ist sehr klein wenn nur padding gesetzt
 * ist. Wir fixen es mit min-height: 44px (Touch-Standard) +
 * Font-Size 16px (vermeidet iOS-Safari Zoom-on-Focus) + appearance:
 * none + Custom-Chevron, damit das Select in beiden Themes gleich
 * gross dargestellt wird. Gleicher Min-Height fuer Inputs damit
 * Passwort-Felder auch klar sichtbar sind.
 * Mobile-S-Fix : Mobile-J hat trotz !important nicht
 * gegriffen — vermutlich greifen weiter unten in der CSS andere
 * Regeln auf .field input mit hoeherer Spezifitaet (z.B. via
 * #profile-modal .modal-form .field input). Sicherheitshalber
 * alle Properties mit !important markieren und zusaetzlich
 * height-Wert (nicht nur min-height) setzen damit nichts mehr
 * stauchen kann. Plus inkl. type-spezifischer Selektoren. */
    #profile-modal .field input,
    #profile-modal .field input[type="text"],
    #profile-modal .field input[type="password"],
    #profile-modal .field input[type="email"],
    #profile-modal .field input[type="number"],
    #profile-modal .field input[type="tel"],
    #profile-modal .field input[type="url"],
    #profile-modal .field input[type="search"],
    #profile-modal .field select,
    #profile-modal .field textarea,
    #profile-modal .modal-form .field input,
    #profile-modal .modal-form .field select,
    #profile-modal .modal-form .field textarea,
    #profile-modal form .field input,
    #profile-modal form .field select,
    #profile-modal form .field textarea {
        min-height: 44px !important;
        height: 44px !important;
        font-size: 16px !important;
        line-height: 1.3 !important;
        padding: 10px 12px !important;
        box-sizing: border-box !important;
        display: block !important;
    }
    #profile-modal .field textarea,
    #profile-modal .modal-form .field textarea {
        height: auto !important;
        min-height: 88px !important;
    }
    #profile-modal .field select,
    #profile-modal .modal-form .field select {
        appearance: none !important;
        -webkit-appearance: none !important;
        -moz-appearance: none !important;
        background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2306829c' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") !important;
        background-repeat: no-repeat !important;
        background-position: right 10px center !important;
        background-size: 18px 18px !important;
        padding-right: 36px !important;
    }
    /* Fields untereinander mit klarem Abstand, kein Stauchen. */
    #profile-modal .field {
        margin-bottom: 4px;
    }
    /* Submit-Btn der inneren Forms (Zeitzone, Passwort) bekommt
     * touch-freundliche Hoehe. */
    #profile-modal .modal-body form.modal-form .modal-actions {
        margin-top: 12px;
    }
    #profile-modal .modal-body form.modal-form .modal-actions button {
        min-height: 44px;
        font-size: 15px;
    }
    /* H4-Sections im profile-modal-body bekommen oben etwas mehr
     * Luft, damit Speicher/Daten/Loeschen klar trennbar bleiben. */
    #profile-modal .profile-modal-body h4 {
        margin-top: 18px;
        font-size: 1.05em;
    }
    #profile-modal .profile-modal-body h4:first-child {
        margin-top: 0;
    }
}

/* ConfirmDialog mit X oben rechts +
 centered primary-wide statt zwei Buttons unten. */
.confirm-card.confirm-card--has-close {
    position: relative;
    padding-top: 36px;
}
.confirm-card .confirm-close {
    position: absolute;
    top: 8px;
    right: 8px;
}
.modal-actions.modal-actions--center {
    justify-content: center;
}

/* Help-Modal-Suche im Footer. */
.help-modal-footer {
    align-items: center;
    gap: 12px;
}
.help-modal-search {
    display: flex;
    align-items: center;
    gap: 6px;
    background: var(--input-bg);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 4px 8px;
    flex: 0 1 260px;
}
.help-modal-search-icon {
    color: var(--muted-hi);
    flex-shrink: 0;
}
.help-modal-search-input {
    border: none;
    background: transparent;
    outline: none;
    color: var(--fg);
    font-size: 0.92em;
    flex: 1;
    min-width: 0;
}
.help-modal-search-input:focus {
    outline: none;
}
mark.help-search-hit {
    background: var(--c-amber, #f0c270);
    color: #1f1500;
    padding: 0 1px;
    border-radius: 2px;
}
@media (max-width: 768px) {
    .help-modal-footer {
        flex-wrap: wrap;
    }
    .help-modal-search {
        flex-basis: 100%;
        order: -1;
    }
}

/* (Batch 5): Presence-Bar als floating Container unten rechts
 neben dem Locate-Control. Chips horizontal, wrap bei vielen Usern.
 Tuerkise Border = User teilt Location (klickbar = pan-to-user). */
.presence-bar.presence-bar--floating {
    position: fixed;
    right: 8px;
    bottom: 110px;  /* knapp ueber Scale-Bar + Zoom-Steuerung */
    z-index: 900;   /* sehr hoch - ueber leaflet-controls (z 600/800) */
    display: flex !important;  /* hidden-Attribut bleibt ueber [hidden] respektiert */
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 4px;
    pointer-events: auto;
    max-width: 260px;
    /* ein Mini-Border-Frame, sonst sieht der "0 weitere"-
 Chip wie ein verirrter Tooltip aus und JP findet ihn nicht. */
    visibility: visible !important;
}
.presence-bar.presence-bar--floating[hidden] { display: none !important; }
.presence-bar.presence-bar--floating[hidden] {
    display: none;
}
.presence-bar.presence-bar--floating .presence-chip {
    cursor: default;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.18);
}
.presence-bar.presence-bar--floating .presence-chip.is-location-sharing,
.sidebar-presence-list .presence-chip.is-location-sharing {
    /* Coral statt tuerkis als Indikator-Border,
 pulsiert. Click pant zur Position des Users. */
    cursor: pointer;
    border: 2px solid #ff7f7f;  /* coral */
    box-shadow: 0 0 0 0 rgba(255, 127, 127, 0.55),
                0 2px 6px rgba(0, 0, 0, 0.18);
    transition: transform 0.12s ease;
    animation: presence-chip-location-pulse 1.8s ease-in-out infinite;
}
@keyframes presence-chip-location-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(255, 127, 127, 0.55),
                           0 2px 6px rgba(0, 0, 0, 0.18); }
    50%      { box-shadow: 0 0 0 6px rgba(255, 127, 127, 0),
                           0 2px 6px rgba(0, 0, 0, 0.18); }
}
.presence-bar.presence-bar--floating .presence-chip.is-location-sharing:hover,
.sidebar-presence-list .presence-chip.is-location-sharing:hover {
    transform: scale(1.08);
}
.sidebar-presence-list .presence-chip {
    cursor: default;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
}
/* "0 weitere"-Hinweis fuer leere Presence-Bar. */
.presence-empty-hint {
    background: var(--bg-card);
    color: var(--muted-hi);
    font-size: 0.75em;
    padding: 4px 10px;
    border: 1px solid var(--border);
    border-radius: 999px;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.18);
    white-space: nowrap;
    pointer-events: auto;
}
[data-theme="dark"] .presence-empty-hint {
    background: var(--surface-elevated, #1f2024);
    color: #aab;
    border-color: rgba(255,255,255,0.18);
}
@media (max-width: 768px) {
    .presence-bar.presence-bar--floating {
        bottom: 96px;
        max-width: 50vw;
    }
}

/* =====================================================================
 Karten-Suche (Geocoding via Nominatim-Proxy)
 ----------------------------------------------------------------------
 Position links neben der Geoman-Toolbar (oben links). Box
 ist standardmaessig hidden; erst Klick auf Toggle-Btn faltet das
 Input-Feld auf. Dark-Mode-Hintergrund opak (vorher transparent +
 schlecht lesbar).
 ===================================================================== */
.map-search {
    /* relativ zum Map-Container (mountGeocoding haengt
 das Element jetzt in map.getContainer ein), nicht zum Window.
 So bleibt der Search-Btn IMMER ueber der Karte und verschwindet
 nicht unter dem Sidepanel.
 Mobile-G-Fix von oben-links nach
 UNTEN-LINKS verschoben, neben den Locate-Btn (bottomleft). Vorher
 wurde der Search-Toggle im Querformat/in der Mobile-Toolbar oft
 verdeckt; unten links ist nichts ausser Locate + Scale.
 Mobile-G2-Fix bottom 12->10, left 56->46
 (kompakter an den Locate-Btn).
 Mobile-G3-Fix : bottom 10->9 (1px tiefer, bessere
 Buendigkeit mit dem Locate-Pfeil). */
    position: absolute;
    bottom: 9px;
    left: 46px;
    top: auto;
    z-index: 800;
    display: flex !important;
    align-items: flex-end;
    gap: 4px;
    pointer-events: auto;
    visibility: visible !important;
}
/* Mobile-G-Fix : Wenn die Search-Box offen ist, soll sie
 * ueber allen Karten-Controls liegen (Layers, Scale, Attribution,
 * GPS-Tools usw.). Unter Modals (z 2000) bleibt sie weiterhin. */
.map-search.is-open {
    z-index: 1900;
}
.map-search,
.map-search > * { box-sizing: border-box; }
/* Search-Toggle pixel-identisch zur Geoman-Toolbar
 (siehe .leaflet-pm-toolbar a). Gleicher BG, Border-Radius, 30x30,
 tuerkiser Hover-Border. */
.map-search-toggle {
    /* Mobile-G2-Fix 30->32 px damit der Btn
 * etwas dominanter wirkt (matched besser den Locate-Btn nebenan).
 * Mobile-G5-Fix : min-height + min-width explizit auf 32
 * gesetzt, sonst greift die globale `button { min-height: 40 }`-Regel
 * aus `@media (hover: none) and (pointer: coarse)` und stretcht den
 * Btn auf 32x40. Das ist die ueberall-greifende Variante (Mobile +
 * Tablet + Desktop). */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    min-width: 32px;
    min-height: 32px;
    border-radius: var(--radius-sm, 6px);
    border: 1px solid var(--border);
    background: var(--bg-elevated);
    color: var(--fg);
    cursor: pointer;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
    transition: background 0.12s, color 0.12s, border-color 0.12s;
}
[data-theme="dark"] .map-search-toggle {
    background: #20262a;
}
.map-search-toggle svg { width: 16px; height: 16px; }
.map-search-toggle:hover {
    background: var(--bg-elevated);
    color: var(--c-primary-hi);
    border-color: var(--c-primary-hi);
}
[data-theme="dark"] .map-search-toggle:hover {
    background: #2b3338;
    border-color: var(--c-primary-hi);
}
.map-search.is-open .map-search-toggle {
    color: var(--c-primary-hi);
    background: var(--bg-elevated);
    border-color: var(--c-primary-hi);
}
.map-search-box {
    display: flex;
    align-items: center;
    /* Hintergrund opak gegen Karte/Tiles, sonst im Dark-Mode
 fast nicht lesbar. surface-elevated als Fallback, sonst bg-card.
 padding reduziert (4px 8px -> 0 6px) damit die Box
 die gleiche 30px-Hoehe wie der Toggle-Btn + die Geoman-Btns hat. */
    background: var(--surface-elevated, var(--bg-card));
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 0 6px;
    box-shadow: var(--shadow-card);
    min-width: 240px;
    max-width: 360px;
    position: relative;
    height: 30px;
}
/* Box explizit ausblenden wenn [hidden] gesetzt. UA-Default
 reicht meistens, aber das `display: flex` der Eltern macht das manchmal
 wackelig. */
.map-search-box[hidden] { display: none !important; }
[data-theme="dark"] .map-search-box,
[data-theme="dark"] .map-search-dropdown {
    background: var(--surface-elevated, #1f2024);
}
.map-search-icon {
    color: var(--muted-hi);
    flex-shrink: 0;
    margin-right: 6px;
    display: inline-flex;
    align-items: center;
}
.map-search-input {
    /* Input-Hoehe exakt auf 28px (die Box ist 30 - 2px Border),
 padding/margin auf 0, damit die Gesamthoehe gleich der Geoman-Btns
 (30px) bleibt. Font-Size bleibt unveraendert. */
    flex: 1;
    border: none;
    background: transparent;
    outline: none;
    color: var(--fg);
    font-size: 0.95em;
    min-width: 0;
    height: 28px;
    padding: 0;
    margin: 0;
    line-height: 28px;
}
.map-search-clear {
    background: transparent;
    border: none;
    color: var(--muted-hi);
    cursor: pointer;
    padding: 4px;
    display: inline-flex;
    align-items: center;
    border-radius: var(--radius-sm);
}
.map-search-clear:hover { color: var(--fg); }
.map-search-dropdown {
    /* Mobile-G-Fix : Da der Search-Toggle jetzt unten links
 * sitzt, gibt es nach unten keinen Platz fuer die Vorschlagsliste —
 * sie wuerde aus dem Map-Container fallen. Wir flippen das Dropdown
 * deshalb nach OBEN: `bottom: calc(100% + 4px)` plus `top: auto`. */
    position: absolute;
    top: auto;
    bottom: calc(100% + 4px);
    left: 0;
    right: 0;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    z-index: 1900;
    box-shadow: var(--shadow-card);
    max-height: 60vh;
    overflow-y: auto;
    z-index: 1;
}
.map-search-empty {
    padding: 10px 12px;
    color: var(--muted-hi);
    font-size: 0.9em;
}
.map-search-empty--err { color: var(--c-warn, #c33); }
.map-search-result {
    display: block;
    width: 100%;
    text-align: left;
    background: transparent;
    border: none;
    padding: 8px 12px;
    cursor: pointer;
    color: var(--fg);
    border-bottom: 1px solid var(--border);
    transition: background 0.08s;
}
.map-search-result:last-child { border-bottom: none; }
.map-search-result:hover {
    background: var(--bg-elevated, rgba(0, 0, 0, 0.04));
}
.map-search-result-name {
    font-size: 0.92em;
    line-height: 1.3;
}
.map-search-result-meta {
    margin-top: 2px;
    font-size: 0.78em;
    color: var(--muted-hi);
}
.map-search-pin {
    background: transparent !important;
    border: none !important;
    pointer-events: auto;
}
.map-search-popup { font-size: 0.9em; line-height: 1.3; max-width: 220px; }

@media (max-width: 768px) {
    /* Mobile-G-Fix : Toggle-Btn sitzt unten-links neben dem
 * Locate-Btn (siehe Standard-Block `bottom: 9px; left: 46px`).
 * Frueher waren hier alte Pre-Mobile-G-Werte (top:4px; left:56px;
 * right:8px) — die haben den absolute-Container ueber die ganze
 * Map-Breite gestreckt + mit pointer-events:auto die Karten-
 * Interaktion blockiert .
 * Wir lassen die Standard-Positionierung greifen und beschraenken
 * nur die innere Search-Box-Breite. */
    .map-search-box {
        min-width: 0;
        max-width: calc(100vw - 80px);
        width: auto;
    }
}

/* Feature-Modal-Footer (.modal-actions) sticky am unteren
 Rand. Der Form-Inhalt scrollt darueber, der Footer mit Speichern/
 Verwerfen/Loeschen bleibt immer sichtbar. */
#feature-modal .modal-card {
    /* breiteres Modal damit Footer-Buttons + Inhalt
 horizontal nicht ueberlaufen. Vorher: 480px Default. */
    max-width: 640px;
    width: min(640px, calc(100vw - 24px));
    overflow-x: hidden;
    overflow-y: hidden;  /* Card selbst scrollt nicht — die Form drin */
    height: auto;
    max-height: calc(100dvh - 16px);
    /* Card ist 3-Slot-Layout: Header (Title) -> Form
 (scrollable Body) -> Footer (modal-actions). Display:flex column
 kommt schon aus der globalen .modal-card-Definition. */
}
/* Form scrollt intern wenn ihr Content die verbleibende
 Card-Hoehe ueberlaeuft. Footer (.modal-actions als Geschwister, NICHT
 mehr in der Form) bleibt visuell ausserhalb des Scroll-Containers —
 damit landet der Scrollbar NUR neben dem Form-Body, nicht neben den
 Buttons. */
#feature-modal .modal-card > .modal-form {
    flex: 1 1 auto;
    overflow-y: auto;
    overflow-x: hidden;
    min-height: 0;
}
/* Footer als Geschwister der Form. KEIN sticky mehr —
 er ist sowieso schon ausserhalb des Scroll-Containers. */
#feature-modal .modal-card > .modal-actions {
    flex: 0 0 auto;
    /* Identisch zum Card-Hintergrund — der Footer wirkt visuell als
       Erweiterung der Card-Flaeche. */
    background: var(--bg-elevated);
    /* bottom-margin auf 0 — der Footer sitzt sauber im
 unteren Card-Padding-Bereich, gibt den 22px-Padding-Abstand zum
 Card-Rand frei. Vorher: -22px hat den Footer in den Padding-Bereich
 reingezogen ohne Bottom-Abstand. */
    margin: 8px -24px 0;
    padding: 12px 24px env(safe-area-inset-bottom, 12px);
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    justify-content: flex-end;
    align-items: center;
}
/* modal-actions ist jetzt Geschwister der Form
 (nicht mehr drinnen). Die obigen #feature-modal .modal-card >
 .modal-actions-Regeln gelten. */
/* v2: Immortal-Checkbox-Label im Footer. Kompakt, mit
 kleinem Shield-Icon. Zwischen Loeschen und Abbrechen platziert. */
.feature-modal-immortal-footer-label {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    cursor: pointer;
    color: var(--muted-hi, #555);
    font-size: 0.85em;
    user-select: none;
    /* Loeschen-Btn hat margin-right:auto inline — das pusht alles
       Andere nach rechts. Immortal-Label sitzt in der rechten Gruppe
       direkt vor Cancel. */
    padding: 4px 6px;
    border-radius: var(--radius-sm, 4px);
    border: 1px solid transparent;
}
/* HTML-[hidden]-Attribut MUSS gegen inline-flex stechen,
 sonst bleibt das Label sichtbar wenn JS hidden=true setzt. Auch fuer
 die alte versteckte Spiegel-Checkbox + den Clone-Btn. */
.feature-modal-immortal-footer-label[hidden],
#feature-modal-clone-btn[hidden],
#feature-modal-immortal-cb[hidden] {
    display: none !important;
}
.feature-modal-immortal-footer-label:hover {
    background: var(--bg-card);
    border-color: var(--border);
}
.feature-modal-immortal-footer-label input[type="checkbox"]:checked + svg {
    color: var(--c-primary, #06829c);
}
.feature-modal-immortal-footer-label input[type="checkbox"]:checked ~ span {
    color: var(--c-primary, #06829c);
    font-weight: 600;
}

/* Retro-Tool-Icons groesser + Dark-Mode-invert. */
.retro-tool-btn .retro-tool-icon-img {
    width: 22px;
    height: 22px;
    display: block;
}
[data-theme="dark"] .retro-tool-btn .retro-tool-icon-img {
    filter: invert(0.9) hue-rotate(180deg);
}

/* Mask-basierte Icon-Variante fuer retro-surface-plane +
 retro-surface. Die externen SVG-Dateien haben hartkodierte Farben;
 wir nutzen sie als CSS-Mask, damit das Icon currentColor folgt (wie
 die anderen retro-Buttons mit inline-SVG + stroke="currentColor"). */
.retro-tool-btn .retro-tool-icon-mask {
    display: inline-block;
    width: 22px;
    height: 22px;
    background-color: currentColor;
    -webkit-mask-position: center;
            mask-position: center;
    -webkit-mask-size: contain;
            mask-size: contain;
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
    vertical-align: middle;
}
.retro-tool-icon-mask--plane {
    -webkit-mask-image: url("/img/icons/icon_3d_plane.svg");
            mask-image: url("/img/icons/icon_3d_plane.svg");
}
.retro-tool-icon-mask--heatmap {
    -webkit-mask-image: url("/img/icons/icon_heatmap.svg");
            mask-image: url("/img/icons/icon_heatmap.svg");
}

/* Up/Down-Pfeile pro Overlay im Leaflet-Layer-Control. */
.geolyser-layer-sort-arrows {
    display: inline-flex;
    flex-direction: column;
    gap: 1px;
    margin-left: 4px;
    vertical-align: middle;
}
.geolyser-layer-sort-arrow {
    background: transparent;
    border: 1px solid var(--border);
    border-radius: 2px;
    color: var(--muted-hi);
    cursor: pointer;
    font-size: 8px;
    line-height: 1;
    padding: 1px 3px;
    width: 18px;
}
.geolyser-layer-sort-arrow:hover {
    color: var(--c-primary, #36b);
    border-color: var(--c-primary, #36b);
}

/* Inkognito-Modus-Button in Topbar (emerald). */
#incognito-btn {
    color: #10b981;  /* emerald-500 */
}
#incognito-btn:hover { color: #059669; }
[data-theme="dark"] #incognito-btn {
    color: #34d399;  /* emerald-400 */
}
[data-theme="dark"] #incognito-btn:hover { color: #6ee7b7; }
#incognito-btn.is-active {
    background: #10b981;
    color: #fff;
    border-color: #047857;
    box-shadow: inset 0 0 0 2px #064e3b;
}
[data-theme="dark"] #incognito-btn.is-active {
    background: #34d399;
    color: #052e16;
    border-color: #10b981;
}
/* Sprach-Toggle in violet. */
#lang-toggle {
    color: #8b5cf6;  /* violet-500 */
}
#lang-toggle:hover { color: #7c3aed; }
[data-theme="dark"] #lang-toggle {
    color: #a78bfa;  /* violet-400 */
}
[data-theme="dark"] #lang-toggle:hover { color: #c4b5fd; }
#incognito-btn.is-active::after {
    content: "";
    display: block;
    position: absolute;
    width: 6px; height: 6px;
    background: #ff4081;
    border-radius: 50%;
    top: 4px; right: 4px;
    box-shadow: 0 0 0 2px var(--bg-card);
}
#incognito-btn { position: relative; }

/* ============================================================
 * Mobile-F-Fix : Landscape-Layout fuer Mobile/Tablet
 * ------------------------------------------------------------
 * Im Querformat ist die Hoehe knapp, die Breite ueppig — eine
 * vertikale Geoman-Toolbar mit 8-12 Buttons + GPS-Tools darunter
 * sprengt den sichtbaren Bereich vertikal. Wir drehen beide
 * Toolbars horizontal damit alle Buttons im Bild bleiben.
 * Greift NUR auf Mobile/Tablet (max-width: 1024) im Landscape.
 * ============================================================ */
@media (orientation: landscape) and (max-width: 1024px) {
    /* Geoman-Toolbar (PM = Phase Manager) — horizontal flex. */
    .leaflet-pm-toolbar {
        display: flex !important;
        flex-direction: row !important;
        flex-wrap: wrap !important;
    }
    .leaflet-pm-toolbar a {
        margin-bottom: 0 !important;
        margin-right: 4px !important;
        margin-top: 0 !important;
    }
    .leaflet-pm-toolbar a:last-child {
        margin-right: 0 !important;
    }
    /* Geoman-Action-Bar (Cancel / Trash / Finish) im Drag-Mode bleibt
     * unter dem Tool-Btn — kein Override hier noetig. */

    /* GPS-Tools (Marker / Track-Line / Track-Polygon) horizontal.
     * Sowohl der Standalone-#gps-tools-Container als auch die Leaflet-
     * Control-Variante (.leaflet-bottom .gps-tools) abdecken. */
    #gps-tools.gps-tools,
    #map > #gps-tools.gps-tools,
    .leaflet-bottom .gps-tools {
        flex-direction: row !important;
        gap: 4px;
        align-items: center !important;
    }
    /* Status-Badge des GPS-Tracks zeigt sonst nach rechts vom Stack —
     * im horizontalen Layout will der User ihn unter den Buttons. */
    .leaflet-bottom .gps-tools .gps-tools-status,
    #gps-tools .gps-tools-status {
        position: absolute !important;
        left: 0 !important;
        bottom: calc(100% + 6px) !important;
        right: auto !important;
        top: auto !important;
        white-space: nowrap;
    }
}

/* Pending-Delete-Section unter Users-Tabelle. */
.admin-pending-delete {
    margin-top: 24px;
    padding-top: 16px;
    border-top: 2px dashed var(--border);
}
.admin-pending-delete-title {
    margin: 0 0 6px;
    font-size: 1.0em;
    color: var(--c-warn, #c93);
}
.admin-pending-delete-table {
    margin-top: 8px;
}

/* Snapshot-Modal Filter + Load-More. */
.snap-filter-row {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    margin: 8px 0;
}
.snap-filter-row label {
    font-size: 0.85em;
    color: var(--muted-hi);
    display: flex;
    align-items: center;
    gap: 4px;
}
.snap-filter-row input[type="date"] {
    padding: 3px 6px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--input-bg, var(--bg-card));
    color: var(--fg);
}
.snap-loadmore-row {
    text-align: center;
    margin-top: 10px;
}

/* Server-Side-Cluster-Marker. */
.geolyser-cluster {
    background: transparent !important;
    border: none !important;
    pointer-events: auto;
}
.geolyser-cluster-inner {
    border-radius: 50%;
    color: #fff;
    text-align: center;
    font-weight: 600;
    font-size: 0.85em;
    box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.7),
                0 2px 6px rgba(0, 0, 0, 0.25);
    user-select: none;
    cursor: pointer;
    transition: transform 0.12s;
}
.geolyser-cluster-inner:hover { transform: scale(1.08); }

/* Undo/Redo-Toolbar unten rechts auf der Karte,
 links neben der Leaflet-Locate-Control. Deutlich sichtbar
 (opaker Hintergrund + Schatten). */
.map-undo-bar {
    position: fixed;
    bottom: calc(env(safe-area-inset-bottom, 0px) + 28px);  /* knapp ueber Scale-Bar */
    right: 56px;          /* links neben Leaflet-Locate (~30px breit + Padding) */
    z-index: 850;
    display: flex;
    gap: 4px;
    pointer-events: auto;
}
.map-undo-btn {
    width: 32px;
    height: 32px;
    border-radius: 4px;
    border: 2px solid rgba(0, 0, 0, 0.2);
    background: #fff;
    color: #111;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
    transition: background 0.12s, color 0.12s, opacity 0.12s;
}
.map-undo-btn:hover:not(:disabled) {
    background: #f3f5f8;
    color: var(--c-primary, #36b);
}
.map-undo-btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}
[data-theme="dark"] .map-undo-btn {
    background: #1f2024;
    color: #eee;
    border-color: rgba(255, 255, 255, 0.2);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
}
[data-theme="dark"] .map-undo-btn:hover:not(:disabled) {
    background: #2a2c30;
    color: #6ad;
}
@media (max-width: 768px) {
    .map-undo-bar {
        right: 56px;
        bottom: calc(env(safe-area-inset-bottom, 0px) + 24px);
    }
}

/* Zeitfilter-Popover im DB-Modal. */
.db-time-popover {
    padding: 10px 12px;
    min-width: 280px;
}
.db-time-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 8px;
    flex-wrap: wrap;
}
.db-time-row label {
    min-width: 80px;
    font-size: 0.88em;
    color: var(--muted-hi);
}
.db-time-row input[type="date"] {
    flex: 1 1 110px;
    min-width: 110px;
    padding: 4px 6px;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--input-bg, var(--bg-card));
    color: var(--fg);
}
.db-time-presets {
    display: flex;
    gap: 6px;
    margin-top: 6px;
    flex-wrap: wrap;
}

/* Kompakte Bulk-Edit-Reihen. Jede Sektion
 * eine flex-row mit Label links + Controls inline daneben. Wraps wenn
 * der Container zu schmal wird (Smartphone). */
.bulk-edit-row {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    min-height: 36px;
}
.bulk-edit-row-label {
    flex: 0 0 auto;
    min-width: 70px;
    color: var(--muted-hi);
    font-weight: 500;
}
.bulk-edit-row > *:not(.bulk-edit-row-label) {
    flex: 1 1 auto;
    min-width: 0;
}
/* Bulk-Tag-Picker inline mit Label: braucht relative-Position fuer
 * den absoluten suggestions-Dropdown. */
.bulk-edit-tag-block .bulk-edit-tag-picker {
    flex: 1 1 200px;
    min-width: 0;
}
/* Color-Tiles + Marker-Tiles im inline-Layout: max-width damit sie
 * nicht den ganzen restlichen Platz fressen. */
.bulk-edit-color-block .bulk-edit-color-tiles,
.bulk-edit-marker-block .bulk-edit-marker-tiles {
    flex: 1 1 auto;
    min-width: 0;
}

/* Unified Bulk-Tag-Picker — alle Tags der
 * Selection als Chips mit X (Klick = pending-remove, durchgestrichen
 * mit ↩-Btn zum Zurueckholen). Neue Tags via Input+Enter werden mit
 * is-add hervorgehoben (cyan-Akzent). Pattern wie Feature-Edit-Modal.
 *
 * KEIN flex-direction: column auf dem
 * .bulk-edit-tag-block (sonst landet die Picker-Box untereinander mit
 * dem Label und der `flex: 1 1 auto`-Vererbung vom .bulk-edit-row laesst
 * den Picker auf VERTIKALER Hauptachse wachsen → 200px hohe Leerflaeche).
 * Inline-Layout aus .bulk-edit-row erbt sauber, Picker bekommt feste
 * Max-Hoehe + overflow:auto fuer die Chip-Liste. */
.bulk-edit-tag-block {
    /* Inline-Layout aus .bulk-edit-row (display:flex; align-items:center)
     * NICHT mehr ueberschreiben. */
}
.bulk-edit-tag-picker {
    position: relative;
    /* Picker darf breit werden (~3x so breit wie vorher), aber nicht
     * mehr als 64px hoch. Chip-Area scrollt intern wenn nötig. */
    max-height: 64px;
    overflow: hidden;
    flex: 1 1 600px !important;
    min-width: 0;
    padding: 4px 8px;
    gap: 4px;
}
.bulk-edit-tag-picker .tag-picker-chips {
    max-height: 28px;
    overflow-y: auto;
    overflow-x: hidden;
    align-content: flex-start;
    padding-right: 2px;
}
.bulk-edit-tag-picker .tag-picker-input {
    min-height: 22px;
}
/* Suggestion-Dropdown soll relativ zum Picker positioniert sein und
 * UEBER das Modal layern (z-index hoeher als Bulk-Edit-Liste). */
.bulk-edit-tag-picker .tag-picker-suggestions {
    z-index: 60;
}
.bulk-tag-chip {
    transition: opacity 0.12s, text-decoration 0.12s;
}
.bulk-tag-chip.is-remove-pending {
    opacity: 0.55;
    text-decoration: line-through;
    border-color: var(--c-error, #c44) !important;
}
.bulk-tag-chip.is-remove-pending .bulk-tag-chip-label {
    color: var(--c-error, #c44);
}
.bulk-tag-chip.is-add {
    border-color: var(--c-cyan, #3BBDE8) !important;
    background: rgba(59, 189, 232, 0.10);
}
.bulk-tag-chip.is-add .bulk-tag-chip-label {
    color: var(--c-cyan, #3BBDE8);
    font-weight: 500;
}
.bulk-tag-chip.is-locked {
    opacity: 0.7;
    font-style: italic;
}
/* v2 Chip-Body als Klick-Bereich fuer das
 * Tag-Color-Popup. Swatch-Dot zeigt aktuelle Tag-Farbe. */
.bulk-tag-chip-body {
    background: transparent;
    border: none;
    padding: 0;
    margin: 0;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    color: inherit;
    font: inherit;
}
.bulk-tag-chip-body:hover .bulk-tag-chip-label {
    text-decoration: underline;
}
.bulk-tag-chip-swatch {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    border: 1px solid var(--border);
    flex-shrink: 0;
}
.bulk-tag-chip-swatch--none {
    background: transparent;
    border-style: dashed;
}

/* Bulk-Name-Block — Mode + X + Y nebeneinander.
 * Mode-Select hat feste Breite, beide Inputs kompakt (1 1 110px) damit
 * X und Y auf derselben Zeile bleiben. Bei "replace"-Mode wird X via JS
 * eingeblendet. */
.bulk-edit-name-block {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}
.bulk-edit-name-mode {
    min-width: 150px;
    max-width: 200px;
}
.bulk-edit-name-input--compact {
    flex: 1 1 110px;
    min-width: 80px;
    max-width: 180px;
}
@media (max-width: 600px) {
    .bulk-edit-name-block {
        flex-direction: row;
        align-items: stretch;
        gap: 4px;
    }
    .bulk-edit-name-input--compact {
        flex: 1 1 90px;
    }
}

/* Bulk-Marker-Block — alle Icons in EINER Zeile
 * unter dem Farb-Picker. flex-wrap-Default damit bei sehr schmalen
 * Viewports doch umgebrochen wird, aber default versucht Inline-Row. */
.bulk-edit-marker-block {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}
.bulk-edit-marker-tiles {
    display: flex !important;
    flex-direction: row !important;
    flex-wrap: wrap;
    gap: 4px;
    align-items: center;
}
.bulk-edit-marker-tiles .marker-icon-pick {
    flex: 0 0 auto;
}
.bulk-marker-tile-none,
.bulk-marker-tile-clear {
    width: 32px;
    height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1.2em;
    color: var(--muted-hi);
}
.bulk-marker-tile-none.is-active,
.bulk-marker-tile-clear.is-active {
    color: var(--c-cyan, #3BBDE8);
    border-color: var(--c-cyan, #3BBDE8) !important;
}

/* Loading-Overlay waehrend Bulk-Apply.
 * Liegt absolut innerhalb der Modal-Card (.modal-card hat
 * position:relative). Semi-transparenter Layer + Spinner aus dem
 * bestehenden .spinner-Pattern (siehe Zeile ~1016). Eingeblendet via
 * JS durch entfernen des [hidden]-Attributs. */
.bulk-edit-loading {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.45);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 12px;
    z-index: 50;
    border-radius: var(--radius-lg);
    color: #fff;
    pointer-events: all;
}
.bulk-edit-loading[hidden] { display: none; }
.bulk-edit-loading .spinner {
    width: 36px; height: 36px;
    border-width: 3px;
    border-color: rgba(255,255,255,0.25);
    border-top-color: var(--c-cyan, #3BBDE8);
}
.bulk-edit-loading-text {
    font-size: 0.95em;
    font-weight: 500;
    color: #fff;
    text-shadow: 0 1px 2px rgba(0,0,0,0.45);
    text-align: center;
    padding: 0 14px;
}
[data-theme="light"] .bulk-edit-loading {
    background: rgba(255, 255, 255, 0.75);
    color: var(--fg);
}
[data-theme="light"] .bulk-edit-loading-text {
    color: var(--fg);
    text-shadow: none;
}

/* =====================================================================
 * Mobile-SS-Fix — End-of-file Override fuer Mess-Tool-Btns
 * + Geoman pm-actions auf Smartphone
 * ---------------------------------------------------------------------
 * JP-Iteration: Mobile-RR-Regeln lagen VOR der Phase-113.26-Regel
 * (Zeile 2431) und wurden bei gleicher Specificity + !important durch
 * Source-Order ueberschrieben. Beenden blieb 26px, Vollbild 32px,
 * Vollbild-Farbe falsch . Plus: display:flex !important auf
 * .geolyser-measure-actions-container hat die JS-inline-display:none-
 * Steuerung uebersteuert → permanent sichtbar. Hier final am Datei-
 * Ende rauschen — wins by source order auch ohne extra !important.
 * ===================================================================== */
@media (max-width: 768px) {
    /* Mess-Tool-Actions-Container vertikal-stapeln, aber Visibility
     * weiter via JS (measurement-tool.js _setActionsVisible). display
     * OHNE !important damit JS-inline `style.display = "none"` greift. */
    .geolyser-measure-actions-container {
        display: flex;
        flex-direction: column;
        align-items: stretch;
        gap: 4px;
    }
    /* Beide Mess-Btns exakt 160x30, gleiche Farbe + Border. Selektor
     * mit doppelter Class + .leaflet-touch sicher hochgezogen. */
    .leaflet-bar a.geolyser-measure-end-action,
    .leaflet-bar a.geolyser-measure-maximize-action,
    .leaflet-touch .leaflet-bar a.geolyser-measure-end-action,
    .leaflet-touch .leaflet-bar a.geolyser-measure-maximize-action,
    a.geolyser-measure-end-action,
    a.geolyser-measure-maximize-action {
        display: block !important;
        width: 160px !important;
        min-width: 160px !important;
        height: 30px !important;
        line-height: 28px !important;
        padding: 0 12px !important;
        font-size: 0.86em !important;
        text-align: center !important;
        margin: 0 !important;
        box-sizing: border-box !important;
        border-radius: 3px !important;
        background-color: var(--bg-elevated) !important;
        color: var(--text) !important;
        border: 1px solid var(--border) !important;
    }
    [data-theme="dark"] .leaflet-bar a.geolyser-measure-end-action,
    [data-theme="dark"] .leaflet-bar a.geolyser-measure-maximize-action,
    [data-theme="dark"] a.geolyser-measure-end-action,
    [data-theme="dark"] a.geolyser-measure-maximize-action {
        background-color: #2c2f33 !important;
        color: #eaeaea !important;
        border-color: rgba(255, 255, 255, 0.10) !important;
    }
    /* Hover + Touch-Active fuer beide Mess-Btns gleich. */
    .leaflet-bar a.geolyser-measure-end-action:hover,
    .leaflet-bar a.geolyser-measure-end-action:focus,
    .leaflet-bar a.geolyser-measure-maximize-action:hover,
    .leaflet-bar a.geolyser-measure-maximize-action:focus,
    a.geolyser-measure-end-action:hover,
    a.geolyser-measure-end-action:focus,
    a.geolyser-measure-maximize-action:hover,
    a.geolyser-measure-maximize-action:focus {
        background-color: var(--bg-card) !important;
        color: var(--c-primary-hi) !important;
        border-color: var(--c-primary-hi) !important;
        cursor: pointer;
    }
    [data-theme="dark"] .leaflet-bar a.geolyser-measure-end-action:hover,
    [data-theme="dark"] .leaflet-bar a.geolyser-measure-end-action:focus,
    [data-theme="dark"] .leaflet-bar a.geolyser-measure-maximize-action:hover,
    [data-theme="dark"] .leaflet-bar a.geolyser-measure-maximize-action:focus,
    [data-theme="dark"] a.geolyser-measure-end-action:hover,
    [data-theme="dark"] a.geolyser-measure-end-action:focus,
    [data-theme="dark"] a.geolyser-measure-maximize-action:hover,
    [data-theme="dark"] a.geolyser-measure-maximize-action:focus {
        background-color: #3b3f44 !important;
        color: var(--c-primary-hi) !important;
        border-color: var(--c-primary-hi) !important;
    }
    .leaflet-bar a.geolyser-measure-end-action:active,
    .leaflet-bar a.geolyser-measure-maximize-action:active,
    a.geolyser-measure-end-action:active,
    a.geolyser-measure-maximize-action:active {
        background-color: var(--c-cyan, #3BBDE8) !important;
        color: #fff !important;
        border-color: var(--c-cyan, #3BBDE8) !important;
    }

    /* Geoman pm-actions: Hover + Touch-Active (klick-Feedback). End-
     * of-file Position garantiert dass diese Regeln gewinnen. */
    .leaflet-pm-toolbar .button-container .leaflet-pm-actions-container
        .leaflet-pm-action:hover,
    .leaflet-pm-toolbar .button-container .leaflet-pm-actions-container
        .leaflet-pm-action:focus {
        background-color: var(--bg-card) !important;
        color: var(--c-primary-hi) !important;
        border-color: var(--c-primary-hi) !important;
        cursor: pointer !important;
        text-decoration: none !important;
    }
    [data-theme="dark"] .leaflet-pm-toolbar .button-container
        .leaflet-pm-actions-container .leaflet-pm-action:hover,
    [data-theme="dark"] .leaflet-pm-toolbar .button-container
        .leaflet-pm-actions-container .leaflet-pm-action:focus {
        background-color: #3b3f44 !important;
        color: var(--c-primary-hi) !important;
        border-color: var(--c-primary-hi) !important;
    }
    .leaflet-pm-toolbar .button-container .leaflet-pm-actions-container
        .leaflet-pm-action:active {
        background-color: var(--c-cyan, #3BBDE8) !important;
        color: #fff !important;
        border-color: var(--c-cyan, #3BBDE8) !important;
    }
}

/* =====================================================================
 * Mobile-TT-Fix — pm-actions auch im LANDSCAPE vertikal
 * ---------------------------------------------------------------------
 * Smartphone-Landscape hat Viewport-Width > 768px (z.B. iPhone 932px
 * horizontal), die 768px-Regeln greifen also nicht. Trotzdem ist die
 * Toolbar horizontal (Mobile-F-Fix), und pm-actions wurden default
 * horizontal angeordnet → Buttons zu schmal, Texte ueberlappen.
 * Selbe Vertikal-Stapel + 160x30 + Hover/Active wie im 768px-Block,
 * hier zusaetzlich fuer orientation:landscape + max-width:1024px.
 * ===================================================================== */
@media (orientation: landscape) and (max-width: 1024px) {
    /* Mobile-VV-Fix Im Landscape sitzt
 * die Toolbar oben — bei vertikalem Stapel mit top:50% +
 * translateY(-50%) (aus ) wandert der erste Btn
 * ("Beenden") oberhalb der Toolbar aus dem Viewport. Im Landscape
 * Actions UNTER den Btn anker statt zentriert. */
    .leaflet-pm-toolbar .button-container .leaflet-pm-actions-container {
        display: flex !important;
        flex-direction: column !important;
        align-items: stretch;
        gap: 4px;
        top: calc(100% + 4px) !important;
        left: 0 !important;
        right: auto !important;
        transform: none !important;
    }
    /* Mess-Tool-Actions-Container im Landscape ebenfalls UNTER dem
     * Mess-Btn anker (selber Grund). */
    .geolyser-measure-actions-container {
        top: calc(100% + 4px) !important;
        left: 0 !important;
        right: auto !important;
        transform: none !important;
    }
    .leaflet-pm-toolbar .button-container .leaflet-pm-actions-container
        .leaflet-pm-action {
        display: block !important;
        white-space: nowrap;
        padding: 0 12px !important;
        font-size: 0.86em !important;
        height: 30px !important;
        line-height: 30px !important;
        min-width: 160px;
        text-align: center;
        margin: 0 !important;
        box-sizing: border-box;
        border-radius: 3px !important;
        border-right: 1px solid var(--border) !important;
    }
    /* Inaktive pm-actions weiter ausblenden — Mobile-LL-Aequivalent
     * fuer Landscape (sonst zeigen alle Tools ihre Actions parallel). */
    .leaflet-pm-toolbar .button-container:not(.active) .leaflet-pm-actions-container {
        display: none !important;
    }
    /* Mess-Tool Actions-Container vertikal, OHNE !important auf display
     * — JS-Inline-style.display: none soll weiter wirken (Mobile-SS). */
    .geolyser-measure-actions-container {
        display: flex;
        flex-direction: column;
        align-items: stretch;
        gap: 4px;
    }
    .leaflet-bar a.geolyser-measure-end-action,
    .leaflet-bar a.geolyser-measure-maximize-action,
    .leaflet-touch .leaflet-bar a.geolyser-measure-end-action,
    .leaflet-touch .leaflet-bar a.geolyser-measure-maximize-action,
    a.geolyser-measure-end-action,
    a.geolyser-measure-maximize-action {
        display: block !important;
        width: 160px !important;
        min-width: 160px !important;
        height: 30px !important;
        line-height: 28px !important;
        padding: 0 12px !important;
        font-size: 0.86em !important;
        text-align: center !important;
        margin: 0 !important;
        box-sizing: border-box !important;
        border-radius: 3px !important;
        background-color: var(--bg-elevated) !important;
        color: var(--text) !important;
        border: 1px solid var(--border) !important;
    }
    [data-theme="dark"] .leaflet-bar a.geolyser-measure-end-action,
    [data-theme="dark"] .leaflet-bar a.geolyser-measure-maximize-action,
    [data-theme="dark"] a.geolyser-measure-end-action,
    [data-theme="dark"] a.geolyser-measure-maximize-action {
        background-color: #2c2f33 !important;
        color: #eaeaea !important;
        border-color: rgba(255, 255, 255, 0.10) !important;
    }

    /* =================================================================
 * Mobile-UU-Fix — Fullscreen-Modals im
 * Landscape mit Scrollbars wenn der Inhalt ueberlaeuft.
 * -----------------------------------------------------------------
 * Im Smartphone-Querformat ist die Hoehe knapp (z.B. 430px), viele
 * Modals (Mein Konto, Admin, DB-Vollansicht) ueberlaufen. Die
 * Mobile-I-Vollbild-Pattern + Body-Scroll-Regeln greifen nur im
 * 768px-Block — Landscape Phones haben aber haeufig 932x430 oder
 * aehnlich, also Width > 768. Hier dasselbe Pattern fuer Landscape.
 * ================================================================= */
    .modal-card {
        padding: 0 !important;
        overflow: hidden !important;
        max-width: 100vw !important;
        width: 100vw !important;
        max-height: 100dvh !important;
        height: 100dvh !important;
        margin: 0 !important;
        border-radius: 0 !important;
        display: flex !important;
        flex-direction: column !important;
    }
    .modal-card > .modal-header,
    .modal-card > h3.modal-title {
        margin: 0 !important;
        padding: 10px 14px !important;
        background: var(--bg-elevated) !important;
        border-bottom: 1px solid var(--border);
        flex-shrink: 0;
        position: relative;
        z-index: 3;
        width: 100%;
    }
    .modal-card > .modal-footer,
    .modal-card > .modal-actions {
        margin: auto 0 0 0 !important;
        padding: 8px 12px !important;
        background: var(--bg-elevated) !important;
        border-top: 1px solid var(--border);
        flex-shrink: 0;
        position: relative;
        z-index: 3;
        width: 100%;
    }
    .modal-card > .modal-body,
    .modal-card > .modal-form,
    .modal-card > [data-role="body"] {
        margin: 0 !important;
        padding: 10px 14px !important;
        flex: 1 1 auto !important;
        overflow-y: auto !important;
        overflow-x: hidden !important;
        -webkit-overflow-scrolling: touch;
        min-height: 0 !important;
    }
    /* Tuerkise Scrollbar im Landscape ebenfalls (Mobile-I-Aequivalent). */
    .modal-card,
    .modal-card * {
        /* scrollbar-color mit sichtbarem Track. */
        scrollbar-color: var(--c-cyan, #3BBDE8) rgba(0,0,0,0.10);
        scrollbar-width: thin;
    }
    .modal-card ::-webkit-scrollbar,
    .modal-card::-webkit-scrollbar {
        /* etwas breiter fuer bessere Touch-Greifbarkeit. */
        width: 12px;
        height: 12px;
    }
    .modal-card ::-webkit-scrollbar-thumb,
    .modal-card::-webkit-scrollbar-thumb {
        background: var(--c-cyan, #3BBDE8) !important;
        border-radius: 5px;
        min-height: 40px;
    }
    .modal-card ::-webkit-scrollbar-track,
    .modal-card::-webkit-scrollbar-track {
        /* sichtbarer Track. */
        background: rgba(0, 0, 0, 0.10);
        border-radius: 6px;
    }
    /* Profile-Modal innere Forms im Landscape (analog Mobile-AA) — die
     * .modal-form-Regel oben mit flex:1 1 auto wuerde sonst innere
     * timezone-/password-forms wieder auf ~12px quetschen. */
    #profile-modal .profile-modal-body > form.modal-form,
    #profile-modal .modal-body > form.modal-form {
        flex: 0 0 auto !important;
        overflow: visible !important;
        height: auto !important;
        min-height: 0 !important;
    }
}

/* ================================================================
 View-Switcher als vertikaler Selector-
 Stack zwischen Anleitung und Sprache. Im Closed-State zeigt der
 Stack nur das aktive Item — sieht aus wie ein normaler Topbar-
 Icon-Btn. Klick darauf klappt die anderen Views darunter aus
 (icon-only). Klick auf ein anderes wechselt die View, die wird
 sofort zum neuen Top-Item.
 Farben pro View: Karte indigo , Punktwolke rose (#e11d48),
 3D-Mesh blau . Aktive Item = voller Background, inaktive
 = neutraler Background mit farbigem Icon.
 ================================================================ */
.view-switcher {
    /* Layout-Spacer im Header — reserviert genau den Platz eines
       Stack-Items, damit die umliegenden Topbar-Buttons nicht
       umspringen. Das echte .view-stack wird per JS in document.body
       verschoben + per position:fixed darueber positioniert (Topbar
       hat eigenen Stacking-Context → Dropdown-Items wuerden sonst
       unter Sidebar/iframe-shell verschwinden). */
    width: 36px;
    height: 36px;
    flex: 0 0 36px;
    display: inline-block;
    position: relative;
}
.view-switcher[hidden] {
    display: none !important;
}
.view-stack {
    display: flex;
    flex-direction: column;
    /* gap analog zu .topbar-right { gap: 10px }
 damit der vertikale Abstand zwischen Items mit dem horizontalen
 Abstand zwischen den anderen Topbar-Buttons matched. */
    gap: 10px;
    /* Items haben Akzent-Farben; im closed-state sind alle nicht-
       aktiven items per Regel weiter unten hidden. Open-State wird
       von JS per .is-open-Klasse gesteuert. */
}
/* Wenn der Stack via JS in den body verschoben wird, bekommt er
   position:fixed + dynamische top/left (siehe map.js _positionStack).
   z-index 1700 = ueber Sidebar (1100), iframe-shell (1500),
   unter Modals (2000). */
.view-stack--floating {
    position: fixed;
    z-index: 1700;
}
/* (v2): Items brauchen einen SOLIDEN Hintergrund.
 Vorher rgba(0,0,0,0.04) bzw. rgba(255,255,255,0.06) — im Dark-Mode
 gegen den bunten Karten-Tile-Hintergrund praktisch unsichtbar
 (Items expandieren ueber die Karte raus aus dem Topbar-Bereich).
 Loesung: var(--bg-elevated) = Modal/Card-Farbe, undurchsichtig und
 konsistent mit anderen schwebenden UI-Elementen (Dropdowns, Toasts). */
.view-stack-item {
    /* JP-Fix : Box-Dimensionen mit min/max gegen jegliche
 Drift-Quellen festnageln (Flex-Stretch, browser-default button
 min-height, Touch-Target-Heuristiken auf Mobile). Pointcloud-Item
 wurde auf manchen Tablets mit 36x40 gerendert, jetzt strikt
 36x36. */
    width: 36px;
    height: 36px;
    min-width: 36px;
    max-width: 36px;
    min-height: 36px;
    max-height: 36px;
    border: 1px solid var(--border);
    /* border-radius an die uebrigen Topbar-
 Buttons angeglichen (vorher 6px, jetzt var(--radius) = 10px). */
    border-radius: var(--radius);
    background: var(--bg-elevated);
    color: var(--fg);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background .12s, color .12s, border-color .12s;
    /* Box-Shadow nur noch im Open-State, damit
 das aktive Item im Closed-State optisch nicht groesser/erhabener
 wirkt als die anderen Topbar-Icon-Btns. Open-State (Dropdown ist
 ausgeklappt) kriegt den Shadow zurueck (siehe `.is-open`-Regel). */
    padding: 0;
    /* JP-Fix : flex-basis als shorthand `flex: 0 0 36px` haengt
 in flex-column an der Main-Axis (Hoehe). Auf Mobile-Browsern, die
 Form-Controls eine User-Agent-min-height von 40px geben, blieb der
 Button trotz height:36px auf 40px stehen. flex-basis bleibt bei
 36px, aber min-height oben killt den UA-Override sauber. */
    flex: 0 0 36px;
    box-sizing: border-box;
    line-height: 0;
}
.view-stack.is-open .view-stack-item {
    box-shadow: 0 2px 6px rgba(0,0,0,0.18);
}
.view-stack-item[hidden] {
    display: none !important;
}
.view-stack-item svg {
    display: block;
    flex: 0 0 auto;
}
/* CSS-order: aktive Item immer ganz oben im Flex-Column-Stack. Andere
   bleiben in DOM-Reihenfolge. */
.view-stack-item.is-active {
    order: -1;
}
/* Closed-State: nur active item sichtbar. Open-State (per JS .is-open
   am .view-stack) zeigt alle nicht-hidden items. */
.view-stack:not(.is-open) .view-stack-item:not(.is-active) {
    display: none;
}
/* Inaktive Items: farbiges Icon, neutraler ghost-Hintergrund (oben). */
.view-stack-item--map:not(.is-active)        { color: #4f46e5; } /* indigo */
.view-stack-item--pointcloud:not(.is-active) { color: #e11d48; } /* rose */
.view-stack-item--mesh3d:not(.is-active)     { color: #2563eb; } /* blau */
/* Hover auf inaktivem Item: Akzent-Tint UEBER dem soliden
   bg-elevated. Wichtig: `background` ist eine Stack-Property — wenn
   wir nur `background: rgba(...)` setzen, ueberschreibt das den
   soliden bg-elevated und der Button wirkt transparent.
   Loesung: Multi-Layer-Background mit linear-gradient (das
   "Tint" als oberster Layer) UND var(--bg-elevated) als solidem
   unteren Layer. Browser kombiniert beide → solides Endergebnis
   mit Akzent-Farbschimmer. */
.view-stack-item--map:not(.is-active):hover {
    background:
        linear-gradient(rgba(79, 70, 229, 0.16), rgba(79, 70, 229, 0.16)),
        var(--bg-elevated);
    border-color: #4f46e5;
}
.view-stack-item--pointcloud:not(.is-active):hover {
    background:
        linear-gradient(rgba(225, 29, 72, 0.16), rgba(225, 29, 72, 0.16)),
        var(--bg-elevated);
    border-color: #e11d48;
}
.view-stack-item--mesh3d:not(.is-active):hover {
    background:
        linear-gradient(rgba(37, 99, 235, 0.16), rgba(37, 99, 235, 0.16)),
        var(--bg-elevated);
    border-color: #2563eb;
}
/* Dark-Mode: gleiches Prinzip, etwas hoehere Tint-Alpha damit der
   Farbschimmer gegen den dunkleren bg-elevated sichtbar wird. */
[data-theme="dark"] .view-stack-item--map:not(.is-active):hover {
    background:
        linear-gradient(rgba(79, 70, 229, 0.28), rgba(79, 70, 229, 0.28)),
        var(--bg-elevated);
}
[data-theme="dark"] .view-stack-item--pointcloud:not(.is-active):hover {
    background:
        linear-gradient(rgba(225, 29, 72, 0.28), rgba(225, 29, 72, 0.28)),
        var(--bg-elevated);
}
[data-theme="dark"] .view-stack-item--mesh3d:not(.is-active):hover {
    background:
        linear-gradient(rgba(37, 99, 235, 0.28), rgba(37, 99, 235, 0.28)),
        var(--bg-elevated);
}
/* Aktive Items: dezenter Akzent-Tint UEBER var(--bg-elevated)
   (gestapelt analog zum Hover), Border + Icon in der vollen Akzent-
   Farbe — eingefaerbt, nicht vollfarbig. */
.view-stack-item.is-active.view-stack-item--map {
    background:
        linear-gradient(rgba(79, 70, 229, 0.20), rgba(79, 70, 229, 0.20)),
        var(--bg-elevated);
    color: #4f46e5;
    border-color: rgba(79, 70, 229, 0.55);
}
.view-stack-item.is-active.view-stack-item--pointcloud {
    background:
        linear-gradient(rgba(225, 29, 72, 0.20), rgba(225, 29, 72, 0.20)),
        var(--bg-elevated);
    color: #e11d48;
    border-color: rgba(225, 29, 72, 0.55);
}
.view-stack-item.is-active.view-stack-item--mesh3d {
    background:
        linear-gradient(rgba(37, 99, 235, 0.20), rgba(37, 99, 235, 0.20)),
        var(--bg-elevated);
    color: #2563eb;
    border-color: rgba(37, 99, 235, 0.55);
}
/* Dark-Mode: gleiches Konzept, aber der Tint wird etwas heller, weil
   gegen dunklen Bg sonst zu unscheinbar; Text-Color wird auf einen
   leichteren Ton verschoben fuer Lesbarkeit. */
[data-theme="dark"] .view-stack-item.is-active.view-stack-item--map {
    background:
        linear-gradient(rgba(79, 70, 229, 0.32), rgba(79, 70, 229, 0.32)),
        var(--bg-elevated);
    color: #a5a4f6;
    border-color: rgba(79, 70, 229, 0.70);
}
[data-theme="dark"] .view-stack-item.is-active.view-stack-item--pointcloud {
    background:
        linear-gradient(rgba(225, 29, 72, 0.32), rgba(225, 29, 72, 0.32)),
        var(--bg-elevated);
    color: #f87a93;
    border-color: rgba(225, 29, 72, 0.70);
}
[data-theme="dark"] .view-stack-item.is-active.view-stack-item--mesh3d {
    background:
        linear-gradient(rgba(37, 99, 235, 0.32), rgba(37, 99, 235, 0.32)),
        var(--bg-elevated);
    color: #7aa6f4;
    border-color: rgba(37, 99, 235, 0.70);
}
/* Aktive Hover: minimaler Helligkeitsboost als Klick-Feedback (Stack
   oeffnet/schliesst beim Klick aufs aktive Item). */
.view-stack-item.is-active:hover {
    filter: brightness(1.06);
}

/* Performance-Optimierung fuer iframe-Modus
 (besonders 3D-Mesh / Cesium, das mit 60 FPS rendert).
 - Topbar-backdrop-filter aus: Browser muss sonst bei jedem Cesium-
 Frame den Blur-Stack hinter der Topbar neu berechnen (= teuerer
 GPU-Compositing-Hit pro Frame). Stattdessen solid background.
 - Map-Shell wird ge-display:none-d: Leaflet-Tiles tickern dann
 nicht im Hintergrund weiter, Browser muss die DOM-Subtree nicht
 mehr layouten/painten.
 - Iframe-Shell bekommt contain:strict + will-change:transform:
 Hint an den Browser dass es ein eigener Rendering-Layer ist;
 GPU bekommt eine eigene Compositing-Layer fuer den iframe. */
body.external-view-active .topbar {
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    background: var(--bg-elevated) !important;
}
body.external-view-active .map-shell {
    display: none !important;
}
body.external-view-active .external-view-shell {
    contain: strict;
    will-change: transform;
}
body.external-view-active .external-view-shell > iframe {
    will-change: transform;
}

/* External-View-Shell: ueber main + alle In-App-UI, unter Modals.
   z-index-Landschaft: Leaflet-Tiles 200..700, Sidebar 1100, Features-
   Panel 1100, Modals 2000+. 1500 sitzt drueber Sidebar+Features-Panel
   (sonst ueberdeckt die Sidebar das iframe rechts oder links), drunter
   Modals/Confirms — Admin-Modal etc. kann weiter aufgemacht werden
   ohne das iframe schliessen zu muessen. */
.external-view-shell {
    position: fixed;
    top: var(--topbar-h, 56px);
    left: 0;
    right: 0;
    bottom: 0;
    background: var(--bg-app);
    z-index: 1500;
    display: flex;
    flex-direction: column;
}
/* das HTML-hidden-Attribut hat per UA-
 Default display:none, wird aber von .external-view-shell { display:flex }
 ueberschrieben — Folge: Shell liegt permanent ueber map + faängt
 alle Klicks ab. Explizit ueberschreiben.
 Das gleiche gilt fuer das interne Loading-Overlay. */
.external-view-shell[hidden],
.external-view-loading[hidden] {
    display: none !important;
}
.external-view-shell > iframe {
    flex: 1 1 auto;
    width: 100%;
    height: 100%;
    min-height: 0;             /* sonst kann flex-child auf 0 collabieren */
    border: 0;
    display: block;
    background: transparent;   /* iframe-Content soll nicht ueberdeckt werden */
}
.external-view-loading {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    background: var(--bg-app);
    color: var(--text-primary);
    font-size: 0.95em;
}
.external-view-loading-spinner {
    width: 18px; height: 18px;
    border: 2px solid var(--border);
    border-top-color: var(--c-primary);
    border-radius: 50%;
    animation: external-view-spin 0.8s linear infinite;
}
@keyframes external-view-spin {
    to { transform: rotate(360deg); }
}

/* Footer-Leiste in iframe-shell mit
 Geolyser-Copyright, Impressum, Datenschutz. Liegt UNTER dem
 iframe (flex-row in shell), klein, mit Akzent-Background damit
 sie sich vom iframe-Content abgrenzt. */
.external-view-footer {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 6px 12px;
    background: var(--bg-panel);
    border-top: 1px solid var(--border);
    color: var(--muted-hi);
    font-size: 0.78em;
    white-space: nowrap;
    overflow-x: auto;
}
.external-view-footer a {
    color: var(--muted-hi);
    text-decoration: none;
    transition: color .12s;
}
.external-view-footer a:hover {
    color: var(--c-primary);
    text-decoration: underline;
}
.external-view-footer .sep {
    opacity: 0.5;
}
@media (max-width: 480px) {
    .external-view-footer { font-size: 0.72em; gap: 6px; padding: 5px 8px; }
}

/* Hover-Outline fuer Punkt-Marker.
 * Vector-Layer (Polygon/Linie/Kreis) bekommen ihren Hover-Outline ueber
 * setStyle in map.js, Marker (Points) brauchen einen CSS-Drop-Shadow weil
 * setStyle dort nicht definiert ist. --hover-color wird vom Mouseover-
 * Handler gesetzt (= Layer-Farbe-Hex). */
.geolyser-pin.is-hover {
    filter:
        drop-shadow(0 0 4px var(--hover-color, #fff))
        drop-shadow(0 0 8px var(--hover-color, #fff));
    z-index: 1000 !important;
}
