The tokens everything else is built from: the colour scale, the type system and the grid of space.
In Ingot a colour is not written as a value but as a role. The accent has four, and each answers a different question:
--accent — the colour itself. Actions, filled buttons, icons, the focus ring; it is also a text colour, so it has to stay readable on surfaces.--accent-ink — the darker step of the accent. Hover on actions, and the colour of links.--accent-bg — the tint under a selected row, a badge and a callout. Never text.--accent-border — the accent line, the outline of that tint. Decorative; it carries no information on its own.A screen reaches for the variable, never the value. That is what makes both the family and the theme swappable without touching screens.
The accent is one of four colour roles a screen takes through a variable — never as a hex. There are five families and they differ only in the values of those four variables; a component never knows which one is in effect.
| Family | Value | --accent | --accent-ink | --accent-bg | --accent-border |
|---|---|---|---|---|---|
| blue | blue | ||||
| emerald | emerald | ||||
| orange | orange | ||||
| violet | violet | ||||
| slate | slate |
Every family carries its own light and dark values, so switching the theme re-resolves it on its own — the switcher in the left column shows this in both themes. In the application the family is picked in the account menu and remembered by the account, not by the browser. Inside a shop, that shop's own colour takes precedence.
The values in the column are read at runtime from the palette currently in effect — switching the theme on the left rewrites them. A screen therefore always reaches for the token name, never the value.
| Token | Value | What for | |
|---|---|---|---|
--bg | — | The page surface. | |
--surface | — | Cards, tables. | |
--surface-2 | — | Headers, hover. | |
--surface-3 | — | Tracks, fills. | |
--border | — | The default line. | |
--border-strong | — | Inputs, active. | |
--ink | — | Text, primary button. | |
--ink-2 | — | Body text. | |
--ink-3 | — | Secondary. | |
--ink-4 | — | Tertiary, disabled. |
| Token | Value | What for | |
|---|---|---|---|
--accent | — | Actions, focus. | |
--accent-ink | — | Hover, links. | |
--accent-bg | — | Selection, callout. | |
--accent-border | — | The accent line. |
| Token | Value | What for | |
|---|---|---|---|
--ok | — | Active, done. | |
--ok-bg | — | The tint underneath. | |
--warn | — | Pending, at the limit. | |
--warn-bg | — | The tint underneath. | |
--danger | — | Error, stop. | |
--danger-bg | — | The tint underneath. |
Every state also has a tint variant. Without it a badge with a state tint cannot be built: the saturated token is the text in it, and the surface underneath has to be a colour of its own, not a weakened version of the first.
The scale has eight steps, each with a name and a fixed value — a size is never picked by eye. The sample on the left is set in exactly the classes the row names.
The sans face carries speech, mono carries facts: numbers, codes, dimensions and identifiers. Tabular figures keep digit above digit, so amounts in a column can be compared by eye.
| Sample | Step | Size / weight | Classes |
|---|---|---|---|
| Manufacturing partners | Page title | 40 / 600 | text-h1 text-ink |
| Pricing formulas | Section heading | 26 / 600 | text-h2 text-ink |
| Machine parameters | Subheading | 18 / 600 | text-h3 text-ink |
| A setting that propagates into every quote. | Lede | 17 | text-lede text-ink-2 |
| The ordinary text in panels and field labels. | Body text | 14,5 | text-body text-ink-2 |
| Secondary information, the hint under an input. | Small text | 13 | text-small text-ink-2 |
| Section · uppercase | Eyebrow | 11 / 500 | text-eyebrow uppercase text-ink-3 |
| 128 640 CZK · S235JR · 3.0 mm · 1 380 pcs | Number | mono | font-mono tabular-nums text-body text-ink |
Spacing runs in four-pixel steps. No smaller step exists — two adjacent values you cannot tell apart by eye are not two values. The square below is exactly the size its label names.
s-1 · 4pxs-2 · 8pxs-3 · 12pxs-4 · 16pxs-5 · 24pxs-6 · 32pxs-7 · 48pxRadius grows with the element: small badges take the smallest, cards and frames the largest. The full circle is reserved for avatars and dots.
rounded-sm · r-xs · 4pxrounded · r-sm · 6pxrounded-md · r-md · 10pxrounded-lg · r-lg · 14pxrounded-full · 999pxA shadow says how high above the page an element sits. Three steps are enough: each has its floor and is not used outside it.
--shadow-smCards on the page and their hover.
--shadow-mdDropdown menus and the modal.
--shadow-lgThe side panel and toasts.
Layers sit at fixed levels so overlays do not outbid each other case by case. The gap between content blocks is 24 px.
| Layer | Level |
|---|---|
| Content | 0 |
| Sticky toolbar | 30 |
| Header | 40 |
| Side panel | 80 |
| Modal | 90 |
| Toast | 100 |
Motion has one duration and one curve across the system. A dialog, a drawer, a toast and a menu therefore open at the same speed — and when that speed should change, it changes in one place.
--dur — 0.22 s. Long enough to show where a panel came from; short enough not to be waited on.--ease — a curve that leaves quickly and lands softly. Linear motion reads as mechanical.