anentrypoint-design 0.0.477 → 0.0.480

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 (53) hide show
  1. package/README.md +101 -0
  2. package/chat.css +4 -4
  3. package/colors_and_type.css +33 -3
  4. package/community.css +22 -8
  5. package/dist/247420.css +324 -49
  6. package/dist/247420.js +123 -55
  7. package/dist/index.html +109 -32
  8. package/package.json +1 -1
  9. package/src/community-app.js +4 -2
  10. package/src/components/community/navigation.js +2 -2
  11. package/src/components/community/presence.js +10 -4
  12. package/src/components/community/views.js +8 -2
  13. package/src/components/content/avatar.js +30 -0
  14. package/src/components/content/hero.js +9 -2
  15. package/src/components/content.js +2 -2
  16. package/src/components/freddie/pages-missing.js +1 -1
  17. package/src/components/overlay-primitives/emoji-picker.js +15 -3
  18. package/src/components/shell/app-shell.js +15 -4
  19. package/src/components/shell/workspace-shell.js +1 -1
  20. package/src/components/theme-toggle.js +8 -3
  21. package/src/copy-code.js +103 -0
  22. package/src/css/app-shell/base.css +18 -0
  23. package/src/css/app-shell/catalog-theme.css +20 -2
  24. package/src/css/app-shell/chat-polish.css +12 -0
  25. package/src/css/app-shell/collab.css +5 -0
  26. package/src/css/app-shell/data-density.css +4 -0
  27. package/src/css/app-shell/files.css +7 -1
  28. package/src/css/app-shell/hero-content.css +14 -1
  29. package/src/css/app-shell/kits-appended.css +13 -0
  30. package/src/css/app-shell/loading-alerts.css +14 -12
  31. package/src/css/app-shell/otp-input.css +2 -2
  32. package/src/css/app-shell/panel-row.css +15 -0
  33. package/src/css/app-shell/plugins-config.css +3 -0
  34. package/src/css/app-shell/primitives.css +13 -4
  35. package/src/css/app-shell/responsive.css +13 -0
  36. package/src/css/app-shell/responsive2-workspace.css +4 -1
  37. package/src/css/app-shell/row-print.css +34 -0
  38. package/src/css/app-shell/states-interactions.css +62 -4
  39. package/src/css/app-shell/topbar.css +1 -0
  40. package/src/kits/os/app-panes.css +3 -2
  41. package/src/kits/os/icons.js +16 -0
  42. package/src/kits/os/shell-geometry.js +2 -2
  43. package/src/kits/os/shell.js +24 -3
  44. package/src/kits/os/theme.css +272 -78
  45. package/src/kits/os/wm.css +19 -6
  46. package/src/kits/os/wm.js +38 -1
  47. package/src/kits/spoint/host-join-lobby.css +3 -3
  48. package/src/page-html/client-script.js +96 -28
  49. package/src/page-html.js +3 -2
  50. package/src/theme.js +6 -2
  51. package/src/web-components/ds-chat.js +9 -0
  52. package/src/web-components/freddie-chat.js +2 -2
  53. package/types/components.d.ts +6 -0
@@ -37,9 +37,58 @@
37
37
  --os-bar-h-mobile: 52px;
38
38
  --os-rail-w: 64px;
39
39
  --os-tap: 44px;
40
+ /* Unified menubar control height: every clickable control in the top bar
41
+ (home/apps buttons, workspace tabs, tray icon buttons) sits on this one
42
+ height so the bar reads as a single control language instead of a mix
43
+ of pill buttons, chips, and icon buttons each sized on their own. */
44
+ --os-control-h: 28px;
40
45
  --os-font: var(--ff-ui);
41
46
  --os-display: var(--ff-display);
42
47
  --os-mono: var(--ff-mono);
