<!-- https://getkonjo.com/design/studio/charts · source: docs/design/studio/charts.md -->

# Charts

Konjo Studio's data visualisation: what to draw, and the palette that survived validation.

> Part of the [Konjo design language](../konjo-design-language.md). The laws in the spine
> apply here unless this chapter contradicts them. Studio-specific — see
> [the dialect](dialect.md).

**Studio has no chart library yet.** Nothing in `apps/studio/package.json` renders a chart, so
this is a specification rather than a description of something shipped.

Whatever renders them, load the `dataviz` skill before writing the first line of chart code.
This chapter supplies Konjo's parameters; that skill supplies the method, the mark specs, and
the validator.

## First: is it a chart?

Most numbers on an owner's dashboard are not. A single figure — this month's revenue, students
active this week, classes taught — is a **stat tile**, and turning it into a chart makes it
slower to read, not richer.

**A stat tile's value is `typography.metric` 28/800, never `typography.hero`.** This chapter
said "a hero number" for a while and it was wrong twice over: `hero` is 64/900, which
[L4](../konjo-design-language.md)'s loud-block budget counts **per instance** — so a Reports
page with four KPI cards spends a budget of one four times — and Studio never gets a hero
block at all ([the dialect](dialect.md)). `metric` is the register between the page title
(`display` 34/800) and a panel title (`title` 22/700): unmistakably a number, and not a hero.

A stat tile is three lines and no more: `eyebrow` label, `metric` value, `caption` hint.
The hint carries the comparison ("+12 vs last month"), and its sign is the only place a
success or error tone is legal on a tile.

Reach for a chart when the *shape* is the point: a trend over time, a comparison across
classes, a distribution across ranks. If the person's question is "what is it right now", a
number answers it.

## The palette

Konjo's brand direction is ink and red, minimal, no rainbow. That holds for **one and two
series**, which is most of what Studio needs:

| Series | Encoding |
|---|---|
| **One** | Ink. No legend — the chart's title names it. |
| **Two** | Ink and `brand.red`, both directly labelled. |

For **three or more categorical series it does not hold**, and this was verified rather than
argued. The palette carried in the old Studio brief — ink `#1C1917`, red `#D62828`, soft red
`#F4978E` — fails validation on three checks: ink sits outside the lightness band and below the
chroma floor (it reads as gray, not as an identity), and the soft red is 2.12:1 against the
chart surface. Muted, brand-toned alternatives fail the same way: the chroma floor and the
colourblind-separation floor both require genuinely chromatic hues, and "tasteful and desaturated"
is precisely what a deuteranope cannot separate.

So for three or more series, use the validated categorical theme, reordered so Konjo's red
leads:

| Slot | Hue | Light |
|---|---|---|
| 1 | red | `#e34948` |
| 2 | blue | `#2a78d6` |
| 3 | yellow | `#eda100` |
| 4 | aqua | `#1baf7a` |
| 5 | violet | `#4a3aa7` |

Verified with the `dataviz` validator at three, four and five slots: **all checks pass** —
lightness band, chroma floor, colourblind separation, normal-vision separation, and contrast
against the chart surface.

Rules that come with it:

- **Assign in fixed order, never cycled.** A ninth series is never a generated hue — it folds
  into "Other", or the chart becomes small multiples.
- **Colour follows the entity, not its rank.** Filtering out a series must not repaint the
  survivors.
- **Magnitude is one hue, light to dark.** Never a rainbow ramp.
- **Polarity is two hues with a neutral gray midpoint.** Never a hue in the middle.
- **Status colours are reserved.** The `feedback` family means good/warning/error and is never
  reused as "series 4".

## The red budget

A chart series painted red **is** the screen's red role. A dashboard with a red line and a red
primary button has spent it twice. On a reports screen the chart usually wins, and the actions
go quiet.

## Marks

- **Thin.** 2px lines, thin bars with a 2px surface gap between adjacent fills.
- **Recessive grid and axes** — `border.hairline`, and only the gridlines that are read.
- **Direct labels beat legends** for four series or fewer; a legend is still present for two or
  more, so identity is never colour-alone.
- **Never a number on every point.** Label the ends, the peak, the thing being discussed.
- **Text wears text tokens**, never the series colour. Values and labels stay in
  `text.primary` / `text.secondary`; the coloured mark beside them carries the identity.

## Never

- **A dual-axis chart.** Two measures at different scales become two charts, small multiples,
  or one index against a common base. This is the single most common chart mistake and it has
  no legitimate use here.
- A pie chart with more than three slices — that is a bar chart.
- A 3D anything.
- A truncated y-axis on a bar chart. Bars encode magnitude from zero; lines may zoom.
- A chart with no empty state. A dojo with three students has a legitimate, ordinary,
  nearly-empty chart, and it must not look broken.
- Colour as the only carrier of meaning — see [accessibility](../foundations/accessibility.md).

## Every chart owes

- A title that says what is being measured and over what period.
- A hover layer: crosshair and tooltip on lines and areas, per-mark tooltip on bars and cells.
- An empty state, a loading state, and an error state — see [states](../patterns/states.md).
- A table view of the same data, reachable, for anyone who cannot read the chart.
