---
name: course-kit
description: 互动学习网页课程的视觉与组件工具箱：按功能组织、与皮肤无关的组件库（概念卡、原理框、图解模板、例子轮播、试试看、收起支线、动手题引擎等），验收过的视觉皮肤（手绘笔记本、纸片、掌机像素、田野手账、贴纸拼贴），配图、交互、动效、阅读激励的规矩，以及规划一章的办法（先写章纲：问题链与难度预算，再按每段在做的事挑元素）。凡是做、改、审、规划、写章纲互动网页课程或讲解型网页（课程章节、互动教程、科普长页）的版式、配图、互动、视觉风格时先用它；开新课选风格、搭共享骨架、做样板章、派写章 agent 时也用。正文文风另用 zh-teaching-prose（英文用 en-teaching-prose），内容规范见 references/content-rules.md。
---

# 互动课程工具箱（course-kit）

用途：做互动学习网页课程的规划、组件、皮肤和检查。规矩来自多门已经做完的互动课程，经用户逐轮验收。目标：普通人读起来**舒服、看得懂、有趣**，画面和谐，不像 AI 拼出来的。

**先想清楚这件事**：一章好不好懂，取决于读者在每一处是否知道"现在在讲什么、为什么讲它"，手里是否已经有理解它所需的东西。图、互动、框、卡片是装答案的容器，不是要凑齐的清单；文中的数字都是"默认值 + 为什么"，课程可以调整，只有技术底线（无障碍、检查脚本的阈值）不动。所以顺序永远是：章纲 → 正文 → 按每段在做的事挑元素。内容怎么讲（原则、难度分、验收、流程）在 `references/content-rules.md`（可整份复制进你的项目）；句子怎么写在 `zh-teaching-prose`；**画面、组件、版式、交互、动效、检查**在这里。

## 用之前读什么

| 要做的事 | 读 |
|---|---|
| 规划一章、写章纲、派审读任务 | 本文件第一节 + `references/content-rules.md` 第一节、一A、第四节、第八节 |
| 定内容怎么讲、验收标准 | `references/content-rules.md`（世界观矩阵、数学台阶等可选内容在 `references/optional-ai-math.md`） |
| 排一章的版式、选组件 | 本文件 + `references/components.md` |
| 画概念图解 | `references/diagrams.md` |
| 找配图、画插画 | `references/visuals.md` |
| 做互动、加动效 | `references/interaction.md` |
| 加阅读激励、陪伴角色、关系图等 | `references/modules.md` |
| 选皮肤、做新皮肤 | `references/skin-contract.md` + `skins/<名>/README.md` |
| 搭新课骨架 | `starter/README.md`：`node starter/new-course.mjs <课程文件夹绝对路径> <皮肤名>` 一条命令生成；API 见 `kit/README.md` |
| 检查 | 第七节 + `tools/check.mjs` |

## 一、一章怎么排：先章纲，再挑元素

规矩分三档：**原则**（保护什么 + 默认做法 + 可不照做的情形，在 content-rules 第一节；少数硬规则除外）、**可选做法**（按内容挑，下面的表和 `components.md`）、**技术底线**（无障碍、检查脚本阈值，不动）。

1. **先写章纲**（模板在 content-rules 第四节）：驱动问题、读者起点、问题链、概念与难度分（算法见 content-rules 一A）、元素表。按 content-rules 第一节的八条原则自检；难度分合计越过警戒线、装不下，先考虑拆章，不拆就在章纲里写明理由。章纲过了逻辑审读才写正文，样板章和每篇首章的章纲还要用户确认（流程见 content-rules 第八节）。
2. **照章纲写正文。** 一个主题娓娓道来，从读者熟悉的处境出发一层层展开，接住上一节留下的东西。难度适中：讲到读者"懂了"就停，推导、数学、研究细节进默认收起的抽屉。每个新概念默认依次走：麻烦 → 读者亲身碰到 → 起名 → 说准 → 边界（底线是名字不早于经验；读者早就认识的名字不受此限，见 content-rules 第一节第 2 条）。
3. **正文定了，再按"这一段在干什么"挑视觉**，不按组件的重要性排。表里找不到对应需要的，就不放元素：

