# 版本日志

**dsh-myskin —— DSH 全兼容皮肤可视化编辑框架。**

版本号遵循语义化版本；同一 minor 内的补丁版本只包含修正。每个版本按「新增 / 变更 / 修复 / 移除」分类，
条目描述**行为**与**取舍**，不记录实现细节。0.3.3 及更早的逐条变更见 git 历史。

---

## [0.4.1] - 2026-10-06

### 新增

- **兼容模式**：「皮肤管理」页新增开关，开启后皮肤**不接管背景**，可与壁纸 / 玻璃 / 桌面壳特效类插件同时使用。
  具体行为：不画 `canvas.background` 与为此服务的表面透明规则；不写背景类令牌（`--dsw-alias-bg-*`、`--dsw-specific-sidebar-fill`）——
  正是不透明表面会盖住别人的背景；不发布 `html[data-dsh-skin]`，因此**不要求壁纸插件让路**（让路会清掉用户的壁纸）。
  前景令牌、`css` 规则、文字替换、注入图层、嵌入图照常生效。
  背景图与背景类令牌仍保存在文档中，关掉即恢复；绘制模式的实时预览遵守同一套规则，令牌面板把跳过的条目标注为「兼容模式：不写」。
  开关状态写成文档 `css` 里 `:root` 上的标记 `--dsh-myskin-compat`（与背景强度 / 壁纸锚点共用一条规则），
  因此**不需要重启 DSH**，旧宿主也能保存。
- **适配 DSH 原生右侧侧边栏**：「区域外观」新增「右侧侧边栏」区域，锚点 `[data-dockkit-pane]`。
  DSH 0.2 自带的右侧栏（文档预览 / 文件 / 浏览器 / 终端等面板）由 `dsh-client-ui-sidebar-right` 渲染，
  `data-dockkit-*` 只此一包使用（对着本机安装核对过），因此不写死构建哈希；容器 `.panel[data-sidebar-right-panel]` 故意**不**做锚点——
  它是面板背后那条全高定位带，染它等于给一块用户看不到边的区域上色，而可视面是 pane 本身。
  变体的质感与底色同步覆盖右侧栏，避免"左右两侧材质不一致"。
- **变体拆成两个轴，并新增「作用对象」**：「卡片材质」拆为**质感**（模糊 / 边框 / 阴影）与**底色**（玻璃白 / 卡片色 / 透明）——
  一个面由"边框模糊阴影"和"底色"两件事组成，回答的是不同问题；绑在一起时「有玻璃边缘但不盖背景」无法表达，
  而这正是与壁纸类插件共存的正解。卡片顶部新增「作用对象」：全部区域，或单独一处（对话区 / 左侧栏 / 右侧侧边栏 /
  输入框 / 设置页 / 消息列表），选中一处后这一轮点击只改那一处。
  选择按处记录（`--dsh-myskin-variant` 的条目形如 `radius=pill@composer`），读回时「全部区域」打底、本处覆盖；
  排版令牌与强调色没有分区形态，始终全局，卡片里写明。旧文档的 `material=…` 自动映射到两个新轴，界面照旧显示真实选择。
- **圆角可四角单独定义（「区域外观」与「变体」都有）**：统一值（`border-radius`）之外，左上 / 右上 / 右下 / 左下各一行
（`border-top-left-radius` 等长属性）。某一角留空＝跟随统一值，单独填了只改那一角。
  两条值同时存在且都能读回：写角时把简写**提到声明块最前面**（简写会一次性设置四角，写在后面就会把角盖掉），
  只重排、不改写其它声明；整套预设仍然描述整个面（会把四角清掉，回到统一值）。
  「变体」里四角是四个**子轴**（折叠在「圆角」下，点选方式与其它维度同构）：每个只写自己的长属性，没点过的角显示「跟随统一圆角」，
  作用对象 / 撤销 / 恢复默认对它们与普通轴完全一致。
