@motion-proto/live-tokens 0.72.1 → 0.73.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: live-tokens-build-page
3
- description: Apply the @motion-proto/live-tokens project conventions when building a page: shipped components, theme tokens over hex/pixel literals, dynamic route mounting, per-page site.css. Use when the user asks to build, create, or lay out a page, route, hero, landing page, dashboard, settings screen, or pricing page; add a route; place an existing component on a page; or assemble a screen from the catalogue. For component choice see live-tokens-pick-component; for a brand-new component, live-tokens-create-component; for look and feel mid-build, live-tokens-generate-theme or live-tokens-adjust-geometry.
3
+ description: Apply the @motion-proto/live-tokens project conventions when building a page: shipped components, theme tokens over hex/pixel literals, dynamic route mounting, per-page site.css. Use when the user asks to build, create, lay out, or rearrange a page, route, hero, landing page, dashboard, settings screen, pricing page, or a tool screen with a stage and controls; add a route; place an existing component on a page; assemble a screen from the catalogue; or says the layout, label sizes, or control sizes of a page are off. For component choice see live-tokens-pick-component; for a brand-new component, live-tokens-create-component; for look and feel mid-build, live-tokens-generate-theme or live-tokens-adjust-geometry.
4
4
  ---
5
5
 
6
6
  # Building pages in a live-tokens project
@@ -16,10 +16,40 @@ Text inside a `Card` or a `CollapsibleSection` is typed by that container, not b
16
16
 
17
17
  ## Layout
18
18
 
19
+ **The purpose of a layout.** The page shows one thing. All other content must stay out of its way. Each mark that is not content costs attention: a rule, a border, a header bar, a shadow. Each mark must do a job that no other mark does.
20
+
21
+ Separate elements with the smallest difference that separates them. Use space first. If space is not sufficient, add a hairline rule. If a rule is not sufficient, use a second surface. Do not stack these separators. Two heavy edges side by side make a third shape between them. A band of boxes with borders and header bars looks like a set of posters.
22
+
23
+ Put each element in one of three layers, and type it from that layer. Content is `--text-primary`. Labels are `--eyebrow-*` or `--text-secondary`. Scaffolding is `--border-neutral`.
24
+
25
+ Show related items side by side when the width permits. Do not put them behind a toggle.
26
+
27
+ On a tool page, the stage is the content. Each control is administration. Give the space to the stage. Give the controls the smallest size that still works.
28
+
29
+ `references/layout-sources.md` names the sources for these laws.
30
+
31
+ Decide the bands before the columns. Read the page top to bottom and name each band by its job: what the user looks at, what they type into, what they press. A content page runs hero, sections, footer. A tool page runs the stage on top (the canvas, player, or strip the work is about), the inputs under it, and one toolbar of actions along the bottom edge. Each band is a row of the page grid; a band that needs columns of its own spans the grid and redeclares it, as below.
32
+
33
+ Separate bands with space and a rule, `padding-top: var(--space-16)` and `border-top: var(--border-width-1) solid var(--border-neutral)`, and stretch a band's boxes to one height (`align-items: stretch`) so their bottom edges make one line. Card chrome does not separate bands.
34
+
19
35
  Pages sit inside the column grid via `--columns-count`, `--columns-gutter`, `--columns-max-width`. The columns button in the overlay's header (the vertical-lines icon) draws the grid over the page while you place content.
20
36
 
21
37
  To place children at specific page-column positions, span the parent grid (`grid-column: 1 / -1`), redeclare `repeat(var(--columns-count), 1fr)` with `--columns-gutter`, then refer to children by real page-column numbers. Never fabricate a local `repeat(N, 1fr)` with a hardcoded count: the widths drift from the page grid and the numbers stop matching `ColumnsOverlay`.
22
38
 
