dsh-claude-style 0.10.4 → 0.10.5

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/CHANGELOG.md CHANGED
@@ -2,6 +2,56 @@
2
2
 
3
3
  All notable changes to `dsh-claude-style` are documented here, newest first.
4
4
 
5
+ ## [0.10.5] - 2026-10-04
6
+
7
+ [中文](#cn-0.10.5) | [English](#en-0.10.5)
8
+
9
+ <h3 id="cn-0.10.5">新增功能</h3>
10
+
11
+ - **配色与字体可以交给宿主,与壁纸等主题插件一起使用**:插件以前总是改写宿主的颜色与字体,并在侧栏、对话区刷上实色底,和 dsh-wallpaper-engine 这类同样改写宿主颜色的主题插件同时启用时,壁纸被盖住,谁的颜色生效还取决于加载先后。设置页新增「配色」与「字体」两项,各有「Claude」与「跟随宿主」两档,默认仍是 Claude。选「跟随宿主」后,插件不再改写宿主的颜色或字体,也不再给侧栏、对话区刷底色,只保留布局和控件;插件自己画的弹层、卡片与选择器改用宿主的颜色,同时启用壁纸插件时随它的玻璃效果变成半透明,弹层还会模糊背后的画面以保证文字清楚。选 Claude 时外观与以前完全一致。
12
+ - **接管宿主界面的功能都能单独关闭**:权限分段控件、侧栏搜索、进行中 / 已归档视图、轮次状态行与对话 / 轨迹标签条以前没有开关,不想要其中一项就只能停用整个插件。现在每一项都有自己的开关,关闭后宿主原来的界面立刻回来,再打开立刻生效,都不需要刷新页面。
13
+ - **设置页分为五个分页**:设置项以前排成一整列。现在顶部的分页条把它们分进「通用」「外观」「输入区」「侧栏」「对话」五页;「快捷供应商」紧跟在「重绘模型选择器」下面、两项之间不画分隔线,模型选择器关闭时变灰不可操作,「出现位置」在吉祥物关闭时同样变灰。
14
+ - **吉祥物可以单独选择,像素螃蟹也随智能体的工作换动画**:吉祥物以前由品牌决定,螃蟹只站在工作台首页,只会偶尔掏出电脑敲一阵代码。现在设置页的「吉祥物」可选「跟随品牌」(默认,Claude 品牌下是螃蟹、DeepSeek 品牌下是 Deepy)、「螃蟹」「Deepy」或「关闭」,「出现位置」可选只在首页,或首页与对话页都出现(默认)。螃蟹和 Deepy 一样站在两种首页版面与对话页的输入区上沿,随工作状态换动画:思考时头顶冒出思考泡泡,写回答与调用工具时敲电脑,三个会话同时工作时戴上安全帽,子代理运行时戴耳机或挥手指挥,等你操作时头顶亮起感叹号,压缩上下文时被压扁,完成时蹦跳,失败时双眼打叉、发抖,闲置一分钟后睡着,有动作时惊醒;闲着时偶尔东张西望、挥挥钳子,或者掏出电脑敲一阵代码。点它的左半边或右半边会被戳得往一侧躲,连点四下会被挠痒,按住拖动会被拎起来。螃蟹的帧图随插件内联,约 20 KB。
15
+
16
+ ### 体验优化
17
+
18
+ - **设置项说明改为只说行为**:设置页十项的说明以前夹带设计缘由(进度圈为什么不停、彩蛋页为什么不跟随界面语言),动辄两三行。现在每条说明只说这一项改什么、各档分别是什么效果;「修改品牌标识」「重绘设置弹层」等动宾式或与其他条目不一致的标题一并统一为名词短语。
19
+ - **Windows 桌面端的顶栏不再是一条单独的色带**:顶栏以前刷着侧栏的颜色,横贯整个窗口,右上角最小化、最大化、关闭三个按钮还托在一块同色的矩形上,打开设置时周围都被遮罩盖暗,只有这块矩形不变。现在顶栏透明,侧栏和主界面各自通到窗口顶端,两者之间的分隔线从顶到底连成一条,主界面左上角的圆角去掉;三个按钮直接落在页面上,打开设置时随页面一起变暗,悬停高亮照常。macOS 与 Web 端不变。
20
+
21
+ ### 问题修复
22
+
23
+ - **小鲸鱼不再把阴影画在目标、待办与排队卡片上**:DeepSeek 品牌下,小鲸鱼被叠在输入卡片上方的目标、待办与排队卡片顶起时,它身下阴影的末端落在那张卡片的最上缘。现在小鲸鱼抬高 3 像素,阴影落在卡片上,卡片上不再压着一道暗色。
24
+ - **侧栏搜索框与它下面的按钮等高、间距一致,桌面端也不再被顶栏盖住**:搜索框以前比「新会话」「插件」这些行高出 4 像素,与它们相隔也只有 4 像素,排在这一列里比其余各行都松。现在搜索框与各按钮同为 28 像素高,与「新会话」的间隔为 6 像素,与各按钮之间的间隔相同;Windows 桌面端那一行为此少抬高 4 像素,搜索框整块落在顶栏下方,不再被截去上缘。
25
+ - **模型选择器右端不再被上下文计量环压住**:在「轨迹」或「上下文」标签页停留后切换对话,模型选择器最右端的档位文字会落在计量环上,并一直保持到上下文数字再次变化;现在回到对话页就恢复两者的间距。
26
+
27
+ ### 其他变更
28
+
29
+ - **设置的保存字段新增九项**:插件的设置表单新增 `palette`、`typeface`、`mascot`、`mascotScope`、`permissionsControl`、`workspaceView`、`sidebarSearch`、`turnStatus`、`viewTabs`。宿主半边是旧版本时(更新插件后没有重启宿主),这几项改动保存不下来,重启宿主后恢复正常。
30
+
31
+ <h3 id="en-0.10.5">New Features</h3>
32
+
33
+ - **Colours and typefaces can be left to the host, so the skin works alongside wallpaper and other theme plugins**: the plugin always rewrote the host's colours and fonts and painted solid canvases under the sidebar and the conversation, so next to a theme plugin that rewrites the same colours, such as dsh-wallpaper-engine, the wallpaper was covered and whose colours won depended on load order. The settings page adds Colours and Typefaces, each with Claude and Follow the host; Claude stays the default. Under Follow the host the plugin rewrites neither the host's colours nor its fonts and paints no canvas under the sidebar or the conversation, keeping only its layout and controls; its own popovers, cards and pickers take the host's colours, turn translucent with a wallpaper plugin's glass, and blur what lies behind them so their text stays readable. Under Claude the look is exactly as before.
34
+ - **Every feature that takes over the host's interface can be switched off on its own**: the permission control, the sidebar search, the In progress / Archived view, the turn status line and the Chat / Trajectory tabs had no switch, so dropping one meant disabling the whole plugin. Each now has its own switch; off brings the host's original back at once, on brings the feature back at once, with no reload either way.
35
+ - **The settings page is split into five tabs**: the settings used to run down one column. A tab strip at the top now sorts them into General, Appearance, Composer, Sidebar and Conversation; Quick providers sits right under Redraw the model picker with no divider between the two, and greys out while the picker is off, as Where it appears does while the mascot is off.
36
+ - **The mascot is chosen on its own, and the pixel crab follows the agent's work too**: the brand used to decide the mascot, and the crab stood on the Studio home page alone, now and then pulling out its laptop to type. The settings page's Mascot now offers Follow the brand (the default: the crab under Claude, Deepy under DeepSeek), Crab, Deepy or Off, and Where it appears offers the home page alone or the home page and conversations (the default). Like Deepy, the crab stands on the composer of both home layouts and of the conversation, and changes its animation with the work: a thought bubble while the model thinks, typing on its laptop while it writes and calls tools, a hard hat with three sessions at work, headphones or conducting while subagents run, an exclamation mark while it waits on you, squashed while the context is compacted, hopping when a turn finishes, crossed eyes and a shake when something fails, asleep after a quiet minute and startled awake at the next move; between jobs it now and then looks around, waves a claw, or pulls out its laptop to type for a while. A click on its left or right half pokes it aside, four quick clicks tickle it, and pressing it and pulling lifts it. The crab's sheets ride the bundle, about 20 KB.
37
+
38
+ ### Improvements
39
+
40
+ - **Settings descriptions now state behavior only**: the ten settings rows used to mix design rationale into their descriptions (why the progress ring never stops, why the easter egg ignores the interface language) and ran two to three lines each. Every description now says only what the setting changes and what each option does; verb-form or inconsistent titles such as the brand and sidebar-footer rows are unified to noun phrases.
41
+ - **The Windows titlebar is no longer a band of its own**: the caption row was painted in the sidebar colour across the whole window, and the minimize, maximize and close buttons sat on a block of that colour, which stayed bright while the settings mask darkened everything around it. The row is transparent now: the sidebar and the main area each run to the top of the window, the divider between them runs top to bottom in one line, and the main area loses its rounded top-left corner; the three buttons sit on the page itself, dim with it under the settings mask, and keep their hover highlight. macOS and the web build are unchanged.
42
+
43
+ ### Bug Fixes
44
+
45
+ - **Deepy no longer paints its shadow across the goal, todo and queue cards**: under the DeepSeek brand, when the goal, todo or queue cards pushed the whale up off the composer card, the tail of the shadow under it landed on the top edge of that card. The whale now sits 3px higher: the shadow rests on the card instead of a dark band being stamped across it.
46
+ - **The sidebar search box matches the height and the rhythm of the rows under it, and no longer hides under the desktop titlebar**: the box stood 4px taller than New session, Plugins and the rows below them, and sat 4px from New session, which left the top of the list looser than the rest of it. The box is 28px like those rows now, 6px above New session, the same step the rows take among themselves; on the Windows Desktop that row rises 4px less, which keeps the whole box below the titlebar instead of cutting its top edge.
47
+ - **The right end of the model trigger no longer sits under the context meter**: after a spell on the Trajectory or Context tab, switching conversations brought the right end of the model trigger under the occupancy ring, and it stayed there until the reading moved again; coming back to the conversation now restores the clearance between the two.
48
+
49
+ ### Chores
50
+
51
+ - **Nine new stored settings**: the plugin's settings form gains `palette`, `typeface`, `mascot`, `mascotScope`, `permissionsControl`, `workspaceView`, `sidebarSearch`, `turnStatus` and `viewTabs`. With an older host half still running (the plugin updated without restarting the host), changes to these do not save until the host restarts.
52
+
53
+ **Full Changelog**: [v0.10.4...v0.10.5](https://github.com/Nwflower/dsh-claude-style/compare/v0.10.4...v0.10.5)
54
+
5
55
  ## [0.10.4] - 2026-10-03
6
56
 
7
57
  [中文](#cn-0.10.4) | [English](#en-0.10.4)
@@ -199,7 +249,7 @@ All notable changes to `dsh-claude-style` are documented here, newest first.
199
249
 
200
250
  ### 体验优化
201
251
 
202
- - **像素螃蟹改用 Claude Code 的原版动画**:工作台首页输入卡片上的螃蟹原来是按 Claude Code 的样子手绘的十一个姿势;现在换成 Claude Code 自己的钓鱼动画,逐帧照搬(43 帧、每帧 80 毫秒,约 3.4 秒):眨眼、举竿甩过卡片边沿、跳一下侧过身钓鱼、收竿转回正面,像素边缘清晰。鱼竿仍用随主题变化的灰色,触发方式(点击、指针移开、闲置时隔二三十秒自己来一次,减少动态效果时只认点击)不变。
252
+ - **像素螃蟹改用 Claude Code 的原版动画**:工作台首页输入卡片上的螃蟹原来是按 Claude Code 的样子手绘的十一个姿势;现在换成 Claude Code 自己的敲代码动画,逐帧照搬(43 帧、每帧 80 毫秒,约 3.4 秒):眨眼、掏出笔记本电脑放到卡片边沿、跳一下侧过身敲一阵键盘、收起电脑转回正面,像素边缘清晰。电脑仍用随主题变化的灰色,触发方式(点击、指针移开、闲置时隔二三十秒自己来一次,减少动态效果时只认点击)不变。
203
253
  - **对话中输入框的发送键改成 Claude Code 的回车图标**:原来是等宽字体里的「↵」字符,有内容时变成陶土橙;现在是按 Claude Code 画的回车箭头(上沿一小段、沿右侧向下、再沿底边向左到箭头),线条清晰,输入框有内容时用正文墨色,空着时仍是浅灰。
204
254
  - **桌面端侧栏的品牌行上移 10px**:桌面端的侧栏从 40px 高的标题栏下方开始,品牌标志因此比 Web 端低出一截;现在品牌行(连同其下的新会话、插件与会话列表)上移 10px,悬停时换上的搜索框仍整个露在标题栏下方,与标题栏里的收起按钮也不重叠。Web 端不变。
205
255
  - **用量面板的倍数趣味行从二十九本书扩到六十五本**:书单补入《黄色壁纸》《变形记》《化身博士》《野性的呼唤》《时间机器》《绿野仙踪》《黑暗之心》《浮士德》《螺丝在拧紧》《伊索寓言》《彼得·潘》《君主论》《隐形人》《安徒生童话》《世界大战》《善恶的彼岸》《白牙》《沉思录》《格林童话》《格列佛游记》《瓦尔登湖》《鲁滨逊漂流记》《神曲》《包法利夫人》《查拉图斯特拉如是说》《奥德赛》《双城记》《远大前程》《理想国》《罪与罚》《利维坦》《安娜·卡列尼娜》《卡拉马佐夫兄弟》《堂吉诃德》《基督山伯爵》《悲惨世界》,长度都是全文以 o200k_base 分词器实测的值(英文原著或通行英译本,《浮士德》为德文原文)。书单仍从《道德经》排到《追忆似水年华》,用量越过的书更密,趣味行落到的那本书离实际用量更近。
@@ -216,7 +266,7 @@ All notable changes to `dsh-claude-style` are documented here, newest first.
216
266
 
217
267
  ### Improvements
218
268
 
219
- - **The pixel crab plays Claude Code's own animation**: the crab on the Studio home page's composer card used to be eleven hand-drawn poses after Claude Code's; it now plays Claude Code's own fishing animation frame for frame (43 frames of 80 ms, about 3.4 s) — a blink, the rod raised and cast past the card's edge, a hop into a side-on stance to fish, the rod reeled in as it turns back — with crisp pixel edges. The rod keeps its theme-following grey, and what sets it off (a click, the pointer leaving it, on its own every half minute or so, only a click under reduced motion) is unchanged.
269
+ - **The pixel crab plays Claude Code's own animation**: the crab on the Studio home page's composer card used to be eleven hand-drawn poses after Claude Code's; it now plays Claude Code's own laptop animation frame for frame (43 frames of 80 ms, about 3.4 s) — a blink, a laptop pulled out onto the card's edge, a hop into a side-on stance to type away, the laptop put away as it turns back — with crisp pixel edges. The laptop keeps its theme-following grey, and what sets it off (a click, the pointer leaving it, on its own every half minute or so, only a click under reduced motion) is unchanged.
220
270
  - **The in-conversation composer's send button uses Claude Code's return glyph**: it used to be the "↵" character from the monospace font, turning clay once there was text; it is now Claude Code's drawn return arrow (a short stub along the top, down the right side, back along the bottom to the arrowhead) in crisp strokes, in the body ink once the box holds text and still pale grey while it is empty.
221
271
  - **The desktop sidebar's brand row sits 10px higher**: the desktop sidebar starts below the 40px titlebar, which left the brand mark lower than on the web; the brand row (and the New session, Plugins and session list below it) now rises 10px, with the search box that takes its place on hover still wholly below the titlebar and clear of the collapse button there. The web build is unchanged.
222
272
  - **The usage panel's yardstick line grows from twenty-nine to sixty-five books**: the list adds The Yellow Wallpaper, Metamorphosis, The Strange Case of Dr Jekyll and Mr Hyde, The Call of the Wild, The Time Machine, The Wonderful Wizard of Oz, Heart of Darkness, Faust, The Turn of the Screw, Aesop's Fables, Peter Pan, The Prince, The Invisible Man, Andersen's Fairy Tales, The War of the Worlds, Beyond Good and Evil, White Fang, Meditations, Grimms' Fairy Tales, Gulliver's Travels, Walden, Robinson Crusoe, The Divine Comedy, Madame Bovary, Thus Spoke Zarathustra, The Odyssey, A Tale of Two Cities, Great Expectations, The Republic, Crime and Punishment, Leviathan, Anna Karenina, The Brothers Karamazov, Don Quixote, The Count of Monte Cristo and Les Misérables, each sized by feeding its full text to the o200k_base tokenizer (the English original or the standard English translation; Faust in the German original). The list still runs from Tao Te Ching to In Search of Lost Time; with the books set closer together, the one the line lands on sits nearer the real usage.
@@ -331,7 +381,7 @@ All notable changes to `dsh-claude-style` are documented here, newest first.
331
381
  - **两套首页版面,设置页随时切换**:新增「首页版面」设置项。**经典**沿用居中大标题加输入卡片;**工作台**把标题移到左上角并固定为一句「What's up next, 用户名?」(无衬线小字,与品牌标记同一行),输入框改用对话内的单行样式贴住窗口底部、上方一行细边框上下文胶囊,标题与一块 480px 窄栏用量面板贴着输入框左缘排布——概览页签是六个数字格(会话数、消息数、Token 总量、活跃天数、高峰时段、最常用模型)与 26 周按天热力图(等分列方格、蓝色数据色阶);模型页签是每天一根按模型颜色自下而上堆叠的柱子,下面跟一份模型排行(色块、模型名、输入与输出、占比,超过六行折成「再显示 N 个」,展开后末尾是「收起」),柱与色块共用同一套按名次取色的蓝色色阶;右上角的「全部 / 30 天 / 7 天」范围切换过滤数字格(含高峰时段)、趣味行与模型排行,热力图与柱状图保持自身窗口;所选范围内的用量超过一本书时,热力图下方出现倍数趣味行:书从《动物农场》到《追忆似水年华》共十一本,每次回到新会话页随机换一本,范围内用量还不到这本书时退到已经超过的最长那本。面板只在新会话页出现,进入对话后自动消失。
332
382
  - **用量数据在本机汇总**:新增只读路由 `GET /dsh-claude-style/usage`(与用户名路由同一同源护栏)。装了 `dsh-cost-meter` 时直接读它的账本缓存(只读),否则读本机会话日志自行汇总,并按日志文件增量缓存——冷启动首次约两秒,之后每次启动约 3 毫秒。两种来源都给出每个模型的四类 token 与每天按模型拆分的 token(`models` 与 `days[].models`),模型页签的柱状图与排行读它们;账本按「提供方:模型」记账,同一模型经不同提供方的用量合成一行。账本不记小时,读账本时其余数字先出,高峰时段随后由本机会话日志按天算出补上。汇总不可用(旧宿主半边或汇总失败)时,面板改用宿主会话列表自带的投影值出数。
333
383
  - **面板先画骨架再填数**:数字到达前先画好外框、占位数字、空热力格与模型行的占位条,到达后只替换文字、格子颜色与条长,整个版面不跳动;取不到数据的格子画破折号,不画零。
334
- - **输入卡片上的像素螃蟹**:工作台版面的新会话页上(经典版面没有),输入卡片上沿靠右站着 Claude Code 的像素螃蟹。点它一下、指针从它身上移开时、以及页面开着时每隔 25–45 秒,它照 Claude Code 的样子钓一次鱼:半转身眨眼,举竿甩到卡片边上,侧身钓一会儿,收竿转回正面,约三秒;系统要求减少动态效果时(例如 Windows 关掉了「在 Windows 中显示动画」),只有点它才播放。只有螃蟹本身接收指针,鱼竿挥动的空白处不挡点击。
384
+ - **输入卡片上的像素螃蟹**:工作台版面的新会话页上(经典版面没有),输入卡片上沿靠右站着 Claude Code 的像素螃蟹。点它一下、指针从它身上移开时、以及页面开着时每隔 25–45 秒,它照 Claude Code 的样子敲一次代码:半转身眨眼,掏出笔记本电脑放到卡片边上,侧身敲一会儿键盘,收起电脑转回正面,约三秒;系统要求减少动态效果时(例如 Windows 关掉了「在 Windows 中显示动画」),只有点它才播放。只有螃蟹本身接收指针,电脑挥动的空白处不挡点击。
335
385
  - **热力图的日期提示**:指针停在热力图的某一天上,立刻浮出 Claude Code 样式的深色提示,写着日期和当天的消息数(如「9月9日 — 15,955」);靠两端的几列提示贴着格子外沿,不会伸出面板。会话列表兜底来源没有按天的消息数,此时提示写当天的 Token。概览的数字格同时改用 Claude Code 的叫法:消息数、Token 总量、最常用模型(模型名不加粗)。
336
386
  - **经典首页的问候更多了**:经典版面的大标题不再每个时段只有一句,早上、午间、下午、晚上、深夜各有一组问候,另有几句不分时段;每次回到新会话页随机换一句,同一次停留里不会跳动。
337
387
  - **接入 HDSL 启动器的账号信息**:由 HDSL 启动的实例,昵称与头像会优先取启动器里的账号。昵称按「自定义昵称 → 官方账号昵称 → HDSL 昵称 → 上次探测到的系统用户名 → 系统用户名 → `User`」回退,头像按「官方账号头像 → HDSL 头像 → Claude 徽标」回退。宿主半边新增两条只读私有路由,与用户名路由同级过宿主请求栅栏:`GET /dsh-claude-style/hdsl` 回账号元数据(不含头像文件的绝对路径),`GET /dsh-claude-style/hdsl-skin.png` 回头像图片。契约版本读不到或不认识时整组忽略;头像文件被删除时回落到徽标。
@@ -341,7 +391,7 @@ All notable changes to `dsh-claude-style` are documented here, newest first.
341
391
  - **Two home layouts, switchable in the settings page**: a new Home layout preference. **Classic** keeps the centered headline over the composer card; **Studio** pins the greeting to the top left as one fixed line ("What's up next, <user>?", in the sans UI face on the brand mark's line), docks the composer in the conversation's single-line form at the window's bottom edge with a row of hairline context chips above it, and sets the greeting and a 480px usage panel against the composer's left edge — an Overview tab with six stat cells (sessions, messages, total tokens, active days, peak hour, favorite model) and a twenty-six-week per-day heat grid of square cells in equal columns, and a Models tab stacking each day's per-model tokens into one bar over a ranked model list (swatch, model name, input and output, share; past six rows it folds behind a "show more" row, and the open list ends in a "show less" row), both reading the same rank-ordered blue ramp. The All / 30d / 7d range pills filter the tiles (the peak hour included), the multiplier line and the model list while the grid and the chart keep their own windows, and once the picked range's total passes one book a multiplier line appears under the grid — eleven books from Animal Farm to In Search of Lost Time, a fresh one drawn each time the new-conversation page comes back, stepping down to the longest book the range has passed when it has not reached the drawn one. The panel appears on the new-conversation page only and steps away once a session is open.
342
392
  - **The usage numbers are folded locally**: a new read-only route, `GET /dsh-claude-style/usage`, behind the same same-origin fence as the username route. With `dsh-cost-meter` installed it reads that plugin's ledger cache (read-only); otherwise the host half folds the local session logs itself and caches the result incrementally per log file — about two seconds on the first cold pass, about 3 ms per start afterwards. Both sources answer each model's four token buckets and each day's per-model tokens (`models` and `days[].models`), which the Models tab's chart and ranking read; the ledger books usage per provider and model, and one model served by several providers is one row. The ledger keeps no hours, so with it the other figures land first and the peak hour follows a moment later, folded per day from the local session logs. When the fold cannot answer (an older host half or a failed pass), the panel falls back to the projection block each host session row carries.
343
393
  - **The panel draws its skeleton before its numbers**: the frame, number placeholders, an empty heat grid and stand-in share bars come first; arriving values replace only the text, the cell colours and the bar lengths, so nothing shifts. A figure no source can answer is a dash, never a zero.
344
- - **A pixel crab on the composer card**: on the new-conversation page of the Studio layout (the Classic layout has none), Claude Code's pixel crab stands on the composer card's top edge near its right end. When it is clicked, when the pointer leaves it, and every 25–45 seconds while the page is in view, it plays Claude Code's fishing routine — a half turn and a wink, the rod cast down onto the card's edge, a spell of fishing side-on, and the rod put away as it turns back, about three seconds; with reduced motion requested (Windows' "Show animations in Windows" turned off, for one) only a click plays it. Only the crab itself takes the pointer, so the room the rod swings through never blocks a click.
394
+ - **A pixel crab on the composer card**: on the new-conversation page of the Studio layout (the Classic layout has none), Claude Code's pixel crab stands on the composer card's top edge near its right end. When it is clicked, when the pointer leaves it, and every 25–45 seconds while the page is in view, it plays Claude Code's laptop routine — a half turn and a wink, a laptop brought out onto the card's edge, a spell of typing side-on, and the laptop put away as it turns back, about three seconds; with reduced motion requested (Windows' "Show animations in Windows" turned off, for one) only a click plays it. Only the crab itself takes the pointer, so the room the laptop swings through never blocks a click.
345
395
  - **Day tips on the heat grid**: resting the pointer on a day of the heat grid shows Claude Code's dark tip at once, with the date and that day's messages ("Sep 9 — 15,955"); over the columns at either end the tip lines up with the cell's outer edge and stays inside the panel. The session list's fallback has no per-day message count, and its tips name the day's tokens instead. The Overview tiles take Claude Code's names as well: Messages, Total tokens and Favorite model (the model name at regular weight).
346
396
  - **More greetings on the classic home page**: the classic headline no longer has one line per time of day — morning, midday, afternoon, evening and night each have a pool, plus a few lines for any hour; a fresh line is drawn each time the new-conversation page comes back and holds still while you stay.
347
397
  - **HDSL launcher accounts are picked up**: an instance started by HDSL prefers the launcher's account for both the nickname and the picture. The nickname falls back through the custom nickname → the signed-in account's name → the HDSL account name → the last probed system user → the system user → `User`; the picture through the account's avatar → the HDSL avatar → the Claude mark. The host half gains two read-only private routes behind the same request fence as the username route: `GET /dsh-claude-style/hdsl` answers the account metadata (never the avatar file's absolute path) and `GET /dsh-claude-style/hdsl-skin.png` answers the image. A contract version that is missing or unknown voids the whole group, and a deleted avatar file falls back to the mark.
package/LICENSE CHANGED
@@ -39,4 +39,13 @@ owners.
39
39
  are JetBrains Mono, distributed under the SIL Open Font License
40
40
  (`fonts/OFL.txt`). They may be redistributed with this plugin.
41
41
 
42
+ Crab artwork notice: the pixel crab (Clawd) is a character of Anthropic, and
43
+ all rights in it remain with Anthropic. `src/assets/mascot/crab-laptop-body.png`
44
+ and `src/assets/mascot/crab-laptop-ink.png` are frames of Claude Code's own
45
+ animation; the sheets under `src/assets/mascot/crab/` are drawn by this project
46
+ after that character (by `scripts/draw-crab.py`, which carries the drawings).
47
+ These files, and their copies inlined into `lib/client.js`, are **not** covered
48
+ by the MIT license above. This plugin is an unofficial fan work, not affiliated
49
+ with or endorsed by Anthropic.
50
+
42
51
 
package/README.en.md CHANGED
@@ -33,7 +33,7 @@ The settings page's Brand mark row switches between the Claude and DeepSeek pale
33
33
  </tr>
34
34
  </table>
35
35
 
36
- > Light mode pairs an ivory canvas `#FCFCFB` with a pale sidebar `#FBFBF9`; dark mode uses warm black `#141413`. Ember orange `#D97757` is the single action accent across both canvases, and Claude Code's pixel crab stands on the Studio home page's composer.
36
+ > Light mode pairs an ivory canvas `#FCFCFB` with a pale sidebar `#FBFBF9`; dark mode uses warm black `#141413`. Ember orange `#D97757` is the single action accent across both canvases, and Claude Code's pixel crab stands on the composer on the home page and in conversations alike.
37
37
 
38
38
  ### DeepSeek
39
39
 
@@ -67,6 +67,24 @@ The settings page's Brand mark row switches between the Claude and DeepSeek pale
67
67
 
68
68
  > The workspaces, sessions, usage figures and nickname in the screenshots are sample data.
69
69
 
70
+ ## Settings
71
+
72
+ The settings page appears both in the settings dialog (the "Claude Style" tab) and on the plugin page, in five tabs:
73
+
74
+ | Tab | Settings |
75
+ |---|---|
76
+ | General | Username, Animation, Open popovers on hover, Account-hold easter egg language |
77
+ | Appearance | Brand mark, Colours, Typefaces, Mascot, Where it appears |
78
+ | Composer | Composer restyle, Home layout, Redraw the model picker (with Quick providers under it), Redraw the permission control |
79
+ | Sidebar | Collapse the sidebar settings area, Sidebar search, In progress / Archived view |
80
+ | Conversation | Turn status line, Chat / Trajectory tabs |
81
+
82
+ Every feature that takes over part of the host's interface has its own switch; turning it off brings the host's original back at once, without a reload.
83
+
84
+ **Alongside other theme plugins**: with Colours and Typefaces set to Follow the host, the skin no longer rewrites the host's colours and fonts and keeps only its layout and controls; the colours are left to DSH itself, or to another theme plugin enabled at the same time. With [dsh-wallpaper-engine](https://github.com/elysia395/dsh-wallpaper-engine), for example, the wallpaper shows through the sidebar and the conversation, and the skin's own popovers take that plugin's glass, translucent and blurring the picture behind them.
85
+
86
+ **Mascot**: a pixel companion stands on the composer's top edge and changes its animation with what the agent is doing (thinking, writing and calling tools, several sessions at work, subagents, waiting on you, compacting the context, finished, failed, asleep). Follow the brand shows the pixel crab under Claude and Deepy the whale under DeepSeek; either can be picked for good, or none. Where it appears keeps it to the new-conversation page, or puts it in conversations as well.
87
+
70
88
  ## Fonts
71
89
 
72
90
  > **Important: the Anthropic fonts are not bundled with the npm package.** They are available for download in this repository under [`fonts/`](fonts/). You can either install them on your system, or skip the install entirely — drop the two `.ttf` files into the plugin package's `fonts/` directory and the host will serve them as webfonts (the files are identical, so the result is the same). Either way, refresh or restart the web UI for the fonts to take effect.
@@ -121,6 +139,8 @@ Keep only one theme enabled at a time. dsh ≥ 0.1.7 is required, and a restart
121
139
 
122
140
  The animation frames of Deepy the pixel whale come from the Deepy whale theme pack drawn by calmly-eating-bugs ([@wp3171216237](https://github.com/wp3171216237)), and ship with the plugin by the author's permission. Many thanks to the author! GIFs of all 20 animations, contributed by the author, are in [showcase/gifs/](showcase/gifs/).
123
141
 
142
+ The pixel crab (Clawd) is a character of Anthropic, and all rights in it remain with Anthropic. Its laptop animation is taken from Claude Code; the animations of its other states are drawn by this project after that character. The crab's frames are not covered by the MIT license (see [LICENSE](LICENSE)). This plugin is an unofficial fan work, not affiliated with or endorsed by Anthropic.
143
+
124
144
  ## Related projects
125
145
 
126
146
  > Running several themes at once? Try [dsh-skin-manager](https://github.com/xiaoyangcheng84-svg/dsh-skin-manager) — it switches between all installed themes from a single settings page.
package/README.md CHANGED
@@ -65,6 +65,24 @@
65
65
  > </tr>
66
66
  > </table>
67
67
 
68
+ ## 设置
69
+
70
+ 设置页同时出现在设置对话框(「Claude Style」标签页)与插件页,分为五个分页:
71
+
72
+ | 分页 | 设置项 |
73
+ |---|---|
74
+ | 通用 | 用户名、动画效果、悬停展开弹层、封号彩蛋语言 |
75
+ | 外观 | 品牌标识、配色、字体、吉祥物、出现位置 |
76
+ | 输入区 | 输入区重绘范围、首页版面、重绘模型选择器(及其下的快捷供应商)、重绘权限控件 |
77
+ | 侧栏 | 折叠侧栏设置区、侧栏搜索、进行中 / 已归档视图 |
78
+ | 对话 | 轮次状态行、对话 / 轨迹标签条 |
79
+
80
+ 每一项接管宿主界面的功能都有自己的开关,关闭后宿主原来的界面原样回来,不需要刷新页面。
81
+
82
+ **与其他主题插件同时使用**:「配色」与「字体」选「跟随宿主」后,本插件不再改写宿主的颜色与字体,只保留布局和控件;颜色交给 DSH 自己,或者交给同时启用的其他主题插件。例如与 [dsh-wallpaper-engine](https://github.com/elysia395/dsh-wallpaper-engine) 一起用时,壁纸透过侧栏与对话区显示出来,插件自己的弹层随壁纸插件的玻璃效果变成半透明并模糊背后的画面。
83
+
84
+ **吉祥物**:输入框上沿站着一只像素小伙伴,随智能体的工作状态换动画(思考、写回答与调用工具、多个会话同时工作、子代理、等你操作、压缩上下文、完成、失败、睡着)。「跟随品牌」在 Claude 品牌下是像素螃蟹,在 DeepSeek 品牌下是小鲸鱼 Deepy,也可以固定选一个或者关闭;「出现位置」决定它只在新会话页出现,还是新会话页和对话页都出现。
85
+
68
86
  ## 字体
69
87
 
70
88
  > 本插件使用的字体如下。
@@ -120,6 +138,8 @@ dsh plugin --profile web add dsh-claude-style # npm 包(推
120
138
 
121
139
  像素小鲸鱼 Deepy 的动画帧图来自 calmly-eating-bugs([@wp3171216237](https://github.com/wp3171216237))绘制的 Deepy 小鲸鱼主题包。
122
140
 
141
+ 像素螃蟹(Clawd)是 Anthropic 的角色形象,相关权利归 Anthropic 所有。螃蟹掏出电脑敲代码的动画取自 Claude Code,其余各个状态的动画由本项目按这一形象绘制。螃蟹的帧图不适用 MIT 许可(见 [LICENSE](LICENSE))。本插件是非官方的爱好者作品,与 Anthropic 没有关联,也未获其认可。
142
+
123
143
  ## 友链
124
144
 
125
145
  > 想把 Claude Code / Codex 等外部代理的会话历史导入 DSH 接着聊?推荐作者的另一个插件 [dsh-chat-import](https://github.com/Nwflower/dsh-chat-import)。
package/docs/STYLE.md CHANGED
@@ -65,11 +65,68 @@ Two fills are palette-specific rather than carried over from the dark base:
65
65
  in light) and `--dsw-alias-button-elevated-fill` (a surface above the canvas in
66
66
  light, a raised gray in dark).
67
67
 
68
+ ## Two palettes · 两套配色归属
69
+
70
+ The Colours and Typefaces rows each choose who paints: **Claude** (the default)
71
+ or **Follow the host**. Every rule that writes a host token carries the Claude
72
+ gate in its selector — `%%PALETTE_CLAUDE%%` for colours, `%%TYPEFACE_CLAUDE%%`
73
+ for `--dsw-font-*` — and so does every rule that paints the skin's canvas onto
74
+ the host's frame (`<html>`, `<body>`, `#root`, the sidebar and conversation
75
+ columns); the build refuses an ungated one. Under "follow the host" those rules
76
+ drop out: the host's own tokens stand, or another theme plugin's, such as a
77
+ wallpaper plugin that clears the canvas and turns the overlays to glass.
78
+
79
+ The skin's own surfaces read only its private tokens and host tokens. Under the
80
+ host palette each private token is an alias of a host token, so those surfaces
81
+ follow whoever paints the host's. A new private colour token is written into
82
+ both the Claude blocks and the host block (the build checks the host block
83
+ covers every one). Cards take the host's overlay layer rather than its canvas:
84
+ a plugin that clears the canvas still gives its overlays a readable fill, and the
85
+ shared popover card blurs what lies behind it (`blur(16px) saturate(1.4)`).
86
+
87
+ | Private token | Host alias | Use |
88
+ |---|---|---|
89
+ | `--dsh-claude-canvas` | `--dsw-alias-bg-base` | the page canvas, the search box |
90
+ | `--dsh-claude-sidebar-canvas` | `--dsw-specific-sidebar-fill` | the sidebar |
91
+ | `--dsh-claude-raised` | `--dsw-alias-bg-overlay` | popovers, menus (dark) |
92
+ | `--dsh-claude-card` | `--dsw-alias-bg-overlay` | cards on the canvas in light and raised in dark: the account popover, the search palette |
93
+ | `--dsh-claude-chip` | `--dsw-specific-selector` | segmented control and switch at rest |
94
+ | `--dsh-claude-hover-bg` | `--dsw-alias-interactive-bg-hover` | hover wash |
95
+ | `--dsh-claude-inline-code-bg` / `-fg` | `--dsw-alias-markdown-inline-code` / `--dsw-alias-label-primary` | inline code |
96
+ | `--dsh-claude-link` / `-underline` / `-hover` | `--dsw-alias-link` (underline at 60%) | markdown links |
97
+ | `--dsh-claude-ink-strong` / `--dsh-claude-session-ink` | `--dsw-alias-label-primary` / `--dsw-alias-label-secondary` | active row ink, session title at rest |
98
+ | `--dsh-claude-table-head` | `--dsw-alias-bg-layer-2` | table header row |
99
+ | `--dsh-claude-scrollbar` / `-hover` | `--dsw-alias-border-l2` / `--dsw-alias-label-caption` | scrollbar thumb |
100
+ | `--dsh-claude-inverse-fill` / `-ink` | `--dsw-alias-interactive-bg-hover` / `--dsw-alias-label-primary` | the model picker's group label (an inverted chip under Claude, a hover-plate chip under the host) |
101
+ | `--dsh-claude-logo-ink` | `--dsw-alias-label-primary` | sidebar brand art |
102
+
103
+ Under the host typeface the skin's own faces fall back to the host's:
104
+ `--dsh-claude-font-serif`, `-prose` and `-brand` to `--dsw-font-family` (the host
105
+ carries no serif), `--dsh-claude-font-code` to `--ds-font-family-code`.
106
+
107
+ Two colours stay whoever paints: the reasoning slider's violet top rung
108
+ (`--dsh-claude-apex*`) and the account-hold page, which reproduces a Claude
109
+ screen. Translucent neutral hover tints and the usage panel's data colours stay
110
+ literal; they read on any canvas. Every other colour that paints a surface, a
111
+ text, a border or an accent reads a token.
112
+
113
+ ## Windows titlebar · 桌面顶栏
114
+
115
+ On the Windows desktop the 40px caption row has no colour of its own: the
116
+ sidebar and the conversation run to the window's top edge, each in its own
117
+ fill (`--dsh-claude-sidebar-canvas`, `--dsh-claude-canvas`), and the sidebar's
118
+ 1px `--dsw-alias-border-l1` hairline runs with them from the top edge to the
119
+ bottom. The conversation column and the fullscreen file panel lose the host's
120
+ 16px top-left corner, so the hairline meets them straight. The three window
121
+ buttons sit on the page itself: no block of their own behind them, and they dim
122
+ with a modal's mask like everything else. Their hover plate is the system's, a
123
+ tint of the button glyph's colour.
124
+
68
125
  ## Typography
69
126
 
70
- - **Serif display** — headings / editorial statements (`--dsw-font-serif`).
127
+ - **Serif display** — headings / editorial statements (`--dsh-claude-font-serif`).
71
128
  - **Sans UI** — chrome, body (`--dsw-font-family`).
72
- - **Mono** — code, technical labels (`--dsw-font-code`).
129
+ - **Mono** — code, technical labels (`--dsh-claude-font-code`).
73
130
 
74
131
 
75
132
  ## Shapes
@@ -466,41 +523,59 @@ placeholder, a zero day draws the grid's own base tone.
466
523
 
467
524
  ## The composer crab · 输入卡片上的螃蟹
468
525
 
469
- On the studio layout's new-conversation page, Claude Code's pixel crab stands on
470
- the composer card's top edge. Its frames are Claude Code's own animation, cut to
471
- 34×23 cells and drawn at 2px a cell, crisp (68×46px); the resting crab is 48×32px
472
- with its feet on the card's edge and the right arm 8px inside the single-line
473
- card's right edge, so the feet stand where its 18px corner starts to round. The
474
- classic layout keeps its centred hero without the crab. The shell is the clay
475
- accent `#d97757` in both themes, the side-on back is `#b9603f`, the eyes
476
- `#141413`, and the rod takes the tertiary label ink. When the crab is clicked,
477
- when the pointer leaves it, and on its own every 25–45 seconds while the page is
478
- in view, it plays Claude Code's fishing routine, 43 frames of 80ms (3.44s): a
479
- blink, the rod raised overhead and cast down past the card's edge, a hop into a
480
- side-on stance, a spell of fishing, and the rod reeled in as it turns back to
481
- face front. With the animation choice resolved to "reduced" (the settings page's
482
- Animation row, or the system's own setting under "follow the system"), only a
483
- click plays it: the pointer passing by and the idle timer leave it still. Only
484
- the crab takes the pointer; the room the rod swings through does not.
526
+ Claude Code's pixel crab is the mascot under the Claude brand (or when picked in
527
+ the Mascot row). It stands where Deepy does — the composer card's top edge on
528
+ both home layouts, the input area or the panel that replaces its card in a
529
+ conversation (unless Where it appears keeps it to the home page) — and follows
530
+ the same states with the same keys. It is drawn on a 52×36 grid of cells at 2px
531
+ a cell, crisp (`pixelated`, 104×72px): feet on the bottom row, on the edge of
532
+ what it stands on; the right claw four cells in from the grid's right edge, so
533
+ it stands 8px inside the card's right edge, where the 18px corner starts to
534
+ round, and the four spare cells take a lean, a note or a sparkle. The resting
535
+ crab — shell 16×12 cells, claws 4×4, eyes 2×2, four legs 2×4 — is 48×32px
536
+ (columns 24–47, rows 20–35) and only it takes the pointer. The shell is the clay
537
+ accent `#d97757` in both themes, the side-on back `#b9603f`, the eyes `#141413`;
538
+ the props (the laptop, the thought bubble, letters, notes, the hard hat) are an
539
+ ink mask filled with the tertiary label ink. Every frame lasts 80ms, Claude
540
+ Code's pace. Its laptop frames are Claude Code's own routine; the rest are drawn
541
+ by `scripts/draw-crab.py` after the same character. With the animation choice
542
+ resolved to "reduced" each state holds its still frame; a click or a pull still
543
+ plays its reaction.
544
+
545
+ | State | Animation | Still frame |
546
+ |---|---|---|
547
+ | idle, every 20–40 s a look around, a claw wave or Claude Code's whole laptop routine | `idle`, `idle-look`, `idle-wave`, `idle-laptop` | 0 |
548
+ | the model reasons or has not answered: eyes up to a thought bubble | `thinking` | 18 |
549
+ | the model writes or tools run: 1 / 2 / 3+ sessions at work (typing / headphones / typing in a hard hat) | `typing` / `music` / `building` | 0 / 0 / 0 |
550
+ | subagents running: 1 / 2+ (headphones / conducting) | `music` / `conducting` | 0 / 0 |
551
+ | a compaction runs: squashed | `compacting` | 3 |
552
+ | an approval, a question or a plan review waits: an exclamation mark | `notification` | 0 |
553
+ | a tool call or a turn failed (4.8 s): crossed eyes, a shake | `error` | 4 |
554
+ | a turn or a compaction finished (5.2 s): hops, claws up | `happy` | 3 |
555
+ | a quiet minute / the next pointer move or key | `sleeping` / `waking` | 0 / 11 |
556
+ | a click on the left / right half, four quick clicks, a pull | `poke-left` / `poke-right`, `tickle`, `drag` | 0 |
485
557
 
486
558
  ## Deepy · 小鲸鱼
487
559
 
488
- Under the DeepSeek brand the crab gives way to Deepy, the pixel whale of the
489
- Deepy theme pack: a 52×52 grid of logical pixels drawn at 2px a pixel (a 104px
560
+ Under the DeepSeek brand (or when picked in the Mascot row) the mascot is
561
+ Deepy, the pixel whale of the Deepy theme pack: a 52×52 grid of logical pixels drawn at 2px a pixel (a 104px
490
562
  square), its ground line — row 48.5, the middle of its shadow — on the top edge
491
- of what it stands on, its box 8px in from the right end of the card it stands
492
- over. On the home page that is the composer card (both layouts); in a
493
- conversation it is the whole input area, and the panel that replaces the card
494
- while the reader is asked for something (those panels start 6–8px above their
495
- card). Every frame lasts 50ms. The sheets carry five device pixels to a logical
496
- pixel and are scaled down smoothly, so the whale stays crisp from 1× to 2×
497
- screens without `image-rendering: pixelated`, which would drop rows on a
498
- downscale. The body is Deepy's blue `#4E6FFF` with a navy `#142660` outline and
499
- a white belly in both themes; on the dark canvas the outline and the soft shadow
500
- recede and the blue body carries the shape. Only the resting body (columns
501
- 12–44, rows 30–48) takes the pointer. With the animation choice resolved to
502
- "reduced" each state holds its still frame; a click or a pull still plays its
503
- reaction.
563
+ of what it stands on. Every sheet's crop box reaches 3px past that ground line,
564
+ and the whale paints over the host's cards, so its box is lifted by those 3px:
565
+ the sprite's last row lands on the card's top edge, and the shadow's tail stays
566
+ off the card instead of being stamped across it. Its box is 8px in from the
567
+ right end of the card it stands over. On the home page that is the composer card
568
+ (both layouts); in a conversation it is the whole input area, and the panel that
569
+ replaces the card while the reader is asked for something (those panels start
570
+ 6–8px above their card). Every frame lasts 50ms. The sheets carry five device
571
+ pixels to a logical pixel and are scaled down smoothly, so the whale stays crisp
572
+ from 1× to 2× screens without `image-rendering: pixelated`, which would drop
573
+ rows on a downscale. The body is Deepy's blue `#4E6FFF` with a navy `#142660`
574
+ outline and a white belly in both themes; on the dark canvas the outline and the
575
+ soft shadow recede and the blue body carries the shape. Only the resting body
576
+ (columns 12–44, rows 30–48) takes the pointer. With the animation choice
577
+ resolved to "reduced" each state holds its still frame; a click or a pull still
578
+ plays its reaction.
504
579
 
505
580
  | State | Animation | Still frame |
506
581
  |---|---|---|
@@ -11,9 +11,9 @@
11
11
  按主题:
12
12
 
13
13
  - 构建与源码:D1 拼接构建 · D5 模型文案是数据 · D18 源码布局与共用部件层 · D4 输入框样式门控
14
- - 宿主边界:D2 只做浏览器半边 · D3 宿主选择器纪律 · D19 宿主契约与构建编号 · D10 设置传输 · D11 私有路由与字符串安全 · D28 桌面标题带的一处读取
15
- - 运行时:D6 单一调度器 · D13 功能契约 · D12 快速失败与功能隔离 · D9 样式性能
16
- - 功能:D14 账号表面 · D15 HDSL 契约 · D16 弹层基准 · D17 权限档位 · D20 滑动高亮 · D21 已归档列表 · D22 搜索面板 · D23 轮次状态行 · D24 小鲸鱼 Deepy · D25 封号彩蛋页的桌面顶栏 · D26 动画效果偏好 · D27 会话数字收进上下文弹层
14
+ - 宿主边界:D2 只做浏览器半边 · D3 宿主选择器纪律 · D19 宿主契约与构建编号 · D10 设置传输 · D11 私有路由与字符串安全 · D28 桌面标题带的一处读取 · D30 配色与字体可以交给宿主 · D31 Windows 顶栏透明
15
+ - 运行时:D6 单一调度器 · D13 功能契约 · D29 功能开关 · D12 快速失败与功能隔离 · D9 样式性能
16
+ - 功能:D14 账号表面 · D15 HDSL 契约 · D16 弹层基准 · D17 权限档位 · D20 滑动高亮 · D21 已归档列表 · D22 搜索面板 · D23 轮次状态行 · D24 吉祥物 · D25 封号彩蛋页的桌面顶栏 · D26 动画效果偏好 · D27 会话数字收进上下文弹层
17
17
  - 分发:D7 行为层与皮肤同包 · D8 多主题
18
18
 
19
19
  ---
@@ -71,8 +71,8 @@
71
71
 
72
72
  ## D7. 行为层与皮肤同包发布
73
73
 
74
- - **决定**:模型选择器、权限分段、账号弹层等行为层与皮肤层共享宿主定位点、调度器与弹层工具,在源码里分目录,发布为同一个包;不想要 Claude 外观的用户在设置里切换品牌。
75
- - **代价**:「只要行为不要外观」没有独立入口。
74
+ - **决定**:模型选择器、权限分段、账号弹层等行为层与皮肤层共享宿主定位点、调度器与弹层工具,在源码里分目录,发布为同一个包。「只要行为不要外观」的入口是设置页的「配色」与「字体」:两项选「跟随宿主」后,皮肤不再改写宿主的颜色与字体,只留布局与控件(D30);每个接管宿主界面的功能另有自己的开关(D29)。
75
+ - **代价**:行为层仍随皮肤的布局一起安装,不能脱离这个包单独使用。
76
76
  - **重审条件**:出现第二个真实使用者(另一个主题包或宿主官方)需要复用行为层时,把它抽成独立包。
77
77
 
78
78
  ## D8. 多主题走单仓库、构建期分包
@@ -112,7 +112,7 @@
112
112
  - 出错的地方直接抛出,不吞错误、不静默回退。宿主服务可能缺席时,用可选链与 `typeof` 检查表达「没有这个服务」,不用 try/catch。
113
113
  - 功能隔离:teardown 最先经 `ctx.effect` 注册且幂等;每个功能单独安装,装不上的报告一次并退役;每轮刷新里每个 `sync()` 单独执行,连续失败 3 轮即报告并退役(`ui.retire`)。调度器自身装不上时整体回滚到宿主原样。
114
114
  - 退役就是运行该功能自己的 teardown,并交还它接管的宿主界面:页脚接管(`FOOTER_ATTR`)与输入框重绘(`COMPOSER_ATTR`)的门控强制关闭;权限控件替换的宿主控件由它自己的标记把守,随它的 teardown 交还。每个功能的 teardown 是它 DOM 与标记的唯一清理。
115
- - 需要隔离、但错误必须可见的地方用 `reportError`:`notifyAll` 逐个通知监听函数,某个出错就报告、其余照常;卸载时单个功能失败同样报告后继续。
115
+ - 需要隔离、但错误必须可见的地方用 `reportError`:`notifyAll` 逐个通知监听函数,某个出错就报告、其余照常;卸载时单个功能失败同样报告后继续;功能开关(D29)关闭某个功能时它的 teardown 抛错,同样报告,这个功能在本代内不再装回。
116
116
  - 允许的 catch 只有以下几类,每处写明原因:上述隔离;宿主以抛错表达的预期状态(设置表单的 `set()` 拒绝不属于该配置的字段;`modelDirectories.directoryFor` 对还没建立的会话抛错,下一轮重试;`sessionQuery.readSession` 以 `SESSION_QUERY_CORRUPT_SESSION` / `SESSION_QUERY_SESSION_NOT_FOUND` 表示某个存档读不了或在列出后被删,内容搜索只把这一个会话记为空并记一条警告);Promise 上表示「宿主半边没有应答」或「宿主自己会提示」的失败回调;小鲸鱼的帧图矢量化两处——Cache API 拒绝读写时视为缓存永远未命中(每次页面加载重转,控制台警告一次),表图能解码但转换失败时按读者要求回退为原 PNG 播放(控制台警告一次)。
117
117
  - **理由**:被吞掉的错误会在别处以更难排查的方式出现;隔离只负责不让一个功能拖垮其他功能,失败本身必须留下记录。
118
118
  - **代价**:功能失效时界面上没有提示,只有控制台记录;依赖同一宿主服务的功能会一起退役(smoke 的「会话列表故障」用例覆盖)。
@@ -121,7 +121,7 @@
121
121
  ## D13. 功能契约:FEATURES 表与调度钩子
122
122
 
123
123
  - **决定**:
124
- - `src/entry.js` 的 FEATURES 表(`{ name, handle?, install }`)同时决定安装顺序与刷新顺序:刷新顺序就是安装顺序中句柄带 `sync` 的那些。
124
+ - `src/entry.js` 的 FEATURES 表(`{ name, handle?, pref | ungated, install }`)同时决定安装顺序与刷新顺序:刷新顺序就是这个顺序,每轮跳过句柄此刻不存在或没有 `sync` 的功能。每项必须声明开关或不设开关的理由(D29)。
125
125
  - 调度器只认功能句柄上的可选钩子(类型定义在 scheduler.js 开头):`sync` / `owns` + `close('outside')` / `onPointerDown` / `close('escape')` / `close('composer')` / `onInput` / `onFocusIn` / `reposition('viewport' | 'composer')` / `onCopyChange` / `onKey` / `onActivity`;没实现的钩子直接跳过,每个功能保留自己的关闭方式。
126
126
  - `retire` 按 name 或 handle 匹配:只匹配到 handle 时只停止 sync、不拆安装(设置页的 `settingsNav`)。
127
127
  - 功能拆出的部分写成顶层工厂 `createX(...)`:状态留在工厂自己的闭包里,访问器与回调经参数传入,不伸手进别的闭包;名字以功能开头(`createAccountProfile`)。
@@ -226,21 +226,25 @@
226
226
  - **代价**:依赖对话列是纵向 flex、行上的 `data-chat-flow-kind` / `data-chat-turn` 与聊天快照的现状;读屏与 Tab 键仍按文档顺序先经过这个控件;历史里有停止或失败的轮次时,它之后的每一行都带一个内联顺序值。
227
227
  - **重审条件**:宿主提供可替换的轮次状态插槽,或把这个控件移到这一轮末尾时,改用宿主的。
228
228
 
229
- ## D24. 小鲸鱼 Deepy:宿主的状态、宿主半边供图、自己的节点上换帧
229
+ ## D24. 吉祥物:宿主的状态、一套播放器、两个角色
230
230
 
231
231
  - **决定**:
232
- - 品牌偏好有两档:Claude(默认)与 DeepSeek。DeepSeek 的值是 `deepseek`(早先这一档叫「关闭」,存下的 `off` 读作 DeepSeek;更早还有第三档 `anthropic`,它与 Claude 同貌,已删除,存下的该值读作 Claude)。这一档保留宿主自己的品牌区(Claude 的品牌不像它)并画成 DeepSeek 蓝,亮暗两套配色都换成蓝色系(亮色的画布只带一点天蓝,接近白),皮肤自己画的 Claude 标(账号行的兜底头像、轮次状态行的火花)换成宿主的鲸鱼标(`FISH_LOGO_PATH`,构建时内联),输入框上的螃蟹换成小鲸鱼 Deepy。配色的切换只靠令牌:宿主的别名令牌与皮肤自己的 `--dsh-claude-canvas`、`--dsh-claude-raised`、`--dsh-claude-logo-ink` 等令牌在 Claude 的亮暗两块里给出原值,DeepSeek 的亮暗两块(多一个品牌属性,优先级更高)整组重写;各功能样式表里原来写死的画布、卡片、边框与强调色一律改读这些令牌,所以 Claude 一档的取值不变(smoke 的默认用例核对)。
233
- - 站位:首页站在输入卡片上沿(composer 功能读出的首页卡片,与螃蟹同一处,两种版面都有)。对话页只认主对话区(`[data-phase="active"]` 里的 `[data-conversation-session]`),站在输入区 composerStack 的上沿;宿主的 composer 链选出替代面板时(ui-renderer 把 `[data-chain-overlay-fallback="conversation.composer"]` 内联写成 `display: none`,面板紧跟其后挂载),站到那块面板上沿。站着的宿主元素打 `data-dsh-claude-deepy-anchor`,样式表给它 `position: relative` 作小鲸鱼的定位容器,换位置或离开时撤掉。
232
+ - 品牌偏好有两档:Claude(默认)与 DeepSeek。DeepSeek 的值是 `deepseek`(早先这一档叫「关闭」,存下的 `off` 读作 DeepSeek;更早还有第三档 `anthropic`,它与 Claude 同貌,已删除,存下的该值读作 Claude)。这一档保留宿主自己的品牌区(Claude 的品牌不像它)并画成 DeepSeek 蓝,配色为 Claude 时亮暗两套都换成蓝色系(亮色的画布只带一点天蓝,接近白),皮肤自己画的 Claude 标(账号行的兜底头像、轮次状态行的火花)换成宿主的鲸鱼标(`FISH_LOGO_PATH`,构建时内联)。配色的切换只靠令牌:宿主的别名令牌与皮肤自己的 `--dsh-claude-canvas`、`--dsh-claude-raised`、`--dsh-claude-logo-ink` 等令牌在 Claude 的亮暗两块里给出原值,DeepSeek 的亮暗两块(多一个品牌属性,优先级更高)整组重写;各功能样式表里原来写死的画布、卡片、边框与强调色一律改读这些令牌,所以 Claude 一档的取值不变(smoke 的默认用例核对)。
233
+ - 吉祥物与品牌分开:`mascot` 偏好有 `brand`(默认,Claude 品牌下是螃蟹、DeepSeek 品牌下是 Deepy)、`crab`、`deepy`、`off` 四档,解析后的角色写成 `<body data-dsh-claude-mascot="crab|deepy|off">`(`MASCOT_ATTR`);`mascotScope` 有 `home` 与 `all`(默认)两档,决定它只站在首页,还是首页与对话页都站。`src/features/mascot/mascot.js` 按这两项让一个角色出场,另一个释放,页面上始终最多一只。
234
+ - 站位:首页站在输入卡片上沿(composer 功能读出的首页卡片,两种版面都有)。对话页只认主对话区(`[data-phase="active"]` 里的 `[data-conversation-session]`),站在输入区 composerStack 的上沿;宿主的 composer 链选出替代面板时(ui-renderer 把 `[data-chain-overlay-fallback="conversation.composer"]` 内联写成 `display: none`,面板紧跟其后挂载),站到那块面板上沿。站着的宿主元素打 `data-dsh-claude-<角色>-anchor`,样式表给它 `position: relative` 作吉祥物的定位容器,换位置或离开时撤掉。
234
235
  - 状态只读宿主的客户端数据:`uiSession.sessionStatus`(是否在跑、等待你的那一个交互)、`sessions.list`(哪些是顶层会话,各自的子代理目录 `subagentCatalog`)、聊天快照(打开的轮次、正在输出的一步的最后一块、进行中的工具调用),每轮刷新、会话状态与聊天快照的订阅通知时重读。聊天快照在跟随这个会话期间订阅:宿主只为订阅者(或正在显示的聊天视图)构建聊天目标,只读不订阅时在轨迹视图下读不到内容。一次性的时刻(轮次结束的原因、失败的工具结果、压缩开始与结束)订阅这个会话的事件流 `sessions.binding(id).eventSource`,只处理订阅之后追加的事件;聊天快照在自动压缩结束之前不显示它,事件流是唯一能看到压缩进行中的地方。正在进行的压缩按事件流的整个窗口算(开始了、还没结束的),开始跟随时与窗口整体重新下发时(例如重新连接)重算,其间由追加的事件更新。首页读整个工作区:会话状态里新出现的 `completionUnread` 就是「后台做完」的时刻。
235
- - 状态到动画按 Deepy 为 Clawd on Desk 做的主题映射。优先级从高到低为:点击与拖动的反应、出错、等待你、压缩、完成、子代理、工作、思考、空闲;工作按同时在跑的顶层会话数分三档,子代理按数目分两档。一个状态上台后一秒内不被同级或更低的状态换下;出错与完成各停两轮动画(4.8 秒、5.2 秒),较低的时刻在较高的时刻结束后接着演。空闲时每二三十秒随机东张西望或喷水一次;空闲满一分钟、其间也没有 `onActivity`(D6)就睡着(这一分钟从读者的最后一次活动与最后一个非空闲状态中较晚的那个算起),下一次活动先演惊醒;`onActivity` 只记下时刻与「该醒了」,惊醒由小鲸鱼自己的下一次计时演出。
236
- - 帧图:每个动画一张精灵图——帧裁到能装下全部帧的最小整数逻辑像素框,八帧一行,每个逻辑像素 5 个像素(这同时就是原作的原生分辨率),无损的调色板 PNG——放在 `src/assets/mascot/deepy/`,由 `src/constants.js` 的 `DEEPY_SHEETS` 登记帧数、裁切框与减少动态效果时的静止帧。构建复制到 `lib/deepy/` 并给每张表算一个内容戳打进产物的 `DEEPY_STAMPS`,宿主半边在公开路由 `/dsh-claude-style/deepy/<名字>.png` 提供(D11),浏览器在地址里带上构建编号,所以可以长期缓存。某个动画第一次要演时才加载:浏览器把 PNG 的像素重建成 SVG(按颜色各一条 path,同行同色游程合并),以「内容戳 + 转换器版本」为键把文本存进 Cache API——表图只有自己的像素变了才重转,与构建编号无关——播放用的是这张矢量(浏览器按显示尺寸栅格化,内存里只留那张小图,各像素密度都锐利);能解码但转换失败的表按读者要求回退为原 PNG 播放(控制台警告一次)。转换完成之前画面上的动画照演;加载失败时这个动画缺席,控制台说一次。
236
+ - 状态到动画按 Deepy 为 Clawd on Desk 做的主题映射(`src/features/mascot/mascot-signals.js`),两个角色共用同一组动画名。优先级从高到低为:点击与拖动的反应、出错、等待你、压缩、完成、子代理、工作、思考、空闲;工作按同时在跑的顶层会话数分三档,子代理按数目分两档。一个状态上台后一秒内不被同级或更低的状态换下;出错与完成各停两轮动画(4.8 秒、5.2 秒),较低的时刻在较高的时刻结束后接着演。空闲时每二三十秒随机演一个角色自己的空闲小节目(Deepy 东张西望或喷水,螃蟹东张西望、挥钳子,或演一整段 Claude Code 原版的掏出电脑敲代码);空闲满一分钟、其间也没有 `onActivity`(D6)就睡着(这一分钟从读者的最后一次活动与最后一个非空闲状态中较晚的那个算起),下一次活动先演惊醒;`onActivity` 只记下时刻与「该醒了」,惊醒由吉祥物自己的下一次计时演出。
237
+ - 一套播放器,两个角色:`src/features/mascot/mascot-player.js` 的 `createMascotPlayer` 是站位、状态机与播放的全部;角色(`whale.js`、`crab.js`)只给出自己的名字、动画表、每帧时长、空闲小节目与帧图管线(`ready` / `failed` / `paint` / `dispose`)。
238
+ - Deepy 的帧图:每个动画一张精灵图——帧裁到能装下全部帧的最小整数逻辑像素框,八帧一行,每个逻辑像素 5 个像素(这同时就是原作的原生分辨率),无损的调色板 PNG——放在 `src/assets/mascot/deepy/`,由 `src/constants.js` 的 `DEEPY_SHEETS` 登记帧数、裁切框与减少动态效果时的静止帧。构建复制到 `lib/deepy/` 并给每张表算一个内容戳打进产物的 `DEEPY_STAMPS`,宿主半边在公开路由 `/dsh-claude-style/deepy/<名字>.png` 提供(D11),浏览器在地址里带上构建编号,所以可以长期缓存。某个动画第一次要演时才加载:浏览器把 PNG 的像素重建成 SVG(按颜色各一条 path,同行同色游程合并),以「内容戳 + 转换器版本」为键把文本存进 Cache API——表图只有自己的像素变了才重转,与构建编号无关——播放用的是这张矢量(浏览器按显示尺寸栅格化,内存里只留那张小图,各像素密度都锐利);能解码但转换失败的表按读者要求回退为原 PNG 播放(控制台警告一次)。转换完成之前画面上的动画照演;加载失败时这个动画缺席,控制台说一次。
239
+ - 螃蟹的帧图:`scripts/draw-crab.py` 按 Claude Code 螃蟹的比例逐帧画出,掏出电脑敲代码的那几帧取自 Claude Code 原版(`src/assets/mascot/crab-laptop-*.png`)。螃蟹画在 52×36 格上、每格 1 像素,每个动画两张表:本体(壳、侧面与眼睛的颜色)和墨色遮罩(电脑、思考泡泡、字母、音符、安全帽),八帧一行、裁到最小框,放在 `src/assets/mascot/crab/`,由 `CRAB_SHEETS` 登记,每帧 80 毫秒(Claude Code 的节奏)。全部表图约 14 KB,构建内联成产物里的 `CRAB_SHEET_URLS`,每个动画要演时即刻可用;样式表按 2 像素一格、`pixelated` 放大,遮罩填主题的三级标签墨色。
237
240
  - 播放:换帧用胶片条——sprite 是 overflow-hidden 的窗口,内层 strip 带整张表图、以 transform 平移对帧;循环动画整段交给浏览器动画引擎(WAAPI steps 关键帧,播放期间主线程无定时器、无重绘),一次性动画以 `finished` 收尾、同刻的截止定时器兜底(后台标签页的事件可能延迟)。状态机的时钟决策(时刻落幕、一秒同台、入睡、空闲小节目)汇成单个一次性定时器,其余由事件驱动。减少动态效果时钉静止帧;换帧不碰 DOM 属性,不唤醒刷新。
238
241
  - **理由**:
239
- - 帧图共约 0.4 MB,内联进产物会让每个品牌的每次页面加载都多解析这么多样式文本;从宿主半边按需取,只有 DeepSeek 品牌、只有演到的动画才下载。
242
+ - 一套播放器:两个角色在同样的时刻演同样的状态,读者换角色时行为不变;新角色只需一张动画表与一条帧图管线。
243
+ - Deepy 的帧图共约 0.4 MB,内联进产物会让每次页面加载都多解析这么多文本;从宿主半边按需取,只有出场的角色、只有演到的动画才下载。螃蟹的表图只有十几 KB,内联省掉一条路由,也不受宿主半边新旧的影响。
240
244
  - 站在输入区上沿:待办、排队与目标卡片叠在输入卡片上面,站在卡片上会盖住它们右端的按钮;等待批准时输入卡片被隐藏,站到面板上,摇铃正好出现在要你操作的地方。
241
245
  - 时刻读事件流:轮次结束的原因、工具失败与压缩都原样出现在事件里,只算订阅之后追加的,打开历史会话不会误报。
242
- - **代价**:依赖 composer 链的替代方式(内联 `display: none` 与紧随其后的面板)、composerStack 的类名片段与会话状态、事件流的现状;订阅聊天目标让宿主在轨迹视图下也为这个会话构建聊天视图;宿主半边是旧版时(更新插件后没有重启宿主)帧图读不到,小鲸鱼不出现。持续的动画每 50 毫秒改一次自己节点的样式,只牵动这一个元素的样式重算与一小块重绘。
243
- - **重审条件**:宿主提供放置状态角色的插槽或统一的「会话活动」服务时改用宿主的;加载器支持资产 URL 时,帧图改随客户端包提供。
246
+ - **代价**:依赖 composer 链的替代方式(内联 `display: none` 与紧随其后的面板)、composerStack 的类名片段与会话状态、事件流的现状;订阅聊天目标让宿主在轨迹视图下也为这个会话构建聊天视图;宿主半边是旧版时(更新插件后没有重启宿主)Deepy 的帧图读不到,小鲸鱼不出现。持续的动画每一帧(Deepy 50 毫秒、螃蟹 80 毫秒)改一次自己节点的样式,只牵动这一个元素的样式重算与一小块重绘。螃蟹的表图让产物多约 20 KB。角色的动画表必须覆盖状态机用到的全部动画名。
247
+ - **重审条件**:宿主提供放置状态角色的插槽或统一的「会话活动」服务时改用宿主的;加载器支持资产 URL 时,Deepy 的帧图改随客户端包提供。
244
248
 
245
249
  ## D25. 封号彩蛋页在桌面端骑在系统标题栏那一行上
246
250
 
@@ -257,7 +261,7 @@
257
261
 
258
262
  - **决定**:
259
263
  - 设置页「动画效果」有 `system` / `reduced` / `full` 三档(随系统 / 减弱 / 总是),默认随系统。解析只发生在 `src/core/prefs.js`:随系统时读操作系统的 `prefers-reduced-motion`,另外两档直接给出答案,结果写成 `<body data-dsh-claude-motion="reduced|full">`(`MOTION_ATTR`)。偏好每次被采用时写一次,系统设置中途变化由调度器(D6)的 `matchMedia` 监听重新解析并排一轮。
260
- - 两个脚本读者一律问 `motionReduced()`(读属性,不读媒体查询):螃蟹的钓鱼动作、「减弱」下只由点击触发;小鲸鱼停在代表帧上、不排额外动作、醒来不演惊醒。样式表读者是 `theme/chrome.css` 的一条属性规则:把皮肤自己的节点(`dsh-claude-` 类名前缀与 `data-dsh-claude-` 标记)的 `animation-duration` 与 `transition-duration` 压到 0.01ms,一次动画即停。宿主自己的过渡不在这条规则的范围内。
264
+ - 脚本读者一律问 `motionReduced()`(读属性,不读媒体查询):吉祥物(D24)停在代表帧上、不排空闲小节目、醒来不演惊醒,点击与拖动的反应照演。样式表读者是 `theme/chrome.css` 的一条属性规则:把皮肤自己的节点(`dsh-claude-` 类名前缀与 `data-dsh-claude-` 标记)的 `animation-duration` 与 `transition-duration` 压到 0.01ms,一次动画即停。宿主自己的过渡不在这条规则的范围内。
261
265
  - 两个例外,理由写在各自的样式表里:分段控件的滑动高亮(D20)与后台任务的转圈(`theme/sidebar.css`)在减弱的设置下照旧播放。
262
266
  - **理由**:媒体查询是系统的事实,样式表改不了它;「总是」必须在系统要求减弱时照样播放,所以答案必须先解析成一个文档属性,脚本与样式表才能读到同一个值。
263
267
  - **代价**:多一条偏好与一个文档属性;系统设置变化后要等调度器重新解析(同一事件内完成,绘制之前)。
@@ -282,3 +286,30 @@
282
286
  - **理由**:封号彩蛋页是第一个读者;判据若写在每个读者里,两个平台的三处分歧就要在每一处重复一遍。集中之后 Windows 的行为不变,macOS 拿到的是同一套答案换成本平台的量值。
283
287
  - **代价**:多一个片段,每次调用多一次 `getComputedStyle` 读取;`--dsh-frame-top-clearance` 缺席时回落到模块内的常数(macOS 48px、Windows 40px)。
284
288
  - **重审条件**:宿主给出统一的标题带插槽或平台无关的度量接口时,改读宿主的接口。
289
+
290
+ ## D29. 功能开关:每个功能声明开关或不设开关的理由
291
+
292
+ - **决定**:
293
+ - FEATURES 表(D13)的每一项二选一地声明 `pref: '<偏好键>'` 或 `ungated: '<理由>'`;两个都没写、两个都写,或 `pref` 不是 `host/settings.js` 的 `PREFS_DEFAULT` 里的键,构建拒绝(`checkFeatureSwitches`)。划分标准:替换或挪动宿主原有的控件与区域、或往界面上加新可见元素的功能设开关;只修宿主的毛病而不改变功能的(`selection`、`themeFlip`)、从属于另一个已有开关的(`copy` 与 `heroMenu` 跟随输入框改造的范围,`effort` 跟随模型选择器——宿主的工作强度在宿主自己的模型菜单里——`quickProviders` 是模型选择器的设置项)、只在点击时出现的(`ban`)以及设置页本身不设。
294
+ - `pref` 是 `FEATURE_PREF_DEFAULTS`(`src/constants.js`,全部默认开)里的键时由 `entry.js` 统一执行:启动时关着的功能不安装;偏好每次被采用时逐个对照,关掉就运行这个功能自己的 teardown、删掉它的句柄,交还它接管的宿主界面,打开就重新安装,都不刷新页面。调度器的两张清单列出全部句柄名,每次使用时检查句柄在不在。其余的 `pref`(`composerScope`、`homeLayout`、`modelPicker`、`collapseFooter`、`mascot`)由功能自己读。退役过的功能(D12)在本代内不因偏好变化装回。
295
+ - 设置页按分页组织(通用、外观、输入区、侧栏、对话),每页的行定义各在 `src/features/settings/settings-tab-*.js`,控件在 `settings-controls.js`;从属于另一项的行紧跟在它下面、两行之间不画分隔线,父项关闭时变灰、不能操作。
296
+ - **理由**:新功能登记时就要回答「读者能不能关掉它」,不会等到发布后才发现漏了;开关的语义统一为「关掉 = 宿主原样」,每个功能的 teardown 本来就负责交还宿主界面(D12),开关只是在运行中调用它。
297
+ - **代价**:每个功能的 teardown 必须能在运行中途执行并完整交还宿主界面(smoke 的 switches 与 switches-off 用例逐项核对);设置表单多五个字段。
298
+ - **重审条件**:宿主提供插件级的功能开关或按区域停用插件的机制时,改接宿主的。
299
+
300
+ ## D30. 配色与字体可以交给宿主
301
+
302
+ - **决定**:
303
+ - 「配色」与「字体」两项偏好各有 `claude`(默认)与 `host` 两档,写成 `<body data-dsh-claude-palette>` 与 `<body data-dsh-claude-typeface>`。每条写宿主令牌的规则都挂在 Claude 一档上:选择器里写构建期令牌 `%%PALETTE_CLAUDE%%`(颜色)或 `%%TYPEFACE_CLAUDE%%`(`--dsw-font-*`),构建按字面检查——写 `--dsw-` 颜色令牌的规则缺 `%%PALETTE_CLAUDE%%`、写 `--dsw-font-*` 的规则缺 `%%TYPEFACE_CLAUDE%%`,构建拒绝(`checkTokenGates`)。把皮肤的画布刷到宿主框架上的规则(`<html>`、`<body>`、`#root`、侧栏、对话列)同样挂在 Claude 一档上。
304
+ - 皮肤自己的节点只读私有令牌(`--dsh-claude-*`)与宿主令牌。`%%PALETTE_HOST%%` / `%%TYPEFACE_HOST%%` 的规则把每个私有令牌改成宿主令牌的别名(对照表在 docs/STYLE.md 的「Two palettes」);Claude 一档定义的每个私有令牌在宿主一档都要有别名,构建核对(`checkTokenAliases`)。卡片类的面(弹层、账号弹层、搜索面板)用宿主的浮层令牌 `--dsw-alias-bg-overlay`,在宿主一档下给共用弹层外壳加背景模糊(D16),透明的浮层上文字仍然清楚。皮肤自造的字体令牌改名为私有的 `--dsh-claude-font-serif` / `-prose` / `-code` / `-brand`,宿主一档回落到宿主的 `--dsw-font-family` 与 `--ds-font-family-code`。
305
+ - 推理强度滑杆顶档的紫色、封号彩蛋页复刻的 Claude 页面在两档下都保留原色;半透明的中性悬停色与用量面板的数据配色写成字面值,在任何画布上都能读。
306
+ - **理由**:「跟随宿主」时皮肤不和宿主或其他主题插件(例如 dsh-wallpaper-engine 把画布清空、把浮层改成玻璃)争同一组令牌,结果不取决于样式表的加载先后;皮肤自己的面读别名,所以跟着别人画的颜色走,不用逐个功能处理。挂门由构建检查,以后新增的规则漏挂就构建不过。
307
+ - **代价**:Claude 一档的令牌规则多一个属性选择器(各档之间的相对优先级不变,Claude 一档的计算值逐字不变);新的私有颜色令牌要同时写进两档;功能样式表里画面的颜色不能写字面值,要读令牌。
308
+ - **重审条件**:宿主提供主题层级或令牌分层机制(多个主题插件按层叠加)时,改用宿主的。
309
+
310
+ ## D31. Windows 桌面顶栏透明,各列延伸到窗口顶端
311
+
312
+ - **决定**:Windows 桌面端(`html[data-windows-titlebar]`)的顶栏不再有自己的颜色。宿主在各列上方留出的一行(框架的 `padding-top`,由框架本身与它的 `::before` 拖动条刷成侧栏底色)改为透明,侧栏与对话列各用一层向上偏移顶栏高度的外阴影(`box-shadow`)把自己的底色延伸进这一行;侧栏右边的细分隔线由侧栏的拖动把手(`[data-side="sidebar"]`,骑在列边上、和列宽走同一条动画曲线)的 `::before` 向上画过这一行;宿主的 `--dsh-windows-content-radius` 设为 0,对话列与全屏文件面板左上角的圆角去掉,分隔线直着接下去。右上角三个窗口按钮下的底色由系统绘制,颜色来自宿主桌面端 preload 放在 `<body>` 下的隐藏探针 `<span>`(读 `--dsw-specific-sidebar-fill`,`<head>` 变化时重读并交给 `setTitleBarOverlay`);皮肤把这个探针的 `background-color` 设为透明,系统收到 `rgba(0, 0, 0, 0)` 后按钮下露出页面本身,弹窗遮罩盖上来时按钮区随页面一起变暗。实测:透明后按钮的悬停高亮照常,系统按图标颜色叠一层大约一成浓度的颜色。
313
+ - **理由**:Claude Code 桌面端的侧栏与主界面都通到窗口顶端,中间一条分隔线从上到下;宿主的顶栏是另一种颜色的横条,三个按钮还单独托在一块同色矩形上,页面这一侧一变(遮罩、壁纸插件)就露出来。外阴影只画在列的盒子外面,列里的内容和宿主的布局都不动,拖动列宽与收起动画时自动跟着列走。
314
+ - **代价**:认探针靠它内联样式里的 `--dsw-specific-sidebar-fill` 子串,属于宿主 preload 的内部写法、不是公开契约(D3 的例外,记在这里);宿主改了写法,按钮区退回宿主的底色,不会出错。收起侧栏时宿主立即移除拖动把手,顶栏里那段分隔线比列宽动画先消失。
315
+ - **重审条件**:宿主的桌面端提供顶栏透明的选项或按钮区底色的公开接口时,改用宿主的。