Files

231 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 无 | 无 | ✅ |
| `<h1>` 数量 | — | 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** | ✅ |
| `<h1>` 数量 | — | 1 | 1 | ✅ |
| 首屏按钮对 | A1 反模式 | 6 个药丸 | **0** | ✅ |
| 横向溢出 / 截断 / undefined / NaN | — | 0 | **0(12 页 × 4 档视口)** | ✅ |
| 渐变 | 0 / 15 | home 2, results 10 | 仅剩基线条的**斜纹填充**(语义编码,见下) | ⚠️ 保留 |
**顺带修掉一个真 bug**:`<pre>` 一直没有显式 `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. **`<pre>` 没有 `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 下页面完整