39
+ ### Containers by job
40
+
41
+ - `Panel` is a stage: a canvas, a player, a preview. It pins its height so the page holds still while what it shows changes.
42
+ - `Card` is a titled block of content. Its header is typed by the card's own tokens, `--card-default-title-*` at `--font-size-2xl` with a body at `--font-size-xl` by default; `size="compact"` drops the title to md, the body to sm, and tightens the padding. That is a content card's voice, and the theme editor retunes it for the whole project.
43
+ - A box in a tool UI labels itself. Use `variant="bare" size="compact"` and put your own label in the body, typed from a text style: the `.eyebrow` class from `site.css` for a quiet section label, `.heading-sm` for one that leads. Leave the shipped header alone rather than shrinking it with a page rule.
44
+ - A toolbar is a flex row of small buttons on the band's bottom edge, grouped left and right with `justify-content: space-between`. No card around it.
45
+
46
+ ### Density
47
+
48
+ - `Button` and `IconButton` take `size="small"` in toolbars, compose rows, and any band that holds more than a couple of actions; the default size is for the page's primary action. `fullWidth` belongs to a stacked rail and comes off in a row.
49
+ - A project component that wraps shipped buttons forwards a `size` prop to them, so a page sets density the same way for shipped and custom pieces.
50
+ - Text in your own elements inside a `Card` inherits the card's body size unless you type it. A label, count, or status line inside a card sets a text style of its own (`--body-sm-*`, `--code-*`).
51
+ - `MenuSelect` renders its list open. For a picker, toggle it from a small `Button` with a trailing chevron (`icon="fa-solid fa-chevron-down" iconPosition="right"`) and position the list absolutely under the button, `top: 100%` with a `--space-*` margin.
52
+
23
53
  ## Wiring
24
54
 
25
55
  - Add the route the way `App.svelte` already wires routes:
@@ -48,6 +78,7 @@ const pages = {
48
78
  - Colour literals, and px or rem in spacing, stroke, radius, or shadow.
49
79
  - Hardcoded page-grid counts (`repeat(10, 1fr)`). Use `repeat(var(--columns-count), 1fr)`, or `calc(var(--columns-count) - 2)` for a sub-grid that spans fewer page columns. A local two-up or three-up is a layout and is fine.
50
80
  - Utility classes overriding shipped components. Extend via the `/live-tokens/components` editor instead.
81
+ - A card header as a section label in a tool UI, and a page rule that shrinks it. Label the box yourself with a text style.
51
82
  - Deep imports from `node_modules/@motion-proto/live-tokens/src/...`. Use public entry points only.
52
83
  - Mounting `Editor` or `ComponentEditorPage` outside their dedicated routes.
53
84
  - A page route under `/live-tokens/*`. That namespace is reserved for the package's own dev surfaces so they can never shadow your routes; the rest of the URL space is yours.
@@ -65,4 +96,8 @@ It fails on a component outside the catalogue, a prop or value the component doe
65
96
 
66
97
  Warnings do not fail the run. `--strict` makes them fail, which is the setting to use when the page is meant to be fully tokenized. `--json` prints findings with a stable `rule` id, so you can work through one rule at a time and re-run. `--off=<rule>` silences a rule for a run; `"checks": { "rules": { ... } }` in `live-tokens.config.json` sets it for the project. A project scaffolded by `create` runs the checker, with `check-component`, as `npm run check:design` before every `vite build`, so the page has to pass before it can ship.
67
98
 
99
+ The checker cannot see a layout. Open the page at the width it is built for and read it band by band: the boxes in a band end on one line, no label is larger than the page's body copy, every control stays inside its box (a `width: 100%` field without `box-sizing: border-box` pushes past it by its padding), and the actions sit where the eye goes last. Fix what you see before you move on.
100
+
101
+ Then look at the page from a distance. The bands and their edges must be the only shapes that you see. Then look closely. For each border, header bar, and box, ask this question: does the page lose information if this element is removed? If the answer is no, remove the element. Find the element that a reader sees first, second, and third. Make sure that this is the reading order the page needs.
102
+
68
103
  Then in dev: change a colour in `/live-tokens/editor` and confirm your page repaints (proves token usage). The overlay's "Page Source" button on the new route opens the page in VS Code (proves the route's `source`). The columns overlay shows content sitting inside `--columns-max-width`.
