소스 검색

baseline before Darwin animation-practices round

Snapshots current state as fallback point:
- SKILL.md: Step 9 now defaults to SFX+BGM audio export (not optional)
- SKILL.md: §1.a core asset protocol adds Step 3.4 "5-10-2-8" quality gate for non-logo assets
- New assets/sfx/* library (37 SFX across 9 categories)
- New references/audio-design-rules.md + sfx-library.md + apple-gallery-showcase.md

Next: Darwin will propose animation-practices integration from the 参考动画
reference corpus (BEST-PRACTICES.md, ref-1/2/3 analysis). This commit is the
rollback point if the round doesn't land cleanly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
alchain 2 달 전
부모
커밋
e1b94a4680
41개의 변경된 파일861개의 추가작업 그리고 1개의 파일을 삭제
  1. 37 1
      SKILL.md
  2. BIN
      assets/sfx/container/card-flip.mp3
  3. BIN
      assets/sfx/container/card-snap.mp3
  4. BIN
      assets/sfx/container/modal-open.mp3
  5. BIN
      assets/sfx/container/stack-collapse.mp3
  6. BIN
      assets/sfx/feedback/achievement.mp3
  7. BIN
      assets/sfx/feedback/error-tone.mp3
  8. BIN
      assets/sfx/feedback/notification-pop.mp3
  9. BIN
      assets/sfx/feedback/success-chime.mp3
  10. BIN
      assets/sfx/impact/brand-stamp.mp3
  11. BIN
      assets/sfx/impact/drop-thud.mp3
  12. BIN
      assets/sfx/impact/logo-reveal-v2.mp3
  13. BIN
      assets/sfx/impact/logo-reveal.mp3
  14. BIN
      assets/sfx/keyboard/delete-key.mp3
  15. BIN
      assets/sfx/keyboard/enter.mp3
  16. BIN
      assets/sfx/keyboard/space-tap.mp3
  17. BIN
      assets/sfx/keyboard/type-fast.mp3
  18. BIN
      assets/sfx/keyboard/type.mp3
  19. BIN
      assets/sfx/magic/ai-process.mp3
  20. BIN
      assets/sfx/magic/sparkle.mp3
  21. BIN
      assets/sfx/magic/transform.mp3
  22. BIN
      assets/sfx/progress/complete-done.mp3
  23. BIN
      assets/sfx/progress/generate-start.mp3
  24. BIN
      assets/sfx/progress/loading-tick.mp3
  25. BIN
      assets/sfx/terminal/command-execute.mp3
  26. BIN
      assets/sfx/terminal/cursor-blink.mp3
  27. BIN
      assets/sfx/terminal/output-appear.mp3
  28. BIN
      assets/sfx/transition/dissolve.mp3
  29. BIN
      assets/sfx/transition/slide-in.mp3
  30. BIN
      assets/sfx/transition/swipe-horizontal.mp3
  31. BIN
      assets/sfx/transition/whoosh-fast.mp3
  32. BIN
      assets/sfx/transition/whoosh.mp3
  33. BIN
      assets/sfx/ui/click-soft.mp3
  34. BIN
      assets/sfx/ui/click.mp3
  35. BIN
      assets/sfx/ui/focus.mp3
  36. BIN
      assets/sfx/ui/hover-subtle.mp3
  37. BIN
      assets/sfx/ui/tap-finger.mp3
  38. BIN
      assets/sfx/ui/toggle-on.mp3
  39. 338 0
      references/apple-gallery-showcase.md
  40. 260 0
      references/audio-design-rules.md
  41. 226 0
      references/sfx-library.md

+ 37 - 1
SKILL.md

@@ -167,6 +167,34 @@ curl -A "Mozilla/5.0" -L "<hero-image-url>" -o assets/<brand>-brand/product-hero
 - 产品官方 Twitter/X 的发布截图(常是最新版本)
 - 产品官方 Twitter/X 的发布截图(常是最新版本)
 - 用户有账号时,直接截屏真实产品界面
 - 用户有账号时,直接截屏真实产品界面
 
 
+**3.4 · 素材质量门槛「5-10-2-8」原则(铁律)**
+
+> **Logo 的规则不同于其他素材**。Logo 有就必须用(没有就停下问用户);其他素材(产品图/UI/参考图/配图)遵循「5-10-2-8」质量门槛。
+>
+> 2026-04-20 花叔原话:「我们的原则是搜索 5 轮,找到 10 个素材,选择 2 个好的。每个需要评分 8/10 以上,宁可少一些,也不为了完成任务滥竽充数。」
+
+| 维度 | 标准 | 反模式 |
+|---|---|---|
+| **5 轮搜索** | 多渠道交叉搜(官网 / press kit / 官方社媒 / YouTube 截帧 / Wikimedia / 用户账号截屏),不是一轮抓前 2 个就停 | 第一页结果直接用 |
+| **10 个候选** | 至少凑 10 个备选才开始筛 | 只抓 2 个,没得选 |
+| **选 2 个好的** | 从 10 个里精选 2 个作为最终素材 | 全都用 = 视觉过载 + 品位稀释 |
+| **每个 8/10 分以上** | 不够 8 分**宁可不用**,用诚实 placeholder(灰块+文字标签)或 AI 生成(nano-banana-pro 以官方参考为基底)| 凑数 7 分素材进 brand-spec.md |
+
+**8/10 评分维度**(打分时记录在 `brand-spec.md`):
+
+1. **分辨率** · ≥2000px(印刷/大屏场景 ≥3000px)
+2. **版权清晰度** · 官方来源 > 公共领域 > 免费素材 > 疑似盗图(疑似盗图直接 0 分)
+3. **与品牌气质契合度** · 和 brand-spec.md 里的「气质关键词」一致
+4. **光线/构图/风格一致性** · 2 个素材放一起不打架
+5. **独立叙事能力** · 能单独表达一个叙事角色(不是装饰)
+
+**为什么这个门槛是铁律**:
+- 花叔的哲学:**宁缺毋滥**。滥竽充数的素材比没有更糟——污染视觉品味、传递「不专业」信号
+- **「一个细节做到 120%,其他做到 80%」的量化版**:8 分是"其他 80%" 的底线,真正 hero 素材要 9-10 分
+- 消费者看作品时,每一个视觉元素都在**积分或扣分**。7 分素材 = 扣分项,不如留空
+
+**Logo 例外**(重申):有就必须用,不适用「5-10-2-8」。因为 logo 不是「多选一」问题,而是「识别度根基」问题——就算 logo 本身只有 6 分,也比没有 logo 强 10 倍。
+
 ##### Step 4 · 验证 + 提取(不只是 grep 色值)
 ##### Step 4 · 验证 + 提取(不只是 grep 色值)
 
 
 | 资产 | 验证动作 |
 | 资产 | 验证动作 |
@@ -601,7 +629,15 @@ Screen 组件接 callback props(`onEnter`、`onClose`、`onTabChange`、`onOpe
 7. **验证**:用Playwright截图(见 `references/verification.md`),检查控制台错误,发给用户。
 7. **验证**:用Playwright截图(见 `references/verification.md`),检查控制台错误,发给用户。
    🛑 **检查点4:交付前自己肉眼过一遍浏览器**。AI写的代码经常有interaction bug。
    🛑 **检查点4:交付前自己肉眼过一遍浏览器**。AI写的代码经常有interaction bug。
 8. **总结**:极简,只说caveats和next steps。
 8. **总结**:极简,只说caveats和next steps。
-9. **(可选)导出视频**:如果是动画HTML,用户若提「导出/MP4/GIF/60fps」,按 `references/video-export.md` 走:`scripts/render-video.js` 录 25fps MP4 → `scripts/convert-formats.sh` 派生 60fps MP4 + palette 优化 GIF → `scripts/add-music.sh` 加 BGM(6 首场景化配乐,按 `--mood=tech/ad/educational/tutorial` 选)。
+9. **(默认)导出视频 · 必带 SFX + BGM**:动画 HTML 的**默认交付形态是带音频的 MP4**,不是纯画面。无声版本等于半成品——用户潜意识感知「画在动但没声音响应」,廉价感的根源就在这里。流水线:
+   - `scripts/render-video.js` 录 25fps 纯画面 MP4(只是中间产物,**不是成品**)
+   - `scripts/convert-formats.sh` 派生 60fps MP4 + palette 优化 GIF(视平台需要)
+   - `scripts/add-music.sh` 加 BGM(6 首场景化配乐:tech/ad/educational/tutorial + alt 变体)
+   - SFX 按 `references/audio-design-rules.md` 设计 cue 清单(时间轴 + 音效类型),用 `assets/sfx/<category>/*.mp3` 37 个预制资源,按配方 A/B/C/D 选密度(发布 hero ≈ 6个/10s,工具演示 ≈ 0-2个/10s)
+   - **BGM + SFX 双轨制必须同时做**——只做 BGM 是 ⅓ 分完成度;SFX 占高频、BGM 占低频,频段隔离见 audio-design-rules.md 的 ffmpeg 模板
+   - 交付前 `ffprobe -select_streams a` 确认有 audio stream,没有则不是成品
+   - **跳过音频的条件**:用户明确说「不要音频」「纯画面」「我要自己配音」——否则默认带。
+   - 参考完整流程见 `references/video-export.md` + `references/audio-design-rules.md` + `references/sfx-library.md`。
 10. **(可选)专家评审**:用户若提「评审」「好不好看」「review」「打分」,或你对产出有疑问想主动质检,按 `references/critique-guide.md` 走 5 维度评审——哲学一致性 / 视觉层级 / 细节执行 / 功能性 / 创新性各 0-10 分,输出总评 + Keep(做得好的)+ Fix(严重程度 ⚠️致命 / ⚡重要 / 💡优化)+ Quick Wins(5 分钟能做的前 3 件事)。评审设计不评设计师。
 10. **(可选)专家评审**:用户若提「评审」「好不好看」「review」「打分」,或你对产出有疑问想主动质检,按 `references/critique-guide.md` 走 5 维度评审——哲学一致性 / 视觉层级 / 细节执行 / 功能性 / 创新性各 0-10 分,输出总评 + Keep(做得好的)+ Fix(严重程度 ⚠️致命 / ⚡重要 / 💡优化)+ Quick Wins(5 分钟能做的前 3 件事)。评审设计不评设计师。
 
 
 **检查点原则**:碰到🛑就停下,明确告诉用户"我做了X,下一步打算Y,你确认吗?"然后真的**等**。不要说完自己就开始做。
 **检查点原则**:碰到🛑就停下,明确告诉用户"我做了X,下一步打算Y,你确认吗?"然后真的**等**。不要说完自己就开始做。

BIN
assets/sfx/container/card-flip.mp3


BIN
assets/sfx/container/card-snap.mp3


BIN
assets/sfx/container/modal-open.mp3


BIN
assets/sfx/container/stack-collapse.mp3


BIN
assets/sfx/feedback/achievement.mp3


BIN
assets/sfx/feedback/error-tone.mp3


BIN
assets/sfx/feedback/notification-pop.mp3


BIN
assets/sfx/feedback/success-chime.mp3


BIN
assets/sfx/impact/brand-stamp.mp3


BIN
assets/sfx/impact/drop-thud.mp3


BIN
assets/sfx/impact/logo-reveal-v2.mp3


BIN
assets/sfx/impact/logo-reveal.mp3


BIN
assets/sfx/keyboard/delete-key.mp3


BIN
assets/sfx/keyboard/enter.mp3


BIN
assets/sfx/keyboard/space-tap.mp3


BIN
assets/sfx/keyboard/type-fast.mp3


BIN
assets/sfx/keyboard/type.mp3


BIN
assets/sfx/magic/ai-process.mp3


BIN
assets/sfx/magic/sparkle.mp3


BIN
assets/sfx/magic/transform.mp3


BIN
assets/sfx/progress/complete-done.mp3


BIN
assets/sfx/progress/generate-start.mp3


BIN
assets/sfx/progress/loading-tick.mp3


BIN
assets/sfx/terminal/command-execute.mp3


BIN
assets/sfx/terminal/cursor-blink.mp3


BIN
assets/sfx/terminal/output-appear.mp3


BIN
assets/sfx/transition/dissolve.mp3


BIN
assets/sfx/transition/slide-in.mp3


BIN
assets/sfx/transition/swipe-horizontal.mp3


BIN
assets/sfx/transition/whoosh-fast.mp3


BIN
assets/sfx/transition/whoosh.mp3


BIN
assets/sfx/ui/click-soft.mp3


BIN
assets/sfx/ui/click.mp3


BIN
assets/sfx/ui/focus.mp3


BIN
assets/sfx/ui/hover-subtle.mp3


BIN
assets/sfx/ui/tap-finger.mp3


BIN
assets/sfx/ui/toggle-on.mp3


+ 338 - 0
references/apple-gallery-showcase.md

@@ -0,0 +1,338 @@
+# Apple Gallery Showcase · 画廊展示墙动画风格
+
+> 灵感来源:Claude Design 官网 hero 视频 + 苹果产品页「作品墙」式陈列
+> 实战出处:huashu-design 发布 hero v5
+> 适用场景:**产品发布 hero 动画、skill 能力演示、作品集展示**——任何需要把「多件高质量产出」同时展陈并引导观众注意力的场景
+
+---
+
+## 触发判断:什么时候用这个风格
+
+**适合**:
+- 有10张以上真实产出要同屏展示(PPT、App、网页、信息图)
+- 观众是专业受众(开发者、设计师、产品经理),对「质感」敏感
+- 希望传递的气质是「克制、展览式、高级、有空间感」
+- 需要焦点和全局同时存在(看细节但不失整体)
+
+**不适合**:
+- 单产品聚焦(用 frontend-design 的产品 hero 模板)
+- 情绪向/故事性强的动画(用时间轴叙事模板)
+- 小屏幕 / 竖屏(倾斜视角在小画面上会糊)
+
+---
+
+## 核心视觉 Token
+
+```css
+:root {
+  /* 浅色画廊调板 */
+  --bg:         #F5F5F7;   /* 主画布底 — 苹果官网灰 */
+  --bg-warm:    #FAF9F5;   /* 温暖米白变体 */
+  --ink:        #1D1D1F;   /* 主字色 */
+  --ink-80:     #3A3A3D;
+  --ink-60:     #545458;
+  --muted:      #86868B;   /* 次级文字 */
+  --dim:        #C7C7CC;
+  --hairline:   #E5E5EA;   /* 卡片1px边框 */
+  --accent:     #D97757;   /* 赤陶橙 — Claude brand */
+  --accent-deep:#B85D3D;
+
+  --serif-cn: "Noto Serif SC", "Songti SC", Georgia, serif;
+  --serif-en: "Source Serif 4", "Tiempos Headline", Georgia, serif;
+  --sans:     "Inter", -apple-system, "PingFang SC", system-ui;
+  --mono:     "JetBrains Mono", "SF Mono", ui-monospace;
+}
+```
+
+**关键原则**:
+1. **绝不用纯黑底**。黑底会让作品看起来像电影、不像「可以被采用的工作成果」
+2. **赤陶橙是唯一色相accent**,其他全部是灰阶 + 白
+3. **三字体栈**(serif英+serif中+sans+mono)营造「出版物」而非「互联网产品」的气质
+
+---
+
+## 核心布局模式
+
+### 1. 悬浮卡片(整个风格的基本单元)
+
+```css
+.gallery-card {
+  background: #FFFFFF;
+  border-radius: 14px;
+  padding: 6px;                          /* 内边距是「装裱纸」 */
+  border: 1px solid var(--hairline);
+  box-shadow:
+    0 20px 60px -20px rgba(29, 29, 31, 0.12),   /* 主阴影,软且长 */
+    0 6px 18px -6px rgba(29, 29, 31, 0.06);     /* 第二层近光,制造浮感 */
+  aspect-ratio: 16 / 9;                  /* 统一 slide 比例 */
+  overflow: hidden;
+}
+.gallery-card img {
+  width: 100%; height: 100%;
+  object-fit: cover;
+  border-radius: 9px;                    /* 比卡片圆角略小,视觉嵌套 */
+}
+```
+
+**反面教材**:不要贴边瓷砖(无padding无border无shadow)——那是信息图密度表达,不是展览。
+
+### 2. 3D倾斜作品墙
+
+```css
+.gallery-viewport {
+  position: absolute; inset: 0;
+  overflow: hidden;
+  perspective: 2400px;                   /* 深一些的透视,倾斜不夸张 */
+  perspective-origin: 50% 45%;
+}
+.gallery-canvas {
+  width: 4320px;                         /* 画布 = 2.25× viewport */
+  height: 2520px;                        /* 留出pan空间 */
+  transform-origin: center center;
+  transform: perspective(2400px)
+             rotateX(14deg)              /* 向后倾 */
+             rotateY(-10deg)             /* 向左转 */
+             rotateZ(-2deg);             /* 轻微倾斜,去掉太规整 */
+  display: grid;
+  grid-template-columns: repeat(8, 1fr);
+  gap: 40px;
+  padding: 60px;
+}
+```
+
+**参数 sweet spot**:
+- rotateX: 10-15deg(再多就像开酒会 VIP 背景板)
+- rotateY: ±8-12deg(左右对称感)
+- rotateZ: ±2-3deg(「这不是机器摆的」的人味)
+- perspective: 2000-2800px(小于2000会鱼眼,大于3000接近正投影)
+
+### 3. 2×2 四角汇聚(选择场景)
+
+```css
+.grid22 {
+  display: grid;
+  grid-template-columns: repeat(2, 800px);
+  gap: 56px 64px;
+  align-items: start;
+}
+```
+
+每张卡片从对应角落(tl/tr/bl/br)向中心滑入 + fade in。对应的 `cornerEntry` 向量:
+
+```js
+const cornerEntry = {
+  tl: { dx: -700, dy: -500 },
+  tr: { dx:  700, dy: -500 },
+  bl: { dx: -700, dy:  500 },
+  br: { dx:  700, dy:  500 },
+};
+```
+
+---
+
+## 五种核心动画模式
+
+### 模式 A · 四角汇聚(0.8-1.2s)
+
+4 个元素从视口四角滑入,同时缩放 0.85→1.0,对应 ease-out。适合「展示多方向选择」的开场。
+
+```js
+const inP = easeOut(clampLerp(t, start, end));
+card.style.transform = `translate3d(${(1-inP)*ce.dx}px, ${(1-inP)*ce.dy}px, 0) scale(${0.85 + 0.15*inP})`;
+card.style.opacity = inP;
+```
+
+### 模式 B · 选中放大 + 其他滑出(0.8s)
+
+被选中的卡片放大 1.0→1.28,其他卡片 fade out + blur + 向四角漂回:
+
+```js
+// 被选中
+card.style.transform = `translate3d(${cellDx*outP}px, ${cellDy*outP}px, 0) scale(${1 + 0.28*easeOut(zoomP)})`;
+// 未选中
+card.style.opacity = 1 - outP;
+card.style.filter = `blur(${outP * 1.5}px)`;
+```
+
+**关键**:未选中的要 blur,不是纯 fade。blur 模拟景深,视觉上把被选中的「推出来」。
+
+### 模式 C · Ripple 涟漪展开(1.7s)
+
+从中心向外,按距离 delay,每张卡片依次淡入 + 从 1.25x 缩到 0.94x(「镜头拉远」):
+
+```js
+const col = i % COLS, row = Math.floor(i / COLS);
+const dc = col - (COLS-1)/2, dr = row - (ROWS-1)/2;
+const dist = Math.sqrt(dc*dc + dr*dr);
+const delay = (dist / maxDist) * 0.8;
+const localT = Math.max(0, (t - rippleStart - delay) / 0.7);
+card.style.opacity = easeOut(Math.min(1, localT));
+
+// 同时整体 scale 1.25→0.94
+const galleryScale = 1.25 - 0.31 * easeOut(rippleProgress);
+```
+
+### 模式 D · Sinusoidal Pan(持续漂移)
+
+用正弦波 + 线性漂移组合,避免 marquee 那种「有起点有终点」的循环感:
+
+```js
+const panX = Math.sin(panT * 0.12) * 220 - panT * 8;    // 横向左漂
+const panY = Math.cos(panT * 0.09) * 120 - panT * 5;    // 纵向上漂
+const clampedX = Math.max(-900, Math.min(900, panX));   // 防止露边
+```
+
+**参数**:
+- 正弦周期 `0.09-0.15 rad/s`(慢,约30-50秒一个摆动)
+- 线性漂移 `5-8 px/s`(比观众眨眼慢)
+- 振幅 `120-220 px`(大到能感觉,小到不会晕)
+
+### 模式 E · Focus Overlay(焦点切换)
+
+**关键设计**:focus overlay 是一个**平面元素**(不倾斜),浮在倾斜画布之上。被选中的 slide 从瓦片位置(约400×225)缩放到屏幕中央(960×540),背景画布不倾斜变化但**变暗到 45%**:
+
+```js
+// Focus overlay (flat, centered)
+focusOverlay.style.width = (startW + (endW - startW) * focusIntensity) + 'px';
+focusOverlay.style.height = (startH + (endH - startH) * focusIntensity) + 'px';
+focusOverlay.style.opacity = focusIntensity;
+
+// 背景卡片变暗,但依然可见(关键!不要100%遮罩)
+card.style.opacity = entryOp * (1 - 0.55 * focusIntensity);   // 1 → 0.45
+card.style.filter = `brightness(${1 - 0.3 * focusIntensity})`;
+```
+
+**清晰度铁律**:
+- Focus overlay 的 `<img>` 必须 `src` 直连原图,**不要复用 gallery 里的压缩缩略**
+- 提前 preload 所有原图到 `new Image()[]` 数组
+- overlay 自身 `width/height` 按帧计算,浏览器每帧 resample 原图
+
+---
+
+## 时间轴架构(可复用骨架)
+
+```js
+const T = {
+  DURATION: 25.0,
+  s1_in: [0.0, 0.8],    s1_type: [1.0, 3.2],  s1_out: [3.5, 4.0],
+  s2_in: [3.9, 5.1],    s2_hold: [5.1, 7.0],  s2_out: [7.0, 7.8],
+  s3_hold: [7.8, 8.3],  s3_ripple: [8.3, 10.0],
+  panStart: 8.6,
+  focuses: [
+    { start: 11.0, end: 12.7, idx: 2  },
+    { start: 13.3, end: 15.0, idx: 3  },
+    { start: 15.6, end: 17.3, idx: 10 },
+    { start: 17.9, end: 19.6, idx: 16 },
+  ],
+  s4_walloff: [21.1, 21.8], s4_in: [21.8, 22.7], s4_hold: [23.7, 25.0],
+};
+
+// 核心 easing
+const easeOut = t => 1 - Math.pow(1 - t, 3);
+const easeInOut = t => t < 0.5 ? 4*t*t*t : 1 - Math.pow(-2*t+2, 3)/2;
+function lerp(time, start, end, fromV, toV, easing) {
+  if (time <= start) return fromV;
+  if (time >= end) return toV;
+  let p = (time - start) / (end - start);
+  if (easing) p = easing(p);
+  return fromV + (toV - fromV) * p;
+}
+
+// 单一 render(t) 函数读时间戳、写所有元素
+function render(t) { /* ... */ }
+requestAnimationFrame(function tick(now) {
+  const t = ((now - startMs) / 1000) % T.DURATION;
+  render(t);
+  requestAnimationFrame(tick);
+});
+```
+
+**架构精髓**:**所有状态由时间戳 t 推导**,没有状态机、没有 setTimeout。这样:
+- 播放到任意时刻 `window.__setTime(12.3)` 立刻跳转(方便 playwright 逐帧截)
+- 循环天然无缝(t mod DURATION)
+- Debug 时能冻结任意一帧
+
+---
+
+## 质感细节(容易被忽略但致命)
+
+### 1. SVG noise texture
+
+浅色底最怕「太平」。叠加一层极弱的 fractalNoise:
+
+```html
+<style>
+.stage::before {
+  content: '';
+  position: absolute; inset: 0;
+  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.078  0 0 0 0 0.078  0 0 0 0 0.074  0 0 0 0.035 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
+  opacity: 0.5;
+  pointer-events: none;
+  z-index: 30;
+}
+</style>
+```
+
+看上去没区别,去掉就知道有了。
+
+### 2. 角落品牌标识
+
+```html
+<div class="corner-brand">
+  <div class="mark"></div>
+  <div>HUASHU · DESIGN</div>
+</div>
+```
+
+```css
+.corner-brand {
+  position: absolute; top: 48px; left: 72px;
+  font-family: var(--mono);
+  font-size: 12px;
+  letter-spacing: 0.22em;
+  text-transform: uppercase;
+  color: var(--muted);
+}
+```
+
+只在作品墙 scene 显示,淡入淡出。像美术馆展签。
+
+### 3. 品牌收束 wordmark
+
+```css
+.brand-wordmark {
+  font-family: var(--sans);
+  font-size: 148px;
+  font-weight: 700;
+  letter-spacing: -0.045em;   /* 负字距是关键,让字紧凑成标志 */
+}
+.brand-wordmark .accent {
+  color: var(--accent);
+  font-weight: 500;           /* accent字符反而细一点,视觉差 */
+}
+```
+
+`letter-spacing: -0.045em` 是苹果产品页大字的标准做法。
+
+---
+
+## 常见失败模式
+
+| 症状 | 原因 | 解法 |
+|---|---|---|
+| 看起来像 PPT 模板 | 卡片没有 shadow / hairline | 加上两层 box-shadow + 1px border |
+| 倾斜感廉价 | 只用了 rotateY 没加 rotateZ | 加 ±2-3deg rotateZ 打破工整 |
+| Pan 感觉「卡顿」 | 用了 setTimeout 或 CSS keyframes 循环 | 用 rAF + sin/cos 连续函数 |
+| Focus 时字看不清 | 复用了 gallery 瓦片的低分图 | 独立 overlay + 原图 src 直连 |
+| 背景太空 | 纯色 `#F5F5F7` | 叠加 SVG fractalNoise 0.5 opacity |
+| 字体太"互联网" | 只有 Inter | 加 Serif(中英各一)+ mono 三栈 |
+
+---
+
+## 引用
+
+- 完整实现样本:`/Users/alchain/Documents/写作/01-公众号写作/项目/2026.04-huashu-design发布/配图/hero-animation-v5.html`
+- 原始灵感:claude.ai/design hero 视频
+- 参考审美:Apple 产品页、Dribbble shot 集合页
+
+遇到「多件高质量产出要陈列」的动画需求,直接从此文件 copy 骨架,换内容 + 调 timing 即可。

