@happyvertical/smrt-svelte 0.55.15 → 0.55.17

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 (153) hide show
  1. package/README.md +5 -3
  2. package/agents/cookbook-shell.md +7 -1
  3. package/agents/overview-surfaces.md +5 -0
  4. package/agents/workspace.md +145 -11
  5. package/dist/browser-ai/svelte/components/DownloadProgress.svelte +22 -19
  6. package/dist/browser-ai/svelte/components/ModelStatusControl.svelte +16 -13
  7. package/dist/browser-ai/svelte/components/STTTest.svelte +41 -38
  8. package/dist/browser-ai/svelte/components/VoiceInput.svelte +17 -14
  9. package/dist/components/activity/ActivityList.svelte +1 -1
  10. package/dist/components/app/AppShell.svelte +274 -9
  11. package/dist/components/app/AppShell.svelte.d.ts +63 -2
  12. package/dist/components/app/AppShell.svelte.d.ts.map +1 -1
  13. package/dist/components/app/DockToggles.svelte +27 -1
  14. package/dist/components/app/DockToggles.svelte.d.ts.map +1 -1
  15. package/dist/components/app/OwnerSetupForm.svelte +98 -34
  16. package/dist/components/app/OwnerSetupForm.svelte.d.ts +4 -0
  17. package/dist/components/app/OwnerSetupForm.svelte.d.ts.map +1 -1
  18. package/dist/components/app/PhoneTabBar.svelte +136 -0
  19. package/dist/components/app/PhoneTabBar.svelte.d.ts +22 -0
  20. package/dist/components/app/PhoneTabBar.svelte.d.ts.map +1 -0
  21. package/dist/components/app/ShellSettingsPage.svelte +17 -2
  22. package/dist/components/app/ShellSettingsPage.svelte.d.ts +11 -16
  23. package/dist/components/app/ShellSettingsPage.svelte.d.ts.map +1 -1
  24. package/dist/components/app/dock-toggle.d.ts +3 -2
  25. package/dist/components/app/dock-toggle.d.ts.map +1 -1
  26. package/dist/components/app/index.d.ts +2 -1
  27. package/dist/components/app/index.d.ts.map +1 -1
  28. package/dist/components/app/index.js +1 -0
  29. package/dist/components/app/owner-setup-types.d.ts +5 -0
  30. package/dist/components/app/owner-setup-types.d.ts.map +1 -1
  31. package/dist/components/app/phone-tabs.d.ts +41 -0
  32. package/dist/components/app/phone-tabs.d.ts.map +1 -0
  33. package/dist/components/app/phone-tabs.js +66 -0
  34. package/dist/components/app/slot-item.d.ts +16 -0
  35. package/dist/components/app/slot-item.d.ts.map +1 -1
  36. package/dist/components/app/view-transition.d.ts +43 -0
  37. package/dist/components/app/view-transition.d.ts.map +1 -0
  38. package/dist/components/app/view-transition.js +76 -0
  39. package/dist/components/audit/AuditList.svelte +4 -1
  40. package/dist/components/audit/RecordHistory.svelte +4 -1
  41. package/dist/components/board/Board.svelte +4 -1
  42. package/dist/components/command-palette/CommandPalette.svelte +4 -1
  43. package/dist/components/command-palette/CommandPalette.svelte.d.ts +2 -0
  44. package/dist/components/command-palette/CommandPalette.svelte.d.ts.map +1 -1
  45. package/dist/components/command-palette/CommandPaletteDialog.svelte +3 -0
  46. package/dist/components/command-palette/CommandPaletteTrigger.svelte +3 -0
  47. package/dist/components/cookbook/CookbookApp.svelte +2 -1
  48. package/dist/components/cookbook/CookbookApp.svelte.d.ts.map +1 -1
  49. package/dist/components/cookbook/CookbookSectionPage.svelte +4 -1
  50. package/dist/components/cookbook/brand-theme.d.ts.map +1 -1
  51. package/dist/components/cookbook/brand-theme.js +21 -2
  52. package/dist/components/cookbook/build.js +1 -1
  53. package/dist/components/cookbook/theme.d.ts.map +1 -1
  54. package/dist/components/cookbook/theme.js +9 -5
  55. package/dist/components/cookbook/types.d.ts +5 -1
  56. package/dist/components/cookbook/types.d.ts.map +1 -1
  57. package/dist/components/forms/AddressInput.svelte +25 -22
  58. package/dist/components/forms/CheckboxInput.svelte +8 -5
  59. package/dist/components/forms/DateRangeInput.svelte +41 -38
  60. package/dist/components/forms/DateTimeInput.svelte +29 -26
  61. package/dist/components/forms/FileUpload.svelte +24 -21
  62. package/dist/components/forms/Form.svelte +34 -31
  63. package/dist/components/forms/FormMicButton.svelte +10 -7
  64. package/dist/components/forms/FormScope.svelte +4 -1
  65. package/dist/components/forms/MeasurementInput.svelte +26 -23
  66. package/dist/components/forms/MoneyInput.svelte +18 -15
  67. package/dist/components/forms/NumberInput.svelte +17 -14
  68. package/dist/components/forms/PhoneInput.svelte +37 -34
  69. package/dist/components/forms/SearchInput.svelte +16 -13
  70. package/dist/components/forms/SelectInput.svelte +17 -14
  71. package/dist/components/forms/TextInput.svelte +19 -16
  72. package/dist/components/forms/TextareaInput.svelte +21 -18
  73. package/dist/components/import-export/ImportExport.svelte +4 -1
  74. package/dist/components/module/ModulePanel.svelte +14 -11
  75. package/dist/components/notifications/NotificationBell.svelte +4 -1
  76. package/dist/components/overview/OverviewAssistantUndo.svelte +4 -1
  77. package/dist/components/overview/OverviewGrid.svelte +11 -6
  78. package/dist/components/overview/OverviewGrid.svelte.d.ts.map +1 -1
  79. package/dist/components/overview/WidgetOptionsForm.svelte +3 -0
  80. package/dist/components/overview/widgets/ChartWidget.svelte +7 -4
  81. package/dist/components/overview/widgets/MetricWidget.svelte +5 -2
  82. package/dist/components/overview/widgets/NoteWidget.svelte +5 -2
  83. package/dist/components/overview/widgets/RecordListWidget.svelte +6 -3
  84. package/dist/components/overview/widgets/ShortcutsWidget.svelte +12 -6
  85. package/dist/components/overview/widgets/ShortcutsWidget.svelte.d.ts.map +1 -1
  86. package/dist/components/screens/DetailScreen.svelte +6 -3
  87. package/dist/components/screens/EditForm.svelte +6 -3
  88. package/dist/components/screens/ListScreen.svelte +4 -1
  89. package/dist/components/screens/RecipeScreens.svelte +1 -1
  90. package/dist/components/settings/SettingsCatalog.svelte +4 -1
  91. package/dist/components/sortable/Sortable.svelte +11 -5
  92. package/dist/components/sortable/Sortable.svelte.d.ts.map +1 -1
  93. package/dist/components/workspace/Breadcrumbs.svelte +4 -1
  94. package/dist/components/workspace/NavTree.svelte +4 -1
  95. package/dist/components/workspace/RoleShell.svelte +4 -1
  96. package/dist/components/workspace/WorkspaceShell.svelte +43 -40
  97. package/dist/components/workspace/admin-shell/ActivityItem.svelte +4 -1
  98. package/dist/components/workspace/admin-shell/ActivityList.svelte +5 -2
  99. package/dist/components/workspace/admin-shell/ActivityTicker.svelte +6 -3
  100. package/dist/components/workspace/admin-shell/ActivityToasts.svelte +4 -1
  101. package/dist/components/workspace/admin-shell/AdminShell.svelte +502 -72
  102. package/dist/components/workspace/admin-shell/AdminShell.svelte.d.ts +7 -1
  103. package/dist/components/workspace/admin-shell/AdminShell.svelte.d.ts.map +1 -1
  104. package/dist/components/workspace/admin-shell/AppScopePanel.svelte +4 -1
  105. package/dist/components/workspace/admin-shell/HotkeyInput.svelte +4 -1
  106. package/dist/components/workspace/admin-shell/PhoneBottomBar.svelte +21 -8
  107. package/dist/components/workspace/admin-shell/PhoneBottomBar.svelte.d.ts +9 -2
  108. package/dist/components/workspace/admin-shell/PhoneBottomBar.svelte.d.ts.map +1 -1
  109. package/dist/components/workspace/admin-shell/PhoneTopBar.svelte +4 -1
  110. package/dist/components/workspace/admin-shell/ShellBrand.svelte +3 -0
  111. package/dist/components/workspace/admin-shell/ShellCorner.svelte +4 -1
  112. package/dist/components/workspace/admin-shell/ShellIconButton.svelte +4 -1
  113. package/dist/components/workspace/admin-shell/ShellLayoutEditor.svelte +4 -1
  114. package/dist/components/workspace/admin-shell/ShellNavEditor.svelte +13 -7
  115. package/dist/components/workspace/admin-shell/ShellNavEditor.svelte.d.ts +1 -1
  116. package/dist/components/workspace/admin-shell/ShellNavEditor.svelte.d.ts.map +1 -1
  117. package/dist/components/workspace/admin-shell/ShellNavToggle.svelte +4 -1
  118. package/dist/components/workspace/admin-shell/ShellSectionIcon.svelte +4 -1
  119. package/dist/components/workspace/admin-shell/ShellSectionMenu.svelte +15 -10
  120. package/dist/components/workspace/admin-shell/ShellSectionMenu.svelte.d.ts.map +1 -1
  121. package/dist/components/workspace/admin-shell/ShellSettingsPanel.svelte +236 -48
  122. package/dist/components/workspace/admin-shell/ShellSettingsPanel.svelte.d.ts +11 -1
  123. package/dist/components/workspace/admin-shell/ShellSettingsPanel.svelte.d.ts.map +1 -1
  124. package/dist/components/workspace/admin-shell/ShellTitle.svelte +4 -1
  125. package/dist/components/workspace/admin-shell/ShortcutsOverlay.svelte +4 -1
  126. package/dist/components/workspace/admin-shell/SystemScopePanel.svelte +4 -1
  127. package/dist/components/workspace/admin-shell/SystemStatusChips.svelte +5 -2
  128. package/dist/components/workspace/admin-shell/TenantNav.svelte +81 -36
  129. package/dist/components/workspace/admin-shell/TenantNav.svelte.d.ts +4 -3
  130. package/dist/components/workspace/admin-shell/TenantNav.svelte.d.ts.map +1 -1
  131. package/dist/components/workspace/admin-shell/WorkspaceAccountMenu.svelte +305 -53
  132. package/dist/components/workspace/admin-shell/WorkspaceAccountMenu.svelte.d.ts +15 -2
  133. package/dist/components/workspace/admin-shell/WorkspaceAccountMenu.svelte.d.ts.map +1 -1
  134. package/dist/components/workspace/admin-shell/motion.d.ts +19 -0
  135. package/dist/components/workspace/admin-shell/motion.d.ts.map +1 -0
  136. package/dist/components/workspace/admin-shell/motion.js +44 -0
  137. package/dist/components/workspace/admin-shell/settings.d.ts +1 -0
  138. package/dist/components/workspace/admin-shell/settings.d.ts.map +1 -1
  139. package/dist/components/workspace/admin-shell/settings.js +1 -1
  140. package/dist/components/workspace/admin-shell/shell-icons.d.ts +8 -0
  141. package/dist/components/workspace/admin-shell/shell-icons.d.ts.map +1 -1
  142. package/dist/components/workspace/admin-shell/shell-icons.js +8 -0
  143. package/dist/components/workspace/admin-shell/state.svelte.d.ts +6 -0
  144. package/dist/components/workspace/admin-shell/state.svelte.d.ts.map +1 -1
  145. package/dist/components/workspace/admin-shell/state.svelte.js +15 -0
  146. package/dist/components/workspace/admin-shell/types.d.ts +13 -3
  147. package/dist/components/workspace/admin-shell/types.d.ts.map +1 -1
  148. package/dist/components/workspace/tools-dock/ToolsDock.svelte +41 -38
  149. package/dist/i18n/strings.workspace.d.ts +37 -0
  150. package/dist/i18n/strings.workspace.d.ts.map +1 -1
  151. package/dist/i18n/strings.workspace.js +42 -2
  152. package/dist/mcp-apps/McpAppsBridge.svelte +4 -1
  153. package/package.json +14 -14
