@sunshaobei/dsh-session-manager 0.0.0-stage → 0.4.3-fork.1

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.
package/client.css ADDED
@@ -0,0 +1,1178 @@
1
+ /*
2
+ * dsh-session-recycle-bin — plugin stylesheet (client.css)
3
+ *
4
+ * Served by the host at GET /api/session-trash/client.css and injected by
5
+ * client.js as a <link rel="stylesheet">. All colors are CSS custom
6
+ * properties (design tokens) declared on :root; the dark palette applies
7
+ * under `body[data-ds-dark-theme]` (the resolved DSH appearance: light /
8
+ * dark / system, set by the host right after <body> opens) OR under
9
+ * `@media (prefers-color-scheme: dark)` (OS-level fallback), while an
10
+ * explicit light appearance restores the light palette via
11
+ * `body:not([data-ds-dark-theme])` — so inside DSH the app preference is
12
+ * authoritative, and the OS media query remains the fallback without it.
13
+ *
14
+ * Naming: components use the `dsh-trash-` prefix; markdown blocks are styled
15
+ * with element selectors scoped under `.dsh-trash-md`.
16
+ */
17
+
18
+ /* ------------------------------------------------------------------ */
19
+ /* Design tokens (light default; dark = app theme || OS fallback) */
20
+ /* ------------------------------------------------------------------ */
21
+
22
+ :root {
23
+ /* FONT STACKS ARE RESOLVED AT THE POINT OF USE, NOT HERE.
24
+ *
25
+ * These two tokens are the last-resort fallbacks for hosts that do not
26
+ * publish the shell's own font tokens (older DSH builds, the standalone
27
+ * test harness). They are deliberately CONCRETE stacks: a custom property
28
+ * whose value contains var() is substituted at computed-value time on the
29
+ * element that DECLARES it, and that computed value is what inherits. So
30
+ * :root { --dstrb-font: var(--dsw-font-family); }
31
+ * would freeze the :root-scoped stock stack and would NOT follow the
32
+ * body-level `--dsw-font-family` override that dsh-ui-font installs for the
33
+ * whole app — the plugin page would keep rendering in the default face.
34
+ * The effective font is therefore routed at the use sites (see the
35
+ * "Font routing" block below), where the inherited DSH tokens are visible.
36
+ */
37
+ --dstrb-font-fallback: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', 'Helvetica Neue', Arial, sans-serif;
38
+ --dstrb-mono-fallback: SFMono-Regular, Consolas, 'Liberation Mono', Menlo, monospace;
39
+
40
+ /* Text */
41
+ --dstrb-text-strong: #1a202c;
42
+ --dstrb-text: #2d3748;
43
+ --dstrb-text-secondary: #4a5568;
44
+ --dstrb-text-muted: #718096;
45
+ --dstrb-text-faint: #a0aec0;
46
+
47
+ /* Accents */
48
+ --dstrb-accent: #3182ce;
49
+ --dstrb-accent-veil: rgba(49, 130, 206, 0.15);
50
+ --dstrb-danger: #e53e3e;
51
+ --dstrb-danger-strong: #c53030;
52
+ --dstrb-danger-border: #feb2b2;
53
+ --dstrb-danger-veil: rgba(229, 62, 62, 0.08);
54
+ --dstrb-on-danger: #ffffff;
55
+
56
+ /* Surfaces */
57
+ --dstrb-surface: #ffffff; /* cards, modals, menus */
58
+ --dstrb-surface-subtle: #f7fafc; /* inputs, badges, checked rows */
59
+ --dstrb-surface-hover: #edf2f7; /* cancel button, user bubble base */
60
+
61
+ /* Borders */
62
+ --dstrb-border: #e2e8f0;
63
+ --dstrb-border-light: #edf2f7;
64
+ --dstrb-border-hairline: #f0f4f8;
65
+
66
+ /* Veils & overlays */
67
+ --dstrb-veil: rgba(0, 0, 0, 0.06);
68
+ --dstrb-overlay: rgba(0, 0, 0, 0.45);
69
+
70
+ /* Shadows */
71
+ --dstrb-shadow-card: 0 2px 8px rgba(0, 0, 0, 0.03);
72
+ --dstrb-shadow-menu: 0 4px 16px rgba(0, 0, 0, 0.12);
73
+ --dstrb-shadow-modal: 0 20px 40px rgba(0, 0, 0, 0.2);
74
+ --dstrb-shadow-modal-sm: 0 10px 25px rgba(0, 0, 0, 0.2);
75
+ --dstrb-shadow-tooltip: 0 8px 24px rgba(0, 0, 0, 0.2);
76
+ --dstrb-shadow-toast: 0 4px 12px rgba(0, 0, 0, 0.15);
77
+
78
+ /* Inverted tooltip */
79
+ --dstrb-tooltip-bg: #1a202c;
80
+ --dstrb-tooltip-text: #ffffff;
81
+ --dstrb-tooltip-muted: #a0aec0;
82
+
83
+ /* Toast (also inverted) */
84
+ --dstrb-toast-bg: #2d3748;
85
+ --dstrb-toast-text: #ffffff;
86
+ --dstrb-toast-btn-bg: #4a5568;
87
+ --dstrb-toast-btn-text: #63b3ed;
88
+
89
+ /* Markdown */
90
+ --dstrb-code-inline-bg: rgba(0, 0, 0, 0.07);
91
+ --dstrb-code-inline-text: #c53030;
92
+ --dstrb-quote-bg: rgba(0, 0, 0, 0.02);
93
+ --dstrb-quote-border: #cbd5e0;
94
+ --dstrb-bubble-user: #edf2f7;
95
+ /* Code blocks stay dark in both modes (editor-style) */
96
+ --dstrb-codeblock-bg: #1e293b;
97
+ --dstrb-codeblock-text: #e2e8f0;
98
+ --dstrb-codeblock-lang: #94a3b8;
99
+ }
100
+
101
+ @media (prefers-color-scheme: dark) {
102
+ :root {
103
+ --dstrb-text-strong: #edf2f7;
104
+ --dstrb-text: #e2e8f0;
105
+ --dstrb-text-secondary: #cbd5e0;
106
+ --dstrb-text-muted: #a0aec0;
107
+ --dstrb-text-faint: #718096;
108
+
109
+ --dstrb-accent: #63b3ed;
110
+ --dstrb-accent-veil: rgba(99, 179, 237, 0.2);
111
+ --dstrb-danger: #fc8181;
112
+ --dstrb-danger-strong: #feb2b2;
113
+ --dstrb-danger-border: #9b2c2c;
114
+ --dstrb-danger-veil: rgba(252, 129, 129, 0.12);
115
+ --dstrb-on-danger: #1a202c;
116
+
117
+ --dstrb-surface: #1f2530;
118
+ --dstrb-surface-subtle: #262e3d;
119
+ --dstrb-surface-hover: #2c3444;
120
+
121
+ --dstrb-border: #3a4356;
122
+ --dstrb-border-light: #333c4e;
123
+ --dstrb-border-hairline: #2c3444;
124
+
125
+ --dstrb-veil: rgba(255, 255, 255, 0.08);
126
+ --dstrb-overlay: rgba(0, 0, 0, 0.65);
127
+
128
+ --dstrb-shadow-card: 0 2px 8px rgba(0, 0, 0, 0.35);
129
+ --dstrb-shadow-menu: 0 4px 16px rgba(0, 0, 0, 0.5);
130
+ --dstrb-shadow-modal: 0 20px 40px rgba(0, 0, 0, 0.55);
131
+ --dstrb-shadow-modal-sm: 0 10px 25px rgba(0, 0, 0, 0.5);
132
+ --dstrb-shadow-tooltip: 0 8px 24px rgba(0, 0, 0, 0.55);
133
+ --dstrb-shadow-toast: 0 4px 12px rgba(0, 0, 0, 0.4);
134
+
135
+ --dstrb-tooltip-bg: #e2e8f0;
136
+ --dstrb-tooltip-text: #1a202c;
137
+ --dstrb-tooltip-muted: #4a5568;
138
+
139
+ --dstrb-toast-bg: #e2e8f0;
140
+ --dstrb-toast-text: #1a202c;
141
+ --dstrb-toast-btn-bg: #cbd5e0;
142
+ --dstrb-toast-btn-text: #1a202c;
143
+
144
+ --dstrb-code-inline-bg: rgba(255, 255, 255, 0.12);
145
+ --dstrb-code-inline-text: #fc8181;
146
+ --dstrb-quote-bg: rgba(255, 255, 255, 0.04);
147
+ --dstrb-quote-border: #4a5568;
148
+ --dstrb-bubble-user: #2c3444;
149
+ }
150
+ }
151
+
152
+ /* ------------------------------------------------------------------ */
153
+ /* DSH app theme — body[data-ds-dark-theme] */
154
+ /* ------------------------------------------------------------------ */
155
+ /* The host app resolves its appearance preference (light / dark / */
156
+ /* system) onto body[data-ds-dark-theme] as an inline script right */
157
+ /* after <body> opens. This block ORs with the OS media query above: */
158
+ /* either match resolves the dark palette. */
159
+ /* ------------------------------------------------------------------ */
160
+
161
+ body[data-ds-dark-theme] {
162
+ --dstrb-text-strong: #edf2f7;
163
+ --dstrb-text: #e2e8f0;
164
+ --dstrb-text-secondary: #cbd5e0;
165
+ --dstrb-text-muted: #a0aec0;
166
+ --dstrb-text-faint: #718096;
167
+
168
+ --dstrb-accent: #63b3ed;
169
+ --dstrb-accent-veil: rgba(99, 179, 237, 0.2);
170
+ --dstrb-danger: #fc8181;
171
+ --dstrb-danger-strong: #feb2b2;
172
+ --dstrb-danger-border: #9b2c2c;
173
+ --dstrb-danger-veil: rgba(252, 129, 129, 0.12);
174
+ --dstrb-on-danger: #1a202c;
175
+
176
+ --dstrb-surface: #1f2530;
177
+ --dstrb-surface-subtle: #262e3d;
178
+ --dstrb-surface-hover: #2c3444;
179
+
180
+ --dstrb-border: #3a4356;
181
+ --dstrb-border-light: #333c4e;
182
+ --dstrb-border-hairline: #2c3444;
183
+
184
+ --dstrb-veil: rgba(255, 255, 255, 0.08);
185
+ --dstrb-overlay: rgba(0, 0, 0, 0.65);
186
+
187
+ --dstrb-shadow-card: 0 2px 8px rgba(0, 0, 0, 0.35);
188
+ --dstrb-shadow-menu: 0 4px 16px rgba(0, 0, 0, 0.5);
189
+ --dstrb-shadow-modal: 0 20px 40px rgba(0, 0, 0, 0.55);
190
+ --dstrb-shadow-modal-sm: 0 10px 25px rgba(0, 0, 0, 0.5);
191
+ --dstrb-shadow-tooltip: 0 8px 24px rgba(0, 0, 0, 0.55);
192
+ --dstrb-shadow-toast: 0 4px 12px rgba(0, 0, 0, 0.4);
193
+
194
+ --dstrb-tooltip-bg: #e2e8f0;
195
+ --dstrb-tooltip-text: #1a202c;
196
+ --dstrb-tooltip-muted: #4a5568;
197
+
198
+ --dstrb-toast-bg: #e2e8f0;
199
+ --dstrb-toast-text: #1a202c;
200
+ --dstrb-toast-btn-bg: #cbd5e0;
201
+ --dstrb-toast-btn-text: #1a202c;
202
+
203
+ --dstrb-code-inline-bg: rgba(255, 255, 255, 0.12);
204
+ --dstrb-code-inline-text: #fc8181;
205
+ --dstrb-quote-bg: rgba(255, 255, 255, 0.04);
206
+ --dstrb-quote-border: #4a5568;
207
+ --dstrb-bubble-user: #2c3444;
208
+ }
209
+
210
+ /* An explicit light preference restores the light palette even under */
211
+ /* a dark OS, so the app preference stays authoritative inside DSH */
212
+ /* (fixes near-white titles on a light page). */
213
+
214
+ body:not([data-ds-dark-theme]) {
215
+ /* Fonts are NOT palette state: they are routed once, at the point of use,
216
+ in the "Font routing" block above — do not re-declare them here, or the
217
+ explicit-light branch would pin the plugin back to the stock stack. */
218
+
219
+ /* Text */
220
+ --dstrb-text-strong: #1a202c;
221
+ --dstrb-text: #2d3748;
222
+ --dstrb-text-secondary: #4a5568;
223
+ --dstrb-text-muted: #718096;
224
+ --dstrb-text-faint: #a0aec0;
225
+
226
+ /* Accents */
227
+ --dstrb-accent: #3182ce;
228
+ --dstrb-accent-veil: rgba(49, 130, 206, 0.15);
229
+ --dstrb-danger: #e53e3e;
230
+ --dstrb-danger-strong: #c53030;
231
+ --dstrb-danger-border: #feb2b2;
232
+ --dstrb-danger-veil: rgba(229, 62, 62, 0.08);
233
+ --dstrb-on-danger: #ffffff;
234
+
235
+ /* Surfaces */
236
+ --dstrb-surface: #ffffff; /* cards, modals, menus */
237
+ --dstrb-surface-subtle: #f7fafc; /* inputs, badges, checked rows */
238
+ --dstrb-surface-hover: #edf2f7; /* cancel button, user bubble base */
239
+
240
+ /* Borders */
241
+ --dstrb-border: #e2e8f0;
242
+ --dstrb-border-light: #edf2f7;
243
+ --dstrb-border-hairline: #f0f4f8;
244
+
245
+ /* Veils & overlays */
246
+ --dstrb-veil: rgba(0, 0, 0, 0.06);
247
+ --dstrb-overlay: rgba(0, 0, 0, 0.45);
248
+
249
+ /* Shadows */
250
+ --dstrb-shadow-card: 0 2px 8px rgba(0, 0, 0, 0.03);
251
+ --dstrb-shadow-menu: 0 4px 16px rgba(0, 0, 0, 0.12);
252
+ --dstrb-shadow-modal: 0 20px 40px rgba(0, 0, 0, 0.2);
253
+ --dstrb-shadow-modal-sm: 0 10px 25px rgba(0, 0, 0, 0.2);
254
+ --dstrb-shadow-tooltip: 0 8px 24px rgba(0, 0, 0, 0.2);
255
+ --dstrb-shadow-toast: 0 4px 12px rgba(0, 0, 0, 0.15);
256
+
257
+ /* Inverted tooltip */
258
+ --dstrb-tooltip-bg: #1a202c;
259
+ --dstrb-tooltip-text: #ffffff;
260
+ --dstrb-tooltip-muted: #a0aec0;
261
+
262
+ /* Toast (also inverted) */
263
+ --dstrb-toast-bg: #2d3748;
264
+ --dstrb-toast-text: #ffffff;
265
+ --dstrb-toast-btn-bg: #4a5568;
266
+ --dstrb-toast-btn-text: #63b3ed;
267
+
268
+ /* Markdown */
269
+ --dstrb-code-inline-bg: rgba(0, 0, 0, 0.07);
270
+ --dstrb-code-inline-text: #c53030;
271
+ --dstrb-quote-bg: rgba(0, 0, 0, 0.02);
272
+ --dstrb-quote-border: #cbd5e0;
273
+ --dstrb-bubble-user: #edf2f7;
274
+ /* Code blocks stay dark in both modes (editor-style) */
275
+ --dstrb-codeblock-bg: #1e293b;
276
+ --dstrb-codeblock-text: #e2e8f0;
277
+ --dstrb-codeblock-lang: #94a3b8;
278
+ }
279
+
280
+ /* ------------------------------------------------------------------ */
281
+ /* Font routing — follow the DSH shell, stay overridable */
282
+ /* ------------------------------------------------------------------ */
283
+ /*
284
+ * The shell paints `<body>` with `font-family: var(--dsw-font-family, …)`
285
+ * and dsh-ui-font swaps that token at the body level to apply the user's
286
+ * Settings → 字体 choice (and `--ds-font-family-code` for code faces)
287
+ * across the whole app. Referencing those host tokens HERE — on the plugin
288
+ * roots, where the inherited values are already in scope — is what makes
289
+ * the settings page and the portaled toast track the app font, live.
290
+ *
291
+ * --dstrb-font / --dstrb-mono remain available as optional override hooks:
292
+ * a theme may still declare either one higher up the tree and it wins,
293
+ * because the fallback chain is evaluated at the use site.
294
+ */
295
+ .dsh-trash-container,
296
+ .dsh-trash-toast {
297
+ font-family: var(--dstrb-font, var(--dsw-font-family, var(--dstrb-font-fallback)));
298
+ }
299
+
300
+ /* ------------------------------------------------------------------ */
301
+ /* Page container — width follows the window ratio (no fixed px cap) */
302
+ /* ------------------------------------------------------------------ */
303
+
304
+ .dsh-trash-container {
305
+ width: 90%;
306
+ padding: 24px;
307
+ margin: 0 auto;
308
+ color: var(--dstrb-text);
309
+ color-scheme: light dark; /* native select/checkbox follow the resolved mode */
310
+ }
311
+
312
+ /* App-theme-scoped overrides: native controls (select, checkbox,
313
+ scrollbars) follow the resolved plugin mode, matching the painted
314
+ surfaces even when the OS media query disagrees with the DSH
315
+ appearance preference. */
316
+ body[data-ds-dark-theme] .dsh-trash-container { color-scheme: dark; }
317
+ body:not([data-ds-dark-theme]) .dsh-trash-container { color-scheme: light; }
318
+
319
+ .dsh-trash-container,
320
+ .dsh-trash-container * {
321
+ box-sizing: border-box;
322
+ }
323
+
324
+ /* ------------------------------------------------------------------ */
325
+ /* Header */
326
+ /* ------------------------------------------------------------------ */
327
+
328
+ .dsh-trash-header {
329
+ display: flex;
330
+ justify-content: space-between;
331
+ align-items: center;
332
+ margin-bottom: 20px;
333
+ }
334
+
335
+ .dsh-trash-header-left {
336
+ display: flex;
337
+ flex-direction: column;
338
+ gap: 4px;
339
+ }
340
+
341
+ .dsh-trash-title {
342
+ margin: 0;
343
+ font-size: 20px;
344
+ font-weight: 600;
345
+ color: var(--dstrb-text-strong);
346
+ display: flex;
347
+ align-items: center;
348
+ }
349
+
350
+ .dsh-trash-subtitle {
351
+ margin: 0;
352
+ font-size: 13px;
353
+ color: var(--dstrb-text-muted);
354
+ }
355
+
356
+ /* Icons (size/margin/color moved out of JS inline styles) */
357
+ .dsh-trash-icon-title { width: 20px; height: 20px; margin-right: 8px; color: var(--dstrb-text-secondary); flex: none; }
358
+ .dsh-trash-icon-btn { width: 14px; height: 14px; margin-right: 6px; }
359
+ .dsh-trash-icon-menu { width: 13px; height: 13px; margin-right: 6px; }
360
+ .dsh-trash-icon-folder { width: 18px; height: 18px; color: var(--dstrb-text-muted); flex: none; }
361
+ .dsh-trash-icon-badge { width: 13px; height: 13px; margin-right: 4px; color: var(--dstrb-text-muted); }
362
+ .dsh-trash-icon-sm { width: 12px; height: 12px; margin-right: 3px; }
363
+
364
+ /* ------------------------------------------------------------------ */
365
+ /* Search bar */
366
+ /* ------------------------------------------------------------------ */
367
+
368
+ .dsh-trash-search {
369
+ position: relative;
370
+ margin-bottom: 12px;
371
+ width: 100%;
372
+ }
373
+
374
+ .dsh-trash-search-icon {
375
+ position: absolute;
376
+ top: 50%;
377
+ transform: translateY(-50%);
378
+ left: 14px;
379
+ color: var(--dstrb-text-faint);
380
+ pointer-events: none;
381
+ }
382
+
383
+ .dsh-trash-search-input {
384
+ width: 100%;
385
+ padding: 10px 14px 10px 40px;
386
+ border-radius: 24px;
387
+ border: 1px solid var(--dstrb-border);
388
+ background-color: var(--dstrb-surface-subtle);
389
+ font-size: 14px;
390
+ font-family: inherit;
391
+ color: var(--dstrb-text);
392
+ outline: none;
393
+ transition: all 0.15s ease;
394
+ }
395
+
396
+ .dsh-trash-search-input::placeholder {
397
+ color: var(--dstrb-text-faint);
398
+ }
399
+
400
+ .dsh-trash-search-input:focus {
401
+ border-color: var(--dstrb-accent);
402
+ box-shadow: 0 0 0 3px var(--dstrb-accent-veil);
403
+ background-color: var(--dstrb-surface);
404
+ }
405
+
406
+ /* ------------------------------------------------------------------ */
407
+ /* Filter toolbar */
408
+ /* ------------------------------------------------------------------ */
409
+
410
+ .dsh-trash-toolbar {
411
+ display: grid;
412
+ grid-template-columns: 1fr 1fr auto;
413
+ gap: 12px;
414
+ align-items: center;
415
+ margin-bottom: 20px;
416
+ }
417
+
418
+ .dsh-trash-select {
419
+ width: 100%;
420
+ height: 36px;
421
+ padding: 0 32px 0 14px;
422
+ border-radius: 18px;
423
+ border: 1px solid var(--dstrb-border);
424
+ background-color: var(--dstrb-surface);
425
+ font-size: 13px;
426
+ font-family: inherit;
427
+ color: var(--dstrb-text-secondary);
428
+ cursor: pointer;
429
+ outline: none;
430
+ appearance: none;
431
+ background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23a0aec0' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e");
432
+ background-repeat: no-repeat;
433
+ background-position: right 10px center;
434
+ background-size: 14px;
435
+ }
436
+
437
+ .dsh-trash-btn-danger-outline {
438
+ height: 36px;
439
+ background-color: var(--dstrb-surface);
440
+ color: var(--dstrb-danger);
441
+ border: 1px solid var(--dstrb-danger-border);
442
+ padding: 0 16px;
443
+ border-radius: 18px;
444
+ font-size: 13px;
445
+ font-weight: 500;
446
+ font-family: inherit;
447
+ display: inline-flex;
448
+ align-items: center;
449
+ justify-content: center;
450
+ cursor: pointer;
451
+ transition: all 0.15s ease;
452
+ white-space: nowrap;
453
+ }
454
+
455
+ .dsh-trash-btn-danger-outline:hover {
456
+ background-color: var(--dstrb-danger-veil);
457
+ }
458
+
459
+ /* ------------------------------------------------------------------ */
460
+ /* States (loading / error / empty) */
461
+ /* ------------------------------------------------------------------ */
462
+
463
+ .dsh-trash-state {
464
+ padding: 40px 0;
465
+ text-align: center;
466
+ color: var(--dstrb-text-faint);
467
+ font-size: 14px;
468
+ }
469
+
470
+ .dsh-trash-state--error {
471
+ color: var(--dstrb-danger);
472
+ }
473
+
474
+ /* ------------------------------------------------------------------ */
475
+ /* Workspace groups */
476
+ /* ------------------------------------------------------------------ */
477
+
478
+ .dsh-trash-groups {
479
+ display: flex;
480
+ flex-direction: column;
481
+ gap: 24px;
482
+ }
483
+
484
+ .dsh-trash-group {
485
+ display: flex;
486
+ flex-direction: column;
487
+ gap: 10px;
488
+ }
489
+
490
+ .dsh-trash-group-header {
491
+ display: flex;
492
+ justify-content: space-between;
493
+ align-items: center;
494
+ padding: 4px 2px;
495
+ }
496
+
497
+ .dsh-trash-group-title-group {
498
+ display: flex;
499
+ align-items: center;
500
+ gap: 8px;
501
+ min-width: 0;
502
+ flex: 1;
503
+ margin-right: 12px;
504
+ }
505
+
506
+ .dsh-trash-group-title {
507
+ font-size: 15px;
508
+ font-weight: 600;
509
+ color: var(--dstrb-text-strong);
510
+ white-space: nowrap;
511
+ }
512
+
513
+ .dsh-trash-group-path {
514
+ font-size: 11px;
515
+ color: var(--dstrb-text-faint);
516
+ font-family: var(--dstrb-mono, var(--ds-font-family-code, var(--dstrb-mono-fallback)));
517
+ margin-left: 4px;
518
+ overflow: hidden;
519
+ text-overflow: ellipsis;
520
+ white-space: nowrap;
521
+ max-width: 260px;
522
+ }
523
+
524
+ .dsh-trash-group-right {
525
+ display: flex;
526
+ align-items: center;
527
+ gap: 12px;
528
+ flex-shrink: 0;
529
+ }
530
+
531
+ .dsh-trash-group-count {
532
+ font-size: 12px;
533
+ color: var(--dstrb-text-faint);
534
+ }
535
+
536
+ .dsh-trash-more-wrap {
537
+ position: relative;
538
+ }
539
+
540
+ .dsh-trash-more-btn {
541
+ background: none;
542
+ border: none;
543
+ color: var(--dstrb-text-faint);
544
+ font-size: 14px;
545
+ cursor: pointer;
546
+ padding: 2px 6px;
547
+ border-radius: 4px;
548
+ transition: background 0.12s ease, color 0.12s ease;
549
+ }
550
+
551
+ .dsh-trash-more-btn:hover {
552
+ background: var(--dstrb-veil);
553
+ color: var(--dstrb-text-muted);
554
+ }
555
+
556
+ .dsh-trash-menu {
557
+ position: absolute;
558
+ right: 0;
559
+ top: 24px;
560
+ background-color: var(--dstrb-surface);
561
+ box-shadow: var(--dstrb-shadow-menu);
562
+ border-radius: 8px;
563
+ padding: 6px 0;
564
+ z-index: 100;
565
+ min-width: 180px;
566
+ border: 1px solid var(--dstrb-border-light);
567
+ }
568
+
569
+ .dsh-trash-menu-item--danger {
570
+ width: 100%;
571
+ text-align: left;
572
+ padding: 8px 14px;
573
+ background-color: transparent;
574
+ border: none;
575
+ color: var(--dstrb-danger);
576
+ font-size: 13px;
577
+ font-family: inherit;
578
+ display: flex;
579
+ align-items: center;
580
+ cursor: pointer;
581
+ }
582
+
583
+ .dsh-trash-menu-item--danger:hover {
584
+ background-color: var(--dstrb-danger-veil);
585
+ }
586
+
587
+ /* ------------------------------------------------------------------ */
588
+ /* Session cards */
589
+ /* ------------------------------------------------------------------ */
590
+
591
+ .dsh-trash-cards {
592
+ display: flex;
593
+ flex-direction: column;
594
+ background-color: var(--dstrb-surface);
595
+ border-radius: 16px;
596
+ border: 1px solid var(--dstrb-border-light);
597
+ overflow: hidden;
598
+ box-shadow: var(--dstrb-shadow-card);
599
+ }
600
+
601
+ .dsh-trash-card {
602
+ display: flex;
603
+ justify-content: space-between;
604
+ align-items: center;
605
+ padding: 14px 20px;
606
+ border-bottom: 1px solid var(--dstrb-border-hairline);
607
+ transition: background-color 0.15s ease;
608
+ gap: 16px;
609
+ }
610
+
611
+ .dsh-trash-card--checked {
612
+ background-color: var(--dstrb-surface-subtle);
613
+ }
614
+
615
+ .dsh-trash-checkbox {
616
+ width: 16px;
617
+ height: 16px;
618
+ border-radius: 4px;
619
+ border: 1px solid var(--dstrb-border);
620
+ cursor: pointer;
621
+ accent-color: var(--dstrb-accent);
622
+ margin-right: 8px;
623
+ flex-shrink: 0;
624
+ }
625
+
626
+ .dsh-trash-card-main {
627
+ display: flex;
628
+ flex-direction: column;
629
+ gap: 6px;
630
+ min-width: 0;
631
+ flex: 1 1 0%;
632
+ }
633
+
634
+ .dsh-trash-card-title {
635
+ font-size: 14px;
636
+ font-weight: 600;
637
+ color: var(--dstrb-text);
638
+ overflow: hidden;
639
+ text-overflow: ellipsis;
640
+ white-space: nowrap;
641
+ line-height: 1.3;
642
+ }
643
+
644
+ .dsh-trash-card-meta {
645
+ display: flex;
646
+ align-items: center;
647
+ flex-wrap: wrap;
648
+ gap: 14px;
649
+ font-size: 12px;
650
+ color: var(--dstrb-text-muted);
651
+ line-height: 1;
652
+ }
653
+
654
+ .dsh-trash-card-meta-item {
655
+ white-space: nowrap;
656
+ }
657
+
658
+ .dsh-trash-badge {
659
+ background-color: var(--dstrb-surface-subtle);
660
+ padding: 2px 8px;
661
+ border-radius: 6px;
662
+ font-size: 11px;
663
+ color: var(--dstrb-text-muted);
664
+ border: 1px solid var(--dstrb-border-light);
665
+ white-space: nowrap;
666
+ display: inline-flex;
667
+ align-items: center;
668
+ }
669
+
670
+ .dsh-trash-card-actions {
671
+ display: flex;
672
+ align-items: center;
673
+ gap: 8px;
674
+ flex-shrink: 0;
675
+ }
676
+
677
+ .dsh-trash-btn-ghost {
678
+ background-color: var(--dstrb-surface-subtle);
679
+ color: var(--dstrb-text-secondary);
680
+ border: 1px solid var(--dstrb-border);
681
+ padding: 3px 9px;
682
+ border-radius: 12px;
683
+ font-size: 11px;
684
+ font-weight: 500;
685
+ font-family: inherit;
686
+ display: inline-flex;
687
+ align-items: center;
688
+ cursor: pointer;
689
+ transition: all 0.12s ease;
690
+ white-space: nowrap;
691
+ }
692
+
693
+ .dsh-trash-btn-ghost:hover {
694
+ background-color: var(--dstrb-surface-hover);
695
+ border-color: var(--dstrb-text-faint);
696
+ }
697
+
698
+ .dsh-trash-btn-danger-text {
699
+ background-color: transparent;
700
+ color: var(--dstrb-danger);
701
+ border: none;
702
+ padding: 3px 6px;
703
+ border-radius: 12px;
704
+ font-size: 11px;
705
+ font-weight: 500;
706
+ font-family: inherit;
707
+ display: inline-flex;
708
+ align-items: center;
709
+ cursor: pointer;
710
+ transition: all 0.12s ease;
711
+ white-space: nowrap;
712
+ }
713
+
714
+ .dsh-trash-btn-danger-text:hover {
715
+ background-color: var(--dstrb-danger-veil);
716
+ }
717
+
718
+ /* ------------------------------------------------------------------ */
719
+ /* Hover tooltip (position left/top set inline by JS) */
720
+ /* ------------------------------------------------------------------ */
721
+
722
+ .dsh-trash-tooltip {
723
+ position: fixed;
724
+ transform: translateY(-100%);
725
+ background-color: var(--dstrb-tooltip-bg);
726
+ color: var(--dstrb-tooltip-text);
727
+ padding: 10px 14px;
728
+ border-radius: 8px;
729
+ box-shadow: var(--dstrb-shadow-tooltip);
730
+ pointer-events: none;
731
+ z-index: 20000;
732
+ max-width: 380px;
733
+ display: flex;
734
+ flex-direction: column;
735
+ gap: 4px;
736
+ }
737
+
738
+ .dsh-trash-tooltip-title {
739
+ font-size: 13px;
740
+ font-weight: 600;
741
+ color: var(--dstrb-tooltip-text);
742
+ word-break: break-all;
743
+ }
744
+
745
+ .dsh-trash-tooltip-sub {
746
+ font-size: 11px;
747
+ color: var(--dstrb-tooltip-muted);
748
+ font-family: var(--dstrb-mono, var(--ds-font-family-code, var(--dstrb-mono-fallback)));
749
+ word-break: break-all;
750
+ }
751
+
752
+ /* ------------------------------------------------------------------ */
753
+ /* Footer */
754
+ /* ------------------------------------------------------------------ */
755
+
756
+ .dsh-trash-footer {
757
+ margin-top: 24px;
758
+ font-size: 12px;
759
+ color: var(--dstrb-text-faint);
760
+ text-align: right;
761
+ }
762
+
763
+ /* ------------------------------------------------------------------ */
764
+ /* Modals */
765
+ /* ------------------------------------------------------------------ */
766
+
767
+ .dsh-trash-overlay {
768
+ position: fixed;
769
+ top: 0;
770
+ left: 0;
771
+ right: 0;
772
+ bottom: 0;
773
+ background-color: var(--dstrb-overlay);
774
+ display: flex;
775
+ justify-content: center;
776
+ align-items: center;
777
+ z-index: 10000;
778
+ }
779
+
780
+ .dsh-trash-preview {
781
+ background-color: var(--dstrb-surface);
782
+ border-radius: 12px;
783
+ width: 680px;
784
+ max-width: 92vw;
785
+ max-height: 85vh;
786
+ display: flex;
787
+ flex-direction: column;
788
+ box-shadow: var(--dstrb-shadow-modal);
789
+ overflow: hidden;
790
+ }
791
+
792
+ .dsh-trash-preview-header {
793
+ padding: 16px 24px;
794
+ border-bottom: 1px solid var(--dstrb-border-light);
795
+ display: flex;
796
+ justify-content: space-between;
797
+ align-items: center;
798
+ }
799
+
800
+ .dsh-trash-preview-title {
801
+ font-size: 16px;
802
+ font-weight: 600;
803
+ color: var(--dstrb-text-strong);
804
+ overflow: hidden;
805
+ text-overflow: ellipsis;
806
+ white-space: nowrap;
807
+ }
808
+
809
+ .dsh-trash-close {
810
+ background: none;
811
+ border: none;
812
+ font-size: 18px;
813
+ color: var(--dstrb-text-faint);
814
+ cursor: pointer;
815
+ padding: 4px 8px;
816
+ }
817
+
818
+ .dsh-trash-close:hover {
819
+ color: var(--dstrb-text-muted);
820
+ }
821
+
822
+ .dsh-trash-preview-body {
823
+ padding: 20px 24px;
824
+ overflow-y: auto;
825
+ display: flex;
826
+ flex-direction: column;
827
+ gap: 16px;
828
+ max-height: 70vh;
829
+ background-color: var(--dstrb-surface-subtle);
830
+ }
831
+
832
+ .dsh-trash-preview-state {
833
+ text-align: center;
834
+ padding: 30px;
835
+ color: var(--dstrb-text-faint);
836
+ }
837
+
838
+ .dsh-trash-modal {
839
+ background-color: var(--dstrb-surface);
840
+ border-radius: 12px;
841
+ padding: 24px;
842
+ width: 420px;
843
+ max-width: 92vw;
844
+ box-shadow: var(--dstrb-shadow-modal-sm);
845
+ }
846
+
847
+ .dsh-trash-modal-title {
848
+ margin: 0 0 12px 0;
849
+ font-size: 16px;
850
+ font-weight: 600;
851
+ color: var(--dstrb-text-strong);
852
+ }
853
+
854
+ .dsh-trash-modal-body {
855
+ margin: 0 0 20px 0;
856
+ font-size: 14px;
857
+ color: var(--dstrb-text-secondary);
858
+ line-height: 1.5;
859
+ }
860
+
861
+ .dsh-trash-modal-actions {
862
+ display: flex;
863
+ justify-content: flex-end;
864
+ gap: 12px;
865
+ }
866
+
867
+ .dsh-trash-btn-cancel {
868
+ background-color: var(--dstrb-surface-hover);
869
+ color: var(--dstrb-text-secondary);
870
+ border: none;
871
+ padding: 8px 16px;
872
+ border-radius: 6px;
873
+ font-size: 14px;
874
+ font-family: inherit;
875
+ cursor: pointer;
876
+ }
877
+
878
+ .dsh-trash-btn-cancel:hover {
879
+ background-color: var(--dstrb-border);
880
+ }
881
+
882
+ .dsh-trash-btn-confirm {
883
+ background-color: var(--dstrb-danger);
884
+ color: var(--dstrb-on-danger);
885
+ border: none;
886
+ padding: 8px 16px;
887
+ border-radius: 6px;
888
+ font-size: 14px;
889
+ font-family: inherit;
890
+ cursor: pointer;
891
+ }
892
+
893
+ .dsh-trash-btn-confirm:hover {
894
+ background-color: var(--dstrb-danger-strong);
895
+ }
896
+
897
+ /* ------------------------------------------------------------------ */
898
+ /* Message bubbles (preview modal) */
899
+ /* ------------------------------------------------------------------ */
900
+
901
+ .dsh-trash-message {
902
+ display: flex;
903
+ flex-direction: column;
904
+ gap: 6px;
905
+ }
906
+
907
+ .dsh-trash-message-header {
908
+ display: flex;
909
+ align-items: center;
910
+ gap: 10px;
911
+ font-size: 12px;
912
+ }
913
+
914
+ .dsh-trash-message-role {
915
+ font-weight: 600;
916
+ color: var(--dstrb-text-secondary);
917
+ }
918
+
919
+ .dsh-trash-message-time {
920
+ color: var(--dstrb-text-faint);
921
+ }
922
+
923
+ .dsh-trash-bubble-user {
924
+ background-color: var(--dstrb-bubble-user);
925
+ color: var(--dstrb-text-strong);
926
+ padding: 12px 16px;
927
+ border-radius: 12px;
928
+ border-top-left-radius: 2px;
929
+ font-size: 14px;
930
+ line-height: 1.6;
931
+ white-space: pre-wrap;
932
+ word-break: break-word;
933
+ }
934
+
935
+ .dsh-trash-bubble-assistant {
936
+ background-color: var(--dstrb-surface);
937
+ color: var(--dstrb-text);
938
+ padding: 14px 18px;
939
+ border-radius: 12px;
940
+ border-top-left-radius: 2px;
941
+ border: 1px solid var(--dstrb-border);
942
+ font-size: 14px;
943
+ line-height: 1.6;
944
+ white-space: pre-wrap;
945
+ word-break: break-word;
946
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.02);
947
+ }
948
+
949
+ /* ------------------------------------------------------------------ */
950
+ /* Lightweight markdown renderer */
951
+ /* ------------------------------------------------------------------ */
952
+
953
+ .dsh-trash-md {
954
+ white-space: normal;
955
+ word-break: break-word;
956
+ }
957
+
958
+ .dsh-trash-md p {
959
+ margin: 0 0 10px 0;
960
+ line-height: 1.65;
961
+ }
962
+
963
+ .dsh-trash-md h1 { font-size: 20px; font-weight: 600; margin: 16px 0 8px; line-height: 1.4; color: var(--dstrb-text-strong); }
964
+ .dsh-trash-md h2 { font-size: 18px; font-weight: 600; margin: 14px 0 8px; line-height: 1.4; color: var(--dstrb-text-strong); }
965
+ .dsh-trash-md h3 { font-size: 16px; font-weight: 600; margin: 12px 0 6px; line-height: 1.4; color: var(--dstrb-text-strong); }
966
+ .dsh-trash-md h4 { font-size: 15px; font-weight: 600; margin: 12px 0 6px; line-height: 1.4; color: var(--dstrb-text-strong); }
967
+ .dsh-trash-md h5 { font-size: 14px; font-weight: 600; margin: 10px 0 4px; line-height: 1.4; color: var(--dstrb-text-strong); }
968
+ .dsh-trash-md h6 { font-size: 13px; font-weight: 600; margin: 10px 0 4px; line-height: 1.4; color: var(--dstrb-text-strong); }
969
+
970
+ .dsh-trash-md ul,
971
+ .dsh-trash-md ol {
972
+ margin: 6px 0 10px;
973
+ padding-left: 22px;
974
+ }
975
+
976
+ .dsh-trash-md li {
977
+ margin: 3px 0;
978
+ line-height: 1.6;
979
+ }
980
+
981
+ .dsh-trash-md blockquote {
982
+ border-left: 3px solid var(--dstrb-quote-border);
983
+ margin: 8px 0;
984
+ padding: 4px 12px;
985
+ color: var(--dstrb-text-secondary);
986
+ background-color: var(--dstrb-quote-bg);
987
+ }
988
+
989
+ .dsh-trash-md hr {
990
+ border: none;
991
+ border-top: 1px solid var(--dstrb-border);
992
+ margin: 14px 0;
993
+ }
994
+
995
+ .dsh-trash-md-code-inline {
996
+ background-color: var(--dstrb-code-inline-bg);
997
+ padding: 2px 5px;
998
+ border-radius: 4px;
999
+ font-family: var(--dstrb-mono, var(--ds-font-family-code, var(--dstrb-mono-fallback)));
1000
+ font-size: 0.9em;
1001
+ color: var(--dstrb-code-inline-text);
1002
+ }
1003
+
1004
+ .dsh-trash-md-codeblock {
1005
+ background-color: var(--dstrb-codeblock-bg);
1006
+ color: var(--dstrb-codeblock-text);
1007
+ padding: 12px 14px;
1008
+ border-radius: 8px;
1009
+ overflow-x: auto;
1010
+ margin: 10px 0;
1011
+ font-family: var(--dstrb-mono, var(--ds-font-family-code, var(--dstrb-mono-fallback)));
1012
+ font-size: 13px;
1013
+ line-height: 1.5;
1014
+ white-space: pre-wrap;
1015
+ word-break: break-word;
1016
+ }
1017
+
1018
+ .dsh-trash-md-codeblock-content {
1019
+ font-family: inherit;
1020
+ font-size: inherit;
1021
+ white-space: pre-wrap;
1022
+ word-break: break-word;
1023
+ }
1024
+
1025
+ .dsh-trash-md-lang {
1026
+ font-size: 11px;
1027
+ color: var(--dstrb-codeblock-lang);
1028
+ text-transform: uppercase;
1029
+ letter-spacing: 0.5px;
1030
+ margin-bottom: 6px;
1031
+ }
1032
+
1033
+ .dsh-trash-md-link {
1034
+ color: var(--dstrb-accent);
1035
+ text-decoration: underline;
1036
+ }
1037
+
1038
+ .dsh-trash-md-table-wrap {
1039
+ overflow-x: auto;
1040
+ margin: 10px 0;
1041
+ }
1042
+
1043
+ .dsh-trash-md-table {
1044
+ border-collapse: collapse;
1045
+ width: 100%;
1046
+ font-size: 13px;
1047
+ }
1048
+
1049
+ .dsh-trash-md-th {
1050
+ border: 1px solid var(--dstrb-border);
1051
+ padding: 6px 10px;
1052
+ background-color: var(--dstrb-surface-subtle);
1053
+ font-weight: 600;
1054
+ text-align: left;
1055
+ }
1056
+
1057
+ .dsh-trash-md-td {
1058
+ border: 1px solid var(--dstrb-border);
1059
+ padding: 6px 10px;
1060
+ }
1061
+
1062
+ /* ------------------------------------------------------------------ */
1063
+ /* Toast layer (bottom-left; show/hide animated via inline styles) */
1064
+ /* ------------------------------------------------------------------ */
1065
+
1066
+ .dsh-trash-toast-container {
1067
+ position: fixed;
1068
+ bottom: 24px;
1069
+ right: 24px;
1070
+ z-index: 10000;
1071
+ display: flex;
1072
+ flex-direction: column;
1073
+ gap: 8px;
1074
+ pointer-events: none;
1075
+ }
1076
+
1077
+ .dsh-trash-toast {
1078
+ background-color: var(--dstrb-toast-bg);
1079
+ color: var(--dstrb-toast-text);
1080
+ padding: 10px 18px;
1081
+ border-radius: 6px;
1082
+ box-shadow: var(--dstrb-shadow-toast);
1083
+ display: flex;
1084
+ align-items: center;
1085
+ gap: 12px;
1086
+ font-size: 13px;
1087
+ /* font-family comes from the "Font routing" block (it is portaled to
1088
+ <body>, outside .dsh-trash-container, so it is routed there too). */
1089
+ pointer-events: auto;
1090
+ transition: all 0.2s ease;
1091
+ opacity: 0;
1092
+ transform: translateY(10px);
1093
+ }
1094
+
1095
+ .dsh-trash-toast-undo {
1096
+ background-color: var(--dstrb-toast-btn-bg);
1097
+ color: var(--dstrb-toast-btn-text);
1098
+ border: none;
1099
+ padding: 4px 10px;
1100
+ border-radius: 4px;
1101
+ font-size: 12px;
1102
+ font-family: inherit;
1103
+ cursor: pointer;
1104
+ margin-left: 4px;
1105
+ }
1106
+
1107
+ /* ------------------------------------------------------------------ */
1108
+ /* Sidebar per-row delete button (moved out of client.js) */
1109
+ /* ------------------------------------------------------------------ */
1110
+
1111
+ .dsh-trash-row-btn {
1112
+ background: none;
1113
+ border: none;
1114
+ padding: 2px;
1115
+ width: 20px;
1116
+ height: 20px;
1117
+ flex: none;
1118
+ display: inline-flex;
1119
+ align-items: center;
1120
+ justify-content: center;
1121
+ cursor: pointer;
1122
+ border-radius: 4px;
1123
+ opacity: 0;
1124
+ transition: opacity 0.12s ease, color 0.12s ease, background 0.12s ease;
1125
+ color: var(--dsw-alias-label-tertiary, var(--dstrb-text-faint));
1126
+ margin-right: 4px;
1127
+ }
1128
+
1129
+ /* 占位按钮:等宽隐形,保持无法解析 ID 的会话行与其它行布局一致(防止"往左靠") */
1130
+ .dsh-trash-row-btn--spacer {
1131
+ pointer-events: none;
1132
+ cursor: default;
1133
+ opacity: 0 !important;
1134
+ }
1135
+
1136
+ .dsh-trash-row:hover .dsh-trash-row-btn:not(.dsh-trash-row-btn--spacer),
1137
+ [role="treeitem"]:hover .dsh-trash-row-btn:not(.dsh-trash-row-btn--spacer),
1138
+ .dsh-session-item:hover .dsh-trash-row-btn:not(.dsh-trash-row-btn--spacer),
1139
+ a[href*="/session/"]:hover .dsh-trash-row-btn:not(.dsh-trash-row-btn--spacer) {
1140
+ opacity: 0.85;
1141
+ }
1142
+
1143
+ .dsh-trash-row-btn:not(.dsh-trash-row-btn--spacer):hover {
1144
+ opacity: 1;
1145
+ color: var(--dstrb-danger);
1146
+ background: var(--dstrb-veil);
1147
+ }
1148
+
1149
+ .dsh-trash-row-btn svg {
1150
+ display: block;
1151
+ }
1152
+
1153
+ /* ------------------------------------------------------------------ */
1154
+ /* Conversation-header delete action */
1155
+ /* ------------------------------------------------------------------ */
1156
+
1157
+ .dsh-trash-header-action {
1158
+ display: inline-flex;
1159
+ align-items: center;
1160
+ justify-content: center;
1161
+ background: none;
1162
+ border: none;
1163
+ padding: 5px;
1164
+ width: 26px;
1165
+ height: 26px;
1166
+ border-radius: 7px;
1167
+ line-height: 1;
1168
+ cursor: pointer;
1169
+ color: var(--dsw-alias-label-tertiary, var(--dstrb-text-faint));
1170
+ opacity: 0.85;
1171
+ transition: color 0.12s ease, background 0.12s ease, opacity 0.12s ease;
1172
+ }
1173
+
1174
+ .dsh-trash-header-action:hover {
1175
+ color: var(--dstrb-danger);
1176
+ background: var(--dstrb-veil);
1177
+ opacity: 1;
1178
+ }