git-watchtower 1.10.1 → 1.10.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,917 @@
1
+ /**
2
+ * CSS styles for the Git Watchtower web dashboard.
3
+ * @module server/web-ui/css
4
+ */
5
+
6
+ /**
7
+ * Get the dashboard CSS.
8
+ * @returns {string} CSS content (without style tags)
9
+ */
10
+ function getDashboardCss() {
11
+ return `
12
+ :root {
13
+ --bg: #0d1117;
14
+ --bg-surface: #161b22;
15
+ --bg-surface-hover: #1c2129;
16
+ --bg-surface-active: #252c35;
17
+ --border: #30363d;
18
+ --border-subtle: #21262d;
19
+ --text: #e6edf3;
20
+ --text-dim: #8b949e;
21
+ --text-muted: #484f58;
22
+ --accent: #58a6ff;
23
+ --accent-dim: #1f6feb;
24
+ --green: #3fb950;
25
+ --green-dim: #238636;
26
+ --red: #f85149;
27
+ --red-dim: #da3633;
28
+ --yellow: #d29922;
29
+ --cyan: #39d2c0;
30
+ --magenta: #bc8cff;
31
+ --orange: #db6d28;
32
+ --sparkline: #58a6ff;
33
+ --header-bg: linear-gradient(135deg, #0550ae 0%, #0969da 100%);
34
+ --radius: 8px;
35
+ --radius-sm: 4px;
36
+ --font: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, sans-serif;
37
+ --font-mono: 'SF Mono', 'Fira Code', 'Fira Mono', 'Roboto Mono', Consolas, monospace;
38
+ --shadow-sm: 0 1px 2px rgba(0,0,0,0.3);
39
+ --shadow-md: 0 4px 12px rgba(0,0,0,0.4);
40
+ --shadow-lg: 0 8px 24px rgba(0,0,0,0.5);
41
+ --merged-text: #484f58;
42
+ --merged-bg: rgba(72,79,88,0.06);
43
+ }
44
+
45
+ * { margin: 0; padding: 0; box-sizing: border-box; }
46
+
47
+ body {
48
+ font-family: var(--font);
49
+ background: var(--bg);
50
+ color: var(--text);
51
+ line-height: 1.5;
52
+ overflow: hidden;
53
+ height: 100vh;
54
+ }
55
+
56
+ /* ── Header ────────────────────────────────────────────────────── */
57
+ .header {
58
+ background: var(--header-bg);
59
+ padding: 14px 24px;
60
+ display: flex;
61
+ align-items: center;
62
+ justify-content: space-between;
63
+ border-bottom: 1px solid rgba(255,255,255,0.08);
64
+ user-select: none;
65
+ box-shadow: 0 1px 8px rgba(0,0,0,0.3);
66
+ position: relative;
67
+ z-index: 10;
68
+ }
69
+ .header-left {
70
+ display: flex;
71
+ align-items: center;
72
+ gap: 14px;
73
+ }
74
+ .header-title {
75
+ font-size: 15px;
76
+ font-weight: 700;
77
+ color: #fff;
78
+ letter-spacing: -0.2px;
79
+ }
80
+ .header-version {
81
+ font-size: 11px;
82
+ color: rgba(255,255,255,0.4);
83
+ font-weight: 500;
84
+ }
85
+ .header-project {
86
+ font-size: 13px;
87
+ font-weight: 600;
88
+ color: rgba(255,255,255,0.95);
89
+ background: rgba(255,255,255,0.12);
90
+ padding: 3px 12px;
91
+ border-radius: var(--radius-sm);
92
+ backdrop-filter: blur(4px);
93
+ border: 1px solid rgba(255,255,255,0.08);
94
+ }
95
+ .header-right {
96
+ display: flex;
97
+ align-items: center;
98
+ gap: 12px;
99
+ }
100
+ .badge {
101
+ font-size: 10px;
102
+ font-weight: 700;
103
+ padding: 3px 10px;
104
+ border-radius: 10px;
105
+ text-transform: uppercase;
106
+ letter-spacing: 0.8px;
107
+ }
108
+ .badge-online { background: var(--green-dim); color: #fff; box-shadow: 0 0 8px rgba(63,185,80,0.3); }
109
+ .badge-offline { background: var(--red-dim); color: #fff; box-shadow: 0 0 8px rgba(248,81,73,0.3); }
110
+ .badge-fetching { background: var(--yellow); color: #000; }
111
+
112
+ /* ── Layout ────────────────────────────────────────────────────── */
113
+ .layout {
114
+ display: grid;
115
+ grid-template-columns: 1fr 320px;
116
+ grid-template-rows: 1fr auto;
117
+ height: calc(100vh - 49px);
118
+ min-height: 0;
119
+ gap: 0;
120
+ }
121
+
122
+ /* ── Branch List ───────────────────────────────────────────────── */
123
+ .branch-panel {
124
+ display: flex;
125
+ flex-direction: column;
126
+ overflow: hidden;
127
+ }
128
+ .panel-header {
129
+ padding: 12px 20px;
130
+ font-size: 10px;
131
+ font-weight: 700;
132
+ text-transform: uppercase;
133
+ letter-spacing: 1.2px;
134
+ color: var(--text-muted);
135
+ border-bottom: 1px solid var(--border);
136
+ background: var(--bg-surface);
137
+ display: flex;
138
+ align-items: center;
139
+ justify-content: space-between;
140
+ }
141
+ .branch-count {
142
+ color: var(--text-muted);
143
+ font-weight: 400;
144
+ }
145
+ .branch-list {
146
+ flex: 1;
147
+ overflow-y: auto;
148
+ scrollbar-width: thin;
149
+ scrollbar-color: var(--border) transparent;
150
+ }
151
+ .branch-list::-webkit-scrollbar { width: 6px; }
152
+ .branch-list::-webkit-scrollbar-track { background: transparent; }
153
+ .branch-list::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
154
+
155
+ .branch-item {
156
+ display: grid;
157
+ grid-template-columns: 24px 1fr auto;
158
+ align-items: center;
159
+ padding: 10px 20px;
160
+ border-bottom: 1px solid var(--border-subtle);
161
+ border-left: 2px solid transparent;
162
+ cursor: pointer;
163
+ transition: background 0.15s, opacity 0.15s, border-color 0.15s;
164
+ }
165
+ .branch-item:hover { background: var(--bg-surface-hover); }
166
+ .branch-item.selected { background: var(--bg-surface-active); border-left-color: var(--accent); }
167
+ .branch-item.selected .branch-name { color: var(--accent); }
168
+ .branch-item.current {
169
+ background: rgba(63,185,80,0.06);
170
+ border-left-color: var(--green);
171
+ }
172
+ .branch-item.current:hover { background: rgba(63,185,80,0.10); }
173
+ .branch-item.current.selected { border-left-color: var(--green); background: rgba(63,185,80,0.10); }
174
+ .branch-item.current .branch-name { color: var(--green); font-weight: 600; }
175
+ .branch-item.merged { opacity: 0.45; }
176
+ .branch-item.merged:hover { opacity: 0.7; }
177
+ .branch-item.merged .branch-name { color: var(--text-muted); }
178
+
179
+ .branch-cursor {
180
+ font-size: 9px;
181
+ color: var(--accent);
182
+ opacity: 0;
183
+ transition: opacity 0.15s;
184
+ filter: drop-shadow(0 0 3px var(--accent));
185
+ }
186
+ .branch-item.selected .branch-cursor { opacity: 1; }
187
+ .branch-current-icon {
188
+ font-size: 10px;
189
+ color: var(--green);
190
+ filter: drop-shadow(0 0 4px rgba(63,185,80,0.6));
191
+ }
192
+ .branch-item.current .branch-cursor { display: none; }
193
+ .branch-item.current.selected .branch-current-icon { display: none; }
194
+ .branch-item.current.selected .branch-cursor { display: inline; opacity: 1; }
195
+
196
+ .branch-info {
197
+ min-width: 0;
198
+ display: flex;
199
+ flex-direction: column;
200
+ gap: 2px;
201
+ }
202
+ .branch-name-row {
203
+ display: flex;
204
+ align-items: center;
205
+ gap: 8px;
206
+ }
207
+ .branch-name {
208
+ font-family: var(--font-mono);
209
+ font-size: 13px;
210
+ font-weight: 500;
211
+ white-space: nowrap;
212
+ overflow: hidden;
213
+ text-overflow: ellipsis;
214
+ }
215
+ .branch-current-badge {
216
+ font-size: 10px;
217
+ color: var(--green);
218
+ background: rgba(63,185,80,0.15);
219
+ padding: 0 6px;
220
+ border-radius: var(--radius-sm);
221
+ font-weight: 600;
222
+ flex-shrink: 0;
223
+ }
224
+ .branch-new-badge {
225
+ font-size: 10px;
226
+ color: var(--yellow);
227
+ background: rgba(210,153,34,0.15);
228
+ padding: 0 6px;
229
+ border-radius: var(--radius-sm);
230
+ font-weight: 600;
231
+ flex-shrink: 0;
232
+ }
233
+ .branch-deleted-badge {
234
+ font-size: 10px;
235
+ color: var(--red);
236
+ background: rgba(248,81,73,0.15);
237
+ padding: 0 6px;
238
+ border-radius: var(--radius-sm);
239
+ font-weight: 600;
240
+ flex-shrink: 0;
241
+ }
242
+ .branch-updated-badge {
243
+ font-size: 10px;
244
+ color: var(--cyan);
245
+ background: rgba(57,210,192,0.15);
246
+ padding: 0 6px;
247
+ border-radius: var(--radius-sm);
248
+ font-weight: 600;
249
+ flex-shrink: 0;
250
+ }
251
+ .branch-meta {
252
+ font-size: 11px;
253
+ color: var(--text-dim);
254
+ display: flex;
255
+ align-items: center;
256
+ gap: 10px;
257
+ }
258
+ .branch-commit {
259
+ font-family: var(--font-mono);
260
+ color: var(--text-muted);
261
+ font-size: 11px;
262
+ }
263
+ .branch-subject {
264
+ white-space: nowrap;
265
+ overflow: hidden;
266
+ text-overflow: ellipsis;
267
+ max-width: 300px;
268
+ }
269
+ .branch-right {
270
+ display: flex;
271
+ flex-direction: column;
272
+ align-items: flex-end;
273
+ gap: 4px;
274
+ padding-left: 16px;
275
+ flex-shrink: 0;
276
+ min-width: 60px;
277
+ }
278
+ .branch-time-row {
279
+ display: flex;
280
+ align-items: center;
281
+ gap: 6px;
282
+ justify-content: flex-end;
283
+ }
284
+ .branch-badges {
285
+ display: flex;
286
+ gap: 4px;
287
+ justify-content: flex-end;
288
+ flex-wrap: wrap;
289
+ }
290
+ .branch-time {
291
+ font-size: 12px;
292
+ font-family: var(--font-mono);
293
+ color: var(--text-dim);
294
+ white-space: nowrap;
295
+ font-weight: 500;
296
+ letter-spacing: -0.3px;
297
+ }
298
+ .sparkline-bar {
299
+ display: flex;
300
+ align-items: flex-end;
301
+ gap: 1px;
302
+ height: 16px;
303
+ }
304
+ .spark-bar {
305
+ width: 4px;
306
+ border-radius: 1px;
307
+ background: var(--sparkline);
308
+ transition: height 0.3s;
309
+ min-height: 1px;
310
+ }
311
+
312
+ .branch-diff {
313
+ display: flex;
314
+ gap: 6px;
315
+ font-size: 11px;
316
+ font-family: var(--font-mono);
317
+ justify-content: flex-end;
318
+ text-align: right;
319
+ white-space: nowrap;
320
+ }
321
+ .diff-added { color: var(--green); }
322
+ .diff-deleted { color: var(--red); }
323
+ .diff-label { color: var(--text-muted); font-size: 10px; }
324
+
325
+ .pr-badge {
326
+ font-size: 10px;
327
+ padding: 1px 6px;
328
+ border-radius: var(--radius-sm);
329
+ font-weight: 600;
330
+ flex-shrink: 0;
331
+ }
332
+ .pr-open { color: var(--green); background: rgba(63,185,80,0.15); }
333
+ .pr-merged { color: var(--magenta); background: rgba(188,140,255,0.15); }
334
+ .pr-closed { color: var(--red); background: rgba(248,81,73,0.15); }
335
+
336
+ /* ── Side Panel ────────────────────────────────────────────────── */
337
+ .side-panel {
338
+ display: flex;
339
+ flex-direction: column;
340
+ overflow: hidden;
341
+ background: var(--bg-surface);
342
+ border-left: 1px solid var(--border);
343
+ box-shadow: -2px 0 8px rgba(0,0,0,0.15);
344
+ }
345
+
346
+ /* ── Activity Log ──────────────────────────────────────────────── */
347
+ .activity-log {
348
+ flex: 1;
349
+ overflow-y: auto;
350
+ scrollbar-width: thin;
351
+ scrollbar-color: var(--border) transparent;
352
+ }
353
+ .log-entry {
354
+ padding: 6px 16px;
355
+ font-size: 12px;
356
+ border-bottom: 1px solid var(--border-subtle);
357
+ display: flex;
358
+ gap: 8px;
359
+ align-items: flex-start;
360
+ }
361
+ .log-dot {
362
+ width: 6px;
363
+ height: 6px;
364
+ border-radius: 50%;
365
+ margin-top: 6px;
366
+ flex-shrink: 0;
367
+ }
368
+ .log-dot.info { background: var(--accent); }
369
+ .log-dot.success { background: var(--green); }
370
+ .log-dot.warning { background: var(--yellow); }
371
+ .log-dot.error { background: var(--red); }
372
+ .log-dot.update { background: var(--cyan); }
373
+ .log-text {
374
+ color: var(--text-dim);
375
+ line-height: 1.4;
376
+ word-break: break-word;
377
+ }
378
+ .log-time {
379
+ color: var(--text-muted);
380
+ font-size: 10px;
381
+ font-family: var(--font-mono);
382
+ flex-shrink: 0;
383
+ margin-left: auto;
384
+ padding-left: 8px;
385
+ }
386
+
387
+ /* ── Search Overlay ────────────────────────────────────────────── */
388
+ .search-bar {
389
+ display: none;
390
+ padding: 8px 16px;
391
+ background: var(--bg-surface);
392
+ border-bottom: 1px solid var(--border);
393
+ }
394
+ .search-bar.active { display: flex; }
395
+ .search-input {
396
+ width: 100%;
397
+ background: var(--bg);
398
+ border: 1px solid var(--border);
399
+ color: var(--text);
400
+ font-family: var(--font-mono);
401
+ font-size: 13px;
402
+ padding: 6px 12px;
403
+ border-radius: var(--radius-sm);
404
+ outline: none;
405
+ }
406
+ .search-input:focus { border-color: var(--accent); }
407
+
408
+ /* ── Footer ────────────────────────────────────────────────────── */
409
+ .footer {
410
+ grid-column: 1 / -1;
411
+ padding: 8px 20px;
412
+ background: var(--bg-surface);
413
+ border-top: 1px solid var(--border);
414
+ font-size: 11px;
415
+ color: var(--text-muted);
416
+ display: flex;
417
+ gap: 14px;
418
+ flex-wrap: wrap;
419
+ user-select: none;
420
+ }
421
+ .footer kbd {
422
+ display: inline-block;
423
+ background: var(--bg);
424
+ border: 1px solid var(--border);
425
+ border-radius: 3px;
426
+ padding: 0 5px;
427
+ font-family: var(--font-mono);
428
+ font-size: 10px;
429
+ color: var(--text-dim);
430
+ line-height: 18px;
431
+ margin-right: 2px;
432
+ box-shadow: 0 1px 0 var(--border);
433
+ }
434
+
435
+ /* ── Flash Message ─────────────────────────────────────────────── */
436
+ .flash {
437
+ position: fixed;
438
+ top: 60px;
439
+ left: 50%;
440
+ transform: translateX(-50%);
441
+ padding: 8px 20px;
442
+ border-radius: var(--radius);
443
+ font-size: 13px;
444
+ font-weight: 500;
445
+ z-index: 100;
446
+ opacity: 0;
447
+ transition: opacity 0.3s;
448
+ pointer-events: none;
449
+ }
450
+ .flash.visible { opacity: 1; }
451
+ .flash.info { background: var(--accent-dim); color: #fff; }
452
+ .flash.success { background: var(--green-dim); color: #fff; }
453
+ .flash.warning { background: var(--yellow); color: #000; }
454
+ .flash.error { background: var(--red-dim); color: #fff; }
455
+ .flash.update { background: var(--cyan); color: #000; }
456
+
457
+
458
+ /* ── Connection indicator ──────────────────────────────────────── */
459
+ .connection-dot {
460
+ width: 8px;
461
+ height: 8px;
462
+ border-radius: 50%;
463
+ display: inline-block;
464
+ }
465
+ .connection-dot.connected { background: var(--green); box-shadow: 0 0 6px rgba(63,185,80,0.5), 0 0 2px var(--green); }
466
+ .connection-dot.disconnected { background: var(--red); box-shadow: 0 0 6px rgba(248,81,73,0.5), 0 0 2px var(--red); animation: pulse-dot 2s ease-in-out infinite; }
467
+ @keyframes pulse-dot { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } }
468
+
469
+ /* ── Empty state ───────────────────────────────────────────────── */
470
+ .empty-state {
471
+ display: flex;
472
+ flex-direction: column;
473
+ align-items: center;
474
+ justify-content: center;
475
+ height: 200px;
476
+ color: var(--text-muted);
477
+ font-size: 13px;
478
+ }
479
+ .empty-state-icon { font-size: 32px; margin-bottom: 12px; opacity: 0.5; }
480
+
481
+ /* ── Tab Bar ───────────────────────────────────────────────────── */
482
+ .tab-bar {
483
+ display: none;
484
+ background: var(--bg-surface);
485
+ border-bottom: 1px solid var(--border);
486
+ padding: 0 16px;
487
+ gap: 2px;
488
+ overflow-x: auto;
489
+ scrollbar-width: none;
490
+ flex-shrink: 0;
491
+ align-items: stretch;
492
+ box-shadow: inset 0 -1px 0 var(--border);
493
+ }
494
+ .tab-bar::-webkit-scrollbar { display: none; }
495
+ .tab-bar.visible { display: flex; }
496
+ .tab {
497
+ padding: 10px 20px 9px;
498
+ font-size: 13px;
499
+ font-weight: 500;
500
+ color: var(--text-muted);
501
+ cursor: pointer;
502
+ border-bottom: 2px solid transparent;
503
+ white-space: nowrap;
504
+ transition: color 0.15s, border-color 0.15s, background 0.15s;
505
+ user-select: none;
506
+ position: relative;
507
+ border-radius: var(--radius-sm) var(--radius-sm) 0 0;
508
+ }
509
+ .tab:hover { color: var(--text-dim); background: rgba(255,255,255,0.03); }
510
+ .tab.active {
511
+ color: var(--text);
512
+ font-weight: 600;
513
+ border-bottom-color: var(--accent);
514
+ background: var(--bg);
515
+ }
516
+ .tab .tab-dot {
517
+ display: inline-block;
518
+ width: 7px;
519
+ height: 7px;
520
+ border-radius: 50%;
521
+ margin-right: 8px;
522
+ background: var(--green);
523
+ box-shadow: 0 0 4px rgba(63,185,80,0.4);
524
+ }
525
+ .tab .tab-number {
526
+ font-size: 10px;
527
+ color: var(--text-muted);
528
+ margin-left: 6px;
529
+ font-family: var(--font-mono);
530
+ opacity: 0.6;
531
+ }
532
+ .tab.active .tab-number { color: var(--accent); opacity: 0.8; }
533
+
534
+ /* ── Confirm Dialog ────────────────────────────────────────────── */
535
+ .confirm-overlay {
536
+ display: none;
537
+ position: fixed;
538
+ inset: 0;
539
+ background: rgba(0,0,0,0.6);
540
+ z-index: 200;
541
+ justify-content: center;
542
+ align-items: center;
543
+ }
544
+ .confirm-overlay.active { display: flex; }
545
+ .confirm-box {
546
+ background: var(--bg-surface);
547
+ border: 1px solid var(--border);
548
+ border-radius: var(--radius);
549
+ padding: 28px;
550
+ min-width: 360px;
551
+ max-width: 480px;
552
+ box-shadow: var(--shadow-lg);
553
+ }
554
+ .confirm-title {
555
+ font-size: 15px;
556
+ font-weight: 600;
557
+ color: var(--text);
558
+ margin-bottom: 8px;
559
+ }
560
+ .confirm-message {
561
+ font-size: 13px;
562
+ color: var(--text-dim);
563
+ margin-bottom: 20px;
564
+ line-height: 1.5;
565
+ }
566
+ .confirm-actions {
567
+ display: flex;
568
+ gap: 8px;
569
+ justify-content: flex-end;
570
+ }
571
+ .confirm-btn {
572
+ padding: 6px 16px;
573
+ border-radius: var(--radius-sm);
574
+ border: 1px solid var(--border);
575
+ font-size: 13px;
576
+ font-weight: 500;
577
+ cursor: pointer;
578
+ background: var(--bg);
579
+ color: var(--text);
580
+ transition: background 0.15s;
581
+ }
582
+ .confirm-btn:hover { background: var(--bg-surface-hover); }
583
+ .confirm-btn.primary {
584
+ background: var(--accent-dim);
585
+ border-color: var(--accent-dim);
586
+ color: #fff;
587
+ }
588
+ .confirm-btn.primary:hover { background: var(--accent); }
589
+ .confirm-btn.danger {
590
+ background: var(--red-dim);
591
+ border-color: var(--red-dim);
592
+ color: #fff;
593
+ }
594
+ .confirm-btn.danger:hover { background: var(--red); }
595
+
596
+ /* ── Toast Notifications ───────────────────────────────────────── */
597
+ .toast-container {
598
+ position: fixed;
599
+ bottom: 60px;
600
+ right: 20px;
601
+ z-index: 150;
602
+ display: flex;
603
+ flex-direction: column-reverse;
604
+ gap: 8px;
605
+ pointer-events: none;
606
+ }
607
+ .toast {
608
+ padding: 10px 16px;
609
+ border-radius: var(--radius);
610
+ font-size: 13px;
611
+ font-weight: 500;
612
+ pointer-events: auto;
613
+ opacity: 0;
614
+ transform: translateX(20px);
615
+ transition: opacity 0.3s, transform 0.3s;
616
+ max-width: 360px;
617
+ display: flex;
618
+ align-items: center;
619
+ gap: 8px;
620
+ border: 1px solid;
621
+ }
622
+ .toast.visible { opacity: 1; transform: translateX(0); }
623
+ .toast.success { background: rgba(35,134,54,0.9); border-color: var(--green); color: #fff; }
624
+ .toast.error { background: rgba(218,54,51,0.9); border-color: var(--red); color: #fff; }
625
+ .toast.info { background: rgba(31,111,235,0.9); border-color: var(--accent); color: #fff; }
626
+ .toast.warning { background: rgba(210,153,34,0.9); border-color: var(--yellow); color: #000; }
627
+ .toast-icon { font-size: 14px; flex-shrink: 0; }
628
+ .toast-action {
629
+ cursor: pointer;
630
+ text-decoration: underline;
631
+ font-weight: 600;
632
+ margin-left: 4px;
633
+ opacity: 0.9;
634
+ }
635
+ .toast-action:hover { opacity: 1; }
636
+
637
+ /* ── Modal Overlay (shared) ──────────────────────────────────── */
638
+ .modal-overlay {
639
+ display: none;
640
+ position: fixed;
641
+ inset: 0;
642
+ background: rgba(0,0,0,0.6);
643
+ z-index: 200;
644
+ justify-content: center;
645
+ align-items: center;
646
+ }
647
+ .modal-overlay.active { display: flex; }
648
+ .modal-box {
649
+ background: var(--bg-surface);
650
+ border: 1px solid var(--border);
651
+ border-radius: var(--radius);
652
+ padding: 24px;
653
+ min-width: 400px;
654
+ max-width: 600px;
655
+ max-height: 80vh;
656
+ overflow-y: auto;
657
+ box-shadow: var(--shadow-lg);
658
+ }
659
+ .modal-title {
660
+ font-size: 15px;
661
+ font-weight: 600;
662
+ color: var(--text);
663
+ margin-bottom: 16px;
664
+ display: flex;
665
+ align-items: center;
666
+ gap: 8px;
667
+ }
668
+ .modal-close {
669
+ margin-left: auto;
670
+ background: none;
671
+ border: none;
672
+ color: var(--text-muted);
673
+ cursor: pointer;
674
+ font-size: 16px;
675
+ padding: 4px 8px;
676
+ }
677
+ .modal-close:hover { color: var(--text); }
678
+
679
+ /* ── Log Viewer ──────────────────────────────────────────────── */
680
+ .log-viewer-tabs {
681
+ display: flex;
682
+ gap: 2px;
683
+ margin-bottom: 12px;
684
+ border-bottom: 1px solid var(--border);
685
+ }
686
+ .log-viewer-tab {
687
+ padding: 6px 14px;
688
+ font-size: 12px;
689
+ font-weight: 500;
690
+ color: var(--text-muted);
691
+ cursor: pointer;
692
+ border-bottom: 2px solid transparent;
693
+ background: none;
694
+ border-top: none;
695
+ border-left: none;
696
+ border-right: none;
697
+ }
698
+ .log-viewer-tab:hover { color: var(--text-dim); }
699
+ .log-viewer-tab.active { color: var(--text); border-bottom-color: var(--accent); }
700
+ .log-viewer-content {
701
+ font-family: var(--font-mono);
702
+ font-size: 12px;
703
+ line-height: 1.6;
704
+ max-height: 400px;
705
+ overflow-y: auto;
706
+ background: var(--bg);
707
+ border: 1px solid var(--border);
708
+ border-radius: var(--radius-sm);
709
+ padding: 12px;
710
+ scrollbar-width: thin;
711
+ scrollbar-color: var(--border) transparent;
712
+ }
713
+ .log-line { padding: 1px 0; white-space: pre-wrap; word-break: break-all; }
714
+ .log-line.error { color: var(--red); }
715
+ .log-line .log-ts { color: var(--text-muted); margin-right: 8px; }
716
+
717
+ /* ── Branch Action Modal ─────────────────────────────────────── */
718
+ .action-list {
719
+ display: flex;
720
+ flex-direction: column;
721
+ gap: 4px;
722
+ }
723
+ .action-item {
724
+ display: flex;
725
+ align-items: center;
726
+ gap: 10px;
727
+ padding: 8px 12px;
728
+ border-radius: var(--radius-sm);
729
+ cursor: pointer;
730
+ color: var(--text);
731
+ font-size: 13px;
732
+ background: none;
733
+ border: 1px solid transparent;
734
+ text-align: left;
735
+ width: 100%;
736
+ transition: background 0.15s, border-color 0.15s;
737
+ }
738
+ .action-item:hover { background: var(--bg-surface-hover); border-color: var(--border); }
739
+ .action-item .action-icon { font-size: 14px; width: 20px; text-align: center; flex-shrink: 0; }
740
+ .action-item .action-label { flex: 1; }
741
+ .action-item .action-kbd {
742
+ font-family: var(--font-mono);
743
+ font-size: 10px;
744
+ color: var(--text-muted);
745
+ background: var(--bg);
746
+ border: 1px solid var(--border);
747
+ border-radius: 3px;
748
+ padding: 1px 6px;
749
+ }
750
+ .action-item.disabled { opacity: 0.4; cursor: not-allowed; }
751
+
752
+ /* ── Info Panel ──────────────────────────────────────────────── */
753
+ .info-grid {
754
+ display: grid;
755
+ grid-template-columns: auto 1fr;
756
+ gap: 6px 16px;
757
+ font-size: 13px;
758
+ }
759
+ .info-label { color: var(--text-muted); font-weight: 500; }
760
+ .info-value { color: var(--text); font-family: var(--font-mono); }
761
+
762
+ /* ── Session Stats (footer) ──────────────────────────────────── */
763
+ .stats-bar {
764
+ display: flex;
765
+ gap: 16px;
766
+ align-items: center;
767
+ font-size: 11px;
768
+ color: var(--text-muted);
769
+ font-family: var(--font-mono);
770
+ flex-wrap: wrap;
771
+ }
772
+ .stats-bar .stat-item {
773
+ display: flex;
774
+ align-items: center;
775
+ gap: 4px;
776
+ }
777
+ .stats-bar .stat-value { color: var(--text-dim); font-weight: 600; }
778
+ .stats-bar .stat-label { font-family: var(--font); }
779
+
780
+ /* ── Cleanup Modal ───────────────────────────────────────────── */
781
+ .cleanup-branch-list {
782
+ display: flex;
783
+ flex-direction: column;
784
+ gap: 4px;
785
+ margin: 12px 0;
786
+ max-height: 200px;
787
+ overflow-y: auto;
788
+ }
789
+ .cleanup-branch-item {
790
+ display: flex;
791
+ align-items: center;
792
+ gap: 8px;
793
+ padding: 6px 10px;
794
+ font-family: var(--font-mono);
795
+ font-size: 12px;
796
+ color: var(--text-dim);
797
+ background: var(--bg);
798
+ border-radius: var(--radius-sm);
799
+ border: 1px solid var(--border-subtle);
800
+ }
801
+ .cleanup-branch-icon { color: var(--red); font-size: 10px; }
802
+
803
+ /* ── Update Modal ────────────────────────────────────────────── */
804
+ .update-info {
805
+ font-size: 13px;
806
+ color: var(--text-dim);
807
+ margin-bottom: 16px;
808
+ line-height: 1.5;
809
+ }
810
+ .update-versions {
811
+ display: flex;
812
+ align-items: center;
813
+ gap: 12px;
814
+ margin-bottom: 16px;
815
+ font-family: var(--font-mono);
816
+ font-size: 13px;
817
+ }
818
+ .update-versions .old-version { color: var(--text-muted); }
819
+ .update-versions .arrow { color: var(--text-muted); }
820
+ .update-versions .new-version { color: var(--green); font-weight: 600; }
821
+ .update-progress {
822
+ font-size: 12px;
823
+ color: var(--yellow);
824
+ font-style: italic;
825
+ }
826
+
827
+ /* ── Clickable Links ────────────────────────────────────────── */
828
+ .branch-name a, .branch-commit a, .pr-badge a {
829
+ color: inherit;
830
+ text-decoration: none;
831
+ transition: color 0.15s, text-decoration 0.15s;
832
+ }
833
+ .branch-name a:hover { text-decoration: underline; color: var(--accent); }
834
+ .branch-commit a:hover { text-decoration: underline; color: var(--yellow); }
835
+ .pr-badge a:hover { text-decoration: underline; }
836
+
837
+ /* ── Copy to Clipboard Button ───────────────────────────────── */
838
+ .copy-btn {
839
+ display: inline-flex;
840
+ align-items: center;
841
+ justify-content: center;
842
+ width: 20px;
843
+ height: 20px;
844
+ border: none;
845
+ background: none;
846
+ color: var(--text-muted);
847
+ cursor: pointer;
848
+ border-radius: var(--radius-sm);
849
+ font-size: 11px;
850
+ opacity: 0;
851
+ transition: opacity 0.15s, background 0.15s, color 0.15s;
852
+ flex-shrink: 0;
853
+ padding: 0;
854
+ vertical-align: middle;
855
+ }
856
+ .branch-item:hover .copy-btn,
857
+ .copy-btn:focus { opacity: 0.7; }
858
+ .copy-btn:hover { opacity: 1; background: var(--bg-surface-active); color: var(--text); }
859
+ .copy-btn.copied { color: var(--green); opacity: 1; }
860
+
861
+ /* ── Notification Permission Button ─────────────────────────── */
862
+ .notif-btn {
863
+ font-size: 11px;
864
+ padding: 3px 10px;
865
+ border-radius: 10px;
866
+ border: 1px solid var(--border);
867
+ background: var(--bg);
868
+ color: var(--text-dim);
869
+ cursor: pointer;
870
+ text-transform: uppercase;
871
+ letter-spacing: 0.5px;
872
+ font-weight: 600;
873
+ transition: background 0.15s, border-color 0.15s;
874
+ }
875
+ .notif-btn:hover { background: var(--bg-surface-hover); border-color: var(--accent); }
876
+ .notif-btn.granted { background: var(--green-dim); color: #fff; border-color: var(--green-dim); cursor: default; }
877
+ .notif-btn.denied { background: var(--red-dim); color: #fff; border-color: var(--red-dim); cursor: default; opacity: 0.6; }
878
+
879
+ /* ── Sidebar Toggle ─────────────────────────────────────────── */
880
+ .sidebar-toggle {
881
+ background: none;
882
+ border: none;
883
+ color: var(--text-muted);
884
+ cursor: pointer;
885
+ font-size: 12px;
886
+ padding: 2px 6px;
887
+ border-radius: var(--radius-sm);
888
+ transition: color 0.15s, background 0.15s;
889
+ }
890
+ .sidebar-toggle:hover { color: var(--text); background: var(--bg-surface-hover); }
891
+
892
+ /* ── Collapsed sidebar ──────────────────────────────────────── */
893
+ .layout.sidebar-collapsed { grid-template-columns: 1fr 0px; }
894
+ .layout.sidebar-collapsed .side-panel { display: none; }
895
+
896
+
897
+ /* ── Preferences bar in footer ──────────────────────────────── */
898
+ .pref-btn {
899
+ background: none;
900
+ border: 1px solid var(--border);
901
+ color: var(--text-muted);
902
+ cursor: pointer;
903
+ font-size: 10px;
904
+ padding: 1px 8px;
905
+ border-radius: var(--radius-sm);
906
+ font-family: var(--font);
907
+ transition: background 0.15s, color 0.15s, border-color 0.15s;
908
+ }
909
+ .pref-btn:hover { background: var(--bg-surface-hover); color: var(--text-dim); border-color: var(--text-muted); }
910
+ .pref-btn.active { background: var(--accent-dim); color: #fff; border-color: var(--accent-dim); }
911
+
912
+ @media (max-width: 900px) {
913
+ }
914
+ `;
915
+ }
916
+
917
+ module.exports = { getDashboardCss };