# STYLE-SCOPE-GUARD —— 「我们注入的 CSS 只准命中自己的标记」自动护栏 > 对应门禁:`tools/check.sh` 第 12 步(`node tools/style-scope-guard.mjs`,全量模式)。 > 判据产物:`tools/probe-out/style-scope.json`(`.gitignore` 已忽略)。 > 该护栏的由来是两次真实事故:**右侧轮次导航条被弄透明**(`TIMELINE-RAIL-TOKEN.md`)与 > **顶栏下描边被抹掉**(`HEADER-FROST.md` §0b)。两次都不是"某一行写错",而是**选择器作用域没人管**。 --- ## 1. 判据(四类,逐条会给 `lib/client.js:<行号>`) | 分类 | 含义 | 处理 | |---|---|---| | **OK** | 选择器命中我们自己的标记:`.mpw*` / `[data-mpw*]` / `#mpw-*` / `[data-plugin="dsh-mpkg-wallpaper"]` | 放行 | | **ALLOWLISTED** | 命中**已登记**的宿主/第三方作用域(§2 账本,每条带 reason + `docs/*.md:行号` 指针) | 放行 | | **REVIEW** | 未登记、判不了(新宿主类名 / 新作用域 / 未登记的宿主 token) | **判红**:必须先登记 | | **RED** | 明确违规(见 §3) | 判红 | 判红的硬规则(`ALLOWLIST` 洗不白): 1. **裸元素 / 裸 `*` / 无锚点**:`button{…}`、`div{…}`、`*{…}`,或整条选择器既没有我们的标记、也没有已登记的宿主作用域 (例:`[class*="_dhs-unknown"]{…}`)⇒ RED。元素选择器(`button`/`header`/`svg`…)与通用类名子串 (`card`/`row`/`panel`/`fade`…)**只能作为已锚定选择器里的细化**,裸出现即红。 2. **`:root` 上出现非 `--mpw-*` 声明** ⇒ RED(宿主 token 定义在 `body` 上,从 `:root` 覆盖属于越界改宿主主题)。 裸 `html`/`body` 只允许 `background*` 与§4 登记表里的宿主 token,其它属性(含未登记 token)⇒ RED。 3. **宿主 token**: * 把宿主 token 设成 `transparent`/`inherit`/`unset`/`none`/空 ⇒ RED(这是"整块界面变透明/失色"的机制)。 唯一白名单:`--dsw-specific-sidebar-fill` 落在文档点名的**侧栏白名单容器**上(`TIMELINE-RAIL-TOKEN.md:63`)。 * 覆盖 rail 依赖的 `--dsw-alias-border-l4` / `--dsw-alias-label-primary`:必须门控在 `[data-mpw*]` 上且值非 degenerate ⇒ 否则 RED。 * 对**未登记**的宿主 token 加 `!important` ⇒ RED。 4. **禁止锚点**: * rail 家族(`.eGxaPq_*` / `.Y0dWHa_*` / `qBU-ya` / `_1p9O6q_` / `turn-rail`):只有两处白名单—— `body[data-mpw-rail-ink]` 下的对比补偿(**不得含 `!important`、不得引用/重定义任何 `--dsw-*`**)、 `data-mpw-traject-clip` 门控下**仅几何属性**(`overflow*`/`max-width`/`box-sizing`…)的裁剪 ⇒ 其余一律 RED。 * 会话区容器(`[data-slot*="session"]` 等):历史事故是把对话流整条 `display:none` ⇒ 只有带我们自有门控 (`[data-mpw*]`,例:`body[data-mpw-aqua-text] [data-slot*="conversation"] …` 的文字可读性补偿)才放行,未门控一律 RED。 * `[data-dsh-panel-host]`(宿主 fixed 全屏层)⇒ RED(文档明确"不要碰")。 5. **顶栏描边**:选择器命中 `wSkVaW_header` / `_header_` 且写 `border*: …transparent !important` ⇒ RED。 --- ## 2. 允许清单账本(`ALLOWLIST`,35 条) `docKind=existing` = 仓内既有文档本来就写了这件事;`docKind=ledger` = 既有文档没写,**在本表首次登记**(理由是代码注释里的功能语义 + 该作用域在真机 DOM 契约里的位置)。 | id | 层 | 作用域 | 理由 | 依据 | |---|---|---|---|---| | `ours:class` | anchor | `.mpw*` | 插件自有 UI 类名(面板控件 / 壁纸层 / 磨砂层) | 本表 | | `ours:data-mpw` | anchor | `[data-mpw*]` | 插件自有状态标记(门控用;宿主永不带 `data-mpw-*`) | 本表 | | `ours:id` | anchor | `#mpw-*` | 插件自有 id(`#mpw-bgWrap` 等) | 本表 | | `ours:data-plugin` | anchor | `[data-plugin=…]` | 插件注入的 `