@motion-proto/live-tokens 0.61.0 → 0.62.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 (36) hide show
  1. package/.claude/skills/live-tokens-build-page/SKILL.md +1 -1
  2. package/.claude/skills/live-tokens-pair-fonts/SKILL.md +1 -1
  3. package/CHANGELOG.md +73 -0
  4. package/dist-plugin/{chunk-OIOXU7FR.js → chunk-OPYOK2CA.js} +45 -25
  5. package/dist-plugin/index.cjs +45 -25
  6. package/dist-plugin/index.js +1 -1
  7. package/dist-plugin/tokensCssMigrations/index.cjs +45 -25
  8. package/dist-plugin/tokensCssMigrations/index.js +1 -1
  9. package/package.json +1 -1
  10. package/src/app/site.css +16 -0
  11. package/src/editor/component-editor/CardEditor.svelte +7 -1
  12. package/src/editor/component-editor/scaffolding/VariantGroup.svelte +25 -2
  13. package/src/editor/core/sketch/maskField.ts +70 -34
  14. package/src/editor/core/sketch/sketchLayer.ts +24 -3
  15. package/src/editor/core/sketch/sketchPresets.ts +10 -11
  16. package/src/editor/core/sketch/sketchStore.ts +89 -18
  17. package/src/editor/docs/content/sketch-mode.md +7 -2
  18. package/src/editor/docs/content.generated.ts +1 -1
  19. package/src/editor/overlay/LiveTokensRouter.svelte +8 -0
  20. package/src/editor/ui/sections/textStyles.ts +15 -1
  21. package/src/editor/ui/sketch/SketchTab.svelte +33 -81
  22. package/src/live-tokens/data/colors-and-type/midnight-study.json +40 -30
  23. package/src/live-tokens/data/themes/autumn.json +3 -3
  24. package/src/live-tokens/data/themes/halloween.json +3 -3
  25. package/src/live-tokens/data/themes/midnight-study.json +61 -49
  26. package/src/live-tokens/data/themes/ocean.json +3 -3
  27. package/src/live-tokens/data/themes/royal-velvet.json +3 -3
  28. package/src/live-tokens/data/themes/sketchy.json +3 -3
  29. package/src/live-tokens/data/themes/spring-meadow.json +3 -3
  30. package/src/live-tokens/data/themes/sunset.json +3 -3
  31. package/src/system/components/Card.svelte +27 -9
  32. package/src/system/components/ImageLightbox.svelte +5 -2
  33. package/src/system/components/SectionDivider.svelte +3 -3
  34. package/src/system/components/SegmentedControl.svelte +11 -9
  35. package/src/system/styles/tokens.css +13 -5
  36. package/template/src/pages/Home.svelte +1 -11
@@ -10,7 +10,7 @@ Two rules above all else:
10
10
  1. **Use a shipped component if one fits.** Import from `@motion-proto/live-tokens/components/<Name>.svelte`. See [[live-tokens-pick-component]] for the catalogue and the confusing-pair decisions. Author custom markup only when nothing fits, and then consider [[live-tokens-create-component]] so the new piece is editable too.
11
11
  2. **Use theme tokens for every value.** Every color, spacing, radius, font-size, and font-family in page CSS is a `var(--token-*)`. No hex literals. No pixel literals. A change in `/live-tokens/editor` should repaint your page.
12
12
 
13
- For text, reach for a whole text style rather than assembling one: `--heading-xl` through `--heading-sm`, `--body-md`, `--body-sm`, `--eyebrow`, and `--code` each carry a `-font-family`, `-font-size`, `-font-weight`, `-line-height`, and `-letter-spacing`. A heading set from `--heading-lg-*` retypes when the theme's fonts change; one set from a raw `font-size` does not.
13
+ For text, reach for a whole text style rather than assembling one: `--heading-xl` through `--heading-sm`, `--body-md`, `--body-sm`, `--editorial-md`, `--editorial-sm`, `--eyebrow`, and `--code` each carry a `-font-family`, `-font-size`, `-font-weight`, `-line-height`, and `-letter-spacing`. A heading set from `--heading-lg-*` retypes when the theme's fonts change; one set from a raw `font-size` does not.
14
14
 
