# Agent Skills Hub · 原型设计规范（Design Spec）

> 路径：`prototype/DESIGN.md` · 版本：1.20.45
> 本文档是原型设计的事实来源（Single Source of Truth），涵盖设计原则、设计系统、组件库、交互标准与响应式规范。
> 适用目录：`prototype/`（已重命名自 `site/`）。
>
> **原型实现方式（v1.9.1 起，v1.12.0 对齐，v1.14.6 交互脚本拆分为 parts，v1.14.42 样式拆分为 tokens/base/layout/components/responsive，v1.17.x 交互/布局/可访问性系列改进）**：`prototype/prototype.html` 为纯 HTML 自包含单文件——由根目录 `npm run build`（=`node tools/build-skills-data.mjs && node tools/build.mjs`）将 `src/index.html` 模板内联 `src/styles/tokens.css` 及按序拼接的 `src/styles/base.css` + `src/styles/layout.css` + `src/styles/components.css` + `src/styles/responsive.css`、`src/i18n.js`、按序拼接的 `src/parts/*.js`（状态/渲染/详情/交互/启动五模块）与真实技能数据（合并 `data/skills-data.json` + `data/skills-metrics.json` 后注入）生成，双击即可离线预览，无 Next.js/Tailwind/React 构建。国际化由独立模块 `src/i18n.js` 驱动（`data-i18n` 占位 + `I18N.t()` 容错兜底）。源码在 `prototype/src/` 随仓库分发；`prototype/` 下的 `index.html`/`favicon.svg`/`banner-og.svg` 为构建产物（构建脚本 `tools/build.mjs`/`tools/build-skills-data.mjs` 置于仓库根 `tools/`，不混入原型目录）。

---

## 1. 设计原则

| 原则 | 说明 |
|------|------|
| 极简（Minimal） | 克制的视觉语言，留白即设计；单一主色，避免渐变滥用与装饰性元素 |
| 层级清晰（Hierarchy） | 通过字号、字重、色彩对比建立明确的信息层级，首屏 3 秒可读懂核心 |
| 一致（Consistent） | 所有间距、圆角、阴影、动效遵循统一 Token，视觉基线参考 shadcn/ui（**仅为设计风格参考，原型无 shadcn/Tailwind/Radix 运行时**） |
| 真实（Real Data） | 原型数据为构建期从磁盘 `skills/<name>/SKILL.md` 由根目录 `build-skills-data.mjs` 生成 `data/skills-data.json`，再由根目录 `build.mjs` 注入并预渲染进 `prototype/`，非占位假数据 |
| 无障碍（Accessible） | 对比度 ≥ WCAG AA，键盘可达，支持 `prefers-reduced-motion` |

---

## 2. 设计系统（Design Tokens）

设计 Token 以 **shadcn/ui CSS 变量（HSL 通道）** 定义在 `prototype/src/styles/tokens.css` 的 `:root`（浅色）与 `html[data-theme="dark"]`（深色，主题由 `<html data-theme>` 切换）中，由 `prototype/src/styles/base.css`/`layout.css`/`components.css`/`responsive.css` 直接消费（原型为纯原生 CSS，无 Tailwind/React 运行时）。这是全局唯一来源。

### 2.1 色彩（HSL 通道，语义化命名）

