# DESIGN.md — 视觉风格约束
> 参考来源：2026-04-16-gemma4-jailbreak 项目（已完成上线）
> 所有新 slide 必须严格遵守本约束

---

## 1. 基础规格

| 项目 | 值 |
|------|-----|
| 分辨率 | 1920 × 1080（16:9） |
| 背景色 | `#060810`（深宇宙黑，非纯黑） |
| overflow | hidden，所有 slide 全屏覆盖 |
| 字体加载 | Google Fonts：Noto Sans SC (300/400/700/900) + JetBrains Mono (400/700) |
| 动画库 | GSAP 3.12.2 |
| 图表库 | ECharts 5 |

---

## 2. 颜色系统

| 用途 | 颜色 | 说明 |
|------|------|------|
| 主背景 | `#060810` | 深宇宙黑 |
| 主文字 | `#FFFFFF` | 纯白 |
| 主蓝（强调/流程/技术） | `#4D9EFF` | 科技蓝，用于 accent、SVG 连线、边框 |
| 警示红（危险/关键数据） | `#DC2626` | 用于 countup 数字、警告信息、markPoint |
| 卡片背景（蓝调） | `rgba(77,158,255,0.05~0.15)` | 低饱和蓝色底 |
| 卡片边框（蓝调） | `rgba(77,158,255,0.2)` 或 `#4D9EFF` | 视强调程度 |
| 次要文字 | `rgba(255,255,255,0.5~0.6)` | 弱化说明文字 |
| 代码块背景 | `#0a0a0a` | 比主背景略深 |

**禁止使用：**
- `rgba(255,255,255,0.2)` 用于正文（对比度极差）
- 暖色系（橙/黄）作为主 accent（这个系列用蓝+红，不用橙）
- 纯白背景、亮色背景

---

## 3. 字体规范

| 用途 | 字体 | 字重 | 字号范围 |
|------|------|------|---------|
| Slide 主标题 | Noto Sans SC | 900 | 72px ~ 100px |
| 超大冲击数字/标语 | Noto Sans SC | 900 | 100px ~ 240px |
| 副标题 / 说明 | Noto Sans SC | 400/700 | 28px ~ 48px |
| 次要说明 | Noto Sans SC | 300/400 | 24px ~ 32px |
| 代码 / 技术标识符 | JetBrains Mono | 400/700 | 28px ~ 64px |

**规则：**
- `font-family` 显式写 `'Noto Sans SC'` 或 `'JetBrains Mono', monospace`
- 标题必须 `white-space: nowrap`，宁可缩字号也不折行
- 关键词单独上色（`#4D9EFF` 或 `#DC2626`），不要整段上色

---

## 4. 布局规范

- 所有 slide 绝对定位 `position:fixed; inset:0`，全屏
- 内容水平垂直居中：外层 `display:flex; align-items:center; justify-content:center`
- 最大内容宽度：`max-width: 900px ~ 1600px`（根据内容密度）
- 卡片圆角：`border-radius: 12px ~ 16px`
- 卡片 padding：`40px ~ 64px`
- 元素间距 `gap`：`24px ~ 48px`

---

## 5. 背景视频（bg/）

每个 slide 有一个循环背景视频：
```html
<video class="slide-bg-video" loop src="bg/s01.mp4" muted playsinline preload="auto"
  style="position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
         opacity:0.25;filter:brightness(0.45)">
</video>
```
- `opacity: 0.25`，`brightness(0.45)` — 压暗处理，不抢前景
- 视频格式：mp4，循环，静音
- 必须放在 `.slide` 最顶部（最底层）

---

## 6. Scene 系统（每个 slide 内多场景切换）

```css
.scene { position:absolute; inset:0; display:flex; flex-direction:column;
         align-items:center; justify-content:center;
         opacity:0; pointer-events:none; transition:none; }
.scene.scene-on { opacity:1; pointer-events:auto; }
```

入场动画只有两种：
- `sf`（sceneFadeUp）：`translateY(32px) → 0, opacity 0→1, 0.6s ease-out`
- `sz`（sceneZoomIn）：`scale(0.1)→1, opacity 0→1, 0.6s ease-out`

调用方式：`sceneGo('s01', 's01-sc-2', 'sf')`

**规则：**
- 每个 slide 3~7 个 scene，避免超过 7 个
- scene 切换时间间隔通常 5~10 秒
- 第一个 scene 永远在 `t:0` 触发

---

## 7. 数据可视化规范

### SVG 图表（流程图、时间线、对比图）
- 背景透明
- 节点：`fill: rgba(77,158,255,0.15); stroke: #4D9EFF; stroke-width: 1~2`
- 连线：`stroke: #4D9EFF; stroke-width: 2~3`
- 文字：`fill: #FFFFFF; font-family: Noto Sans SC; font-size: 22~28px`
- 箭头：用 `<polygon>` 实现，填充 `#4D9EFF`

