@fullstackhouse/cerber 0.18.2 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -1
- package/dist/core/artifact.js +8 -1
- package/dist/core/diff.js +19 -7
- package/dist/runner/prompt.js +28 -0
- package/package.json +1 -1
- package/web/dist/assets/{index-Cg6579bg.css → index-9eOzcIGo.css} +1 -1
- package/web/dist/assets/index-BETPG0t0.js +236 -0
- package/web/dist/index.html +2 -2
- package/web/dist/assets/index-BPX9h5Ec.js +0 -236
package/README.md
CHANGED
|
@@ -109,6 +109,13 @@ about, each waiting for you to keep, rewrite, or drop it:
|
|
|
109
109
|
|
|
110
110
|

|
|
111
111
|
|
|
112
|
+
Any line of the diff is one click away from being talked about: hover it and a
|
|
113
|
+
`+` appears in the gutter, the way it does on GitHub. What opens is one box
|
|
114
|
+
with two exits — write the comment yourself, or ask the reviewer about that
|
|
115
|
+
line and get the answer in the conversation below. A line the PR removes can be
|
|
116
|
+
asked about too; a comment on one posts on the file, since GitHub only takes
|
|
117
|
+
inline comments on the new side of a diff.
|
|
118
|
+
|
|
112
119
|
Artifacts are plain JSON you can `cat`, edit, or pipe into anything.
|
|
113
120
|
|
|
114
121
|
The queue is meant to be walked, not clicked through: `j`/`k` move the cursor
|
|
@@ -304,7 +311,10 @@ the exchange went anywhere near GitHub.
|
|
|
304
311
|
will tell you one of them needs changing rather than rewriting it. Say so
|
|
305
312
|
explicitly and it will.
|
|
306
313
|
- **Point at things.** *discuss* on any comment, chapter, or the summary drops
|
|
307
|
-
a reference into your next message.
|
|
314
|
+
a reference into your next message. From the diff's own gutter, *ask the
|
|
315
|
+
reviewer* points at one line and sends the question there and then — the
|
|
316
|
+
line comes along quoted, so it answers about that line rather than counting
|
|
317
|
+
rows.
|
|
308
318
|
- **Reset** puts the review back the way the AI first wrote it and keeps the
|
|
309
319
|
conversation — you lose the edits, not the reasoning.
|
|
310
320
|
|
package/dist/core/artifact.js
CHANGED
|
@@ -153,8 +153,15 @@ export const ChatTurnSchema = z.object({
|
|
|
153
153
|
/** What the user pointed at with "discuss this" — user turns only. */
|
|
154
154
|
refs: z
|
|
155
155
|
.array(z.object({
|
|
156
|
-
target: z.enum(["summary", "verdict", "chapter", "comment"]),
|
|
156
|
+
target: z.enum(["summary", "verdict", "chapter", "comment", "line"]),
|
|
157
157
|
id: z.string().nullable().default(null),
|
|
158
|
+
/** A "line" ref: the file, and the line as numbered on `side`. */
|
|
159
|
+
path: z.string().nullish(),
|
|
160
|
+
line: z.number().nullish(),
|
|
161
|
+
/** Which column of the diff the number came from — a removed line is
|
|
162
|
+
only numbered on the old side, and can still be asked about.
|
|
163
|
+
Absent means the new side. */
|
|
164
|
+
side: z.enum(["new", "old"]).optional(),
|
|
158
165
|
}))
|
|
159
166
|
.default([]),
|
|
160
167
|
/** Edits this turn made to the review. Assistant turns only. */
|
package/dist/core/diff.js
CHANGED
|
@@ -47,17 +47,29 @@ export function patchForFiles(diff, files) {
|
|
|
47
47
|
* lines inside hunks — exactly the lines a GitHub comment can attach to.
|
|
48
48
|
*/
|
|
49
49
|
export function newSideLineText(diff) {
|
|
50
|
+
return sideLineText(diff, "new");
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Old-side lines with their text, per file: removed and context lines. Nothing
|
|
54
|
+
* can be posted against these — they only exist to quote a line the PR took
|
|
55
|
+
* out, which is a fair thing to ask the reviewer about.
|
|
56
|
+
*/
|
|
57
|
+
export function oldSideLineText(diff) {
|
|
58
|
+
return sideLineText(diff, "old");
|
|
59
|
+
}
|
|
60
|
+
function sideLineText(diff, side) {
|
|
61
|
+
const own = side === "new" ? "+" : "-";
|
|
50
62
|
const result = new Map();
|
|
51
63
|
for (const { path, patch } of splitDiffByFile(diff)) {
|
|
52
64
|
const lines = new Map();
|
|
53
|
-
let
|
|
65
|
+
let n = 0;
|
|
54
66
|
let inHunk = false;
|
|
55
67
|
const patchLines = patch.split("\n");
|
|
56
68
|
for (let i = 0; i < patchLines.length; i++) {
|
|
57
69
|
const line = patchLines[i];
|
|
58
|
-
const hunk = line.match(/^@@
|
|
70
|
+
const hunk = line.match(/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/);
|
|
59
71
|
if (hunk) {
|
|
60
|
-
|
|
72
|
+
n = Number(side === "new" ? hunk[2] : hunk[1]);
|
|
61
73
|
inHunk = true;
|
|
62
74
|
continue;
|
|
63
75
|
}
|
|
@@ -67,11 +79,11 @@ export function newSideLineText(diff) {
|
|
|
67
79
|
continue; // trailing split artifact
|
|
68
80
|
if (line.startsWith("\\"))
|
|
69
81
|
continue; // ""
|
|
70
|
-
if (line.startsWith(
|
|
71
|
-
lines.set(
|
|
72
|
-
|
|
82
|
+
if (line.startsWith(own) || line.startsWith(" ") || line === "") {
|
|
83
|
+
lines.set(n, line === "" ? "" : line.slice(1));
|
|
84
|
+
n++;
|
|
73
85
|
}
|
|
74
|
-
//
|
|
86
|
+
// The other side's lines don't exist on this one.
|
|
75
87
|
}
|
|
76
88
|
result.set(path, lines);
|
|
77
89
|
}
|
package/dist/runner/prompt.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { newSideLineText, oldSideLineText } from "../core/diff.js";
|
|
1
2
|
/** Keep the prompt within a sane context budget. */
|
|
2
3
|
export const MAX_DIFF_CHARS = 300_000;
|
|
3
4
|
/** Told to the model only when a checkout backs it up. */
|
|
@@ -126,6 +127,17 @@ ${diffBody}
|
|
|
126
127
|
function describeRefs(artifact, refs) {
|
|
127
128
|
if (refs.length === 0)
|
|
128
129
|
return "";
|
|
130
|
+
// Quoting a line means walking the whole diff, so each side is walked at
|
|
131
|
+
// most once per turn — and not at all unless a line ref asks for it.
|
|
132
|
+
const walked = new Map();
|
|
133
|
+
const sideText = (side) => {
|
|
134
|
+
const already = walked.get(side);
|
|
135
|
+
if (already)
|
|
136
|
+
return already;
|
|
137
|
+
const text = (side === "old" ? oldSideLineText : newSideLineText)(artifact.diff);
|
|
138
|
+
walked.set(side, text);
|
|
139
|
+
return text;
|
|
140
|
+
};
|
|
129
141
|
const lines = refs.map((ref) => {
|
|
130
142
|
if (ref.target === "summary")
|
|
131
143
|
return "- the summary";
|
|
@@ -135,6 +147,8 @@ function describeRefs(artifact, refs) {
|
|
|
135
147
|
const ch = artifact.chapters.find((c) => c.id === ref.id);
|
|
136
148
|
return `- the chapter "${ch?.title ?? ref.id}" (chapterId: ${ref.id})`;
|
|
137
149
|
}
|
|
150
|
+
if (ref.target === "line")
|
|
151
|
+
return describeLineRef(ref, sideText);
|
|
138
152
|
const c = artifact.comments.find((x) => x.id === ref.id);
|
|
139
153
|
return c
|
|
140
154
|
? `- the comment on ${c.path}:${c.line ?? "file"} (commentId: ${c.id})`
|
|
@@ -142,6 +156,20 @@ function describeRefs(artifact, refs) {
|
|
|
142
156
|
});
|
|
143
157
|
return `\n## What the user is pointing at\n\n${lines.join("\n")}\n`;
|
|
144
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* A line of the diff the user clicked, quoted back so the model is looking at
|
|
161
|
+
* the same thing they are — a number alone would make it count rows.
|
|
162
|
+
*/
|
|
163
|
+
function describeLineRef(ref, sideText) {
|
|
164
|
+
if (ref.path == null || ref.line == null)
|
|
165
|
+
return "- a line of the diff";
|
|
166
|
+
const removed = ref.side === "old";
|
|
167
|
+
const where = `${ref.path}:${ref.line}${removed ? " (a line this PR removes)" : ""}`;
|
|
168
|
+
const text = sideText(removed ? "old" : "new")
|
|
169
|
+
.get(ref.path)
|
|
170
|
+
?.get(ref.line);
|
|
171
|
+
return text?.trim() ? `- ${where} — \`${text.trim()}\`` : `- ${where}`;
|
|
172
|
+
}
|
|
145
173
|
/** The review as it stands right now, with the ids a revision has to name. */
|
|
146
174
|
function renderReview(artifact) {
|
|
147
175
|
const chapters = artifact.chapters
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fullstackhouse/cerber",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"description": "AI code-review cockpit: Claude reviews your PRs into local artifacts; nothing reaches GitHub until you say so.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Full Stack House (https://fullstack.house)",
|
|
@@ -7,4 +7,4 @@
|
|
|
7
7
|
|
|
8
8
|
Outdated base version: https://github.com/primer/github-syntax-light
|
|
9
9
|
Current colors taken from GitHub's CSS
|
|
10
|
-
*/.hljs{color:#24292e;background:#fff}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#d73a49}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#6f42c1}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-variable,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id{color:#005cc5}.hljs-regexp,.hljs-string,.hljs-meta .hljs-string{color:#032f62}.hljs-built_in,.hljs-symbol{color:#e36209}.hljs-comment,.hljs-code,.hljs-formula{color:#6a737d}.hljs-name,.hljs-quote,.hljs-selector-tag,.hljs-selector-pseudo{color:#22863a}.hljs-subst{color:#24292e}.hljs-section{color:#005cc5;font-weight:700}.hljs-bullet{color:#735c0f}.hljs-emphasis{color:#24292e;font-style:italic}.hljs-strong{color:#24292e;font-weight:700}.hljs-addition{color:#22863a;background-color:#f0fff4}.hljs-deletion{color:#b31d28;background-color:#ffeef0}:root{--bg: #fcfcfd;--surface: #ffffff;--fg: #14171a;--fg-2: #3a3f45;--fg-3: #4a5058;--muted: #6b7178;--faint: #9aa0a8;--fainter: #b6bbc1;--line: #e6e8eb;--line-2: #dcdfe4;--line-3: #eef0f2;--accent: #3d4fd6;--accent-dark: #2c3aa8;--accent-wash: #f4f5ff;--green: #1a7f5a;--amber: #a06a00;--red: #c2314a;--mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;--prose: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Helvetica, sans-serif;--measure: 1560px}*{box-sizing:border-box}body{margin:0;font-family:var(--mono);font-size:12px;color:var(--fg);background:var(--bg)}a{color:var(--accent)}a:hover{color:var(--accent-dark)}h1,h2,h3{font-size:13px;font-weight:700;margin:0}.app{padding-bottom:48px}.wrap{max-width:var(--measure);margin:0 auto;padding:0 40px}.bar-inner{max-width:var(--measure);margin:0 auto;padding:0 40px;display:flex;align-items:center;gap:14px}.grow{flex-grow:1}.pad{padding:24px 40px}.muted,.faint{color:var(--faint)}.warn{color:var(--amber)}.danger{color:var(--red)}.add{color:var(--green)}.del{color:var(--red)}.icon{flex-shrink:0}.lab{font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--faint)}.key{font-size:10px;border:1px solid var(--line-2);border-bottom-width:2px;border-radius:3px;padding:1px 5px;color:var(--muted);background:var(--surface)}.hint{display:inline-flex;gap:5px;align-items:center;font-size:10.5px;color:var(--faint);white-space:nowrap}.prose{font-family:var(--prose);font-size:13px;line-height:1.6;color:var(--fg-2);text-wrap:pretty;max-width:720px}.prose.lead{font-size:13.5px;line-height:1.62;color:var(--fg)}.error{color:var(--red);background:#c2314a0f;border:1px solid rgba(194,49,74,.3);padding:8px 12px;border-radius:4px;margin:10px 0}.empty{text-align:center;color:var(--faint);margin:64px auto;flex-direction:column}.empty pre{display:inline-block;background:var(--line-3);padding:8px 16px;border-radius:4px}button{font:inherit;cursor:pointer}.btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;font-size:11px;color:var(--fg-3);border:1px solid var(--line-2);border-radius:4px;padding:6px 10px;background:var(--surface);white-space:nowrap;text-decoration:none}.btn:hover:not(:disabled){color:var(--fg);border-color:var(--fainter)}.btn:disabled{opacity:.5;cursor:default}.btn-sm{font-size:10.5px;padding:3px 8px;gap:5px}.btn-accent{color:var(--accent);border-color:#3d4fd659}.btn-keep-on{color:#fff;background:var(--green);border-color:var(--green)}.btn-drop-on{color:var(--red);border-color:#c2314a66}.btn-dark{color:#fff;background:var(--fg);border-color:var(--fg);font-size:11.5px;padding:7px 14px}.btn-dark:disabled{color:var(--faint);background:#f0f1f3;border-color:var(--line-2)}.btn-dashed{display:inline-flex;align-items:center;gap:5px;font-size:10.5px;color:var(--muted);border:1px dashed var(--line-2);border-radius:4px;padding:5px 10px;background:transparent;margin-top:10px}.btn-primary{display:flex;align-items:center;justify-content:center;gap:8px;height:40px;padding:0 14px;font-size:12px;font-weight:500;color:#fff;background:var(--accent);border:1px solid var(--accent);border-radius:4px}.btn-primary .key{border-color:#ffffff4d;color:#ffffffbf;background:transparent}.link{display:inline-flex;align-items:center;gap:5px;font:inherit;font-size:11px;color:var(--accent);background:none;border:none;padding:0;text-decoration:none}.link:hover:not(:disabled){color:var(--accent-dark)}.link:disabled{color:var(--faint);cursor:default}.topbar{border-bottom:1px solid var(--line);background:var(--surface)}.topbar .bar-inner{padding-top:14px;padding-bottom:14px}.brand{display:inline-flex;align-items:center;gap:7px;font-size:15px;font-weight:700;letter-spacing:-.02em;color:var(--fg);text-decoration:none}.brand .logo{color:var(--accent);flex-shrink:0}.tagline{font-size:11px;color:var(--faint)}.topbar-link{font-size:11px;color:var(--muted);text-decoration:none;border-left:1px solid var(--line);padding-left:14px;display:inline-flex;align-items:center}.topbar-link:hover{color:var(--fg)}.bell{background:none;border:0;border-left:1px solid var(--line);padding:0 0 0 14px;font-family:inherit;cursor:pointer}.bell-on,.bell-ask{color:var(--accent)}.bell-blocked{color:var(--fainter);cursor:help}.daemon-bar{border-bottom:1px solid var(--line);background:#f7f8fa;font-size:11px;color:var(--muted)}.daemon-bar .bar-inner{padding-top:8px;padding-bottom:8px;gap:18px;flex-wrap:wrap}.daemon-bar b{color:var(--fg);font-weight:400}.daemon-live{display:inline-flex;align-items:center;gap:6px;color:var(--fg)}.daemon-bar .warn{display:inline-flex;align-items:center;gap:6px}.dot{width:5px;height:5px;border-radius:999px;background:var(--green);display:inline-block}.dot-off{background:var(--fainter)}.tabs{display:flex;align-items:center;gap:2px;padding-top:14px}.tab{font-size:12px;padding:6px 12px;border:none;border-bottom:2px solid transparent;border-radius:4px 4px 0 0;background:none;color:var(--muted)}.tab:hover{color:var(--fg)}.tab-on{color:var(--fg);font-weight:500;border-bottom-color:var(--accent)}.tab-count{color:var(--fainter);margin-left:4px}.tab-on .tab-count{color:var(--accent)}.tab-split{width:1px;flex-shrink:0;align-self:stretch;margin:4px 10px 6px;background:var(--line-2)}.tab-filed{color:var(--faint)}.tab-filed:hover,.tab-filed.tab-on{color:var(--muted)}.tab-requests{color:var(--amber)}.tab-requests:hover,.tab-requests.tab-on{color:var(--amber);border-bottom-color:var(--amber)}.tab-requests .tab-count,.tab-requests.tab-on .tab-count{color:var(--amber)}.empty-tab{padding:22px 10px;font-size:12.5px;max-width:88ch}.empty-tab .btn{margin-top:10px}.table-head,.row{display:flex;gap:12px;align-items:center}.table-head{font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--faint);padding:12px 10px 7px;border-bottom:1px solid var(--line-2)}.row{font-size:12px;padding:8px 10px;cursor:pointer;border-bottom:1px solid var(--line-3);border-left:2px solid transparent}.row:hover{background:#f7f8fa}.row-on{background:var(--accent-wash);border-left-color:var(--accent)}.row-on .col-caret{color:var(--accent)}.row-on .col-title{font-weight:500}.tag-done{flex-shrink:0;color:var(--muted);background:var(--line-3)}.tag-awaiting{flex-shrink:0;color:var(--amber);background:#a06a001a}.pull{display:flex;align-items:center;gap:6px;position:relative;color:var(--muted)}.tabs .pull{margin-right:16px}.empty .pull{justify-content:center;margin-top:10px}.pull:hover,.pull:focus-within{color:var(--fg-3)}.pull-input{width:200px;max-width:100%;font:inherit;font-size:12px;padding:2px 0;color:var(--fg);background:transparent;border:none;border-bottom:1px solid transparent;transition:width .12s ease,border-color .12s ease}.pull-input:hover::placeholder{color:var(--fg)}.pull-input:focus{outline:none;width:320px;border-bottom-color:var(--accent)}.pull-input::placeholder{color:var(--muted);transition:color .12s ease}.btn-small{padding:2px 8px;font-size:10px}.pull-error{position:absolute;top:100%;right:0;z-index:5;margin-top:4px;max-width:360px;padding:5px 8px;font-size:11px;line-height:1.4;color:var(--red);background:var(--bg);border:1px solid var(--line-2);border-radius:4px;box-shadow:0 2px 8px #14171a14}.tag-draft{flex-shrink:0;color:var(--muted);background:var(--line-3)}.col-caret{width:12px;flex-shrink:0;color:transparent}.col-slug{width:184px;flex-shrink:0;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.col-title{flex-grow:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.col-author{width:104px;flex-shrink:0;color:var(--faint);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.col-verdict{width:136px;flex-shrink:0;text-align:right;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.col-comments{width:26px;flex-shrink:0;text-align:right;color:var(--muted)}.col-size{width:104px;flex-shrink:0;text-align:right;color:var(--muted)}.col-age{width:44px;flex-shrink:0;text-align:right;color:var(--faint)}.table-head .col-verdict,.table-head .col-slug,.table-head .col-author{color:var(--faint);font-weight:400}.cursor-strip{display:flex;gap:18px;align-items:flex-start;border:1px solid var(--line-2);border-top:none;border-radius:0 0 4px 4px;background:var(--surface);padding:14px 16px}.cursor-strip-body{flex-grow:1;min-width:0}.strip-prose{--strip-cap: 196px;--strip-fade: 46px;margin:6px 0 0;max-width:700px;max-height:var(--strip-cap);overflow:hidden}.strip-prose-clipped{-webkit-mask-image:linear-gradient(#000 calc(var(--strip-cap) - var(--strip-fade)),transparent var(--strip-cap));mask-image:linear-gradient(#000 calc(var(--strip-cap) - var(--strip-fade)),transparent var(--strip-cap))}.cursor-strip-body .md p{margin:5px 0}.cursor-strip-body .md ul,.cursor-strip-body .md ol{margin:5px 0;padding-left:17px}.cursor-strip-body .md li{margin:2px 0}.cursor-strip-body .md li::marker{color:var(--faint)}.cursor-strip-body .md strong{font-weight:600;color:var(--fg)}.cursor-strip-meta{font-size:10.5px;color:var(--faint);margin-top:8px}.cursor-strip-actions{display:flex;flex-direction:column;gap:6px;width:176px;flex-shrink:0}.cursor-strip-row{display:flex;gap:6px}.cursor-strip-row .btn{flex-grow:1;padding:7px 0}.review-top{position:sticky;top:0;z-index:20;background:var(--surface)}.crumb{border-bottom:1px solid var(--line);background:var(--surface);font-size:11.5px;color:var(--muted)}.crumb .bar-inner{padding-top:12px;padding-bottom:12px;gap:12px}.crumb a{text-decoration:none}.crumb-sep{color:var(--line-2)}.crumb-slug{color:var(--fg)}.crumb-next{font-size:11px;max-width:300px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.walk{display:inline-flex;gap:2px}.walk-btn{display:inline-flex;align-items:center;justify-content:center;padding:4px 6px;border:1px solid var(--line-2);border-radius:3px;background:var(--surface);color:var(--fg-3)}.walk-btn:disabled{color:#d4d7db;border-color:var(--line-3);cursor:default}.review-head{border-bottom:1px solid var(--line);background:var(--surface)}.review-head .wrap{padding-top:20px;padding-bottom:16px}.review-head-top,.review-head-meta{display:flex;align-items:center;gap:14px}.review-head-top{margin-bottom:8px}.review-title{font-size:19px;font-weight:700;letter-spacing:-.025em;color:var(--fg);text-decoration:none}.review-title:hover{color:var(--accent)}.review-head-meta{font-size:11px;color:var(--muted);gap:10px;flex-wrap:wrap}.verdict-pick{display:inline-flex;align-items:center;gap:5px;font-size:10.5px;padding:4px 9px;border-radius:4px;border:1px solid transparent;background:none;color:var(--faint);white-space:nowrap}.verdict-pick:hover{color:var(--fg-3)}.verdict-pick-on{background:#f0f1f3;border-color:var(--line-2);font-weight:500}.review-body{display:grid;align-items:start;grid-template-columns:236px minmax(0,1fr);grid-template-areas:"rail main" "rail cockpit"}.rail{grid-area:rail}.main{grid-area:main}.cockpit{grid-area:cockpit;min-width:0;padding-bottom:18px}.rail{padding:22px 20px 22px 0;position:sticky;top:var(--top-h, 0px);z-index:5;max-height:calc(100vh - var(--top-h, 0px));overflow-y:auto}@media(min-width:1600px){.review{--measure: 2100px}.review-body{grid-template-columns:236px minmax(0,1fr) clamp(420px,34%,680px);grid-template-areas:"rail main cockpit"}.cockpit{position:sticky;top:var(--top-h, 0px);height:calc(100vh - var(--top-h, 0px));padding:22px 0 18px 22px;display:flex;flex-direction:column;justify-content:space-between;gap:10px}.cockpit .chat-panel{flex:0 1 auto;display:flex;flex-direction:column;min-height:120px;margin:0}.cockpit .chat-panel .card-body{display:flex;flex-direction:column;min-height:0}.cockpit .chat-log{flex:1 1 auto;min-height:0;overflow-y:auto}.cockpit .verdict-bar{margin-top:0}.cockpit-decide{flex:0 0 auto;max-height:65%;overflow-y:auto}}.chapter,.comment,.card-summary,.card-why,.chat-panel,.send-panel,.sent-strip,.verdict-bar{scroll-margin-top:calc(var(--top-h, 0px) + 12px)}.rail-lab{display:block;margin-top:22px}.rail-jumps{display:flex;flex-direction:column;align-items:flex-start;gap:7px}.rail .rail-jumps .lab{margin-bottom:0}.rail-lab-btn{display:block;width:100%;text-align:left;font:inherit;padding:0;background:none;border:none}.rail-lab-btn:hover{color:var(--fg)}.rail .lab{margin-bottom:10px}.rail-item{display:flex;align-items:center;gap:6px;width:100%;text-align:left;font:inherit;font-size:11.5px;line-height:1.5;padding:5px 0 5px 9px;margin-left:-11px;background:none;border:none;border-left:2px solid transparent;color:var(--muted)}.rail-item:hover{color:var(--fg)}.rail-item-on{border-left-color:var(--accent);color:var(--fg);font-weight:500}.rail-group{margin-bottom:2px}.rail-count{font-size:10.5px;color:var(--fainter)}.rail-comment{display:flex;align-items:center;gap:6px;width:100%;font:inherit;font-size:11px;text-align:left;padding:3px 0 3px 20px;margin-left:-11px;background:none;border:none;border-left:2px solid transparent;color:var(--muted)}.rail-comment:hover{color:var(--fg)}.rail-comment-loc{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rail-comment-dropped{opacity:.55}.rail-comment-dropped .rail-comment-loc{text-decoration:line-through}.rail-dot{font-size:8px}.comment-flash{animation:comment-flash 1.8s ease-out}@keyframes comment-flash{0%,60%{background:var(--accent-wash);box-shadow:inset 0 0 0 2px #3d4fd673}}.rail-facts{font-size:11.5px;line-height:1.85;color:var(--muted)}.rail-facts b{color:var(--fg);font-weight:400}.main{min-width:0;padding:22px 0 0}.card{border:1px solid var(--line);border-radius:4px;background:var(--surface);margin-bottom:10px}.card-head{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;padding:11px 16px;border-bottom:1px solid var(--line-3)}.card-head .faint{font-size:11px}.card-body{padding:14px 16px}.card-body .lab{display:block;margin-bottom:7px}.card-body .prose{margin:0}.card-body .btn{margin-top:12px}.card-why{margin-bottom:8px}.chapter{border:1px solid var(--line);border-radius:4px;background:var(--surface);margin-bottom:10px;overflow:hidden}.chapter-head{display:flex;align-items:center;gap:10px;padding:11px 16px;cursor:pointer;-webkit-user-select:none;user-select:none}.chapter-body{padding:14px 16px 16px;border-top:1px solid var(--line-3)}.chapter-meta{font-size:11px;font-weight:400}.chapter-explanation{margin:0 0 14px}.comment{border:1px solid var(--line);border-radius:4px;background:#fbfbfc;padding:12px 14px;margin:8px 0}.comment-dropped{opacity:.5}.comment-dropped .comment-body{text-decoration:line-through}.comment-head{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:6px}.comment-loc{font-size:10.5px;color:var(--faint)}.comment-body{font-size:13px;line-height:1.58;color:var(--fg);max-width:640px}.comment-edit,.add-comment textarea,.chat-input{width:100%;font-family:var(--mono);font-size:12.5px;line-height:1.55;color:var(--fg);padding:10px 12px;border:1px solid var(--line-2);border-radius:4px;background:var(--surface);resize:vertical}.add-comment{border:1px dashed var(--line-2);border-radius:4px;padding:10px 12px;margin:10px 0;display:flex;flex-direction:column;gap:8px}.add-comment-row{display:flex;gap:8px;align-items:center}.add-comment select,.add-comment input{font:inherit;font-size:11.5px;padding:5px 7px;border:1px solid var(--line-2);border-radius:4px;background:var(--surface)}.inline-comment-row td{padding:0;background:#fbfbfc;border-top:1px solid var(--line);border-bottom:1px solid var(--line);white-space:normal}.inline-comment-row .comment{margin:0;border:none;border-radius:0;padding-left:44px;max-width:none}.diff{margin-top:8px;font-size:11.5px}.diff .d2h-file-header,.diff .d2h-file-name{font-family:var(--mono);font-size:11px}.diff .d2h-code-line{white-space:normal;width:calc(100% - 9em);padding-right:1em}.diff .d2h-code-line-ctn{display:inline;width:auto;white-space:pre-wrap;overflow-wrap:anywhere}.diff .d2h-code-line ins,.diff .d2h-code-line del{display:inline}.diff .hljs{display:inline;padding:0;background:transparent;color:inherit}.freshness{background:#a06a0012;border:1px solid rgba(160,106,0,.3);color:#57430a;padding:10px 12px;border-radius:4px;margin-bottom:10px;line-height:1.55;font-size:11.5px}.freshness code{background:#0000000f;padding:1px 4px;border-radius:3px}.freshness-running{background:#3d4fd60f;border-color:#3d4fd64d;color:#26307a}.freshness .btn{margin-left:8px}.chat-panel{margin:18px 0 10px}.chat-log{display:flex;flex-direction:column;gap:14px;margin-bottom:14px}.chat-turn{border-left:2px solid var(--line-2);padding:2px 0 2px 12px}.chat-turn-user{border-left-color:var(--accent)}.chat-turn-pending{border-left-style:dashed}.chat-turn-who{font-size:10.5px;color:var(--faint);margin-bottom:4px}.chat-turn-body{max-width:700px;color:var(--fg)}.chat-revision{font-size:10.5px;color:var(--green);margin-top:6px}.chat-refusal{font-size:10.5px;color:var(--amber);margin-top:6px}.chat-waiting{font-size:11.5px;color:var(--muted);margin-top:6px}.chat-progress{list-style:none;margin:0;padding:0}.chat-progress li{opacity:.55;padding:1px 0}.chat-progress li.now{opacity:1}.chat-progress li.now:after{content:"…"}.chat-failed{font-size:11.5px;color:var(--red);margin-top:6px}.chat-refs{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-bottom:8px}.chat-ref{font-size:10.5px;font-family:var(--mono);padding:3px 9px;border:1px solid var(--line-2);border-radius:999px;color:var(--muted);background:transparent}.chat-refs-pending .chat-ref{cursor:pointer;color:var(--accent);border-color:#3d4fd659}.chat-actions{display:flex;align-items:center;gap:12px;margin-top:10px}.send-panel{border:1px solid var(--line-2);border-radius:4px;background:#f7f8fa;padding:16px 18px}.verdict-bar+.send-panel{border-radius:0 0 4px 4px}.send-top{display:flex;align-items:baseline;gap:12px;margin-bottom:14px}.send-top .faint{font-size:11px}.send-top .link{text-decoration:underline;text-underline-offset:2px}.send-action{display:flex;align-items:center;gap:16px;flex-wrap:wrap}.send-btn{display:inline-flex;align-items:center;gap:10px;height:44px;padding:0 20px;font-size:13px;font-weight:500;color:#fff;border:none;border-radius:4px;box-shadow:0 1px 2px #14171a1f}.send-btn:disabled{opacity:.6;cursor:default}.send-btn .key{border-color:#ffffff4d;color:#fffc;background:transparent}.send-as{position:relative}.send-as-toggle{font:inherit;font-size:11.5px;color:var(--fg-3);background:none;border:none;padding:0}.send-as-toggle b{color:var(--fg);font-weight:500;border-bottom:1px dotted var(--fainter)}.send-as-why{font-size:10.5px;color:var(--faint);margin-top:3px}.menu{position:absolute;top:34px;left:0;z-index:10;background:var(--surface);border:1px solid var(--line-2);border-radius:4px;box-shadow:0 6px 18px #14171a17;padding:4px;min-width:190px}.menu-item{display:flex;align-items:center;gap:9px;width:100%;font:inherit;font-size:11.5px;text-align:left;padding:7px 9px;border:none;border-radius:3px;background:none;color:var(--fg-3)}.menu-item:hover{background:#f7f8fa}.menu-item-on{background:#f4f5f7;color:var(--fg)}.menu-check{font-size:10px;color:var(--green)}.verdict-bar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;border:1px solid var(--line-2);border-bottom:none;border-radius:4px 4px 0 0;background:var(--surface);padding:10px 18px;margin-top:18px}.verdict-bar .lab{margin-right:4px}.verdict-bar .faint{font-size:10.5px}.send-footer{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:16px;padding-top:14px;border-top:1px solid var(--line-2);font-size:10.5px}.body-preview{margin-top:14px;padding:14px 16px;background:var(--surface);border:1px solid var(--line);border-radius:4px;font-family:var(--prose);font-size:12.5px;line-height:1.62;color:var(--fg-2);white-space:pre-wrap;max-width:760px;max-height:420px;overflow:auto}.sent-strip{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;border:1px solid rgba(26,127,90,.4);background:#1a7f5a12;border-radius:4px;padding:14px 16px;font-size:11.5px}.sent-strip strong{color:var(--green);font-size:13px;white-space:nowrap}.sent-strip a{display:inline-flex;align-items:center;gap:5px;white-space:nowrap;text-decoration:none}.post-actions{display:flex;align-items:center;gap:12px;margin-top:12px;font-size:10.5px}.post-actions .link{font-size:10.5px;color:var(--muted)}.post-actions .link:hover{color:var(--fg)}.md>:first-child{margin-top:0}.md>:last-child{margin-bottom:0}.md p{margin:8px 0}.md code{font-family:var(--mono);font-size:.9em;background:#f0f2f5;padding:1px 5px;border-radius:3px}.md pre{background:#f7f8fa;border:1px solid var(--line);border-radius:4px;padding:10px 12px;overflow-x:auto}.md pre code{background:none;padding:0;font-size:11.5px}.md ul,.md ol{margin:8px 0;padding-left:24px}.md blockquote{margin:8px 0;padding-left:12px;border-left:2px solid var(--line-2);color:var(--muted)}.md h1,.md h2,.md h3,.md h4{font-size:1em;font-weight:650;letter-spacing:-.01em;margin:18px 0 2px;color:var(--fg)}.md h1+p,.md h2+p,.md h3+p,.md h4+p,.md h1+ul,.md h2+ul,.md h3+ul,.md h4+ul{margin-top:4px}.settings{max-width:780px;margin:0 auto;padding:24px 40px 64px;font-family:var(--prose);font-size:13px;line-height:1.6;color:var(--fg-2)}.settings .back{display:inline-block;font-family:var(--mono);font-size:11.5px;text-decoration:none;margin-bottom:16px}.settings h1{font-family:var(--mono);font-size:15px;margin:32px 0 8px}.settings h2{font-family:var(--mono);font-size:13px;margin:28px 0 8px}.settings code{font-family:var(--mono);font-size:.92em;background:#f0f2f5;padding:1px 5px;border-radius:3px}.inbox-toggle{display:block;margin:8px 0}.trust-add{display:flex;gap:8px;margin:20px 0 12px}.trust-add input{flex:1;font:inherit;padding:7px 10px;color:var(--fg);border:1px solid var(--line-2);border-radius:4px;background:var(--surface)}.trust-table{border-collapse:collapse;width:100%}.trust-table td{padding:6px 10px 6px 0;border-bottom:1px solid var(--line);vertical-align:baseline}.trust-actions{text-align:right}.trust-deny code{text-decoration:line-through}.tone-approve{color:var(--green)}.tone-comment{color:var(--amber)}.tone-changes{color:var(--red)}.tone-running,.tone-sent,.tone-none{color:var(--muted);font-weight:400}.tone-failed{color:var(--red)}.tone-awaiting{color:var(--accent)}.tone-bg-approve{background:var(--green)}.tone-bg-comment{background:var(--amber)}.tone-bg-changes{background:var(--red)}.tone-border-approve{border-left:2px solid var(--green)}.tone-border-comment{border-left:2px solid var(--amber)}.tone-border-changes{border-left:2px solid var(--red)}.tone-border-none{border-left:2px solid var(--line-2)}.chip{font-size:11.5px;font-weight:500;padding:3px 9px;border-radius:3px;border:1px solid currentColor;background:#14171a08;white-space:nowrap}.chip-btn{display:inline-flex;align-items:center;gap:6px;font-family:inherit}.chip-btn:hover{background:#14171a12}.tag{font-size:10px;letter-spacing:.06em;padding:1px 6px;border-radius:3px;color:var(--muted);background:#f0f1f3;white-space:nowrap}.tag-yours{color:var(--accent);background:#3d4fd617}.tag-kept{color:var(--green);background:#1a7f5a1a}.tag-drift{color:var(--amber);background:#a06a001a}.sev-counts{font-size:12px;color:var(--muted);margin-bottom:6px}.verdict-hint{display:flex;align-items:center;gap:10px;flex-wrap:wrap;background:#a06a0012;border:1px solid rgba(160,106,0,.3);color:#57430a;padding:10px 12px;border-radius:4px}
|
|
10
|
+
*/.hljs{color:#24292e;background:#fff}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#d73a49}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#6f42c1}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-variable,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id{color:#005cc5}.hljs-regexp,.hljs-string,.hljs-meta .hljs-string{color:#032f62}.hljs-built_in,.hljs-symbol{color:#e36209}.hljs-comment,.hljs-code,.hljs-formula{color:#6a737d}.hljs-name,.hljs-quote,.hljs-selector-tag,.hljs-selector-pseudo{color:#22863a}.hljs-subst{color:#24292e}.hljs-section{color:#005cc5;font-weight:700}.hljs-bullet{color:#735c0f}.hljs-emphasis{color:#24292e;font-style:italic}.hljs-strong{color:#24292e;font-weight:700}.hljs-addition{color:#22863a;background-color:#f0fff4}.hljs-deletion{color:#b31d28;background-color:#ffeef0}:root{--bg: #fcfcfd;--surface: #ffffff;--fg: #14171a;--fg-2: #3a3f45;--fg-3: #4a5058;--muted: #6b7178;--faint: #9aa0a8;--fainter: #b6bbc1;--line: #e6e8eb;--line-2: #dcdfe4;--line-3: #eef0f2;--accent: #3d4fd6;--accent-dark: #2c3aa8;--accent-wash: #f4f5ff;--green: #1a7f5a;--amber: #a06a00;--red: #c2314a;--mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;--prose: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Helvetica, sans-serif;--measure: 1560px}*{box-sizing:border-box}body{margin:0;font-family:var(--mono);font-size:12px;color:var(--fg);background:var(--bg)}a{color:var(--accent)}a:hover{color:var(--accent-dark)}h1,h2,h3{font-size:13px;font-weight:700;margin:0}.app{padding-bottom:48px}.wrap{max-width:var(--measure);margin:0 auto;padding:0 40px}.bar-inner{max-width:var(--measure);margin:0 auto;padding:0 40px;display:flex;align-items:center;gap:14px}.grow{flex-grow:1}.pad{padding:24px 40px}.muted,.faint{color:var(--faint)}.warn{color:var(--amber)}.danger{color:var(--red)}.add{color:var(--green)}.del{color:var(--red)}.icon{flex-shrink:0}.lab{font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--faint)}.key{font-size:10px;border:1px solid var(--line-2);border-bottom-width:2px;border-radius:3px;padding:1px 5px;color:var(--muted);background:var(--surface)}.hint{display:inline-flex;gap:5px;align-items:center;font-size:10.5px;color:var(--faint);white-space:nowrap}.prose{font-family:var(--prose);font-size:13px;line-height:1.6;color:var(--fg-2);text-wrap:pretty;max-width:720px}.prose.lead{font-size:13.5px;line-height:1.62;color:var(--fg)}.error{color:var(--red);background:#c2314a0f;border:1px solid rgba(194,49,74,.3);padding:8px 12px;border-radius:4px;margin:10px 0}.empty{text-align:center;color:var(--faint);margin:64px auto;flex-direction:column}.empty pre{display:inline-block;background:var(--line-3);padding:8px 16px;border-radius:4px}button{font:inherit;cursor:pointer}.btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;font-size:11px;color:var(--fg-3);border:1px solid var(--line-2);border-radius:4px;padding:6px 10px;background:var(--surface);white-space:nowrap;text-decoration:none}.btn:hover:not(:disabled){color:var(--fg);border-color:var(--fainter)}.btn:disabled{opacity:.5;cursor:default}.btn-sm{font-size:10.5px;padding:3px 8px;gap:5px}.btn-accent{color:var(--accent);border-color:#3d4fd659}.btn-keep-on{color:#fff;background:var(--green);border-color:var(--green)}.btn-drop-on{color:var(--red);border-color:#c2314a66}.btn-dark{color:#fff;background:var(--fg);border-color:var(--fg);font-size:11.5px;padding:7px 14px}.btn-dark:disabled{color:var(--faint);background:#f0f1f3;border-color:var(--line-2)}.btn-dashed{display:inline-flex;align-items:center;gap:5px;font-size:10.5px;color:var(--muted);border:1px dashed var(--line-2);border-radius:4px;padding:5px 10px;background:transparent;margin-top:10px}.btn-primary{display:flex;align-items:center;justify-content:center;gap:8px;height:40px;padding:0 14px;font-size:12px;font-weight:500;color:#fff;background:var(--accent);border:1px solid var(--accent);border-radius:4px}.btn-primary .key{border-color:#ffffff4d;color:#ffffffbf;background:transparent}.link{display:inline-flex;align-items:center;gap:5px;font:inherit;font-size:11px;color:var(--accent);background:none;border:none;padding:0;text-decoration:none}.link:hover:not(:disabled){color:var(--accent-dark)}.link:disabled{color:var(--faint);cursor:default}.topbar{border-bottom:1px solid var(--line);background:var(--surface)}.topbar .bar-inner{padding-top:14px;padding-bottom:14px}.brand{display:inline-flex;align-items:center;gap:7px;font-size:15px;font-weight:700;letter-spacing:-.02em;color:var(--fg);text-decoration:none}.brand .logo{color:var(--accent);flex-shrink:0}.tagline{font-size:11px;color:var(--faint)}.topbar-link{font-size:11px;color:var(--muted);text-decoration:none;border-left:1px solid var(--line);padding-left:14px;display:inline-flex;align-items:center}.topbar-link:hover{color:var(--fg)}.bell{background:none;border:0;border-left:1px solid var(--line);padding:0 0 0 14px;font-family:inherit;cursor:pointer}.bell-on,.bell-ask{color:var(--accent)}.bell-blocked{color:var(--fainter);cursor:help}.daemon-bar{border-bottom:1px solid var(--line);background:#f7f8fa;font-size:11px;color:var(--muted)}.daemon-bar .bar-inner{padding-top:8px;padding-bottom:8px;gap:18px;flex-wrap:wrap}.daemon-bar b{color:var(--fg);font-weight:400}.daemon-live{display:inline-flex;align-items:center;gap:6px;color:var(--fg)}.daemon-bar .warn{display:inline-flex;align-items:center;gap:6px}.dot{width:5px;height:5px;border-radius:999px;background:var(--green);display:inline-block}.dot-off{background:var(--fainter)}.tabs{display:flex;align-items:center;gap:2px;padding-top:14px}.tab{font-size:12px;padding:6px 12px;border:none;border-bottom:2px solid transparent;border-radius:4px 4px 0 0;background:none;color:var(--muted)}.tab:hover{color:var(--fg)}.tab-on{color:var(--fg);font-weight:500;border-bottom-color:var(--accent)}.tab-count{color:var(--fainter);margin-left:4px}.tab-on .tab-count{color:var(--accent)}.tab-split{width:1px;flex-shrink:0;align-self:stretch;margin:4px 10px 6px;background:var(--line-2)}.tab-filed{color:var(--faint)}.tab-filed:hover,.tab-filed.tab-on{color:var(--muted)}.tab-requests{color:var(--amber)}.tab-requests:hover,.tab-requests.tab-on{color:var(--amber);border-bottom-color:var(--amber)}.tab-requests .tab-count,.tab-requests.tab-on .tab-count{color:var(--amber)}.empty-tab{padding:22px 10px;font-size:12.5px;max-width:88ch}.empty-tab .btn{margin-top:10px}.table-head,.row{display:flex;gap:12px;align-items:center}.table-head{font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--faint);padding:12px 10px 7px;border-bottom:1px solid var(--line-2)}.row{font-size:12px;padding:8px 10px;cursor:pointer;border-bottom:1px solid var(--line-3);border-left:2px solid transparent}.row:hover{background:#f7f8fa}.row-on{background:var(--accent-wash);border-left-color:var(--accent)}.row-on .col-caret{color:var(--accent)}.row-on .col-title{font-weight:500}.tag-done{flex-shrink:0;color:var(--muted);background:var(--line-3)}.tag-awaiting{flex-shrink:0;color:var(--amber);background:#a06a001a}.pull{display:flex;align-items:center;gap:6px;position:relative;color:var(--muted)}.tabs .pull{margin-right:16px}.empty .pull{justify-content:center;margin-top:10px}.pull:hover,.pull:focus-within{color:var(--fg-3)}.pull-input{width:200px;max-width:100%;font:inherit;font-size:12px;padding:2px 0;color:var(--fg);background:transparent;border:none;border-bottom:1px solid transparent;transition:width .12s ease,border-color .12s ease}.pull-input:hover::placeholder{color:var(--fg)}.pull-input:focus{outline:none;width:320px;border-bottom-color:var(--accent)}.pull-input::placeholder{color:var(--muted);transition:color .12s ease}.btn-small{padding:2px 8px;font-size:10px}.pull-error{position:absolute;top:100%;right:0;z-index:5;margin-top:4px;max-width:360px;padding:5px 8px;font-size:11px;line-height:1.4;color:var(--red);background:var(--bg);border:1px solid var(--line-2);border-radius:4px;box-shadow:0 2px 8px #14171a14}.tag-draft{flex-shrink:0;color:var(--muted);background:var(--line-3)}.col-caret{width:12px;flex-shrink:0;color:transparent}.col-slug{width:184px;flex-shrink:0;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.col-title{flex-grow:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.col-author{width:104px;flex-shrink:0;color:var(--faint);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.col-verdict{width:136px;flex-shrink:0;text-align:right;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.col-comments{width:26px;flex-shrink:0;text-align:right;color:var(--muted)}.col-size{width:104px;flex-shrink:0;text-align:right;color:var(--muted)}.col-age{width:44px;flex-shrink:0;text-align:right;color:var(--faint)}.table-head .col-verdict,.table-head .col-slug,.table-head .col-author{color:var(--faint);font-weight:400}.cursor-strip{display:flex;gap:18px;align-items:flex-start;border:1px solid var(--line-2);border-top:none;border-radius:0 0 4px 4px;background:var(--surface);padding:14px 16px}.cursor-strip-body{flex-grow:1;min-width:0}.strip-prose{--strip-cap: 196px;--strip-fade: 46px;margin:6px 0 0;max-width:700px;max-height:var(--strip-cap);overflow:hidden}.strip-prose-clipped{-webkit-mask-image:linear-gradient(#000 calc(var(--strip-cap) - var(--strip-fade)),transparent var(--strip-cap));mask-image:linear-gradient(#000 calc(var(--strip-cap) - var(--strip-fade)),transparent var(--strip-cap))}.cursor-strip-body .md p{margin:5px 0}.cursor-strip-body .md ul,.cursor-strip-body .md ol{margin:5px 0;padding-left:17px}.cursor-strip-body .md li{margin:2px 0}.cursor-strip-body .md li::marker{color:var(--faint)}.cursor-strip-body .md strong{font-weight:600;color:var(--fg)}.cursor-strip-meta{font-size:10.5px;color:var(--faint);margin-top:8px}.cursor-strip-actions{display:flex;flex-direction:column;gap:6px;width:176px;flex-shrink:0}.cursor-strip-row{display:flex;gap:6px}.cursor-strip-row .btn{flex-grow:1;padding:7px 0}.review-top{position:sticky;top:0;z-index:20;background:var(--surface)}.crumb{border-bottom:1px solid var(--line);background:var(--surface);font-size:11.5px;color:var(--muted)}.crumb .bar-inner{padding-top:12px;padding-bottom:12px;gap:12px}.crumb a{text-decoration:none}.crumb-sep{color:var(--line-2)}.crumb-slug{color:var(--fg)}.crumb-next{font-size:11px;max-width:300px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.walk{display:inline-flex;gap:2px}.walk-btn{display:inline-flex;align-items:center;justify-content:center;padding:4px 6px;border:1px solid var(--line-2);border-radius:3px;background:var(--surface);color:var(--fg-3)}.walk-btn:disabled{color:#d4d7db;border-color:var(--line-3);cursor:default}.review-head{border-bottom:1px solid var(--line);background:var(--surface)}.review-head .wrap{padding-top:20px;padding-bottom:16px}.review-head-top,.review-head-meta{display:flex;align-items:center;gap:14px}.review-head-top{margin-bottom:8px}.review-title{font-size:19px;font-weight:700;letter-spacing:-.025em;color:var(--fg);text-decoration:none}.review-title:hover{color:var(--accent)}.review-head-meta{font-size:11px;color:var(--muted);gap:10px;flex-wrap:wrap}.verdict-pick{display:inline-flex;align-items:center;gap:5px;font-size:10.5px;padding:4px 9px;border-radius:4px;border:1px solid transparent;background:none;color:var(--faint);white-space:nowrap}.verdict-pick:hover{color:var(--fg-3)}.verdict-pick-on{background:#f0f1f3;border-color:var(--line-2);font-weight:500}.review-body{display:grid;align-items:start;grid-template-columns:236px minmax(0,1fr);grid-template-areas:"rail main" "rail cockpit"}.rail{grid-area:rail}.main{grid-area:main}.cockpit{grid-area:cockpit;min-width:0;padding-bottom:18px}.rail{padding:22px 20px 22px 0;position:sticky;top:var(--top-h, 0px);z-index:5;max-height:calc(100vh - var(--top-h, 0px));overflow-y:auto}@media(min-width:1600px){.review{--measure: 2100px}.review-body{grid-template-columns:236px minmax(0,1fr) clamp(420px,34%,680px);grid-template-areas:"rail main cockpit"}.cockpit{position:sticky;top:var(--top-h, 0px);height:calc(100vh - var(--top-h, 0px));padding:22px 0 18px 22px;display:flex;flex-direction:column;justify-content:space-between;gap:10px}.cockpit .chat-panel{flex:0 1 auto;display:flex;flex-direction:column;min-height:120px;margin:0}.cockpit .chat-panel .card-body{display:flex;flex-direction:column;min-height:0}.cockpit .chat-log{flex:1 1 auto;min-height:0;overflow-y:auto}.cockpit .verdict-bar{margin-top:0}.cockpit-decide{flex:0 0 auto;max-height:65%;overflow-y:auto}}.chapter,.comment,.card-summary,.card-why,.chat-panel,.send-panel,.sent-strip,.verdict-bar{scroll-margin-top:calc(var(--top-h, 0px) + 12px)}.rail-lab{display:block;margin-top:22px}.rail-jumps{display:flex;flex-direction:column;align-items:flex-start;gap:7px}.rail .rail-jumps .lab{margin-bottom:0}.rail-lab-btn{display:block;width:100%;text-align:left;font:inherit;padding:0;background:none;border:none}.rail-lab-btn:hover{color:var(--fg)}.rail .lab{margin-bottom:10px}.rail-item{display:flex;align-items:center;gap:6px;width:100%;text-align:left;font:inherit;font-size:11.5px;line-height:1.5;padding:5px 0 5px 9px;margin-left:-11px;background:none;border:none;border-left:2px solid transparent;color:var(--muted)}.rail-item:hover{color:var(--fg)}.rail-item-on{border-left-color:var(--accent);color:var(--fg);font-weight:500}.rail-group{margin-bottom:2px}.rail-count{font-size:10.5px;color:var(--fainter)}.rail-comment{display:flex;align-items:center;gap:6px;width:100%;font:inherit;font-size:11px;text-align:left;padding:3px 0 3px 20px;margin-left:-11px;background:none;border:none;border-left:2px solid transparent;color:var(--muted)}.rail-comment:hover{color:var(--fg)}.rail-comment-loc{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rail-comment-dropped{opacity:.55}.rail-comment-dropped .rail-comment-loc{text-decoration:line-through}.rail-dot{font-size:8px}.comment-flash{animation:comment-flash 1.8s ease-out}@keyframes comment-flash{0%,60%{background:var(--accent-wash);box-shadow:inset 0 0 0 2px #3d4fd673}}.rail-facts{font-size:11.5px;line-height:1.85;color:var(--muted)}.rail-facts b{color:var(--fg);font-weight:400}.main{min-width:0;padding:22px 0 0}.card{border:1px solid var(--line);border-radius:4px;background:var(--surface);margin-bottom:10px}.card-head{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;padding:11px 16px;border-bottom:1px solid var(--line-3)}.card-head .faint{font-size:11px}.card-body{padding:14px 16px}.card-body .lab{display:block;margin-bottom:7px}.card-body .prose{margin:0}.card-body .btn{margin-top:12px}.card-why{margin-bottom:8px}.chapter{border:1px solid var(--line);border-radius:4px;background:var(--surface);margin-bottom:10px;overflow:hidden}.chapter-head{display:flex;align-items:center;gap:10px;padding:11px 16px;cursor:pointer;-webkit-user-select:none;user-select:none}.chapter-body{padding:14px 16px 16px;border-top:1px solid var(--line-3)}.chapter-meta{font-size:11px;font-weight:400}.chapter-explanation{margin:0 0 14px}.comment{border:1px solid var(--line);border-radius:4px;background:#fbfbfc;padding:12px 14px;margin:8px 0}.comment-dropped{opacity:.5}.comment-dropped .comment-body{text-decoration:line-through}.comment-head{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:6px}.comment-loc{font-size:10.5px;color:var(--faint)}.comment-body{font-size:13px;line-height:1.58;color:var(--fg);max-width:640px}.comment-edit,.add-comment textarea,.chat-input{width:100%;font-family:var(--mono);font-size:12.5px;line-height:1.55;color:var(--fg);padding:10px 12px;border:1px solid var(--line-2);border-radius:4px;background:var(--surface);resize:vertical}.add-comment{border:1px dashed var(--line-2);border-radius:4px;padding:10px 12px;margin:10px 0;display:flex;flex-direction:column;gap:8px}.add-comment-row{display:flex;gap:8px;align-items:center}.add-comment select,.add-comment input{font:inherit;font-size:11.5px;padding:5px 7px;border:1px solid var(--line-2);border-radius:4px;background:var(--surface)}.inline-comment-row td{padding:0;background:#fbfbfc;border-top:1px solid var(--line);border-bottom:1px solid var(--line);white-space:normal}.inline-comment-row .comment{margin:0;border:none;border-radius:0;padding-left:44px;max-width:none}.line-composer-row td{padding:0;background:var(--accent-wash);border-top:1px solid var(--line);border-bottom:1px solid var(--line);white-space:normal}.line-composer{display:flex;flex-direction:column;gap:8px;padding:10px 12px 10px 44px;max-width:760px;font-family:var(--mono)}.line-composer-head{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.line-composer-actions{display:flex;align-items:center;gap:8px}.diff{margin-top:8px;font-size:11.5px}.diff .line-add{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;padding:0;border:0;background:none;cursor:pointer;opacity:0}.diff tr:hover .line-add{opacity:1}.diff .line-add:before{content:"+";position:absolute;left:1px;top:50%;transform:translateY(-50%);width:13px;height:13px;border-radius:3px;background:var(--accent);color:#fff;font-family:var(--mono);font-size:11px;font-weight:700;line-height:12px;text-align:center;direction:ltr}.diff .d2h-file-header,.diff .d2h-file-name{font-family:var(--mono);font-size:11px}.diff .d2h-code-line{white-space:normal;width:calc(100% - 9em);padding-right:1em}.diff .d2h-code-line-ctn{display:inline;width:auto;white-space:pre-wrap;overflow-wrap:anywhere}.diff .d2h-code-line ins,.diff .d2h-code-line del{display:inline}.diff .hljs{display:inline;padding:0;background:transparent;color:inherit}.freshness{background:#a06a0012;border:1px solid rgba(160,106,0,.3);color:#57430a;padding:10px 12px;border-radius:4px;margin-bottom:10px;line-height:1.55;font-size:11.5px}.freshness code{background:#0000000f;padding:1px 4px;border-radius:3px}.freshness-running{background:#3d4fd60f;border-color:#3d4fd64d;color:#26307a}.freshness .btn{margin-left:8px}.chat-panel{margin:18px 0 10px}.chat-log{display:flex;flex-direction:column;gap:14px;margin-bottom:14px}.chat-turn{border-left:2px solid var(--line-2);padding:2px 0 2px 12px}.chat-turn-user{border-left-color:var(--accent)}.chat-turn-pending{border-left-style:dashed}.chat-turn-who{font-size:10.5px;color:var(--faint);margin-bottom:4px}.chat-turn-body{max-width:700px;color:var(--fg)}.chat-revision{font-size:10.5px;color:var(--green);margin-top:6px}.chat-refusal{font-size:10.5px;color:var(--amber);margin-top:6px}.chat-waiting{font-size:11.5px;color:var(--muted);margin-top:6px}.chat-progress{list-style:none;margin:0;padding:0}.chat-progress li{opacity:.55;padding:1px 0}.chat-progress li.now{opacity:1}.chat-progress li.now:after{content:"…"}.chat-failed{font-size:11.5px;color:var(--red);margin-top:6px}.chat-refs{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-bottom:8px}.chat-ref{font-size:10.5px;font-family:var(--mono);padding:3px 9px;border:1px solid var(--line-2);border-radius:999px;color:var(--muted);background:transparent}.chat-refs-pending .chat-ref{cursor:pointer;color:var(--accent);border-color:#3d4fd659}.chat-actions{display:flex;align-items:center;gap:12px;margin-top:10px}.send-panel{border:1px solid var(--line-2);border-radius:4px;background:#f7f8fa;padding:16px 18px}.verdict-bar+.send-panel{border-radius:0 0 4px 4px}.send-top{display:flex;align-items:baseline;gap:12px;margin-bottom:14px}.send-top .faint{font-size:11px}.send-top .link{text-decoration:underline;text-underline-offset:2px}.send-action{display:flex;align-items:center;gap:16px;flex-wrap:wrap}.send-btn{display:inline-flex;align-items:center;gap:10px;height:44px;padding:0 20px;font-size:13px;font-weight:500;color:#fff;border:none;border-radius:4px;box-shadow:0 1px 2px #14171a1f}.send-btn:disabled{opacity:.6;cursor:default}.send-btn .key{border-color:#ffffff4d;color:#fffc;background:transparent}.send-as{position:relative}.send-as-toggle{font:inherit;font-size:11.5px;color:var(--fg-3);background:none;border:none;padding:0}.send-as-toggle b{color:var(--fg);font-weight:500;border-bottom:1px dotted var(--fainter)}.send-as-why{font-size:10.5px;color:var(--faint);margin-top:3px}.menu{position:absolute;top:34px;left:0;z-index:10;background:var(--surface);border:1px solid var(--line-2);border-radius:4px;box-shadow:0 6px 18px #14171a17;padding:4px;min-width:190px}.menu-item{display:flex;align-items:center;gap:9px;width:100%;font:inherit;font-size:11.5px;text-align:left;padding:7px 9px;border:none;border-radius:3px;background:none;color:var(--fg-3)}.menu-item:hover{background:#f7f8fa}.menu-item-on{background:#f4f5f7;color:var(--fg)}.menu-check{font-size:10px;color:var(--green)}.verdict-bar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;border:1px solid var(--line-2);border-bottom:none;border-radius:4px 4px 0 0;background:var(--surface);padding:10px 18px;margin-top:18px}.verdict-bar .lab{margin-right:4px}.verdict-bar .faint{font-size:10.5px}.send-footer{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:16px;padding-top:14px;border-top:1px solid var(--line-2);font-size:10.5px}.body-preview{margin-top:14px;padding:14px 16px;background:var(--surface);border:1px solid var(--line);border-radius:4px;font-family:var(--prose);font-size:12.5px;line-height:1.62;color:var(--fg-2);white-space:pre-wrap;max-width:760px;max-height:420px;overflow:auto}.sent-strip{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;border:1px solid rgba(26,127,90,.4);background:#1a7f5a12;border-radius:4px;padding:14px 16px;font-size:11.5px}.sent-strip strong{color:var(--green);font-size:13px;white-space:nowrap}.sent-strip a{display:inline-flex;align-items:center;gap:5px;white-space:nowrap;text-decoration:none}.post-actions{display:flex;align-items:center;gap:12px;margin-top:12px;font-size:10.5px}.post-actions .link{font-size:10.5px;color:var(--muted)}.post-actions .link:hover{color:var(--fg)}.md>:first-child{margin-top:0}.md>:last-child{margin-bottom:0}.md p{margin:8px 0}.md code{font-family:var(--mono);font-size:.9em;background:#f0f2f5;padding:1px 5px;border-radius:3px}.md pre{background:#f7f8fa;border:1px solid var(--line);border-radius:4px;padding:10px 12px;overflow-x:auto}.md pre code{background:none;padding:0;font-size:11.5px}.md ul,.md ol{margin:8px 0;padding-left:24px}.md blockquote{margin:8px 0;padding-left:12px;border-left:2px solid var(--line-2);color:var(--muted)}.md h1,.md h2,.md h3,.md h4{font-size:1em;font-weight:650;letter-spacing:-.01em;margin:18px 0 2px;color:var(--fg)}.md h1+p,.md h2+p,.md h3+p,.md h4+p,.md h1+ul,.md h2+ul,.md h3+ul,.md h4+ul{margin-top:4px}.settings{max-width:780px;margin:0 auto;padding:24px 40px 64px;font-family:var(--prose);font-size:13px;line-height:1.6;color:var(--fg-2)}.settings .back{display:inline-block;font-family:var(--mono);font-size:11.5px;text-decoration:none;margin-bottom:16px}.settings h1{font-family:var(--mono);font-size:15px;margin:32px 0 8px}.settings h2{font-family:var(--mono);font-size:13px;margin:28px 0 8px}.settings code{font-family:var(--mono);font-size:.92em;background:#f0f2f5;padding:1px 5px;border-radius:3px}.inbox-toggle{display:block;margin:8px 0}.trust-add{display:flex;gap:8px;margin:20px 0 12px}.trust-add input{flex:1;font:inherit;padding:7px 10px;color:var(--fg);border:1px solid var(--line-2);border-radius:4px;background:var(--surface)}.trust-table{border-collapse:collapse;width:100%}.trust-table td{padding:6px 10px 6px 0;border-bottom:1px solid var(--line);vertical-align:baseline}.trust-actions{text-align:right}.trust-deny code{text-decoration:line-through}.tone-approve{color:var(--green)}.tone-comment{color:var(--amber)}.tone-changes{color:var(--red)}.tone-running,.tone-sent,.tone-none{color:var(--muted);font-weight:400}.tone-failed{color:var(--red)}.tone-awaiting{color:var(--accent)}.tone-bg-approve{background:var(--green)}.tone-bg-comment{background:var(--amber)}.tone-bg-changes{background:var(--red)}.tone-border-approve{border-left:2px solid var(--green)}.tone-border-comment{border-left:2px solid var(--amber)}.tone-border-changes{border-left:2px solid var(--red)}.tone-border-none{border-left:2px solid var(--line-2)}.chip{font-size:11.5px;font-weight:500;padding:3px 9px;border-radius:3px;border:1px solid currentColor;background:#14171a08;white-space:nowrap}.chip-btn{display:inline-flex;align-items:center;gap:6px;font-family:inherit}.chip-btn:hover{background:#14171a12}.tag{font-size:10px;letter-spacing:.06em;padding:1px 6px;border-radius:3px;color:var(--muted);background:#f0f1f3;white-space:nowrap}.tag-yours{color:var(--accent);background:#3d4fd617}.tag-kept{color:var(--green);background:#1a7f5a1a}.tag-drift{color:var(--amber);background:#a06a001a}.sev-counts{font-size:12px;color:var(--muted);margin-bottom:6px}.verdict-hint{display:flex;align-items:center;gap:10px;flex-wrap:wrap;background:#a06a0012;border:1px solid rgba(160,106,0,.3);color:#57430a;padding:10px 12px;border-radius:4px}
|