@payconductor/houndsman 0.8.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/cli/index.ts +9 -1
- package/src/core/ai/ai-client.ts +21 -0
- package/src/core/ai/ai-sdk-model-provider.ts +43 -18
- package/src/core/ai/features/technical-summarizer.ts +43 -0
- package/src/core/ai/index.ts +4 -1
- package/src/core/ai/prompts/base.ts +7 -0
- package/src/core/ai/prompts/context.ts +5 -4
- package/src/core/ai/prompts/technical.ts +31 -0
- package/src/core/ai/provider-capabilities.ts +45 -0
- package/src/core/ai/schemas.ts +19 -3
- package/src/core/ai/types.ts +3 -1
- package/src/core/brief.ts +25 -4
- package/src/core/commands/scaffold.ts +5 -0
- package/src/core/config-loader.ts +18 -4
- package/src/core/config.ts +17 -1
- package/src/core/engine/review-workspace.ts +6 -2
- package/src/core/git-runner.ts +8 -1
- package/src/core/orchestrator.ts +114 -2
- package/src/core/paths.ts +3 -0
- package/src/core/pr-context.ts +11 -6
- package/src/core/project-config.ts +9 -1
- package/src/core/renderers/resume-renderer.ts +17 -34
- package/src/core/report-builder.ts +6 -6
- package/src/core/services/worktree-manager.ts +90 -7
- package/src/core/storage/types.ts +1 -0
- package/src/core/technical-summary.ts +398 -0
- package/src/harness/agent/agent-factory.ts +1 -0
- package/src/harness/agent/review-agent.ts +11 -1
- package/src/harness/config/harness-config.ts +6 -1
- package/src/index.ts +2 -0
- package/src/server/client/App.tsx +2 -1
- package/src/server/client/PrsSection.tsx +296 -0
- package/src/server/client/ResumePanel.tsx +10 -13
- package/src/server/client/RunsSection.tsx +73 -0
- package/src/server/client/Sidebar.tsx +171 -413
- package/src/server/client/sidebar-sections.tsx +73 -0
- package/src/server/client/utils/constants.ts +7 -2
- package/src/server/client/utils/sidebar-prefs.ts +64 -0
- package/src/server/client/utils/types.ts +1 -0
- package/src/server/index.ts +23 -409
- package/src/server/styles.css +454 -0
- package/src/tests/__snapshots__/baseline.test.ts.snap +5 -0
- package/src/tests/ai-core.test.ts +71 -0
- package/src/tests/ai-features.test.ts +47 -0
- package/src/tests/baseline.test.ts +4 -1
- package/src/tests/harness-agent.test.ts +19 -0
- package/src/tests/review-resume.test.ts +36 -8
- package/src/tests/review-scope.test.ts +67 -0
- package/src/tests/review-scripts.test.ts +2 -2
- package/src/tests/server.test.ts +16 -1
- package/src/tests/sidebar-sections.test.ts +94 -0
- package/src/tests/technical-summary.test.ts +176 -0
- package/src/tests/worktree.test.ts +110 -5
- package/assets/logo-legacy.png +0 -0
package/src/server/index.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* Bun e do Preact. Bind padrão em `127.0.0.1` — ferramenta local, sem autenticação.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import { join } from "node:path";
|
|
9
10
|
import { mediaPath } from "../core/assets";
|
|
10
11
|
import type { HoundsmanConfig } from "../core/config";
|
|
11
12
|
import type { FindingUpdate } from "../core/findings-state";
|
|
@@ -81,6 +82,7 @@ type ServerDeps = {
|
|
|
81
82
|
|
|
82
83
|
const API_RUN = /^\/api\/runs\/([^/]+)(\/.*)?$/;
|
|
83
84
|
const LOGO_FILE = "logo.png";
|
|
85
|
+
const STYLES_FILE = "styles.css";
|
|
84
86
|
|
|
85
87
|
/** Serve a logo do pacote (`assets/logo.png`). */
|
|
86
88
|
async function serveLogo(): Promise<Response> {
|
|
@@ -91,6 +93,23 @@ async function serveLogo(): Promise<Response> {
|
|
|
91
93
|
});
|
|
92
94
|
}
|
|
93
95
|
|
|
96
|
+
/**
|
|
97
|
+
* Serve o CSS da UI (`styles.css`, ao lado deste módulo) direto do disco.
|
|
98
|
+
*
|
|
99
|
+
* Ler a cada request mantém o hot reload: editar o CSS só exige recarregar a
|
|
100
|
+
* página — igual ao bundle do cliente.
|
|
101
|
+
*/
|
|
102
|
+
async function serveStyles(): Promise<Response> {
|
|
103
|
+
const file = Bun.file(join(import.meta.dir, STYLES_FILE));
|
|
104
|
+
if (!(await file.exists())) return notFound("styles não encontrado");
|
|
105
|
+
return new Response(file, {
|
|
106
|
+
headers: {
|
|
107
|
+
"content-type": "text/css; charset=utf-8",
|
|
108
|
+
"cache-control": "no-store, no-cache, must-revalidate",
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
94
113
|
async function route(
|
|
95
114
|
request: Request,
|
|
96
115
|
runs: RunRepository,
|
|
@@ -109,6 +128,7 @@ async function route(
|
|
|
109
128
|
if (path === "/assets/app.js") {
|
|
110
129
|
return noStore(await buildClientBundle(), "text/javascript; charset=utf-8");
|
|
111
130
|
}
|
|
131
|
+
if (path === `/assets/${STYLES_FILE}`) return serveStyles();
|
|
112
132
|
if (path === `/assets/${LOGO_FILE}`) return serveLogo();
|
|
113
133
|
if (path === "/api/health") return json({ ok: true });
|
|
114
134
|
if (path === "/api/editor" && request.method === "GET") return json(editor);
|
|
@@ -376,416 +396,9 @@ export function startServer(options: ServerOptions): { server: BunServer; url: s
|
|
|
376
396
|
}
|
|
377
397
|
|
|
378
398
|
// ---------------------------------------------------------------------------
|
|
379
|
-
// Shell (HTML
|
|
399
|
+
// Shell (HTML)
|
|
380
400
|
// ---------------------------------------------------------------------------
|
|
381
401
|
|
|
382
|
-
const STYLES = `
|
|
383
|
-
@import url('https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap');
|
|
384
|
-
|
|
385
|
-
:root {
|
|
386
|
-
color-scheme: dark;
|
|
387
|
-
--bg:#0a0a0c; --surface:#101014; --surface-2:#17171c; --card:#131318;
|
|
388
|
-
--border:rgba(255,255,255,.07); --border-strong:rgba(255,255,255,.14);
|
|
389
|
-
--fg:#ece9e4; --muted:#9d978e; --muted-2:#6d6862;
|
|
390
|
-
--accent:#f0a52c; --accent-strong:#ffc247; --accent-soft:rgba(240,165,44,.07); --accent-line:rgba(240,165,44,.25);
|
|
391
|
-
--blocking:#f2595e; --attention:#eda13a; --suggestion:#5aa4f0; --nit:#8d8a85; --success:#45c07a;
|
|
392
|
-
--radius:16px; --radius-lg:18px;
|
|
393
|
-
--font-sans:"Poppins","Space Grotesk","Geist Sans",ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;
|
|
394
|
-
--font-mono:"JetBrains Mono",ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
|
|
395
|
-
}
|
|
396
|
-
* { box-sizing:border-box; }
|
|
397
|
-
html, body { height:100%; }
|
|
398
|
-
body { margin:0; font-size:14px; background:var(--bg); color:var(--fg); font-family:var(--font-sans); -webkit-font-smoothing:antialiased; }
|
|
399
|
-
body::before { content:""; position:fixed; inset:0; pointer-events:none; z-index:0;
|
|
400
|
-
background:radial-gradient(820px 420px at 8% -12%, rgba(240,165,44,.08), transparent 62%); }
|
|
401
|
-
code, pre, .mono { font-family:var(--font-mono); tab-size:4; }
|
|
402
|
-
::-webkit-scrollbar { width:10px; height:10px; }
|
|
403
|
-
::-webkit-scrollbar-thumb { background:rgba(255,255,255,.1); border:2px solid transparent; border-radius:999px; background-clip:padding-box; }
|
|
404
|
-
::-webkit-scrollbar-thumb:hover { background:rgba(255,255,255,.18); background-clip:padding-box; }
|
|
405
|
-
.app { position:relative; z-index:1; display:flex; height:100vh; overflow:hidden; }
|
|
406
|
-
.sidebar { width:292px; flex:0 0 292px; display:flex; flex-direction:column; gap:14px; padding:18px 14px;
|
|
407
|
-
background:var(--surface); border-right:1px solid var(--border); overflow-y:auto; }
|
|
408
|
-
.brand { display:flex; align-items:center; gap:12px; }
|
|
409
|
-
.brand .logo { width:42px; height:42px; object-fit:contain; border-radius:12px; background:var(--surface-2); border:1px solid var(--border); }
|
|
410
|
-
.sidebar h1 { font-size:15.5px; font-weight:700; letter-spacing:-.01em; margin:0; }
|
|
411
|
-
.sub { color:var(--muted); font-size:11.5px; margin:0; }
|
|
412
|
-
.section-label { margin:4px 0 0; font-size:10px; font-weight:700; letter-spacing:.16em; text-transform:uppercase; color:var(--muted-2); }
|
|
413
|
-
.runs { display:flex; flex-direction:column; gap:6px; }
|
|
414
|
-
.run { display:flex; flex-direction:column; gap:8px; text-align:left; cursor:pointer; font:inherit; color:inherit; padding:11px 13px;
|
|
415
|
-
background:transparent; border:1px solid transparent; border-radius:var(--radius); transition:background .15s ease, border-color .15s ease; }
|
|
416
|
-
.run:hover { background:var(--surface-2); border-color:var(--border); }
|
|
417
|
-
.run.active { background:var(--accent-soft); border-color:var(--accent-line); }
|
|
418
|
-
.run-top { display:flex; align-items:flex-start; gap:8px; }
|
|
419
|
-
.run-icon { flex:none; margin-top:2px; color:var(--muted-2); }
|
|
420
|
-
.run.active .run-icon { color:var(--accent); }
|
|
421
|
-
.run-branch { font-size:13.5px; font-weight:600; line-height:1.35; word-break:break-word; }
|
|
422
|
-
.run-meta { display:flex; align-items:center; gap:10px; font-family:var(--font-mono); font-size:11px; color:var(--muted); }
|
|
423
|
-
.run-when { display:inline-flex; align-items:center; gap:6px; }
|
|
424
|
-
.run-count { margin-left:auto; color:var(--muted-2); }
|
|
425
|
-
.run-badge { align-self:flex-start; display:inline-flex; align-items:center; gap:6px; padding:4px 9px; border-radius:999px;
|
|
426
|
-
font-size:10px; font-weight:700; letter-spacing:.07em; text-transform:uppercase;
|
|
427
|
-
color:var(--success); background:rgba(69,192,122,.12); border:1px solid rgba(69,192,122,.32); }
|
|
428
|
-
.run-status { font-size:10px; font-weight:600; letter-spacing:.07em; text-transform:uppercase; color:var(--muted-2); }
|
|
429
|
-
.status-reviewing, .status-fixing { color:var(--accent); }
|
|
430
|
-
.status-review_done { color:var(--suggestion); }
|
|
431
|
-
.status-fix_done { color:var(--success); }
|
|
432
|
-
.status-timeout { color:var(--blocking); }
|
|
433
|
-
.side-tabs { display:flex; gap:4px; padding:4px; background:var(--surface-2); border:1px solid var(--border); border-radius:999px; }
|
|
434
|
-
.side-tab { flex:1; display:inline-flex; align-items:center; justify-content:center; gap:7px; font:inherit; font-size:12px; font-weight:600; cursor:pointer; color:var(--muted);
|
|
435
|
-
padding:7px 10px; background:transparent; border:1px solid transparent; border-radius:999px; transition:color .15s ease, background .15s ease; }
|
|
436
|
-
.side-tab:hover { color:var(--fg); }
|
|
437
|
-
.side-tab.active { color:#1b1305; background:linear-gradient(180deg, var(--accent-strong), var(--accent)); }
|
|
438
|
-
.side-count { padding:1px 6px; font-family:var(--font-mono); font-size:10px; color:var(--muted); background:rgba(255,255,255,.08); border-radius:999px; }
|
|
439
|
-
.side-tab.active .side-count { color:#1b1305; background:rgba(0,0,0,.14); }
|
|
440
|
-
.icon-btn { display:inline-grid; place-items:center; width:26px; height:26px; color:var(--muted); background:transparent; border:1px solid var(--border); border-radius:8px; cursor:pointer; text-decoration:none; }
|
|
441
|
-
.icon-btn:hover { color:var(--fg); border-color:var(--border-strong); }
|
|
442
|
-
.icon-btn:disabled { opacity:.5; cursor:not-allowed; }
|
|
443
|
-
.pr-toolbar { display:flex; align-items:center; justify-content:space-between; gap:8px; }
|
|
444
|
-
.pr-toolbar .section-label { margin:0; }
|
|
445
|
-
.prs { display:flex; flex-direction:column; gap:8px; }
|
|
446
|
-
.pr { display:flex; flex-direction:column; gap:7px; padding:11px 12px; background:var(--card); border:1px solid var(--border); border-radius:var(--radius); }
|
|
447
|
-
.pr.current { background:var(--accent-soft); border-color:var(--accent-line); }
|
|
448
|
-
.pr-head { display:flex; align-items:center; gap:7px; font-family:var(--font-mono); font-size:11px; color:var(--muted); }
|
|
449
|
-
.pr-icon { color:var(--muted-2); }
|
|
450
|
-
.pr.current .pr-icon { color:var(--accent); }
|
|
451
|
-
.pr-number { font-weight:600; color:var(--fg); }
|
|
452
|
-
.pr-current { padding:1px 6px; font-size:9px; font-weight:700; letter-spacing:.08em; text-transform:uppercase; color:var(--accent); background:rgba(240,165,44,.12); border-radius:999px; }
|
|
453
|
-
.pr-title { margin:0; font-size:12.5px; font-weight:600; line-height:1.4; word-break:break-word; }
|
|
454
|
-
.pr-meta { display:flex; flex-wrap:wrap; align-items:center; gap:1px 5px; margin:0; font-family:var(--font-mono); font-size:10.5px; color:var(--muted-2); }
|
|
455
|
-
.pr-branch { color:var(--suggestion); }
|
|
456
|
-
.pr-review { margin:0; font-size:10.5px; font-weight:600; }
|
|
457
|
-
.pr-review-APPROVED { color:var(--success); }
|
|
458
|
-
.pr-review-CHANGES_REQUESTED { color:var(--blocking); }
|
|
459
|
-
.pr-review-REVIEW_REQUIRED { color:var(--attention); }
|
|
460
|
-
.pr-actions { display:flex; flex-wrap:wrap; gap:6px; margin-top:2px; }
|
|
461
|
-
.pr-btn { display:inline-flex; align-items:center; gap:5px; font:inherit; font-size:10.5px; font-weight:600; cursor:pointer; padding:4px 9px; color:var(--muted);
|
|
462
|
-
background:transparent; border:1px solid var(--border-strong); border-radius:999px; text-decoration:none; }
|
|
463
|
-
.pr-btn:hover { color:var(--fg); border-color:var(--accent-line); }
|
|
464
|
-
.pr-btn:disabled { opacity:.45; cursor:not-allowed; }
|
|
465
|
-
.pr-btn.danger { color:var(--accent); background:var(--accent-soft); border-color:var(--accent-line); }
|
|
466
|
-
.pr-warning { margin:0; padding:8px 10px; font-size:11px; line-height:1.5; color:var(--attention);
|
|
467
|
-
background:rgba(237,161,58,.08); border:1px solid rgba(237,161,58,.24); border-radius:10px; }
|
|
468
|
-
.pr-notice { margin:0; padding:8px 10px; font-size:11px; line-height:1.5; color:var(--success);
|
|
469
|
-
background:rgba(69,192,122,.08); border:1px solid rgba(69,192,122,.24); border-radius:10px; }
|
|
470
|
-
.pr-current-branch { margin:0; font-family:var(--font-mono); font-size:10.5px; color:var(--muted-2); }
|
|
471
|
-
.pr-current-branch code { color:var(--fg); }
|
|
472
|
-
.comments { display:flex; flex-direction:column; gap:18px; }
|
|
473
|
-
.comments-toolbar { display:flex; align-items:center; justify-content:space-between; gap:12px; }
|
|
474
|
-
.comments-counts { display:flex; flex-wrap:wrap; align-items:center; gap:12px; font-size:11.5px; color:var(--muted); }
|
|
475
|
-
.comments-counts b { font-family:var(--font-mono); font-weight:600; color:var(--fg); }
|
|
476
|
-
.comment-group { display:flex; flex-direction:column; gap:10px; }
|
|
477
|
-
.comment-group-title { margin:0; font-size:11px; font-weight:700; letter-spacing:.16em; text-transform:uppercase; color:var(--muted-2); }
|
|
478
|
-
.comment-file-group { display:flex; flex-direction:column; gap:8px; }
|
|
479
|
-
.comment-group-label { display:flex; align-items:center; gap:8px; margin:0; font-family:var(--font-mono); font-size:11.5px; color:var(--suggestion); }
|
|
480
|
-
.comment-thread { display:flex; flex-direction:column; overflow:hidden; background:var(--card); border:1px solid var(--border); border-radius:var(--radius-lg); }
|
|
481
|
-
.comment-thread-head { display:flex; align-items:center; gap:8px; padding:9px 13px; font-family:var(--font-mono); font-size:11px; color:var(--muted);
|
|
482
|
-
background:var(--surface-2); border-bottom:1px solid var(--border); }
|
|
483
|
-
.comment-file { overflow:hidden; color:var(--fg); text-overflow:ellipsis; white-space:nowrap; }
|
|
484
|
-
.pr-comment { display:flex; flex-direction:column; gap:7px; padding:12px 14px; border-top:1px solid var(--border); }
|
|
485
|
-
.comment-thread .pr-comment:first-of-type { border-top:0; }
|
|
486
|
-
.pr-comment.reply { margin-left:26px; background:rgba(255,255,255,.012); border-left:2px solid var(--accent-line); }
|
|
487
|
-
.pr-comment-head { display:flex; align-items:center; gap:9px; font-size:11px; color:var(--muted-2); }
|
|
488
|
-
.pr-comment-author { font-size:12px; font-weight:600; color:var(--fg); }
|
|
489
|
-
.pr-comment-link { display:inline-flex; align-items:center; gap:5px; font-size:11px; color:var(--muted); text-decoration:none; }
|
|
490
|
-
.pr-comment-link:hover { color:var(--accent); }
|
|
491
|
-
.pr-comment-body { font-size:12.5px; line-height:1.6; color:#f0ece6; }
|
|
492
|
-
.pr-comment-body .md-p, .pr-comment-body .md-list { font-size:12.5px; }
|
|
493
|
-
.main { flex:1; min-width:0; display:flex; flex-direction:column; overflow-y:auto; }
|
|
494
|
-
.topbar { position:sticky; top:0; z-index:10; display:flex; align-items:center; justify-content:space-between; gap:16px;
|
|
495
|
-
padding:13px 24px; border-bottom:1px solid var(--border); background:rgba(16,16,20,.74);
|
|
496
|
-
backdrop-filter:blur(16px) saturate(140%); -webkit-backdrop-filter:blur(16px) saturate(140%); }
|
|
497
|
-
.segmented { display:inline-flex; gap:4px; padding:4px; background:var(--surface-2); border:1px solid var(--border); border-radius:999px; }
|
|
498
|
-
.seg-btn { display:inline-flex; align-items:center; gap:8px; font:inherit; font-size:12.5px; font-weight:600; cursor:pointer;
|
|
499
|
-
color:var(--muted); background:transparent; border:1px solid transparent; border-radius:999px; padding:7px 16px;
|
|
500
|
-
transition:color .15s ease, background .15s ease; }
|
|
501
|
-
.seg-btn:hover { color:var(--fg); }
|
|
502
|
-
.seg-btn.active { color:#1b1305; background:linear-gradient(180deg, var(--accent-strong), var(--accent)); box-shadow:0 4px 14px rgba(240,165,44,.24); }
|
|
503
|
-
.topbar-right { display:flex; align-items:center; gap:14px; }
|
|
504
|
-
.auto-refresh { display:inline-flex; align-items:center; gap:8px; white-space:nowrap; font-family:var(--font-mono); font-size:11.5px; color:var(--muted); }
|
|
505
|
-
.dot { width:8px; height:8px; border-radius:50%; background:var(--success); box-shadow:0 0 0 3px rgba(69,192,122,.14); }
|
|
506
|
-
.dot.busy { background:var(--accent); box-shadow:0 0 0 3px rgba(240,165,44,.18); animation:pulse 1.1s ease-in-out infinite; }
|
|
507
|
-
.btn { display:inline-flex; align-items:center; gap:8px; font:inherit; font-size:12.5px; font-weight:500; cursor:pointer; color:var(--fg);
|
|
508
|
-
padding:8px 15px; background:var(--surface-2); border:1px solid var(--border-strong); border-radius:999px;
|
|
509
|
-
transition:background .15s ease, border-color .15s ease, color .15s ease; }
|
|
510
|
-
.btn:hover { background:#202027; border-color:var(--accent-line); }
|
|
511
|
-
.btn:disabled { opacity:.55; cursor:not-allowed; }
|
|
512
|
-
.btn.danger { color:#ffb3b3; background:rgba(255,86,86,.12); border-color:rgba(255,86,86,.4); }
|
|
513
|
-
.btn.danger:hover { background:rgba(255,86,86,.2); border-color:rgba(255,86,86,.62); }
|
|
514
|
-
.modal-check { display:flex; align-items:flex-start; gap:10px; padding:12px 14px; font-size:12.5px; line-height:1.55;
|
|
515
|
-
color:var(--fg); background:var(--surface-2); border:1px solid var(--border); border-radius:12px; cursor:pointer; }
|
|
516
|
-
.modal-check input { margin:3px 0 0; flex:none; accent-color:var(--accent); }
|
|
517
|
-
.modal-check code { font-family:var(--font-mono); font-size:11.5px; color:var(--muted); word-break:break-all; }
|
|
518
|
-
.modal-warn { margin:0; font-size:12px; line-height:1.55; color:var(--muted); }
|
|
519
|
-
.icon.spin { animation:spin .8s linear infinite; }
|
|
520
|
-
.content { width:100%; max-width:1180px; margin:0 auto; padding:22px 24px 64px; }
|
|
521
|
-
.page-header { display:flex; align-items:flex-start; justify-content:space-between; gap:18px; margin-bottom:16px; }
|
|
522
|
-
.page-header-text { min-width:0; }
|
|
523
|
-
.page-header-actions { display:flex; align-items:center; gap:10px; flex:none; }
|
|
524
|
-
.btn.submit-review { color:#1b1305; background:linear-gradient(180deg, var(--accent-strong), var(--accent)); border-color:transparent; box-shadow:0 4px 14px rgba(240,165,44,.22); }
|
|
525
|
-
.btn.submit-review:hover { background:linear-gradient(180deg, var(--accent-strong), var(--accent)); border-color:transparent; filter:brightness(1.07); }
|
|
526
|
-
.page-title { margin:0 0 8px; font-size:26px; font-weight:700; letter-spacing:-.02em; word-break:break-word; }
|
|
527
|
-
.page-sub { margin:0; max-width:78ch; color:var(--muted); font-size:12.5px; line-height:1.55; }
|
|
528
|
-
.page-sub code { color:var(--fg); background:rgba(255,255,255,.06); border-radius:6px; padding:1px 6px; font-size:11.5px; }
|
|
529
|
-
.error { color:#ff8b8f; font-size:12.5px; }
|
|
530
|
-
.empty { color:var(--muted); font-size:13px; }
|
|
531
|
-
.kpis { display:grid; grid-template-columns:repeat(4, minmax(0,1fr)); gap:12px; margin:20px 0 18px; }
|
|
532
|
-
.kpi { display:flex; flex-direction:column; gap:8px; padding:15px 16px; background:var(--card);
|
|
533
|
-
border:1px solid var(--border); border-radius:var(--radius-lg); }
|
|
534
|
-
.kpi-label { font-size:10px; font-weight:700; letter-spacing:.14em; text-transform:uppercase; color:var(--muted-2); }
|
|
535
|
-
.kpi-value { font-size:30px; font-weight:700; line-height:1; letter-spacing:-.02em; font-variant-numeric:tabular-nums; }
|
|
536
|
-
.kpi-hint { font-family:var(--font-mono); font-size:11px; color:var(--muted-2); }
|
|
537
|
-
.kpi-execute .kpi-value { color:var(--accent); }
|
|
538
|
-
.kpi-ignore .kpi-value { color:var(--muted); }
|
|
539
|
-
.kpi-done .kpi-value { color:var(--success); }
|
|
540
|
-
.progress { margin:0 0 22px; }
|
|
541
|
-
.progress-head { display:flex; align-items:center; justify-content:space-between; margin-bottom:8px; font-size:11.5px; color:var(--muted); }
|
|
542
|
-
.progress-head .pct { color:var(--fg); font-family:var(--font-mono); }
|
|
543
|
-
.progress-track { height:8px; border-radius:999px; background:var(--surface-2); border:1px solid var(--border); overflow:hidden; }
|
|
544
|
-
.progress-fill { display:block; height:100%; border-radius:999px; background:linear-gradient(90deg, #2c8f57, var(--success)); transition:width .35s ease; }
|
|
545
|
-
.filters { display:flex; flex-wrap:wrap; align-items:center; gap:10px; margin-bottom:20px; }
|
|
546
|
-
.search { display:flex; align-items:center; gap:8px; flex:1 1 240px; max-width:330px; padding:8px 14px; color:var(--muted);
|
|
547
|
-
background:var(--surface-2); border:1px solid var(--border-strong); border-radius:999px; }
|
|
548
|
-
.search:focus-within { color:var(--accent); border-color:var(--accent-line); }
|
|
549
|
-
.search input { flex:1; min-width:0; font:inherit; font-size:12.5px; color:var(--fg); background:transparent; border:0; outline:0; }
|
|
550
|
-
.search input::placeholder { color:var(--muted-2); }
|
|
551
|
-
.search-clear { padding:0 2px; font-size:15px; line-height:1; color:var(--muted); background:transparent; border:0; cursor:pointer; }
|
|
552
|
-
.chips { display:inline-flex; gap:3px; padding:4px; background:var(--surface-2); border:1px solid var(--border); border-radius:999px; }
|
|
553
|
-
.chip { display:inline-flex; align-items:center; gap:6px; font:inherit; font-size:12px; font-weight:600; cursor:pointer; color:var(--muted);
|
|
554
|
-
padding:6px 13px; background:transparent; border:1px solid transparent; border-radius:999px; transition:color .15s ease, background .15s ease; }
|
|
555
|
-
.chip:hover { color:var(--fg); }
|
|
556
|
-
.chip.active { color:#14100a; background:#e9e5df!important; }
|
|
557
|
-
.sev-group { margin-bottom:24px; }
|
|
558
|
-
.sev-head { display:flex; align-items:center; gap:8px; margin:0 0 10px; font-size:11px; font-weight:700;
|
|
559
|
-
letter-spacing:.16em; text-transform:uppercase; color:var(--muted-2); }
|
|
560
|
-
.sev-head .n { font-family:var(--font-mono); letter-spacing:0; }
|
|
561
|
-
.sev-group.sev-blocking .sev-head { color:var(--blocking); }
|
|
562
|
-
.sev-group.sev-attention .sev-head { color:var(--attention); }
|
|
563
|
-
.sev-group.sev-suggestion .sev-head { color:var(--suggestion); }
|
|
564
|
-
.sev-group.sev-nit .sev-head { color:var(--nit); }
|
|
565
|
-
.card { position:relative; margin-bottom:20px; overflow:hidden; background:var(--card);
|
|
566
|
-
border:1px solid var(--border); border-left:4px solid var(--border-strong); border-radius:var(--radius-lg);
|
|
567
|
-
transition:background .15s ease, border-color .15s ease, opacity .2s ease; }
|
|
568
|
-
.card:hover { background:#16161b; }
|
|
569
|
-
.card.sev-blocking { border-left-color:var(--blocking); }
|
|
570
|
-
.card.sev-attention { border-left-color:var(--attention); }
|
|
571
|
-
.card.sev-suggestion { border-left-color:var(--suggestion); }
|
|
572
|
-
.card.sev-nit { border-left-color:var(--nit); }
|
|
573
|
-
.card.absent { opacity:.5; }
|
|
574
|
-
.card.done { opacity:.6; }
|
|
575
|
-
.card-head { display:flex; align-items:center; gap:10px; padding:12px 14px 0; }
|
|
576
|
-
.chev { display:grid; place-items:center; flex:none; width:22px; height:22px; cursor:pointer; color:var(--muted-2);
|
|
577
|
-
background:transparent; border:1px solid transparent; border-radius:7px; }
|
|
578
|
-
.chev:hover { color:var(--fg); background:rgba(255,255,255,.06); }
|
|
579
|
-
.chev:focus-visible { color:var(--fg); border-color:var(--accent-line); outline:none; }
|
|
580
|
-
.chev svg { transition:transform .18s ease; }
|
|
581
|
-
.chev.open svg { transform:rotate(90deg); }
|
|
582
|
-
.sev-badge { display:inline-flex; align-items:center; flex:none; padding:3px 9px; border-radius:999px;
|
|
583
|
-
font-size:10px; letter-spacing:.08em; text-transform:uppercase; }
|
|
584
|
-
.card.sev-blocking .sev-badge { color:var(--blocking); background:rgba(242,89,94,.12); }
|
|
585
|
-
.card.sev-attention .sev-badge { color:var(--attention); background:rgba(237,161,58,.12); }
|
|
586
|
-
.card.sev-suggestion .sev-badge { color:var(--suggestion); background:rgba(90,164,240,.12); }
|
|
587
|
-
.card.sev-nit .sev-badge { color:var(--nit); background:rgba(255,255,255,.06); }
|
|
588
|
-
.loc { display:inline-flex; align-items:center; gap:7px; max-width: 406ch; overflow:hidden; white-space:break-spaces; text-overflow:ellipsis;
|
|
589
|
-
padding:4px 9px; font-family:var(--font-mono); font-size:11.5px; color:#aba7a1; text-decoration:none; }
|
|
590
|
-
.loc:hover { color:#fff; }
|
|
591
|
-
.loc .ext { flex:none; opacity:0; transition:opacity .15s ease; }
|
|
592
|
-
.loc:hover .ext { opacity:1; }
|
|
593
|
-
.loc.static { color:var(--muted); }
|
|
594
|
-
.count { padding:2px 7px; font-family:var(--font-mono); font-size:11px; color:var(--muted);
|
|
595
|
-
background:var(--surface-2); border:1px solid var(--border); border-radius:999px; }
|
|
596
|
-
.spacer { flex:1; }
|
|
597
|
-
.done-btn { display:inline-flex; align-items:center; gap:7px; flex:none; font:inherit; font-size:12px; font-weight:600; cursor:pointer;
|
|
598
|
-
padding:7px 13px; color:var(--muted); background:transparent; border:1px solid var(--border-strong); border-radius:999px;
|
|
599
|
-
transition:color .15s ease, background .15s ease, border-color .15s ease; }
|
|
600
|
-
.done-btn:hover { color:var(--fg); border-color:rgba(69,192,122,.55); }
|
|
601
|
-
.done-btn:disabled { opacity:.55; cursor:not-allowed; }
|
|
602
|
-
.done-btn.is-done { color:var(--success); background:rgba(69,192,122,.14); border-color:rgba(69,192,122,.5); }
|
|
603
|
-
.card-title { margin:9px 0 0; padding:0 16px 20px; font-size:14px; font-weight:400; }
|
|
604
|
-
.card.done .card-title { color:#b7b7b7; text-decoration:line-through; text-decoration-color:rgba(255,255,255,.15); }
|
|
605
|
-
.card-body { display:flex; flex-direction:column; gap:12px; padding:20px 16px 15px; background:rgba(255,255,255,.012); border-top:1px solid var(--border); }
|
|
606
|
-
.meta-row { display:flex; flex-wrap:wrap; gap:14px; font-size:11.5px; color:var(--muted); }
|
|
607
|
-
.meta { display:inline-flex; align-items:center; gap:7px; }
|
|
608
|
-
.meta-k { font-size:10px; font-weight:700; letter-spacing:.1em; text-transform:uppercase; color:var(--muted-2); }
|
|
609
|
-
.meta code { padding:2px 6px; font-size:11.5px; color:var(--fg); background:rgba(255,255,255,.04); border:1px solid var(--border); border-radius:6px; }
|
|
610
|
-
.action-block { display:flex; gap:11px; padding:0; background:transparent; border:0; border-radius:0; }
|
|
611
|
-
.action-icon { flex:none; display:inline-block; margin-top:3px; margin-right:2px; color:var(--accent); }
|
|
612
|
-
.action-text { flex:1; min-width:0; }
|
|
613
|
-
.action-label { display:block; margin-bottom:4px; font-size:10px; font-weight:600; letter-spacing:.12em; text-transform:uppercase; color:var(--accent); }
|
|
614
|
-
.action-text p, .md-p { margin:0 0 6px; font-size:13px; line-height:1.65; color:#f0ece6; white-space:pre-wrap; }
|
|
615
|
-
.action-text p:last-child { margin-bottom:0; }
|
|
616
|
-
.md-list { margin:0 0 6px; padding-left:20px; font-size:13px; line-height:1.65; color:#f0ece6; }
|
|
617
|
-
.md-list li { margin:0 0 2px; }
|
|
618
|
-
.md-quote { margin:0 0 6px; padding:2px 0 2px 10px; border-left:2px solid var(--accent-line); color:var(--muted); font-size:13px; line-height:1.65; white-space:pre-wrap; }
|
|
619
|
-
.action-text code, .md-code { font-family:var(--font-mono); font-size:11.5px; padding:1px 5px; color:#f0ece6; background:rgba(255,255,255,.06); border:1px solid var(--border); border-radius:5px; }
|
|
620
|
-
code.md-path { color:#8fc7ff; background:rgba(90,164,240,.1); border-color:rgba(90,164,240,.24); }
|
|
621
|
-
.action-text a, .md-p a, .md-list a, .md-quote a, .md-table a, .md-h a { color:var(--accent-strong); text-decoration:underline; text-underline-offset:2px; }
|
|
622
|
-
.action-text strong, .md-p strong, .md-list strong, .md-quote strong, .md-table strong, .md-h strong { color:#fff; font-weight:600; }
|
|
623
|
-
.action-text em, .md-p em, .md-list em, .md-quote em, .md-table em, .md-h em { color:#e9e4dc; }
|
|
624
|
-
.md-code-block { margin:6px 0; padding:10px 12px; max-height:320px; overflow:auto; white-space:pre; font-size:11.5px; line-height:1.6; color:#cdc7bf; background:#0b0b0e; border-radius:10px; }
|
|
625
|
-
.md-h { margin:16px 0 8px; font-size:14px; font-weight:700; line-height:1.35; letter-spacing:-.01em; color:#eee9e2; }
|
|
626
|
-
.md-h:first-child { margin-top:0; }
|
|
627
|
-
.md-h1 { font-size:19px; }
|
|
628
|
-
.md-h2 { font-size:16px; }
|
|
629
|
-
.md-h3 { font-size:14px; }
|
|
630
|
-
.md-h4, .md-h5, .md-h6 { font-size:13px; color:#e4dfd7; font-weight:600; }
|
|
631
|
-
.md-hr { margin:14px 0; border:0; border-top:1px solid var(--border); }
|
|
632
|
-
.md-table-wrap { margin:8px 0 12px; padding:4px; overflow-x:auto; border:1px solid rgba(255,255,255,.07); border-radius:10px; background:rgba(255,255,255,.012); }
|
|
633
|
-
.md-table { width:100%; border-collapse:separate; border-spacing:3px; font-size:12px; line-height:1.5; }
|
|
634
|
-
.md-table th, .md-table td { padding:6px 9px; text-align:left; vertical-align:top; border:1px solid rgba(255,255,255,.035); border-radius:6px; }
|
|
635
|
-
.md-table th { color:var(--muted); font-weight:600; background:rgba(255,255,255,.03); }
|
|
636
|
-
.md-table td { color:#d8d3cc; }
|
|
637
|
-
.decision-tags-block { display:flex; align-items:center; gap:8px; }
|
|
638
|
-
.evidence { margin:0; padding: 16px; white-space:break-spaces; font-size:12px; line-height:1.6; color:#cdc7bf;
|
|
639
|
-
background:#0b0b0e; border:1px solid var(--border); border-radius:var(--radius); }
|
|
640
|
-
.evidence-block { display:flex; flex-direction:column; gap:6px; }
|
|
641
|
-
.evidence-head { display:flex; justify-content:flex-end; }
|
|
642
|
-
.code-lang { font-family:var(--font-mono); font-size:9.5px; font-weight:700; letter-spacing:.1em; text-transform:uppercase; color:var(--muted-2); }
|
|
643
|
-
.code-evidence { white-space:pre; overflow:auto; }
|
|
644
|
-
.tok-keyword { color:#c792ea; }
|
|
645
|
-
.tok-string { color:#9ddc8a; }
|
|
646
|
-
.tok-comment { color:#6d6862; font-style:italic; }
|
|
647
|
-
.tok-number { color:#8fc7ff; }
|
|
648
|
-
.tok-type { color:var(--accent-strong); }
|
|
649
|
-
.tok-function { color:#82aaff; }
|
|
650
|
-
.tok-property { color:#e6c07b; }
|
|
651
|
-
.tok-punct { color:#8d8a85; }
|
|
652
|
-
.tags { display:flex; flex-wrap:wrap; align-items:center; gap:7px; margin-left: auto; }
|
|
653
|
-
.tags-label { display:inline-flex; align-items:center; gap:6px; font-size:10px; font-weight:700; letter-spacing:.1em; text-transform:uppercase; color:var(--muted-2); }
|
|
654
|
-
.tag { display:inline-flex; align-items:center; gap:6px; padding:3px 9px; font-family:var(--font-mono); font-size:11px; color:var(--muted);
|
|
655
|
-
background:var(--surface-2); border:1px solid var(--border); border-radius:999px; }
|
|
656
|
-
.decisions { display:inline-flex; gap:3px; align-self:flex-start; padding:4px; background:var(--surface-2); border:1px solid var(--border); border-radius:999px; }
|
|
657
|
-
.dec-btn { font:inherit; font-size:12px; font-weight:600; cursor:pointer; color:var(--muted); padding:6px 15px;
|
|
658
|
-
background:transparent; border:1px solid transparent; border-radius:999px; transition:color .15s ease, background .15s ease; }
|
|
659
|
-
.dec-btn:hover { color:var(--fg); }
|
|
660
|
-
.dec-btn:disabled { opacity:.55; cursor:not-allowed; }
|
|
661
|
-
.dec-btn.dec-execute.active { color:#1b1305; background:linear-gradient(180deg, var(--accent-strong), var(--accent)); }
|
|
662
|
-
.dec-btn.dec-ignore.active { color:#ffd2d3; background:rgba(242,89,94,.18); box-shadow:inset 0 0 0 1px rgba(242,89,94,.45); }
|
|
663
|
-
.dec-btn.dec-pending.active { color:var(--fg); background:rgba(255,255,255,.08); box-shadow:inset 0 0 0 1px var(--border-strong); }
|
|
664
|
-
.comment { position:relative; }
|
|
665
|
-
.comment textarea { width:100%; min-height:58px; padding:11px 13px 26px; resize:vertical; font:inherit; font-size:12.5px; line-height:1.5;
|
|
666
|
-
color:var(--fg); background:var(--surface-2); border:1px solid var(--border-strong); border-radius:var(--radius); outline:none;
|
|
667
|
-
transition:border-color .15s ease, box-shadow .15s ease; }
|
|
668
|
-
.comment textarea::placeholder { color:var(--muted-2); }
|
|
669
|
-
.comment textarea:focus { border-color:var(--accent-line); box-shadow:0 0 0 3px rgba(240,165,44,.12); }
|
|
670
|
-
.comment-status { position:absolute; right:12px; bottom:9px; display:inline-flex; align-items:center; gap:6px;
|
|
671
|
-
font-family:var(--font-mono); font-size:11px; color:var(--muted); }
|
|
672
|
-
.comment-status.saved { color:var(--success); }
|
|
673
|
-
.artifacts { display:flex; flex-direction:column; }
|
|
674
|
-
.artifact-layout { display:grid; grid-template-columns:minmax(190px,250px) minmax(0,1fr); gap:16px; align-items:start; }
|
|
675
|
-
.artifact-list { display:flex; flex-direction:column; gap:14px; max-height:72vh; overflow:auto; padding:2px 4px 2px 0; }
|
|
676
|
-
.artifact-group { display:flex; flex-direction:column; gap:4px; }
|
|
677
|
-
.artifact-group-label { margin:0 0 2px; font-size:10px; font-weight:700; letter-spacing:.14em; text-transform:uppercase; color:var(--muted); }
|
|
678
|
-
.artifact-item { display:flex; flex-direction:column; gap:2px; text-align:left; cursor:pointer; font:inherit; color:var(--muted);
|
|
679
|
-
padding:8px 10px; background:transparent; border:1px solid transparent; border-radius:10px;
|
|
680
|
-
transition:background .15s ease, border-color .15s ease, color .15s ease; }
|
|
681
|
-
.artifact-item:hover { color:var(--fg); background:var(--surface-2); border-color:var(--border); }
|
|
682
|
-
.artifact-item.active { color:var(--fg); background:var(--accent-soft); border-color:var(--accent-line); }
|
|
683
|
-
.artifact-item-name { font-family:var(--font-mono); font-size:11.5px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
|
|
684
|
-
.artifact-item-kind { font-size:9.5px; font-weight:700; letter-spacing:.1em; text-transform:uppercase; color:var(--muted-2); }
|
|
685
|
-
.artifact-item.active .artifact-item-kind { color:var(--accent); }
|
|
686
|
-
.artifact-pane { min-width:0; }
|
|
687
|
-
.artifact-head { display:flex; align-items:flex-start; justify-content:space-between; gap:14px; margin-bottom:12px; }
|
|
688
|
-
.artifact-title { margin:0 0 5px; font-family:var(--font-mono); font-size:13px; font-weight:600; word-break:break-word; }
|
|
689
|
-
.artifact-desc { margin:0; max-width:78ch; color:var(--muted); font-size:12.5px; line-height:1.55; }
|
|
690
|
-
.artifact-kind-badge { flex:none; display:inline-flex; align-items:center; padding:3px 9px; font-size:10px; font-weight:700;
|
|
691
|
-
letter-spacing:.08em; text-transform:uppercase; color:var(--accent); background:var(--accent-soft);
|
|
692
|
-
border:1px solid var(--accent-line); border-radius:999px; }
|
|
693
|
-
.artifact-view { margin:0; padding:14px 16px; max-height:70vh; overflow:auto; font-size:12px; line-height:1.6; color:#cdc7bf;
|
|
694
|
-
background:#0b0b0e; border:1px solid var(--border); border-radius:var(--radius); }
|
|
695
|
-
.artifact-markdown { white-space:normal; }
|
|
696
|
-
.artifact-markdown .md-p, .artifact-markdown .md-list, .artifact-markdown .md-quote { font-size:12.5px; }
|
|
697
|
-
.artifact-markdown .md-p, .artifact-markdown .md-list { color:#d8d3cc; }
|
|
698
|
-
.artifact-markdown .md-code-block { border:1px solid var(--border); }
|
|
699
|
-
.json-view { white-space:pre; }
|
|
700
|
-
.json-key { color:var(--accent-strong); }
|
|
701
|
-
.json-string { color:#9ddc8a; }
|
|
702
|
-
.json-number { color:#8fc7ff; }
|
|
703
|
-
.json-literal { color:#d7a6ff; }
|
|
704
|
-
.json-punct { color:#8d8a85; }
|
|
705
|
-
@media (max-width:900px) { .artifact-layout { grid-template-columns:1fr; } .artifact-list { max-height:240px; } }
|
|
706
|
-
.sent-tag { display:inline-flex; align-items:center; gap:5px; padding:2px 8px; font-size:10px; font-weight:700; letter-spacing:.06em; text-transform:uppercase;
|
|
707
|
-
color:var(--success); background:rgba(69,192,122,.12); border:1px solid rgba(69,192,122,.32); border-radius:999px; text-decoration:none; }
|
|
708
|
-
.sent-tag:hover { color:#fff; }
|
|
709
|
-
.sent-tag.gh { color:#b9c7d6; background:rgba(139,164,191,.12); border-color:rgba(139,164,191,.35); }
|
|
710
|
-
.sent-tag.gh:hover { color:#fff; background:rgba(139,164,191,.2); }
|
|
711
|
-
.resume { display:flex; flex-direction:column; }
|
|
712
|
-
.resume-hero { display:flex; align-items:flex-start; justify-content:space-between; gap:16px; padding:18px 20px;
|
|
713
|
-
background:linear-gradient(135deg, rgba(240,165,44,.08), rgba(255,255,255,.015) 55%);
|
|
714
|
-
border:1px solid var(--border); border-radius:var(--radius-lg); }
|
|
715
|
-
.resume-kicker { display:block; font-size:10px; font-weight:700; letter-spacing:.14em; text-transform:uppercase; color:var(--accent); }
|
|
716
|
-
.resume-title { margin:5px 0 7px; font-size:22px; font-weight:700; letter-spacing:-.02em; word-break:break-word; }
|
|
717
|
-
.resume-meta { display:flex; flex-wrap:wrap; align-items:center; gap:12px; margin:0; font-size:12px; color:var(--muted); }
|
|
718
|
-
.resume-pr { display:inline-flex; align-items:center; gap:5px; color:var(--accent-strong); text-decoration:none; }
|
|
719
|
-
.resume-pr:hover { text-decoration:underline; }
|
|
720
|
-
.resume-hero-side { display:flex; flex:none; flex-direction:column; align-items:flex-end; gap:10px; }
|
|
721
|
-
.resume-status { display:inline-flex; align-items:center; padding:5px 12px; font-size:11px; font-weight:700; letter-spacing:.04em; border-radius:999px; }
|
|
722
|
-
.resume-status.blocking { color:var(--blocking); background:rgba(242,89,94,.12); border:1px solid rgba(242,89,94,.35); }
|
|
723
|
-
.resume-status.attention { color:var(--attention); background:rgba(237,161,58,.12); border:1px solid rgba(237,161,58,.35); }
|
|
724
|
-
.resume-status.clean { color:var(--success); background:rgba(69,192,122,.12); border:1px solid rgba(69,192,122,.35); }
|
|
725
|
-
.resume-kpis { margin:14px 0 18px; }
|
|
726
|
-
.resume-kpis .kpi-value { font-size:24px; }
|
|
727
|
-
.churn-add { color:var(--success); }
|
|
728
|
-
.churn-del { color:var(--blocking); }
|
|
729
|
-
.churn-sep { margin:0 3px; color:var(--muted-2); font-weight:400; }
|
|
730
|
-
.kpi-blocking .kpi-value { color:var(--blocking); }
|
|
731
|
-
.kpi-attention .kpi-value { color:var(--attention); }
|
|
732
|
-
.kpi-total .kpi-value { color:var(--fg); }
|
|
733
|
-
.resume-grid { display:grid; grid-template-columns:minmax(0,1.35fr) minmax(0,1fr); gap:16px; align-items:start; }
|
|
734
|
-
.resume-card { min-width:0; padding:16px 18px; background:var(--card); border:1px solid var(--border); border-radius:var(--radius-lg); }
|
|
735
|
-
.resume-card-head { display:flex; align-items:center; justify-content:space-between; gap:10px; }
|
|
736
|
-
.resume-card-title { margin:0 0 10px; font-size:12px; font-weight:700; letter-spacing:.1em; text-transform:uppercase; color:var(--muted); }
|
|
737
|
-
.resume-card-count { display:inline-flex; align-items:center; justify-content:center; min-width:22px; height:22px; margin-bottom:10px; padding:0 7px;
|
|
738
|
-
font-family:var(--font-mono); font-size:11px; color:var(--accent); background:var(--accent-soft); border:1px solid var(--accent-line); border-radius:999px; }
|
|
739
|
-
.resume-narrative .md-p:last-child { margin-bottom:0; }
|
|
740
|
-
.resume-domains { display:flex; flex-direction:column; gap:8px; margin:0; padding:0; list-style:none; }
|
|
741
|
-
.resume-domain { display:flex; flex-direction:column; gap:7px; padding:10px 12px; background:var(--surface-2);
|
|
742
|
-
border:1px solid var(--border); border-radius:10px; }
|
|
743
|
-
.resume-domain-head { display:flex; align-items:baseline; justify-content:space-between; gap:10px; }
|
|
744
|
-
.resume-domain-name { font-size:12.5px; font-weight:600; color:var(--fg); }
|
|
745
|
-
.resume-domain-files { flex:none; font-family:var(--font-mono); font-size:10.5px; color:var(--muted-2); }
|
|
746
|
-
.resume-domain-sev { display:flex; flex-wrap:wrap; gap:6px; }
|
|
747
|
-
.resume-domain-sev .sev-badge { padding:2px 7px; font-size:9.5px; }
|
|
748
|
-
.resume-domain-ok { font-size:11.5px; color:var(--success); }
|
|
749
|
-
@media (max-width:900px) { .resume-grid { grid-template-columns:1fr; } .resume-hero { flex-direction:column; } .resume-hero-side { flex-direction:row; align-items:flex-start; } }
|
|
750
|
-
.modal-layer { position:fixed; inset:0; z-index:50; display:grid; place-items:center; padding:24px; }
|
|
751
|
-
.modal-backdrop { position:absolute; inset:0; width:100%; padding:0; background:rgba(5,5,7,.66); border:0; cursor:default; backdrop-filter:blur(5px); -webkit-backdrop-filter:blur(5px); }
|
|
752
|
-
.modal { position:relative; width:min(640px, 100%); max-height:min(78vh, 780px); display:flex; flex-direction:column; overflow:hidden;
|
|
753
|
-
background:var(--surface); border:1px solid var(--border-strong); border-radius:var(--radius-lg); box-shadow:0 24px 70px rgba(0,0,0,.5); }
|
|
754
|
-
.modal-head { display:flex; align-items:flex-start; justify-content:space-between; gap:14px; padding:18px 20px 14px; border-bottom:1px solid var(--border); }
|
|
755
|
-
.modal-title { margin:0; font-size:17px; font-weight:700; letter-spacing:-.01em; }
|
|
756
|
-
.modal-sub { margin:5px 0 0; font-size:12px; color:var(--muted); line-height:1.5; }
|
|
757
|
-
.modal-close { flex:none; display:grid; place-items:center; width:30px; height:30px; font:inherit; font-size:19px; line-height:1; color:var(--muted); background:transparent; border:1px solid var(--border); border-radius:9px; cursor:pointer; }
|
|
758
|
-
.modal-close:hover { color:var(--fg); border-color:var(--border-strong); }
|
|
759
|
-
.modal-body { display:flex; flex-direction:column; gap:16px; padding:16px 20px; overflow-y:auto; }
|
|
760
|
-
.modal-foot { display:flex; align-items:center; justify-content:space-between; gap:12px; padding:14px 20px; background:var(--surface-2); border-top:1px solid var(--border); }
|
|
761
|
-
.submit-field { display:flex; flex-direction:column; gap:8px; }
|
|
762
|
-
.submit-label { font-size:10px; font-weight:700; letter-spacing:.14em; text-transform:uppercase; color:var(--muted-2); }
|
|
763
|
-
.submit-summary { padding:13px 15px; font-size:12.5px; color:var(--fg); background:var(--accent-soft); border:1px solid var(--accent-line); border-radius:var(--radius); }
|
|
764
|
-
.submit-summary b { font-family:var(--font-mono); }
|
|
765
|
-
.submit-list { display:flex; flex-direction:column; gap:6px; max-height:240px; overflow-y:auto; padding-right:2px; }
|
|
766
|
-
.submit-item { display:flex; align-items:center; gap:10px; padding:8px 11px; font-size:12px; background:var(--surface-2); border:1px solid var(--border); border-radius:10px; }
|
|
767
|
-
.submit-item.sent { opacity:.7; }
|
|
768
|
-
.submit-item .rule { flex:1; min-width:0; color:var(--muted); overflow:hidden; white-space:nowrap; text-overflow:ellipsis; }
|
|
769
|
-
.submit-empty { color:var(--muted); font-size:12.5px; }
|
|
770
|
-
.submit-field .chips { flex-wrap:wrap; }
|
|
771
|
-
.submit-check { display:inline-flex; align-items:center; gap:8px; font-size:12.5px; color:var(--muted); cursor:pointer; }
|
|
772
|
-
.submit-check input { accent-color:var(--accent); }
|
|
773
|
-
.submit-actions { display:flex; align-items:center; gap:8px; }
|
|
774
|
-
.sev-badge.sev-blocking { color:var(--blocking); background:rgba(242,89,94,.12); }
|
|
775
|
-
.sev-badge.sev-attention { color:var(--attention); background:rgba(237,161,58,.12); }
|
|
776
|
-
.sev-badge.sev-suggestion { color:var(--suggestion); background:rgba(90,164,240,.12); }
|
|
777
|
-
.sev-badge.sev-nit { color:var(--nit); background:rgba(255,255,255,.06); }
|
|
778
|
-
@keyframes pulse { 0%,100% { opacity:1; transform:scale(1); } 50% { opacity:.4; transform:scale(.8); } }
|
|
779
|
-
@keyframes spin { to { transform:rotate(360deg); } }
|
|
780
|
-
@media (max-width:980px) { .kpis { grid-template-columns:repeat(2, minmax(0,1fr)); } }
|
|
781
|
-
@media (max-width:820px) {
|
|
782
|
-
.sidebar { width:232px; flex-basis:232px; }
|
|
783
|
-
.topbar { padding:12px 16px; }
|
|
784
|
-
.content { padding:18px 16px 56px; }
|
|
785
|
-
.auto-refresh { display:none; }
|
|
786
|
-
}
|
|
787
|
-
`;
|
|
788
|
-
|
|
789
402
|
/** Id de build por processo — muda a URL do bundle a cada reinício do servidor. */
|
|
790
403
|
const BUILD_ID = Date.now().toString(36);
|
|
791
404
|
|
|
@@ -797,11 +410,12 @@ function renderShell(): string {
|
|
|
797
410
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
798
411
|
<meta name="color-scheme" content="dark" />
|
|
799
412
|
<title>Houndsman — Revisões</title>
|
|
413
|
+
<link rel="icon" type="image/png" href="/assets/${LOGO_FILE}" />
|
|
800
414
|
<!-- Fontes de CDN: se estiver offline, o CSS cai para a pilha de sistema. -->
|
|
801
415
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
802
416
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
803
417
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" />
|
|
804
|
-
<
|
|
418
|
+
<link rel="stylesheet" href="/assets/${STYLES_FILE}?v=${BUILD_ID}" />
|
|
805
419
|
</head>
|
|
806
420
|
<body>
|
|
807
421
|
<div id="app"></div>
|