Color
One primary, a small set of accents, one neutral ramp. The purple marks what you can act on; greys do almost all the work.
Core colors
Four values carry the identity.
Brand Purple
#471eff
--brand-primary
The primary. Every call to action, link, focus ring and selected state. This is the 1club purple — nothing else is.
Ink
#212121
--ink
The near-black. Dark brand surfaces, and the strongest text on light backgrounds.
Mist
#e7fefd
--mist
The pale cyan that pairs with Ink. Text and icons on dark brand surfaces.
White
#ffffff
--canvas
The page. Also the text colour on Brand Purple.
Brand Purple is a signal, not a decoration — if it appears somewhere the user cannot act, it is misused. On a club’s own surfaces their colour replaces it.
Accent colors
Two sets, two jobs: brand accents give a surface mood, feedback colours mean one thing each.
Brand accents
Lavender
#a294ea
Closest to the primary — identity and brand surfaces.
Sand
#ebd69f
Warm and editorial. Pairs with photography in the ritual register.
Rose
#d9adc4
Soft counterweight to the cooler accents.
Mint
#bfe0dc
Calm, quiet surfaces — content and copy.
Blue
#b3c7e6
Structure and motion; the most neutral of the accents.
Sage
#c2d8a1
Grounded and organic. Wide surfaces and banners.
Never mix a saturated colour into this set — one loud tile makes the other five look broken.
Feedback
Success
#10b981
Confirmed, paid, active.
Warning
#f59e0b
Pending, expiring, needs attention.
Danger
#ef4444
Failed, cancelled, destructive actions.
Never branded. A club whose brand colour is red still gets our red for errors.
Greys
One ramp, ten steps. Text, borders, surfaces and dark mode all come from here.
50
#fafafa
100
#f4f4f5
200
#e4e4e7
300
#d4d4d8
400
#a1a1aa
500
#71717a
600
#52525b
700
#3f3f46
800
#27272a
900
#18181b
On light
- 50–200 — surfaces, hovers, cards
- 200–300 — borders and dividers
- 500–600 — secondary text
- 800–900 — primary text
On dark
- 900 — page background
- 800 — cards and raised surfaces
- 700 — borders (or white at 12%)
- 400 — secondary text · 50 — primary text
Neutral, never blue-tinted. On white, 500 is the lightest step that clears WCAG AA for text.
Unresolved — decisions pending
Everything above is brand guidance. Everything below is a holding area — duplicated tokens and open questions, none of it a rule yet. It should shrink to nothing.
| Item | Where it stands | Decision needed |
|---|---|---|
| --platform-purple (#6949e3) | Decided against as a brand colour — but it is not a stray duplicate. It is the focus-ring and selected-state colour in ~17 shared components (ModernInput, ModernTabs, booking pills, event dialogs, account rows). | Retiring it is a migration, not a deletion. Cheapest path: set --platform-purple to #471eff so all 17 usages become brand purple at once, then rename the token later. |
| Three app primaries | network #471eff · portal #1f1f1f · kiosk #2563eb. The portal neutral is intentional (org branding overrides it); the kiosk blue is an untouched Tailwind default. | Point the kiosk at the org brand colour, falling back to #471eff — it stands in a club’s reception, where the club’s colour matters most. |
| Three --foreground near-blacks | network #333333 · portal #082a24 (a leftover dark green) · kiosk #171717. Three authoring sessions, not three decisions. | Collapse to Ink / grey-900. Confirm nothing depends on the green. |
| Four near-identical light greys | #f7f7f6 (portal sidebar) · #f6f7f8 (portal card) · #f5f5f5 (portal muted) · #f4f4f5 (network muted). Visually indistinguishable. | Map all four onto grey-50/100. Highest-value cleanup on this page; nothing depends on the differences. |
| --brand-navy = --brand-dark | Both are #051915 in shared globals — two names for one colour. --brand-light (#0a3d35) and --brand-slate (#64748b) are declared there too; their usage is unaudited. | Audit the five --brand-* primitives, keep what is used, delete the aliases. |
| --brand-sky (#e5e5e5) | Named like a colour, is a neutral grey. | Rename or fold into the grey ramp. |
| Status tokens are scope-bound | --status-confirmed / --status-pending / --status-cancelled are set on .shared-branding-theme, so they are unset anywhere outside that wrapper — components reaching for them in a plain page context get nothing. | Promote to :root, or document the wrapper as required. |
| Two dark moods | The portal’s dark surfaces are blue-tinted slate (#1f2937, #374151); the network’s are true neutral (#1e1e1e, #1a1a1a). | Standardise on the neutral ramp above. |
| Computed contrast is coarse | --primary-foreground is never configured — it is derived from the org primary’s luminance with a single 0.5 threshold, returning #121212 or #ffffff. | Accept, or add a mid-range case for brand colours that land near the boundary. |