@motion-proto/live-tokens 0.72.1 → 0.74.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 (81) hide show
  1. package/.claude/skills/live-tokens-build-page/SKILL.md +37 -2
  2. package/.claude/skills/live-tokens-build-page/references/layout-sources.md +48 -0
  3. package/.claude/skills/live-tokens-check-compliance/SKILL.md +2 -2
  4. package/.claude/skills/live-tokens-create-component/SKILL.md +4 -4
  5. package/.claude/skills/live-tokens-create-theme/SKILL.md +80 -0
  6. package/.claude/skills/live-tokens-create-theme/references/design-directions.md +94 -0
  7. package/.claude/skills/live-tokens-pick-component/SKILL.md +1 -1
  8. package/.claude/skills/live-tokens-set-colors/SKILL.md +140 -0
  9. package/.claude/skills/live-tokens-set-colors/references/color-anchors.md +80 -0
  10. package/.claude/skills/{live-tokens-adjust-geometry → live-tokens-set-geometry}/SKILL.md +12 -7
  11. package/.claude/skills/live-tokens-set-geometry/references/geometry-anchors.md +61 -0
  12. package/.claude/skills/{live-tokens-pair-fonts → live-tokens-set-type}/SKILL.md +18 -15
  13. package/.claude/skills/live-tokens-set-type/references/type-anchors.md +60 -0
  14. package/CHANGELOG.md +141 -0
  15. package/README.md +24 -15
  16. package/bin/check-page.mjs +3 -3
  17. package/bin/cli.mjs +92 -55
  18. package/bin/lib/liveState.mjs +110 -0
  19. package/bin/save-theme.mjs +177 -0
  20. package/bin/set-colors.mjs +191 -0
  21. package/bin/{adjust.mjs → set-geometry.mjs} +18 -50
  22. package/bin/{set-fonts.mjs → set-type.mjs} +21 -55
  23. package/dist-plugin/{chunk-RIXO2E55.js → chunk-7VRTBGJT.js} +1 -1
  24. package/dist-plugin/{chunk-YLCOIGQC.js → chunk-V3YF6CGT.js} +56 -2
  25. package/dist-plugin/index.cjs +58 -3
  26. package/dist-plugin/index.js +11 -11
  27. package/dist-plugin/migrateData/index.cjs +56 -1
  28. package/dist-plugin/migrateData/index.js +2 -2
  29. package/dist-plugin/{generateColorsAndType → setColors}/index.cjs +1109 -1071
  30. package/dist-plugin/{generateColorsAndType → setColors}/index.d.cts +33 -24
  31. package/dist-plugin/{generateColorsAndType → setColors}/index.d.ts +33 -24
  32. package/dist-plugin/{generateColorsAndType → setColors}/index.js +45 -63
  33. package/dist-plugin/{adjust → setGeometry}/index.cjs +60 -5
  34. package/dist-plugin/{adjust → setGeometry}/index.d.cts +1 -1
  35. package/dist-plugin/{adjust → setGeometry}/index.d.ts +1 -1
  36. package/dist-plugin/{adjust → setGeometry}/index.js +1 -1
  37. package/dist-plugin/{fontPairing → setType}/index.cjs +4 -4
  38. package/dist-plugin/{fontPairing → setType}/index.d.cts +1 -1
  39. package/dist-plugin/{fontPairing → setType}/index.d.ts +1 -1
  40. package/dist-plugin/{themeTypes-DSV3Zisf.d.cts → themeTypes-BxRtuN5V.d.cts} +1 -1
  41. package/dist-plugin/{themeTypes-DSV3Zisf.d.ts → themeTypes-BxRtuN5V.d.ts} +1 -1
  42. package/package.json +10 -2
  43. package/src/editor/core/themes/{generateColorsAndType.ts → buildColors.ts} +82 -96
  44. package/src/editor/core/themes/migrations/2026-09-03-drop-legacy-component-keys.ts +62 -0
  45. package/src/editor/core/themes/migrations/index.ts +2 -0
  46. package/src/editor/docs/content/creating-components.md +13 -0
  47. package/src/editor/docs/content/themes-workflow.md +2 -2
  48. package/src/editor/docs/content.generated.ts +2 -2
  49. package/src/editor/overlay/LiveEditorOverlay.svelte +519 -28
  50. package/src/editor/skill-atlas/SkillAtlas.svelte +836 -0
  51. package/src/editor/skill-atlas/SkillAtlas.svelte.d.ts +4 -0
  52. package/src/editor/skill-atlas/SourcePane.svelte +364 -0
  53. package/src/editor/skill-atlas/TreeNodeCard.svelte +206 -0
  54. package/src/editor/skill-atlas/skillSources.generated.ts +45 -0
  55. package/src/editor/skill-atlas/skillSources.ts +1 -0
  56. package/src/editor/skill-atlas/skillTrees.ts +3844 -0
  57. package/src/editor/skill-atlas/types.ts +65 -0
  58. package/src/live-tokens/data/colors-and-type/autumn.json +1 -37
  59. package/src/live-tokens/data/colors-and-type/default.json +1 -37
  60. package/src/live-tokens/data/colors-and-type/halloween.json +1 -37
  61. package/src/live-tokens/data/colors-and-type/midnight-study.json +1 -37
  62. package/src/live-tokens/data/colors-and-type/ocean.json +1 -37
  63. package/src/live-tokens/data/colors-and-type/royal-velvet.json +1 -37
  64. package/src/live-tokens/data/colors-and-type/sketchy.json +1 -37
  65. package/src/live-tokens/data/colors-and-type/spring-meadow.json +1 -37
  66. package/src/live-tokens/data/colors-and-type/sunset.json +1 -37
  67. package/src/live-tokens/data/themes/autumn.json +1 -37
  68. package/src/live-tokens/data/themes/halloween.json +1 -37
  69. package/src/live-tokens/data/themes/midnight-study.json +1 -37
  70. package/src/live-tokens/data/themes/ocean.json +1 -37
  71. package/src/live-tokens/data/themes/royal-velvet.json +1 -37
  72. package/src/live-tokens/data/themes/sketchy.json +1 -37
  73. package/src/live-tokens/data/themes/spring-meadow.json +1 -37
  74. package/src/live-tokens/data/themes/sunset.json +1 -37
  75. package/src/live-tokens/data/tokens.generated.css +0 -36
  76. package/.claude/skills/live-tokens-generate-theme/SKILL.md +0 -156
  77. package/.claude/skills/live-tokens-generate-theme/references/mood-vocabulary.md +0 -43
  78. package/.claude/skills/live-tokens-generate-theme/references/named-themes.md +0 -18
  79. package/.claude/skills/live-tokens-generate-theme/references/style-vocabulary.md +0 -35
  80. package/bin/generate-theme.mjs +0 -260
  81. /package/dist-plugin/{fontPairing → setType}/index.js +0 -0
