@sienklogic/plan-build-run 2.30.0 → 2.32.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.
Files changed (32) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dashboard/public/css/settings.css +314 -0
  3. package/dashboard/public/css/timeline.css +240 -0
  4. package/dashboard/src/components/Layout.tsx +4 -0
  5. package/dashboard/src/components/settings/ConfigEditor.tsx +399 -0
  6. package/dashboard/src/components/settings/LogEntryList.tsx +108 -0
  7. package/dashboard/src/components/settings/LogFileList.tsx +36 -0
  8. package/dashboard/src/components/settings/LogViewer.tsx +129 -0
  9. package/dashboard/src/components/settings/SettingsPage.tsx +44 -0
  10. package/dashboard/src/components/timeline/AnalyticsPanel.tsx +99 -0
  11. package/dashboard/src/components/timeline/DependencyGraph.tsx +23 -0
  12. package/dashboard/src/components/timeline/TimelinePage.tsx +124 -0
  13. package/dashboard/src/index.tsx +4 -0
  14. package/dashboard/src/routes/settings.routes.tsx +231 -0
  15. package/dashboard/src/routes/timeline.routes.tsx +50 -0
  16. package/dashboard/src/services/analytics.service.d.ts +24 -0
  17. package/dashboard/src/services/config.service.d.ts +9 -0
  18. package/dashboard/src/services/local-llm-metrics.service.d.ts +26 -0
  19. package/dashboard/src/services/log.service.d.ts +13 -0
  20. package/dashboard/src/services/timeline.service.d.ts +20 -0
  21. package/dashboard/src/services/timeline.service.js +174 -0
  22. package/package.json +1 -1
  23. package/plugins/copilot-pbr/plugin.json +1 -1
  24. package/plugins/cursor-pbr/.cursor-plugin/plugin.json +1 -1
  25. package/plugins/pbr/.claude-plugin/plugin.json +1 -1
  26. package/plugins/pbr/scripts/config-schema.json +12 -0
  27. package/plugins/pbr/scripts/context-budget-check.js +4 -1
  28. package/plugins/pbr/scripts/enforce-pbr-workflow.js +218 -0
  29. package/plugins/pbr/scripts/pre-bash-dispatch.js +7 -0
  30. package/plugins/pbr/scripts/pre-write-dispatch.js +30 -18
  31. package/plugins/pbr/scripts/progress-tracker.js +1 -1
  32. package/plugins/pbr/scripts/validate-task.js +6 -1
