@motion-proto/live-tokens 0.94.2 → 0.95.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 (108) hide show
  1. package/.claude/skills/live-tokens-create-page/SKILL.md +7 -3
  2. package/CHANGELOG.md +108 -0
  3. package/README.md +6 -6
  4. package/dist-plugin/{chunk-7XSUHJUH.js → chunk-4J6JPSVS.js} +53 -2
  5. package/dist-plugin/{chunk-W5VQV32K.js → chunk-GYRULB2X.js} +1 -1
  6. package/dist-plugin/{chunk-ONYAIXCZ.js → chunk-QQASYPW7.js} +32 -9
  7. package/dist-plugin/index.cjs +598 -17
  8. package/dist-plugin/index.d.cts +9 -1
  9. package/dist-plugin/index.d.ts +9 -1
  10. package/dist-plugin/index.js +513 -6
  11. package/dist-plugin/migrateData/index.cjs +32 -9
  12. package/dist-plugin/migrateData/index.js +2 -2
  13. package/dist-plugin/setColors/index.cjs +32 -22
  14. package/dist-plugin/setColors/index.js +2 -15
  15. package/dist-plugin/setGeometry/index.cjs +32 -9
  16. package/dist-plugin/setGeometry/index.js +1 -1
  17. package/dist-plugin/tokensCssMigrations/index.cjs +53 -2
  18. package/dist-plugin/tokensCssMigrations/index.d.cts +9 -2
  19. package/dist-plugin/tokensCssMigrations/index.d.ts +9 -2
  20. package/dist-plugin/tokensCssMigrations/index.js +1 -1
  21. package/package.json +8 -3
  22. package/src/demo/ChromeSelect.svelte +111 -0
  23. package/src/demo/Demo.svelte +39 -5
  24. package/src/demo/DemoBar.svelte +33 -14
  25. package/src/demo/FloatingTokenTags.css +33 -4
  26. package/src/demo/FloatingTokenTags.svelte +81 -68
  27. package/src/demo/Section.svelte +1 -7
  28. package/src/demo/SketchSelect.svelte +36 -12
  29. package/src/demo/SourceLinks.svelte +5 -4
  30. package/src/demo/TestingLoops.svelte +128 -19
  31. package/src/demo/ThemeSelect.svelte +34 -11
  32. package/src/demo/evalResults.ts +7 -7
  33. package/src/demo/sections/SectionClaude.svelte +20 -13
  34. package/src/demo/sections/SectionFooter.svelte +4 -5
  35. package/src/demo/sections/SectionGetStarted.svelte +5 -6
  36. package/src/demo/sections/SectionHero.svelte +43 -23
  37. package/src/demo/sections/SectionKit.svelte +141 -45
  38. package/src/demo/sections/SectionLayers.svelte +3 -3
  39. package/src/demo/sections/SectionOffering.svelte +8 -23
  40. package/src/editor/bootstrap.ts +12 -6
  41. package/src/editor/component-editor/ImageEditor.svelte +1 -1
  42. package/src/editor/component-editor/ImageLightboxEditor.svelte +3 -4
  43. package/src/editor/component-editor/registration.ts +36 -0
  44. package/src/editor/component-editor/registry.ts +5 -12
  45. package/src/editor/component-editor/scaffolding/ShadowBackdrop.svelte +11 -2
  46. package/src/editor/component-editor/scaffolding/StateBlock.svelte +7 -0
  47. package/src/editor/component-editor/scaffolding/TokenLayout.svelte +1 -2
  48. package/src/editor/component-editor/scaffolding/VariantGroup.svelte +17 -2
  49. package/src/editor/core/store/editorPersistence.ts +6 -1
  50. package/src/editor/core/store/editorRenderer.ts +1 -4
  51. package/src/editor/core/store/editorStore.ts +5 -9
  52. package/src/editor/core/store/editorTypes.ts +2 -2
  53. package/src/editor/core/themes/migrations/2026-10-15-responsive-columns.ts +40 -0
  54. package/src/editor/core/themes/migrations/index.ts +2 -0
  55. package/src/editor/core/themes/slices/columns.ts +112 -42
  56. package/src/editor/docs/Docs.svelte +25 -22
  57. package/src/editor/docs/chapters.ts +1 -0
  58. package/src/editor/docs/content/editing-tokens.md +5 -3
  59. package/src/editor/docs/content/production-css.md +116 -0
  60. package/src/editor/docs/content/themes-workflow.md +2 -0
  61. package/src/editor/docs/content.generated.ts +3 -2
  62. package/src/editor/index.ts +2 -1
  63. package/src/editor/overlay/LiveEditorOverlay.svelte +67 -19
  64. package/src/editor/overlay/LiveTokensRouter.svelte +8 -4
  65. package/src/editor/pages/Editor.svelte +15 -1
  66. package/src/editor/pages/EditorShell.svelte +312 -99
  67. package/src/editor/skill-atlas/SkillAtlas.svelte +111 -24
  68. package/src/editor/skill-atlas/TreeCanvas.svelte +14 -0
  69. package/src/editor/skill-atlas/skillSources.generated.ts +1 -1
  70. package/src/editor/skill-atlas/trees/create-page.ts +24 -24
  71. package/src/editor/skill-atlas/wireLayout.ts +62 -0
  72. package/src/editor/ui/BezierCurveEditor.svelte +3 -0
  73. package/src/editor/ui/FontStackEditor.svelte +2 -2
  74. package/src/editor/ui/PaletteEditor.svelte +64 -6
  75. package/src/editor/ui/UIPaletteSelector.svelte +2 -0
  76. package/src/editor/ui/colors/ColorsTab.svelte +5 -2
  77. package/src/editor/ui/palette/OverridesPanel.svelte +1 -0
  78. package/src/editor/ui/palette/ScaleCurveEditor.svelte +127 -18
  79. package/src/editor/ui/sections/ColumnsSection.svelte +79 -49
  80. package/src/editor/ui/sections/ShadowsSection.svelte +14 -0
  81. package/src/editor/ui/sections/WashesSection.svelte +11 -0
  82. package/src/editor/ui/sketch/SketchTab.svelte +1 -1
  83. package/src/live-tokens/data/colors-and-type/autumn.json +1 -4
  84. package/src/live-tokens/data/colors-and-type/default.json +1 -4
  85. package/src/live-tokens/data/colors-and-type/halloween.json +1 -4
  86. package/src/live-tokens/data/colors-and-type/midnight-study.json +1 -4
  87. package/src/live-tokens/data/colors-and-type/ocean.json +1 -4
  88. package/src/live-tokens/data/colors-and-type/royal-velvet.json +1 -4
  89. package/src/live-tokens/data/colors-and-type/sketchy.json +1 -4
  90. package/src/live-tokens/data/colors-and-type/spring-meadow.json +1 -4
  91. package/src/live-tokens/data/colors-and-type/sunset.json +1 -4
  92. package/src/live-tokens/data/themes/autumn.json +1 -4
  93. package/src/live-tokens/data/themes/halloween.json +1 -4
  94. package/src/live-tokens/data/themes/midnight-study.json +1 -4
  95. package/src/live-tokens/data/themes/ocean.json +1 -4
  96. package/src/live-tokens/data/themes/royal-velvet.json +1 -4
  97. package/src/live-tokens/data/themes/sketchy.json +1 -4
  98. package/src/live-tokens/data/themes/spring-meadow.json +1 -4
  99. package/src/live-tokens/data/themes/sunset.json +1 -4
  100. package/src/live-tokens/data/tokens.generated.css +1 -4
  101. package/src/system/components/SectionDivider.svelte +4 -0
  102. package/src/system/styles/CONVENTIONS.md +1 -1
  103. package/src/system/styles/tokens.css +30 -4
  104. package/template/src/main.ts +2 -2
  105. package/template/src/pages/Home.svelte +11 -8
  106. package/template/vite.config.ts +7 -3
  107. package/src/system/assets/offering.webp +0 -0
  108. /package/dist-plugin/{chunk-O6GQ6GBH.js → chunk-A4TBP4MM.js} +0 -0
