feat(icicle): refine layout, labels, and zoom UX

- Sticky labels: each bar's title slides down inside its rect under
  the sticky timeline so it stays visible while any part of the rect
  is in view, then slides off when the rect's bottom passes.
- Auto-wrap long bar names into multiple <tspan> lines so labels
  no longer overrun their box.
- Drop browser-native <title> tooltips; the custom tooltip remains.
- Demote depth-1 nameSize to depth-2 size when a bar shows its name
  but not its euro amount, so it doesn't outshout column-2 titles.
- Collapse the depth-4 column when the zoomed-in scope has no
  Breakdown items; surviving columns expand to fill the canvas.
- Tighter year-budget centering, runtime gap (GAP_Y) instead of
  d3 partition padding, gutter masks for year-frame strokes.
- Two-hue OKLCH palette tuned so all labels can stay a single colour
  per flow (light on Aufwendungen, dark on Erträge).
- Sidebar: clickable Aufw/Ertr/Saldo to swap flow; Beschreibung +
  collapsed Erläuterungen extracted from PG sections.
- Sticky timeline axis with active-year tick in the active flow's
  colour; URL state sync for path/year/flow.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Flo
2026-05-07 16:29:04 +02:00
co-authored by Claude
parent 9a958c0051
commit 04a46caf19
5 changed files with 589 additions and 130 deletions
+12 -8
View File
@@ -42,17 +42,21 @@
/* Two-hue flow palette per design brief §9.5: deep purple for
Aufwendungen (money leaving), orange for Erträge (money coming in).
Far enough apart on the OKLCH wheel to read as a clear pivot; both
hold their own against the warm-paper background. NOT red/green. */
The two ranges sit on opposite sides of the label-contrast
threshold so all labels on each flow's icicle can be a single
colour: light text on the dark purples, dark text on the light
oranges. Mirrors the JS PALETTE in src/lib/colors.ts. */
--flow-aufwand-h: 295; /* deep plum-purple */
--flow-aufwand-c: 0.17;
--flow-aufwand-c: 0.19;
--flow-ertrag-h: 55; /* warm orange / amber */
--flow-ertrag-c: 0.16;
--flow-ertrag-c: 0.15;
/* Solid ink-on-paper renders of each flow accent (used for active toggle
state, breadcrumb separators, slider handle, etc.). */
--flow-aufwand: oklch(40% var(--flow-aufwand-c) var(--flow-aufwand-h));
--flow-ertrag: oklch(58% var(--flow-ertrag-c) var(--flow-ertrag-h));
/* Solid ink-on-paper renders of each flow accent (used for active
toggle state, breadcrumb separators, slider handle, etc.). The
accent uses Ldark / Llight values that match the bar palette's
darkest-purple and lightest-readable-orange respectively. */
--flow-aufwand: oklch(34% var(--flow-aufwand-c) var(--flow-aufwand-h));
--flow-ertrag: oklch(68% var(--flow-ertrag-c) var(--flow-ertrag-h));
/* ── Spacing (4pt scale, semantic names) ──────────────────────────── */
--space-2xs: 4px;