difftab 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,155 +1,72 @@
1
1
  # difftab
2
2
 
3
+ [![npm](https://img.shields.io/npm/v/difftab)](https://www.npmjs.com/package/difftab)
4
+
3
5
  **See what your AI coding agent changed — in one tab.**
4
6
 
5
- Run one command in your repo. A local page opens with your working-tree diff and
6
- branch status — read-only. Close the tab and the process exits on its own.
7
+ Run one command in your repo. A local page opens with your working-tree diff and branch
8
+ status — what `git status` and `git diff HEAD` would show — read-only, refreshing itself
9
+ while the agent keeps writing. Close the tab and the process exits.
7
10
 
8
11
  [中文文档](README.zh-CN.md)
9
12
 
10
- difftab is built for the moment right after an agent finishes (or while it is still
11
- running): you want a quick look at the changes, not a review session. It shows the
12
- same thing `git status` and `git diff HEAD` would, rendered as side-by-side diffs with
13
- syntax highlighting, and it refreshes itself as the agent keeps writing. It never writes
14
- to your repository — the core promise, enforced by two CI gates and
15
- [described below](#never-writes-to-your-repository).
16
-
17
13
  ## Install
18
14
 
19
- Nothing to install — run it in any repository:
20
-
21
- ```bash
22
- npx difftab # pnpm users: pnpm dlx difftab
23
- ```
24
-
25
- The first run spends a few seconds downloading and unpacking the package; later runs come
26
- from the cache.
27
-
28
- If you reach for it after every agent run, install it once instead — an `npx` run spends
29
- more time resolving which version to fetch than difftab spends starting up:
30
-
31
15
  ```bash
32
- npm i -g difftab # or: pnpm add -g difftab
16
+ npx difftab # or install it once: npm i -g difftab
33
17
  ```
34
18
 
35
- Requires **Node.js 22.0.0 or newer**. `dependencies` is empty: the backend uses only the
36
- Node standard library, and the frontend is bundled at build time, so a global install
37
- pulls in zero transitive packages.
19
+ Requires **Node.js 22 or newer** on macOS, Windows or Linux. Zero dependencies.
38
20
 
39
21
  ## Usage
40
22
 
41
23
  ```bash
42
24
  cd /path/to/your/repo
43
- difftab # or: npx difftab
25
+ difftab
44
26
  ```
45
27
 
46
- | Option | What it does |
47
- |---|---|
48
- | `--no-open` | print the URL instead of opening a browser |
49
- | `-v`, `--version` | print the version and exit |
50
- | `-h`, `--help` | print help and exit |
28
+ - `--no-open` — print the URL instead of opening a browser
29
+ - `-v`, `--version` — print the version and exit
30
+ - `-h`, `--help` — print help and exit
51
31
 
52
- Running it again in the same repository reuses the running instance instead of starting a
53
- second process.
32
+ Running it again in the same repository reuses the running instance.
54
33
 
55
34
  ## What you get
56
35
 
57
- - **Change list** — staged, unstaged and untracked files in three groups, plus conflicts
58
- in their own group with both status letters. Untracked directories are expanded to
59
- individual files rather than collapsed into a single `dir/` entry.
60
- - **Diffs, lazily** — click a file to load its patch; nothing fetches the whole-repo diff.
61
- Rendered with [diff2html](https://diff2html.xyz/) and highlight.js in a VS Code-like
62
- theme, light and dark following your system appearance.
63
- - **Branch status** — current branch and ahead/behind counts, "no upstream" when there is
64
- none, and a label for detached HEAD or an in-progress rebase / merge / cherry-pick /
65
- revert / bisect / `git am`.
66
- - **Auto-refresh** — a file watcher pushes changes over SSE, so the page keeps up while
67
- an agent is still writing. Where recursive watching would exhaust the machine-wide
68
- inotify quota (Linux on Node < 24.14.0), it polls instead and says so in the UI; while
69
- polling, editing an *untracked* file's contents does not refresh the page (an untracked
70
- entry is a single line in `git status` that does not change when its content does).
71
- - **Exits on its own** — 45 seconds after the last tab closes. Multiple tabs, page
72
- reloads, sleep/wake and backgrounded tabs do not trigger it.
73
-
74
- Edge cases are handled explicitly rather than left to fail: empty repositories (no
75
- commits yet), detached HEAD, an interrupted rebase, linked worktrees, submodules, binary
76
- files, files over 5 MB, renames (annotated with the old path and similarity), deleted
77
- files, and paths containing spaces, quotes, CJK characters or emoji.
78
-
79
- difftab is deliberately a viewer: no editing, no history, no blame, no review workflow.
80
- The full out-of-scope list is in
81
- [CONTRIBUTING.md](CONTRIBUTING.md#the-read-only-promise-is-not-negotiable) and
82
- [`docs/spec.md`](docs/spec.md) §4.
36
+ - **Change list** — staged, unstaged, untracked and conflicting files in four groups, with
37
+ untracked directories expanded to files.
38
+ - **Diffs, lazily** — click a file to load its patch, rendered by
39
+ [diff2html](https://diff2html.xyz/) + highlight.js in a VS Code-like theme, side by side
40
+ until the pane gets too narrow.
41
+ - **Branch status** — branch name, ahead/behind counts, "no upstream", detached HEAD, and
42
+ an in-progress rebase / merge / cherry-pick / revert / bisect / `git am`.
43
+ - **Auto-refresh** — a file watcher pushes changes over SSE, falling back to polling where
44
+ recursive watching would exhaust the inotify quota (and saying so in the UI).
45
+ - **Exits on its own** — 45 seconds after the last tab closes.
46
+
47
+ Empty repositories, interrupted rebases, linked worktrees, submodules, binary and >5 MB
48
+ files, renames, and paths with spaces, quotes, CJK or emoji are handled explicitly.
49
+ difftab is deliberately a viewer: no editing, history, blame or review workflow
50
+ ([out-of-scope list](CONTRIBUTING.md#the-read-only-promise-is-not-negotiable)).
83
51
 
84
52
  ## Never writes to your repository
85
53
 
86
- Not a best-effort claim. difftab never stages, commits, discards, pulls, pushes,
87
- branches or stashes — it only ever runs read-only git commands. Two independent gates
88
- enforce that on every CI run, on all three platforms:
89
-
90
- 1. **Command allowlist.** The whole flow runs under `GIT_TRACE`, and every git
91
- invocation the product makes — including subprocesses git spawns internally, such as
92
- an accidental `gc` — is asserted to be one of `status` / `diff` / `rev-parse` /
93
- `ls-files` / `version`. A positive assertion checks the trace is not empty, so the
94
- allowlist can never pass against nothing.
95
- 2. **`.git` is byte-for-byte unchanged.** The flow runs once against a read-only `.git`,
96
- and once against a writable one with a before/after snapshot of every file (size,
97
- mtime, content digest). A control run proves the snapshot would have caught a change.
98
-
99
- The backend is also auditable by hand: `dist/server/main.js` ships unminified precisely
100
- so you can read which git commands it runs.
101
-
102
- ## Local security
103
-
104
- The server binds `127.0.0.1` on a random port with a session token, and every request —
105
- including SSE and static assets — passes three checks *before* anything else is decided:
106
-
107
- - **`Host`** must be `127.0.0.1:<port>` or `localhost:<port>`. This, not the token, is the
108
- real defence against DNS rebinding.
109
- - **`Origin`**, when present, must be the server's own. No CORS headers are ever sent.
110
- - **Token**, bound to this session's port, so a token that leaks to another localhost
111
- service (cookies are scoped by host, not by port) cannot be replayed there.
112
-
113
- The token arrives in the URL once and is immediately swapped for an `HttpOnly;
114
- SameSite=Strict` cookie with a 302 that strips the query, so it does not linger in browser
115
- history. Responses carry a strict CSP (`default-src 'none'`, plus `frame-ancestors` /
116
- `base-uri` / `form-action`, which do not fall back to it), `Cache-Control: no-store` and
117
- `X-Content-Type-Options: nosniff`. Static assets are served from an in-memory allowlist,
118
- never by joining a request path onto a directory. There is no environment variable or code
119
- branch that relaxes any of this.
120
-
121
- ## Platform support
122
-
123
- macOS, Windows and Linux are all supported and all tested. CI runs the full smoke suite
124
- across three platforms × Node 22 / 24 / 26, plus dedicated jobs for global installation,
125
- the Node version guard, and degrading to polling when the inotify quota is exhausted.
126
- What CI cannot cover is in [Known limitations](#known-limitations), below.
127
-
128
- ## Known limitations
129
-
130
- - **The token is passed on a command line.** argv is readable by other users on the same
131
- machine, so launching the browser opens a window of tens of milliseconds — one that
132
- requires an attacker already logged in locally, polling in a tight loop. Closing it
133
- properly conflicts with reusing a running instance, so it is revisited after 0.1.0. How
134
- wide it is under `xdg-open` is deliberately *not* measured in CI: a headless number
135
- would be reassuring and meaningless.
136
- - **The browser actually appearing on a Windows or Linux desktop is not covered by CI.**
137
- Runners have no desktop session, so the *choice* of `open` / `cmd /c start ""` /
138
- `xdg-open` and its argv are asserted, but not the window. Both of these wait on a first
139
- real user.
54
+ Not a best-effort claim: difftab only ever runs read-only git commands — no stage, commit,
55
+ discard, pull, push, branch or stash. Two gates enforce it on every change: a `GIT_TRACE`
56
+ allowlist over every git invocation, and a byte-for-byte comparison of `.git` before and
57
+ after. And `dist/server/main.js` ships unminified, so you can audit it by hand.
140
58
 
141
59
  ## Development
142
60
 
143
61
  ```bash
144
- pnpm install --frozen-lockfile # pnpm version is pinned by the packageManager field
62
+ pnpm install --frozen-lockfile
145
63
  pnpm build # frontend (Vite) + backend (tsdown)
146
64
  node bin/difftab.js # run it against any repository
147
65
  ```
148
66
 
149
- [CONTRIBUTING.md](CONTRIBUTING.md) has the rest: the dev-server setup, the full list of
150
- gates, and the handful of things in this codebase that fail silently rather than loudly.
151
- Requirements and design live in [`docs/`](docs/README.md) and are the single source of
152
- truth — they change before the code does.
67
+ [CONTRIBUTING.md](CONTRIBUTING.md) has the dev-server setup, the gates, and the things
68
+ that fail silently rather than loudly; [`docs/`](docs/README.md) holds requirements and
69
+ design, the single source of truth.
153
70
 
154
71
  ## License
155
72
 
package/README.zh-CN.md CHANGED
@@ -1,136 +1,58 @@
1
1
  # difftab
2
2
 
3
- **一个标签页,看懂 AI 编码 Agent 改了哪些代码。**
3
+ [![npm](https://img.shields.io/npm/v/difftab)](https://www.npmjs.com/package/difftab)
4
4
 
5
- 在仓库目录敲一条命令。本地网页随即打开,只读展示当前工作区的 diff 与分支状态。
6
- 关掉标签页,进程自行退出。
5
+ **一个标签页,看懂 AI 编码 Agent 改了哪些代码。**
7
6
 
8
- [English](README.md)
7
+ 在仓库目录敲一条命令,本地网页随即打开,只读展示当前工作区的 diff 与分支状态(就是 `git status` 与 `git diff HEAD` 的内容),并在 agent 继续写的过程中自动刷新;关掉标签页,进程自行退出。
9
8
 
10
- difftab 面向的是 agent 刚跑完(或者还在跑)的那一刻:你想「瞥一眼」改了什么,而不是
11
- 开一场代码评审。它展示的就是 `git status` 与 `git diff HEAD` 的内容,以并排 diff 加语法
12
- 高亮呈现,并在 agent 继续写的过程中自动刷新。它对你的仓库**全程零写操作**——这是核心承诺,
13
- 由两道 CI 门禁守着,详见[下文](#全程零写操作)。
9
+ [English](README.md)
14
10
 
15
11
  ## 安装
16
12
 
17
- 不用装,在任意仓库目录里直接跑:
18
-
19
- ```bash
20
- npx difftab # pnpm 用户:pnpm dlx difftab
21
- ```
22
-
23
- 首次要下载解包,多花几秒,之后走缓存。
24
-
25
- 如果你每次 agent 跑完都要看一眼,那就装一次——`npx` 光是决定该跑哪个版本,就比 difftab
26
- 自己启动还花时间:
27
-
28
13
  ```bash
29
- npm i -g difftab # 或:pnpm add -g difftab
14
+ npx difftab # 或者装一次:npm i -g difftab
30
15
  ```
31
16
 
32
- 要求 **Node.js 22.0.0 或更高**。`dependencies` 为空:后端只用 Node 标准库,前端在构建期
33
- 就打进产物,所以全局安装是零传递依赖的。
17
+ 要求 **Node.js 22 或更高**,macOS / Windows / Linux 三端均支持,零依赖。
34
18
 
35
19
  ## 使用
36
20
 
37
21
  ```bash
38
22
  cd /path/to/your/repo
39
- difftab # 或:npx difftab
23
+ difftab
40
24
  ```
41
25
 
42
- | 参数 | 作用 |
43
- |---|---|
44
- | `--no-open` | 只打印 URL,不拉起浏览器 |
45
- | `-v`, `--version` | 打印版本号并退出 |
46
- | `-h`, `--help` | 打印帮助并退出 |
26
+ - `--no-open`——只打印 URL,不拉起浏览器
27
+ - `-v`, `--version`——打印版本号并退出
28
+ - `-h`, `--help`——打印帮助并退出
47
29
 
48
- 在同一个仓库里再敲一次,会复用已在跑的实例,而不是起第二个进程。
30
+ 在同一个仓库里再敲一次,会复用已在跑的实例。
49
31
 
50
32
  ## 能看到什么
51
33
 
52
- - **变更列表** —— 已暂存、未暂存、未跟踪三组,冲突文件自成一组并印出 XY 两位状态。未跟踪
53
- 的目录展开到文件粒度,而不是折叠成一行 `dir/`。
54
- - **按文件懒加载的 diff** —— 点开某个文件才取它的补丁,任何时候都不会去取整仓 diff。渲染
55
- 用 [diff2html](https://diff2html.xyz/) + highlight.js,配色仿 VS Code,深浅两套跟随系统
56
- 外观。
57
- - **分支状态** —— 当前分支与 ahead/behind 计数,无上游时明说「无上游」;游离 HEAD 与进行
58
- 中的 rebase / merge / cherry-pick / revert / bisect / `git am` 各出一个标注。
59
- - **自动刷新** —— 文件监听经 SSE 推到前端,agent 边改你边看。在递归监听会耗尽整机
60
- inotify 配额的场合(Linux + Node < 24.14.0),改用轮询,并在界面上标注出来;轮询期间改
61
- 一个**未跟踪**文件的内容不会刷新页面(未跟踪条目在 `git status` 里只有一行,内容变了它
62
- 一个字节都不变)。
63
- - **自己退出** —— 最后一个标签页关掉 45 秒后自动退。多标签、刷新页面、系统休眠唤醒、浏览
64
- 器丢弃后台标签都不会误触发。
65
-
66
- 边界情况是被显式处理的,而不是留着崩:空仓库(还没有提交)、游离 HEAD、停在中途的 rebase、
67
- linked worktree、submodule、二进制文件、超过 5MB 的文件、重命名(标注完整旧路径与相似度)、
68
- 删除的文件,以及路径里带空格、引号、中日韩文字或 emoji 的文件。
69
-
70
- difftab 刻意只是个查看器:不编辑代码、不看历史、不做 blame、不承载评审流程。完整的不做
71
- 清单在 [CONTRIBUTING.md](CONTRIBUTING.md#the-read-only-promise-is-not-negotiable) 与
72
- [`docs/spec.md`](docs/spec.md) §4。
73
-
74
- ## 全程零写操作
34
+ - **变更列表**——已暂存、未暂存、未跟踪、冲突四组,未跟踪的目录展开到文件粒度。
35
+ - **按文件懒加载的 diff**——点开某个文件才取它的补丁,渲染用 [diff2html](https://diff2html.xyz/) + highlight.js,配色仿 VS Code,面板窄到放不下两列时自动切成逐行。
36
+ - **分支状态**——当前分支、ahead/behind 计数、无上游、游离 HEAD,以及进行中的 rebase /
37
+ merge / cherry-pick / revert / bisect / `git am`。
38
+ - **自动刷新**——文件监听经 SSE 推到前端;递归监听会耗尽 inotify 配额的场合改用轮询,并在界面上标注。
39
+ - **自己退出**——最后一个标签页关掉 45 秒后自动退。
75
40
 
76
- 不是「尽量」。difftab 不 stage、不 commit、不 discard、不 pull / push、不建分支、
77
- 不 stash——它只发只读的 git 命令。这条由两道互相独立的门禁在每次 CI、三个平台上守着:
41
+ 空仓库、停在中途的 rebase、linked worktree、submodule、二进制与超过 5MB 的文件、重命名,以及带空格、引号、中日韩文字或 emoji 的路径,都是被显式处理的。difftab 刻意只是个查看器:不编辑、不看历史、不做 blame、不承载评审流程(完整的不做清单见 [CONTRIBUTING.md](CONTRIBUTING.md#the-read-only-promise-is-not-negotiable))。
78
42
 
79
- 1. **命令白名单。** 整条流程跑在 `GIT_TRACE` 之下,产品发出的每一次 git 调用——包括 git
80
- 自己内部再起的子进程(比如一次意外触发的 `gc`)——都被断言只能是 `status` / `diff` /
81
- `rev-parse` / `ls-files` / `version`。另配一条「确实记到了东西」的正面断言,白名单不会
82
- 对着一个空数组通过。
83
- 2. **`.git` 逐字节不变。** 同一条流程跑两遍:一遍对着只读的 `.git`,一遍对着可写的
84
- `.git` 并在前后各拍一次快照(每个文件的 size、mtime、内容摘要)比对。另有一组正面对照
85
- 证明这份快照真的抓得住变化。
86
-
87
- 后端也支持手工审计:`dist/server/main.js` **不压缩不混淆**发布,就是为了让你自己读一遍它
88
- 到底跑了哪些 git 命令。
89
-
90
- ## 本地安全
91
-
92
- 服务绑定 `127.0.0.1`,随机端口 + 会话级 token。每一个请求——包括 SSE 与静态资源——都要先
93
- 过三道校验,**排在其余一切判定之前**:
94
-
95
- - **`Host`** 必须是 `127.0.0.1:<端口>` 或 `localhost:<端口>`。挡住 DNS rebinding 的是这一
96
- 道,不是 token。
97
- - **`Origin`** 非空时必须是服务自身。所有响应不带任何 CORS 头。
98
- - **token** 与本次会话的端口绑定——cookie 的作用域是 host 而非 origin,不隔离端口,绑上
99
- 端口后即使 token 漏给了同机另一个 localhost 服务,也没法在别处复用。
100
-
101
- token 只在 URL 里出现一次,首访即置换成 `HttpOnly; SameSite=Strict` cookie 并 302 掉
102
- query,不会长期滞留在浏览器历史里。响应带严格 CSP(`default-src 'none'`,外加不回退到它的
103
- `frame-ancestors` / `base-uri` / `form-action`),以及 `Cache-Control: no-store` 与
104
- `X-Content-Type-Options: nosniff`。静态资源按内存里的白名单映射,绝不用请求路径去拼目录。
105
- **后端不存在任何放宽上述校验的环境变量或分支。**
106
-
107
- ## 平台支持
108
-
109
- macOS / Windows / Linux 三端均支持、均有测试。CI 在三平台 × Node 22 / 24 / 26 上跑完整冒烟
110
- 套件,另有全局安装、Node 版本守卫、inotify 配额耗尽降级三个专用作业。CI 覆盖不到的部分在
111
- 下面的[已知边界](#已知边界)。
112
-
113
- ## 已知边界
43
+ ## 全程零写操作
114
44
 
115
- - **token 要经过一次命令行。** argv 对同机其他用户可读,所以拉起浏览器时有一个几十毫秒的
116
- 窗口——而它要求攻击者已经以另一个本机用户身份在紧循环轮询。真正关掉它与「再敲一次命令
117
- 复用已有实例」相冲突,留到 0.1.0 之后再看。这个窗口在 `xdg-open` 下有多宽**刻意不在 CI
118
- 里量**:headless 上量出来的数字会让人放心,但没有意义。
119
- - **浏览器在 Windows / Linux 桌面上真的弹出来,CI 覆盖不到。** runner 没有桌面会话,所以
120
- `open` / `cmd /c start ""` / `xdg-open` 的**选择与 argv** 有断言,窗口本身没有。这两条
121
- 都等首个真实用户。
45
+ 不是「尽量」:difftab 只发只读的 git 命令——不 stage、不 commit、不 discard、不 pull / push、不建分支、不 stash。两道门禁在每次改动上守着:一道是覆盖每一次 git 调用的 `GIT_TRACE` 命令白名单,另一道是 `.git` 前后逐字节比对。后端也支持手工审计:`dist/server/main.js` 不压缩不混淆发布。
122
46
 
123
47
  ## 开发
124
48
 
125
49
  ```bash
126
- pnpm install --frozen-lockfile # pnpm 版本由 packageManager 字段固定
50
+ pnpm install --frozen-lockfile
127
51
  pnpm build # 前端 Vite + 后端 tsdown
128
52
  node bin/difftab.js # 在任意 git 仓库目录下跑起来
129
53
  ```
130
54
 
131
- 其余在 [CONTRIBUTING.md](CONTRIBUTING.md):dev server 怎么起、完整的门禁清单,以及这个仓库
132
- 里那几条「坏了不报错」的地方。需求与设计的唯一事实来源是 [`docs/`](docs/README.md)——需求要
133
- 变,先改 docs 再改代码。
55
+ 其余在 [CONTRIBUTING.md](CONTRIBUTING.md):dev server 怎么起、门禁清单,以及那几条「坏了不报错」的地方;需求与设计的唯一事实来源是 [`docs/`](docs/README.md)。
134
56
 
135
57
  ## License
136
58
 
@@ -1,7 +1,7 @@
1
1
  import { closeSync, mkdirSync, openSync, readFileSync, realpathSync, statSync, unlinkSync, watch, writeFileSync, writeSync } from "node:fs";
2
2
  import { fileURLToPath } from "node:url";
3
3
  import { parseArgs } from "node:util";
4
- import { isAbsolute, join, relative, resolve, sep } from "node:path";
4
+ import { basename, isAbsolute, join, relative, resolve, sep } from "node:path";
5
5
  import { spawn } from "node:child_process";
6
6
  import { createServer, request } from "node:http";
7
7
  import { homedir, tmpdir } from "node:os";
@@ -267,6 +267,23 @@ async function locateRepo(cwd) {
267
267
  };
268
268
  }
269
269
  /**
270
+ * 工作区根目录名 —— 页面标题里的项目标识(§5.4 / §5.12 的 `RepoState.repoName`)。
271
+ *
272
+ * **和 `root` 住在一起,不在消费者那边现切**:下面那条「用 `node:path` 不手写切分」
273
+ * 的理由整个建立在 `root` 是怎么来的之上(`rev-parse --show-toplevel`),而那件事只有
274
+ * 本文件知道。放在 `http/` 里的话,这里改一次 `root` 的产出方式,那边的论证就静默过期。
275
+ *
276
+ * **用 `node:path` 的 `basename`,不要自己切 `/`**:Windows 上 `--show-toplevel` 回的是
277
+ * `C:/…` 正斜杠,而 win32 的 basename 两种分隔符都认;POSIX 上 `\` 是合法文件名字符,
278
+ * posix 的 basename 不会误把它当分隔符。两个平台各有一半是手写切分挑不对的。
279
+ *
280
+ * 根目录没有 basename 时(`/`、Windows 盘符根)回空串,**不编一个名字出来** ——
281
+ * 「取不到时显示什么」是展示决定,归消费者(见 `shared/protocol.ts`)。
282
+ */
283
+ function repoNameOf(repo) {
284
+ return basename(repo.root);
285
+ }
286
+ /**
270
287
  * diff 的基准。
271
288
  *
272
289
  * 正常仓库是 `HEAD`;空仓库(尚无任何提交)下 HEAD 不存在,`git diff HEAD` 会 fatal,
@@ -1575,6 +1592,7 @@ async function startServer(repo, options = {}) {
1575
1592
  message: sanitizeMessage(message, repo.root)
1576
1593
  } });
1577
1594
  };
1595
+ const repoName = repoNameOf(repo);
1578
1596
  const secret = createSecret();
1579
1597
  let token = "";
1580
1598
  let port = 0;
@@ -1721,6 +1739,7 @@ async function startServer(repo, options = {}) {
1721
1739
  case "/api/state": {
1722
1740
  const status = await readStatus(repo);
1723
1741
  sendJson(res, 200, {
1742
+ repoName,
1724
1743
  branch: status.branch,
1725
1744
  files: status.files,
1726
1745
  watch: currentWatchState()
package/dist/web/app.css CHANGED
@@ -1,3 +1,3 @@
1
1
  /*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
2
- @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{--tw-border-style:solid;--tw-font-weight:initial;--tw-outline-style:solid}::backdrop{--tw-border-style:solid;--tw-font-weight:initial;--tw-outline-style:solid}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, -apple-system, "Segoe UI", "Noto Sans", "PingFang SC", "Microsoft YaHei", sans-serif;--font-mono:ui-monospace, "SF Mono", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-medium:500;--radius-sm:.25rem;--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-editor-background:#fff;--color-editor-foreground:#3b3b3b;--color-side-bar-background:#f8f8f8;--color-side-bar-section-header-background:#f0f0f0;--color-title-bar-background:#f8f8f8;--color-panel-border:#e5e5e5;--color-description-foreground:#6f6f6f;--color-focus-border:#005fb8;--color-text-link-foreground:#005fb8;--color-list-hover-background:#e8e8e8;--color-list-active-selection-background:#e4e6f1;--color-list-active-selection-foreground:#000;--color-warning-background:#fdf6d3;--color-warning-border:#b89500;--color-git-modified:#895503;--color-git-deleted:#ad0707;--color-git-added:#587c0c;--color-git-untracked:#007100;--color-git-conflicting:#ad0707;--color-diff-inserted-background:#9bb95533;--color-diff-inserted-text-background:#9bb95573;--color-diff-inserted-border:#9bb95580;--color-diff-removed-background:#ff000029;--color-diff-removed-text-background:#ff000052;--color-diff-removed-border:#ff000059;--color-diff-diagonal-fill:#0000000f}}@layer base{*,:after,:before{box-sizing:border-box;border:0 solid;margin:0;padding:0}::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;-webkit-text-decoration:inherit;-webkit-text-decoration: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}}@layer components;@layer utilities{.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.top-0{top:0}.ml-1{margin-left:var(--spacing)}.contents{display:contents}.flex{display:flex}.h-screen{height:100vh}.min-h-0{min-height:0}.w-5{width:calc(var(--spacing) * 5)}.w-80{width:calc(var(--spacing) * 80)}.w-full{width:100%}.max-w-60{max-width:calc(var(--spacing) * 60)}.min-w-0{min-width:0}.flex-1{flex:1}.shrink-0{flex-shrink:0}.flex-col{flex-direction:column}.items-baseline{align-items:baseline}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.rounded-sm{border-radius:var(--radius-sm)}.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-panel-border{border-color:var(--color-panel-border)}.border-warning-border{border-color:var(--color-warning-border)}.bg-editor-background{background-color:var(--color-editor-background)}.bg-list-active-selection-background{background-color:var(--color-list-active-selection-background)}.bg-side-bar-background{background-color:var(--color-side-bar-background)}.bg-side-bar-section-header-background{background-color:var(--color-side-bar-section-header-background)}.bg-title-bar-background{background-color:var(--color-title-bar-background)}.bg-warning-background{background-color:var(--color-warning-background)}.p-4{padding:calc(var(--spacing) * 4)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.py-2{padding-block:calc(var(--spacing) * 2)}.text-center{text-align:center}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.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))}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.break-all{word-break:break-all}.text-description-foreground{color:var(--color-description-foreground)}.text-editor-foreground{color:var(--color-editor-foreground)}.text-git-added{color:var(--color-git-added)}.text-git-conflicting{color:var(--color-git-conflicting)}.text-git-deleted{color:var(--color-git-deleted)}.text-git-modified{color:var(--color-git-modified)}.text-git-untracked{color:var(--color-git-untracked)}.text-list-active-selection-foreground{color:var(--color-list-active-selection-foreground)}@media (hover:hover){.hover\:bg-list-hover-background:hover{background-color:var(--color-list-hover-background)}}.focus-visible\:outline-2:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px}.focus-visible\:-outline-offset-2:focus-visible{outline-offset:calc(2px * -1)}.focus-visible\:outline-focus-border:focus-visible{outline-color:var(--color-focus-border)}}pre code.hljs{padding:1em;display:block;overflow-x:auto}code.hljs{padding:3px 5px}.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}@media (prefers-color-scheme:dark){pre code.hljs{padding:1em;display:block;overflow-x:auto}code.hljs{padding:3px 5px}.hljs{color:#c9d1d9;background:#0d1117}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#ff7b72}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#d2a8ff}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-variable,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id{color:#79c0ff}.hljs-regexp,.hljs-string,.hljs-meta .hljs-string{color:#a5d6ff}.hljs-built_in,.hljs-symbol{color:#ffa657}.hljs-comment,.hljs-code,.hljs-formula{color:#8b949e}.hljs-name,.hljs-quote,.hljs-selector-tag,.hljs-selector-pseudo{color:#7ee787}.hljs-subst{color:#c9d1d9}.hljs-section{color:#1f6feb;font-weight:700}.hljs-bullet{color:#f2cc60}.hljs-emphasis{color:#c9d1d9;font-style:italic}.hljs-strong{color:#c9d1d9;font-weight:700}.hljs-addition{color:#aff5b4;background-color:#033a16}.hljs-deletion{color:#ffdcd7;background-color:#67060c}}:host,:root{--d2h-bg-color:#fff;--d2h-border-color:#ddd;--d2h-dim-color:#0000004d;--d2h-line-border-color:#eee;--d2h-file-header-bg-color:#f7f7f7;--d2h-file-header-border-color:#d8d8d8;--d2h-empty-placeholder-bg-color:#f1f1f1;--d2h-empty-placeholder-border-color:#e1e1e1;--d2h-selected-color:#c8e1ff;--d2h-ins-bg-color:#dfd;--d2h-ins-border-color:#b4e2b4;--d2h-ins-highlight-bg-color:#97f295;--d2h-ins-label-color:#399839;--d2h-del-bg-color:#fee8e9;--d2h-del-border-color:#e9aeae;--d2h-del-highlight-bg-color:#ffb6ba;--d2h-del-label-color:#c33;--d2h-change-del-color:#fdf2d0;--d2h-change-ins-color:#ded;--d2h-info-bg-color:#f8fafd;--d2h-info-border-color:#d5e4f2;--d2h-change-label-color:#d0b44c;--d2h-moved-label-color:#3572b0;--d2h-dark-color:#e6edf3;--d2h-dark-bg-color:#0d1117;--d2h-dark-border-color:#30363d;--d2h-dark-dim-color:#6e7681;--d2h-dark-line-border-color:#21262d;--d2h-dark-file-header-bg-color:#161b22;--d2h-dark-file-header-border-color:#30363d;--d2h-dark-empty-placeholder-bg-color:#6e76811a;--d2h-dark-empty-placeholder-border-color:#30363d;--d2h-dark-selected-color:#388bfd1a;--d2h-dark-ins-bg-color:#2ea04326;--d2h-dark-ins-border-color:#2ea04366;--d2h-dark-ins-highlight-bg-color:#2ea04366;--d2h-dark-ins-label-color:#3fb950;--d2h-dark-del-bg-color:#f851491a;--d2h-dark-del-border-color:#f8514966;--d2h-dark-del-highlight-bg-color:#f8514966;--d2h-dark-del-label-color:#f85149;--d2h-dark-change-del-color:#d2992233;--d2h-dark-change-ins-color:#2ea04340;--d2h-dark-info-bg-color:#388bfd1a;--d2h-dark-info-border-color:#388bfd66;--d2h-dark-change-label-color:#d29922;--d2h-dark-moved-label-color:#3572b0}.d2h-wrapper{text-align:left}.d2h-file-header{background-color:#f7f7f7;background-color:var(--d2h-file-header-bg-color);border-bottom:1px solid #d8d8d8;border-bottom:1px solid var(--d2h-file-header-border-color);height:35px;padding:5px 10px;font-family:Source Sans Pro,Helvetica Neue,Helvetica,Arial,sans-serif;display:flex}.d2h-file-header.d2h-sticky-header{z-index:1;position:sticky;top:0}.d2h-file-stats{margin-left:auto;font-size:14px;display:flex}.d2h-lines-added{border:1px solid #b4e2b4;border:1px solid var(--d2h-ins-border-color);color:var(--d2h-ins-label-color);text-align:right;vertical-align:middle;border-radius:5px 0 0 5px;padding:2px}.d2h-lines-deleted{border:1px solid #e9aeae;border:1px solid var(--d2h-del-border-color);color:var(--d2h-del-label-color);text-align:left;vertical-align:middle;border-radius:0 5px 5px 0;margin-left:1px;padding:2px}.d2h-file-name-wrapper{align-items:center;width:100%;font-size:15px;display:flex}.d2h-file-name{text-overflow:ellipsis;white-space:nowrap;overflow-x:hidden}.d2h-file-wrapper{border:1px solid #ddd;border:1px solid var(--d2h-border-color);border-radius:3px;margin-bottom:1em}.d2h-file-collapse{cursor:pointer;border:1px solid #ddd;border:1px solid var(--d2h-border-color);border-radius:3px;justify-content:flex-end;align-items:center;padding:4px 8px;font-size:12px;display:none}.d2h-file-collapse.d2h-selected{background-color:#c8e1ff;background-color:var(--d2h-selected-color)}.d2h-file-collapse-input{margin:0 4px 0 0}.d2h-diff-table{border-collapse:collapse;width:100%;font-family:Menlo,Consolas,monospace;font-size:13px}.d2h-files-diff{width:100%;display:flex}.d2h-file-diff{overflow-y:hidden}.d2h-file-diff.d2h-d-none,.d2h-files-diff.d2h-d-none{display:none}.d2h-file-side-diff{width:50%;display:inline-block;overflow:scroll hidden}.d2h-code-line{width:calc(100% - 16em);padding:0 8em}.d2h-code-line,.d2h-code-side-line{-webkit-user-select:none;user-select:none;white-space:nowrap;display:inline-block}.d2h-code-side-line{width:calc(100% - 9em);padding:0 4.5em}.d2h-code-line-ctn{word-wrap:normal;-webkit-user-select:text;user-select:text;vertical-align:middle;white-space:pre;background:0 0;width:100%;padding:0;display:inline-block}.d2h-code-line del,.d2h-code-side-line del{background-color:#ffb6ba;background-color:var(--d2h-del-highlight-bg-color)}.d2h-code-line del,.d2h-code-line ins,.d2h-code-side-line del,.d2h-code-side-line ins{border-radius:.2em;margin-top:-1px;-webkit-text-decoration:none;text-decoration:none;display:inline-block}.d2h-code-line ins,.d2h-code-side-line ins{background-color:#97f295;background-color:var(--d2h-ins-highlight-bg-color);text-align:left}.d2h-code-line-prefix{word-wrap:normal;white-space:pre;background:0 0;padding:0;display:inline}.line-num1{float:left}.line-num1,.line-num2{box-sizing:border-box;text-overflow:ellipsis;width:3.5em;padding:0 .5em;overflow:hidden}.line-num2{float:right}.d2h-code-linenumber{background-color:#fff;background-color:var(--d2h-bg-color);border:solid #eee;border:solid var(--d2h-line-border-color);box-sizing:border-box;color:var(--d2h-dim-color);cursor:pointer;text-align:right;border-width:0 1px;width:7.5em;display:inline-block;position:absolute}.d2h-code-linenumber:after{content:"​"}.d2h-code-side-linenumber{background-color:#fff;background-color:var(--d2h-bg-color);border:solid #eee;border:solid var(--d2h-line-border-color);box-sizing:border-box;color:var(--d2h-dim-color);cursor:pointer;text-align:right;text-overflow:ellipsis;border-width:0 1px;width:4em;padding:0 .5em;display:inline-block;position:absolute;overflow:hidden}.d2h-code-side-linenumber:after{content:"​"}.d2h-code-side-emptyplaceholder,.d2h-emptyplaceholder{background-color:#f1f1f1;background-color:var(--d2h-empty-placeholder-bg-color);border-color:#e1e1e1;border-color:var(--d2h-empty-placeholder-border-color)}.d2h-code-line-prefix,.d2h-code-linenumber,.d2h-code-side-linenumber,.d2h-emptyplaceholder{-webkit-user-select:none;user-select:none}.d2h-code-linenumber,.d2h-code-side-linenumber{direction:rtl}.d2h-del{background-color:#fee8e9;background-color:var(--d2h-del-bg-color);border-color:#e9aeae;border-color:var(--d2h-del-border-color)}.d2h-ins{background-color:#dfd;background-color:var(--d2h-ins-bg-color);border-color:#b4e2b4;border-color:var(--d2h-ins-border-color)}.d2h-info{background-color:#f8fafd;background-color:var(--d2h-info-bg-color);border-color:#d5e4f2;border-color:var(--d2h-info-border-color);color:var(--d2h-dim-color)}.d2h-file-diff .d2h-del.d2h-change{background-color:#fdf2d0;background-color:var(--d2h-change-del-color)}.d2h-file-diff .d2h-ins.d2h-change{background-color:#ded;background-color:var(--d2h-change-ins-color)}.d2h-file-list-wrapper{margin-bottom:10px}.d2h-file-list-wrapper a{-webkit-text-decoration:none;text-decoration:none}.d2h-file-list-wrapper a,.d2h-file-list-wrapper a:visited{color:var(--d2h-moved-label-color)}.d2h-file-list-header{text-align:left}.d2h-file-list-title{font-weight:700}.d2h-file-list-line{text-align:left;display:flex}.d2h-file-list{margin:0;padding:0;list-style:none;display:block}.d2h-file-list>li{border-bottom:1px solid #ddd;border-bottom:1px solid var(--d2h-border-color);margin:0;padding:5px 10px}.d2h-file-list>li:last-child{border-bottom:none}.d2h-file-switch{cursor:pointer;font-size:10px;display:none}.d2h-icon{fill:currentColor;vertical-align:middle;margin-right:10px}.d2h-deleted{color:var(--d2h-del-label-color)}.d2h-added{color:var(--d2h-ins-label-color)}.d2h-changed{color:var(--d2h-change-label-color)}.d2h-moved{color:var(--d2h-moved-label-color)}.d2h-tag{background-color:#fff;background-color:var(--d2h-bg-color);margin-left:5px;padding:0 2px;font-size:10px;display:flex}.d2h-deleted-tag{border:1px solid #c33;border:1px solid var(--d2h-del-label-color)}.d2h-added-tag{border:1px solid #399839;border:1px solid var(--d2h-ins-label-color)}.d2h-changed-tag{border:1px solid #d0b44c;border:1px solid var(--d2h-change-label-color)}.d2h-moved-tag{border:1px solid #3572b0;border:1px solid var(--d2h-moved-label-color)}.d2h-dark-color-scheme{background-color:#0d1117;background-color:var(--d2h-dark-bg-color);color:var(--d2h-dark-color)}.d2h-dark-color-scheme .d2h-file-header{background-color:#161b22;background-color:var(--d2h-dark-file-header-bg-color);border-bottom:#30363d;border-bottom:var(--d2h-dark-file-header-border-color)}.d2h-dark-color-scheme .d2h-lines-added{border:1px solid #2ea04366;border:1px solid var(--d2h-dark-ins-border-color);color:var(--d2h-dark-ins-label-color)}.d2h-dark-color-scheme .d2h-lines-deleted{border:1px solid #f8514966;border:1px solid var(--d2h-dark-del-border-color);color:var(--d2h-dark-del-label-color)}.d2h-dark-color-scheme .d2h-code-line del,.d2h-dark-color-scheme .d2h-code-side-line del{background-color:#f8514966;background-color:var(--d2h-dark-del-highlight-bg-color)}.d2h-dark-color-scheme .d2h-code-line ins,.d2h-dark-color-scheme .d2h-code-side-line ins{background-color:#2ea04366;background-color:var(--d2h-dark-ins-highlight-bg-color)}.d2h-dark-color-scheme .d2h-diff-tbody{border-color:#30363d;border-color:var(--d2h-dark-border-color)}.d2h-dark-color-scheme .d2h-code-side-linenumber{background-color:#0d1117;background-color:var(--d2h-dark-bg-color);border-color:#21262d;border-color:var(--d2h-dark-line-border-color);color:var(--d2h-dark-dim-color)}.d2h-dark-color-scheme .d2h-files-diff .d2h-code-side-emptyplaceholder,.d2h-dark-color-scheme .d2h-files-diff .d2h-emptyplaceholder{background-color:#6e76811a;background-color:var(--d2h-dark-empty-placeholder-bg-color);border-color:#30363d;border-color:var(--d2h-dark-empty-placeholder-border-color)}.d2h-dark-color-scheme .d2h-code-linenumber{background-color:#0d1117;background-color:var(--d2h-dark-bg-color);border-color:#21262d;border-color:var(--d2h-dark-line-border-color);color:var(--d2h-dark-dim-color)}.d2h-dark-color-scheme .d2h-del{background-color:#f851491a;background-color:var(--d2h-dark-del-bg-color);border-color:#f8514966;border-color:var(--d2h-dark-del-border-color)}.d2h-dark-color-scheme .d2h-ins{background-color:#2ea04326;background-color:var(--d2h-dark-ins-bg-color);border-color:#2ea04366;border-color:var(--d2h-dark-ins-border-color)}.d2h-dark-color-scheme .d2h-info{background-color:#388bfd1a;background-color:var(--d2h-dark-info-bg-color);border-color:#388bfd66;border-color:var(--d2h-dark-info-border-color);color:var(--d2h-dark-dim-color)}.d2h-dark-color-scheme .d2h-file-diff .d2h-del.d2h-change{background-color:#d2992233;background-color:var(--d2h-dark-change-del-color)}.d2h-dark-color-scheme .d2h-file-diff .d2h-ins.d2h-change{background-color:#2ea04340;background-color:var(--d2h-dark-change-ins-color)}.d2h-dark-color-scheme .d2h-file-wrapper{border:1px solid #30363d;border:1px solid var(--d2h-dark-border-color)}.d2h-dark-color-scheme .d2h-file-collapse{border:1px solid #0d1117;border:1px solid var(--d2h-dark-bg-color)}.d2h-dark-color-scheme .d2h-file-collapse.d2h-selected{background-color:#388bfd1a;background-color:var(--d2h-dark-selected-color)}.d2h-dark-color-scheme .d2h-file-list-wrapper a,.d2h-dark-color-scheme .d2h-file-list-wrapper a:visited{color:var(--d2h-dark-moved-label-color)}.d2h-dark-color-scheme .d2h-file-list>li{border-bottom:1px solid #0d1117;border-bottom:1px solid var(--d2h-dark-bg-color)}.d2h-dark-color-scheme .d2h-deleted{color:var(--d2h-dark-del-label-color)}.d2h-dark-color-scheme .d2h-added{color:var(--d2h-dark-ins-label-color)}.d2h-dark-color-scheme .d2h-changed{color:var(--d2h-dark-change-label-color)}.d2h-dark-color-scheme .d2h-moved{color:var(--d2h-dark-moved-label-color)}.d2h-dark-color-scheme .d2h-tag{background-color:#0d1117;background-color:var(--d2h-dark-bg-color)}.d2h-dark-color-scheme .d2h-deleted-tag{border:1px solid #f85149;border:1px solid var(--d2h-dark-del-label-color)}.d2h-dark-color-scheme .d2h-added-tag{border:1px solid #3fb950;border:1px solid var(--d2h-dark-ins-label-color)}.d2h-dark-color-scheme .d2h-changed-tag{border:1px solid #d29922;border:1px solid var(--d2h-dark-change-label-color)}.d2h-dark-color-scheme .d2h-moved-tag{border:1px solid #3572b0;border:1px solid var(--d2h-dark-moved-label-color)}@media (prefers-color-scheme:dark){.d2h-auto-color-scheme{background-color:#0d1117;background-color:var(--d2h-dark-bg-color);color:var(--d2h-dark-color)}.d2h-auto-color-scheme .d2h-file-header{background-color:#161b22;background-color:var(--d2h-dark-file-header-bg-color);border-bottom:#30363d;border-bottom:var(--d2h-dark-file-header-border-color)}.d2h-auto-color-scheme .d2h-lines-added{border:1px solid #2ea04366;border:1px solid var(--d2h-dark-ins-border-color);color:var(--d2h-dark-ins-label-color)}.d2h-auto-color-scheme .d2h-lines-deleted{border:1px solid #f8514966;border:1px solid var(--d2h-dark-del-border-color);color:var(--d2h-dark-del-label-color)}.d2h-auto-color-scheme .d2h-code-line del,.d2h-auto-color-scheme .d2h-code-side-line del{background-color:#f8514966;background-color:var(--d2h-dark-del-highlight-bg-color)}.d2h-auto-color-scheme .d2h-code-line ins,.d2h-auto-color-scheme .d2h-code-side-line ins{background-color:#2ea04366;background-color:var(--d2h-dark-ins-highlight-bg-color)}.d2h-auto-color-scheme .d2h-diff-tbody{border-color:#30363d;border-color:var(--d2h-dark-border-color)}.d2h-auto-color-scheme .d2h-code-side-linenumber{background-color:#0d1117;background-color:var(--d2h-dark-bg-color);border-color:#21262d;border-color:var(--d2h-dark-line-border-color);color:var(--d2h-dark-dim-color)}.d2h-auto-color-scheme .d2h-files-diff .d2h-code-side-emptyplaceholder,.d2h-auto-color-scheme .d2h-files-diff .d2h-emptyplaceholder{background-color:#6e76811a;background-color:var(--d2h-dark-empty-placeholder-bg-color);border-color:#30363d;border-color:var(--d2h-dark-empty-placeholder-border-color)}.d2h-auto-color-scheme .d2h-code-linenumber{background-color:#0d1117;background-color:var(--d2h-dark-bg-color);border-color:#21262d;border-color:var(--d2h-dark-line-border-color);color:var(--d2h-dark-dim-color)}.d2h-auto-color-scheme .d2h-del{background-color:#f851491a;background-color:var(--d2h-dark-del-bg-color);border-color:#f8514966;border-color:var(--d2h-dark-del-border-color)}.d2h-auto-color-scheme .d2h-ins{background-color:#2ea04326;background-color:var(--d2h-dark-ins-bg-color);border-color:#2ea04366;border-color:var(--d2h-dark-ins-border-color)}.d2h-auto-color-scheme .d2h-info{background-color:#388bfd1a;background-color:var(--d2h-dark-info-bg-color);border-color:#388bfd66;border-color:var(--d2h-dark-info-border-color);color:var(--d2h-dark-dim-color)}.d2h-auto-color-scheme .d2h-file-diff .d2h-del.d2h-change{background-color:#d2992233;background-color:var(--d2h-dark-change-del-color)}.d2h-auto-color-scheme .d2h-file-diff .d2h-ins.d2h-change{background-color:#2ea04340;background-color:var(--d2h-dark-change-ins-color)}.d2h-auto-color-scheme .d2h-file-wrapper{border:1px solid #30363d;border:1px solid var(--d2h-dark-border-color)}.d2h-auto-color-scheme .d2h-file-collapse{border:1px solid #0d1117;border:1px solid var(--d2h-dark-bg-color)}.d2h-auto-color-scheme .d2h-file-collapse.d2h-selected{background-color:#388bfd1a;background-color:var(--d2h-dark-selected-color)}.d2h-auto-color-scheme .d2h-file-list-wrapper a,.d2h-auto-color-scheme .d2h-file-list-wrapper a:visited{color:var(--d2h-dark-moved-label-color)}.d2h-auto-color-scheme .d2h-file-list>li{border-bottom:1px solid #0d1117;border-bottom:1px solid var(--d2h-dark-bg-color)}.d2h-dark-color-scheme .d2h-deleted{color:var(--d2h-dark-del-label-color)}.d2h-auto-color-scheme .d2h-added{color:var(--d2h-dark-ins-label-color)}.d2h-auto-color-scheme .d2h-changed{color:var(--d2h-dark-change-label-color)}.d2h-auto-color-scheme .d2h-moved{color:var(--d2h-dark-moved-label-color)}.d2h-auto-color-scheme .d2h-tag{background-color:#0d1117;background-color:var(--d2h-dark-bg-color)}.d2h-auto-color-scheme .d2h-deleted-tag{border:1px solid #f85149;border:1px solid var(--d2h-dark-del-label-color)}.d2h-auto-color-scheme .d2h-added-tag{border:1px solid #3fb950;border:1px solid var(--d2h-dark-ins-label-color)}.d2h-auto-color-scheme .d2h-changed-tag{border:1px solid #d29922;border:1px solid var(--d2h-dark-change-label-color)}.d2h-auto-color-scheme .d2h-moved-tag{border:1px solid #3572b0;border:1px solid var(--d2h-dark-moved-label-color)}}:root{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light dark}@media (prefers-color-scheme:dark){:root{--lightningcss-light: ;--lightningcss-dark:initial;--color-editor-background:#1f1f1f;--color-editor-foreground:#ccc;--color-side-bar-background:#181818;--color-side-bar-section-header-background:#202020;--color-title-bar-background:#181818;--color-panel-border:#2b2b2b;--color-description-foreground:#9d9d9d;--color-focus-border:#0078d4;--color-text-link-foreground:#4daafc;--color-list-hover-background:#2a2d2e;--color-list-active-selection-background:#04395e;--color-list-active-selection-foreground:#fff;--color-warning-background:#352a05;--color-git-modified:#e2c08d;--color-git-deleted:#c74e39;--color-git-added:#81b88b;--color-git-untracked:#73c991;--color-git-conflicting:#e4676b;--color-diff-diagonal-fill:#ffffff0f}}:root{--gg-d2h-map:1;--d2h-bg-color:var(--color-editor-background);--d2h-border-color:var(--color-panel-border);--d2h-dim-color:var(--color-description-foreground);--d2h-line-border-color:var(--color-panel-border);--d2h-file-header-bg-color:var(--color-side-bar-section-header-background);--d2h-file-header-border-color:var(--color-panel-border);--d2h-info-bg-color:var(--color-side-bar-background);--d2h-info-border-color:var(--color-panel-border);--d2h-empty-placeholder-bg-color:var(--color-diff-diagonal-fill);--d2h-empty-placeholder-border-color:var(--color-panel-border);--d2h-selected-color:var(--color-list-active-selection-background);--d2h-ins-bg-color:var(--color-diff-inserted-background);--d2h-ins-highlight-bg-color:var(--color-diff-inserted-text-background);--d2h-ins-border-color:var(--color-diff-inserted-border);--d2h-ins-label-color:var(--color-git-added);--d2h-del-bg-color:var(--color-diff-removed-background);--d2h-del-highlight-bg-color:var(--color-diff-removed-text-background);--d2h-del-border-color:var(--color-diff-removed-border);--d2h-del-label-color:var(--color-git-deleted);--d2h-change-del-color:var(--color-diff-removed-background);--d2h-change-ins-color:var(--color-diff-inserted-background);--d2h-change-label-color:var(--color-git-modified);--d2h-moved-label-color:var(--color-text-link-foreground)}body{background-color:var(--color-editor-background);color:var(--color-editor-foreground)}.d2h-diff-table{font-family:var(--font-mono)}.d2h-file-header{font-family:var(--font-sans)}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}
2
+ @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{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-font-weight:initial;--tw-outline-style:solid}::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-font-weight:initial;--tw-outline-style:solid}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, -apple-system, "Segoe UI", "Noto Sans", "PingFang SC", "Microsoft YaHei", sans-serif;--font-mono:ui-monospace, "SF Mono", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-medium:500;--radius-sm:.25rem;--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-editor-background:#fff;--color-editor-foreground:#3b3b3b;--color-side-bar-background:#f8f8f8;--color-side-bar-section-header-background:#f0f0f0;--color-title-bar-background:#f8f8f8;--color-panel-border:#e5e5e5;--color-description-foreground:#6f6f6f;--color-focus-border:#005fb8;--color-text-link-foreground:#005fb8;--color-list-hover-background:#e8e8e8;--color-list-active-selection-background:#e4e6f1;--color-list-active-selection-foreground:#000;--color-warning-background:#fdf6d3;--color-warning-border:#b89500;--color-git-modified:#895503;--color-git-deleted:#ad0707;--color-git-added:#587c0c;--color-git-untracked:#007100;--color-git-conflicting:#ad0707;--color-diff-inserted-background:#9bb95533;--color-diff-inserted-text-background:#9bb95573;--color-diff-inserted-border:#9bb95580;--color-diff-removed-background:#ff000029;--color-diff-removed-text-background:#ff000052;--color-diff-removed-border:#ff000059;--color-diff-diagonal-fill:#0000000f}}@layer base{*,:after,:before{box-sizing:border-box;border:0 solid;margin:0;padding:0}::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;-webkit-text-decoration:inherit;-webkit-text-decoration: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}}@layer components;@layer utilities{.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.top-0{top:0}.ml-1{margin-left:var(--spacing)}.ml-2{margin-left:calc(var(--spacing) * 2)}.contents{display:contents}.flex{display:flex}.h-screen{height:100vh}.min-h-0{min-height:0}.w-5{width:calc(var(--spacing) * 5)}.w-80{width:calc(var(--spacing) * 80)}.w-full{width:100%}.max-w-60{max-width:calc(var(--spacing) * 60)}.min-w-0{min-width:0}.flex-1{flex:1}.shrink-0{flex-shrink:0}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.flex-col{flex-direction:column}.items-baseline{align-items:baseline}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.rounded-sm{border-radius:var(--radius-sm)}.border{border-style:var(--tw-border-style);border-width:1px}.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-panel-border{border-color:var(--color-panel-border)}.border-warning-border{border-color:var(--color-warning-border)}.bg-editor-background{background-color:var(--color-editor-background)}.bg-list-active-selection-background{background-color:var(--color-list-active-selection-background)}.bg-side-bar-background{background-color:var(--color-side-bar-background)}.bg-side-bar-section-header-background{background-color:var(--color-side-bar-section-header-background)}.bg-title-bar-background{background-color:var(--color-title-bar-background)}.bg-warning-background{background-color:var(--color-warning-background)}.p-4{padding:calc(var(--spacing) * 4)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.py-2{padding-block:calc(var(--spacing) * 2)}.text-center{text-align:center}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.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))}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.break-all{word-break:break-all}.text-description-foreground{color:var(--color-description-foreground)}.text-editor-foreground{color:var(--color-editor-foreground)}.text-git-added{color:var(--color-git-added)}.text-git-conflicting{color:var(--color-git-conflicting)}.text-git-deleted{color:var(--color-git-deleted)}.text-git-modified{color:var(--color-git-modified)}.text-git-untracked{color:var(--color-git-untracked)}.text-list-active-selection-foreground{color:var(--color-list-active-selection-foreground)}@media (hover:hover){.hover\:bg-list-hover-background:hover{background-color:var(--color-list-hover-background)}}.focus-visible\:outline-2:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px}.focus-visible\:-outline-offset-2:focus-visible{outline-offset:calc(2px * -1)}.focus-visible\:outline-focus-border:focus-visible{outline-color:var(--color-focus-border)}}pre code.hljs{padding:1em;display:block;overflow-x:auto}code.hljs{padding:3px 5px}.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}@media (prefers-color-scheme:dark){pre code.hljs{padding:1em;display:block;overflow-x:auto}code.hljs{padding:3px 5px}.hljs{color:#c9d1d9;background:#0d1117}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#ff7b72}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#d2a8ff}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-variable,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id{color:#79c0ff}.hljs-regexp,.hljs-string,.hljs-meta .hljs-string{color:#a5d6ff}.hljs-built_in,.hljs-symbol{color:#ffa657}.hljs-comment,.hljs-code,.hljs-formula{color:#8b949e}.hljs-name,.hljs-quote,.hljs-selector-tag,.hljs-selector-pseudo{color:#7ee787}.hljs-subst{color:#c9d1d9}.hljs-section{color:#1f6feb;font-weight:700}.hljs-bullet{color:#f2cc60}.hljs-emphasis{color:#c9d1d9;font-style:italic}.hljs-strong{color:#c9d1d9;font-weight:700}.hljs-addition{color:#aff5b4;background-color:#033a16}.hljs-deletion{color:#ffdcd7;background-color:#67060c}}:host,:root{--d2h-bg-color:#fff;--d2h-border-color:#ddd;--d2h-dim-color:#0000004d;--d2h-line-border-color:#eee;--d2h-file-header-bg-color:#f7f7f7;--d2h-file-header-border-color:#d8d8d8;--d2h-empty-placeholder-bg-color:#f1f1f1;--d2h-empty-placeholder-border-color:#e1e1e1;--d2h-selected-color:#c8e1ff;--d2h-ins-bg-color:#dfd;--d2h-ins-border-color:#b4e2b4;--d2h-ins-highlight-bg-color:#97f295;--d2h-ins-label-color:#399839;--d2h-del-bg-color:#fee8e9;--d2h-del-border-color:#e9aeae;--d2h-del-highlight-bg-color:#ffb6ba;--d2h-del-label-color:#c33;--d2h-change-del-color:#fdf2d0;--d2h-change-ins-color:#ded;--d2h-info-bg-color:#f8fafd;--d2h-info-border-color:#d5e4f2;--d2h-change-label-color:#d0b44c;--d2h-moved-label-color:#3572b0;--d2h-dark-color:#e6edf3;--d2h-dark-bg-color:#0d1117;--d2h-dark-border-color:#30363d;--d2h-dark-dim-color:#6e7681;--d2h-dark-line-border-color:#21262d;--d2h-dark-file-header-bg-color:#161b22;--d2h-dark-file-header-border-color:#30363d;--d2h-dark-empty-placeholder-bg-color:#6e76811a;--d2h-dark-empty-placeholder-border-color:#30363d;--d2h-dark-selected-color:#388bfd1a;--d2h-dark-ins-bg-color:#2ea04326;--d2h-dark-ins-border-color:#2ea04366;--d2h-dark-ins-highlight-bg-color:#2ea04366;--d2h-dark-ins-label-color:#3fb950;--d2h-dark-del-bg-color:#f851491a;--d2h-dark-del-border-color:#f8514966;--d2h-dark-del-highlight-bg-color:#f8514966;--d2h-dark-del-label-color:#f85149;--d2h-dark-change-del-color:#d2992233;--d2h-dark-change-ins-color:#2ea04340;--d2h-dark-info-bg-color:#388bfd1a;--d2h-dark-info-border-color:#388bfd66;--d2h-dark-change-label-color:#d29922;--d2h-dark-moved-label-color:#3572b0}.d2h-wrapper{text-align:left}.d2h-file-header{background-color:#f7f7f7;background-color:var(--d2h-file-header-bg-color);border-bottom:1px solid #d8d8d8;border-bottom:1px solid var(--d2h-file-header-border-color);height:35px;padding:5px 10px;font-family:Source Sans Pro,Helvetica Neue,Helvetica,Arial,sans-serif;display:flex}.d2h-file-header.d2h-sticky-header{z-index:1;position:sticky;top:0}.d2h-file-stats{margin-left:auto;font-size:14px;display:flex}.d2h-lines-added{border:1px solid #b4e2b4;border:1px solid var(--d2h-ins-border-color);color:var(--d2h-ins-label-color);text-align:right;vertical-align:middle;border-radius:5px 0 0 5px;padding:2px}.d2h-lines-deleted{border:1px solid #e9aeae;border:1px solid var(--d2h-del-border-color);color:var(--d2h-del-label-color);text-align:left;vertical-align:middle;border-radius:0 5px 5px 0;margin-left:1px;padding:2px}.d2h-file-name-wrapper{align-items:center;width:100%;font-size:15px;display:flex}.d2h-file-name{text-overflow:ellipsis;white-space:nowrap;overflow-x:hidden}.d2h-file-wrapper{border:1px solid #ddd;border:1px solid var(--d2h-border-color);border-radius:3px;margin-bottom:1em}.d2h-file-collapse{cursor:pointer;border:1px solid #ddd;border:1px solid var(--d2h-border-color);border-radius:3px;justify-content:flex-end;align-items:center;padding:4px 8px;font-size:12px;display:none}.d2h-file-collapse.d2h-selected{background-color:#c8e1ff;background-color:var(--d2h-selected-color)}.d2h-file-collapse-input{margin:0 4px 0 0}.d2h-diff-table{border-collapse:collapse;width:100%;font-family:Menlo,Consolas,monospace;font-size:13px}.d2h-files-diff{width:100%;display:flex}.d2h-file-diff{overflow-y:hidden}.d2h-file-diff.d2h-d-none,.d2h-files-diff.d2h-d-none{display:none}.d2h-file-side-diff{width:50%;display:inline-block;overflow:scroll hidden}.d2h-code-line{width:calc(100% - 16em);padding:0 8em}.d2h-code-line,.d2h-code-side-line{-webkit-user-select:none;user-select:none;white-space:nowrap;display:inline-block}.d2h-code-side-line{width:calc(100% - 9em);padding:0 4.5em}.d2h-code-line-ctn{word-wrap:normal;-webkit-user-select:text;user-select:text;vertical-align:middle;white-space:pre;background:0 0;width:100%;padding:0;display:inline-block}.d2h-code-line del,.d2h-code-side-line del{background-color:#ffb6ba;background-color:var(--d2h-del-highlight-bg-color)}.d2h-code-line del,.d2h-code-line ins,.d2h-code-side-line del,.d2h-code-side-line ins{border-radius:.2em;margin-top:-1px;-webkit-text-decoration:none;text-decoration:none;display:inline-block}.d2h-code-line ins,.d2h-code-side-line ins{background-color:#97f295;background-color:var(--d2h-ins-highlight-bg-color);text-align:left}.d2h-code-line-prefix{word-wrap:normal;white-space:pre;background:0 0;padding:0;display:inline}.line-num1{float:left}.line-num1,.line-num2{box-sizing:border-box;text-overflow:ellipsis;width:3.5em;padding:0 .5em;overflow:hidden}.line-num2{float:right}.d2h-code-linenumber{background-color:#fff;background-color:var(--d2h-bg-color);border:solid #eee;border:solid var(--d2h-line-border-color);box-sizing:border-box;color:var(--d2h-dim-color);cursor:pointer;text-align:right;border-width:0 1px;width:7.5em;display:inline-block;position:absolute}.d2h-code-linenumber:after{content:"​"}.d2h-code-side-linenumber{background-color:#fff;background-color:var(--d2h-bg-color);border:solid #eee;border:solid var(--d2h-line-border-color);box-sizing:border-box;color:var(--d2h-dim-color);cursor:pointer;text-align:right;text-overflow:ellipsis;border-width:0 1px;width:4em;padding:0 .5em;display:inline-block;position:absolute;overflow:hidden}.d2h-code-side-linenumber:after{content:"​"}.d2h-code-side-emptyplaceholder,.d2h-emptyplaceholder{background-color:#f1f1f1;background-color:var(--d2h-empty-placeholder-bg-color);border-color:#e1e1e1;border-color:var(--d2h-empty-placeholder-border-color)}.d2h-code-line-prefix,.d2h-code-linenumber,.d2h-code-side-linenumber,.d2h-emptyplaceholder{-webkit-user-select:none;user-select:none}.d2h-code-linenumber,.d2h-code-side-linenumber{direction:rtl}.d2h-del{background-color:#fee8e9;background-color:var(--d2h-del-bg-color);border-color:#e9aeae;border-color:var(--d2h-del-border-color)}.d2h-ins{background-color:#dfd;background-color:var(--d2h-ins-bg-color);border-color:#b4e2b4;border-color:var(--d2h-ins-border-color)}.d2h-info{background-color:#f8fafd;background-color:var(--d2h-info-bg-color);border-color:#d5e4f2;border-color:var(--d2h-info-border-color);color:var(--d2h-dim-color)}.d2h-file-diff .d2h-del.d2h-change{background-color:#fdf2d0;background-color:var(--d2h-change-del-color)}.d2h-file-diff .d2h-ins.d2h-change{background-color:#ded;background-color:var(--d2h-change-ins-color)}.d2h-file-list-wrapper{margin-bottom:10px}.d2h-file-list-wrapper a{-webkit-text-decoration:none;text-decoration:none}.d2h-file-list-wrapper a,.d2h-file-list-wrapper a:visited{color:var(--d2h-moved-label-color)}.d2h-file-list-header{text-align:left}.d2h-file-list-title{font-weight:700}.d2h-file-list-line{text-align:left;display:flex}.d2h-file-list{margin:0;padding:0;list-style:none;display:block}.d2h-file-list>li{border-bottom:1px solid #ddd;border-bottom:1px solid var(--d2h-border-color);margin:0;padding:5px 10px}.d2h-file-list>li:last-child{border-bottom:none}.d2h-file-switch{cursor:pointer;font-size:10px;display:none}.d2h-icon{fill:currentColor;vertical-align:middle;margin-right:10px}.d2h-deleted{color:var(--d2h-del-label-color)}.d2h-added{color:var(--d2h-ins-label-color)}.d2h-changed{color:var(--d2h-change-label-color)}.d2h-moved{color:var(--d2h-moved-label-color)}.d2h-tag{background-color:#fff;background-color:var(--d2h-bg-color);margin-left:5px;padding:0 2px;font-size:10px;display:flex}.d2h-deleted-tag{border:1px solid #c33;border:1px solid var(--d2h-del-label-color)}.d2h-added-tag{border:1px solid #399839;border:1px solid var(--d2h-ins-label-color)}.d2h-changed-tag{border:1px solid #d0b44c;border:1px solid var(--d2h-change-label-color)}.d2h-moved-tag{border:1px solid #3572b0;border:1px solid var(--d2h-moved-label-color)}.d2h-dark-color-scheme{background-color:#0d1117;background-color:var(--d2h-dark-bg-color);color:var(--d2h-dark-color)}.d2h-dark-color-scheme .d2h-file-header{background-color:#161b22;background-color:var(--d2h-dark-file-header-bg-color);border-bottom:#30363d;border-bottom:var(--d2h-dark-file-header-border-color)}.d2h-dark-color-scheme .d2h-lines-added{border:1px solid #2ea04366;border:1px solid var(--d2h-dark-ins-border-color);color:var(--d2h-dark-ins-label-color)}.d2h-dark-color-scheme .d2h-lines-deleted{border:1px solid #f8514966;border:1px solid var(--d2h-dark-del-border-color);color:var(--d2h-dark-del-label-color)}.d2h-dark-color-scheme .d2h-code-line del,.d2h-dark-color-scheme .d2h-code-side-line del{background-color:#f8514966;background-color:var(--d2h-dark-del-highlight-bg-color)}.d2h-dark-color-scheme .d2h-code-line ins,.d2h-dark-color-scheme .d2h-code-side-line ins{background-color:#2ea04366;background-color:var(--d2h-dark-ins-highlight-bg-color)}.d2h-dark-color-scheme .d2h-diff-tbody{border-color:#30363d;border-color:var(--d2h-dark-border-color)}.d2h-dark-color-scheme .d2h-code-side-linenumber{background-color:#0d1117;background-color:var(--d2h-dark-bg-color);border-color:#21262d;border-color:var(--d2h-dark-line-border-color);color:var(--d2h-dark-dim-color)}.d2h-dark-color-scheme .d2h-files-diff .d2h-code-side-emptyplaceholder,.d2h-dark-color-scheme .d2h-files-diff .d2h-emptyplaceholder{background-color:#6e76811a;background-color:var(--d2h-dark-empty-placeholder-bg-color);border-color:#30363d;border-color:var(--d2h-dark-empty-placeholder-border-color)}.d2h-dark-color-scheme .d2h-code-linenumber{background-color:#0d1117;background-color:var(--d2h-dark-bg-color);border-color:#21262d;border-color:var(--d2h-dark-line-border-color);color:var(--d2h-dark-dim-color)}.d2h-dark-color-scheme .d2h-del{background-color:#f851491a;background-color:var(--d2h-dark-del-bg-color);border-color:#f8514966;border-color:var(--d2h-dark-del-border-color)}.d2h-dark-color-scheme .d2h-ins{background-color:#2ea04326;background-color:var(--d2h-dark-ins-bg-color);border-color:#2ea04366;border-color:var(--d2h-dark-ins-border-color)}.d2h-dark-color-scheme .d2h-info{background-color:#388bfd1a;background-color:var(--d2h-dark-info-bg-color);border-color:#388bfd66;border-color:var(--d2h-dark-info-border-color);color:var(--d2h-dark-dim-color)}.d2h-dark-color-scheme .d2h-file-diff .d2h-del.d2h-change{background-color:#d2992233;background-color:var(--d2h-dark-change-del-color)}.d2h-dark-color-scheme .d2h-file-diff .d2h-ins.d2h-change{background-color:#2ea04340;background-color:var(--d2h-dark-change-ins-color)}.d2h-dark-color-scheme .d2h-file-wrapper{border:1px solid #30363d;border:1px solid var(--d2h-dark-border-color)}.d2h-dark-color-scheme .d2h-file-collapse{border:1px solid #0d1117;border:1px solid var(--d2h-dark-bg-color)}.d2h-dark-color-scheme .d2h-file-collapse.d2h-selected{background-color:#388bfd1a;background-color:var(--d2h-dark-selected-color)}.d2h-dark-color-scheme .d2h-file-list-wrapper a,.d2h-dark-color-scheme .d2h-file-list-wrapper a:visited{color:var(--d2h-dark-moved-label-color)}.d2h-dark-color-scheme .d2h-file-list>li{border-bottom:1px solid #0d1117;border-bottom:1px solid var(--d2h-dark-bg-color)}.d2h-dark-color-scheme .d2h-deleted{color:var(--d2h-dark-del-label-color)}.d2h-dark-color-scheme .d2h-added{color:var(--d2h-dark-ins-label-color)}.d2h-dark-color-scheme .d2h-changed{color:var(--d2h-dark-change-label-color)}.d2h-dark-color-scheme .d2h-moved{color:var(--d2h-dark-moved-label-color)}.d2h-dark-color-scheme .d2h-tag{background-color:#0d1117;background-color:var(--d2h-dark-bg-color)}.d2h-dark-color-scheme .d2h-deleted-tag{border:1px solid #f85149;border:1px solid var(--d2h-dark-del-label-color)}.d2h-dark-color-scheme .d2h-added-tag{border:1px solid #3fb950;border:1px solid var(--d2h-dark-ins-label-color)}.d2h-dark-color-scheme .d2h-changed-tag{border:1px solid #d29922;border:1px solid var(--d2h-dark-change-label-color)}.d2h-dark-color-scheme .d2h-moved-tag{border:1px solid #3572b0;border:1px solid var(--d2h-dark-moved-label-color)}@media (prefers-color-scheme:dark){.d2h-auto-color-scheme{background-color:#0d1117;background-color:var(--d2h-dark-bg-color);color:var(--d2h-dark-color)}.d2h-auto-color-scheme .d2h-file-header{background-color:#161b22;background-color:var(--d2h-dark-file-header-bg-color);border-bottom:#30363d;border-bottom:var(--d2h-dark-file-header-border-color)}.d2h-auto-color-scheme .d2h-lines-added{border:1px solid #2ea04366;border:1px solid var(--d2h-dark-ins-border-color);color:var(--d2h-dark-ins-label-color)}.d2h-auto-color-scheme .d2h-lines-deleted{border:1px solid #f8514966;border:1px solid var(--d2h-dark-del-border-color);color:var(--d2h-dark-del-label-color)}.d2h-auto-color-scheme .d2h-code-line del,.d2h-auto-color-scheme .d2h-code-side-line del{background-color:#f8514966;background-color:var(--d2h-dark-del-highlight-bg-color)}.d2h-auto-color-scheme .d2h-code-line ins,.d2h-auto-color-scheme .d2h-code-side-line ins{background-color:#2ea04366;background-color:var(--d2h-dark-ins-highlight-bg-color)}.d2h-auto-color-scheme .d2h-diff-tbody{border-color:#30363d;border-color:var(--d2h-dark-border-color)}.d2h-auto-color-scheme .d2h-code-side-linenumber{background-color:#0d1117;background-color:var(--d2h-dark-bg-color);border-color:#21262d;border-color:var(--d2h-dark-line-border-color);color:var(--d2h-dark-dim-color)}.d2h-auto-color-scheme .d2h-files-diff .d2h-code-side-emptyplaceholder,.d2h-auto-color-scheme .d2h-files-diff .d2h-emptyplaceholder{background-color:#6e76811a;background-color:var(--d2h-dark-empty-placeholder-bg-color);border-color:#30363d;border-color:var(--d2h-dark-empty-placeholder-border-color)}.d2h-auto-color-scheme .d2h-code-linenumber{background-color:#0d1117;background-color:var(--d2h-dark-bg-color);border-color:#21262d;border-color:var(--d2h-dark-line-border-color);color:var(--d2h-dark-dim-color)}.d2h-auto-color-scheme .d2h-del{background-color:#f851491a;background-color:var(--d2h-dark-del-bg-color);border-color:#f8514966;border-color:var(--d2h-dark-del-border-color)}.d2h-auto-color-scheme .d2h-ins{background-color:#2ea04326;background-color:var(--d2h-dark-ins-bg-color);border-color:#2ea04366;border-color:var(--d2h-dark-ins-border-color)}.d2h-auto-color-scheme .d2h-info{background-color:#388bfd1a;background-color:var(--d2h-dark-info-bg-color);border-color:#388bfd66;border-color:var(--d2h-dark-info-border-color);color:var(--d2h-dark-dim-color)}.d2h-auto-color-scheme .d2h-file-diff .d2h-del.d2h-change{background-color:#d2992233;background-color:var(--d2h-dark-change-del-color)}.d2h-auto-color-scheme .d2h-file-diff .d2h-ins.d2h-change{background-color:#2ea04340;background-color:var(--d2h-dark-change-ins-color)}.d2h-auto-color-scheme .d2h-file-wrapper{border:1px solid #30363d;border:1px solid var(--d2h-dark-border-color)}.d2h-auto-color-scheme .d2h-file-collapse{border:1px solid #0d1117;border:1px solid var(--d2h-dark-bg-color)}.d2h-auto-color-scheme .d2h-file-collapse.d2h-selected{background-color:#388bfd1a;background-color:var(--d2h-dark-selected-color)}.d2h-auto-color-scheme .d2h-file-list-wrapper a,.d2h-auto-color-scheme .d2h-file-list-wrapper a:visited{color:var(--d2h-dark-moved-label-color)}.d2h-auto-color-scheme .d2h-file-list>li{border-bottom:1px solid #0d1117;border-bottom:1px solid var(--d2h-dark-bg-color)}.d2h-dark-color-scheme .d2h-deleted{color:var(--d2h-dark-del-label-color)}.d2h-auto-color-scheme .d2h-added{color:var(--d2h-dark-ins-label-color)}.d2h-auto-color-scheme .d2h-changed{color:var(--d2h-dark-change-label-color)}.d2h-auto-color-scheme .d2h-moved{color:var(--d2h-dark-moved-label-color)}.d2h-auto-color-scheme .d2h-tag{background-color:#0d1117;background-color:var(--d2h-dark-bg-color)}.d2h-auto-color-scheme .d2h-deleted-tag{border:1px solid #f85149;border:1px solid var(--d2h-dark-del-label-color)}.d2h-auto-color-scheme .d2h-added-tag{border:1px solid #3fb950;border:1px solid var(--d2h-dark-ins-label-color)}.d2h-auto-color-scheme .d2h-changed-tag{border:1px solid #d29922;border:1px solid var(--d2h-dark-change-label-color)}.d2h-auto-color-scheme .d2h-moved-tag{border:1px solid #3572b0;border:1px solid var(--d2h-dark-moved-label-color)}}:root{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light dark}@media (prefers-color-scheme:dark){:root{--lightningcss-light: ;--lightningcss-dark:initial;--color-editor-background:#1f1f1f;--color-editor-foreground:#ccc;--color-side-bar-background:#181818;--color-side-bar-section-header-background:#202020;--color-title-bar-background:#181818;--color-panel-border:#2b2b2b;--color-description-foreground:#9d9d9d;--color-focus-border:#0078d4;--color-text-link-foreground:#4daafc;--color-list-hover-background:#2a2d2e;--color-list-active-selection-background:#04395e;--color-list-active-selection-foreground:#fff;--color-warning-background:#352a05;--color-git-modified:#e2c08d;--color-git-deleted:#c74e39;--color-git-added:#81b88b;--color-git-untracked:#73c991;--color-git-conflicting:#e4676b;--color-diff-diagonal-fill:#ffffff0f}}:root{--gg-d2h-map:1;--d2h-bg-color:var(--color-editor-background);--d2h-border-color:var(--color-panel-border);--d2h-dim-color:var(--color-description-foreground);--d2h-line-border-color:var(--color-panel-border);--d2h-file-header-bg-color:var(--color-side-bar-section-header-background);--d2h-file-header-border-color:var(--color-panel-border);--d2h-info-bg-color:var(--color-side-bar-background);--d2h-info-border-color:var(--color-panel-border);--d2h-empty-placeholder-bg-color:var(--color-diff-diagonal-fill);--d2h-empty-placeholder-border-color:var(--color-panel-border);--d2h-selected-color:var(--color-list-active-selection-background);--d2h-ins-bg-color:var(--color-diff-inserted-background);--d2h-ins-highlight-bg-color:var(--color-diff-inserted-text-background);--d2h-ins-border-color:var(--color-diff-inserted-border);--d2h-ins-label-color:var(--color-git-added);--d2h-del-bg-color:var(--color-diff-removed-background);--d2h-del-highlight-bg-color:var(--color-diff-removed-text-background);--d2h-del-border-color:var(--color-diff-removed-border);--d2h-del-label-color:var(--color-git-deleted);--d2h-change-del-color:var(--color-diff-removed-background);--d2h-change-ins-color:var(--color-diff-inserted-background);--d2h-change-label-color:var(--color-git-modified);--d2h-moved-label-color:var(--color-text-link-foreground)}body{background-color:var(--color-editor-background);color:var(--color-editor-foreground)}.d2h-diff-table{font-family:var(--font-mono)}.d2h-file-header{display:none}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}
3
3
  /*$vite$:1*/