Elements
The indivisible atoms — a single design class each: a button, a link, an input, a chip, a platform tile, a star rating, a quotation. Elements carry no layout opinions of their own; they’re the smallest pieces that Objects and Components snap together.
Buttons & links
One primary action per view, in black (--ink-900). Everything else is secondary (outlined) or quiet (text). Destructive actions read in red but stay understated. Orange is reserved for brand & wayfinding — never a button fill.
--ink-800 · soft neutral shadow for a floating-CTA feel · Secondary surface + strong border · Quiet text-only · --size-ctl (34px) tall, --size-ctl-sm (28px) small · focus = --focus-ring..km-btn--ondark): transparent fill, --ondark-line border, --ondark-hover wash on hover. Inherits the full button contract so it
can never wrap or de-centre.Icon micro-motions on buttons
.km-ic-swing · .km-ic-turn · .km-ic-tilt · .km-ic-rise · .km-ic-spin while syncing. One glyph at a time, never ambient.Form fields & textareas
Calm inputs with a clear focus state. The intake textarea is the most important field in the app — make it inviting and large.
Chips, status pills & platform indicators
The most-repeated, most-abusable elements in the app. Lock them now. Status pills always pair colour + dot + word. Live platform tiles fill green to match the Published pill; not-live tiles stay neutral and a corner dot names the work that's left.
Status pills
--plain variant
(no dot) for neutral counts/tags so it never reads as a status.Platform indicators
title/aria gives the full name on
hover & to screen readers.Tile status system
A live tile is a square sibling of the Published pill — same green fill, same green glyph, no dot, because the fill already says “done”. Every not-live tile stays neutral; its corner dot names the one thing left to do. So a row of green = fully live, and the only marks left on a card point at real work.
| Tile | State | Reads as |
|---|---|---|
| Live · green fill · no dot · link | Published and reachable — the tile opens the public profile. A platform counts as live even if it was published by hand (Apple/Bing). | |
| Action needed · amber dot | Connected but waiting on a person — a manual desk task or a pending review. | |
| Not connected · hollow ring | No matching listing found. The slot is genuinely empty — free to create a new listing from scratch. | |
| Not connected — possible match · filled ring | An existing listing shares this address under a different business name. Worth checking first to link, request access, or knowingly create a separate listing. | |
| Sync failed · red dot · optional | Was live, last push errored. Borrows the system --block hue; pairs with a retry. |
Star rating
Literal stars, but monochrome — keeping the house rule that icons never carry their own colour. Filled (ink) = the score; hollow (border-grey) = the remainder. Rating reads from the count of filled stars, never from gold. Gold/amber was rejected: amber already means “pending” in the status system, and gold would be the first icon allowed its own colour.
.km-stars — the Stars component renders filled + hollow glyphs. .on = --ink-700, .off = --border-strong.Quote
Review text — and later, customer messages — are quotations, not our copy. The block opens with the system's filled quote glyph in muted --ink-500 in place of a grey left rule, so it reads as a quiet ornament; the quoted text sits at --ink-900 regular so it's the primary read.
.km-quote — flex row: .km-quote__mark (the glyph) + the quoted text. Weight, not colour, separates it from names.