15
15
  ## Layout
16
16
 
@@ -24,7 +24,7 @@ Flags: `--dry-run` reports without writing. `--no-verify` skips the network and
24
24
  { "display": "Fraunces", "body": "Nunito Sans" }
25
25
  ```
26
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.
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-md-*` and `--editorial-sm-*` text styles: 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
28
 
29
29
  ## Choose the body face first
30
30
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,78 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.62.0 — Editorial type reads as a pair
4
+
5
+ ### Added
6
+
7
+ - **The editorial role has its own sizes.** The role shipped with a single
8
+ unsized bundle, so an editorial surface could only take the body size. It now
9
+ reads as a pair, matching body: `--editorial-md-*` and `--editorial-sm-*`,
10
+ both editable in the editor's Text Styles section beside the other styles, and
11
+ both carried by an `.editorial-md` / `.editorial-sm` class in `site.css`. Each
12
+ step mirrors its body counterpart apart from the family, so a project that
13
+ never repoints `--font-editorial` renders exactly as it did.
14
+ - **`Card` takes `variant="bare"`.** A card with no icon and no title dropped
15
+ its header silently, which read the same as a card whose title had gone
16
+ missing. `bare` says the headerless card is the intent; the frame and body
17
+ keep every token the default variant uses, so padding, stroke and fill stay
18
+ editable. A default-variant card with nothing to put in its header now warns
19
+ in dev.
20
+ - **Sketch mode reaches the component editor.** A component demo draws itself
21
+ the way the page will, sketch included, while the tab strips and property rows
22
+ around it stay chrome: they run on `--ui-*` tokens the layer knows nothing
23
+ about. The router hands the layer the root to paint, so a sketch style never
24
+ bleeds onto the editor's own routes.
25
+
26
+ ### Changed (breaking)
27
+
28
+ - **`--editorial-*` is now `--editorial-md-*`.** The unsized bundle became the
29
+ medium step. A `breaking` tokens.css migration
30
+ (`2026-08-27-editorial-size-steps`) renames it and backfills both steps,
31
+ carrying any value already tuned. It never auto-applies: run
32
+ `npx live-tokens migrate`.
33
+
34
+ ### Changed
35
+
36
+ - **Ink coverage is a levels control.** The dials read as a pile of unrelated
37
+ knobs because each one meant something different depending on the grain and
38
+ octave count under it. The field is now normalized to run black to white
39
+ whatever the noise beneath, so **Steps** flattens it into tones and **Output**
40
+ squeezes the whole of it into the range the ink covers, from palest to
41
+ densest. The field is squeezed into that gap, never clipped at it, so both
42
+ ends mean the same thing at every setting. The seven shipped presets are
43
+ retuned against the new response.
44
+ - **Menus and tooltips are drawn solid whatever the coverage dials say.** They
45
+ float over arbitrary page content, so a fill worn through in patches let the
46
+ page show through them and they stopped reading as a surface the pointer can
47
+ land on.
48
+ - **`SectionDivider` titles take no outline by default.** The three sizes each
49
+ carried a themed outline color, which drew a halo around every subsection
50
+ title on a page that never asked for one. All three default to transparent;
51
+ a theme that wants the halo sets the color.
52
+
53
+ ### Fixed
54
+
55
+ - **Per-side padding no longer strands the base token.** `themed-padding`
56
+ emits `var(--x-side, <base>)` for each side, so a per-side token is an
57
+ override slot the editor fills when the user splits the padding. `Card` and
58
+ `SegmentedControl` declared sides that named a literal step instead, which
59
+ always beat that fallback and left the base inert: merging split padding back
60
+ to one value cleared the side aliases, the fallback never took over, and the
61
+ padding control moved nothing. Both now track their own base, and
62
+ `paddingBaseStaysLive` holds every component that uses `themed-padding` to
63
+ the same rule. `Card`'s header and body padding are symmetric as a result;
64
+ a theme that wants the asymmetry back sets the per-side aliases.
65
+ - **`ImageLightbox`'s tile fill stays on the closed tile.** The fill also
66
+ painted the opened stage, where it had nothing to do: the stage rides a
67
+ near-opaque overlay that already backs transparent art, so the fill only
68
+ showed as a slab of theme color in the gap the image's aspect left inside the
69
+ stage box. The open stage now takes no fill of its own, matching the tile
70
+ shadow, which already stopped at the same edge.
71
+ - **Sketch settings no longer accumulate a trace on `globalThis`.** Debug
72
+ instrumentation left in `sketchStore` pushed an entry onto an unbounded
73
+ global array on every settings write, every share and every cross-frame
74
+ adopt. It is gone.
75
+
3
76
  ## 0.61.0 — A surface says which way it leans
