@k2b/cloud 0.38.0 → 0.39.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 (99) hide show
  1. package/package.json +6 -3
  2. package/scripts/build-canvas-workers.ts +109 -29
  3. package/scripts/build.ts +3 -5
  4. package/src/_internal/app-path.ts +25 -0
  5. package/src/_internal/app-presentation.ts +4 -0
  6. package/src/_internal/canvas-worker.ts +5 -3
  7. package/src/_internal/define-app.ts +28 -2
  8. package/src/_internal/panel-cookie.ts +39 -0
  9. package/src/_internal/registry-validation.ts +21 -26
  10. package/src/_internal/runtime-context.ts +1 -0
  11. package/src/access/PermissionEditor.browser-harness.tsx +57 -38
  12. package/src/access/PermissionEditor.tsx +30 -5
  13. package/src/access/ResourceApiKeys.tsx +5 -1
  14. package/src/ai/approval-routes.ts +5 -2
  15. package/src/ai/approvals.ts +139 -28
  16. package/src/ai/browser.ts +10 -0
  17. package/src/ai/chat/action-sentences.ts +1 -44
  18. package/src/ai/chat/turn-view.tsx +35 -3
  19. package/src/ai/chat/view-block.tsx +7 -2
  20. package/src/ai/chat-task-contracts.ts +28 -3
  21. package/src/ai/chat-task-reasons-migrate.ts +68 -0
  22. package/src/ai/chat-task-reasons.ts +92 -0
  23. package/src/ai/chat-tasks.ts +396 -66
  24. package/src/ai/index.ts +12 -0
  25. package/src/ai/migrate.ts +28 -2
  26. package/src/ai/request-context.ts +7 -1
  27. package/src/ai/routes.ts +27 -1
  28. package/src/ai/runtime.ts +12 -27
  29. package/src/ai/store.ts +5 -3
  30. package/src/ai/timeline.ts +9 -1
  31. package/src/ai/tool-wording.ts +45 -0
  32. package/src/ai/turn-abort.ts +33 -0
  33. package/src/ai/types.ts +12 -1
  34. package/src/api/admin-core-settings.ts +190 -139
  35. package/src/api/admin-outgoing-mail.ts +4 -2
  36. package/src/api/app-approval.ts +9 -2
  37. package/src/api/approvals.ts +1 -1
  38. package/src/api/index.ts +2 -1
  39. package/src/browser/CloudResourceSearch.tsx +10 -6
  40. package/src/browser/app-approval.ts +7 -2
  41. package/src/browser/composer-catalog.ts +103 -0
  42. package/src/browser/composer-insert-messages.ts +31 -0
  43. package/src/browser/composer-insert.ts +150 -0
  44. package/src/browser/panel-messages.ts +24 -0
  45. package/src/browser/panel-slot.ts +354 -0
  46. package/src/browser/panel.ts +28 -0
  47. package/src/browser/resource-picker.tsx +12 -1
  48. package/src/contracts/app-approval.ts +49 -9
  49. package/src/contracts/app.ts +14 -0
  50. package/src/contracts/registry.ts +3 -1
  51. package/src/contracts/shared.ts +2 -0
  52. package/src/server/services/access.ts +5 -1
  53. package/src/services/accounts/posix.ts +2 -1
  54. package/src/services/app-approval.ts +158 -38
  55. package/src/services/approvals/device.ts +2 -0
  56. package/src/services/index.ts +21 -3
  57. package/src/services/notifications/browser.ts +16 -5
  58. package/src/services/pdf/image-protocol.ts +135 -0
  59. package/src/services/pdf/image-variants.ts +124 -0
  60. package/src/services/pdf/image-worker.ts +31 -0
  61. package/src/services/pdf/image.ts +109 -0
  62. package/src/services/pdf/index.ts +9 -0
  63. package/src/services/settings/api.ts +11 -6
  64. package/src/services/settings/app.ts +5 -4
  65. package/src/services/settings/core-settings.ts +4 -3
  66. package/src/services/settings/index.ts +19 -17
  67. package/src/services/settings/namespace.ts +2 -1
  68. package/src/services/settings/store.ts +83 -11
  69. package/src/shared/ai-platform-prompt.ts +1 -1
  70. package/src/shared/app-presentation.ts +1 -0
  71. package/src/shared/redirect.ts +12 -0
  72. package/src/ssr/CloudShell.island.tsx +86 -9
  73. package/src/ssr/Layout.tsx +42 -9
  74. package/src/ssr/LayoutHeader.tsx +15 -9
  75. package/src/ssr/LayoutHelp.tsx +1 -1
  76. package/src/ssr/LayoutRail.tsx +2 -2
  77. package/src/ssr/LayoutTabBar.tsx +29 -0
  78. package/src/ssr/PanelLayout.tsx +27 -0
  79. package/src/ssr/PanelRuntime.island.tsx +87 -0
  80. package/src/ssr/PanelSlot.tsx +108 -0
  81. package/src/ssr/PanelTrigger.tsx +49 -0
  82. package/src/ssr/ShellRuntime.island.tsx +60 -5
  83. package/src/ssr/app-appearance.ts +3 -2
  84. package/src/ssr/app-color.ts +100 -0
  85. package/src/ssr/app-launchpad.tsx +18 -1
  86. package/src/ssr/app-navigation.ts +15 -0
  87. package/src/ssr/compact-shell.baseline.json +5270 -0
  88. package/src/ssr/compact-shell.browser-harness.ts +431 -0
  89. package/src/ssr/index.ts +3 -0
  90. package/src/ssr/panel-slot.browser-harness.tsx +110 -0
  91. package/src/ssr/platform-messages.ts +30 -0
  92. package/src/ssr/rail-navigation.ts +44 -0
  93. package/src/ssr/shell-data.tsx +4 -0
  94. package/src/ssr/shell-shortcuts.ts +13 -2
  95. package/src/styles/effects.css +3 -2
  96. package/src/styles/global.css +269 -55
  97. package/src/styles/panel.css +373 -0
  98. package/src/styles/tokens.css +23 -6
  99. package/src/styles/utilities-navigation.css +5 -21