@@ -0,0 +1,4 @@
1
+ import type { Component } from 'svelte';
2
+
3
+ declare const SkillAtlas: Component<Record<string, never>>;
4
+ export default SkillAtlas;
@@ -0,0 +1,364 @@
1
+ <script lang="ts">
2
+ import type { LineRange } from './types';
3
+
4
+ interface Props {
5
+ lines: string[];
6
+ highlight: LineRange | null;
7
+ /** The skill's other documents, so only a reference that exists links. */
8
+ siblings: string[];
9
+ onpick: (lineNumber: number) => void;
10
+ onopen: (doc: string) => void;
11
+ }
12
+
13
+ let { lines, highlight, siblings, onpick, onopen }: Props = $props();
14
+
15
+ type Segment = { text: string; kind: 'plain' | 'code' | 'strong' | 'em' | 'link' };
16
+
17
+ /** Line-level role, used for weight and colour only. */
18
+ type Role = 'frontmatter' | 'heading' | 'subheading' | 'code' | 'table' | 'text';
19
+
20
+ interface Row {
21
+ n: number;
22
+ role: Role;
23
+ segments: Segment[];
24
+ }
25
+
26
+ const INLINE = /(`[^`]+`|\*\*[^*]+\*\*|\*[^*\n]+\*)/g;
27
+
28
+ function segment(text: string): Segment[] {
29
+ if (text === '') return [{ text: ' ', kind: 'plain' }];
30
+ return text
31
+ .split(INLINE)
32
+ .filter((part) => part !== '')
33
+ .map((part) => {
34
+ if (part.startsWith('`') && part.endsWith('`')) {
35
+ const inner = part.slice(1, -1);
36
+ // Every skill names its references in backticks, so the prose already
37
+ // marks them; the pane only has to make them go somewhere.
38
+ return { text: inner, kind: siblings.includes(inner) ? ('link' as const) : ('code' as const) };
39
+ }
40
+ if (part.startsWith('**') && part.endsWith('**')) {
41
+ return { text: part.slice(2, -2), kind: 'strong' as const };
42
+ }
43
+ if (part.startsWith('*') && part.endsWith('*')) {
44
+ return { text: part.slice(1, -1), kind: 'em' as const };
45
+ }
46
+ return { text: part, kind: 'plain' as const };
47
+ });
48
+ }
49
+
50
+ let rows: Row[] = $derived.by(() => {
51
+ let inFence = false;
52
+ let delimiters = 0;
53
+
54
+ return lines.map((raw, i) => {
55
+ const isDelimiter = raw.trim() === '---' && delimiters < 2;
56
+ if (isDelimiter) delimiters += 1;
57
+ const isFence = raw.startsWith('```');
58
+ if (isFence) inFence = !inFence;
59
+
60
+ let role: Role = 'text';
61
+ if (isFence || (inFence && !isFence)) role = 'code';
62
+ else if (isDelimiter || delimiters < 2) role = 'frontmatter';
63
+ else if (raw.startsWith('# ')) role = 'heading';
64
+ else if (/^#{2,}\s/.test(raw)) role = 'subheading';
65
+ else if (raw.startsWith('|')) role = 'table';
66
+
67
+ // Inside a fence the markers are literal, so they stay unparsed.
68
+ const segments = role === 'code' ? [{ text: raw === '' ? ' ' : raw, kind: 'plain' as const }] : segment(raw);
69
+ return { n: i + 1, role, segments };
70
+ });
71
+ });
72
+
73
+ function marked(n: number): boolean {
74
+ return highlight !== null && n >= highlight[0] && n <= highlight[1];
75
+ }
76
+
77
+ let container: HTMLElement | undefined = $state();
78
+ let band: { top: number; height: number } | null = $state(null);
79
+
80
+ /** The band stands a little proud of the rows so the brackets clear the text. */
81
+ const BLEED = 4;
82
+
83
+ function measure() {
84
+ const first = highlight && container?.querySelector<HTMLElement>(`[data-line="${highlight[0]}"]`);
85
+ const last = highlight && container?.querySelector<HTMLElement>(`[data-line="${highlight[1]}"]`);
86
+ band =
87
+ first && last
88
+ ? {
89
+ top: first.offsetTop - BLEED,
90
+ height: last.offsetTop + last.offsetHeight - first.offsetTop + BLEED * 2,
91
+ }
92
+ : null;
93
+ }
94
+
95
+ $effect(() => {
96
+ // `rows` because a document switch renumbers every line under the band.
97
+ rows;
98
+ measure();
99
+ });
100
+
101
+ // Wrapping reflows the rows under a fixed band, so width alone must re-measure.
102
+ $effect(() => {
103
+ if (!container) return;
104
+ const observer = new ResizeObserver(measure);
105
+ observer.observe(container);
106
+ return () => observer.disconnect();
107
+ });
108
+ </script>
109
+
110
+ <div class="source" bind:this={container}>
111
+ {#if band}
112
+ <!-- Keyed on the range so a new selection replays the flash. -->
113
+ {#key highlight}
114
+ <div class="band" style="top: {band.top}px; height: {band.height}px" aria-hidden="true">
115
+ <span class="wash"></span>
116
+ <span class="frame">
117
+ <span class="corner tl"></span>
118
+ <span class="corner tr"></span>
119
+ <span class="corner bl"></span>
120
+ <span class="corner br"></span>
121
+ </span>
122
+ </div>
123
+ {/key}
124
+ {/if}
125
+ {#each rows as row (row.n)}
126
+ <div class="row role-{row.role}" class:hl={marked(row.n)} data-line={row.n}>
127
+ <button
128
+ type="button"
129
+ class="gutter"
130
+ aria-label="Select the step covering line {row.n}"
131
+ onclick={() => onpick(row.n)}
132
+ >
133
+ {row.n}
134
+ </button>
135
+ <code class="text">
136
+ {#each row.segments as seg, i (i)}
137
+ {#if seg.kind === 'link'}<button
138
+ type="button"
139
+ class="tick link"
140
+ onclick={() => onopen(seg.text)}>{seg.text}</button>
141
+ {:else if seg.kind === 'code'}<span class="tick">{seg.text}</span>
142
+ {:else if seg.kind === 'strong'}<strong>{seg.text}</strong>
143
+ {:else if seg.kind === 'em'}<em>{seg.text}</em>
144
+ {:else}{seg.text}{/if}
145
+ {/each}
146
+ </code>
147
+ </div>
148
+ {/each}
149
+ </div>
150
+
151
+ <style>
152
+ .source {
153
+ position: relative;
154
+ /* The band sits behind the rows, so the source needs its own stacking
155
+ context to keep it off the pane background. */
156
+ isolation: isolate;
157
+ padding: var(--space-16) 0 var(--space-96);
158
+ }
159
+
160
+ .row {
161
+ display: flex;
162
+ align-items: flex-start;
163
+ gap: var(--space-8);
164
+ padding-right: var(--space-24);
165
+ scroll-margin-block: var(--space-96);
166
+ }
167
+
168
+ .gutter {
169
+ flex: 0 0 auto;
170
+ width: var(--space-48);
171
+ padding: 0 var(--space-12) 0 0;
172
+ border: none;
173
+ background: transparent;
174
+ text-align: right;
175
+ font-family: var(--code-font-family);
176
+ font-size: var(--font-size-md);
177
+ line-height: var(--code-line-height);
178
+ font-variant-numeric: tabular-nums;
179
+ color: var(--text-muted);
180
+ cursor: pointer;
181
+ }
182
+
183
+ .gutter:hover {
184
+ color: var(--text-accent);
185
+ }
186
+
187
+ .text {
188
+ flex: 1 1 auto;
189
+ min-width: 0;
190
+ padding-left: var(--space-16);
191
+ border-left: var(--border-width-2) solid transparent;
192
+ white-space: pre-wrap;
193
+ overflow-wrap: break-word;
194
+ font-family: var(--code-font-family);
195
+ font-size: var(--font-size-md);
196
+ font-weight: var(--code-font-weight);
197
+ line-height: var(--code-line-height);
198
+ letter-spacing: var(--code-letter-spacing);
199
+ color: var(--text-secondary);
200
+ }
201
+
202
+ .role-frontmatter .text {
203
+ color: var(--text-muted);
204
+ font-style: italic;
205
+ }
206
+
207
+ .role-heading .text,
208
+ .role-subheading .text {
209
+ color: var(--text-primary);
210
+ font-weight: var(--font-weight-bold);
211
+ }
212
+
213
+ .role-heading .text {
214
+ font-size: var(--font-size-lg);
215
+ }
216
+
217
+ .role-code .text {
218
+ color: var(--text-accent);
219
+ }
220
+
221
+ .role-table .text {
222
+ color: var(--text-tertiary);
223
+ }
224
+
225
+ .tick {
226
+ padding: 0 var(--space-4);
227
+ border-radius: var(--radius-sm);
228
+ background: var(--surface-neutral-lower);
229
+ color: var(--text-primary);
230
+ }
231
+
232
+ /* The link inherits the code run it replaces, so a reference reads as the
233
+ same token in the prose whether or not the pane can open it. */
234
+ .link {
235
+ border: none;
236
+ font: inherit;
237
+ letter-spacing: inherit;
238
+ background: var(--surface-accent-lower);
239
+ color: var(--text-accent);
240
+ text-decoration: underline;
241
+ text-underline-offset: var(--space-2);
242
+ cursor: pointer;
243
+ }
244
+
245
+ .link:hover {
246
+ background: var(--surface-accent-low);
247
+ }
248
+
249
+ strong {
250
+ color: var(--text-primary);
251
+ font-weight: var(--font-weight-bold);
252
+ }
253
+
254
+ em {
255
+ color: var(--text-primary);
256
+ }
257
+
258
+ .hl .text {
259
+ color: var(--text-primary);
260
+ }
261
+
262
+ .hl .gutter {
263
+ color: var(--text-accent);
264
+ }
265
+
266
+ /* The selected range is one block, so it is drawn as one shape spanning the
267
+ text column rather than as a stack of per-row backgrounds. */
268
+ .band {
269
+ position: absolute;
270
+ z-index: -1;
271
+ left: calc(var(--space-48) + var(--space-8));
272
+ right: var(--space-24);
273
+ border-radius: var(--radius-md);
274
+ background: color-mix(in srgb, var(--text-accent) 12%, transparent);
275
+ pointer-events: none;
276
+ }
277
+
278
+ .wash {
279
+ position: absolute;
280
+ inset: 0;
281
+ border-radius: inherit;
282
+ background: color-mix(in srgb, var(--text-accent) 26%, transparent);
283
+ animation: wash var(--duration-1000) var(--ease-out-quad) forwards;
284
+ }
285
+
286
+ .frame {
287
+ position: absolute;
288
+ inset: 0;
289
+ animation: settle var(--duration-500) var(--ease-out-cubic) both;
290
+ }
291
+
292
+ .corner {
293
+ position: absolute;
294
+ width: var(--space-16);
295
+ height: var(--space-16);
296
+ border: 0 solid var(--text-accent);
297
+ }
298
+
299
+ .tl {
300
+ top: 0;
301
+ left: 0;
302
+ border-top-width: var(--border-width-2);
303
+ border-left-width: var(--border-width-2);
304
+ border-top-left-radius: var(--radius-md);
305
+ }
306
+
307
+ .tr {
308
+ top: 0;
309
+ right: 0;
310
+ border-top-width: var(--border-width-2);
311
+ border-right-width: var(--border-width-2);
312
+ border-top-right-radius: var(--radius-md);
313
+ }
314
+
315
+ .bl {
316
+ bottom: 0;
317
+ left: 0;
318
+ border-bottom-width: var(--border-width-2);
319
+ border-left-width: var(--border-width-2);
320
+ border-bottom-left-radius: var(--radius-md);
321
+ }
322
+
323
+ .br {
324
+ bottom: 0;
325
+ right: 0;
326
+ border-bottom-width: var(--border-width-2);
327
+ border-right-width: var(--border-width-2);
328
+ border-bottom-right-radius: var(--radius-md);
329
+ }
330
+
331
+ @keyframes wash {
332
+ 0% {
333
+ opacity: 0;
334
+ }
335
+ 12% {
336
+ opacity: 1;
337
+ }
338
+ 100% {
339
+ opacity: 0;
340
+ }
341
+ }
342
+
343
+ @keyframes settle {
344
+ from {
345
+ inset: calc(-1 * var(--space-8));
346
+ opacity: 0;
347
+ }
348
+ to {
349
+ inset: 0;
350
+ opacity: 1;
351
+ }
352
+ }
353
+
354
+ @media (prefers-reduced-motion: reduce) {
355
+ .wash {
356
+ animation: none;
357
+ opacity: 0;
358
+ }
359
+
360
+ .frame {
361
+ animation: none;
362
+ }
363
+ }
364
+ </style>
@@ -0,0 +1,206 @@
1
+ <script lang="ts">
2
+ import Button from '../../system/components/Button.svelte';
3
+ import Card from '../../system/components/Card.svelte';
4
+ import CodeSnippet from '../../system/components/CodeSnippet.svelte';
5
+ import type { LineRange, NodeKind, TreeNode } from './types';
6
+
7
+ interface Props {
8
+ node: TreeNode;
9
+ selected: string | null;
10
+ onselect: (key: string, label: string, lines: LineRange) => void;
11
+ onopen: (doc: string) => void;
12
+ }
13
+
14
+ let { node, selected, onselect, onopen }: Props = $props();
15
+
16
+ const KIND_LABEL: Record<NodeKind, string> = {
17
+ trigger: 'trigger',
18
+ step: 'step',
19
+ decide: 'decision',
20
+ cli: 'command',
21
+ hand: 'hands off',
22
+ gate: 'failure',
23
+ ok: 'pass',
24
+ ref: 'reference',
25
+ ask: 'question',
26
+ chipset: 'reference set',
27
+ done: 'verify',
28
+ };
29
+
30
+ let kindLabel = $derived(node.tag ?? KIND_LABEL[node.kind]);
31
+ let cardSelected = $derived(selected === node.id);
32
+ let range = $derived(node.lines ? rangeLabel(node.lines) : '');
33
+
34
+ function rangeLabel([a, b]: LineRange): string {
35
+ return a === b ? `line ${a}` : `lines ${a}–${b}`;
36
+ }
37
+
38
+ function selectSelf() {
39
+ if (node.lines) onselect(node.id, node.title, node.lines);
40
+ }
41
+ </script>
42
+
43
+ <div class="shell" class:on={cardSelected} data-node={node.id}>
44
+ {#if node.lines}
45
+ <button
46
+ type="button"
47
+ class="hit"
48
+ aria-pressed={cardSelected}
49
+ aria-label="{node.title}. SKILL.md {range}"
50
+ onclick={selectSelf}
51
+ ></button>
52
+ {/if}
53
+
54
+ <Card title={node.title} prose={false}>
55
+ <div class="meta">
56
+ <h3 class="kind">
57
+ {#if node.n}<span class="step-n">{node.n}</span>{/if}{kindLabel}
58
+ </h3>
59
+ {#if range}<span class="range">{range}</span>{/if}
60
+ </div>
61
+
62
+ {#if node.desc}<p class="desc">{node.desc}</p>{/if}
63
+
64
+ {#if node.reference}
65
+ <button type="button" class="doclink" onclick={() => onopen(node.reference!)}>
66
+ {node.reference.replace('references/', '')}
67
+ </button>
68
+ {/if}
69
+
70
+ {#if node.command}
71
+ <div class="command"><CodeSnippet code={node.command} /></div>
72
+ {/if}
73
+
74
+ {#if node.chips}
75
+ <ul class="chips">
76
+ {#each node.chips as chip, i (chip.label)}
77
+ {@const key = `${node.id}:${i}`}
78
+ <li>
79
+ <Button
80
+ variant={selected === key ? 'secondary' : 'outline'}
81
+ onclick={() => onselect(key, chip.label, chip.lines)}
82
+ >
83
+ {chip.label}
84
+ </Button>
85
+ </li>
86
+ {/each}
87
+ </ul>
88
+ {/if}
89
+ </Card>
90
+ </div>
91
+
92
+ <style>
93
+ .shell {
94
+ position: relative;
95
+ border-radius: var(--card-default-radius);
96
+ }
97
+
98
+ /* A transparent overlay makes the whole card the click target without
99
+ nesting the chip buttons inside another button. */
100
+ .hit {
101
+ position: absolute;
102
+ inset: 0;
103
+ z-index: 1;
104
+ padding: 0;
105
+ border: none;
106
+ border-radius: inherit;
107
+ background: transparent;
108
+ cursor: pointer;
109
+ }
110
+
111
+ /* The package Card clips its title to one line; a node title is the step
112
+ itself, so it has to read whole. */
113
+ .shell :global(.card-title) {
114
+ white-space: normal;
115
+ overflow-wrap: anywhere;
116
+ }
117
+
118
+ .shell:has(.hit:hover) {
119
+ outline: var(--border-width-1) solid var(--border-accent-medium);
120
+ outline-offset: var(--space-2);
121
+ }
122
+
123
+ .shell.on {
124
+ outline: var(--border-width-2) solid var(--text-accent);
125
+ outline-offset: var(--space-2);
126
+ }
127
+
128
+ /* Chips, the copy button and the reference link sit above the overlay so they
129
+ stay clickable. */
130
+ .chips,
131
+ .command,
132
+ .doclink {
133
+ position: relative;
134
+ z-index: 2;
135
+ }
136
+
137
+ .doclink {
138
+ max-width: 100%;
139
+ padding: var(--space-4) var(--space-8);
140
+ border: var(--border-width-1) solid var(--border-accent-subtle);
141
+ border-radius: var(--radius-sm);
142
+ background: var(--surface-accent-lower);
143
+ font-family: var(--code-font-family);
144
+ font-size: var(--font-size-sm);
145
+ color: var(--text-accent);
146
+ overflow-wrap: break-word;
147
+ text-align: left;
148
+ cursor: pointer;
149
+ }
150
+
151
+ .doclink:hover {
152
+ background: var(--surface-accent-low);
153
+ }
154
+
155
+ .meta {
156
+ display: flex;
157
+ align-items: center;
158
+ gap: var(--space-12);
159
+ flex-wrap: wrap;
160
+ margin-bottom: var(--space-12);
161
+ }
162
+
163
+ .kind {
164
+ margin: 0;
165
+ font-family: var(--heading-sm-font-family);
166
+ font-size: var(--heading-sm-font-size);
167
+ font-weight: var(--heading-sm-font-weight);
168
+ line-height: var(--heading-sm-line-height);
169
+ letter-spacing: var(--heading-sm-letter-spacing);
170
+ color: var(--text-secondary);
171
+ }
172
+
173
+ .step-n {
174
+ margin-right: var(--space-8);
175
+ font-weight: var(--font-weight-bold);
176
+ }
177
+
178
+ .range {
179
+ font-family: var(--code-font-family);
180
+ font-size: var(--font-size-md);
181
+ color: var(--text-tertiary);
182
+ }
183
+
184
+ .desc {
185
+ margin: 0;
186
+ font-family: var(--body-md-font-family);
187
+ font-size: var(--body-md-font-size);
188
+ font-weight: var(--body-md-font-weight);
189
+ line-height: var(--body-md-line-height);
190
+ letter-spacing: var(--body-md-letter-spacing);
191
+ color: var(--text-secondary);
192
+ }
193
+
194
+ .command {
195
+ margin-top: var(--space-16);
196
+ }
197
+
198
+ .chips {
199
+ display: flex;
200
+ flex-wrap: wrap;
201
+ gap: var(--space-12);
202
+ margin: var(--space-20) 0 0;
203
+ padding: 0;
204
+ list-style: none;
205
+ }
206
+ </style>