:root {
  --bg: #0f1420;
  --card: #171e2e;
  --border: #2a3348;
  --text: #e6e9f0;
  --muted: #8b95ab;
  --accent: #4fd1a5;
  --accent2: #5b8def;
  --warn: #f2b84b;
  --danger: #ef6461;
  /* Logo-Gruen. Bewusst NICHT --accent (#4fd1a5): das ist der Bedienfarbton
     der Oberflaeche, das hier ist die Farbe der Marke (Kabel im Logo) und
     soll nur dort auftauchen. */
  --brand: #3bf07c;
}

* { box-sizing: border-box; }

body {
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  margin: 0;
}

.topnav {
  display: flex;
  align-items: center;
  gap: 24px;
  padding: 16px 24px;
  border-bottom: 1px solid var(--border);
  background: var(--card);
}

/* Wort-Bild-Marke: Zeichen und Schriftzug sind EIN Objekt, deshalb
   gemeinsame Flexbox statt Rand am Bild - der Abstand bleibt so bei jeder
   Schriftgroesse gleich. Die Hoehe steuert das Bild, die Breite folgt aus
   dem Seitenverhaeltnis des SVG (2,55:1).

   Bewusst NICHT an .topnav gebunden: dieselbe Marke steht auch ueber den
   Anmeldeseiten (auth_base.html), die keine Navigationsleiste haben. Zwei
   Definitionen wuerden frueher oder spaeter auseinanderlaufen; die
   Abweichungen dort (groesser, zentriert) haengen als .auth-brand im
   Style-Block von auth_base.html. */
.brand {
  display: flex;
  align-items: center;
  gap: 9px;
}
/* Fliessende Groesse statt eines zweiten Breakpoints: die Datei kommt
   bewusst mit genau einem aus (720 px). clamp() laesst Zeichen und Schriftzug
   auf schmalen Schirmen mitschrumpfen, damit Marke, Versions-Badge und
   Burger-Knopf eine Zeile bleiben, ohne dass die Leiste dafuer eine zweite
   Regel braucht. */
.brand img {
  height: clamp(21px, 6.2vw, 30px);
  width: auto;
  display: block;
}
.brandname {
  font-weight: 700;
  font-size: clamp(14px, 4.3vw, 17px);
  letter-spacing: -0.2px;
  color: var(--text);
  white-space: nowrap;
}
.brandname b { color: var(--brand); font-weight: 700; }

.topnav .brand { margin-right: 16px; }

/* Nur auf schmalen Schirmen sichtbar (siehe Media Query unten) - dort traegt
   der Button das Aufklappen, auf dem Desktop bleibt die Leiste wie bisher. */
.navtoggle {
  display: none;
  background: transparent;
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 8px;
  /* 44 px ist die uebliche Mindestgroesse fuer eine Fingerflaeche. */
  min-width: 44px;
  min-height: 44px;
  padding: 0 12px;
  font-size: 20px;
  line-height: 1;
  margin-left: auto;
}
.navtoggle:hover { border-color: var(--accent2); color: var(--accent2); opacity: 1; }
.topnav.open .navtoggle { border-color: var(--accent2); color: var(--accent2); }

/* Die eigentlichen Links, damit sie mobil als Block unter der Leiste
   sitzen koennen, ohne die Reihenfolge im Markup zu aendern. */
.navlinks {
  display: contents;
}

.topnav a {
  color: var(--muted);
  text-decoration: none;
  font-size: 14px;
}

.topnav a:hover { color: var(--text); }

.container {
  max-width: 1100px;
  margin: 0 auto;
  padding: 24px;
}

/* Die Ladevorgangs-Tabelle hat zwoelf Spalten und passte auch nach dem
   Verschlanken der Aktionsspalte nicht in die 1100 px, die fuer Dashboard und
   Einstellungen genau richtig sind - dort waere die volle Fensterbreite
   dagegen unangenehm zu lesen. Deshalb nur diese eine Seite breiter, und auch
   das nur so weit, wie das Fenster hergibt. */
.container.wide { max-width: 1500px; }

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 16px;
  margin-bottom: 24px;
}

.card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 16px 20px;
}

.stat-label {
  font-size: 12px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.stat-value {
  font-size: 26px;
  font-weight: 700;
  margin-top: 4px;
}

.stat-sub {
  font-size: 12px;
  color: var(--muted);
  margin-top: 2px;
}

.stat-sub:empty { display: none; }

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}

th, td {
  text-align: left;
  padding: 10px 12px;
  border-bottom: 1px solid var(--border);
}

th { color: var(--muted); font-weight: 600; font-size: 12px; text-transform: uppercase; }

/* Datums-/Zeitspalten nie umbrechen. Die automatische Spaltenbreite orientiert
   sich sonst an der kurzen Ueberschrift statt am laengeren Inhalt - im
   Englischen ("Date" + "Sep 1, 2026, 5:56 PM") faellt das Datum dadurch auf
   mehrere Zeilen, im Deutschen ("Datum" + "01.09.2026, 17:56") faellt es nur
   knapp nicht auf. nowrap statt fester min-width, damit die Breite dem
   tatsaechlichen Datumsformat der jeweiligen Sprache folgt. */
th.col-datetime, td.col-datetime { white-space: nowrap; }

