/* Hartix Cloud — Web-App. Dunkel, Hartix-Violett, responsiv.
 *
 * ZWEI FARBSCHEMEN. Dieses hier (:root) ist das ursprüngliche und bleibt die Vorgabe; das wärmere
 * steht weiter unten in `:root[data-design="warm"]` und wird nur wirksam, solange das Attribut am
 * <html> steht. Attribut weg = alter Zustand, Zeichen für Zeichen. Das ist die Rücknahme.
 *
 * Damit das überhaupt funktioniert, mussten zuvor 39 Farben, die direkt im Regelwerk standen, zu
 * Variablen werden — Tönungen des Akzents, Ampelfarben, weisse Vordergründe, Schatten und die
 * Glasleiste. Die WERTE sind dabei unverändert geblieben: dieser Schritt allein sieht genauso aus
 * wie vorher. Wer hier eine Farbe direkt einträgt, nimmt sie damit aus dem Umschalter heraus.
 *
 * MODULFARBE: `--mod` ist die Farbe des Bereichs, in dem man gerade steht. Vorgabe ist der Akzent,
 * das Schema darf sie je Modul überschreiben. Der Rückfall ist Absicht — solange nichts sie setzt,
 * verhält sich alles wie zuvor.
 */
:root {
    --bg: #15171c;
    /* Die Glasleiste hatte diesen Wert als Literal — zahlengleich zu --bg mit 92 % Deckung. */
    --bg-glass: rgba(21, 23, 28, .92);
    --surface: #1d2027;
    --surface2: #262a33;
    --accent: #8b7cff;
    --accent-soft: #b69bff;
    --on: #e7eaf0;
    /* Schrift auf Akzentflächen (Anmelde-Umschalter, Nutzerfarben). */
    --on-accent: #fff;
    /* Schrift auf der MODULFLÄCHE. Eigene Variable, weil helle Modulfarben — Gelb, Grün —
       weisse Schrift unlesbar machen. Wird je Modul gesetzt, Vorgabe ist weiss. */
    --on-mod: var(--on-accent);
    --muted: #9aa3b2;
    --outline: #323743;
    --error: #ff6b6b;
    --ok: #4dd0a0;
    /* Gelb gab es bisher NICHT als Variable, obwohl es sechsmal im Spar-Tracker steht. */
    --warn: #ffb84d;
    /* Vorhang hinter Dialogen und Schatten. Reines Schwarz wirkt auf warmem Grund schmutzig,
       deshalb gehören beide ins Schema. */
    --scrim: rgba(0, 0, 0, .55);
    --shadow: rgba(0, 0, 0, .4);
    --radius: 14px;

    /* Modulfarben. Hier alle gleich dem Akzent — das ursprüngliche Bild kennt nur eine Farbe. */
    --c-cal: var(--accent);
    --c-doc: var(--accent);
    --c-note: var(--accent);
    --c-meal: var(--accent);
    --c-save: var(--accent);
    --c-cont: var(--accent);
    --c-fam: var(--accent);
    /* Der Tresor steht auf einer eigenen Seite (/tresor) und lädt diese Datei nur wegen der
       Farben. Seine Modulfarbe gehört trotzdem hierher: eine im Tresor-Regelwerk eingetragene
       Farbe fiele aus dem Umschalter „Familie → Aussehen" heraus. */
    --c-vault: var(--accent);
    --c-fin: var(--accent);
    --mod: var(--accent);
}

/* ============================================================================
 * SCHEMA „Warmes Zuhause" — nur wirksam, solange <html data-design="warm"> steht.
 * Bleibt dunkel, wird aber wärmer, und jedes Modul bekommt eine eigene Farbe.
 * ============================================================================ */
:root[data-design="warm"] {
    --bg: #17151b;
    --bg-glass: rgba(23, 21, 27, .92);
    --surface: #211e27;
    --surface2: #2b2733;
    --accent: #a58bff;
    --accent-soft: #c4b0ff;
    --on: #efeaf2;
    --muted: #a79fb3;
    --outline: #38323f;
    --error: #ff7a7a;
    --ok: #4dd0a0;
    --warn: #ffc861;
    /* Vorhang und Schatten zur Grundfarbe getönt statt reinem Schwarz — sonst wirkt der
       Schatten auf warmem Grund schmutzig statt weich. */
    --scrim: rgba(14, 11, 17, .62);
    --shadow: rgba(12, 9, 15, .5);

    /* Eine Farbe je Modul. */
    --c-cal: #a58bff;
    --c-doc: #5cc8ff;
    --c-note: #ffc861;
    --c-meal: #ff9166;
    --c-save: #4dd0a0;
    --c-cont: #ff7eb6;
    --c-fam: #b9a6d6;
    /* Türkis — als einzige Modulfarbe kühl, damit das Tresorfenster in der Taskleiste nicht
       mit der Cloud verwechselt wird. Passt zum Symbol hartix-tresor-icon.svg. */
    --c-vault: #3ecfc4;
    /* Haushaltsbuch: gedecktes Grüngold. Deutlich genug von --c-save (Sparen) entfernt,
       damit man die beiden Geld-Module in der Leiste nicht verwechselt. */
    --c-fin: #c2b280;
}
/* Sehr zurückhaltender Schimmer in den oberen Ecken. Eine freistehende Gruppe auf einer glatten
   Fläche wirkt sonst, als schwebe sie im Nichts — der Verlauf gibt Tiefe, ohne sich vorzudrängen.
   `fixed`, damit er beim Scrollen liegen bleibt. */
:root[data-design="warm"] body {
    background-image:
        radial-gradient(900px 500px at 12% -8%, color-mix(in srgb, var(--c-cal) 13%, transparent), transparent),
        radial-gradient(800px 460px at 92% 4%, color-mix(in srgb, var(--c-cont) 9%, transparent), transparent);
    background-attachment: fixed;
    background-repeat: no-repeat;
}
/* Auf Gelb, Grün, Orange und Hellblau ist weisse Schrift nicht lesbar — dort steht der Text
   in der Grundfarbe. Betrifft Knopfflächen, den heutigen Tag und die Haken. */
