feat(site): 新增赞助商独立页;顺带修掉三处一直坏着的链接 / 布局

官网此前一条赞助商内容都没有。这一版把赞助内容全部收敛到独立页
/sponsors(中 / EN / 繁三语各一份),首页不放任何赞助位,入口进导航栏。

赞助商页结构:Hero → 旗舰位 → 当前赞助商 → 专属福利汇总 → FAQ →
赞助权益 → CTA。

- 分档由数据驱动:SPONSORS 里 tier: 'flagship' 的用大 banner 单独成块
  (读 img),其余是紧凑卡(读 logo,简介 CSS 截 4 行);当前无 flagship,
  该区块渲染成「虚位以待」招商卡
- 紧凑卡的简介可展开:JS 比对 scrollHeight/clientHeight,只有真被截断
  时才显示「展开全部」,避免出现点了没反应的死按钮
- 福利汇总表里的优惠码点一下即复制,复用站内已有的 copy 委托,未新增
  第三方依赖
- Hero 原文案写「不做付费墙也不接广告」,但赞助位本身就是付费展示位,
  自相矛盾。改为如实说明;外链一律 rel="sponsored nofollow noopener"

顺带修掉三处做入口时发现的老问题(都是线上正在坏的):

- 每个 skill 详情页的「← 返回全部 Skill」是 404:链接写的 index.html,
  从 /skills/xxx 解析成 /skills/index.html —— 该文件不存在。实测线上
  同样 404。60 个详情页全中,已改 ../index.html
- EN / 繁體页面的导航与品牌链接全部跳回中文首页:base 原本按「相对站点
  根」算,/en/index.html 的导航是 ../index.html。已改为相对当前语言根
- 导航栏在 900px 以下挤成两三行(「支持工具」被竖排拆开):原来跟着
  720px 断点走,721–900px 这段一直是坏的。现改为导航项永不折行 + 独立
  900px 断点 + 窄屏横向滚动

