Skip to content
Brand guide

Chapter 04

Colour

Warm paper, one hot accent, and a strict rule about which terracotta you are allowed to read. Live swatches and every computed contrast ratio are in the colour explorer.

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:

ShareRoleColour
~60%The groundPaper #F7F5F2
~30%Content and structureInk, white surfaces, hairlines
~10%EmphasisTerracotta #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

TokenHexUse
ink#1A1917Headlines, primary text, dark surfaces, the dark-theme ground
ink-body#2C2A28Running body copy. Softer than ink so long text does not vibrate
ink-muted#6B6762Labels, captions, secondary text, inactive nav
on-ink#F5F1EAText on ink. Warm off-white, never #FFFFFF — pure white on a warm dark ground reads clinical and slightly blue

Paper — the grounds

TokenHexUse
paper#F7F5F2The default page background
paper-base#F4F3F1Recessed chrome — sidebars, rails, the app frame. One step behind paper

Surfaces — things on top of paper

TokenHexUse
surface#FFFFFFCards, panels, inputs, modals
surface-mist#EFEFECSubtle neutral fill — hover, neutral chips, icon tiles, avatar wells
surface-cream#F0E4DAWarm accent fill. The tinted sibling of mist

Borders

TokenHexUse
border#E5E2DEDefault hairline — card edges, table rules, dividers
border-strong#D8D5D0Emphasised edge — input borders, secondary buttons

4.3 Terracotta, and the one rule that matters

This is the most important paragraph in the chapter.

#C4602A is a fill colour. #A34A1F is 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.

TokenHexOn whiteUse
accent#C4602A4.16:1Fills only. The // mark, focus rings, chart series, dots, icons, accent tiles
accent-hover#A84E225.56:1Hover for a terracotta fill
accent-ink#A34A1F5.90:1Text and links on light surfaces, and solid buttons whose label must clear AA
accent-ink-hover#8B3D188.1:1Hover 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-softrgba(196,96,42,0.12)Translucent wash — active nav rows, attention chips
accent-light#F0E4DAOpaque 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.

ValueWhere it appearsVerdict
#C4602ALive site CSS (--accent), app globals.cssCanonical
#E8501ANotion Agent.md § 1❌ Stale. Update Agent.md
#C4561ANotion "Brand Design System Skills"❌ An eyeball approximation of the live value
#A95022App dashboard charts, hard-coded❌ A drift. Close to accent-ink — use #A34A1F
#FF5C35Brand 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.

StateBackgroundTextDotMeans
Success#EAF3DE#3B6D11#639922Active, approved, live, complete
Attention#F0E4DA#9A4A1F#C4602APending, waiting, needs review
Warning#FFF3E0#8A4A05#B25C00Degraded, stale, partial
Error#FCEBEB#791F1F#E24B4ARejected, failed, disabled, suspended
Info#EBF0F7#3A4A60#3A4A60Internal, draft, informational
Neutral#EFEFEC#6B6762#6B6762Inactive, 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.

StateBackgroundTextDotText on bg
Success#26321C#83B456#6399225.6:1
Attention#40291E#EF8D5D#C4602A5.6:1
Warning#3F2A1B#E89150#B7600B5.5:1
Error#422725#F3867F#E24B4A5.5:1
Info#292F36#95A7BF#6778905.5:1
Neutral#2F2E2C#A9A5A0#7A76705.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 #232120 card 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.

TokenLightDark
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 washrgba(196,96,42,.12)#2E1E0F

Three traps.

  1. 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.
  2. Terracotta must lift to #E07A38 on dark. #C4602A drops to 4.23:1 against ink.
  3. 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:

  1. Every entry clears 3:1 against white, so a thin line or a small dot is a visible graphical object (WCAG 1.4.11).
  2. 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

AliasLightDark
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 (#38352F on dark), never a mid grey.
  • Axis labels are ink-muted at 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-ink for anything with letterforms.
  • ✅ Pair every status colour with a dot or a word.
  • ✅ Use on-ink #F5F1EA on 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 #C4602A as 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-800 are all off-brand, and all currently in the app
  • ❌ Use gradients, except the one sanctioned accent-tile wash
  • ❌ Use pure #000000 or pure #FFFFFF as a page ground
  • ❌ Communicate state by colour alone

This chapter as plain markdown: /docs/color.md