tr.needs-review { background: rgba(242, 184, 75, 0.08); }

.badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
}

.badge-manual { background: rgba(91, 141, 239, 0.15); color: var(--accent2); }
.badge-automatic { background: rgba(242, 184, 75, 0.15); color: var(--warn); }
.badge-import { background: rgba(139, 149, 171, 0.15); color: var(--muted); }

form.inline-form {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 12px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 20px;
  margin-bottom: 24px;
}

label { font-size: 12px; color: var(--muted); display: block; margin-bottom: 4px; }

input, select {
  width: 100%;
  padding: 8px 10px;
  background: #0d1220;
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  font-size: 14px;
}

button {
  background: var(--accent);
  color: #0f1420;
  border: none;
  border-radius: 8px;
  padding: 10px 16px;
  font-weight: 600;
  cursor: pointer;
  font-size: 14px;
}

button:hover { opacity: 0.9; }

.form-actions { grid-column: 1 / -1; display: flex; justify-content: flex-end; }

/* Ein Feld ueber die volle Formularbreite. Die Rasterspalten sind auf kurze
   Eingabefelder ausgelegt (min. 140 px); eine Auswahl, deren Beschriftung ein
   ganzer Satz ist, bricht darin auf vier Zeilen um. */
.form-row-wide { grid-column: 1 / -1; }
.form-row-wide label { font-size: 14px; color: var(--text); margin-bottom: 0; }

/* Volle Breite, aber mit normaler Feldbeschriftung (z.B. die Notiz). */
.form-span { grid-column: 1 / -1; }
textarea {
  width: 100%;
  padding: 8px 10px;
  background: #0d1220;
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  font: inherit;
  font-size: 14px;
  resize: vertical;
}
select:disabled { opacity: 0.6; }

/* Ladevorgangs-Formular: erweiterte Felder nur mit dem Schalter "Alle
   Felder", Felder fuer bestehende Vorgaenge nur beim Bearbeiten. */
form.inline-form:not(.show-adv) .adv,
form.inline-form:not(.editing) .edit-only { display: none; }
.form-meta { font-size: 12px; color: var(--muted); word-break: break-all; }

/* --------------------------------------------------------------------------
   Aktionsspalte der Tabellen

   Vorher zwei beschriftete Knoepfe ("Bearbeiten"/"Löschen") - zusammen gut
   200 px und damit die breiteste Spalte der Ladevorgangs-Tabelle. Jetzt zwei
   quadratische Icon-Knoepfe (~76 px inkl. Abstand): flaechig gefaerbt waeren
   sie in einer langen Liste das auffaelligste Element, deshalb nur Rahmen und
   Faerbung beim Draufzeigen - dieselbe Zurueckhaltung wie beim Loeschen auf
   den Ladevorgangs-Karten.
   -------------------------------------------------------------------------- */
.row-actions { display: flex; gap: 6px; justify-content: flex-end; }

.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  background: transparent;
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.icon-btn:hover { opacity: 1; }
.icon-btn.edit:hover { color: var(--accent2); border-color: var(--accent2); }
.icon-btn.danger:hover { color: var(--danger); border-color: var(--danger); }
.icon-btn:focus-visible { outline: 2px solid var(--accent2); outline-offset: 2px; }

/* `width: 1%` zwingt die automatische Tabellenbreite, dieser Spalte nur so
   viel zu geben, wie ihr Inhalt braucht - der uebrige Platz geht an die
   Textspalten statt an eine Aktionsspalte, die ohnehin nur zwei Icons haelt. */
th.col-actions, td.col-actions { width: 1%; white-space: nowrap; }

h1 { font-size: 22px; margin-bottom: 20px; }
h2 { font-size: 16px; color: var(--muted); margin: 24px 0 12px; }

/* Abschnittsueberschrift mit einem Schalter rechts daneben. */
.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px 16px;
}
.section-head h2 { margin-bottom: 0; }

/* Schiebeschalter fuer die eine Einstellung, die einen ganzen Abschnitt
   scharf schaltet - eine Checkbox zwischen zehn weiteren Formularfeldern
   wird schlicht uebersehen. Der Checkbox-Input bleibt erhalten und wird nur
   visuell versteckt (nicht display:none), damit Tastaturbedienung,
   :checked-Styling und die bestehende JS-Anbindung ueber die id
   unveraendert funktionieren. */
.switch {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  font-size: 12px;
  color: var(--muted);
  cursor: pointer;
  align-self: center;
}
.switch input { position: absolute; opacity: 0; width: 0; height: 0; margin: 0; }

.switch .track {
  position: relative;
  flex: none;
  width: 42px;
  height: 24px;
  border-radius: 999px;
  background: var(--border);
  transition: background 0.15s;
}
.switch .track::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--text);
  transition: transform 0.15s;
}
.switch input:checked + .track { background: var(--accent); }
.switch input:checked + .track::after { transform: translateX(18px); }
.switch input:focus-visible + .track { outline: 2px solid var(--accent2); outline-offset: 2px; }

/* Feste Mindestbreite, damit die Ueberschrift beim Umschalten nicht springt. */
.switch .state {
  min-width: 3em;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.04em;
}
.switch input:checked ~ .state { color: var(--accent); }

