/* shared.css - das Gestaltungssystem und die gemeinsamen Bausteine
 *
 * Wird NACH app.css bzw. portfolio.css geladen und gewinnt deshalb bei
 * gleicher Spezifitaet. Enthaelt: Farben, Masse, Hilfsklassen, alle
 * Bausteine, die mehr als eine Seite braucht.
 */

/* ======================================================================
 * FARBEN
 * ======================================================================
 * ANLASS war kein Geschmacksurteil, sondern eine Messung: im hellen Modus
 * lagen die Bedeutungsfarben unter dem Textminimum von 4,5:1.
 *
 *     Gruen  #10b981   2,54:1     16 Zahlen auf der Seite
 *     Gold   #f59e0b   2,15:1
 *     Rot    #f43f5e   3,67:1
 *
 * Ausgerechnet die Zahlen, auf die es ankommt - Gewinn, Verlust, Warnung -
 * waren die am schlechtesten lesbaren. Die Werte unten liegen bei 5,4 bis
 * 5,8:1.
 *
 * ZWEI FARBROLLEN, die vorher eine waren. `--primary-color` war zugleich
 * Markenfarbe (Knoepfe, aktiver Menuepunkt, Fokus) UND die Bedeutung
 * "positiv" (.text-green, .tag.ok, 27 Verwendungen). Dadurch war die halbe
 * Seite gruen und nichts hob sich ab. Jetzt:
 *
 *     --primary-color   BEDEUTUNG: Ertrag, Gewinn, erledigt
 *     --brand-color     BEDIENUNG: Knoepfe, aktiver Menuepunkt, Fokusring
 *
 * Die Bedienelemente treten damit aus den Daten heraus, statt mit ihnen um
 * dieselbe Farbe zu konkurrieren.
 *
 * Neutraltoene sind waermer als vorher. Das Blaustich-Grau (slate) ist die
 * Voreinstellung jedes Baukastens und laesst jede Oberflaeche gleich
 * aussehen; ein neutrales Grau laesst dem Akzent den Auftritt.
 */

:root {
    color-scheme: light;

    /* Flaechen */
    --bg-color:      #f6f6f5;
    --card-color:    #ffffff;
    --card-hover:    #fafaf9;
    --bg-subtle:     #f1f1ef;
    --border-color:  #e4e4e1;
    --border-strong: #d3d3cf;

    /* Schrift */
    --text-color:  #16161a;      /* 18,0:1 */
    --text-light:  #63636b;      /*  5,9:1 */

    /* Bedeutung */
    --primary-color: #0f7a4d;    /* 5,4:1 - Ertrag, Gewinn */
    --primary-hover: #0c6340;
    --primary-glow:  rgba(15, 122, 77, 0.10);
    --red-color:     #c0322c;    /* 5,6:1 - Verlust, Warnung */
    --red-glow:      rgba(192, 50, 44, 0.10);
    --gold-color:    #8a5d00;    /* 5,8:1 - Achtung */
    --gold-glow:     rgba(138, 93, 0, 0.10);
    /* Zwei Stufen desselben Blaus: die hellere ist die Diagrammfarbe (dort
       zaehlt Unterscheidbarkeit von den Nachbarfarben, nicht Textkontrast),
       die dunklere ist fuer Schrift - #2a78d6 lag auf Weiss bei 4,42:1 und
       damit knapp unter dem Textminimum. */
    --accent-color:  #2a78d6;    /* Flaeche, = Diagrammfarbe 1 */
    --accent-text:   #2569c0;    /* 5,4:1 - als Schrift */

    /* Bedienung */
    --brand-color: #4f46e5;      /* 6,3:1 */
    --brand-hover: #4338ca;
    --brand-glow:  rgba(79, 70, 229, 0.12);
    --brand-ring:  rgba(79, 70, 229, 0.35);

    /* Rundungen - vier benannte Stufen statt der vorher dreizehn freien
       Werte zwischen 2 und 999px */
    --rund-mini:  2px;           /* Wortmarke, Miniaturen */
    --rund-klein: 6px;           /* Eingaben, Badges, Balken */
    --rund:      10px;           /* Karten, Knoepfe, Leiste */
    --rund-voll: 999px;          /* Pillen */

    /* Erhebung. Vorher lag auf allem ein Schatten - das ist die Optik, die
       jede Baukasten-Oberflaeche traegt. Jetzt tragen Raender die Struktur,
       Schatten nur noch, was wirklich schwebt. */
    --schatten-1: 0 1px 2px rgba(16, 16, 20, 0.04);
    --schatten-2: 0 2px 4px rgba(16, 16, 20, 0.06),
                  0 1px 2px rgba(16, 16, 20, 0.04);
    --schatten-3: 0 16px 32px -12px rgba(16, 16, 20, 0.22);

    /* Schriftfarbe AUF einer gefuellten Bedeutungsflaeche (Zaehler, gefuellte
       Marke). Im hellen Modus sind die Bedeutungsfarben dunkel, also weisse
       Schrift; im dunklen sind sie hell, dann braucht es dunkle Schrift.
       Fest "weiss" ergab im Dunkeln 2,69:1 - unter dem Textminimum. */
    --auf-farbe: #ffffff;

    /* Hinweisblase. EINE Quelle fuer beide Sorten Hinweis auf dieser
       Oberflaeche: die Blasen in HTML (`.blase`) und die Hinweise der
       Diagramme, die Chart.js zeichnet. Vorher waren es zwei verschiedene
       Erscheinungen auf derselben Seite - die Blase kehrte sich um (im
       Dunkelmodus fast weiss mit dunkler Schrift), waehrend Chart.js seine
       Voreinstellung `rgba(0,0,0,0.8)` behielt: dunkel und durchscheinend.
       Nebeneinander sah das nach zwei Anwendungen aus.
       palette.js liest diese Werte und setzt damit die Chart.js-Vorgaben.

       Als Kanaele, nicht als Hexwert: so steht die Farbe EINMAL da und die
       Deckung laesst sich getrennt aendern, ohne dass beide auseinander
       laufen koennen. Die undurchsichtige Entsprechung ist --blase-voll -
       an ihr rechnet der Kontrasttest. */
    --blase-kanaele: 11 13 17;
    --blase-voll: #0b0d11;
    --blase-deckung: 0.88;
    --blase-schrift: #f4f4f5;

    /* Bewegung */
    --zeit-schnell: 120ms;
    --zeit:         200ms;
    --kurve: cubic-bezier(0.2, 0, 0.2, 1);
}

:root.dark-theme {
    color-scheme: dark;

    --bg-color:      #0d0f13;
    --card-color:    #14171d;
    --card-hover:    #1a1e26;
    --bg-subtle:     #101319;
    --border-color:  #242830;
    --border-strong: #333944;

    --text-color:  #f4f4f5;      /* 16,3:1 */
    --text-light:  #9a9aa6;      /*  6,5:1 */

    --primary-color: #3ddc97;    /* 10,2:1 */
    --primary-hover: #2bc383;
    --primary-glow:  rgba(61, 220, 151, 0.14);
    --red-color:     #ff7070;    /*  6,7:1 */
    --red-glow:      rgba(255, 112, 112, 0.14);
    --gold-color:    #f5b544;    /*  9,9:1 */
    --gold-glow:     rgba(245, 181, 68, 0.14);
    --accent-color:  #3987e5;
    --accent-text:   #7fb4f0;    /* 6,9:1 auf der dunklen Karte */

    --brand-color: #9b93ff;      /*  6,9:1 */
    --brand-hover: #b0a9ff;
    --brand-glow:  rgba(155, 147, 255, 0.16);
    --brand-ring:  rgba(155, 147, 255, 0.40);

    /* Dunkle Schrift auf den hellen Bedeutungsfarben - siehe hell */
    --auf-farbe: #0d0f13;

    /* Im Dunkeln traegt ein Schatten kaum - Helligkeit macht die Erhebung.
       Deshalb flacher als im hellen Modus, dafuer hellere Flaechen. */
    --schatten-1: 0 1px 2px rgba(0, 0, 0, 0.35);
    --schatten-2: 0 2px 6px rgba(0, 0, 0, 0.40);
    --schatten-3: 0 20px 40px -12px rgba(0, 0, 0, 0.65);
}

