# rubric.md

> 领域：把一份文稿封装成「发布级」的单页网站。
> 这份 rubric 是验收用的——成品出来后逐条打分，加权汇总，对照档位阈值。
> 60% 以上条目是**可程序化检查**（grep / 脚本 / DOM 查询）的，剩下是带 anchor 的半客观判断。
>
> 数据来源：高分样本组评分 + 复刻样本组诚实差距字段 + 审美验收共识 + 建站方法论。
> Principle ID 引用 `principles.md`（P-001 ~ P-049）。

---

## A. 客观可程序化检查（grep/脚本/DOM 一查就有答案）

### R-001 · 单文件交付
- 问题：成品是否为单个 `.html` 文件？所有 CSS / JS 是否内联或仅通过白名单 CDN 引入？
- 通过标准：目录只有 1 个 html；如果引外部脚本，只允许 Google Fonts / cdnjs / unpkg 这类带版本号的 CDN，且总外链数 ≤ 5。
- 关联原则：P-001（单文件交付）、P-002（依赖纪律）
- 打分：0（多文件依赖本地资源）/ 0.5（少量外链但无版本号或 >5 条）/ 1（单文件 + 合规 CDN）

### R-002 · 移动端 viewport meta
- 问题：`<head>` 是否含 `<meta name="viewport" content="width=device-width,initial-scale=1">`？
- 通过标准：必须存在且 `initial-scale=1`；不允许 `user-scalable=no` 完全禁缩放（无障碍硬伤）。
- 关联原则：P-003（移动端优先）
- 打分：0（无 viewport）/ 0.5（有但禁缩放）/ 1（标准 viewport）

### R-003 · HTML 标签平衡 & 无控制台报错
- 问题：浏览器解析后是否无 parse error？打开页面 5 秒内 `console.error` 数为 0？
- 通过标准：W3C validator 无 critical error；DevTools console 无红色 error（warning 可接受）。
- 关联原则：P-004（工程基线）
- 打分：0（有 error 阻塞渲染）/ 0.5（有 error 但不影响渲染）/ 1（全清）

### R-004 · Canvas / rAF 资源回收
- 问题：所有 `requestAnimationFrame` 是否在 `visibilitychange='hidden'` 或 `beforeunload` 时调用 `cancelAnimationFrame`？
- 通过标准：grep 源码：每个 `requestAnimationFrame` 对应 ≥1 个 `cancelAnimationFrame` 调用，且能 grep 到 `visibilitychange` 或 `beforeunload` 监听。
- 关联原则：P-005（动效性能纪律）
- 打分：0（有 rAF 无 cancel）/ 0.5（有 cancel 但无 visibilitychange 守卫）/ 1（双重清理到位）

### R-005 · 桌面端 cursor 在移动端正确门控
- 问题：自定义光标 / hover 重交互是否用 `@media (hover: hover) and (pointer: fine)` 门控？
- 通过标准：如出现 `cursor: none` 或自定义光标 DOM，必须包在 `@media (hover: hover)` 内；移动端 viewport 下不应有"鼠标残影 / 死光标"。
- 关联原则：P-003（移动端优先）、P-006（交互降级）
- 打分：0（PC 光标直接搬到移动端）/ 0.5（部分门控）/ 1（完全门控或不用自定义光标）

### R-006 · 配色 hex 落在所选风格范围内
- 问题：CSS 里出现的所有 hex 颜色，是否落在所选风格代号（S1-S7）的 hex 推荐范围 ±10% 内？
- 通过标准：grep `#[0-9a-fA-F]{6}` → 比对 `风格库.md` 的推荐 hex 表；不允许出现纯 `#ff0000` `#00ffff` 这类过饱和原色（除非风格明确要求）。
- 关联原则：P-007（配色纪律）、P-008（风格一致性）
- 打分：0（颜色乱用 / 出现 KTV 紫金）/ 0.5（主色对但有 1-2 个跑偏）/ 1（全部落在风格表）

### R-007 · 字体引用纪律
- 问题：S2 / S3 / S7 这类对字体敏感的风格，是否引了对应的 Google Font（Fraunces / Cormorant / JetBrains Mono / Noto Serif SC）而非裸用 system 栈？
- 通过标准：grep `fonts.googleapis.com` 或本地 base64 字体；S1/S2/S7 至少 1 个衬线 Google Font；S3 至少 1 个等宽 Google Font。
- 关联原则：P-009（字体决定气质）
- 打分：0（system serif/sans 凑数）/ 0.5（引了但未真正用到大标题）/ 1（标题字明确是 Google Font）