| Token | 浅色 | 深色 | 用途 |
|-------|------|------|------|
| `--background` | `0 0% 100%` | `224 28% 8%` | 页面背景 |
| `--foreground` | `224 24% 12%` | `220 18% 92%` | 主文字 |
| `--card` / `--card-foreground` | `0 0% 100%` / `224 24% 12%` | `224 24% 11%` / `220 18% 92%` | 卡片/弹窗表面 |
| `--popover` / `--popover-foreground` | 同 card | 同 card（深） | 浮层表面 |
| `--primary` / `--primary-foreground` | `152 56% 40%` / `0 0% 100%` | `146 52% 60%` / `224 32% 8%` | **主色（单一绿色，降饱和）** |
| `--secondary` / `--secondary-foreground` | `220 16% 96%` / `224 24% 18%` | `224 18% 18%` / `220 18% 88%` | 次级表面（按钮、标签底） |
| `--muted` / `--muted-foreground` | `220 16% 96%` / `220 9% 46%` | `224 18% 16%` / `220 12% 60%` | 辅助表面 / 辅助文字 |
| `--accent` / `--accent-foreground` | `152 56% 95%` / `152 56% 33%` | `146 52% 22%` / `146 52% 82%` | 主色浅底（聚焦环、徽章） |
| `--destructive` / `--destructive-foreground` | `0 72% 51%` / `0 0% 100%` | `0 62% 52%` / `0 0% 100%` | 破坏性操作 |
| `--border` / `--input` / `--ring` | `220 14% 90%` / 同 border / `152 56% 40%` | `224 16% 22%` / `224 16% 24%` / `146 52% 60%` | 边框 / 输入 / 聚焦环 |
| `--radius` | `0.75rem` | 同 | 默认圆角基准 |
| `--shadow-color` | `224 32% 20%` | `0 0% 0%` | 阴影色相（中性低透明） |

色彩纪律：**主色仅用于主按钮、聚焦态、分类标识、选中态**；强调色仅用于 `scripts/references/assets` 等资源标签。禁止大面积渐变背景（Hero 仅保留极淡光晕 `radial-gradient`，透明度 ≤ 0.08）。

### 2.2 字体

参考 Claude（Anthropic）官方品牌字体体系：标题使用衬线（Anthropic Serif，外部实现以 `Georgia` 为官方回退），正文/界面使用无衬线系统栈（Anthropic Sans，外部实现以 `system-ui` 为回退）。本项目为纯静态/Next.js 实现，不内嵌自定义字体，统一采用以下回退栈。

| Token | 值 | 用途 |
|------|----|------|
| `--font-display` | `Georgia, "Times New Roman", "Songti SC", "STSong", serif` | 标题/品牌名/卡片名（衬线，对标 Anthropic Serif） |
| `--font-sans` | `-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "PingFang SC", "Microsoft YaHei", system-ui, sans-serif` | 正文与界面（无衬线，对标 Anthropic Sans） |
| `--font-en` | `-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif` | 英文 UI 文案 |
| `--font-mono` | `ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace` | 代码/英文名等宽展示 |

- 基础字号 `15px`，行高 `1.6`
- 大标题 `clamp(34px, 5.5vw, 52px)`，字重 `700`，字距 `-0.02em`，字体 `--font-display`
- 卡片标题 `15px`，字重 `600`，字距 `-0.01em`，字体 `--font-display`
- 品牌名、弹窗标题、空状态标题均使用 `--font-display` 衬线，与正文无衬线形成层级对比
- 英文 UI 文案首字母大写，中文不加字距

### 2.3 间距（4 的倍数尺度，取值约定参照 Tailwind 默认值）

| 值 | 典型用途 |
|----|---------|
| `4px` (1) | 标签内边距微调 |
| `8px` (2) | 元素间紧凑间距 |
| `12px` (3) | chip/标签内边距 |
| `16px` (4) | 卡片内边距基准 |
| `24px` (6) | 区块/工具栏内边距 |
| `32px` (8) | 容器/章节间距 |
| `48px` (12) | Hero 内边距、弹窗内边距 |
| `64px` (16) | 大区块间距 |

### 2.4 圆角（映射到 `--radius` 设计令牌）

| Token | 值 | 用途 |
|-------|----|------|
| `rounded-sm` | `calc(--radius - 4px)` | 标签、输入框 |
| `rounded-md` | `calc(--radius - 2px)` | 按钮、搜索框 |
| `rounded-lg` | `--radius` (0.75rem) | 卡片（默认） |
| `rounded-xl` | 1rem | 弹窗、统计条 |
| `rounded-full` | 999px | chip、徽章、按钮胶囊 |

### 2.5 阴影（分层次，浅而柔，带 `--shadow-color`）

