Config Layer
The config layer is a collection of CSS custom properties that define your design system. Everything in Axiom references these tokens, so changing a value here ripples through your entire project.
This file is meant to be edited. Unlike a framework you install and leave alone, config.css is where you make Axiom yours.
T-Shirt Sizing, Not Arbitrary Numbers
Tailwind uses numeric scales: p-1, p-2, p-4, text-sm, text-base, text-lg. The numbers are arbitrary steps that you memorize over time.
Axiom takes a different approach. We define a sensible "medium" value, then build t-shirt sizes around it: xs, sm, md, lg, xl, 2xl. Whether it's spacing, font size, or border radius, md is always your baseline and everything else scales from there.
This means fewer magic numbers to remember. p-md is medium padding. text-size-lg is large text. The naming tells you the intent.
Mathematical Foundations
Those t-shirt sizes are derived from base numbers and scale ratios, not arbitrary pixel values. Change one variable and the entire system recalculates proportionally.
The size system uses a base of 32px and a scale of 2:
--size-xs= 8px (base / scale / scale)--size-sm= 16px (base / scale)--size-md= 32px (base)--size-lg= 64px (base * scale)--size-xl= 128px (base * scale * scale)--size-2xl= 256px (base * scale * scale * scale)
Want tighter spacing? Change --size-scale to 1.5. Want larger steps? Try 2.5. The math handles the rest.
Control Height
Form inputs, selects, and buttons share a fixed height via --control-height (default 40px). This ensures uniform alignment when controls sit side by side, like a search input next to a button. This value is a deliberate design choice, not derived from the size scale.
One Type Scale
Axiom has a single type scale controlled by two variables: --text-base (the base font size, default 16px) and --type-scale (the ratio between steps, default 1.25 -- a Major Third).
Sizes from --text-md to --text-4xl derive from these two values. Change --type-scale to 1.2 for tighter steps or 1.333 for more dramatic ones. The entire upper hierarchy recalculates.
--text-xs (12px) and --text-sm (14px) are fixed rather than derived. Scaling downward from a base produces values that shrink to unusable sizes when the scale is increased -- a caption at 7px helps nobody. These values match the industry standard and sit above the 12px accessibility floor. Override them directly if your project needs different values.
There is no separate "responsive" or "fixed" type system. A heading is a heading everywhere. If you want headings to scale fluidly with their container, the utility layer provides a .headings-fluid class that uses container query units. But by default, sizes are fixed and predictable.
Line Height System
Line heights are explicit named values, not mathematically derived. Larger text generally needs tighter line-height, and smaller text needs more breathing room, but we let you choose rather than calculating it.
The available values are: --line-height-none (1), --line-height-tight (1.1), --line-height-snug (1.3), --line-height-normal (1.5), --line-height-relaxed (1.625), and --line-height-loose (1.8).
In the base layer, headings use tight or snug line-heights, body text uses normal, and you can override any of them with utility classes.
Letter Spacing
Four em-based tokens control character spacing. Em units ensure the spacing scales proportionally with font size, so the same token works correctly on both a 48px headline and a 12px label.
--letter-spacing-tight(-0.025em) -- tightens display text--letter-spacing-normal(0) -- browser default--letter-spacing-wide(0.05em) -- opens up small text--letter-spacing-wider(0.1em) -- for uppercase labels, badges, overlines
Color System
Colors are defined in OKLCH, a perceptually uniform color space. Each of the six chromatic hues (red, orange, yellow, green, blue, purple) has five hand-tuned shades with lightness and chroma values chosen for clean results across the full range. Each hue shares a single --{color}-hue variable, so you can rotate an entire ramp in one edit. Individual lightness and chroma values can be tweaked freely per shade.
Neutrals use OKLCH too, with two tuneable knobs: --neutral-hue controls warmth (try 60 for warm, 260 for cool) and --neutral-chroma controls saturation (0 for true gray, 0.02 for tinted). The invertible semantic tokens for backgrounds, text, and borders all derive from these same knobs.
Invertible Semantic Tokens
The i- prefixed tokens are the heart of Axiom's theming. They define semantic roles rather than specific colors:
- Backgrounds:
i-bg-floor,i-bg-surface,i-bg-raised,i-bg-float - Text:
i-text-strong,i-text-regular,i-text-soft - Borders:
i-border-strong,i-border-regular,i-border-soft
These tokens invert automatically when you add a .dark class to your HTML element. In light mode, i-bg-floor is the darkest background; in dark mode, it becomes the lightest. Your markup stays the same.
Background tokens represent elevation: floor is the base layer, surface sits above it, raised elements come next, and float is for modals and tooltips. This spatial metaphor works regardless of whether "higher" means lighter or darker.
Contrast Matrix
Every text and border token shown against every background. Toggle dark mode to see how they invert.
Text on backgrounds
Borders on backgrounds
Accent Color
The --i-accent token provides a single interactive color for links, buttons, and focus rings. It defaults to --blue-500 in light mode and --blue-300 in dark mode. Override it to match your brand.
Status Colors
Four semantic status palettes handle callouts, alerts, badges, and form validation. Each status has three tokens: background, text, and border. They auto-invert with .dark just like the rest of the system.
- Info:
--i-status-info-bg,--i-status-info-text,--i-status-info-border - Success:
--i-status-success-bg,--i-status-success-text,--i-status-success-border - Warning:
--i-status-warning-bg,--i-status-warning-text,--i-status-warning-border - Error:
--i-status-error-bg,--i-status-error-text,--i-status-error-border
In light mode these use light tinted backgrounds with dark text. In dark mode they invert to dark tinted backgrounds with light text. The utility layer exposes each token as a class:
Override any token in your own CSS to re-skin a status. For example, setting --i-status-info-bg to a purple tint turns all info callouts purple, in both light and dark mode.
Mark (Highlight)
The <mark> element uses invertible tokens too: --i-mark-bg and --i-mark-text. In light mode it uses yellow-100 on yellow-900; in dark mode these invert. Here is an example of highlighted text that adapts to either theme automatically.
Font Stacks
Axiom includes modern system font stacks that load instantly because they use fonts already on your device. Options include transitional serifs, humanist sans, geometric sans, monospace for code, and more.
Set your defaults with --font-family-default and --font-family-heading, or use the stacks directly via utility classes.
Customizing Config
The recommended approach is to edit config.css directly. This is your design system. Some starting points:
- Change
--neutral-hueto shift your grays warm (60) or cool (260) - Adjust
--type-scalefor more or less dramatic heading sizes - Rotate any hue variable (e.g.
--blue-hue) or fine-tune individual shade lightness and chroma - Swap
--font-family-defaultto a different stack
Because everything derives from these tokens, your changes propagate consistently throughout your project.
A Note on Units
The size system defaults to 32px, which gives a comfortable spatial baseline for layout and spacing. The type system uses its own 16px base (1rem), keeping text and space independent. If you prefer working in rems, you can change the base values accordingly and the calculations will produce rem-based results throughout.