@hirohsu/user-web-feedback 2.8.8 → 2.8.9

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 (34) hide show
  1. package/README.md +953 -953
  2. package/dist/cli.cjs +35073 -22235
  3. package/dist/index.cjs +39829 -26989
  4. package/dist/static/app.js +385 -385
  5. package/dist/static/components/navbar.css +406 -406
  6. package/dist/static/components/navbar.html +49 -49
  7. package/dist/static/components/navbar.js +211 -211
  8. package/dist/static/dashboard.css +495 -495
  9. package/dist/static/dashboard.html +95 -95
  10. package/dist/static/dashboard.js +540 -540
  11. package/dist/static/favicon.svg +27 -27
  12. package/dist/static/index.html +541 -541
  13. package/dist/static/logs.html +376 -376
  14. package/dist/static/logs.js +442 -442
  15. package/dist/static/mcp-settings.html +797 -797
  16. package/dist/static/mcp-settings.js +884 -884
  17. package/dist/static/modules/app-core.js +124 -124
  18. package/dist/static/modules/conversation-panel.js +247 -247
  19. package/dist/static/modules/feedback-handler.js +1420 -1420
  20. package/dist/static/modules/image-handler.js +155 -155
  21. package/dist/static/modules/log-viewer.js +296 -296
  22. package/dist/static/modules/mcp-manager.js +474 -474
  23. package/dist/static/modules/prompt-manager.js +364 -364
  24. package/dist/static/modules/settings-manager.js +299 -299
  25. package/dist/static/modules/socket-manager.js +170 -170
  26. package/dist/static/modules/state-manager.js +352 -352
  27. package/dist/static/modules/timer-controller.js +243 -243
  28. package/dist/static/modules/ui-helpers.js +246 -246
  29. package/dist/static/settings.html +426 -426
  30. package/dist/static/settings.js +767 -767
  31. package/dist/static/style.css +2156 -2156
  32. package/dist/static/terminals.html +357 -357
  33. package/dist/static/terminals.js +321 -321
  34. package/package.json +95 -95