/* ======================================================================
 * MASSE
 * ======================================================================
 * ANLASS: in den Vorlagen standen 361 style="..."-Attribute mit zusammen
 * 762 Deklarationen - davon 297 reines Layout (Abstaende, Schriftgroessen,
 * flex/grid). Jede Seite hatte damit ihre eigene Vorstellung von "ein
 * bisschen Abstand", und eine Aenderung am Raster hiess: acht Dateien
 * anfassen. Ausserdem zwang es die Content-Security-Policy zu
 * style-src 'unsafe-inline'.
 *
 * Die Werte hier sind die TATSAECHLICH verwendeten - nichts ist beim
 * Herausziehen verschoben worden. Das Ergebnis sieht also aus wie vorher.
 *
 * OFFEN, bewusst nicht mitentschieden: die vier Schriftgroessen 0,78 / 0,80 /
 * 0,82 / 0,85rem liegen zusammen unter einem Pixel auseinander. Das sind vier
 * Stufen, wo zwei genuegen wuerden - aber sie zusammenzulegen ist eine
 * Gestaltungsentscheidung, keine Aufraeumarbeit. Deshalb stehen sie hier
 * einzeln, sichtbar nebeneinander.
 */

:root {
    /* Abstaende */
    --raum-1: 0.25rem;
    --raum-2: 0.5rem;
    --raum-3: 0.75rem;
    --raum-4: 1rem;
    --raum-5: 1.25rem;
    --raum-6: 1.5rem;
    --raum-8: 2rem;

    /* Schriftgroessen */
    --schrift-xs: 0.78rem;
    --schrift-s:  0.8rem;
    --schrift-m:  0.82rem;
    --schrift-l:  0.85rem;
    --schrift-xl: 0.9rem;
    --schrift-gross: 1.75rem;

    /* Zeilenhoehen */
    --zeile-eng:  1.4;
    --zeile-mittel: 1.45;
    --zeile-halb: 1.5;
    --zeile-weit: 1.6;

    /* Umbruchpunkte. Bis hierher gab es fuenf verschiedene ueber drei
     * Dateien verteilt (1200, 1024, 1000, 576, 500 px) - drei davon lagen
     * innerhalb von 200 px beieinander und meinten dasselbe.
     * CSS kann Variablen in @media nicht auswerten, die Werte stehen
     * deshalb ausgeschrieben; hier stehen sie als verbindliche Referenz.
     *   --umbruch-breit:  1024px   ab hier zweispaltig statt dreispaltig
     *   --umbruch-schmal:  560px   ab hier alles untereinander
     */
}

/* ----------------------------------------------------------------------
 * HILFSKLASSEN
 * ----------------------------------------------------------------------
 * Bewusst klein gehalten und mit u- praefixiert: sie ersetzen genau die
 * Deklarationen, die in den Vorlagen am haeufigsten vorkamen. Alles, was
 * nur ein- oder zweimal auftaucht, steht weiterhin inline - eine
 * Hilfsklasse je Einzelfall waere nur eine andere Art von Unordnung.
 */

/* Anordnung */
.u-flex    { display: flex; }
.u-grid    { display: grid; }
.u-block   { display: block; }
.u-none    { display: none; }
.u-inline  { display: inline; }
.u-col     { flex-direction: column; }
.u-wrap    { flex-wrap: wrap; }
.u-grow    { flex: 1; }
.u-between { justify-content: space-between; }
.u-mitte-x { justify-content: center; }
.u-ende-x  { justify-content: flex-end; }
.u-mitte   { align-items: center; }
.u-oben    { align-items: flex-start; }
.u-unten   { align-items: flex-end; }
.u-voll    { width: 100%; }
.u-rel     { position: relative; }
.u-zeiger  { cursor: pointer; }
.u-zwei    { grid-template-columns: 1fr 1fr; }

.u-hoch    { height: 100%; }

/* Zwischenraum */
.u-luft-2 { gap: var(--raum-2); }
.u-luft-3 { gap: var(--raum-3); }
.u-luft-4 { gap: var(--raum-4); }
.u-luft-5 { gap: var(--raum-5); }
.u-luft-6 { gap: var(--raum-6); }
.u-luft-8 { gap: var(--raum-8); }

/* Innenabstand */
.u-p-2    { padding: var(--raum-2); }
.u-p-3    { padding: var(--raum-3); }
.u-p-4    { padding: var(--raum-4); }

/* Flaeche und Rand */
.u-rand    { border: 1px solid var(--border-color); }
.u-flaeche { background: var(--bg-subtle); }
.u-primaer { color: var(--primary-color); }
.u-akzent  { color: var(--accent-text); }

/* Aussenabstand */
.u-m0     { margin: 0; }
.u-mt-0   { margin-top: 0; }
.u-mb-0   { margin-bottom: 0; }
.u-mt-8   { margin-top: var(--raum-8); }
.u-mb-8   { margin-bottom: var(--raum-8); }
.u-mt-2   { margin-top: var(--raum-2); }
.u-mt-3   { margin-top: var(--raum-3); }
.u-mt-4   { margin-top: var(--raum-4); }
.u-mt-5   { margin-top: var(--raum-5); }
.u-mt-6   { margin-top: var(--raum-6); }
.u-mb-2   { margin-bottom: var(--raum-2); }
.u-mb-3   { margin-bottom: var(--raum-3); }
.u-mb-4   { margin-bottom: var(--raum-4); }
.u-mb-5   { margin-bottom: var(--raum-5); }
.u-mb-6   { margin-bottom: var(--raum-6); }

/* Schrift */
.u-xs     { font-size: var(--schrift-xs); }
.u-s      { font-size: var(--schrift-s); }
.u-m      { font-size: var(--schrift-m); }
.u-l      { font-size: var(--schrift-l); }
.u-xl     { font-size: var(--schrift-xl); }
.u-gross  { font-size: var(--schrift-gross); }
.u-halbfett { font-weight: 600; }
.u-fett     { font-weight: 700; }
.u-normal   { font-weight: 500; }
.u-leise    { color: var(--text-light); }
.u-zeile      { line-height: var(--zeile-weit); }
.u-zeile-eng  { line-height: var(--zeile-eng); }
.u-zeile-mittel { line-height: var(--zeile-mittel); }

/* ======================================================================
 * GRUNDLAGE
 * ====================================================================== */

/* Google Fonts wurden entfernt: die App laedt nichts mehr von externen
 * Servern. Vorteile: funktioniert offline, keine IP-Uebermittlung an Google,
 * und die Content-Security-Policy bleibt eng. */
body,
input, select, textarea, button {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI',
                 Roboto, 'Helvetica Neue', Arial, sans-serif;
}

body {
    background-color: var(--bg-color);
    color: var(--text-color);
    margin: 0;
    padding: var(--raum-6);
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
    transition: background-color var(--zeit), color var(--zeit);
}

/* TABELLENZIFFERN.
 *
 * Der groesste einzelne Gewinn fuer eine Anwendung, die fast nur aus Zahlen
 * besteht: in der Standardeinstellung ist die 1 schmaler als die 8, wodurch
 * untereinanderstehende Betraege nicht fluchten und das Auge beim Vergleichen
 * springen muss. `tabular-nums` gibt jeder Ziffer dieselbe Breite.
 *
 * Global gesetzt, weil in dieser Anwendung praktisch jede Zahl eine Zahl in
 * einer Spalte ist - Betraege, Prozente, Datumsangaben, Stueckzahlen. */
body {
    font-variant-numeric: tabular-nums;
}

*:focus-visible {
    outline: 2px solid var(--brand-color);
    outline-offset: 2px;
    border-radius: var(--rund-klein);
}

/* Waehrend des Themenwechsels alle Uebergaenge stilllegen - siehe die
   ausfuehrliche Begruendung in theme.js. Kurzfassung: aendert sich nur eine
   CSS-Variable, startet der Browser eine laufende background-color-Ueberblendung
   nicht neu, und die Flaeche behaelt die alte Farbe. Im hellen Modus stand
   dann dunkle Schrift auf dunkler Karte. */
.theme-wechsel,
.theme-wechsel *,
.theme-wechsel *::before,
.theme-wechsel *::after {
    transition: none !important;
}

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

/* ======================================================================
 * BAUSTEINE
 * ======================================================================
 * Alles hier stand vorher DOPPELT - je einmal in app.css und portfolio.css.
 * Neunzehn Selektoren, darunter zwei vollstaendige :root-Bloecke. Zweimal
 * hat genau das schon einen Fehler verursacht: eine Regel wurde in der einen
 * Datei geaendert und in der anderen vergessen.
 */

