diff --git a/agents/plugin-advisor.md b/agents/plugin-advisor.md index 3939f80..8829a61 100644 --- a/agents/plugin-advisor.md +++ b/agents/plugin-advisor.md @@ -217,10 +217,10 @@ findings before producing recommendations: | Signal | Enable / Use | Disable / Skip | Notes | |---|---|---|---| -| `frontend` | ui-ux-pro-max, frontend-design | — | UI design and polish. frontend-design = Anthropic's anti-AI-slop design skill (external, symlinked) | +| `frontend` | ui-ux-pro-max, frontend-design, design-motion-principles | — | UI design + polish + motion. frontend-design = anti-AI-slop, design-motion-principles = motion/animation (both external, symlinked) | | `mobile` (React Native/Expo/Flutter) | — | gstack (no browser QA), Docker N/A | ui-ux-pro-max optional | | `monorepo` | per-package plugin recommendations | avoid recommending gstack for whole repo if only one package has browser QA | Specify which plugin applies to which package | -| `design-system` | ui-ux-pro-max, frontend-design | — | Design tokens, theme, Storybook | +| `design-system` | ui-ux-pro-max, frontend-design, design-motion-principles | — | Design tokens, theme, Storybook, motion | | `deploy` + `browser-qa` | gstack | — | Full-product workflow | | `multi-session` | gsd v2 CLI | — | Run `gsd` in terminal, not CC plugin | | `fast-libs` | context7 | — | Doc freshness critical | @@ -271,12 +271,12 @@ When the plugin-advisor detects a `simple` or `hotfix` signal, suggest the appro | Project type | Plugins ON | OFF | Passive cost | |---|---|---|---| | Backend API / microservice | superpowers, context7 (if fast libs) | ui-ux-pro-max, gstack | ~800t | -| Frontend SPA / SSR | superpowers, ui-ux-pro-max, frontend-design, context7 | gstack | ~1400t | -| Full-stack SaaS | superpowers, gstack, ui-ux-pro-max, frontend-design, context7 | — | ~4200t | +| Frontend SPA / SSR | superpowers, ui-ux-pro-max, frontend-design, design-motion-principles, context7 | gstack | ~1400t | +| Full-stack SaaS | superpowers, gstack, ui-ux-pro-max, frontend-design, design-motion-principles, context7 | — | ~4200t | | CLI tool / library | superpowers | all toggles | ~800t | | Multi-session large feature | superpowers + gsd v2 CLI (external) | — | ~800t CC | | Quick fix / hotfix | superpowers | all toggles | ~800t | -| Design system / component lib | superpowers, ui-ux-pro-max, frontend-design | gstack, gsd | ~1200t | +| Design system / component lib | superpowers, ui-ux-pro-max, frontend-design, design-motion-principles | gstack, gsd | ~1200t | | Fast-evolving libs (Next.js etc.) | superpowers, context7 | — | ~1000t | | Enterprise multi-agent orchestration | superpowers + gsd v2 (external) | plugin-dev | ~800t CC | @@ -300,6 +300,7 @@ RULE: IF "monorepo" signal detected: RULE: IF "frontend" signal OR .tsx/.jsx count > 0: → ui-ux-pro-max ON if "design-system" signal (~400t) → frontend-design ON (external skill, 0t passive — symlink at ~/.claude/skills/frontend-design) + → design-motion-principles ON if anim-lib-installed or description mentions animation/motion (external, 0t passive) RULE: IF "deploy" AND "browser-qa" signals: → gstack ON (~2750t) — full-product workflow @@ -340,7 +341,8 @@ RULE: IF `browser-qa` signal (e2e tests, Playwright/Cypress/Puppeteer in deps): RULE: IF `design-system` signal (tokens, theme files, Storybook present): → ui-ux-pro-max ON (~400t) → frontend-design ON (external skill, 0t passive) - → WARN if both OFF with this signal: significant design gap + → design-motion-principles ON (external skill, 0t passive) + → WARN if all three OFF with this signal: significant design gap RULE: IF `complex-arch` signal (multiple services, event bus, distributed system): → gsd v2 CLI recommended for multi-session coordination diff --git a/install-plugins.sh b/install-plugins.sh index a6a244a..27529a8 100644 --- a/install-plugins.sh +++ b/install-plugins.sh @@ -620,6 +620,22 @@ else fi echo "" +# ── Step 8c: Design Motion Principles (kylezantos) ───────── +echo "── Step 8c: Design Motion Principles ─────────────────────" +echo "" +DMP_DIR="$REPO/skills-external/design-motion-principles" +if [ -f "$DMP_DIR/SKILL.md" ]; then + ok "design-motion-principles already present" +else + warn "design-motion-principles: not installed — clone from https://github.com/kylezantos/design-motion-principles" +fi +if [ -L "$HOME/.claude/skills/design-motion-principles" ]; then + ok "design-motion-principles symlink OK" +else + info "Symlinking — will be created by link.sh" +fi +echo "" + # ============================================================ # STEP 8.5 — EXTERNAL SKILLS (npx skills add …) # ============================================================ @@ -763,6 +779,7 @@ echo " 🔄 context7 CLI — ctx7 (npm global, standalone or MCP setup echo " 🔄 graphifyy — codebase knowledge graph (pipx, PreToolUse hook)" echo " 🔄 emil-design-eng — UI polish, animations, component craft (curl → symlink)" echo " 🔄 frontend-design — distinctive frontend interfaces, anti-AI-slop (anthropic-agent-skills)" +echo " 🔄 design-motion-principles — motion/animation design, 3-designer lens (kylezantos)" echo " 🔄 darwin-skill — autonomous skill optimizer (npx skills, ~/.agents/skills/)" echo " 🔄 find-skills — skill discovery helper (npx skills, ~/.agents/skills/)" echo " 🔄 magic MCP — 21st-dev UI generation MCP (toggle: lib/toggle-external.sh enable magic)" @@ -771,6 +788,7 @@ echo " All plugins installed at: user scope (~/.claude/plugins/)" echo " GStack skills symlinked individually into ~/.claude/skills/ (→ submodule)" echo " Emil Design Eng at: ~/.claude/skills/emil-design-eng/ (symlink → skills-external)" echo " Frontend Design at: ~/.claude/skills/frontend-design/ (symlink → skills-external)" +echo " Design Motion Principles at: ~/.claude/skills/design-motion-principles/ (symlink → skills-external)" echo " npx skills at: ~/.agents/skills/ (symlinked into ~/.claude/skills/)" echo "" echo " → Restart Claude Code — plugins load automatically" diff --git a/lib/design-gate.md b/lib/design-gate.md index 4a679f0..1ffd3dc 100644 --- a/lib/design-gate.md +++ b/lib/design-gate.md @@ -27,14 +27,15 @@ Check BOTH the task description AND the filesystem: If **at least one signal** is detected: -1. Check if `ui-ux-pro-max` and `frontend-design` are active: +1. Check if `ui-ux-pro-max`, `frontend-design`, and `design-motion-principles` are active: ```bash source "$HOME/.claude/lib/detect-plugins.sh" detect_uiux_pro_max && echo "ui-ux-pro-max: ACTIVE" || echo "ui-ux-pro-max: INACTIVE" [ -L "$HOME/.claude/skills/frontend-design" ] && echo "frontend-design: ACTIVE" || echo "frontend-design: INACTIVE" + [ -L "$HOME/.claude/skills/design-motion-principles" ] && echo "design-motion-principles: ACTIVE" || echo "design-motion-principles: INACTIVE" ``` -2. If **both ACTIVE** → proceed silently. Design context is fully available. +2. If **all three ACTIVE** → proceed silently. Design context is fully available. 3. If **ui-ux-pro-max INACTIVE** → ask the user: ``` @@ -51,6 +52,12 @@ If **at least one signal** is detected: Install: run install-plugins.sh or symlink skills-external/frontend-design to ~/.claude/skills/frontend-design ``` +5. If **design-motion-principles INACTIVE** and task mentions animation/motion/transition → warn (non-blocking): + ``` + ℹ️ design-motion-principles skill not installed — motion design guidelines unavailable. + Install: run install-plugins.sh or symlink skills-external/design-motion-principles to ~/.claude/skills/design-motion-principles + ``` + ## IMPORTANT - This gate adds ~5 seconds overhead. Worth it for design quality. diff --git a/lib/profiles/design.profile b/lib/profiles/design.profile index de1fb84..2a9a3f6 100644 --- a/lib/profiles/design.profile +++ b/lib/profiles/design.profile @@ -20,6 +20,7 @@ plan-ceo-review # External: design skills emil-design-eng external frontend-design external +design-motion-principles external # Plugin (auto-toggle) ui-ux-pro-max plugin@ui-ux-pro-max-skill diff --git a/lib/profiles/full.profile b/lib/profiles/full.profile index c70b53b..08b7de3 100644 --- a/lib/profiles/full.profile +++ b/lib/profiles/full.profile @@ -75,6 +75,7 @@ guard # === External + plugin + MCP ========================================= emil-design-eng external frontend-design external +design-motion-principles external ui-ux-pro-max plugin@ui-ux-pro-max-skill pr-review-toolkit plugin@claude-code-plugins magic mcp diff --git a/lib/profiles/web-full.profile b/lib/profiles/web-full.profile index 7a8a9fa..7be1836 100644 --- a/lib/profiles/web-full.profile +++ b/lib/profiles/web-full.profile @@ -46,6 +46,7 @@ qa-only # === External + plugin + MCP ========================================= emil-design-eng external frontend-design external +design-motion-principles external ui-ux-pro-max plugin@ui-ux-pro-max-skill magic mcp diff --git a/lib/profiles/web.profile b/lib/profiles/web.profile index 39be2b6..8f3c2cf 100644 --- a/lib/profiles/web.profile +++ b/lib/profiles/web.profile @@ -35,6 +35,7 @@ validate personal # External: design skills emil-design-eng external frontend-design external +design-motion-principles external # Plugin: UI/UX intelligence (auto-toggle) ui-ux-pro-max plugin@ui-ux-pro-max-skill diff --git a/link.sh b/link.sh index 0847bce..51bf084 100644 --- a/link.sh +++ b/link.sh @@ -50,7 +50,7 @@ if [ ! -d "$REPO/skills-external/gstack" ]; then echo "⚠️ GStack submodule not found — run: git submodule update --init" fi -EXTERNAL_SKILLS=(emil-design-eng frontend-design) +EXTERNAL_SKILLS=(emil-design-eng frontend-design design-motion-principles) for _ext_skill in "${EXTERNAL_SKILLS[@]}"; do if [ -d "$REPO/skills-external/$_ext_skill" ]; then if [ -L "$CLAUDE/skills/$_ext_skill" ] && [ "$(readlink "$CLAUDE/skills/$_ext_skill")" = "$REPO/skills-external/$_ext_skill" ]; then diff --git a/skills-external/design-motion-principles/LICENSE.txt b/skills-external/design-motion-principles/LICENSE.txt new file mode 100644 index 0000000..adbcec5 --- /dev/null +++ b/skills-external/design-motion-principles/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Kyle Zantos + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/skills-external/design-motion-principles/SKILL.md b/skills-external/design-motion-principles/SKILL.md new file mode 100644 index 0000000..080d6e5 --- /dev/null +++ b/skills-external/design-motion-principles/SKILL.md @@ -0,0 +1,122 @@ +--- +name: design-motion-principles +description: Motion and interaction design expert based on Emil Kowalski, Jakub Krehel, and Jhey Tompkins' techniques. Two modes — build interactive components with purposeful motion, or audit existing animations to catch AI-slop motion patterns (audit emits a branded HTML report with looping demos). Use when creating, adding, animating, or reviewing UI motion: transitions, hover states, micro-interactions, enter/exit animations, or any motion design work in React, Framer Motion, CSS, or HTML. Provides per-designer perspectives with context-aware weighting. +--- + +# Design Motion Principles + +You are a senior design engineer specializing in motion and interaction design. This skill operates in two modes: + +- **Create** — Build interactive components with purposeful motion → `workflows/create.md` +- **Audit** — Review existing motion design and report findings → `workflows/audit.md` + +**Scope**: Web and app UI motion — HTML/CSS, React, Framer Motion / Motion, iOS/Android transitions, design system animations. The frequency framework still applies to other motion work (game engines, Lottie, Rive, video), but designer-specific techniques may not translate. + +--- + +## STEP 0: Detect Mode (DO THIS FIRST) + +| Signal in the request | Mode | +|-----------------------|------| +| "build", "create", "add animation", "animate this", "implement", "make it feel…" | **Create** | +| "audit", "review", "evaluate", "check", "feedback on", "is this motion good" | **Audit** | +| Ambiguous (e.g. "look at this modal animation") | Ask the user | + +For ambiguous requests, if `AskUserQuestion` is available, present: +- **Create** — Build or improve the component's motion +- **Audit** — Review existing motion and report findings + +Otherwise ask in plain text: "Should I build/improve the motion (Create mode), or review existing motion and report findings (Audit mode)?" + +**Once the mode is known, read the matching workflow file and follow it exactly.** + +--- + +## The Three Designers + +- **Emil Kowalski** (Linear, ex-Vercel) — Restraint, speed, purposeful motion. Best for productivity tools. +- **Jakub Krehel** (jakub.kr) — Subtle production polish, professional refinement. Best for shipped consumer apps. +- **Jhey Tompkins** (@jh3yy) — Playful experimentation, CSS innovation. Best for creative sites, kids apps, portfolios. + +> These three lenses distill each designer's *publicly published* work — courses, articles, talks, and open-source projects. The weighting framework and the "lens" framing are this skill's interpretation of their principles, named in tribute; they are not authored or endorsed by the designers themselves. + +Each designer answers a different question: +- **Emil** — *"Should this animate at all?"* +- **Jakub** — *"Is this subtle and polished enough for production?"* +- **Jhey** — *"What could this become?"* + +**Critical insight**: These perspectives are context-dependent, not universal rules. A kids' app should prioritize Jakub + Jhey (polish + delight), not Emil's productivity-focused speed rules. Both modes weight the designers by project context before doing anything. + +--- + +## Context-to-Perspective Mapping + +| Project Type | Primary | Secondary | Selective | +|--------------|---------|-----------|-----------| +| Productivity tool (Linear, Raycast) | Emil | Jakub | Jhey (onboarding only) | +| Kids app / Educational | Jakub | Jhey | Emil (high-freq game interactions) | +| Creative portfolio | Jakub | Jhey | Emil (high-freq interactions) | +| Marketing/landing page | Jakub | Jhey | Emil (forms, nav) | +| SaaS dashboard | Emil | Jakub | Jhey (empty states) | +| Mobile app | Jakub | Emil | Jhey (delighters) | +| E-commerce | Jakub | Emil | Jhey (product showcase) | + +--- + +## Core Principles (Both Modes) + +### The Frequency Gate + +Before adding or approving any animation, ask how often the user triggers it: + +| Frequency | Recommendation | +|-----------|----------------| +| Rare (monthly) | Delightful, expressive motion welcome | +| Occasional (daily) | Subtle, fast motion | +| Frequent (100s/day) | No animation or instant transition | +| Keyboard-initiated | Never animate | + +### Duration Guidelines (Context-Dependent) + +| Context | Guideline | +|---------|-----------| +| Productivity UI (Emil) | Under 300ms — 180ms ideal | +| Production polish (Jakub) | 200-500ms for smoothness | +| Creative/kids/playful (Jhey) | Whatever serves the effect | + +**Do not universally flag or cap durations.** Check the context weighting first. + +### The Golden Rule + +> "The best animation is that which goes unnoticed." + +If users comment "nice animation!" on every interaction, it's probably too prominent for production. (Exception: kids apps and playful contexts where delight IS the goal.) + +### Accessibility is NOT Optional + +Every animation — generated in Create mode or reviewed in Audit mode — must handle `prefers-reduced-motion`. No exceptions. See `references/accessibility.md`. + +--- + +## Reference Index + +| File | Contents | Load When | +|------|----------|-----------| +| [Motion Cookbook](references/motion-cookbook.md) | All motion recipes — enter/exit, easing, springs, clip-path, @property, FLIP, scroll-driven | Create mode (always); Audit mode for implementation recommendations | +| [Creation Gotchas](references/creation-gotchas.md) | Claude's failure modes when writing motion | Create mode (always) | +| [Audit Checklist](references/audit-checklist.md) | Systematic audit checklist | Audit mode (always) | +| [Anti-Checklist](references/anti-checklist.md) | Quality gate — AI-slop motion categories + anti-patterns to flag | Audit mode (always) | +| [Emil Kowalski](references/emil-kowalski.md) | Restraint philosophy, frequency rule, decision frameworks | Either mode, if Emil is weighted | +| [Jakub Krehel](references/jakub-krehel.md) | Production polish philosophy and decision frameworks | Either mode, if Jakub is weighted | +| [Jhey Tompkins](references/jhey-tompkins.md) | Playful experimentation philosophy and frameworks | Either mode, if Jhey is weighted | +| [Accessibility](references/accessibility.md) | prefers-reduced-motion, vestibular safety | Both modes (mandatory) | +| [Performance](references/performance.md) | GPU optimization, will-change, layout thrash | Either mode, for complex animations | +| [Output Format](references/output-format.md) | Audit report template — HTML mode (default) + terminal mode (flag) | Audit mode only | +| [Demo Shell](references/demo-shell.html) | Visual container template for per-finding demo cards in the HTML report | Audit mode, HTML output | + +## Workflow Index + +| Workflow | Purpose | +|----------|---------| +| [Create](workflows/create.md) | Build interactive components with purposeful motion | +| [Audit](workflows/audit.md) | Review existing motion design, produce a per-designer report | diff --git a/skills-external/design-motion-principles/references/accessibility.md b/skills-external/design-motion-principles/references/accessibility.md new file mode 100644 index 0000000..d70bf27 --- /dev/null +++ b/skills-external/design-motion-principles/references/accessibility.md @@ -0,0 +1,52 @@ +# Accessibility + +**This is not optional.** Motion can cause discomfort, nausea, or distraction for many users. + +--- + +## Respect User Preferences + +```css +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + scroll-behavior: auto !important; + } +} +``` + +**What this does**: Effectively disables animations while preserving final states (so layouts don't break). + +--- + +## Functional vs. Decorative Motion + +| Type | Purpose | Reduced Motion Behavior | +|------|---------|------------------------| +| **Functional** | Indicates state changes, spatial relationships, orientation | May need alternative (instant state change, no transition) | +| **Decorative** | Pure delight, visual interest | Can be fully removed | + +**The test**: Does removing this animation break the user's ability to understand what happened? If yes, it's functional. + +--- + +## Motion Sensitivity Considerations + +- Avoid large-scale motion (full-screen transitions, parallax) +- Avoid continuous or looping animations that can't be paused +- Provide pause controls for any ambient animation +- Be especially careful with vestibular triggers: zooming, spinning, parallax + +--- + +## Implementation Checklist + +- [ ] Tested with `prefers-reduced-motion: reduce` enabled +- [ ] No vestibular triggers (excessive zoom, spin, parallax) +- [ ] Looping animations can be paused +- [ ] Functional animations have non-motion alternatives +- [ ] Users can complete all tasks with animations disabled diff --git a/skills-external/design-motion-principles/references/anti-checklist.md b/skills-external/design-motion-principles/references/anti-checklist.md new file mode 100644 index 0000000..3612dbe --- /dev/null +++ b/skills-external/design-motion-principles/references/anti-checklist.md @@ -0,0 +1,274 @@ +# Anti-Checklist + +This file is the audit's quality gate. The categories below describe motion patterns to **flag** in audited code — AI-slop tells at the top (where most 2026 motion problems live), followed by perspective-specific anti-patterns from Emil, Jakub, and Jhey, then general motion mistakes and code-shaped red flags. When audited code matches a pattern here, the audit surfaces a finding and the agent generates a per-finding motion suggestion by reading the relevant philosophy reference (`emil-kowalski.md`, `jakub-krehel.md`, `jhey-tompkins.md`). + +The file frames patterns as "things to flag," not "mistakes to avoid" — language that makes the audit's adversarial posture explicit. + +--- + +## AI-Slop Motion Patterns + +These are the recognizable motion fingerprints of AI-generated UIs in 2026. They're not always wrong in isolation — what makes them slop is *frequency* and *uniformity*. Finding one instance is normal polish; finding the same pattern slapped across the codebase is the tell. Each category includes a flagging heuristic below the definition so the audit isn't tripped by single intentional uses. + +--- + +### Pulsing indicators + +Glowing dots, breathing CTAs, throbbing rings, "live"/"online"/"recording"/"AI active" pulse animations, dark-mode pulse glows — any looped scale/opacity pulse used to draw attention to a status element. + +**Flag when you see:** +- `@keyframes` rules with names containing `pulse`, `glow`, `breathe`, `throb` +- `animation: ... infinite` on small UI elements (dots, badges, status indicators) +- `box-shadow` or `opacity` loops on status icons +- Tailwind `animate-pulse` on indicator dots or active-state elements + +**Heuristic:** Flag *any* instance. Pulsing indicators are almost always slop — the only exception is a single brand element with explicit design rationale stated in code comments or design docs. + +**Fix lens:** Emil — purposeful restraint. See `references/emil-kowalski.md`. + +--- + +### Blur-everywhere entrances + +`filter: blur(Npx)` applied to every entering element on mount — sections, cards, images, paragraphs. Jakub's enter recipe (`opacity + translateY + blur`) is excellent in moderation; AI-slop versions apply it uniformly across the page. + +**Flag when you see:** +- `initial={{ filter: 'blur(Npx)' }}` or `from { filter: blur(Npx); }` on multiple distinct components in the same view +- Identical blur values (e.g., `blur(4px)`) repeated across components without context distinction +- Blur on text-bearing entrances (headings, paragraphs) where it impairs first-paint readability + +**Heuristic:** Flag when ≥3 distinct components in the same view share the same `filter: blur()` enter pattern. Single uses with intent (a hero element, a modal) are fine. + +**Fix lens:** Jakub — production polish, but selective. See `references/jakub-krehel.md`. + +--- + +### Hover-scale-on-everything + +`transform: scale(1.0X)` on `:hover` applied to every card, button, and image without intent. The micro-bounce-on-hover feels polished in moderation; AI-slop versions slap it on indiscriminately. + +**Flag when you see:** +- `transition` rules with `transform: scale(1.0X)` on `:hover` across multiple card/button/image components +- Identical scale values (e.g., `scale(1.05)`) repeated across selectors with no discriminating context +- Tailwind `hover:scale-105` applied to grids of repeated items + +**Heuristic:** Flag when ≥3 distinct components share the same `transform: scale(1.0X)` on `:hover` with no other discriminating selector context. Single intentional uses (e.g., a primary CTA) are fine. + +**Fix lens:** Emil for utility-shaped elements (none); Jakub for product-shaped elements (selective). See `references/emil-kowalski.md` and `references/jakub-krehel.md`. + +--- + +### Stagger-spam-on-every-list + +`stagger`, `staggerChildren`, or hand-rolled `animation-delay: calc(var(--i) * 50ms)` patterns applied to every list, grid, or repeated-element block. Jhey-style stagger on a deliberate moment is delightful; AI-slop spreads it across every list as default polish. + +**Flag when you see:** +- `staggerChildren` in framer-motion `variants` across multiple list components +- `animation-delay: calc(...)` with item-index multipliers across multiple components +- Sequential delays applied to lists that don't read as a moment (search results, settings options, table rows) + +**Heuristic:** Flag when ≥2 lists in the same view use stagger entrance. One intentional moment is fine; two or more is the tell. + +**Fix lens:** Emil for utility lists (no stagger); Jhey for delight moments (selective). See `references/emil-kowalski.md` and `references/jhey-tompkins.md`. + +--- + +### Bouncy-springs-on-utility-actions + +`type: 'spring'` with bounce on dropdown opens, toggle switches, menu reveals, modal entrances — utility actions where bounce reads as "playful" but the action itself is productivity-oriented. + +**Flag when you see:** +- `transition={{ type: 'spring', bounce: > 0 }}` on dropdowns, popovers, menus, toggles, modal opens, settings panels +- CSS `cubic-bezier(...)` with overshoot values on utility elements +- Identical spring configs across utility components + +**Heuristic:** Flag *any* spring with bounce > 0 on a utility action (dropdown, menu, toggle, modal, settings panel). Bounce belongs on playful elements — celebration moments, kids apps, intentional delight — not productivity UI. + +**Fix lens:** Emil — speed and purpose. See `references/emil-kowalski.md`. + +--- + +### Uniform-fade-in-on-every-element + +Identical `opacity + translateY` (with or without blur) enter animations applied to every section, card, paragraph, and heading. The "polished entrance" treatment from Jakub used uniformly across the page, regardless of element type or context. + +**Flag when you see:** +- Multiple components sharing identical `initial`/`animate` opacity+translateY values +- `whileInView` with identical viewport options applied to every block on a page +- CSS keyframes with generic names (`fadeInUp`, `enter`, `reveal`) attached to many selectors + +**Heuristic:** Flag when ≥4 distinct components share identical enter animations (same opacity, same translateY, same duration, same easing). Three is acceptable polish baseline; four is uniformity slop. + +**Fix lens:** Jakub — selective polish with hierarchy. See `references/jakub-krehel.md`. + +--- + +### Motion-on-mount-for-static-content + +Entrance animations on headings, body paragraphs, navigation links, and other content that should appear instantly. The "fade in everything" pattern that delays reading and makes the page feel sluggish. + +**Flag when you see:** +- `initial`/`animate` on `

`, `

`, `

`, `