diff --git a/LOCAL_SETUP_NOTES.md b/LOCAL_SETUP_NOTES.md
new file mode 100644
index 00000000..b215db01
--- /dev/null
+++ b/LOCAL_SETUP_NOTES.md
@@ -0,0 +1,168 @@
+# Sub2API 本地开发环境搭建记录
+
+> 2026-04-19 @ macOS (darwin/arm64)
+
+## 一、环境依赖
+
+| 项 | 版本 | 说明 |
+|---|---|---|
+| Go | 1.24.3(本机)→ 1.26.2(auto via GOTOOLCHAIN) | go.mod 要求 1.26.2,靠 Go 1.21+ 的 GOTOOLCHAIN 机制自动下载 |
+| Node | v24.13.0 | ≥18 即可 |
+| pnpm | v10.33.0 | 现装:`npm install -g pnpm` |
+| Docker | OrbStack | 已跑 mysql8@3306,端口冲突规避见下 |
+| 端口占用 | 8080 / 5433 / 6380 均空闲 | 5432/6379 留给可能的其他 PG/Redis |
+
+## 二、部署步骤(实际执行)
+
+### 1. 拉源码
+```bash
+git clone https://github.com/Wei-Shaw/sub2api.git /Users/mini/Work/dev/sub2api
+```
+
+### 2. 起依赖容器(非默认端口)
+```bash
+docker run -d --name sub2api-pg \
+ -e POSTGRES_PASSWORD=devpass -e POSTGRES_DB=sub2api \
+ -p 5433:5432 postgres:15
+
+docker run -d --name sub2api-redis \
+ -p 6380:6379 redis:7
+```
+
+### 3. 安装 pnpm(首次)
+```bash
+npm install -g pnpm
+```
+
+### 4. 构建前端
+```bash
+cd /Users/mini/Work/dev/sub2api/frontend
+pnpm install # ~9 秒
+pnpm run build # ~8 秒,产物输出到 ../backend/internal/web/dist/
+```
+
+### 5. 构建后端(⚠️ 必带 `-tags embed`)
+```bash
+cd /Users/mini/Work/dev/sub2api/backend
+go build -tags embed -o sub2api ./cmd/server
+# 产物:105MB Mach-O 64-bit arm64
+```
+
+### 6. 生成 config.yaml
+```bash
+cp /Users/mini/Work/dev/sub2api/deploy/config.example.yaml \
+ /Users/mini/Work/dev/sub2api/backend/config.yaml
+```
+
+修改四处(见下方问题点 Issue #1 说明 sslmode):
+
+| 字段 | 原值 | 改为 |
+|---|---|---|
+| `database.port` | 5432 | **5433** |
+| `database.password` | `"your_secure_password_here"` | `"devpass"` |
+| `database.sslmode` | `"prefer"` | **`"disable"`** |
+| `redis.port` | 6379 | **6380** |
+| `jwt.secret` | `"change-this-..."` | `openssl rand -hex 32` 产出的 64 位 hex |
+
+### 7. 启动 + 验证
+```bash
+cd /Users/mini/Work/dev/sub2api/backend
+nohup ./sub2api > /tmp/sub2api.log 2>&1 &
+# 等 5-10 秒让服务完成 pricing 数据下载
+curl -si http://localhost:8080 | head
+# 期望:HTTP/1.1 200 OK,HTML 含
` with an extra chip `
{{ $t('pricing.soonChip') }} ` (chip = small pill, amber/muted). Add chip CSS in same scoped style.
+
+- [ ] **Step 1: Audit backend for advertised features**
+
+Run: `cd /Users/mini/Work/dev/sub2api && grep -ril -E "budget|zero_log|priority_schedul|failover|cooling" backend/ 2>/dev/null | head -20`
+
+Document which features are implemented; the rest get `SOON` chips.
+
+- [ ] **Step 2: Add `pricing` namespace to `zh.ts`** with structure:
+
+```ts
+pricing: {
+ hero: {
+ kicker: '// pricing · 充多少 · 用多少 · 永不过期',
+ previewPill: '// preview · 最终定价以开售为准',
+ title1: '一次充值,',
+ titleAccent: '全平台',
+ title2: '通用',
+ sub: '同一份积分可以用在 Claude / ChatGPT / Gemini 任意池上。我们把你的订阅额度变成真正的 API 余额 —— 相比官方 API 便宜 {discount}。',
+ subDiscount: '至多 70%',
+ underline: '余额永不过期 · 支持支付宝 / 微信 / USDT · 无隐藏订阅费'
+ },
+ soonChip: 'SOON',
+ tiers: {
+ starter: {
+ flag: 'STARTER',
+ tierLabel: 'tier · 01',
+ headline: '先尝尝鲜,跑通接入',
+ credit: '充 $9.9 → 得 {credit} 积分 {bonus}',
+ creditAmount: '$12',
+ creditBonus: '+21%',
+ discountTag: '相当于官方 API · 0.5 折起',
+ cta: '充值 →',
+ features: {
+ allModels: '可用所有模型 / 所有池',
+ oneKey: '{count} 个 API Key',
+ oneKeyCount: '1',
+ rpm60: '60 RPM 速率限制',
+ log7: '基础日志(7 天保留)',
+ noBYOS: '自带订阅接入',
+ noTeam: '团队 / 多人协作'
+ }
+ },
+ pro: {
+ flag: '◆ 推荐',
+ tierLabel: 'tier · 02',
+ headline: '个人重度用户 · 最划算',
+ credit: '充 $29.9 → 得 {credit} 积分 {bonus}',
+ creditAmount: '$45',
+ creditBonus: '+50%',
+ discountTag: '相当于官方 API · 3-7 折',
+ cta: '立即充值 →',
+ features: {
+ allModels: '可用所有模型 / 所有池',
+ threeKeys: '{count} 个 API Key · 独立预算',
+ threeKeysCount: '3',
+ rpm120: '120 RPM 速率限制',
+ log30: '调用日志(30 天保留)',
+ byos: '自带订阅接入(无限个)',
+ failover: '多账号 failover 调度'
+ }
+ },
+ scale: {
+ flag: '⚡ 限时 +100%',
+ tierLabel: 'tier · 03',
+ headline: '小团队 / 长跑项目',
+ credit: '充 $99 → 得 {credit} 积分 {bonus}',
+ creditAmount: '$198',
+ creditBonus: '+100%',
+ discountTag: '相当于官方 API · 2-5 折',
+ cta: '充值 →',
+ features: {
+ proAll: '所有 Pro 能力',
+ tenKeys: '{count} 个 API Key · 独立预算',
+ tenKeysCount: '10',
+ rpm300: '300 RPM 速率限制',
+ log90: '调用日志(90 天保留)',
+ priority: '请求优先级加权调度',
+ community: 'Slack / Discord 群组支持'
+ }
+ },
+ custom: {
+ flag: 'CUSTOM',
+ tierLabel: 'tier · 04',
+ headline: '自定义金额 · 按需充值',
+ creditPrefix: '得约',
+ bonusPrefix: '+',
+ discountTag: '根据金额阶梯自动匹配折扣',
+ cta: '定制充值 →',
+ features: {
+ noExpire: '积分永不过期',
+ proAll: 'Pro 全部能力',
+ tier: '阶梯 +21% ~ +100%',
+ pay: '支付宝 / 微信 / USDT',
+ slider: '拖动滑块预览赠送'
+ }
+ }
+ },
+ custom: {
+ enterprise: {
+ title: 'Enterprise · 企业定制',
+ desc: '专属订阅池、SLA、合规审计、私有化部署、发票结算。规模 >$500/月起可申请。',
+ cta: '联系商务 →'
+ },
+ binding: {
+ title: '已有订阅?直接接入',
+ desc: '有 Claude Max / ChatGPT Pro?免费注册后绑定,只为 PURO 路由费买单 —— 按次 {price}。',
+ price: '$0.0008/request',
+ cta: '接入我的订阅 →'
+ }
+ },
+ calc: {
+ kicker: '// cost estimator',
+ previewPill: '// estimated · 以实际计费为准',
+ title: '算算你能省多少?',
+ sub: '按你的使用场景,对比 PURO 和官方 API 的月度花费差。数字会根据你选的场景自动更新。',
+ reqLabel: '日均请求数',
+ tokLabel: '平均每请求 tokens',
+ mixLabel: 'Claude 占比',
+ monthlyTok: '月度 tokens 消耗',
+ officialCost: '官方 API 价格',
+ puroCost: 'PURO 价格(含 +50% 赠送)',
+ savings: '节省',
+ recLabel: '建议充值',
+ recStarter: '≈ Starter 档够用',
+ recPro: '≈ Pro 档 1 个月',
+ recScale: '≈ Scale 档 · 1 个月'
+ },
+ works: {
+ kicker: '// works everywhere',
+ title: '一个 key,所有工具通用',
+ sub: '只要支持自定义 {baseUrl} 或 OpenAI / Anthropic API,都能直接接入 PURO。',
+ baseUrl: 'base_url'
+ },
+ faq: {
+ kicker: '// frequently asked',
+ title: '你可能想问的',
+ noAnswer: '没找到答案?{contact} · 通常 2 小时内回复。',
+ contact: '发邮件给我们 ↗',
+ q1: 'PURO 和 API 中转站 / API 代理有什么不同?',
+ a1: '中转站只是把官方 API 请求转一手,价格取决于你预付多少 balance。PURO 的不同是 —— 我们让你 {bold}。你原本就在付的 $20/月,不再只能在官网聊天里用,而是通过统一 API 喂给 Cursor、Claude Code、任何 SDK。同时我们也提供按量充值的官方 API 备用池,两种模式可以混用。',
+ a1bold: '把已有的 Claude Pro / ChatGPT Plus 订阅变成 API',
+ q2: '用订阅跑 API 会不会被封号?',
+ a2: '我们会自动控制每个订阅的请求节奏,并在触发限流时把请求 failover 到池子里的其他订阅。实际上 PURO 的调用模式比你在官方客户端直接复制粘贴大段对话 {bold}。你绑定多个订阅时,单个账号的 RPM 会被压到足够安全的阈值内。另外所有凭证用 AES-256 加密存储,请求链路不经过第三方。',
+ a2bold: '更不容易触发风控',
+ q3: '积分会过期吗?可以退款吗?',
+ a3: '{bold}你可以攒着慢慢用 —— 包括几个月都不用。首次充值 7 天内未产生任何调用可全额退款,之后按剩余积分 85% 比例退。详见退款政策。',
+ a3bold: '积分永不过期。',
+ q4: '支持哪些支付方式?',
+ a4: '国内:支付宝 · 微信支付。国际:Stripe 信用卡 · USDT (TRC20 / ERC20) · PayPal。企业充值支持 Invoice 对公打款,人民币开票。',
+ q5: '一个 PURO 账号可以绑定多少个订阅?',
+ a5Starter: 'Starter 档:不支持绑定自带订阅',
+ a5Pro: 'Pro 档及以上:无限制,你可以把 10 个 ChatGPT Plus + 3 个 Claude Pro 一起绑上去,统一调度',
+ a5Enterprise: 'Enterprise:支持跨团队共享池,按组织维度隔离',
+ q6: '如果某个订阅触发限流了会怎样?',
+ a6: 'PURO 的调度器会把受限的订阅自动标记为 cooling 状态,暂时从池子里摘除。同一请求会立刻被 failover 到池内其他健康订阅上 —— 调用方通常 {bold}。你可以在 Dashboard 看到每个订阅的当前状态和剩余配额。',
+ a6bold: '感受不到中断',
+ q7: '计费精度?超量会怎么办?',
+ a7: '按实际 token 数 + 模型单价计费,精度到 4 位小数。每个 API Key 可设置独立月度预算,达到后 402 Payment Required,不会继续扣费。账户总余额不足时同样会返回 402,且 Dashboard 有 80% / 95% 两级提醒邮件。',
+ q8: '数据会被用于训练吗?',
+ a8: '{bold}所有请求仅用于路由转发,不入库、不留存内容(仅保留元数据如模型、token 数、延迟,用于计费和日志)。Pro 档及以上可选开启"零日志模式",我们连请求 ID 都不记录。',
+ a8bold: '不会。',
+ q9: '可以私有化部署吗?',
+ a9: 'Enterprise 档支持 Docker / K8s 私有化部署,控制面和数据面可以分开。授权按年订阅,包含升级和技术支持。',
+ q10: '支持哪些模型?会跟进新模型吗?',
+ a10: '当前覆盖 Claude(Sonnet 4.5 / Opus 4 / Haiku 4.5)、ChatGPT(GPT-5 / GPT-5 Codex / GPT-4.1)、Gemini(2.5 Pro / 2.5 Flash)。每当官方发布新模型,我们通常在 {bold}。完整模型列表见文档。',
+ a10bold: '24 小时内上线'
+ },
+ finalCta: {
+ kicker: '// ready to start',
+ title: '5 分钟,拿到你第一个 sk-puro-* key',
+ subtitle: '绑定你的第一个订阅即可开始。',
+ ctaPrimary: '免费注册 →',
+ ctaDocs: '查看文档'
+ }
+}
+```
+
+**Note:** The zip's final CTA contains `注册送 $5 测试积分` — DROP this line per Stage 1 decision (no $5 bonus). The subtitle above is pruned.
+
+- [ ] **Step 3: Mirror `pricing` namespace in `en.ts`**
+
+Translation guidelines:
+- Hero title: `"Top up once," / "unlimited across" / "all platforms"`
+- Hero sub: `"The same credits work across Claude / ChatGPT / Gemini pools. We turn your subscription into real API balance — {discount} cheaper than the official API."`
+- Tier CTAs: `"Top up →"` / `"Buy Pro →"` / `"Top up →"` / `"Custom top-up →"`
+- Tier flags: `"STARTER"` / `"◆ RECOMMENDED"` / `"⚡ LIMITED +100%"` / `"CUSTOM"`
+- FAQ answers: professional/concise tone, keep technical terms English
+
+- [ ] **Step 4: Write `PricingView.vue`**
+
+Structure:
+
+```vue
+
+
+
+
+
+
+
+
+
+
+
+
+ PURO AI
+
+
+ {{ $t('landing.nav.products') }}
+ {{ $t('landing.nav.pricing') }}
+ {{ $t('landing.nav.docs') }}
+
+
+
+
{{ $t('landing.nav.login') }}
+
{{ $t('landing.nav.signup') }}
+
+
+
+
+
+
+ {{ $t('pricing.hero.kicker') }}
+ {{ $t('pricing.hero.previewPill') }}
+
+ {{ $t('pricing.hero.title1') }}{{ $t('pricing.hero.titleAccent') }} {{ $t('pricing.hero.title2') }}
+
+
+ {{ $t('pricing.hero.subDiscount') }}
+
+
+
+ {{ $t('pricing.hero.underline') }}
+
+
+
+
+
+
+
+
+
+
+ {{ $t('pricing.calc.previewPill') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+**Subagent execution note:** This task is large. Full template is ~400 lines of Vue. Subagent should:
+1. Open `docs/design-drafts/v2/Pricing.html` in one tab
+2. Open the target `PricingView.vue` being written
+3. Copy each section (hero → tier grid → custom row → calc → works → faq → final-cta), replacing raw Chinese with `$t(...)` lookups per the schema in Step 2
+4. Keep all SVG/HTML structure verbatim
+5. Apply the SOON chip to any unimplemented feature per Step 1 audit results
+6. Remove the $5 bonus line from final CTA
+
+- [ ] **Step 5: Add `/pricing` route**
+
+Modify `frontend/src/router/index.ts`. Add new route entry (public, no auth guard):
+
+```ts
+{
+ path: '/pricing',
+ name: 'pricing',
+ component: () => import('@/views/pricing/PricingView.vue'),
+ meta: { requiresAuth: false, title: 'Pricing · PURO AI' }
+}
+```
+
+Add this near the `/docs` route (public portal section).
+
+- [ ] **Step 6: Add `定价 / Pricing` link to LandingView nav**
+
+Modify `LandingView.vue` `.nav-links` block:
+
+```vue
+
+```
+
+(Landing's Pricing link was added as part of Task 3's nav update for Docs; Landing gets it here.)
+
+- [ ] **Step 7: Typecheck + build**
+
+Run: `pnpm run typecheck && pnpm run build`
+Expected: PASS.
+
+- [ ] **Step 8: Commit**
+
+```bash
+git add frontend/src/views/pricing/ frontend/src/router/index.ts frontend/src/views/landing/LandingView.vue frontend/src/i18n/locales/zh.ts frontend/src/i18n/locales/en.ts
+git commit -m "feat(pricing): add PricingView with bilingual i18n + nav link"
+```
+
+---
+
+## Task 10: Verification + PR + deploy
+
+**Files:** none changed
+
+- [ ] **Step 1: Run full typecheck + build**
+
+```bash
+cd frontend
+pnpm run typecheck
+pnpm run build
+```
+
+Expected: both PASS.
+
+- [ ] **Step 2: Scan for leftover hard-coded Chinese in portal views**
+
+```bash
+cd /Users/mini/Work/dev/sub2api
+grep -rnP "[\x{4e00}-\x{9fa5}]" frontend/src/views/landing/ frontend/src/views/docs/ frontend/src/views/pricing/ 2>/dev/null | grep -v "^.*://" | grep -vE ""
+```
+
+Expected: empty output (only things that should remain are comments, which this grep filters).
+
+- [ ] **Step 3: Start preview and manually verify**
+
+```bash
+cd frontend
+pnpm run preview
+```
+
+Open in browser (http://localhost:4173):
+- `/` — Landing: switcher in top-right, click `EN` → all text flips to English, refresh → stays English
+- `/pricing` — Pricing: 4 tiers render, calculator sliders work, FAQ accordions open, switcher works
+- `/docs` — Docs: tables render, copy-code works, switcher works
+- `/login` — narrative panel + form, switcher top-right
+- `/register` — narrative panel + form, switcher top-right
+
+For each page: toggle EN ↔ ZH at least twice, confirm no flashes of untranslated Chinese.
+
+- [ ] **Step 4: Stop preview**
+
+Ctrl-C the preview server. Verify no zombie processes:
+```bash
+pgrep -f "vite.*preview"
+```
+Expected: no output. If any: `pkill -f "vite.*preview"`.
+
+- [ ] **Step 5: Push branch and open PR**
+
+```bash
+git push -u origin feat/portal-i18n-pricing
+gh pr create --title "feat: PURO portal i18n (zh/en) + Pricing page" --body "$(cat <<'EOF'
+## Summary
+- Puro-themed `PuroLocaleSwitcher` mounted in Landing/Docs/Login/Register top nav
+- Full i18n extraction for LandingView / DocsView / Login & Register narrative panels (zh + en)
+- New `/pricing` page ported from design zip, i18n-native, with preview pricing pill + SOON chips for unshipped features
+- Nav adds 定价 / Pricing link on Landing + Docs
+
+## Test plan
+- [ ] Typecheck + build pass
+- [ ] Toggle EN/ZH on /, /pricing, /docs, /login, /register — all text switches
+- [ ] Refresh persists locale (localStorage `sub2api_locale`)
+- [ ] Pricing calculator sliders update live; custom tier bonus updates
+- [ ] Admin pages (`/dashboard`, `/admin/*`) unaffected — no CSS regressions
+
+🤖 Generated with [Claude Code](https://claude.com/claude-code)
+EOF
+)"
+```
+
+- [ ] **Step 6: Merge when CI green**
+
+```bash
+gh pr merge --squash --delete-branch
+```
+
+- [ ] **Step 7: Verify production deploy**
+
+```bash
+curl -sSf -o /dev/null -w "%{http_code}\n" https://ai.puro.im/
+curl -sSf -o /dev/null -w "%{http_code}\n" https://ai.puro.im/pricing
+curl -sSf -o /dev/null -w "%{http_code}\n" https://ai.puro.im/docs
+```
+
+Expected: `200 200 200`.
+
+- [ ] **Step 8: Cleanup worktree**
+
+```bash
+cd /Users/mini/Work/dev/sub2api
+git worktree remove ../sub2api-portal-i18n
+```
+
+---
+
+## Appendix: Translation style guide (EN)
+
+- **Register:** tech-product, concise, no marketing fluff
+- **Technical terms:** keep English (`OAuth`, `SDK`, `API key`, `RPM`, `base_url`, `tokens`)
+- **Brand tone:** PURO speaks to developers first, so answers in FAQ stay factual, not salesy
+- **Punctuation:** English full stops / commas (not `,` or `。`)
+- **Numbers:** keep format from zh (e.g., `$29.9`, `$198`)
+
+## Appendix: Key guarantees
+
+- All 5 pages continue to render correctly in zh after extraction (regression check at Task 10 Step 3)
+- `setLocale()` remains the single source of truth — no custom storage added
+- `PuroLocaleSwitcher` reuses `setLocale()` imports; does not duplicate i18n plumbing
+- No changes to admin pages, AppHeader, or existing `LocaleSwitcher.vue` (decoupled)
diff --git a/docs/superpowers/plans/fidelity-delta-report.md b/docs/superpowers/plans/fidelity-delta-report.md
new file mode 100644
index 00000000..a507233b
--- /dev/null
+++ b/docs/superpowers/plans/fidelity-delta-report.md
@@ -0,0 +1,445 @@
+# PURO AI Fidelity Delta Report
+
+> Compare: `docs/design-drafts/v2/{Landing,Login,Register}.html` vs `frontend/src/views/{landing,auth}/*.vue`
+> Generated: 2026-04-19
+
+---
+
+## 1. LandingView
+
+**Zip:** `docs/design-drafts/v2/Landing.html`
+**Vue:** `frontend/src/views/landing/LandingView.vue`
+
+---
+
+### Copy / Text Deltas
+
+| # | Zip (HTML) | Vue (SFC) | Severity | Notes |
+|---|---|---|---|---|
+| L-T1 | Hero eyebrow: `
NEW 统一接入多个 AI 平台 · 零改动切换` | Hero eyebrow: `ChatGPT Plus · Claude Pro · Codex · Gemini` (plain pill, no badge) | **important** | Zip has a highlighted NEW badge + tagline; Vue shows only a product-list pill with no "NEW" call-out and no `统一接入…` text |
+| L-T2 | Hero sub: `聚合成统一 API,零改动接入
OpenAI /
Anthropic SDK` — pill is a code-styled inline token | Vue: `聚合成统一 API,零改动接入 OpenAI / Anthropic SDK` — plain text, no pill styling | **cosmetic** | Inline `
` with monospace border lost |
+| L-T3 | Hero CTA buttons: `立即开始 →` (primary) + `查看文档` (ghost) | Hero CTA buttons: `登录 →` (primary) + `联系咨询` (ghost) | **important** | Primary button label changed from "立即开始" to "登录"; secondary changed from "查看文档" to "联系咨询". Zip routes unauthenticated users to Register first; Vue routes to Login |
+| L-T4 | Hero micro-text: `无需信用卡 · 用你已有的订阅 · 5 分钟跑通` (three dot-separated items, each a ``) | Hero micro-text: `已验证可用 Codex CLI · Claude Code · curl · 服务器出口新加坡` (single plain string) | **important** | Entirely different social-proof claims; zip emphasises zero-friction onboarding, Vue emphasises tech compatibility |
+| L-T5 | Model-wall section kicker: `// providers` | Vue model-wall section kicker: `支持的 AI 平台` (Chinese, no `//` prefix) | **cosmetic** | Zip uses monospace `// providers` pattern; Vue switches to Chinese heading |
+| L-T6 | Model-wall subtitle: `通过 OAuth 直接复用你的订阅,无需申请官方 API key` | Vue sub: `无需申请官方 API key,也无需切换账号` | **cosmetic** | Minor copy rewrite; same meaning |
+| L-T7 | Features section title: `付一次订阅, 用起一整个模型池` | Vue section title: `一套 key,三件武器` | **important** | Substantially different headline; zip's "pay once" framing vs Vue's "one key, three weapons" |
+| L-T8 | Features section sub: `把散落在各个平台的订阅,整合成开发者真正能用的基础设施` | Vue: *(sub entirely absent)* | **important** | Vue omits the features section subtitle entirely |
+| L-T9 | Feature card 2 copy: `某个 ChatGPT Plus 触发限流,自动 failover 到下一个。重启、刷新 token 全自动。` | Vue: `某个上游触发限流 / 冷却时,流量切到下一个健康账号,token 刷新全自动。` | **cosmetic** | Light rewrite, same meaning |
+| L-T10 | Feature bullets (all 3 cards): 3-bullet lists under a dashed-border divider | Vue: *bullets entirely absent* from all feature cards | **important** | All 9 feature bullet items (`OpenAI Responses API 兼容`, `限流/5xx 自动 failover`, etc.) are missing |
+| L-T11 | Code demo section kicker: `// integration` | Vue: `快速接入` | **cosmetic** | |
+| L-T12 | Dashboard section sub (long): `不像第三方 API 池子那种"扣了多少不告诉你"。你能看到每次调用:扣了哪个账号、跑了哪个模型、用了多少 tokens、花了多少钱、上游响应几秒。` | Vue: `不像第三方 API 池子那种"扣了多少不告诉你"——扣哪个账号、跑哪个模型、用了多少 tokens、上游响应几秒,一目了然。` | **cosmetic** | Condensed; "花了多少钱" detail removed from Vue version |
+| L-T13 | CTA banner: `把订阅变成 API — 5 分钟` + `绑定第一个账号,生成 sk- key,把 base_url 指过来。就这些。` | *CTA banner entirely absent from Vue* | **important** | The mid-page conversion CTA section is completely missing from Vue |
+| L-T14 | Pricing section (full 3-tier grid + `pricing-more-link`) | *Pricing section entirely absent from Vue* | **important** | Full pricing section with 3 tiers ($9.9 / $29.9 / $99), all tier copy, and "查看完整定价" link is missing |
+| L-T15 | FAQ section (6 expandable `` + "查看全部 10 个问题" link) | *FAQ section entirely absent from Vue* | **important** | All FAQ content missing |
+| L-T16 | Footer brand tagline: `把多个 AI 订阅聚合成统一 API。让「已经付过钱」的订阅真正为你工作。` | Vue: `Self-hosted on puro.im` | **important** | Zip has Chinese product tagline; Vue shows English self-hosted note |
+| L-T17 | Footer meta: `© 2026 puro.im · Built with ♥ in Shanghai` | Vue: `© 2026 puro.im · MIT License\nfork of Wei-Shaw/sub2api` | **cosmetic** | Different but both acceptable |
+| L-T18 | Footer "产品" column: 文档 / 定价 / FAQ / 功能 | Vue "产品" column: 文档 / 更新日志 | **important** | Vue removes 定价/FAQ/功能 links |
+| L-T19 | Footer "账户" column: 登录 / 注册 / Dashboard / 绑定订阅 | Vue footer has "联系" column (admin@puro.im / git.puro.im) instead of "账户" column | **important** | Entire "账户" column replaced with "联系" column |
+| L-T20 | Footer system-status line: `all systems operational` (with green dot) | *Absent from Vue footer* | **cosmetic** | |
+| L-T21 | Stat card labels (dashboard): `Requests · 24h`, `Tokens · 24h`, `Avg latency`, `Est. savings` | Vue: `今日请求`, `输入 Tokens`, `输出 Tokens`, `今日费用` | **important** | Different stat names and dimensions (4th stat is "savings" in zip vs "cost" in Vue; zip has 1 tokens stat vs Vue has 2 separate I/O token stats) |
+| L-T22 | Log table columns: Time / Provider / Model / Tokens / Cost / Latency / Status | Vue: 时间 / 模型 / 上游 / 状态 / 用量 (5 cols, Chinese, Cost and Latency absent) | **important** | Zip has 7-column table with Cost + Latency; Vue drops those two columns |
+
+---
+
+### Structure Deltas
+
+| # | What zip has | Vue status | Severity |
+|---|---|---|---|
+| L-S1 | Nav links include `#pricing` and `#faq` anchor links | Vue nav only has `#features` + `/docs` (no pricing/faq) | **important** |
+| L-S2 | Hero: `` with 3 `` children and `.dot` separators | Vue: single plain string in `.hero-micro`, no separators | **cosmetic** |
+| L-S3 | Model cards: icon logo (`` + inline SVG) + name + tag stacked vertically with green status chip | Vue: colored dot + name + meta in a row (horizontal), no status chip, no SVG logos | **important** |
+| L-S4 | Code demo: single-column with TWO separate `code-frame` panels, each with traffic-light dots + tabs + `● edited 2s ago` / `zsh · puro ≈ 210ms` labels | Vue: two-column `code-demo` grid with simplified `code-block` panels (no tab row, no traffic dots) | **important** |
+| L-S5 | Dashboard: browser-chrome header (`dash-head` with url bar `ai.puro.im/dashboard` + lock icon + `me@puro` label) | Vue: minimal `dash-header` with title + three dots, no URL bar | **important** |
+| L-S6 | Dashboard: left sidebar (`dash-side`) with WORKSPACE and SETTINGS nav groups | Vue: sidebar entirely absent | **important** |
+| L-S7 | Dashboard chart area: `chart-grid` (2fr + 1fr) with line chart SVG + donut chart SVG side-by-side | Vue: single `chart-card` with a simplified `
` chart only, no donut | **important** |
+| L-S8 | Donut chart: full SVG with 4 arc segments (Claude 48% / GPT 32% / Gemini 14% / Codex 6%) + legend | Vue: absent | **important** |
+| L-S9 | CTA banner section (mid-page, after dashboard) | Vue: absent | **important** |
+| L-S10 | Pricing section (3-tier grid) | Vue: absent | **important** |
+| L-S11 | FAQ section (`` accordion, 6 items) | Vue: absent | **important** |
+| L-S12 | Footer: 4-column grid (2fr brand + 3×1fr cols) with `footer-brand` description paragraph | Vue: 4-column grid present but content differs (see L-T16/T18/T19) | **cosmetic** (structure match, content differs) |
+
+---
+
+### Visuals / SVG
+
+| # | Delta | Severity |
+|---|---|---|
+| L-V1 | Nav brand: inline SVG hexagon (`` + inner fill path) | Vue: `⬢` Unicode emoji | **important** — SVG renders crisp at all sizes; emoji rendering varies by OS/font |
+| L-V2 | Footer brand: same inline SVG hexagon | Vue: `⬢` emoji | **important** |
+| L-V3 | Model-card logos: unique inline SVG per provider (Claude chevron, GPT circle, Codex bracket, Gemini star, "..." dots) | Vue: colored 10px `` only | **important** |
+| L-V4 | Dashboard line-chart: SVG with gradient fill area, cyan/purple/amber stroke lines, x-axis time labels (`00:00`…`now`) | Vue: simplified `
` without fill area or x-axis labels | **important** |
+| L-V5 | Hero eyebrow: `.badge` span with cyan tinted background for "NEW" | Vue: no badge element | **important** |
+| L-V6 | Pricing tier-flag chips (STARTER / ◆ 推荐 / ⚡ 限时) with color variants (`muted` / default / `amber`) | Vue: absent (no pricing section) | n/a (section missing) |
+
+---
+
+### Missing CSS (zip has, Vue scoped missing)
+
+| # | Missing rule / component | Impact |
+|---|---|---|
+| L-C1 | `.model-logo` (icon container with border + bg), `.status-chip` (green dot + glow pulse), `.model-card.disabled` opacity | Model wall looks flat vs. designed appearance |
+| L-C2 | `.hero-eyebrow .badge` (cyan tinted pill) | Missing "NEW" badge styling |
+| L-C3 | `.hero-micro .dot` (4px separator dots) | Separator dots between hero micro items |
+| L-C4 | `.code-tabs`, `.tab`, `.tab.active`, `.tab-dot`, `.traffic` | Full code-frame tab-bar styling missing |
+| L-C5 | `.dash-head .url` (address-bar mockup with lock icon pseudo) | Dashboard browser-chrome bar |
+| L-C6 | `.dash-side`, `.side-group`, `.side-label`, `.side-item`, `.side-item.active` | Sidebar nav entirely unstyled |
+| L-C7 | `.chart-grid` 2:1 layout, `.chart-title .legend`, `.sw` (legend swatch) | Chart section layout and legend |
+| L-C8 | `.cta-banner` and all sub-rules | Mid-page CTA banner |
+| L-C9 | `.pricing-grid-landing`, `.tier-l`, `.tier-l-flag`, `.tier-l-price`, `.tier-l-credit`, `.tier-l-discount`, `.tier-l-feats`, `.pricing-more-link` | Entire pricing card system |
+| L-C10 | `.faq-l` + `summary`, `::after`, `[open]` variants, `.faq-answer` | FAQ accordion |
+| L-C11 | `.section-kicker` with `// ` monospace prefix convention (zip uses `letter-spacing: 0.15em`) | Vue uses 0.12em and different style |
+
+---
+
+### Missing Scripts / Interactivity
+
+| # | What zip has | Vue status | Severity |
+|---|---|---|
+| L-I1 | Code-frame tab switching: clicking `.tab` elements switches displayed code block | Vue code demo has no tab interaction (static 2 panels) | **interactive** |
+
+---
+---
+
+## 2. LoginView
+
+**Zip:** `docs/design-drafts/v2/Login.html`
+**Vue:** `frontend/src/views/auth/LoginView.vue`
+
+---
+
+### Copy / Text Deltas
+
+| # | Zip (HTML) | Vue (SFC) | Severity | Notes |
+|---|---|---|---|---|
+| LN-T1 | Narrative headline: `N 个订阅 → 1 个 key` (N is amber-colored variable) | Vue: `5 个订阅 → 1 个 key` | **important** | Zip uses abstract "N" (variable quantity); Vue hardcodes "5". This was the specific discrepancy the user noticed |
+| LN-T2 | Narrative kicker: `// 你的订阅,已经付过钱了` | Vue: absent (no kicker element in narrative) | **important** | |
+| LN-T3 | n-sub text: `省去切换账号的繁琐,` / `省去为多个高昂订阅重复买单。` / `PURO(纯粹)—— 让 AI 调用回归本质。` | Vue: `省去切换账号的繁琐,` / `省去为多个高昂订阅重复买单。` / `PURO(纯粹)—— 让 AI 调用回归本质。` (via `auth-narrative-tagline`) | **cosmetic** | Full-width vs half-width punctuation (`,` vs `,`, `()` vs `()`); same meaning otherwise |
+| LN-T4 | Form title: `登录` (h1) + sub: `用你的 PURO AI 账户继续` | Vue: `{{ t('auth.puroLoginTitle') }}` + `{{ t('auth.puroLoginSub') }}` — actual rendered text depends on i18n key values | **important** | Need to verify i18n values match; design source has specific Chinese copy |
+| LN-T5 | "Remember me" checkbox: `记住我` | Vue: absent (no remember-me UI) | **cosmetic** | |
+| LN-T6 | "Forgot password" link: `忘记密码?` (always visible, inline with remember-me) | Vue: only shown `v-if="passwordResetEnabled && !backendModeEnabled"` | **cosmetic** | Conditioned; zip always shows it |
+| LN-T7 | Submit button text: `登录 →` | Vue: i18n key `t('auth.signIn')` / `t('auth.signingIn')` | **cosmetic** | Likely matches; verify arrow `→` is included |
+| LN-T8 | LinuxDO button: `使用 LinuxDO 登录` with custom orange gradient `.linuxdo-ico` "L" badge | Vue: delegated to `` component | **cosmetic** | Functionally equivalent; visual parity depends on component implementation |
+| LN-T9 | Footer link: `没有账户?注册 ` | Vue: i18n `t('auth.dontHaveAccount')` + `t('auth.signUp')` | **cosmetic** | Verify i18n values |
+| LN-T10 | Legal line: `登录即表示你同意 服务条款 与 隐私政策 ` | Vue: **absent** | **important** | No terms/privacy consent text in Vue login form |
+
+---
+
+### Structure Deltas
+
+| # | What zip has | Vue status | Severity |
+|---|---|---|
+| LN-S1 | `route-demo` block: live routing demo panel showing `POST /v1/chat/completions`, `model: claude-sonnet-4-5`, `route → claude-pool-03`, `status 200 · 213ms · 42 tok` | Vue: **entirely absent** | **important** |
+| LN-S2 | `n-bottom` bar: provider list (`Claude · ChatGPT · Codex · Gemini`) + `live · ai.puro.im · operational` green-dot status | Vue: replaced by simpler `auth-narrative-foot` = `Claude · ChatGPT · Codex · Gemini` only; no live status | **important** |
+| LN-S3 | `back-home` link (`← 返回首页`) absolute-positioned top-right of form panel | Vue: absent | **cosmetic** |
+| LN-S4 | Password field: eye toggle with two SVG states (open / closed-with-slash), both embedded inline | Vue: `` / `` (component-based) | **cosmetic** — functionally equivalent |
+| LN-S5 | `remember-me` checkbox with custom styled box + check mark | Vue: absent | **cosmetic** |
+| LN-S6 | Login form `autocomplete="off" novalidate` attribute | Vue: `autocomplete` per-field, no `novalidate` (uses Vue validation) | **cosmetic** |
+
+---
+
+### Visuals / SVG
+
+| # | Delta | Severity |
+|---|---|---|
+| LN-V1 | Brand in narrative: inline SVG hexagon (same double-path as Landing) | Vue: `⬢` emoji | **important** |
+| LN-V2 | `route-demo` styling: pill-inline badges with cyan/amber/green border-tinted backgrounds, green dot-pulse status | Vue: absent (whole block missing) | n/a (structure missing) |
+| LN-V3 | `n-bottom .live .dot` — 5px green dot with `box-shadow` glow | Vue: absent | **important** |
+| LN-V4 | Narrative background: `narrative::before` pseudo with dual radial-gradient overlay (cyan + purple) | Vue: handled by `AuthLayout` — parity depends on that component | unknown — needs AuthLayout check |
+
+---
+
+### Missing CSS (zip has, Vue scoped missing)
+
+| # | Missing rule | Impact |
+|---|---|---|
+| LN-C1 | `.route-demo` and all its `.row`, `.k`, `.v`, `.pill-inline` variants | Route demo panel |
+| LN-C2 | `.n-bottom` and `.n-bottom .live`, `.n-bottom .sep` | Bottom status bar |
+| LN-C3 | `.n-kicker` | Kicker line above headline |
+| LN-C4 | `.check` custom checkbox (`.box`, `:checked ~ .box::after`) | Remember-me checkbox |
+| LN-C5 | `.legal` legal notice line (monospace, dashed link underlines) | Terms/privacy link |
+| LN-C6 | `.back-home` | Return-to-home link |
+| LN-C7 | `@media (max-width: 900px)` hides `.route-demo` and `.n-bottom` | Responsive rule |
+
+---
+
+### Missing Scripts / Interactivity
+
+| # | Zip has | Vue status | Severity |
+|---|---|---|
+| LN-I1 | Password eye-toggle: vanilla JS swaps `pw.type` + toggles two SVG icons by `display` | Vue: reactive `showPassword` ref + Icon component. Functionally equivalent | **none** — Vue solution is better |
+| LN-I2 | Login submit: loading spinner class, success state (`✓ 登录成功` label text change + green background), redirect to Dashboard.html | Vue: `isLoading` spinner, redirect via `router.push('/dashboard')`; no "✓ 登录成功" button text mutation | **cosmetic** — success toast used instead |
+| LN-I3 | Basic non-empty check only (`if (!form.email.value || !form.password.value)`) | Vue: full regex email validation + min-length password validation + Turnstile + 2FA flow | **none** — Vue is more complete |
+
+---
+---
+
+## 3. RegisterView
+
+**Zip:** `docs/design-drafts/v2/Register.html`
+**Vue:** `frontend/src/views/auth/RegisterView.vue`
+
+---
+
+### Copy / Text Deltas
+
+| # | Zip (HTML) | Vue (SFC) | Severity | Notes |
+|---|---|---|---|---|
+| R-T1 | Narrative kicker: `// 5 分钟开始用` | Vue: absent (no kicker) | **important** | |
+| R-T2 | Narrative headline: `N 个订阅 → 1 个 key` | Vue: `5 个订阅 → 1 个 key` | **important** | Same as Login: "N" vs hardcoded "5" |
+| R-T3 | Form title: `创建账户` (h1) + sub: `注册即送 $5 测试积分` | Vue: `{{ t('auth.puroRegisterTitle') }}` + `{{ t('auth.puroRegisterSub') }}` | **important** | The "$5 bonus credit" hook in the sub-title is a key conversion element; Vue moves it to i18n |
+| R-T4 | Password placeholder: `至少 8 位,含字母与数字` | Vue: `{{ t('auth.createPasswordPlaceholder') }}` | **cosmetic** | Verify i18n value matches |
+| R-T5 | `bonus-note` block: green-bordered callout `+$5 完成注册即送 $5 测试积分 —— 够你跑几万次 Claude 请求。` | Vue: **absent** | **important** | High-conversion element entirely missing |
+| R-T6 | Steps panel title: `// 下一步` with 3 numbered onboarding steps (创建账户 → 绑定订阅 → 生成 key) | Vue: **absent** | **important** | The onboarding journey explainer is missing |
+| R-T7 | `n-bottom` provider list + `live · ai.puro.im · operational` | Vue: `auth-narrative-foot` = `Claude · ChatGPT · Codex · Gemini` only | **important** | Live status indicator missing |
+| R-T8 | `back-home` link: `← 返回首页` | Vue: absent | **cosmetic** | |
+| R-T9 | Footer: `已有账户?登录 ` | Vue: i18n `t('auth.alreadyHaveAccount')` + `t('auth.signIn')` | **cosmetic** | Verify i18n values |
+
+---
+
+### Structure Deltas
+
+| # | What zip has | Vue status | Severity |
+|---|---|---|
+| R-S1 | Onboarding `.steps` panel (3-step card in the narrative: 1. Create account, 2. Bind subscription, 3. Generate key) | Vue: **entirely absent** | **important** |
+| R-S2 | Email field: inline validation green checkmark (`valid-ico` SVG) appears when email format is valid | Vue: shows `input-error-text` below field on error; no inline success icon on valid state during typing | **cosmetic** |
+| R-S3 | Password field: 4-bar strength meter (`pw-strength` div) + text label (`// strength · 弱/中/强/极强`) | Vue: no strength meter; only a static `input-hint` paragraph | **important** |
+| R-S4 | Confirm-password field with: `valid-ico` checkmark + `match-hint` (`// matched` / `// passwords do not match`) | Vue: no confirm-password field at all | **important** |
+| R-S5 | Terms checkbox (`我已阅读并同意 服务条款 与 隐私政策`) — submit button disabled until checked | Vue: no terms checkbox | **important** |
+| R-S6 | `bonus-note` callout block | Vue: absent | **important** |
+| R-S7 | Password confirm field activates submit only when: email valid + score ≥ 2 + passwords match + terms checked | Vue: password min-length 6, no confirm field, no terms gate | **important** |
+| R-S8 | Vue-only: invitation code field (conditional on `invitationCodeEnabled`) | Zip: absent | n/a (Vue enhancement) |
+| R-S9 | Vue-only: promo code field (conditional on `promoCodeEnabled`) | Zip: absent | n/a (Vue enhancement) |
+| R-S10 | Vue-only: Turnstile CAPTCHA widget | Zip: absent | n/a (Vue enhancement) |
+
+---
+
+### Visuals / SVG
+
+| # | Delta | Severity |
+|---|---|---|
+| R-V1 | Brand in narrative: inline SVG hexagon | Vue: `⬢` emoji | **important** |
+| R-V2 | Steps panel: numbered circles (`step-num`) with cyan border and active fill | Vue: absent | **important** |
+| R-V3 | `bonus-note` callout: green border `rgba(52,211,153,0.2)` + `+$5` chip in green background | Vue: absent | **important** |
+| R-V4 | Password strength bars: 4 `` elements that fill red/amber/cyan/green based on `data-score` | Vue: absent | **important** |
+| R-V5 | Match-hint monospace text (`// matched` in green / `// passwords do not match` in red) | Vue: absent | **important** |
+| R-V6 | `valid-ico` green SVG checkmark inside input-wrap when field is valid | Vue: absent | **cosmetic** |
+
+---
+
+### Missing CSS (zip has, Vue scoped missing)
+
+| # | Missing rule | Impact |
+|---|---|---|
+| R-C1 | `.steps`, `.steps-title`, `.step`, `.step-num`, `.step.active .step-num`, `.step-text .k` | Onboarding steps panel |
+| R-C2 | `.pw-strength[data-score]` + `.bar` + 4 score-tinted variants | Password strength meter |
+| R-C3 | `.pw-hint[data-score]` + `.val` color variants | Strength label |
+| R-C4 | `.match-hint`, `.match-hint.mismatch`, `.match-hint.ok` | Confirm-password match feedback |
+| R-C5 | `.valid-ico` + `.input-wrap input.ok ~ .valid-ico` | Inline valid checkmark |
+| R-C6 | `.bonus-note` + `.bonus-note .emoji` | Registration bonus callout |
+| R-C7 | `.n-bottom` + live-dot styles (same as Login) | Bottom status bar |
+
+---
+
+### Missing Scripts / Interactivity
+
+| # | Zip has | Vue status | Severity |
+|---|---|---|
+| R-I1 | Password strength scorer (`scorePw()`) — counts: ≥8 chars, mixed case, digit, special/long; maps score 0-4 to `['—','弱','中','强','极强']` | Vue: no strength meter, only min-length check | **interactive** |
+| R-I2 | Real-time confirm-password match checker with `// matched` / `// passwords do not match` feedback | Vue: no confirm-password field | **interactive** |
+| R-I3 | Email inline validation (adds `.ok` class → shows green checkmark) | Vue: error shown on submit, not live | **interactive** |
+| R-I4 | Submit button gated on: email `.ok` + `score >= 2` + passwords match + terms checkbox checked | Vue: submit gated only on loading + optional Turnstile | **interactive** |
+| R-I5 | Success animation: button text changes to `✓ 注册成功,正在跳转...` + green background, then redirects | Vue: toast notification + router.push — no button animation | **cosmetic** |
+
+---
+---
+
+## 4. DocsView
+
+**Zip:** `docs/design-drafts/v2/Docs.html`
+**Vue:** `frontend/src/views/docs/DocsView.vue`
+
+---
+
+### Copy / Text Deltas
+
+| # | Zip (HTML) | Vue (SFC) | Severity | Notes |
+|---|---|---|---|---|
+| D-T1 | Page title / h1: `快速开始` + lede: `PURO AI 提供一个统一的 OpenAI 兼容端点 —— 你已有的 SDK 代码只需要改 base_url 和 api_key 两行…整个过程通常不超过 5 分钟。` | Vue h1: `快速接入 PURO AI` + subtitle: `三步走:拿 key → 配 base_url → 发请求` | **important** | Zip's lede is a full paragraph explaining the product value and 5-minute setup claim; Vue's subtitle is a terse 3-step summary. Different framing. |
+| D-T2 | Step-card labels: `STEP 01 / 绑定订阅`, `STEP 02 / 创建 API Key`, `STEP 03 / 切换 base_url` with description paragraphs | Vue: no step-card grid at all | **important** | The `quick-grid` 3-card visual summary is entirely absent from Vue |
+| D-T3 | Section "① 绑定你的订阅": full paragraph about Dashboard → OAuth flow + KMS callout `凭证通过 AES-256 加密存储在隔离的 KMS 中…` | Vue: Section "1. 获取 API key": `当前 PURO AI 不开放自助注册付费。联系管理员获取:admin@puro.im` + note `未来通过 iShare 入口开放订阅购买。` | **important** | Completely different content: zip describes the self-serve OAuth flow; Vue describes an invite-only alpha state. Vue reflects current operational reality; zip is the target product state. |
+| D-T4 | Section "② 创建 API Key": instructions for `Dashboard → API Keys → 创建 Key`, advice to create per-client keys for safe revocation | Vue: no dedicated "create API key" section | **important** | Zip's key-management guidance (per-client keys, revoke without affecting others) is absent from Vue |
+| D-T5 | Section "③ 发送第一个请求": prose introducing OpenAI + Anthropic format support, code-panel with Python/Node/cURL/Anthropic SDK tabs | Vue: "2. Codex CLI 接入", "3. Claude Code 接入", "4. curl 直连测试" — three separate sections each with a plain `` block | **important** | Zip organises code samples under one tabbed panel; Vue splits them into three separate sections with different tool focus (Codex CLI is a Vue-only section) |
+| D-T6 | Codex CLI section: **absent from zip** | Vue: Section "2. Codex CLI 接入" with `~/.codex/config.toml` and `~/.codex/auth.json` config samples | n/a (Vue enhancement) | Vue-only section targeting Codex CLI users; not in zip |
+| D-T7 | Models table: `claude-sonnet-4-5`, `claude-opus-4`, `claude-haiku-4-5`, `gpt-5`, `gpt-5-codex`, `gemini-2.5-pro`, `gemini-2.5-flash` with PROVIDER / 池 / 上下文 / 状态 columns | Vue model-list: `gpt-5.4`, `gpt-5.4-codex`, `claude-opus-4-7`, `claude-sonnet-4-6`, `gemini-2.5-pro`, `gemini-2.5-flash` (plain `