package/README.md CHANGED
@@ -572,8 +572,8 @@ keys the shell renders exactly as before.
572
572
  on scroll (`phone.hideOnScroll`, pinned by `pinChrome` or an open drawer);
573
573
  `phoneBottomBar` is a bottom row that a form's `[data-form-action-bar]` (see
574
574
  smrt-ui `FormActionBar`) replaces and the on-screen keyboard hides
575
- (`:root[data-keyboard-open]`). `phone.scrim` dims the page behind a drawer or
576
- sheet, `phone.swipeToClose` closes drawers by swiping. A `path` change on a
575
+ (`:root[data-keyboard-open]`). `phone.scrim` (default on) dims the page behind a drawer or
576
+ sheet, `phone.swipeToClose` (default on) closes drawers by swiping. A `path` change on a
577
577
  phone closes open drawers. `overlays` is a layer above the edges (and above
578
578
  the bottom bar's row) for `PhoneSheet`s and status strips.
579
579
  - **Page contracts** on phones: `data-shell-breadcrumbs` is hidden only when
@@ -857,7 +857,9 @@ AdminShell's edge toggle buttons and WASD hotkeys are opt-in via `edgeToggles`
857
857
  keep the drop-down behaviour; `showTenantToggle` is a deprecated alias for
858
858
  `edgeToggles.left`), a Menu opener in narrow layouts, and the