| 这一段在做的事 | 用什么 |
|---|---|
| 抛出处境、勾起兴趣 | 场景插画、漫画格 |
| 讲历史、真人真事 | 真实图片、文档道具、带图时间线 |
| 讲清一个结构或机制（循环、层级、因果、对比、分类） | **概念图解**（`diagrams.md` 的模板） |
| 讲"改一个东西会怎样" | 活图、招牌互动 |
| 举例、举反例 | 例子插画轮播 |
| 点出名字 | 概念卡（带小图） |

判断要不要画图解：这段话里有没有"结构"？有就画图解，没有就用插画或照片。插画先从紧挨着的那句话写画面脚本再画，图解画出机制、用正文刚用的数（做法见 `references/visuals.md` 第三节、`references/diagrams.md` 第一节）。

4. **让读者随时知道在讲哪个概念**（用户验收过的偏好，默认要做）。每个核心概念四处凸显，名字四处一致：
   1. 主讲这个概念的那一节，小标题写出概念名（只是定位，正文里的起名要等读者碰到它之后；写法、长度见 `zh-teaching-prose` 的"章名和小标题"与"偏好"；✓"凌晨一点停不下来的核心循环"，✗"凌晨一点的最后一局"）；
   2. 正文里概念第一次被命名处套荧光笔起名标记 `<span class="vl-cn">核心循环</span>`，荧光笔只给这里用，不拿来划重点；
   3. 紧接着一张带图的概念卡（K1）；
   4. 章末要点里再回顾一次。
   次要概念只做起名标记，不做卡。一段里要读者记住的那句用着重标记 `.vl-em`，一段最多两处。`tools/check.mjs` 会查：有概念卡却没有同名起名标记或小标题的，报错。
5. **节奏规则**：
   1. 不留文字墙：读者面对一大片没有图的字会疲劳、失去位置感。默认两个视觉之间不超过约 360 字、单段不超过约 220 字，`check.mjs` 第 3 步超过就提示，由人判断：一段因果讲到一半、硬拆反而断了的，可以不照做；连着 500 字以上没有视觉的报错。超了先看是不是一段塞了两个新东西，拆开往往就够了；确实缺图才补图，补的图要画出这段的机制，不补装饰。**框也算正文**：原理框、概念卡、故事框里超过 2 段就要配图，或者拆成"图 + 短文"。
   2. 一节的开头和结尾宜放有温度的图（插画、照片、例子），图解放中间（审美偏好）。
   3. 默认不连放两张静态图解（读者连看两张同类图会疲劳），中间隔一个插画、例子或互动；成对对照的两张除外。能点、能拖的图解算半个互动。
   4. 次要内容默认收起：发明故事框、完整时间线、延伸、推导、补充案例。只露一个**具体问题式**的钩子标题 + 一句介绍 + 展开按钮。钩子说清里面有什么（✓"1898 年，一只猫被关进笼子：奖励规律是怎么被发现的"），不替读者安排体验（✗"你想穿越历史重新踏上冒险吗？"）。
   5. 重复的元素横向翻：例子、练习、时间线卡，一次显示一个。
   6. 同一张图全课只用一次。一个主例子可以贯穿全章、反复回指，但同一段描述不在开场、概念卡、轮播里重写三遍。

**版式自由组合。** 固定的只有导航和章的外壳（题头、学习目标、开场、要点、练习等，见 content-rules 第四节）。五层是"讲透没有"的写完自检，不是节的顺序；中间的节和元素按章纲挑，每章不必长得一样。

## 二、视觉的底线

