Design system
Colors
Palette roles, automatic shades, transparencies and the page background.
A palette in sitereal is a handful of roles, not a list of hexes. You set the role; the module generates the shades, the transparencies and the parts that read them.

The roles
| Group | Roles |
|---|---|
| Main | primary, secondary, tertiary, accent, base, neutral |
| Semantic | success, warning, info, danger |
| Endpoints | white, black |
Each role can be switched off; an inactive role emits nothing. base is the neutral a site's text and surfaces are built from — it is the one to get right first.
What one role emits
:root {
--primary: #c50041;
--primary-h: 340;
--primary-s: 100%;
--primary-l: 39%;
--primary-100: #ffe5ee;
--primary-200: #ffb3cc;
--primary-300: #ff0055;
--primary-400: #80002a;
--primary-500: #330011;
--primary-600: #9e0035;
--primary-10: rgba(197, 0, 65, 0.1);
/* … the ramp continues to --primary-90 */
}- Hue, saturation and lightness are emitted separately, so you can build a color of your own from a role's hue:
hsl(var(--primary-h) 40% 96%). - Shades are computed from fixed lightness stops (
-100at 95%,-200at 85%,-300at 50%,-400at 25%,-500at 10%), and-600is the hover — the color itself nudged a step, which usually lands between-300and-400. Any single shade can be overridden by hand without giving up the rest. - Transparencies are the same color at a ramp of alphas — the honest way to tint something over an image.
White and black get no shade strip (there is nowhere left for white to go but darker, which is another color's job) but do get transparencies.
Unified lightness
Optionally, every role's shades can be forced to the same lightness stops, so --primary-300 and --danger-300 sit at the same brightness. It is what makes a set of badges look like a set.
The page background
The background of the page is a color, so it is edited here, beside the palette it is picked from — not on a "site" page somewhere else. It is emitted on body, together with the running text settings from Typography.
Spending them
Anywhere a color is asked for, the picker offers your variables and these tokens, each resolved to what it actually is. Picking one writes var(--primary), never the hex it happens to resolve to today.
A color is decided by its value, not by its name. --white is a color and says so nowhere in its name; --accent-h: 12 is a number that reads like one. The pickers look at values, which is why they get both right.