/* --- Anwendungsrahmen -------------------------------------------------- */
/* VORHER: eine schwebende, rundum gerahmte Navigationsbox mit Schatten,
   darunter ein Raster gleichwertiger Kaesten. Das ist die Anordnung, die
   jede Baukasten-Oberflaeche hat - und der Grund, warum die Anwendung
   "Standard" wirkte, unabhaengig von der Farbe.
   JETZT: eine randlose Leiste, die am oberen Rand klebt, mit einer
   Haarlinie als Abschluss. Der Inhalt beginnt direkt darunter mit einer
   Seitenueberschrift. */

body { padding: 0; }

.app-leiste {
    position: sticky;
    top: 0;
    z-index: 50;
    background: color-mix(in srgb, var(--card-color) 82%, transparent);
    backdrop-filter: saturate(180%) blur(12px);
    -webkit-backdrop-filter: saturate(180%) blur(12px);
    border-bottom: 1px solid var(--border-color);
}

.leiste-innen {
    max-width: 1600px;
    margin: 0 auto;
    padding: 0 var(--raum-6);
    height: 54px;
    display: flex;
    align-items: center;
    gap: var(--raum-8);
}

/* Wortmarke - gibt der Leiste einen Anfang. Vorher begann die Seite mit
   dem ersten Menuepunkt. */
.marke {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    text-decoration: none;
    color: var(--text-color);
    font-weight: 600;
    font-size: 0.9375rem;
    letter-spacing: -0.015em;
    white-space: nowrap;
}

.marke-zeichen {
    width: 9px;
    height: 9px;
    border-radius: var(--rund-mini);
    background: var(--brand-color);
    transform: rotate(45deg);
}

.haupt-nav {
    display: flex;
    align-items: center;
    gap: 0.15rem;
    margin-right: auto;
}

/* Der aktive Punkt bekommt eine Pille statt eines Unterstrichs. Ein
   Unterstrich am Rand einer randlosen Leiste haette nichts, woran er sich
   ausrichtet. */
.haupt-nav a {
    position: relative;
    text-decoration: none;
    color: var(--text-light);
    font-weight: 500;
    font-size: 0.8438rem;
    letter-spacing: -0.005em;
    padding: 0.4rem 0.7rem;
    border-radius: var(--rund-klein);
    white-space: nowrap;
    transition: color var(--zeit-schnell), background-color var(--zeit-schnell);
}

.haupt-nav a:hover {
    color: var(--text-color);
    background: var(--bg-subtle);
}

.haupt-nav a.active {
    color: var(--text-color);
    font-weight: 600;
    background: var(--bg-subtle);
}

.leiste-rechts {
    display: flex;
    align-items: center;
    gap: var(--raum-3);
}

.leiste-knopf {
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--rund-klein);
    padding: 0.3rem 0.45rem;
    font-size: 1rem;
    line-height: 1;
    cursor: pointer;
    color: var(--text-light);
    transition: background-color var(--zeit-schnell);
}

.leiste-knopf:hover { background: var(--bg-subtle); }

/* --- Inhaltsbereich ---------------------------------------------------- */

.container,
.dashboard-container {
    max-width: 1600px;
    margin: 0 auto;
    padding: var(--raum-8) var(--raum-6) var(--raum-8);
    animation: none;                      /* kein Einfahren mehr */
}

.container { max-width: 1100px; }

/* --- Seitenkopf -------------------------------------------------------- */
/* Vorher hatte keine Seite eine Ueberschrift - der Inhalt begann direkt mit
   dem ersten Kasten, und wo man war, stand nur im Menue. */

.seitenkopf {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--raum-4);
    flex-wrap: wrap;
    margin-bottom: var(--raum-8);
    padding-bottom: var(--raum-5);
    border-bottom: 1px solid var(--border-color);
}

.seitenkopf h1 {
    margin: 0;
    font-size: clamp(1.5rem, 2.6vw, 1.9rem);
    font-weight: 600;
    letter-spacing: -0.025em;
    line-height: 1.15;
}

.seitenkopf-zusatz {
    margin: 0.35rem 0 0 0;
    color: var(--text-light);
    font-size: 0.875rem;
}

.seitenkopf-aktionen {
    display: flex;
    align-items: center;
    gap: var(--raum-2);
}

/* --- Karte ------------------------------------------------------------- */

.card {
    background-color: var(--card-color);
    border: 1px solid var(--border-color);
    border-radius: var(--rund);
    box-shadow: none;
    padding: var(--raum-6);
    display: flex;
    flex-direction: column;
    position: relative;
    transition: border-color var(--zeit), background-color var(--zeit);
}

/* Kein Anheben beim Ueberfahren. Eine Karte, die sich bewegt, verspricht
   eine Aktion - diese Karten sind aber Anzeigen, nicht Schaltflaechen. */
.card:hover { border-color: var(--border-strong); }

/* Die Ueberschrift trug vorher einen gruenen Balken links. Bei bis zu zehn
   Karten je Seite waren das zehn Balken, die alle dasselbe sagten: "hier
   faengt eine Karte an" - was der Rand der Karte schon sagt. Jetzt traegt
   die Schrift selbst die Auszeichnung, und zwar als richtige Ueberschrift
   in Normalschreibung statt als Versalien-Etikett. */
.card-title {
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--text-color);
    text-transform: none;
    letter-spacing: -0.01em;
    margin: 0 0 var(--raum-4) 0;
    padding: 0;
    border: none;
}

/* --- Kennzahlenleiste -------------------------------------------------- */
/* Die oberste Reihe traegt die vier, fuenf Zahlen, um die es geht. Als
   gerahmte Kaesten standen sie gleichberechtigt neben jedem Diagramm und
   jeder Liste darunter. Jetzt: EIN Feld, innen durch Haarlinien geteilt -
   die Zahlen stehen zusammen, wie sie zusammengehoeren, und der Rest der
   Seite tritt zurueck. */

.kpi-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 0;
    background: var(--card-color);
    border: 1px solid var(--border-color);
    border-radius: var(--rund);
    overflow: hidden;
}

.kpi-grid > .card {
    border: none;
    border-radius: 0;
    border-left: 1px solid var(--border-color);
    padding: var(--raum-5) var(--raum-6);
    background: transparent;
}

.kpi-grid > .card:first-child { border-left: none; }
.kpi-grid > .card:hover { background: var(--card-hover); }

/* In der Kennzahlenleiste bleibt die Ueberschrift ein kleines Etikett -
   dort IST sie eine Beschriftung ueber einer Zahl, keine Ueberschrift. */
.kpi-grid .card-title {
    font-size: 0.6875rem;
    font-weight: 600;
    color: var(--text-light);
    text-transform: uppercase;
    letter-spacing: 0.07em;
    margin-bottom: var(--raum-2);
}

/* --- Zahlen ------------------------------------------------------------ */
/* Die Hauptzahl war 2,2rem und stand damit kaum ueber dem Fliesstext.
   In einer Anwendung, die man oeffnet, um EINE Zahl abzulesen, darf die
   Zahl das Bild bestimmen. */

.main-stat,
.dividends-main-value {
    font-size: clamp(1.6rem, 3.2vw, 2.1rem);
    font-weight: 600;
    letter-spacing: -0.03em;
    line-height: 1.1;
    margin: 0;
    color: var(--text-color);
    font-variant-numeric: tabular-nums;
}

.dividends-main-value {
    font-size: clamp(2rem, 4.2vw, 2.9rem);
    color: var(--primary-color);
}

.meta-line {
    font-size: 0.8125rem;
    color: var(--text-light);
    margin: 0.35rem 0 0 0;
    line-height: 1.45;
}

/* --- Schaltflaechen ---------------------------------------------------- */

.btn {
    background: var(--brand-color);
    color: var(--auf-farbe);
    border: 1px solid transparent;
    padding: 0.55rem 1.1rem;
    border-radius: var(--rund-klein);
    cursor: pointer;
    font-weight: 500;
    font-size: 0.875rem;
    line-height: 1.3;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--raum-2);
    box-shadow: none;
    transition: background-color var(--zeit-schnell),
                border-color var(--zeit-schnell);
}

.btn:hover  { background: var(--brand-hover); }
.btn:active { background: var(--brand-hover); transform: translateY(1px); }

.btn.secondary {
    background: transparent;
    color: var(--text-color);
    border-color: var(--border-strong);
}

