One badge, two ways to mean state
A small mono, uppercase pill under a record's title signals its state at a glance. The same primitive carries state two ways — a fixed lifecycle vocabulary, and an urgency gradient that a pill computes for itself from time-to-deadline.
Flavour A · the lifecycle vocabulary
Five semantic variants, driven from one JSON state-vocabulary so you add a state once — not
per row. A confirmation wears the green (service shares resolved's tone;
the 🔧 sets it apart), and the loud orange is reserved for the warning tier.
Shelf: assets.gf.cx/status-pill · icons come from each variant's
CSS ::before — never typed into the label.
Flavour B · the urgency gradient
Instead of a fixed word, the band is computed from time until due. One pill walks
green → amber → red as a deadline approaches, then flips to red OVERDUE N once it
passes — so a recurring chore signals its own urgency with no operator math. This flavour is emitted
by the maintenance-timer
primitive. Hover any pill for the weeks·days countdown (the data-tip tooltip standard).
The bare pills, side by side
| Band | Trigger | Pill | Colour |
|---|---|---|---|
mt-ok | > 30 days out | DUE 6mo | green |
mt-soon | 8–30 days | DUE 3w | amber |
mt-due | 0–7 days / today | DUE 3d · DUE NOW | red |
mt-overdue | past due | OVERDUE 12d (carries N) | red |
mt-never | no data-last | NEVER LOGGED | dark red |
Live — real timers rendering the pill in context
These are actual maintenance-timer cards rendered by the shipped script from a fixed
data-last — the whole card (label, meta, progress bar, hover countdown), not just the
badge. One reads green (months out), one reads overdue.
Wiring
<link rel="stylesheet" href="https://assets.gf.cx/maintenance-timer/maintenance-timer.css">
<link rel="stylesheet" href="https://assets.gf.cx/tooltip/tooltip.css">
<script src="https://assets.gf.cx/maintenance-timer/maintenance-timer.js" defer></script>
<div data-maintenance
data-label="Descale"
data-detail="every 6 months"
data-last="2026-08-15"
data-interval="6mo"></div>
The committed data-last is the source of truth. Add data-store="key" to
show a "✓ Mark done today" button that stamps localStorage and then prints the exact
data-last="…" line to bake back into the page — the browser never becomes the record.
Why one primitive, two flavours
Lifecycle state is a word a human sets; urgency is a number time computes. Both want the same at-a-glance badge, so they share the pill's shape, type, and colour semantics — a reader learns "green good, amber soon, red now" once and it holds across both. First shipped on the DeLonghi EC9255M household record — a 6-month descale cadence that counts itself down.