@motion-proto/live-tokens 0.55.1 → 0.57.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.
Files changed (107) hide show
  1. package/.claude/skills/{live-tokens-adjust-shape-space → live-tokens-adjust-geometry}/SKILL.md +5 -5
  2. package/.claude/skills/live-tokens-build-page/SKILL.md +2 -0
  3. package/.claude/skills/live-tokens-create-component/SKILL.md +20 -357
  4. package/.claude/skills/live-tokens-create-component/references/fixed-overlays.md +3 -0
  5. package/.claude/skills/live-tokens-create-component/references/intrinsics.md +58 -0
  6. package/.claude/skills/live-tokens-create-component/references/linked-siblings.md +70 -0
  7. package/.claude/skills/live-tokens-generate-theme/SKILL.md +79 -98
  8. package/.claude/skills/live-tokens-generate-theme/references/named-themes.md +18 -0
  9. package/.claude/skills/live-tokens-pair-fonts/SKILL.md +88 -0
  10. package/.claude/skills/live-tokens-pick-component/SKILL.md +4 -1
  11. package/CHANGELOG.md +197 -0
  12. package/README.md +21 -8
  13. package/bin/cli.mjs +42 -3
  14. package/bin/set-fonts.mjs +280 -0
  15. package/dist-plugin/adjust/index.cjs +1 -0
  16. package/dist-plugin/adjust/index.d.cts +3 -3
  17. package/dist-plugin/adjust/index.d.ts +3 -3
  18. package/dist-plugin/adjust/index.js +1 -1
  19. package/dist-plugin/{chunk-TKZBVIW5.js → chunk-E5QYON4L.js} +59 -2
  20. package/dist-plugin/{chunk-PB2JTK2H.js → chunk-LW4SR7AZ.js} +39 -6
  21. package/dist-plugin/{chunk-YR6GPXW2.js → chunk-XWXIMTWZ.js} +0 -5
  22. package/dist-plugin/{chunk-D3ZVKOR4.js → chunk-Y5CNFSSV.js} +1 -0
  23. package/dist-plugin/{dataPaths-DBN0RPuT.d.cts → dataPaths-CRfD1LdA.d.cts} +3 -0
  24. package/dist-plugin/{dataPaths-DBN0RPuT.d.ts → dataPaths-CRfD1LdA.d.ts} +3 -0
  25. package/dist-plugin/fontPairing/index.cjs +413 -0
  26. package/dist-plugin/fontPairing/index.d.cts +109 -0
  27. package/dist-plugin/fontPairing/index.d.ts +109 -0
  28. package/dist-plugin/fontPairing/index.js +321 -0
  29. package/dist-plugin/generateColorsAndType/index.cjs +22 -9
  30. package/dist-plugin/generateColorsAndType/index.d.cts +3 -3
  31. package/dist-plugin/generateColorsAndType/index.d.ts +3 -3
  32. package/dist-plugin/generateColorsAndType/index.js +8 -5
  33. package/dist-plugin/index-4N-Orzzi.d.cts +3 -0
  34. package/dist-plugin/index-4N-Orzzi.d.ts +3 -0
  35. package/dist-plugin/index.cjs +158 -9
  36. package/dist-plugin/index.d.cts +1 -1
  37. package/dist-plugin/index.d.ts +1 -1
  38. package/dist-plugin/index.js +71 -4
  39. package/dist-plugin/migrateData/index.cjs +1 -0
  40. package/dist-plugin/migrateData/index.d.cts +1 -1
  41. package/dist-plugin/migrateData/index.d.ts +1 -1
  42. package/dist-plugin/migrateData/index.js +1 -1
  43. package/dist-plugin/{index-DpTIRZ2H.d.cts → themeTypes-DSV3Zisf.d.cts} +13 -4
  44. package/dist-plugin/{index-DpTIRZ2H.d.ts → themeTypes-DSV3Zisf.d.ts} +13 -4
  45. package/dist-plugin/tokensCssMigrations/index.cjs +58 -1
  46. package/dist-plugin/tokensCssMigrations/index.d.cts +1 -1
  47. package/dist-plugin/tokensCssMigrations/index.d.ts +1 -1
  48. package/dist-plugin/tokensCssMigrations/index.js +3 -3
  49. package/package.json +5 -2
  50. package/src/editor/core/fonts/applyFontPairing.ts +158 -0
  51. package/src/editor/core/fonts/fontLoader.ts +1 -0
  52. package/src/editor/core/fonts/fontMigration.ts +31 -1
  53. package/src/editor/core/fonts/fontPairing.ts +13 -6
  54. package/src/editor/core/fonts/googleFontsUrl.ts +123 -0
  55. package/src/editor/core/fonts/weightCoverage.ts +92 -0
  56. package/src/editor/core/palettes/paletteDerivation.ts +9 -2
  57. package/src/editor/core/sketch/maskField.ts +381 -0
  58. package/src/editor/core/sketch/sketchLayer.ts +1028 -0
  59. package/src/editor/core/sketch/sketchPresetService.ts +65 -0
  60. package/src/editor/core/sketch/sketchPresets.ts +328 -0
  61. package/src/editor/core/sketch/sketchStore.ts +190 -0
  62. package/src/editor/core/store/editorPersistence.ts +28 -12
  63. package/src/editor/core/store/editorTypes.ts +4 -1
  64. package/src/editor/core/store/editorViewStore.ts +2 -2
  65. package/src/editor/core/store/gradientSource.ts +15 -1
  66. package/src/editor/core/themes/parsers/gradient.ts +62 -4
  67. package/src/editor/core/themes/slices/gradients.ts +75 -14
  68. package/src/editor/core/themes/themeTypes.ts +6 -1
  69. package/src/editor/docs/Docs.svelte +4 -3
  70. package/src/editor/docs/chapters.ts +1 -0
  71. package/src/editor/docs/content/01-overview.md +2 -1
  72. package/src/editor/docs/content/editing-tokens.md +5 -1
  73. package/src/editor/docs/content/sketch-mode.md +89 -0
  74. package/src/editor/docs/content/themes-workflow.md +39 -0
  75. package/src/editor/docs/content.generated.ts +4 -3
  76. package/src/editor/overlay/LiveEditorOverlay.svelte +15 -0
  77. package/src/editor/pages/EditorShell.svelte +43 -0
  78. package/src/editor/ui/EditorViewSwitcher.svelte +15 -2
  79. package/src/editor/ui/FontStackEditor.svelte +3 -0
  80. package/src/editor/ui/GradientEditor.svelte +38 -1
  81. package/src/editor/ui/ProjectFontsSection.svelte +24 -36
  82. package/src/editor/ui/UIReveal.svelte +7 -1
  83. package/src/editor/ui/UISegmentedControl.svelte +4 -8
  84. package/src/editor/ui/sections/GradientsSection.svelte +47 -1
  85. package/src/editor/ui/sketch/SketchDial.svelte +124 -0
  86. package/src/editor/ui/sketch/SketchPreview.svelte +119 -0
  87. package/src/editor/ui/sketch/SketchRange.svelte +185 -0
  88. package/src/editor/ui/sketch/SketchTab.svelte +1263 -0
  89. package/src/live-tokens/data/colors-and-type/autumn.json +17 -0
  90. package/src/live-tokens/data/colors-and-type/default.json +17 -0
  91. package/src/live-tokens/data/colors-and-type/halloween.json +17 -0
  92. package/src/live-tokens/data/colors-and-type/midnight-study.json +17 -0
  93. package/src/live-tokens/data/colors-and-type/ocean.json +17 -0
  94. package/src/live-tokens/data/colors-and-type/royal-velvet.json +17 -0
  95. package/src/live-tokens/data/colors-and-type/sketches.json +2520 -0
  96. package/src/live-tokens/data/colors-and-type/spring-meadow.json +17 -0
  97. package/src/live-tokens/data/colors-and-type/sunset.json +17 -0
  98. package/src/live-tokens/data/themes/autumn.json +17 -0
  99. package/src/live-tokens/data/themes/halloween.json +17 -0
  100. package/src/live-tokens/data/themes/midnight-study.json +17 -0
  101. package/src/live-tokens/data/themes/ocean.json +17 -0
  102. package/src/live-tokens/data/themes/royal-velvet.json +17 -0
  103. package/src/live-tokens/data/themes/sketches.json +3984 -0
  104. package/src/live-tokens/data/themes/spring-meadow.json +17 -0
  105. package/src/live-tokens/data/themes/sunset.json +17 -0
  106. package/src/live-tokens/data/tokens.generated.css +1 -0
  107. package/src/system/styles/tokens.css +15 -2
