Highlighter — app design contract
Locked 2026-09-22 (direction D). Tokens live in src/index.css. Do not touch src/pages/LandingPage.tsx or src/components/landing/*.
World
A clipboard with one highlighter. Plain paper, black type, black buttons. A single yellow wash marks the thing you are on right now (nav item, selected row, focused field, text selection). Colour otherwise means status, and status is always a dot + a word.
No blue, purple, or green in chrome. No display/body pairing. No eyebrow/kicker above titles.
Tokens (read these)
| Role | Light | Dark | Use |
|---|---|---|---|
| canvas | #F6F6F4 | #16171A | page |
| surface | #FFFFFF | #1F2023 | panels, drawers, dialogs |
| ink | #17181A | #F2F2EF | text, primary buttons |
| ink2 / ink3 | #5F6368 / #9A9EA3 | muted | secondary / tertiary |
| highlight | #FFF3A3 | #4A4310 | current only |
| highlight-edge | #E8C800 | #F3D94A | focus ring, marker |
| rule | #E5E6E3 | #2C2D31 | hairlines |
Status: overdue #C62828 · due soon #C75B12 (never yellow) · scheduled hollow ink · in progress ink · done #8A8F94 · service grey · lab tan.
--os-brand is ink, not a colour. --os-highlight is the yellow wash. bg-os-brand/5 is wrong for “selected” — use bg-highlight / highlight-stroke.
Type
One family: Atkinson Hyperlegible Next (font-ui). Applied by data-app-shell on the layout root. Do not use font-heading or font-display in the app (those stay Space Grotesk for the landing page).
Titles: text-[26px] font-semibold tracking-[-0.01em]. Body text-sm. Labels text-[13px]. Captions text-[11px] — sentence case, not tracked all-caps unless it is a column header.
Shape
12px corners (--radius inside the app). Pills fully round. Controls 36px. List rows 56px. 8px grid.
Exception — field / tablet surfaces: on /field, /floor-plans, and the inspection wizard (/field/:inspectionId and its field-job tabs), every control is 44px minimum, not 36px. Page-local touch tabs / empty-state actions / descendant rules implement this; do not quietly shrink them back to 36px.
Components
- Buttons: primary = solid ink, white text. Secondary/outline = white + hairline. Ghost = text. Destructive = red text, never a red fill. No coloured fills.
- Sidebar: white. Current item = yellow wash (
bg-side-active-bg/highlight-stroke). No left green/ink bar. Avatar = ink disk, white initial. - Top bar: canvas, hairline, quiet.
- Lists: hairline rows, hover
bg-muted, selectedbg-highlight. Group header is a quiet label, not a black bar. - Tabs: current = solid ink pill, white text.
- Drawers: right sheet, white, soft shadow, header + scrolling body + footer. Banner at top in plain words (“Overdue by 4 days…”).
- Dialogs: centre, interrupt only when needed. Same paper + hairline + footer.
- Fields: 36px (44px on
/field,/floor-plans, and the inspection wizard — see Shape exception), hairline, yellow focus ring (ring-ring). - Links: ink + underline on hover. Never a green/brand colour.
Copy
Plain words. A screen answers “what needs doing, by when, what happens if not” before anything else. Controls name the action.
Landing page
Out of scope. Keep Space Grotesk / Inter / #00bf63 there. Do not change Button in a way that restyles landing CTAs beyond the existing dark primary (they already use the default ink button).
Do not
Change behaviour, routes, or data. Do not invent testimonials. Do not reintroduce eco green, Command green, or Space Grotesk in the app.