| Token | 值 |
|-------|----|
| `--shadow-color` | `224 32% 20%`（浅）/ `0 0% 0%`（深）— 阴影色相，统一低透明 |
| `shadow-xs` | `0 1px 2px hsl(var(--shadow-color)/.04), 0 1px 3px hsl(var(--shadow-color)/.06)` |
| `shadow-sm` | `0 1px 2px hsl(var(--shadow-color)/.05), 0 2px 6px -1px hsl(var(--shadow-color)/.08)` |
| `shadow-md` | `0 4px 12px -2px hsl(var(--shadow-color)/.10), 0 2px 6px -2px hsl(var(--shadow-color)/.06)` |
| `shadow-lg` | `0 12px 32px -8px hsl(var(--shadow-color)/.16), 0 4px 10px -4px hsl(var(--shadow-color)/.08)` |
| `shadow-pop` | `var(--shadow-lg)`（弹窗/浮层专用，桌面 Dialog 与卡片 hover 使用） |

### 2.6 图标

- 使用 **本地内联 SVG 图标集**（定义在 `prototype/src/index.html` 模板中，随 `prototype/src/` 源码分发），零外部依赖，统一 `24x24 viewBox` + `currentColor` 描边，等价于 lucide 风格。
- 图标尺寸统一 `16-20px`（`h-4 w-4` / `h-5 w-5`），颜色继承 `currentColor` 随状态变化。
- 业务图标语义：搜索 `Search`、主题 `Sun/Moon`、视图 `LayoutGrid/Rows3`、资源 `FileCode2/BookOpen/FolderOpen`、外链 `ExternalLink`、空态 `SlidersHorizontal`、品牌 `Boxes`、GitHub `Github`、关闭 `X`。

### 2.7 动效（Motion）

| Token | 值 |
|-------|----|
| `ease-out-quint` | `cubic-bezier(0.22, 1, 0.36, 1)`（顺滑收尾） |
| `duration-200` | 200ms（交互反馈基准） |
| `animate-fade-in` | `fade-in 0.3s easeOutQuint`（背景/遮罩） |
| `animate-pop-in` | `pop-in 0.28s easeOutQuint`（弹窗卡片） |
| `animate-slide-in-right` / `slide-out-right` | 移动端 Sheet 抽屉 |

动效纪律：
- 交互反馈（hover/active）仅 200ms，位移 ≤ 3px（`active:scale-[0.98]`）。
- 弹窗：背景 `fade` + 卡片 `pop`。
- 必须尊重 `prefers-reduced-motion: reduce`——全局动画/过渡降为 `0.001ms`。

---

## 3. 组件库（Component Library）

组件分三类：**基础（Base）**、**复合（Composite）**、**业务（Domain）**。视觉风格参考 shadcn/ui（new-york），原型以**纯原生 CSS/JS 实现**（无 Tailwind/React/Radix 运行时），禁止手写重复样式。

### 3.1 基础组件（Base）— `components/ui/*`（构建期源码映射）

> 以下组件为**原型源码结构映射**（源码在 `prototype/src/` 随仓库分发，由 `build.mjs` 内联为静态产物 `prototype/prototype.html`）；此处列出供理解静态产物的实现结构与评审对齐。注：当前实现为原生 HTML/CSS/JS（非 React 组件文件），交互脚本已按职责拆分到 `src/parts/`（01-state / 02-render / 03-detail / 04-interactions / 05-main），以下按职责对应到对应 parts 模块的渲染/交互函数。

| 组件 | 文件 | 变体/状态 |
|------|------|-----------|
| Button | `button.tsx` | `default/secondary/outline/ghost/destructive` × `default/sm/lg/icon`；`asChild` 支持 `a` 包装 |
| Input | `input.tsx` | default / focus（ring） |
| Badge | `badge.tsx` | `default/secondary/outline/muted/accent` |
| Card | `card.tsx` | `Card/CardHeader/CardTitle/CardContent` |
| Skeleton | `skeleton.tsx` | `animate-pulse` 占位 |
| Separator | `separator.tsx` | horizontal / vertical |
| Tabs | `parts/05-main.js` 视图切换 | 原生实现（Radix Tabs 风格的可访问性模式，无 Radix 依赖） |
| Dialog | `parts/03-detail.js` `openDetail()` | 原生实现（Radix Dialog 风格焦点陷阱 + `aria-modal`，无 Radix 依赖） |
| Sheet | `layout.css` 预留 `.sheet` | 移动端详情**复用居中 Dialog**（未启用独立抽屉；`.sheet`/`.sheet-grip` 为预留样式，标注保留未启用，无对应 DOM/JS） |