- **课程只用验收过的皮肤**（`skins/`），不在课程页里临时拼一套风格（章节专属的小样式按 content-rules 第七节写在页内）。选哪套、想要新风格怎么办，见第六节。
- **安静的底子**：长文直接排在底上（纸、墙、版面），不在平涂底色上浮一张卡片放长文。只有"东西"才有实体（图、互动台、概念卡、文档道具），带同向投影。
- **粗框只给主角**：招牌互动、概念图解用粗描边；其他用细线或无框。不用 emoji 当图标、渐变字、发光阴影。
- **一章一个主题色**，同篇各章在主色、纹理、题头装饰上小变化，字体和组件形状不变。
- **字体**：装饰字体只给大标题，手写体验证过才用于小标题和图中字，正文用清晰字体；细则见 `skin-contract.md` 第一节"字体规则"。
- **对比度** ≥4.5:1，包括图注、图中文字、选中态按钮。
- **图文并排**：宽屏一栏文字一栏图，顶端对齐，不绕排、不垂直居中；窄屏上下排。
- 读者可以切换**配色**（亮、护眼；暗色已有变量但未完整验收）；**皮肤**在开课时定好，因为插画按皮肤画法画。

## 三、互动的底线

- 互动出场前用一句话说清它要回答什么问题；"试试看"写明要做什么，完成时给反馈；互动标题和试试看只用正文已经起名的新词。
- 控件少，读者 3 秒内知道怎么玩；关键处先预测，再看结果；能撤销、能重来。
- 难的玩法进进阶抽屉。选择题放哪里，见 `interaction.md` 第二节规则 12。
- 键盘能用，触屏目标够大。
- 细则见 `interaction.md`。

## 四、动效的底线

按作用分四类，各有规矩（细则见 `interaction.md`）：

| 作用 | 规矩 |
|---|---|
| 帮助理解 | 关掉动效也保留最终状态，信息不丢 |
| 反馈操作 | 要感觉即时，时长见 `interaction.md` 第四节"时长与缓动"；减少动态时只留颜色变化 |
| 阅读激励 | 只在读懂后触发一次，不打断阅读 |
| 氛围 | 只在正文以外，默认轻量，可一键关 |

全局尊重 `prefers-reduced-motion`；顶栏"显示"里可选"自动 / 全开 / 轻量 / 关"（三档 + 自动判定，细则见 `interaction.md` 第四节）。

## 五、可选模块（开课时逐项决定，写进项目文档）

- **阅读激励**：机制通用，外观随皮肤（笔记本→集邮册、图鉴、盖章；纸片爬塔→背包、亮灯）。只奖励"读懂了"（答对、完成试试看），不奖励滚动到底或停留时长。
- **陪伴角色**：默认不加。有世界观或读者年纪小时才加（世界观只在简报、题头图、角色台词里露面，正文仍讲概念本身，见 `content-rules.md` 一C）；点击才说话，台词和读到的内容有关，可关，键盘可触发，语气平常。
- **概念关系图**：概念多、彼此牵连时加；和概念卡、图鉴共用一份概念数据。
- 声音、术语表、闪卡、学习路径等，见 `modules.md`。

## 六、开新课的流程

**第一件事是问美术风格。** 用户说"做一门课"时，先用提问工具（AskUserQuestion，没有就直接问）让用户选皮肤，或选"和 AI 一起设计新皮肤"；不要默认，不要自己拼风格。每个选项写一句"适合什么课"，有截图就附验收页 `skins/<名>/gallery.html` 的路径：