- **装了壁纸插件就自动进入兼容模式**：检测到 `dsh-plugin-wallpaper-engine` 时（只读它常挂的 `data-we-glass-page` / `data-we-adapter` / `data-we-wallpaper`），
  文档里**没表过态**的皮肤自动不接管背景：装了就说明背景有人管，不必先让用户去找开关。
  开关一旦被点过就是**明确的**决定（`--dsh-myskin-compat: 1` / `: 0`），永远盖过自动检测；「还原默认」清空文档后回到自动。
  检测只看 DOM，不读对方配置、不写对方标记；插件中途装上或卸下都会即时生效。

### 变更

- **皮肤包格式改名为 `.dshframework`**（原 `.dshskin`）：「导出皮肤」产出的文件名与导入口的接受列表同步更新，
  包内 `manifest.json` 的 `format` 字段写作 `dshframework`、资源引用写作 `dshframework:assets/…`。
  **旧包照旧能导入**：`format: "dshskin"` 与 `dshskin:assets/…` 两种写法都认，`.dshskin` / `.json` 也仍在接受列表里——
  磁盘上已有的文件不该因为改名而失效。模块随之改名为 `src/client/dshframework.ts`（测试 `tests/dshframework.test.mjs`）。
- **定位改为「DSH 全兼容皮肤可视化编辑框架」**：README、包描述、设置页首行说明、随包技能与本文档同步。
- **声明兼容适配 [dsh-wallpaper-engine](https://github.com/elysia395/dsh-wallpaper-engine)**：README「兼容性」新增专节、随包技能 §10.1 写出上游链接与三条不变量；
  对照版本 1.3.0-r2（自动兼容模式 / 不发布让路标记 / 读它的在台标记，三条都有测试）。

### 移除

- **「实时预览」按钮**：它做的只是 `enabled: true` + 关闭设置弹窗，与上方「启用皮肤」开关重复，而名字承诺了它没有的"不写入文档"。
  绘制模式内的即时预览不受影响。`preview` 文案键一并删除（中英）。

### 修复

- **绘制模式的「还原默认」无法还原**：它此前只把草稿清空。已写入的皮肤仍由引擎画在页面上（自有样式表 + `body` 上的令牌变量），
  而绘制模式这一层只能做加法，因此点完按钮页面「什么都没发生」。现在它把空文档写进皮肤文档（走「保存」同一条通道），
  引擎随之撤掉旧皮肤，页面真正回到原生外观；撤销栈留一步，Ctrl+Z 可把整套皮肤取回草稿继续编辑。
- **极客模式的「还原默认」无法还原**：它此前只清空代码框，规则本身仍留在草稿（并已画在页面上），下一次编辑又会把框填回来。
  现在它连同规则一起删除，并让面板放弃对该元素各字段的占用——否则预览会把这些属性再写回去。
- **「还原默认」会吃掉皮肤库**：皮肤管理页那一个写入的是整份空文档，`library` 一并清空，用户保存过的命名皮肤（连同其画布与图片）
  一次点击即丢失。现在还原写入的是"保留皮肤库的空文档"（`resetSkin`），皮肤库是用户数据，不属于"当前外观"。
- **还原的二次确认按钮叫「保存」**：该按钮此前复用了命名皮肤弹窗的文案键，于是"确定丢弃草稿？"下面写着「保存」。
  新增独立文案「确定还原 / Restore now」，并把提示改写为它真正做的事（清空整套皮肤，保留皮肤库）。
- **写入失败被画成绿色成功**：保存 / 还原被宿主拒绝时，提示行用的是成功色。现在按告警色显示并点名被拒字段。
- **变体的「玻璃」其实一直没有模糊**：区域字段自带模板 `blur({value})`，而变体传的是 `blur(18px)`，
  写出来是 `backdrop-filter: blur(blur(18px))`——无效 CSS，等于没有模糊（同类的 `blur(none)` 也一样）。
  现在传裸数字、关闭时清掉声明，并加了一条**直接断言画到页面上的 CSS** 的测试（旧测试从模板读回，正好把这个错盖住了）。
- **「右侧侧边栏」改了没反应**：右侧栏**不是一个元素**，而上一版只锚了已停靠的 pane（`[data-dockkit-pane]`）。
  侧栏刚打开时显示的是「开始」引导页，**此时没有任何 pane 挂载** ⇒ 命中 0，改圆角自然毫无反应。
  现在锚点补齐为三个：面板本身 `[data-sidebar-right-panel][data-sidebar-right-open]`（引导态与已打开态都在）、
  已停靠 pane `[data-dockkit-pane]`、浮层 pane `[data-dockkit-float]`（与面板拿同一个圆角，否则方角子元素会盖住面板圆角）。
  `[data-sidebar-right-open]` 这半截是必须的：面板容器**关闭时仍留在布局里**（只把子元素 `visibility:hidden`），
  只锚裸属性会在关闭状态留下一块色板——壁纸引擎的样式表里写着同一个坑，并做了同样的护栏。
- **`npm run check:compat` 在本机直接崩溃**：该脚本把 pnpm store 里每个 `@deepseek-ai+dsh-*` 包的文本拼成一个字符串再查找，
  而本机同时装着 0.1.5 / 0.1.7 / 0.2.0 三代 DSH（合计约 827 MB 文本），拼接超出 V8 的字符串长度上限，
  抛 `RangeError: Invalid string length`，一条契约都没检查。改为逐个包扫描（needle 只可能落在单个包内，语义等价），
  现在跑完并 PASS。

### 变更

- 令牌面板在兼容模式下把背景类条目标为「兼容模式：不写」并置灰：设置项"改了没反应"必须当场有解释。
- 绘制模式画面页在兼容模式开启时说明背景不生效及其原因。
- README / 随包技能同步：新增「兼容模式（不接管背景）」小节，并把那条自动互操作（对方壁纸在台则不抢画布）写成兼容模式的**手动退出**。
- **兼容模式同时管住区域 / 面板底色**：区域卡写下的 `background-color` 现在带一条自有标记（`--dsh-myskin-panel`），
  引擎在兼容模式下只摘掉这条声明与标记，保留同一规则里的圆角 / 模糊 / 边框 / 内边距；**手写规则不受影响**。
  区域卡与「变体」的底色都走这条路径，因此在壁纸前自动让开；两处卡片在兼容模式下都会写明"底色不写"。
- 绘制模式的实时预览改用引擎同一套过滤（`paintableRules`）：预览不再承诺一个保存后不会出现的底色。
- 变体的标记格式扩为 `axis=option[@scope]`，并**只记录真正被点的那一个轴**：旧行为会把没点过的轴按"第一个选项"一并写进标记，
  有了作用对象之后那就是在替用户宣称一个没人做过的选择（"全部区域：直角"而输入框是胶囊）。

### 兼容

- **与壁纸插件 `dsh-plugin-wallpaper-engine` 共存**：新增 `src/client/interop.ts`，按对方 1.3.0-r2 公布的契约（只读 DOM 标记，双向都不 import）：
  皮肤在台上时挂 `html[data-dsh-skin="dsh-myskin"]`，对方据此让路（清壁纸层 + 摘玻璃整族，并记住用户选的壁纸以便放回）；
  停用 / 还原 / 卸载时摘掉，另一个皮肤插件写的同名标记只读不写。
- **对方壁纸在台时不抢画布**：读 `body[data-we-wallpaper]`，命中时本插件不画自己的画布壁纸与表面透明层（其余令牌 / 规则 / 文字 / 图层照常），
  并观察该标记的变化——对方让出画布后壁纸自动回来。

### 测试

- 新增 `tests/reset.test.mjs`（还原文档的形状、皮肤库保留、宿主 schema 接受）、
  `tests/reset-ui.test.mjs`（三个「还原默认」按钮 + 撤销，跑真实组件）、`tests/interop.test.mjs`（两个标记的读 / 写 / 不越界）。
- 新增 `tests/compat.test.mjs` 与 `tests/compat-ui.test.mjs`（兼容模式：令牌分类 / 标记共用 / 引擎组合 / 面板底色过滤 / 开关端到端 / 令牌面板标注）；
  `tests/regions.test.mjs` 增加右侧栏锚点与底色标记，`tests/variants.test.mjs` 增加右侧栏材质覆盖。
  UI 组件测试的 jsdom 外壳抽成 `tests/helpers/section-harness.mjs`，由 `reset-ui` 与 `compat-ui` 共用。
- 变体重做：`tests/variants.test.mjs`（8 项：两轴独立、作用对象、全局令牌、旧标记映射、整套、清理）与
  `tests/variant-ui.test.mjs`（3 项：作用对象端到端、玻璃边缘不盖背景、兼容模式下底色被点名且不画）。
- 自动兼容：`tests/interop.test.mjs` 增加"插件是否已加载"的标记识别与观察，`tests/compat.test.mjs` 增加
  `on`/`off`/`auto` 三态与"装了就自动进入"（含用户明确关闭的反例），`tests/compat-ui.test.mjs` 增加自动开启的界面表现。
  `tests/regions.test.mjs` 另外钉住四角独立写入、简写提序与整套预设对四角的清理。
  `tests/variants.test.mjs` 与 `tests/variant-ui.test.mjs` 钉住变体卡的四角子轴（只写自己那条长属性、统一值仍在、界面标注"跟随统一圆角"）。
  `tests/dshframework.test.mjs` 另外钉住旧名包的导入（`format: "dshskin"` + `dshskin:assets/…`）与"新包只写新名"。
  合计 **245** 项通过；`npm run check:types` 对本机 DSH 0.2.0-rc.2 通过，`npm run check:compat` 通过。

- 打包：`npm run pack:share` 产出 `/home/share/dsh-myskin-<版本>-rN.zip`（含预构建 `lib/`，脚本见 `scripts/pack-share.mjs`）。

### 升级说明

- 客户端半区有改动：更新后刷新页面（或在 DSH Desktop 重新打开窗口）即可生效，无需重启 DSH，皮肤文档结构未变。
- 「还原默认」的语义变化：不再删除皮肤库里已保存的皮肤。需要连库一起清空时，逐条删除皮肤库条目即可。
- 「兼容模式」的状态同样写在文档 `css` 的 `:root` 标记（`--dsh-myskin-compat`）里，不是新字段，旧宿主也能保存。

---

## [0.4.0] - 2026-10-01

### 新增

- **面板停靠（左 / 右）**：绘制面板可停靠在窗口任意一侧，面板与页面内缩同步换边，被面板压住的固定定位组件
  重新回到视野并可点选。跟随换边的还有设置弹窗的收口规则、Windows 标题栏分支的页面外距、面板分隔线与阴影方向、
  入场与收起动画方向、折叠箭头。停靠偏好存于浏览器本地（`dsh-myskin.dock`），不写入皮肤文档。
- **遮挡诊断**：绘制模式每 1.5 秒在面板区域做一次网格命中测试，跳过插件自有层与 `html`/`body`/`#root`，
  在工具条第二行提示被遮挡的元素，并提供一键换边。只报事实与提供入口，不修改页面、不猜测 class 与 z-index。
- **「全站」作用域**：只用元素自身的标识（生成的类名、共享的 `data-*`、`role`）生成选择器，不带祖先路径与位置，
  因此跨界面、以及之后新建的实例都命中。没有可用标识时按钮置灰并说明原因；命中超过 64 处判定为布局类并拒绝写入。
  按钮上显示当前命中数，画布为其余命中元素描虚线框（最多 24 个）。切换作用域时已有声明迁移到新选择器。
- **「界面显示」**：按界面决定组件显示或不显示。界面由语义标记推导（设置弹窗 `data-shortcut-modal`、
  当前页面的页面根），规则形式为 `body:has(<界面标记>) <组件标识> { display: none !important }`，
  主语始终是该组件自身，因此"每个界面各渲染一份"与"一个全局节点盖住所有界面"两种形态都适用。
  提供三个预设：只在本页显示、到处都不显示、全部恢复显示。访问过的页面记录在本地（`dsh-myskin.surfaces`，上限 8 个）。
  页面缺少语义标记时该行不出现并说明原因，不按类哈希或导航序号猜测。
- **隐藏后的恢复**：隐藏规则就是普通 `css` 条目，可通过卡片内的「全部恢复显示」（含旧版本写入的反向规则）、
  隐藏全部界面时的就地警告、以及回收站三条路径恢复。
- **层级（z-index）字段**：数值输入 + 滚轮微调（±1，Shift ±10）+ 常用值快捷键 + 独立清除。
  选中 `position: static` 的元素时提示 z-index 不生效，并提供「设为 relative」。
- **叠放诊断**：z-index 填写后无变化的三类成因分别报出——元素未定位、祖先形成层叠上下文天花板（点名祖先与原因）、
  没有重叠元素（此时改数字本就不应有变化）。同时列出真实竞争者的层级，并给出「置顶（max+1）」「置底（min-1）」。
- **壁纸「跟随对话区」**（可选）：勾选后对话列自己绘制一份壁纸并锚定在它自己的框上，侧边栏展开或收起时重新居中，
  不依赖脚本。侧边栏仍使用整页那一份，因此两侧取景不同，这是该选项的固有代价。
- **嵌入动图（GIF 保留动画）**：按字节判断是否动图（GIF89a 块结构，≥2 帧或含 NETSCAPE/ANIMEXTS 循环块），
  动图按原始字节嵌入、不缩放不重编码。动图预算放宽到约 3 MB，超过则退回首帧并明确提示动画丢失。壁纸同理。
  非 GIF 文件只读文件头 16 字节。新嵌入的图片按自身比例放入 320×240 的框，且不放大小图。
- **嵌入图边缘晕染**：每张图可设置羽化宽度（0–200px，向外扩张）与柔化（边缘过渡曲线 0–100，不做模糊）。
  羽化向外扩张，图看起来会大一圈，面板中说明"想保持原大小就把宽高各减 2×宽度"。
- **对话排版（Markdown）**：新增「对话」页签，覆盖会话正文、思考与工具输出的 markdown。
  锚点为渲染器自身的根元素 `[class*="_markdown"]:not([data-markdown-variant="compact"])`（不写构建哈希，
  compact 变体不受影响）。类型走分量令牌（正文与 H1–H4 的字号、行高、字重，行内代码与代码块的底色、字号，链接色），
  间距、内边距、圆角、边框走常规规则。22 个字段分 7 组，另有紧凑 / 标准 / 宽松三个密度预设与恢复默认。
  作用范围可选"全部输出"或"仅对话正文"。卡片显示本页 markdown 命中数；空字段以灰字显示**当前生效值**
  （读取 CSS 变量的计算值，不依赖页面上是否存在对应元素）。
- **变体（点选整套观感）**：新增「变体」页签，四个维度（卡片材质：玻璃 / 纸片 / 描边 / 无框；圆角：直角到胶囊；
  密度：紧凑 / 标准 / 宽松；强调色：跟随主题 / 蓝 / 紫 / 青 / 粉）加四个整套（玻璃通透、纸片清爽、极简安静、张扬）。
  全部为点选，不需要编写 CSS；每个选项幂等地写入它拥有的全部属性，切换不残留；写入的仍是区域规则、排版令牌与品牌令牌。
- **区域外观**：新增「区域」页签，可整块调整对话区、侧边栏、输入框、设置页与消息列表的背景、圆角、阴影、
  背景模糊、边框、内边距、间距与不透明度，并提供玻璃 / 纸片 / 平整三个整套预设。
- **绘制模式的设置实时生效**：令牌类改动（markdown 字号与行高、变体强调色与密度、令牌面板颜色）在绘制模式下即时预览，
  不必先点应用。
- **同类编辑拆分**：面板按编辑类型分为七个页签——变体 / 组件（元素 Inspector 与回收站）/ 图片 / 文字 / 对话 /
  区域 / 画面（壁纸与令牌）；画布上的选择会自动切换到对应页签。
- **嵌入图片的独立设置**：每张图片一个可折叠面板，含锚点、解析状态、呈现方式、不透明度、混合模式、位置与大小，
  以及「选中容器」（把画布带到它身上）。图片成为与组件选择互斥的选中对象：选中图片时画布上只有图片一个框，
  面板顶部切换为图片头卡。
- **嵌入图片的层级与诊断**：每张图可选自动 / 内容之下 / 内容之上。选中图片时给出不可见的原因诊断：
  锚点解析不到、按设置页作用域收起、被容器内容盖住、被容器裁剪，每种都指向对应的开关。

### 变更

- 项目简介统一为「**DSH 通用皮肤框架：可视化自定义 + 实时预览 + 「皮肤管理」**，可以随心设计你的专属皮肤，并通过分发皮肤包和你的小伙伴们分享」，README、包描述与技能说明同步。
- 版本日志改为按版本分组、条目分为新增 / 变更 / 修复 / 移除四类，不再记录实现细节。
- README 新增「界面预览」：应用效果（主界面、对话）、设置页面（账号与余额、皮肤管理）、绘制模式共五张截图，均取自 DSH Desktop；
  示例皮肤使用的侧边栏插画由 @zhangyuzhangyu233 提供，已在致谢中署名。
- 图片位置与大小改为每轴一行（X / Y / 宽 / 高），数值显示到小数点后一位。
- 面板文案不再绑定侧别（「展开 / 收起面板」），折叠箭头随停靠侧翻转。

### 修复

- **类名识别**：兼容三种 CSS-module 类名形态（含本机 DSH 的 `pI_x6G_frame`），并排除 `is-*` / `has-*` /
  `active` / `selected` / `disabled` 等状态类。此前会把这些状态类写进选择器，导致规则在别的实例上永不匹配。
- **「界面显示」在插件页不生效**：原实现把界面写为"设置弹窗开着 / 没开"两个桶，而插件页是主区域里的另一个面板，
  设置弹窗并未挂载。现改为每个页面用自身的语义标记表达。
- **侧边栏收起再展开后嵌入图消失**：标记打在真实节点上，重建子树会连标记一起消失。编辑器现在以 rAF 合并的
  MutationObserver 按草稿重新解析锚点并补打标记，与引擎同一条路。
- **嵌入图盖住容器自身的内容**：`::after` 原用 `z-index: 1`，画在内容之上，与文档所述相反。
  宿主加 `isolation: isolate`、层改 `z-index: -1`，落在容器背景之上、内容之下。
- **四种混合模式看起来一样**：`isolation: isolate` 会隔离混合组，使混合只能与容器背景发生。
  现由混合模式决定层级：`normal` 走内容之下并隔离；任何真实混合模式改为内容之上且不隔离。
- **「壁纸跟随对话区」勾选后无反应**：引擎的应用路径未传入锚点参数；开关的复选框嵌套在滑块的 label 内导致点击
  激活了滑块；开关此前只改草稿不落盘。三处均已修正，开关与强度滑块一样自动保存。
- **设置页中嵌入的图片应用后不可见**：确认是层级问题——设置页卡片的子元素不透明，内容之下的图被自身内容盖住。
  除新增层级选项外，选中图片时直接给出成因诊断。
- **「对话排版」完全没有效果**：锚点原为 `_markdownPayload`（trajectory 表格外壳类），会话正文中不存在。
  现锚定渲染器自身的根元素。
- **边缘晕染指向左上方**：伪元素向左上扩张后坐标已位移，`background-position` 又做了一次位移，导致图片被二次移动。
  现按用户坐标写入，仅将 `background-size` 加上两倍晕染量，图片围绕同一中心放大；衰减坡道重算，
  使完全不透明点落在用户图框内"宽度"像素处，硬边真正消失。
- **「柔化」实为模糊整图**：改为边缘过渡曲线（0 为线性衰减，100 为 smoothstep），不再模糊图像。
- **「对话」页签改动不实时、读不到当前值**：编辑器此前只预览 `css`，未应用令牌，令牌类改动需点应用后才生效；
  现已按引擎方式预览令牌，并在退出时交还原先的值。生效值改为直接读取令牌的计算值，元素探针仅作兜底。
  另修正卡片中残留的旧锚点说明。
- 旧版本写入的羽化标记（`--dsh-myskin-feather-blur` / `-feather-shape`）在下次写入时自动清理。

### 移除

- 区域形状（梯形、波浪、花瓣等）：区域外观保持为背景与面的调整，不再提供轮廓裁剪。

### 升级说明

仅客户端半区变更，刷新页面即可生效，无需重启 DSH。

---

## [0.3.9] - 2026-09-30

### 新增

- **回收站**：列出当前皮肤移除的全部组件，可单项或全部恢复，恢复只删除对应的 `display` 声明，元素上的其它自定义原样保留。
  列表由文档中的 `css` 派生，不存在第二份状态。
- **本机字体列表**：读取本机已安装字体并列成可搜索列表，每项以自身字体渲染。优先使用 Chromium 的 Local Font Access API，
  不可用时退化为候选字体探测；列表标注来源。字体列表不写入皮肤文档，文档中只保存 `font-family` 字符串。
- **字体作用域（界面 / 正文 / 代码）**：三个作用域各自写入普通 `css` 条目，界面与代码通过 DSH 的字体变量生效，
  正文在对话内容与 markdown 选择器上覆盖且不使用 `!important`，以免影响行内代码。写入作用域时附带同类兜底字体。
- **嵌入图片的锚定**：每张图可选用元素（结构选择器）、文字（跟随该段文案）或内置组件（从目录中选择固定部位）作为锚点。
  解析顺序为锚点、冻结的结构选择器、上次命中的节点指纹；锚点暂时找不到时保持不动并重试，不会贴到其它节点上。
  面板显示每张图的锚定状态。
- **嵌入图片的呈现方式**：组件嵌入（画在组件内部，随组件被裁剪）与组件锚定（画在组件之外的独立图层，
  可超出组件范围，不修改宿主元素的位置与溢出）。
- **组块编辑**：编辑范围可选"仅此元素"或"整组"，整组时写入同类元素的公共选择器，因此之后新建的实例同样生效。
  工作区行与对话行按 ARIA 语义区分。画布为其余成员描虚线框并标注成员数量。
- **整组间隔**：设置成员彼此之间的距离，第一个成员与容器顶部的距离不变。成员不是相邻兄弟时该字段不出现并说明原因。
- **嵌入图片的整组锚定**：一张图片可贴到整类元素（例如每一条工作区行），之后新建的成员自动带上，成员离开分组时收回标记。
- **`/dsh-myskin` 命令**：在输入框中使用该命令可让助手按皮肤技能引导设计主题（先加载技能、确认方向、
  给出令牌级方案，交付前校验对比度）。

### 变更

- 「关闭」与「保存 / 应用」的语义分离：`✕` 与 Esc 一律放弃未保存的改动并退出，不再先保存后退出。
  编辑器卸载时把嵌入标记交还给已提交文档。
- 三套预览主题一律跟随应用的明暗模式，皮肤文档中保存的是令牌值本身。

### 修复

- **组件位移抽搐**：拖动时不再丢宽高、内边距与字号等受管声明；两个写入方改为基于最新状态；
  草稿样式表始终排在已提交样式表之后；面板输入框在画布手势期间不再作为写入源。
- **嵌入图的锚点标记未随皮肤撤销**：关闭皮肤后标记仍留在真实节点上。现在按本次应用的图片 id 精确摘除。
- **本机字体列表为空**：列表行作为 flex 子项带有 `overflow: hidden`，自动最小尺寸为 0，行被压缩并裁掉文字。
  改为定高块级滚动区，行不再参与收缩。

### 移除

- 预览主题「极夜」：其强制深色模型需要在浅色模式下额外覆盖 16 个令牌，遗漏即出现亮面配亮字。
  替换为「粉黛」。使用其令牌保存过的皮肤不受影响，界面显示为「自定义皮肤」。

### 升级说明

宿主半区新增命令注册，本版需要重启一次 DSH 才会出现 `/dsh-myskin` 命令。

---

## [0.3.8] - 2026-09-29

### 新增

- **皮肤包 `.dshskin`**：标准 ZIP（以 STORE 写入，兼容 DEFLATE 读取），`manifest.json` 保存完整配置，
  `assets/` 保存壁纸、嵌入图与字体的原始字节。文档中的引用写作 `dshskin:assets/…`，仅在包内存在，
  运行时文档仍为 data URL。同一资源多次引用只存一份；逐条 CRC 校验，缺少资源时明确报错。旧版 `.json` 导出继续支持。
- **位置与缩放**：X / Y 位移与等比缩放，画布上可拖动与缩放，数值支持滚轮微调，每个轴可单独重置，
  只做视觉位移，不改变布局流。
- **对齐线**：移动或缩放时与同级元素、父容器、视口中线比对，4px 内吸附并绘制对齐线；可按 Alt 临时关闭。
- **编辑文字**：边输入边预览（250ms 去抖，一次手势只记一条历史），回车或点击写入，改回原文即撤销该条覆盖。
- **绘制模式的分组与信息**：样式字段拆为文字 / 盒子 / 外观 / 位置与缩放 / 元素操作五组；
  悬停与选中框带元素标签；支持上下级选择；工具条含保存状态、撤销重做与快捷键提示；面板可折叠；还原默认需二次确认。
- **字体**：字体字段支持任意家族栈与建议列表；支持嵌入 `.woff2/.woff/.ttf/.otf` 字体文件（上限 30 MB，
  超过 2 MB 时提示代价），以 `@font-face` 条目存入，删除条目即卸载。
- **编辑器的动效与性能约束**：动画只使用 `transform` 与 `opacity`，不使用 `backdrop-filter`，
  面板折叠不做宽度动画，滚动与缩放的重绘按帧合并，并遵循 `prefers-reduced-motion`。

### 变更

- **保存 / 应用 / 关闭**：保存写入文档并留在绘制模式；应用写入并启用后退出；关闭在无未保存改动时直接退出。

### 修复

- **新对话页的灰色默认文字无法选中**：占位文字不接受指针事件，命中测试返回的是背后空的输入区。
  选择器改为按"指针不可见的文字浮层优先"判定，选中后标注为灰色默认文字。
- **文字无法修改**：文字此前只在点击按钮时写入，输入过程中页面没有反馈，现已改为边输入边预览。

---

## [0.3.7] - 2026-09-29

### 变更

- 项目定位由「DSH Web 皮肤插件」改为「**DSH 通用皮肤框架**」：Web 与 Desktop 共用同一条客户端插件管线。

### 修复

- **桌面壁纸的圆角切割与不透明度不一致**：壁纸改画在对话列上，由列自身的圆角与溢出裁剪；
  列内只保留唯一画布层，背景强度在顶栏、对话区与发送栏三处为同一个值。
- **绘制模式下打开设置时弹窗被遮挡**：设置界面是 portal 到 `body` 的全视口浮层，层级低于绘制画布层。
  现让弹窗遵守与主界面相同的内缩规则，落在应用区域内。
- **侧栏收起或展开后嵌入图消失**：重建节点会抹掉标记。补打标记时优先取可见者，并按祖先链指纹重找节点，只认唯一命中。

---

## [0.3.6] - 2026-09-28

### 修复

- **桌面壁纸的背景强度几乎不生效**：染色层被叠加两次。现改为只施加一次。

---

## [0.3.5] - 2026-09-28

### 修复

- **portal 中的元素无法选中**，导致隐藏、移除与编辑文字静默无效：设置面板、菜单与弹窗挂在 `#root` 之外，
  而选择器一律以 `#root` 打头。现在 portal 内优先使用稳定锚点，最后退化为 `body > …`。
- **桌面端对话区左上角圆角处出现黑块**：圆角缺口露出了窗口原生底色，0.3.7 起由"壁纸画在对话列"彻底解决。

---

## [0.3.4] - 2026-09-28

### 修复

- 客户端激活条件中移除了从未使用的服务，避免上游改名后客户端半区永久挂起、设置页静默消失。
- 补齐 `ctx.slots` 的类型导入（仅类型，不进入产物）。
- 保存皮肤库时补上必填的 `layers` 字段，避免已注入的图层被静默丢弃。
- 文档中补充 `npm install` 的环境变量注意事项（`NODE_ENV=production` 会跳过开发依赖）。