859
859
  system toggle alongside a custom `systemBar` that has a `systemPanel` to open
860
- (a `systemBar` with no `systemPanel` owns the bottom band and draws no toggle). Closed narrow drawers are inert;
860
+ (a `systemBar` with no `systemPanel` owns the bottom band and draws no toggle). The left toggle is an
861
+ icon-only chevron pinned to the bottom of the sidebar rail (its accessible name is
862
+ `Collapse Left sidebar` / `Expand Left sidebar`); the other edges keep their labelled buttons. Closed narrow drawers are inert;
861
863
  opening focuses the first control, and closing or Escape restores the opener.
862
864
  TenantNav accepts `density="touch"` for canonical 48px link targets, including
863
865
  collapsed rail links; omit density to inherit the theme's control density.
@@ -29,7 +29,7 @@ sample data source are not part of it.
29
29
  the selected recipes and the models they or the cookbook's `features` name, so
30
30
  a load serializes a few KB instead of the whole workspace.
31
31
  - **`buildCookbookShell({ cookbook, catalog, ... })`** returns a `CookbookShell`:
32
- `navGroups` for `AppShell` (`navMode: 'sections'`, one group per suggested
32
+ `navGroups` for `AppShell` (one group per suggested
33
33
  section, icon and section-page `href`), `layout` (the cookbook's, passed to
34
34
  the shell, which applies order/hidden/labels itself), `sections` and `entries`
35
35
  (every entry by stable id), `theme`, `overviews`, recipe surfaces
@@ -37,6 +37,9 @@ sample data source are not part of it.
37
37
  `issues`. It never throws for cookbook content: an unknown recipe, a nav model
38
38
  the catalog lacks or a feature that is not exposed becomes an `issues` entry
39
39
  and is left out.
40
+ - `CookbookApp` uses `navMode: 'sections-with-items'` by default: the open
41
+ drawer shows section pages and their entries, while the rail keeps section
42
+ icons. Hosts can choose `navMode: 'sections'` for headings only.
40
43
  - **Ids are the contract.** Section layout ids are `section:<id>` (a recipe's
41
44
  `section`, else its `group`, else the recipe) or `custom:<slug>` (the layout's
42
45
  own); entries are `item:<package>:<Model>[:<key>]`. They never name labels or
@@ -66,6 +69,9 @@ sample data source are not part of it.
66
69
  `validateCookbook` is where it is rejected). A brand colour becomes the preset
67
70
  id `cookbook-brand-<hex>[-<font>]`; the colour/font pair is encoded in the id
68
71
  because `ThemeProvider` looks a registered theme up once per id.
72
+ A top-level `fontFamily` keeps the built-in preset's palette, spacing and
73
+ shape while replacing its typography. It takes precedence over the legacy
74
+ `custom.fontFamily` when both are present.
69
75
  - **Recipe surfaces**: `shell-widget` surfaces are returned with their slot (a
70
76
  smrt-svelte `ShellSlot`; the equality with `RecipeShellSlot` is a typechecked
71
77
  assertion), `route` and `settings-panel` as data, `widget` surfaces grouped by
@@ -158,6 +158,11 @@ Call `destroy()` when the owner unmounts.
158
158
 
159
159
  ## Grid and edit mode (`OverviewGrid.svelte`)
160
160
 
161
+ The core shortcuts widget draws each shortcut with an inline icon/title heading.
162
+ The icon uses `--smrt-color-primary` from the active theme, matching the
163
+ `ShellSectionMenu` card layout; descriptions remain below the heading. Hosts
164
+ may still provide an icon component for their own glyphs.
165
+
161
166
  Props in `grid-types.ts`. `editing` defaults to the shell's layout editor
162
167
  (`tryUseShellLayout()?.editing`), so the same pencil edits the grid under an
163
168
  `AppShell` with `layoutEditing`; pass `editing` to drive it without a shell. It is
@@ -53,6 +53,8 @@ to shrink; use safe alignment if aligning its contents to the end.
53
53
 
54
54
  Sidebar-only shells may set `top: false`. In that mode the configured brand is
55
55
  shown at the top of the expanded tenant panel as well as in the compact rail.
56
+ When the top header is visible, its brand is the only copy; collapsing the
57
+ left sidebar does not add a second logo to the rail.
56
58
  Use `tenantRailFooter` for a control pinned below collapsed navigation; it sits
57
59
  outside the rail's scroll clip so menus can open over the workspace. Pair it
58
60
  with `WorkspaceAccountMenu compact` for an avatar-only trigger that retains the
@@ -65,6 +67,25 @@ The root grid has five rows: `header` · top edge · body · bottom edge · phon
65
67
  bottom bar. The header and phone-bar tracks are `0rem` unless their snippets
66
68
  render, so hosts that pass none of the new props get the original layout; keep
67
69
  that invariant (`AdminShell.responsive.test.ts` "backward compatibility").
70
+
71
+ **Empty regions render nothing.** The header band, footer band and right edge
72
+ are skipped (and their tracks collapse to `0rem`, the grid keeps its five rows)
73
+ when nothing would render in them: no slot content, `appBar`/`systemBar`, corners,
74
+ toggles, focus tools, mounted drawer, or edit-mode controls. A default
75
+ `AdminShell` still shows its brand, so its header stays; an app with no
76
+ footer content and no dock tools has no footer and no right strip.
77
+
78
+ **Phone defaults.** `phone.scrim` and `phone.swipeToClose` are on (pass `false`
79
+ to turn one off). Opening the left or right surface collapses the other
80
+ (`ShellState.closeExclusivePeers`, not persisted), and starting a layout edit
81
+ closes any open surface. The Menu opener is an icon button (hamburger, name
82
+ "Menu"); the left drawer's title is the app brand and its close control is an
83
+ icon-only "Close menu". While the right edge has focus tools, phones get a
84
+ "Tools" icon opener at the header end (`phoneDockOpener`, default true;
85
+ `AppShell` turns it off when `dockToggles` already open the dock) and the edge
86
+ presents as a drawer (or sheet) with an icon-only "Close tools". Chrome buttons,
87
+ rail tool buttons and dock toggles use `--smrt-touch-target-min` on phones. A
88
+ tool without an icon uses the generic tool icon, never its first letter.
68
89
  Phone drawers and the bottom drawer offset themselves by the header and phone