.filter-widget { margin-bottom: 24px; }
.filter-toggle-btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  background: var(--card);
  color: var(--text);
  border: 1px solid var(--border);
  font-weight: 500;
  padding: 10px 14px;
}
.filter-toggle-btn.filter-toggle-active { border-color: var(--accent2); color: var(--accent2); }
.filter-toggle-chevron { color: var(--muted); font-size: 10px; }
.filter-panel { margin-top: 8px; }
.filter-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.filter-row + .filter-row { margin-top: 10px; }
.filter-row input[type="date"] { width: auto; }
.filter-preset-btn, .filter-apply-btn {
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--border);
  font-weight: 500;
  padding: 8px 12px;
}

.ver {
  background: var(--bg);
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 3px 10px;
  font-size: 12px;
  font-weight: 600;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  cursor: pointer;
}
.ver:hover { color: var(--accent2); border-color: var(--accent2); opacity: 1; }

.modal {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(5, 8, 15, 0.7);
  align-items: center;
  justify-content: center;
  /* Ueber ALLES, auch ueber die Karte: Leaflet vergibt seinen Ebenen und
     Bedienelementen z-index-Werte bis 1000 - mit dem frueheren Wert 100 lag
     ein geoeffneter Dialog auf der Kartenseite unsichtbar hinter den
     Kartenkacheln. */
  z-index: 1100;
  padding: 24px;
}
.modal.open { display: flex; }
.modal .box {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  max-width: 560px;
  width: 100%;
  max-height: 80vh;
  display: flex;
  flex-direction: column;
}
.modal .mtop {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.modal .mtop h3 { margin: 0; font-size: 16px; }
.modal .close {
  background: transparent;
  color: var(--muted);
  border: none;
  padding: 4px 8px;
  font-size: 14px;
}
.modal .close:hover { color: var(--text); }
.modal .mbody { padding: 16px 20px; overflow-y: auto; }

.clog { padding: 14px 0; border-bottom: 1px solid var(--border); }
.clog:last-child { border-bottom: none; }
.cloghead { display: flex; align-items: center; gap: 8px; }
.clogver { font-weight: 700; font-size: 14px; }
.clognow {
  background: rgba(79, 209, 165, 0.15);
  color: var(--accent);
  border-radius: 999px;
  padding: 2px 8px;
  font-size: 11px;
  font-weight: 600;
}
.clogdate { margin-left: auto; color: var(--muted); font-size: 12px; }
.clogtitle { font-weight: 600; margin: 8px 0 4px; }
.cloglist { margin: 0; padding-left: 18px; color: var(--muted); font-size: 14px; }
.cloglist li { margin-bottom: 4px; }

/* --------------------------------------------------------------------------
   Aufklappbare Bloecke (<details>)

   Zwei Rollen: `.help` fuer die langen Erklaertexte, die auf jeder Seite
   dauerhaft Platz gekostet haben, und `.panel` fuer ganze Abschnitte wie das
   MyŠkoda-Debug-Protokoll. Bewusst natives <details> statt eigenem JS -
   funktioniert ohne Skript, ist per Tastatur bedienbar und der Browser merkt
   sich beim Zurueckspringen den Zustand.
   -------------------------------------------------------------------------- */
details.help, details.panel {
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--card);
  margin-bottom: 16px;
}
details.help > summary, details.panel > summary {
  cursor: pointer;
  padding: 12px 16px;
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
  list-style: none;
  display: flex;
  align-items: center;
  gap: 8px;
}
details.help > summary::-webkit-details-marker,
details.panel > summary::-webkit-details-marker { display: none; }
/* Eigener Pfeil statt des Standard-Dreiecks, damit er zum Chevron der
   Filterleiste passt und in beiden Browsern gleich aussieht. */
details.help > summary::before, details.panel > summary::before {
  content: "▸";
  font-size: 10px;
  transition: transform 0.15s;
}
details.help[open] > summary::before, details.panel[open] > summary::before {
  transform: rotate(90deg);
}
details.help > summary:hover, details.panel > summary:hover { color: var(--text); }
/* Das Ladevorgangs-Formular ist selbst schon eine Karte (form.inline-form) -
   der Panel-Rahmen drumherum wuerde doppelt wirken. */
details.panel.plain { border: none; background: transparent; margin-bottom: 0; }
/* Uebernimmt den Abstand, den vorher das <h2> der Abschnittsueberschrift
   hatte - die Ueberschrift IST hier das <summary>. */
details.panel.plain > summary { padding: 24px 0 12px; font-size: 16px; color: var(--muted); }
details.panel.plain > summary:hover { color: var(--text); }
details.panel.plain > .inner { border-top: none; padding: 0; }

details.help > .inner, details.panel > .inner {
  padding: 0 16px 16px;
  border-top: 1px solid var(--border);
  padding-top: 14px;
}
details.help > .inner { color: var(--muted); font-size: 0.9em; }
details.panel > summary { font-size: 15px; color: var(--text); }

/* Ein aufklappbarer Abschnitt kann jetzt einen ganzen Bereich der
   Einstellungen enthalten (Liste UND Anlege-Formular). Das Formular ist darin
   ein zweites, eigenes <details> - geschachtelt braucht es weniger Luft nach
   oben als ein Abschnitt auf oberster Ebene. */
