pi-web-ui 0.78.0 → 0.80.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/CHANGELOG.md +34 -1
  2. package/README.md +68 -0
  3. package/package.json +15 -6
  4. package/themes/mist.css +179 -0
  5. package/themes/paper.css +179 -0
  6. package/themes/sakura.css +179 -0
  7. package/web/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  8. package/web/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  9. package/web/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  10. package/web/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  11. package/web/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  12. package/web/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  13. package/web/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  14. package/web/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  15. package/web/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  16. package/web/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  17. package/web/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  18. package/web/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  19. package/web/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  20. package/web/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  21. package/web/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  22. package/web/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  23. package/web/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  24. package/web/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  25. package/web/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  26. package/web/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  27. package/web/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  28. package/web/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  29. package/web/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  30. package/web/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  31. package/web/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  32. package/web/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  33. package/web/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  34. package/web/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  35. package/web/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  36. package/web/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  37. package/web/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  38. package/web/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  39. package/web/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  40. package/web/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  41. package/web/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  42. package/web/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  43. package/web/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  44. package/web/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  45. package/web/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  46. package/web/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  47. package/web/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  48. package/web/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  49. package/web/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  50. package/web/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  51. package/web/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  52. package/web/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  53. package/web/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  54. package/web/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  55. package/web/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  56. package/web/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  57. package/web/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  58. package/web/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  59. package/web/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  60. package/web/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  61. package/web/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  62. package/web/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  63. package/web/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  64. package/web/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  65. package/web/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  66. package/web/dist/assets/{TerminalPanel-DCQcbf-J.js → TerminalPanel-BYigWYyx.js} +1 -1
  67. package/web/dist/assets/index-D7BpHJ59.js +347 -0
  68. package/web/dist/assets/index-GKv6Qo91.css +10 -0
  69. package/web/dist/assets/markdown-D3PKeHAZ.js +311 -0
  70. package/web/dist/assets/{react-CtudoG1_.js → react-w24rH0km.js} +1 -1
  71. package/web/dist/index.html +4 -4
  72. package/web/dist/assets/index-CaC1cuAF.css +0 -10
  73. package/web/dist/assets/index-SREmjZgY.js +0 -346
  74. package/web/dist/assets/markdown-Cpo0pNcR.js +0 -51
package/CHANGELOG.md CHANGED
@@ -12,6 +12,37 @@
12
12
 
13
13
  暂无未发布内容。
14
14
 