:root[data-design="warm"] .mod-notes,
:root[data-design="warm"] .mod-meals,
:root[data-design="warm"] .mod-save,
:root[data-design="warm"] .mod-docs,
:root[data-design="warm"] .mod-fin { --on-mod: #17151b; }

/* Die Modulfarbe wird am Rahmen gesetzt und gilt damit für Leiste UND Inhalt. */
.mod-cal { --mod: var(--c-cal); }
.mod-docs { --mod: var(--c-doc); }
.mod-notes { --mod: var(--c-note); }
.mod-meals { --mod: var(--c-meal); }
.mod-save { --mod: var(--c-save); }
.mod-contacts { --mod: var(--c-cont); }
.mod-fin { --mod: var(--c-fin); }
.mod-fam, .mod-trip, .mod-overview { --mod: var(--c-fam); }

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
    background: var(--bg);
    color: var(--on);
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    -webkit-font-smoothing: antialiased;
}
.boot { padding: 40px; text-align: center; color: var(--muted); }
a { color: var(--accent-soft); }

/* ---- Layout ---- */
.topbar {
    position: sticky; top: 0; z-index: 20;
    display: flex; align-items: center; gap: 12px;
    padding: 12px 16px;
    background: var(--bg-glass);
    backdrop-filter: blur(8px);
    border-bottom: 1px solid var(--outline);
}
.topbar .brand { font-weight: 700; font-size: 18px; color: var(--accent); }
.topbar .spacer { flex: 1; }
.tabs { display: flex; gap: 4px; padding: 8px 12px 0; flex-wrap: wrap; }
.tab {
    padding: 9px 16px; border-radius: 999px; cursor: pointer;
    color: var(--muted); border: 1px solid transparent; user-select: none;
}
.tab:hover { color: var(--on); }
/* Tönungen entstehen aus der Modulfarbe, statt das RGB-Triplet einzubacken — sonst bliebe der
   aktive Reiter violett, während der Rest des Bildes wechselt. */
.tab.active {
    color: var(--mod);
    background: color-mix(in srgb, var(--mod) 14%, transparent);
    border-color: color-mix(in srgb, var(--mod) 30%, transparent);
}
.content { max-width: 900px; margin: 0 auto; padding: 16px; }

/* ---- Buttons / inputs ---- */
button, .btn {
    font: inherit; cursor: pointer; border-radius: 10px; border: 1px solid transparent;
    padding: 9px 14px; background: var(--surface2); color: var(--on);
    display: inline-flex; align-items: center; gap: 6px;
}
button:hover, .btn:hover { filter: brightness(1.1); }
button:disabled { opacity: .5; cursor: default; }
.btn-primary { background: var(--mod); color: var(--on-mod); }
.btn-ghost { background: transparent; border-color: var(--outline); }
.btn-danger { background: transparent; border-color: var(--outline); color: var(--error); }
.btn-sm { padding: 6px 10px; font-size: 13px; }
.iconbtn { background: transparent; border: none; padding: 6px; color: var(--muted); border-radius: 8px; }
.iconbtn:hover { color: var(--on); background: var(--surface2); }

label { display: block; font-size: 13px; color: var(--muted); margin: 10px 0 4px; }
input, select, textarea {
    font: inherit; width: 100%; padding: 10px 12px; color: var(--on);
    background: var(--bg); border: 1px solid var(--outline); border-radius: 10px;
}
input:focus, select:focus, textarea:focus { outline: none; border-color: var(--mod); }
textarea { min-height: 72px; resize: vertical; }
/* Checkboxen dürfen die 100%-Breite der Formularfelder NICHT erben — sonst werden sie
   über die ganze Zeile gezogen und die Beschriftung rutscht per flex-wrap darunter. */
input[type="checkbox"] {
    width: 18px; height: 18px; flex: none; padding: 0;
    accent-color: var(--mod); cursor: pointer;
}
label.row { cursor: pointer; }
.row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.row > * { min-width: 0; }
.grow { flex: 1; }

/* ---- Cards / lists ---- */
.card { background: var(--surface); border: 1px solid var(--outline); border-radius: var(--radius); padding: 16px; margin-bottom: 14px; }
.card h3 { margin: 0 0 10px; font-size: 14px; color: var(--muted); font-weight: 600; }
.muted { color: var(--muted); }
.small { font-size: 13px; }
.err { color: var(--error); }
.ok { color: var(--ok); }
.center { text-align: center; }
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }

.list-item {
    display: flex; align-items: center; gap: 12px;
    padding: 12px; border: 1px solid var(--outline); border-radius: 12px;
    background: var(--surface); margin-bottom: 8px;
}
.list-item .ic { position: relative; width: 34px; height: 34px; flex: none; display: grid; place-items: center; border-radius: 8px; background: var(--surface2); color: var(--mod); font-size: 18px; overflow: hidden; }
/* Die Vorschau legt sich UEBER das Emoji, statt es zu ersetzen. Solange kein `src` da ist
   (oder das Laden scheitert), bleibt das Emoji sichtbar — so entsteht nie ein leeres Kaestchen.
   ⚠ NICHT mit `grid-area: 1/1` loesen: das belegt Zelle eins, der Emoji-Textknoten wandert
   dann automatisch in eine ZWEITE Zeile und guckt unter dem Bild hervor (gemessen: Zeilen
   "3.5px 30.5px", Bild nur 3,5 px hoch). Absolut positioniert deckt das Bild die Flaeche ganz. */
