Files
FPT/src/app/globals.css
T
admGitAICDS b42f9b385f
Deploy App / deploy (push) Successful in 1m59s
Modul-Review 3: Struktur, Dashboard, CSV-Export und Grafiken
Versionierung:
- startet neu bei 0.1; erst eine gesetzte Hauptversion macht daraus 1.0
- Szenario-Liste zeigt die echte Version (z.B. 0.17) statt "1.x", plus
  neue Spalte "Phasen"
- Migration 20260724120000_version_zero_start (nur der Default)

Plan-Dashboard:
- Kacheln anklickbar (fuehren in ihren Bereich), neue Kachel "Berichte"
- Plan umbenennen ueber Stift-Symbol
- Ist-Abweichung nennt das Jahr des juengsten Ist-Datensatzes und ist bei
  positiver Abweichung gruen statt rot

Szenario-Liste:
- Klick auf die Zeile oeffnet die Matrix (Matrix-Knopf entfaellt)
- je Zeile Kopie (Vorlage frei waehlbar) und Loeschen
- laedt nach einer Loeschung neu (zeigte vorher den alten Stand)

Seitenleiste:
- Szenarien wieder verschachtelt nach Herkunft
- Effektive Werte / Analysen / Berichte buendig zum Knoten "Szenarien"

CSV-Export (neues Modul lib/csv.ts):
- vier Bloecke: Kopf, Lebensphasen, ganze Matrix (Elemente x Phasen inkl.
  Uebergangs-Entscheide im Klartext), Jahreswerte
- mit BOM (Excel-Umlaute), Dateiname transliteriert Umlaute
- vorher enthielt die Datei kein einziges finanzielles Element

Grafiken:
- Szenario-Waehler gilt fuer alle drei Grafiken
- BUGFIX Szenario-Vergleich: WealthChart nutzte den Namen als Datenschluessel
  -> gleichnamige Szenarien ueberschrieben sich (Legende zeigte beide, Chart
  nur eine). Neu die ID; stille Deckelung auf 4 Serien entfaellt
- eigene Legende mit freier Farbwahl je Serie + Erklaerung des Linienstils
- Vermoegensaufteilung neu: gestapelte Flaeche ueber die Planjahre + Ring
  fuer die relative Aufteilung zu einem waehlbaren Zeitpunkt
- alle Diagrammfarben aus neuen Theme-Tokens (--chart-1..6, --chart-grid)

Doku-Drift bereinigt: Kapitel 2.1, 3.2.2-3.2.7 und 3.10 beschrieben noch den
Stand vor V7 (Grundprofil am Szenario, parentPlanId, Scenario.startYear,
window.confirm, drei Sidebar-Unterpunkte).

Nebenbei: verstuemmelte Hex-Farbe --danger-soft (warm) repariert, deutsche
Plural-/Umlautfehler in den Uebersichts-Kacheln.

SPEZIFIKATION 0.31. 267 -> 275 Tests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 12:16:07 +02:00

354 lines
10 KiB
CSS