@@ -2,6 +2,7 @@
2
2
  import { run } from 'svelte/legacy';
3
3
 
4
4
  import { onMount } from 'svelte';
5
+ import { MediaQuery } from 'svelte/reactivity';
5
6
  import VariablesTab from '../ui/VariablesTab.svelte';
6
7
  import ColorsTab from '../ui/colors/ColorsTab.svelte';
7
8
  import EditorViewSwitcher from '../ui/EditorViewSwitcher.svelte';
@@ -9,7 +10,7 @@
9
10
  import SketchTab from '../ui/sketch/SketchTab.svelte';
10
11
  import ThemePanel from '../ui/ThemePanel.svelte';
11
12
  import { scrollSectionIntoView } from '../ui/scrollSection';
12
- import { editorView, sidebarCondensed, selectedComponent } from '../core/store/editorViewStore';
13
+ import { editorView, sidebarCondensed, selectedComponent, type EditorView } from '../core/store/editorViewStore';
13
14
  import { componentDirty } from '../core/store/editorStore';
14
15
  import { getComponentRegistryEntries, validateRegistryAgainstServerScan } from '../component-editor/registry';
15
16
  import { listComponents } from '../core/components/componentConfigService';
@@ -41,6 +42,8 @@
41
42
  { id: 'sketch-preview', label: 'Preview', icon: 'fas fa-eye' }