赞助商图标取自 ao.aiolaola.com(同一维护者的站、同一批赞助商)。
This commit is contained in:
AI不止语
2026-08-18 18:56:03 +08:00
parent 747cfa4a0d
commit ae316d87f3
6 changed files with 507 additions and 17 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -5,7 +5,7 @@
## 构建 / 预览
```bash
node site/build.mjs # 生成 site/dist/42 个页面)
node site/build.mjs # 生成 site/dist/66 个页面)
npx serve site/dist # 本地预览(或 python3 -m http.server
```
@@ -14,6 +14,7 @@ npx serve site/dist # 本地预览(或 python3 -m http.server
```
dist/
index.html # 中文首页
sponsors.html # 中文赞助商页(每种语言一份)
en/index.html # 英文首页
skills/<name>.html # 中文 skill 详情(操作文档)× 20
en/skills/<name>.html # 英文 skill 详情 × 20
@@ -37,6 +38,9 @@ dist/
| Skill 中/英标题、英文简介、分组 | `site/build.mjs``SKILL_META` |
| 首页所有文案(中/英) | `site/build.mjs``T.zh` / `T.en` |
| 支持工具 / 安装命令 | `site/build.mjs``TOOLS`(与 `bin/superpowers-zh.js``TARGETS` 对齐) |
| 赞助商logo / banner / 文案 / 链接 / 优惠码) | `site/build.mjs``SPONSORS``logo` 小图标 + `img` 大 banner 都放 `assets/sponsors/`,构建时自动拷进 `dist/assets/sponsors/`)——首页不放赞助内容,全部在 `sponsors.html`。**改完同步改 README.md / README.zh-Hant.md 的赞助商区块** |
| 赞助商页文案 / 赞助权益 / 赞助 FAQ | `site/build.mjs``T.<lang>.sp` |
| 谁上旗舰位 | `SPONSORS` 里该条的 `tier``'flagship'` 用大 banner 单独成块(读 `img`),其余是紧凑卡(读 `logo`,简介截 4 行);没有 flagship 时该区块渲染成「虚位以待」招商卡 |
| 样式 / 主题 | `site/template/styles.css` |
| 交互逻辑 | `site/template/app.js` |
| Markdown 渲染规则 | `site/md.mjs` |

View File

@@ -105,12 +105,73 @@ const TOOLS = [
];
// ---- 双语文案 ----
// ---- 赞助商(与 README / README.zh-Hant 的赞助商区块同源;改这里也要同步改 README ----
// 注意:链接是赞助方的推广链接,外链一律带 rel="sponsored nofollow noopener"。
const SPONSORS = [
{
tier: 'standard',
img: 'compshare.jpg', w: 800, h: 368, code: '',
logo: 'logo-compshare-icon.png',
url: 'https://passport.compshare.cn/register?referral_code=ETD3L5JBM13CtKARkMORot&ytag=GPU_YY_YX_git_superpowers-zh',
name: { zh: '优云智算', en: 'CompShare by UCloud', zht: '優雲智算' },
tagline: {
zh: 'UCloud 旗下 AI 云平台 · 国产模型 Agent Plan 套餐低至 49 元/月',
en: 'UCloud\u2019s AI cloud · Agent Plans for Chinese models from ¥49/month',
zht: 'UCloud 旗下 AI 雲平台 · 國產模型 Agent Plan 套餐低至 49 元/月',
},
alt: {
zh: '优云智算 by UCloud — 热门国产模型按次调用套餐包,低至 49 元/月起',
en: 'CompShare by UCloud — pay-per-call plans for popular Chinese models, from ¥49/month',
zht: '優雲智算 by UCloud — 熱門國產模型按次調用套餐包,低至 49 元/月起',
},
desc: {
zh: 'UCloud 旗下 AI 云平台,主打包月 / 按次的高性价比国模 Agent Plan 套餐,支持 GLM-5.2,低至 49 元/月起。同时提供官转稳定海外模型,支持接入 Claude Code、Codex 及 API 调用企业高并发、7×24 技术支持、自助开票。',
en: 'UCloud\u2019s AI cloud platform. Cost-effective monthly / pay-per-call Agent Plans for Chinese models (incl. GLM-5.2) from ¥49/month, plus stable access to overseas models. Works with Claude Code, Codex and direct API calls; enterprise concurrency, 24/7 support, self-service invoicing.',
zht: 'UCloud 旗下 AI 雲平台,主打包月 / 按次的高性價比國模 Agent Plan 套餐,支援 GLM-5.2,低至 49 元/月起。同時提供官轉穩定海外模型,支援接入 Claude Code、Codex 及 API 呼叫企業高併發、7×24 技術支援、自助開票。',
},
perk: {
zh: '🎁 通过本页链接注册,可得免费 5 元平台体验金',
en: '🎁 Sign up via this link to get ¥5 free platform credit',
zht: '🎁 透過本頁連結註冊,可得免費 5 元平台體驗金',
},
perkShort: { zh: '新用户注册立得 5 元平台体验金', en: '¥5 free platform credit on sign-up', zht: '新使用者註冊立得 5 元平台體驗金' },
},
{
tier: 'standard',
img: 'cubence.jpg', w: 800, h: 333, code: 'AGENCY',
logo: 'logo-cubence-icon.png',
url: 'https://cubence.com/signup?code=SCW29JP9',
name: { zh: 'Cubence', en: 'Cubence', zht: 'Cubence' },
tagline: {
zh: '专业 AI API 网关 · 支持 Claude Code / Codex / Gemini',
en: 'AI API gateway · Claude Code / Codex / Gemini',
zht: '專業 AI API 閘道 · 支援 Claude Code / Codex / Gemini',
},
alt: {
zh: 'Cubence — 专业 AI API 网关,稳定高效的 API 中转服务,支持 Claude Code、Codex、Gemini 等多种模型',
en: 'Cubence — AI API gateway with stable relay service for Claude Code, Codex, Gemini and more',
zht: 'Cubence — 專業 AI API 閘道,穩定高效的 API 中轉服務,支援 Claude Code、Codex、Gemini 等多種模型',
},
desc: {
zh: '专业 AI API 网关,致力于提供稳定、高效的 API 中转服务。自 2025 年 9 月运营至今,支持 Claude Code、Codex、Gemini 等多种模型。',
en: 'A professional AI API gateway focused on stable, efficient relay service. Running since September 2025, with support for Claude Code, Codex, Gemini and more.',
zht: '專業 AI API 閘道,致力於提供穩定、高效的 API 中轉服務。自 2025 年 9 月營運至今,支援 Claude Code、Codex、Gemini 等多種模型。',
},
perk: {
zh: '🎁 本项目用户专属优惠码 AGENCY通过本页链接注册首次购买 9 折',
en: '🎁 Code AGENCY for this project\u2019s users — 10% off your first purchase via this link',
zht: '🎁 本專案使用者專屬優惠碼 AGENCY透過本頁連結註冊首次購買 9 折',
},
perkShort: { zh: '首次购买 9 折优惠', en: '10% off your first purchase', zht: '首次購買 9 折優惠' },
},
];
const T = {
zh: {
htmlLang: 'zh-CN',
title: 'superpowers-zh · AI 编程超能力中文增强版',
desc: 'superpowers250k+ ⭐)完整汉化 + 4 个中国原创 skills一条 npx 命令为 23 款 AI 编程工具装上系统化工作方法论。',
nav: { why: '特性', install: '安装', skills: 'Skills', tools: '支持工具', faq: 'FAQ', learn: '学习 ↗', github: 'GitHub ↗' },
nav: { why: '特性', install: '安装', skills: 'Skills', tools: '支持工具', faq: 'FAQ', sponsors: '赞助商', learn: '学习 ↗', github: 'GitHub ↗' },
heroBadge: 'superpowers 250k+ ⭐ · 完整汉化 + 中国原创',
heroH1: '给你的 AI 编程工具<br>装上<span class="grad">真正会干活</span>的超能力',
heroLead: '{n} 个经过实战验证的工作方法论 skill —— 从头脑风暴到 TDD从系统化调试到代码审查。<br>一条命令,自动识别项目里的工具并安装。',
@@ -138,6 +199,53 @@ const T = {
ucTitle: '典型使用场景', ucSub: '每个场景背后都是一组协同工作的 skill。',
toolsTitle: '一套 skill23 款工具通用', toolsSub: '换工具不用换习惯,方法论跟着你走。',
faqTitle: '常见问题',
sponsorCta: '了解详情 ↗',
sponsorNote: '以上为赞助商推广链接。',
sp: {
nav: '赞助商',
title: '赞助商 · superpowers-zh',
desc: 'superpowers-zh 免费开源、零依赖,由社区赞助商共同支持。本页列出全部赞助商及其为本项目用户提供的专属福利。',
badge: '开源 · 社区支持',
h1: '感谢每一位支持者',
lead: 'superpowers-zh 是一个面向中文开发者的开源项目 —— 永久免费、MIT 协议、零依赖,不设付费墙。它由社区与赞助商共同支撑:本页的赞助位是付费展示位,也正是它们让项目能持续维护下去。我们把每一份支持,都视作让项目走得更远的力量。',
becomeBtn: '♡ 成为赞助商',
backBtn: '← 返回首页',
expand: '展开全部 ',
collapse: '收起 ∧',
emptyTitle: '旗舰位虚位以待',
emptyDesc: '本页顶部整块大图展位 + 专属行动按钮,同时在两版 README 顶部优先展示。长期合作可谈,邮件聊聊。',
emptyBtn: '申请旗舰位 →',
flagTitle: '旗舰赞助商',
flagSub: '深度合作伙伴,长期为项目提供关键支持。旗舰位虚位以待,欢迎申请。',
moreTitle: '更多赞助商',
moreSub: '感谢这些持续支持本项目、并为用户提供专属优惠的赞助商。',
visitFlag: '使用专属优惠访问 →',
copyHint: '点击优惠码一键复制。',
faqTitle: '常见问题',
faq: [
{ q: '如何成为 superpowers-zh 的赞助商?', a: '邮件联系 jnMetaCode@qq.com说明你的产品、目标人群和想要的展位形式。我们会回复可选方案、素材要求和上线时间。' },
{ q: '有哪些合作方案?', a: '分旗舰位与常规位两档:旗舰位在本页顶部单独成块展示,常规位在「更多赞助商」卡片区。两档都含 GitHub 简繁双版 README 展位与官网三语站点露出。具体以邮件沟通为准。' },
{ q: '谈完多久可以上线?', a: '素材齐全后改动会随下一次站点构建发布 —— 本站接的是仓库自动部署,推送即上线,通常当天可见。' },
{ q: '需要准备哪些素材?', a: '一张横版 banner参考现有赞助位约 800×368JPG / PNG、一句话定位、一段 100 字左右的介绍、落地链接,以及给本项目用户的专属优惠码或福利(可选)。' },
],
listTitle: '当前赞助商',
listSub: '感谢他们持续支持本项目,并为本项目用户提供专属福利。',
perkTitle: '专属福利汇总',
perkSub: '通过本页链接注册即可享受下列福利。',
thSponsor: '赞助商', thPerk: '专属福利', thCode: '优惠码', thGo: '前往',
goto: '前往 ↗', noCode: '—',
benefitTitle: '成为赞助商可以获得什么',
benefitSub: '面向 AI 编程开发者的精准展位 —— GitHub + 官网双通道曝光。',
benefits: [
{ icon: '📖', t: 'GitHub README 展位', d: '在简体 / 繁体两版 README 顶部展示 banner + 介绍文案,覆盖 GitHub 上的全部访客。' },
{ icon: '🌐', t: '官网赞助商页展示', d: '官网赞助商页展示,导航栏常驻入口,中文 / EN / 繁體三语站点全部覆盖。' },
{ icon: '🎯', t: '精准开发者受众', d: '本项目用户是正在用 Claude Code / Cursor / Codex 等 23 款 AI 编程工具的开发者 —— 模型与 API 服务的直接买家。' },
{ icon: '🎁', t: '专属优惠码展示', d: '你的专属优惠码 / 福利会在赞助商页的「福利汇总」表里单独列出,方便用户直接使用。' },
],
ctaTitle: '想出现在这里?',
ctaDesc: '欢迎邮件联系,我们会把展位形式、素材要求和上线时间一次说清。',
ctaBtn: '✉ jnMetaCode@qq.com',
},
bookTitle: '装好之后,配上方法论效率翻倍',
bookDesc: '《AI 编程实战 · 方法论三卷书》—— 10 个 AI 编程工具完整教程 + 真实踩坑。在线书 + PDF永久免费。',
bookBtn: '免费阅读 ↗',
@@ -146,7 +254,7 @@ const T = {
ctaDesc: '一条命令,{n} 个实战方法论装进你的工具。免费、开源、零依赖。',
ctaBtn1: '查看安装命令', ctaBtn2: '⭐ Star on GitHub',
footCols: [
{ h: '产品', links: [['特性', '#why'], ['Skills', '#skills'], ['支持工具', '#tools'], ['FAQ', '#faq']] },
{ h: '产品', links: [['特性', '#why'], ['Skills', '#skills'], ['支持工具', '#tools'], ['FAQ', '#faq'], ['赞助商', 'sponsors.html']] },
{ h: '资源', links: [['GitHub', 'https://github.com/jnMetaCode/superpowers-zh'], ['npm', 'https://www.npmjs.com/package/superpowers-zh'], ['方法论三卷书', 'https://book.aibuzhiyu.com/']] },
{ h: '生态', links: [['aiOlaOla · 从零学会 AI 编程', 'https://aiolaola.com/?utm_source=sp1'], ['X / Twitter', 'https://x.com/jnMetaCode'], ['公众号 AI不止语', 'https://aiolaola.com/'], ['姐妹项目', 'https://github.com/jnMetaCode']] },
{ h: '社区', links: [['提交 Issue', 'https://github.com/jnMetaCode/superpowers-zh/issues'], ['贡献指南', 'https://github.com/jnMetaCode/superpowers-zh/blob/main/CLAUDE.md'], ['联系邮箱', 'mailto:jnMetaCode@qq.com']] },
@@ -194,7 +302,7 @@ const T = {
htmlLang: 'en',
title: 'superpowers-zh · Battle-tested AI coding skills (CN-enhanced)',
desc: 'Full Chinese localization of superpowers (250k+ ⭐) plus 4 China-native skills. One npx command installs systematic workflow methodology into 23 AI coding tools.',
nav: { why: 'Features', install: 'Install', skills: 'Skills', tools: 'Tools', faq: 'FAQ', learn: 'Learn ↗', github: 'GitHub ↗' },
nav: { why: 'Features', install: 'Install', skills: 'Skills', tools: 'Tools', faq: 'FAQ', sponsors: 'Sponsors', learn: 'Learn ↗', github: 'GitHub ↗' },
heroBadge: 'superpowers 250k+ ⭐ · Full CN localization + China-native skills',
heroH1: 'Give your AI coding tools<br>superpowers that <span class="grad">actually ship</span>',
heroLead: '{n} battle-tested workflow skills — from brainstorming to TDD, systematic debugging to code review.<br>One command auto-detects your tool and installs.',
@@ -222,6 +330,53 @@ const T = {
ucTitle: 'Typical use cases', ucSub: 'Each scenario is backed by a set of cooperating skills.',
toolsTitle: 'One skill set, 23 tools', toolsSub: 'Switch tools without switching habits — the methodology follows you.',
faqTitle: 'FAQ',
sponsorCta: 'Learn more ↗',
sponsorNote: 'Links above are sponsored links.',
sp: {
nav: 'Sponsors',
title: 'Sponsors · superpowers-zh',
desc: 'superpowers-zh is free, open source and dependency-free, supported by community sponsors. This page lists every sponsor and the perks they offer to users of this project.',
badge: 'Open source · Community backed',
h1: 'Thanks to everyone who backs this project',
lead: 'superpowers-zh is an open source project for Chinese-speaking developers — free forever, MIT licensed, dependency-free, no paywall. It is kept going by its community and its sponsors: the slots on this page are paid placements, and they are what makes continued maintenance possible. Every bit of support takes the project further.',
becomeBtn: '♡ Become a sponsor',
backBtn: '← Back to home',
expand: 'Read more ',
collapse: 'Show less ∧',
emptyTitle: 'The flagship slot is open',
emptyDesc: 'A full-width banner block at the top of this page with its own call-to-action button, plus priority placement at the top of both READMEs. Long-term partnerships welcome — drop us an email.',
emptyBtn: 'Apply for the flagship slot →',
flagTitle: 'Flagship sponsor',
flagSub: 'A long-term partner backing this project. The flagship slot is open — get in touch.',
moreTitle: 'More sponsors',
moreSub: 'Thanks to everyone backing this project and offering perks to its users.',
visitFlag: 'Claim the offer →',
copyHint: 'Click a code to copy it.',
faqTitle: 'FAQ',
faq: [
{ q: 'How do I become a sponsor?', a: 'Email jnMetaCode@qq.com with your product, target audience and the placement you have in mind. We will reply with options, asset specs and timing.' },
{ q: 'What tiers are there?', a: 'Two: flagship, which gets its own block at the top of this page, and standard, which appears in the sponsor card grid. Both include placement in the Simplified and Traditional Chinese READMEs on GitHub and across all three site locales. Exact terms are settled over email.' },
{ q: 'How soon does it go live?', a: 'Once assets are in, the change ships with the next site build — the site deploys straight from the repo, so it is usually live the same day.' },
{ q: 'What assets do you need?', a: 'A landscape banner (existing slots are around 800×368, JPG / PNG), a one-line positioning statement, a short paragraph of copy, a landing URL, and optionally a promo code or perk for this project\u2019s users.' },
],
listTitle: 'Current sponsors',
listSub: 'Thanks for backing this project — and for the perks they offer to its users.',
perkTitle: 'All perks at a glance',
perkSub: 'Sign up through the links on this page to claim them.',
thSponsor: 'Sponsor', thPerk: 'Perk', thCode: 'Code', thGo: 'Go',
goto: 'Visit ↗', noCode: '—',
benefitTitle: 'What sponsors get',
benefitSub: 'A focused placement in front of AI-coding developers — on GitHub and on the site.',
benefits: [
{ icon: '📖', t: 'GitHub README placement', d: 'Banner plus copy at the top of both the Simplified and Traditional Chinese READMEs, seen by every GitHub visitor.' },
{ icon: '🌐', t: 'Website placement', d: 'Listed on the sponsors page, reachable from the main nav on every page, across all three locales (CN / EN / TW).' },
{ icon: '🎯', t: 'A developer audience', d: 'Our users are developers running Claude Code, Cursor, Codex and 20 other AI coding tools — direct buyers of model and API services.' },
{ icon: '🎁', t: 'Your promo code, listed', d: 'Your code or offer gets its own row in the perks table on this page, ready for users to copy.' },
],
ctaTitle: 'Want your logo here?',
ctaDesc: 'Drop us an email and we will walk you through placements, assets and timing in one go.',
ctaBtn: '✉ jnMetaCode@qq.com',
},
bookTitle: 'Pair it with the methodology for 2× efficiency',
bookDesc: '"AI Coding in Practice · The Three-Volume Methodology" — full tutorials for 10 AI coding tools plus real-world pitfalls. Online book + PDF, free forever.',
bookBtn: 'Read free ↗',
@@ -230,7 +385,7 @@ const T = {
ctaDesc: 'One command installs {n} battle-tested skills into your tool. Free, open-source, zero-dependency.',
ctaBtn1: 'Get the command', ctaBtn2: '⭐ Star on GitHub',
footCols: [
{ h: 'Product', links: [['Features', '#why'], ['Skills', '#skills'], ['Tools', '#tools'], ['FAQ', '#faq']] },
{ h: 'Product', links: [['Features', '#why'], ['Skills', '#skills'], ['Tools', '#tools'], ['FAQ', '#faq'], ['Sponsors', 'sponsors.html']] },
{ h: 'Resources', links: [['GitHub', 'https://github.com/jnMetaCode/superpowers-zh'], ['npm', 'https://www.npmjs.com/package/superpowers-zh'], ['Methodology book', 'https://book.aibuzhiyu.com/']] },
{ h: 'Ecosystem', links: [['aiOlaOla', 'https://aiolaola.com/?utm_source=sp1'], ['X / Twitter', 'https://x.com/jnMetaCode'], ['Sister projects', 'https://github.com/jnMetaCode']] },
{ h: 'Community', links: [['Open an Issue', 'https://github.com/jnMetaCode/superpowers-zh/issues'], ['Contributing', 'https://github.com/jnMetaCode/superpowers-zh/blob/main/CLAUDE.md'], ['Contact', 'mailto:jnMetaCode@qq.com']] },
@@ -278,7 +433,7 @@ const T = {
htmlLang: 'zh-Hant',
title: 'superpowers-zh · AI 編程超能力中文增強版',
desc: 'superpowers250k+ ⭐)完整漢化 + 4 個中國原創 skills一條 npx 命令為 23 款 AI 編程工具裝上系統化工作方法論。',
nav: { why: '特性', install: '安裝', skills: 'Skills', tools: '支援工具', faq: 'FAQ', learn: '學習 ↗', github: 'GitHub ↗' },
nav: { why: '特性', install: '安裝', skills: 'Skills', tools: '支援工具', faq: 'FAQ', sponsors: '贊助商', learn: '學習 ↗', github: 'GitHub ↗' },
heroBadge: 'superpowers 250k+ ⭐ · 完整漢化 + 中國原創',
heroH1: '給你的 AI 編程工具<br>裝上<span class="grad">真正會幹活</span>的超能力',
heroLead: '{n} 個經過實戰驗證的工作方法論 skill —— 從頭腦風暴到 TDD從系統化除錯到程式碼審查。<br>一條命令,自動識別專案裡的工具並安裝。',
@@ -306,6 +461,53 @@ const T = {
ucTitle: '典型使用場景', ucSub: '每個場景背後都是一組協同工作的 skill。',
toolsTitle: '一套 skill23 款工具通用', toolsSub: '換工具不用換習慣,方法論跟著你走。',
faqTitle: '常見問題',
sponsorCta: '了解詳情 ↗',
sponsorNote: '以上為贊助商推廣連結。',
sp: {
nav: '贊助商',
title: '贊助商 · superpowers-zh',
desc: 'superpowers-zh 免費開源、零依賴,由社群贊助商共同支持。本頁列出全部贊助商及其為本專案使用者提供的專屬福利。',
badge: '開源 · 社群支持',
h1: '感謝每一位支持者',
lead: 'superpowers-zh 是一個面向中文開發者的開源專案 —— 永久免費、MIT 協議、零依賴,不設付費牆。它由社群與贊助商共同支撐:本頁的贊助位是付費展示位,也正是它們讓專案能持續維護下去。我們把每一份支持,都視作讓專案走得更遠的力量。',
becomeBtn: '♡ 成為贊助商',
backBtn: '← 返回首頁',
expand: '展開全部 ',
collapse: '收起 ∧',
emptyTitle: '旗艦位虛位以待',
emptyDesc: '本頁頂部整塊大圖展位 + 專屬行動按鈕,同時在兩版 README 頂部優先展示。長期合作可談,郵件聊聊。',
emptyBtn: '申請旗艦位 →',
flagTitle: '旗艦贊助商',
flagSub: '深度合作夥伴,長期為專案提供關鍵支持。旗艦位虛位以待,歡迎申請。',
moreTitle: '更多贊助商',
moreSub: '感謝這些持續支持本專案、並為使用者提供專屬優惠的贊助商。',
visitFlag: '使用專屬優惠訪問 →',
copyHint: '點選優惠碼一鍵複製。',
faqTitle: '常見問題',
faq: [
{ q: '如何成為 superpowers-zh 的贊助商?', a: '郵件聯絡 jnMetaCode@qq.com說明你的產品、目標人群和想要的展位形式。我們會回覆可選方案、素材要求和上線時間。' },
{ q: '有哪些合作方案?', a: '分旗艦位與常規位兩檔:旗艦位在本頁頂部單獨成塊展示,常規位在「更多贊助商」卡片區。兩檔都含 GitHub 簡繁雙版 README 展位與官網三語站點露出。具體以郵件溝通為準。' },
{ q: '談完多久可以上線?', a: '素材齊全後改動會隨下一次站點構建釋出 —— 本站接的是倉庫自動部署,推送即上線,通常當天可見。' },
{ q: '需要準備哪些素材?', a: '一張橫版 banner參考現有贊助位約 800×368JPG / PNG、一句話定位、一段 100 字左右的介紹、落地連結,以及給本專案使用者的專屬優惠碼或福利(可選)。' },
],
listTitle: '目前贊助商',
listSub: '感謝他們持續支持本專案,並為本專案使用者提供專屬福利。',
perkTitle: '專屬福利彙總',
perkSub: '透過本頁連結註冊即可享受下列福利。',
thSponsor: '贊助商', thPerk: '專屬福利', thCode: '優惠碼', thGo: '前往',
goto: '前往 ↗', noCode: '—',
benefitTitle: '成為贊助商可以獲得什麼',
benefitSub: '面向 AI 編程開發者的精準展位 —— GitHub + 官網雙通道曝光。',
benefits: [
{ icon: '📖', t: 'GitHub README 展位', d: '在簡體 / 繁體兩版 README 頂部展示 banner + 介紹文案,覆蓋 GitHub 上的全部訪客。' },
{ icon: '🌐', t: '官網贊助商頁展示', d: '官網贊助商頁展示,導覽列常駐入口,中文 / EN / 繁體三語站點全部覆蓋。' },
{ icon: '🎯', t: '精準開發者受眾', d: '本專案使用者是正在用 Claude Code / Cursor / Codex 等 23 款 AI 編程工具的開發者 —— 模型與 API 服務的直接買家。' },
{ icon: '🎁', t: '專屬優惠碼展示', d: '你的專屬優惠碼 / 福利會在贊助商頁的「福利彙總」表裡單獨列出,方便使用者直接使用。' },
],
ctaTitle: '想出現在這裡?',
ctaDesc: '歡迎郵件聯絡,我們會把展位形式、素材要求和上線時間一次說清。',
ctaBtn: '✉ jnMetaCode@qq.com',
},
bookTitle: '裝好之後,配上方法論效率翻倍',
bookDesc: '《AI 編程實戰 · 方法論三卷書》—— 10 個 AI 編程工具完整教程 + 真實踩坑。線上書 + PDF永久免費。',
bookBtn: '免費閱讀 ↗',
@@ -314,7 +516,7 @@ const T = {
ctaDesc: '一條命令,{n} 個實戰方法論裝進你的工具。免費、開源、零依賴。',
ctaBtn1: '查看安裝命令', ctaBtn2: '⭐ Star on GitHub',
footCols: [
{ h: '產品', links: [['特性', '#why'], ['Skills', '#skills'], ['支援工具', '#tools'], ['FAQ', '#faq']] },
{ h: '產品', links: [['特性', '#why'], ['Skills', '#skills'], ['支援工具', '#tools'], ['FAQ', '#faq'], ['贊助商', 'sponsors.html']] },
{ h: '資源', links: [['GitHub', 'https://github.com/jnMetaCode/superpowers-zh'], ['npm', 'https://www.npmjs.com/package/superpowers-zh'], ['方法論三卷書', 'https://book.aibuzhiyu.com/']] },
{ h: '生態', links: [['aiOlaOla · 從零學會 AI 編程', 'https://aiolaola.com/?utm_source=sp1'], ['X / Twitter', 'https://x.com/jnMetaCode'], ['公眾號 AI不止語', 'https://aiolaola.com/'], ['姊妹專案', 'https://github.com/jnMetaCode']] },
{ h: '社群', links: [['提交 Issue', 'https://github.com/jnMetaCode/superpowers-zh/issues'], ['貢獻指南', 'https://github.com/jnMetaCode/superpowers-zh/blob/main/CLAUDE.md'], ['聯絡信箱', 'mailto:jnMetaCode@qq.com']] },
@@ -450,6 +652,7 @@ ${extraHead}</head>
<a href="${base}index.html#skills">${t.nav.skills}</a>
<a href="${base}index.html#tools">${t.nav.tools}</a>
<a href="${base}index.html#faq">${t.nav.faq}</a>
<a href="${base}sponsors.html">${t.nav.sponsors}</a>
<a href="https://aiolaola.com/?utm_source=sp1" target="_blank" rel="noopener">${t.nav.learn}</a>
<a href="https://github.com/jnMetaCode/superpowers-zh" target="_blank" rel="noopener">${t.nav.github}</a>
${langSwitch}
@@ -471,7 +674,12 @@ ${body}
<strong>superpowers<b>-zh</b></strong>
<span>${t.footTag}</span>
</div>
${t.footCols.map(col => `<div class="foot-col"><h4>${col.h}</h4>${col.links.map(l => `<a href="${l[1]}"${l[1].startsWith('http') ? ' target="_blank" rel="noopener"' : ''}>${l[0]}</a>`).join('')}</div>`).join('')}
${t.footCols.map(col => `<div class="foot-col"><h4>${col.h}</h4>${col.links.map(l => {
const ext = l[1].startsWith('http');
// 站内相对链接(如 sponsors.html要按当前页面深度补 base'#' 锚点与外链原样
const href = (ext || l[1].startsWith('#') || l[1].startsWith('mailto:')) ? l[1] : base + l[1];
return `<a href="${href}"${ext ? ' target="_blank" rel="noopener"' : ''}>${l[0]}</a>`;
}).join('')}</div>`).join('')}
</div>
<p class="copyright">${t.copyright}</p>
</footer>
@@ -605,6 +813,128 @@ function renderLanding(skills, lang) {
<script>window.__TOOLS__=${toolData};window.__I18N__={auto:${JSON.stringify(t.instNoteAuto)},manual:${JSON.stringify(t.instNoteManual)},copy:${JSON.stringify(t.copy)},copied:${JSON.stringify(t.copied)}};</script>`;
}
// ---- 赞助商独立页 ----
// 首页不放任何赞助内容,全部收敛到这一页:旗舰位 → 常规位 → 福利汇总 → FAQ → 赞助权益。
// tier: 'flagship' 的赞助商单独成块;没有 flagship 时该区块整体不渲染。
function renderSponsors(lang) {
const t = T[lang];
const sp = t.sp;
const flagship = SPONSORS.filter(x => x.tier === 'flagship');
const standard = SPONSORS.filter(x => x.tier !== 'flagship');
const flagCards = flagship.map(s => `
<article class="sponsor sponsor-flag">
<a class="sponsor-shot" href="${esc(s.url)}" target="_blank" rel="sponsored nofollow noopener">
<img src="/assets/sponsors/${s.img}" alt="${esc(s.alt[lang])}" width="${s.w}" height="${s.h}" loading="lazy">
</a>
<div class="flag-body">
<h3>${esc(s.name[lang])}</h3>
<p class="flag-tag">${esc(s.tagline[lang])}</p>
<p class="flag-desc">${esc(s.desc[lang])}</p>
<div class="flag-foot">
<span class="sponsor-perk">${esc(s.perk[lang])}</span>
<a class="btn btn-primary" href="${esc(s.url)}" target="_blank" rel="sponsored nofollow noopener">${esc(sp.visitFlag)}</a>
</div>
</div>
</article>`).join('');
const cards = standard.map(s => `
<article class="sponsor-card">
<a class="sc-head" href="${esc(s.url)}" target="_blank" rel="sponsored nofollow noopener">
<span class="sc-logo"><img src="/assets/sponsors/${s.logo}" alt="" width="36" height="36" loading="lazy"></span>
<b>${esc(s.name[lang])}</b>
<span class="sc-ext" aria-hidden="true">↗</span>
</a>
<p class="sc-desc">${esc(s.desc[lang])}</p>
<button class="sc-toggle" type="button" aria-expanded="false" hidden>${esc(sp.expand)}</button>
<p class="sc-perk">${esc(s.perk[lang])}</p>
<a class="sc-go" href="${esc(s.url)}" target="_blank" rel="sponsored nofollow noopener">${esc(sp.goto)}</a>
</article>`).join('');
const rows = SPONSORS.map(s => `
<tr>
<td><b>${esc(s.name[lang])}</b></td>
<td>${esc(s.perkShort[lang])}</td>
<td>${s.code
? `<span class="code-chip" data-copy="${esc(s.code)}"><code>${esc(s.code)}</code><button class="copy-btn" aria-label="${t.copy}">\u29c9</button></span>`
: sp.noCode}</td>
<td><a href="${esc(s.url)}" target="_blank" rel="sponsored nofollow noopener">${sp.goto}</a></td>
</tr>`).join('');
const faqs = sp.faq.map(f =>
`<details class="faq-item"><summary>${esc(f.q)}</summary><div class="faq-a">${esc(f.a)}</div></details>`).join('');
const benefits = sp.benefits.map(b =>
`<article class="feat"><div class="feat-icon">${b.icon}</div><h3>${esc(b.t)}</h3><p>${esc(b.d)}</p></article>`).join('');
// 没有 flagship 时不留白,改渲染一张「虚位以待」招商卡
const flagSection = `
<section class="sp-tier">
<h2 class="tier-title">${esc(sp.flagTitle)}</h2>
<p class="tier-sub">${esc(sp.flagSub)}</p>
${flagship.length ? flagCards : `
<div class="flag-empty">
<h3>${esc(sp.emptyTitle)}</h3>
<p>${esc(sp.emptyDesc)}</p>
<a class="btn btn-primary" href="mailto:jnMetaCode@qq.com">${esc(sp.emptyBtn)}</a>
</div>`}
</section>
`;
const moreSection = standard.length ? `
<section class="sp-tier">
<h2 class="tier-title">${esc(flagship.length ? sp.moreTitle : sp.listTitle)}</h2>
<p class="tier-sub">${esc(flagship.length ? sp.moreSub : sp.listSub)}</p>
<div class="sponsor-cards">${cards}</div>
</section>
` : '';
return `
<main id="top">
<section class="hero sp-hero">
<div class="badge">${sp.badge}</div>
<h1>${esc(sp.h1)}</h1>
<p class="lead">${esc(sp.lead)}</p>
<div class="hero-cta">
<a class="btn btn-primary" href="mailto:jnMetaCode@qq.com">${esc(sp.becomeBtn)}</a>
<a class="btn btn-ghost" href="index.html">${esc(sp.backBtn)}</a>
</div>
</section>
${flagSection}${moreSection}
<section class="sp-perks">
<h2 class="section-title">${esc(sp.perkTitle)}</h2>
<p class="section-sub">${esc(sp.perkSub)}${sp.copyHint ? ' ' + esc(sp.copyHint) : ''}</p>
<div class="sp-table-wrap">
<table class="sp-table">
<thead><tr><th>${esc(sp.thSponsor)}</th><th>${esc(sp.thPerk)}</th><th>${esc(sp.thCode)}</th><th>${esc(sp.thGo)}</th></tr></thead>
<tbody>${rows}</tbody>
</table>
</div>
<p class="sponsor-note">${t.sponsorNote}</p>
</section>
<section class="faq">
<h2 class="section-title">${esc(sp.faqTitle)}</h2>
<div class="faq-list">${faqs}</div>
</section>
<section class="why sp-benefits">
<h2 class="section-title">${esc(sp.benefitTitle)}</h2>
<p class="section-sub">${esc(sp.benefitSub)}</p>
<div class="feat-grid">${benefits}</div>
</section>
<section class="cta"><div class="cta-inner">
<h2>${esc(sp.ctaTitle)}</h2><p>${esc(sp.ctaDesc)}</p>
<div class="hero-cta">
<a class="btn btn-primary" href="mailto:jnMetaCode@qq.com">${esc(sp.ctaBtn)}</a>
<a class="btn btn-ghost" href="index.html">${esc(sp.backBtn)}</a>
</div>
</div></section>
</main>
<script>window.__I18N__={copy:${JSON.stringify(t.copy)},copied:${JSON.stringify(t.copied)},expand:${JSON.stringify(sp.expand)},collapse:${JSON.stringify(sp.collapse)}};</script>`;
}
// ---- skill 详情(操作文档)页正文 ----
function renderDetail(skill, lang) {
const t = T[lang];
@@ -616,7 +946,7 @@ function renderDetail(skill, lang) {
const srcUrl = `https://github.com/jnMetaCode/superpowers-zh/blob/main/skills/${skill.name}/SKILL.md`;
return `
<main class="doc">
<a class="doc-back" href="index.html#skills">${t.backToSkills}</a>
<a class="doc-back" href="../index.html#skills">${t.backToSkills}</a>
<header class="doc-head">
<div class="doc-titles">
<h1>${esc(title)}</h1>
@@ -631,7 +961,7 @@ function renderDetail(skill, lang) {
</header>
${cnNotice}
<article class="doc-body">${bodyHtml}</article>
<a class="doc-back" href="index.html#skills">${t.backToSkills}</a>
<a class="doc-back" href="../index.html#skills">${t.backToSkills}</a>
</main>
<script>window.__I18N__={copy:${JSON.stringify(t.copy)},copied:${JSON.stringify(t.copied)}};</script>`;
}
@@ -652,24 +982,37 @@ function build() {
copyFileSync(join(TEMPLATE, 'assets', 'qr-wechat.jpg'), join(DIST, 'assets', 'qr-wechat.jpg'));
copyFileSync(join(TEMPLATE, 'assets', 'qr-douyin.jpg'), join(DIST, 'assets', 'qr-douyin.jpg'));
copyFileSync(join(TEMPLATE, 'assets', 'qr-x.png'), join(DIST, 'assets', 'qr-x.png'));
mkdirSync(join(DIST, 'assets', 'sponsors'), { recursive: true });
for (const s of SPONSORS) {
for (const f of [s.img, s.logo].filter(Boolean)) {
copyFileSync(join(ROOT, 'assets', 'sponsors', f), join(DIST, 'assets', 'sponsors', f));
}
}
// ---- 每种语言生成首页 + 全部 skill 详情页 ----
for (const L of LANGS) {
const t = T[L.code];
const dirParts = L.dir ? [L.dir.replace(/\/$/, '')] : [];
const homeBase = L.dir ? '../' : '';
// base = 相对**当前语言根**的前缀:首页 ''、skill 详情页 '../'。
// (早先写成相对站点根,导致 /en/ 与 /zh-Hant/ 页面的导航/品牌链接全部跳回中文首页)
const homeBase = '';
mkdirSync(join(DIST, ...dirParts, 'skills'), { recursive: true });
// 首页
writeFileSync(join(DIST, ...dirParts, 'index.html'), layout({
lang: L.code, base: homeBase, title: t.title, desc: t.desc,
body: renderLanding(skills, L.code), pageClean: '', pageFile: '',
}));
// 赞助商页(每种语言一份,与首页同级)
writeFileSync(join(DIST, ...dirParts, 'sponsors.html'), layout({
lang: L.code, base: homeBase, title: t.sp.title, desc: t.sp.desc,
body: renderSponsors(L.code), pageClean: 'sponsors', pageFile: 'sponsors.html',
}));
// skill 详情页
for (const s of skills) {
const title = L.code === 'en' ? s.titleEn : s.title;
const desc = L.code === 'en' ? (s.descEn || s.desc) : s.desc;
writeFileSync(join(DIST, ...dirParts, 'skills', `${s.name}.html`), layout({
lang: L.code, base: L.dir ? '../../' : '../',
lang: L.code, base: '../',
title: `${title} · superpowers-zh`, desc,
body: renderDetail(s, L.code),
pageClean: `skills/${s.name}`, pageFile: `skills/${s.name}.html`,
@@ -708,6 +1051,7 @@ function build() {
const urls = [];
for (const L of LANGS) {
urls.push(`/${L.dir}`);
urls.push(`/${L.dir}sponsors`);
for (const s of skills) urls.push(`/${L.dir}skills/${s.name}`);
}
const sitemap = '<?xml version="1.0" encoding="UTF-8"?>\n' +
@@ -769,8 +1113,8 @@ function build() {
'/styles.css\n Cache-Control: public, max-age=31536000, immutable\n' +
'/app.js\n Cache-Control: public, max-age=31536000, immutable\n');
const pages = LANGS.length * (1 + skills.length);
console.log(`✅ 生成 ${pages} 个页面:${LANGS.length} 语言(${LANGS.map(l => l.code).join('/')}× (首页 + ${skills.length} 个 skill 详情页) → ${DIST}`);
const pages = LANGS.length * (2 + skills.length);
console.log(`✅ 生成 ${pages} 个页面:${LANGS.length} 语言(${LANGS.map(l => l.code).join('/')}× (首页 + 赞助商页 + ${skills.length} 个 skill 详情页) → ${DIST}`);
}
build();

View File

@@ -36,6 +36,21 @@
}).catch(function () { btn.textContent = '×'; });
});
// ---------- 赞助商卡片:简介展开 / 收起 ----------
// 简介默认 CSS 截 4 行;只有真的被截断时才把「展开全部」按钮显示出来。
Array.prototype.slice.call(document.querySelectorAll('.sponsor-card')).forEach(function (card) {
var desc = card.querySelector('.sc-desc');
var btn = card.querySelector('.sc-toggle');
if (!desc || !btn) return;
if (desc.scrollHeight <= desc.clientHeight + 2) return; // 没截断就不用按钮
btn.hidden = false;
btn.addEventListener('click', function () {
var open = card.classList.toggle('expanded');
btn.setAttribute('aria-expanded', open ? 'true' : 'false');
btn.textContent = open ? (I18N.collapse || '收起') : (I18N.expand || '展开全部');
});
});
// ---------- 安装命令生成器 ----------
var sel = document.getElementById('toolSel');
var cmdText = document.getElementById('cmdText');

View File

@@ -66,6 +66,7 @@ body::before {
.brand { display: flex; align-items: center; gap: 9px; font-size: 18px; font-weight: 600; }
.brand b { background: var(--accent-grad); -webkit-background-clip: text; background-clip: text; color: transparent; }
.nav nav { display: flex; gap: 24px; font-size: 14px; }
.nav nav > * { flex: 0 0 auto; white-space: nowrap; }
.nav nav a { color: var(--text-dim); transition: color .2s; }
.nav nav a:hover { color: var(--text); }
@@ -251,10 +252,21 @@ footer { border-top: 1px solid var(--border-soft); margin-top: 40px; padding: 40
.qr-card a:hover { text-decoration: underline; }
/* ---------- 响应式 ---------- */
/* 导航单独用 900px 断点:整条导航在 900px 以下就装不下了,
低于该宽度隐藏站内锚点项,余下项横向滚动(滚动条隐藏),永不折行。 */
@media (max-width: 900px) {
.nav { padding: 12px 16px; gap: 10px; }
.brand { flex: 0 0 auto; font-size: 16px; }
.nav nav a:nth-child(-n+5) { display: none; }
.nav nav {
gap: 14px; font-size: 13px; flex: 1 1 auto; justify-content: flex-start;
overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
}
.nav nav::-webkit-scrollbar { display: none; }
}
@media (max-width: 720px) {
section { padding: 56px 18px; }
.nav nav { gap: 16px; font-size: 13px; }
.nav nav a:nth-child(1), .nav nav a:nth-child(2) { display: none; }
.compare-grid { grid-template-columns: 1fr; }
.stats { gap: 28px; }
.foot-inner { flex-direction: column; align-items: flex-start; }
@@ -329,6 +341,120 @@ footer { border-top: 1px solid var(--border-soft); margin-top: 40px; padding: 40
.faq-item[open] summary::after { transform: rotate(45deg); }
.faq-a { padding: 0 0 20px; font-size: 14.5px; color: var(--text-dim); line-height: 1.75; }
/* 赞助商页 */
.sp-hero { padding-top: 90px; padding-bottom: 40px; }
.sp-hero h1 { font-size: clamp(28px, 5vw, 44px); }
/* 分档小节(旗舰 / 更多)—— 左对齐标题 + 分隔线 */
.sp-tier { padding-top: 34px; padding-bottom: 34px; }
.tier-title { font-size: 17px; font-weight: 700; padding-bottom: 10px; border-bottom: 1px solid var(--border); }
.tier-sub { font-size: 13px; color: var(--text-faint); margin: 10px 0 22px; }
/* 旗舰位 */
.sponsor-flag { display: block; }
.flag-body { padding: 22px 26px 24px; }
.flag-body h3 { font-size: 19px; font-weight: 700; }
.flag-tag { font-size: 13.5px; color: var(--accent-2); font-weight: 600; margin: 6px 0 12px; }
.flag-desc { font-size: 14px; color: var(--text-dim); line-height: 1.75; }
.flag-foot { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-top: 16px; }
.flag-foot .sponsor-perk { margin: 0; flex: 1 1 320px; }
.flag-foot .btn { flex: 0 0 auto; padding: 10px 20px; font-size: 14px; }
/* 常规位紧凑卡logo + 名 + 截断简介 + 福利),不放 banner —— banner 只给旗舰位 */
.sponsor-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(310px, 1fr)); gap: 16px; }
.sponsor-card {
position: relative; display: flex; flex-direction: column;
background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius);
padding: 22px; transition: border-color .2s, transform .2s;
}
.sponsor-card:hover { border-color: var(--accent); transform: translateY(-2px); }
.sc-ext { position: absolute; top: 16px; right: 18px; color: var(--text-faint); font-size: 13px; }
.sc-head:hover .sc-ext { color: var(--accent-2); }
.sc-head { display: flex; align-items: center; gap: 13px; padding-right: 22px; }
.sc-head:hover b { color: var(--accent-2); }
.sc-logo {
display: grid; place-items: center; flex: 0 0 auto;
width: 46px; height: 46px; border-radius: 13px;
background: #fff; border: 1px solid var(--border); overflow: hidden;
}
.sc-logo img { width: 34px; height: 34px; object-fit: contain; }
.sc-head b { font-size: 17px; font-weight: 700; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sc-desc {
margin-top: 16px; flex: 1; font-size: 13.5px; line-height: 1.75; color: var(--text-dim);
display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 4; overflow: hidden;
}
.sc-perk {
margin-top: 16px; font-size: 12.5px; line-height: 1.6; color: var(--text);
background: rgba(124,108,255,0.12); border: 1px solid rgba(124,108,255,0.25);
border-radius: 9px; padding: 9px 12px;
}
/* 展开后取消 4 行截断 */
.sponsor-card.expanded .sc-desc { -webkit-line-clamp: unset; overflow: visible; }
.sc-toggle {
align-self: flex-start; margin-top: 8px; padding: 0; background: none; border: none;
color: var(--accent-2); font-size: 12.5px; font-family: inherit; cursor: pointer;
}
.sc-toggle:hover { text-decoration: underline; text-underline-offset: 3px; }
.sc-go {
margin-top: 14px; align-self: flex-start; font-size: 13px; color: var(--text-dim);
border: 1px solid var(--border); border-radius: 9px; padding: 7px 14px; transition: all .2s;
}
.sc-go:hover { color: var(--text); border-color: var(--accent); }
/* 旗舰位空位(招商卡) */
.flag-empty {
border: 1px dashed var(--border); border-radius: var(--radius);
padding: 40px 28px; text-align: center; background: var(--bg-soft);
}
.flag-empty h3 { font-size: 18px; font-weight: 700; margin-bottom: 10px; }
.flag-empty p { font-size: 14px; color: var(--text-dim); line-height: 1.75; max-width: 620px; margin: 0 auto 20px; }
/* 赞助权益4 张卡一行(首页的 feat-grid 是 3 列,这里单独收窄) */
.sp-benefits .feat-grid { grid-template-columns: repeat(auto-fit, minmax(215px, 1fr)); }
/* 福利汇总表 */
.sp-table-wrap { overflow-x: auto; border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg-card); }
.sp-table { width: 100%; border-collapse: collapse; font-size: 14px; min-width: 560px; }
.sp-table th, .sp-table td { padding: 13px 18px; text-align: left; border-bottom: 1px solid var(--border-soft); }
.sp-table thead th { background: var(--bg-soft); font-weight: 600; font-size: 13px; color: var(--text-dim); }
.sp-table tbody tr:last-child td { border-bottom: none; }
.sp-table td a { color: var(--accent-2); text-decoration: underline; text-underline-offset: 3px; }
.sp-perks .sponsor-note { margin-top: 14px; }
.code-chip {
display: inline-flex; align-items: center; gap: 6px;
background: var(--bg-soft); border: 1px solid var(--border); border-radius: 7px; padding: 2px 4px 2px 9px;
}
.code-chip code { color: var(--accent-2); font-size: 13px; letter-spacing: .04em; }
.code-chip .copy-btn {
background: none; border: none; color: var(--text-faint); cursor: pointer;
font-size: 13px; padding: 2px 5px; border-radius: 5px; font-family: inherit;
}
.code-chip .copy-btn:hover { color: var(--text); background: var(--bg-card); }
.code-chip .copy-btn.done { color: var(--good); }
/* 赞助商 —— 完整卡片(赞助商页) */
/* 赞助商 —— 完整卡片(赞助商页) */
.sponsor-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); gap: 18px; }
.sponsor {
display: flex; flex-direction: column;
background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius);
overflow: hidden; transition: border-color .2s, transform .2s;
}
.sponsor:hover { border-color: var(--accent); transform: translateY(-2px); }
.sponsor-shot { display: block; background: var(--bg-soft); }
.sponsor-shot img { display: block; width: 100%; height: auto; }
.sponsor-body { flex: 1; display: flex; flex-direction: column; align-items: flex-start; gap: 10px; padding: 20px 22px 22px; }
.sponsor-body h3 { font-size: 17px; font-weight: 700; }
.sponsor-body p { font-size: 13.5px; color: var(--text-dim); line-height: 1.7; }
.sponsor-perk {
font-size: 13px; color: var(--text) !important;
background: rgba(124,108,255,0.12); border: 1px solid rgba(124,108,255,0.25);
border-radius: 8px; padding: 8px 12px; align-self: stretch;
}
.sponsor-body .btn { margin-top: auto; padding: 8px 16px; font-size: 13.5px; }
.sponsor-note { text-align: center; font-size: 12.5px; color: var(--text-faint); margin-top: 18px; }
.section-sub a { color: var(--accent-2); text-decoration: underline; text-underline-offset: 2px; }
/* 收尾 CTA */
.cta-inner {
background: linear-gradient(135deg, rgba(124,108,255,0.16), rgba(77,214,200,0.10));
@@ -438,7 +564,8 @@ a.card:hover .card-more { color: var(--accent); }
.doc-body th { background: var(--bg-soft); font-weight: 600; }
@media (max-width: 720px) {
.sponsor-grid, .sponsor-cards { grid-template-columns: 1fr; }
.flag-foot .btn { width: 100%; text-align: center; }
.nav nav { gap: 12px; }
.nav nav a:nth-child(1), .nav nav a:nth-child(2), .nav nav a:nth-child(3) { display: none; }
.foot-cols { flex-direction: row; flex-wrap: wrap; gap: 32px; }
}