ShlakShlak

Design system

Walk the map. Everything below is read from @shlak/design-tokens, the one place a brand value is written. The written source is brand/DESIGN-SYSTEM.md; the tokens are transcribed from it by hand and a drift test fails if the two disagree.

The theme control in the header applies to this page only. It overrides the semantic tokens for this subtree, so you can read either scheme without changing your OS.

Colour

DESIGN-SYSTEM §1

Ramps

Three ramps and one flat ink. Ramp steps are theme-invariant: bg-trail-900 is the same colour in both schemes, which is why they are the escape hatch rather than the default.

Trail

The green-black neutral. Every dark-theme surface.

trail-50

#F1F7F1

trail-100

#DCE9DD

trail-200

#BCD3C0

trail-300

#8AAF93

trail-400

#5C8869

trail-500

#3F664E

trail-600

#2C4A38

trail-700

#1E3428

trail-800

#15251C

trail-900

#0E1A14

trail-950

#0A130E

Lime

The accent. Progress, achievement, the primary action.

lime-100

#EEFCCB

lime-200

#DBF894

lime-300

#C6F24E

lime-400

#A9D634

lime-500

#8CB520

lime-600

#6F9013

lime-700

#52690E

Stone

The warm neutral. Every light-theme surface.

stone-50

#FAF8F4

stone-100

#F2EFE8

stone-200

#E8E3D9

stone-300

#D6CFC1

stone-400

#B3AA99

stone-500

#8B8272

stone-600

#6B6355

stone-700

#4C463C

Ink and Signal

Signal is semantic only, never decorative.

ink

#121512

danger

#D4553D

warning

#E0A32E

success

#8CB520

info

#4E8FA8

Semantic tokens

Every token carries both schemes, so a dark: pairing on one of these utilities is redundant. Reach for these first; reach for a ramp step only when you want one fixed colour in both schemes.

bg.canvas

bg-canvas

#FAF8F4 / #0A130E

bg.surface

bg-surface

#F2EFE8 / #0E1A14

bg.raised

bg-raised

#FFFFFF / #15251C

fg.default

text-fg

#121512 / #E8E3D9

fg.muted

text-fg-muted

#6B6355 / #8AAF93

fg.accent

text-accent

#6F9013 / #C6F24E

border.default

border-border

#D6CFC1 / #1E3428

track.unfilled

bg-track

#B3AA99 / #2C4A38

track.filled

bg-track-filled

#6F9013 / #C6F24E

track.rut

bg-track-rut

#52690E / #A9D634

action.bg

bg-action

#C6F24E / #C6F24E

action.fg

text-on-action

#121512 / #121512

The one colour rule that matters

lime-300 is a surface colour, never a text colour on light. On stone-50 it measures 1.24 : 1, which is invisible. When lime has to appear as a colour on a light ground it steps down to lime-600.

Two thousand steps

lime-300 on stone-50 · 1.2 : 1 · never

Two thousand steps

lime-600 on stone-50 · 3.5 : 1 · clears the non-text minimum

The primary action is the other half of the rule: a lime-300 fill with ink text in both themes. The brand's most recognisable element is identical light and dark.

light

dark

Verified contrast

Measured, not assumed.

ink on stone-50
17.5 : 1AAA
stone-600 on stone-50
5.6 : 1AA
stone-200 on trail-900
13.9 : 1AAA
trail-300 on trail-900
7.2 : 1AAA
ink on lime-300
14.3 : 1AAA
lime-300 on trail-900
13.7 : 1AAA
lime-600 on stone-50
3.5 : 1non-text only
lime-300 on stone-50
1.2 : 1never

Typography

DESIGN-SYSTEM §2

Families

All three are vendored into the repository and loaded from pinned binaries. Neither app fetches a typeface over the network at build or run time, so web and mobile render identically.

Space Grotesk

Display and wordmark · 600, 700

ABCDEFGHIJKLMNOPRSTUWYZ ąćęłńóśźż 0123456789

Latin Extended-A, so Polish diacritics render.

Inter

UI and body · 400, 500, 600

ABCDEFGHIJKLMNOPRSTUWYZ ąćęłńóśźż 0123456789

Tabular numerals are on, so a changing step count does not re-flow its neighbours.

JetBrains Mono

Data and labels · 400, 500

ABCDEFGHIJKLMNOPRSTUWYZ ąćęłńóśźż 0123456789

Distances, step counts, and every small-caps label.

Scale

A 1.200 minor third off a 16 px base. Each specimen below is rendered through its Tailwind utility; the metrics beside it are read from the TypeScript constants.

display

38 / 42 · -0.02em

Wiślana Trasa Rowerowa

h1

30 / 36 · -0.02em

Today's walk

h2

24 / 30 · -0.02em

Stages and elevation

h3

20 / 26 · 0em

Vistula bend, kilometre 214

body-lg

18 / 28 · 0em

Your feet move the pin. Every step you take counts toward somewhere real.

body

16 / 24 · 0em

The route ahead splits at the old ferry crossing and rejoins after the treeline.

body-sm

14 / 20 · 0.01em

Synced 4 minutes ago from Health.

caption

12 / 16 · 0.01em

Updated 09:41

label

11 / 14 · 0.12em

Stage 4 of 10

caption is metadata only. The smallest step allowed for running body text is body-sm; never ship 12 px as running text on mobile.

Space, radius, size

DESIGN-SYSTEM §3

Space

A 4 px base, so Tailwind's own multiplier generates every step from one variable. Screen gutters are 20 px on mobile, 24 px on tablet and 32 px on web at 768 px and up.

4
8
12
16
20
24
32
40
48
64
80

Radius

xs · 4

chip

sm · 8

input, small button

md · 12

card

lg · 20

sheet, large button

xl · 28

modal

full · 9999

pill, avatar

Icon sizes

Icons are drawn on the same 24-unit grid as the mark, with round caps and joins, so they sit beside it without a weight mismatch. Stroke width is paired to size and never passed separately.

16 · stroke 1.5

20 · stroke 1.5

24 · stroke 1.5

32 · stroke 2

Hit targets

Never smaller, whatever the icon inside it measures.

44 × 44

everywhere

48 × 48

bottom bar

Elevation

Light theme uses shadow. Dark theme uses surface tint instead, which is why there is deliberately no dark counterpart to the three shadows.

light · shadow

raised

cards on canvas

overlay

menus, popovers

sheet

bottom sheets

dark · surface tint

trail-900

base surface

trail-800

raised surface, card

trail-700

border, divider

Motion

DESIGN-SYSTEM §4

Durations

Progress advances are the one place to spend the motion budget. Everything else is 200 ms or less. Press play to run all four at once; the difference between 120 ms and 900 ms is the whole point of the scale.

instant

120 ms · cubic-bezier(.2,0,0,1)

state flips, hovers, toggles

default

200 ms · cubic-bezier(.2,0,0,1)

everything not listed elsewhere

emphasis

320 ms · cubic-bezier(.2,0,0,1)

sheets, modals, screen transitions

progress

900 ms · cubic-bezier(.4,0,.2,1)

an accent fill advancing

The track and the rut

The progress track carries the same flat band across the top of its filled portion as the mark's accent leg, at the same share of the height. The logo and the progress UI are one object at two scales.

track · track-filled · track-rut at 26.7% of the height

28%

Reduced motion

Every transition on this page is gated behind Tailwind's motion-reduce variant. With Reduce Motion on, the fills and the dots jump straight to their end state instead of travelling, and nothing on the page loops.