brain0 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,506 @@
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.0" />
6
+ <title>brain0</title>
7
+ <!-- Inter + JetBrains Mono are the documented open substitutes for the Linear families;
8
+ system fonts are the offline fallback. -->
9
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
10
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
11
+ <link rel="icon" type="image/svg+xml" href="/brain0-logo.svg" />
12
+ <link
13
+ href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap"
14
+ rel="stylesheet"
15
+ />
16
+ <style>
17
+ /* ── Linear design tokens ─────────────────────────────────────────────── */
18
+ :root {
19
+ color-scheme: dark;
20
+ --canvas: #010102;
21
+ --surface-1: #0f1011;
22
+ --surface-2: #141516;
23
+ --surface-3: #18191a;
24
+ --hairline: #23252a;
25
+ --hairline-strong: #34343a;
26
+ --ink: #f7f8f8;
27
+ --ink-muted: #d0d6e0;
28
+ --ink-subtle: #8a8f98;
29
+ --ink-tertiary: #62666d;
30
+ --accent: #5e6ad2;
31
+ --accent-hover: #828fff;
32
+ --accent-focus: #5e69d1;
33
+ --success: #27a644;
34
+ --danger: #d65c5c;
35
+ --font-sans: "Inter", "SF Pro Display", -apple-system, system-ui, "Segoe UI", Roboto, sans-serif;
36
+ --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
37
+ --r-md: 8px;
38
+ --r-lg: 12px;
39
+ --r-xl: 16px;
40
+ --r-pill: 9999px;
41
+ --panel-w: 440px;
42
+ }
43
+ * { box-sizing: border-box; }
44
+ body {
45
+ margin: 0; overflow: hidden;
46
+ font-family: var(--font-sans);
47
+ font-size: 14px; line-height: 1.5; letter-spacing: -0.05px;
48
+ background: var(--canvas); color: var(--ink);
49
+ -webkit-font-smoothing: antialiased;
50
+ }
51
+
52
+ /* ── Top nav (Linear top-nav: 56px, canvas, hairline rule) ────────────── */
53
+ #toolbar {
54
+ position: fixed; top: 0; left: 0; right: 0; height: 56px; z-index: 10;
55
+ display: flex; align-items: center; gap: 16px; padding: 0 20px;
56
+ background: rgba(1, 1, 2, 0.82); border-bottom: 1px solid var(--hairline);
57
+ backdrop-filter: blur(8px);
58
+ }
59
+ .brand { display: flex; align-items: center; color: var(--ink); }
60
+ .brand svg { height: 22px; width: auto; display: block; }
61
+
62
+ #toolbar label { font-size: 12px; color: var(--ink-subtle); display: flex; align-items: center; gap: 8px; }
63
+ #toolbar .spacer { flex: 1; }
64
+
65
+ /* ── Refresh button + live status (mirrors the viewctl button + tl-now styling) ───────── */
66
+ .tb-btn {
67
+ color: var(--ink); background: var(--surface-2); border: 1px solid var(--hairline);
68
+ border-radius: var(--r-md); font-size: 12px; padding: 5px 12px; cursor: pointer;
69
+ transition: background 0.12s ease, border-color 0.12s ease;
70
+ }
71
+ .tb-btn:hover:not(:disabled) { background: var(--surface-3); border-color: var(--hairline-strong); }
72
+ .tb-btn:disabled { opacity: 0.5; cursor: default; }
73
+ .tb-status { font-family: var(--font-mono); font-size: 11px; color: var(--accent-hover); min-width: 120px; }
74
+
75
+ /* ── Timeline scrubber: dated edges + live cutoff + filled track ───────── */
76
+ .timeline { display: flex; flex-direction: column; gap: 3px; width: 340px; }
77
+ .tl-top { display: flex; align-items: baseline; justify-content: space-between; }
78
+ .tl-label { font-size: 11px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.5px; color: var(--ink-subtle); }
79
+ .tl-now { font-family: var(--font-mono); font-size: 11px; color: var(--accent-hover); }
80
+ .tl-track { display: flex; align-items: center; gap: 8px; }
81
+ .tl-edge { font-family: var(--font-mono); font-size: 10px; color: var(--ink-tertiary); white-space: nowrap; }
82
+ #timeline {
83
+ flex: 1; -webkit-appearance: none; appearance: none; height: 4px; border-radius: var(--r-pill);
84
+ background: var(--hairline-strong); outline: none; cursor: pointer;
85
+ }
86
+ #timeline::-webkit-slider-thumb {
87
+ -webkit-appearance: none; appearance: none; width: 14px; height: 14px; border-radius: 50%;
88
+ background: var(--accent); border: 2px solid var(--surface-2);
89
+ box-shadow: 0 0 0 1px var(--accent), 0 0 8px rgba(94, 106, 210, 0.5); cursor: pointer;
90
+ }
91
+ #timeline::-moz-range-thumb {
92
+ width: 14px; height: 14px; border: 2px solid var(--surface-2); border-radius: 50%;
93
+ background: var(--accent); cursor: pointer;
94
+ }
95
+ #timeline::-moz-range-progress { background: var(--accent); height: 4px; border-radius: var(--r-pill); }
96
+ /* ── Legend: fixed bottom-left overlay over the graph ─────────────────── */
97
+ #legend {
98
+ position: fixed; left: 20px; bottom: 24px; z-index: 11;
99
+ display: flex; flex-direction: column; gap: 7px;
100
+ padding: 11px 13px; font-size: 11px; color: var(--ink-subtle);
101
+ background: rgba(15, 16, 17, 0.9); border: 1px solid var(--hairline);
102
+ border-radius: var(--r-md); backdrop-filter: blur(6px);
103
+ }
104
+ #legend .row { display: flex; align-items: center; gap: 8px; }
105
+ #legend .dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }
106
+ #legend .dot-task { background: var(--accent); }
107
+ #legend .riskbar { display: flex; flex-direction: column; gap: 4px; margin-top: 1px; }
108
+ #legend .swatch { width: 104px; height: 6px; border-radius: var(--r-pill);
109
+ background: linear-gradient(90deg, var(--success), #d8b24a, var(--danger)); }
110
+ #legend .scale { display: flex; justify-content: space-between; width: 104px;
111
+ color: var(--ink-tertiary); font-size: 10px; }
112
+
113
+ /* ── View control: level-of-detail indicator + zoom (bottom-right, before the sidebar) ── */
114
+ #viewctl {
115
+ position: fixed; bottom: 24px; right: calc(var(--panel-w) + 20px); z-index: 11;
116
+ display: flex; flex-direction: column; gap: 8px; min-width: 196px;
117
+ padding: 11px 13px; background: rgba(15, 16, 17, 0.9);
118
+ border: 1px solid var(--hairline); border-radius: var(--r-md); backdrop-filter: blur(6px);
119
+ }
120
+ #viewctl .vc-title { font-size: 10px; font-weight: 500; text-transform: uppercase;
121
+ letter-spacing: 0.5px; color: var(--ink-subtle); }
122
+ #viewctl .lod { display: flex; align-items: center; gap: 3px; font-size: 11px; color: var(--ink-tertiary); }
123
+ #viewctl .lod-sep { opacity: 0.45; }
124
+ #viewctl .lod-step { cursor: pointer; padding: 1px 5px; border-radius: 4px;
125
+ transition: color 0.12s ease, background 0.12s ease; }
126
+ #viewctl .lod-step:hover { color: var(--ink-muted); }
127
+ #viewctl .lod-step.active { color: var(--accent-hover); font-weight: 600;
128
+ background: color-mix(in srgb, var(--accent) 18%, transparent); }
129
+ #viewctl .zoom { display: flex; align-items: center; gap: 8px; }
130
+ #viewctl .zoom button {
131
+ width: 26px; height: 26px; display: inline-flex; align-items: center; justify-content: center;
132
+ font-size: 16px; line-height: 1; color: var(--ink); background: var(--surface-2);
133
+ border: 1px solid var(--hairline); border-radius: var(--r-md); cursor: pointer;
134
+ transition: background 0.12s ease, border-color 0.12s ease;
135
+ }
136
+ #viewctl .zoom button:hover { background: var(--surface-3); border-color: var(--hairline-strong); }
137
+ #viewctl #zoom-pct { font-family: var(--font-mono); font-size: 11px; color: var(--ink-muted);
138
+ min-width: 42px; text-align: center; }
139
+ #viewctl #zoom-fit { margin-left: auto; font-size: 13px; }
140
+
141
+ #stage { position: fixed; inset: 56px var(--panel-w) 0 0; }
142
+
143
+ /* ── Detail panel = fixed docked reading pane (always present, not a floating popup) ──── */
144
+ #panel {
145
+ position: fixed; top: 56px; right: 0; bottom: 0; width: var(--panel-w); z-index: 10;
146
+ display: block; overflow-y: auto;
147
+ padding: 24px 24px 32px; font-size: 14px; line-height: 1.55;
148
+ background: var(--surface-1); color: var(--ink-muted);
149
+ border-left: 1px solid var(--hairline);
150
+ }
151
+ #panel::-webkit-scrollbar { width: 10px; }
152
+ #panel::-webkit-scrollbar-thumb { background: var(--hairline-strong); border-radius: var(--r-pill); border: 3px solid var(--surface-1); }
153
+ #panel h3 { margin: 0 0 4px; font-size: 20px; font-weight: 600; letter-spacing: -0.4px; color: var(--ink); }
154
+ #panel h4 {
155
+ margin: 22px 0 10px; padding-bottom: 6px; font-size: 11px; font-weight: 500;
156
+ text-transform: uppercase; letter-spacing: 0.6px; color: var(--ink-subtle);
157
+ border-bottom: 1px solid var(--hairline);
158
+ }
159
+ #panel > div { color: var(--ink-muted); margin: 3px 0; }
160
+ #panel b { color: var(--ink); font-weight: 500; }
161
+ #panel .muted { color: var(--ink-subtle); font-size: 13px; }
162
+ #panel .eyebrow {
163
+ font-size: 11px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.6px;
164
+ color: var(--accent-hover); margin-bottom: 4px;
165
+ }
166
+ #panel .version { border-left: 2px solid var(--hairline); padding: 6px 0 8px 12px; margin: 10px 0; }
167
+ #panel .version:hover { border-left-color: var(--hairline-strong); }
168
+ #panel .version .ts { color: var(--ink-tertiary); font-size: 11px; font-family: var(--font-mono); }
169
+ #panel ul { margin: 4px 0; padding-left: 18px; color: var(--ink-muted); }
170
+ #panel li { margin: 2px 0; }
171
+ #panel code { font-family: var(--font-mono); font-size: 12px; color: var(--accent-hover); }
172
+ #panel .empty { color: var(--ink-subtle); }
173
+ /* Visual legend: a real lavender dot and a green→red gradient so meaning reads instantly. */
174
+ #panel .empty .guide-legend { display: flex; flex-direction: column; gap: 12px; margin: 4px 0 2px; }
175
+ #panel .empty .guide-item { display: flex; align-items: flex-start; gap: 11px; }
176
+ #panel .empty .guide-item > div { display: flex; flex-direction: column; line-height: 1.35; }
177
+ #panel .empty .guide-item b { color: var(--ink); font-weight: 500; font-size: 13px; }
178
+ #panel .empty .g-note { color: var(--ink-subtle); font-size: 12px; }
179
+ #panel .empty .g-dot { width: 12px; height: 12px; border-radius: 50%; flex-shrink: 0; margin-top: 2px; }
180
+ #panel .empty .g-dot-task { background: var(--accent); box-shadow: 0 0 8px rgba(94, 106, 210, 0.5); }
181
+ #panel .empty .g-grad { width: 30px; height: 12px; border-radius: var(--r-pill); flex-shrink: 0; margin-top: 2px;
182
+ background: linear-gradient(90deg, var(--success), #d8b24a, var(--danger)); }
183
+ /* Gesture key: verb in a fixed column, result beside it — scannable, not a prose blob. */
184
+ #panel .empty .guide-key { margin: 4px 0 0; display: flex; flex-direction: column; gap: 9px; }
185
+ #panel .empty .guide-row { display: grid; grid-template-columns: 52px 1fr; gap: 12px; align-items: baseline; }
186
+ #panel .empty .guide-row dt { color: var(--ink); font-weight: 500; font-size: 13px; }
187
+ #panel .empty .guide-row dd { margin: 0; color: var(--ink-subtle); font-size: 13px; line-height: 1.4; }
188
+
189
+ /* Contextual header: badge + title + pills, instead of raw key:value rows. */
190
+ #panel .hd { margin-bottom: 6px; }
191
+ #panel .hd-top { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
192
+ #panel .badge {
193
+ font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px;
194
+ padding: 2px 8px; border-radius: var(--r-pill); flex-shrink: 0;
195
+ }
196
+ #panel .badge-task {
197
+ color: var(--accent-hover);
198
+ background: color-mix(in srgb, var(--accent) 20%, transparent);
199
+ border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
200
+ }
201
+ #panel .badge-artifact { color: var(--ink-muted); background: var(--surface-2); border: 1px solid var(--hairline-strong); }
202
+ #panel .hd-title { font-size: 18px; font-weight: 600; letter-spacing: -0.3px; color: var(--ink); line-height: 1.4; }
203
+ #panel .hd-title-sm { font-size: 16px; word-break: break-all; }
204
+ #panel .hd-sub { font-family: var(--font-mono); font-size: 11px; color: var(--ink-tertiary); margin-top: 4px; word-break: break-all; }
205
+ #panel .pills { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
206
+ #panel .pill {
207
+ display: inline-flex; align-items: center; gap: 6px; font-size: 11px; color: var(--ink-muted);
208
+ background: var(--surface-2); border: 1px solid var(--hairline); border-radius: var(--r-pill); padding: 3px 9px;
209
+ }
210
+ #panel .pill .k { color: var(--ink-tertiary); }
211
+ #panel .pill .dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
212
+ #panel .hd-id { font-family: var(--font-mono); font-size: 10px; color: var(--ink-tertiary); margin-top: 10px; word-break: break-all; }
213
+
214
+ /* ── Commit card: message body, prompts-behind, files-changed ─────────── */
215
+ #panel .badge-commit {
216
+ color: var(--accent-hover);
217
+ background: color-mix(in srgb, var(--accent) 20%, transparent);
218
+ border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
219
+ }
220
+ #panel pre.commit-msg {
221
+ white-space: pre-wrap; word-break: break-word; color: var(--ink-muted);
222
+ font-family: var(--font-mono); font-size: 12px; line-height: 1.5;
223
+ background: var(--surface-2); border: 1px solid var(--hairline);
224
+ border-radius: var(--r-md); padding: 10px 12px; margin: 10px 0 0; max-height: 200px;
225
+ }
226
+ /* Prompts behind a commit: clickable summary cards. */
227
+ #panel .prompt-list { display: flex; flex-direction: column; gap: 6px; }
228
+ #panel .prompt-item {
229
+ display: flex; flex-direction: column; gap: 4px; width: 100%; text-align: left; cursor: pointer;
230
+ padding: 9px 11px; border: 1px solid var(--hairline); border-radius: var(--r-md);
231
+ background: var(--surface-2); color: var(--ink-muted); font-family: var(--font-sans);
232
+ transition: background 0.12s ease, border-color 0.12s ease;
233
+ }
234
+ #panel .prompt-item:hover { background: var(--surface-3); border-color: var(--accent-focus); }
235
+ #panel .prompt-sum { font-size: 13px; color: var(--ink); line-height: 1.4; }
236
+ #panel .prompt-meta { font-size: 11px; color: var(--ink-subtle); }
237
+ /* Files read (audit): reuses the "files changed" list style (.cf). Directory dimmed, name in
238
+ the default ink; out-of-repo reads coloured + flagged as the audit red flags. */
239
+ #panel .cf-path .rd-dir { color: var(--ink-tertiary); }
240
+ #panel .cf.cf-ext .cf-path { color: var(--danger); }
241
+ #panel .cf-kind.read-ext {
242
+ color: var(--danger); background: color-mix(in srgb, var(--danger) 16%, transparent);
243
+ border: 1px solid color-mix(in srgb, var(--danger) 40%, transparent);
244
+ border-radius: var(--r-pill); padding: 1px 7px;
245
+ }
246
+ /* ── Smart-chat (debug/audit) result: intent badge, egress notice, finding cards ──────── */
247
+ #panel .badge-debug { color: var(--accent-hover); background: color-mix(in srgb, var(--accent) 20%, transparent);
248
+ border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent); }
249
+ #panel .badge-audit { color: #d8b24a; background: color-mix(in srgb, #d8b24a 18%, transparent);
250
+ border: 1px solid color-mix(in srgb, #d8b24a 40%, transparent); }
251
+ #panel .ask-notice { font-size: 11px; font-family: var(--font-mono); margin: 8px 0 0; padding: 5px 9px;
252
+ border-radius: var(--r-md); border: 1px solid var(--hairline); }
253
+ #panel .ask-notice.ok { color: var(--success); background: color-mix(in srgb, var(--success) 12%, transparent); }
254
+ #panel .ask-notice.warn { color: #e0a33a; background: color-mix(in srgb, #e0a33a 12%, transparent); }
255
+ #panel .ask-notice.err { color: var(--danger); background: color-mix(in srgb, var(--danger) 12%, transparent); }
256
+ #panel .ask-explain { color: var(--ink-muted); margin: 12px 0 0; line-height: 1.55; }
257
+ #panel .dist { font-size: 13px; color: var(--ink-muted); }
258
+ #panel .dist .dist-g { color: var(--success); } #panel .dist .dist-y { color: #d8b24a; } #panel .dist .dist-r { color: var(--danger); }
259
+ #panel .read-ext { font-size: 9px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.4px;
260
+ color: var(--danger); background: color-mix(in srgb, var(--danger) 16%, transparent);
261
+ border: 1px solid color-mix(in srgb, var(--danger) 40%, transparent); border-radius: var(--r-pill); padding: 1px 7px; }
262
+ #panel .finding-list { display: flex; flex-direction: column; gap: 6px; }
263
+ #panel .finding-card { display: flex; flex-direction: column; gap: 4px; width: 100%; text-align: left; cursor: pointer;
264
+ padding: 9px 11px; border: 1px solid var(--hairline); border-left-width: 3px; border-radius: var(--r-md);
265
+ background: var(--surface-2); color: var(--ink-muted); font-family: var(--font-sans);
266
+ transition: background 0.12s ease, border-color 0.12s ease; }
267
+ #panel .finding-card:hover { background: var(--surface-3); }
268
+ #panel .finding-card .f-top { display: flex; align-items: center; gap: 7px; font-size: 10px; text-transform: uppercase;
269
+ letter-spacing: 0.4px; color: var(--ink-subtle); }
270
+ #panel .finding-card .f-verdict { text-transform: none; letter-spacing: 0; color: var(--ink-muted); }
271
+ #panel .finding-card .f-name { font-size: 13px; color: var(--ink); font-family: var(--font-mono); word-break: break-all; }
272
+ #panel .finding-card .f-reason { font-size: 12px; color: var(--ink-subtle); }
273
+ #panel .finding-card .sev-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; background: var(--ink-subtle); }
274
+ #panel .finding-card.sev-info { border-left-color: var(--accent); }
275
+ #panel .finding-card.sev-info .sev-dot { background: var(--accent); }
276
+ #panel .finding-card.sev-warn { border-left-color: #e0a33a; } #panel .finding-card.sev-warn .sev-dot { background: #e0a33a; }
277
+ #panel .finding-card.sev-critical { border-left-color: var(--danger); } #panel .finding-card.sev-critical .sev-dot { background: var(--danger); }
278
+ #panel .finding-card.sev-gold { border-left-color: #d8b24a; } #panel .finding-card.sev-gold .sev-dot { background: #d8b24a; }
279
+
280
+ /* Files changed: a compact git-style list. */
281
+ #panel .cf-list { display: flex; flex-direction: column; gap: 8px; }
282
+ #panel .cf { border-left: 2px solid var(--hairline); padding: 2px 0 2px 12px; }
283
+ #panel .cf-head { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
284
+ #panel .cf-path { font-family: var(--font-mono); font-size: 12px; color: var(--ink); word-break: break-all; }
285
+ #panel .cf-kind { font-size: 10px; text-transform: uppercase; letter-spacing: 0.4px; color: var(--ink-subtle); }
286
+ #panel .cf-stat { font-family: var(--font-mono); font-size: 11px; }
287
+ #panel .cf-stat .add { color: var(--success); }
288
+ #panel .cf-stat .del { color: var(--danger); }
289
+ /* Back link from a prompt to its commit. */
290
+ #panel .back-link {
291
+ margin-bottom: 12px; padding: 4px 10px; cursor: pointer;
292
+ font-family: var(--font-sans); font-size: 12px; color: var(--ink-muted);
293
+ background: transparent; border: 1px solid var(--hairline); border-radius: var(--r-pill);
294
+ transition: color 0.12s ease, border-color 0.12s ease;
295
+ }
296
+ #panel .back-link:hover { color: var(--ink); border-color: var(--hairline-strong); }
297
+
298
+ /* Turn cards: summary prose + file chips grouped by meaning (declared / undeclared / phantom) */
299
+ #panel .vsum { margin: 6px 0 10px; color: var(--ink-muted); font-size: 13.5px; line-height: 1.6; }
300
+ #panel .vfiles { display: flex; flex-direction: column; gap: 8px; }
301
+ #panel .vf-row { display: flex; flex-direction: column; gap: 5px; }
302
+ #panel .vf-label {
303
+ font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px;
304
+ color: var(--ink-subtle); cursor: help;
305
+ }
306
+ #panel .chips { display: flex; flex-wrap: wrap; gap: 5px; }
307
+ #panel .chip {
308
+ font-family: var(--font-mono); font-size: 11px; color: var(--ink-muted);
309
+ background: var(--surface-2); border: 1px solid var(--hairline);
310
+ border-radius: var(--r-pill); padding: 2px 9px; white-space: nowrap;
311
+ }
312
+ /* Changed silently — the drift that matters: amber. */
313
+ #panel .chip-undeclared { color: #d8b24a; border-color: color-mix(in srgb, #d8b24a 45%, transparent);
314
+ background: color-mix(in srgb, #d8b24a 10%, transparent); }
315
+ /* Announced but never observed: hollow/dashed. */
316
+ #panel .chip-phantom { color: var(--ink-tertiary); border-style: dashed; background: transparent; }
317
+ #panel .read-sum { margin: 2px 0 10px; font-size: 12px; color: var(--ink-subtle); }
318
+ /* DLP red flag: this read's content held a secret. */
319
+ #panel .chip-secret { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 45%, transparent);
320
+ background: color-mix(in srgb, var(--danger) 10%, transparent); }
321
+ /* Read from outside the project tree. */
322
+ #panel .chip-external { color: var(--accent-hover); border-color: color-mix(in srgb, var(--accent) 45%, transparent);
323
+ background: color-mix(in srgb, var(--accent) 10%, transparent); }
324
+ #panel .chips:not(.expanded) .chip-hidden { display: none; }
325
+ #panel .chip-more {
326
+ color: var(--ink-tertiary); cursor: pointer; font-family: var(--font-mono);
327
+ transition: color 0.12s ease, border-color 0.12s ease;
328
+ }
329
+ #panel .chip-more:hover { color: var(--ink); border-color: var(--hairline-strong); }
330
+
331
+ /* See-details = Linear button-secondary (surface lift + hairline, 8px) */
332
+ #panel .see-details {
333
+ margin-top: 6px; padding: 5px 12px; cursor: pointer;
334
+ font-family: var(--font-sans); font-size: 12px; font-weight: 500;
335
+ color: var(--ink); background: var(--surface-2);
336
+ border: 1px solid var(--hairline); border-radius: var(--r-md);
337
+ transition: background 0.12s ease, border-color 0.12s ease;
338
+ }
339
+ #panel .see-details:hover { background: var(--surface-3); border-color: var(--hairline-strong); }
340
+
341
+ /* Code / diff (Linear mono in product surfaces) */
342
+ #panel pre {
343
+ white-space: pre-wrap; word-break: break-word;
344
+ background: var(--canvas); border: 1px solid var(--hairline);
345
+ border-radius: var(--r-md); padding: 10px; margin: 6px 0 0;
346
+ font-family: var(--font-mono); font-size: 11px; line-height: 1.5;
347
+ overflow: auto; max-height: 240px;
348
+ }
349
+ #panel pre.diff { max-height: 380px; }
350
+ #panel pre.diff .dl { display: block; }
351
+ #panel pre.diff .add { color: var(--success); background: rgba(39, 166, 68, 0.10); }
352
+ #panel pre.diff .del { color: var(--danger); background: rgba(214, 92, 92, 0.10); }
353
+ #panel pre.diff .hunk { color: var(--accent-hover); }
354
+ #panel pre.diff .meta { color: var(--ink-tertiary); }
355
+ #panel pre.diff .ctx { color: var(--ink-muted); }
356
+
357
+ /* ── Prompt box (bottom-centered, AI-composer aesthetic, text-only) ───── */
358
+ #promptbar {
359
+ position: fixed; bottom: 24px; z-index: 12;
360
+ left: calc((100vw - var(--panel-w)) / 2); transform: translateX(-50%);
361
+ width: min(680px, calc(100vw - var(--panel-w) - 48px));
362
+ }
363
+ .prompt-box {
364
+ background: var(--surface-2); border: 1px solid var(--hairline);
365
+ border-radius: 22px; padding: 10px 12px 8px;
366
+ box-shadow: 0 8px 30px rgba(0, 0, 0, 0.32);
367
+ transition: border-color 0.12s ease, box-shadow 0.12s ease;
368
+ }
369
+ .prompt-box:focus-within {
370
+ border-color: var(--hairline-strong);
371
+ box-shadow: 0 8px 30px rgba(0, 0, 0, 0.42),
372
+ 0 0 0 2px color-mix(in srgb, var(--accent-focus) 35%, transparent);
373
+ }
374
+ #prompt {
375
+ display: block; width: 100%; border: none; outline: none; resize: none;
376
+ background: transparent; color: var(--ink);
377
+ font-family: var(--font-sans); font-size: 15px; line-height: 1.5; letter-spacing: -0.05px;
378
+ max-height: 168px; padding: 4px 4px 0; overflow-y: auto;
379
+ }
380
+ #prompt::placeholder { color: var(--ink-tertiary); }
381
+ #prompt::-webkit-scrollbar { width: 6px; }
382
+ #prompt::-webkit-scrollbar-thumb { background: var(--hairline-strong); border-radius: 3px; }
383
+ .prompt-actions {
384
+ display: flex; align-items: center; justify-content: space-between; gap: 8px; padding-top: 6px;
385
+ }
386
+ .prompt-hint { font-size: 11px; color: var(--ink-tertiary); }
387
+ .prompt-hint kbd {
388
+ font-family: var(--font-mono); font-size: 10px; color: var(--ink-subtle);
389
+ background: var(--surface-3); border: 1px solid var(--hairline);
390
+ border-radius: 4px; padding: 1px 4px;
391
+ }
392
+ .send-btn {
393
+ display: inline-flex; align-items: center; justify-content: center;
394
+ width: 32px; height: 32px; flex-shrink: 0; border: none; border-radius: 9999px;
395
+ cursor: pointer; background: var(--surface-3); color: var(--ink-tertiary);
396
+ transition: background 0.12s ease, color 0.12s ease, transform 0.08s ease;
397
+ }
398
+ .send-btn:disabled { cursor: default; }
399
+ .send-btn.ready { background: var(--accent); color: #fff; }
400
+ .send-btn.ready:hover { background: var(--accent-hover); transform: translateY(-1px); }
401
+ .send-btn svg { width: 16px; height: 16px; }
402
+ </style>
403
+ <script type="module" crossorigin src="/assets/index-QopGLZI_.js"></script>
404
+ </head>
405
+ <body>
406
+ <div id="toolbar">
407
+ <span class="brand" aria-label="Brain0">
408
+ <svg viewBox="-16 -16 472 162" fill="currentColor" role="img" aria-label="Brain0">
409
+ <g>
410
+ <path fill-rule="evenodd" d="M0,10 H20 V45 H72 V130 H0 Z M20,65 H52 V110 H20 Z"></path>
411
+ <path d="M88,45 H132 V65 H108 V130 H88 Z"></path>
412
+ <path d="M148,45 H212 V130 H148 V80 H168 V110 H192 V65 H148 V45 Z"></path>
413
+ <path d="M228,45 H248 V130 H228 Z M228,10 H248 V30 H228 Z"></path>
414
+ <path d="M264,45 H334 V130 H314 V65 H284 V130 H264 Z"></path>
415
+ <path fill-rule="evenodd" d="M350,10 L416,10 L440,34 L440,130 L350,130 Z M370,30 L420,30 L420,110 L370,110 Z"></path>
416
+ <polygon points="411.52,24.70 428.48,35.30 378.48,115.30 361.52,104.70"></polygon>
417
+ </g>
418
+ </svg>
419
+ </span>
420
+ <span class="spacer"></span>
421
+ <button id="refresh" class="tb-btn" title="Re-run the observer and reload the graph">Refresh</button>
422
+ <span id="refresh-status" class="tb-status"></span>
423
+ <div class="timeline">
424
+ <div class="tl-top">
425
+ <span class="tl-label">Timeline</span>
426
+ <span id="tl-now" class="tl-now">all</span>
427
+ </div>
428
+ <div class="tl-track">
429
+ <span id="tl-start" class="tl-edge">—</span>
430
+ <input id="timeline" type="range" min="0" max="100" value="100" step="0.5" />
431
+ <span id="tl-end" class="tl-edge">—</span>
432
+ </div>
433
+ </div>
434
+ </div>
435
+ <div id="stage"></div>
436
+ <div id="legend">
437
+ <div class="row"><span class="dot dot-task"></span> intent (task)</div>
438
+ <div class="row">code by risk</div>
439
+ <div class="riskbar">
440
+ <span class="swatch"></span>
441
+ <div class="scale"><span>safe</span><span>risky</span></div>
442
+ </div>
443
+ </div>
444
+ <div id="viewctl">
445
+ <div class="vc-title">graph level</div>
446
+ <div class="lod" id="lod">
447
+ <span class="lod-step" data-level="repo">repo</span><span class="lod-sep">›</span>
448
+ <span class="lod-step" data-level="module">module</span><span class="lod-sep">›</span>
449
+ <span class="lod-step" data-level="file">file</span><span class="lod-sep">›</span>
450
+ <span class="lod-step" data-level="symbol">symbol</span>
451
+ </div>
452
+ <div class="zoom">
453
+ <button id="zoom-out" aria-label="Zoom out" title="Zoom out">−</button>
454
+ <span id="zoom-pct">100%</span>
455
+ <button id="zoom-in" aria-label="Zoom in" title="Zoom in">+</button>
456
+ <button id="zoom-fit" aria-label="Fit to view" title="Fit to view">⤢</button>
457
+ </div>
458
+ </div>
459
+ <aside id="panel">
460
+ <div class="empty">
461
+ <h3>Inspect the graph</h3>
462
+ <p class="muted">Select any node to read its full history here.</p>
463
+
464
+ <h4>What the dots mean</h4>
465
+ <div class="guide-legend">
466
+ <div class="guide-item">
467
+ <span class="g-dot g-dot-task"></span>
468
+ <div><b>Intents</b><span class="g-note">what an agent set out to do</span></div>
469
+ </div>
470
+ <div class="guide-item">
471
+ <span class="g-grad"></span>
472
+ <div><b>Code</b><span class="g-note">colored by risk — green is safe, red is risky</span></div>
473
+ </div>
474
+ </div>
475
+
476
+ <h4>How to explore</h4>
477
+ <dl class="guide-key">
478
+ <div class="guide-row"><dt>Scroll</dt><dd>zoom the lens: repo → module → file → symbol</dd></div>
479
+ <div class="guide-row"><dt>Drag</dt><dd>pan across the graph</dd></div>
480
+ <div class="guide-row"><dt>Click</dt><dd>open a node's versions, attribution and diffs</dd></div>
481
+ <div class="guide-row"><dt>Ask</dt><dd>type below to light up the agent's chain of edits</dd></div>
482
+ </dl>
483
+ </div>
484
+ </aside>
485
+
486
+ <form id="promptbar" autocomplete="off">
487
+ <div class="prompt-box">
488
+ <textarea
489
+ id="prompt"
490
+ rows="1"
491
+ placeholder="Debug an issue or audit a change…"
492
+ ></textarea>
493
+ <div class="prompt-actions">
494
+ <span class="prompt-hint"><kbd>Enter</kbd> to ask · <kbd>Shift</kbd>+<kbd>Enter</kbd> for a new line</span>
495
+ <button id="send" type="submit" class="send-btn" aria-label="Ask" disabled>
496
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"
497
+ stroke-linecap="round" stroke-linejoin="round">
498
+ <path d="M12 19V5" /><path d="m5 12 7-7 7 7" />
499
+ </svg>
500
+ </button>
501
+ </div>
502
+ </div>
503
+ </form>
504
+
505
+ </body>
506
+ </html>