dsh-any-background 0.3.9 → 0.3.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  <a href="https://www.npmjs.com/package/dsh-any-background"><img alt="npm version" src="https://img.shields.io/npm/v/dsh-any-background?color=4d6bfe"></a>
5
5
  <a href="https://www.npmjs.com/package/dsh-any-background"><img alt="npm monthly downloads" src="https://img.shields.io/npm/dm/dsh-any-background?color=4d6bfe"></a>
6
6
  <a href="https://github.com/Tkingxiao/dsh-any-background/blob/main/LICENSE"><img alt="License: MIT" src="https://img.shields.io/npm/l/dsh-any-background?color=4d6bfe"></a>
7
- <a href="https://www.npmjs.com/package/@deepseek-ai/dsh?activeTab=versions"><img alt="Supported DSH versions: 0.2.0-rc.1 ~ 0.2.1-rc.2 and above" src="https://img.shields.io/badge/DSH-0.2.0--rc.1%20~%200.2.1--rc.2%2B-4d6bfe" /></a>
7
+ <a href="https://www.npmjs.com/package/@deepseek-ai/dsh?activeTab=versions"><img alt="Supported DSH versions: 0.2.0-rc.1 ~ 0.2.1-rc.3 and above" src="https://img.shields.io/badge/DSH-0.2.0--rc.1%20~%200.2.1--rc.3%2B-4d6bfe" /></a>
8
8
  <a href="https://github.com/topics/dsh-better-sidebar"><img alt="Plugin ecosystem: GitHub topic dsh-better-sidebar" src="https://img.shields.io/badge/plugin%20ecosystem-topic%20dsh--better--sidebar-4d6bfe" /></a><br /><br />
9
9
  <a href="https://github.com/Tkingxiao/dsh-any-background"><img src="https://img.shields.io/github/stars/Tkingxiao/dsh-any-background?style=social" alt="GitHub stars"></a>
10
10
  <a href="https://dsh.directory/plugins/tkingxiao/dsh-any-background"><img src="https://dsh.directory/badges/listed.svg" alt="dsh.directory listed"></a>
@@ -12,7 +12,7 @@
12
12
 
13
13
  English | [中文](README.zh.md)
14
14
 
15
- A **DeepSeek Harness** appearance plugin: custom theme color, background wallpaper (image / video / algorithmically generated), and fine-grained per-surface opacity & blur controls. Compatible with **DSH `0.2.0-rc.1` through `0.2.1-rc.2` — and every host release above it** (official-Sidebar UI such as the "Theme" card enables itself where the host exposes the Sidebar registry extension point, and is skipped silently where it does not).
15
+ A **DeepSeek Harness** appearance plugin: custom theme color, background wallpaper (image / video / algorithmically generated), and fine-grained per-surface opacity & blur controls. Compatible with **DSH `0.2.0-rc.1` through `0.2.1-rc.3` — and every host release above it** (official-Sidebar UI such as the "Theme" card enables itself where the host exposes the Sidebar registry extension point, and is skipped silently where it does not).
16
16
 
17
17
  ---
18
18
 
@@ -95,6 +95,10 @@ controls (`z-index:-1`) and carries its own ink (`--dsh-any-caption-ink`), so th
95
95
 
96
96
  ## Changelog (latest two releases)
97
97
 
98
+ ### v0.3.10 (0.2.1-rc.3 verified: one more SUPPORTED_RELEASES row, no new facts)
99
+
100
+ - **`0.2.1-rc.3` is a checked build now, not a clamped guess.** `git diff rc.2 rc.3` over every file the `0.2.1` adapter speaks for comes back empty where it matters: `design-platform.css`, both menu stylesheets and `MenuGroup.tsx` are byte-identical, and so are `SidebarRight.module.css`, `TabLayout.tsx`, `base.css`, `gradient-shadow-text.css`, `AppFrame.*`, `InlineEditor.module.css`, `TextShimmer`, `JobListAction`, `TaskMenu`, `scoped-slots` and `PluginManagerPage.tsx`, and the five header slot keys stand. The adapter's facts hold, so rc.3 joins `v0-2-1` with a `SUPPORTED_RELEASES` row — its verdict reads `exact` — and the folder's header records what the tag did move: `Menu.tsx` is additive (an `aria-current` render and a portal-only `min-width` switch, with no stylesheet moving alongside), the guide and the sidebar panel list grow pin state and More menus AROUND the existing registrations while the tab registry in `shell/` is untouched, the session header's new View-row More menu mounts through `<Menu … portal>` to `document.body` and is therefore already claimed by the tagger's portaled arm, and `ConversationRoot.module.css` only re-lays the View tab row. `engines.dsh`, the six gated `@deepseek-ai/dsh-*` peers, `dsh.compatibility.dsh` and `dsh.compatibility.dshReleases` all name `0.2.1-rc.3`.
101
+
98
102
  ### v0.3.9 (Issue #30 makes the caption ink a choice, and the header sliders reach every header popover)
99
103
 
100
104
  - **The caption strip's ink is the user's call now (issue #30).** 0.3.8 derived it from what the strip is actually painted on, which fixed the invisible white toggle — and made the native menubar (「应用 / 编辑」) black under a dark theme whose sidebar is translucent over a bright wallpaper, because there the strip really IS light. The two reports of that one situation wanted opposite winners, so the 「标题栏」 card gained a 「标题条带文字」 selector: **自动** keeps the strip-following derivation, **跟随主题** emits no override at all (the menubar and the sidebar's fixed caption controls read the host's own label tokens, exactly as they did through 0.3.7), **始终白色 / 始终黑色** pin it. The key is stored and whitelisted on the host half too — the #28 lesson is that a key only one half knows is silently dropped at write time — and `npm test` round-trips it, including an unknown value collapsing to `auto`.
@@ -104,18 +108,6 @@ controls (`z-index:-1`) and carries its own ink (`--dsh-any-caption-ink`), so th
104
108
  - **A 0 on a menu blur slider now means no frost.** 0.3.7 introduced a `<html>` class gate (`dab-card-frost` / `dab-header-frost`) so a slider parked at 0 would not delete the host's own `--dsw-menu-backdrop-filter: blur(40px) saturate(150%)` — an element's own declaration always beats what it inherits, so the un-gated `var(--x, none)` really did clear it. The gate turned out to be the wrong trade: it made the slider's LOW end its HIGH end (0 → the host's 40 px, 1 → 1 px), so 「把模糊度关掉」 was unreachable and the control read as dead at exactly the position the user was testing. The frost token is now asserted at every value with the `none` fallback winning at 0, and the gate machinery is gone. Nothing loses the host look by accident: every part default is 30 px, so a stock install is frosted and only an explicit drag to 0 clears it.
