ash lumen

monochromatic design system · token-based · light/dark aware

a minimal system built from the grey spectrum. hierarchy through luminance, not hue.

v0.1.0stablemit

brand

wordmark
ash lumen
monochromatic · token-based · light + dark
iconography · lucide · 1.5px stroke · currentColor · 22px

color via currentColor — inherits parent text token automatically. never tint with hex.

type scale · 1.1rem base
3xlDisplay2.2rem
2xlHeading two1.65rem
xlHeading three1.375rem
lgHeading four1.2375rem
basebody — large by default for calm reading.1.1rem
smsecondary copy and form labels0.9625rem
xscaptions, metadata, badges0.825rem
type families
sans — inter
AaBbCcDdEeFfGg
400 · 500 · 600 · 700
mono — jetbrains mono
AaBbCcDdEeFfGg
400 · 500 · 600
text utilities

lead — lg size, text-secondary color. for subtitles and intro text.

body — 1.1rem base. the default reading size.

secondary — one step down. supporting copy.

muted — for metadata, timestamps, placeholders.

faint — barely visible. for dividers, underlines, ghost ui.

label — mono xs uppercase. for section eyebrows and data keys.

caption — xs, muted. for footnotes and image descriptions.

colors

surface ramp
bg
surface
surface-raised
border-subtle
border
accent + interaction
accent
accent-hover
focus-ring
text ramp
accent
text
secondary
muted
faint
semantic — desaturated by design
error
warning
success
info
syntax
keyword
string
function
constant
comment
parameter

foundations

spacing · 8px-derived (5 / 7 / 9 / 10 / 11 omitted)
1
0.25rem · 4px
2
0.5rem · 8px
3
0.75rem · 12px
4
1rem · 16px
6
1.5rem · 24px
8
2rem · 32px
12
3rem · 48px
16
4rem · 64px
24
6rem · 96px
radii
sm
3px
md · default
6px
lg
10px
full · pill
9999px
shadows · two total
shadow-sm
0 1px 3px #00000010
shadow-md
0 4px 12px #00000015
motion
fast · 120ms ease
hover / focus transitions
normal · 200ms ease
layout changes, dialogs

buttons

variants
sizes

badges

mono-typed · pill shape
v0.1.0draftfaileddeprecatedpassingbeta

alerts

3px left rule · title + description · desaturated semantic
tokens reloaded
light/dark resolved automatically — no dark: prefix needed.
build passing
all 96 token declarations compiled without error.
opacity modifiers won't work
use color-mix() with css variable colors instead of /30 or /50.
pure #ff0000 is never acceptable
semantic colors are two-channel muted greys. #806060 for error, #607060 for success.

inputs

form surface

cards

variants
surface card
flat. no shadow. hairline border carries the edge.

default card — surface background, border-subtle, 6px radius, 24px padding.

raised card
surface-raised · shadow-sm

for panels that hover one layer above the page.

interactive card
hover to see the transition

border shifts to visible, shadow-md appears. 200ms ease.

structured card with sub-elements
token pipeline
tokens/*.json → src/tokens.css

96 declarations generated from base, light, and dark token files via the build script.

dialog

overlay 75% bg + blur(4px) · border-radius lg · shadow-md · open/close scale(0.97↔1) 150ms

code

syntax highlighting
import { readFileSync } from 'node:fs';

interface Token {
  name: string;
  value: string;
}

// resolve design tokens at runtime
function getTokens(path: string): Token[] {
  const raw = readFileSync(path, 'utf-8');
  return JSON.parse(raw);
}
inline code

use color-mix(in srgb, var(--color-bg) 90%, transparent) for translucent surfaces. opacity modifiers like /30 don't work with css variable colors.

motion

animated stats · count-up on scroll
tokens
0
+6 this week
components
0
stable
open issues
0
low
build
pass
2 min ago
durations · hover each box
fast · 120ms ease · hover / focus
hover me
normal · 200ms ease · layout / dialog
hover me
dialog entrance · opacity + scale(0.97 → 1) · 200ms
confirm action
this dialog enters with opacity + scale(0.97 → 1) over 200ms ease. no bounce.
button hover · primary shimmer sweep · 900ms ease

primary: light sweep translateX(−120% → 120%) · secondary: surface-raised bg · ghost: gains surface bg · danger: opacity 0.8

card hover · border + shadow-md + accent glow · 200ms
hover this card
border → visible · shadow-md · accent radial glow appears
and this one
200ms ease. no scale, no translate. restrained.
and this
the glow is a radial gradient at 12% accent opacity. barely there.
badge pulse · breathing dot · 2.4s ease-in-out infinite
passinglivereview
prefers-reduced-motion: all transitions and animations should be wrapped in a motion media query for accessibility. the token durations make this straightforward.

separator

1px hairline · border-subtle · horizontal + vertical
horizontal

content above


content below

vertical
left
right

states

focus ring

2px solid focus-ring · outline-offset 2px · grey, not blue

disabled

opacity: 0.35 · pointer-events: none

links

links inherit accent color with a faint underline at 0.15em offset. on hover, the underline darkens to text-secondary — no color change, just the decoration.

within prose: underline-offset: 2px · transition: text-decoration-color 120ms ease.

selection

select this text to see the custom selection color — background: border · foreground: text. monochromatic. no blue highlight.