# 设计规范 · 罗德岛终端(Rhodes Terminal) > **这一份是新页面的前置读物。** 动 `assets/*.css` 或写任何新页面之前先读它, > 按里面的色值、字号、间距、组件规则来。规范里没有的东西,先想清楚再发明—— > 大多数时候你要的那一条已经在下面了,只是叫别的名字。 > > 唯一的事实来源是 `assets/style.css` 顶部的 `:root`(**深色,默认**)与 > `html[data-theme="light"]`(纸白那一档)。这份文档解释它为什么是这样、 > 什么时候该用哪一个;**两边不一致时以 CSS 为准,并把这份文档改回来。** > 造型那一层(细规、角包、斜纹、索引字、硬偏移)集中在 `style.css` 末尾的「方舟层」。 --- ## 1. 取向与来路 这个项目是**一个中文学习工具**:每天要被打开很多次,一次待几十分钟,内容以 「成段的文字 + 密集的清单 + 少量数字」为主。所以它要的是**能久读、层次清楚、 安静、可信**——不是热闹,也不是把游戏界面搬进来。 取向对着三份东西做取舍: | 来源 | 抄它的什么 | 不抄什么 | | --- | --- | --- | | **明日方舟官方站**(生产 CSS 实测) | 近黑冷灰底 + 纯白正文 + **一条信号青只指「当前 / 动作 / 进度」**;`1px hsla(0,0%,100%,.3)` 这种细规;**圆角 0**;零模糊的硬偏移抬升;方角主按钮配左侧信号条 | 它的整屏 hero、视频与巨型字号——我们是工具,不是官网 | | **HyperGryph 家族设计语言** | 编辑式层级(大标题与小标签并存、中间尺寸填充要少)、非对称平衡、克制的信号色、分层扁平(层次靠蒙版与细规,不靠亮面卡片) | 没有信息作用的六边形、终端噪音、扫描线、glitch、霓虹渐变;给每个容器都切一刀 | | **Linear + Notion**(排版纪律) | 字重阶梯(最重 600)、4px 间距刻度、**边框优先而不是阴影优先**、控件最小高度 40px、行高与行宽纪律、等宽数字 | 全黑面板与靛蓝主色、16px 正文、大圆角卡片 | 一句话概括:**近黑面板、白字、一条信号青只指「该点这儿」,其余全中性;造型靠细规、 角包、切角、索引字这四样,不靠阴影、辉光和渐变。** 中文与拉丁是分开处理的:拉丁编号 / 数字 / 路径有专门的显示字体与大写字距; **汉字一律不加字距,也绝不排衬线正文。** --- ## 2. 配色 所有颜色都走 CSS 变量,**不许在规则里写死色值**(`color-mix()` 混变量可以)。 变量表在 `assets/style.css` 的 `:root`(深色,默认)与 `html[data-theme="light"]`。 ### 2.1 面与线(深色,默认) | 变量 | 色值 | 用在哪 | | --- | --- | --- | | `--bg` | `#1b1b1b` | 页面画布。官方站的页面底就是这个值 | | `--card` | `#141618` | 卡片、抬升面。比画布**更深**一档,冷调,不是亮一档 | | `--card-2` | `#1f2224` | 卡内柔和区块(列表行、计时面、标签底) | | `--input` | `#101214` | 输入框、下拉、文本域的底 | | `--line` | `rgba(255,255,255,.22)` | **默认细规与分隔线**。整页一半的层次靠它 | | `--line-2` | `rgba(255,255,255,.38)` | 强调细规:卡片外沿、输入框、浮层 | 面的层级只有三层:**画布 → 卡片 → 卡内区块**。别再加第四层,需要再分就用线和间距。 深底上「亮一档」不是抬升——**卡片比画布暗**才像一块嵌进去的仪表板。 ### 2.2 文字 | 变量 | 色值 | 用在哪 | | --- | --- | --- | | `--text` | `#d2d2d2` | 正文(默认 `body` 色) | | `--ink` | `#ffffff` | 标题、大数字、最高强调 | | `--dim` | `#999999` | 次级文字、元信息、说明 | | `--faint` | `#6e7276` | 占位符、被禁用 / 折叠态的最弱文字。**不承载信息** | 四级文字就够。正文与次级之间的差要一眼看得出——这是这套设计里最要紧的一层对比。 ### 2.3 信号色 | 变量 | 色值 | 用在哪 | | --- | --- | --- | | `--accent` | `#18d1ff` | **信号青**。主按钮底、当前导航的下划线、进度条填充、焦点边 | | `--accent-hover` | `#4cd9ff` | 主按钮 hover | | `--accent-soft` | `rgba(24,209,255,.12)` | 主色淡面(选中项的底、教练话气泡的底) | | `--on-accent` | `#000000` | 压在 `--accent` 上的字。官方站主按钮就是青底黑字 | **青只用来指「这里是动作 / 这里是当前 / 这里在走」。** 它不该出现在标题、正文、 分隔线、静态面板的描边上;一屏出现三处以上,就是铺多了(警示斜纹里那条信号带算一处)。 ### 2.4 功能色 | 变量 | 色值 | 用在哪 | | --- | --- | --- | | `--ok` | `#c8eb21` | 已掌握、通过、做完(酸绿,只当功能色) | | `--warn` | `#f1c644` | 该修但不挡路、待验证、顶栏那排斜纹 | | `--bad` | `#e33b3b` | 错误、坏了、挡住路了(边框与图标) | | `--bad-text` | `#ff8f8f` | 错误文字(比 `--bad` 亮,保证在近黑底上读得出) | | `--danger-bg` | `rgba(227,59,59,.14)` | 危险操作的确认行底 | | `--hl` | `rgba(24,209,255,.14)` | 高亮块底(教练指引的激活态) | | `--hl-text` | `#a8e9ff` | 高亮块里的文字 | | `--toast-bg` | `#181818` | 吐司底 | | `--scrim` | `rgba(0,0,0,.72)` | 模态遮罩 | 功能色是**状态**,不是**情绪**。同一屏里最多两档同时出现。 ### 2.5 六档掌握度 `--stage-1` … `--stage-6` 是知识点六档的专用色,深底上**越靠后越亮**,倒数第二档进 信号青、最后一档进酸绿。它们是**文字色**,每一档都必须压在 `--card` 上看得清: | 档 | 色值 | | 档 | 色值 | | --- | --- | --- | --- | --- | | `--stage-1` 没接触过 | `#6e7276` | | `--stage-4` 能独立做 | `#7fe0ff` | | `--stage-2` 见过 | `#93a0a6` | | `--stage-5` 熟练稳定 | `#18d1ff` | | `--stage-3` 能跟做 | `#b9c2c7` | | `--stage-6` 能讲明白 | `#c8eb21` | 改配色时这六个要一起校。 ### 2.6 浅色(`html[data-theme="light"]`) 浅色不是把深色反相,是**同一套造型的纸白版**:底用官方站的纸白 token `#f4f6f6`, 信号青压深到能在白底上读出来。浅底上尤其别用信号青写长正文;中性面要占七成以上。 | 变量 | 色值 | | 变量 | 色值 | | --- | --- | --- | --- | --- | | `--bg` | `#f4f6f6` | | `--text` | `#26302f` | | `--card` | `#ffffff` | | `--ink` | `#0b0e0f` | | `--card-2` | `#eceeed` | | `--dim` | `#5f6968` | | `--input` | `#ffffff` | | `--faint` | `#8b9493` | | `--line` | `rgba(0,0,0,.16)` | | `--accent` | `#0b7e9e` | | `--line-2` | `rgba(0,0,0,.3)` | | `--accent-hover` | `#096a86` | | `--on-accent` | `#ffffff` | | `--accent-soft` | `rgba(11,126,158,.1)` | | `--ok` | `#4e7a0b` | | `--warn` | `#8a6a0a` | | `--bad` | `#c0392b` | | `--bad-text` | `#9e2f23` | | `--hl` | `rgba(11,126,158,.1)` | | `--hl-text` | `#0b5a73` | | `--toast-bg` | `#ffffff` | | `--scrim` | `rgba(11,14,15,.42)` | 浅色的六档是「越靠后越深」:`#9aa3a4` / `#77898c` / `#4e7c88` / `#1e8aa8` / `#0b7e9e` / `#7a6a08`。 --- ## 3. 字体 ### 3.1 字族 ```css --font: system-ui, "Segoe UI", "Microsoft YaHei", "PingFang SC", "Hiragino Sans GB", sans-serif; /* 正文与汉字 */ --font-display: "Rajdhani", "Arial Narrow", "Roboto Condensed", system-ui, "Microsoft YaHei", "PingFang SC", sans-serif; /* 标题、编号、数字 */ --font-mono: ui-monospace, SFMono-Regular, "Cascadia Mono", Consolas, monospace; ``` - **`--font-display` 只给拉丁**:Rajdhani(SIL OFL 1.1,许可全文在 `assets/fonts/OFL.txt`, 三个 woff2 就在同目录)是免费里最接近游戏里那支八角工业体的字。**它一个汉字都没有**, 汉字照旧落回系统字族——所以显示字体只许挂在「标题、编号、大数字、路径」上, 拿它去排整段中文正文是没用的。 - 官方站真正用的 `Novecento Sans Wide` 与 `Trajan` 是**商业授权,不能随包发**; `Bender` 是免费发的,但我们的中文环境里收益不大。别再引第三个显示字族。 - 数字一律 `font-variant-numeric: tabular-nums`,别让它们在刷新时跳。 ### 3.2 字号表 这张表是全站字号的**唯一来源**。新元素先在这张表里找身份,找不到再商量,别现编一个 15.5px。 | 角色 | 字号 | 字重 | 行高 | 字距 | 颜色 | | --- | --- | --- | --- | --- | --- | | 页面大标题 | 30px | 600 | 1.25 | -0.01em | `--ink` | | 大数字(KPI) | 30px | 600 | 1.1 | -0.02em | `--ink` | | 卡头 `h2` | 17px | 600 | 1.4 | -0.005em | `--ink` | | 小节 `h3` | 14px | 600 | 1.45 | 0 | `--ink` | | 正文 | 14px | 400 | 1.7 | 0 | `--text` | | 引导正文(`.lede` / `.guide-text`) | 15px | 400 | 1.7 | 0 | `--text` | | 次要正文 | 13px | 400 | 1.65 | 0 | `--dim` | | 标签 / 元信息 | 12px | 500 | 1.5 | +0.02em | `--dim` | | 微标(计数、路径) | 11.5px | 500 | 1.45 | +0.01em | `--faint` | | 计时器 | 54px | 600 | 1.05 | -0.01em | `--ink` | | 代码 / 路径 | 12px | 400 | 1.55 | 0 | `--dim`(`--font-mono`) | ### 3.3 字重阶梯 **中文只有 400 / 500 / 600 三档。** - `400` 正文、说明、长段落。 - `500` 标签、药丸、导航条目、列表里的次要强调。 - `600` 卡头、小节标题、按钮文字、大数字。 - `700` **只留给拉丁显示层**(Rajdhani 的编号、`NN / NN`、大写微标)——那些是图形化的 字,不是中文句子。 **不给中文用 700。** 中文黑体在 700 上会糊成一团,层级靠的是**字号 + 颜色 + 间距**。 ### 3.4 字距 - **汉字、中文标签、中文正文:一律 `0`。** 给中文加字距是外行做派,也让标题变散。 - 拉丁微标(全大写):`+0.08em` ~ `+0.18em`,配合 `text-transform: uppercase`。 - 拉丁编号 / 数字 / 路径:`+0.06em`。 - 字号 ≥ 24px 的显示字:负字距 `-0.01em` ~ `-0.02em`。 ### 3.5 行高 正文 `1.7`(中文比西文需要更多行距),次要正文 `1.65`,标题 `1.25`~`1.45`, 大数字 `1.1`。**行高低于 1.5 的正文一律不合格。** --- ## 4. 间距 ### 4.1 刻度 只有两套数,别在这两套外面现造: **一、版式刻度(块与块之间):4 / 8 / 12 / 16 / 20 / 24 / 32 / 48。** 小控件内部用 4 与 8,块内元素之间用 8 与 12,卡片内边距用 16~20,模块之间用 20~32, 页面级大分隔用 48。**这几个值才是「布局」的答案。** **二、组件微调值(块内部的缝):1 / 2 / 3 / 5 / 6 / 7 / 9 / 10 / 11 / 13 / 17 / 18。** 一行文字和它旁边的图标之间、药丸的左右内衬、卡头竖条和标题之间——这类缝比 4px 还小, 硬套 4 的倍数反而会松。这一组是**封闭名单**,CSS 里现存的就这些。 真正要守的纪律是这一条:**改之前先看这个位置别人用的是什么值,用同一个。** 同一个位置上出现 7px 和 8px 两种数,才是「乱」的来源。 ### 4.2 常用值 | 位置 | 值 | | --- | --- | | 页面左右内边距 | 24px(侧栏模式 12px) | | 页面底部留白 | 72px(给悬浮按钮让位) | | 顶栏下边距 | 20px | | 卡片内边距 | 16px 20px | | 卡片之间 | 12px | | 卡头到下边内容 | 12px | | 列表行内边距 | 8px 12px(紧凑版 5px 9px) | | 列表行之间 | 8px(紧凑版 4px) | | 表单控件之间 | 8px | | 一栏之内的小节之间 | 20px | | 正文段落之间 | 10px | ### 4.3 留白哲学:**功能性,不是奢侈** 每一块给一点空气,让人分得清这是两块东西;**但不要留大片空区**。 这是每天要用的工具,不是宣传页。判断标准很简单:如果一块空白没有帮你分组、 也没有帮你聚焦,它就是浪费。 --- ## 5. 布局 ### 5.1 版心 - 浏览器模式:`max-width: 1160px`(两栏)。做题页、读卷页是单栏长文,单独压回 `900px`。 - 侧栏模式:撑满,左右 12px。 - 正文行宽控制在 **60 个字符以内**(`max-width: 60ch`),再宽就该分栏了。 ### 5.2 两种模式 - **browser**:两栏,主栏 `1.45fr` / 边栏 `1fr`,**两个独立的竖列容器**,各自往下摞。 不要用 `column-count` 做瀑布流——多栏是全局平衡的,一张宽卡会在它上面留个大洞。 窄屏(≤ 820px)塌成单列。 - **sidebar**:单列,卡片**默认折起来只留一行名字**,进哪一页就把那一页的主卡展开。 ### 5.3 区块组织 页面是**一段段堆起来的积木**,不是一整个仪表盘面板:每张卡有自己的头、自己的身体, 卡与卡之间靠 12px 间距和一条边线分开。卡内部再分组时,用 `h3` 小节标题 + 8px 间距, **不要再套一层带边框的盒子**——更不要给每个模块都做一圈描边圆角卡,那是官方站明说的反例。 ### 5.4 响应式 断点:**480 / 820**(外加做题页 `practice.css` 自己那条 560 的 `PICK` 塌点)。规则: - 窄屏优先保证**内容可读**,再谈布局技巧。宁可把模块堆成一列,也别把字号压到 13px 以下。 - 复杂网格在窄屏塌成单列。 - 触控目标最小 **40×40px**。 - 表格 / 日历这类东西允许**横向滚动**,别压碎列。 --- ## 6. 组件 ### 6.1 按钮 三种,别造第四种。**圆角 0,全部方角**;主按钮左侧那条信号条是 `.btn.primary` 唯一的装饰。 ```css /* 主按钮:一屏最多一颗,就是「现在该点的那颗」。左起 10px 处一条信号条, hover 时那条从方块变成三角并向右挪 2px——官方站主按钮就是这个动作。 */ .btn.primary { min-height: 40px; padding: 0 16px 0 28px; /* 左边多留出来给信号条 */ font-size: 14px; font-weight: 600; letter-spacing: .04em; color: var(--on-accent); /* 黑字 */ background: var(--accent); /* 青底 */ border: 1px solid var(--accent); border-radius: 0; } /* 次按钮:细边方角,成组出现(取消 / 换一个 / 展开) */ .btn { min-height: 40px; padding: 0 16px; font-weight: 500; color: var(--text); background: var(--card); border: 1px solid var(--line-2); border-radius: 0; } .btn:hover { border-color: var(--accent); color: var(--ink); } /* 幽灵按钮:不描边,只留一条底细规(官方站那套 ghost) */ .btn.ghost { background: transparent; border-color: transparent; border-bottom: 1px solid var(--line-2); color: var(--dim); } .btn.ghost:hover { border-bottom-color: var(--accent); background: var(--card-2); } ``` - **高度 40px**;密集区域(列表行内、页码)可以降到 28px,但那是例外,要写注释说明。 - **不做发光、不做渐变、不做模糊阴影。** 整钮位移最多 1~2px。 - 主按钮一屏最多一颗。两颗青按钮等于没有重点。 ### 6.2 卡片 ```css .card { background: var(--card); border: 1px solid var(--line-2); /* 外沿收到强调级 */ border-radius: 0; padding: 16px 20px; margin-bottom: 12px; box-shadow: none; /* 抬升只给真浮层 */ position: relative; } .card::before { /* 左上角一个 12×12 的角包,只钉一个角 */ content: ""; position: absolute; top: -1px; left: -1px; width: 12px; height: 12px; border-top: 1px solid var(--accent); border-left: 1px solid var(--accent); } ``` - **圆角 0**。这套家族里没有圆角卡片这种东西。 - **默认无阴影**。深色下层次靠「面与面的明度差 + 一条细规」,再加阴影就是脏。 - 卡头用 `.card-head`:`h2` 17px/600,左边一条 3×14px 的 `--accent` 竖条。 - 角包**只钉左上**;四角都加就变成「复古科技边框」,那是反例。 ### 6.3 导航栏 ```css .top { position: sticky; top: 0; z-index: 20; padding: 12px 0; margin-bottom: 20px; background: color-mix(in srgb, var(--bg) 92%, transparent); backdrop-filter: blur(8px); /* 全站唯一允许 backdrop-filter 的地方 */ border-bottom: 1px solid var(--line-2); } .top::after { /* 底沿一条 3px 的琥珀斜纹,压得很低 */ content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 3px; background-image: repeating-linear-gradient(115deg, var(--warn) 0 5px, transparent 5px 12px); opacity: .5; pointer-events: none; } ``` - 导航条目是**文字**,不是按钮:13px / 500 / `--dim`,当前页是 `--ink` + 一条 2px 青下划线 + 一块 12% 的青底,**不能只靠颜色区分**。 - **不要药丸底、不要大色块。** - **通栏用 `position: sticky` 自己撑满,绝不用负边距**——负边距会让页面比视口宽, 窄屏右边一圈内容会被切掉。 ### 6.4 表单控件 ```css input, select, textarea { min-height: 40px; padding: 8px 12px; font-size: 14px; color: var(--text); background: var(--input); border: 1px solid var(--line-2); border-radius: 0; } input:focus { border-color: var(--accent); box-shadow: none; } /* 一条青边就够 */ ``` - 边框用 `--line-2`(比卡片边线深一档),因为输入框是**能被操作的东西**,要显出来。 - 聚焦**不加光圈**:官方站那套里没有「到处辉光」这一档。 - `::placeholder` 用 `--faint`,`--dim` 留给真信息。 ### 6.5 标签、药丸、状态 - **没有胶囊。** 计数、状态、筛选一律**方角**:`--card-2` 底 + `1px --line` 边 + 12px/500。 - **状态标签**:`1px solid currentColor`、文字色即状态色(`--ok` / `--warn` / `--bad`)。 **不用实心底**——实心标签在一行里太响。 - **`.tag`**(类别、来源):方角小标签,`--fs-micro`(11.5px),底用 `--card-2`。 - 标签都**不长于 6 个汉字**,超了就换行或者改成一句话。 ### 6.6 列表 ```css .list { display: grid; gap: 8px; } .list li { position: relative; padding: 8px 12px; background: var(--card-2); } ``` - 列表行**用 `--card-2` 的淡底而不是描边**,因为一行挨着一行,描边会变成栅栏。 - hover 时右下角冒一个 10×10 的角包(`.list li::after` / `.entry::after`), 这是「这一行可以点」的提示,不靠变色。 - `.list.tight`:紧凑版,`gap: 4px`、`padding: 5px 9px`、13px。 - 危险操作(删除确认)那一行换 `--danger-bg` + 一道 `--bad` 边。 - **列表里的行内小按钮一律 `.mini`**(28px 高、12px 字、白底细边)。 ### 6.7 进度条 高度 6~8px,**方角**,轨道用 `--line-2` 压出来的半透明灰,填充 `--accent`。 **不要在填充上加渐变。** 分段用 N 个 div + `1px` 的缝(`.bar { gap: 1px }`), 番茄钟那条轨道更要分段——两条都压在近黑面上,不分段就看不见还剩多少。 ### 6.8 空态 空态**不画插画**,一句话说清「为什么现在是空的 + 怎么让它不空」, `.dim` 13px/1.65,必要时配一颗次按钮。别用「暂无数据」。 --- ## 7. 层次与阴影 | Token | 值(深色) | 用在哪 | | --- | --- | --- | | `--shadow` | `none` | 卡片、导航。默认就是没有 | | `--shadow-sm` | `none` | 连 hover 也不给模糊阴影 | | `--shadow-pop` | `.35rem .35rem 0 color-mix(in srgb, var(--accent) 30%, transparent)` | 浮层:悬浮聊天窗、吐司。**零模糊硬偏移** | | `--shadow-modal` | `.5rem .5rem 0 rgba(0,0,0,.55)` | 模态框(它盖在遮罩上,硬黑就够) | **规矩一句话:先用细规和面层级拉层次,抬升只给「真的浮在页面上面」的东西, 而且抬升是「往右下硬挪一格」,不是高斯模糊。** **不要玻璃拟态**(`backdrop-filter` 只给顶栏那一层)、不要发光、不要彩色渐变。 ### 7.1 造型动机(`style.css` 末尾那一节「方舟层」) 这一节是全站共用的小配件,**一个组件只许用一样,不要叠**: | 手法 | 用在哪 | 实现 | | --- | --- | --- | | **细规** | 卡片外沿、分隔线、输入框 | `1px solid var(--line-2)` | | **角包** | 卡片左上、列表行 / `.entry` 的右下(hover 才现) | 一个 12×12 的 `::before`,只留两条 1px 边 | | **切角** | 只给 `.fab`(右下角那颗悬浮按钮) | `clip-path: polygon(...)` 切**右上**一个角 | | **斜纹** | 顶栏底沿那一条 3px | `repeating-linear-gradient(115deg, var(--warn) 0 5px, transparent 5px 12px)`,透明度过半 | | **菱形** | 档位圆点(`.dot`) | `border-radius: 0` + `rotate(45deg)` | | **信号条** | 主按钮左侧、`.brand` 左侧 | 3~7px 宽的青 / 黑竖条,hover 时变三角 | | **索引字** | `.hero .eyebrow`、`.stat-label`、路径、计时 | `--font-display` + 大写 + 字距 + 等宽数字 | | **硬偏移** | 吐司、悬浮窗 | `--shadow-pop` | 反过来说:**不许**给中文加字距、不许给中文排衬线、不许把每个容器都切一刀、 不许在静态面板上描青边、不许给大段正文上信号色、不许出现胶囊。 --- ## 8. Do / Don't **Do** - 用近黑中性面当默认基调;信号青留给当前项、动作和进度。 - 靠**细规 + 面层级 + 角包 + hover 填充**做层次。 - 卡头 17/600、正文 14/400 —— 层级靠这三样:字号、颜色、间距。 - 版面按「一段段积木」组织,每块有自己的头。 - 让长文读起来舒服:14px、行高 1.7、行宽 60ch 以内。 - 数字用等宽数字(`tabular-nums`),拉丁编号用 `--font-display` 加一点字距。 - 中文与拉丁分开排:汉字用系统字族、字距 0;编号与数字才上显示字体。 **Don't** - 别在规则里写死色值,一律走变量。 - 别把信号青铺到标题、正文、分隔线、静态卡片描边和装饰块上。 - 别用胶囊 / `999px`;别把圆角开到 2px 以上(功能性切角除外)。 - 别用带模糊的投影、发光、装饰性渐变、到处 glassmorphism。 - 别给中文加字距,别用衬线排中文正文,别用 700 排中文。 - 别用「黑底 + 青边 + 到处辉光」那套偷懒的「科幻感」,也别加扫描线、glitch、终端噪音、 六边形——**没有信息作用的装饰一律不加**。 - 别在版式刻度(4/8/12/16/20/24/32/48)外现造一个新数。 - 别在窄屏把字号压到 13px 以下;交互目标别小于 40×40px。 - 别一次上三种以上功能色。 - 别用「暂无数据」这种空话,把原因和下一步写出来。 - **别把游戏素材拷进仓库**:logo、角色立绘、UI 截图、官方 CDN 上的任何图,一律不许; 这一版全部是 CSS / SVG 自己画的。字体只许用 OFL 授权的(Rajdhani 是), 商业授权的那几支(Novecento Sans Wide / Trajan)不许嵌。 --- ## 9. 给新页面的一段话(写新页面前把这段抄进脑子) > 现在我要做一个新页面。按 `design.md` 来:画布 `--bg`,卡片 `--card`**方角** + 一条 > `--line-2` 边、左上角一个 12×12 的 `--accent` 角包、**不加阴影**、内边距 16/20; > 卡头 `h2` 17px/600 `--ink`,带一条 3×14px 的 `--accent` 竖条;正文 14px/400/1.7 > `--text`,说明文字 13px `--dim`;间距只用 4/8/12/16/20/24/32/48,卡与卡之间 12px; > 主按钮一屏最多一颗(青底黑字、方角、左侧一条信号条、40px 高),其余是细边方角次按钮; > 列表行用 `--card-2` 淡底、不要描边;信号青只出现在动作、当前项和进度条上; > 拉丁编号用 `--font-display` 加 .06~.18em 字距,**中文一律不加字距**。 --- ## 10. 落地位置 | 文件 | 管什么 | | --- | --- | | `assets/style.css` | 面板全部样式。顶部 `:root` 是唯一的变量来源,**末尾那一节「方舟层」是造型层** | | `assets/practice.css` | 做题页。只写这一页特有的东西,其余继承 `style.css` | | `assets/read.css` | 读卷页(AI 出的卷子、`.md` / `.txt`)。同上,且**一条 `var(--x, 兜底值)` 都不写** | | `assets/graph.css` | 知识图谱(SVG 内部无法用 CSS 变量的地方才写死,并留注释) | | `assets/fonts/` | Rajdhani 三个 woff2 + `OFL.txt`。汉字不在这里 | | `lib/review.js` | 复盘图(独立渲染的 SVG,**不跟 CSS 变量走**,色板在文件顶上那一块) | | `design.md` | 就是这一份(放仓库根目录,不在 assets 里) | 改配色或刻度要一起动的地方:`style.css` 的 `:root`、`html[data-theme="light"]`、 `graph.css` 里那些 `var(--x, 兜底色)` 的兜底值、以及 `lib/review.js` 顶上那两块色板。 (`read.css` 不在这几处里——它刻意一个兜底值都不写,`test/mirrors.test.js` 那条 「兜底值必须跟 `:root` 逐字相同」的守卫对它无事可做,也少一处以后会漂的地方。)