details.panel > .inner > details.panel.plain > summary { padding: 4px 0 12px; font-size: 14px; }
details.panel > .inner > details.panel.plain > summary::before { font-size: 9px; }
/* Der Zaehler hinter dem Abschnittsnamen ("Fahrzeuge 3") - macht zugeklappt
   sichtbar, ob ueberhaupt etwas drinsteht. */
details.panel > summary .count {
  margin-left: auto;
  color: var(--muted);
  font-size: 12px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------------------
   Unterseiten-Kacheln (Einstellungen -> Import / Backup / API & Debug)

   Diese drei Bereiche sind jeweils fuer sich schon eine Seite: der Import hat
   eine Vorschau-Tabelle, das Backup drei Formulare, die API-Seite ein
   Debug-Protokoll. Als weitere Klappabschnitte in den Einstellungen waeren sie
   nur schwerer zu finden, deshalb echte Seiten mit einer Kachel als Einstieg.
   -------------------------------------------------------------------------- */
.subpages {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 12px;
  margin-bottom: 24px;
}
.subpage {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 16px;
  text-decoration: none;
  color: var(--text);
}
.subpage:hover { border-color: var(--accent2); }
.subpage .ic { font-size: 20px; line-height: 1.2; }
.subpage strong { display: block; font-size: 15px; }
.subpage small { display: block; margin-top: 4px; color: var(--muted); font-size: 12px; }

/* Rueckweg von einer Unterseite. Relativer Pfad wie ueberall sonst (siehe
   main.py::_page) - alle Seiten liegen genau eine Ebene unter der Basis,
   damit funktioniert das unter dem Home-Assistant-Ingress-Unterpfad genauso
   wie am Domain-Root. */
.backlink {
  display: inline-block;
  margin-bottom: 12px;
  color: var(--muted);
  text-decoration: none;
  font-size: 13px;
}
.backlink:hover { color: var(--accent2); }

/* Tabellen laufen sonst aus dem Viewport (die Ladeorte-Tabelle hat fuenf
   Spalten mit Koordinaten). Der Wrapper scrollt statt die Seite zu dehnen. */
.tablewrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.tablewrap table { min-width: 100%; }

/* --------------------------------------------------------------------------
   Ladevorgaenge als Karten (mobil statt der zwoelfspaltigen Tabelle)

   Aufbau bewusst wie die Zeile in der iOS-App (SessionsListView.swift):
   links Datum + Lade-Art + Hinweis, darunter Fahrzeug/Anbieter/Ort, SoC und
   Kilometerstand, Verbrauch; rechts die Zahlen (kWh, Preis, Preis je kWh).
   Die ganze Karte ist antippbar und oeffnet den Bearbeiten-Modus, ebenfalls
   wie in der App.
   -------------------------------------------------------------------------- */
.session-cards { display: flex; flex-direction: column; gap: 10px; }

.scard {
  display: flex;
  gap: 12px;
  background: var(--card);
  /* Der Unterschied zwischen --card und --bg allein traegt nicht: auf einem
     Handydisplay bei Tageslicht verschwimmen #171e2e und #0f1420 zu einer
     Flaeche und die Liste sieht aus wie durchlaufender Text. Deshalb ein
     deutlicherer Rahmen, ein Schatten fuer die Abhebung und eine farbige
     linke Kante nach Lade-Art - die trennt und codiert gleichzeitig. */
  border: 1px solid #38445e;
  border-left: 4px solid var(--border);
  border-radius: 12px;
  padding: 12px 14px;
  cursor: pointer;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
}
.scard:active { border-color: var(--accent2); }
.scard.type-row-ac { border-left-color: var(--accent2); }
.scard.type-row-dc { border-left-color: var(--warn); }
/* Gleiche Bedeutung wie tr.needs-review in der Tabelle, aber als Flaeche UND
   Kante: rein ueber die Kante ginge es hier mit der Lade-Art-Codierung oben
   durcheinander. Die Einfaerbung bleibt schwach genug fuer die grauen
   Sekundaertexte darauf. */
.scard.needs-review {
  border-left-color: var(--warn);
  background: linear-gradient(rgba(242, 184, 75, 0.07), rgba(242, 184, 75, 0.07)), var(--card);
}

.scard .main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.scard .side {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 3px;
  text-align: right;
  white-space: nowrap;
}

.scard .stitle { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.scard .sdate { font-size: 14px; font-weight: 600; }
.scard .skwh { font-size: 14px; font-weight: 600; }
/* Zweite/dritte Zeile: alles Sekundaerinformation, wie in der App gestaffelt. */
.scard .ssub { font-size: 12px; color: var(--muted); overflow-wrap: anywhere; }
.scard .smeta { font-size: 11px; color: var(--muted); }

/* Loeschen ist auf der Karte bewusst zurueckhaltend: in der iOS-App liegt es
   hinter einer Wischgeste und draengt sich gar nicht auf. Ein flaechig roter
   Button waere hier das auffaelligste Element der ganzen Liste - und die
   Karte selbst ist das, was man antippen soll (Bearbeiten). Rot wird er erst
   beim Draufzeigen; die Sicherheitsabfrage haengt ohnehin davor. */
.scard .sactions { margin-top: auto; padding-top: 6px; }
.scard .sactions button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 5px 9px;
  font-size: 15px;
  font-weight: 400;
  line-height: 1.2;
}
.scard .sactions button:hover { color: var(--danger); border-color: var(--danger); opacity: 1; }

/* Ovales AC/DC-Badge, Farbgebung wie ChargingTypeBadge in der iOS-App. */
.type-badge {
  display: inline-block;
  padding: 1px 7px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
}
.type-ac { background: rgba(91, 141, 239, 0.15); color: var(--accent2); }
.type-dc { background: rgba(242, 184, 75, 0.15); color: var(--warn); }

.sitefoot {
  max-width: 1100px;
  margin: 0 auto;
  padding: 8px 24px 24px;
  font-size: 12px;
}
.sitefoot a { color: var(--muted); }
.sitefoot a:hover { color: var(--text); }

/* --------------------------------------------------------------------------
   Schmale Schirme
   -------------------------------------------------------------------------- */
@media (max-width: 720px) {
  .container { padding: 16px 12px; }
  h1 { font-size: 20px; margin-bottom: 16px; }

  /* Navigation: Links verschwinden hinter dem Burger-Button. Die Leiste
     selbst bleibt eine Zeile (Marke + Version + Button), die Links klappen
     darunter als Liste auf. */
  .topnav { flex-wrap: wrap; gap: 12px; padding: 12px 16px; }
  /* Marke, Versions-Badge und Burger-Knopf teilen sich hier eine Zeile; die
     Groesse regelt clamp() weiter oben, hier faellt nur der Rand weg. */
  .topnav .brand { margin-right: 0; gap: 7px; }
  .navtoggle { display: block; }
  .navlinks {
    display: none;
    flex-basis: 100%;
    flex-direction: column;
    gap: 0;
    /* Bis an den Rand der Leiste, damit die Trennlinien die volle Breite
       haben und die Liste nicht wie eingerueckter Fliesstext wirkt. Die
       flex-basis muss die negativen Raender mitrechnen - sonst bleibt die
       Liste 100 % breit und haengt nur nach links verschoben. */
    margin: 0 -16px -12px;
    flex-basis: calc(100% + 32px);
    border-top: 1px solid var(--border);
  }
  .topnav.open .navlinks { display: flex; }
  /* Jeder Eintrag eine eigene Zeile mit Fingerflaeche (44 px) statt
     aneinandergereihter Textlinks. */
  .navlinks a {
    display: flex;
    align-items: center;
    min-height: 44px;
    padding: 0 16px;
    font-size: 16px;
    color: var(--text);
  }
  .navlinks a:active { background: var(--bg); }
  .navlinks a + a { border-top: 1px solid var(--border); }
  /* Der Nutzerblock ist im Markup ein <span> mit margin-left:auto - das ergibt
     umgebrochen einen sinnlosen Rechtsbund. */
  .navlinks .navuser {
    margin-left: 0 !important;
    display: flex;
    align-items: center;
    min-height: 44px;
    padding: 0 16px;
    border-top: 1px solid var(--border);
    background: var(--bg);
  }
  /* Logout ist eine echte Aktion und liegt hier als Inline-Link mitten im
     Nutzernamen - ohne eigene Flaeche waere er 17 px hoch. */
  .navlinks .navuser a {
    display: inline-flex;
    align-items: center;
    min-height: 36px;
    padding: 0 8px;
    margin-left: 4px;
    border: 1px solid var(--border);
    border-radius: 8px;
    font-size: 14px;
  }

  /* Die Kennzahlen sind kurz genug fuer zwei Spalten - mit der
     auto-fit-Regel (min. 180 px) passte auf 375 px nur eine, was acht
     Bildschirmhoehen Kacheln vor den ersten Chart schob. */
  .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .card { padding: 12px 14px; }
  .stat-value { font-size: 20px; }
  .stat-label { font-size: 11px; }

  /* Ein Feld pro Zeile: bei zwei Spalten sind Zahlenfelder auf dem Handy so
     schmal, dass der Wert nicht mehr vollstaendig sichtbar ist. */
  form.inline-form { grid-template-columns: 1fr; padding: 16px; }
  .form-actions { flex-wrap: wrap; gap: 8px; }
  .form-actions button, .form-actions a { flex: 1 1 auto; }


  /* Tabellen scrollen mobil im Wrapper - je weniger Polsterung, desto seltener
     muss man ueberhaupt schieben. Die Aktionsknoepfe sind dort der breiteste
     Teil und schrumpfen mit. */
  .tablewrap th, .tablewrap td { padding: 8px 8px; }
  .tablewrap td button { padding: 6px 10px; font-size: 12px; }
  /* Icon-Knoepfe bleiben quadratisch und fingergerecht - die Regel darueber
     zielt auf beschriftete Knoepfe. */
  .tablewrap td .icon-btn { width: 34px; height: 34px; padding: 0; }

  .subpages { grid-template-columns: 1fr; }

  .filter-row input[type="date"] { flex: 1 1 45%; }
  .modal { padding: 12px; }
}

/* --------------------------------------------------------------------------
   Kartenansicht (map.html)

   Aufbau nach dem Vorbild von MapOverviewView.swift in der iOS-App: Ladeorte
   als blaue Marker mit ihrem Matching-Radius als Kreis, Ladevorgaenge als
   kleinere Punkte bzw. Zahlen-Cluster, Legende und Standort-Knopf liegen als
   Overlay ueber der Karte statt daneben - sonst frisst die Bedienleiste auf
   dem Handy die halbe Kartenflaeche.
   -------------------------------------------------------------------------- */
.maparea {
  position: relative;
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
}

/* Feste Hoehe aus der Viewport-Hoehe abzueglich Leiste, Ueberschrift und
   Filterzeile: eine Karte in einem mitwachsenden Container hat beim Laden
   die Hoehe 0 und bleibt grau. */
#map {
  height: clamp(360px, calc(100vh - 300px), 780px);
  background: var(--bg);
}