.list-item .ic img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border-radius: inherit; }
.list-item .ic img:not([src]), .list-item .ic img.thumb-fehlt { display: none; }
.list-item .body { flex: 1; min-width: 0; }
.list-item .title { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.list-item .sub { font-size: 12px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Terminbeschreibung auf der Karte: höchstens zwei Zeilen, damit ein langer Text die Liste
   nicht sprengt. `pre-wrap` erhält die Zeilenumbrüche aus der Beschreibung. */
.list-item .evdesc {
    font-size: 12px; color: var(--muted); margin-top: 3px;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden; white-space: pre-wrap; word-break: break-word;
}
.list-item .evdesc a { color: var(--accent); text-decoration: underline; }
.list-item .evdesc a:hover { text-decoration: none; }
.daygroup { font-size: 13px; color: var(--muted); margin: 14px 2px 6px; }

.chips { display: flex; gap: 8px; flex-wrap: wrap; }
.chip {
    padding: 6px 12px; border-radius: 999px; cursor: pointer;
    border: 1px solid var(--outline); color: var(--muted); background: transparent; font-size: 13px;
}
.chip.active { color: var(--mod); border-color: var(--mod); background: color-mix(in srgb, var(--mod) 12%, transparent); }
.dot { width: 12px; height: 12px; border-radius: 999px; flex: none; }
.badge { font-size: 11px; padding: 3px 8px; border-radius: 6px; background: var(--surface2); color: var(--muted); }
.badge.admin { background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent); }
.evbar { width: 5px; align-self: stretch; border-radius: 3px; flex: none; }

/* ---- Auth ---- */
.auth-wrap { max-width: 380px; margin: 8vh auto; padding: 24px; }
.auth-wrap h1 { color: var(--accent); text-align: center; margin: 0; }
.auth-wrap .sub { text-align: center; color: var(--muted); margin: 4px 0 20px; }
.seg { display: flex; border: 1px solid var(--outline); border-radius: 10px; overflow: hidden; margin-bottom: 8px; }
.seg button { flex: 1; background: transparent; border: none; border-radius: 0; color: var(--muted); }
.seg button.active { background: var(--accent); color: var(--on-accent); }

/* ---- Modal ---- */
.modal-back { position: fixed; inset: 0; background: var(--scrim); display: grid; place-items: center; z-index: 50; padding: 16px; }
.modal { background: var(--surface); border: 1px solid var(--outline); border-radius: var(--radius); padding: 20px; width: 100%; max-width: 460px; max-height: 88vh; overflow: auto; }
.modal h2 { margin: 0 0 12px; font-size: 18px; }
.modal .actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 16px; }
.palette { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 6px; }
.swatch { width: 30px; height: 30px; border-radius: 999px; cursor: pointer; border: 1px solid var(--outline); }
.swatch.sel { outline: 3px solid var(--on); outline-offset: 1px; }

/* ---- Toast ---- */
.toast { position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%); z-index: 60;
    background: var(--surface2); border: 1px solid var(--outline); padding: 10px 16px; border-radius: 10px; box-shadow: 0 8px 24px var(--shadow); }
.toast.err { border-color: var(--error); color: var(--error); }

/* ---- Preview ---- */
.preview-img { max-width: 100%; max-height: 78vh; border-radius: 10px; display: block; margin: 0 auto; }

.fab { position: fixed; right: 20px; bottom: 20px; z-index: 30; }
.fab button { box-shadow: 0 8px 24px var(--shadow); padding: 14px 18px; border-radius: 999px; }

/* ---- Galerie ---- */
.gal-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); gap: 8px; }
.gal-cell { aspect-ratio: 1 / 1; border-radius: 10px; overflow: hidden; background: var(--surface2); cursor: pointer; }
.gal-cell img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ---- Kalender-Auswahl (mehrere Kalender zugleich) ---- */
.cal-chip { display: inline-flex; align-items: center; gap: 7px; }
.cal-chip .dot { width: 10px; height: 10px; }
.cal-chip:not(.active) { opacity: .55; text-decoration: line-through; }

/* ---- Kalender-Monat ---- */
.cal-head { display: flex; align-items: center; gap: 8px; margin: 6px 0 8px; }
.cal-head .title { flex: 1; text-align: center; font-weight: 600; font-size: 16px; text-transform: capitalize; }
.cal-week { display: grid; grid-template-columns: repeat(7, 1fr); }
.cal-wd { text-align: center; font-size: 12px; color: var(--muted); padding: 4px 0; }
/* Monatsraster: eine Zeile je WOCHE. Nur so kann ein mehrtägiger Termin als durchgehender
   Balken über mehrere Spalten laufen — eine einzelne Tageszelle endet an ihrem Rand. */
.cal-grid { display: flex; flex-direction: column; gap: 3px; }
.cal-wrow { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px 3px; }
/* Der anklickbare Tag liegt als Hintergrund über die volle Wochenhöhe. */
.cal-cellbg { min-height: 52px; border-radius: 8px; cursor: pointer; border: 1px solid transparent; }
.cal-cellbg:hover { background: var(--surface); }
.cal-cellbg.sel { border-color: var(--mod); }
/* Zahl und Punkte liegen darüber, dürfen den Klick aber nicht abfangen. */
.cal-num {
    width: 26px; height: 26px; display: grid; place-items: center; border-radius: 999px;
    font-size: 14px; justify-self: center; margin-top: 4px; pointer-events: none;
}
.cal-num.today { background: var(--mod); color: var(--on-mod); }
.cal-num.dim { color: var(--muted); opacity: .45; }
.cal-marks { display: flex; gap: 2px; height: 8px; justify-content: center; align-items: center; pointer-events: none; }
.cal-marks .m { width: 5px; height: 5px; border-radius: 999px; }
/* Der Balken selbst. Läuft er über den Wochenrand hinaus, wird die Kante eckig — so sieht man,
   dass er weitergeht, statt dass er dort zu enden scheint. */
.cal-bar {
    height: 17px; line-height: 17px; border-radius: 5px; margin: 0 1px;
    padding: 0 6px; font-size: 11px; color: var(--on-accent); font-weight: 500;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer;
}
.cal-bar:hover { filter: brightness(1.12); }
.cal-bar.cont-l { border-top-left-radius: 0; border-bottom-left-radius: 0; margin-left: 0; }
.cal-bar.cont-r { border-top-right-radius: 0; border-bottom-right-radius: 0; margin-right: 0; }

/* ---- Drag & Drop + Mehrfachauswahl ---- */
.list-item[draggable="true"], .gal-cell[draggable="true"] { cursor: grab; }
.list-item.dragging, .gal-cell.dragging { opacity: .45; }
.drop-hot { outline: 2px dashed var(--mod); outline-offset: 2px; background: color-mix(in srgb, var(--mod) 16%, transparent) !important; }
.drag-ghost {
    position: fixed; top: -1000px; left: -1000px; z-index: 80;
    padding: 6px 12px; background: var(--mod); color: var(--on-mod); border-radius: 999px;
    font-size: 13px; font-weight: 600; box-shadow: 0 6px 18px var(--shadow);
}

.tgl-on { border-color: var(--mod); color: var(--mod); }
.selbar {
    display: flex; align-items: center; gap: 8px; padding: 8px 12px; margin: 0 0 12px;
    border: 1px solid var(--mod); border-radius: 12px; background: color-mix(in srgb, var(--mod) 10%, transparent);
}
.selbar .count { font-size: 14px; font-weight: 600; }