@@ -1,22 +1,24 @@
1
1
  ---
2
2
  name: live-tokens-generate-theme
3
- description: Generate a complete live-tokens color theme from a natural-language mood brief by choosing 10 OKLCH seeds and running the packaged generator, which enforces AA contrast automatically. Use when the user asks for a color theme, color scheme, or palette by mood, vibe, season, holiday, or hue — make me a bright and cheerful theme, give me a dark and moody night theme, a St. Patrick's Day theme with green and gold, a Christmas theme, a red-based theme, make it warmer, more contrast, a calmer palette. Changes color assignments only, never fonts. Not for editing a single token (use the editor) or building pages (see live-tokens-build-page).
3
+ description: Generate a complete live-tokens theme (color, type, and geometry) from a natural-language mood brief. Chooses 10 OKLCH seeds and runs the packaged generator, which enforces AA contrast, then carries the same brief into a font pairing and a geometry through the sibling skills. Use whenever the user asks for a theme, a look, a vibe, a brand feel, a color scheme, or a palette, by mood, season, holiday, or hue, even if they only mention color: make me a bright and cheerful theme, a dark moody night theme, a St. Patrick's Day theme in green and gold, a Christmas look, something red-based, warmer, more contrast, calmer. Not for a single token (use the editor), for type alone (live-tokens-pair-fonts), or for geometry alone (live-tokens-adjust-geometry).
4
4
  ---
5
5
 
6
6
  # Generating a theme from a mood brief
7
7
 
8
- You translate the brief into 10 OKLCH seed colors plus a scheme; the CLI does everything else (curve assembly, AA contrast enforcement with auto-correction, writing the theme, opening it). Never hand-author theme JSON and never edit the data tree directly. Seeds in, valid theme out.
8
+ A theme is three decisions made from one brief: color, type, and geometry. This skill owns the color decision directly and delegates the other two, so the whole look comes from the same reading of the brief. Never hand-author theme JSON and never edit the data tree directly.
9
9
 
10
10
  ## Workflow
11
11
 
12
- 1. Translate the brief into a seed file using the framework below. Write it to a temp path (not the project tree), e.g. `/tmp/theme-brief.json`.
13
- 2. Run `npx live-tokens generate-theme /tmp/theme-brief.json`. It writes `themes/<slug>.json`, opens that theme, and prints a contrast report card. Exit 1 means unmet floors.
14
- 3. Read the report. Auto-corrections are fine (the engine adjusted text curves to hit the floors). Unmet floors mean the seeds themselves are unworkable; each failure line says which seed to adjust (usually raise the seed's lightness or cut chroma). Fix the brief and re-run — same name, same file, it overwrites.
15
- 4. Tell the user to look at the running app. Offer refinements ("warmer", "more contrast", "less saturated") as seed adjustments to the same brief, re-run.
12
+ 1. Read the brief once and name its voice in a sentence: the mood, the hue family, the scheme, and the type and geometry that mood implies. Everything below keys off that sentence.
13
+ 2. Translate the brief into a seed file using the framework below. Write it to `scratch/theme-brief.json`.
14
+ 3. Run `npx live-tokens generate-theme scratch/theme-brief.json`. It writes `themes/<slug>.json`, opens that theme, and prints a contrast report. Auto-corrections are fine. Unmet floors (exit 1) mean the seeds themselves are unworkable; each failure line names the seed to change, usually by raising its lightness or cutting its chroma. Fix the brief and re-run; the same name overwrites. Regeneration replaces that theme's whole color state, including palette edits made in the editor since the last run, so say so once when iterating.
15
+ 4. Invoke **live-tokens-pair-fonts** with the same voice. Skip only when the user asked for colors specifically and said to leave the type alone.
16
+ 5. Invoke **live-tokens-adjust-geometry** with the geometry the voice implies (table below). Skip when the voice implies nothing about geometry.
17
+ 6. Tell the user to look at the running app, and that type and geometry sit in the unsaved buffer until they save the open theme. Offer refinements as edits to the same brief.
16
18
 
17
- Flags: `--dry-run` prints the report without writing; `--no-activate` writes the theme without opening it. Opening a theme never changes what the site ships: only Adopt, in the editor, does that.
19
+ Order matters only for safety, and the order above is safe: the color generator carries the live buffers forward into the new theme file, so a color re-roll after fonts and geometry keeps both.
18
20
 
19
- Warn once per session when iterating: regeneration replaces the whole color state of that theme, including any manual palette tweaks made in the editor after the last generation.
21
+ Flags: `--dry-run` prints the report without writing; `--no-activate` writes without opening. Opening a theme never changes what the site ships. Only Adopt, in the editor, does that.
20
22
 
21
23
  ## The brief
22
24
 
@@ -28,140 +30,119 @@ Warn once per session when iterating: regeneration replaces the whole color stat
28
30
  "Brand": { "l": 0.62, "c": 0.17, "h": 145 },
29
31
  "Accent": { "l": 0.80, "c": 0.15, "h": 95 },
30
32
  "Special": { "l": 0.60, "c": 0.19, "h": 300 },
31
- "Canvas": { "l": 0.97, "c": 0.01, "h": 120 },
33
+ "Canvas": { "l": 0.93, "c": 0.04, "h": 120 },
32
34
  "Neutral": { "l": 0.55, "c": 0.012, "h": 140 },
33
35
  "Alternate": { "l": 0.58, "c": 0.009, "h": 60 },
34
36
  "Info": { "l": 0.60, "c": 0.15, "h": 255 },
35
37
  "Success": { "l": 0.60, "c": 0.16, "h": 150 },
36
38
  "Warning": { "l": 0.75, "c": 0.15, "h": 85 },
37
39
  "Danger": { "l": 0.58, "c": 0.20, "h": 25 }
38
- },
39
- "harmony": { "mode": "analogous" }
40
+ }
40
41
  }