### R-008 · 首屏字号 & 视觉焦点
- 问题：首屏（折叠线以上）是否有 ≥1 个字号 ≥ `clamp(2.4rem, 8vw, 6rem)` 的主标题，并且首屏 DOM 元素数 ≤ 8？
- 通过标准：DOM 查询第一屏内最大字号 ≥ 2.4rem（移动）/ 4.5rem（桌面）；首屏元素稀疏不堆。
- 关联原则：P-010（首屏定生死）、P-011（巨字张力）
- 打分：0（首屏字小 + 元素堆）/ 0.5（字够大但堆元素）/ 1（巨字 + 留白）

### R-009 · 无占位文案残留
- 问题：grep `lorem|占位|placeholder|待补充|TODO|TBD|示例文字|这里写`，命中数是否为 0？
- 通过标准：全文 0 命中；如果是接单交付，额外要求无错别字（人工抽查 3 段）。
- 关联原则：P-012（文字含金量）、P-013（交付完整性）
- 打分：0（≥1 处占位）/ 0.5（仅注释里有 TODO）/ 1（全清）

### R-010 · 点击区域 ≥ 44px
- 问题：所有可点击元素（button/a/[role=button]）的渲染尺寸是否 ≥ 44×44px？
- 通过标准：用 puppeteer 或手测，375 视口下所有点击元素 `getBoundingClientRect()` 长宽都 ≥ 44px。
- 关联原则：P-003（移动端优先）、P-014（无障碍基线）
- 打分：0（多个小按钮）/ 0.5（1-2 个偏小）/ 1（全部达标）

### R-011 · 无横向滚动条 & 无溢出
- 问题：375px 宽度下，`document.documentElement.scrollWidth ≤ 375`？无元素溢出视口？
- 通过标准：375 视口下 `scrollWidth === clientWidth`；无水平 scrollbar。
- 关联原则：P-003（移动端优先）
- 打分：0（横向溢出）/ 0.5（轻微溢出 1-5px）/ 1（完美贴边）

### R-012 · 首屏不白屏 & 加载体感
- 问题：DOMContentLoaded 后 1.5s 内是否已有可见内容渲染？base64 图片体量是否 ≤ 1MB 单张？
- 通过标准：DCL → first paint ≤ 1.5s（4G 模拟）；grep base64 块长度，单张图 ≤ 1.3M 字符（约 1MB 解码）。
- 关联原则：P-015（加载体感）、P-003
- 打分：0（白屏 >2s 或单图 >2MB）/ 0.5（白屏 1-2s）/ 1（首屏即时呈现）

### R-013 · 音频按钮一致性（不留死按钮）
- 问题：如果 UI 上有"播放 / PLAY / 音乐"按钮，点击后是否真的有声音？
- 通过标准：要么有内联 base64 音频，要么有 Web Audio 程序合成（`new AudioContext()` + oscillator/buffer），要么**根本不放按钮**。绝对禁止"按钮存在但点击无声"。
- 关联原则：P-016（不撒谎的交互）、P-017（BGM 是 S 档门票）
- 打分：0（死按钮 / 占位 UI）/ 0.5（按钮存在但只播放 1s 提示音）/ 1（真音频 或 无按钮）

### R-014 · 章节数 vs 内容类型匹配
- 问题：长文 manifesto / 文学体例类内容是否 ≥ 5 章；影片式短片是否 ≥ 8 幕；单屏海报 = 1 屏？
- 通过标准：DOM 数 `[data-section]` 或主要 `<section>` 数量；按 §1 前 10 名归纳：长文 ≥ 5 章、影片式 ≥ 8 幕、海报型严格 1 屏。
- 关联原则：P-018（结构匹配内容）
- 打分：0（数量不达标且节奏掉了）/ 0.5（数量边缘但内容够）/ 1（章节数足且节奏稳）

