Colour
Three layers: primitives hold the raw values, semantic tokens say what a colour is for, and the accent is resolved in context. Components only use semantic and accent tokens.
Accent in context
The site accent is orange (--color-accent-main). Inside an article,
ArticleLayout's accent prop replaces it with the customer's brand
colour, and band sets the band gradient (--article-band). Everything in
the article that uses --color-accent follows: chapter bar, progress line, list
bullets, badges. Add a new customer as --color-accent-<brand> plus a
--gradient-accent-<brand>.
| Token | Base | Note | |
|---|---|---|---|
--color-accent-main | var(--color-orange-primary) | the site | |
--color-accent-happeo | var(--color-teal-500) | Happeo articles | |
--color-accent | var(--color-accent-main) | accent in context |
| Token | Base | Note |
|---|---|---|
--gradient-accent-happeo | radial-gradient(103% 156% at 1% 50%, var(--color-teal-400) 0%, var(--color-teal-600) 50%, var(--color-teal-700) 100%) | |
--gradient-accent-sandudd | radial-gradient(103% 156% at 1% 50%, var(--color-sand-200) 0%, var(--color-sand-400) 50%, var(--color-sand-600) 100%) | |
--gradient-accent-main | radial-gradient(103% 156% at 1% 50%, var(--color-orange-300) 0%, var(--color-orange-500) 50%, var(--color-orange-600) 75%, var(--color-orange-700) 100%) |
The bands are subtle radial gradients, light at the left edge. A film-grain texture was tried on them and dropped: it made the orange muddy.
Semantic
What each colour is for. Use these in components.
| Token | Base | Note | |
|---|---|---|---|
--color-bg-primary | var(--color-page-bg) | ||
--color-bg-surface | var(--color-white-1000) | ||
--color-bg-inverse | var(--color-black-1000) | ||
--color-bg-accent-teal | var(--color-teal-500) | ||
--color-bg-accent-yellow | var(--color-yellow-500) | ||
--color-text-primary | var(--color-black-1000) | ||
--color-text-on-dark | var(--color-cream-1000) | ||
--color-bg-placeholder | var(--color-grey-50) | project visual screens | |
--color-text-on-accent | var(--color-black-1000) | ||
--color-text-brand | var(--color-orange-primary) | ||
--color-text-muted | var(--color-black-transparent-60) | ||
--color-border-default | var(--color-black-1000) | ||
--color-border-subtle | var(--color-black-transparent-15) | ||
--color-backdrop | var(--color-black-transparent-85) | image lightbox |
Buttons
All buttons share one hover: a fill wipes up from the bottom (cream, with black text). A page may set --color-button-fill locally, e.g. orange on the Contact page where cream would vanish.
| Token | Base | Note | |
|---|---|---|---|
--color-button-primary-bg | var(--color-bg-inverse) | ||
--color-button-primary-fg | var(--color-text-on-dark) | ||
--color-button-fill | var(--color-text-on-dark) | cream wipe (all buttons) … | |
--color-button-fg-hover | var(--color-text-primary) | … with black text |
Device illustration
| Token | Base | Note | |
|---|---|---|---|
--color-device-body | var(--color-black-1000) | ||
--color-device-bezel | var(--color-white-transparent-50) |
Primitives
Raw values, named by hue and step. Don't use them in components; map them to a semantic token first.
| Token | Base | Note | |
|---|---|---|---|
--color-black-1000 | #0b0b0b | ||
--color-cream-1000 | #f2efe1 | ||
--color-page-bg | #f4efec | ||
--color-yellow-500 | #f1d64a | ||
--color-teal-500 | #30d7d2 | ||
--color-white-1000 | #ffffff | ||
--color-black-transparent-60 | rgba(11, 11, 11, 0.6) | Figma color-text-muted | |
--color-orange-primary | #ed711f | ||
--color-orange-warm | #f58032 | ||
--color-orange-300 | #f0975c | orange band gradient stops (Figma 137:2370) | |
--color-orange-500 | #f28238 | ||
--color-orange-600 | #f37827 | ||
--color-orange-700 | #f36d15 | ||
--color-grey-50 | #f3f5f7 | ||
--color-teal-400 | #3eded9 | accent band gradient stops | |
--color-teal-600 | #27c8c3 | ||
--color-teal-700 | #10b2ad | ||
--color-black-transparent-15 | rgba(11, 11, 11, 0.15) | ||
--color-black-transparent-85 | rgba(11, 11, 11, 0.85) | ||
--color-white-transparent-50 | rgba(255, 255, 255, 0.5) |