105
109
  - **No release-table change.** The shapes above were re-checked against the installed `0.2.0-rc.1`, `0.2.1-alpha.3` and `0.2.1-rc.2` bundles: both utilities controls, `MenuSurface`'s `data-menu-material` + `.material` painter and the menu token set are identical across the three, so the `0.2.1` adapter's facts still hold.
106
110
 
107
-
108
- ### v0.3.8 (Issues #28/#29 and the desktop sidebar: the header-bar card persists, its band stops eating clicks, the mask reaches the caption, and the sidebar is one surface again)
109
-
110
- - **The 「标题栏」 settings survive a restart now.** The host half whitelists every key before it writes (`normalizeConfig` → `theme-config.json`), and its copy of the config shape had never learned that card's three keys: `blurs.headerBar` fell back to 30 px, `strokes.headerBar` to width 0, and `headerBarOpacity` was dropped outright at write time — while the browser half restored the file with its own defaults (`clamp01(undefined, .5) → 50%`), so the card looked like it saved and then reset on every reload. The profile sanitizer had the same hole, and was also dropping `blurs.header` from saved profiles. All three keys now exist in the host's `PartBlurs`, `DEFAULT_CONFIG`, `STROKE_GROUPS`, both normalizers and `ProfileAppearance`; `npm test` boots the built host half against a throwaway `$DSH_HOME` and asserts the whole round trip (disk + reload + profile), including the "ignoring unknown config field" warning staying silent.
111
- - **The caption band's left segment no longer swallows clicks.** Chromium collects `-webkit-app-region` items in paint order, and the drag annotation 0.3.7 put on the generated band segment (`::after`) overrode the `no-drag` holes the native caption menubar punches for its own buttons — the top-left navigation stopped responding while dragging still worked. The segment is paint-only now: `pointer-events:none` and no app-region declaration at all; the host's own `.frame::before` still carries the band's drag region.
112
- - **A modal's dim now reaches the caption strip.** The host's mask deliberately starts below the caption (`--dsh-frame-chrome-top` = the titlebar height) so the native drag strip keeps working, which left the top 40 px bright once a wallpaper was showing. The band is the plugin's own paint, so it dims itself while a modal exists — `[data-windows-titlebar]:has([role="dialog"][aria-modal="true"])`, with the host's own `--dsw-alias-bg-mask-1` and no interaction change. Measured in a browser: `box-shadow: none` closed → inset mask while open → none again.
113
- - **The sidebar toggle over the caption is readable again — and no longer painted over.** Two faults stacked on the same control. First, the band's left segment (0.3.7) was a positioned box painted AFTER the sidebar column in tree order, and that column becomes a stacking context whenever the sidebar blur is on, so the fixed toggle the host floats over the strip was being washed out by our own plate. Second, the toggle's ink comes from `--dsw-alias-label-secondary`, which the plugin flips white against the PICKED PALETTE, while the strip shows that palette at the **sidebar opacity** over the wallpaper: at 22% over a bright wallpaper the strip is light, and white ink disappeared (the reported desktop regression). The segment now paints at `z-index:-1` — above the wallpaper, below every control — and the caption strip derives its own ink from what it is actually painted on: past ~85% opacity the surface dominates and the palette direction decides, below it the wallpaper's brightness verdict does. It is published as `--dsh-any-caption-ink`, with a collapsed variant switched by the host's own `data-sidebar-collapsed` marker (a collapsed sidebar hands the whole strip back to the 标题栏 card), applied to the native caption menubar host and to the sidebar's fixed caption controls — the toggle and, while collapsed, the new-session button. Nothing else is re-inked, and the whole thing is paint only.
114
- - **The band has two owners ON PURPOSE.** The segment above the left sidebar follows the 「侧栏」 pair (same material literal, same blur mirror); everything right of the sidebar width follows the 「标题栏」 pair. That is why moving the header-bar sliders only changes the right part (issue #29 item 3) — the boundary is `--dsh-windows-sidebar-width`, published by the host, so it follows a dragged or collapsed sidebar by itself.
115
- - **The sidebar reads as ONE surface now, so its top strip and its body stop splitting.** `--dsw-specific-sidebar-fill` is a theme token the host ships OPAQUE, and three elements inside the sidebar's box each declare `background:var(--dsw-specific-sidebar-fill)` on top of one another: `AppFrame`'s `.sidebarCol` (the grid track), `SidebarRoot`'s `.root` (the shell inside it) and the workspace tree's `.fade` (a 24 px bottom gradient into that same fill). Over an opaque color that stacking is invisible; with the 「侧栏」 opacity slider it is not, and on the desktop it became a hard line — the caption strip above the sidebar is the plugin's own plate, painted with the same variable at the same alpha exactly once, so the strip sat at one density and the column under it at another (the reported desktop split). The token is now re-declared `transparent` for the column's descendants (`SIDEBAR_ONE_LAYER_RULE`), which leaves the outermost box as the single painter — the same owner the host already picked on macOS, where `SidebarRoot.module.css` clears its own `.root` fill for precisely this reason. Measured in a mock built from the installed bundles: before, column 0.22 over root 0.22 (≈0.39) against a 0.22 strip; after, one 0.22 everywhere. Bound by the CSS-Module class shape (`[class*="_sidebarCol"]`, identical in `0.2.0-rc.1` / `0.2.1-alpha.3` / `0.2.1-rc.2`), so a build that renames the track just keeps the untouched host look.
116
- - **The plugin-install dialog's npm-registry panel keeps the host's opacity.** `<fieldset data-install-registry>` is `createPortal`ed to `document.body` as a `position:fixed; z-index:1100` panel and paints from `--dsw-alias-bg-layer-2` (itself and its toggle) and `--dsw-alias-bg-layer-3` (the expanded toggle, the typed-address input) — tokens the 「卡片」 slider owns globally, so the panel faded with the card slider while the host's own comment on that rule says the layer is opaque *"to keep the registry form controls readable over the dialog"*. It joins the exemption set `applyExemptDefaults` already pins for confirm dialogs and the session-row menu: the current theme color at alpha 1, no translucency, nothing else re-inked or re-tinted, and the pin spelled for the subtree as well because a custom property travels downward and the options live inside it.
117
- - **The `0.2.1` line is one channel, and every checked build is named.** `0.2.1-alpha.3` moved the background-job list onto the shared `MenuSurface` — the surface root carries no `role`, and the fill plus the frost live on its `.material` child — so the runtime tagger now also claims body-level `[data-menu-material]` surfaces and the header selector set gained the matching arm; the older self-painting `<ul class*="_menu">` shape stays matched. Verified per tag from `alpha.3` through `rc.2`: no file the adapter speaks for moved (`design-platform.css`, `MenuSurface`, `MenuGroup`, `AppFrame`, `ConversationRoot`, `TaskMenu`, `preload-windows`, the five header slots). `SidebarRight.module.css` only gained `overflow:clip` on the panel wrapper (fixed floating children still escape), and the plugin-manager page was refactored with all three list anchors intact. The `0.2.1-alpha` and `0.2.1-rc` channels therefore collapse into one `0.2.1` channel covering `alpha.1`…`rc.2`, with a `SUPPORTED_RELEASES` row per build (each `exact`), `engines`/peers/`dsh.compatibility` naming them, and the folder renamed `v0-2-1`.
118
-
119
111
  ## Installation
120
112
 
121
113
  ### Method 1: npm install (Recommended)
@@ -158,8 +150,8 @@ pnpm dsh web
158
150
 
159
151
  ## Compatibility
160
152
 
161
- - **[`dsh web`](https://github.com/deepseek-ai/deepseek-harness) `0.2.0-rc.1` ~ `0.2.1-alpha.2`, and everything above it with it** — `engines.dsh`, the gated `@deepseek-ai/dsh-*` `peerDependencies` and `dsh.compatibility.dsh` name the builds this plugin was checked against one by one (`0.2.0-rc.1`, `0.2.0-rc.2`, `0.2.1-alpha.1`, `0.2.1-alpha.2`) and close with an uncapped `>=0.2.0-rc.1`, so every later release loads. The uncapped umbrella is the deliberate choice: the host enforces exactly this peer list — a release it does not name is disabled before a single module is imported — so a range that runs out is a wall in front of a plugin that would have gone on working. An unseen release gets the closest verified adapter plus a log line saying how far from `exact` that is, and the worst a stale guess can cost is one slider no longer fading a surface the host has since moved; a version check that failed closed would have cost the whole plugin. `dsh.compatibility.dshReleases` records which builds were checked and how: every release in the list was checked by diffing its tag against the adapter folder that answers for it. That enforcement still means a `dsh web` restart when the plugin is installed or updated — the check runs while the profile is composed, not when the plugin is updated — but the uncapped umbrella is what spares a machine that has already moved to a newer host from needing a plugin release or a manual exact-version exemption (`dsh plugin allow-version`) first. The host release is resolved on the Node half at runtime, and features that depend on a specific host release channel (the right Sidebar's panel blur, the official Sidebar's "Theme" card) enable themselves only where the corresponding host structure exists; everything else behaves identically across the range. THE `0.1.5` / `0.1.6` / `0.1.7` ERA IS OUT OF THE SUPPORTED RANGE: those adapter folders asserted facts nothing re-checks any more, and the range above now starts at `0.2.0-rc.1`, so an older host is refused at composition rather than quietly styled with the wrong adapter.
162
- - **Isolated per-version adaptation**: the release is resolved on the Node half from the app manifest the process was composed from (`ctx.profileContext.installAnchor`, with the launcher's on-disk layout behind it — the client context exposes no version) and, once handed down through the `read` RPC, is routed only by the front-layer adapter — `src/host-compat/` detects and buckets channels, while `src/client/host-compat/versions/` holds **one folder per set of verified facts** (`v0-2-0-rc-1` / `v0-2-0-rc-2` / `v0-2-1` / `unknown`), each describing that version's panel mechanics, header slot keys, plugin-page shape and where a menu's paint lives. A folder is keyed to what its facts cover, not to the shape of the version number: `0.2.0-rc.1` and `0.2.0-rc.2` are one prerelease channel, but rc.2 renamed the token a sticky menu group heading paints from, so the line carries two folders and the newer one is named for the build that opened it. A newer build whose facts did NOT move joins the folder that held instead of opening one of its own — the whole `0.2.1` line (`alpha.1` … `rc.2`) sits in `v0-2-1` for exactly that reason, with one `SUPPORTED_RELEASES` row per checked build so each verdict reads `exact` rather than `line`. Base code just asks the adapter questions (who owns the guide surface, which layer carries the blur, which token fades a menu) and never compares version strings. Another build on a verified patch line (`0.2.1-rc.3` against a table checked through `rc.2`) keeps that line's adapter, and a patch line nothing was checked against clamps to the nearest one with a log line saying so — which is the arm that now serves every release above `0.2.1-rc.2`. Only a release that will not parse at all falls into `unknown` and probes the DOM shape instead of guessing (`:has()` dual arms); supporting a new host means adding one folder and registering it.
153
+ - **[`dsh web`](https://github.com/deepseek-ai/deepseek-harness) `0.2.0-rc.1` ~ `0.2.1-rc.3`, and everything above it with it** — `engines.dsh`, the gated `@deepseek-ai/dsh-*` `peerDependencies` and `dsh.compatibility.dsh` name the builds this plugin was checked against one by one (`0.2.0-rc.1`, `0.2.0-rc.2`, `0.2.1-alpha.1` … `0.2.1-rc.3`) and close with an uncapped `>=0.2.0-rc.1`, so every later release loads. The uncapped umbrella is the deliberate choice: the host enforces exactly this peer list — a release it does not name is disabled before a single module is imported — so a range that runs out is a wall in front of a plugin that would have gone on working. An unseen release gets the closest verified adapter plus a log line saying how far from `exact` that is, and the worst a stale guess can cost is one slider no longer fading a surface the host has since moved; a version check that failed closed would have cost the whole plugin. `dsh.compatibility.dshReleases` records which builds were checked and how: every release in the list was checked by diffing its tag against the adapter folder that answers for it. That enforcement still means a `dsh web` restart when the plugin is installed or updated — the check runs while the profile is composed, not when the plugin is updated — but the uncapped umbrella is what spares a machine that has already moved to a newer host from needing a plugin release or a manual exact-version exemption (`dsh plugin allow-version`) first. The host release is resolved on the Node half at runtime, and features that depend on a specific host release channel (the right Sidebar's panel blur, the official Sidebar's "Theme" card) enable themselves only where the corresponding host structure exists; everything else behaves identically across the range. THE `0.1.5` / `0.1.6` / `0.1.7` ERA IS OUT OF THE SUPPORTED RANGE: those adapter folders asserted facts nothing re-checks any more, and the range above now starts at `0.2.0-rc.1`, so an older host is refused at composition rather than quietly styled with the wrong adapter.
154
+ - **Isolated per-version adaptation**: the release is resolved on the Node half from the app manifest the process was composed from (`ctx.profileContext.installAnchor`, with the launcher's on-disk layout behind it — the client context exposes no version) and, once handed down through the `read` RPC, is routed only by the front-layer adapter — `src/host-compat/` detects and buckets channels, while `src/client/host-compat/versions/` holds **one folder per set of verified facts** (`v0-2-0-rc-1` / `v0-2-0-rc-2` / `v0-2-1` / `unknown`), each describing that version's panel mechanics, header slot keys, plugin-page shape and where a menu's paint lives. A folder is keyed to what its facts cover, not to the shape of the version number: `0.2.0-rc.1` and `0.2.0-rc.2` are one prerelease channel, but rc.2 renamed the token a sticky menu group heading paints from, so the line carries two folders and the newer one is named for the build that opened it. A newer build whose facts did NOT move joins the folder that held instead of opening one of its own — the whole `0.2.1` line (`alpha.1` … `rc.3`) sits in `v0-2-1` for exactly that reason, with one `SUPPORTED_RELEASES` row per checked build so each verdict reads `exact` rather than `line`. Base code just asks the adapter questions (who owns the guide surface, which layer carries the blur, which token fades a menu) and never compares version strings. Another build on a verified patch line (a future `0.2.1-rc.4` against a table checked through `rc.3`) keeps that line's adapter, and a patch line nothing was checked against clamps to the nearest one with a log line saying so — which is the arm that now serves every release above `0.2.1-rc.3`. Only a release that will not parse at all falls into `unknown` and probes the DOM shape instead of guessing (`:has()` dual arms); supporting a new host means adding one folder and registering it.
163
155
  - **[DSHA](https://github.com/DSH-APP/DSHA)** — DeepSeek Harness Android launcher (ROOT-free, Termux-free). Its bundled `dsh` is `0.1.5-rc.2`, BELOW this plugin's supported floor since v0.3.7: the peer gate refuses it at composition, so the plugin never loads there rather than restyling that shell with 0.2.x facts.
164
156
  - **[deepseek-harness-desktop](https://github.com/anywhere-labs/deepseek-harness-desktop)** — Supported
165
157
 
package/README.zh.md CHANGED
@@ -4,7 +4,7 @@
4
4
  <a href="https://www.npmjs.com/package/dsh-any-background"><img alt="npm 版本" src="https://img.shields.io/npm/v/dsh-any-background?color=4d6bfe"></a>
5
5
  <a href="https://www.npmjs.com/package/dsh-any-background"><img alt="npm 月下载量" src="https://img.shields.io/npm/dm/dsh-any-background?color=4d6bfe"></a>
6
6
  <a href="https://github.com/Tkingxiao/dsh-any-background/blob/main/LICENSE"><img alt="License: MIT" src="https://img.shields.io/npm/l/dsh-any-background?color=4d6bfe"></a>
7
- <a href="https://www.npmjs.com/package/@deepseek-ai/dsh?activeTab=versions"><img alt="支持的 DSH 版本:0.2.0-rc.1 ~ 0.2.1-rc.2 及其上" src="https://img.shields.io/badge/DSH-0.2.0--rc.1%20~%200.2.1--rc.2%2B-4d6bfe" /></a>
7
+ <a href="https://www.npmjs.com/package/@deepseek-ai/dsh?activeTab=versions"><img alt="支持的 DSH 版本:0.2.0-rc.1 ~ 0.2.1-rc.3 及其上" src="https://img.shields.io/badge/DSH-0.2.0--rc.1%20~%200.2.1--rc.3%2B-4d6bfe" /></a>
8
8
  <a href="https://github.com/topics/dsh-better-sidebar"><img alt="插件生态:GitHub topic dsh-better-sidebar" src="https://img.shields.io/badge/%E6%8F%92%E4%BB%B6%E7%94%9F%E6%80%81-topic%20dsh--better--sidebar-4d6bfe" /></a><br /><br />
9
9
  <a href="https://github.com/Tkingxiao/dsh-any-background"><img src="https://img.shields.io/github/stars/Tkingxiao/dsh-any-background?style=social" alt="GitHub stars"></a>
10
10
  <a href="https://dsh.directory/plugins/tkingxiao/dsh-any-background"><img src="https://dsh.directory/badges/listed.svg" alt="dsh.directory listed"></a>
@@ -12,7 +12,7 @@
12
12
 
13
13
  [English](README.md) | 中文
14
14
 
15
- 一个 **DeepSeek Harness** 外观插件:自定义主题色、背景壁纸(图片 / 视频 / 算法动态生成),以及逐表面的透明度与模糊度控制。兼容 **DSH `0.2.0-rc.1` 直至 `0.2.1-rc.2`,其上所有版本一并放行**(官方右侧栏「主题」卡片等界面按宿主是否提供右侧栏注册表扩展点自动启用,缺失时静默跳过)。
15
+ 一个 **DeepSeek Harness** 外观插件:自定义主题色、背景壁纸(图片 / 视频 / 算法动态生成),以及逐表面的透明度与模糊度控制。兼容 **DSH `0.2.0-rc.1` 直至 `0.2.1-rc.3`,其上所有版本一并放行**(官方右侧栏「主题」卡片等界面按宿主是否提供右侧栏注册表扩展点自动启用,缺失时静默跳过)。
16
16
 
17
17
  ---
18
18
 
@@ -93,6 +93,10 @@
93
93
 
94
94
  ## 更新日志(只保留最近两个版本)
95
95
 
96
+ ### v0.3.10(0.2.1-rc.3 过检:SUPPORTED_RELEASES 多一行,事实零新增)
97
+
98
+ - **`0.2.1-rc.3` 从「收边夹取的猜测」变成「逐项核对过的构建」。** 对 `0.2.1` 适配层发言的每一个文件跑 `git diff rc.2 rc.3`:`design-platform.css`、两份菜单样式表、`MenuGroup.tsx` 逐字节一致,`SidebarRight.module.css`、`TabLayout.tsx`、`base.css`、`gradient-shadow-text.css`、`AppFrame.*`、`InlineEditor.module.css`、`TextShimmer`、`JobListAction`、`TaskMenu`、`scoped-slots`、`PluginManagerPage.tsx` 也全部未动,五个头部槽位键原样成立。事实不变,所以 rc.3 并入 `v0-2-1`、只添一条 `SUPPORTED_RELEASES` 行——判定从 `line` 升为 `exact`——该 tag 真正动了的东西记在目录头注释里:`Menu.tsx` 是纯增量(渲染 `aria-current`、portal 模式下写一个 `min-width`,没有任何样式表随行迁移);guide 与侧栏面板列表在**既有注册的外围**长出 pin 状态和 More 菜单,而 `native-tab.tsx` 对话的那个 tab 注册表(`shell/`)原封未动;会话头部新增的 View 行 More 菜单经 `<Menu … portal>` 挂到 `document.body`,标记器的 portal 分支本来就会认领它;`ConversationRoot.module.css` 只重排了 View 标签行。`engines.dsh`、六个受门禁的 `@deepseek-ai/dsh-*` peer、`dsh.compatibility.dsh` 与 `dsh.compatibility.dshReleases` 均已点名 `0.2.1-rc.3`。
99
+
96
100
  ### v0.3.9(issue #30:条带墨色改由用户裁定;顶栏那对滑块重新管住所有头部浮层)
97
101
 
98
102
  - **「标题条带文字」现在是一个选项(issue #30)。** 0.3.8 让条带墨色跟随它实际被画在什么上,这修好了「白色开合按钮在亮条带上消失」——但也让暗色主题下、侧栏半透明压在亮壁纸上时,原生菜单条(「应用 / 编辑」)变成黑色,因为那一段条带确实是亮的。同一个场景,两份反馈要的是相反的赢家,所以这个取舍交给用户:「标题栏」卡片新增「标题条带文字」——**自动**保持 0.3.8 的推导;**跟随主题**完全不发射覆盖(菜单条与侧栏 fixed 在条带上的控件读宿主自己的标签令牌,即 0.3.7 及之前的样子);**始终白色 / 始终黑色**钉死。这个键同样补进了宿主半侧的白名单(#28 的教训是:只有一侧认识的键会在写盘时被静默丢弃),`npm test` 会把「落盘 → 重读」跑一遍,并断言未知值塌回 `auto`。
@@ -102,18 +106,6 @@
102
106
  - **菜单模糊滑块拉到 0,现在就是没有磨砂。** 0.3.7 加过一个 `<html>` 类门控(`dab-card-frost` / `dab-header-frost`),让停在 0 的滑块不去抹宿主自己的 `--dsw-menu-backdrop-filter: blur(40px) saturate(150%)`(元素自身声明恒胜继承,所以未门控的 `var(--x, none)` 确实会清掉它)。事后看这个取舍是错的:它把滑块的**下端变成了最糊的一端**(0 → 宿主的 40px,1 → 1px),于是「把模糊度关掉」根本够不到,用户恰恰在那个位置上觉得控件是死的。现在这个 frost 令牌在每个取值上都被声明,0 时由 `none` 兜底胜出,门控机制整体删除。不会有人因此丢掉宿主观感:每个部件的默认值都是 30px,全新安装依旧是磨砂的,只有明确拖到 0 才会清掉。
103
107
  - **版本表不动。** 上面这些形状都对着安装产物里的 `0.2.0-rc.1`、`0.2.1-alpha.3`、`0.2.1-rc.2` 三个构建复核过:两个 utilities 控件、`MenuSurface` 的 `data-menu-material` + `.material` 绘制层、菜单令牌集合三处一致,`0.2.1` 适配层的事实继续成立。
104
108
 
105
-
106
- ### v0.3.8(issue #28/#29 与桌面端侧栏:「标题栏」设置能落盘了,条带不再吞点击,模态蒙版够到标题区,侧栏重新是一个面)
107
-
108
- - **「标题栏」的三项设置现在重启后还在。** 宿主半侧在写盘前会按白名单归一化(`normalizeConfig` → `theme-config.json`),而它那份配置形状一直没学会这张卡的三把键:`blurs.headerBar` 回落到 30px、`strokes.headerBar` 回落到 0 宽、`headerBarOpacity` 在写盘时被整条丢掉——浏览器半侧读回时又用自己的默认值回填(`clamp01(undefined,.5) → 50%`),于是看起来"保存成功、刷新即还原"。保存 Profile 的归一化器有同一个洞,还额外丢了 `blurs.header`。现在三把键都补进了宿主的 `PartBlurs`、`DEFAULT_CONFIG`、`STROKE_GROUPS`、两个归一化器和 `ProfileAppearance`;`npm test` 会用一个临时 `$DSH_HOME` 启起真正的宿主半侧,把「落盘 → 重读 → Profile」整条往返跑一遍,并断言不再出现 `ignoring unknown config field` 警告。
109
- - **条带左段不再吞掉点击。** Chromium 按绘制顺序收集 `-webkit-app-region` 区域,0.3.7 给生成出来的那一段(`::after`)加的 drag 标注盖过了原生标题栏菜单为自己的按钮打出的 `no-drag` 洞——左上角导航点不动,而拖动窗口仍正常。这一段现在只负责绘制:`pointer-events:none`,并且完全不再声明 app-region;整条条带的拖拽区仍由宿主自己的 `.frame::before` 提供。
110
- - **模态蒙版现在也能盖住标题条带。** 宿主的蒙版故意从标题栏下方开始(`--dsh-frame-chrome-top` = 标题栏高度),为的是保住原生拖拽条;结果壁纸一开,顶部 40px 就成了一条亮带。条带是本插件自己的绘制,所以模态存在时它自己变暗——`[data-windows-titlebar]:has([role="dialog"][aria-modal="true"])`,用的是宿主自己的 `--dsw-alias-bg-mask-1`,不改变任何交互。浏览器实测:关闭时 `box-shadow: none` → 打开时 inset 蒙版 → 关闭后恢复 none。
111
- - **压在这条条带上的侧栏开合按钮重新看得见了,也不再被自身涂盖。** 同一个控件上叠了两个问题:其一,0.3.7 画的条带左段是一个定位盒子,在树序上**排在侧栏列之后**,而侧栏一开模糊就会成为层叠上下文——于是宿主固定在条带上的那个按钮被我们自己的板子冲淡;其二,按钮的墨色来自 `--dsw-alias-label-secondary`,插件是按**选定的主题色**把它翻成白色的,可条带显示的是该调色板在**侧栏透明度**下叠在壁纸上的结果:22% 不透明度压在明亮壁纸上,条带是浅色,白字就消失了(这次桌面端反馈的现象)。现在这一段以 `z-index:-1` 绘制——高于壁纸、低于所有控件;同时条带按它**实际被画在什么上**推导自己的墨色:不透明度约 85% 以上由表面色说了算(跟随调色板方向),低于此值由壁纸明暗判定说了算。结果发布为 `--dsh-any-caption-ink`,并带一个折叠态变体(用宿主自己的 `data-sidebar-collapsed` 标记切换——侧栏折叠后整条条带交还「标题栏」卡片),应用到原生标题栏菜单宿主,以及侧栏自己固定在条带上的控件(开合按钮,折叠时的新建会话按钮)。其它任何地方都不重新上色,且全程只是绘制层面。
112
- - **条带是「两个主人」,这是设计。** 左侧栏上方那一段归「侧栏」这一对滑块(同一份材质、同一份模糊镜像);侧栏宽度右侧全部归「标题栏」。所以移动标题栏滑块只会改变右段(issue #29 第 3 条)——分界就是宿主发布的 `--dsh-windows-sidebar-width`,拖动或折叠侧栏时它自己会跟着走。
113
- - **侧栏重新读作「一个表面」,它的顶部与下方不再分层。** `--dsw-specific-sidebar-fill` 是宿主以**不透明**发布的主题令牌,而侧栏这个盒子里有三个元素各自声明了 `background:var(--dsw-specific-sidebar-fill)` 互相叠涂:`AppFrame` 的 `.sidebarCol`(网格列)、其内 `SidebarRoot` 的 `.root`(外壳本身)、以及工作区树那条 `.fade`(24px 渐变到底色)。底色不透明时叠几层看不出来,一交给「侧栏」透明度滑块就不是了;桌面端尤其明显——侧栏上方那条标题带是本插件自己的板子,用同一个变量、同一个不透明度只画一次,于是条带一个浓度、下面的列另一个浓度(就是这次桌面端反馈的分层)。现在这个令牌在列的**后代**上被重新声明为 `transparent`(`SIDEBAR_ONE_LAYER_RULE`),让最外层那个盒子成为唯一的绘制者——这也是宿主自己在 macOS 上的选择,`SidebarRoot.module.css` 正是为此把 `.root` 的底色清空。用宿主安装产物搭的 mock 实测:修前列 0.22 叠 `.root` 0.22(≈0.39)对 0.22 的条带;修后处处都是同一个 0.22。绑定用的是 CSS-Module 的类名形状(`[class*="_sidebarCol"]`,`0.2.0-rc.1` / `0.2.1-alpha.3` / `0.2.1-rc.2` 三处一致),所以哪个构建改了名,就只是回到未改动的宿主样子。
114
- - **插件安装对话框里的「npm 源」面板保持宿主的不透明度。** `<fieldset data-install-registry>` 被 `createPortal` 到 `document.body`,是一个 `position:fixed; z-index:1100` 的面板,底色取自 `--dsw-alias-bg-layer-2`(面板自身与它的开关)和 `--dsw-alias-bg-layer-3`(展开态开关、手填地址的输入框)——这些都是「卡片」滑块全局接管的令牌,于是这块面板跟着卡片滑块一起变透明;而宿主写在那条规则上的注释恰恰相反:这层之所以不透明,是为了"让源选择表单控件压在对话框上仍然可读"。它因此并入 `applyExemptDefaults` 已经在维护的那组豁免(确认对话框、会话行菜单):保持当前主题色、把 alpha 钉在 1,不撤模糊也不改字色,其它一律不动;钉的值同样要覆盖其子树,因为自定义属性只会向下传播,选项就在里面。
115
- - **`0.2.1` 整条线合成一个渠道,并逐构建点名。** `0.2.1-alpha.3` 把后台任务列表改画到共享的 `MenuSurface` 上——表面根没有 `role`,底色与磨砂落到了它的 `.material` 子层——所以运行时标记器现在也会认领 body 级的 `[data-menu-material]` 表面,顶栏选择器组同步加了对应分支;更早那种自己上色的 `<ul class*="_menu">` 形状继续匹配。从 `alpha.3` 到 `rc.2` 逐 tag 核对:适配层发言的文件一个都没动(`design-platform.css`、`MenuSurface`、`MenuGroup`、`AppFrame`、`ConversationRoot`、`TaskMenu`、`preload-windows`、五个头部槽位)。`SidebarRight.module.css` 只给面板外层加了 `overflow:clip`(fixed 浮动子节点仍会逃逸),插件页重构过但三个列表锚点都在。于是 `0.2.1-alpha` 与 `0.2.1-rc` 合为一个 `0.2.1` 渠道,覆盖 `alpha.1`…`rc.2`,每个构建一条 `SUPPORTED_RELEASES` 行(均为 `exact`),`engines`/peer/`dsh.compatibility` 逐一点名,事实目录改名为 `v0-2-1`。
116
-
117
109
  ## 安装
118
110
 
119
111
  ### 方式一:npm 安装(推荐)
@@ -156,8 +148,8 @@ pnpm dsh web
156
148
 
157
149
  ## 兼容性
158
150
 
159
- - **[`dsh web`](https://github.com/deepseek-ai/deepseek-harness) `0.2.0-rc.1` ~ `0.2.1-alpha.2`,其上所有版本一并放行** — `engines.dsh`、受门禁的 `@deepseek-ai/dsh-*` `peerDependencies` 与 `dsh.compatibility.dsh` 先逐一列出本插件核对过的构建(`0.2.0-rc.1`、`0.2.0-rc.2`、`0.2.1-alpha.1`、`0.2.1-alpha.2`),再以不设上界的 `>=0.2.0-rc.1` 收尾,让其后每一个 release 都能加载。不设上界是有意选的:宿主强制的正是这份 peer 列表——范围没写到的版本会在导入任何模块之前被整行禁用——一条写到头的范围等于在一款还能正常工作的插件前面砌墙。没见过的 release 会取最近的一份事实,并在日志里写清它离 `exact` 有多远;一份过期事实最坏的代价是某个滑块不再淡出宿主已经搬走的那个表面,而一道失败关闭的版本检查代价是整个插件。`dsh.compatibility.dshReleases` 记录哪些构建被核对过、怎么核对的:列表里的每个 release 都是按 tag 逐包比对其事实目录核实的。这道门禁也意味着安装或更新插件后仍需重启 `dsh web`——检查发生在 profile 组装时,而不是插件更新时——但不设上界的总括,正让已经升到更新宿主的机器不再需要先等插件发版(或手工授予精确版本豁免 `dsh plugin allow-version`)。宿主版本在运行时由 Node 半侧解析,依赖特定宿主版本渠道的功能(右侧栏面板模糊、官方侧栏「主题」卡片)只在对应宿主结构存在时启用,其余功能在整个范围内表现一致。**`0.1.5` / `0.1.6` / `0.1.7` 这一档已移出兼容范围**:那些事实目录断言的东西已经没有再被核对,而一张没人核对的表比没有表更糟;范围从 `0.2.0-rc.1` 起步,意味着更旧的宿主会在组装期被明确拒绝,而不是被一份错的适配事实悄悄改版式。
160
- - **版本适配隔离**:release 由 Node 半侧从进程自身那份 `@deepseek-ai/dsh/package.json` 读出(客户端上下文不暴露版本;`ctx.profileContext.installAnchor` 指不到时退回启动器的磁盘布局),经 `read` RPC 下发后只由前置适配层路由——`src/host-compat/` 负责探测与渠道归类,`src/client/host-compat/versions/` 下**每个事实集合一个目录**(`v0-2-0-rc-1` / `v0-2-0-rc-2` / `v0-2-1` / `unknown`),各自描述该版本的面板力学、头部槽位键、插件页形状,以及菜单的底色与磨砂落在哪一层。目录按它覆盖的事实命名,不按版本号的形状:`0.2.0-rc.1` 与 `0.2.0-rc.2` 同属一个预发布渠道,但 rc.2 改了吸顶菜单分组标题取色的令牌,于是这条补丁行上并着两个目录,较新的那个按开启它的那个构建命名。**事实没变的更新版本不新开目录,而是并入那份仍然成立的事实目录**——整条 `0.2.1` 线(`alpha.1` … `rc.2`)正因如此都坐在 `v0-2-1` 里,每个核对过的构建各占一条 `SUPPORTED_RELEASES` 行,判定都是 `exact` 而不是 `line`。底码只向适配层提问(引导页表面归谁、模糊挂在哪一层、菜单该重写哪些令牌),不比较版本字符串。同一补丁行内的其它构建(`0.2.1-rc.3` 之于核对基准 `rc.2`)用该行的档位;整条补丁行都不在已核对范围内才收边取最近的一档并写日志——`0.2.1-rc.2` 之上的每一个 release 如今就是靠这一档加载的。只有解析不到 release 时归入 `unknown`,回退到按 DOM 形状探测(`:has()` 双臂)而不是猜一个版本;适配新宿主 = 新增一个版本目录并在注册表登记。
151
+ - **[`dsh web`](https://github.com/deepseek-ai/deepseek-harness) `0.2.0-rc.1` ~ `0.2.1-rc.3`,其上所有版本一并放行** — `engines.dsh`、受门禁的 `@deepseek-ai/dsh-*` `peerDependencies` 与 `dsh.compatibility.dsh` 先逐一列出本插件核对过的构建(`0.2.0-rc.1`、`0.2.0-rc.2`、`0.2.1-alpha.1` … `0.2.1-rc.3`),再以不设上界的 `>=0.2.0-rc.1` 收尾,让其后每一个 release 都能加载。不设上界是有意选的:宿主强制的正是这份 peer 列表——范围没写到的版本会在导入任何模块之前被整行禁用——一条写到头的范围等于在一款还能正常工作的插件前面砌墙。没见过的 release 会取最近的一份事实,并在日志里写清它离 `exact` 有多远;一份过期事实最坏的代价是某个滑块不再淡出宿主已经搬走的那个表面,而一道失败关闭的版本检查代价是整个插件。`dsh.compatibility.dshReleases` 记录哪些构建被核对过、怎么核对的:列表里的每个 release 都是按 tag 逐包比对其事实目录核实的。这道门禁也意味着安装或更新插件后仍需重启 `dsh web`——检查发生在 profile 组装时,而不是插件更新时——但不设上界的总括,正让已经升到更新宿主的机器不再需要先等插件发版(或手工授予精确版本豁免 `dsh plugin allow-version`)。宿主版本在运行时由 Node 半侧解析,依赖特定宿主版本渠道的功能(右侧栏面板模糊、官方侧栏「主题」卡片)只在对应宿主结构存在时启用,其余功能在整个范围内表现一致。**`0.1.5` / `0.1.6` / `0.1.7` 这一档已移出兼容范围**:那些事实目录断言的东西已经没有再被核对,而一张没人核对的表比没有表更糟;范围从 `0.2.0-rc.1` 起步,意味着更旧的宿主会在组装期被明确拒绝,而不是被一份错的适配事实悄悄改版式。
152
+ - **版本适配隔离**:release 由 Node 半侧从进程自身那份 `@deepseek-ai/dsh/package.json` 读出(客户端上下文不暴露版本;`ctx.profileContext.installAnchor` 指不到时退回启动器的磁盘布局),经 `read` RPC 下发后只由前置适配层路由——`src/host-compat/` 负责探测与渠道归类,`src/client/host-compat/versions/` 下**每个事实集合一个目录**(`v0-2-0-rc-1` / `v0-2-0-rc-2` / `v0-2-1` / `unknown`),各自描述该版本的面板力学、头部槽位键、插件页形状,以及菜单的底色与磨砂落在哪一层。目录按它覆盖的事实命名,不按版本号的形状:`0.2.0-rc.1` 与 `0.2.0-rc.2` 同属一个预发布渠道,但 rc.2 改了吸顶菜单分组标题取色的令牌,于是这条补丁行上并着两个目录,较新的那个按开启它的那个构建命名。**事实没变的更新版本不新开目录,而是并入那份仍然成立的事实目录**——整条 `0.2.1` 线(`alpha.1` … `rc.3`)正因如此都坐在 `v0-2-1` 里,每个核对过的构建各占一条 `SUPPORTED_RELEASES` 行,判定都是 `exact` 而不是 `line`。底码只向适配层提问(引导页表面归谁、模糊挂在哪一层、菜单该重写哪些令牌),不比较版本字符串。同一补丁行内的其它构建(将来的 `0.2.1-rc.4` 之于核对基准 `rc.3`)用该行的档位;整条补丁行都不在已核对范围内才收边取最近的一档并写日志——`0.2.1-rc.3` 之上的每一个 release 如今就是靠这一档加载的。只有解析不到 release 时归入 `unknown`,回退到按 DOM 形状探测(`:has()` 双臂)而不是猜一个版本;适配新宿主 = 新增一个版本目录并在注册表登记。
161
153
  - **[DSHA](https://github.com/DSH-APP/DSHA)** — DeepSeek Harness 安卓启动器(免 ROOT、免 Termux)。其包内 dsh 为 `0.1.5-rc.2`,自 v0.3.7 起**低于本插件的兼容下界**:peer 门禁会在组装期拒绝它,所以插件在那上面根本不加载,而不是拿 0.2.x 的事实去改版那个壳。
162
154
  ## 权限、副作用与边界
163
155
 
package/lib/client.js CHANGED
@@ -1087,6 +1087,10 @@ window.__ModuleLoader__.load({
1087
1087
  {
1088
1088
  channel: "0.2.1",
1089
1089
  release: "0.2.1-rc.2"
1090
+ },
1091
+ {
1092
+ channel: "0.2.1",
1093
+ release: "0.2.1-rc.3"
1090
1094
  }
1091
1095
  ];
1092
1096
  const UNKNOWN_HOST_INFO = {
@@ -1563,7 +1567,7 @@ window.__ModuleLoader__.load({
1563
1567
  //#region src/client/host-compat/versions/v0-2-1/adapter.ts
1564
1568
  /**
1565
1569
  * Adapter for the DSH `0.2.1` patch line, verified at `0.2.1-alpha.1`,
1566
- * `alpha.2`, `alpha.3`, `alpha.4`, `alpha.5`, `rc.1` and `rc.2`.
1570
+ * `alpha.2`, `alpha.3`, `alpha.4`, `alpha.5`, `rc.1`, `rc.2` and `rc.3`.
1567
1571
  *
1568
1572
  * A new MINOR line opened with a prerelease, and the answer is the `0.2.0-rc.2`
1569
1573
  * folder's — which is a statement this file has to earn, because "same as the
@@ -1587,6 +1591,34 @@ window.__ModuleLoader__.load({
1587
1591
  * · `TextShimmer` still marks its root `data-shimmer`, so the stroke exemption
1588
1592
  * written for rc.1 stands.
1589
1593
  *
1594
+ * Re-checked at `0.2.1-rc.3` (`git diff rc.2 rc.3` on every file above), the
1595
+ * facts hold untouched: `design-platform.css`, both menu stylesheets and
1596
+ * `MenuGroup.tsx` byte-identical; `SidebarRight.module.css`, `TabLayout.tsx`,
1597
+ * `base.css`, `gradient-shadow-text.css`, `AppFrame.*`, `InlineEditor.module.css`,
1598
+ * `TextShimmer`, `JobListAction`, `TaskMenu`, `scoped-slots` and
1599
+ * `PluginManagerPage.tsx` all unchanged, and the five header slot keys stand.
1600
+ * What rc.3 did move, and why none of it needs a fact from this folder:
1601
+ * · `ui-primitives/Menu.tsx` is ADDITIVE — a `current` prop that renders
1602
+ * `aria-current="page"` and a `minWidthFromAnchor` switch that sets a
1603
+ * `min-width` style in portal mode. No stylesheet moved with it
1604
+ * (`MenuSurface.module.css` is byte-identical), so the menu paint and the
1605
+ * frost stay exactly where the facts say.
1606
+ * · the guide (`GuideBody.tsx`) and the sidebar panel list (`SidebarRoot.tsx`)
1607
+ * grow pin state and a More menu AROUND the existing registrations — guide
1608
+ * entries still arrive through `useGuideEntries`, panels through
1609
+ * `selectPanel`, and the new menus mount empty until something registers
1610
+ * into their `*.actions` slots, which this plugin does not. The tab
1611
+ * registry itself (`shell/`), which `native-tab.tsx` speaks to, is untouched.
1612
+ * · the session header's View tab row gained its own More menu
1613
+ * (`conversation.session.header.views.actions` slot). It mounts through
1614
+ * `<Menu … portal>` to `document.body`, so `header-tag.ts` already claims
1615
+ * it through the portaled arm — the trigger sits in the header and reports
1616
+ * `aria-expanded`, which is all that arm asks. The five in-place header
1617
+ * slot anchors are unchanged.
1618
+ * · `ConversationRoot.module.css` re-laid the View tab row (wrap, gaps, the
1619
+ * More launcher's classes). Layout inside the header, not a surface the
1620
+ * plugin styles by these class names.
1621
+ *
1590
1622
  * Re-checked again across the rest of the line (`alpha.3` … `rc.2`, `git diff
1591
1623
  * <tag> rc.2` on every file above): the menu token contract, both menu stylesheets
1592
1624
  * (`MenuSurface`, `MenuGroup`), `gradient-shadow-text.css` / `base.css`,
@@ -1678,7 +1710,7 @@ window.__ModuleLoader__.load({
1678
1710
  }
1679
1711
  function createAdapter$1(host) {
1680
1712
  return {
1681
- id: "0.2.1-alpha.1…rc.2",
1713
+ id: "0.2.1-alpha.1…rc.3",
1682
1714
  channel: "0.2.1",
1683
1715
  host,
1684
1716
  panelFragments: panelFragments$1,
@@ -4734,7 +4766,8 @@ window.__ModuleLoader__.load({
4734
4766
  *
4735
4767
  * Bound by the CSS-Module class shape, same as `[class*="_ioCard"]`: the built
4736
4768
  * bundle names these `pI_x6G_sidebarCol` — prefix first, local name last, and the
4737
- * pair is identical across `0.2.0-rc.1`, `0.2.1-alpha.3` and `0.2.1-rc.2`. A build
4769
+ * pair is identical across `0.2.0-rc.1`, `0.2.1-alpha.3`, `0.2.1-rc.2` and
4770
+ * `0.2.1-rc.3` (`AppFrame.module.css` byte-identical rc.2→rc.3). A build
4738
4771
  * that renames the track simply stops matching, which is the untouched host look. */
4739
4772
  const SIDEBAR_ONE_LAYER_RULE = "[class*=\"_sidebarCol\"] *{--dsw-specific-sidebar-fill:transparent}";
4740
4773
  const PART_BLUR_RULE = `.${PART_BLUR_CLASS}{isolation:isolate}.${PART_BLUR_CLASS}:has([role="dialog"]){isolation:auto}.${PART_UNDERLAY_CLASS}{position:absolute;inset:0;z-index:-1;pointer-events:none;border-radius:inherit;backdrop-filter:var(--dsh-any-part-blur,none);-webkit-backdrop-filter:var(--dsh-any-part-blur,none)}`;