@@ -0,0 +1,48 @@
1
+ # Layout sources
2
+
3
+ Read this when a layout decision in SKILL.md needs its reason. Each law in the
4
+ Layout section comes from one of these sources. The sources are for layout and
5
+ hierarchy only. Do not take color or type opinions from them: the theme owns
6
+ those.
7
+
8
+ ## Edward Tufte
9
+
10
+ Tufte wrote about information graphics. His laws apply to a page because a page
11
+ is an information display with controls on it.
12
+
13
+ | Law | Statement | Rule in SKILL.md |
14
+ |---|---|---|
15
+ | Smallest effective difference | Make all visual distinctions as subtle as possible, but still clear and effective. | Separate with space first, then a hairline rule, then a second surface. |
16
+ | 1+1=3 | Two heavy marks side by side make a third mark: the space between them. | A band of boxes with borders and header bars looks like a set of posters. |
17
+ | Layering and separation | Put data on top, labels next, and scaffolding faintest. | Content, labels, and scaffolding each take their own token. |
18
+ | Administrative debris | The metaphor for the interface is the information. Remove the chrome that the tool adds for itself. | The stage takes the space. Controls take the smallest size that still works. |
19
+ | Spatial over temporal | Show information adjacent in space, not stacked in time behind controls. | Show related items side by side. Frames in a strip are small multiples. |
20
+ | Erase non-data ink | Remove each mark that carries no information. | The Verify question: does the page lose information if this element is removed? |
21
+ | Micro and macro readings | A good display reads at a distance and up close. | Verify from a distance, then closely. |
22
+
23
+ Sources:
24
+
25
+ - Envisioning Information (1990): layering and separation, small multiples, micro and macro. https://www.edwardtufte.com/book/envisioning-information/
26
+ - The Visual Display of Quantitative Information (1983): data-ink, chartjunk.
27
+ - iPhone interface design, edwardtufte.com notebook: administrative debris, spatial over temporal. https://www.edwardtufte.com/notebook/iphone-interface-design/
28
+
29
+ ## Josef Müller-Brockmann
30
+
31
+ Grid Systems in Graphic Design (1981) is the discipline behind the page column
32
+ grid. The grid does the separating, so an element needs no border to show
33
+ where it sits. His stated aim is compact planning, intelligibility, and
34
+ clarity. That is Tufte's aim in a typographer's words.
35
+
36
+ ## Refactoring UI
37
+
38
+ Adam Wathan and Steve Schoger, Refactoring UI (2018), turns both into working
39
+ rules for product screens:
40
+
41
+ - Put more space around a group than within it.
42
+ - Start with too much white space, then remove some.
43
+ - Use fewer borders. Separate with space, a shadow, or a second background.
44
+ - Emphasize by de-emphasizing the secondary content.
45
+ - Labels are a last resort.
46
+ - Keep a spacing scale where no two steps are closer than a quarter. The `--space-*` scale is that scale.
47
+
48
+ https://www.refactoringui.com/
@@ -39,7 +39,7 @@ All four pick one option from a set. The right one depends on **option count**,
39
39
  | `SegmentedControl`| Inline switch between alternative *views of the same data* | Compact pill | 2–4 |
40
40
  | `TabBar` | Switching between *tab panels* (content area swaps below) | Page-section | 2–7 |
41
41
  | `RadioButton` | Form-style selection where the user reviews all options as text | Form-row | Any |
42
- | `MenuSelect` | Hide the option set behind a dropdown to save vertical/horizontal space | Compact dropdown | Any |
42
+ | `MenuSelect` | A list of options, one checked; renders open, so a dropdown toggles it from a `Button` | Open list | Any |
43
43
 
44
44
  - `TabBar` implies "this changes the page"; `SegmentedControl` implies "this is one knob among others."
45
45
  - Use `RadioButton` when labels deserve room to breathe and the user is committing to a larger form.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,55 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.73.0 — The skill atlas ships from the package
