Color

The palette is ink-led: black type on white surfaces, hairline borders, and one loud color — Miltinson Amber — used as a signal, never a fill. Every value on this page is read live from @elirobinson/tokens/tokens.css; the swatches and contrast ratios below cannot drift from what the package ships.

How to think about it

  • Ink does the work. Headings are pure black, body text near-black, and hierarchy comes from the ink scale — not from adding color.
  • Amber is the only loud color. Primary CTAs, the dot in the wordmark, eyebrow underlines, key stats, link hovers. If two things on a screen are amber, one of them is wrong.
  • Forest is the quiet second. Trust marks, success states, and the earnest surfaces (coaching guides). It anchors; it doesn't shout.
  • No gradients, no purple. Flat color only.

Reference semantic tokens (--fg, --surface, --accent) in components, never raw scale values (--ink-500) — the semantic layer is what makes a future dark theme possible without touching component code.

Ink — the neutral scale

TokenValueHexOn whiteOn black
--ink-0#ffffff#ffffff1.00:121.00:1
--ink-50oklch(98.4% 0.002 247)#f9fafb1.05:120.06:1
--ink-100oklch(96.2% 0.003 247)#f1f3f41.12:118.81:1
--ink-200oklch(92.8% 0.004 247)#e5e7ea1.24:116.99:1
--ink-300oklch(86% 0.005 247)#ced1d41.53:113.73:1
--ink-400oklch(70% 0.006 247)#9b9fa22.67:17.87:1
--ink-500oklch(55% 0.008 247)#6e72764.85:14.33:1
--ink-600oklch(42% 0.01 247)#494e528.45:12.49:1
--ink-700oklch(30% 0.01 247)#2a2e3313.62:11.54:1
--ink-800oklch(20% 0.01 247)#12171a18.09:11.16:1
--ink-900oklch(12% 0.008 247)#04060820.29:11.03:1
--ink-950oklch(6% 0.006 247)#00010120.91:11.00:1
--ink-1000#000000#00000021.00:11.00:1

Signal — Miltinson Amber

Warm, craftsman, honest. --signal-500 is the brand amber; the darker steps exist because raw amber fails AA on white — text uses --signal-700 and darker.

TokenValueHexOn whiteOn black
--signal-50oklch(97.5% 0.025 75)#fff5e51.08:119.42:1
--signal-100oklch(94% 0.055 75)#ffe7c31.20:117.44:1
--signal-200oklch(89% 0.1 75)#ffd28f1.42:114.84:1
--signal-300oklch(83% 0.14 72)#ffb7551.72:112.18:1
--signal-400oklch(78% 0.16 68)#f9a1292.06:110.17:1
--signal-500oklch(72.5% 0.175 65)#ef8a002.53:18.30:1
--signal-600oklch(63% 0.165 55)#d267003.69:15.69:1
--signal-700oklch(52% 0.145 45)#a946085.86:13.59:1
--signal-800oklch(40% 0.115 40)#782c0c9.69:12.17:1
--signal-900oklch(28% 0.08 38)#48170715.00:11.40:1

Anchor — Miltinson Forest

TokenValueHexOn whiteOn black
--anchor-50oklch(96% 0.018 165)#e7f6ef1.12:118.82:1
--anchor-100oklch(91% 0.035 165)#cde9db1.29:116.29:1
--anchor-200oklch(82% 0.055 162)#a5d0b91.71:112.30:1
--anchor-300oklch(70% 0.075 160)#74ad8e2.58:18.13:1
--anchor-400oklch(55% 0.085 158)#42815e4.65:14.51:1
--anchor-500oklch(42% 0.08 156)#215a3a8.13:12.58:1
--anchor-600oklch(34% 0.065 156)#16422911.41:11.84:1
--anchor-700oklch(26% 0.05 156)#0b2b1a15.26:11.38:1
--anchor-800oklch(19% 0.035 156)#05180d18.32:11.15:1
--anchor-900oklch(13% 0.025 156)#010a0420.06:11.05:1
--anchor-hoveroklch(55% 0.085 158)#42815e4.65:14.51:1
--anchor-pressoklch(34% 0.065 156)#16422911.41:11.84:1
--anchor-fg#ffffff#ffffff1.00:121.00:1
--anchor-tintoklch(96% 0.018 165)#e7f6ef1.12:118.82:1