.btn.secondary:hover {
    background: var(--card-hover);
    border-color: var(--text-light);
    color: var(--text-color);
}

.btn.danger {
    background: transparent;
    color: var(--red-color);
    border-color: var(--red-color);
}

.btn.danger:hover { background: var(--red-glow); }

.btn:disabled,
.btn[disabled] { opacity: 0.5; cursor: not-allowed; }

/* --- Bedeutungsfarben -------------------------------------------------- */

.text-green { color: var(--primary-color) !important; font-weight: 600; }
.text-red   { color: var(--red-color)     !important; font-weight: 600; }
.text-gold  { color: var(--gold-color)    !important; font-weight: 600; }

/* --- Listenzeile ------------------------------------------------------- */

.sub-stats-list li,
.detail-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 0.875rem;
    padding: 0.55rem 0;
    border-bottom: 1px solid var(--border-color);
    transition: border-color var(--zeit);
}

.sub-stats-list li:last-child,
.detail-item:last-child { border-bottom: none; padding-bottom: 0; }

/* --- Eingaben ---------------------------------------------------------- */
/* Standen vorher nur teilweise und uneinheitlich in den Seitendateien -
   deshalb sahen dieselben Felder auf Portfolio und Verlauf verschieden aus. */

input[type="text"],
input[type="number"],
input[type="date"],
input[type="month"],
input[type="file"],
input[type="search"],
select,
textarea {
    width: 100%;
    box-sizing: border-box;
    background: var(--card-color);
    color: var(--text-color);
    border: 1px solid var(--border-strong);
    border-radius: var(--rund-klein);
    padding: 0.5rem 0.65rem;
    font-size: 0.875rem;
    line-height: 1.4;
    transition: border-color var(--zeit-schnell), box-shadow var(--zeit-schnell);
}

input:hover:not(:disabled),
select:hover:not(:disabled),
textarea:hover:not(:disabled) { border-color: var(--text-light); }

input:focus,
select:focus,
textarea:focus {
    outline: none;
    border-color: var(--brand-color);
    box-shadow: 0 0 0 3px var(--brand-ring);
}

input:disabled,
select:disabled { background: var(--bg-subtle); color: var(--text-light); }

label {
    display: block;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--text-light);
    margin-bottom: 0.3rem;
    letter-spacing: 0.01em;
}

.form-group { margin-bottom: var(--raum-4); }

/* Ankreuzfelder in der Markenfarbe statt im Browser-Blau */
input[type="checkbox"],
input[type="radio"] {
    width: auto;
    accent-color: var(--brand-color);
    margin-right: 0.4rem;
}

/* --- Marken und Pillen ------------------------------------------------- */

.tag,
.badge {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.1rem 0.5rem;
    border-radius: var(--rund-voll);
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    line-height: 1.6;
    white-space: nowrap;
}

.tag.ok      { background: var(--primary-glow); color: var(--primary-color); }
.tag.warn    { background: var(--gold-glow);    color: var(--gold-color); }
.tag.danger  { background: var(--red-glow);     color: var(--red-color); }
.tag.neutral { background: var(--bg-subtle);    color: var(--text-light); }

/* Zaehler am Menuepunkt - klein, rund, an der Schrift ausgerichtet */
.nav-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 17px;
    height: 17px;
    padding: 0 4px;
    margin-left: 5px;
    border-radius: var(--rund-voll);
    font-size: 0.625rem;
    font-weight: 700;
    line-height: 1;
    vertical-align: middle;
}

.nav-badge.rot    { background: var(--red-color);  color: var(--auf-farbe); }
.nav-badge.orange { background: var(--gold-color); color: var(--auf-farbe); }

/* --- Hinweise ---------------------------------------------------------- */
/* Linke Kante statt Rundum-Rahmen: der Hinweis soll sich an den Text
   anlehnen, nicht als zweite Karte in der Karte stehen. */

.notice {
    display: flex;
    gap: var(--raum-3);
    align-items: flex-start;
    background: var(--bg-subtle);
    border: 1px solid var(--border-color);
    border-left: 3px solid var(--text-light);
    border-radius: var(--rund-klein);
    padding: var(--raum-3) var(--raum-4);
    font-size: 0.8125rem;
    line-height: 1.55;
    margin-bottom: var(--raum-4);
}

.notice.warning { border-left-color: var(--gold-color); background: var(--gold-glow); }
.notice.danger  { border-left-color: var(--red-color);  background: var(--red-glow); }
.notice.ok      { border-left-color: var(--primary-color); background: var(--primary-glow); }

/* --- Tabellen ---------------------------------------------------------- */

table { border-collapse: collapse; width: 100%; font-size: 0.8125rem; }

th {
    text-align: left;
    font-size: 0.6875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-light);
    padding: 0.5rem 0.6rem;
    border-bottom: 1px solid var(--border-strong);
    white-space: nowrap;
}

td {
    padding: 0.5rem 0.6rem;
    border-bottom: 1px solid var(--border-color);
}

tbody tr:last-child td { border-bottom: none; }
tbody tr:hover { background: var(--card-hover); }

/* Zahlen gehoeren rechts - dann fluchten die Stellen untereinander und die
   Tabellenziffern koennen ihre Wirkung entfalten. */
td.zahl, th.zahl { text-align: right; }

/* --- Monatsprofil der Ausschuettungen ---------------------------------- */
/* Zwoelf Zeilen statt eines Diagramms: die Werte sollen ABLESBAR sein, nicht
   nur vergleichbar. Ein Balkendiagramm haette dieselbe Information, aber man
   muesste die Zahlen daneben trotzdem hinschreiben. */

.monatsprofil {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
}

.monatsprofil li {
    display: grid;
    grid-template-columns: 2.4rem 1fr 5.5rem 2.4rem;
    align-items: center;
    gap: var(--raum-3);
    font-size: 0.8125rem;
    padding: 0.15rem 0;
}

.mp-name  { color: var(--text-light); font-weight: 600; }
.mp-wert  { text-align: right; font-weight: 600; }
.mp-zahl  { text-align: right; color: var(--text-light); font-size: 0.75rem; }

.mp-balken {
    height: 8px;
    background: var(--bg-subtle);
    border-radius: var(--rund-voll);
    overflow: hidden;
}

.mp-balken > span {
    display: block;
    height: 100%;
    background: var(--primary-color);
    border-radius: var(--rund-voll);
}

/* Duenne Monate tragen die Warnfarbe - sie sind die Aussage der Karte. */
.monatsprofil li.duenn .mp-balken > span { background: var(--gold-color); }
.monatsprofil li.duenn .mp-name,
.monatsprofil li.duenn .mp-wert { color: var(--gold-color); }

/* Anteilsliste - woran das Einkommen haengt. Gleiche Bauform wie das
   Monatsprofil, aber der Name braucht Platz und muss kuerzen duerfen:
   "Global X Superdividend UCITS ETF" passt sonst auf keinem Telefon. */
.anteilsliste {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
}

.anteilsliste li {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 6rem 5rem 3.5rem;
    align-items: center;
    gap: var(--raum-3);
    font-size: 0.8125rem;
    padding: 0.15rem 0;
}

.al-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}
.al-wert   { text-align: right; font-weight: 600; }
.al-anteil { text-align: right; color: var(--text-light); }

.al-balken {
    height: 8px;
    background: var(--bg-subtle);
    border-radius: var(--rund-voll);
    overflow: hidden;
}

.al-balken > span {
    display: block;
    height: 100%;
    background: var(--primary-color);
    border-radius: var(--rund-voll);
}

/* Die groesste Quelle traegt die Warnfarbe, sobald sie ueber die Haelfte
   geht - dann ist die Konzentration die Aussage der Karte. */
.anteilsliste li:first-child .al-balken > span { background: var(--accent-color); }

/* Die Beitragsliste teilt sich die Bauform mit der Anteilsliste, hat aber
   drei Zahlenspalten statt Balken und Anteil: Kurs, Ausschuettungen, Summe.
   Ein Balken waere hier sinnlos - die Werte haben beide Vorzeichen. */
.beitragsliste li {
    grid-template-columns: minmax(0, 1fr) 6.5rem 6.5rem 7rem;
}

/* Kuerzungen. Kurze Liste, drei Spalten, keine Balken - die Zahl selbst ist
   die Aussage, ein Balken wuerde nur Flaeche fuellen. */
.kuerzliste {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--raum-2);
}

