/* ==========================================================================
   iCash — Stylesheet (Neugestaltung 19.08.2026)
   Reines CSS, kein Framework, kein Build, keine externe Abhaengigkeit.

   WAS SICH GEGENUEBER DER FASSUNG VOM 03.08.2026 AENDERT

   1  Ebenen statt einer Flaeche.  Vorher lagen Grund, Karte, eingebettete
      Karte und Kopfzeile alle auf nahezu demselben Ton (#0f1013 / #1c1d20).
      Ein Bildschirm ohne Tiefenstaffelung liest sich als eine einzige lange
      Flaeche - man findet den Anfang eines Blocks nur ueber die Schriftgroesse.
      Jetzt drei klar getrennte Stufen plus Schatten (hell) bzw. Rand (dunkel).

   2  Farbe traegt Bedeutung, sichtbar.  Die Kategorie stand als 8-px-Punkt
      am Zeilenanfang - auf Armlaenge nicht unterscheidbar. Sie steht jetzt
      als getoentes Rundzeichen mit Symbol: dieselbe Information, aus einem
      Meter Entfernung lesbar, und sie macht eine Liste ueberfliegbar.

   3  Weniger Hoehe.  "Heute" war 2.900 px hoch. Die fuenf Ledger-Zeilen -
      Zahlen, die man abliest und nie anfasst - sind zu drei Kennzahlfeldern
      geworden, die zugleich Sprungziele sind. Die Bewegungsliste ist nach
      Tagen gruppiert statt in einer 6er-Kolonne ohne Zaesur.

   4  Erfassen zuerst.  Die Leitzahl schrumpft ausserhalb von "Heute" zu
      einer schmalen Zeile. Auf dem Startbild "Erfassen" standen vorher
      300 px Kennzahl ueber dem Feld, in das man tippen wollte.

   5  Ein Farbschema, vier Auspraegungen (data-skin auf <html>), dazu
      automatisch hell/dunkel nach Systemeinstellung. Wer nichts setzt,
      bekommt "marke".

   AUFBAU — in dieser Reihenfolge lesen
     1  Schriften
     2  Tokens          Farbwelten, Masse, Radien
     3  Grundlagen      Reset und Elementstile
     4  Grammatik       .view .panel .split
     5  Text            Titel, Kennzahlen, Hinweise
     6  Eingaben        Felder, Knoepfe, Schalter
     7  Listen          das vom JavaScript erzeugte Markup
     8  Rahmen          Seitenleiste, Bottom-Navigation, Kontomenue
     9  Bereiche        Leitzahl, Kennzahlen, Kalender, Diagramme
    10  Overlays        Dialog, Hinweis, Toast
    11  Bausteine
    12  Anmeldung

   REGELN, die aus Fehlern dieses Projekts stammen und weiter gelten
     - Ein Eingabefeld ist so breit wie die erwartete Eingabe.
     - Die Aktion steht bei den Feldern, nicht am rechten Rand.
     - Eine folgenreiche Warnung steht VOR der Aktion, in Signalfarbe.
     - Genau eine Hero-Zahl je Ansicht.
     - Abstaende kommen aus --rhythm, nie aus dem Panel selbst.
     - Farbe bedeutet Kategorie oder Zustand - nie Dekoration.
     - Neu: Der Akzent gehoert dem, was man anfassen kann. Was Geld bewegt,
       traegt --positive oder --negative, nie den Akzent.
   ========================================================================== */

/* ---------------------------------------------------------------- 1 Schriften */

