Foundations

Colour

Three ramps carry the brand, five fixed hues carry clinical meaning, and the two groups are never allowed to be confused with one another.

Stable · v1.0 IEC 60601-1-8 WCAG 2.2 AA

Overview

Colour in a clinical interface does two jobs that pull in opposite directions. It expresses a brand, and it encodes safety-critical state. When those two jobs share a hue, the brand wins by accident and the safety signal degrades.

This system separates them explicitly. Brand colour — teal, coral, warm neutral — is free to be expressive and may be re-themed. Alarm colour — the five fixed hues below — is a controlled characteristic, fixed by standard, and must not be re-themed by any product, theme or customer skin.

Meaningful

Every colour in the product palette has one job. If a hue means "urgent" in one screen it cannot mean "selected" in another.

Never alone

Colour is always a second channel. Any state encoded chromatically is also encoded in text, shape or position, so the interface survives greyscale and colour-vision deficiency.

Environment-proof

The palette is validated in both a bright ward and a darkened reading room. Contrast is measured, not judged by eye on a designer's calibrated monitor.

Brand ramps

Three primitive ramps. These are raw values — components never consume them directly, they consume the semantic tokens further down.

Teal — the brand spine

Steps 500–900 are the exact anchors from md.notjustany.tech. Steps 50–400 are derived from the same hue for tints and dark-theme use.

50F1F6F6
100DCEDEA
200B7DED8
3007FCFC3
4003BC4AF
5002A8B7C
6001D6E62
70016504A
8000F3B35
9000B2A26

Coral — brand accent

Step 500 is the brand coral. See Why coral is banned in product before using any of this ramp inside an application.

50F8F1EF
100F1DEDA
200EABEB3
300E39582
400DF755B
500D8593A
600C04426
700A03920
800792D1B
900522014

Warm neutral

50F8F9F9
100EFF0F0
200DDDFDE
300C1C3C2
4009CA09F
500797E7C
6005E6260
700484C4B
800333635
9001F2120

Plus three warm paper surfaces carried over from the brand: --njt-paper #FFFDF9, --njt-cream #F6F1E7, --njt-cream-card #FBF7EE.

Alarm colour is not brand colour

IEC 60601-1-8 assigns meaning to three specific hues for alarm priority. They are not suggestions and not a starting point for a palette — they are the reason a clinician trained on one device can read another.

TokenHuePriorityForegroundContrast
--alarm-critical #CE0E2D red IEC high — immediate responseWhite5.64:1 AA
--alarm-urgent #F2C200 yellow IEC medium — prompt responseBlack12.49:1 AAA
--alarm-advisory #4FB3D9 cyan IEC low — awarenessBlack8.78:1 AAA
--alarm-info #B3BEB9 warm grey Not an alarm — state changeBlack10.98:1 AAA
--alarm-ok #1D6E62 teal-600 Not an alarm — action succeededWhite6.07:1 AA
Controlled characteristic

The three IEC hues must not be re-themed by a product, a customer skin, a dark mode or an accessibility preference. They are identical in both themes by design. Changing them is a design change with safety consequence and requires re-validation, not a token override.

Two consequences that designers reliably want to "fix" and must not:

Why coral is banned in product

The brand coral #D8593A is not permitted anywhere inside a clinical product interface. At distance, in peripheral vision, under warm ward lighting, or for a user with a red–green deficiency, it is not reliably distinguishable from the IEC high-priority alarm red #CE0E2D.

The problem, at size
brand coral
#D8593A
IEC alarm red
#CE0E2D

Adjacent and at full saturation they are separable. Across a room, on a 3 m wall display, or as a 24 px button beside a banner, they are not.

So the split is:

The brand still reads as itself in-product through teal, the warm paper surfaces, Fraunces in headings and a dark theme built on teal-900. It gives up one accent colour in the one place where colour carries clinical meaning.

Note on the marketing site

Coral #D8593A on cream measures 3.45:1, which is below AA for the small uppercase eyebrow text it currently sets on md.notjustany.tech. This system uses --njt-coral-700 #A03920 (6.58:1) for small coral text and reserves #D8593A for rules and accent bars, which carry no contrast requirement.

Semantic tokens

What components actually consume. These follow the shadcn/ui contract exactly, so any shadcn block or third-party example drops in unmodified.

Semantic surface & text tokens
--backgroundApp canvas #FDFCF8 / #0B2A26
--cardRaised surface #FFFFFF / #0F3B35
--foregroundBody text #16231F / #F6F1E7
--muted-foregroundSecondary text #54635E / #A8BDB6
--primaryPrimary action #0F3B35 / #3BC4AF
--borderDividers, input edges #DEE4DF / #1E4A43
--ringFocus ring #2A8B7C / #3BC4AF
--destructiveDestructive action — not an alarm #CE0E2D / #D93650
destructive ≠ alarm

--destructive means "this button deletes something." It shares a hue with --alarm-critical because both are red, but they are different tokens with different jobs and must never be substituted for one another. A destructive button is a control; an alarm is a signal about the patient.

The two themes

Light is the ward default. Dark is not a preference — it is the required mode for darkened reading rooms, and it is built on the brand's own teal-900 rather than a neutral black so the product still reads as NotJustAnyMed.Tech at 2 a.m.

TokenLightDarkNote
--background#FDFCF8#0B2A26 Warm white reduces glare versus pure #FFF.
--foreground#16231F#F6F1E7 13.58:1 on the dark canvas.
--primary#0F3B35#3BC4AF Lifted to teal-400 in dark to clear AA against its foreground.
--muted-foreground#54635E#A8BDB6 7.73:1 on canvas, 6.26:1 on card.
--alarm-*identical Deliberately unchanged. The standard's hues are absolute.

Theming mechanism

// Standard shadcn — a class on the root element.
<html className={theme === "dark" ? "dark" : undefined}>

// Theme must be a user-controlled setting, never automatic from ambient
// light or time of day: an unexpected theme flip mid-procedure is a hazard.

Do's and don'ts

Do
hs-troponin rising — NSTEMI cannot be excluded
14 → 47 ng/L across the 0/1 h interval.

Yellow with black text, and the word "cannot be excluded" carrying the same meaning independently of the colour.

Don't
hs-troponin rising
14 → 47 ng/L across the 0/1 h interval.

White on yellow measures 1.68:1. Unreadable, and the title no longer says what the finding means.

Do

Teal primary. Distinct from every alarm hue at any size or distance.

Don't

Brand coral as a primary action. Reads as an alarm, and competes with the real one when both are on screen.

Data visualisation

Charts get their own categorical ramp, drawn from the brand rather than the alarm hues, so a trend line can never be mistaken for a priority signal.

More do's and don'ts

Do
! Critical ▲ Urgent i Advisory

Hue, glyph and word together. Remove any two and the priority still arrives.

Don't

A legend of coloured dots. Nothing survives greyscale print, forced-colours mode, or a colour-vision deficiency.

Do
hs-troponin rising
dark theme · #F2C200, unchanged

The alarm hue is identical in both themes. A clinician moving from a bright bay to a reading room sees the same signal.

Don't
hs-troponin rising
dark theme · “softened” amber

Amber muted so the dark theme looks calmer. It is now neither the IEC hue nor recognisable as medium priority.

Clinical safety notes

Risk controls carried by this foundation

Trace these in your risk file (ISO 14971). Each is a mitigation, not a preference.

NotJustAnyMed.Tech Design System · Colour · v1.0 · draft for review