@jaychang1989/dsh-webchat 0.3.0 → 0.4.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 (44) hide show
  1. package/NOTICE +10 -3
  2. package/README.md +44 -40
  3. package/README.zh.md +43 -44
  4. package/cordis.patch.yml +8 -7
  5. package/lib/client.js +402 -1693
  6. package/lib/index.js +246 -3884
  7. package/package.json +3 -35
  8. package/lib/client.js.map +0 -1
  9. package/lib/types/client/api.d.ts +0 -74
  10. package/lib/types/client/controller.d.ts +0 -19
  11. package/lib/types/client/index.d.ts +0 -30
  12. package/lib/types/client/locales.d.ts +0 -169
  13. package/lib/types/client/mount.d.ts +0 -23
  14. package/lib/types/client/panel/Markdown.d.ts +0 -15
  15. package/lib/types/client/panel/WebChatPanel.d.ts +0 -28
  16. package/lib/types/client/sidebar-entry-core.d.ts +0 -60
  17. package/lib/types/client/sidebar-entry.d.ts +0 -22
  18. package/lib/types/engine/engine.d.ts +0 -247
  19. package/lib/types/engine/html-md.d.ts +0 -23
  20. package/lib/types/index.d.ts +0 -63
  21. package/lib/types/protocol.d.ts +0 -107
  22. package/lib/types/routes.d.ts +0 -22
  23. package/lib/types/store.d.ts +0 -69
  24. package/lib/types/tools.d.ts +0 -27
  25. package/lib/types/transfer.d.ts +0 -138
  26. package/src/client/api.ts +0 -90
  27. package/src/client/controller.ts +0 -43
  28. package/src/client/css-modules.d.ts +0 -5
  29. package/src/client/index.ts +0 -75
  30. package/src/client/locales.ts +0 -172
  31. package/src/client/mount.tsx +0 -125
  32. package/src/client/panel/Markdown.tsx +0 -251
  33. package/src/client/panel/WebChatPanel.tsx +0 -760
  34. package/src/client/panel/panel.module.css +0 -936
  35. package/src/client/sidebar-entry-core.ts +0 -207
  36. package/src/client/sidebar-entry.ts +0 -49
  37. package/src/engine/engine.ts +0 -1385
  38. package/src/engine/html-md.ts +0 -126
  39. package/src/index.ts +0 -212
  40. package/src/protocol.ts +0 -116
  41. package/src/routes.ts +0 -307
  42. package/src/store.ts +0 -217
  43. package/src/tools.ts +0 -257
  44. package/src/transfer.ts +0 -602
