@deepseek-insight/dsi 0.11.4 → 0.11.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/.agents/skills/glass-dsh/SKILL.md +18 -4
  2. package/.agents/skills/glass-dsh/scripts/_connect.mjs +37 -1
  3. package/.agents/skills/glass-dsh/scripts/gesture.mjs +117 -45
  4. package/README.md +9 -3
  5. package/bin/dsi-chassis.mjs +40 -6
  6. package/build/client/_app/immutable/assets/0.DtmjX3F5.css +2 -0
  7. package/build/client/_app/immutable/chunks/{C2MzPOYY.js → 5F6_LRci.js} +2 -2
  8. package/build/client/_app/immutable/chunks/Cy0k93LK.js +1 -0
  9. package/build/client/_app/immutable/chunks/DnaGnyhX.js +1 -0
  10. package/build/client/_app/immutable/chunks/{BQI9wyZo.js → QgjwhBIU.js} +1 -1
  11. package/build/client/_app/immutable/entry/{app.CaHTeMGs.js → app.Co_inv9_.js} +2 -2
  12. package/build/client/_app/immutable/entry/start.ChC0XjdC.js +1 -0
  13. package/build/client/_app/immutable/nodes/{1.AoWxyOCL.js → 1.CehXn9FF.js} +1 -1
  14. package/build/client/_app/immutable/nodes/{2.BiOhzV1A.js → 2.w_WIg8AR.js} +2 -2
  15. package/build/client/_app/version.json +1 -1
  16. package/build/handler.js +4 -4
  17. package/build/index.js +4 -4
  18. package/build/server/chunks/chunks/{internal2.js-y5mpUnMs.js → internal2.js-DnFD_BfX.js} +2 -2
  19. package/build/server/chunks/chunks/{registry.js-Cnmd1vW3.js → registry.js-BuEw-96E.js} +2 -2
  20. package/build/server/chunks/chunks/{state.js-DgYQBCjR.js → state.js-CDQqciQ7.js} +2 -2
  21. package/build/server/chunks/entries/endpoints/api/browser/_id_/activate/{_server.ts.js-DlbbO3RF.js → _server.ts.js-BWbEzlCm.js} +2 -2
  22. package/build/server/chunks/entries/endpoints/api/browser/_id_/close/{_server.ts.js-B85bLw4w.js → _server.ts.js-BRhxONLL.js} +2 -2
  23. package/build/server/chunks/entries/endpoints/api/browser/_id_/closetab/{_server.ts.js-Dt5Bxv2-.js → _server.ts.js-DcafQOUs.js} +2 -2
  24. package/build/server/chunks/entries/endpoints/api/browser/_id_/element/{_server.ts.js-uJ5BnGUA.js → _server.ts.js-BBSIIDAx.js} +2 -2
  25. package/build/server/chunks/entries/endpoints/api/browser/_id_/history/{_server.ts.js-CVCoWk2n.js → _server.ts.js-BDAujEcp.js} +2 -2
  26. package/build/server/chunks/entries/endpoints/api/browser/_id_/input/{_server.ts.js-CmhQ7zGO.js → _server.ts.js-PP6mc-7m.js} +2 -2
  27. package/build/server/chunks/entries/endpoints/api/browser/_id_/mcp/{_server.ts.js-CFtpmSCd.js → _server.ts.js-N1WWoP-W.js} +2 -2
  28. package/build/server/chunks/entries/endpoints/api/browser/_id_/navigate/{_server.ts.js-BH8MNt9W.js → _server.ts.js-7iuI6c8E.js} +2 -2
  29. package/build/server/chunks/entries/endpoints/api/browser/_id_/opentab/{_server.ts.js-uIrK0T8h.js → _server.ts.js-CsF_LSmK.js} +2 -2
  30. package/build/server/chunks/entries/endpoints/api/browser/_id_/page/{_server.ts.js-Bg5yHS9F.js → _server.ts.js-CshBvfm4.js} +2 -2
  31. package/build/server/chunks/entries/endpoints/api/browser/_id_/stream/{_server.ts.js-DG6xvUsm.js → _server.ts.js-CAtPWIGT.js} +2 -2
  32. package/build/server/chunks/entries/endpoints/api/browser/_id_/tabs/{_server.ts.js-RiXP45mV.js → _server.ts.js-Cuqk6xWI.js} +2 -2
  33. package/build/server/chunks/entries/endpoints/api/browser/_id_/viewport/{_server.ts.js-w9MNQddQ.js → _server.ts.js-CstasxV_.js} +2 -2
  34. package/build/server/chunks/entries/endpoints/api/browser/_id_/zoom/{_server.ts.js-BoXDoshV.js → _server.ts.js-BAe1WUX-.js} +2 -2
  35. package/build/server/chunks/entries/endpoints/api/browser/{_server.ts.js-pQmJm_Io.js → _server.ts.js-CkzA7KWV.js} +2 -2
  36. package/build/server/chunks/entries/pages/{_error.svelte.js-BIJ7nQ2M.js → _error.svelte.js-D3pmlPEF.js} +3 -3
  37. package/build/server/chunks/entries/pages/{_page.svelte.js-u9R9oLkN.js → _page.svelte.js-obnPPtTC.js} +4 -4
  38. package/build/server/chunks/{handler-B33Zuq6Y.js → handler-C5MXm18U.js} +3 -3
  39. package/build/server/chunks/{index.js-_yRI545U.js → index.js-BNS107fU.js} +2 -2
  40. package/build/server/chunks/{manifest.js-mKEDDCRk.js → manifest.js-y2FjcUQH.js} +20 -20
  41. package/build/server/chunks/nodes/{0.js-B8ciwPSu.js → 0.js-tNBtSaEq.js} +3 -3
  42. package/build/server/chunks/nodes/1.js-09WIpQBi.js +9 -0
  43. package/build/server/chunks/nodes/{2.js-qAWSZ3SP.js → 2.js-B_yNxiNi.js} +3 -3
  44. package/package.json +1 -1
  45. package/template/.dsi/prompts.sqlite-shm +0 -0
  46. package/template/.dsi/prompts.sqlite-wal +0 -0
  47. package/build/client/_app/immutable/assets/0.Bjw4vcZl.css +0 -2
  48. package/build/client/_app/immutable/chunks/C-zV0ulT.js +0 -1
  49. package/build/client/_app/immutable/chunks/DQy5rtST.js +0 -1
  50. package/build/client/_app/immutable/entry/start.D9CL1tVI.js +0 -1
  51. package/build/server/chunks/nodes/1.js-Cw3CxJ6F.js +0 -9
  52. /package/build/client/_app/immutable/nodes/{0.DopnsZUT.js → 0.IJdZxujs.js} +0 -0
@@ -55,10 +55,15 @@ The floor registry (glass sessions) is resolved separately: `DSI_UI` env when
55
55
  set, else probe `5175` then `5174` (`/api/browser`). A floor stamps its own
56
56
  addresses at boot — agents in a floor's conversations drive that floor's glass.
57
57
 
58
- ## Environment contract (D6)
59
-
60
- - Run `node skills/glass-dsh/scripts/*.mjs` from the **DSI repo root** so
61
- `playwright-core` resolves; plain node ESM, no build step.
58
+ ## Environment contract (D6, amended by D16 2026-11-09)
59
+
60
+ - Plain node ESM, no build step. The driver resolves `playwright-core`
61
+ **itself** (D16): script-relative `node_modules` → the cwd's `package.json`
62
+ tree → `$DSI_REPO_ROOT` → loud death naming the remedy. Running from the DSI
63
+ repo root still works (the cwd fallback), but is no longer required; there is
64
+ NO symlink step. If the skill directory is read-only (harness workspace-write
65
+ mode), copying `scripts/` into the workspace is the sanctioned deployment —
66
+ the copy bootstraps itself.
62
67
  - Every verb prints ONE JSON verdict on stdout and exits 0/1; failures print
63
68
  `{"error": ...}` via `die()` — a refusal is an answer, quote it.
64
69
  - No state files between runs: every run re-derives session and tab from the
@@ -76,6 +81,15 @@ addresses at boot — agents in a floor's conversations drive that floor's glass
76
81
  3. **Gestures (Gates 3–4)** — one verb per process, composition in your hands:
77
82
  `glass-dsh.mjs eval --b64` for reads, `gesture.mjs click|type|drag|control|persist`
78
83
  for real input. Each verb prints `{before, after, moved}` — quote the pair.
84
+ For gesture SEQUENCES prefer the D17 composite (one process, one CDP session,
85
+ one verdict per step):
86
+ `node gesture.mjs run steps.json` where steps.json is an array like
87
+ `[{"verb":"click","selector":"…","label":"open"},{"verb":"drag","selector":"…","dx":-433,"dy":-303},{"verb":"type","selector":"…","text":"…"},{"verb":"control","expr":"…"}]`
88
+ → `{"verb":"run","steps":4,"executed":N,"failedAt":null,"ok":true,"results":[…per-step verdicts…]}`
89
+ and exit 1 if any step failed. The composite STOPS at the first failed gate
90
+ (control `pass:false`, gesture `moved:false`, any `die`) and reports the
91
+ completed prefix — quote the prefix, do not improvise onward (D11). Single
92
+ verbs stay for one-off reads and re-runs of a single failed step.
79
93
  4. **Restore (Gate 5)** — clear seeded state via the page's own store, reload,
80
94
  re-probe: launcher present, console clean, store empty.
81
95
  5. **Report** — table of before/after numbers, the gesture that produced them,
@@ -26,7 +26,43 @@
26
26
  * (never a port substring, never positional). Dies when
27
27
  * absent, naming the resolved origin.
28
28
  */
