Single source of truth
Shabana Colour Alignment
Where the dark-mode palette stands, the decisions Shabana needs to make, and exactly what a "delete everything not on the list" pass would break. Read against the shabana-test Figma file, 2026-06-01.
Current State
Shabana's canonical list is 34 primitive stops and 36 dark semantic tokens. The live file holds more: 116 primitives, 97 dark semantics, 98 light semantics. Two things are already settled.
The six dark tokens Shabana's usage guide moved are done, re-pointed to approved primitives with the alias chain kept (no raw hex):
| Token | Was | Now | |
|---|---|---|---|
dark/bg/raised | Neutral/925 #09141C | Slate-900 #092D46 | Done |
dark/bg/page-subtle | Neutral/900 #0D1117 | Slate-900 #092D46 | Done |
dark/bg/inverse | Neutral/100 #E6EDF3 | Slate-100 #F5F9FB | Done |
dark/action/selected | raw #FFFFFF33 (20% white) | Slate-100 #F5F9FB (solid) | Done |
dark/border/subtle | Neutral/700 #30363D | Neutral-800 #1C2128 | Done |
dark/icon/primary | Neutral/White #FFFFFF | Slate-100 #F5F9FB | Done |
dark/action/selected went from translucent 20% white to solid Slate-100, so any selected/active state that relied on see-through will now read as an opaque fill.Decisions Needed
These five are the only open questions. The six dark-token moves and all 34 primitive values are already settled (see Current State). Each row is a question for Shabana, with the options and our recommendation; the full consequence sits under What Breaks.
| # | Question to answer | Options | Recommended | Status |
|---|---|---|---|---|
| 1 | Keep the 9 primitives her own dark tokens rely on but that aren't in the 34? (detail)Delete them and 14 of her own canonical dark tokens lose their colour. | Add the 9 to the approved palette, or remap each token to one of the 34 | Add as approved primitives (they're already in use) | Blocker |
| 2 | Is light mode in or out of scope? (detail)The list is dark-only, so all 98 light tokens count as "unlisted" and would be deleted. | Keep all 98 light tokens until the light pass, or delete now | Keep; treat light as out of scope | Blocker |
| 3 | What happens to the ~50 in-use colours not on the list? (detail)They're referenced in cur8-mob, so deleting the variable orphans live usage. | Replace with an approved colour, approve as an internal exception, or keep internal-only | Approve as internal exceptions until a code migration is scoped | Needs direction |
| 4 | Approve deleting the 16 safe orphans? (detail)2 test tokens + 14 unused stops, with no alias and no code reference. | Delete now, or keep | Delete now (no breakage) | Ready |
| 5 | Is the 34-stop palette a hard deletion target or an approved working palette?Sets whether legacy primitives get removed, or kept internal and simply unpromoted. | Hard deletion target, or working palette with legacy kept internally | Approved working palette | Needs direction |
What Breaks If We Delete Blindly
The evidence behind the decisions above. A literal "delete everything not on the list" pass is not safe to run as-is.
1. The core conflict: 9 primitives her own tokens need
Shabana's primitive list (34) and her dark semantic list (36) are not internally consistent. Fourteen of her own canonical dark tokens point at primitives outside the 34. Delete those primitives and her own tokens lose their colour.
| Primitive (not in the 34) | Value | Canonical token(s) that need it |
|---|---|---|
Neutral/975 | #030F1A | dark/bg/page |
Green/Green-900 | #236C18 | dark/bg/success |
Red/Red-900 | #470E00 | dark/bg/error |
Yellow/Yellow-900 | #332D00 | dark/bg/warning |
Neutral/300 | #C9D1D9 | dark/text/secondary, dark/icon/secondary |
Neutral/900 | #0D1117 | dark/text/inverse, dark/icon/inverse |
Blue/Blue-400 | #8CA1EE | dark/text/brand, dark/icon/brand, dark/feedback/info |
Yellow/Yellow-300 | #FFEF75 | dark/text/warning, dark/feedback/warning |
Yellow/Yellow-200 | #FFF5AB | dark/feedback/pending |
2. Light mode would be wiped
The list is dark-only, so none of the 98 light semantic tokens are on it. A literal pass deletes the entire light theme, including bg/page, text/primary, action/primary and the full light product, badge and entity set.
Semantic Light untouched until the dedicated light-mode pass.3. ~50 colours are live in cur8-mob
Not on the list, but referenced in the app through semantic mappings or component files. Deleting the variable orphans the usage, so each family needs a replace / approve / keep-internal call plus a code migration.
| Family | Members | Where used |
|---|---|---|
| Extended accents | Peach, Rose, Lavender, Salmon, Cyan-Light/Dark, Magenta, Magenta-Light, Terracotta-light/Dark | deal types, entity accents and backgrounds |
| Gold / premium | Gold-200, Gold-500, Gold-800, Gold-pending set | premium badges, pending states |
| Info blues | Sky-400, Blue-950 | info text/icons, info badge and background |
| Neutrals / slate steps | Neutral-200/300/600/900/975, Slate-150/200/400/600/700 | secondary text, inverse, inset, page tints, muted accents |
| Overlays / glass | Neutral/Black alpha set, Neutral/Glass(+10/80), White-8/10/12/31/50, Glass gradients | modals, drawers, frosted panels, blur fallbacks |
| Status depths | Green-50/600/750/900, Yellow-50/600/750/900/300/200, Red-900 | tint surfaces, feedback, high-contrast status text |
How the numbers break down
| Set | Bucket | Count | Meaning |
|---|---|---|---|
| Primitives (116) | Canonical | 34 | On the list, values already correct. |
| Load-bearing | 49 | Not on the list, but a kept semantic token aliases to them (the 9 above plus 40 backing info, product, overlay, glass and light tokens). Cannot delete without breaking a token. | |
| Orphan | 33 | No semantic alias, so these are the deletion candidates. But orphan is not the same as safe: 17 are still used in code or purpose-built, only 16 are safe to delete. See the orphan breakdown. | |
| Dark semantics (97) | On the list | 36 | Shabana's canonical dark set. |
| Would be deleted | 61 | Product/domain (~37), info family (4), disabled/inset variants (~7), overlays/base/on-fill (~9). Most are used in the app today. | |
| Light semantics (98) | Would be deleted | 98 | All of them, see point 2. |
Canonical Reference
The approved set to align to, one table per fact. Open as needed.
34 canonical primitives
| Family | Token | Value |
|---|---|---|
| Slate | Slate-100 | #F5F9FB |
| Slate | Slate-300 | #CEDBE4 |
| Slate | Slate-500 | #7992A6 |
| Slate | Slate-800 | #25445B |
| Slate | Slate-900 | #092D46 |
| Blue | Blue-100 | #EEF0F7 |
| Blue | Blue-300 | #B9C4EE |
| Blue | Blue-500 | #5D7DF4 |
| Blue | Blue-600 | #1E4FDD |
| Blue | Blue-800 | #1334AE |
| Blue | Blue-900 | #142871 |
| Green | Green-100 | #ECFBEA |
| Green | Green-300 | #AFFAA3 |
| Green | Green-400 | #82FF6F |
| Green | Green-500 | #31F613 |
| Green | Green-700 (N) | #27A414 |
| Green | Green-800 | #268717 |
| Red | Red-100 | #FFE7E0 |
| Red | Red-400 | #FF6C47 |
| Red | Red-700 (N) | #AD2300 |
| Red | Red-800 | #7A1800 |
| Yellow | Yellow-100 | #FFFBE0 |
| Yellow | Yellow-400 | #FFE940 |
| Yellow | Yellow-700 | #9E8C00 |
| Yellow | Yellow-800 | #695C00 |
| Extended | Violet | #DD97F2 |
| Extended | Cyan | #3A9AA8 |
| Extended | Coral | #F1A297 |
| Extended | Terracotta | #A67B4B |
| Neutral | Neutral-100 | #E6EDF3 |
| Neutral | Neutral-400 | #8B949E |
| Neutral | Neutral-500 | #57606A |
| Neutral | Neutral-700 | #30363D |
| Neutral | Neutral-800 | #1C2128 |
36 canonical dark semantic tokens
| Group | Token | Value | Role |
|---|---|---|---|
| Surface | dark/bg/page | #030F1A | App canvas |
| Surface | dark/bg/raised | #092D46 | Card, panel, sheet |
| Surface | dark/bg/page-subtle | #092D46 | Sidebar, tray |
| Surface | dark/bg/inverse | #F5F9FB | Light islands in dark UI |
| Surface | dark/bg/success | #236C18 | Success tint |
| Surface | dark/bg/error | #470E00 | Error tint |
| Surface | dark/bg/warning | #332D00 | Warning tint |
| Text | dark/text/primary | #E6EDF3 | Body, headings |
| Text | dark/text/secondary | #C9D1D9 | Descriptions |
| Text | dark/text/tertiary | #8B949E | Placeholder, hint |
| Text | dark/text/disabled | #57606A | Disabled text |
| Text | dark/text/inverse | #0D1117 | Text on light |
| Text | dark/text/brand | #8CA1EE | Links, brand |
| Text | dark/text/success | #31F613 | Success inline |
| Text | dark/text/error | #FF6C47 | Error inline |
| Text | dark/text/warning | #FFEF75 | Warning inline |
| Action | dark/action/primary | #1E4FDD | Hero CTA |
| Action | dark/action/secondary | #30363D | Secondary / ghost |
| Action | dark/action/selected | #F5F9FB | Selected / active |
| Action | dark/action/destructive | #FF6C47 | Delete / danger |
| Action | dark/action/disabled | #57606A | Disabled CTA |
| Border | dark/border/subtle | #1C2128 | Divider |
| Border | dark/border/default | #30363D | Card / input outline |
| Border | dark/border/strong | #57606A | Emphasis / hover |
| Border | dark/border/focus | #F5F9FB | Focus ring |
| Border | dark/border/error | #FF6C47 | Error outline |
| Border | dark/border/success | #31F613 | Success outline |
| Icon | dark/icon/primary | #F5F9FB | Primary icon |
| Icon | dark/icon/secondary | #C9D1D9 | Secondary icon |
| Icon | dark/icon/inverse | #0D1117 | Icon on light |
| Icon | dark/icon/brand | #8CA1EE | Brand icon |
| Feedback | dark/feedback/success | #31F613 | Success / live |
| Feedback | dark/feedback/error | #FF6C47 | Error / critical |
| Feedback | dark/feedback/warning | #FFEF75 | Warning / at-risk |
| Feedback | dark/feedback/pending | #FFF5AB | Pending / queued |
| Feedback | dark/feedback/info | #8CA1EE | Info notice |
Usage notes (accessibility)
| Colour | Use for | A11y note |
|---|---|---|
Blue-600 | Hero CTA, primary button, active indicator | Large-text AA only (min 18px) |
Blue-800 | CTA text on light/inverse and any CTA text under 18px | Full AA at 7.2:1 |
Green-400 | Positive growth and data-viz highlights (electric lime) | High-impact data colour, not a generic semantic |
Yellow-400 | Neutral / average reference line in charts | Data-viz primitive |
dark/text/brand, dark/icon/brand | Links, brand moments, onboarding icons | Large-text only |
Full Inventory
The detail behind the buckets, for the engineering migration once the decisions land.
Orphan primitives (33)
An orphan is a primitive no semantic token aliases to, so orphans are the deletion candidates. But orphan does not mean safe: 17 of the 33 are still referenced in cur8-mob code or are purpose-built, leaving only 16 safe to remove now. Code references are from the 2026-06-01 audit, so re-check before deleting.
Orphans to keep or verify (17) — used in code or purpose-built
| Group | Primitives | Why keep |
|---|---|---|
| White overlays | White-8, White-10, White-12, White-31, White-50 | whiteOverlay* in modal and fund-notice styled files |
| Glass gradients | Glass/Gradient-start, Glass/Gradient-end, Glass/Icon-start, Glass/Icon-end | IconBadge, if-isa status card, summary/review screens |
| Dark glass | Neutral/Glass-10, Neutral/Glass-80 | pv2 card and surface backgrounds |
| Gold pending | Gold/Gold-pending, Gold/Gold-pending-bg, Gold/Gold-pending-border, Gold/Gold-pending-subtle | purpose-built for pending badges; confirm usage before removing |
| Other | Blue-200, Neutral/925 | SecondaryDarkExplorer.stories.tsx (Neutral/925 only freed up after the recent dark/bg/raised re-alias) |
Orphans safe to delete now (16)
No semantic alias and no known code reference. Lowest-risk trim.
| Type | Tokens |
|---|---|
| Test / junk (2) | TEST 02, red-icon |
| Unused stops (14) | Blue-700, Green-200, Green-track-subtle, Red-200, Red-300, Red-500, Red-600, Yellow-500, Neutral-50, Neutral-950, Extended/Indigo, Extended/Azure, Extended/Magenta-Dark, Sky-700 |
Dark semantics that would be deleted (61)
| Group | Examples | Risk |
|---|---|---|
| Product / domain (~37) | dark/product/deal/*, /entity/*, /badge/*, /premium/*, /number/* | High |
| Info family (4) | dark/bg/info, dark/text/info, dark/icon/info, dark/border/info | High |
| Disabled / inset (~7) | dark/bg/disabled, dark/bg/inset, dark/action/disabled-text, dark/action/secondary-border | Medium |
| Overlays / base / on-fill (~9) | dark/overlay/*, dark/base/black, dark/text/on-fill, dark/icon/tertiary | Medium |