Color & Tokens
A sterile canvas, one action color, and alarm colors that mean the same thing everywhere. Tokens run primitives → semantic → component as CSS custom properties. Themes switch with data-theme, and a brand re-skins by overriding 8 tokens.
Token architecture
Every color, size and duration the system is allowed to use. Never referenced directly by components.
--scrub-600: #0A7A5F;
Intent-based aliases that change per theme. The 8 --brand-* tokens are the only layer a brand overrides.
--color-action:
var(--brand-action);
Scoped to a component and always pointing at semantic tokens, so themes cascade without touching component CSS.
--button-primary-bg:
var(--color-action);
Themes
The same components rendered from three token sets. Clinical Light is the default for public pages. OR Dark is a low-glare theme for the portal and in-room displays. Veyra Pulse shows brand theming: only the 8 --brand-* tokens change.
data-theme="light"data-theme="dark"data-brand="pulse"| BRAND TOKEN (8) | CLINICAL LIGHT | OR DARK | VEYRA PULSE |
|---|---|---|---|
| --brand-action | #0A7A5F | #52E0A8 | #3D4FD1 |
| --brand-action-hover | #086650 | #7BEBC0 | #2F3FB3 |
| --brand-action-fg | #FFFFFF | #0A1216 | #FFFFFF |
| --brand-glow | #52E0A8 | #52E0A8 | #9AA8FF |
| --brand-focus | #0A1216 | #52E0A8 | #0A1216 |
| --brand-selected | #0A7A5F | #52E0A8 | #3D4FD1 |
| --brand-link | #0A7A5F | #52E0A8 | #3D4FD1 |
| --brand-data-primary | #0A7A5F | #52E0A8 | #3D4FD1 |
Primitives
Status & alarm semantics
Priority colors follow clinical alarm conventions inspired by IEC 60601-1-8. Status never relies on color alone: every state pairs a distinct shape, a text label and color. Success uses Leaf, which is warmer and yellower than Scrub, so a confirmation never reads as a button.
Immediate response required: device fault, critical field safety notice, failed sterilization check.
Prompt response: calibration due, service ticket waiting, training expiring within 30 days.
Awareness only: software update available, live data indicator, scheduled maintenance.
Confirmation: form submitted, self-test passed, ticket resolved. Never used for CTAs.
Data visualization palette
Rules: at most 5 categories per chart before grouping into "Other". Direct labels are preferred over legends. Yellow (5) is used for fills only, never text or thin lines. Series also differ by marker shape or dash pattern.
Contrast
Ratios are calculated live from the token values (WCAG 2.2). Body text targets AAA (7:1). Secondary and UI text meet AA (4.5:1) at minimum.
| SAMPLE | PAIR | THEME | RATIO | RESULT |
|---|---|---|---|---|
| Aa | Body text#0A1216 on #F5F6F3 |
Light | 17.42:1 | AAA |
| Aa | Body text on surface#0A1216 on #FFFFFF |
Light | 18.90:1 | AAA |
| Aa | Secondary text#3A4449 on #F5F6F3 |
Light | 9.21:1 | AAA |
| Aa | Tertiary text#5C666B on #F5F6F3 |
Light | 5.43:1 | AA |
| Aa | Scrub link#0A7A5F on #F5F6F3 |
Light | 4.89:1 | AA |
| Aa | Primary button#FFFFFF on #0A7A5F |
Light | 5.30:1 | AA |
| Aa | Primary button hover#FFFFFF on #086650 |
Light | 6.94:1 | AA |
| Aa | High priority#B8261C on #FCEBE9 |
Light | 5.46:1 | AA |
| Aa | Medium priority#7A5200 on #FFF5D6 |
Light | 6.36:1 | AA |
| Aa | Info#0A6280 on #E4F4FA |
Light | 6.06:1 | AA |
| Aa | Success#3B6E17 on #EEF6E6 |
Light | 5.53:1 | AA |
| Aa | Pulse button#FFFFFF on #3D4FD1 |
Pulse | 6.49:1 | AA |
| Aa | Body text#E8ECEA on #0B1215 |
OR Dark | 15.85:1 | AAA |
| Aa | Secondary text#B4BEBB on #121B1F |
OR Dark | 9.17:1 | AAA |
| Aa | Tertiary text#9AA6A3 on #0B1215 |
OR Dark | 7.52:1 | AAA |
| Aa | Glow button#0A1216 on #52E0A8 |
OR Dark | 11.33:1 | AAA |
| Aa | Glow link#52E0A8 on #121B1F |
OR Dark | 10.47:1 | AAA |
| Aa | High priority#FF7A6E on #121B1F |
OR Dark | 6.87:1 | AA |
| Aa | Medium priority#FFD34D on #121B1F |
OR Dark | 12.21:1 | AAA |
| Aa | Info#6FD2EE on #121B1F |
OR Dark | 10.09:1 | AAA |
Color discipline
Implementation
<html data-theme="light"> <!-- or "dark" --> <body data-brand="pulse"> <!-- optional brand layer --> .button-primary { background: var(--button-primary-bg); /* → --color-action → --brand-action */ color: var(--button-primary-fg); border-radius: var(--button-radius); transition: background var(--dur-2) var(--ease-systole); } .button-primary:focus-visible { box-shadow: var(--focus-ring); }