29
- import { chromium } from 'playwright-core';
29
+ import { createRequire } from 'node:module';
30
+ import { join } from 'node:path';
31
+
32
+ // D16 (ADR-0045 Amendment 7) — the driver resolves its own engine; the cwd is
33
+ // never the contract. Resolution order: script-relative node_modules → the
34
+ // cwd's package.json tree (the documented "run from the repo root" case) →
35
+ // the stamped default repo (~/agentic-ai/deepseek-insight) or $DSI_REPO_ROOT →
36
+ // die loudly with the exact remedy. ESM bare imports resolve from the script's
37
+ // own directory, which is why cwd alone was never enough.
38
+ function resolveChromium() {
39
+ const attempts = [];
40
+ const repoCandidates = [];
41
+ if (process.env.DSI_REPO_ROOT) repoCandidates.push(process.env.DSI_REPO_ROOT);
42
+ if (process.env.HOME) repoCandidates.push(join(process.env.HOME, 'agentic-ai', 'deepseek-insight'));
43
+ const tryRequire = (label, anchor) => {
44
+ try {
45
+ return createRequire(anchor)('playwright-core');
46
+ } catch (e) {
47
+ attempts.push(label + ': ' + (e?.code ?? e?.message ?? String(e)));
48
+ return null;
49
+ }
50
+ };
51
+ let mod = tryRequire('script-relative', import.meta.url);
52
+ if (!mod) mod = tryRequire('cwd', join(process.cwd(), 'package.json'));
53
+ for (const root of repoCandidates) {
54
+ if (mod) break;
55
+ mod = tryRequire('repo:' + root, join(root, 'package.json'));
56
+ }
57
+ if (!mod?.chromium) {
58
+ die('playwright-core not resolvable — tried: ' + attempts.join(' | ') +
59
+ '. Remedy: run from the DSI repo root (cwd with a package.json), copy these ' +
60
+ 'scripts next to a node_modules that has playwright-core, export DSI_REPO_ROOT=<repo path>, ' +
61
+ 'or clone the DSI repo to ~/agentic-ai/deepseek-insight.');
62
+ }
63
+ return mod.chromium;
64
+ }
65
+ const chromium = resolveChromium();
30
66
 
31
67
  const DEFAULT_FLOOR_BASES = ['http://127.0.0.1:5175', 'http://127.0.0.1:5174'];
32
68
 
@@ -3,7 +3,7 @@
3
3
  * gesture.mjs — real-gesture verbs for the glass-dsh skill (Gates 3–5, D15).
4
4
  * Real mouse/keyboard only: synthetic dispatchEvent is not verification.
5
5
  * One verb per process; each prints {before, after, moved|delta} JSON.
6
- * Run from the DSI repo root (playwright-core resolves there).
6
+ * Run from any cwd (D16: the driver resolves its own playwright-core).
7
7
  *
8
8
  * Verbs:
9
9
  * click <selector> real click (raises interception as an error, never force-clicks)
@@ -11,10 +11,17 @@
11
11
  * drag <selector> <dx> <dy> real mouse down → 10 stepped moves with waits → up, on the element's box
12
12
  * control <js-expr> control gate: evaluate an assertion expression → {pass, result}
13
13
  * persist <localStorageKey> read a store key from the DSH tab → {raw}
14
+ * run <steps.json> D17 composite: ONE process + ONE CDP session executes a JSON
15
+ * array of steps ({verb, …args, label?}) in order, printing one
16
+ * verdict per step (same shapes as the single verbs) and stopping
17
+ * at the first failed gate — control pass:false, a moved:false on
18
+ * a gesture, or any die() — reporting the completed prefix.
19
+ * Exit 1 when a step failed, 0 otherwise (D11 stop-loss, batched).
14
20
  *
15
21
  * Flags: --dsh-url|--dsh-port|--owner-session (see _connect.mjs); --substr <s> selects a tab by URL
16
22
  * substring for reads (never positional, D10); input verbs always target the DSH-origin tab.
17
23
  */
24
+ import { readFileSync } from 'node:fs';
18
25
  import { connect, pickByOrigin, originOf, die } from './_connect.mjs';
19
26
 
20
27
  const argv = process.argv.slice(2);
@@ -35,64 +42,129 @@ function page() {
35
42
  return pickByOrigin(ctx, dshOrigin);
36
43
  }
37
44
 
