@youtyan/code-viewer 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/web/style.css ADDED
@@ -0,0 +1,1584 @@
1
+ /* git-diff-preview — GitHub-Primer-aligned theme
2
+ * Light + dark, color tokens borrowed from GitHub Primer.
3
+ */
4
+
5
+ :root {
6
+ /* canvas */
7
+ --bg: #ffffff;
8
+ --bg-soft: #f6f8fa; /* subtle */
9
+ --bg-mute: #eaeef2; /* inset */
10
+ --bg-emph: #d0d7de;
11
+ /* borders */
12
+ --border: #d0d7de;
13
+ --border-muted: #d8dee4;
14
+ --border-strong: #afb8c1;
15
+ /* text */
16
+ --fg: #1f2328;
17
+ --fg-muted: #59636e;
18
+ --fg-subtle: #6e7781;
19
+ --fg-onemphasis: #ffffff;
20
+ /* accent */
21
+ --accent: #0969da;
22
+ --accent-emph: #0550ae;
23
+ --accent-subtle: #ddf4ff;
24
+ --accent-muted: #54aeff66;
25
+ /* success / danger / attention / done */
26
+ --success: #1a7f37;
27
+ --success-emph: #1f883d;
28
+ --danger: #cf222e;
29
+ --danger-emph: #cf222e;
30
+ --attn: #9a6700;
31
+ --done: #8250df;
32
+ /* diff colors (GitHub exact) */
33
+ --diff-add-bg: #dafbe1;
34
+ --diff-add-num-bg: #ccffd8;
35
+ --diff-add-word-bg: #aceebb;
36
+ --diff-del-bg: #ffebe9;
37
+ --diff-del-num-bg: #ffd7d5;
38
+ --diff-del-word-bg: #ff818266;
39
+ --diff-hunk-bg: #ddf4ff;
40
+ --diff-hunk-fg: #0550ae;
41
+ /* sizing */
42
+ --topbar-h: 56px;
43
+ --sidebar-w: 308px;
44
+ /* shadows */
45
+ --shadow-sm: 0 1px 0 rgba(31,35,40,0.04);
46
+ --shadow-md: 0 3px 6px rgba(140,149,159,0.15);
47
+ }
48
+
49
+ [data-theme="dark"] {
50
+ --bg: #0d1117;
51
+ --bg-soft: #161b22;
52
+ --bg-mute: #21262d;
53
+ --bg-emph: #30363d;
54
+ --border: #30363d;
55
+ --border-muted: #21262d;
56
+ --border-strong: #6e7681;
57
+ --fg: #e6edf3;
58
+ --fg-muted: #9198a1;
59
+ --fg-subtle: #6e7681;
60
+ --fg-onemphasis: #ffffff;
61
+ --accent: #2f81f7;
62
+ --accent-emph: #1f6feb;
63
+ --accent-subtle: rgba(56,139,253,0.10);
64
+ --accent-muted: rgba(56,139,253,0.40);
65
+ --success: #3fb950;
66
+ --success-emph: #238636;
67
+ --danger: #f85149;
68
+ --danger-emph: #da3633;
69
+ --attn: #d29922;
70
+ --done: #a371f7;
71
+ --diff-add-bg: rgba(46,160,67,0.15);
72
+ --diff-add-num-bg: rgba(46,160,67,0.30);
73
+ --diff-add-word-bg: rgba(46,160,67,0.40);
74
+ --diff-del-bg: rgba(248,81,73,0.15);
75
+ --diff-del-num-bg: rgba(248,81,73,0.30);
76
+ --diff-del-word-bg: rgba(248,81,73,0.40);
77
+ --diff-hunk-bg: rgba(56,139,253,0.10);
78
+ --diff-hunk-fg: #58a6ff;
79
+ }
80
+
81
+ /* ===== Reset / base ===== */
82
+ *, *::before, *::after { box-sizing: border-box; }
83
+ html, body {
84
+ margin: 0; padding: 0;
85
+ background: var(--bg); color: var(--fg);
86
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans",
87
+ Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
88
+ font-size: 14px;
89
+ line-height: 1.5;
90
+ /* GitHub uses subpixel rendering (the macOS default) on the diff page,
91
+ * which renders text slightly thicker than -webkit-font-smoothing:antialiased */
92
+ -webkit-font-smoothing: auto;
93
+ -moz-osx-font-smoothing: auto;
94
+ }
95
+
96
+ /* Window scrolls; topbar + sidebar are fixed */
97
+ #app { display: block; }
98
+
99
+ /* ===== Topbar ===== */
100
+ #topbar {
101
+ position: fixed;
102
+ top: 0; left: 0; right: 0;
103
+ height: var(--topbar-h);
104
+ display: flex;
105
+ align-items: center;
106
+ gap: 14px;
107
+ padding: 0 16px;
108
+ background: var(--bg);
109
+ border-bottom: 1px solid var(--border);
110
+ z-index: 50;
111
+ }
112
+ .brand {
113
+ display: flex; align-items: center; gap: 8px;
114
+ font-weight: 600;
115
+ font-size: 14px;
116
+ color: var(--fg);
117
+ }
118
+ .brand .dot {
119
+ width: 8px; height: 8px; border-radius: 50%;
120
+ background: var(--accent);
121
+ }
122
+ .brand .title { letter-spacing: -0.005em; }
123
+
124
+ #meta {
125
+ display: flex; align-items: center; gap: 10px;
126
+ color: var(--fg-muted);
127
+ font-size: 12px;
128
+ }
129
+ #meta .ref {
130
+ display: inline-flex; align-items: center; gap: 4px;
131
+ background: var(--bg-soft);
132
+ border: 1px solid var(--border);
133
+ border-radius: 999px;
134
+ padding: 3px 9px;
135
+ color: var(--fg);
136
+ font-family: "Monaspace Neon", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
137
+ font-size: 11px;
138
+ line-height: 1;
139
+ white-space: nowrap;
140
+ }
141
+ #meta .num {
142
+ display: inline-flex; gap: 8px;
143
+ font-variant-numeric: tabular-nums;
144
+ font-size: 12px;
145
+ }
146
+ #meta .num .add { color: var(--success); font-weight: 600; }
147
+ #meta .num .del { color: var(--danger); font-weight: 600; }
148
+ #meta .updated-at {
149
+ display: inline-flex;
150
+ align-items: center;
151
+ gap: 4px;
152
+ color: var(--fg-muted);
153
+ background: var(--bg-soft);
154
+ border: 1px solid var(--border-muted);
155
+ border-radius: 999px;
156
+ padding: 3px 8px;
157
+ font-size: 11px;
158
+ line-height: 1;
159
+ font-variant-numeric: tabular-nums;
160
+ white-space: nowrap;
161
+ }
162
+ .ref-pickers {
163
+ display: flex;
164
+ align-items: center;
165
+ gap: 4px;
166
+ margin-left: 8px;
167
+ }
168
+ .ref-input {
169
+ background: var(--bg-soft);
170
+ border: 1px solid var(--border);
171
+ color: var(--fg);
172
+ border-radius: 6px;
173
+ font-family: "Monaspace Neon", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
174
+ font-size: 12px;
175
+ padding: 4px 8px;
176
+ width: 130px;
177
+ height: 26px;
178
+ outline: none;
179
+ transition: border-color 0.12s, box-shadow 0.12s, background 0.12s;
180
+ }
181
+ .ref-input::placeholder { color: var(--fg-subtle); }
182
+ .ref-input:focus {
183
+ background: var(--bg);
184
+ border-color: var(--accent);
185
+ box-shadow: 0 0 0 3px var(--accent-muted);
186
+ }
187
+ .ref-dots {
188
+ color: var(--fg-subtle);
189
+ font-size: 14px;
190
+ padding: 0 2px;
191
+ user-select: none;
192
+ }
193
+ .ref-pickers > button {
194
+ width: 24px; height: 26px;
195
+ border: 1px solid var(--border);
196
+ background: var(--bg);
197
+ color: var(--fg-muted);
198
+ border-radius: 6px;
199
+ cursor: pointer;
200
+ font-size: 13px;
201
+ transition: background 0.12s, color 0.12s;
202
+ }
203
+ .ref-pickers > button:hover {
204
+ background: var(--accent);
205
+ color: #fff;
206
+ border-color: var(--accent);
207
+ }
208
+ #ref-reset:hover { background: var(--bg-mute); color: var(--danger); border-color: var(--danger); }
209
+ #reload-prom {
210
+ width: 28px; height: 26px;
211
+ font-size: 14px;
212
+ margin-left: 6px;
213
+ background: var(--accent);
214
+ color: #fff;
215
+ border-color: var(--accent);
216
+ }
217
+ #reload-prom:hover { background: var(--accent-emph); border-color: var(--accent-emph); }
218
+ #reload-prom.spinning { animation: gdp-spin 0.7s linear infinite; }
219
+ @keyframes gdp-spin { to { transform: rotate(360deg); } }
220
+ #auto-reload {
221
+ height: 26px; padding: 0 8px;
222
+ font-size: 11px; font-weight: 600;
223
+ letter-spacing: 0.04em;
224
+ width: auto;
225
+ border: 1px solid var(--border);
226
+ background: var(--bg);
227
+ color: var(--fg-muted);
228
+ border-radius: 6px;
229
+ cursor: pointer;
230
+ }
231
+ #auto-reload:hover { background: var(--bg-soft); color: var(--fg); }
232
+ #auto-reload.active {
233
+ background: #2da44e;
234
+ color: #fff;
235
+ border-color: #2da44e;
236
+ animation: gdp-auto-pulse 2.4s ease-in-out infinite;
237
+ }
238
+ @keyframes gdp-auto-pulse {
239
+ 0%, 100% { box-shadow: 0 0 0 0 rgba(46, 164, 78, 0.45); }
240
+ 50% { box-shadow: 0 0 0 4px rgba(46, 164, 78, 0); }
241
+ }
242
+ #hide-tests {
243
+ width: auto !important;
244
+ padding: 0 8px;
245
+ font-size: 11px;
246
+ font-weight: 600;
247
+ letter-spacing: 0.04em;
248
+ }
249
+ #hide-tests.active {
250
+ background: var(--attn);
251
+ color: #fff;
252
+ border-color: var(--attn);
253
+ }
254
+ .hidden-by-tests { display: none !important; }
255
+
256
+ /* ===== Ref picker popover ===== */
257
+ #ref-popover[hidden] { display: none !important; }
258
+ #ref-popover {
259
+ position: fixed;
260
+ z-index: 80;
261
+ width: 560px;
262
+ max-width: 90vw;
263
+ max-height: min(640px, 75vh);
264
+ background: var(--bg);
265
+ border: 1px solid var(--border);
266
+ border-radius: 8px;
267
+ box-shadow: 0 12px 28px rgba(31,35,40,0.20);
268
+ display: flex;
269
+ flex-direction: column;
270
+ overflow: hidden;
271
+ }
272
+
273
+ /* Quick-fill chips for the most common refs */
274
+ .rp-quick {
275
+ display: flex;
276
+ gap: 6px;
277
+ padding: 8px 10px 0;
278
+ background: var(--bg-soft);
279
+ }
280
+ .rp-chip {
281
+ flex: 1;
282
+ background: var(--bg);
283
+ border: 1px solid var(--border);
284
+ color: var(--fg);
285
+ border-radius: 6px;
286
+ padding: 5px 10px;
287
+ font: inherit;
288
+ font-size: 12px;
289
+ font-family: "Monaspace Neon", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
290
+ font-weight: 600;
291
+ cursor: pointer;
292
+ transition: background 0.10s, color 0.10s, border-color 0.10s;
293
+ }
294
+ .rp-chip:hover {
295
+ background: var(--accent);
296
+ color: #fff;
297
+ border-color: var(--accent);
298
+ }
299
+
300
+ /* Tab bar */
301
+ .rp-tabs {
302
+ display: flex;
303
+ background: var(--bg-soft);
304
+ border-bottom: 1px solid var(--border);
305
+ padding: 0 6px;
306
+ }
307
+ .rp-tab {
308
+ background: transparent;
309
+ border: 0;
310
+ color: var(--fg-muted);
311
+ padding: 9px 14px 8px;
312
+ font: inherit;
313
+ font-size: 12px;
314
+ font-weight: 500;
315
+ cursor: pointer;
316
+ border-bottom: 2px solid transparent;
317
+ margin-bottom: -1px;
318
+ transition: color 0.12s, border-color 0.12s;
319
+ }
320
+ .rp-tab:hover { color: var(--fg); }
321
+ .rp-tab.active {
322
+ color: var(--accent);
323
+ border-bottom-color: var(--accent);
324
+ }
325
+
326
+ .rp-search-wrap {
327
+ padding: 8px;
328
+ border-bottom: 1px solid var(--border);
329
+ background: var(--bg);
330
+ }
331
+ .rp-search {
332
+ width: 100%;
333
+ background: var(--bg-soft);
334
+ border: 1px solid var(--border);
335
+ color: var(--fg);
336
+ border-radius: 6px;
337
+ padding: 6px 10px;
338
+ font: inherit;
339
+ font-size: 12px;
340
+ outline: none;
341
+ }
342
+ .rp-search:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-muted); }
343
+ .rp-body { overflow-y: auto; padding: 4px 0 8px; flex: 1; }
344
+
345
+ /* Commit item — two-line layout, plenty of room for time/author */
346
+ .rp-item-commit {
347
+ display: block;
348
+ padding: 8px 14px;
349
+ cursor: pointer;
350
+ border-left: 2px solid transparent;
351
+ transition: background 0.10s, border-color 0.10s;
352
+ }
353
+ .rp-item-commit:hover {
354
+ background: var(--bg-mute);
355
+ border-left-color: var(--accent);
356
+ }
357
+ .rp-item-commit .row1 {
358
+ display: flex;
359
+ align-items: baseline;
360
+ gap: 10px;
361
+ margin-bottom: 2px;
362
+ }
363
+ .rp-item-commit .sha {
364
+ font-family: "Monaspace Neon", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
365
+ font-size: 12px;
366
+ color: var(--accent);
367
+ font-weight: 600;
368
+ flex-shrink: 0;
369
+ width: 60px;
370
+ }
371
+ .rp-item-commit .subject {
372
+ flex: 1;
373
+ overflow: hidden;
374
+ text-overflow: ellipsis;
375
+ white-space: nowrap;
376
+ color: var(--fg);
377
+ font-size: 12.5px;
378
+ }
379
+ .rp-item-commit .row2 {
380
+ display: flex;
381
+ gap: 10px;
382
+ font-size: 11px;
383
+ color: var(--fg-subtle);
384
+ padding-left: 70px;
385
+ }
386
+ .rp-item-commit .author {
387
+ font-weight: 500;
388
+ color: var(--fg-muted);
389
+ }
390
+ .rp-item-commit .when { color: var(--fg-subtle); }
391
+
392
+ /* Branch / tag / special items */
393
+ .rp-item-ref {
394
+ display: flex;
395
+ align-items: center;
396
+ gap: 10px;
397
+ padding: 7px 14px;
398
+ cursor: pointer;
399
+ border-left: 2px solid transparent;
400
+ transition: background 0.10s, border-color 0.10s;
401
+ font-size: 12.5px;
402
+ }
403
+ .rp-item-ref:hover {
404
+ background: var(--bg-mute);
405
+ border-left-color: var(--accent);
406
+ }
407
+ .rp-item-ref .name {
408
+ font-family: "Monaspace Neon", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
409
+ flex: 1;
410
+ overflow: hidden;
411
+ text-overflow: ellipsis;
412
+ white-space: nowrap;
413
+ color: var(--fg);
414
+ }
415
+ .rp-item-ref .badge {
416
+ font-size: 10px;
417
+ font-weight: 600;
418
+ text-transform: uppercase;
419
+ letter-spacing: 0.06em;
420
+ color: var(--fg-subtle);
421
+ background: var(--bg-mute);
422
+ padding: 2px 6px;
423
+ border-radius: 4px;
424
+ }
425
+ .rp-item-ref .badge.cur { background: var(--accent-subtle); color: var(--accent); }
426
+ .rp-item-ref .desc {
427
+ font-size: 11px;
428
+ color: var(--fg-subtle);
429
+ font-style: italic;
430
+ }
431
+ .rp-empty {
432
+ padding: 36px 14px;
433
+ text-align: center;
434
+ color: var(--fg-subtle);
435
+ font-size: 12px;
436
+ }
437
+
438
+ /* Currently-selected ref highlight (matches focused input's value) */
439
+ #ref-popover .rp-item-commit.current,
440
+ #ref-popover .rp-item-ref.current {
441
+ background: color-mix(in srgb, var(--accent) 16%, transparent);
442
+ border-left-color: var(--accent);
443
+ }
444
+ #ref-popover .rp-item-commit.current .sha,
445
+ #ref-popover .rp-item-commit.current .subject,
446
+ #ref-popover .rp-item-ref.current .name {
447
+ color: var(--accent);
448
+ font-weight: 700;
449
+ }
450
+ #ref-popover .rp-item-ref.current .badge {
451
+ background: var(--accent-subtle);
452
+ color: var(--accent-emph);
453
+ }
454
+ .rp-chip.current {
455
+ background: var(--accent);
456
+ color: #fff;
457
+ border-color: var(--accent);
458
+ }
459
+
460
+ .spacer { flex: 1; }
461
+
462
+ .controls {
463
+ display: flex; gap: 6px; align-items: center;
464
+ }
465
+ .controls input[type="search"] {
466
+ background: var(--bg);
467
+ border: 1px solid var(--border);
468
+ border-radius: 6px;
469
+ color: var(--fg);
470
+ font: inherit;
471
+ font-size: 13px;
472
+ padding: 5px 10px;
473
+ width: 220px;
474
+ outline: none;
475
+ transition: border-color 0.12s ease, box-shadow 0.12s ease;
476
+ }
477
+ .controls input[type="search"]::placeholder { color: var(--fg-subtle); }
478
+ .controls input[type="search"]:focus {
479
+ border-color: var(--accent);
480
+ box-shadow: 0 0 0 3px var(--accent-muted);
481
+ }
482
+ .seg {
483
+ display: inline-flex;
484
+ background: var(--bg);
485
+ border: 1px solid var(--border);
486
+ border-radius: 6px;
487
+ overflow: hidden;
488
+ height: 28px;
489
+ }
490
+ .seg button {
491
+ border: 0;
492
+ background: transparent;
493
+ color: var(--fg-muted);
494
+ padding: 0 11px;
495
+ cursor: pointer;
496
+ font: inherit;
497
+ font-size: 12px;
498
+ font-weight: 500;
499
+ transition: background 0.12s, color 0.12s;
500
+ }
501
+ .seg button + button { border-left: 1px solid var(--border); }
502
+ .seg button:hover { background: var(--bg-soft); color: var(--fg); }
503
+ .seg button.active {
504
+ background: var(--accent);
505
+ color: #fff;
506
+ }
507
+ .seg button.active + button,
508
+ .seg button + button.active { border-left-color: transparent; }
509
+
510
+ .controls > button {
511
+ display: inline-flex; align-items: center; justify-content: center;
512
+ width: 28px; height: 28px;
513
+ border: 1px solid var(--border);
514
+ background: var(--bg);
515
+ color: var(--fg);
516
+ border-radius: 6px;
517
+ cursor: pointer;
518
+ font-size: 13px;
519
+ transition: background 0.12s, border-color 0.12s;
520
+ }
521
+ .controls > button:hover { background: var(--bg-soft); border-color: var(--border-strong); }
522
+ .controls > button.active {
523
+ background: var(--accent);
524
+ color: #fff;
525
+ border-color: var(--accent);
526
+ }
527
+ .controls > button.active:hover { background: var(--accent-emph); border-color: var(--accent-emph); }
528
+ #ignore-ws,
529
+ #syntax-highlight {
530
+ width: auto;
531
+ padding: 0 8px;
532
+ font-size: 11px;
533
+ font-weight: 600;
534
+ letter-spacing: 0.04em;
535
+ }
536
+ #syntax-highlight.loading {
537
+ color: var(--fg-muted);
538
+ }
539
+ #reload { font-size: 14px; }
540
+ #reload.spinning { animation: gdp-spin 0.7s linear infinite; }
541
+ @keyframes gdp-spin { to { transform: rotate(360deg); } }
542
+
543
+ #status {
544
+ width: 8px; height: 8px; border-radius: 50%;
545
+ background: var(--fg-subtle);
546
+ margin-left: 4px;
547
+ transition: background 0.2s ease, box-shadow 0.2s ease;
548
+ }
549
+ #status.live { background: #2ea043; box-shadow: 0 0 0 3px rgba(46,160,67,0.20); }
550
+ #status.refreshing { background: #d29922; box-shadow: 0 0 0 3px rgba(210,153,34,0.25); }
551
+ #status.error { background: var(--danger); box-shadow: 0 0 0 3px rgba(207,34,46,0.20); }
552
+
553
+ /* ===== Top-edge loading bar (indeterminate) ===== */
554
+ #load-bar {
555
+ position: fixed;
556
+ top: var(--topbar-h);
557
+ left: 0; right: 0;
558
+ height: 2px;
559
+ z-index: 49;
560
+ pointer-events: none;
561
+ overflow: hidden;
562
+ opacity: 0;
563
+ transition: opacity 0.18s ease;
564
+ background: transparent;
565
+ }
566
+ #load-bar.active { opacity: 1; }
567
+ #load-bar::after {
568
+ content: "";
569
+ position: absolute;
570
+ left: 0; top: 0; bottom: 0;
571
+ width: 30%;
572
+ background: linear-gradient(90deg, transparent, var(--accent), transparent);
573
+ animation: gdp-loadbar 1.1s linear infinite;
574
+ }
575
+ @keyframes gdp-loadbar {
576
+ 0% { transform: translateX(-100%); }
577
+ 100% { transform: translateX(450%); }
578
+ }
579
+
580
+ /* ===== Sidebar ===== */
581
+ #sidebar {
582
+ position: fixed;
583
+ left: 0;
584
+ top: var(--topbar-h);
585
+ bottom: 0;
586
+ width: var(--sidebar-w);
587
+ background: var(--bg-soft);
588
+ border-right: 1px solid var(--border);
589
+ overflow-y: auto;
590
+ padding: 0 0 32px;
591
+ z-index: 30;
592
+ }
593
+ .sb-head {
594
+ display: flex; justify-content: space-between; align-items: center;
595
+ padding: 14px 16px 10px;
596
+ color: var(--fg);
597
+ font-size: 12px;
598
+ font-weight: 600;
599
+ position: sticky; top: 0;
600
+ background: var(--bg-soft);
601
+ border-bottom: 1px solid var(--border);
602
+ z-index: 1;
603
+ }
604
+ .sb-title { letter-spacing: 0.01em; }
605
+ #totals {
606
+ color: var(--fg-muted);
607
+ font-weight: 400;
608
+ font-variant-numeric: tabular-nums;
609
+ margin-right: auto;
610
+ margin-left: 6px;
611
+ }
612
+ .sb-view-seg { height: 22px; }
613
+ .sb-view-seg button { padding: 0 8px; font-size: 11px; }
614
+ .sb-filter-wrap {
615
+ position: sticky;
616
+ top: 36px;
617
+ background: var(--bg-soft);
618
+ padding: 6px 12px 8px;
619
+ border-bottom: 1px solid var(--border-muted);
620
+ z-index: 1;
621
+ }
622
+ #sb-filter {
623
+ width: 100%;
624
+ background: var(--bg);
625
+ border: 1px solid var(--border);
626
+ color: var(--fg);
627
+ border-radius: 6px;
628
+ font: inherit;
629
+ font-size: 12.5px;
630
+ padding: 5px 10px;
631
+ outline: none;
632
+ transition: border-color 0.12s ease, box-shadow 0.12s ease;
633
+ }
634
+ #sb-filter:focus {
635
+ border-color: var(--accent);
636
+ box-shadow: 0 0 0 3px var(--accent-muted);
637
+ }
638
+ #sb-filter::placeholder { color: var(--fg-subtle); }
639
+
640
+ /* ===== Sidebar resizer (drag right edge to resize) ===== */
641
+ #sidebar-resizer {
642
+ position: absolute;
643
+ top: 0; right: -3px;
644
+ width: 6px;
645
+ height: 100%;
646
+ cursor: col-resize;
647
+ z-index: 31;
648
+ background: transparent;
649
+ transition: background 0.12s;
650
+ }
651
+ #sidebar-resizer:hover,
652
+ body.gdp-resizing #sidebar-resizer {
653
+ background: var(--accent);
654
+ opacity: 0.5;
655
+ }
656
+
657
+ /* Lightweight preview line shown only while dragging — avoids reflowing the
658
+ * (very tall) diff content on every mousemove. */
659
+ #sidebar-resize-preview {
660
+ display: none;
661
+ position: fixed;
662
+ top: 0; bottom: 0;
663
+ width: 2px;
664
+ background: var(--accent);
665
+ z-index: 100;
666
+ pointer-events: none;
667
+ box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 25%, transparent);
668
+ }
669
+ #sidebar { position: fixed; } /* ensure relative ancestor for resizer */
670
+ body.gdp-resizing { cursor: col-resize !important; user-select: none; }
671
+ body.gdp-resizing * { user-select: none !important; }
672
+
673
+ /* ===== Tree view ===== */
674
+ #filelist.tree {
675
+ padding: 4px 0 0;
676
+ }
677
+ #filelist.tree .tree-dir {
678
+ display: flex;
679
+ align-items: center;
680
+ gap: 4px;
681
+ padding: 4px 12px 4px var(--lvl-pad, 12px);
682
+ cursor: pointer;
683
+ color: var(--fg-muted);
684
+ font-size: 12.5px;
685
+ user-select: none;
686
+ }
687
+ #filelist.tree .tree-dir:hover { background: var(--bg-mute); color: var(--fg); }
688
+ #filelist.tree .tree-dir .chev {
689
+ display: inline-block;
690
+ width: 14px; text-align: center;
691
+ font-size: 11px;
692
+ font-weight: 700;
693
+ transition: transform 0.15s, color 0.15s;
694
+ color: var(--fg-muted);
695
+ }
696
+ #filelist.tree .tree-dir.collapsed .chev { transform: rotate(-90deg); }
697
+ #filelist.tree .tree-dir:hover .chev { color: var(--accent); }
698
+ #filelist.tree .tree-dir .dir-name {
699
+ font-size: 12px;
700
+ color: var(--fg);
701
+ font-weight: 500;
702
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
703
+ }
704
+ #filelist.tree .tree-dir .dir-icon {
705
+ color: var(--accent);
706
+ flex-shrink: 0;
707
+ font-size: 12px;
708
+ width: 14px; text-align: center;
709
+ }
710
+ #filelist.tree .tree-dir.collapsed { color: var(--fg-subtle); }
711
+ #filelist.tree .tree-dir.collapsed .dir-name { color: var(--fg-muted); font-weight: 400; }
712
+ #filelist.tree .tree-children { list-style: none; padding: 0; margin: 0; }
713
+ #filelist.tree .tree-dir.collapsed + .tree-children { display: none; }
714
+
715
+ #filelist.tree .tree-file {
716
+ display: grid;
717
+ grid-template-columns: 16px 1fr auto;
718
+ align-items: center;
719
+ gap: 8px;
720
+ padding: 4px 12px 4px var(--lvl-pad, 12px);
721
+ cursor: pointer;
722
+ font-size: 12.5px;
723
+ color: var(--fg);
724
+ border-left: 2px solid transparent;
725
+ transition: background 0.10s, border-color 0.10s;
726
+ }
727
+ #filelist.tree .tree-file:hover { background: var(--bg-mute); }
728
+ #filelist.tree .tree-file.active {
729
+ background: var(--accent-subtle);
730
+ border-left-color: var(--accent);
731
+ }
732
+ #filelist.tree .tree-file.hidden,
733
+ #filelist.tree .tree-dir.hidden { display: none; }
734
+ #filelist.tree .tree-file .name {
735
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
736
+ font-size: 12.5px;
737
+ }
738
+ #filelist.tree .tree-file .stat {
739
+ display: inline-flex; align-items: center; gap: 6px;
740
+ font-size: 11px;
741
+ font-variant-numeric: tabular-nums;
742
+ }
743
+ #filelist.tree .tree-file .stat .a { color: var(--success); }
744
+ #filelist.tree .tree-file .stat .d { color: var(--danger); }
745
+ #filelist { list-style: none; margin: 0; padding: 6px 0 0; }
746
+ #filelist li {
747
+ display: grid;
748
+ grid-template-columns: 16px 1fr auto;
749
+ align-items: center;
750
+ gap: 8px;
751
+ padding: 6px 14px 6px 12px;
752
+ cursor: pointer;
753
+ font-size: 12.5px;
754
+ color: var(--fg);
755
+ border-left: 2px solid transparent;
756
+ transition: background 0.10s, border-color 0.10s;
757
+ }
758
+ #filelist li:hover { background: var(--bg-mute); }
759
+ #filelist li.active {
760
+ background: var(--accent-subtle);
761
+ border-left-color: var(--accent);
762
+ color: var(--fg);
763
+ }
764
+ #filelist li.hidden { display: none; }
765
+ #filelist li .name {
766
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
767
+ direction: rtl; text-align: left;
768
+ }
769
+ #filelist li .name::before { content: "\200E"; }
770
+ #filelist li .stat {
771
+ display: inline-flex; align-items: center; gap: 6px;
772
+ font-size: 11px;
773
+ font-variant-numeric: tabular-nums;
774
+ font-family: "Monaspace Neon", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
775
+ }
776
+ #filelist li .stat .a { color: var(--success); }
777
+ #filelist li .stat .d { color: var(--danger); }
778
+ .bar {
779
+ display: inline-flex; gap: 1px;
780
+ margin-left: 4px;
781
+ }
782
+ .bar > span {
783
+ width: 6px; height: 8px;
784
+ background: var(--bg-emph);
785
+ border-radius: 1px;
786
+ }
787
+ .bar > span.a { background: var(--success); }
788
+ .bar > span.d { background: var(--danger); }
789
+
790
+ .badge {
791
+ width: 16px; height: 16px;
792
+ display: inline-flex;
793
+ align-items: center;
794
+ justify-content: center;
795
+ border-radius: 3px;
796
+ font-size: 9px;
797
+ font-weight: 700;
798
+ letter-spacing: 0;
799
+ background: var(--bg-emph);
800
+ color: var(--fg);
801
+ flex-shrink: 0;
802
+ }
803
+ .badge.M { background: #f9d97a55; color: #7d4e00; }
804
+ .badge.A { background: #ccffd866; color: var(--success); }
805
+ .badge.D { background: #ffd7d566; color: var(--danger); }
806
+ .badge.R { background: #d8b9ff66; color: var(--done); }
807
+
808
+ [data-theme="dark"] .badge.M { background: rgba(210,153,34,0.20); color: var(--attn); }
809
+ [data-theme="dark"] .badge.A { background: rgba(46,160,67,0.20); color: var(--success); }
810
+ [data-theme="dark"] .badge.D { background: rgba(248,81,73,0.20); color: var(--danger); }
811
+ [data-theme="dark"] .badge.R { background: rgba(163,113,247,0.20); color: var(--done); }
812
+
813
+ /* ===== Main content area ===== */
814
+ #content {
815
+ margin-left: var(--sidebar-w);
816
+ padding: calc(var(--topbar-h) + 18px) 24px 80px;
817
+ min-height: calc(100vh - var(--topbar-h));
818
+ }
819
+
820
+ #diff > *:first-child { margin-top: 0; }
821
+
822
+ .empty {
823
+ display: flex; flex-direction: column; align-items: center; justify-content: center;
824
+ padding: 80px 16px; color: var(--fg-muted); text-align: center;
825
+ }
826
+ .empty .emoji { font-size: 40px; margin-bottom: 8px; }
827
+ .empty h2 { color: var(--fg); margin: 0 0 4px; font-size: 18px; font-weight: 600; }
828
+ .empty.hidden { display: none; }
829
+
830
+ /* ===== diff2html overrides ===== */
831
+
832
+ /* Force overflow:visible to keep paint tree intact (see earlier fix) */
833
+ .d2h-file-wrapper,
834
+ .d2h-files-diff,
835
+ .d2h-file-diff,
836
+ .d2h-code-wrapper {
837
+ overflow: visible !important;
838
+ contain: none !important;
839
+ content-visibility: visible !important;
840
+ transform: none !important;
841
+ will-change: auto !important;
842
+ }
843
+ .d2h-code-wrapper { overflow-x: auto !important; }
844
+
845
+ .d2h-wrapper {
846
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
847
+ }
848
+
849
+ .d2h-file-list-wrapper { display: none !important; }
850
+
851
+ .d2h-file-wrapper {
852
+ background: var(--bg);
853
+ border: 1px solid var(--border);
854
+ border-radius: 6px;
855
+ margin: 0 0 16px;
856
+ isolation: isolate;
857
+ box-shadow: var(--shadow-sm);
858
+ /* When scrolled to (e.g. from sidebar click), leave room for the fixed
859
+ topbar so the file header doesn't get hidden behind it. */
860
+ scroll-margin-top: calc(var(--topbar-h) + 8px);
861
+ }
862
+
863
+ .d2h-file-header {
864
+ background: var(--bg-soft);
865
+ border-bottom: 1px solid var(--border);
866
+ border-radius: 6px 6px 0 0;
867
+ padding: 8px 16px;
868
+ display: flex;
869
+ align-items: center;
870
+ gap: 8px;
871
+ /* Hard-coded value (var(--topbar-h) was being resolved to 0 by some
872
+ browser quirk on this nested element, breaking sticky). */
873
+ position: sticky;
874
+ top: 56px;
875
+ z-index: 5;
876
+ font-size: 13px;
877
+ }
878
+ .d2h-file-name-wrapper {
879
+ display: flex; align-items: center; gap: 8px;
880
+ flex: 1; min-width: 0;
881
+ font-size: 13px;
882
+ }
883
+ .d2h-file-name {
884
+ color: var(--fg) !important;
885
+ font-weight: 600;
886
+ font-family: "Monaspace Neon", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
887
+ font-size: 12.5px;
888
+ overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
889
+ }
890
+ .d2h-icon-wrapper { display: inline-flex; color: var(--fg-muted); }
891
+ .d2h-icon-wrapper svg, .d2h-file-name-wrapper svg { fill: var(--fg-muted); }
892
+
893
+ .d2h-file-stats { display: none !important; } /* replaced by .gdp-stat-text */
894
+ .d2h-lines-added {
895
+ color: var(--success); font-weight: 600;
896
+ font-variant-numeric: tabular-nums;
897
+ font-size: 12px;
898
+ font-family: "Monaspace Neon", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
899
+ }
900
+ .d2h-lines-deleted {
901
+ color: var(--danger); font-weight: 600;
902
+ font-variant-numeric: tabular-nums;
903
+ font-size: 12px;
904
+ font-family: "Monaspace Neon", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
905
+ }
906
+
907
+ /* Hunk expand row — single-line 20px to match github.com. The class
908
+ * `gdp-hunk-row` is added by setupHunkExpand() on every paired @@ row
909
+ * (left + right in split, single in unified) so CSS targeting is
910
+ * deterministic regardless of d2h's underlying class names. */
911
+ /* Hunk row sizes to its tallest cell content (1 arrow = 20px, 2 stacked
912
+ * arrows = 40px). No max-height clamp here — let the stack drive it. */
913
+ tr.gdp-hunk-row,
914
+ tr.gdp-hunk-row > td {
915
+ line-height: 0 !important;
916
+ }
917
+ tr.gdp-hunk-row > td {
918
+ padding: 0 !important;
919
+ vertical-align: middle !important;
920
+ overflow: hidden;
921
+ white-space: nowrap;
922
+ font-size: 0 !important;
923
+ }
924
+ /* Force the inner div to act as a 20px block. d2h ships
925
+ * `.d2h-code-side-line { display: inline-block }`, and inline-blocks
926
+ * sitting next to whitespace text nodes inside a table-cell create a
927
+ * second line box (~20px). Switching to `display: block` leaves only
928
+ * the div in the cell's flow. */
929
+ tr.gdp-hunk-row > td > .d2h-code-line,
930
+ tr.gdp-hunk-row > td > .d2h-code-side-line,
931
+ tr.gdp-hunk-row > td > .gdp-expand-stack {
932
+ /* Stack auto-sizes: 1 button = 20px, 2 buttons (↑+↓) = 40px. */
933
+ font-size: 12px;
934
+ line-height: 20px;
935
+ }
936
+ tr.gdp-hunk-row .d2h-code-line,
937
+ tr.gdp-hunk-row .d2h-code-side-line,
938
+ tr.gdp-hunk-row .d2h-code-line-ctn {
939
+ height: 20px !important;
940
+ line-height: 20px !important;
941
+ padding-top: 0 !important;
942
+ padding-bottom: 0 !important;
943
+ overflow: hidden;
944
+ }
945
+ /* Hide any d2h placeholder children inside the hunk-row line-number cell
946
+ * (e.g. the empty old/new line-num divs) so only the expand stack shows
947
+ * and the cell collapses to 20px. */
948
+ tr.gdp-hunk-row td.d2h-code-linenumber > :not(.gdp-expand-stack),
949
+ tr.gdp-hunk-row td.d2h-code-side-linenumber > :not(.gdp-expand-stack) {
950
+ display: none !important;
951
+ }
952
+ /* d2h ships `td.d2h-code-linenumber { position: absolute; ... }` and
953
+ * `.d2h-code-line { padding: 0 8em; width: calc(100% - 16em); }` so the
954
+ * line-number cell floats over an empty padded area inside the code cell.
955
+ * That leaves a real ~175px horizontal gap between the line-num column and
956
+ * the actual code text. Reset to a normal table layout: line-num is a real
957
+ * table-cell, code-line has no horizontal padding/width override. */
958
+ /* Line-number column: min-width fits 3-digit numbers; the cell grows
959
+ * automatically when content (e.g. 4-5 digit lines on big files) needs
960
+ * more space, matching github.com which never clips line numbers. */
961
+ table.d2h-diff-table td.d2h-code-linenumber,
962
+ table.d2h-diff-table td.d2h-code-side-linenumber {
963
+ position: static !important;
964
+ display: table-cell !important;
965
+ width: 1%; /* shrink-to-fit while still respecting min-width */
966
+ min-width: 50px;
967
+ padding: 0 4px !important;
968
+ text-align: center;
969
+ direction: ltr;
970
+ line-height: 20px;
971
+ white-space: nowrap;
972
+ }
973
+ /* Unified line-num cell holds two numbers (old, new) side-by-side via d2h's
974
+ * `.line-num1{float:left}` / `.line-num2{float:right}`. Inner numbers are
975
+ * inline-block min-width 30px (fits 3 digits) and grow with content. */
976
+ table.d2h-diff-table td.d2h-code-linenumber {
977
+ min-width: 78px;
978
+ text-align: left;
979
+ }
980
+ /* d2h ships `width: 3.5em` + `overflow: hidden; text-overflow: ellipsis`
981
+ * which clips 4-5 digit line numbers. Override to auto width with a
982
+ * monospace tabular floor so 1-3 digits stay aligned and bigger numbers
983
+ * just push the cell wider. */
984
+ table.d2h-diff-table td.d2h-code-linenumber > .line-num1,
985
+ table.d2h-diff-table td.d2h-code-linenumber > .line-num2 {
986
+ display: inline-block;
987
+ width: auto !important;
988
+ min-width: 28px;
989
+ padding: 0 2px !important;
990
+ overflow: visible !important;
991
+ text-overflow: clip !important;
992
+ text-align: right;
993
+ white-space: nowrap;
994
+ font-variant-numeric: tabular-nums;
995
+ }
996
+ table.d2h-diff-table td.d2h-code-linenumber > .line-num1 { float: left; }
997
+ table.d2h-diff-table td.d2h-code-linenumber > .line-num2 { float: right; }
998
+ /* Match GitHub's 20px row height: remove td padding, let line-height fill. */
999
+ table.d2h-diff-table td.d2h-cntx,
1000
+ table.d2h-diff-table td.d2h-ins,
1001
+ table.d2h-diff-table td.d2h-del,
1002
+ table.d2h-diff-table td.d2h-info {
1003
+ padding: 0 !important;
1004
+ line-height: 20px;
1005
+ }
1006
+ table.d2h-diff-table .d2h-code-line,
1007
+ table.d2h-diff-table .d2h-code-side-line {
1008
+ padding: 0 !important;
1009
+ width: auto !important;
1010
+ line-height: 20px;
1011
+ }
1012
+ table.d2h-diff-table .d2h-code-line-prefix {
1013
+ display: inline-block;
1014
+ width: 1.5em;
1015
+ padding-left: 4px;
1016
+ }
1017
+ /* Stack height = number of buttons * 20px. With 1 button = 20px row,
1018
+ * with 2 (↑+↓) = 40px row, matching GitHub. */
1019
+ .gdp-expand-stack {
1020
+ display: flex;
1021
+ flex-direction: column;
1022
+ align-items: stretch;
1023
+ width: 100%;
1024
+ }
1025
+ .gdp-expand-btn {
1026
+ appearance: none;
1027
+ -webkit-appearance: none;
1028
+ display: grid;
1029
+ place-items: center;
1030
+ flex: 0 0 20px;
1031
+ width: 100%;
1032
+ height: 20px;
1033
+ min-height: 0;
1034
+ border: 0;
1035
+ background: var(--accent-subtle);
1036
+ color: var(--accent);
1037
+ cursor: pointer;
1038
+ padding: 0;
1039
+ margin: 0;
1040
+ overflow: hidden;
1041
+ transition: background 0.10s, color 0.10s;
1042
+ }
1043
+ .gdp-expand-btn svg {
1044
+ display: block;
1045
+ }
1046
+ .gdp-expand-btn + .gdp-expand-btn { border-top: 1px solid var(--bg); }
1047
+ .gdp-expand-btn:hover {
1048
+ background: var(--accent);
1049
+ color: #fff;
1050
+ }
1051
+ .gdp-inserted-ctx td { background: var(--bg) !important; }
1052
+
1053
+ /* GitHub-style "+10 -113" stats appended to the file header. */
1054
+ .gdp-stat-text {
1055
+ margin-left: auto;
1056
+ display: inline-flex;
1057
+ gap: 8px;
1058
+ font-size: 12px;
1059
+ font-weight: 600;
1060
+ font-variant-numeric: tabular-nums;
1061
+ }
1062
+ .gdp-stat-text .a { color: #1a7f37; }
1063
+ .gdp-stat-text .d { color: #d1242f; }
1064
+ [data-theme="dark"] .gdp-stat-text .a { color: #3fb950; }
1065
+ [data-theme="dark"] .gdp-stat-text .d { color: #f85149; }
1066
+
1067
+ /* GitHub-style diff squares appended to the file header. */
1068
+ .gdp-stat-squares {
1069
+ display: inline-flex;
1070
+ gap: 1px;
1071
+ margin-left: 8px;
1072
+ vertical-align: middle;
1073
+ }
1074
+ .gdp-stat-squares .sq {
1075
+ display: inline-block;
1076
+ width: 8px;
1077
+ height: 8px;
1078
+ border-radius: 2px;
1079
+ background: #d0d7de; /* fallback / neutral */
1080
+ }
1081
+ .gdp-stat-squares .sq.add { background: #1f883d; } /* Primer success-emphasis */
1082
+ .gdp-stat-squares .sq.del { background: #cf222e; } /* Primer danger-emphasis */
1083
+ .gdp-stat-squares .sq.nu { background: var(--bg-emph); }
1084
+ [data-theme="dark"] .gdp-stat-squares .sq.add { background: #2ea043; }
1085
+ [data-theme="dark"] .gdp-stat-squares .sq.del { background: #da3633; }
1086
+ [data-theme="dark"] .gdp-stat-squares .sq.nu { background: var(--border-strong); }
1087
+
1088
+ .d2h-tag {
1089
+ font-size: 10px;
1090
+ font-weight: 600;
1091
+ text-transform: uppercase;
1092
+ letter-spacing: 0.04em;
1093
+ padding: 2px 7px;
1094
+ border-radius: 999px;
1095
+ border: 1px solid transparent;
1096
+ line-height: 1.4;
1097
+ }
1098
+ .d2h-changed-tag { background: #fff8c5; border-color: #d4a72c80; color: var(--attn); }
1099
+ .d2h-added-tag { background: #ccffd866; border-color: #2da44e44; color: var(--success); }
1100
+ .d2h-deleted-tag { background: #ffebe9; border-color: #cf222e44; color: var(--danger); }
1101
+ .d2h-moved-tag { background: #d8b9ff44; border-color: #8250df44; color: var(--done); }
1102
+
1103
+ [data-theme="dark"] .d2h-changed-tag { background: rgba(210,153,34,0.15); border-color: rgba(210,153,34,0.40); color: var(--attn); }
1104
+ [data-theme="dark"] .d2h-added-tag { background: rgba(46,160,67,0.15); border-color: rgba(46,160,67,0.40); color: var(--success); }
1105
+ [data-theme="dark"] .d2h-deleted-tag { background: rgba(248,81,73,0.15); border-color: rgba(248,81,73,0.40); color: var(--danger); }
1106
+ [data-theme="dark"] .d2h-moved-tag { background: rgba(163,113,247,0.15);border-color: rgba(163,113,247,0.40);color: var(--done); }
1107
+
1108
+ /* ===== Diff body / table ===== */
1109
+ .d2h-file-wrapper .d2h-file-diff,
1110
+ .d2h-file-wrapper .d2h-files-diff {
1111
+ border-radius: 0 0 6px 6px;
1112
+ }
1113
+ .d2h-diff-table {
1114
+ border: 0 !important;
1115
+ border-collapse: collapse;
1116
+ width: 100%;
1117
+ /* match GitHub Primer exactly */
1118
+ font-family: "Monaspace Neon", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
1119
+ font-size: 12px;
1120
+ line-height: 20px;
1121
+ color: var(--fg);
1122
+ tab-size: 4;
1123
+ -moz-tab-size: 4;
1124
+ font-variant-ligatures: none;
1125
+ text-size-adjust: 100%;
1126
+ -webkit-text-size-adjust: 100%;
1127
+ }
1128
+ .d2h-code-line, .d2h-code-side-line, .d2h-code-line-ctn, .d2h-code-side-emptyplaceholder {
1129
+ font-family: inherit !important;
1130
+ font-size: 12px !important;
1131
+ line-height: 20px !important;
1132
+ font-weight: 400 !important;
1133
+ }
1134
+ /* Force the line wrappers (NOT the inner highlighted spans) to use Primer's
1135
+ * full-strength fg color so the text feels as solid as github.com. */
1136
+ .d2h-code-line, .d2h-code-side-line { color: #1f2328 !important; }
1137
+ [data-theme="dark"] .d2h-code-line,
1138
+ [data-theme="dark"] .d2h-code-side-line { color: #e6edf3 !important; }
1139
+
1140
+ /* highlight.js's .hljs class adds a white background — let the parent
1141
+ * add/del/cntx/info row color show through instead. */
1142
+ .d2h-code-line-ctn,
1143
+ .d2h-code-line-ctn.hljs {
1144
+ background: transparent !important;
1145
+ }
1146
+
1147
+ /* Override highlight.js github theme with the actual Primer "prettylights"
1148
+ * token colors used on github.com — the vendored `github.min.css` palette is
1149
+ * notably more muted/grey, which made our diff feel washed out. */
1150
+ .d2h-code-line-ctn .hljs-keyword,
1151
+ .d2h-code-line-ctn .hljs-selector-tag,
1152
+ .d2h-code-line-ctn .hljs-built_in,
1153
+ .d2h-code-line-ctn .hljs-builtin-name,
1154
+ .d2h-code-line-ctn .hljs-tag,
1155
+ .d2h-code-line-ctn .hljs-meta-keyword { color: #cf222e !important; }
1156
+
1157
+ .d2h-code-line-ctn .hljs-string,
1158
+ .d2h-code-line-ctn .hljs-symbol,
1159
+ .d2h-code-line-ctn .hljs-bullet,
1160
+ .d2h-code-line-ctn .hljs-attr,
1161
+ .d2h-code-line-ctn .hljs-template-tag,
1162
+ .d2h-code-line-ctn .hljs-template-variable { color: #0a3069 !important; }
1163
+
1164
+ .d2h-code-line-ctn .hljs-comment,
1165
+ .d2h-code-line-ctn .hljs-quote,
1166
+ .d2h-code-line-ctn .hljs-deletion { color: #6e7781 !important; }
1167
+
1168
+ .d2h-code-line-ctn .hljs-number,
1169
+ .d2h-code-line-ctn .hljs-literal,
1170
+ .d2h-code-line-ctn .hljs-doctag,
1171
+ .d2h-code-line-ctn .hljs-meta { color: #0550ae !important; }
1172
+
1173
+ .d2h-code-line-ctn .hljs-title,
1174
+ .d2h-code-line-ctn .hljs-section,
1175
+ .d2h-code-line-ctn .hljs-function .hljs-title,
1176
+ .d2h-code-line-ctn .hljs-name { color: #8250df !important; }
1177
+
1178
+ .d2h-code-line-ctn .hljs-variable,
1179
+ .d2h-code-line-ctn .hljs-template-variable,
1180
+ .d2h-code-line-ctn .hljs-type,
1181
+ .d2h-code-line-ctn .hljs-class .hljs-title,
1182
+ .d2h-code-line-ctn .hljs-attribute { color: #953800 !important; }
1183
+
1184
+ .d2h-code-line-ctn .hljs-emphasis { font-style: italic; }
1185
+ .d2h-code-line-ctn .hljs-strong { font-weight: 600; }
1186
+
1187
+ [data-theme="dark"] .d2h-code-line-ctn .hljs-keyword,
1188
+ [data-theme="dark"] .d2h-code-line-ctn .hljs-selector-tag,
1189
+ [data-theme="dark"] .d2h-code-line-ctn .hljs-built_in,
1190
+ [data-theme="dark"] .d2h-code-line-ctn .hljs-tag { color: #ff7b72 !important; }
1191
+ [data-theme="dark"] .d2h-code-line-ctn .hljs-string,
1192
+ [data-theme="dark"] .d2h-code-line-ctn .hljs-attr,
1193
+ [data-theme="dark"] .d2h-code-line-ctn .hljs-symbol { color: #a5d6ff !important; }
1194
+ [data-theme="dark"] .d2h-code-line-ctn .hljs-comment,
1195
+ [data-theme="dark"] .d2h-code-line-ctn .hljs-quote { color: #8b949e !important; }
1196
+ [data-theme="dark"] .d2h-code-line-ctn .hljs-number,
1197
+ [data-theme="dark"] .d2h-code-line-ctn .hljs-literal,
1198
+ [data-theme="dark"] .d2h-code-line-ctn .hljs-meta { color: #79c0ff !important; }
1199
+ [data-theme="dark"] .d2h-code-line-ctn .hljs-title,
1200
+ [data-theme="dark"] .d2h-code-line-ctn .hljs-name,
1201
+ [data-theme="dark"] .d2h-code-line-ctn .hljs-function .hljs-title { color: #d2a8ff !important; }
1202
+ [data-theme="dark"] .d2h-code-line-ctn .hljs-variable,
1203
+ [data-theme="dark"] .d2h-code-line-ctn .hljs-type,
1204
+ [data-theme="dark"] .d2h-code-line-ctn .hljs-attribute { color: #ffa657 !important; }
1205
+
1206
+ /* Line number column */
1207
+ .d2h-code-linenumber {
1208
+ background: var(--bg) !important;
1209
+ color: var(--fg-subtle) !important;
1210
+ border-right: 1px solid var(--border-muted) !important;
1211
+ font-size: 12px !important;
1212
+ font-variant-numeric: tabular-nums;
1213
+ user-select: none;
1214
+ }
1215
+ .d2h-code-side-linenumber {
1216
+ background: var(--bg) !important;
1217
+ color: var(--fg-subtle) !important;
1218
+ border-right: 1px solid var(--border-muted) !important;
1219
+ font-size: 12px !important;
1220
+ font-variant-numeric: tabular-nums;
1221
+ }
1222
+
1223
+ /* Hunk headers (@@) — GitHub style: blue tint */
1224
+ .d2h-info {
1225
+ background: var(--diff-hunk-bg) !important;
1226
+ color: var(--diff-hunk-fg) !important;
1227
+ border-color: var(--diff-hunk-bg) !important;
1228
+ }
1229
+ .d2h-info .d2h-code-line,
1230
+ .d2h-info .d2h-code-side-line {
1231
+ color: var(--diff-hunk-fg) !important;
1232
+ }
1233
+
1234
+ /* Context (unchanged) lines */
1235
+ .d2h-cntx { background: var(--bg) !important; color: var(--fg) !important; }
1236
+
1237
+ /* Addition rows */
1238
+ .d2h-ins,
1239
+ .d2h-ins .d2h-code-line,
1240
+ .d2h-ins .d2h-code-side-line,
1241
+ .d2h-ins.d2h-change.d2h-code-line {
1242
+ background: var(--diff-add-bg) !important;
1243
+ color: var(--fg) !important;
1244
+ }
1245
+ .d2h-ins .d2h-code-linenumber,
1246
+ .d2h-ins.d2h-code-linenumber,
1247
+ .d2h-ins .d2h-code-side-linenumber {
1248
+ background: var(--diff-add-num-bg) !important;
1249
+ color: var(--fg) !important;
1250
+ border-right-color: rgba(46,160,67,0.30) !important;
1251
+ }
1252
+
1253
+ /* Deletion rows */
1254
+ .d2h-del,
1255
+ .d2h-del .d2h-code-line,
1256
+ .d2h-del .d2h-code-side-line,
1257
+ .d2h-del.d2h-change.d2h-code-line {
1258
+ background: var(--diff-del-bg) !important;
1259
+ color: var(--fg) !important;
1260
+ }
1261
+ .d2h-del .d2h-code-linenumber,
1262
+ .d2h-del.d2h-code-linenumber,
1263
+ .d2h-del .d2h-code-side-linenumber {
1264
+ background: var(--diff-del-num-bg) !important;
1265
+ color: var(--fg) !important;
1266
+ border-right-color: rgba(207,34,46,0.30) !important;
1267
+ }
1268
+
1269
+ /* Word-level highlights inside add/del lines */
1270
+ .d2h-ins.d2h-change ins,
1271
+ .d2h-ins ins {
1272
+ background: var(--diff-add-word-bg) !important;
1273
+ color: var(--fg);
1274
+ text-decoration: none;
1275
+ border-radius: 1px;
1276
+ padding: 0 1px;
1277
+ }
1278
+ .d2h-del.d2h-change del,
1279
+ .d2h-del del {
1280
+ background: var(--diff-del-word-bg) !important;
1281
+ color: var(--fg);
1282
+ text-decoration: none;
1283
+ border-radius: 1px;
1284
+ padding: 0 1px;
1285
+ }
1286
+
1287
+ /* Empty placeholder cells (for split view) */
1288
+ .d2h-emptyplaceholder,
1289
+ .d2h-code-side-emptyplaceholder {
1290
+ background: var(--bg-soft) !important;
1291
+ border-color: var(--border-muted) !important;
1292
+ }
1293
+ .d2h-code-side-emptyplaceholder { color: var(--fg-subtle) !important; }
1294
+
1295
+ /* Side-by-side divider */
1296
+ .d2h-file-side-diff > div { border-color: var(--border-muted) !important; }
1297
+ .d2h-files-diff > div { background: var(--bg) !important; }
1298
+
1299
+ /* Prefix coloring (use diff2html's default layout) */
1300
+ .d2h-code-line-prefix { color: var(--fg-subtle); user-select: none; }
1301
+ .d2h-ins .d2h-code-line-prefix { color: var(--success); }
1302
+ .d2h-del .d2h-code-line-prefix { color: var(--danger); }
1303
+
1304
+ /* ===== Viewed checkbox (top-right of file header) ===== */
1305
+ .d2h-file-collapse {
1306
+ margin-left: auto;
1307
+ display: inline-flex;
1308
+ align-items: center;
1309
+ gap: 6px;
1310
+ font-size: 12px;
1311
+ color: var(--fg-muted);
1312
+ cursor: pointer;
1313
+ }
1314
+
1315
+ /* ===== Scrollbars ===== */
1316
+ ::-webkit-scrollbar { width: 12px; height: 12px; }
1317
+ ::-webkit-scrollbar-thumb {
1318
+ background: var(--bg-emph);
1319
+ border-radius: 6px;
1320
+ border: 3px solid var(--bg);
1321
+ }
1322
+ ::-webkit-scrollbar-thumb:hover { background: var(--border-strong); }
1323
+ ::-webkit-scrollbar-track { background: var(--bg); }
1324
+ [data-theme="dark"] ::-webkit-scrollbar-thumb { border-color: var(--bg); }
1325
+
1326
+ /* ===== Responsive ===== */
1327
+ @media (max-width: 900px) {
1328
+ #sidebar {
1329
+ position: static;
1330
+ width: auto;
1331
+ max-height: 220px;
1332
+ border-right: 0;
1333
+ border-bottom: 1px solid var(--border);
1334
+ }
1335
+ #content { margin-left: 0; max-width: none; padding-top: calc(var(--topbar-h) + 240px); }
1336
+ .controls input[type="search"] { width: 130px; }
1337
+ }
1338
+
1339
+ /* ===== File shell (placeholder + loaded card) ===== */
1340
+ .gdp-file-shell {
1341
+ background: var(--bg);
1342
+ border: 1px solid var(--border);
1343
+ border-radius: 6px;
1344
+ margin: 0 0 16px;
1345
+ scroll-margin-top: calc(var(--topbar-h) + 8px);
1346
+ isolation: isolate;
1347
+ box-shadow: 0 1px 0 rgba(31,35,40,0.04);
1348
+ content-visibility: auto;
1349
+ contain-intrinsic-size: auto 200px;
1350
+ }
1351
+ .gdp-shell-header {
1352
+ display: flex;
1353
+ align-items: center;
1354
+ gap: 10px;
1355
+ padding: 8px 14px;
1356
+ background: var(--bg-soft);
1357
+ border-bottom: 1px solid var(--border);
1358
+ border-radius: 6px 6px 0 0;
1359
+ font-size: 13px;
1360
+ font-family: "Monaspace Neon", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
1361
+ }
1362
+ .gdp-shell-header .status-pill {
1363
+ display: inline-flex;
1364
+ align-items: center;
1365
+ justify-content: center;
1366
+ width: 18px; height: 18px;
1367
+ border-radius: 4px;
1368
+ font-size: 10px;
1369
+ font-weight: 700;
1370
+ font-family: -apple-system, sans-serif;
1371
+ background: var(--bg-mute);
1372
+ color: var(--fg-muted);
1373
+ }
1374
+ .gdp-shell-header .status-pill.M { background: #f9d97a55; color: #7d4e00; }
1375
+ .gdp-shell-header .status-pill.A { background: #ccffd866; color: var(--success); }
1376
+ .gdp-shell-header .status-pill.D { background: #ffd7d566; color: var(--danger); }
1377
+ .gdp-shell-header .status-pill.R { background: #d8b9ff66; color: var(--done); }
1378
+ .gdp-shell-header .path {
1379
+ color: var(--fg);
1380
+ font-weight: 600;
1381
+ flex: 1;
1382
+ overflow: hidden;
1383
+ text-overflow: ellipsis;
1384
+ white-space: nowrap;
1385
+ }
1386
+ .gdp-shell-header .stats {
1387
+ font-variant-numeric: tabular-nums;
1388
+ font-size: 12px;
1389
+ }
1390
+ .gdp-shell-header .stats .a { color: var(--success); font-weight: 600; }
1391
+ .gdp-shell-header .stats .d { color: var(--danger); font-weight: 600; }
1392
+ .gdp-shell-header .size-tag {
1393
+ font-size: 10px;
1394
+ font-weight: 700;
1395
+ text-transform: uppercase;
1396
+ letter-spacing: 0.05em;
1397
+ padding: 2px 6px;
1398
+ border-radius: 3px;
1399
+ color: var(--fg-subtle);
1400
+ background: var(--bg-mute);
1401
+ font-family: -apple-system, sans-serif;
1402
+ }
1403
+ .gdp-shell-header .size-tag.large,
1404
+ .gdp-shell-header .size-tag.huge {
1405
+ background: #fff8c5;
1406
+ color: var(--attn);
1407
+ }
1408
+ [data-theme="dark"] .gdp-shell-header .size-tag.large,
1409
+ [data-theme="dark"] .gdp-shell-header .size-tag.huge {
1410
+ background: rgba(210,153,34,0.15);
1411
+ color: var(--attn);
1412
+ }
1413
+ .gdp-shell-header .size-tag.binary {
1414
+ background: #ddf4ff;
1415
+ color: var(--accent-emph);
1416
+ }
1417
+ .gdp-shell-header .loading-indicator {
1418
+ font-family: -apple-system, sans-serif;
1419
+ font-size: 11px;
1420
+ color: var(--fg-subtle);
1421
+ font-style: italic;
1422
+ }
1423
+ .gdp-shell-body {
1424
+ /* Diff2HtmlUI mounts here */
1425
+ }
1426
+
1427
+ .gdp-file-shell.loaded {
1428
+ background: transparent;
1429
+ border: 0;
1430
+ box-shadow: none;
1431
+ }
1432
+ .gdp-file-shell.loaded .d2h-file-wrapper {
1433
+ margin-bottom: 0;
1434
+ }
1435
+
1436
+ /* Pending shell: subtle pulse so user knows it's still loading */
1437
+ .gdp-file-shell.pending .gdp-shell-body {
1438
+ background: linear-gradient(90deg, transparent, var(--bg-soft), transparent);
1439
+ background-size: 200% 100%;
1440
+ animation: gdp-shimmer 1.4s ease-in-out infinite;
1441
+ opacity: 0.5;
1442
+ }
1443
+ .gdp-file-shell.manual-load .gdp-shell-body {
1444
+ background: var(--bg);
1445
+ animation: none;
1446
+ opacity: 1;
1447
+ }
1448
+ @keyframes gdp-shimmer {
1449
+ 0% { background-position: 200% 0; }
1450
+ 100% { background-position: -200% 0; }
1451
+ }
1452
+ .gdp-file-shell.error .gdp-shell-body { background: var(--diff-del-bg); }
1453
+
1454
+ /* "Show next / Show all" buttons after a hunk preview */
1455
+ .gdp-show-full-wrap {
1456
+ padding: 10px 14px;
1457
+ background: var(--bg-soft);
1458
+ border-top: 1px dashed var(--border);
1459
+ display: flex;
1460
+ gap: 10px;
1461
+ align-items: center;
1462
+ justify-content: center;
1463
+ flex-wrap: wrap;
1464
+ }
1465
+ .gdp-hunk-note {
1466
+ font-size: 11.5px;
1467
+ color: var(--fg-subtle);
1468
+ font-family: "Monaspace Neon", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
1469
+ margin-right: auto;
1470
+ }
1471
+ .gdp-show-full {
1472
+ background: var(--bg);
1473
+ border: 1px solid var(--border);
1474
+ color: var(--fg);
1475
+ padding: 6px 14px;
1476
+ border-radius: 6px;
1477
+ font: inherit;
1478
+ font-size: 12.5px;
1479
+ cursor: pointer;
1480
+ transition: background 0.12s, border-color 0.12s;
1481
+ }
1482
+ .gdp-show-full:hover { background: var(--accent); color: #fff; border-color: var(--accent); }
1483
+ .gdp-show-full.secondary { background: transparent; color: var(--fg-muted); }
1484
+ .gdp-show-full.secondary:hover { color: var(--fg); border-color: var(--border-strong); background: var(--bg); }
1485
+ .gdp-show-full:disabled { opacity: 0.6; cursor: wait; }
1486
+
1487
+ .gdp-manual-load {
1488
+ padding: 14px;
1489
+ display: flex;
1490
+ align-items: center;
1491
+ gap: 10px;
1492
+ flex-wrap: wrap;
1493
+ }
1494
+ .gdp-manual-note {
1495
+ color: var(--fg-muted);
1496
+ font-size: 12.5px;
1497
+ margin-right: auto;
1498
+ }
1499
+
1500
+ .gdp-error {
1501
+ padding: 14px;
1502
+ color: var(--danger);
1503
+ font-family: -apple-system, sans-serif;
1504
+ }
1505
+ .gdp-error .retry {
1506
+ margin-left: 8px;
1507
+ background: var(--bg);
1508
+ border: 1px solid var(--border);
1509
+ color: var(--fg);
1510
+ padding: 3px 10px;
1511
+ border-radius: 5px;
1512
+ cursor: pointer;
1513
+ }
1514
+ .gdp-info {
1515
+ padding: 14px;
1516
+ color: var(--fg-subtle);
1517
+ font-size: 13px;
1518
+ font-style: italic;
1519
+ }
1520
+
1521
+ /* ===== Media (binary image/video) ===== */
1522
+ .gdp-media {
1523
+ display: flex;
1524
+ gap: 16px;
1525
+ padding: 16px;
1526
+ background: var(--bg);
1527
+ border-radius: 0 0 6px 6px;
1528
+ flex-wrap: wrap;
1529
+ }
1530
+ .gdp-media .media-side {
1531
+ flex: 1 1 300px;
1532
+ display: flex;
1533
+ flex-direction: column;
1534
+ align-items: center;
1535
+ gap: 8px;
1536
+ }
1537
+ .gdp-media .media-label {
1538
+ font-size: 10px;
1539
+ font-weight: 700;
1540
+ text-transform: uppercase;
1541
+ letter-spacing: 0.06em;
1542
+ padding: 3px 10px;
1543
+ border-radius: 999px;
1544
+ border: 1px solid transparent;
1545
+ }
1546
+ .gdp-media .media-label.add {
1547
+ background: var(--diff-add-bg);
1548
+ border-color: rgba(46,160,67,0.4);
1549
+ color: var(--success);
1550
+ }
1551
+ .gdp-media .media-label.del {
1552
+ background: var(--diff-del-bg);
1553
+ border-color: rgba(207,34,46,0.4);
1554
+ color: var(--danger);
1555
+ }
1556
+ .gdp-media img,
1557
+ .gdp-media video {
1558
+ max-width: 100%;
1559
+ max-height: 70vh;
1560
+ border: 1px solid var(--border);
1561
+ border-radius: 6px;
1562
+ background-color: var(--bg-soft);
1563
+ background-image:
1564
+ linear-gradient(45deg, var(--bg-mute) 25%, transparent 25%),
1565
+ linear-gradient(-45deg, var(--bg-mute) 25%, transparent 25%),
1566
+ linear-gradient(45deg, transparent 75%, var(--bg-mute) 75%),
1567
+ linear-gradient(-45deg, transparent 75%, var(--bg-mute) 75%);
1568
+ background-size: 16px 16px;
1569
+ background-position: 0 0, 0 8px, 8px -8px, -8px 0;
1570
+ object-fit: contain;
1571
+ }
1572
+ .gdp-media .media-empty {
1573
+ width: 100%;
1574
+ min-height: 120px;
1575
+ border: 1px dashed var(--border);
1576
+ border-radius: 6px;
1577
+ display: flex;
1578
+ align-items: center;
1579
+ justify-content: center;
1580
+ color: var(--fg-subtle);
1581
+ font-size: 12px;
1582
+ font-style: italic;
1583
+ background: var(--bg-soft);
1584
+ }