### 3.2 复合/业务组件（对应 `src/app.js` 渲染函数）

| 职责 | 实现 | 说明 |
|------|------|------|
| ThemeToggle | `04-interactions.js` 的 `applyTheme()` | 深浅主题切换，写根节点 `data-theme` |
| LangToggle | `i18n.js` 的 `I18N.toggleLang()` | 中英切换（受控），`I18N.syncDOM()` 同步 `data-lang` 与 `<html lang>` |
| ViewToggle | `01-state.js` 的 `state.view` + `02-render.js` 的 `renderGrid()` | 网格/列表切换（受控） |
| ShareButton | `03-detail.js` 的 `shareSkill(name)` | 技能详情弹窗内的「分享」按钮；点击复制「技能链接 + 随机宣传文案」并 toast 反馈 |
| SkillCard | `02-render.js` 的 `cardHTML()` | 网格/列表共用；**渲染为原生 `<button type="button" class="card">`**（a11y 语义，Enter/Space 原生触发，点击经 `#grid` 委托打开详情）；双语描述与分类标签 |
| SkillDetail | `03-detail.js` 的 `openDetail()` | 弹窗内容体；含中英文描述、分类、授权工具、本地仓库链接 |
| SettingsButton | `03-detail.js` 的 `openSettings()` | 顶部栏右上角齿轮按钮 `#settingsBtn`；复用 Dialog 框架承载语言/主题/视图模式/显示密度四组切换（就地刷新文案，不重建弹窗） |
| 主页面 | `05-main.js` 的 `init()` | 承载 Hero、Toolbar、Chip 过滤、结果区、响应式弹窗调度 |

### 3.3 业务数据契约

| 组件 | 数据来源（`skills-data.json` 扁平结构） |
|------|----------|
| SkillCard / SkillDetail | `skill{name, category, enCategory, zh, description(中文), enDescription(英文), allowedTools}`（`name` 为权威标识；`description` 为中文描述，`enDescription` 为英文描述） |
| CategoryFilter（Chip） | `categories[](string)` + `categoryEn{}`（分类中文→英文映射）+ 内置「全部」；计数由 `02-render.js` 预聚合 `catCounts` |
| 语言/主题 | 根节点 `data-lang` / `data-theme` 属性 |

---

## 4. 交互标准（Interaction Standards）

### 4.1 模式（Patterns）

- **单一主任务流**：浏览 → 搜索/筛选 → 查看详情（弹窗/抽屉）→ 跳转仓库。无多级路由，详情用模态而非新页面（保持原型轻量）。
- **响应式详情载体**：当前实现桌面与移动端**均用居中 Dialog**（`.sheet` 抽屉为预留样式未启用，v1.17.2 暂未接入）。
- **即时筛选**：搜索与分类筛选为受控状态、实时过滤，无需提交按钮。
- **双语即时切换**：语言切换即时重渲 UI 文案与分类英文名，不刷新。

### 4.2 反馈（Feedback）

| 场景 | 反馈 |
|------|------|
| 输入聚焦 | 主色边框 + 2px 主色聚焦环（`focus-visible:ring-2 ring-ring`） |
| 按钮悬停/点击 | 颜色/阴影变化，`active:scale-[0.98]` |
| 卡片悬停 | `hover:border-primary/40 hover:shadow-md` + 轻微上浮 |
| 筛选结果变化 | 数量文本 `#resultCount` 实时更新（`aria-live="polite"` 播报条数；`#grid` 为 `aria-live="off"`，避免读屏朗读整网格） |
| 弹窗打开 | 背景 `fade` + 卡片 `pop`（桌面）/ 抽屉 `slide-in-right`（移动） |
| 复制分享链接 | 成功 toast「已复制链接」（`role="status"` `aria-live="polite"`）；失败 toast「复制失败，请手动复制」；3s 自动消失 |

### 4.3 错误（Error）

