Cards
Generated from data-products/tokens/aleris-tokens.css at build. The values,
the usage and constraint notes, and the contrast ratios are read and measured from that file —
there is no card text to keep in step, because there is no card text. Ratios are against the
three grounds a colour actually meets; a value clearing one can fail another.
Petrol
Structure and trust. Primary text, headings, navigation, dark surfaces.
--color-petrol-100#d9e1e2white 1.33:1sand-50 1.25:1sand-100 1.13:1Tinted backgrounds, selected row, inverted primary hover fillNever as text color--color-petrol-200#abc7c9white 1.79:1sand-50 1.69:1sand-100 1.52:1Tinted backgrounds a step down from petrol-100Never as text color – too light--color-petrol-300#7fa9aewhite 2.56:1sand-50 2.42:1sand-100 2.19:1Secondary accents, hover tintsNot for body text – too light. Never behind white text: 2.56:1--color-petrol-400#4f868ewhite 4.09:1sand-50 3.86:1sand-100 3.49:1Mid petrol for structure and accentsNot for body text--color-petrol-450#0f6b73white 6.23:1sand-50 5.88:1sand-100 5.31:1The far stop of --surface-gradient-cold, and the petrol to reach for on any petrol ground light text sits onMeasured 2026-09-13, all four light roles clear 1.4.3's 4.5:1 body floor on it: white 6.23:1, petrol-100 4.69:1, sand-50 5.88:1, sand-100 5.31:1. VALUE TAKEN FROM sundviktlakemedel, which minted this token under this exact name on 2026-09-02, eleven days before Brand OS did, and for the same reason — a ghost Button inside its WaitPanel rendered at 1.00:1 against the top-left of its own gradient panel, so five of seven seeded patients had an unreachable action on their home screen. Brand OS independently added the same name at #437d85 on 2026-09-13, chosen as minimum headroom over white alone and placed on the petrol-500 → petrol-400 interpolation so the gradient's appearance would not change. That criterion was too narrow: at #437d85 petrol-100 measures 3.51:1 and a secondary line fails, which the consumer's value had already solved. Torfinn ruled for the consumer's value on 2026-09-13. IT IS NOT ON THE INTERPOLATION LINE — it is a deeper, more saturated teal, 52/18/18 in RGB from #437d85 — so the gradient does look different, and that is the cost of the wider floor rather than an oversight.--color-petrol-500#004851white 10.27:1sand-50 9.69:1sand-100 8.75:1Primary text, headings, structural elementsDefault text color. Only specify when deviating--color-petrol-700#003238white 13.88:1sand-50 13.10:1sand-100 11.82:1Secondary/confirm button press fillInteraction only, never decorative or print. White text 13.88:1. Added 2026-08-05, card 19 – hover no longer needs a colour step (card 16, the hover/focus merge), so only the press step was needed, not the petrol-600 the design return also proposed
Orange
Action and warmth. The ramp splits by job: 100–500 are brand tints for print and digital, 600–700 are interaction fills that exist to hold contrast on screen.
--color-orange-100#fde8dfwhite 1.18:1sand-50 1.11:1sand-100 1.01:1--color-orange-200#fbd1c0white 1.40:1sand-50 1.32:1sand-100 1.19:1Soft tint, backgrounds and surfaces. Print and digitalDecorative/background only, not for interactive states--color-orange-300#ffbe9fwhite 1.60:1sand-50 1.51:1sand-100 1.36:1Light accent backgrounds, soft orange tintsDecorative/background only, not for interactive states--color-orange-400#faaa8dwhite 1.88:1sand-50 1.77:1sand-100 1.60:1Accent tint, backgrounds and surfaces. Print and digitalDecorative/background only, not for interactive states. Never an interactive state – this is the exact hex the retired primary hover pointed at--color-orange-500#f58c61white 2.38:1sand-50 2.25:1sand-100 2.03:1Accent, decorative, print. The brand orangeBrand use only. Never an interactive state or interactive fill – use orange-600/700--color-orange-600#d14811white 4.52:1sand-50 4.27:1sand-100 3.85:1Primary button fill, interactive orangeInteraction only, never decorative or print. White text 4.52:1. Never on a petrol surface--color-orange-700#b23c0ewhite 5.92:1sand-50 5.59:1sand-100 5.05:1Interaction hover and active fillInteraction only, never decorative or print. White text 5.92:1
Sand
The calm everything rests on. Page ground is sand, never white; cards are white, never sand.
--color-sand-50#faf8f6white 1.06:1sand-50 1.00:1sand-100 1.11:1Page background for instrumental surfacesTools, admin, dashboards only. Communicative uses sand-100--color-sand-100#f2ece4white 1.17:1sand-50 1.11:1sand-100 1.00:1Page background for communicative surfacesPatient-facing, marketing, booking. Never use white as page bg--color-sand-300#e7ceb5white 1.51:1sand-50 1.43:1sand-100 1.29:1--color-sand-500#d9b48fwhite 1.93:1sand-50 1.82:1sand-100 1.65:1
Warm neutrals
Even the greys lean brown, never blue.
--color-gray-100#d7d2cbwhite 1.50:1sand-50 1.42:1sand-100 1.28:1--color-gray-300#9e9281white 3.05:1sand-50 2.88:1sand-100 2.60:1--color-gray-500#585044white 7.94:1sand-50 7.49:1sand-100 6.76:1
Status
State communication only, never decoration.
--status-error#c14444white 5.03:1sand-50 4.74:1sand-100 4.28:1--status-warning#d9b48fwhite 1.93:1sand-50 1.82:1sand-100 1.65:1--status-confirm#4f866ewhite 4.23:1sand-50 3.99:1sand-100 3.60:1--status-info#007bc7white 4.51:1sand-50 4.26:1sand-100 3.84:1--status-background#ffffffwhite 1.00:1sand-50 1.06:1sand-100 1.17:1
Goal status
Dashboard KPI indicators, instrumental surfaces only. Always paired with an icon or shape — colour never carries a goal state alone.
--goal-achieved#2e8540white 4.62:1sand-50 4.36:1sand-100 3.94:1--goal-borderline#ffb81cwhite 1.73:1sand-50 1.63:1sand-100 1.48:1--goal-missed#d4351cwhite 4.86:1sand-50 4.58:1sand-100 4.14:1--goal-no-data#007bc7white 4.51:1sand-50 4.26:1sand-100 3.84:1
Chart palette
Deliberately distinct from the brand palette, so a data point is never mistaken for interactive UI.
--color-chart-01-teal#0f9081white 3.94:1sand-50 3.72:1sand-100 3.36:1--color-chart-02-mint#94cbc4white 1.81:1sand-50 1.71:1sand-100 1.54:1--color-chart-03-blue#577ba3white 4.41:1sand-50 4.16:1sand-100 3.75:1--color-chart-04-blue-light#98c9efwhite 1.76:1sand-50 1.66:1sand-100 1.50:1--color-chart-05-purple#a078c2white 3.52:1sand-50 3.33:1sand-100 3.00:1--color-chart-06-purple-light#d8b8efwhite 1.75:1sand-50 1.65:1sand-100 1.49:1--color-chart-07-terracotta#d77a61white 3.07:1sand-50 2.90:1sand-100 2.61:1--color-chart-08-terracotta-light#f0c3b2white 1.60:1sand-50 1.51:1sand-100 1.36:1--color-chart-09-marine#6b9495white 3.34:1sand-50 3.15:1sand-100 2.84:1--color-chart-10-olive#bed0c0white 1.62:1sand-50 1.53:1sand-100 1.38:1--color-chart-11-warm-grey#e4ded5white 1.34:1sand-50 1.26:1sand-100 1.14:1--color-chart-12-dark-sand#d9b48fwhite 1.93:1sand-50 1.82:1sand-100 1.65:1
Type scale
14px is the hard accessibility floor.
- Aa Bb Cc
--font-size-xs0.875rem - Aa Bb Cc
--font-size-sm1rem - Aa Bb Cc
--font-size-base1.125rem - Aa Bb Cc
--font-size-md1.375rem - Aa Bb Cc
--font-size-lg1.6875rem - Aa Bb Cc
--font-size-xl2.5rem - Aa Bb Cc
--font-size-2xl3.75rem
Weights
Museo Sans has two working weights. There is no 400 — declaring one causes browser synthesis and distorts the letterforms.
- Sentence case
--font-weight-light300Large display text on communicative surfacesExceptional use only. Size must be xl (40px) or above - Sentence case
--font-weight-regular500Body text, labels, buttons, UI chromeThe workhorse. Never use 400 — Museo Sans has no 400 weight - Sentence case
--font-weight-bold700Headings, emphasis, CTAsThe other workhorse. 500 and 700 are the system - Sentence case
--font-weight-black900Almost neverExceptional use only. Try 700 at larger size first
Spacing
A 1.5 modular scale on a 4px grid.
--spacing-00pxZero gap, collapsed stateUse explicitly — don't omit spacing, set it to 0--spacing-3xs4pxMinimum gap, icon padding, label-to-fieldSmallest usable gap. Never go below this--spacing-2xs8pxTight element spacing, inline gapsRelated inline elements--spacing-xs12pxRelated element spacing, input padding-yDefault vertical rhythm within components--spacing-sm16pxDefault component padding, grid margin mobileMost common padding value--spacing-md24pxSection spacing within components, card paddingPrimary structural spacing--spacing-lg36pxBetween components, above h2Component-level separation--spacing-xl48pxBetween sectionsSection-level separation--spacing-2xl72pxMajor section breaksCommunicative surfaces mainly--spacing-3xl96pxPage-level spacingCommunicative surfaces only. Never on instrumental--spacing-page-padding16px--spacing-card-padding24px--spacing-section-gap24px--spacing-element-gap12px--spacing-label-gap4px
Radius by role
Radius is chosen by role, not by size.
--radius-00pxSharp corners, full-bleed edgesExplicit removal of rounding--radius-s4pxGeneral containers: panels, modals, tablesGeneral container tier. Cards use --radius-l instead. Not for buttons or inputs--radius-l16pxCards onlyCard tier, decided 2026-08-10 (board card 45) from a live production measurement. Not a general container value--radius-m8pxInteractive: buttons, inputs, dropdownsInteractive element tier. Not for containers--radius-full100pxCompact indicators: badges, tags, avatarsIndicator tier only. No full-pill buttons exist in Aleris
Elevation
Petrol-tinted, never neutral black. Two-part and directional since 2026-09-17: a soft light source at the top right, so every shadow drifts down and to the left.
--shadow-e00px 0px 0px rgba(0, 72, 81, 0)--shadow-e1-1px 1px 2px rgba(0, 72, 81, 0.04), -1px 2px 8px rgba(0, 72, 81, 0.06)--shadow-e2-2px 2px 4px rgba(0, 72, 81, 0.06), -3px 8px 24px rgba(0, 72, 81, 0.1)--shadow-e3-3px 8px 16px rgba(0, 72, 81, 0.08), -6px 24px 48px rgba(0, 72, 81, 0.16)--elevation-flat0px 0px 0px rgba(0, 72, 81, 0)--elevation-card-1px 1px 2px rgba(0, 72, 81, 0.04), -1px 2px 8px rgba(0, 72, 81, 0.06)--elevation-dropdown-2px 2px 4px rgba(0, 72, 81, 0.06), -3px 8px 24px rgba(0, 72, 81, 0.1)--elevation-modal-3px 8px 16px rgba(0, 72, 81, 0.08), -6px 24px 48px rgba(0, 72, 81, 0.16)
Focus, hover and press
Focus is a dual ring and both halves are always drawn. Hover draws the outer ring only and never a fill change.
--state-focus-ring#004851--state-focus-ring-inner#ffffff--state-focus-ring-width2px--state-focus-ring-shadow0 0 0 2px #ffffff, 0 0 0 calc(2px * 2) #004851--state-focus-ring-shadow-inverse0 0 0 2px #004851, 0 0 0 calc(2px * 2) #ffffff--state-hover-ring-shadow-primary0 0 0 2px #b23c0e--state-hover-ring-shadow-secondary0 0 0 2px #004851--state-press-shadergba(0, 0, 0, 0.4)--state-press-translate-y1px--state-disabled-bg#d7d2cb--state-disabled-text#9e9281
Motion
Only transform and opacity animate. ease-out arrives, ease-in-out moves; ease-in alone is never used, because a slow start reads as unresponsive.
--duration-instant100ms--duration-fast200ms--duration-moderate350ms--duration-slow500ms--ease-outcubic-bezier(0.0, 0.0, 0.2, 1)--ease-in-outcubic-bezier(0.4, 0.0, 0.2, 1)