/* Die OSM-Standardkacheln sind fuer helle Oberflaechen gezeichnet und
   leuchten in dieser dunklen sonst wie ein Scheinwerfer. Nur leicht
   abgedunkelt statt invertiert - eine invertierte Karte liest sich zwar
   "dunkel", aber Wald, Wasser und Autobahnen bekommen dabei Farben, die
   niemand erwartet. Der Filter liegt ausschliesslich auf der Kachelebene,
   Marker und Kreise darueber behalten ihre volle Farbe. */
.leaflet-tile-pane { filter: brightness(0.82) saturate(0.85) contrast(1.05); }

.leaflet-container { font: inherit; background: var(--bg); }
.leaflet-container a { color: var(--accent2); }
.leaflet-popup-content-wrapper, .leaflet-tooltip {
  background: var(--card);
  color: var(--text);
  border: 1px solid var(--border);
}
.leaflet-tooltip::before { display: none; }
.leaflet-bar a, .leaflet-bar a:hover {
  background: var(--card);
  color: var(--text);
  border-bottom-color: var(--border);
}
.leaflet-control-attribution {
  background: rgba(15, 20, 32, 0.8);
  color: var(--muted);
}

/* Marker: divIcon ohne eigenen Hintergrund, die Form steckt im inneren
   <span>. iconAnchor sitzt in der Mitte, deshalb ist der Punkt selbst
   zentriert und braucht keine Spitze wie ein klassischer Pin. */