- 原型为只读展示，无表单提交错误。
- 边界情况：技能 `zh`/`description` 缺失时由 `esc()` 安全降级为空串，i18n 缺失 key 时由 `I18N.t()` 回退 zh / key 原文，均不崩溃。
- 仓库内 Markdown 文档（README / CONTRIBUTING 等）的技能链接使用相对路径 `skills/<name>/`，由 GitHub 自动解析，避免硬编码用户名。
- 原型站点详情弹窗的"查看技能"使用绝对 GitHub 链接 `https://github.com/sutchan/Agent-Skills-Hub/tree/main/skills/<name>/`，由 `prototype/src/parts/03-detail.js` 的 `REPO_SKILLS_TREE` 常量维护；app 层 `app/components/detail-modal.tsx` 同样硬编码 `githubDir`（`app/lib/skills.ts`）指向该常量，两层保持一致。

### 4.4 空状态（Empty）

- 搜索/筛选无结果时显示空状态区（`#emptyState`）：图标 + 双语标题「未找到匹配的技能」+ 描述 + 「清除筛选」按钮（`#clearFilters`，点击重置 `q`/`cat` 并重渲染）。
- 不显示空白页；保持布局稳定。

### 4.5 键盘与可达性

- 卡片为**原生 `<button>`**，Enter/Space 原生打开；点击经 `#grid` 事件委托（v1.16.0 修复 double-open，移除冗余 keydown 委托）。
- 弹窗为**原生实现**，按 Radix Dialog 风格提供 `Esc` 关闭、焦点陷阱、`aria-modal`（详见 §7，无 Radix 运行时）。
- 分类 chip 用 `aria-pressed` 反映选中态。
- 所有图标按钮带 `aria-label`；`DialogTitle`/`SheetTitle` 用 `sr-only` 保证可访问标题。
- 顶部栏图标按钮统一 `.icon-btn`（34px、flex 居中、`aria-pressed`/`aria-label`），`#settingsBtn` 带 `aria-label`（v1.17.2 补齐样式，修复按钮参差对齐）。
- **app 层对齐（v1.20.6）**：`app/components/skill-card.tsx` 卡片根已改为原生 `<button>`（依赖原生 Enter/Space）；`app/components/detail-modal.tsx` 自带 Esc 关闭 + 焦点陷阱（`keydown` 监听，无独立 `ui/dialog.tsx`）；顶栏（`AppShell.tsx`）已含 `#langBtn` 语言切换与 `#themeBtn` 主题切换（写根节点 `data-theme` + localStorage `ash-theme`）；`SkillsExplorer.tsx` 顶栏含网格/列表视图切换（`#viewBtn`）与 `#settingsBtn` 齿轮按钮，打开 `app/components/settings-panel.tsx` 设置弹窗（聚合「界面元素 / 名称显示 / 显示密度」三组，无独立 `ui/settings-dialog.tsx`）；视图（`ash-view`）、密度（`ash-density`，写 `data-density` + globals.css `:root[data-density="compact"]` 生效）、界面元素、名称显示均持久化；搜索框新增 120ms 防抖 + 输入法 composition 拦截（对齐原型 `DEBOUNCE_MS`）；结果计数 `#resultCount`（aria-live）；滚动超 300px 显示回到顶部 `#toTop`（`.to-top.show` 样式）；`AppShell.tsx` 渲染 `<section class="hero" id="hero">` 节点网 Hero（按分类计数动态生成 `#netNodes`，双语标题/副标题/特性标签 + 方案 B 随机骰子 `#diceBtn`，点击派发 `ash:open-skill` 由 `SkillsExplorer.tsx` 打开 `detail-modal.tsx`，样式同源 `app/globals.css`）。

### 4.6 页脚区（Footer）

- 位于技能网格 `<main>` 之后、`overlay` 之前，作为页面收尾区块（语义化 `<footer id="siteFooter">`）。
- 结构分两段：
  - **品牌与导航**（`footer-inner`）：左侧品牌区（`footer-brand` 含 logo + 名称 + 简介 `footer-desc`），右侧导航链接列（`footer-links`，含 GitHub 仓库、README、规范文档、品牌资产）。
  - **版本与协议**（`footer-bottom`）：项目版本 `footer-ver`（来自根 `package.json`，由 `build.mjs` 注入 `{{VERSION}}` / app 经 `page.tsx` 读取传入）+ 分隔符 + 开源协议声明 `footer-copy`。