| 皮肤 | 一句话 | 适合 | 状态（以各 `skins/<名>/README.md` 和 `skin-contract.md` 第六节为准） |
|---|---|---|---|
| `notebook` 手绘笔记本 | 横线纸、墨线火柴人、色块 | 设计、思维、文科；成人和高中生 | 已入库；暗色未精调 |
| `paper` 纸片 | 卡纸剪纸、白裁边、柔和投影，目录页是一座塔 | 有故事、有角色的课；初中到高中 | 已入库，有样板章；暗色未精调 |
| `pixel` 掌机像素 | 四阶绿液晶屏、像素插画、阶梯动效 | 计算、编程、游戏化的课 | 已入库，有样板章；暗色未精调 |
| `fieldbook` 田野手账 | 方格活页纸、彩铅、胶带贴的照片和票根 | 人文、社科、田野和历史类 | 已入库，有样板章；暗色未精调；"抽成皮肤后的样子"尚未单独验收 |
| `collage` 贴纸拼贴 | 手工纸、马蒂斯剪纸色、照片名画和剪纸人都做成白边贴纸 | 名画、历史照片多的入门课（教育、艺术史、心理学） | 2026-10-26 用户同意入库；暗色、护眼未精调；引线标签拆解还没做成组件 |

用户要的风格不在表里，或选了"一起设计新皮肤"时：先聊清楚想要的感觉、参考作品和读者是谁，提两三个方向让用户挑；再按 `skin-contract.md` 第五节做展示页和一章样稿，用户验收、进库后再开课。`examples/` 下有三章用真实内容做的样板章（`paper-survivorship`、`pixel-binary-search`、`fieldbook-gift`），可以给用户看、也可以当样稿的参照。

**第二件事是问课程安排。** 选完皮肤，接着用提问工具一次问完四个问题（选择题，用户点一下就能答）：

| 问题 | 选项示例 |
|---|---|
| 读者是谁 | 零基础成人 / 高中生 / 初中生 / 有基础想深入 |
| 学多久 | 入门短课 5–8 章 / 标准课 15–25 章 / 完整课 25 章以上 |
| 语言 | 只做中文 / 中英双语 / 只做英文 |
| 加哪些模块（多选） | 关系图、术语表、闪卡、集邮册、陪伴角色（第五节） |

**然后交一份课程方案给用户确认**，确认前不生成骨架、不写章：
- 知识地图：分几篇、每篇几章、先学什么；
- 章节表：每章一行：章名（直接写出主题）、驱动问题、核心概念及难度分合计（content-rules 一A）；难度分估出来装不下的章当场拆开；
- 学完能做到什么（可观察）。
结构铺开后很难改（改编号要全课重映射），所以这一步宁可多问一句。

之后的流程（骨架 → 样板章 → 按篇铺开；每章：章纲 → 逻辑审读 → 用户确认（样板章、每篇首章）→ 写 → 检查 → 读者审读 → 主控验收）和用户在哪几处参与，见 `references/content-rules.md` 第八节。骨架用 `starter/new-course.mjs <课程文件夹绝对路径> <皮肤名>` 生成（kit、皮肤、配置、目录页、第 1 章模板、项目文档模板），再改 `js/course.js` 的章节表和模块开关；读者、预算数字、语言、模块写进项目文档。

## 七、检查（防止"写的时候看不见"的错）

代码是盲写的：字体实际宽度、屏幕宽度、几个文件之间的类名对不对得上，都只有打开页面才知道。所以写完必须跑检查，agent 不能自己跳过；用户明确说"先不测"时可以跳过，但交付时列出未测清单。

**一键检查**（工具都在本 skill 的 `tools/`，必须传绝对路径）：

```
node <skill>/tools/check.mjs <课程文件夹绝对路径> [ch02,ch03] [--fast]
```

