FoundationsUpdated Sep 9, 2026
Color
Every color is a CSS variable in @highlight/ui, exposed as a Tailwind utility. Light and dark are two values of the same token, so components never branch on theme.
Usage
Semantic first. Hierarchy comes from opacity on one token, not from a second hue.
- Text is
text-foreground; secondary/80, tertiary/60. Do not go below/50for readable copy. - Surfaces are
bg-background(ground),bg-secondary(raised) andbg-muted(recessed, popups). - Strokes are always
border-borderwith an opacity, typically/10to/20. Neverborder-foreground. - Brand is loud. One primary action per view, and selection. Never as body text.
text-black/text-whiteonly when the color must not flip with the theme (for example, on a photo).
// Text: one token, opacity for hierarchy
<p className="text-foreground">Primary</p>
<p className="text-foreground/80">Secondary</p>
<p className="text-foreground/60">Tertiary</p>
// Surfaces and strokes
<div className="bg-background border border-border/10 rounded-xl" />
<div className="bg-muted" />
// Accent only where it means something
<button className="bg-brand text-brand-foreground">Primary action</button>Semantic
The 2.0 tokens. Reach for these first. They flip with the theme and carry meaning, so a surface stays a surface in light and dark.
bg-backgroundPage and surface ground
- light
- #fafafa
- dark
- #212121
text-foregroundText and icons; step opacity for hierarchy
- light
- #2e2e2e
- dark
- #e0e0e0
bg-secondaryRaised surface
- light
- #ffffff
- dark
- #4a4a4a
bg-mutedRecessed surface, popups
- light
- #f2f2f2
- dark
- #292929
border-borderStrokes and rings; always with opacity
- light
- #000000
- dark
- #ffffff
bg-brandHighlight yellow. Primary actions and selection
- light
- #f9f33e
- dark
- #fff71a
text-brand-foregroundText on brand
- light
- #404040
- dark
- #333333
text-successPositive status
- light
- #27b951
- dark
- #00cc88
text-dangerDestructive, errors
- light
- #ec5b51
- dark
- #f04e42
bg-meeting-accentLive meeting affordances
- light
- #009994
- dark
- #00998a
bg-meeting-mutedMeeting surface tint
- light
- #efece6
- dark
- #2f2d28
Palette
Named hues, desaturated in dark mode. Use them for illustration, integrations, and charts, never for text hierarchy.
bg-light- light
- #ffffff
- dark
- #1a1a1a
bg-dark- light
- #000000
- dark
- #e6e6e6
bg-green- light
- #27b951
- dark
- #3d8f5b
bg-red- light
- #ff3860
- dark
- #cc3352
bg-primary- light
- #00ffff
- dark
- #339999
bg-teal- light
- #00faf6
- dark
- #339997
bg-blue- light
- #2b3cf3
- dark
- #4753d1
bg-purple- light
- #6730fd
- dark
- #684db3
bg-pink- light
- #ff1f8f
- dark
- #a14573
bg-light-pink- light
- #ffa8d4
- dark
- #c27099
bg-yellow- light
- #ecbd13
- dark
- #e7ff0f
bg-warning- light
- #ff8c1a
- dark
- #cc8033
bg-premium-green- light
- #089900
- dark
- #39d600
bg-premium-blue- light
- #008bc2
- dark
- #2292bf
Green scale
A stepped scale that inverts in dark mode (100 is lightest in light mode, darkest in dark mode).
bg-green-100- light
- #ddf9dd
- dark
- #29562a
bg-green-200- light
- #bdecb6
- dark
- #326734
bg-green-300- light
- #acdf96
- dark
- #3a784f
bg-green-400- light
- #acd38d
- dark
- #428a5c
bg-green-500- light
- #41dc68
- dark
- #4b9b69
bg-green-600- light
- #066b3b
- dark
- #64b484
bg-green-700- light
- #0d4529
- dark
- #87c5a1
bg-green-800- light
- #133a25
- dark
- #a9d6bc
bg-green-900- light
- #143322
- dark
- #cbe6d8
bg-green-950- light
- #031c11
- dark
- #ddeee6
Alpha scales
LegacyPre-mixed translucent tints. Prefer the semantic token with a Tailwind opacity modifier (`bg-foreground/10`) in new code; these remain for existing surfaces.
bg-light-2- light
- 0 0% 100% / 0.02
- dark
- 0 0% 0% / 0.02
bg-light-3- light
- 0 0% 100% / 0.03
- dark
- 0 0% 0% / 0.03
bg-light-4- light
- 0 0% 100% / 0.04
- dark
- 0 0% 0% / 0.04
bg-light-5- light
- 0 0% 100% / 0.05
- dark
- 0 0% 0% / 0.05
bg-light-8- light
- 0 0% 100% / 0.08
- dark
- 0 0% 0% / 0.08
bg-light-10- light
- 0 0% 100% / 0.1
- dark
- 0 0% 0% / 0.1
bg-light-15- light
- 0 0% 100% / 0.15
- dark
- 0 0% 0% / 0.15
bg-light-16- light
- 0 0% 100% / 0.16
- dark
- 0 0% 0% / 0.16
bg-light-20- light
- 0 0% 100% / 0.2
- dark
- 0 0% 0% / 0.2
bg-light-40- light
- 0 0% 100% / 0.4
- dark
- 0 0% 0% / 0.4
bg-light-50- light
- 0 0% 100% / 0.5
- dark
- 0 0% 0% / 0.5
bg-light-60- light
- 0 0% 100% / 0.6
- dark
- 0 0% 0% / 0.6
bg-light-70- light
- 0 0% 100% / 0.7
- dark
- 0 0% 100% / 0.7
bg-light-80- light
- 0 0% 100% / 0.8
- dark
- 0 0% 0% / 0.8
bg-light-90- light
- 0 0% 100% / 0.9
- dark
- 0 0% 0% / 0.9
bg-dark-5- light
- 0 0% 0% / 0.05
- dark
- 0 0% 90% / 0.05
bg-dark-10- light
- 0 0% 0% / 0.1
- dark
- 0 0% 90% / 0.1
bg-dark-20- light
- 0 0% 0% / 0.2
- dark
- 0 0% 90% / 0.2
bg-dark-40- light
- 0 0% 0% / 0.4
- dark
- 0 0% 90% / 0.4
bg-dark-60- light
- 0 0% 0% / 0.6
- dark
- 0 0% 90% / 0.6
bg-dark-80- light
- 0 0% 0% / 0.8
- dark
- 0 0% 90% / 0.8
bg-dark-90- light
- 0 0% 0% / 0.9
- dark
- 0 0% 90% / 0.9
bg-green-5- light
- 142 78% 61% / 0.05
- dark
- 142 40% 40% / 0.05
bg-green-10- light
- 142 78% 61% / 0.1
- dark
- 142 40% 40% / 0.1
bg-green-20- light
- 142 78% 61% / 0.2
- dark
- 142 40% 40% / 0.2
bg-green-40- light
- 142 78% 61% / 0.4
- dark
- 142 40% 40% / 0.4
bg-green-60- light
- 142 78% 61% / 0.6
- dark
- 142 40% 40% / 0.6
bg-green-80- light
- 142 78% 61% / 0.8
- dark
- 142 40% 40% / 0.8
bg-red-5- light
- 348 100% 61% / 0.05
- dark
- 348 60% 50% / 0.05
bg-red-10- light
- 348 100% 61% / 0.1
- dark
- 348 60% 50% / 0.1
bg-red-20- light
- 348 100% 61% / 0.2
- dark
- 348 60% 50% / 0.2
bg-red-40- light
- 348 100% 61% / 0.4
- dark
- 348 60% 50% / 0.4
bg-red-60- light
- 348 100% 61% / 0.6
- dark
- 348 60% 50% / 0.6
bg-red-80- light
- 348 100% 61% / 0.8
- dark
- 348 60% 50% / 0.8
bg-primary-5- light
- 181 100% 50% / 0.05
- dark
- 181 50% 40% / 0.05
bg-primary-10- light
- 181 100% 50% / 0.1
- dark
- 181 50% 40% / 0.1
bg-primary-20- light
- 181 100% 50% / 0.2
- dark
- 181 50% 40% / 0.2
bg-primary-30- light
- 181 100% 50% / 0.3
- dark
- 181 50% 40% / 0.3
bg-primary-40- light
- 181 100% 50% / 0.4
- dark
- 181 50% 40% / 0.4
bg-primary-50- light
- 181 100% 50% / 0.5
- dark
- 181 50% 40% / 0.5
bg-primary-60- light
- 181 100% 50% / 0.6
- dark
- 181 50% 40% / 0.6
bg-primary-70- light
- 181 100% 50% / 0.7
- dark
- 181 50% 40% / 0.7
bg-primary-80- light
- 181 100% 50% / 0.8
- dark
- 181 50% 40% / 0.8
bg-primary-90- light
- 181 100% 50% / 0.9
- dark
- 181 50% 40% / 0.9
bg-pink-5- light
- 330 100% 56% / 0.05
- dark
- 330 40% 45% / 0.05
bg-pink-10- light
- 330 100% 56% / 0.1
- dark
- 330 40% 45% / 0.1
bg-pink-20- light
- 330 100% 56% / 0.2
- dark
- 330 40% 45% / 0.2
bg-pink-40- light
- 330 100% 56% / 0.4
- dark
- 330 40% 45% / 0.4
bg-pink-60- light
- 330 100% 56% / 0.6
- dark
- 330 40% 45% / 0.6
bg-pink-80- light
- 330 100% 56% / 0.8
- dark
- 330 40% 45% / 0.8
bg-purple-5- light
- 255 100% 59% / 0.05
- dark
- 255 40% 50% / 0.05
bg-purple-10- light
- 255 100% 59% / 0.1
- dark
- 255 40% 50% / 0.1
bg-purple-20- light
- 255 100% 59% / 0.2
- dark
- 255 40% 50% / 0.2
bg-purple-40- light
- 255 100% 59% / 0.4
- dark
- 255 40% 50% / 0.4
bg-purple-60- light
- 255 100% 59% / 0.6
- dark
- 255 40% 50% / 0.6
bg-purple-80- light
- 255 100% 59% / 0.8
- dark
- 255 40% 50% / 0.8
bg-warning-5- light
- 30 100% 55% / 0.05
- dark
- 30 60% 50% / 0.05
bg-warning-10- light
- 30 100% 55% / 0.1
- dark
- 30 60% 50% / 0.1
bg-warning-20- light
- 30 100% 55% / 0.2
- dark
- 30 60% 50% / 0.2
bg-warning-40- light
- 30 100% 55% / 0.4
- dark
- 30 60% 50% / 0.4
bg-warning-60- light
- 30 100% 55% / 0.6
- dark
- 30 60% 50% / 0.6
bg-warning-80- light
- 30 100% 55% / 0.8
- dark
- 30 60% 50% / 0.8
bg-yellow-10- light
- 66 100% 53% / 0.1
- dark
- 45 70% 45% / 0.1
bg-yellow-80- light
- 66 100% 53% / 0.8
- dark
- 45 70% 45% / 0.8
bg-teal-16- light
- 180 100% 49% / 0.16
- dark
- 180 50% 40% / 0.16
bg-teal-80- light
- 180 100% 49% / 0.8
- dark
- 180 50% 40% / 0.8
Legacy roles
LegacyRole tokens from the 1.0 dark-first theme. Map them per the style guide: text โ `text-foreground` with opacity, surfaces โ `bg-background`/`bg-muted`, strokes โ `border-border`.
text-primary- light
- #f7f7f7
- dark
- #080808
text-secondary-old- light
- #cccccc
- dark
- #333333
text-tertiary- light
- #999999
- dark
- #666666
text-subtle- light
- #666666
- dark
- #999999
text-disabled- light
- #333333
- dark
- #cccccc
text-accent- light
- #00f1f5
- dark
- #2d8486
bg-primary- light
- #212121
- dark
- #e8e8e8
bg-secondary-old- light
- #1a1a1a
- dark
- #f0f0f0
bg-tertiary- light
- #2b2b2b
- dark
- #e0e0e0
bg-hover- light
- #292929
- dark
- #e6e6e6
bg-bg-layer-1- light
- #0f0f0f
- dark
- #f5f5f5
border-primary- light
- #00ffff
- dark
- #339999
border-secondary-old- light
- #454545
- dark
- #bfbfbf
border-tertiary- light
- #212121
- dark
- #d9d9d9
border-subtle- light
- #1a1a1a
- dark
- #d9d9d9
bg-tertiary-0- light
- #b5b5b5
- dark
- #4d4d4d
bg-tertiary-30- light
- #87847d
- dark
- #868279
bg-tertiary-50- light
- #3d3d3d
- dark
- #b3b3b3
bg-tertiary-70- light
- #262626
- dark
- #cccccc
bg-tertiary-100- light
- #161618
- dark
- #eaeaec
How theming works
Values live in packages/ui/src/styles/base.css; this page reads that file at build time.
/* Tokens are HSL triples so Tailwind opacity modifiers work: */
:root { --brand: 58 94% 61%; }
.dark { --brand: 58 100% 55%; }
/* tailwind.config.ts (from @highlight/ui) */
colors: { brand: 'hsl(var(--brand))' }
/* .dark on <html> switches the theme; .dark.low-contrast lifts the darkest surfaces */