42
43
  ];
43
44
 
45
+ let { onclose }: { onclose?: () => void } = $props();
46
+
44
47
  const allComponentNavItems = getComponentRegistryEntries().map(({ id, label, icon, origin }) => ({ id, label, icon, origin }));
45
48
  const systemNavItems = allComponentNavItems.filter((i) => i.origin === 'system');
46
49
  const customNavItems = allComponentNavItems.filter((i) => i.origin === 'custom');
@@ -104,6 +107,62 @@
104
107
  sidebarCondensed.update((v) => !(v === true));
105
108
  }
106
109
 
110
+ // A narrow editor shows one section at a time, picked from a select, because
111
+ // the rail would leave the section itself no room.
112
+ const singleSection = new MediaQuery('max-width: 600px');
113
+ let themeScreen = $state(false);
114
+ let menuOpen = $state(false);
115
+ let screenBarHeight = $state(0);
116
+
117
+ const sectionNav: Partial<Record<EditorView, { id: string }[]>> = {
118
+ tokens: tokenNavItems,
119
+ sketch: sketchNavItems,
120
+ colors: colorsNavItems,
121
+ };
122
+
123
+ function shownSection(view: EditorView): string | null {
124
+ const items = sectionNav[view];
125
+ if (!items) return null;
126
+ return items.some((i) => i.id === selectedTokenSection) ? selectedTokenSection : items[0].id;
127
+ }
128
+
129
+ let menuItems = $derived(
130
+ $editorView === 'components' ? allComponentNavItems : (sectionNav[$editorView] as typeof tokenNavItems),
131
+ );
132
+ let activeItemId = $derived(
133
+ themeScreen ? null : $editorView === 'components' ? $selectedComponent : shownSection($editorView),
134
+ );
135
+ let activeItemLabel = $derived(menuItems.find((i) => i.id === activeItemId)?.label ?? '');
136
+
137
+ function pickSection(id: string) {
138
+ themeScreen = false;
139
+ if ($editorView === 'components') {
140
+ selectComponent(id);
141
+ } else {
142
+ selectedTokenSection = id;
143
+ sectionJump = { id };
144
+ }
145
+ menuOpen = false;
146
+ window.scrollTo(0, 0);
147
+ }
148
+
149
+ function pickTheme() {
150
+ themeScreen = true;
151
+ menuOpen = false;
152
+ window.scrollTo(0, 0);
153
+ }
154
+
155
+ // The panes render every section; a narrow editor marks all but the picked
156
+ // one so they drop out of the flow.
157
+ $effect(() => {
158
+ const items = sectionNav[$editorView];
159
+ if (!items) return;
160
+ const only = singleSection.current ? shownSection($editorView) : null;
161
+ for (const { id } of items) {
162
+ document.getElementById(id)?.toggleAttribute('data-off-screen', only !== null && id !== only);
163
+ }
164
+ });
165
+
107
166
  onMount(async () => {
108
167
  try {
109
168
  const summaries = await listComponents();
@@ -114,105 +173,144 @@
114
173
  });
115
174
  </script>
116
175
 
117
- <div class="layout" class:condensed>
118
- <nav class="sidebar" class:condensed>
119
- <div class="rail-toggle-row">
176
+ <svelte:window onkeydown={(e) => { if (menuOpen && e.key === 'Escape') menuOpen = false; }} />
177
+
178
+ <!-- Panes that pin a preview offset it by --editor-sticky-top to clear the
179
+ pinned select bar. -->
180
+ <div
181
+ class="layout"
182
+ class:condensed
183
+ class:single-section={singleSection.current}
184
+ style:--editor-sticky-top="{singleSection.current ? screenBarHeight : 0}px"
185
+ >
186
+ {#if singleSection.current}
187
+ <header class="screen-bar" bind:clientHeight={screenBarHeight}>
120
188
  <button
121
189
  type="button"
122
- class="rail-toggle"
123
- aria-label={condensed ? 'Expand sidebar' : 'Collapse sidebar'}
124
- aria-expanded={!condensed}
125
- onclick={toggleCondensed}
190
+ class="screen-picker"
191
+ aria-expanded={menuOpen}
192
+ aria-controls="screen-menu"
193
+ onclick={() => (menuOpen = !menuOpen)}
126
194
  >
127
- <i class="fas {condensed ? 'fa-arrow-right' : 'fa-arrow-left'}"></i>
195
+ {#if themeScreen}
196
+ <span class="screen-picker-section">Theme</span>
197
+ {:else}
198
+ <span class="screen-picker-section">{activeItemLabel}</span>
199
+ {/if}
200
+ <i class="fas {menuOpen ? 'fa-chevron-up' : 'fa-chevron-down'}" aria-hidden="true"></i>
128
201
  </button>
129
- </div>
130
-
131
- <EditorViewSwitcher {condensed} />
132
-
133
- {#if $editorView === 'tokens'}
134
- <div class="nav-items">
135
- {#each tokenNavItems as item (item.id)}
136
- <button
137
- class="nav-item"
138
- class:active={selectedTokenSection === item.id}
139
- onmouseenter={(e) => showHint(item.label, e.currentTarget)}
140
- onmouseleave={hideHint}
141
- onclick={() => scrollToSection(item.id)}
142
- >
143
- <i class={item.icon}></i>
144
- <span class="nav-label">{item.label}</span>
145
- </button>
146
- {/each}
147
- </div>
148
- {#if !condensed}
149
- <div class="sidebar-footer">
150
- <ThemePanel />
151
- </div>
202
+ {#if onclose}
203
+ <button type="button" class="screen-close" aria-label="Close the editor" onclick={onclose}>
204
+ <i class="fas fa-xmark"></i>
205
+ </button>
152
206
  {/if}
153
- {:else if $editorView === 'sketch'}
154
- <div class="nav-items">
155
- {#each sketchNavItems as item (item.id)}
156
- <button
157
- class="nav-item"
158
- class:active={selectedTokenSection === item.id}
159
- onmouseenter={(e) => showHint(item.label, e.currentTarget)}
160
- onmouseleave={hideHint}
161
- onclick={() => jumpToSketchSection(item.id)}
162
- >
163
- <i class={item.icon}></i>
164
- <span class="nav-label">{item.label}</span>
165
- </button>
166
- {/each}
167
- </div>
168
- {#if !condensed}
169
- <div class="sidebar-footer">
170
- <ThemePanel />
207
+ </header>
208
+ {#if menuOpen}
209
+ <nav id="screen-menu" class="screen-menu" aria-label="Editor sections">
210
+ <EditorViewSwitcher />
211
+ <div class="nav-items">
212
+ {#each menuItems as item (item.id)}
213
+ <button
214
+ type="button"
215
+ class="nav-item"
216
+ class:active={activeItemId === item.id}
217
+ class:dirty={$editorView === 'components' && $componentDirty[item.id]}
218
+ onclick={() => pickSection(item.id)}
219
+ >
220
+ <i class={item.icon}></i>
221
+ <span class="nav-label">{item.label}</span>
222
+ {#if $editorView === 'components' && $componentDirty[item.id]}
223
+ <span class="dirty-dot" aria-label="Unsaved changes" title="Unsaved changes"></span>
224
+ {/if}
225
+ </button>
226
+ {/each}
171
227
  </div>
172
- {/if}
173
- {:else if $editorView === 'colors'}
174
- <div class="nav-items">
175
- {#each colorsNavItems as item (item.id)}
176
- <button
177
- class="nav-item"
178
- class:active={selectedTokenSection === item.id}
179
- onmouseenter={(e) => showHint(item.label, e.currentTarget)}
180
- onmouseleave={hideHint}
181
- onclick={() => scrollToSection(item.id)}
182
- >
183
- <i class={item.icon}></i>
184
- <span class="nav-label">{item.label}</span>
185
- </button>
186
- {/each}
228
+ <div class="nav-divider"></div>
229
+ <button type="button" class="nav-item" class:active={themeScreen} onclick={pickTheme}>
230
+ <i class="fas fa-swatchbook"></i>
231
+ <span class="nav-label">Theme</span>
232
+ </button>
233
+ </nav>
234
+ {/if}
235
+ {:else}
236
+ <nav class="sidebar" class:condensed>
237
+ <div class="rail-toggle-row">
238
+ <button
239
+ type="button"
240
+ class="rail-toggle"
241
+ aria-label={condensed ? 'Expand sidebar' : 'Collapse sidebar'}
242
+ aria-expanded={!condensed}
243
+ onclick={toggleCondensed}
244
+ >
245
+ <i class="fas {condensed ? 'fa-arrow-right' : 'fa-arrow-left'}"></i>
246
+ </button>
187
247
  </div>
188
- {#if !condensed}
189
- <div class="sidebar-footer">
190
- <ThemePanel />
248
+
249
+ <EditorViewSwitcher {condensed} />
250
+
251
+ {#if $editorView === 'tokens'}
252
+ <div class="nav-items">
253
+ {#each tokenNavItems as item (item.id)}
254
+ <button
255
+ class="nav-item"
256
+ class:active={selectedTokenSection === item.id}
257
+ onmouseenter={(e) => showHint(item.label, e.currentTarget)}
258
+ onmouseleave={hideHint}
259
+ onclick={() => scrollToSection(item.id)}
260
+ >
261
+ <i class={item.icon}></i>
262
+ <span class="nav-label">{item.label}</span>
263
+ </button>
264
+ {/each}
191
265
  </div>
192
- {/if}
193
- {:else}
194
- <div class="nav-items">
195
- {#each systemNavItems as item (item.id)}
196
- <button
197
- class="nav-item"
198
- class:active={$selectedComponent === item.id}
199
- class:dirty={$componentDirty[item.id]}
200
- onmouseenter={(e) => showHint(item.label, e.currentTarget)}
201
- onmouseleave={hideHint}
202
- onclick={() => selectComponent(item.id)}
203
- >
204
- <i class={item.icon}></i>
205
- <span class="nav-label">{item.label}</span>
206
- {#if $componentDirty[item.id]}
207
- <span class="dirty-dot" aria-label="Unsaved changes" title="Unsaved changes"></span>
208
- {/if}
209
- </button>
210
- {/each}
211
- {#if customNavItems.length > 0}
212
- <div class="nav-divider">
213
- <span class="nav-divider-label">Custom</span>
266
+ {#if !condensed}
267
+ <div class="sidebar-footer">
268
+ <ThemePanel />
214
269
  </div>
215
- {#each customNavItems as item (item.id)}
270
+ {/if}
271
+ {:else if $editorView === 'sketch'}
272
+ <div class="nav-items">
273
+ {#each sketchNavItems as item (item.id)}
274
+ <button
275
+ class="nav-item"
276
+ class:active={selectedTokenSection === item.id}
277
+ onmouseenter={(e) => showHint(item.label, e.currentTarget)}
278
+ onmouseleave={hideHint}
279
+ onclick={() => jumpToSketchSection(item.id)}
280
+ >
281
+ <i class={item.icon}></i>
282
+ <span class="nav-label">{item.label}</span>
283
+ </button>
284
+ {/each}
285
+ </div>
286
+ {#if !condensed}
287
+ <div class="sidebar-footer">
288
+ <ThemePanel />
289
+ </div>
290
+ {/if}
291
+ {:else if $editorView === 'colors'}
292
+ <div class="nav-items">
293
+ {#each colorsNavItems as item (item.id)}
294
+ <button
295
+ class="nav-item"
296
+ class:active={selectedTokenSection === item.id}
297
+ onmouseenter={(e) => showHint(item.label, e.currentTarget)}
298
+ onmouseleave={hideHint}
299
+ onclick={() => scrollToSection(item.id)}
300
+ >
301
+ <i class={item.icon}></i>
302
+ <span class="nav-label">{item.label}</span>
303
+ </button>
304
+ {/each}
305
+ </div>
306
+ {#if !condensed}
307
+ <div class="sidebar-footer">
308
+ <ThemePanel />
309
+ </div>
310
+ {/if}
311
+ {:else}
312
+ <div class="nav-items">
313
+ {#each systemNavItems as item (item.id)}
216
314
  <button
217
315
  class="nav-item"
218
316
  class:active={$selectedComponent === item.id}
@@ -228,18 +326,41 @@
228
326
  {/if}
229
327
  </button>
230
328
  {/each}
231
- {/if}
232
- </div>
233
- {#if !condensed}
234
- <div class="sidebar-footer">
235
- <ThemePanel />
329
+ {#if customNavItems.length > 0}
330
+ <div class="nav-divider">
331
+ <span class="nav-divider-label">Custom</span>
332
+ </div>
333
+ {#each customNavItems as item (item.id)}
334
+ <button
335
+ class="nav-item"
336
+ class:active={$selectedComponent === item.id}
337
+ class:dirty={$componentDirty[item.id]}
338
+ onmouseenter={(e) => showHint(item.label, e.currentTarget)}
339
+ onmouseleave={hideHint}
340
+ onclick={() => selectComponent(item.id)}
341
+ >
342
+ <i class={item.icon}></i>
343
+ <span class="nav-label">{item.label}</span>
344
+ {#if $componentDirty[item.id]}
345
+ <span class="dirty-dot" aria-label="Unsaved changes" title="Unsaved changes"></span>
346
+ {/if}
347
+ </button>
348
+ {/each}
349
+ {/if}
236
350
  </div>
351
+ {#if !condensed}
352
+ <div class="sidebar-footer">
353
+ <ThemePanel />
354
+ </div>
355
+ {/if}
237
356
  {/if}
238
- {/if}
239
- </nav>
357
+ </nav>
358
+ {/if}
240
359
 
241
360
  <main class="content">
242
- {#if $editorView === 'tokens'}
361
+ {#if singleSection.current && themeScreen}
362
+ <ThemePanel />
363
+ {:else if $editorView === 'tokens'}
243
364
  <VariablesTab />
244
365
  {:else if $editorView === 'colors'}
245
366
  <ColorsTab />
@@ -271,6 +392,98 @@
271
392
  --sidebar-w: 48px;
272
393
  }
273
394
 
395
+ .layout.single-section {
396
+ grid-template-columns: minmax(0, 1fr);
397
+ grid-template-rows: auto 1fr;
398
+ }
399
+
400
+ .screen-bar {
401
+ position: sticky;
402
+ top: 0;
403
+ z-index: 2;
404
+ display: flex;
405
+ align-items: center;
406
+ gap: var(--ui-space-8);
407
+ padding: var(--ui-space-8) var(--ui-space-12);
408
+ background: black;
409
+ border-bottom: 1px solid var(--ui-border-low);
410
+ }
411
+
412
+ .screen-picker {
413
+ flex: 1;
414
+ min-width: 0;
415
+ display: flex;
416
+ align-items: baseline;
417
+ gap: var(--ui-space-8);
418
+ padding: var(--ui-space-8) var(--ui-space-12);
419
+ background: var(--ui-surface-low);
420
+ border: 1px solid var(--ui-border);
421
+ border-radius: var(--ui-radius-md);
422
+ color: var(--ui-text-primary);
423
+ font-size: var(--ui-font-size-md);
424
+ text-align: left;
425
+ cursor: pointer;
426
+ }
427
+
428
+ .screen-picker-section {
429
+ min-width: 0;
430
+ overflow: hidden;
431
+ text-overflow: ellipsis;
432
+ white-space: nowrap;
433
+ }
434
+
435
+ .screen-picker i {
436
+ margin-left: auto;
437
+ align-self: center;
438
+ color: var(--ui-text-tertiary);
439
+ }
440
+
441
+ /* Fills the editor under the bar; picking a row closes it. */
442
+ .screen-menu {
443
+ position: fixed;
444
+ top: var(--editor-sticky-top);
445
+ right: 0;
446
+ bottom: 0;
447
+ left: 0;
448
+ z-index: 3;
449
+ overflow-y: auto;
450
+ padding: var(--ui-space-12) var(--ui-space-8) var(--ui-space-24);
451
+ background: black;
452
+ }
453
+
454
+ .screen-menu .nav-item {
455
+ height: 44px;
456
+ font-size: var(--ui-font-size-lg);
457
+ }
458
+
459
+ .screen-menu .dirty-dot {
460
+ top: 12px;
461
+ }
462
+
463
+ .screen-close {
464
+ display: flex;
465
+ align-items: center;
466
+ justify-content: center;
467
+ flex: none;
468
+ width: 40px;
469
+ height: 40px;
470
+ background: none;
471
+ border: none;
472
+ border-radius: var(--ui-radius-md);
473
+ color: var(--ui-text-primary);
474
+ font-size: var(--ui-font-size-lg);
475
+ cursor: pointer;
476
+ }
477
+
478
+ .screen-close:hover {
479
+ background: var(--ui-hover);
480
+ }
481
+
482
+ /* Beats each pane's own display rule for its sections. */
483
+ .content :global([data-off-screen]) {
484
+ display: none !important;
485
+ }
486
+
274
487
  .sidebar {
275
488
  position: sticky;
276
489
  top: 0;