### R-015 · 文字长度 vs 原作比例
- 问题：复刻 / 改编场景下，正文字符数是否 ≥ 原作正文的 1/3？
- 通过标准：源文档 wc -m 对比成品文字 wc -m，比例 ≥ 0.33；100% 全文最佳。原创场景跳过本条。
- 关联原则：P-012（文字含金量）、P-019（不裁画面感细节）
- 打分：0（裁掉一半以上）/ 0.5（保留 1/3 ~ 2/3）/ 1（≥ 2/3 或全保留）

### R-016 · 长文画面感细节存活率
- 问题：原文中"凌晨两点 / 咖啡凉掉 / 路边的猫"这类具象画面感句子是否保留 ≥ 80%？
- 通过标准：人工标出原文里"画面感钩子句"清单，逐句 grep 成品；命中率 ≥ 80%。
- 关联原则：P-019（不裁画面感细节）、P-012
- 打分：0（核心钩子句全删）/ 0.5（保留一半）/ 1（≥80% 存活）

---

## B. 半客观（带阈值 / 带 anchor）

### R-017 · 首屏信息密度
- 问题：首屏视觉单元数量是否合适？文字是否克制？
- 通过标准：首屏「独立视觉块」数 ≤ 5（巨标题 + 副标题 + 1-2 个装饰元素 + 可选 CTA）；首屏正文字数 ≤ 60 字（中文）/ 30 词（英文）。anchor：单屏海报样本组（5 单元上限）。
- 关联原则：P-010（首屏定生死）、P-020（克制）
- 打分：0（首屏挤 8+ 元素或 >100 字）/ 0.5（边缘）/ 1（5 以内 + 留白）

### R-018 · 动效程度匹配内容描述
- 问题：动效强度是否匹配内容定调（宣言 → 强；文学长文 → 弱；HUD → 数据感强）？
- 通过标准：对照 `风格库.md` × `特效与3D.md` 的"风格 × 动效组合表"。anchor：S1 影片式必须有章节切场 flash；S7 文学体例最多用 IO reveal + 暖光呼吸，禁止粒子爆炸；S5 长文最多 grain + 微缩放。
- 关联原则：P-021（动效服务于内容）
- 打分：0（错配，文学风用了粒子爆炸）/ 0.5（基本匹配但有违和）/ 1（动效与内容同频）

### R-019 · 章节切换节奏（影片式专项）
- 问题：影片式作品每章是否 10-15s 一切？章节间是否有 flash/wipe/curtain 转场？
- 通过标准：仅适用于影片式。总时长 60-135s 甜区；章节切换间隔 8-15s；至少 80% 章节切换处有 visual cue（闪白 / 斜光扫 / 黑场）。
- 关联原则：P-022（影片式节奏甜区）
- 打分：0（无转场 / >150s 拖沓）/ 0.5（部分有转场）/ 1（节奏 + 转场 100% 命中）

### R-020 · 时长 vs 内容形态匹配
- 问题：影片式时长是否落在 60-135s 甜区？长文 manifesto 滚动深度是否够 5-7 屏？
- 通过标准：影片式：60s ≤ 时长 ≤ 135s；长文：滚动深度（scrollHeight / viewportHeight） ∈ [5, 9]；单屏海报：滚动深度 ≤ 1.2。
- 关联原则：P-023（时长甜区）
- 打分：0（明显超出 / 不足）/ 0.5（边缘）/ 1（甜区内）

### R-021 · BGM 卡点精度（如有 BGM）
- 问题：BGM 与章节切换是否精确卡点？非线性 cue mapping 还是线性时间轴？
- 通过标准：若有 BGM，章节切换必须由 `audio.currentTime` 触发（grep `audio.currentTime` 或 `addEventListener('timeupdate'`）；用 cue 数组（{audioT, visualT}）做 phrase mapping 优于纯等比拉伸。anchor：影片式样本组共识——虚拟时钟"皮+骨 1:1，神略减"，所以真 audio 驱动 +1，虚拟时钟 +0.5。
- 关联原则：P-017（BGM 是 S 档门票）、P-024（cue mapping）
- 打分：0（BGM 与画面脱节）/ 0.5（虚拟时钟 / 等比线性）/ 1（audio.currentTime + phrase mapping）

