@jpkme/diff-review 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +99 -0
  3. package/bin/diff-review.mjs +175 -0
  4. package/package.json +53 -0
  5. package/schema.json +158 -0
  6. package/web/build/client/_app/immutable/assets/0.CLQiq3Ed.css +1 -0
  7. package/web/build/client/_app/immutable/assets/0.CLQiq3Ed.css.br +0 -0
  8. package/web/build/client/_app/immutable/assets/0.CLQiq3Ed.css.gz +0 -0
  9. package/web/build/client/_app/immutable/assets/2.CHpfuCyA.css +1 -0
  10. package/web/build/client/_app/immutable/assets/2.CHpfuCyA.css.br +0 -0
  11. package/web/build/client/_app/immutable/assets/2.CHpfuCyA.css.gz +0 -0
  12. package/web/build/client/_app/immutable/assets/3.BiNtcbA-.css +1 -0
  13. package/web/build/client/_app/immutable/assets/3.BiNtcbA-.css.br +0 -0
  14. package/web/build/client/_app/immutable/assets/3.BiNtcbA-.css.gz +0 -0
  15. package/web/build/client/_app/immutable/assets/ThemeToggle.DcT79vPK.css +1 -0
  16. package/web/build/client/_app/immutable/assets/ThemeToggle.DcT79vPK.css.br +0 -0
  17. package/web/build/client/_app/immutable/assets/ThemeToggle.DcT79vPK.css.gz +0 -0
  18. package/web/build/client/_app/immutable/chunks/BZfQ9INH.js +1 -0
  19. package/web/build/client/_app/immutable/chunks/BZfQ9INH.js.br +0 -0
  20. package/web/build/client/_app/immutable/chunks/BZfQ9INH.js.gz +0 -0
  21. package/web/build/client/_app/immutable/chunks/Bjy-W4x2.js +81 -0
  22. package/web/build/client/_app/immutable/chunks/Bjy-W4x2.js.br +0 -0
  23. package/web/build/client/_app/immutable/chunks/Bjy-W4x2.js.gz +0 -0
  24. package/web/build/client/_app/immutable/chunks/Czsj8nEn.js +114 -0
  25. package/web/build/client/_app/immutable/chunks/Czsj8nEn.js.br +0 -0
  26. package/web/build/client/_app/immutable/chunks/Czsj8nEn.js.gz +0 -0
  27. package/web/build/client/_app/immutable/chunks/DWi-qjc4.js +2 -0
  28. package/web/build/client/_app/immutable/chunks/DWi-qjc4.js.br +0 -0
  29. package/web/build/client/_app/immutable/chunks/DWi-qjc4.js.gz +0 -0
  30. package/web/build/client/_app/immutable/chunks/Dur-vdUf.js +3 -0
  31. package/web/build/client/_app/immutable/chunks/Dur-vdUf.js.br +0 -0
  32. package/web/build/client/_app/immutable/chunks/Dur-vdUf.js.gz +0 -0
  33. package/web/build/client/_app/immutable/chunks/tYeNsyIK.js +1 -0
  34. package/web/build/client/_app/immutable/chunks/tYeNsyIK.js.br +0 -0
  35. package/web/build/client/_app/immutable/chunks/tYeNsyIK.js.gz +0 -0
  36. package/web/build/client/_app/immutable/entry/app.BTcBsRpu.js +2 -0
  37. package/web/build/client/_app/immutable/entry/app.BTcBsRpu.js.br +0 -0
  38. package/web/build/client/_app/immutable/entry/app.BTcBsRpu.js.gz +0 -0
  39. package/web/build/client/_app/immutable/entry/start.kanpokEP.js +1 -0
  40. package/web/build/client/_app/immutable/entry/start.kanpokEP.js.br +1 -0
  41. package/web/build/client/_app/immutable/entry/start.kanpokEP.js.gz +0 -0
  42. package/web/build/client/_app/immutable/nodes/0.s5xmjXoS.js +1 -0
  43. package/web/build/client/_app/immutable/nodes/0.s5xmjXoS.js.br +1 -0
  44. package/web/build/client/_app/immutable/nodes/0.s5xmjXoS.js.gz +0 -0
  45. package/web/build/client/_app/immutable/nodes/1.CgR83Zma.js +1 -0
  46. package/web/build/client/_app/immutable/nodes/1.CgR83Zma.js.br +0 -0
  47. package/web/build/client/_app/immutable/nodes/1.CgR83Zma.js.gz +0 -0
  48. package/web/build/client/_app/immutable/nodes/2.CQ9hcOOu.js +66 -0
  49. package/web/build/client/_app/immutable/nodes/2.CQ9hcOOu.js.br +0 -0
  50. package/web/build/client/_app/immutable/nodes/2.CQ9hcOOu.js.gz +0 -0
  51. package/web/build/client/_app/immutable/nodes/3.DkvQklXV.js +170 -0
  52. package/web/build/client/_app/immutable/nodes/3.DkvQklXV.js.br +0 -0
  53. package/web/build/client/_app/immutable/nodes/3.DkvQklXV.js.gz +0 -0
  54. package/web/build/client/_app/version.json +1 -0
  55. package/web/build/client/_app/version.json.br +0 -0
  56. package/web/build/client/_app/version.json.gz +0 -0
  57. package/web/build/env.js +70 -0
  58. package/web/build/env.js.map +1 -0
  59. package/web/build/handler.js +16 -0
  60. package/web/build/handler.js.map +1 -0
  61. package/web/build/index.js +139 -0
  62. package/web/build/index.js.map +1 -0
  63. package/web/build/server/chunks/0-SseDy__O.js +11 -0
  64. package/web/build/server/chunks/0-SseDy__O.js.map +1 -0
  65. package/web/build/server/chunks/1-D4XIiB5g.js +7 -0
  66. package/web/build/server/chunks/1-D4XIiB5g.js.map +1 -0
  67. package/web/build/server/chunks/2-VwXkm01F.js +7 -0
  68. package/web/build/server/chunks/2-VwXkm01F.js.map +1 -0
  69. package/web/build/server/chunks/3-g6WScD1p.js +7 -0
  70. package/web/build/server/chunks/3-g6WScD1p.js.map +1 -0
  71. package/web/build/server/chunks/handler-UGld1DQG.js +1473 -0
  72. package/web/build/server/chunks/handler-UGld1DQG.js.map +1 -0
  73. package/web/build/server/chunks/hooks.server-DERFlOe1.js +14 -0
  74. package/web/build/server/chunks/hooks.server-DERFlOe1.js.map +1 -0
  75. package/web/build/server/chunks/index.js-A_Q670iW.js +11784 -0
  76. package/web/build/server/chunks/index.js-A_Q670iW.js.map +1 -0
  77. package/web/build/server/chunks/manifest.js-CbjlFtox.js +50 -0
  78. package/web/build/server/chunks/manifest.js-CbjlFtox.js.map +1 -0
  79. package/web/build/server/chunks/remote-1g4ayag-ipWXvkjB.js +2239 -0
  80. package/web/build/server/chunks/remote-1g4ayag-ipWXvkjB.js.map +1 -0
  81. package/web/build/shims.js +33 -0
  82. package/web/build/shims.js.map +1 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 juanpablocamejo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,99 @@