@import "tailwindcss";
/* -------------------------------------------------------------------------
Semantische Farb-Tokens. Drei umschaltbare Schemata über data-theme am
<html>: "light", "dark", "warm". Ohne explizite Wahl folgt das Standard-
:root der OS-Einstellung (prefers-color-scheme). Umschaltung: lib/theme.ts.
------------------------------------------------------------------------- */
:root,
:root[data-theme="light"] {
--bg: #f8fafc;
--surface: #ffffff;
--surface-2: #f4f4f5;
--input: #ffffff;
--border: #e4e4e7;
--border-strong: #d4d4d8;
--fg: #18181b;
--muted: #52525b;
--faint: #a1a1aa;
--accent: #4f46e5;
--accent-hover: #4338ca;
--accent-fg: #ffffff;
--accent-soft: #eef2ff;
--accent-soft-fg: #4338ca;
--danger: #dc2626;
--danger-soft: #fef2f2;
--success: #059669;
--person-a: #4f46e5;
--diff: #b45309;
--diff-soft: #fef3c7;
--diff-added: #15803d;
--diff-added-soft: #dcfce7;
--diff-removed: #71717a;
--diff-removed-soft: #f4f4f5;
--person-b: #0ea5e9;
/* Attention: "hier fehlt eine Eingabe" -- bewusst getrennt vom Akzent, damit
"offen" und "klickbar" nicht dieselbe Farbe tragen. */
--attention: #d97706;
--attention-fg: #ffffff;
--attention-soft: #fef3c7;
--attention-soft-fg: #92400e;
/* Diagramm-Palette: bewusst gedämpfte Töne, je Farbschema abgestimmt. Recharts bekommt
die Variablen direkt als Attributwert (var(--chart-1)) -- der Browser löst sie im SVG auf. */
--chart-1: #5b5bd6;
--chart-2: #3b8ea5;
--chart-3: #4c9a6a;
--chart-4: #c98a2e;
--chart-5: #c25d6b;
--chart-6: #8b6bb1;
--chart-grid: #e4e4e7;
}
:root[data-theme="dark"] {
--bg: #10131c;
--surface: #18181b;
--surface-2: #27272a;
--input: #27272a;
--border: #27272a;
--border-strong: #3f3f46;
--fg: #f4f4f5;
--muted: #a1a1aa;
--faint: #71717a;
--accent: #6366f1;
--accent-hover: #818cf8;
--accent-fg: #ffffff;
--accent-soft: rgba(99, 102, 241, 0.16);
--accent-soft-fg: #a5b4fc;
--danger: #f87171;
--danger-soft: rgba(220, 38, 38, 0.16);
--success: #34d399;
--person-a: #818cf8;
--diff: #fbbf24;
--diff-soft: rgba(251, 191, 36, 0.16);
--diff-added: #4ade80;
--diff-added-soft: rgba(74, 222, 128, 0.14);
--diff-removed: #a1a1aa;
--diff-removed-soft: rgba(161, 161, 170, 0.12);
--person-b: #38bdf8;
--attention: #f59e0b;
--attention-fg: #1c1400;
--attention-soft: rgba(245, 158, 11, 0.16);
--attention-soft-fg: #fcd34d;
--chart-1: #818cf8;
--chart-2: #5eb3c9;
--chart-3: #6ec898;
--chart-4: #e0b25c;
--chart-5: #e08a9a;
--chart-6: #b39ae0;
--chart-grid: #3f3f46;
}
/* Warm / Sunset: cremefarbener Grund, Koralle-Akzent, Amber-Sekundärton. */
:root[data-theme="warm"] {
--bg: #fbf7f2;
--surface: #fffdfa;
--surface-2: #f5ede3;
--input: #ffffff;
--border: #eadfd2;
--border-strong: #dac9b6;
--fg: #2b2320;
--muted: #6b5d53;
--faint: #a89a8c;
--accent: #e8663c;
--accent-hover: #d2542c;
--accent-fg: #ffffff;
--accent-soft: #fcebe2;
--accent-soft-fg: #b24521;
--danger: #c0392b;
--danger-soft: #fbeae7;
--success: #2e9e7b;
--person-a: #e8663c;
--diff: #b45309;
--diff-soft: #fbeccb;
--diff-added: #2e7d52;
--diff-added-soft: #dcf0e2;
--diff-removed: #8a7f72;
--diff-removed-soft: #f0e8dd;
--person-b: #f2a93b;
--attention: #c77414;
--attention-fg: #ffffff;
--attention-soft: #fdeed3;
--attention-soft-fg: #8f5410;
--chart-1: #e8663c;
--chart-2: #4e8fa3;
--chart-3: #7ba05b;
--chart-4: #d99441;
--chart-5: #a9556b;
--chart-6: #8c6a9e;
--chart-grid: #eadfd2;
}
/* Ohne gespeicherte Wahl der Dunkel-OS-Einstellung folgen. */
@media (prefers-color-scheme: dark) {
:root:not([data-theme]) {
--bg: #10131c;
--surface: #18181b;
--surface-2: #27272a;
--input: #27272a;
--border: #27272a;
--border-strong: #3f3f46;
--fg: #f4f4f5;
--muted: #a1a1aa;
--faint: #71717a;
--accent: #6366f1;
--accent-hover: #818cf8;
--accent-fg: #ffffff;
--accent-soft: rgba(99, 102, 241, 0.16);
--accent-soft-fg: #a5b4fc;
--danger: #f87171;
--danger-soft: rgba(220, 38, 38, 0.16);
--success: #34d399;
--person-a: #818cf8;
--diff: #fbbf24;
--diff-soft: rgba(251, 191, 36, 0.16);
--diff-added: #4ade80;
--diff-added-soft: rgba(74, 222, 128, 0.14);
--diff-removed: #a1a1aa;
--diff-removed-soft: rgba(161, 161, 170, 0.12);
--person-b: #38bdf8;
--attention: #f59e0b;
--attention-fg: #1c1400;
--attention-soft: rgba(245, 158, 11, 0.16);
--attention-soft-fg: #fcd34d;
--chart-1: #818cf8;
--chart-2: #5eb3c9;
--chart-3: #6ec898;
--chart-4: #e0b25c;
--chart-5: #e08a9a;
--chart-6: #b39ae0;
--chart-grid: #3f3f46;
}
}
@theme inline {
--color-bg: var(--bg);
--color-surface: var(--surface);
--color-surface-2: var(--surface-2);
--color-input: var(--input);
--color-border: var(--border);
--color-border-strong: var(--border-strong);
--color-fg: var(--fg);
--color-muted: var(--muted);
--color-faint: var(--faint);
--color-accent: var(--accent);
--color-accent-hover: var(--accent-hover);
--color-accent-fg: var(--accent-fg);
--color-accent-soft: var(--accent-soft);
--color-accent-soft-fg: var(--accent-soft-fg);
--color-danger: var(--danger);
--color-danger-soft: var(--danger-soft);
--color-success: var(--success);
--color-diff: var(--diff);
--color-diff-soft: var(--diff-soft);
--color-diff-added: var(--diff-added);
--color-diff-added-soft: var(--diff-added-soft);
--color-diff-removed: var(--diff-removed);
--color-diff-removed-soft: var(--diff-removed-soft);
--color-attention: var(--attention);
--color-attention-fg: var(--attention-fg);
--color-attention-soft: var(--attention-soft);
--color-attention-soft-fg: var(--attention-soft-fg);
--color-person-a: var(--person-a);
--color-person-b: var(--person-b);
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
}
body {
background: var(--bg);
color: var(--fg);
font-family: var(--font-geist-sans), Arial, Helvetica, sans-serif;
}
/* -------------------------------------------------------------------------
Micro-Interactions: kurze, dezente Übergänge für Dialoge, Panels, Toasts.
150-220 ms -- schnell genug, um nie zu bremsen (Doherty-Schwelle).
------------------------------------------------------------------------- */
@keyframes ui-fade-kf {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes ui-pop-kf {
from { opacity: 0; transform: translateY(6px) scale(0.985); }
to { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes ui-slide-in-kf {
from { opacity: 0.4; transform: translateX(24px); }
to { opacity: 1; transform: translateX(0); }
}
.ui-fade { animation: ui-fade-kf 150ms ease-out; }
.ui-pop { animation: ui-pop-kf 180ms cubic-bezier(0.2, 0.9, 0.3, 1); }
.ui-slide-in { animation: ui-slide-in-kf 200ms cubic-bezier(0.2, 0.9, 0.3, 1); }
@media (prefers-reduced-motion: reduce) {
.ui-fade, .ui-pop, .ui-slide-in { animation: none; }
}
/* Hervorhebung des aktuellen Tour-Ziels. */
/* Tour-Spotlight: Der abgedunkelte Bereich entsteht aus vier fixed-Flächen UM das Ziel herum
(in Tour.tsx aus der Bounding-Box berechnet) -- das funktioniert unabhängig von z-index und
overflow. Hier nur der pulsierende Rahmen, der als eigene fixed-Fläche über dem Loch liegt. */
@keyframes tour-ring-kf {
0%, 100% {
box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 85%, transparent), 0 0 14px 2px color-mix(in srgb, var(--accent) 40%, transparent);
}
50% {
box-shadow: 0 0 0 7px color-mix(in srgb, var(--accent) 50%, transparent), 0 0 22px 6px color-mix(in srgb, var(--accent) 25%, transparent);
}
}
.tour-ring {
border: 2px solid var(--accent);
animation: tour-ring-kf 1.4s ease-in-out infinite;
}
/* -------------------------------------------------------------------------
Dokument-Darstellung für gerenderten Markdown (Spezifikation, /spezifikation).
Bewusst über die semantischen Tokens, damit alle drei Farbschemata greifen.
------------------------------------------------------------------------- */
.md-doc {
color: var(--fg);
line-height: 1.65;
font-size: 0.9rem;
max-width: 62rem;
overflow-wrap: break-word;
}
.md-doc > *:first-child { margin-top: 0; }
.md-doc > *:last-child { margin-bottom: 0; }
.md-doc h1,
.md-doc h2,
.md-doc h3,
.md-doc h4 {
color: var(--fg);
font-weight: 600;
line-height: 1.3;
scroll-margin-top: 1rem;
}
.md-doc h1 { font-size: 1.6rem; margin: 2.4rem 0 1rem; }
.md-doc h2 {
font-size: 1.25rem;
margin: 2.2rem 0 0.85rem;
padding-bottom: 0.35rem;
border-bottom: 1px solid var(--border);
}
.md-doc h3 { font-size: 1.05rem; margin: 1.7rem 0 0.6rem; }
.md-doc h4 { font-size: 0.95rem; margin: 1.3rem 0 0.5rem; color: var(--muted); }
.md-doc p { margin: 0.75rem 0; }
.md-doc strong { font-weight: 600; color: var(--fg); }
.md-doc em { font-style: italic; }
.md-doc a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }
.md-doc a:hover { color: var(--accent-hover); }
.md-doc ul,
.md-doc ol { margin: 0.75rem 0; padding-left: 1.4rem; }
.md-doc ul { list-style: disc; }
.md-doc ol { list-style: decimal; }
.md-doc li { margin: 0.3rem 0; }
.md-doc li::marker { color: var(--faint); }
.md-doc code {
font-family: var(--font-mono), monospace;
font-size: 0.84em;
background: var(--surface-2);
border: 1px solid var(--border);
border-radius: 0.25rem;
padding: 0.1em 0.35em;
}
.md-doc pre {
background: var(--surface-2);
border: 1px solid var(--border);
border-radius: 0.6rem;
padding: 0.9rem 1rem;
margin: 1rem 0;
overflow-x: auto;
line-height: 1.5;
}
.md-doc pre code {
background: none;
border: none;
padding: 0;
font-size: 0.82rem;
white-space: pre;
}
/* Breite Tabellen scrollen in ihrem eigenen Container, die Seite bleibt ruhig. */
.md-doc .md-table-wrap { overflow-x: auto; margin: 1rem 0; }
.md-doc table { border-collapse: collapse; width: 100%; font-size: 0.82rem; }
.md-doc th,
.md-doc td {
border: 1px solid var(--border);
padding: 0.4rem 0.6rem;
text-align: left;
vertical-align: top;
}
.md-doc th { background: var(--surface-2); font-weight: 600; white-space: nowrap; }
.md-doc tbody tr:nth-child(even) { background: color-mix(in srgb, var(--surface-2) 45%, transparent); }
.md-doc blockquote {
margin: 1rem 0;
padding: 0.6rem 1rem;
border-left: 3px solid var(--accent);
background: var(--accent-soft);
color: var(--accent-soft-fg);
border-radius: 0 0.4rem 0.4rem 0;
}
.md-doc blockquote p { margin: 0.3rem 0; }
.md-doc hr { border: 0; border-top: 1px solid var(--border); margin: 2rem 0; }