@font-face {
  font-family: "InterLocal";
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url("../assets/fonts/inter-latin-wght-normal.woff2") format("woff2-variations");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Bleibt eingebunden, damit vorhandene Verweise nicht ins Leere laufen.
   Benutzt wird sie nicht mehr: Eine Serifenschrift ueber einem Messwert
   liest sich als Zeitschrift, nicht als Werkzeug. Die Titel tragen jetzt
   dieselbe Schrift wie die Zahlen, nur enger gesetzt. */
@font-face {
  font-family: "FrauncesLocal";
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url("../assets/fonts/fraunces-latin-wght-normal.woff2") format("woff2-variations");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ------------------------------------------------------------------ 2 Tokens */

/* Masse, Schrift und Kurven sind in allen Farbwelten gleich - nur die Farben
   wechseln. Wer ein Mass aendert, aendert es ueberall. */
:root {
  --font-sans: "InterLocal", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --rhythm: 1rem;         /* vertikaler Abstand zwischen Bloecken            */
  --pad: 1.125rem;        /* Innenabstand jeder Flaeche                      */
  --radius-lg: 1.25rem;   /* Karte                                           */
  --radius: 0.875rem;     /* eingebettete Flaeche, Knopf                     */
  --radius-sm: 0.625rem;  /* Kleinteil                                       */
  --w-form: 34rem;        /* Blickspanne fuer Beschriftung + Eingabe         */
  --w-sidebar: 15rem;
  --touch: 2.75rem;       /* Mindestgroesse fuer alles, was ein Finger trifft */

  --ease: cubic-bezier(.22, 1, .36, 1);
}

/* --- Farbwelt "marke" (Vorgabe) -----------------------------------------
   Behaelt den Weinton des App-Zeichens, gibt ihm aber einen Grund, auf dem
   er wirkt: waermeres Anthrazit statt Neutralgrau, klar getrennte Ebenen.
   Der Weinton allein ist als Text zu dunkel (2,3:1) - dafuer gibt es
   --accent-text, denselben Farbton aufgehellt. */
:root,
[data-skin="marke"] {
  color-scheme: dark;

  --bg:        #121316;   /* Grund                                       */
  --bg-soft:   #191b1f;   /* eingesenkte Flaeche, Eingabefeld             */
  --surface:   #1e2025;   /* Karte                                       */
  --surface-2: #272a31;   /* Karte auf Karte, Spur eines Balkens         */
  --surface-3: #33373f;   /* Zustand: gedrueckt, ueberfahren             */

  --accent:        #b02742;
  --accent-strong: #c72e4c;
  --accent-soft:   rgba(199, 46, 76, .18);
  --accent-text:   #f08099;
  --on-accent:     #ffffff;

  --positive:  #4ec77a;   /* Geld kommt rein, unter Budget                */
  --negative:  #f26d6d;   /* Geld geht raus in gefaehrlicher Hoehe        */
  --signal:    #efac44;   /* faellig, Warnung, folgenreiche Aktion        */

  --ink-strong: #ffffff;
  --ink:        #eceef1;
  --ink-2:      #a9adb5;
  --ink-faint:  #7d818a;

  --line:        rgba(255, 255, 255, .10);
  --line-soft:   rgba(255, 255, 255, .06);
  --line-strong: rgba(255, 255, 255, .20);

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .40);
  --shadow:    0 2px 4px rgba(0, 0, 0, .35), 0 12px 32px -18px rgba(0, 0, 0, .8);
  --shadow-lg: 0 8px 40px -12px rgba(0, 0, 0, .75);
}

/* --- Farbwelt "hell" ----------------------------------------------------
   Der klassische Zuschnitt heutiger Finanz-Apps: heller, leicht kuehler
   Grund, weisse Karten mit Schatten statt Rand, ein tiefes Petrol als
   Akzent. Petrol statt Blau, weil Blau in Diagrammen schon eine Kategorie
   ist - der Akzent darf mit keiner Bedeutung kollidieren. */
[data-skin="hell"] {
  color-scheme: light;

  --bg:        #f2f4f7;
  --bg-soft:   #ffffff;
  --surface:   #ffffff;
  --surface-2: #f0f2f5;
  --surface-3: #e3e7ec;

  --accent:        #0f766e;
  --accent-strong: #0b5f59;
  --accent-soft:   rgba(15, 118, 110, .12);
  --accent-text:   #0b5f59;
  --on-accent:     #ffffff;

  --positive:  #15803d;
  --negative:  #c2334d;
  --signal:    #b45309;

  --ink-strong: #0d1117;
  --ink:        #23272f;
  --ink-2:      #5b6270;
  --ink-faint:  #838b98;

  --line:        rgba(13, 17, 23, .10);
  --line-soft:   rgba(13, 17, 23, .06);
  --line-strong: rgba(13, 17, 23, .20);

  --shadow-sm: 0 1px 2px rgba(13, 17, 23, .06);
  --shadow:    0 1px 3px rgba(13, 17, 23, .07), 0 8px 24px -12px rgba(13, 17, 23, .16);
  --shadow-lg: 0 12px 40px -12px rgba(13, 17, 23, .22);
}

/* --- Kategoriefarben ----------------------------------------------------
   Uebernommen aus tools/palette.py und unveraendert: gleiche Saettigung
   gedeckelt, Helligkeit gestaffelt, Paarabstand unter Normalsicht UND unter
   allen drei Formen der Farbfehlsichtigkeit geprueft (8,9 - die
   Vorgaengertafel fiel unter Rotgruenblindheit auf 1,6 zusammen).
   Wer hier einen Wert von Hand aendert, umgeht die Pruefung.

   Neu sind nur --cat-6 bis --cat-8: Der Satz reichte fuer fuenf Kategorien,
   danach begann er von vorn und zwei Kategorien trugen denselben Ton. */
:root {
  --cat-1: #68aceb;      /* Blau       */
  --cat-2: #c36e59;      /* Terrakotta */
  --cat-3: #80d3a4;      /* Gruen      */
  --cat-4: #9478c4;      /* Violett    */
  --cat-5: #cd8aa9;      /* Altrosa    */
  --cat-6: #d8b25e;      /* Ocker      */
  --cat-7: #6fc4c0;      /* Petrol     */
  --cat-8: #a2b06a;      /* Oliv       */
  --cat-none: #8d9198;   /* "ohne Kategorie" ist bewusst unbunt */

  /* Zustand "im Rahmen". Unbunt, und das ist der Punkt: Farbe im Balken
     bedeutet genau eine Sache - es reicht nicht mehr. */
  --state-ok: var(--ink-2);
}

/* In der hellen Welt sind die Kategorietoene fuer weissen Grund zu blass -
   sie sind gegen dunklen Grund gerechnet. Hier dieselbe Reihenfolge, eine
   Stufe tiefer, damit der Kontrast gegen Weiss stimmt. */
[data-skin="hell"] {
  --cat-1: #2f74b5;
  --cat-2: #a44b34;
  --cat-3: #2c8f5e;
  --cat-4: #6a4ba0;
  --cat-5: #a85379;
  --cat-6: #97701c;
  --cat-7: #217e7a;
  --cat-8: #5f7028;
  --cat-none: #6b7280;
}

/* -------------------------------------------------------------- 3 Grundlagen */

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

html { -webkit-text-size-adjust: 100%; }

body {
  font-family: var(--font-sans);
  font-size: 1rem;
  line-height: 1.5;
  color: var(--ink);
  background-color: var(--bg);
  -webkit-font-smoothing: antialiased;
  min-height: 100dvh;
}

img, svg { display: block; max-width: 100%; }
button, input, select, textarea { font: inherit; color: inherit; }
button { background: none; border: 0; cursor: pointer; }
a { color: inherit; }
ul, ol { list-style: none; padding: 0; }

:focus-visible {
  outline: 2px solid var(--accent-strong);
  outline-offset: 2px;
}

[hidden], .hidden { display: none !important; }

.icon { width: 1.125rem; height: 1.125rem; flex: none; fill: currentColor; }

.text-soft { color: var(--ink-2); }
.text-muted { color: var(--ink-faint); }
.divider { height: 1px; background-color: var(--line); }

/* Alles, was ein Finger trifft, verschluckt den 300-ms-Tap-Verzug und den
   grauen Aufleuchter, den Android sonst darueberlegt. */
button, a, input, select, label, [role="button"] {
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

/* -------------------------------------------------------------- 4 Grammatik */

.view { display: flex; flex-direction: column; gap: var(--rhythm); }
.view-head { display: flex; flex-direction: column; gap: .25rem; }

/* Auf "Heute" ist der Titel ausgeblendet, weil die Navigation ihn nennt.
   Der leere Kopf erzeugte trotzdem seinen Abstand - sichtbar als Loch. */
/* Entfallen am 23.08.2026: .tab-title-redundant blendete den Bereichstitel
   aus, weil die Navigation den Bereich ohnehin benannte. Seit dem Makeover
   liegen mehrere Abschnitte in einem Bereich - dort ist jeder Titel noetig,
   um den Anfang eines Abschnitts zu finden. */

/* Die Karte. Schatten statt Rand in der hellen Welt, Rand statt Schatten
   in den dunklen - eine Kante braucht dort mehr Trennkraft als ein
   Schlagschatten, den man auf Schwarz ohnehin nicht sieht. */
.panel, .panel-card {
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background-color: var(--surface);
  box-shadow: var(--shadow-sm);
  padding: var(--pad);
  min-width: 0;
}

[data-skin="hell"] .panel,
[data-skin="hell"] .panel-card { border-color: transparent; box-shadow: var(--shadow); }

.panel--form { max-width: var(--w-form); }
.split .panel--form { max-width: none; }
.panel--data { width: 100%; }

/* Eingebettete Flaeche liegt eine Stufe tiefer, nicht heller - sonst
   konkurriert sie mit ihrem Traeger. */
.panel--sunken {
  background-color: var(--bg-soft);
  border-color: var(--line-soft);
  box-shadow: none;
  border-radius: var(--radius);
}

[data-skin="hell"] .panel--sunken { background-color: var(--surface-2); border-color: var(--line-soft); }

.panel-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: .25rem .75rem;
  padding-bottom: .75rem;
  border-bottom: 1px solid var(--line-soft);
  margin-bottom: .75rem;
}

.panel-title { font-size: .9375rem; font-weight: 650; letter-spacing: -.01em; color: var(--ink-strong); }
.panel-sub { margin-bottom: .75rem; font-size: .8125rem; color: var(--ink-faint); }

/* Steht die Beschreibung im Kopf, bekommt sie eine eigene Zeile: Der Kopf
   verteilt seine Kinder auf die Aussenkanten - richtig fuer "Titel links,
   Kennzahl rechts", falsch fuer einen Beschreibungssatz. */
.panel-head .panel-sub { flex-basis: 100%; margin-bottom: 0; }

.panel-meta {
  font-size: .75rem;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.panel-body { min-width: 0; }
.panel-empty { padding: 1.25rem 0; font-size: .8125rem; color: var(--ink-faint); }

.panel-filter {
  display: flex;
  flex-direction: column;
  gap: .375rem;
  margin-bottom: .875rem;
  max-width: 22rem;
}

.panel-filter label { font-size: .75rem; font-weight: 500; color: var(--ink-faint); }

/* Die EINE Zweispaltigkeit. Links Steuerung in fester Breite, rechts Daten.
   Die Steuerung waechst nicht mit: Ein Eingabefeld wird nicht besser, wenn
   es breiter wird, eine Liste schon. */
.split {
  display: grid;
  gap: var(--rhythm);
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
}

@container main (min-width: 58rem) {
  .split { grid-template-columns: var(--w-form) minmax(0, 1fr); }
  .split--even { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ------------------------------------------------------------------- 5 Text */

.view-title {
  font-size: clamp(1.375rem, 5vw, 1.75rem);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -.025em;
  color: var(--ink-strong);
}

.view-sub { font-size: .875rem; color: var(--ink-faint); max-width: 60ch; }

/* Die eine Hero-Zahl je Ansicht. Proportionale Ziffern: tabular-nums gibt
   jeder Ziffer die Breite einer Null und reisst bei 52 px Luecken. */
.balance-hero-amount {
  font-size: clamp(2.75rem, 12vw, 3.5rem);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -.035em;
  font-variant-numeric: proportional-nums;
  color: var(--ink-strong);
}

.balance-hero-label,
.stat-label,
.account-section-title,
.overline {
  font-size: .6875rem;
  font-weight: 650;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.figure-lead {
  margin-bottom: .875rem;
  font-size: clamp(1.75rem, 7vw, 2.125rem);
  font-weight: 700;
  letter-spacing: -.03em;
  color: var(--ink-strong);
  font-variant-numeric: proportional-nums;
}

/* Die Leitzahl faerbt sich erst, wenn sie etwas zu sagen hat. Ein grosser
   Betrag in Signalfarbe, obwohl alles in Ordnung ist, stumpft ab. */
.balance-value-neutral, .balance-value-good, .balance-value-medium { color: var(--ink-strong); }
.balance-value-low { color: var(--signal); }
.balance-value-negative { color: var(--negative); }

/* Hinweiszeilen. Getoenter Grund statt nur einer Kante: Ein 3-px-Strich
   links traegt bei 13-px-Text zu wenig, um vor einer Aktion zu warnen. */
.notice {
  padding: .6875rem .875rem;
  border-radius: var(--radius);
  border: 1px solid var(--line-soft);
  border-left: 3px solid var(--line-strong);
  background-color: var(--bg-soft);
  font-size: .8125rem;
  line-height: 1.45;
  color: var(--ink);
}

[data-skin="hell"] .notice { background-color: var(--surface-2); }

.notice--signal {
  border-left-color: var(--signal);
  background-color: color-mix(in srgb, var(--signal) 10%, var(--surface));
  border-color: color-mix(in srgb, var(--signal) 24%, transparent);
}

.notice--info {
  border-left-color: var(--cat-1);
  background-color: color-mix(in srgb, var(--cat-1) 9%, var(--surface));
  border-color: color-mix(in srgb, var(--cat-1) 22%, transparent);
  color: var(--ink);
}

.header-progress {
  font-size: .8125rem;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---------------------------------------------------------------- 6 Eingaben */

.input {
  width: 100%;
  min-height: var(--touch);
  padding: .5rem .8125rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background-color: var(--bg-soft);
  color: var(--ink);
  transition: border-color .15s var(--ease), box-shadow .15s var(--ease), background-color .15s var(--ease);
}

[data-skin="hell"] .input { background-color: var(--surface-2); }

.input::placeholder { color: var(--ink-faint); }
.input:hover { border-color: var(--line-strong); }

.input:focus-visible {
  border-color: var(--accent-strong);
  box-shadow: 0 0 0 3px var(--accent-soft);
  outline: none;
}

select.input {
  appearance: none;
  padding-right: 2.25rem;
  background-image: linear-gradient(45deg, transparent 50%, var(--ink-2) 50%),
                    linear-gradient(135deg, var(--ink-2) 50%, transparent 50%);
  background-position: right 1.125rem center, right .875rem center;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}

/* Betragsfelder sind Ziffernfelder: groesser, halbfett, mit Tabellenziffern.
   Der Betrag ist in jeder Maske dieser App das eine Feld, auf das es
   ankommt - er darf aussehen wie eine Zahl, nicht wie ein Textfeld. */
.field--amount .input {
  font-size: 1.125rem;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
}

.capture-form { max-width: var(--w-form); }
.split .capture-form { max-width: none; }

.capture-fields { display: grid; grid-template-columns: minmax(0, 1fr); gap: .875rem; }

@media (min-width: 560px) {
  .capture-fields { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .field--wide { grid-column: 1 / -1; }
  .field--amount { max-width: 11rem; }
}

.field { display: flex; flex-direction: column; gap: .375rem; min-width: 0; }
.field label { font-size: .8125rem; font-weight: 550; color: var(--ink-2); }

.capture-fields.panel--sunken { grid-column: 1 / -1; padding: .875rem; }

.capture-actions { display: flex; justify-content: flex-start; margin-top: 1.25rem; }

/* Auf dem Handy fuellt die Hauptaktion die Zeile: Ein 140 px breiter Knopf
   in einer 358 px breiten Spalte laesst offen, wo man hintippen soll. */
@media (max-width: 559px) {
  .capture-actions { display: block; }
  .capture-actions .btn-primary { width: 100%; }
}

.capture-form + .panel-filter { margin-top: 1.75rem; }

.inline-form { display: flex; flex-wrap: wrap; gap: .625rem; margin-bottom: .875rem; }
.inline-form .input { flex: 1 1 12rem; }

/* Schalterzeile. Statt eines Kaestchens ein echter Kippschalter: Ein
   Haekchen sagt "ausgewaehlt", ein Schalter sagt "an oder aus" - und genau
   das ist hier gemeint. */
.switch-row {
  display: flex;
  align-items: center;
  gap: .75rem;
  margin-bottom: 1rem;
  font-size: .875rem;
  font-weight: 550;
  color: var(--ink);
  cursor: pointer;
}

.switch-row input[type="checkbox"] {
  appearance: none;
  position: relative;
  width: 2.75rem;
  height: 1.625rem;
  flex: none;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  background-color: var(--surface-2);
  transition: background-color .18s var(--ease), border-color .18s var(--ease);
}

.switch-row input[type="checkbox"]::after {
  content: "";
  position: absolute;
  top: 50%;
  left: .1875rem;
  width: 1.125rem;
  height: 1.125rem;
  border-radius: 999px;
  background-color: var(--ink-2);
  transform: translateY(-50%);
  transition: transform .18s var(--ease), background-color .18s var(--ease);
}

.switch-row input[type="checkbox"]:checked {
  background-color: var(--accent);
  border-color: var(--accent);
}

.switch-row input[type="checkbox"]:checked::after {
  transform: translateY(-50%) translateX(1.0625rem);
  background-color: var(--on-accent);
}

/* Knoepfe */
.btn-primary, .btn-secondary, .quick-chip, .capture-mode-btn, .icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  border-radius: var(--radius);
  font-weight: 550;
  transition: background-color .15s var(--ease), border-color .15s var(--ease),
              color .15s var(--ease), transform .1s var(--ease);
}

.btn-primary, .btn-secondary {
  min-height: var(--touch);
  padding: 0 1.125rem;
  font-size: .875rem;
  border: 1px solid transparent;
}

.btn-primary {
  background-color: var(--accent);
  color: var(--on-accent);
  font-weight: 650;
  box-shadow: var(--shadow-sm);
}

.btn-primary:hover { background-color: var(--accent-strong); }
.btn-primary:active { transform: translateY(1px); }

.btn-secondary { background-color: var(--surface-2); border-color: var(--line); color: var(--ink); }
.btn-secondary:hover { border-color: var(--line-strong); background-color: var(--surface-3); }
.btn-secondary:active { transform: translateY(1px); }

.btn-primary:disabled, .btn-secondary:disabled { opacity: .5; cursor: not-allowed; transform: none; }

.icon-btn {
  width: 2.25rem;
  height: 2.25rem;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background-color: transparent;
  color: var(--ink-faint);
}

.icon-btn:hover { color: var(--ink-strong); background-color: var(--surface-2); }

/* Typwechsler. Ein Schieber unter dem aktiven Feld statt einer gefaerbten
   Flaeche: Vier gleich grosse Farbflaechen nebeneinander konkurrieren mit
   dem Speichern-Knopf darunter, der dieselbe Farbe traegt. */
.capture-modes {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: .1875rem;
  width: 100%;
  max-width: 30rem;
  padding: .25rem;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  background-color: var(--bg-soft);
  margin-bottom: 1rem;
}

[data-skin="hell"] .capture-modes { background-color: var(--surface-2); }

.capture-mode-btn {
  min-height: 2.375rem;
  padding: 0 .375rem;
  border-radius: calc(var(--radius) - .25rem);
  color: var(--ink-2);
  font-size: .8125rem;
}

.capture-mode-btn:hover { color: var(--ink-strong); }

.capture-mode-btn[data-active="true"] {
  background-color: var(--surface);
  color: var(--ink-strong);
  font-weight: 650;
  box-shadow: var(--shadow-sm);
}

[data-skin="hell"] .capture-mode-btn[data-active="true"] { background-color: #fff; }

/* Schnellbuttons ueber den Feldern. Waagerecht scrollend statt umbrechend:
   Die Leiste bleibt eine Zeile hoch, egal ob zwei oder zwoelf Eintraege da
   sind - sonst schiebt sie die Felder aus dem Bild. */
.quick-strip {
  display: flex;
  gap: .375rem;
  margin-bottom: 1rem;
  padding-bottom: .25rem;
  overflow-x: auto;
  scrollbar-width: none;
  scroll-snap-type: x proximity;
}

.quick-strip::-webkit-scrollbar { display: none; }

.quick-chip {
  display: inline-flex;
  align-items: baseline;
  gap: .4375rem;
  flex: 0 0 auto;
  min-height: 2.375rem;
  padding: 0 .875rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background-color: var(--bg-soft);
  color: var(--ink);
  font-size: .875rem;
  scroll-snap-align: start;
}

[data-skin="hell"] .quick-chip { background-color: var(--surface-2); }

.quick-chip:hover { border-color: var(--accent); background-color: var(--accent-soft); }
.quick-chip:active { transform: scale(.97); }

.quick-chip-label { font-weight: 550; }

.quick-chip-amount {
  font-size: .8125rem;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

/* Der Anlegen-Chip ist eine Einladung, keine Buchung: gestrichelt und ohne
   Flaeche, damit er nicht wie ein weiterer Betrag aussieht. */
.quick-chip-add {
  align-items: center;
  border-style: dashed;
  background-color: transparent;
  color: var(--ink-2);
}

.quick-chip-add:hover { color: var(--ink-strong); border-color: var(--line-strong); background-color: transparent; }

/* ----------------------------------------------------------------- 7 Listen */

/* Markup aus assets/js/dashboard.js. Eine Zeile: Zeichen, Text, Betrag,
   Aktionen.

   Das Zeichen war ein 8-px-Punkt in Kategoriefarbe. Auf Armlaenge war das
   ein Fleck - man konnte die Kategorie nicht ablesen, nur ahnen, dass da
   eine ist. Es ist jetzt ein getoentes Rundzeichen von 36 px mit Symbol:
   dieselbe Information, aus einem Meter lesbar, und es gibt der Liste einen
   linken Rand, an dem das Auge herunterlaeuft. Die Farbe kommt weiter aus
   dem style-Attribut, das der Renderer setzt - der Vertrag bleibt. */
.entry-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  align-items: center;
  gap: .75rem;
  padding: .625rem 0;
  border-top: 1px solid var(--line-soft);
}

.entry-row:first-child { border-top: 0; }

/* Der Punkt wird zum Rundzeichen mit dem Anfangsbuchstaben der Kategorie.

   Der Renderer liefert den Kategorieton nicht mehr als background-color,
   sondern als Eigenschaft --cat. Grund: Aus einer deckenden Flaeche laesst
   sich kein getoenter Grund plus lesbarer Buchstabe ableiten - aus einem
   Farbwert schon. Faellt --cat aus, greift --cat-none, und die Zeile sieht
   aus wie eine ohne Kategorie. Nichts bricht. */
.entry-row-dot {
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  flex: none;
  border-radius: 999px;
  background-color: color-mix(in srgb, var(--cat, var(--cat-none)) 18%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--cat, var(--cat-none)) 32%, transparent);
  color: var(--cat, var(--cat-none));
  font-size: .8125rem;
  font-weight: 700;
  line-height: 1;
  text-transform: uppercase;
  overflow: hidden;
}

/* In der hellen Welt sind 18 % gegen Weiss zu wenig - der Buchstabe stuende
   auf einem Hauch. Gegen Dunkel ist derselbe Wert genau richtig. */
[data-skin="hell"] .entry-row-dot {
  background-color: color-mix(in srgb, var(--cat, var(--cat-none)) 13%, #fff);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--cat, var(--cat-none)) 22%, transparent);
}

.entry-row-body { display: flex; flex-direction: column; gap: .0625rem; min-width: 0; }

.entry-row-name {
  font-size: .9375rem;
  font-weight: 600;
  letter-spacing: -.005em;
  color: var(--ink-strong);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.entry-row-meta {
  font-size: .75rem;
  color: var(--ink-faint);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.entry-row-amount {
  font-size: .9375rem;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
  white-space: nowrap;
  color: var(--ink-strong);
}

.entry-row-amount-in { color: var(--positive); }
.entry-row-amount-out { color: var(--ink-strong); }
.entry-row-amount-due { color: var(--ink-strong); }
.cash-entry-amount { font-variant-numeric: tabular-nums; }

.entry-row-actions { display: flex; gap: .125rem; }

.entry-row-actions button {
  width: 2rem;
  height: 2rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: .5rem;
  color: var(--ink-faint);
  transition: color .15s var(--ease), background-color .15s var(--ease);
}

.entry-row-actions button:hover { color: var(--ink-strong); background-color: var(--surface-2); }

/* Auf dem Handy teilen sich Zeichen, Name, Betrag und zwei Knoepfe 326 px.
   Mit den Desktop-Massen blieben fuer den Namen 96 px - "Wochenmarkt" wurde
   zu "Wochenma...". Zeichen und Knoepfe geben hier jeweils ein Stueck ab;
   die Trefferflaeche der Knoepfe bleibt ueber padding erhalten. */
@media (max-width: 559px) {
  .entry-row { gap: .625rem; }
  .entry-row-dot { width: 2rem; height: 2rem; font-size: .75rem; }
  .entry-row-actions { gap: 0; }
  .entry-row-actions button { width: 1.875rem; height: 2.25rem; border-radius: .4375rem; }
  .entry-row-actions button .icon { width: 1rem; height: 1rem; }
}

/* Gerade gespeichert. Kurz getoent, damit man sieht, wo der Eintrag gelandet
   ist - nicht dauerhaft, sonst wird die Markierung zur Dekoration. */
.entry-highlight {
  background-color: var(--accent-soft);
  border-radius: var(--radius);
  box-shadow: 0 0 0 .5rem var(--accent-soft);
}

/* Bargeldbuchung: gleiche vier Spalten, nur ohne Kategoriefarbe. */
.cash-entry .entry-row-dot { background-color: var(--cat-none); }

/* Kennzeichen tragen Woerter - "heute", "in 5 Tagen". */
.entry-chip {
  display: inline-block;
  padding: .0625rem .4375rem;
  border-radius: .375rem;
  background-color: var(--surface-2);
  color: var(--ink-2);
  font-size: .6875rem;
  font-weight: 550;
  white-space: nowrap;
}

/* Heute oder morgen faellig ist der einzige Zustand, der aus der Liste
   heraussticht. Den Namen .entry-chip-soon vergibt renderHomeTab() in
   assets/js/dashboard.js seit dem 03.08.2026 - eine Regel dazu gab es bis
   zum 19.08.2026 nicht, das Kennzeichen sah also aus wie jedes andere.
   Genau das sollte die Klasse verhindern. */
.entry-chip-soon {
  background-color: color-mix(in srgb, var(--signal) 18%, transparent);
  color: var(--signal);
}

.card-soft {
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  background-color: var(--bg-soft);
  padding: .875rem;
}

[data-skin="hell"] .card-soft { background-color: var(--surface-2); }

/* Messbalken. Der Balken kennt zwei Zustaende: im Rahmen und darueber.
   "Darueber" traegt Bernstein, nicht Rot - Rot ist in "marke" die
   Markenfarbe und saesse sonst gleichzeitig auf Knopf und Warnung. */
.meter-idle, .meter-good, .meter-bad {
  height: 100%;
  border-radius: 999px;
  transition: width .5s var(--ease), background-color .3s var(--ease);
}

.meter-idle { background-color: var(--line-strong); }
.meter-good { background-color: var(--state-ok); }
.meter-bad  { background-color: var(--signal); }

/* Tagesgruppe in einer Bewegungsliste. Sechs Zeilen ohne Zaesur liest man
   als Block; mit Datumszeile liest man sie als Verlauf. Der Renderer darf
   die Gruppe weglassen - dann faellt die Liste auf ihr altes Verhalten
   zurueck, ohne dass etwas bricht. */
.day-group + .day-group { margin-top: .25rem; }

.day-group-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: .75rem;
  padding: .75rem 0 .375rem;
  border-top: 1px solid var(--line-soft);
}

.day-group:first-child .day-group-head { border-top: 0; padding-top: 0; }

.day-group-label {
  font-size: .6875rem;
  font-weight: 650;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.day-group-sum {
  font-size: .75rem;
  font-weight: 600;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}

.day-group .entry-row:first-child { border-top: 0; }

/* ----------------------------------------------------------------- 8 Rahmen */

.app-shell {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  min-height: 100dvh;
  position: relative;
  overflow-x: hidden;
}

@media (min-width: 1024px) {
  .app-shell {
    grid-template-columns: var(--w-sidebar) minmax(0, 1fr);
    background-image: linear-gradient(
      to right,
      var(--bg-soft) 0 var(--w-sidebar),
      var(--line) var(--w-sidebar) calc(var(--w-sidebar) + 1px),
      transparent calc(var(--w-sidebar) + 1px)
    );
  }
}

.app-main {
  /* Bezugsgroesse fuer alle Umbrueche im Inhalt: gemessen wird, was nach
     der Seitenleiste wirklich da ist, nicht die Fensterbreite. */
  container-type: inline-size;
  container-name: main;

  display: flex;
  flex-direction: column;
  gap: var(--rhythm);
  min-width: 0;
  width: 100%;
  padding-top: calc(1rem + env(safe-area-inset-top));
  padding-right: calc(1rem + env(safe-area-inset-right));
  padding-bottom: calc(6rem + env(safe-area-inset-bottom));
  padding-left: calc(1rem + env(safe-area-inset-left));
}

@media (min-width: 640px) { .app-main { padding-left: 1.5rem; padding-right: 1.5rem; } }
@media (min-width: 1024px) { .app-main { padding: 2rem 2rem 3rem; } }

/* Seitenleiste ab 1024 px. Alle zehn Bereiche dauerhaft sichtbar. */
.app-sidebar {
  display: none;
  position: sticky;
  top: 0;
  height: 100dvh;
  flex-direction: column;
  gap: 1.5rem;
  padding: 1.5rem 1rem;
  overflow-y: auto;
}

@media (min-width: 1024px) { .app-sidebar { display: flex; } }

.sidebar-brand { display: flex; align-items: center; gap: .75rem; padding: 0 .5rem; }

.sidebar-brand-mark {
  display: grid;
  place-items: center;
  width: 2.25rem; height: 2.25rem;
  border-radius: .75rem;
  background-color: var(--surface);
  border: 1px solid var(--line);
  overflow: hidden;
}

.sidebar-brand-mark img { width: 100%; height: 100%; object-fit: cover; }
.sidebar-brand-text { display: flex; flex-direction: column; line-height: 1.2; min-width: 0; }
.sidebar-brand-name { font-weight: 650; color: var(--ink-strong); }
.sidebar-brand-kicker { font-size: .6875rem; color: var(--ink-faint); }

.sidebar-nav { display: flex; flex-direction: column; gap: .125rem; }

.sidebar-item {
  display: flex;
  align-items: center;
  gap: .75rem;
  width: 100%;
  min-height: 2.625rem;
  padding: 0 .75rem;
  border-radius: var(--radius);
  color: var(--ink-2);
  font-size: .875rem;
  text-align: left;
  transition: background-color .15s var(--ease), color .15s var(--ease);
}

.sidebar-item:hover { background-color: var(--surface); color: var(--ink-strong); }
.sidebar-item-label { min-width: 0; }

/* Bottom-Navigation. Vier Bereiche plus ein erhabener Erfassen-Knopf in der
   Mitte.

   WARUM DIE MITTE: "Erfassen" ist die einzige taegliche Handlung dieser App
   und stand deshalb schon vorher auf Platz 1 der Leiste - aber als
   gleichwertiger fuenfter Eintrag. Ein erhabener Knopf in der Mitte ist der
   Ort, den der Daumen ohne Hinsehen trifft, und er nimmt keinen der fuenf
   Plaetze weg: die uebrigen vier bleiben, "Mehr" bleibt. */
.bottom-nav {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 40;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  border-top: 1px solid var(--line);
  background-color: color-mix(in srgb, var(--surface) 88%, transparent);
  backdrop-filter: blur(16px) saturate(1.4);
  -webkit-backdrop-filter: blur(16px) saturate(1.4);
  padding-bottom: env(safe-area-inset-bottom);
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
}

@media (min-width: 1024px) { .bottom-nav { display: none; } }

.bottom-nav-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .1875rem;
  min-height: 3.5rem;
  color: var(--ink-faint);
  transition: color .15s var(--ease);
}

.bottom-nav-item .icon { width: 1.375rem; height: 1.375rem; }
.bottom-nav-label { font-size: .625rem; font-weight: 550; letter-spacing: .01em; }

/* Der erhabene Erfassen-Knopf. Er steht in derselben Spur wie die anderen,
   ragt aber nach oben heraus - deshalb bekommt seine Zelle keine eigene
   Hoehe, sondern der Knopf wird ueber den Rand gehoben. */
.bottom-nav-item--fab {
  position: relative;
  color: var(--ink-faint);
}

.bottom-nav-fab {
  display: grid;
  place-items: center;
  width: 3.25rem;
  height: 3.25rem;
  margin-top: -1.5rem;
  border-radius: 999px;
  background-color: var(--accent);
  color: var(--on-accent);
  box-shadow: 0 6px 20px -6px color-mix(in srgb, var(--accent) 70%, transparent), var(--shadow-sm);
  border: 3px solid var(--surface);
  transition: transform .12s var(--ease), background-color .15s var(--ease);
}

.bottom-nav-fab .icon { width: 1.625rem; height: 1.625rem; }
.bottom-nav-item--fab:active .bottom-nav-fab { transform: scale(.93); }
.bottom-nav-item--fab .bottom-nav-label { margin-top: .0625rem; }
.bottom-nav-item--fab[data-active="true"] .bottom-nav-fab { background-color: var(--accent-strong); }

/* Sheet fuer die uebrigen Bereiche. */
/* Kopfzeile. Sitzt direkt auf dem Grund, ohne eigene Karte. */
.app-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  padding: 0 .125rem;
}

.app-header-id { display: flex; align-items: center; gap: .75rem; min-width: 0; }
.app-header-text { min-width: 0; }
.app-header-account { display: flex; align-items: center; justify-content: flex-end; }

@media (min-width: 640px) { .app-header, .app-header-id { gap: 1rem; } }

.app-brand-mark {
  display: grid;
  place-items: center;
  width: 2.25rem; height: 2.25rem;
  flex: none;
  border-radius: .75rem;
  background-color: var(--surface);
  border: 1px solid var(--line);
  overflow: hidden;
}

.app-brand-mark img { width: 100%; height: 100%; object-fit: cover; }

@media (min-width: 640px) {
  .app-brand-mark { width: 2.75rem; height: 2.75rem; border-radius: .875rem; }
}

.header-month {
  font-size: 1.0625rem;
  font-weight: 700;
  letter-spacing: -.02em;
  color: var(--ink-strong);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@media (min-width: 640px) { .header-month { font-size: 1.25rem; } }
@media (min-width: 768px) { .header-month { font-size: 1.5rem; } }

/* Tagesbudget in der Kopfzeile — die Leitzahl, ueberall sichtbar.

   Sie ersetzt rund 380 px Uebersichtsblock, der bis zum 23.08.2026 im Rahmen
   ueber JEDEM Bereich lag. Hier kostet dieselbe Auskunft rund 44 px, und sie
   ist ein Knopf: ein Tipp fuehrt zu "Heute", wo die Zahl gross steht.

   Bewusst KEIN Akzentton. Der Akzent gehoert dem, was man anfassen kann;
   was Geld bewegt, traegt --positive/--negative. Eine Zahl, die nur Auskunft
   gibt, traegt Textfarbe. */
.header-pace {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: .0625rem;
  margin-left: auto;
  padding: .3125rem .625rem;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
  background-color: var(--bg-soft);
  color: inherit;
  cursor: pointer;
  text-align: right;
  white-space: nowrap;
}

.header-pace:hover { border-color: var(--line); }

.header-pace-label {
  font-size: .6875rem;
  line-height: 1;
  color: var(--ink-faint);
}

.header-pace-value {
  font-variant-numeric: tabular-nums;
  font-size: 1rem;
  font-weight: 620;
  line-height: 1.2;
  letter-spacing: -.01em;
  color: var(--ink-strong);
}

/* Aufgebraucht: die Zahl faerbt sich, nicht der Rahmen. Ein rot umrandeter
   Kasten in der Kopfzeile laege dauerhaft im Blick und waere nach zwei Tagen
   Hintergrundrauschen. */
.header-pace-value[data-state="empty"] { color: var(--negative); }

/* Abschnitt in einem gebuendelten Bereich.

   Seit dem Makeover (23.08.2026) tragen "Plan" und "Rueckblick" mehrere
   Abschnitte untereinander - vorher war jeder davon ein eigener Bereich.
   Der Abstand ZWISCHEN Abschnitten ist groesser als der Abstand INNERHALB
   eines Abschnitts: sonst liest sich die Seite als eine durchgehende Flaeche
   und man findet den Anfang des naechsten Themas nicht. */
.view-section {
  display: flex;
  flex-direction: column;
  gap: var(--rhythm);
  scroll-margin-top: 4.5rem;
}

.view-section + .view-section {
  margin-top: calc(var(--rhythm) * 1.5);
  padding-top: calc(var(--rhythm) * 1.5);
  border-top: 1px solid var(--line-soft);
}

.view-sub {
  font-size: .8125rem;
  color: var(--ink-2);
}


/* Sprungmarken innerhalb eines Bereichs.

   Vier Abschnitte untereinander sind eine lange Seite. Die Leiste ueberspringt,
   was man gerade nicht sucht - ohne eine zweite Navigationsebene einzufuehren,
   die alles wieder zwei Tipps entfernt machen wuerde. Sie scrollt selbst, wenn
   die Marken nicht in eine Zeile passen. */
.section-jump {
  display: flex;
  gap: .375rem;
  overflow-x: auto;
  padding-bottom: .125rem;
  scrollbar-width: none;
}

.section-jump::-webkit-scrollbar { display: none; }

.section-jump-item {
  flex: none;
  appearance: none;
  padding: .3125rem .625rem;
  border: 1px solid var(--line-soft);
  border-radius: 999px;
  background-color: var(--bg-soft);
  color: var(--ink-2);
  font-size: .75rem;
  font-weight: 550;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
}

.section-jump-item:hover {
  border-color: var(--line);
  color: var(--ink-strong);
}

.section-jump-item[data-active="true"] {
  border-color: color-mix(in srgb, var(--accent) 45%, var(--line));
  background-color: var(--accent-soft);
  color: var(--accent-text);
}


/* Herkunft der Leitzahl — zugeklappt.

   Fuenf Zeilen, die man abliest und nie anfasst. Aufgeklappt braechten sie den
   Startbildschirm auf vier Bloecke; der Entwurf sieht drei vor. Es faellt
   nichts weg - ein Tipp oeffnet sie. */
.ledger-details {
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
  background-color: var(--bg-soft);
}

.ledger-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .5rem;
  padding: .625rem var(--pad);
  color: var(--ink-2);
  font-size: .8125rem;
  font-weight: 550;
  cursor: pointer;
  list-style: none;
}

.ledger-summary::-webkit-details-marker { display: none; }
.ledger-summary:hover { color: var(--ink-strong); }
.ledger-summary .icon { transition: transform .15s ease; }
.ledger-details[open] .ledger-summary .icon { transform: rotate(180deg); }
.ledger-details[open] .ledger-summary { border-bottom: 1px solid var(--line-soft); }
.ledger-details .ledger { padding: .25rem var(--pad) .625rem; }

@media (prefers-reduced-motion: reduce) {
  .ledger-summary .icon { transition: none; }
}


/* Tagessumme in "Heute gebucht". Farbe sagt die Richtung, das Vorzeichen
   sagt sie noch einmal - wer Farben nicht unterscheidet, liest das Vorzeichen. */
#home-today-total[data-state="out"] { color: var(--negative); }
#home-today-total[data-state="in"]  { color: var(--positive); }
#home-today-total[data-state="idle"] { color: var(--ink-faint); }


/* "Erfassen" in der Seitenleiste: eine Aktion, kein Ort.

   Auf dem Handy ist es der erhabene Knopf in der Mitte der unteren Leiste.
   Auf dem Desktop stuende es sonst als vierter gleichwertiger Eintrag zwischen
   den Bereichen - und saehe aus wie einer. */
.sidebar-item--action {
  margin-top: .75rem;
  border: 1px dashed var(--line);
  color: var(--ink-strong);
}

.sidebar-item--action:hover { border-style: solid; border-color: var(--accent); }


/* Kontomenue */
.account-anchor { position: relative; }

.account-trigger {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .25rem .5rem .25rem .25rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background-color: var(--surface);
  max-width: 14rem;
  transition: border-color .15s var(--ease);
}

.account-trigger:hover { border-color: var(--line-strong); }

.account-avatar, .account-trigger-avatar {
  display: grid;
  place-items: center;
  width: 2rem; height: 2rem;
  flex: none;
  border-radius: 999px;
  background-color: var(--accent);
  color: var(--on-accent);
  font-size: .8125rem;
  font-weight: 650;
}

.account-trigger-meta { display: none; flex-direction: column; line-height: 1.2; min-width: 0; text-align: left; }
@media (min-width: 640px) { .account-trigger-meta { display: flex; } }

.account-trigger-name {
  font-size: .8125rem; font-weight: 650; color: var(--ink-strong);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.account-trigger-kicker, .account-kicker { font-size: .6875rem; color: var(--ink-faint); }
.account-trigger-chevron { width: 1rem; height: 1rem; flex: none; color: var(--ink-faint); }

.account-menu {
  position: absolute;
  right: 0;
  top: calc(100% + .5rem);
  z-index: 50;
  width: min(19rem, calc(100vw - 2rem));
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background-color: var(--surface);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}

.account-menu-header { display: flex; align-items: center; gap: .75rem; padding: 1rem; border-bottom: 1px solid var(--line-soft); }
.account-name { font-size: .875rem; font-weight: 650; color: var(--ink-strong); }
.account-menu-body { padding: .5rem; max-height: 60vh; overflow-y: auto; }
.account-menu-footer { padding: .5rem; border-top: 1px solid var(--line-soft); }

/* Auf dem Handy steht der Kontoknopf in der unteren Leiste - die Kopfzeile
   braucht ihn oben nicht doppelt und gibt den Platz der Leitzahl.

   ABER: Es verschwindet nur der AUSLOESER, nicht sein Rahmen.
   Hier stand bis zum 23.08.2026 abends `.app-header-account { display: none }`.
   Das Konto-MENUE (#userDropdownMenu) liegt in diesem Rahmen - es lag damit in
   einem display:none-Teilbaum. Der Knopf in der unteren Leiste schaltete den
   Zustand brav um, sichtbar wurde nie etwas. Ein Element, das man versteckt,
   versteckt alles darin. */
@media (max-width: 639px) {
  .account-trigger { display: none; }

  /* Das Menue kommt von unten, weil der Knopf unten steht. Es als Klappe an
     der Kopfzeile aufgehen zu lassen, waehrend der Daumen unten rechts tippt,
     laesst einen zweimal hinsehen: erst dorthin, wo nichts passiert ist.
     3,5rem ist die Hoehe von .bottom-nav-item, dazu der sichere Bereich. */
  .account-menu {
    position: fixed;
    top: auto;
    right: .75rem;
    left: .75rem;
    bottom: calc(3.5rem + env(safe-area-inset-bottom) + .5rem);
    width: auto;
    max-height: 70vh;
    overflow-y: auto;
    overscroll-behavior: contain;
  }
}


.account-list-item, .account-link-item {
  display: flex;
  align-items: center;
  gap: .625rem;
  width: 100%;
  min-height: 2.5rem;
  padding: 0 .625rem;
  border-radius: var(--radius-sm);
  color: var(--ink-2);
  font-size: .875rem;
  text-align: left;
  text-decoration: none;
}

.account-list-item { justify-content: space-between; }
.account-list-item:hover, .account-link-item:hover { background-color: var(--surface-2); color: var(--ink-strong); }
.account-link-item-danger { color: var(--negative); }
.account-link-item-danger:hover { color: var(--negative); background-color: color-mix(in srgb, var(--negative) 12%, transparent); }
.account-section-title { padding: .625rem .625rem .25rem; }

/* Bereiche. activateTab() setzt panel.hidden und data-active - .tab-panel
   bekommt bewusst KEINE display-Regel. */
.tab-trigger { cursor: pointer; }

.sidebar-item[data-active="true"] {
  background-color: var(--accent-soft);
  color: var(--ink-strong);
  font-weight: 650;
  box-shadow: inset 3px 0 0 var(--accent-strong);
}

.bottom-nav-item[data-active="true"] { color: var(--accent-text); }
.bottom-nav-item[data-active="true"] .icon { color: var(--accent-text); }
.bottom-nav-item--fab[data-active="true"] .bottom-nav-fab .icon { color: var(--on-accent); }

/* Entfallen am 23.08.2026 (Makeover).

   Hier standen rund 50 Zeilen, die den Uebersichtsblock je nach Bereich
   verkleinerten oder ausblendeten: volle Leitzahl auf "Heute", schmale Zeile
   auf "Erfassen", weg auf allen uebrigen. Sie waren noetig, weil der Block
   im Rahmen ueber JEDEM Bereich lag und dort ueberall Hoehe kostete.

   Er liegt jetzt in views/home.php - also im Bereich "Heute" und sonst
   nirgends. Was gar nicht da ist, muss nicht ausgeblendet werden. Die
   dauerhaft sichtbare Fassung ist .header-pace in der Kopfzeile. */

/* --------------------------------------------------------------- 9 Bereiche */

.overview-stack { display: flex; flex-direction: column; gap: var(--rhythm); }

/* Die Leitzahl der App: was diesen Monat noch da ist. */
.balance-hero {
  display: flex;
  flex-direction: column;
  gap: .375rem;
  padding: 1.375rem var(--pad) 1.25rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background-color: var(--surface);
  box-shadow: var(--shadow);
  position: relative;
  overflow: hidden;
}

/* Ein einzelner, sehr flacher Lichtschein von oben links. Nicht Stimmung,
   sondern Rangordnung: Er hebt die eine Karte heraus, die die Antwort
   traegt, ohne ihr eine Farbe zu geben, die man als Zustand lesen koennte. */
.balance-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(120% 100% at 0% 0%, var(--accent-soft), transparent 60%);
  opacity: .7;
}

.balance-hero > * { position: relative; }

[data-skin="hell"] .balance-hero { border-color: transparent; }

.balance-hero-meter {
  height: .5rem;
  margin-top: .625rem;
  border-radius: 999px;
  background-color: var(--surface-2);
  overflow: hidden;
}

.balance-hero-legend {
  display: flex;
  flex-direction: column;
  gap: .125rem;
  margin-top: .5rem;
  font-size: .75rem;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

/* Zwei getrennte Angaben, nicht ein Satz.
   Nebeneinander gesetzt las sich das bei 390 px als
   "742,18 € bis Monatsende 1.587,82 € von 2.330,00 € verbraucht" - eine Zeile
   ohne Zaesur, in der die zweite Zahl wie eine Fortsetzung der ersten wirkt.
   Ab 560 px ist Platz fuer eine Zeile, dann mit Abstand statt Umbruch. */
@media (min-width: 560px) {
  .balance-hero-legend {
    flex-direction: row;
    justify-content: space-between;
    gap: .75rem;
  }
}

/* Der Zustand steht oben rechts neben der Beschriftung, nicht unten in der
   Legende: "1.587,82 € von 2.330,00 € verbraucht" und "Im Rahmen" passen bei
   326 px nutzbarer Breite nicht in eine Zeile - der Zustand rutschte auf eine
   eigene und sah aus wie ein vergessener Rest. Oben rechts hat er Platz und
   steht dort, wo das Auge nach der grossen Zahl ohnehin hinkommt.
   Die Zeile wird per .balance-hero-top im Markup gebildet. */
.balance-hero-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
}

#overview-budget-status {
  flex: none;
  padding: .1875rem .5625rem;
  border-radius: 999px;
  background-color: var(--surface-2);
  color: var(--ink-2);
  font-size: .6875rem;
  font-weight: 650;
  white-space: nowrap;
}

/* Ueber Budget ist der einzige Zustand, der Farbe verdient. */
#overview-budget-status[data-state="over"] {
  background-color: color-mix(in srgb, var(--signal) 18%, transparent);
  color: var(--signal);
}

/* Die Herkunft der Leitzahl.

   Vorher: fuenf Zeilen in einer Aufstellung - Gehalt, Weitere Einnahmen,
   Fixkosten, Ausgaben, Bargeld. Rund 300 px, an denen man auf "Heute" bei
   jedem Aufruf vorbeiscrollte, um zu den Listen zu kommen. Es sind Zahlen,
   die man abliest und nie anfasst.

   Jetzt vier Kennzahlfelder im Zweiersatz - Gehalt, Weitere Einnahmen,
   Fixkosten, Ausgaben - und Bargeld abgesetzt darunter, weil es der einzige
   Wert hier ist, den man aendert statt ihn abzulesen. Zwei Spalten und nicht
   vier: "1.142,00 €" braucht bei 390 px Geraetebreite rund 90 px, in vier
   Spalten blieben 78 px. Die IDs bleiben unveraendert - dashboard.js
   schreibt weiter hinein. */
.ledger {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: .5rem;
}

@media (min-width: 640px) { .ledger { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.ledger-row {
  display: flex;
  flex-direction: column;
  gap: .1875rem;
  padding: .75rem .75rem .8125rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background-color: var(--surface);
  box-shadow: var(--shadow-sm);
  min-width: 0;
}

[data-skin="hell"] .ledger-row { border-color: transparent; box-shadow: var(--shadow-sm); }

.ledger-row dt {
  display: flex;
  flex-direction: column;
  gap: .0625rem;
  font-size: .6875rem;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--ink-faint);
  min-width: 0;
}

.ledger-row dd {
  margin: 0;
  font-size: .9375rem;
  font-weight: 700;
  letter-spacing: -.015em;
  color: var(--ink-strong);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ledger-note {
  font-size: .6875rem;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-faint);
}

/* Die vierte und fuenfte Zeile - "Weitere Einnahmen" und "Bargeld" - passen
   nicht in drei Spalten. Sie laufen als volle Breite darunter: Bargeld ist
   ohnehin ein zweiter Topf, keine Kennzahl. */
.ledger-row--wide { grid-column: 1 / -1; flex-direction: row; align-items: center; justify-content: space-between; gap: .75rem; }
.ledger-row--wide dt { flex-direction: row; align-items: baseline; gap: .5rem; flex-wrap: wrap; }
.ledger-row--wide dd { font-size: 1rem; }

.ledger-row--cash {
  grid-column: 1 / -1;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  background-color: var(--bg-soft);
}

[data-skin="hell"] .ledger-row--cash { background-color: var(--surface-2); box-shadow: none; }

.ledger-row--cash dt { flex-direction: column; }
.ledger-row--cash dd { font-size: 1rem; }

/* Tagesbudget. Die Zahl, die eine Budget-App eigentlich beantwortet:
   "wie viel darf ich heute noch ausgeben?" Sie stand nirgends - man musste
   Restbetrag durch Resttage im Kopf teilen. */
.pace {
  display: flex;
  align-items: center;
  gap: .5rem;
  margin-top: .625rem;
  font-size: .8125rem;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}

.pace-value { font-weight: 700; color: var(--ink-strong); }
.pace .icon { width: 1rem; height: 1rem; color: var(--ink-faint); }

/* Analyse: Auswahl links, Diagramm rechts. */
.analytics-layout { display: grid; gap: var(--rhythm); grid-template-columns: minmax(0, 1fr); }
@container main (min-width: 48rem) { .analytics-layout { grid-template-columns: 13rem minmax(0, 1fr); align-items: start; } }

/* Kalender. Sieben Spalten, quadratische Felder. */
.calendar-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: .25rem; }

.cal-weekday {
  padding-bottom: .5rem;
  text-align: center;
  font-size: .6875rem;
  font-weight: 650;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.cal-day {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .1875rem;
  aspect-ratio: 1;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  background-color: var(--bg-soft);
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
  transition: background-color .15s var(--ease), border-color .15s var(--ease);
}

[data-skin="hell"] .cal-day { background-color: var(--surface-2); }

.cal-empty { aspect-ratio: 1; }

@media (min-width: 640px) {
  .cal-day, .cal-empty { aspect-ratio: auto; min-height: 4.25rem; }
}

.cal-day-num { font-size: .8125rem; font-weight: 550; }
.cal-day:hover { border-color: var(--line-strong); color: var(--ink-strong); }

/* Faelliger Tag: Flaeche plus Punkt. Der Punkt allein waere auf 44 px zu
   klein - und Farbe allein traegt in diesem System nie eine Bedeutung. */
.cal-day-due {
  background-color: color-mix(in srgb, var(--signal) 16%, var(--bg-soft));
  color: var(--ink-strong);
  font-weight: 650;
}

.cal-day-dot { width: .3125rem; height: .3125rem; border-radius: 999px; background-color: var(--signal); }

.cal-day-today {
  border-color: var(--accent-text);
  color: var(--ink-strong);
  font-weight: 700;
  box-shadow: inset 0 0 0 1px var(--accent-text);
}

.cal-legend { display: flex; gap: .875rem; font-size: .6875rem; color: var(--ink-faint); }
.cal-key { display: inline-flex; align-items: center; gap: .375rem; }
.cal-dot { width: .5rem; height: .5rem; border-radius: 999px; flex: none; }
.cal-dot--due { background-color: var(--signal); }
.cal-dot--today { background-color: var(--accent-text); }

.cal-detail {
  margin-top: .875rem;
  padding: .875rem;
  border-radius: var(--radius);
  background-color: var(--bg-soft);
  border: 1px solid var(--line-soft);
  font-size: .875rem;
}

[data-skin="hell"] .cal-detail { background-color: var(--surface-2); }

.cal-foot { margin-top: .75rem; font-size: .75rem; color: var(--ink-faint); }

/* Budgetaufteilung. Ein gestapelter Balken plus Legende - kein Ring: Ein
   Kreis laesst Anteile nur schaetzen, eine gemeinsame Grundlinie nicht. */
.budget-split { display: flex; flex-direction: column; gap: .875rem; }
.budget-split-head { display: flex; align-items: baseline; justify-content: space-between; gap: .75rem; }
.budget-split-title { font-size: .875rem; font-weight: 650; color: var(--ink-strong); }
.budget-split-total { font-size: .8125rem; color: var(--ink-faint); font-variant-numeric: tabular-nums; }

.budget-bar {
  display: flex;
  gap: 2px;
  height: 1.75rem;
  border-radius: var(--radius-sm);
  overflow: hidden;
  background-color: var(--surface-2);
}

.budget-bar-empty { display: grid; place-items: center; width: 100%; font-size: .75rem; color: var(--ink-faint); }
.budget-seg { min-width: 2px; transition: width .5s var(--ease); position: relative; }

.budget-seg-label {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  font-size: .6875rem; font-weight: 700; color: #fff;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .55);
}

.budget-keys { display: flex; flex-direction: column; gap: .5rem; }

.budget-key {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  align-items: center;
  gap: .625rem;
  font-size: .8125rem;
}

.budget-key-dot { width: .625rem; height: .625rem; border-radius: .25rem; flex: none; }
.budget-key-label { color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.budget-key-value { color: var(--ink-strong); font-weight: 650; font-variant-numeric: tabular-nums; }
.budget-key-share { color: var(--ink-faint); font-variant-numeric: tabular-nums; min-width: 2.75rem; text-align: right; }
.budget-key-empty { font-size: .8125rem; color: var(--ink-faint); }

.chart-panel { display: flex; flex-direction: column; gap: .875rem; }
.chart-shell { display: grid; gap: var(--rhythm); grid-template-columns: minmax(0, 1fr); }
@container main (min-width: 48rem) { .chart-shell { grid-template-columns: minmax(0, 1fr) 13rem; } }

.chart-stage { min-width: 0; }
.chart-picker { display: flex; flex-direction: column; gap: .5rem; }
.chart-picker-label { font-size: .6875rem; font-weight: 650; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-faint); }
.chart-picker-list { display: flex; flex-wrap: wrap; gap: .375rem; }
@container main (min-width: 48rem) { .chart-picker-list { flex-direction: column; flex-wrap: nowrap; } }

.chart-pick {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  min-height: 2.375rem;
  padding: 0 .875rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background-color: var(--bg-soft);
  color: var(--ink-2);
  font-size: .8125rem;
  font-weight: 550;
  text-align: left;
  transition: background-color .15s var(--ease), border-color .15s var(--ease), color .15s var(--ease);
}

[data-skin="hell"] .chart-pick { background-color: var(--surface-2); }

@container main (min-width: 48rem) { .chart-pick { border-radius: var(--radius); } }

.chart-pick:hover { color: var(--ink-strong); border-color: var(--line-strong); }

.chart-pick[data-active="true"] {
  background-color: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
  font-weight: 650;
}

.chart-updated { margin-top: 1.5rem; text-align: right; font-size: .75rem; color: var(--ink-faint); }

/* --------------------------------------------------------------- 10 Overlays */

/* Drei Widgets aus dist/ mit eigenem JavaScript und ohne eigenes CSS. Ihre
   Klassennamen sind Vertrag, kein Geschmack. */

#notify-container, #toast-container { position: fixed; z-index: 80; display: flex; pointer-events: none; }

#notify-container {
  inset: calc(1rem + env(safe-area-inset-top)) 1rem auto auto;
  flex-direction: column;
  gap: .5rem;
  width: min(22rem, calc(100vw - 2rem));
}

#toast-container {
  inset: auto 0 calc(5.25rem + env(safe-area-inset-bottom)) 0;
  flex-direction: column;
  align-items: center;
  gap: .5rem;
}

@media (min-width: 1024px) { #toast-container { bottom: 1.5rem; } }

.dc-notify-item {
  display: flex;
  align-items: flex-start;
  gap: .75rem;
  padding: .8125rem;
  border: 1px solid var(--line);
  border-left-width: 3px;
  border-radius: var(--radius);
  background-color: var(--surface);
  box-shadow: var(--shadow-lg);
  pointer-events: auto;
  opacity: 0;
  transform: translateX(.75rem);
  transition: opacity .2s var(--ease), transform .2s var(--ease);
}

.dc-notify-item.is-visible { opacity: 1; transform: none; }

.dc-notify-main { display: flex; align-items: flex-start; gap: .625rem; min-width: 0; flex: 1; }
.dc-notify-icon svg { width: 1.25rem; height: 1.25rem; fill: currentColor; }
.dc-notify-copy { min-width: 0; }
.dc-notify-title { font-size: .8125rem; font-weight: 650; color: var(--ink-strong); }
.dc-notify-message { font-size: .8125rem; color: var(--ink-2); overflow-wrap: anywhere; }

.dc-notify-close {
  flex: none; width: 1.5rem; height: 1.5rem; border-radius: .375rem;
  color: var(--ink-faint); font-size: 1.125rem; line-height: 1;
}

.dc-notify-close:hover { color: var(--ink-strong); background-color: var(--surface-2); }

/* Zustandsfarbe traegt die Kante und das Zeichen - nie die Flaeche. */
.dc-notify-erfolg  { border-left-color: var(--positive); }
.dc-notify-erfolg  .dc-notify-icon { color: var(--positive); }
.dc-notify-fehler  { border-left-color: var(--negative); }
.dc-notify-fehler  .dc-notify-icon { color: var(--negative); }
.dc-notify-warnung { border-left-color: var(--signal); }
.dc-notify-warnung .dc-notify-icon { color: var(--signal); }
.dc-notify-info    { border-left-color: var(--cat-1); }
.dc-notify-info    .dc-notify-icon { color: var(--cat-1); }

.dc-toast-item {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  max-width: min(30rem, calc(100vw - 2rem));
  padding: .625rem 1rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background-color: var(--surface);
  box-shadow: var(--shadow-lg);
  font-size: .8125rem;
  color: var(--ink);
  pointer-events: auto;
  opacity: 0;
  transform: translateY(.5rem);
  transition: opacity .2s var(--ease), transform .2s var(--ease);
}

.dc-toast-item.is-visible { opacity: 1; transform: none; }
.dc-toast-icon svg { width: 1.125rem; height: 1.125rem; fill: currentColor; }
.dc-toast-message { overflow-wrap: anywhere; }
.dc-toast-erfolg  .dc-toast-icon { color: var(--positive); }
.dc-toast-fehler  .dc-toast-icon { color: var(--negative); }
.dc-toast-warnung .dc-toast-icon { color: var(--signal); }
.dc-toast-info    .dc-toast-icon,
.dc-toast-default .dc-toast-icon { color: var(--ink-faint); }

/* "Rueckgaengig" nach einer Loeschung. Die einzige Meldung mit einer
   Handlung darin - deshalb mit Rahmen, damit sie nicht wie ein Hinweis
   wirkt, der von allein verschwindet. */
.undo-bar {
  display: flex;
  align-items: center;
  gap: .75rem;
  align-self: center;
  width: fit-content;
  max-width: calc(100vw - 2rem);
  padding: .625rem .75rem .625rem 1rem;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background-color: var(--surface);
  box-shadow: var(--shadow-lg);
  font-size: .875rem;
  pointer-events: auto;
  opacity: 0;
  transform: translateY(.5rem);
  transition: opacity .3s var(--ease), transform .3s var(--ease);
}

.undo-bar.is-visible { opacity: 1; transform: none; }
.undo-bar-text { max-width: 15rem; color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Rueckfrage. Wird fuer Loeschungen benutzt - der bestaetigende Knopf traegt
   die Signalfarbe und steht rechts, der Abbruch links. */
.dc-modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: grid;
  place-items: center;
  padding: 1rem;
  background-color: rgba(0, 0, 0, .6);
  backdrop-filter: blur(3px);
  opacity: 0;
  visibility: hidden;
  transition: opacity .18s var(--ease), visibility .18s var(--ease);
}

.dc-modal-overlay-open { opacity: 1; visibility: visible; }

.dc-modal-card {
  width: min(26rem, 100%);
  padding: 1.25rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background-color: var(--surface);
  box-shadow: var(--shadow-lg);
  transform: scale(.96);
  transition: transform .18s var(--ease);
}

.dc-modal-overlay-open .dc-modal-card { transform: none; }

.dc-modal-head { display: flex; align-items: center; gap: .75rem; margin-bottom: .625rem; }

.dc-modal-icon {
  display: grid; place-items: center;
  width: 2.5rem; height: 2.5rem; flex: none;
  border-radius: .75rem;
  background-color: color-mix(in srgb, var(--signal) 16%, transparent);
  color: var(--signal);
}

.dc-modal-icon svg { width: 1.25rem; height: 1.25rem; fill: currentColor; }
.dc-modal-title { font-size: 1rem; font-weight: 650; color: var(--ink-strong); }
.dc-modal-message { font-size: .875rem; line-height: 1.5; color: var(--ink-2); }
.dc-modal-actions { display: flex; justify-content: flex-end; gap: .5rem; margin-top: 1.25rem; }

.dc-modal-btn {
  min-height: var(--touch);
  padding: 0 1.125rem;
  border: 1px solid transparent;
  border-radius: var(--radius);
  font-size: .875rem;
  font-weight: 550;
  transition: background-color .15s var(--ease), border-color .15s var(--ease);
}

.dc-modal-btn-cancel { background-color: var(--surface-2); border-color: var(--line); color: var(--ink); }
.dc-modal-btn-cancel:hover { border-color: var(--line-strong); }
.dc-modal-btn-confirm { background-color: var(--signal); color: #24170a; font-weight: 650; }
.dc-modal-btn-confirm:hover { filter: brightness(1.08); }

/* -------------------------------------------------------------- 11 Bausteine

   Diese Klassen ersetzen die Utility-Ketten, die vorher im Markup standen -
   vor allem im JavaScript, wo sie am schlechtesten zu pruefen waren.
   ------------------------------------------------------------------------ */

.stack   { display: flex; flex-direction: column; gap: .5rem; min-width: 0; }
.stack-3 { gap: .75rem; }
.stack-4 { gap: 1rem; }
.stack-5 { gap: 1.25rem; }

.hint { font-size: .75rem; color: var(--ink-faint); }
.hint-signal { font-size: .75rem; color: var(--signal); }

/* Leerzustand. Die gestrichelte Kante sagt "hier koennte etwas stehen" -
   eine durchgezogene wuerde ihn wie ausgegrauten Inhalt aussehen lassen. */
.empty-state {
  padding: 1.25rem 1rem;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
  background-color: transparent;
  font-size: .875rem;
  color: var(--ink-2);
  text-align: center;
}

.item-title { font-size: .875rem; font-weight: 650; color: var(--ink-strong); }
.item-label { font-size: .875rem; font-weight: 550; color: var(--ink-2); }

.row-between { display: flex; align-items: center; justify-content: space-between; gap: .75rem; min-width: 0; }
.row-actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: .5rem; }

.line-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  padding: .5rem .75rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background-color: var(--bg-soft);
  min-width: 0;
}

[data-skin="hell"] .line-item { background-color: var(--surface-2); }

.grid-2 { display: grid; grid-template-columns: minmax(0, 1fr); gap: .75rem; }
@media (min-width: 640px) { .grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.icon-btn-danger:hover {
  color: var(--negative);
  background-color: color-mix(in srgb, var(--negative) 12%, transparent);
}

.text-signal { color: var(--signal); }
.text-strong { color: var(--ink-strong); }
.fw-semibold { font-weight: 650; }

.btn-block { width: 100%; }
@media (min-width: 640px) { .btn-block { width: auto; align-self: flex-start; } }

.chip-btn {
  min-height: 1.875rem;
  padding: .25rem .75rem;
  border-radius: 999px;
  background-color: var(--surface-2);
  font-size: .75rem;
  font-weight: 650;
  color: var(--ink);
  transition: background-color .15s var(--ease);
}

.chip-btn:hover { background-color: var(--surface-3); }
.chip-btn-signal { color: var(--signal); }
.chip-btn-primary { background-color: var(--accent); color: var(--on-accent); }
.chip-btn-primary:hover { background-color: var(--accent-strong); }

/* Zustandsmarke, nicht anklickbar. */
.tag {
  display: inline-block;
  padding: .1875rem .625rem;
  border-radius: 999px;
  background-color: var(--accent-soft);
  font-size: .75rem;
  font-weight: 650;
  color: var(--accent-text);
}

/* Fortschrittsbalken ausserhalb der Hero-Zahl - Sparziel, Kategorieanteil. */
.progress { height: .625rem; width: 100%; border-radius: 999px; background-color: var(--surface-2); overflow: hidden; }
.progress-fill { height: 100%; border-radius: 999px; background-color: var(--accent); transition: width .5s var(--ease); }

.card-line {
  padding: .75rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background-color: var(--bg-soft);
}

[data-skin="hell"] .card-line { background-color: var(--surface-2); }

.card-line-plain { background-color: transparent; }
.card-line-action { transition: border-color .15s var(--ease), background-color .15s var(--ease); }
.card-line-action:hover { border-color: var(--accent); background-color: var(--accent-soft); }

.grid-3, .grid-4, .grid-5 { display: grid; grid-template-columns: minmax(0, 1fr); gap: .75rem; }
@media (min-width: 640px) {
  .grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .grid-4, .grid-5 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1024px) {
  .grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .grid-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
}

.span-full { grid-column: 1 / -1; }
@media (min-width: 640px) { .span-2 { grid-column: span 2; } }

.mt-2 { margin-top: .5rem; }
.mt-3 { margin-top: .75rem; }
.mt-4 { margin-top: 1rem; }

/* Farbwelt-Auswahl in den Einstellungen.

   Die Farbproben tragen als einzige Stelle dieser Datei feste Werte statt
   Token: Sie sollen zeigen, wie die ANDEREN Farbwelten aussehen - ein Token
   wuerde ueberall die gerade aktive zeigen und die Auswahl damit sinnlos
   machen. Die Werte sind Kopien aus Abschnitt 2; wer dort einen Grundton
   aendert, zieht ihn hier nach. */
.skin-picker { display: grid; grid-template-columns: minmax(0, 1fr); gap: .5rem; }
@media (min-width: 560px) { .skin-picker { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.skin-option {
  display: flex;
  align-items: center;
  gap: .75rem;
  min-height: var(--touch);
  padding: .625rem .75rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background-color: var(--bg-soft);
  text-align: left;
  transition: border-color .15s var(--ease), background-color .15s var(--ease);
}

[data-skin="hell"] .skin-option { background-color: var(--surface-2); }

.skin-option:hover { border-color: var(--line-strong); }

.skin-option[data-active="true"] {
  border-color: var(--accent);
  background-color: var(--accent-soft);
  box-shadow: inset 0 0 0 1px var(--accent);
}

/* Die Probe zeigt beides, worauf es ankommt: den Grund als Flaeche und den
   Akzent als Punkt darauf. Eine einfarbige Flaeche wuerde "hell" und
   "System" ununterscheidbar machen. */
.skin-swatch {
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  flex: none;
  border-radius: .625rem;
  border: 1px solid var(--line-strong);
  overflow: hidden;
}

.skin-swatch-accent { width: 1rem; height: 1rem; border-radius: 999px; }

.skin-swatch--marke  { background-color: #121316; }
.skin-swatch--marke  .skin-swatch-accent { background-color: #b02742; }
.skin-swatch--hell   { background-color: #f2f4f7; }
.skin-swatch--hell   .skin-swatch-accent { background-color: #0f766e; }

/* "System" ist keine eigene Farbwelt, sondern eine Weiche - die Probe zeigt
   deshalb beide Seiten, zwischen denen sie waehlt. */
.skin-swatch--auto { background-image: linear-gradient(135deg, #f2f4f7 0 50%, #121316 50% 100%); }
.skin-swatch--auto .skin-swatch-accent {
  background-image: linear-gradient(135deg, #0f766e 0 50%, #b02742 50% 100%);
}

.skin-option-text { display: flex; flex-direction: column; gap: .0625rem; min-width: 0; }
.skin-option-name { font-size: .875rem; font-weight: 650; color: var(--ink-strong); }
.skin-option-desc { font-size: .75rem; color: var(--ink-faint); }

/* Sparziel. Der Inhalt kommt vollstaendig aus renderGoal(). */
.goal-title { font-size: 1rem; font-weight: 650; color: var(--ink-strong); }
.goal-amount { font-variant-numeric: tabular-nums; }
.goal-add-form { margin-bottom: 0; }

/* ------------------------------------------------------------- 12 Anmeldung

   Login und Registrierung teilen sich einen eigenen Rahmen: eine Karte in
   der Mitte, kein Geruest drumherum. Es gibt hier nichts zu navigieren.
   ------------------------------------------------------------------------ */

.auth-shell {
  display: grid;
  place-items: center;
  min-height: 100dvh;
  padding: calc(1.5rem + env(safe-area-inset-top))
           calc(1.5rem + env(safe-area-inset-right))
           calc(1.5rem + env(safe-area-inset-bottom))
           calc(1.5rem + env(safe-area-inset-left));
  background-color: var(--bg);
}

.auth-shell::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  /* Auf der Anmeldeseite gibt es nichts abzulesen, hier darf Atmosphaere
     sein - aber gedaempft. */
  background: radial-gradient(48rem 40rem at 20% 8%, var(--accent-soft), transparent 65%);
}

.auth-card { position: relative; z-index: 1; width: 100%; max-width: 25rem; }
.auth-head { margin-bottom: 1.75rem; text-align: center; }

.auth-mark {
  display: grid;
  place-items: center;
  width: 3.5rem; height: 3.5rem;
  margin: 0 auto;
  border-radius: 1.125rem;
  background-color: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--shadow);
  overflow: hidden;
}

.auth-mark img { width: 100%; height: 100%; object-fit: cover; }

.auth-title {
  margin-top: 1.25rem;
  font-size: 1.75rem;
  font-weight: 700;
  letter-spacing: -.03em;
  color: var(--ink-strong);
}

.auth-sub { margin-top: .375rem; font-size: .875rem; color: var(--ink-2); }

.auth-panel {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  padding: 1.75rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background-color: var(--surface);
  box-shadow: var(--shadow-lg);
}

[data-skin="hell"] .auth-panel { border-color: transparent; }

.auth-form { display: flex; flex-direction: column; gap: 1.125rem; }
.auth-foot { margin-top: 1.75rem; text-align: center; font-size: .875rem; color: var(--ink-2); }
.auth-copyright { margin-top: 1.25rem; font-size: .75rem; color: var(--ink-faint); }

.link-accent { font-weight: 550; color: var(--accent-text); text-decoration: none; }
.link-accent:hover { text-decoration: underline; }

.alert {
  padding: .75rem 1rem;
  border: 1px solid var(--line);
  border-left-width: 3px;
  border-radius: var(--radius);
  font-size: .875rem;
  line-height: 1.45;
}

.alert-ok {
  border-left-color: var(--positive);
  border-color: color-mix(in srgb, var(--positive) 25%, transparent);
  background-color: color-mix(in srgb, var(--positive) 10%, var(--surface));
  color: var(--ink);
}

.alert-error {
  border-left-color: var(--signal);
  border-color: color-mix(in srgb, var(--signal) 25%, transparent);
  background-color: color-mix(in srgb, var(--signal) 10%, var(--surface));
  color: var(--ink);
}

.alert ul { list-style: disc; padding-left: 1.25rem; display: flex; flex-direction: column; gap: .25rem; }

/* Bewegung ist Beiwerk. Wer sie abbestellt hat, bekommt sie nicht. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}