15
+ ## [0.80.0] — 2026-09-12
16
+
17
+ ### Added
18
+
19
+ - **桌面版(Electron 外壳)**:同一套服务端 + 前端装进一个原生窗口——主进程用随机空闲口起 `dist/server/index.js`(`ELECTRON_RUN_AS_NODE` 当纯 Node 用,不再额外捆一个 Node),`/api/health` 就绪后 `BrowserWindow` 直接加载该地址,因此前端 `appUrl("/ws")`、`server/protocol.ts` 全部零改动。可与网页版并存:不抢 `8787`(`PI_WEB_PORT` 被占用时自动退到随机空闲口)、独立数据目录(`<userData>/data`)、独立单实例锁;外链丢给系统浏览器,renderer 走 `contextIsolation + sandbox` 且无 Node。Windows 安装包(NSIS,可选安装目录)随每个 Release 由 CI 出包并附在 Release 页面(macOS dmg / Linux AppImage 已配好,CI 暂只出 Windows);开发用 `npm run desktop:dev`,本地打包用 `npm run desktop:dist`。
20
+ - 当前**未签名**:首次运行 Windows 会提示「未知发布者」(进展见仓库 README 的 Code signing policy 一节)。
21
+
22
+ ### Changed
23
+
24
+ - 桌面版图标复用网页版 PWA 图标(`web/public/icons/icon-1024.png`),网页版与桌面版换图标只改一处。
25
+ - 仓库自检现在覆盖桌面壳:`npm run typecheck` / `format:check` / `lint` 都把 `desktop/` 纳入范围。
26
+
27
+ ## [0.79.0] — 2026-09-11
28
+
29
+ ### Added
30
+
31
+ - 聊天消息支持渲染 LaTeX 公式(issue #116):`$...$` 行内、`$$...$$` 独立行块走 KaTeX 渲染(`remark-math + rehype-katex`,字体随包离线可用);代码围栏/行内 code 不受影响,公式写坏了只显示红色源码不打断整条消息。
32
+ - 排队/插队气泡新增「撤回」按钮 ↩(#118):点一下把该条消息从队列取回、文字落回输入框(输入框非空时追加到末尾,绝不覆盖正在打的字),改完直接重发;连续撤回多条按序追加。队列里只存文本,撤回只回文字(附件不恢复)。
33
+ - 新增 paper(暖纸)/ mist(雾蓝灰)/ sakura(樱粉)三套浅色主题:主题切换器与 `make-light-theme.mjs` 生成器同步增强,终端配色跟随主题;`vscode-editor` / `db-client` 插件同步跟随亮色(见下 Fixed)。
34
+
35
+ ### Fixed
36
+
37
+ - `vscode-editor` 插件跟随亮色主题:之前文件树/标签栏/弹窗底色引用了主应用不存在的 `--bg-elev0/1` 变量,亮色下永远回退到深色硬编码值;编辑器(CodeMirror `oneDark`)与底部 SSH 终端配色也是写死的深色。现在底色改走 `--bg/--bg-elev`,编辑器亮色用跟随 `--bg/--text/--accent` 的浅色壳(暗色仍是 `oneDark`,Compartment 热切换),终端读 `--term-*` 调色板;主应用切换主题时(`pi-web-ui:theme-change`)已打开的编辑器与存活终端一起换肤,无需重载。
38
+ - `db-client` 插件跟随亮色主题:同上,文件树/主区/表头/弹窗输入框底色引用的 `--bg-elev0/1` 改走 `--bg/--bg-elev`(该插件无自绘深色组件,一次变量映射即完整跟随)。
39
+
40
+ <!-- auto-i18n:start -->
41
+ ### i18n
42
+
43
+ - 前端新增 key(1):`queueRecallTip`
44
+ <!-- auto-i18n:end -->
45
+
15
46
  ## [0.78.0] — 2026-09-11
16
47
 
17
48
  ### Added
@@ -450,7 +481,9 @@
450
481
  - 0.35.1(2026-08-27):编辑重问保留附件(#18)+ 全窗口拖放(#19)。
451
482
  - 0.29.0(2026-08-23):全局搜索弹窗(Ctrl+K)+ 消息列表惰性窗口化。
452
483
 
453
- [Unreleased]: https://github.com/xing-shuyin/pi-web-ui/compare/v0.78.0...main
484
+ [Unreleased]: https://github.com/xing-shuyin/pi-web-ui/compare/v0.79.0...main
485
+ [0.80.0]: https://github.com/xing-shuyin/pi-web-ui/releases/tag/v0.80.0
486
+ [0.79.0]: https://github.com/xing-shuyin/pi-web-ui/releases/tag/v0.79.0
454
487
  [0.78.0]: https://github.com/xing-shuyin/pi-web-ui/releases/tag/v0.78.0
455
488
  [0.77.0]: https://github.com/xing-shuyin/pi-web-ui/releases/tag/v0.77.0
456
489
  [0.76.0]: https://github.com/xing-shuyin/pi-web-ui/releases/tag/v0.76.0
package/README.md CHANGED
@@ -51,6 +51,8 @@ theme switching, and a full settings panel — tuned for daily development.
51
51
  - 🧩 [Plugins](#plugins)
52
52
  - 🎨 [Themes](#themes)
53
53
  - 🔒 [Security](#security)
54
+ - 🪪 [Code signing policy](#code-signing-policy)
55
+ - 🔐 [Privacy](#privacy)
54
56
  - 🌐 [Reverse proxy (nginx)](#reverse-proxy-nginx)
55
57
  - 🤝 [Contribute](#contribute)
56
58
  - 📄 [License](#license)
@@ -174,6 +176,24 @@ silences the warning):
174
176
  npm i -g --allow-scripts=node-pty,@google/genai,protobufjs pi-web-ui@latest
175
177
  ```
176
178
 
179
+ ### 🖥️ Desktop app (Windows installer)
180
+
181
+ Prefer a window over a browser tab? Every release ships a Windows installer built
182
+ from this repository by GitHub Actions:
183
+
184
+ **[⬇ Download the latest installer](https://github.com/xing-shuyin/pi-web-ui/releases/latest)**
185
+ — `pi-web-ui-desktop Setup <version>.exe`
186
+
187
+ The desktop shell reuses this very server: it spawns `dist/server/index.js` on a
188
+ random free loopback port and opens a window pointed at it (see
189
+ [`desktop/README.md`](desktop/README.md)). The web version is untouched — no
190
+ fight over port `8787`, separate data directory, both can run side by side.
191
+
192
+ Currently Windows-only and **not code signed yet** — Windows SmartScreen will
193
+ show an “unknown publisher” prompt the first time you run it (see the
194
+ [code signing policy](#code-signing-policy)). Build it yourself with
195
+ `npm run desktop:dist`.
196
+
177
197
  ### Termux (Android)
178
198
 
179
199
  pi-web-ui runs fine on Android via [Termux](https://termux.dev), but `node-pty`
@@ -471,6 +491,54 @@ Rules for merged themes: the file must be a single CSS file, set the `--term-*`
471
491
  management UI edits everything else and the server preserves the headers.
472
492
 
473
493
 
494
+ ## 🪪 Code signing policy
495
+
496
+ Free code signing provided by [SignPath.io](https://signpath.io), certificate by
497
+ [SignPath Foundation](https://signpath.org).
498
+
499
+ Release binaries — the Windows installer `pi-web-ui-desktop Setup <version>.exe`
500
+ attached to every [release](https://github.com/xing-shuyin/pi-web-ui/releases) —
501
+ are built from the tagged commit by
502
+ [`.github/workflows/desktop-release.yml`](.github/workflows/desktop-release.yml)
503
+ and signed in that CI run, so a valid signature means the file is an automated
504
+ build of the source code at that tag.
505
+
506
+ ### Team roles
507
+
508
+ | Role | Who |
509
+ | --- | --- |
510
+ | **Authors / committers** (may push to `main`) | [@xing-shuyin](https://github.com/xing-shuyin) |
511
+ | **Reviewers** (every non-committer change arrives as a PR and is reviewed before merge) | [@xing-shuyin](https://github.com/xing-shuyin) — community contributions are credited in the [contributors graph](https://github.com/xing-shuyin/pi-web-ui/graphs/contributors) |
512
+ | **Approvers** (must approve each signing request) | [@xing-shuyin](https://github.com/xing-shuyin) |
513
+
514
+ All team members use multi-factor authentication for both GitHub and SignPath.
515
+ Our release artifacts contain no binaries we did not build ourselves, except
516
+ upstream open-source components bundled by npm and electron-builder (see
517
+ [License](#license)).
518
+
519
+ **Privacy policy:** see [Privacy](#privacy) below.
520
+
521
+ ## 🔐 Privacy
522
+
523
+ pi-web-ui runs entirely on your own machine and has **no telemetry, no analytics
524
+ and no accounts of its own**. Conversations, attachments, settings and terminal
525
+ history stay in your local data directory (`~/.pi-web/` by default, or
526
+ `%APPDATA%\pi-web-ui\data` for the desktop app), and the HTTP server binds
527
+ loopback unless you explicitly expose it.
528
+
529
+ Network requests happen only in these cases:
530
+
531
+ | When | To | What leaves your machine |
532
+ | --- | --- | --- |
533
+ | You send a message, or the agent calls a model | the model providers **you** configure (e.g. `api.openai.com`, `api.opencode.ai`, a local endpoint) | your prompt, the attached file contents and the conversation context |
534
+ | Model catalog refresh (startup, then every 4 h) | `pi.dev` | nothing but the request itself |
535
+ | You install or update a plugin, theme or language pack | `github.com` / `raw.githubusercontent.com` | nothing but the request itself |
536
+ | You check for or install an update | `registry.npmjs.org` | nothing but the request itself |
537
+ | Terminals on Windows, when neither Git Bash nor a `bash` on `PATH` exists | `frippery.org` | one download of `busybox64u.exe` into `<data dir>/bin/bash.exe`, reused offline afterwards |
538
+
539
+ Reverse-proxy setups, the optional `PI_WEB_TOKEN` password and Docker port
540
+ mappings are under your control — see [Security](#security).
541
+
474
542
  ## Reverse proxy (nginx)
475
543
 
476
544
  Serve pi-web-ui behind nginx on the same host (it binds loopback only, so a
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-web-ui",
3
- "version": "0.78.0",
3
+ "version": "0.80.0",
4
4
  "description": "Web chat interface for the pi coding agent, powered by the pi SDK (@earendil-works/pi-coding-agent) — one-command run, Docker/systemd/launchd deployable",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -15,6 +15,7 @@
15
15
  "files": [
16
16
  "bin/",
17
17
  "dist/",
18
+ "!dist/desktop",
18
19
  "web/dist/",
19
20
  "web/public/",
20
21
  "themes/",
@@ -59,7 +60,7 @@
59
60
  "build:dsh-runtime": "node scripts/copy-dsh-runtime.mjs",
60
61
  "build:mermaid-vendor": "node scripts/build-mermaid-vendor.mjs",
61
62
  "build:runtrace-vendor": "node scripts/build-runtrace-vendor.mjs",
62
- "typecheck": "tsc -p tsconfig.server.json --noEmit && tsc -p web/tsconfig.json --noEmit && tsc -p tsconfig.tests.json --noEmit",
63
+ "typecheck": "tsc -p tsconfig.server.json --noEmit && tsc -p web/tsconfig.json --noEmit && tsc -p tsconfig.tests.json --noEmit && tsc -p desktop/tsconfig.json --noEmit",
63
64
  "test": "vitest run",
64
65
  "test:unit": "vitest run",
65
66
  "test:smoke": "node tests/run-smoke.mjs",
@@ -69,10 +70,13 @@
69
70
  "changelog:i18n": "node scripts/release-notes.mjs --unreleased",
70
71
  "test:freeze": "node tests/freeze-test.mjs",
71
72
  "start": "node dist/server/index.js",
72
- "format": "prettier --write server/ web/src/ extensions/ scripts/ bin/ tests/*.mjs tests/unit/ *.mjs",
73
- "format:check": "prettier --check server/ web/src/ extensions/ scripts/ bin/ tests/*.mjs tests/unit/ *.mjs",
74
- "lint": "oxlint server/ web/src/ extensions/ scripts/",
75
- "lint:fix": "oxlint --fix server/ web/src/ extensions/ scripts/"
73
+ "build:desktop": "tsc -p desktop/tsconfig.json",
74
+ "desktop:dev": "npm run build:desktop && electron dist/desktop/main.js",
75
+ "desktop:dist": "npm run build && npm run build:desktop && electron-builder -c desktop/electron-builder.yml",
76
+ "format": "prettier --write server/ web/src/ extensions/ scripts/ bin/ desktop/ tests/*.mjs tests/unit/ *.mjs",
77
+ "format:check": "prettier --check server/ web/src/ extensions/ scripts/ bin/ desktop/ tests/*.mjs tests/unit/ *.mjs",
78
+ "lint": "oxlint server/ web/src/ extensions/ scripts/ desktop/",
79
+ "lint:fix": "oxlint --fix server/ web/src/ extensions/ scripts/ desktop/"
76
80
  },
77
81
  "dependencies": {
78
82
  "@deepseek-ai/dsh-sdk-jsonrpc-server": "^0.1.1-rc.2",
@@ -83,15 +87,18 @@
83
87
  "compression": "^1.8.1",
84
88
  "express": "^4.21.2",
85
89
  "highlight.js": "^11.10.0",
90
+ "katex": "^0.16.47",
86
91
  "node-pty": "^1.1.0",
87
92
  "react": "^18.3.1",
88
93
  "react-dom": "^18.3.1",
89
94
  "react-icons": "^5.7.0",
90
95
  "react-markdown": "^9.0.1",
91
96
  "rehype-highlight": "^7.0.1",
97
+ "rehype-katex": "^7.0.1",
92
98
  "rehype-raw": "^7.0.0",
93
99
  "remark-breaks": "^4.0.0",
94
100
  "remark-gfm": "^4.0.0",
101
+ "remark-math": "^6.0.0",
95
102
  "typebox": "^1.3.14",
96
103
  "ws": "^8.18.0"
97
104
  },
@@ -106,6 +113,8 @@
106
113
  "concurrently": "^9.1.0",
107
114
  "cross-env": "^10.1.0",
108
115
  "esbuild": "^0.25.12",
116
+ "electron": "^44.0.0",
117
+ "electron-builder": "^26.0.0",
109
118
  "jsdom": "^26.1.0",
110
119
  "mermaid": "^11.17.2",
111
120
  "oxlint": "^1.81.0",
@@ -0,0 +1,179 @@
1
+ /* theme-name: 雾蓝灰 */
2
+ /* theme-name-en: Misty Blue Gray */
3
+ :root {
4
+ color-scheme: light;
5
+ --bg: #e9eef4;
6
+ --bg-elev: #f8fafc;
7
+ --bg-elev2: #dde5ec;
8
+ --border: #cbd5e1;
9
+ --border-soft: #dde5ec;
10
+ --text: #1e293b;
11
+ --text-dim: #475569;
12
+ --text-faint: #94a3b8;
13
+ --accent: #0284c7;
14
+ --accent-soft: rgba(2, 132, 199, 0.12);
15
+ --green: #059669;
16
+ --green-soft: rgba(5, 150, 105, 0.12);
17
+ --red: #dc2626;
18
+ --red-soft: rgba(220, 38, 38, 0.1);
19
+ --amber: #d97706;
20
+ --term-bg: #f8fafc;
21
+ --term-fg: #1e293b;
22
+ --term-cursor: #0284c7;
23
+ --term-cursor-accent: #ffffff;
24
+ --term-selection: rgba(2, 132, 199, 0.28);
25
+ --term-black: #dbe3ec;
26
+ --term-red: #dc2626;
27
+ --term-green: #059669;
28
+ --term-yellow: #d97706;
29
+ --term-blue: #2563eb;
30
+ --term-magenta: #9333ea;
31
+ --term-cyan: #0e7490;
32
+ --term-white: #1e293b;
33
+ --term-bright-black: #94a3b8;
34
+ --term-bright-red: #dc2626;
35
+ --term-bright-green: #059669;
36
+ --term-bright-yellow: #d97706;
37
+ --term-bright-blue: #2563eb;
38
+ --term-bright-magenta: #9333ea;
39
+ --term-bright-cyan: #0e7490;
40
+ --term-bright-white: #020617;
41
+ --mono: "SF Mono", "JetBrains Mono", ui-monospace, Menlo, Consolas, monospace;
42
+ --mermaid-font-size: 12px;
43
+ --tooltip-bg: #ffffff;
44
+ --code-bg: #dde5ec;
45
+ --code-text: #1e293b;
46
+ --code-border: var(--border-soft);
47
+ --code-pad: 8px 10px;
48
+ --card-body-pad: 4px 14px 12px;
49
+ --err-text: #dc2626;
50
+ --red-text: #dc2626;
51
+ --amber-text: #b45309;
52
+ --info-blue: #2563eb;
53
+ --link: #0284c7;
54
+ --link-hover: #0369a1;
55
+ --link-soft: #0284c7;
56
+ --md-strong: #0f172a;
57
+ --skill-blue: #0284c7;
58
+ --plugin-purple: #b58cff;
59
+ --auth-green: #059669;
60
+ --scroll-thumb: #b6c2d1;
61
+ --scroll-thumb-hover: #94a3b8;
62
+ --notice-err-bg: #f9dee0;
63
+ --notice-warn-bg: #f0e6cb;
64
+ --notice-info-bg: #d9e6f5;
65
+ --notice-err-border: #dc2626;
66
+ --notice-warn-border: #b45309;
67
+ --notice-info-border: #2563eb;
68
+ --send-blue: #0284c7;
69
+ --send-blue-hover: #0369a1;
70
+ --brand-grad-a: #38bdf8;
71
+ --brand-grad-b: #0284c7;
72
+ --on-amber: #1a1a1a;
73
+ --search-active-fg: #1a1d26;
74
+ --switch-knob: #ffffff;
75
+ --bg-elev3: rgba(30, 58, 95, 0.05);
76
+ --glow-015: rgba(30, 58, 95, 0.02);
77
+ --glow-025: rgba(30, 58, 95, 0.02);
78
+ --glow-03: rgba(30, 58, 95, 0.02);
79
+ --glow-04: rgba(30, 58, 95, 0.03);
80
+ --glow-05: rgba(30, 58, 95, 0.03);
81
+ --glow-12: rgba(30, 58, 95, 0.08);
82
+ --glow-18: rgba(30, 58, 95, 0.12);
83
+ --glow-22: rgba(30, 58, 95, 0.15);
84
+ --glow-38: rgba(30, 58, 95, 0.25);
85
+ --control-fg: #475569;
86
+ --control-bg: #dde5ec;
87
+ --control-border: #cbd5e1;
88
+ --bg-image: none;
89
+ --bg-image-dim: 0.78;
90
+ --bg-image-blur: 0px;
91
+ --wallpaper-panel-alpha: 62%;
92
+ --topbar-bg: color-mix(in srgb, var(--bg-elev) var(--wallpaper-panel-alpha, 62%), transparent);
93
+ --statusbar-bg: color-mix(in srgb, var(--bg-elev) var(--wallpaper-panel-alpha, 62%), transparent);
94
+ --panel-bg: color-mix(in srgb, var(--bg-elev) var(--wallpaper-panel-alpha, 62%), transparent);
95
+ --card-bg: color-mix(in srgb, var(--bg-elev) var(--wallpaper-panel-alpha, 62%), transparent);
96
+ --chip-bg: color-mix(in srgb, var(--bg-elev2) var(--wallpaper-panel-alpha, 62%), transparent);
97
+ --msgs-bg: color-mix(in srgb, var(--bg-elev) var(--wallpaper-panel-alpha, 62%), transparent);
98
+ --inputbox-bg: color-mix(in srgb, var(--bg-elev2) var(--wallpaper-panel-alpha, 62%), transparent);
99
+ --menu-bg: var(--bg-elev2);
100
+ }
101
+
102
+ /* ---- syntax highlighting (overrides static github-dark import) ---- */
103
+ .hljs {
104
+ color: #1e293b;
105
+ background: #dde5ec;
106
+ }
107
+ .hljs-doctag,
108
+ .hljs-keyword,
109
+ .hljs-meta .hljs-keyword,
110
+ .hljs-template-tag,
111
+ .hljs-template-variable,
112
+ .hljs-type,
113
+ .hljs-variable.language_ {
114
+ color: #cf222e;
115
+ }
116
+ .hljs-title,
117
+ .hljs-title.class_,
118
+ .hljs-title.class_.inherited__,
119
+ .hljs-title.function_ {
120
+ color: #8250df;
121
+ }
122
+ .hljs-attr,
123
+ .hljs-attribute,
124
+ .hljs-literal,
125
+ .hljs-meta,
126
+ .hljs-number,
127
+ .hljs-operator,
128
+ .hljs-variable,
129
+ .hljs-selector-attr,
130
+ .hljs-selector-class,
131
+ .hljs-selector-id {
132
+ color: #0550ae;
133
+ }
134
+ .hljs-regexp,
135
+ .hljs-string,
136
+ .hljs-meta .hljs-string {
137
+ color: #0a3069;
138
+ }
139
+ .hljs-built_in,
140
+ .hljs-symbol {
141
+ color: #953800;
142
+ }
143
+ .hljs-comment,
144
+ .hljs-code,
145
+ .hljs-formula {
146
+ color: #7c8da0;
147
+ }
148
+ .hljs-name,
149
+ .hljs-quote,
150
+ .hljs-selector-tag,
151
+ .hljs-selector-pseudo {
152
+ color: #116329;
153
+ }
154
+ .hljs-subst {
155
+ color: #1e293b;
156
+ }
157
+ .hljs-section {
158
+ color: #0550ae;
159
+ font-weight: 700;
160
+ }
161
+ .hljs-bullet {
162
+ color: #0550ae;
163
+ }
164
+ .hljs-emphasis {
165
+ color: #1e293b;
166
+ font-style: italic;
167
+ }
168
+ .hljs-strong {
169
+ color: #1e293b;
170
+ font-weight: 700;
171
+ }
172
+ .hljs-addition {
173
+ color: #116329;
174
+ background: #d7e9db;
175
+ }
176
+ .hljs-deletion {
177
+ color: #82071e;
178
+ background: #f2d3d6;
179
+ }
@@ -0,0 +1,179 @@
1
+ /* theme-name: 暖纸 */
2
+ /* theme-name-en: Warm Paper */
3
+ :root {
4
+ color-scheme: light;
5
+ --bg: #f7f1e3;
6
+ --bg-elev: #fffdf6;
7
+ --bg-elev2: #efe7d3;
8
+ --border: #ddcfae;
9
+ --border-soft: #e7dcc2;
10
+ --text: #3f372c;
11
+ --text-dim: #6f6250;
12
+ --text-faint: #a2937a;
13
+ --accent: #b45309;
14
+ --accent-soft: rgba(180, 83, 9, 0.12);
15
+ --green: #15803d;
16
+ --green-soft: rgba(21, 128, 61, 0.12);
17
+ --red: #b91c1c;
18
+ --red-soft: rgba(185, 28, 28, 0.1);
19
+ --amber: #d97706;
20
+ --term-bg: #f7f1e3;
21
+ --term-fg: #3f372c;
22
+ --term-cursor: #b45309;
23
+ --term-cursor-accent: #fffdf6;
24
+ --term-selection: rgba(180, 83, 9, 0.28);
25
+ --term-black: #e2d5b8;
26
+ --term-red: #b91c1c;
27
+ --term-green: #15803d;
28
+ --term-yellow: #a16207;
29
+ --term-blue: #1d4ed8;
30
+ --term-magenta: #9333ea;
31
+ --term-cyan: #0e7490;
32
+ --term-white: #3f372c;
33
+ --term-bright-black: #a2937a;
34
+ --term-bright-red: #b91c1c;
35
+ --term-bright-green: #15803d;
36
+ --term-bright-yellow: #a16207;
37
+ --term-bright-blue: #1d4ed8;
38
+ --term-bright-magenta: #9333ea;
39
+ --term-bright-cyan: #0e7490;
40
+ --term-bright-white: #1c1917;
41
+ --mono: "SF Mono", "JetBrains Mono", ui-monospace, Menlo, Consolas, monospace;
42
+ --mermaid-font-size: 12px;
43
+ --tooltip-bg: #fffdf6;
44
+ --code-bg: #efe7d3;
45
+ --code-text: #43382c;
46
+ --code-border: var(--border-soft);
47
+ --code-pad: 8px 10px;
48
+ --card-body-pad: 4px 14px 12px;
49
+ --err-text: #b91c1c;
50
+ --red-text: #b91c1c;
51
+ --amber-text: #92400e;
52
+ --info-blue: #1d4ed8;
53
+ --link: #9a3412;
54
+ --link-hover: #7c2d12;
55
+ --link-soft: #9a3412;
56
+ --md-strong: #292019;
57
+ --skill-blue: #b45309;
58
+ --plugin-purple: #b58cff;
59
+ --auth-green: #15803d;
60
+ --scroll-thumb: #d3c4a3;
61
+ --scroll-thumb-hover: #b8a67f;
62
+ --notice-err-bg: #f5dcd2;
63
+ --notice-warn-bg: #f0e5c8;
64
+ --notice-info-bg: #e6dfc9;
65
+ --notice-err-border: #b91c1c;
66
+ --notice-warn-border: #b45309;
67
+ --notice-info-border: #57534e;
68
+ --send-blue: #b45309;
69
+ --send-blue-hover: #92400e;
70
+ --brand-grad-a: #d97706;
71
+ --brand-grad-b: #b45309;
72
+ --on-amber: #1a1a1a;
73
+ --search-active-fg: #1a1d26;
74
+ --switch-knob: #ffffff;
75
+ --bg-elev3: rgba(120, 90, 30, 0.06);
76
+ --glow-015: rgba(120, 90, 30, 0.02);
77
+ --glow-025: rgba(120, 90, 30, 0.02);
78
+ --glow-03: rgba(120, 90, 30, 0.02);
79
+ --glow-04: rgba(120, 90, 30, 0.03);
80
+ --glow-05: rgba(120, 90, 30, 0.03);
81
+ --glow-12: rgba(120, 90, 30, 0.08);
82
+ --glow-18: rgba(120, 90, 30, 0.12);
83
+ --glow-22: rgba(120, 90, 30, 0.15);
84
+ --glow-38: rgba(120, 90, 30, 0.25);
85
+ --control-fg: #6f6250;
86
+ --control-bg: #efe7d3;
87
+ --control-border: #ddcfae;
88
+ --bg-image: none;
89
+ --bg-image-dim: 0.78;
90
+ --bg-image-blur: 0px;
91
+ --wallpaper-panel-alpha: 62%;
92
+ --topbar-bg: color-mix(in srgb, var(--bg-elev) var(--wallpaper-panel-alpha, 62%), transparent);
93
+ --statusbar-bg: color-mix(in srgb, var(--bg-elev) var(--wallpaper-panel-alpha, 62%), transparent);
94
+ --panel-bg: color-mix(in srgb, var(--bg-elev) var(--wallpaper-panel-alpha, 62%), transparent);
95
+ --card-bg: color-mix(in srgb, var(--bg-elev) var(--wallpaper-panel-alpha, 62%), transparent);
96
+ --chip-bg: color-mix(in srgb, var(--bg-elev2) var(--wallpaper-panel-alpha, 62%), transparent);
97
+ --msgs-bg: color-mix(in srgb, var(--bg-elev) var(--wallpaper-panel-alpha, 62%), transparent);
98
+ --inputbox-bg: color-mix(in srgb, var(--bg-elev2) var(--wallpaper-panel-alpha, 62%), transparent);
99
+ --menu-bg: var(--bg-elev2);
100
+ }
101
+
102
+ /* ---- syntax highlighting (overrides static github-dark import) ---- */
103
+ .hljs {
104
+ color: #3f372c;
105
+ background: #efe7d3;
106
+ }
107
+ .hljs-doctag,
108
+ .hljs-keyword,
109
+ .hljs-meta .hljs-keyword,
110
+ .hljs-template-tag,
111
+ .hljs-template-variable,
112
+ .hljs-type,
113
+ .hljs-variable.language_ {
114
+ color: #cf222e;
115
+ }
116
+ .hljs-title,
117
+ .hljs-title.class_,
118
+ .hljs-title.class_.inherited__,
119
+ .hljs-title.function_ {
120
+ color: #8250df;
121
+ }
122
+ .hljs-attr,
123
+ .hljs-attribute,
124
+ .hljs-literal,
125
+ .hljs-meta,
126
+ .hljs-number,
127
+ .hljs-operator,
128
+ .hljs-variable,
129
+ .hljs-selector-attr,
130
+ .hljs-selector-class,
131
+ .hljs-selector-id {
132
+ color: #0550ae;
133
+ }
134
+ .hljs-regexp,
135
+ .hljs-string,
136
+ .hljs-meta .hljs-string {
137
+ color: #0a3069;
138
+ }
139
+ .hljs-built_in,
140
+ .hljs-symbol {
141
+ color: #953800;
142
+ }
143
+ .hljs-comment,
144
+ .hljs-code,
145
+ .hljs-formula {
146
+ color: #8a7d64;
147
+ }
148
+ .hljs-name,
149
+ .hljs-quote,
150
+ .hljs-selector-tag,
151
+ .hljs-selector-pseudo {
152
+ color: #116329;
153
+ }
154
+ .hljs-subst {
155
+ color: #3f372c;
156
+ }
157
+ .hljs-section {
158
+ color: #0550ae;
159
+ font-weight: 700;
160
+ }
161
+ .hljs-bullet {
162
+ color: #0550ae;
163
+ }
164
+ .hljs-emphasis {
165
+ color: #3f372c;
166
+ font-style: italic;
167
+ }
168
+ .hljs-strong {
169
+ color: #3f372c;
170
+ font-weight: 700;
171
+ }
172
+ .hljs-addition {
173
+ color: #116329;
174
+ background: #dfe8cf;
175
+ }
176
+ .hljs-deletion {
177
+ color: #82071e;
178
+ background: #f0d4c4;
179
+ }