4
77
 
5
78
  ### Added
@@ -377,37 +377,15 @@ var tokensCssMigration_2026_08_19_oklchColorValues = {
377
377
 
378
378
  // vite-plugin/tokensCssMigrations/migrations/2026-08-25-editorial-type-role.ts
379
379
  var STACK = [{ name: "--font-editorial", value: "var(--font-sans)" }];
380
- var BUNDLE2 = [
381
- { name: "--editorial-font-family", value: "var(--font-editorial)" },
382
- { name: "--editorial-font-size", value: "var(--font-size-md)" },
383
- { name: "--editorial-font-weight", value: "var(--font-weight-normal)" },
384
- { name: "--editorial-line-height", value: "var(--line-height-normal)" },
385
- { name: "--editorial-letter-spacing", value: "var(--letter-spacing-normal)" }
386
- ];
387
380
  var tokensCssMigration_2026_08_25_editorialTypeRole = {
388
381
  id: "2026-08-25-editorial-type-role",
389
382
  kind: "additive",
390
- description: "Add the editorial type role (--font-editorial and the --editorial-* bundle)",
383
+ description: "Add the editorial type role (--font-editorial)",
391
384
  apply(css) {
392
- const withStack = ensureScale(css, {
385
+ return ensureScale(css, {
393
386
  anchorPrefixes: ["--font-mono", "--font-serif", "--font-sans", "--font-display"],
394
387
  entries: STACK
395
388
  });
396
- return ensureScale(withStack, {
397
- sectionComment: "Editorial \u2014 the long-reading role, body face until repointed",
398
- anchorPrefixes: [
399
- "--eyebrow-",
400
- "--code-",
401
- "--body-",
402
- "--heading-",
403
- "--letter-spacing-",
404
- "--line-height-",
405
- "--font-weight-",
406
- "--font-size-",
407
- "--font-"
408
- ],
409
- entries: BUNDLE2
410
- });
411
389
  }
412
390
  };
413
391
 
@@ -460,6 +438,47 @@ ${css.slice(at)}`;
460
438
  }
461
439
  };
462
440
 
441
+ // vite-plugin/tokensCssMigrations/migrations/2026-08-27-editorial-size-steps.ts
442
+ var AXES = ["font-family", "font-size", "font-weight", "line-height", "letter-spacing"];
443
+ var BUNDLE2 = [
444
+ { name: "--editorial-md-font-family", value: "var(--font-editorial)" },
445
+ { name: "--editorial-md-font-size", value: "var(--font-size-md)" },
446
+ { name: "--editorial-md-font-weight", value: "var(--font-weight-normal)" },
447
+ { name: "--editorial-md-line-height", value: "var(--line-height-normal)" },
448
+ { name: "--editorial-md-letter-spacing", value: "var(--letter-spacing-normal)" },
449
+ { name: "--editorial-sm-font-family", value: "var(--font-editorial)" },
450
+ { name: "--editorial-sm-font-size", value: "var(--font-size-sm)" },
451
+ { name: "--editorial-sm-font-weight", value: "var(--font-weight-normal)" },
452
+ { name: "--editorial-sm-line-height", value: "var(--line-height-tight)" },
453
+ { name: "--editorial-sm-letter-spacing", value: "var(--letter-spacing-normal)" }
454
+ ];
455
+ var tokensCssMigration_2026_08_27_editorialSizeSteps = {
456
+ id: "2026-08-27-editorial-size-steps",
457
+ kind: "breaking",
458
+ description: "Split the editorial bundle into --editorial-md-* and --editorial-sm-* steps",
459
+ apply(css) {
460
+ let out = css;
461
+ for (const axis of AXES) {
462
+ out = renameToken(out, `--editorial-${axis}`, `--editorial-md-${axis}`);
463
+ }
464
+ return ensureScale(out, {
465
+ sectionComment: "Editorial \u2014 the long-reading role, body face until repointed",
466
+ anchorPrefixes: [
467
+ "--eyebrow-",
468
+ "--code-",
469
+ "--body-",
470
+ "--heading-",
471
+ "--letter-spacing-",
472
+ "--line-height-",
473
+ "--font-weight-",
474
+ "--font-size-",
475
+ "--font-"
476
+ ],
477
+ entries: BUNDLE2
478
+ });
479
+ }
480
+ };
481
+
463
482
  // vite-plugin/tokensCssMigrations/index.ts
464
483
  var TOKENS_CSS_MIGRATIONS = [
465
484
  tokensCssMigration_2026_05_29_typographyScaleAdditions,
@@ -472,7 +491,8 @@ var TOKENS_CSS_MIGRATIONS = [
472
491
  tokensCssMigration_2026_08_19_oklchColorValues,
473
492
  tokensCssMigration_2026_08_25_editorialTypeRole,
474
493
  tokensCssMigration_2026_08_26_gradientStops,
475
- tokensCssMigration_2026_08_27_backdropPolarity
494
+ tokensCssMigration_2026_08_27_backdropPolarity,
495
+ tokensCssMigration_2026_08_27_editorialSizeSteps
476
496
  ];
477
497
  function runTokensCssMigrations(css) {
478
498
  return foldMigrations(css, () => true);
@@ -2510,37 +2510,15 @@ var tokensCssMigration_2026_08_19_oklchColorValues = {
2510
2510
 
2511
2511
  // vite-plugin/tokensCssMigrations/migrations/2026-08-25-editorial-type-role.ts
2512
2512
  var STACK = [{ name: "--font-editorial", value: "var(--font-sans)" }];
2513
- var BUNDLE2 = [
2514
- { name: "--editorial-font-family", value: "var(--font-editorial)" },
2515
- { name: "--editorial-font-size", value: "var(--font-size-md)" },
2516
- { name: "--editorial-font-weight", value: "var(--font-weight-normal)" },
2517
- { name: "--editorial-line-height", value: "var(--line-height-normal)" },
2518
- { name: "--editorial-letter-spacing", value: "var(--letter-spacing-normal)" }
2519
- ];
2520
2513
  var tokensCssMigration_2026_08_25_editorialTypeRole = {
2521
2514
  id: "2026-08-25-editorial-type-role",
2522
2515
  kind: "additive",
2523
- description: "Add the editorial type role (--font-editorial and the --editorial-* bundle)",
2516
+ description: "Add the editorial type role (--font-editorial)",
2524
2517
  apply(css) {
2525
- const withStack = ensureScale(css, {
2518
+ return ensureScale(css, {
2526
2519
  anchorPrefixes: ["--font-mono", "--font-serif", "--font-sans", "--font-display"],
2527
2520
  entries: STACK
2528
2521
  });
2529
- return ensureScale(withStack, {
2530
- sectionComment: "Editorial \u2014 the long-reading role, body face until repointed",
2531
- anchorPrefixes: [
2532
- "--eyebrow-",
2533
- "--code-",
2534
- "--body-",
2535
- "--heading-",
2536
- "--letter-spacing-",
2537
- "--line-height-",
2538
- "--font-weight-",
2539
- "--font-size-",
2540
- "--font-"
2541
- ],
2542
- entries: BUNDLE2
2543
- });
2544
2522
  }
2545
2523
  };
2546
2524
 
@@ -2593,6 +2571,47 @@ ${css.slice(at)}`;
2593
2571
  }
2594
2572
  };
2595
2573
 
2574
+ // vite-plugin/tokensCssMigrations/migrations/2026-08-27-editorial-size-steps.ts
2575
+ var AXES = ["font-family", "font-size", "font-weight", "line-height", "letter-spacing"];
2576
+ var BUNDLE2 = [
2577
+ { name: "--editorial-md-font-family", value: "var(--font-editorial)" },
2578
+ { name: "--editorial-md-font-size", value: "var(--font-size-md)" },
2579
+ { name: "--editorial-md-font-weight", value: "var(--font-weight-normal)" },
2580
+ { name: "--editorial-md-line-height", value: "var(--line-height-normal)" },
2581
+ { name: "--editorial-md-letter-spacing", value: "var(--letter-spacing-normal)" },
2582
+ { name: "--editorial-sm-font-family", value: "var(--font-editorial)" },
2583
+ { name: "--editorial-sm-font-size", value: "var(--font-size-sm)" },
2584
+ { name: "--editorial-sm-font-weight", value: "var(--font-weight-normal)" },
2585
+ { name: "--editorial-sm-line-height", value: "var(--line-height-tight)" },
2586
+ { name: "--editorial-sm-letter-spacing", value: "var(--letter-spacing-normal)" }
2587
+ ];
2588
+ var tokensCssMigration_2026_08_27_editorialSizeSteps = {
2589
+ id: "2026-08-27-editorial-size-steps",
2590
+ kind: "breaking",
2591
+ description: "Split the editorial bundle into --editorial-md-* and --editorial-sm-* steps",
2592
+ apply(css) {
2593
+ let out = css;
2594
+ for (const axis of AXES) {
2595
+ out = renameToken2(out, `--editorial-${axis}`, `--editorial-md-${axis}`);
2596
+ }
2597
+ return ensureScale(out, {
2598
+ sectionComment: "Editorial \u2014 the long-reading role, body face until repointed",
2599
+ anchorPrefixes: [
2600
+ "--eyebrow-",
2601
+ "--code-",
2602
+ "--body-",
2603
+ "--heading-",
2604
+ "--letter-spacing-",
2605
+ "--line-height-",
2606
+ "--font-weight-",
2607
+ "--font-size-",
2608
+ "--font-"
2609
+ ],
2610
+ entries: BUNDLE2
2611
+ });
2612
+ }
2613
+ };
2614
+
2596
2615
  // vite-plugin/tokensCssMigrations/index.ts
2597
2616
  var TOKENS_CSS_MIGRATIONS = [
2598
2617
  tokensCssMigration_2026_05_29_typographyScaleAdditions,
@@ -2605,7 +2624,8 @@ var TOKENS_CSS_MIGRATIONS = [
2605
2624
  tokensCssMigration_2026_08_19_oklchColorValues,
2606
2625
  tokensCssMigration_2026_08_25_editorialTypeRole,
2607
2626
  tokensCssMigration_2026_08_26_gradientStops,
2608
- tokensCssMigration_2026_08_27_backdropPolarity
2627
+ tokensCssMigration_2026_08_27_backdropPolarity,
2628
+ tokensCssMigration_2026_08_27_editorialSizeSteps
2609
2629
  ];
2610
2630
  function runTokensCssMigrations(css) {
2611
2631
  return foldMigrations(css, () => true);
@@ -23,7 +23,7 @@ import {
23
23
  runAdditiveTokensCssMigrations,
24
24
  runTokensCssMigrations,
25
25
  validateTokensCss
26
- } from "./chunk-OIOXU7FR.js";
26
+ } from "./chunk-OPYOK2CA.js";
27
27
  import {
28
28
  hexToOklch,
29
29
  oklchToRgb255,
@@ -464,37 +464,15 @@ var tokensCssMigration_2026_08_19_oklchColorValues = {
464
464
 
465
465
  // vite-plugin/tokensCssMigrations/migrations/2026-08-25-editorial-type-role.ts
466
466
  var STACK = [{ name: "--font-editorial", value: "var(--font-sans)" }];
467
- var BUNDLE2 = [
468
- { name: "--editorial-font-family", value: "var(--font-editorial)" },
469
- { name: "--editorial-font-size", value: "var(--font-size-md)" },
470
- { name: "--editorial-font-weight", value: "var(--font-weight-normal)" },
471
- { name: "--editorial-line-height", value: "var(--line-height-normal)" },
472
- { name: "--editorial-letter-spacing", value: "var(--letter-spacing-normal)" }
473
- ];
474
467
  var tokensCssMigration_2026_08_25_editorialTypeRole = {
475
468
  id: "2026-08-25-editorial-type-role",
476
469
  kind: "additive",
477
- description: "Add the editorial type role (--font-editorial and the --editorial-* bundle)",
470
+ description: "Add the editorial type role (--font-editorial)",
478
471
  apply(css) {
479
- const withStack = ensureScale(css, {
472
+ return ensureScale(css, {
480
473
  anchorPrefixes: ["--font-mono", "--font-serif", "--font-sans", "--font-display"],
481
474
  entries: STACK
482
475
  });
483
- return ensureScale(withStack, {
484
- sectionComment: "Editorial \u2014 the long-reading role, body face until repointed",
485
- anchorPrefixes: [
486
- "--eyebrow-",
487
- "--code-",
488
- "--body-",
489
- "--heading-",
490
- "--letter-spacing-",
491
- "--line-height-",
492
- "--font-weight-",
493
- "--font-size-",
494
- "--font-"
495
- ],
496
- entries: BUNDLE2
497
- });
498
476
  }
499
477
  };
500
478
 
@@ -547,6 +525,47 @@ ${css.slice(at)}`;
547
525
  }
548
526
  };
549
527
 
528
+ // vite-plugin/tokensCssMigrations/migrations/2026-08-27-editorial-size-steps.ts
529
+ var AXES = ["font-family", "font-size", "font-weight", "line-height", "letter-spacing"];
530
+ var BUNDLE2 = [
531
+ { name: "--editorial-md-font-family", value: "var(--font-editorial)" },
532
+ { name: "--editorial-md-font-size", value: "var(--font-size-md)" },
533
+ { name: "--editorial-md-font-weight", value: "var(--font-weight-normal)" },
534
+ { name: "--editorial-md-line-height", value: "var(--line-height-normal)" },
535
+ { name: "--editorial-md-letter-spacing", value: "var(--letter-spacing-normal)" },
536
+ { name: "--editorial-sm-font-family", value: "var(--font-editorial)" },
537
+ { name: "--editorial-sm-font-size", value: "var(--font-size-sm)" },
538
+ { name: "--editorial-sm-font-weight", value: "var(--font-weight-normal)" },
539
+ { name: "--editorial-sm-line-height", value: "var(--line-height-tight)" },
540
+ { name: "--editorial-sm-letter-spacing", value: "var(--letter-spacing-normal)" }
541
+ ];
542
+ var tokensCssMigration_2026_08_27_editorialSizeSteps = {
543
+ id: "2026-08-27-editorial-size-steps",
544
+ kind: "breaking",
545
+ description: "Split the editorial bundle into --editorial-md-* and --editorial-sm-* steps",
546
+ apply(css) {
547
+ let out = css;
548
+ for (const axis of AXES) {
549
+ out = renameToken(out, `--editorial-${axis}`, `--editorial-md-${axis}`);
550
+ }
551
+ return ensureScale(out, {
552
+ sectionComment: "Editorial \u2014 the long-reading role, body face until repointed",
553
+ anchorPrefixes: [
554
+ "--eyebrow-",
555
+ "--code-",
556
+ "--body-",
557
+ "--heading-",
558
+ "--letter-spacing-",
559
+ "--line-height-",
560
+ "--font-weight-",
561
+ "--font-size-",
562
+ "--font-"
563
+ ],
564
+ entries: BUNDLE2
565
+ });
566
+ }
567
+ };
568
+
550
569
  // vite-plugin/files/dataPaths.ts
551
570
  var import_fs = __toESM(require("fs"), 1);
552
571
  var import_path = __toESM(require("path"), 1);
@@ -593,7 +612,8 @@ var TOKENS_CSS_MIGRATIONS = [
593
612
  tokensCssMigration_2026_08_19_oklchColorValues,
594
613
  tokensCssMigration_2026_08_25_editorialTypeRole,
595
614
  tokensCssMigration_2026_08_26_gradientStops,
596
- tokensCssMigration_2026_08_27_backdropPolarity
615
+ tokensCssMigration_2026_08_27_backdropPolarity,
616
+ tokensCssMigration_2026_08_27_editorialSizeSteps
597
617
  ];
598
618
  function runTokensCssMigrations(css) {
599
619
  return foldMigrations(css, () => true);
@@ -13,7 +13,7 @@ import {
13
13
  runTokensCssMigrations,
14
14
  semverBumpType,
15
15
  validateTokensCss
16
- } from "../chunk-OIOXU7FR.js";
16
+ } from "../chunk-OPYOK2CA.js";
17
17
  import "../chunk-7TQQTHI6.js";
18
18
  import {
19
19
  readLiveTokensConfig
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@motion-proto/live-tokens",
3
- "version": "0.61.0",
3
+ "version": "0.62.0",
4
4
  "type": "module",
5
5
  "description": "Design token editor with live CSS variable editing. Svelte 5 + Vite 8.",
6
6
  "keywords": [
package/src/app/site.css CHANGED
@@ -205,6 +205,22 @@ blockquote {
205
205
  letter-spacing: var(--body-sm-letter-spacing);
206
206
  }
207
207
 
208
+ .editorial-md {
209
+ font-family: var(--editorial-md-font-family);
210
+ font-size: var(--editorial-md-font-size);
211
+ font-weight: var(--editorial-md-font-weight);
212
+ line-height: var(--editorial-md-line-height);
213
+ letter-spacing: var(--editorial-md-letter-spacing);
214
+ }
215
+
216
+ .editorial-sm {
217
+ font-family: var(--editorial-sm-font-family);
218
+ font-size: var(--editorial-sm-font-size);
219
+ font-weight: var(--editorial-sm-font-weight);
220
+ line-height: var(--editorial-sm-line-height);
221
+ letter-spacing: var(--editorial-sm-letter-spacing);
222
+ }
223
+
208
224
  .eyebrow {
209
225
  font-family: var(--eyebrow-font-family);
210
226
  font-size: var(--eyebrow-font-size);
@@ -134,7 +134,7 @@
134
134
  }
135
135
  </script>
136
136
 
137
- <ComponentEditorBase {component} title="Card" description="Generic card with icon, title, and slotted body." tokens={allTokens} {linked}>
137
+ <ComponentEditorBase {component} title="Card" description="Generic card with icon, title, and slotted body. The bare variant drops the header and keeps every frame and body token." tokens={allTokens} {linked}>
138
138
  <VariantGroup
139
139
  name="card"
140
140
  title="Card"
@@ -165,6 +165,9 @@
165
165
  <Card title="Card title" icon="fas fa-star" class={previewClass}>
166
166
  <div class="content-placeholder">Content Placeholder</div>
167
167
  </Card>
168
+ <Card variant="bare" class={previewClass}>
169
+ <div class="content-placeholder">Bare variant</div>
170
+ </Card>
168
171
  </div>
169
172
  {/snippet}
170
173
  </VariantGroup>
@@ -172,6 +175,9 @@
172
175
 
173
176
  <style>
174
177
  .card-demo {
178
+ display: flex;
179
+ flex-direction: column;
180
+ gap: var(--ui-space-12);
175
181
  min-width: 16rem;
176
182
  max-width: 28rem;
177
183
  }
@@ -11,6 +11,8 @@
11
11
  import type { CssVarRef } from '../../core/store/editorTypes';
12
12
  import { cssStringToRef, refToCss } from '../../core/store/cssVarRef';
13
13
  import { getEditorContext } from './editorContext';
14
+ import { setSketchScope } from '../../core/sketch/sketchLayer';
15
+ import { sketchEnabled, sketchSettings } from '../../core/sketch/sketchStore';
14
16
  import type { Token, TypeGroupConfig } from './types';
15
17
  import type { Sibling } from './siblings';
16
18
 
@@ -84,6 +86,15 @@
84
86
  let bgMode: 'default' | 'image' | 'color' = $state('default');
85
87
  let bgVar = $derived(`--backdrop-${component ?? name}-surface`);
86
88
 
89
+ // The demo shows the component as the page will draw it, sketch included, so
90
+ // the scope attribute goes on this wrapper. It stops here: the tab strips and
91
+ // property rows around it are chrome and run on --ui-* tokens the layer knows
92
+ // nothing about. Only one of the four render sites below is ever mounted.
93
+ let sketchStage = $state<HTMLDivElement | undefined>(undefined);
94
+ $effect(() => {
95
+ setSketchScope(sketchStage ?? null, $sketchEnabled ? $sketchSettings : null);
96
+ });
97
+
87
98
  const editorCtx = getEditorContext();
88
99
  const linkedOrderStore = editorCtx?.linkedOrder ?? writable<Map<string, number> | null>(null);
89
100
  const focusedVariantStore = editorCtx?.focusedVariant ?? writable<string | null>(null);
@@ -397,7 +408,9 @@
397
408
  {/if}
398
409
  </div>
399
410
  {#if unboxedPreview}
400
- {@render children?.({ activeState: activeTab })}
411
+ <div class="sketch-scope" bind:this={sketchStage}>
412
+ {@render children?.({ activeState: activeTab })}
413
+ </div>
401
414
  {:else}
402
415
  <ShadowBackdrop mode={bgMode} colorVariable={bgVar} padding={backdropPadding}>
403
416
  {#snippet controls()}
@@ -407,7 +420,9 @@
407
420
  {@render canvasToolbarExtras?.()}
408
421
  </div>
409
422
  {/snippet}
423
+ <div class="sketch-scope" bind:this={sketchStage}>
410
424
  {@render children?.({ activeState: activeTab })}
425
+ </div>
411
426
  </ShadowBackdrop>
412
427
  {/if}
413
428
 
@@ -508,10 +523,14 @@
508
523
  {/if}
509
524
  {:else}
510
525
  {#if unboxedPreview}
511
- {@render children?.({ activeState: '' })}
526
+ <div class="sketch-scope" bind:this={sketchStage}>
527
+ {@render children?.({ activeState: '' })}
528
+ </div>
512
529
  {:else}
513
530
  <ShadowBackdrop mode={bgMode} colorVariable={bgVar} padding={backdropPadding}>
531
+ <div class="sketch-scope" bind:this={sketchStage}>
514
532
  {@render children?.({ activeState: '' })}
533
+ </div>
515
534
  </ShadowBackdrop>
516
535
  {/if}
517
536
  <TokenLayout
@@ -572,6 +591,10 @@
572
591
  pointer-events: none;
573
592
  }
574
593
 
594
+ .sketch-scope {
595
+ display: contents;
596
+ }
597
+
575
598
  .preview-header {
576
599
  display: flex;
577
600
  align-items: center;