Design System · Application & governance

Application

How the system is applied and kept clean — accessibility, the cleanup strategy, governance for the registry, and the open decisions. A catch-all for governance material that doesn’t belong to a single primitive; prune items here as they resolve.

01

Accessibility & usability

A rep uses this all day, sometimes on a mediocre shop monitor. These aren't compliance checkboxes — they're what keeps the tool fast and unambiguous.

Contrast

  • Body text on surface clears AA (ink-900/ink-700 ≥ 7:1). Ink-500 metadata stays ≥ 4.5:1 — never lighter for primary content.
  • The primary button is white text on ink-900 black (~16:1) — far clearer than any orange fill, which is why orange was retired from buttons.
  • Status tints are backgrounds only; the text carries the accessible contrast.

Status is never color-only

  • Every pill = tint + dot + word. Every checklist mark = color + glyph.
  • Platform tiles read in grayscale: the letter is the platform, the dot position + tooltip carry state.

Focus & keyboard

  • Visible focus everywhere: 2px brand ring (buttons) / brand border + tint ring (inputs). Never outline:none without a replacement.
  • Tab order follows reading order. The intake composer is reachable and submittable by keyboard (⌘/Ctrl+Enter).
  • Tabs are real links/roles with aria-current="page"; search is a labelled field; lists are navigable.

Avoiding ambiguous chips

  • Reserve the plain (dot-less) chip for counts/tags so it never reads as a status.
  • “Manual” amber is distinct from “draft” grey — a desk task is an action, not a neutral state.
  • Never reuse a status color for a module accent (module hues are deliberately teal/violet/magenta).
02

Cleanup strategy

What to lock now, what to keep loose, and how to stop the product from sprouting one-off tokens and near-duplicate components.

DecisionWhenRationale
Status language & colors (the 4 states)NowRepeated on every surface. Pick the words and the four tokens once; ban ad-hoc statuses.
Platform indicator (letter tile + dot)NowAppears on cards, details, intake, feed. One component, four instances — no per-platform variants.
Field row + card primitivesNowDetail pages are just stacks of these. Lock the row grid and card so new modules inherit them.
Type ramp & spacing scaleNowCheap to set, expensive to retrofit. Enforce the sizes / 4px scale before more screens exist.
Module accents (which hue, where used)SoonKeep the hues fixed but stay flexible on how much they show until Updates/Translation feel right.
Brand orange + blackLockedApproved as the internal brand. --brand = #EC6A1E lives in the registry. Wordmark to be tuned to it later.
User model & assignment (team app)NowMulti-user from the start: every action carries an author; manual desk tasks carry an assignee.
Locations dense table (default at 300+)NowAt 300+ locations the table is the primary view; cards are the toggle. Saved filters matter more than card polish.
Voice transcript flowSoonDesign the composer mic + editable-transcript step now; the speech engine itself can land slightly later behind the same UI.
Intake confirmation schemaLaterThe key/value rows will shift as request types grow. Keep the card flexible; don’t over-specify fields yet.
Reviews module componentsDoneBuilt & promoted to core: metric hero, facets, stars, quote, review card, dropdown. --m-reviews active as the card spine.
Photos componentsLaterAccent reserved, shell ready. Don’t design the internals until the workflow is real.

Guardrails against sprawl

  • Tokens only. No raw hex/px in components — if a value isn’t in the registry, it doesn’t ship. New need → propose a token, don’t inline. The audit flags every off-system colour automatically.
  • Extend, don’t fork. A new surface adds a modifier to an existing component before it earns a new one. “Is this really not a card?” is the gate.
  • One primary per view. If a screen wants two primary buttons, the layout is wrong, not the button.
  • Status words live in one list. Adding a state is a deliberate edit to a shared enum, reviewed — not a new chip in a feature branch.
  • Every class is registered. A new km-* or ds-* class must land in the component manifest in the same change — the audit reconciles the manifest against the stylesheets, so unregistered styling cannot exist invisibly.
03

How a change ships

This app is the source of truth for every krownmanager.com surface. A change is a registry edit, a version bump, and a publish — the docs, the stylesheet, the audit and the consumer feed all update from the same data.

  • 1 · Edit the registry. Tokens in src/lib/registry/tokens.ts, motion in motion.ts, icons in icons.ts, class manifests in components.ts / shell.ts. Component CSS lives beside them in src/lib/styles and references tokens only.
  • 2 · Check the audit. The coverage ledgers recompute from source — new tokens show as unused until wired, off-system values are flagged immediately.
  • 3 · Bump the version. src/lib/registry/meta.ts holds the system version and the changelog shown on Distribution.
  • 4 · Publish. Deploying this app updates the live documentation and the export endpoints (/api/tokens.css, /api/tokens.json, /api/registry.json) that dealer and marketing consume.
04

Decisions & remaining questions

Mark's answers (May 29, 2026) are folded into the system above. Recap of what's locked, then the few things still open.

Locked decisions
Brand
Orange + black approved as the internal brand. --brand = #EC6A1E. Wordmark tuned to it later.
Scale
~300+ locations → dense table is the default Locations view; cards are a toggle.
Apple / Bing
Manual desk tasks, user-assigned to whoever holds the login (one assignee at a time).
Translation
Live-first. Content publishes immediately; internal reviewers approve French refinements asynchronously from their own queue. Never a blocker.
Voice
Near-term — composer mic + editable-transcript step designed in now.
Users
Team app: every action attributed; feed filterable by person.
Language
UI is English-only. French exists solely as the field-level content/translation layer.

Still open

1 · Wordmark

Send the app logo/wordmark when ready — it drops into the header lockup (it’ll sit on the locked orange + black).

2 · What’s live in French before a reviewer signs off?

In the live-first model, something is published in FR immediately. Is that seeded by machine translation, a previous human version, or does it mirror EN until reviewed? This drives how the “FR review pending” card frames the current live text.

3 · Roles & permissions

A separate reviewer dashboard exists. Do we need defined roles (rep vs. translation reviewer vs. admin), or can any team member do anything for now?

4 · Auto-assigning Apple/Bing tasks

Should the app know which user holds which platform login so it can auto-assign desk tasks, or is assignment manual per task to start?

5 · Voice scope

English-only dictation (matching the UI), or should it also handle spoken French content? Any device/browser constraints to design the mic affordance around?

05

System coverage audit

The cleanup strategy, made live and self-checking. The audit reads the app's own source on every build — every token, icon and registered class, reconciled against real usage. Nothing can slip in untracked.

The audit now lives at Audit — registry-driven, with no hardcoded file lists: the census discovers the app’s pages and stylesheets by glob, so adding a surface automatically adds it to the count. It ledgers tokens, classes, icons and off-system colours, and exports a copy-ready cleanup request.