# DESIGN.md — Natural Memory 站点重设计 > 这份文件是**设计动作的产物**,写在动效之前。依据是 `motion-web` skill: > `page-design.md`(静态帧怎么设计)、`design-slop.md`(AI 味闸门)、`data/visual-bank.json`(可选原型)、 > `motion-tokens.md`(时长/缓动/弹簧)、`choreography-arc.md`(叙事弧)。 --- ## 0. 先测量,再设计:旧版站点的问题(实测,不是印象) 在 `assets/_gate.html` 里按 `design-slop.md` + `page-design.md §2` 的可量化条款跑了一遍旧站(1576px,12 页): | 闸门 | 获奖站中位数(n=12) | 旧站实测 | 判定 | |---|---|---|---| | 最大渲染字号 | **108 px**(52–218) | **48 px** | ❌ | | 正文字号 | 16 px(12–16) | 12–14 px | ✅ | | **display ÷ body** | **≈ 8×**(3.3–14×) | **3.4–4.0×** | ❌ A6 | | 主色数量 | **4**(1–6) | 6–7 | ❌ A4 | | 渐变 | **0 / 15** | home 2、results 10 | ❌ A4 | | body 全局 max-width | 15/15 无 | 无 | ✅ | | `

` 数量 | — | 1 | ✅ | **结论**:旧站最大的问题是**字阶没有落差**。48 px 的标题正好落在 `design-slop.md` A6 点名的 「everything between 16 and 48px」区间里 —— 那不是「不够大」,是**整个页面没有尺度对比**。 这一条足以解释「普通 / 没设计感」,而且**加留白、换配色都救不回来**。 其余是次要的:颜色偏多、有几处渐变、色带落在 2–6 屏这个「中段」(获奖站是双峰的:≈1 屏或 7–57 屏)。 ### 重设计之后(同一把尺子,同样 12 页,1576px) | 闸门 | 获奖站中位数 | 旧站 | **新站** | 判定 | |---|---|---|---|---| | 最大渲染字号 | 108 px | 48 px | **200 px**(`.mega`)/ 132 px(首屏标题) | ✅ | | display ÷ body | ≈ 8× | 3.4–4.0× | **7.1 – 14.3×**(12/12 页 ≥ 7.1) | ✅ | | 字体家族 | 2 | 3(含一个漏出来的 `monospace`) | **2** | ✅ | | `

` 数量 | — | 1 | 1 | ✅ | | 首屏按钮对 | A1 反模式 | 6 个药丸 | **0** | ✅ | | 横向溢出 / 截断 / undefined / NaN | — | 0 | **0(12 页 × 4 档视口)** | ✅ | | 渐变 | 0 / 15 | home 2, results 10 | 仅剩基线条的**斜纹填充**(语义编码,见下) | ⚠️ 保留 | **顺带修掉一个真 bug**:`
` 一直没有显式 `font-family`,掉回 UA 样式表的 `monospace` ——
**全站代码块此前都不是 Geist Mono**。这也是「字体家族 = 3」的来源。已修。

**唯一保留的渐变**:`.bar--base .bar__fill` 用的是 `repeating-linear-gradient` 斜纹,
它编码的是「无记忆基线」这一条数据,是数据墨水不是装饰(A4 针对的是渐变**背景处理**)。

---

## 7. 明确的偏差与代价(不藏)

1. **移动端的字阶落差改用「数字」承担 —— 这一条已经解决,不是遗留问题。**
   中文标题在 320px 上推不到 7×:`page-design.md §4` 自己写了
   「weight contrast carries hierarchy better than size contrast alone, because a huge 黑体 becomes a solid block」——
   320px 宽放 98px 的中文标题,一行只有 3 个字,13 个字的标题要断成 5 行,那是排版事故。
   所以**每个证据页的页眉由一个真实数字领起**(`.doc__figure` + `.mega`),
   中文标题负责可读性,数字负责落差。实测结果:

   | 视口 | 12 页 ratio 最小值 | ≥ 7× 的页数 | 布局问题 |
   |---|---:|---:|---:|
   | 1600 px | **11.1×** | 12 / 12 | 0 |
   | 768 px | **7.8×** | 12 / 12 | 0 |
   | 390 px | **7.1×** | 12 / 12 | 0 |
   | 320 px | **7.1×** | 12 / 12 | 0 |
   | 1600 px + reduced-motion | **11.1×** | 12 / 12 | 0 |

   这不是把数字调到达标,而是**让每一页自己先把最强的那条数字说出来** ——
   这些页面本来就是证据页,页眉只有一个标题反而浪费了它们最好的东西。
2. **地址空间装置在 `≤900px` 与 `prefers-reduced-motion` 下不下降**,冻结成一帧静态地址空间
   (窄屏冻结在 t=0.30「Qwen hidden state」,reduced-motion 冻结在 t=0.52「候选页」)。
   页面高度同时从 340vh 收到 1 屏,不留下 3 屏的空滚动。
3. **`--body` 用 `#9a9a92` 而不是 p-07 原型写的 `#909090`** —— 为了 12 页技术文档的连续阅读,
   在原型值上抬了一档(对比度 7.6:1,AAA 正文标准以上)。这是对原型的**唯一**颜色偏离,特此标明。