48
+
49
+ /* ---- Unified spacing scale (--space-1..6) ----
50
+ colors_and_type.css already defines --space-1 (4px) through --space-6
51
+ (48px), plus finer hair/half/fractional rungs (--space-hair/half/0/1-5/
52
+ 1-75/2-5/2-75/3-5), all loaded before this sheet for every .ds-247420
53
+ consumer. That IS the unified spacing scale this contract asks for — no
54
+ redeclaration here (a self-referencing `--space-1: var(--space-1)` would
55
+ be circular and resolve to invalid at computed-value time). New call
56
+ sites and the migrations below consolidate onto --space-1..6 directly. */
57
+
58
+ /* ---- Unified type scale (title / body / meta) ----
59
+ Maps onto the canonical --fs-* rail (colors_and_type.css) rather than
60
+ inventing new pixel values: title = display-weight heading size already
61
+ used by .os-drawer-title/.chat-empty-title (--fs-xl); body = the base
62
+ readable size already used by .chat-bubble/.app-pane (--fs-xs); meta =
63
+ the small secondary/timestamp size already used by .chat-meta/.os-clock
64
+ (--fs-nano). */
65
+ --font-size-title: var(--fs-xl);
66
+ --font-size-body: var(--fs-xs);
67
+ --font-size-meta: var(--fs-nano);
68
+
69
+ /* ---- Unified corner-radius scale (sm / md / lg / pill) ----
70
+ Aliases of the canonical --r-* rail (colors_and_type.css: --r-0 4px,
71
+ --r-1 8px, --r-2 10px, --r-3 14px, --r-pill 999px) under the names this
72
+ token contract specifies, so windows/buttons/badges can standardize on
73
+ one vocabulary instead of picking --r-0 vs --r-1 vs --r-2 ad hoc. */
74
+ --radius-sm: var(--r-1);
75
+ --radius-md: var(--r-2);
76
+ --radius-lg: var(--r-3);
77
+ --radius-pill: var(--r-pill, 999px);
78
+
79
+ /* ---- Unified color / accent system ----
80
+ --accent-primary is the brand lead (#247420 in the thebird preset via
81
+ --os-accent, which already resolves through --accent-ink); kept as its
82
+ own token (rather than a bare alias) so non-.ds-247420 consumers of this
83
+ kit get the literal brand green called for by this contract even before
84
+ any brand-scoped override applies. --color-success/warning/danger alias
85
+ the existing canonical severity primitives (--green-2/--sun/--warn) so
86
+ severity language is consistent with what --success/--warn already mean
87
+ everywhere else in colors_and_type.css — not a second competing set. */
88
+ --accent-primary: #247420;
89
+ --color-success: var(--success, var(--green-2, #3A9A34));
90
+ --color-warning: var(--sun, #F5C344);
91
+ --color-danger: var(--warn, #C41C0C);
43
92
  }
44
93
 
45
94
  html, body {
@@ -50,6 +99,20 @@ html, body {
50
99
  text-rendering: optimizeLegibility;
51
100
  }
52
101
 
102
+ /* ---- Global focus-visible ring ----
103
+ Baseline accent-colored outline for every keyboard-focusable element
104
+ (inputs/textareas/buttons/links/contenteditable, including the terminal's
105
+ and chat composer's text entry) so focus is never invisible. Component-
106
+ level :focus-visible rules elsewhere in this sheet (chat composer textarea,
107
+ composer-btn, chat-empty-suggestion, fsb-row, ...) already set a matching
108
+ var(--os-accent) ring with layout-specific offset/inset and win by source
109
+ order + specificity; this is the catch-all every other focusable surface
110
+ falls back to. */
111
+ .ds-247420 :focus-visible {
112
+ outline: 2px solid var(--os-accent);
113
+ outline-offset: 2px;
114
+ }
115
+
53
116
  .os-menubar, .os-taskbar {
54
117
  background: color-mix(in oklab, var(--os-bg-2) 88%, transparent);
55
118
  backdrop-filter: blur(10px);
@@ -58,6 +121,8 @@ html, body {
58
121
  color: var(--os-fg);
59
122
  font: var(--fs-tiny) var(--os-font);
60
123
  height: var(--os-bar-h);
124
+ /* prefers-reduced-transparency handled below (near bottom of this file):
125
+ drops the blur + backing translucency to a solid --os-bg-2 fill. */
61
126
  padding: 0 var(--space-2-75);
62
127
  gap: var(--space-1-75);
63
128
  box-shadow: none;
@@ -87,25 +152,35 @@ html, body {
87
152
  gap: var(--space-2);
88
153
  text-transform: lowercase;
89
154
  }
155
+ /* Wordmark lockup: the mark echoes favicon.svg (rounded-square tile, accent
156
+ fill, monogram) instead of a bare accent dot, so the brand reads as an
157
+ actual logo mark next to the "thebird" text rather than plain type with a
158
+ decorative dot. Inlined as a data-URI (same technique renderFaviconTags
159
+ already uses for the <link rel="icon"> glyph case) since theme.css ships
160
+ standalone via unpkg with no guaranteed relative path to favicon.svg. */
90
161
  .os-brand::before {
91
162
  content: '';
92
163
  display: inline-block;
93
- width: 8px; height: 8px;
94
- border-radius: 50%;
95
- background: var(--os-accent);
164
+ width: 16px; height: 16px;
165
+ border-radius: var(--r-1, 4px);
166
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='6' fill='%23247420'/%3E%3Ctext x='16' y='22' font-family='ui-monospace,monospace' font-size='14' font-weight='700' fill='%23EFE9DD' text-anchor='middle'%3E24%3C/text%3E%3C/svg%3E");
167
+ background-size: contain;
168
+ background-repeat: no-repeat;
169
+ flex: 0 0 auto;
96
170
  }
97
171
 
98
172
  .os-btn {
99
173
  background: transparent;
100
174
  color: var(--os-fg-2);
101
- border: none;
102
- padding: 7px 14px;
175
+ border: 1px solid transparent;
176
+ height: var(--os-control-h);
177
+ padding: 0 14px;
103
178
  cursor: pointer;
104
179
  font: inherit;
105
180
  font-family: var(--os-font);
106
181
  font-size: var(--fs-tiny);
107
- border-radius: var(--r-pill, 999px);
108
- transition: background 80ms ease, color 80ms ease;
182
+ border-radius: var(--radius-pill, var(--r-pill, 999px));
183
+ transition: background 80ms ease, color 80ms ease, border-color 80ms ease;
109
184
  display: inline-flex;
110
185
  align-items: center;
111
186
  gap: var(--space-1-75);
@@ -122,9 +197,16 @@ html, body {
122
197
  position: absolute;
123
198
  background: var(--os-bg-1);
124
199
  border: none;
125
- border-radius: var(--r-3, 18px);
200
+ border-radius: var(--radius-lg, var(--r-3, 18px));
126
201
  padding: var(--space-2, 8px);
127
202
  min-width: 220px;
203
+ /* Uncapped, the menu grows to its widest label and — at the common
204
+ * tablet-range window widths (~810-1150px) where content columns are
205
+ * already narrow — reads as covering most of the open content instead
206
+ * of a dropdown. Cap to a comfortable reading width but never past
207
+ * the viewport (same "must not extend past the viewport" contract the
208
+ * height clamp below already applies). */
209
+ max-width: min(320px, calc(100vw - var(--space-4, 16px)));
128
210
  top: calc(var(--os-bar-h) + var(--space-1, 4px));
129
211
  left: var(--space-2, 8px);
130
212
  z-index: var(--z-dropdown);
@@ -137,12 +219,40 @@ html, body {
137
219
  max-height: calc(100dvh - var(--os-bar-h) - env(safe-area-inset-top, 0px) - 16px);
138
220
  overflow-y: auto;
139
221
  overscroll-behavior: contain;
222
+ /* Scroll-shadow affordance: dual-background trick -- the fade gradients
223
+ * are pinned to the scrollport (background-attachment: local) so they
224
+ * only appear once there is actually more content to reveal in that
225
+ * direction, cueing that the menu is scrollable rather than just
226
+ * clipped at the viewport edge. */
227
+ background-image:
228
+ linear-gradient(var(--os-bg-1), var(--os-bg-1)),
229
+ linear-gradient(var(--os-bg-1), var(--os-bg-1)),
230
+ linear-gradient(to bottom, color-mix(in oklab, var(--os-bg-1) 100%, transparent), transparent),
231
+ linear-gradient(to top, color-mix(in oklab, var(--os-bg-1) 100%, transparent), transparent);
232
+ background-position: top, bottom, top, bottom;
233
+ background-repeat: no-repeat;
234
+ background-size: 100% var(--space-2, 8px), 100% var(--space-2, 8px), 100% var(--space-4, 16px), 100% var(--space-4, 16px);
235
+ background-attachment: local, local, scroll, scroll;
140
236
  }
141
237
  .os-menu.open { display: flex; }
238
+ /* Dimming scrim behind the open apps menu — same var(--scrim) fixed-inset
239
+ * pattern as .tb-sess-overlay, but as a pseudo-element (not a sibling DOM
240
+ * node) since buildAppsMenu() in shell-chrome.js emits only the menu itself.
241
+ * pointer-events:none so existing click-outside-to-close handling (thebird
242
+ * JS) keeps working unmodified; the scrim sits one layer below the menu's
243
+ * own z-index but still above .wm-root's windows. */
244
+ .os-menu.open::before {
245
+ content: '';
246
+ position: fixed;
247
+ inset: 0;
248
+ z-index: var(--z-below);
249
+ background: var(--scrim);
250
+ pointer-events: none;
251
+ }
142
252
  .os-menu .os-btn {
143
253
  width: 100%;
144
254
  text-align: left;
145
- border-radius: var(--os-radius-sm);
255
+ border-radius: var(--radius-sm, var(--os-radius-sm));
146
256
  padding: var(--space-2) var(--space-2-5);
147
257
  color: var(--os-fg);
148
258
  justify-content: flex-start;
@@ -164,16 +274,19 @@ html, body {
164
274
  .os-clock {
165
275
  color: var(--os-fg-2);
166
276
  font-variant-numeric: tabular-nums;
167
- font-family: var(--os-mono);
277
+ font-family: var(--os-font);
168
278
  padding: 0 var(--space-2-5);
169
279
  font-size: var(--fs-micro);
170
280
  }
171
281
 
172
282
  .os-task {
283
+ display: inline-flex;
284
+ align-items: center;
285
+ gap: var(--space-1-5, 6px);
173
286
  border: none;
174
287
  background: var(--os-bg-1);
175
288
  color: var(--os-fg-2);
176
- border-radius: var(--r-pill, 999px);
289
+ border-radius: var(--radius-pill, var(--r-pill, 999px));
177
290
  padding: var(--space-1-75) 14px;
178
291
  font-size: var(--fs-micro);
179
292
  font-family: var(--os-font);
@@ -184,20 +297,23 @@ html, body {
184
297
  white-space: nowrap;
185
298
  overflow: hidden;
186
299
  text-overflow: ellipsis;
187
- /* No text-transform here: .os-task carries the app/window's own dynamic
188
- * title (shell.js refreshTaskbar -> t.textContent = w.title), and a
189
- * user- or app-supplied string (filename, acronym, URL) must render
190
- * as-authored rather than get silently lowercased by brand-voice CSS. */
300
+ /* No text-transform here: .os-task-label carries the app/window's own
301
+ * dynamic title (shell.js refreshTaskbar), and a user- or app-supplied
302
+ * string (filename, acronym, URL) must render as-authored rather than
303
+ * get silently lowercased by brand-voice CSS. */
191
304
  }
192
305
  .os-task { min-height: 28px; }
193
306
  .os-task:hover { background: var(--panel-hover, var(--os-bg-2)); color: var(--os-fg); }
307
+ .os-task .ic { flex: none; display: inline-flex; width: 14px; height: 14px; }
308
+ .os-task .ic svg { width: 100%; height: 100%; fill: none; stroke: currentColor; }
309
+ .os-task-label { overflow: hidden; text-overflow: ellipsis; }
194
310
  /* Empty taskbar reads as an intentional strip, not a stray blurred bar. */
195
311
  .os-task-empty { font-size: var(--fs-nano); color: var(--os-fg-3); padding: 0 var(--space-2-5); font-family: var(--os-font); }
196
312
  .os-task.focused {
197
- background: var(--panel-select, var(--os-accent-soft));
313
+ background: var(--panel-select, color-mix(in oklab, var(--os-accent) 30%, var(--os-bg-1)));
198
314
  color: var(--os-fg);
199
- font-weight: 600;
200
- box-shadow: inset 4px 0 0 var(--os-accent);
315
+ font-weight: 700;
316
+ box-shadow: inset 4px 0 0 var(--os-accent), inset 0 0 0 1px color-mix(in oklab, var(--os-accent) 40%, transparent);
201
317
  }
202
318
 
203
319
  /* Window-chrome overrides of wm.css.
@@ -210,14 +326,14 @@ html, body {
210
326
  * job by force. Do not un-scope these; the scope IS the override mechanism. */
211
327
  .ds-247420 .wm-win {
212
328
  background: var(--os-bg-1);
213
- border: none;
214
- border-radius: var(--r-3);
215
- box-shadow: none;
329
+ border: 1px solid color-mix(in oklab, var(--os-fg) 14%, transparent);
330
+ border-radius: var(--radius-lg, var(--r-3));
331
+ box-shadow: var(--shadow-2);
216
332
  overflow: hidden;
217
333
  }
218
334
  .ds-247420 .wm-win.wm-focused {
219
- border: none;
220
- box-shadow: inset var(--space-1) 0 0 var(--os-accent);
335
+ border-color: color-mix(in oklab, var(--os-fg) 28%, transparent);
336
+ box-shadow: inset var(--space-1) 0 0 var(--os-accent), var(--shadow-3);
221
337
  }
222
338
 
223
339
  .ds-247420 .wm-bar {
@@ -225,6 +341,14 @@ html, body {
225
341
  border: none;
226
342
  padding: var(--space-2) var(--space-2-75);
227
343
  gap: var(--space-2-5);
344
+ transition: background 120ms ease;
345
+ }
346
+ /* Focused vs. unfocused titlebar differentiation: stacked windows otherwise
347
+ * share one flat gray bar and blur together. The focused window's bar picks
348
+ * up the accent-tinted panel shade and full-strength title text; unfocused
349
+ * bars stay on the plain background with dimmed title opacity. */
350
+ .ds-247420 .wm-win.wm-focused .wm-bar {
351
+ background: color-mix(in oklab, var(--os-accent) 10%, var(--os-bg-2));
228
352
  }
229
353
  .ds-247420 .wm-title {
230
354
  font: var(--fs-tiny) var(--os-font);
@@ -232,15 +356,21 @@ html, body {
232
356
  letter-spacing: 0.005em;
233
357
  text-align: center;
234
358
  font-weight: 600;
359
+ opacity: 0.65;
360
+ transition: opacity 120ms ease;
235
361
  /* No text-transform here: the titlebar renders the window's own dynamic
236
362
  * title (renderWindow({title}) / setTitle(t) in wm.js) — a user- or
237
363
  * app-supplied filename/acronym/URL must not be silently lowercased. */
238
364
  }
239
- .ds-247420 .wm-btns { gap: var(--space-1-75); order: -1; }
365
+ .ds-247420 .wm-win.wm-focused .wm-title {
366
+ color: var(--os-fg);
367
+ opacity: 1;
368
+ }
369
+ .ds-247420 .wm-btns { display: flex; align-items: center; gap: var(--space-1-75); order: -1; }
240
370
  .ds-247420 .wm-btn {
241
- width: 22px;
242
- height: 22px;
243
- border-radius: var(--r-1);
371
+ width: 26px;
372
+ height: 26px;
373
+ border-radius: var(--radius-sm, var(--r-1));
244
374
  border: none;
245
375
  background: var(--os-bg-3);
246
376
  color: var(--os-fg-2);
@@ -254,11 +384,20 @@ html, body {
254
384
  transition: background 100ms ease, color 100ms ease;
255
385
  }
256
386
  .ds-247420 .wm-btn:hover { background: var(--panel-hover, var(--os-bg-2)); color: var(--os-fg); }
257
- .ds-247420 .wm-btn svg { width: 12px; height: 12px; display: block; fill: none; stroke: currentColor; }
387
+ .ds-247420 .wm-btn svg { width: 13px; height: 13px; display: block; fill: none; stroke: currentColor; }
388
+ /* Hover-only color differentiation on the close button (independent of the
389
+ * armed/confirm state below) so it reads as the destructive action at a
390
+ * glance, matching the base wm.css rule. */
391
+ .ds-247420 .wm-btn[title='close']:hover,
392
+ .ds-247420 .wm-btn[aria-label='close']:hover {
393
+ background: var(--color-danger);
394
+ color: var(--paper);
395
+ }
258
396
  /* Armed (first-click) confirm state for the window close button's
259
397
  * second-click-to-confirm idiom — an unrecoverable close gets a visible cue
260
398
  * before it commits, matching the launcher dock's instance-close treatment. */
261
- .ds-247420 .wm-btn.confirm { background: var(--os-red); color: var(--paper); }
399
+ .ds-247420 .wm-btn.confirm { background: var(--color-danger); color: var(--paper); }
400
+ .ds-247420 .wm-btn.confirm:hover { background: color-mix(in oklab, var(--color-danger) 85%, black); }
262
401
 
263
402
  .ds-247420 .wm-resize {
264
403
  background: transparent;
@@ -336,7 +475,7 @@ html, body {
336
475
  box-sizing: border-box;
337
476
  background: var(--os-bg-2);
338
477
  }
339
- .os-drawer-title { color: var(--os-fg); font-family: var(--os-display); font-size: var(--fs-xl); font-weight: 700; letter-spacing: -0.01em; text-transform: lowercase; }
478
+ .os-drawer-title { color: var(--os-fg); font-family: var(--os-display); font-size: var(--font-size-title, var(--fs-xl)); font-weight: 700; letter-spacing: -0.01em; text-transform: lowercase; }
340
479
  .os-drawer-close {
341
480
  width: 44px; height: 44px;
342
481
  border: none; background: transparent;
@@ -372,7 +511,7 @@ html, body {
372
511
  cursor: pointer;
373
512
  transition: background 80ms ease;
374
513
  outline: none;
375
- border-radius: var(--r-3, 18px);
514
+ border-radius: var(--radius-lg, var(--r-3, 18px));
376
515
  text-transform: lowercase;
377
516
  }
378
517
  .os-drawer-tile:hover { background: var(--panel-hover, var(--os-bg-2)); }
@@ -385,7 +524,7 @@ html, body {
385
524
  .os-tray { display: flex; align-items: center; gap: var(--space-1-75); }
386
525
  .os-instances { display: flex; gap: var(--space-1); margin-left: var(--space-2); flex: 0 1 40vw; max-width: 40vw; overflow-x: auto; overflow-y: hidden; scrollbar-width: thin; padding: 0 var(--space-1); -webkit-mask-image: linear-gradient(to right, transparent, black 12px, black calc(100% - 12px), transparent); mask-image: linear-gradient(to right, transparent, black 12px, black calc(100% - 12px), transparent); }
387
526
  .os-instances::-webkit-scrollbar { height: 4px; }
388
- .os-instances .os-btn { flex: 0 0 auto; min-width: 36px; padding: var(--space-hair) var(--space-2); font-family: var(--os-mono); font-size: var(--fs-nano); }
527
+ .os-instances .os-btn { flex: 0 0 auto; min-width: 36px; height: var(--os-control-h); padding: 0 var(--space-2); font-family: var(--os-mono); font-size: var(--fs-nano); }
389
528
  .os-instances .os-btn.active { background: var(--panel-select, var(--os-accent-soft)); color: var(--os-fg); border-color: var(--panel-accent, var(--os-accent)); box-shadow: inset 0 0 0 1px var(--panel-accent, var(--os-accent)); }
390
529
  .os-menubar [data-role="home"] { display: none; }
391
530
  .os-root { position: fixed; inset: 0; display: flex; flex-direction: column; pointer-events: none; z-index: calc(var(--z-dock) + 2); }
@@ -414,12 +553,13 @@ html, body {
414
553
  .app-pane.mono .head { color: var(--os-accent); margin-bottom: var(--space-2); padding-bottom: var(--space-2); font-weight: 600; letter-spacing: 0.02em; border-bottom: 1px solid var(--os-bg-3); }
415
554
  /* Visible fetch-error surface for polling app panes (files/monitor): a swallowed
416
555
  * rejection must not leave the pane silently frozen with no user-facing signal. */
417
- .app-pane.mono .row-error { color: var(--danger, #c0392b); padding: var(--space-2); }
418
- .app-pane.mono[data-component="monitor-app"].is-error { color: var(--danger, #c0392b); }
556
+ .app-pane.mono .row-error { color: var(--color-danger); padding: var(--space-2); }
557
+ .app-pane.mono[data-component="monitor-app"].is-error { color: var(--color-danger); }
419
558
  /* Placeholder body shown immediately for a window spawned by an async app
420
559
  * factory, swapped for the real content on resolve — see openApp() in
421
560
  * shell.js. Prevents a slow factory from reading as a dead click. */
422
- .os-app-loading { display: flex; align-items: center; justify-content: center; color: var(--os-fg-3); font-style: italic; }
561
+ .os-app-loading { display: flex; align-items: center; justify-content: center; gap: var(--space-2, 8px); color: var(--os-fg-3); }
562
+ .os-app-loading-label { font-style: italic; }
423
563
  .app-pane.mono pre { background: var(--os-bg-2); padding: var(--space-2-5) var(--space-2-75); margin: var(--space-2) 0 0 0; max-height: 220px; overflow: auto; white-space: pre-wrap; font: var(--fs-nano) var(--os-mono); border-radius: var(--r-1, 6px); color: var(--os-fg); border: none; }
424
564
  .app-shell-pane { margin: 0; padding: var(--space-2); font: var(--fs-micro) var(--os-mono); color: var(--os-fg); background: var(--os-bg-0); height: 100%; overflow: auto; white-space: pre-wrap; box-sizing: border-box; }
425
565
  .app-canvas { width: 100%; height: 100%; background: var(--os-bg-0); display: block; cursor: default; }
@@ -444,7 +584,13 @@ html, body {
444
584
  .os-menubar { padding-left: calc(var(--os-rail-w) + env(safe-area-inset-left, 0px) + var(--space-2, 8px)); }
445
585
  .os-taskbar { padding-left: calc(var(--os-rail-w) + env(safe-area-inset-left, 0px) + var(--space-2, 8px)); }
446
586
  .os-menubar .os-instances { display: flex; }
447
- .os-menu { left: calc(var(--os-rail-w) + env(safe-area-inset-left, 0px) + var(--space-2, 8px)); }
587
+ .os-menu {
588
+ left: calc(var(--os-rail-w) + env(safe-area-inset-left, 0px) + var(--space-2, 8px));
589
+ /* The base rule's max-width doesn't know about the rail's left offset;
590
+ * re-derive it here so the menu still can't overflow the viewport's
591
+ * right edge on tablet-band windows (~810-1150px is the tightest). */
592
+ max-width: min(320px, calc(100vw - var(--os-rail-w) - env(safe-area-inset-left, 0px) - var(--space-4, 16px)));
593
+ }
448
594
  }
449
595
 
450
596
  @media (max-width: 767px) {
@@ -478,7 +624,7 @@ html, body {
478
624
  scroll-snap-align: start;
479
625
  font-size: var(--fs-tiny);
480
626
  }
481
- .os-task.focused { background: var(--panel-select, var(--os-accent-soft)); box-shadow: inset var(--space-1) 0 0 var(--os-accent); }
627
+ .os-task.focused { background: var(--panel-select, color-mix(in oklab, var(--os-accent) 30%, var(--os-bg-1))); font-weight: 700; box-shadow: inset var(--space-1) 0 0 var(--os-accent), inset 0 0 0 1px color-mix(in oklab, var(--os-accent) 40%, transparent); }
482
628
  .os-side-rail { display: none; }
483
629
  .os-menu { left: var(--space-2); right: var(--space-2); min-width: 0; top: calc(var(--os-bar-h) + env(safe-area-inset-top, 0) + var(--space-1)); }
484
630
  .ds-247420 .wm-root {
@@ -720,8 +866,8 @@ html.ds-247420 { touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-t
720
866
 
721
867
  .ds-247420 .tb-sess-chip {
722
868
  display: inline-flex; align-items: center; gap: var(--space-1-75);
723
- height: 22px; padding: 0 var(--space-1-75) 0 var(--space-2);
724
- border-radius: var(--r-pill, 999px);
869
+ height: var(--os-control-h); padding: 0 var(--space-1-75) 0 var(--space-2);
870
+ border-radius: var(--radius-pill, var(--r-pill, 999px));
725
871
  background: color-mix(in oklab, var(--fg) 6%, transparent);
726
872
  color: var(--fg);
727
873
  font-family: var(--ff-ui); font-size: var(--fs-nano); font-weight: 500;
@@ -742,7 +888,7 @@ html.ds-247420 { touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-t
742
888
  .ds-247420 .tb-sess-badge {
743
889
  display: inline-flex; align-items: center; justify-content: center;
744
890
  min-width: 16px; height: 14px; padding: 0 var(--space-1);
745
- border-radius: var(--r-0);
891
+ border-radius: var(--radius-sm, var(--r-0));
746
892
  background: color-mix(in oklab, var(--fg) 14%, transparent);
747
893
  font-size: var(--fs-pico); font-weight: 600; line-height: 1;
748
894
  }
@@ -755,14 +901,14 @@ html.ds-247420 { touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-t
755
901
  opacity: 0.55; transition: opacity 120ms ease, background 120ms ease;
756
902
  }
757
903
  .ds-247420 .tb-sess-chip:hover .tb-sess-x { opacity: 1; }
758
- .ds-247420 .tb-sess-x:hover { background: color-mix(in oklab, var(--danger) 30%, transparent); color: var(--on-color); }
904
+ .ds-247420 .tb-sess-x:hover { background: color-mix(in oklab, var(--color-danger) 30%, transparent); color: var(--on-color); }
759
905
 
760
906
  .ds-247420 .tb-sess-add {
761
907
  display: inline-flex; align-items: center; gap: var(--space-1);
762
- height: 22px; padding: 0 var(--space-2-5);
908
+ height: var(--os-control-h); padding: 0 var(--space-2-5);
763
909
  border: 1px dashed color-mix(in oklab, var(--fg) 30%, transparent);
764
910
  background: transparent;
765
- border-radius: var(--r-pill, 999px);
911
+ border-radius: var(--radius-pill, var(--r-pill, 999px));
766
912
  font-family: var(--ff-ui); font-size: var(--fs-nano); font-weight: 500;
767
913
  color: var(--fg);
768
914
  cursor: pointer;
@@ -786,7 +932,7 @@ html.ds-247420 { touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-t
786
932
  .tb-sess-modal {
787
933
  background: var(--bg);
788
934
  color: var(--fg);
789
- border-radius: var(--r-1);
935
+ border-radius: var(--radius-sm, var(--r-1));
790
936
  box-shadow: var(--shadow-overlay);
791
937
  min-width: 320px; max-width: 480px;
792
938
  border: 1px solid color-mix(in oklab, var(--fg) 12%, transparent);
@@ -802,7 +948,7 @@ html.ds-247420 { touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-t
802
948
  width: 100%; box-sizing: border-box;
803
949
  height: 32px; padding: 0 var(--space-2-5);
804
950
  border: 1px solid color-mix(in oklab, var(--fg) 20%, transparent);
805
- border-radius: var(--r-0);
951
+ border-radius: var(--radius-sm, var(--r-0));
806
952
  background: color-mix(in oklab, var(--fg) 6%, var(--bg));
807
953
  color: inherit;
808
954
  font-family: inherit; font-size: var(--fs-tiny);
@@ -813,16 +959,16 @@ html.ds-247420 { touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-t
813
959
  .tb-sess-modal-foot { display: flex; justify-content: flex-end; gap: var(--space-2); padding: var(--space-2-75) var(--space-3); border-top: 1px solid color-mix(in oklab, var(--fg) 8%, transparent); }
814
960
  .tb-sess-modal-btn {
815
961
  height: 28px; padding: 0 14px;
816
- border-radius: var(--r-0); border: 1px solid color-mix(in oklab, var(--fg) 20%, transparent);
962
+ border-radius: var(--radius-sm, var(--r-0)); border: 1px solid color-mix(in oklab, var(--fg) 20%, transparent);
817
963
  background: transparent; color: inherit;
818
964
  font-family: inherit; font-size: var(--fs-micro); font-weight: 500; cursor: pointer;
819
965
  transition: background 120ms ease, border-color 120ms ease;
820
966
  }
821
967
  .tb-sess-modal-btn:hover { background: color-mix(in oklab, var(--fg) 6%, transparent); }
822
- .tb-sess-modal-btn.primary { background: var(--os-accent); color: var(--on-color); border-color: var(--os-accent); }
823
- .tb-sess-modal-btn.primary:hover { background: color-mix(in oklab, var(--os-accent) 80%, var(--ink)); }
824
- .tb-sess-modal-btn.danger { background: var(--danger); color: var(--on-color); border-color: var(--danger); }
825
- .tb-sess-modal-btn.danger:hover { background: color-mix(in oklab, var(--danger) 80%, var(--ink)); }
968
+ .tb-sess-modal-btn.primary { background: var(--accent-primary, var(--os-accent)); color: var(--on-color); border-color: var(--accent-primary, var(--os-accent)); }
969
+ .tb-sess-modal-btn.primary:hover { background: color-mix(in oklab, var(--accent-primary, var(--os-accent)) 80%, var(--ink)); }
970
+ .tb-sess-modal-btn.danger { background: var(--color-danger); color: var(--on-color); border-color: var(--color-danger); }
971
+ .tb-sess-modal-btn.danger:hover { background: color-mix(in oklab, var(--color-danger) 80%, var(--ink)); }
826
972
 
827
973
  .tb-sess-empty {
828
974
  position: fixed; inset: 0; z-index: var(--z-window);
@@ -835,7 +981,7 @@ html.ds-247420 { touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-t
835
981
  background: var(--bg);
836
982
  color: var(--fg);
837
983
  border: 1px solid color-mix(in oklab, var(--fg) 14%, transparent);
838
- border-radius: var(--r-2);
984
+ border-radius: var(--radius-md, var(--r-2));
839
985
  box-shadow: var(--shadow-3);
840
986
  padding: var(--space-5) 40px; text-align: center;
841
987
  font-family: var(--ff-ui);
@@ -845,8 +991,8 @@ html.ds-247420 { touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-t
845
991
  .tb-sess-empty-sub { font-size: var(--fs-tiny); opacity: 0.7; margin-bottom: var(--space-3-5); }
846
992
  .tb-sess-empty-cta {
847
993
  height: 40px; padding: 0 var(--space-4);
848
- background: var(--os-accent); color: var(--on-color);
849
- border: 0; border-radius: var(--r-pill, 999px);
994
+ background: var(--accent-primary, var(--os-accent)); color: var(--on-color);
995
+ border: 0; border-radius: var(--radius-pill, var(--r-pill, 999px));
850
996
  font-family: inherit; font-size: var(--fs-xs); font-weight: 600;
851
997
  cursor: pointer;
852
998
  transition: transform 120ms ease, box-shadow 120ms ease;
@@ -859,25 +1005,25 @@ html.ds-247420 { touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-t
859
1005
  .ds-247420 .tb-sessions-title { font-weight: 600; font-size: var(--fs-xs); }
860
1006
  .ds-247420 .tb-sessions-count { font-size: var(--fs-micro); opacity: 0.6; margin-left: var(--space-1); }
861
1007
  .ds-247420 .tb-sessions-spacer { flex: 1; }
862
- .ds-247420 .tb-sessions-btn { height: 28px; padding: 0 var(--space-2-75); border-radius: var(--r-0); border: 1px solid color-mix(in oklab, var(--fg) 20%, transparent); background: transparent; color: inherit; font-size: var(--fs-micro); font-weight: 500; cursor: pointer; font-family: inherit; }
1008
+ .ds-247420 .tb-sessions-btn { height: 28px; padding: 0 var(--space-2-75); border-radius: var(--radius-sm, var(--r-0)); border: 1px solid color-mix(in oklab, var(--fg) 20%, transparent); background: transparent; color: inherit; font-size: var(--fs-micro); font-weight: 500; cursor: pointer; font-family: inherit; }
863
1009
  .ds-247420 .tb-sessions-btn:hover { background: color-mix(in oklab, var(--fg) 6%, transparent); }
864
- .ds-247420 .tb-sessions-btn.primary { background: var(--os-accent); color: var(--on-color); border-color: var(--os-accent); }
865
- .ds-247420 .tb-sessions-btn.danger { background: var(--danger); color: var(--on-color); border-color: var(--danger); }
1010
+ .ds-247420 .tb-sessions-btn.primary { background: var(--accent-primary, var(--os-accent)); color: var(--on-color); border-color: var(--accent-primary, var(--os-accent)); }
1011
+ .ds-247420 .tb-sessions-btn.danger { background: var(--color-danger); color: var(--on-color); border-color: var(--color-danger); }
866
1012
  .ds-247420 .tb-sessions-btn:disabled { opacity: 0.4; cursor: not-allowed; }
867
1013
  .ds-247420 .tb-sessions-grid { flex: 1; overflow: auto; padding: 14px; display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: var(--space-2-75); align-content: start; }
868
- .ds-247420 .tb-sessions-card { padding: var(--space-2-75); border-radius: var(--r-1, 10px); border: 1px solid color-mix(in oklab, var(--fg) 12%, transparent); background: color-mix(in oklab, var(--fg) 3%, transparent); display: flex; flex-direction: column; gap: var(--space-2); transition: border-color 120ms ease, transform 120ms ease; }
1014
+ .ds-247420 .tb-sessions-card { padding: var(--space-2-75); border-radius: var(--radius-sm, var(--r-1, 10px)); border: 1px solid color-mix(in oklab, var(--fg) 12%, transparent); background: color-mix(in oklab, var(--fg) 3%, transparent); display: flex; flex-direction: column; gap: var(--space-2); transition: border-color 120ms ease, transform 120ms ease; }
869
1015
  .ds-247420 .tb-sessions-card:hover { border-color: var(--os-accent); }
870
1016
  .ds-247420 .tb-sessions-card.active { border-color: var(--os-accent); box-shadow: 0 0 0 2px color-mix(in oklab, var(--os-accent) 30%, transparent); }
871
1017
  .ds-247420 .tb-sessions-card-head { display: flex; align-items: center; gap: var(--space-2); }
872
1018
  .ds-247420 .tb-sessions-card-check { width: 14px; height: 14px; cursor: pointer; flex: 0 0 14px; }
873
- .ds-247420 .tb-sessions-card-name { font-weight: 600; font-size: var(--fs-tiny); flex: 1; outline: none; padding: var(--space-hair) var(--space-1); border-radius: var(--r-0); }
1019
+ .ds-247420 .tb-sessions-card-name { font-weight: 600; font-size: var(--fs-tiny); flex: 1; outline: none; padding: var(--space-hair) var(--space-1); border-radius: var(--radius-sm, var(--r-0)); }
874
1020
  .ds-247420 .tb-sessions-card-name[contenteditable="true"] { background: color-mix(in oklab, var(--fg) 8%, transparent); }
875
1021
  .ds-247420 .tb-sessions-card-id { font-family: var(--os-mono, monospace); font-size: var(--fs-pico); opacity: 0.5; }
876
1022
  .ds-247420 .tb-sessions-card-stats { font-size: var(--fs-nano); opacity: 0.7; display: flex; gap: var(--space-2-75); }
877
1023
  .ds-247420 .tb-sessions-card-actions { display: flex; gap: var(--space-1-75); margin-top: var(--space-1); }
878
- .ds-247420 .tb-sessions-card-actions button { flex: 1; height: 24px; font-size: var(--fs-nano); padding: 0 var(--space-2); border-radius: var(--r-0); border: 1px solid color-mix(in oklab, var(--fg) 16%, transparent); background: transparent; color: inherit; cursor: pointer; font-family: inherit; }
1024
+ .ds-247420 .tb-sessions-card-actions button { flex: 1; height: 24px; font-size: var(--fs-nano); padding: 0 var(--space-2); border-radius: var(--radius-sm, var(--r-0)); border: 1px solid color-mix(in oklab, var(--fg) 16%, transparent); background: transparent; color: inherit; cursor: pointer; font-family: inherit; }
879
1025
  .ds-247420 .tb-sessions-card-actions button:hover { background: color-mix(in oklab, var(--fg) 6%, transparent); }
880
- .ds-247420 .tb-sessions-card-actions button.danger:hover { background: var(--danger); color: var(--on-color); border-color: var(--danger); }
1026
+ .ds-247420 .tb-sessions-card-actions button.danger:hover { background: var(--color-danger); color: var(--on-color); border-color: var(--color-danger); }
881
1027
  .ds-247420 .tb-sessions-empty-mid { padding: 40px; text-align: center; opacity: 0.6; font-size: var(--fs-tiny); }
882
1028
 
883
1029
  /* ---- prefers-contrast: more — strengthen borders + focus so the translucent
@@ -922,9 +1068,9 @@ html.ds-247420 { touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-t
922
1068
  .ds-247420 .freddie-chat-wrap { position: absolute; inset: 0; display: flex; flex-direction: column; min-height: 0; }
923
1069
  .ds-247420 .freddie-chat-wrap > freddie-chat { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; overflow: hidden; }
924
1070
  .ds-247420 .cc-strip { flex: 0 0 auto; font-size: var(--fs-micro); border-bottom: 1px solid color-mix(in oklab, var(--fg) 16%, transparent); }
925
- .ds-247420 .cc-toggle { all: unset; cursor: pointer; display: inline-flex; align-items: center; gap: .4em; padding: .35em .7em; color: var(--fg, inherit); opacity: .75; }
926
- .ds-247420 .cc-toggle:hover { opacity: 1; }
927
- .ds-247420 .cc-toggle.cc-open { opacity: 1; font-weight: 600; }
1071
+ .ds-247420 .cc-toggle { all: unset; cursor: pointer; display: inline-flex; align-items: center; gap: .4em; padding: .35em .7em; color: var(--fg, inherit); opacity: .75; border: 1px solid transparent; border-radius: var(--r-1, 8px); }
1072
+ .ds-247420 .cc-toggle:hover { opacity: 1; background: var(--panel-hover, var(--os-bg-2)); border-color: color-mix(in oklab, var(--fg) 18%, transparent); color: var(--os-fg, inherit); }
1073
+ .ds-247420 .cc-toggle.cc-open { opacity: 1; font-weight: 600; background: var(--panel-hover, var(--os-bg-2)); border-color: color-mix(in oklab, var(--fg) 18%, transparent); }
928
1074
  .ds-247420 .cc-body { padding: .5em .7em .7em; display: flex; flex-direction: column; gap: .5em; max-height: 42vh; max-height: 42dvh; overflow: auto; }
929
1075
  .ds-247420 .cc-body[hidden] { display: none; }
930
1076
  .ds-247420 .cc-row { display: flex; gap: .6em; flex-wrap: wrap; }
@@ -1027,13 +1173,13 @@ html.ds-247420 { touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-t
1027
1173
  /* Tool-call card — collapsible details with status icon + name + label. */
1028
1174
  .ds-247420 .chat-tool { display: block; background: var(--panel-1, color-mix(in oklab, var(--fg) 4%, transparent)); border: 1px solid color-mix(in oklab, var(--fg) 14%, transparent); border-radius: var(--r-0); padding: 0; max-width: min(640px, 92%); overflow: hidden; font-size: var(--fs-micro); }
1029
1175
  .ds-247420 .chat-tool[open] { background: var(--panel-1, color-mix(in oklab, var(--fg) 6%, transparent)); }
1030
- .ds-247420 .chat-tool.tool-error { border-color: color-mix(in oklab, var(--danger, #c0392b) 60%, transparent); }
1031
- .ds-247420 .chat-tool.tool-done { border-color: color-mix(in oklab, var(--os-accent, #247420) 35%, transparent); }
1176
+ .ds-247420 .chat-tool.tool-error { border-color: color-mix(in oklab, var(--color-danger) 60%, transparent); }
1177
+ .ds-247420 .chat-tool.tool-done { border-color: color-mix(in oklab, var(--color-success) 35%, transparent); }
1032
1178
  .ds-247420 .chat-tool-head { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-1-75) var(--space-2-5); cursor: pointer; list-style: none; user-select: none; }
1033
1179
  .ds-247420 .chat-tool-head::-webkit-details-marker { display: none; }
1034
1180
  .ds-247420 .chat-tool-icon { display: inline-flex; width: 14px; height: 14px; align-items: center; justify-content: center; font-family: var(--os-mono, monospace); font-size: var(--fs-micro); opacity: 0.7; }
1035
- .ds-247420 .chat-tool.tool-error .chat-tool-icon { color: var(--danger, #c0392b); opacity: 1; }
1036
- .ds-247420 .chat-tool.tool-done .chat-tool-icon { color: var(--os-accent, #247420); opacity: 1; }
1181
+ .ds-247420 .chat-tool.tool-error .chat-tool-icon { color: var(--color-danger); opacity: 1; }
1182
+ .ds-247420 .chat-tool.tool-done .chat-tool-icon { color: var(--color-success); opacity: 1; }
1037
1183
  .ds-247420 .chat-tool.tool-running .chat-tool-icon { animation: chat-spin 1.4s linear infinite; }
1038
1184
  @keyframes chat-spin { to { transform: rotate(360deg); } }
1039
1185
  .ds-247420 .chat-tool-name { font-family: var(--os-mono, monospace); font-weight: 600; font-size: var(--fs-micro); }
@@ -1043,7 +1189,7 @@ html.ds-247420 { touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-t
1043
1189
  .ds-247420 .chat-tool-section { display: flex; flex-direction: column; gap: var(--space-half); }
1044
1190
  .ds-247420 .chat-tool-section-label { font-size: var(--fs-pico); opacity: 0.5; text-transform: lowercase; letter-spacing: 0.05em; }
1045
1191
  .ds-247420 .chat-tool-pre { margin: 0; padding: var(--space-1-75) var(--space-2); background: color-mix(in oklab, var(--fg) 4%, transparent); border-radius: var(--r-0); max-height: 200px; overflow: auto; font: var(--fs-nano)/1.45 var(--os-mono, ui-monospace, monospace); white-space: pre-wrap; word-break: break-word; }
1046
- .ds-247420 .chat-tool-pre.is-error { color: var(--danger, #c0392b); }
1192
+ .ds-247420 .chat-tool-pre.is-error { color: var(--color-danger); }
1047
1193
 
1048
1194
  /* Thinking indicator — typing dots + label, transient (assistant-side). */
1049
1195
  .ds-247420 .chat-thinking { display: inline-flex; align-items: center; gap: var(--space-2); background: transparent; border: 0; padding: var(--space-1) var(--space-2); opacity: 0.7; font-size: var(--fs-micro); }
@@ -1064,8 +1210,8 @@ html.ds-247420 { touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-t
1064
1210
  .ds-247420 .chat-empty-suggestion:focus-visible { outline: 2px solid var(--os-accent, #247420); outline-offset: 2px; }
1065
1211
 
1066
1212
  /* Cancel-while-generating button replaces send. */
1067
- .ds-247420 .chat-composer .send.cancel { background: var(--danger); color: var(--on-color); }
1068
- .ds-247420 .chat-composer .send.cancel:hover { background: color-mix(in oklab, var(--danger, #c0392b) 80%, black); }
1213
+ .ds-247420 .chat-composer .send.cancel { background: var(--color-danger); color: var(--on-color); }
1214
+ .ds-247420 .chat-composer .send.cancel:hover { background: color-mix(in oklab, var(--color-danger) 80%, black); }
1069
1215
 
1070
1216
  /* ============================================================================
1071
1217
  * Jank pass 2 (2026-05-30) — outer-layer scroll containment + iframe gesture
@@ -1093,10 +1239,53 @@ html.ds-247420 { touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-t
1093
1239
 
1094
1240
  /* Subtle backdrop blur behind modal overlays — depth cue without compounding
1095
1241
  * paint cost since the blur layer is GPU-composited. Respect reduced-motion
1096
- * by falling back to plain dim. */
1097
- .ds-247420 .tb-sess-overlay { backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); }
1242
+ * by falling back to plain dim. Shared with the overlay-primitives backdrops
1243
+ * below (.ov-cmd-backdrop / .ov-lightbox-backdrop / .ov-auth-backdrop) so
1244
+ * every full-viewport modal in the kit reads as one consistent "on top of
1245
+ * dimmed content" language instead of some floating over undimmed chrome. */
1246
+ .ds-247420 .tb-sess-overlay,
1247
+ .ds-247420 .ov-cmd-backdrop,
1248
+ .ds-247420 .ov-lightbox-backdrop,
1249
+ .ds-247420 .ov-auth-backdrop { backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); }
1098
1250
  @media (prefers-reduced-motion: reduce) {
1099
- .ds-247420 .tb-sess-overlay { backdrop-filter: none; -webkit-backdrop-filter: none; }
1251
+ .ds-247420 .tb-sess-overlay,
1252
+ .ds-247420 .ov-cmd-backdrop,
1253
+ .ds-247420 .ov-lightbox-backdrop,
1254
+ .ds-247420 .ov-auth-backdrop { backdrop-filter: none; -webkit-backdrop-filter: none; }
1255
+ }
1256
+
1257
+ /* Shared full-viewport dimming scrim for the overlay-primitives components
1258
+ * (CommandPalette, VideoLightbox, AuthModal) — these three ship a *-backdrop
1259
+ * root element (command-palette.js / full-screen.js / auth-modal.js) but had
1260
+ * zero CSS anywhere in the kit, so they rendered undimmed, competing with
1261
+ * whatever page content sat behind them instead of reading as on-top. Same
1262
+ * position:fixed/inset:0/var(--z-modal)/var(--scrim) shape as .tb-sess-overlay
1263
+ * above — one scrim implementation, not three near-duplicates. */
1264
+ .ov-cmd-backdrop,
1265
+ .ov-lightbox-backdrop,
1266
+ .ov-auth-backdrop {
1267
+ position: fixed; inset: 0; z-index: var(--z-modal);
1268
+ background: var(--scrim);
1269
+ display: flex; align-items: center; justify-content: center;
1270
+ }
1271
+
1272
+ /* -----------------------------------------------------------------------
1273
+ prefers-reduced-transparency — distinct from prefers-reduced-motion
1274
+ above: a user can want full animation but zero see-through/blur panel
1275
+ chrome (vestibular-motion sensitivity vs. low-vision/legibility need are
1276
+ different accessibility needs, so this is its own media query, not folded
1277
+ into the motion one). Every backdrop-blur/translucent-panel effect in this
1278
+ kit drops to a solid, fully-opaque backing fill — the blur adds nothing
1279
+ once nothing shows through it, so it is dropped alongside the alpha for
1280
+ one less GPU compositing pass, not just left as dead blur-on-opaque.
1281
+ ----------------------------------------------------------------------- */
1282
+ @media (prefers-reduced-transparency: reduce) {
1283
+ .os-menubar, .os-taskbar {
1284
+ background: var(--os-bg-2);
1285
+ backdrop-filter: none;
1286
+ -webkit-backdrop-filter: none;
1287
+ }
1288
+ .ds-247420 .tb-sess-overlay { background: var(--scrim-strong); backdrop-filter: none; -webkit-backdrop-filter: none; }
1100
1289
  }
1101
1290
 
1102
1291
  /* -----------------------------------------------------------------------
@@ -1250,12 +1439,17 @@ html.ds-247420 { touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-t
1250
1439
  }
1251
1440
 
1252
1441
  .ds-247420 .chat-bubble {
1253
- background: var(--panel-1, color-mix(in oklab, var(--fg) 5%, transparent));
1442
+ /* --panel-1 aliases the same --bg-2 the window body already sits on
1443
+ (.wm-body uses --os-bg-1 = --bg-2), so an incoming bubble on --panel-1
1444
+ read as near-invisible against its own window. --panel-2 (--bg-3) is
1445
+ the next real step up the existing panel scale — visible separation,
1446
+ no new token. */
1447
+ background: var(--panel-2, color-mix(in oklab, var(--fg) 10%, transparent));
1254
1448
  color: var(--fg);
1255
1449
  border: 1px solid color-mix(in oklab, var(--fg) 8%, transparent);
1256
- border-radius: var(--r-1);
1450
+ border-radius: var(--radius-sm, var(--r-1));
1257
1451
  padding: var(--space-2) var(--space-2-75);
1258
- font-size: var(--fs-xs);
1452
+ font-size: var(--font-size-body, var(--fs-xs));
1259
1453
  line-height: 1.5;
1260
1454
  max-width: min(720px, 86%);
1261
1455
  overflow-wrap: anywhere;
@@ -1296,8 +1490,8 @@ html.ds-247420 { touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-t
1296
1490
  }
1297
1491
 
1298
1492
  .ds-247420 .chat-meta {
1299
- font-size: var(--fs-nano);
1300
- opacity: 0.55;
1493
+ font-size: var(--font-size-meta, var(--fs-nano));
1494
+ color: var(--fg-3);
1301
1495
  display: inline-flex;
1302
1496
  align-items: center;
1303
1497
  gap: var(--space-1-75);