@opencode-trace/viewer 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -27,14 +27,29 @@ opencode-trace-viewer
27
27
  opencode-trace viewer
28
28
  ```
29
29
 
30
- After starting, browser automatically opens (default http://localhost:3000).
30
+ ```bash
31
+ # Start Viewer with custom trace directory
32
+ opencode-trace-viewer --trace-dir /path/to/traces
33
+
34
+ # Start Viewer
35
+ npx @opencode-trace/viewer
36
+
37
+ # Or (if globally installed)
38
+ opencode-trace-viewer
39
+
40
+ # Or (via CLI)
41
+ opencode-trace viewer
42
+ ```
43
+
44
+ After starting, browser automatically opens (default http://localhost:3210).
31
45
 
32
46
  ### Options
33
47
 
34
48
  | Option | Description |
35
49
  |--------|-------------|
36
- | `--port <num>` | Specify port (default 3000) |
50
+ | `--port <num>` | Specify port (default 3210) |
37
51
  | `--no-open` | Don't auto-open browser |
52
+ | `--trace-dir <path>` | Read trace data from custom directory (default `~/.opencode-trace`) |
38
53
 
39
54
  ## Features
40
55
 
package/dist/cli.js CHANGED
@@ -1,16 +1,30 @@
1
1
  #!/usr/bin/env node
2
2
  import { createViewer } from "./server.js";
3
- const args = process.argv.slice(2);
4
- const openBrowser = !args.includes("--no-open");
5
- const portArg = args.find((a) => !a.startsWith("--"));
3
+ const rawArgs = process.argv.slice(2);
4
+ let traceDir;
5
+ let openBrowser = true;
6
+ let portArg;
7
+ for (let i = 0; i < rawArgs.length; i++) {
8
+ const a = rawArgs[i];
9
+ if (a === "--trace-dir" && i + 1 < rawArgs.length) {
10
+ traceDir = rawArgs[++i];
11
+ }
12
+ else if (a === "--no-open") {
13
+ openBrowser = false;
14
+ }
15
+ else if (!a.startsWith("--") && portArg === undefined) {
16
+ portArg = a;
17
+ }
18
+ }
6
19
  const port = portArg ? parseInt(portArg, 10) : 3210;
7
20
  if (isNaN(port)) {
8
- console.error("Usage: opencode-trace-viewer [port] [--no-open]");
21
+ console.error("Usage: opencode-trace-viewer [port] [--no-open] [--trace-dir <path>]");
9
22
  console.error("Default port: 3210");
10
- console.error(" --no-open Don't open browser automatically");
23
+ console.error(" --no-open Don't open browser automatically");
24
+ console.error(" --trace-dir Read trace data from custom path instead of ~/.opencode-trace");
11
25
  process.exit(1);
12
26
  }
13
- createViewer({ port, open: openBrowser }).then((instance) => {
27
+ createViewer({ port, open: openBrowser, traceDir }).then((instance) => {
14
28
  console.log(`opencode-trace viewer running at ${instance.url}`);
15
29
  console.log("Press Ctrl+C to stop");
16
30
  process.on("SIGINT", () => {
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,MAAM,WAAW,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AAChD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;AACtD,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAEpD,IAAI,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;IAChB,OAAO,CAAC,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACjE,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;IACpC,OAAO,CAAC,KAAK,CAAC,+CAA+C,CAAC,CAAC;IAC/D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,YAAY,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE;IAC1D,OAAO,CAAC,GAAG,CAAC,oCAAoC,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC;IAChE,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IAEpC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;QACxB,QAAQ,CAAC,KAAK,EAAE,CAAC;QACjB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEtC,IAAI,QAA4B,CAAC;AACjC,IAAI,WAAW,GAAG,IAAI,CAAC;AACvB,IAAI,OAA2B,CAAC;AAEhC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;IACxC,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACrB,IAAI,CAAC,KAAK,aAAa,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;QAClD,QAAQ,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1B,CAAC;SAAM,IAAI,CAAC,KAAK,WAAW,EAAE,CAAC;QAC7B,WAAW,GAAG,KAAK,CAAC;IACtB,CAAC;SAAM,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QACxD,OAAO,GAAG,CAAC,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAEpD,IAAI,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;IAChB,OAAO,CAAC,KAAK,CAAC,sEAAsE,CAAC,CAAC;IACtF,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;IACpC,OAAO,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACnE,OAAO,CAAC,KAAK,CAAC,gFAAgF,CAAC,CAAC;IAChG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,YAAY,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE;IACpE,OAAO,CAAC,GAAG,CAAC,oCAAoC,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC;IAChE,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IAEpC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;QACxB,QAAQ,CAAC,KAAK,EAAE,CAAC;QACjB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cli.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.test.d.ts","sourceRoot":"","sources":["../src/cli.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,110 @@
1
+ import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
2
+ const { mockCreateViewer } = vi.hoisted(() => ({
3
+ mockCreateViewer: vi.fn(),
4
+ }));
5
+ vi.mock("./server.js", () => ({
6
+ createViewer: mockCreateViewer,
7
+ }));
8
+ describe("cli", () => {
9
+ let originalArgv;
10
+ let exitSpy;
11
+ let logSpy;
12
+ let errorSpy;
13
+ let onSpy;
14
+ let mockInstance;
15
+ async function loadCliWithArgs(args) {
16
+ vi.resetModules();
17
+ process.argv = ["node", "cli.js", ...args];
18
+ await import("./cli.js");
19
+ await new Promise((resolve) => setImmediate(resolve));
20
+ }
21
+ beforeEach(() => {
22
+ originalArgv = process.argv;
23
+ mockInstance = {
24
+ url: "http://localhost:3210",
25
+ close: vi.fn().mockResolvedValue(undefined),
26
+ };
27
+ mockCreateViewer.mockReset();
28
+ mockCreateViewer.mockResolvedValue(mockInstance);
29
+ exitSpy = vi.spyOn(process, "exit").mockImplementation(((code) => {
30
+ throw new Error(`exit_${code}`);
31
+ }));
32
+ logSpy = vi.spyOn(console, "log").mockImplementation(() => { });
33
+ errorSpy = vi.spyOn(console, "error").mockImplementation(() => { });
34
+ onSpy = vi.spyOn(process, "on");
35
+ });
36
+ afterEach(() => {
37
+ process.argv = originalArgv;
38
+ exitSpy.mockRestore();
39
+ logSpy.mockRestore();
40
+ errorSpy.mockRestore();
41
+ onSpy.mockRestore();
42
+ vi.resetModules();
43
+ });
44
+ it("uses defaults (port 3210, open=true, no traceDir) when no args", async () => {
45
+ await loadCliWithArgs([]);
46
+ expect(mockCreateViewer).toHaveBeenCalledTimes(1);
47
+ expect(mockCreateViewer).toHaveBeenCalledWith({
48
+ port: 3210,
49
+ open: true,
50
+ traceDir: undefined,
51
+ });
52
+ expect(logSpy).toHaveBeenCalledWith("opencode-trace viewer running at http://localhost:3210");
53
+ expect(logSpy).toHaveBeenCalledWith("Press Ctrl+C to stop");
54
+ });
55
+ it("accepts positional port arg", async () => {
56
+ mockInstance.url = "http://localhost:3211";
57
+ await loadCliWithArgs(["3211"]);
58
+ expect(mockCreateViewer).toHaveBeenCalledWith({
59
+ port: 3211,
60
+ open: true,
61
+ traceDir: undefined,
62
+ });
63
+ expect(logSpy).toHaveBeenCalledWith("opencode-trace viewer running at http://localhost:3211");
64
+ });
65
+ it("--no-open disables browser open", async () => {
66
+ await loadCliWithArgs(["--no-open"]);
67
+ expect(mockCreateViewer).toHaveBeenCalledWith({
68
+ port: 3210,
69
+ open: false,
70
+ traceDir: undefined,
71
+ });
72
+ });
73
+ it("--trace-dir sets traceDir", async () => {
74
+ await loadCliWithArgs(["--trace-dir", "/tmp/x"]);
75
+ expect(mockCreateViewer).toHaveBeenCalledWith({
76
+ port: 3210,
77
+ open: true,
78
+ traceDir: "/tmp/x",
79
+ });
80
+ });
81
+ it("combines port, --no-open and --trace-dir", async () => {
82
+ mockInstance.url = "http://localhost:3211";
83
+ await loadCliWithArgs(["3211", "--no-open", "--trace-dir", "/tmp/x"]);
84
+ expect(mockCreateViewer).toHaveBeenCalledWith({
85
+ port: 3211,
86
+ open: false,
87
+ traceDir: "/tmp/x",
88
+ });
89
+ });
90
+ it("invalid port prints usage and exits with code 1", async () => {
91
+ vi.resetModules();
92
+ process.argv = ["node", "cli.js", "abc"];
93
+ await expect(import("./cli.js")).rejects.toThrow("exit_1");
94
+ expect(errorSpy).toHaveBeenCalledWith("Usage: opencode-trace-viewer [port] [--no-open] [--trace-dir <path>]");
95
+ expect(errorSpy).toHaveBeenCalledWith("Default port: 3210");
96
+ expect(errorSpy).toHaveBeenCalledWith(" --no-open Don't open browser automatically");
97
+ expect(errorSpy).toHaveBeenCalledWith(" --trace-dir Read trace data from custom path instead of ~/.opencode-trace");
98
+ expect(mockCreateViewer).not.toHaveBeenCalled();
99
+ });
100
+ it("registers SIGINT handler that closes instance and exits 0", async () => {
101
+ await loadCliWithArgs([]);
102
+ const sigintCall = onSpy.mock.calls.find((c) => c[0] === "SIGINT");
103
+ expect(sigintCall).toBeDefined();
104
+ const handler = sigintCall[1];
105
+ expect(() => handler()).toThrow("exit_0");
106
+ expect(mockInstance.close).toHaveBeenCalledTimes(1);
107
+ expect(exitSpy).toHaveBeenCalledWith(0);
108
+ });
109
+ });
110
+ //# sourceMappingURL=cli.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.test.js","sourceRoot":"","sources":["../src/cli.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,21 @@
1
+ import { describe, it, expect } from "vitest";
2
+ describe("index (barrel)", () => {
3
+ it("re-exports createViewer from ./server.js", async () => {
4
+ const indexExports = await import("./index.js");
5
+ expect(indexExports.createViewer).toBeDefined();
6
+ expect(typeof indexExports.createViewer).toBe("function");
7
+ });
8
+ it("createViewer reference equals the one exported from server.js", async () => {
9
+ const indexExports = await import("./index.js");
10
+ const serverExports = await import("./server.js");
11
+ expect(indexExports.createViewer).toBe(serverExports.createViewer);
12
+ });
13
+ it("exposes only runtime symbols (types are erased)", async () => {
14
+ const indexExports = await import("./index.js");
15
+ const runtimeKeys = Object.keys(indexExports).sort();
16
+ // ViewerOptions and ViewerInstance are type-only re-exports
17
+ // so only createViewer is present at runtime.
18
+ expect(runtimeKeys).toEqual(["createViewer"]);
19
+ });
20
+ });
21
+ //# sourceMappingURL=index.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE9C,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;QAChD,MAAM,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,WAAW,EAAE,CAAC;QAChD,MAAM,CAAC,OAAO,YAAY,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+DAA+D,EAAE,KAAK,IAAI,EAAE;QAC7E,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;QAChD,MAAM,aAAa,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;QAClD,MAAM,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAC/D,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;QAChD,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,EAAE,CAAC;QACrD,4DAA4D;QAC5D,8CAA8C;QAC9C,MAAM,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ header[data-v-dac32c4f]{display:flex;align-items:center;justify-content:space-between;padding:12px 24px;background:var(--bg-primary);border-bottom:1px solid var(--border);flex-shrink:0;min-height:48px}header h1[data-v-dac32c4f]{font-size:16px;font-weight:700;display:flex;align-items:center;gap:8px;line-height:1}.header-actions[data-v-dac32c4f]{display:flex;align-items:center;gap:12px}.dropdown[data-v-dac32c4f]{position:relative}.dropdown-toggle[data-v-dac32c4f]{padding:8px;border-radius:var(--radius);display:flex;align-items:center;justify-content:center;transition:background .1s}.dropdown-toggle[data-v-dac32c4f]:hover{background:var(--bg-hover)}.dropdown-menu[data-v-dac32c4f]{position:absolute;right:0;top:100%;margin-top:4px;background:var(--bg-secondary);border:1px solid var(--border);border-radius:var(--radius);min-width:200px;z-index:100;padding:4px}.dropdown-item[data-v-dac32c4f]{display:flex;align-items:center;gap:8px;width:100%;padding:8px 12px;font-size:14px;font-weight:500;border-radius:var(--radius);transition:background .1s;text-align:left}.dropdown-item[data-v-dac32c4f]:hover{background:var(--bg-hover)}.dropdown-item.danger[data-v-dac32c4f]{color:var(--danger)}.dropdown-divider[data-v-dac32c4f]{height:1px;background:var(--border);margin:4px 0}.breadcrumb[data-v-1dcd01d0]{display:flex;align-items:center;gap:6px;font-size:13px;color:var(--text-secondary);padding:8px 24px;background:var(--bg-primary);border-bottom:1px solid var(--border);flex-shrink:0;flex-wrap:wrap}.breadcrumb a[data-v-1dcd01d0]{color:var(--text-secondary);text-decoration:none}.breadcrumb a[data-v-1dcd01d0]:hover{color:var(--accent);text-decoration:underline}.sep[data-v-1dcd01d0]{color:var(--text-tertiary);margin:0 2px}.current[data-v-1dcd01d0]{color:var(--text-primary);font-weight:500}.fab-container[data-v-05bb3e02]{position:fixed;bottom:24px;right:24px;display:flex;flex-direction:column;gap:8px;z-index:50}.fab-scroll[data-v-05bb3e02]{width:40px;height:40px;border-radius:var(--radius);background:var(--bg-secondary);border:1px solid var(--border);display:flex;align-items:center;justify-content:center;transition:background .1s}.fab-scroll[data-v-05bb3e02]:hover{background:var(--bg-hover)}.toast-container[data-v-c0d5f9b8]{position:fixed;bottom:24px;left:50%;transform:translate(-50%);display:flex;flex-direction:column;gap:8px;z-index:200;pointer-events:none}.toast[data-v-c0d5f9b8]{display:flex;align-items:center;gap:12px;padding:10px 16px;border-radius:var(--radius);font-size:14px;font-weight:500;pointer-events:auto;animation:toast-in-c0d5f9b8 .2s ease-out;border:1px solid}.toast.success[data-v-c0d5f9b8]{background:#30d1581f;border-color:var(--success);color:var(--success)}.toast.error[data-v-c0d5f9b8]{background:#ff3b301f;border-color:var(--danger);color:var(--danger)}.toast.info[data-v-c0d5f9b8]{background:var(--bg-secondary);border-color:var(--border);color:var(--text-primary)}.toast.warning[data-v-c0d5f9b8]{background:#ff9f0a1f;border-color:var(--warning);color:var(--warning)}.toast-action[data-v-c0d5f9b8]{padding:4px 10px;border-radius:var(--radius);font-size:12px;font-weight:700;background:var(--bg-tertiary);white-space:nowrap}@keyframes toast-in-c0d5f9b8{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.confirm-overlay[data-v-d7ee27c7]{position:fixed;top:0;right:0;bottom:0;left:0;background:#00000080;display:flex;align-items:center;justify-content:center;z-index:300}.confirm-dialog[data-v-d7ee27c7]{background:var(--bg-primary);border:1px solid var(--border);border-radius:var(--radius);padding:24px;max-width:420px;width:90%}.confirm-title[data-v-d7ee27c7]{font-size:16px;font-weight:700;margin-bottom:8px}.confirm-message[data-v-d7ee27c7]{font-size:14px;color:var(--text-secondary);margin-bottom:20px;line-height:1.5}.confirm-actions[data-v-d7ee27c7]{display:flex;gap:8px;justify-content:flex-end}.confirm-btn[data-v-d7ee27c7]{padding:8px 20px;border-radius:var(--radius);font-size:14px;font-weight:500;transition:background .1s}.confirm-btn.cancel[data-v-d7ee27c7]{background:var(--bg-tertiary);color:var(--text-primary)}.confirm-btn.cancel[data-v-d7ee27c7]:hover{background:var(--bg-hover)}.confirm-btn.danger[data-v-d7ee27c7]{background:var(--danger);color:var(--oc-light)}.confirm-btn.danger[data-v-d7ee27c7]:hover{background:var(--danger-hover)}.keyboard-help-overlay[data-v-3d1cdec0]{position:fixed;top:0;right:0;bottom:0;left:0;background:#00000080;display:flex;align-items:center;justify-content:center;z-index:300}.keyboard-help[data-v-3d1cdec0]{background:var(--bg-primary);border:1px solid var(--border);border-radius:var(--radius);padding:24px;max-width:380px;width:90%}.keyboard-help h3[data-v-3d1cdec0]{font-size:16px;font-weight:700;margin-bottom:16px}.shortcut-list[data-v-3d1cdec0]{display:flex;flex-direction:column;gap:10px;margin-bottom:20px}.shortcut[data-v-3d1cdec0]{display:flex;align-items:center;gap:10px;font-size:14px;color:var(--text-secondary)}.help-close[data-v-3d1cdec0]{width:100%;padding:8px 20px;border-radius:var(--radius);font-size:14px;font-weight:500;background:var(--bg-tertiary);transition:background .1s}.help-close[data-v-3d1cdec0]:hover{background:var(--bg-hover)}.modal-overlay[data-v-3bdf94c5]{position:fixed;top:0;right:0;bottom:0;left:0;background:#00000080;display:flex;align-items:center;justify-content:center;z-index:300}.modal-content[data-v-3bdf94c5]{background:var(--bg-primary);border:1px solid var(--border);border-radius:var(--radius);max-width:480px;width:90%}.modal-header[data-v-3bdf94c5]{display:flex;align-items:center;justify-content:space-between;padding:16px 20px;border-bottom:1px solid var(--border)}.modal-header h3[data-v-3bdf94c5]{font-size:16px;font-weight:700}.modal-close[data-v-3bdf94c5]{font-size:20px;padding:4px 8px;border-radius:var(--radius)}.modal-close[data-v-3bdf94c5]:hover{background:var(--bg-hover)}.modal-body[data-v-3bdf94c5]{padding:20px}.file-label[data-v-3bdf94c5]{display:flex;flex-direction:column;gap:8px;margin-bottom:16px}.file-label-text[data-v-3bdf94c5]{font-size:14px;font-weight:500}.file-input-wrapper[data-v-3bdf94c5]{position:relative;display:inline-block}.file-input-native[data-v-3bdf94c5]{position:absolute;top:0;left:0;width:100%;height:100%;opacity:0;cursor:pointer}.file-input-button[data-v-3bdf94c5]{display:inline-block;padding:10px 18px;background:var(--bg-tertiary);color:var(--text-primary);border-radius:var(--radius);font-size:14px;font-weight:500;cursor:pointer;transition:background .1s;border:1px solid var(--border)}.file-input-button[data-v-3bdf94c5]:hover{background:var(--bg-hover)}.file-input-native:focus-visible+.file-input-button[data-v-3bdf94c5]{outline:2px solid var(--accent);outline-offset:2px}.import-status[data-v-3bdf94c5]{min-height:24px}.status-msg[data-v-3bdf94c5]{font-size:14px;padding:8px 12px;border-radius:var(--radius)}.status-msg.success[data-v-3bdf94c5]{background:#30d1581f;color:var(--success)}.status-msg.error[data-v-3bdf94c5]{background:#ff3b301f;color:var(--danger)}.status-msg.warning[data-v-3bdf94c5]{background:#ff9f0a1f;color:var(--warning)}.conflict-panel[data-v-3bdf94c5]{margin-top:16px}.conflict-panel h4[data-v-3bdf94c5]{font-size:14px;font-weight:700;margin-bottom:8px}.conflict-list[data-v-3bdf94c5]{display:flex;flex-direction:column;gap:4px;margin-bottom:12px;max-height:200px;overflow-y:auto}.conflict-item[data-v-3bdf94c5]{display:flex;gap:8px;padding:6px 10px;background:var(--bg-tertiary);border-radius:var(--radius);font-size:13px}.conflict-id[data-v-3bdf94c5]{font-weight:500;color:var(--text-primary)}.conflict-title[data-v-3bdf94c5]{color:var(--text-secondary)}.conflict-actions[data-v-3bdf94c5]{display:flex;gap:8px}.conflict-actions button[data-v-3bdf94c5]{padding:6px 14px;border-radius:var(--radius);font-size:13px;font-weight:500}.action-rename[data-v-3bdf94c5]{background:var(--accent);color:var(--oc-light)}.action-rename[data-v-3bdf94c5]:hover{background:var(--accent-hover)}.action-skip[data-v-3bdf94c5]{background:var(--bg-tertiary)}.action-skip[data-v-3bdf94c5]:hover{background:var(--bg-hover)}.action-cancel[data-v-3bdf94c5]{background:var(--bg-tertiary)}.action-cancel[data-v-3bdf94c5]:hover{background:var(--bg-hover)}.sessions-controls-bar[data-v-15c5be0c]{margin-top:16px;margin-bottom:16px}.view-controls[data-v-15c5be0c]{display:flex;align-items:center;justify-content:flex-end;gap:12px;flex-wrap:wrap}.search-input-container[data-v-15c5be0c]{position:relative;display:flex;align-items:center}.search-icon[data-v-15c5be0c]{position:absolute;left:12px;color:var(--text-tertiary);pointer-events:none;display:flex}.search-input[data-v-15c5be0c]{padding:8px 36px;border:1px solid var(--border);border-radius:var(--radius-input);background:var(--bg-tertiary);color:var(--text-primary);font-family:var(--font-family);font-size:14px;width:240px;outline:none;transition:border-color .1s}.search-input[data-v-15c5be0c]:focus{border-color:var(--accent)}.search-clear[data-v-15c5be0c]{position:absolute;right:4px;padding:4px;border-radius:2px;display:flex;align-items:center}.search-clear[data-v-15c5be0c]:hover{background:var(--bg-hover)}.sort-label[data-v-15c5be0c]{display:flex;align-items:center;gap:6px;font-size:13px;color:var(--text-secondary)}.sort-select[data-v-15c5be0c]{padding:6px 32px 6px 12px;border:1px solid var(--border);border-radius:var(--radius);background:var(--bg-tertiary);color:var(--text-primary);font-family:var(--font-family);font-size:13px;outline:none;-webkit-appearance:none;-moz-appearance:none;appearance:none;cursor:pointer;position:relative}.sort-select[data-v-15c5be0c]:after{content:"";position:absolute;right:10px;top:50%;transform:translateY(-50%);width:12px;height:12px;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:center;color:var(--text-secondary);pointer-events:none}.sort-select option[data-v-15c5be0c]{background:var(--bg-primary);color:var(--text-primary)}.folder-groups[data-v-15c5be0c]{display:flex;flex-direction:column;gap:24px}.folder-group[data-v-15c5be0c]{border:1px solid var(--border);border-radius:var(--radius);overflow:hidden}.folder-header[data-v-15c5be0c]{display:flex;align-items:center;gap:12px;padding:12px 16px;background:var(--bg-tertiary);border-bottom:1px solid var(--border);flex-wrap:wrap}.folder-title[data-v-15c5be0c]{font-size:14px;font-weight:700}.folder-path[data-v-15c5be0c]{font-size:12px;color:var(--text-tertiary);flex:1}.folder-sessions[data-v-15c5be0c]{padding:8px;display:flex;flex-direction:column;gap:4px}.session-card[data-v-15c5be0c]{padding:12px 16px}.session-card-header[data-v-15c5be0c]{display:flex;align-items:center;justify-content:space-between}.session-title-row[data-v-15c5be0c]{flex:1;min-width:0}.session-card-content[data-v-15c5be0c]{display:flex;flex-direction:column;gap:4px}.session-title[data-v-15c5be0c]{font-size:14px;font-weight:700;word-break:break-word}.session-id[data-v-15c5be0c]{font-size:12px;color:var(--text-tertiary);word-break:break-all}.session-meta[data-v-15c5be0c]{display:flex;gap:6px;flex-wrap:wrap;margin-top:4px}.session-card-actions[data-v-15c5be0c]{flex-shrink:0;margin-left:12px}.session-card-more[data-v-15c5be0c]{position:relative}.session-more-btn[data-v-15c5be0c]{padding:4px 8px;border-radius:var(--radius);font-size:16px;line-height:1}.session-more-btn[data-v-15c5be0c]:hover{background:var(--bg-hover)}.session-more-menu[data-v-15c5be0c]{position:absolute;right:0;top:100%;margin-top:4px;background:var(--bg-secondary);border:1px solid var(--border);border-radius:var(--radius);min-width:200px;z-index:50;padding:4px}.session-more-menu .dropdown-item[data-v-15c5be0c]{display:flex;align-items:center;gap:8px;width:100%;padding:8px 12px;font-size:13px;font-weight:500;border-radius:var(--radius);text-align:left}.session-more-menu .dropdown-item[data-v-15c5be0c]:hover{background:var(--bg-hover)}.session-more-menu .dropdown-item.danger[data-v-15c5be0c]{color:var(--danger)}.subsession-arrow[data-v-15c5be0c]{transition:transform .2s ease}.subsession-arrow.rotated[data-v-15c5be0c]{transform:rotate(180deg)}.children-container[data-v-15c5be0c]{margin-left:24px;margin-top:4px;margin-bottom:4px;display:flex;flex-direction:column;gap:4px}.child-card[data-v-15c5be0c]{padding:10px 14px}.batch-toggle-btn[data-v-15c5be0c]{display:flex;align-items:center;gap:6px;padding:6px 14px;border:1px solid var(--border);border-radius:var(--radius);background:var(--bg-tertiary);color:var(--text-primary);font-family:var(--font-family);font-size:13px;font-weight:500;cursor:pointer;transition:background .1s,border-color .1s}.batch-toggle-btn[data-v-15c5be0c]:hover{background:var(--bg-hover)}.batch-toggle-btn.active[data-v-15c5be0c]{background:var(--accent);border-color:var(--accent);color:#fff}.batch-delete-btn[data-v-15c5be0c]{display:flex;align-items:center;gap:6px;padding:6px 14px;border:1px solid var(--danger);border-radius:var(--radius);background:var(--danger);color:#fff;font-family:var(--font-family);font-size:13px;font-weight:500;cursor:pointer;transition:opacity .1s}.batch-delete-btn[data-v-15c5be0c]:hover{opacity:.85}.batch-checkbox[data-v-15c5be0c]{display:flex;align-items:center;flex-shrink:0;margin-right:8px;cursor:pointer}.batch-checkbox input[type=checkbox][data-v-15c5be0c]{width:16px;height:16px;accent-color:var(--accent);cursor:pointer}.folder-checkbox[data-v-15c5be0c]{margin-right:12px}.cs-group{display:inline-flex;align-items:center;gap:4px;margin-right:8px}.cs-label{font-size:11px;font-weight:700;padding:1px 5px;border-radius:2px}.cs-label.sys{background:#8b5cf626;color:var(--sys-color)}.cs-label.tool{background:#ff9f0a26;color:var(--warning)}.cs-label.msg{background:#3d8bff26;color:var(--accent)}.cs-types{display:inline-flex;gap:3px}.cs-type{font-size:11px;font-weight:500;color:var(--text-secondary)}.cs-plus{color:var(--success);margin-left:2px}.cs-minus{color:var(--danger);margin-left:2px}.metadata-header[data-v-1868ccb6]{padding:12px 16px;background:var(--bg-tertiary);font-size:12px;font-weight:700;color:var(--text-tertiary);text-transform:uppercase;letter-spacing:.8px}.metadata-body[data-v-1868ccb6]{padding:16px}.stat-section[data-v-1868ccb6]{margin-bottom:12px}.stat-section[data-v-1868ccb6]:last-child{margin-bottom:0}.stat-section-title[data-v-1868ccb6]{font-size:11px;color:var(--text-tertiary);font-weight:600;margin-bottom:6px;text-transform:uppercase;letter-spacing:.5px}.stat-row-inline[data-v-1868ccb6]{display:flex;gap:12px;flex-wrap:wrap}.stat-item[data-v-1868ccb6]{display:flex;align-items:center;gap:4px;font-size:12px;padding:4px 10px;background:var(--bg-tertiary);border-radius:var(--radius)}.stat-key[data-v-1868ccb6]{color:var(--text-tertiary);font-weight:500;font-size:10px;text-transform:uppercase;letter-spacing:.4px}.stat-key[data-v-1868ccb6]:after{content:":"}.stat-val[data-v-1868ccb6]{color:var(--text-primary);font-weight:600;font-family:var(--font-family);font-size:12px}.stat-item.highlight .stat-val[data-v-1868ccb6]{color:var(--accent)}.stat-item.warning .stat-val[data-v-1868ccb6]{color:var(--warning)}.stat-item.danger .stat-val[data-v-1868ccb6]{color:var(--danger)}.stat-item.success .stat-val[data-v-1868ccb6]{color:var(--success)}.stat-grid[data-v-1868ccb6]{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:8px}.stat-grid .stat-item[data-v-1868ccb6]{flex-direction:column;align-items:flex-start;gap:2px;padding:8px;background:var(--bg-tertiary);border-radius:var(--radius)}.stat-grid .stat-key[data-v-1868ccb6]{font-size:10px;text-transform:uppercase;letter-spacing:.5px}.stat-grid .stat-val[data-v-1868ccb6]{font-size:14px}.stat-link[data-v-1868ccb6]{color:var(--accent);text-decoration:underline;font-weight:500}.stat-link[data-v-1868ccb6]:hover{color:var(--accent-hover)}.timeline-controls[data-v-08b9d9bb]{display:flex;justify-content:flex-end;margin-top:16px;margin-bottom:16px}.sort-label[data-v-08b9d9bb]{display:flex;align-items:center;gap:6px;font-size:13px;color:var(--text-secondary)}.sort-select[data-v-08b9d9bb]{padding:6px 32px 6px 12px;border:1px solid var(--border);border-radius:var(--radius);background:var(--bg-tertiary);color:var(--text-primary);font-family:var(--font-family);font-size:13px;outline:none;-webkit-appearance:none;-moz-appearance:none;appearance:none;cursor:pointer;position:relative}.sort-select[data-v-08b9d9bb]:after{content:"";position:absolute;right:10px;top:50%;transform:translateY(-50%);width:12px;height:12px;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:center;color:var(--text-secondary);pointer-events:none}.sort-select option[data-v-08b9d9bb]{background:var(--bg-primary);color:var(--text-primary)}.timeline[data-v-08b9d9bb]{display:flex;flex-direction:column;gap:4px}.timeline-item[data-v-08b9d9bb]{margin-bottom:4px}.timeline-card[data-v-08b9d9bb]{padding:12px 16px}.timeline-card-header[data-v-08b9d9bb]{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.timeline-card-header .left[data-v-08b9d9bb]{display:flex;align-items:center;gap:8px;flex-wrap:wrap;flex:1;min-width:0}.timeline-card-header .right[data-v-08b9d9bb]{display:flex;align-items:center;gap:6px;flex-shrink:0}.req-num[data-v-08b9d9bb]{font-weight:700;font-size:14px;color:var(--text-primary)}.call-type[data-v-08b9d9bb]{font-size:11px;font-weight:700;padding:1px 6px;border-radius:2px}.call-type.user[data-v-08b9d9bb]{background:#3d8bff26;color:var(--accent)}.call-type.agent[data-v-08b9d9bb]{background:#8b5cf626;color:var(--sys-color)}.url[data-v-08b9d9bb]{font-size:13px;color:var(--text-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:300px}.time-badge[data-v-08b9d9bb]{font-size:12px;font-weight:500;padding:2px 8px;border-radius:var(--radius);white-space:nowrap}.time-badge.dur[data-v-08b9d9bb]{background:#3d8bff1a;color:var(--accent)}.time-badge.gap[data-v-08b9d9bb]{background:#ff9f0a1a;color:var(--warning)}.time-badge.model[data-v-08b9d9bb]{background:#30d1581a;color:var(--success)}.time-badge.provider[data-v-08b9d9bb]{background:var(--bg-tertiary);color:var(--text-secondary)}.block-item[data-v-f15798cd]{margin-bottom:8px}.block-type-bar[data-v-f15798cd]{display:flex;align-items:center;justify-content:space-between;padding:6px 10px;background:var(--bg-tertiary);border-radius:var(--radius) var(--radius) 0 0;border:1px solid var(--border);border-bottom:none}.block-type-left[data-v-f15798cd]{display:flex;align-items:center;gap:8px;font-size:12px}.block-type-right[data-v-f15798cd]{display:flex;align-items:center;gap:4px}.block-type-tag[data-v-f15798cd]{font-weight:700;font-size:11px;padding:1px 6px;border-radius:2px}.block-type-tag.text[data-v-f15798cd]{background:#3d8bff26;color:var(--accent)}.block-type-tag.thinking[data-v-f15798cd]{background:#8b5cf626;color:var(--sys-color)}.block-type-tag.td[data-v-f15798cd]{background:#ff9f0a26;color:var(--warning)}.block-type-tag.tc[data-v-f15798cd],.block-type-tag.tr[data-v-f15798cd]{background:#30d15826;color:var(--success)}.block-type-tag.image[data-v-f15798cd]{background:#9a989826;color:var(--text-secondary)}.block-type-tag.json[data-v-f15798cd]{background:#a78bfa26;color:var(--json-key-color)}.block-type-tag.xml[data-v-f15798cd]{background:#ff9f0a26;color:var(--warning)}.block-type-tag.status[data-v-f15798cd]{background:#9a989826;color:var(--text-secondary)}.tool-meta-name[data-v-f15798cd]{font-weight:500;color:var(--text-primary)}.tool-meta-id[data-v-f15798cd]{color:var(--text-secondary)}.toggle-btn[data-v-f15798cd]{font-size:11px;font-weight:700;padding:2px 6px;border-radius:2px;color:var(--text-tertiary);transition:color .1s,background .1s}.toggle-btn[data-v-f15798cd]:hover,.toggle-btn.active[data-v-f15798cd]{color:var(--accent);background:#3d8bff1a}.block-content[data-v-f15798cd]{padding:10px 12px;background:var(--bg-primary);border:1px solid var(--border);border-radius:0 0 var(--radius) var(--radius);font-size:13px;line-height:1.6;overflow-x:auto;position:relative}.block-content.empty[data-v-f15798cd]{display:none}.block-content.raw[data-v-f15798cd]{white-space:pre-wrap;word-break:break-word}.copy-btn[data-v-f15798cd]{position:absolute;top:6px;right:6px;padding:4px;border-radius:2px;opacity:0;transition:opacity .1s;z-index:1}.block-content:hover .copy-btn[data-v-f15798cd]{opacity:1}.copy-btn[data-v-f15798cd]:hover{background:var(--bg-hover)}.content-muted[data-v-f15798cd]{color:var(--text-tertiary);font-style:italic}.tool-def-desc[data-v-f15798cd]{margin-bottom:8px;color:var(--text-secondary)}.tool-def-params[data-v-f15798cd]{margin-top:4px}.section-content[data-v-6a06d44d]{margin-bottom:16px}.change-card[data-v-6a06d44d]{border:1px solid var(--border);border-radius:var(--radius);margin-bottom:8px;overflow:hidden}.change-card.added[data-v-6a06d44d]{border-left:3px solid var(--success)}.change-card.removed[data-v-6a06d44d]{border-left:3px solid var(--danger)}.change-card-header[data-v-6a06d44d]{display:flex;align-items:center;gap:8px;padding:8px 12px;background:var(--bg-tertiary);border-bottom:1px solid var(--border)}.change-card-body[data-v-6a06d44d]{padding:8px}.cat-tag[data-v-6a06d44d]{font-size:11px;font-weight:700;padding:1px 6px;border-radius:2px}.cat-tag.sys[data-v-6a06d44d]{background:#8b5cf626;color:var(--sys-color)}.cat-tag.tool[data-v-6a06d44d]{background:#ff9f0a26;color:var(--warning)}.cat-tag.msg[data-v-6a06d44d]{background:#3d8bff26;color:var(--accent)}.action-tag[data-v-6a06d44d]{font-size:11px;font-weight:700;padding:1px 6px;border-radius:2px}.action-tag.new[data-v-6a06d44d]{background:#30d15826;color:var(--success)}.action-tag.del[data-v-6a06d44d]{background:#ff3b3026;color:var(--danger)}.section-content[data-v-c5e69052]{margin-bottom:16px}.msg[data-v-c5e69052]{border:1px solid var(--border);border-radius:var(--radius);margin-bottom:8px;overflow:hidden}.msg-header[data-v-c5e69052]{display:flex;align-items:center;gap:8px;padding:8px 12px;background:var(--bg-tertiary);border-bottom:1px solid var(--border)}.msg-body[data-v-c5e69052]{padding:8px}.cat-tag[data-v-c5e69052]{font-size:11px;font-weight:700;padding:1px 6px;border-radius:2px}.cat-tag.sys[data-v-c5e69052]{background:#8b5cf626;color:var(--sys-color)}.cat-tag.tool[data-v-c5e69052]{background:#ff9f0a26;color:var(--warning)}.cat-tag.msg[data-v-c5e69052]{background:#3d8bff26;color:var(--accent)}.role-tag[data-v-c5e69052]{font-size:12px;font-weight:500;color:var(--text-secondary)}.json-container[data-v-4b06a711]{position:relative;background:var(--bg-primary);font-size:13px;line-height:1.6}.copy-btn[data-v-4b06a711]{position:absolute;top:6px;right:6px;padding:4px;border-radius:2px;opacity:0;transition:opacity .1s;z-index:1}.json-container:hover .copy-btn[data-v-4b06a711]{opacity:1}.copy-btn[data-v-4b06a711]:hover{background:var(--bg-hover)}.json-line[data-v-4b06a711]{display:flex;padding:0 12px;min-height:22px}.json-line[data-v-4b06a711]:hover{background:var(--bg-hover)}.json-num[data-v-4b06a711]{flex-shrink:0;width:40px;text-align:right;padding-right:12px;color:var(--text-tertiary);-webkit-user-select:none;user-select:none}.section-content[data-v-880e4b46]{margin-bottom:16px}.json-block[data-v-880e4b46]{border:1px solid var(--border);border-radius:var(--radius);overflow:hidden}.section-content[data-v-7107da38]{margin-bottom:16px}.json-block[data-v-7107da38]{border:1px solid var(--border);border-radius:var(--radius);overflow:hidden}.view-toggle[data-v-57d357ff]{display:flex;gap:4px;margin-top:16px;margin-bottom:16px;padding:4px;background:var(--bg-tertiary);border-radius:var(--radius);width:fit-content}.view-toggle button[data-v-57d357ff]{padding:6px 16px;border-radius:var(--radius);font-size:13px;font-weight:500;color:var(--text-secondary);transition:background .1s,color .1s}.view-toggle button[data-v-57d357ff]:hover{color:var(--text-primary)}.view-toggle button.active[data-v-57d357ff]{background:var(--bg-primary);color:var(--text-primary);font-weight:700}.record-view-content[data-v-57d357ff]{margin-top:8px}*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}:root{--oc-dark: #201d1d;--oc-light: #fdfcfc;--oc-mid: #9a9898;--oc-dark-surface: #302c2c;--oc-border-gray: #646262;--oc-light-surface: #f1eeee;--accent: #3d8bff;--accent-hover: #1a6fff;--accent-active: #0056b3;--danger: #ff3b30;--danger-hover: #d70015;--danger-active: #a50011;--success: #30d158;--warning: #ff9f0a;--warning-hover: #cc7f08;--warning-active: #995f06;--sys-color: #8b5cf6;--json-key-color: #a78bfa;--text-muted: #6e6e73;--text-secondary-light: #424245;--border-warm: rgba(15, 0, 0, .12);--border-tab: #9a9898;--border-outline: #646262;--input-bg: #f8f7f7;--bg-primary: var(--oc-dark);--bg-secondary: var(--oc-dark-surface);--bg-tertiary: rgba(253, 252, 252, .04);--bg-hover: rgba(253, 252, 252, .08);--text-primary: var(--oc-light);--text-secondary: var(--oc-mid);--text-tertiary: var(--text-muted);--border: rgba(100, 98, 98, .25);--added-bg: rgba(48, 209, 88, .08);--added-border: var(--success);--removed-bg: rgba(255, 59, 48, .08);--removed-border: var(--danger);--radius: 4px;--radius-input: 6px;--font-family: "Berkeley Mono", "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}[data-theme=light]{--bg-primary: var(--oc-light);--bg-secondary: var(--oc-light-surface);--bg-tertiary: rgba(32, 29, 29, .04);--bg-hover: rgba(32, 29, 29, .06);--text-primary: var(--oc-dark);--text-secondary: var(--text-secondary-light);--text-tertiary: var(--oc-mid);--border: var(--border-warm);--added-bg: rgba(48, 209, 88, .06);--added-border: #1a8a3d;--removed-bg: rgba(255, 59, 48, .06);--removed-border: #c41e3a}html,body{height:100%;font-family:var(--font-family);background:var(--bg-primary);color:var(--text-primary);line-height:1.5;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}a{color:var(--accent);text-decoration:underline;font-weight:500;transition:color .1s}a:hover{color:var(--accent-hover)}button{font-family:inherit;cursor:pointer;border:none;background:none;color:inherit;font-size:inherit}.skip-link{position:absolute;top:-100px;left:50%;transform:translate(-50%);padding:8px 16px;background:var(--accent);color:var(--oc-light);font-weight:500;border-radius:var(--radius);z-index:1000;transition:top .2s}.skip-link:focus{top:8px}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}#app{display:flex;flex-direction:column;height:100vh;overflow:hidden}main{flex:1;overflow-y:auto;padding:24px;-webkit-overflow-scrolling:touch}.container{max-width:1200px;margin:0 auto}.spinner{width:20px;height:20px;border:2px solid var(--border);border-top-color:var(--accent);border-radius:50%;animation:spin .6s linear infinite;display:inline-block;vertical-align:middle;margin-right:8px}@keyframes spin{to{transform:rotate(360deg)}}.loading{display:flex;align-items:center;justify-content:center;padding:48px;color:var(--text-secondary);font-size:14px}.empty-state{text-align:center;padding:64px 24px;color:var(--text-secondary)}.empty-state .icon{font-size:48px;margin-bottom:16px}.empty-state p{font-size:16px;margin-bottom:8px}.error-banner{padding:16px 20px;background:var(--removed-bg);border:1px solid var(--removed-border);border-radius:var(--radius);color:var(--danger);font-size:14px}.page-title{font-size:38px;font-weight:700;line-height:1.5;margin-bottom:24px;display:flex;align-items:baseline;gap:12px;flex-wrap:wrap}.page-title .count{font-size:16px;font-weight:500;color:var(--text-secondary)}.page-title .subtitle{font-size:16px;font-weight:400;color:var(--text-tertiary)}.card{background:var(--bg-secondary);border:1px solid var(--border);border-radius:var(--radius)}.card-interactive{cursor:pointer;transition:background .1s,border-color .1s}.card-interactive:hover{background:var(--bg-hover)}.card-interactive:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.badge{display:inline-flex;align-items:center;padding:2px 8px;font-size:12px;font-weight:500;color:var(--text-secondary);background:var(--bg-tertiary);border-radius:var(--radius);white-space:nowrap}code{background:var(--bg-tertiary);padding:2px 6px;border-radius:var(--radius);font-family:var(--font-family);font-size:13px}kbd{display:inline-block;padding:2px 8px;font-size:12px;font-family:var(--font-family);background:var(--bg-tertiary);border:1px solid var(--border);border-radius:var(--radius);min-width:24px;text-align:center}.section-title{display:flex;align-items:center;gap:8px;font-size:13px;font-weight:700;padding:8px 12px;background:var(--bg-tertiary);border-radius:var(--radius);margin-bottom:8px;cursor:pointer;-webkit-user-select:none;user-select:none;transition:background .1s}.section-title:hover{background:var(--bg-hover)}.section-arrow{transition:transform .2s ease;color:var(--text-secondary)}.section-title.expanded .section-arrow{transform:rotate(0)}.section-title:not(.expanded) .section-arrow{transform:rotate(-90deg)}