---

## 8. 动效闸门自检结果(B1–B8)

| 闸门 | 实测 | 处置 |
|---|---|---|
| B1 统一上浮 hover | `translateY(-*)` 命中 **0** | ✅ |
| B2 全页统一 fade-up | 原本 ~20 个元素同款入场 → 现在 **3 处,三种不同手势**(擦除 / 数字冲入 / 侧向错峰)+ 路径图自己的画线 | ✅ |
| B3 一个缓动一个时长 | 原本 5 个时长令牌有 3 个没用、**15 处硬编码 `120ms ease-out`** → 现在 **23 条 transition 全部走令牌**,实际用到 fast/std/med/slow **4 档** | ✅ |
| B4 预算全烧在首屏 | 首屏是装置,但 ~60% 处另有头号数字、重启装置两处收网 | ✅ |
| B5 动效与内容无关 | 机制来自「寻址」本身的物理,换到别的题材讲不通 | ✅ |
| B6 只有视差做纵深 | 无视差图层 | ✅ |
| B7 跟随光标的圆圈 | 无 | ✅ |
| B8 reduced-motion 下什么都不剩 | 实测 `wipeTarget=none`、装置冻结成完整静态帧、页高收到 1 屏、12 页 0 布局问题 | ✅ |

**顺带修掉的三个健壮性问题**(都不是猜的,是量出来的):

1. **`
` 没有 `font-family`** → 掉回 UA 的 `monospace`,**全站代码块此前都不是 Geist Mono**。
2. **入场只靠 `IntersectionObserver`** → IO 在被节流的 iframe / 无头虚拟时间 / 某些低端 WebView 里不保证投递;
   而 `clip-path` 擦除一旦不触发就是**一个永远看不见的标题**。已加「按滚动位置判定」的兜底,实测未入场元素从 **5 → 0**。
3. **首屏循环 latch**:`raf` 句柄非空但帧被冻结时,`kick()` 永远提前返回,循环永久卡死。
   已改为超时同步走一帧 —— 实测 `spaceT` 从 **0.00 → 0.39**。


---

## 1. 叙事结构(macrostructure)

**Editorial + set-pieces** —— 页面主体是**可读的正文**,动效出现 3 次、每次都有明确含义,
是段落之间的标点,不是背景装饰。

选它的理由来自内容本身:这是一个**研究发布站**,主体是 12 页文档、数据表和一份 108 条台账。
把它硬塞进「单场景」或「Acts」会牺牲可读性;而纯粹的 Editorial 又浪费了这套内容里
**唯一真正有空间感的东西 —— 记忆的地址空间**。

- **线性内容** → 走 editorial,而不是 index / instrument(`page-design.md §1` 的两条判据之一)。
- **相机移动还是世界移动**:世界移动(地址空间被镜头穿过),所以镜头更像「下降」而不是「横摇」。

**叙事弧:`cold-open`**(安静入场 → 复杂度上升 → 峰值 → 收束)
`0–20%` 极简、只有字;`20–70%` 地址空间下降(峰值在此);`70–100%` 结果与边界,留白放开。

---

## 2. 视觉系统(提交一个原型,不混搭)

来自 `data/visual-bank.json`,**选一个、执行到底**:

- **调色:`p-07 Bold Black + Signal Accent`**("creative agencies, award sites, experimental portfolios, bold studios")
  - ground `#000000`(纯黑,不是近黑)
  - ink `#fffef4`(骨白,不是纯白)
  - ink-2 `#909090` / ink-3 `#555555`
  - surface `rgba(255,255,255,.05)` · border `rgba(255,255,255,.12)`
  - **信号色 `#00ff6a`,每页只出现一次**(原型原文:one per page max)
  - 主色数量从 6–7 压到 **≤4**;**渐变全部删除**
- **字体:两个家族**(获奖站中位数就是 2,range 1–4)
  - `Archivo Variable`(wght 100–900 · wdth 62–125%)—— 显示与正文的拉丁部分、**全部数字**
  - `Geist Mono` —— 标签、代码、字段名
  - 中文回落到系统 CJK(PingFang SC / 微软雅黑 / Noto Sans CJK),**不额外加载 CJK 字体**

### 2.1 字阶:落差就是设计(`page-design.md §4`)

| 令牌 | 值 | 用途 |
|---|---|---|
| `--fs-mega` | `clamp(4.5rem, 12vw, 12.5rem)` = 72 → **200 px** | 拉丁/数字巨字 |
| `--fs-display` | `clamp(2.75rem, 7vw, 6.5rem)` = 44 → **104 px** | 页面主标题 |
| `--fs-h2` | `clamp(1.75rem, 3.4vw, 3rem)` | 章节标题 |
| `--fs-lede` | `1.125rem` | 导语 |
| `--fs-body` | `0.875rem` | **正文(14 px)** |

`mega ÷ body = 200/14 ≈ 14×`(获奖站上沿),`display ÷ body ≈ 7.4×`(≈ 中位数 8×)。
旧站是 3.4× —— **这是本次重设计的核心动作**。