### R-022 · 强对比配色力度
- 问题：是否避开了灰扑扑中间色？是否有 ≥1 个高饱和强调色（红 / 暖金 / 荧光绿）？
- 通过标准：grep 主色 hex，背景与强调色 contrast ratio ≥ 7:1；强调色 saturation ≥ 60%；禁止整页都是 #ccc/#999/#666 这类中性灰。anchor：S 档样本组 #A 配色（暖红 #E23B22 + 暖金 #D8AA58 + 骨白 #F7ECD8）。
- 关联原则：P-007（配色纪律）、P-025（克制的强调色）
- 打分：0（灰扑扑）/ 0.5（对比弱）/ 1（强对比 + 克制强调色）

### R-023 · 字体层级 4 级以内但拉得开
- 问题：是否 H1/H2/正文/注释 四级以内？最大字号 / 最小字号比例 ≥ 4:1？
- 通过标准：grep CSS 中的 font-size，去重后字号档位 ≤ 5；max/min 比例 ≥ 4。anchor：杂志样本组 #C 用了 PingFang / Noto Serif SC 900 / Noto Sans SC 100 / Fraunces italic 三套系统，但字号档位仅 4 档。
- 关联原则：P-026（层级分明）、P-009
- 打分：0（一锅粥同字号 / 档位 >7）/ 0.5（档位 5-6）/ 1（4 档内 + 比例拉开）

---

## C. 品味维度（主观但有 anchor，按 0-1 量化）

### R-024 · 第一眼气质（3 秒测试）
- 问题：打开网站 3 秒内，是否有"咦，这个不错"的反应？是否避免"一眼 AI 模板感"？
- 通过标准：anchor 比对——把成品截图与 training/exemplars/good/ 同风格 3-5 个 S 档样本并排放，看是否能混入其中而不被一眼挑出。
- 关联原则：P-027（产品级气质）、P-010
- 打分：0（一眼 demo / 模板感）/ 0.5（基本气质对但有瑕疵）/ 1（混入参考库不违和）

### R-025 · 字体张力（标题字是否挑过）
- 问题：主标题字体是否经过挑选、有明显性格？还是默认宋体 / 黑体凑数？
- 通过标准：标题字体必须是 Google Font 衬线 italic（Fraunces / Cormorant / EB Garamond）或思源黑体 Heavy / Noto Serif SC 900 这类有"重量"的字体；禁止 PingFang Regular / 默认 sans 当大标题。anchor：单屏海报样本组的巨型 Fraunces italic。
- 关联原则：P-009（字体决定气质）、P-011
- 打分：0（默认字体）/ 0.5（挑过但缺张力）/ 1（一眼看出字体性格）

### R-026 · 小亮点（grain / 光晕 / 划痕 / 细线装饰）
- 问题：是否有至少 1 个"小亮点细节"——SVG 噪点 / radial 暖光 / 边角细线 / 划痕 / 双层光标 / 字符级 kinetic？
- 通过标准：grep `<svg>` 或 `radial-gradient` 或 `filter: url(#noise)`，至少 1 处明显小亮点；anchor：长文样本组共识——"SVG 噪点 0.04 不透明度 + 四角细线 + 双层 radial 暖光"。
- 关联原则：P-028（小亮点 = 高级感）
- 打分：0（白板 / 平铺直叙）/ 0.5（有但程式化）/ 1（≥2 个相互呼应的细节）

### R-027 · 风格统一性（无半路画风突变）
- 问题：从头到尾是否同一个人格？无半路换风格、换配色、换字体？
- 通过标准：人工通读 / 滚动一遍，检查是否有"前 3 屏 S1 暗黑宣言，第 4 屏突然变 S5 米黄纸感"这种突变。
- 关联原则：P-008（风格一致性）
- 打分：0（明显画风突变）/ 0.5（轻微违和）/ 1（一气呵成）

### R-028 · 情绪扳机存在性
- 问题：是否存在至少 1 个"情绪扳机"——能让群里"卧槽 / 哭了 / 接力喊"的钩子？
- 通过标准：以下至少命中 1 个：① BGM 卡章节节拍（R-021=1）；② 长文里有"凌晨两点 / 咖啡凉掉"级的画面感钩子（R-016=1）；③ 3D 物件交互仪式（信封展开 / 卡片翻面）；④ 创意稀缺形态（命运骰子 / 公开表白 / 程序合成 ambient）。anchor：§3 触发器 B/C/E。
- 关联原则：P-029（情绪扳机）、P-017、P-019
- 打分：0（4 个都没有）/ 0.5（命中 1 个但弱）/ 1（命中 ≥1 个且力度足）