1
+ # diff-review
2
+
3
+ App local para revisar un branch: generás un prompt, lo corrés vos con tu agente
4
+ (Claude, Cursor, Copilot, etc.), soltás el JSON que te devuelve, y la UI completa
5
+ los diffs con `git` y te deja triager hallazgos.
6
+
7
+ No spawnea agentes ni corre reviews sola: el modelo lo manejás vos a mano.
8
+
9
+ ## Instalación
10
+
11
+ Requiere **Node ≥ 20** y **git** en el PATH. En Windows/macOS/Linux x64 el diálogo
12
+ de carpeta usa `@bindrs/rfd` (nativo); si el addon no está para tu plataforma, hay fallback.
13
+
14
+ ```bash
15
+ npm install -g @jpkme/diff-review
16
+ diff-review
17
+ ```
18
+
19
+ O sin instalar:
20
+
21
+ ```bash
22
+ npx @jpkme/diff-review
23
+ ```
24
+
25
+ Abre `http://127.0.0.1:5190`. Opciones: `--port`, `--host`, `--no-open`.
26
+
27
+ ## Desarrollo (desde el repo)
28
+
29
+ ```bash
30
+ npm run web:install
31
+ npm run web:dev # UI en modo dev
32
+ npm run build # build de producción → web/build
33
+ npm start # mismo que el bin global
34
+ ```
35
+
36
+ ## Flujo
37
+
38
+ 1. Pegá la ruta (o URL) del repo y elegí branch / base.
39
+ 2. Copiá el prompt (o el comando de skill `/diff-review`).
40
+ 3. Corrélo en tu agente; que escriba `diff-review-output.json`.
41
+ 4. Arrastrá ese JSON a la dropzone. La UI hidrata los diffs con git.
42
+
43
+ "Ver ejemplo" carga un reporte de muestra sin tocar un repo.
44
+
45
+ ## Qué hace git (en tu máquina)
46
+
47
+ Al abrir un reporte, el backend local corre `git` contra el repo que indicaste
48
+ para armar los diffs y, si pedís contexto faltante, leer el archivo en la punta
49
+ del branch. Por eso corre en localhost, no como SaaS.
50
+
51
+ Los reportes y el triage viven en **localStorage** del navegador.
52
+
53
+ ## Qué se reporta y qué no
54
+
55
+ Los hallazgos tienen dos ejes. `class=risk` es lo que puede romper en producción
56
+ o al mergear, y solo eso puede marcar `blocking`. `class=quality` son mejoras
57
+ reales de mantenibilidad y nunca frenan un merge.
58
+
59
+ No se reporta lo que ya cazan el linter, el typechecker, el formatter o el CI,
60
+ ni preferencias de estilo sin consecuencia, ni "falta documentación" sin un
61
+ escenario concreto que se rompa.
62
+
63
+ ## Configuración del repo revisado
64
+
65
+ Poné `.diff-review.yml` (o `.json`) y `REVIEW.md` en el repo que revisás:
66
+
67
+ ```yaml
68
+ # .diff-review.yml
69
+ ignore:
70
+ - "**/Generated/**"
71
+ rulesFile: REVIEW.md # default
72
+ ```
73
+
74
+ `REVIEW.md` son reglas del equipo que van en el prompt. También se cargan
75
+ `CLAUDE.md` y `AGENTS.md` de la raíz y de cada carpeta de los archivos tocados.
76
+ Por default se ignoran lockfiles, `*.g.cs`, snapshots EF, `node_modules`, builds
77
+ y minificados.
78
+
79
+ ## Estructura
80
+
81
+ ```
82
+ .
83
+ ├── bin/ # CLI (diff-review)
84
+ ├── schema.json # contrato del JSON que escribe el agente
85
+ ├── lib/ # git / extract (dev + tests; va embebido en el build)
86
+ └── web/ # UI SvelteKit → web/build en el paquete npm
87
+ ```
88
+
89
+ Tests del pipeline: `npm test` (`node --test lib/*.test.mjs`).
90
+
91
+ ## Publicar
92
+
93
+ ```bash
94
+ npm run build # o se corre solo en prepack (incluye web:install)
95
+ npm publish
96
+ ```
97
+
98
+ Paquete: `@jpkme/diff-review` (el comando global sigue siendo `diff-review`).
99
+ El tarball incluye `web/build` (sin depender de las deps de Svelte en runtime).
@@ -0,0 +1,175 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CLI: levanta la UI local (build de SvelteKit) y abre el browser.
4
+ *
5
+ * diff-review
6
+ * diff-review --port 5191
7
+ * diff-review --no-open
8
+ */
9
+
10
+ import { spawn, spawnSync } from 'node:child_process';
11
+ import { existsSync } from 'node:fs';
12
+ import { createServer } from 'node:net';
13
+ import { dirname, join } from 'node:path';
14
+ import { fileURLToPath } from 'node:url';
15
+
16
+ const here = dirname(fileURLToPath(import.meta.url));
17
+ const packageRoot = join(here, '..');
18
+ const buildDir = join(packageRoot, 'web', 'build');
19
+ const entry = join(buildDir, 'index.js');
20
+
21
+ const DEFAULT_HOST = '127.0.0.1';
22
+ const DEFAULT_PORT = 5190;
23
+
24
+ /** El server debe ser Node: Bun como runtime hijo suele romper diálogos nativos de Windows. */
25
+ function resolveNodeBin() {
26
+ if (process.execPath && /node(\.exe)?$/i.test(process.execPath)) return process.execPath;
27
+ const which = spawnSync(process.platform === 'win32' ? 'where.exe' : 'which', ['node'], {
28
+ encoding: 'utf8',
29
+ windowsHide: true
30
+ });
31
+ const first = String(which.stdout || '')
32
+ .split(/\r?\n/)
33
+ .map((s) => s.trim())
34
+ .find(Boolean);
35
+ if (first) return first;
36
+ return 'node';
37
+ }
38
+
39
+ function printHelp() {
40
+ console.log(`diff-review — UI local para revisar un branch con tu agente.
41
+
42
+ Usage:
43
+ diff-review [options]
44
+
45
+ Options:
46
+ -p, --port <n> Puerto (default ${DEFAULT_PORT})
47
+ --host <h> Host (default ${DEFAULT_HOST})
48
+ --no-open No abrir el navegador
49
+ -h, --help Esta ayuda
50
+
51
+ Requiere git en PATH. Los reportes viven en localStorage del navegador.
52
+ `);
53
+ }
54
+
55
+ function parseArgs(argv) {
56
+ const opts = { port: DEFAULT_PORT, host: DEFAULT_HOST, open: true, help: false };
57
+ for (let i = 0; i < argv.length; i++) {
58
+ const a = argv[i];
59
+ if (a === '-h' || a === '--help') opts.help = true;
60
+ else if (a === '--no-open') opts.open = false;
61
+ else if (a === '--host') opts.host = argv[++i] || opts.host;
62
+ else if (a === '-p' || a === '--port') {
63
+ const n = Number(argv[++i]);
64
+ if (!Number.isFinite(n) || n <= 0) {
65
+ console.error(`Puerto inválido: ${argv[i]}`);
66
+ process.exit(1);
67
+ }
68
+ opts.port = Math.floor(n);
69
+ } else if (a.startsWith('-')) {
70
+ console.error(`Opción desconocida: ${a}`);
71
+ printHelp();
72
+ process.exit(1);
73
+ }
74
+ }
75
+ return opts;
76
+ }
77
+
78
+ function openBrowser(url) {
79
+ try {
80
+ if (process.platform === 'win32') {
81
+ spawn('cmd', ['/c', 'start', '', url], { stdio: 'ignore', detached: true }).unref();
82
+ } else if (process.platform === 'darwin') {
83
+ spawn('open', [url], { stdio: 'ignore', detached: true }).unref();
84
+ } else {
85
+ spawn('xdg-open', [url], { stdio: 'ignore', detached: true }).unref();
86
+ }
87
+ } catch {
88
+ /* el usuario puede abrir la URL a mano */
89
+ }
90
+ }
91
+
92
+ /** Hipervínculo OSC 8 (Windows Terminal, VS Code, iTerm, Zed, etc.). */
93
+ function terminalLink(url, label = url) {
94
+ return `\x1b]8;;${url}\x07${label}\x1b]8;;\x07`;
95
+ }
96
+
97
+ function canListen(host, port) {
98
+ return new Promise((resolve) => {
99
+ const server = createServer();
100
+ server.once('error', () => resolve(false));
101
+ server.once('listening', () => {
102
+ server.close(() => resolve(true));
103
+ });
104
+ server.listen(port, host);
105
+ });
106
+ }
107
+
108
+ async function main() {
109
+ const opts = parseArgs(process.argv.slice(2));
110
+ if (opts.help) {
111
+ printHelp();
112
+ process.exit(0);
113
+ }
114
+
115
+ if (!existsSync(entry)) {
116
+ console.error(`No encontré el build en ${entry}
117
+ Corré desde el repo: npm run build
118
+ O reinstalá el paquete (el tarball de npm incluye el build).`);
119
+ process.exit(1);
120
+ }
121
+
122
+ if (!(await canListen(opts.host, opts.port))) {
123
+ console.error(`No se pudo usar ${opts.host}:${opts.port} (¿ocupado?). Probá --port otro.`);
124
+ process.exit(1);
125
+ }
126
+
127
+ const origin = `http://${opts.host}:${opts.port}`;
128
+ const nodeBin = resolveNodeBin();
129
+ const child = spawn(nodeBin, [entry], {
130
+ cwd: buildDir,
131
+ env: {
132
+ ...process.env,
133
+ HOST: opts.host,
134
+ PORT: String(opts.port),
135
+ ORIGIN: origin
136
+ },
137
+ stdio: ['ignore', 'pipe', 'inherit'],
138
+ windowsHide: false
139
+ });
140
+
141
+ let ready = false;
142
+ let stdoutBuf = '';
143
+ child.stdout?.on('data', (chunk) => {
144
+ stdoutBuf += String(chunk);
145
+ const parts = stdoutBuf.split(/\r?\n/);
146
+ stdoutBuf = parts.pop() ?? '';
147
+ for (const line of parts) {
148
+ if (/Listening on/i.test(line)) {
149
+ if (!ready) {
150
+ ready = true;
151
+ console.log(`diff-review listo en ${terminalLink(origin)} — Ctrl+C para salir.`);
152
+ if (opts.open) openBrowser(origin);
153
+ }
154
+ continue;
155
+ }
156
+ if (line.length) process.stdout.write(`${line}\n`);
157
+ }
158
+ });
159
+ child.on('error', (err) => {
160
+ console.error('No se pudo arrancar el server:', err.message);
161
+ process.exit(1);
162
+ });
163
+ child.on('exit', (code, signal) => {
164
+ if (signal) process.exit(0);
165
+ process.exit(code ?? 1);
166
+ });
167
+
168
+ const stop = () => {
169
+ if (!child.killed) child.kill('SIGTERM');
170
+ };
171
+ process.on('SIGINT', stop);
172
+ process.on('SIGTERM', stop);
173
+ }
174
+
175
+ main();
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@jpkme/diff-review",
3
+ "version": "0.1.0",
4
+ "description": "Local UI to prompt a coding agent for a branch review and browse the result.",
5
+ "type": "module",
6
+ "bin": {
7
+ "diff-review": "bin/diff-review.mjs"
8
+ },
9
+ "files": [
10
+ "bin",
11
+ "web/build",
12
+ "schema.json",
13
+ "README.md",
14
+ "LICENSE"
15
+ ],
16
+ "scripts": {
17
+ "test": "node --test lib/*.test.mjs",
18
+ "web:install": "npm --prefix web install",
19
+ "web:dev": "npm --prefix web run dev",
20
+ "web:build": "npm --prefix web run build",
21
+ "web:check": "npm --prefix web run type-check",
22
+ "build": "npm run web:build",
23
+ "prepack": "npm run web:install && npm run build",
24
+ "start": "node bin/diff-review.mjs",
25
+ "diff-review": "node bin/diff-review.mjs"
26
+ },
27
+ "engines": {
28
+ "node": ">=20"
29
+ },
30
+ "keywords": [
31
+ "code-review",
32
+ "git",
33
+ "diff",
34
+ "local",
35
+ "sveltekit"
36
+ ],
37
+ "author": "jpkme",
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "git+https://github.com/juanpablocamejo/diff-review.git"
41
+ },
42
+ "bugs": {
43
+ "url": "https://github.com/juanpablocamejo/diff-review/issues"
44
+ },
45
+ "homepage": "https://github.com/juanpablocamejo/diff-review#readme",
46
+ "license": "MIT",
47
+ "publishConfig": {
48
+ "access": "public"
49
+ },
50
+ "dependencies": {
51
+ "@bindrs/rfd": "^2.2.2"
52
+ }
53
+ }
package/schema.json ADDED
@@ -0,0 +1,158 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/juanpablocamejo/diff-review/schemas/review-document.json",
4
+ "title": "Diff Review Document",
5
+ "description": "JSON que escribe el agente (meta/intent/groups/blocks/findings/skipped). La UI completa files con git al abrir el reporte; no hace falta que el modelo incluya diffs.",
6
+ "type": "object",
7
+ "required": ["intent", "groups", "blocks", "findings"],
8
+ "properties": {
9
+ "meta": {
10
+ "type": "object",
11
+ "description": "Contexto del repo para reabrir el reporte sin rellenar el formulario. Copiá source/repo/branch/base del prompt.",
12
+ "required": ["source", "repo", "branch", "base"],
13
+ "properties": {
14
+ "source": { "type": "string", "enum": ["local", "url"] },
15
+ "repo": {
16
+ "type": "string",
17
+ "description": "Ruta absoluta local o URL git (https://… / git@…)."
18
+ },
19
+ "branch": { "type": "string", "description": "Branch bajo review." },
20
+ "base": { "type": "string", "description": "Branch base del merge-base (ej. develop)." },
21
+ "remoteUrl": {
22
+ "type": "string",
23
+ "description": "URL del remote (origin). Fallback si la carpeta local no existe en otra máquina."
24
+ }
25
+ }
26
+ },
27
+
28
+ "intent": {
29
+ "type": "string",
30
+ "description": "Intención general del diff en 2-4 oraciones: qué problema resuelve, no qué archivos toca."
31
+ },
32
+
33
+ "groups": {
34
+ "type": "array",
35
+ "minItems": 1,
36
+ "description": "Temas del diff. El orden refleja dependencias: si g2 usa lo que introduce g1, g1 va antes.",
37
+ "items": {
38
+ "type": "object",
39
+ "required": ["id", "kind", "title", "intent"],
40
+ "properties": {
41
+ "id": { "type": "string", "pattern": "^g[0-9]+$" },
42
+ "kind": {
43
+ "type": "string",
44
+ "enum": ["feat", "fix", "refactor", "perf", "test", "chore", "docs", "infra"]
45
+ },
46
+ "title": {
47
+ "type": "string",
48
+ "maxLength": 72,
49
+ "description": "Resumen del tema en una línea sin repetir kind (el chip ya lo muestra), ej. 'warehouses: CRUD de depósitos locales' o 'product: alta de depósitos'."
50
+ },
51
+ "intent": { "type": "string", "maxLength": 240, "description": "Por qué existe este tema." }
52
+ }
53
+ }
54
+ },
55
+
56
+ "blocks": {
57
+ "type": "array",
58
+ "minItems": 1,
59
+ "description": "Diccionario de tramos. Un bloque puede abarcar varios hunks contiguos del mismo archivo con el mismo motivo.",
60
+ "items": {
61
+ "type": "object",
62
+ "required": ["id", "group", "file", "lines", "op", "what"],
63
+ "properties": {
64
+ "id": { "type": "string", "pattern": "^b[0-9]+$" },
65
+ "group": { "type": "string", "pattern": "^g[0-9]+$" },
66
+ "file": { "type": "string", "description": "Path relativo exacto del archivo en el diff." },
67
+ "lines": {
68
+ "type": "string",
69
+ "description": "Rango post-imagen: 'L40-58' o 'L40'. Con guion adelante si es pre-imagen (borrado): '-L88-95'."
70
+ },
71
+ "side": { "type": "string", "enum": ["new", "old"] },
72
+ "start": { "type": "integer", "minimum": 1 },
73
+ "end": { "type": "integer", "minimum": 1 },
74
+ "op": { "type": "string", "enum": ["add", "mod", "del", "rename"] },
75
+ "what": {
76
+ "type": "string",
77
+ "maxLength": 200,
78
+ "description": "Qué cambia este bloque."
79
+ },
80
+ "why": {
81
+ "type": "string",
82
+ "maxLength": 200,
83
+ "description": "Por qué. Vacío solo si no es inferible."
84
+ },
85
+ "source": {
86
+ "type": "string",
87
+ "enum": ["code", "commit", "pr", "issue", "inferred"]
88
+ }
89
+ }
90
+ }
91
+ },
92
+
93
+ "findings": {
94
+ "type": "array",
95
+ "description": "class=risk son riesgos de merge; class=quality son mejoras de calidad.",
96
+ "items": {
97
+ "type": "object",
98
+ "required": ["id", "class", "severity", "blocking", "kind", "file", "what", "fix"],
99
+ "properties": {
100
+ "id": { "type": "string", "pattern": "^f[0-9]+$" },
101
+ "class": { "type": "string", "enum": ["risk", "quality"] },
102
+ "severity": { "type": "string", "enum": ["high", "med", "low", "nit"] },
103
+ "blocking": {
104
+ "type": "boolean",
105
+ "description": "true = no debería mergearse así. Solo con class=risk."
106
+ },
107
+ "kind": {
108
+ "type": "string",
109
+ "enum": ["bug", "race", "auth", "security", "api-break", "missing-test", "perf", "maintainability", "docs", "other"]
110
+ },
111
+ "file": { "type": "string" },
112
+ "line": { "type": ["integer", "null"], "description": "Línea de la post-imagen (columna derecha / @@ +N)." },
113
+ "block": { "type": ["string", "null"], "description": "Id del bloque, o vacío/null si es transversal." },
114
+ "what": { "type": "string", "maxLength": 300 },
115
+ "fix": { "type": "string", "maxLength": 300, "description": "Acción concreta." }
116
+ }
117
+ }
118
+ },
119
+
120
+ "skipped": {
121
+ "type": "array",
122
+ "description": "Archivos del diff que no se explican, con motivo (o glob).",
123
+ "items": {
124
+ "type": "object",
125
+ "required": ["file", "reason"],
126
+ "properties": {
127
+ "file": { "type": "string" },
128
+ "reason": {
129
+ "type": "string",
130
+ "enum": ["generated", "lockfile", "format", "vendored", "binary", "trivial", "ignored"]
131
+ }
132
+ }
133
+ }
134
+ },
135
+
136
+ "files": {
137
+ "type": "array",
138
+ "description": "Diffs para renderizar. Los llena la UI con git; el agente no los incluye.",
139
+ "items": {
140
+ "type": "object",
141
+ "required": ["path", "changeType", "diff"],
142
+ "properties": {
143
+ "path": { "type": "string" },
144
+ "oldPath": { "type": "string" },
145
+ "changeType": { "type": "string", "enum": ["added", "modified", "deleted", "renamed"] },
146
+ "diff": { "type": "string" },
147
+ "group": { "type": "string" }
148
+ }
149
+ }
150
+ },
151
+
152
+ "notes": {
153
+ "type": "array",
154
+ "description": "Avisos breves sobre limitaciones de la review, si aplica.",
155
+ "items": { "type": "string" }
156
+ }
157
+ }
158
+ }
@@ -0,0 +1 @@
1
+ :root{--bg:#0b0e14;--bg-elev:#11151d;--bg-card:#151a24;--bg-card-hover:#1a2130;--border:#242b3a;--border-soft:#1c2230;--text:#e6e9ef;--text-dim:#9aa4b8;--text-faint:#5f6b82;--accent:#6ea8fe;--accent-soft:#1c2b45;--ok:#7ee2a8;--ok-bg:#0d2a1c;--warn:#e2c67e;--danger:#ff9a9a;--danger-bg:#2a1414;--danger-border:#4a1e1e;--mono:ui-monospace, "JetBrains Mono", "Fira Code", Consolas, "SFMono-Regular", Menlo, monospace;--sans:-apple-system, "Segoe UI", Inter, Roboto, Helvetica, Arial, sans-serif;--btn-primary-bg:#1c2b45;--btn-primary-border:#3a5a8f;--btn-primary-text:#cfe0ff;--kind-feat:#7ee2a8;--kind-fix:#ff9a9a;--kind-refactor:#c9a5ff;--kind-perf:#e2c67e;--kind-test:#6ea8fe;--kind-chore:#9aa4b8;--kind-docs:#7fd6e0;--kind-infra:#f0a868;--sev-high:#ff9a9a;--sev-med:#f08a5a;--sev-low:#c4b86a;--sev-nit:#7f8aa3;--diff-add-bg:#0f2419;--diff-add-fg:#7ee2a8;--diff-del-bg:#2a1418;--diff-del-fg:#ff9a9a;--diff-hunk-bg:#141924;--diff-gutter:#46516a;--diff-mark:#2b3f63;--diff-mark-edge:#6ea8fe;--diff-add-strong:#1f6b3c;--diff-del-strong:#6d2530;--diff-blank-bg:repeating-linear-gradient(135deg, #11151d 0 6px, #151a24 6px 12px);--fix-bg:#0e1a13;--fix-border:#2f6b46;--fix-text:#7ee2a8;--publish-bg:#0e1622;--publish-border:#3a5a8f;--publish-text:#7db8ff;--scrollbar-thumb:#2a3348;--scrollbar-thumb-hover:#3a4660;--selection-bg:#33507a;--header-bg:#0b0e14eb}:root[data-theme=light]{--bg:#fff;--bg-elev:#f6f7f9;--bg-card:#eef0f3;--bg-card-hover:#e4e7ec;--border:#d7dbe2;--border-soft:#e4e7ec;--text:#16181d;--text-dim:#4b5563;--text-faint:#6b7280;--accent:#2f6fe0;--accent-soft:#dce8ff;--ok:#1f9d55;--ok-bg:#e3f8ea;--warn:#a5720a;--danger:#c92a2a;--danger-bg:#fbe4e4;--danger-border:#f3b4b4;--btn-primary-bg:#2f6fe0;--btn-primary-border:#2358b8;--btn-primary-text:#fff;--kind-feat:#1f9d55;--kind-fix:#c92a2a;--kind-refactor:#7c4dd6;--kind-perf:#a5720a;--kind-test:#2f6fe0;--kind-chore:#5b6472;--kind-docs:#0f8fa3;--kind-infra:#c1690f;--sev-high:#c92a2a;--sev-med:#c44d1a;--sev-low:#8b7d2e;--sev-nit:#6b7280;--diff-add-bg:#e6f7ec;--diff-add-fg:#1f9d55;--diff-del-bg:#fbe9e9;--diff-del-fg:#c92a2a;--diff-hunk-bg:#eef1f5;--diff-gutter:#9aa3b2;--diff-mark:#cfe0ff;--diff-mark-edge:#2f6fe0;--diff-add-strong:#a7ebbd;--diff-del-strong:#f9b8b8;--diff-blank-bg:repeating-linear-gradient(135deg, #f6f7f9 0 6px, #eef0f3 6px 12px);--fix-bg:#e6f7ec;--fix-border:#1f9d55;--fix-text:#157a41;--publish-bg:#e8f0fe;--publish-border:#2f6fe0;--publish-text:#1d4fa8;--scrollbar-thumb:#c7cbd4;--scrollbar-thumb-hover:#aab0bb;--selection-bg:#cfe0ff;--header-bg:#ffffffeb}.code .chg{border-radius:2px}.code.del .chg{background:var(--diff-del-strong)}.code.add .chg{background:var(--diff-add-strong)}.hljs-comment,.hljs-quote{color:#6b7689;font-style:italic}.hljs-keyword,.hljs-selector-tag,.hljs-literal,.hljs-doctag,.hljs-formula{color:#c9a5ff}.hljs-string,.hljs-regexp,.hljs-addition,.hljs-attribute,.hljs-meta .hljs-string{color:#a5d6a7}.hljs-number,.hljs-variable,.hljs-template-variable,.hljs-type,.hljs-selector-class,.hljs-selector-attr,.hljs-selector-pseudo{color:#f0a868}.hljs-title,.hljs-section,.hljs-title.class_,.hljs-title.function_{color:#7fd6e0}.hljs-attr,.hljs-property,.hljs-symbol,.hljs-bullet,.hljs-link{color:#6ea8fe}.hljs-built_in,.hljs-class,.hljs-params{color:#e6e9ef}.hljs-meta,.hljs-tag{color:#9aa4b8}:root[data-theme=light] .hljs-comment,:root[data-theme=light] .hljs-quote{color:#6b7280}:root[data-theme=light] .hljs-keyword,:root[data-theme=light] .hljs-selector-tag,:root[data-theme=light] .hljs-literal,:root[data-theme=light] .hljs-doctag,:root[data-theme=light] .hljs-formula{color:#7c4dd6}:root[data-theme=light] .hljs-string,:root[data-theme=light] .hljs-regexp,:root[data-theme=light] .hljs-addition,:root[data-theme=light] .hljs-attribute,:root[data-theme=light] .hljs-meta .hljs-string{color:#1f9d55}:root[data-theme=light] .hljs-number,:root[data-theme=light] .hljs-variable,:root[data-theme=light] .hljs-template-variable,:root[data-theme=light] .hljs-type,:root[data-theme=light] .hljs-selector-class,:root[data-theme=light] .hljs-selector-attr,:root[data-theme=light] .hljs-selector-pseudo{color:#b5650f}:root[data-theme=light] .hljs-title,:root[data-theme=light] .hljs-section,:root[data-theme=light] .hljs-title.class_,:root[data-theme=light] .hljs-title.function_{color:#0f8fa3}:root[data-theme=light] .hljs-attr,:root[data-theme=light] .hljs-property,:root[data-theme=light] .hljs-symbol,:root[data-theme=light] .hljs-bullet,:root[data-theme=light] .hljs-link{color:#2f6fe0}:root[data-theme=light] .hljs-built_in,:root[data-theme=light] .hljs-class,:root[data-theme=light] .hljs-params{color:#16181d}:root[data-theme=light] .hljs-meta,:root[data-theme=light] .hljs-tag{color:#5b6472}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.anchor-flash{animation:1.4s ease-out anchor-flash}@keyframes anchor-flash{0%{box-shadow:0 0 0 2px var(--accent)}to{box-shadow:0 0 0 2px #0000}}*{box-sizing:border-box}html,body{background:var(--bg);color:var(--text);font-family:var(--sans);min-height:100%;margin:0;padding:0}body{-webkit-font-smoothing:antialiased}button,input,select{font:inherit;color:inherit}button{cursor:pointer}::selection{background:var(--selection-bg)}html,body,*{scrollbar-width:thin;scrollbar-color:var(--scrollbar-thumb) transparent}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-thumb{background:var(--scrollbar-thumb);background-clip:padding-box;border:2px solid #0000;border-radius:999px}::-webkit-scrollbar-thumb:hover{background:var(--scrollbar-thumb-hover);background-clip:padding-box;border:2px solid #0000}::-webkit-scrollbar-corner{background:0 0}.boot.svelte-12qhfyh{color:var(--text-dim);font-family:var(--mono);padding:48px 28px;font-size:13px}.boot.svelte-12qhfyh button:where(.svelte-12qhfyh){background:var(--btn-primary-bg);border:1px solid var(--btn-primary-border);color:var(--btn-primary-text);border-radius:8px;margin-top:12px;padding:8px 14px}
@@ -0,0 +1 @@
1
+ .page.svelte-1uha8ag{flex-direction:column;min-height:100vh;display:flex}.topbar.svelte-1uha8ag{border-bottom:1px solid var(--border);background:var(--header-bg);z-index:5;justify-content:space-between;align-items:center;gap:12px;padding:16px 28px;display:flex;position:sticky;top:0}.brand.svelte-1uha8ag{color:var(--text);align-items:center;gap:10px;text-decoration:none;display:flex}.brand-dot.svelte-1uha8ag{background:linear-gradient(135deg,#6ea8fe,#c9a5ff);border-radius:50%;flex-shrink:0;width:9px;height:9px;box-shadow:0 0 12px #6ea8fe88}.title-block.svelte-1uha8ag{text-align:left;flex-direction:column;line-height:1.25;display:flex}.title-block.svelte-1uha8ag span:where(.svelte-1uha8ag):first-child{font-size:15px;font-weight:700}.title-block.svelte-1uha8ag small:where(.svelte-1uha8ag){color:var(--text-faint);font-size:11.5px;font-weight:400}.workspace.svelte-1uha8ag{flex:1;grid-template-columns:minmax(0,1fr) minmax(300px,380px);align-items:start;gap:28px;width:100%;max-width:1280px;margin:0 auto;padding:22px 28px 40px;display:grid;overflow:auto}.setup.svelte-1uha8ag{min-width:0}h2.svelte-1uha8ag{letter-spacing:.06em;text-transform:uppercase;color:var(--text-faint);margin:0 0 4px;font-size:13px;font-weight:600}.result-head.svelte-1uha8ag{margin-top:24px}.section-head.svelte-1uha8ag{justify-content:space-between;align-items:baseline;margin-top:22px;display:flex}.hint-text.svelte-1uha8ag{color:var(--text-dim);margin:0 0 12px;font-size:12.5px;line-height:1.5}.hint-text.svelte-1uha8ag code:where(.svelte-1uha8ag){font-family:var(--mono);color:var(--text);font-size:12px}.error-line.svelte-1uha8ag{color:var(--danger);margin:0 0 10px;font-size:12px}.ok-line.svelte-1uha8ag{color:var(--ok);margin:0 0 10px;font-size:12px}.row.svelte-1uha8ag{flex-wrap:wrap;gap:8px;display:flex}.field.svelte-1uha8ag{flex-direction:column;flex:1;gap:4px;min-width:180px;display:flex}.repo-field.svelte-1uha8ag{flex:2;min-width:280px}.field.svelte-1uha8ag span:where(.svelte-1uha8ag){color:var(--text-faint);font-size:11px}.repo-row.svelte-1uha8ag{gap:6px;display:flex}.source-toggle.svelte-1uha8ag{margin-bottom:10px}input[type=text].svelte-1uha8ag,select.svelte-1uha8ag{background:var(--bg-card);border:1px solid var(--border);flex:1;min-width:0;padding:9px 12px}button.svelte-1uha8ag{background:var(--bg-card);border:1px solid var(--border);color:var(--text);padding:9px 12px;font-size:12.5px}button.svelte-1uha8ag:hover:not(:disabled){border-color:var(--accent)}button.svelte-1uha8ag:disabled{opacity:.5;cursor:not-allowed}.mode-toggle.svelte-1uha8ag{border:1px solid var(--border);width:fit-content;margin-bottom:10px;display:flex;overflow:hidden}.mode-toggle.svelte-1uha8ag button:where(.svelte-1uha8ag){background:0 0;border:0;padding:6px 12px;font-size:12px}.mode-toggle.svelte-1uha8ag button:where(.svelte-1uha8ag)+button:where(.svelte-1uha8ag){border-left:1px solid var(--border)}.mode-toggle.svelte-1uha8ag button.on:where(.svelte-1uha8ag){background:var(--accent-soft)}textarea.svelte-1uha8ag{resize:vertical;background:var(--bg);border:1px solid var(--border);width:100%;height:220px;font-family:var(--mono);color:var(--text);padding:12px;font-size:12px;line-height:1.5}.command-box.svelte-1uha8ag{background:var(--bg);border:1px solid var(--border);padding:10px 12px;overflow:auto}.command-box.svelte-1uha8ag code:where(.svelte-1uha8ag){font-family:var(--mono);color:var(--text);white-space:nowrap;font-size:12.5px}.actions.svelte-1uha8ag{gap:8px;margin-top:10px;display:flex}button.primary.svelte-1uha8ag{background:var(--btn-primary-bg);border-color:var(--btn-primary-border);color:var(--btn-primary-text);font-weight:600}button.ghost.svelte-1uha8ag{color:var(--text-dim);background:0 0}.skill-block.svelte-1uha8ag{border-top:1px solid var(--border);margin-top:16px;padding-top:14px}.skill-block.svelte-1uha8ag h3:where(.svelte-1uha8ag){letter-spacing:.06em;text-transform:uppercase;color:var(--text-faint);margin:0 0 4px;font-size:11.5px;font-weight:650}.skill-buttons.svelte-1uha8ag{flex-wrap:wrap;gap:8px;display:flex}.coverage-box.svelte-1uha8ag{border:1px solid var(--border);border-left:3px solid var(--sev-med);background:var(--bg-card);flex-direction:column;gap:10px;margin-top:12px;padding:12px 14px;display:flex}.coverage-head.svelte-1uha8ag{flex-wrap:wrap;align-items:baseline;gap:8px;display:flex}.coverage-head.svelte-1uha8ag strong:where(.svelte-1uha8ag){color:var(--sev-med);font-size:13px}.coverage-head.svelte-1uha8ag span:where(.svelte-1uha8ag){color:var(--text-faint);font-size:11.5px}.coverage-box.svelte-1uha8ag summary:where(.svelte-1uha8ag){color:var(--text-dim);cursor:pointer;font-size:12px}.coverage-list.svelte-1uha8ag{max-height:180px;font-family:var(--mono);color:var(--text-faint);margin:8px 0 0;padding-left:18px;font-size:11px;overflow:auto}.coverage-box.svelte-1uha8ag textarea:where(.svelte-1uha8ag){resize:vertical;background:var(--bg);border:1px solid var(--border);width:100%;font-family:var(--mono);color:var(--text);padding:10px;font-size:11.5px;line-height:1.5}.coverage-actions.svelte-1uha8ag{flex-wrap:wrap;gap:8px;display:flex}.dropzone.svelte-1uha8ag{border:1.5px dashed var(--border);text-align:center;background:var(--bg-elev);padding:26px;transition:background .15s,border-color .15s}.dropzone.drag.svelte-1uha8ag{border-color:var(--accent);background:var(--accent-soft)}.dropzone.busy.svelte-1uha8ag{opacity:.7}.dropzone.svelte-1uha8ag p:where(.svelte-1uha8ag){color:var(--text-dim);margin:0 0 6px;font-size:14px}.visually-hidden.svelte-1uha8ag{clip:rect(0 0 0 0);width:1px;height:1px;position:absolute;overflow:hidden}.drop-errors.svelte-1uha8ag{background:var(--danger-bg);color:var(--danger);margin-top:10px;padding:10px 12px;font-size:12.5px}.drop-errors.svelte-1uha8ag strong:where(.svelte-1uha8ag){margin-bottom:4px;display:block}.drop-errors.svelte-1uha8ag ul:where(.svelte-1uha8ag){margin:0;padding-left:18px;line-height:1.6}.reports-col.svelte-1uha8ag{min-width:0;max-height:calc(100vh - 110px);position:sticky;top:88px;overflow:auto}.report-list.svelte-1uha8ag{flex-direction:column;gap:8px;margin:0;padding:0;list-style:none;display:flex}.report-item.svelte-1uha8ag{border:1px solid var(--border);background:var(--bg-card);align-items:stretch;display:flex;position:relative}.report-item.svelte-1uha8ag:hover{background:var(--bg-card-hover);border-color:#33507a}.report-card.svelte-1uha8ag{min-width:0;color:var(--text);flex:1;padding:12px 8px 12px 14px;text-decoration:none;display:block}.report-actions.svelte-1uha8ag{flex-shrink:0;padding:8px 8px 0 0;position:relative}.kebab.svelte-1uha8ag{width:26px;height:26px;color:var(--text-faint);cursor:pointer;background:0 0;border:1px solid #0000;justify-content:center;align-items:center;padding:0;display:inline-flex}.kebab.svelte-1uha8ag:hover{border-color:var(--border);color:var(--text);background:var(--bg)}.report-menu.svelte-1uha8ag{z-index:20;border:1px solid var(--border);background:var(--bg-card);min-width:140px;padding:4px;position:absolute;top:calc(100% - 2px);right:8px;box-shadow:0 8px 24px #0000002e}.report-menu.svelte-1uha8ag .menu-item:where(.svelte-1uha8ag){width:100%;color:var(--text);text-align:left;cursor:pointer;background:0 0;border:0;padding:8px 10px;font-size:12.5px;display:block}.report-menu.svelte-1uha8ag .menu-item:where(.svelte-1uha8ag):hover{background:var(--accent-soft)}.report-menu.svelte-1uha8ag .menu-item.danger:where(.svelte-1uha8ag){color:var(--danger)}.report-top.svelte-1uha8ag{justify-content:space-between;align-items:baseline;gap:12px;display:flex}.report-top.svelte-1uha8ag strong:where(.svelte-1uha8ag){font-size:14px}.when.svelte-1uha8ag{color:var(--text-dim);font-size:12px}.report-meta.svelte-1uha8ag{color:var(--text-dim);flex-wrap:wrap;align-items:center;gap:8px;margin-top:6px;font-size:12px;display:flex}.pill.svelte-1uha8ag{font-family:var(--mono);font-size:11px}.pill.bad.svelte-1uha8ag{color:var(--danger)}.report-intent.svelte-1uha8ag{color:var(--text-dim);-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;margin:8px 0 0;font-size:12.5px;line-height:1.45;display:-webkit-box;overflow:hidden}@media (width<=960px){.workspace.svelte-1uha8ag{grid-template-columns:1fr}.reports-col.svelte-1uha8ag{max-height:none;position:static}}
@@ -0,0 +1 @@
1
+ .diff-wrap.svelte-13r6alg{background:var(--bg);--ln-w:calc(var(--diff-font-size,11.5px) * 3.1);--sign-w:calc(var(--diff-font-size,11.5px) * 1.05);--divider-w:5px}.collapse-bar.svelte-13r6alg{background:var(--diff-hunk-bg);border-bottom:1px solid var(--border-soft);color:var(--text-faint);flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px;padding:5px 10px;font-size:10.5px;display:flex}.link.svelte-13r6alg{color:var(--accent);background:0 0;border:0;padding:0;font-size:10.5px;text-decoration:underline}.gap-bar.svelte-13r6alg{background:var(--diff-hunk-bg);border-top:1px solid var(--border-soft);border-bottom:1px solid var(--border-soft);align-items:center;gap:10px;padding:3px 10px;display:flex}.gap-actions.svelte-13r6alg{border:1px solid var(--border);flex-shrink:0;display:flex;overflow:hidden}.gap-actions.svelte-13r6alg button:where(.svelte-13r6alg){background:var(--bg-card);font-family:var(--mono);font-size:calc(var(--diff-font-size,11.5px) * .87);color:var(--text-dim);border:0;padding:1px 8px;line-height:1.5}.gap-actions.svelte-13r6alg button:where(.svelte-13r6alg)+button:where(.svelte-13r6alg){border-left:1px solid var(--border)}.gap-actions.svelte-13r6alg button:where(.svelte-13r6alg):hover:not(:disabled){background:var(--accent-soft);color:var(--text)}.gap-actions.svelte-13r6alg button:where(.svelte-13r6alg):disabled{opacity:.4;cursor:not-allowed}.gap-info.svelte-13r6alg{font-family:var(--mono);font-size:calc(var(--diff-font-size,11.5px) * .87);color:var(--text-faint);white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.empty.svelte-13r6alg{color:var(--text-faint);margin:0;padding:12px;font-size:11.5px}.diff.svelte-13r6alg,.hunk-header.svelte-13r6alg{font-family:var(--mono)}.diff.svelte-13r6alg{max-height:55vh;font-size:var(--diff-font-size,11.5px);overflow:auto}.diff.wrap.svelte-13r6alg{overflow-x:hidden}.diff.wrap.svelte-13r6alg .row:where(.svelte-13r6alg){width:auto;min-width:0}.diff.wrap.svelte-13r6alg .code:where(.svelte-13r6alg){white-space:pre-wrap;overflow-wrap:anywhere}.hunk-header.svelte-13r6alg{background:var(--diff-hunk-bg);border-top:1px solid var(--border-soft);border-bottom:1px solid var(--border-soft);font-size:calc(var(--diff-font-size,11.5px) * .913);color:var(--text-faint);white-space:nowrap;text-overflow:ellipsis;padding:3px 10px;overflow:hidden}.row.svelte-13r6alg{grid-template-columns:var(--ln-w) var(--ln-w) var(--sign-w) auto;border-left:2px solid #0000;width:max-content;min-width:100%;display:grid}.split-grid.svelte-13r6alg{align-items:stretch;display:grid}.srow.svelte-13r6alg{display:contents}.divider.svelte-13r6alg{background:var(--border-soft);cursor:col-resize;touch-action:none}.divider.svelte-13r6alg:hover,.divider.svelte-13r6alg:active{background:var(--accent)}.split-grid.svelte-13r6alg .code:where(.svelte-13r6alg){white-space:pre-wrap;overflow-wrap:anywhere}.ln.svelte-13r6alg{text-align:right;color:var(--diff-gutter);font-size:calc(var(--diff-font-size,11.5px) * .87);-webkit-user-select:none;user-select:none;font-variant-numeric:tabular-nums;border-left:2px solid #0000;padding-right:6px;overflow:hidden}.row.svelte-13r6alg .ln:where(.svelte-13r6alg){border-left:0}.sign.svelte-13r6alg{text-align:center;-webkit-user-select:none;user-select:none;color:var(--text-faint)}.sign.add.svelte-13r6alg{color:var(--diff-add-fg)}.sign.del.svelte-13r6alg{color:var(--diff-del-fg)}.code.svelte-13r6alg{white-space:pre;padding-right:10px}.row.add.svelte-13r6alg{background:var(--diff-add-bg)}.row.add.svelte-13r6alg .sign:where(.svelte-13r6alg){color:var(--diff-add-fg)}.row.del.svelte-13r6alg{background:var(--diff-del-bg)}.row.del.svelte-13r6alg .sign:where(.svelte-13r6alg){color:var(--diff-del-fg)}.file-icon.svelte-1dshc1f{flex-shrink:0;justify-content:center;align-items:center;display:inline-flex}.file-icon.svelte-1dshc1f svg{fill:currentColor;width:100%;height:100%}.resize-handle.svelte-ywcz8g{cursor:col-resize;z-index:2;touch-action:none;background:0 0;flex-shrink:0;width:6px;position:relative}.resize-handle.svelte-ywcz8g:after{content:"";background:0 0;width:2px;position:absolute;top:0;bottom:0;left:2px}.resize-handle.svelte-ywcz8g:hover:after,.resize-handle.dragging.svelte-ywcz8g:after{background:var(--accent)}.explore.svelte-1k3qopq{display:contents}.blocker-bar.svelte-1k3qopq{background:var(--danger-bg);border:1px solid var(--danger-border);color:var(--danger);margin:0;padding:10px 14px;font-size:13px;font-weight:600}h2.svelte-1k3qopq{letter-spacing:.07em;text-transform:uppercase;color:var(--text-faint);margin:0 0 8px;font-size:12px;font-weight:650}.intent.svelte-1k3qopq{border-bottom:1px solid var(--border);padding:0 0 16px}.intent-text.svelte-1k3qopq{color:var(--text);max-width:80ch;margin:0;font-size:14px;line-height:1.6}.note.svelte-1k3qopq{color:var(--text-faint);max-width:80ch;margin:8px 0 0;font-size:11.5px;line-height:1.5}.group.svelte-1k3qopq{flex-direction:column;gap:12px;padding:18px 0 6px;display:flex}.group-sticky.svelte-1k3qopq{z-index:4;background:var(--bg);border-bottom:1px solid var(--border-soft);flex-direction:column;gap:6px;margin:0 -20px;padding:14px 20px 12px;display:flex;position:sticky;top:-14px}.group-head.svelte-1k3qopq{flex-wrap:wrap;align-items:baseline;gap:10px;display:flex}.group-head.svelte-1k3qopq .number:where(.svelte-1k3qopq){color:var(--text-faint);flex-shrink:0;font-size:12px;font-weight:700}.group-head.svelte-1k3qopq h2:where(.svelte-1k3qopq){color:var(--text);text-transform:none;letter-spacing:normal;margin:0;font-size:15px;font-weight:650;line-height:1.3}.kind-chip.svelte-1k3qopq{border:1px solid var(--border);background:var(--bg-card);flex-shrink:0;padding:2px 8px;font-size:11px;font-weight:700}.group-intent.svelte-1k3qopq{color:var(--text-dim);max-width:80ch;margin:0;font-size:12.5px;line-height:1.45}.loose.svelte-1k3qopq .kind-chip:where(.svelte-1k3qopq){color:var(--text-faint)}.file-section.svelte-1k3qopq{border-top:1px solid var(--border)}.file-head.svelte-1k3qopq{border-bottom:1px solid var(--border-soft);align-items:center;display:grid}.file-section.collapsed.svelte-1k3qopq .file-head:where(.svelte-1k3qopq){border-bottom:0}.file-head-main.svelte-1k3qopq{align-items:center;gap:8px;min-width:0;padding:6px 0;display:flex}.file-toggle.svelte-1k3qopq{text-align:left;min-width:0;color:inherit;cursor:pointer;background:0 0;border:0;flex:1;align-items:center;gap:8px;padding:4px 0;display:flex}.file-toggle.svelte-1k3qopq:hover .path:where(.svelte-1k3qopq){color:var(--accent)}.caret.svelte-1k3qopq{width:10px;color:var(--text-faint);flex-shrink:0;font-size:10px}.file-head-gutter.svelte-1k3qopq{flex-shrink:0}.file-head-explain.svelte-1k3qopq{align-items:center;padding:10px 0 10px 14px;display:flex}.path.svelte-1k3qopq{font-family:var(--mono);color:var(--text);text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:12.5px;overflow:hidden}.change-label.svelte-1k3qopq{color:var(--text-faint);flex:1;font-size:11px}.findings-control.svelte-1k3qopq{color:var(--text);background:0 0;border:0;flex-shrink:0;align-items:center;gap:6px;padding:0;display:flex}.count-badge.svelte-1k3qopq{justify-content:center;align-items:center;min-width:18px;height:18px;padding:0 4px;font-size:10.5px;font-weight:700;display:flex}.count-badge.done.svelte-1k3qopq{border:1px solid var(--fix-border);color:var(--ok)}.count-badge.open.svelte-1k3qopq{background:color-mix(in srgb, var(--finding-sev) 22%, transparent);color:var(--finding-sev)}.count-label.svelte-1k3qopq{color:var(--text-faint);font-size:11.5px}.count-label.open.svelte-1k3qopq{color:var(--text-dim)}.arrow.svelte-1k3qopq{color:var(--finding-sev,var(--accent));font-size:14px}.file-grid.svelte-1k3qopq{grid-template-columns:minmax(0,1fr) minmax(260px,320px);display:grid}.file-grid.no-explanations.svelte-1k3qopq{grid-template-columns:minmax(0,1fr)}.diff-col.svelte-1k3qopq{min-width:0}.explain-col.svelte-1k3qopq{border-left:1px solid var(--border-soft);background:var(--bg-elev);flex-direction:column;display:flex;overflow:auto}.explain-row.svelte-1k3qopq{border-bottom:1px solid var(--border-soft);padding:10px 14px}.explain-top.svelte-1k3qopq{align-items:baseline;gap:8px;margin-bottom:4px;display:flex}.lines.svelte-1k3qopq{color:var(--text-faint);font-size:10.5px;font-family:var(--mono)}.op.svelte-1k3qopq{color:var(--text-faint);text-transform:uppercase;letter-spacing:.04em;font-size:10px}.what.svelte-1k3qopq{color:var(--text);max-width:80ch;margin:0 0 3px;font-size:13px;line-height:1.4}.why.svelte-1k3qopq{color:var(--text-dim);max-width:80ch;margin:0;font-size:11.5px;line-height:1.4}.orphans.svelte-1k3qopq,.skipped.svelte-1k3qopq{border-top:1px solid var(--border-soft);padding-top:12px}.orphan-list.svelte-1k3qopq{flex-direction:column;gap:6px;display:flex}.orphan-row.svelte-1k3qopq{background:var(--bg-elev);border-left:2px solid #0000;align-items:baseline;gap:10px;padding:6px 10px;display:flex}.orphan-row.svelte-1k3qopq .badge:where(.svelte-1k3qopq){flex-shrink:0;font-size:10px;font-weight:700}.orphan-row.svelte-1k3qopq .what:where(.svelte-1k3qopq){flex:1;margin:0;font-size:12.5px}.orphan-row.svelte-1k3qopq .where:where(.svelte-1k3qopq){font-family:var(--mono);color:var(--text-faint);font-size:10.5px}.skipped-list.svelte-1k3qopq{flex-wrap:wrap;gap:6px;display:flex}.skipped-chip.svelte-1k3qopq{font-size:11px;font-family:var(--mono);color:var(--text-faint);border:1px solid var(--border);padding:4px 8px}.prompt-box.svelte-1dm34m1{border:1px solid var(--fix-border);background:var(--fix-bg);flex-direction:column;gap:10px;padding:14px 16px;display:flex}.prompt-box.publish.svelte-1dm34m1{border-color:var(--publish-border);background:var(--publish-bg)}.prompt-head.svelte-1dm34m1{justify-content:space-between;align-items:center;display:flex}.fix-title.svelte-1dm34m1{letter-spacing:.07em;text-transform:uppercase;color:var(--fix-text);margin:0;font-size:12px;font-weight:650}.publish-title.svelte-1dm34m1{letter-spacing:.07em;text-transform:uppercase;color:var(--publish-text);margin:0;font-size:12px;font-weight:650}.close.svelte-1dm34m1{color:var(--text-faint);background:0 0;border:0;padding:0;font-size:12px}.mode-toggle.svelte-1dm34m1{border:1px solid var(--border);width:fit-content;display:flex;overflow:hidden}.mode-toggle.svelte-1dm34m1 button:where(.svelte-1dm34m1){color:var(--text);background:0 0;border:0;padding:6px 12px;font-size:12px}.mode-toggle.svelte-1dm34m1 button:where(.svelte-1dm34m1)+button:where(.svelte-1dm34m1){border-left:1px solid var(--border)}.mode-toggle.svelte-1dm34m1 button.on:where(.svelte-1dm34m1){background:var(--accent-soft)}textarea.svelte-1dm34m1{resize:vertical;background:var(--bg);border:1px solid var(--border);width:100%;height:220px;font-family:var(--mono);color:var(--text);padding:12px;font-size:12px;line-height:1.5}.command-box.svelte-1dm34m1{background:var(--bg);border:1px solid var(--border);padding:10px 12px;overflow:auto}.command-box.svelte-1dm34m1 code:where(.svelte-1dm34m1){font-family:var(--mono);color:var(--text);white-space:nowrap;font-size:12.5px}.hint.svelte-1dm34m1{color:var(--text-faint);margin:0;font-size:11.5px}.copy.svelte-1dm34m1{background:var(--btn-primary-bg);border:1px solid var(--btn-primary-border);color:var(--btn-primary-text);padding:9px 14px;font-size:13px;font-weight:600}.detail-panel.svelte-1dm34m1{border:1px solid var(--border);background:var(--bg-card);flex-direction:column;flex:1;min-width:0;min-height:0;display:flex;overflow:hidden}.detail-head.svelte-1dm34m1{border-bottom:1px solid var(--border-soft);background:var(--bg-elev);flex-shrink:0;justify-content:space-between;align-items:center;gap:12px;padding:10px 16px;display:flex}.detail-head-left.svelte-1dm34m1{align-items:center;gap:8px;display:flex}.number.svelte-1dm34m1{color:var(--text);font-size:12px;font-weight:700}.badge.svelte-1dm34m1{font-size:10px;font-weight:700}.file-line.svelte-1dm34m1{min-width:0;font-family:var(--mono);align-items:baseline;gap:8px;display:flex}.file-name.svelte-1dm34m1{color:var(--text);flex-shrink:0;font-size:12px;font-weight:600}.file-dir.svelte-1dm34m1{color:var(--text-faint);text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:11px;overflow:hidden}.decision-group.svelte-1dm34m1{border:1px solid var(--border);flex-shrink:0;display:flex;overflow:hidden}.decision-group.svelte-1dm34m1 button:where(.svelte-1dm34m1){color:var(--text-dim);background:0 0;border:0;padding:6px 14px;font-size:12px;font-weight:600}.decision-group.svelte-1dm34m1 button:first-child.on:where(.svelte-1dm34m1){background:var(--danger-bg);color:var(--danger)}.decision-group.svelte-1dm34m1 button:nth-child(2).on:where(.svelte-1dm34m1){background:var(--fix-bg);color:var(--ok)}.decision-group.svelte-1dm34m1 button:where(.svelte-1dm34m1)+button:where(.svelte-1dm34m1){border-left:1px solid var(--border)}.decision-group.svelte-1dm34m1 .clear:where(.svelte-1dm34m1){color:var(--text-faint);padding:6px 10px}.detail-grid.svelte-1dm34m1{flex:1;grid-template-columns:minmax(0,1fr) minmax(260px,320px);min-height:0;display:grid}.detail-grid.no-explanations.svelte-1dm34m1{grid-template-columns:minmax(0,1fr)}.diff-col.svelte-1dm34m1{flex-direction:column;min-width:0;display:flex;overflow:hidden auto}.file-path-bar.svelte-1dm34m1{border-bottom:1px solid var(--border-soft);background:var(--bg-elev);flex-shrink:0;align-items:center;gap:8px;min-width:0;padding:8px 14px;display:flex}.file-path-text.svelte-1dm34m1{font-family:var(--mono);color:var(--text-faint);text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:11px;overflow:hidden}.explain-col.svelte-1dm34m1{border-left:1px solid var(--border-soft);background:var(--bg-elev);flex-direction:column;gap:16px;padding:14px 16px;display:flex;overflow:auto}.explain-counter.svelte-1dm34m1{color:var(--text-dim);border:1px solid var(--border);background:var(--bg-card);align-self:flex-start;padding:3px 8px;font-size:10.5px;font-weight:650}.explain-col.svelte-1dm34m1 h3:where(.svelte-1dm34m1){letter-spacing:.06em;text-transform:uppercase;color:var(--text-faint);margin:0 0 4px;font-size:10.5px;font-weight:650}.explain-col.svelte-1dm34m1 .what:where(.svelte-1dm34m1){color:var(--text);margin:0;font-size:13px;line-height:1.45}.explain-col.svelte-1dm34m1 .fix:where(.svelte-1dm34m1){color:var(--text-dim);margin:0;font-size:13px;line-height:1.45}.backdrop.svelte-lfje9j{z-index:9;background:#00000059;position:fixed;inset:0}.drawer.svelte-lfje9j{background:var(--bg-card);border-left:1px solid var(--border);z-index:10;flex-direction:column;width:420px;transition:transform .2s;display:flex;position:fixed;top:0;bottom:0;right:0;transform:translate(100%)}.drawer.open.svelte-lfje9j{transform:translate(0)}.drawer-head.svelte-lfje9j{border-bottom:1px solid var(--border-soft);flex-shrink:0;justify-content:space-between;align-items:center;gap:8px;min-width:0;padding:12px 14px;display:flex}.drawer-title.svelte-lfje9j{flex:1;align-items:center;gap:8px;min-width:0;display:flex}.file-ref.svelte-lfje9j{align-items:baseline;gap:8px;min-width:0;display:flex;overflow:hidden}.name.svelte-lfje9j{color:var(--text);font-size:13px;font-weight:600;font-family:var(--mono);flex-shrink:0}.dir.svelte-lfje9j{color:var(--text-faint);font-size:11px;font-family:var(--mono);text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.close.svelte-lfje9j{color:var(--text-faint);background:0 0;border:0;flex-shrink:0;padding:0;font-size:14px}.list.svelte-lfje9j{flex-direction:column;display:flex;overflow:auto}.item.svelte-lfje9j{border-bottom:1px solid var(--border-soft)}.item-head.svelte-lfje9j{text-align:left;background:0 0;border:0;border-left:2px solid #0000;align-items:center;gap:8px;width:100%;padding:10px 14px;display:flex}.status.svelte-lfje9j{border:1px solid #0000;flex-shrink:0;justify-content:center;align-items:center;width:14px;height:14px;font-size:10px;line-height:1;display:flex}.badge.svelte-lfje9j{flex-shrink:0;font-size:10px;font-weight:700}.what.svelte-lfje9j{color:var(--text);text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-size:12.5px;overflow:hidden}.chevron.svelte-lfje9j{color:var(--text-faint);flex-shrink:0;font-size:11px}.item-body.svelte-lfje9j{flex-direction:column;gap:14px;padding:0 14px 14px 20px;display:flex}.item-body.svelte-lfje9j h4:where(.svelte-lfje9j){letter-spacing:.06em;text-transform:uppercase;color:var(--text-faint);margin:0 0 4px;font-size:10px;font-weight:650}.item-body.svelte-lfje9j p:where(.svelte-lfje9j){color:var(--text);margin:0;font-size:13px;line-height:1.5}.item-body.svelte-lfje9j p.fix:where(.svelte-lfje9j){color:var(--text-dim)}.decision-group.svelte-lfje9j{border:1px solid var(--border);width:fit-content;display:flex;overflow:hidden}.decision-group.svelte-lfje9j button:where(.svelte-lfje9j){color:var(--text-dim);background:0 0;border:0;padding:7px 14px;font-size:12px;font-weight:600}.decision-group.svelte-lfje9j button:first-child.on:where(.svelte-lfje9j){background:var(--danger-bg);color:var(--danger)}.decision-group.svelte-lfje9j button:nth-child(2).on:where(.svelte-lfje9j){background:var(--fix-bg);color:var(--ok)}.decision-group.svelte-lfje9j button:where(.svelte-lfje9j)+button:where(.svelte-lfje9j){border-left:1px solid var(--border)}.decision-group.svelte-lfje9j .clear:where(.svelte-lfje9j){color:var(--text-faint);padding:7px 10px}.footer.svelte-67e2dl{border-top:1px solid var(--border);background:var(--bg-elev);flex-shrink:0;justify-content:space-between;align-items:center;gap:12px;min-height:33px;padding:6px 16px;display:flex}.right.svelte-67e2dl{align-items:center;gap:12px;display:flex}.reviewed.svelte-67e2dl{color:var(--text-faint);font-size:11px}.fix.svelte-67e2dl,.publish.svelte-67e2dl{border:1px solid;padding:6px 12px;font-size:11.5px;font-weight:600}.fix.svelte-67e2dl{background:var(--fix-bg);border-color:var(--fix-border);color:var(--ok)}.publish.svelte-67e2dl{background:var(--publish-bg);border-color:var(--publish-border);color:var(--publish-text)}.sidebar.svelte-xengl2{border-right:1px solid var(--border);background:var(--bg-elev);flex-direction:column;height:100%;min-height:0;padding:14px 0;display:flex;overflow:hidden}.sidebar.collapsed.svelte-xengl2{border-right:0}.mode-toggle.svelte-xengl2{border:1px solid var(--border);flex-shrink:0;margin:0 14px 12px;display:flex;overflow:hidden}.mode-toggle.svelte-xengl2 button:where(.svelte-xengl2){color:var(--text);background:0 0;border:0;flex:1;justify-content:center;align-items:center;gap:6px;padding:7px 8px;font-size:12px;display:flex}.mode-toggle.svelte-xengl2 button:where(.svelte-xengl2)+button:where(.svelte-xengl2){border-left:1px solid var(--border)}.mode-toggle.svelte-xengl2 button.on:where(.svelte-xengl2){background:var(--accent-soft)}.mode-label.svelte-xengl2{align-items:center;gap:6px;line-height:1;display:inline-flex}.count-badge.svelte-xengl2{font-family:var(--mono);border:1px solid color-mix(in srgb, var(--finding-sev,var(--border)) 45%, transparent);background:color-mix(in srgb, var(--finding-sev,var(--bg-card)) 18%, transparent);color:var(--finding-sev,var(--text-dim));justify-content:center;align-items:center;padding:2px 6px;font-size:10px;font-weight:700;line-height:1;display:inline-flex}.panel.svelte-xengl2{padding:0 14px 10px}.explore-panel.svelte-xengl2{flex-direction:column;flex:1;min-height:0;padding:0 0 10px;display:flex;overflow:hidden}.panel-chrome.svelte-xengl2{flex-shrink:0;padding:0 14px}.panel-scroll.svelte-xengl2{flex:1;min-height:0;padding:0 14px;overflow:hidden auto}h3.svelte-xengl2{letter-spacing:.06em;text-transform:uppercase;color:var(--text-faint);margin:0 0 8px;font-size:11.5px;font-weight:650}.index-tabs.svelte-xengl2{border-bottom:1px solid var(--border-soft);gap:12px;margin-bottom:8px;display:flex}.index-tabs.svelte-xengl2 button:where(.svelte-xengl2){letter-spacing:.06em;text-transform:uppercase;color:var(--text-faint);background:0 0;border:0;border-bottom:2px solid #0000;padding:0 0 6px;font-size:11.5px;font-weight:650}.index-tabs.svelte-xengl2 button.on:where(.svelte-xengl2){color:var(--text);border-bottom-color:var(--accent)}.files-toolbar.svelte-xengl2{justify-content:space-between;align-items:center;gap:6px;margin:-2px 0 8px;display:flex}.files-toolbar.svelte-xengl2 .tool:where(.svelte-xengl2){border:1px solid var(--border);background:var(--bg-card);width:26px;height:26px;color:var(--text-dim);justify-content:center;align-items:center;padding:0;display:inline-flex}.files-toolbar.svelte-xengl2 .tool:where(.svelte-xengl2):hover:not(:disabled){color:var(--text);border-color:var(--text-faint)}.files-toolbar.svelte-xengl2 .tool.on:where(.svelte-xengl2){background:var(--accent-soft);border-color:var(--border);color:var(--text)}.files-toolbar.svelte-xengl2 .tool:where(.svelte-xengl2):disabled{opacity:.35;cursor:default}.files-toolbar.svelte-xengl2 .tool-icon:where(.svelte-xengl2){width:14px;height:14px;display:block}.files-toolbar.svelte-xengl2 .seg:where(.svelte-xengl2){border:1px solid var(--border);display:flex;overflow:hidden}.files-toolbar.svelte-xengl2 .seg:where(.svelte-xengl2) .tool:where(.svelte-xengl2){background:0 0;border:0;border-radius:0}.files-toolbar.svelte-xengl2 .seg:where(.svelte-xengl2) .tool:where(.svelte-xengl2)+.tool:where(.svelte-xengl2){border-left:1px solid var(--border)}.files-toolbar.svelte-xengl2 .seg:where(.svelte-xengl2) .tool.on:where(.svelte-xengl2){background:var(--accent-soft)}.nav-list.svelte-xengl2{flex-direction:column;gap:2px;display:flex}.tree.svelte-xengl2{flex-direction:column;display:flex}.tree-row.svelte-xengl2{text-align:left;width:100%;color:var(--text);background:0 0;border:0;align-items:center;gap:4px;min-width:0;padding:2px 6px 2px 0;font-size:12px;display:flex;position:relative}.tree-row.svelte-xengl2:hover:not(:disabled){background:var(--bg-card)}.tree-row.dir.svelte-xengl2{color:var(--text-dim)}.tree-row.muted.svelte-xengl2{color:var(--text-faint);cursor:default}.tree-row.skipped.svelte-xengl2 .name:where(.svelte-xengl2){text-decoration:line-through;-webkit-text-decoration-color:var(--text-faint);text-decoration-color:var(--text-faint)}.tree-guides.svelte-xengl2{pointer-events:none;width:0;position:absolute;inset:0 auto 0 0}.tree-guide.svelte-xengl2{background:var(--border-soft);opacity:.9;width:1px;position:absolute;top:0;bottom:0}.tree-slot.svelte-xengl2{flex-shrink:0;justify-content:center;align-items:center;width:16px;height:16px;display:inline-flex}.caret.svelte-xengl2{color:var(--text-faint);font-size:10px;line-height:1}.mark.svelte-xengl2{width:9px;font-family:var(--mono);color:var(--text-faint);flex-shrink:0;font-size:9.5px;font-weight:700}.mark.add.svelte-xengl2{color:var(--diff-add-fg)}.mark.del.svelte-xengl2{color:var(--diff-del-fg)}.tree-row.svelte-xengl2 .name:where(.svelte-xengl2){text-overflow:ellipsis;white-space:nowrap;min-width:0;font-family:var(--mono);flex:1;font-size:11.5px;overflow:hidden}.tree-row.svelte-xengl2 .name-line:where(.svelte-xengl2){flex:1;align-items:baseline;gap:6px;min-width:0;display:flex;overflow:hidden}.tree-row.svelte-xengl2 .name-line:where(.svelte-xengl2) .name:where(.svelte-xengl2){text-overflow:ellipsis;flex:0 auto;overflow:hidden}.tree-row.svelte-xengl2 .name-line:where(.svelte-xengl2) .dir:where(.svelte-xengl2){text-overflow:ellipsis;white-space:nowrap;min-width:0;font-family:var(--mono);color:var(--text-faint);flex:1;font-size:10.5px;overflow:hidden}.tree-row.svelte-xengl2 .count:where(.svelte-xengl2),.group-link.svelte-xengl2 .count:where(.svelte-xengl2){color:var(--finding-sev,var(--danger));border:1px solid color-mix(in srgb, var(--finding-sev,var(--danger-border)) 55%, transparent);flex-shrink:0;padding:2px 5px;font-size:9.5px;font-weight:700;line-height:1}.tree-row.svelte-xengl2 .count.done:where(.svelte-xengl2),.group-link.svelte-xengl2 .count.done:where(.svelte-xengl2){color:var(--ok);border-color:var(--border)}.group-link.svelte-xengl2{min-width:0;color:var(--text);flex-direction:column;flex:1;gap:2px;padding:6px 8px 6px 0;font-size:12.5px;text-decoration:none;display:flex}.group-link.svelte-xengl2:hover{background:0 0}.group-item.svelte-xengl2{border-radius:0}.group-item.open.svelte-xengl2>.group-head-row:where(.svelte-xengl2){background:var(--bg-card)}.group-head-row.svelte-xengl2{align-items:flex-start;gap:0;display:flex}.group-head-row.svelte-xengl2:hover{background:var(--bg-card)}.group-caret.svelte-xengl2{width:20px;color:var(--text-faint);cursor:pointer;background:0 0;border:0;flex-shrink:0;justify-content:center;align-items:center;padding:8px 0 0;display:inline-flex}.group-caret.svelte-xengl2:hover{color:var(--text)}.group-files.svelte-xengl2{flex-direction:column;padding:0 0 4px 8px;display:flex}.row.svelte-xengl2{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.group-link.svelte-xengl2 .number:where(.svelte-xengl2){color:var(--text-faint);flex-shrink:0;font-size:10px;font-weight:700}.kind-chip.svelte-xengl2{border:1px solid var(--border);background:var(--bg-card);flex-shrink:0;padding:1px 5px;font-size:10px;font-weight:700}.group-link.svelte-xengl2 .title:where(.svelte-xengl2){white-space:normal;overflow-wrap:anywhere;line-height:1.35;display:block}.group-link.svelte-xengl2 .row:where(.svelte-xengl2)>.count:where(.svelte-xengl2){margin-left:auto}.meta.svelte-xengl2{color:var(--text-faint);padding-left:0;font-size:11px}.group-files.svelte-xengl2 .tree-row.file.active:where(.svelte-xengl2){background:var(--accent-soft)}.findings-panel.svelte-xengl2{flex-direction:column;flex:1;min-height:0;display:flex;overflow:hidden}.findings-head.svelte-xengl2{justify-content:space-between;align-items:baseline;margin-bottom:8px;display:flex}.findings-head.svelte-xengl2 h3:where(.svelte-xengl2){margin:0}.reviewed.svelte-xengl2{color:var(--text-faint);font-size:10.5px}.progress.svelte-xengl2{background:var(--border-soft);flex-shrink:0;height:3px;margin-bottom:10px;overflow:hidden}.progress-bar.svelte-xengl2{background:var(--accent);height:100%}.findings-list.svelte-xengl2{flex-direction:column;flex:1;gap:4px;min-height:0;display:flex;overflow:hidden auto}.finding-row.svelte-xengl2{text-align:left;border:0;border-bottom:1px solid var(--border-soft);background:var(--bg-elev);border-left:2px solid #0000;flex-direction:column;width:100%;min-width:0;padding:8px 10px;display:flex}.finding-row.active.svelte-xengl2{background:var(--accent-soft)}.finding-row.svelte-xengl2 .top:where(.svelte-xengl2){flex-wrap:wrap;justify-content:space-between;align-items:center;gap:4px 6px;margin-bottom:3px;display:flex}.finding-row.svelte-xengl2 .left:where(.svelte-xengl2){flex-wrap:wrap;align-items:center;gap:4px 6px;min-width:0;display:flex}.status.svelte-xengl2{border:1px solid #0000;flex-shrink:0;justify-content:center;align-items:center;width:14px;height:14px;font-size:10px;line-height:1;display:flex}.number.svelte-xengl2{color:var(--text-faint);font-size:9.5px;font-weight:650}.badge.svelte-xengl2{font-size:9.5px;font-weight:700}.decision.svelte-xengl2{font-size:9.5px;font-weight:650}.what.svelte-xengl2{color:var(--text);overflow-wrap:anywhere;font-size:12.5px;line-height:1.35;display:block}.file-line.svelte-xengl2{color:var(--text-faint);font-size:10.5px;font-family:var(--mono);overflow-wrap:anywhere;margin-top:3px;display:block}.report-shell.svelte-1ipe5j3{flex-direction:column;flex:1;min-height:0;display:flex}.report.svelte-1ipe5j3{flex:1;min-height:0;display:grid}.content.svelte-1ipe5j3{flex-direction:column;gap:18px;min-height:0;padding:14px 20px 24px;display:flex;overflow:auto}.page.svelte-67dwv3{background:var(--bg);flex-direction:column;height:100vh;min-height:0;display:flex}.chrome.svelte-67dwv3{border-bottom:1px solid var(--border);background:var(--header-bg);flex-shrink:0;grid-template-columns:1fr auto 1fr;align-items:center;gap:16px;padding:12px 28px;display:grid}.chrome-left.svelte-67dwv3{justify-self:start;align-items:center;gap:12px;min-width:0;display:flex}.chrome-center.svelte-67dwv3{justify-self:center;align-items:center;gap:10px;display:flex}.chrome-right.svelte-67dwv3{justify-self:end;align-items:center;gap:10px;display:flex}.brand.svelte-67dwv3{color:var(--text);flex-shrink:0;align-items:center;gap:10px;font-size:15px;font-weight:700;text-decoration:none;display:flex}.brand-dot.svelte-67dwv3{background:linear-gradient(135deg,#6ea8fe,#c9a5ff);border-radius:50%;flex-shrink:0;width:9px;height:9px;box-shadow:0 0 12px #6ea8fe88}.chrome-divider.svelte-67dwv3{background:var(--border);flex-shrink:0;width:1px;height:18px}.breadcrumb.svelte-67dwv3{font-family:var(--mono);align-items:center;gap:6px;min-width:0;font-size:12.5px;display:flex}.crumb-branch.svelte-67dwv3{color:var(--text);text-overflow:ellipsis;white-space:nowrap;font-weight:600;overflow:hidden}.crumb-sep.svelte-67dwv3{color:var(--text-faint)}.crumb-base.svelte-67dwv3{color:var(--text-faint);white-space:nowrap}.menu-wrap.svelte-67dwv3{flex-shrink:0;position:relative}.menu.svelte-67dwv3{z-index:40;border:1px solid var(--border);background:var(--bg-card);min-width:180px;padding:4px;position:absolute;top:calc(100% + 4px);left:0;box-shadow:0 8px 24px #0000002e}.download-menu.svelte-67dwv3{min-width:240px;left:auto;right:0}.menu-mode.svelte-67dwv3{border:1px solid var(--border);grid-template-columns:1fr 1fr;gap:0;margin:2px 2px 6px;display:grid}.menu-mode.svelte-67dwv3 button:where(.svelte-67dwv3){color:var(--text-dim);background:0 0;border:0;padding:6px 8px;font-size:11px;font-weight:600}.menu-mode.svelte-67dwv3 button:where(.svelte-67dwv3)+button:where(.svelte-67dwv3){border-left:1px solid var(--border)}.menu-mode.svelte-67dwv3 button.on:where(.svelte-67dwv3){background:var(--accent-soft);color:var(--text)}.menu-mode-hint.svelte-67dwv3{color:var(--text-faint);margin:0 8px 8px;font-size:10.5px;line-height:1.35}.menu-item.svelte-67dwv3{width:100%;color:var(--text);text-align:left;cursor:pointer;background:0 0;border:0;flex-direction:column;align-items:flex-start;gap:0;padding:4px 8px;font-size:12px;line-height:1.25;display:flex}.menu-item.svelte-67dwv3:hover{background:var(--accent-soft)}.menu-item.danger.svelte-67dwv3{color:var(--danger)}.menu-item.svelte-67dwv3 .fmt:where(.svelte-67dwv3){font-weight:600;line-height:1.2}.menu-item.svelte-67dwv3 .hint:where(.svelte-67dwv3){color:var(--text-faint);font-size:10.5px;line-height:1.2}.mode-toggle.svelte-67dwv3{border:1px solid var(--border);display:flex;overflow:hidden}.mode-toggle.svelte-67dwv3 button:where(.svelte-67dwv3){white-space:nowrap;color:var(--text);background:0 0;border:0;padding:6px 12px;font-size:12px}.mode-toggle.svelte-67dwv3 button:where(.svelte-67dwv3)+button:where(.svelte-67dwv3){border-left:1px solid var(--border)}.mode-toggle.svelte-67dwv3 button.on:where(.svelte-67dwv3){background:var(--accent-soft)}.zoom.svelte-67dwv3{align-items:center;gap:4px;display:flex}.icon-btn.svelte-67dwv3{background:var(--bg-card);border:1px solid var(--border);width:26px;height:26px;color:var(--text-dim);justify-content:center;align-items:center;padding:0;font-size:13px;display:flex}.icon-btn.svelte-67dwv3:hover{border-color:var(--accent);color:var(--text)}.icon-btn.on.svelte-67dwv3{background:var(--accent-soft);border-color:var(--accent);color:var(--text)}.icon-btn.kebab.svelte-67dwv3{background:0 0;border-color:#0000;width:24px;height:24px}.icon-btn.kebab.svelte-67dwv3:hover{border-color:var(--border);background:var(--bg-card)}.icon-btn.panel.svelte-67dwv3{font-size:15px}.icon-btn.svelte-67dwv3:disabled{opacity:.4;cursor:not-allowed}.zoom-label.svelte-67dwv3{font-family:var(--mono);color:var(--text-faint);text-align:center;width:30px;font-size:10.5px}.ghost.svelte-67dwv3{background:var(--bg-card);border:1px solid var(--border);color:var(--text);padding:7px 12px;font-size:12.5px}.download-btn.svelte-67dwv3{align-items:center;gap:6px;display:inline-flex}.download-btn.svelte-67dwv3 .caret:where(.svelte-67dwv3){opacity:.7}.hint.svelte-67dwv3{color:var(--text-faint);padding:40px 28px;font-size:13px}
@@ -0,0 +1 @@
1
+ .theme-toggle.svelte-lu0t34{background:var(--bg-card);border:1px solid var(--border);width:30px;height:30px;color:var(--text-dim);flex-shrink:0;justify-content:center;align-items:center;padding:0;font-size:14px;display:flex}.theme-toggle.svelte-lu0t34:hover{border-color:var(--accent);color:var(--text)}
@@ -0,0 +1 @@
1
+ var e=`diff-review:theme`;function t(){try{return localStorage.getItem(e)===`light`?`light`:`dark`}catch{return`dark`}}function n(t){try{localStorage.setItem(e,t)}catch{}}function r(e){document.documentElement.setAttribute(`data-theme`,e)}export{t as n,n as r,r as t};