4.1 The idea
Since Labs is cream, ink and terracotta. Not dark-mode navy, not electric blue, not a gradient. The palette is the single fastest signal that this is not another AI cockpit — protect it harder than anything else in this guide.
The proportions matter as much as the values. 60 / 30 / 10:
| Share | Role | Colour |
|---|---|---|
| ~60% | The ground | Paper #F7F5F2 |
| ~30% | Content and structure | Ink, white surfaces, hairlines |
| ~10% | Emphasis | Terracotta #C4602A |
If a surface is more than roughly a tenth terracotta, it has stopped meaning anything. The accent is a scalpel.
4.2 The palette
Ink — everything you read
| Token | Hex | Use |
|---|---|---|
ink | #1A1917 | Headlines, primary text, dark surfaces, the dark-theme ground |
ink-body | #2C2A28 | Running body copy. Softer than ink so long text does not vibrate |
ink-muted | #6B6762 | Labels, captions, secondary text, inactive nav |
on-ink | #F5F1EA | Text on ink. Warm off-white, never #FFFFFF — pure white on a warm dark ground reads clinical and slightly blue |
Paper — the grounds
| Token | Hex | Use |
|---|---|---|
paper | #F7F5F2 | The default page background |
paper-base | #F4F3F1 | Recessed chrome — sidebars, rails, the app frame. One step behind paper |
Surfaces — things on top of paper
| Token | Hex | Use |
|---|---|---|
surface | #FFFFFF | Cards, panels, inputs, modals |
surface-mist | #EFEFEC | Subtle neutral fill — hover, neutral chips, icon tiles, avatar wells |
surface-cream | #F0E4DA | Warm accent fill. The tinted sibling of mist |
Borders
| Token | Hex | Use |
|---|---|---|
border | #E5E2DE | Default hairline — card edges, table rules, dividers |
border-strong | #D8D5D0 | Emphasised edge — input borders, secondary buttons |
4.3 Terracotta, and the one rule that matters
This is the most important paragraph in the chapter.
#C4602Ais a fill colour.#A34A1Fis a text colour.
#C4602A on white measures 4.16:1. WCAG AA for normal text is 4.5:1. So
the brand orange, used as a link or a button label, fails — by a margin small
enough that nobody notices in review and large enough to matter to a contractor
reading a phone in daylight. The fix is not to abandon the brand colour; it is to
keep a second, darker terracotta for anything with letterforms in it.
| Token | Hex | On white | Use |
|---|---|---|---|
accent | #C4602A | 4.16:1 | Fills only. The // mark, focus rings, chart series, dots, icons, accent tiles |
accent-hover | #A84E22 | 5.56:1 | Hover for a terracotta fill |
accent-ink | #A34A1F | 5.90:1 | Text and links on light surfaces, and solid buttons whose label must clear AA |
accent-ink-hover | #8B3D18 | 8.1:1 | Hover for accent text and links |
accent-lift | #E07A38 | — (5.86:1 on ink) | Terracotta on dark surfaces. #C4602A only reaches 4.23:1 there |
accent-soft | rgba(196,96,42,0.12) | — | Translucent wash — active nav rows, attention chips |
accent-light | #F0E4DA | — | Opaque equivalent of accent-soft |
Both #A34A1F and #C4602A already ship on sincelabs.com as --accent-ink
and --accent. This is not a new colour; it is an existing one being given its
job in writing.
⚠️ Conflicting values in circulation
Three different "brand oranges" exist in Since Labs documents. #C4602A is
correct — it is what both sincelabs.com and sincelabs/app actually ship.
| Value | Where it appears | Verdict |
|---|---|---|
#C4602A | Live site CSS (--accent), app globals.css | ✅ Canonical |
#E8501A | Notion Agent.md § 1 | ❌ Stale. Update Agent.md |
#C4561A | Notion "Brand Design System Skills" | ❌ An eyeball approximation of the live value |
#A95022 | App dashboard charts, hard-coded | ❌ A drift. Close to accent-ink — use #A34A1F |
#FF5C35 | Brand Guidelines v1 § 5 | ❌ An explicit placeholder, marked TO CONFIRM. Now confirmed |
4.4 Status colours
Six states. Each is a triple — a background, a text colour, and a dot.
| State | Background | Text | Dot | Means |
|---|---|---|---|---|
| Success | #EAF3DE | #3B6D11 | #639922 | Active, approved, live, complete |
| Attention | #F0E4DA | #9A4A1F | #C4602A | Pending, waiting, needs review |
| Warning | #FFF3E0 | #8A4A05 | #B25C00 | Degraded, stale, partial |
| Error | #FCEBEB | #791F1F | #E24B4A | Rejected, failed, disabled, suspended |
| Info | #EBF0F7 | #3A4A60 | #3A4A60 | Internal, draft, informational |
| Neutral | #EFEFEC | #6B6762 | #6B6762 | Inactive, retired, archived, unknown |
Every pairing above clears AA (5.4:1 to 9.0:1).
The dot is not decoration. It is the redundant, non-colour channel. A status communicated by colour alone fails WCAG 1.4.1 and fails a colour-blind operator scanning a review queue. Ship the dot, or ship a word.
Attention deliberately shares terracotta. "Waiting on you" is the brand's most common state, and it should feel like the brand rather than like a warning.
On dark
Every status has a second triple. Without it the light fills survive into the dark theme and a chip renders cream-on-cream — unreadable, and the exact bug that shipped in the scrap-desk mockup before this table existed.
| State | Background | Text | Dot | Text on bg |
|---|---|---|---|---|
| Success | #26321C | #83B456 | #639922 | 5.6:1 |
| Attention | #40291E | #EF8D5D | #C4602A | 5.6:1 |
| Warning | #3F2A1B | #E89150 | #B7600B | 5.5:1 |
| Error | #422725 | #F3867F | #E24B4A | 5.5:1 |
| Info | #292F36 | #95A7BF | #677890 | 5.5:1 |
| Neutral | #2F2E2C | #A9A5A0 | #7A7670 | 5.5:1 |
A dark fill sits above the surface, not below it. This is the one thing that is not obvious. On light, a status fill is a pale tint lighter than the page and darker than nothing. The instinct on dark is to make it a deep tint — but a fill darker than the
#232120card it sits on is invisible: it reads as a hole, not a chip. Every fill above is a tint lighter than the card, separating at 1.18:1 — the same margin the light set gets against white (~1.15:1).
scripts/check-tokens.mjs enforces both halves: AA for the label on its own
fill, and that the fill is actually distinguishable from dark.surface.
4.5 Dark
The brand inverts; it does not switch palettes. Ink becomes the ground, paper becomes the text, and terracotta lifts so it still clears AA.
| Token | Light | Dark |
|---|---|---|
| Ground | #F7F5F2 | #1A1917 |
| Surface | #FFFFFF | #232120 |
| Raised surface | #EFEFEC | #2C2A28 |
| Primary text | #1A1917 | #F5F1EA |
| Muted text | #6B6762 | #98938C |
| Border | #E5E2DE | #38352F |
| Accent | #C4602A | #E07A38 |
| Accent wash | rgba(196,96,42,.12) | #2E1E0F |
Three traps.
- Muted text on dark must be
#98938C(5.8:1). The site currently also defines#7A7570, which is 3.9:1 — fine for a 20px label, a failure for a caption. - Terracotta must lift to
#E07A38on dark.#C4602Adrops to 4.23:1 against ink. - The table above is not the whole palette. Status and chart colours invert too, and they are easy to forget because nothing on a light screen shows you they are missing. Their dark values are in 4.4 and 4.6.
accent wash on dark (#2E1E0F) is tuned to sit on the ground, not on a
card — it separates from #1A1917 at 1.10:1 but from #232120 at only 1.00:1.
For an accent-tinted region inside a card, use the attention fill #40291E.
sincelabs.com ships dark. sincelabs/app does not — it is light-only, and
that is a deliberate, documented gap, not an oversight. See the app audit.
4.6 Data visualisation
Sequential — one measure across ranked categories. Darkest is largest.
#A34A1F → #C4602A → #D27C53 → #E9A88A → #F4D2C3
Categorical — unordered series. Terracotta always leads: it is the subject, the rest are context.
#C4602A terracotta · #3A4A60 slate · #639922 moss · #7A4A5F wine · #2C2A28 ink
The categorical set is built to two constraints, both enforced by
npm run check:
- Every entry clears 3:1 against white, so a thin line or a small dot is a visible graphical object (WCAG 1.4.11).
- Every pair differs by at least 1.2:1, so the set survives greyscale — a printed report, a projector, a colour-blind reader.
That second rule is why the obvious warm choices are not in the set. #B25C00
amber sits at 4.75:1 and terracotta at 4.16:1 — a 1.14:1 separation, which is
two indistinguishable oranges the moment colour is removed.
On dark
The light set cannot carry over. Slot 5 is near-black ink, which is invisible on
an ink ground — and slate at #3A4A60 is a dark navy that all but disappears
on a #232120 card.
Sequential — #B0562C → #C4602A → #D27C53 → #E9A88A → #F4D2C3
Categorical — #C7632D terracotta · #6F8199 slate · #639922 moss · #9D5E7A wine · #A6A4A2 ink
| Alias | Light | Dark |
|---|---|---|
| slate | #3A4A60 | #6F8199 |
| moss | #639922 | #639922 |
| amber | #B25C00 | #C0691B |
| wine | #7A4A5F | #9D5E7A |
Slots 4 and 5 are re-stepped, not merely lifted. Lifting near-black ink far
enough to clear the dark surface lands it on top of wine at ΔE 7 —
indistinguishable even with full colour vision, before you get to colour
blindness. Re-stepped, the adjacent pair clears ΔE 18. Every dark slot clears
4:1 on dark.surface.
Rules:
- Five series maximum. Past five, the reader is decoding a legend instead of reading a chart. Group the tail into "Other".
- Never encode by colour alone. Label the series directly, or give each a shape or a pattern.
- Never a dual axis. Two measures on two y-scales invent a correlation the data does not contain. Two charts, small multiples, or index both to a common base.
- Gridlines are
border#E5E2DE(#38352Fon dark), never a mid grey. - Axis labels are
ink-mutedat 11px. - Area fills are the series colour at 12–15% opacity, and the stroke is the full-strength colour.
4.7 Do and don't
Do
- ✅ Let paper dominate. Whitespace is the design.
- ✅ Use
accent-inkfor anything with letterforms. - ✅ Pair every status colour with a dot or a word.
- ✅ Use
on-ink#F5F1EAon dark grounds, not#FFFFFF. - ✅ Check a new surface in both themes before calling it done — a light-only review cannot see a missing dark token.
Don't
- ❌ Use
accent#C4602Aas a text or link colour on light - ❌ Introduce a colour that is not in this chapter, "just for this one screen"
- ❌ Ship a status chip or chart series without its dark value — the light fill survives into dark and renders cream-on-cream
- ❌ Reach for Tailwind's default palette —
zinc,red-700,indigo-800are all off-brand, and all currently in the app - ❌ Use gradients, except the one sanctioned accent-tile wash
- ❌ Use pure
#000000or pure#FFFFFFas a page ground - ❌ Communicate state by colour alone