.list-item.selectable { cursor: pointer; }
.list-item.selectable:hover { border-color: color-mix(in srgb, var(--mod) 60%, var(--outline)); }
.list-item.selected { border-color: var(--mod); background: color-mix(in srgb, var(--mod) 12%, transparent); }
.list-item .check {
    width: 34px; height: 34px; flex: none; border-radius: 8px; border: 2px solid var(--outline);
    display: grid; place-items: center; color: var(--on-mod);
}
.list-item .check.on { border-color: var(--mod); background: var(--mod); }
.list-item .check.on::after { content: "✓"; font-size: 16px; }

.gal-cell { position: relative; }
.gal-cell.selected { outline: 3px solid var(--mod); outline-offset: -3px; }
.gal-check {
    position: absolute; top: 6px; right: 6px; width: 22px; height: 22px; border-radius: 999px;
    border: 2px solid #fff; background: rgba(0,0,0,.4); display: grid; place-items: center; color: #fff; font-size: 13px;
}
.gal-check.on { background: var(--mod); }
.gal-check.on::after { content: "✓"; }

/* Abspiel-Markierung auf Video-Kacheln. Wie beim `.gal-check` bewusst HART kodiert und nicht
   über die Theme-Farben: das Zeichen liegt auf einem beliebigen Standbild, nicht auf einer
   Theme-Fläche — dort muss es gegen hell UND dunkel bestehen. */
.gal-play {
    position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
    width: 34px; height: 34px; border-radius: 999px;
    background: rgba(0, 0, 0, .5); color: #fff; font-size: 15px;
    display: grid; place-items: center; pointer-events: none; padding-left: 2px;
}
/* Vorschaubild ließ sich nicht holen — dann wenigstens keine leere weiße Fläche. */
.gal-cell img.thumb-fehlt { opacity: .25; }

/* ---- Bild-/Video-Betrachter (Vollbild, blätterbar) ---- */
/* ACHTUNG, hier steckte ein Fehler, der genau wie ein CSS-Rätsel aussieht:
   `align-items: center` am Raster hebt die Streckung der Zeile auf — die Bühne war dann nur so
   hoch wie ihr INHALT, und `max-height: 100%` am Bild bezog sich damit auf seine eigene Höhe,
   also auf nichts. Ergebnis: das Bild kam in voller Auflösung und hing oben aus dem Bild heraus.
   Dieselbe Falle wie beim Seitenleisten-Umbau am 26.07. (`align-self: start`).
   Deshalb: KEIN `align-items` am Raster (die Pfeile zentrieren sich selbst), und die Zeile als
   `minmax(0, 1fr)` — ohne die 0 als Minimum darf ein Rasterelement nicht unter seine
   Inhaltsgrösse schrumpfen, und dann hilft auch das Strecken nichts. */
.lightbox {
    position: fixed; inset: 0; z-index: 80;
    background: var(--scrim);
    backdrop-filter: blur(6px);
    display: grid;
    grid-template-columns: auto 1fr auto;
    grid-template-rows: auto minmax(0, 1fr);
    grid-template-areas: "kopf kopf kopf" "links buehne rechts";
}
.lb-kopf {
    grid-area: kopf; display: flex; align-items: center; gap: 12px;
    padding: 10px 14px; background: var(--bg-glass); border-bottom: 1px solid var(--outline);
}
.lb-titel { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; }
.lb-zaehler { color: var(--muted); font-size: 13px; flex: none; }
.lb-zu {
    flex: none; width: 32px; height: 32px; border-radius: 999px; cursor: pointer;
    border: 1px solid var(--outline); background: transparent; color: var(--text); font-size: 15px;
}
/* `overflow: hidden` ist der Riegel: sollte je etwas doch zu gross sein, quillt es nicht mehr
   über den Bildschirmrand, sondern wird beschnitten. */
/* FLEX, nicht Grid — und das ist der entscheidende Punkt, nicht Geschmack:
   Als Raster bekommt das Bild eine automatisch bemessene Zeile. `max-height: 100%` bezieht sich
   dann auf die Höhe DIESER Zeile, also auf die Bildhöhe selbst — die Regel begrenzt sich damit
   gegen sich selbst und tut nichts. Genau daran hing der Fehler: die Bühne war mit 1027 px längst
   richtig bemessen, das Bild rechnete trotzdem gegen 3000 px.
   Im Flex-Container löst die Prozenthöhe gegen den Container auf, und der ist definit. */
.lb-buehne {
    grid-area: buehne;
    display: flex; align-items: center; justify-content: center;
    padding: 12px; min-width: 0; min-height: 0; overflow: hidden;
}
/* `max-height: 100%` statt einer vh-Rechnung: die Bühne ist bereits die Restzeile des Rasters,
   eine eigene Höhenrechnung ginge bei jeder Kopfzeilenänderung daneben. */
.lb-medium { max-width: 100%; max-height: 100%; object-fit: contain; border-radius: 8px; display: block; }
.lb-laedt { color: var(--muted); font-size: 14px; }
.lb-pfeil {
    align-self: center;
    width: 52px; height: 72px; cursor: pointer; font-size: 34px; line-height: 1;
    border: none; background: transparent; color: var(--text); opacity: .65;
}
.lb-pfeil:hover { opacity: 1; }
.lb-links { grid-area: links; }
.lb-rechts { grid-area: rechts; }

/* Am Handy nehmen die Pfeile zu viel Breite — dort wird gewischt, und sie rücken als
   schmale Flächen an den Rand. */
@media (max-width: 640px) {
    .lb-pfeil { width: 34px; font-size: 26px; }
    .lb-buehne { padding: 6px; }
}

/* ---- Speicher-Belegung ---- */
.quota-bar { height: 10px; border-radius: 999px; background: var(--surface2); overflow: hidden; }
.quota-fill { height: 100%; width: 0; background: var(--mod); transition: width .3s ease; }
.quota-fill.hot { background: var(--error); }

/* ---- Kontakte ---- */
.avatar {
    width: 38px; height: 38px; flex: none; border-radius: 999px;
    display: grid; place-items: center; color: var(--on-accent); font-weight: 700; font-size: 14px;
}
.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0 10px; }

/* ---- Sicherheit / 2FA ---- */
.keybox {
    background: var(--bg); border: 1px solid var(--outline); border-radius: 10px;
    padding: 12px; word-break: break-all; letter-spacing: 1px;
}
.codes { display: grid; grid-template-columns: repeat(auto-fill, minmax(126px, 1fr)); gap: 6px; }
.codes > div {
    background: var(--bg); border: 1px solid var(--outline); border-radius: 8px;
    padding: 8px 6px; text-align: center; letter-spacing: 1px; font-size: 14px;
}

