Accessibility
Verified WCAG 2.2 contrast, light on mm-paper unless stated: ink 17.6:1, ink-2 7.3:1 (6.8:1 on sunken), ink-3 5.2:1, burnt sienna 5.1:1 (4.7:1 on sunken), white on burnt sienna 5.2:1, white on hover 6.9:1, moss 5.2:1, slate 5.8:1, crimson 6.3:1, white on crimson 6.5:1, ochre text 5.5:1, control border 3.2:1. Ochre #a27825 (3.9:1) and contour (3.9:1) are for marks and large text only. Peat on mm-surface: text 15.1:1, text-2 7.1:1, text-3 4.5:1, burnt sienna text 7.6:1, white on the button fill 5.0:1, moss 7.7:1, ochre 7.9:1, slate 7.2:1, crimson 7.2:1, control border 3.6:1. In Peat mm-text-3 drops to 4.1:1 on mm-raised, so captions in popovers and dialogs use mm-text-2 there.
- Body text targets 7:1 (
mm-text,mm-text-2). Nothing that must be read falls below 4.5:1. mm-rule(1.3:1) is decorative only. Inputs and checkboxes usemm-control-border.- Focus is always visible through
:focus-visible; sticky headers never hide the focused element. - Interactive targets are at least 24×24px on desktop and 44×44px (
target-touch) on touch. - Never rely on colour alone. Status pills carry words. Run strips and lineage edges carry a pattern or icon too (failed runs show an ×, observed edges are dashed). Charts use direct labels. Destructive actions say what they destroy.
- Hover, active and focus states increase contrast, never reduce it.
- Respect
prefers-reduced-motionandprefers-color-scheme. Setcolor-schemeon the root and atheme-colormeta matchingmm-paper. - Mobile inputs are at least 16px so iOS does not zoom.
Keyboard
- Everything you can do with a mouse, you can do with a keyboard, in a sensible Tab order.
- Composite widgets (lists, tabs, segmented controls, grids, menus) are one Tab stop with arrow keys inside, following the WAI-ARIA Authoring Practices pattern for that widget.
- Escape closes the innermost popup, menu, drawer or dialog, and focus returns to what opened it.
- When something is added, focus moves to it (a new query condition focuses its first field). When something is removed, focus moves to the next item, or to the control that adds more.
- Enter in a search or filter box runs it. Keyboard-opened popups appear instantly, with no animation.
Screen readers
- Every control has a name: a visible label, or a hidden one when the design shows none. Hidden labels are specific ("Remove condition 2", not "Remove").
- Icons beside text are decorative and hidden. Icon-only buttons carry the name.
- Visual summaries have a text alternative: popularity bars read "Popularity: high", run strips "Last 7 runs of postgres-shop", charts offer their values.
- Changes that happen without a page load are announced politely: result counts, suggestion lists opening, items added or removed, copy confirmations.
- Nothing essential lives only in a tooltip or a
title. - Pages use landmarks (navigation, main) and headings in order, so people can jump between sections.
Checking
- Every interactive component has keyboard tests in its stories and passes axe with violations treated as errors.
- Before shipping a screen, use it with the keyboard alone, then with a screen reader (VoiceOver or NVDA): can you reach, understand and complete every task?