comprehende 0.5.0 → 0.5.2
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 +1 -1
- package/dist/api/agent-md.js +204 -0
- package/dist/api/live.js +16 -2
- package/dist/api/paths.js +30 -0
- package/dist/git/diff.js +2 -5
- package/dist/git/repo.js +42 -0
- package/dist/server/http.js +1 -0
- package/dist/ui/assets/index-DLIYSuqF.css +1 -0
- package/dist/ui/assets/{index-CNz9KqcH.js → index-DTYliZBb.js} +61 -61
- package/dist/ui/index.html +2 -2
- package/package.json +1 -1
- package/skills/comprehende/SKILL.md +4 -4
- package/dist/ui/assets/index-DJMUAjCi.css +0 -1
package/README.md
CHANGED
|
@@ -42,7 +42,7 @@ This tool is for preventing this cognitive surrender while trying to maintain mo
|
|
|
42
42
|
|
|
43
43
|
`comprehende serve` and `comprehende export` share one UI and one git payload. Serve resolves refs to commit SHAs when it starts, then computes those payloads from the objects on each request. Export writes the same JSON (and image bytes) next to the UI so any static file server can host the review.
|
|
44
44
|
|
|
45
|
-
`pnpm dev` and `pnpm exec` run with this package as cwd, so they only make sense when _this_ repo is the one under review. To review a different project from a checkout, `cd` into it and run `npx comprehende@0.5.
|
|
45
|
+
`pnpm dev` and `pnpm exec` run with this package as cwd, so they only make sense when _this_ repo is the one under review. To review a different project from a checkout, `cd` into it and run `npx comprehende@0.5.2` (or `node /path/to/comprehende/dist/cli/main.js` after `pnpm build`).
|
|
46
46
|
|
|
47
47
|
## Release
|
|
48
48
|
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
export const AGENT_MD_MEDIA_TYPE = "text/markdown; charset=utf-8";
|
|
2
|
+
export function formatHunkRef(ref) {
|
|
3
|
+
const rename = ref.oldPath !== undefined ? `${ref.oldPath} -> ` : "";
|
|
4
|
+
return `${rename}${ref.path} @@ -${ref.oldStart},${ref.oldLines} +${ref.newStart},${ref.newLines} @@`;
|
|
5
|
+
}
|
|
6
|
+
export function isImageSlot(ref) {
|
|
7
|
+
return ref.oldStart === 0 && ref.oldLines === 0 && ref.newStart === 0 && ref.newLines === 0;
|
|
8
|
+
}
|
|
9
|
+
export function agentClipboardPrompt(url) {
|
|
10
|
+
return `Answer the following questions by using ${url}`;
|
|
11
|
+
}
|
|
12
|
+
function groupAgentMdHref(id) {
|
|
13
|
+
return `groups/${encodeURIComponent(id)}.md`;
|
|
14
|
+
}
|
|
15
|
+
export function agentMd(review, resource) {
|
|
16
|
+
if (resource.target === "overview") {
|
|
17
|
+
return overviewAgentMd(review);
|
|
18
|
+
}
|
|
19
|
+
return groupAgentMd(review, resource.group);
|
|
20
|
+
}
|
|
21
|
+
function overviewAgentMd(review) {
|
|
22
|
+
return joinBlocks([
|
|
23
|
+
"Answer questions about this git change.",
|
|
24
|
+
overviewSteps(review),
|
|
25
|
+
pinBlock(review, { commits: true }),
|
|
26
|
+
ticketsBlock(review),
|
|
27
|
+
coverageBlock(review),
|
|
28
|
+
review.document.why !== undefined ? joinBlocks(["The why:", review.document.why]) : null,
|
|
29
|
+
joinBlocks([`The what (${sizeLabel(review.document.size)}):`, review.document.summary]),
|
|
30
|
+
reviewConcernsBlock(review),
|
|
31
|
+
]);
|
|
32
|
+
}
|
|
33
|
+
function groupAgentMd(review, id) {
|
|
34
|
+
const listed = review.groups.find((group) => group.id === id);
|
|
35
|
+
const documentGroup = review.document.groups.find((group) => group.id === id);
|
|
36
|
+
if (listed === undefined || documentGroup === undefined) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
const index = review.groups.findIndex((group) => group.id === id) + 1;
|
|
40
|
+
const total = review.groups.length;
|
|
41
|
+
const hunks = documentGroup.hunkRefs;
|
|
42
|
+
const heading = `Review concern ${padIndex(index)} of ${padIndex(total)}: ${listed.title} (\`${listed.id}\`)`;
|
|
43
|
+
return joinBlocks([
|
|
44
|
+
"Answer questions about this review concern.",
|
|
45
|
+
groupSteps(review),
|
|
46
|
+
pinBlock(review, { commits: false }),
|
|
47
|
+
heading,
|
|
48
|
+
listed.part !== undefined ? `Part: ${listed.part}` : null,
|
|
49
|
+
"The why:",
|
|
50
|
+
listed.why,
|
|
51
|
+
"The what:",
|
|
52
|
+
listed.summary,
|
|
53
|
+
lookForBlock(listed.lookFor),
|
|
54
|
+
dependsOnBlock(review, listed.dependsOn),
|
|
55
|
+
hunkList("Hunk refs for this concern:", hunks),
|
|
56
|
+
imageNote(hunks),
|
|
57
|
+
listed.staleCount > 0
|
|
58
|
+
? `Stale hunk refs in this concern: ${listed.staleCount}. Live git wins. The pointer is flagged, not replaced.`
|
|
59
|
+
: null,
|
|
60
|
+
]);
|
|
61
|
+
}
|
|
62
|
+
function pinBlock(review, options) {
|
|
63
|
+
const { baseSha, headSha, baseRef, headRef } = review.resolved;
|
|
64
|
+
const repo = review.repo.origin !== null
|
|
65
|
+
? `Repository: ${review.repo.name}\nOrigin: ${review.repo.origin}`
|
|
66
|
+
: `Repository: ${review.repo.name}`;
|
|
67
|
+
const commits = options.commits && review.commits.length > 0
|
|
68
|
+
? ["Commits:", ...review.commits.map((commit) => `- ${commit.shortSha} ${commit.subject}`)].join("\n")
|
|
69
|
+
: null;
|
|
70
|
+
return joinBlocks([
|
|
71
|
+
"## Pin",
|
|
72
|
+
repo,
|
|
73
|
+
`base (merge-base) ${baseSha}`,
|
|
74
|
+
`head ${headSha}`,
|
|
75
|
+
`Named refs at pin: ${baseRef} ... ${headRef}`,
|
|
76
|
+
"Read the diff:",
|
|
77
|
+
`git diff --find-renames ${baseSha} ${headSha}`,
|
|
78
|
+
commits,
|
|
79
|
+
]);
|
|
80
|
+
}
|
|
81
|
+
function ticketsBlock(review) {
|
|
82
|
+
const tickets = review.document.tickets ?? [];
|
|
83
|
+
if (tickets.length === 0) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
const lines = tickets.map((ticket) => {
|
|
87
|
+
const title = ticket.title !== undefined ? ` ${ticket.title}` : "";
|
|
88
|
+
const url = ticket.url !== undefined ? `\n ${ticket.url}` : "";
|
|
89
|
+
return `- ${ticket.id}${title}${url}`;
|
|
90
|
+
});
|
|
91
|
+
return ["Tickets:", ...lines].join("\n");
|
|
92
|
+
}
|
|
93
|
+
function coverageBlock(review) {
|
|
94
|
+
const lines = [];
|
|
95
|
+
if (review.coverage.unassignedCount > 0) {
|
|
96
|
+
lines.push(`Unassigned live hunks: ${review.coverage.unassignedCount}. They are in git and in no group.`);
|
|
97
|
+
}
|
|
98
|
+
if (review.coverage.staleCount > 0) {
|
|
99
|
+
lines.push(`Stale hunk refs: ${review.coverage.staleCount}. Live git wins. The pointer is flagged, not replaced.`);
|
|
100
|
+
}
|
|
101
|
+
return lines.length === 0 ? null : lines.join("\n");
|
|
102
|
+
}
|
|
103
|
+
function reviewConcernsBlock(review) {
|
|
104
|
+
const sections = review.groups.map((group, i) => {
|
|
105
|
+
const href = groupAgentMdHref(group.id);
|
|
106
|
+
return joinBlocks([
|
|
107
|
+
`### ${padIndex(i + 1)} ${group.title} (\`${group.id}\`)`,
|
|
108
|
+
group.summary,
|
|
109
|
+
dependsOnBlock(review, group.dependsOn),
|
|
110
|
+
`[${href}](${href})`,
|
|
111
|
+
]);
|
|
112
|
+
});
|
|
113
|
+
return ["## Review concerns", ...sections].join("\n\n");
|
|
114
|
+
}
|
|
115
|
+
function lookForBlock(lookFor) {
|
|
116
|
+
if (lookFor.length === 0) {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
return ["Look for:", ...lookFor.map((item) => `- ${item}`)].join("\n");
|
|
120
|
+
}
|
|
121
|
+
function dependsOnBlock(review, dependsOn) {
|
|
122
|
+
if (dependsOn.length === 0) {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
const lines = dependsOn.map((id) => {
|
|
126
|
+
const dep = review.groups.find((group) => group.id === id);
|
|
127
|
+
if (dep === undefined) {
|
|
128
|
+
return `- ${id}`;
|
|
129
|
+
}
|
|
130
|
+
const index = review.groups.findIndex((group) => group.id === id) + 1;
|
|
131
|
+
return `- ${padIndex(index)} ${dep.title} (\`${dep.id}\`)`;
|
|
132
|
+
});
|
|
133
|
+
return ["Depends on:", ...lines].join("\n");
|
|
134
|
+
}
|
|
135
|
+
function hunkList(heading, hunks) {
|
|
136
|
+
if (hunks.length === 0) {
|
|
137
|
+
return `${heading}\n(none)`;
|
|
138
|
+
}
|
|
139
|
+
return [heading, ...hunks.map((hunk) => `- ${formatHunkRef(hunk)}`)].join("\n");
|
|
140
|
+
}
|
|
141
|
+
function imageNote(hunks) {
|
|
142
|
+
if (!hunks.some(isImageSlot)) {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
return "Hunk refs with @@ -0,0 +0,0 @@ are image or binary slots. Identify those by path.";
|
|
146
|
+
}
|
|
147
|
+
function overviewSteps(review) {
|
|
148
|
+
return [
|
|
149
|
+
"## Steps",
|
|
150
|
+
"",
|
|
151
|
+
"When no question follows this paste, explain this change.",
|
|
152
|
+
"",
|
|
153
|
+
...resolveShaSteps(review),
|
|
154
|
+
"",
|
|
155
|
+
"2. Choose the relevant review concerns.",
|
|
156
|
+
" Read Review concerns. Fetch a concern file only when that concern is relevant to the question.",
|
|
157
|
+
" Done when every concern the question touches has its markdown loaded.",
|
|
158
|
+
"",
|
|
159
|
+
"3. Answer from live git.",
|
|
160
|
+
" Follow those files. Use the why and the what as interpretation. Live git wins when they disagree.",
|
|
161
|
+
` ${showCodeRule()}`,
|
|
162
|
+
" Done when the answer quotes the live code.",
|
|
163
|
+
].join("\n");
|
|
164
|
+
}
|
|
165
|
+
function groupSteps(review) {
|
|
166
|
+
const { baseSha, headSha } = review.resolved;
|
|
167
|
+
return [
|
|
168
|
+
"## Steps",
|
|
169
|
+
"",
|
|
170
|
+
"When no question follows this paste, explain this review concern.",
|
|
171
|
+
"",
|
|
172
|
+
...resolveShaSteps(review),
|
|
173
|
+
"",
|
|
174
|
+
"2. Load the hunks.",
|
|
175
|
+
" A hunk ref is a pointer into the live git diff at the pinned SHAs.",
|
|
176
|
+
` For each hunk ref, run \`git diff --find-renames ${baseSha} ${headSha} -- <path>\` and keep the hunk whose header matches the @@ range.`,
|
|
177
|
+
" Done when every hunk ref has a matching live hunk.",
|
|
178
|
+
"",
|
|
179
|
+
"3. Answer from live git.",
|
|
180
|
+
" Read those hunks. Use the why and the what as interpretation. Live git wins when they disagree.",
|
|
181
|
+
` ${showCodeRule()}`,
|
|
182
|
+
" Done when the answer quotes the live code.",
|
|
183
|
+
].join("\n");
|
|
184
|
+
}
|
|
185
|
+
function resolveShaSteps(review) {
|
|
186
|
+
const { baseSha, headSha } = review.resolved;
|
|
187
|
+
return [
|
|
188
|
+
"1. Resolve the pinned SHAs.",
|
|
189
|
+
` Run \`git rev-parse --verify ${baseSha}\` and \`git rev-parse --verify ${headSha}\` in this repository.`,
|
|
190
|
+
" Done when both objects exist.",
|
|
191
|
+
];
|
|
192
|
+
}
|
|
193
|
+
function showCodeRule() {
|
|
194
|
+
return "When you show code, quote the live git lines.";
|
|
195
|
+
}
|
|
196
|
+
function padIndex(index) {
|
|
197
|
+
return String(index).padStart(2, "0");
|
|
198
|
+
}
|
|
199
|
+
function sizeLabel(size) {
|
|
200
|
+
return size.replace("-", " ");
|
|
201
|
+
}
|
|
202
|
+
function joinBlocks(parts) {
|
|
203
|
+
return parts.filter((part) => part !== null && part !== undefined && part.length > 0).join("\n\n");
|
|
204
|
+
}
|
package/dist/api/live.js
CHANGED
|
@@ -4,10 +4,11 @@ import { readImageBlob } from "../git/blob.js";
|
|
|
4
4
|
import { fileLanguage, filePatchFromGit, readPathDiff, toHunkRef } from "../git/diff.js";
|
|
5
5
|
import { GitError } from "../git/exec.js";
|
|
6
6
|
import { listCommits } from "../git/log.js";
|
|
7
|
-
import { pinRange } from "../git/repo.js";
|
|
7
|
+
import { pinRange, readRepoIdentity } from "../git/repo.js";
|
|
8
8
|
import { showFile } from "../git/show.js";
|
|
9
9
|
import { coverReview } from "../review/coverage.js";
|
|
10
10
|
import { isLockfilePath } from "../schema/lockfile.js";
|
|
11
|
+
import { AGENT_MD_MEDIA_TYPE, agentMd } from "./agent-md.js";
|
|
11
12
|
import { ApiError } from "./error.js";
|
|
12
13
|
export async function pinReviewSource(cwd, dataPath) {
|
|
13
14
|
const document = await loadDocument(dataPath);
|
|
@@ -18,9 +19,11 @@ export async function openReview(cwd, dataPath, pin) {
|
|
|
18
19
|
const range = pin ?? (await pinRange(cwd, document.source.baseRef, document.source.headRef));
|
|
19
20
|
const { files, coverage } = await coverReview(cwd, document, range);
|
|
20
21
|
const commits = await listCommits(cwd, range.baseSha, range.headSha);
|
|
22
|
+
const repo = await readRepoIdentity(cwd);
|
|
21
23
|
return {
|
|
22
24
|
cwd,
|
|
23
25
|
document,
|
|
26
|
+
repo,
|
|
24
27
|
resolved: {
|
|
25
28
|
baseRef: document.source.baseRef,
|
|
26
29
|
headRef: document.source.headRef,
|
|
@@ -35,10 +38,11 @@ export async function openReview(cwd, dataPath, pin) {
|
|
|
35
38
|
};
|
|
36
39
|
}
|
|
37
40
|
export function reviewPayload(ctx) {
|
|
38
|
-
const { document, resolved, files, coverage, commits } = ctx;
|
|
41
|
+
const { document, repo, resolved, files, coverage, commits } = ctx;
|
|
39
42
|
const lockfiles = lockfileFiles(files);
|
|
40
43
|
return {
|
|
41
44
|
document,
|
|
45
|
+
repo,
|
|
42
46
|
resolved,
|
|
43
47
|
coverage: {
|
|
44
48
|
totalHunks: coverage.totalHunks,
|
|
@@ -156,6 +160,14 @@ export async function renderResource(ctx, resource) {
|
|
|
156
160
|
switch (resource.kind) {
|
|
157
161
|
case "review":
|
|
158
162
|
return { encoding: "json", body: reviewPayload(ctx) };
|
|
163
|
+
case "agent-md": {
|
|
164
|
+
const body = agentMd(reviewPayload(ctx), resource);
|
|
165
|
+
if (body === null) {
|
|
166
|
+
const id = resource.target === "group" ? resource.group : "overview";
|
|
167
|
+
throw new ApiError(404, `unknown group "${id}"`);
|
|
168
|
+
}
|
|
169
|
+
return { encoding: "bytes", mediaType: AGENT_MD_MEDIA_TYPE, body: Buffer.from(body, "utf8") };
|
|
170
|
+
}
|
|
159
171
|
case "hunks":
|
|
160
172
|
return { encoding: "json", body: hunksPayload(ctx, resource.group) };
|
|
161
173
|
case "file":
|
|
@@ -171,11 +183,13 @@ export async function renderResource(ctx, resource) {
|
|
|
171
183
|
export function listResources(ctx) {
|
|
172
184
|
const resources = [
|
|
173
185
|
{ kind: "review" },
|
|
186
|
+
{ kind: "agent-md", target: "overview" },
|
|
174
187
|
{ kind: "hunks", group: "unassigned" },
|
|
175
188
|
{ kind: "hunks", group: "lockfiles" },
|
|
176
189
|
];
|
|
177
190
|
for (const group of ctx.document.groups) {
|
|
178
191
|
resources.push({ kind: "hunks", group: group.id });
|
|
192
|
+
resources.push({ kind: "agent-md", target: "group", group: group.id });
|
|
179
193
|
}
|
|
180
194
|
for (const file of ctx.files) {
|
|
181
195
|
if (file.image) {
|
package/dist/api/paths.js
CHANGED
|
@@ -2,6 +2,8 @@ export function apiHref(resource) {
|
|
|
2
2
|
switch (resource.kind) {
|
|
3
3
|
case "review":
|
|
4
4
|
return "api/review.json";
|
|
5
|
+
case "agent-md":
|
|
6
|
+
return agentMdRel(resource);
|
|
5
7
|
case "hunks":
|
|
6
8
|
return `api/hunks/${encodeURIComponent(resource.group)}.json`;
|
|
7
9
|
case "file":
|
|
@@ -19,6 +21,8 @@ export function apiFsRel(resource) {
|
|
|
19
21
|
switch (resource.kind) {
|
|
20
22
|
case "review":
|
|
21
23
|
return "api/review.json";
|
|
24
|
+
case "agent-md":
|
|
25
|
+
return agentMdRel(resource);
|
|
22
26
|
case "hunks":
|
|
23
27
|
return `api/hunks/${encodeURIComponent(resource.group)}.json`;
|
|
24
28
|
case "file":
|
|
@@ -39,6 +43,19 @@ export function parseApiPath(pathname) {
|
|
|
39
43
|
if (parts[1] === "review.json" && parts.length === 2) {
|
|
40
44
|
return { kind: "review" };
|
|
41
45
|
}
|
|
46
|
+
if (parts[1] === "agent") {
|
|
47
|
+
if (parts.length === 3 && parts[2] === "overview.md") {
|
|
48
|
+
return { kind: "agent-md", target: "overview" };
|
|
49
|
+
}
|
|
50
|
+
if (parts.length === 4 && parts[2] === "groups" && parts[3] !== undefined) {
|
|
51
|
+
const group = mdStem(parts[3]);
|
|
52
|
+
if (group === undefined) {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
return { kind: "agent-md", target: "group", group };
|
|
56
|
+
}
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
42
59
|
if (parts[1] === "hunks" && parts.length === 3 && parts[2] !== undefined) {
|
|
43
60
|
const group = jsonStem(parts[2]);
|
|
44
61
|
if (group === undefined) {
|
|
@@ -102,6 +119,12 @@ function decodeSegment(segment) {
|
|
|
102
119
|
return segment;
|
|
103
120
|
}
|
|
104
121
|
}
|
|
122
|
+
function agentMdRel(resource) {
|
|
123
|
+
if (resource.target === "overview") {
|
|
124
|
+
return "api/agent/overview.md";
|
|
125
|
+
}
|
|
126
|
+
return `api/agent/groups/${encodeURIComponent(resource.group)}.md`;
|
|
127
|
+
}
|
|
105
128
|
function jsonStem(file) {
|
|
106
129
|
if (!file.endsWith(".json")) {
|
|
107
130
|
return undefined;
|
|
@@ -109,6 +132,13 @@ function jsonStem(file) {
|
|
|
109
132
|
const stem = file.slice(0, -".json".length);
|
|
110
133
|
return stem === "" ? undefined : stem;
|
|
111
134
|
}
|
|
135
|
+
function mdStem(file) {
|
|
136
|
+
if (!file.endsWith(".md")) {
|
|
137
|
+
return undefined;
|
|
138
|
+
}
|
|
139
|
+
const stem = file.slice(0, -".md".length);
|
|
140
|
+
return stem === "" ? undefined : stem;
|
|
141
|
+
}
|
|
112
142
|
function isRepoPath(path) {
|
|
113
143
|
return path !== "" && !path.startsWith("/") && !path.includes("\0") && !path.split("/").includes("..");
|
|
114
144
|
}
|
package/dist/git/diff.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isImagePath
|
|
1
|
+
import { isImagePath } from "../schema/image.js";
|
|
2
2
|
import { isLockfilePath } from "../schema/lockfile.js";
|
|
3
3
|
import { git } from "./exec.js";
|
|
4
4
|
import { parseNameStatus, parseNumstat } from "./name-status.js";
|
|
@@ -363,10 +363,7 @@ function classifyDiffFile(file) {
|
|
|
363
363
|
if (!isImagePath(file.path) && (file.oldPath === undefined || !isImagePath(file.oldPath))) {
|
|
364
364
|
return file;
|
|
365
365
|
}
|
|
366
|
-
|
|
367
|
-
return asImageFile(file);
|
|
368
|
-
}
|
|
369
|
-
return file;
|
|
366
|
+
return asImageFile(file);
|
|
370
367
|
}
|
|
371
368
|
function asImageFile(file) {
|
|
372
369
|
return { ...file, image: true, hunks: [imageLiveHunk(file.path, file.oldPath)] };
|
package/dist/git/repo.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { basename } from "node:path";
|
|
1
2
|
import { git, gitOk } from "./exec.js";
|
|
2
3
|
export async function assertWorkTree(cwd) {
|
|
3
4
|
const inside = await git(cwd, ["rev-parse", "--is-inside-work-tree"], { allowFail: true });
|
|
@@ -14,6 +15,47 @@ export async function mergeBase(cwd, baseRef, headRef) {
|
|
|
14
15
|
const sha = await git(cwd, ["merge-base", baseRef, headRef]);
|
|
15
16
|
return sha.trim();
|
|
16
17
|
}
|
|
18
|
+
/** Last path segment of a git remote URL, without .git. */
|
|
19
|
+
export function nameFromRemoteUrl(url) {
|
|
20
|
+
let value = url.trim();
|
|
21
|
+
if (value === "") {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
value = value.replace(/\.git$/i, "").replace(/\/+$/, "");
|
|
25
|
+
const pathPart = value.includes("://")
|
|
26
|
+
? value.replace(/^[^:]+:\/\/[^/]+\//, "")
|
|
27
|
+
: value.includes(":")
|
|
28
|
+
? value.slice(value.lastIndexOf(":") + 1)
|
|
29
|
+
: value;
|
|
30
|
+
const last = pathPart.split("/").filter(Boolean).at(-1);
|
|
31
|
+
return last === undefined || last === "" ? null : last;
|
|
32
|
+
}
|
|
33
|
+
export async function readRepoIdentity(cwd) {
|
|
34
|
+
const originText = (await git(cwd, ["config", "--get", "remote.origin.url"], { allowFail: true })).trim();
|
|
35
|
+
const origin = originText === "" ? null : stripRemoteCredentials(originText);
|
|
36
|
+
const top = (await git(cwd, ["rev-parse", "--show-toplevel"])).trim();
|
|
37
|
+
const fromOrigin = origin !== null ? nameFromRemoteUrl(origin) : null;
|
|
38
|
+
return { name: fromOrigin ?? basename(top), origin };
|
|
39
|
+
}
|
|
40
|
+
/** Drop userinfo from an http(s) remote so a copied prompt never carries a token. */
|
|
41
|
+
export function stripRemoteCredentials(url) {
|
|
42
|
+
const trimmed = url.trim();
|
|
43
|
+
if (!/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(trimmed)) {
|
|
44
|
+
return trimmed;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const parsed = new URL(trimmed);
|
|
48
|
+
if (parsed.username === "" && parsed.password === "") {
|
|
49
|
+
return trimmed;
|
|
50
|
+
}
|
|
51
|
+
parsed.username = "";
|
|
52
|
+
parsed.password = "";
|
|
53
|
+
return parsed.toString().replace(/\/$/, "");
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return trimmed;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
17
59
|
/** Resolve refs to commits once. Later checkout or branch motion does not move these SHAs. */
|
|
18
60
|
export async function pinRange(cwd, baseRef, headRef) {
|
|
19
61
|
const baseSha = await resolveCommit(cwd, baseRef);
|
package/dist/server/http.js
CHANGED
|
@@ -11,6 +11,7 @@ const MIME = {
|
|
|
11
11
|
".js": "text/javascript; charset=utf-8",
|
|
12
12
|
".css": "text/css; charset=utf-8",
|
|
13
13
|
".json": "application/json; charset=utf-8",
|
|
14
|
+
".md": "text/markdown; charset=utf-8",
|
|
14
15
|
".svg": "image/svg+xml",
|
|
15
16
|
".map": "application/json; charset=utf-8",
|
|
16
17
|
".woff2": "font/woff2",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:400;src:url(./ibm-plex-sans-cyrillic-ext-400-normal-g30qAdWV.woff2) format("woff2"),url(./ibm-plex-sans-cyrillic-ext-400-normal-Dsrv2Tcn.woff) format("woff");unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:400;src:url(./ibm-plex-sans-cyrillic-400-normal-DZqxrq2p.woff2) format("woff2"),url(./ibm-plex-sans-cyrillic-400-normal-BTotfTJu.woff) format("woff");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:400;src:url(./ibm-plex-sans-greek-400-normal-_efipK4i.woff2) format("woff2"),url(./ibm-plex-sans-greek-400-normal-D9ESIMu3.woff) format("woff");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:400;src:url(./ibm-plex-sans-vietnamese-400-normal-DG4YqDda.woff2) format("woff2"),url(./ibm-plex-sans-vietnamese-400-normal-fK1oJ5dG.woff) format("woff");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:400;src:url(./ibm-plex-sans-latin-ext-400-normal-C5H60-Va.woff2) format("woff2"),url(./ibm-plex-sans-latin-ext-400-normal-RBey6euL.woff) format("woff");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:400;src:url(./ibm-plex-sans-latin-400-normal-CDDApCn2.woff2) format("woff2"),url(./ibm-plex-sans-latin-400-normal-CYLoc0-x.woff) format("woff");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:500;src:url(./ibm-plex-sans-cyrillic-ext-500-normal-Cs5J6C77.woff2) format("woff2"),url(./ibm-plex-sans-cyrillic-ext-500-normal-DB5PtV2g.woff) format("woff");unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:500;src:url(./ibm-plex-sans-cyrillic-500-normal-CocWQlwt.woff2) format("woff2"),url(./ibm-plex-sans-cyrillic-500-normal-ByOcLdNv.woff) format("woff");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:500;src:url(./ibm-plex-sans-greek-500-normal-JMMifIXV.woff2) format("woff2"),url(./ibm-plex-sans-greek-500-normal-CuWXN6rf.woff) format("woff");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:500;src:url(./ibm-plex-sans-vietnamese-500-normal-e4dixQRQ.woff2) format("woff2"),url(./ibm-plex-sans-vietnamese-500-normal-BEb3_waV.woff) format("woff");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:500;src:url(./ibm-plex-sans-latin-ext-500-normal-DakdToA3.woff2) format("woff2"),url(./ibm-plex-sans-latin-ext-500-normal-D0aIdm-b.woff) format("woff");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:500;src:url(./ibm-plex-sans-latin-500-normal-6ng42L7E.woff2) format("woff2"),url(./ibm-plex-sans-latin-500-normal-BgVn5rGT.woff) format("woff");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:600;src:url(./ibm-plex-sans-cyrillic-ext-600-normal-DUMzJB7m.woff2) format("woff2"),url(./ibm-plex-sans-cyrillic-ext-600-normal-Bz0x94Yp.woff) format("woff");unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:600;src:url(./ibm-plex-sans-cyrillic-600-normal-71GNu3SW.woff2) format("woff2"),url(./ibm-plex-sans-cyrillic-600-normal-BGq0mW3O.woff) format("woff");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:600;src:url(./ibm-plex-sans-greek-600-normal-DzTrcv_p.woff2) format("woff2"),url(./ibm-plex-sans-greek-600-normal-D-CqTdkO.woff) format("woff");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:600;src:url(./ibm-plex-sans-vietnamese-600-normal-DpPYBSTl.woff2) format("woff2"),url(./ibm-plex-sans-vietnamese-600-normal-DgdngZtN.woff) format("woff");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:600;src:url(./ibm-plex-sans-latin-ext-600-normal-DOrvGEcy.woff2) format("woff2"),url(./ibm-plex-sans-latin-ext-600-normal-DIrixKbi.woff) format("woff");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:IBM Plex Sans;font-style:normal;font-display:swap;font-weight:600;src:url(./ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2) format("woff2"),url(./ibm-plex-sans-latin-600-normal-Cu4Hd6ag.woff) format("woff");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:IBM Plex Mono;font-style:normal;font-display:swap;font-weight:400;src:url(./ibm-plex-mono-cyrillic-ext-400-normal-xuaO2J-f.woff2) format("woff2"),url(./ibm-plex-mono-cyrillic-ext-400-normal-DMdlQ8Kv.woff) format("woff");unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:IBM Plex Mono;font-style:normal;font-display:swap;font-weight:400;src:url(./ibm-plex-mono-cyrillic-400-normal-BSMlKf0J.woff2) format("woff2"),url(./ibm-plex-mono-cyrillic-400-normal-CEL4l2ZJ.woff) format("woff");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:IBM Plex Mono;font-style:normal;font-display:swap;font-weight:400;src:url(./ibm-plex-mono-vietnamese-400-normal-BulugwFq.woff2) format("woff2"),url(./ibm-plex-mono-vietnamese-400-normal-DDuiU_S-.woff) format("woff");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:IBM Plex Mono;font-style:normal;font-display:swap;font-weight:400;src:url(./ibm-plex-mono-latin-ext-400-normal-BmRBH3aV.woff2) format("woff2"),url(./ibm-plex-mono-latin-ext-400-normal-D3D2R8hC.woff) format("woff");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:IBM Plex Mono;font-style:normal;font-display:swap;font-weight:400;src:url(./ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2) format("woff2"),url(./ibm-plex-mono-latin-400-normal-CvHOgSBP.woff) format("woff");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:IBM Plex Mono;font-style:normal;font-display:swap;font-weight:500;src:url(./ibm-plex-mono-cyrillic-ext-500-normal-BqneJy0T.woff2) format("woff2"),url(./ibm-plex-mono-cyrillic-ext-500-normal-BIfNGwUT.woff) format("woff");unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:IBM Plex Mono;font-style:normal;font-display:swap;font-weight:500;src:url(./ibm-plex-mono-cyrillic-500-normal-Bq9vWWag.woff2) format("woff2"),url(./ibm-plex-mono-cyrillic-500-normal-Ael50iVv.woff) format("woff");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:IBM Plex Mono;font-style:normal;font-display:swap;font-weight:500;src:url(./ibm-plex-mono-vietnamese-500-normal-DZ4AoWbu.woff2) format("woff2"),url(./ibm-plex-mono-vietnamese-500-normal-C8zxqsMH.woff) format("woff");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:IBM Plex Mono;font-style:normal;font-display:swap;font-weight:500;src:url(./ibm-plex-mono-latin-ext-500-normal-CAhNIIs5.woff2) format("woff2"),url(./ibm-plex-mono-latin-ext-500-normal-CZ70TYgx.woff) format("woff");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:IBM Plex Mono;font-style:normal;font-display:swap;font-weight:500;src:url(./ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2) format("woff2"),url(./ibm-plex-mono-latin-500-normal-CB9ihrfo.woff) format("woff");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:"Source Serif 4";font-style:normal;font-display:swap;font-weight:400;src:url(./source-serif-4-cyrillic-ext-400-normal-CWV284fw.woff2) format("woff2"),url(./source-serif-4-cyrillic-ext-400-normal-DLkyKLvH.woff) format("woff");unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:"Source Serif 4";font-style:normal;font-display:swap;font-weight:400;src:url(./source-serif-4-cyrillic-400-normal-C44pakCn.woff2) format("woff2"),url(./source-serif-4-cyrillic-400-normal-B8Z6Jvzv.woff) format("woff");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:"Source Serif 4";font-style:normal;font-display:swap;font-weight:400;src:url(./source-serif-4-greek-400-normal-Cw5-AHNN.woff2) format("woff2"),url(./source-serif-4-greek-400-normal-BccYJ-vZ.woff) format("woff");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:"Source Serif 4";font-style:normal;font-display:swap;font-weight:400;src:url(./source-serif-4-vietnamese-400-normal-BbG3LG1A.woff2) format("woff2"),url(./source-serif-4-vietnamese-400-normal-DR1UuFon.woff) format("woff");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:"Source Serif 4";font-style:normal;font-display:swap;font-weight:400;src:url(./source-serif-4-latin-ext-400-normal-Cp7z-ARB.woff2) format("woff2"),url(./source-serif-4-latin-ext-400-normal-CEpydyUl.woff) format("woff");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:"Source Serif 4";font-style:normal;font-display:swap;font-weight:400;src:url(./source-serif-4-latin-400-normal-DJ5YJwmz.woff2) format("woff2"),url(./source-serif-4-latin-400-normal-Dn3IlU-Z.woff) format("woff");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:"Source Serif 4";font-style:normal;font-display:swap;font-weight:600;src:url(./source-serif-4-cyrillic-ext-600-normal-D_E8FDgP.woff2) format("woff2"),url(./source-serif-4-cyrillic-ext-600-normal-DiT2IGQm.woff) format("woff");unicode-range:U+0460-052F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:"Source Serif 4";font-style:normal;font-display:swap;font-weight:600;src:url(./source-serif-4-cyrillic-600-normal-BDP5YDHD.woff2) format("woff2"),url(./source-serif-4-cyrillic-600-normal-DFnC3vAY.woff) format("woff");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:"Source Serif 4";font-style:normal;font-display:swap;font-weight:600;src:url(./source-serif-4-greek-600-normal-DdRkKr-1.woff2) format("woff2"),url(./source-serif-4-greek-600-normal-DhXQw1Kl.woff) format("woff");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:"Source Serif 4";font-style:normal;font-display:swap;font-weight:600;src:url(./source-serif-4-vietnamese-600-normal-CznyfUKR.woff2) format("woff2"),url(./source-serif-4-vietnamese-600-normal-B0WJbuqT.woff) format("woff");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:"Source Serif 4";font-style:normal;font-display:swap;font-weight:600;src:url(./source-serif-4-latin-ext-600-normal-0sIUyHMO.woff2) format("woff2"),url(./source-serif-4-latin-ext-600-normal-C6NNqpJh.woff) format("woff");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:"Source Serif 4";font-style:normal;font-display:swap;font-weight:600;src:url(./source-serif-4-latin-600-normal-DouSKlru.woff2) format("woff2"),url(./source-serif-4-latin-600-normal-DMD1h6_f.woff) format("woff");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}._stage_2307v_2{background-color:var(--diff-canvas);background-image:repeating-conic-gradient(var(--muted) 0% 25%,var(--diff-canvas) 0% 50%);background-size:12px 12px;box-shadow:inset 0 0 0 1px var(--border)}@keyframes _wait-walk_1s58a_1{0%{top:-40%}to{top:100%}}@media(prefers-reduced-motion:no-preference){._walker_1s58a_11{animation:_wait-walk_1s58a_1 1.7s var(--motion-ease) infinite}}._itemActive_xc7sz_1{background-color:var(--accent)}._selection_xc7sz_5{display:none}@supports (anchor-name: --stack-active){._itemActive_xc7sz_1{background-color:transparent;anchor-name:--stack-active}._selection_xc7sz_5{display:block;pointer-events:none;position:absolute;z-index:0;position-anchor:--stack-active;top:anchor(top);left:anchor(left);width:anchor-size(width);height:anchor-size(height);border-radius:var(--radius);background-color:var(--accent)}}@media(prefers-reduced-motion:no-preference){._selection_xc7sz_5{transition-property:top,left,width,height;transition-duration:var(--motion);transition-timing-function:var(--motion-ease)}}@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-duration:initial;--tw-ease:initial;--tw-content:"";--tw-animation-delay:0s;--tw-animation-direction:normal;--tw-animation-duration:initial;--tw-animation-fill-mode:none;--tw-animation-iteration-count:1;--tw-enter-blur:0;--tw-enter-opacity:1;--tw-enter-rotate:0;--tw-enter-scale:1;--tw-enter-translate-x:0;--tw-enter-translate-y:0;--tw-exit-blur:0;--tw-exit-opacity:1;--tw-exit-rotate:0;--tw-exit-scale:1;--tw-exit-translate-x:0;--tw-exit-translate-y:0}}}@layer theme{:root,:host{--font-sans:"IBM Plex Sans", ui-sans-serif, system-ui, sans-serif;--font-mono:"IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;--color-white:#fff;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--tracking-wide:.025em;--leading-snug:1.375;--leading-relaxed:1.625;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:"IBM Plex Sans", ui-sans-serif, system-ui, sans-serif;--default-mono-font-family:"IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}*{border-color:var(--border)}html,body,#root{height:100%}html{view-transition-name:none}body{background-color:var(--background);color:var(--foreground);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:IBM Plex Sans,ui-sans-serif,system-ui,sans-serif;font-size:14px;line-height:1.55}code,pre,kbd{font-family:var(--font-mono)}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.sticky{position:sticky}.inset-x-0{inset-inline:0}.inset-y-0{inset-block:0}.inset-y-1\.5{inset-block:calc(var(--spacing) * 1.5)}.top-0{top:0}.top-1\/2{top:50%}.top-\[28\%\]{top:28%}.left-0{left:0}.z-1{z-index:1}.z-10{z-index:10}.z-50{z-index:50}.m-0{margin:0}.mx-1{margin-inline:var(--spacing)}.mx-3{margin-inline:calc(var(--spacing) * 3)}.mx-\[0\.08em\]{margin-inline:.08em}.mx-auto{margin-inline:auto}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:var(--spacing)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-8{margin-top:calc(var(--spacing) * 8)}.mt-px{margin-top:1px}.mb-1{margin-bottom:var(--spacing)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-5{margin-bottom:calc(var(--spacing) * 5)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.mb-8{margin-bottom:calc(var(--spacing) * 8)}.mb-12{margin-bottom:calc(var(--spacing) * 12)}.ml-auto{margin-left:auto}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.size-2{width:calc(var(--spacing) * 2);height:calc(var(--spacing) * 2)}.size-2\.5{width:calc(var(--spacing) * 2.5);height:calc(var(--spacing) * 2.5)}.size-3\.5{width:calc(var(--spacing) * 3.5);height:calc(var(--spacing) * 3.5)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-6{width:calc(var(--spacing) * 6);height:calc(var(--spacing) * 6)}.size-8{width:calc(var(--spacing) * 8);height:calc(var(--spacing) * 8)}.size-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}.size-full{width:100%;height:100%}.h-6{height:calc(var(--spacing) * 6)}.h-7{height:calc(var(--spacing) * 7)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.h-\[1\.1rem\]{height:1.1rem}.h-\[44\%\]{height:44%}.h-auto{height:auto}.h-full{height:100%}.min-h-0{min-height:0}.w-0\.5{width:calc(var(--spacing) * .5)}.w-2{width:calc(var(--spacing) * 2)}.w-3{width:calc(var(--spacing) * 3)}.w-5{width:calc(var(--spacing) * 5)}.w-\[3px\]{width:3px}.w-\[calc\(100\%-24px\)\]{width:calc(100% - 24px)}.w-fit{width:fit-content}.w-full{width:100%}.w-px{width:1px}.max-w-\[10rem\]{max-width:10rem}.max-w-\[min\(24rem\,calc\(100vw-2rem\)\)\]{max-width:min(24rem,100vw - 2rem)}.max-w-full{max-width:100%}.max-w-none{max-width:none}.min-w-0{min-width:0}.min-w-8{min-width:calc(var(--spacing) * 8)}.min-w-9{min-width:calc(var(--spacing) * 9)}.min-w-10{min-width:calc(var(--spacing) * 10)}.flex-1{flex:1}.flex-none{flex:none}.flex-shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.origin-\(--radix-tooltip-content-transform-origin\){transform-origin:var(--radix-tooltip-content-transform-origin)}.-translate-x-1\/2{--tw-translate-x: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.-rotate-90{rotate:-90deg}.cursor-col-resize{cursor:col-resize}.cursor-pointer{cursor:pointer}.touch-none{touch-action:none}.resize{resize:both}.list-disc{list-style-type:disc}.list-none{list-style-type:none}.auto-cols-\[minmax\(16rem\,1fr\)\]{grid-auto-columns:minmax(16rem,1fr)}.grid-flow-col{grid-auto-flow:column}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-start{align-items:flex-start}.items-stretch{align-items:stretch}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-start{justify-content:flex-start}.gap-0{gap:0}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-\[0\.28rem\]{gap:.28rem}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(var(--spacing) * var(--tw-space-y-reverse));margin-block-end:calc(var(--spacing) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-8>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 8) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 8) * calc(1 - var(--tw-space-y-reverse)))}.gap-x-3{column-gap:calc(var(--spacing) * 3)}.gap-y-1{row-gap:var(--spacing)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.scroll-smooth{scroll-behavior:smooth}.rounded-\[0\.22em\]{border-radius:.22em}.rounded-\[1px\]{border-radius:1px}.rounded-\[inherit\]{border-radius:inherit}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:calc(var(--radius) * 1.3)}.rounded-md{border-radius:var(--radius)}.rounded-none{border-radius:0}.rounded-sm{border-radius:calc(var(--radius) * .7)}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-border{border-color:var(--border)}.border-input{border-color:var(--input)}.border-primary{border-color:var(--primary)}.border-transparent{border-color:#0000}.bg-\[color-mix\(in_srgb\,var\(--foreground\)_8\%\,transparent\)\]{background-color:var(--foreground)}@supports (color:color-mix(in lab,red,red)){.bg-\[color-mix\(in_srgb\,var\(--foreground\)_8\%\,transparent\)\]{background-color:color-mix(in srgb,var(--foreground) 8%,transparent)}}.bg-\[var\(--diff-canvas\)\]{background-color:var(--diff-canvas)}.bg-\[var\(--strand\,var\(--primary\)\)\]{background-color:var(--strand,var(--primary))}.bg-add,.bg-add\/38{background-color:var(--add)}@supports (color:color-mix(in lab,red,red)){.bg-add\/38{background-color:color-mix(in oklab,var(--add) 38%,transparent)}}.bg-background{background-color:var(--background)}.bg-border{background-color:var(--border)}.bg-card{background-color:var(--card)}.bg-del,.bg-del\/38{background-color:var(--del)}@supports (color:color-mix(in lab,red,red)){.bg-del\/38{background-color:color-mix(in oklab,var(--del) 38%,transparent)}}.bg-destructive,.bg-destructive\/20{background-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.bg-destructive\/20{background-color:color-mix(in oklab,var(--destructive) 20%,transparent)}}.bg-foreground{background-color:var(--foreground)}.bg-muted-foreground{background-color:var(--muted-foreground)}.bg-primary{background-color:var(--primary)}.bg-secondary{background-color:var(--secondary)}.bg-transparent{background-color:#0000}.box-decoration-clone{-webkit-box-decoration-break:clone;box-decoration-break:clone}.p-0{padding:0}.px-0\.5{padding-inline:calc(var(--spacing) * .5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.px-8{padding-inline:calc(var(--spacing) * 8)}.px-10{padding-inline:calc(var(--spacing) * 10)}.px-\[0\.32em\]{padding-inline:.32em}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-5{padding-block:calc(var(--spacing) * 5)}.py-6{padding-block:calc(var(--spacing) * 6)}.py-8{padding-block:calc(var(--spacing) * 8)}.py-\[0\.12em\]{padding-block:.12em}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-6{padding-top:calc(var(--spacing) * 6)}.pb-1{padding-bottom:var(--spacing)}.pb-4{padding-bottom:calc(var(--spacing) * 4)}.pb-8{padding-bottom:calc(var(--spacing) * 8)}.pl-5{padding-left:calc(var(--spacing) * 5)}.text-left{text-align:left}.font-mono{font-family:IBM Plex Mono,ui-monospace,SF Mono,Menlo,monospace}.font-sans{font-family:IBM Plex Sans,ui-sans-serif,system-ui,sans-serif}.font-serif{font-family:"Source Serif 4",Iowan Old Style,Georgia,serif}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[0\.86em\]{font-size:.86em}.text-\[1\.75rem\]{font-size:1.75rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.whitespace-normal{white-space:normal}.whitespace-nowrap{white-space:nowrap}.text-add{color:var(--add)}.text-background{color:var(--background)}.text-del{color:var(--del)}.text-destructive{color:var(--destructive)}.text-foreground{color:var(--foreground)}.text-muted-foreground{color:var(--muted-foreground)}.text-primary{color:var(--primary)}.text-primary-foreground{color:var(--primary-foreground)}.text-secondary-foreground{color:var(--secondary-foreground)}.text-warn{color:var(--warn)}.text-white{color:var(--color-white)}.not-italic{font-style:normal}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.underline-offset-4{text-underline-offset:4px}.accent-primary{accent-color:var(--primary)}.opacity-45{opacity:.45}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xs{--tw-shadow:0 1px 2px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.transition-\[border-color\]{transition-property:border-color;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[color\,background-color\,border-color\,box-shadow\,opacity\]{transition-property:color,background-color,border-color,box-shadow,opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-150{--tw-duration:.15s;transition-duration:.15s}.duration-\[var\(--motion\)\]{--tw-duration:var(--motion);transition-duration:var(--motion)}.ease-\[var\(--motion-ease\)\]{--tw-ease:var(--motion-ease);transition-timing-function:var(--motion-ease)}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.after\:absolute:after{content:var(--tw-content);position:absolute}.after\:inset-y-0:after{content:var(--tw-content);inset-block:0}.after\:left-1\/2:after{content:var(--tw-content);left:50%}.after\:w-px:after{content:var(--tw-content);width:1px}.after\:-translate-x-1\/2:after{content:var(--tw-content);--tw-translate-x: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.after\:bg-border:after{content:var(--tw-content);background-color:var(--border)}.after\:transition-\[background-color\]:after{content:var(--tw-content);transition-property:background-color;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.after\:duration-\[var\(--motion\)\]:after{content:var(--tw-content);--tw-duration:var(--motion);transition-duration:var(--motion)}.after\:ease-\[var\(--motion-ease\)\]:after{content:var(--tw-content);--tw-ease:var(--motion-ease);transition-timing-function:var(--motion-ease)}.last\:mb-0:last-child{margin-bottom:0}@media(hover:hover){.hover\:bg-accent:hover{background-color:var(--accent)}.hover\:bg-destructive\/90:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-destructive\/90:hover{background-color:color-mix(in oklab,var(--destructive) 90%,transparent)}}.hover\:bg-muted:hover{background-color:var(--muted)}.hover\:bg-primary\/90:hover{background-color:var(--primary)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-primary\/90:hover{background-color:color-mix(in oklab,var(--primary) 90%,transparent)}}.hover\:bg-secondary\/80:hover{background-color:var(--secondary)}@supports (color:color-mix(in lab,red,red)){.hover\:bg-secondary\/80:hover{background-color:color-mix(in oklab,var(--secondary) 80%,transparent)}}.hover\:bg-transparent:hover{background-color:#0000}.hover\:text-accent-foreground:hover{color:var(--accent-foreground)}.hover\:text-muted-foreground:hover{color:var(--muted-foreground)}.hover\:text-warn:hover{color:var(--warn)}.hover\:underline:hover{text-decoration-line:underline}.hover\:after\:bg-primary\/60:hover:after{content:var(--tw-content);background-color:var(--primary)}@supports (color:color-mix(in lab,red,red)){.hover\:after\:bg-primary\/60:hover:after{background-color:color-mix(in oklab,var(--primary) 60%,transparent)}}.hover\:after\:bg-primary\/70:hover:after{content:var(--tw-content);background-color:var(--primary)}@supports (color:color-mix(in lab,red,red)){.hover\:after\:bg-primary\/70:hover:after{background-color:color-mix(in oklab,var(--primary) 70%,transparent)}}}.focus-visible\:border-ring:focus-visible{border-color:var(--ring)}.focus-visible\:ring-1:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\:ring-ring:focus-visible,.focus-visible\:ring-ring\/50:focus-visible{--tw-ring-color:var(--ring)}@supports (color:color-mix(in lab,red,red)){.focus-visible\:ring-ring\/50:focus-visible{--tw-ring-color:color-mix(in oklab, var(--ring) 50%, transparent)}}.focus-visible\:outline-hidden:focus-visible{--tw-outline-style:none;outline-style:none}@media(forced-colors:active){.focus-visible\:outline-hidden:focus-visible{outline-offset:2px;outline:2px solid #0000}}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:opacity-50:disabled{opacity:.5}.has-\[\>svg\]\:px-2\.5:has(>svg){padding-inline:calc(var(--spacing) * 2.5)}.has-\[\>svg\]\:px-3:has(>svg){padding-inline:calc(var(--spacing) * 3)}.has-\[\>svg\]\:px-4:has(>svg){padding-inline:calc(var(--spacing) * 4)}.aria-\[orientation\=horizontal\]\:h-2[aria-orientation=horizontal]{height:calc(var(--spacing) * 2)}.aria-\[orientation\=horizontal\]\:w-full[aria-orientation=horizontal]{width:100%}.aria-\[orientation\=horizontal\]\:after\:left-0[aria-orientation=horizontal]:after{content:var(--tw-content);left:0}.aria-\[orientation\=horizontal\]\:after\:h-px[aria-orientation=horizontal]:after{content:var(--tw-content);height:1px}.aria-\[orientation\=horizontal\]\:after\:w-full[aria-orientation=horizontal]:after{content:var(--tw-content);width:100%}.aria-\[orientation\=horizontal\]\:after\:translate-x-0[aria-orientation=horizontal]:after{content:var(--tw-content);--tw-translate-x:0px;translate:var(--tw-translate-x) var(--tw-translate-y)}.aria-\[orientation\=horizontal\]\:after\:-translate-y-1\/2[aria-orientation=horizontal]:after{content:var(--tw-content);--tw-translate-y: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.aria-\[orientation\=vertical\]\:flex-col[aria-orientation=vertical]{flex-direction:column}.data-\[orientation\=horizontal\]\:h-px[data-orientation=horizontal]{height:1px}.data-\[orientation\=horizontal\]\:w-full[data-orientation=horizontal]{width:100%}.data-\[orientation\=vertical\]\:h-full[data-orientation=vertical]{height:100%}.data-\[orientation\=vertical\]\:w-px[data-orientation=vertical]{width:1px}.data-\[state\=closed\]\:animate-out[data-state=closed]{animation:exit var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.data-\[state\=closed\]\:fade-out-0[data-state=closed]{--tw-exit-opacity:0}.data-\[state\=delayed-open\]\:animate-in[data-state=delayed-open]{animation:enter var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.data-\[state\=delayed-open\]\:fade-in-0[data-state=delayed-open]{--tw-enter-opacity:0}.data-\[state\=instant-open\]\:animate-in[data-state=instant-open]{animation:enter var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.data-\[state\=instant-open\]\:fade-in-0[data-state=instant-open]{--tw-enter-opacity:0}.data-\[state\=on\]\:bg-accent[data-state=on]{background-color:var(--accent)}.data-\[state\=on\]\:text-accent-foreground[data-state=on]{color:var(--accent-foreground)}@media(prefers-reduced-motion:no-preference){.motion-safe\:after\:transition-colors:after{content:var(--tw-content);transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}}@media not all and (min-width:40rem){.max-sm\:hidden{display:none}}@media(min-width:800px){.min-\[800px\]\:flex-row{flex-direction:row}.min-\[800px\]\:flex-wrap{flex-wrap:wrap}.min-\[800px\]\:items-center{align-items:center}.min-\[800px\]\:justify-between{justify-content:space-between}.min-\[800px\]\:justify-end{justify-content:flex-end}}.\[\&_svg\]\:pointer-events-none svg{pointer-events:none}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}.\[\&_svg\:not\(\[class\*\=\'size-\'\]\)\]\:size-4 svg:not([class*=size-]){width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.\[\&\>svg\]\:pointer-events-none>svg{pointer-events:none}.\[\&\>svg\]\:size-3>svg{width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}[data-motion=group] .\[\[data-motion\=group\]_\&\]\:\[view-transition-name\:review-copy\]{view-transition-name:review-copy}[data-motion=group] .\[\[data-motion\=group\]_\&\]\:\[view-transition-name\:review-overview\]{view-transition-name:review-overview}[data-motion=group] .\[\[data-motion\=group\]_\&\]\:\[view-transition-name\:review-strand\]{view-transition-name:review-strand}[data-motion=scene] .\[\[data-motion\=scene\]_\&\]\:\[view-transition-name\:review-scene\]{view-transition-name:review-scene}}@property --tw-animation-delay{syntax:"*";inherits:false;initial-value:0s}@property --tw-animation-direction{syntax:"*";inherits:false;initial-value:normal}@property --tw-animation-duration{syntax:"*";inherits:false}@property --tw-animation-fill-mode{syntax:"*";inherits:false;initial-value:none}@property --tw-animation-iteration-count{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-blur{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-opacity{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-rotate{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-scale{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-blur{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-opacity{syntax:"*";inherits:false;initial-value:1}@property --tw-exit-rotate{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-scale{syntax:"*";inherits:false;initial-value:1}@property --tw-exit-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-translate-y{syntax:"*";inherits:false;initial-value:0}:root{color-scheme:light;--motion:.18s;--motion-brief:.5s;--motion-brief-gap:50ms;--motion-ease:cubic-bezier(.2, .8, .2, 1);--radius:.45rem;--background:#f4f6f8;--foreground:#171b22;--card:#fff;--card-foreground:#171b22;--popover:#fff;--popover-foreground:#171b22;--primary:#3d4fd8;--primary-foreground:#fff;--secondary:#e8ecf1;--secondary-foreground:#171b22;--muted:#e8ecf1;--muted-foreground:#5c6570;--accent:#e4e8f4;--accent-foreground:#171b22;--destructive:#cf222e;--border:#d5dbe3;--input:#d5dbe3;--ring:#3d4fd8;--add:#1a7f37;--del:#cf222e;--warn:#9a6700;--add-bg:#1a7f3729;--del-bg:#cf222e29;--diff-canvas:#fff;--diff-fg:#1f2328;--diff-add-line:#e6ffec;--diff-add-num:#ccffd8;--diff-add-word:#abf2bc;--diff-del-line:#ffebe9;--diff-del-num:#ffd7d5;--diff-del-word:#ff818266;--diff-hunk:#ddf4ff;--diff-hover:#f6f8fa;--strand-0:#2458b5;--strand-1:#9a5b00;--strand-2:#6b3d96;--strand-3:#0b6e78;--strand-4:#9a356e;--strand-5:#3a5366}.dark{color-scheme:dark;--background:#12151c;--foreground:#e6eaf0;--card:#1a1e27;--card-foreground:#e6eaf0;--popover:#1a1e27;--popover-foreground:#e6eaf0;--primary:#8b9cff;--primary-foreground:#12151c;--secondary:#252a33;--secondary-foreground:#e6eaf0;--muted:#252a33;--muted-foreground:#8b939e;--accent:#2a3148;--accent-foreground:#e6eaf0;--destructive:#f85149;--border:#2c3340;--input:#2c3340;--ring:#8b9cff;--add:#3fb950;--del:#f85149;--warn:#d4a017;--add-bg:#3fb95029;--del-bg:#f8514929;--diff-canvas:#0d1117;--diff-fg:#e6edf3;--diff-add-line:#2ea04326;--diff-add-num:#2ea04366;--diff-add-word:#2ea04366;--diff-del-line:#f8514926;--diff-del-num:#f8514966;--diff-del-word:#f8514966;--diff-hunk:#388bfd1a;--diff-hover:#161b22;--strand-0:#8fb4f0;--strand-1:#e0a64a;--strand-2:#c9a3e8;--strand-3:#6ed0d6;--strand-4:#e399c0;--strand-5:#9ab0c2}::view-transition-old(review-strand){mix-blend-mode:normal;animation-timing-function:var(--motion-ease);animation-fill-mode:both}::view-transition-new(review-strand){mix-blend-mode:normal;animation-timing-function:var(--motion-ease);animation-fill-mode:both}::view-transition-old(review-copy){mix-blend-mode:normal;animation-timing-function:var(--motion-ease);animation-fill-mode:both}::view-transition-new(review-copy){mix-blend-mode:normal;animation-timing-function:var(--motion-ease);animation-fill-mode:both}::view-transition-old(review-overview){mix-blend-mode:normal;animation-timing-function:var(--motion-ease);animation-fill-mode:both}::view-transition-new(review-overview){mix-blend-mode:normal;animation-timing-function:var(--motion-ease);animation-fill-mode:both}::view-transition-old(review-scene){mix-blend-mode:normal;animation-timing-function:var(--motion-ease);animation-fill-mode:both}::view-transition-new(review-scene){mix-blend-mode:normal;animation-timing-function:var(--motion-ease);animation-fill-mode:both}::view-transition-old(review-strand){height:100%;animation-duration:var(--motion-brief);overflow:clip}::view-transition-new(review-strand){height:100%;animation-duration:var(--motion-brief);overflow:clip}::view-transition-old(review-strand){animation-name:motion-fade-out}::view-transition-new(review-strand){animation-name:motion-fade-in}::view-transition-group(review-strand){animation-duration:var(--motion-brief);animation-timing-function:var(--motion-ease)}::view-transition-image-pair(review-strand){isolation:isolate}::view-transition-old(review-copy){animation-name:motion-slide-down-out;animation-duration:calc((var(--motion-brief) - var(--motion-brief-gap)) / 2)}::view-transition-new(review-copy){animation-name:motion-slide-up-in;animation-duration:calc((var(--motion-brief) - var(--motion-brief-gap)) / 2);animation-delay:calc((var(--motion-brief) + var(--motion-brief-gap)) / 2)}::view-transition-group(review-copy){animation:none}::view-transition-old(review-overview){animation-name:motion-fade-out;animation-duration:var(--motion-brief)}::view-transition-new(review-overview){animation-name:motion-fade-in;animation-duration:var(--motion-brief)}::view-transition-group(review-overview){animation:none}::view-transition-old(review-scene){animation-name:motion-fade-out;animation-duration:var(--motion)}::view-transition-new(review-scene){animation-name:motion-fade-in;animation-duration:var(--motion)}::view-transition-group(review-scene){animation-duration:var(--motion);animation-timing-function:var(--motion-ease)}::view-transition-image-pair(review-scene){isolation:isolate}@keyframes motion-fade-out{to{opacity:0}}@keyframes motion-fade-in{0%{opacity:0}}@keyframes motion-slide-down-out{to{opacity:0;translate:0 .75rem}}@keyframes motion-slide-up-in{0%{opacity:0;translate:0 .75rem}}@media(prefers-reduced-motion:reduce){*,:before,:after{scroll-behavior:auto!important;transition-duration:.01ms!important;animation-duration:.01ms!important;animation-iteration-count:1!important}::view-transition-group(*){animation:none!important}::view-transition-old(*){animation:none!important}::view-transition-new(*){animation:none!important}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-content{syntax:"*";inherits:false;initial-value:""}@keyframes enter{0%{opacity:var(--tw-enter-opacity,1);transform:translate3d(var(--tw-enter-translate-x,0),var(--tw-enter-translate-y,0),0)scale3d(var(--tw-enter-scale,1),var(--tw-enter-scale,1),var(--tw-enter-scale,1))rotate(var(--tw-enter-rotate,0));filter:blur(var(--tw-enter-blur,0))}}@keyframes exit{to{opacity:var(--tw-exit-opacity,1);transform:translate3d(var(--tw-exit-translate-x,0),var(--tw-exit-translate-y,0),0)scale3d(var(--tw-exit-scale,1),var(--tw-exit-scale,1),var(--tw-exit-scale,1))rotate(var(--tw-exit-rotate,0));filter:blur(var(--tw-exit-blur,0))}}
|