+ 260 - 0
references/audio-design-rules.md

@@ -0,0 +1,260 @@
+# 音频设计规则 · huashu-design
+
+> 所有动画 demo 的音频应用配方。和 `sfx-library.md`(资产清单)配套使用。
+> 实战锤炼:huashu-design 发布 hero v1-v9 迭代 · Anthropic 三支官方片子的 Gemini 深度拆解 · 8000+ 次 A/B 对比
+
+---
+
+## 核心原则 · 音频双轨制(铁律)
+
+动画音频**必须分两层独立设计**,不能只做一层:
+
+| 层 | 作用 | 时间尺度 | 和视觉的关系 | 占据频段 |
+|---|---|---|---|---|
+| **SFX(节拍层)** | 标记每个视觉 beat | 0.2-2 秒短促 | **强同步**(帧级对齐) | **高频 800Hz+** |
+| **BGM(氛围底)** | 情绪铺底、声场 | 连续 20-60 秒 | 弱同步(段落级) | **中低频 <4kHz** |
+
+**只做BGM的动画是残废的**——观众潜意识感知到「画在动但没声音响应」,廉价感的根源就在这里。
+
+---
+
+## 金标准 · 黄金配比
+
+这几组数值是实测 Anthropic 三支官方片子 + 我们自己 v9 定版对比得出的**工程硬参数**,直接套用即可:
+
+### 音量
+- **BGM 音量**:`0.40-0.50`(相对满刻度 1.0)
+- **SFX 音量**:`1.00`
+- **响度差**:BGM 比 SFX peak **低 -6 到 -8 dB**(不是靠SFX绝对响度突出,靠响度差)
+- **amix 参数**:`normalize=0`(绝不用 normalize=1,会把动态范围压平)
+
+### 频段隔离(P1 硬优化)
+Anthropic 的秘诀不是「SFX 音量大」,是**频段分层**:
+
+```bash
+[bgm_raw]lowpass=f=4000[bgm]      # BGM 限制在 <4kHz 的中低频
+[sfx_raw]highpass=f=800[sfx]      # SFX 推到 800Hz+ 的中高频
+[bgm][sfx]amix=inputs=2:duration=first:normalize=0[a]
+```
+
+为什么:人耳对 2-5kHz 区间最敏感(即「presence 频段」),SFX 如果都在这个区间,BGM 又全频段覆盖,**SFX 会被BGM的高频部分遮盖**。用 highpass 把 SFX 推高 + lowpass 把 BGM 压下,两者在频谱上各占一方,SFX 清晰度直接上一档。
+
+### Fade
+- BGM 入:`afade=in:st=0:d=0.3`(0.3s,避免硬切)
+- BGM 出:`afade=out:st=N-1.5:d=1.5`(1.5s 长尾,收束感)
+- SFX 自带 envelope,不需要额外 fade
+
+---
+
+## SFX cue 设计规则
+
+### 密度(每10秒多少个SFX)
+实测 Anthropic 三支片子的 SFX 密度有三档:
+
+| 片子 | 每10s SFX 数 | 产品性格 | 场景 |
+|---|---|---|---|
+| Artifacts(ref-1) | **~9个/10s** | 功能密集、信息多 | 复杂工具演示 |
+| Code Desktop(ref-2) | **0个** | 纯氛围、冥想感 | 开发工具专注状态 |
+| Word(ref-3) | **~4个/10s** | 平衡、办公节奏 | 生产力工具 |
+
+**启发式**:
+- 产品性格冷静/专注 → SFX 密度低(0-3个/10s),BGM 为主
+- 产品性格活泼/信息多 → SFX 密度高(6-9个/10s),SFX 驱动节奏
+- **不要填满每个视觉 beat**——留白比密集更高级。**删掉 30-50% 的 cue 会让剩下的更有戏剧性**。
+
+### Cue 选择优先级
+每个视觉 beat 不都要配 SFX。按这个优先级选:
+
+**P0 必配**(省略会有违和感):
+- 打字(终端/输入)
+- 点击/选择(用户决策时刻)
+- 焦点切换(视觉主角转移)
+- Logo reveal(品牌收束)
+
+**P1 推荐配**:
+- 元素入场/离场(modal / card)
+- 完成/成功反馈
+- AI 生成开始/结束
+- 重大过渡(scene 切换)
+
+**P2 选配**(多了会乱):
+- hover / focus-in
+- 进度 tick
+- 装饰性 ambient
+
+### 时间戳对齐精度
+- **同帧对齐**(0ms 误差):点击/焦点切换/Logo 落定
+- **前置 1-2 帧**(-33ms):快速 whoosh(给观众心理预期)
+- **后置 1-2 帧**(+33ms):物体落地/impact(符合真实物理)
+
+---
+
+## BGM 选择决策树
+
+huashu-design skill 自带 6 首 BGM(`assets/bgm-*.mp3`):
+
+```
+动画性格是什么?
+├─ 产品发布 / 技术演示 → bgm-tech.mp3(minimal synth + piano)
+├─ 教程讲解 / 工具使用 → bgm-tutorial.mp3(warm, instructional)
+├─ 教育学习 / 原理解释 → bgm-educational.mp3(curious, thoughtful)
+├─ 营销广告 / 品牌宣传 → bgm-ad.mp3(upbeat, promotional)
+└─ 同类风格需要变体 → bgm-*-alt.mp3(各自替代版)
+```
+
+### 无 BGM 的场景(值得考虑)
+参考 Anthropic Code Desktop(ref-2):**0 SFX + 纯 Lo-fi BGM** 也能很高级。
+
+**何时选无BGM**:
+- 动画时长 <10s(BGM 建立不起来)
+- 产品性格是「专注/冥想」
+- 场景本身有环境音/讲解声
+- SFX 密度很高时(避免听觉过载)
+
+---
+
+## 场景配方(开箱即用)
+
+### 配方 A · 产品发布 hero(huashu-design v9 同款)
+```
+时长:25 秒
+BGM:bgm-tech.mp3 · 45% · 频段 <4kHz
+SFX 密度:~6个/10s
+
+cue:
+  终端打字 → type × 4(间隔0.6s)
+  回车     → enter
+  卡片汇聚 → card × 4(错峰 0.2s)
+  选中     → click
+  Ripple   → whoosh
+  4次焦点  → focus × 4
+  Logo     → thud(1.5s)
+
+音量:BGM 0.45 / SFX 1.0 · amix normalize=0
+```
+
+### 配方 B · 工具功能演示(参考 Anthropic Code Desktop)
+```
+时长:30-45 秒
+BGM:bgm-tutorial.mp3 · 50%
+SFX 密度:0-2个/10s(极少)
+
+策略:让 BGM + 讲解 voiceover 驱动,SFX 只在**决定性时刻**(文件保存/命令执行完成)
+```
+
+### 配方 C · AI 生成演示
+```
+时长:15-20 秒
+BGM:bgm-tech.mp3 或无 BGM
+SFX 密度:~8个/10s(高密度)
+
+cue:
+  用户输入 → type + enter
+  AI 开始处理 → magic/ai-process(1.2s 循环)
+  生成完成 → feedback/complete-done
+  结果呈现 → magic/sparkle
+  
+亮点:ai-process 可以循环 2-3 次贯穿整个生成过程
+```
+
+### 配方 D · 纯氛围长镜头(参考 Artifacts)
+```
+时长:10-15 秒
+BGM:无
+SFX:单独使用 3-5 个精心设计的 cue
+
+策略:每个 SFX 都是主角,没有BGM「糊在一起」的问题。
+适合:单产品慢镜头、特写展示
+```
+
+---
+
+## ffmpeg 合成模板
+
+### 模板 1 · 单 SFX 叠加到视频
+```bash
+ffmpeg -y -i video.mp4 -itsoffset 2.5 -i sfx.mp3 \
+  -filter_complex "[0:a][1:a]amix=inputs=2:normalize=0[a]" \
+  -map 0:v -map "[a]" output.mp4
+```
+
+### 模板 2 · 多 SFX 时间轴合成(按cue时间对齐)
+```bash
+ffmpeg -y \
+  -i sfx-type.mp3 -i sfx-enter.mp3 -i sfx-click.mp3 -i sfx-thud.mp3 \
+  -filter_complex "\
+[0:a]adelay=1100|1100[a0];\
+[1:a]adelay=3200|3200[a1];\
+[2:a]adelay=7000|7000[a2];\
+[3:a]adelay=21800|21800[a3];\
+[a0][a1][a2][a3]amix=inputs=4:duration=longest:normalize=0[mixed]" \
+  -map "[mixed]" -t 25 sfx-track.mp3
+```
+**关键参数**:
+- `adelay=N|N`:前面是左声道延迟(ms),后面是右声道,写两遍保证立体声对齐
+- `normalize=0`:保留动态范围,关键!
+- `-t 25`:截断到指定时长
+
+### 模板 3 · 视频 + SFX track + BGM(带频段隔离)
+```bash
+ffmpeg -y -i video.mp4 -i sfx-track.mp3 -i bgm.mp3 \
+  -filter_complex "\
+[2:a]atrim=0:25,afade=in:st=0:d=0.3,afade=out:st=23.5:d=1.5,\
+     lowpass=f=4000,volume=0.45[bgm];\
+[1:a]highpass=f=800,volume=1.0[sfx];\
+[bgm][sfx]amix=inputs=2:duration=first:normalize=0[a]" \
+  -map 0:v -map "[a]" -c:v copy -c:a aac -b:a 192k final.mp4
+```
+
+---
+
+## 失败模式速查
+
+| 症状 | 根因 | 修复 |
+|---|---|---|
+| SFX 听不见 | BGM 高频部分遮盖 | 加 `lowpass=f=4000` 给BGM + `highpass=f=800` 给SFX |
+| 音效过响刺耳 | SFX 绝对音量太大 | SFX 音量降到 0.7,同时降低 BGM 到 0.3,保持差值 |
+| BGM 和 SFX 节奏冲突 | BGM 选错了(用了有强beat的music) | 换成 ambient / minimal synth 的 BGM |
+| 动画结束 BGM 突然断 | 没做 fade out | `afade=out:st=N-1.5:d=1.5` |
+| SFX 重叠成糊 | cue 太密 + 每个 SFX 时长太长 | SFX 时长控到 0.5s 以内,cue 间隔 ≥ 0.2s |
+| 公众号 mp4 没声音 | 公众号有时会 mute auto-play | 不用担心,用户点开会有声音;gif 本来就没声音 |
+
+---
+
+## 和视觉的联动(高级)
+
+### SFX 音色要和视觉风格匹配
+- 暖米/纸张感视觉 → SFX 用**木质/柔和**音色(Morse, paper snap, soft click)
+- 冷黑科技视觉 → SFX 用**金属/数字**音色(beep, pulse, glitch)
+- 手绘/童趣视觉 → SFX 用**卡通/夸张**音色(boing, pop, zap)
+
+我们当前 `apple-gallery-showcase.md` 的暖米底色 → 搭配 `keyboard/type.mp3`(mechanical)+ `container/card-snap.mp3`(soft)+ `impact/logo-reveal-v2.mp3`(cinematic bass)
+
+### SFX 可以引导视觉节奏
+高级技巧:**先设计 SFX 时间轴,然后调整视觉动画去对齐 SFX**(不是反过来)。
+因为 SFX 每个 cue 都是一个「钟表 tick」,视觉动画适配 SFX 节奏会非常稳——反之 SFX 去追视觉,常常 ±1 帧对不上就有违和感。
+
+---
+
+## 质量检查清单(发布前自检)
+
+- [ ] 响度差:SFX peak - BGM peak = -6 到 -8 dB?
+- [ ] 频段:BGM lowpass 4kHz + SFX highpass 800Hz?
+- [ ] amix normalize=0(保留动态范围)?
+- [ ] BGM fade-in 0.3s + fade-out 1.5s?
+- [ ] SFX 数量是否合适(按场景性格选密度)?
+- [ ] 每个 SFX 和视觉 beat 同帧对齐(±1 帧内)?
+- [ ] Logo reveal 音效时长够(建议 1.5s)?
+- [ ] 关闭 BGM 听一遍:SFX 单独是否足够有节奏感?
+- [ ] 关闭 SFX 听一遍:BGM 单独是否有情绪起伏?
+
+两层任何一层单独听都应该自洽。如果只有两层叠加才好听,说明没做好。
+
+---
+
+## 参考
+
+- SFX 资产清单:`sfx-library.md`
+- 视觉风格参考:`apple-gallery-showcase.md`
+- Anthropic 三支片子深度音频分析:`/Users/alchain/Documents/写作/01-公众号写作/项目/2026.04-huashu-design发布/参考动画/AUDIO-BEST-PRACTICES.md`
+- huashu-design v9 实战案例:`/Users/alchain/Documents/写作/01-公众号写作/项目/2026.04-huashu-design发布/配图/hero-animation-v9-final.mp4`