---

## 总评分公式

### 权重分配（满分 5.0）

每条 rubric 单独打分（0 / 0.5 / 1），分维度加权：

| 维度 | 条目 | 单项权重 | 维度小计 |
|---|---|---|---|
| **A. 客观工程基线**（16 条 × 必过项） | R-001 ~ R-016 | 各 0.10 | 1.6 |
| **B. 半客观（结构 / 节奏 / 色字）**（7 条） | R-017 ~ R-023 | 各 0.20 | 1.4 |
| **C. 品味维度**（5 条） | R-024 ~ R-028 | 各 0.40 | 2.0 |

总分 = ΣA × 0.10 + ΣB × 0.20 + ΣC × 0.40，满分 5.0。

### 一票否决项（任何一条不过 = 直接 B 档以下，无法上 A 档）

- **R-001（单文件）** = 0：交付不合规
- **R-002（viewport）** = 0：移动端硬伤
- **R-009（占位文案）** = 0：业余出局
- **R-011（横向溢出）** = 0：手机端坏
- **R-013（死音频按钮）** = 0：撒谎的交互
- **R-027（画风突变）** = 0：风格不统一

### 档位阈值

| 档位 | 总分 | 对标 53 条原作 | 进档必备条件 |
|---|---|---|---|
| **S 档** | ≥ 4.5 / 5 | idx 0-13（score ≥85） | C 维度满分 ≥ 4.0/5 + 无一票否决 + R-028（情绪扳机）= 1 + （影片式则 R-021 BGM ≥ 0.5）|
| **A 档** | ≥ 3.5 / 5 | idx 14-30（score 75-84） | A 全过 + B 平均 ≥ 0.7 + 无一票否决 |
| **B 档** | ≥ 2.5 / 5 | idx 31-50（score 60-74） | A 平均 ≥ 0.7 + 无一票否决 |
| **不通过** | < 2.5 | score < 60 | 任一一票否决项 = 0，或 A 平均 < 0.5 |

### 进 S 档的硬路径（必须额外满足之一）

光达到 4.5 分还不够，进 S 档要至少命中下面一条「情绪扳机硬通货」：

1. **真 BGM 路径**：R-021 = 1（audio.currentTime 驱动 + phrase mapping）+ R-019 = 1（章节切场 + 转场命中）
2. **文学长文路径**：R-015 = 1（文字 ≥ 2/3）+ R-016 = 1（画面感钩子 ≥ 80% 存活）+ R-026 = 1（小亮点 ≥ 2）
3. **3D 仪式路径**：自定义"打开仪式"（信封 / 卡片 / 折页）+ R-024 = 1 + R-026 = 1
4. **单帧海报路径**：滚动深度 ≤ 1.2 + R-008 = 1（巨字）+ R-017 = 1（首屏 ≤ 5 单元）+ R-025 = 1（衬线 italic 张力）
5. **程序合成 ambient 路径**：Web Audio drone（参考程序合成样本组玩法）+ R-013 = 1 + R-024 = 1

### 复评规则

- A 维度任何一条 = 0：先修工程，再评 B/C
- C 维度全部 < 0.5：成品有"AI 随便做"嫌疑，回 `审美验收清单.md` 终极一问重审
- "高位反响候选"加分项（可选）：如果作品具备创意稀缺 / 风格延续 / 情绪扳机三选一的潜质，打分备注 "+S 档候选"，但不直接折算成分数——外部反响不可控但可设计

---

## 附：rubric 使用方式

1. **生成后自检**：build-site skill 跑完 6 步工作流后，逐条对照本 rubric，记录 0/0.5/1 三值数组
2. **维度汇总**：算出 A/B/C 三维度小计 → 总分
3. **档位判定**：对照「档位阈值」表，输出 S/A/B/不通过
4. **未达档说明**：列出所有 < 1 的条目，按维度排序，作为下一轮迭代的修改清单
5. **一票否决兜底**：如命中一票否决，立即停手回修，不允许"先发出去看看反响"

> rubric 是验收尺，不是创作清单。
> 创作走 `principles.md` + `知识库/`，验收才查 rubric。