.map-pin-wrap { background: none; border: none; }
.map-pin {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  border: 2px solid #fff;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.5);
  color: #fff;
  font-size: 12px;
  font-weight: 600;
}
/* Ladeort: klassischer Pin mit Spitze auf dem Punkt - die Ladevorgaenge
   sitzen als Punkt genau auf derselben Koordinate, ohne den Versatz nach
   oben verdeckt der eine den anderen. */
.pin-location { position: relative; background: var(--accent2); }
.pin-location::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-top: 8px solid #fff;
}
.pin-session { background: #6b7690; border-width: 1.5px; }
.pin-cluster { background: var(--accent2); }
/* Orange wie das needs_review-Flag in Tabelle und Liste: ein noch nicht
   gepruefter Vorgang soll auf der Karte genauso auffallen. */
.pin-review { background: var(--warn); }

/* Legende und Standort-Knopf teilen sich den unteren Rand: die Legende
   mittig, der Knopf rechts - so ueberlappen sie sich auf keiner Breite. */
.map-legend {
  position: absolute;
  left: 50%;
  bottom: 14px;
  transform: translateX(-50%);
  z-index: 500;
  display: flex;
  gap: 6px;
  padding: 5px;
  background: rgba(23, 30, 46, 0.92);
  border: 1px solid var(--border);
  border-radius: 999px;
}
.legend-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px;
  border: none;
  border-radius: 999px;
  background: none;
  color: var(--muted);
  font-size: 12px;
  cursor: pointer;
  /* Durchgestrichen statt nur blass, wie die LegendToggle in der iOS-App:
     "ausgeblendet" ist damit auch ohne Farbvergleich erkennbar. */
  text-decoration: line-through;
}
.legend-toggle.on { color: var(--text); text-decoration: none; }
.legend-toggle .dot { width: 9px; height: 9px; border-radius: 50%; }
.legend-toggle .dot-location { background: var(--accent2); }
.legend-toggle .dot-session { background: #6b7690; }

.map-locate {
  position: absolute;
  right: 12px;
  /* Ueber der Zeile mit dem Attributionshinweis, nicht darauf - der Hinweis
     auf OpenStreetMap muss lesbar bleiben. */
  bottom: 30px;
  z-index: 900;
  width: 40px;
  height: 40px;
  padding: 0;
  font-size: 18px;
  border-radius: 10px;
}

.map-overlay {
  position: absolute;
  inset: 0;
  z-index: 600;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(15, 20, 32, 0.72);
}
.map-overlay .card { text-align: center; max-width: 420px; }
.map-overlay p { margin-top: 0; }

.map-hint { color: var(--muted); font-size: 12px; margin-top: 10px; }

/* Wertetabelle der Ladevorgangs-Vorschau: zwei Spalten, Label links. */
.detail-list {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 8px 16px;
  margin: 0 0 16px;
  font-size: 14px;
}
.detail-list dt { color: var(--muted); }
.detail-list dd { margin: 0; }

/* Zeile der Cluster-Liste - dieselbe Rolle wie ClusterSessionListSheet in
   der iOS-App: antippen oeffnet die Vorschau des Ladevorgangs. */
.cluster-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  width: 100%;
  margin-bottom: 8px;
  padding: 10px 12px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 10px;
  color: var(--text);
  text-align: left;
  cursor: pointer;
}
.cluster-row:hover { border-color: var(--accent2); }
.cluster-row small { display: block; color: var(--muted); font-size: 12px; }
.listempty { color: var(--muted); font-size: 14px; margin: 0 0 16px; }

