Foundations
Color
Neutral grays for the page, one red for the brand and the main action, and eight division colors that appear only in network graphics.
Concept
- Station architecture is white and cool concrete (
beton). - Signage ink is near-black, with a hint of blue.
- One signal red (
merah) is the PPITSZ line and the call to action. - Eight line colors identify divisions, and appear only in network graphics.
- Status colors are green and amber, used for states only.
Real transit systems keep their architecture neutral so line colors read at a glance. The site does the same. merah-500 (#F5392C) is warmer and brighter than the logo's crimson (#ED1C24), but close enough to read as the same brand.
Ramps
Implemented in OKLCH, all inside sRGB; hex values are for reference. Components never use ramps directly; they use the semantic tokens below.
merah
- 50#FDF2F0oklch(0.97 0.012 29)
- 100#FDE3DEoklch(0.935 0.03 29)
- 200#FCCCC5oklch(0.885 0.055 29)
- 300#FBA89Coklch(0.81 0.1 29)
- 400#FD7464oklch(0.72 0.17 29)
- 500#F5392Coklch(0.635 0.225 29)
- 600#D61E17oklch(0.56 0.215 29)
- 700#AC1B14oklch(0.48 0.18 29)
- 800#841711oklch(0.4 0.145 29)
- 900#5F120Doklch(0.32 0.11 29)
- 950#3C0C08oklch(0.24 0.075 29)
beton
- 50#F8F9FBoklch(0.982 0.003 255)
- 100#F0F3F6oklch(0.962 0.005 255)
- 200#E3E6EBoklch(0.925 0.007 255)
- 300#D0D5DAoklch(0.87 0.009 255)
- 400#A6ABB2oklch(0.74 0.012 255)
- 500#7E848Boklch(0.61 0.013 255)
- 600#61676Eoklch(0.51 0.014 255)
- 700#484E55oklch(0.42 0.014 255)
- 800#2E333Aoklch(0.32 0.013 255)
- 900#1B1E23oklch(0.235 0.011 255)
- 950#0D1013oklch(0.17 0.009 255)
hijau (status only)
- 50
- 300
- 600
- 700
- 950
amber (status only)
- 50
- 300
- 600
- 800
- 950
Semantic tokens
Components use these and never the ramps. Dark mode, nested previews and the tone-ink scope work by re-assigning them, so components need no dark: classes. The swatches below are live: switch the theme to see them change.
| Token | Live | Light | Dark | Use |
|---|---|---|---|---|
bg | white | beton-950 | Page | |
surface | beton-50 | beton-900 | Panels, image placeholders, skeletons | |
surface-strong | beton-100 | beton-800 | Hover fills, pressed rows | |
surface-raised | white | beton-800 | Inputs, dialogs, popovers, toasts | |
text | beton-950 | beton-50 | Body text and headings | |
muted | beton-600 | beton-400 | Secondary text, metadata, placeholders | |
subtle | beton-500 | beton-500 | Disabled text only | |
border | beton-200 | beton-800 | Dividers (decorative) | |
border-strong | beton-500 | beton-500 | Control boundaries (≥ 3:1) | |
accent | merah-600 | merah-600 | Primary button fill | |
accent-hover | merah-700 | merah-700 | Primary hover | |
accent-active | merah-800 | merah-800 | Primary pressed | |
accent-fg | white | white | Text on accent | |
accent-text | merah-700 | merah-300 | Links, kickers, current-page markers | |
accent-subtle | merah-50 | merah-950 | Selected rows | |
accent-line | merah-500 | merah-500 | The brand line (the default --line) | |
focus | beton-950 | beton-50 | Focus outline | |
highlight | amber-300 | amber-300 | <mark>, ::selection, “New” | |
success | hijau-600 | hijau-300 | Success icons and edges | |
success-text | hijau-700 | hijau-300 | Success text | |
success-subtle | hijau-50 | hijau-950 | Success fills | |
warning | amber-600 | amber-300 | Warning icons and edges | |
warning-text | amber-800 | amber-300 | Warning text | |
warning-subtle | amber-50 | amber-950 | Warning fills | |
danger | merah-600 | merah-400 | Errors, destructive edges | |
danger-text | merah-700 | merah-300 | Error text | |
danger-subtle | merah-50 | merah-950 | Error fills | |
backdrop | beton-950 / 50% | beton-950 / 72% | Dialog backdrop |
Show codeHide code
<Button variant="primary">Register</Button>
<Button>See schedule</Button>
<StatusBadge domain="event" value="registration_open" />
<a className="text-accent-text underline">Tautan</a>Division lines
Each division owns one line color permanently, keyed by its code. Colors appear only in line badges, route lines and station markers, not as text, backgrounds or buttons. Set a division with data-line="humas" on any element; network graphics inside it use that line through --line.
In light mode every line sits at the same lightness (L ≈ 0.52–0.56) and carries white badge text; in dark mode at L ≈ 0.70–0.76 with dark text. Equal lightness means no division looks more important than another. BPH shares the brand red: the core board is the main line. A ninth division takes the unused hue nearest 320.
Light
- BPHBadan Pengurus Harian#D61E17
- DANUSDana Usaha#AD5C15
- DEPOLDepartemen Olahraga#287F3D
- HUMASHubungan Masyarakat#116BB5
- ITInformasi Teknologi#037A84
- MEDKREFMedia Kreatif#BC2B74
- PKAPerkembangan Karir dan Akademik#6A53BD
- SOSBUDSosial Budaya#922FA1
Dark / tone-ink
- BPHBadan Pengurus Harian#F66E5E
- DANUSDana Usaha#E6964F
- DEPOLDepartemen Olahraga#63BF74
- HUMASHubungan Masyarakat#67AAED
- ITInformasi Teknologi#50BDC9
- MEDKREFMedia Kreatif#EC79A9
- PKAPerkembangan Karir dan Akademik#A497EA
- SOSBUDSosial Budaya#D082DC
Station screen
Add tone-ink to a section to render it as a dark station screen inside a light page, as the home page does with the departure board and the network map. Every token inside switches to its dark value, line and status colors included. In dark mode it lifts one step to beton-900 so it still reads as a panel. At most two per page, never adjacent.
Upcoming events
Shenzhen Cup 2026
Contrast
WCAG 2.2 AA, computed from the values above. Text reaches 4.5:1; control boundaries and graphics reach 3:1.
| Pair | Light | Dark |
|---|---|---|
| text on bg / surface / surface-raised | 19.12 / 18.15 / 19.12 | 18.15 / 15.83 / 12.04 |
| muted on bg / surface / surface-strong | 5.74 / 5.45 / 5.14 | 8.29 / 7.23 / 5.50 |
| border-strong on bg / surface | 3.79 / 3.60 | 5.05 / 4.40 |
| accent-fg on accent / hover / active | 5.19 / 7.17 / 9.90 | 5.19 / 7.17 / 9.90 |
| accent-text on bg / surface / accent-subtle | 7.17 / 6.81 / 6.55 | 10.20 / 8.89 / 8.98 |
| accent-line (graphic) on bg / surface | 3.82 / 3.62 | 5.01 / 4.37 |
| success-text on bg / subtle | 7.08 / 6.54 | 10.71 / 9.08 |
| warning-text on bg / subtle | 7.36 / 6.85 | 11.97 / 9.84 |
| danger-text on bg / subtle | 7.17 / 6.55 | 10.20 / 8.98 |
| highlight-fg on highlight | 11.97 | 11.97 |
| Line | Light: badge text / on bg / on surface | Dark: badge text / on bg / on surface / on surface-strong |
|---|---|---|
| bph | 5.19 / 5.19 / 4.92 | 6.65 / 6.65 / 5.80 / 4.41 |
| danus | 4.86 / 4.86 / 4.62 | 8.03 / 8.03 / 7.00 / 5.32 |
| depol | 4.98 / 4.98 / 4.73 | 8.44 / 8.44 / 7.36 / 5.60 |
| humas | 5.51 / 5.51 / 5.23 | 7.75 / 7.75 / 6.76 / 5.14 |
| it | 5.07 / 5.07 / 4.82 | 8.61 / 8.61 / 7.50 / 5.71 |
| medkref | 5.63 / 5.63 / 5.35 | 7.17 / 7.17 / 6.25 / 4.75 |
| pka | 5.87 / 5.87 / 5.57 | 7.46 / 7.46 / 6.50 / 4.94 |
| sosbud | 6.67 / 6.67 / 6.33 | 7.21 / 7.21 / 6.29 / 4.78 |
Rules
Don’t
Several red buttons, red headings or red section backgrounds.
Do
One primary button per screen. Red is the brand line, the current-page marker and links.
Don’t
text-line-humas headings, a HUMAS-blue section, division-colored buttons.
Do
Line colors only on line-badge, route and station. Everything else stays neutral.
Don’t
bg-red-600, text-gray-500, bg-merah-600, text-[#D61E17].
Do
bg-accent, text-muted, text-accent-text. Only semantic tokens survive dark mode and tone-ink.
Don’t
A colored dot alone to show a division or a status.
Do
Pair color with the code (HUMAS) or words (“Registration open”). Roughly 5–8% of men have some color-vision deficiency.
Danger shares the red family, so an error always comes with an icon and a message, and a destructive button is an outlined tint, never a solid red fill. No gradients, transparent text or tinted photos.