- 文案遵循全局 i18n：原型层 `footer.desc` / `footer.copyright` 用 `data-i18n` + `.zh`/`.en` 类随语言切换；`app/` 层以 `lang` 条件渲染。
- 链接统一 `target="_blank" rel="noopener"` 外链，内链用相对路径；品牌 logo 与页眉同源（三节点 Hub SVG）。
- 样式在 `prototype/src/styles/components.css` 与 `app/globals.css` 同步维护，主色与令牌同源；移动端 `footer-inner` 竖向堆叠。

---

## 5. 响应式（Responsive）

| 断点 | 布局 |
|------|------|
| `≥1024px` | 平板/桌面中间断点（v1.15.0 新增）：压缩 hero 字号与顶栏间距 |
| `≥640px` | 工具栏横排；详情用居中 Dialog |
| `< 640px` | 网格单列；分类 chip 横排可滚动；工具栏纵向堆叠（`view-toggle` 隐藏） |

- **网格列数**：实际用 CSS Grid `grid-template-columns: repeat(auto-fill, minmax(260px, 1fr))` **自适应**（非固定 2/3 列），由容器宽度决定列数，无需逐断点声明。
- 移动端优先保证触控目标 ≥ 42px（按钮、图标按钮 `.icon-btn` 34px）。
- 分类 chip 横向排列，超出可滚动（`.cats-scroll` 限宽居中）。
- 顶栏/搜索控制/分类/页脚采用「背景全宽 + 内容限宽居中」结构（`--maxw: 1200px`），与网格同宽对齐（v1.17.1 修复大屏过宽断层）。

---

## 6. 数据架构（Data Contract）

- **单一事实来源**：磁盘 `skills/<name>/SKILL.md` → 根目录 `build-skills-data.mjs`（生成 `data/skills-data.json`）→ 根目录 `build.mjs`（注入 `src/index.html` 模板）→ 预渲染进 `prototype/prototype.html` 静态产物（仓库已入库 `prototype/`，如需更新数据重跑两脚本即可）。
- 数据 Schema（实际为扁平结构）：`{ total:number, categories: string[], categoryEn: Record<string,string>, skills: Skill[] }`，其中 `Skill{ name, category, enCategory, zh, description, enDescription, allowedTools, hidden }`：
  - `name`：技能唯一标识（英文 slug）。
  - `category`：中文分类名；`enCategory`：该分类的英文名。
  - `zh`：中文名（可为空，空时渲染回退 `name`）。
  - `description`：**中文描述**；`enDescription`：英文描述。
  - `allowedTools`：授权工具列表；`hidden`：是否隐藏（`renderGrid` 过滤）。
  - `categoryEn`（根级）：分类中文→英文映射对象。
- 分类计数由 `02-render.js` 的 `catCounts()` 预聚合为 `Map`，搜索由 `matches(s, terms)`（预切分词表缓存）实现。
- 注意：`app/` 是项目**可运行 Web 应用**源码工作区，与 `prototype/`（预构建静态原型）分层；两者数据源均为磁盘 `skills/<name>/SKILL.md`（构建时由 `tools/build-skills-data.mjs` 生成 `data/skills-data.json` + `data/skills-metrics.json`）。
- 红色底线：数据契约须与 `tools/build-skills-data.mjs`/`tools/build.mjs`、`openspec/spec.md` 严格一致。

---

## 7. 技术栈（构建期，产物已预渲染）

- 原型为**纯静态原生实现**：`src/index.html`（HTML 模板）+ `src/styles/tokens.css` + `src/styles/base.css`/`layout.css`/`components.css`/`responsive.css`（设计令牌与组件样式，以 `:root` CSS 变量为唯一来源，非 Tailwind/HSL）+ `src/i18n.js`（独立国际化模块）+ `src/parts/*.js`（原生 JS 渲染与交互，按职责拆分 01-state / 02-render / 03-detail / 04-interactions / 05-main，无 React/Next.js/Radix）。
- 构建：根目录 `build.mjs` 将 CSS/JS/数据内联进 `src/index.html` 生成自包含 `prototype/prototype.html`；无任何 npm 运行时依赖（仅 Node 内置模块）。
- 数据源：`skills/<name>/SKILL.md` → `build-skills-data.mjs` 生成 `data/skills-data.json` → `build.mjs` 注入并预渲染进 `prototype/prototype.html`。
- 分发形态：仓库保留 `prototype/src/` 源码与其构建产物 `prototype/prototype.html`、设计文档（`DESIGN.md` / `COMPONENTS.md`）。
- 部署：静态托管（以 `prototype/` 为站点根目录，`buildCommand` 执行 `npm run build` 重新生成产物；无运行时依赖，直接托管 `prototype/prototype.html` 即可）。