@@ -0,0 +1,373 @@
1
+ /* Panel slot: one provider page in a same-origin iframe beside the app.
2
+ From 1024 px it is a column after the app card and the app card narrows;
3
+ from 768 to 1023 px a non-modal drawer over the right edge; below 768 px a
4
+ sheet from the bottom. The canvas carries the state from the cloud_panel
5
+ cookie, so the server draws the first frame. Loading, failure, the resize
6
+ shield and the closing hint are stacked in the body and only change their
7
+ visibility, so nothing ever moves inside the reserved box. */
8
+ .cloud-panel {
9
+ --cloud-panel-width: var(--cloud-panel-width-set, 26rem);
10
+ position: relative;
11
+ display: none;
12
+ min-height: 0;
13
+ color: var(--k2b-text);
14
+ }
15
+
16
+ @media not all and (min-width: 1280px) {
17
+ .cloud-panel {
18
+ --cloud-panel-width: var(--cloud-panel-width-set, 21.5rem);
19
+ }
20
+ }
21
+
22
+ /* The same surface, radius, frame and dark border as the app card. */
23
+ .cloud-panel__card {
24
+ display: flex;
25
+ flex-direction: column;
26
+ width: 100%;
27
+ height: 100%;
28
+ min-height: 0;
29
+ overflow: hidden;
30
+ border: 1px solid transparent;
31
+ border-radius: var(--cloud-card-radius, var(--k2b-radius-dialog));
32
+ background: var(--k2b-surface);
33
+ box-shadow: var(--k2b-shadow-frame);
34
+ }
35
+
36
+ .dark .cloud-panel__card {
37
+ border-color: var(--k2b-border);
38
+ }
39
+
40
+ /* One 46 px row, no line below; the provider's page starts right under it. */
41
+ .cloud-panel__head {
42
+ display: flex;
43
+ flex: none;
44
+ align-items: center;
45
+ gap: 0.25rem;
46
+ min-height: 2.875rem;
47
+ padding: 0.375rem 0.375rem 0.375rem 0.5rem;
48
+ }
49
+
50
+ .cloud-panel__head .k2b-icon-button .ti {
51
+ font-size: 1.125rem;
52
+ }
53
+
54
+ .cloud-panel__title {
55
+ display: flex;
56
+ flex: 1;
57
+ min-width: 0;
58
+ align-items: center;
59
+ gap: 0.5rem;
60
+ padding-inline-start: 0.5rem;
61
+ font-size: 0.875rem;
62
+ font-weight: 600;
63
+ }
64
+
65
+ .cloud-panel__title > .ti {
66
+ flex: none;
67
+ font-size: 1rem;
68
+ color: var(--k2b-text-muted);
69
+ }
70
+
71
+ .cloud-panel__title > span,
72
+ .cloud-panel__tab-label {
73
+ overflow: hidden;
74
+ text-overflow: ellipsis;
75
+ white-space: nowrap;
76
+ }
77
+
78
+ .cloud-panel__tabs {
79
+ display: flex;
80
+ flex: 1;
81
+ min-width: 0;
82
+ gap: 0.125rem;
83
+ overflow-x: auto;
84
+ scrollbar-width: none;
85
+ }
86
+
87
+ .cloud-panel__tab {
88
+ display: inline-flex;
89
+ flex: none;
90
+ max-width: 12rem;
91
+ height: 2rem;
92
+ align-items: center;
93
+ gap: 0.375rem;
94
+ padding: 0 0.625rem;
95
+ border: 0;
96
+ border-radius: var(--k2b-radius-control);
97
+ background: transparent;
98
+ color: var(--k2b-text-muted);
99
+ font-size: 0.875rem;
100
+ font-weight: 500;
101
+ cursor: pointer;
102
+ }
103
+
104
+ .cloud-panel__tab > .ti {
105
+ flex: none;
106
+ font-size: 1rem;
107
+ }
108
+
109
+ .cloud-panel__tab:hover {
110
+ background: var(--k2b-hover);
111
+ color: var(--k2b-text);
112
+ }
113
+
114
+ .cloud-panel__tab[aria-selected="true"] {
115
+ background: var(--k2b-surface-muted);
116
+ color: var(--k2b-text);
117
+ }
118
+
119
+ .cloud-panel__tab:focus-visible,
120
+ .cloud-panel__grabber:focus-visible {
121
+ outline: 2px solid var(--k2b-focus-ring);
122
+ outline-offset: -2px;
123
+ }
124
+
125
+ .cloud-panel__body {
126
+ position: relative;
127
+ flex: 1;
128
+ min-height: 0;
129
+ }
130
+
131
+ .cloud-panel__body > :is(.cloud-panel__skeleton, .cloud-panel__frame, .cloud-panel__fallback, .cloud-panel__shield, .cloud-panel__closing) {
132
+ position: absolute;
133
+ inset: 0;
134
+ width: 100%;
135
+ height: 100%;
136
+ visibility: hidden;
137
+ opacity: 0;
138
+ }
139
+
140
+ .cloud-panel[data-state="ready"] .cloud-panel__frame,
141
+ .cloud-panel[data-state="failed"] .cloud-panel__fallback,
142
+ .cloud-panel[data-resizing="true"] .cloud-panel__shield,
143
+ .cloud-panel[data-closing="true"] .cloud-panel__closing {
144
+ visibility: visible;
145
+ opacity: 1;
146
+ }
147
+
148
+ /* A loading page already takes focus and keys; the skeleton covers it until it reports ready. */
149
+ .cloud-panel[data-state="loading"] .cloud-panel__frame {
150
+ visibility: visible;
151
+ }
152
+
153
+ .cloud-panel[data-state="loading"] .cloud-panel__skeleton {
154
+ visibility: visible;
155
+ opacity: 1;
156
+ }
157
+
158
+ .cloud-panel__frame {
159
+ display: block;
160
+ border: 0;
161
+ background: var(--k2b-surface);
162
+ }
163
+
164
+ .cloud-panel__skeleton {
165
+ z-index: 1;
166
+ display: flex;
167
+ flex-direction: column;
168
+ gap: 0.75rem;
169
+ padding: 0.5rem 1rem;
170
+ background: var(--k2b-surface);
171
+ pointer-events: none;
172
+ }
173
+
174
+ .cloud-panel__skeleton > span {
175
+ display: block;
176
+ height: 0.75rem;
177
+ border-radius: 0.375rem;
178
+ background: var(--k2b-surface-muted);
179
+ }
180
+
181
+ .cloud-panel__skeleton > span:nth-child(2) {
182
+ width: 85%;
183
+ }
184
+
185
+ .cloud-panel__skeleton > span:last-child {
186
+ width: 60%;
187
+ }
188
+
189
+ @media (prefers-reduced-motion: no-preference) {
190
+ html:not([data-k2b-motion="reduced"]) .cloud-panel[data-state="loading"] .cloud-panel__skeleton > span {
191
+ animation: cloud-panel-pulse 1.4s ease-in-out infinite;
192
+ }
193
+ }
194
+
195
+ @keyframes cloud-panel-pulse {
196
+ 50% {
197
+ opacity: 0.55;
198
+ }
199
+ }
200
+
201
+ .cloud-panel__fallback {
202
+ z-index: 1;
203
+ display: flex;
204
+ align-items: center;
205
+ justify-content: center;
206
+ padding: 1.5rem;
207
+ background: var(--k2b-surface);
208
+ }
209
+
210
+ /* Takes the pointer from the iframe while the separator drags. */
211
+ .cloud-panel__shield {
212
+ z-index: 2;
213
+ cursor: col-resize;
214
+ }
215
+
216
+ /* Dragging clearly below 20 rem: the panel fades and says what release does. */
217
+ .cloud-panel__closing {
218
+ z-index: 3;
219
+ display: flex;
220
+ align-items: center;
221
+ justify-content: center;
222
+ padding: 1rem;
223
+ background: color-mix(in srgb, var(--k2b-surface) 82%, transparent);
224
+ pointer-events: none;
225
+ }
226
+
227
+ .cloud-panel__closing > span {
228
+ display: inline-flex;
229
+ align-items: center;
230
+ gap: 0.5rem;
231
+ padding: 0.5rem 0.75rem;
232
+ border-radius: var(--k2b-radius-control);
233
+ background: var(--k2b-surface-muted);
234
+ color: var(--k2b-text);
235
+ font-size: 0.875rem;
236
+ font-weight: 500;
237
+ }
238
+
239
+ .cloud-panel__closing .ti {
240
+ font-size: 1rem;
241
+ color: var(--k2b-text-muted);
242
+ }
243
+
244
+ .cloud-panel__grabber {
245
+ display: none;
246
+ }
247
+
248
+ /* The separator sits in the gap at the panel's start edge. */
249
+ .cloud-panel__resize {
250
+ position: absolute !important;
251
+ inset-block: 0;
252
+ inset-inline-start: calc(-6px - var(--cloud-card-inset, 0.5rem) / 2);
253
+ z-index: 4;
254
+ }
255
+
256
+ /* Column: the app area is the AppWorkspace host, so the app lays out by its narrowed width. */
257
+ @media (min-width: 1024px) {
258
+ .cloud-app-canvas[data-panel="open"] > .cloud-panel {
259
+ display: block;
260
+ flex: none;
261
+ align-self: stretch;
262
+ width: var(--cloud-panel-width);
263
+ margin-inline-start: var(--cloud-card-inset, 0.5rem);
264
+ }
265
+
266
+ .cloud-app-canvas[data-panel="open"] > [data-cloud-app-area] {
267
+ container: k2b-app-area / inline-size;
268
+ }
269
+ }
270
+
271
+ /* Drawer: over the app's right edge; the app keeps its width. Not modal. */
272
+ @media (min-width: 768px) {
273
+ @media not all and (min-width: 1024px) {
274
+ .cloud-app-canvas[data-panel="open"] > .cloud-panel {
275
+ position: absolute;
276
+ z-index: 20;
277
+ inset-block: calc(0.5rem + env(safe-area-inset-top, 0px)) calc(0.5rem + env(safe-area-inset-bottom, 0px));
278
+ inset-inline-end: calc(0.5rem + env(safe-area-inset-right, 0px));
279
+ display: block;
280
+ width: min(var(--cloud-panel-width), calc(100% - 1rem));
281
+ }
282
+
283
+ .cloud-panel__card {
284
+ border-radius: var(--k2b-radius-dialog);
285
+ box-shadow: var(--k2b-shadow-float);
286
+ }
287
+
288
+ .cloud-panel__resize {
289
+ display: none !important;
290
+ }
291
+ }
292
+ }
293
+
294
+ /* Sheet: from the bottom, a little over half the height; the grabber makes it full. */
295
+ @media not all and (min-width: 768px) {
296
+ .cloud-app-canvas[data-panel-sheet="open"] > .cloud-panel {
297
+ position: fixed;
298
+ z-index: 30;
299
+ inset-inline: 0;
300
+ bottom: 0;
301
+ display: block;
302
+ height: 58dvh;
303
+ }
304
+
305
+ /* The page's last row scrolls up above the sheet. Only the end of the page
306
+ grows, so nothing above it moves; full pages own their own scrollers. */
307
+ .cloud-app-canvas[data-layout-authenticated][data-panel-sheet="open"]:not([data-layout-full-page]) .layout-content-main {
308
+ padding-bottom: max(58dvh, var(--cloud-tab-bar-space, 0px));
309
+ scroll-padding-bottom: max(58dvh, var(--cloud-tab-bar-space, 0px));
310
+ }
311
+
312
+ .cloud-app-canvas[data-panel-sheet="open"] > .cloud-panel[data-panel-size="full"] {
313
+ height: calc(100dvh - 2.875rem - env(safe-area-inset-top, 0px));
314
+ }
315
+
316
+ .cloud-panel__card {
317
+ padding-bottom: env(safe-area-inset-bottom, 0px);
318
+ border-radius: 1.125rem 1.125rem 0 0;
319
+ box-shadow: 0 -10px 36px rgb(9 9 11 / 0.18);
320
+ }
321
+
322
+ .dark .cloud-panel__card {
323
+ border-bottom-color: transparent;
324
+ box-shadow: 0 -10px 36px rgb(0 0 0 / 0.5);
325
+ }
326
+
327
+ .cloud-panel__grabber {
328
+ display: flex;
329
+ flex: none;
330
+ align-items: center;
331
+ justify-content: center;
332
+ width: 100%;
333
+ height: 1.25rem;
334
+ padding: 0;
335
+ border: 0;
336
+ background: transparent;
337
+ }
338
+
339
+ .cloud-panel__grabber > span {
340
+ width: 2.375rem;
341
+ height: 0.3125rem;
342
+ border-radius: 999px;
343
+ background: var(--k2b-border-strong);
344
+ }
345
+
346
+ .cloud-panel__head {
347
+ padding-top: 0;
348
+ }
349
+
350
+ .cloud-panel__resize {
351
+ display: none !important;
352
+ }
353
+ }
354
+
355
+ @media print {
356
+ .cloud-panel {
357
+ display: none !important;
358
+ }
359
+ }
360
+
361
+ /* The provider's page inside the iframe: the panel surface from the first paint. */
362
+ .cloud-panel-page {
363
+ display: flex;
364
+ height: 100dvh;
365
+ min-height: 0;
366
+ flex-direction: column;
367
+ background: var(--k2b-surface);
368
+ }
369
+
370
+ html:has([data-cloud-panel-page]),
371
+ html:has([data-cloud-panel-page]) body {
372
+ background: var(--k2b-surface);
373
+ }
@@ -15,7 +15,16 @@
15
15
  --ui-hover: rgb(239 240 239 / 0.9);