@@ -1,495 +1,495 @@
1
- /* ============ Dashboard 專用樣式 ============ */
2
-
3
- .dashboard-body {
4
- overflow-y: auto;
5
- min-height: 100vh;
6
- padding-bottom: 60px;
7
- }
8
-
9
- /* ============ Dashboard Header ============ */
10
-
11
- .dashboard-header {
12
- display: flex;
13
- justify-content: space-between;
14
- align-items: center;
15
- padding: var(--spacing-md) var(--spacing-lg);
16
- background: var(--bg-secondary);
17
- border-bottom: 1px solid var(--border-color);
18
- position: sticky;
19
- top: 0;
20
- z-index: 100;
21
- }
22
-
23
- .header-left {
24
- display: flex;
25
- align-items: center;
26
- gap: var(--spacing-md);
27
- }
28
-
29
- .dashboard-title {
30
- font-size: 20px;
31
- font-weight: 600;
32
- color: var(--text-primary);
33
- display: flex;
34
- align-items: center;
35
- gap: var(--spacing-sm);
36
- }
37
-
38
- .header-right {
39
- display: flex;
40
- align-items: center;
41
- gap: var(--spacing-md);
42
- }
43
-
44
- .connection-indicator {
45
- display: flex;
46
- align-items: center;
47
- gap: var(--spacing-sm);
48
- padding: var(--spacing-xs) var(--spacing-sm);
49
- background: var(--bg-tertiary);
50
- border-radius: var(--radius-sm);
51
- font-size: 12px;
52
- }
53
-
54
- .connection-indicator .status-dot {
55
- width: 8px;
56
- height: 8px;
57
- border-radius: 50%;
58
- background: var(--text-muted);
59
- animation: pulse 2s ease-in-out infinite;
60
- }
61
-
62
- .connection-indicator.connected .status-dot {
63
- background: var(--accent-green);
64
- }
65
-
66
- .connection-indicator.disconnected .status-dot {
67
- background: var(--accent-red);
68
- animation: none;
69
- }
70
-
71
- /* ============ 統計摘要 ============ */
72
-
73
- .stats-summary {
74
- display: flex;
75
- gap: var(--spacing-md);
76
- padding: var(--spacing-lg);
77
- flex-wrap: wrap;
78
- }
79
-
80
- .stat-card {
81
- flex: 1;
82
- min-width: 150px;
83
- display: flex;
84
- align-items: center;
85
- gap: var(--spacing-md);
86
- padding: var(--spacing-md) var(--spacing-lg);
87
- background: var(--bg-secondary);
88
- border: 1px solid var(--border-color);
89
- border-radius: var(--radius-md);
90
- transition: all 0.2s ease;
91
- }
92
-
93
- .stat-card:hover {
94
- border-color: var(--accent-blue);
95
- transform: translateY(-2px);
96
- box-shadow: var(--shadow-md);
97
- }
98
-
99
- .stat-icon {
100
- font-size: 32px;
101
- }
102
-
103
- .stat-info {
104
- display: flex;
105
- flex-direction: column;
106
- }
107
-
108
- .stat-value {
109
- font-size: 24px;
110
- font-weight: 700;
111
- color: var(--text-primary);
112
- }
113
-
114
- .stat-label {
115
- font-size: 12px;
116
- color: var(--text-secondary);
117
- }
118
-
119
- /* ============ 專案容器 ============ */
120
-
121
- .projects-container {
122
- padding: 0 var(--spacing-lg);
123
- }
124
-
125
- .projects-header {
126
- display: flex;
127
- justify-content: space-between;
128
- align-items: center;
129
- margin-bottom: var(--spacing-md);
130
- }
131
-
132
- .section-title {
133
- font-size: 16px;
134
- font-weight: 600;
135
- color: var(--text-primary);
136
- display: flex;
137
- align-items: center;
138
- gap: var(--spacing-sm);
139
- }
140
-
141
- .filter-controls {
142
- display: flex;
143
- gap: var(--spacing-sm);
144
- }
145
-
146
- .search-input {
147
- padding: var(--spacing-sm) var(--spacing-md);
148
- background: var(--bg-tertiary);
149
- border: 1px solid var(--border-color);
150
- border-radius: var(--radius-sm);
151
- color: var(--text-primary);
152
- font-size: 13px;
153
- width: 200px;
154
- transition: all 0.2s ease;
155
- }
156
-
157
- .search-input:focus {
158
- outline: none;
159
- border-color: var(--accent-blue);
160
- }
161
-
162
- .search-input::placeholder {
163
- color: var(--text-muted);
164
- }
165
-
166
- /* ============ 專案卡片網格 ============ */
167
-
168
- .projects-grid {
169
- display: grid;
170
- grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
171
- gap: var(--spacing-md);
172
- }
173
-
174
- /* ============ 專案卡片 ============ */
175
-
176
- .project-card {
177
- background: var(--bg-secondary);
178
- border: 1px solid var(--border-color);
179
- border-radius: var(--radius-md);
180
- overflow: hidden;
181
- cursor: pointer;
182
- transition: all 0.3s ease;
183
- opacity: 1;
184
- transform: translateY(0);
185
- }
186
-
187
- /* 淡入動畫 */
188
- .project-card.fade-in {
189
- animation: projectFadeIn 0.3s ease forwards;
190
- }
191
-
192
- /* 淡出動畫 */
193
- .project-card.fade-out {
194
- animation: projectFadeOut 0.3s ease forwards;
195
- }
196
-
197
- @keyframes projectFadeIn {
198
- from {
199
- opacity: 0;
200
- transform: translateY(-10px);
201
- }
202
- to {
203
- opacity: 1;
204
- transform: translateY(0);
205
- }
206
- }
207
-
208
- @keyframes projectFadeOut {
209
- from {
210
- opacity: 1;
211
- transform: translateY(0);
212
- }
213
- to {
214
- opacity: 0;
215
- transform: translateY(-10px);
216
- }
217
- }
218
-
219
- .project-card:hover {
220
- border-color: var(--accent-blue);
221
- transform: translateY(-2px);
222
- box-shadow: var(--shadow-md);
223
- }
224
-
225
- .project-card.has-active {
226
- border-left: 3px solid var(--accent-green);
227
- }
228
-
229
- .project-card-header {
230
- display: flex;
231
- justify-content: space-between;
232
- align-items: flex-start;
233
- padding: var(--spacing-md);
234
- background: var(--bg-tertiary);
235
- transition: background 0.2s ease;
236
- border-bottom: 1px solid var(--border-color);
237
- }
238
-
239
- .project-name {
240
- font-size: 15px;
241
- font-weight: 600;
242
- color: var(--text-primary);
243
- display: flex;
244
- align-items: center;
245
- gap: var(--spacing-sm);
246
- }
247
-
248
- .project-name .icon {
249
- font-size: 16px;
250
- }
251
-
252
- .project-badge {
253
- padding: 2px 8px;
254
- border-radius: var(--radius-sm);
255
- font-size: 11px;
256
- font-weight: 600;
257
- }
258
-
259
- .project-badge.active {
260
- background: rgba(78, 201, 176, 0.2);
261
- color: var(--accent-green);
262
- }
263
-
264
- .project-badge.idle {
265
- background: rgba(150, 150, 150, 0.2);
266
- color: var(--text-secondary);
267
- }
268
-
269
- .project-card-body {
270
- padding: var(--spacing-md);
271
- }
272
-
273
- .project-path {
274
- font-size: 11px;
275
- color: var(--text-muted);
276
- margin-bottom: var(--spacing-sm);
277
- white-space: nowrap;
278
- overflow: hidden;
279
- text-overflow: ellipsis;
280
- }
281
-
282
- .project-stats {
283
- display: flex;
284
- gap: var(--spacing-md);
285
- margin-bottom: var(--spacing-sm);
286
- }
287
-
288
- .project-stat {
289
- display: flex;
290
- align-items: center;
291
- gap: var(--spacing-xs);
292
- font-size: 12px;
293
- color: var(--text-secondary);
294
- transition: all 0.2s ease;
295
- }
296
-
297
- .project-stat .value {
298
- font-weight: 600;
299
- color: var(--text-primary);
300
- transition: color 0.2s ease;
301
- }
302
-
303
- .project-stat.active .value {
304
- color: var(--accent-green);
305
- }
306
-
307
- .project-sessions {
308
- border-top: 1px solid var(--border-color);
309
- padding-top: var(--spacing-sm);
310
- margin-top: var(--spacing-sm);
311
- }
312
-
313
- .session-list {
314
- display: flex;
315
- flex-direction: column;
316
- gap: var(--spacing-xs);
317
- max-height: 120px;
318
- overflow-y: auto;
319
- }
320
-
321
- .session-item {
322
- display: flex;
323
- justify-content: space-between;
324
- align-items: center;
325
- padding: var(--spacing-xs) var(--spacing-sm);
326
- background: var(--bg-primary);
327
- border-radius: var(--radius-sm);
328
- font-size: 11px;
329
- transition: background 0.2s ease;
330
- }
331
-
332
- .session-item:hover {
333
- background: var(--bg-hover);
334
- }
335
-
336
- .session-item.active {
337
- border-left: 2px solid var(--accent-green);
338
- }
339
-
340
- .session-item.timeout {
341
- opacity: 0.6;
342
- }
343
-
344
- .session-summary {
345
- flex: 1;
346
- white-space: nowrap;
347
- overflow: hidden;
348
- text-overflow: ellipsis;
349
- color: var(--text-primary);
350
- }
351
-
352
- .session-status {
353
- padding: 1px 6px;
354
- border-radius: var(--radius-sm);
355
- font-size: 10px;
356
- font-weight: 600;
357
- }
358
-
359
- .session-status.waiting {
360
- background: rgba(255, 152, 0, 0.2);
361
- color: #ff9800;
362
- }
363
-
364
- .session-status.active {
365
- background: rgba(78, 201, 176, 0.2);
366
- color: var(--accent-green);
367
- }
368
-
369
- .session-status.completed {
370
- background: rgba(0, 122, 204, 0.2);
371
- color: var(--accent-blue);
372
- }
373
-
374
- .session-status.timeout {
375
- background: rgba(244, 135, 113, 0.2);
376
- color: var(--accent-red);
377
- }
378
-
379
- /* ============ Loading & Empty States ============ */
380
-
381
- .loading-placeholder {
382
- grid-column: 1 / -1;
383
- display: flex;
384
- flex-direction: column;
385
- align-items: center;
386
- justify-content: center;
387
- padding: var(--spacing-xl);
388
- color: var(--text-secondary);
389
- }
390
-
391
- .loading-placeholder .icon {
392
- font-size: 48px;
393
- animation: pulse 1.5s ease-in-out infinite;
394
- }
395
-
396
- .empty-state {
397
- display: flex;
398
- flex-direction: column;
399
- align-items: center;
400
- justify-content: center;
401
- padding: var(--spacing-xl);
402
- text-align: center;
403
- color: var(--text-secondary);
404
- }
405
-
406
- .empty-icon {
407
- font-size: 64px;
408
- margin-bottom: var(--spacing-md);
409
- }
410
-
411
- .empty-state h3 {
412
- font-size: 18px;
413
- font-weight: 600;
414
- color: var(--text-primary);
415
- margin-bottom: var(--spacing-sm);
416
- }
417
-
418
- .empty-state p {
419
- font-size: 13px;
420
- color: var(--text-muted);
421
- }
422
-
423
- /* ============ 響應式設計 ============ */
424
-
425
- @media (max-width: 768px) {
426
- .dashboard-header {
427
- flex-direction: column;
428
- gap: var(--spacing-md);
429
- }
430
-
431
- .header-left,
432
- .header-right {
433
- width: 100%;
434
- justify-content: center;
435
- }
436
-
437
- .stats-summary {
438
- flex-direction: column;
439
- }
440
-
441
- .stat-card {
442
- min-width: 100%;
443
- }
444
-
445
- .projects-grid {
446
- grid-template-columns: 1fr;
447
- }
448
-
449
- .projects-header {
450
- flex-direction: column;
451
- gap: var(--spacing-sm);
452
- align-items: flex-start;
453
- }
454
-
455
- .search-input {
456
- width: 100%;
457
- }
458
- }
459
-
460
- /* ============ 動畫 ============ */
461
-
462
- @keyframes fadeIn {
463
- from {
464
- opacity: 0;
465
- transform: translateY(10px);
466
- }
467
- to {
468
- opacity: 1;
469
- transform: translateY(0);
470
- }
471
- }
472
-
473
- .project-card {
474
- animation: fadeIn 0.3s ease;
475
- }
476
-
477
- /* ============ 滾動條樣式 ============ */
478
-
479
- .session-list::-webkit-scrollbar {
480
- width: 6px;
481
- }
482
-
483
- .session-list::-webkit-scrollbar-track {
484
- background: var(--bg-primary);
485
- border-radius: 3px;
486
- }
487
-
488
- .session-list::-webkit-scrollbar-thumb {
489
- background: var(--border-color);
490
- border-radius: 3px;
491
- }
492
-
493
- .session-list::-webkit-scrollbar-thumb:hover {
494
- background: var(--text-muted);
495
- }
1
+ /* ============ Dashboard 專用樣式 ============ */
2
+
3
+ .dashboard-body {
4
+ overflow-y: auto;
5
+ min-height: 100vh;
6
+ padding-bottom: 60px;
7
+ }
8
+
9
+ /* ============ Dashboard Header ============ */
10
+
11
+ .dashboard-header {
12
+ display: flex;
13
+ justify-content: space-between;
14
+ align-items: center;
15
+ padding: var(--spacing-md) var(--spacing-lg);
16
+ background: var(--bg-secondary);
17
+ border-bottom: 1px solid var(--border-color);
18
+ position: sticky;
19
+ top: 0;
20
+ z-index: 100;
21
+ }
22
+
23
+ .header-left {
24
+ display: flex;
25
+ align-items: center;
26
+ gap: var(--spacing-md);
27
+ }
28
+
29
+ .dashboard-title {
30
+ font-size: 20px;
31
+ font-weight: 600;
32
+ color: var(--text-primary);
33
+ display: flex;
34
+ align-items: center;
35
+ gap: var(--spacing-sm);
36
+ }
37
+
38
+ .header-right {
39
+ display: flex;
40
+ align-items: center;
41
+ gap: var(--spacing-md);
42
+ }
43
+
44
+ .connection-indicator {
45
+ display: flex;
46
+ align-items: center;
47
+ gap: var(--spacing-sm);
48
+ padding: var(--spacing-xs) var(--spacing-sm);
49
+ background: var(--bg-tertiary);
50
+ border-radius: var(--radius-sm);
51
+ font-size: 12px;
52
+ }
53
+
54
+ .connection-indicator .status-dot {
55
+ width: 8px;
56
+ height: 8px;
57
+ border-radius: 50%;
58
+ background: var(--text-muted);
59
+ animation: pulse 2s ease-in-out infinite;
60
+ }
61
+
62
+ .connection-indicator.connected .status-dot {
63
+ background: var(--accent-green);
64
+ }
65
+
66
+ .connection-indicator.disconnected .status-dot {
67
+ background: var(--accent-red);
68
+ animation: none;
69
+ }
70
+
71
+ /* ============ 統計摘要 ============ */
72
+
73
+ .stats-summary {
74
+ display: flex;
75
+ gap: var(--spacing-md);
76
+ padding: var(--spacing-lg);
77
+ flex-wrap: wrap;
78
+ }
79
+
80
+ .stat-card {
81
+ flex: 1;
82
+ min-width: 150px;
83
+ display: flex;
84
+ align-items: center;
85
+ gap: var(--spacing-md);
86
+ padding: var(--spacing-md) var(--spacing-lg);
87
+ background: var(--bg-secondary);
88
+ border: 1px solid var(--border-color);
89
+ border-radius: var(--radius-md);
90
+ transition: all 0.2s ease;
91
+ }
92
+
93
+ .stat-card:hover {
94
+ border-color: var(--accent-blue);
95
+ transform: translateY(-2px);
96
+ box-shadow: var(--shadow-md);
97
+ }
98
+
99
+ .stat-icon {
100
+ font-size: 32px;
101
+ }
102
+
103
+ .stat-info {
104
+ display: flex;
105
+ flex-direction: column;
106
+ }
107
+
108
+ .stat-value {
109
+ font-size: 24px;
110
+ font-weight: 700;
111
+ color: var(--text-primary);
112
+ }
113
+
114
+ .stat-label {
115
+ font-size: 12px;
116
+ color: var(--text-secondary);
117
+ }
118
+
119
+ /* ============ 專案容器 ============ */
120
+
121
+ .projects-container {
122
+ padding: 0 var(--spacing-lg);
123
+ }
124
+
125
+ .projects-header {
126
+ display: flex;
127
+ justify-content: space-between;
128
+ align-items: center;
129
+ margin-bottom: var(--spacing-md);
130
+ }
131
+
132
+ .section-title {
133
+ font-size: 16px;
134
+ font-weight: 600;
135
+ color: var(--text-primary);
136
+ display: flex;
137
+ align-items: center;
138
+ gap: var(--spacing-sm);
139
+ }
140
+
141
+ .filter-controls {
142
+ display: flex;
143
+ gap: var(--spacing-sm);
144
+ }
145
+
146
+ .search-input {
147
+ padding: var(--spacing-sm) var(--spacing-md);
148
+ background: var(--bg-tertiary);
149
+ border: 1px solid var(--border-color);
150
+ border-radius: var(--radius-sm);
151
+ color: var(--text-primary);
152
+ font-size: 13px;
153
+ width: 200px;
154
+ transition: all 0.2s ease;
155
+ }
156
+
157
+ .search-input:focus {
158
+ outline: none;
159
+ border-color: var(--accent-blue);
160
+ }
161
+
162
+ .search-input::placeholder {
163
+ color: var(--text-muted);
164
+ }
165
+
166
+ /* ============ 專案卡片網格 ============ */
167
+
168
+ .projects-grid {
169
+ display: grid;
170
+ grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
171
+ gap: var(--spacing-md);
172
+ }
173
+
174
+ /* ============ 專案卡片 ============ */
175
+
176
+ .project-card {
177
+ background: var(--bg-secondary);
178
+ border: 1px solid var(--border-color);
179
+ border-radius: var(--radius-md);
180
+ overflow: hidden;
181
+ cursor: pointer;
182
+ transition: all 0.3s ease;
183
+ opacity: 1;
184
+ transform: translateY(0);
185
+ }
186
+
187
+ /* 淡入動畫 */
188
+ .project-card.fade-in {
189
+ animation: projectFadeIn 0.3s ease forwards;
190
+ }
191
+
192
+ /* 淡出動畫 */
193
+ .project-card.fade-out {
194
+ animation: projectFadeOut 0.3s ease forwards;
195
+ }
196
+
197
+ @keyframes projectFadeIn {
198
+ from {
199
+ opacity: 0;
200
+ transform: translateY(-10px);
201
+ }
202
+ to {
203
+ opacity: 1;
204
+ transform: translateY(0);
205
+ }
206
+ }
207
+
208
+ @keyframes projectFadeOut {
209
+ from {
210
+ opacity: 1;
211
+ transform: translateY(0);
212
+ }
213
+ to {
214
+ opacity: 0;
215
+ transform: translateY(-10px);
216
+ }
217
+ }
218
+
219
+ .project-card:hover {
220
+ border-color: var(--accent-blue);
221
+ transform: translateY(-2px);
222
+ box-shadow: var(--shadow-md);
223
+ }
224
+
225
+ .project-card.has-active {
226
+ border-left: 3px solid var(--accent-green);
227
+ }
228
+
229
+ .project-card-header {
230
+ display: flex;
231
+ justify-content: space-between;
232
+ align-items: flex-start;
233
+ padding: var(--spacing-md);
234
+ background: var(--bg-tertiary);
235
+ transition: background 0.2s ease;
236
+ border-bottom: 1px solid var(--border-color);
237
+ }
238
+
239
+ .project-name {
240
+ font-size: 15px;
241
+ font-weight: 600;
242
+ color: var(--text-primary);
243
+ display: flex;
244
+ align-items: center;
245
+ gap: var(--spacing-sm);
246
+ }
247
+
248
+ .project-name .icon {
249
+ font-size: 16px;
250
+ }
251
+
252
+ .project-badge {
253
+ padding: 2px 8px;
254
+ border-radius: var(--radius-sm);
255
+ font-size: 11px;
256
+ font-weight: 600;
257
+ }
258
+
259
+ .project-badge.active {
260
+ background: rgba(78, 201, 176, 0.2);
261
+ color: var(--accent-green);
262
+ }
263
+
264
+ .project-badge.idle {
265
+ background: rgba(150, 150, 150, 0.2);
266
+ color: var(--text-secondary);
267
+ }
268
+
269
+ .project-card-body {
270
+ padding: var(--spacing-md);
271
+ }
272
+
273
+ .project-path {
274
+ font-size: 11px;
275
+ color: var(--text-muted);
276
+ margin-bottom: var(--spacing-sm);
277
+ white-space: nowrap;
278
+ overflow: hidden;
279
+ text-overflow: ellipsis;
280
+ }
281
+
282
+ .project-stats {
283
+ display: flex;
284
+ gap: var(--spacing-md);
285
+ margin-bottom: var(--spacing-sm);
286
+ }
287
+
288
+ .project-stat {
289
+ display: flex;
290
+ align-items: center;
291
+ gap: var(--spacing-xs);
292
+ font-size: 12px;
293
+ color: var(--text-secondary);
294
+ transition: all 0.2s ease;
295
+ }
296
+
297
+ .project-stat .value {
298
+ font-weight: 600;
299
+ color: var(--text-primary);
300
+ transition: color 0.2s ease;
301
+ }
302
+
303
+ .project-stat.active .value {
304
+ color: var(--accent-green);
305
+ }
306
+
307
+ .project-sessions {
308
+ border-top: 1px solid var(--border-color);
309
+ padding-top: var(--spacing-sm);
310
+ margin-top: var(--spacing-sm);
311
+ }
312
+
313
+ .session-list {
314
+ display: flex;
315
+ flex-direction: column;
316
+ gap: var(--spacing-xs);
317
+ max-height: 120px;
318
+ overflow-y: auto;
319
+ }
320
+
321
+ .session-item {
322
+ display: flex;
323
+ justify-content: space-between;
324
+ align-items: center;
325
+ padding: var(--spacing-xs) var(--spacing-sm);
326
+ background: var(--bg-primary);
327
+ border-radius: var(--radius-sm);
328
+ font-size: 11px;
329
+ transition: background 0.2s ease;
330
+ }
331
+
332
+ .session-item:hover {
333
+ background: var(--bg-hover);
334
+ }
335
+
336
+ .session-item.active {
337
+ border-left: 2px solid var(--accent-green);
338
+ }
339
+
340
+ .session-item.timeout {
341
+ opacity: 0.6;
342
+ }
343
+
344
+ .session-summary {
345
+ flex: 1;
346
+ white-space: nowrap;
347
+ overflow: hidden;
348
+ text-overflow: ellipsis;
349
+ color: var(--text-primary);
350
+ }
351
+
352
+ .session-status {
353
+ padding: 1px 6px;
354
+ border-radius: var(--radius-sm);
355
+ font-size: 10px;
356
+ font-weight: 600;
357
+ }
358
+
359
+ .session-status.waiting {
360
+ background: rgba(255, 152, 0, 0.2);
361
+ color: #ff9800;
362
+ }
363
+
364
+ .session-status.active {
365
+ background: rgba(78, 201, 176, 0.2);
366
+ color: var(--accent-green);
367
+ }
368
+
369
+ .session-status.completed {
370
+ background: rgba(0, 122, 204, 0.2);
371
+ color: var(--accent-blue);
372
+ }
373
+
374
+ .session-status.timeout {
375
+ background: rgba(244, 135, 113, 0.2);
376
+ color: var(--accent-red);
377
+ }
378
+
379
+ /* ============ Loading & Empty States ============ */
380
+
381
+ .loading-placeholder {
382
+ grid-column: 1 / -1;
383
+ display: flex;
384
+ flex-direction: column;
385
+ align-items: center;
386
+ justify-content: center;
387
+ padding: var(--spacing-xl);
388
+ color: var(--text-secondary);
389
+ }
390
+
391
+ .loading-placeholder .icon {
392
+ font-size: 48px;
393
+ animation: pulse 1.5s ease-in-out infinite;
394
+ }
395
+
396
+ .empty-state {
397
+ display: flex;
398
+ flex-direction: column;
399
+ align-items: center;
400
+ justify-content: center;
401
+ padding: var(--spacing-xl);
402
+ text-align: center;
403
+ color: var(--text-secondary);
404
+ }
405
+
406
+ .empty-icon {
407
+ font-size: 64px;
408
+ margin-bottom: var(--spacing-md);
409
+ }
410
+
411
+ .empty-state h3 {
412
+ font-size: 18px;
413
+ font-weight: 600;
414
+ color: var(--text-primary);
415
+ margin-bottom: var(--spacing-sm);
416
+ }
417
+
418
+ .empty-state p {
419
+ font-size: 13px;
420
+ color: var(--text-muted);
421
+ }
422
+
423
+ /* ============ 響應式設計 ============ */
424
+
425
+ @media (max-width: 768px) {
426
+ .dashboard-header {
427
+ flex-direction: column;
428
+ gap: var(--spacing-md);
429
+ }
430
+
431
+ .header-left,
432
+ .header-right {
433
+ width: 100%;
434
+ justify-content: center;
435
+ }
436
+
437
+ .stats-summary {
438
+ flex-direction: column;
439
+ }
440
+
441
+ .stat-card {
442
+ min-width: 100%;
443
+ }
444
+
445
+ .projects-grid {
446
+ grid-template-columns: 1fr;
447
+ }
448
+
449
+ .projects-header {
450
+ flex-direction: column;
451
+ gap: var(--spacing-sm);
452
+ align-items: flex-start;
453
+ }
454
+
455
+ .search-input {
456
+ width: 100%;
457
+ }
458
+ }
459
+
460
+ /* ============ 動畫 ============ */
461
+
462
+ @keyframes fadeIn {
463
+ from {
464
+ opacity: 0;
465
+ transform: translateY(10px);
466
+ }
467
+ to {
468
+ opacity: 1;
469
+ transform: translateY(0);
470
+ }
471
+ }
472
+
473
+ .project-card {
474
+ animation: fadeIn 0.3s ease;
475
+ }
476
+
477
+ /* ============ 滾動條樣式 ============ */
478
+
479
+ .session-list::-webkit-scrollbar {
480
+ width: 6px;
481
+ }
482
+
483
+ .session-list::-webkit-scrollbar-track {
484
+ background: var(--bg-primary);
485
+ border-radius: 3px;
486
+ }
487
+
488
+ .session-list::-webkit-scrollbar-thumb {
489
+ background: var(--border-color);
490
+ border-radius: 3px;
491
+ }
492
+
493
+ .session-list::-webkit-scrollbar-thumb:hover {
494
+ background: var(--text-muted);
495
+ }