69
90
  bar tracks. `shell.viewport` comes from `ADMIN_SHELL_PHONE_QUERY` (48rem, the
70
91
  same boundary as the CSS media query — never make one configurable without the
@@ -72,6 +93,27 @@ other) and `ADMIN_SHELL_DESKTOP_QUERY` (64rem); `installShellViewport` runs on
72
93
  mount and the `ShellState` constructor detects the initial class so the first
73
94
  paint is right.
74
95
 
96
+ **Phone tab bar (`AppShell` `phoneTabBar`, default `false`).** On phones it
97
+ fills `AdminShell`'s `phoneBottomBar` track; conceptually that is the footer
98
+ region's phone presentation (its center slot), not a new region. Tabs, in
99
+ order: the first N top-level nav items (flat `nav`, then group entries, or one
100
+ per group in `navMode: 'sections'`; icon + label, `aria-current="page"` from
101
+ `currentHref`, placeholder glyph when no icon), the dock tab (first
102
+ `dockToggles` entry, else a "Tools" tab while the right edge has tools), then
103
+ "More" (opens the left drawer) only when nav overflows. `N` defaults to 4 and
104
+ includes the dock tab; `phoneTabBar={{ items: n }}` overrides. Selection is the
105
+ pure `planPhoneTabs` in `app/phone-tabs.ts`; `PhoneTabBar.svelte` renders it
106
+ through `PhoneBottomBar` (which now also takes `iconName` entries and an
107
+ `iconComponent`). With the bar on, the header "Tools" opener and the header copy
108
+ of the dock tab's toggle are not rendered on phones. `phoneDock` (`'sheet' |
109
+ 'drawer'`, default `'sheet'` with the tab bar, else `'drawer'`; an explicit value
110
+ beats `config.right.phone`) sets the right edge's phone presentation; the sheet
111
+ already sits between the top bars and the phone-bar track, so it rises above the
112
+ tab bar. Both props are read once at mount (like `config`). Header-end slot
113
+ content (`slots['header.end']`, e.g. a future account avatar) stays in the
114
+ header band on phones. Safe-area padding is `env(safe-area-inset-bottom)` in
115
+ the bar's CSS.
116
+
75
117
  Edge config: `viewportDefaults` (applied per class change; such an edge never
76
118
  stores its state), `phone: 'drawer' | 'sheet' | 'hidden'` (`sheet` is right
77
119
  edge only), `resizable` (side edges, `push` only, not on phones) and `persist`.
@@ -126,10 +168,26 @@ comes from `ShellLayout.panels.visible` and edit mode. The right edge is the
126
168
  dock: dock toggles and focus tools still open it, it just loses its button.
127
169
  `hotkeys` (default: follows the toggles) forces shortcuts on (`true`, panels
128
170
  behave as drop-downs without buttons) or off. Phones keep the Menu opener and
129
- the left drawer's close toggle. `showTenantToggle` is a deprecated alias for
171
+ the left drawer's close toggle. The left edge toggle is an icon above the
172
+ sidebar header content in both expanded and collapsed states, with a tooltip
173
+ and accessible expand/collapse name. `showTenantToggle` is a deprecated alias for
130
174
  `edgeToggles.left`. Migration: pass `edgeToggles` (true) to keep the previous
131
175
  behaviour.
132
176
 
177
+ The left edge's toggle is an icon-only chevron, not a labelled button: it
178
+ points the way the panel will move (left to collapse, right to expand), its
179
+ accessible name is `Collapse sidebar` / `Expand sidebar` (the hotkey rides
180
+ in the tooltip, there is no visible `<kbd>`), and off phones it closes the
181
+ navigation region: it sits at the end of the nav (`margin-block-start: auto`),
182
+ above the `leftSidebar.footer` slot, never below it. Order top to bottom, expanded
183
+ and collapsed: nav, chevron, footer (the account menu; the compact avatar last
184
+ in the collapsed rail). Expanded it lives inside the sidebar body
185
+ (`tenant-stack`) and hugs the inner edge; collapsed it is the middle row of the
186
+ rail stack (content, chevron, `tenantRailFooter`) and is centred. Only a rail
187
+ with neither nav nor footer content draws it alone at the bottom. Phones replace it with the drawer's
188
+ icon-only "Close menu" at the top, so opening the drawer still focuses a close control. The
189
+ header, footer and right toggles keep their region label and hotkey hint.
190
+
133
191
  ### Moving items between slots
134
192
 
135
193
  Movable items have stable ids: dock toggles `dock:<tool>`, each host `slots`
@@ -139,7 +197,34 @@ layouts). `AppShell` also supplies the built-in item `item:brand` (the shell
139
197
  `logoSrc`/`logoAlt`, title and subtitle, linked to `homeHref` when set, default slot `header.start`, movable, same fallback chain
140
198
  when the header is hidden); it sets `AdminShell` `brandInSlot` so the top band
141
199
  draws no brand of its own (standalone `AdminShell` still does). The menu
142
- opener and account content are not items yet (#3656 step 3).
200
+ opener and the legacy `account`/`tenantFooter` snippets are not items.
201
+
202
+ `AppShell` also supplies three more built-in items (ids are stored in layouts,
203
+ keep them stable), all movable in the layout editor like `item:brand`:
204
+
205
+ | Item | Default slot | Phone | Opt out |
206
+ | --- | --- | --- | --- |
207
+ | `item:account` | `leftSidebar.footer` | compact avatar, last in the header band (`header.end`) | `accountMenu={false}`; `accountMenu={{ slot }}` sets the default |
208
+ | `item:color-scheme` | `header.end` | icon-only (no label), accessible name kept | `colorSchemeToggle={false}`; `{ slot }` sets the default |
209
+ | `item:command-palette` | `header.center` | search glyph button | off unless `commandPalette` is passed |
210
+
211
+ `item:account` renders `WorkspaceAccountMenu` only when `user` is set (nothing
212
+ for `null`). Menu: name and email (when present on the user object), a Settings
213
+ link when `settingsHref` is set, Sign out when `onSignOut` (callback, wins) or
214
+ `signOutHref` (link) is given; plus tenant switching when used standalone. The
215
+ trigger carries `aria-expanded`, focus moves into the menu on open, Escape
216
+ closes only the menu and returns focus to the trigger. In an expanded sidebar
217
+ it shows the full identity (menu opens upward); everywhere else, and in the
218
+ collapsed rail, it is the compact avatar. In the collapsed rail `AppShell`
219
+ passes it as `tenantRailFooter` (outside the rail's scroll clip; the menu opens
220
+ to the inline end over the workspace) instead of letting the footer slot fall
221
+ back to another region. `item:color-scheme` reuses `ColorSchemeToggle` from
222
+ `@happyvertical/smrt-ui/themes` (no second switcher). `item:command-palette`
223
+ mounts the existing `CommandPalette` (`commandPalette: { providers, placeholder? }`,
224
+ types `AppShellCommandPalette`/`AppShellAccountMenu` from `./app`): it owns the
225
+ dialog and the global shortcut, so it mounts once. Planner-style hosts that
226
+ rendered their own `header.end` assistant toggle should pass `dockToggles`
227
+ (`dock:assistant`) and `user` instead.
143
228
 
144
229
  `ShellLayout.placements?: Record<itemId, ShellSlot>` (additive, still version
145
230
  1) overrides default slots. Pure helpers in `layout.ts` (also `./workspace/layout`):
@@ -320,6 +405,45 @@ enforce permissions.
320
405
 
321
406
  `ActivityTicker` accepts optional `statuses` restricted to queued/running; running-only remains the default. Opting into queued work adds an explicit localized Queued label without progress. Terminal outcomes belong in expanded `ActivityList`, with retention controlled by the app-owned data source.
322
407
 
408
+ ### Motion (#3858)
409
+
410
+ All durations and easings are theme tokens, never literals. The CSS motion sits
411
+ in `@media (prefers-reduced-motion: no-preference)` (or is zeroed by the reduced
412
+ block), and `tokenDuration()` returns 0 under reduced motion. `data-motion` is
413
+ set on the shell root after hydration and two frames, so first paint, SSR and a
414
+ persisted layout restoring never animate; phone drawers keep their own
415
+ `onEdgeAnimationEnd` / `waitForPanelAnimations` handshake (no track transition
416
+ on phone, and the tracks are on the shell root, not the panel, so `inert` is
417
+ never held by a transition).
418
+
419
+ | Motion | Token | Reduced motion |
420
+ | --- | --- | --- |
421
+ | Left sidebar / right dock track (`grid-template-columns`, desktop push), `--smrt-easing-emphasized`; stays immediate while `data-resizing` | `--smrt-duration-short4` | none |
422
+ | Revealed sidebar / dock content fade-in | `--smrt-duration-short2` | none |
423
+ | Edit mode: drop zones, strips, region controls, item grips fade and scale in | `--smrt-duration-short2` | none |
424
+ | List reorder/filter `animate:flipRow` on TenantNav rows, section-menu cards/rows, overview tiles, `Sortable` items (`ShellNavEditor` rows go through `Sortable`) | `--smrt-duration-short4` via `tokenDuration()` | duration 0 |
425
+ | Colour-scheme crossfade of shell background/colour, while `data-smrt-theme-changing` is set for one transition | `--smrt-duration-medium1` | not set |
426
+ | View transitions: brand, nav, dock persist while the page crossfades | browser default | `runViewTransition` skips |
427
+
428
+ Host-facing helpers, exported from `@happyvertical/smrt-svelte/app` and free of
429
+ `$app/*` (a hash router or non-SvelteKit host can use them):
430
+
431
+ - `runViewTransition(update, { skip? }): Promise<void>` calls
432
+ `document.startViewTransition(update)` when present and reduced motion is off,
433
+ else awaits `update()`. Resolves when the DOM update is applied; an aborted or
434
+ skipped transition never throws, an error from `update` does. `AppShell`
435
+ wraps the edit-mode toggle in it.
436
+ - `createOnNavigateViewTransition(options?)` returns a function for SvelteKit's
437
+ `onNavigate(createOnNavigateViewTransition())`. It takes the navigation
438
+ structurally (`{ complete, type?, willUnload? }`).
439
+
440
+ While a transition runs `<html data-smrt-view-transition>` is set and only then
441
+ does the shell assign `view-transition-name: smrt-shell-brand`, `smrt-shell-nav`
442
+ and `smrt-shell-dock` (so they never become containing blocks otherwise).
443
+ Names must be unique per document: hosts must not reuse them.
444
+ `tokenDuration(name, element?)` and `flipRow` live in
445
+ `workspace/admin-shell/motion.ts` for in-package lists.
446
+
323
447
  ## Shell layout customization
324
448
 
325
449
  Users can show/hide the edge panels and reorder, hide, and move navigation
@@ -389,11 +513,13 @@ control panel), wired by `app/AppShell.svelte`.
389
513
  "Rename <label>" button opening an inline field (Enter saves, Escape cancels,
390
514
  blur saves) and, once renamed, "Reset <label> to <original>"; the original shows
391
515
  as the row tooltip. Presets ("cookbooks") ship it in the stored layout.
392
- - **Sections-only navigation (`navMode: 'sections'`).** `AppShell` (and
393
- `TenantNav` / `ShellNavEditor` directly) take `navMode?: 'items' | 'sections'`
394
- (default `'items'`, unchanged). In `'sections'` the left sidebar shows one
395
- link per section (icon + label), no entries; a collapsed rail (`tenantRail`)
396
- shows the icons with tooltips. The link goes to `ShellNavGroup.href`, else
516
+ - **Section navigation (`navMode: 'sections' | 'sections-with-items'`).** `AppShell`
517
+ (and `TenantNav` / `ShellNavEditor` directly) also support `'items'` (the
518
+ default). `'sections'` keeps one link per section with no entries.
519
+ `'sections-with-items'` adds indented entry links in the expanded drawer;
520
+ its collapsed rail still shows section icons with tooltips. In edit mode,
521
+ this variant exposes both section icons and entry editing. The section link
522
+ goes to `ShellNavGroup.href`, else
397
523
  `AppShell` `sectionHref(sectionId)` (user-created sections), else the first
398
524
  entry; it is `aria-current="page"` on that page and `"true"` on any of the
399
525
  section's entry pages. `AppShell` also takes `iconComponent` for host icon
@@ -403,12 +529,16 @@ control panel), wired by `app/AppShell.svelte`.
403
529
  `setSectionIcon(id, icon | null)`; `resolveShellNavModel` sections carry
404
530
  `icon` / `defaultIcon` and `applyShellLayout` emits the effective `icon`.
405
531
  Icons are shell icon names (`SHELL_SECTION_ICONS` is the picker set, drawn
406
- from Material icons like the rest of `SHELL_ICON_PATHS`; `SHELL_DEFAULT_SECTION_ICON`
407
- is `folder`) or host names rendered by `iconComponent` (`ShellSectionIcon`
408
- tries the built-in set first). Edit mode in this mode: sections keep grip,
532
+ from Material icons like the rest of `SHELL_ICON_PATHS`;
533
+ `SHELL_DEFAULT_SECTION_ICON` is `folder`) or host names rendered by
534
+ `iconComponent`. Entry and action icons use built-in SVGs when no host
535
+ renderer is supplied, falling back to the default section glyph for unknown
536
+ names. Edit mode in `sections` mode: sections keep grip,
409
537
  rename, hide, delete; the title toggle is replaced by an "Icon of <label>"
410
538
  popover grid ("Use <icon> icon", `aria-pressed` on the current one; Escape
411
- closes the grid before the toolbar). Entries are not in the sidebar.
539
+ closes the grid before the toolbar). Entries are not in the sidebar in
540
+ `sections` mode; `sections-with-items` shows them under their section.
541
+ - **TenantNav rows.** `ShellNavItem.icon` renders in items mode and the collapsed rail (host `iconComponent` first, else `SHELL_ICON_PATHS`); an iconless item shows the `placeholder` glyph in the rail only. The current row has a `secondary-container` fill plus a start indicator bar (`aria-current="page"` unchanged). Row block-size is `--smrt-touch-target-min` at the phone boundary (`max-width: 48rem`) and `--smrt-control-target-min` otherwise; `ShellNavEditor` item rows use the same sizing.
412
542
  - **`ShellSectionMenu`** (`sectionId`, `controller?`, `meta(entry)`,
413
543
  `actions(entry)`, `iconComponent`, `aria-label`, `layout`): the section's page body.
414
544
  `layout="cards"` renders an auto-fill grid (min 16rem) of cards: 32px icon in a
@@ -448,6 +578,10 @@ removing the item from `source`.
448
578
  lives beside, not inside, `./workspace` so the AdminShell barrel stays free of
449
579
  `Provider` and its tests.
450
580
 
581
+ - `AppShell` built-in items (`item:account`, `item:color-scheme`,
582
+ `item:command-palette`, with `user`, `onSignOut`, `signOutHref`, `accountMenu`,
583
+ `colorSchemeToggle`, `commandPalette`) are documented under "Moving items
584
+ between slots".
451
585
  - `AppShell` composes `Provider` (`webmcp`, `user`, `permissions` pass through
452
586
  unchanged), `ThemeProvider`, the theme CSS (`themes/styles/{all,fonts}.css`
453
587
  are imported by the component — forgetting them leaves `--smrt-*` unresolved),
@@ -28,7 +28,7 @@ function formatBytes(bytes: number): string {
28
28
  }
29
29
  </script>
30
30
 
31
- <div class="download-progress">
31
+ <div class="download-progress" data-smrt-component="DownloadProgress">
32
32
  <div class="label">
33
33
  <span>{label}</span>
34
34
  {#if showPercent && progress}
@@ -39,7 +39,7 @@ function formatBytes(bytes: number): string {
39
39
  <div class="progress-bar">
40
40
  <div
41
41
  class="progress-fill"
42
- style:width="{progress?.percent ?? 0}%"
42
+ style:width={progress && progress.state !== 'idle' ? `${progress.percent ?? 0}%` : undefined}
43
43
  class:indeterminate={!progress || progress.state === 'idle'}
44
44
  ></div>
45
45
  </div>
@@ -60,11 +60,13 @@ function formatBytes(bytes: number): string {
60
60
  </div>
61
61
 
62
62
  <style>
63
+ @layer smrt.reset, smrt.structure, smrt.theme;
64
+ @layer smrt.theme {
63
65
  .download-progress {
64
66
  width: 100%;
65
- padding: var(--smrt-spacing-md, 12px);
66
- background: var(--smrt-color-surface-container-low, #f9fafb);
67
- border-radius: var(--smrt-radius-medium, 8px);
67
+ padding: var(--smrt-spacing-md);
68
+ background: var(--smrt-color-surface-container-low);
69
+ border-radius: var(--smrt-radius-medium);
68
70
  }
69
71
 
70
72
  .label {
@@ -72,32 +74,32 @@ function formatBytes(bytes: number): string {
72
74
  justify-content: space-between;
73
75
  align-items: center;
74
76
  font: var(--smrt-typography-body-medium-font, 0.875rem / 1.25 sans-serif);
75
- color: var(--smrt-color-on-surface, #1a1c1e);
76
- margin-bottom: var(--smrt-spacing-sm, 8px);
77
+ color: var(--smrt-color-on-surface);
78
+ margin-bottom: var(--smrt-spacing-sm);
77
79
  }
78
80
 
79
81
  .percent {
80
82
  font-weight: var(--smrt-typography-weight-semibold, 600);
81
- color: var(--smrt-color-primary, #005ac1);
83
+ color: var(--smrt-color-primary);
82
84
  }
83
85
 
84
86
  .progress-bar {
85
87
  width: 100%;
86
88
  height: 8px;
87
- background: var(--smrt-color-outline-variant, #c4c6cf);
88
- border-radius: var(--smrt-radius-small, 4px);
89
+ background: var(--smrt-color-outline-variant);
90
+ border-radius: var(--smrt-radius-small);
89
91
  overflow: hidden;
90
92
  }
91
93
 
92
94
  .progress-fill {
93
95
  height: 100%;
94
- background: linear-gradient(90deg, var(--smrt-color-primary, #005ac1), var(--smrt-color-primary-container, #d6e3ff));
95
- border-radius: var(--smrt-radius-small, 4px);
96
+ background: linear-gradient(90deg, var(--smrt-color-primary), var(--smrt-color-primary-container));
97
+ border-radius: var(--smrt-radius-small);
96
98
  transition: width var(--smrt-duration-medium1, 300ms) var(--smrt-easing-standard, ease);
97
99
  }
98
100
 
99
101
  .progress-fill.indeterminate {
100
- width: 30% !important;
102
+ width: 30%;
101
103
  animation: indeterminate 1.5s infinite linear;
102
104
  }
103
105
 
@@ -108,15 +110,15 @@ function formatBytes(bytes: number): string {
108
110
 
109
111
  .bytes {
110
112
  font: var(--smrt-typography-body-small-font, 0.75rem / 1.25 sans-serif);
111
- color: var(--smrt-color-on-surface-variant, #43474e);
112
- margin-top: var(--smrt-spacing-2, 8px);
113
+ color: var(--smrt-color-on-surface-variant);
114
+ margin-top: var(--smrt-spacing-2);
113
115
  text-align: center;
114
116
  }
115
117
 
116
118
  .current-file {
117
119
  font: var(--smrt-typography-body-small-font, 0.75rem / 1.25 sans-serif);
118
- color: var(--smrt-color-outline, #74777f);
119
- margin-top: var(--smrt-spacing-1, 4px);
120
+ color: var(--smrt-color-outline);
121
+ margin-top: var(--smrt-spacing-1);
120
122
  text-align: center;
121
123
  white-space: nowrap;
122
124
  overflow: hidden;
@@ -125,8 +127,8 @@ function formatBytes(bytes: number): string {
125
127
 
126
128
  .error {
127
129
  font: var(--smrt-typography-body-small-font, 0.75rem / 1.25 sans-serif);
128
- color: var(--smrt-color-error, #ba1a1a);
129
- margin-top: var(--smrt-spacing-2, 8px);
130
+ color: var(--smrt-color-error);
131
+ margin-top: var(--smrt-spacing-2);
130
132
  }
131
133
 
132
134
  @media (prefers-reduced-motion: reduce) {
@@ -138,4 +140,5 @@ function formatBytes(bytes: number): string {
138
140
  animation: none;
139
141
  }
140
142
  }
143
+ }
141
144
  </style>
@@ -97,7 +97,7 @@ async function run(
97
97
  }
98
98
  </script>
99
99
 
100
- <div class="model-status {className}" data-status={snapshot.status}>
100
+ <div class="model-status {className}" data-status={snapshot.status} data-smrt-component="ModelStatusControl">
101
101
  <div class="header">
102
102
  <span class="label">{label}</span>
103
103
  <span class="state" role="status">{STATUS_LABEL[snapshot.status]}</span>
@@ -138,53 +138,56 @@ async function run(
138
138
  </div>
139
139
 
140
140
  <style>
141
+ @layer smrt.reset, smrt.structure, smrt.theme;
142
+ @layer smrt.theme {
141
143
  .model-status {
142
144
  display: flex;
143
145
  flex-direction: column;
144
- gap: var(--smrt-spacing-sm, 8px);
145
- padding: var(--smrt-spacing-md, 12px);
146
- background: var(--smrt-color-surface-container-low, #f9fafb);
147
- border-radius: var(--smrt-radius-medium, 8px);
146
+ gap: var(--smrt-spacing-sm);
147
+ padding: var(--smrt-spacing-md);
148
+ background: var(--smrt-color-surface-container-low);
149
+ border-radius: var(--smrt-radius-medium);
148
150
  }
149
151
 
150
152
  .header {
151
153
  display: flex;
152
154
  justify-content: space-between;
153
155
  align-items: baseline;
154
- gap: var(--smrt-spacing-sm, 8px);
156
+ gap: var(--smrt-spacing-sm);
155
157
  }
156
158
 
157
159
  .label {
158
160
  font-weight: var(--smrt-typography-weight-semibold, 600);
159
- color: var(--smrt-color-on-surface, #1a1c1e);
161
+ color: var(--smrt-color-on-surface);
160
162
  }
161
163
 
162
164
  .state {
163
165
  font: var(--smrt-typography-body-small-font, 0.8125rem / 1.2 sans-serif);
164
- color: var(--smrt-color-on-surface-variant, #44474f);
166
+ color: var(--smrt-color-on-surface-variant);
165
167
  }
166
168
 
167
169
  .model-status[data-status='ready'] .state {
168
- color: var(--smrt-color-primary, #005ac1);
170
+ color: var(--smrt-color-primary);
169
171
  }
170
172
 
171
173
  .model-status[data-status='error'] .state {
172
- color: var(--smrt-color-error, #ba1a1a);
174
+ color: var(--smrt-color-error);
173
175
  }
174
176
 
175
177
  .hint,
176
178
  .error {
177
179
  margin: 0;
178
180
  font: var(--smrt-typography-body-small-font, 0.8125rem / 1.2 sans-serif);
179
- color: var(--smrt-color-on-surface-variant, #44474f);
181
+ color: var(--smrt-color-on-surface-variant);
180
182
  }
181
183
 
182
184
  .error {
183
- color: var(--smrt-color-error, #ba1a1a);
185
+ color: var(--smrt-color-error);
184
186
  }
185
187
 
186
188
  .actions {
187
189
  display: flex;
188
- gap: var(--smrt-spacing-sm, 8px);
190
+ gap: var(--smrt-spacing-sm);
189
191
  }
192
+ }
190
193
  </style>
@@ -106,7 +106,7 @@ function clearLogs() {
106
106
  }
107
107
  </script>
108
108
 
109
- <div class="stt-test">
109
+ <div class="stt-test" data-smrt-component="STTTest">
110
110
  <h3>{t(M['ui.stt_test.heading'])}</h3>
111
111
 
112
112
  <div class="controls">
@@ -203,30 +203,32 @@ function clearLogs() {
203
203
  </div>
204
204
 
205
205
  <style>
206
+ @layer smrt.reset, smrt.structure, smrt.theme;
207
+ @layer smrt.theme {
206
208
  .stt-test {
207
- padding: var(--smrt-spacing-md, 16px);
208
- border: 1px solid var(--smrt-color-outline-variant, #c4c6cf);
209
- border-radius: var(--smrt-radius-medium, 8px);
210
- background: var(--smrt-color-surface-container-low, #f9fafb);
209
+ padding: var(--smrt-spacing-md);
210
+ border: 1px solid var(--smrt-color-outline-variant);
211
+ border-radius: var(--smrt-radius-medium);
212
+ background: var(--smrt-color-surface-container-low);
211
213
  max-width: 500px;
212
214
  }
213
215
 
214
216
  h3 {
215
- margin: 0 0 var(--smrt-spacing-md, 16px);
217
+ margin: 0 0 var(--smrt-spacing-md);
216
218
  font: var(--smrt-typography-title-large-font, 1.125rem / 1.25 sans-serif);
217
219
  }
218
220
 
219
221
  .controls {
220
222
  display: flex;
221
- gap: var(--smrt-spacing-sm, 12px);
223
+ gap: var(--smrt-spacing-sm);
222
224
  align-items: flex-end;
223
- margin-bottom: var(--smrt-spacing-md, 16px);
225
+ margin-bottom: var(--smrt-spacing-md);
224
226
  }
225
227
 
226
228
  .adapter-select {
227
229
  display: flex;
228
230
  flex-direction: column;
229
- gap: var(--smrt-spacing-1, 4px);
231
+ gap: var(--smrt-spacing-1);
230
232
  flex: 1;
231
233
  }
232
234
 
@@ -236,43 +238,43 @@ function clearLogs() {
236
238
 
237
239
  .status {
238
240
  display: flex;
239
- gap: var(--smrt-spacing-md, 16px);
241
+ gap: var(--smrt-spacing-md);
240
242
  font: var(--smrt-typography-body-medium-font, 0.875rem / 1.25 sans-serif);
241
- margin-bottom: var(--smrt-spacing-md, 16px);
242
- padding: var(--smrt-spacing-sm, 8px);
243
+ margin-bottom: var(--smrt-spacing-md);
244
+ padding: var(--smrt-spacing-sm);
243
245
  background: var(--smrt-color-surface, white);
244
- border-radius: var(--smrt-radius-small, 4px);
246
+ border-radius: var(--smrt-radius-small);
245
247
  }
246
248
 
247
249
  .status-item {
248
250
  display: flex;
249
- gap: var(--smrt-spacing-1, 4px);
251
+ gap: var(--smrt-spacing-1);
250
252
  }
251
253
 
252
254
  .record-controls {
253
255
  display: flex;
254
256
  justify-content: center;
255
- margin: var(--smrt-spacing-md, 20px) 0;
257
+ margin: var(--smrt-spacing-md) 0;
256
258
  }
257
259
 
258
260
  .record-btn {
259
- padding: var(--smrt-spacing-md, 16px) var(--smrt-spacing-xl, 32px);
261
+ padding: var(--smrt-spacing-md) var(--smrt-spacing-xl);
260
262
  font: var(--smrt-typography-label-large-font, 500 1rem / 1.25 sans-serif);
261
- background: var(--smrt-color-tertiary, #006c4f);
262
- color: var(--smrt-color-on-tertiary, #ffffff);
263
+ background: var(--smrt-color-tertiary);
264
+ color: var(--smrt-color-on-tertiary);
263
265
  border: none;
264
- border-radius: var(--smrt-radius-medium, 8px);
266
+ border-radius: var(--smrt-radius-medium);
265
267
  cursor: pointer;
266
268
  transition: all var(--smrt-duration-short3, 200ms) var(--smrt-easing-standard, ease);
267
269
  }
268
270
 
269
271
  .record-btn:hover:not(:disabled) {
270
- background: var(--smrt-color-tertiary-container, #006c4f);
272
+ background: var(--smrt-color-tertiary-container);
271
273
  opacity: 0.9;
272
274
  }
273
275
 
274
276
  .record-btn.recording {
275
- background: var(--smrt-color-error, #ba1a1a);
277
+ background: var(--smrt-color-error);
276
278
  animation: pulse 1s infinite;
277
279
  }
278
280
 
@@ -287,25 +289,25 @@ function clearLogs() {
287
289
  }
288
290
 
289
291
  .error {
290
- padding: var(--smrt-spacing-md, 12px);
291
- background: var(--smrt-color-error-container, #ffdad6);
292
- border: 1px solid var(--smrt-color-error, #ba1a1a);
293
- border-radius: var(--smrt-radius-small, 6px);
294
- color: var(--smrt-color-on-error-container, #410002);
292
+ padding: var(--smrt-spacing-md);
293
+ background: var(--smrt-color-error-container);
294
+ border: 1px solid var(--smrt-color-error);
295
+ border-radius: var(--smrt-radius-small);
296
+ color: var(--smrt-color-on-error-container);
295
297
  font: var(--smrt-typography-body-medium-font, 0.875rem / 1.25 sans-serif);
296
- margin-bottom: var(--smrt-spacing-md, 16px);
298
+ margin-bottom: var(--smrt-spacing-md);
297
299
  }
298
300
 
299
301
  .result {
300
- margin-bottom: var(--smrt-spacing-md, 16px);
302
+ margin-bottom: var(--smrt-spacing-md);
301
303
  }
302
304
 
303
305
  .transcript {
304
- margin-top: var(--smrt-spacing-sm, 8px);
305
- padding: var(--smrt-spacing-md, 12px);
306
+ margin-top: var(--smrt-spacing-sm);
307
+ padding: var(--smrt-spacing-md);
306
308
  background: var(--smrt-color-surface, white);
307
- border: 1px solid var(--smrt-color-outline-variant, #c4c6cf);
308
- border-radius: var(--smrt-radius-small, 6px);
309
+ border: 1px solid var(--smrt-color-outline-variant);
310
+ border-radius: var(--smrt-radius-small);
309
311
  min-height: 60px;
310
312
  font: var(--smrt-typography-body-large-font, 1rem / 1.5 sans-serif);
311
313
  }
@@ -318,21 +320,21 @@ function clearLogs() {
318
320
  display: flex;
319
321
  justify-content: space-between;
320
322
  align-items: center;
321
- margin-bottom: var(--smrt-spacing-sm, 8px);
323
+ margin-bottom: var(--smrt-spacing-sm);
322
324
  }
323
325
 
324
326
  .log-list {
325
- background: var(--smrt-color-inverse-surface, #1f2937);
326
- color: var(--smrt-color-inverse-on-surface, #d1d5db);
327
- padding: var(--smrt-spacing-sm, 8px);
328
- border-radius: var(--smrt-radius-small, 4px);
327
+ background: var(--smrt-color-inverse-surface);
328
+ color: var(--smrt-color-inverse-on-surface);
329
+ padding: var(--smrt-spacing-sm);
330
+ border-radius: var(--smrt-radius-small);
329
331
  max-height: 150px;
330
332
  overflow-y: auto;
331
333
  font-family: var(--smrt-font-family-mono, ui-monospace, monospace);
332
334
  }
333
335
 
334
336
  .log-entry {
335
- padding: var(--smrt-spacing-1, 4px) 0;
337
+ padding: var(--smrt-spacing-1) 0;
336
338
  }
337
339
 
338
340
  @media (prefers-reduced-motion: reduce) {
@@ -344,4 +346,5 @@ function clearLogs() {
344
346
  animation: none;
345
347
  }
346
348
  }
349
+ }
347
350
  </style>