@@ -1,936 +0,0 @@
1
- /**
2
- * dsh-webchat panel styles. Scoped by the plugin's own data attributes so
3
- * nothing leaks into the rest of the GUI; colors ride the dsh --dsw-* tokens
4
- * so the panel follows the active theme (light/dark and skins). The
5
- * center-column hide rules are attribute-scoped and must stay in this
6
- * stylesheet (it is imported by mount.tsx, so the styles load with the
7
- * plugin).
8
- *
9
- * Design language: the panel is a bridge between two modes of working — a
10
- * human conversation (proportional type, bubbles, calm) and a handoff into
11
- * executable harness context (monospace, hairlines, a labeled dock). The
12
- * monospace "utility" register is reserved for machine things (timestamps,
13
- * model names, counts, status, and the handoff eyebrow); chat copy stays in
14
- * the shell's proportional family. The handoff dock is the signature.
15
- */
16
-
17
- /* --- center-column takeover (global rules, attribute-scoped) ----------------- */
18
-
19
- [data-pane='conversation'],
20
- [class*='centerCol'] {
21
- position: relative;
22
- }
23
-
24
- [data-dsh-webchat-view] {
25
- position: absolute;
26
- inset: 0;
27
- display: none;
28
- z-index: 60;
29
- background: var(--dsw-alias-bg-base);
30
- }
31
-
32
- html[data-dsh-webchat-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-active]) [data-dsh-webchat-view] {
33
- display: block;
34
- }
35
-
36
- html[data-dsh-webchat-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-active]) [data-pane='conversation'] > :not([data-dsh-webchat-view]),
37
- html[data-dsh-webchat-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-active]) [class*='centerCol'] > :not([data-dsh-webchat-view]) {
38
- display: none !important;
39
- }
40
-
41
- /* --- sidebar entry row ------------------------------------------------------- */
42
-
43
- .entry {
44
- display: flex;
45
- align-items: center;
46
- gap: 8px;
47
- width: 100%;
48
- height: 32px;
49
- padding: 0 12px;
50
- background: transparent;
51
- border: none;
52
- border-radius: 8px;
53
- color: var(--dsw-alias-label-secondary);
54
- cursor: pointer;
55
- font-size: 13px;
56
- white-space: nowrap;
57
- }
58
-
59
- .entry:hover {
60
- background: var(--dsw-specific-sidebar-nav-item-hover);
61
- color: var(--dsw-alias-label-primary);
62
- }
63
-
64
- .entry[data-active] {
65
- background: var(--dsw-specific-sidebar-nav-item-active);
66
- color: var(--dsw-alias-label-primary);
67
- font-weight: 600;
68
- }
69
-
70
- .entryIcon {
71
- display: inline-flex;
72
- align-items: center;
73
- justify-content: center;
74
- flex: none;
75
- }
76
-
77
- .entryLabel {
78
- overflow: hidden;
79
- text-overflow: ellipsis;
80
- }
81
-
82
- [data-dsh-frame][data-sidebar-collapsed] .entry {
83
- justify-content: center;
84
- padding: 0;
85
- width: 100%;
86
- }
87
-
88
- [data-dsh-frame][data-sidebar-collapsed] .entryLabel {
89
- display: none;
90
- }
91
-
92
- /* --- panel frame -------------------------------------------------------------- */
93
-
94
- .view {
95
- overflow: hidden;
96
- box-sizing: border-box;
97
- }
98
-
99
- /* The shell does not apply a global border-box reset to divs, so the panel
100
- and every element inside it set it explicitly — otherwise height:100% plus
101
- padding overflows the center column and the composer is clipped. */
102
- .panel,
103
- .panel * {
104
- box-sizing: border-box;
105
- }
106
-
107
- .panel {
108
- display: flex;
109
- flex-direction: column;
110
- height: 100%;
111
- min-width: 0;
112
- min-height: 0;
113
- padding: 12px 14px 14px;
114
- gap: 8px;
115
- background: var(--dsw-alias-bg-base);
116
- color: var(--dsw-alias-label-primary);
117
- font-family: var(--dsw-font-family);
118
- }
119
-
120
- /* --- header (identity + live status) ----------------------------------------- */
121
-
122
- .panelHeader {
123
- display: flex;
124
- align-items: center;
125
- gap: 10px;
126
- flex: none;
127
- flex-wrap: wrap;
128
- }
129
-
130
- .panelTitle {
131
- margin: 0;
132
- font-size: 15px;
133
- font-weight: 700;
134
- letter-spacing: -0.01em;
135
- color: var(--dsw-alias-label-primary);
136
- white-space: nowrap;
137
- }
138
-
139
- .headerSpacer {
140
- flex: 1;
141
- min-width: 8px;
142
- }
143
-
144
- .statusChip {
145
- display: inline-flex;
146
- align-items: center;
147
- gap: 7px;
148
- flex: none;
149
- padding: 4px 10px;
150
- border: 1px solid var(--dsw-alias-border-l1);
151
- border-radius: 999px;
152
- background: var(--dsw-alias-bg-layer1, var(--dsw-alias-bg-elevated));
153
- font-size: 11.5px;
154
- color: var(--dsw-alias-label-secondary);
155
- }
156
-
157
- .statusText {
158
- min-width: 0;
159
- overflow: hidden;
160
- text-overflow: ellipsis;
161
- white-space: nowrap;
162
- font-family: var(--dsw-font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
163
- letter-spacing: 0.01em;
164
- }
165
-
166
- .statusDot {
167
- width: 7px;
168
- height: 7px;
169
- border-radius: 50%;
170
- flex: none;
171
- }
172
-
173
- .statusDot[data-state='ok'] {
174
- background: var(--dsw-alias-state-success, #22c55e);
175
- }
176
-
177
- .statusDot[data-state='warn'] {
178
- background: var(--dsw-alias-state-warning, #f59e0b);
179
- }
180
-
181
- .statusDot[data-state='bad'] {
182
- background: var(--dsw-alias-state-danger, #ef4444);
183
- }
184
-
185
- .statusDot[data-state='busy'] {
186
- background: var(--dsw-alias-state-info, #3b82f6);
187
- animation: dshWcPulse 1.2s ease-in-out infinite;
188
- }
189
-
190
- @keyframes dshWcPulse {
191
- 0%, 100% { opacity: 1; }
192
- 50% { opacity: 0.35; }
193
- }
194
-
195
- /* --- panel body (sidebar + main) ---------------------------------------------- */
196
-
197
- .panelBody {
198
- flex: 1;
199
- min-height: 0;
200
- display: flex;
201
- gap: 10px;
202
- }
203
-
204
- .sidebar {
205
- flex: 0 0 172px;
206
- min-width: 0;
207
- display: flex;
208
- flex-direction: column;
209
- gap: 6px;
210
- padding: 8px;
211
- border: 1px solid var(--dsw-alias-border-l1);
212
- border-radius: 10px;
213
- background: var(--dsw-alias-bg-layer1, var(--dsw-alias-bg-elevated));
214
- overflow: hidden;
215
- }
216
-
217
- .sidebarNew {
218
- width: 100%;
219
- justify-content: center;
220
- }
221
-
222
- .recoverList {
223
- max-height: 160px;
224
- overflow-y: auto;
225
- display: flex;
226
- flex-direction: column;
227
- gap: 2px;
228
- padding: 4px;
229
- border: 1px solid var(--dsw-alias-border-l2);
230
- border-radius: 8px;
231
- background: var(--dsw-alias-bg-layer1, var(--dsw-alias-bg-elevated));
232
- }
233
-
234
- .recoverItem {
235
- display: block;
236
- width: 100%;
237
- padding: 6px 8px;
238
- border: none;
239
- border-radius: 6px;
240
- background: transparent;
241
- color: var(--dsw-alias-label-primary);
242
- font: inherit;
243
- font-size: 12.5px;
244
- text-align: left;
245
- cursor: pointer;
246
- }
247
-
248
- .recoverItem:hover:not(:disabled) {
249
- background: var(--dsw-alias-interactive-bg-hover, rgba(128, 128, 128, 0.12));
250
- }
251
-
252
- .recoverItem:disabled {
253
- opacity: 0.5;
254
- cursor: default;
255
- }
256
-
257
- .recoverTitle {
258
- display: inline-block;
259
- max-width: 100%;
260
- overflow: hidden;
261
- text-overflow: ellipsis;
262
- white-space: nowrap;
263
- }
264
-
265
- .recoverEmpty {
266
- padding: 6px 8px;
267
- font-size: 12px;
268
- color: var(--dsw-alias-label-tertiary);
269
- }
270
-
271
- .sidebarList {
272
- flex: 1;
273
- min-height: 0;
274
- overflow-y: auto;
275
- display: flex;
276
- flex-direction: column;
277
- gap: 2px;
278
- }
279
-
280
- .sidebarItem {
281
- display: flex;
282
- align-items: center;
283
- gap: 2px;
284
- border-radius: 7px;
285
- }
286
-
287
- .sidebarItem:hover {
288
- background: var(--dsw-alias-interactive-bg-hover, rgba(128, 128, 128, 0.12));
289
- }
290
-
291
- .sidebarItem[data-active] {
292
- background: var(--dsw-specific-sidebar-nav-item-active, var(--dsw-alias-interactive-bg-hover));
293
- }
294
-
295
- .sidebarRow {
296
- flex: 1;
297
- min-width: 0;
298
- display: flex;
299
- flex-direction: column;
300
- align-items: flex-start;
301
- gap: 1px;
302
- padding: 6px 8px;
303
- background: transparent;
304
- border: none;
305
- border-radius: 7px;
306
- color: var(--dsw-alias-label-primary);
307
- cursor: pointer;
308
- text-align: left;
309
- }
310
-
311
- .sidebarTitle {
312
- display: block;
313
- width: 100%;
314
- overflow: hidden;
315
- text-overflow: ellipsis;
316
- white-space: nowrap;
317
- font-size: 12.5px;
318
- line-height: 1.3;
319
- }
320
-
321
- .sidebarMeta {
322
- font-family: var(--dsw-font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
323
- font-size: 10px;
324
- color: var(--dsw-alias-label-tertiary);
325
- }
326
-
327
- .sidebarActions {
328
- flex: none;
329
- display: flex;
330
- gap: 2px;
331
- padding-right: 4px;
332
- opacity: 0;
333
- transition: opacity 120ms ease;
334
- }
335
-
336
- .sidebarItem:hover .sidebarActions,
337
- .sidebarItem[data-active] .sidebarActions {
338
- opacity: 1;
339
- }
340
-
341
- .sidebarAction {
342
- display: inline-flex;
343
- align-items: center;
344
- justify-content: center;
345
- width: 22px;
346
- height: 22px;
347
- padding: 0;
348
- border: none;
349
- border-radius: 6px;
350
- background: transparent;
351
- color: var(--dsw-alias-label-secondary);
352
- cursor: pointer;
353
- }
354
-
355
- .sidebarAction:hover {
356
- background: var(--dsw-alias-interactive-bg-hover);
357
- color: var(--dsw-alias-label-primary);
358
- }
359
-
360
- .sidebarActionDanger {
361
- display: inline-flex;
362
- align-items: center;
363
- justify-content: center;
364
- height: 22px;
365
- padding: 0 6px;
366
- border: none;
367
- border-radius: 6px;
368
- background: var(--dsw-alias-state-danger, #ef4444);
369
- color: #fff;
370
- font-size: 11px;
371
- cursor: pointer;
372
- white-space: nowrap;
373
- }
374
-
375
- .sidebarRename {
376
- flex: 1;
377
- min-width: 0;
378
- display: flex;
379
- align-items: center;
380
- gap: 2px;
381
- padding: 2px;
382
- }
383
-
384
- .sidebarRenameInput {
385
- flex: 1;
386
- min-width: 0;
387
- padding: 4px 6px;
388
- font-size: 12px;
389
- color: var(--dsw-alias-label-primary);
390
- background: var(--dsw-specific-input-major, var(--dsw-alias-bg-layer1));
391
- border: 1px solid var(--dsw-alias-state-business-primary, #4f6bfa);
392
- border-radius: 6px;
393
- outline: none;
394
- }
395
-
396
- .sidebarEmpty {
397
- margin: auto;
398
- padding: 12px 8px;
399
- text-align: center;
400
- font-size: 12px;
401
- color: var(--dsw-alias-label-tertiary);
402
- }
403
-
404
- .sidebarClear {
405
- width: 100%;
406
- justify-content: center;
407
- }
408
-
409
- /* --- main chat column ----------------------------------------------------------- */
410
-
411
- .main {
412
- flex: 1;
413
- min-width: 0;
414
- min-height: 0;
415
- display: flex;
416
- flex-direction: column;
417
- overflow: hidden;
418
- gap: 8px;
419
- }
420
-
421
- /* --- composer toggles (深度思考 / 智能搜索) -------------------------------------- */
422
-
423
- .composerToolbar {
424
- display: flex;
425
- align-items: center;
426
- gap: 6px;
427
- flex: none;
428
- padding: 2px 12px 2px;
429
- }
430
-
431
- .toggleButton {
432
- appearance: none;
433
- display: inline-flex;
434
- align-items: center;
435
- gap: 5px;
436
- padding: 4px 11px;
437
- border: 1px solid var(--dsw-alias-border-l2);
438
- border-radius: 999px;
439
- background: transparent;
440
- color: var(--dsw-alias-label-secondary);
441
- font-family: var(--dsw-font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
442
- font-size: 11.5px;
443
- cursor: pointer;
444
- white-space: nowrap;
445
- transition: color 120ms ease, border-color 120ms ease, background 120ms ease;
446
- }
447
-
448
- .toggleButton:hover:not(:disabled) {
449
- color: var(--dsw-alias-label-primary);
450
- border-color: var(--dsw-alias-border-l1);
451
- }
452
-
453
- .toggleButton:disabled {
454
- opacity: 0.45;
455
- cursor: not-allowed;
456
- }
457
-
458
- .toggleButton[data-active] {
459
- color: var(--dsw-alias-state-business-primary, #4f6bfa);
460
- border-color: var(--dsw-alias-state-business-primary, #4f6bfa);
461
- background: var(--dsw-alias-interactive-bg-hover, rgba(128, 128, 128, 0.1));
462
- font-weight: 600;
463
- }
464
-
465
- /* --- segmented control (model + transfer mode) -------------------------------- */
466
-
467
- .segmented {
468
- display: inline-flex;
469
- align-items: stretch;
470
- flex: none;
471
- gap: 2px;
472
- padding: 2px;
473
- border: 1px solid var(--dsw-alias-border-l2);
474
- border-radius: 8px;
475
- background: var(--dsw-alias-bg-base);
476
- }
477
-
478
- .segmentedButton {
479
- appearance: none;
480
- border: none;
481
- background: transparent;
482
- padding: 4px 10px;
483
- border-radius: 6px;
484
- font-family: var(--dsw-font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
485
- font-size: 11.5px;
486
- color: var(--dsw-alias-label-secondary);
487
- cursor: pointer;
488
- white-space: nowrap;
489
- }
490
-
491
- .segmentedButton:hover:not([data-active]):not(:disabled) {
492
- color: var(--dsw-alias-label-primary);
493
- background: var(--dsw-alias-interactive-bg-hover);
494
- }
495
-
496
- .segmentedButton[data-active] {
497
- background: var(--dsw-alias-bg-elevated, var(--dsw-alias-bg-layer1));
498
- color: var(--dsw-alias-state-business-primary, #4f6bfa);
499
- font-weight: 600;
500
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12);
501
- }
502
-
503
- /* --- buttons ------------------------------------------------------------------ */
504
-
505
- .button {
506
- display: inline-flex;
507
- align-items: center;
508
- gap: 6px;
509
- padding: 6px 12px;
510
- font-size: 12.5px;
511
- border: 1px solid var(--dsw-alias-border-l2);
512
- border-radius: 8px;
513
- background: var(--dsw-specific-input-major, var(--dsw-alias-bg-layer1));
514
- color: var(--dsw-alias-label-primary);
515
- cursor: pointer;
516
- white-space: nowrap;
517
- transition: background 120ms ease, filter 120ms ease;
518
- }
519
-
520
- .button:hover:not(:disabled) {
521
- background: var(--dsw-alias-interactive-bg-hover);
522
- }
523
-
524
- .button:disabled {
525
- opacity: 0.45;
526
- cursor: not-allowed;
527
- }
528
-
529
- .buttonPrimary {
530
- border-color: transparent;
531
- background: var(--dsw-alias-state-business-primary, #4f6bfa);
532
- color: #fff;
533
- }
534
-
535
- .buttonPrimary:hover:not(:disabled) {
536
- filter: brightness(1.08);
537
- }
538
-
539
- .buttonDanger {
540
- border-color: transparent;
541
- background: var(--dsw-alias-state-danger, #ef4444);
542
- color: #fff;
543
- }
544
-
545
- .buttonGhost {
546
- border-color: transparent;
547
- background: transparent;
548
- color: var(--dsw-alias-label-secondary);
549
- font-size: 12px;
550
- padding: 5px 8px;
551
- }
552
-
553
- .buttonGhost:hover:not(:disabled) {
554
- color: var(--dsw-alias-label-primary);
555
- background: var(--dsw-alias-interactive-bg-hover);
556
- }
557
-
558
- /* --- chat area (message list) --------------------------------------------------- */
559
-
560
- .messageList {
561
- flex: 1;
562
- min-height: 0;
563
- overflow-y: auto;
564
- display: flex;
565
- flex-direction: column;
566
- gap: 14px;
567
- padding: 4px 2px;
568
- }
569
-
570
- .messageRow {
571
- display: flex;
572
- flex-direction: column;
573
- gap: 5px;
574
- max-width: 92%;
575
- }
576
-
577
- .messageRow[data-role='user'] {
578
- align-self: flex-end;
579
- align-items: flex-end;
580
- }
581
-
582
- .messageRow[data-role='assistant'] {
583
- align-self: flex-start;
584
- align-items: flex-start;
585
- }
586
-
587
- .messageMeta {
588
- display: flex;
589
- align-items: baseline;
590
- gap: 8px;
591
- padding: 0 4px;
592
- font-family: var(--dsw-font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
593
- font-size: 10.5px;
594
- line-height: 1;
595
- }
596
-
597
- .messageSpeaker {
598
- color: var(--dsw-alias-label-secondary);
599
- font-weight: 600;
600
- }
601
-
602
- .messageTime {
603
- color: var(--dsw-alias-label-tertiary);
604
- font-variant-numeric: tabular-nums;
605
- }
606
-
607
- .streamBadge {
608
- color: var(--dsw-alias-state-info, #3b82f6);
609
- }
610
-
611
- .messageBubble {
612
- padding: 10px 14px;
613
- border-radius: 12px;
614
- font-size: 13.5px;
615
- line-height: 1.6;
616
- overflow-wrap: anywhere;
617
- max-width: 100%;
618
- min-width: 0;
619
- }
620
-
621
- .messageRow[data-role='user'] .messageBubble {
622
- background: var(--dsw-alias-state-business-primary, #4f6bfa);
623
- color: #fff;
624
- border-bottom-right-radius: 4px;
625
- }
626
-
627
- .messageRow[data-role='assistant'] .messageBubble {
628
- background: var(--dsw-alias-bg-layer1, var(--dsw-alias-bg-elevated));
629
- border: 1px solid var(--dsw-alias-border-l1);
630
- border-bottom-left-radius: 4px;
631
- }
632
-
633
- .messageError {
634
- font-size: 11px;
635
- color: var(--dsw-alias-state-danger, #ef4444);
636
- }
637
-
638
- /* --- empty state (first-run hero) --------------------------------------------- */
639
-
640
- .emptyState {
641
- margin: auto;
642
- display: flex;
643
- flex-direction: column;
644
- align-items: center;
645
- gap: 10px;
646
- text-align: center;
647
- max-width: 420px;
648
- padding: 24px 20px;
649
- }
650
-
651
- .emptyEyebrow {
652
- font-family: var(--dsw-font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
653
- font-size: 10.5px;
654
- letter-spacing: 0.12em;
655
- text-transform: uppercase;
656
- color: var(--dsw-alias-state-business-primary, #4f6bfa);
657
- }
658
-
659
- .emptyTitle {
660
- margin: 0;
661
- font-size: 17px;
662
- font-weight: 700;
663
- letter-spacing: -0.01em;
664
- color: var(--dsw-alias-label-primary);
665
- }
666
-
667
- .emptyBody {
668
- margin: 0;
669
- font-size: 13px;
670
- line-height: 1.6;
671
- color: var(--dsw-alias-label-secondary);
672
- }
673
-
674
- /* --- composer ------------------------------------------------------------------ */
675
-
676
- .composer {
677
- display: flex;
678
- flex-direction: column;
679
- flex: none;
680
- border: 1px solid var(--dsw-alias-border-l2);
681
- border-radius: 12px;
682
- background: var(--dsw-specific-input-major, var(--dsw-alias-bg-layer1));
683
- transition: border-color 120ms ease;
684
- }
685
-
686
- .composer:focus-within {
687
- border-color: var(--dsw-alias-state-business-primary, #4f6bfa);
688
- }
689
-
690
- .composerInput {
691
- flex: 1;
692
- min-height: 44px;
693
- max-height: 180px;
694
- resize: none;
695
- border: none;
696
- outline: none;
697
- background: transparent;
698
- color: var(--dsw-alias-label-primary);
699
- font: inherit;
700
- font-size: 13.5px;
701
- line-height: 1.5;
702
- padding: 10px 12px 6px;
703
- }
704
-
705
- .composerInput::placeholder {
706
- color: var(--dsw-alias-label-tertiary);
707
- }
708
-
709
- .attachInput {
710
- margin: 0 12px 4px;
711
- padding: 7px 10px;
712
- border: 1px solid var(--dsw-alias-border-l2);
713
- border-radius: 8px;
714
- background: var(--dsw-alias-bg-layer1, var(--dsw-alias-bg-elevated));
715
- color: var(--dsw-alias-label-primary);
716
- font: inherit;
717
- font-size: 12.5px;
718
- }
719
-
720
- .attachInput::placeholder {
721
- color: var(--dsw-alias-label-tertiary);
722
- }
723
-
724
- .composerFooter {
725
- display: flex;
726
- align-items: center;
727
- gap: 8px;
728
- padding: 0 8px 8px 12px;
729
- }
730
-
731
- .composerHint {
732
- font-family: var(--dsw-font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
733
- font-size: 10.5px;
734
- color: var(--dsw-alias-label-tertiary);
735
- letter-spacing: 0.02em;
736
- }
737
-
738
- .composerSpacer {
739
- flex: 1;
740
- }
741
-
742
- /* --- handoff dock (signature) -------------------------------------------------- */
743
-
744
- .handoffDock {
745
- display: flex;
746
- align-items: center;
747
- gap: 10px;
748
- flex: none;
749
- flex-wrap: wrap;
750
- padding: 9px 12px;
751
- border: 1px solid var(--dsw-alias-border-l2);
752
- border-left: 2px solid var(--dsw-alias-state-business-primary, #4f6bfa);
753
- border-radius: 10px;
754
- background: var(--dsw-alias-bg-layer1, var(--dsw-alias-bg-elevated));
755
- }
756
-
757
- .handoffEyebrow {
758
- flex: none;
759
- font-family: var(--dsw-font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
760
- font-size: 10.5px;
761
- letter-spacing: 0.1em;
762
- text-transform: uppercase;
763
- color: var(--dsw-alias-label-tertiary);
764
- white-space: nowrap;
765
- }
766
-
767
- .handoffSpacer {
768
- flex: 1;
769
- min-width: 8px;
770
- }
771
-
772
- .workspaceSelect {
773
- flex: none;
774
- max-width: 280px;
775
- appearance: none;
776
- padding: 6px 10px;
777
- font-size: 12px;
778
- font-family: var(--dsw-font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
779
- color: var(--dsw-alias-label-primary);
780
- background: var(--dsw-specific-input-major, var(--dsw-alias-bg-layer1));
781
- border: 1px solid var(--dsw-alias-border-l2);
782
- border-radius: 8px;
783
- cursor: pointer;
784
- }
785
-
786
- .workspaceSelect:focus-visible {
787
- outline: 2px solid var(--dsw-alias-state-business-primary, #4f6bfa);
788
- outline-offset: 1px;
789
- }
790
-
791
- /* --- markdown ------------------------------------------------------------------- */
792
-
793
- .markdown {
794
- font-size: 13.5px;
795
- line-height: 1.65;
796
- }
797
-
798
- .markdown p {
799
- margin: 0.4em 0;
800
- }
801
-
802
- .markdown pre {
803
- position: relative;
804
- margin: 0.6em 0;
805
- padding: 10px 12px;
806
- border-radius: 8px;
807
- background: var(--dsw-alias-bg-deep, rgba(0, 0, 0, 0.45));
808
- overflow-x: auto;
809
- font-size: 12.5px;
810
- line-height: 1.5;
811
- }
812
-
813
- .markdown code {
814
- font-family: var(--dsw-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
815
- font-size: 0.92em;
816
- }
817
-
818
- .markdown :not(pre) > code {
819
- padding: 1px 5px;
820
- border-radius: 5px;
821
- background: var(--dsw-alias-interactive-bg-hover, rgba(128, 128, 128, 0.18));
822
- }
823
-
824
- .markdown h1, .markdown h2, .markdown h3, .markdown h4 {
825
- margin: 0.8em 0 0.4em;
826
- line-height: 1.3;
827
- }
828
-
829
- .markdown ul, .markdown ol {
830
- margin: 0.4em 0;
831
- padding-left: 1.4em;
832
- }
833
-
834
- .markdown blockquote {
835
- margin: 0.5em 0;
836
- padding: 2px 12px;
837
- border-left: 3px solid var(--dsw-alias-border-l2);
838
- color: var(--dsw-alias-label-secondary);
839
- }
840
-
841
- .tableWrap {
842
- overflow-x: auto;
843
- }
844
-
845
- .markdown table {
846
- border-collapse: collapse;
847
- margin: 0.6em 0;
848
- font-size: 12.5px;
849
- }
850
-
851
- .markdown th, .markdown td {
852
- border: 1px solid var(--dsw-alias-border-l2);
853
- padding: 4px 10px;
854
- }
855
-
856
- .markdown sup.citation {
857
- font-family: var(--dsw-font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
858
- font-size: 9.5px;
859
- font-weight: 600;
860
- line-height: 1.4;
861
- color: var(--dsw-alias-state-business-primary, #4f6bfa);
862
- background: var(--dsw-alias-interactive-bg-hover, rgba(128, 128, 128, 0.16));
863
- border-radius: 999px;
864
- padding: 0 4px;
865
- margin: 0 2px;
866
- vertical-align: super;
867
- white-space: nowrap;
868
- }
869
-
870
- .markdown a {
871
- color: var(--dsw-alias-state-business-primary, #4f6bfa);
872
- }
873
-
874
- .markdown details {
875
- margin: 0.5em 0;
876
- padding: 6px 10px;
877
- border-radius: 8px;
878
- background: var(--dsw-alias-interactive-bg-hover, rgba(128, 128, 128, 0.12));
879
- font-size: 12.5px;
880
- }
881
-
882
- .markdown summary {
883
- cursor: pointer;
884
- font-weight: 600;
885
- color: var(--dsw-alias-label-secondary);
886
- }
887
-
888
- /* --- toast ----------------------------------------------------------------------- */
889
-
890
- .toast {
891
- position: fixed;
892
- right: 20px;
893
- bottom: 20px;
894
- z-index: 200;
895
- max-width: 420px;
896
- padding: 10px 14px;
897
- border-radius: 10px;
898
- background: var(--dsw-alias-bg-elevated);
899
- border: 1px solid var(--dsw-alias-border-l2);
900
- box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
901
- font-size: 13px;
902
- color: var(--dsw-alias-label-primary);
903
- animation: dshWcToast 180ms ease-out;
904
- }
905
-
906
- @keyframes dshWcToast {
907
- from { transform: translateY(8px); opacity: 0; }
908
- to { transform: translateY(0); opacity: 1; }
909
- }
910
-
911
- /* --- accessibility --------------------------------------------------------------- */
912
-
913
- .button:focus-visible,
914
- .segmentedButton:focus-visible,
915
- .toggleButton:focus-visible,
916
- .sidebarRow:focus-visible,
917
- .sidebarAction:focus-visible,
918
- .sidebarActionDanger:focus-visible,
919
- .sidebarRenameInput:focus-visible,
920
- .composerInput:focus-visible {
921
- outline: 2px solid var(--dsw-alias-state-business-primary, #4f6bfa);
922
- outline-offset: 1px;
923
- }
924
-
925
- @media (prefers-reduced-motion: reduce) {
926
- .statusDot[data-state='busy'] {
927
- animation: none;
928
- }
929
- .toast {
930
- animation: none;
931
- }
932
- .button,
933
- .composer {
934
- transition: none;
935
- }
936
- }