/* ---- Essensplan ---- */
.meal-day { width: 48px; flex: none; text-align: center; }
.meal-day .wd { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: .5px; }
.meal-day .dm { font-size: 14px; font-weight: 600; }
.list-item.today { border-color: var(--mod); }
.list-item.today .meal-day .dm { color: var(--mod); }

/* ---- Notizen ---- */
.note-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 12px; align-items: start; }
.note-card {
    background: var(--surface); border: 1px solid var(--outline); border-radius: var(--radius);
    padding: 14px; display: flex; flex-direction: column; gap: 8px;
}
.note-card.pinned { border-color: color-mix(in srgb, var(--mod) 50%, transparent); }
.note-head { display: flex; align-items: center; gap: 8px; cursor: pointer; }
.note-title { font-weight: 600; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.note-body {
    color: var(--muted); font-size: 13px; white-space: pre-wrap; word-break: break-word; cursor: pointer;
    overflow: hidden; display: -webkit-box; -webkit-line-clamp: 10; -webkit-box-orient: vertical;
}
.note-foot { display: flex; align-items: center; gap: 8px; font-size: 11px; color: var(--muted); margin-top: auto; padding-top: 2px; }
.note-items { display: flex; flex-direction: column; gap: 1px; }
.note-item { display: flex; align-items: flex-start; gap: 9px; padding: 5px 4px; border-radius: 8px; cursor: pointer; }
.note-item:hover { background: var(--surface2); }
.note-item .t { font-size: 14px; line-height: 1.35; word-break: break-word; }
.note-item.done .t { text-decoration: line-through; color: var(--muted); }
.chk {
    width: 18px; height: 18px; flex: none; margin-top: 2px; border-radius: 5px;
    border: 2px solid var(--outline); display: grid; place-items: center; color: var(--on-mod); font-size: 12px; line-height: 1;
}
.chk.on { background: var(--mod); border-color: var(--mod); }
.chk.on::after { content: "✓"; }
.quick-add { padding: 7px 10px; font-size: 13px; background: transparent; }

/* ---- Ordnerpfad („Brotkrumen") im Dokumentbereich ---- */
.crumbs { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 12px 0 0; font-size: 14px; }
.crumb { color: var(--accent-soft); cursor: pointer; padding: 3px 6px; border-radius: 8px; }
.crumb:hover { background: var(--surface2); }
/* Der aktuelle Ordner ist Ziel, kein Weg — deshalb ohne Zeigefinger und in Textfarbe. */
.crumb.cur { color: var(--on); font-weight: 600; cursor: default; }
.crumb.cur:hover { background: transparent; }
.crumb-sep { color: var(--muted); }
/* Das Aufleuchten beim Ziehen kommt aus der globalen .drop-hot-Regel — hier nichts Eigenes nötig. */

/* ---- Ansichtsstil „Ordner" (Explorer-Kacheln) ---- */
.fold-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); gap: 10px; }
/* Feste Mindesthöhe: sonst sind die Kacheln je nach Namenslänge und Unterzeile
   unterschiedlich hoch, und das Raster wirkt von Zeile zu Zeile unruhig. */
.fold-cell {
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px;
    min-height: 112px; padding: 16px 10px; border: 1px solid var(--outline); border-radius: 12px;
    background: var(--surface); cursor: pointer; text-align: center;
}
.fold-cell:hover { border-color: color-mix(in srgb, var(--mod) 60%, var(--outline)); }
.fold-cell .fic { font-size: 30px; line-height: 1.1; }
/* Ordnernamen dürfen umbrechen (bis zu zwei Zeilen), aber nicht die Kachel sprengen —
   „Versicherungsunterlagen" hat kein Leerzeichen zum Umbrechen, daher `anywhere`. */
.fold-cell .fname {
    font-weight: 600; font-size: 14px; line-height: 1.25; overflow-wrap: anywhere;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.fold-cell .fsub { font-size: 11px; color: var(--muted); }
.fold-new { border-style: dashed; color: var(--muted); }
.fold-new .fname { font-weight: 500; }
/* Trennt die Ordner von den Dateien derselben Ebene. */
.fold-sep { font-size: 13px; color: var(--muted); margin: 18px 2px 8px; }

/* ---- Spar-Tracker ---- */
.sav-head { text-align: center; }
.sav-big { font-size: 34px; font-weight: 700; letter-spacing: -.5px; }
/* Ampel: die Abweichung ist die zweitwichtigste Zahl nach dem Stand selbst. */
.sav-amp {
    display: inline-flex; align-items: center; gap: 10px; margin-top: 10px;
    padding: 5px 14px; border-radius: 999px; font-size: 14px; font-weight: 600;
    border: 1px solid transparent;
}
.sav-amp .pct { opacity: .75; font-weight: 500; }
.sav-amp.green  { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 45%, transparent); background: color-mix(in srgb, var(--ok) 12%, transparent); }
.sav-amp.yellow { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 45%, transparent); background: color-mix(in srgb, var(--warn) 12%, transparent); }
.sav-amp.red    { color: var(--error); border-color: color-mix(in srgb, var(--error) 45%, transparent); background: color-mix(in srgb, var(--error) 12%, transparent); }

.sav-row { display: flex; align-items: flex-start; gap: 12px; }
.sav-need {
    margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--outline);
    display: flex; flex-wrap: wrap; gap: 6px; font-size: 13px;
}
.sav-need.ok   { color: var(--ok); }
.sav-need.warn { color: var(--warn); }

/* Das Diagramm skaliert über die viewBox — die Zeichnung selbst rechnet in festen Maßen. */
.sav-chart { padding: 14px 10px 10px; }
.sav-svg { width: 100%; height: auto; display: block; overflow: visible; }
.sav-grid   { stroke: var(--outline); stroke-width: 1; }
.sav-axis   { fill: var(--muted); font-size: 11px; }
.sav-today  { stroke: var(--muted); stroke-width: 1; stroke-dasharray: 2 3; }
.sav-plan   { fill: none; stroke: var(--mod); stroke-width: 2.5; stroke-linejoin: round; }
.sav-fc     { fill: none; stroke: var(--muted); stroke-width: 2; stroke-dasharray: 6 4; }
.sav-actual-line { fill: none; stroke: var(--ok); stroke-width: 2; stroke-linejoin: round; }
.sav-actual-dot  { fill: var(--ok); }
.sav-ms line   { stroke: var(--warn); stroke-width: 2; }
.sav-ms circle { fill: var(--surface); stroke: var(--warn); stroke-width: 2; }
.sav-ms.done circle { fill: var(--warn); }