4
+
5
+ ### Added
6
+
7
+ - **A public export for the skill atlas, `@motion-proto/live-tokens/skill-atlas`.**
8
+ The atlas is a Svelte component that diagrams the reasoning tree behind each
9
+ bundled skill, with the source `SKILL.md` and its reference files alongside
10
+ so a reader can see which lines drive which step. It carries no route of its
11
+ own; a consumer mounts it wherever it likes. `live-tokens-online` is its
12
+ first consumer, mounting it at its existing `/skills` route. Skill text
13
+ reaches the component through a generated module built from `.claude/skills`
14
+ and gated by `check:skill-sources`; the trees each carry a digest of the
15
+ `SKILL.md` they cite and are gated by `check:skill-atlas`. Both run in
16
+ `prepublishOnly`.
17
+
18
+ ### Changed
19
+
20
+ - **`live-tokens-build-page` lays out the page before it places columns.**
21
+ The Layout section opens with bands: name each by its job, put a tool
22
+ page's stage on top and its toolbar along the bottom edge, separate bands
23
+ with space and a rule, and stretch a band's boxes to one height. Two new
24
+ subsections follow. *Containers by job* says what `Panel`, `Card`, a bare
25
+ compact `Card` with its own text-style label, and a toolbar are each for,
26
+ and that a card header is typed by the card's own tokens at 2xl. *Density*
27
+ covers `size="small"` in toolbars and compose rows, forwarding `size` from
28
+ a project component, text inside a card body inheriting the card's size,
29
+ and toggling `MenuSelect` from a `Button`. Verify now asks for a look at
30
+ the page band by band, since the checker cannot see a layout. The gap
31
+ came from a studio page whose card headers, buttons, and inherited body
32
+ text all ran large with every check green; `docs/build-page-gap-analysis.md`
33
+ records it.
34
+
35
+ - **`live-tokens-build-page` opens Layout with the laws behind its rules.**
36
+ A short block before the bands states what a layout is for: the page
37
+ shows one thing, each mark that is not content must do a job no other mark does,
38
+ separate with the smallest difference that separates (space, then a
39
+ hairline rule, then a second surface), rank content, labels, and
40
+ scaffolding on their own tokens, show related items side by side, and
41
+ give a tool page's space to the stage. Verify adds a look from a distance,
42
+ a removal question for each border and header bar, and a check of the
43
+ reading order. The laws are Tufte's (smallest effective difference,
44
+ 1+1=3, layering and separation, administrative debris), with
45
+ Müller-Brockmann and Refactoring UI as the working restatements;
46
+ `references/layout-sources.md` in the skill names each source and where
47
+ it lands.
48
+
49
+ - **`live-tokens-pick-component` says `MenuSelect` renders open.** The
50
+ selection table called it a compact dropdown; the shipped component is a
51
+ list, and a dropdown is a `Button` that toggles it.
52
+
3
53
  ## 0.72.1 — The compliance skills have a spine
4
54
 
5
55
  ### Changed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@motion-proto/live-tokens",
3
- "version": "0.72.1",
3
+ "version": "0.73.0",
4
4
  "type": "module",
5
5
  "description": "Design token editor with live CSS variable editing. Svelte 5 + Vite 8.",
6
6
  "keywords": [
@@ -101,6 +101,11 @@
101
101
  "svelte": "./src/editor/docs/Docs.svelte",
102
102
  "default": "./src/editor/docs/Docs.svelte"
103
103
  },
104
+ "./skill-atlas": {
105
+ "types": "./src/editor/skill-atlas/SkillAtlas.svelte.d.ts",
106
+ "svelte": "./src/editor/skill-atlas/SkillAtlas.svelte",
107
+ "default": "./src/editor/skill-atlas/SkillAtlas.svelte"
108
+ },
104
109
  "./backdrop": {
105
110
  "svelte": "./src/system/backdrop/index.ts",
106
111
  "types": "./src/system/backdrop/index.ts",
@@ -154,15 +159,17 @@
154
159
  "check:token-contract": "node scripts/check-token-contract.mjs",
155
160
  "check:preset-themes": "node scripts/check-preset-themes.mjs",
156
161
  "check:skills": "node scripts/check-skills.mjs",
162
+ "check:skill-sources": "node scripts/sync-skill-sources.mjs --check",
157
163
  "check:skill-atlas": "node scripts/sync-skill-atlas.mjs",
158
164
  "sync:component-defaults": "node scripts/sync-component-defaults.mjs --write",
159
165
  "sync:docs": "node scripts/sync-docs.mjs --write",
166
+ "sync:skill-sources": "node scripts/sync-skill-sources.mjs --write",
160
167
  "sync:skill-atlas": "node scripts/sync-skill-atlas.mjs --write",
161
168
  "seed:preset-theme": "node scripts/seed-preset-theme.mjs",
162
169
  "collapse:theme": "node scripts/collapse-theme-to-default.mjs",
163
170
  "check:smoke-install": "bash scripts/smoke-install.sh",
164
171
  "check:smoke-create": "bash scripts/smoke-create.sh",
165
- "prepublishOnly": "npm run check:no-style-imports && npm run check:no-tooling-imports && npm run check:slot-prose && npm run check:overlay-portal && npm run check:editor-font-isolation && npm run check:component-defaults && npm run check:pages && npm run check:production-is-default && npm run check:docs-content && npm run build:lib && npm run check:token-contract && npm run check:preset-themes && npm run check:skills && npm run check:skill-atlas && npm run check:smoke-install && npm run check:smoke-create"
172
+ "prepublishOnly": "npm run check:no-style-imports && npm run check:no-tooling-imports && npm run check:slot-prose && npm run check:overlay-portal && npm run check:editor-font-isolation && npm run check:component-defaults && npm run check:pages && npm run check:production-is-default && npm run check:docs-content && npm run build:lib && npm run check:token-contract && npm run check:preset-themes && npm run check:skills && npm run check:skill-sources && npm run check:skill-atlas && npm run check:smoke-install && npm run check:smoke-create"
166
173
  },