---

## 8. 品牌形象规范（Brand Identity）

品牌资产为矢量 SVG，单一事实来源位于仓库根 [`public/`](public/) 目录：`logo.svg`（彩色主标志）、`logo-monochrome.svg`（单色版）、`favicon.svg`（网站图标）、`banner.svg`（README 横幅）、`banner-og.svg`（社交分享横幅）；图形唯一来源为 [`public/hub.svg`](public/hub.svg) 的 `<symbol id="ash-hub">`（以 `currentColor` 驱动，消费方用 `<use href="/hub.svg#ash-hub" color="...">` 控制图形色），`logo/favicon/mono/banner` 均 `<use>` 同源 symbol 保持造型单一来源。所有资产由 Next.js 以 `/` 路径提供；`public/favicon.svg` 同时作为 Next.js `/favicon.svg`。所有资产在 `README.md`「品牌资产」章节统一索引。

> 版本：v1.19.13 — 筛选增强：分类筛选由单选升级为**多选 OR**（state.cat → state.cats 数组，空=全部，点击 chip 非破坏式 toggle）；新增**排序**下拉（控制区 `#sortSelect`：名称 A-Z / 名称 Z-A / 按分类 / 按中文名，默认 A-Z）。原型 `02-render.js` 新增 `sortSkills()`、renderCats 按 `state.cats.includes` 判 active；`04-interactions.js` 分类点击改 toggle、`clearFilters` 重置 cats+sort、绑定 `#sortSelect` change；`index.html` 控制区加排序 select + `i18n.js` 加 `sort.*` 中英文案 + `components.css` 加 `.sort-wrap select` 样式。app `SkillsExplorer.tsx` 改 `cats` 多选(toggleCat)+`sort` state+排序比较器+控制区 select；`globals.css` 补 `.sort-wrap` 样式。其余同 v1.19.12（全字段规范重排 SKILL.md 头部注释）+ v1.19.7（统计迁入页脚 4 项：技能总数/分类/英文描述覆盖/支持语言）+ v1.19.6（名称显示分组 + 设置紧凑化）+ v1.19.5（界面元素分组）+ v1.19.4（app 卡片层重建、`app/components/` 最小可用 `AppShell`/`SkillsExplorer`/`skill-card`、`.card-body` 列表布局修复）+ v1.19.3（原型卡片双名/列表修复）+ v1.18.3（页眉品牌区优化、设置弹窗四组、视图/密度持久化、卡片原生 button、响应式 `--maxw` 限宽）。

> 版本：v1.19.14 — 详情弹窗重构：新增 `app/components/detail-modal.tsx`，`build-skills-data.mjs` 提取 `author`/`license`/`version`/`githubDir`；原型 `03-detail.js` 注入元信息区（作者/协议/GitHub 目录）+ 相关技能 + 复制命令；数据契约 `SkillEntry` 增 `source?` 可选字段（v1.19.18 规范补充，指向 skills.sh 生态上游溯源）。后续 v1.19.15~v1.19.18 的逐项变更见根 `CHANGELOG.md`。

### 8.1 标志释义（Logo）

三节点（技能）经连线汇聚至中心 Hub 圆点，象征「技能 → 统一中心枢纽」的产品定位；圆角方形承载（对齐 `--radius: 0.75rem` 视觉语言），主绿填充。

