hyper-pm-web 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,1261 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <meta name="color-scheme" content="light" />
7
+ <title>hyper-pm</title>
8
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
9
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
10
+ <link
11
+ href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:ital,wght@0,400;0,500;0,600;0,700;1,400&family=IBM+Plex+Mono:wght@400;500&display=swap"
12
+ rel="stylesheet"
13
+ />
14
+ <style>
15
+ :root {
16
+ --font-sans: "IBM Plex Sans", system-ui, -apple-system, sans-serif;
17
+ --font-mono: "IBM Plex Mono", ui-monospace, monospace;
18
+ --bg: #f4f4f5;
19
+ --bg-elevated: #ffffff;
20
+ --text: #18181b;
21
+ --text-secondary: #52525b;
22
+ --text-tertiary: #a1a1aa;
23
+ --border: #e4e4e7;
24
+ --border-strong: #d4d4d8;
25
+ --sidebar-bg: #09090b;
26
+ --sidebar-surface: rgba(255, 255, 255, 0.04);
27
+ --sidebar-hover: rgba(255, 255, 255, 0.07);
28
+ --sidebar-active: rgba(255, 255, 255, 0.11);
29
+ --sidebar-text: #fafafa;
30
+ --sidebar-muted: #a1a1aa;
31
+ --accent: #4338ca;
32
+ --accent-hover: #3730a3;
33
+ --accent-subtle: #eef2ff;
34
+ --danger: #b91c1c;
35
+ --danger-bg: #fef2f2;
36
+ --radius-sm: 6px;
37
+ --radius: 10px;
38
+ --radius-lg: 14px;
39
+ --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.04);
40
+ --shadow: 0 1px 3px rgba(0, 0, 0, 0.06), 0 4px 12px rgba(0, 0, 0, 0.04);
41
+ --shadow-lg:
42
+ 0 4px 6px -1px rgba(0, 0, 0, 0.05),
43
+ 0 12px 24px -4px rgba(0, 0, 0, 0.08);
44
+ --ease: cubic-bezier(0.4, 0, 0.2, 1);
45
+ }
46
+
47
+ *,
48
+ *::before,
49
+ *::after {
50
+ box-sizing: border-box;
51
+ }
52
+
53
+ html {
54
+ -webkit-font-smoothing: antialiased;
55
+ -moz-osx-font-smoothing: grayscale;
56
+ }
57
+
58
+ html.history-modal-open {
59
+ overflow: hidden;
60
+ }
61
+
62
+ body {
63
+ margin: 0;
64
+ font-family: var(--font-sans);
65
+ font-size: 15px;
66
+ line-height: 1.5;
67
+ color: var(--text);
68
+ background: var(--bg);
69
+ min-height: 100vh;
70
+ }
71
+
72
+ .app-shell {
73
+ display: flex;
74
+ min-height: 100vh;
75
+ }
76
+
77
+ .sidebar {
78
+ width: 16.25rem;
79
+ flex-shrink: 0;
80
+ background: var(--sidebar-bg);
81
+ color: var(--sidebar-text);
82
+ display: flex;
83
+ flex-direction: column;
84
+ padding: 1.25rem 0 0;
85
+ border-right: 1px solid rgba(255, 255, 255, 0.06);
86
+ box-shadow: 4px 0 24px rgba(0, 0, 0, 0.12);
87
+ }
88
+
89
+ .brand {
90
+ font-weight: 600;
91
+ font-size: 1.125rem;
92
+ letter-spacing: -0.02em;
93
+ padding: 0 1rem 1.25rem;
94
+ margin: 0 0.75rem;
95
+ border-bottom: 1px solid rgba(255, 255, 255, 0.08);
96
+ }
97
+
98
+ .brand span {
99
+ display: block;
100
+ font-size: 0.6875rem;
101
+ font-weight: 500;
102
+ letter-spacing: 0.12em;
103
+ text-transform: uppercase;
104
+ color: var(--sidebar-muted);
105
+ margin-bottom: 0.25rem;
106
+ }
107
+
108
+ nav[aria-label="Main navigation"] {
109
+ flex: 1;
110
+ padding: 0.5rem 0;
111
+ overflow-y: auto;
112
+ }
113
+
114
+ .nav-section {
115
+ font-size: 0.625rem;
116
+ font-weight: 600;
117
+ letter-spacing: 0.14em;
118
+ text-transform: uppercase;
119
+ color: var(--sidebar-muted);
120
+ padding: 1rem 1.25rem 0.375rem;
121
+ }
122
+
123
+ .nav-btn {
124
+ display: flex;
125
+ align-items: center;
126
+ width: calc(100% - 1rem);
127
+ margin: 0.125rem 0.5rem;
128
+ text-align: left;
129
+ padding: 0.625rem 0.875rem;
130
+ border: none;
131
+ border-radius: var(--radius-sm);
132
+ background: transparent;
133
+ color: var(--sidebar-text);
134
+ font: inherit;
135
+ font-size: 0.9375rem;
136
+ font-weight: 500;
137
+ cursor: pointer;
138
+ transition:
139
+ background 0.15s var(--ease),
140
+ color 0.15s var(--ease);
141
+ }
142
+
143
+ .nav-btn:hover {
144
+ background: var(--sidebar-hover);
145
+ }
146
+
147
+ .nav-btn[aria-current="true"] {
148
+ background: var(--sidebar-active);
149
+ color: #fff;
150
+ box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08);
151
+ }
152
+
153
+ .workspace {
154
+ flex: 1;
155
+ display: flex;
156
+ flex-direction: column;
157
+ min-width: 0;
158
+ background: linear-gradient(180deg, #fafafa 0%, var(--bg) 32%);
159
+ }
160
+
161
+ .topbar {
162
+ display: flex;
163
+ align-items: flex-start;
164
+ justify-content: space-between;
165
+ gap: 1rem;
166
+ padding: 1.125rem 1.75rem;
167
+ background: rgba(255, 255, 255, 0.72);
168
+ backdrop-filter: blur(12px);
169
+ -webkit-backdrop-filter: blur(12px);
170
+ border-bottom: 1px solid var(--border);
171
+ position: sticky;
172
+ top: 0;
173
+ z-index: 10;
174
+ }
175
+
176
+ .topbar h1 {
177
+ margin: 0;
178
+ font-size: 1.375rem;
179
+ font-weight: 600;
180
+ letter-spacing: -0.025em;
181
+ line-height: 1.2;
182
+ }
183
+
184
+ .health {
185
+ margin: 0.35rem 0 0;
186
+ font-size: 0.8125rem;
187
+ color: var(--text-secondary);
188
+ max-width: min(36rem, 100%);
189
+ line-height: 1.45;
190
+ }
191
+
192
+ .toolbar {
193
+ display: flex;
194
+ gap: 0.5rem;
195
+ flex-wrap: wrap;
196
+ align-items: center;
197
+ padding-top: 0.125rem;
198
+ }
199
+
200
+ main#main {
201
+ flex: 1;
202
+ padding: 1.5rem 1.75rem 2.5rem;
203
+ overflow: auto;
204
+ max-width: 72rem;
205
+ width: 100%;
206
+ margin: 0 auto;
207
+ }
208
+
209
+ .panel {
210
+ background: var(--bg-elevated);
211
+ border: 1px solid var(--border);
212
+ border-radius: var(--radius-lg);
213
+ padding: 1.25rem 1.375rem;
214
+ box-shadow: var(--shadow-sm);
215
+ }
216
+
217
+ .panel + .panel {
218
+ margin-top: 1.25rem;
219
+ }
220
+
221
+ .panel-head {
222
+ display: flex;
223
+ flex-wrap: wrap;
224
+ align-items: center;
225
+ justify-content: space-between;
226
+ gap: 0.75rem 1rem;
227
+ margin-bottom: 1rem;
228
+ padding-bottom: 0.875rem;
229
+ border-bottom: 1px solid var(--border);
230
+ }
231
+
232
+ .panel-head h2 {
233
+ margin: 0;
234
+ font-size: 1rem;
235
+ font-weight: 600;
236
+ letter-spacing: -0.02em;
237
+ }
238
+
239
+ .panel-head-actions {
240
+ display: flex;
241
+ flex-wrap: wrap;
242
+ align-items: center;
243
+ gap: 0.5rem;
244
+ }
245
+
246
+ .panel h3 {
247
+ margin: 1rem 0 0.5rem;
248
+ font-size: 0.8125rem;
249
+ font-weight: 600;
250
+ text-transform: uppercase;
251
+ letter-spacing: 0.06em;
252
+ color: var(--text-secondary);
253
+ }
254
+
255
+ label {
256
+ display: block;
257
+ font-size: 0.8125rem;
258
+ font-weight: 500;
259
+ color: var(--text-secondary);
260
+ margin: 0.875rem 0 0.375rem;
261
+ }
262
+
263
+ label:first-of-type,
264
+ .panel > label:first-child {
265
+ margin-top: 0;
266
+ }
267
+
268
+ input[type="text"],
269
+ input[type="password"],
270
+ textarea,
271
+ select {
272
+ width: 100%;
273
+ max-width: 36rem;
274
+ font: inherit;
275
+ font-size: 0.9375rem;
276
+ padding: 0.5625rem 0.75rem;
277
+ border: 1px solid var(--border-strong);
278
+ border-radius: var(--radius-sm);
279
+ background: #fafafa;
280
+ color: var(--text);
281
+ transition:
282
+ border-color 0.15s var(--ease),
283
+ box-shadow 0.15s var(--ease),
284
+ background 0.15s var(--ease);
285
+ }
286
+
287
+ input:hover,
288
+ textarea:hover,
289
+ select:hover {
290
+ border-color: #a1a1aa;
291
+ background: #fff;
292
+ }
293
+
294
+ input:focus-visible,
295
+ textarea:focus-visible,
296
+ select:focus-visible {
297
+ outline: none;
298
+ border-color: var(--accent);
299
+ background: #fff;
300
+ box-shadow: 0 0 0 3px var(--accent-subtle);
301
+ }
302
+
303
+ textarea {
304
+ min-height: 5.5rem;
305
+ resize: vertical;
306
+ line-height: 1.55;
307
+ }
308
+
309
+ .row {
310
+ display: flex;
311
+ flex-wrap: wrap;
312
+ gap: 0.5rem;
313
+ align-items: center;
314
+ margin-top: 0.75rem;
315
+ }
316
+
317
+ button {
318
+ font: inherit;
319
+ font-size: 0.875rem;
320
+ font-weight: 500;
321
+ cursor: pointer;
322
+ border-radius: var(--radius-sm);
323
+ padding: 0.5rem 1rem;
324
+ border: 1px solid var(--border-strong);
325
+ background: var(--bg-elevated);
326
+ color: var(--text);
327
+ transition:
328
+ background 0.15s var(--ease),
329
+ border-color 0.15s var(--ease),
330
+ box-shadow 0.15s var(--ease),
331
+ transform 0.1s var(--ease);
332
+ }
333
+
334
+ button:hover {
335
+ background: #fafafa;
336
+ border-color: #a1a1aa;
337
+ }
338
+
339
+ button:active {
340
+ transform: scale(0.98);
341
+ }
342
+
343
+ button:focus-visible {
344
+ outline: none;
345
+ box-shadow: 0 0 0 3px var(--accent-subtle);
346
+ }
347
+
348
+ button.primary {
349
+ background: var(--accent);
350
+ color: #fff;
351
+ border-color: var(--accent);
352
+ box-shadow: 0 1px 2px rgba(67, 56, 202, 0.25);
353
+ }
354
+
355
+ button.primary:hover {
356
+ background: var(--accent-hover);
357
+ border-color: var(--accent-hover);
358
+ }
359
+
360
+ button.danger {
361
+ color: #fff;
362
+ background: var(--danger);
363
+ border-color: var(--danger);
364
+ }
365
+
366
+ button.danger:hover {
367
+ filter: brightness(1.05);
368
+ }
369
+
370
+ button.ghost {
371
+ background: transparent;
372
+ border-color: transparent;
373
+ color: var(--accent);
374
+ }
375
+
376
+ button.ghost:hover {
377
+ background: var(--accent-subtle);
378
+ border-color: transparent;
379
+ }
380
+
381
+ /* Read-mode “Edit” — visible on focus/hover, not a primary CTA */
382
+ button.btn-subtle {
383
+ background: transparent;
384
+ border-color: var(--border);
385
+ color: var(--text-secondary);
386
+ font-weight: 500;
387
+ box-shadow: none;
388
+ }
389
+
390
+ button.btn-subtle:hover {
391
+ background: #fafafa;
392
+ color: var(--text);
393
+ border-color: var(--border-strong);
394
+ }
395
+
396
+ button.btn-inverted {
397
+ background: var(--sidebar-surface);
398
+ border: 1px solid rgba(255, 255, 255, 0.12);
399
+ color: var(--sidebar-text);
400
+ }
401
+
402
+ button.btn-inverted:hover {
403
+ background: var(--sidebar-hover);
404
+ border-color: rgba(255, 255, 255, 0.18);
405
+ }
406
+
407
+ .table-wrap {
408
+ margin-top: 0.25rem;
409
+ border: 1px solid var(--border);
410
+ border-radius: var(--radius);
411
+ overflow: hidden;
412
+ background: #fafafa;
413
+ }
414
+
415
+ table.data-table {
416
+ width: 100%;
417
+ border-collapse: collapse;
418
+ font-size: 0.875rem;
419
+ }
420
+
421
+ .data-table thead {
422
+ background: #f4f4f5;
423
+ }
424
+
425
+ .data-table th,
426
+ .data-table td {
427
+ text-align: left;
428
+ padding: 0.75rem 1rem;
429
+ border-bottom: 1px solid var(--border);
430
+ vertical-align: middle;
431
+ }
432
+
433
+ .data-table th {
434
+ font-size: 0.6875rem;
435
+ font-weight: 600;
436
+ text-transform: uppercase;
437
+ letter-spacing: 0.08em;
438
+ color: var(--text-tertiary);
439
+ }
440
+
441
+ .data-table tbody tr:last-child td {
442
+ border-bottom: none;
443
+ }
444
+
445
+ .data-table tbody tr {
446
+ background: #fff;
447
+ transition: background 0.12s var(--ease);
448
+ }
449
+
450
+ .data-table tbody tr:hover {
451
+ background: #fafafa;
452
+ }
453
+
454
+ .cell-title {
455
+ font-weight: 500;
456
+ color: var(--text);
457
+ max-width: 20rem;
458
+ }
459
+
460
+ .id-chip {
461
+ font-family: var(--font-mono);
462
+ font-size: 0.75rem;
463
+ font-weight: 500;
464
+ color: var(--text-secondary);
465
+ background: #f4f4f5;
466
+ padding: 0.2rem 0.45rem;
467
+ border-radius: 4px;
468
+ border: 1px solid var(--border);
469
+ }
470
+
471
+ .status-pill {
472
+ display: inline-block;
473
+ font-size: 0.6875rem;
474
+ font-weight: 600;
475
+ text-transform: capitalize;
476
+ letter-spacing: 0.02em;
477
+ padding: 0.25rem 0.55rem;
478
+ border-radius: 999px;
479
+ border: 1px solid transparent;
480
+ }
481
+
482
+ .status-pill[data-status="backlog"] {
483
+ background: #f4f4f5;
484
+ color: #52525b;
485
+ border-color: var(--border);
486
+ }
487
+ .status-pill[data-status="todo"] {
488
+ background: #eff6ff;
489
+ color: #1d4ed8;
490
+ border-color: #bfdbfe;
491
+ }
492
+ .status-pill[data-status="in_progress"] {
493
+ background: #fffbeb;
494
+ color: #b45309;
495
+ border-color: #fde68a;
496
+ }
497
+ .status-pill[data-status="done"] {
498
+ background: #ecfdf5;
499
+ color: #047857;
500
+ border-color: #a7f3d0;
501
+ }
502
+ .status-pill[data-status="cancelled"] {
503
+ background: #fef2f2;
504
+ color: #b91c1c;
505
+ border-color: #fecaca;
506
+ }
507
+
508
+ .muted {
509
+ color: var(--text-secondary);
510
+ font-size: 0.875rem;
511
+ line-height: 1.55;
512
+ }
513
+
514
+ .empty-state {
515
+ text-align: center;
516
+ padding: 2.5rem 1.5rem;
517
+ color: var(--text-secondary);
518
+ font-size: 0.9375rem;
519
+ }
520
+
521
+ .stat-grid {
522
+ display: grid;
523
+ grid-template-columns: repeat(auto-fill, minmax(10.5rem, 1fr));
524
+ gap: 1rem;
525
+ }
526
+
527
+ .stat-card {
528
+ padding: 1.125rem 1.25rem;
529
+ border: 1px solid var(--border);
530
+ border-radius: var(--radius);
531
+ background: linear-gradient(145deg, #ffffff 0%, #fafafa 100%);
532
+ box-shadow: var(--shadow-sm);
533
+ }
534
+
535
+ .stat-card .label {
536
+ font-size: 0.75rem;
537
+ font-weight: 600;
538
+ text-transform: uppercase;
539
+ letter-spacing: 0.06em;
540
+ color: var(--text-tertiary);
541
+ margin-bottom: 0.35rem;
542
+ }
543
+
544
+ .stat-card strong {
545
+ display: block;
546
+ font-size: 2rem;
547
+ font-weight: 700;
548
+ letter-spacing: -0.03em;
549
+ font-variant-numeric: tabular-nums;
550
+ line-height: 1.1;
551
+ color: var(--text);
552
+ }
553
+
554
+ #toast {
555
+ margin: 0 1.75rem;
556
+ padding: 0.625rem 1rem;
557
+ border-radius: var(--radius-sm);
558
+ font-size: 0.875rem;
559
+ font-weight: 500;
560
+ display: none;
561
+ }
562
+
563
+ #toast.show {
564
+ display: block;
565
+ }
566
+
567
+ #toast.error {
568
+ background: var(--danger-bg);
569
+ color: var(--danger);
570
+ border: 1px solid #fecaca;
571
+ }
572
+
573
+ #toast.ok {
574
+ background: #ecfdf5;
575
+ color: #047857;
576
+ border: 1px solid #a7f3d0;
577
+ }
578
+
579
+ .comment {
580
+ border: 1px solid var(--border);
581
+ padding: 0.875rem 1rem;
582
+ margin: 0.625rem 0;
583
+ background: #fafafa;
584
+ border-radius: var(--radius-sm);
585
+ }
586
+
587
+ .comment-meta {
588
+ font-size: 0.75rem;
589
+ font-weight: 500;
590
+ color: var(--text-tertiary);
591
+ margin-bottom: 0.375rem;
592
+ }
593
+
594
+ .sidebar-footer {
595
+ margin-top: auto;
596
+ padding: 1.125rem 1rem 1.25rem;
597
+ border-top: 1px solid rgba(255, 255, 255, 0.08);
598
+ font-size: 0.8125rem;
599
+ }
600
+
601
+ .sidebar-footer label {
602
+ color: var(--sidebar-muted);
603
+ margin-top: 0;
604
+ font-size: 0.6875rem;
605
+ text-transform: uppercase;
606
+ letter-spacing: 0.1em;
607
+ }
608
+
609
+ .sidebar-footer input {
610
+ max-width: 100%;
611
+ margin-top: 0.375rem;
612
+ background: rgba(0, 0, 0, 0.25);
613
+ border: 1px solid rgba(255, 255, 255, 0.12);
614
+ color: var(--sidebar-text);
615
+ }
616
+
617
+ .sidebar-footer input::placeholder {
618
+ color: #71717a;
619
+ }
620
+
621
+ .sidebar-footer input:focus-visible {
622
+ border-color: rgba(255, 255, 255, 0.35);
623
+ box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.12);
624
+ }
625
+
626
+ code {
627
+ font-family: var(--font-mono);
628
+ font-size: 0.8125em;
629
+ background: #f4f4f5;
630
+ padding: 0.15em 0.4em;
631
+ border-radius: 4px;
632
+ border: 1px solid var(--border);
633
+ }
634
+
635
+ .icon-refresh {
636
+ display: inline-block;
637
+ width: 1em;
638
+ height: 1em;
639
+ margin-right: 0.35em;
640
+ vertical-align: -0.15em;
641
+ }
642
+
643
+ .filter-bar {
644
+ padding: 0.875rem 1rem;
645
+ background: #fafafa;
646
+ border: 1px solid var(--border);
647
+ border-radius: var(--radius);
648
+ margin-bottom: 1rem;
649
+ }
650
+
651
+ .filter-bar label {
652
+ margin-top: 0;
653
+ margin-bottom: 0.35rem;
654
+ }
655
+
656
+ .lead {
657
+ margin: 0 0 1rem;
658
+ line-height: 1.55;
659
+ }
660
+
661
+ .back-link {
662
+ margin-bottom: 0.75rem;
663
+ }
664
+
665
+ .detail-page-top {
666
+ margin: 0 0 1rem;
667
+ }
668
+
669
+ .detail-page-top .detail-back {
670
+ font-size: 0.875rem;
671
+ font-weight: 500;
672
+ padding: 0.35rem 0.5rem;
673
+ margin: 0 -0.35rem 0 -0.5rem;
674
+ }
675
+
676
+ .pre-out {
677
+ font-family: var(--font-mono);
678
+ font-size: 0.8125rem;
679
+ line-height: 1.5;
680
+ white-space: pre-wrap;
681
+ background: #fafafa;
682
+ padding: 1rem;
683
+ border-radius: var(--radius);
684
+ border: 1px solid var(--border);
685
+ max-height: 22rem;
686
+ overflow: auto;
687
+ margin-top: 0.75rem;
688
+ }
689
+
690
+ .panel-tools h2 {
691
+ margin: 0;
692
+ }
693
+
694
+ /* Ticket (and similar) detail: main column + metadata sidebar */
695
+ .issue-detail-layout {
696
+ display: grid;
697
+ gap: 1.5rem;
698
+ align-items: start;
699
+ }
700
+
701
+ @media (min-width: 768px) {
702
+ .issue-detail-layout {
703
+ grid-template-columns: minmax(0, 1fr) 16.5rem;
704
+ gap: 1.75rem 2rem;
705
+ }
706
+ }
707
+
708
+ .issue-main input[type="text"],
709
+ .issue-main textarea {
710
+ max-width: none;
711
+ }
712
+
713
+ .issue-sidebar select {
714
+ max-width: none;
715
+ }
716
+
717
+ .issue-panel-head.panel-head {
718
+ margin-bottom: 0.75rem;
719
+ }
720
+
721
+ .panel-head h2.issue-title {
722
+ margin: 0;
723
+ font-size: 1.375rem;
724
+ font-weight: 600;
725
+ letter-spacing: -0.03em;
726
+ line-height: 1.25;
727
+ color: var(--text);
728
+ }
729
+
730
+ @media (min-width: 768px) {
731
+ .panel-head h2.issue-title {
732
+ font-size: 1.625rem;
733
+ }
734
+ }
735
+
736
+ .issue-kicker {
737
+ font-size: 0.8125rem;
738
+ }
739
+
740
+ .issue-body {
741
+ margin-top: 0.25rem;
742
+ padding-top: 0.25rem;
743
+ }
744
+
745
+ .issue-body .read-body {
746
+ font-size: 1rem;
747
+ line-height: 1.65;
748
+ }
749
+
750
+ .issue-sidebar {
751
+ padding-top: 0.25rem;
752
+ }
753
+
754
+ @media (min-width: 768px) {
755
+ .issue-sidebar {
756
+ padding-top: 0;
757
+ padding-left: 1.25rem;
758
+ margin: 0;
759
+ border-left: 1px solid var(--border);
760
+ }
761
+ }
762
+
763
+ @media (max-width: 767.98px) {
764
+ .issue-sidebar {
765
+ padding-top: 1rem;
766
+ border-top: 1px solid var(--border);
767
+ }
768
+ }
769
+
770
+ .issue-meta-stack {
771
+ gap: 1rem;
772
+ margin-top: 0;
773
+ }
774
+
775
+ .issue-meta-stack .read-row .read-label {
776
+ font-size: 0.75rem;
777
+ text-transform: uppercase;
778
+ letter-spacing: 0.06em;
779
+ font-weight: 600;
780
+ }
781
+
782
+ .issue-sidebar-story-nav {
783
+ margin-bottom: 0.5rem;
784
+ }
785
+
786
+ button.link-title.issue-meta-link {
787
+ display: inline;
788
+ vertical-align: baseline;
789
+ font-size: inherit;
790
+ font-weight: 500;
791
+ white-space: normal;
792
+ text-align: left;
793
+ word-break: break-word;
794
+ max-width: 100%;
795
+ }
796
+
797
+ .issue-meta-sep {
798
+ color: var(--text-tertiary);
799
+ user-select: none;
800
+ }
801
+
802
+ .label-pill-wrap {
803
+ display: flex;
804
+ flex-wrap: wrap;
805
+ gap: 0.35rem;
806
+ }
807
+
808
+ .label-pill {
809
+ display: inline-block;
810
+ font-size: 0.75rem;
811
+ font-weight: 500;
812
+ padding: 0.2rem 0.5rem;
813
+ border-radius: 999px;
814
+ background: #f4f4f5;
815
+ border: 1px solid var(--border);
816
+ color: var(--text-secondary);
817
+ }
818
+
819
+ .read-stack {
820
+ display: flex;
821
+ flex-direction: column;
822
+ gap: 1.125rem;
823
+ margin-top: 0.75rem;
824
+ }
825
+
826
+ .read-row .read-label {
827
+ font-size: 0.8125rem;
828
+ font-weight: 500;
829
+ color: var(--text-secondary);
830
+ margin: 0 0 0.35rem;
831
+ }
832
+
833
+ .read-row .read-value {
834
+ margin: 0;
835
+ color: var(--text);
836
+ font-size: 0.9375rem;
837
+ line-height: 1.55;
838
+ }
839
+
840
+ .read-body {
841
+ white-space: pre-wrap;
842
+ }
843
+
844
+ .read-body.md-body,
845
+ .issue-body .read-body.md-body {
846
+ white-space: normal;
847
+ }
848
+
849
+ .read-body.md-body > *:first-child,
850
+ .md-inline > *:first-child {
851
+ margin-top: 0;
852
+ }
853
+
854
+ .read-body.md-body > *:last-child,
855
+ .md-inline > *:last-child {
856
+ margin-bottom: 0;
857
+ }
858
+
859
+ .read-body.md-body p {
860
+ margin: 0.5em 0;
861
+ }
862
+
863
+ .read-body.md-body h1,
864
+ .read-body.md-body h2,
865
+ .read-body.md-body h3 {
866
+ margin: 0.75em 0 0.35em;
867
+ font-weight: 600;
868
+ line-height: 1.3;
869
+ color: var(--text);
870
+ }
871
+
872
+ .read-body.md-body h1 {
873
+ font-size: 1.25rem;
874
+ }
875
+
876
+ .read-body.md-body h2 {
877
+ font-size: 1.125rem;
878
+ }
879
+
880
+ .read-body.md-body h3 {
881
+ font-size: 1rem;
882
+ }
883
+
884
+ .read-body.md-body ul,
885
+ .read-body.md-body ol {
886
+ margin: 0.5em 0;
887
+ padding-left: 1.5rem;
888
+ }
889
+
890
+ .read-body.md-body li {
891
+ margin: 0.2em 0;
892
+ }
893
+
894
+ .read-body.md-body pre {
895
+ overflow-x: auto;
896
+ margin: 0.65em 0;
897
+ padding: 0.75rem 1rem;
898
+ background: #f4f4f5;
899
+ border: 1px solid var(--border);
900
+ border-radius: var(--radius);
901
+ font-size: 0.8125rem;
902
+ line-height: 1.5;
903
+ }
904
+
905
+ .read-body.md-body code {
906
+ font-size: 0.9em;
907
+ background: #f4f4f5;
908
+ padding: 0.12em 0.35em;
909
+ border-radius: 4px;
910
+ }
911
+
912
+ .read-body.md-body pre code {
913
+ background: none;
914
+ padding: 0;
915
+ font-size: inherit;
916
+ }
917
+
918
+ .read-body.md-body blockquote {
919
+ margin: 0.65em 0;
920
+ padding: 0.15em 0 0.15em 1rem;
921
+ border-left: 3px solid var(--border);
922
+ color: var(--text-secondary);
923
+ }
924
+
925
+ .read-body.md-body a,
926
+ .md-inline a {
927
+ color: var(--accent);
928
+ text-decoration: underline;
929
+ text-underline-offset: 2px;
930
+ }
931
+
932
+ .md-inline a:hover {
933
+ color: var(--accent-hover);
934
+ }
935
+
936
+ .issue-title .md-inline a {
937
+ color: var(--accent);
938
+ }
939
+
940
+ .panel-head h2 .md-inline {
941
+ font-weight: inherit;
942
+ font-size: inherit;
943
+ letter-spacing: inherit;
944
+ line-height: inherit;
945
+ color: inherit;
946
+ }
947
+
948
+ .panel-head h2 .md-inline a {
949
+ color: var(--accent);
950
+ }
951
+
952
+ p.read-empty {
953
+ margin: 0;
954
+ font-style: italic;
955
+ }
956
+
957
+ .nav-workflow {
958
+ display: flex;
959
+ flex-direction: column;
960
+ gap: 0.125rem;
961
+ margin: 0 0.5rem 0.5rem;
962
+ padding: 0.5rem 0 0.5rem 0.75rem;
963
+ border-left: 2px solid rgba(255, 255, 255, 0.12);
964
+ }
965
+
966
+ .nav-workflow .nav-btn {
967
+ width: calc(100% - 0.25rem);
968
+ margin-left: 0.125rem;
969
+ }
970
+
971
+ .crumbs {
972
+ display: flex;
973
+ flex-wrap: wrap;
974
+ align-items: center;
975
+ gap: 0.35rem 0.5rem;
976
+ font-size: 0.8125rem;
977
+ color: var(--text-secondary);
978
+ margin: 0 0 0.75rem;
979
+ padding: 0.5rem 0;
980
+ border-bottom: 1px solid var(--border);
981
+ }
982
+
983
+ .crumbs .crumb-btn {
984
+ font-size: inherit;
985
+ padding: 0.2rem 0.45rem;
986
+ margin: 0;
987
+ }
988
+
989
+ .crumb-sep {
990
+ color: var(--text-tertiary);
991
+ user-select: none;
992
+ }
993
+
994
+ .crumb-current {
995
+ font-weight: 500;
996
+ color: var(--text);
997
+ max-width: min(28rem, 100%);
998
+ overflow: hidden;
999
+ text-overflow: ellipsis;
1000
+ white-space: nowrap;
1001
+ }
1002
+
1003
+ .nav-related {
1004
+ display: flex;
1005
+ flex-wrap: wrap;
1006
+ gap: 0.5rem;
1007
+ align-items: center;
1008
+ margin: 0 0 1rem;
1009
+ }
1010
+
1011
+ .filter-context-bar {
1012
+ display: flex;
1013
+ flex-wrap: wrap;
1014
+ align-items: center;
1015
+ justify-content: space-between;
1016
+ gap: 0.75rem;
1017
+ padding: 0.75rem 1rem;
1018
+ margin-bottom: 1rem;
1019
+ background: var(--accent-subtle);
1020
+ border: 1px solid #c7d2fe;
1021
+ border-radius: var(--radius);
1022
+ font-size: 0.875rem;
1023
+ }
1024
+
1025
+ .filter-context-bar .filter-actions {
1026
+ display: flex;
1027
+ flex-wrap: wrap;
1028
+ gap: 0.5rem;
1029
+ }
1030
+
1031
+ .filter-context-entity {
1032
+ font-weight: 600;
1033
+ color: var(--text);
1034
+ }
1035
+
1036
+ .filter-context-entity .md-inline {
1037
+ display: inline;
1038
+ }
1039
+
1040
+ button.link-title {
1041
+ background: none;
1042
+ border: none;
1043
+ padding: 0;
1044
+ margin: 0;
1045
+ font: inherit;
1046
+ font-weight: 500;
1047
+ color: var(--accent);
1048
+ text-align: left;
1049
+ cursor: pointer;
1050
+ text-decoration: underline;
1051
+ text-decoration-thickness: 1px;
1052
+ text-underline-offset: 2px;
1053
+ max-width: 100%;
1054
+ }
1055
+
1056
+ button.link-title:hover {
1057
+ color: var(--accent-hover);
1058
+ }
1059
+
1060
+ .history-modal-backdrop {
1061
+ position: fixed;
1062
+ inset: 0;
1063
+ z-index: 80;
1064
+ display: flex;
1065
+ align-items: center;
1066
+ justify-content: center;
1067
+ padding: 1.25rem;
1068
+ background: rgba(9, 9, 11, 0.45);
1069
+ backdrop-filter: blur(4px);
1070
+ }
1071
+
1072
+ .history-modal {
1073
+ width: min(40rem, 100%);
1074
+ max-height: min(32rem, 88vh);
1075
+ overflow: hidden;
1076
+ display: flex;
1077
+ flex-direction: column;
1078
+ background: var(--bg-elevated);
1079
+ border-radius: var(--radius-lg);
1080
+ box-shadow: var(--shadow-lg);
1081
+ border: 1px solid var(--border);
1082
+ }
1083
+
1084
+ .history-modal header {
1085
+ display: flex;
1086
+ align-items: center;
1087
+ justify-content: space-between;
1088
+ gap: 0.75rem;
1089
+ padding: 1rem 1.125rem;
1090
+ border-bottom: 1px solid var(--border);
1091
+ }
1092
+
1093
+ .history-modal header h2 {
1094
+ margin: 0;
1095
+ font-size: 1.0625rem;
1096
+ font-weight: 600;
1097
+ }
1098
+
1099
+ .history-modal-body {
1100
+ padding: 0.75rem 1.125rem 1.125rem;
1101
+ overflow-y: auto;
1102
+ }
1103
+
1104
+ /*
1105
+ * Timeline: line is positioned from the <ol> edge; each <li> starts after
1106
+ * padding-left, so dot `left` must subtract that gutter or markers sit on the text.
1107
+ */
1108
+ .audit-timeline {
1109
+ --timeline-gutter: 1.625rem;
1110
+ --timeline-line-x: 0.5625rem;
1111
+ list-style: none;
1112
+ margin: 0;
1113
+ padding: 0 0 0 var(--timeline-gutter);
1114
+ position: relative;
1115
+ }
1116
+
1117
+ .audit-timeline::before {
1118
+ content: "";
1119
+ position: absolute;
1120
+ left: var(--timeline-line-x);
1121
+ top: calc(0.75rem + 0.25rem - 1px);
1122
+ bottom: calc(0.75rem + 0.25rem - 1px);
1123
+ width: 2px;
1124
+ background: var(--border-strong);
1125
+ border-radius: 1px;
1126
+ }
1127
+
1128
+ .audit-timeline li {
1129
+ position: relative;
1130
+ padding: 0.75rem 0;
1131
+ border: none;
1132
+ }
1133
+
1134
+ .audit-timeline li::before {
1135
+ content: "";
1136
+ position: absolute;
1137
+ left: calc(var(--timeline-line-x) + 1px - var(--timeline-gutter));
1138
+ top: calc(0.75rem + 0.25rem - 0.25rem);
1139
+ width: 0.5rem;
1140
+ height: 0.5rem;
1141
+ border-radius: 999px;
1142
+ background: var(--accent);
1143
+ border: 2px solid var(--bg-elevated);
1144
+ box-sizing: border-box;
1145
+ transform: translateX(-50%);
1146
+ }
1147
+
1148
+ .audit-ts {
1149
+ font-size: 0.75rem;
1150
+ font-family: var(--font-mono);
1151
+ color: var(--text-secondary);
1152
+ margin-bottom: 0.125rem;
1153
+ }
1154
+
1155
+ .audit-actor {
1156
+ font-size: 0.8125rem;
1157
+ color: var(--text-secondary);
1158
+ margin-bottom: 0.25rem;
1159
+ }
1160
+
1161
+ .audit-title {
1162
+ font-weight: 600;
1163
+ font-size: 0.9375rem;
1164
+ }
1165
+
1166
+ .audit-detail {
1167
+ margin: 0.25rem 0 0;
1168
+ font-size: 0.875rem;
1169
+ color: var(--text-secondary);
1170
+ line-height: 1.45;
1171
+ }
1172
+ </style>
1173
+ </head>
1174
+ <body>
1175
+ <div class="app-shell">
1176
+ <aside class="sidebar">
1177
+ <div class="brand">
1178
+ <span>Workspace</span>
1179
+ hyper-pm
1180
+ </div>
1181
+ <nav aria-label="Main navigation">
1182
+ <div class="nav-section">Plan &amp; track</div>
1183
+ <button type="button" class="nav-btn" data-nav="dashboard">
1184
+ Overview
1185
+ </button>
1186
+ <div
1187
+ class="nav-workflow"
1188
+ role="group"
1189
+ aria-label="Epics, stories, and tickets"
1190
+ >
1191
+ <button type="button" class="nav-btn" data-nav="epics">
1192
+ Epics
1193
+ </button>
1194
+ <button type="button" class="nav-btn" data-nav="stories">
1195
+ Stories
1196
+ </button>
1197
+ <button type="button" class="nav-btn" data-nav="tickets">
1198
+ Tickets
1199
+ </button>
1200
+ </div>
1201
+ <div class="nav-section">Repository</div>
1202
+ <button type="button" class="nav-btn" data-nav="tools">Tools</button>
1203
+ <button type="button" class="nav-btn" data-nav="advanced">
1204
+ Advanced CLI
1205
+ </button>
1206
+ </nav>
1207
+ <div class="sidebar-footer">
1208
+ <label for="bearer">API token</label>
1209
+ <input
1210
+ type="password"
1211
+ id="bearer"
1212
+ autocomplete="off"
1213
+ placeholder="Optional bearer…"
1214
+ />
1215
+ <div class="row" style="margin-top: 0.625rem">
1216
+ <button type="button" id="saveToken" class="btn-inverted">
1217
+ Save token
1218
+ </button>
1219
+ </div>
1220
+ </div>
1221
+ </aside>
1222
+ <div class="workspace">
1223
+ <header class="topbar">
1224
+ <div>
1225
+ <h1 id="pageTitle">Overview</h1>
1226
+ <p id="healthLine" class="health">Loading…</p>
1227
+ </div>
1228
+ <div class="toolbar">
1229
+ <button type="button" id="btnRefresh" class="primary">
1230
+ <svg
1231
+ class="icon-refresh"
1232
+ aria-hidden="true"
1233
+ viewBox="0 0 20 20"
1234
+ fill="currentColor"
1235
+ >
1236
+ <path
1237
+ fill-rule="evenodd"
1238
+ d="M4 2a1 1 0 011 1v2.101a7.002 7.002 0 0111.601 2.566 1 1 0 11-1.885.666A5.002 5.002 0 005.999 7H9a1 1 0 010 2H4a1 1 0 01-1-1V3a1 1 0 011-1zm.008 9.057a1 1 0 011.276.61A5.002 5.002 0 0014.001 13H11a1 1 0 110-2h5a1 1 0 011 1v5a1 1 0 11-2 0v-2.101a7.002 7.002 0 01-11.601-2.566 1 1 0 01.61-1.276z"
1239
+ clip-rule="evenodd"
1240
+ />
1241
+ </svg>
1242
+ Refresh
1243
+ </button>
1244
+ </div>
1245
+ </header>
1246
+ <div id="toast" role="status" aria-live="polite"></div>
1247
+ <main id="main" tabindex="-1"></main>
1248
+ </div>
1249
+ </div>
1250
+ <script
1251
+ src="https://cdn.jsdelivr.net/npm/marked@12.0.2/marked.min.js"
1252
+ crossorigin="anonymous"
1253
+ ></script>
1254
+ <script
1255
+ src="https://cdn.jsdelivr.net/npm/dompurify@3.2.4/dist/purify.min.js"
1256
+ crossorigin="anonymous"
1257
+ ></script>
1258
+ <script src="./audit-event-summary.js"></script>
1259
+ <script src="./app.js"></script>
1260
+ </body>
1261
+ </html>