### 2.2 中日韩显示字的特殊处理(`page-design.md §4` 明确点名)

中文大字和拉丁大字**不是一套参数**:

| | 行高 | 字距 | 字重 |
|---|---|---|---|
| 拉丁/数字 `.dsp--lat` | 0.90 | `-0.045em` | 700,`font-stretch: 92%` |
| 中文 `.dsp` | **1.28** | **-0.005em** | 500 |

中文行高更大、负字距要收(不然字腔会闭合),层级**靠字重对比**而不是只靠字号。
所以拉丁与中文的 display 是两个 class,在标记里显式指定,不靠回落碰运气。

---

## 3. 版面(layout)

- **全幅页面,逐元素设 measure**(获奖站 15/15 都没有 body 全局 max-width):
  `--measure: 62ch` 用于连续正文,`--measure-wide: 88ch` 用于说明,媒体全幅。
- **间距不是常数**(`page-design.md §6`):`--band-tight 48–80px` / `--band 80–160px` /
  `--band-wide 120–260px`,按「两块该不该被读成一组」来给。
- **至少三种不同的 section 形状**:全幅巨字带 / 非对称 2:1 分栏 / 数据表带 / 卡片网格 /
  装置带(整屏交互)/ 引用带 —— 不允许「每段都是居中标题 + 段落」。

---

## 4. 动效概念(来自题材自身的物理)

**概念名:地址空间下降(Address Descent)**

题材的物理就是**寻址**:1,048,576 个槽位、738 条活跃记录、730 个 LSH 桶、
每页 32 条、每次只把少量记录提升到 GPU。整条读取路径本来就是**一次下降**:
问题 → 128 维地址 → 粗索引桶 → 候选页 → 页内重排 → Top-K → 证据前缀 → 生成。

**招牌场景**:一个整屏的地址空间栅格(1,048,576 个槽位画成点阵,738 个亮着)。
滚动时镜头**一路下降五个数量级**:整个空间 → 730 个桶 → 一页 32 条 → 一条记录 →
这条记录变成注入模型的前缀 token。终点是**一条记录**,不是一句 slogan。

这个机制满足 `design-slop.md` B5(机制必须来自题材自身的物理):换到任何别的题材上都讲不通。

**动效令牌**(`motion-tokens.md`,至少三档时长 + 弹簧):

| 令牌 | 值 | 用途 |
|---|---|---|
| `--dur-fast` | 160ms | 悬停、按下、开关 |
| `--dur-std` | 300ms | 面板、抽屉、状态切换 |
| `--dur-med` | 460ms | 区块入场(少数几处) |
| `--dur-slow` | 700ms | 巨字入场 |
| `--dur-cine` | 1200ms | 冷开场 |
| `--ease-exp` | `cubic-bezier(.16,1,.3,1)` | 默认出场 |
| `--ease-sharp` | `cubic-bezier(.65,0,.45,1)` | 硬切、品牌感 |
| `--ease-in-expo` | `cubic-bezier(.7,0,.84,0)` | **只用于离场** |

**明确不做什么**(对应 `design-slop.md` B1–B8):
- B1 不做「所有卡片统一上浮 4px + 阴影」
- B2 不做「每个区块都 fade-up 20px」—— 大多数内容**本来就在那儿**,入场只留给 3 处
- B3 不允许全站一个 `0.3s ease`
- B4 不把预算全烧在首屏
- B7 不做跟随光标的圆圈
- B8 reduced-motion 下必须仍然是一张完整的页面

---

## 5. 移动端降级(`page-design.md §7`,显式写明,不含糊)

- **地址空间装置**:`< 900px` 关闭点阵与镜头下降,改为一帧静态的地址空间图 + 数字条。
  降级**不是**隐藏内容,是把动效换成静态帧。
- 巨字:`12vw` 下限 72px,320px 宽时仍是 72px(不缩到看不清)。
- 悬停不存在 —— 所有悬停信息必须有第二个落点(见设备页/台账页的显式状态)。
- 滚动在移动端更长,节奏按移动端重读一遍,不假设等比缩放。

---

## 6. 设计闸门自检(交付前必须全过)

`design-slop.md` A1–A8 / B1–B8 + `page-design.md §8`,用 `assets/_gate.html` 逐条量:

- [ ] A1 首屏不是「徽标 + 标题 + 副标题 + 两个按钮」
- [ ] A2 没有三张等宽居中卡片
- [ ] A3 每页 ≥3 种不同 section 形状
- [ ] A4 无紫/靛渐变;主色 ≤4;信号色每页只出现一次
- [ ] A5 没有噪点/光晕/网格纸这类「填空装饰」
- [ ] A6 display ÷ body ≥ 7×
- [ ] A7 没有手绘的假浏览器/假手机外壳
- [ ] A8 没有编造的证明(本站所有数字都来自工程内真实报告)
- [ ] B1–B8 动效闸门
- [ ] D 移动端 320/375/414/768 无横向滚动;reduced-motion 下页面完整