claude-inspect 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.de.md CHANGED
@@ -1,17 +1,33 @@
1
- # claude-inspect
1
+ # claude-inspect – Claude-Code-Dashboard & Monitor für Agenten, Subagenten und Verbrauch
2
2
 
3
- > English: [README.md](README.md) · Website: [brokoskokoli.github.io/claude_inspect](https://brokoskokoli.github.io/claude_inspect/) · Screenshots: [docs/screenshots](docs/screenshots)
3
+ [![npm](https://img.shields.io/npm/v/claude-inspect)](https://www.npmjs.com/package/claude-inspect)
4
+ [![npm downloads](https://img.shields.io/npm/dm/claude-inspect)](https://www.npmjs.com/package/claude-inspect)
5
+ [![CI](https://github.com/brokoskokoli/claude_inspect/actions/workflows/ci.yml/badge.svg)](https://github.com/brokoskokoli/claude_inspect/actions/workflows/ci.yml)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/brokoskokoli/claude_inspect/blob/main/LICENSE)
7
+ [![GitHub stars](https://img.shields.io/github/stars/brokoskokoli/claude_inspect?style=social)](https://github.com/brokoskokoli/claude_inspect)
8
+
9
+ **htop plus Flugschreiber für Claude Code. Keine Hooks, kein Proxy, ein `npx`.**
10
+
11
+ Lokales Live-Dashboard und Monitor für Claude-Code-Agenten: laufende Sessions, Subagenten,
12
+ per `claude -p` gestartete Worker, Tool-Aufrufe, Zeitleisten, CPU- und Token-Verbrauch
13
+ und ein Transcript-Viewer mit durchsuchbarer History.
14
+
15
+ ```bash
16
+ npx claude-inspect --open # Node.js ≥ 22 · macOS, Linux, Windows
17
+ ```
18
+
19
+ Liest **passiv** die Dateien unter `~/.claude`, ohne Hooks und ohne Konfigurationsänderung.
20
+ Das Einzige, was es schreibt, ist ein CPU-Protokoll im eigenen Datenverzeichnis (siehe *CPU*).
21
+
22
+ > English: [README.md](https://github.com/brokoskokoli/claude_inspect/blob/main/README.md) · Website: [brokoskokoli.github.io/claude_inspect](https://brokoskokoli.github.io/claude_inspect/) · Mitmachen: [CONTRIBUTING.md](https://github.com/brokoskokoli/claude_inspect/blob/main/CONTRIBUTING.md)
4
23
  >
5
24
  > Die Oberfläche ist englisch; hell, dunkel oder nach Systemeinstellung (Umschalter oben rechts).
6
25
 
7
- Lokales Live-Dashboard für Claude-Code-Agenten. Liest **passiv** die Dateien unter
8
- `~/.claude`, ohne Hooks und ohne Konfigurationsänderung. Das Einzige, was es schreibt, ist ein
9
- CPU-Protokoll im eigenen Datenverzeichnis (siehe *CPU*).
26
+ ![Live-Dashboard mit laufenden Agenten, Subagenten und einer gestarteten Worker-Session](https://raw.githubusercontent.com/brokoskokoli/claude_inspect/main/docs/screenshots/dashboard.jpg)
10
27
 
11
- ## Start
28
+ ## Installation
12
29
 
13
30
  ```bash
14
- npx claude-inspect --open # einmal ausprobieren
15
31
  npm install -g claude-inspect # dauerhaft installieren
16
32
  claude-inspect service install # Autostart → http://localhost:47717 (Lesezeichen)
17
33
  claude-inspect demo --open # ohne eigene Daten ausprobieren
@@ -47,6 +63,9 @@ Aus den Quellen: `git clone …`, `npm install`, `npm run build`, `npm start`
47
63
  - *Tasks*: Task-Liste der Session als Board
48
64
  - *CPU*: Auslastung des Claude-Prozesses samt aller Unterprozesse (Shells, Builds, Tests,
49
65
  MCP-Server …) als gestapelter Verlauf je Programmname, dazu die Prozesse mit der meisten CPU-Zeit
66
+ - *Cost*: geschätzte Kosten (API-Listenpreis) der Session samt aller Subagenten und per
67
+ `claude` gestarteten Sitzungen, je Agent und je Modell mit Tokens (Input, Output, Cache)
68
+ - Beim Hochscrollen blendet sich eine kompakte Kopfzeile mit Sprung nach oben/unten ein
50
69
  - **CPU**: alle 3 s aus der Prozesstabelle gemessen (100 % = ein Kern), Verlaufslinie auf der
51
70
  Dashboard-Karte. Pro Session eine CSV-Datei im App-Datenverzeichnis (macOS
52
71
  `~/Library/Application Support/claude-inspect/cpu`, Linux `~/.local/share/claude-inspect/cpu`,
@@ -90,11 +109,11 @@ tests/ Fixtures je Claude-Code-Version, Snapshots, Tests
90
109
  scripts/ Fixture-Generator
91
110
  ```
92
111
 
93
- Neue Dateiformate: siehe [docs/FORMATS.md](docs/FORMATS.md). Gesamtkonzept: [KONZEPT.md](KONZEPT.md).
112
+ Neue Dateiformate: siehe [docs/FORMATS.md](https://github.com/brokoskokoli/claude_inspect/blob/main/docs/FORMATS.md). Gesamtkonzept: [KONZEPT.md](https://github.com/brokoskokoli/claude_inspect/blob/main/KONZEPT.md).
94
113
 
95
114
  ## Speicher & Leistung
96
115
 
97
- Nichts wird auf Platte geschrieben. Beim Start liest der Server nur Prozess-, Job- und
116
+ Außer dem CPU-Log im eigenen Datenverzeichnis wird nichts auf Platte geschrieben. Beim Start liest der Server nur Prozess-, Job- und
98
117
  Kopfdaten (unter 1 s); die komplette History (hier ~600 MB) wird im Hintergrund in
99
118
  2–3 s aggregiert und danach nur noch inkrementell nachgeführt. Vollständige Verläufe
100
119
  werden erst beim Öffnen geladen und mit einer Obergrenze im Speicher gehalten.
package/README.md CHANGED
@@ -1,23 +1,33 @@
1
- # claude-inspect – live dashboard & history viewer for Claude Code agents
1
+ # claude-inspect – Claude Code dashboard & monitor for agents, subagents and usage
2
2
 
3
- [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
4
3
  [![npm](https://img.shields.io/npm/v/claude-inspect)](https://www.npmjs.com/package/claude-inspect)
4
+ [![npm downloads](https://img.shields.io/npm/dm/claude-inspect)](https://www.npmjs.com/package/claude-inspect)
5
+ [![CI](https://github.com/brokoskokoli/claude_inspect/actions/workflows/ci.yml/badge.svg)](https://github.com/brokoskokoli/claude_inspect/actions/workflows/ci.yml)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/brokoskokoli/claude_inspect/blob/main/LICENSE)
7
+ [![GitHub stars](https://img.shields.io/github/stars/brokoskokoli/claude_inspect?style=social)](https://github.com/brokoskokoli/claude_inspect)
5
8
  ![Node.js ≥ 22](https://img.shields.io/badge/node-%E2%89%A5%2022-green)
6
- ![TypeScript](https://img.shields.io/badge/TypeScript-Svelte%205-3178c6)
7
- ![Dark mode](https://img.shields.io/badge/dark%20mode-%E2%9C%93-2b2a27)
8
9
  ![No hooks](https://img.shields.io/badge/Claude%20Code-no%20hooks%20needed-d97757)
9
10
 
10
- **See what your [Claude Code](https://claude.com/claude-code) agents are doing – right now and in the past.**
11
- claude-inspect is a local web UI that reads the files Claude Code already writes to `~/.claude`
11
+ **htop plus a flight recorder for [Claude Code](https://claude.com/claude-code). No hooks, no proxy, one `npx`.**
12
+
13
+ claude-inspect is a local Claude Code dashboard and monitor that reads the files Claude Code already writes to `~/.claude`
12
14
  and shows running sessions, subagents, `claude -p` worker sessions started by other agents,
13
- every tool call with its result, timelines, a call graph, token usage and a searchable history.
15
+ every tool call with its result, timelines, a call graph, CPU and token usage
16
+ and a transcript viewer with a searchable history.
17
+
18
+ ```bash
19
+ npx claude-inspect --open # Node.js ≥ 22 · macOS, Linux, Windows
20
+ ```
21
+
22
+ No Claude Code data at hand? `npx claude-inspect demo --open` starts it with a fictional data set.
23
+ Permanent install with autostart: see [Installation](#installation).
14
24
 
15
25
  It is **read-only and passive** towards `~/.claude`: no hooks, no settings changes, no proxy, no data leaves
16
26
  your machine. The only thing it writes is a CPU log in its own data directory (see *CPU usage*).
17
27
 
18
- > Website: [brokoskokoli.github.io/claude_inspect](https://brokoskokoli.github.io/claude_inspect/) · Deutsch: [README.de.md](README.de.md) · Design notes (German): [KONZEPT.md](KONZEPT.md)
28
+ > Website: [brokoskokoli.github.io/claude_inspect](https://brokoskokoli.github.io/claude_inspect/) · Deutsch: [README.de.md](https://github.com/brokoskokoli/claude_inspect/blob/main/README.de.md) · Design notes (German): [KONZEPT.md](https://github.com/brokoskokoli/claude_inspect/blob/main/KONZEPT.md) · [Contributing](https://github.com/brokoskokoli/claude_inspect/blob/main/CONTRIBUTING.md)
19
29
 
20
- ![Live dashboard with running agents, subagents and a spawned worker session](docs/screenshots/dashboard.jpg)
30
+ ![Live dashboard with running agents, subagents and a spawned worker session](https://raw.githubusercontent.com/brokoskokoli/claude_inspect/main/docs/screenshots/dashboard.jpg)
21
31
 
22
32
  ## Why
23
33
 
@@ -40,6 +50,7 @@ becomes hard to tell *who is doing what*. claude-inspect answers:
40
50
  | **Agent tree & call graph** | Main agent → subagents (nested) → `claude` sessions started via Bash, including fork/resume relations. Finished agents are greyed out. |
41
51
  | **Timeline** | One lane per agent, tool calls as bars, spawn links between lanes, idle gaps > 10 min collapsed, zoom. Click a bar to jump to the call. |
42
52
  | **Spawn linking** | Links sessions started by `claude -p …` to the calling tool use via the process tree (exact), `--session-id`, prompt text, `--agent`, time window and working directory – with a confidence label. |
53
+ | **Cost per agent tree** | Cost tab per session: API list-price estimate for the main agent plus all its subagents and spawned `claude` sessions, per agent and per model with input, output and cache tokens. |
43
54
  | **Statistics** | API list-price estimate, tokens per model/day/project, cache share, activity heatmap, tool statistics with error rate and p95 duration. |
44
55
  | **CPU usage** | CPU of each Claude Code process plus all its subprocesses (shells, builds, test runners, MCP servers …), measured every 3 s from the process table. Sparkline on the dashboard card, a *CPU* tab per session with a stacked chart by process name and the processes that used the most CPU time. Recorded as one CSV per session in the app data directory (`~/Library/Application Support/claude-inspect/cpu` on macOS, `~/.local/share/claude-inspect/cpu` on Linux, `%LOCALAPPDATA%\claude-inspect\cpu` on Windows), so it stays available after the session ended; files older than 30 days are deleted. Only measured while claude-inspect runs; processes that live less than 3 s are missed. `--no-cpu-log` turns recording off. |
45
56
  | **Tool explorer & files** | Every tool call across all sessions, filterable; which files agents read, edited or wrote. |
@@ -49,29 +60,29 @@ becomes hard to tell *who is doing what*. claude-inspect answers:
49
60
  | **Dark mode** | Light, dark or system theme, remembered per browser. |
50
61
  | **Phone-friendly** | On narrow screens (phones, small iframes) the navigation collapses into a menu, tables turn into compact lists, the session view is single-column and long code, paths and JSON scroll inside their block. The server still listens on 127.0.0.1 only – to open it from a phone you need your own tunnel or reverse proxy that forwards to it with a local `Host` header (other hosts are rejected). |
51
62
 
52
- ![CPU tab: CPU usage of a worker session and its subprocesses (vitest, tsc, esbuild …) over time](docs/screenshots/cpu.jpg)
63
+ ![CPU tab: CPU usage of a worker session and its subprocesses (vitest, tsc, esbuild …) over time](https://raw.githubusercontent.com/brokoskokoli/claude_inspect/main/docs/screenshots/cpu.jpg)
53
64
 
54
65
  <table>
55
66
  <tr>
56
- <td><img src="docs/screenshots/timeline.jpg" alt="Timeline of an orchestrator with subagents and a spawned worker session"></td>
57
- <td><img src="docs/screenshots/call-graph.jpg" alt="Call graph: main agent, subagents and a claude -p worker session"></td>
67
+ <td><img src="https://raw.githubusercontent.com/brokoskokoli/claude_inspect/main/docs/screenshots/timeline.jpg" alt="Timeline of an orchestrator with subagents and a spawned worker session"></td>
68
+ <td><img src="https://raw.githubusercontent.com/brokoskokoli/claude_inspect/main/docs/screenshots/call-graph.jpg" alt="Call graph: main agent, subagents and a claude -p worker session"></td>
58
69
  </tr>
59
70
  <tr>
60
- <td><img src="docs/screenshots/transcript.jpg" alt="Transcript viewer with an expanded Edit tool call shown as diff"></td>
61
- <td><img src="docs/screenshots/statistics.jpg" alt="Statistics: API cost estimate per day and model, activity heatmap"></td>
71
+ <td><img src="https://raw.githubusercontent.com/brokoskokoli/claude_inspect/main/docs/screenshots/transcript.jpg" alt="Transcript viewer with an expanded Edit tool call shown as diff"></td>
72
+ <td><img src="https://raw.githubusercontent.com/brokoskokoli/claude_inspect/main/docs/screenshots/statistics.jpg" alt="Statistics: API cost estimate per day and model, activity heatmap"></td>
62
73
  </tr>
63
74
  </table>
64
75
 
65
76
  <table>
66
77
  <tr>
67
- <td><img src="docs/screenshots/tool-explorer.jpg" alt="Tool explorer listing tool calls across all sessions"></td>
68
- <td><img src="docs/screenshots/dashboard-dark.jpg" alt="Live dashboard in dark mode"></td>
78
+ <td><img src="https://raw.githubusercontent.com/brokoskokoli/claude_inspect/main/docs/screenshots/tool-explorer.jpg" alt="Tool explorer listing tool calls across all sessions"></td>
79
+ <td><img src="https://raw.githubusercontent.com/brokoskokoli/claude_inspect/main/docs/screenshots/dashboard-dark.jpg" alt="Live dashboard in dark mode"></td>
69
80
  </tr>
70
81
  </table>
71
82
 
72
83
  *All screenshots show the built-in demo data set (`claude-inspect demo`), not real sessions.*
73
84
 
74
- ## Quick start
85
+ ## Installation
75
86
 
76
87
  Requirements: Node.js ≥ 22, macOS, Linux or Windows, Claude Code writing to `~/.claude`. On Windows, live process status is read via PowerShell; the autostart service and the live `demo` are macOS/Linux only (`demo --out <dir>` works everywhere).
77
88
 
@@ -129,7 +140,7 @@ Light, dark or follow the OS – switch with the button in the header (the choic
129
140
  FormatRegistry → versioned decoders → normalized model → REST + SSE → Svelte UI
130
141
  ```
131
142
 
132
- - **Per-record format detection:** every decoder scores a record (`type`, version range, structure); the best one wins, a fallback keeps unknown records. Adding support for a new Claude Code version = adding a decoder file. See [docs/FORMATS.md](docs/FORMATS.md).
143
+ - **Per-record format detection:** every decoder scores a record (`type`, version range, structure); the best one wins, a fallback keeps unknown records. Adding support for a new Claude Code version = adding a decoder file. See [docs/FORMATS.md](https://github.com/brokoskokoli/claude_inspect/blob/main/docs/FORMATS.md).
133
144
  - **In memory only:** startup reads process/job data and file heads (< 1 s); the full history (hundreds of MB) is aggregated in the background in a few seconds and then followed incrementally.
134
145
  - **Privacy & security:** listens on `127.0.0.1` only (never reachable from the network), rejects requests whose `Host` header isn't `localhost`/`127.0.0.1` (DNS rebinding), sends no CORS headers (other websites in your browser can't read the API), is read-only towards `~/.claude` (the CPU log goes to its own data directory and contains only timestamps, PIDs, program names and CPU percentages – no command lines), never reads credential files (`*.key`, `daemon/auth`, `ide/*.lock`, …) and masks token/secret fields in the raw view. The access token is an extra layer against *other local processes or users* on the same machine; on a single-user machine `--no-auth` (used by the autostart service) is a reasonable trade-off. Cost figures are estimates from public API list prices – with a subscription you do not pay these amounts directly.
135
146
 
@@ -159,7 +170,7 @@ tests/ anonymized fixtures per Claude Code version, snapshots, tests
159
170
  scripts/ fixture generator (demo data: src/server/cli/demo.ts)
160
171
  ```
161
172
 
162
- Contributions welcome – especially decoders for new Claude Code versions (run `npm run fixtures` and
173
+ Contributions welcome – see [CONTRIBUTING.md](https://github.com/brokoskokoli/claude_inspect/blob/main/CONTRIBUTING.md), especially decoders for new Claude Code versions (run `npm run fixtures` and
163
174
  `npm test`, then check the *Formats* page for unknown fields).
164
175
 
165
176
  ## Disclaimer
@@ -169,4 +180,4 @@ may change at any time; claude-inspect is designed to degrade gracefully (unknow
169
180
 
170
181
  ## License
171
182
 
172
- [MIT](LICENSE)
183
+ [MIT](https://github.com/brokoskokoli/claude_inspect/blob/main/LICENSE)
@@ -261,6 +261,33 @@ export class HistoryIndex {
261
261
  heat,
262
262
  };
263
263
  }
264
+ /**
265
+ * Tokens je Modell eines Transkripts (Hauptagent oder Subagent) für die Kostenansicht.
266
+ * `seen` enthält bereits gezählte Message-Ids, damit bei Fork/Resume kopierte Antworten
267
+ * im selben Baum nicht doppelt zählen.
268
+ */
269
+ usageOf(sessionId, agentId, seen, each) {
270
+ const out = new Map();
271
+ for (const a of this.files.values()) {
272
+ if (a.sessionId !== sessionId || a.agentId !== agentId)
273
+ continue;
274
+ for (const [messageId, u] of a.usage) {
275
+ if (seen.has(messageId))
276
+ continue;
277
+ seen.add(messageId);
278
+ let t = out.get(u.model);
279
+ if (!t)
280
+ out.set(u.model, (t = emptyTotals()));
281
+ addUsage(t, u.usage);
282
+ if (each) {
283
+ const one = emptyTotals();
284
+ addUsage(one, u.usage);
285
+ each(u.model, u.ts, one);
286
+ }
287
+ }
288
+ }
289
+ return out;
290
+ }
264
291
  toolCalls(q) {
265
292
  const { aggs, since } = this.selected(q);
266
293
  const needle = q.q?.toLowerCase();
@@ -155,6 +155,11 @@ export function startServer(inspector, opts) {
155
155
  m = /^\/api\/cpu\/([\w-]+)$/.exec(p);
156
156
  if (m)
157
157
  return json(res, 200, await inspector.cpuHistory(m[1]));
158
+ m = /^\/api\/cost\/([\w-]+)$/.exec(p);
159
+ if (m) {
160
+ const cost = await inspector.sessionCost(m[1]);
161
+ return cost ? json(res, 200, cost) : json(res, 404, { error: 'unknown session' });
162
+ }
158
163
  m = /^\/api\/flow\/([\w-]+)$/.exec(p);
159
164
  if (m) {
160
165
  const flow = await inspector.flow(m[1]);
@@ -6,6 +6,7 @@ import { CLAUDE_DIR, relToClaude } from './config.js';
6
6
  import { CpuMonitor } from './cpu-monitor.js';
7
7
  import { registry } from './formats/index.js';
8
8
  import { HistoryIndex } from './history/aggregator.js';
9
+ import { emptyTotals, estimateCost, mergeTotals } from '../shared/pricing.js';
9
10
  import { search } from './history/search.js';
10
11
  import { analyze } from './model/analyze.js';
11
12
  import { laneData } from './model/flow.js';
@@ -500,7 +501,125 @@ export class Inspector extends EventEmitter {
500
501
  }
501
502
  return { rootSessionId, lanes, origin };
502
503
  }
504
+ /**
505
+ * Geschätzte Kosten einer Session samt aller Subagenten und per `claude` gestarteten
506
+ * Sitzungen (rekursiv, gleicher Baum wie Zeitleiste und Graph).
507
+ */
508
+ async sessionCost(rootSessionId) {
509
+ const flow = await this.flow(rootSessionId);
510
+ if (!flow)
511
+ return undefined;
512
+ await this.historyLoaded;
513
+ const seen = new Set();
514
+ const total = emptyTotals();
515
+ const byModel = new Map();
516
+ const unpriced = new Set();
517
+ let costUSD = 0;
518
+ const points = [];
519
+ const rows = flow.lanes.map((lane) => {
520
+ const usage = this.history.usageOf(lane.sessionId, lane.agentId, seen, (model, ts, one) => {
521
+ if (ts)
522
+ points.push({ ts, cost: estimateCost(model, one) ?? 0, output: one.output, model, lane });
523
+ });
524
+ const tokens = emptyTotals();
525
+ let cost = 0;
526
+ const models = [...usage.entries()].map(([model, t]) => {
527
+ mergeTotals(tokens, t);
528
+ let m = byModel.get(model);
529
+ if (!m)
530
+ byModel.set(model, (m = emptyTotals()));
531
+ mergeTotals(m, t);
532
+ const c = estimateCost(model, t);
533
+ if (c === undefined)
534
+ unpriced.add(model);
535
+ else
536
+ cost += c;
537
+ return { model, tokens: t, costUSD: c };
538
+ });
539
+ mergeTotals(total, tokens);
540
+ costUSD += cost;
541
+ return {
542
+ id: lane.id,
543
+ sessionId: lane.sessionId,
544
+ agentId: lane.agentId,
545
+ kind: lane.kind,
546
+ label: lane.label,
547
+ sublabel: lane.sublabel,
548
+ parentId: lane.parentId,
549
+ depth: lane.depth,
550
+ status: lane.status,
551
+ byModel: models.sort((a, b) => (b.costUSD ?? 0) - (a.costUSD ?? 0)),
552
+ tokens,
553
+ costUSD: cost,
554
+ };
555
+ });
556
+ const rootFile = this.index.get(rootSessionId);
557
+ return {
558
+ rootSessionId,
559
+ ready: this.historyReady,
560
+ rows,
561
+ total,
562
+ costUSD,
563
+ byModel: [...byModel.entries()]
564
+ .map(([model, tokens]) => ({ model, tokens, costUSD: estimateCost(model, tokens) }))
565
+ .sort((a, b) => (b.costUSD ?? 0) - (a.costUSD ?? 0)),
566
+ unpricedModels: [...unpriced],
567
+ reportedCostUSD: rootFile ? (await this.index.summary(rootFile)).costUSD : undefined,
568
+ timeline: costTimeline(points),
569
+ };
570
+ }
503
571
  formats() {
504
572
  return registry.report();
505
573
  }
506
574
  }
575
+ const MIN = 60_000;
576
+ const BUCKET_SIZES = [1, 2, 5, 10, 15, 30, 60, 120, 180, 360, 720, 1440].map((m) => m * MIN);
577
+ /** Verteilt die Modellantworten auf höchstens ~120 gleich lange Zeitabschnitte. */
578
+ function costTimeline(points) {
579
+ if (!points.length)
580
+ return { bucketMs: MIN, buckets: [] };
581
+ let first = Infinity;
582
+ let last = -Infinity;
583
+ for (const p of points) {
584
+ first = Math.min(first, p.ts);
585
+ last = Math.max(last, p.ts);
586
+ }
587
+ const span = last - first;
588
+ const bucketMs = BUCKET_SIZES.find((b) => span / b <= 120) ?? Math.ceil(span / 120 / (1440 * MIN)) * 1440 * MIN;
589
+ // an der lokalen Uhr ausrichten (volle Minuten/Stunden/Tage)
590
+ const offset = new Date(first).getTimezoneOffset() * MIN;
591
+ const start = Math.floor((first - offset) / bucketMs) * bucketMs + offset;
592
+ const n = Math.floor((last - start) / bucketMs) + 1;
593
+ const buckets = Array.from({ length: n }, (_, i) => ({
594
+ start: start + i * bucketMs,
595
+ costUSD: 0,
596
+ outputTokens: 0,
597
+ requests: 0,
598
+ byKind: {},
599
+ byModel: {},
600
+ top: [],
601
+ lanes: new Map(),
602
+ }));
603
+ for (const p of points) {
604
+ const b = buckets[Math.floor((p.ts - start) / bucketMs)];
605
+ b.costUSD += p.cost;
606
+ b.outputTokens += p.output;
607
+ b.requests++;
608
+ b.byKind[p.lane.kind] = (b.byKind[p.lane.kind] ?? 0) + p.cost;
609
+ b.byModel[p.model] = (b.byModel[p.model] ?? 0) + p.cost;
610
+ let l = b.lanes.get(p.lane.id);
611
+ if (!l)
612
+ b.lanes.set(p.lane.id, (l = { label: p.lane.label, costUSD: 0 }));
613
+ l.costUSD += p.cost;
614
+ }
615
+ return {
616
+ bucketMs,
617
+ buckets: buckets.map(({ lanes, ...b }) => ({
618
+ ...b,
619
+ top: [...lanes.entries()]
620
+ .map(([id, l]) => ({ id, ...l }))
621
+ .sort((x, y) => y.costUSD - x.costUSD)
622
+ .slice(0, 3),
623
+ })),
624
+ };
625
+ }
@@ -0,0 +1 @@
1
+ .backdrop.svelte-4pc5q2{position:fixed;top:0;right:0;bottom:0;left:0;z-index:50;background:#00000059;display:flex;align-items:center;justify-content:center;padding:24px}.modal.svelte-4pc5q2{width:min(1000px,100%);max-height:100%;display:flex;flex-direction:column;padding:12px 14px}.head.svelte-4pc5q2{display:flex;align-items:center;gap:10px;margin-bottom:8px}.head.svelte-4pc5q2 .mono:where(.svelte-4pc5q2){font-weight:600}.head.svelte-4pc5q2 .btn:where(.svelte-4pc5q2):first-of-type{margin-left:auto}.small.svelte-4pc5q2{font-size:12px}@media(max-width:640px){.backdrop.svelte-4pc5q2{padding:8px}.head.svelte-4pc5q2{flex-wrap:wrap}}pre.svelte-4pc5q2{overflow:auto;background:var(--code-bg);padding:10px 12px;border-radius:6px;font-size:12px}.act.svelte-1ncbav4{display:flex;align-items:baseline;gap:7px;min-width:0;font-size:13px}.icon.svelte-1ncbav4{flex:none;width:16px;text-align:center;color:var(--muted)}.tool.svelte-1ncbav4{flex:none;font-family:var(--mono);font-size:12px;font-weight:600;color:var(--accent)}.label.svelte-1ncbav4{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.since.svelte-1ncbav4{flex:none;margin-left:auto;font-size:12px;color:var(--faint);font-variant-numeric:tabular-nums}.idle.svelte-1ncbav4 .label:where(.svelte-1ncbav4){color:var(--muted)}.error.svelte-1ncbav4{color:var(--error)}.thinking.svelte-1ncbav4 .label:where(.svelte-1ncbav4){font-style:italic;color:var(--muted)}svg.svelte-8jlei4{display:inline-block;vertical-align:middle;overflow:visible}.area.svelte-8jlei4{fill:color-mix(in srgb,var(--series-1) 18%,transparent)}.line.svelte-8jlei4{fill:none;stroke:var(--series-1);stroke-width:1.5;stroke-linejoin:round}.conf.svelte-b9fh4t{font-size:10.5px;padding:0 5px;border-radius:8px;line-height:16px;white-space:nowrap;background:var(--surface-2);color:var(--muted)}.exact.svelte-b9fh4t{background:color-mix(in srgb,var(--busy) 16%,transparent);color:var(--busy)}.high.svelte-b9fh4t{background:var(--info-soft);color:var(--info)}.likely.svelte-b9fh4t{background:color-mix(in srgb,var(--idle) 18%,transparent);color:var(--idle)}.dot.svelte-cu6fe6{display:inline-block;border-radius:50%;flex:none;background:var(--dead)}.busy.svelte-cu6fe6,.running.svelte-cu6fe6{background:var(--busy);box-shadow:0 0 color-mix(in srgb,var(--busy) 60%,transparent);animation:svelte-cu6fe6-pulse 1.6s infinite}.idle.svelte-cu6fe6{background:var(--idle)}.stale.svelte-cu6fe6{background:transparent;box-shadow:inset 0 0 0 1.5px var(--dead)}.mark.svelte-cu6fe6{flex:none;display:inline-block;vertical-align:middle}.mark.done.svelte-cu6fe6{color:var(--faint)}.mark.error.svelte-cu6fe6{color:var(--error)}@keyframes svelte-cu6fe6-pulse{70%{box-shadow:0 0 0 6px transparent}to{box-shadow:0 0 0 0 transparent}}.proc.svelte-4ocmfk{display:flex;flex-direction:column;gap:10px;padding:14px 16px 12px;color:inherit;text-decoration:none;min-width:0;transition:border-color .15s}.proc.svelte-4ocmfk:hover{border-color:color-mix(in srgb,var(--accent) 50%,var(--border));text-decoration:none}.proc.busy.svelte-4ocmfk{border-top:3px solid var(--busy)}.proc.idle.svelte-4ocmfk{border-top:3px solid var(--idle)}.proc.error.svelte-4ocmfk{border-top:3px solid var(--error)}.proc.dead.svelte-4ocmfk{opacity:.65}.head.svelte-4ocmfk{display:flex;align-items:center;gap:9px;min-width:0}.titles.svelte-4ocmfk{min-width:0;flex:1}.title.svelte-4ocmfk{font-weight:600;font-size:15px}.subtitle.svelte-4ocmfk{font-size:12.5px;color:var(--muted)}.badges.svelte-4ocmfk{display:flex;gap:4px;flex:none}@media(max-width:480px){.head.svelte-4ocmfk{flex-wrap:wrap}.titles.svelte-4ocmfk{flex:1 1 calc(100% - 20px)}.badges.svelte-4ocmfk{flex-wrap:wrap;padding-left:19px}}.where.svelte-4ocmfk{display:flex;gap:10px;font-size:12.5px;min-width:0}.branch.svelte-4ocmfk{flex:none;font-family:var(--mono);font-size:11.5px}.now.svelte-4ocmfk{display:flex;flex-direction:column;gap:4px;padding:8px 10px;background:var(--surface-2);border-radius:7px}.pending.svelte-4ocmfk{display:flex;align-items:baseline;gap:7px;min-width:0;font-size:12.5px;padding-left:23px}.tool.svelte-4ocmfk{flex:none;font-family:var(--mono);font-size:11.5px;font-weight:600;color:var(--accent)}.since.svelte-4ocmfk{flex:none;margin-left:auto;font-size:11.5px;color:var(--faint);font-variant-numeric:tabular-nums}.job.svelte-4ocmfk{display:flex;flex-direction:column;gap:4px;font-size:12.5px}.job-head.svelte-4ocmfk{display:flex;gap:8px;align-items:center}.job-detail.svelte-4ocmfk{color:var(--text)}.job.svelte-4ocmfk .pending:where(.svelte-4ocmfk){padding-left:0}.subs.svelte-4ocmfk{display:flex;flex-direction:column;gap:3px;font-size:12.5px}.subs-head.svelte-4ocmfk{display:flex;justify-content:space-between;font-size:12px}.sub.svelte-4ocmfk{display:flex;align-items:center;gap:7px;min-width:0}.sub-type.svelte-4ocmfk{flex:none;font-weight:500}.sub.svelte-4ocmfk{padding:1px 6px;margin:0 -6px;border-radius:5px}.sub.finished.svelte-4ocmfk{background:var(--surface-2);color:var(--faint)}.sub.finished.svelte-4ocmfk .sub-type:where(.svelte-4ocmfk){font-weight:400}.link.svelte-4ocmfk{border:none;background:none;padding:0;color:var(--accent);font-weight:500}.link.svelte-4ocmfk:hover{text-decoration:underline}.parent.svelte-4ocmfk{display:flex;align-items:center;gap:6px;font-size:12.5px;margin-top:-4px}.metrics.svelte-4ocmfk{display:flex;flex-wrap:wrap;gap:4px 12px;padding-top:8px;border-top:1px solid var(--border);font-size:12px;color:var(--muted);font-variant-numeric:tabular-nums}.cpu.svelte-4ocmfk{display:inline-flex;align-items:center;gap:5px}.cpu.svelte-4ocmfk .hot:where(.svelte-4ocmfk){color:var(--text);font-weight:600}.perm.svelte-4ocmfk{font-family:var(--mono);font-size:11px}.ver.svelte-4ocmfk{margin-left:auto}.row.svelte-yge1ub{display:inline-flex;gap:4px}.resume.svelte-yge1ub{display:flex;flex-direction:column;gap:6px}.cmd.svelte-yge1ub{display:flex;align-items:center;gap:8px;min-width:0}.cmd.svelte-yge1ub code:where(.svelte-yge1ub){font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;-webkit-user-select:all;user-select:all}.secondary.svelte-yge1ub code:where(.svelte-yge1ub){opacity:.7}.btn.svelte-yge1ub{white-space:nowrap;min-width:92px}@media(max-width:640px){.cmd.svelte-yge1ub{flex-wrap:wrap}.cmd.svelte-yge1ub code:where(.svelte-yge1ub){flex:1 1 100%;overflow-x:auto;text-overflow:clip;padding:4px 0}}.btn.primary.svelte-yge1ub{border-color:var(--accent);color:var(--accent)}.wrap.svelte-1oevp43{overflow-x:auto}.dot.svelte-1oevp43{width:18px;padding-right:0}.proj.svelte-1oevp43{white-space:nowrap;font-weight:500}.title.svelte-1oevp43{max-width:0;width:55%}.when.svelte-1oevp43{white-space:nowrap;color:var(--muted)}.spawned.svelte-1oevp43{color:var(--info);margin-right:5px}.small.svelte-1oevp43{font-size:12px}.num.svelte-1oevp43{text-align:right;font-variant-numeric:tabular-nums}@media(max-width:760px){.hide-s.svelte-1oevp43{display:none}}@media(max-width:640px){thead.svelte-1oevp43{display:none}table.svelte-1oevp43,tbody.svelte-1oevp43{display:block}tr.svelte-1oevp43{display:grid;grid-template-columns:14px minmax(0,1fr) auto;grid-template-areas:"dot proj when" ". title title";column-gap:6px;row-gap:2px;padding:10px 12px;border-bottom:1px solid var(--border)}tr.svelte-1oevp43:last-child{border-bottom:none}table.list.svelte-1oevp43 td:where(.svelte-1oevp43){display:block;padding:0;border:none}table.list.svelte-1oevp43 td.hide-s:where(.svelte-1oevp43){display:none}.dot.svelte-1oevp43{grid-area:dot;width:auto;padding-top:1px!important}.proj.svelte-1oevp43{grid-area:proj;display:flex;gap:8px;align-items:baseline;min-width:0;overflow:hidden}.title.svelte-1oevp43{grid-area:title;max-width:none;width:auto;min-width:0}.when.svelte-1oevp43{grid-area:when;font-size:13px}}section.svelte-1woq6ux{margin-bottom:28px}.section-head.svelte-1woq6ux{display:flex;align-items:baseline;gap:12px;margin-bottom:10px}.src.svelte-1woq6ux{margin-left:auto;font-size:12px}@media(max-width:640px){.section-head.svelte-1woq6ux{flex-wrap:wrap;row-gap:2px}.src.svelte-1woq6ux{margin-left:0;flex-basis:100%;overflow-wrap:anywhere}}.grid.svelte-1woq6ux{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(420px,100%),1fr));gap:14px}.empty.svelte-1woq6ux{padding:28px;text-align:center}.two.svelte-1woq6ux{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(460px,100%),1fr));gap:20px}.small.svelte-1woq6ux{font-size:12px}.nowrap.svelte-1woq6ux{white-space:nowrap}.bar.svelte-1mqd5mo{margin-bottom:12px}.bar.svelte-1mqd5mo input[type=search]:where(.svelte-1mqd5mo){margin-left:auto;width:min(320px,100%)}.path.svelte-1mqd5mo{max-width:0;width:55%}.nowrap.svelte-1mqd5mo{white-space:nowrap}@media(max-width:640px){thead.svelte-1mqd5mo{display:none}table.svelte-1mqd5mo,tbody.svelte-1mqd5mo{display:block}tr.svelte-1mqd5mo{display:flex;flex-wrap:wrap;gap:2px 14px;padding:10px 12px;border-bottom:1px solid var(--border)}tr.svelte-1mqd5mo:last-child{border-bottom:none}table.list.svelte-1mqd5mo td:where(.svelte-1mqd5mo){display:block;padding:0;border:none}.path.svelte-1mqd5mo{flex:1 1 100%;max-width:none;width:auto}.path.svelte-1mqd5mo .ellipsis:where(.svelte-1mqd5mo){white-space:normal;overflow-wrap:anywhere}.proj.svelte-1mqd5mo{order:1;flex:1 1 60%;min-width:0;overflow:hidden;text-overflow:ellipsis}.last.svelte-1mqd5mo{order:2;text-align:right}.cnt.svelte-1mqd5mo{order:3;font-size:13px}.cnt.svelte-1mqd5mo:empty{display:none}.cnt.svelte-1mqd5mo:before{content:attr(data-label) " ";color:var(--faint)}}.center.svelte-1mqd5mo{text-align:center}.intro.svelte-1osu0b9{max-width:820px;margin-bottom:20px}.intro.svelte-1osu0b9 p:where(.svelte-1osu0b9){margin:6px 0 0}section.svelte-1osu0b9{margin-bottom:26px}h3.svelte-1osu0b9{font-size:14px;margin-bottom:8px}.num.svelte-1osu0b9{text-align:right;font-variant-numeric:tabular-nums}.warn.svelte-1osu0b9{color:var(--error)}@media(max-width:640px){td.svelte-1osu0b9:nth-child(4){min-width:200px}td.mono.svelte-1osu0b9{white-space:nowrap}}.bar.svelte-1qygqtx{margin-bottom:14px}.bar.svelte-1qygqtx input:where(.svelte-1qygqtx){width:min(480px,100%)}.hits.svelte-1qygqtx{display:flex;flex-direction:column;gap:8px}.hit.svelte-1qygqtx{display:block;padding:9px 14px;color:inherit;text-decoration:none}a.hit.svelte-1qygqtx:hover{border-color:color-mix(in srgb,var(--accent) 45%,var(--border));text-decoration:none}.meta.svelte-1qygqtx{display:flex;gap:9px;align-items:baseline;font-size:12.5px;min-width:0}.when.svelte-1qygqtx{margin-left:auto;white-space:nowrap}.snip.svelte-1qygqtx{margin-top:3px;font-size:13px;color:var(--muted);word-break:break-word}@media(max-width:640px){.bar.svelte-1qygqtx input:where(.svelte-1qygqtx){flex:1 1 0!important;min-width:0}.meta.svelte-1qygqtx{flex-wrap:wrap;row-gap:2px}.snip.svelte-1qygqtx{font-size:14px}}.snip.svelte-1qygqtx mark{background:var(--accent-soft);color:var(--text);border-radius:3px;padding:0 2px}.chart.svelte-a3eum1{width:100%}svg.svelte-a3eum1{display:block;overflow:visible}.grid.svelte-a3eum1{stroke:var(--grid);stroke-width:1}.axis.svelte-a3eum1{stroke:var(--border);stroke-width:1}.tick.svelte-a3eum1{font-size:11px;fill:var(--faint);font-variant-numeric:tabular-nums}.tip-title.svelte-a3eum1{font-weight:600;margin-bottom:4px}.tip-row.svelte-a3eum1{display:flex;align-items:center;gap:7px}.tip-row.svelte-a3eum1 .num:where(.svelte-a3eum1){margin-left:auto;padding-left:14px}.heat.svelte-1gmymgh{display:grid;grid-template-columns:28px repeat(24,minmax(0,1fr));gap:2px;font-size:11px}.col-label.svelte-1gmymgh,.row-label.svelte-1gmymgh{color:var(--faint)}.col-label.svelte-1gmymgh{text-align:left}.row-label.svelte-1gmymgh{align-self:center}.cell.svelte-1gmymgh{aspect-ratio:1.3;border-radius:3px}.cell.svelte-1gmymgh:hover{outline:2px solid var(--text);outline-offset:-1px}.scale.svelte-1gmymgh{display:flex;align-items:center;gap:3px;justify-content:flex-end;font-size:11px;margin-top:6px}section.svelte-1mx7ju4{margin-bottom:16px}.tiles.svelte-1mx7ju4{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:12px}.tile.svelte-1mx7ju4{padding:14px 16px}.label.svelte-1mx7ju4{font-size:12.5px;color:var(--muted)}.value.svelte-1mx7ju4{font-size:28px;font-weight:600;letter-spacing:-.02em;margin:2px 0}.sub.svelte-1mx7ju4{font-size:12px}.block.svelte-1mx7ju4{padding:14px 16px;overflow-x:auto}.block.svelte-1mx7ju4 h3:where(.svelte-1mx7ju4){font-size:14px;margin-bottom:8px}.block-head.svelte-1mx7ju4{display:flex;justify-content:space-between;align-items:baseline;gap:12px}.legend.svelte-1mx7ju4{display:flex;gap:14px;flex-wrap:wrap;font-size:12.5px;color:var(--muted);margin:4px 0 10px}.legend.svelte-1mx7ju4>span:where(.svelte-1mx7ju4){display:inline-flex;align-items:center;gap:6px}.two.svelte-1mx7ju4{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(520px,100%),1fr));gap:16px}.two.svelte-1mx7ju4 section:where(.svelte-1mx7ju4){margin-bottom:0}.two.svelte-1mx7ju4{margin-bottom:16px}.small.svelte-1mx7ju4{font-size:12px;margin:-4px 0 8px}.err.svelte-1mx7ju4{color:var(--error)}table.list.svelte-1mx7ju4 td:where(.svelte-1mx7ju4):first-child{white-space:nowrap}@media(max-width:640px){.tiles.svelte-1mx7ju4{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}.tile.svelte-1mx7ju4{padding:12px}.value.svelte-1mx7ju4{font-size:22px}.block-head.svelte-1mx7ju4{flex-wrap:wrap}}.bar.svelte-17jmn20{margin-bottom:12px}.bar.svelte-17jmn20 input[type=search]:where(.svelte-17jmn20){margin-left:auto;width:min(320px,100%)}.chk.svelte-17jmn20{display:flex;gap:5px;align-items:center;font-size:13px}@media(max-width:640px){.chk.svelte-17jmn20{min-height:44px;font-size:14px}}.sum.svelte-17jmn20{max-width:0;width:60%}.nowrap.svelte-17jmn20{white-space:nowrap}.small.svelte-17jmn20{font-size:11.5px}@media(max-width:640px){thead.svelte-17jmn20{display:none}table.svelte-17jmn20,tbody.svelte-17jmn20{display:block}tr.svelte-17jmn20{display:grid;grid-template-columns:minmax(0,1fr) auto auto;grid-template-areas:"tool flag dur" "sum sum sum" "proj time time";column-gap:8px;row-gap:2px;padding:10px 12px;border-bottom:1px solid var(--border)}tr.svelte-17jmn20:last-child{border-bottom:none}table.list.svelte-17jmn20 td:where(.svelte-17jmn20){display:block;padding:0;border:none}.tool.svelte-17jmn20{grid-area:tool}.flag.svelte-17jmn20{grid-area:flag}.dur.svelte-17jmn20{grid-area:dur;color:var(--muted)}.sum.svelte-17jmn20{grid-area:sum;max-width:none;width:auto;min-width:0}.proj.svelte-17jmn20{grid-area:proj;font-size:12.5px;overflow:hidden;text-overflow:ellipsis}.time.svelte-17jmn20{grid-area:time;font-size:12.5px;text-align:right}}.more.svelte-17jmn20{text-align:center;margin-top:14px}.tiles.svelte-15p9gjz{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(200px,100%),1fr));gap:12px;margin-bottom:10px}.tile.svelte-15p9gjz{padding:12px 16px}.label.svelte-15p9gjz{font-size:12px;color:var(--muted)}.value.svelte-15p9gjz{font-size:22px;font-weight:600;margin:2px 0}.sub.svelte-15p9gjz,.small.svelte-15p9gjz{font-size:12px}.note.svelte-15p9gjz{margin:0 0 14px;display:flex;flex-wrap:wrap;gap:6px 10px;align-items:center}.block.svelte-15p9gjz{padding:14px 16px;margin-bottom:16px;min-width:0}h3.svelte-15p9gjz{font-size:14px;margin:0 0 10px}.scroll.svelte-15p9gjz{overflow-x:auto}.agent.svelte-15p9gjz{display:flex;align-items:center;gap:6px;white-space:nowrap}div.sub.svelte-15p9gjz{max-width:420px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.models.svelte-15p9gjz{white-space:nowrap}.models.svelte-15p9gjz span:where(.svelte-15p9gjz)+span:where(.svelte-15p9gjz){margin-left:8px}.swatch.svelte-15p9gjz{display:inline-block;width:9px;height:9px;border-radius:2px;margin-right:4px}.strong.svelte-15p9gjz{font-weight:600}tfoot.svelte-15p9gjz td:where(.svelte-15p9gjz){border-top:1px solid var(--border);font-weight:600}.bar-col.svelte-15p9gjz{width:90px;min-width:60px}.bar.svelte-15p9gjz{height:8px;border-radius:4px;background:var(--accent);opacity:.75}.summary.svelte-1o2hosd{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 26px;margin-bottom:10px}.summary.svelte-1o2hosd>div:where(.svelte-1o2hosd):not(.note){display:flex;flex-direction:column}.label.svelte-1o2hosd{font-size:12px;color:var(--muted)}.value.svelte-1o2hosd{font-size:20px;font-weight:600;font-variant-numeric:tabular-nums}.value.small.svelte-1o2hosd{font-size:14px;font-weight:500}.note.svelte-1o2hosd{font-size:12px;margin-left:auto}.legend.svelte-1o2hosd{display:flex;gap:14px;flex-wrap:wrap;font-size:12.5px;color:var(--muted);margin:4px 0 10px}.legend.svelte-1o2hosd>span:where(.svelte-1o2hosd){display:inline-flex;align-items:center;gap:6px}.plot.svelte-1o2hosd{width:100%}svg.svelte-1o2hosd{display:block;overflow:visible}.grid.svelte-1o2hosd{stroke:var(--grid);stroke-width:1}.axis.svelte-1o2hosd{stroke:var(--border);stroke-width:1}.cross.svelte-1o2hosd{stroke:var(--muted);stroke-width:1;stroke-dasharray:3 3}.tick.svelte-1o2hosd{font-size:11px;fill:var(--faint);font-variant-numeric:tabular-nums}.tip-title.svelte-1o2hosd{font-weight:600;margin-bottom:4px}.tip-row.svelte-1o2hosd{display:flex;align-items:center;gap:7px}.tip-row.total.svelte-1o2hosd{font-weight:600}.tip-row.svelte-1o2hosd .num:where(.svelte-1o2hosd){margin-left:auto;padding-left:14px}h3.svelte-1o2hosd{margin:22px 0 8px;font-size:14px}.file.svelte-1o2hosd{margin-top:10px;word-break:break-all}.small.svelte-1o2hosd{font-size:12px}.legend.svelte-6d86j7{display:flex;gap:16px;flex-wrap:wrap;align-items:center;font-size:12px;color:var(--muted);margin:4px 0 10px}.legend.svelte-6d86j7>span:where(.svelte-6d86j7){display:inline-flex;gap:6px;align-items:center}.graph.svelte-6d86j7{position:relative;overflow:auto;max-height:75vh}.graph.svelte-6d86j7>svg:where(.svelte-6d86j7){position:absolute;left:0;top:0}.nodes.svelte-6d86j7{position:relative}.e.svelte-6d86j7{fill:none;stroke:var(--faint);stroke-width:1.5}.e.spawn.svelte-6d86j7{stroke:var(--info);stroke-dasharray:5 4}.e.origin.svelte-6d86j7{stroke:var(--accent);stroke-dasharray:2 4}.node.svelte-6d86j7{position:absolute;display:flex;flex-direction:column;justify-content:center;gap:1px;padding:6px 10px;border-radius:9px;background:var(--surface);border:1px solid var(--border);color:inherit;text-decoration:none;box-shadow:var(--shadow)}.node.svelte-6d86j7:hover{border-color:var(--accent);text-decoration:none}.node.main.svelte-6d86j7{border-width:2px}.node.spawn.svelte-6d86j7{border-color:color-mix(in srgb,var(--info) 45%,var(--border))}.node.finished.svelte-6d86j7{background:var(--surface-2);box-shadow:none}.node.finished.svelte-6d86j7 .t:where(.svelte-6d86j7){color:var(--muted)}.node.origin.svelte-6d86j7{border-style:dashed;background:var(--surface-2)}.k.svelte-6d86j7{display:flex;align-items:center;gap:5px;font-size:10.5px;text-transform:uppercase;letter-spacing:.03em;color:var(--faint)}.k.svelte-6d86j7{white-space:nowrap;min-width:0}.sl.svelte-6d86j7{overflow:hidden;text-overflow:ellipsis;text-transform:none;letter-spacing:0;min-width:0}.d.svelte-6d86j7{flex:none;margin-left:auto;text-transform:none;letter-spacing:0;font-variant-numeric:tabular-nums}.dot.svelte-6d86j7{flex:none;width:7px;height:7px;border-radius:50%;background:var(--dead)}.st-running.svelte-6d86j7 .dot:where(.svelte-6d86j7){background:var(--busy)}.st-idle.svelte-6d86j7 .dot:where(.svelte-6d86j7){background:var(--idle)}.st-error.svelte-6d86j7 .dot:where(.svelte-6d86j7){background:var(--error)}.st-done.svelte-6d86j7 .dot:where(.svelte-6d86j7){background:transparent;width:auto;height:auto;border-radius:0}.st-done.svelte-6d86j7 .dot:where(.svelte-6d86j7):before{content:"✓";color:var(--faint);font-size:11px}.st-stale.svelte-6d86j7 .dot:where(.svelte-6d86j7){background:transparent;box-shadow:inset 0 0 0 1.5px var(--dead)}.t.svelte-6d86j7{font-weight:600;font-size:13px}.s.svelte-6d86j7{font-size:11.5px;color:var(--faint)}.board.svelte-1irkpk4{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(240px,100%),1fr));gap:14px;align-items:start}.col.svelte-1irkpk4{display:flex;flex-direction:column;gap:8px}.col-head.svelte-1irkpk4{font-weight:600;font-size:13px}.task.svelte-1irkpk4{padding:9px 12px;font-size:13px}.task.done.svelte-1irkpk4{background:var(--surface-2);box-shadow:none;color:var(--muted)}.subj.svelte-1irkpk4{font-weight:500}.active.svelte-1irkpk4{font-size:12px;color:var(--busy);margin-top:2px}details.svelte-1irkpk4{margin-top:4px;font-size:12.5px}summary.svelte-1irkpk4{cursor:pointer;color:var(--muted);font-size:12px}details.svelte-1irkpk4 p:where(.svelte-1irkpk4){margin:4px 0 0;white-space:pre-wrap}.dep.svelte-1irkpk4{font-size:12px;margin-top:4px}.small.svelte-1irkpk4{font-size:11.5px}.toolbar.svelte-zid8p2{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;margin:4px 0 10px}.legend.svelte-zid8p2{display:flex;gap:12px;flex-wrap:wrap;font-size:12px;color:var(--muted)}.legend.svelte-zid8p2>span:where(.svelte-zid8p2){display:inline-flex;gap:5px;align-items:center}.swatch.err.svelte-zid8p2{background:var(--status-critical)}.controls.svelte-zid8p2{display:flex;gap:12px;align-items:center}.chk.svelte-zid8p2{display:flex;gap:5px;align-items:center;font-size:12.5px}.tl.svelte-zid8p2{display:grid;grid-template-columns:minmax(180px,260px) minmax(0,1fr);overflow:hidden}.labels.svelte-zid8p2{border-right:1px solid var(--border);background:var(--surface)}.axis-space.svelte-zid8p2{height:26px;border-bottom:1px solid var(--border)}.lane-label.svelte-zid8p2{display:flex;align-items:center;gap:6px;width:100%;height:30px;padding-right:8px;border:none;background:none;text-align:left;font-size:12.5px;min-width:0}.lane-label.svelte-zid8p2:hover,.lane-label.finished.svelte-zid8p2{background:var(--surface-2)}.lane-label.finished.svelte-zid8p2 .ll-main:where(.svelte-zid8p2){color:var(--faint)}.ll-main.svelte-zid8p2{font-weight:600;flex:none;max-width:60%}.lane-label.spawn.svelte-zid8p2 .ll-main:where(.svelte-zid8p2){color:var(--info)}.lane-label.finished.spawn.svelte-zid8p2 .ll-main:where(.svelte-zid8p2){color:var(--faint)}.ll-sub.svelte-zid8p2{min-width:0;font-size:11.5px}.scroller.svelte-zid8p2{overflow-x:auto}svg.svelte-zid8p2{display:block}.grid.svelte-zid8p2{stroke:var(--grid)}.tick.svelte-zid8p2{font-size:10.5px;fill:var(--faint)}.gap.svelte-zid8p2{fill:var(--surface-2);opacity:.8}.gap-label.svelte-zid8p2{font-style:italic}.lane-bg.svelte-zid8p2{fill:color-mix(in srgb,var(--busy) 12%,transparent)}.lane-bg.finished.svelte-zid8p2{fill:var(--surface-2)}.link.svelte-zid8p2{stroke:var(--faint);stroke-width:1}.link.spawn.svelte-zid8p2{stroke:var(--info);stroke-dasharray:3 3}.link-dot.svelte-zid8p2{fill:var(--faint)}.link-dot.spawn.svelte-zid8p2{fill:var(--info)}.turn.svelte-zid8p2{stroke:var(--muted);stroke-width:1;opacity:.5}.span.svelte-zid8p2{cursor:pointer}.span.svelte-zid8p2:hover{stroke:var(--text);stroke-width:1.5}@media(max-width:640px){.tl.svelte-zid8p2{grid-template-columns:minmax(96px,38%) minmax(0,1fr)}.ll-main.svelte-zid8p2{max-width:none;flex:1;min-width:0}.ll-sub.svelte-zid8p2{display:none}.controls.svelte-zid8p2{flex-wrap:wrap}}ul.svelte-1ofycba{list-style:none;margin:0;padding:0}li.svelte-1ofycba+li:where(.svelte-1ofycba),ul.svelte-1ofycba ul:where(.svelte-1ofycba){margin-top:2px}.node.svelte-1ofycba{display:flex;gap:8px;align-items:flex-start;padding:6px 8px;border-radius:7px;color:inherit;text-decoration:none;border:1px solid transparent}.node.svelte-1ofycba .dot{margin-top:6px}.node.svelte-1ofycba .mark{margin-top:3px}.node.svelte-1ofycba:hover{border-color:var(--border);text-decoration:none}.node.finished.svelte-1ofycba{background:var(--surface-2)}.node.finished.svelte-1ofycba .type:where(.svelte-1ofycba),.node.finished.svelte-1ofycba .desc:where(.svelte-1ofycba){color:var(--faint)}.node.finished.svelte-1ofycba .type:where(.svelte-1ofycba){font-weight:500}.node.sel.svelte-1ofycba{background:var(--accent-soft);border-color:color-mix(in srgb,var(--accent) 35%,transparent)}.node.sel.svelte-1ofycba .type:where(.svelte-1ofycba),.node.sel.svelte-1ofycba .desc:where(.svelte-1ofycba){color:var(--text)}.node.spawn.svelte-1ofycba .type:where(.svelte-1ofycba){color:var(--info)}.node.spawn.finished.svelte-1ofycba .type:where(.svelte-1ofycba){color:var(--faint)}.body.svelte-1ofycba{display:flex;flex-direction:column;min-width:0;flex:1}.line1.svelte-1ofycba{display:flex;flex-wrap:wrap;gap:2px 6px;align-items:baseline;min-width:0}.type.svelte-1ofycba{font-weight:600;font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}.tag.svelte-1ofycba{font-size:10.5px;color:var(--info)}.tag.done.svelte-1ofycba{color:var(--faint)}.when.svelte-1ofycba{margin-left:auto;font-size:11px;white-space:nowrap}.desc.svelte-1ofycba{font-size:12.5px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical}.stats.svelte-1ofycba{font-size:11px}summary.svelte-1pv0tzq{cursor:pointer;font-size:12px;color:var(--muted);-webkit-user-select:none;user-select:none}.json.svelte-1pv0tzq{max-height:420px;overflow:auto;padding:8px 10px;margin-top:4px;background:var(--code-bg);border-radius:6px;font-size:12px}.out.svelte-bitruc{background:var(--code-bg);border-radius:6px;overflow:hidden}.out.error.svelte-bitruc{background:var(--error-soft)}.label.svelte-bitruc{font-size:11px;color:var(--muted);padding:4px 10px 0;text-transform:uppercase;letter-spacing:.04em}pre.svelte-bitruc{padding:6px 10px 8px;overflow:auto}.error.svelte-bitruc pre:where(.svelte-bitruc){color:var(--error)}.entry.svelte-1li56xm{position:relative;padding-right:110px}.side.svelte-1li56xm{position:absolute;right:0;top:2px;display:flex;gap:4px;align-items:baseline;opacity:.55}.entry.svelte-1li56xm:hover .side:where(.svelte-1li56xm){opacity:1}@media(max-width:640px){.entry.svelte-1li56xm{display:flex;flex-direction:column;padding-right:0}.side.svelte-1li56xm{position:static;order:-1;align-self:flex-end;align-items:center;margin-bottom:-6px}.side.svelte-1li56xm .icon-btn:where(.svelte-1li56xm){min-height:32px;min-width:44px}.think.svelte-1li56xm{min-height:44px}details.line.svelte-1li56xm summary:where(.svelte-1li56xm){padding:10px 0}}.ts.svelte-1li56xm{font-size:11.5px;color:var(--faint);font-variant-numeric:tabular-nums}.who.svelte-1li56xm{display:flex;gap:8px;align-items:baseline;font-size:12px;font-weight:600;color:var(--muted);margin-bottom:3px}.who.svelte-1li56xm .faint:where(.svelte-1li56xm){font-weight:400}.user.svelte-1li56xm{background:var(--accent-soft);border-radius:10px;padding:8px 12px}.user.svelte-1li56xm .text:where(.svelte-1li56xm){font-family:var(--sans);font-size:14px;max-height:420px;overflow:auto}.assistant.svelte-1li56xm{padding:2px 0}.assistant.apierr.svelte-1li56xm{color:var(--error)}.md.svelte-1li56xm p{margin:0 0 2px}.md.svelte-1li56xm .md-gap{height:8px}.md.svelte-1li56xm ul,.md.svelte-1li56xm ol{margin:2px 0;padding-left:22px}.md.svelte-1li56xm code{background:var(--code-bg);padding:0 4px;border-radius:4px}.md.svelte-1li56xm .md-code{background:var(--code-bg);padding:8px 10px;border-radius:6px;margin:4px 0;overflow:auto;max-height:400px}.md.svelte-1li56xm .md-h{font-weight:600;margin:6px 0 2px}.md.svelte-1li56xm .md-h1,.md.svelte-1li56xm .md-h2{font-size:15px}.md.svelte-1li56xm .md-table{border-collapse:collapse;margin:4px 0;font-size:13px}.md.svelte-1li56xm .md-table td,.md.svelte-1li56xm .md-table th{border:1px solid var(--border);padding:2px 8px;text-align:left;vertical-align:top}.line.svelte-1li56xm{display:flex;gap:8px;align-items:baseline;font-size:12.5px;color:var(--muted);min-width:0}details.line.svelte-1li56xm{display:block}details.line.svelte-1li56xm summary:where(.svelte-1li56xm){cursor:pointer;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tag.svelte-1li56xm{flex:none;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.03em;color:var(--faint)}.dim.svelte-1li56xm{opacity:.8}.think.svelte-1li56xm{border:none;background:none;padding:0;width:100%;text-align:left;font-style:italic}.think-body.svelte-1li56xm{font-family:var(--sans);font-size:13px;font-style:italic;color:var(--muted);padding:4px 0 4px 12px;border-left:2px solid var(--border)}.sys.err.svelte-1li56xm{color:var(--error)}.sys.compact_boundary.svelte-1li56xm{padding:6px 0;border-top:1px dashed var(--border);border-bottom:1px dashed var(--border);color:var(--info)}.cmd.svelte-1li56xm .mono:where(.svelte-1li56xm){color:var(--text)}.notif.svelte-1li56xm{padding:6px 10px;border-left:3px solid var(--info);background:var(--info-soft);border-radius:4px;font-size:12.5px}.notif.svelte-1li56xm pre:where(.svelte-1li56xm){max-height:160px;overflow:auto}.unknown.svelte-1li56xm{padding:6px 10px;border:1px dashed var(--error);border-radius:6px}.meta.svelte-h9thfq,.stats.svelte-h9thfq{display:flex;gap:6px 12px;flex-wrap:wrap;align-items:center;font-size:12.5px}.open.svelte-h9thfq{display:inline-flex;align-items:center;gap:6px;margin-left:auto;font-weight:500}summary.svelte-h9thfq{cursor:pointer;font-size:12px;color:var(--muted)}.prompt.svelte-h9thfq{padding:8px 10px;background:var(--code-bg);border-radius:6px;max-height:320px;overflow:auto;margin-top:4px}.md.svelte-h9thfq{margin-top:4px;padding:4px 0 0 10px;border-left:2px solid var(--border)}.small.svelte-h9thfq{font-size:12px}.cmd.svelte-c2rndl{padding:6px 10px;background:var(--code-bg);border-radius:6px;font-weight:500}.flags.svelte-c2rndl{display:flex;gap:6px;flex-wrap:wrap}.flags.svelte-c2rndl:empty{display:none}.diff.svelte-91uzui{max-height:480px;overflow:auto;border-radius:6px;background:var(--code-bg)}table.svelte-91uzui{border-collapse:collapse;width:100%;font-family:var(--mono);font-size:12px}td.svelte-91uzui{padding:0 6px;vertical-align:top}.ln.svelte-91uzui{width:1%;color:var(--faint);text-align:right;-webkit-user-select:none;user-select:none;font-variant-numeric:tabular-nums}.sign.svelte-91uzui{width:1%;-webkit-user-select:none;user-select:none;color:var(--faint)}.kadd.svelte-91uzui{background:var(--add)}.kadd.svelte-91uzui .code:where(.svelte-91uzui),.kadd.svelte-91uzui .sign:where(.svelte-91uzui){color:var(--add-text)}.kdel.svelte-91uzui{background:var(--del)}.kdel.svelte-91uzui .code:where(.svelte-91uzui),.kdel.svelte-91uzui .sign:where(.svelte-91uzui){color:var(--del-text)}.khunk.svelte-91uzui td:where(.svelte-91uzui){color:var(--info);background:var(--info-soft);padding-top:2px;padding-bottom:2px}.path.svelte-g6pwu3{font-size:12px;word-break:break-all;display:flex;gap:8px;align-items:center}.path.svelte-1pl9rnj{font-size:12px;word-break:break-all}.q.svelte-180n7pj{display:flex;gap:6px;flex-wrap:wrap;align-items:center}.pattern.svelte-180n7pj{font-weight:600}.small.svelte-180n7pj{font-size:12px}.path.svelte-eak8ac{font-size:12px;word-break:break-all;display:flex;gap:8px;align-items:center}.tool.svelte-1aouhgl{border:1px solid var(--border);border-radius:8px;background:var(--surface);overflow:hidden}.tool.error.svelte-1aouhgl{border-color:color-mix(in srgb,var(--error) 45%,var(--border))}.tool.pending.svelte-1aouhgl{border-color:color-mix(in srgb,var(--busy) 55%,var(--border))}.row.svelte-1aouhgl{display:flex;align-items:baseline;gap:8px;width:100%;padding:5px 10px;border:none;background:none;text-align:left;min-width:0}.row.svelte-1aouhgl:hover{background:var(--surface-2)}.chev.svelte-1aouhgl{flex:none;width:10px;color:var(--faint);font-size:11px}.server.svelte-1aouhgl{flex:none;font-size:11px;color:var(--faint);font-family:var(--mono)}.name.svelte-1aouhgl{flex:none;font-family:var(--mono);font-size:12.5px;font-weight:600;color:var(--accent)}.summary.svelte-1aouhgl{flex:1;min-width:0;font-size:13px;color:var(--text)}.spawn-hint.svelte-1aouhgl{flex:none;font-size:11.5px;color:var(--info)}.spawns.svelte-1aouhgl{display:flex;flex-direction:column;gap:4px}.spawn.svelte-1aouhgl{display:flex;align-items:center;gap:8px;min-width:0;padding:6px 10px;border-radius:7px;background:var(--info-soft);color:var(--text);font-size:13px;text-decoration:none}.spawn.finished.svelte-1aouhgl{background:var(--surface-2);color:var(--muted)}.spawn.svelte-1aouhgl .open:where(.svelte-1aouhgl){margin-left:auto;flex:none;color:var(--accent)}.st.svelte-1aouhgl{flex:none;font-size:11.5px;padding:0 6px;border-radius:9px;background:var(--surface-2);color:var(--muted)}.error.svelte-1aouhgl .st:where(.svelte-1aouhgl),.denied.svelte-1aouhgl .st:where(.svelte-1aouhgl){background:var(--error-soft);color:var(--error)}.pending.svelte-1aouhgl .st:where(.svelte-1aouhgl){background:color-mix(in srgb,var(--busy) 18%,transparent);color:var(--busy)}.took.svelte-1aouhgl,.ts.svelte-1aouhgl{flex:none;font-size:11.5px;color:var(--faint);font-variant-numeric:tabular-nums}.ts.svelte-1aouhgl{width:58px;text-align:right}.body.svelte-1aouhgl{display:flex;flex-direction:column;gap:8px;padding:8px 12px 10px 28px;border-top:1px solid var(--border)}.foot.svelte-1aouhgl{display:flex;gap:10px;align-items:baseline;flex-wrap:wrap}.spacer.svelte-1aouhgl{flex:1}.small.svelte-1aouhgl{font-size:11px}@media(max-width:640px){.ts.svelte-1aouhgl,.server.svelte-1aouhgl{display:none}.row.svelte-1aouhgl{align-items:center;min-height:44px;padding:6px 10px}.body.svelte-1aouhgl{padding:8px 10px 10px}.spawn.svelte-1aouhgl{flex-wrap:wrap;min-height:44px}.foot.svelte-1aouhgl .icon-btn:where(.svelte-1aouhgl){min-height:44px;padding:0 8px}}.toolbar.svelte-17i7dft{position:sticky;top:52px;z-index:5;display:flex;flex-wrap:wrap;gap:6px 14px;align-items:center;padding:8px 0 10px;margin-bottom:6px;background:var(--bg);border-bottom:1px solid var(--border);font-size:12.5px}label.svelte-17i7dft{display:flex;align-items:center;gap:4px;cursor:pointer;-webkit-user-select:none;user-select:none}.toolbar.svelte-17i7dft input[type=search]:where(.svelte-17i7dft){margin-left:auto;width:min(260px,100%);padding:3px 9px}@media(max-width:640px){.toolbar.svelte-17i7dft{position:static;font-size:14px;gap:0 14px}label.svelte-17i7dft{min-height:44px}.toolbar.svelte-17i7dft input[type=search]:where(.svelte-17i7dft){padding:6px 10px}}.entries.svelte-17i7dft{display:flex;flex-direction:column;gap:8px}.item.focused.svelte-17i7dft{outline:2px solid var(--accent);outline-offset:4px;border-radius:8px}.older.svelte-17i7dft{text-align:center;margin:6px 0 12px}.follow.svelte-17i7dft{text-align:center;font-size:12px;padding:14px 0}.peek.svelte-1us386d{position:fixed;top:52px;left:0;right:0;z-index:9;display:flex;align-items:center;gap:10px;min-width:0;padding:7px 24px;background:color-mix(in srgb,var(--bg) 92%,transparent);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border-bottom:1px solid var(--border);box-shadow:0 4px 12px #0000000f;transform:translateY(-110%);opacity:0;pointer-events:none;transition:transform .18s ease,opacity .18s ease}.peek.show.svelte-1us386d{transform:none;opacity:1;pointer-events:auto}.peek-title.svelte-1us386d{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.peek-sub.svelte-1us386d,.peek-meta.svelte-1us386d{white-space:nowrap;font-size:12.5px}.peek-actions.svelte-1us386d{margin-left:auto;display:flex;gap:6px;flex-shrink:0}@media(max-width:640px){.peek.svelte-1us386d{padding:6px 12px}.peek-meta.svelte-1us386d{display:none}}.cpu-card.svelte-1us386d{padding:16px;min-width:0}.resume-row.svelte-1us386d{margin-top:12px;padding-top:12px;border-top:1px solid var(--border)}.spawned-by.svelte-1us386d{display:flex;align-items:center;gap:7px;flex-wrap:wrap;font-size:13px}.tabs.svelte-1us386d{display:flex;gap:2px;border-bottom:1px solid var(--border);margin:-4px 0 14px}.tabs.svelte-1us386d a:where(.svelte-1us386d){padding:7px 14px;color:var(--muted);border-bottom:2px solid transparent;margin-bottom:-1px;text-decoration:none;font-weight:500}.tabs.svelte-1us386d a:where(.svelte-1us386d):hover{color:var(--text)}.tabs.svelte-1us386d a.on:where(.svelte-1us386d){color:var(--text);border-bottom-color:var(--accent)}.n.svelte-1us386d{margin-left:6px;font-size:11px;padding:0 6px;border-radius:9px;background:var(--surface-2);color:var(--muted)}.crumbs.svelte-1us386d{font-size:12.5px;margin-bottom:8px}.head.svelte-1us386d{padding:14px 18px;margin-bottom:18px;display:flex;flex-direction:column;gap:6px}.title-row.svelte-1us386d{display:flex;align-items:center;gap:10px;flex-wrap:wrap}h1.svelte-1us386d{font-size:19px}.now.svelte-1us386d{padding:7px 10px;background:var(--surface-2);border-radius:7px;max-width:900px}dl.svelte-1us386d{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(230px,100%),1fr));gap:6px 20px;margin:6px 0 0}dl.svelte-1us386d div:where(.svelte-1us386d){min-width:0}dt.svelte-1us386d{font-size:11.5px;color:var(--faint)}dd.svelte-1us386d{margin:0;font-size:13px;overflow:hidden;text-overflow:ellipsis}.layout.svelte-1us386d{display:grid;grid-template-columns:290px minmax(0,1fr);min-width:0;gap:20px;align-items:start}aside.svelte-1us386d{position:sticky;top:64px;transition:top .18s ease;max-height:calc(100vh - 80px);overflow-y:auto;overflow-x:hidden}.peeking.svelte-1us386d aside:where(.svelte-1us386d){top:108px}.aside-head.svelte-1us386d{font-size:12px;margin:0 0 6px 8px}.sub-head.svelte-1us386d{display:flex;gap:10px;align-items:center;padding:10px 14px;margin-bottom:8px}.back.svelte-1us386d{margin-left:auto;white-space:nowrap}.meta-toggle.svelte-1us386d{display:none}dd.svelte-1us386d{overflow-wrap:anywhere}.small.svelte-1us386d{font-size:12px}@media(max-width:900px){.layout.svelte-1us386d{grid-template-columns:minmax(0,1fr)}aside.svelte-1us386d{position:static;max-height:300px}}@media(max-width:640px){.head.svelte-1us386d{padding:12px 14px}h1.svelte-1us386d{font-size:17px;overflow-wrap:anywhere}.meta-toggle.svelte-1us386d{display:block;align-self:flex-start;min-height:44px;padding:0 2px;border:none;background:none;color:var(--muted);font-size:14px}dl.svelte-1us386d{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px 14px;margin:0}dl.collapsed.svelte-1us386d{display:none}dl.svelte-1us386d>div:where(.svelte-1us386d):last-child{grid-column:1 / -1}dd.svelte-1us386d{font-size:14px}.tabs.svelte-1us386d{overflow-x:auto;scrollbar-width:none}.tabs.svelte-1us386d a:where(.svelte-1us386d){display:flex;align-items:center;min-height:44px;padding:0 12px;white-space:nowrap}.sub-head.svelte-1us386d{flex-wrap:wrap}.back.svelte-1us386d{min-height:44px;display:flex;align-items:center}}.head.svelte-f3z2nw{display:flex;align-items:baseline;gap:12px;margin-bottom:12px}input.svelte-f3z2nw{margin-left:auto;width:min(360px,50vw)}@media(max-width:640px){.head.svelte-f3z2nw{flex-wrap:wrap}input.svelte-f3z2nw{margin-left:0;width:100%}}.more.svelte-f3z2nw{text-align:center;margin-top:14px}.top.svelte-16t12jp{position:sticky;top:0;z-index:10;display:flex;align-items:center;gap:28px;padding:0 24px;height:52px;background:color-mix(in srgb,var(--bg) 88%,transparent);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border-bottom:1px solid var(--border)}.brand.svelte-16t12jp{display:flex;align-items:center;gap:8px;font-weight:600;color:var(--text);text-decoration:none}nav.svelte-16t12jp{display:flex;gap:2px;overflow-x:auto;min-width:0}nav.svelte-16t12jp a:where(.svelte-16t12jp){white-space:nowrap}nav.svelte-16t12jp a:where(.svelte-16t12jp){color:var(--muted);padding:5px 12px;border-radius:7px;text-decoration:none}nav.svelte-16t12jp a:where(.svelte-16t12jp):hover{background:var(--surface-2)}nav.svelte-16t12jp a.active:where(.svelte-16t12jp){color:var(--text);background:var(--surface-2);font-weight:500}.count.svelte-16t12jp{display:inline-block;min-width:18px;padding:0 5px;margin-left:2px;border-radius:9px;background:var(--accent-soft);color:var(--accent);font-size:11.5px;text-align:center}.theme.svelte-16t12jp{margin-left:auto;display:grid;place-items:center;width:30px;height:30px;border:1px solid var(--border);border-radius:8px;background:var(--surface);color:var(--muted)}.theme.svelte-16t12jp:hover{color:var(--text);background:var(--surface-2)}.conn.svelte-16t12jp{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--faint)}.conn.svelte-16t12jp .dot:where(.svelte-16t12jp){width:7px;height:7px;border-radius:50%;background:var(--dead)}.conn.ok.svelte-16t12jp .dot:where(.svelte-16t12jp){background:var(--busy)}main.svelte-16t12jp{padding:20px 24px 60px;max-width:1600px;margin:0 auto}.menu.svelte-16t12jp,.scrim.svelte-16t12jp{display:none}@media(max-width:760px){.top.svelte-16t12jp{padding:0 12px;gap:8px}.brand.svelte-16t12jp{flex:none;min-height:44px}.menu.svelte-16t12jp{display:inline-flex;align-items:center;gap:6px;min-height:40px;min-width:44px;padding:0 10px;border:1px solid var(--border);border-radius:8px;background:var(--surface);color:var(--text);font-weight:500}.menu[aria-expanded=true].svelte-16t12jp{background:var(--surface-2)}nav.svelte-16t12jp{display:none;position:absolute;top:52px;left:0;right:0;flex-direction:column;gap:2px;padding:8px 12px 12px;background:var(--bg);border-bottom:1px solid var(--border);box-shadow:0 8px 24px #0000001f;overflow:visible}nav.open.svelte-16t12jp{display:flex}nav.svelte-16t12jp a:where(.svelte-16t12jp){display:flex;align-items:center;gap:6px;min-height:44px;padding:0 12px;font-size:15px}.scrim.svelte-16t12jp{display:block;position:fixed;top:52px;right:0;bottom:0;left:0;z-index:9;border:none;padding:0;background:#00000040}.theme.svelte-16t12jp{width:40px;height:40px}main.svelte-16t12jp{padding:14px 12px 40px}}@media(max-width:400px){.brand-name.svelte-16t12jp,.conn-label.svelte-16t12jp{display:none}}:root{--bg: #f6f5f1;--surface: #ffffff;--surface-2: #f0eee8;--border: #e3e0d8;--text: #1f1e1c;--muted: #6b6860;--faint: #9b978d;--accent: #c2643f;--accent-soft: #f6e6de;--busy: #2f9e5b;--idle: #c9962a;--dead: #a8a49b;--error: #cc3d3d;--error-soft: #fbe9e9;--info: #3f6fc2;--info-soft: #e6eefb;--add: #e3f4e6;--add-text: #1d6b33;--del: #fbe7e7;--del-text: #a12b2b;--code-bg: #f3f1ec;--shadow: 0 1px 2px rgb(0 0 0 / .04), 0 2px 8px rgb(0 0 0 / .04);--series-1: #2a78d6;--series-2: #eb6834;--series-3: #1baf7a;--series-4: #eda100;--series-5: #e87ba4;--series-6: #008300;--series-7: #4a3aa7;--series-8: #e34948;--series-other: #a8a49b;--seq-0: #f0eee8;--seq-1: #cde2fb;--seq-2: #9ec5f4;--seq-3: #6da7ec;--seq-4: #3987e5;--seq-5: #256abf;--seq-6: #184f95;--seq-7: #0d366b;--status-good: #0ca30c;--status-critical: #d03b3b;--grid: #e8e6df;--radius: 10px;--mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;--sans: -apple-system, BlinkMacSystemFont, "Inter", "Segoe UI", system-ui, sans-serif;color-scheme:light}@media(prefers-color-scheme:dark){:root:not([data-theme=light]){--bg: #161614;--surface: #1f1e1b;--surface-2: #282724;--border: #353430;--text: #ebe8e1;--muted: #a39f95;--faint: #75726a;--accent: #e0835f;--accent-soft: #3a2a22;--busy: #4cc27b;--idle: #deb04a;--dead: #6f6c65;--error: #ef6666;--error-soft: #3b2222;--info: #7aa2ee;--info-soft: #1f2a3d;--add: #1c3524;--add-text: #8fdca5;--del: #3d1f1f;--del-text: #f0a0a0;--code-bg: #262521;--shadow: 0 1px 2px rgb(0 0 0 / .3);--series-1: #3987e5;--series-2: #d95926;--series-3: #199e70;--series-4: #c98500;--series-5: #d55181;--series-6: #008300;--series-7: #9085e9;--series-8: #e66767;--series-other: #6f6c65;--seq-0: #262521;--seq-1: #104281;--seq-2: #184f95;--seq-3: #1c5cab;--seq-4: #256abf;--seq-5: #3987e5;--seq-6: #6da7ec;--seq-7: #9ec5f4;--grid: #2e2d29;color-scheme:dark}}:root[data-theme=dark]{--bg: #161614;--surface: #1f1e1b;--surface-2: #282724;--border: #353430;--text: #ebe8e1;--muted: #a39f95;--faint: #75726a;--accent: #e0835f;--accent-soft: #3a2a22;--busy: #4cc27b;--idle: #deb04a;--dead: #6f6c65;--error: #ef6666;--error-soft: #3b2222;--info: #7aa2ee;--info-soft: #1f2a3d;--add: #1c3524;--add-text: #8fdca5;--del: #3d1f1f;--del-text: #f0a0a0;--code-bg: #262521;--shadow: 0 1px 2px rgb(0 0 0 / .3);--series-1: #3987e5;--series-2: #d95926;--series-3: #199e70;--series-4: #c98500;--series-5: #d55181;--series-6: #008300;--series-7: #9085e9;--series-8: #e66767;--series-other: #6f6c65;--seq-0: #262521;--seq-1: #104281;--seq-2: #184f95;--seq-3: #1c5cab;--seq-4: #256abf;--seq-5: #3987e5;--seq-6: #6da7ec;--seq-7: #9ec5f4;--grid: #2e2d29;color-scheme:dark}*{box-sizing:border-box}html,body{margin:0;background:var(--bg);color:var(--text);font:14px/1.5 var(--sans);-webkit-font-smoothing:antialiased}a{color:var(--accent);text-decoration:none}a:hover{text-decoration:underline}code,pre,.mono{font-family:var(--mono);font-size:12.5px}pre{margin:0;white-space:pre-wrap;word-break:break-word}h1,h2,h3{margin:0;font-weight:600;letter-spacing:-.01em}h2{font-size:15px}button{font:inherit;color:inherit;cursor:pointer}.muted{color:var(--muted)}.faint{color:var(--faint)}.badge{display:inline-flex;align-items:center;gap:4px;padding:1px 7px;border-radius:999px;font-size:11.5px;line-height:18px;background:var(--surface-2);color:var(--muted);white-space:nowrap}.badge.accent{background:var(--accent-soft);color:var(--accent)}.badge.info{background:var(--info-soft);color:var(--info)}.badge.error{background:var(--error-soft);color:var(--error)}.card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);box-shadow:var(--shadow)}.btn{border:1px solid var(--border);background:var(--surface);border-radius:7px;padding:3px 10px;font-size:12.5px}.btn:hover{background:var(--surface-2)}.icon-btn{border:none;background:none;padding:0 4px;color:var(--faint);font-family:var(--mono);font-size:11px}.icon-btn:hover{color:var(--accent)}table.list{width:100%;border-collapse:collapse}table.list th{text-align:left;font-weight:500;font-size:12px;color:var(--muted);padding:6px 10px;border-bottom:1px solid var(--border)}table.list td{padding:7px 10px;border-bottom:1px solid var(--border);vertical-align:top}table.list tr:last-child td{border-bottom:none}table.list tr.clickable:hover td{background:var(--surface-2);cursor:pointer}.ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}input[type=search],input[type=text]{font:inherit;color:inherit;background:var(--surface);border:1px solid var(--border);border-radius:7px;padding:5px 10px;outline:none}input[type=search]:focus{border-color:var(--accent)}.page-head{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;margin-bottom:14px}.filters{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.filters select,.filters input{font:inherit;font-size:13px;color:inherit;background:var(--surface);border:1px solid var(--border);border-radius:7px;padding:4px 8px}.seg{display:inline-flex;border:1px solid var(--border);border-radius:7px;overflow:hidden}.seg button{border:none;background:var(--surface);padding:4px 10px;font-size:12.5px;color:var(--muted)}.seg button+button{border-left:1px solid var(--border)}.seg button.on{background:var(--surface-2);color:var(--text);font-weight:500}.num{text-align:right;font-variant-numeric:tabular-nums}.tip{position:fixed;z-index:60;pointer-events:none;background:var(--surface);border:1px solid var(--border);border-radius:8px;box-shadow:0 4px 16px #0000001f;padding:7px 10px;font-size:12.5px;left:0;top:0;max-width:min(360px,calc(100vw - 16px));max-height:calc(100vh - 16px);overflow:hidden;overflow-wrap:anywhere}.swatch{display:inline-block;width:9px;height:9px;border-radius:2px;flex:none}.table-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch}html{-webkit-text-size-adjust:100%;text-size-adjust:100%}@media(max-width:760px){input[type=search],input[type=text],.filters select,.filters input:not([type=checkbox]){font-size:16px;min-height:44px}.filters input[type=search],.filters input[type=text]{flex:1 1 100%;width:100%!important;margin-left:0!important}.btn,.seg button{min-height:44px;padding:6px 14px;font-size:14px}input[type=checkbox]{width:20px;height:20px}table.list td{padding:10px}}@media(hover:none){table.list tr.clickable:hover td{background:none}}