.kuerzliste li {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 5rem 7rem;
    align-items: baseline;
    gap: var(--raum-3);
    font-size: var(--schrift-l);
    padding-bottom: var(--raum-2);
    border-bottom: 1px solid var(--border-color);
}
.kuerzliste li:last-child { border-bottom: none; padding-bottom: 0; }

.kl-name  { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kl-wert  { text-align: right; font-weight: 700; }
.kl-jahre { text-align: right; color: var(--text-light); font-size: var(--schrift-xs); }

/* --- Code -------------------------------------------------------------- */

code {
    background: var(--bg-subtle);
    border: 1px solid var(--border-color);
    border-radius: var(--rund-klein);
    padding: 0.1em 0.35em;
    font-size: 0.9em;
    font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas,
                 'Liberation Mono', monospace;
}

/* --- Modale Overlays --------------------------------------------------- */
/* Muss hier stehen, nicht in app.css: portfolio.css definiert
 * .modal-overlay nur mit backdrop-filter, ohne Positionierung. Das
 * Fortschritts-Fenster beim Kursupdate hing dadurch oben in der Seite statt
 * zentriert im Vordergrund. shared.css wird von allen Seiten geladen. */

.modal-overlay {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    background: rgba(11, 15, 25, 0.65);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    display: none;
    align-items: center;
    justify-content: center;
    z-index: 9999;
    padding: 1rem;
    box-sizing: border-box;
    animation: fadeInModal 0.25s ease-out;
}

/* Wird per JS auf 'flex' gesetzt */
.modal-overlay.open { display: flex; }

.modal-content {
    background: var(--card-color);
    color: var(--text-color);
    padding: 2.25rem;
    border-radius: var(--rund);
    border: 1px solid var(--border-color);
    width: 100%;
    max-width: 480px;
    max-height: 90vh;
    overflow-y: auto;
    box-shadow: var(--schatten-3);
    animation: slideInModal 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
    transition: background-color 0.3s, border-color 0.3s, color 0.3s;
}

@keyframes fadeInModal {
    from { opacity: 0; }
    to   { opacity: 1; }
}

@keyframes slideInModal {
    from { opacity: 0; transform: translateY(18px) scale(0.97); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}

/* --- Flash-Messages ---------------------------------------------------- */
/* Frueher liefen Fehler still in ein print() - der Nutzer sah die
 * unveraenderte Seite und hielt das fuer einen Bedienfehler. */

.flash-container {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    margin-bottom: 1.5rem;
}

.flash {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    padding: 0.9rem 1.1rem;
    border-radius: var(--rund);
    font-size: 0.92rem;
    font-weight: 500;
    border: 1px solid transparent;
    background: var(--card-color);
    animation: flash-in 0.25s ease-out;
}

@keyframes flash-in {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: translateY(0); }
}

.flash-icon { font-size: 1.05rem; line-height: 1.3; }
.flash-text { flex-grow: 1; line-height: 1.45; }

.flash-close {
    background: none;
    border: none;
    color: inherit;
    opacity: 0.55;
    cursor: pointer;
    font-size: 1.1rem;
    padding: 0 0.2rem;
    line-height: 1;
}
.flash-close:hover { opacity: 1; }

.flash.success {
    border-color: var(--primary-color);
    background: var(--primary-glow);
    color: var(--text-color);
}
.flash.error {
    border-color: var(--red-color);
    background: rgba(244, 63, 94, 0.1);
    color: var(--text-color);
}
.flash.warning {
    border-color: var(--gold-color);
    background: rgba(245, 158, 11, 0.1);
    color: var(--text-color);
}

/* --- Hinweisbanner ----------------------------------------------------- */

/* Der Rest von `.notice` und `.tag` steht oben bei den Komponenten. Hier
   lagen zwei aeltere Fassungen mit fest eingetragenen rgba-Werten und
   Rundum-Rahmen; weil sie SPAETER standen, gewannen sie - die linke Kante
   und die Glow-Token waren gebaut, aber nie zu sehen. */
.notice strong { color: var(--text-color); }

/* --- Zaehler am Menuepunkt --------------------------------------------- */
/* Zeigt offene rote/orange Signale des Beraters von jeder Seite aus an.
   Ohne das steht ein Befund auf einer Seite, die man wochenlang nicht
   aufruft. Ein rotes Signal gewinnt die Farbe, auch wenn orange ueberwiegt. */

/* --- Freibetrags-Anzeige ----------------------------------------------- */

.allowance-widget { margin-top: 1rem; }

.allowance-bar {
    height: 8px;
    border-radius: var(--rund-klein);
    background: var(--bg-subtle);
    border: 1px solid var(--border-color);
    overflow: hidden;
    margin-top: 0.4rem;
}
.allowance-bar > div {
    height: 100%;
    background: var(--primary-color);
    transition: width 0.4s ease;
}
.allowance-bar.exceeded > div {
    background: var(--red-color);
}

.allowance-labels {
    display: flex;
    justify-content: space-between;
    font-size: 0.78rem;
    color: var(--text-light);
    margin-top: 0.35rem;
}

/* --- Aktionen als Formular-Buttons ------------------------------------- */
/* Loeschen laeuft jetzt ueber POST - der Button muss aber aussehen wie der
 * frueher verwendete Icon-Link. */

.icon-btn {
    background: none;
    border: none;
    padding: 0;
    font-size: 1rem;
    cursor: pointer;
    line-height: 1;
    transition: opacity 0.2s, transform 0.2s;
}
.icon-btn:hover { opacity: 0.65; transform: scale(1.12); }

.actions form { display: inline; margin: 0; }

/* --- Autocomplete ------------------------------------------------------ */

.ac-item {
    padding: 0.7rem 1rem;
    cursor: pointer;
    border-bottom: 1px solid var(--border-color);
    font-size: 0.9rem;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 0.75rem;
}
.ac-item:last-child { border-bottom: none; }
.ac-item:hover, .ac-item.active { background: var(--card-hover); }
.ac-name { color: var(--text-light); margin-left: 0.5rem; }

/* --- Tabellen-Fussnote / Metadaten ------------------------------------- */

.meta-line {
    font-size: 0.72rem;
    color: var(--text-light);
    margin-top: 0.15rem;
}

.empty-state {
    padding: 2.5rem 1rem;
    text-align: center;
    color: var(--text-light);
    font-size: 0.92rem;
}
.empty-state .big { font-size: 2rem; display: block; margin-bottom: 0.5rem; }

/* --- Formulargruppen und Eingabefelder ---------------------------------- */
/* Standen bis zuletzt nur in portfolio.css und damit nur den Seiten zur
   Verfügung, die diese Datei laden. Tipps- und Verlaufsseite laden
   app.css und hatten dadurch ungestylte Eingabefelder. */

.form-group {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}

.form-group label {
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--text-light);
}

input, select {
    background-color: var(--bg-subtle);
    color: var(--text-color);
    border: 1px solid var(--border-color);
    border-radius: var(--rund-klein);
    padding: 0.7rem 0.85rem;
    font-size: 0.9rem;
    outline: none;
    box-sizing: border-box;
    transition: border-color 0.2s ease, box-shadow 0.2s ease, background-color 0.3s;
}

input:focus, select:focus {
    border-color: var(--primary-color);
    box-shadow: 0 0 0 3px var(--primary-glow);
}

/* Ankreuzfelder und Auswahlknöpfe sollen die Rahmen-/Polsterregeln oben
   NICHT erben - sonst werden sie zu Kästen in Eingabefeldgröße. */
input[type="checkbox"], input[type="radio"] {
    padding: 0;
    width: auto;
    accent-color: var(--primary-color);
}

/* --- Verlaufsseite ------------------------------------------------------ */

/* Hier stand eine zweite `.kpi-grid`-Regel mit `gap: 1.5rem`. Sie ist beim
   Umbau auf die Komponentenschicht liegengeblieben und hat, weil sie SPAETER
   steht, die Kennzahlenleiste oben stillschweigend wieder auseinander-
   gezogen - aus einem Feld mit Haarlinien wurden fuenf einzelne Kaesten.
   Denselben Fehler machte spaeter `.monatsbalken` (Befund D16). */

.main-stat {
    font-size: 1.85rem;
    font-weight: 800;
    letter-spacing: -0.02em;
    margin: 0 0 0.35rem 0;
}