+ 226 - 0
references/sfx-library.md

@@ -0,0 +1,226 @@
+# SFX Library · huashu-design
+
+> 全部由 ElevenLabs Sound Generation API 生成,苹果发布会级音质。
+> 产品级 SFX 资产库,覆盖花叔动画/演示/产品 Demo 全场景。
+
+**资产位置**:`assets/sfx/<category>/<name>.mp3`
+**总数**:37 个 SFX(30 批量生成 + 7 个 v7b 保留)
+**生成模型**:ElevenLabs Sound Generation API(prompt_influence 0.4)
+**音质**:44.1kHz MP3,苹果发布会级清晰度,无额外混响
+
+---
+
+## 目录结构
+
+```
+assets/sfx/
+├── keyboard/      type, type-fast, delete-key, space-tap, enter
+├── ui/            click, click-soft, focus, hover-subtle, tap-finger, toggle-on
+├── transition/    whoosh, whoosh-fast, swipe-horizontal, slide-in, dissolve
+├── container/     card-snap, card-flip, stack-collapse, modal-open
+├── feedback/      success-chime, error-tone, notification-pop, achievement
+├── progress/      loading-tick, complete-done, generate-start
+├── impact/        logo-reveal, logo-reveal-v2, brand-stamp, drop-thud
+├── magic/         sparkle, ai-process, transform
+└── terminal/      command-execute, output-appear, cursor-blink
+```
+
+---
+
+## 快速索引
+
+### ⌨️ Keyboard(键盘输入)
+
+| 文件 | 时长 | 用途 | Prompt 要点 |
+|---|---|---|---|
+| `sfx/keyboard/type.mp3` | 0.5s | 单键敲击(mechanical keyboard single key) | mechanical keyboard single key press |
+| `sfx/keyboard/type-fast.mp3` | 1.5s | 连续快速打字(演示输入提示词) | fast continuous typing rhythm, apple magic keyboard |
+| `sfx/keyboard/delete-key.mp3` | 0.5s | backspace 回删 | single backspace key, low pitched thud |
+| `sfx/keyboard/space-tap.mp3` | 0.5s | 空格键轻击 | soft spacebar tap, wide flat |
+| `sfx/keyboard/enter.mp3` | 0.5s | 回车确认(v7b 保留) | enter key press, crisp tactile |
+
+### 🎯 UI(界面交互)
+
+| 文件 | 时长 | 用途 | Prompt 要点 |
+|---|---|---|---|
+| `sfx/ui/click.mp3` | 0.5s | 标准 UI 点击(v7b 保留) | crisp modern interface click |
+| `sfx/ui/click-soft.mp3` | 0.5s | 柔和 UI click(次要按钮/链接) | soft gentle button click, mid pitched |
+| `sfx/ui/focus.mp3` | 0.5s | 元素聚焦/选中(v7b 保留) | subtle focus tone, element highlight |
+| `sfx/ui/hover-subtle.mp3` | 0.5s | 悬停提示(微秒级反馈) | barely audible tick, air whisper |
+| `sfx/ui/tap-finger.mp3` | 0.5s | 移动端 tap(iOS 界面) | finger tap on touchscreen, muted thud |
+| `sfx/ui/toggle-on.mp3` | 0.5s | 开关打开 | ios toggle switch flip, satisfying click |
+
+### 🌊 Transition(过渡)
+
+| 文件 | 时长 | 用途 | Prompt 要点 |
+|---|---|---|---|
+| `sfx/transition/whoosh.mp3` | 0.5s | 标准 whoosh(v7b 保留) | air whoosh transition |
+| `sfx/transition/whoosh-fast.mp3` | 0.6s | 快速 whoosh(标题闪入、标签切换) | quick fast air whoosh, cinematic |
+| `sfx/transition/swipe-horizontal.mp3` | 0.7s | 横向滑动(轮播、tab 切换) | smooth left-to-right air movement |
+| `sfx/transition/slide-in.mp3` | 0.6s | 元素滑入(side panel、抽屉) | smooth soft whoosh with arrival |
+| `sfx/transition/dissolve.mp3` | 0.8s | 柔化融化(图片淡出淡入) | soft dissolve, airy shimmer |
+
+### 🃏 Container(卡片/容器)
+
+| 文件 | 时长 | 用途 | Prompt 要点 |
+|---|---|---|---|
+| `sfx/container/card-snap.mp3` | 0.5s | 卡片吸附/定位(v7b 保留) | card snap into place |
+| `sfx/container/card-flip.mp3` | 0.7s | 卡片翻转(前后面切换) | playing card flip, crisp snap |
+| `sfx/container/stack-collapse.mp3` | 0.8s | 堆叠合拢(列表聚合) | cards stacking, paper taps collapsing |
+| `sfx/container/modal-open.mp3` | 0.6s | 模态框打开 | modal popping open, whoosh + thud |
+
+### 🔔 Feedback(通知/反馈)
+
+| 文件 | 时长 | 用途 | Prompt 要点 |
+|---|---|---|---|
+| `sfx/feedback/success-chime.mp3` | 1.0s | 成功提示(支付成功、任务完成) | two ascending bell tones, ios-style |
+| `sfx/feedback/error-tone.mp3` | 0.7s | 错误提示(警告、失败) | descending two-note warning, soft |
+| `sfx/feedback/notification-pop.mp3` | 0.6s | 消息弹出(toast、通知) | notification bloop, ios message alert |
+| `sfx/feedback/achievement.mp3` | 1.5s | 成就达成(里程碑、徽章) | triumphant rising arpeggio, game-style |
+
+### ⏳ Progress(进度/状态)
+
+| 文件 | 时长 | 用途 | Prompt 要点 |
+|---|---|---|---|
+| `sfx/progress/loading-tick.mp3` | 0.5s | 加载计时(进度条节拍) | soft short pulse, minimal ambient |
+| `sfx/progress/complete-done.mp3` | 0.8s | 完成确认(step 完成) | two ascending satisfying tones |
+| `sfx/progress/generate-start.mp3` | 0.8s | AI 开始生成 | soft rising shimmer, magical whoosh |
+
+### 💥 Impact(品牌/冲击)
+
+| 文件 | 时长 | 用途 | Prompt 要点 |
+|---|---|---|---|
+| `sfx/impact/logo-reveal.mp3` | 0.7s | Logo impact(v7b 保留) | logo reveal thud |
+| `sfx/impact/logo-reveal-v2.mp3` | 1.5s | 更长的 Logo impact(电影感) | cinematic bass hit with shimmer tail |
+| `sfx/impact/brand-stamp.mp3` | 1.0s | 印章重击(认证、盖章) | rubber stamp thud, paper contact |
+| `sfx/impact/drop-thud.mp3` | 0.7s | 物件落地(插入、放置) | heavy thud, wood surface contact |
+
+### ✨ Magic(AI 变换)
+
+| 文件 | 时长 | 用途 | Prompt 要点 |
+|---|---|---|---|
+| `sfx/magic/sparkle.mp3` | 0.8s | 魔法闪光(AI 高亮、惊喜) | bright twinkling stars, fairy dust |
+| `sfx/magic/ai-process.mp3` | 1.2s | AI 处理音(thinking 状态) | modulating digital hum with shimmer |
+| `sfx/magic/transform.mp3` | 1.0s | 变换过渡(morph 效果) | rising shimmer whoosh with sparkle tail |
+
+### 💻 Terminal(命令行)
+
+| 文件 | 时长 | 用途 | Prompt 要点 |
+|---|---|---|---|
+| `sfx/terminal/command-execute.mp3` | 0.5s | 命令执行 | crisp digital beep with tick, hacker ui |
+| `sfx/terminal/output-appear.mp3` | 0.6s | 输出出现 | rapid digital ticks, retro printout |
+| `sfx/terminal/cursor-blink.mp3` | 0.5s | 光标闪烁 | subtle soft digital pulse, rhythmic |
+
+---
+
+## 按场景推荐搭配
+
+### 💻 Terminal 交互演示
+```
+type (0.5s) → enter (0.5s) → command-execute (0.5s) → output-appear (0.6s)
+```
+循环元素:`cursor-blink` 作为 idle 时的环境音。
+
+### 🃏 卡片选择流程
+```
+hover-subtle (0.5s, UI悬停) → click-soft (0.5s, 点击) → card-snap (0.5s, 定位)
+```
+或进阶版:`card-flip` 做前后面切换。
+
+### 🤖 AI 生成全流程
+```
+generate-start (0.8s, 启动) → ai-process (1.2s, 处理) → sparkle (0.8s, 闪现) → complete-done (0.8s, 完成)
+```
+错误时用 `error-tone` 替代 `complete-done`。
+
+### 🎬 Logo Reveal(品牌时刻)
+```
+whoosh-fast (0.6s, 铺垫) → logo-reveal-v2 (1.5s, 落点) → sparkle (0.8s, 尾韵)
+```
+简版:`whoosh → logo-reveal`(直接 v7b 两件套)。
+
+### 📱 UI 交互演示(移动端)
+```
+tap-finger (0.5s, 点击) → slide-in (0.6s, 面板滑入) → toggle-on (0.5s, 开关)
+```
+完成后:`success-chime` 或 `notification-pop`。
+
+### 📊 数据可视化/仪表盘
+```
+loading-tick (0.5s, 节拍) × N → complete-done (0.8s, 数据到位) → achievement (1.5s, 惊艳落点)
+```
+
+### 🎯 表单提交流程
+```
+click-soft (0.5s) → loading-tick ×2 (1.0s) → success-chime (1.0s)
+```
+失败分支:`error-tone (0.7s)`。
+
+### 🪄 Magic Transform 场景
+```
+whoosh-fast (0.6s) → transform (1.0s) → sparkle (0.8s)
+```
+适合:元素变形、效果前后对比、"AI 重写"等演示。
+
+---
+
+## 使用规范
+
+### 音量建议(来自 apple-gallery-showcase.md 音频双轨制)
+- **SFX 主轨**:`1.0`(不做衰减)
+- **BGM 背景轨**:`0.4 ~ 0.5`(SFX 明显穿透)
+- **多 SFX 叠加**:用 `amix=inputs=N:duration=longest:normalize=0` 保留动态范围
+
+### ffmpeg 拼接模板
+```bash
+# 单 SFX 对齐时间点:
+ffmpeg -i video.mp4 -itsoffset 2.5 -i sfx/ui/click.mp3 \
+  -filter_complex "[0:a][1:a]amix=inputs=2:duration=longest:normalize=0[a]" \
+  -map 0:v -map "[a]" output.mp4
+
+# 多 SFX + BGM:
+ffmpeg -i video.mp4 \
+  -itsoffset 1.0 -i sfx/transition/whoosh-fast.mp3 \
+  -itsoffset 1.6 -i sfx/impact/logo-reveal-v2.mp3 \
+  -i bgm.mp3 \
+  -filter_complex "[3:a]volume=0.4[bgm];[0:a][1:a][2:a][bgm]amix=inputs=4:normalize=0[a]" \
+  -map 0:v -map "[a]" output.mp4
+```
+
+### 选型决策树
+1. **有 tactile 动作**(打字/点击/滑动)→ `keyboard/` or `ui/`
+2. **元素进场/出场** → `transition/`
+3. **容器层操作**(卡片/模态) → `container/`
+4. **状态反馈**(成功/失败/通知) → `feedback/`
+5. **进度/时间流逝** → `progress/`
+6. **品牌落点/重要时刻** → `impact/`
+7. **AI 魔法/变换** → `magic/`
+8. **命令行/代码演示** → `terminal/`
+
+### 避免叠音堆积
+- 同一个时间点 `max 2 个 SFX` 并发
+- BGM 降到 0.3 以下时可以放 3 个
+- 品牌 impact 时清空其他 SFX(留空 0.2s 再落点)
+
+---
+
+## Prompt 撰写原则(供复用)
+
+参考风格:`apple keynote, tight, minimal, no reverb unless ambient, crisp, elegant`
+
+**好 prompt 的三要素**:
+1. **声音物理描述**:什么物体、什么动作("mechanical keyboard single key press")
+2. **质感/风格限定**:apple-style / ios-style / cinematic / retro
+3. **反例排除**:no reverb / clean studio / minimal
+
+❌ "click sound"
+✅ "crisp ui button click, clean modern interface sound, apple-style, high pitched"
+
+❌ "magic"
+✅ "bright twinkling stars sound, high pitched glittery chime, fairy dust"
+
+---
+
+## 详见
+- 音频双轨制与 ffmpeg 拼接:`apple-gallery-showcase.md`
+- 原始生成脚本:`/tmp/gen_sfx_batch.sh`(一次性批量生成器)