16
16
  --ui-active: rgb(229 231 230 / 0.94);
17
17
  --ui-selected: color-mix(in srgb, var(--color-blue-500) 7%, var(--ui-surface));
18
- --ui-app-accent-text: color-mix(in srgb, var(--app-accent, var(--color-blue-500)) 78%, black);
18
+ /* app-color.ts computes these defaults from --color-blue-500; app-color.test.ts pins them. */
19
+ --app-ink-light: #2264c9;
20
+ --app-ink-dark: #589aff;
21
+ --app-selected-light: #f0f6ff;
22
+ --app-selected-dark: #15243b;
23
+ --app-selected-nav-light: #e0e8f6;
24
+ --app-selected-nav-dark: #22334e;
25
+ --ui-app-accent-text: var(--app-ink-light);
26
+ --ui-app-selected: var(--app-selected-light);
27
+ --ui-app-selected-nav: var(--app-selected-nav-light);
19
28
  --ui-app-accent-border: var(--app-accent, var(--color-blue-500));
20
29
  --ui-focus: inset 0 0 0 2px color-mix(in srgb, var(--color-blue-500) 45%, transparent);
21
30
  --ui-action-primary-surface: var(--color-zinc-900);
@@ -143,7 +152,9 @@
143
152
  --ui-hover: #252c35;