/* Die beiden Renditezahlen. Sie stehen nebeneinander, weil jede fuer sich
   irrefuehrend ist: die geldgewichtete allein liest sich als Urteil ueber die
   Papiere, die zeitgewichtete allein als Urteil ueber das eigene Geld. Die
   Trennlinie dazwischen sagt "zwei Antworten", nicht "eine mit Zusatz". */
.rendite-paar {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--raum-6);
}
.rendite-paar > div + div {
    padding-left: var(--raum-6);
    border-left: 1px solid var(--border-color);
}
.r-frage {
    display: block;
    font-size: var(--schrift-m);
    font-weight: 600;
    color: var(--text-light);
    margin-bottom: var(--raum-2);
}

.zwei-spalten {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1.5rem;
}
@media (max-width: 1024px) {
    .zwei-spalten { grid-template-columns: 1fr; }
}

/* Lange Befehlszeilen (z.B. der docker-Aufruf auf der Tipps-Seite) duerfen
   umbrechen, statt die Seite aufzuschieben - sonst scrollt auf einem Telefon
   die ganze Seite seitlich wegen eines einzigen <code>-Elements. */
code {
    overflow-wrap: anywhere;
}

/* Die beiden Eingabefelder unter dem Simulations-Schieberegler. Zwei
   Zahlenfelder nebeneinander brauchen zusammen rund 450px - mehr, als ein
   Telefon hergibt. */
.regler-felder {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 15px;
}

/* Die linke Spalte der Simulationskarte. Das feste min-width: 300px stand
   frueher inline - es verhinderte, dass die Karte auf einem Telefon
   schmaler wird, und schob damit die ganze Startseite auf 454px auf. */
.sim-spalte {
    flex: 1.2;
    min-width: 300px;
    display: flex;
    flex-direction: column;
    gap: var(--raum-4);
}

/* ======================================================================
 * STARTSEITE - verdichtete Uebersicht
 * ======================================================================
 * ANLASS: die Startseite bestand aus langen Fliesstexten und einer Liste mit
 * zehn Zielstufen, von denen acht gesperrt waren. Der Platz ging an
 * Erklaerungen, die man einmal liest, statt an Zahlen, die man taeglich
 * ansieht.
 *
 * Jetzt liegt der erklaerende Text im Mouse-over; sichtbar bleiben
 * Bezeichnung, Zahl und Einheit. Von den Zielen steht nur das naechste da.
 */

.uebersicht {
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    gap: var(--raum-4);
    margin-bottom: var(--raum-6);
}
.sp12 { grid-column: span 12; }
.sp8  { grid-column: span 8; }
.sp4  { grid-column: span 4; }

/* Der erklaerende Text. Bewusst auch per TASTATUR erreichbar - ein Hinweis,
   den nur die Maus oeffnet, existiert fuer die halbe Bedienung nicht.
   Deshalb :focus-within und ein tabindex am Traeger. */
.hat-info { position: relative; }

.hat-info > .blase {
    position: absolute;
    z-index: 40;
    top: calc(100% + var(--raum-2));
    left: 0;
    width: max(100%, 19rem);
    max-width: 25rem;
    /* Ohne border-box zaehlt der Innenabstand ZUSAETZLICH zur Breite: aus
       19 rem wurden 363 px statt 343, und die Blase ragte aus der Seite.
       Das Projekt hat keinen globalen box-sizing-Reset. */
    box-sizing: border-box;
    /* Dunkel und durchscheinend, in BEIDEN Modi - genau wie die Hinweise in
       den Diagrammen. Vorher lief die Blase ueber --text-color und kehrte
       sich damit um: im Dunkelmodus eine fast weisse Flaeche neben einem
       dunklen Chart.js-Hinweis, keine drei Zentimeter entfernt.
       Lesbar bleibt sie mit Abstand: bei 88 % Deckung ueber dem hellsten
       denkbaren Untergrund (weiss) ergibt die Schrift noch 12,8:1. */
    background: rgb(var(--blase-kanaele) / var(--blase-deckung));
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    color: var(--blase-schrift);
    border-radius: var(--rund-klein);
    padding: var(--raum-3);
    font-size: var(--schrift-s);
    line-height: var(--zeile-mittel);
    font-weight: 400;
    text-transform: none;
    letter-spacing: 0;
    opacity: 0;
    visibility: hidden;
    transform: translateY(-3px);
    transition: opacity var(--zeit-schnell), transform var(--zeit-schnell),
                visibility var(--zeit-schnell);
    box-shadow: var(--schatten-3);
}

/* Am rechten Rand nach links ausrichten, sonst laeuft die Blase aus der
   Seite heraus. */
.hat-info.rechts > .blase { left: auto; right: 0; }

.hat-info:hover > .blase,
.hat-info:focus-within > .blase {
    opacity: 1;
    visibility: visible;
    transform: none;
}

/* Auf der dunklen Blase gilt IMMER die helle Schrift - auch fuer die Teile,
   die sonst eine eigene Farbe tragen. Im hellen Modus waere `--text-color`
   hier fast schwarz auf fast schwarz. */
.blase strong { color: var(--blase-schrift); font-weight: 600; }
.blase em { color: var(--blase-schrift); }
.blase a {
    color: var(--blase-schrift);
    text-decoration: underline;
    text-underline-offset: 2px;
}

/* Ein Wort im Fliesstext, an dem eine Erklaerung haengt. */
.info-wort {
    cursor: help;
    border-bottom: 1px dotted var(--border-strong);
}

@media (prefers-reduced-motion: reduce) {
    .hat-info > .blase { transition: none; }
}

/* --- Ziel-Ring --------------------------------------------------------- */

.ziel-block { display: flex; align-items: center; gap: var(--raum-5); }

.ziel-ring { flex: none; }
.ziel-ring circle { fill: none; stroke-width: 9; }
.ziel-ring .spur { stroke: var(--bg-subtle); }
.ziel-ring .fuellung {
    stroke: var(--primary-color);
    stroke-linecap: round;
    transform: rotate(-90deg);
    transform-origin: 50% 50%;
}

/* Die uebrigen Stufen als Punkte - erreichte gefuellt, offene blass. Aus
   zehn Listenzeilen sind damit zehn Punkte geworden. */
.ziel-punkte {
    display: flex;
    gap: var(--raum-1);
    align-items: center;
    margin-top: var(--raum-2);
}
.ziel-punkt {
    width: 7px;
    height: 7px;
    border-radius: var(--rund-voll);
    background: var(--primary-color);
}
.ziel-punkt.offen { background: var(--border-strong); }

/* --- Kachelband -------------------------------------------------------- */

.kachelband {
    display: grid;
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: var(--raum-4);
    grid-column: span 12;
}

.kachel {
    background: var(--card-color);
    border: 1px solid var(--border-color);
    border-radius: var(--rund);
    box-shadow: var(--schatten-1);
    padding: var(--raum-3) var(--raum-4);
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--raum-1);
}

.kachel-titel {
    font-size: var(--schrift-xs);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-light);
    margin: 0;
}

.kachel-wert {
    font-size: 1.35rem;
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
    margin: 0;
}

.kachel-fuss { font-size: var(--schrift-xs); color: var(--text-light); }

/* Die Mikroskala sagt, WO im moeglichen Bereich der Wert liegt. Ihre Farbe
   kodiert den Zustand - damit ist er ohne Lesen erkennbar. */
.mikroskala {
    height: 3px;
    border-radius: var(--rund-voll);
    background: var(--bg-subtle);
    overflow: hidden;
    margin-top: var(--raum-1);
}
.mikroskala > span {
    display: block;
    height: 100%;
    border-radius: var(--rund-voll);
    background: var(--primary-color);
}
.kachel.achtung  .mikroskala > span { background: var(--gold-color); }
.kachel.kritisch .mikroskala > span { background: var(--red-color); }

/* --- Ausschuettungskalender -------------------------------------------- */

/* HEISST BEWUSST NICHT `.monatsbalken`. Diesen Namen belegt die Plan-Seite
   fuer ihren Erfuellungsstreifen - und weil ihre Regel spaeter in derselben
   Datei steht, hat sie `display: grid` hier stillschweigend auf `flex`
   zurueckgesetzt. Die zwoelf Saeulen standen dadurch zusammengedraengt am
   linken Rand statt ueber die volle Kartenbreite. */

/* Die Karte fuellt ihre Zeile. Im Gitter ist sie so hoch wie „Was
   auffaellt" daneben (dort 319 px); ihr eigener Inhalt brauchte nur 210.
   Die Saeulen klebten dadurch oben, darunter stand ein Streifen Nichts.
   `flex: 1` auf der Saeulenflaeche verteilt die Zeilenhoehe auf das
   Diagramm, statt sie unten liegenzulassen. */