.sav-legend { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 10px; font-size: 12px; color: var(--muted); }
.sav-legend .lg { display: inline-flex; align-items: center; gap: 6px; }
.sav-legend .lg::before { content: ""; width: 16px; height: 3px; border-radius: 2px; background: currentColor; }
.sav-legend .plan::before   { background: var(--mod); }
.sav-legend .actual::before { background: var(--ok); }
.sav-legend .fc::before     { background: linear-gradient(90deg, var(--muted) 55%, color-mix(in srgb, var(--muted) 0%, transparent) 55%); }
.sav-legend .ms::before     { background: var(--warn); width: 9px; height: 9px; border-radius: 999px; }

/* Abgehakter Meilenstein: erledigt, aber nicht unsichtbar. */
.list-item.sav-done .title { text-decoration: line-through; opacity: .7; }

/* Hinweis direkt am Eingabefeld, wenn der gewählte Monat ausserhalb des Plans liegt. */
.sav-warn { color: var(--warn); margin-top: 6px; }
.sav-warn:empty { display: none; }
/* Karte für Einträge, die deshalb nirgends auftauchen. */
.sav-outside { border-color: color-mix(in srgb, var(--warn) 45%, transparent); background: color-mix(in srgb, var(--warn) 7%, transparent); }

/* ---- Ortssuche im Termin-Dialog (OpenStreetMap) ---- */
.geo-wrap { position: relative; }
.geo-hits {
    position: absolute; left: 0; right: 0; top: 100%; z-index: 5; margin-top: 4px;
    background: var(--surface2); border: 1px solid var(--outline); border-radius: 10px;
    max-height: 244px; overflow: auto; box-shadow: 0 10px 24px var(--scrim);
}
.geo-hit { padding: 9px 12px; cursor: pointer; }
/* Trennlinie NUR zwischen Treffern. Nicht als border-bottom je Treffer: der letzte stößt an die
   Namensnennung, die schon eine eigene Oberkante hat — das gäbe einen doppelten Strich. */
.geo-hit + .geo-hit { border-top: 1px solid var(--outline); }
.geo-hit:hover, .geo-hit.on { background: color-mix(in srgb, var(--accent) 14%, transparent); }
.geo-hit .t { font-size: 14px; line-height: 1.3; word-break: break-word; }
.geo-hit .s { font-size: 12px; color: var(--muted); margin-top: 2px; }
.geo-note { padding: 9px 12px; }
/* Die Namensnennung klebt unten an der Liste — sie darf beim Scrollen nicht verschwinden. */
.geo-attr {
    position: sticky; bottom: 0; padding: 5px 12px; font-size: 11px; color: var(--muted);
    background: var(--surface); border-top: 1px solid var(--outline);
}
.geo-coord { margin-top: 6px; }

/* ---- Beginn/Ende im Termin-Dialog: Datum + eigenes Uhrzeitfeld ---- */
/* Die Zeile darf umbrechen: auf Handybreite passen Datumsfeld, Uhrzeit und „entfernen"
   nicht nebeneinander — untereinander bleiben sie voll bedienbar. */
.dt-row { gap: 8px; margin-bottom: 2px; }
.dt-date { flex: 1 1 150px; min-width: 140px; }
.dt-time { flex: 0 1 116px; min-width: 96px; }
.dt-sum { color: var(--muted); margin-top: 6px; }
.dt-sum.warn { color: var(--warn); }
.dt-sum:empty { display: none; }

.tf-wrap { position: relative; }
.tf-hits {
    position: absolute; left: 0; right: 0; top: 100%; z-index: 6; margin-top: 4px;
    background: var(--surface2); border: 1px solid var(--outline); border-radius: 10px;
    max-height: 232px; overflow: auto; box-shadow: 0 10px 24px var(--scrim);
}
/* Die Liste ist schmal — die Dauer steht deshalb rechts und darf nicht umbrechen. */
.tf-opt {
    display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
    padding: 8px 10px; cursor: pointer; font-size: 14px; white-space: nowrap;
}
.tf-opt + .tf-opt { border-top: 1px solid var(--outline); }
.tf-opt:hover, .tf-opt.on { background: color-mix(in srgb, var(--accent) 14%, transparent); }
.tf-opt.sel { font-weight: 600; color: var(--mod); }
.tf-dur { font-size: 12px; color: var(--muted); }

/* ---- Datei in die Seite ziehen ---- */
/* `pointer-events: none` ist hier nicht optional: der Schleier liegt über allem, und ohne das
   käme das drop-Ereignis bei IHM an statt beim Dokument — der Browser würde die Datei dann
   einfach öffnen. */
.drop-veil {
    position: fixed; inset: 0; z-index: 70; display: none; place-items: center;
    background: var(--scrim); pointer-events: none;
}
.drop-veil.on { display: grid; }
.drop-box {
    text-align: center; padding: 28px 36px; border-radius: var(--radius);
    border: 2px dashed var(--accent); background: var(--surface);
    box-shadow: 0 12px 40px var(--shadow);
}
.drop-txt { font-size: 16px; margin-top: 6px; }

/* ---- Teilen: Links nach aussen ---- */
.share-h { margin: 18px 0 8px; font-size: 13px; color: var(--muted); font-weight: 600; }
.share-item { padding: 12px; margin-bottom: 8px; background: var(--surface2); }
/* Zurückgezogene und abgelaufene Links bleiben sichtbar, treten aber zurück. */
.share-tot { opacity: .55; }
/* Der Link ist lang und hat keine Leerzeichen — ohne Umbruch an jeder Stelle sprengt er den
   Dialog auf Handybreite. `anywhere` statt `break-all`, damit kurze Links am Stück bleiben. */
.share-url {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px;
    overflow-wrap: anywhere; color: var(--on); line-height: 1.4;
}

/* ============================================================================
 * SEITENLEISTE (nur im warmen Schema; die alten .tabs-Regeln bleiben unberührt daneben)
 * ============================================================================ */
/* Leiste und Inhalt bilden EINE zentrierte Gruppe (Vorbild: Rivok). Das ist der Unterschied,
 * der die Breitenfrage auflöst: der Rand links und rechts ist dann keine Lücke, die etwas
 * füllen müsste, sondern Teil des Bildes. */
