OPERATOR

Color

Bone is OPERATOR's only theme, and it is dark. It declares color-scheme: dark, so scrollbars, select popups, and form controls follow the page. pnpm verify:contrast measures the contrast and separation figures on this page, and the token tests recompute every ratio quoted here.

Surfaces

Keep surfaces achromatic so UI chrome cannot resemble affiliation fills. Most content sits on bg to surface-3. Surfaces 4 to 6 raise panels and overlays, and carry fewer text colors.

TOKENVALUEUSAGESWATCH
--oprt-bg#0A0A0AApplication background
--oprt-surface-1#101010Cards, sidebar
--oprt-surface-2#161616Elevated surfaces, inputs
--oprt-surface-3#1C1C1CHover, active surfaces
--oprt-surface-4#222222Raised panels
--oprt-surface-5#282828Overlays on panels
--oprt-surface-6#2E2E2EHighest elevation
--oprt-border-subtle#1E1E1EHairline separators
--oprt-border#252525Layout lines: tables, tabs, cards, dividers, panels
--oprt-border-strong#333333Emphasized layout lines
--oprt-border-control#6B6B6BControl outline — the boundary of anything you click or type into (text fields, selects, checkboxes, radios, toggles, segmented and disabled buttons); 3:1 non-text contrast

Control outline

--oprt-border is for layout lines: tables, tabs, cards, dividers, and panels. It is deliberately quiet, and it is not a control boundary. The boundary of anything you click or type into uses --oprt-border-control (border-oprt-border-control in Tailwind), which keeps 3:1 non-text contrast (WCAG 1.4.11) against the surface the control sits on. pnpm verify:contrast checks it on bg to surface-3.

Surface--oprt-border-control
bg3.72
surface-13.57
surface-23.40
surface-33.20

Text

TOKENVALUEUSAGESWATCH
--oprt-text#E0E0E0Primary text — 15.00:1 on bg (AAA)
--oprt-text-dim#8A8A8ASecondary text — 5.73:1 on bg; allowed on fewer surfaces, see below
--oprt-text-muted#444444Decorative only — 2.03:1 on bg. Never text a reader needs, including placeholders and disabled labels

Where text may go

Text needs 4.5:1 against what it sits on (WCAG 1.4.3). This is the allowed-text matrix, and pnpm verify:contrast requires every cell to pass; a test fails when a cell passes but is missing, so the matrix is exactly what the tokens measure. A state layer is a translucent token, so its contrast is measured with the layer composited over the surface beneath it. The hover, active, and selected tokens are state layers, and so are the two accent washes.

Text colorAllowed on surfacesAllowed on state layers
--oprt-textAllAll
--oprt-text-dimbg to surface-4Hover: bg to surface-2. Active: bg. Selected: none. Accent-ghost: bg to surface-1. Accent-bg: bg to surface-2.
--oprt-accentAllAll
--oprt-accent-hoverAllAll
--oprt-accent-activeAllAll
--oprt-successAllAll
--oprt-warningAllAll
--oprt-errorbg to surface-3Hover: bg to surface-1. Active: bg. Selected: none. Accent-ghost: bg to surface-1. Accent-bg: bg to surface-2.
--oprt-infoAllAll

--oprt-accent, --oprt-accent-hover, --oprt-accent-active, --oprt-success, --oprt-warning, and --oprt-info measure at least 5.44:1 on every surface. Where a color is not allowed, use --oprt-text. "All" on a state layer means over bg to surface-3.

Contrast on each surface

Surface--oprt-text--oprt-text-dim--oprt-error
bg15.005.735.59
surface-114.415.515.37
surface-213.715.245.11
surface-312.914.944.81
surface-412.054.614.49 fail
surface-511.174.27 fail4.16 fail
surface-610.293.93 fail3.83 fail

A cell marked fail is below 4.5:1. Secondary text and error text lose contrast as surfaces rise, which is why they stop where the matrix says they stop.

Contrast on state layers

Layer over surface--oprt-text--oprt-text-dim--oprt-error
hover over bg13.715.245.11
hover over surface-112.914.944.81
hover over surface-212.054.614.49 fail
hover over surface-311.324.33 fail4.22 fail
active over bg12.344.724.60
active over surface-111.464.38 fail4.27 fail
active over surface-210.734.10 fail4.00 fail
active over surface-310.003.82 fail3.72 fail
selected over bg11.474.39 fail4.27 fail
selected over surface-110.744.11 fail4.00 fail
selected over surface-29.983.82 fail3.72 fail
selected over surface-39.273.55 fail3.45 fail
accent-ghost over bg13.195.054.92
accent-ghost over surface-112.464.764.64
accent-ghost over surface-211.624.44 fail4.33 fail
accent-ghost over surface-310.844.15 fail4.04 fail
accent-bg over bg13.725.255.11
accent-bg over surface-112.924.944.81
accent-bg over surface-212.204.664.54
accent-bg over surface-311.334.33 fail4.22 fail

