Palettes¶
This page is the catalog. For how to call the resolver — palette(),
color(), YAML shorthand, errors, smart defaults, scoring, anti-patterns —
see Palette resolver.
Families¶
Every palette belongs to one of five families. The family determines how the resolver treats the palette and what kind of data it's for.
| Family | Purpose | Used for |
|---|---|---|
sequential |
Ordered magnitude (light → dark) | Continuous numeric data without a midpoint |
diverging |
Signed values around a midpoint | Continuous numeric data with a meaningful zero or center |
categorical |
Unordered categories | Discrete enums where each value is its own identity |
scaffold |
UI structural framing | Canvas, borders, dividers, axis text — not data encoding |
tone |
Role tokens | Negative / positive / warning semantics |
Scaffolds and tones use named slots (canvas, solid, text, …), not
numbered stops. The other three families use ordered stops.
Sequential¶
Use for ordered magnitude — light at the low end, dark at the high end.
All sequential palettes ship 11 stops and downsample evenly: pass steps=N
to get N evenly-spaced stops from the spine.
WCAG note. Dark-end stops will fail WCAG AA (4.5:1) against
#222 body text. For table cell backgrounds, use
palette(name, surface="table") — see
Palette resolver
— which carves the spine at the contrast boundary and returns
AA-safe stops. Or set an explicit text_color override on dark cells.
dft-seq-blue — default sequential¶
Single-hue blue. Default for continuous numeric data without a midpoint.
Other sequential hues¶
Same 11-stop architecture, different hue anchor. Pick by editorial fit; all share the WCAG dark-end caveat above.
| Palette | Reads as | Light end | Mid (step 6) | Dark end |
|---|---|---|---|---|
dft-seq-amber |
Honey → deep amber | #f6edde |
#a2781a |
#2e1f00 |
dft-seq-brown |
Cream → warm brown (pairs with cream theme) | #f3eee6 |
#9b785e |
#341911 |
dft-seq-gray |
Pure achromatic (magnitude without hue) | #eeeeee |
#808080 |
#222222 |
dft-seq-green |
Single-hue green | #e4f3ea |
#44926e |
#002a19 |
dft-seq-purple |
Single-hue purple | #f5eaf8 |
#9b6ba8 |
#32113a |
dft-seq-rust |
Cream-peach → terracotta → deep rust | #fdeae3 |
#b96648 |
#3e1000 |
dft-seq-teal |
Teal / turquoise | #dff3f5 |
#00919d |
#00272b |
Diverging¶
Use for signed values around a midpoint — temperature anomalies, profit/loss, deviations from a baseline. All diverging palettes ship 11 stops with a neutral midpoint at step 6. Even-N downsamples auto-skip the midpoint (no gray middle); odd-N include it.
When to use which¶
| Situation | Palette |
|---|---|
| Default CVD-safe diverging | dft-div-blue-red |
| Political-sensitivity (avoid red/blue) | dft-div-orange-teal |
| Financial loss/gain (red negative, green positive) | dft-div-crimson-green — must pair with icon + label |
| Climate / atmospheric data (conventional sunset ramp) | dft-div-sunset |
| Scientific visualization (Moreland 2009) | dft-div-coolwarm |
dft-div-blue-red — default¶
Symmetric blue-to-red about a light midpoint. CVD-safe at common subset counts.
Other diverging palettes¶
| Palette | Low extreme | Mid | High extreme | Notes |
|---|---|---|---|---|
dft-div-orange-teal |
#4c1f00 |
#e4e4e4 |
#003634 |
Symmetric, fully CVD-safe; non-politically-loaded |
dft-div-crimson-green |
#540a31 |
#e4e4e4 |
#00481d |
Engineered red↔green CVD pass via lightness asymmetry; icon + label required |
dft-div-sunset |
#125a56 |
#eceada |
#a01813 |
Paul Tol multi-hue ramp; CVD-safe; conventional in climate work |
dft-div-coolwarm |
#3b4cc0 |
#dddddd |
#8b0000 |
Moreland 2009; canonical in ParaView/VTK and scientific viz |
Categorical¶
Use for unordered categories — series in a multi-line chart, slices in a
stacked bar, items in a legend. Categorical palettes ship a fixed number of
slots; steps=N returns the first N. There is no interpolation: stops are
what you get.
editorial-10 — default for editorial themes¶
Quieter ten-color set designed for cycling — the engine fills slots in
order without a human picker. Default for the shipped default and
cream themes.
Slot progression — what comes out at each cardinality:
- Slots 1–2 — two blues at different lightnesses (brand anchor + lighter sibling). A 2-series chart reads as a single-hue lightness pair, not max-contrast.
- Slots 3–4 — paired neutrals (warm
sand+ coolgray). A 3- or 4-series chart adds a temperature break without introducing a new hue. - Slots 5–6 — muted second/third hues (
plum,green) at low chroma. - Slot 7 — first saturated warm (
gold). Reserved for cardinality 7+ or the highlight role. - Slots 8–10 — earth + cool + anchor (
rust,teal,charcoal).
Reach for editorial-10 (over vivid-10) when:
- The dashboard is meant to read as editorial — calmer, lower-chroma, fewer competing hues.
- Charts often have 2–4 series. Editorial-10's first four slots are two blues + two neutrals; most charts will live in slots 1–4 and feel quiet by default.
- Cross-chart palette consistency matters and you'd rather not hand-pin per chart.
Stay on vivid-10 when:
- The dashboard genuinely needs 6+ visually-distinct categories on a single chart and editorial restraint isn't a goal.
- The product surface is brand-default rather than editorial.
Companion palette — editorial-10-dark¶
Direct labels at line endpoints (or segment names on stacked bars) need to read a notch darker than the mark they ink, so the label reads as authored ink rather than just a duplicate of the series color. editorial-10-dark is the dark companion that provides those label colors.
Pairing is positional: stop N in editorial-10-dark is the dark companion of stop N in editorial-10. Each stop drops L by ~0.10 in OKLCH, with a small chroma bump so the darker tone keeps perceptual punch. Slot 10 (charcoal) is the exception — it equals its base stop, because charcoal-base already sits at the ink-band floor (L≈0.30) and has no meaningful darker twin.
| Slot | editorial-10 |
editorial-10-dark |
|---|---|---|
| 1 | #3164a3 denim |
#0e4786 |
| 2 | #779bc9 sky |
#557daf |
| 3 | #ad9c7f sand |
#917d5a |
| 4 | #7a8895 gray |
#5b6b7a |
| 5 | #8a576f plum |
#6f3854 |
| 6 | #5c7b5c green |
#3a603b |
| 7 | #d49656 gold |
#b46e0f |
| 8 | #ae6349 rust |
#944123 |
| 9 | #609f9e teal |
#2a807f |
| 10 | #232f3a charcoal |
#232f3a |
The two files are edited together. A regression test pins the per-slot pairing contract (same hue family, dark stop has lower L — except the consolidated charcoal slot) so accidental drift between the two surfaces fails CI.
These are direct-label colors, not body-text or axis-label colors. They're designed to ink labels that sit on or beside a chart mark — not labels that float on open canvas. A few stops (slot 2 sky, slot 3 sand, slot 7 gold, slot 9 teal) clear WCAG 3:1 graphic contrast against the cream canvas but fall short of the AA 4.5:1 body-text bar. That's the cycling-palette chroma envelope; the dark companion sharpens the label-on-mark contrast without trying to be a body-text palette.
Companion palette — editorial-10-light¶
Light states need the opposite treatment from direct-label ink: a mark should stay recognizably tied to its series color, but sit above the base color by roughly the same lightness distance that editorial-10-dark sits below it. editorial-10-light is the moderate light companion for that job.
Pairing is positional: stop N in editorial-10-light is the light companion of stop N in editorial-10. Each stop is lifted in OKLCH L above its base and cuts chroma so the lighter mark does not become louder. The lift is directional, not a strict mirror of the editorial-10-dark drop (gold is tuned down to L≈0.80 by eye so the light band reads evenly rather than carrying a lightness outlier).
| Slot | editorial-10 |
editorial-10-light |
|---|---|---|
| 1 | #3164a3 denim |
#6682a6 |
| 2 | #779bc9 sky |
#a5b9d3 |
| 3 | #ad9c7f sand |
#c6bdac |
| 4 | #7a8895 gray |
#9ea6ad |
| 5 | #8a576f plum |
#9b7d8a |
| 6 | #5c7b5c green |
#839583 |
| 7 | #d49656 gold |
#dab696 |
| 8 | #ae6349 rust |
#b88c7d |
| 9 | #609f9e teal |
#9bbcbb |
| 10 | #232f3a charcoal |
#3c4349 |
Companion palette — editorial-10-ghost¶
De-emphasis states need a stronger fade: out-of-focus marks should recede behind the highlighted member while keeping their hue identity. editorial-10-ghost is the pale companion for dim-the-chorus patterns.
Pairing is positional: stop N in editorial-10-ghost is the ghost companion of stop N in editorial-10. It uses the same derivation as vivid-10-ghost: preserve hue, lift slots 1-9 to OKLCH L≈0.86, and cut chroma to 32%. Slot 10 charcoal stays lower at L≈0.80 — lifted toward the ghost band but kept a notch below it so it stays distinct from gray-ghost.
| Slot | editorial-10 |
editorial-10-ghost |
|---|---|---|
| 1 | #3164a3 denim |
#c1d3e9 |
| 2 | #779bc9 sky |
#c6d2e2 |
| 3 | #ad9c7f sand |
#d6d0c7 |
| 4 | #7a8895 gray |
#cdd2d6 |
| 5 | #8a576f plum |
#decbd3 |
| 6 | #5c7b5c green |
#cad4c9 |
| 7 | #d49656 gold |
#e2cdb9 |
| 8 | #ae6349 rust |
#e6cac1 |
| 9 | #609f9e teal |
#c2d6d5 |
| 10 | #232f3a charcoal |
#babec3 |
editorial-10-light and editorial-10-ghost are companion palettes, not standalone categorical cycles. They deliberately have lower pairwise separation than editorial-10; use them alongside a base-color focus mark, not as the primary series cycle.
Companion palette — editorial-10-ink¶
Single-series chart marks (bar fills, line strokes, area fills, table inline-bars) need a deeper ink than direct labels — dark enough to read as "considered ink on the page" rather than as the chart system's anchor blue, with hue identity preserved across slots so themes can pick a chromatic ink that ties to their canvas. editorial-10-ink is that companion: the symmetric opposite of editorial-10-ghost at the dark end of the perceptual scale.
Pairing is positional: stop N in editorial-10-ink is the ink companion of stop N in editorial-10. All ten stops sit in a tight OKLCH L band (0.30–0.36) with chroma preserved from the base palette — slot identity is carried by hue, not by lightness.
| Slot | editorial-10 |
editorial-10-ink |
|---|---|---|
| 1 | #3164a3 denim |
#1b3659 |
| 2 | #779bc9 sky |
#203c65 |
| 3 | #ad9c7f sand |
#443924 |
| 4 | #7a8895 gray |
#2d383f |
| 5 | #8a576f plum |
#4a2a3a |
| 6 | #5c7b5c green |
#263d2a |
| 7 | #d49656 gold |
#523500 |
| 8 | #ae6349 rust |
#53291d |
| 9 | #609f9e teal |
#143e3e |
| 10 | #232f3a charcoal |
#232f3a |
Themes pick a subset of these stops by inlining hexes into style.charts.single_series_palette — they don't reference the palette name directly. Today the shipped themes use one stop each (editorial → sky-ink slot 2, cream → sand-ink slot 3); the rhythm-palette work that grows those lists for cross-chart visual variety is tracked separately.
vivid-10 — general-purpose ten-color¶
Blue-led, with chroma-pushed cool leads over an earth-and-neutral expansion
after the first five hues. The default categorical palette for the stark
theme; editorial-10 (above) is the default for the editorial and cream
themes.
vivid-10-dark, vivid-10-light, vivid-10-ghost, and vivid-10-ink ship as
positional companions — same ten slots, slot-by-slot. Use them for
chart-emphasis patterns: the dark twin inks direct labels a notch darker
than the line they belong to, the light twin provides a moderate lighter
state, the ghost twin fades out-of-focus series in dim-the-chorus
highlighting, and the ink twin drops every slot into a tight dark band for
single-series marks (consumed by the vivid-family themes).
hero-6 — single dominant series¶
A six-color hero-blue-versus-neutrals palette for charts where one series should dominate. Slot 1 is the only saturated color; slots 2–6 are gray/brown neutrals that step into warmth.
Contract. The hero blue is both the most saturated and the darkest color in the palette — that's the perceptual rule that makes slot 1 win. Don't reorder; the support neutrals are designed to lie behind it.
Tonal monochrome — category-6-tonal-*¶
Single-hue categorical palettes for editorial / brand-restrained
dashboards. Five hues ship: blue, green, purple, orange, brown — each
anchored on a vivid-10 slot so they coordinate with the default
categorical system.
| Palette | Anchor color | Reads as |
|---|---|---|
category-6-tonal-blue |
#0375c4 |
All-blue |
category-6-tonal-green |
#00875a |
All-green |
category-6-tonal-purple |
#9650a8 |
All-purple |
category-6-tonal-orange |
#b74c1f |
All-orange |
category-6-tonal-brown |
#9a642b |
All-brown (cream-theme companion) |
Contract — 4 strict-safe + 2 extended. Every tonal palette ships 6 stops with a layered contract:
| Slots | Role | CVD safety |
|---|---|---|
| 0–3 (core) | strict-safe | Color alone sufficient; pairwise CVD ΔE ≥ 11 |
| 4–5 (extended) | form-redundant only | Below the strict gate. Require dash, marker, or pattern redundancy when used in a chart |
The 6-stop cap is structural: at fixed hue, English's color vocabulary
saturates around 4–5 stops ("two blues that are 'just blue'"), and CVD
simulation collapses adjacent stops. If a chart needs 7+ categories, use
vivid-10 instead.
When to use. Editorial / branded dashboards where chromatic restraint matters more than category count. Small-multiples and KPI tiles where the color budget is tight. Charts with direct labels or stable category order — the legend reads via labels, not by glance. Avoid for many-slice pies, dense scatters, or stacked bars with more than four segments.
Brown ↔ cream bridge. category-6-tonal-brown's extended slots (4–5)
are deliberately hue-shifted to overlap the dft-creams scaffold region.
On the cream theme, slot 5 visually merges with the surrounding chrome —
that's the design intent. Use slot 5 only with form redundancy on cream
backgrounds.
Compatibility palettes¶
| Palette | Use |
|---|---|
tableau |
Tableau-style 10-color set. Retained for users who want the familiar Tableau hues instead of vivid-10. |
Scaffold¶
Scaffolds are UI structural framing — canvas, borders, dividers, axis
labels, table stripes, secondary text. Not data encoding. Address
them through named aliases (chrome.canvas, chrome.ink, etc.) rather
than by integer slot.
dft-grays — neutral chrome¶
Twelve steps from near-white to near-black. The darkest step, void, is
the near-black canvas for dark themes; stark and other light themes use
the lighter steps for chrome.
dft-creams — warm chrome¶
Same twelve-step shape as dft-grays, in warm cream tones. Default
chrome for the cream theme.
Tone¶
Tone palettes encode role semantics — info, negative, positive, warning. Six
named slots per palette: bg, subtle, border, solid, solid-hover,
text. Address them through color(), not palette().
Contract. All tone slots are designed so canonical pairs (text-on-bg, solid-on-white) pass WCAG AA. Tone color alone is insufficient communication — always pair with icon + label per the standard accessibility discipline.
info — blue / information / neutral status¶
Informational notes, neutral status messages, non-error callouts.
| Alias | Hex | Role |
|---|---|---|
bg |
#e7f4ff |
Very light blue background |
subtle |
#d6ecff |
Secondary fill or hover-on-bg |
border |
#6bb9f8 |
Mid-tone divider / outline |
solid |
#008cdd |
Canonical "information" fill |
solid-hover |
#0070b3 |
Darker variant for button hover state |
text |
#003659 |
AA-contrast text color on .bg and on white |
negative — red / stop / bad¶
Critical errors, destructive actions, losses. Western convention: red = stop/bad.
| Alias | Hex | Role |
|---|---|---|
bg |
#ffedec |
Very light peach tint for surface backgrounds |
subtle |
#ffdbd8 |
Hover-on-bg or secondary fill |
border |
#e79491 |
Mid-tone divider / outline |
solid |
#94001e |
Canonical "this is negative" fill |
solid-hover |
#6e0014 |
Darker variant for button hover state |
text |
#4b000a |
AA-contrast text color on .bg and on white |
positive — green / go / good¶
Successful actions, gains, completions. Western convention: green = go/good.
| Alias | Hex | Role |
|---|---|---|
bg |
#e3f8e9 |
Very light green background |
subtle |
#cff2da |
Secondary fill / hover-on-bg |
border |
#82cb9b |
Mid-tone divider / outline |
solid |
#00884d |
Canonical "all good" fill |
solid-hover |
#006d3c |
Darker variant for button hover state |
text |
#003e20 |
AA-contrast text color on .bg and on white |
warning — amber / caution¶
Pay attention — something needs input, nothing's broken. Western convention: amber = caution.
| Alias | Hex | Role |
|---|---|---|
bg |
#fff3e5 |
Very light cream-amber background |
subtle |
#ffe7ca |
Secondary fill / hover-on-bg |
border |
#f0b871 |
Mid-tone divider / outline |
solid |
#e69812 |
Canonical "pay attention" fill |
solid-hover |
#c68100 |
Darker variant for button hover state |
text |
#643f00 |
AA-contrast text color on .bg and on white |
Further reading¶
- Palette resolver — how to call
palette()/color()from Python or YAML, plus error semantics and the anti-pattern list. - Tonal foundations — the neutral-frame thinking that pairs with the chrome scaffolds.