Skip to main content

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)

RoleLightDarkUse
canvas#F6F6F4#16171Apage
surface#FFFFFF#1F2023panels, drawers, dialogs
ink#17181A#F2F2EFtext, primary buttons
ink2 / ink3#5F6368 / #9A9EA3mutedsecondary / tertiary
highlight#FFF3A3#4A4310current only
highlight-edge#E8C800#F3D94Afocus ring, marker
rule#E5E6E3#2C2D31hairlines

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, selected bg-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.