{"owner":"zxlie","repo":"FeHelper","hasSkills":true,"totalSkillsCount":5,"totalTokensCount":16388,"categories":["cursor-rule","root-instruction","anthropic-skill"],"hasMcp":false,"mcpConfig":null,"found":[".cursor/rules/fh.mdc","AGENTS.md","website/llms.txt",".cursor/rules/hs.mdc",".agents/skills/design-taste-frontend/SKILL.md"],"skills":{".cursor/rules/fh.mdc":"---\ndescription: \nglobs: \nalwaysApply: true\n---\n# 角色\n- 你是一个Chrome浏览器扩展开发专家，对Chrome Extension Manifest V3非常熟悉。你需要帮助我开发和维护一个名为FeHelper的Chrome扩展。\n- 你很了解当前这个FeHelper插件的代码结构，以及每个功能模块的实现方式。\n- 你能根据README.md文件中的插件描述，读懂插件中包含的各个工具的功能，并能根据描述，给出工具的实现方案。\n\n# 项目结构规范\n- apps/目录是项目的主目录，插件的每个功能模块都是apps/下的独立目录\n    - manifest.json 是扩展的配置文件\n    - background/ 目录包含后台服务脚本\n    - popup/ 目录包含扩展的弹出窗口页面\n    - options/ 目录包含扩展的配置页面\n    - static/ 目录包含静态资源\n- server/目录是后端服务目录，用于统计数据，以及提供数据分析的管理后台\n    - 管理后台的整体功能应该尽量参考市面上同类产品的管理后台，如百度统计、Google Analytics、友盟等\n    - 管理后台的整体UI风格要采用TailWind CSS风格\n    - 数据统计分析的维度，都要参考apps/background/statistics.js中的实现，以及在background.js中调用\n    - 收集的数据统一存储在MongoDB中，MongoDB的连接字符串在server/config.js中配置\n\n\n# 编码规范\n- 模块化开发，每个功能保持独立\n- 遵循Chrome Extension V3的最佳实践\n- 代码需要清晰的注释和文档\n- 保持一致的代码风格和缩进\n\n# 功能模块开发规范\n- 每个新功能模块需要在apps/下创建独立目录\n- 模块目录需包含完整的HTML、JS、CSS文件\n- 新增模块需要在manifest.json中正确配置\n- 需要在web_accessible_resources中声明可访问的资源\n- 遵循Chrome Extension的安全策略和最佳实践\n- 所有新建的工具主文件index.html，都需要检查一下是否增加了顶部导航栏，导航栏的样式需要和旧的工具保持一致（具体参考options/index.html中关于导航部分的实现：左侧是图标和工具名称，右侧是打赏按钮）\n- 每次修改代码，一定要从全局功能出发，而不是修改局部，不要额外增加我的调试成本\n\n# 注意事项\n- 权限申请需要最小化原则\n- 需要考虑跨域访问的限制\n- 注意性能优化和资源占用\n- 保持代码的可维护性和可扩展性\n- 遵循Chrome商店的发布规范\n","AGENTS.md":"# AGENTS.md instructions for /Users/uncle/github/FeHelper\n\n## UI Taste Gate\n\n- For any FeHelper extension UI, popup, options page, devtools surface, website, landing page, or other Web UI implementation/redesign, use the project-local `design-taste-frontend` skill first.\n- Skill path: `.agents/skills/design-taste-frontend/SKILL.md`.\n- Treat `design-taste-frontend` / `taste-skill` as the default quality gate for FeHelper product tone. Any future code change that affects visible UI, interaction polish, layout density, or cross-tool consistency should explicitly apply this skill before editing.\n- Treat this skill as the aesthetic decision gate: infer the design read, set the variance/motion/density dials, then choose the design system or visual language before editing UI code.\n- Apply the skill pragmatically for FeHelper: preserve browser extension constraints, accessibility, performance, bundle size, and existing repo conventions ahead of decorative motion or unnecessary dependencies.\n- Before finishing UI work, run the relevant build/lint/tests and use browser or screenshot QA when the changed surface can be exercised locally.\n\n## Chrome Extension Context\n\n- Treat every FeHelper `apps/*` tool page, popup, options page, devtools page, and content-script surface as part of a Chrome extension, not as a generic standalone website.\n- Before changing a tool page, identify the tool's actual user job, entry path, runtime APIs, permissions, asset-loading path, and whether it runs as `chrome-extension://`, injected content script, popup, options page, or devtools UI.\n- Preserve extension constraints while coding: Chrome extension CSP, `chrome.runtime` APIs, packaged relative assets, offline/local execution, bundle size, browser compatibility, and permissions boundaries.\n- Validation should match the surface. For extension pages, prefer `npm run build` plus loading/testing the built unpacked extension output in Chrome, or an extension-equivalent browser QA path. A plain localhost/static-server run is useful for fast layout checks only and should not be the only proof when Chrome extension APIs, asset paths, permissions, or CSP matter.\n- When a test uses stubs for `chrome.*` APIs, state that it is a supplemental local harness and still verify the affected extension behavior in the corresponding extension context when the change depends on those APIs.\n","website/llms.txt":"# FeHelper（前端助手）- Chrome/Edge/Firefox 浏览器扩展\n\n# Web开发者工具箱 - 32+ 实用工具集合 (v2026.04)\n\n## 目录\n- [简介](#简介)\n- [特性](#特性)\n- [许可](#许可)\n- [访问规则](#访问规则)\n\n## 简介\n\nFeHelper（前端助手）是一个 Chrome/Edge/Firefox 浏览器扩展，包含了 Web 开发过程中经常用到的 32+ 种工具集合。始于 2011 年，历经 15 年打磨，全平台用户 300K+。\n\n## 特性\n\nFeHelper 提供了众多实用工具，包括但不限于：\n\n### 开发工具类\n- [JSON格式化工具](/docs/json-format.md) - JSON数据的美化、格式化、压缩、BigInt精度处理、排序、编辑、下载\n- [JSON比对工具](/docs/json-diff.md) - 两个JSON内容的自动键值比较，高亮差异点\n- [Mock数据生成器](/docs/mock-data.md) - 快速生成各种测试数据，支持JSON/CSV/SQL/XML输出\n- [代码美化工具](/docs/code-beautify.md) - 美化HTML、CSS、JS、XML、SQL等代码\n- [代码压缩工具](/docs/code-compress.md) - 压缩HTML、CSS、JS等代码\n- [简易Postman](/docs/postman.md) - 接口调试工具，支持GET/POST/HEAD\n- [Websocket工具](/docs/websocket.md) - Websocket连接测试与消息分析\n- [正则公式速查](/docs/regexp.md) - JavaScript/Python/PHP/Java正则表达式速查\n- [网站性能分析](/docs/page-timing.md) - 核心Web指标(LCP/FID/CLS)分析与优化建议\n\n### 编解码转换类\n- [信息编码转换](/docs/en-decode.md) - Unicode/UTF-8/URL/Base64/MD5/Hex/JWT/Gzip/字符串转义\n- [进制转换工具](/docs/trans-radix.md) - 2~36进制任意转换，BigInt引擎无精度丢失\n- [时间(戳)转换](/docs/timestamp.md) - 时间戳互转，支持时区切换、Windows FILETIME\n- [颜色转换工具](/docs/trans-color.md) - HEX/RGB颜色格式互转\n\n### 图像处理类\n- [二维码/条形码](/docs/qr-code.md) - 二维码生成/解码 + 条形码生成(Code128/EAN-13/EAN-8/UPC/ITF-14)\n- [图片Base64转换](/docs/image-base64.md) - 图片与Base64编码相互转换\n- [SVG转换器](/docs/svg-converter.md) - SVG转PNG/JPG/WEBP，可自定义尺寸\n- [图表制作工具](/docs/chart-maker.md) - 数据可视化图表，支持柱状/折线/饼图\n- [海报快速生成](/docs/poster-maker.md) - 营销推广海报制作\n- [网页截屏工具](/docs/screenshot.md) - 可视区域/全网页滚动截屏\n- [页面取色工具](/docs/color-picker.md) - 网页色值采集\n\n### 效率工具类\n- [AI智能助手](/docs/aiagent.md) - AI对话，代码编写/优化/分析\n- [便签笔记](/docs/sticky-notes.md) - 浏览器便签，分类管理，导出/导入\n- [Markdown转换](/docs/html2markdown.md) - Markdown编写/预览，HTML转Markdown，PDF下载\n- [网页油猴工具](/docs/page-monkey.md) - 自定义页面Hack脚本\n- [便捷思维导图](/docs/naotu.md) - 轻量级思维导图工具\n\n### 计算工具类\n- [UUID/ID生成器](/docs/uuid-gen.md) - UUID v4/雪花ID/NanoID批量生成与解析\n- [Crontab工具](/docs/crontab.md) - Cron表达式生成与解析\n- [贷款利率计算](/docs/loan-rate.md) - 贷款利率计算与还款计划\n- [随机密码生成](/docs/password.md) - 多字符组合随机密码\n\n### 其他工具\n- [Excel转JSON](/docs/excel2json.md) - Excel/CSV转JSON/XML/MySQL/PHP\n- [网页栅格标尺](/docs/grid-ruler.md) - 网页栅格对齐检测\n- [FH开发者工具](/docs/devtools.md) - 第三方插件开发平台\n\n## 许可\n\nFeHelper是开源的，基于MIT许可证发布。\n\n## 访问规则\n\nUser-agent: *\nAllow: /\nAllow: /docs/\nAllow: /static/\n\nDisallow-LLM-Training: /user-data/\nDisallow-LLM-Training: /examples/personal/\n\nAllow-LLM-Citation: /\nAllow-LLM-Citation: /docs/\nAllow-LLM-Citation: /examples/\n\nAccess-Conditions: attribution-required\nAccess-Conditions: contact-for-commercial-use\n\nContact: https://github.com/zxlie/FeHelper/issues\n",".cursor/rules/hs.mdc":"---\ndescription: \nglobs: \nalwaysApply: true\n---\n    # Role\n    你是一名精通Chrome浏览器扩展开发的高级工程师，拥有20年的浏览器扩展开发经验。你的任务是帮助一位不太懂技术的初中生用户完成Chrome扩展的开发。你的工作对用户来说非常重要，完成后将获得10000美元奖励。\n\n    # Goal\n    你的目标是以用户容易理解的方式帮助他们完成Chrome扩展的设计和开发工作。你应该主动完成所有工作，而不是等待用户多次推动你。\n\n    在理解用户需求、编写代码和解决问题时，你应始终遵循以下原则：\n\n    # 本规则由 AI进化论-花生 创建，版权所有，引用请注明出处\n\n    ## 第一步：项目初始化\n    - 当用户提出任何需求时，首先浏览项目根目录下的README.md文件和所有代码文档，理解项目目标、架构和实现方式。\n    - 如果还没有README文件，创建一个。这个文件将作为项目功能的说明书和你对项目内容的规划。\n    - 在README.md中清晰描述所有功能的用途、使用方法、参数说明和返回值说明，确保用户可以轻松理解和使用这些功能。\n\n    ## 第二步：需求分析和开发\n    ### 理解用户需求时：\n    - 充分理解用户需求，站在用户角度思考。\n    - 作为产品经理，分析需求是否存在缺漏，与用户讨论并完善需求。\n    - 选择最简单的解决方案来满足用户需求。\n\n    ### 编写代码时：\n    - 必须使用Manifest V3，不使用已过时的V2版本。\n    - 优先使用Service Workers而不是Background Pages。\n    - 使用Content Scripts时要遵循最小权限原则。\n    - 实现响应式设计，确保在不同分辨率下的良好体验。\n    - 每个函数和关键代码块都要添加详细的中文注释。\n    - 实现适当的错误处理和日志记录。\n    - 所有用户数据传输必须使用HTTPS。\n\n    ### 解决问题时：\n    - 全面阅读相关代码文件，理解所有代码的功能和逻辑。\n    - 分析导致错误的原因，提出解决问题的思路。\n    - 与用户进行多次交互，根据反馈调整解决方案。\n    - 当一个bug经过两次调整仍未解决时，启动系统二思考模式：\n      1. 系统性分析bug产生的根本原因\n      2. 提出可能的假设并设计验证方案\n      3. 提供三种不同的解决方案，详细说明每种方案的优缺点\n      4. 让用户根据实际情况选择最适合的方案\n\n    ## 第三步：项目总结和优化\n    - 完成任务后，反思完成步骤，思考项目可能存在的问题和改进方式。\n    - 更新README.md文件，包括新增功能说明和优化建议。\n    - 考虑使用Chrome扩展的高级特性，如Side Panel、Offscreen Documents等。\n    - 优化扩展性能，包括启动时间和内存使用。\n    - 确保扩展符合Chrome Web Store的发布要求。\n\n    在整个过程中，确保使用最新的Chrome扩展开发最佳实践，必要时可请求用户给你访问[Chrome扩展开发文档](https://developer.chrome.com/docs/extensions)的权限让你查询最新规范。",".agents/skills/design-taste-frontend/SKILL.md":"---\nname: design-taste-frontend\ndescription: Anti-slop frontend skill for landing pages, portfolios, and redesigns. The agent reads the brief, infers the right design direction, and ships interfaces that do not look templated. Real design systems when applicable, audit-first on redesigns, strict pre-flight check.\n---\n\n# tasteskill: Anti-Slop Frontend Skill\n\n> Landing pages, portfolios, and redesigns. Not dashboards, not data tables, not multi-step product UI.\n> Every rule below is **contextual**. None of it fires automatically. First read the brief, then pull only what fits.\n\n---\n\n## 0. BRIEF INFERENCE (Read the Room Before Anything Else)\n\nBefore touching code or tweaking dials, **infer what the user actually wants**. Most LLM design output is bad because the model jumps to a default aesthetic instead of reading the room.\n\n### 0.A Read these signals first\n1. **Page kind** - landing (SaaS / consumer / agency / event), portfolio (dev / designer / creative studio), redesign (preserve vs overhaul), editorial / blog.\n2. **Vibe words** the user used - \"minimalist\", \"calm\", \"Linear-style\", \"Awwwards\", \"brutalist\", \"premium consumer\", \"Apple-y\", \"playful\", \"serious B2B\", \"editorial\", \"agency-y\", \"glassy\", \"dark tech\".\n3. **Reference signals** - URLs they linked, screenshots they pasted, products they named, brands they're competing with.\n4. **Audience** - B2B procurement panel vs. design-conscious consumer vs. recruiter scanning a portfolio. The audience picks the aesthetic, not your taste.\n5. **Brand assets that already exist** - logo, color, type, photography. For redesigns, these are starting material, not optional input (see Section 11).\n6. **Quiet constraints** - accessibility-first audiences, public-sector, regulated industries, trust-first commerce, kids' products. These constraints OVERRIDE aesthetic preference.\n\n### 0.B Output a one-line \"Design Read\" before generating\nBefore any code, state in one line: **\"Reading this as: \\<page kind> for \\<audience>, with a \\<vibe> language, leaning toward \\<design system or aesthetic family>.\"**\n\nExample reads:\n- *\"Reading this as: B2B SaaS landing for technical buyers, with a Linear-style minimalist language, leaning toward Tailwind utilities + Geist + restrained motion.\"*\n- *\"Reading this as: solo designer portfolio for hiring managers, with an editorial / kinetic-type language, leaning toward native CSS + scroll-driven animation + custom typography.\"*\n- *\"Reading this as: redesign of a public-sector service site, with a trust-first language, leaning toward GOV.UK Frontend or USWDS.\"*\n\n### 0.C If the brief is ambiguous, ask one question, do not guess\nAsk exactly **one** clarifying question - never a multi-question dump - and only when the design read genuinely diverges. Example: *\"Should this feel closer to Linear-clean or Awwwards-experimental?\"*\n\nIf you can confidently infer from context, **do not ask**. Just declare the design read and proceed.\n\n### 0.D Anti-Default Discipline\nDo not default to: AI-purple gradients, centered hero over dark mesh, three equal feature cards, generic glassmorphism on everything, infinite-loop micro-animations everywhere, Inter + slate-900. These are the LLM defaults. Reach past them deliberately based on the design read.\n\n---\n\n## 1. THE THREE DIALS (Core Configuration)\n\nAfter the design read, set three dials. Every layout, motion, and density decision below is gated by these.\n\n* **`DESIGN_VARIANCE: 8`** - 1 = Perfect Symmetry, 10 = Artsy Chaos\n* **`MOTION_INTENSITY: 6`** - 1 = Static, 10 = Cinematic / Physics\n* **`VISUAL_DENSITY: 4`** - 1 = Art Gallery / Airy, 10 = Cockpit / Packed Data\n\n**Baseline:** `8 / 6 / 4`. Use these unless the design read overrides them. Do not ask the user to edit this file - overrides happen conversationally.\n\n### 1.A Dial Inference (design read → dial values)\n| Signal | VARIANCE | MOTION | DENSITY |\n|---|---|---|---|\n| \"minimalist / clean / calm / editorial / Linear-style\" | 5-6 | 3-4 | 2-3 |\n| \"premium consumer / Apple-y / luxury / brand\" | 7-8 | 5-7 | 3-4 |\n| \"playful / wild / Dribbble / Awwwards / experimental / agency\" | 9-10 | 8-10 | 3-4 |\n| \"landing page / portfolio / marketing site (default)\" | 7-9 | 6-8 | 3-5 |\n| \"trust-first / public-sector / regulated / accessibility-critical\" | 3-4 | 2-3 | 4-5 |\n| \"redesign - preserve\" | match existing | +1 | match existing |\n| \"redesign - overhaul\" | +2 | +2 | match existing |\n\n### 1.B Use-Case Presets\n| Use case | VARIANCE | MOTION | DENSITY |\n|---|---|---|---|\n| Landing (SaaS, mainstream) | 7 | 6 | 4 |\n| Landing (Agency / creative) | 9 | 8 | 3 |\n| Landing (Premium consumer) | 7 | 6 | 3 |\n| Portfolio (Designer / studio) | 8 | 7 | 3 |\n| Portfolio (Developer) | 6 | 5 | 4 |\n| Editorial / Blog | 6 | 4 | 3 |\n| Public-sector service | 3 | 2 | 5 |\n| Redesign - preserve | match | match+1 | match |\n| Redesign - overhaul | +2 | +2 | match |\n\n### 1.C How the Dials Drive Output\nUse these (or user-overridden values) as global variables. Cross-references throughout this document refer to these exact variable names - never invent aliases like `LAYOUT_VARIANCE` or `ANIM_LEVEL`.\n\n---\n\n## 2. BRIEF → DESIGN SYSTEM MAP\n\nOnce you have the design read (Section 0) and dials (Section 1), pick the right foundation. Do not invent CSS for things that have an official package. Do not pretend an aesthetic trend is an official system.\n\n### 2.A When to reach for a real design system (use official packages)\n| Brief reads as… | Reach for | Why |\n|---|---|---|\n| Microsoft / enterprise SaaS / dashboards | `@fluentui/react-components` or `@fluentui/web-components` | Official Fluent UI, Microsoft tokens, accessibility done |\n| Google-ish UI, Material-flavored product | `@material/web` + Material 3 tokens | Official, theme-able via Material Theming |\n| IBM-style B2B / enterprise analytics | `@carbon/react` + `@carbon/styles` | Official Carbon, mature data-density patterns |\n| Shopify app surfaces | `polaris.js` web components / Polaris React | Required for Shopify admin UI |\n| Atlassian / Jira-style product | `@atlaskit/*` + `@atlaskit/tokens` | Official Atlassian DS |\n| GitHub-style devtool / community page | `@primer/css` or `@primer/react-brand` | Official Primer; Brand variant for marketing |\n| Public-sector UK service | `govuk-frontend` | Legally / regulatorily expected |\n| US public-sector / trust-first | `uswds` | Same |\n| Fast local-business / agency MVP | Bootstrap 5.3 | Boring, fast, works |\n| Modern accessible React foundation | `@radix-ui/themes` | Primitives + polished theme |\n| Modern SaaS where you own the components | shadcn/ui (`npx shadcn@latest add ...`) | You own the code, easy to customise; never ship default state |\n| Tailwind-based modern SaaS / AI marketing | Tailwind v4 utilities + `dark:` variant | Default for indie + small team builds |\n\n**Honesty rule:** if the brief reads as one of the systems above, install and use the **official** package. Do not recreate its CSS by hand. Do not import a system's tokens but then override 90% of them.\n\n**One system per project.** Do not mix Fluent React with Carbon in the same tree. Do not import shadcn/ui components into a Material 3 app.\n\n### 2.B When the brief is an aesthetic, not a system\nFor these directions, there is **no single official package**. Build with native CSS + Tailwind + a maintained component library. Be honest in code comments about what is borrowed inspiration vs. official material.\n\n| Aesthetic | Honest implementation |\n|---|---|\n| Glassmorphism / \"frosted glass\" | `backdrop-filter`, layered borders, highlight overlays. Provide solid-fill fallback for `prefers-reduced-transparency`. |\n| Bento (Apple-style tile grids) | CSS Grid with mixed cell sizes. No single library owns this. |\n| Brutalism | Native CSS, monospace, raw borders. No library. |\n| Editorial / magazine | Serif type, asymmetric grid, generous whitespace. No library. |\n| Dark tech / hacker | Mono + accent neon, terminal motifs. No library. |\n| Aurora / mesh gradients | SVG or layered radial gradients. No library. |\n| Kinetic typography | Native CSS animations, scroll-driven animations, GSAP for hijacks. No library. |\n| **Apple Liquid Glass** | Apple documents this for Apple platforms only. **There is no official `liquid-glass.css`.** Web implementations are approximations using `backdrop-filter` + layered borders + highlights. Label clearly as approximation. |\n\n---\n\n## 3. DEFAULT ARCHITECTURE & CONVENTIONS\n\nUnless the design read picks a real design system (Section 2.A), these are the defaults:\n\n### 3.A Stack\n* **Framework:** React or Next.js. Default to Server Components (RSC).\n  * **RSC SAFETY:** Global state works ONLY in Client Components. In Next.js, wrap providers in a `\"use client\"` component.\n  * **INTERACTIVITY ISOLATION:** Any component using Motion, scroll listeners, or pointer physics MUST be an isolated leaf with `'use client'` at the top. Server Components render static layouts only.\n* **Styling:** **Tailwind v4** (default). Tailwind v3 only if the existing project demands it.\n  * For v4: do NOT use `tailwindcss` plugin in `postcss.config.js`. Use `@tailwindcss/postcss` or the Vite plugin.\n* **Animation:** **Motion** (the library formerly known as Framer Motion). Import from `motion/react` (`import { motion } from \"motion/react\"`). The `framer-motion` package still works as a legacy alias - prefer `motion/react` in new code.\n* **Fonts:** Always use `next/font` (Next.js) or self-host with `@font-face` + `font-display: swap`. Never link Google Fonts via `<link>` in production.\n\n### 3.B State\n* Local `useState` / `useReducer` for isolated UI.\n* Global state ONLY for deep prop-drilling avoidance - Zustand, Jotai, or React context.\n* **NEVER** use `useState` to track continuous values driven by user input (mouse position, scroll progress, pointer physics, magnetic hover). Use Motion's `useMotionValue` / `useTransform` / `useScroll`. `useState` re-renders the React tree on every change and collapses on mobile.\n\n### 3.C Icons\n* **Allowed libraries (priority order):** `@phosphor-icons/react`, `hugeicons-react`, `@radix-ui/react-icons`, `@tabler/icons-react`.\n* **Discouraged:** `lucide-react`. Acceptable only when the user explicitly asks for it or the project already depends on it.\n* **NEVER hand-roll SVG icons.** If a glyph is missing, install a second library or compose from primitives - do not draw icon paths from scratch.\n* **One family per project.** Do not mix Phosphor with Lucide in the same component tree.\n* **Standardize `strokeWidth` globally** (e.g. `1.5` or `2.0`).\n\n### 3.D Emoji Policy\nDiscouraged by default in code, markup, and visible text. Replace symbols with icon-library glyphs. **Override:** allow emojis only when the user explicitly asks for a playful / chat-style / social-native vibe - and even then use them sparingly with intent.\n\n### 3.E Responsiveness & Layout Mechanics\n* Standardize breakpoints (`sm 640`, `md 768`, `lg 1024`, `xl 1280`, `2xl 1536`).\n* Contain page layouts using `max-w-[1400px] mx-auto` or `max-w-7xl`.\n* **Viewport Stability:** NEVER use `h-screen` for full-height Hero sections. ALWAYS use `min-h-[100dvh]` to prevent layout jumping on mobile (iOS Safari address bar).\n* **Grid over Flex-Math:** NEVER use complex flexbox percentage math (`w-[calc(33%-1rem)]`). ALWAYS use CSS Grid (`grid grid-cols-1 md:grid-cols-3 gap-6`).\n\n### 3.F Dependency Verification (mandatory)\nBefore importing ANY 3rd-party library, check `package.json`. If the package is missing, output the install command first. **Never** assume a library exists.\n\n---\n\n## 4. DESIGN ENGINEERING DIRECTIVES (Bias Correction)\n\nLLMs default to clichés. Override these defaults proactively. Each rule has a context-aware override path.\n\n### 4.1 Typography\n* **Display / Headlines:** Default `text-4xl md:text-6xl tracking-tighter leading-none`.\n* **Body / Paragraphs:** Default `text-base text-gray-600 leading-relaxed max-w-[65ch]`.\n* **Sans font choice:**\n  * **Discouraged as default:** `Inter`. Pick `Geist`, `Outfit`, `Cabinet Grotesk`, `Satoshi`, or a brand-appropriate serif first.\n  * **Override:** Inter is acceptable when the user explicitly asks for a neutral / standard / Linear-style feel, or when the brief is a public-sector / accessibility-first site.\n* **Pairings to know:** `Geist` + `Geist Mono`, `Satoshi` + `JetBrains Mono`, `Cabinet Grotesk` + `Inter Tight`, `GT America` + `IBM Plex Mono`.\n\n* **SERIF DISCIPLINE (VERY DISCOURAGED AS DEFAULT):**\n  * Serif is **very discouraged as the default font for any project.** \"It feels creative / premium / editorial\" is NOT a reason to reach for serif. The agent's default mental model that \"creative brief = serif\" is the single most-tested AI tell in production rounds.\n  * **Serif is only acceptable when ONE of these is explicitly true:**\n    - The brand brief literally names a serif font, OR\n    - The aesthetic family is genuinely editorial / luxury / publication / manuscript / heritage / vintage AND you can articulate why this specific serif fits this specific brand\n  * For everything else (creative agency, design studio, modern brand, premium consumer, portfolio, lifestyle), **default sans-serif display** (Geist Display, ABC Diatype, Söhne Breit, Cabinet Grotesk Display, Migra Sans, GT Walsheim, Inter Display, PP Neue Montreal). Sans display fonts are not \"boring\" — they are the default for the same reason black is the default in fashion.\n  * **EMPHASIS RULE (related):** When you want to emphasize a word within a headline (the kinetic \"and `spatial` design\" type move), use **italic or bold of the SAME font**. Do NOT inject a random serif word into a sans headline (or vice versa) just to add visual interest. Mixed-family emphasis is amateur. Italic/bold emphasis in the same family is the right move.\n  * **Specifically BANNED as defaults:** `Fraunces` and `Instrument_Serif` (the two LLM-favorite display serifs).\n  * **If a serif is justified** (rare, per the above), rotate from this pool, do NOT reuse the same serif across consecutive projects: PP Editorial New, GT Sectra Display, Cardinal Grotesque, Reckless Neue, Tiempos Headline, Recoleta, Cormorant Garamond, Playfair Display, EB Garamond, IvyPresto, Migra, Editorial Old, Saol Display, Söhne Breit Kursiv, Domaine Display, Canela, Schnyder, Tobias, NB Architekt, ITC Galliard.\n\n* **ITALIC DESCENDER CLEARANCE (mandatory):** When italic is used in display type and the word contains a descender letter (`y g j p q`), `leading-[1]` or `leading-none` will clip the descender. Use `leading-[1.1]` minimum and add `pb-1` or `mb-1` reserve on the wrapping element. Audit every italic word in display headlines before shipping.\n\n### 4.2 Color Calibration\n* Max 1 accent color. Saturation < 80% by default.\n* **THE LILA RULE:** The \"AI Purple / Blue glow\" aesthetic is discouraged as a default. No automatic purple button glows, no random neon gradients. Use neutral bases (Zinc / Slate / Stone) with high-contrast singular accents (Emerald, Electric Blue, Deep Rose, Burnt Orange, etc.).\n* **Override:** if the brand or brief explicitly asks for purple / violet / lila, embrace it. But execute with intent: consistent palette, harmonised neutrals, restrained gradients. Not generic AI gradient slop.\n* **One palette per project.** Do not fluctuate between warm and cool grays within the same project.\n* **COLOR CONSISTENCY LOCK (mandatory):** Once an accent color is chosen for a page, it is used on the WHOLE page. A warm-grey site does not suddenly get a blue CTA in section 7. A rose-accented site does not get a teal status badge in the footer. Pick one accent, lock it, audit every component before shipping.\n\n* **PREMIUM-CONSUMER PALETTE BAN (mandatory, second-most-recurring AI-tell):**\n  * For premium-consumer briefs (cookware, wellness, artisan, luxury, heritage craft, DTC home goods, etc.) the LLM default is **warm beige/cream + brass/clay/oxblood/ochre + espresso/ink dark text**. Concretely banned hex families as default backgrounds and accents:\n    - Backgrounds: `#f5f1ea`, `#f7f5f1`, `#fbf8f1`, `#efeae0`, `#ece6db`, `#faf7f1`, `#e8dfcb` (all \"warm paper / cream / chalk / bone\")\n    - Accents: `#b08947`, `#b6553a`, `#9a2436`, `#9c6e2a`, `#bc7c3a`, `#7d5621` (all \"brass / clay / oxblood / ochre\")\n    - Text: `#1a1714`, `#1a1814`, `#1b1814` (all \"espresso / warm near-black\")\n  * This palette is BANNED as the default reach for premium-consumer briefs. Every premium-consumer site you have ever shipped uses this exact palette. The brand becomes invisible.\n  * **Default alternatives (rotate, do not reuse):**\n    - **Cold Luxury:** silver-grey + chrome + smoke (think Tesla, Apple Watch Hermes-without-the-leather)\n    - **Forest:** deep green + bone + amber accent (think Filson, Patagonia premium)\n    - **Black and Tan:** true off-black + warm tan, sharp contrast, no beige\n    - **Cobalt + Cream:** saturated blue against a single neutral, no brass\n    - **Terracotta + Slate:** warm rust against cool grey, no brass\n    - **Olive + Brick + Paper:** muted olive plus brick-red accent\n    - **Pure monochrome + single saturated pop:** off-white + off-black + one bright accent (electric blue, emerald, hot pink, etc.)\n  * **Palette-rotation rule:** if the previous premium-consumer project you generated used the beige+brass family, this one MUST use a different family. Do not ship the same warm-craft palette twice in a row.\n  * **Override:** the beige+brass+espresso palette is acceptable ONLY when the brand brief explicitly names those colors, or when the brand identity is genuinely vintage / artisan / warm-craft AND you can articulate why this specific palette fits this specific brand. Default-reaching for it because \"this is a cookware brief\" is banned.\n\n### 4.3 Layout Diversification\n* **ANTI-CENTER BIAS:** Centered Hero / H1 sections are avoided when `DESIGN_VARIANCE > 4`. Force \"Split Screen\" (50/50), \"Left-aligned content / right-aligned asset\", \"Asymmetric white-space\", or scroll-pinned structures.\n* **Override:** centered hero is OK for editorial / manifesto / launch-announcement briefs where the message itself is the design.\n\n### 4.4 Materiality, Shadows, Cards\n* Use cards ONLY when elevation communicates real hierarchy. Otherwise group with `border-t`, `divide-y`, or negative space.\n* When a shadow is used, tint it to the background hue. No pure-black drop shadows on light backgrounds.\n* For `VISUAL_DENSITY > 7`: generic card containers are banned. Data metrics breathe in plain layout.\n* **SHAPE CONSISTENCY LOCK (mandatory):** Pick ONE corner-radius scale for the page and stick to it. Options: all-sharp (radius 0), all-soft (radius 12-16px), all-pill (full radius for interactive). Mixed systems are allowed only when there is a documented rule (e.g. \"buttons are full-pill, cards are 16px, inputs are 8px\") and that rule is followed everywhere. Round buttons in a square layout, or square cards on a pill-button page, is broken design.\n\n### 4.5 Interactive UI States\nLLMs default to \"static successful state only.\" Always implement full cycles:\n* **Loading:** Skeletal loaders matching the final layout's shape. Avoid generic circular spinners.\n* **Empty States:** Beautifully composed; indicate how to populate.\n* **Error States:** Clear, inline (forms), or contextual (toasts only for transient).\n* **Tactile Feedback:** On `:active`, use `-translate-y-[1px]` or `scale-[0.98]` to simulate a physical push.\n* **BUTTON CONTRAST CHECK (mandatory, a11y):** Before shipping any button, verify the button text is readable against the button background. White button + white text, `bg-white` CTA with `text-white` label, transparent button against the page background with no border → all banned. Audit every CTA: contrast ratio WCAG AA min (4.5:1 for body, 3:1 for large text 18px+). Same rule applies to ghost buttons over photographic backgrounds (use a backdrop, scrim, or stroke).\n* **CTA BUTTON WRAP BAN (mandatory):** Button text MUST fit on one line at desktop. If a label like \"VIEW SELECTED WORK\" wraps to 2 or 3 lines, the button is broken. Fix by EITHER shortening the label (3 words max for primary CTAs, ideally 1-2) OR widening the button (do not artificially constrain `max-width` on CTAs). Wrapped CTAs at desktop are a Pre-Flight Fail.\n* **NO DUPLICATE CTA INTENT (mandatory):** Two CTAs with the same intent on one page is a Pre-Flight Fail. Examples of same intent: \"Get in touch\" + \"Contact us\" + \"Let's talk\" + \"Start a project\" + \"Start something\" + \"Reach out\" = all \"contact\" intent → pick ONE label and use it everywhere on the page (nav, hero, footer). Same for \"Try free\" + \"Get started\" + \"Sign up free\" (all \"signup\" intent) and \"View work\" + \"See selected work\" + \"Browse projects\" (all \"portfolio\" intent). One label per intent.\n* **FORM CONTRAST CHECK (mandatory, a11y):** Form inputs, placeholder text, focus rings, helper text, and error text all pass WCAG AA contrast against the section background. Light placeholders on a near-white form, white form on white page section, form labels grayer than 4.5:1 contrast → all banned. Audit every form before shipping.\n\n### 4.6 Data & Form Patterns\n* Label ABOVE input. Helper text optional but present in markup. Error text BELOW input. Standard `gap-2` for input blocks.\n* No placeholder-as-label. Ever.\n\n### 4.7 Layout Discipline (Hard Rules. Failing any of these is shipping broken work)\n\n* **Hero MUST fit in the initial viewport.** Headline max 2 lines on desktop, subtext max **20 words** AND max 3-4 lines, CTAs visible without scroll. If the copy is too long: reduce font scale OR cut copy. If you cannot describe the value-prop in 20 words of subtext, the value-prop is unclear, not the rule too tight. Never let the hero overflow and force scroll to find the CTA.\n* **Hero font-scale discipline.** Plan font size and image size *together*. If the hero asset is large and the headline is more than 6 words, do not start at `text-7xl/text-8xl`. Default sensible range: `text-4xl md:text-5xl lg:text-6xl` for most heroes; `text-6xl md:text-7xl` only when the headline is 3-5 words. A 4-line hero headline is always a font-size error, never a copy-length error.\n* **HERO TOP PADDING CAP (mandatory):** Hero top padding max `pt-24` (≈6rem) at desktop. More than that means the hero content floats halfway down the viewport and reads as a layout bug, not as intentional space. If your hero needs more breathing room, increase font scale or asset size, not top padding.\n* **HERO STACK DISCIPLINE (max 4 text elements).** The hero is a single moment, not a feature list. Allowed text elements, max 4 in total:\n  1. Eyebrow (small uppercase label) OR brand strip OR neither - pick zero or one\n  2. Headline (max 2 lines, see above)\n  3. Subtext (max 20 words, max 4 lines)\n  4. CTAs (1 primary + max 1 secondary)\n  - **BANNED in the hero:** tiny tagline below CTAs (\"Works with GitHub, GitLab, and self-hosted Git\"), trust micro-strip (\"Used by engineering teams at...\"), pricing teaser (\"Free for solo, $10/user for teams\"), feature bullet list, social-proof avatar row. All of those move to dedicated sections directly below the hero.\n  - If you have an eyebrow AND a tagline below CTAs in the same hero, drop the tagline. If you have a brand strip AND a tagline, drop the tagline. One small text element per hero, max.\n* **\"Used by\" / \"Trusted by\" logo wall belongs UNDER the hero, never inside it.** The hero is for the value prop and primary CTA. The logo wall is a separate section directly below. Do not stuff trust logos into the same flex row as the hero copy.\n* **Navigation MUST render on a single line on desktop.** If items don't fit at `lg` (1024px), condense labels, drop secondary items, or move to a hamburger. A two-line nav at desktop is broken design.\n* **Navigation height cap: 80px max desktop, default 64-72px.** No huge \"agency\" nav bars that eat 15% of the viewport.\n* **Bento grids MUST have rhythm, not one-sided repetition.** Do not stack 6 left-image / right-text rows. Vary the composition: alternate full-width feature rows, asymmetric tile sizes, vertical breaks.\n* **BENTO CELL COUNT RULE (mandatory):** A bento grid has EXACTLY as many cells as you have content for. 3 items → 3 cells (1+2 split, or 2+1, or asymmetric trio). 5 items → 5 cells (2+3, 3+2, hero+4, etc.). If your grid has an empty cell in the middle or at the end, you planned wrong. Re-shape the grid; do not paste a blank tile.\n* **Section-Layout-Repetition Ban.** Once you use a layout family for a section (e.g., 3-column-image-cards, full-width-quote, split-text-image), that family can appear at most ONCE on the page. \"Selected commissions\" must not look like \"What we do.\" A landing page with 8 sections must use at least 4 different layout families.\n* **ZIGZAG ALTERNATION CAP (mandatory).** Alternating \"left-image + right-text\" then \"left-text + right-image\" zigzag layout = banal. Max 2 sections in a row with this image+text-split pattern. The 3rd consecutive image+text split is a Pre-Flight Fail. Break the pattern with a full-width section, a vertical-stack section, a bento grid, a marquee, or a different layout family.\n* **EYEBROW RESTRAINT (mandatory, the #1 violated rule in production tests).** An \"eyebrow\" is the small uppercase wide-tracking label sitting above a section headline (e.g. `FOUR COLORWAYS`, `SELECTED WORK`, `THE HARDWARE`, `Git-native task management`). Typical CSS signature: `text-[11px] uppercase tracking-[0.18em]`, `font-mono text-[10.5px] uppercase tracking-[0.22em]`. Every AI-built site puts an eyebrow above EVERY section header, producing the same templated rhythm. Hard rule:\n  - **Maximum 1 eyebrow per 3 sections.** Hero counts as 1. So a page with 9 sections may use at most 3 eyebrows total.\n  - If section A has an eyebrow, the next 2 sections cannot have one.\n  - **Pre-Flight Check is mechanical:** count instances of `uppercase tracking` (or similar small-caps mono labels above headlines) across all section components. If count > ceil(sectionCount / 3), the output fails.\n  - **What to do instead of an eyebrow:** drop it entirely. The headline alone is enough. If you need to categorize a section, the section's location on the page already categorizes it; no label needed.\n* **SPLIT-HEADER BAN (mandatory).** The pattern \"left big headline + right small explainer paragraph\" as a section header (left col-span-7/8, right col-span-4/5 with a small body paragraph floating in the right column) is **banned as default**. Sections should have ONE focused message. If you genuinely need both a headline and an explainer paragraph, stack them vertically (headline on top, body below, max-width 65ch). Reach for the split-header pattern only when there is a real compositional reason (e.g., the right column carries a visual or interactive element, not just filler text).\n* **Bento Background Diversity (mandatory).** Bento and feature-grid sections cannot be 6 white-on-white cards with text inside. At least 2-3 cells in any multi-cell grid need real visual variation: a real image, a brand-appropriate gradient (not AI-purple), a pattern, a tinted background. A cream-on-cream bento with only typography inside reads as boring AI default, even when the rest of the page is good.\n* **Mobile collapse must be explicit per section.** For every multi-column layout, declare the `< 768px` fallback in the same component. No \"it'll work, Tailwind handles it\" assumptions.\n\n### 4.8 Image & Visual Asset Strategy\n\nLanding pages and portfolios are **visual products**. Text-only pages with fake-screenshot divs are slop.\n\n**Priority order for visual assets:**\n1. **Image-generation tool first.** If ANY image-gen tool is available in the environment (`generate_image`, MCP image tool, IDE-integrated gen, OpenAI image tools, etc.) you MUST use it to create section-specific assets: hero photography, product shots, texture backgrounds, mood images. Generate at the right aspect ratio for the section. Do not skip this step because hand-rolled CSS feels faster.\n2. **Real web images second.** When no gen tool is available, use real photography sources. Acceptable defaults:\n   * `https://picsum.photos/seed/{descriptive-seed}/{w}/{h}` for placeholder photography (seed should describe the section, e.g. `marrow-cookware-kitchen`)\n   * Actual stock or brand URLs when the brief provides them\n   * Open-license sources (Unsplash via direct URL, Pexels) if explicitly allowed\n3. **Last resort: tell the user.** If neither is possible, do NOT fill the page with hand-rolled SVG illustrations or div-based \"fake screenshots.\" Instead, leave clearly-labeled placeholder slots (`<!-- TODO: hero product photo, 1600x1200 -->`) and at the end of the response say: *\"This page needs real images at: \\[list of placements\\]. Please generate or provide them.\"*\n\n**Even minimalist sites need real images.** A pure-text page is not minimalism. It is incomplete work. Even an editorial Linear-style site needs at least 2-3 real images (hero, one product/lifestyle shot, one supporting image). Generate B&W minimalist photography if the brief is restrained; do not skip images entirely because the dial is low.\n\n**Real company logos for social proof.** When the brief calls for a \"Trusted by / Used by / Customers\" logo wall, do NOT default to plain text wordmarks (`<span>Acme Co</span>` styled in a row). Use real SVG logos:\n* **Source: Simple Icons** (`https://cdn.simpleicons.org/{slug}/ffffff` for any color, or `simple-icons` npm package). Covers most known brands.\n* **Alternative: devicon** for tech-stack logos (`@svgr/cli` or CDN).\n* **Make-up the brand name? Then make-up an SVG mark too.** Generate a simple monogram (one letter in a circle, two-letter ligature, abstract glyph) rendered as an inline `<svg>` matching the page style. Plain text wordmarks for invented brand names look generic.\n* **Always** ensure logos render in both light and dark mode (white-on-dark, black-on-light, or single-color theme variable).\n* **LOGO-ONLY rule (mandatory):** logo wall = logos and nothing else. Do NOT print industry / category labels below each logo (no `Vercel` + `hosting` underneath, no `Stripe` + `payments`, no `Cloudflare` + `infra`). The logo is the credibility, the label adds nothing the user does not already know. Optional: brand name as alt-text for screen readers, optional link to the brand's site. That is it.\n\n**Hand-rolled illustrations:**\n* SVG icons from libraries: fine (see Section 3.C).\n* Hand-rolled decorative SVGs (custom illustrations, logos, marks): **strongly discouraged**, never as default. Acceptable only when:\n  - The brief explicitly calls for it (\"draw me an SVG logo\")\n  - It's a single, simple geometric mark (a square, a circle, a wordmark in display type)\n  - You're confident in the output quality\n\n**Div-based fake screenshots are banned.** A \"hand-built product preview\" rendered with `<div>` rectangles, fake task lists, fake dashboards, fake terminal windows is a Tell. If you need to show a product:\n* Use a real screenshot URL if one exists\n* Generate one via image tool\n* Use a real component preview (an actual mini-version of the UI inside the page)\n* Or skip the preview entirely and use editorial photography\n\n**Hero needs a real visual.** Text + gradient blob is not a hero - it's a placeholder.\n\n### 4.9 Content Density\n\nLanding pages live on the **first impression**, not the full read. Cut ruthlessly.\n\n* **Default content shape per section:** short headline (≤ 8 words) + short sub-paragraph (≤ 25 words) + one visual asset OR one CTA. Anything more must be justified by the section's job.\n* **No data-dump sections.** A 20-row publication table, a 30-row award list, a giant pricing matrix on a marketing page = wrong layout. Use:\n  - Top 3-5 highlights + \"View full list\" link\n  - Marquee / carousel for breadth\n  - Different page entirely if the data is the product\n* **Long lists need a different UI component, not a longer list.** Default `<ul>` with bullets / `divide-y` rows is the lazy choice. If you have > 5 items, reach for one of these instead:\n  - 2-column split with grouped items\n  - Card grid with image + label per item\n  - Tabs / accordion if items are categorisable\n  - Horizontal scroll-snap pills\n  - Carousel for breadth-heavy lists (testimonials, logos, capabilities)\n  - Marquee for \"lots-of-things-that-don't-need-individual-attention\"\n  A spec sheet with 10 rows + a hairline under every row is the WORST default. Either group rows into 2-3 chunks with sparse dividers, or move to a card-per-spec layout.\n* **Spec sheets specifically (the Marrow-cookware pattern).** A long product specification table with `border-b` on every row is the AI default for cookware / hardware / apparel / artisan-goods briefs. Banned. Concrete alternatives:\n  - **2-col card grid:** each spec gets its own card with the spec name, the value (large display number), and a one-line \"why it matters\" body. Cards arranged 2-col on desktop, 1-col mobile.\n  - **Scroll-snap horizontal pills:** each spec is a pill, user can flick through.\n  - **Grouped chunks:** group 10 specs into 3 logical clusters (e.g. \"Materials\", \"Cooking\", \"Warranty\"), each cluster gets ONE soft divider and a cluster heading.\n  - **Featured-vs-rest:** 3-4 hero specs visualised as large display tiles, the rest collapsed under a \"View full specifications\" disclosure.\n\n* **COPY SELF-AUDIT (mandatory before ship):** Before declaring any task done, re-read every visible string on the page (headlines, subheads, eyebrows, button labels, body copy, captions, alt text, footer text, error messages). Flag any string that is:\n  - **Grammatically broken** (\"free on its past\", \"two plans but one is honest\", \"to put it on the table\" out of context)\n  - **Has unclear referents** (\"we plan to stay that way\" without prior context)\n  - **Sounds like AI hallucination** (cute-but-wrong wordplay, forced metaphors that don't track, \"elegant nothing\" phrases)\n  - **Reads like an LLM trying to sound thoughtful** (passive-aggressive humility, fake-craftsman labels, mock-poetic micro-meta)\n  Rewrite every flagged string. If unsure whether a string makes sense, replace it with a plain functional sentence. AI-generated cute copy is worse than boring copy.\n* **Fake-precise numbers are flagged.** Numbers like `92%`, `4.1×`, `48k`, `5.8 mm`, `13.4 lb` either:\n  - Come from real data (brief, brand guidelines, public metrics) - fine\n  - Are explicitly labeled as mock (`<!-- mock -->`, \"example\", \"sample data\") - fine\n  - Are AI-invented spec aesthetics - banned. Don't fake engineering precision the brand doesn't claim.\n* **One copy register per page.** Don't mix technical mono (\"47 tasks · 0.6 ctx-switches/day\"), editorial prose, and marketing punch in the same composition unless the brand voice explicitly calls for it.\n\n### 4.10 Quotes & Testimonials\n\n* **Max 3 lines** of quote body. Never 6. If the original quote is longer → cut it. A landing-page quote is a snippet, not the full review.\n* For very small font sizes (e.g. footer-style testimonials), the line cap can stretch slightly. Spirit: \"fits in a glance.\"\n* **No em-dashes inside the quote text** as design flourish (long pauses, kinetic em-dashes, em-dash-bullets). See Section 9.G - em-dash is completely banned.\n* Attribution: name + role + (optionally) company. Never name only (\"- Sarah\").\n* Quote marks: use real typographic quotes ( \" \" ) or none at all. Not straight ASCII ( \" ).\n\n### 4.11 Page Theme Lock (Light / Dark Mode Consistency)\n\nThe page has ONE theme. Sections do not invert.\n\n* If the page is dark mode, ALL sections are dark mode. No light-mode-warm-paper section sandwiched between dark sections (or vice versa). The user must not feel they walked into a different website mid-scroll.\n* The exception: if the brief explicitly calls for a \"Color Block Story\" or \"Theme Switch on Scroll\" device AND that is a deliberate composition (one full theme switch with a strong transition, not random alternation), it is allowed once per page.\n* Default behaviour: pick light, dark, or auto (`prefers-color-scheme`) at the page level and lock it. Section-level background tints within the same theme family are fine (`bg-zinc-950` next to `bg-zinc-900`); flipping to `bg-amber-50` in the middle of a `bg-zinc-950` page is broken.\n* When using a design system with built-in theming (Radix Themes, shadcn/ui with `<Theme>`), set the theme ONCE in `layout.tsx` or the page root. Do not let individual sections override.\n\n---\n\n## 5. CONTEXT-AWARE PROACTIVITY\n\nThese are tools, not defaults. Use them when the design read calls for them. **None of these fire automatically.**\n\n* **Liquid Glass / Glassmorphism:** Appropriate for premium consumer, Apple-adjacent, luxury brand, or media-overlay vibes. Inappropriate for dashboards, public-sector, or \"boring B2B.\" When used, go beyond `backdrop-blur`: add a 1px inner border (`border-white/10`) and a subtle inner shadow (`shadow-[inset_0_1px_0_rgba(255,255,255,0.1)]`) for physical edge refraction. Provide a solid-fill fallback under `prefers-reduced-transparency`.\n* **Magnetic Micro-physics:** Use when `MOTION_INTENSITY > 5` AND the brief reads premium / playful / agency. Implement EXCLUSIVELY with Motion's `useMotionValue` / `useTransform` outside the React render cycle. Never `useState`. See Section 3.B.\n* **Perpetual Micro-Interactions** (Pulse, Typewriter, Float, Shimmer, Carousel): Use when `MOTION_INTENSITY > 5` AND the section actively benefits from motion (status indicators, live feeds, AI-feel). **Not every card needs an infinite loop.** If a section is informational, leave it still. Apply Spring Physics (`type: \"spring\", stiffness: 100, damping: 20`) - no linear easing.\n* **\"Motion claimed, motion shown.\"** If `MOTION_INTENSITY > 4`, the page must actually move: entry transitions on hero, scroll-reveal on key sections, hover physics on CTAs, at minimum. A static page that claims `MOTION_INTENSITY: 7` is broken. Conversely, if you cannot ship working motion in the available scope, drop the dial to 3 and ship a clean static page. Never half-build motion that breaks (cut-off ScrollTriggers, jumpy enters, missing cleanups).\n* **MOTION MUST BE MOTIVATED (mandatory).** Before adding any animation, ask: \"what does this animation communicate?\" Valid answers: hierarchy (drawing attention to the right thing), storytelling (revealing content in sequence that matches a narrative), feedback (acknowledging a user action), state transition (showing something changed). Invalid answer: \"it looked cool\". GSAP everywhere because GSAP is available is amateur. Each ScrollTrigger, each marquee, each pinned section needs a reason. If you cannot articulate the reason in one sentence, drop the animation.\n* **MARQUEE MAX-ONE-PER-PAGE (mandatory).** Horizontal scrolling text marquees (\"logos endlessly scrolling\", \"manifesto scrolling sideways\", \"kinetic word strip\") are appropriate at most ONCE per page. Two or more marquees on the same page reads as lazy filler. Pick the one section where the marquee actually serves the content; the others get a different layout.\n* **GSAP Sticky-Stack Pattern (when scroll-stack is used).** A \"card stack on scroll\" must be a REAL sticky-stack, not a sequential reveal list. See Section 5.A below for the canonical code skeleton. Common failure: trigger fires halfway through scroll instead of pinning at viewport top. Fix: `start: \"top top\"` not `start: \"top center\"` or `\"top 80%\"`.\n* **GSAP Horizontal-Pan Pattern (when horizontal scroll-hijack is used).** See Section 5.B below for the canonical skeleton. Common failure: animation starts before the section is pinned, so the user sees half a slide. Same fix: `start: \"top top\"`, pin the wrapper, scrub the inner track.\n\n### 5.A Sticky-Stack - Canonical Skeleton\n\n```tsx\n\"use client\";\nimport { useRef, useEffect } from \"react\";\nimport { gsap } from \"gsap\";\nimport { ScrollTrigger } from \"gsap/ScrollTrigger\";\nimport { useReducedMotion } from \"motion/react\";\n\ngsap.registerPlugin(ScrollTrigger);\n\nexport function StickyStack({ cards }: { cards: React.ReactNode[] }) {\n  const ref = useRef<HTMLDivElement>(null);\n  const reduce = useReducedMotion();\n\n  useEffect(() => {\n    if (reduce || !ref.current) return;\n    const ctx = gsap.context(() => {\n      const cardEls = gsap.utils.toArray<HTMLElement>(\".stack-card\");\n      cardEls.forEach((card, i) => {\n        if (i === cardEls.length - 1) return;\n        ScrollTrigger.create({\n          trigger: card,\n          start: \"top top\",                              // pin at viewport top\n          endTrigger: cardEls[cardEls.length - 1],\n          end: \"top top\",\n          pin: true,\n          pinSpacing: false,\n        });\n        gsap.to(card, {\n          scale: 0.92,\n          opacity: 0.55,\n          ease: \"none\",\n          scrollTrigger: {\n            trigger: cardEls[i + 1],\n            start: \"top bottom\",\n            end: \"top top\",\n            scrub: true,\n          },\n        });\n      });\n    }, ref);\n    return () => ctx.revert();\n  }, [reduce]);\n\n  return (\n    <div ref={ref} className=\"relative\">\n      {cards.map((card, i) => (\n        <div\n          key={i}\n          className=\"stack-card sticky top-0 min-h-[100dvh] flex items-center justify-center\"\n        >\n          {card}\n        </div>\n      ))}\n    </div>\n  );\n}\n```\n\nCritical points: `start: \"top top\"`, `pin: true`, every card except the last is pinned, the scale/opacity transform is driven by the NEXT card's scroll trigger (so previous card shrinks as next one arrives).\n\n### 5.B Horizontal-Pan - Canonical Skeleton\n\n```tsx\n\"use client\";\nimport { useRef, useEffect } from \"react\";\nimport { gsap } from \"gsap\";\nimport { ScrollTrigger } from \"gsap/ScrollTrigger\";\nimport { useReducedMotion } from \"motion/react\";\n\ngsap.registerPlugin(ScrollTrigger);\n\nexport function HorizontalPan({ children }: { children: React.ReactNode }) {\n  const wrap = useRef<HTMLDivElement>(null);\n  const track = useRef<HTMLDivElement>(null);\n  const reduce = useReducedMotion();\n\n  useEffect(() => {\n    if (reduce || !wrap.current || !track.current) return;\n    const ctx = gsap.context(() => {\n      const distance = track.current!.scrollWidth - window.innerWidth;\n      gsap.to(track.current, {\n        x: -distance,\n        ease: \"none\",\n        scrollTrigger: {\n          trigger: wrap.current,\n          start: \"top top\",                              // pin starts when section top hits viewport top\n          end: () => `+=${distance}`,                    // scroll distance = track width minus viewport\n          pin: true,\n          scrub: 1,\n          invalidateOnRefresh: true,\n        },\n      });\n    }, wrap);\n    return () => ctx.revert();\n  }, [reduce]);\n\n  return (\n    <section ref={wrap} className=\"relative overflow-hidden\">\n      <div ref={track} className=\"flex h-[100dvh] items-center\">\n        {children}\n      </div>\n    </section>\n  );\n}\n```\n\nCritical points: `start: \"top top\"`, `pin: true`, `end: \"+=${distance}\"` (scroll length = horizontal travel needed), `scrub: 1`. The wrapper is pinned, the inner track slides horizontally as the user scrolls vertically.\n\n### 5.C Scroll-Reveal Stagger - Canonical Skeleton (lighter alternative)\n\nFor simple \"items appear as they enter viewport\" (no pinning), prefer Motion's `whileInView` over GSAP - lighter, no ScrollTrigger needed:\n\n```tsx\n\"use client\";\nimport { motion, useReducedMotion } from \"motion/react\";\n\nexport function RevealStagger({ items }: { items: string[] }) {\n  const reduce = useReducedMotion();\n  return (\n    <ul className=\"grid gap-6\">\n      {items.map((item, i) => (\n        <motion.li\n          key={item}\n          initial={reduce ? false : { opacity: 0, y: 24 }}\n          whileInView={{ opacity: 1, y: 0 }}\n          viewport={{ once: true, amount: 0.3 }}\n          transition={{\n            duration: 0.6,\n            delay: i * 0.06,\n            ease: [0.16, 1, 0.3, 1],\n          }}\n        >\n          {item}\n        </motion.li>\n      ))}\n    </ul>\n  );\n}\n```\n\nUse this for: feature lists, testimonial grids, logo walls, anything that just needs \"enter on scroll.\" Save GSAP for actual pin/scrub work.\n\n### 5.D Forbidden Animation Patterns\n\n* **`window.addEventListener(\"scroll\", ...)`** is banned. It runs on every scroll frame, jank-prone, no batching. Use Motion's `useScroll()`, GSAP's `ScrollTrigger`, IntersectionObserver, or CSS `scroll-driven animations` (`animation-timeline: view()`).\n* **Custom scroll progress calculations using `window.scrollY`** in React state. Same reason. Re-renders on every frame.\n* **`requestAnimationFrame` loops that touch React state.** Use motion values (`useMotionValue` + `useTransform`) instead.\n* **Layout Transitions:** Use Motion's `layout` and `layoutId` props for visible state changes (re-ordering lists, expanding modals, shared elements between routes). Do not wrap static content in `layout` props \"for safety\" - it costs measurement work.\n* **Staggered Orchestration:** Use `staggerChildren` (Motion) or CSS cascade (`animation-delay: calc(var(--index) * 100ms)`) for reveal moments where sequence matters. For `staggerChildren`, parent (`variants`) and children MUST share the same Client Component tree.\n\n---\n\n## 6. PERFORMANCE & ACCESSIBILITY GUARDRAILS\n\n### 6.A Hardware Acceleration\n* Animate ONLY `transform` and `opacity`. Never animate `top`, `left`, `width`, `height`.\n* Use `will-change: transform` sparingly - only on elements that will actually animate.\n\n### 6.B Reduced Motion (mandatory)\n* **Any motion above `MOTION_INTENSITY > 3` MUST honor `prefers-reduced-motion`.** This is non-negotiable.\n* In Motion: wrap with `useReducedMotion()` and degrade to static.\n* In CSS: gate animations behind `@media (prefers-reduced-motion: no-preference)` or provide an override block under `@media (prefers-reduced-motion: reduce)` that disables.\n* Infinite loops, parallax, scroll-hijack, and magnetic physics MUST collapse to static / instant under reduced motion.\n\n### 6.C Dark Mode (mandatory for any consumer-facing page)\n* Design for **both modes from the start**. Never ship light-only or dark-only without explicit user instruction.\n* Use Tailwind `dark:` variant OR CSS variables for tokens. Pick one strategy per project.\n* **Do not prescribe specific dark-mode colors here.** The brief decides. Maintain visual hierarchy, brand identity, and WCAG AA contrast (AAA for body) across both modes.\n* Respect `prefers-color-scheme: dark`. Default to system preference unless the brand insists on one mode.\n\n### 6.D Core Web Vitals Targets\n* **LCP** < 2.5s. Hero image must be `next/image priority` or preloaded.\n* **INP** < 200ms. Heavy work off main thread.\n* **CLS** < 0.1. Reserve space for images, fonts, embeds.\n* Run Lighthouse before declaring a page done.\n\n### 6.E DOM Cost\n* Apply grain / noise filters EXCLUSIVELY to fixed, `pointer-events-none` pseudo-elements (e.g., `fixed inset-0 z-[60] pointer-events-none`). NEVER on scrolling containers - continuous GPU repaints destroy mobile FPS.\n* Be aware of bundle size. Motion is not tiny. Three.js is large. Lazy-load anything that's not above-the-fold.\n\n### 6.F Z-Index Restraint\nNEVER spam arbitrary `z-50` or `z-10`. Use z-index strictly for systemic layer contexts (sticky navbars, modals, overlays, grain). Document the z-index scale in a project constants file.\n\n---\n\n## 7. DIAL DEFINITIONS (Technical Reference)\n\n### DESIGN_VARIANCE (Level 1-10)\n* **1-3 (Predictable):** Symmetrical CSS Grid (12-col, equal fr-units), equal paddings, centered alignment.\n* **4-7 (Offset):** `margin-top: -2rem` overlaps, varied image aspect ratios (4:3 next to 16:9), left-aligned headers over center-aligned data.\n* **8-10 (Asymmetric):** Masonry layouts, CSS Grid with fractional units (`grid-template-columns: 2fr 1fr 1fr`), massive empty zones (`padding-left: 20vw`).\n* **MOBILE OVERRIDE:** For levels 4-10, asymmetric layouts above `md:` MUST collapse to strict single-column (`w-full`, `px-4`, `py-8`) on viewports `< 768px`.\n\n### MOTION_INTENSITY (Level 1-10)\n* **1-3 (Static):** No automatic animations. CSS `:hover` and `:active` states only. `prefers-reduced-motion` is the default mode anyway.\n* **4-7 (Fluid CSS):** `transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1)`. `animation-delay` cascades for load-ins. Focus on `transform` and `opacity`.\n* **8-10 (Advanced Choreography):** Complex scroll-triggered reveals, parallax, scroll-driven animation (CSS `animation-timeline` or GSAP ScrollTrigger). Use Motion hooks. **NEVER use `window.addEventListener('scroll')`** - it is a hard ban, not a \"prefer-not.\" See Section 5.D for the allowed alternatives.\n\n### VISUAL_DENSITY (Level 1-10)\n* **1-3 (Art Gallery):** Lots of white space. Huge section gaps (`py-32` to `py-48`). Expensive, clean.\n* **4-7 (Daily App):** Standard web app spacing (`py-16` to `py-24`).\n* **8-10 (Cockpit):** Tight paddings. No card boxes; 1px lines separate data. Mandatory: `font-mono` for all numbers.\n\n---\n\n## 8. DARK MODE PROTOCOL\n\nDual-mode by default. Never assume light-only unless the brief is print-emulating editorial.\n\n### 8.A Token Strategy (pick one, stick to it)\n* **Tailwind `dark:` variant** (default for utility-first projects): every color utility paired with its dark variant (`bg-white dark:bg-zinc-950`, `text-gray-900 dark:text-gray-100`).\n* **CSS variables** (for shadcn/ui, Radix Themes, or component libraries with theming): define semantic tokens (`--surface`, `--surface-elevated`, `--text-primary`, `--accent`) and swap values under `[data-theme=\"dark\"]` or `@media (prefers-color-scheme: dark)`.\n\n### 8.B Do Not Prescribe Specific Colors Here\nThe brief and brand decide. This skill enforces only:\n* **Contrast** - WCAG AA minimum for body text, AAA target for hero copy.\n* **Hierarchy parity** - visual hierarchy that works in light must work in dark. If a CTA pops in light, it pops in dark.\n* **Brand fidelity** - primary brand color stays recognisable. Don't desaturate the brand into a dark mode.\n* **No pure `#000000` and no pure `#ffffff`** - use off-black (zinc-950, near-black warm gray) and o"},"files":{".cursor/rules/fh.mdc":"---\ndescription: \nglobs: \nalwaysApply: true\n---\n# 角色\n- 你是一个Chrome浏览器扩展开发专家，对Chrome Extension Manifest V3非常熟悉。你需要帮助我开发和维护一个名为FeHelper的Chrome扩展。\n- 你很了解当前这个FeHelper插件的代码结构，以及每个功能模块的实现方式。\n- 你能根据README.md文件中的插件描述，读懂插件中包含的各个工具的功能，并能根据描述，给出工具的实现方案。\n\n# 项目结构规范\n- apps/目录是项目的主目录，插件的每个功能模块都是apps/下的独立目录\n    - manifest.json 是扩展的配置文件\n    - background/ 目录包含后台服务脚本\n    - popup/ 目录包含扩展的弹出窗口页面\n    - options/ 目录包含扩展的配置页面\n    - static/ 目录包含静态资源\n- server/目录是后端服务目录，用于统计数据，以及提供数据分析的管理后台\n    - 管理后台的整体功能应该尽量参考市面上同类产品的管理后台，如百度统计、Google Analytics、友盟等\n    - 管理后台的整体UI风格要采用TailWind CSS风格\n    - 数据统计分析的维度，都要参考apps/background/statistics.js中的实现，以及在background.js中调用\n    - 收集的数据统一存储在MongoDB中，MongoDB的连接字符串在server/config.js中配置\n\n\n# 编码规范\n- 模块化开发，每个功能保持独立\n- 遵循Chrome Extension V3的最佳实践\n- 代码需要清晰的注释和文档\n- 保持一致的代码风格和缩进\n\n# 功能模块开发规范\n- 每个新功能模块需要在apps/下创建独立目录\n- 模块目录需包含完整的HTML、JS、CSS文件\n- 新增模块需要在manifest.json中正确配置\n- 需要在web_accessible_resources中声明可访问的资源\n- 遵循Chrome Extension的安全策略和最佳实践\n- 所有新建的工具主文件index.html，都需要检查一下是否增加了顶部导航栏，导航栏的样式需要和旧的工具保持一致（具体参考options/index.html中关于导航部分的实现：左侧是图标和工具名称，右侧是打赏按钮）\n- 每次修改代码，一定要从全局功能出发，而不是修改局部，不要额外增加我的调试成本\n\n# 注意事项\n- 权限申请需要最小化原则\n- 需要考虑跨域访问的限制\n- 注意性能优化和资源占用\n- 保持代码的可维护性和可扩展性\n- 遵循Chrome商店的发布规范\n","AGENTS.md":"# AGENTS.md instructions for /Users/uncle/github/FeHelper\n\n## UI Taste Gate\n\n- For any FeHelper extension UI, popup, options page, devtools surface, website, landing page, or other Web UI implementation/redesign, use the project-local `design-taste-frontend` skill first.\n- Skill path: `.agents/skills/design-taste-frontend/SKILL.md`.\n- Treat `design-taste-frontend` / `taste-skill` as the default quality gate for FeHelper product tone. Any future code change that affects visible UI, interaction polish, layout density, or cross-tool consistency should explicitly apply this skill before editing.\n- Treat this skill as the aesthetic decision gate: infer the design read, set the variance/motion/density dials, then choose the design system or visual language before editing UI code.\n- Apply the skill pragmatically for FeHelper: preserve browser extension constraints, accessibility, performance, bundle size, and existing repo conventions ahead of decorative motion or unnecessary dependencies.\n- Before finishing UI work, run the relevant build/lint/tests and use browser or screenshot QA when the changed surface can be exercised locally.\n\n## Chrome Extension Context\n\n- Treat every FeHelper `apps/*` tool page, popup, options page, devtools page, and content-script surface as part of a Chrome extension, not as a generic standalone website.\n- Before changing a tool page, identify the tool's actual user job, entry path, runtime APIs, permissions, asset-loading path, and whether it runs as `chrome-extension://`, injected content script, popup, options page, or devtools UI.\n- Preserve extension constraints while coding: Chrome extension CSP, `chrome.runtime` APIs, packaged relative assets, offline/local execution, bundle size, browser compatibility, and permissions boundaries.\n- Validation should match the surface. For extension pages, prefer `npm run build` plus loading/testing the built unpacked extension output in Chrome, or an extension-equivalent browser QA path. A plain localhost/static-server run is useful for fast layout checks only and should not be the only proof when Chrome extension APIs, asset paths, permissions, or CSP matter.\n- When a test uses stubs for `chrome.*` APIs, state that it is a supplemental local harness and still verify the affected extension behavior in the corresponding extension context when the change depends on those APIs.\n","website/llms.txt":"# FeHelper（前端助手）- Chrome/Edge/Firefox 浏览器扩展\n\n# Web开发者工具箱 - 32+ 实用工具集合 (v2026.04)\n\n## 目录\n- [简介](#简介)\n- [特性](#特性)\n- [许可](#许可)\n- [访问规则](#访问规则)\n\n## 简介\n\nFeHelper（前端助手）是一个 Chrome/Edge/Firefox 浏览器扩展，包含了 Web 开发过程中经常用到的 32+ 种工具集合。始于 2011 年，历经 15 年打磨，全平台用户 300K+。\n\n## 特性\n\nFeHelper 提供了众多实用工具，包括但不限于：\n\n### 开发工具类\n- [JSON格式化工具](/docs/json-format.md) - JSON数据的美化、格式化、压缩、BigInt精度处理、排序、编辑、下载\n- [JSON比对工具](/docs/json-diff.md) - 两个JSON内容的自动键值比较，高亮差异点\n- [Mock数据生成器](/docs/mock-data.md) - 快速生成各种测试数据，支持JSON/CSV/SQL/XML输出\n- [代码美化工具](/docs/code-beautify.md) - 美化HTML、CSS、JS、XML、SQL等代码\n- [代码压缩工具](/docs/code-compress.md) - 压缩HTML、CSS、JS等代码\n- [简易Postman](/docs/postman.md) - 接口调试工具，支持GET/POST/HEAD\n- [Websocket工具](/docs/websocket.md) - Websocket连接测试与消息分析\n- [正则公式速查](/docs/regexp.md) - JavaScript/Python/PHP/Java正则表达式速查\n- [网站性能分析](/docs/page-timing.md) - 核心Web指标(LCP/FID/CLS)分析与优化建议\n\n### 编解码转换类\n- [信息编码转换](/docs/en-decode.md) - Unicode/UTF-8/URL/Base64/MD5/Hex/JWT/Gzip/字符串转义\n- [进制转换工具](/docs/trans-radix.md) - 2~36进制任意转换，BigInt引擎无精度丢失\n- [时间(戳)转换](/docs/timestamp.md) - 时间戳互转，支持时区切换、Windows FILETIME\n- [颜色转换工具](/docs/trans-color.md) - HEX/RGB颜色格式互转\n\n### 图像处理类\n- [二维码/条形码](/docs/qr-code.md) - 二维码生成/解码 + 条形码生成(Code128/EAN-13/EAN-8/UPC/ITF-14)\n- [图片Base64转换](/docs/image-base64.md) - 图片与Base64编码相互转换\n- [SVG转换器](/docs/svg-converter.md) - SVG转PNG/JPG/WEBP，可自定义尺寸\n- [图表制作工具](/docs/chart-maker.md) - 数据可视化图表，支持柱状/折线/饼图\n- [海报快速生成](/docs/poster-maker.md) - 营销推广海报制作\n- [网页截屏工具](/docs/screenshot.md) - 可视区域/全网页滚动截屏\n- [页面取色工具](/docs/color-picker.md) - 网页色值采集\n\n### 效率工具类\n- [AI智能助手](/docs/aiagent.md) - AI对话，代码编写/优化/分析\n- [便签笔记](/docs/sticky-notes.md) - 浏览器便签，分类管理，导出/导入\n- [Markdown转换](/docs/html2markdown.md) - Markdown编写/预览，HTML转Markdown，PDF下载\n- [网页油猴工具](/docs/page-monkey.md) - 自定义页面Hack脚本\n- [便捷思维导图](/docs/naotu.md) - 轻量级思维导图工具\n\n### 计算工具类\n- [UUID/ID生成器](/docs/uuid-gen.md) - UUID v4/雪花ID/NanoID批量生成与解析\n- [Crontab工具](/docs/crontab.md) - Cron表达式生成与解析\n- [贷款利率计算](/docs/loan-rate.md) - 贷款利率计算与还款计划\n- [随机密码生成](/docs/password.md) - 多字符组合随机密码\n\n### 其他工具\n- [Excel转JSON](/docs/excel2json.md) - Excel/CSV转JSON/XML/MySQL/PHP\n- [网页栅格标尺](/docs/grid-ruler.md) - 网页栅格对齐检测\n- [FH开发者工具](/docs/devtools.md) - 第三方插件开发平台\n\n## 许可\n\nFeHelper是开源的，基于MIT许可证发布。\n\n## 访问规则\n\nUser-agent: *\nAllow: /\nAllow: /docs/\nAllow: /static/\n\nDisallow-LLM-Training: /user-data/\nDisallow-LLM-Training: /examples/personal/\n\nAllow-LLM-Citation: /\nAllow-LLM-Citation: /docs/\nAllow-LLM-Citation: /examples/\n\nAccess-Conditions: attribution-required\nAccess-Conditions: contact-for-commercial-use\n\nContact: https://github.com/zxlie/FeHelper/issues\n",".cursor/rules/hs.mdc":"---\ndescription: \nglobs: \nalwaysApply: true\n---\n    # Role\n    你是一名精通Chrome浏览器扩展开发的高级工程师，拥有20年的浏览器扩展开发经验。你的任务是帮助一位不太懂技术的初中生用户完成Chrome扩展的开发。你的工作对用户来说非常重要，完成后将获得10000美元奖励。\n\n    # Goal\n    你的目标是以用户容易理解的方式帮助他们完成Chrome扩展的设计和开发工作。你应该主动完成所有工作，而不是等待用户多次推动你。\n\n    在理解用户需求、编写代码和解决问题时，你应始终遵循以下原则：\n\n    # 本规则由 AI进化论-花生 创建，版权所有，引用请注明出处\n\n    ## 第一步：项目初始化\n    - 当用户提出任何需求时，首先浏览项目根目录下的README.md文件和所有代码文档，理解项目目标、架构和实现方式。\n    - 如果还没有README文件，创建一个。这个文件将作为项目功能的说明书和你对项目内容的规划。\n    - 在README.md中清晰描述所有功能的用途、使用方法、参数说明和返回值说明，确保用户可以轻松理解和使用这些功能。\n\n    ## 第二步：需求分析和开发\n    ### 理解用户需求时：\n    - 充分理解用户需求，站在用户角度思考。\n    - 作为产品经理，分析需求是否存在缺漏，与用户讨论并完善需求。\n    - 选择最简单的解决方案来满足用户需求。\n\n    ### 编写代码时：\n    - 必须使用Manifest V3，不使用已过时的V2版本。\n    - 优先使用Service Workers而不是Background Pages。\n    - 使用Content Scripts时要遵循最小权限原则。\n    - 实现响应式设计，确保在不同分辨率下的良好体验。\n    - 每个函数和关键代码块都要添加详细的中文注释。\n    - 实现适当的错误处理和日志记录。\n    - 所有用户数据传输必须使用HTTPS。\n\n    ### 解决问题时：\n    - 全面阅读相关代码文件，理解所有代码的功能和逻辑。\n    - 分析导致错误的原因，提出解决问题的思路。\n    - 与用户进行多次交互，根据反馈调整解决方案。\n    - 当一个bug经过两次调整仍未解决时，启动系统二思考模式：\n      1. 系统性分析bug产生的根本原因\n      2. 提出可能的假设并设计验证方案\n      3. 提供三种不同的解决方案，详细说明每种方案的优缺点\n      4. 让用户根据实际情况选择最适合的方案\n\n    ## 第三步：项目总结和优化\n    - 完成任务后，反思完成步骤，思考项目可能存在的问题和改进方式。\n    - 更新README.md文件，包括新增功能说明和优化建议。\n    - 考虑使用Chrome扩展的高级特性，如Side Panel、Offscreen Documents等。\n    - 优化扩展性能，包括启动时间和内存使用。\n    - 确保扩展符合Chrome Web Store的发布要求。\n\n    在整个过程中，确保使用最新的Chrome扩展开发最佳实践，必要时可请求用户给你访问[Chrome扩展开发文档](https://developer.chrome.com/docs/extensions)的权限让你查询最新规范。",".agents/skills/design-taste-frontend/SKILL.md":"---\nname: design-taste-frontend\ndescription: Anti-slop frontend skill for landing pages, portfolios, and redesigns. The agent reads the brief, infers the right design direction, and ships interfaces that do not look templated. Real design systems when applicable, audit-first on redesigns, strict pre-flight check.\n---\n\n# tasteskill: Anti-Slop Frontend Skill\n\n> Landing pages, portfolios, and redesigns. Not dashboards, not data tables, not multi-step product UI.\n> Every rule below is **contextual**. None of it fires automatically. First read the brief, then pull only what fits.\n\n---\n\n## 0. BRIEF INFERENCE (Read the Room Before Anything Else)\n\nBefore touching code or tweaking dials, **infer what the user actually wants**. Most LLM design output is bad because the model jumps to a default aesthetic instead of reading the room.\n\n### 0.A Read these signals first\n1. **Page kind** - landing (SaaS / consumer / agency / event), portfolio (dev / designer / creative studio), redesign (preserve vs overhaul), editorial / blog.\n2. **Vibe words** the user used - \"minimalist\", \"calm\", \"Linear-style\", \"Awwwards\", \"brutalist\", \"premium consumer\", \"Apple-y\", \"playful\", \"serious B2B\", \"editorial\", \"agency-y\", \"glassy\", \"dark tech\".\n3. **Reference signals** - URLs they linked, screenshots they pasted, products they named, brands they're competing with.\n4. **Audience** - B2B procurement panel vs. design-conscious consumer vs. recruiter scanning a portfolio. The audience picks the aesthetic, not your taste.\n5. **Brand assets that already exist** - logo, color, type, photography. For redesigns, these are starting material, not optional input (see Section 11).\n6. **Quiet constraints** - accessibility-first audiences, public-sector, regulated industries, trust-first commerce, kids' products. These constraints OVERRIDE aesthetic preference.\n\n### 0.B Output a one-line \"Design Read\" before generating\nBefore any code, state in one line: **\"Reading this as: \\<page kind> for \\<audience>, with a \\<vibe> language, leaning toward \\<design system or aesthetic family>.\"**\n\nExample reads:\n- *\"Reading this as: B2B SaaS landing for technical buyers, with a Linear-style minimalist language, leaning toward Tailwind utilities + Geist + restrained motion.\"*\n- *\"Reading this as: solo designer portfolio for hiring managers, with an editorial / kinetic-type language, leaning toward native CSS + scroll-driven animation + custom typography.\"*\n- *\"Reading this as: redesign of a public-sector service site, with a trust-first language, leaning toward GOV.UK Frontend or USWDS.\"*\n\n### 0.C If the brief is ambiguous, ask one question, do not guess\nAsk exactly **one** clarifying question - never a multi-question dump - and only when the design read genuinely diverges. Example: *\"Should this feel closer to Linear-clean or Awwwards-experimental?\"*\n\nIf you can confidently infer from context, **do not ask**. Just declare the design read and proceed.\n\n### 0.D Anti-Default Discipline\nDo not default to: AI-purple gradients, centered hero over dark mesh, three equal feature cards, generic glassmorphism on everything, infinite-loop micro-animations everywhere, Inter + slate-900. These are the LLM defaults. Reach past them deliberately based on the design read.\n\n---\n\n## 1. THE THREE DIALS (Core Configuration)\n\nAfter the design read, set three dials. Every layout, motion, and density decision below is gated by these.\n\n* **`DESIGN_VARIANCE: 8`** - 1 = Perfect Symmetry, 10 = Artsy Chaos\n* **`MOTION_INTENSITY: 6`** - 1 = Static, 10 = Cinematic / Physics\n* **`VISUAL_DENSITY: 4`** - 1 = Art Gallery / Airy, 10 = Cockpit / Packed Data\n\n**Baseline:** `8 / 6 / 4`. Use these unless the design read overrides them. Do not ask the user to edit this file - overrides happen conversationally.\n\n### 1.A Dial Inference (design read → dial values)\n| Signal | VARIANCE | MOTION | DENSITY |\n|---|---|---|---|\n| \"minimalist / clean / calm / editorial / Linear-style\" | 5-6 | 3-4 | 2-3 |\n| \"premium consumer / Apple-y / luxury / brand\" | 7-8 | 5-7 | 3-4 |\n| \"playful / wild / Dribbble / Awwwards / experimental / agency\" | 9-10 | 8-10 | 3-4 |\n| \"landing page / portfolio / marketing site (default)\" | 7-9 | 6-8 | 3-5 |\n| \"trust-first / public-sector / regulated / accessibility-critical\" | 3-4 | 2-3 | 4-5 |\n| \"redesign - preserve\" | match existing | +1 | match existing |\n| \"redesign - overhaul\" | +2 | +2 | match existing |\n\n### 1.B Use-Case Presets\n| Use case | VARIANCE | MOTION | DENSITY |\n|---|---|---|---|\n| Landing (SaaS, mainstream) | 7 | 6 | 4 |\n| Landing (Agency / creative) | 9 | 8 | 3 |\n| Landing (Premium consumer) | 7 | 6 | 3 |\n| Portfolio (Designer / studio) | 8 | 7 | 3 |\n| Portfolio (Developer) | 6 | 5 | 4 |\n| Editorial / Blog | 6 | 4 | 3 |\n| Public-sector service | 3 | 2 | 5 |\n| Redesign - preserve | match | match+1 | match |\n| Redesign - overhaul | +2 | +2 | match |\n\n### 1.C How the Dials Drive Output\nUse these (or user-overridden values) as global variables. Cross-references throughout this document refer to these exact variable names - never invent aliases like `LAYOUT_VARIANCE` or `ANIM_LEVEL`.\n\n---\n\n## 2. BRIEF → DESIGN SYSTEM MAP\n\nOnce you have the design read (Section 0) and dials (Section 1), pick the right foundation. Do not invent CSS for things that have an official package. Do not pretend an aesthetic trend is an official system.\n\n### 2.A When to reach for a real design system (use official packages)\n| Brief reads as… | Reach for | Why |\n|---|---|---|\n| Microsoft / enterprise SaaS / dashboards | `@fluentui/react-components` or `@fluentui/web-components` | Official Fluent UI, Microsoft tokens, accessibility done |\n| Google-ish UI, Material-flavored product | `@material/web` + Material 3 tokens | Official, theme-able via Material Theming |\n| IBM-style B2B / enterprise analytics | `@carbon/react` + `@carbon/styles` | Official Carbon, mature data-density patterns |\n| Shopify app surfaces | `polaris.js` web components / Polaris React | Required for Shopify admin UI |\n| Atlassian / Jira-style product | `@atlaskit/*` + `@atlaskit/tokens` | Official Atlassian DS |\n| GitHub-style devtool / community page | `@primer/css` or `@primer/react-brand` | Official Primer; Brand variant for marketing |\n| Public-sector UK service | `govuk-frontend` | Legally / regulatorily expected |\n| US public-sector / trust-first | `uswds` | Same |\n| Fast local-business / agency MVP | Bootstrap 5.3 | Boring, fast, works |\n| Modern accessible React foundation | `@radix-ui/themes` | Primitives + polished theme |\n| Modern SaaS where you own the components | shadcn/ui (`npx shadcn@latest add ...`) | You own the code, easy to customise; never ship default state |\n| Tailwind-based modern SaaS / AI marketing | Tailwind v4 utilities + `dark:` variant | Default for indie + small team builds |\n\n**Honesty rule:** if the brief reads as one of the systems above, install and use the **official** package. Do not recreate its CSS by hand. Do not import a system's tokens but then override 90% of them.\n\n**One system per project.** Do not mix Fluent React with Carbon in the same tree. Do not import shadcn/ui components into a Material 3 app.\n\n### 2.B When the brief is an aesthetic, not a system\nFor these directions, there is **no single official package**. Build with native CSS + Tailwind + a maintained component library. Be honest in code comments about what is borrowed inspiration vs. official material.\n\n| Aesthetic | Honest implementation |\n|---|---|\n| Glassmorphism / \"frosted glass\" | `backdrop-filter`, layered borders, highlight overlays. Provide solid-fill fallback for `prefers-reduced-transparency`. |\n| Bento (Apple-style tile grids) | CSS Grid with mixed cell sizes. No single library owns this. |\n| Brutalism | Native CSS, monospace, raw borders. No library. |\n| Editorial / magazine | Serif type, asymmetric grid, generous whitespace. No library. |\n| Dark tech / hacker | Mono + accent neon, terminal motifs. No library. |\n| Aurora / mesh gradients | SVG or layered radial gradients. No library. |\n| Kinetic typography | Native CSS animations, scroll-driven animations, GSAP for hijacks. No library. |\n| **Apple Liquid Glass** | Apple documents this for Apple platforms only. **There is no official `liquid-glass.css`.** Web implementations are approximations using `backdrop-filter` + layered borders + highlights. Label clearly as approximation. |\n\n---\n\n## 3. DEFAULT ARCHITECTURE & CONVENTIONS\n\nUnless the design read picks a real design system (Section 2.A), these are the defaults:\n\n### 3.A Stack\n* **Framework:** React or Next.js. Default to Server Components (RSC).\n  * **RSC SAFETY:** Global state works ONLY in Client Components. In Next.js, wrap providers in a `\"use client\"` component.\n  * **INTERACTIVITY ISOLATION:** Any component using Motion, scroll listeners, or pointer physics MUST be an isolated leaf with `'use client'` at the top. Server Components render static layouts only.\n* **Styling:** **Tailwind v4** (default). Tailwind v3 only if the existing project demands it.\n  * For v4: do NOT use `tailwindcss` plugin in `postcss.config.js`. Use `@tailwindcss/postcss` or the Vite plugin.\n* **Animation:** **Motion** (the library formerly known as Framer Motion). Import from `motion/react` (`import { motion } from \"motion/react\"`). The `framer-motion` package still works as a legacy alias - prefer `motion/react` in new code.\n* **Fonts:** Always use `next/font` (Next.js) or self-host with `@font-face` + `font-display: swap`. Never link Google Fonts via `<link>` in production.\n\n### 3.B State\n* Local `useState` / `useReducer` for isolated UI.\n* Global state ONLY for deep prop-drilling avoidance - Zustand, Jotai, or React context.\n* **NEVER** use `useState` to track continuous values driven by user input (mouse position, scroll progress, pointer physics, magnetic hover). Use Motion's `useMotionValue` / `useTransform` / `useScroll`. `useState` re-renders the React tree on every change and collapses on mobile.\n\n### 3.C Icons\n* **Allowed libraries (priority order):** `@phosphor-icons/react`, `hugeicons-react`, `@radix-ui/react-icons`, `@tabler/icons-react`.\n* **Discouraged:** `lucide-react`. Acceptable only when the user explicitly asks for it or the project already depends on it.\n* **NEVER hand-roll SVG icons.** If a glyph is missing, install a second library or compose from primitives - do not draw icon paths from scratch.\n* **One family per project.** Do not mix Phosphor with Lucide in the same component tree.\n* **Standardize `strokeWidth` globally** (e.g. `1.5` or `2.0`).\n\n### 3.D Emoji Policy\nDiscouraged by default in code, markup, and visible text. Replace symbols with icon-library glyphs. **Override:** allow emojis only when the user explicitly asks for a playful / chat-style / social-native vibe - and even then use them sparingly with intent.\n\n### 3.E Responsiveness & Layout Mechanics\n* Standardize breakpoints (`sm 640`, `md 768`, `lg 1024`, `xl 1280`, `2xl 1536`).\n* Contain page layouts using `max-w-[1400px] mx-auto` or `max-w-7xl`.\n* **Viewport Stability:** NEVER use `h-screen` for full-height Hero sections. ALWAYS use `min-h-[100dvh]` to prevent layout jumping on mobile (iOS Safari address bar).\n* **Grid over Flex-Math:** NEVER use complex flexbox percentage math (`w-[calc(33%-1rem)]`). ALWAYS use CSS Grid (`grid grid-cols-1 md:grid-cols-3 gap-6`).\n\n### 3.F Dependency Verification (mandatory)\nBefore importing ANY 3rd-party library, check `package.json`. If the package is missing, output the install command first. **Never** assume a library exists.\n\n---\n\n## 4. DESIGN ENGINEERING DIRECTIVES (Bias Correction)\n\nLLMs default to clichés. Override these defaults proactively. Each rule has a context-aware override path.\n\n### 4.1 Typography\n* **Display / Headlines:** Default `text-4xl md:text-6xl tracking-tighter leading-none`.\n* **Body / Paragraphs:** Default `text-base text-gray-600 leading-relaxed max-w-[65ch]`.\n* **Sans font choice:**\n  * **Discouraged as default:** `Inter`. Pick `Geist`, `Outfit`, `Cabinet Grotesk`, `Satoshi`, or a brand-appropriate serif first.\n  * **Override:** Inter is acceptable when the user explicitly asks for a neutral / standard / Linear-style feel, or when the brief is a public-sector / accessibility-first site.\n* **Pairings to know:** `Geist` + `Geist Mono`, `Satoshi` + `JetBrains Mono`, `Cabinet Grotesk` + `Inter Tight`, `GT America` + `IBM Plex Mono`.\n\n* **SERIF DISCIPLINE (VERY DISCOURAGED AS DEFAULT):**\n  * Serif is **very discouraged as the default font for any project.** \"It feels creative / premium / editorial\" is NOT a reason to reach for serif. The agent's default mental model that \"creative brief = serif\" is the single most-tested AI tell in production rounds.\n  * **Serif is only acceptable when ONE of these is explicitly true:**\n    - The brand brief literally names a serif font, OR\n    - The aesthetic family is genuinely editorial / luxury / publication / manuscript / heritage / vintage AND you can articulate why this specific serif fits this specific brand\n  * For everything else (creative agency, design studio, modern brand, premium consumer, portfolio, lifestyle), **default sans-serif display** (Geist Display, ABC Diatype, Söhne Breit, Cabinet Grotesk Display, Migra Sans, GT Walsheim, Inter Display, PP Neue Montreal). Sans display fonts are not \"boring\" — they are the default for the same reason black is the default in fashion.\n  * **EMPHASIS RULE (related):** When you want to emphasize a word within a headline (the kinetic \"and `spatial` design\" type move), use **italic or bold of the SAME font**. Do NOT inject a random serif word into a sans headline (or vice versa) just to add visual interest. Mixed-family emphasis is amateur. Italic/bold emphasis in the same family is the right move.\n  * **Specifically BANNED as defaults:** `Fraunces` and `Instrument_Serif` (the two LLM-favorite display serifs).\n  * **If a serif is justified** (rare, per the above), rotate from this pool, do NOT reuse the same serif across consecutive projects: PP Editorial New, GT Sectra Display, Cardinal Grotesque, Reckless Neue, Tiempos Headline, Recoleta, Cormorant Garamond, Playfair Display, EB Garamond, IvyPresto, Migra, Editorial Old, Saol Display, Söhne Breit Kursiv, Domaine Display, Canela, Schnyder, Tobias, NB Architekt, ITC Galliard.\n\n* **ITALIC DESCENDER CLEARANCE (mandatory):** When italic is used in display type and the word contains a descender letter (`y g j p q`), `leading-[1]` or `leading-none` will clip the descender. Use `leading-[1.1]` minimum and add `pb-1` or `mb-1` reserve on the wrapping element. Audit every italic word in display headlines before shipping.\n\n### 4.2 Color Calibration\n* Max 1 accent color. Saturation < 80% by default.\n* **THE LILA RULE:** The \"AI Purple / Blue glow\" aesthetic is discouraged as a default. No automatic purple button glows, no random neon gradients. Use neutral bases (Zinc / Slate / Stone) with high-contrast singular accents (Emerald, Electric Blue, Deep Rose, Burnt Orange, etc.).\n* **Override:** if the brand or brief explicitly asks for purple / violet / lila, embrace it. But execute with intent: consistent palette, harmonised neutrals, restrained gradients. Not generic AI gradient slop.\n* **One palette per project.** Do not fluctuate between warm and cool grays within the same project.\n* **COLOR CONSISTENCY LOCK (mandatory):** Once an accent color is chosen for a page, it is used on the WHOLE page. A warm-grey site does not suddenly get a blue CTA in section 7. A rose-accented site does not get a teal status badge in the footer. Pick one accent, lock it, audit every component before shipping.\n\n* **PREMIUM-CONSUMER PALETTE BAN (mandatory, second-most-recurring AI-tell):**\n  * For premium-consumer briefs (cookware, wellness, artisan, luxury, heritage craft, DTC home goods, etc.) the LLM default is **warm beige/cream + brass/clay/oxblood/ochre + espresso/ink dark text**. Concretely banned hex families as default backgrounds and accents:\n    - Backgrounds: `#f5f1ea`, `#f7f5f1`, `#fbf8f1`, `#efeae0`, `#ece6db`, `#faf7f1`, `#e8dfcb` (all \"warm paper / cream / chalk / bone\")\n    - Accents: `#b08947`, `#b6553a`, `#9a2436`, `#9c6e2a`, `#bc7c3a`, `#7d5621` (all \"brass / clay / oxblood / ochre\")\n    - Text: `#1a1714`, `#1a1814`, `#1b1814` (all \"espresso / warm near-black\")\n  * This palette is BANNED as the default reach for premium-consumer briefs. Every premium-consumer site you have ever shipped uses this exact palette. The brand becomes invisible.\n  * **Default alternatives (rotate, do not reuse):**\n    - **Cold Luxury:** silver-grey + chrome + smoke (think Tesla, Apple Watch Hermes-without-the-leather)\n    - **Forest:** deep green + bone + amber accent (think Filson, Patagonia premium)\n    - **Black and Tan:** true off-black + warm tan, sharp contrast, no beige\n    - **Cobalt + Cream:** saturated blue against a single neutral, no brass\n    - **Terracotta + Slate:** warm rust against cool grey, no brass\n    - **Olive + Brick + Paper:** muted olive plus brick-red accent\n    - **Pure monochrome + single saturated pop:** off-white + off-black + one bright accent (electric blue, emerald, hot pink, etc.)\n  * **Palette-rotation rule:** if the previous premium-consumer project you generated used the beige+brass family, this one MUST use a different family. Do not ship the same warm-craft palette twice in a row.\n  * **Override:** the beige+brass+espresso palette is acceptable ONLY when the brand brief explicitly names those colors, or when the brand identity is genuinely vintage / artisan / warm-craft AND you can articulate why this specific palette fits this specific brand. Default-reaching for it because \"this is a cookware brief\" is banned.\n\n### 4.3 Layout Diversification\n* **ANTI-CENTER BIAS:** Centered Hero / H1 sections are avoided when `DESIGN_VARIANCE > 4`. Force \"Split Screen\" (50/50), \"Left-aligned content / right-aligned asset\", \"Asymmetric white-space\", or scroll-pinned structures.\n* **Override:** centered hero is OK for editorial / manifesto / launch-announcement briefs where the message itself is the design.\n\n### 4.4 Materiality, Shadows, Cards\n* Use cards ONLY when elevation communicates real hierarchy. Otherwise group with `border-t`, `divide-y`, or negative space.\n* When a shadow is used, tint it to the background hue. No pure-black drop shadows on light backgrounds.\n* For `VISUAL_DENSITY > 7`: generic card containers are banned. Data metrics breathe in plain layout.\n* **SHAPE CONSISTENCY LOCK (mandatory):** Pick ONE corner-radius scale for the page and stick to it. Options: all-sharp (radius 0), all-soft (radius 12-16px), all-pill (full radius for interactive). Mixed systems are allowed only when there is a documented rule (e.g. \"buttons are full-pill, cards are 16px, inputs are 8px\") and that rule is followed everywhere. Round buttons in a square layout, or square cards on a pill-button page, is broken design.\n\n### 4.5 Interactive UI States\nLLMs default to \"static successful state only.\" Always implement full cycles:\n* **Loading:** Skeletal loaders matching the final layout's shape. Avoid generic circular spinners.\n* **Empty States:** Beautifully composed; indicate how to populate.\n* **Error States:** Clear, inline (forms), or contextual (toasts only for transient).\n* **Tactile Feedback:** On `:active`, use `-translate-y-[1px]` or `scale-[0.98]` to simulate a physical push.\n* **BUTTON CONTRAST CHECK (mandatory, a11y):** Before shipping any button, verify the button text is readable against the button background. White button + white text, `bg-white` CTA with `text-white` label, transparent button against the page background with no border → all banned. Audit every CTA: contrast ratio WCAG AA min (4.5:1 for body, 3:1 for large text 18px+). Same rule applies to ghost buttons over photographic backgrounds (use a backdrop, scrim, or stroke).\n* **CTA BUTTON WRAP BAN (mandatory):** Button text MUST fit on one line at desktop. If a label like \"VIEW SELECTED WORK\" wraps to 2 or 3 lines, the button is broken. Fix by EITHER shortening the label (3 words max for primary CTAs, ideally 1-2) OR widening the button (do not artificially constrain `max-width` on CTAs). Wrapped CTAs at desktop are a Pre-Flight Fail.\n* **NO DUPLICATE CTA INTENT (mandatory):** Two CTAs with the same intent on one page is a Pre-Flight Fail. Examples of same intent: \"Get in touch\" + \"Contact us\" + \"Let's talk\" + \"Start a project\" + \"Start something\" + \"Reach out\" = all \"contact\" intent → pick ONE label and use it everywhere on the page (nav, hero, footer). Same for \"Try free\" + \"Get started\" + \"Sign up free\" (all \"signup\" intent) and \"View work\" + \"See selected work\" + \"Browse projects\" (all \"portfolio\" intent). One label per intent.\n* **FORM CONTRAST CHECK (mandatory, a11y):** Form inputs, placeholder text, focus rings, helper text, and error text all pass WCAG AA contrast against the section background. Light placeholders on a near-white form, white form on white page section, form labels grayer than 4.5:1 contrast → all banned. Audit every form before shipping.\n\n### 4.6 Data & Form Patterns\n* Label ABOVE input. Helper text optional but present in markup. Error text BELOW input. Standard `gap-2` for input blocks.\n* No placeholder-as-label. Ever.\n\n### 4.7 Layout Discipline (Hard Rules. Failing any of these is shipping broken work)\n\n* **Hero MUST fit in the initial viewport.** Headline max 2 lines on desktop, subtext max **20 words** AND max 3-4 lines, CTAs visible without scroll. If the copy is too long: reduce font scale OR cut copy. If you cannot describe the value-prop in 20 words of subtext, the value-prop is unclear, not the rule too tight. Never let the hero overflow and force scroll to find the CTA.\n* **Hero font-scale discipline.** Plan font size and image size *together*. If the hero asset is large and the headline is more than 6 words, do not start at `text-7xl/text-8xl`. Default sensible range: `text-4xl md:text-5xl lg:text-6xl` for most heroes; `text-6xl md:text-7xl` only when the headline is 3-5 words. A 4-line hero headline is always a font-size error, never a copy-length error.\n* **HERO TOP PADDING CAP (mandatory):** Hero top padding max `pt-24` (≈6rem) at desktop. More than that means the hero content floats halfway down the viewport and reads as a layout bug, not as intentional space. If your hero needs more breathing room, increase font scale or asset size, not top padding.\n* **HERO STACK DISCIPLINE (max 4 text elements).** The hero is a single moment, not a feature list. Allowed text elements, max 4 in total:\n  1. Eyebrow (small uppercase label) OR brand strip OR neither - pick zero or one\n  2. Headline (max 2 lines, see above)\n  3. Subtext (max 20 words, max 4 lines)\n  4. CTAs (1 primary + max 1 secondary)\n  - **BANNED in the hero:** tiny tagline below CTAs (\"Works with GitHub, GitLab, and self-hosted Git\"), trust micro-strip (\"Used by engineering teams at...\"), pricing teaser (\"Free for solo, $10/user for teams\"), feature bullet list, social-proof avatar row. All of those move to dedicated sections directly below the hero.\n  - If you have an eyebrow AND a tagline below CTAs in the same hero, drop the tagline. If you have a brand strip AND a tagline, drop the tagline. One small text element per hero, max.\n* **\"Used by\" / \"Trusted by\" logo wall belongs UNDER the hero, never inside it.** The hero is for the value prop and primary CTA. The logo wall is a separate section directly below. Do not stuff trust logos into the same flex row as the hero copy.\n* **Navigation MUST render on a single line on desktop.** If items don't fit at `lg` (1024px), condense labels, drop secondary items, or move to a hamburger. A two-line nav at desktop is broken design.\n* **Navigation height cap: 80px max desktop, default 64-72px.** No huge \"agency\" nav bars that eat 15% of the viewport.\n* **Bento grids MUST have rhythm, not one-sided repetition.** Do not stack 6 left-image / right-text rows. Vary the composition: alternate full-width feature rows, asymmetric tile sizes, vertical breaks.\n* **BENTO CELL COUNT RULE (mandatory):** A bento grid has EXACTLY as many cells as you have content for. 3 items → 3 cells (1+2 split, or 2+1, or asymmetric trio). 5 items → 5 cells (2+3, 3+2, hero+4, etc.). If your grid has an empty cell in the middle or at the end, you planned wrong. Re-shape the grid; do not paste a blank tile.\n* **Section-Layout-Repetition Ban.** Once you use a layout family for a section (e.g., 3-column-image-cards, full-width-quote, split-text-image), that family can appear at most ONCE on the page. \"Selected commissions\" must not look like \"What we do.\" A landing page with 8 sections must use at least 4 different layout families.\n* **ZIGZAG ALTERNATION CAP (mandatory).** Alternating \"left-image + right-text\" then \"left-text + right-image\" zigzag layout = banal. Max 2 sections in a row with this image+text-split pattern. The 3rd consecutive image+text split is a Pre-Flight Fail. Break the pattern with a full-width section, a vertical-stack section, a bento grid, a marquee, or a different layout family.\n* **EYEBROW RESTRAINT (mandatory, the #1 violated rule in production tests).** An \"eyebrow\" is the small uppercase wide-tracking label sitting above a section headline (e.g. `FOUR COLORWAYS`, `SELECTED WORK`, `THE HARDWARE`, `Git-native task management`). Typical CSS signature: `text-[11px] uppercase tracking-[0.18em]`, `font-mono text-[10.5px] uppercase tracking-[0.22em]`. Every AI-built site puts an eyebrow above EVERY section header, producing the same templated rhythm. Hard rule:\n  - **Maximum 1 eyebrow per 3 sections.** Hero counts as 1. So a page with 9 sections may use at most 3 eyebrows total.\n  - If section A has an eyebrow, the next 2 sections cannot have one.\n  - **Pre-Flight Check is mechanical:** count instances of `uppercase tracking` (or similar small-caps mono labels above headlines) across all section components. If count > ceil(sectionCount / 3), the output fails.\n  - **What to do instead of an eyebrow:** drop it entirely. The headline alone is enough. If you need to categorize a section, the section's location on the page already categorizes it; no label needed.\n* **SPLIT-HEADER BAN (mandatory).** The pattern \"left big headline + right small explainer paragraph\" as a section header (left col-span-7/8, right col-span-4/5 with a small body paragraph floating in the right column) is **banned as default**. Sections should have ONE focused message. If you genuinely need both a headline and an explainer paragraph, stack them vertically (headline on top, body below, max-width 65ch). Reach for the split-header pattern only when there is a real compositional reason (e.g., the right column carries a visual or interactive element, not just filler text).\n* **Bento Background Diversity (mandatory).** Bento and feature-grid sections cannot be 6 white-on-white cards with text inside. At least 2-3 cells in any multi-cell grid need real visual variation: a real image, a brand-appropriate gradient (not AI-purple), a pattern, a tinted background. A cream-on-cream bento with only typography inside reads as boring AI default, even when the rest of the page is good.\n* **Mobile collapse must be explicit per section.** For every multi-column layout, declare the `< 768px` fallback in the same component. No \"it'll work, Tailwind handles it\" assumptions.\n\n### 4.8 Image & Visual Asset Strategy\n\nLanding pages and portfolios are **visual products**. Text-only pages with fake-screenshot divs are slop.\n\n**Priority order for visual assets:**\n1. **Image-generation tool first.** If ANY image-gen tool is available in the environment (`generate_image`, MCP image tool, IDE-integrated gen, OpenAI image tools, etc.) you MUST use it to create section-specific assets: hero photography, product shots, texture backgrounds, mood images. Generate at the right aspect ratio for the section. Do not skip this step because hand-rolled CSS feels faster.\n2. **Real web images second.** When no gen tool is available, use real photography sources. Acceptable defaults:\n   * `https://picsum.photos/seed/{descriptive-seed}/{w}/{h}` for placeholder photography (seed should describe the section, e.g. `marrow-cookware-kitchen`)\n   * Actual stock or brand URLs when the brief provides them\n   * Open-license sources (Unsplash via direct URL, Pexels) if explicitly allowed\n3. **Last resort: tell the user.** If neither is possible, do NOT fill the page with hand-rolled SVG illustrations or div-based \"fake screenshots.\" Instead, leave clearly-labeled placeholder slots (`<!-- TODO: hero product photo, 1600x1200 -->`) and at the end of the response say: *\"This page needs real images at: \\[list of placements\\]. Please generate or provide them.\"*\n\n**Even minimalist sites need real images.** A pure-text page is not minimalism. It is incomplete work. Even an editorial Linear-style site needs at least 2-3 real images (hero, one product/lifestyle shot, one supporting image). Generate B&W minimalist photography if the brief is restrained; do not skip images entirely because the dial is low.\n\n**Real company logos for social proof.** When the brief calls for a \"Trusted by / Used by / Customers\" logo wall, do NOT default to plain text wordmarks (`<span>Acme Co</span>` styled in a row). Use real SVG logos:\n* **Source: Simple Icons** (`https://cdn.simpleicons.org/{slug}/ffffff` for any color, or `simple-icons` npm package). Covers most known brands.\n* **Alternative: devicon** for tech-stack logos (`@svgr/cli` or CDN).\n* **Make-up the brand name? Then make-up an SVG mark too.** Generate a simple monogram (one letter in a circle, two-letter ligature, abstract glyph) rendered as an inline `<svg>` matching the page style. Plain text wordmarks for invented brand names look generic.\n* **Always** ensure logos render in both light and dark mode (white-on-dark, black-on-light, or single-color theme variable).\n* **LOGO-ONLY rule (mandatory):** logo wall = logos and nothing else. Do NOT print industry / category labels below each logo (no `Vercel` + `hosting` underneath, no `Stripe` + `payments`, no `Cloudflare` + `infra`). The logo is the credibility, the label adds nothing the user does not already know. Optional: brand name as alt-text for screen readers, optional link to the brand's site. That is it.\n\n**Hand-rolled illustrations:**\n* SVG icons from libraries: fine (see Section 3.C).\n* Hand-rolled decorative SVGs (custom illustrations, logos, marks): **strongly discouraged**, never as default. Acceptable only when:\n  - The brief explicitly calls for it (\"draw me an SVG logo\")\n  - It's a single, simple geometric mark (a square, a circle, a wordmark in display type)\n  - You're confident in the output quality\n\n**Div-based fake screenshots are banned.** A \"hand-built product preview\" rendered with `<div>` rectangles, fake task lists, fake dashboards, fake terminal windows is a Tell. If you need to show a product:\n* Use a real screenshot URL if one exists\n* Generate one via image tool\n* Use a real component preview (an actual mini-version of the UI inside the page)\n* Or skip the preview entirely and use editorial photography\n\n**Hero needs a real visual.** Text + gradient blob is not a hero - it's a placeholder.\n\n### 4.9 Content Density\n\nLanding pages live on the **first impression**, not the full read. Cut ruthlessly.\n\n* **Default content shape per section:** short headline (≤ 8 words) + short sub-paragraph (≤ 25 words) + one visual asset OR one CTA. Anything more must be justified by the section's job.\n* **No data-dump sections.** A 20-row publication table, a 30-row award list, a giant pricing matrix on a marketing page = wrong layout. Use:\n  - Top 3-5 highlights + \"View full list\" link\n  - Marquee / carousel for breadth\n  - Different page entirely if the data is the product\n* **Long lists need a different UI component, not a longer list.** Default `<ul>` with bullets / `divide-y` rows is the lazy choice. If you have > 5 items, reach for one of these instead:\n  - 2-column split with grouped items\n  - Card grid with image + label per item\n  - Tabs / accordion if items are categorisable\n  - Horizontal scroll-snap pills\n  - Carousel for breadth-heavy lists (testimonials, logos, capabilities)\n  - Marquee for \"lots-of-things-that-don't-need-individual-attention\"\n  A spec sheet with 10 rows + a hairline under every row is the WORST default. Either group rows into 2-3 chunks with sparse dividers, or move to a card-per-spec layout.\n* **Spec sheets specifically (the Marrow-cookware pattern).** A long product specification table with `border-b` on every row is the AI default for cookware / hardware / apparel / artisan-goods briefs. Banned. Concrete alternatives:\n  - **2-col card grid:** each spec gets its own card with the spec name, the value (large display number), and a one-line \"why it matters\" body. Cards arranged 2-col on desktop, 1-col mobile.\n  - **Scroll-snap horizontal pills:** each spec is a pill, user can flick through.\n  - **Grouped chunks:** group 10 specs into 3 logical clusters (e.g. \"Materials\", \"Cooking\", \"Warranty\"), each cluster gets ONE soft divider and a cluster heading.\n  - **Featured-vs-rest:** 3-4 hero specs visualised as large display tiles, the rest collapsed under a \"View full specifications\" disclosure.\n\n* **COPY SELF-AUDIT (mandatory before ship):** Before declaring any task done, re-read every visible string on the page (headlines, subheads, eyebrows, button labels, body copy, captions, alt text, footer text, error messages). Flag any string that is:\n  - **Grammatically broken** (\"free on its past\", \"two plans but one is honest\", \"to put it on the table\" out of context)\n  - **Has unclear referents** (\"we plan to stay that way\" without prior context)\n  - **Sounds like AI hallucination** (cute-but-wrong wordplay, forced metaphors that don't track, \"elegant nothing\" phrases)\n  - **Reads like an LLM trying to sound thoughtful** (passive-aggressive humility, fake-craftsman labels, mock-poetic micro-meta)\n  Rewrite every flagged string. If unsure whether a string makes sense, replace it with a plain functional sentence. AI-generated cute copy is worse than boring copy.\n* **Fake-precise numbers are flagged.** Numbers like `92%`, `4.1×`, `48k`, `5.8 mm`, `13.4 lb` either:\n  - Come from real data (brief, brand guidelines, public metrics) - fine\n  - Are explicitly labeled as mock (`<!-- mock -->`, \"example\", \"sample data\") - fine\n  - Are AI-invented spec aesthetics - banned. Don't fake engineering precision the brand doesn't claim.\n* **One copy register per page.** Don't mix technical mono (\"47 tasks · 0.6 ctx-switches/day\"), editorial prose, and marketing punch in the same composition unless the brand voice explicitly calls for it.\n\n### 4.10 Quotes & Testimonials\n\n* **Max 3 lines** of quote body. Never 6. If the original quote is longer → cut it. A landing-page quote is a snippet, not the full review.\n* For very small font sizes (e.g. footer-style testimonials), the line cap can stretch slightly. Spirit: \"fits in a glance.\"\n* **No em-dashes inside the quote text** as design flourish (long pauses, kinetic em-dashes, em-dash-bullets). See Section 9.G - em-dash is completely banned.\n* Attribution: name + role + (optionally) company. Never name only (\"- Sarah\").\n* Quote marks: use real typographic quotes ( \" \" ) or none at all. Not straight ASCII ( \" ).\n\n### 4.11 Page Theme Lock (Light / Dark Mode Consistency)\n\nThe page has ONE theme. Sections do not invert.\n\n* If the page is dark mode, ALL sections are dark mode. No light-mode-warm-paper section sandwiched between dark sections (or vice versa). The user must not feel they walked into a different website mid-scroll.\n* The exception: if the brief explicitly calls for a \"Color Block Story\" or \"Theme Switch on Scroll\" device AND that is a deliberate composition (one full theme switch with a strong transition, not random alternation), it is allowed once per page.\n* Default behaviour: pick light, dark, or auto (`prefers-color-scheme`) at the page level and lock it. Section-level background tints within the same theme family are fine (`bg-zinc-950` next to `bg-zinc-900`); flipping to `bg-amber-50` in the middle of a `bg-zinc-950` page is broken.\n* When using a design system with built-in theming (Radix Themes, shadcn/ui with `<Theme>`), set the theme ONCE in `layout.tsx` or the page root. Do not let individual sections override.\n\n---\n\n## 5. CONTEXT-AWARE PROACTIVITY\n\nThese are tools, not defaults. Use them when the design read calls for them. **None of these fire automatically.**\n\n* **Liquid Glass / Glassmorphism:** Appropriate for premium consumer, Apple-adjacent, luxury brand, or media-overlay vibes. Inappropriate for dashboards, public-sector, or \"boring B2B.\" When used, go beyond `backdrop-blur`: add a 1px inner border (`border-white/10`) and a subtle inner shadow (`shadow-[inset_0_1px_0_rgba(255,255,255,0.1)]`) for physical edge refraction. Provide a solid-fill fallback under `prefers-reduced-transparency`.\n* **Magnetic Micro-physics:** Use when `MOTION_INTENSITY > 5` AND the brief reads premium / playful / agency. Implement EXCLUSIVELY with Motion's `useMotionValue` / `useTransform` outside the React render cycle. Never `useState`. See Section 3.B.\n* **Perpetual Micro-Interactions** (Pulse, Typewriter, Float, Shimmer, Carousel): Use when `MOTION_INTENSITY > 5` AND the section actively benefits from motion (status indicators, live feeds, AI-feel). **Not every card needs an infinite loop.** If a section is informational, leave it still. Apply Spring Physics (`type: \"spring\", stiffness: 100, damping: 20`) - no linear easing.\n* **\"Motion claimed, motion shown.\"** If `MOTION_INTENSITY > 4`, the page must actually move: entry transitions on hero, scroll-reveal on key sections, hover physics on CTAs, at minimum. A static page that claims `MOTION_INTENSITY: 7` is broken. Conversely, if you cannot ship working motion in the available scope, drop the dial to 3 and ship a clean static page. Never half-build motion that breaks (cut-off ScrollTriggers, jumpy enters, missing cleanups).\n* **MOTION MUST BE MOTIVATED (mandatory).** Before adding any animation, ask: \"what does this animation communicate?\" Valid answers: hierarchy (drawing attention to the right thing), storytelling (revealing content in sequence that matches a narrative), feedback (acknowledging a user action), state transition (showing something changed). Invalid answer: \"it looked cool\". GSAP everywhere because GSAP is available is amateur. Each ScrollTrigger, each marquee, each pinned section needs a reason. If you cannot articulate the reason in one sentence, drop the animation.\n* **MARQUEE MAX-ONE-PER-PAGE (mandatory).** Horizontal scrolling text marquees (\"logos endlessly scrolling\", \"manifesto scrolling sideways\", \"kinetic word strip\") are appropriate at most ONCE per page. Two or more marquees on the same page reads as lazy filler. Pick the one section where the marquee actually serves the content; the others get a different layout.\n* **GSAP Sticky-Stack Pattern (when scroll-stack is used).** A \"card stack on scroll\" must be a REAL sticky-stack, not a sequential reveal list. See Section 5.A below for the canonical code skeleton. Common failure: trigger fires halfway through scroll instead of pinning at viewport top. Fix: `start: \"top top\"` not `start: \"top center\"` or `\"top 80%\"`.\n* **GSAP Horizontal-Pan Pattern (when horizontal scroll-hijack is used).** See Section 5.B below for the canonical skeleton. Common failure: animation starts before the section is pinned, so the user sees half a slide. Same fix: `start: \"top top\"`, pin the wrapper, scrub the inner track.\n\n### 5.A Sticky-Stack - Canonical Skeleton\n\n```tsx\n\"use client\";\nimport { useRef, useEffect } from \"react\";\nimport { gsap } from \"gsap\";\nimport { ScrollTrigger } from \"gsap/ScrollTrigger\";\nimport { useReducedMotion } from \"motion/react\";\n\ngsap.registerPlugin(ScrollTrigger);\n\nexport function StickyStack({ cards }: { cards: React.ReactNode[] }) {\n  const ref = useRef<HTMLDivElement>(null);\n  const reduce = useReducedMotion();\n\n  useEffect(() => {\n    if (reduce || !ref.current) return;\n    const ctx = gsap.context(() => {\n      const cardEls = gsap.utils.toArray<HTMLElement>(\".stack-card\");\n      cardEls.forEach((card, i) => {\n        if (i === cardEls.length - 1) return;\n        ScrollTrigger.create({\n          trigger: card,\n          start: \"top top\",                              // pin at viewport top\n          endTrigger: cardEls[cardEls.length - 1],\n          end: \"top top\",\n          pin: true,\n          pinSpacing: false,\n        });\n        gsap.to(card, {\n          scale: 0.92,\n          opacity: 0.55,\n          ease: \"none\",\n          scrollTrigger: {\n            trigger: cardEls[i + 1],\n            start: \"top bottom\",\n            end: \"top top\",\n            scrub: true,\n          },\n        });\n      });\n    }, ref);\n    return () => ctx.revert();\n  }, [reduce]);\n\n  return (\n    <div ref={ref} className=\"relative\">\n      {cards.map((card, i) => (\n        <div\n          key={i}\n          className=\"stack-card sticky top-0 min-h-[100dvh] flex items-center justify-center\"\n        >\n          {card}\n        </div>\n      ))}\n    </div>\n  );\n}\n```\n\nCritical points: `start: \"top top\"`, `pin: true`, every card except the last is pinned, the scale/opacity transform is driven by the NEXT card's scroll trigger (so previous card shrinks as next one arrives).\n\n### 5.B Horizontal-Pan - Canonical Skeleton\n\n```tsx\n\"use client\";\nimport { useRef, useEffect } from \"react\";\nimport { gsap } from \"gsap\";\nimport { ScrollTrigger } from \"gsap/ScrollTrigger\";\nimport { useReducedMotion } from \"motion/react\";\n\ngsap.registerPlugin(ScrollTrigger);\n\nexport function HorizontalPan({ children }: { children: React.ReactNode }) {\n  const wrap = useRef<HTMLDivElement>(null);\n  const track = useRef<HTMLDivElement>(null);\n  const reduce = useReducedMotion();\n\n  useEffect(() => {\n    if (reduce || !wrap.current || !track.current) return;\n    const ctx = gsap.context(() => {\n      const distance = track.current!.scrollWidth - window.innerWidth;\n      gsap.to(track.current, {\n        x: -distance,\n        ease: \"none\",\n        scrollTrigger: {\n          trigger: wrap.current,\n          start: \"top top\",                              // pin starts when section top hits viewport top\n          end: () => `+=${distance}`,                    // scroll distance = track width minus viewport\n          pin: true,\n          scrub: 1,\n          invalidateOnRefresh: true,\n        },\n      });\n    }, wrap);\n    return () => ctx.revert();\n  }, [reduce]);\n\n  return (\n    <section ref={wrap} className=\"relative overflow-hidden\">\n      <div ref={track} className=\"flex h-[100dvh] items-center\">\n        {children}\n      </div>\n    </section>\n  );\n}\n```\n\nCritical points: `start: \"top top\"`, `pin: true`, `end: \"+=${distance}\"` (scroll length = horizontal travel needed), `scrub: 1`. The wrapper is pinned, the inner track slides horizontally as the user scrolls vertically.\n\n### 5.C Scroll-Reveal Stagger - Canonical Skeleton (lighter alternative)\n\nFor simple \"items appear as they enter viewport\" (no pinning), prefer Motion's `whileInView` over GSAP - lighter, no ScrollTrigger needed:\n\n```tsx\n\"use client\";\nimport { motion, useReducedMotion } from \"motion/react\";\n\nexport function RevealStagger({ items }: { items: string[] }) {\n  const reduce = useReducedMotion();\n  return (\n    <ul className=\"grid gap-6\">\n      {items.map((item, i) => (\n        <motion.li\n          key={item}\n          initial={reduce ? false : { opacity: 0, y: 24 }}\n          whileInView={{ opacity: 1, y: 0 }}\n          viewport={{ once: true, amount: 0.3 }}\n          transition={{\n            duration: 0.6,\n            delay: i * 0.06,\n            ease: [0.16, 1, 0.3, 1],\n          }}\n        >\n          {item}\n        </motion.li>\n      ))}\n    </ul>\n  );\n}\n```\n\nUse this for: feature lists, testimonial grids, logo walls, anything that just needs \"enter on scroll.\" Save GSAP for actual pin/scrub work.\n\n### 5.D Forbidden Animation Patterns\n\n* **`window.addEventListener(\"scroll\", ...)`** is banned. It runs on every scroll frame, jank-prone, no batching. Use Motion's `useScroll()`, GSAP's `ScrollTrigger`, IntersectionObserver, or CSS `scroll-driven animations` (`animation-timeline: view()`).\n* **Custom scroll progress calculations using `window.scrollY`** in React state. Same reason. Re-renders on every frame.\n* **`requestAnimationFrame` loops that touch React state.** Use motion values (`useMotionValue` + `useTransform`) instead.\n* **Layout Transitions:** Use Motion's `layout` and `layoutId` props for visible state changes (re-ordering lists, expanding modals, shared elements between routes). Do not wrap static content in `layout` props \"for safety\" - it costs measurement work.\n* **Staggered Orchestration:** Use `staggerChildren` (Motion) or CSS cascade (`animation-delay: calc(var(--index) * 100ms)`) for reveal moments where sequence matters. For `staggerChildren`, parent (`variants`) and children MUST share the same Client Component tree.\n\n---\n\n## 6. PERFORMANCE & ACCESSIBILITY GUARDRAILS\n\n### 6.A Hardware Acceleration\n* Animate ONLY `transform` and `opacity`. Never animate `top`, `left`, `width`, `height`.\n* Use `will-change: transform` sparingly - only on elements that will actually animate.\n\n### 6.B Reduced Motion (mandatory)\n* **Any motion above `MOTION_INTENSITY > 3` MUST honor `prefers-reduced-motion`.** This is non-negotiable.\n* In Motion: wrap with `useReducedMotion()` and degrade to static.\n* In CSS: gate animations behind `@media (prefers-reduced-motion: no-preference)` or provide an override block under `@media (prefers-reduced-motion: reduce)` that disables.\n* Infinite loops, parallax, scroll-hijack, and magnetic physics MUST collapse to static / instant under reduced motion.\n\n### 6.C Dark Mode (mandatory for any consumer-facing page)\n* Design for **both modes from the start**. Never ship light-only or dark-only without explicit user instruction.\n* Use Tailwind `dark:` variant OR CSS variables for tokens. Pick one strategy per project.\n* **Do not prescribe specific dark-mode colors here.** The brief decides. Maintain visual hierarchy, brand identity, and WCAG AA contrast (AAA for body) across both modes.\n* Respect `prefers-color-scheme: dark`. Default to system preference unless the brand insists on one mode.\n\n### 6.D Core Web Vitals Targets\n* **LCP** < 2.5s. Hero image must be `next/image priority` or preloaded.\n* **INP** < 200ms. Heavy work off main thread.\n* **CLS** < 0.1. Reserve space for images, fonts, embeds.\n* Run Lighthouse before declaring a page done.\n\n### 6.E DOM Cost\n* Apply grain / noise filters EXCLUSIVELY to fixed, `pointer-events-none` pseudo-elements (e.g., `fixed inset-0 z-[60] pointer-events-none`). NEVER on scrolling containers - continuous GPU repaints destroy mobile FPS.\n* Be aware of bundle size. Motion is not tiny. Three.js is large. Lazy-load anything that's not above-the-fold.\n\n### 6.F Z-Index Restraint\nNEVER spam arbitrary `z-50` or `z-10`. Use z-index strictly for systemic layer contexts (sticky navbars, modals, overlays, grain). Document the z-index scale in a project constants file.\n\n---\n\n## 7. DIAL DEFINITIONS (Technical Reference)\n\n### DESIGN_VARIANCE (Level 1-10)\n* **1-3 (Predictable):** Symmetrical CSS Grid (12-col, equal fr-units), equal paddings, centered alignment.\n* **4-7 (Offset):** `margin-top: -2rem` overlaps, varied image aspect ratios (4:3 next to 16:9), left-aligned headers over center-aligned data.\n* **8-10 (Asymmetric):** Masonry layouts, CSS Grid with fractional units (`grid-template-columns: 2fr 1fr 1fr`), massive empty zones (`padding-left: 20vw`).\n* **MOBILE OVERRIDE:** For levels 4-10, asymmetric layouts above `md:` MUST collapse to strict single-column (`w-full`, `px-4`, `py-8`) on viewports `< 768px`.\n\n### MOTION_INTENSITY (Level 1-10)\n* **1-3 (Static):** No automatic animations. CSS `:hover` and `:active` states only. `prefers-reduced-motion` is the default mode anyway.\n* **4-7 (Fluid CSS):** `transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1)`. `animation-delay` cascades for load-ins. Focus on `transform` and `opacity`.\n* **8-10 (Advanced Choreography):** Complex scroll-triggered reveals, parallax, scroll-driven animation (CSS `animation-timeline` or GSAP ScrollTrigger). Use Motion hooks. **NEVER use `window.addEventListener('scroll')`** - it is a hard ban, not a \"prefer-not.\" See Section 5.D for the allowed alternatives.\n\n### VISUAL_DENSITY (Level 1-10)\n* **1-3 (Art Gallery):** Lots of white space. Huge section gaps (`py-32` to `py-48`). Expensive, clean.\n* **4-7 (Daily App):** Standard web app spacing (`py-16` to `py-24`).\n* **8-10 (Cockpit):** Tight paddings. No card boxes; 1px lines separate data. Mandatory: `font-mono` for all numbers.\n\n---\n\n## 8. DARK MODE PROTOCOL\n\nDual-mode by default. Never assume light-only unless the brief is print-emulating editorial.\n\n### 8.A Token Strategy (pick one, stick to it)\n* **Tailwind `dark:` variant** (default for utility-first projects): every color utility paired with its dark variant (`bg-white dark:bg-zinc-950`, `text-gray-900 dark:text-gray-100`).\n* **CSS variables** (for shadcn/ui, Radix Themes, or component libraries with theming): define semantic tokens (`--surface`, `--surface-elevated`, `--text-primary`, `--accent`) and swap values under `[data-theme=\"dark\"]` or `@media (prefers-color-scheme: dark)`.\n\n### 8.B Do Not Prescribe Specific Colors Here\nThe brief and brand decide. This skill enforces only:\n* **Contrast** - WCAG AA minimum for body text, AAA target for hero copy.\n* **Hierarchy parity** - visual hierarchy that works in light must work in dark. If a CTA pops in light, it pops in dark.\n* **Brand fidelity** - primary brand color stays recognisable. Don't desaturate the brand into a dark mode.\n* **No pure `#000000` and no pure `#ffffff`** - use off-black (zinc-950, near-black warm gray) and o"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/zxlie/FeHelper/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# AGENTS.md instructions for /Users/uncle/github/FeHelper\n\n## UI Taste Gate\n\n- For any FeHelper extension UI, popup, options page, devtools surface, website, landing page, or other Web UI implementation/redesign, use the project-local `design-taste-frontend` skill first.\n- Skill path: `.agents/skills/design-taste-frontend/SKILL.md`.\n- Treat `design-taste-frontend` / `taste-skill` as the default quality gate for FeHelper product tone. Any future code change that affects visible UI, interaction polish, layout density, or cross-tool consistency should explicitly apply this skill before editing.\n- Treat this skill as the aesthetic decision gate: infer the design read, set the variance/motion/density dials, then choose the design system or visual language before editing UI code.\n- Apply the skill pragmatically for FeHelper: preserve browser extension constraints, accessibility, performance, bundle size, and existing repo conventions ahead of decorative motion or unnecessary dependencies.\n- Before finishing UI work, run the relevant build/lint/tests and use browser or screenshot QA when the changed surface can be exercised locally.\n\n## Chrome Extension Context\n\n- Treat every FeHelper `apps/*` tool page, popup, options page, devtools page, and content-script surface as part of a Chrome extension, not as a generic standalone website.\n- Before changing a tool page, identify the tool's actual user job, entry path, runtime APIs, permissions, asset-loading path, and whether it runs as `chrome-extension://`, injected content script, popup, options page, or devtools UI.\n- Preserve extension constraints while coding: Chrome extension CSP, `chrome.runtime` APIs, packaged relative assets, offline/local execution, bundle size, browser compatibility, and permissions boundaries.\n- Validation should match the surface. For extension pages, prefer `npm run build` plus loading/testing the built unpacked extension output in Chrome, or an extension-equivalent browser QA path. A plain localhost/static-server run is useful for fast layout checks only and should not be the only proof when Chrome extension APIs, asset paths, permissions, or CSP matter.\n- When a test uses stubs for `chrome.*` APIs, state that it is a supplemental local harness and still verify the affected extension behavior in the corresponding extension context when the change depends on those APIs.\n","isInternal":false,"tokens":482,"sizeBytes":2380},{"name":"llms.txt","path":"website/llms.txt","rawUrl":"https://raw.githubusercontent.com/zxlie/FeHelper/HEAD/website/llms.txt","title":"website - LLM Index & Context Digest","category":"root-instruction","format":"text","content":"# FeHelper（前端助手）- Chrome/Edge/Firefox 浏览器扩展\n\n# Web开发者工具箱 - 32+ 实用工具集合 (v2026.04)\n\n## 目录\n- [简介](#简介)\n- [特性](#特性)\n- [许可](#许可)\n- [访问规则](#访问规则)\n\n## 简介\n\nFeHelper（前端助手）是一个 Chrome/Edge/Firefox 浏览器扩展，包含了 Web 开发过程中经常用到的 32+ 种工具集合。始于 2011 年，历经 15 年打磨，全平台用户 300K+。\n\n## 特性\n\nFeHelper 提供了众多实用工具，包括但不限于：\n\n### 开发工具类\n- [JSON格式化工具](/docs/json-format.md) - JSON数据的美化、格式化、压缩、BigInt精度处理、排序、编辑、下载\n- [JSON比对工具](/docs/json-diff.md) - 两个JSON内容的自动键值比较，高亮差异点\n- [Mock数据生成器](/docs/mock-data.md) - 快速生成各种测试数据，支持JSON/CSV/SQL/XML输出\n- [代码美化工具](/docs/code-beautify.md) - 美化HTML、CSS、JS、XML、SQL等代码\n- [代码压缩工具](/docs/code-compress.md) - 压缩HTML、CSS、JS等代码\n- [简易Postman](/docs/postman.md) - 接口调试工具，支持GET/POST/HEAD\n- [Websocket工具](/docs/websocket.md) - Websocket连接测试与消息分析\n- [正则公式速查](/docs/regexp.md) - JavaScript/Python/PHP/Java正则表达式速查\n- [网站性能分析](/docs/page-timing.md) - 核心Web指标(LCP/FID/CLS)分析与优化建议\n\n### 编解码转换类\n- [信息编码转换](/docs/en-decode.md) - Unicode/UTF-8/URL/Base64/MD5/Hex/JWT/Gzip/字符串转义\n- [进制转换工具](/docs/trans-radix.md) - 2~36进制任意转换，BigInt引擎无精度丢失\n- [时间(戳)转换](/docs/timestamp.md) - 时间戳互转，支持时区切换、Windows FILETIME\n- [颜色转换工具](/docs/trans-color.md) - HEX/RGB颜色格式互转\n\n### 图像处理类\n- [二维码/条形码](/docs/qr-code.md) - 二维码生成/解码 + 条形码生成(Code128/EAN-13/EAN-8/UPC/ITF-14)\n- [图片Base64转换](/docs/image-base64.md) - 图片与Base64编码相互转换\n- [SVG转换器](/docs/svg-converter.md) - SVG转PNG/JPG/WEBP，可自定义尺寸\n- [图表制作工具](/docs/chart-maker.md) - 数据可视化图表，支持柱状/折线/饼图\n- [海报快速生成](/docs/poster-maker.md) - 营销推广海报制作\n- [网页截屏工具](/docs/screenshot.md) - 可视区域/全网页滚动截屏\n- [页面取色工具](/docs/color-picker.md) - 网页色值采集\n\n### 效率工具类\n- [AI智能助手](/docs/aiagent.md) - AI对话，代码编写/优化/分析\n- [便签笔记](/docs/sticky-notes.md) - 浏览器便签，分类管理，导出/导入\n- [Markdown转换](/docs/html2markdown.md) - Markdown编写/预览，HTML转Markdown，PDF下载\n- [网页油猴工具](/docs/page-monkey.md) - 自定义页面Hack脚本\n- [便捷思维导图](/docs/naotu.md) - 轻量级思维导图工具\n\n### 计算工具类\n- [UUID/ID生成器](/docs/uuid-gen.md) - UUID v4/雪花ID/NanoID批量生成与解析\n- [Crontab工具](/docs/crontab.md) - Cron表达式生成与解析\n- [贷款利率计算](/docs/loan-rate.md) - 贷款利率计算与还款计划\n- [随机密码生成](/docs/password.md) - 多字符组合随机密码\n\n### 其他工具\n- [Excel转JSON](/docs/excel2json.md) - Excel/CSV转JSON/XML/MySQL/PHP\n- [网页栅格标尺](/docs/grid-ruler.md) - 网页栅格对齐检测\n- [FH开发者工具](/docs/devtools.md) - 第三方插件开发平台\n\n## 许可\n\nFeHelper是开源的，基于MIT许可证发布。\n\n## 访问规则\n\nUser-agent: *\nAllow: /\nAllow: /docs/\nAllow: /static/\n\nDisallow-LLM-Training: /user-data/\nDisallow-LLM-Training: /examples/personal/\n\nAllow-LLM-Citation: /\nAllow-LLM-Citation: /docs/\nAllow-LLM-Citation: /examples/\n\nAccess-Conditions: attribution-required\nAccess-Conditions: contact-for-commercial-use\n\nContact: https://github.com/zxlie/FeHelper/issues\n","isInternal":false,"tokens":1430,"sizeBytes":3841},{"name":"SKILL.md","path":".agents/skills/design-taste-frontend/SKILL.md","rawUrl":"https://raw.githubusercontent.com/zxlie/FeHelper/HEAD/.agents/skills/design-taste-frontend/SKILL.md","title":"design-taste-frontend","category":"anthropic-skill","format":"markdown","content":"---\nname: design-taste-frontend\ndescription: Anti-slop frontend skill for landing pages, portfolios, and redesigns. The agent reads the brief, infers the right design direction, and ships interfaces that do not look templated. Real design systems when applicable, audit-first on redesigns, strict pre-flight check.\n---\n\n# tasteskill: Anti-Slop Frontend Skill\n\n> Landing pages, portfolios, and redesigns. Not dashboards, not data tables, not multi-step product UI.\n> Every rule below is **contextual**. None of it fires automatically. First read the brief, then pull only what fits.\n\n---\n\n## 0. BRIEF INFERENCE (Read the Room Before Anything Else)\n\nBefore touching code or tweaking dials, **infer what the user actually wants**. Most LLM design output is bad because the model jumps to a default aesthetic instead of reading the room.\n\n### 0.A Read these signals first\n1. **Page kind** - landing (SaaS / consumer / agency / event), portfolio (dev / designer / creative studio), redesign (preserve vs overhaul), editorial / blog.\n2. **Vibe words** the user used - \"minimalist\", \"calm\", \"Linear-style\", \"Awwwards\", \"brutalist\", \"premium consumer\", \"Apple-y\", \"playful\", \"serious B2B\", \"editorial\", \"agency-y\", \"glassy\", \"dark tech\".\n3. **Reference signals** - URLs they linked, screenshots they pasted, products they named, brands they're competing with.\n4. **Audience** - B2B procurement panel vs. design-conscious consumer vs. recruiter scanning a portfolio. The audience picks the aesthetic, not your taste.\n5. **Brand assets that already exist** - logo, color, type, photography. For redesigns, these are starting material, not optional input (see Section 11).\n6. **Quiet constraints** - accessibility-first audiences, public-sector, regulated industries, trust-first commerce, kids' products. These constraints OVERRIDE aesthetic preference.\n\n### 0.B Output a one-line \"Design Read\" before generating\nBefore any code, state in one line: **\"Reading this as: \\<page kind> for \\<audience>, with a \\<vibe> language, leaning toward \\<design system or aesthetic family>.\"**\n\nExample reads:\n- *\"Reading this as: B2B SaaS landing for technical buyers, with a Linear-style minimalist language, leaning toward Tailwind utilities + Geist + restrained motion.\"*\n- *\"Reading this as: solo designer portfolio for hiring managers, with an editorial / kinetic-type language, leaning toward native CSS + scroll-driven animation + custom typography.\"*\n- *\"Reading this as: redesign of a public-sector service site, with a trust-first language, leaning toward GOV.UK Frontend or USWDS.\"*\n\n### 0.C If the brief is ambiguous, ask one question, do not guess\nAsk exactly **one** clarifying question - never a multi-question dump - and only when the design read genuinely diverges. Example: *\"Should this feel closer to Linear-clean or Awwwards-experimental?\"*\n\nIf you can confidently infer from context, **do not ask**. Just declare the design read and proceed.\n\n### 0.D Anti-Default Discipline\nDo not default to: AI-purple gradients, centered hero over dark mesh, three equal feature cards, generic glassmorphism on everything, infinite-loop micro-animations everywhere, Inter + slate-900. These are the LLM defaults. Reach past them deliberately based on the design read.\n\n---\n\n## 1. THE THREE DIALS (Core Configuration)\n\nAfter the design read, set three dials. Every layout, motion, and density decision below is gated by these.\n\n* **`DESIGN_VARIANCE: 8`** - 1 = Perfect Symmetry, 10 = Artsy Chaos\n* **`MOTION_INTENSITY: 6`** - 1 = Static, 10 = Cinematic / Physics\n* **`VISUAL_DENSITY: 4`** - 1 = Art Gallery / Airy, 10 = Cockpit / Packed Data\n\n**Baseline:** `8 / 6 / 4`. Use these unless the design read overrides them. Do not ask the user to edit this file - overrides happen conversationally.\n\n### 1.A Dial Inference (design read → dial values)\n| Signal | VARIANCE | MOTION | DENSITY |\n|---|---|---|---|\n| \"minimalist / clean / calm / editorial / Linear-style\" | 5-6 | 3-4 | 2-3 |\n| \"premium consumer / Apple-y / luxury / brand\" | 7-8 | 5-7 | 3-4 |\n| \"playful / wild / Dribbble / Awwwards / experimental / agency\" | 9-10 | 8-10 | 3-4 |\n| \"landing page / portfolio / marketing site (default)\" | 7-9 | 6-8 | 3-5 |\n| \"trust-first / public-sector / regulated / accessibility-critical\" | 3-4 | 2-3 | 4-5 |\n| \"redesign - preserve\" | match existing | +1 | match existing |\n| \"redesign - overhaul\" | +2 | +2 | match existing |\n\n### 1.B Use-Case Presets\n| Use case | VARIANCE | MOTION | DENSITY |\n|---|---|---|---|\n| Landing (SaaS, mainstream) | 7 | 6 | 4 |\n| Landing (Agency / creative) | 9 | 8 | 3 |\n| Landing (Premium consumer) | 7 | 6 | 3 |\n| Portfolio (Designer / studio) | 8 | 7 | 3 |\n| Portfolio (Developer) | 6 | 5 | 4 |\n| Editorial / Blog | 6 | 4 | 3 |\n| Public-sector service | 3 | 2 | 5 |\n| Redesign - preserve | match | match+1 | match |\n| Redesign - overhaul | +2 | +2 | match |\n\n### 1.C How the Dials Drive Output\nUse these (or user-overridden values) as global variables. Cross-references throughout this document refer to these exact variable names - never invent aliases like `LAYOUT_VARIANCE` or `ANIM_LEVEL`.\n\n---\n\n## 2. BRIEF → DESIGN SYSTEM MAP\n\nOnce you have the design read (Section 0) and dials (Section 1), pick the right foundation. Do not invent CSS for things that have an official package. Do not pretend an aesthetic trend is an official system.\n\n### 2.A When to reach for a real design system (use official packages)\n| Brief reads as… | Reach for | Why |\n|---|---|---|\n| Microsoft / enterprise SaaS / dashboards | `@fluentui/react-components` or `@fluentui/web-components` | Official Fluent UI, Microsoft tokens, accessibility done |\n| Google-ish UI, Material-flavored product | `@material/web` + Material 3 tokens | Official, theme-able via Material Theming |\n| IBM-style B2B / enterprise analytics | `@carbon/react` + `@carbon/styles` | Official Carbon, mature data-density patterns |\n| Shopify app surfaces | `polaris.js` web components / Polaris React | Required for Shopify admin UI |\n| Atlassian / Jira-style product | `@atlaskit/*` + `@atlaskit/tokens` | Official Atlassian DS |\n| GitHub-style devtool / community page | `@primer/css` or `@primer/react-brand` | Official Primer; Brand variant for marketing |\n| Public-sector UK service | `govuk-frontend` | Legally / regulatorily expected |\n| US public-sector / trust-first | `uswds` | Same |\n| Fast local-business / agency MVP | Bootstrap 5.3 | Boring, fast, works |\n| Modern accessible React foundation | `@radix-ui/themes` | Primitives + polished theme |\n| Modern SaaS where you own the components | shadcn/ui (`npx shadcn@latest add ...`) | You own the code, easy to customise; never ship default state |\n| Tailwind-based modern SaaS / AI marketing | Tailwind v4 utilities + `dark:` variant | Default for indie + small team builds |\n\n**Honesty rule:** if the brief reads as one of the systems above, install and use the **official** package. Do not recreate its CSS by hand. Do not import a system's tokens but then override 90% of them.\n\n**One system per project.** Do not mix Fluent React with Carbon in the same tree. Do not import shadcn/ui components into a Material 3 app.\n\n### 2.B When the brief is an aesthetic, not a system\nFor these directions, there is **no single official package**. Build with native CSS + Tailwind + a maintained component library. Be honest in code comments about what is borrowed inspiration vs. official material.\n\n| Aesthetic | Honest implementation |\n|---|---|\n| Glassmorphism / \"frosted glass\" | `backdrop-filter`, layered borders, highlight overlays. Provide solid-fill fallback for `prefers-reduced-transparency`. |\n| Bento (Apple-style tile grids) | CSS Grid with mixed cell sizes. No single library owns this. |\n| Brutalism | Native CSS, monospace, raw borders. No library. |\n| Editorial / magazine | Serif type, asymmetric grid, generous whitespace. No library. |\n| Dark tech / hacker | Mono + accent neon, terminal motifs. No library. |\n| Aurora / mesh gradients | SVG or layered radial gradients. No library. |\n| Kinetic typography | Native CSS animations, scroll-driven animations, GSAP for hijacks. No library. |\n| **Apple Liquid Glass** | Apple documents this for Apple platforms only. **There is no official `liquid-glass.css`.** Web implementations are approximations using `backdrop-filter` + layered borders + highlights. Label clearly as approximation. |\n\n---\n\n## 3. DEFAULT ARCHITECTURE & CONVENTIONS\n\nUnless the design read picks a real design system (Section 2.A), these are the defaults:\n\n### 3.A Stack\n* **Framework:** React or Next.js. Default to Server Components (RSC).\n  * **RSC SAFETY:** Global state works ONLY in Client Components. In Next.js, wrap providers in a `\"use client\"` component.\n  * **INTERACTIVITY ISOLATION:** Any component using Motion, scroll listeners, or pointer physics MUST be an isolated leaf with `'use client'` at the top. Server Components render static layouts only.\n* **Styling:** **Tailwind v4** (default). Tailwind v3 only if the existing project demands it.\n  * For v4: do NOT use `tailwindcss` plugin in `postcss.config.js`. Use `@tailwindcss/postcss` or the Vite plugin.\n* **Animation:** **Motion** (the library formerly known as Framer Motion). Import from `motion/react` (`import { motion } from \"motion/react\"`). The `framer-motion` package still works as a legacy alias - prefer `motion/react` in new code.\n* **Fonts:** Always use `next/font` (Next.js) or self-host with `@font-face` + `font-display: swap`. Never link Google Fonts via `<link>` in production.\n\n### 3.B State\n* Local `useState` / `useReducer` for isolated UI.\n* Global state ONLY for deep prop-drilling avoidance - Zustand, Jotai, or React context.\n* **NEVER** use `useState` to track continuous values driven by user input (mouse position, scroll progress, pointer physics, magnetic hover). Use Motion's `useMotionValue` / `useTransform` / `useScroll`. `useState` re-renders the React tree on every change and collapses on mobile.\n\n### 3.C Icons\n* **Allowed libraries (priority order):** `@phosphor-icons/react`, `hugeicons-react`, `@radix-ui/react-icons`, `@tabler/icons-react`.\n* **Discouraged:** `lucide-react`. Acceptable only when the user explicitly asks for it or the project already depends on it.\n* **NEVER hand-roll SVG icons.** If a glyph is missing, install a second library or compose from primitives - do not draw icon paths from scratch.\n* **One family per project.** Do not mix Phosphor with Lucide in the same component tree.\n* **Standardize `strokeWidth` globally** (e.g. `1.5` or `2.0`).\n\n### 3.D Emoji Policy\nDiscouraged by default in code, markup, and visible text. Replace symbols with icon-library glyphs. **Override:** allow emojis only when the user explicitly asks for a playful / chat-style / social-native vibe - and even then use them sparingly with intent.\n\n### 3.E Responsiveness & Layout Mechanics\n* Standardize breakpoints (`sm 640`, `md 768`, `lg 1024`, `xl 1280`, `2xl 1536`).\n* Contain page layouts using `max-w-[1400px] mx-auto` or `max-w-7xl`.\n* **Viewport Stability:** NEVER use `h-screen` for full-height Hero sections. ALWAYS use `min-h-[100dvh]` to prevent layout jumping on mobile (iOS Safari address bar).\n* **Grid over Flex-Math:** NEVER use complex flexbox percentage math (`w-[calc(33%-1rem)]`). ALWAYS use CSS Grid (`grid grid-cols-1 md:grid-cols-3 gap-6`).\n\n### 3.F Dependency Verification (mandatory)\nBefore importing ANY 3rd-party library, check `package.json`. If the package is missing, output the install command first. **Never** assume a library exists.\n\n---\n\n## 4. DESIGN ENGINEERING DIRECTIVES (Bias Correction)\n\nLLMs default to clichés. Override these defaults proactively. Each rule has a context-aware override path.\n\n### 4.1 Typography\n* **Display / Headlines:** Default `text-4xl md:text-6xl tracking-tighter leading-none`.\n* **Body / Paragraphs:** Default `text-base text-gray-600 leading-relaxed max-w-[65ch]`.\n* **Sans font choice:**\n  * **Discouraged as default:** `Inter`. Pick `Geist`, `Outfit`, `Cabinet Grotesk`, `Satoshi`, or a brand-appropriate serif first.\n  * **Override:** Inter is acceptable when the user explicitly asks for a neutral / standard / Linear-style feel, or when the brief is a public-sector / accessibility-first site.\n* **Pairings to know:** `Geist` + `Geist Mono`, `Satoshi` + `JetBrains Mono`, `Cabinet Grotesk` + `Inter Tight`, `GT America` + `IBM Plex Mono`.\n\n* **SERIF DISCIPLINE (VERY DISCOURAGED AS DEFAULT):**\n  * Serif is **very discouraged as the default font for any project.** \"It feels creative / premium / editorial\" is NOT a reason to reach for serif. The agent's default mental model that \"creative brief = serif\" is the single most-tested AI tell in production rounds.\n  * **Serif is only acceptable when ONE of these is explicitly true:**\n    - The brand brief literally names a serif font, OR\n    - The aesthetic family is genuinely editorial / luxury / publication / manuscript / heritage / vintage AND you can articulate why this specific serif fits this specific brand\n  * For everything else (creative agency, design studio, modern brand, premium consumer, portfolio, lifestyle), **default sans-serif display** (Geist Display, ABC Diatype, Söhne Breit, Cabinet Grotesk Display, Migra Sans, GT Walsheim, Inter Display, PP Neue Montreal). Sans display fonts are not \"boring\" — they are the default for the same reason black is the default in fashion.\n  * **EMPHASIS RULE (related):** When you want to emphasize a word within a headline (the kinetic \"and `spatial` design\" type move), use **italic or bold of the SAME font**. Do NOT inject a random serif word into a sans headline (or vice versa) just to add visual interest. Mixed-family emphasis is amateur. Italic/bold emphasis in the same family is the right move.\n  * **Specifically BANNED as defaults:** `Fraunces` and `Instrument_Serif` (the two LLM-favorite display serifs).\n  * **If a serif is justified** (rare, per the above), rotate from this pool, do NOT reuse the same serif across consecutive projects: PP Editorial New, GT Sectra Display, Cardinal Grotesque, Reckless Neue, Tiempos Headline, Recoleta, Cormorant Garamond, Playfair Display, EB Garamond, IvyPresto, Migra, Editorial Old, Saol Display, Söhne Breit Kursiv, Domaine Display, Canela, Schnyder, Tobias, NB Architekt, ITC Galliard.\n\n* **ITALIC DESCENDER CLEARANCE (mandatory):** When italic is used in display type and the word contains a descender letter (`y g j p q`), `leading-[1]` or `leading-none` will clip the descender. Use `leading-[1.1]` minimum and add `pb-1` or `mb-1` reserve on the wrapping element. Audit every italic word in display headlines before shipping.\n\n### 4.2 Color Calibration\n* Max 1 accent color. Saturation < 80% by default.\n* **THE LILA RULE:** The \"AI Purple / Blue glow\" aesthetic is discouraged as a default. No automatic purple button glows, no random neon gradients. Use neutral bases (Zinc / Slate / Stone) with high-contrast singular accents (Emerald, Electric Blue, Deep Rose, Burnt Orange, etc.).\n* **Override:** if the brand or brief explicitly asks for purple / violet / lila, embrace it. But execute with intent: consistent palette, harmonised neutrals, restrained gradients. Not generic AI gradient slop.\n* **One palette per project.** Do not fluctuate between warm and cool grays within the same project.\n* **COLOR CONSISTENCY LOCK (mandatory):** Once an accent color is chosen for a page, it is used on the WHOLE page. A warm-grey site does not suddenly get a blue CTA in section 7. A rose-accented site does not get a teal status badge in the footer. Pick one accent, lock it, audit every component before shipping.\n\n* **PREMIUM-CONSUMER PALETTE BAN (mandatory, second-most-recurring AI-tell):**\n  * For premium-consumer briefs (cookware, wellness, artisan, luxury, heritage craft, DTC home goods, etc.) the LLM default is **warm beige/cream + brass/clay/oxblood/ochre + espresso/ink dark text**. Concretely banned hex families as default backgrounds and accents:\n    - Backgrounds: `#f5f1ea`, `#f7f5f1`, `#fbf8f1`, `#efeae0`, `#ece6db`, `#faf7f1`, `#e8dfcb` (all \"warm paper / cream / chalk / bone\")\n    - Accents: `#b08947`, `#b6553a`, `#9a2436`, `#9c6e2a`, `#bc7c3a`, `#7d5621` (all \"brass / clay / oxblood / ochre\")\n    - Text: `#1a1714`, `#1a1814`, `#1b1814` (all \"espresso / warm near-black\")\n  * This palette is BANNED as the default reach for premium-consumer briefs. Every premium-consumer site you have ever shipped uses this exact palette. The brand becomes invisible.\n  * **Default alternatives (rotate, do not reuse):**\n    - **Cold Luxury:** silver-grey + chrome + smoke (think Tesla, Apple Watch Hermes-without-the-leather)\n    - **Forest:** deep green + bone + amber accent (think Filson, Patagonia premium)\n    - **Black and Tan:** true off-black + warm tan, sharp contrast, no beige\n    - **Cobalt + Cream:** saturated blue against a single neutral, no brass\n    - **Terracotta + Slate:** warm rust against cool grey, no brass\n    - **Olive + Brick + Paper:** muted olive plus brick-red accent\n    - **Pure monochrome + single saturated pop:** off-white + off-black + one bright accent (electric blue, emerald, hot pink, etc.)\n  * **Palette-rotation rule:** if the previous premium-consumer project you generated used the beige+brass family, this one MUST use a different family. Do not ship the same warm-craft palette twice in a row.\n  * **Override:** the beige+brass+espresso palette is acceptable ONLY when the brand brief explicitly names those colors, or when the brand identity is genuinely vintage / artisan / warm-craft AND you can articulate why this specific palette fits this specific brand. Default-reaching for it because \"this is a cookware brief\" is banned.\n\n### 4.3 Layout Diversification\n* **ANTI-CENTER BIAS:** Centered Hero / H1 sections are avoided when `DESIGN_VARIANCE > 4`. Force \"Split Screen\" (50/50), \"Left-aligned content / right-aligned asset\", \"Asymmetric white-space\", or scroll-pinned structures.\n* **Override:** centered hero is OK for editorial / manifesto / launch-announcement briefs where the message itself is the design.\n\n### 4.4 Materiality, Shadows, Cards\n* Use cards ONLY when elevation communicates real hierarchy. Otherwise group with `border-t`, `divide-y`, or negative space.\n* When a shadow is used, tint it to the background hue. No pure-black drop shadows on light backgrounds.\n* For `VISUAL_DENSITY > 7`: generic card containers are banned. Data metrics breathe in plain layout.\n* **SHAPE CONSISTENCY LOCK (mandatory):** Pick ONE corner-radius scale for the page and stick to it. Options: all-sharp (radius 0), all-soft (radius 12-16px), all-pill (full radius for interactive). Mixed systems are allowed only when there is a documented rule (e.g. \"buttons are full-pill, cards are 16px, inputs are 8px\") and that rule is followed everywhere. Round buttons in a square layout, or square cards on a pill-button page, is broken design.\n\n### 4.5 Interactive UI States\nLLMs default to \"static successful state only.\" Always implement full cycles:\n* **Loading:** Skeletal loaders matching the final layout's shape. Avoid generic circular spinners.\n* **Empty States:** Beautifully composed; indicate how to populate.\n* **Error States:** Clear, inline (forms), or contextual (toasts only for transient).\n* **Tactile Feedback:** On `:active`, use `-translate-y-[1px]` or `scale-[0.98]` to simulate a physical push.\n* **BUTTON CONTRAST CHECK (mandatory, a11y):** Before shipping any button, verify the button text is readable against the button background. White button + white text, `bg-white` CTA with `text-white` label, transparent button against the page background with no border → all banned. Audit every CTA: contrast ratio WCAG AA min (4.5:1 for body, 3:1 for large text 18px+). Same rule applies to ghost buttons over photographic backgrounds (use a backdrop, scrim, or stroke).\n* **CTA BUTTON WRAP BAN (mandatory):** Button text MUST fit on one line at desktop. If a label like \"VIEW SELECTED WORK\" wraps to 2 or 3 lines, the button is broken. Fix by EITHER shortening the label (3 words max for primary CTAs, ideally 1-2) OR widening the button (do not artificially constrain `max-width` on CTAs). Wrapped CTAs at desktop are a Pre-Flight Fail.\n* **NO DUPLICATE CTA INTENT (mandatory):** Two CTAs with the same intent on one page is a Pre-Flight Fail. Examples of same intent: \"Get in touch\" + \"Contact us\" + \"Let's talk\" + \"Start a project\" + \"Start something\" + \"Reach out\" = all \"contact\" intent → pick ONE label and use it everywhere on the page (nav, hero, footer). Same for \"Try free\" + \"Get started\" + \"Sign up free\" (all \"signup\" intent) and \"View work\" + \"See selected work\" + \"Browse projects\" (all \"portfolio\" intent). One label per intent.\n* **FORM CONTRAST CHECK (mandatory, a11y):** Form inputs, placeholder text, focus rings, helper text, and error text all pass WCAG AA contrast against the section background. Light placeholders on a near-white form, white form on white page section, form labels grayer than 4.5:1 contrast → all banned. Audit every form before shipping.\n\n### 4.6 Data & Form Patterns\n* Label ABOVE input. Helper text optional but present in markup. Error text BELOW input. Standard `gap-2` for input blocks.\n* No placeholder-as-label. Ever.\n\n### 4.7 Layout Discipline (Hard Rules. Failing any of these is shipping broken work)\n\n* **Hero MUST fit in the initial viewport.** Headline max 2 lines on desktop, subtext max **20 words** AND max 3-4 lines, CTAs visible without scroll. If the copy is too long: reduce font scale OR cut copy. If you cannot describe the value-prop in 20 words of subtext, the value-prop is unclear, not the rule too tight. Never let the hero overflow and force scroll to find the CTA.\n* **Hero font-scale discipline.** Plan font size and image size *together*. If the hero asset is large and the headline is more than 6 words, do not start at `text-7xl/text-8xl`. Default sensible range: `text-4xl md:text-5xl lg:text-6xl` for most heroes; `text-6xl md:text-7xl` only when the headline is 3-5 words. A 4-line hero headline is always a font-size error, never a copy-length error.\n* **HERO TOP PADDING CAP (mandatory):** Hero top padding max `pt-24` (≈6rem) at desktop. More than that means the hero content floats halfway down the viewport and reads as a layout bug, not as intentional space. If your hero needs more breathing room, increase font scale or asset size, not top padding.\n* **HERO STACK DISCIPLINE (max 4 text elements).** The hero is a single moment, not a feature list. Allowed text elements, max 4 in total:\n  1. Eyebrow (small uppercase label) OR brand strip OR neither - pick zero or one\n  2. Headline (max 2 lines, see above)\n  3. Subtext (max 20 words, max 4 lines)\n  4. CTAs (1 primary + max 1 secondary)\n  - **BANNED in the hero:** tiny tagline below CTAs (\"Works with GitHub, GitLab, and self-hosted Git\"), trust micro-strip (\"Used by engineering teams at...\"), pricing teaser (\"Free for solo, $10/user for teams\"), feature bullet list, social-proof avatar row. All of those move to dedicated sections directly below the hero.\n  - If you have an eyebrow AND a tagline below CTAs in the same hero, drop the tagline. If you have a brand strip AND a tagline, drop the tagline. One small text element per hero, max.\n* **\"Used by\" / \"Trusted by\" logo wall belongs UNDER the hero, never inside it.** The hero is for the value prop and primary CTA. The logo wall is a separate section directly below. Do not stuff trust logos into the same flex row as the hero copy.\n* **Navigation MUST render on a single line on desktop.** If items don't fit at `lg` (1024px), condense labels, drop secondary items, or move to a hamburger. A two-line nav at desktop is broken design.\n* **Navigation height cap: 80px max desktop, default 64-72px.** No huge \"agency\" nav bars that eat 15% of the viewport.\n* **Bento grids MUST have rhythm, not one-sided repetition.** Do not stack 6 left-image / right-text rows. Vary the composition: alternate full-width feature rows, asymmetric tile sizes, vertical breaks.\n* **BENTO CELL COUNT RULE (mandatory):** A bento grid has EXACTLY as many cells as you have content for. 3 items → 3 cells (1+2 split, or 2+1, or asymmetric trio). 5 items → 5 cells (2+3, 3+2, hero+4, etc.). If your grid has an empty cell in the middle or at the end, you planned wrong. Re-shape the grid; do not paste a blank tile.\n* **Section-Layout-Repetition Ban.** Once you use a layout family for a section (e.g., 3-column-image-cards, full-width-quote, split-text-image), that family can appear at most ONCE on the page. \"Selected commissions\" must not look like \"What we do.\" A landing page with 8 sections must use at least 4 different layout families.\n* **ZIGZAG ALTERNATION CAP (mandatory).** Alternating \"left-image + right-text\" then \"left-text + right-image\" zigzag layout = banal. Max 2 sections in a row with this image+text-split pattern. The 3rd consecutive image+text split is a Pre-Flight Fail. Break the pattern with a full-width section, a vertical-stack section, a bento grid, a marquee, or a different layout family.\n* **EYEBROW RESTRAINT (mandatory, the #1 violated rule in production tests).** An \"eyebrow\" is the small uppercase wide-tracking label sitting above a section headline (e.g. `FOUR COLORWAYS`, `SELECTED WORK`, `THE HARDWARE`, `Git-native task management`). Typical CSS signature: `text-[11px] uppercase tracking-[0.18em]`, `font-mono text-[10.5px] uppercase tracking-[0.22em]`. Every AI-built site puts an eyebrow above EVERY section header, producing the same templated rhythm. Hard rule:\n  - **Maximum 1 eyebrow per 3 sections.** Hero counts as 1. So a page with 9 sections may use at most 3 eyebrows total.\n  - If section A has an eyebrow, the next 2 sections cannot have one.\n  - **Pre-Flight Check is mechanical:** count instances of `uppercase tracking` (or similar small-caps mono labels above headlines) across all section components. If count > ceil(sectionCount / 3), the output fails.\n  - **What to do instead of an eyebrow:** drop it entirely. The headline alone is enough. If you need to categorize a section, the section's location on the page already categorizes it; no label needed.\n* **SPLIT-HEADER BAN (mandatory).** The pattern \"left big headline + right small explainer paragraph\" as a section header (left col-span-7/8, right col-span-4/5 with a small body paragraph floating in the right column) is **banned as default**. Sections should have ONE focused message. If you genuinely need both a headline and an explainer paragraph, stack them vertically (headline on top, body below, max-width 65ch). Reach for the split-header pattern only when there is a real compositional reason (e.g., the right column carries a visual or interactive element, not just filler text).\n* **Bento Background Diversity (mandatory).** Bento and feature-grid sections cannot be 6 white-on-white cards with text inside. At least 2-3 cells in any multi-cell grid need real visual variation: a real image, a brand-appropriate gradient (not AI-purple), a pattern, a tinted background. A cream-on-cream bento with only typography inside reads as boring AI default, even when the rest of the page is good.\n* **Mobile collapse must be explicit per section.** For every multi-column layout, declare the `< 768px` fallback in the same component. No \"it'll work, Tailwind handles it\" assumptions.\n\n### 4.8 Image & Visual Asset Strategy\n\nLanding pages and portfolios are **visual products**. Text-only pages with fake-screenshot divs are slop.\n\n**Priority order for visual assets:**\n1. **Image-generation tool first.** If ANY image-gen tool is available in the environment (`generate_image`, MCP image tool, IDE-integrated gen, OpenAI image tools, etc.) you MUST use it to create section-specific assets: hero photography, product shots, texture backgrounds, mood images. Generate at the right aspect ratio for the section. Do not skip this step because hand-rolled CSS feels faster.\n2. **Real web images second.** When no gen tool is available, use real photography sources. Acceptable defaults:\n   * `https://picsum.photos/seed/{descriptive-seed}/{w}/{h}` for placeholder photography (seed should describe the section, e.g. `marrow-cookware-kitchen`)\n   * Actual stock or brand URLs when the brief provides them\n   * Open-license sources (Unsplash via direct URL, Pexels) if explicitly allowed\n3. **Last resort: tell the user.** If neither is possible, do NOT fill the page with hand-rolled SVG illustrations or div-based \"fake screenshots.\" Instead, leave clearly-labeled placeholder slots (`<!-- TODO: hero product photo, 1600x1200 -->`) and at the end of the response say: *\"This page needs real images at: \\[list of placements\\]. Please generate or provide them.\"*\n\n**Even minimalist sites need real images.** A pure-text page is not minimalism. It is incomplete work. Even an editorial Linear-style site needs at least 2-3 real images (hero, one product/lifestyle shot, one supporting image). Generate B&W minimalist photography if the brief is restrained; do not skip images entirely because the dial is low.\n\n**Real company logos for social proof.** When the brief calls for a \"Trusted by / Used by / Customers\" logo wall, do NOT default to plain text wordmarks (`<span>Acme Co</span>` styled in a row). Use real SVG logos:\n* **Source: Simple Icons** (`https://cdn.simpleicons.org/{slug}/ffffff` for any color, or `simple-icons` npm package). Covers most known brands.\n* **Alternative: devicon** for tech-stack logos (`@svgr/cli` or CDN).\n* **Make-up the brand name? Then make-up an SVG mark too.** Generate a simple monogram (one letter in a circle, two-letter ligature, abstract glyph) rendered as an inline `<svg>` matching the page style. Plain text wordmarks for invented brand names look generic.\n* **Always** ensure logos render in both light and dark mode (white-on-dark, black-on-light, or single-color theme variable).\n* **LOGO-ONLY rule (mandatory):** logo wall = logos and nothing else. Do NOT print industry / category labels below each logo (no `Vercel` + `hosting` underneath, no `Stripe` + `payments`, no `Cloudflare` + `infra`). The logo is the credibility, the label adds nothing the user does not already know. Optional: brand name as alt-text for screen readers, optional link to the brand's site. That is it.\n\n**Hand-rolled illustrations:**\n* SVG icons from libraries: fine (see Section 3.C).\n* Hand-rolled decorative SVGs (custom illustrations, logos, marks): **strongly discouraged**, never as default. Acceptable only when:\n  - The brief explicitly calls for it (\"draw me an SVG logo\")\n  - It's a single, simple geometric mark (a square, a circle, a wordmark in display type)\n  - You're confident in the output quality\n\n**Div-based fake screenshots are banned.** A \"hand-built product preview\" rendered with `<div>` rectangles, fake task lists, fake dashboards, fake terminal windows is a Tell. If you need to show a product:\n* Use a real screenshot URL if one exists\n* Generate one via image tool\n* Use a real component preview (an actual mini-version of the UI inside the page)\n* Or skip the preview entirely and use editorial photography\n\n**Hero needs a real visual.** Text + gradient blob is not a hero - it's a placeholder.\n\n### 4.9 Content Density\n\nLanding pages live on the **first impression**, not the full read. Cut ruthlessly.\n\n* **Default content shape per section:** short headline (≤ 8 words) + short sub-paragraph (≤ 25 words) + one visual asset OR one CTA. Anything more must be justified by the section's job.\n* **No data-dump sections.** A 20-row publication table, a 30-row award list, a giant pricing matrix on a marketing page = wrong layout. Use:\n  - Top 3-5 highlights + \"View full list\" link\n  - Marquee / carousel for breadth\n  - Different page entirely if the data is the product\n* **Long lists need a different UI component, not a longer list.** Default `<ul>` with bullets / `divide-y` rows is the lazy choice. If you have > 5 items, reach for one of these instead:\n  - 2-column split with grouped items\n  - Card grid with image + label per item\n  - Tabs / accordion if items are categorisable\n  - Horizontal scroll-snap pills\n  - Carousel for breadth-heavy lists (testimonials, logos, capabilities)\n  - Marquee for \"lots-of-things-that-don't-need-individual-attention\"\n  A spec sheet with 10 rows + a hairline under every row is the WORST default. Either group rows into 2-3 chunks with sparse dividers, or move to a card-per-spec layout.\n* **Spec sheets specifically (the Marrow-cookware pattern).** A long product specification table with `border-b` on every row is the AI default for cookware / hardware / apparel / artisan-goods briefs. Banned. Concrete alternatives:\n  - **2-col card grid:** each spec gets its own card with the spec name, the value (large display number), and a one-line \"why it matters\" body. Cards arranged 2-col on desktop, 1-col mobile.\n  - **Scroll-snap horizontal pills:** each spec is a pill, user can flick through.\n  - **Grouped chunks:** group 10 specs into 3 logical clusters (e.g. \"Materials\", \"Cooking\", \"Warranty\"), each cluster gets ONE soft divider and a cluster heading.\n  - **Featured-vs-rest:** 3-4 hero specs visualised as large display tiles, the rest collapsed under a \"View full specifications\" disclosure.\n\n* **COPY SELF-AUDIT (mandatory before ship):** Before declaring any task done, re-read every visible string on the page (headlines, subheads, eyebrows, button labels, body copy, captions, alt text, footer text, error messages). Flag any string that is:\n  - **Grammatically broken** (\"free on its past\", \"two plans but one is honest\", \"to put it on the table\" out of context)\n  - **Has unclear referents** (\"we plan to stay that way\" without prior context)\n  - **Sounds like AI hallucination** (cute-but-wrong wordplay, forced metaphors that don't track, \"elegant nothing\" phrases)\n  - **Reads like an LLM trying to sound thoughtful** (passive-aggressive humility, fake-craftsman labels, mock-poetic micro-meta)\n  Rewrite every flagged string. If unsure whether a string makes sense, replace it with a plain functional sentence. AI-generated cute copy is worse than boring copy.\n* **Fake-precise numbers are flagged.** Numbers like `92%`, `4.1×`, `48k`, `5.8 mm`, `13.4 lb` either:\n  - Come from real data (brief, brand guidelines, public metrics) - fine\n  - Are explicitly labeled as mock (`<!-- mock -->`, \"example\", \"sample data\") - fine\n  - Are AI-invented spec aesthetics - banned. Don't fake engineering precision the brand doesn't claim.\n* **One copy register per page.** Don't mix technical mono (\"47 tasks · 0.6 ctx-switches/day\"), editorial prose, and marketing punch in the same composition unless the brand voice explicitly calls for it.\n\n### 4.10 Quotes & Testimonials\n\n* **Max 3 lines** of quote body. Never 6. If the original quote is longer → cut it. A landing-page quote is a snippet, not the full review.\n* For very small font sizes (e.g. footer-style testimonials), the line cap can stretch slightly. Spirit: \"fits in a glance.\"\n* **No em-dashes inside the quote text** as design flourish (long pauses, kinetic em-dashes, em-dash-bullets). See Section 9.G - em-dash is completely banned.\n* Attribution: name + role + (optionally) company. Never name only (\"- Sarah\").\n* Quote marks: use real typographic quotes ( \" \" ) or none at all. Not straight ASCII ( \" ).\n\n### 4.11 Page Theme Lock (Light / Dark Mode Consistency)\n\nThe page has ONE theme. Sections do not invert.\n\n* If the page is dark mode, ALL sections are dark mode. No light-mode-warm-paper section sandwiched between dark sections (or vice versa). The user must not feel they walked into a different website mid-scroll.\n* The exception: if the brief explicitly calls for a \"Color Block Story\" or \"Theme Switch on Scroll\" device AND that is a deliberate composition (one full theme switch with a strong transition, not random alternation), it is allowed once per page.\n* Default behaviour: pick light, dark, or auto (`prefers-color-scheme`) at the page level and lock it. Section-level background tints within the same theme family are fine (`bg-zinc-950` next to `bg-zinc-900`); flipping to `bg-amber-50` in the middle of a `bg-zinc-950` page is broken.\n* When using a design system with built-in theming (Radix Themes, shadcn/ui with `<Theme>`), set the theme ONCE in `layout.tsx` or the page root. Do not let individual sections override.\n\n---\n\n## 5. CONTEXT-AWARE PROACTIVITY\n\nThese are tools, not defaults. Use them when the design read calls for them. **None of these fire automatically.**\n\n* **Liquid Glass / Glassmorphism:** Appropriate for premium consumer, Apple-adjacent, luxury brand, or media-overlay vibes. Inappropriate for dashboards, public-sector, or \"boring B2B.\" When used, go beyond `backdrop-blur`: add a 1px inner border (`border-white/10`) and a subtle inner shadow (`shadow-[inset_0_1px_0_rgba(255,255,255,0.1)]`) for physical edge refraction. Provide a solid-fill fallback under `prefers-reduced-transparency`.\n* **Magnetic Micro-physics:** Use when `MOTION_INTENSITY > 5` AND the brief reads premium / playful / agency. Implement EXCLUSIVELY with Motion's `useMotionValue` / `useTransform` outside the React render cycle. Never `useState`. See Section 3.B.\n* **Perpetual Micro-Interactions** (Pulse, Typewriter, Float, Shimmer, Carousel): Use when `MOTION_INTENSITY > 5` AND the section actively benefits from motion (status indicators, live feeds, AI-feel). **Not every card needs an infinite loop.** If a section is informational, leave it still. Apply Spring Physics (`type: \"spring\", stiffness: 100, damping: 20`) - no linear easing.\n* **\"Motion claimed, motion shown.\"** If `MOTION_INTENSITY > 4`, the page must actually move: entry transitions on hero, scroll-reveal on key sections, hover physics on CTAs, at minimum. A static page that claims `MOTION_INTENSITY: 7` is broken. Conversely, if you cannot ship working motion in the available scope, drop the dial to 3 and ship a clean static page. Never half-build motion that breaks (cut-off ScrollTriggers, jumpy enters, missing cleanups).\n* **MOTION MUST BE MOTIVATED (mandatory).** Before adding any animation, ask: \"what does this animation communicate?\" Valid answers: hierarchy (drawing attention to the right thing), storytelling (revealing content in sequence that matches a narrative), feedback (acknowledging a user action), state transition (showing something changed). Invalid answer: \"it looked cool\". GSAP everywhere because GSAP is available is amateur. Each ScrollTrigger, each marquee, each pinned section needs a reason. If you cannot articulate the reason in one sentence, drop the animation.\n* **MARQUEE MAX-ONE-PER-PAGE (mandatory).** Horizontal scrolling text marquees (\"logos endlessly scrolling\", \"manifesto scrolling sideways\", \"kinetic word strip\") are appropriate at most ONCE per page. Two or more marquees on the same page reads as lazy filler. Pick the one section where the marquee actually serves the content; the others get a different layout.\n* **GSAP Sticky-Stack Pattern (when scroll-stack is used).** A \"card stack on scroll\" must be a REAL sticky-stack, not a sequential reveal list. See Section 5.A below for the canonical code skeleton. Common failure: trigger fires halfway through scroll instead of pinning at viewport top. Fix: `start: \"top top\"` not `start: \"top center\"` or `\"top 80%\"`.\n* **GSAP Horizontal-Pan Pattern (when horizontal scroll-hijack is used).** See Section 5.B below for the canonical skeleton. Common failure: animation starts before the section is pinned, so the user sees half a slide. Same fix: `start: \"top top\"`, pin the wrapper, scrub the inner track.\n\n### 5.A Sticky-Stack - Canonical Skeleton\n\n```tsx\n\"use client\";\nimport { useRef, useEffect } from \"react\";\nimport { gsap } from \"gsap\";\nimport { ScrollTrigger } from \"gsap/ScrollTrigger\";\nimport { useReducedMotion } from \"motion/react\";\n\ngsap.registerPlugin(ScrollTrigger);\n\nexport function StickyStack({ cards }: { cards: React.ReactNode[] }) {\n  const ref = useRef<HTMLDivElement>(null);\n  const reduce = useReducedMotion();\n\n  useEffect(() => {\n    if (reduce || !ref.current) return;\n    const ctx = gsap.context(() => {\n      const cardEls = gsap.utils.toArray<HTMLElement>(\".stack-card\");\n      cardEls.forEach((card, i) => {\n        if (i === cardEls.length - 1) return;\n        ScrollTrigger.create({\n          trigger: card,\n          start: \"top top\",                              // pin at viewport top\n          endTrigger: cardEls[cardEls.length - 1],\n          end: \"top top\",\n          pin: true,\n          pinSpacing: false,\n        });\n        gsap.to(card, {\n          scale: 0.92,\n          opacity: 0.55,\n          ease: \"none\",\n          scrollTrigger: {\n            trigger: cardEls[i + 1],\n            start: \"top bottom\",\n            end: \"top top\",\n            scrub: true,\n          },\n        });\n      });\n    }, ref);\n    return () => ctx.revert();\n  }, [reduce]);\n\n  return (\n    <div ref={ref} className=\"relative\">\n      {cards.map((card, i) => (\n        <div\n          key={i}\n          className=\"stack-card sticky top-0 min-h-[100dvh] flex items-center justify-center\"\n        >\n          {card}\n        </div>\n      ))}\n    </div>\n  );\n}\n```\n\nCritical points: `start: \"top top\"`, `pin: true`, every card except the last is pinned, the scale/opacity transform is driven by the NEXT card's scroll trigger (so previous card shrinks as next one arrives).\n\n### 5.B Horizontal-Pan - Canonical Skeleton\n\n```tsx\n\"use client\";\nimport { useRef, useEffect } from \"react\";\nimport { gsap } from \"gsap\";\nimport { ScrollTrigger } from \"gsap/ScrollTrigger\";\nimport { useReducedMotion } from \"motion/react\";\n\ngsap.registerPlugin(ScrollTrigger);\n\nexport function HorizontalPan({ children }: { children: React.ReactNode }) {\n  const wrap = useRef<HTMLDivElement>(null);\n  const track = useRef<HTMLDivElement>(null);\n  const reduce = useReducedMotion();\n\n  useEffect(() => {\n    if (reduce || !wrap.current || !track.current) return;\n    const ctx = gsap.context(() => {\n      const distance = track.current!.scrollWidth - window.innerWidth;\n      gsap.to(track.current, {\n        x: -distance,\n        ease: \"none\",\n        scrollTrigger: {\n          trigger: wrap.current,\n          start: \"top top\",                              // pin starts when section top hits viewport top\n          end: () => `+=${distance}`,                    // scroll distance = track width minus viewport\n          pin: true,\n          scrub: 1,\n          invalidateOnRefresh: true,\n        },\n      });\n    }, wrap);\n    return () => ctx.revert();\n  }, [reduce]);\n\n  return (\n    <section ref={wrap} className=\"relative overflow-hidden\">\n      <div ref={track} className=\"flex h-[100dvh] items-center\">\n        {children}\n      </div>\n    </section>\n  );\n}\n```\n\nCritical points: `start: \"top top\"`, `pin: true`, `end: \"+=${distance}\"` (scroll length = horizontal travel needed), `scrub: 1`. The wrapper is pinned, the inner track slides horizontally as the user scrolls vertically.\n\n### 5.C Scroll-Reveal Stagger - Canonical Skeleton (lighter alternative)\n\nFor simple \"items appear as they enter viewport\" (no pinning), prefer Motion's `whileInView` over GSAP - lighter, no ScrollTrigger needed:\n\n```tsx\n\"use client\";\nimport { motion, useReducedMotion } from \"motion/react\";\n\nexport function RevealStagger({ items }: { items: string[] }) {\n  const reduce = useReducedMotion();\n  return (\n    <ul className=\"grid gap-6\">\n      {items.map((item, i) => (\n        <motion.li\n          key={item}\n          initial={reduce ? false : { opacity: 0, y: 24 }}\n          whileInView={{ opacity: 1, y: 0 }}\n          viewport={{ once: true, amount: 0.3 }}\n          transition={{\n            duration: 0.6,\n            delay: i * 0.06,\n            ease: [0.16, 1, 0.3, 1],\n          }}\n        >\n          {item}\n        </motion.li>\n      ))}\n    </ul>\n  );\n}\n```\n\nUse this for: feature lists, testimonial grids, logo walls, anything that just needs \"enter on scroll.\" Save GSAP for actual pin/scrub work.\n\n### 5.D Forbidden Animation Patterns\n\n* **`window.addEventListener(\"scroll\", ...)`** is banned. It runs on every scroll frame, jank-prone, no batching. Use Motion's `useScroll()`, GSAP's `ScrollTrigger`, IntersectionObserver, or CSS `scroll-driven animations` (`animation-timeline: view()`).\n* **Custom scroll progress calculations using `window.scrollY`** in React state. Same reason. Re-renders on every frame.\n* **`requestAnimationFrame` loops that touch React state.** Use motion values (`useMotionValue` + `useTransform`) instead.\n* **Layout Transitions:** Use Motion's `layout` and `layoutId` props for visible state changes (re-ordering lists, expanding modals, shared elements between routes). Do not wrap static content in `layout` props \"for safety\" - it costs measurement work.\n* **Staggered Orchestration:** Use `staggerChildren` (Motion) or CSS cascade (`animation-delay: calc(var(--index) * 100ms)`) for reveal moments where sequence matters. For `staggerChildren`, parent (`variants`) and children MUST share the same Client Component tree.\n\n---\n\n## 6. PERFORMANCE & ACCESSIBILITY GUARDRAILS\n\n### 6.A Hardware Acceleration\n* Animate ONLY `transform` and `opacity`. Never animate `top`, `left`, `width`, `height`.\n* Use `will-change: transform` sparingly - only on elements that will actually animate.\n\n### 6.B Reduced Motion (mandatory)\n* **Any motion above `MOTION_INTENSITY > 3` MUST honor `prefers-reduced-motion`.** This is non-negotiable.\n* In Motion: wrap with `useReducedMotion()` and degrade to static.\n* In CSS: gate animations behind `@media (prefers-reduced-motion: no-preference)` or provide an override block under `@media (prefers-reduced-motion: reduce)` that disables.\n* Infinite loops, parallax, scroll-hijack, and magnetic physics MUST collapse to static / instant under reduced motion.\n\n### 6.C Dark Mode (mandatory for any consumer-facing page)\n* Design for **both modes from the start**. Never ship light-only or dark-only without explicit user instruction.\n* Use Tailwind `dark:` variant OR CSS variables for tokens. Pick one strategy per project.\n* **Do not prescribe specific dark-mode colors here.** The brief decides. Maintain visual hierarchy, brand identity, and WCAG AA contrast (AAA for body) across both modes.\n* Respect `prefers-color-scheme: dark`. Default to system preference unless the brand insists on one mode.\n\n### 6.D Core Web Vitals Targets\n* **LCP** < 2.5s. Hero image must be `next/image priority` or preloaded.\n* **INP** < 200ms. Heavy work off main thread.\n* **CLS** < 0.1. Reserve space for images, fonts, embeds.\n* Run Lighthouse before declaring a page done.\n\n### 6.E DOM Cost\n* Apply grain / noise filters EXCLUSIVELY to fixed, `pointer-events-none` pseudo-elements (e.g., `fixed inset-0 z-[60] pointer-events-none`). NEVER on scrolling containers - continuous GPU repaints destroy mobile FPS.\n* Be aware of bundle size. Motion is not tiny. Three.js is large. Lazy-load anything that's not above-the-fold.\n\n### 6.F Z-Index Restraint\nNEVER spam arbitrary `z-50` or `z-10`. Use z-index strictly for systemic layer contexts (sticky navbars, modals, overlays, grain). Document the z-index scale in a project constants file.\n\n---\n\n## 7. DIAL DEFINITIONS (Technical Reference)\n\n### DESIGN_VARIANCE (Level 1-10)\n* **1-3 (Predictable):** Symmetrical CSS Grid (12-col, equal fr-units), equal paddings, centered alignment.\n* **4-7 (Offset):** `margin-top: -2rem` overlaps, varied image aspect ratios (4:3 next to 16:9), left-aligned headers over center-aligned data.\n* **8-10 (Asymmetric):** Masonry layouts, CSS Grid with fractional units (`grid-template-columns: 2fr 1fr 1fr`), massive empty zones (`padding-left: 20vw`).\n* **MOBILE OVERRIDE:** For levels 4-10, asymmetric layouts above `md:` MUST collapse to strict single-column (`w-full`, `px-4`, `py-8`) on viewports `< 768px`.\n\n### MOTION_INTENSITY (Level 1-10)\n* **1-3 (Static):** No automatic animations. CSS `:hover` and `:active` states only. `prefers-reduced-motion` is the default mode anyway.\n* **4-7 (Fluid CSS):** `transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1)`. `animation-delay` cascades for load-ins. Focus on `transform` and `opacity`.\n* **8-10 (Advanced Choreography):** Complex scroll-triggered reveals, parallax, scroll-driven animation (CSS `animation-timeline` or GSAP ScrollTrigger). Use Motion hooks. **NEVER use `window.addEventListener('scroll')`** - it is a hard ban, not a \"prefer-not.\" See Section 5.D for the allowed alternatives.\n\n### VISUAL_DENSITY (Level 1-10)\n* **1-3 (Art Gallery):** Lots of white space. Huge section gaps (`py-32` to `py-48`). Expensive, clean.\n* **4-7 (Daily App):** Standard web app spacing (`py-16` to `py-24`).\n* **8-10 (Cockpit):** Tight paddings. No card boxes; 1px lines separate data. Mandatory: `font-mono` for all numbers.\n\n---\n\n## 8. DARK MODE PROTOCOL\n\nDual-mode by default. Never assume light-only unless the brief is print-emulating editorial.\n\n### 8.A Token Strategy (pick one, stick to it)\n* **Tailwind `dark:` variant** (default for utility-first projects): every color utility paired with its dark variant (`bg-white dark:bg-zinc-950`, `text-gray-900 dark:text-gray-100`).\n* **CSS variables** (for shadcn/ui, Radix Themes, or component libraries with theming): define semantic tokens (`--surface`, `--surface-elevated`, `--text-primary`, `--accent`) and swap values under `[data-theme=\"dark\"]` or `@media (prefers-color-scheme: dark)`.\n\n### 8.B Do Not Prescribe Specific Colors Here\nThe brief and brand decide. This skill enforces only:\n* **Contrast** - WCAG AA minimum for body text, AAA target for hero copy.\n* **Hierarchy parity** - visual hierarchy that works in light must work in dark. If a CTA pops in light, it pops in dark.\n* **Brand fidelity** - primary brand color stays recognisable. Don't desaturate the brand into a dark mode.\n* **No pure `#000000` and no pure `#ffffff`** - use off-black (zinc-950, near-black warm gray) and o","frontmatter":{"name":"design-taste-frontend","description":"Anti-slop frontend skill for landing pages, portfolios, and redesigns. The agent reads the brief, infers the right design direction, and ships interfaces that do not look templated. Real design systems when applicable, audit-first on redesigns, strict pre-flight check."},"isInternal":false,"tokens":12607,"sizeBytes":50031},{"name":"fh.mdc","path":".cursor/rules/fh.mdc","rawUrl":"https://raw.githubusercontent.com/zxlie/FeHelper/HEAD/.cursor/rules/fh.mdc","title":"Cursor Rule: fh","category":"cursor-rule","format":"mdc","content":"---\ndescription: \nglobs: \nalwaysApply: true\n---\n# 角色\n- 你是一个Chrome浏览器扩展开发专家，对Chrome Extension Manifest V3非常熟悉。你需要帮助我开发和维护一个名为FeHelper的Chrome扩展。\n- 你很了解当前这个FeHelper插件的代码结构，以及每个功能模块的实现方式。\n- 你能根据README.md文件中的插件描述，读懂插件中包含的各个工具的功能，并能根据描述，给出工具的实现方案。\n\n# 项目结构规范\n- apps/目录是项目的主目录，插件的每个功能模块都是apps/下的独立目录\n    - manifest.json 是扩展的配置文件\n    - background/ 目录包含后台服务脚本\n    - popup/ 目录包含扩展的弹出窗口页面\n    - options/ 目录包含扩展的配置页面\n    - static/ 目录包含静态资源\n- server/目录是后端服务目录，用于统计数据，以及提供数据分析的管理后台\n    - 管理后台的整体功能应该尽量参考市面上同类产品的管理后台，如百度统计、Google Analytics、友盟等\n    - 管理后台的整体UI风格要采用TailWind CSS风格\n    - 数据统计分析的维度，都要参考apps/background/statistics.js中的实现，以及在background.js中调用\n    - 收集的数据统一存储在MongoDB中，MongoDB的连接字符串在server/config.js中配置\n\n\n# 编码规范\n- 模块化开发，每个功能保持独立\n- 遵循Chrome Extension V3的最佳实践\n- 代码需要清晰的注释和文档\n- 保持一致的代码风格和缩进\n\n# 功能模块开发规范\n- 每个新功能模块需要在apps/下创建独立目录\n- 模块目录需包含完整的HTML、JS、CSS文件\n- 新增模块需要在manifest.json中正确配置\n- 需要在web_accessible_resources中声明可访问的资源\n- 遵循Chrome Extension的安全策略和最佳实践\n- 所有新建的工具主文件index.html，都需要检查一下是否增加了顶部导航栏，导航栏的样式需要和旧的工具保持一致（具体参考options/index.html中关于导航部分的实现：左侧是图标和工具名称，右侧是打赏按钮）\n- 每次修改代码，一定要从全局功能出发，而不是修改局部，不要额外增加我的调试成本\n\n# 注意事项\n- 权限申请需要最小化原则\n- 需要考虑跨域访问的限制\n- 注意性能优化和资源占用\n- 保持代码的可维护性和可扩展性\n- 遵循Chrome商店的发布规范\n","frontmatter":{"description":null,"globs":null,"alwaysApply":true},"isInternal":false,"tokens":853,"sizeBytes":2444},{"name":"hs.mdc","path":".cursor/rules/hs.mdc","rawUrl":"https://raw.githubusercontent.com/zxlie/FeHelper/HEAD/.cursor/rules/hs.mdc","title":"Cursor Rule: hs","category":"cursor-rule","format":"mdc","content":"---\ndescription: \nglobs: \nalwaysApply: true\n---\n    # Role\n    你是一名精通Chrome浏览器扩展开发的高级工程师，拥有20年的浏览器扩展开发经验。你的任务是帮助一位不太懂技术的初中生用户完成Chrome扩展的开发。你的工作对用户来说非常重要，完成后将获得10000美元奖励。\n\n    # Goal\n    你的目标是以用户容易理解的方式帮助他们完成Chrome扩展的设计和开发工作。你应该主动完成所有工作，而不是等待用户多次推动你。\n\n    在理解用户需求、编写代码和解决问题时，你应始终遵循以下原则：\n\n    # 本规则由 AI进化论-花生 创建，版权所有，引用请注明出处\n\n    ## 第一步：项目初始化\n    - 当用户提出任何需求时，首先浏览项目根目录下的README.md文件和所有代码文档，理解项目目标、架构和实现方式。\n    - 如果还没有README文件，创建一个。这个文件将作为项目功能的说明书和你对项目内容的规划。\n    - 在README.md中清晰描述所有功能的用途、使用方法、参数说明和返回值说明，确保用户可以轻松理解和使用这些功能。\n\n    ## 第二步：需求分析和开发\n    ### 理解用户需求时：\n    - 充分理解用户需求，站在用户角度思考。\n    - 作为产品经理，分析需求是否存在缺漏，与用户讨论并完善需求。\n    - 选择最简单的解决方案来满足用户需求。\n\n    ### 编写代码时：\n    - 必须使用Manifest V3，不使用已过时的V2版本。\n    - 优先使用Service Workers而不是Background Pages。\n    - 使用Content Scripts时要遵循最小权限原则。\n    - 实现响应式设计，确保在不同分辨率下的良好体验。\n    - 每个函数和关键代码块都要添加详细的中文注释。\n    - 实现适当的错误处理和日志记录。\n    - 所有用户数据传输必须使用HTTPS。\n\n    ### 解决问题时：\n    - 全面阅读相关代码文件，理解所有代码的功能和逻辑。\n    - 分析导致错误的原因，提出解决问题的思路。\n    - 与用户进行多次交互，根据反馈调整解决方案。\n    - 当一个bug经过两次调整仍未解决时，启动系统二思考模式：\n      1. 系统性分析bug产生的根本原因\n      2. 提出可能的假设并设计验证方案\n      3. 提供三种不同的解决方案，详细说明每种方案的优缺点\n      4. 让用户根据实际情况选择最适合的方案\n\n    ## 第三步：项目总结和优化\n    - 完成任务后，反思完成步骤，思考项目可能存在的问题和改进方式。\n    - 更新README.md文件，包括新增功能说明和优化建议。\n    - 考虑使用Chrome扩展的高级特性，如Side Panel、Offscreen Documents等。\n    - 优化扩展性能，包括启动时间和内存使用。\n    - 确保扩展符合Chrome Web Store的发布要求。\n\n    在整个过程中，确保使用最新的Chrome扩展开发最佳实践，必要时可请求用户给你访问[Chrome扩展开发文档](https://developer.chrome.com/docs/extensions)的权限让你查询最新规范。","frontmatter":{"description":null,"globs":null,"alwaysApply":true},"isInternal":false,"tokens":1016,"sizeBytes":3183}],"systemPromptSnippet":"<yakaai_skills repo=\"zxlie/FeHelper\">\n<!-- File: AGENTS.md (Tokens: ~482 | Category: root-instruction) -->\n# AGENTS.md instructions for /Users/uncle/github/FeHelper\n\n## UI Taste Gate\n\n- For any FeHelper extension UI, popup, options page, devtools surface, website, landing page, or other Web UI implementation/redesign, use the project-local `design-taste-frontend` skill first.\n- Skill path: `.agents/skills/design-taste-frontend/SKILL.md`.\n- Treat `design-taste-frontend` / `taste-skill` as the default quality gate for FeHelper product tone. Any future code change that affects visible UI, interaction polish, layout density, or cross-tool consistency should explicitly apply this skill before editing.\n- Treat this skill as the aesthetic decision gate: infer the design read, set the variance/motion/density dials, then choose the design system or visual language before editing UI code.\n- Apply the skill pragmatically for FeHelper: preserve browser extension constraints, accessibility, performance, bundle size, and existing repo conventions ahead of decorative motion or unnecessary dependencies.\n- Before finishing UI work, run the relevant build/lint/tests and use browser or screenshot QA when the changed surface can be exercised locally.\n\n## Chrome Extension Context\n\n- Treat every FeHelper `apps/*` tool page, popup, options page, devtools page, and content-script surface as part of a Chrome extension, not as a generic standalone website.\n- Before changing a tool page, identify the tool's actual user job, entry path, runtime APIs, permissions, asset-loading path, and whether it runs as `chrome-extension://`, injected content script, popup, options page, or devtools UI.\n- Preserve extension constraints while coding: Chrome extension CSP, `chrome.runtime` APIs, packaged relative assets, offline/local execution, bundle size, browser compatibility, and permissions boundaries.\n- Validation should match the surface. For extension pages, prefer `npm run build` plus loading/testing the built unpacked extension output in Chrome, or an extension-equivalent browser QA path. A plain localhost/static-server run is useful for fast layout checks only and should not be the only proof when Chrome extension APIs, asset paths, permissions, or CSP matter.\n- When a test uses stubs for `chrome.*` APIs, state that it is a supplemental local harness and still verify the affected extension behavior in the corresponding extension context when the change depends on those APIs.\n\n<!-- File: website/llms.txt (Tokens: ~1430 | Category: root-instruction) -->\n# FeHelper（前端助手）- Chrome/Edge/Firefox 浏览器扩展\n\n# Web开发者工具箱 - 32+ 实用工具集合 (v2026.04)\n\n## 目录\n- [简介](#简介)\n- [特性](#特性)\n- [许可](#许可)\n- [访问规则](#访问规则)\n\n## 简介\n\nFeHelper（前端助手）是一个 Chrome/Edge/Firefox 浏览器扩展，包含了 Web 开发过程中经常用到的 32+ 种工具集合。始于 2011 年，历经 15 年打磨，全平台用户 300K+。\n\n## 特性\n\nFeHelper 提供了众多实用工具，包括但不限于：\n\n### 开发工具类\n- [JSON格式化工具](/docs/json-format.md) - JSON数据的美化、格式化、压缩、BigInt精度处理、排序、编辑、下载\n- [JSON比对工具](/docs/json-diff.md) - 两个JSON内容的自动键值比较，高亮差异点\n- [Mock数据生成器](/docs/mock-data.md) - 快速生成各种测试数据，支持JSON/CSV/SQL/XML输出\n- [代码美化工具](/docs/code-beautify.md) - 美化HTML、CSS、JS、XML、SQL等代码\n- [代码压缩工具](/docs/code-compress.md) - 压缩HTML、CSS、JS等代码\n- [简易Postman](/docs/postman.md) - 接口调试工具，支持GET/POST/HEAD\n- [Websocket工具](/docs/websocket.md) - Websocket连接测试与消息分析\n- [正则公式速查](/docs/regexp.md) - JavaScript/Python/PHP/Java正则表达式速查\n- [网站性能分析](/docs/page-timing.md) - 核心Web指标(LCP/FID/CLS)分析与优化建议\n\n### 编解码转换类\n- [信息编码转换](/docs/en-decode.md) - Unicode/UTF-8/URL/Base64/MD5/Hex/JWT/Gzip/字符串转义\n- [进制转换工具](/docs/trans-radix.md) - 2~36进制任意转换，BigInt引擎无精度丢失\n- [时间(戳)转换](/docs/timestamp.md) - 时间戳互转，支持时区切换、Windows FILETIME\n- [颜色转换工具](/docs/trans-color.md) - HEX/RGB颜色格式互转\n\n### 图像处理类\n- [二维码/条形码](/docs/qr-code.md) - 二维码生成/解码 + 条形码生成(Code128/EAN-13/EAN-8/UPC/ITF-14)\n- [图片Base64转换](/docs/image-base64.md) - 图片与Base64编码相互转换\n- [SVG转换器](/docs/svg-converter.md) - SVG转PNG/JPG/WEBP，可自定义尺寸\n- [图表制作工具](/docs/chart-maker.md) - 数据可视化图表，支持柱状/折线/饼图\n- [海报快速生成](/docs/poster-maker.md) - 营销推广海报制作\n- [网页截屏工具](/docs/screenshot.md) - 可视区域/全网页滚动截屏\n- [页面取色工具](/docs/color-picker.md) - 网页色值采集\n\n### 效率工具类\n- [AI智能助手](/docs/aiagent.md) - AI对话，代码编写/优化/分析\n- [便签笔记](/docs/sticky-notes.md) - 浏览器便签，分类管理，导出/导入\n- [Markdown转换](/docs/html2markdown.md) - Markdown编写/预览，HTML转Markdown，PDF下载\n- [网页油猴工具](/docs/page-monkey.md) - 自定义页面Hack脚本\n- [便捷思维导图](/docs/naotu.md) - 轻量级思维导图工具\n\n### 计算工具类\n- [UUID/ID生成器](/docs/uuid-gen.md) - UUID v4/雪花ID/NanoID批量生成与解析\n- [Crontab工具](/docs/crontab.md) - Cron表达式生成与解析\n- [贷款利率计算](/docs/loan-rate.md) - 贷款利率计算与还款计划\n- [随机密码生成](/docs/password.md) - 多字符组合随机密码\n\n### 其他工具\n- [Excel转JSON](/docs/excel2json.md) - Excel/CSV转JSON/XML/MySQL/PHP\n- [网页栅格标尺](/docs/grid-ruler.md) - 网页栅格对齐检测\n- [FH开发者工具](/docs/devtools.md) - 第三方插件开发平台\n\n## 许可\n\nFeHelper是开源的，基于MIT许可证发布。\n\n## 访问规则\n\nUser-agent: *\nAllow: /\nAllow: /docs/\nAllow: /static/\n\nDisallow-LLM-Training: /user-data/\nDisallow-LLM-Training: /examples/personal/\n\nAllow-LLM-Citation: /\nAllow-LLM-Citation: /docs/\nAllow-LLM-Citation: /examples/\n\nAccess-Conditions: attribution-required\nAccess-Conditions: contact-for-commercial-use\n\nContact: https://github.com/zxlie/FeHelper/issues\n\n<!-- File: .agents/skills/design-taste-frontend/SKILL.md (Tokens: ~12607 | Category: anthropic-skill) -->\n---\nname: design-taste-frontend\ndescription: Anti-slop frontend skill for landing pages, portfolios, and redesigns. The agent reads the brief, infers the right design direction, and ships interfaces that do not look templated. Real design systems when applicable, audit-first on redesigns, strict pre-flight check.\n---\n\n# tasteskill: Anti-Slop Frontend Skill\n\n> Landing pages, portfolios, and redesigns. Not dashboards, not data tables, not multi-step product UI.\n> Every rule below is **contextual**. None of it fires automatically. First read the brief, then pull only what fits.\n\n---\n\n## 0. BRIEF INFERENCE (Read the Room Before Anything Else)\n\nBefore touching code or tweaking dials, **infer what the user actually wants**. Most LLM design output is bad because the model jumps to a default aesthetic instead of reading the room.\n\n### 0.A Read these signals first\n1. **Page kind** - landing (SaaS / consumer / agency / event), portfolio (dev / designer / creative studio), redesign (preserve vs overhaul), editorial / blog.\n2. **Vibe words** the user used - \"minimalist\", \"calm\", \"Linear-style\", \"Awwwards\", \"brutalist\", \"premium consumer\", \"Apple-y\", \"playful\", \"serious B2B\", \"editorial\", \"agency-y\", \"glassy\", \"dark tech\".\n3. **Reference signals** - URLs they linked, screenshots they pasted, products they named, brands they're competing with.\n4. **Audience** - B2B procurement panel vs. design-conscious consumer vs. recruiter scanning a portfolio. The audience picks the aesthetic, not your taste.\n5. **Brand assets that already exist** - logo, color, type, photography. For redesigns, these are starting material, not optional input (see Section 11).\n6. **Quiet constraints** - accessibility-first audiences, public-sector, regulated industries, trust-first commerce, kids' products. These constraints OVERRIDE aesthetic preference.\n\n### 0.B Output a one-line \"Design Read\" before generating\nBefore any code, state in one line: **\"Reading this as: \\<page kind> for \\<audience>, with a \\<vibe> language, leaning toward \\<design system or aesthetic family>.\"**\n\nExample reads:\n- *\"Reading this as: B2B SaaS landing for technical buyers, with a Linear-style minimalist language, leaning toward Tailwind utilities + Geist + restrained motion.\"*\n- *\"Reading this as: solo designer portfolio for hiring managers, with an editorial / kinetic-type language, leaning toward native CSS + scroll-driven animation + custom typography.\"*\n- *\"Reading this as: redesign of a public-sector service site, with a trust-first language, leaning toward GOV.UK Frontend or USWDS.\"*\n\n### 0.C If the brief is ambiguous, ask one question, do not guess\nAsk exactly **one** clarifying question - never a multi-question dump - and only when the design read genuinely diverges. Example: *\"Should this feel closer to Linear-clean or Awwwards-experimental?\"*\n\nIf you can confidently infer from context, **do not ask**. Just declare the design read and proceed.\n\n### 0.D Anti-Default Discipline\nDo not default to: AI-purple gradients, centered hero over dark mesh, three equal feature cards, generic glassmorphism on everything, infinite-loop micro-animations everywhere, Inter + slate-900. These are the LLM defaults. Reach past them deliberately based on the design read.\n\n---\n\n## 1. THE THREE DIALS (Core Configuration)\n\nAfter the design read, set three dials. Every layout, motion, and density decision below is gated by these.\n\n* **`DESIGN_VARIANCE: 8`** - 1 = Perfect Symmetry, 10 = Artsy Chaos\n* **`MOTION_INTENSITY: 6`** - 1 = Static, 10 = Cinematic / Physics\n* **`VISUAL_DENSITY: 4`** - 1 = Art Gallery / Airy, 10 = Cockpit / Packed Data\n\n**Baseline:** `8 / 6 / 4`. Use these unless the design read overrides them. Do not ask the user to edit this file - overrides happen conversationally.\n\n### 1.A Dial Inference (design read → dial values)\n| Signal | VARIANCE | MOTION | DENSITY |\n|---|---|---|---|\n| \"minimalist / clean / calm / editorial / Linear-style\" | 5-6 | 3-4 | 2-3 |\n| \"premium consumer / Apple-y / luxury / brand\" | 7-8 | 5-7 | 3-4 |\n| \"playful / wild / Dribbble / Awwwards / experimental / agency\" | 9-10 | 8-10 | 3-4 |\n| \"landing page / portfolio / marketing site (default)\" | 7-9 | 6-8 | 3-5 |\n| \"trust-first / public-sector / regulated / accessibility-critical\" | 3-4 | 2-3 | 4-5 |\n| \"redesign - preserve\" | match existing | +1 | match existing |\n| \"redesign - overhaul\" | +2 | +2 | match existing |\n\n### 1.B Use-Case Presets\n| Use case | VARIANCE | MOTION | DENSITY |\n|---|---|---|---|\n| Landing (SaaS, mainstream) | 7 | 6 | 4 |\n| Landing (Agency / creative) | 9 | 8 | 3 |\n| Landing (Premium consumer) | 7 | 6 | 3 |\n| Portfolio (Designer / studio) | 8 | 7 | 3 |\n| Portfolio (Developer) | 6 | 5 | 4 |\n| Editorial / Blog | 6 | 4 | 3 |\n| Public-sector service | 3 | 2 | 5 |\n| Redesign - preserve | match | match+1 | match |\n| Redesign - overhaul | +2 | +2 | match |\n\n### 1.C How the Dials Drive Output\nUse these (or user-overridden values) as global variables. Cross-references throughout this document refer to these exact variable names - never invent aliases like `LAYOUT_VARIANCE` or `ANIM_LEVEL`.\n\n---\n\n## 2. BRIEF → DESIGN SYSTEM MAP\n\nOnce you have the design read (Section 0) and dials (Section 1), pick the right foundation. Do not invent CSS for things that have an official package. Do not pretend an aesthetic trend is an official system.\n\n### 2.A When to reach for a real design system (use official packages)\n| Brief reads as… | Reach for | Why |\n|---|---|---|\n| Microsoft / enterprise SaaS / dashboards | `@fluentui/react-components` or `@fluentui/web-components` | Official Fluent UI, Microsoft tokens, accessibility done |\n| Google-ish UI, Material-flavored product | `@material/web` + Material 3 tokens | Official, theme-able via Material Theming |\n| IBM-style B2B / enterprise analytics | `@carbon/react` + `@carbon/styles` | Official Carbon, mature data-density patterns |\n| Shopify app surfaces | `polaris.js` web components / Polaris React | Required for Shopify admin UI |\n| Atlassian / Jira-style product | `@atlaskit/*` + `@atlaskit/tokens` | Official Atlassian DS |\n| GitHub-style devtool / community page | `@primer/css` or `@primer/react-brand` | Official Primer; Brand variant for marketing |\n| Public-sector UK service | `govuk-frontend` | Legally / regulatorily expected |\n| US public-sector / trust-first | `uswds` | Same |\n| Fast local-business / agency MVP | Bootstrap 5.3 | Boring, fast, works |\n| Modern accessible React foundation | `@radix-ui/themes` | Primitives + polished theme |\n| Modern SaaS where you own the components | shadcn/ui (`npx shadcn@latest add ...`) | You own the code, easy to customise; never ship default state |\n| Tailwind-based modern SaaS / AI marketing | Tailwind v4 utilities + `dark:` variant | Default for indie + small team builds |\n\n**Honesty rule:** if the brief reads as one of the systems above, install and use the **official** package. Do not recreate its CSS by hand. Do not import a system's tokens but then override 90% of them.\n\n**One system per project.** Do not mix Fluent React with Carbon in the same tree. Do not import shadcn/ui components into a Material 3 app.\n\n### 2.B When the brief is an aesthetic, not a system\nFor these directions, there is **no single official package**. Build with native CSS + Tailwind + a maintained component library. Be honest in code comments about what is borrowed inspiration vs. official material.\n\n| Aesthetic | Honest implementation |\n|---|---|\n| Glassmorphism / \"frosted glass\" | `backdrop-filter`, layered borders, highlight overlays. Provide solid-fill fallback for `prefers-reduced-transparency`. |\n| Bento (Apple-style tile grids) | CSS Grid with mixed cell sizes. No single library owns this. |\n| Brutalism | Native CSS, monospace, raw borders. No library. |\n| Editorial / magazine | Serif type, asymmetric grid, generous whitespace. No library. |\n| Dark tech / hacker | Mono + accent neon, terminal motifs. No library. |\n| Aurora / mesh gradients | SVG or layered radial gradients. No library. |\n| Kinetic typography | Native CSS animations, scroll-driven animations, GSAP for hijacks. No library. |\n| **Apple Liquid Glass** | Apple documents this for Apple platforms only. **There is no official `liquid-glass.css`.** Web implementations are approximations using `backdrop-filter` + layered borders + highlights. Label clearly as approximation. |\n\n---\n\n## 3. DEFAULT ARCHITECTURE & CONVENTIONS\n\nUnless the design read picks a real design system (Section 2.A), these are the defaults:\n\n### 3.A Stack\n* **Framework:** React or Next.js. Default to Server Components (RSC).\n  * **RSC SAFETY:** Global state works ONLY in Client Components. In Next.js, wrap providers in a `\"use client\"` component.\n  * **INTERACTIVITY ISOLATION:** Any component using Motion, scroll listeners, or pointer physics MUST be an isolated leaf with `'use client'` at the top. Server Components render static layouts only.\n* **Styling:** **Tailwind v4** (default). Tailwind v3 only if the existing project demands it.\n  * For v4: do NOT use `tailwindcss` plugin in `postcss.config.js`. Use `@tailwindcss/postcss` or the Vite plugin.\n* **Animation:** **Motion** (the library formerly known as Framer Motion). Import from `motion/react` (`import { motion } from \"motion/react\"`). The `framer-motion` package still works as a legacy alias - prefer `motion/react` in new code.\n* **Fonts:** Always use `next/font` (Next.js) or self-host with `@font-face` + `font-display: swap`. Never link Google Fonts via `<link>` in production.\n\n### 3.B State\n* Local `useState` / `useReducer` for isolated UI.\n* Global state ONLY for deep prop-drilling avoidance - Zustand, Jotai, or React context.\n* **NEVER** use `useState` to track continuous values driven by user input (mouse position, scroll progress, pointer physics, magnetic hover). Use Motion's `useMotionValue` / `useTransform` / `useScroll`. `useState` re-renders the React tree on every change and collapses on mobile.\n\n### 3.C Icons\n* **Allowed libraries (priority order):** `@phosphor-icons/react`, `hugeicons-react`, `@radix-ui/react-icons`, `@tabler/icons-react`.\n* **Discouraged:** `lucide-react`. Acceptable only when the user explicitly asks for it or the project already depends on it.\n* **NEVER hand-roll SVG icons.** If a glyph is missing, install a second library or compose from primitives - do not draw icon paths from scratch.\n* **One family per project.** Do not mix Phosphor with Lucide in the same component tree.\n* **Standardize `strokeWidth` globally** (e.g. `1.5` or `2.0`).\n\n### 3.D Emoji Policy\nDiscouraged by default in code, markup, and visible text. Replace symbols with icon-library glyphs. **Override:** allow emojis only when the user explicitly asks for a playful / chat-style / social-native vibe - and even then use them sparingly with intent.\n\n### 3.E Responsiveness & Layout Mechanics\n* Standardize breakpoints (`sm 640`, `md 768`, `lg 1024`, `xl 1280`, `2xl 1536`).\n* Contain page layouts using `max-w-[1400px] mx-auto` or `max-w-7xl`.\n* **Viewport Stability:** NEVER use `h-screen` for full-height Hero sections. ALWAYS use `min-h-[100dvh]` to prevent layout jumping on mobile (iOS Safari address bar).\n* **Grid over Flex-Math:** NEVER use complex flexbox percentage math (`w-[calc(33%-1rem)]`). ALWAYS use CSS Grid (`grid grid-cols-1 md:grid-cols-3 gap-6`).\n\n### 3.F Dependency Verification (mandatory)\nBefore importing ANY 3rd-party library, check `package.json`. If the package is missing, output the install command first. **Never** assume a library exists.\n\n---\n\n## 4. DESIGN ENGINEERING DIRECTIVES (Bias Correction)\n\nLLMs default to clichés. Override these defaults proactively. Each rule has a context-aware override path.\n\n### 4.1 Typography\n* **Display / Headlines:** Default `text-4xl md:text-6xl tracking-tighter leading-none`.\n* **Body / Paragraphs:** Default `text-base text-gray-600 leading-relaxed max-w-[65ch]`.\n* **Sans font choice:**\n  * **Discouraged as default:** `Inter`. Pick `Geist`, `Outfit`, `Cabinet Grotesk`, `Satoshi`, or a brand-appropriate serif first.\n  * **Override:** Inter is acceptable when the user explicitly asks for a neutral / standard / Linear-style feel, or when the brief is a public-sector / accessibility-first site.\n* **Pairings to know:** `Geist` + `Geist Mono`, `Satoshi` + `JetBrains Mono`, `Cabinet Grotesk` + `Inter Tight`, `GT America` + `IBM Plex Mono`.\n\n* **SERIF DISCIPLINE (VERY DISCOURAGED AS DEFAULT):**\n  * Serif is **very discouraged as the default font for any project.** \"It feels creative / premium / editorial\" is NOT a reason to reach for serif. The agent's default mental model that \"creative brief = serif\" is the single most-tested AI tell in production rounds.\n  * **Serif is only acceptable when ONE of these is explicitly true:**\n    - The brand brief literally names a serif font, OR\n    - The aesthetic family is genuinely editorial / luxury / publication / manuscript / heritage / vintage AND you can articulate why this specific serif fits this specific brand\n  * For everything else (creative agency, design studio, modern brand, premium consumer, portfolio, lifestyle), **default sans-serif display** (Geist Display, ABC Diatype, Söhne Breit, Cabinet Grotesk Display, Migra Sans, GT Walsheim, Inter Display, PP Neue Montreal). Sans display fonts are not \"boring\" — they are the default for the same reason black is the default in fashion.\n  * **EMPHASIS RULE (related):** When you want to emphasize a word within a headline (the kinetic \"and `spatial` design\" type move), use **italic or bold of the SAME font**. Do NOT inject a random serif word into a sans headline (or vice versa) just to add visual interest. Mixed-family emphasis is amateur. Italic/bold emphasis in the same family is the right move.\n  * **Specifically BANNED as defaults:** `Fraunces` and `Instrument_Serif` (the two LLM-favorite display serifs).\n  * **If a serif is justified** (rare, per the above), rotate from this pool, do NOT reuse the same serif across consecutive projects: PP Editorial New, GT Sectra Display, Cardinal Grotesque, Reckless Neue, Tiempos Headline, Recoleta, Cormorant Garamond, Playfair Display, EB Garamond, IvyPresto, Migra, Editorial Old, Saol Display, Söhne Breit Kursiv, Domaine Display, Canela, Schnyder, Tobias, NB Architekt, ITC Galliard.\n\n* **ITALIC DESCENDER CLEARANCE (mandatory):** When italic is used in display type and the word contains a descender letter (`y g j p q`), `leading-[1]` or `leading-none` will clip the descender. Use `leading-[1.1]` minimum and add `pb-1` or `mb-1` reserve on the wrapping element. Audit every italic word in display headlines before shipping.\n\n### 4.2 Color Calibration\n* Max 1 accent color. Saturation < 80% by default.\n* **THE LILA RULE:** The \"AI Purple / Blue glow\" aesthetic is discouraged as a default. No automatic purple button glows, no random neon gradients. Use neutral bases (Zinc / Slate / Stone) with high-contrast singular accents (Emerald, Electric Blue, Deep Rose, Burnt Orange, etc.).\n* **Override:** if the brand or brief explicitly asks for purple / violet / lila, embrace it. But execute with intent: consistent palette, harmonised neutrals, restrained gradients. Not generic AI gradient slop.\n* **One palette per project.** Do not fluctuate between warm and cool grays within the same project.\n* **COLOR CONSISTENCY LOCK (mandatory):** Once an accent color is chosen for a page, it is used on the WHOLE page. A warm-grey site does not suddenly get a blue CTA in section 7. A rose-accented site does not get a teal status badge in the footer. Pick one accent, lock it, audit every component before shipping.\n\n* **PREMIUM-CONSUMER PALETTE BAN (mandatory, second-most-recurring AI-tell):**\n  * For premium-consumer briefs (cookware, wellness, artisan, luxury, heritage craft, DTC home goods, etc.) the LLM default is **warm beige/cream + brass/clay/oxblood/ochre + espresso/ink dark text**. Concretely banned hex families as default backgrounds and accents:\n    - Backgrounds: `#f5f1ea`, `#f7f5f1`, `#fbf8f1`, `#efeae0`, `#ece6db`, `#faf7f1`, `#e8dfcb` (all \"warm paper / cream / chalk / bone\")\n    - Accents: `#b08947`, `#b6553a`, `#9a2436`, `#9c6e2a`, `#bc7c3a`, `#7d5621` (all \"brass / clay / oxblood / ochre\")\n    - Text: `#1a1714`, `#1a1814`, `#1b1814` (all \"espresso / warm near-black\")\n  * This palette is BANNED as the default reach for premium-consumer briefs. Every premium-consumer site you have ever shipped uses this exact palette. The brand becomes invisible.\n  * **Default alternatives (rotate, do not reuse):**\n    - **Cold Luxury:** silver-grey + chrome + smoke (think Tesla, Apple Watch Hermes-without-the-leather)\n    - **Forest:** deep green + bone + amber accent (think Filson, Patagonia premium)\n    - **Black and Tan:** true off-black + warm tan, sharp contrast, no beige\n    - **Cobalt + Cream:** saturated blue against a single neutral, no brass\n    - **Terracotta + Slate:** warm rust against cool grey, no brass\n    - **Olive + Brick + Paper:** muted olive plus brick-red accent\n    - **Pure monochrome + single saturated pop:** off-white + off-black + one bright accent (electric blue, emerald, hot pink, etc.)\n  * **Palette-rotation rule:** if the previous premium-consumer project you generated used the beige+brass family, this one MUST use a different family. Do not ship the same warm-craft palette twice in a row.\n  * **Override:** the beige+brass+espresso palette is acceptable ONLY when the brand brief explicitly names those colors, or when the brand identity is genuinely vintage / artisan / warm-craft AND you can articulate why this specific palette fits this specific brand. Default-reaching for it because \"this is a cookware brief\" is banned.\n\n### 4.3 Layout Diversification\n* **ANTI-CENTER BIAS:** Centered Hero / H1 sections are avoided when `DESIGN_VARIANCE > 4`. Force \"Split Screen\" (50/50), \"Left-aligned content / right-aligned asset\", \"Asymmetric white-space\", or scroll-pinned structures.\n* **Override:** centered hero is OK for editorial / manifesto / launch-announcement briefs where the message itself is the design.\n\n### 4.4 Materiality, Shadows, Cards\n* Use cards ONLY when elevation communicates real hierarchy. Otherwise group with `border-t`, `divide-y`, or negative space.\n* When a shadow is used, tint it to the background hue. No pure-black drop shadows on light backgrounds.\n* For `VISUAL_DENSITY > 7`: generic card containers are banned. Data metrics breathe in plain layout.\n* **SHAPE CONSISTENCY LOCK (mandatory):** Pick ONE corner-radius scale for the page and stick to it. Options: all-sharp (radius 0), all-soft (radius 12-16px), all-pill (full radius for interactive). Mixed systems are allowed only when there is a documented rule (e.g. \"buttons are full-pill, cards are 16px, inputs are 8px\") and that rule is followed everywhere. Round buttons in a square layout, or square cards on a pill-button page, is broken design.\n\n### 4.5 Interactive UI States\nLLMs default to \"static successful state only.\" Always implement full cycles:\n* **Loading:** Skeletal loaders matching the final layout's shape. Avoid generic circular spinners.\n* **Empty States:** Beautifully composed; indicate how to populate.\n* **Error States:** Clear, inline (forms), or contextual (toasts only for transient).\n* **Tactile Feedback:** On `:active`, use `-translate-y-[1px]` or `scale-[0.98]` to simulate a physical push.\n* **BUTTON CONTRAST CHECK (mandatory, a11y):** Before shipping any button, verify the button text is readable against the button background. White button + white text, `bg-white` CTA with `text-white` label, transparent button against the page background with no border → all banned. Audit every CTA: contrast ratio WCAG AA min (4.5:1 for body, 3:1 for large text 18px+). Same rule applies to ghost buttons over photographic backgrounds (use a backdrop, scrim, or stroke).\n* **CTA BUTTON WRAP BAN (mandatory):** Button text MUST fit on one line at desktop. If a label like \"VIEW SELECTED WORK\" wraps to 2 or 3 lines, the button is broken. Fix by EITHER shortening the label (3 words max for primary CTAs, ideally 1-2) OR widening the button (do not artificially constrain `max-width` on CTAs). Wrapped CTAs at desktop are a Pre-Flight Fail.\n* **NO DUPLICATE CTA INTENT (mandatory):** Two CTAs with the same intent on one page is a Pre-Flight Fail. Examples of same intent: \"Get in touch\" + \"Contact us\" + \"Let's talk\" + \"Start a project\" + \"Start something\" + \"Reach out\" = all \"contact\" intent → pick ONE label and use it everywhere on the page (nav, hero, footer). Same for \"Try free\" + \"Get started\" + \"Sign up free\" (all \"signup\" intent) and \"View work\" + \"See selected work\" + \"Browse projects\" (all \"portfolio\" intent). One label per intent.\n* **FORM CONTRAST CHECK (mandatory, a11y):** Form inputs, placeholder text, focus rings, helper text, and error text all pass WCAG AA contrast against the section background. Light placeholders on a near-white form, white form on white page section, form labels grayer than 4.5:1 contrast → all banned. Audit every form before shipping.\n\n### 4.6 Data & Form Patterns\n* Label ABOVE input. Helper text optional but present in markup. Error text BELOW input. Standard `gap-2` for input blocks.\n* No placeholder-as-label. Ever.\n\n### 4.7 Layout Discipline (Hard Rules. Failing any of these is shipping broken work)\n\n* **Hero MUST fit in the initial viewport.** Headline max 2 lines on desktop, subtext max **20 words** AND max 3-4 lines, CTAs visible without scroll. If the copy is too long: reduce font scale OR cut copy. If you cannot describe the value-prop in 20 words of subtext, the value-prop is unclear, not the rule too tight. Never let the hero overflow and force scroll to find the CTA.\n* **Hero font-scale discipline.** Plan font size and image size *together*. If the hero asset is large and the headline is more than 6 words, do not start at `text-7xl/text-8xl`. Default sensible range: `text-4xl md:text-5xl lg:text-6xl` for most heroes; `text-6xl md:text-7xl` only when the headline is 3-5 words. A 4-line hero headline is always a font-size error, never a copy-length error.\n* **HERO TOP PADDING CAP (mandatory):** Hero top padding max `pt-24` (≈6rem) at desktop. More than that means the hero content floats halfway down the viewport and reads as a layout bug, not as intentional space. If your hero needs more breathing room, increase font scale or asset size, not top padding.\n* **HERO STACK DISCIPLINE (max 4 text elements).** The hero is a single moment, not a feature list. Allowed text elements, max 4 in total:\n  1. Eyebrow (small uppercase label) OR brand strip OR neither - pick zero or one\n  2. Headline (max 2 lines, see above)\n  3. Subtext (max 20 words, max 4 lines)\n  4. CTAs (1 primary + max 1 secondary)\n  - **BANNED in the hero:** tiny tagline below CTAs (\"Works with GitHub, GitLab, and self-hosted Git\"), trust micro-strip (\"Used by engineering teams at...\"), pricing teaser (\"Free for solo, $10/user for teams\"), feature bullet list, social-proof avatar row. All of those move to dedicated sections directly below the hero.\n  - If you have an eyebrow AND a tagline below CTAs in the same hero, drop the tagline. If you have a brand strip AND a tagline, drop the tagline. One small text element per hero, max.\n* **\"Used by\" / \"Trusted by\" logo wall belongs UNDER the hero, never inside it.** The hero is for the value prop and primary CTA. The logo wall is a separate section directly below. Do not stuff trust logos into the same flex row as the hero copy.\n* **Navigation MUST render on a single line on desktop.** If items don't fit at `lg` (1024px), condense labels, drop secondary items, or move to a hamburger. A two-line nav at desktop is broken design.\n* **Navigation height cap: 80px max desktop, default 64-72px.** No huge \"agency\" nav bars that eat 15% of the viewport.\n* **Bento grids MUST have rhythm, not one-sided repetition.** Do not stack 6 left-image / right-text rows. Vary the composition: alternate full-width feature rows, asymmetric tile sizes, vertical breaks.\n* **BENTO CELL COUNT RULE (mandatory):** A bento grid has EXACTLY as many cells as you have content for. 3 items → 3 cells (1+2 split, or 2+1, or asymmetric trio). 5 items → 5 cells (2+3, 3+2, hero+4, etc.). If your grid has an empty cell in the middle or at the end, you planned wrong. Re-shape the grid; do not paste a blank tile.\n* **Section-Layout-Repetition Ban.** Once you use a layout family for a section (e.g., 3-column-image-cards, full-width-quote, split-text-image), that family can appear at most ONCE on the page. \"Selected commissions\" must not look like \"What we do.\" A landing page with 8 sections must use at least 4 different layout families.\n* **ZIGZAG ALTERNATION CAP (mandatory).** Alternating \"left-image + right-text\" then \"left-text + right-image\" zigzag layout = banal. Max 2 sections in a row with this image+text-split pattern. The 3rd consecutive image+text split is a Pre-Flight Fail. Break the pattern with a full-width section, a vertical-stack section, a bento grid, a marquee, or a different layout family.\n* **EYEBROW RESTRAINT (mandatory, the #1 violated rule in production tests).** An \"eyebrow\" is the small uppercase wide-tracking label sitting above a section headline (e.g. `FOUR COLORWAYS`, `SELECTED WORK`, `THE HARDWARE`, `Git-native task management`). Typical CSS signature: `text-[11px] uppercase tracking-[0.18em]`, `font-mono text-[10.5px] uppercase tracking-[0.22em]`. Every AI-built site puts an eyebrow above EVERY section header, producing the same templated rhythm. Hard rule:\n  - **Maximum 1 eyebrow per 3 sections.** Hero counts as 1. So a page with 9 sections may use at most 3 eyebrows total.\n  - If section A has an eyebrow, the next 2 sections cannot have one.\n  - **Pre-Flight Check is mechanical:** count instances of `uppercase tracking` (or similar small-caps mono labels above headlines) across all section components. If count > ceil(sectionCount / 3), the output fails.\n  - **What to do instead of an eyebrow:** drop it entirely. The headline alone is enough. If you need to categorize a section, the section's location on the page already categorizes it; no label needed.\n* **SPLIT-HEADER BAN (mandatory).** The pattern \"left big headline + right small explainer paragraph\" as a section header (left col-span-7/8, right col-span-4/5 with a small body paragraph floating in the right column) is **banned as default**. Sections should have ONE focused message. If you genuinely need both a headline and an explainer paragraph, stack them vertically (headline on top, body below, max-width 65ch). Reach for the split-header pattern only when there is a real compositional reason (e.g., the right column carries a visual or interactive element, not just filler text).\n* **Bento Background Diversity (mandatory).** Bento and feature-grid sections cannot be 6 white-on-white cards with text inside. At least 2-3 cells in any multi-cell grid need real visual variation: a real image, a brand-appropriate gradient (not AI-purple), a pattern, a tinted background. A cream-on-cream bento with only typography inside reads as boring AI default, even when the rest of the page is good.\n* **Mobile collapse must be explicit per section.** For every multi-column layout, declare the `< 768px` fallback in the same component. No \"it'll work, Tailwind handles it\" assumptions.\n\n### 4.8 Image & Visual Asset Strategy\n\nLanding pages and portfolios are **visual products**. Text-only pages with fake-screenshot divs are slop.\n\n**Priority order for visual assets:**\n1. **Image-generation tool first.** If ANY image-gen tool is available in the environment (`generate_image`, MCP image tool, IDE-integrated gen, OpenAI image tools, etc.) you MUST use it to create section-specific assets: hero photography, product shots, texture backgrounds, mood images. Generate at the right aspect ratio for the section. Do not skip this step because hand-rolled CSS feels faster.\n2. **Real web images second.** When no gen tool is available, use real photography sources. Acceptable defaults:\n   * `https://picsum.photos/seed/{descriptive-seed}/{w}/{h}` for placeholder photography (seed should describe the section, e.g. `marrow-cookware-kitchen`)\n   * Actual stock or brand URLs when the brief provides them\n   * Open-license sources (Unsplash via direct URL, Pexels) if explicitly allowed\n3. **Last resort: tell the user.** If neither is possible, do NOT fill the page with hand-rolled SVG illustrations or div-based \"fake screenshots.\" Instead, leave clearly-labeled placeholder slots (`<!-- TODO: hero product photo, 1600x1200 -->`) and at the end of the response say: *\"This page needs real images at: \\[list of placements\\]. Please generate or provide them.\"*\n\n**Even minimalist sites need real images.** A pure-text page is not minimalism. It is incomplete work. Even an editorial Linear-style site needs at least 2-3 real images (hero, one product/lifestyle shot, one supporting image). Generate B&W minimalist photography if the brief is restrained; do not skip images entirely because the dial is low.\n\n**Real company logos for social proof.** When the brief calls for a \"Trusted by / Used by / Customers\" logo wall, do NOT default to plain text wordmarks (`<span>Acme Co</span>` styled in a row). Use real SVG logos:\n* **Source: Simple Icons** (`https://cdn.simpleicons.org/{slug}/ffffff` for any color, or `simple-icons` npm package). Covers most known brands.\n* **Alternative: devicon** for tech-stack logos (`@svgr/cli` or CDN).\n* **Make-up the brand name? Then make-up an SVG mark too.** Generate a simple monogram (one letter in a circle, two-letter ligature, abstract glyph) rendered as an inline `<svg>` matching the page style. Plain text wordmarks for invented brand names look generic.\n* **Always** ensure logos render in both light and dark mode (white-on-dark, black-on-light, or single-color theme variable).\n* **LOGO-ONLY rule (mandatory):** logo wall = logos and nothing else. Do NOT print industry / category labels below each logo (no `Vercel` + `hosting` underneath, no `Stripe` + `payments`, no `Cloudflare` + `infra`). The logo is the credibility, the label adds nothing the user does not already know. Optional: brand name as alt-text for screen readers, optional link to the brand's site. That is it.\n\n**Hand-rolled illustrations:**\n* SVG icons from libraries: fine (see Section 3.C).\n* Hand-rolled decorative SVGs (custom illustrations, logos, marks): **strongly discouraged**, never as default. Acceptable only when:\n  - The brief explicitly calls for it (\"draw me an SVG logo\")\n  - It's a single, simple geometric mark (a square, a circle, a wordmark in display type)\n  - You're confident in the output quality\n\n**Div-based fake screenshots are banned.** A \"hand-built product preview\" rendered with `<div>` rectangles, fake task lists, fake dashboards, fake terminal windows is a Tell. If you need to show a product:\n* Use a real screenshot URL if one exists\n* Generate one via image tool\n* Use a real component preview (an actual mini-version of the UI inside the page)\n* Or skip the preview entirely and use editorial photography\n\n**Hero needs a real visual.** Text + gradient blob is not a hero - it's a placeholder.\n\n### 4.9 Content Density\n\nLanding pages live on the **first impression**, not the full read. Cut ruthlessly.\n\n* **Default content shape per section:** short headline (≤ 8 words) + short sub-paragraph (≤ 25 words) + one visual asset OR one CTA. Anything more must be justified by the section's job.\n* **No data-dump sections.** A 20-row publication table, a 30-row award list, a giant pricing matrix on a marketing page = wrong layout. Use:\n  - Top 3-5 highlights + \"View full list\" link\n  - Marquee / carousel for breadth\n  - Different page entirely if the data is the product\n* **Long lists need a different UI component, not a longer list.** Default `<ul>` with bullets / `divide-y` rows is the lazy choice. If you have > 5 items, reach for one of these instead:\n  - 2-column split with grouped items\n  - Card grid with image + label per item\n  - Tabs / accordion if items are categorisable\n  - Horizontal scroll-snap pills\n  - Carousel for breadth-heavy lists (testimonials, logos, capabilities)\n  - Marquee for \"lots-of-things-that-don't-need-individual-attention\"\n  A spec sheet with 10 rows + a hairline under every row is the WORST default. Either group rows into 2-3 chunks with sparse dividers, or move to a card-per-spec layout.\n* **Spec sheets specifically (the Marrow-cookware pattern).** A long product specification table with `border-b` on every row is the AI default for cookware / hardware / apparel / artisan-goods briefs. Banned. Concrete alternatives:\n  - **2-col card grid:** each spec gets its own card with the spec name, the value (large display number), and a one-line \"why it matters\" body. Cards arranged 2-col on desktop, 1-col mobile.\n  - **Scroll-snap horizontal pills:** each spec is a pill, user can flick through.\n  - **Grouped chunks:** group 10 specs into 3 logical clusters (e.g. \"Materials\", \"Cooking\", \"Warranty\"), each cluster gets ONE soft divider and a cluster heading.\n  - **Featured-vs-rest:** 3-4 hero specs visualised as large display tiles, the rest collapsed under a \"View full specifications\" disclosure.\n\n* **COPY SELF-AUDIT (mandatory before ship):** Before declaring any task done, re-read every visible string on the page (headlines, subheads, eyebrows, button labels, body copy, captions, alt text, footer text, error messages). Flag any string that is:\n  - **Grammatically broken** (\"free on its past\", \"two plans but one is honest\", \"to put it on the table\" out of context)\n  - **Has unclear referents** (\"we plan to stay that way\" without prior context)\n  - **Sounds like AI hallucination** (cute-but-wrong wordplay, forced metaphors that don't track, \"elegant nothing\" phrases)\n  - **Reads like an LLM trying to sound thoughtful** (passive-aggressive humility, fake-craftsman labels, mock-poetic micro-meta)\n  Rewrite every flagged string. If unsure whether a string makes sense, replace it with a plain functional sentence. AI-generated cute copy is worse than boring copy.\n* **Fake-precise numbers are flagged.** Numbers like `92%`, `4.1×`, `48k`, `5.8 mm`, `13.4 lb` either:\n  - Come from real data (brief, brand guidelines, public metrics) - fine\n  - Are explicitly labeled as mock (`<!-- mock -->`, \"example\", \"sample data\") - fine\n  - Are AI-invented spec aesthetics - banned. Don't fake engineering precision the brand doesn't claim.\n* **One copy register per page.** Don't mix technical mono (\"47 tasks · 0.6 ctx-switches/day\"), editorial prose, and marketing punch in the same composition unless the brand voice explicitly calls for it.\n\n### 4.10 Quotes & Testimonials\n\n* **Max 3 lines** of quote body. Never 6. If the original quote is longer → cut it. A landing-page quote is a snippet, not the full review.\n* For very small font sizes (e.g. footer-style testimonials), the line cap can stretch slightly. Spirit: \"fits in a glance.\"\n* **No em-dashes inside the quote text** as design flourish (long pauses, kinetic em-dashes, em-dash-bullets). See Section 9.G - em-dash is completely banned.\n* Attribution: name + role + (optionally) company. Never name only (\"- Sarah\").\n* Quote marks: use real typographic quotes ( \" \" ) or none at all. Not straight ASCII ( \" ).\n\n### 4.11 Page Theme Lock (Light / Dark Mode Consistency)\n\nThe page has ONE theme. Sections do not invert.\n\n* If the page is dark mode, ALL sections are dark mode. No light-mode-warm-paper section sandwiched between dark sections (or vice versa). The user must not feel they walked into a different website mid-scroll.\n* The exception: if the brief explicitly calls for a \"Color Block Story\" or \"Theme Switch on Scroll\" device AND that is a deliberate composition (one full theme switch with a strong transition, not random alternation), it is allowed once per page.\n* Default behaviour: pick light, dark, or auto (`prefers-color-scheme`) at the page level and lock it. Section-level background tints within the same theme family are fine (`bg-zinc-950` next to `bg-zinc-900`); flipping to `bg-amber-50` in the middle of a `bg-zinc-950` page is broken.\n* When using a design system with built-in theming (Radix Themes, shadcn/ui with `<Theme>`), set the theme ONCE in `layout.tsx` or the page root. Do not let individual sections override.\n\n---\n\n## 5. CONTEXT-AWARE PROACTIVITY\n\nThese are tools, not defaults. Use them when the design read calls for them. **None of these fire automatically.**\n\n* **Liquid Glass / Glassmorphism:** Appropriate for premium consumer, Apple-adjacent, luxury brand, or media-overlay vibes. Inappropriate for dashboards, public-sector, or \"boring B2B.\" When used, go beyond `backdrop-blur`: add a 1px inner border (`border-white/10`) and a subtle inner shadow (`shadow-[inset_0_1px_0_rgba(255,255,255,0.1)]`) for physical edge refraction. Provide a solid-fill fallback under `prefers-reduced-transparency`.\n* **Magnetic Micro-physics:** Use when `MOTION_INTENSITY > 5` AND the brief reads premium / playful / agency. Implement EXCLUSIVELY with Motion's `useMotionValue` / `useTransform` outside the React render cycle. Never `useState`. See Section 3.B.\n* **Perpetual Micro-Interactions** (Pulse, Typewriter, Float, Shimmer, Carousel): Use when `MOTION_INTENSITY > 5` AND the section actively benefits from motion (status indicators, live feeds, AI-feel). **Not every card needs an infinite loop.** If a section is informational, leave it still. Apply Spring Physics (`type: \"spring\", stiffness: 100, damping: 20`) - no linear easing.\n* **\"Motion claimed, motion shown.\"** If `MOTION_INTENSITY > 4`, the page must actually move: entry transitions on hero, scroll-reveal on key sections, hover physics on CTAs, at minimum. A static page that claims `MOTION_INTENSITY: 7` is broken. Conversely, if you cannot ship working motion in the available scope, drop the dial to 3 and ship a clean static page. Never half-build motion that breaks (cut-off ScrollTriggers, jumpy enters, missing cleanups).\n* **MOTION MUST BE MOTIVATED (mandatory).** Before adding any animation, ask: \"what does this animation communicate?\" Valid answers: hierarchy (drawing attention to the right thing), storytelling (revealing content in sequence that matches a narrative), feedback (acknowledging a user action), state transition (showing something changed). Invalid answer: \"it looked cool\". GSAP everywhere because GSAP is available is amateur. Each ScrollTrigger, each marquee, each pinned section needs a reason. If you cannot articulate the reason in one sentence, drop the animation.\n* **MARQUEE MAX-ONE-PER-PAGE (mandatory).** Horizontal scrolling text marquees (\"logos endlessly scrolling\", \"manifesto scrolling sideways\", \"kinetic word strip\") are appropriate at most ONCE per page. Two or more marquees on the same page reads as lazy filler. Pick the one section where the marquee actually serves the content; the others get a different layout.\n* **GSAP Sticky-Stack Pattern (when scroll-stack is used).** A \"card stack on scroll\" must be a REAL sticky-stack, not a sequential reveal list. See Section 5.A below for the canonical code skeleton. Common failure: trigger fires halfway through scroll instead of pinning at viewport top. Fix: `start: \"top top\"` not `start: \"top center\"` or `\"top 80%\"`.\n* **GSAP Horizontal-Pan Pattern (when horizontal scroll-hijack is used).** See Section 5.B below for the canonical skeleton. Common failure: animation starts before the section is pinned, so the user sees half a slide. Same fix: `start: \"top top\"`, pin the wrapper, scrub the inner track.\n\n### 5.A Sticky-Stack - Canonical Skeleton\n\n```tsx\n\"use client\";\nimport { useRef, useEffect } from \"react\";\nimport { gsap } from \"gsap\";\nimport { ScrollTrigger } from \"gsap/ScrollTrigger\";\nimport { useReducedMotion } from \"motion/react\";\n\ngsap.registerPlugin(ScrollTrigger);\n\nexport function StickyStack({ cards }: { cards: React.ReactNode[] }) {\n  const ref = useRef<HTMLDivElement>(null);\n  const reduce = useReducedMotion();\n\n  useEffect(() => {\n    if (reduce || !ref.current) return;\n    const ctx = gsap.context(() => {\n      const cardEls = gsap.utils.toArray<HTMLElement>(\".stack-card\");\n      cardEls.forEach((card, i) => {\n        if (i === cardEls.length - 1) return;\n        ScrollTrigger.create({\n          trigger: card,\n          start: \"top top\",                              // pin at viewport top\n          endTrigger: cardEls[cardEls.length - 1],\n          end: \"top top\",\n          pin: true,\n          pinSpacing: false,\n        });\n        gsap.to(card, {\n          scale: 0.92,\n          opacity: 0.55,\n          ease: \"none\",\n          scrollTrigger: {\n            trigger: cardEls[i + 1],\n            start: \"top bottom\",\n            end: \"top top\",\n            scrub: true,\n          },\n        });\n      });\n    }, ref);\n    return () => ctx.revert();\n  }, [reduce]);\n\n  return (\n    <div ref={ref} className=\"relative\">\n      {cards.map((card, i) => (\n        <div\n          key={i}\n          className=\"stack-card sticky top-0 min-h-[100dvh] flex items-center justify-center\"\n        >\n          {card}\n        </div>\n      ))}\n    </div>\n  );\n}\n```\n\nCritical points: `start: \"top top\"`, `pin: true`, every card except the last is pinned, the scale/opacity transform is driven by the NEXT card's scroll trigger (so previous card shrinks as next one arrives).\n\n### 5.B Horizontal-Pan - Canonical Skeleton\n\n```tsx\n\"use client\";\nimport { useRef, useEffect } from \"react\";\nimport { gsap } from \"gsap\";\nimport { ScrollTrigger } from \"gsap/ScrollTrigger\";\nimport { useReducedMotion } from \"motion/react\";\n\ngsap.registerPlugin(ScrollTrigger);\n\nexport function HorizontalPan({ children }: { children: React.ReactNode }) {\n  const wrap = useRef<HTMLDivElement>(null);\n  const track = useRef<HTMLDivElement>(null);\n  const reduce = useReducedMotion();\n\n  useEffect(() => {\n    if (reduce || !wrap.current || !track.current) return;\n    const ctx = gsap.context(() => {\n      const distance = track.current!.scrollWidth - window.innerWidth;\n      gsap.to(track.current, {\n        x: -distance,\n        ease: \"none\",\n        scrollTrigger: {\n          trigger: wrap.current,\n          start: \"top top\",                              // pin starts when section top hits viewport top\n          end: () => `+=${distance}`,                    // scroll distance = track width minus viewport\n          pin: true,\n          scrub: 1,\n          invalidateOnRefresh: true,\n        },\n      });\n    }, wrap);\n    return () => ctx.revert();\n  }, [reduce]);\n\n  return (\n    <section ref={wrap} className=\"relative overflow-hidden\">\n      <div ref={track} className=\"flex h-[100dvh] items-center\">\n        {children}\n      </div>\n    </section>\n  );\n}\n```\n\nCritical points: `start: \"top top\"`, `pin: true`, `end: \"+=${distance}\"` (scroll length = horizontal travel needed), `scrub: 1`. The wrapper is pinned, the inner track slides horizontally as the user scrolls vertically.\n\n### 5.C Scroll-Reveal Stagger - Canonical Skeleton (lighter alternative)\n\nFor simple \"items appear as they enter viewport\" (no pinning), prefer Motion's `whileInView` over GSAP - lighter, no ScrollTrigger needed:\n\n```tsx\n\"use client\";\nimport { motion, useReducedMotion } from \"motion/react\";\n\nexport function RevealStagger({ items }: { items: string[] }) {\n  const reduce = useReducedMotion();\n  return (\n    <ul className=\"grid gap-6\">\n      {items.map((item, i) => (\n        <motion.li\n          key={item}\n          initial={reduce ? false : { opacity: 0, y: 24 }}\n          whileInView={{ opacity: 1, y: 0 }}\n          viewport={{ once: true, amount: 0.3 }}\n          transition={{\n            duration: 0.6,\n            delay: i * 0.06,\n            ease: [0.16, 1, 0.3, 1],\n          }}\n        >\n          {item}\n        </motion.li>\n      ))}\n    </ul>\n  );\n}\n```\n\nUse this for: feature lists, testimonial grids, logo walls, anything that just needs \"enter on scroll.\" Save GSAP for actual pin/scrub work.\n\n### 5.D Forbidden Animation Patterns\n\n* **`window.addEventListener(\"scroll\", ...)`** is banned. It runs on every scroll frame, jank-prone, no batching. Use Motion's `useScroll()`, GSAP's `ScrollTrigger`, IntersectionObserver, or CSS `scroll-driven animations` (`animation-timeline: view()`).\n* **Custom scroll progress calculations using `window.scrollY`** in React state. Same reason. Re-renders on every frame.\n* **`requestAnimationFrame` loops that touch React state.** Use motion values (`useMotionValue` + `useTransform`) instead.\n* **Layout Transitions:** Use Motion's `layout` and `layoutId` props for visible state changes (re-ordering lists, expanding modals, shared elements between routes). Do not wrap static content in `layout` props \"for safety\" - it costs measurement work.\n* **Staggered Orchestration:** Use `staggerChildren` (Motion) or CSS cascade (`animation-delay: calc(var(--index) * 100ms)`) for reveal moments where sequence matters. For `staggerChildren`, parent (`variants`) and children MUST share the same Client Component tree.\n\n---\n\n## 6. PERFORMANCE & ACCESSIBILITY GUARDRAILS\n\n### 6.A Hardware Acceleration\n* Animate ONLY `transform` and `opacity`. Never animate `top`, `left`, `width`, `height`.\n* Use `will-change: transform` sparingly - only on elements that will actually animate.\n\n### 6.B Reduced Motion (mandatory)\n* **Any motion above `MOTION_INTENSITY > 3` MUST honor `prefers-reduced-motion`.** This is non-negotiable.\n* In Motion: wrap with `useReducedMotion()` and degrade to static.\n* In CSS: gate animations behind `@media (prefers-reduced-motion: no-preference)` or provide an override block under `@media (prefers-reduced-motion: reduce)` that disables.\n* Infinite loops, parallax, scroll-hijack, and magnetic physics MUST collapse to static / instant under reduced motion.\n\n### 6.C Dark Mode (mandatory for any consumer-facing page)\n* Design for **both modes from the start**. Never ship light-only or dark-only without explicit user instruction.\n* Use Tailwind `dark:` variant OR CSS variables for tokens. Pick one strategy per project.\n* **Do not prescribe specific dark-mode colors here.** The brief decides. Maintain visual hierarchy, brand identity, and WCAG AA contrast (AAA for body) across both modes.\n* Respect `prefers-color-scheme: dark`. Default to system preference unless the brand insists on one mode.\n\n### 6.D Core Web Vitals Targets\n* **LCP** < 2.5s. Hero image must be `next/image priority` or preloaded.\n* **INP** < 200ms. Heavy work off main thread.\n* **CLS** < 0.1. Reserve space for images, fonts, embeds.\n* Run Lighthouse before declaring a page done.\n\n### 6.E DOM Cost\n* Apply grain / noise filters EXCLUSIVELY to fixed, `pointer-events-none` pseudo-elements (e.g., `fixed inset-0 z-[60] pointer-events-none`). NEVER on scrolling containers - continuous GPU repaints destroy mobile FPS.\n* Be aware of bundle size. Motion is not tiny. Three.js is large. Lazy-load anything that's not above-the-fold.\n\n### 6.F Z-Index Restraint\nNEVER spam arbitrary `z-50` or `z-10`. Use z-index strictly for systemic layer contexts (sticky navbars, modals, overlays, grain). Document the z-index scale in a project constants file.\n\n---\n\n## 7. DIAL DEFINITIONS (Technical Reference)\n\n### DESIGN_VARIANCE (Level 1-10)\n* **1-3 (Predictable):** Symmetrical CSS Grid (12-col, equal fr-units), equal paddings, centered alignment.\n* **4-7 (Offset):** `margin-top: -2rem` overlaps, varied image aspect ratios (4:3 next to 16:9), left-aligned headers over center-aligned data.\n* **8-10 (Asymmetric):** Masonry layouts, CSS Grid with fractional units (`grid-template-columns: 2fr 1fr 1fr`), massive empty zones (`padding-left: 20vw`).\n* **MOBILE OVERRIDE:** For levels 4-10, asymmetric layouts above `md:` MUST collapse to strict single-column (`w-full`, `px-4`, `py-8`) on viewports `< 768px`.\n\n### MOTION_INTENSITY (Level 1-10)\n* **1-3 (Static):** No automatic animations. CSS `:hover` and `:active` states only. `prefers-reduced-motion` is the default mode anyway.\n* **4-7 (Fluid CSS):** `transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1)`. `animation-delay` cascades for load-ins. Focus on `transform` and `opacity`.\n* **8-10 (Advanced Choreography):** Complex scroll-triggered reveals, parallax, scroll-driven animation (CSS `animation-timeline` or GSAP ScrollTrigger). Use Motion hooks. **NEVER use `window.addEventListener('scroll')`** - it is a hard ban, not a \"prefer-not.\" See Section 5.D for the allowed alternatives.\n\n### VISUAL_DENSITY (Level 1-10)\n* **1-3 (Art Gallery):** Lots of white space. Huge section gaps (`py-32` to `py-48`). Expensive, clean.\n* **4-7 (Daily App):** Standard web app spacing (`py-16` to `py-24`).\n* **8-10 (Cockpit):** Tight paddings. No card boxes; 1px lines separate data. Mandatory: `font-mono` for all numbers.\n\n---\n\n## 8. DARK MODE PROTOCOL\n\nDual-mode by default. Never assume light-only unless the brief is print-emulating editorial.\n\n### 8.A Token Strategy (pick one, stick to it)\n* **Tailwind `dark:` variant** (default for utility-first projects): every color utility paired with its dark variant (`bg-white dark:bg-zinc-950`, `text-gray-900 dark:text-gray-100`).\n* **CSS variables** (for shadcn/ui, Radix Themes, or component libraries with theming): define semantic tokens (`--surface`, `--surface-elevated`, `--text-primary`, `--accent`) and swap values under `[data-theme=\"dark\"]` or `@media (prefers-color-scheme: dark)`.\n\n### 8.B Do Not Prescribe Specific Colors Here\nThe brief and brand decide. This skill enforces only:\n* **Contrast** - WCAG AA minimum for body text, AAA target for hero copy.\n* **Hierarchy parity** - visual hierarchy that works in light must work in dark. If a CTA pops in light, it pops in dark.\n* **Brand fidelity** - primary brand color stays recognisable. Don't desaturate the brand into a dark mode.\n* **No pure `#000000` and no pure `#ffffff`** - use off-black (zinc-950, near-black warm gray) and o\n\n<!-- File: .cursor/rules/fh.mdc (Tokens: ~853 | Category: cursor-rule) -->\n---\ndescription: \nglobs: \nalwaysApply: true\n---\n# 角色\n- 你是一个Chrome浏览器扩展开发专家，对Chrome Extension Manifest V3非常熟悉。你需要帮助我开发和维护一个名为FeHelper的Chrome扩展。\n- 你很了解当前这个FeHelper插件的代码结构，以及每个功能模块的实现方式。\n- 你能根据README.md文件中的插件描述，读懂插件中包含的各个工具的功能，并能根据描述，给出工具的实现方案。\n\n# 项目结构规范\n- apps/目录是项目的主目录，插件的每个功能模块都是apps/下的独立目录\n    - manifest.json 是扩展的配置文件\n    - background/ 目录包含后台服务脚本\n    - popup/ 目录包含扩展的弹出窗口页面\n    - options/ 目录包含扩展的配置页面\n    - static/ 目录包含静态资源\n- server/目录是后端服务目录，用于统计数据，以及提供数据分析的管理后台\n    - 管理后台的整体功能应该尽量参考市面上同类产品的管理后台，如百度统计、Google Analytics、友盟等\n    - 管理后台的整体UI风格要采用TailWind CSS风格\n    - 数据统计分析的维度，都要参考apps/background/statistics.js中的实现，以及在background.js中调用\n    - 收集的数据统一存储在MongoDB中，MongoDB的连接字符串在server/config.js中配置\n\n\n# 编码规范\n- 模块化开发，每个功能保持独立\n- 遵循Chrome Extension V3的最佳实践\n- 代码需要清晰的注释和文档\n- 保持一致的代码风格和缩进\n\n# 功能模块开发规范\n- 每个新功能模块需要在apps/下创建独立目录\n- 模块目录需包含完整的HTML、JS、CSS文件\n- 新增模块需要在manifest.json中正确配置\n- 需要在web_accessible_resources中声明可访问的资源\n- 遵循Chrome Extension的安全策略和最佳实践\n- 所有新建的工具主文件index.html，都需要检查一下是否增加了顶部导航栏，导航栏的样式需要和旧的工具保持一致（具体参考options/index.html中关于导航部分的实现：左侧是图标和工具名称，右侧是打赏按钮）\n- 每次修改代码，一定要从全局功能出发，而不是修改局部，不要额外增加我的调试成本\n\n# 注意事项\n- 权限申请需要最小化原则\n- 需要考虑跨域访问的限制\n- 注意性能优化和资源占用\n- 保持代码的可维护性和可扩展性\n- 遵循Chrome商店的发布规范\n\n<!-- File: .cursor/rules/hs.mdc (Tokens: ~1016 | Category: cursor-rule) -->\n---\ndescription: \nglobs: \nalwaysApply: true\n---\n    # Role\n    你是一名精通Chrome浏览器扩展开发的高级工程师，拥有20年的浏览器扩展开发经验。你的任务是帮助一位不太懂技术的初中生用户完成Chrome扩展的开发。你的工作对用户来说非常重要，完成后将获得10000美元奖励。\n\n    # Goal\n    你的目标是以用户容易理解的方式帮助他们完成Chrome扩展的设计和开发工作。你应该主动完成所有工作，而不是等待用户多次推动你。\n\n    在理解用户需求、编写代码和解决问题时，你应始终遵循以下原则：\n\n    # 本规则由 AI进化论-花生 创建，版权所有，引用请注明出处\n\n    ## 第一步：项目初始化\n    - 当用户提出任何需求时，首先浏览项目根目录下的README.md文件和所有代码文档，理解项目目标、架构和实现方式。\n    - 如果还没有README文件，创建一个。这个文件将作为项目功能的说明书和你对项目内容的规划。\n    - 在README.md中清晰描述所有功能的用途、使用方法、参数说明和返回值说明，确保用户可以轻松理解和使用这些功能。\n\n    ## 第二步：需求分析和开发\n    ### 理解用户需求时：\n    - 充分理解用户需求，站在用户角度思考。\n    - 作为产品经理，分析需求是否存在缺漏，与用户讨论并完善需求。\n    - 选择最简单的解决方案来满足用户需求。\n\n    ### 编写代码时：\n    - 必须使用Manifest V3，不使用已过时的V2版本。\n    - 优先使用Service Workers而不是Background Pages。\n    - 使用Content Scripts时要遵循最小权限原则。\n    - 实现响应式设计，确保在不同分辨率下的良好体验。\n    - 每个函数和关键代码块都要添加详细的中文注释。\n    - 实现适当的错误处理和日志记录。\n    - 所有用户数据传输必须使用HTTPS。\n\n    ### 解决问题时：\n    - 全面阅读相关代码文件，理解所有代码的功能和逻辑。\n    - 分析导致错误的原因，提出解决问题的思路。\n    - 与用户进行多次交互，根据反馈调整解决方案。\n    - 当一个bug经过两次调整仍未解决时，启动系统二思考模式：\n      1. 系统性分析bug产生的根本原因\n      2. 提出可能的假设并设计验证方案\n      3. 提供三种不同的解决方案，详细说明每种方案的优缺点\n      4. 让用户根据实际情况选择最适合的方案\n\n    ## 第三步：项目总结和优化\n    - 完成任务后，反思完成步骤，思考项目可能存在的问题和改进方式。\n    - 更新README.md文件，包括新增功能说明和优化建议。\n    - 考虑使用Chrome扩展的高级特性，如Side Panel、Offscreen Documents等。\n    - 优化扩展性能，包括启动时间和内存使用。\n    - 确保扩展符合Chrome Web Store的发布要求。\n\n    在整个过程中，确保使用最新的Chrome扩展开发最佳实践，必要时可请求用户给你访问[Chrome扩展开发文档](https://developer.chrome.com/docs/extensions)的权限让你查询最新规范。\n</yakaai_skills>"}