diff --git a/.agents/skills/impeccable/SKILL.md b/.agents/skills/impeccable/SKILL.md index 8af38df3d..9b7ca8f70 100644 --- a/.agents/skills/impeccable/SKILL.md +++ b/.agents/skills/impeccable/SKILL.md @@ -7,85 +7,87 @@ Designs and iterates production-grade frontend interfaces. Real working code, co ## Setup -Before any design work or file edits: +You MUST do these steps before proceeding: -1. Load context (PRODUCT.md / DESIGN.md) via the loader script. -2. Identify the register and load the matching register reference (brand.md or product.md). -3. **If the user invoked a sub-command (e.g. `craft`, `shape`, `audit`), load its reference file too.** This is non-negotiable: `craft` without `craft.md` loaded means you'll skip the shape-and-confirm step the user expects. +1. Run `node .agents/skills/impeccable/scripts/context.mjs` once per session. If you've already seen its output in this conversation, do not re-run it. The script either prints the project's PRODUCT.md (and DESIGN.md when present) as a markdown block, or tells you it's missing. Follow whatever it prints. **If it reports `NO_PRODUCT_MD`, stop and follow `reference/teach.md` before doing anything else.** +2. Familiarize yourself with any existing design system, conventions, and components in the code. Don't reinvent the wheel; use what's there when it works, branch out when the UX wins. +3. Read the matching register reference. **This is non-optional; skipping it produces generic output.** If the project is marketing, a landing page, a campaign, long-form content, or a portfolio (design IS the product), read `reference/brand.md`. If it is app UI, admin, a dashboard, or a tool (design SERVES the product), read `reference/product.md`. Pick by first match: (1) task cue ("landing page" vs "dashboard"); (2) surface in focus (the page, file, or route being worked on); (3) `register` field in PRODUCT.md. +4. If the user invoked a sub-command (`craft`, `shape`, `audit`, ...), load its reference too. -Skipping these produces generic output that ignores the project. +## Design guidance -### 1. Context gathering +Produce ready-to-ship, production-grade code, not prototypes or starting points. Take no shortcuts unless the user asks for them (when in doubt, ask). Don't stop until arriving at a complete implementation (beautiful, responsive, fast, precise, bug-free, on brand). You take attention to detail seriously: every page, section or component crafted is battle tested using the tools available to you (browser screenshotting, computer use, etc). GPT is capable of extraordinary work. Don't hold back. -Two files, case-insensitive. The loader looks at the project root by default and falls back to `.agents/context/` and `docs/` if the root is clean. Override with `IMPECCABLE_CONTEXT_DIR=path/to/dir` (absolute or relative to cwd). +### General rules -- **PRODUCT.md**: required. Users, brand, tone, anti-references, strategic principles. -- **DESIGN.md**: optional, strongly recommended. Colors, typography, elevation, components. +#### Color -Load both in one call: +- **Verify contrast.** Body text must hit ≥4.5:1 against its background; large text (≥18px or bold ≥14px) needs ≥3:1. Placeholder text needs the same 4.5:1, not the muted-gray default. The most common failure: muted gray body text on a tinted near-white. If the contrast is even close, bump the body color toward the ink end of the ramp; light gray "for elegance" is the single biggest reason AI designs feel hard to read. +- Gray text on a colored background looks washed out. Use a darker shade of the background's own hue, or a transparency of the text color. -```bash -node .agents/skills/impeccable/scripts/load-context.mjs -``` +#### Typography -Consume the full JSON output. Never pipe through `head`, `tail`, `grep`, or `jq`. The output's `contextDir` field tells you where the files were resolved from. +- Cap body line length at 65–75ch. +- Hierarchy through scale + weight contrast (≥1.25 ratio between steps). Avoid flat scales. +- Cap font-family count at 3 (display + body + optional mono). More than 3 reads as indecision, not richness. One well-tuned family with weight contrast usually beats three competing typefaces. +- Don't pair fonts that are similar but not identical (two geometric sans-serifs, two humanist sans-serifs). Pair on a contrast axis (serif + sans, geometric + humanist) or use one family in multiple weights. +- No all-caps body copy. Reserve uppercase for short labels (≤4 words), section eyebrows (used sparingly per the Absolute bans), and badges. Sentences in ALL CAPS are unreadable at body sizes. +- Hero / display heading ceiling: clamp() max ≤ 6rem (~96px). Above that the page is shouting, not designing. +- Display heading letter-spacing floor: ≥ -0.04em. Anything tighter and letters touch; cramped, not "designed". +- Use `text-wrap: balance` on h1–h3 for even line lengths; `text-wrap: pretty` on long prose to reduce orphans. +- Use `font-variant-numeric: tabular-nums` on data tables, totals, and any column of aligned numbers. -If the output is already in this session's conversation history, don't re-run. Exceptions requiring a fresh load: you just ran `$impeccable teach` or `$impeccable document` (they rewrite the files), or the user manually edited one. +Two hard typographic ceilings you currently miss: +- Hero clamp() max ≤ 6rem. 8–11rem (128–176px) reads as comically loud, not bold. +- Display letter-spacing ≥ -0.04em. Your default of -0.05 to -0.085em on display H1s makes the letters touch and reads as cramped. -0.02 to -0.03em is plenty for tight grotesque display; -0.04em is the floor. -`$impeccable live` already warms context via `live.mjs`. If you've run `live.mjs`, don't also run `load-context.mjs` this session. +#### Layout -If PRODUCT.md is missing, empty, or placeholder (`[TODO]` markers, <200 chars): run `$impeccable teach`, then resume the user's original task with the fresh context. If the original task was `$impeccable craft`, resume into `$impeccable shape` before any implementation work. +- Vary spacing for rhythm. +- Don't default to centering everything. Left-aligned with asymmetric layout reads as designed; centered icon-title-subtitle stacks read as template. +- Cards are the lazy answer. Use them only when they're truly the best affordance. Nested cards are always wrong. +- Don't wrap everything in a container. Most things don't need one. +- Flexbox for 1D, Grid for 2D. Don't default to Grid when `flex-wrap` would be simpler. +- For responsive grids without breakpoints: `repeat(auto-fit, minmax(280px, 1fr))`. +- Build a semantic z-index scale (dropdown → sticky → modal-backdrop → modal → toast → tooltip). Never arbitrary values like 999 or 9999. -If DESIGN.md is missing: nudge once per session (*"Run `$impeccable document` for more on-brand output"*), then proceed. +#### Motion +- Motion should be intentional, and not be an afterthought. consider it as part of the build. +- Don't animate CSS layout properties unless truly needed. +- Ease out with exponential curves (ease-out-quart / quint / expo). No bounce, no elastic. +- Use libraries for more advanced motion needs (e.g. motion, gsap, anime.js, lenis etc) +- Reduced motion is not optional. Every animation needs a `@media (prefers-reduced-motion: reduce)` alternative: typically a crossfade or instant transition. +- Sibling stagger on a list (cards, list items) is legitimate. Whole-section fade-on-scroll on every scrolled section is not a list; it's the saturated AI motion reflex. +- Premium motion materials are not just transform/opacity. Blur, backdrop-filter, clip-path, mask, and shadow/glow are part of the palette when they materially improve the effect and stay smooth. -### 2. Register +#### Interaction -Every design task is **brand** (marketing, landing, campaign, long-form content, portfolio: design IS the product) or **product** (app UI, admin, dashboard, tool: design SERVES the product). +- Never `outline: none` without a replacement. Use `:focus-visible` to show focus rings only for keyboard users; never strip focus indicators unconditionally. +- Placeholders aren't labels. Always use a visible `