LutzStack — Brand System
v1.0 / colour, surface, component
One violet,
extended without
losing its nerve.
The identity gives us three fixed values and one accent. Everything below is derived from them: every hue in the system walks the same five-step lightness ladder and is capped at the accent's own chroma, so nothing in the palette can out-shout the brand.
#8E7FE8 accent — from the mark
#0F1219 base — every canvas
#E7E9EA type — primary ink
01 / Core violet
h 288 · five steps · 500 is the accent, unchanged
violet 500 · accent
#8E7FE8
oklch(0.6564 0.1526 288)
the only value inherited from the mark
100 #DAD7FF
300 #B2AAFB
500 #8E7FE8
700 #6255AE
900 #37305E
tints, quiet labels on dark text and icons on the base colour the accent — one per view hover on filled violet, borders badge and notice fills
700 and 900 are the identity's own #6255AE and #37305E — the ladder was fitted to them, not around them. Click any swatch to copy.
02 / Extended spectrum
10 hues · one ladder · chroma capped per hue
The accent is a restrained violet — C 0.15, not 0.25. Every other hue is held to the same ceiling and adjusted only where the sRGB gamut forces it lower, which is why the cyans and teals read quiet rather than weak. Any two of these can sit side by side at the same step without one dominating.
Hue
100 300 500 700 900
Violet h 288 · c≤0.153
#DAD7FF
#B2AAFB
#8E7FE8
#6255AE
#37305E
Indigo h 268 · c≤0.150
#CDDCFF
#97B3FF
#6A8BEC
#445FB1
#273560
Blue h 250 · c≤0.142
#C4E0FE
#80BBF8
#4395E4
#1D68AA
#163A5C
Cyan h 225 · c≤0.102
#C4E2EF
#7EC1DB
#3D9EC0
#116F8C
#133E4D
Teal h 195 · c≤0.088
#C5E3E3
#82C4C3
#44A2A2
#1B7373
#163F3F
Green h 150 · c≤0.140
#C6E6CB
#83C992
#46A861
#1D783C
#174223
Lime h 128 · c≤0.150
#D2E4BE
#A1C474
#76A22E
#4E7200
#2C3F0D
Orange h 48 · c≤0.160
#FED2BC
#F59D70
#E0702A
#A34400
#59280A
Red h 25 · c≤0.160
#FFCEC9
#F9968F
#E2635D
#A83B39
#5C2421
Magenta h 330 · c≤0.160
#F3CFEF
#E199DA
#C669BF
#91418B
#4F264C
One accent per view
Violet 500 marks the single most important action on screen. A second violet element demotes the first.
Steps, not opacity
Never fade a colour to suggest a lighter one. Step down the ramp instead — opacity over a violet surface muddies the hue.
Fills go dark
On the base colour, 900 fills with 300 text is the readable pairing. 500 fills take base-coloured type, never white.
Ten is the ceiling
The system will not grow past these hues. New needs are met by picking a step, not adding an angle.
03 / Neutrals & surfaces
violet-tinted · dark-native
Grey ramp — h 288, chroma under 0.02
100 #E7E9EA
300 #9F9FA6
500 #81818A
700 #474750
900 #23232B
The tint is invisible on any single swatch and unmistakable across a full screen. It is what keeps a page of greys inside the brand instead of drifting to a generic slate.
Surface stack — fixed values, do not derive
#0F1219 surface-base page canvas, input wells
#171A24 surface-raised cards, panels, table body
#221F3A surface-violet active rows, notices, tooltips
#37305E border default 1px hairline
#463E78 border-strong hover, focus, emphasis
04 / Gradients & surface treatments
four sanctioned treatments
Signal
Launch moments, hero panels, cover slides.
Depth
Dark full-bleed sections behind large type.
Cool run
Charts, dashboards, capacity graphics.
Rule grid
Empty states and pattern fills. Never behind text.
Interpolate in OKLCH, never sRGB — a violet-to-cyan blend in sRGB collapses to grey through the middle. Gradients are for large flat areas only: never behind body copy, never as a button fill, never on the mark.
05 / Components
radius 4 · border 1px #37305E · square corners on the mark only
Buttons
Badges
applied drifted failed planning v2.4.1
Inputs
select a region
must be at least 1
Table
14 stacks
stackregiondriftstate
prod-eu-west-1 eu-west-1 0 applied
prod-us-east-1 us-east-1 2 drifted
staging-eu eu-west-2 0 applied
edge-apac ap-south-1 11 failed
sandbox-lutz eu-west-1 planning
Accent card
14 running
all regions healthy · last check 4m
plan preview ready
6 to add, 2 to change, 0 to destroy.
Progress
applying68%
06 / Data visualisation
fixed order · series 1 is always violet
series 1
#8E7FE8
series 2
#E0702A
series 3
#3D9EC0
series 4
#C669BF
series 5
#44A2A2
series 6
#E2635D
series 7
#76A22E
series 8
#4395E4
Categorical
Sequential — violet
Diverging — cyan to red
Grid lines #221F3A, axis labels #7C838B at 10px. Never colour a chart by aesthetics — take the next colour in the fixed order and stop at six series; past that, group the tail as other in grey 500.
07 / Iconography
the mark's grid, scaled down
The system does not draw its own icon set. It specifies one: take an orthogonal open-source set — Lucide is the closest fit — and restyle it to the grid below. What the mark contributes is not a shape to reuse but a ratio: stroke 6 on a 32 unit grid, which rescales to stroke 2 on 24.
Grid
24 unit box · 20 unit live area
2 unit padding on all four sides
snap every terminal to a whole unit
orthogonal and 45° only
counter gap 2 · never below 1.5
Stroke weight
1.5u — too light, breaks at 16px
2u — the system weight
2.5u — competes with the mark
Terminals
square · correct
rounded · never
Colour
default
hover
active
status
Grey by default. Violet marks the single active item in a set — if two icons in one view are violet, one of them is wrong. Semantic hues appear on status icons only, never on navigation.
Sizes
16 · inline, table cells
20 · buttons, inputs
24 · nav, toolbars
32 · empty states
Only these four. At 16px the stroke stays 2 units, which renders as 1.33px — accept the softness rather than thinning the shape.
08 / Typography
one family · three weights · seven roles
Aa
JetBrains Mono
400 regular · 500 medium · 700 bold
fallbacks: Berkeley Mono, ui-monospace,
SFMono-Regular, monospace
tabular figures by default
no italics · no condensed · no second family
display 52 / 700 / −0.055em
lutzstack
heading-1 30 / 700 / −0.05em
Infrastructure as record
heading-2 19 / 700 / −0.04em
Regions and availability
label 12 / 500 / 0.14em caps
SECTION LABEL
body 13 / 400 / 1.8
One family, one voice — the scale does the work that a second typeface would.
meta 11 / 400 / 1.8
last check 4m · 14 stacks · eu-west-1
data 12 / 400 / −0.02em
0.6564 0.1526 288°
Tracking tightens with size
Mono is wide by default. Anything above 19px takes negative tracking — −0.04em at heading, −0.055em at display, matching the wordmark.
Caps for labels only
0.14em letterspaced uppercase belongs to section labels and column headers at 11–12px. Never a heading, never a sentence.
Weight, not colour, for hierarchy
700 and 400 are the only weights in running text. 500 is reserved for caps labels, where 700 would go blocky.
Measure caps at 84ch
Monospace runs long. Body copy stops at 84 characters; anything wider stops scanning and starts sprawling.
Wordmark
lutzstack
always lowercase · tracking −0.055em
never letterspaced, never all-caps in running text
Numerals
0123456789
99.982%
14 drifted
4m 12s
tabular throughout — figures must align in tables and logs without exception
09 / Tokens
:root { /* identity constants */ --ls-accent: #8E7FE8; --ls-base: #0F1219; --ls-type: #E7E9EA; /* surfaces */ --ls-surface-base: #0F1219; --ls-surface-raised: #171A24; --ls-surface-violet: #221F3A; --ls-border: #37305E; --ls-border-strong: #463E78; /* grey — violet-tinted, h 288 */ --ls-grey-100: #E7E9EA; --ls-grey-300: #9F9FA6; --ls-grey-500: #81818A; --ls-grey-700: #474750; --ls-grey-900: #23232B; /* violet */ --ls-violet-100: #DAD7FF; --ls-violet-300: #B2AAFB; --ls-violet-500: #8E7FE8; --ls-violet-700: #6255AE; --ls-violet-900: #37305E; /* indigo */ --ls-indigo-100: #CDDCFF; --ls-indigo-300: #97B3FF; --ls-indigo-500: #6A8BEC; --ls-indigo-700: #445FB1; --ls-indigo-900: #273560; /* blue */ --ls-blue-100: #C4E0FE; --ls-blue-300: #80BBF8; --ls-blue-500: #4395E4; --ls-blue-700: #1D68AA; --ls-blue-900: #163A5C; /* cyan */ --ls-cyan-100: #C4E2EF; --ls-cyan-300: #7EC1DB; --ls-cyan-500: #3D9EC0; --ls-cyan-700: #116F8C; --ls-cyan-900: #133E4D; /* teal */ --ls-teal-100: #C5E3E3; --ls-teal-300: #82C4C3; --ls-teal-500: #44A2A2; --ls-teal-700: #1B7373; --ls-teal-900: #163F3F; /* green */ --ls-green-100: #C6E6CB; --ls-green-300: #83C992; --ls-green-500: #46A861; --ls-green-700: #1D783C; --ls-green-900: #174223; /* lime */ --ls-lime-100: #D2E4BE; --ls-lime-300: #A1C474; --ls-lime-500: #76A22E; --ls-lime-700: #4E7200; --ls-lime-900: #2C3F0D; /* orange */ --ls-orange-100: #FED2BC; --ls-orange-300: #F59D70; --ls-orange-500: #E0702A; --ls-orange-700: #A34400; --ls-orange-900: #59280A; /* red */ --ls-red-100: #FFCEC9; --ls-red-300: #F9968F; --ls-red-500: #E2635D; --ls-red-700: #A83B39; --ls-red-900: #5C2421; /* magenta */ --ls-magenta-100: #F3CFEF; --ls-magenta-300: #E199DA; --ls-magenta-500: #C669BF; --ls-magenta-700: #91418B; --ls-magenta-900: #4F264C; /* type */ --ls-font: "JetBrains Mono", ui-monospace, SFMono-Regular, monospace; --ls-radius: 4px; }
10 / Assets
svg · png · pdf · woff2 · ttf
The mark is four bars on a 32-unit grid — a bracket, two indented rows, a base. It is never redrawn, re-proportioned, or given a second colour. Clearspace is the height of one bar on every side; below 16px, drop the wordmark and ship the icon alone.
Two cuts of every lockup
The plain files set lutzstack as live text and need JetBrains Mono present. The -outlined files carry the letterforms as paths — use those for print, email, embedding, and anywhere the font is not guaranteed.
lutzstack
Horizontal lockup
The default. Nav bars, letterheads, anywhere width is cheap.
lutzstack
Stacked lockup
Square-ish spaces — covers, avatars with room, slide corners.
App mark
132px rounded tile, accent or dark. Favicons, docks, store listings.
JetBrains Mono
The whole system, one family. Weights 400, 500 and 700 are the only ones in use. SIL Open Font License.
family · 2.2 MB licence
Web subsets
This page serves its own woff2. Point at brand.lutzstack.com/fonts/ and skip Google Fonts entirely.
latin · 31 KB latin-ext · 11 KB
Reference PDFs
This page as a flat document, and the lockup sheet with clearspace and minimum sizes drawn out.
brand system · 1.2 MB lockups · 140 KB
brand.lutzstack.com — every value on this page is copy-to-clipboard.
lutzstack.com