144
153
  --ui-active: color-mix(in srgb, var(--ui-hover) 72%, var(--ui-border-strong));
145
154
  --ui-selected: color-mix(in srgb, var(--color-blue-400) 12%, var(--ui-surface));
146
- --ui-app-accent-text: color-mix(in srgb, var(--app-accent, var(--color-blue-400)) 58%, white);
155
+ --ui-app-accent-text: var(--app-ink-dark);
156
+ --ui-app-selected: var(--app-selected-dark);
157
+ --ui-app-selected-nav: var(--app-selected-nav-dark);
147
158
  --ui-app-accent-border: color-mix(in srgb, var(--app-accent, var(--color-blue-400)) 58%, white);
148
159
  --ui-focus: inset 0 0 0 2px color-mix(in srgb, var(--color-blue-400) 55%, transparent);
149
160
  --ui-action-primary-surface: var(--color-zinc-100);
@@ -186,23 +197,29 @@
186
197
  --ui-shadow-workspace-edge: -3px 0 6px -5px rgb(0 0 0 / 0.28), 3px 0 6px -5px rgb(0 0 0 / 0.28);
187
198
  }
188
199
 
189
- /* App appearance is applied on the canvas rather than :root. Recompute the
190
- derived accent roles here so an app never inherits the platform fallback. */
200
+ /* Custom properties resolve where declared. Each app scope must re-read its
201
+ inline per-app values instead of inheriting the resolved platform defaults. */
191
202
  .cloud-app-canvas,
192
203
  .app-accent-scope {
193
- --ui-app-accent-text: color-mix(in srgb, var(--app-accent, var(--color-blue-500)) 78%, black);
204
+ --ui-app-accent-text: var(--app-ink-light);
205
+ --ui-app-selected: var(--app-selected-light);
206
+ --ui-app-selected-nav: var(--app-selected-nav-light);
194
207
  --ui-app-accent-border: var(--app-accent, var(--color-blue-500));
195
208
  /* Portable UI components consume their own optional hook; Cloud alone maps
196
209
  it to the active app appearance. */
197
210
  --k2b-app-workspace-active: var(--ui-app-accent-text);
211
+ --k2b-app-workspace-selected: var(--ui-app-selected-nav);
198
212
  --k2b-detail-panel-accent: var(--ui-app-accent-text);
199
213
  --k2b-link-accent: var(--ui-app-accent-text);
200
214
  }
201
215
 
202
216
  .dark :is(.cloud-app-canvas, .app-accent-scope) {
203
- --ui-app-accent-text: color-mix(in srgb, var(--app-accent, var(--color-blue-400)) 58%, white);
217
+ --ui-app-accent-text: var(--app-ink-dark);
218
+ --ui-app-selected: var(--app-selected-dark);
219
+ --ui-app-selected-nav: var(--app-selected-nav-dark);
204
220
  --ui-app-accent-border: color-mix(in srgb, var(--app-accent, var(--color-blue-400)) 58%, white);
205
221
  --k2b-app-workspace-active: var(--ui-app-accent-text);
222
+ --k2b-app-workspace-selected: var(--ui-app-selected-nav);
206
223
  --k2b-detail-panel-accent: var(--ui-app-accent-text);
207
224
  --k2b-link-accent: var(--ui-app-accent-text);
208
225
  }
@@ -226,12 +226,12 @@
226
226
  @utility sidebar-item-active {
227
227
  position: relative;
228
228
  background: var(--ui-selected);
229
- color: color-mix(in srgb, var(--app-accent, var(--color-blue-500)) 78%, black);
229
+ color: var(--ui-app-accent-text);
230
230
  @apply font-medium;
231
231
  box-shadow: var(--ui-shadow-surface);
232
232
 
233
233
  &:hover {
234
- color: color-mix(in srgb, var(--app-accent, var(--color-blue-500)) 88%, black);
234
+ color: var(--ui-app-accent-text);
235
235
  }
236
236
 
237
237
  &::before {
@@ -241,14 +241,6 @@
241
241
  }
242
242
  }
243
243
 
244
- .dark .sidebar-item-active {
245
- color: color-mix(in srgb, var(--app-accent, var(--color-blue-400)) 58%, white);
246
- }
247
-
248
- .dark .sidebar-item-active:hover {
249
- color: color-mix(in srgb, var(--app-accent, var(--color-blue-400)) 45%, white);
250
- }
251
-
252
244
  @utility sidebar-item-meta {
253
245
  @apply mt-0.5 text-left text-xs leading-tight text-dimmed;
254
246
  }
@@ -723,12 +715,12 @@
723
715
  border-left: 0;
724
716
  position: relative;
725
717
  background: var(--ui-selected);
726
- color: color-mix(in srgb, var(--app-accent, var(--color-blue-500)) 78%, black);
718
+ color: var(--ui-app-accent-text);
727
719
  @apply rounded-lg font-medium;
728
720
  box-shadow: var(--ui-shadow-surface);
729
721
 
730
722
  &:hover {
731
- color: color-mix(in srgb, var(--app-accent, var(--color-blue-500)) 88%, black);
723
+ color: var(--ui-app-accent-text);
732
724
  }
733
725
 
734
726
  &::before {
@@ -738,14 +730,6 @@
738
730
  }
739
731
  }
740
732
 
741
- .dark .list-item-active {
742
- color: color-mix(in srgb, var(--app-accent, var(--color-blue-400)) 58%, white);
743
- }
744
-
745
- .dark .list-item-active:hover {
746
- color: color-mix(in srgb, var(--app-accent, var(--color-blue-400)) 45%, white);
747
- }
748
-
749
733
  @utility section-label {
750
734
  @apply text-[0.6875rem] font-medium normal-case tracking-normal mb-5 text-dimmed select-none;
751
735
  }
@@ -1115,7 +1099,7 @@
1115
1099
  }
1116
1100
 
1117
1101
  .sidebar-icon-action-active {
1118
- color: color-mix(in srgb, var(--app-accent, var(--color-blue-500)) 78%, black);
1102
+ color: var(--ui-app-accent-text);
1119
1103
  background: var(--ui-selected);
1120
1104
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--app-accent, var(--color-blue-500)) 20%, transparent);
1121
1105
  }