41
42
  ```
42
43
 
43
- All 10 seeds are required. A seed may also be a `"#rrggbb"` hex string (converted for you). OKLCH: `l` 0–1 perceptual lightness, `c` chroma (0 grey, ~0.37 max), `h` hue degrees. `name` becomes the theme file slug, tidied to lowercase with hyphens and stripped of any leading underscore (those names are reserved); `"default"` is refused (protected package theme). `harmony` is an optional record of your reasoning; the seeds are ground truth. `canvasGradient` is an optional boolean — see "The canvas sky" below before setting it.
44
+ All 10 seeds are required; a seed may also be a `"#rrggbb"` string. OKLCH: `l` is 0 to 1 lightness, `c` is chroma (0 grey, about 0.37 max), `h` is hue in degrees. `name` becomes the file slug; `"default"` is refused. `canvasGradient` is an optional boolean, see below.
44
45
 
45
- Roles: **Brand** is the dominant chromatic identity; **Accent** the supporting color; **Special** the rare expressive tertiary; **Canvas** is the page background verbatim; **Neutral** drives all neutral surfaces and body text; **Alternate** is the second near-grey family; the four status colors are conventional signals.
46
+ Roles: **Brand** is the dominant chromatic identity; **Accent** the supporting color; **Special** the rare expressive tertiary; **Canvas** is the page background verbatim; **Neutral** drives neutral surfaces and body text; **Alternate** is the second near-grey family; the four statuses are conventional signals.
46
47
 
47
48
  ## Chroma budget: color is inversely proportional to area
48
49
 
49
50
  | Tier | Palettes | Chroma |
50
51
  |---|---|---|
51
- | Ground (~60% of every screen) | Canvas, Neutral, Alternate | C 0.005–0.03 |
52
- | Dominant chromatic (~30%) | Brand | C 0.10–0.20 |
53
- | Garnish (~10%) | Accent, Special | may exceed Brand; at most one at full saturation |
54
- | Conditional | Info, Success, Warning, Danger | C 0.12–0.19 |
52
+ | Ground (about 60% of every screen) | Canvas, Neutral, Alternate | C 0.005 to 0.03 |
53
+ | Dominant chromatic (about 30%) | Brand | C 0.10 to 0.20 |
54
+ | Garnish (about 10%) | Accent, Special | may exceed Brand; at most one at full saturation |
55
+ | Conditional | Info, Success, Warning, Danger | C 0.12 to 0.19 |
55
56
 
56
- A good theme reads as 3–4 hue families on screen, never 10. Neutral and Alternate stay near-grey, tinted toward the theme (Neutral near Brand's hue; Alternate offset +15–60° or as a warm/cool counterpoint), never pure C = 0.
57
+ A good theme reads as 3 or 4 hue families on screen, never 10. Neutral and Alternate stay near-grey but tinted toward the theme (Neutral near Brand's hue; Alternate offset 15 to 60 degrees, or a warm/cool counterpoint), never pure C = 0.
57
58
 
58
59
  ## Per-role bands
59
60
 
60
61
  | Seed | Light scheme | Dark scheme | Hue |
61
62
  |---|---|---|---|
62
- | Canvas | L 0.92–0.98, C 0.02–0.06 (see below) | L 0.15–0.28, C 0.01–0.05 | brand hue or its harmony slot |
63
- | Neutral / Alternate | L ≈ 0.55, C 0.008–0.02 | same | see chroma budget |
64
- | Brand | L 0.45–0.62, C 0.12–0.20 | L 0.70–0.83, C cut by ~⅓ | the brief's identity hue |
65
- | Accent | harmony slot, or ΔL ≥ 0.25 from Brand when the mode collapses hue distance | lighten/desaturate like Brand | harmony slot |
66
- | Special | most expressive; default = Brand hue +60° at ~65% of Brand's C | same transform | harmony slot |
67
- | Info | shared status L (0.55–0.65 light) | lighten like Brand | H 230–260 |
68
- | Success | shared status L | same | H 140–155 |
69
- | Warning | L ≥ 0.75 (vivid yellow must be light) | same | H 70–90 |
70
- | Danger | shared status L, C 0.15–0.20 | same | H 20–30 |
71
-
72
- - **The canvas carries the theme's identity — commit to it.** The page background is the largest area on screen and the strongest differentiator between themes; a timid canvas makes every theme look the same. Below C ≈ 0.015 at L ≥ 0.95 a tint is imperceptible: that near-white is a deliberate choice for clean/minimal briefs, never the default. Three escalating levels of commitment, matched to the brief:
73
- 1. *Tinted paper* (most UI briefs): a tint you can actually see — C 0.02–0.06, dropping L to 0.92–0.95 where the hue needs room.
74
- 2. *Colored ground* (expressive briefs): L 0.85–0.92 at C 0.05–0.10 — the page is unmistakably mint, parchment, sky.
75
- 3. *Full-color ground* (holiday and statement briefs): the canvas IS the theme color — a red Christmas page (0.40–0.48, C 0.12–0.16, H 25) with green and gold on it, an orange Halloween page. Keep canvas L ≤ ~0.48 or ≥ ~0.85 so text has somewhere to go; the contrast gate enforces legibility either way. A saturated background is a legitimate choice, not something to correct.
76
- - **Gamut note for light canvases**: blue tints cap very low at high L (H 264 at L 0.95 barely reaches C 0.03) — for a blue-leaning canvas, lower L instead of fighting the ceiling; yellow/green/cream hues tint generously at high L.
77
- - **When generating a set of themes, make the canvases pairwise distinct.** Any two Canvas seeds should differ noticeably in hue (at visible chroma) or in L. Two light themes both near (0.97, 0.01, anything) read as the same theme with different buttons. Dark canvases differentiate the same way: deep indigo, plum, and near-black violet are three different nights.
78
- - **Dark scheme is a transform, not just a dark Canvas**: every chromatic seed lightens to L ≈ 0.75–0.85 and drops about a third of its chroma. Saturated color vibrates on dark grounds.
79
- - **Equal lightness = equal weight**: give the four statuses one shared L; do the same for Brand vs Accent when they should balance.
80
- - Status hues never rotate with the harmony; only their L/C adapt to the mood.
63
+ | Canvas | L 0.92 to 0.98, C 0.02 to 0.06 | L 0.15 to 0.28, C 0.01 to 0.05 | Brand's hue or its harmony slot |
64
+ | Neutral, Alternate | L about 0.55, C 0.008 to 0.02 | same | per the chroma budget |
65
+ | Brand | L 0.45 to 0.62, C 0.12 to 0.20 | L 0.70 to 0.83, C cut by a third | the brief's identity hue |
66
+ | Accent | harmony slot, or at least 0.25 L from Brand when the mode collapses hue distance | lighten and desaturate like Brand | harmony slot |
67
+ | Special | most expressive; default Brand hue +60 at about 65% of Brand's C | same transform | harmony slot |
68
+ | Info | shared status L (0.55 to 0.65 light) | lighten like Brand | H 230 to 260 |
69
+ | Success | shared status L | same | H 140 to 155 |
70
+ | Warning | L 0.75 or higher (vivid yellow must be light) | same | H 70 to 90 |
71
+ | Danger | shared status L, C 0.15 to 0.20 | same | H 20 to 30 |
72
+
73
+ **The canvas carries the theme's identity, so commit to it.** The page background is the largest area on screen and the strongest difference between themes; a timid canvas makes every theme look the same. Below C 0.015 at L 0.95 a tint is imperceptible, which makes near-white a deliberate choice for clean or minimal briefs and never the default. Three levels of commitment:
74
+
75
+ 1. *Tinted paper* (most UI briefs): C 0.02 to 0.06, with L down to 0.92 where the hue needs room.
76
+ 2. *Colored ground* (expressive briefs): L 0.85 to 0.92 at C 0.05 to 0.10. The page is unmistakably mint, parchment, sky.
77
+ 3. *Full-color ground* (holiday and statement briefs): the canvas is the theme color, like a red Christmas page with green and gold on it. Keep canvas L at or below 0.48 or at or above 0.85 so text has somewhere to go; the contrast gate enforces legibility either way.
78
+
79
+ Also:
80
+
81
+ - Blue tints cap very low at high L (H 264 at L 0.95 barely reaches C 0.03): lower L for a blue canvas rather than fighting the ceiling. Yellow, green, and cream tint generously at high L.
82
+ - When generating a set of themes, make the canvases pairwise distinct in hue or in L. Two light themes both near (0.97, 0.01) read as one theme with different buttons.
83
+ - A dark scheme is a transform, not just a dark canvas: every chromatic seed lightens to L 0.75 to 0.85 and drops about a third of its chroma, because saturated color vibrates on dark grounds.
84
+ - Equal lightness reads as equal weight: give the four statuses one shared L, and do the same for Brand and Accent when they should balance.
85
+ - Status hues never rotate with the harmony; only their L and C adapt to the mood.
81
86
 
82
87
  ## Mood dials
83
88
 
84
- Empirically: pleasantness rises with lightness (strongly) and saturation (weakly); energy/arousal rises with saturation; drama/dominance rises with dark + saturated.
89
+ Pleasantness rises with lightness (strongly) and saturation (weakly); energy rises with saturation; drama rises with dark plus saturated.
85
90
 
86
91
  | Brief says | Dials |
87
92
  |---|---|
88
- | cheerful, bright, playful | light scheme; Brand/Accent L 0.7–0.9, C 0.15–0.22; warm hues 40–140 (yellow is the strongest joy hue) |
89
- | calm, serene, soft | light scheme; C 0.03–0.08 on everything chromatic; cool hues 140–260 |
90
- | energetic, bold | C ≥ 0.18 at L 0.55–0.65; red/orange/magenta |
91
- | dark, moody, dramatic, luxurious | dark scheme; Canvas L 0.15–0.25; purple, deep blue, crimson; keep working accents light per the dark transform, reserve dark-saturated color for one or two moments |
92
- | professional, trustworthy | blue 230–265, C 0.08–0.15; everything else muted |
93
- | warm / cool | hues 20–110 (plus pink 290–360) / hues 140–290 |
93
+ | cheerful, bright, playful | light; Brand and Accent L 0.7 to 0.9, C 0.15 to 0.22; warm hues 40 to 140 (yellow is the strongest joy hue) |
94
+ | calm, serene, soft | light; C 0.03 to 0.08 on everything chromatic; cool hues 140 to 260 |
95
+ | energetic, bold | C 0.18 or more at L 0.55 to 0.65; red, orange, magenta |
96
+ | dark, moody, dramatic, luxurious | dark; Canvas L 0.15 to 0.25; purple, deep blue, crimson; working accents stay light per the dark transform, with dark saturated color saved for one or two moments |
97
+ | professional, trustworthy | blue 230 to 265, C 0.08 to 0.15; everything else muted |
98
+ | warm / cool | hues 20 to 110 plus pink 290 to 360 / hues 140 to 290 |
94
99
 
95
- Avoid mid-lightness yellow-green (H 100–120 at L 0.5–0.7, C ≈ 0.1) unless the brief asks for olive/toxic.
100
+ Avoid mid-lightness yellow-green (H 100 to 120 at L 0.5 to 0.7, C about 0.1) unless the brief asks for olive or toxic.
96
101
 
97
- ## Gamut guardrails (don't request impossible seeds)
102
+ ## Gamut guardrails
98
103
 
99
- - Dark saturated yellow does not exist: H 90 at L 0.4 caps at C ≈ 0.08 and reads olive. Vivid yellow needs L ≥ 0.8. Brown = dark low-chroma orange.
100
- - Vivid light blue does not exist: H 264 at L 0.9 caps at C ≈ 0.05. Rich blue lives at L 0.40–0.55.
101
- - Teal/sky cap at C ≈ 0.15; a "vivid teal" is C 0.13–0.15.
102
- - Peak chroma anchors: red H20 C 0.25 @ L 0.63; orange H60 C 0.18 @ L 0.76; yellow H90 C 0.18 @ L 0.86; green H140 C 0.28 @ L 0.88; blue H264 C 0.28 @ L 0.50; magenta H320 C 0.31 @ L 0.65.
104
+ The engine clamps to gamut regardless; these keep your intent achievable rather than silently muted.
103
105
 
104
- The engine gamut-clamps regardless; these rules keep your *intent* achievable rather than silently muted.
106
+ - Dark saturated yellow does not exist: H 90 at L 0.4 caps at C 0.08 and reads olive. Vivid yellow needs L 0.8 or more. Brown is dark low-chroma orange.
107
+ - Vivid light blue does not exist: H 264 at L 0.9 caps at C 0.05. Rich blue lives at L 0.40 to 0.55.
108
+ - Teal and sky cap at C 0.15.
109
+ - Peak chroma anchors: red H20 C 0.25 at L 0.63; orange H60 C 0.18 at L 0.76; yellow H90 C 0.18 at L 0.86; green H140 C 0.28 at L 0.88; blue H264 C 0.28 at L 0.50; magenta H320 C 0.31 at L 0.65.
105
110
 
106
- ## Choosing the harmony mode
111
+ ## Harmony
107
112
 
108
- Modes and hue offsets from Brand: complementary +180; split-complementary +150/+210; triadic +120/+240; tetradic +60/+180/+240; square +90 steps; compound +30/+180/+210; analogous ±30; monochromatic same hue.
113
+ Hue offsets from Brand: complementary +180; split-complementary +150/+210; triadic +120/+240; tetradic +60/+180/+240; square +90 steps; compound +30/+180/+210; analogous plus or minus 30; monochromatic same hue.
109
114
 
110
- - Vague or single-adjective brief → monochromatic or analogous; differentiate Accent from Brand by L/C, not hue. Polished-UI default: Accent = Brand's hue at ~45% chroma, Special = +60° at ~65% chroma.
111
- - Brief names two colors → measure their hue gap and pick the matching mode (green + gold ≈ 60–90° → analogous/compound).
112
- - Drama or maximum contrast → complementary/triadic/tetradic; then never pair max-chroma text with a near-black ground; tone one side down.
115
+ - A vague or single-adjective brief takes monochromatic or analogous, with Accent separated from Brand by L and C rather than hue. The polished-UI default: Accent at Brand's hue and about 45% of its chroma, Special at +60 and about 65%.
116
+ - A brief naming two colors: measure their hue gap and pick the matching mode (green plus gold is 60 to 90 degrees, so analogous or compound).
117
+ - Drama or maximum contrast: complementary, triadic, or tetradic, and then tone one side down, since max-chroma text on a near-black ground vibrates.
113
118
 
114
- ## The canvas sky (optional page-background gradient)
119
+ ## Canvas sky and shadows
115
120
 
116
- The brief may set `"canvasGradient": true` to render the page background as a
117
- vertical gradient built from the Canvas ramp. The engine picks the stops itself
118
- (two ramp steps from the Canvas anchor on the scheme's safe side), so the
119
- choice you make is only *whether*, never *how*.
121
+ `"canvasGradient": true` renders the page background as a vertical gradient from the Canvas ramp. Default off. Turn it on only when the brief evokes atmosphere (sky, night, dusk, glow, underwater) or asks for a gradient outright; keep it off for crisp, flat, minimal, or corporate briefs and whenever in doubt, because a sky on every theme stops meaning anything. It needs a committed canvas (level 2 or 3); at the ramp edge the engine skips it and says so. Say why you enabled it in one line.
120
122
 
121
- Default **off**. Turn it on only when the brief evokes atmosphere: sky, night,
122
- dusk, dawn, sunset, glow, candlelight, underwater, depth — or when the user
123
- asks for a gradient outright. Keep it off for crisp, clean, flat, minimal, or
124
- corporate briefs, and whenever in doubt. Most themes should not have one; a sky
125
- that appears on every generated theme stops meaning anything. When you enable
126
- it, say why in one sentence when reporting back ("night brief → canvas sky").
123
+ Shadow opacity derives from Canvas lightness and re-derives on every run, so there is nothing to choose. When shadows read heavy or muddy, raise the Canvas seed's L.
127
124
 
128
- A sky needs a committed canvas: when the Canvas seed anchors at the ramp edge
129
- (near-white light canvas, near-black dark one) there is no room on the safe
130
- side and the engine skips the sky, saying so in the report. An atmospheric
131
- brief that wants one should already be at canvas commitment level 2–3.
125
+ ## Named themes
132
126
 
133
- ## Shadow weight follows the canvas
127
+ A holiday or season brief is a statement brief: commitment level 2 or 3, with the named color on the ground rather than only on the buttons. Read `references/named-themes.md` for the OKLCH anchors of Christmas, Halloween, St. Patrick's, Ocean, Sunset, Autumn, and Spring before seeding one.
134
128
 
135
- The engine sets the opacity of the `--shadow-*` scale from the Canvas seed's
136
- lightness and carries each shadow's geometry and color through untouched. A
137
- near-black shadow at 0.9 opacity is what a dark ground needs to show any
138
- shadow at all, and it punches a hole in paper, so opacity holds at 0.9 up to
139
- canvas L 0.5 and eases to 0.2 by L 0.9. There is nothing to choose: the report
140
- prints the derived value, and every regeneration re-derives it, so a brief
141
- iterated from a light canvas to a dark one gets its weight back.
129
+ ## Geometry from the voice
142
130
 
143
- When the user says the shadows read heavy, muddy, or dirty, the canvas is the
144
- lever. Raise the Canvas seed's lightness and the shadows lighten with it. A
145
- one-off override lives in the editor's Shadows tab and survives regeneration
146
- in everything except opacity.
131
+ The geometry lives in radius, padding, gap, and border width, and `live-tokens-adjust-geometry` knows the mechanics. Hand it the intent:
147
132
 
148
- ## Named themes (canonical OKLCH anchors)
149
-
150
- Holiday briefs are statement briefs — default to commitment level 2–3 above, not cream. The named colors go on the *ground*, not just the buttons.
151
-
152
- - **Christmas**: red (0.53, 0.21, 22) + green (0.46, 0.11, 155) + gold (0.77, 0.14, 91). Strongest form: a full red canvas (0.42, 0.14, 25) with green Brand and gold Accent on it (dark scheme). Softer form: evergreen canvas (0.35, 0.07, 160) or deep cream (0.95, 0.04, 85). Never a 50/50 red-green split — one owns the ground, the other highlights.
153
- - **Halloween**: pumpkin (0.70, 0.20, 46) + purple (0.51, 0.21, 313) + poison green (0.73, 0.20, 137). Strongest form: an orange canvas (0.45, 0.13, 55) with violet and poison-green accents; alternative: near-black violet canvas with pumpkin Brand. Dark scheme either way.
154
- - **St. Patrick's**: green (0.51, 0.13, 152) Brand, gold Accent, white/beige neutrals.
155
- - **Ocean**: deep blue (0.35, 0.08, 237) vs aqua (0.78, 0.12, 214); H 180–240.
156
- - **Sunset**: hues 90 → 320 through red, L falling 0.85 → 0.40.
157
- - **Autumn / Fall**: leaves and dry grass — canvas warm tan/parchment (0.87, 0.06, 80), rust Brand (0.55, 0.15, 40), golden Accent (0.75, 0.15, 85), moss/olive Special (0.55, 0.10, 120), warm brown neutrals H 50–70. Deep red H 25 welcome. **Spring**: pastels L 0.85–0.95, C 0.04–0.10, greens 130–150 / pinks 0–20, mint canvas.
133
+ | Voice | Geometry |
134
+ |---|---|
135
+ | playful, friendly, soft | rounder, a step airier; pill buttons when the brief is warm |
136
+ | luxurious, elegant, editorial | sharper corners, airier padding, thin borders |
137
+ | technical, dense, systematic | tighter spacing, small radius, square corners on containers |
138
+ | calm, minimal | leave geometry alone unless the brief says otherwise |
158
139
 
159
- ## Scope
140
+ ## What each step writes
160
141
 
161
- Fonts are never touched (they carry forward from the live look, as do component aliases and shadow geometry; shadow opacity is derived, see above). Swatch gradients (`--gradient-1..4`) carry forward when user-tuned; if they are absent or still stock, the engine rebuilds them from the new theme's families — you never author them. Radius is out of scope for generation. Shipping the theme stays a human action: Adopt, in the editor.
142
+ Color writes `themes/<slug>.json` and opens it. Type and geometry write the unsaved buffers, which the page already runs. One Save in the editor keeps all three; Adopt ships them. Component aliases and gradients carry forward from the live look into a generated theme; user-tuned gradients survive, stock ones rebuild from the new families.
162
143
 
163
144
  ## Verify
164
145
 
165
- - The CLI exits 0 and the report card shows every check ✓ (auto-corrected is fine).
166
- - The app (dev server running) shows the new theme after a reload; the editor's Theme panel names it.
167
- - If the user wants the previous look back, the CLI output names the theme that was open; load it from the Theme panel.
146
+ - The color CLI exits 0 with every check passing (auto-corrected is fine), and the two sibling skills report what they changed.
147
+ - The app (dev server running) shows the whole look after a reload, and the editor's Theme panel names the theme.
148
+ - To return to the previous look, load the theme the CLI output named from the Theme panel; that discards the buffers too.
@@ -0,0 +1,18 @@
1
+ # Named themes: canonical OKLCH anchors
2
+
3
+ Read this when the brief names a holiday, a season, or a natural scene. These
4
+ are starting points, not seeds to copy: apply the chroma budget, per-role bands,
5
+ and canvas commitment rules from SKILL.md on top of them.
6
+
7
+ Holiday briefs are statement briefs. Default to canvas commitment level 2 or 3,
8
+ never cream, and put the named color on the ground, not only on the buttons.
9
+
10
+ | Brief | Anchors (L, C, H) | Strongest form |
11
+ |---|---|---|
12
+ | Christmas | red (0.53, 0.21, 22), green (0.46, 0.11, 155), gold (0.77, 0.14, 91) | red canvas (0.42, 0.14, 25), green Brand, gold Accent, dark scheme. Softer: evergreen canvas (0.35, 0.07, 160) or deep cream (0.95, 0.04, 85). One of red or green owns the ground; never a 50/50 split. |
13
+ | Halloween | pumpkin (0.70, 0.20, 46), purple (0.51, 0.21, 313), poison green (0.73, 0.20, 137) | orange canvas (0.45, 0.13, 55) with violet and poison-green accents, or near-black violet canvas with pumpkin Brand. Dark scheme either way. |
14
+ | St. Patrick's | green (0.51, 0.13, 152) | green Brand, gold Accent, white or beige neutrals. |
15
+ | Ocean | deep blue (0.35, 0.08, 237), aqua (0.78, 0.12, 214) | hues held to 180 to 240. |
16
+ | Sunset | hues 90 to 320 through red | L falls 0.85 to 0.40 across the sweep. |
17
+ | Autumn | parchment canvas (0.87, 0.06, 80), rust Brand (0.55, 0.15, 40), gold Accent (0.75, 0.15, 85), moss Special (0.55, 0.10, 120) | warm brown neutrals H 50 to 70; deep red H 25 welcome. |
18
+ | Spring | pastels L 0.85 to 0.95, C 0.04 to 0.10 | greens 130 to 150, pinks 0 to 20, mint canvas. |
@@ -0,0 +1,88 @@
1
+ ---
2
+ name: live-tokens-pair-fonts
3
+ description: Choose and apply a Google Fonts pairing for a live-tokens theme by binding families to the --font-display, --font-sans, --font-serif, --font-mono and --font-editorial stacks. Use whenever the user asks to pair fonts, pick a typeface, change or set the fonts, or describes type by voice: give me a font pairing, what font should the headings use, make the type more editorial, friendlier, more technical, more elegant, a serif for headings, a display font for this theme, less generic type, match the fonts to the theme. Also invoked by live-tokens-generate-theme for the type half of a whole look. Changes type only, never color. Not for a single token (use the editor) or for color (see live-tokens-generate-theme).
4
+ ---
5
+
6
+ # Pairing fonts for a theme
7
+
8
+ You choose the families; the CLI verifies each against Google Fonts, builds the URL from the weights the family actually has, and writes the result into the unsaved buffer. Never hand-author font JSON and never edit the data tree directly. Google Fonts is the pool because it is freely licensable and loads by URL; other sources go in by hand through the editor's Project fonts section.
9
+
10
+ ## Workflow
11
+
12
+ 1. Choose the pairing with the framework below and write a brief to `scratch/font-brief.json`.
13
+ 2. Run `npx live-tokens set-fonts scratch/font-brief.json`. It prints each stack that moved, each family's real weights and URL, and the weights your typography tokens ask for that the family lacks.
14
+ 3. Read the report. A weight gap is a quality note: name it and offer an alternative only if it matters (a body face without 400 or 700 matters; a display face without 300 does not). A family not on Google Fonts fails the run; fix the spelling and re-run.
15
+ 4. Tell the user to reload and look, and that the edit is unsaved until they save the open theme.
16
+
17
+ State your reasoning when you propose the pairing: each face's form model and the matrix verdict, in one sentence, so the user can argue with the argument rather than only the result.
18
+
19
+ Flags: `--dry-run` reports without writing. `--no-verify` skips the network and requires an explicit URL per family; use it only offline with a URL in hand.
20
+
21
+ ## The brief
22
+
23
+ ```json
24
+ { "display": "Fraunces", "body": "Nunito Sans" }
25
+ ```
26
+
27
+ Every slot is optional and an omitted slot is left exactly as it is. `display` is `--font-display`, `body` is `--font-sans`; `serif`, `mono` and `editorial` exist when a theme needs them. `editorial` is `--font-editorial`, the long-reading face behind the `--editorial-*` text style: it tracks the body face until a theme repoints it, so set it only when essays and articles should not carry the body face. A slot may be `{ "name": "...", "url": "..." }` to pin an exact URL. Spell families as Google does; the CLI reports the canonical spelling back.
28
+
29
+ ## Choose the body face first
30
+
31
+ The body face is the anchor. It carries most of the words, and text faces survive small sizes where display faces do not. Pick it against the brief, then pick the display face against it. A body face must have regular, bold, and italic; low to moderate stroke contrast; open apertures; and a large x-height. A face failing any of these is a display face whatever its name says. Single-weight families are fine for `display` and disqualifying for `body`.
32
+
33
+ ## The font matrix: the decision rule
34
+
35
+ Classify each candidate on two layers. The **skeleton** is its form model; the **flesh** is its stroke contrast and serif treatment.
36
+
37
+ | Form model | Construction | Reads as |
38
+ |---|---|---|
39
+ | **Dynamic** | diagonal stress, open apertures, written origin | open, warm, humane, timeless |
40
+ | **Rational** | vertical stress, closed apertures, drawn not written | orderly, reserved, elegant, authoritative |
41
+ | **Geometric** | monolinear, circle-and-line | technical, modern, systematic, sober |
42
+
43
+ - **Same skeleton, different flesh: reliable.** Helvetica and Bodoni are both rational, one a linear sans and one a contrasting serif.
44
+ - **Same flesh, different skeleton: the failure case.** The two look alike on the surface and fight underneath. This is why two arbitrary sans-serifs so often clash.
45
+ - **Far apart on both: works, deliberately.** An unmistakable difference reads as a decision.
46
+
47
+ Many faces sit between columns. When one straddles, say so and lean on the voice table and the x-height check instead.
48
+
49
+ ## Voice
50
+
51
+ | Brief says | Type voice |
52
+ |---|---|
53
+ | editorial, literary, considered | dynamic serif display over a humanist sans body |
54
+ | elegant, luxurious, formal | rational high-contrast serif display; keep the body quiet |
55
+ | friendly, warm, approachable | dynamic sans on both sides, or a soft serif display |
56
+ | technical, systematic, precise | geometric or neo-grotesque sans; a mono for code |
57
+ | playful, informal | an expressive display face over a plain workhorse body |
58
+ | serious, institutional, trustworthy | rational sans body, rational serif display |
59
+ | quiet, minimal, unbranded | one superfamily across both slots |
60
+
61
+ Match the type to the same brief the color came from. A warm autumn palette under a cold geometric sans reads as two projects.
62
+
63
+ ## Shortcuts
64
+
65
+ These find an adequate pairing fast and skip the reasoning; use them when the brief is vague or the type should stay quiet.
66
+
67
+ - **A superfamily.** Google Fonts families with both sans and serif siblings: Alegreya, Ancizar, IBM Plex, Inria, Merriweather, Noto, PT, Roboto, Source.
68
+ - **One family across weights.**
69
+ - **Same designer or foundry.**
70
+ - **Serif display over sans body** when nothing else decides it.
71
+
72
+ ## Watch for
73
+
74
+ - **x-height parity.** Both faces are set from one size scale, so a small-x-height display face over a large-x-height body face gives a heading that looks weaker than its own body text. This is the one visual check that matters on screen; make it on the rendered page.
75
+ - **Print faces at small sizes.** Delicate serifs and high stroke contrast turn to mud below 16px.
76
+ - **Every family is a request.** Two is the target; three needs a reason.
77
+ - **Sets of themes:** no two share a display face or a body face.
78
+
79
+ ## Scope
80
+
81
+ Type only. Color, component aliases, shape, and the type scale are untouched: `set-fonts` moves families between stacks and nothing else, writing only the unsaved colors-and-type buffer. Save the theme to keep it, Adopt to ship it.
82
+
83
+ ## Verify
84
+
85
+ - The CLI exits 0 and names each stack that moved, before and after.
86
+ - Each URL reflects the family's real weights: a range for a variable family, an enumeration for a static one, a bare URL for a single-weight face.
87
+ - The app shows the new type after a reload, and the editor's Fonts section lists both families with their fallbacks intact.
88
+ - To revert, run the inverse brief, or load the open theme again to discard the buffer.
@@ -11,7 +11,7 @@ For composing a page once you've picked components, see [[live-tokens-build-page
11
11
 
12
12
  ## Catalogue
13
13
 
14
- Action: `Button`, `IconButton`. Input: `Input`. Selection: `SegmentedControl`, `TabBar`, `RadioButton`, `MenuSelect`, `Toggle`. Containers: `Card`, `CollapsibleSection`, `Dialog`. Messaging: `Callout`, `Notification`, `Tooltip`, `Badge`, `CornerBadge`. Display: `Table`, `Image`, `ImageLightbox`, `ProgressBar`, `SectionDivider`, `SideNavigation`, `CodeSnippet`.
14
+ Action: `Button`, `IconButton`, `InlineEditActions`. Input: `Input`. Selection: `SegmentedControl`, `TabBar`, `RadioButton`, `MenuSelect`, `Toggle`. Containers: `Card`, `CollapsibleSection`, `Dialog`, `Panel`. Messaging: `Callout`, `Notification`, `Tooltip`, `Badge`, `CornerBadge`. Display: `Table`, `Image`, `ImageLightbox`, `ProgressBar`, `SectionDivider`, `SideNavigation`, `CodeSnippet`.
15
15
 
16
16
  `CodeSnippet` is for a single-line command or value the user is meant to copy and paste back into a terminal (install commands, generated keys, ids). Click-to-copy with a brief "Copied" popover. Use it whenever your page asks the reader to *run* something, rather than just *read* it.
17
17
 
@@ -22,6 +22,7 @@ Both trigger an action and share the same six variants (primary, secondary, outl
22
22
  - `Button` carries a text label, optionally with a leading or trailing icon. Use it whenever the action needs a word to be unambiguous.
23
23
  - `IconButton` is icon-only and square. Use it for compact, space-constrained actions whose meaning is obvious from the glyph alone (toolbar controls, close/edit/delete affordances, card overflow menus). It has no text slot, so an `ariaLabel` is required for accessibility.
24
24
  - **Don't reach for `IconButton` when the icon's meaning isn't self-evident.** A labelled `Button` (or a `Button` with an icon) avoids the guessing game.
25
+ - `InlineEditActions` is the confirm-and-cancel pair that follows an inline edit (rename a row, edit a value in place). Use it rather than two loose `IconButton`s so every inline edit on the page resolves the same way.
25
26
 
26
27
  ## Single-selection family: SegmentedControl vs TabBar vs RadioButton vs MenuSelect
27
28
 
@@ -46,9 +47,11 @@ All four pick one option from a set. The right one depends on **option count**,
46
47
  | `Card` | Inline, always open | Default container for grouped content |
47
48
  | `CollapsibleSection` | Inline, toggleable | Progressive disclosure inside a longer page |
48
49
  | `Dialog` | Modal, blocks page | Confirmations, focused tasks the page can't continue around |
50
+ | `Panel` | Inline, fixed stage | A demo or preview surface whose height must not reflow |
49
51
 
50
52
  - Default to `Card`. It's the workhorse.
51
53
  - Reach for `CollapsibleSection` only when the content is *legitimately secondary* (advanced users open it; most skip). Don't use collapse as a styling choice when the content matters.
54
+ - `Panel` is a stage, not a content container. It pins its own height so what it shows can resize without moving the page, which is what a component preview or a live example needs and what article content does not. Content goes in `Card`.
52
55
  - **Don't use `Dialog` for routine forms.** Reach for it only when the page cannot meaningfully continue until the user decides (destructive confirmations, payment, sign-in). Routine forms go inline in a `Card`.
53
56
 
54
57
  ## Messaging family: Callout vs Notification vs Tooltip vs Badge
package/CHANGELOG.md CHANGED
@@ -1,5 +1,202 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.57.0 — A theme can be drawn by hand
4
+
5
+ ### Added
6
+
7
+ - **Sketch mode: a fourth editor view, beside Tokens, Colors and Components.**
8
+ It is an effect layer over the active theme, not a set of theme values. It
9
+ reads nothing from the theme and writes nothing back. Each component's fill
10
+ and outline are repainted onto `::before`/`::after` from the tokens that
11
+ component already owns (`--<component>-<variant>-surface`, `-border`,
12
+ `-radius`), the real background and border are hidden behind them, and both
13
+ are pushed around one shared noise field. Turning it off removes every trace.
14
+ While it is on it applies to the page behind the editor as well as to the
15
+ preview, because the layer is injected into every document `cssVarSync`
16
+ tracks. Scope is the `data-sketch` attribute, so it switches on for a whole
17
+ document root or for one preview container.
18
+ - **Seven shipped looks, and every dial behind them.** Pencil, Marker,
19
+ Whiteboard, Hatched, Dashed, Napkin and Dry marker, each a complete set of
20
+ settings with a blurb naming what it is. The dials sit under five headings:
21
+ **Border** (travel, wavelength, width, ink, pressure, pooling, dashes, a
22
+ second pass that either copies the first line or runs it through the pen again
23
+ on its own seed), **Fill** (solid or hatched, travel, per-instance offset,
24
+ rotation and scale), **Shape** (corner spread, and a corner travel that leans
25
+ the drawn box into a quadrilateral with no two sides parallel), **Icons and
26
+ SVG** (glyph travel and wavelength on their own scale, because a glyph is all
27
+ curves and needs more travel than a card's long straight edge), and **Noise**
28
+ (the shared displacement field's wavelength, roughness and waveform).
29
+ - **Ink coverage as a generated field.** The mask that thins a fill is a tiling
30
+ Perlin field rasterised to a greyscale PNG and applied with `mask-mode:
31
+ luminance`, rather than an `feTurbulence` primitive. Turbulence lands in a
32
+ narrow band around its own midpoint, so a dial walking a cut across 0 to 1
33
+ spends most of its travel outside the field and the rest reads as flat grey.
34
+ Generated, the tile is stretched onto its own measured range first, so Min and
35
+ Max always mean levels at every grain and octave count. The panel previews the
36
+ field at each stage: noise, output, blur.
37
+ - **Saved sketch presets.** Any set of dials saves under a name and reloads
38
+ later, as files under `<dataDir>/sketch-presets/` served by a new
39
+ `/api/sketch-presets` route on the dev plugin. A sketch look is a draft
40
+ effect, never part of a theme: it has no active/production pointer, it is not
41
+ adopted, and it never reaches `tokens.generated.css`. The shipped seven stay
42
+ in code, so the directory holds nothing but your own files.
43
+ - **A page can hand the layer its own elements.** The effect displaces boxes, so
44
+ a rule drawn as a `border` is not one of them. `--sketch-fill`,
45
+ `--sketch-stroke`, `--sketch-hatch-color` and `--sketch-radius` name what an
46
+ element should be drawn with, and `--sketch-icon-off: none` opts a subtree
47
+ out. The demo app's kit section draws its rules this way; the editor's own
48
+ overlay bar opts out, because the effect is for the page being designed and
49
+ not for the tool looking at it.
50
+ - **A Sketch mode chapter in the user guide.** It sits after Editing tokens and
51
+ covers the presets, the dials, and the `--sketch-*` properties a page uses to
52
+ hand the layer its own elements. Editing tokens itself now names all four
53
+ views; it had been describing two since the Colors view landed.
54
+ - **Sketches ships as an eighth preset theme.** A whole look built on the
55
+ effect: Cabin Sketch over Shantell Sans, square corners, and component
56
+ aliases tuned for a page that is drawn rather than rendered. Load it from the
57
+ Theme panel like any other preset. It stands on its own with Sketch mode off,
58
+ and the effect is what it was designed under.
59
+ - **The gradient library is open-ended.** `--gradient-N` was a fixed four-slot
60
+ scale; the Gradients section now has Add and Remove, and any number of
61
+ numbered slots loads from a theme file. A new slot seeds from the last one, so
62
+ it lands as a gradient you edit rather than an invisible transparent one.
63
+ - **A gradient can point at a corner.** Alongside degrees, a linear gradient
64
+ takes CSS's `to top right` and its seven neighbours. A keyword angles the
65
+ gradient line off the box's own diagonal, so it tracks the element's aspect
66
+ where a fixed angle cannot: `to bottom right` reads as about 95deg across a
67
+ wide heading and about 111deg once that heading wraps. The degrees underneath
68
+ are kept, so clearing the keyword lands on the nearest angle rather than
69
+ snapping to 0deg.
70
+ - **`--gradient-N-stops`.** Each slot now also emits its stop list on its own,
71
+ so a consumer can keep the theme's colours and supply their own geometry:
72
+ `linear-gradient(to top, var(--gradient-5-stops))`. One set of stops then
73
+ serves every direction a design needs, instead of a token per angle.
74
+ - **The editorial type role.** A fifth font stack (`--font-editorial`) and a
75
+ ninth text-style bundle (`--editorial-*`), for the long-reading surfaces that
76
+ should not carry the body face under an expressive display face. Both default
77
+ to indirections rather than literals: the stack resolves to `var(--font-sans)`
78
+ and the bundle mirrors `--body-md-*`, so a project that never mentions
79
+ editorial renders byte-identically. `live-tokens set-fonts` gained a matching
80
+ `editorial` slot, and the stack is editable in the editor beside the other
81
+ four.
82
+
83
+ ### Changed
84
+
85
+ - **Derived palette values serialize unclamped.** A palette's basis is OKLCH,
86
+ and clamping every derived step into sRGB on the way out threw away chroma a
87
+ wide-gamut display can show. Values already inside sRGB serialize identically,
88
+ so nothing moves in an existing theme; intent authored beyond sRGB now
89
+ survives to the browser, which does its own gamut mapping at paint. The hex
90
+ readouts still show the clamped projection, which is what a hex readout is
91
+ for.
92
+ - **The product is spelled LiveTokens.** One word, in the README, the docs and
93
+ the demo app. The package name is unchanged.
94
+ - **A test fails on any engine load at module top.** `bin/engineLoadsLazily.test.ts`
95
+ follows every `.mjs` module a test suite can reach, transitively, and rejects
96
+ a top-level import of the compiled engine. CI runs the suite before it builds
97
+ the plugin, so such a load is a publish failure rather than a test failure.
98
+ This is the bug that took down 0.56.0.
99
+
100
+ ### Fixed
101
+
102
+ - **A session persisted before the OKLCH palette basis no longer throws on
103
+ hydrate.** Such a session holds hex strings where every palette color is now
104
+ `{ l, c, h }`. `loadFromFile` migrated those on the way in and `hydrate` did
105
+ not, so the session reached the renderer with an undefined hue and threw on
106
+ the first serialization.
107
+ - **The overlay panel's chrome keeps its own font.** `tokens.css` sets the theme
108
+ font on `:where(*)`, and a matching rule beats inheritance, so the panel's
109
+ font-family never reached its children. The editor page already restored
110
+ inheritance for its chrome; the overlay now does the same.
111
+
112
+ ### Migration
113
+
114
+ - Two **tokens.css migrations** ship here, both additive: `--font-editorial`
115
+ with the `--editorial-*` bundle, and a `--gradient-N-stops` companion per
116
+ gradient slot. Each companion is read out of the slot it belongs to rather
117
+ than hardcoded, so a retuned gradient does not get a stop list contradicting
118
+ it. Run `npx live-tokens migrate` to apply them to a vendored `tokens.css`, or
119
+ set the plugin's `autoMigrate` option and let it apply additive migrations on
120
+ boot. Until then the dev plugin warns on the gap and the new names simply
121
+ resolve to nothing.
122
+ - The **editorial font stack** is added to a theme file on load, cloned from
123
+ that theme's `--font-sans`. It is presence-based and idempotent, so there is
124
+ no schema step and a theme that never touches editorial keeps rendering as it
125
+ did.
126
+
127
+ ## 0.56.1 — Release fix
128
+
129
+ ### Fixed
130
+
131
+ - **The 0.56.0 publish failed in CI and never reached npm.** `scripts/lib/presetFonts.mjs`
132
+ loaded the compiled font-pairing engine at import time, and a vitest suite
133
+ imports that module for its `PRESET_FONTS` table; CI runs the tests before
134
+ it builds the plugin. The engine now loads inside `stampPresetFonts`, the
135
+ one caller that needs it. Everything listed under 0.56.0 ships here.
136
+
137
+ ## 0.56.0 — Type is a first-class half of a theme
138
+
139
+ ### Added
140
+
141
+ - **`live-tokens set-fonts` and the `live-tokens-pair-fonts` skill.** A theme's
142
+ type can now be chosen the way its color already could: describe the voice you
143
+ want and get a verified Google Fonts pairing bound to `--font-display`,
144
+ `--font-sans`, `--font-serif` and `--font-mono`. The skill carries the
145
+ reasoning (anchor on the body face, classify both candidates by form model,
146
+ apply the font matrix, gate every candidate on screen legibility); the CLI
147
+ does the verifying and the writing. Like `adjust`, it edits the unsaved
148
+ colors-and-type buffer, so a retype is an edit you keep by saving the open
149
+ theme. Color, component aliases, `tokens.css` and `fonts.css` are untouched.
150
+ - **URLs are negotiated from the family's real weights, not guessed.** A 200
151
+ from the Google Fonts API never proved weight coverage: the API silently drops
152
+ enumerated weights a family lacks and only rejects a *range* its axis cannot
153
+ serve. `set-fonts` now takes a census from the returned CSS and builds the
154
+ narrowest URL that delivers everything the family has: a range for a variable
155
+ family, an enumeration for a static one, a bare URL for a single-weight
156
+ display face. It also reports the weights your typography tokens ask for and
157
+ the family does not have.
158
+ - **`generate-theme` owns the whole look.** A theme is three decisions made
159
+ from one brief: color, type, and geometry. The skill reads the brief once,
160
+ names its voice, seeds the color, then invokes `live-tokens-pair-fonts` and
161
+ `live-tokens-adjust-geometry` with the same voice, so a moody night theme
162
+ arrives with type and corners to match rather than with the previous look's.
163
+ The three CLIs stay separate, so any one decision retunes without re-rolling
164
+ the others.
165
+
166
+ ### Changed (breaking)
167
+
168
+ - **`live-tokens-adjust-shape-space` is now `live-tokens-adjust-geometry`.**
169
+ Same skill, same `adjust` verb; the name now matches the heading the token
170
+ suffix vocabulary already uses for radius, padding, gap, and border width.
171
+ Re-run `npx live-tokens setup-claude --force` to pick it up, then delete
172
+ `.claude/skills/live-tokens-adjust-shape-space/` by hand: `setup-claude`
173
+ never removes a directory, and the stale copy would keep triggering under
174
+ the old name.
175
+
176
+ ### Changed
177
+
178
+ - **Skills are leaner and read the package instead of copying it.** The
179
+ create-component skill no longer inlines the shipped `Toggle` (the copy had
180
+ drifted 174 lines from its source); it points at the files in
181
+ `node_modules` and moves the linked-siblings, intrinsics, and fixed-overlay
182
+ material into reference files read on demand. The theme skill moved its
183
+ holiday anchors the same way. Every skill body is now under 250 lines.
184
+ - **The picker catalogue lists `Panel` and `InlineEditActions`.** Both shipped
185
+ without an entry, so the picker could never recommend them.
186
+ - **`npm run check:skills` gates the bundle.** It asserts the catalogue names
187
+ every shipped component, every reference file is pointed at and present,
188
+ every CLI verb a skill mentions exists, every skill has a sample prompt, and
189
+ no skill pastes a long file inline.
190
+
191
+ ### Fixed
192
+
193
+ - **Adding a Google font by name in the editor no longer persists a dead URL.**
194
+ The by-name field built a `wght@100..900` range URL and never checked it, so
195
+ any family without that exact variable axis (every static family, every
196
+ single-weight display face) was saved with a URL the API answers 400 to. It
197
+ now runs the same negotiation `set-fonts` does, reports the family's real
198
+ weights, and fails loudly for a family that is not on Google Fonts.
199
+
3
200
  ## 0.55.1 — The anchored step is the base color
4
201
 
5
202
  ### Fixed