# 05 · Colour Three primary ramps, eight structural neutrals and three gradients, governed by one ratio. The palette is deliberately small: the discipline is in how much of each colour is used, not how many exist. *Updated 2026-08-17. Source: https://brand.haux.studio/colour* ## The ratio governs everything Before any specific colour, the proportion. Haux is a near-white brand with near-black structure and a single orange signal, in a 60/30/10 split. Orange is the signal, never the field. The 10% is not a budget to spend down. It is a ceiling that most work will not reach, and a page with no orange at all is a correct page. The moment a second orange element appears in a view, neither one is a signal any more. They are just two orange things, and the eye has to choose between them. The 30% covers everything structural: type, rules, dense panels, the inverted bands that break a long scroll. It is the colour doing the reading. The 60% is what is left, and what is left is meant to be most of it. > Orange is the signal, never the field. | Name | Hex | Token | Share | Role | | --- | --- | --- | --- | --- | | Near-white | `#fcfcfc` | `--haux-white-100` | 60% | The field. Every layout starts as this and earns its way off it. | | Near-black | `#050505` | `--haux-black-900` | 30% | Structure. Type, rules, dense panels, inverted bands. | | Orange | `#ff3c00` | `--haux-orange-500` | 10% | Signal. One moment per view. The thing you want looked at. | *Proportions are drawn to scale here on purpose. Rendered as three equal boxes with percentages underneath, the rule teaches the opposite of what it says.* ## The palette Two tiers and a gradient set. Tier 1 is the brand; Tier 2 is the furniture that lets Tier 1 stay rare. #### Tier 1 · Primary Three ramps of nine steps. These are the brand; everything else in the palette exists so these can stay rare. Three ramps, nine steps each. The step number is a role, not a lightness value: 500 is always the base the Pantone was matched to, 100 is always the lightest background tint, 900 is always the deepest. The roles hold across all three ramps, so a component can move from the orange ramp to the near-black ramp without rewriting its logic. Only the 500 step of each ramp has a Pantone equivalent. The other eight are digital derivations and should not be sent to a printer as if they were specified inks. ##### Orange · PMS 172 C > The accent. Orange 500 is a fill colour; Orange 700 is its text equivalent on light surfaces. | Name | Hex | Token | Role | Pantone | | --- | --- | --- | --- | --- | | Orange 100 | `#ffefeb` | `--haux-orange-100` | Background | | | Orange 200 | `#ffd8cc` | `--haux-orange-200` | Surface | | | Orange 300 | `#ffb199` | `--haux-orange-300` | Hover | | | Orange 400 | `#ff774d` | `--haux-orange-400` | Border | | | Orange 500 | `#ff3c00` | `--haux-orange-500` | Base | PMS 172 C | | Orange 600 | `#c22e00` | `--haux-orange-600` | Active | | | Orange 700 | `#8f2200` | `--haux-orange-700` | Strong | | | Orange 800 | `#5c1600` | `--haux-orange-800` | Deep | | | Orange 900 | `#290a00` | `--haux-orange-900` | Darkest | | *Figma and the strategy document disagree by one digit on the base: #FF3C00 against #FF3B00. Figma is the source of truth for the identity, so #FF3C00 ships. The difference is below a perceptible threshold, but the token is the tiebreaker either way.* ##### Near-black · PMS Black 6 C > Structure and type. Near-black 900 is the default ink; nothing in the system uses pure #000000. | Name | Hex | Token | Role | Pantone | | --- | --- | --- | --- | --- | | Near-black 100 | `#ededed` | `--haux-black-100` | Background | | | Near-black 200 | `#d4d4d4` | `--haux-black-200` | Surface | | | Near-black 300 | `#b8b8b8` | `--haux-black-300` | Hover | | | Near-black 400 | `#999999` | `--haux-black-400` | Border | | | Near-black 500 | `#787878` | `--haux-black-500` | Base | PMS Black 6 C | | Near-black 600 | `#595959` | `--haux-black-600` | Active | | | Near-black 700 | `#3b3b3b` | `--haux-black-700` | Strong | | | Near-black 800 | `#212121` | `--haux-black-800` | Deep | | | Near-black 900 | `#050505` | `--haux-black-900` | Darkest | | ##### Near-white · PMS 663 C > Surfaces and inverted type. Near-white 100 is the default page; nothing uses pure #FFFFFF. | Name | Hex | Token | Role | Pantone | | --- | --- | --- | --- | --- | | Near-white 100 | `#fcfcfc` | `--haux-white-100` | Background | | | Near-white 200 | `#e6e6e6` | `--haux-white-200` | Surface | | | Near-white 300 | `#cccccc` | `--haux-white-300` | Hover | | | Near-white 400 | `#adadad` | `--haux-white-400` | Border | | | Near-white 500 | `#8c8c8c` | `--haux-white-500` | Base | PMS 663 C | | Near-white 600 | `#6b6b6b` | `--haux-white-600` | Active | | | Near-white 700 | `#4d4d4d` | `--haux-white-700` | Strong | | | Near-white 800 | `#2e2e2e` | `--haux-white-800` | Deep | | | Near-white 900 | `#121212` | `--haux-white-900` | Darkest | | *Every contrast figure published on this site is measured against Near-white 100, not against pure white. The gap is small but it is real: it costs about 0.07 of a ratio point, which is enough to move a borderline pair across a threshold.* #### Tier 2 · Secondary Eight structural neutrals: a warm family from the print identity and a cool family for interface furniture. Eight structural neutrals, split between a warm family carried over from the print identity and a cool family that handles interface furniture. They exist so that Tier 1 can stay rare: a layout that needs three levels of surface separation should reach for Sage, Bone and Cloud rather than three steps of the near-white ramp. Two of these carry warnings, and both warnings come from measurement rather than taste. They are stated on the swatch itself so that nobody has to read the accessibility section to find out. ##### Structural neutrals | Name | Hex | Token | Role | Pantone | | --- | --- | --- | --- | --- | | Espresso | `#3b2f28` | `--haux-espresso` | Dark surface | PMS Black 7 C | | Umber | `#674e42` | `--haux-umber` | Secondary text | PMS 7518 C | | Stone | `#aa9f8d` | `--haux-stone` | Decorative only — Figma captions this "muted text". It reaches 2.54:1 on Near-white and 2.03:1 on Bone, and fails AA at every size. Use Near-white 700 for muted text. Decorative only, never text. | PMS Warm Gray 8 C | | Bone | `#ebe2d5` | `--haux-bone` | Warm surface | PMS 7527 C | | Sage | `#e5e5dd` | `--haux-sage` | Primary surface | PMS Warm Gray 1 C | | Silver | `#afafaf` | `--haux-silver` | Borders — At 2.14:1 on Near-white it misses the 3:1 non-text threshold. Decorative rules only. Never a focus ring or an input border. | PMS Cool Gray 6 C | | Mist | `#d4d4d4` | `--haux-mist` | Dividers | PMS Cool Gray 4 C | | Cloud | `#eaeaea` | `--haux-cloud` | Light surface | PMS Cool Gray 1 C | *Warm family: Espresso, Umber, Stone, Bone, Sage. Cool family: Silver, Mist, Cloud. Do not mix the two inside a single surface stack. A Sage panel with a Mist divider reads as a printing error.* #### Gradients Three, and all three stay inside one hue family. A gradient counts against the accent budget. ##### Three gradients > Gradients stay within one hue family, never across the wheel. | Name | Stops | Token | | --- | --- | --- | | Signal | `#ff3c00 → #ffae5d` | `--haux-gradient-signal` | | Depth | `#050505 → #3b2f28` | `--haux-gradient-depth` | | Heat | `#ff3c00 → #c5334d` | `--haux-gradient-heat` | *A gradient that crosses hue families reads as a third colour appearing in the middle of it, which is precisely the thing the 60/30/10 ratio exists to prevent. Signal runs orange to warm orange, Depth runs near-black to espresso, Heat runs orange to a red that is still on the warm side of the wheel.* A gradient is an accent, so it inherits the accent's budget. One gradient per screen, and it counts against the 10%. Never set body text over a gradient. Contrast is measured at a point, and a gradient has no single point, so the ratio at one end of a Signal panel is not the ratio at the other. Where text must sit on a gradient, it sits on a solid plate over it. #### Do and don’t Live samples, with contrast measured at build time. If a token moves, these numbers move with it. Each pair below is rendered live from the tokens, and the contrast figure under it is computed at build time rather than typed in. If a token moves, these numbers move with it. **Orange 500 is a fill, not a text colour. On a light surface it reaches 3.47:1, below AA for body text at any weight. Orange 700 is the text step.** - Do: Orange 700 on Near-white 100. Reads as the same accent, clears AAA. - Don't: Orange 500 on Near-white 100. Legible to you, illegible to a meaningful share of your audience. **On an orange fill, the label is Near-black. White on Orange 500 is the single most common mistake in the system and it fails AA body.** - Do: Near-black 900 on Orange 500. This is what --on-accent resolves to. - Don't: Near-white 100 on Orange 500. If the button must carry white text, the fill steps to Orange 600. **Stone is a decorative colour. It is captioned "muted text" in Figma, and it cannot be used for text at any size.** - Do: Near-white 700 on Bone. The substitute for every place Stone was reached for as an ink. - Don't: Stone on Bone. Two warm neutrals a hair apart, and the pairing that put Stone on this list. *The full matrix, including the non-text 3:1 threshold for borders and focus rings, is in the accessibility section.*