/* Zwei Zeilen: die Kopfzeile läuft über BEIDE Spalten, darunter stehen Leiste und Inhalt
 * nebeneinander. Dadurch fluchtet die Oberkante der Leiste mit der des Inhalts — vorher begann
 * sie ganz oben, während der Inhalt erst unter der Begrüssung anfing, und die Leiste stand
 * sichtbar zu hoch. */
.shell {
    display: grid; grid-template-columns: 208px 1fr; gap: 16px;
    grid-template-areas: "kopf kopf" "leiste inhalt";
    /* `grid-template-rows` und `align-content: start` sind BEIDE nötig: zusammen mit
       `min-height: 100vh` verteilt der Grid-Standard (`align-content: stretch`) den freien Platz
       sonst auf die Zeilen — die Kopfzeile wurde dadurch 254 px hoch, obwohl ihr Inhalt 47 px misst,
       und schob den ganzen Aufbau nach unten. */
    grid-template-rows: auto 1fr;
    align-content: start;
    max-width: 1680px; margin: 0 auto; padding: 16px; min-height: 100vh;
}
.shell > .topbar { grid-area: kopf; }
.shell > .side { grid-area: leiste; }
.shell > .main { grid-area: inhalt; }
/* Datum als Pille in der Leiste, zwischen Marke und erstem Eintrag. Nimmt die Form der
   Navigationseinträge auf, ist aber ohne Zeigefinger — es ist eine Anzeige, kein Ziel. */
.side .datepill {
    margin: 2px 4px 12px; padding: 6px 12px; border-radius: 999px;
    background: var(--surface2); color: var(--muted);
    font-size: 12px; text-align: center; white-space: nowrap;
    overflow: hidden; text-overflow: ellipsis;
}
/* Die Leiste ist eine KARTE, keine randlose Spalte. Deshalb darf sie unten enden, wo ihr Inhalt
 * endet — bei einer randlosen Fläche sah genau das nach einem Abbruch aus, bei einer Karte ist
 * es gewollt. `align-self: start` ist hier also Absicht, nicht das alte Versehen. */
.side {
    background: var(--surface); border: 1px solid var(--outline); border-radius: 16px;
    position: sticky; top: 16px; align-self: start; max-height: calc(100vh - 32px);
    overflow-y: auto;
}
.side-inner { padding: 14px 10px; display: flex; flex-direction: column; gap: 2px; min-height: 0; }
/* `width: fit-content` + `margin: auto` statt nur `text-align: center`: der Farbverlauf wird auf
   die Textform beschnitten, und bei einem blockbreiten Element läge der Text mitten im Verlauf —
   sichtbar wäre dann nur dessen blasse Mitte statt des Übergangs von Violett nach Orange. */