| 步 | 查什么 | 抓得到的错 |
|---|---|---|
| 1 语法 | 每个 .js `node --check`，每段内联脚本试编译 | 整页脚本不跑 |
| 2 接线 | JS 去找的 `vl-` 类，页面和脚本里有没有造出来（报错）；页面写的类没有样式也没被脚本用到（只提示） | 改名没同步、按钮没反应、样式不生效 |
| 2b 凸显 | 每张概念卡的名字，正文有没有同名起名标记 `.vl-cn`、小标题有没有写出它 | 概念凸显漏了一处 |
| 2c 先讲后用（只提示） | 概念在正文里第一次起名之前，互动台标题、试试看、按钮、先猜后揭晓题干里就出现了它的名字 | 任务里用了读者还不认识的词 |
| 2d 负荷（只提示） | 一段里有 ≥2 个第一次出现的术语或概念名；一段里数字超过 6 个 | 一段塞了两个新东西、要记的数堆在句子里 |
| 2e 文风（只提示，中文页） | 段首 ≤10 字的短句、连续三个以上 ≤15 字的短句、两句以上命令式开头、冒号后罗列 | AI 腔的短句串、像在催人的任务提示 |
| 3 配图密度（提示；超限报错） | 阈值见第一节第 5 条 1：超过只提示，连着没有视觉到报错线才报错。计法和算作视觉的元素见 `visuals.md` 第四节 | 长文无图 |
| 4 链接 | 本地 href / src 是否存在 | 图片、脚本路径写错 |
| 5 运行 | `qa.mjs`：420 和 1100 宽度下点遍按钮、拖遍滑块 | JS 报错、插画没画出来（插画名写错、插画脚本括号错位）、横向溢出、图内文字压线/出界/重叠；有 JS 错误或缺图时汇总处单独打一行 ！！！ |
| 6 截图 | 每页 420、1100 整页图，存在 `%TEMP%/course-check-shots/<课程文件夹名>/`（英文页前缀 `en-`） | 打印路径，**必须用 Read 打开看** |

2c、2d、2e 和第 3 步的提示行只打印「· 提示」，不计入错误数：提示靠人判断（读者早就认识的名字不算"没讲过"，基础好的读者能多带一点，单句短有时是对的），但交付汇报要贴出全部提示行，逐条写"已改"或"有意保留及理由"。

`--fast` 只跑 1–4（几秒，不开浏览器），适合边写边查；交付前跑完整版。第 5、6 步要 Edge 或 Chrome，`tools/browser.mjs` 自动找；找不到时把浏览器路径写进环境变量 `EDGE_PATH`。

**脚本之外必须人眼看的**（截图后逐项看）：脚本不查文风，正文要有人按 `zh-teaching-prose/references/review.md` 逐句读过（写作 agent 自审，主控验收时再读几段）；图解文字是否压线、插画人物是否合规（脚落地、手握物、不悬空，用 `tools/illus-overlap.mjs` 辅助）、配色对比度、一节的节奏是否符合第一节、成品每节是否回答章纲里那一问。单张图用 `tools/shot.mjs <html> <png> "选择器@序号" 1100` 截下来放大看；html 后加 `?scheme=sepia`（或 `dark`）截别的配色；整页超过 16000px 时只截到 16000px 并警告，下半截用选择器分段截。

**交付汇报必须写**：跑了哪几步、结果（贴 ✗ 行）、看了哪些截图、没测的项目。"语法通过"不等于"测试过"。

**流程**：写完 → `--fast` 修到 0 → 完整版修到 0 → 看截图 → 修 → 再跑一次 → 交付。主控收到 agent 交付后，自己再跑一次完整版并看截图。整章流水线（章纲、两种审读）见 `references/content-rules.md` 第八节。

## 八、学新的

**中英两份**：英文版 skill 在 `../course-kit-en/`，两份共用同一套代码（kit、skins、tools、starter），以中文版为准。改了代码就跑 `node tools/sync-en.mjs` 同步过去（`examples/` 不在同步范围内）；改了规则（SKILL.md、references/）就在英文版对应条目同样改一遍。kit/README.md 英文版另有译本，不随 sync-en 同步，改中文版时手动同步。

用户每次反馈先归类：理解原则 → content-rules 第一节、一A；审美偏好 → 对应组件或皮肤，写明这是偏好；技术 → kit / tools。找到现有条目改写，不追加，写之前先查有没有相反的旧条目；写法见 content-rules 第九节最后一条（"当……时"、数字写成"默认值 + 为什么"、分三档）；新皮肤验收后加进 `skins/`。
