* { box-sizing: border-box; }

:root {
    --bg: #080a0c;
    --bg-grid: #0c0e11;
    --panel: #12161a;
    --panel-2: #171c21;
    --border: #262c32;
    --steel: #d7dee4;
    --steel-dim: #8b96a1;
    /* Chrome-Akzent (Buttons, Rahmen, Logo-Glow) - stahlblau statt rot.
       Echte Gefahr/Alarm bleibt bewusst separat rot (--danger), siehe
       .dot-alert / .intel-toast .system / .tag.nullsec. */
    --accent: #4f9fd8;
    --accent-dim: #285a7a;
    --accent-glow: rgba(79, 159, 216, 0.45);
    --danger: #e6212b;
    --danger-dim: #8f171f;
    --danger-glow: rgba(230, 33, 43, 0.45);
    --gold: #f5c518;
    --gold-glow: rgba(245, 197, 24, 0.35);
    --highsec: #4ade80;
    --lowsec: #fbbf24;
    --nullsec: #f87171;
}

body {
    background:
        radial-gradient(circle at 50% -10%, #101820 0%, var(--bg) 45%),
        var(--bg);
    color: var(--steel);
    font-family: "Inter", "Segoe UI", Arial, sans-serif;
    margin: 0;
    padding: 0;
    min-height: 100vh;
}

h1, h2, h3, .btn, .tag, .stat-label, .tab, .brand-text {
    font-family: "Oswald", "Segoe UI", Arial, sans-serif;
    letter-spacing: 0.03em;
}

.site-header {
    background: linear-gradient(180deg, #0e0e11 0%, #0a0a0c 100%);
    border-bottom: 1px solid var(--border);
    position: sticky;
    top: 0;
    z-index: 10;
    box-shadow: 0 1px 0 rgba(79, 159, 216, 0.1);
}

.topbar {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: 18px;
    padding: 12px 28px;
}
.topbar-side { display: flex; align-items: center; gap: 22px; }
.topbar-left { justify-content: flex-start; }
.topbar-right { justify-content: flex-end; }
.topbar-center { display: flex; justify-content: center; }

.brand {
    display: flex;
    align-items: center;
    gap: 10px;
    text-decoration: none;
}
.fc-mark { width: 26px; height: 31px; display: block; object-fit: contain; }
.brand-text-wrap { display: flex; flex-direction: column; align-items: center; }
.brand-welcome { font-size: 15px; color: var(--steel-dim); text-transform: none; font-weight: 500; letter-spacing: 0; text-align: center; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; }
.brand-portrait { width: 32px; height: 32px; border-radius: 4px; display: block; }
.brand-text {
    font-size: 17px;
    font-weight: 700;
    text-transform: uppercase;
    color: var(--steel);
    line-height: 1.1;
}
.brand-text .accent { color: var(--accent); }

.stat { display: flex; flex-direction: column; line-height: 1.3; }
.stat-label {
    font-size: 10px;
    text-transform: uppercase;
    color: var(--steel-dim);
    letter-spacing: 0.08em;
}
.stat-value { font-size: 14px; color: var(--steel); font-weight: 600; display: flex; align-items: center; }
.stat-sub { font-size: 11px; color: var(--steel-dim); }

.dot {
    display: inline-block;
    width: 7px; height: 7px;
    border-radius: 50%;
    margin-right: 5px;
}
.dot-online { background: var(--highsec); box-shadow: 0 0 5px var(--highsec); }
.dot-idle { background: var(--steel-dim); }
.dot-alert {
    background: var(--danger);
    box-shadow: 0 0 6px var(--danger-glow);
    animation: pulse-alert 1.4s infinite;
}
@keyframes pulse-alert {
    0%, 100% { box-shadow: 0 0 4px var(--danger-glow); }
    50% { box-shadow: 0 0 10px var(--danger-glow); }
}
.intel-stat { cursor: default; position: relative; }
/* Nutzerwunsch (Mike-Perf-Fall, 2026-07-16): An/Aus direkt am Intel-Indikator
   im Header - AUS unterbindet client-seitig das Polling von /api/intel (und
   damit serverseitig das teure Chatlog-Neueinlesen, siehe intel_monitor.
   poll_intel/chatlog_reader.read_new_lines), AN/rot-gruen macht sofort
   sichtbar, ob es gerade laeuft, ohne extra Text lesen zu muessen. */
.intel-toggle-btn {
    display: inline-block;
    margin-left: 4px;
    padding: 0 6px;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.04em;
    line-height: 1.6;
    border-radius: 999px;
    border: 1px solid transparent;
    cursor: pointer;
    text-transform: uppercase;
    vertical-align: middle;
}
.intel-toggle-btn.on { background: rgba(74, 222, 128, 0.15); color: var(--highsec); border-color: rgba(74, 222, 128, 0.4); }
.intel-toggle-btn.off { background: rgba(248, 113, 113, 0.15); color: var(--nullsec); border-color: rgba(248, 113, 113, 0.4); }

/* Nutzerwunsch: Popup soll INNERHALB der mittleren Dashboard-Karte (.hero,
   direkt ueber dem Sigil, in den grauen Bereich der Karte) erscheinen statt
   schwebend ueber dem Header - intel.js haengt es dafuer per JS direkt in
   .card.hero ein (Modifier-Klasse .intel-toast-in-hero) statt in
   document.body. Nur auf Seiten OHNE diese Karte (Karte/Route, Settings,
   ...) faellt es auf die alte fixed+zentrierte Position unterhalb von
   Header+Tableiste zurueck. */
.intel-toast {
    position: fixed;
    top: 60px;
    left: 50%;
    transform: translateX(-50%);
    background: linear-gradient(180deg, var(--panel-2) 0%, var(--panel) 100%);
    border: 1px solid var(--danger-dim);
    border-radius: 8px;
    padding: 10px 16px;
    font-size: 13px;
    color: var(--steel);
    box-shadow: 0 8px 24px -8px rgba(0,0,0,0.7), 0 0 0 1px rgba(230,33,43,0.1);
    z-index: 100;
    max-width: 320px;
    animation: toast-in .2s ease-out;
}
.intel-toast-in-hero {
    position: absolute;
    top: 8px;
    max-width: 232px;
    z-index: 5;
}
.intel-toast .system { color: var(--danger); font-weight: 700; }
@keyframes toast-in {
    from { opacity: 0; transform: translateY(-6px); }
    to { opacity: 1; transform: translateY(0); }
}

.feed-item {
    padding: 6px 0;
    border-bottom: 1px solid #1b1b1f;
    font-size: 13px;
    display: flex;
    gap: 8px;
    align-items: baseline;
    flex-wrap: wrap;
}
.feed-item:last-child { border-bottom: none; }
.feed-time { color: var(--steel-dim); font-size: 11px; flex-shrink: 0; }
.feed-sender { color: #7dd3fc; font-weight: 700; flex-shrink: 0; }
.feed-system { color: #fb923c; font-weight: 700; flex-shrink: 0; }
/* Der Meldungstext (letztes Element jeder Feed-Zeile) hatte bisher kein
   flex-grow - die Zeile blieb dadurch so breit wie ihr eigener Inhalt und
   liess ein Drittel der Karte rechts leer (Nutzer-Bugreport), statt die
   volle Kartenbreite zu nutzen. */
.feed-item > span:last-child { flex: 1 1 auto; min-width: 0; }

/* Scrollbare Feeds statt wachsender Karten - neuestes steht am Ende und
   wird per JS/Inline-Script automatisch ins Bild gescrollt. Feste
   max-height ist hier bewusst so gewaehlt, dass sie zur Kartenhoehe der
   Nachbarspalten passt (siehe .dash-columns .card min-height) - so bleibt
   die Box "bis zum Ende des Kastens" gross, waechst aber NICHT unbegrenzt
   mit (das war ein frueherer Fehlversuch mit flex/min-height:0, der die
   Karte bei vielen Meldungen einfach immer weiter aufgeblaeht hat, statt
   intern zu scrollen). */
.scroll-feed { max-height: 260px; overflow-y: auto; }
.scroll-feed-tall { max-height: 314px; }
/* Nutzerwunsch: Flotten-MOTD um ca. 1/4 kuerzen, der Platz geht an die neue
   Rollen-Zaehlung darunter (.role-count-grid) - "MOTD ist nie so lang, dass
   man alles braucht". */
.scroll-feed-short { max-height: 195px; }

.hint { color: var(--steel-dim); font-size: 11px; text-transform: none; font-weight: 400; letter-spacing: 0; margin-left: 6px; }
#intel-active-channel { font-size: 14px; }

.motd-row { padding: 3px 0; font-size: 12px; line-height: 1.4; }
.motd-label { color: var(--danger); font-weight: 700; text-transform: uppercase; margin-right: 5px; }
.motd-value { color: #fb923c; }

/* Nutzerwunsch: Rollen-Zaehlung (Dictor/Bubbler/DPS/Logi/Links/EWAR/Special
   Support) statt des unteren MOTD-Viertels - durchgehend 2 Spalten, keine
   Zeile nimmt die volle Breite (auch "Special Support" nicht). */
.role-count-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 4px 12px;
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px solid var(--border);
}
.role-count-item { display: flex; justify-content: space-between; font-size: 12px; }
.role-count-label { color: var(--steel-dim); }
.role-count-value { font-weight: 700; }
/* Nutzerwunsch (Kill-Check-Abgleich): stirbt gerade wer, zeigt die
   betroffene Rolle ein rotes "-N" vor der bereits korrigierten Zahl. */
.role-count-dead { color: var(--danger); font-weight: 700; }

.aar-report-list { display: flex; flex-wrap: wrap; gap: 8px; }
.aar-report-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;
    background: var(--panel-2);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 6px 10px;
    cursor: pointer;
}
.aar-report-chip:hover { border-color: var(--accent-dim); }
.aar-report-chip input[type="checkbox"] { margin: 0; }

.tag-intel, .tag-jb {
    color: var(--gold);
    border: 1px solid var(--gold);
    background: rgba(245, 197, 24, 0.1);
    font-size: 10px;
    font-weight: 700;
    padding: 1px 6px;
    border-radius: 4px;
    letter-spacing: 0.04em;
}

.comp-role-header {
    margin: 14px 0 6px;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--gold);
    border-bottom: 1px solid var(--border);
    padding-bottom: 4px;
}
.comp-role-header:first-child { margin-top: 0; }

/* Mehrspaltig (Flottenzusammensetzung-Karte ist volle Seitenbreite, nicht
   Teil von .dash-columns) - so viele Spalten wie reinpassen (Nutzerwunsch:
   "je mehr in eine Zeile passen desto besser"), aber breit genug (280px
   statt frueher 230px), dass Name+Schiff darin normalerweise nicht
   umbrechen muessen. Kein Ellipsis mehr - im seltenen Fall eines sehr
   langen Namens wird umgebrochen statt abgeschnitten, "man soll aber
   alles lesen koennen" bleibt so in jedem Fall erfuellt. */
.comp-role-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 4px 16px;
}
.comp-row { display: flex; align-items: center; gap: 8px; padding: 3px 2px; font-size: 13px; min-width: 0; flex-wrap: wrap; }
.comp-row .feed-sender, .comp-row .comp-ship {
    min-width: 0;
    overflow-wrap: break-word;
}
.comp-row .feed-sender { flex: 1 1 auto; }
.comp-row .comp-ship { flex: 1 1 auto; color: var(--steel-dim); }
.comp-row .comp-system {
    flex: 0 0 auto;
    color: var(--steel-dim);
    font-size: 11px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 90px;
}
.comp-row .comp-system.comp-location-mismatch { color: var(--danger); font-weight: 600; }
.comp-mismatch { background: rgba(239, 68, 68, 0.14); border-radius: 4px; }
/* Nutzerwunsch: zKillboard-Abgleich (siehe kill_check.py) - noch in der
   Kapsel (kein neues Schiff bestiegen) -> Name+Schiff rot durchgestrichen;
   wieder in einem Schiff, aber kuerzlich gestorben -> nur rot umrandet. */
.comp-dead { color: #f87171 !important; text-decoration: line-through; }
.comp-reshipped { outline: 2px solid #f87171; outline-offset: -1px; border-radius: 4px; }
/* Scout/Cyno-Ausnahme-Checkbox (siehe fleet_composition.check_system_
   deviations) - bewusst klein/unauffaellig, nur fuer FCs relevant, die
   das mal setzen muessen, nicht Teil der normalen Lesefluss-Info. */
.comp-scout-toggle { margin-left: auto; flex-shrink: 0; }
.comp-scout-toggle label {
    display: flex;
    align-items: center;
    gap: 3px;
    font-size: 11px;
    color: var(--steel-dim);
    cursor: pointer;
}

/* Einspaltige Liste statt Mehrspalten-Grid (siehe .comp-role-grid) - Fit-
   Namen sind oft lang (Allianz-Praefix + Schiff + Tank-Variante), in
   schmalen Grid-Spalten wurden sie bisher hart abgeschnitten ("SYN ...").
   Hier bekommt der Name die volle Kartenbreite und darf umbrechen. */
.esi-fit-list { display: flex; flex-direction: column; gap: 4px; max-height: 480px; overflow-y: auto; }
.esi-fit-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 8px;
    border-radius: 6px;
    font-size: 13px;
}
.esi-fit-row:nth-child(odd) { background: rgba(255, 255, 255, 0.02); }
.esi-fit-row .esi-fit-ship { flex: 0 0 110px; color: var(--steel-dim); font-size: 12px; }
.esi-fit-row .esi-fit-name { flex: 1 1 auto; min-width: 0; color: var(--steel); white-space: normal; word-break: break-word; }
.esi-fit-row .esi-fit-role {
    background: var(--bg);
    border: 1px solid var(--border);
    color: var(--steel);
    border-radius: 6px;
    padding: 3px 8px;
    font-family: inherit;
    font-size: 12px;
    flex-shrink: 0;
}
.tag-mismatch {
    color: #fff;
    background: var(--danger);
    font-size: 10px;
    font-weight: 700;
    padding: 1px 6px;
    border-radius: 4px;
    letter-spacing: 0.04em;
    margin-left: auto;
}

.logout-link {
    color: var(--steel-dim);
    text-decoration: none;
    font-size: 12px;
    text-transform: uppercase;
    border-left: 1px solid var(--border);
    padding-left: 18px;
}
.logout-link:hover { color: var(--accent); }

.tabbar {
    display: flex;
    gap: 8px;
    padding: 0 28px 12px;
}
.tab {
    color: var(--steel-dim);
    text-decoration: none;
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    padding: 7px 16px;
    border-radius: 6px;
    border: 1px solid transparent;
    transition: color .15s, border-color .15s, background .15s;
}
.tab:hover { color: var(--steel); border-color: var(--border); }
.tab.active {
    color: var(--gold);
    background: var(--panel-2);
    border-color: var(--gold);
    box-shadow: 0 0 0 1px var(--gold-glow) inset;
}

/* Unterreiter innerhalb "Karte / Route" (Gate-Route vs. Capital-Route) -
   eigene, dezentere Klasse statt .tab/.tabbar wiederzuverwenden, damit es
   nicht wie ein zweiter Satz Haupt-Navigation aussieht. */
.subtab-bar { display: flex; gap: 8px; margin-bottom: 20px; }
.subtab {
    color: var(--steel-dim);
    text-decoration: none;
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    padding: 6px 14px;
    border-radius: 6px;
    border: 1px solid var(--border);
    transition: color .15s, border-color .15s, background .15s;
}
.subtab:hover { color: var(--steel); }
.subtab.active { color: var(--accent); border-color: var(--accent-dim); background: var(--panel-2); }
/* Nutzerwunsch: kompakter [Intel]/[Karte]-Umschalter im Kopf des Dashboard-
   Intel-Feed-Kastens - gleicher .subtab-Look wie die grossen Subtab-Leisten,
   nur ohne deren Standardabstand/Cursor als <a>, hier <button>. */
.dash-feed-switch { display: flex; gap: 6px; flex-shrink: 0; }
.dash-feed-switch .subtab { padding: 3px 10px; font-size: 11px; cursor: pointer; background: none; }

main {
    /* Passt sich der Fensterbreite an (fluessig), deckelt aber bei sehr
       breiten Fenstern auf 1760px, damit Zeilen nicht endlos lang werden. */
    max-width: min(1760px, 96vw);
    margin: 36px auto 80px;
    padding: 0 24px;
}

.dash-columns {
    display: grid;
    grid-template-columns: 1fr 280px 1fr;
    gap: 20px;
    align-items: stretch;
    margin-bottom: 20px;
}
/* min-height noetig, weil ein Grid-Row sich sonst auf die kuerzeste Karte
   zusammenzieht (Standort-Platzhaltertext ist kurz) - das .card-flex-Kind
   (Intel Feed) haette dann nur einen winzigen Feed-Bereich statt echt "bis
   zum Ende des Kastens" zu gehen. Mit fester Mindesthoehe bleibt die Reihe
   verlaesslich gross, waechst aber trotzdem mit, sobald eine Karte (z.B.
   die echte Standort-Karte nach Login) natuerlich hoeher ist. */
.dash-columns .card { margin-bottom: 0; height: 100%; min-height: 420px; }
.dash-columns-even { grid-template-columns: 1fr 1fr 1fr; }
@media (max-width: 900px) {
    .dash-columns { grid-template-columns: 1fr; }
}

/* Schmale Vorschau-Leiste der uebernommenen Route (siehe active_route.py) -
   bewusst niedrig/einzeilig statt einer vollen Karte, nur Systemname +
   kompakter Hinweis (SOV/Jump Bridge/Wurmloch-Ein-/Aussprung). */
.route-preview-bar { padding: 10px 16px; margin-bottom: 20px; display: flex; align-items: center; gap: 12px; }
.route-preview-scroll {
    display: flex;
    align-items: center;
    gap: 8px;
    overflow-x: auto;
    white-space: nowrap;
    padding-bottom: 10px;
    margin-bottom: -10px;
    flex: 1 1 auto;
    min-width: 0;
    scrollbar-width: thin;
}
/* Duenne Scrollbar statt der fetten Standard-Leiste, die sonst ueber die
   einzeilige Chip-Reihe ragte und Text verdeckte. */
.route-preview-scroll::-webkit-scrollbar { height: 6px; }
.route-preview-scroll::-webkit-scrollbar-track { background: transparent; }
.route-preview-scroll::-webkit-scrollbar-thumb { background: var(--border); border-radius: 999px; }
.route-clear-btn { flex-shrink: 0; font-size: 11px; padding: 5px 12px; }
.route-chip {
    flex-shrink: 0;
    font-size: 12px;
    padding: 4px 12px;
    border-radius: 999px;
    border: 1px solid var(--border);
    background: var(--panel-2);
    color: var(--steel);
}
.route-chip.highsec { border-color: rgba(74, 222, 128, 0.3); }
.route-chip.lowsec  { border-color: rgba(251, 191, 36, 0.3); }
.route-chip.nullsec { border-color: rgba(248, 113, 113, 0.3); }
.route-chip-note { color: var(--gold); font-weight: 600; }
/* NPC-Station (Haeuschen) und Kills der letzten Stunde direkt im kompakten
   Routen-Chip - gleiche Bedeutung wie in der grossen Routentabelle
   (map.html: .route-step .station-icon/.kill-count), nur kleiner, damit sie
   in die schmale Pille passen. */
.route-chip-station { font-size: 11px; margin-left: 4px; }
.route-chip-kills {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    margin-left: 4px;
    color: var(--gold);
    font-size: 11px;
    font-weight: 700;
}
.route-chip-kills::before {
    content: "";
    display: inline-block;
    width: 0.6em;
    height: 1.2em;
    background-image: url("../img/tc-icon.png");
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
    flex-shrink: 0;
}

.hero {
    position: relative;
    overflow: hidden;
    text-align: center;
    padding: 46px 24px 38px;
    display: flex;
    flex-direction: column;
    justify-content: center;
}
.hero::before {
    content: "";
    position: absolute;
    inset: 0;
    background:
        repeating-radial-gradient(circle at 50% 30%, transparent 0, transparent 70px, rgba(79,159,216,0.06) 71px, transparent 72px);
    pointer-events: none;
}
.hero .hero-mark { display: flex; justify-content: center; margin: 0 -26px 14px; }
.hero .hero-mark .fc-mark {
    width: 100%;
    height: auto;
    max-width: none;
    object-fit: contain;
    filter: drop-shadow(0 0 18px var(--accent-glow));
}
.hero h2 { margin: 0 0 6px; font-size: 26px; text-transform: uppercase; color: var(--steel); }
.hero p.sub { color: var(--steel-dim); margin: 0; font-size: 14px; }
/* After-Action-Report Start/Stop (siehe aar.py) - direkt unter dem Logo,
   Logo selbst bleibt unveraendert (Nutzerwunsch: "ohne dass sich das Logo
   veraendert"). Position ergibt sich rein aus der Dokumentreihenfolge
   (direkt nach .hero-mark, .hero ist schon text-align:center), keine
   absolute Positionierung noetig. */
.aar-toggle { position: relative; z-index: 1; }
.aar-toggle .btn { min-width: 160px; }

/* Nutzerwunsch: EVE-Zeit (immer UTC) + lokale Zeit direkt unter dem
   Flotte-Start-Bereich, damit man beim Formup nicht extra umrechnen muss. */
.hero-clock {
    position: relative;
    z-index: 1;
    margin-top: 14px;
    display: grid;
    grid-template-columns: auto auto;
    column-gap: 6px;
    row-gap: 2px;
    justify-content: center;
    font-size: 12px;
    color: var(--steel-dim);
}
.hero-clock-label { text-align: right; }
.hero-clock-value { text-align: left; color: var(--steel); font-weight: 600; }

/* Kill-Log im AAR-Report (siehe aar_report.html) - feste Spaltenbreiten
   statt loser flex-wrap-Reihen (Nutzer-Feedback: "soll alles immer buendig
   dargestellt werden"), damit Zeit/System/Ziel/ISK/Angreifer untereinander
   ausgerichtet bleiben, egal wie lang der jeweilige Inhalt ist. */
.kill-log { display: flex; flex-direction: column; max-height: 480px; overflow-y: auto; }
.kill-log-row {
    display: grid;
    grid-template-columns: 70px 90px minmax(120px, 1fr) 100px minmax(160px, 2fr);
    gap: 10px;
    align-items: center;
    padding: 5px 2px;
    border-bottom: 1px solid #1b1b1f;
    font-size: 13px;
}
.kill-log-row:last-child { border-bottom: none; }
.kill-log-row.kill-log-header {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--steel-dim);
    border-bottom: 1px solid var(--border);
    padding-bottom: 6px;
}
.kill-log-row span { min-width: 0; overflow-wrap: break-word; }

/* Name+Zahl-Zeilen im AAR-Report (Top Schaden/Kills/Final Blows, Systeme,
   System-Abweichungen) - Grid statt flex, damit die Zahlen untereinander
   buendig stehen statt an unterschiedlich langen Namen zu "kleben"
   (Nutzer-Feedback: "die Zahlen untereinander buendig"). */
.stat-row { display: grid; grid-template-columns: 1fr auto; gap: 10px; align-items: center; padding: 3px 2px; }
.stat-row.stat-row-3col { grid-template-columns: 1fr auto auto; }
.stat-row .stat-value { text-align: right; font-variant-numeric: tabular-nums; min-width: 70px; }

.card {
    background: linear-gradient(180deg, var(--panel-2) 0%, var(--panel) 100%);
    border: 1px solid var(--border);
    border-top: 2px solid var(--accent-dim);
    border-radius: 10px;
    padding: 22px 26px;
    margin-bottom: 20px;
    box-shadow: 0 12px 24px -16px rgba(0,0,0,0.6);
}
/* "Route ingame uebernehmen"-Knopf (siehe active_route.send_route_to_game)
   - immer unten rechts in der Standort-Karte (Nutzerwunsch), unabhaengig
   von der Standort-Karten-Groesse darunter. */
.location-card { position: relative; }
.route-to-game-btn { position: absolute; bottom: 14px; right: 14px; margin: 0; }
.route-to-game-status {
    position: absolute;
    bottom: 50px;
    right: 14px;
    margin: 0;
    font-size: 12px;
    max-width: 240px;
    text-align: right;
}
/* "Alternative Route"-Knopf (Nutzerwunsch) - immer unten LINKS in der
   Standort-Karte, spiegelbildlich zu "Route ingame uebernehmen" rechts. */
.alt-route-btn { position: absolute; bottom: 14px; left: 14px; margin: 0; }
.alt-route-status {
    position: absolute;
    bottom: 50px;
    left: 14px;
    margin: 0;
    font-size: 12px;
    max-width: 240px;
}
.card h2, .card h3 {
    margin-top: 0;
    text-transform: uppercase;
    font-size: 15px;
    color: var(--steel);
    display: flex;
    align-items: center;
    gap: 8px;
}
.card h2::before, .card h3::before {
    content: "";
    width: 6px; height: 6px;
    background: var(--accent);
    border-radius: 50%;
    box-shadow: 0 0 6px var(--accent-glow);
    display: inline-block;
}
.card p, .card li { color: #c3c6cc; font-size: 14px; line-height: 1.6; }
.card p a { color: var(--accent); text-decoration: underline; }
.card p a:hover { color: var(--gold); }

.btn {
    display: inline-block;
    background: linear-gradient(180deg, #5aacdf 0%, #2f6f95 100%);
    color: #fff;
    border: none;
    border-radius: 6px;
    padding: 10px 20px;
    cursor: pointer;
    text-decoration: none;
    font-size: 13px;
    font-weight: 600;
    text-transform: uppercase;
    box-shadow: 0 4px 14px -4px var(--accent-glow);
    transition: transform .12s, box-shadow .12s;
}
.btn:hover { transform: translateY(-1px); box-shadow: 0 6px 18px -4px var(--accent-glow); }
.btn.secondary {
    background: var(--panel-2);
    border: 1px solid var(--border);
    color: var(--steel);
    box-shadow: none;
}
.btn.secondary:hover { border-color: var(--steel-dim); }
.btn.secondary.active-filter { border-color: var(--gold); color: var(--gold); }

.tag {
    display: inline-block;
    padding: 3px 12px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    border: 1px solid transparent;
}
.tag.highsec { background: rgba(74, 222, 128, 0.1); color: var(--highsec); border-color: rgba(74, 222, 128, 0.3); }
.tag.lowsec  { background: rgba(251, 191, 36, 0.1); color: var(--lowsec); border-color: rgba(251, 191, 36, 0.3); }
.tag.nullsec { background: rgba(248, 113, 113, 0.1); color: var(--nullsec); border-color: rgba(248, 113, 113, 0.3); }
.tag.unknown { background: rgba(139, 142, 150, 0.12); color: var(--steel-dim); border-color: var(--border); }

.route-step {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 4px;
    border-bottom: 1px solid #1b1b1f;
    font-size: 13px;
}
.route-step:last-child { border-bottom: none; }
/* War 220px - bei den meisten Systemnamen (kurz) blieb da eine grosse
   Luecke vor der Region-Spalte. Deutlich schmaler, reicht auch fuer
   laengere Namen + Nummerierung ("12. Otanuomi"). */
.route-step .name { min-width: 140px; color: var(--steel); }
/* Nutzerwunsch (2026-07-19): Region/Kills/SOV/Sicherheit sollen "genau
   uebereinander" stehen, egal ob eine Zeile eine Gatecamp-/Trig-Warnung
   zeigt oder nicht - vorher wurden diese Tags nur bei Bedarf gerendert und
   verschoben dadurch alles Nachfolgende nach rechts (Referenz-Zeile ohne
   Warnung stand weiter links als eine mit HIC/DICTOR-Badge). Fester,
   IMMER gerenderter Slot (auch wenn leer) reserviert den Platz einheitlich. */
.route-step .warning-badge-slot {
    min-width: 150px;
    flex-shrink: 0;
    display: inline-flex;
    gap: 6px;
}
.route-step.bridge { color: var(--highsec); }
.route-step.bridge .name::after { content: " ⚡"; }
.route-step.wormhole { color: #a78bfa; }
.route-step.wormhole .name::after { content: " ≈"; }
.tag.wormhole {
    background: rgba(167, 139, 250, 0.1);
    color: #a78bfa;
    border-color: rgba(167, 139, 250, 0.3);
    text-transform: none;
    letter-spacing: 0;
}
.wormhole-exit { color: var(--gold); font-weight: 700; font-size: 12px; }
/* Feste Breiten statt nur Reihenfolge, damit die Spalten (Region/SOV/Sec)
   ueber alle Routen-Schritte hinweg linksbuendig untereinander stehen,
   auch wenn ein Feld (z.B. SOV) mal leer ist. */
.route-step .region-name { min-width: 130px; color: var(--steel-dim); font-size: 12px; }
.route-step .sov-holder { min-width: 170px; color: #7dd3fc; font-size: 12px; font-weight: 600; }
/* Kills der letzten Stunde (ESI /universe/system_kills/) - Format
   "Schiffe/Kapseln". Immer gerendert (auch leer, siehe map.html) und mit
   fester Breite statt nur min-width - sonst verschieben sich SOV/Sec-Spalte
   je nach Zeile, wenn mal keine Kills da sind oder die Zahl laenger ist
   (z.B. "37/23" vs. "1/1"). Rot (auch das hellere --nullsec) war auf dem
   dunklen Hintergrund weiterhin schwer lesbar - Gold statt Rot (schon
   anderswo in der App als gut lesbare Akzentfarbe bewaehrt) + groesser.
   Icon vor der Zahl per background-image (eigenes TC-Logo statt Skull-
   Emoji, sobald static/img/tc-icon.png vorliegt). */
.route-step .kill-count {
    width: 84px;
    flex-shrink: 0;
    color: var(--gold);
    font-size: 14px;
    font-weight: 700;
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
/* Nutzerwunsch: Icon immer zeigen, auch bei 0 Kills - vorher nur bei
   has-kills (also >0), dadurch fehlte es in den meisten Zeilen einer
   Route (die meisten Systeme haben ja keine Kills) und wirkte inkonsistent. */
.route-step .kill-count::before {
    content: "";
    display: inline-block;
    /* Icon ist ein hochkantes Kreuz (kein Quadrat) - Bilddatei ist schon
       eng auf das sichtbare Motiv zugeschnitten (24x48), Seitenverhaeltnis
       hier beibehalten statt quadratisch zu erzwingen, sonst wirkt es
       trotz "passender" Boxgroesse winzig (viel Leerraum drumrum). Hoeher
       als der Zifferntext, damit es optisch gleich schwer wirkt. */
    width: 0.7em;
    height: 1.4em;
    background-image: url("../img/tc-icon.png");
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
    flex-shrink: 0;
}
/* Etwas groesser als der App-weite .tag-Standard (11px) - in der dichten
   Routen-Tabelle sonst schwer lesbar. Nur hier, nicht global. */
.route-step .tag { font-size: 12px; padding: 4px 13px; }
/* NPC-Station im System ("Haeuschen" wie bei Dotlan) - reine Sub-Cap-Info. */
.route-step .station-icon { font-size: 15px; flex-shrink: 0; }

/* Nutzerwunsch: Klick auf einen Routen-Schritt zeigt alternative Systeme
   fuer den Sprung DAVOR an ("falls ich mit der Auswahl nicht zufrieden
   bin") - nur Schritte ab dem zweiten (der erste ist der Ausgangspunkt
   selbst, kein "Sprung davor" vorhanden). */
.route-step-clickable { cursor: pointer; }
.route-step-clickable:hover { background: rgba(255, 255, 255, 0.04); }
.route-step-alternatives {
    padding: 6px 4px 10px 24px;
    border-bottom: 1px solid #1b1b1f;
    font-size: 12.5px;
    color: var(--steel-dim);
}
/* Nutzerwunsch: Klick auf eine Alternative leitet die Route tatsaechlich um
   (siehe capital_map.html-JS, haengt system_id an "via" an) statt nur
   informativ zu sein - Cursor/Hover signalisieren das. */
.route-step-alternatives .alt-row {
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 4px 0;
}
.route-step-alternatives .alt-row .name { min-width: 140px; color: var(--steel); }
.route-step-alternatives .alt-row .distance { min-width: 70px; }
.route-step-alternatives .alt-row:hover { background: rgba(255, 255, 255, 0.06); }
/* 24h-/1h-Kills auch in den Alternativen-Zeilen (Nutzerwunsch), gleiche
   Optik wie in den Routen-Schritten inkl. TC-Icon davor - eigene Regel
   noetig, da die .route-step .kill-count-Regeln oben nur INNERHALB einer
   .route-step-Zeile greifen, die Alt-Zeilen aber im separaten
   .route-step-alternatives-Panel liegen. Etwas kompakter (12px statt
   14px), damit die dichte Alternativen-Liste nicht ueberladen wirkt. */
.route-step-alternatives .kill-count {
    width: 72px;
    flex-shrink: 0;
    color: var(--gold);
    font-size: 12px;
    font-weight: 700;
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.route-step-alternatives .kill-count::before {
    content: "";
    display: inline-block;
    width: 0.7em;
    height: 1.4em;
    background-image: url("../img/tc-icon.png");
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
    flex-shrink: 0;
}
/* Nutzerwunsch (2026-07-18): Liste/Karte-Umschalter im Alternativen-Panel -
   gleiche Optik wie die uebrigen sekundaeren Buttons, nur kompakter. */
.alt-view-toggle { display: flex; gap: 6px; margin-bottom: 8px; }
.alt-view-btn {
    background: var(--panel-2);
    border: 1px solid var(--border);
    color: var(--steel-dim);
    border-radius: 4px;
    padding: 2px 10px;
    font-size: 11px;
    cursor: pointer;
    font-family: inherit;
}
.alt-view-btn.active { color: var(--steel); border-color: var(--accent); }
.alt-map-legend { margin-top: 6px; font-size: 11px; color: var(--steel-dim); }
.alt-map-node text { pointer-events: none; }
/* Nutzerwunsch: "man muesste hier reinzoomen koennen" - bei ~100-250
   Systemen in der Kontext-Karte ist ein statisches SVG zu dicht zum Lesen.
   Gleiches Viewport-Muster wie .capital-map-viewport (Mausrad=Zoom,
   Ziehen=Verschieben), nur kompakter fuer das Alternativen-Panel. */
.alt-map-viewport {
    width: 100%;
    max-width: 560px;
    height: 460px;
    overflow: auto;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--bg);
    cursor: grab;
}
.alt-map-viewport.panning { cursor: grabbing; user-select: none; }
.alt-map-viewport svg { display: block; }

form.route-form label {
    display: block;
    margin: 12px 0 5px;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--steel-dim);
}
form.route-form input[type="text"] {
    background: var(--bg);
    border: 1px solid var(--border);
    color: var(--steel);
    border-radius: 6px;
    padding: 9px 12px;
    width: 260px;
    font-size: 14px;
}
form.route-form input[type="text"]:focus {
    outline: none;
    border-color: var(--accent-dim);
    box-shadow: 0 0 0 3px rgba(79, 159, 216, 0.15);
}
form.route-form .checkbox-row { margin-top: 14px; }
form.route-form .checkbox-row label {
    display: inline-flex; align-items: center; gap: 6px;
    margin-right: 20px; font-size: 13px;
    text-transform: none; color: var(--steel-dim);
}

.error-box {
    background: rgba(248, 113, 113, 0.08);
    border: 1px solid rgba(248, 113, 113, 0.35);
    color: #fca5a5;
    border-radius: 8px;
    padding: 12px 16px;
    margin-bottom: 18px;
    font-size: 14px;
}
.route-svg-wrap { overflow-x: auto; margin-top: 18px; }

.badge-row { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; margin-top: 12px; }

/* Interaktive Capital-Reichweiten-Karte (capital_explore.html) - fixe
   Viewport-Hoehe mit Scroll/Zoom statt die ganze (potenziell riesige, bei
   grosser Reichweite mit vielen Systemen dichte) Karte auf Seitenbreite zu
   quetschen. transform:scale() auf dem SVG selbst (nicht viewBox-Aenderung)
   ist einfacher und schneller als eine echte SVG-Pan/Zoom-Bibliothek. */
.capital-map-toolbar { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.capital-map-toolbar .btn { padding: 6px 16px; font-size: 13px; }
.capital-map-viewport {
    width: 100%;
    height: 900px;
    overflow: auto;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: var(--bg);
    cursor: grab;
}
/* Waehrend des Ziehens (siehe mousedown/mousemove im Template) - eigener
   Cursor + kein Text-/Element-Markieren, das beim schnellen Ziehen sonst
   stoert. */
.capital-map-viewport.panning {
    cursor: grabbing;
    user-select: none;
}
/* Nutzerwunsch: Kompaktkarte im Dashboard-Intel-Feed-Kasten (Umschalter
   [Intel]/[Karte]) - gleicher Viewport-Stil wie die Reichweiten-/Capital-
   Karte, aber auf Kartenhoehe des Kastens begrenzt statt 900px. */
.dashboard-map-viewport { height: 340px; }
/* Keine Transition mehr auf width/height - bei einer SVG mit >100 Kindern
   fuehrte die Animation beim Zoomen in manchen Browsern zu einem Render-
   Glitch (kurzzeitig doppelt gezeichnete Kreise, siehe Nutzer-Bugreport). */
.capital-map-viewport svg { display: block; }

/* Layer-Umschalter (Incursion/Sov-Kampagne) - siehe static/js/system_map.js,
   initSystemMap() blendet passende [data-layer] SVG-Elemente per Checkbox. */
.map-layer-toggles { display: flex; gap: 18px; flex-wrap: wrap; font-size: 12px; color: var(--steel-dim); }
.map-layer-toggles label { display: flex; align-items: center; gap: 6px; cursor: pointer; }

/* Nutzerwunsch: die Karte im Content Planer soll ebenfalls das ganze Fenster
   ausfuellen ("so gross wie das Fenster ist") - NUR diese eine Karte bricht
   aus der normalen main{}-Breitenbegrenzung aus (klassischer "full-bleed
   innerhalb eines zentrierten Layouts"-Trick per negativem Margin), der Rest
   der Seite (Formular, Operationen-Listen) bleibt bewusst in der normalen,
   schmaleren Spalte - die wuerden bei voller Fensterbreite nur unhandlich
   auseinandergezogene Formularfelder ergeben. */
.card-full-bleed {
    width: 100vw;
    position: relative;
    left: 50%;
    right: 50%;
    margin-left: -50vw;
    margin-right: -50vw;
    border-radius: 0;
}

/* Universum-Karte (Nutzerwunsch: "nicht in den tab beschraenkt" - die Karte
   soll den Rest des Browserfensters ausfuellen statt in einer festen Box zu
   stecken). main.main-full-bleed hebt main's normale Breiten-/Randbegrenzung
   auf (siehe main{} weiter oben), NUR fuer diese eine Seite. */
main.main-full-bleed {
    /* Nutzerwunsch: die Karte soll das Fenster wirklich komplett ausfuellen
       ("ganz links oben unten rechts ausgenutzt") - kein Rand/Polster mehr
       um main selbst, nur die Toolbar-Zeile darunter bekommt noch eigenes
       Innen-Polster (siehe .universe-toolbar), damit Suchfeld/Checkboxen
       nicht direkt an der Fensterkante kleben. */
    max-width: none;
    margin: 0;
    padding: 0;
}
.universe-toolbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
    padding: 8px 16px 12px;
}
.universe-toolbar #universe-search {
    background: var(--bg);
    border: 1px solid var(--border);
    color: var(--steel);
    border-radius: 6px;
    padding: 7px 12px;
    font-family: inherit;
    font-size: 13px;
    width: 220px;
}
.universe-map-wrap { position: relative; }
.universe-map-viewport { width: 100%; }
.universe-region-node { cursor: pointer; }
.universe-legend {
    position: absolute;
    bottom: 16px;
    right: 16px;
    z-index: 5;
    background: rgba(13, 18, 28, 0.88);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 10px 14px;
    font-size: 11.5px;
    color: var(--steel);
    line-height: 1.7;
    pointer-events: none;
    /* War ohne Breitenbegrenzung eine einzelne lange Zeile - seit dem
       Souveraenitaets-Eintrag (laengster Satz der Legende) zog sich die Box
       fast ueber die gesamte Kartenbreite statt als kompakte Ecken-Box zu
       bleiben (Nutzer-Audit "optische Verbesserungen", 2026-07-16). Feste
       max-width laesst sie wieder als schmaler Block in der Ecke umbrechen. */
    max-width: 360px;
}

/* Rechtsklick-Kontextmenue (Kartenpunkte in system_map.js UND "Route
   setzen" im Intel-Feed/TC-Flotte in intel.js) - Nutzerwunsch: soll direkt
   neben dem Mauszeiger aufgehen und wie ein aufklappendes Submenue wirken
   statt einfach ohne Uebergang zu erscheinen. Position (left/top) wird
   dynamisch per JS gesetzt, alles Visuelle (Farben/Uebergang) hier zentral -
   das Element bleibt dauerhaft im DOM (nicht display:none), damit die
   Opacity/Transform-Transition beim Oeffnen ueberhaupt sichtbar ablaufen
   kann; pointer-events:none haelt es im geschlossenen Zustand unklickbar
   und aus dem Layout-Fluss unsichtbar. */
.system-map-context-menu {
    position: fixed;
    z-index: 1000;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 7px;
    box-shadow: 0 10px 28px -8px rgba(0, 0, 0, 0.75);
    padding: 4px;
    min-width: 170px;
    opacity: 0;
    transform: scale(0.9);
    transform-origin: top left;
    transition: opacity 0.11s ease-out, transform 0.11s ease-out;
    pointer-events: none;
}
.system-map-context-menu.open {
    opacity: 1;
    transform: scale(1);
    pointer-events: auto;
}
.system-map-context-menu button {
    display: block;
    width: 100%;
    text-align: left;
    padding: 7px 12px;
    font-size: 12.5px;
    margin: 0;
    background: none;
    border: none;
    border-radius: 4px;
    color: var(--steel);
    cursor: pointer;
    white-space: nowrap;
}
.system-map-context-menu button:hover {
    background: var(--accent);
    color: #fff;
}

/* Doctrine-Zeilen (Schiffstyp + Anzahl) - geteilt zwischen dem Analysen-Tab
   (fight_analyse.html, eigene Battle-Karten) und dem D-Scan-Gegenvorschlag
   aus gesammelten Daten (doctrine.html, siehe fight_analyse.find_historical_counters). */
.fa-doctrine { display: flex; flex-direction: column; gap: 2px; }
.fa-doctrine-row {
    display: flex;
    justify-content: space-between;
    font-size: 12px;
    padding: 1px 0;
}
.fa-doctrine-row.fa-logi span:first-child { color: #7dd3fc; }
.fa-doctrine-count { color: var(--steel-dim); }

/* Infofenster (Stationen/Gate-Kills) - Klick auf einen Kartenpunkt, siehe
   static/js/system_map.js openSystemDetailPanel(). Gleiches Grundmuster wie
   Tonis Detail-Panel, aber mit unseren eigenen CSS-Variablen. */
.detail-panel {
    display: none;
    position: fixed;
    top: 0; right: 0;
    z-index: 100;
    width: 360px;
    max-width: 92vw;
    height: 100%;
    background: linear-gradient(180deg, var(--panel), var(--panel-2));
    border-left: 1px solid var(--border);
    overflow-y: auto;
    padding: 0 0 30px;
}
.detail-panel.open { display: block; }
.detail-panel .dp-head { padding: 20px 20px 14px; border-bottom: 1px solid var(--border); position: relative; }
.detail-panel .dp-head h2 { margin: 0; font-size: 18px; }
.detail-panel .dp-close { position: absolute; top: 16px; right: 16px; cursor: pointer; color: var(--steel-dim); font-size: 18px; line-height: 1; }
.detail-panel .dp-close:hover { color: var(--accent); }
.detail-panel .dp-section { padding: 14px 20px; border-bottom: 1px solid var(--border); }
.detail-panel .dp-section h3 { margin: 0 0 8px; font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--accent); }
.detail-panel .dp-row { display: flex; justify-content: space-between; gap: 10px; padding: 4px 0; font-size: 12.5px; }
.detail-panel .dp-row-sub { padding-left: 8px; opacity: 0.85; }
.detail-panel .dp-empty { color: var(--steel-dim); font-size: 12px; font-style: italic; }
/* Kopfzeile (Region/Konstellation/Security), Souveraenitaet + SOV-Hub,
   Aktivitaets-Hinweistext, externe Link-Buttons - Nutzerwunsch: Detailpanel
   an Tonis Karte als Vorbild ausgebaut (2026-07-14). */
.detail-panel .dp-sub { padding: 0 20px 14px; border-bottom: 1px solid var(--border); }
.detail-panel .dp-loc { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 12px; color: var(--steel-dim); }
.detail-panel .dp-sec-badge {
    display: inline-block; padding: 2px 8px; border-radius: 4px; border: 1px solid;
    font-weight: 700; font-size: 12px; line-height: 1.4;
}
.detail-panel .dp-region { color: var(--steel); }
.detail-panel .dp-constellation { color: var(--steel-dim); }
.detail-panel .dp-sov-row { display: flex; align-items: center; gap: 10px; }
.detail-panel .dp-sov-logo { width: 40px; height: 40px; border-radius: 4px; flex-shrink: 0; }
.detail-panel .dp-sov-names { flex: 1; min-width: 0; }
.detail-panel .dp-hint { margin-top: 8px; font-size: 11px; color: var(--steel-dim); font-style: italic; line-height: 1.5; }
.detail-panel .dp-links { display: flex; gap: 8px; flex-wrap: wrap; padding: 16px 20px 0; }
/* Incursion-Warnung (Nutzerwunsch: "wenn Incursions dort sind auch
   reinschreiben") - gleiche Farbe wie der Incursion-Ring auf den
   Regionskarten (#b46fe6, siehe region_map.html). */
.detail-panel .dp-incursion-box {
    margin: 0 20px 14px; padding: 8px 12px; border-radius: 6px;
    background: rgba(180, 111, 230, 0.12); border: 1px solid rgba(180, 111, 230, 0.4);
    color: #b46fe6; font-size: 12px; font-weight: 700;
}
/* Pochven-WH-Kandidat (Nutzerwunsch 2026-07-17: C729-Verbindungskandidaten
   vom EDENCOM Triglavian Tracker, auch ohne bekannte Signatur) - eigene
   Farbe, unterscheidbar von Incursion-Lila/Sov-Kampagne-Blau/Thera-Cyan auf
   denselben Karten. */
.detail-panel .dp-pochven-box {
    margin: 0 20px 14px; padding: 8px 12px; border-radius: 6px;
    background: rgba(233, 48, 255, 0.12); border: 1px solid rgba(233, 48, 255, 0.4);
    color: #e930ff; font-size: 12px; font-weight: 700;
}
.detail-panel .dp-links .btn { padding: 6px 14px; font-size: 12px; }
.spinner {
    display: inline-block;
    width: 12px; height: 12px;
    border: 2px solid var(--border);
    border-top-color: var(--accent);
    border-radius: 50%;
    animation: spinner-rotate 0.7s linear infinite;
}
@keyframes spinner-rotate { to { transform: rotate(360deg); } }
/* Sichtbarkeit einzelner .map-label-Elemente wird per JS (declutterLabels(),
   siehe capital_explore.html) inline gesetzt - echte Kollisionspruefung per
   SVG-BBox statt einer pauschalen Zoomstufe (die versteckte anfangs ALLE
   Namen, das war fuer den Nutzer schlechter als Ueberlappung). */
