@yolk_vat-y/dsh-project-memory 0.4.0 → 0.4.2

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.
@@ -0,0 +1,74 @@
1
+ /**
2
+ * /tasks、/task 命令在会话中的节点渲染器(conversation.chat.commandview,按命令名 key)。
3
+ *
4
+ * 目标:不再让大段文本+JSON 出现在会话里——
5
+ * - 列表型(/tasks、无动词的 /task):只渲染一行极简“已同步 N 套”状态;
6
+ * 同时把节点文本里的 JSON 载荷解析进浮动面板(侧边卡片由它驱动),
7
+ * 面板若被收起则自动展开(等价“输入 /task 就看到卡片”)。
8
+ * - 动作型(/task switch|archive):渲染一行操作结果(切换/归档反馈)。
9
+ * - 错误/执行中:一行极简状态,不倾倒原文。
10
+ */
11
+ import { useEffect } from 'react'
12
+ import { IconFolderOpenOutline16 } from '@deepseek-ai/dsh-client-ui-primitives'
13
+ import { parseTaskPayloadText, taskStore } from './task-store.ts'
14
+ import css from './TaskCommandNode.module.css'
15
+
16
+ /** node = CommandRowOwnerProps.node(CommandNode: name / args / outcome{kind,text}) */
17
+ export function TaskCommandNode({ node }: { node?: any }) {
18
+ const name = node?.name ?? 'task'
19
+ const outcome = node?.outcome ?? null
20
+ const args = typeof node?.args === 'string' ? node.args : ''
21
+ const verb = args.trim().split(/\s+/)[0] ?? ''
22
+ const isList = name === 'tasks' || !verb
23
+ const text = outcome?.text ?? ''
24
+
25
+ const parsed = parseTaskPayloadText(text)
26
+
27
+ // 载荷进面板 + 列表型自动展开面板。
28
+ // 注意:命令节点先以“执行中”创建、完成后原地更新(同一组件实例),
29
+ // 所以 effect 必须在结果文本变化时重跑,而不是只在挂载时跑一次。
30
+ useEffect(() => {
31
+ if (!parsed) return
32
+ taskStore.actions.setTasks({
33
+ tasks: parsed.tasks,
34
+ boundTaskId: parsed.boundId,
35
+ archivedCount: parsed.archived,
36
+ })
37
+ if (isList) taskStore.actions.open()
38
+ // eslint-disable-next-line react-hooks/exhaustive-deps
39
+ }, [text])
40
+
41
+ // 执行中
42
+ if (outcome === null) {
43
+ return <div className={css.row} data-variant="running">/{name} 执行中…</div>
44
+ }
45
+
46
+ // 失败:一行极简,不含大段原文
47
+ if (outcome.kind === 'error') {
48
+ const brief = String(text ?? '').split('\n')[0].slice(0, 120)
49
+ return <div className={css.row} data-variant="error">/{name} 失败{brief ? `:${brief}` : ''}</div>
50
+ }
51
+
52
+ // 动作型:取第一段(操作反馈),不带 JSON
53
+ if (!isList) {
54
+ const note = String(text ?? '')
55
+ .split(/\n{2,}/)[0]
56
+ .replace(/```.*$/s, '')
57
+ .trim()
58
+ .slice(0, 200)
59
+ return <div className={css.row} data-variant="ok">/{name} {note || '已完成'}</div>
60
+ }
61
+
62
+ // 列表型:一行极简状态
63
+ const count = parsed ? parsed.tasks.length : 0
64
+ const archived = parsed ? parsed.archived : 0
65
+ const label = parsed
66
+ ? `任务 ${count} 套${archived ? `(归档 ${archived})` : ''} · 已同步到任务面板`
67
+ : `/${name} 已执行`
68
+ return (
69
+ <div className={css.row} data-variant="ok">
70
+ <IconFolderOpenOutline16 className={css.icon} />
71
+ <span>{label}</span>
72
+ </div>
73
+ )
74
+ }
@@ -0,0 +1,564 @@
1
+ /* Task Panel — dsh web shell.overlay 浮层样式。
2
+ 全部用 dsh 别名 token(--dsw-alias-*),亮暗随宿主主题自动切换;
3
+ 轻边框 + 轻阴影,无玻璃拟态、无默认 AI 渐变,与 dsh 控件同语言。 */
4
+
5
+ .panel,
6
+ .pill {
7
+ /* shell.overlay 默认 click-through,条目自身开启 pointer-events */
8
+ pointer-events: auto;
9
+ font-family: inherit;
10
+ }
11
+
12
+ .panel {
13
+ position: fixed;
14
+ width: 380px;
15
+ max-width: calc(100vw - 24px);
16
+ max-height: min(70vh, 640px);
17
+ display: flex;
18
+ flex-direction: column;
19
+ background: var(--dsw-alias-bg-layer-2, var(--dsw-alias-bg-base, #fff));
20
+ border: 1px solid var(--dsw-alias-border-l2, rgba(127, 127, 127, 0.3));
21
+ border-radius: 14px;
22
+ box-shadow: 0 12px 32px rgba(0, 0, 0, 0.16), 0 2px 8px rgba(0, 0, 0, 0.08);
23
+ overflow: hidden;
24
+ animation: panelIn 0.18s ease-out;
25
+ }
26
+
27
+ @keyframes panelIn {
28
+ from { opacity: 0; transform: translateY(-4px); }
29
+ to { opacity: 1; transform: none; }
30
+ }
31
+
32
+ /* 拖拽把手:顶部细条,不抢占 header 交互 */
33
+ .dragHandle {
34
+ position: absolute;
35
+ top: 0;
36
+ left: 0;
37
+ right: 0;
38
+ height: 12px;
39
+ cursor: grab;
40
+ display: flex;
41
+ align-items: center;
42
+ justify-content: center;
43
+ z-index: 1;
44
+ }
45
+ .dragHandle:active { cursor: grabbing; }
46
+ .handleGrip {
47
+ width: 32px;
48
+ height: 3px;
49
+ border-radius: 2px;
50
+ background: var(--dsw-alias-separator-primary, rgba(127, 127, 127, 0.35));
51
+ opacity: 0.8;
52
+ }
53
+
54
+ .header {
55
+ display: flex;
56
+ align-items: center;
57
+ justify-content: space-between;
58
+ gap: 8px;
59
+ padding: 10px 10px 8px 14px;
60
+ border-bottom: 1px solid var(--dsw-alias-border-l1, rgba(127, 127, 127, 0.18));
61
+ user-select: none;
62
+ }
63
+ .headerLeft {
64
+ display: flex;
65
+ align-items: center;
66
+ gap: 6px;
67
+ min-width: 0;
68
+ }
69
+ .headerIcon {
70
+ color: var(--dsw-alias-label-secondary);
71
+ flex: none;
72
+ }
73
+ .headerTitle {
74
+ margin: 0;
75
+ font-size: 13px;
76
+ font-weight: 600;
77
+ line-height: 20px;
78
+ color: var(--dsw-alias-label-primary);
79
+ white-space: nowrap;
80
+ }
81
+ .headerRight {
82
+ display: flex;
83
+ align-items: center;
84
+ gap: 2px;
85
+ margin-left: auto;
86
+ }
87
+ .counts {
88
+ font-size: 11px;
89
+ line-height: 16px;
90
+ color: var(--dsw-alias-label-tertiary);
91
+ white-space: nowrap;
92
+ margin-right: 4px;
93
+ }
94
+
95
+ .boundBadge {
96
+ flex: none;
97
+ font-size: 10px;
98
+ line-height: 14px;
99
+ padding: 0 6px;
100
+ border-radius: 7px;
101
+ color: var(--dsw-alias-label-primary-foreground, #fff);
102
+ background: var(--dsw-alias-button-primary-fill, #3a6ef5);
103
+ white-space: nowrap;
104
+ }
105
+ .softBadge {
106
+ flex: none;
107
+ font-size: 10px;
108
+ line-height: 14px;
109
+ padding: 0 6px;
110
+ border-radius: 7px;
111
+ color: var(--dsw-alias-label-tertiary);
112
+ background: var(--dsw-alias-interactive-bg-hover, rgba(127, 127, 127, 0.12));
113
+ white-space: nowrap;
114
+ }
115
+
116
+ .notice {
117
+ margin: 8px 12px 0;
118
+ padding: 6px 10px;
119
+ border-radius: 8px;
120
+ font-size: 12px;
121
+ line-height: 18px;
122
+ color: var(--dsw-alias-state-warn-label, #b7791f);
123
+ background: var(--dsw-alias-interactive-bg-hover, rgba(127, 127, 127, 0.1));
124
+ word-break: break-all;
125
+ }
126
+
127
+ .taskList {
128
+ overflow-y: auto;
129
+ padding: 8px;
130
+ display: flex;
131
+ flex-direction: column;
132
+ gap: 6px;
133
+ scrollbar-width: thin;
134
+ scrollbar-color: var(--dsw-alias-scrollbar-bg-l2, transparent) transparent;
135
+ }
136
+
137
+ .emptyState {
138
+ padding: 36px 24px 30px;
139
+ text-align: center;
140
+ color: var(--dsw-alias-label-secondary);
141
+ }
142
+ .emptyTitle {
143
+ margin: 0 0 6px;
144
+ font-size: 13px;
145
+ font-weight: 600;
146
+ color: var(--dsw-alias-label-primary);
147
+ }
148
+ .emptyDesc {
149
+ margin: 0;
150
+ font-size: 12px;
151
+ line-height: 20px;
152
+ color: var(--dsw-alias-label-tertiary);
153
+ }
154
+ .syncHint {
155
+ margin: 10px 0 0;
156
+ font-size: 11px;
157
+ color: var(--dsw-alias-label-dimmed);
158
+ display: flex;
159
+ align-items: center;
160
+ justify-content: center;
161
+ gap: 6px;
162
+ }
163
+
164
+ /* —— 任务卡片 —— */
165
+ .card {
166
+ border: 1px solid var(--dsw-alias-border-l1, rgba(127, 127, 127, 0.16));
167
+ border-radius: 10px;
168
+ background: var(--dsw-alias-bg-base, transparent);
169
+ overflow: hidden;
170
+ transition: border-color 0.15s ease;
171
+ }
172
+ .cardBound {
173
+ border-color: var(--dsw-alias-border-l3, rgba(127, 127, 127, 0.35));
174
+ box-shadow: inset 0 0 0 0.5px var(--dsw-alias-border-l3, transparent);
175
+ }
176
+ .cardHead {
177
+ width: 100%;
178
+ display: flex;
179
+ align-items: center;
180
+ justify-content: space-between;
181
+ gap: 8px;
182
+ padding: 8px 10px 7px;
183
+ background: transparent;
184
+ border: none;
185
+ cursor: pointer;
186
+ text-align: left;
187
+ }
188
+ .cardHead:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(127, 127, 127, 0.08)); }
189
+ .cardTitleRow {
190
+ display: flex;
191
+ align-items: center;
192
+ gap: 6px;
193
+ min-width: 0;
194
+ }
195
+ .cardTitle {
196
+ font-size: 13px;
197
+ font-weight: 500;
198
+ line-height: 20px;
199
+ color: var(--dsw-alias-label-primary);
200
+ white-space: nowrap;
201
+ overflow: hidden;
202
+ text-overflow: ellipsis;
203
+ }
204
+ .cardMeta {
205
+ display: flex;
206
+ align-items: center;
207
+ gap: 8px;
208
+ flex: none;
209
+ color: var(--dsw-alias-label-tertiary);
210
+ }
211
+ .progressText {
212
+ font-size: 11px;
213
+ line-height: 16px;
214
+ font-variant-numeric: tabular-nums;
215
+ color: var(--dsw-alias-label-secondary);
216
+ }
217
+ .updated { font-size: 10px; line-height: 14px; color: var(--dsw-alias-label-dimmed); }
218
+ .chevron {
219
+ display: inline-flex;
220
+ color: var(--dsw-alias-label-tertiary);
221
+ }
222
+
223
+ /* 进度细条 */
224
+ .track {
225
+ height: 2px;
226
+ margin: 0 10px 6px;
227
+ border-radius: 1px;
228
+ background: var(--dsw-alias-interactive-bg-hover, rgba(127, 127, 127, 0.12));
229
+ overflow: hidden;
230
+ }
231
+ .trackFill {
232
+ height: 100%;
233
+ border-radius: 1px;
234
+ background: var(--dsw-alias-label-primary-bluish, var(--dsw-alias-button-primary-fill, #3a6ef5));
235
+ transition: width 0.2s ease;
236
+ }
237
+
238
+ .cardBody {
239
+ border-top: 1px solid var(--dsw-alias-border-l1, rgba(127, 127, 127, 0.14));
240
+ padding: 8px 10px 10px;
241
+ }
242
+ .section { margin-bottom: 8px; }
243
+ .section:last-child { margin-bottom: 0; }
244
+ .sectionLabel {
245
+ display: flex;
246
+ align-items: center;
247
+ gap: 6px;
248
+ font-size: 11px;
249
+ line-height: 16px;
250
+ color: var(--dsw-alias-label-secondary);
251
+ margin-bottom: 4px;
252
+ }
253
+ .sectionCount {
254
+ font-size: 10px;
255
+ line-height: 14px;
256
+ padding: 0 5px;
257
+ border-radius: 6px;
258
+ background: var(--dsw-alias-interactive-bg-hover, rgba(127, 127, 127, 0.1));
259
+ color: var(--dsw-alias-label-tertiary);
260
+ }
261
+
262
+ .stepsList {
263
+ list-style: none;
264
+ margin: 0;
265
+ padding: 0;
266
+ display: flex;
267
+ flex-direction: column;
268
+ gap: 1px;
269
+ }
270
+ .stepRow {
271
+ display: flex;
272
+ align-items: flex-start;
273
+ gap: 7px;
274
+ padding: 3px 2px;
275
+ }
276
+ .stepRow > svg { flex: none; margin-top: 2px; }
277
+ .stepDone { color: var(--dsw-alias-label-dimmed); }
278
+ .stepRun { color: var(--dsw-alias-label-primary-bluish, #3a6ef5); }
279
+ .stepPending {
280
+ flex: none;
281
+ width: 8px;
282
+ height: 8px;
283
+ margin: 5px 3px;
284
+ border-radius: 50%;
285
+ background: var(--dsw-alias-border-l3, rgba(127, 127, 127, 0.5));
286
+ }
287
+ .stepContent {
288
+ font-size: 12px;
289
+ line-height: 20px;
290
+ color: var(--dsw-alias-label-secondary);
291
+ word-break: break-word;
292
+ }
293
+ .stepContentDone {
294
+ color: var(--dsw-alias-label-dimmed);
295
+ text-decoration: line-through;
296
+ }
297
+ .stepContentRun {
298
+ color: var(--dsw-alias-label-primary);
299
+ }
300
+
301
+ .muted {
302
+ font-size: 11px;
303
+ line-height: 18px;
304
+ color: var(--dsw-alias-label-dimmed);
305
+ }
306
+
307
+ .filesList {
308
+ list-style: none;
309
+ margin: 0;
310
+ padding: 0;
311
+ display: flex;
312
+ flex-direction: column;
313
+ }
314
+ .fileRow {
315
+ width: 100%;
316
+ display: flex;
317
+ align-items: center;
318
+ gap: 6px;
319
+ padding: 3px 4px;
320
+ border: none;
321
+ border-radius: 6px;
322
+ background: transparent;
323
+ cursor: pointer;
324
+ text-align: left;
325
+ }
326
+ .fileRow:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(127, 127, 127, 0.08)); }
327
+ .fileDot {
328
+ flex: none;
329
+ width: 5px;
330
+ height: 5px;
331
+ border-radius: 50%;
332
+ background: var(--dsw-alias-border-l3, rgba(127, 127, 127, 0.5));
333
+ }
334
+ .filePath {
335
+ font-size: 11px;
336
+ line-height: 18px;
337
+ color: var(--dsw-alias-label-secondary);
338
+ white-space: nowrap;
339
+ overflow: hidden;
340
+ text-overflow: ellipsis;
341
+ direction: rtl;
342
+ text-align: left;
343
+ font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
344
+ }
345
+ .fileLine {
346
+ flex: none;
347
+ font-size: 10px;
348
+ line-height: 18px;
349
+ color: var(--dsw-alias-label-dimmed);
350
+ }
351
+
352
+ .cardFooter {
353
+ display: flex;
354
+ gap: 6px;
355
+ margin-top: 8px;
356
+ }
357
+
358
+ .spinning svg {
359
+ animation: spin 0.9s linear infinite;
360
+ }
361
+ @keyframes spin {
362
+ to { transform: rotate(360deg); }
363
+ }
364
+
365
+ @media (prefers-reduced-motion: reduce) {
366
+ .panel { animation: none; }
367
+ .trackFill, .card, .pill { transition: none; }
368
+ .spinning svg { animation-duration: 2.4s; }
369
+ }
370
+
371
+ /* —— 折叠迷你条(顶部可拖拽) —— */
372
+ .miniBar {
373
+ position: fixed;
374
+ display: inline-flex;
375
+ align-items: center;
376
+ gap: 7px;
377
+ max-width: min(46vw, 340px);
378
+ height: 34px;
379
+ padding: 0 12px;
380
+ border-radius: 999px;
381
+ border: 1px solid var(--dsw-alias-border-l3, rgba(127, 127, 127, 0.3));
382
+ background: var(--dsw-alias-bg-layer-2, var(--dsw-alias-bg-base, #fff));
383
+ color: var(--dsw-alias-label-primary);
384
+ box-shadow: 0 6px 20px rgba(0, 0, 0, 0.14), 0 1px 4px rgba(0, 0, 0, 0.08);
385
+ cursor: grab;
386
+ user-select: none;
387
+ pointer-events: auto;
388
+ transition: background 0.15s ease, border-color 0.15s ease;
389
+ font-size: 12px;
390
+ line-height: 18px;
391
+ }
392
+ .miniBar:active { cursor: grabbing; }
393
+ .miniBar:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(127, 127, 127, 0.08)); }
394
+ .miniIcon { color: var(--dsw-alias-label-secondary); flex: none; }
395
+ .miniText {
396
+ white-space: nowrap;
397
+ overflow: hidden;
398
+ text-overflow: ellipsis;
399
+ }
400
+ .miniChevron { color: var(--dsw-alias-label-tertiary); flex: none; }
401
+
402
+ /* —— 滚动修正:任务列表占满可用高度,展开卡内部可滚 —— */
403
+ .taskList {
404
+ flex: 1 1 auto;
405
+ min-height: 0;
406
+ }
407
+ .cardBody {
408
+ max-height: 300px;
409
+ overflow-y: auto;
410
+ overscroll-behavior: contain;
411
+ }
412
+ .card {
413
+ display: flex;
414
+ flex-direction: column;
415
+ }
416
+
417
+ /* —— 错误边界兜底按钮 —— */
418
+ .boundaryFallback {
419
+ position: fixed;
420
+ right: 16px;
421
+ top: 64px;
422
+ font-size: 12px;
423
+ line-height: 18px;
424
+ padding: 4px 10px;
425
+ border-radius: 999px;
426
+ border: 1px solid var(--dsw-alias-border-l3, rgba(127,127,127,.3));
427
+ background: var(--dsw-alias-bg-layer-2, #fff);
428
+ color: var(--dsw-alias-label-secondary);
429
+ cursor: pointer;
430
+ pointer-events: auto;
431
+ }
432
+
433
+ /* —— 绑定卡片步骤:可点状态/可双击编辑 —— */
434
+ .stepToggle {
435
+ flex: none;
436
+ display: inline-flex;
437
+ align-items: center;
438
+ margin-top: 2px;
439
+ padding: 0;
440
+ border: none;
441
+ background: transparent;
442
+ cursor: pointer;
443
+ border-radius: 4px;
444
+ }
445
+ .stepToggle:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(127,127,127,.12)); }
446
+ .stepToggle:disabled { cursor: default; opacity: .5; }
447
+ .stepEditable {
448
+ cursor: text;
449
+ border-radius: 3px;
450
+ }
451
+ .stepEditable:hover {
452
+ outline: 1px dashed var(--dsw-alias-border-l3, rgba(127,127,127,.4));
453
+ outline-offset: 1px;
454
+ }
455
+ .stepInput {
456
+ flex: 1;
457
+ min-width: 0;
458
+ font: inherit;
459
+ font-size: 12px;
460
+ line-height: 20px;
461
+ color: var(--dsw-alias-label-primary);
462
+ background: var(--dsw-alias-bg-base, transparent);
463
+ border: 1px solid var(--dsw-alias-border-l3, rgba(127,127,127,.45));
464
+ border-radius: 5px;
465
+ padding: 0 5px;
466
+ }
467
+
468
+ /* —— 行内编辑框(自动长高) —— */
469
+ .stepInput {
470
+ display: block;
471
+ flex: 1 1 auto;
472
+ min-width: 0;
473
+ width: auto;
474
+ resize: none;
475
+ overflow: hidden;
476
+ box-sizing: border-box;
477
+ white-space: pre-wrap;
478
+ word-break: break-word;
479
+ line-height: 20px;
480
+ }
481
+ .cardTitleEditable {
482
+ cursor: text;
483
+ border-radius: 3px;
484
+ }
485
+ .cardTitleEditable:hover {
486
+ outline: 1px dashed var(--dsw-alias-border-l3, rgba(127,127,127,.4));
487
+ outline-offset: 1px;
488
+ }
489
+
490
+ /* —— 面板风格主题 ——
491
+ 默认 native = 现款(Linear/干净,不改任何东西)。
492
+ 其余档位只改材质/几何/字型/密度;颜色一律仍取自 dsw 别名令牌,
493
+ 因此宿主明暗与主题插件对颜色的影响始终保留。 */
494
+ .panel[data-theme="glass"], .miniBar[data-theme="glass"] {
495
+ background: color-mix(in srgb, var(--dsw-alias-bg-layer-2, #ffffff) 90%, transparent);
496
+ backdrop-filter: blur(18px) saturate(1.2);
497
+ -webkit-backdrop-filter: blur(18px) saturate(1.2);
498
+ border: 1px solid color-mix(in srgb, var(--dsw-alias-border-l2, rgba(127,127,127,.3)) 80%, transparent);
499
+ }
500
+ .panel[data-theme="glass"] .card {
501
+ background: color-mix(in srgb, var(--dsw-alias-bg-base, transparent) 84%, transparent);
502
+ border-color: color-mix(in srgb, var(--dsw-alias-border-l1, rgba(127,127,127,.16)) 60%, transparent);
503
+ }
504
+ .panel[data-theme="glass"] .cardBody { border-top-color: color-mix(in srgb, var(--dsw-alias-border-l1, rgba(127,127,127,.14)) 60%, transparent); }
505
+ @media (prefers-reduced-transparency: reduce) {
506
+ .panel[data-theme="glass"], .miniBar[data-theme="glass"] { background: var(--dsw-alias-bg-layer-2, #fff); backdrop-filter: none; }
507
+ .panel[data-theme="glass"] .card { background: var(--dsw-alias-bg-base, transparent); }
508
+ }
509
+ @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
510
+ .panel[data-theme="glass"], .miniBar[data-theme="glass"] { background: var(--dsw-alias-bg-layer-2, #fff); }
511
+ }
512
+
513
+ /* 粗野主义:直角/重边框/无阴影/实心分层 */
514
+ .panel[data-theme="brutal"] { border-radius: 6px; border-width: 1px; box-shadow: none; }
515
+ .panel[data-theme="brutal"] .card {
516
+ border-radius: 3px;
517
+ border: 1px solid var(--dsw-alias-border-l3, rgba(127,127,127,.42));
518
+ background: var(--dsw-alias-bg-base, transparent);
519
+ box-shadow: none;
520
+ }
521
+ .panel[data-theme="brutal"] .cardHead { padding: 7px 10px 6px; }
522
+ .panel[data-theme="brutal"] .cardTitle { font-weight: 650; letter-spacing: .01em; }
523
+ .panel[data-theme="brutal"] .headerTitle { letter-spacing: .03em; }
524
+ .panel[data-theme="brutal"] .boundBadge { border-radius: 2px; }
525
+ .panel[data-theme="brutal"] .track { height: 3px; border-radius: 0; }
526
+ .panel[data-theme="brutal"] .trackFill { border-radius: 0; }
527
+ .panel[data-theme="brutal"] .cardBody { border-top: 1px solid var(--dsw-alias-border-l2, rgba(127,127,127,.24)); }
528
+
529
+ /* 终端等宽:字型密度向命令行靠拢,颜色不变 */
530
+ .panel[data-theme="mono"] .headerTitle,
531
+ .panel[data-theme="mono"] .counts,
532
+ .panel[data-theme="mono"] .cardTitle,
533
+ .panel[data-theme="mono"] .progressText,
534
+ .panel[data-theme="mono"] .stepContent,
535
+ .panel[data-theme="mono"] .filePath {
536
+ font-family: ui-monospace, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
537
+ }
538
+ .panel[data-theme="mono"] .cardTitle { font-size: 12px; }
539
+ .panel[data-theme="mono"] .stepContent { font-size: 11.5px; }
540
+ .panel[data-theme="mono"] .card { border-radius: 5px; }
541
+ .panel[data-theme="mono"] .trackFill { border-radius: 0; }
542
+ .panel[data-theme="mono"] .stepPending { border-radius: 1px; }
543
+ .panel[data-theme="mono"] .updated { letter-spacing: .02em; }
544
+ /* 标题左侧文件夹图标(点击切风格)——无框,视觉上就是个图标 */
545
+ .headerIconBtn {
546
+ display: inline-flex;
547
+ align-items: center;
548
+ justify-content: center;
549
+ padding: 0;
550
+ margin: 0;
551
+ border: none;
552
+ border-radius: 0;
553
+ background: transparent;
554
+ color: inherit;
555
+ cursor: pointer;
556
+ flex: none;
557
+ }
558
+ .headerIcon { color: var(--dsw-alias-label-secondary); flex: none; display: block; }
559
+
560
+ /* —— header 防重叠 —— */
561
+ .headerLeft { min-width: 0; }
562
+ .headerTitle { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
563
+ .headerRight { min-width: 0; }
564
+ .counts { flex: none; max-width: 45%; overflow: hidden; text-overflow: ellipsis; margin-left: auto; }