.karte-fuellt { display: flex; flex-direction: column; }

.zahlmonate {
    display: flex;
    flex-direction: column;
    gap: var(--raum-2);
    flex: 1;
    min-height: 150px;
}

/* Saeulen und Beschriftung sind ZWEI Gitter, nicht eines mit zwoelf
   Spalten aus je Saeule und Text. Grund ist die Durchschnittslinie: eine
   Saeule mit `height: 62 %` muss 62 % der Flaeche hoch sein, an der auch
   die Linie haengt. Steckte die Beschriftung mit in der Spalte, waeren die
   Prozente auf eine Hoehe INKLUSIVE Textzeile bezogen und die Linie liefe
   um deren Hoehe daneben - sichtbar falsch, gerade bei den kurzen Saeulen. */
.zahlmonate .saeulen {
    position: relative;
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    gap: var(--raum-2);
    align-items: end;
    flex: 1;
    min-height: 90px;
}
.zahlmonate .saeulen > div {
    display: flex;
    align-items: flex-end;
    height: 100%;
    min-width: 0;
}
.zahlmonate .saeule {
    width: 100%;
    background: var(--primary-color);
    border-radius: var(--rund-klein) var(--rund-klein) 0 0;
    min-height: 3px;
    transition: filter var(--zeit-schnell);
}
.zahlmonate .saeulen > div:hover .saeule,
.zahlmonate .saeulen > div:focus-within .saeule { filter: brightness(1.15); }
.zahlmonate .duenn .saeule { background: var(--gold-color); }
.zahlmonate .saeulen > div:focus-visible { outline: 2px solid var(--brand-ring); }

/* Der Durchschnitt als Bezugsgroesse. Ohne ihn ist „Gold heisst unter dem
   halben Durchschnitt" eine Behauptung, die das Bild nicht belegt.
   Gestrichelter Rand statt Verlauf - Farbverlaeufe sind ausgeschlossen und
   ein Test haelt das fest. */
.zahlmonate .schnittlinie {
    position: absolute;
    left: 0;
    right: 0;
    border-top: 1px dashed var(--text-light);
    opacity: 0.55;
    pointer-events: none;
}
.zahlmonate .schnittlinie b {
    position: absolute;
    right: 0;
    top: -0.95em;
    font-size: var(--schrift-xs);
    font-weight: 400;
    color: var(--text-light);
    background: var(--card-color);
    padding: 0 0.3rem;
}

.zahlmonate .monatsnamen {
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    gap: var(--raum-2);
}
.zahlmonate .monatsnamen small {
    font-size: var(--schrift-xs);
    color: var(--text-light);
    text-align: center;
}

@media (prefers-reduced-motion: reduce) {
    .zahlmonate .saeule { transition: none; }
}

/* Die Blase eines Monats ist sechsmal so breit wie seine Saeule. Sie
   richtet sich deshalb nach der Kartenmitte aus und wird an den Raendern
   umgehaengt - sonst ragt sie aus der Karte. */
.zahlmonate .saeulen > div > .blase {
    left: 50%;
    right: auto;
    transform: translate(-50%, -3px);
    width: 17rem;
}
.zahlmonate .saeulen > div:hover > .blase,
.zahlmonate .saeulen > div:focus-within > .blase { transform: translate(-50%, 0); }

.zahlmonate .saeulen > div:nth-child(-n+3) > .blase { left: 0; transform: translateY(-3px); }
.zahlmonate .saeulen > div:nth-child(-n+3):hover > .blase,
.zahlmonate .saeulen > div:nth-child(-n+3):focus-within > .blase { transform: none; }

.zahlmonate .saeulen > div:nth-child(n+10) > .blase { left: auto; right: 0; transform: translateY(-3px); }
.zahlmonate .saeulen > div:nth-child(n+10):hover > .blase,
.zahlmonate .saeulen > div:nth-child(n+10):focus-within > .blase { transform: none; }

/* --- Befunde ----------------------------------------------------------- */

.befundliste { list-style: none; margin: 0; padding: 0; }

.befundliste li {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    gap: var(--raum-3);
    align-items: center;
    padding: var(--raum-2) 0;
    border-bottom: 1px solid var(--border-color);
    font-size: var(--schrift-l);
}
.befundliste li:last-child { border-bottom: none; }

.befund-art {
    font-size: 0.66rem;
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    padding: 0.12rem 0.45rem;
    border-radius: var(--rund-klein);
    border: 1px solid currentColor;
    white-space: nowrap;
}
.befund-art.rot  { color: var(--red-color); }
.befund-art.gold { color: var(--gold-color); }
.befund-art.blau { color: var(--accent-text); }

.befund-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.befund-wert {
    font-variant-numeric: tabular-nums;
    font-size: var(--schrift-m);
    font-weight: 600;
}

/* --- Verlaufsminiatur -------------------------------------------------- */

/* Die Kurve war zuerst ein handgezeichnetes SVG (`.miniverlauf`). Sie zeigte
   aber beim Ueberfahren nichts an - ohne Achsenbeschriftung stand damit eine
   Linie da, aus der sich kein Monat ablesen liess. Jetzt zeichnet Chart.js,
   das auf dieser Seite ohnehin geladen wird. */
.verlaufsflaeche { position: relative; height: 170px; }

.mini-legende {
    display: flex;
    gap: var(--raum-4);
    margin-left: auto;
    font-size: var(--schrift-xs);
    color: var(--text-light);
}
.mini-legende i {
    display: inline-block;
    width: 14px;
    height: 2px;
    vertical-align: middle;
    margin-right: var(--raum-1);
    background: var(--primary-color);
}
/* Gestrichelt ueber einen Rand, nicht ueber einen Verlauf: Farbverlaeufe
   sind im Gestaltungssystem ausgeschlossen und ein Test haelt das fest. */
.mini-legende i.gestrichelt {
    background: none;
    height: 0;
    border-top: 2px dashed var(--text-light);
}

.karten-kopf {
    display: flex;
    align-items: baseline;
    gap: var(--raum-3);
    flex-wrap: wrap;
    margin-bottom: var(--raum-3);
}

/* --- Zahltage ---------------------------------------------------------- */

.zahltagliste { list-style: none; margin: 0; padding: 0; }
.zahltagliste li {
    display: grid;
    grid-template-columns: 3.4rem minmax(0, 1fr) auto;
    gap: var(--raum-3);
    align-items: baseline;
    padding: var(--raum-2) 0;
    border-bottom: 1px solid var(--border-color);
    font-size: var(--schrift-l);
}
.zahltagliste li:last-child { border-bottom: none; }
.zahltag-tag {
    font-size: var(--schrift-xs);
    color: var(--text-light);
    text-transform: uppercase;
    font-variant-numeric: tabular-nums;
}
.zahltag-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.zahltag-wert { font-variant-numeric: tabular-nums; font-weight: 600; }

/* Die Blase ist breiter als eine Kachel - sie MUSS also ueber den Rand der
   Kachel hinausragen. Damit sie nicht ueber den Rand der SEITE hinausragt,
   richtet sich die jeweils letzte Spalte nach rechts aus. Welche das ist,
   haengt an der Spaltenzahl und wird deshalb je Umbruchpunkt gesetzt.
   Ohne diese Regel lief die Seite auf 375 px um 150 px seitlich ueber. */
.kachelband .kachel > .blase { left: 0; right: auto; }

/* Bei SECHS Spalten sind das die Kacheln 4 bis 6. Die Bedingung nach unten
   ist noetig: eine :nth-child-Regel ist spezifischer als die einfache Regel
   in den schmaleren Bloecken und wuerde dort gewinnen - Kachel 5 stand
   dadurch in der linken Spalte und richtete sich trotzdem nach rechts aus. */
@media (min-width: 1025px) {
    .kachelband .kachel:nth-child(n+4) > .blase { left: auto; right: 0; }
}

