local·first·lab

The design system, printed by the code that implements it. Every number on this page is computed at build time by reading the repo; a stale claim here is a build bug, not an editorial one.

THE TOKENS

Tokens

TYPE 9 steps, whole 4px line boxes
--t-0
600 11px/16px var(--font-mono) (16px box, x4 OK)
--t-1
600 12.5px/20px var(--font-mono) (20px box, x4 OK)
--t-2
400 14px/24px var(--font-mono) (24px box, x4 OK)
--t-3
600 15px/24px var(--font-mono) (24px box, x4 OK)
--t-4
400 15.5px/24px var(--font-body) (24px box, x4 OK)
--t-5
400 17px/28px var(--font-body) (28px box, x4 OK)
--t-6
600 21px/28px var(--font-mono) (28px box, x4 OK)
--t-7
600 26px/36px var(--font-mono) (36px box, x4 OK)
--t-8
600 clamp(30px,4.5vw,40px)/1.12 var(--font-mono) (ratio leading (the one exemption))
SPACE base unit 4px
--space-0
4px
--space-1
8px
--space-2
12px
--space-3
16px
--space-4
24px
--space-5
32px
--space-6
48px
--space-7
72px
--space-8
112px
COLOR recomputed each build; numbers, not paint chips
--ink / --bg (dark)
15.06 AA
--ink / --panel-bg (dark)
13.58 AA
--ink / --panel-bar-bg (dark)
14.50 AA
--muted / --bg (dark)
8.71 AA
--muted / --panel-bg (dark)
7.86 AA
--muted / --panel-bar-bg (dark)
8.39 AA
--accent / --bg (dark)
8.71 AA
--accent / --panel-bg (dark)
7.86 AA
--accent / --panel-bar-bg (dark)
8.39 AA
--ok / --bg (dark)
12.57 AA
--ok / --panel-bg (dark)
11.34 AA
--ok / --panel-bar-bg (dark)
12.11 AA
--bad / --bg (dark)
6.96 AA
--bad / --panel-bg (dark)
6.28 AA
--bad / --panel-bar-bg (dark)
6.71 AA
--accent-dim / --bg (dark)
9.53 AA
--accent-dim / --panel-bg (dark)
8.60 AA
--accent-dim / --panel-bar-bg (dark)
9.18 AA
--dim / --bg (dark)
3.93 AA-LARGE
--dim / --panel-bg (dark)
3.55 AA-LARGE
--dim / --panel-bar-bg (dark)
3.79 AA-LARGE
--panel-bar-fg / --bg (dark)
7.51 AA
--panel-bar-fg / --panel-bg (dark)
6.78 AA
--panel-bar-fg / --panel-bar-bg (dark)
7.24 AA
--ink / --bg (light)
15.64 AA
--ink / --panel-bg (light)
17.04 AA
--ink / --panel-bar-bg (light)
17.04 AA
--muted / --bg (light)
8.13 AA
--muted / --panel-bg (light)
8.86 AA
--muted / --panel-bar-bg (light)
8.86 AA
--accent / --bg (light)
4.76 AA
--accent / --panel-bg (light)
5.19 AA
--accent / --panel-bar-bg (light)
5.19 AA
--ok / --bg (light)
4.89 AA
--ok / --panel-bg (light)
5.33 AA
--ok / --panel-bar-bg (light)
5.33 AA
--bad / --bg (light)
6.00 AA
--bad / --panel-bg (light)
6.54 AA
--bad / --panel-bar-bg (light)
6.54 AA
--accent-dim / --bg (light)
3.08 AA-LARGE
--accent-dim / --panel-bg (light)
3.35 AA-LARGE
--accent-dim / --panel-bar-bg (light)
3.35 AA-LARGE
--dim / --bg (light)
3.17 AA-LARGE
--dim / --panel-bg (light)
3.45 AA-LARGE
--dim / --panel-bar-bg (light)
3.45 AA-LARGE
--panel-bar-fg / --bg (light)
8.13 AA
--panel-bar-fg / --panel-bg (light)
8.86 AA
--panel-bar-fg / --panel-bar-bg (light)
8.86 AA
MOTION three durations, one curve
--dur-1
120ms
--dur-2
220ms
--dur-3
420ms
--ease
cubic-bezier(.2,.6,.2,1)

THE SYSTEM

Eight primitives

PRIMITIVE

sec

EYEBROW

A section heading

Rhythm and the eyebrow pair, owned once.

sec() the exact call
sec("ship", "WHAT THIS LAB SHIPS", "What this lab ships", body)
class
sec
aria
aria-labelledby binds region to heading

PRIMITIVE

panel

panel optional titlebar

A bordered surface.

panel() the exact call
panel(body, tone="surface", bar_title="panel")
class
panel panel-bar panel-body
data-tone
surface | term | accent | ok | bad

PRIMITIVE

rack

one

two

rack() the exact call
rack([panel(...), panel(...)], cols=2)
class
rack
data-cols
2 | 3 | 4, collapsing at 900/560

PRIMITIVE

spec

LICENSE
AGPL-3.0
SELF-HOST
yes
spec() the exact call
spec([("LICENSE", "AGPL-3.0"), ("SELF-HOST", "yes", "ok")])
class
spec
element
dl/dt/dd, a real description list

PRIMITIVE

strip

  • 0 trackers
  • 0 third-party requests
strip() the exact call
strip(["0 trackers", "0 third-party requests"], glyph="check")
class
strip
data-glyph
check | dot | none

PRIMITIVE

bar

status demo
bar() the exact call
bar(cells, kind="head" | "status", nav=[...], active="/kit.html")
class
bar
data-kind
head | status
active state
aria-current, rendered as a CSS prompt glyph

PRIMITIVE

prose

Long-form copy at the measure.

prose() the exact call
prose(html)
class
prose
measure
680px

PRIMITIVE

btn

view comparisons
btn() the exact call
btn("view comparisons", "/alternatives.html", role="primary")
class
btn
data-role
primary | secondary | ghost | ok | bad
brackets
CSS content, never copy

PAGE SHAPE

Skeleton

ORDER
bar[head] . sec* . footer . bar[status]
SECTION RHYTHM
clamp(56px,8vw,96px)
SIBLING BLOCKS
32px
HEADING TO BODY
24px
INSIDE LISTS
16px

DRIFT DASHBOARD

Census

THE CONTRACT

Rules

VARIANTS
a variant is a data attribute, never a new class: test_class_vocabulary_closed (planned)
TYPE
a size is a --t-N token, never a px; exceptions: the .brand wordmark, the .skip link, --t-8's own clamp, and the 25 counted declarations in lawfirms.css: test_type_scale_is_closed (planned)
SPACE
a gap is a --space-N token or one of seven named layout tokens: test_space_scale_is_closed (planned)
BREAKPOINTS
a breakpoint is 560, 900 or 1200: test_breakpoints_closed (planned)
READER COPY
reader copy uses --ink or --muted, nothing else: test_reader_copy_is_aa (enforced)
localfirstlab.org · kit · theme dark · crt low · 0 trackers · 0 third-party requests