| 变体 | 文件 | 用途 | 背景 |
|------|------|------|------|
| 彩色主标志 | `logo.svg` | 官网页眉、README 头图、文档封面 | 浅/深皆可（自身含底） |
| 单色版 | `public/logo-monochrome.svg` | 页脚、浅色文档、印刷单色场景 | 浅色 |
| 网站图标 | `public/favicon.svg` | 浏览器标签、书签 | 透明（纯绿图形） |
| README 横幅 | `public/banner.svg` | `README.md`/`README.en.md` 标题下顶部 hero（1200×400，主绿渐变 + 衬线项目名/副标题） | 浅/深皆可（自身含底） |
| 社交分享横幅 | `public/banner-og.svg` | Open Graph / 社交卡（Twitter·X、LinkedIn 等，1.91:1 = 1200×628），避免文字被裁切 | 浅/深皆可（自身含底） |
| 应用图标 / 网站图标 | `public/favicon.svg` | Next.js `/favicon.svg` 与浏览器标签、书签（纯绿无渐变） | 透明（纯绿图形） |

### 8.2 标志网格与安全区

- 画布 `viewBox="0 0 32 32"`，图形在 32×32 内居中，圆角 `rx="8"`。
- **安全区**：标志四周保留 ≥ 1/8 画布（即 4px@32）留白，避免与文字/边框贴合。
- **最小尺寸**：独立展示 ≥ 24×24px（或 16px 仅作 favicon）；低于 16px 建议仅用 `favicon.svg` 纯图形。

### 8.3 品牌配色（Brand Palette）

标志与界面共用同一套主绿，禁用其它色相作为主品牌色。

| 名称 | 色值 | HSL 通道 | 用途 |
|------|------|----------|------|
| 品牌主绿（浅） | `#2e9e6b` | `152 56% 40%` | 标志填充、主按钮、聚焦环（`--primary` 浅） |
| 品牌主绿（深/悬停） | `#5cc98c` | `146 52% 60%` | logo 渐变终点、深色模式 `--primary` 提亮（`--primary` 深） |
| 单色深底 | `#10231a` | `152 50% 9%` | 单色标志底、深背景反白 |
| 反白 | `#ffffff` | `0 0% 100%` | 标志内图形、深色文字 |

> 品牌主绿即设计系统 `--primary`（§2.1），两者必须保持同一 HSL 通道，禁止漂移。`logo.svg` 使用浅→深绿线性渐变（`#2e9e6b`→`#5cc98c`，端点分别对应上述两行）；`favicon.svg` 为纯 `#2e9e6b` 无渐变，保证 16px 下清晰。

### 8.4 favicon 规格

- 格式：SVG（矢量，自适应任意 DPI）；如目标平台仅接受位图，由 `favicon.svg` 栅格化为 32×32 / 180×180（apple-touch）PNG。
- 颜色：纯 `#2e9e6b` 底 + 反白图形，无渐变（保证 16px 下清晰）。
- 部署：`prototype/favicon.svg` 由根 `build.mjs` 从 `public/favicon.svg` 复制；`app/` 通过 `app/layout.tsx` 的 `metadata.icons.icon = "/favicon.svg"` 引用 `public/favicon.svg`。

### 8.5 禁用示例（Don'ts）

- ❌ 修改主绿色相（如改用蓝/紫）或降低饱和度至灰绿。
- ❌ 拉伸、压扁、旋转标志或改动节点相对位置。
- ❌ 在标志图形上叠加文字、阴影或额外装饰。
- ❌ 在对比度不足的浅灰背景使用彩色标志却不保留圆角底（应优先用含底的 `logo.svg`）。
- ❌ 用等位图（JPG/PNG）替代矢量源，导致缩放失真。

### 8.6 使用约定

- 页眉品牌区：标志（30×30，圆角底 + 极淡主绿光晕 `box-shadow`，hover `scale(1.06)`）+ 文字两行——主名「Agent Skills Hub」（衬线 `--font-display`，17px/700）+ 副标题（11px/`--text-2`/弱化），见 `app/components/AppShell.tsx` 的 `BrandMark()`+`.brand-text` 与原型 `prototype/src/index.html` 的 `.brand`+`.brand-text`。
- 代码内联引用：原型用 data-URI 内联 `public/hub.svg` 的 symbol + 外链 `favicon.svg` 双重声明（见 `prototype/src/index.html` `<head>`）。
- 品牌资产变更须同步：①本 §8 与 README「品牌资产」；②`public/hub.svg` 与 `public/*` 资产同源；③版本号 bump。
