Modes
Ragnar ships three modes — light, dim, and dark — controlled entirely by the data-mode attribute. Mode swapping is a single attribute change with zero JavaScript on the critical path.
Overview
A mode is the second layer of Ragnar's token architecture. It decides what the --backgrounds-* and --foregrounds-* tokens resolve to, plus the per-palette --<palette>-main / -background / -tint / -foreground / -shade mappings. Themes consume those tokens to color components.
The three modes
Light
Cool monochrome — backgrounds run from mono-0 (pure white) through mono-400, foregrounds from mono-950 down through mono-400. The default for most users who haven't expressed a preference.
Dim
Warm low-contrast — backgrounds and foregrounds both come from the teak palette instead of mono. The result is a sepia / parchment feel that's easier on the eyes than full light mode without going all the way to dark. Per-palette aliases shift up one shade (e.g. --maitai-main: var(--color-maitai-600) instead of 500) to keep accent colors readable on the warmer backgrounds.
Dark
Inverted monochrome — backgrounds run from mono-800 down to mono-950 (with mono-700/600 for elevated surfaces), foregrounds from mono-0 (pure white) down through mono-400. Palette aliases invert their dark / light roles — --<palette>-background is now the darkest shade (950), and --<palette>-foreground is the lightest (50).
How it works
Mode-aware tokens are CSS custom properties scoped by attribute selector. There's no class-toggle, no .dark selector duplication, no JS necessary at render time. data-mode on any ancestor cascades through.
Setup
Set data-mode on the <html> element for a global default:
With next-themes
Use next-themes with attribute="data-mode"so its switcher writes Ragnar's mode attribute directly:
System preference
Pass enableSystem to next-themes and it will watch the OS preference and apply light or dark automatically. Dim is opt-in — the OS only signals light or dark, not warm-low-contrast.
Scoped mode
Because data-mode works on any ancestor, you can scope a single section to a different mode without touching the rest of the page. Useful for a darkened hero inside an otherwise light layout, or a dim-mode reading view: