@liberation-data/desk 0.1.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 (172) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +4 -0
  3. package/README.md +436 -0
  4. package/dist/core/commands.d.ts +40 -0
  5. package/dist/core/commands.d.ts.map +1 -0
  6. package/dist/core/commands.js +92 -0
  7. package/dist/core/commands.js.map +1 -0
  8. package/dist/core/desk.d.ts +46 -0
  9. package/dist/core/desk.d.ts.map +1 -0
  10. package/dist/core/desk.js +178 -0
  11. package/dist/core/desk.js.map +1 -0
  12. package/dist/core/events.d.ts +42 -0
  13. package/dist/core/events.d.ts.map +1 -0
  14. package/dist/core/events.js +54 -0
  15. package/dist/core/events.js.map +1 -0
  16. package/dist/core/index.d.ts +13 -0
  17. package/dist/core/index.d.ts.map +1 -0
  18. package/dist/core/index.js +7 -0
  19. package/dist/core/index.js.map +1 -0
  20. package/dist/core/location.d.ts +30 -0
  21. package/dist/core/location.d.ts.map +1 -0
  22. package/dist/core/location.js +99 -0
  23. package/dist/core/location.js.map +1 -0
  24. package/dist/core/shortcuts.d.ts +36 -0
  25. package/dist/core/shortcuts.d.ts.map +1 -0
  26. package/dist/core/shortcuts.js +73 -0
  27. package/dist/core/shortcuts.js.map +1 -0
  28. package/dist/core/titles.d.ts +3 -0
  29. package/dist/core/titles.d.ts.map +1 -0
  30. package/dist/core/titles.js +26 -0
  31. package/dist/core/titles.js.map +1 -0
  32. package/dist/core/types.d.ts +51 -0
  33. package/dist/core/types.d.ts.map +1 -0
  34. package/dist/core/types.js +2 -0
  35. package/dist/core/types.js.map +1 -0
  36. package/dist/desk.css +2550 -0
  37. package/dist/react/Desktop.d.ts +24 -0
  38. package/dist/react/Desktop.d.ts.map +1 -0
  39. package/dist/react/Desktop.js +212 -0
  40. package/dist/react/Desktop.js.map +1 -0
  41. package/dist/react/Dock.d.ts +42 -0
  42. package/dist/react/Dock.d.ts.map +1 -0
  43. package/dist/react/Dock.js +103 -0
  44. package/dist/react/Dock.js.map +1 -0
  45. package/dist/react/MenuBar.d.ts +64 -0
  46. package/dist/react/MenuBar.d.ts.map +1 -0
  47. package/dist/react/MenuBar.js +245 -0
  48. package/dist/react/MenuBar.js.map +1 -0
  49. package/dist/react/appFrame.d.ts +37 -0
  50. package/dist/react/appFrame.d.ts.map +1 -0
  51. package/dist/react/appFrame.js +119 -0
  52. package/dist/react/appFrame.js.map +1 -0
  53. package/dist/react/arrange.d.ts +24 -0
  54. package/dist/react/arrange.d.ts.map +1 -0
  55. package/dist/react/arrange.js +61 -0
  56. package/dist/react/arrange.js.map +1 -0
  57. package/dist/react/commands.d.ts +23 -0
  58. package/dist/react/commands.d.ts.map +1 -0
  59. package/dist/react/commands.js +41 -0
  60. package/dist/react/commands.js.map +1 -0
  61. package/dist/react/context.d.ts +25 -0
  62. package/dist/react/context.d.ts.map +1 -0
  63. package/dist/react/context.js +28 -0
  64. package/dist/react/context.js.map +1 -0
  65. package/dist/react/controls.d.ts +111 -0
  66. package/dist/react/controls.d.ts.map +1 -0
  67. package/dist/react/controls.js +83 -0
  68. package/dist/react/controls.js.map +1 -0
  69. package/dist/react/conversation.d.ts +41 -0
  70. package/dist/react/conversation.d.ts.map +1 -0
  71. package/dist/react/conversation.js +73 -0
  72. package/dist/react/conversation.js.map +1 -0
  73. package/dist/react/dnd.d.ts +51 -0
  74. package/dist/react/dnd.d.ts.map +1 -0
  75. package/dist/react/dnd.js +138 -0
  76. package/dist/react/dnd.js.map +1 -0
  77. package/dist/react/dragContext.d.ts +32 -0
  78. package/dist/react/dragContext.d.ts.map +1 -0
  79. package/dist/react/dragContext.js +14 -0
  80. package/dist/react/dragContext.js.map +1 -0
  81. package/dist/react/events.d.ts +41 -0
  82. package/dist/react/events.d.ts.map +1 -0
  83. package/dist/react/events.js +91 -0
  84. package/dist/react/events.js.map +1 -0
  85. package/dist/react/index.d.ts +43 -0
  86. package/dist/react/index.d.ts.map +1 -0
  87. package/dist/react/index.js +22 -0
  88. package/dist/react/index.js.map +1 -0
  89. package/dist/react/layers.d.ts +5 -0
  90. package/dist/react/layers.d.ts.map +1 -0
  91. package/dist/react/layers.js +65 -0
  92. package/dist/react/layers.js.map +1 -0
  93. package/dist/react/overlays.d.ts +67 -0
  94. package/dist/react/overlays.d.ts.map +1 -0
  95. package/dist/react/overlays.js +98 -0
  96. package/dist/react/overlays.js.map +1 -0
  97. package/dist/react/popup.d.ts +21 -0
  98. package/dist/react/popup.d.ts.map +1 -0
  99. package/dist/react/popup.js +94 -0
  100. package/dist/react/popup.js.map +1 -0
  101. package/dist/react/search.d.ts +33 -0
  102. package/dist/react/search.d.ts.map +1 -0
  103. package/dist/react/search.js +82 -0
  104. package/dist/react/search.js.map +1 -0
  105. package/dist/react/setupProgress.d.ts +35 -0
  106. package/dist/react/setupProgress.d.ts.map +1 -0
  107. package/dist/react/setupProgress.js +68 -0
  108. package/dist/react/setupProgress.js.map +1 -0
  109. package/dist/react/shell.d.ts +17 -0
  110. package/dist/react/shell.d.ts.map +1 -0
  111. package/dist/react/shell.js +13 -0
  112. package/dist/react/shell.js.map +1 -0
  113. package/dist/react/sidebar.d.ts +23 -0
  114. package/dist/react/sidebar.d.ts.map +1 -0
  115. package/dist/react/sidebar.js +26 -0
  116. package/dist/react/sidebar.js.map +1 -0
  117. package/dist/react/table.d.ts +39 -0
  118. package/dist/react/table.d.ts.map +1 -0
  119. package/dist/react/table.js +86 -0
  120. package/dist/react/table.js.map +1 -0
  121. package/dist/react/tasks.d.ts +41 -0
  122. package/dist/react/tasks.d.ts.map +1 -0
  123. package/dist/react/tasks.js +79 -0
  124. package/dist/react/tasks.js.map +1 -0
  125. package/dist/react/tour.d.ts +42 -0
  126. package/dist/react/tour.d.ts.map +1 -0
  127. package/dist/react/tour.js +68 -0
  128. package/dist/react/tour.js.map +1 -0
  129. package/dist/react/windowBoundary.d.ts +22 -0
  130. package/dist/react/windowBoundary.d.ts.map +1 -0
  131. package/dist/react/windowBoundary.js +50 -0
  132. package/dist/react/windowBoundary.js.map +1 -0
  133. package/dist/react/wizard.d.ts +41 -0
  134. package/dist/react/wizard.d.ts.map +1 -0
  135. package/dist/react/wizard.js +60 -0
  136. package/dist/react/wizard.js.map +1 -0
  137. package/llms.txt +410 -0
  138. package/package.json +64 -0
  139. package/src/core/commands.ts +142 -0
  140. package/src/core/desk.ts +229 -0
  141. package/src/core/events.ts +99 -0
  142. package/src/core/index.ts +43 -0
  143. package/src/core/location.ts +127 -0
  144. package/src/core/shortcuts.ts +119 -0
  145. package/src/core/titles.ts +28 -0
  146. package/src/core/types.ts +49 -0
  147. package/src/desk.css +2550 -0
  148. package/src/react/Desktop.tsx +349 -0
  149. package/src/react/Dock.tsx +258 -0
  150. package/src/react/MenuBar.tsx +350 -0
  151. package/src/react/appFrame.tsx +183 -0
  152. package/src/react/arrange.ts +82 -0
  153. package/src/react/commands.ts +60 -0
  154. package/src/react/context.tsx +55 -0
  155. package/src/react/controls.tsx +364 -0
  156. package/src/react/conversation.tsx +208 -0
  157. package/src/react/dnd.tsx +189 -0
  158. package/src/react/dragContext.tsx +60 -0
  159. package/src/react/events.tsx +149 -0
  160. package/src/react/index.ts +64 -0
  161. package/src/react/layers.ts +66 -0
  162. package/src/react/overlays.tsx +254 -0
  163. package/src/react/popup.tsx +176 -0
  164. package/src/react/search.tsx +177 -0
  165. package/src/react/setupProgress.ts +113 -0
  166. package/src/react/shell.tsx +27 -0
  167. package/src/react/sidebar.tsx +84 -0
  168. package/src/react/table.tsx +176 -0
  169. package/src/react/tasks.tsx +176 -0
  170. package/src/react/tour.tsx +183 -0
  171. package/src/react/windowBoundary.tsx +110 -0
  172. package/src/react/wizard.tsx +150 -0
package/src/desk.css ADDED
@@ -0,0 +1,2550 @@
1
+ /*
2
+ * desk — the stage and its windows. Every value reads a --desk-* token, so an
3
+ * app restyles the desk by redefining tokens, never by overriding selectors.
4
+ */
5
+ :root {
6
+ --desk-ground: #eef0f4;
7
+ --desk-surface: #ffffff;
8
+ --desk-titlebar: #f6f7f9;
9
+ --desk-ink: #1b1f27;
10
+ --desk-muted: #667085;
11
+ --desk-rule: #dde1e8;
12
+ --desk-accent: #5b57f5;
13
+ --desk-close: #ef6b63;
14
+ --desk-mode: #34c47a;
15
+ --desk-radius: 12px;
16
+ --desk-gap: 12px;
17
+ --desk-padding: 12px;
18
+ --desk-shadow: 0 1px 2px rgb(16 24 40 / 6%), 0 12px 32px rgb(16 24 40 / 10%);
19
+ --desk-shadow-floating: 0 2px 4px rgb(16 24 40 / 8%), 0 24px 60px rgb(16 24 40 / 22%);
20
+ --desk-font: system-ui, -apple-system, "Segoe UI", sans-serif;
21
+ --desk-font-mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
22
+
23
+ /* The spacing scale (HIG.md §2). Nothing between these values. */
24
+ --desk-space-1: 4px;
25
+ --desk-space-2: 8px;
26
+ --desk-space-3: 12px;
27
+ --desk-space-4: 16px;
28
+ --desk-space-5: 24px;
29
+ --desk-space-6: 32px;
30
+ --desk-space-7: 48px;
31
+
32
+ /* State, kept apart from the accent. */
33
+ --desk-ok: #2f9e68;
34
+ --desk-warn: #b7791f;
35
+ --desk-bad: #c6483f;
36
+
37
+ --desk-control-height: 28px;
38
+ --desk-control-height-small: 22px;
39
+ --desk-control-radius: 7px;
40
+ --desk-field-bg: #ffffff;
41
+ --desk-on-accent: #ffffff;
42
+ --desk-ease: cubic-bezier(.32, .72, 0, 1);
43
+ --desk-dock-size: 48px;
44
+ --desk-dock-glass: rgb(255 255 255 / 72%);
45
+ --desk-dock-icon: linear-gradient(160deg, #ffffff, #eceff5);
46
+ --desk-badge: #ef4444;
47
+ --desk-badge-ink: #ffffff;
48
+ /* Room the stage leaves at the bottom for an overlay dock. */
49
+ --desk-inset-bottom: 0px;
50
+ }
51
+
52
+ @media (prefers-color-scheme: dark) {
53
+ :root:not([data-theme="light"]) {
54
+ --desk-ground: #07090f;
55
+ --desk-surface: #101828;
56
+ --desk-titlebar: #0b111d;
57
+ --desk-ink: #e6e6e6;
58
+ --desk-muted: #99a1af;
59
+ --desk-rule: #1e2939;
60
+ --desk-shadow: 0 12px 32px rgb(0 0 0 / 45%);
61
+ --desk-shadow-floating: 0 30px 80px rgb(0 0 0 / 70%);
62
+ --desk-dock-glass: rgb(11 18 32 / 62%);
63
+ --desk-dock-icon: linear-gradient(160deg, #1a2338, #0e1526);
64
+ --desk-ok: #3ecf8e;
65
+ --desk-warn: #fbbf24;
66
+ --desk-bad: #f87171;
67
+ --desk-field-bg: rgb(0 0 0 / 35%);
68
+ }
69
+ }
70
+
71
+ :root[data-theme="dark"] {
72
+ --desk-ground: #07090f;
73
+ --desk-surface: #101828;
74
+ --desk-titlebar: #0b111d;
75
+ --desk-ink: #e6e6e6;
76
+ --desk-muted: #99a1af;
77
+ --desk-rule: #1e2939;
78
+ --desk-shadow: 0 12px 32px rgb(0 0 0 / 45%);
79
+ --desk-shadow-floating: 0 30px 80px rgb(0 0 0 / 70%);
80
+ --desk-dock-glass: rgb(11 18 32 / 62%);
81
+ --desk-dock-icon: linear-gradient(160deg, #1a2338, #0e1526);
82
+ --desk-ok: #3ecf8e;
83
+ --desk-warn: #fbbf24;
84
+ --desk-bad: #f87171;
85
+ --desk-field-bg: rgb(0 0 0 / 35%);
86
+ }
87
+
88
+ .desk-stage {
89
+ position: relative;
90
+ box-sizing: border-box;
91
+ height: 100%;
92
+ min-height: 0;
93
+ padding: var(--desk-padding);
94
+ padding-bottom: calc(var(--desk-padding) + var(--desk-inset-bottom));
95
+ display: grid;
96
+ grid-template: minmax(0, 1fr) / minmax(0, 1fr);
97
+ gap: var(--desk-gap);
98
+ overflow: hidden;
99
+ background: var(--desk-ground);
100
+ color: var(--desk-ink);
101
+ font-family: var(--desk-font);
102
+ }
103
+
104
+ .desk-window {
105
+ /* Filled windows fill the stage inside its padding, layered in the order they were used. */
106
+ position: absolute;
107
+ top: var(--desk-padding);
108
+ right: var(--desk-padding);
109
+ bottom: calc(var(--desk-padding) + var(--desk-inset-bottom));
110
+ left: var(--desk-padding);
111
+ box-sizing: border-box;
112
+ min-width: 0;
113
+ min-height: 0;
114
+ display: flex;
115
+ flex-direction: column;
116
+ background: var(--desk-surface);
117
+ border: 1px solid var(--desk-rule);
118
+ border-radius: var(--desk-radius);
119
+ box-shadow: var(--desk-shadow);
120
+ overflow: hidden;
121
+ transition: border-color .15s var(--desk-ease), box-shadow .15s var(--desk-ease);
122
+ }
123
+
124
+ .desk-window:focus {
125
+ /* The key window is already marked by its border; a ring on the whole window would be noise. */
126
+ outline: none;
127
+ }
128
+
129
+ .desk-window[data-focused] {
130
+ border-color: color-mix(in srgb, var(--desk-accent) 45%, var(--desk-rule));
131
+ }
132
+
133
+ .desk-window[data-hidden] {
134
+ display: none;
135
+ }
136
+
137
+ /* One window at a time: it fills the stage, and the zoom control is not offered. */
138
+ .desk-stage[data-layout="fullscreen"] .desk-window {
139
+ position: static;
140
+ inset: auto;
141
+ grid-area: 1 / 1;
142
+ }
143
+
144
+ .desk-window[data-mode="floating"] {
145
+ right: auto;
146
+ bottom: auto;
147
+ box-shadow: var(--desk-shadow-floating);
148
+ }
149
+
150
+ .desk-window[data-dragging] {
151
+ transition: none;
152
+ user-select: none;
153
+ }
154
+
155
+ .desk-titlebar {
156
+ flex: none;
157
+ display: flex;
158
+ align-items: center;
159
+ gap: 10px;
160
+ padding: 8px 12px;
161
+ background: var(--desk-titlebar);
162
+ border-bottom: 1px solid var(--desk-rule);
163
+ user-select: none;
164
+ }
165
+
166
+ .desk-titlebar[data-draggable] {
167
+ cursor: grab;
168
+ touch-action: none;
169
+ }
170
+
171
+ .desk-window[data-dragging] .desk-titlebar {
172
+ cursor: grabbing;
173
+ }
174
+
175
+ .desk-controls {
176
+ display: flex;
177
+ gap: 7px;
178
+ }
179
+
180
+ .desk-control {
181
+ width: 12px;
182
+ height: 12px;
183
+ padding: 0;
184
+ border: 0;
185
+ border-radius: 50%;
186
+ cursor: pointer;
187
+ background: var(--desk-rule);
188
+ }
189
+
190
+ .desk-window[data-focused] .desk-control[data-control="close"],
191
+ .desk-control[data-control="close"]:hover {
192
+ background: var(--desk-close);
193
+ }
194
+
195
+ .desk-window[data-focused] .desk-control[data-control="mode"],
196
+ .desk-control[data-control="mode"]:hover {
197
+ background: var(--desk-mode);
198
+ }
199
+
200
+ .desk-control:focus-visible {
201
+ outline: 2px solid var(--desk-accent);
202
+ outline-offset: 2px;
203
+ }
204
+
205
+ .desk-title {
206
+ margin: 0;
207
+ min-width: 0;
208
+ overflow: hidden;
209
+ text-overflow: ellipsis;
210
+ white-space: nowrap;
211
+ font-size: 13px;
212
+ font-weight: 600;
213
+ }
214
+
215
+ .desk-window:not([data-focused]) .desk-title {
216
+ color: var(--desk-muted);
217
+ }
218
+
219
+ .desk-window-actions {
220
+ margin-left: auto;
221
+ display: flex;
222
+ align-items: center;
223
+ gap: var(--desk-space-1);
224
+ }
225
+
226
+ .desk-body {
227
+ flex: 1;
228
+ min-height: 0;
229
+ overflow: auto;
230
+ }
231
+
232
+ .desk-window-status {
233
+ box-sizing: border-box;
234
+ height: 100%;
235
+ min-height: 120px;
236
+ display: flex;
237
+ flex-direction: column;
238
+ align-items: center;
239
+ justify-content: center;
240
+ gap: var(--desk-space-2);
241
+ padding: var(--desk-space-4);
242
+ text-align: center;
243
+ color: var(--desk-muted);
244
+ font-size: 13px;
245
+ }
246
+
247
+ .desk-window-status b {
248
+ color: var(--desk-ink);
249
+ font-weight: 600;
250
+ }
251
+
252
+ .desk-window-status-detail {
253
+ max-width: 40ch;
254
+ font-size: 12px;
255
+ }
256
+
257
+ /* Edges a window resizes from. Inside the window, so nothing clips them. */
258
+ .desk-edge {
259
+ position: absolute;
260
+ touch-action: none;
261
+ }
262
+
263
+ .desk-edge[data-edge="left"],
264
+ .desk-edge[data-edge="right"] {
265
+ top: 0;
266
+ bottom: 0;
267
+ width: 5px;
268
+ cursor: ew-resize;
269
+ }
270
+
271
+ .desk-edge[data-edge="left"] {
272
+ left: 0;
273
+ }
274
+
275
+ .desk-edge[data-edge="right"] {
276
+ right: 0;
277
+ }
278
+
279
+ .desk-edge[data-edge="bottom"] {
280
+ left: 0;
281
+ right: 0;
282
+ bottom: 0;
283
+ height: 5px;
284
+ cursor: ns-resize;
285
+ }
286
+
287
+ .desk-grip {
288
+ position: absolute;
289
+ right: 0;
290
+ bottom: 0;
291
+ width: 16px;
292
+ height: 16px;
293
+ cursor: nwse-resize;
294
+ touch-action: none;
295
+ }
296
+
297
+ /* Where a dragged window would land if it were dropped now. */
298
+ .desk-stage[data-snap]::after {
299
+ content: "";
300
+ position: absolute;
301
+ top: var(--desk-padding);
302
+ bottom: calc(var(--desk-padding) + var(--desk-inset-bottom));
303
+ width: calc(50% - var(--desk-padding) - var(--desk-gap) / 2);
304
+ border: 2px solid var(--desk-accent);
305
+ border-radius: var(--desk-radius);
306
+ background: color-mix(in srgb, var(--desk-accent) 14%, transparent);
307
+ pointer-events: none;
308
+ z-index: 5;
309
+ }
310
+
311
+ .desk-stage[data-snap="start"]::after {
312
+ left: var(--desk-padding);
313
+ }
314
+
315
+ .desk-stage[data-snap="end"]::after {
316
+ right: var(--desk-padding);
317
+ }
318
+
319
+ /* ── Dock ── */
320
+
321
+ .desk-dock {
322
+ box-sizing: border-box;
323
+ display: flex;
324
+ align-items: flex-end;
325
+ gap: 6px;
326
+ padding: 7px 9px;
327
+ max-width: calc(100% - 24px);
328
+ border-radius: 20px;
329
+ background: var(--desk-dock-glass);
330
+ backdrop-filter: blur(28px) saturate(170%);
331
+ -webkit-backdrop-filter: blur(28px) saturate(170%);
332
+ border: 1px solid var(--desk-rule);
333
+ box-shadow: var(--desk-shadow-floating);
334
+ font-family: var(--desk-font);
335
+ color: var(--desk-ink);
336
+ }
337
+
338
+ .desk-dock[data-placement="overlay"] {
339
+ position: absolute;
340
+ left: 50%;
341
+ bottom: 12px;
342
+ z-index: 1000;
343
+ transform: translateX(-50%);
344
+ }
345
+
346
+ .desk-dock-separator {
347
+ flex: none;
348
+ align-self: stretch;
349
+ width: 1px;
350
+ margin: 6px 4px;
351
+ background: var(--desk-rule);
352
+ }
353
+
354
+ .desk-dock-slot {
355
+ position: relative;
356
+ display: flex;
357
+ }
358
+
359
+ .desk-dock-item {
360
+ position: relative;
361
+ flex: none;
362
+ width: var(--desk-dock-size);
363
+ height: var(--desk-dock-size);
364
+ padding: 0;
365
+ display: grid;
366
+ place-items: center;
367
+ border: 1px solid var(--desk-rule);
368
+ border-radius: calc(var(--desk-dock-size) / 4);
369
+ background: var(--desk-dock-icon);
370
+ color: var(--desk-ink);
371
+ cursor: pointer;
372
+ transition: transform .18s var(--desk-ease), margin .18s var(--desk-ease);
373
+ }
374
+
375
+ .desk-dock-item:disabled {
376
+ opacity: .45;
377
+ cursor: not-allowed;
378
+ }
379
+
380
+ .desk-dock-item:focus-visible,
381
+ .desk-stack-item:focus-visible {
382
+ outline: 2px solid var(--desk-accent);
383
+ outline-offset: 2px;
384
+ }
385
+
386
+ @media (hover: hover) and (pointer: fine) {
387
+ .desk-dock-item:hover:not(:disabled) {
388
+ transform: translateY(-8px) scale(1.14);
389
+ margin: 0 5px;
390
+ }
391
+ }
392
+
393
+ .desk-dock-icon {
394
+ position: relative;
395
+ display: grid;
396
+ place-items: center;
397
+ width: 46%;
398
+ height: 46%;
399
+ }
400
+
401
+ .desk-dock-icon > svg {
402
+ width: 100%;
403
+ height: 100%;
404
+ }
405
+
406
+ .desk-dock-item[data-stack] .desk-dock-icon {
407
+ width: 72%;
408
+ height: 72%;
409
+ }
410
+
411
+ .desk-dock-preview {
412
+ width: 100%;
413
+ height: 100%;
414
+ display: grid;
415
+ grid-template-columns: 1fr 1fr;
416
+ gap: 3px;
417
+ }
418
+
419
+ .desk-dock-preview > span {
420
+ display: grid;
421
+ place-items: center;
422
+ padding: 3px;
423
+ border-radius: 4px;
424
+ background: color-mix(in srgb, var(--desk-ink) 10%, transparent);
425
+ color: var(--desk-muted);
426
+ }
427
+
428
+ .desk-dock-preview svg {
429
+ width: 100%;
430
+ height: 100%;
431
+ }
432
+
433
+ /* A dot for "a window is open", brighter when it has focus. */
434
+ .desk-dock-item[data-running]::after {
435
+ content: "";
436
+ position: absolute;
437
+ left: 50%;
438
+ bottom: -6px;
439
+ width: 4px;
440
+ height: 4px;
441
+ margin-left: -2px;
442
+ border-radius: 50%;
443
+ background: var(--desk-muted);
444
+ }
445
+
446
+ .desk-dock-item[data-focused]::after {
447
+ background: var(--desk-accent);
448
+ }
449
+
450
+ .desk-dock-badge {
451
+ position: absolute;
452
+ top: -5px;
453
+ right: -5px;
454
+ min-width: 18px;
455
+ height: 18px;
456
+ padding: 0 5px;
457
+ box-sizing: border-box;
458
+ display: grid;
459
+ place-items: center;
460
+ border-radius: 9px;
461
+ border: 2px solid var(--desk-surface);
462
+ background: var(--desk-badge);
463
+ color: var(--desk-badge-ink);
464
+ font-size: 10px;
465
+ font-weight: 700;
466
+ font-variant-numeric: tabular-nums;
467
+ line-height: 1;
468
+ }
469
+
470
+ .desk-dock-tip {
471
+ position: absolute;
472
+ bottom: calc(100% + 14px);
473
+ left: 50%;
474
+ transform: translateX(-50%);
475
+ padding: 3px 9px;
476
+ border-radius: 6px;
477
+ border: 1px solid var(--desk-rule);
478
+ background: var(--desk-surface);
479
+ color: var(--desk-ink);
480
+ font-size: 12px;
481
+ white-space: nowrap;
482
+ pointer-events: none;
483
+ opacity: 0;
484
+ transition: opacity .12s;
485
+ }
486
+
487
+ .desk-dock-item:hover .desk-dock-tip,
488
+ .desk-dock-item:focus-visible .desk-dock-tip {
489
+ opacity: 1;
490
+ }
491
+
492
+ .desk-dock-item[aria-expanded="true"] .desk-dock-tip {
493
+ opacity: 0;
494
+ }
495
+
496
+ /* ── Stack: a dock folder, fanned out ── */
497
+
498
+ .desk-stack {
499
+ position: absolute;
500
+ bottom: calc(100% + 18px);
501
+ left: 50%;
502
+ transform: translateX(-50%);
503
+ box-sizing: border-box;
504
+ width: max-content;
505
+ max-width: min(420px, calc(100vw - 32px));
506
+ padding: 12px;
507
+ border-radius: 18px;
508
+ border: 1px solid var(--desk-rule);
509
+ /* It carries labels, so it needs a surface behind them: glass alone let the window under it read through. */
510
+ background: var(--desk-surface);
511
+ backdrop-filter: blur(30px) saturate(160%);
512
+ -webkit-backdrop-filter: blur(30px) saturate(160%);
513
+ box-shadow: var(--desk-shadow-floating);
514
+ animation: desk-pop .18s var(--desk-ease);
515
+ }
516
+
517
+ @keyframes desk-pop {
518
+ from {
519
+ opacity: 0;
520
+ transform: translateX(-50%) translateY(6px) scale(.98);
521
+ }
522
+ }
523
+
524
+ .desk-stack-title {
525
+ margin: 0 0 8px 4px;
526
+ font-size: 11px;
527
+ font-weight: 700;
528
+ letter-spacing: .08em;
529
+ text-transform: uppercase;
530
+ color: var(--desk-muted);
531
+ }
532
+
533
+ .desk-stack-grid {
534
+ display: grid;
535
+ grid-template-columns: repeat(auto-fill, minmax(92px, 1fr));
536
+ width: min(380px, calc(100vw - 56px));
537
+ gap: 6px;
538
+ }
539
+
540
+ .desk-stack-item {
541
+ display: flex;
542
+ flex-direction: column;
543
+ align-items: center;
544
+ gap: 5px;
545
+ padding: 8px 4px;
546
+ border: 0;
547
+ border-radius: 11px;
548
+ background: none;
549
+ color: inherit;
550
+ font: inherit;
551
+ text-align: center;
552
+ cursor: pointer;
553
+ }
554
+
555
+ .desk-stack-item:hover:not(:disabled) {
556
+ background: color-mix(in srgb, var(--desk-ink) 7%, transparent);
557
+ }
558
+
559
+ .desk-stack-item .desk-dock-icon {
560
+ width: 40px;
561
+ height: 40px;
562
+ padding: 10px;
563
+ box-sizing: border-box;
564
+ border-radius: 10px;
565
+ border: 1px solid var(--desk-rule);
566
+ background: var(--desk-dock-icon);
567
+ }
568
+
569
+ .desk-stack-label {
570
+ font-size: 12px;
571
+ font-weight: 560;
572
+ }
573
+
574
+ .desk-stack-description {
575
+ font-size: 10.5px;
576
+ line-height: 1.3;
577
+ color: var(--desk-muted);
578
+ }
579
+
580
+ /* ── Menu bar ── */
581
+
582
+ .desk-menubar {
583
+ position: relative;
584
+ z-index: 1100;
585
+ box-sizing: border-box;
586
+ display: flex;
587
+ align-items: center;
588
+ gap: 2px;
589
+ height: 30px;
590
+ padding: 0 10px;
591
+ background: var(--desk-dock-glass);
592
+ backdrop-filter: blur(24px) saturate(160%);
593
+ -webkit-backdrop-filter: blur(24px) saturate(160%);
594
+ border-bottom: 1px solid var(--desk-rule);
595
+ color: var(--desk-ink);
596
+ font-family: var(--desk-font);
597
+ font-size: 13px;
598
+ user-select: none;
599
+ }
600
+
601
+ .desk-menubar-leading,
602
+ .desk-menubar-trailing {
603
+ display: flex;
604
+ align-items: center;
605
+ gap: 8px;
606
+ padding: 0 6px;
607
+ }
608
+
609
+ .desk-menubar-leading {
610
+ font-weight: 700;
611
+ }
612
+
613
+ .desk-menubar-trailing {
614
+ color: var(--desk-muted);
615
+ font-size: 12px;
616
+ font-variant-numeric: tabular-nums;
617
+ }
618
+
619
+ .desk-menubar-spacer {
620
+ flex: 1;
621
+ }
622
+
623
+ .desk-menubar-slot {
624
+ position: relative;
625
+ }
626
+
627
+ .desk-menubar-title {
628
+ display: flex;
629
+ align-items: center;
630
+ gap: 6px;
631
+ height: 22px;
632
+ padding: 0 9px;
633
+ border: 0;
634
+ border-radius: 6px;
635
+ background: none;
636
+ color: inherit;
637
+ font: inherit;
638
+ white-space: nowrap;
639
+ cursor: default;
640
+ }
641
+
642
+ .desk-menubar-title[data-emphasis] {
643
+ font-weight: 700;
644
+ }
645
+
646
+ .desk-menubar-title:hover,
647
+ .desk-menubar-title[aria-expanded="true"] {
648
+ background: color-mix(in srgb, var(--desk-ink) 12%, transparent);
649
+ }
650
+
651
+ .desk-menubar-title:focus-visible {
652
+ outline: 2px solid var(--desk-accent);
653
+ outline-offset: -2px;
654
+ }
655
+
656
+ .desk-menubar-title svg {
657
+ width: 15px;
658
+ height: 15px;
659
+ }
660
+
661
+ .desk-menubar-slot[data-align="end"] .desk-menu {
662
+ left: auto;
663
+ right: 0;
664
+ }
665
+
666
+ .desk-menu {
667
+ position: absolute;
668
+ top: calc(100% + 4px);
669
+ left: 0;
670
+ box-sizing: border-box;
671
+ min-width: 220px;
672
+ max-width: min(360px, calc(100vw - 24px));
673
+ padding: 5px;
674
+ border-radius: 10px;
675
+ border: 1px solid var(--desk-rule);
676
+ /* Opaque, like every other popup. A menu sits inside the menu bar's own backdrop blur, and a nested
677
+ backdrop-filter does not blur what is behind the bar, so a translucent menu let window text read through. */
678
+ background: var(--desk-surface);
679
+ box-shadow: var(--desk-shadow-floating);
680
+ animation: desk-menu-in .12s var(--desk-ease);
681
+ }
682
+
683
+ @keyframes desk-menu-in {
684
+ from {
685
+ opacity: 0;
686
+ transform: translateY(-3px);
687
+ }
688
+ }
689
+
690
+ .desk-menu-item {
691
+ display: flex;
692
+ align-items: center;
693
+ gap: 6px;
694
+ min-height: 24px;
695
+ padding: 2px 10px 2px 4px;
696
+ border-radius: 5px;
697
+ cursor: default;
698
+ }
699
+
700
+ .desk-menu-item[data-active] {
701
+ background: var(--desk-accent);
702
+ color: #fff;
703
+ }
704
+
705
+ .desk-menu-item[aria-disabled="true"] {
706
+ color: var(--desk-muted);
707
+ opacity: .55;
708
+ }
709
+
710
+ .desk-menu-check {
711
+ flex: none;
712
+ width: 14px;
713
+ text-align: center;
714
+ font-size: 12px;
715
+ }
716
+
717
+ .desk-menu-label {
718
+ flex: 1;
719
+ min-width: 0;
720
+ white-space: nowrap;
721
+ overflow: hidden;
722
+ text-overflow: ellipsis;
723
+ }
724
+
725
+ .desk-menu-detail,
726
+ .desk-menu-shortcut {
727
+ flex: none;
728
+ color: var(--desk-muted);
729
+ font-size: 12px;
730
+ }
731
+
732
+ .desk-menu-shortcut {
733
+ margin-left: 18px;
734
+ font-family: var(--desk-font);
735
+ letter-spacing: .04em;
736
+ }
737
+
738
+ .desk-menu-item[data-active] .desk-menu-detail,
739
+ .desk-menu-item[data-active] .desk-menu-shortcut {
740
+ color: rgb(255 255 255 / 80%);
741
+ }
742
+
743
+ .desk-menu-separator {
744
+ height: 1px;
745
+ margin: 5px 8px;
746
+ background: var(--desk-rule);
747
+ }
748
+
749
+ .desk-menu-header {
750
+ padding: 5px 10px 2px 24px;
751
+ font-size: 11px;
752
+ font-weight: 600;
753
+ color: var(--desk-muted);
754
+ }
755
+
756
+ @media (max-width: 640px) {
757
+ .desk-stage {
758
+ grid-template-columns: minmax(0, 1fr);
759
+ grid-auto-rows: minmax(320px, auto);
760
+ overflow-y: auto;
761
+ }
762
+ }
763
+
764
+ @media (prefers-reduced-motion: reduce) {
765
+ .desk-window,
766
+ .desk-dock-item,
767
+ .desk-dock-tip {
768
+ transition: none;
769
+ }
770
+
771
+ .desk-stack,
772
+ .desk-menu {
773
+ animation: none;
774
+ }
775
+ }
776
+
777
+ /* ── Controls ── */
778
+
779
+ .desk-button {
780
+ position: relative;
781
+ display: inline-flex;
782
+ align-items: center;
783
+ justify-content: center;
784
+ gap: var(--desk-space-2);
785
+ min-height: var(--desk-control-height);
786
+ padding: 0 var(--desk-space-3);
787
+ border: 1px solid var(--desk-rule);
788
+ border-radius: var(--desk-control-radius);
789
+ background: var(--desk-surface);
790
+ color: var(--desk-ink);
791
+ font-family: var(--desk-font);
792
+ font-size: 13px;
793
+ font-weight: 500;
794
+ white-space: nowrap;
795
+ cursor: pointer;
796
+ transition: background .12s var(--desk-ease), border-color .12s var(--desk-ease);
797
+ }
798
+
799
+ .desk-button[data-size="small"] {
800
+ min-height: var(--desk-control-height-small);
801
+ padding: 0 var(--desk-space-2);
802
+ font-size: 12px;
803
+ }
804
+
805
+ .desk-button[data-icon-only] {
806
+ padding: 0;
807
+ width: var(--desk-control-height);
808
+ }
809
+
810
+ /* A finger needs 44px even when the drawn control is smaller (HIG.md §9). */
811
+ @media (pointer: coarse) {
812
+ .desk-button::after,
813
+ .desk-toggle::after {
814
+ content: "";
815
+ position: absolute;
816
+ top: 50%;
817
+ left: 50%;
818
+ width: max(100%, 44px);
819
+ height: max(100%, 44px);
820
+ transform: translate(-50%, -50%);
821
+ }
822
+ }
823
+
824
+ .desk-button:hover:not(:disabled) {
825
+ border-color: color-mix(in srgb, var(--desk-ink) 28%, var(--desk-rule));
826
+ }
827
+
828
+ .desk-button:active:not(:disabled) {
829
+ background: color-mix(in srgb, var(--desk-ink) 8%, var(--desk-surface));
830
+ }
831
+
832
+ .desk-button[data-intent="default"] {
833
+ border-color: var(--desk-accent);
834
+ background: var(--desk-accent);
835
+ color: var(--desk-on-accent);
836
+ font-weight: 600;
837
+ }
838
+
839
+ .desk-button[data-intent="default"]:hover:not(:disabled) {
840
+ background: color-mix(in srgb, #fff 12%, var(--desk-accent));
841
+ }
842
+
843
+ .desk-button[data-intent="quiet"] {
844
+ border-color: transparent;
845
+ background: none;
846
+ }
847
+
848
+ .desk-button[data-intent="quiet"]:hover:not(:disabled) {
849
+ background: color-mix(in srgb, var(--desk-ink) 8%, transparent);
850
+ }
851
+
852
+ .desk-button[data-intent="destructive"] {
853
+ border-color: color-mix(in srgb, var(--desk-bad) 50%, var(--desk-rule));
854
+ color: var(--desk-bad);
855
+ }
856
+
857
+ .desk-button[data-intent="destructive"]:hover:not(:disabled) {
858
+ background: color-mix(in srgb, var(--desk-bad) 12%, transparent);
859
+ }
860
+
861
+ .desk-button:disabled,
862
+ .desk-segment:disabled,
863
+ .desk-toggle:disabled {
864
+ opacity: .45;
865
+ cursor: not-allowed;
866
+ }
867
+
868
+ .desk-button:focus-visible,
869
+ .desk-segment:focus-visible,
870
+ .desk-toggle:focus-visible,
871
+ .desk-input:focus-visible {
872
+ outline: 2px solid var(--desk-accent);
873
+ outline-offset: 2px;
874
+ }
875
+
876
+ .desk-button-icon,
877
+ .desk-segment-icon {
878
+ display: grid;
879
+ place-items: center;
880
+ width: 15px;
881
+ height: 15px;
882
+ }
883
+
884
+ .desk-button-icon svg,
885
+ .desk-segment-icon svg {
886
+ width: 100%;
887
+ height: 100%;
888
+ }
889
+
890
+ .desk-segmented {
891
+ display: inline-flex;
892
+ gap: 2px;
893
+ padding: 2px;
894
+ border: 1px solid var(--desk-rule);
895
+ border-radius: calc(var(--desk-control-radius) + 2px);
896
+ background: color-mix(in srgb, var(--desk-ink) 5%, transparent);
897
+ }
898
+
899
+ .desk-segment {
900
+ display: inline-flex;
901
+ align-items: center;
902
+ gap: var(--desk-space-1);
903
+ min-height: calc(var(--desk-control-height) - 6px);
904
+ padding: 0 var(--desk-space-3);
905
+ border: 0;
906
+ border-radius: calc(var(--desk-control-radius) - 1px);
907
+ background: none;
908
+ color: var(--desk-muted);
909
+ font-family: var(--desk-font);
910
+ font-size: 12.5px;
911
+ white-space: nowrap;
912
+ cursor: pointer;
913
+ }
914
+
915
+ .desk-segmented[data-size="small"] .desk-segment {
916
+ min-height: calc(var(--desk-control-height-small) - 4px);
917
+ padding: 0 var(--desk-space-2);
918
+ font-size: 11.5px;
919
+ }
920
+
921
+ .desk-segment[aria-checked="true"] {
922
+ background: var(--desk-surface);
923
+ border: 1px solid var(--desk-rule);
924
+ color: var(--desk-ink);
925
+ font-weight: 500;
926
+ }
927
+
928
+ .desk-segment:hover:not(:disabled):not([aria-checked="true"]) {
929
+ color: var(--desk-ink);
930
+ }
931
+
932
+ .desk-toggle {
933
+ position: relative;
934
+ flex: none;
935
+ width: 40px;
936
+ height: 24px;
937
+ padding: 0;
938
+ border: 1px solid var(--desk-rule);
939
+ border-radius: 12px;
940
+ background: color-mix(in srgb, var(--desk-ink) 12%, transparent);
941
+ cursor: pointer;
942
+ transition: background .16s var(--desk-ease), border-color .16s var(--desk-ease);
943
+ }
944
+
945
+ .desk-toggle[aria-checked="true"] {
946
+ border-color: var(--desk-accent);
947
+ background: var(--desk-accent);
948
+ }
949
+
950
+ .desk-toggle-knob {
951
+ position: absolute;
952
+ top: 2px;
953
+ left: 2px;
954
+ width: 18px;
955
+ height: 18px;
956
+ border-radius: 50%;
957
+ background: var(--desk-field-bg);
958
+ box-shadow: 0 1px 2px rgb(0 0 0 / 35%);
959
+ transition: transform .16s var(--desk-ease);
960
+ }
961
+
962
+ .desk-toggle[aria-checked="true"] .desk-toggle-knob {
963
+ transform: translateX(16px);
964
+ background: var(--desk-on-accent);
965
+ }
966
+
967
+ .desk-toggle-row {
968
+ display: flex;
969
+ align-items: center;
970
+ gap: var(--desk-space-3);
971
+ padding: var(--desk-space-2) 0;
972
+ }
973
+
974
+ .desk-toggle-text {
975
+ flex: 1;
976
+ min-width: 0;
977
+ display: flex;
978
+ flex-direction: column;
979
+ gap: 2px;
980
+ }
981
+
982
+ .desk-field {
983
+ display: flex;
984
+ flex-direction: column;
985
+ gap: var(--desk-space-1);
986
+ }
987
+
988
+ .desk-label {
989
+ font-size: 12px;
990
+ font-weight: 500;
991
+ color: var(--desk-muted);
992
+ }
993
+
994
+ .desk-label[data-hidden] {
995
+ position: absolute;
996
+ width: 1px;
997
+ height: 1px;
998
+ margin: -1px;
999
+ padding: 0;
1000
+ overflow: hidden;
1001
+ clip-path: inset(50%);
1002
+ white-space: nowrap;
1003
+ }
1004
+
1005
+ .desk-input {
1006
+ box-sizing: border-box;
1007
+ width: 100%;
1008
+ min-height: var(--desk-control-height);
1009
+ padding: 0 var(--desk-space-3);
1010
+ border: 1px solid var(--desk-rule);
1011
+ border-radius: var(--desk-control-radius);
1012
+ background: var(--desk-field-bg);
1013
+ color: var(--desk-ink);
1014
+ font-family: var(--desk-font);
1015
+ font-size: 13px;
1016
+ }
1017
+
1018
+ .desk-input::placeholder {
1019
+ color: var(--desk-muted);
1020
+ }
1021
+
1022
+ .desk-field[data-invalid] .desk-input {
1023
+ border-color: var(--desk-bad);
1024
+ }
1025
+
1026
+ .desk-help,
1027
+ .desk-error {
1028
+ font-size: 11.5px;
1029
+ line-height: 1.4;
1030
+ }
1031
+
1032
+ .desk-help {
1033
+ color: var(--desk-muted);
1034
+ }
1035
+
1036
+ .desk-error {
1037
+ color: var(--desk-bad);
1038
+ }
1039
+
1040
+ @media (prefers-reduced-motion: reduce) {
1041
+ .desk-button,
1042
+ .desk-toggle,
1043
+ .desk-toggle-knob {
1044
+ transition: none;
1045
+ }
1046
+ }
1047
+
1048
+ /* ── Overlays ── */
1049
+
1050
+ .desk-popover-anchor {
1051
+ position: relative;
1052
+ display: inline-flex;
1053
+ }
1054
+
1055
+ .desk-popover {
1056
+ position: absolute;
1057
+ z-index: 1200;
1058
+ min-width: 220px;
1059
+ max-width: min(360px, calc(100vw - 24px));
1060
+ padding: var(--desk-space-3);
1061
+ border: 1px solid var(--desk-rule);
1062
+ border-radius: 12px;
1063
+ background: var(--desk-surface);
1064
+ box-shadow: var(--desk-shadow-floating);
1065
+ animation: desk-menu-in .14s var(--desk-ease);
1066
+ }
1067
+
1068
+ .desk-popover[data-placement="below"] {
1069
+ top: calc(100% + 6px);
1070
+ }
1071
+
1072
+ .desk-popover[data-placement="above"] {
1073
+ bottom: calc(100% + 6px);
1074
+ }
1075
+
1076
+ .desk-popover[data-align="start"] {
1077
+ left: 0;
1078
+ }
1079
+
1080
+ .desk-popover[data-align="end"] {
1081
+ right: 0;
1082
+ }
1083
+
1084
+ /* A sheet belongs to its window: the scrim covers that window and nothing else. */
1085
+ .desk-sheet-scrim,
1086
+ .desk-alert-scrim {
1087
+ position: absolute;
1088
+ inset: 0;
1089
+ z-index: 1300;
1090
+ display: grid;
1091
+ background: rgb(0 0 0 / 35%);
1092
+ animation: desk-fade .16s var(--desk-ease);
1093
+ }
1094
+
1095
+ .desk-sheet-scrim {
1096
+ place-items: start center;
1097
+ padding: var(--desk-space-4);
1098
+ }
1099
+
1100
+ .desk-alert-scrim {
1101
+ position: fixed;
1102
+ z-index: 1400;
1103
+ place-items: center;
1104
+ padding: var(--desk-space-4);
1105
+ background: rgb(0 0 0 / 45%);
1106
+ }
1107
+
1108
+ @keyframes desk-fade {
1109
+ from {
1110
+ opacity: 0;
1111
+ }
1112
+ }
1113
+
1114
+ .desk-sheet,
1115
+ .desk-alert {
1116
+ box-sizing: border-box;
1117
+ width: min(440px, 100%);
1118
+ padding: var(--desk-space-4);
1119
+ border: 1px solid var(--desk-rule);
1120
+ border-radius: 14px;
1121
+ background: var(--desk-surface);
1122
+ color: var(--desk-ink);
1123
+ box-shadow: var(--desk-shadow-floating);
1124
+ font-family: var(--desk-font);
1125
+ }
1126
+
1127
+ .desk-sheet {
1128
+ animation: desk-sheet-in .22s var(--desk-ease);
1129
+ }
1130
+
1131
+ .desk-alert {
1132
+ width: min(380px, 100%);
1133
+ text-align: center;
1134
+ animation: desk-alert-in .16s var(--desk-ease);
1135
+ }
1136
+
1137
+ @keyframes desk-sheet-in {
1138
+ from {
1139
+ transform: translateY(-12px);
1140
+ opacity: 0;
1141
+ }
1142
+ }
1143
+
1144
+ @keyframes desk-alert-in {
1145
+ from {
1146
+ transform: scale(.97);
1147
+ opacity: 0;
1148
+ }
1149
+ }
1150
+
1151
+ .desk-sheet-title,
1152
+ .desk-alert-title {
1153
+ margin: 0 0 var(--desk-space-1);
1154
+ font-size: 15px;
1155
+ font-weight: 600;
1156
+ }
1157
+
1158
+ .desk-sheet-description,
1159
+ .desk-alert-message {
1160
+ margin: 0 0 var(--desk-space-3);
1161
+ color: var(--desk-muted);
1162
+ font-size: 13px;
1163
+ line-height: 1.5;
1164
+ }
1165
+
1166
+ .desk-sheet-actions,
1167
+ .desk-alert-actions {
1168
+ display: flex;
1169
+ justify-content: flex-end;
1170
+ gap: var(--desk-space-2);
1171
+ margin-top: var(--desk-space-4);
1172
+ }
1173
+
1174
+ .desk-alert-actions {
1175
+ justify-content: center;
1176
+ }
1177
+
1178
+ .desk-toasts {
1179
+ position: fixed;
1180
+ z-index: 1500;
1181
+ right: var(--desk-space-4);
1182
+ bottom: var(--desk-space-4);
1183
+ display: flex;
1184
+ flex-direction: column;
1185
+ gap: var(--desk-space-2);
1186
+ max-width: min(420px, calc(100vw - 32px));
1187
+ }
1188
+
1189
+ .desk-toast {
1190
+ display: flex;
1191
+ align-items: center;
1192
+ gap: var(--desk-space-2);
1193
+ padding: var(--desk-space-2) var(--desk-space-2) var(--desk-space-2) var(--desk-space-3);
1194
+ border: 1px solid var(--desk-rule);
1195
+ border-radius: 10px;
1196
+ background: var(--desk-surface);
1197
+ box-shadow: var(--desk-shadow-floating);
1198
+ font-family: var(--desk-font);
1199
+ font-size: 13px;
1200
+ animation: desk-toast-in .2s var(--desk-ease);
1201
+ }
1202
+
1203
+ @keyframes desk-toast-in {
1204
+ from {
1205
+ transform: translateY(8px);
1206
+ opacity: 0;
1207
+ }
1208
+ }
1209
+
1210
+ .desk-toast[data-tone="ok"] {
1211
+ border-color: color-mix(in srgb, var(--desk-ok) 45%, var(--desk-rule));
1212
+ }
1213
+
1214
+ .desk-toast[data-tone="bad"] {
1215
+ border-color: color-mix(in srgb, var(--desk-bad) 45%, var(--desk-rule));
1216
+ }
1217
+
1218
+ .desk-toast-message {
1219
+ flex: 1;
1220
+ min-width: 0;
1221
+ }
1222
+
1223
+ @media (prefers-reduced-motion: reduce) {
1224
+ .desk-inputbar,
1225
+ .desk-inputbar-scrim,
1226
+ .desk-popover,
1227
+ .desk-sheet,
1228
+ .desk-alert,
1229
+ .desk-toast,
1230
+ .desk-sheet-scrim,
1231
+ .desk-alert-scrim {
1232
+ animation: none;
1233
+ }
1234
+ }
1235
+
1236
+ /* ── Conversation ── */
1237
+
1238
+ .desk-thread {
1239
+ position: relative;
1240
+ display: flex;
1241
+ flex-direction: column;
1242
+ min-height: 0;
1243
+ height: 100%;
1244
+ font-family: var(--desk-font);
1245
+ }
1246
+
1247
+ .desk-thread-scroll {
1248
+ flex: 1;
1249
+ min-height: 0;
1250
+ overflow-y: auto;
1251
+ display: flex;
1252
+ flex-direction: column;
1253
+ gap: var(--desk-space-1);
1254
+ padding: var(--desk-space-4);
1255
+ }
1256
+
1257
+ .desk-message {
1258
+ display: flex;
1259
+ flex-direction: column;
1260
+ align-items: flex-start;
1261
+ max-width: min(80%, 60ch);
1262
+ }
1263
+
1264
+ .desk-message[data-mine] {
1265
+ align-self: flex-end;
1266
+ align-items: flex-end;
1267
+ }
1268
+
1269
+ /* A new run of messages from the same person gets air; the rest stay close. */
1270
+ .desk-message[data-run-start] {
1271
+ margin-top: var(--desk-space-3);
1272
+ }
1273
+
1274
+ .desk-message:first-child {
1275
+ margin-top: 0;
1276
+ }
1277
+
1278
+ .desk-message-author {
1279
+ margin-bottom: 2px;
1280
+ padding: 0 var(--desk-space-1);
1281
+ font-size: 11.5px;
1282
+ font-weight: 600;
1283
+ color: var(--desk-muted);
1284
+ }
1285
+
1286
+ .desk-bubble {
1287
+ padding: var(--desk-space-2) var(--desk-space-3);
1288
+ border: 1px solid var(--desk-rule);
1289
+ border-radius: 14px;
1290
+ background: var(--desk-surface);
1291
+ font-size: 13.5px;
1292
+ line-height: 1.5;
1293
+ white-space: pre-wrap;
1294
+ overflow-wrap: anywhere;
1295
+ }
1296
+
1297
+ .desk-message[data-mine] .desk-bubble {
1298
+ border-color: transparent;
1299
+ background: var(--desk-accent);
1300
+ color: var(--desk-on-accent);
1301
+ border-bottom-right-radius: 5px;
1302
+ }
1303
+
1304
+ .desk-message:not([data-mine]) .desk-bubble {
1305
+ border-bottom-left-radius: 5px;
1306
+ }
1307
+
1308
+ .desk-message[data-state="sending"] .desk-bubble {
1309
+ opacity: .6;
1310
+ }
1311
+
1312
+ .desk-message[data-state="failed"] .desk-bubble {
1313
+ border-color: var(--desk-bad);
1314
+ }
1315
+
1316
+ .desk-message-foot {
1317
+ display: flex;
1318
+ align-items: center;
1319
+ gap: var(--desk-space-2);
1320
+ padding: 2px var(--desk-space-1) 0;
1321
+ font-size: 11px;
1322
+ color: var(--desk-muted);
1323
+ }
1324
+
1325
+ .desk-message-foot:empty {
1326
+ display: none;
1327
+ }
1328
+
1329
+ .desk-message-failed {
1330
+ color: var(--desk-bad);
1331
+ }
1332
+
1333
+ .desk-typing {
1334
+ align-self: flex-start;
1335
+ margin-top: var(--desk-space-2);
1336
+ padding: var(--desk-space-2) var(--desk-space-3);
1337
+ border: 1px solid var(--desk-rule);
1338
+ border-radius: 14px;
1339
+ border-bottom-left-radius: 5px;
1340
+ background: var(--desk-surface);
1341
+ }
1342
+
1343
+ .desk-typing-dots {
1344
+ display: flex;
1345
+ gap: 4px;
1346
+ }
1347
+
1348
+ .desk-typing-dots i {
1349
+ width: 5px;
1350
+ height: 5px;
1351
+ border-radius: 50%;
1352
+ background: var(--desk-muted);
1353
+ animation: desk-typing 1.2s var(--desk-ease) infinite;
1354
+ }
1355
+
1356
+ .desk-typing-dots i:nth-child(2) {
1357
+ animation-delay: .15s;
1358
+ }
1359
+
1360
+ .desk-typing-dots i:nth-child(3) {
1361
+ animation-delay: .3s;
1362
+ }
1363
+
1364
+ @keyframes desk-typing {
1365
+ 0%, 60%, 100% {
1366
+ opacity: .3;
1367
+ }
1368
+ 30% {
1369
+ opacity: 1;
1370
+ }
1371
+ }
1372
+
1373
+ .desk-thread-jump {
1374
+ position: absolute;
1375
+ left: 50%;
1376
+ bottom: var(--desk-space-3);
1377
+ transform: translateX(-50%);
1378
+ box-shadow: var(--desk-shadow);
1379
+ }
1380
+
1381
+ .desk-composer {
1382
+ flex: none;
1383
+ display: flex;
1384
+ align-items: flex-end;
1385
+ gap: var(--desk-space-2);
1386
+ padding: var(--desk-space-3) var(--desk-space-4);
1387
+ border-top: 1px solid var(--desk-rule);
1388
+ }
1389
+
1390
+ .desk-composer-field {
1391
+ flex: 1;
1392
+ min-width: 0;
1393
+ min-height: var(--desk-control-height);
1394
+ max-height: 40vh;
1395
+ padding: var(--desk-space-2) var(--desk-space-3);
1396
+ border: 1px solid var(--desk-rule);
1397
+ border-radius: var(--desk-control-radius);
1398
+ background: var(--desk-field-bg);
1399
+ color: var(--desk-ink);
1400
+ font-family: var(--desk-font);
1401
+ font-size: 13.5px;
1402
+ line-height: 20px;
1403
+ resize: none;
1404
+ }
1405
+
1406
+ .desk-composer-field:focus-visible {
1407
+ outline: 2px solid var(--desk-accent);
1408
+ outline-offset: 2px;
1409
+ }
1410
+
1411
+ .desk-composer-field::placeholder {
1412
+ color: var(--desk-muted);
1413
+ }
1414
+
1415
+ @media (prefers-reduced-motion: reduce) {
1416
+ .desk-typing-dots i {
1417
+ animation: none;
1418
+ }
1419
+ }
1420
+
1421
+ /* ── Input bar: one place to type, which reaches the key window ── */
1422
+
1423
+ .desk-inputbar-scrim {
1424
+ position: fixed;
1425
+ inset: 0;
1426
+ z-index: 1450;
1427
+ display: grid;
1428
+ justify-items: center;
1429
+ align-content: center;
1430
+ padding: var(--desk-space-4);
1431
+ background: rgb(0 0 0 / 30%);
1432
+ animation: desk-fade .14s var(--desk-ease);
1433
+ }
1434
+
1435
+ .desk-inputbar[data-mode="summoned"] {
1436
+ animation: desk-alert-in .16s var(--desk-ease);
1437
+ }
1438
+
1439
+ .desk-inputbar {
1440
+ box-sizing: border-box;
1441
+ width: min(720px, 100%);
1442
+ border: 1px solid var(--desk-rule);
1443
+ border-radius: 14px;
1444
+ background: var(--desk-dock-glass);
1445
+ backdrop-filter: blur(28px) saturate(170%);
1446
+ -webkit-backdrop-filter: blur(28px) saturate(170%);
1447
+ box-shadow: var(--desk-shadow-floating);
1448
+ }
1449
+
1450
+ .desk-inputbar .desk-composer {
1451
+ border-top: 0;
1452
+ padding: var(--desk-space-2);
1453
+ }
1454
+
1455
+ .desk-inputbar-target {
1456
+ display: block;
1457
+ padding: 0 var(--desk-space-3) var(--desk-space-2);
1458
+ font-family: var(--desk-font);
1459
+ font-size: 11px;
1460
+ color: var(--desk-muted);
1461
+ }
1462
+
1463
+ .desk-inputbar-target b {
1464
+ font-weight: 600;
1465
+ color: var(--desk-ink);
1466
+ }
1467
+
1468
+ /* ── Search ── */
1469
+
1470
+ .desk-search-scrim {
1471
+ position: fixed;
1472
+ inset: 0;
1473
+ z-index: 1450;
1474
+ display: grid;
1475
+ justify-items: center;
1476
+ align-content: start;
1477
+ padding: 12vh var(--desk-space-4) var(--desk-space-4);
1478
+ background: rgb(0 0 0 / 35%);
1479
+ animation: desk-fade .14s var(--desk-ease);
1480
+ }
1481
+
1482
+ .desk-search {
1483
+ box-sizing: border-box;
1484
+ width: min(620px, 100%);
1485
+ max-height: 70vh;
1486
+ display: flex;
1487
+ flex-direction: column;
1488
+ border: 1px solid var(--desk-rule);
1489
+ border-radius: 14px;
1490
+ background: var(--desk-surface);
1491
+ box-shadow: var(--desk-shadow-floating);
1492
+ font-family: var(--desk-font);
1493
+ overflow: hidden;
1494
+ animation: desk-alert-in .16s var(--desk-ease);
1495
+ }
1496
+
1497
+ .desk-search-bar {
1498
+ flex: none;
1499
+ padding: var(--desk-space-3) var(--desk-space-4);
1500
+ border-bottom: 1px solid var(--desk-rule);
1501
+ }
1502
+
1503
+ .desk-search-field {
1504
+ width: 100%;
1505
+ border: 0;
1506
+ background: none;
1507
+ color: var(--desk-ink);
1508
+ font-family: var(--desk-font);
1509
+ font-size: 17px;
1510
+ outline: none;
1511
+ }
1512
+
1513
+ .desk-search-field::placeholder {
1514
+ color: var(--desk-muted);
1515
+ }
1516
+
1517
+ .desk-search-results {
1518
+ flex: 1;
1519
+ min-height: 0;
1520
+ margin: 0;
1521
+ padding: var(--desk-space-1);
1522
+ list-style: none;
1523
+ overflow-y: auto;
1524
+ }
1525
+
1526
+ .desk-search-group {
1527
+ margin: var(--desk-space-2) 0 2px;
1528
+ padding: 0 var(--desk-space-2);
1529
+ font-size: 11px;
1530
+ font-weight: 700;
1531
+ letter-spacing: .08em;
1532
+ text-transform: uppercase;
1533
+ color: var(--desk-muted);
1534
+ }
1535
+
1536
+ .desk-search-row {
1537
+ display: flex;
1538
+ align-items: center;
1539
+ gap: var(--desk-space-3);
1540
+ padding: var(--desk-space-2);
1541
+ border-radius: 8px;
1542
+ cursor: default;
1543
+ }
1544
+
1545
+ .desk-search-row[data-active] {
1546
+ background: var(--desk-accent);
1547
+ color: var(--desk-on-accent);
1548
+ }
1549
+
1550
+ .desk-search-icon {
1551
+ display: grid;
1552
+ place-items: center;
1553
+ width: 28px;
1554
+ height: 28px;
1555
+ flex: none;
1556
+ border: 1px solid var(--desk-rule);
1557
+ border-radius: 7px;
1558
+ }
1559
+
1560
+ .desk-search-icon svg {
1561
+ width: 15px;
1562
+ height: 15px;
1563
+ }
1564
+
1565
+ .desk-search-row[data-active] .desk-search-icon {
1566
+ border-color: transparent;
1567
+ background: rgb(255 255 255 / 18%);
1568
+ }
1569
+
1570
+ .desk-search-text {
1571
+ flex: 1;
1572
+ min-width: 0;
1573
+ }
1574
+
1575
+ .desk-search-title {
1576
+ display: block;
1577
+ font-size: 13.5px;
1578
+ font-weight: 500;
1579
+ }
1580
+
1581
+ .desk-search-subtitle,
1582
+ .desk-search-kind {
1583
+ font-size: 11.5px;
1584
+ color: var(--desk-muted);
1585
+ }
1586
+
1587
+ .desk-search-subtitle {
1588
+ display: block;
1589
+ }
1590
+
1591
+ .desk-search-kind {
1592
+ flex: none;
1593
+ font-family: var(--desk-font-mono);
1594
+ font-size: 10.5px;
1595
+ }
1596
+
1597
+ .desk-search-row[data-active] .desk-search-subtitle,
1598
+ .desk-search-row[data-active] .desk-search-kind {
1599
+ color: rgb(255 255 255 / 80%);
1600
+ }
1601
+
1602
+ .desk-search-empty {
1603
+ margin: 0;
1604
+ padding: var(--desk-space-5) var(--desk-space-4);
1605
+ text-align: center;
1606
+ color: var(--desk-muted);
1607
+ font-size: 13px;
1608
+ }
1609
+
1610
+ @media (prefers-reduced-motion: reduce) {
1611
+ .desk-search,
1612
+ .desk-search-scrim {
1613
+ animation: none;
1614
+ }
1615
+ }
1616
+
1617
+ /* ── Tour ── */
1618
+
1619
+ .desk-tour {
1620
+ box-sizing: border-box;
1621
+ width: min(620px, 100%);
1622
+ padding: var(--desk-space-3);
1623
+ border: 1px solid color-mix(in srgb, var(--desk-accent) 45%, var(--desk-rule));
1624
+ border-radius: 14px;
1625
+ background: var(--desk-dock-glass);
1626
+ backdrop-filter: blur(28px) saturate(170%);
1627
+ -webkit-backdrop-filter: blur(28px) saturate(170%);
1628
+ box-shadow: var(--desk-shadow-floating), 0 0 30px color-mix(in srgb, var(--desk-accent) 20%, transparent);
1629
+ font-family: var(--desk-font);
1630
+ color: var(--desk-ink);
1631
+ }
1632
+
1633
+ .desk-tour-head {
1634
+ display: flex;
1635
+ align-items: center;
1636
+ gap: var(--desk-space-2);
1637
+ font-size: 13px;
1638
+ }
1639
+
1640
+ .desk-tour-count {
1641
+ color: var(--desk-muted);
1642
+ font-size: 11.5px;
1643
+ font-variant-numeric: tabular-nums;
1644
+ }
1645
+
1646
+ .desk-tour-head .desk-button {
1647
+ margin-left: auto;
1648
+ }
1649
+
1650
+ .desk-tour-progress {
1651
+ height: 3px;
1652
+ margin: var(--desk-space-2) 0;
1653
+ border-radius: 2px;
1654
+ background: var(--desk-rule);
1655
+ overflow: hidden;
1656
+ }
1657
+
1658
+ .desk-tour-progress i {
1659
+ display: block;
1660
+ height: 100%;
1661
+ background: var(--desk-accent);
1662
+ transition: width .3s var(--desk-ease);
1663
+ }
1664
+
1665
+ .desk-tour-caption {
1666
+ margin: 0 0 var(--desk-space-2);
1667
+ font-size: 13.5px;
1668
+ line-height: 1.45;
1669
+ }
1670
+
1671
+ .desk-tour-turn {
1672
+ margin-right: var(--desk-space-1);
1673
+ color: var(--desk-warn);
1674
+ font-weight: 700;
1675
+ }
1676
+
1677
+ .desk-tour-turn::after {
1678
+ content: " ·";
1679
+ }
1680
+
1681
+ .desk-tour-actions {
1682
+ display: flex;
1683
+ align-items: center;
1684
+ gap: var(--desk-space-2);
1685
+ }
1686
+
1687
+ .desk-tour-spacer {
1688
+ flex: 1;
1689
+ }
1690
+
1691
+ /* What the tour is pointing at. */
1692
+ [data-desk-tour-pointed] {
1693
+ position: relative;
1694
+ z-index: 3;
1695
+ outline: 2px solid var(--desk-accent);
1696
+ outline-offset: 3px;
1697
+ border-radius: 6px;
1698
+ animation: desk-tour-pulse 1.6s var(--desk-ease) 2;
1699
+ }
1700
+
1701
+ @keyframes desk-tour-pulse {
1702
+ 0%, 100% {
1703
+ box-shadow: 0 0 0 0 color-mix(in srgb, var(--desk-accent) 0%, transparent);
1704
+ }
1705
+ 40% {
1706
+ box-shadow: 0 0 0 4px color-mix(in srgb, var(--desk-accent) 45%, transparent);
1707
+ }
1708
+ }
1709
+
1710
+ @media (prefers-reduced-motion: reduce) {
1711
+ .desk-tour-progress i {
1712
+ transition: none;
1713
+ }
1714
+
1715
+ [data-desk-tour-pointed] {
1716
+ animation: none;
1717
+ }
1718
+ }
1719
+
1720
+ /* ── Checkbox and slider ── */
1721
+
1722
+ .desk-check-row {
1723
+ display: flex;
1724
+ align-items: flex-start;
1725
+ gap: var(--desk-space-2);
1726
+ padding: var(--desk-space-1) 0;
1727
+ }
1728
+
1729
+ .desk-checkbox {
1730
+ width: 16px;
1731
+ height: 16px;
1732
+ margin: 2px 0 0;
1733
+ accent-color: var(--desk-accent);
1734
+ flex: none;
1735
+ }
1736
+
1737
+ .desk-check-text {
1738
+ display: flex;
1739
+ flex-direction: column;
1740
+ gap: 2px;
1741
+ }
1742
+
1743
+ .desk-check-label {
1744
+ font-size: 13px;
1745
+ }
1746
+
1747
+ .desk-checkbox:focus-visible,
1748
+ .desk-slider-track:focus-visible {
1749
+ outline: 2px solid var(--desk-accent);
1750
+ outline-offset: 2px;
1751
+ }
1752
+
1753
+ .desk-choices {
1754
+ margin: 0;
1755
+ padding: 0;
1756
+ border: 0;
1757
+ display: flex;
1758
+ flex-direction: column;
1759
+ gap: var(--desk-space-2);
1760
+ }
1761
+
1762
+ .desk-choice {
1763
+ display: flex;
1764
+ align-items: flex-start;
1765
+ gap: var(--desk-space-3);
1766
+ padding: var(--desk-space-3);
1767
+ border: 1px solid var(--desk-rule);
1768
+ border-radius: 12px;
1769
+ background: var(--desk-surface);
1770
+ cursor: pointer;
1771
+ }
1772
+
1773
+ .desk-choice:hover:not([data-disabled]) {
1774
+ border-color: color-mix(in srgb, var(--desk-accent) 50%, var(--desk-rule));
1775
+ }
1776
+
1777
+ .desk-choice[data-chosen] {
1778
+ border-color: var(--desk-accent);
1779
+ box-shadow: 0 0 0 1px var(--desk-accent);
1780
+ }
1781
+
1782
+ .desk-choice[data-disabled] {
1783
+ opacity: .45;
1784
+ cursor: not-allowed;
1785
+ }
1786
+
1787
+ .desk-choice:has(:focus-visible) {
1788
+ outline: 2px solid var(--desk-accent);
1789
+ outline-offset: 2px;
1790
+ }
1791
+
1792
+ .desk-choice-input {
1793
+ position: absolute;
1794
+ opacity: 0;
1795
+ pointer-events: none;
1796
+ }
1797
+
1798
+ .desk-choice-mark {
1799
+ flex: none;
1800
+ display: grid;
1801
+ place-items: center;
1802
+ width: 16px;
1803
+ height: 16px;
1804
+ margin-top: 2px;
1805
+ border: 1.5px solid var(--desk-rule);
1806
+ border-radius: 50%;
1807
+ }
1808
+
1809
+ .desk-choice[data-chosen] .desk-choice-mark {
1810
+ border-color: var(--desk-accent);
1811
+ }
1812
+
1813
+ .desk-choice[data-chosen] .desk-choice-mark::after {
1814
+ content: "";
1815
+ width: 8px;
1816
+ height: 8px;
1817
+ border-radius: 50%;
1818
+ background: var(--desk-accent);
1819
+ }
1820
+
1821
+ .desk-choice-icon {
1822
+ flex: none;
1823
+ display: grid;
1824
+ place-items: center;
1825
+ width: 36px;
1826
+ height: 36px;
1827
+ border: 1px solid var(--desk-rule);
1828
+ border-radius: 10px;
1829
+ color: var(--desk-muted);
1830
+ }
1831
+
1832
+ .desk-choice-icon svg {
1833
+ width: 18px;
1834
+ height: 18px;
1835
+ }
1836
+
1837
+ .desk-choice-text {
1838
+ flex: 1;
1839
+ min-width: 0;
1840
+ display: flex;
1841
+ flex-direction: column;
1842
+ gap: 2px;
1843
+ }
1844
+
1845
+ .desk-choice-label {
1846
+ font-weight: 600;
1847
+ }
1848
+
1849
+ .desk-choice-tag {
1850
+ margin-left: var(--desk-space-2);
1851
+ font-weight: 400;
1852
+ color: var(--desk-muted);
1853
+ }
1854
+
1855
+ .desk-checklist {
1856
+ display: flex;
1857
+ flex-direction: column;
1858
+ gap: var(--desk-space-3);
1859
+ }
1860
+
1861
+ .desk-progress {
1862
+ height: 5px;
1863
+ border-radius: 3px;
1864
+ background: var(--desk-rule);
1865
+ overflow: hidden;
1866
+ }
1867
+
1868
+ .desk-progress i {
1869
+ display: block;
1870
+ height: 100%;
1871
+ background: var(--desk-accent);
1872
+ transition: width .4s var(--desk-ease);
1873
+ }
1874
+
1875
+ .desk-tasks {
1876
+ margin: 0;
1877
+ padding: 0;
1878
+ list-style: none;
1879
+ border: 1px solid var(--desk-rule);
1880
+ border-radius: 12px;
1881
+ }
1882
+
1883
+ .desk-task {
1884
+ display: flex;
1885
+ align-items: center;
1886
+ gap: var(--desk-space-3);
1887
+ padding: var(--desk-space-2) var(--desk-space-3);
1888
+ }
1889
+
1890
+ .desk-task + .desk-task {
1891
+ border-top: 1px solid var(--desk-rule);
1892
+ }
1893
+
1894
+ .desk-task-mark {
1895
+ flex: none;
1896
+ display: grid;
1897
+ place-items: center;
1898
+ box-sizing: border-box;
1899
+ width: 20px;
1900
+ height: 20px;
1901
+ border-radius: 50%;
1902
+ font-size: 12px;
1903
+ border: 1.5px dashed var(--desk-rule);
1904
+ }
1905
+
1906
+ .desk-task[data-state="working"] .desk-task-mark {
1907
+ border: 2px solid var(--desk-rule);
1908
+ border-top-color: var(--desk-accent);
1909
+ animation: desk-spin .8s linear infinite;
1910
+ }
1911
+
1912
+ .desk-task[data-state="done"] .desk-task-mark {
1913
+ border: 0;
1914
+ background: color-mix(in srgb, var(--desk-ok) 18%, transparent);
1915
+ color: var(--desk-ok);
1916
+ }
1917
+
1918
+ .desk-task[data-state="failed"] .desk-task-mark {
1919
+ border: 0;
1920
+ background: color-mix(in srgb, var(--desk-bad) 18%, transparent);
1921
+ color: var(--desk-bad);
1922
+ font-weight: 700;
1923
+ }
1924
+
1925
+ @keyframes desk-spin {
1926
+ to {
1927
+ transform: rotate(360deg);
1928
+ }
1929
+ }
1930
+
1931
+ .desk-task-text {
1932
+ flex: 1;
1933
+ min-width: 0;
1934
+ display: flex;
1935
+ flex-direction: column;
1936
+ }
1937
+
1938
+ .desk-task-name {
1939
+ font-size: 13px;
1940
+ font-weight: 600;
1941
+ }
1942
+
1943
+ .desk-task-detail,
1944
+ .desk-task-error {
1945
+ font-size: 12px;
1946
+ color: var(--desk-muted);
1947
+ }
1948
+
1949
+ .desk-task-error {
1950
+ color: var(--desk-bad);
1951
+ }
1952
+
1953
+ @media (prefers-reduced-motion: reduce) {
1954
+ .desk-task[data-state="working"] .desk-task-mark {
1955
+ animation: none;
1956
+ }
1957
+ }
1958
+
1959
+ .desk-radiogroup {
1960
+ margin: 0;
1961
+ padding: 0;
1962
+ border: 0;
1963
+ display: flex;
1964
+ flex-direction: column;
1965
+ gap: var(--desk-space-1);
1966
+ }
1967
+
1968
+ .desk-radiogroup legend {
1969
+ padding: 0;
1970
+ margin-bottom: var(--desk-space-1);
1971
+ }
1972
+
1973
+ .desk-radio {
1974
+ width: 16px;
1975
+ height: 16px;
1976
+ margin: 2px 0 0;
1977
+ accent-color: var(--desk-accent);
1978
+ flex: none;
1979
+ }
1980
+
1981
+ .desk-radio:focus-visible {
1982
+ outline: 2px solid var(--desk-accent);
1983
+ outline-offset: 2px;
1984
+ }
1985
+
1986
+ .desk-slider {
1987
+ display: flex;
1988
+ flex-direction: column;
1989
+ gap: var(--desk-space-1);
1990
+ }
1991
+
1992
+ .desk-slider-head {
1993
+ display: flex;
1994
+ align-items: baseline;
1995
+ justify-content: space-between;
1996
+ gap: var(--desk-space-2);
1997
+ }
1998
+
1999
+ .desk-slider-value {
2000
+ font-size: 12px;
2001
+ font-variant-numeric: tabular-nums;
2002
+ color: var(--desk-ink);
2003
+ }
2004
+
2005
+ .desk-slider-track {
2006
+ width: 100%;
2007
+ accent-color: var(--desk-accent);
2008
+ }
2009
+
2010
+ /* ── Pop-up button ── */
2011
+
2012
+ .desk-popup-anchor {
2013
+ position: relative;
2014
+ }
2015
+
2016
+ .desk-popup-button {
2017
+ display: flex;
2018
+ align-items: center;
2019
+ gap: var(--desk-space-2);
2020
+ width: 100%;
2021
+ min-height: var(--desk-control-height);
2022
+ padding: 0 var(--desk-space-2) 0 var(--desk-space-3);
2023
+ border: 1px solid var(--desk-rule);
2024
+ border-radius: var(--desk-control-radius);
2025
+ background: var(--desk-field-bg);
2026
+ color: var(--desk-ink);
2027
+ font-family: var(--desk-font);
2028
+ font-size: 13px;
2029
+ text-align: left;
2030
+ cursor: pointer;
2031
+ }
2032
+
2033
+ .desk-popup-button[data-size="small"] {
2034
+ min-height: var(--desk-control-height-small);
2035
+ font-size: 12px;
2036
+ }
2037
+
2038
+ .desk-popup-button:focus-visible {
2039
+ outline: 2px solid var(--desk-accent);
2040
+ outline-offset: 2px;
2041
+ }
2042
+
2043
+ .desk-popup-button:disabled {
2044
+ opacity: .45;
2045
+ cursor: not-allowed;
2046
+ }
2047
+
2048
+ .desk-popup-value {
2049
+ flex: 1;
2050
+ min-width: 0;
2051
+ overflow: hidden;
2052
+ text-overflow: ellipsis;
2053
+ white-space: nowrap;
2054
+ }
2055
+
2056
+ .desk-popup-value[data-placeholder] {
2057
+ color: var(--desk-muted);
2058
+ }
2059
+
2060
+ .desk-popup-icon {
2061
+ display: grid;
2062
+ place-items: center;
2063
+ width: 16px;
2064
+ height: 16px;
2065
+ }
2066
+
2067
+ .desk-popup-chevron {
2068
+ color: var(--desk-muted);
2069
+ line-height: 1;
2070
+ }
2071
+
2072
+ .desk-popup-list {
2073
+ position: absolute;
2074
+ z-index: 1200;
2075
+ top: calc(100% + 4px);
2076
+ left: 0;
2077
+ min-width: 100%;
2078
+ max-height: 40vh;
2079
+ margin: 0;
2080
+ padding: 4px;
2081
+ list-style: none;
2082
+ overflow-y: auto;
2083
+ border: 1px solid var(--desk-rule);
2084
+ border-radius: 10px;
2085
+ background: var(--desk-surface);
2086
+ box-shadow: var(--desk-shadow-floating);
2087
+ animation: desk-menu-in .12s var(--desk-ease);
2088
+ }
2089
+
2090
+ .desk-popup-list:focus {
2091
+ outline: none;
2092
+ }
2093
+
2094
+ .desk-popup-option {
2095
+ display: flex;
2096
+ align-items: flex-start;
2097
+ gap: var(--desk-space-1);
2098
+ padding: var(--desk-space-1) var(--desk-space-2);
2099
+ border-radius: 6px;
2100
+ font-size: 13px;
2101
+ cursor: default;
2102
+ }
2103
+
2104
+ .desk-popup-option[data-active] {
2105
+ background: var(--desk-accent);
2106
+ color: var(--desk-on-accent);
2107
+ }
2108
+
2109
+ .desk-popup-option[data-active] .desk-help {
2110
+ color: rgb(255 255 255 / 80%);
2111
+ }
2112
+
2113
+ .desk-popup-option[aria-disabled] {
2114
+ opacity: .5;
2115
+ }
2116
+
2117
+ .desk-popup-check {
2118
+ width: 14px;
2119
+ flex: none;
2120
+ text-align: center;
2121
+ }
2122
+
2123
+ .desk-popup-text {
2124
+ display: flex;
2125
+ flex-direction: column;
2126
+ }
2127
+
2128
+ /* ── Table ── */
2129
+
2130
+ .desk-table-wrap {
2131
+ overflow: auto;
2132
+ }
2133
+
2134
+ .desk-table {
2135
+ width: 100%;
2136
+ border-collapse: collapse;
2137
+ font-family: var(--desk-font);
2138
+ font-size: 13px;
2139
+ }
2140
+
2141
+ .desk-table th {
2142
+ position: sticky;
2143
+ top: 0;
2144
+ z-index: 1;
2145
+ padding: var(--desk-space-1) var(--desk-space-2);
2146
+ border-bottom: 1px solid var(--desk-rule);
2147
+ background: var(--desk-surface);
2148
+ font-size: 11px;
2149
+ font-weight: 600;
2150
+ letter-spacing: .06em;
2151
+ text-transform: uppercase;
2152
+ color: var(--desk-muted);
2153
+ text-align: left;
2154
+ white-space: nowrap;
2155
+ }
2156
+
2157
+ .desk-table th[data-align="end"],
2158
+ .desk-table td[data-align="end"] {
2159
+ text-align: right;
2160
+ }
2161
+
2162
+ .desk-table-sort {
2163
+ display: inline-flex;
2164
+ align-items: center;
2165
+ gap: 4px;
2166
+ padding: 0;
2167
+ border: 0;
2168
+ background: none;
2169
+ color: inherit;
2170
+ font: inherit;
2171
+ letter-spacing: inherit;
2172
+ text-transform: inherit;
2173
+ cursor: pointer;
2174
+ }
2175
+
2176
+ .desk-table-sort:hover {
2177
+ color: var(--desk-ink);
2178
+ }
2179
+
2180
+ .desk-table td {
2181
+ padding: var(--desk-space-2);
2182
+ border-bottom: 1px solid var(--desk-rule);
2183
+ }
2184
+
2185
+ .desk-table td[data-numeric] {
2186
+ font-variant-numeric: tabular-nums;
2187
+ }
2188
+
2189
+ .desk-table tbody tr {
2190
+ cursor: default;
2191
+ }
2192
+
2193
+ .desk-table tbody tr:hover {
2194
+ background: color-mix(in srgb, var(--desk-ink) 5%, transparent);
2195
+ }
2196
+
2197
+ .desk-table tbody tr[data-selected] {
2198
+ background: color-mix(in srgb, var(--desk-accent) 16%, transparent);
2199
+ }
2200
+
2201
+ .desk-table tbody tr:focus-visible {
2202
+ outline: 2px solid var(--desk-accent);
2203
+ outline-offset: -2px;
2204
+ }
2205
+
2206
+ .desk-table-empty {
2207
+ padding: var(--desk-space-6) var(--desk-space-4);
2208
+ text-align: center;
2209
+ color: var(--desk-muted);
2210
+ font-family: var(--desk-font);
2211
+ font-size: 13px;
2212
+ }
2213
+
2214
+ /* ── Sidebar ── */
2215
+
2216
+ .desk-sidebar {
2217
+ display: flex;
2218
+ flex-direction: column;
2219
+ gap: var(--desk-space-3);
2220
+ padding: var(--desk-space-2);
2221
+ font-family: var(--desk-font);
2222
+ overflow-y: auto;
2223
+ }
2224
+
2225
+ .desk-sidebar ul {
2226
+ margin: 0;
2227
+ padding: 0;
2228
+ list-style: none;
2229
+ }
2230
+
2231
+ .desk-sidebar-heading {
2232
+ margin: 0 0 var(--desk-space-1);
2233
+ padding: 0 var(--desk-space-2);
2234
+ font-size: 11px;
2235
+ font-weight: 700;
2236
+ letter-spacing: .08em;
2237
+ text-transform: uppercase;
2238
+ color: var(--desk-muted);
2239
+ }
2240
+
2241
+ .desk-sidebar-item {
2242
+ display: flex;
2243
+ align-items: center;
2244
+ gap: var(--desk-space-2);
2245
+ width: 100%;
2246
+ padding: var(--desk-space-1) var(--desk-space-2);
2247
+ border: 0;
2248
+ border-radius: 7px;
2249
+ background: none;
2250
+ color: var(--desk-ink);
2251
+ font-family: inherit;
2252
+ font-size: 13px;
2253
+ text-align: left;
2254
+ cursor: pointer;
2255
+ }
2256
+
2257
+ .desk-sidebar-item:hover:not(:disabled) {
2258
+ background: color-mix(in srgb, var(--desk-ink) 7%, transparent);
2259
+ }
2260
+
2261
+ .desk-sidebar-item[data-current] {
2262
+ background: color-mix(in srgb, var(--desk-accent) 18%, transparent);
2263
+ font-weight: 500;
2264
+ }
2265
+
2266
+ .desk-sidebar-item:focus-visible {
2267
+ outline: 2px solid var(--desk-accent);
2268
+ outline-offset: -2px;
2269
+ }
2270
+
2271
+ .desk-sidebar-item:disabled {
2272
+ opacity: .45;
2273
+ cursor: not-allowed;
2274
+ }
2275
+
2276
+ .desk-sidebar-icon {
2277
+ display: grid;
2278
+ place-items: center;
2279
+ width: 16px;
2280
+ height: 16px;
2281
+ flex: none;
2282
+ color: var(--desk-muted);
2283
+ }
2284
+
2285
+ .desk-sidebar-item[data-current] .desk-sidebar-icon {
2286
+ color: var(--desk-accent);
2287
+ }
2288
+
2289
+ .desk-sidebar-label {
2290
+ flex: 1;
2291
+ min-width: 0;
2292
+ overflow: hidden;
2293
+ text-overflow: ellipsis;
2294
+ white-space: nowrap;
2295
+ }
2296
+
2297
+ .desk-sidebar-badge {
2298
+ flex: none;
2299
+ min-width: 18px;
2300
+ padding: 0 5px;
2301
+ border-radius: 9px;
2302
+ background: color-mix(in srgb, var(--desk-ink) 12%, transparent);
2303
+ font-size: 11px;
2304
+ font-variant-numeric: tabular-nums;
2305
+ text-align: center;
2306
+ }
2307
+
2308
+ .desk-sidebar-footer {
2309
+ margin-top: auto;
2310
+ padding: var(--desk-space-2);
2311
+ border-top: 1px solid var(--desk-rule);
2312
+ }
2313
+
2314
+ /* ── Wizard ── */
2315
+
2316
+ .desk-wizard {
2317
+ box-sizing: border-box;
2318
+ width: min(640px, 100%);
2319
+ min-height: 520px;
2320
+ display: flex;
2321
+ flex-direction: column;
2322
+ border: 1px solid var(--desk-rule);
2323
+ border-radius: 20px;
2324
+ background: var(--desk-surface);
2325
+ box-shadow: var(--desk-shadow-floating);
2326
+ font-family: var(--desk-font);
2327
+ color: var(--desk-ink);
2328
+ overflow: hidden;
2329
+ }
2330
+
2331
+ .desk-wizard-content {
2332
+ flex: 1;
2333
+ display: flex;
2334
+ flex-direction: column;
2335
+ align-items: center;
2336
+ gap: var(--desk-space-2);
2337
+ padding: var(--desk-space-7) var(--desk-space-6) var(--desk-space-5);
2338
+ text-align: center;
2339
+ animation: desk-wizard-in .32s var(--desk-ease);
2340
+ }
2341
+
2342
+ .desk-wizard-content[data-direction="back"] {
2343
+ animation-name: desk-wizard-back;
2344
+ }
2345
+
2346
+ @keyframes desk-wizard-in {
2347
+ from {
2348
+ opacity: 0;
2349
+ transform: translateX(22px);
2350
+ }
2351
+ }
2352
+
2353
+ @keyframes desk-wizard-back {
2354
+ from {
2355
+ opacity: 0;
2356
+ transform: translateX(-22px);
2357
+ }
2358
+ }
2359
+
2360
+ .desk-wizard-glyph {
2361
+ display: grid;
2362
+ place-items: center;
2363
+ width: 60px;
2364
+ height: 60px;
2365
+ margin-bottom: var(--desk-space-2);
2366
+ border: 1px solid var(--desk-rule);
2367
+ border-radius: 16px;
2368
+ color: var(--desk-accent);
2369
+ }
2370
+
2371
+ .desk-wizard-glyph svg {
2372
+ width: 28px;
2373
+ height: 28px;
2374
+ }
2375
+
2376
+ .desk-wizard-title {
2377
+ margin: 0;
2378
+ font-size: 22px;
2379
+ font-weight: 700;
2380
+ letter-spacing: -.02em;
2381
+ text-wrap: balance;
2382
+ }
2383
+
2384
+ .desk-wizard-title:focus {
2385
+ outline: none;
2386
+ }
2387
+
2388
+ .desk-wizard-description {
2389
+ margin: 0 0 var(--desk-space-4);
2390
+ max-width: 46ch;
2391
+ color: var(--desk-muted);
2392
+ font-size: 13.5px;
2393
+ line-height: 1.5;
2394
+ text-wrap: pretty;
2395
+ }
2396
+
2397
+ /* Whatever the step puts in the pane lines up left, even though the pane is centred. */
2398
+ .desk-wizard-content > *:not(.desk-wizard-glyph):not(.desk-wizard-title):not(.desk-wizard-description) {
2399
+ width: 100%;
2400
+ max-width: 420px;
2401
+ text-align: left;
2402
+ }
2403
+
2404
+ .desk-wizard-error {
2405
+ margin: var(--desk-space-3) 0 0;
2406
+ padding: var(--desk-space-2) var(--desk-space-3);
2407
+ border-radius: var(--desk-control-radius);
2408
+ background: color-mix(in srgb, var(--desk-bad) 14%, transparent);
2409
+ color: var(--desk-ink);
2410
+ font-size: 13px;
2411
+ }
2412
+
2413
+ .desk-wizard-foot {
2414
+ flex: none;
2415
+ display: flex;
2416
+ align-items: center;
2417
+ gap: var(--desk-space-3);
2418
+ padding: var(--desk-space-3) var(--desk-space-4);
2419
+ border-top: 1px solid var(--desk-rule);
2420
+ background: var(--desk-titlebar);
2421
+ }
2422
+
2423
+ .desk-wizard-steps {
2424
+ display: flex;
2425
+ align-items: center;
2426
+ gap: 6px;
2427
+ margin: 0;
2428
+ padding: 0;
2429
+ list-style: none;
2430
+ }
2431
+
2432
+ .desk-wizard-dot {
2433
+ width: 7px;
2434
+ height: 7px;
2435
+ border-radius: 50%;
2436
+ background: color-mix(in srgb, var(--desk-ink) 20%, transparent);
2437
+ transition: width .25s var(--desk-ease), background .25s var(--desk-ease);
2438
+ }
2439
+
2440
+ .desk-wizard-dot[data-state="done"] {
2441
+ background: var(--desk-muted);
2442
+ }
2443
+
2444
+ .desk-wizard-dot[data-state="now"] {
2445
+ width: 22px;
2446
+ border-radius: 4px;
2447
+ background: var(--desk-accent);
2448
+ }
2449
+
2450
+ .desk-wizard-dot-name {
2451
+ position: absolute;
2452
+ width: 1px;
2453
+ height: 1px;
2454
+ overflow: hidden;
2455
+ clip-path: inset(50%);
2456
+ white-space: nowrap;
2457
+ }
2458
+
2459
+ .desk-wizard-step-name {
2460
+ font-size: 11.5px;
2461
+ color: var(--desk-muted);
2462
+ }
2463
+
2464
+ .desk-wizard-actions {
2465
+ margin-left: auto;
2466
+ display: flex;
2467
+ align-items: center;
2468
+ gap: var(--desk-space-2);
2469
+ }
2470
+
2471
+ @media (max-width: 560px) {
2472
+ .desk-wizard {
2473
+ min-height: 0;
2474
+ }
2475
+
2476
+ .desk-wizard-content {
2477
+ padding: var(--desk-space-5) var(--desk-space-4) var(--desk-space-4);
2478
+ }
2479
+
2480
+ .desk-wizard-step-name {
2481
+ display: none;
2482
+ }
2483
+ }
2484
+
2485
+ @media (prefers-reduced-motion: reduce) {
2486
+ .desk-wizard-content {
2487
+ animation: none;
2488
+ }
2489
+
2490
+ .desk-wizard-dot {
2491
+ transition: none;
2492
+ }
2493
+ }
2494
+
2495
+ /* ── Dragging between windows ── */
2496
+
2497
+ .desk-drag-preview {
2498
+ position: fixed;
2499
+ z-index: 1600;
2500
+ transform: translate(12px, 12px);
2501
+ padding: var(--desk-space-1) var(--desk-space-3);
2502
+ border: 1px solid var(--desk-rule);
2503
+ border-radius: 8px;
2504
+ background: var(--desk-surface);
2505
+ box-shadow: var(--desk-shadow-floating);
2506
+ color: var(--desk-ink);
2507
+ font-family: var(--desk-font);
2508
+ font-size: 12.5px;
2509
+ pointer-events: none;
2510
+ }
2511
+
2512
+ [data-desk-draggable] {
2513
+ cursor: grab;
2514
+ touch-action: none;
2515
+ /* Pressing to drag should pick the thing up, not start selecting its text. */
2516
+ user-select: none;
2517
+ -webkit-user-select: none;
2518
+ }
2519
+
2520
+ [data-desk-draggable]:active {
2521
+ cursor: grabbing;
2522
+ }
2523
+
2524
+ /* A target says it could take this while something is being carried, and lights up under it. */
2525
+ [data-desk-drop][data-ready] {
2526
+ outline: 1px dashed color-mix(in srgb, var(--desk-accent) 55%, transparent);
2527
+ outline-offset: -3px;
2528
+ border-radius: 8px;
2529
+ }
2530
+
2531
+ [data-desk-drop][data-over] {
2532
+ outline: 2px solid var(--desk-accent);
2533
+ background: color-mix(in srgb, var(--desk-accent) 12%, transparent);
2534
+ }
2535
+
2536
+ /* ── A generated app in a window ── */
2537
+
2538
+ .desk-app-frame {
2539
+ position: relative;
2540
+ height: 100%;
2541
+ min-height: 0;
2542
+ display: flex;
2543
+ }
2544
+
2545
+ .desk-app-frame-page {
2546
+ flex: 1;
2547
+ width: 100%;
2548
+ border: 0;
2549
+ background: var(--desk-surface);
2550
+ }