6f69ba34

Rebuild centjes-chart: pure report IR, diagrams backend, tests

## Summary

Restructures the `centjes-chart` package around a **backend-agnostic, pure report** so the data pipeline is total and testable and rendering is fully isolated. Net diff is the `centjes-chart` package plus its wiring (no `Balance.hs` change — the earlier WIP re-export hack is reverted by this work).

## Architecture

| Module | Role |
|---|---|
| `Centjes.Chart.Report` | Pure IR (`ChartReport`/`ChartSeries`), typed `ChartError` with a composing `ToReport`, total `produceChartReport`, `sampleStepFunction` |
| `Centjes.Chart.Render` | The *only* place precise money becomes `Double`; stacked-area SVG via `Chart` + **`Chart-diagrams`** |
| `Command/All` + `OptParse` | Wires Report→Render; currency / filter / output / title are settings |

## Highlights

- **No partial functions** in the pipeline — `fromJust`/`minimum`/`maximum` replaced by typed `ChartError`s rendered through the usual diagnostic machinery.
- **Exactness to the edge** — `really-safe-money` values flow into the IR; only the renderer converts to `Double`.
- **Dropped the cairo C dependency** by rendering through the pure-Haskell `Chart-diagrams` backend (confirmed in both the stack snapshot and nixpkgs).
- **No hardcoding** — currency, account filter (reusing `Centjes.Filter`), output path and title are CLI/config settings.
- **Daily revaluation** — held balances are re-valued at each day's exchange rate; the per-day price graph is shared across accounts.

## Tests (new `centjes-chart-test`)

- `sampleStepFunction` property tests (carry-forward invariants)
- A valid `ChartReport` golden
- Error goldens for every `ChartError` constructor: unknown-currency, no-data, missing-price

## Verification

- `stack test --pedantic` — 7/7
- pre-commit (ormolu, hlint, hpack, cabal2nix, deadnix, nixpkgs-fmt) — pass
- Nix `weeder-check` — compiles `-O2 -Werror`, no dead code
- End-to-end: `centjes-chart all` writes a valid 1920x1080 SVG (incl. into a nonexistent output dir via `ensureDir`)

## Notes / out of scope

- One chart kind today (assets stacked-area); the IR is built so additional kinds are mostly new `produce*Report` + subcommands.
- Stacked-area assumes non-negative series; negative balances invert a band (inherent charting limitation, pre-existing).