# MoneyChart

> Line/area with a money axis and negative-aware baseline.

Source: https://lopifi.com/components/money-chart
Part of: Lopifi — US GAAP books on autopilot, reviewed by a CPA (https://lopifi.com)

---

- **Family:** Dashboard & charts — 
- **Status:** Implemented
- **Spec:** https://lopifi.com/docs/catalog/07-dashboard-charts

## Install

```bash
npx shadcn@latest add @lopifi/theme
npx shadcn@latest add @lopifi/money-chart
```

## Specification

Line and area, with everything a generic chart library gets wrong about money:

- **Money-formatted axis** — abbreviated (`$1.2M`) with the exact value in the tooltip. Abbreviation is licensed here; see [numerics](../foundations/06-numerics.md#abbreviation).
- **Zero baseline is emphasized** — a 1px `--border-strong` line, distinct from the `--border-subtle` gridlines. When data crosses zero, that line is the most important thing in the chart.
- **Negative regions are visually distinct** — a fill below zero at `--negative` with a 45° hatch, so it survives greyscale.
- **Y-axis starts at zero** for quantities. The only sanctioned exception is a rate chart (`CurrencyPairChart`), and there the axis is explicitly labeled.
- **Projections are dashed.** A forecast rendered identically to actuals is a lie. The boundary itself is drawn — a dashed vertical rule labelled `Forecast →` — because a dash pattern read across six months is not a date.
- **Gridlines: horizontal only**, `--border-subtle`. Vertical gridlines on a time series are noise.
- **Area fill** is the one sanctioned gradient — a single hue fading to transparent, because it keeps the line readable over gridlines. Legibility, not decoration.
- Multi-currency series is **rejected at the type level**. Convert to a stated presentation currency first, and label the axis with it.

### The FP&A layer

A plan chart has to say four things a line chart cannot, and each of them is a way of being wrong that a prettier chart hides.

- **The range, and what it is.** `band` takes a low and a high and a **required** `label` — `P10–P90`, `±1σ`, `Downside to upside`. A shaded cone with no stated interval is a precision claim nobody made, and a reader who cannot tell which interval they are looking at will assume whichever suits them. The band is bounded by a hairline as well as shaded, because a fill alone disappears on a projector, and the edges are the part people quote. It widens with distance or it is lying about what is knowable.
- **The alternatives, unranked.** `scenarios` draws base, upside and downside from the same anchor, told apart by **dash rhythm first and colour second** — a base/upside/downside triple in red-amber-green is three lines a third of readers cannot separate. No best-case styling and no ordering by outcome: a scenario is a set of assumptions, and presenting one as the good one is how a forecast review becomes a negotiation about which line to show the board.
- **The plan.** `plan` is a *reference*, not a series: dotted, in the neutral tertiary tone, taking no viz colour and absent from the legend's isolate control. A budget is the line the business agreed to, not another thing that happened, and giving it a series colour puts it in competition with the measure it exists to be read against.
- **The variance, in words that survive greyscale.** Stated as **F** and **U** rather than as a colour or a bare sign. Favourable and unfavourable are the terms of art, they are unambiguous under polarity — a cost under plan is F and revenue under plan is U, and *both are negative absolute variances* — and no amount of red and green carries that. `plan.polarity` is required for the same reason it is required everywhere else: a chart does not know its own polarity, and guessing one gets half of FP&A backwards.

The variance is always taken against the **first** series declared, and the readout disappears when that series is isolated away. A variance whose base silently changes as the reader filters is worse than no variance: the number moves and nothing on the chart says why.

The band, the scenarios and the plan are all inside the y-domain. A cone clipped by the axis is a chart that has quietly cropped the bad case out of the picture.

**The table equivalent carries all of it** — a `Basis` column marking each period actual or forecast, the band's range, each scenario, the plan and the variance. A table listing the base values alone is not the chart in another form; it is a different, more confident chart.

**Motion:** `stroke-dashoffset` draw, 400ms `--ease-out`, once on mount or scroll-into-view. Instant on data change.

**Touch:** 44px-tall scrub target across the plot, with a **persistent readout** in a fixed header — not a floating tooltip a finger covers.

## Rules this component obeys

Money is minor units, never floats. `null` is not `0` and neither is redacted. Negatives render in accounting parentheses with the parenthesis column reserved on both sides. Debit and credit are two columns. Per-currency decimal places. Polarity is explicit — up is not always good. Every figure states its period, entity, currency, basis and as-of.