Semantic tokens

These are the names components actually use. Each references a base-scale value, so retuning the palette is a one-line change per token.

Backgrounds and surfaces

TokenReferencesPurpose
--bgvar(--ink-0)page background
--bg-subtlevar(--ink-50)zebra / panel
--bg-mutedvar(--ink-100)code blocks, inset wells
--bg-inversevar(--ink-1000)dark hero, footer
--surfacevar(--ink-0)cards
--surface-2var(--ink-50)nested cards
--surface-3var(--ink-100)deeper inset

Text

TokenReferencesPurpose
--fgvar(--ink-1000)primary text
--fg-1var(--ink-1000)alias
--fg-2var(--ink-600)secondary text
--fg-3var(--ink-500)tertiary / meta
--fg-4var(--ink-400)disabled
--fg-inversevar(--ink-0)on dark
--fg-on-signalvar(--ink-1000)text on lime

Borders

TokenReferencesPurpose
--bordervar(--ink-200)default hairline
--border-strongvar(--ink-300)emphasized
--border-inverseoklch(100% 0 0 / 0.12)on dark

Accent — Miltinson Amber

TokenReferencesPurpose
--accentvar(--signal-500)Miltinson Amber
--accent-hovervar(--signal-400)
--accent-pressvar(--signal-600)
--accent-fgvar(--ink-1000)
--accent-tintvar(--signal-50)very-light amber backgrounds

Anchor — Miltinson Forest

TokenReferencesPurpose
--anchorvar(--anchor-500)Miltinson Forest
--anchor-hovervar(--anchor-400)
--anchor-pressvar(--anchor-600)
--anchor-fgvar(--ink-0)
--anchor-tintvar(--anchor-50)

Links and focus

TokenReferencesPurpose
--focus-ringvar(--ink-1000)high-contrast focus, ink-on-bg
--linkvar(--ink-1000)
--link-hovervar(--signal-700)
--link-visitedvar(--ink-700)

Status

TokenReferencesPurpose
--status-successvar(--anchor-500)
--status-warningvar(--signal-600)
--status-dangeroklch(58% 0.22 25)
--status-infooklch(60% 0.13 240)

Contrast

Computed from the live token values with WCAG 2.x math. Two pairings deserve a note: raw amber (--accent) fails AA as text on white — which is exactly why button labels use --accent-fg (ink on amber, 8.7:1) and text links only shift to amber's dark step (--signal-700) on hover. --status-warning passes at large sizes only; pair it with an icon or keep warning text at --fg with a warning-colored border.

ForegroundBackgroundSampleRatioWCAG AA
--fg
Body text on the page
--bgAa 16px21.00:1AA
--fg-2
Secondary text
--bgAa 16px8.45:1AA
--fg-3
Tertiary / meta text
--bgAa 16px4.85:1AA
--fg
Text on panels and zebra rows
--bg-subtleAa 16px20.06:1AA
--accent-fg
Label on an accent (amber) button
--accentAa 16px8.30:1AA
--anchor-fg
Label on a forest button
--anchorAa 16px8.13:1AA
--fg-inverse
Text on dark hero / footer
--bg-inverseAa 16px21.00:1AA
--accent
Amber accents on ink (stats, links on dark)
--bg-inverseAa 16px8.30:1AA
--link-hover
Link hover color
--bgAa 16px5.86:1AA
--status-success
Success text
--bgAa 16px8.13:1AA
--status-warning
Warning text
--bgAa 16px3.69:1AA large only
--status-danger
Danger text
--bgAa 16px4.79:1AA
--status-info
Info text
--bgAa 16px3.88:1AA large only