.side .brand {
    font-weight: 800; font-size: 17px; padding: 2px 0 14px; letter-spacing: -.3px;
    width: fit-content; margin: 0 auto; text-align: center;
    background: linear-gradient(92deg, var(--c-cal), var(--c-meal));
    -webkit-background-clip: text; background-clip: text; color: transparent;
}
.side .item {
    display: flex; align-items: center; gap: 10px; padding: 9px 11px; border-radius: 10px;
    color: var(--muted); font-size: 14.5px; cursor: pointer; user-select: none;
    border: 1px solid transparent;
}
.side .item:hover { color: var(--on); background: var(--surface2); }
.side .item .dot { width: 8px; height: 8px; border-radius: 999px; background: var(--mod); flex: none; opacity: .5; }
.side .item.active {
    color: var(--on); font-weight: 600;
    background: color-mix(in srgb, var(--mod) 16%, transparent);
    border-color: color-mix(in srgb, var(--mod) 32%, transparent);
}
.side .item.active .dot { opacity: 1; box-shadow: 0 0 0 3px color-mix(in srgb, var(--mod) 22%, transparent); }
.side .sep { height: 1px; background: var(--outline); margin: 10px 6px; }
.side .spacer { flex: 1; }
.side .foot { padding: 10px 4px 0; margin-top: 10px; border-top: 1px solid var(--outline); }
/* Nutzerzeile am Fuss der Leiste — zeigt, wer angemeldet ist (bei Rivok die ELO-Karte). */
.side .who { display: flex; align-items: center; gap: 9px; padding: 4px 6px; }
.side .who .av {
    width: 30px; height: 30px; border-radius: 999px; flex: none;
    display: grid; place-items: center; font-size: 12px; font-weight: 700; color: var(--on-accent);
}
.side .who .nm { font-size: 13.5px; font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.side .who .rl { font-size: 11px; color: var(--muted); }
.side .abmelden { width: 100%; justify-content: center; margin-top: 8px; }

/* Der Deckel sitzt jetzt an der GRUPPE (.shell), nicht mehr am Inhalt — sonst käme ein zweiter
   Deckel dazu und der Inhalt rutschte innerhalb der eigenen Spalte noch einmal zusammen. */
.main { min-width: 0; }
.main .content { margin: 0; max-width: none; padding: 0; }
/* Kopfzeile ohne eigene Fläche — der Hintergrund dahinter ist ohnehin die Seite. */
.shell > .topbar {
    background: transparent; backdrop-filter: none; border-bottom: 0;
    padding: 0 0 4px; position: static; align-items: flex-start;
}

/* ============================================================================
 * ÜBERSICHT (Kacheln)
 * ============================================================================ */
/* `auto-fill` statt `auto-fit`: auto-fit zieht die vorhandenen Kacheln auf die volle Breite
   auseinander — bei sechs Kacheln auf einem breiten Monitor entstand daraus eine dünne Zeile.
   auto-fill lässt die Spaltenbreite stehen und bricht stattdessen um. */
.ov-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(290px, 1fr)); gap: 14px; }
.ov-w {
    background: var(--surface); border: 1px solid var(--outline); border-radius: 15px;
    padding: 15px; position: relative; overflow: hidden; cursor: pointer;
    /* Mindesthöhe, damit eine Kachel mit wenig Inhalt nicht zum Strich zusammenfällt und die
       Reihe unruhig wird. */
    min-height: 168px; display: flex; flex-direction: column;
}
.ov-w:hover { border-color: color-mix(in srgb, var(--mod) 45%, var(--outline)); }
/* Farbstreifen oben: das einzige Erkennungszeichen, welchem Modul die Kachel gehört. */
.ov-w::before { content: ""; position: absolute; inset: 0 0 auto 0; height: 3px; background: var(--mod); }
.ov-w h4 {
    margin: 0 0 3px; font-size: 11.5px; text-transform: uppercase;
    letter-spacing: .08em; color: var(--mod);
}
.ov-w .lead { font-size: 16.5px; font-weight: 650; margin: 6px 0 3px; line-height: 1.3; }
.ov-w .osub { color: var(--muted); font-size: 12.5px; line-height: 1.5; }
.ov-w.wide { grid-column: span 2; }
.ov-mini { display: flex; align-items: center; gap: 9px; padding: 5px 0; font-size: 13.5px; }
.ov-mini .d { width: 6px; height: 6px; border-radius: 999px; background: var(--mod); flex: none; }
.ov-mini .t { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ov-bar { height: 6px; border-radius: 99px; background: var(--surface2); overflow: hidden; margin-top: 10px; }
.ov-bar i { display: block; height: 100%; background: var(--mod); }
.ov-money { font-size: 21px; font-weight: 750; letter-spacing: -.3px; }
.ov-empty { color: var(--muted); font-size: 13px; }

@media (max-width: 560px) {
    .content { padding: 12px; }
    .hide-sm { display: none; }
    .cal-cellbg { min-height: 46px; }
    .grid2 { grid-template-columns: 1fr; }
    .note-grid { grid-template-columns: 1fr; }
    .ov-w.wide { grid-column: auto; }
}

/* Unter 900px wird die Seitenleiste zur unteren Leiste. Eine 216px-Spalte frisst auf einem
   Handy den halben Bildschirm, und die alte Pillenreihe hatte hier ihren Notausgang über
   flex-wrap — den hat eine Spalte nicht. */
@media (max-width: 900px) {
    /* Auf dem Handy wird aus der Karte die untere Leiste — dort ist eine 208px-Spalte nicht
       tragbar, und die alte Pillenreihe hatte hier ihren flex-wrap-Notausgang, den eine Spalte
       nicht hat. */
    .shell {
        grid-template-columns: 1fr; gap: 0; padding: 0; max-width: none;
        grid-template-areas: "kopf" "inhalt" "leiste";
    }
    .side {
        position: fixed; bottom: 0; left: 0; right: 0; top: auto; z-index: 40;
        max-height: none; border-radius: 0; border: 0; border-top: 1px solid var(--outline);
        overflow-x: auto; overflow-y: hidden;
    }
    .side-inner {
        flex-direction: row; padding: 6px 8px; gap: 4px;
        /* Nicht unter die Systemleiste rutschen (iPhone-Kinn). */
        padding-bottom: max(6px, env(safe-area-inset-bottom));
    }
    /* In der unteren Leiste ist kein Platz für die Datumspille — dort zählt jede Antippfläche. */
    .side .brand, .side .sep, .side .spacer, .side .foot, .side .datepill { display: none; }
    .side .item { flex: none; padding: 8px 12px; font-size: 13.5px; border-radius: 999px; }
    .main .content { padding: 0 12px; }
    .shell > .topbar { padding: 10px 12px 6px; }
    /* Platz für die Leiste, sonst verdeckt sie das letzte Element der Seite. */
    .main { padding-bottom: 76px; }
}

/* ---- Haushaltsbuch ----
   Nur zwei eigene Regeln: die Zeile in der Auswertung und ihr Balken. Alles andere kommt aus
   `.card`, `.list-item` und `.chip` — ein eigenes Aussehen fuer ein weiteres Modul waere genau
   die Art Sonderweg, die spaeter beim Umschalten der Farbschemen auffaellt. */
.fin-zeile { padding: 7px 0; cursor: pointer; border-bottom: 1px solid var(--outline); }
.fin-zeile:last-child { border-bottom: none; }
.fin-zeile:hover { background: color-mix(in srgb, var(--mod) 8%, transparent); }
.fin-bar { height: 6px; border-radius: 3px; background: var(--surface2); overflow: hidden; margin-top: 5px; }
.fin-bar > i { display: block; height: 100%; background: var(--mod); }

/* Periodenvergleich (Quartal, Jahr, freier Zeitraum).
   Die Tabelle scrollt in ihrem EIGENEN Kasten. Zwoelf Jahresspalten passen auf Florians
   3440-px-Monitor bequem, auf dem Handy nicht — und eine Seite, die als Ganzes seitwaerts
   rutscht, macht jede andere Ansicht mit unbenutzbar. */
.fin-tab-wrap { overflow-x: auto; margin: 0 -4px; }
.fin-tab { border-collapse: collapse; width: 100%; font-size: 14px; }
.fin-tab th, .fin-tab td { padding: 6px 8px; text-align: right; white-space: nowrap; }
.fin-tab th {
    font-weight: 600; font-size: 12px; color: var(--muted);
    border-bottom: 1px solid var(--outline); text-align: right;
}
/* Die Kategoriespalte bleibt beim Scrollen stehen — ohne sie weiss man in Spalte neun nicht
   mehr, welche Zeile man liest. */
.fin-tab-kat {
    position: sticky; left: 0; text-align: left !important;
    background: var(--surface); max-width: 190px; overflow: hidden; text-overflow: ellipsis;
}
.fin-tab thead .fin-tab-kat { background: var(--surface); }
.fin-tab-z { font-variant-numeric: tabular-nums; }
.fin-tab-z.leer { color: color-mix(in srgb, var(--muted) 55%, transparent); }
/* Der auffaelligste Wert der Zeile: das ist der Ausreisser, um den es beim Vergleich geht. */
.fin-tab-z.spitze { font-weight: 600; color: var(--mod); }
.fin-tab-sum {
    font-variant-numeric: tabular-nums; font-weight: 600;
    border-left: 1px solid var(--outline);
}
.fin-tab-zeile { cursor: pointer; }
.fin-tab-zeile:hover td { background: color-mix(in srgb, var(--mod) 8%, transparent); }
.fin-tab-zeile:hover .fin-tab-kat { background: color-mix(in srgb, var(--mod) 8%, var(--surface)); }
.fin-tab-fuss td { border-top: 1px solid var(--outline); font-weight: 600; padding-top: 8px; }

/* Die drei Summenkacheln führen auf ihre Posten — das muss man ihnen ansehen. */
.fin-kachel { cursor: pointer; transition: border-color .12s, transform .12s; }
.fin-kachel:hover { border-color: var(--mod); transform: translateY(-1px); }
