issue-map 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.
@@ -0,0 +1,878 @@
1
+ <title>開發地圖</title>
2
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
3
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
4
+ <link
5
+ rel="stylesheet"
6
+ href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,600;12..96,700&family=IBM+Plex+Mono:wght@400;500;600&family=Public+Sans:wght@400;500;600&family=Noto+Sans+TC:wght@400;500;700&display=swap"
7
+ />
8
+ <style>
9
+ :root {
10
+ --paper: #f4f6f7;
11
+ --card: #ffffff;
12
+ --ink: #13181d;
13
+ --muted: #626d78;
14
+ --faint: #8b949e;
15
+ --line: #dce1e6;
16
+ --line-strong: #c3ccd4;
17
+
18
+ /* 狀態色。go/wait/done 之外多一個 active,因為這裡的票會有人接手。 */
19
+ --go: #0f7b5f;
20
+ --go-soft: #e8f6f0;
21
+ --wait: #b45309;
22
+ --wait-soft: #fdf4e7;
23
+ --done: #55616f;
24
+ /* 圖標用的淺色。徽章的小字得撐 4.5:1,圖標只要看得出形狀,分兩支才不會互相綁死。 */
25
+ --done-mark: #b8c2cc;
26
+ --done-soft: #eef1f5;
27
+ --active: #4f46b8;
28
+ --active-soft: #e8e6f8;
29
+ --aside: #a03585;
30
+ --aside-soft: #fceaf6;
31
+
32
+ /* 每一組子票一條線的顏色,與狀態色無關。 */
33
+ --t1: #1f6f8b;
34
+ --t2: #7a4a92;
35
+ --t3: #8c5a24;
36
+ --t4: #2f7a5a;
37
+
38
+ --display: 'Bricolage Grotesque', 'Noto Sans TC', 'PingFang TC', sans-serif;
39
+ --body: 'Public Sans', 'Noto Sans TC', 'PingFang TC', system-ui, sans-serif;
40
+ --mono: 'IBM Plex Mono', ui-monospace, 'SF Mono', Menlo, monospace;
41
+ color-scheme: light;
42
+ }
43
+ @media (prefers-color-scheme: dark) {
44
+ :root:not([data-theme='light']) {
45
+ --paper: #11151a;
46
+ --card: #181d24;
47
+ --ink: #e8ecf0;
48
+ --muted: #9aa4af;
49
+ --faint: #6f7984;
50
+ --line: #262d36;
51
+ --line-strong: #3a434e;
52
+ --go: #4fbf94;
53
+ --go-soft: #10332a;
54
+ --wait: #e0a34a;
55
+ --wait-soft: #362614;
56
+ --done: #8b98a8;
57
+ --done-mark: #485564;
58
+ --done-soft: #202832;
59
+ --active: #a99cf0;
60
+ --active-soft: #262040;
61
+ --aside: #e07ac0;
62
+ --aside-soft: #3a1c31;
63
+ --t1: #6fb4d0;
64
+ --t2: #c093dd;
65
+ --t3: #d9a26a;
66
+ --t4: #5fc297;
67
+ color-scheme: dark;
68
+ }
69
+ }
70
+ :root[data-theme='dark'] {
71
+ --paper: #11151a;
72
+ --card: #181d24;
73
+ --ink: #e8ecf0;
74
+ --muted: #9aa4af;
75
+ --faint: #6f7984;
76
+ --line: #262d36;
77
+ --line-strong: #3a434e;
78
+ --go: #4fbf94;
79
+ --go-soft: #10332a;
80
+ --wait: #e0a34a;
81
+ --wait-soft: #362614;
82
+ --done: #8b98a8;
83
+ --done-mark: #485564;
84
+ --done-soft: #202832;
85
+ --active: #a99cf0;
86
+ --active-soft: #262040;
87
+ --aside: #e07ac0;
88
+ --aside-soft: #3a1c31;
89
+ --t1: #6fb4d0;
90
+ --t2: #c093dd;
91
+ --t3: #d9a26a;
92
+ --t4: #5fc297;
93
+ color-scheme: dark;
94
+ }
95
+
96
+ * {
97
+ box-sizing: border-box;
98
+ }
99
+ [hidden] {
100
+ display: none !important;
101
+ }
102
+ body {
103
+ margin: 0;
104
+ background: var(--paper);
105
+ color: var(--ink);
106
+ font-family: var(--body);
107
+ font-size: 15px;
108
+ line-height: 1.6;
109
+ -webkit-font-smoothing: antialiased;
110
+ }
111
+ a {
112
+ color: inherit;
113
+ }
114
+ a:focus-visible,
115
+ button:focus-visible,
116
+ .node:focus-visible {
117
+ outline: 2px solid var(--go);
118
+ outline-offset: 2px;
119
+ }
120
+
121
+ .page {
122
+ max-width: 1080px;
123
+ margin: 0 auto;
124
+ padding: 40px 24px 72px;
125
+ display: flex;
126
+ flex-direction: column;
127
+ gap: 40px;
128
+ }
129
+ /*
130
+ * flex 子項的 min-width 預設是 auto,也就是「不縮到比內容還窄」。線路圖與表格都比視窗寬,
131
+ * 不寫這一行的話它們會把整頁撐開、變成整頁橫向捲,而不是各自在自己的框裡捲。
132
+ */
133
+ .page > *,
134
+ section.group,
135
+ #groups > * {
136
+ min-width: 0;
137
+ }
138
+
139
+ /* ---------- 抬頭 ---------- */
140
+
141
+ header.masthead {
142
+ display: flex;
143
+ flex-direction: column;
144
+ gap: 14px;
145
+ }
146
+ .eyebrow {
147
+ font-family: var(--mono);
148
+ font-size: 11px;
149
+ font-weight: 500;
150
+ letter-spacing: 0.14em;
151
+ text-transform: uppercase;
152
+ color: var(--faint);
153
+ }
154
+ h1 {
155
+ font-family: var(--display);
156
+ font-weight: 700;
157
+ font-size: clamp(28px, 4.2vw, 40px);
158
+ line-height: 1.08;
159
+ letter-spacing: -0.02em;
160
+ margin: 0;
161
+ text-wrap: balance;
162
+ }
163
+ .lede {
164
+ max-width: 64ch;
165
+ margin: 0;
166
+ font-size: 15.5px;
167
+ color: var(--muted);
168
+ }
169
+ .lede strong {
170
+ color: var(--ink);
171
+ font-weight: 600;
172
+ }
173
+ .lede a {
174
+ color: var(--go);
175
+ text-decoration: none;
176
+ border-bottom: 1px solid var(--line-strong);
177
+ }
178
+
179
+ /* 統計併成一條,不是五張卡。 */
180
+ .stats {
181
+ display: flex;
182
+ flex-wrap: wrap;
183
+ border: 1px solid var(--line);
184
+ border-radius: 3px;
185
+ overflow: hidden;
186
+ background: var(--card);
187
+ }
188
+ .stat {
189
+ flex: 1 1 120px;
190
+ padding: 14px 18px;
191
+ border-right: 1px solid var(--line);
192
+ border-top: 2px solid var(--line);
193
+ }
194
+ .stat[data-tone='ready'] {
195
+ border-top-color: var(--go);
196
+ }
197
+ .stat[data-tone='active'] {
198
+ border-top-color: var(--active);
199
+ }
200
+ .stat[data-tone='blocked'] {
201
+ border-top-color: var(--wait);
202
+ }
203
+ .stat[data-tone='triage'] {
204
+ border-top-color: var(--aside);
205
+ }
206
+ .stat:last-child {
207
+ border-right: 0;
208
+ }
209
+ .stat b {
210
+ display: block;
211
+ font-family: var(--display);
212
+ font-size: 26px;
213
+ font-weight: 700;
214
+ line-height: 1;
215
+ font-variant-numeric: tabular-nums;
216
+ }
217
+ .stat b small {
218
+ font-family: var(--mono);
219
+ font-size: 12px;
220
+ font-weight: 400;
221
+ color: var(--faint);
222
+ margin-left: 5px;
223
+ }
224
+ .stat span {
225
+ display: block;
226
+ margin-top: 5px;
227
+ font-family: var(--mono);
228
+ font-size: 10.5px;
229
+ letter-spacing: 0.08em;
230
+ text-transform: uppercase;
231
+ color: var(--faint);
232
+ }
233
+ .stat[data-tone='ready'] b {
234
+ color: var(--go);
235
+ }
236
+ .stat[data-tone='active'] b {
237
+ color: var(--active);
238
+ }
239
+ .stat[data-tone='blocked'] b {
240
+ color: var(--wait);
241
+ }
242
+ .stat[data-tone='triage'] b {
243
+ color: var(--aside);
244
+ }
245
+
246
+ /* ---------- 選取的那張票 ---------- */
247
+
248
+ .detail {
249
+ background: var(--card);
250
+ border: 1px solid var(--line);
251
+ border-left: 3px solid var(--line-strong);
252
+ border-radius: 2px;
253
+ padding: 16px 20px;
254
+ display: grid;
255
+ grid-template-columns: minmax(0, 1fr) auto;
256
+ gap: 10px 24px;
257
+ align-items: start;
258
+ }
259
+ .detail[data-status='ready'] {
260
+ border-left-color: var(--go);
261
+ background: var(--go-soft);
262
+ }
263
+ .detail[data-status='active'] {
264
+ border-left-color: var(--active);
265
+ }
266
+ .detail[data-status='blocked'] {
267
+ border-left-color: var(--wait);
268
+ }
269
+ .detail[data-status='triage'] {
270
+ border-left-color: var(--aside);
271
+ }
272
+ .detail[data-status='done'] {
273
+ border-left-color: var(--done);
274
+ }
275
+ .detail h3 {
276
+ margin: 0;
277
+ font-family: var(--display);
278
+ font-size: 19px;
279
+ font-weight: 600;
280
+ letter-spacing: -0.01em;
281
+ line-height: 1.35;
282
+ }
283
+ .detail h3 .num {
284
+ font-family: var(--mono);
285
+ font-size: 16px;
286
+ font-weight: 500;
287
+ color: var(--muted);
288
+ margin-right: 9px;
289
+ font-variant-numeric: tabular-nums;
290
+ }
291
+ .detail .rows {
292
+ grid-column: 1 / -1;
293
+ display: grid;
294
+ grid-template-columns: max-content 1fr;
295
+ gap: 5px 18px;
296
+ font-size: 13.5px;
297
+ }
298
+ .detail .rows dt {
299
+ font-family: var(--mono);
300
+ font-size: 10.5px;
301
+ letter-spacing: 0.08em;
302
+ text-transform: uppercase;
303
+ color: var(--faint);
304
+ padding-top: 3px;
305
+ }
306
+ .detail .rows dd {
307
+ margin: 0;
308
+ }
309
+ .detail .rows dd a {
310
+ font-family: var(--mono);
311
+ font-size: 13px;
312
+ text-decoration: none;
313
+ border-bottom: 1px solid var(--line-strong);
314
+ }
315
+ .detail .open {
316
+ font-family: var(--mono);
317
+ font-size: 11.5px;
318
+ white-space: nowrap;
319
+ color: var(--muted);
320
+ text-decoration: none;
321
+ border: 1px solid var(--line-strong);
322
+ border-radius: 2px;
323
+ padding: 5px 10px;
324
+ }
325
+ .detail .open:hover {
326
+ color: var(--ink);
327
+ }
328
+
329
+ /* ---------- 分組與線路圖 ---------- */
330
+
331
+ #groups {
332
+ display: flex;
333
+ flex-direction: column;
334
+ gap: 40px;
335
+ }
336
+ section.group {
337
+ display: flex;
338
+ flex-direction: column;
339
+ gap: 14px;
340
+ }
341
+ .group-head {
342
+ display: flex;
343
+ flex-wrap: wrap;
344
+ align-items: baseline;
345
+ gap: 8px 12px;
346
+ padding: 0 0 9px 12px;
347
+ border-bottom: 1px solid var(--line-strong);
348
+ /* 左邊那道色帶就是這一組在圖上的線色,標頭與圖對得起來。 */
349
+ border-left: 3px solid var(--track, var(--line-strong));
350
+ }
351
+ .group-head h2 {
352
+ font-family: var(--display);
353
+ font-weight: 600;
354
+ font-size: 19px;
355
+ letter-spacing: -0.01em;
356
+ margin: 0;
357
+ }
358
+ .group-head .sub {
359
+ font-size: 13px;
360
+ color: var(--muted);
361
+ }
362
+ .group-head a {
363
+ font-family: var(--mono);
364
+ font-size: 12.5px;
365
+ color: var(--muted);
366
+ text-decoration: none;
367
+ border-bottom: 1px solid var(--line);
368
+ }
369
+ .group-head a:hover {
370
+ color: var(--ink);
371
+ }
372
+
373
+ .fold {
374
+ font-family: var(--mono);
375
+ font-size: 13px;
376
+ line-height: 1;
377
+ width: 20px;
378
+ height: 20px;
379
+ padding: 0;
380
+ color: var(--muted);
381
+ background: var(--card);
382
+ border: 1px solid var(--line-strong);
383
+ border-radius: 2px;
384
+ cursor: pointer;
385
+ align-self: center;
386
+ }
387
+ .fold:hover {
388
+ color: var(--ink);
389
+ border-color: var(--ink);
390
+ }
391
+ section.group[data-folded='true'] .group-head h2 {
392
+ color: var(--muted);
393
+ }
394
+
395
+ .map-wrap {
396
+ background: var(--card);
397
+ border: 1px solid var(--line);
398
+ border-top: 2px solid var(--track, var(--line-strong));
399
+ border-radius: 2px;
400
+ overflow-x: auto;
401
+ padding: 14px 12px;
402
+ }
403
+ .map-wrap svg {
404
+ display: block;
405
+ font-family: var(--body);
406
+ }
407
+
408
+ /* 軌道。實線是前置關係,走完的那一段轉虛線。 */
409
+ .edge {
410
+ fill: none;
411
+ stroke: var(--track, var(--line-strong));
412
+ stroke-width: 3;
413
+ stroke-linecap: round;
414
+ stroke-linejoin: round;
415
+ }
416
+ .edge[data-done='true'] {
417
+ stroke: var(--line-strong);
418
+ stroke-dasharray: 5 4;
419
+ stroke-width: 2;
420
+ }
421
+
422
+ /* 站點:圓=流程上的票,三角=有人在做,菱形=規格未定案。 */
423
+ .node {
424
+ cursor: pointer;
425
+ text-decoration: none;
426
+ }
427
+ .node .mark {
428
+ fill: var(--card);
429
+ stroke: var(--track, var(--line-strong));
430
+ stroke-width: 3;
431
+ stroke-linejoin: round;
432
+ }
433
+ .node .core {
434
+ fill: var(--go);
435
+ stroke: none;
436
+ }
437
+ .node .halo {
438
+ fill: none;
439
+ stroke: var(--go);
440
+ stroke-width: 1.8;
441
+ opacity: 0.55;
442
+ }
443
+ .node .sid {
444
+ font-family: var(--mono);
445
+ font-size: 12px;
446
+ font-weight: 600;
447
+ fill: var(--ink);
448
+ font-variant-numeric: tabular-nums;
449
+ }
450
+ .node .sdesc {
451
+ font-size: 10px;
452
+ fill: var(--muted);
453
+ }
454
+ .node:hover .sid {
455
+ fill: var(--go);
456
+ }
457
+ .node[data-status='ready'] .mark {
458
+ stroke: var(--go);
459
+ stroke-width: 3;
460
+ }
461
+ .node[data-status='ready'] .sid {
462
+ fill: var(--go);
463
+ }
464
+ .node[data-status='active'] .mark {
465
+ fill: var(--active);
466
+ stroke: var(--active);
467
+ stroke-width: 2;
468
+ }
469
+ .node[data-status='active'] .sid {
470
+ fill: var(--active);
471
+ }
472
+ .node[data-status='blocked'] .mark {
473
+ stroke: var(--wait);
474
+ stroke-width: 2;
475
+ }
476
+ .node[data-status='triage'] .mark {
477
+ fill: var(--aside-soft);
478
+ stroke: var(--aside);
479
+ stroke-width: 2;
480
+ stroke-dasharray: 3 2.5;
481
+ }
482
+ .node[data-status='triage'] .sid {
483
+ fill: var(--aside);
484
+ }
485
+ /* 已關閉的站點淺一階:它只是進度,不該跟還要做的票搶注意力。圖例用同一支色。 */
486
+ .node[data-status='done'] .mark {
487
+ fill: var(--done-mark);
488
+ stroke: none;
489
+ }
490
+ .node[data-status='done'] .sid {
491
+ fill: var(--faint);
492
+ font-weight: 500;
493
+ }
494
+ .node[data-status='done'] .sdesc {
495
+ fill: var(--faint);
496
+ }
497
+ .node.selected .mark {
498
+ stroke: var(--ink);
499
+ stroke-width: 3.5;
500
+ }
501
+ svg.has-selection .node:not(.lit) {
502
+ opacity: 0.22;
503
+ }
504
+ svg.has-selection .edge:not(.lit) {
505
+ opacity: 0.1;
506
+ }
507
+
508
+ /* 線名 */
509
+ .tname {
510
+ font-family: var(--mono);
511
+ font-size: 12px;
512
+ font-weight: 600;
513
+ fill: var(--muted);
514
+ font-variant-numeric: tabular-nums;
515
+ }
516
+ .tsub {
517
+ font-family: var(--mono);
518
+ font-size: 10px;
519
+ fill: var(--faint);
520
+ }
521
+
522
+ .map-key {
523
+ display: flex;
524
+ flex-wrap: wrap;
525
+ align-items: center;
526
+ gap: 6px 18px;
527
+ font-family: var(--mono);
528
+ font-size: 11px;
529
+ color: var(--muted);
530
+ }
531
+ .map-key span {
532
+ display: inline-flex;
533
+ align-items: center;
534
+ gap: 6px;
535
+ }
536
+ .map-key i {
537
+ width: 13px;
538
+ height: 13px;
539
+ box-sizing: border-box;
540
+ flex: none;
541
+ }
542
+ .k-ready {
543
+ border-radius: 50%;
544
+ background: radial-gradient(circle, var(--go) 0 3px, var(--card) 3px);
545
+ border: 2.5px solid var(--go);
546
+ }
547
+ .k-active {
548
+ background: var(--active);
549
+ clip-path: polygon(8% 0, 100% 50%, 8% 100%);
550
+ }
551
+ .k-blocked {
552
+ border-radius: 50%;
553
+ background: var(--card);
554
+ border: 2px solid var(--wait);
555
+ }
556
+ .k-triage {
557
+ background: var(--aside-soft);
558
+ border: 1.6px dashed var(--aside);
559
+ transform: rotate(45deg);
560
+ }
561
+ .k-done {
562
+ border-radius: 50%;
563
+ background: var(--done-mark);
564
+ }
565
+
566
+ /* ---------- 清單 ---------- */
567
+
568
+ .list-head {
569
+ display: flex;
570
+ flex-wrap: wrap;
571
+ align-items: baseline;
572
+ justify-content: space-between;
573
+ gap: 8px 16px;
574
+ padding-bottom: 9px;
575
+ border-bottom: 1px solid var(--line-strong);
576
+ }
577
+ .list-head .group-head {
578
+ border-bottom: 0;
579
+ padding-bottom: 0;
580
+ }
581
+ .tabs {
582
+ display: flex;
583
+ flex-wrap: wrap;
584
+ gap: 6px;
585
+ }
586
+ .tab {
587
+ font-family: var(--mono);
588
+ font-size: 11px;
589
+ letter-spacing: 0.06em;
590
+ text-transform: uppercase;
591
+ color: var(--muted);
592
+ background: var(--card);
593
+ border: 1px solid var(--line);
594
+ border-radius: 2px;
595
+ padding: 5px 9px;
596
+ cursor: pointer;
597
+ }
598
+ .tab[aria-pressed='true'] {
599
+ color: var(--ink);
600
+ border-color: var(--ink);
601
+ }
602
+ .tab .n {
603
+ margin-left: 5px;
604
+ color: var(--faint);
605
+ font-variant-numeric: tabular-nums;
606
+ }
607
+
608
+ /* ---------- 清單:一列是一張卡,不是表格 ---------- */
609
+
610
+ .rows {
611
+ display: flex;
612
+ flex-direction: column;
613
+ gap: 6px;
614
+ }
615
+ .row {
616
+ display: grid;
617
+ /* 狀態固定在最後一欄、固定寬度,掃一眼那一欄就知道整份清單的狀況。 */
618
+ grid-template-columns: 132px minmax(0, 1fr) max-content 92px;
619
+ gap: 14px;
620
+ align-items: start;
621
+ padding: 11px 14px;
622
+ background: var(--card);
623
+ border: 1px solid var(--line);
624
+ border-left: 3px solid var(--line-strong);
625
+ border-radius: 2px;
626
+ cursor: pointer;
627
+ }
628
+ .row:hover {
629
+ border-color: var(--line-strong);
630
+ }
631
+ .row:focus-visible {
632
+ outline: 2px solid var(--go);
633
+ outline-offset: 1px;
634
+ }
635
+ .row[data-status='ready'] {
636
+ border-left-color: var(--go);
637
+ }
638
+ .row[data-status='active'] {
639
+ border-left-color: var(--active);
640
+ }
641
+ .row[data-status='blocked'] {
642
+ border-left-color: var(--wait);
643
+ }
644
+ .row[data-status='triage'] {
645
+ border-left-color: var(--aside);
646
+ }
647
+ .row[data-status='done'] {
648
+ border-left-color: var(--done);
649
+ border-style: dashed;
650
+ background: transparent;
651
+ }
652
+ .row.selected {
653
+ background: var(--go-soft);
654
+ border-color: var(--go);
655
+ }
656
+ /* 主票是一組子票的標頭,子票往右縮。 */
657
+ .row[data-haskids='true'] {
658
+ background: var(--paper);
659
+ }
660
+ .row[data-parent] {
661
+ margin-left: 28px;
662
+ }
663
+
664
+ .row .id {
665
+ display: flex;
666
+ align-items: baseline;
667
+ gap: 7px;
668
+ }
669
+ .row .id .no {
670
+ font-family: var(--mono);
671
+ font-size: 13.5px;
672
+ font-weight: 600;
673
+ text-decoration: none;
674
+ border-bottom: 1px solid var(--line-strong);
675
+ font-variant-numeric: tabular-nums;
676
+ }
677
+ .row .id .no:hover {
678
+ border-bottom-color: currentColor;
679
+ }
680
+ .row .who {
681
+ font-family: var(--mono);
682
+ font-size: 10.5px;
683
+ letter-spacing: 0.04em;
684
+ color: var(--faint);
685
+ }
686
+
687
+ .row .what {
688
+ font-size: 14px;
689
+ line-height: 1.45;
690
+ }
691
+ .row.selected .what .title {
692
+ font-weight: 600;
693
+ }
694
+ .row .waits {
695
+ display: block;
696
+ margin-top: 3px;
697
+ font-family: var(--mono);
698
+ font-size: 11.5px;
699
+ color: var(--muted);
700
+ font-variant-numeric: tabular-nums;
701
+ }
702
+ .row .waits .more {
703
+ color: var(--faint);
704
+ }
705
+
706
+ .row .step {
707
+ display: flex;
708
+ justify-content: flex-end;
709
+ min-width: 0;
710
+ }
711
+ .row .step .next {
712
+ white-space: nowrap;
713
+ }
714
+ .row .gate {
715
+ display: flex;
716
+ justify-content: flex-start;
717
+ }
718
+ .row .gate .pill {
719
+ white-space: nowrap;
720
+ }
721
+
722
+ /* 可複製的指令。看起來就是可按的,按完當場說一聲。 */
723
+ .copy {
724
+ font-family: var(--mono);
725
+ font-size: 11.5px;
726
+ line-height: 1.4;
727
+ color: var(--muted);
728
+ background: var(--paper);
729
+ border: 1px solid var(--line);
730
+ border-radius: 2px;
731
+ padding: 2px 7px;
732
+ cursor: pointer;
733
+ white-space: nowrap;
734
+ }
735
+ .copy:hover {
736
+ color: var(--ink);
737
+ border-color: var(--line-strong);
738
+ }
739
+ .copy[data-copied='true'] {
740
+ color: var(--go);
741
+ border-color: var(--go);
742
+ background: var(--go-soft);
743
+ }
744
+ .row[data-status='done'] .what,
745
+ .row[data-status='done'] .id .no {
746
+ color: var(--faint);
747
+ }
748
+
749
+ .fold-slot {
750
+ display: inline-flex;
751
+ }
752
+
753
+ /* 就地展開的細節:直接接在那一列後面,共用 .detail 的樣子。 */
754
+ .rows > .detail.expand {
755
+ margin: -2px 0 4px 28px;
756
+ border-left-width: 3px;
757
+ }
758
+
759
+ .pill {
760
+ display: inline-block;
761
+ font-family: var(--mono);
762
+ font-size: 10px;
763
+ letter-spacing: 0.07em;
764
+ text-transform: uppercase;
765
+ padding: 3px 7px;
766
+ border-radius: 2px;
767
+ white-space: nowrap;
768
+ }
769
+ .pill[data-status='ready'] {
770
+ background: var(--go-soft);
771
+ color: var(--go);
772
+ }
773
+ .pill[data-status='active'] {
774
+ background: var(--active-soft);
775
+ color: var(--active);
776
+ }
777
+ .pill[data-status='blocked'] {
778
+ background: var(--wait-soft);
779
+ color: var(--wait);
780
+ }
781
+ .pill[data-status='triage'] {
782
+ background: var(--aside-soft);
783
+ color: var(--aside);
784
+ }
785
+ .pill[data-status='done'] {
786
+ background: var(--done-soft);
787
+ color: var(--done);
788
+ }
789
+ .next {
790
+ display: inline-block;
791
+ font-family: var(--mono);
792
+ font-size: 11.5px;
793
+ color: var(--muted);
794
+ }
795
+ .label {
796
+ display: inline-block;
797
+ font-family: var(--mono);
798
+ font-size: 10px;
799
+ letter-spacing: 0.05em;
800
+ padding: 3px 6px;
801
+ border-radius: 2px;
802
+ border: 1px solid var(--line);
803
+ color: var(--muted);
804
+ margin-right: 4px;
805
+ }
806
+
807
+ footer {
808
+ font-family: var(--mono);
809
+ font-size: 11.5px;
810
+ line-height: 1.8;
811
+ color: var(--faint);
812
+ border-top: 1px solid var(--line);
813
+ padding-top: 16px;
814
+ display: flex;
815
+ flex-direction: column;
816
+ gap: 2px;
817
+ }
818
+ footer code {
819
+ color: var(--muted);
820
+ }
821
+
822
+ @media (max-width: 720px) {
823
+ .detail {
824
+ grid-template-columns: 1fr;
825
+ }
826
+ .row {
827
+ grid-template-columns: 1fr;
828
+ gap: 6px;
829
+ }
830
+ .row .step {
831
+ justify-content: flex-start;
832
+ }
833
+ }
834
+ @media (prefers-reduced-motion: reduce) {
835
+ * {
836
+ transition: none !important;
837
+ }
838
+ }
839
+ </style>
840
+
841
+ <script id="issue-map-data" type="application/json">
842
+ {}
843
+ </script>
844
+
845
+ <div class="page">
846
+ <header class="masthead">
847
+ <div class="eyebrow" id="eyebrow"></div>
848
+ <h1 id="page-title">開發地圖</h1>
849
+ <p class="lede" id="lede"></p>
850
+ <div class="stats" id="stats"></div>
851
+ </header>
852
+
853
+ <div class="detail" id="detail"></div>
854
+
855
+ <div id="groups"></div>
856
+
857
+ <section class="group">
858
+ <div class="list-head">
859
+ <div class="group-head">
860
+ <h2>清單</h2>
861
+ <span class="sub" id="list-sub"></span>
862
+ </div>
863
+ <div class="tabs" id="tabs" role="group" aria-label="狀態篩選"></div>
864
+ </div>
865
+ <div class="rows" id="rows"></div>
866
+ </section>
867
+
868
+ <footer>
869
+ <div>狀態的權威是 GitHub Issues。這一頁是快照,頁面上不能改狀態。</div>
870
+ <div>
871
+ 重跑 <code>bun run issue-map</code> 產檔,或
872
+ <code>bun run issue-map:serve</code> 讓重新整理就是最新。
873
+ </div>
874
+ <div id="foot-config"></div>
875
+ </footer>
876
+ </div>
877
+
878
+ <script id="issue-map-code"></script>