Color
Generated from DESIGN_SYSTEM.md
Rules
Semantic → Platform Mapping
All implementations must map to the canonical semantic name. When a new color is needed, name it semantically here first.
| Semantic Name | Light Hex | Dark Hex | Web (Tailwind) | iOS (AppTheme.Colors) | Android (colorScheme) |
|---|---|---|---|---|---|
| Brand | |||||
brand-primary | #155CFB | #155CFB | text-yroun-blue / bg-blue-600 (the filled button; white on bg-blue-500 fails AA) | brandPrimary | primary |
brand-inverse | #FFFFFF | #FFFFFF | text-white | brandInverse | onPrimary |
brand-container | #EFF6FF | #172545 | bg-blue-50 dark:bg-blue-950/40 | navActiveBg* | primaryContainer |
brand-on-container | #155CFB | #60A5FA | text-yroun-blue dark:text-blue-400 | navActiveText* | onPrimaryContainer |
yroun-yellow | #FCB319 | same | text-yroun-yellow | brandYellow | brandYellow |
yroun-green | #00A651 | same | text-yroun-green | brandGreen | brandGreen |
yroun-red | #EF4632 | same | text-yroun-red | brandRed | brandRed |
| Surfaces | |||||
surface-page | #E4E4E7 | #09090B | bg-background (--background) | backgroundBottom | background |
surface-card | #FFFFFF | #1C1F24 | bg-surface (--surface) | surfacePrimary | surface |
surface-secondary | #F4F4F5 | #27272A | bg-muted (--muted) | surfaceSecondary | surfaceVariant |
surface-overlay | rgba(255,255,255,0.92) | rgba(32,40,51,0.92) | — | surfaceOverlay | — |
surface-brand | #09090B → #14171D | same — theme-independent | brand-surface utility (--surface-brand-start/-end, sets on-brand text) | brandSurface | brandSurface |
| Text | |||||
text-primary | #0A1931 | #F8FAFC | text-prime (--prime) | textPrimary | onSurface |
text-secondary | #71717A | #A1A1AA | text-muted-foreground | textSecondary | onSurfaceVariant |
text-muted | #A1A1AA | #52525B | text-muted-foreground/60 | textMuted | — |
| Borders | |||||
border-subtle | #E4E4E7 | #27272A | border-line / divide-line | strokeSubtle | outlineVariant |
border-strong | #D4D4D8 | #3F3F46 | border-border | strokeStrong | outline |
border-interactive | #A1A1AA | #52525B | border-interactive (--interactive-border) | strokeStrong | outline |
| Semantic | |||||
success | #19844D | #58D68D | text-green-700 dark:text-green-400 | accentGreen | — |
warning | #F08F23 | #FFB257 | text-amber-600 dark:text-amber-400 | accentOrange | — |
error | #C94545 | #FF8F8F | text-destructive | accentRed | error |
info | #2C6EE8 | #76A6FF | text-blue-600 dark:text-blue-400 | accentBlue | — |
accent-sky | #7DD3FC | #BAE6FD | text-sky-300 dark:text-sky-200 | accentSky | — |
mate-violet (gradient) | #8B5CF6 → #9333EA | same | from-violet-500 to-purple-600 | Gradients.mateViolet | — |
| Semantic containers † | |||||
success-container | #E8F6EE | #12301F | bg-success-container | successContainer | — |
success-on-container | #116B3E | #58D68D | text-success-on-container | onSuccessContainer | — |
warning-container | #FDF3E3 | #33230A | bg-warning-container | warningContainer | — |
warning-on-container | #8A5109 | #FFB257 | text-warning-on-container | onWarningContainer | — |
error-container | #FBEBEB | #331717 | bg-error-container | errorContainer | — |
error-on-container | #A93030 | #FF8F8F | text-error-on-container | onErrorContainer | — |
* navActiveBg / navActiveText are iOS-only tokens derived from brand-container / brand-on-container. Use them for active navigation state only.
† Semantic containers are the tinted-pill pair; the bare success/warning/error tone above is text-on-page only. A status pill is -container fill + -on-container for BOTH its label and its dot — one value does both jobs, so there is no third "indicator" color to keep in sync. Every on/container pair is ≥ 5.77:1 and every on-container against its own page surface is ≥ 6.44:1, so the pair satisfies the 4.5:1 text floor and the 3:1 non-text floor simultaneously, in both themes.
Do NOT use the bare warning tone as a dot, bar, or icon on a light surface — #F08F23 measures 2.43:1 against #FFFFFF, under the 3:1 non-text floor. It is legible as large/bold text and nothing else; the light-mode indicator color is warning-on-container. (success 4.72 and error 4.75 do pass, but use the on-container value anyway so all three behave alike.)
Health status maps onto this palette — it does not get its own colors. resolveHealthState returns ok | warn | danger; those render as success / warning / error containers. One palette, two vocabularies pointing at it — a third color trio is the fragmentation the "no rainbow accent system" rule exists to prevent.
Never for financial price movement. Korean market convention is red = up, blue = down; a finance surface that borrowed the green/red status palette would invert its own meaning.
* accent-sky exists for the weather icon condition map only (snow). mate-violet is the ONE Mate-identity violet on every platform (roster tiles, mate chat, recommend cards) — never restyle a Mate surface with brand-primary.
Rules
- Never hardcode a hex value in any view, component, or stylesheet. Reference the token.
- Never use opacity hacks like
brandPrimary.opacity(0.12)for container backgrounds — usebrand-containerdirectly. - Dark mode is not optional. Every token must have both light and dark values.
- The wordmark's yellow, green and red are accents, never surfaces. They colour one word or one mark to say which domain it belongs to (www /about's day lines: briefing blue, hub and pages green, series red, the time word yellow). Measured on the brand surface: 9.9:1, 5.6:1, 4.8:1. Never a background, never two of them in one sentence for decoration.
- A dark hero or panel uses
surface-brand, neverbg-prime.--primeis the TEXT token and flips to near-white in dark mode, so a hero painted with it turns white-on-white the moment the viewer's theme is dark. The brand surface is the one surface that does not follow the theme. - The brand surface's dot grid:
.brand-dotsis the still frame (no JS, reduced motion); the moving water is a canvas (BrandDotsCanvas, @yroun/ui; the about hero and the sign-in panel) whose numbers are named at the top of the file (wave period 3.4s, wavelength 290px, swell 7s/750px, flatten 1.6). Decorative,aria-hidden, paused off screen, one still frame underprefers-reduced-motion. The hero headline reveals terminal-style (.typewriter-box>.typewriter,--charsinline) with the text in the DOM for crawlers.
Live specimens
brand-primary
bg-yroun-bluebrand-container
bg-blue-50yroun-yellow
bg-yroun-yellowyroun-green
bg-yroun-greenyroun-red
bg-yroun-red
surface-page
bg-backgroundsurface-card
bg-surfacesurface-secondary
bg-mutedsurface-brand
brand-surface
text-prime Every screen has one clear focal point
text-muted-foreground Every screen has one clear focal point