@media (max-width: 720px) {
  /* Mobil zaehlt jede Zeile: die Karte bekommt den Rest des Bildschirms,
     die Legende rutscht nach unten links, damit sie den Attributionshinweis
     nicht verdeckt. */
  #map { height: clamp(320px, calc(100vh - 260px), 640px); }
  .map-legend { font-size: 11px; padding: 4px; }
  .legend-toggle { padding: 5px 9px; }
  .detail-list { grid-template-columns: 1fr; gap: 2px 0; }
  .detail-list dd { margin-bottom: 8px; }
}

/* ---------- Verbrauch nach Temperatur (index.html) ---------- */
.temphero {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: 16px;
  flex-wrap: wrap;
}
.temphero-figure {
  /* Die eine Zahl, wegen der es den ganzen Abschnitt gibt. Dieselbe Schrift
     wie ueberall - eine Auszeichnungsschrift allein fuer diese Stelle waere
     Dekoration. Bewusst OHNE tabular-nums: gleich breite Ziffern lassen eine
     grosse Zahl locker/auseinandergezogen wirken; die brauchen nur Spalten,
     die untereinander stehen (Tabelle, Achsenbeschriftung). */
  font-size: 48px;
  font-weight: 700;
  line-height: 1;
  color: var(--text);
}
.temphero-label { color: var(--text); font-size: 15px; }
.temphero-detail { color: var(--muted); font-size: 13px; margin-top: 4px; }
.tempempty { color: var(--muted); margin: 0; }

.scatterwrap { position: relative; }
.charttip {
  position: absolute;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 6px 9px;
  font-size: 13px;
  pointer-events: none;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.45);
  white-space: nowrap;
}
.charttip .muted { color: var(--muted); }

/* Legende: Farbe traegt die Marke, nie der Text - deshalb ein Punkt daneben
   und normale Textfarbe statt eingefaerbter Beschriftung. */
.chartlegend {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
  margin-top: 10px;
  color: var(--muted);
  font-size: 13px;
}
.chartlegend .dot {
  display: inline-block;
  width: 10px; height: 10px;
  border-radius: 50%;
  margin-right: 6px;
}
.chartnote { color: var(--muted); font-size: 13px; margin: 10px 0 0; }
.chartnote:empty { margin: 0; }

@media (max-width: 720px) {
  .temphero-figure { font-size: 38px; }
}

/* Profiltiefe je Rad (Reifenseite): 2x2 wie die Raeder am Fahrzeug, vorne
   oben. Die Zusammenfassung bleibt klein - meist reicht der eine Wert. */
.tread-wheels { margin-top: 4px; }
.tread-wheels > summary { cursor: pointer; font-size: 0.85em; color: var(--muted); }
.tread-wheel-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px;
  margin-top: 6px;
}

/* Dashboard: Zuhause/Arbeit/Unterwegs (index.html, renderPlaces) */
.place-row {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1fr;
  gap: 8px;
  align-items: baseline;
  padding: 8px 0;
  border-top: 1px solid var(--border, #2a3348);
  font-size: 14px;
}
.place-row small { color: var(--muted); font-size: 12px; margin-left: 4px; }
.place-name { font-weight: 600; }
.place-name small { display: block; margin-left: 0; font-weight: 400; }
.place-dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; margin-right: 6px; }
.place-price { text-align: right; font-weight: 600; }
@media (max-width: 720px) {
  .place-row { grid-template-columns: 1fr 1fr; }
  .place-price { text-align: left; }
}

/* Kostenkategorien (Dashboard "Gesamtkosten", Seite "Fahrzeug"; ui.js
   renderCostBars) */