167
174
  "peerDependencies": {
168
175
  "@sveltejs/vite-plugin-svelte": "^7.0",
@@ -16,6 +16,19 @@ npx @motion-proto/live-tokens setup-claude
16
16
  This copies the bundled skills into your project's `.claude/skills/`. Once
17
17
  they're there, Claude Code picks them up automatically.
18
18
 
19
+ ## Browse the skill atlas
20
+
21
+ The package also ships a Skill Atlas component: a diagram of the reasoning
22
+ behind each bundled skill, with its `SKILL.md` and reference files alongside
23
+ so you can see exactly which lines drive which step. Import it from
24
+ `@motion-proto/live-tokens/skill-atlas` and mount it on a route of your own:
25
+
26
+ ```js
27
+ '/skills': {
28
+ lazy: () => import('@motion-proto/live-tokens/skill-atlas'),
29
+ },
30
+ ```
31
+
19
32
  ## Ask for a component
20
33
 
21
34
  Describe what you want in plain English. Phrases like these trigger the skill:
@@ -3,7 +3,7 @@
3
3
 
4
4
  export const docContent: Record<string, string> = {
5
5
  "01-overview": "# Overview\n\nLiveTokens is a design system for building Svelte microsites quickly. You\nstyle your site by editing tokens and components in a live editor. When it looks right, you save the theme and ship it.\n\n## How it works\n\n- The editor runs in your dev server, on top of your real pages. You style in\n context, not in a separate sandbox.\n- Every change updates a CSS variable, so the page repaints instantly. No\n reload, no build step.\n- Saving writes a small JSON file into your project. Shipping bakes your chosen\n theme into a plain CSS file that the build bundles.\n- The editor is dev-only. Production ships plain CSS variables and the\n components you used, nothing else.\n\n## What you can edit\n\n- **Tokens**: the design-system primitives, colour palettes, type, spacing,\n radius, shadow, and gradients, that apply across your whole site.\n- **Components**: the package ships about 25 editable components (Button,\n IconButton, Card, Dialog, Table, and more). You style components by changing\n the tokens assigned to each property.\n\n## Where to go next\n\n- **[Getting started](getting-started.md)**: scaffold a project and make your\n first edit.\n- **[Editing tokens](editing-tokens.md)**: a tour of the editor.\n- **[Sketch mode](sketch-mode.md)**: redraw the page by hand.\n- **[Themes](themes-workflow.md)**: save, switch, and ship.\n- **[Creating components](creating-components.md)**: make your own components\n editable.\n",
6
- "creating-components": "# Creating components\n\nThe package ships about 25 editable components. When you need one it doesn't\nhave, you can make your own Svelte component editable, so anyone using the\neditor can re-point its colours, type, and spacing without touching code.\n\nThe simplest way is to ask Claude. The package bundles a Claude Code skill that\nknows the conventions, writes the files, and checks the result for you.\n\n## Install the skills\n\n```bash\nnpx @motion-proto/live-tokens setup-claude\n```\n\nThis copies the bundled skills into your project's `.claude/skills/`. Once\nthey're there, Claude Code picks them up automatically.\n\n## Ask for a component\n\nDescribe what you want in plain English. Phrases like these trigger the skill:\n\n- \"Add a Toggle component to live-tokens\"\n- \"Make this Svelte component editable in the live-tokens editor\"\n- \"Create a Stat component with a value and a label\"\n\nClaude asks any clarifying questions it needs (which variants, which states,\nwhich parts), then writes the component, registers it with the editor, and runs\nits verification checklist. When it finishes, open `/live-tokens/components` to see your new\ncomponent in the editor and confirm everything works.\n\n## What you get\n\n- A runtime component whose editable properties default to your theme tokens.\n- An editor entry that appears under **Custom** in the `/live-tokens/components` view.\n- The naming and wiring handled for you, so the component fits the system.\n\nAdvanced authors who want to write a component by hand can read the naming and\nstate-model conventions shipped in the package\n(`src/system/styles/CONVENTIONS.md` and the skill's own `SKILL.md`).\n",
6
+ "creating-components": "# Creating components\n\nThe package ships about 25 editable components. When you need one it doesn't\nhave, you can make your own Svelte component editable, so anyone using the\neditor can re-point its colours, type, and spacing without touching code.\n\nThe simplest way is to ask Claude. The package bundles a Claude Code skill that\nknows the conventions, writes the files, and checks the result for you.\n\n## Install the skills\n\n```bash\nnpx @motion-proto/live-tokens setup-claude\n```\n\nThis copies the bundled skills into your project's `.claude/skills/`. Once\nthey're there, Claude Code picks them up automatically.\n\n## Browse the skill atlas\n\nThe package also ships a Skill Atlas component: a diagram of the reasoning\nbehind each bundled skill, with its `SKILL.md` and reference files alongside\nso you can see exactly which lines drive which step. Import it from\n`@motion-proto/live-tokens/skill-atlas` and mount it on a route of your own:\n\n```js\n'/skills': {\n lazy: () => import('@motion-proto/live-tokens/skill-atlas'),\n},\n```\n\n## Ask for a component\n\nDescribe what you want in plain English. Phrases like these trigger the skill:\n\n- \"Add a Toggle component to live-tokens\"\n- \"Make this Svelte component editable in the live-tokens editor\"\n- \"Create a Stat component with a value and a label\"\n\nClaude asks any clarifying questions it needs (which variants, which states,\nwhich parts), then writes the component, registers it with the editor, and runs\nits verification checklist. When it finishes, open `/live-tokens/components` to see your new\ncomponent in the editor and confirm everything works.\n\n## What you get\n\n- A runtime component whose editable properties default to your theme tokens.\n- An editor entry that appears under **Custom** in the `/live-tokens/components` view.\n- The naming and wiring handled for you, so the component fits the system.\n\nAdvanced authors who want to write a component by hand can read the naming and\nstate-model conventions shipped in the package\n(`src/system/styles/CONVENTIONS.md` and the skill's own `SKILL.md`).\n",
7
7
  "editing-tokens": "# Editing tokens\n\nA tour of the editor. The page behind it repaints on every change; saving\nwrites a theme file you can reload later.\n\nThe editor has four views:\n\n- **Tokens**: the design-system primitives (colour, type, spacing, and so on).\n They apply everywhere your site uses them.\n- **Color Wheel**: the harmony wheel, the palette curves, and the story your colours\n tell across a page.\n- **Components**: per-component editors. Re-Assign what tokens a component uses\n without changing the underlying system.\n- **Sketchstyle**: an effect layer that redraws the page by hand. See\n [Sketch mode](sketch-mode.md).\n\nThis page covers **Tokens**. For components, see\n[Creating components](creating-components.md).\n\n## Palettes\n\nMost colour work happens here. Each palette (Brand, Accent, Neutral, Canvas,\nSuccess, Warning, Info, Danger, and a few more) has:\n\n- **Base colour.** Pick a hex; the palette derives an 11-step ramp (100 to 950)\n from it.\n- **Curves.** Three curves shape the ramp, in stack order: Hue, Saturation,\n Lightness. Drag the handles to bias it warmer or cooler, more or less\n saturated, darker or lighter. Hue drifts the ramp's temperature without\n moving contrast, because OKLCH hue rotation is close to lightness-preserving.\n It holds ±45 degrees; a bigger shift belongs on the base colour or the\n harmony axis.\n- **Overrides.** Lock a single step to a hand-picked hex when the curve doesn't\n land where you want.\n\nEditing a palette base ripples through every colour that depends on it, in real\ntime. Colours use OKLCH, so the ramp stays perceptually even across hues\nwithout muddy mid-tones.\n\n## Type\n\n- **Fonts.** Add sources from Google Fonts, Adobe (Typekit), a CSS URL, or an\n inline `@font-face`. The font loads in the page as soon as you add it.\n- **Stacks.** Named font cascades you reference by token, such as a display\n stack and a body stack.\n- **Sizes and weights.** A t-shirt scale (xs, sm, md, lg, xl, 2xl…) for size and\n a numeric scale (100 to 900) for weight.\n\n## Spacing, radius, shadow\n\nNumeric scales with a slider per step.\n\n- **Spacing**: the padding, gap, and margin scale.\n- **Radius**: none through full.\n- **Shadow**: colour, offset, blur, spread, and opacity per step, with stacked\n shadows supported.\n\nChange a step and every element using it repaints.\n\n## Washes and gradients\n\n- **Scrims** are translucent layers that dim what sits behind them, like the\n one a dialog draws over the page. Set a colour and opacity per stop.\n- **Tints** are the opposite operation: they shade the surface they sit on\n rather than dimming what is behind it, which is what a hover needs.\n- **Gradients** are reusable gradient tokens with a stop list and direction, for\n hero panels and accent backgrounds.\n\n## Columns\n\nThe page-grid overlay. Set column count, gutter, and outer margin, and toggle\nthe visual guide with `Cmd/Ctrl+G`. Pages built on the column system reflow\nlive.\n\n## Saving\n\nThe editor saves to your browser continuously, so work survives a reload\nmid-edit. Writing a file is a separate step: the **Theme** panel at the foot of\nthe sidebar has **Save**, **Save As**, and **Load**, and each theme is one JSON\nfile under `src/live-tokens/data/themes/`.\n\nThe header gives you undo/redo (`Cmd/Ctrl+Z`, `Cmd/Ctrl+Shift+Z`). You can keep\nmany themes side by side; one is open at a time, and only **Adopt** publishes\none. See [Themes](themes-workflow.md) for the full lifecycle.\n",
8
8
  "getting-started": "# Getting started\n\nScaffold a live token site in a moments. You need Node 20 or later, a\npackage manager (npm, pnpm, or yarn), and a browser. Open claude code in your repo and start building.\n\n## Scaffold a new app\n\n```bash\nnpm create @motion-proto/live-tokens@latest my-app\ncd my-app\nnpm install\nnpm run dev\n```\n\nOpen the URL Vite prints (usually `http://localhost:5173`). You get a\none-page Svelte + Vite app that depends on the published package, with the\neditor wired up and the full component set ready to import.\n\n`npx @motion-proto/live-tokens create my-app` runs the same scaffold without\nthe initialiser package.\n\n### What the scaffold gives you\n\nEvery editable file lives under `src/` and is committed, so `npm install` and\nversion upgrades never touch your styles. The package code stays in\n`node_modules`.\n\n| Path | What it is |\n|------|------------|\n| `src/pages/Home.svelte` | The starter page. Replace it with your own content. |\n| `src/App.svelte` | Your routes. `<LiveTokensRouter>` adds dev-only routes under a reserved `/live-tokens/*` namespace: `/live-tokens/editor`, `/live-tokens/components`, and `/live-tokens/docs`. |\n| `src/system/styles/tokens.css` | Your base token vocabulary, hand-authored. |\n| `src/styles/site.css` | Themed page typography, yours to edit. |\n\n## Your first edit\n\n1. Run `npm run dev` and open the home page.\n2. Click **Open Token Editor**, or visit `/live-tokens/editor`. The editor opens beside\n the page.\n3. Open **Palettes**, pick **Brand**, and change the base hex. The page\n repaints as you type.\n4. In the **Theme** panel at the foot of the sidebar, choose **Save As**. Your\n theme appears as JSON under `src/live-tokens/data/themes/`.\n5. Reload. The editor reopens on your theme, so the page returns as you left\n it.\n\n## What you just changed\n\nEvery edit sets a CSS custom property on `:root`. Your components read those\nproperties through `var(--...)`. There is no token build step and no\npreprocessor rewriting your code: the page renders against plain CSS variables\nthe editor swaps live.\n\nTo ship, click **Adopt** in the Theme panel. That saves the open theme and bakes\nit into `src/live-tokens/data/tokens.generated.css`, which your build bundles\nalongside `tokens.css`. Adopt is the only action that changes what your site\nships, so try any theme you like first. The editor itself never reaches\nproduction.\n\nAlready have a Svelte 5 + Vite app? The\n[README](https://github.com/motionproto/live-tokens#readme) covers installing\ninto an existing project.\n\n## Where to go next\n\n- **[Editing tokens](editing-tokens.md)**: a tour of the editor.\n- **[Themes](themes-workflow.md)**: save, switch, and ship.\n- **[Creating components](creating-components.md)**: make your own component\n editable.\n",
9
9
  "light-and-dark": "# Light and dark\n\nSome things on a page cannot be written as a token. A wordmark drawn in white\ndisappears on a pale theme. Ink that multiplies onto paper vanishes on a dark\none. A photograph behind a headline is dark no matter what the palette says.\n\nEach of those needs the same fact first: which way does the surface behind this\nthing lean? One attribute carries it.\n\n## The attribute\n\n`data-backdrop` is either `light` or `dark`, and it does two things at once: it\nselects, so a rule can key on it, and it sets `color-scheme`, so every\n`light-dark()` under it resolves the half that reads.\n\n```css\n.title {\n color: light-dark(var(--color-black), var(--color-white));\n}\n```\n\nThat line is right on both sides of the theme, and it is right inside a dark\nband on a pale page, because the nearest `color-scheme` wins.\n\n## Stating it\n\nPut it in the markup when the surface knows its own tone — a hero over a\nphotograph, a plate that stays pale in every theme:\n\n```svelte\n<div class=\"hero-panel\" data-backdrop=\"dark\">\n```\n\nA stated tone beats any measurement, and it inherits, so everything inside the\npanel resolves against it.\n\n## Measuring it\n\nWhere the tone is a property of the theme rather than of the markup, let it be\nmeasured:\n\n```svelte\n<script>\n import { backdrop } from '@motion-proto/live-tokens/backdrop';\n</script>\n\n<section use:backdrop>\n```\n\nThe action reads whatever actually paints behind the element — the nearest\nancestor with an opaque fill, averaged across its gradient stops, falling back\nto the theme's `--page-bg` — and stamps the answer. It re-reads when the theme\nchanges, which the editor does by rewriting custom properties with no reload,\nso the stamp follows a live edit.\n\nThe page itself is stamped for you: the build bakes the production theme's\npolarity into `tokens.generated.css`, so the first paint is already right, and\n`syncDocumentBackdrop()` keeps `<html>` current as themes switch.\n\n```ts\nimport { syncDocumentBackdrop } from '@motion-proto/live-tokens/backdrop';\n\nsyncDocumentBackdrop();\n```\n\n## Reading it from JavaScript\n\nAnything that paints outside CSS — a canvas, a WebGL uniform, an `<img>` that\ncomes in two versions — asks the same question through the same module:\n\n```ts\nimport { isLightBackdrop, watchBackdrop, cssColorToHex } from '@motion-proto/live-tokens/backdrop';\n\nconst stop = watchBackdrop(logoEl, {\n stamp: false,\n onChange: (polarity) => (src = polarity === 'light' ? darkMark : lightMark),\n});\n```\n\n`isLightBackdrop(el)` answers once. `watchBackdrop` keeps answering and returns\na stop function. `cssColorToHex` resolves any CSS colour — including the\n`oklch()` a token holds — to a hex a non-CSS consumer can take.\n\n## What it does not do\n\nPolarity is a property of a surface, not of a component, so nothing is stamped\nfor you below `<html>`: a section that needs an answer either states one or asks\nfor one. And a measurement reads the paint at the moment it runs — an element\nthat scrolls from a pale band onto a dark one keeps the answer it was given.\nState the tone on each band instead.\n",