Layers lighten the surface beneath them, so secondary text and error text lose contrast on them. Put --oprt-text on a selected row. --oprt-accent-ghost and --oprt-accent-bg are state layers too: they are the quiet hover and selection washes, and where secondary or error text fails on them it measures between 4.04:1 and 4.44:1. Accent, success, warning, and info text clear 4.5:1 on every layer over bg to surface-3.

Accent

TOKENVALUEUSAGESWATCH
--oprt-accent#D4D0C8Primary interactive — 12.87:1 on bg (AAA)
--oprt-accent-light#EAE8E4Highlights, button borders
--oprt-accent-hover#C0BCB4Hover
--oprt-accent-active#AAA69EActive / pressed
--oprt-accent-ghostrgba(212, 208, 200, 0.08)Quiet hover and selection wash — 8% accent
--oprt-accent-bgrgba(212, 208, 200, 0.06)Subtle accent fill — 6% accent
--oprt-accent-borderrgba(212, 208, 200, 0.25)Accent-tinted border — 25% accent

Semantic

Use -subtle for background washes, the base for text and borders, and the darker -strong fill with --oprt-text. Pair every semantic color with a non-color indicator (WCAG 1.4.1).

TOKENVALUEUSAGESWATCH
--oprt-success-subtle#0F1E17Active, online, healthy — background wash
--oprt-success#7DBEA0Active, online, healthy
--oprt-success-strong#216F51Active, online, healthy — solid fill
--oprt-warning-subtle#1F190DDegraded, threshold exceeded — background wash
--oprt-warning#D4A844Degraded, threshold exceeded
--oprt-warning-strong#7D5D13Degraded, threshold exceeded — solid fill
--oprt-error-subtle#241614Failed, offline, critical — background wash
--oprt-error#D86464Failed, offline, critical
--oprt-error-strong#9B4A44Failed, offline, critical — solid fill
--oprt-info-subtle#111B25Informational, neutral — background wash
--oprt-info#88A8C0Informational, neutral
--oprt-info-strong#1B4975Informational, neutral — solid fill

Categorical

For charts and legends, use the first three colors first: their minimum separation is 28.6 CIEDE2000. Always include non-color cues such as dashes or markers, especially for series 5–8. Red and pink are reserved for error and 2525 hostile.

TOKENVALUEUSAGESWATCH
--oprt-cat-1#B87347Series 1
--oprt-cat-2#B1BDDCSeries 2
--oprt-cat-3#E8D4A5Series 3
--oprt-cat-4#599795Series 4
--oprt-cat-5#9F72B1Series 5
--oprt-cat-6#98A887Series 6
--oprt-cat-7#BFE5D5Series 7
--oprt-cat-8#A79BDDSeries 8

Sequential and chart roles

Ordered magnitudes rise in lightness and keep 3:1 on the chart surfaces, bg to surface-3. Numeric labels on a step use --oprt-bg at 4.5:1. Axis labels, grids, and thresholds inherit foundation tokens rather than carrying a palette of their own; see Data visualization.

TOKENVALUEUSAGESWATCH
--oprt-data-seq-1#808080Lowest magnitude
--oprt-data-seq-2#999999Low magnitude
--oprt-data-seq-3#B0B0B0Middle magnitude
--oprt-data-seq-4#C8C8C8High magnitude
--oprt-data-seq-5#E0E0E0Highest magnitude
--oprt-chart-gridvar(--oprt-border-strong)Decorative grid lines
--oprt-chart-axisvar(--oprt-text-dim)Axis labels and ticks
--oprt-chart-thresholdvar(--oprt-warning)A labeled, application-supplied reference

Interaction states

State tokens are translucent layers, so the surface beneath shows through and text contrast depends on both: see the matrix above. Prefer them over per-component opacity values, and check the composite before placing secondary text on one.

TOKENVALUEUSAGESWATCH
--oprt-surface-hoverrgba(255, 255, 255, 0.05)Hover over any surface
--oprt-surface-activergba(255, 255, 255, 0.09)Pressed / active
--oprt-surface-selectedrgba(212, 208, 200, 0.14)Selected row or item
--oprt-overlay-scrimrgba(10, 10, 10, 0.72)Modal and drawer scrim

Using the colors in Tailwind

Every token above is a Tailwind color through @operator-ds/tailwind: bg-oprt-surface-2, text-oprt-text-dim, border-oprt-border-control. Opacity modifiers work (bg-oprt-bg/80) and compile to color-mix(), because Tailwind 3 cannot split a var() into channels.

Separation from map symbology

UI colors must remain distinguishable from the saturated MIL-STD-2525 fills in @operator-ds/tokens-operational. The target is 13 CIEDE2000 from all fifteen affiliation values, and pnpm verify:contrast measures it for every Bone color. Two existing exceptions rely on low chroma: --oprt-error (9.8 from hostile-light) and --oprt-info (11.5 from friendly). Their floors are pinned, so they cannot move closer. Never increase their chroma.

Keep -strong fills darker than their base. Lightening error to a mid-light fill reduces its hostile-light margin to 6.1 and risks resembling map affiliation.

On this page