Diagnostik styleguide
The token contract, component kit and accessibility rules behind both portals. Everything here is shipped code — the contrast table below measures the live theme.
Colour is expressed as intent, never as a raw value. Every token is a CSS custom property with a light and dark definition, so a theme flip needs no component changes.
Every pairing the product actually ships, measured in the browser against WCAG 2.x. This runs on the live theme — change a token and the verdict changes with it.
| Pairing | Sample | Ratio | Needs | Result |
|---|
Geist for interface, Geist Mono for micro-labels and figures, Instrument Serif for editorial moments in the report.
Instrument Serif — used sparingly, for report pull-quotes.
A 4px base grid, one radius token, and a single elevation step. Restraint here is what keeps two portals feeling like one product.
Cards use rounded-xl + shadow-sm; controls use rounded-lg. Deeper shadows are not part of the system.
Motion signals that the system is thinking — never decoration. Every animation is disabled under prefers-reduced-motion, which matters because Iris breathes and blinks.
Label, hint, and state are part of the primitive — not something each screen re-implements.
One traffic-light scale across both portals. Status colour never appears ad-hoc — always through these tokens, which is why they all clear AA.
Cards on background, and the permanently-dark navy stage used for the sidebar and the interview room. Dark surfaces re-point the focus ring at the lime accent so it stays visible.
The default container.
Secondary grouping.
Review queues, coverage and roadmap views all use this shape: scoped headers, hover rows, and status carried by pills rather than row colour.
| Item | Module | Status |
|---|---|---|
| Entity merge — “Impuls” / “IMPULS ERP” | AS-IS Map | pending |
| Maturity claim — Data foundations L2 | Maturity | approved |
| Map correction — “Requisition intake” | AS-IS Map | returned |
Numbers carry the argument in this product, so they get their own primitives.
Iris is the product's face. Her four states are the only animation users read as meaning, so they are part of the design system rather than a component detail.



sm · face chipWhat every interactive component must handle. If a screen shows only the default state, it is not finished.
| State | Signal | Where it must exist |
|---|---|---|
| Default | Token colours, no emphasis | Everything |
| Hover | Opacity or accent background | Buttons, rows, nav, chips |
| Focus | Ring from --ring, 2px offset | Every interactive element |
| Disabled | opacity-50/60 + not-allowed cursor | Buttons, inputs, gated actions |
| Invalid | destructive border + message | Form controls |
| Loading | Skeleton or pending label | Any async view or mutation |
| Empty | One sentence explaining what will appear | Lists, tables, queues, maps |
| Error | Amber panel + a way to continue | Anything that can fail — e.g. voice mode |
Nothing in the queue — findings appear here as Iris records them.
Voice unavailable — you can keep typing instead.
Target: WCAG 2.2 AA / EN 301 549, because EU enterprise procurement tests for it under the Accessibility Act.
- · Focus ring on every interactive element, ≥3:1 against its surface, via one base rule
- · All shipped token pairings clear AA — verified live in the table above
- · 44×44 minimum targets on touch devices
- ·
prefers-reduced-motionhonoured, including Iris - · Semantic tables with scoped headers and captions
- · Real dark theme, not an inverted filter
- · CJK / Thai font coverage — gated on an actual APAC tenant
- · Per-tenant white-label theming — gated on a deal that needs it
- · Dialog, toast and tooltip primitives — added when a flow first needs one
- · Published EN 301 549 conformance statement — after a full audit pass
- · 10px micro-labels kept by choice: they clear AA at 4.9:1 and never carry meaning alone