@media (max-width: 1024px) {
    .kachelband { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .sp8, .sp4 { grid-column: span 12; }
}

/* NACH UNTEN BEGRENZT. Ohne die zweite Bedingung gilt diese Regel auch bei
   zwei Spalten - und weil :nth-child(3n) spezifischer ist als die einfache
   Regel im 560er-Block, gewinnt sie dort und richtet eine Kachel der LINKEN
   Spalte nach rechts aus. Die Blase ragte dann links aus der Seite. */
@media (max-width: 1024px) and (min-width: 561px) {
    .kachelband .kachel > .blase { left: 0; right: auto; }
    .kachelband .kachel:nth-child(3n) > .blase { left: auto; right: 0; }
}

/* --- Navigation auf schmalen Geraeten ---------------------------------- */
/* BEFUND: die Navigationsleiste hatte in KEINER der drei Stylesheet-Dateien
 * eine Regel fuer schmale Fenster. Fuenf Menuepunkte mit 2rem Abstand,
 * feste Hoehe 65px, dazu rechts Marktdaten-Hinweis und Theme-Schalter -
 * zusammen 441px, die nie umbrachen. Auf einem 375px breiten Telefon lief
 * dadurch JEDE Seite seitlich ueber; man musste horizontal scrollen, um an
 * den Theme-Schalter zu kommen.
 *
 * Steht bewusst in shared.css: app.css und portfolio.css definieren
 * .main-nav beide, shared.css wird nach beiden geladen und gilt damit fuer
 * alle Seiten. Eine Kopie je Datei waere genau der Fehler, der zu dieser
 * Luecke gefuehrt hat.
 */
@media (max-width: 1024px) {
    /* Die Wortmarke tritt zurueck, sobald der Platz knapp wird - die
       Menuepunkte sind wichtiger als der Name der eigenen Anwendung. */
    .marke-text { display: none; }
    .leiste-innen { gap: var(--raum-4); }
}

@media (max-width: 560px) {
    .leiste-innen {
        height: auto;
        padding: var(--raum-2) var(--raum-4);
        flex-wrap: wrap;
        row-gap: var(--raum-2);
    }

    .haupt-nav {
        order: 3;
        width: 100%;
        overflow-x: auto;
        gap: 0.1rem;
        scrollbar-width: none;
    }
    .haupt-nav::-webkit-scrollbar { display: none; }

    .leiste-rechts { margin-left: auto; }

    .container,
    .dashboard-container { padding: var(--raum-5) var(--raum-4); }

    .seitenkopf {
        margin-bottom: var(--raum-5);
        padding-bottom: var(--raum-4);
    }

    /* Das Monatsprofil verliert die Zahl der Zahlungen - der Betrag zaehlt. */
    .monatsprofil li { grid-template-columns: 2.2rem 1fr 4.8rem; }
    .mp-zahl { display: none; }

    /* Anteilsliste: der Balken weicht, Name und Zahlen bleiben - bei 375 px
       waere ein 40 px breiter Balken keine Information mehr. */
    .anteilsliste li { grid-template-columns: minmax(0, 1fr) 5rem 3.2rem; }
    .al-balken { display: none; }

    /* Die Beitragsliste behaelt nur Name und Summe - Kurs und Ausschuettung
       einzeln passen auf 375 px nicht mehr lesbar nebeneinander. Sie stehen
       im Hinweis darunter, wo es darauf ankommt. */
    .beitragsliste li { grid-template-columns: minmax(0, 1fr) 6rem; }
    .beitragsliste .al-wert:nth-of-type(2),
    .beitragsliste .al-wert:nth-of-type(3) { display: none; }

    .kuerzliste li { grid-template-columns: minmax(0, 1fr) 4.5rem; }
    .kl-jahre { grid-column: 1 / -1; text-align: left; }

    /* Startseite: Kachelband auf zwei Spalten. Die Blase spannt dann ueber
       BEIDE Spalten - schmaler waere sie kaum lesbar, breiter als das Band
       liefe sie aus der Seite. */
    .kachelband { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .hat-info > .blase { width: min(88vw, 19rem); }
    .kachelband .kachel > .blase {
        width: calc(200% + var(--raum-4));
        max-width: none;
        left: 0;
        right: auto;
    }
    .kachelband .kachel:nth-child(even) > .blase { left: auto; right: 0; }
    .zahlmonate { min-height: 130px; }
    .zahlmonate .saeulen,
    .zahlmonate .monatsnamen { gap: 2px; }
    .zahlmonate .monatsnamen small { font-size: 0.6rem; }
    .ziel-block { gap: var(--raum-4); }

    /* Die beiden Renditezahlen untereinander - die senkrechte Trennlinie
       wird dabei zur waagerechten, sonst haengt sie ins Leere. */
    .rendite-paar { grid-template-columns: 1fr; gap: var(--raum-5); }
    .rendite-paar > div + div {
        padding-left: 0;
        padding-top: var(--raum-5);
        border-left: none;
        border-top: 1px solid var(--border-color);
    }

    /* Die Kennzahlenleiste stapelt - dann trennen waagerechte Linien. */
    .kpi-grid > .card {
        border-left: none;
        border-top: 1px solid var(--border-color);
    }
    .kpi-grid > .card:first-child { border-top: none; }

    /* Der Hinweis "Marktdaten offline" ist der breiteste Einzelposten und
       auf einem Telefon nicht die wichtigste Information. */
    .app-leiste .tag.danger {
        font-size: var(--schrift-xs);
    }

    /* Ein Grid- oder Flex-Element ist standardmaessig mindestens so breit
       wie sein laengster nicht umbrechbarer Inhalt (min-width: auto). Die
       Spalte klappte auf 1fr um, die Karte darin blieb trotzdem 697px breit
       und schob die ganze Seite auf. */
    .summary-grid > *,
    .details-grid > *,
    .kpi-grid > *,
    .card > * {
        min-width: 0;
    }

    .card {
        padding: var(--raum-4);
    }

    /* Beschriftung und Wert nebeneinander brauchen zusammen mehr Platz, als
       375px hergeben - sie duerfen umbrechen. */
    .sub-stats-list li {
        flex-wrap: wrap;
        row-gap: 0.15rem;
    }

    /* Dieselbe Ursache eine Ebene tiefer: ein flex:1-Element bekommt sonst
       die Breite seines Inhalts. Bei den Diagrammen ist das die von
       Chart.js gesetzte Canvas-Breite - 656px auf einem 375px-Bildschirm. */
    .u-grow, .card {
        min-width: 0;
    }

    canvas {
        max-width: 100%;
    }

    /* Breite Tabellen scrollen in ihrem eigenen Kasten, nicht die Seite. */
    .tabelle-scroll {
        overflow-x: auto;
        min-width: 0;
    }

    .regler-felder { grid-template-columns: 1fr; }
    .sim-spalte    { min-width: 0; }
}

/* Woraus der Depotwert besteht: ein Balken, drei Teile, Summe = Depotwert */
.herkunft-balken {
    display: flex;
    height: 26px;
    border-radius: var(--rund-klein);
    overflow: hidden;
    background: var(--bg-subtle);
    border: 1px solid var(--border-color);
}
.herkunft-balken .teil { transition: width 0.4s ease; }
.herkunft-balken .teil.eigen     { background: #64748b; }
.herkunft-balken .teil.ertrag    { background: var(--primary-color); }
.herkunft-balken .teil.geschenkt { background: #a78bfa; }
.herkunft-balken .teil.wert      { background: var(--accent-color, #38bdf8); }

.punkt {
    display: inline-block;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    margin-right: 0.45rem;
}
.punkt.eigen     { background: #64748b; }
.punkt.ertrag    { background: var(--primary-color); }
.punkt.geschenkt { background: #a78bfa; }
.punkt.wert      { background: var(--accent-color, #38bdf8); }

/* Ein Feld je Monat: auf einen Blick sichtbar, ob eine Sparrate durchgehend
   eingehalten wurde oder nur in einzelnen Monaten. Ein Durchschnitt allein
   verdeckt genau das. */
.monatsbalken {
    display: flex;
    gap: 2px;
    margin-top: 0.4rem;
}
.monatsbalken .monat {
    flex: 1;
    height: 10px;
    border-radius: var(--rund-klein);
    min-width: 4px;
}
.monatsbalken .monat.erfuellt { background: var(--primary-color); }
.monatsbalken .monat.verfehlt { background: var(--red-color); opacity: 0.55; }
.monatsbalken .monat.laufend  {
    background: var(--bg-subtle);
    border: 1px dashed var(--border-color);
}

.kurve-label {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.82rem;
    cursor: pointer;
    user-select: none;
}

/* --- Fehlerseite ------------------------------------------------------- */

.error-page {
    min-height: 70vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    gap: 1rem;
}
.error-page .code { font-size: 3.5rem; }