.cost-row {
  display: grid;
  grid-template-columns: minmax(0, 10em) 1fr auto;
  gap: 10px;
  align-items: center;
  padding: 5px 0;
  font-size: 14px;
}
.cost-name { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cost-bar { height: 10px; border-radius: 5px; background: rgba(139,152,169,0.15); overflow: hidden; }
.cost-bar > div { height: 100%; border-radius: 5px; }
.cost-amount { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.cost-link { color: var(--accent2); }
.cost-amount small { color: var(--muted); font-size: 12px; margin-left: 4px; }
.cost-kpis { display: flex; gap: 28px; flex-wrap: wrap; margin-bottom: 12px; }
.cost-kpis .value { font-size: 22px; font-weight: 600; }
.cost-kpis .label { color: var(--muted); font-size: 12px; }
@media (max-width: 720px) {
  .cost-row { grid-template-columns: minmax(0, 7.5em) 1fr auto; gap: 8px; font-size: 13px; }
  .cost-amount small { display: none; }
}

/* Erinnerungen (reminders.py): Status-Badges auf der Seite "Fahrzeug" und
   das Banner oben im Dashboard. */
.badge.reminder-ok { background: rgba(79, 209, 165, 0.15); color: var(--accent); }
.badge.reminder-done { background: rgba(139, 149, 171, 0.15); color: var(--muted); }
.badge.reminder-due_soon { background: rgba(242, 184, 75, 0.15); color: var(--warn); }
.badge.reminder-overdue { background: rgba(239, 100, 97, 0.15); color: var(--danger); }
.reminder-banner { margin-bottom: 16px; border-left: 3px solid var(--warn); }
.reminder-line { display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap; padding: 3px 0; }
.reminder-when { color: var(--muted); font-size: 0.9em; }

/* Erstattungsbericht Dienstwagen (templates/reimbursement.html). */
button.ghost { background: transparent; color: var(--text); border: 1px solid var(--border); }
button.ghost:hover { border-color: var(--accent2); color: var(--accent2); opacity: 1; }
.rb-table td.num, .rb-table th.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.rb-table tr.rb-estimated td { color: var(--warn); }
.rb-table tr.rb-total td { font-weight: 600; border-top: 2px solid var(--border); }
.rb-head { display: grid; grid-template-columns: max-content 1fr; gap: 4px 16px; margin: 0 0 16px; }
.rb-head dt { color: var(--muted); }
.rb-head dd { margin: 0; }

/* Jahres- und Monatsrueckblick (templates/review.html) und seine Kachel im
   Dashboard. */
.review-tile { display: block; margin: 0 0 24px; color: var(--text); text-decoration: none;
  border-left: 3px solid var(--accent); }
.review-tile:hover { border-color: var(--accent2); }
.review-tile-title { font-weight: 600; font-size: 16px; }
.review-tile-figures { margin-top: 4px; }
.review-tile-more { color: var(--muted); font-size: 12px; margin-top: 6px; }
.rv-kpis { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 14px 20px; margin-bottom: 8px; }
.rv-kpi-value { font-size: 22px; font-weight: 600; }
.rv-delta, .rv-muted { color: var(--muted); font-size: 12px; }
.rv-good { color: var(--accent); }
.rv-bad { color: var(--danger); }
.rv-records { display: grid; grid-template-columns: max-content 1fr; gap: 6px 16px; margin: 0 0 12px; }
.rv-records dt { color: var(--muted); }
.rv-records dd { margin: 0; }
.rv-bar { display: flex; height: 22px; border-radius: 6px; overflow: hidden; gap: 2px; margin: 8px 0 6px; }
.rv-bar-legend { display: flex; justify-content: space-between; font-size: 12px; color: var(--muted); margin-bottom: 10px; }
@media (max-width: 720px) {
  .rv-records { grid-template-columns: 1fr; gap: 2px; }
  .rv-records dd { margin-bottom: 8px; }
  .rv-kpi-value { font-size: 18px; }
}

/* PDF ueber "Drucken -> Als PDF sichern": nur der Bericht, schwarz auf weiss. */
@media print {
  body { background: #fff; color: #000; }
  .topnav, .no-print, footer { display: none !important; }
  .container { max-width: none; padding: 0; margin: 0; }
  .print-area { display: block !important; border: none; background: #fff; color: #000; padding: 0; }
  .print-area h2, .print-area h3 { color: #000; }
  .print-area .chartnote, .rb-head dt { color: #444; }
  .print-area table { color: #000; }
  .print-area th { color: #444; }
  .print-area th, .print-area td { border-color: #ccc; }
  .rb-table tr.rb-estimated td { color: #000; font-style: italic; }
  .tablewrap { overflow: visible; }
  .print-area .rv-delta, .print-area .rv-muted, .print-area .rv-records dt,
  .print-area .stat-label, .print-area .place-row small { color: #444; }
  .print-area .rv-good, .print-area .rv-bad { color: #000; }
  .print-area svg text.bar-value { fill: #000; }
  .print-area svg text.bar-label { fill: #444; }
  /* Balken behalten ihre Farbe auch im Druck (Browser lassen Hintergruende
     sonst weg - dann bliebe vom AC/DC-Anteil nur ein leerer Rahmen). */
  .rv-bar div, .place-dot { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}

/* API & Debug: Umschalter zwischen den Quellen (settings_api.html) */
.source-switch { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0 24px; }
.source-switch button { background: transparent; color: var(--text); border: 1px solid var(--border); }
.source-switch button:hover { border-color: var(--accent2); color: var(--accent2); opacity: 1; }
.source-switch button[aria-selected="true"] { background: var(--accent); border-color: var(--accent); color: #0f1420; }

/* Laufender Ladevorgang (templates/_active_charging.html) - gruene Kante wie
   die orange des Erinnerungsbanners, damit er sich von beidem abhebt. */
.active-charging { margin-bottom: 16px; border-left: 3px solid var(--accent); }
.active-line { display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap; padding: 3px 0; }
.active-meta { color: var(--muted); font-size: 12px; }
.badge-active { background: rgba(79, 209, 165, 0.15); color: var(--accent); }
.active-dot {
  display: inline-block; width: 7px; height: 7px; margin-right: 5px; border-radius: 50%;
  background: var(--accent); vertical-align: 1px;
  animation: active-pulse 1.6s ease-in-out infinite;
}
@keyframes active-pulse { 50% { opacity: 0.3; } }
@media (prefers-reduced-motion: reduce) { .active-dot { animation: none; } }