38
- if (verb === 'click') {
45
+ async function readHostPos(p, sel) {
46
+ return p.evaluate((s) => {
47
+ const el = document.querySelector(s);
48
+ if (!el) return null;
49
+ const host = el.closest('[style*="left"]') ?? el;
50
+ return { x: host.style.left, y: host.style.top };
51
+ }, sel);
52
+ }
53
+
54
+ /**
55
+ * Execute one step; returns { ok, verdict }. Verdict shapes are byte-identical
56
+ * to the single-verb shapes (D17 — additive composition only).
57
+ */
58
+ async function execStep(p, step) {
59
+ const v = step.verb;
60
+ try {
61
+ if (v === 'click') {
62
+ const sel = step.selector;
63
+ if (!sel) return { ok: false, verdict: { error: 'click needs a selector' } };
64
+ const before = await p.evaluate((s) => !!document.querySelector(s), sel);
65
+ await p.locator(sel).first().click(); // locator.click raises interception loudly (no force)
66
+ return { ok: true, verdict: { verb: 'click', selector: sel, before, after: true, moved: before !== true } };
67
+ }
68
+ if (v === 'type') {
69
+ const sel = step.selector, text = step.text;
70
+ if (!sel || text === undefined) return { ok: false, verdict: { error: 'type needs selector + text' } };
71
+ const loc = p.locator(sel).first();
72
+ await loc.click();
73
+ await p.keyboard.type(text);
74
+ const after = await loc.inputValue().catch(() => undefined);
75
+ return { ok: after === text, verdict: { verb: 'type', selector: sel, before: '', after, moved: after === text } };
76
+ }
77
+ if (v === 'drag') {
78
+ const sel = step.selector, dx = Number(step.dx), dy = Number(step.dy);
79
+ if (!sel || !Number.isFinite(dx) || !Number.isFinite(dy)) {
80
+ return { ok: false, verdict: { error: 'drag needs selector + finite dx/dy' } };
81
+ }
82
+ const posBefore = await readHostPos(p, sel);
83
+ if (!posBefore) return { ok: false, verdict: { error: 'no element for ' + sel } };
84
+ const box = await p.locator(sel).first().boundingBox();
85
+ if (!box) return { ok: false, verdict: { error: 'boundingBox failed for ' + sel } };
86
+ const sx = box.x + box.width / 2, sy = box.y + Math.min(box.height / 2, 8);
87
+ await p.mouse.move(sx, sy);
88
+ await p.mouse.down();
89
+ for (let i = 1; i <= 10; i++) {
90
+ await p.mouse.move(sx + (dx * i) / 10, sy + (dy * i) / 10);
91
+ await new Promise((r) => setTimeout(r, 20));
92
+ }
93
+ await p.mouse.up();
94
+ await new Promise((r) => setTimeout(r, 300));
95
+ const posAfter = await readHostPos(p, sel);
96
+ const moved = JSON.stringify(posBefore) !== JSON.stringify(posAfter);
97
+ return { ok: moved, verdict: { verb: 'drag', selector: sel, before: posBefore, after: posAfter, moved } };
98
+ }
99
+ if (v === 'control') {
100
+ const expr = step.expr;
101
+ if (!expr) return { ok: false, verdict: { error: 'control needs a JS assertion expression' } };
102
+ const result = await p.evaluate('!!(' + expr + ')');
103
+ return { ok: result === true, verdict: { verb: 'control', expr, pass: result === true, result } };
104
+ }
105
+ if (v === 'persist') {
106
+ const key = step.key;
107
+ if (!key) return { ok: false, verdict: { error: 'persist needs a localStorage key' } };
108
+ const raw = await p.evaluate((k) => window.localStorage.getItem(k), key);
109
+ return { ok: true, verdict: { verb: 'persist', key, raw } };
110
+ }
111
+ return { ok: false, verdict: { error: 'unknown step verb ' + JSON.stringify(v) + ' — click | type | drag | control | persist' } };
112
+ } catch (e) {
113
+ return { ok: false, verdict: { error: String(e?.message ?? e) } };
114
+ }
115
+ }
116
+
117
+ if (verb === 'run') {
118
+ const file = argv[1];
119
+ if (!file) die('run needs a steps.json path');
120
+ let steps;
121
+ try {
122
+ steps = JSON.parse(readFileSync(file, 'utf8'));
123
+ } catch (e) {
124
+ die('run cannot read steps: ' + String(e?.message ?? e));
125
+ }
126
+ if (!Array.isArray(steps)) die('run steps must be a JSON array of {verb, …}');
127
+ const p = page();
128
+ const results = [];
129
+ let failedAt = null;
130
+ for (let i = 0; i < steps.length; i++) {
131
+ const step = steps[i];
132
+ const { ok, verdict } = await execStep(p, step);
133
+ results.push({ label: step.label ?? (step.verb + '#' + i), ok, ...verdict });
134
+ if (!ok) { failedAt = i; break; }
135
+ }
136
+ console.log(JSON.stringify({
137
+ verb: 'run', steps: steps.length, executed: results.length,
138
+ failedAt, ok: failedAt === null, results,
139
+ }));
140
+ process.exit(failedAt === null ? 0 : 1);
141
+ } else if (verb === 'click') {
39
142
  const sel = argv[1];
40
143
  if (!sel) die('click needs a selector');
41
- const p = page();
42
- const before = await p.evaluate((s) => !!document.querySelector(s), sel);
43
- await p.locator(sel).first().click(); // locator.click raises interception loudly (no force)
44
- console.log(JSON.stringify({ verb: 'click', selector: sel, before, after: true, moved: before !== true }));
144
+ const { verdict } = await execStep(page(), { verb: 'click', selector: sel });
145
+ if (verdict.error) die(verdict.error);
146
+ console.log(JSON.stringify(verdict));
45
147
  } else if (verb === 'type') {
46
148
  const sel = argv[1], text = argv[2];
47
149
  if (!sel || text === undefined) die('type needs <selector> <text>');
48
- const p = page();
49
- const loc = p.locator(sel).first();
50
- await loc.click();
51
- await p.keyboard.type(text);
52
- const after = await loc.inputValue().catch(() => undefined);
53
- console.log(JSON.stringify({ verb: 'type', selector: sel, before: '', after, moved: after === text }));
150
+ const { verdict } = await execStep(page(), { verb: 'type', selector: sel, text });
151
+ console.log(JSON.stringify(verdict));
54
152
  } else if (verb === 'drag') {
55
153
  const sel = argv[1], dx = Number(argv[2]), dy = Number(argv[3]);
56
154
  if (!sel || !Number.isFinite(dx) || !Number.isFinite(dy)) die('drag needs <selector> <dx> <dy>');
57
- const p = page();
58
- const posBefore = await p.evaluate((s) => {
59
- const el = document.querySelector(s);
60
- if (!el) return null;
61
- const host = el.closest('[style*="left"]') ?? el;
62
- return { x: host.style.left, y: host.style.top };
63
- }, sel);
64
- if (!posBefore) die('no element for ' + sel);
65
- const box = await p.locator(sel).first().boundingBox();
66
- if (!box) die('boundingBox failed for ' + sel);
67
- const sx = box.x + box.width / 2, sy = box.y + Math.min(box.height / 2, 8);
68
- await p.mouse.move(sx, sy);
69
- await p.mouse.down();
70
- for (let i = 1; i <= 10; i++) {
71
- await p.mouse.move(sx + (dx * i) / 10, sy + (dy * i) / 10);
72
- await new Promise((r) => setTimeout(r, 20));
73
- }
74
- await p.mouse.up();
75
- await new Promise((r) => setTimeout(r, 300));
76
- const posAfter = await p.evaluate((s) => {
77
- const el = document.querySelector(s);
78
- const host = el?.closest('[style*="left"]') ?? el;
79
- return { x: host.style.left, y: host.style.top };
80
- }, sel);
81
- const moved = JSON.stringify(posBefore) !== JSON.stringify(posAfter);
82
- console.log(JSON.stringify({ verb: 'drag', selector: sel, before: posBefore, after: posAfter, moved }));
155
+ const { verdict } = await execStep(page(), { verb: 'drag', selector: sel, dx, dy });
156
+ console.log(JSON.stringify(verdict));
83
157
  } else if (verb === 'control') {
84
158
  const expr = argv[1];
85
159
  if (!expr) die('control needs a JS assertion expression');
86
- const p = page();
87
- const result = await p.evaluate('!!(' + expr + ')');
88
- console.log(JSON.stringify({ verb: 'control', expr, pass: result === true, result }));
160
+ const { verdict } = await execStep(page(), { verb: 'control', expr });
161
+ console.log(JSON.stringify(verdict));
89
162
  } else if (verb === 'persist') {
90
163
  const key = argv[1];
91
164
  if (!key) die('persist needs a localStorage key');
92
- const p = page();
93
- const raw = await p.evaluate((k) => window.localStorage.getItem(k), key);
94
- console.log(JSON.stringify({ verb: 'persist', key, raw }));
165
+ const { verdict } = await execStep(page(), { verb: 'persist', key });
166
+ console.log(JSON.stringify(verdict));
95
167
  } else {
96
- die('unknown verb ' + JSON.stringify(verb) + ' — click | type | drag | control | persist');
168
+ die('unknown verb ' + JSON.stringify(verb) + ' — click | type | drag | control | persist | run');
97
169
  }
98
170
  process.exit(0);
package/README.md CHANGED
@@ -3,14 +3,14 @@
3
3
  </p>
4
4
 
5
5
  <p align="center">
6
- A different style opinionate <strong>DSH web client</strong> - aka <strong>DSI</strong>
6
+ <strong>DSI</strong> — A Different Style of Opinionated <strong>DSH web client</strong>
7
7
  <p>
8
8
 
9
9
  <p align="center">
10
10
  Screenshot: Sidebar, Workspace-explorer, Agent, Glass-browser, Subagent
11
11
  <p>
12
12
  <p align="center">
13
- <strong>Where you can see mulltiple agent / sub-agent plus+ non conversation panels:</strong>
13
+ <strong>A multi-agent workspace where you can see multiple agents and sub-agents working side by side, alongside non-conversational content, in resizable and zoomable multi-column panels:</strong>
14
14
  </p>
15
15
 
16
16
  - keys panel: **Agent**, **Sub-agent**, **Workspace-explorer**, **Glass-browser**, **Terminal**,
@@ -84,6 +84,12 @@ When it is up, your browser opens the page by itself (default `http://127.0.0.1:
84
84
  <img src="https://github.com/mitmplay/dsh-insight/blob/main/docs/images/dsi-insight-5.ws-explorer.png?raw=true"/>
85
85
  </details>
86
86
 
87
+ <details>
88
+ <summary><strong>Glass browser</strong></summary>
89
+ <p>The Glass browser is a real browser living inside DSI. While you work, agents build and change DSI itself — plugins, panels, settings — and instead of telling you "it's done", they can prove it: the work runs right there in the Glass panel, and you watch it live. If a plugin breaks, you see exactly what broke with your own eyes instead of trusting a green test report — the browser is the receipt.</p>
90
+ <img src="https://raw.githubusercontent.com/mitmplay/dsh-insight/refs/heads/main/docs/images/dsi-insight-3.glass-browser.png"/>
91
+ </details>
92
+
87
93
  ## Included skills for:
88
94
  - Coding agents: `/dsi-adr`, `/dsi-spec`, `/dsi-task`
89
95
  - Integration helper for [OpenViking](https://openviking.ai/): `/dsi-ov-setup`
@@ -164,4 +170,4 @@ DSI_PORT=5171 DSH_PORT=3081 GLASS_CHASSIS_URL=http://192.168.1.9:9525 pnpm dsi d
164
170
  [Apache-2.0](LICENSE) — Copyright © 2026 [Widi Harsojo](https://www.linkedin.com/in/wharsojo/)
165
171
  > OPEN TO WORK (SG_PR)
166
172
 
167
- **Your language.** The interface speaks English, Chinese, Indonesian & Spanish.
173
+ **Your language.** The interface speaks English, Chinese, Indonesian & Spanish.
@@ -45,6 +45,21 @@ import {
45
45
  writeOwnerMarker
46
46
  } from '../src/lib/server/browser/chassis-shared.ts';
47
47
 
48
+ /** @typedef {{ ok: false, error: string } | { ok: true, addr: string }} BindVerdict */
49
+ /** @typedef {{ bind: string | undefined, port: number | undefined }} ParsedArgs */
50
+ /** @typedef {{ profileDir: string, args: string[], headless: boolean, width: number, height: number }} LaunchOptions */
51
+ /** @typedef {{ pid: number | null, port: number, close: () => Promise<void> }} LaunchResult */
52
+ /** @typedef {{ id: string, ownerSessionId: string, debugPort: number, pid: number | null, profileDir: string, close: () => Promise<void> }} Glass */
53
+ /** @typedef {{
54
+ * bind?: string,
55
+ * port?: number,
56
+ * debugPort?: number,
57
+ * profileRoot?: string,
58
+ * launch?: (o: LaunchOptions) => Promise<LaunchResult>,
59
+ * portFor?: (preferred?: number) => Promise<number>
60
+ * }} CompanionOptions */
61
+ /** @typedef {{ server: import('node:http').Server, port: number, glasses: Map<string, Glass>, stop: () => Promise<void> }} Companion */
62
+
48
63
  /** The companion's disposable root — the same default the floor config
49
64
  * ships (insight-config). The companion runs on the host and answers to
50
65
  * the Borrowed Chrome posture, so deletes are GUARDED to this root. */
@@ -53,6 +68,7 @@ const PROFILE_ROOT = join(homedir(), '.dsi', 'browser-profiles');
53
68
  /** D4 — the bind verdict. Pure: `--bind` is REQUIRED and 0.0.0.0 (and the
54
69
  * IPv6 all-interfaces '::') are refused. The stamp already names the
55
70
  * exact interface; bind-all buys nothing and invites every device. */
71
+ /** @param {string | undefined} bind @returns {BindVerdict} */
56
72
  export function resolveBind(bind) {
57
73
  if (bind === undefined || bind === '') {
58
74
  return { ok: false, error: 'dsi-chassis: --bind <addr> is required (the private interface from the GLASS_CHASSIS_URL stamp); refusing to guess' };
@@ -64,7 +80,9 @@ export function resolveBind(bind) {
64
80
  }
65
81
 
66
82
  /** CLI arg parsing — pure, so the pins drive it directly. */
83
+ /** @param {string[]} argv @returns {ParsedArgs} */
67
84
  export function parseArgs(argv) {
85
+ /** @type {ParsedArgs} */
68
86
  const out = { bind: undefined, port: undefined };
69
87
  for (let i = 0; i < argv.length; i += 1) {
70
88
  const a = argv[i];
@@ -78,8 +96,10 @@ export function parseArgs(argv) {
78
96
 
79
97
  /** A free port for Chrome's debugging listener — net probe, no lsof
80
98
  * dependency, same behavior on macOS and Linux hosts. */
99
+ /** @param {number} [preferred] @returns {Promise<number>} */
81
100
  async function freeChassisPort(preferred) {
82
101
  const { createServer: probeServer } = await import('node:net');
102
+ /** @param {number} port @returns {Promise<boolean>} */
83
103
  const tryBind = (port) =>
84
104
  new Promise((resolve) => {
85
105
  const s = probeServer();
@@ -95,6 +115,7 @@ async function freeChassisPort(preferred) {
95
115
  /** The REAL launcher: headed Chromium on a disposable profile via the
96
116
  * repo's pinned playwright-core, channel 'chrome' with the bundled
97
117
  * chromium fallback — the same posture registry.open() births with. */
118
+ /** @param {LaunchOptions} opts @returns {Promise<LaunchResult>} */
98
119
  async function defaultLaunch({ profileDir, args, headless, width, height }) {
99
120
  const { chromium } = await import('playwright-core');
100
121
  const ignoreDefaultArgs = ['--enable-automation', '--mute-audio', '--hide-scrollbars'];
@@ -136,6 +157,7 @@ async function defaultLaunch({ profileDir, args, headless, width, height }) {
136
157
  * whole open/close/ownership/bridge contract without a real Chromium.
137
158
  * Returns { server, port, glasses, stop }.
138
159
  */
160
+ /** @param {CompanionOptions} [opts] @returns {Promise<Companion>} */
139
161
  export async function startChassisCompanion(opts = {}) {
140
162
  const bindVerdict = resolveBind(opts.bind);
141
163
  if (!bindVerdict.ok) throw new Error(bindVerdict.error);
@@ -150,7 +172,9 @@ export async function startChassisCompanion(opts = {}) {
150
172
  // The ownership registry lives IN this process: one conversation = one
151
173
  // glass, keyed by the requesting floor's ownerSessionId (karpathy edge
152
174
  // case: two floors stamping the same companion each carry their own id).
175
+ /** @type {Map<string, Glass>} */
153
176
  const glasses = new Map(); // id -> glass
177
+ /** @type {Map<string, string>} */
154
178
  const byOwner = new Map(); // ownerSessionId -> id
155
179
 
156
180
  const server = createServer(async (req, res) => {
@@ -165,6 +189,7 @@ export async function startChassisCompanion(opts = {}) {
165
189
  const preq = httpRequest({ host: '127.0.0.1', port: glass.debugPort, path: cdp[2] + url.search, method: req.method, headers }, (pres) => {
166
190
  const ctype = String(pres.headers['content-type'] ?? '');
167
191
  if (ctype.includes('json')) {
192
+ /** @type {Buffer[]} */
168
193
  const chunks = [];
169
194
  pres.on('data', (c) => chunks.push(c));
170
195
  pres.on('end', () => {
@@ -172,7 +197,7 @@ export async function startChassisCompanion(opts = {}) {
172
197
  // through THIS companion — the floor never needs to know
173
198
  // Chrome's loopback port (ADR fact 7, the Host hop).
174
199
  const body = Buffer.concat(chunks).toString('utf8')
175
- .split('ws://127.0.0.1:' + glass.debugPort).join('ws://' + (req.headers.host ?? bind + ':' + glass.boundPort) + '/cdp/' + glass.id);
200
+ .split('ws://127.0.0.1:' + glass.debugPort).join('ws://' + (req.headers.host ?? bind + ':' + glassPort(server)) + '/cdp/' + glass.id);
176
201
  const headers = { ...pres.headers };
177
202
  delete headers['transfer-encoding'];
178
203
  res.writeHead(pres.statusCode ?? 200, { ...headers, 'content-length': Buffer.byteLength(body) });
@@ -197,6 +222,7 @@ export async function startChassisCompanion(opts = {}) {
197
222
  return;
198
223
  }
199
224
  if (req.method === 'POST' && url.pathname === '/open') {
225
+ /** @type {Buffer[]} */
200
226
  const chunks = [];
201
227
  for await (const c of req) chunks.push(c);
202
228
  let body;
@@ -232,12 +258,15 @@ export async function startChassisCompanion(opts = {}) {
232
258
  '--autoplay-policy=no-user-gesture-required',
233
259
  '--window-size=' + (width + 6) + ',' + (height + 70)
234
260
  ];
235
- const born = await launch({ profileDir, args, headless: body.headless === true, width, height }).catch((e) => {
261
+ let born;
262
+ try {
263
+ born = await launch({ profileDir, args, headless: body.headless === true, width, height });
264
+ } catch (e) {
236
265
  // a failed birth must not leave a profile dir behind (and the
237
266
  // error rides the honest 500 to the floor's panel)
238
267
  try { if (profileDir.startsWith(profileRoot)) rmSync(profileDir, { recursive: true, force: true }); } catch { /* best-effort */ }
239
268
  throw e;
240
- });
269
+ }
241
270
  const glass = {
242
271
  id,
243
272
  ownerSessionId,
@@ -262,6 +291,7 @@ export async function startChassisCompanion(opts = {}) {
262
291
  return;
263
292
  }
264
293
  if (req.method === 'POST' && url.pathname === '/close') {
294
+ /** @type {Buffer[]} */
265
295
  const chunks = [];
266
296
  for await (const c of req) chunks.push(c);
267
297
  let body;
@@ -292,6 +322,7 @@ export async function startChassisCompanion(opts = {}) {
292
322
  }
293
323
  });
294
324
 
325
+ /** @param {Glass} glass @returns {Promise<void>} */
295
326
  function releaseGlass(glass) {
296
327
  glasses.delete(glass.id);
297
328
  if (byOwner.get(glass.ownerSessionId) === glass.id) byOwner.delete(glass.ownerSessionId);
@@ -303,6 +334,7 @@ export async function startChassisCompanion(opts = {}) {
303
334
  })();
304
335
  }
305
336
 
337
+ /** @param {import('node:http').IncomingMessage} req @param {import('node:net').Socket} socket @param {Buffer} head */
306
338
  const upgrade = (req, socket, head) => {
307
339
  const m = (req.url ?? '').match(/^\/cdp\/([^/]+)(\/devtools\/.*)$/);
308
340
  if (!m) { socket.destroy(); return; }
@@ -310,6 +342,7 @@ export async function startChassisCompanion(opts = {}) {
310
342
  if (!glass) { socket.destroy(); return; }
311
343
  // Raw pipe to Chrome's loopback port; the Host header is rewritten —
312
344
  // recent Chrome validates it (ADR fact 7) and the companion is the hop.
345
+ /** @type {string[]} */
313
346
  const headers = [];
314
347
  const raw = req.rawHeaders;
315
348
  for (let i = 0; i < raw.length; i += 2) {
@@ -328,13 +361,13 @@ export async function startChassisCompanion(opts = {}) {
328
361
  server.on('upgrade', upgrade);
329
362
 
330
363
  const wanted = opts.port ?? 9560;
331
- const boundPort = await new Promise((res, rej) => {
364
+ const boundPort = await (/** @type {Promise<number>} */ (new Promise((res, rej) => {
332
365
  server.once('error', rej);
333
366
  server.listen(wanted, bind, () => {
334
367
  const a = server.address();
335
368
  res(typeof a === 'object' && a ? a.port : wanted);
336
369
  });
337
- });
370
+ })));
338
371
  return {
339
372
  server,
340
373
  port: boundPort,
@@ -342,11 +375,12 @@ export async function startChassisCompanion(opts = {}) {
342
375
  stop: async () => {
343
376
  server.removeAllListeners('upgrade');
344
377
  for (const g of [...glasses.values()]) await releaseGlass(g);
345
- await new Promise((res) => server.close(() => res()));
378
+ await /** @type {Promise<void>} */ (new Promise((res) => server.close(() => res())));
346
379
  }
347
380
  };
348
381
  }
349
382
 
383
+ /** @param {import('node:http').Server} server @returns {number} */
350
384
  function glassPort(server) {
351
385
  const a = server.address();
352
386
  return typeof a === 'object' && a ? a.port : 0;
@@ -0,0 +1,2 @@
1
+ /*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
2
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-yellow-200:oklch(94.5% .129 101.54);--color-green-300:oklch(87.1% .15 154.449);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-emerald-500:oklch(69.6% .17 162.48);--color-sky-400:oklch(74.6% .16 232.661);--color-blue-100:oklch(93.2% .032 255.585);--color-blue-900:oklch(37.9% .146 265.522);--color-slate-100:oklch(96.8% .007 247.896);--color-slate-200:oklch(92.9% .013 255.508);--color-slate-300:oklch(86.9% .022 252.894);--color-slate-400:oklch(70.4% .04 256.788);--color-slate-500:oklch(55.4% .046 257.417);--color-slate-600:oklch(44.6% .043 257.281);--color-slate-700:oklch(37.2% .044 257.287);--color-slate-800:oklch(27.9% .041 260.031);--color-slate-900:oklch(20.8% .042 265.755);--color-slate-950:oklch(12.9% .042 264.695);--color-zinc-100:oklch(96.7% .001 286.375);--color-zinc-200:oklch(92% .004 286.32);--color-zinc-300:oklch(87.1% .006 286.286);--color-zinc-400:oklch(70.5% .015 286.067);--color-zinc-500:oklch(55.2% .016 285.938);--color-zinc-600:oklch(44.2% .017 285.786);--color-zinc-700:oklch(37% .013 285.805);--color-zinc-800:oklch(27.4% .006 286.033);--color-zinc-900:oklch(21% .006 285.885);--color-neutral-100:oklch(97% 0 none);--color-neutral-200:oklch(92.2% 0 none);--color-neutral-400:oklch(70.8% 0 none);--color-neutral-700:oklch(37.1% 0 none);--color-neutral-800:oklch(26.9% 0 none);--color-neutral-900:oklch(20.5% 0 none);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-xl:36rem;--container-2xl:42rem;--container-3xl:48rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-5xl:3rem;--text-5xl--line-height:1;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-wide:.025em;--tracking-wider:.05em;--leading-tight:1.25;--leading-normal:1.5;--leading-relaxed:1.625;--radius-sm:.25rem;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--ease-in-out:cubic-bezier(.4, 0, .2, 1);--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-surface:#f8f9fa;--color-surface-alt:#f1f3f5;--color-surface-hover:#e9ecef;--color-surface-border:#dee2e6;--color-surface-elevated:#fff;--color-subagent-tint-1:beige;--color-subagent-tint-2:#e9e3c9;--color-subagent-tint-3:#ddd3b0;--color-text-primary:#212529;--color-text-secondary:#6c757d;--color-text-muted:#adb5bd;--color-accent-blue:#3b82f6;--color-accent-purple:#8b5cf6;--color-accent-purple-soft:#9f88fb;--color-accent-purple-ink:#2e1065;--color-accent-emerald-deep:#15803d;--color-accent-amber:#f59e0b;--color-accent-rose:#f43f5e;--color-accent-cyan:#06b6d4;--color-status-pass:#10b981;--color-status-fail:#ef4444;--color-status-pending:#f59e0b;--color-status-fail-ink:#fff;--color-tree-repo:#ff4500;--color-tree-child:#d2691e;--color-tree-amber:#f7ad31;--color-accent-deep:#7c3aed;--color-success-ink:#1a7f37;--color-success-soft:#27ae60;--color-green-verify:#16a34a;--color-accent-orange:#e67e22;--color-accent-amber-ink:#d97706;--color-accent-amber-ink-deep:#b45309;--color-danger-madrid:#e74c3c;--color-danger-github:#cf222e;--color-danger-editor-surface:#45161c;--color-danger-editor-ink:#ffb4bb;--color-doc-child:maroon;--color-navy-focus:#1e3a8a;--color-header-wash:#fdf5e6;--color-slate-neutral:#52606d;--color-danger-wash:#fef2f2;--color-danger-wash-border:#fee2e2;--color-danger-wash-ink:#991b1b;--color-ws-violet:#9400d3;--color-ws-green:#00a802;--color-ws-blue:#06c}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}:root{--si-run:#b91c1c;--color-surface-primary:var(--color-surface-elevated);--color-surface-secondary:var(--color-surface-alt);--color-border:var(--color-surface-border);--color-text:var(--color-text-primary);--color-bg:var(--color-surface)}svg{color:var(--color-accent-purple)}}@layer components;@layer utilities{.\@container{container-type:inline-size}.pointer-events-auto{pointer-events:auto}.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.invisible{visibility:hidden}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-0{inset:0}.-top-3{top:calc(var(--spacing) * -3)}.top-0{top:0}.top-1{top:var(--spacing)}.top-1\.5{top:calc(var(--spacing) * 1.5)}.top-1\/2{top:50%}.top-5{top:calc(var(--spacing) * 5)}.top-8{top:calc(var(--spacing) * 8)}.top-full{top:100%}.-right-3{right:calc(var(--spacing) * -3)}.right-0{right:0}.right-1{right:var(--spacing)}.right-1\.5{right:calc(var(--spacing) * 1.5)}.right-2{right:calc(var(--spacing) * 2)}.right-3{right:calc(var(--spacing) * 3)}.right-5{right:calc(var(--spacing) * 5)}.right-full{right:100%}.bottom-0{bottom:0}.bottom-0\.5{bottom:calc(var(--spacing) * .5)}.bottom-1{bottom:var(--spacing)}.bottom-1\/2{bottom:50%}.bottom-\[50vh\]{bottom:50vh}.bottom-full{bottom:100%}.left-0{left:0}.left-1\/2{left:50%}.left-3{left:calc(var(--spacing) * 3)}.left-7{left:calc(var(--spacing) * 7)}.left-full{left:100%}.isolate{isolation:isolate}.z-10{z-index:10}.z-30{z-index:30}.z-40{z-index:40}.z-41{z-index:41}.z-50{z-index:50}.z-1000,.z-\[1000\]{z-index:1000}.z-auto{z-index:auto}.order-0{order:0}.order-2{order:2}.row-1{grid-row:1}.\!container{width:100%!important}@media (width>=40rem){.\!container{max-width:40rem!important}}@media (width>=48rem){.\!container{max-width:48rem!important}}@media (width>=64rem){.\!container{max-width:64rem!important}}@media (width>=80rem){.\!container{max-width:80rem!important}}@media (width>=96rem){.\!container{max-width:96rem!important}}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.m-0{margin:0}.-mx-1{margin-inline:calc(var(--spacing) * -1)}.mx-0\.5{margin-inline:calc(var(--spacing) * .5)}.mx-1{margin-inline:var(--spacing)}.mx-auto{margin-inline:auto}.my-0\.5{margin-block:calc(var(--spacing) * .5)}.my-1{margin-block:var(--spacing)}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:var(--spacing)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-px{margin-top:1px}.mr-1\.5{margin-right:calc(var(--spacing) * 1.5)}.mr-2{margin-right:calc(var(--spacing) * 2)}.mb-0\.5{margin-bottom:calc(var(--spacing) * .5)}.mb-1{margin-bottom:var(--spacing)}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.ml-1{margin-left:var(--spacing)}.ml-2{margin-left:calc(var(--spacing) * 2)}.ml-\[-2px\]{margin-left:-2px}.ml-auto{margin-left:auto}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.size-1\.5{width:calc(var(--spacing) * 1.5);height:calc(var(--spacing) * 1.5)}.h-1{height:var(--spacing)}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-2{height:calc(var(--spacing) * 2)}.h-3\.5{height:calc(var(--spacing) * 3.5)}.h-4{height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-7{height:calc(var(--spacing) * 7)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-16{height:calc(var(--spacing) * 16)}.h-\[18px\]{height:18px}.h-\[22px\]{height:22px}.h-\[50px\]{height:50px}.h-\[62px\]{height:62px}.h-dvh{height:100dvh}.h-full{height:100%}.max-h-40{max-height:calc(var(--spacing) * 40)}.max-h-48{max-height:calc(var(--spacing) * 48)}.max-h-72{max-height:calc(var(--spacing) * 72)}.max-h-80{max-height:calc(var(--spacing) * 80)}.max-h-\[28rem\]{max-height:28rem}.max-h-\[30rem\]{max-height:30rem}.max-h-\[60vh\]{max-height:60vh}.max-h-\[500px\]{max-height:500px}.max-h-\[calc\(100vh-80px\)\]{max-height:calc(100vh - 80px)}.min-h-0{min-height:0}.min-h-72{min-height:calc(var(--spacing) * 72)}.min-h-80{min-height:calc(var(--spacing) * 80)}.min-h-\[2\.75rem\]{min-height:2.75rem}.w-1{width:var(--spacing)}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-2{width:calc(var(--spacing) * 2)}.w-3{width:calc(var(--spacing) * 3)}.w-3\.5{width:calc(var(--spacing) * 3.5)}.w-4{width:calc(var(--spacing) * 4)}.w-5{width:calc(var(--spacing) * 5)}.w-6{width:calc(var(--spacing) * 6)}.w-7{width:calc(var(--spacing) * 7)}.w-8{width:calc(var(--spacing) * 8)}.w-9{width:calc(var(--spacing) * 9)}.w-14{width:calc(var(--spacing) * 14)}.w-15{width:calc(var(--spacing) * 15)}.w-16{width:calc(var(--spacing) * 16)}.w-20{width:calc(var(--spacing) * 20)}.w-24{width:calc(var(--spacing) * 24)}.w-36{width:calc(var(--spacing) * 36)}.w-64{width:calc(var(--spacing) * 64)}.w-72{width:calc(var(--spacing) * 72)}.w-96{width:calc(var(--spacing) * 96)}.w-\[18px\]{width:18px}.w-\[22px\]{width:22px}.w-\[62px\]{width:62px}.w-\[200px\]{width:200px}.w-fit{width:fit-content}.w-full{width:100%}.w-max{width:max-content}.max-w-2xl{max-width:var(--container-2xl)}.max-w-3xl{max-width:var(--container-3xl)}.max-w-56{max-width:calc(var(--spacing) * 56)}.max-w-72{max-width:calc(var(--spacing) * 72)}.max-w-\[16rem\]{max-width:16rem}.max-w-\[80\%\]{max-width:80%}.max-w-\[80vw\]{max-width:80vw}.max-w-\[85\%\]{max-width:85%}.max-w-\[min\(100\%\,1600px\)\]{max-width:min(100%,1600px)}.max-w-full{max-width:100%}.max-w-sm{max-width:var(--container-sm)}.max-w-xl{max-width:var(--container-xl)}.min-w-0{min-width:0}.min-w-5{min-width:calc(var(--spacing) * 5)}.min-w-44{min-width:calc(var(--spacing) * 44)}.min-w-72{min-width:calc(var(--spacing) * 72)}.flex-1{flex:1}.flex-none{flex:none}.flex-shrink,.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.border-collapse{border-collapse:collapse}.origin-top-left{transform-origin:0 0}.-translate-x-1\/2{--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.rotate-90{rotate:90deg}.rotate-180{rotate:180deg}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.zoom-1{zoom:1%}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-move{cursor:move}.cursor-pointer{cursor:pointer}.cursor-zoom-in{cursor:zoom-in}.resize{resize:both}.resize-none{resize:none}.scrollbar-none{scrollbar-width:none}.list-none{list-style-type:none}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-\[auto_1fr\]{grid-template-columns:auto 1fr}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.place-items-center{place-items:center}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.items-stretch{align-items:stretch}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}:where(.space-y-0\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * .5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * .5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1.5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1.5) * calc(1 - var(--tw-space-y-reverse)))}.gap-x-0\.5{column-gap:calc(var(--spacing) * .5)}.gap-x-1{column-gap:var(--spacing)}.gap-x-4{column-gap:calc(var(--spacing) * 4)}.gap-y-0\.5{row-gap:calc(var(--spacing) * .5)}.self-start{align-self:flex-start}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-x-clip{overflow-x:clip}.overflow-y-auto{overflow-y:auto}.overflow-y-hidden{overflow-y:hidden}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-\[2px\]{border-radius:2px}.rounded-\[16px\]{border-radius:16px}.rounded-full{border-radius:2147483647px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-t{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.rounded-t-lg{border-top-left-radius:var(--radius-lg);border-top-right-radius:var(--radius-lg)}.rounded-t-md{border-top-left-radius:var(--radius-md);border-top-right-radius:var(--radius-md)}.rounded-l-sm{border-top-left-radius:var(--radius-sm);border-bottom-left-radius:var(--radius-sm)}.rounded-r-sm{border-top-right-radius:var(--radius-sm);border-bottom-right-radius:var(--radius-sm)}.rounded-br-sm{border-bottom-right-radius:var(--radius-sm)}.rounded-bl-sm{border-bottom-left-radius:var(--radius-sm)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-0{border-bottom-style:var(--tw-border-style);border-bottom-width:0}.border-l-0{border-left-style:var(--tw-border-style);border-left-width:0}.border-none{--tw-border-style:none;border-style:none}.border-\[var\(--color-accent-deep\)\]{border-color:var(--color-accent-deep)}.border-\[var\(--color-accent-deep\)\]\/30{border-color:#7c3aed4d}@supports (color:color-mix(in lab, red, red)){.border-\[var\(--color-accent-deep\)\]\/30{border-color:color-mix(in oklab, var(--color-accent-deep) 30%, transparent)}}.border-\[var\(--color-surface-border\)\]{border-color:var(--color-surface-border)}.border-accent-blue{border-color:var(--color-accent-blue)}.border-accent-blue\/20{border-color:#3b82f633}@supports (color:color-mix(in lab, red, red)){.border-accent-blue\/20{border-color:color-mix(in oklab, var(--color-accent-blue) 20%, transparent)}}.border-accent-blue\/30{border-color:#3b82f64d}@supports (color:color-mix(in lab, red, red)){.border-accent-blue\/30{border-color:color-mix(in oklab, var(--color-accent-blue) 30%, transparent)}}.border-accent-purple\/30{border-color:#8b5cf64d}@supports (color:color-mix(in lab, red, red)){.border-accent-purple\/30{border-color:color-mix(in oklab, var(--color-accent-purple) 30%, transparent)}}.border-black\/10{border-color:#0000001a}@supports (color:color-mix(in lab, red, red)){.border-black\/10{border-color:color-mix(in oklab, var(--color-black) 10%, transparent)}}.border-black\/15{border-color:#00000026}@supports (color:color-mix(in lab, red, red)){.border-black\/15{border-color:color-mix(in oklab, var(--color-black) 15%, transparent)}}.border-danger-wash-border{border-color:var(--color-danger-wash-border)}.border-slate-600{border-color:var(--color-slate-600)}.border-slate-700\/50{border-color:#31415880}@supports (color:color-mix(in lab, red, red)){.border-slate-700\/50{border-color:color-mix(in oklab, var(--color-slate-700) 50%, transparent)}}.border-slate-800{border-color:var(--color-slate-800)}.border-status-fail\/30{border-color:#ef44444d}@supports (color:color-mix(in lab, red, red)){.border-status-fail\/30{border-color:color-mix(in oklab, var(--color-status-fail) 30%, transparent)}}.border-status-pass{border-color:var(--color-status-pass)}.border-status-pass\/30{border-color:#10b9814d}@supports (color:color-mix(in lab, red, red)){.border-status-pass\/30{border-color:color-mix(in oklab, var(--color-status-pass) 30%, transparent)}}.border-status-pending\/30{border-color:#f59e0b4d}@supports (color:color-mix(in lab, red, red)){.border-status-pending\/30{border-color:color-mix(in oklab, var(--color-status-pending) 30%, transparent)}}.border-surface-border{border-color:var(--color-surface-border)}.border-surface-border\/30{border-color:#dee2e64d}@supports (color:color-mix(in lab, red, red)){.border-surface-border\/30{border-color:color-mix(in oklab, var(--color-surface-border) 30%, transparent)}}.border-surface-border\/40{border-color:#dee2e666}@supports (color:color-mix(in lab, red, red)){.border-surface-border\/40{border-color:color-mix(in oklab, var(--color-surface-border) 40%, transparent)}}.border-surface-border\/50{border-color:#dee2e680}@supports (color:color-mix(in lab, red, red)){.border-surface-border\/50{border-color:color-mix(in oklab, var(--color-surface-border) 50%, transparent)}}.border-text-muted\/15{border-color:#adb5bd26}@supports (color:color-mix(in lab, red, red)){.border-text-muted\/15{border-color:color-mix(in oklab, var(--color-text-muted) 15%, transparent)}}.border-text-muted\/20{border-color:#adb5bd33}@supports (color:color-mix(in lab, red, red)){.border-text-muted\/20{border-color:color-mix(in oklab, var(--color-text-muted) 20%, transparent)}}.border-transparent{border-color:#0000}.border-zinc-300{border-color:var(--color-zinc-300)}.border-zinc-700{border-color:var(--color-zinc-700)}.bg-\[var\(--color-accent-deep\)\]{background-color:var(--color-accent-deep)}.bg-\[var\(--color-accent-deep\)\]\/10{background-color:#7c3aed1a}@supports (color:color-mix(in lab, red, red)){.bg-\[var\(--color-accent-deep\)\]\/10{background-color:color-mix(in oklab, var(--color-accent-deep) 10%, transparent)}}.bg-\[var\(--color-subagent-tint-1\)\]{background-color:var(--color-subagent-tint-1)}.bg-\[var\(--color-subagent-tint-2\)\]{background-color:var(--color-subagent-tint-2)}.bg-\[var\(--color-subagent-tint-3\)\]{background-color:var(--color-subagent-tint-3)}.bg-\[var\(--color-surface-elevated\)\]{background-color:var(--color-surface-elevated)}.bg-accent-blue{background-color:var(--color-accent-blue)}.bg-accent-blue\/10{background-color:#3b82f61a}@supports (color:color-mix(in lab, red, red)){.bg-accent-blue\/10{background-color:color-mix(in oklab, var(--color-accent-blue) 10%, transparent)}}.bg-accent-blue\/15{background-color:#3b82f626}@supports (color:color-mix(in lab, red, red)){.bg-accent-blue\/15{background-color:color-mix(in oklab, var(--color-accent-blue) 15%, transparent)}}.bg-accent-blue\/20{background-color:#3b82f633}@supports (color:color-mix(in lab, red, red)){.bg-accent-blue\/20{background-color:color-mix(in oklab, var(--color-accent-blue) 20%, transparent)}}.bg-accent-blue\/30{background-color:#3b82f64d}@supports (color:color-mix(in lab, red, red)){.bg-accent-blue\/30{background-color:color-mix(in oklab, var(--color-accent-blue) 30%, transparent)}}.bg-accent-cyan\/10{background-color:#06b6d41a}@supports (color:color-mix(in lab, red, red)){.bg-accent-cyan\/10{background-color:color-mix(in oklab, var(--color-accent-cyan) 10%, transparent)}}.bg-accent-emerald-deep{background-color:var(--color-accent-emerald-deep)}.bg-accent-purple-ink{background-color:var(--color-accent-purple-ink)}.bg-accent-purple-soft{background-color:var(--color-accent-purple-soft)}.bg-accent-purple\/15{background-color:#8b5cf626}@supports (color:color-mix(in lab, red, red)){.bg-accent-purple\/15{background-color:color-mix(in oklab, var(--color-accent-purple) 15%, transparent)}}.bg-accent-purple\/20{background-color:#8b5cf633}@supports (color:color-mix(in lab, red, red)){.bg-accent-purple\/20{background-color:color-mix(in oklab, var(--color-accent-purple) 20%, transparent)}}.bg-amber-400{background-color:var(--color-amber-400)}.bg-black\/5{background-color:#0000000d}@supports (color:color-mix(in lab, red, red)){.bg-black\/5{background-color:color-mix(in oklab, var(--color-black) 5%, transparent)}}.bg-black\/40{background-color:#0006}@supports (color:color-mix(in lab, red, red)){.bg-black\/40{background-color:color-mix(in oklab, var(--color-black) 40%, transparent)}}.bg-black\/60{background-color:#0009}@supports (color:color-mix(in lab, red, red)){.bg-black\/60{background-color:color-mix(in oklab, var(--color-black) 60%, transparent)}}.bg-blue-100{background-color:var(--color-blue-100)}.bg-danger-wash{background-color:var(--color-danger-wash)}.bg-emerald-500{background-color:var(--color-emerald-500)}.bg-green-300{background-color:var(--color-green-300)}.bg-green-500{background-color:var(--color-green-500)}.bg-header-wash{background-color:var(--color-header-wash)}.bg-neutral-100{background-color:var(--color-neutral-100)}.bg-neutral-200{background-color:var(--color-neutral-200)}.bg-red-500{background-color:var(--color-red-500)}.bg-sky-400{background-color:var(--color-sky-400)}.bg-slate-700{background-color:var(--color-slate-700)}.bg-slate-800{background-color:var(--color-slate-800)}.bg-slate-800\/60{background-color:#1d293d99}@supports (color:color-mix(in lab, red, red)){.bg-slate-800\/60{background-color:color-mix(in oklab, var(--color-slate-800) 60%, transparent)}}.bg-slate-800\/90{background-color:#1d293de6}@supports (color:color-mix(in lab, red, red)){.bg-slate-800\/90{background-color:color-mix(in oklab, var(--color-slate-800) 90%, transparent)}}.bg-slate-900{background-color:var(--color-slate-900)}.bg-slate-900\/40{background-color:#0f172b66}@supports (color:color-mix(in lab, red, red)){.bg-slate-900\/40{background-color:color-mix(in oklab, var(--color-slate-900) 40%, transparent)}}.bg-slate-950{background-color:var(--color-slate-950)}.bg-status-fail{background-color:var(--color-status-fail)}.bg-status-fail\/10{background-color:#ef44441a}@supports (color:color-mix(in lab, red, red)){.bg-status-fail\/10{background-color:color-mix(in oklab, var(--color-status-fail) 10%, transparent)}}.bg-status-pass{background-color:var(--color-status-pass)}.bg-status-pass\/10{background-color:#10b9811a}@supports (color:color-mix(in lab, red, red)){.bg-status-pass\/10{background-color:color-mix(in oklab, var(--color-status-pass) 10%, transparent)}}.bg-status-pass\/100{background-color:var(--color-status-pass)}.bg-status-pending{background-color:var(--color-status-pending)}.bg-status-pending\/10{background-color:#f59e0b1a}@supports (color:color-mix(in lab, red, red)){.bg-status-pending\/10{background-color:color-mix(in oklab, var(--color-status-pending) 10%, transparent)}}.bg-status-pending\/100{background-color:var(--color-status-pending)}.bg-surface{background-color:var(--color-surface)}.bg-surface-alt{background-color:var(--color-surface-alt)}.bg-surface-border{background-color:var(--color-surface-border)}.bg-surface-elevated{background-color:var(--color-surface-elevated)}.bg-surface\/60{background-color:#f8f9fa99}@supports (color:color-mix(in lab, red, red)){.bg-surface\/60{background-color:color-mix(in oklab, var(--color-surface) 60%, transparent)}}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.bg-white\/95{background-color:#fffffff2}@supports (color:color-mix(in lab, red, red)){.bg-white\/95{background-color:color-mix(in oklab, var(--color-white) 95%, transparent)}}.bg-yellow-200{background-color:var(--color-yellow-200)}.bg-zinc-400{background-color:var(--color-zinc-400)}.bg-\[linear-gradient\(90deg\,color-mix\(in_srgb\,var\(--color-status-pass\)_18\%\,var\(--color-surface\)\)\,var\(--color-header-wash\)_65\%\,var\(--color-surface\)\)\]{background-image:linear-gradient(90deg,#ceede4,var(--color-header-wash) 65%,var(--color-surface))}@supports (color:color-mix(in lab, red, red)){.bg-\[linear-gradient\(90deg\,color-mix\(in_srgb\,var\(--color-status-pass\)_18\%\,var\(--color-surface\)\)\,var\(--color-header-wash\)_65\%\,var\(--color-surface\)\)\]{background-image:linear-gradient(90deg,color-mix(in srgb,var(--color-status-pass) 18%,var(--color-surface)),var(--color-header-wash) 65%,var(--color-surface))}}.object-contain{object-fit:contain}.object-cover{object-fit:cover}.\[padding\:0_10px\]{padding:0 10px}.p-0{padding:0}.p-0\.5{padding:calc(var(--spacing) * .5)}.p-1{padding:var(--spacing)}.p-1\.5{padding:calc(var(--spacing) * 1.5)}.p-2{padding:calc(var(--spacing) * 2)}.p-2\.5{padding:calc(var(--spacing) * 2.5)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-10{padding:calc(var(--spacing) * 10)}.px-0\.5{padding-inline:calc(var(--spacing) * .5)}.px-1{padding-inline:var(--spacing)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-16{padding-block:calc(var(--spacing) * 16)}.py-\[0\.1rem\]{padding-block:.1rem}.py-px{padding-block:1px}.pt-1\.5{padding-top:calc(var(--spacing) * 1.5)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-2\.5{padding-top:calc(var(--spacing) * 2.5)}.pr-2{padding-right:calc(var(--spacing) * 2)}.pr-4{padding-right:calc(var(--spacing) * 4)}.pr-7{padding-right:calc(var(--spacing) * 7)}.pr-8{padding-right:calc(var(--spacing) * 8)}.pb-0\.5{padding-bottom:calc(var(--spacing) * .5)}.pb-1{padding-bottom:var(--spacing)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pl-1{padding-left:var(--spacing)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.align-bottom{vertical-align:bottom}.align-middle{vertical-align:middle}.align-top{vertical-align:top}.font-mono{font-family:var(--font-mono)}.text-5xl{font-size:var(--text-5xl);line-height:var(--tw-leading,var(--text-5xl--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[0\.8rem\]{font-size:.8rem}.text-\[0\.6875rem\]{font-size:.6875rem}.text-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[12px\]{font-size:12px}.text-\[18px\]{font-size:18px}.leading-4{--tw-leading:calc(var(--spacing) * 4);line-height:calc(var(--spacing) * 4)}.leading-none{--tw-leading:1;line-height:1}.leading-normal{--tw-leading:var(--leading-normal);line-height:var(--leading-normal)}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-\[color\:var\(--color-accent-blue\)\]{color:var(--color-accent-blue)}.text-\[color\:var\(--color-accent-purple\)\]{color:var(--color-accent-purple)}.text-\[color\:var\(--color-text-secondary\,\#6c757d\)\]{color:var(--color-text-secondary,#6c757d)}.text-\[var\(--color-accent-deep\)\]{color:var(--color-accent-deep)}.text-\[var\(--color-accent-purple\)\]{color:var(--color-accent-purple)}.text-\[var\(--color-text-primary\)\]{color:var(--color-text-primary)}.text-\[var\(--color-text-secondary\)\]{color:var(--color-text-secondary)}.text-accent-blue{color:var(--color-accent-blue)}.text-accent-purple{color:var(--color-accent-purple)}.text-accent-purple-ink{color:var(--color-accent-purple-ink)}.text-accent-purple\/80{color:#8b5cf6cc}@supports (color:color-mix(in lab, red, red)){.text-accent-purple\/80{color:color-mix(in oklab, var(--color-accent-purple) 80%, transparent)}}.text-amber-400{color:var(--color-amber-400)}.text-amber-500{color:var(--color-amber-500)}.text-blue-900{color:var(--color-blue-900)}.text-green-400{color:var(--color-green-400)}.text-green-500{color:var(--color-green-500)}.text-neutral-400{color:var(--color-neutral-400)}.text-neutral-700{color:var(--color-neutral-700)}.text-red-400{color:var(--color-red-400)}.text-red-500{color:var(--color-red-500)}.text-slate-100{color:var(--color-slate-100)}.text-slate-200{color:var(--color-slate-200)}.text-slate-300{color:var(--color-slate-300)}.text-slate-400{color:var(--color-slate-400)}.text-slate-500{color:var(--color-slate-500)}.text-status-fail{color:var(--color-status-fail)}.text-status-fail-ink{color:var(--color-status-fail-ink)}.text-status-pass{color:var(--color-status-pass)}.text-status-pending{color:var(--color-status-pending)}.text-status-pending\/80{color:#f59e0bcc}@supports (color:color-mix(in lab, red, red)){.text-status-pending\/80{color:color-mix(in oklab, var(--color-status-pending) 80%, transparent)}}.text-surface{color:var(--color-surface)}.text-text-muted{color:var(--color-text-muted)}.text-text-muted\/60{color:#adb5bd99}@supports (color:color-mix(in lab, red, red)){.text-text-muted\/60{color:color-mix(in oklab, var(--color-text-muted) 60%, transparent)}}.text-text-primary{color:var(--color-text-primary)}.text-text-secondary{color:var(--color-text-secondary)}.text-white{color:var(--color-white)}.text-zinc-500{color:var(--color-zinc-500)}.text-zinc-600{color:var(--color-zinc-600)}.text-zinc-800{color:var(--color-zinc-800)}.text-zinc-900{color:var(--color-zinc-900)}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.italic{font-style:italic}.ordinal{--tw-ordinal:ordinal;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.line-through{text-decoration-line:line-through}.underline{text-decoration-line:underline}.decoration-surface-border{-webkit-text-decoration-color:var(--color-surface-border);-webkit-text-decoration-color:var(--color-surface-border);-webkit-text-decoration-color:var(--color-surface-border);text-decoration-color:var(--color-surface-border)}.underline-offset-2{text-underline-offset:2px}.accent-\[var\(--color-accent-purple\)\]{accent-color:var(--color-accent-purple)}.opacity-0{opacity:0}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-80{opacity:.8}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a), 0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring,.ring-1{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-accent-purple-ink\/30{--tw-ring-color:#2e10654d}@supports (color:color-mix(in lab, red, red)){.ring-accent-purple-ink\/30{--tw-ring-color:color-mix(in oklab, var(--color-accent-purple-ink) 30%, transparent)}}.ring-danger-wash-border{--tw-ring-color:var(--color-danger-wash-border)}.ring-status-fail\/30{--tw-ring-color:#ef44444d}@supports (color:color-mix(in lab, red, red)){.ring-status-fail\/30{--tw-ring-color:color-mix(in oklab, var(--color-status-fail) 30%, transparent)}}.ring-status-pending\/30{--tw-ring-color:#f59e0b4d}@supports (color:color-mix(in lab, red, red)){.ring-status-pending\/30{--tw-ring-color:color-mix(in oklab, var(--color-status-pending) 30%, transparent)}}.ring-surface-border{--tw-ring-color:var(--color-surface-border)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.grayscale{--tw-grayscale:grayscale(100%);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-blur{--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[background-color\,transform\]{transition-property:background-color,transform;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[width\]{transition-property:width;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-100{--tw-duration:.1s;transition-duration:.1s}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.ease-linear{--tw-ease:linear;transition-timing-function:linear}.outline-none{--tw-outline-style:none;outline-style:none}.select-all{-webkit-user-select:all;user-select:all}.select-none{-webkit-user-select:none;user-select:none}@media (hover:hover){.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}.group-hover\/bubble\:text-\[var\(--color-accent-deep\)\]:is(:where(.group\/bubble):hover *){color:var(--color-accent-deep)}.group-hover\/bubble\:opacity-100:is(:where(.group\/bubble):hover *),.group-hover\/code\:opacity-100:is(:where(.group\/code):hover *),.group-hover\/diagram\:opacity-100:is(:where(.group\/diagram):hover *),.group-hover\/featurespec\:opacity-100:is(:where(.group\/featurespec):hover *),.group-hover\/markdown\:opacity-100:is(:where(.group\/markdown):hover *){opacity:1}.group-hover\/new\:block:is(:where(.group\/new):hover *){display:block}.group-hover\/new\:hidden:is(:where(.group\/new):hover *){display:none}.group-hover\/reasoning\:opacity-100:is(:where(.group\/reasoning):hover *),.group-hover\/tab\:opacity-100:is(:where(.group\/tab):hover *),.group-hover\/table\:opacity-100:is(:where(.group\/table):hover *),.group-hover\/terminal\:opacity-100:is(:where(.group\/terminal):hover *){opacity:1}}.placeholder\:text-text-muted::placeholder{color:var(--color-text-muted)}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}@media (hover:hover){.hover\:scale-105:hover{--tw-scale-x:105%;--tw-scale-y:105%;--tw-scale-z:105%;scale:var(--tw-scale-x) var(--tw-scale-y)}.hover\:border-surface-border:hover{border-color:var(--color-surface-border)}.hover\:bg-\[color-mix\(in_srgb\,var\(--color-accent-emerald-deep\)_85\%\,black\)\]:hover{background-color:#126d34}@supports (color:color-mix(in lab, red, red)){.hover\:bg-\[color-mix\(in_srgb\,var\(--color-accent-emerald-deep\)_85\%\,black\)\]:hover{background-color:color-mix(in srgb,var(--color-accent-emerald-deep) 85%,black)}}.hover\:bg-\[var\(--color-accent-deep\)\]\/20:hover{background-color:#7c3aed33}@supports (color:color-mix(in lab, red, red)){.hover\:bg-\[var\(--color-accent-deep\)\]\/20:hover{background-color:color-mix(in oklab, var(--color-accent-deep) 20%, transparent)}}.hover\:bg-accent-blue:hover{background-color:var(--color-accent-blue)}.hover\:bg-accent-blue\/20:hover{background-color:#3b82f633}@supports (color:color-mix(in lab, red, red)){.hover\:bg-accent-blue\/20:hover{background-color:color-mix(in oklab, var(--color-accent-blue) 20%, transparent)}}.hover\:bg-accent-purple\/5:hover{background-color:#8b5cf60d}@supports (color:color-mix(in lab, red, red)){.hover\:bg-accent-purple\/5:hover{background-color:color-mix(in oklab, var(--color-accent-purple) 5%, transparent)}}.hover\:bg-danger-wash-border:hover{background-color:var(--color-danger-wash-border)}.hover\:bg-red-500:hover{background-color:var(--color-red-500)}.hover\:bg-slate-600:hover{background-color:var(--color-slate-600)}.hover\:bg-slate-700:hover{background-color:var(--color-slate-700)}.hover\:bg-slate-800:hover{background-color:var(--color-slate-800)}.hover\:bg-status-fail:hover{background-color:var(--color-status-fail)}.hover\:bg-status-pass:hover{background-color:var(--color-status-pass)}.hover\:bg-status-pending\/20:hover{background-color:#f59e0b33}@supports (color:color-mix(in lab, red, red)){.hover\:bg-status-pending\/20:hover{background-color:color-mix(in oklab, var(--color-status-pending) 20%, transparent)}}.hover\:bg-surface:hover{background-color:var(--color-surface)}.hover\:bg-surface-alt:hover{background-color:var(--color-surface-alt)}.hover\:bg-surface-border\/20:hover{background-color:#dee2e633}@supports (color:color-mix(in lab, red, red)){.hover\:bg-surface-border\/20:hover{background-color:color-mix(in oklab, var(--color-surface-border) 20%, transparent)}}.hover\:bg-surface-hover:hover{background-color:var(--color-surface-hover)}.hover\:bg-zinc-100:hover{background-color:var(--color-zinc-100)}.hover\:bg-zinc-200:hover{background-color:var(--color-zinc-200)}.hover\:text-\[color\:var\(--color-text-primary\,\#212529\)\]:hover{color:var(--color-text-primary,#212529)}.hover\:text-accent-purple:hover{color:var(--color-accent-purple)}.hover\:text-slate-200:hover{color:var(--color-slate-200)}.hover\:text-status-pending:hover{color:var(--color-status-pending)}.hover\:text-text-muted:hover{color:var(--color-text-muted)}.hover\:text-text-primary:hover{color:var(--color-text-primary)}.hover\:text-text-secondary:hover{color:var(--color-text-secondary)}.hover\:opacity-80:hover{opacity:.8}.hover\:ring-accent-purple\/40:hover{--tw-ring-color:#8b5cf666}@supports (color:color-mix(in lab, red, red)){.hover\:ring-accent-purple\/40:hover{--tw-ring-color:color-mix(in oklab, var(--color-accent-purple) 40%, transparent)}}@media (hover:hover){.hover\:group-hover\/bubble\:text-\[var\(--color-accent-deep\)\]:hover:is(:where(.group\/bubble):hover *){color:var(--color-accent-deep)}}}.focus\:border-text-muted:focus{border-color:var(--color-text-muted)}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus\:ring-text-muted:focus{--tw-ring-color:var(--color-text-muted)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\:opacity-100:focus-visible{opacity:1}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:bg-surface:disabled{background-color:var(--color-surface)}.disabled\:bg-surface-alt:disabled{background-color:var(--color-surface-alt)}.disabled\:text-text-muted:disabled{color:var(--color-text-muted)}.disabled\:opacity-30:disabled{opacity:.3}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}@media (hover:hover){.disabled\:hover\:bg-surface-alt:disabled:hover{background-color:var(--color-surface-alt)}.disabled\:hover\:bg-transparent:disabled:hover{background-color:#0000}}@media (prefers-color-scheme:dark){.dark\:border-white\/15{border-color:#ffffff26}@supports (color:color-mix(in lab, red, red)){.dark\:border-white\/15{border-color:color-mix(in oklab, var(--color-white) 15%, transparent)}}.dark\:border-white\/20{border-color:#fff3}@supports (color:color-mix(in lab, red, red)){.dark\:border-white\/20{border-color:color-mix(in oklab, var(--color-white) 20%, transparent)}}.dark\:bg-neutral-700{background-color:var(--color-neutral-700)}.dark\:bg-neutral-800{background-color:var(--color-neutral-800)}.dark\:bg-neutral-900\/95{background-color:#171717f2}@supports (color:color-mix(in lab, red, red)){.dark\:bg-neutral-900\/95{background-color:color-mix(in oklab, var(--color-neutral-900) 95%, transparent)}}.dark\:text-neutral-200{color:var(--color-neutral-200)}}@media (pointer:coarse){.pointer-coarse\:opacity-100{opacity:1}}}pre code.hljs{padding:1em;display:block;overflow-x:auto}code.hljs{padding:3px 5px}.hljs{color:#24292e;background:#fff}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#d73a49}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#6f42c1}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-variable,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id{color:#005cc5}.hljs-regexp,.hljs-string,.hljs-meta .hljs-string{color:#032f62}.hljs-built_in,.hljs-symbol{color:#e36209}.hljs-comment,.hljs-code,.hljs-formula{color:#6a737d}.hljs-name,.hljs-quote,.hljs-selector-tag,.hljs-selector-pseudo{color:#22863a}.hljs-subst{color:#24292e}.hljs-section{color:#005cc5;font-weight:700}.hljs-bullet{color:#735c0f}.hljs-emphasis{color:#24292e;font-style:italic}.hljs-strong{color:#24292e;font-weight:700}.hljs-addition{color:#22863a;background-color:#f0fff4}.hljs-deletion{color:#b31d28;background-color:#ffeef0}[data-theme=dark]{--color-surface:#16181d;--color-surface-alt:#1d2026;--color-surface-hover:#262a32;--color-surface-border:#333842;--color-surface-elevated:#21252c;--color-text-primary:#e9ecef;--color-text-secondary:#9aa3ad;--color-text-muted:#757e89;--color-accent-blue:#60a5fa;--color-accent-purple:#a78bfa;--color-accent-purple-soft:#4c1d95;--color-accent-purple-ink:#ede9fe;--color-accent-emerald:#34d399;--color-accent-emerald-deep:#15803d;--color-accent-amber:#fbbf24;--color-accent-rose:#fb7185;--color-accent-cyan:#22d3ee;--color-accent-pink:#f48bb4;--color-accent-pink-strong:#f7a8c4;--color-status-pass:#34d399;--color-status-fail:#f87171;--color-status-pending:#fbbf24;--color-status-fail-ink:#450a0a;--color-tree-repo:#ff7a4d;--color-tree-child:#f0a05c;--color-tree-amber:#ffc95c;--color-accent-deep:#a78bfa;--color-success-ink:#4ade80;--color-success-soft:#34d399;--color-green-verify:#4ade80;--color-accent-orange:#fb923c;--color-accent-amber-ink:#fbbf24;--color-accent-amber-ink-deep:#fcd34d;--color-danger-madrid:#ff6b6b;--color-danger-github:#ff8181;--color-danger-editor-surface:#3b1218;--color-danger-editor-ink:#ffb4bb;--color-doc-child:#ff9b9b;--color-navy-focus:#93c5fd;--color-header-wash:#2b2620;--color-slate-neutral:#9aa3ad;--color-danger-wash:#2a1215;--color-danger-wash-border:#45161c;--color-danger-wash-ink:#ffb4bb;--color-ws-violet:#c084fc;--color-ws-green:#4ade80;--color-ws-blue:#6cb8ff;--color-subagent-tint-1:#2e2c25;--color-subagent-tint-2:#35332a;--color-subagent-tint-3:#3c3a2f;--si-run:#f87171}[data-theme=dark] pre code.hljs{padding:1em;display:block;overflow-x:auto}[data-theme=dark] code.hljs{padding:3px 5px}[data-theme=dark] .hljs{color:#c9d1d9;background:#0d1117}[data-theme=dark] .hljs-doctag,[data-theme=dark] .hljs-keyword,[data-theme=dark] .hljs-meta .hljs-keyword,[data-theme=dark] .hljs-template-tag,[data-theme=dark] .hljs-template-variable,[data-theme=dark] .hljs-type,[data-theme=dark] .hljs-variable.language_{color:#ff7b72}[data-theme=dark] .hljs-title,[data-theme=dark] .hljs-title.class_,[data-theme=dark] .hljs-title.class_.inherited__,[data-theme=dark] .hljs-title.function_{color:#d2a8ff}[data-theme=dark] .hljs-attr,[data-theme=dark] .hljs-attribute,[data-theme=dark] .hljs-literal,[data-theme=dark] .hljs-meta,[data-theme=dark] .hljs-number,[data-theme=dark] .hljs-operator,[data-theme=dark] .hljs-variable,[data-theme=dark] .hljs-selector-attr,[data-theme=dark] .hljs-selector-class,[data-theme=dark] .hljs-selector-id{color:#79c0ff}[data-theme=dark] .hljs-regexp,[data-theme=dark] .hljs-string,[data-theme=dark] .hljs-meta .hljs-string{color:#a5d6ff}[data-theme=dark] .hljs-built_in,[data-theme=dark] .hljs-symbol{color:#ffa657}[data-theme=dark] .hljs-comment,[data-theme=dark] .hljs-code,[data-theme=dark] .hljs-formula{color:#8b949e}[data-theme=dark] .hljs-name,[data-theme=dark] .hljs-quote,[data-theme=dark] .hljs-selector-tag,[data-theme=dark] .hljs-selector-pseudo{color:#7ee787}[data-theme=dark] .hljs-subst{color:#c9d1d9}[data-theme=dark] .hljs-section{color:#1f6feb;font-weight:700}[data-theme=dark] .hljs-bullet{color:#f2cc60}[data-theme=dark] .hljs-emphasis{color:#c9d1d9;font-style:italic}[data-theme=dark] .hljs-strong{color:#c9d1d9;font-weight:700}[data-theme=dark] .hljs-addition{color:#aff5b4;background-color:#033a16}[data-theme=dark] .hljs-deletion{color:#ffdcd7;background-color:#67060c}::-webkit-scrollbar{width:6px}::-webkit-scrollbar-track{background:var(--color-surface)}::-webkit-scrollbar-thumb{background:var(--color-surface-border);border-radius:3px}::-webkit-scrollbar-thumb:hover{background:var(--color-text-muted)}.scrollbar-none{-ms-overflow-style:none;scrollbar-width:none}.scrollbar-none::-webkit-scrollbar{display:none}body{background-color:var(--color-surface);color:var(--color-text-primary);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif}.md-content{overflow-wrap:break-word;word-break:break-word;min-width:0;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif}.md-content table{border-collapse:collapse;white-space:normal;background:#8b5cf60a;border:1px solid #8b5cf633;border-radius:.5em;width:100%;margin:.5em 0;display:block;overflow:auto hidden}.md-content table th,.md-content table td{white-space:normal;word-break:normal;overflow-wrap:break-word}.md-content p{margin-top:.5em;margin-bottom:.25em}.md-content ul{margin:.2em 0;padding-left:1.5em;list-style-type:disc}.md-content ol{margin:.2em 0;padding-left:1.5em;list-style-type:decimal}.md-content li{display:list-item}.md-content h1,.md-content h2,.md-content h3{color:var(--color-text-primary);margin:.75em 0 .3em;font-weight:800}.md-content h1{font-size:1.25em}.md-content h2{font-size:1.1em}.md-content h3{font-size:1em}.md-content blockquote{color:var(--color-text-secondary);border-left:3px solid #8b5cf666;margin:.5em 0;padding:.3em .75em}.md-content strong{color:var(--color-text-primary);font-weight:600}.md-content em{color:var(--color-accent-deep)}.md-content hr{border:none;border-top:1px solid var(--color-surface-border);margin:.5em 0}.md-content a{color:var(--color-accent-blue);text-underline-offset:2px;text-decoration:underline}.md-content th{color:var(--color-text-primary);background:#8b5cf61f}.md-content th,.md-content td{text-align:left;border:1px solid #8b5cf626;padding:.35em .6em}.md-content tbody tr:nth-child(2n){background:#8b5cf608}.md-content tbody tr:hover{background:#8b5cf614}.md-content code:not(pre code),.md-content :not(pre)>code{color:var(--color-accent-deep);background:#8b5cf614;border-radius:.3em;padding:.15em .35em;font-family:SF Mono,Fira Code,JetBrains Mono,monospace;font-size:.8em}.md-content pre{background:var(--color-surface-alt);border:1px solid var(--color-surface-border);border-radius:.5em;max-width:100%;margin:.5em 0;padding:.5em;font-size:.8em;overflow-x:auto}.md-content pre code{color:var(--color-text-primary);font-family:SF Mono,Fira Code,JetBrains Mono,monospace}[data-testid=assistant-turn] .md-content>:last-child{margin-bottom:.25em}[data-testid=assistant-turn] .md-content>:first-child{margin-top:.5em}.md-content .mermaid-diagram{justify-content:center;margin:.5em 0;padding:.5em;display:flex;overflow-x:auto}.md-content .mermaid-diagram svg{max-width:100%;height:auto}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}