### ECharts 图表
- `backgroundColor: 'transparent'`
- 轴线颜色：`rgba(255,255,255,0.2)`
- 轴标签颜色：`#CCC`，字号 14~18px
- 主线条颜色：`#4D9EFF`，宽度 4px
- 数据点颜色：`#DC2626`
- 面积渐变：蓝色系，`rgba(77,158,255,0.3)` → `rgba(77,158,255,0)` 
- markPoint pin：`#DC2626`
- 标题：`color: #FFF; fontSize: 24~28px; fontFamily: Noto Sans SC`
- `animationDuration: 2000; animationEasing: 'cubicOut'`

### countUp 数字
```html
<span data-countup="90" data-suffix="%" data-duration="2"
      style="font-size:240px;font-weight:900;color:#DC2626">0</span>
```
- 超大数字用 `#DC2626`，字号 160px ~ 240px，字重 900
- 触发时机：scene 进入时自动启动

---

## 8. 代码块样式

```html
<div style="background:#0a0a0a;border-radius:12px;padding:48px 64px;text-align:center">
  <div style="font-size:64px;font-family:'JetBrains Mono',monospace">
    <span style="color:#4D9EFF">key</span><span style="color:#DC2626"> = value</span>
  </div>
  <div style="font-size:28px;color:rgba(255,255,255,0.5);margin-top:24px">说明文字</div>
</div>
```
- 关键词 → `#4D9EFF`
- 值/赋值 → `#DC2626`
- 说明 → `rgba(255,255,255,0.5)`

---

## 9. 引用块 / 强调框

```html
<div style="max-width:1200px;border-left:6px solid #4D9EFF;padding:32px 48px;
            background:rgba(77,158,255,0.05)">
  <div style="font-size:40px;color:#FFFFFF;line-height:1.6">文字内容</div>
</div>
```
- 左侧 6px 蓝色竖线 + 低饱和蓝底
- 字号 36~40px，`line-height: 1.6`

---

## 10. 对比卡片（两列）

```html
<div style="display:flex;align-items:center;gap:40px">
  <!-- 否定卡 -->
  <div style="width:720px;background:rgba(255,255,255,0.05);
              border:1px solid rgba(255,255,255,0.2);border-radius:16px;padding:40px">
    <div style="color:rgba(255,255,255,0.6);font-size:40px">❌ 方案A</div>
    <div style="color:rgba(255,255,255,0.4);font-size:28px;margin-top:16px">缺点说明</div>
  </div>
  <!-- 箭头 -->
  <svg width="60" height="40" viewBox="0 0 60 40">
    <path d="M0 20 L45 20 M35 8 L50 20 L35 32" fill="none" stroke="#4D9EFF" stroke-width="3"/>
  </svg>
  <!-- 肯定卡 -->
  <div style="width:720px;background:rgba(77,158,255,0.1);
              border:2px solid #4D9EFF;border-radius:16px;padding:40px">
    <div style="color:#4D9EFF;font-size:40px">✓ 方案B</div>
    <div style="color:#FFFFFF;font-size:28px;margin-top:16px">优势说明</div>
  </div>
</div>
```

---

## 11. 导航点（nav-dots）

```css
.nav-dots { position:fixed; bottom:24px; left:50%; transform:translateX(-50%);
            display:flex; gap:8px; z-index:100; }
.nav-dot { width:10px; height:10px; border-radius:50%;
           background:rgba(255,255,255,0.3); cursor:pointer; }
.nav-dot.active { background:#4D9EFF; }
```

---

## 12. 架构规范（文件结构）

```
slides/s01.html ~ sNN.html    每个 slide 一个 HTML 片段
bg/s01.mp4 ~ sNN.mp4          背景视频，每 slide 一个
tts/s001.mp3 ~ s032.mp3       语音文件
js/timelines.js               所有 slide 的 SCENE_OFFSETS + TIMELINES
js/engine.js                  sceneGo / countUp / setupAudioTimeline / showSlide
js/idle_effects.js            空闲效果（可选）
captions.js                   SubtitleEngine
index.html                    主入口，fetch 动态加载所有 slide 片段
```

**规则：**
- slide 片段通过 `fetch('slides/sXX.html')` 动态加载，不内联在 index.html
- 所有 timeline 集中在 `js/timelines.js`，不分散在 slide 片段里
- engine.js 负责 `showSlide` / `sceneGo` / `setupAudioTimeline`，slide 片段不写逻辑

---

## 13. 禁止事项

- ❌ 亮色背景（白/浅灰/浅蓝）
- ❌ 多于两种 accent 颜色（只用 `#4D9EFF` 蓝 + `#DC2626` 红）
- ❌ 文字折行（标题 `white-space: nowrap`）
- ❌ slide 内嵌逻辑 JS（业务逻辑全部在 engine.js / timelines.js）
- ❌ 超过 7 个 scene / slide
- ❌ 背景视频 opacity > 0.3（压暗，不抢前景）
- ❌ 使用 CSS transition 代替 GSAP / CSS animation 做入场（会和 engine 冲突）
