Extract cost and spend presentation into CostPresentation.js

main.qml owned 43 side-effect-free functions that formatted money and token
counts, derived chart geometry, and built the cost rows the Usage & Spend tab
and the provider cost sections bind to. They had no interface of their own, so
the only thing guarding them was a set of assertions that grepped main.qml for
its own source text.

Move them behind a .pragma library module, following ProviderNormalizer.js:

* The caller supplies the words. Functions that used to call i18n now return
  figures, so i18n and i18np stay in QML where the plural rules work.
* The caller supplies the locale separators through numberFormat, because
  Qt.locale() is not reachable from a .pragma library module.

main.qml keeps a delegating call site per helper, which is where the i18n words
are applied, and drops 311 lines. tests/tst_cost_presentation.qml adds 34 cases
that call the module directly, covering the metric switch, the mixed-currency
filter, prototype-polluting date labels, stale-range snapshots, and the chart
geometry bound.

The static checks that pinned the old source text now assert the delegation and
read the module instead, so the rules survive without naming a file.

The extraction is behaviour-preserving. amountString still prints "$-" for
non-numeric input rather than rejecting it; a test pins that so the defect is
recorded rather than silently changed here.
8b82d92751Simone committed on 8/19/2026, 3:09:37 AMparent6e12ded
6 files changedLine totals unavailable