package/CHANGELOG.md CHANGED
@@ -5,6 +5,34 @@ All notable changes to Plan-Build-Run will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [2.32.0](https://github.com/SienkLogic/plan-build-run/compare/plan-build-run-v2.31.0...plan-build-run-v2.32.0) (2026-02-24)
9
+
10
+
11
+ ### Features
12
+
13
+ * **42-01:** create settings routes, CSS, wire into app, and add config.service.d.ts ([3c4f953](https://github.com/SienkLogic/plan-build-run/commit/3c4f9531de93acc4e47b4ab6a94f962972c3f6ab))
14
+ * **42-02:** add log viewer routes (page, entries, SSE tail) and CSS ([cbcb47c](https://github.com/SienkLogic/plan-build-run/commit/cbcb47ce31b2e06481e329bfd01597bcc644a4a8))
15
+ * **42-02:** add LogFileList, LogEntryList, and LogViewer components ([3101c12](https://github.com/SienkLogic/plan-build-run/commit/3101c129dbf5e6535b720188be2a49a583008303))
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * **42-02:** move beforeunload cleanup to addEventListener for JSX compatibility ([e582a51](https://github.com/SienkLogic/plan-build-run/commit/e582a51ef628e7596bb42e352dbf8df861d67e07))
21
+
22
+ ## [2.31.0](https://github.com/SienkLogic/plan-build-run/compare/plan-build-run-v2.30.0...plan-build-run-v2.31.0) (2026-02-24)
23
+
24
+
25
+ ### Features
26
+
27
+ * **41-01:** create timeline routes, wire into app, link timeline CSS in Layout ([ffc71c6](https://github.com/SienkLogic/plan-build-run/commit/ffc71c6ff32f72cf09894585e96cfd47d9ebad93))
28
+ * **41-01:** create timeline.service.js with event aggregation and filtering ([f585c2b](https://github.com/SienkLogic/plan-build-run/commit/f585c2b28a35ca028a0dfd6fb98fc3f717b0e42d))
29
+ * **41-01:** create TimelinePage component, EventStreamFragment, and timeline CSS ([105b3d3](https://github.com/SienkLogic/plan-build-run/commit/105b3d3e1fc3ea1f0f71c80301056e7a5ec0b125))
30
+ * **41-02:** add analytics and dependency-graph routes; refactor TimelinePage with section tabs ([4998f40](https://github.com/SienkLogic/plan-build-run/commit/4998f4093097953ca1e1e880413be60e07da08b4))
31
+ * **41-02:** add analytics/graph CSS sections and Mermaid CDN to Layout ([95d8853](https://github.com/SienkLogic/plan-build-run/commit/95d88536e406894021e454bb874d9dcc17abd179))
32
+ * **41-02:** add AnalyticsPanel and DependencyGraph components ([5bb080b](https://github.com/SienkLogic/plan-build-run/commit/5bb080bb363a3e2b56f5e2f2054c15e80dc6be23))
33
+ * **42-01:** create SettingsPage shell and ConfigEditor component (form + raw JSON modes) ([98caf06](https://github.com/SienkLogic/plan-build-run/commit/98caf0651314b4185b9c0e851d1607889956cb7f))
34
+ * **quick-008:** inject PBR workflow directive into SessionStart and PreCompact hooks ([c07574e](https://github.com/SienkLogic/plan-build-run/commit/c07574e32365c18e8c9239b8e4398330ba441182))
35
+
8
36
  ## [2.30.0](https://github.com/SienkLogic/plan-build-run/compare/plan-build-run-v2.29.0...plan-build-run-v2.30.0) (2026-02-24)
9
37
 
10
38
 
@@ -0,0 +1,314 @@
1
+ /* Settings page styles */
2
+
3
+ /* Tab bar */
4
+ .settings-tabs {
5
+ display: flex;
6
+ gap: var(--size-2);
7
+ border-bottom: 2px solid var(--surface-3, #e2e8f0);
8
+ margin-bottom: var(--size-5);
9
+ padding-bottom: 0;
10
+ }
11
+
12
+ /* Mode toggle (Form / Raw JSON) */
13
+ .config-mode-toggle {
14
+ display: flex;
15
+ gap: var(--size-2);
16
+ margin-bottom: var(--size-4);
17
+ }
18
+
19
+ /* Tab buttons — shared by settings-tabs and config-mode-toggle */
20
+ .tab-btn {
21
+ background: none;
22
+ border: none;
23
+ border-bottom: 2px solid transparent;
24
+ padding: var(--size-2) var(--size-4);
25
+ font-size: var(--font-size-1);
26
+ font-weight: 500;
27
+ color: var(--text-2, #64748b);
28
+ cursor: pointer;
29
+ transition: color 0.15s ease, border-color 0.15s ease;
30
+ margin-bottom: -2px;
31
+ }
32
+
33
+ .tab-btn:hover {
34
+ color: var(--text-1, #1e293b);
35
+ }
36
+
37
+ .tab-btn.active {
38
+ color: var(--link, #2563eb);
39
+ border-bottom-color: var(--link, #2563eb);
40
+ }
41
+
42
+ /* Config section card */
43
+ .config-section {
44
+ border: 1px solid var(--surface-3, #e2e8f0);
45
+ border-radius: var(--radius-2);
46
+ padding: var(--size-4);
47
+ margin-bottom: var(--size-4);
48
+ background: var(--surface-1, #f8fafc);
49
+ }
50
+
51
+ .config-section--nested {
52
+ margin-top: var(--size-4);
53
+ background: var(--surface-2, #f1f5f9);
54
+ }
55
+
56
+ /* Section heading */
57
+ .config-section__title {
58
+ font-size: var(--font-size-1);
59
+ font-weight: 600;
60
+ color: var(--text-1, #1e293b);
61
+ margin: 0 0 var(--size-3) 0;
62
+ text-transform: uppercase;
63
+ letter-spacing: 0.05em;
64
+ }
65
+
66
+ /* Individual field row */
67
+ .config-field {
68
+ display: flex;
69
+ align-items: center;
70
+ gap: var(--size-3);
71
+ padding: var(--size-1) 0;
72
+ font-size: var(--font-size-1);
73
+ color: var(--text-1, #1e293b);
74
+ cursor: pointer;
75
+ }
76
+
77
+ .config-field--check {
78
+ flex-direction: row;
79
+ }
80
+
81
+ .config-field__label {
82
+ min-width: 12rem;
83
+ color: var(--text-2, #64748b);
84
+ font-size: var(--font-size-0);
85
+ }
86
+
87
+ .config-field input[type='text'],
88
+ .config-field input[type='number'],
89
+ .config-field select {
90
+ flex: 1;
91
+ padding: var(--size-1) var(--size-2);
92
+ border: 1px solid var(--surface-3, #e2e8f0);
93
+ border-radius: var(--radius-1);
94
+ font-size: var(--font-size-0);
95
+ background: var(--surface-1, #fff);
96
+ color: var(--text-1, #1e293b);
97
+ }
98
+
99
+ .config-field input[readonly] {
100
+ opacity: 0.6;
101
+ cursor: not-allowed;
102
+ }
103
+
104
+ .config-field input[type='checkbox'] {
105
+ width: 1rem;
106
+ height: 1rem;
107
+ accent-color: var(--link, #2563eb);
108
+ cursor: pointer;
109
+ }
110
+
111
+ /* Raw JSON textarea */
112
+ .config-raw-json {
113
+ width: 100%;
114
+ font-family: var(--font-mono, 'JetBrains Mono', monospace);
115
+ font-size: var(--font-size-0);
116
+ padding: var(--size-3);
117
+ border: 1px solid var(--surface-3, #e2e8f0);
118
+ border-radius: var(--radius-2);
119
+ background: var(--surface-1, #f8fafc);
120
+ color: var(--text-1, #1e293b);
121
+ resize: vertical;
122
+ box-sizing: border-box;
123
+ }
124
+
125
+ /* Config actions row */
126
+ .config-actions {
127
+ display: flex;
128
+ justify-content: flex-end;
129
+ margin-bottom: var(--size-3);
130
+ }
131
+
132
+ /* Inline feedback */
133
+ .config-feedback {
134
+ min-height: 1.5rem;
135
+ margin-top: var(--size-2);
136
+ font-size: var(--font-size-0);
137
+ }
138
+
139
+ .feedback--success {
140
+ color: var(--green-7, #15803d);
141
+ font-weight: 500;
142
+ }
143
+
144
+ .feedback--error {
145
+ color: var(--red-7, #b91c1c);
146
+ font-weight: 500;
147
+ }
148
+
149
+ /* Empty state */
150
+ .config-empty {
151
+ font-size: var(--font-size-0);
152
+ color: var(--text-2, #64748b);
153
+ font-style: italic;
154
+ margin: 0;
155
+ }
156
+
157
+ /* Primary button (consistent with other pages) */
158
+ .btn--primary {
159
+ display: inline-flex;
160
+ align-items: center;
161
+ gap: var(--size-2);
162
+ padding: var(--size-2) var(--size-5);
163
+ background: var(--link, #2563eb);
164
+ color: #fff;
165
+ border: none;
166
+ border-radius: var(--radius-2);
167
+ font-size: var(--font-size-1);
168
+ font-weight: 500;
169
+ cursor: pointer;
170
+ transition: background 0.15s ease;
171
+ }
172
+
173
+ .btn--primary:hover {
174
+ background: var(--blue-7, #1d4ed8);
175
+ }
176
+
177
+ /* Dark theme overrides */
178
+ [data-theme='dark'] .config-section {
179
+ background: var(--surface-2, #1e2535);
180
+ border-color: var(--surface-3, #2d3748);
181
+ }
182
+
183
+ [data-theme='dark'] .config-section--nested {
184
+ background: var(--surface-1, #161e2d);
185
+ }
186
+
187
+ [data-theme='dark'] .config-raw-json,
188
+ [data-theme='dark'] .config-field input[type='text'],
189
+ [data-theme='dark'] .config-field input[type='number'],
190
+ [data-theme='dark'] .config-field select {
191
+ background: var(--surface-2, #1e2535);
192
+ border-color: var(--surface-3, #2d3748);
193
+ color: var(--text-1, #e2e8f0);
194
+ }
195
+
196
+ /* ── Log Viewer ─────────────────────────────────────── */
197
+ .log-viewer-layout {
198
+ display: grid;
199
+ grid-template-columns: 220px 1fr;
200
+ gap: var(--size-4);
201
+ height: calc(100vh - var(--size-12));
202
+ }
203
+
204
+ .log-file-sidebar {
205
+ border-right: 1px solid var(--surface-3);
206
+ padding-right: var(--size-3);
207
+ overflow-y: auto;
208
+ }
209
+
210
+ .log-file-list {
211
+ list-style: none;
212
+ padding: 0;
213
+ margin: 0;
214
+ }
215
+
216
+ .log-file-item {
217
+ display: block;
218
+ padding: var(--size-2) var(--size-3);
219
+ border-radius: var(--radius-2);
220
+ text-decoration: none;
221
+ color: var(--text-2);
222
+ font-size: var(--font-size-0);
223
+ margin-block: 2px;
224
+ }
225
+
226
+ .log-file-item:hover { background: var(--surface-2); }
227
+ .log-file-item--active { background: var(--surface-3); color: var(--text-1); font-weight: 500; }
228
+
229
+ .log-file-name { display: block; font-family: var(--font-mono); font-size: 0.75rem; }
230
+ .log-file-size { color: var(--text-2); }
231
+ .log-file-date { color: var(--text-2); }
232
+
233
+ .log-main { overflow-y: auto; padding-right: var(--size-2); }
234
+
235
+ .log-filters {
236
+ display: flex;
237
+ gap: var(--size-3);
238
+ align-items: center;
239
+ margin-bottom: var(--size-3);
240
+ padding: var(--size-2) var(--size-3);
241
+ background: var(--surface-2);
242
+ border-radius: var(--radius-2);
243
+ }
244
+
245
+ .log-table {
246
+ width: 100%;
247
+ border-collapse: collapse;
248
+ font-size: var(--font-size-0);
249
+ }
250
+
251
+ .log-table th,
252
+ .log-table td {
253
+ text-align: left;
254
+ padding: var(--size-1) var(--size-2);
255
+ border-bottom: 1px solid var(--surface-3);
256
+ }
257
+
258
+ .log-table th { color: var(--text-2); font-weight: 500; }
259
+
260
+ .log-badge {
261
+ display: inline-block;
262
+ padding: 1px 6px;
263
+ border-radius: var(--radius-round);
264
+ font-size: 0.7rem;
265
+ font-weight: 600;
266
+ text-transform: uppercase;
267
+ background: var(--surface-3);
268
+ color: var(--text-2);
269
+ }
270
+
271
+ .log-badge--error { background: var(--red-2); color: var(--red-9); }
272
+ .log-badge--warn { background: var(--yellow-2); color: var(--yellow-9); }
273
+ .log-badge--info { background: var(--blue-2); color: var(--blue-9); }
274
+ .log-badge--hook { background: var(--violet-2); color: var(--violet-9); }
275
+ .log-badge--task { background: var(--green-2); color: var(--green-9); }
276
+ .log-badge--agent { background: var(--cyan-2); color: var(--cyan-9); }
277
+
278
+ .log-pagination {
279
+ display: flex;
280
+ gap: var(--size-2);
281
+ align-items: center;
282
+ padding: var(--size-2) 0;
283
+ }
284
+
285
+ .log-tail-indicator {
286
+ display: flex;
287
+ align-items: center;
288
+ gap: var(--size-2);
289
+ font-size: var(--font-size-0);
290
+ color: var(--text-2);
291
+ margin-bottom: var(--size-2);
292
+ }
293
+
294
+ .tail-dot {
295
+ width: 8px;
296
+ height: 8px;
297
+ border-radius: 50%;
298
+ background: var(--surface-3);
299
+ }
300
+
301
+ .tail-dot--active {
302
+ background: var(--green-6);
303
+ animation: pulse 1.5s ease-in-out infinite;
304
+ }
305
+
306
+ @keyframes pulse {
307
+ 0%, 100% { opacity: 1; }
308
+ 50% { opacity: 0.4; }
309
+ }
310
+
311
+ .log-tail-entries { font-family: var(--font-mono); font-size: 0.75rem; color: var(--text-2); }
312
+ .log-tail-row { padding: 2px 0; border-bottom: 1px solid var(--surface-2); }
313
+ .log-empty, .log-prompt { color: var(--text-2); padding: var(--size-4); }
314
+ .log-summary { color: var(--text-2); font-size: var(--font-size-0); margin-bottom: var(--size-2); }
@@ -0,0 +1,240 @@
1
+ /**
2
+ * timeline.css — Timeline page styles
3
+ * Depends on tokens.css for design tokens (--space-*, --color-*, --radius-*, --font-mono)
4
+ */
5
+
6
+ .timeline {
7
+ display: flex;
8
+ flex-direction: column;
9
+ padding: var(--space-lg);
10
+ max-width: 1200px;
11
+ }
12
+
13
+ .timeline__filters {
14
+ display: flex;
15
+ flex-direction: row;
16
+ flex-wrap: wrap;
17
+ gap: var(--space-sm);
18
+ align-items: center;
19
+ padding: var(--space-md);
20
+ background: var(--color-surface);
21
+ border-radius: var(--radius-md);
22
+ margin-bottom: var(--space-lg);
23
+ border: 1px solid var(--color-border);
24
+ }
25
+
26
+ .timeline__filters label {
27
+ display: flex;
28
+ align-items: center;
29
+ gap: var(--space-xs);
30
+ cursor: pointer;
31
+ font-size: 0.875rem;
32
+ }
33
+
34
+ .timeline__stream {
35
+ position: relative;
36
+ }
37
+
38
+ .timeline__list {
39
+ list-style: none;
40
+ padding: 0;
41
+ margin: 0;
42
+ display: flex;
43
+ flex-direction: column;
44
+ gap: 0;
45
+ }
46
+
47
+ .timeline__event {
48
+ display: grid;
49
+ grid-template-columns: 1rem 10rem 9rem 1fr auto;
50
+ align-items: start;
51
+ gap: var(--space-sm);
52
+ padding: var(--space-sm) 0;
53
+ border-bottom: 1px solid var(--color-border);
54
+ }
55
+
56
+ .timeline__event-dot {
57
+ width: 0.5rem;
58
+ height: 0.5rem;
59
+ border-radius: 50%;
60
+ background: var(--color-accent);
61
+ margin-top: 0.35rem;
62
+ }
63
+
64
+ .timeline__event--commit .timeline__event-dot {
65
+ background: var(--color-info, #3b82f6);
66
+ }
67
+
68
+ .timeline__event--todo-completion .timeline__event-dot {
69
+ background: var(--color-success, #22c55e);
70
+ }
71
+
72
+ .timeline__event--phase-transition .timeline__event-dot {
73
+ background: var(--color-warning, #f59e0b);
74
+ }
75
+
76
+ .timeline__event-time {
77
+ font-family: var(--font-mono);
78
+ font-size: 0.8rem;
79
+ color: var(--color-text-dim);
80
+ }
81
+
82
+ .timeline__event-type {
83
+ font-size: 0.75rem;
84
+ padding: 0.1rem 0.4rem;
85
+ border-radius: var(--radius-sm);
86
+ background: var(--color-surface);
87
+ border: 1px solid var(--color-border);
88
+ color: var(--color-text-dim);
89
+ white-space: nowrap;
90
+ }
91
+
92
+ .timeline__event-title {
93
+ font-size: 0.9rem;
94
+ }
95
+
96
+ .timeline__event-author {
97
+ font-size: 0.8rem;
98
+ color: var(--color-text-dim);
99
+ }
100
+
101
+ .timeline__loading {
102
+ color: var(--color-text-dim);
103
+ padding: var(--space-md);
104
+ }
105
+
106
+ .timeline__empty {
107
+ color: var(--color-text-dim);
108
+ padding: var(--space-lg);
109
+ text-align: center;
110
+ }
111
+
112
+ .htmx-indicator {
113
+ opacity: 0;
114
+ transition: opacity 0.2s;
115
+ }
116
+
117
+ .htmx-request .htmx-indicator,
118
+ .htmx-request.htmx-indicator {
119
+ opacity: 1;
120
+ }
121
+
122
+ /* ---- Section tabs ---- */
123
+ .timeline__section-tabs {
124
+ display: flex;
125
+ gap: 0;
126
+ border-bottom: 1px solid var(--color-border);
127
+ margin-bottom: var(--space-lg);
128
+ }
129
+
130
+ .timeline__section-tab {
131
+ padding: var(--space-sm) var(--space-md);
132
+ border: none;
133
+ border-bottom: 2px solid transparent;
134
+ background: none;
135
+ cursor: pointer;
136
+ color: var(--color-text-dim);
137
+ font-size: 0.9rem;
138
+ font-family: var(--font-sans);
139
+ transition: all 0.15s;
140
+ }
141
+
142
+ .timeline__section-tab:hover { color: var(--color-text); }
143
+
144
+ .timeline__section-tab[aria-selected="true"] {
145
+ color: var(--color-accent);
146
+ border-bottom-color: var(--color-accent);
147
+ }
148
+
149
+ /* ---- Analytics panel ---- */
150
+ .analytics-panel {
151
+ display: flex;
152
+ flex-direction: column;
153
+ gap: var(--space-lg);
154
+ }
155
+
156
+ .analytics-panel__section {
157
+ background: var(--color-surface);
158
+ border: 1px solid var(--color-border);
159
+ border-radius: var(--radius-md);
160
+ padding: var(--space-md);
161
+ }
162
+
163
+ .analytics-panel__section h2 {
164
+ font-size: 1rem;
165
+ font-weight: 600;
166
+ margin: 0 0 var(--space-md);
167
+ }
168
+
169
+ .analytics-panel__stats {
170
+ display: flex;
171
+ flex-wrap: wrap;
172
+ gap: var(--space-md);
173
+ margin-bottom: var(--space-md);
174
+ }
175
+
176
+ .analytics-panel__stat {
177
+ display: flex;
178
+ flex-direction: column;
179
+ gap: var(--space-xs);
180
+ min-width: 8rem;
181
+ }
182
+
183
+ .analytics-panel__stat-value {
184
+ font-size: 1.5rem;
185
+ font-weight: 700;
186
+ font-family: var(--font-mono);
187
+ color: var(--color-accent);
188
+ }
189
+
190
+ .analytics-panel__stat-label {
191
+ font-size: 0.8rem;
192
+ color: var(--color-text-dim);
193
+ text-transform: uppercase;
194
+ letter-spacing: 0.05em;
195
+ }
196
+
197
+ .analytics-panel__table {
198
+ width: 100%;
199
+ border-collapse: collapse;
200
+ font-size: 0.875rem;
201
+ }
202
+
203
+ .analytics-panel__table th,
204
+ .analytics-panel__table td {
205
+ text-align: left;
206
+ padding: var(--space-xs) var(--space-sm);
207
+ border-bottom: 1px solid var(--color-border);
208
+ }
209
+
210
+ .analytics-panel__table th {
211
+ color: var(--color-text-dim);
212
+ font-weight: 600;
213
+ font-size: 0.8rem;
214
+ text-transform: uppercase;
215
+ letter-spacing: 0.04em;
216
+ }
217
+
218
+ .analytics-panel__empty,
219
+ .analytics-panel__loading {
220
+ color: var(--color-text-dim);
221
+ padding: var(--space-md);
222
+ }
223
+
224
+ /* ---- Dependency graph ---- */
225
+ .dep-graph {
226
+ background: var(--color-surface);
227
+ border: 1px solid var(--color-border);
228
+ border-radius: var(--radius-md);
229
+ padding: var(--space-md);
230
+ overflow-x: auto;
231
+ }
232
+
233
+ .dep-graph__container {
234
+ min-height: 12rem;
235
+ }
236
+
237
+ .dep-graph__loading {
238
+ color: var(--color-text-dim);
239
+ padding: var(--space-md);
240
+ }
@@ -36,6 +36,8 @@ export function Layout({ title, children, currentView }: LayoutProps) {
36
36
  <link rel="stylesheet" href="/css/status-colors.css" />
37
37
  <link rel="stylesheet" href="/css/command-center.css" />
38
38
  <link rel="stylesheet" href="/css/explorer.css" />
39
+ <link rel="stylesheet" href="/css/timeline.css" />
40
+ <link rel="stylesheet" href="/css/settings.css" />
39
41
 
40
42
  {/* Prevent flash of wrong theme */}
41
43
  {html`<script>
@@ -47,6 +49,8 @@ export function Layout({ title, children, currentView }: LayoutProps) {
47
49
  }
48
50
  })();
49
51
  </script>`}
52
+ <script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js" defer></script>
53
+ {html`<script>document.addEventListener('DOMContentLoaded', function() { mermaid.initialize({ startOnLoad: false, theme: 'neutral' }); });</script>`}
50
54
  </head>
51
55
  <body>
52
56
  <a href="#main-content" class="skip-link">Skip to content</a>